fix:Fix related issues with kexec (pr # 1303) code (#1339)

- Fix some legacy issues of PR 1303
- Supplement the error handling of PR 1303

Signed-off-by: JensenWei007 <jensenwei007@gmail.com>
This commit is contained in:
JingXuan_Wei 2025-11-10 13:31:10 +08:00 committed by GitHub
parent dee2e02034
commit be4ee4f0ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 259 additions and 338 deletions

7
.gitignore vendored
View File

@ -26,4 +26,9 @@ compile_commands.json
/.direnv/
/flake.nix
flake.lock
/default.nix
/default.nix
# initram
*.cpio
*.cpio.xz
*.cpio*

1
env.mk
View File

@ -10,5 +10,6 @@ ifeq ($(EMULATOR), )
export EMULATOR=__NO_EMULATION__
endif
export INITRAM_PATH?=$(ROOT_PATH)/x86.cpio.xz
export DADK?=$(shell which dadk)

4
kernel/.gitignore vendored
View File

@ -10,7 +10,3 @@ src/include/bindings/bindings.h
# Build counter
.build_count
# initram
initram/*.cpio
initram/*.cpio.xz

View File

@ -2,10 +2,13 @@ use std::env;
use std::path::Path;
fn main() {
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let path = format!("{}/initram/x86.cpio.xz", manifest_dir);
if Path::new(&path).exists() {
println!("cargo:rustc-cfg=has_initram_x86");
if let Ok(initram_path) = env::var("INITRAM_PATH") {
if Path::new(&initram_path).exists() {
println!("cargo:rustc-cfg=has_initram");
// 将路径传递给编译时常量
println!("cargo:rustc-env=INITRAM_PATH={}", initram_path);
println!("cargo:rerun-if-env-changed=INITRAM_PATH");
}
}
kernel_build::run();

View File

@ -1,3 +0,0 @@
#!/bin/bash
echo "此脚本暂时废置, 请使用 DragonBoot 仓库进行构建"

View File

@ -42,7 +42,7 @@ kernel_subdirs := debug
TOOLCHAIN := +nightly-2025-08-10
kernel_rust:
DRAGONOS_ACTUAL_BUILD=1 RUSTFLAGS="$(RUSTFLAGS)" cargo $(TOOLCHAIN) $(CARGO_ZBUILD) build --release --target $(TARGET_JSON)
DRAGONOS_ACTUAL_BUILD=1 RUSTFLAGS="$(RUSTFLAGS)" INITRAM_PATH="$(INITRAM_PATH)" cargo $(TOOLCHAIN) $(CARGO_ZBUILD) build --release --target $(TARGET_JSON)
all: kernel

View File

@ -13,8 +13,6 @@ impl ArchBootParams {
pub fn set_scratch(&mut self, _scratch: u32) {}
pub fn add_e820_entry(&mut self, _addr: u64, _size: u64, _mtype: u32) {}
pub fn init_setupheader(&mut self) {}
pub fn convert_to_buf(&self) -> &[u8] {

View File

@ -24,3 +24,28 @@ impl SignalArch for LoongArch64SignalArch {
todo!("la64:sys_rt_sigreturn")
}
}
/// @brief 信号处理备用栈的信息
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub struct LoongArch64SigStack {
pub sp: usize,
pub flags: u32,
pub size: u32,
}
impl LoongArch64SigStack {
pub fn new() -> Self {
Self {
sp: 0,
flags: 0,
size: 0,
}
}
}
impl Default for LoongArch64SigStack {
fn default() -> Self {
Self::new()
}
}

View File

@ -1,11 +1,16 @@
use crate::init::kexec::Kimage;
use crate::libs::spinlock::SpinLock;
use alloc::rc::Rc;
use system_error::SystemError;
pub fn machine_kexec_prepare(kimage: Rc<SpinLock<Kimage>>) -> bool {
false
pub fn machine_kexec_prepare(kimage: Rc<SpinLock<Kimage>>) -> Result<(), SystemError> {
Ok(())
}
pub fn init_pgtable(kimage: Rc<SpinLock<Kimage>>) {}
pub fn init_pgtable(kimage: Rc<SpinLock<Kimage>>) -> Result<(), SystemError> {
Ok(())
}
pub fn machine_kexec(kimage: Rc<SpinLock<Kimage>>) {}
pub fn machine_kexec(kimage: Rc<SpinLock<Kimage>>) -> Result<(), SystemError> {
Ok(())
}

View File

@ -21,6 +21,7 @@ pub mod time;
pub use self::elf::LoongArch64ElfArch as CurrentElfArch;
pub use self::interrupt::LoongArch64InterruptArch as CurrentIrqArch;
pub use self::ipc::signal::LoongArch64SigStack as SigStackArch;
pub use self::ipc::signal::LoongArch64SignalArch as CurrentSignalArch;
pub use self::mm::LoongArch64MMArch as MMArch;
pub use self::pci::LoongArch64PciArch as PciArch;

View File

@ -39,8 +39,8 @@ impl BootCallbacks for DragonStubCallBack {
Ok(())
}
fn early_init_memmap_sysfs(&self) -> Result<(), SystemError> {
log::error!("riscv64, early_init_memmap_sysfs is not impled");
fn init_memmap_sysfs(&self) -> Result<(), SystemError> {
log::error!("riscv64, init_memmap_sysfs is not impled");
Ok(())
}

View File

@ -50,8 +50,6 @@ impl ArchBootParams {
pub fn set_scratch(&mut self, _scratch: u32) {}
pub fn add_e820_entry(&mut self, _addr: u64, _size: u64, _mtype: u32) {}
pub fn init_setupheader(&mut self) {}
pub fn convert_to_buf(&self) -> &[u8] {

View File

@ -40,3 +40,28 @@ bitflags! {
}
}
/// @brief 信号处理备用栈的信息
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub struct RiscV64SigStack {
pub sp: usize,
pub flags: u32,
pub size: u32,
}
impl RiscV64SigStack {
pub fn new() -> Self {
Self {
sp: 0,
flags: 0,
size: 0,
}
}
}
impl Default for RiscV64SigStack {
fn default() -> Self {
Self::new()
}
}

View File

@ -1,11 +1,16 @@
use crate::init::kexec::Kimage;
use crate::libs::spinlock::SpinLock;
use alloc::rc::Rc;
use system_error::SystemError;
pub fn machine_kexec_prepare(kimage: Rc<SpinLock<Kimage>>) -> bool {
false
pub fn machine_kexec_prepare(kimage: Rc<SpinLock<Kimage>>) -> Result<(), SystemError> {
Ok(())
}
pub fn init_pgtable(kimage: Rc<SpinLock<Kimage>>) {}
pub fn init_pgtable(kimage: Rc<SpinLock<Kimage>>) -> Result<(), SystemError> {
Ok(())
}
pub fn machine_kexec(kimage: Rc<SpinLock<Kimage>>) {}
pub fn machine_kexec(kimage: Rc<SpinLock<Kimage>>) -> Result<(), SystemError> {
Ok(())
}

View File

@ -30,6 +30,7 @@ pub use self::time::RiscV64TimeArch as CurrentTimeArch;
pub use self::elf::RiscV64ElfArch as CurrentElfArch;
pub use self::ipc::signal::RiscV64SigStack as SigStackArch;
pub use self::ipc::signal::RiscV64SignalArch as CurrentSignalArch;
pub use crate::arch::smp::RiscV64SMPArch as CurrentSMPArch;

View File

@ -217,7 +217,7 @@ impl BootCallbacks for Mb2Callback {
Ok(())
}
fn early_init_memmap_sysfs(&self) -> Result<(), SystemError> {
fn init_memmap_sysfs(&self) -> Result<(), SystemError> {
// 没测试过, 可能有问题
crate::mm::sysfs::early_memmap_init();

View File

@ -56,7 +56,6 @@ impl BootCallbacks for PvhBootCallback {
}
fn init_initramfs(&self) -> Result<(), SystemError> {
log::error!("x86 pvh, init_initramfs is not impled");
Ok(())
}
@ -125,7 +124,7 @@ impl BootCallbacks for PvhBootCallback {
Ok(())
}
fn early_init_memmap_sysfs(&self) -> Result<(), SystemError> {
fn init_memmap_sysfs(&self) -> Result<(), SystemError> {
crate::mm::sysfs::early_memmap_init();
let start_info = START_INFO.get();

View File

@ -131,16 +131,34 @@ impl SigContext {
return true;
}
}
/// @brief 信号处理备用栈的信息
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub struct X86SigStack {
pub sp: *mut c_void,
pub sp: usize,
pub flags: u32,
pub size: u32,
pub fpstate: FpState,
}
impl X86SigStack {
pub fn new() -> Self {
Self {
sp: 0,
flags: 0,
size: 0,
fpstate: FpState::new(),
}
}
}
impl Default for X86SigStack {
fn default() -> Self {
Self::new()
}
}
unsafe fn do_signal(frame: &mut TrapFrame, got_signal: &mut bool) {
let pcb = ProcessManager::current_pcb();

View File

@ -8,11 +8,12 @@ use crate::mm::MemoryManagementArch;
use crate::mm::{page::EntryFlags, PhysAddr};
use alloc::rc::Rc;
use core::mem::transmute;
use system_error::SystemError;
type RelocateKernelFn =
unsafe extern "C" fn(indirection_page: usize, start_address: usize, stack_page_address: usize);
pub fn machine_kexec_prepare(kimage: Rc<SpinLock<Kimage>>) -> bool {
pub fn machine_kexec_prepare(kimage: Rc<SpinLock<Kimage>>) -> Result<(), SystemError> {
unsafe {
unsafe extern "C" {
unsafe fn __relocate_kernel_start();
@ -69,10 +70,10 @@ pub fn machine_kexec_prepare(kimage: Rc<SpinLock<Kimage>>) -> bool {
mess_buf.resize(2048, 0);
slice.copy_from_slice(&mess_buf);
}
true
Ok(())
}
pub fn init_pgtable(kimage: Rc<SpinLock<Kimage>>) {
pub fn init_pgtable(kimage: Rc<SpinLock<Kimage>>) -> Result<(), SystemError> {
let pgd = ident_pt_alloc();
kimage.lock().pgd = pgd;
@ -92,7 +93,7 @@ pub fn init_pgtable(kimage: Rc<SpinLock<Kimage>>) {
let size = kimage.lock().segment[i].memsz;
// TODO:处理可能不是页面整数的情况, 但是目前, 传入的参数都是在用户层页面对其和取整了
let pages_nums = size / MMArch::PAGE_SIZE;
ident_map_pages(pgd, addr, addr, pages_nums);
ident_map_pages(pgd, addr, addr, pages_nums)?;
}
// pages
@ -106,7 +107,7 @@ pub fn init_pgtable(kimage: Rc<SpinLock<Kimage>>) {
for i in 0..len {
let page = kimage.lock().pages[i].clone();
let addr = page.phys_address().data();
ident_map_page(pgd, addr, addr);
ident_map_page(pgd, addr, addr)?;
}
// efi
@ -126,11 +127,11 @@ pub fn init_pgtable(kimage: Rc<SpinLock<Kimage>>) {
pgd,
unsafe { MMArch::phys_2_virt(control_page_pa).unwrap().data() },
control_page_pa.data(),
);
)?;
// cmdline
let cmdline_ptr = boot_params().read().arch.hdr.cmd_line_ptr as usize;
ident_map_page(pgd, cmdline_ptr, cmdline_ptr);
ident_map_page(pgd, cmdline_ptr, cmdline_ptr)
}
pub fn machine_kexec(kimage: Rc<SpinLock<Kimage>>) {

View File

@ -37,6 +37,8 @@ pub use crate::arch::asm::pio::X86_64PortIOArch as CurrentPortIOArch;
pub use crate::arch::ipc::signal::X86_64SignalArch as CurrentSignalArch;
pub use crate::arch::time::X86_64TimeArch as CurrentTimeArch;
pub use crate::arch::ipc::signal::X86SigStack as SigStackArch;
pub use crate::arch::elf::X86_64ElfArch as CurrentElfArch;
pub use crate::arch::smp::X86_64SMPArch as CurrentSMPArch;

View File

@ -59,8 +59,6 @@ pub struct RamFSInode {
self_ref: Weak<LockedRamFSInode>,
/// 子Inode的B树
children: BTreeMap<DName, Arc<LockedRamFSInode>>,
/// 子Syms的B树, 记录符号到符号的链接
syms: BTreeMap<DName, DName>,
/// 当前inode的数据部分
data: Vec<u8>,
/// 当前inode的元数据
@ -79,7 +77,6 @@ impl RamFSInode {
parent: Weak::default(),
self_ref: Weak::default(),
children: BTreeMap::new(),
syms: BTreeMap::new(),
data: Vec::new(),
metadata: Metadata {
dev_id: 0,
@ -331,7 +328,6 @@ impl IndexNode for LockedRamFSInode {
parent: inode.self_ref.clone(),
self_ref: Weak::default(),
children: BTreeMap::new(),
syms: BTreeMap::new(),
data: Vec::new(),
metadata: Metadata {
dev_id: 0,
@ -420,63 +416,6 @@ impl IndexNode for LockedRamFSInode {
return Ok(());
}
fn symlink(
&self,
name1: &str,
name2: &str,
other: &Arc<dyn IndexNode>,
) -> Result<(), SystemError> {
// TODO: 判断是否指向的other为一个符号链接
// 也就是需要判断 test1 -> echo -> busybox 的情况下, other的name是busybox,但是name2是echo
let other: &LockedRamFSInode = other
.downcast_ref::<LockedRamFSInode>()
.ok_or(SystemError::EPERM)?;
let name = DName::from(name1);
let other_name = DName::from(name2);
let mut inode: SpinLockGuard<RamFSInode> = self.0.lock();
let other_locked: SpinLockGuard<RamFSInode> = other.0.lock();
// 如果当前inode不是文件夹那么报错
if inode.metadata.file_type != FileType::Dir {
return Err(SystemError::ENOTDIR);
}
// 如果另一个inode是文件夹那么也报错
if other_locked.metadata.file_type == FileType::Dir {
return Err(SystemError::EISDIR);
}
// 如果当前文件夹下已经有同名文件,也报错。
if inode.children.contains_key(&name) {
return Err(SystemError::EEXIST);
}
// 将子name插入父syms的B树中
inode.syms.insert(name.clone(), other_name.clone());
inode
.children
.insert(name, other_locked.self_ref.upgrade().unwrap());
return Ok(());
}
fn symunlink(&self, _name: &str) -> Result<(), SystemError> {
// 若文件系统没有实现此方法,则返回“不支持”
return Err(SystemError::ENOSYS);
}
fn get_nextsym(&self, name: &str) -> Result<String, SystemError> {
let name = DName::from(name);
let inode: SpinLockGuard<RamFSInode> = self.0.lock();
if let Some(r) = inode.syms.get(&name) {
return Ok(r.0.to_string());
}
return Ok(name.to_string());
}
fn rmdir(&self, name: &str) -> Result<(), SystemError> {
let name = DName::from(name);
let mut inode: SpinLockGuard<RamFSInode> = self.0.lock();
@ -661,7 +600,6 @@ impl IndexNode for LockedRamFSInode {
parent: inode.self_ref.clone(),
self_ref: Weak::default(),
children: BTreeMap::new(),
syms: BTreeMap::new(),
data: Vec::new(),
metadata: Metadata {
dev_id: 0,

View File

@ -8,7 +8,6 @@ pub mod syscall;
pub mod utils;
pub mod vcore;
use self::utils::rsplit_path;
use ::core::{any::Any, fmt::Debug, sync::atomic::AtomicUsize};
use alloc::{string::String, sync::Arc, vec::Vec};
use derive_builder::Builder;
@ -386,46 +385,6 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync {
return Err(SystemError::ENOSYS);
}
/// @brief 在当前目录下创建一个名为Name的符号链接(软链接)指向另一个IndexNode支持链接向一个符号链接
///
/// @param name1 符号链接的名称, 将会在此目录下创建名为name的inode
/// @param name1 要被指向的 name 名称, 会根据此name与other的name区分是否指向一个符号链接
/// @param other 要被指向的IndexNode的Arc指针
///
/// @return 成功Ok(新的inode的Arc指针)
/// 失败Err(错误码)
fn symlink(
&self,
_name1: &str,
_name2: &str,
_other: &Arc<dyn IndexNode>,
) -> Result<(), SystemError> {
// 若文件系统没有实现此方法,则返回“不支持”
return Err(SystemError::ENOSYS);
}
/// @brief 在当前目录下删除一个名为Name的符号链接(软链接)
///
/// @param name 符号链接的名称
///
/// @return 成功Ok()
/// 失败Err(错误码)
fn symunlink(&self, _name: &str) -> Result<(), SystemError> {
// 若文件系统没有实现此方法,则返回“不支持”
return Err(SystemError::ENOSYS);
}
/// @brief 在当前目录下获取名为Name的符号链接(软链接)的执行的文件名称
///
/// @param name 符号链接的名称
///
/// @return 成功Ok()
/// 失败Err(错误码)
fn get_nextsym(&self, _name: &str) -> Result<String, SystemError> {
// 若文件系统没有实现此方法,则返回“不支持”
return Err(SystemError::ENOSYS);
}
/// @brief 删除文件夹
///
/// @param name 文件夹名称
@ -1334,20 +1293,3 @@ impl<'a> FilldirContext<'a> {
return Ok(());
}
}
/// 查找链接文件的最底层链接, 目的是解决循环嵌套链接
/// 如 test -> echo, echo -> busybox, 需要解析 test 的链接情况
/// 返回 name 指向的文件的名称(可能为绝对路径, 具体值为symlink传入的参数值
/// 如果返回其本身(最底层文件名, 经过路径处理后的), 说明此文件不是链接文件
#[allow(dead_code)]
pub fn get_link_true_file(name: String) -> Result<String, SystemError> {
let (filename, parent_path) = rsplit_path(&name);
let parent_inode = match parent_path {
None => ProcessManager::current_mntns().root_inode(),
Some(path) => ProcessManager::current_mntns()
.root_inode()
.lookup(path)
.unwrap(),
};
parent_inode.get_nextsym(filename)
}

View File

@ -709,24 +709,6 @@ impl IndexNode for MountFSInode {
return self.inner_inode.unlink(name);
}
fn symlink(
&self,
name1: &str,
name2: &str,
other: &Arc<dyn IndexNode>,
) -> Result<(), SystemError> {
return self.inner_inode.symlink(name1, name2, other);
}
fn symunlink(&self, _name: &str) -> Result<(), SystemError> {
// 若文件系统没有实现此方法,则返回“不支持”
return Err(SystemError::ENOSYS);
}
fn get_nextsym(&self, name: &str) -> Result<String, SystemError> {
return self.inner_inode.get_nextsym(name);
}
#[inline]
fn rmdir(&self, name: &str) -> Result<(), SystemError> {
let inode_id = self.inner_inode.find(name)?.metadata()?.inode_id;

View File

@ -173,7 +173,7 @@ pub trait BootCallbacks: Send + Sync {
/// 初始化内存块
fn early_init_memory_blocks(&self) -> Result<(), SystemError>;
/// 初始化内存 memmap 信息到 sysfs
fn early_init_memmap_sysfs(&self) -> Result<(), SystemError>;
fn init_memmap_sysfs(&self) -> Result<(), SystemError>;
/// 初始化内存 memmap 信息到 boot_params
fn init_memmap_bp(&self) -> Result<(), SystemError>;
}

View File

@ -12,7 +12,7 @@ use crate::filesystem::vfs::vcore::change_root_fs;
use crate::{
arch::{interrupt::TrapFrame, process::arch_switch_to_user},
driver::net::e1000e::e1000e::e1000e_init,
filesystem::vfs::vcore::mount_root_fs,
filesystem::vfs::{vcore::mount_root_fs, VFS_MAX_FOLLOW_SYMLINK_TIMES},
net::net_core::net_init,
process::{
exec::ProcInitInfo, execve::do_execve, kthread::KernelThreadMechanism, stdio::stdio_init,
@ -75,7 +75,7 @@ fn kernel_init() -> Result<(), SystemError> {
.inspect_err(|e| log::error!("ahci_init failed: {:?}", e))
.ok();
if super::enable_initramfs() {
if super::initramfs_enabled() {
// 使用 initramfs, 迁移文件系统
#[cfg(feature = "initram")]
change_root_fs().expect("Failed to mount root fs");
@ -127,7 +127,7 @@ fn switch_to_user() -> ! {
let mut trap_frame = TrapFrame::new();
if super::enable_initramfs() {
if super::initramfs_enabled() {
// 使用 initramfs, 启动 /init
log::info!("Initramfs, Boot with specified init process: /init");
@ -212,7 +212,7 @@ fn run_init_process(
let path = proc_init_info.proc_name.to_str().unwrap();
let pwd = ProcessManager::current_pcb().pwd_inode();
let inode = pwd.lookup(path)?;
let inode = pwd.lookup_follow_symlink(path, VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
do_execve(
inode,
proc_init_info.args.clone(),

View File

@ -5,6 +5,7 @@ use alloc::vec::Vec;
use crate::filesystem::ramfs::RamFS;
use crate::filesystem::vfs::mount::MountFlags;
use crate::filesystem::vfs::FilePrivateData;
use crate::filesystem::vfs::FileSystem;
use crate::filesystem::vfs::MountFS;
use crate::init::boot::boot_callbacks;
@ -31,49 +32,14 @@ pub fn INIT_ROOT_INODE() -> Arc<dyn IndexNode> {
}
}
#[cfg(target_arch = "x86_64")]
#[allow(non_upper_case_globals, unexpected_cfgs)]
#[used]
pub static INITRAM_DATA: &[u8] = {
#[cfg(has_initram_x86)]
#[cfg(has_initram)]
{
include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/initram/x86.cpio.xz"))
include_bytes!(env!("INITRAM_PATH"))
}
#[cfg(not(has_initram_x86))]
{
&[]
}
};
#[cfg(target_arch = "riscv64")]
#[allow(non_upper_case_globals, unexpected_cfgs)]
#[used]
pub static INITRAM_DATA: &[u8] = {
#[cfg(has_initram_riscv64)]
{
include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/initram/riscv64.cpio.xz"
))
}
#[cfg(not(has_initram_riscv64))]
{
&[]
}
};
#[cfg(target_arch = "loongarch64")]
#[allow(non_upper_case_globals, unexpected_cfgs)]
#[used]
pub static INITRAM_DATA: &[u8] = {
#[cfg(has_initram_loongarch64)]
{
include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/initram/loongarch64.cpio.xz"
))
}
#[cfg(not(has_initram_loongarch64))]
#[cfg(not(has_initram))]
{
&[]
}
@ -154,7 +120,7 @@ pub fn initramfs_init() -> Result<(), SystemError> {
return Err(SystemError::ENOENT);
}
let cpio_data = xz_decompress(get_initram()).unwrap();
let cpio_data = xz_decompress(get_initram())?;
let collected_entries_vec = cpio_reader::iter_files(&cpio_data)
.map(|entry| CpioEntryInfo {
@ -180,7 +146,10 @@ pub fn initramfs_init() -> Result<(), SystemError> {
for (index, entry) in collected_entries_vec.iter().enumerate() {
// x86 的有 4 种文件Dir, File, CharDevice, SymLink
let name = entry.name.clone();
let mode = ModeType::from_bits(entry.mode.bits()).unwrap();
let mode = ModeType::from_bits(entry.mode.bits()).ok_or_else(|| {
log::error!("initramfs: failed to get mode!");
SystemError::EINVAL
})?;
let file_type = FileType::from(mode);
log::info!(
"Find cpio entry, Name:{}, ModeType:{:?}, FileType:{:?}",
@ -191,24 +160,22 @@ pub fn initramfs_init() -> Result<(), SystemError> {
let (filename, parent_path) = rsplit_path(&name);
let parent_inode = match parent_path {
None => INIT_ROOT_INODE(),
Some(path) => INIT_ROOT_INODE().lookup(path).unwrap(),
Some(path) => INIT_ROOT_INODE().lookup(path)?,
};
match file_type {
FileType::Dir => {
// 直接插入, 无需处理数据
parent_inode.create(filename, file_type, mode).unwrap();
parent_inode.create(filename, file_type, mode)?;
}
FileType::File => {
// 插入, 随后写入文件数据
let inode = parent_inode.create(filename, file_type, mode).unwrap();
inode
.write_at(
0,
entry.file.len(),
&entry.file,
SpinLock::new(crate::filesystem::vfs::FilePrivateData::Unused).lock(),
)
.unwrap();
let inode = parent_inode.create(filename, file_type, mode)?;
inode.write_at(
0,
entry.file.len(),
&entry.file,
SpinLock::new(crate::filesystem::vfs::FilePrivateData::Unused).lock(),
)?;
}
FileType::CharDevice => {
// 不处理, 如果使用 initramfs 那么直接从已经初始化好的根文件系统迁移到此文件系统
@ -223,20 +190,28 @@ pub fn initramfs_init() -> Result<(), SystemError> {
};
}
// 处理链接文件
// TODO: 正常来说必须使用软链接(符号链接), 但是现在内核没有实现软链接
// 这里使用硬链接在一层符号嵌套访问上不会出问题, 但是执行多层符号嵌套会出问题, 这个使用了一个小暂时的方法
// 处理链接文件, 使用符号链接
for i in 0..links.len() {
let entry = &collected_entries_vec[links[i]];
let name = entry.name.clone();
let (filename, parent_path) = rsplit_path(&name);
let parent_inode = match parent_path {
None => INIT_ROOT_INODE(),
Some(path) => INIT_ROOT_INODE().lookup(path).unwrap(),
Some(path) => INIT_ROOT_INODE().lookup(path)?,
};
let other_name = String::from_utf8(entry.file.clone()).unwrap();
let other = parent_inode.lookup(&other_name).unwrap();
parent_inode.symlink(filename, &other_name, &other).unwrap();
let other_name = String::from_utf8(entry.file.clone()).map_err(|err| {
log::error!("initramfs: failed to get utf8_name, err is {}", err);
SystemError::EINVAL
})?;
let new_inode = parent_inode.create_with_data(
filename,
FileType::SymLink,
ModeType::from_bits_truncate(0o777),
0,
)?;
let buf = other_name.as_bytes();
let len = buf.len();
new_inode.write_at(0, len, buf, SpinLock::new(FilePrivateData::Unused).lock())?;
}
// 下面的方式是查看外置 initramfs, 例如使用 qemu 的 -initrd 参数加载的

View File

@ -32,20 +32,18 @@ pub fn do_kexec_load(
return Ok(0);
}
let image = kimage_alloc_init(entry, nr_segments, ksegments, flags).unwrap();
let image = kimage_alloc_init(entry, nr_segments, ksegments, flags)?;
// load segment 的解析: https://zhuanlan.zhihu.com/p/105284305
for i in 0..nr_segments {
kimage_load_normal_segment(image.clone(), i);
kimage_load_normal_segment(image.clone(), i)?;
}
kimage_terminate(image.clone());
KexecArch::init_pgtable(image.clone());
KexecArch::init_pgtable(image.clone())?;
if !KexecArch::machine_kexec_prepare(image.clone()) {
return Err(SystemError::EADV);
}
KexecArch::machine_kexec_prepare(image.clone())?;
unsafe {
KEXEC_IMAGE = Some(image.clone());
@ -91,10 +89,10 @@ pub fn kimage_alloc_init(
image.lock().segment[..ksegments.len()].copy_from_slice(ksegments);
let temp_c = kimage_alloc_pages(image.clone(), 0, false);
let temp_c = kimage_alloc_pages(image.clone(), 0, false)?;
image.lock().control_code_page = temp_c.clone();
let temp_st = kimage_alloc_pages(image.clone(), 0, true);
let temp_st = kimage_alloc_pages(image.clone(), 0, true)?;
image.lock().stack_page = temp_st.clone();
Ok(image)
@ -104,7 +102,7 @@ pub fn kimage_alloc_pages(
kimage: Rc<SpinLock<Kimage>>,
order: usize,
store: bool,
) -> Option<Arc<Page>> {
) -> Result<Option<Arc<Page>>, SystemError> {
let mut _page = None;
let mut extra_pages: Vec<Arc<Page>> = Vec::new();
let mut alloc = page_manager_lock_irqsave();
@ -113,13 +111,11 @@ pub fn kimage_alloc_pages(
// 目前只分配一个页面, 后面改成多个, 使用 order 控制
loop {
let p = alloc
.create_one_page(
PageType::Normal,
PageFlags::PG_RESERVED | PageFlags::PG_PRIVATE,
&mut LockedFrameAllocator,
)
.unwrap();
let p = alloc.create_one_page(
PageType::Normal,
PageFlags::PG_RESERVED | PageFlags::PG_PRIVATE,
&mut LockedFrameAllocator,
)?;
if check_isdst(kimage.clone(), p.clone()) {
extra_pages.push(p);
@ -136,7 +132,7 @@ pub fn kimage_alloc_pages(
alloc.remove_page(&p.phys_address());
}
_page
Ok(_page)
}
pub fn check_isdst(kimage: Rc<SpinLock<Kimage>>, page: Arc<Page>) -> bool {
@ -170,7 +166,10 @@ pub fn kernel_kexec() {
}
}
pub fn kimage_add_entry(kimage: Rc<SpinLock<Kimage>>, entry: KimageEntry) {
pub fn kimage_add_entry(
kimage: Rc<SpinLock<Kimage>>,
entry: KimageEntry,
) -> Result<(), SystemError> {
unsafe {
if *kimage.lock().entry != 0 {
let t = kimage.lock().entry.add(1);
@ -180,7 +179,7 @@ pub fn kimage_add_entry(kimage: Rc<SpinLock<Kimage>>, entry: KimageEntry) {
let k_entry = kimage.lock().entry;
let k_last_entry = kimage.lock().last_entry;
if k_entry == k_last_entry {
let page = kimage_alloc_pages(kimage.clone(), 0, true).unwrap();
let page = kimage_alloc_pages(kimage.clone(), 0, true)?.unwrap();
let ind_page =
MMArch::phys_2_virt(page.phys_address()).unwrap().data() as *mut KimageEntry;
@ -198,19 +197,26 @@ pub fn kimage_add_entry(kimage: Rc<SpinLock<Kimage>>, entry: KimageEntry) {
kimage.lock().entry = t;
*kimage.lock().entry = 0;
}
Ok(())
}
pub fn kimage_set_destination(kimage: Rc<SpinLock<Kimage>>, destination: usize) {
pub fn kimage_set_destination(
kimage: Rc<SpinLock<Kimage>>,
destination: usize,
) -> Result<(), SystemError> {
let d = destination & MMArch::PAGE_MASK;
kimage_add_entry(kimage.clone(), d | IND_DESTINATION);
kimage_add_entry(kimage.clone(), d | IND_DESTINATION)
}
pub fn kimage_add_page(kimage: Rc<SpinLock<Kimage>>, page: usize) {
pub fn kimage_add_page(kimage: Rc<SpinLock<Kimage>>, page: usize) -> Result<(), SystemError> {
let p = page & MMArch::PAGE_MASK;
kimage_add_entry(kimage.clone(), p | IND_SOURCE);
kimage_add_entry(kimage.clone(), p | IND_SOURCE)
}
pub fn kimage_load_normal_segment(kimage: Rc<SpinLock<Kimage>>, index: usize) {
pub fn kimage_load_normal_segment(
kimage: Rc<SpinLock<Kimage>>,
index: usize,
) -> Result<(), SystemError> {
let segment = kimage.lock().segment[index];
let mut maddr = segment.mem;
@ -218,11 +224,11 @@ pub fn kimage_load_normal_segment(kimage: Rc<SpinLock<Kimage>>, index: usize) {
let mut buf = unsafe { segment.buffer.buf } as *mut u8;
let mut ubytes = segment.bufsz;
kimage_set_destination(kimage.clone(), maddr);
kimage_set_destination(kimage.clone(), maddr)?;
loop {
let page = kimage_alloc_pages(kimage.clone(), 0, true).unwrap();
kimage_add_page(kimage.clone(), page.phys_address().data());
let page = (kimage_alloc_pages(kimage.clone(), 0, true)?).unwrap();
kimage_add_page(kimage.clone(), page.phys_address().data())?;
let mut virt_data = unsafe { MMArch::phys_2_virt(page.phys_address()).unwrap().data() };
virt_data += maddr & !(MMArch::PAGE_MASK);
@ -233,8 +239,8 @@ pub fn kimage_load_normal_segment(kimage: Rc<SpinLock<Kimage>>, index: usize) {
let uchunk = min(ubytes, mchunk);
if uchunk != 0 {
let usegments_buf = UserBufferReader::new::<u8>(buf, uchunk, true).unwrap();
let ksegment: &[u8] = usegments_buf.read_from_user(0).unwrap();
let usegments_buf = UserBufferReader::new::<u8>(buf, uchunk, true)?;
let ksegment: &[u8] = usegments_buf.read_from_user(0)?;
unsafe { core::ptr::copy(ksegment.as_ptr(), virt_data as *mut u8, uchunk) };
ubytes -= uchunk;
@ -245,7 +251,7 @@ pub fn kimage_load_normal_segment(kimage: Rc<SpinLock<Kimage>>, index: usize) {
mbytes -= mchunk as isize;
if mbytes <= 0 {
return;
return Ok(());
}
}
}

View File

@ -26,7 +26,7 @@ fn init_intertrait() {
intertrait::init_caster_map();
}
pub fn enable_initramfs() -> bool {
pub fn initramfs_enabled() -> bool {
#[cfg(feature = "initram")]
unsafe {
self::initram::__INIT_ROOT_ENABLED

View File

@ -587,31 +587,6 @@ impl SigPending {
}
}
/// @brief 信号处理备用栈的信息
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub struct SigStack {
pub sp: usize,
pub flags: u32,
pub size: u32,
}
impl SigStack {
pub fn new() -> Self {
Self {
sp: 0,
flags: 0,
size: 0,
}
}
}
impl Default for SigStack {
fn default() -> Self {
Self::new()
}
}
/// @brief 进程接收到的信号的队列
#[derive(Debug, Clone, Default)]
pub struct SigQueue {

View File

@ -50,7 +50,7 @@ impl Syscall for SysPidfdSendSignalHandle {
.fd_table()
.read()
.get_file_by_fd(pidfd)
.unwrap();
.ok_or(SystemError::EBADF)?;
if file.private_data.lock().is_pid() {
pid = file.private_data.lock().get_pid();
}

View File

@ -22,7 +22,10 @@ pub fn xz_decompress(compressed_data: &[u8]) -> Result<Vec<u8>, SystemError> {
decompressed_data.extend_from_slice(&temp_buffer[..output_produced]);
break;
}
Err(err) => panic!("Decompression failed {}", err),
Err(err) => {
log::error!("Decompression failed {}", err);
return Err(SystemError::E2BIG);
}
};
}

View File

@ -8,6 +8,7 @@ use crate::mm::{
use core::marker::PhantomData;
use core::sync::atomic::compiler_fence;
use core::sync::atomic::Ordering;
use system_error::SystemError;
/// 恒等页表映射器( paddr == vaddr )
#[derive(Hash)]
@ -55,7 +56,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> IdentPageMapper<Arch, F> {
virt: VirtAddr,
phys: PhysAddr,
mut allocator: F,
) -> Option<PageFlush<Arch>> {
) -> Result<Option<PageFlush<Arch>>, SystemError> {
// 验证虚拟地址和物理地址是否对齐
if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) {
log::error!(
@ -63,7 +64,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> IdentPageMapper<Arch, F> {
virt,
phys
);
return None;
return Err(SystemError::EFAULT);
}
let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK));
@ -80,7 +81,10 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> IdentPageMapper<Arch, F> {
let entry = PageEntry::new(phys, flags);
let mut table = PageTable::new(VirtAddr::new(0), table_paddr, Arch::PAGE_LEVELS - 1);
loop {
let i = table.index_of(virt).unwrap();
let i = table.index_of(virt).ok_or_else(|| {
log::error!("ident_mapper, map_phys: failed to get index of addr!");
SystemError::EINVAL
})?;
assert!(i < Arch::PAGE_ENTRY_NUM);
if table.level() == 0 {
@ -88,14 +92,17 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> IdentPageMapper<Arch, F> {
table.set_entry(i, entry);
compiler_fence(Ordering::SeqCst);
return Some(PageFlush::new(virt));
return Ok(Some(PageFlush::new(virt)));
} else {
let next_table = table.next_level_table(i);
if let Some(next_table) = next_table {
table = next_table;
} else {
// 分配下一级页表
let frame = allocator.allocate_one().unwrap();
let frame = allocator.allocate_one().ok_or_else(|| {
log::error!("ident_mapper, map_phys: allocate table failed");
SystemError::ENOMEM
})?;
// 清空这个页帧
MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
@ -106,7 +113,10 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> IdentPageMapper<Arch, F> {
table.set_entry(i, PageEntry::new(frame, flags));
// 获取新分配的页表
table = table.next_level_table(i).unwrap();
table = table.next_level_table(i).ok_or_else(|| {
log::error!("ident_mapper, map_phys: get next_level_table failed");
SystemError::EPERM
})?;
}
}
}
@ -119,21 +129,27 @@ pub fn ident_pt_alloc() -> usize {
new_imapper.paddr().data()
}
pub fn ident_map_page(table_paddr: usize, virt: usize, phys: usize) {
pub fn ident_map_page(table_paddr: usize, virt: usize, phys: usize) -> Result<(), SystemError> {
unsafe {
IdentPageMapper::<MMArch, LockedFrameAllocator>::map_phys(
PhysAddr::new(table_paddr),
VirtAddr::new(virt),
PhysAddr::new(phys),
LockedFrameAllocator,
)
)?
.unwrap()
.flush();
};
Ok(())
}
/// 需要对齐
pub fn ident_map_pages(table_paddr: usize, virt: usize, phys: usize, nums: usize) {
pub fn ident_map_pages(
table_paddr: usize,
virt: usize,
phys: usize,
nums: usize,
) -> Result<(), SystemError> {
for i in 0..nums {
let virt = virt + i * MMArch::PAGE_SIZE;
let phys = phys + i * MMArch::PAGE_SIZE;
@ -143,9 +159,10 @@ pub fn ident_map_pages(table_paddr: usize, virt: usize, phys: usize, nums: usize
VirtAddr::new(virt),
PhysAddr::new(phys),
LockedFrameAllocator,
)
)?
.unwrap()
.flush()
};
}
Ok(())
}

View File

@ -313,7 +313,7 @@ fn memmap_sysfs_init() -> Result<(), SystemError> {
.init_memmap_bp()
.expect("init bp memmap failed");
boot_callbacks()
.early_init_memmap_sysfs()
.init_memmap_sysfs()
.expect("init sysfs memmap failed");
let memmap_kobj = CommonKobj::new("memmap".to_string());

View File

@ -444,10 +444,9 @@ impl ProcessManager {
ProcessManager::current_pcb().raw_pid().data(),
pid
);
let new_inode = root_inode
.create(&name, FileType::File, ModeType::from_bits_truncate(0o777))
.unwrap();
let file = File::new(new_inode, FileMode::O_RDWR | FileMode::O_CLOEXEC).unwrap();
let new_inode =
root_inode.create(&name, FileType::File, ModeType::from_bits_truncate(0o777))?;
let file = File::new(new_inode, FileMode::O_RDWR | FileMode::O_CLOEXEC)?;
{
let mut guard = file.private_data.lock();
*guard = FilePrivateData::Pid(PidPrivateData::new(pid));

View File

@ -24,7 +24,7 @@ use crate::{
cpu::current_cpu_id,
ipc::signal::{AtomicSignal, SigSet, Signal},
process::ArchPCBInfo,
CurrentIrqArch,
CurrentIrqArch, SigStackArch,
},
driver::tty::tty_core::TtyCore,
exception::InterruptArch,
@ -36,7 +36,7 @@ use crate::{
ipc::{
sighand::SigHand,
signal::RestartBlock,
signal_types::{SigInfo, SigPending, SigStack},
signal_types::{SigInfo, SigPending},
},
libs::{
align::AlignedBox,
@ -757,7 +757,7 @@ pub struct ProcessControlBlock {
sig_info: RwLock<ProcessSignalInfo>,
sighand: RwLock<Arc<SigHand>>,
/// 备用信号栈
sig_altstack: RwLock<SigStack>,
sig_altstack: RwLock<SigStackArch>,
/// 退出信号S
exit_signal: AtomicSignal,
@ -900,7 +900,7 @@ impl ProcessControlBlock {
arch_info,
sig_info: RwLock::new(ProcessSignalInfo::default()),
sighand: RwLock::new(SigHand::new()),
sig_altstack: RwLock::new(SigStack::new()),
sig_altstack: RwLock::new(SigStackArch::new()),
exit_signal: AtomicSignal::new(Signal::SIGCHLD),
parent_pcb: RwLock::new(ppcb.clone()),
real_parent_pcb: RwLock::new(ppcb),
@ -1161,11 +1161,11 @@ impl ProcessControlBlock {
return &self.sched_info;
}
pub fn sig_altstack(&self) -> RwLockReadGuard<'_, SigStack> {
pub fn sig_altstack(&self) -> RwLockReadGuard<'_, SigStackArch> {
self.sig_altstack.read_irqsave()
}
pub fn sig_altstack_mut(&self) -> RwLockWriteGuard<'_, SigStack> {
pub fn sig_altstack_mut(&self) -> RwLockWriteGuard<'_, SigStackArch> {
self.sig_altstack.write_irqsave()
}

View File

@ -5,7 +5,7 @@ use alloc::sync::Arc;
use crate::arch::interrupt::TrapFrame;
use crate::arch::syscall::nr::SYS_EXECVE;
use crate::filesystem::vfs::{IndexNode, MAX_PATHLEN};
use crate::filesystem::vfs::{IndexNode, MAX_PATHLEN, VFS_MAX_FOLLOW_SYMLINK_TIMES};
use crate::mm::page::PAGE_4K_SIZE;
use crate::mm::{verify_area, VirtAddr};
use crate::process::execve::do_execve;
@ -61,20 +61,19 @@ impl SysExecve {
envp: *const *const u8,
) -> Result<(CString, Vec<CString>, Vec<CString>), SystemError> {
let path: CString = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
#[cfg(not(feature = "initram"))]
let argv: Vec<CString> = check_and_clone_cstr_array(argv)?;
#[cfg(feature = "initram")]
let mut argv: Vec<CString> = check_and_clone_cstr_array(argv)?;
let envp: Vec<CString> = check_and_clone_cstr_array(envp)?;
// 这里需要处理符号链接, 目前内核没有完整实现, 这里是个简易的替代
// 例如执行/bin/echo, 必须拿到echo这个名字, 目前内核只有硬链接, 会执行/bin/busybox, 导致无法识别命令
#[cfg(feature = "initram")]
{
let real =
crate::filesystem::vfs::get_link_true_file(argv[0].to_string_lossy().to_string())
.unwrap();
argv[0] = CString::new(real).unwrap();
// 这里需要处理符号链接, 应用程序一般不支持嵌套符号链接
// 如 test -> echo -> busybox, 需要内核代为解析到 echo, 传入 test 则不会让程序执行 echo 命令
let root = ProcessManager::current_mntns().root_inode();
if let Ok(real_inode) = root.lookup_follow_symlink2(
argv[0].to_string_lossy().as_ref(),
VFS_MAX_FOLLOW_SYMLINK_TIMES,
false,
) {
let real_path = real_inode.absolute_path()?;
argv[0] = CString::new(real_path).unwrap();
}
Ok((path, argv, envp))
@ -127,7 +126,7 @@ impl Syscall for SysExecve {
let path = path.into_string().map_err(|_| SystemError::EINVAL)?;
let pwd = ProcessManager::current_pcb().pwd_inode();
let inode = pwd.lookup(&path)?;
let inode = pwd.lookup_follow_symlink(&path, VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
Self::execve(inode, path, argv, envp, frame)?;
return Ok(0);

View File

@ -37,9 +37,15 @@ impl Syscall for SysPidFdOpen {
let pid = Self::pid(args);
let flags = Self::flags(args);
let mode = ModeType::from_bits(flags).unwrap();
let mode = ModeType::from_bits(flags).ok_or_else(|| {
log::error!("SysPidFdOpen: failed to get mode!");
SystemError::EINVAL
})?;
let file_type = FileType::from(mode);
let file_mode = FileMode::from_bits(flags).unwrap();
let file_mode = FileMode::from_bits(flags).ok_or_else(|| {
log::error!("SysPidFdOpen: failed to get file_mode!");
SystemError::EINVAL
})?;
let root_inode = ProcessManager::current_mntns().root_inode();
let name = format!(
@ -47,20 +53,19 @@ impl Syscall for SysPidFdOpen {
ProcessManager::current_pcb().raw_pid().data(),
pid
);
let new_inode = root_inode.create(&name, file_type, mode).unwrap();
let file = File::new(new_inode, file_mode).unwrap();
let new_inode = root_inode.create(&name, file_type, mode)?;
let file = File::new(new_inode, file_mode)?;
{
let mut guard = file.private_data.lock();
*guard = FilePrivateData::Pid(PidPrivateData::new(pid));
}
// 存入pcb
let r = ProcessManager::current_pcb()
ProcessManager::current_pcb()
.fd_table()
.write()
.alloc_fd(file, None)
.map(|fd| fd as usize);
r
.map(|fd| fd as usize)
}
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {