mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 02:46:47 +00:00
feat(riscv): riscv下能够运行hello world用户程序 (#770)
* feat(riscv): riscv下能够运行hello world用户程序
This commit is contained in:
parent
40348dd8d5
commit
471d65cf15
@ -65,7 +65,7 @@ x86_64 = "=0.14.10"
|
|||||||
|
|
||||||
# target为riscv64时,使用下面的依赖
|
# target为riscv64时,使用下面的依赖
|
||||||
[target.'cfg(target_arch = "riscv64")'.dependencies]
|
[target.'cfg(target_arch = "riscv64")'.dependencies]
|
||||||
riscv = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/riscv.git", revision = "cc4d3ea82a", features = [ "s-mode" ] }
|
riscv = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/riscv.git", rev = "4241a97", features = [ "s-mode" ] }
|
||||||
sbi-rt = { version = "=0.0.3", features = ["legacy"] }
|
sbi-rt = { version = "=0.0.3", features = ["legacy"] }
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ use system_error::SystemError;
|
|||||||
use crate::{
|
use crate::{
|
||||||
driver::open_firmware::fdt::OpenFirmwareFdtDriver,
|
driver::open_firmware::fdt::OpenFirmwareFdtDriver,
|
||||||
init::boot_params,
|
init::boot_params,
|
||||||
|
kdebug,
|
||||||
libs::align::page_align_up,
|
libs::align::page_align_up,
|
||||||
mm::{mmio_buddy::mmio_pool, MemoryManagementArch, PhysAddr},
|
mm::{mmio_buddy::mmio_pool, MemoryManagementArch, PhysAddr},
|
||||||
};
|
};
|
||||||
@ -28,6 +29,7 @@ impl OpenFirmwareFdtDriver {
|
|||||||
|
|
||||||
// drop the boot params guard in order to avoid deadlock
|
// drop the boot params guard in order to avoid deadlock
|
||||||
drop(bp_guard);
|
drop(bp_guard);
|
||||||
|
// kdebug!("map_fdt: map fdt to {:?}, size: {}", map_paddr, map_size);
|
||||||
mmio_guard.map_phys(map_paddr, map_size)?;
|
mmio_guard.map_phys(map_paddr, map_size)?;
|
||||||
let mut bp_guard = boot_params().write();
|
let mut bp_guard = boot_params().write();
|
||||||
let vaddr = mmio_guard.vaddr() + offset;
|
let vaddr = mmio_guard.vaddr() + offset;
|
||||||
|
@ -112,7 +112,7 @@ pub fn early_setup_arch() -> Result<(), SystemError> {
|
|||||||
arch_boot_params_guard.arch.fdt_paddr = fdt_paddr;
|
arch_boot_params_guard.arch.fdt_paddr = fdt_paddr;
|
||||||
arch_boot_params_guard.arch.fdt_size = fdt.total_size();
|
arch_boot_params_guard.arch.fdt_size = fdt.total_size();
|
||||||
arch_boot_params_guard.arch.boot_hartid = ProcessorId::new(hartid);
|
arch_boot_params_guard.arch.boot_hartid = ProcessorId::new(hartid);
|
||||||
|
// kdebug!("fdt_paddr: {:?}, fdt_size: {}", fdt_paddr, fdt.total_size());
|
||||||
drop(arch_boot_params_guard);
|
drop(arch_boot_params_guard);
|
||||||
|
|
||||||
kinfo!(
|
kinfo!(
|
||||||
|
@ -160,7 +160,8 @@ unsafe extern "C" fn _save_context() -> ! {
|
|||||||
off_cause = const offset_of!(TrapFrame, cause),
|
off_cause = const offset_of!(TrapFrame, cause),
|
||||||
off_tp = const offset_of!(TrapFrame, tp),
|
off_tp = const offset_of!(TrapFrame, tp),
|
||||||
off_epc = const offset_of!(TrapFrame, epc),
|
off_epc = const offset_of!(TrapFrame, epc),
|
||||||
sr_sum_and_fsvs = const (SR_FS_VS | SR_SUM),
|
sr_sum_and_fsvs = const (0), // 暂时在内核中不禁用FPU和Vector,以及不禁用用户内存访问
|
||||||
|
// sr_sum_and_fsvs = const (SR_FS_VS | SR_SUM),
|
||||||
csr_status = const CSR_SSTATUS,
|
csr_status = const CSR_SSTATUS,
|
||||||
csr_epc = const CSR_SEPC,
|
csr_epc = const CSR_SEPC,
|
||||||
csr_tval = const CSR_STVAL,
|
csr_tval = const CSR_STVAL,
|
||||||
|
@ -48,10 +48,6 @@ fn riscv64_do_interrupt(trap_frame: &mut TrapFrame) {
|
|||||||
|
|
||||||
/// 处理异常
|
/// 处理异常
|
||||||
fn riscv64_do_exception(trap_frame: &mut TrapFrame) {
|
fn riscv64_do_exception(trap_frame: &mut TrapFrame) {
|
||||||
kdebug!(
|
|
||||||
"riscv64_do_exception: from_user: {}",
|
|
||||||
trap_frame.is_from_user()
|
|
||||||
);
|
|
||||||
let code = trap_frame.cause.code();
|
let code = trap_frame.cause.code();
|
||||||
|
|
||||||
if code < EXCEPTION_HANDLERS.len() {
|
if code < EXCEPTION_HANDLERS.len() {
|
||||||
@ -153,8 +149,16 @@ fn do_trap_user_env_call(trap_frame: &mut TrapFrame) -> Result<(), SystemError>
|
|||||||
// 9-11 reserved
|
// 9-11 reserved
|
||||||
|
|
||||||
/// 处理指令页错误异常 #12
|
/// 处理指令页错误异常 #12
|
||||||
fn do_trap_insn_page_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
|
fn do_trap_insn_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
|
||||||
kerror!("riscv64_do_irq: do_insn_page_fault");
|
let vaddr = trap_frame.badaddr;
|
||||||
|
let cause = trap_frame.cause;
|
||||||
|
let epc = trap_frame.epc;
|
||||||
|
kerror!(
|
||||||
|
"riscv64_do_irq: do_insn_page_fault vaddr: {:#x}, cause: {:?} epc: {:#x}",
|
||||||
|
vaddr,
|
||||||
|
cause,
|
||||||
|
epc
|
||||||
|
);
|
||||||
loop {
|
loop {
|
||||||
spin_loop();
|
spin_loop();
|
||||||
}
|
}
|
||||||
@ -179,8 +183,13 @@ fn do_trap_load_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError
|
|||||||
// 14 reserved
|
// 14 reserved
|
||||||
|
|
||||||
/// 处理页存储错误异常 #15
|
/// 处理页存储错误异常 #15
|
||||||
fn do_trap_store_page_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
|
fn do_trap_store_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
|
||||||
kerror!("riscv64_do_irq: do_trap_store_page_fault");
|
kerror!(
|
||||||
|
"riscv64_do_irq: do_trap_store_page_fault: epc: {:#x}, vaddr={:#x}, cause={:?}",
|
||||||
|
trap_frame.epc,
|
||||||
|
trap_frame.badaddr,
|
||||||
|
trap_frame.cause
|
||||||
|
);
|
||||||
loop {
|
loop {
|
||||||
spin_loop();
|
spin_loop();
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,8 @@ pub(super) unsafe fn riscv_mm_init() -> Result<(), SystemError> {
|
|||||||
mem_block_manager()
|
mem_block_manager()
|
||||||
.reserve_block(KERNEL_BEGIN_PA, KERNEL_END_PA - KERNEL_BEGIN_PA)
|
.reserve_block(KERNEL_BEGIN_PA, KERNEL_END_PA - KERNEL_BEGIN_PA)
|
||||||
.expect("Failed to reserve kernel memory");
|
.expect("Failed to reserve kernel memory");
|
||||||
|
// 开启S-mode User Memory Access,允许内核访问用户空间
|
||||||
|
riscv::register::sstatus::set_sum();
|
||||||
|
|
||||||
let mut bump_allocator = BumpAllocator::<RiscV64MMArch>::new(0);
|
let mut bump_allocator = BumpAllocator::<RiscV64MMArch>::new(0);
|
||||||
let _old_page_table = MMArch::table(PageTableKind::Kernel);
|
let _old_page_table = MMArch::table(PageTableKind::Kernel);
|
||||||
@ -76,7 +78,7 @@ pub(super) unsafe fn riscv_mm_init() -> Result<(), SystemError> {
|
|||||||
|
|
||||||
// 使用bump分配器,把所有的内存页都映射到页表
|
// 使用bump分配器,把所有的内存页都映射到页表
|
||||||
{
|
{
|
||||||
kdebug!("to create new page table");
|
// kdebug!("to create new page table");
|
||||||
// 用bump allocator创建新的页表
|
// 用bump allocator创建新的页表
|
||||||
let mut mapper: crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>> =
|
let mut mapper: crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>> =
|
||||||
crate::mm::page::PageMapper::<MMArch, _>::create(
|
crate::mm::page::PageMapper::<MMArch, _>::create(
|
||||||
@ -85,7 +87,7 @@ pub(super) unsafe fn riscv_mm_init() -> Result<(), SystemError> {
|
|||||||
)
|
)
|
||||||
.expect("Failed to create page mapper");
|
.expect("Failed to create page mapper");
|
||||||
new_page_table = mapper.table().phys();
|
new_page_table = mapper.table().phys();
|
||||||
kdebug!("PageMapper created");
|
// kdebug!("PageMapper created");
|
||||||
|
|
||||||
// 取消最开始时候,在head.S中指定的映射(暂时不刷新TLB)
|
// 取消最开始时候,在head.S中指定的映射(暂时不刷新TLB)
|
||||||
{
|
{
|
||||||
|
@ -105,7 +105,9 @@ impl MemoryManagementArch for RiscV64MMArch {
|
|||||||
|
|
||||||
const ENTRY_FLAG_PRESENT: usize = 1 << 0;
|
const ENTRY_FLAG_PRESENT: usize = 1 << 0;
|
||||||
|
|
||||||
const ENTRY_FLAG_READONLY: usize = 0;
|
const ENTRY_FLAG_READONLY: usize = (1 << 1);
|
||||||
|
|
||||||
|
const ENTRY_FLAG_WRITEABLE: usize = (1 << 2);
|
||||||
|
|
||||||
const ENTRY_FLAG_READWRITE: usize = (1 << 2) | (1 << 1);
|
const ENTRY_FLAG_READWRITE: usize = (1 << 2) | (1 << 1);
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ impl ProcessManager {
|
|||||||
spin_loop();
|
spin_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
kdebug!("idle loop");
|
// kdebug!("idle loop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ impl KernelThreadMechanism {
|
|||||||
// 使能中断
|
// 使能中断
|
||||||
frame.status.update_sie(true);
|
frame.status.update_sie(true);
|
||||||
frame.status.update_spp(SPP::Supervisor);
|
frame.status.update_spp(SPP::Supervisor);
|
||||||
|
frame.status.update_sum(true);
|
||||||
|
|
||||||
frame.ra = kernel_thread_bootstrap_stage1 as usize;
|
frame.ra = kernel_thread_bootstrap_stage1 as usize;
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ use crate::{
|
|||||||
PROCESS_SWITCH_RESULT,
|
PROCESS_SWITCH_RESULT,
|
||||||
},
|
},
|
||||||
smp::cpu::ProcessorId,
|
smp::cpu::ProcessorId,
|
||||||
|
syscall::Syscall,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@ -53,7 +54,64 @@ static BSP_IDLE_STACK_SPACE: InitProcUnion = InitProcUnion {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<String>) -> ! {
|
pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<String>) -> ! {
|
||||||
unimplemented!("RiscV64 arch_switch_to_user")
|
// 以下代码不能发生中断
|
||||||
|
CurrentIrqArch::interrupt_disable();
|
||||||
|
|
||||||
|
let current_pcb = ProcessManager::current_pcb();
|
||||||
|
let trap_frame_vaddr = VirtAddr::new(
|
||||||
|
current_pcb.kernel_stack().stack_max_address().data() - core::mem::size_of::<TrapFrame>(),
|
||||||
|
);
|
||||||
|
let new_pc = VirtAddr::new(ret_from_exception as usize);
|
||||||
|
|
||||||
|
let mut arch_guard = current_pcb.arch_info_irqsave();
|
||||||
|
arch_guard.ksp = trap_frame_vaddr.data();
|
||||||
|
|
||||||
|
arch_guard.ra = new_pc.data();
|
||||||
|
drop(arch_guard);
|
||||||
|
|
||||||
|
// 删除kthread的标志
|
||||||
|
current_pcb.flags().remove(ProcessFlags::KTHREAD);
|
||||||
|
current_pcb.worker_private().take();
|
||||||
|
|
||||||
|
*current_pcb.sched_info().sched_policy.write_irqsave() = crate::sched::SchedPolicy::CFS;
|
||||||
|
|
||||||
|
let mut trap_frame = TrapFrame::new();
|
||||||
|
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
Syscall::do_execve(path, argv, envp, &mut trap_frame).unwrap_or_else(|e| {
|
||||||
|
panic!(
|
||||||
|
"arch_switch_to_user(): pid: {pid:?}, Failed to execve: , error: {e:?}",
|
||||||
|
pid = current_pcb.pid(),
|
||||||
|
e = e
|
||||||
|
);
|
||||||
|
});
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
// 重要!在这里之后,一定要保证上面的引用计数变量、动态申请的变量、锁的守卫都被drop了,否则可能导致内存安全问题!
|
||||||
|
|
||||||
|
drop(current_pcb);
|
||||||
|
|
||||||
|
*(trap_frame_vaddr.data() as *mut TrapFrame) = trap_frame;
|
||||||
|
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
ready_to_switch_to_user(trap_frame_vaddr.data(), new_pc.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
unsafe extern "C" fn ready_to_switch_to_user(trap_frame: usize, new_pc: usize) -> ! {
|
||||||
|
asm!(
|
||||||
|
concat!(
|
||||||
|
"
|
||||||
|
// 设置trap frame
|
||||||
|
mv sp, a0
|
||||||
|
// 设置返回地址
|
||||||
|
|
||||||
|
jr a1
|
||||||
|
|
||||||
|
"
|
||||||
|
),
|
||||||
|
options(noreturn)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProcessManager {
|
impl ProcessManager {
|
||||||
@ -98,6 +156,7 @@ impl ProcessManager {
|
|||||||
let current_arch_guard = current_pcb.arch_info_irqsave();
|
let current_arch_guard = current_pcb.arch_info_irqsave();
|
||||||
// 拷贝浮点寄存器的状态
|
// 拷贝浮点寄存器的状态
|
||||||
new_arch_guard.fp_state = current_arch_guard.fp_state;
|
new_arch_guard.fp_state = current_arch_guard.fp_state;
|
||||||
|
new_arch_guard.sstatus = current_arch_guard.sstatus;
|
||||||
|
|
||||||
drop(current_arch_guard);
|
drop(current_arch_guard);
|
||||||
|
|
||||||
@ -128,11 +187,11 @@ impl ProcessManager {
|
|||||||
/// 参考: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/include/asm/switch_to.h#76
|
/// 参考: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/include/asm/switch_to.h#76
|
||||||
pub unsafe fn switch_process(prev: Arc<ProcessControlBlock>, next: Arc<ProcessControlBlock>) {
|
pub unsafe fn switch_process(prev: Arc<ProcessControlBlock>, next: Arc<ProcessControlBlock>) {
|
||||||
assert!(!CurrentIrqArch::is_irq_enabled());
|
assert!(!CurrentIrqArch::is_irq_enabled());
|
||||||
kdebug!(
|
// kdebug!(
|
||||||
"riscv switch process: prev: {:?}, next: {:?}",
|
// "riscv switch process: prev: {:?}, next: {:?}",
|
||||||
prev.pid(),
|
// prev.pid(),
|
||||||
next.pid()
|
// next.pid()
|
||||||
);
|
// );
|
||||||
Self::switch_process_fpu(&prev, &next);
|
Self::switch_process_fpu(&prev, &next);
|
||||||
Self::switch_local_context(&prev, &next);
|
Self::switch_local_context(&prev, &next);
|
||||||
|
|
||||||
@ -144,6 +203,8 @@ impl ProcessManager {
|
|||||||
drop(next_addr_space);
|
drop(next_addr_space);
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
// kdebug!("current sum={}, prev sum={}, next_sum={}", riscv::register::sstatus::read().sum(), prev.arch_info_irqsave().sstatus.sum(), next.arch_info_irqsave().sstatus.sum());
|
||||||
|
|
||||||
// 获取arch info的锁,并强制泄露其守卫(切换上下文后,在switch_finish_hook中会释放锁)
|
// 获取arch info的锁,并强制泄露其守卫(切换上下文后,在switch_finish_hook中会释放锁)
|
||||||
let next_arch = SpinLockGuard::leak(next.arch_info_irqsave()) as *mut ArchPCBInfo;
|
let next_arch = SpinLockGuard::leak(next.arch_info_irqsave()) as *mut ArchPCBInfo;
|
||||||
let prev_arch = SpinLockGuard::leak(prev.arch_info_irqsave()) as *mut ArchPCBInfo;
|
let prev_arch = SpinLockGuard::leak(prev.arch_info_irqsave()) as *mut ArchPCBInfo;
|
||||||
@ -153,7 +214,7 @@ impl ProcessManager {
|
|||||||
ProcessManager::current_pcb().preempt_enable();
|
ProcessManager::current_pcb().preempt_enable();
|
||||||
PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().prev_pcb = Some(prev);
|
PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().prev_pcb = Some(prev);
|
||||||
PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().next_pcb = Some(next);
|
PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().next_pcb = Some(next);
|
||||||
kdebug!("riscv switch process: before to inner");
|
// kdebug!("riscv switch process: before to inner");
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
// 正式切换上下文
|
// 正式切换上下文
|
||||||
switch_to_inner(prev_arch, next_arch);
|
switch_to_inner(prev_arch, next_arch);
|
||||||
@ -206,8 +267,8 @@ unsafe extern "C" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBI
|
|||||||
|
|
||||||
addi sp , sp, -8
|
addi sp , sp, -8
|
||||||
sd a1, 0(sp)
|
sd a1, 0(sp)
|
||||||
csrr a0, sstatus
|
csrr a1, sstatus
|
||||||
sd a0, {off_sstatus}(a1)
|
sd a1, {off_sstatus}(a0)
|
||||||
ld a1, 0(sp)
|
ld a1, 0(sp)
|
||||||
addi sp, sp, 8
|
addi sp, sp, 8
|
||||||
|
|
||||||
@ -271,13 +332,12 @@ unsafe extern "C" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBI
|
|||||||
/// 在切换上下文完成后的钩子函数(必须在这里加一个跳转函数,否则会出现relocation truncated to fit: R_RISCV_JAL错误)
|
/// 在切换上下文完成后的钩子函数(必须在这里加一个跳转函数,否则会出现relocation truncated to fit: R_RISCV_JAL错误)
|
||||||
unsafe extern "C" fn before_switch_finish_hook() {
|
unsafe extern "C" fn before_switch_finish_hook() {
|
||||||
let pcb = ProcessManager::current_pcb();
|
let pcb = ProcessManager::current_pcb();
|
||||||
kdebug!(
|
// kdebug!(
|
||||||
"before_switch_finish_hook, pid: {:?}, name: {:?}",
|
// "before_switch_finish_hook, pid: {:?}, name: {:?}",
|
||||||
pcb.pid(),
|
// pcb.pid(),
|
||||||
pcb.basic().name()
|
// pcb.basic().name()
|
||||||
);
|
// );
|
||||||
switch_finish_hook();
|
switch_finish_hook();
|
||||||
kdebug!("after switch_finish_hook");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProcessControlBlock {
|
impl ProcessControlBlock {
|
||||||
@ -344,6 +404,8 @@ impl ArchPCBInfo {
|
|||||||
///
|
///
|
||||||
/// 返回一个新的ArchPCBInfo
|
/// 返回一个新的ArchPCBInfo
|
||||||
pub fn new(kstack: &KernelStack) -> Self {
|
pub fn new(kstack: &KernelStack) -> Self {
|
||||||
|
let mut sstatus = Sstatus::from(0);
|
||||||
|
sstatus.update_sum(true);
|
||||||
Self {
|
Self {
|
||||||
ra: 0,
|
ra: 0,
|
||||||
ksp: kstack.stack_max_address().data(),
|
ksp: kstack.stack_max_address().data(),
|
||||||
@ -359,7 +421,7 @@ impl ArchPCBInfo {
|
|||||||
s9: 0,
|
s9: 0,
|
||||||
s10: 0,
|
s10: 0,
|
||||||
s11: 0,
|
s11: 0,
|
||||||
sstatus: Sstatus::from(0),
|
sstatus,
|
||||||
fp_state: FpDExtState::new(),
|
fp_state: FpDExtState::new(),
|
||||||
local_context: LocalContext::new(ProcessorId::new(0)),
|
local_context: LocalContext::new(ProcessorId::new(0)),
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,18 @@
|
|||||||
use alloc::{string::String, vec::Vec};
|
use alloc::{string::String, vec::Vec};
|
||||||
|
use riscv::register::sstatus::{Sstatus, FS, SPP};
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::{arch::interrupt::TrapFrame, syscall::Syscall};
|
use crate::{
|
||||||
|
arch::{interrupt::TrapFrame, CurrentIrqArch},
|
||||||
|
exception::InterruptArch,
|
||||||
|
kdebug,
|
||||||
|
mm::ucontext::AddressSpace,
|
||||||
|
process::{
|
||||||
|
exec::{load_binary_file, ExecParam, ExecParamFlags},
|
||||||
|
ProcessManager,
|
||||||
|
},
|
||||||
|
syscall::Syscall,
|
||||||
|
};
|
||||||
|
|
||||||
impl Syscall {
|
impl Syscall {
|
||||||
pub fn do_execve(
|
pub fn do_execve(
|
||||||
@ -10,7 +21,95 @@ impl Syscall {
|
|||||||
envp: Vec<String>,
|
envp: Vec<String>,
|
||||||
regs: &mut TrapFrame,
|
regs: &mut TrapFrame,
|
||||||
) -> Result<(), SystemError> {
|
) -> Result<(), SystemError> {
|
||||||
unimplemented!("Syscall::do_execve")
|
// 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
|
||||||
|
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||||
|
let pcb = ProcessManager::current_pcb();
|
||||||
|
// crate::kdebug!(
|
||||||
|
// "pid: {:?} do_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
|
||||||
|
// pcb.pid(),
|
||||||
|
// path,
|
||||||
|
// argv,
|
||||||
|
// envp
|
||||||
|
// );
|
||||||
|
|
||||||
|
let mut basic_info = pcb.basic_mut();
|
||||||
|
// 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free)
|
||||||
|
let old_address_space = basic_info.user_vm();
|
||||||
|
|
||||||
|
// 在pcb中原来的用户地址空间
|
||||||
|
unsafe {
|
||||||
|
basic_info.set_user_vm(None);
|
||||||
|
}
|
||||||
|
// 创建新的地址空间并设置为当前地址空间
|
||||||
|
let address_space = AddressSpace::new(true).expect("Failed to create new address space");
|
||||||
|
unsafe {
|
||||||
|
basic_info.set_user_vm(Some(address_space.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// to avoid deadlock
|
||||||
|
drop(basic_info);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
AddressSpace::is_current(&address_space),
|
||||||
|
"Failed to set address space"
|
||||||
|
);
|
||||||
|
// kdebug!("Switch to new address space");
|
||||||
|
|
||||||
|
// 切换到新的用户地址空间
|
||||||
|
unsafe { address_space.read().user_mapper.utable.make_current() };
|
||||||
|
|
||||||
|
drop(old_address_space);
|
||||||
|
drop(irq_guard);
|
||||||
|
// kdebug!("to load binary file");
|
||||||
|
let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC)?;
|
||||||
|
|
||||||
|
// 加载可执行文件
|
||||||
|
let load_result = load_binary_file(&mut param)
|
||||||
|
.unwrap_or_else(|e| panic!("Failed to load binary file: {:?}, path: {:?}", e, path));
|
||||||
|
// kdebug!("load binary file done");
|
||||||
|
// kdebug!("argv: {:?}, envp: {:?}", argv, envp);
|
||||||
|
param.init_info_mut().args = argv;
|
||||||
|
param.init_info_mut().envs = envp;
|
||||||
|
|
||||||
|
// 把proc_init_info写到用户栈上
|
||||||
|
let mut ustack_message = unsafe {
|
||||||
|
address_space
|
||||||
|
.write()
|
||||||
|
.user_stack_mut()
|
||||||
|
.expect("No user stack found")
|
||||||
|
.clone_info_only()
|
||||||
|
};
|
||||||
|
let (user_sp, argv_ptr) = unsafe {
|
||||||
|
param
|
||||||
|
.init_info()
|
||||||
|
.push_at(
|
||||||
|
// address_space
|
||||||
|
// .write()
|
||||||
|
// .user_stack_mut()
|
||||||
|
// .expect("No user stack found"),
|
||||||
|
&mut ustack_message,
|
||||||
|
)
|
||||||
|
.expect("Failed to push proc_init_info to user stack")
|
||||||
|
};
|
||||||
|
address_space.write().user_stack = Some(ustack_message);
|
||||||
|
|
||||||
|
// kdebug!("write proc_init_info to user stack done");
|
||||||
|
|
||||||
|
regs.a0 = param.init_info().args.len();
|
||||||
|
regs.a1 = argv_ptr.data();
|
||||||
|
|
||||||
|
// 设置系统调用返回时的寄存器状态
|
||||||
|
regs.sp = user_sp.data();
|
||||||
|
|
||||||
|
regs.epc = load_result.entry_point().data();
|
||||||
|
regs.status.update_spp(SPP::User);
|
||||||
|
regs.status.update_fs(FS::Clean);
|
||||||
|
regs.status.update_sie(true);
|
||||||
|
regs.status.update_sum(true);
|
||||||
|
|
||||||
|
drop(param);
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## 用于控制和查询与体系结构相关的进程特定选项
|
/// ## 用于控制和查询与体系结构相关的进程特定选项
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
pub mod nr;
|
pub mod nr;
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::{exception::InterruptArch, process::ProcessManager, syscall::Syscall};
|
use crate::{exception::InterruptArch, kdebug, process::ProcessManager, syscall::Syscall};
|
||||||
|
|
||||||
use super::{interrupt::TrapFrame, CurrentIrqArch};
|
use super::{interrupt::TrapFrame, CurrentIrqArch};
|
||||||
|
|
||||||
@ -29,6 +29,7 @@ macro_rules! syscall_return {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn syscall_handler(syscall_num: usize, frame: &mut TrapFrame) -> () {
|
pub(super) fn syscall_handler(syscall_num: usize, frame: &mut TrapFrame) -> () {
|
||||||
|
// kdebug!("syscall_handler: syscall_num: {}", syscall_num);
|
||||||
unsafe {
|
unsafe {
|
||||||
CurrentIrqArch::interrupt_enable();
|
CurrentIrqArch::interrupt_enable();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
driver::open_firmware::fdt::open_firmware_fdt_driver,
|
driver::open_firmware::fdt::open_firmware_fdt_driver,
|
||||||
kinfo,
|
kdebug, kinfo,
|
||||||
time::{clocksource::HZ, TimeArch},
|
time::{clocksource::HZ, TimeArch},
|
||||||
};
|
};
|
||||||
pub struct RiscV64TimeArch;
|
pub struct RiscV64TimeArch;
|
||||||
@ -14,10 +14,12 @@ static mut TIME_FREQ: usize = 0;
|
|||||||
///
|
///
|
||||||
/// todo: 支持从acpi中获取
|
/// todo: 支持从acpi中获取
|
||||||
fn init_time_freq() {
|
fn init_time_freq() {
|
||||||
|
kdebug!("init_time_freq: init");
|
||||||
let fdt = open_firmware_fdt_driver().fdt_ref();
|
let fdt = open_firmware_fdt_driver().fdt_ref();
|
||||||
if fdt.is_err() {
|
if fdt.is_err() {
|
||||||
panic!("init_time_freq: failed to get fdt");
|
panic!("init_time_freq: failed to get fdt");
|
||||||
}
|
}
|
||||||
|
kdebug!("init_time_freq: get fdt");
|
||||||
let fdt = fdt.unwrap();
|
let fdt = fdt.unwrap();
|
||||||
let cpu_node = fdt.find_node("/cpus");
|
let cpu_node = fdt.find_node("/cpus");
|
||||||
if cpu_node.is_none() {
|
if cpu_node.is_none() {
|
||||||
|
@ -94,6 +94,7 @@ impl MemoryManagementArch for X86_64MMArch {
|
|||||||
|
|
||||||
const ENTRY_FLAG_READONLY: usize = 0;
|
const ENTRY_FLAG_READONLY: usize = 0;
|
||||||
|
|
||||||
|
const ENTRY_FLAG_WRITEABLE: usize = 1 << 1;
|
||||||
const ENTRY_FLAG_READWRITE: usize = 1 << 1;
|
const ENTRY_FLAG_READWRITE: usize = 1 << 1;
|
||||||
|
|
||||||
const ENTRY_FLAG_USER: usize = 1 << 2;
|
const ENTRY_FLAG_USER: usize = 1 << 2;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
CFLAGS += -I .
|
CFLAGS += -I .
|
||||||
|
|
||||||
kernel_driver_subdirs:=acpi disk multiboot2 timers
|
kernel_driver_subdirs:=acpi multiboot2
|
||||||
|
|
||||||
ECHO:
|
ECHO:
|
||||||
@echo "$@"
|
@echo "$@"
|
||||||
|
@ -34,11 +34,11 @@ impl RiscVSbiTimer {
|
|||||||
|
|
||||||
fn handle_irq(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
|
fn handle_irq(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
|
||||||
// 更新下一次中断时间
|
// 更新下一次中断时间
|
||||||
kdebug!(
|
// kdebug!(
|
||||||
"riscv_sbi_timer: handle_irq: cpu_id: {}, time: {}",
|
// "riscv_sbi_timer: handle_irq: cpu_id: {}, time: {}",
|
||||||
smp_get_processor_id().data(),
|
// smp_get_processor_id().data(),
|
||||||
CurrentTimeArch::get_cycles() as u64
|
// CurrentTimeArch::get_cycles() as u64
|
||||||
);
|
// );
|
||||||
sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64 + unsafe { INTERVAL_CNT } as u64);
|
sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64 + unsafe { INTERVAL_CNT } as u64);
|
||||||
ProcessManager::update_process_times(trap_frame.is_from_user());
|
ProcessManager::update_process_times(trap_frame.is_from_user());
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
SRC = $(wildcard *.c)
|
|
||||||
OBJ = $(SRC:.c=.o)
|
|
||||||
CFLAGS += -I .
|
|
||||||
|
|
||||||
.PHONY: all
|
|
||||||
|
|
||||||
all: $(OBJ)
|
|
||||||
|
|
||||||
%.o: %.c
|
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
|
13
kernel/src/driver/firmware/efi/esrt.rs
Normal file
13
kernel/src/driver/firmware/efi/esrt.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//! 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/esrt.c#1
|
||||||
|
|
||||||
|
use super::efi_manager;
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
pub(super) fn efi_esrt_init() {
|
||||||
|
if !efi_manager().esrt_table_exists() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: 参考linux 的 `efi_esrt_init`来实现
|
||||||
|
todo!("efi_esrt_init")
|
||||||
|
}
|
@ -29,6 +29,15 @@ pub static EFI_MEMRESERVE_TABLE_GUID: Guid = Guid::new(
|
|||||||
0xf0,
|
0xf0,
|
||||||
[0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2],
|
[0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
pub static EFI_SYSTEM_RESOURCE_TABLE_GUID: Guid = Guid::new(
|
||||||
|
unsafe { mem::transmute_copy(&0xb122a263u32) },
|
||||||
|
unsafe { mem::transmute_copy(&0x3661u32) },
|
||||||
|
unsafe { mem::transmute_copy(&0x4f68u32) },
|
||||||
|
0x99,
|
||||||
|
0x29,
|
||||||
|
[0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80],
|
||||||
|
);
|
||||||
/// 表示内核被加载到的地址的信息。
|
/// 表示内核被加载到的地址的信息。
|
||||||
///
|
///
|
||||||
/// 对应 `DRAGONSTUB_EFI_PAYLOAD_EFI_GUID`
|
/// 对应 `DRAGONSTUB_EFI_PAYLOAD_EFI_GUID`
|
||||||
|
@ -5,7 +5,10 @@ use uefi_raw::table::boot::{MemoryAttribute, MemoryType};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::MMArch,
|
arch::MMArch,
|
||||||
driver::{firmware::efi::EFIInitFlags, open_firmware::fdt::open_firmware_fdt_driver},
|
driver::{
|
||||||
|
firmware::efi::{esrt::efi_esrt_init, EFIInitFlags},
|
||||||
|
open_firmware::fdt::open_firmware_fdt_driver,
|
||||||
|
},
|
||||||
libs::align::{page_align_down, page_align_up},
|
libs::align::{page_align_down, page_align_up},
|
||||||
mm::{
|
mm::{
|
||||||
allocator::page_frame::PhysPageFrame, early_ioremap::EarlyIoRemap,
|
allocator::page_frame::PhysPageFrame, early_ioremap::EarlyIoRemap,
|
||||||
@ -66,6 +69,11 @@ pub fn efi_init() {
|
|||||||
// todo: 模仿Linux的行为,做好接下来的几步工作:
|
// todo: 模仿Linux的行为,做好接下来的几步工作:
|
||||||
// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/efi-init.c#217
|
// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/efi-init.c#217
|
||||||
|
|
||||||
|
// todo: early_init_dt_check_for_usable_mem_range
|
||||||
|
|
||||||
|
efi_find_mirror();
|
||||||
|
efi_esrt_init();
|
||||||
|
|
||||||
// 保留mmap table的内存
|
// 保留mmap table的内存
|
||||||
let base = page_align_down(data_from_fdt.mmap_base.unwrap() as usize);
|
let base = page_align_down(data_from_fdt.mmap_base.unwrap() as usize);
|
||||||
let offset = data_from_fdt.mmap_base.unwrap() as usize - base;
|
let offset = data_from_fdt.mmap_base.unwrap() as usize - base;
|
||||||
@ -78,7 +86,7 @@ pub fn efi_init() {
|
|||||||
.expect("Failed to reserve memory for EFI mmap table");
|
.expect("Failed to reserve memory for EFI mmap table");
|
||||||
|
|
||||||
// 保留内核的内存
|
// 保留内核的内存
|
||||||
if let Some(info) = efi_manager().inner.read().dragonstub_load_info {
|
if let Some(info) = efi_manager().inner_read().dragonstub_load_info {
|
||||||
mem_block_manager()
|
mem_block_manager()
|
||||||
.reserve_block(
|
.reserve_block(
|
||||||
PhysAddr::new(info.paddr as usize),
|
PhysAddr::new(info.paddr as usize),
|
||||||
@ -92,6 +100,31 @@ pub fn efi_init() {
|
|||||||
kinfo!("UEFI init done!");
|
kinfo!("UEFI init done!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn efi_find_mirror() {
|
||||||
|
let efi_guard = efi_manager().inner_read();
|
||||||
|
let mut total_size = 0;
|
||||||
|
let mut mirror_size = 0;
|
||||||
|
for md in efi_guard.mmap.iter() {
|
||||||
|
let start = PhysAddr::new(md.phys_start as usize);
|
||||||
|
let size = (md.page_count << (MMArch::PAGE_SHIFT as u64)) as usize;
|
||||||
|
|
||||||
|
if md.att.contains(MemoryAttribute::MORE_RELIABLE) {
|
||||||
|
mem_block_manager().mark_mirror(start, size).unwrap();
|
||||||
|
mirror_size += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_size += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if mirror_size > 0 {
|
||||||
|
kinfo!(
|
||||||
|
"Memory: {}M/{}M mirrored memory",
|
||||||
|
mirror_size >> 20,
|
||||||
|
total_size >> 20
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> {
|
fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> {
|
||||||
// 定义错误处理函数
|
// 定义错误处理函数
|
||||||
@ -142,7 +175,7 @@ fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> {
|
|||||||
let st_ref = unsafe { st_ptr.as_ref().unwrap() };
|
let st_ref = unsafe { st_ptr.as_ref().unwrap() };
|
||||||
|
|
||||||
let runtime_service_paddr = efi_vaddr_2_paddr(st_ref.runtime_services as usize);
|
let runtime_service_paddr = efi_vaddr_2_paddr(st_ref.runtime_services as usize);
|
||||||
let mut inner_write_guard = efi_manager().inner.write();
|
let mut inner_write_guard = efi_manager().inner_write();
|
||||||
inner_write_guard.runtime_paddr = Some(runtime_service_paddr);
|
inner_write_guard.runtime_paddr = Some(runtime_service_paddr);
|
||||||
inner_write_guard.runtime_service_version = Some(st_ref.header.revision);
|
inner_write_guard.runtime_service_version = Some(st_ref.header.revision);
|
||||||
|
|
||||||
@ -189,7 +222,7 @@ fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> {
|
|||||||
///
|
///
|
||||||
/// 在进入该函数前,请不要持有`efi_manager().inner`的写锁
|
/// 在进入该函数前,请不要持有`efi_manager().inner`的写锁
|
||||||
fn efi_vaddr_2_paddr(efi_vaddr: usize) -> PhysAddr {
|
fn efi_vaddr_2_paddr(efi_vaddr: usize) -> PhysAddr {
|
||||||
let guard = efi_manager().inner.read();
|
let guard = efi_manager().inner_read();
|
||||||
let mmap = &guard.mmap;
|
let mmap = &guard.mmap;
|
||||||
|
|
||||||
let efi_vaddr: u64 = efi_vaddr as u64;
|
let efi_vaddr: u64 = efi_vaddr as u64;
|
||||||
@ -236,6 +269,11 @@ fn reserve_memory_regions() {
|
|||||||
if md.is_memory() {
|
if md.is_memory() {
|
||||||
open_firmware_fdt_driver().early_init_dt_add_memory(phys_start as u64, size as u64);
|
open_firmware_fdt_driver().early_init_dt_add_memory(phys_start as u64, size as u64);
|
||||||
if !md.is_usable_memory() {
|
if !md.is_usable_memory() {
|
||||||
|
// kdebug!(
|
||||||
|
// "Marking non-usable memory as nomap: {:#x}-{:#x}",
|
||||||
|
// phys_start,
|
||||||
|
// phys_start + size
|
||||||
|
// );
|
||||||
mem_block_manager()
|
mem_block_manager()
|
||||||
.mark_nomap(PhysAddr::new(phys_start), size)
|
.mark_nomap(PhysAddr::new(phys_start), size)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::{libs::rwlock::RwLock, mm::PhysAddr};
|
use crate::{
|
||||||
|
libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||||
|
mm::PhysAddr,
|
||||||
|
};
|
||||||
|
|
||||||
use self::{guid::DragonStubPayloadEFI, memmap::EFIMemoryMapInfo};
|
use self::{guid::DragonStubPayloadEFI, memmap::EFIMemoryMapInfo};
|
||||||
|
|
||||||
|
pub mod esrt;
|
||||||
mod fdt;
|
mod fdt;
|
||||||
pub mod guid;
|
pub mod guid;
|
||||||
pub mod init;
|
pub mod init;
|
||||||
@ -39,6 +43,8 @@ struct InnerEFIManager {
|
|||||||
pub memory_attribute_table_paddr: Option<PhysAddr>,
|
pub memory_attribute_table_paddr: Option<PhysAddr>,
|
||||||
/// uefi 内存保留表的物理地址
|
/// uefi 内存保留表的物理地址
|
||||||
pub memreserve_table_paddr: Option<PhysAddr>,
|
pub memreserve_table_paddr: Option<PhysAddr>,
|
||||||
|
/// uefi esrt表的物理地址
|
||||||
|
pub esrt_table_paddr: Option<PhysAddr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EFIManager {
|
impl EFIManager {
|
||||||
@ -52,6 +58,7 @@ impl EFIManager {
|
|||||||
dragonstub_load_info: None,
|
dragonstub_load_info: None,
|
||||||
memory_attribute_table_paddr: None,
|
memory_attribute_table_paddr: None,
|
||||||
memreserve_table_paddr: None,
|
memreserve_table_paddr: None,
|
||||||
|
esrt_table_paddr: None,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,6 +104,19 @@ impl EFIManager {
|
|||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn inner_read(&self) -> RwLockReadGuard<InnerEFIManager> {
|
||||||
|
self.inner.read()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inner_write(&self) -> RwLockWriteGuard<InnerEFIManager> {
|
||||||
|
self.inner.write()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 是否存在ESRT表
|
||||||
|
fn esrt_table_exists(&self) -> bool {
|
||||||
|
self.inner_read().esrt_table_paddr.is_some()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在Rust中,我们使用枚举和bitflags来表示这些宏
|
// 在Rust中,我们使用枚举和bitflags来表示这些宏
|
||||||
|
@ -20,7 +20,9 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
guid::{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, EFI_MEMRESERVE_TABLE_GUID},
|
guid::{
|
||||||
|
EFI_MEMORY_ATTRIBUTES_TABLE_GUID, EFI_MEMRESERVE_TABLE_GUID, EFI_SYSTEM_RESOURCE_TABLE_GUID,
|
||||||
|
},
|
||||||
EFIManager,
|
EFIManager,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -29,6 +31,7 @@ static TABLE_PARSERS: &[&TableMatcher] = &[
|
|||||||
&TableMatcher::new(&MatchTableDragonStubPayloadEFI),
|
&TableMatcher::new(&MatchTableDragonStubPayloadEFI),
|
||||||
&TableMatcher::new(&MatchTableMemoryAttributes),
|
&TableMatcher::new(&MatchTableMemoryAttributes),
|
||||||
&TableMatcher::new(&MatchTableMemReserve),
|
&TableMatcher::new(&MatchTableMemReserve),
|
||||||
|
&TableMatcher::new(&MatchTableEsrt),
|
||||||
];
|
];
|
||||||
|
|
||||||
impl EFIManager {
|
impl EFIManager {
|
||||||
@ -99,7 +102,7 @@ impl EFIManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 如果存在mem reserve table
|
// 如果存在mem reserve table
|
||||||
if let Some(mem_reserve) = efi_manager().inner.read().memreserve_table_paddr {
|
if let Some(mem_reserve) = efi_manager().inner_read().memreserve_table_paddr {
|
||||||
let mut prev_paddr = mem_reserve;
|
let mut prev_paddr = mem_reserve;
|
||||||
while !prev_paddr.is_null() {
|
while !prev_paddr.is_null() {
|
||||||
let vaddr = EarlyIoRemap::map_not_aligned(prev_paddr, MMArch::PAGE_SIZE, true)
|
let vaddr = EarlyIoRemap::map_not_aligned(prev_paddr, MMArch::PAGE_SIZE, true)
|
||||||
@ -283,7 +286,7 @@ impl MatchTable for MatchTableDragonStubPayloadEFI {
|
|||||||
let vendor_table_vaddr = vendor_table_vaddr.unwrap();
|
let vendor_table_vaddr = vendor_table_vaddr.unwrap();
|
||||||
let data = unsafe { *(vendor_table_vaddr.data() as *const DragonStubPayloadEFI) };
|
let data = unsafe { *(vendor_table_vaddr.data() as *const DragonStubPayloadEFI) };
|
||||||
|
|
||||||
efi_manager().inner.write().dragonstub_load_info = Some(data);
|
efi_manager().inner_write().dragonstub_load_info = Some(data);
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@ -349,6 +352,33 @@ impl MatchTable for MatchTableMemReserve {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MatchTableEsrt;
|
||||||
|
|
||||||
|
impl MatchTable for MatchTableEsrt {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"ESRT"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn guid(&self) -> &'static uefi_raw::Guid {
|
||||||
|
&EFI_SYSTEM_RESOURCE_TABLE_GUID
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn post_process(
|
||||||
|
&self,
|
||||||
|
_vendor_table_vaddr: Option<VirtAddr>,
|
||||||
|
table_raw: &ConfigurationTable,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
efi_manager().inner.write_irqsave().esrt_table_paddr =
|
||||||
|
Some(PhysAddr::new(table_raw.vendor_table as usize));
|
||||||
|
kdebug!("esrt_table_paddr: {:#x}", table_raw.vendor_table as usize);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 用于匹配配置表的匹配器
|
/// 用于匹配配置表的匹配器
|
||||||
struct TableMatcher {
|
struct TableMatcher {
|
||||||
table: &'static dyn MatchTable,
|
table: &'static dyn MatchTable,
|
||||||
|
@ -162,7 +162,7 @@ pub unsafe fn riscv_intc_init() -> Result<(), SystemError> {
|
|||||||
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-riscv-intc.c#23
|
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-riscv-intc.c#23
|
||||||
pub fn riscv_intc_irq(trap_frame: &mut TrapFrame) {
|
pub fn riscv_intc_irq(trap_frame: &mut TrapFrame) {
|
||||||
let hwirq = HardwareIrqNumber::new(trap_frame.cause.code() as u32);
|
let hwirq = HardwareIrqNumber::new(trap_frame.cause.code() as u32);
|
||||||
kdebug!("riscv64_do_irq: interrupt {hwirq:?}");
|
// kdebug!("riscv64_do_irq: interrupt {hwirq:?}");
|
||||||
GenericIrqHandler::handle_domain_irq(riscv_intc_domain().clone().unwrap(), hwirq, trap_frame)
|
GenericIrqHandler::handle_domain_irq(riscv_intc_domain().clone().unwrap(), hwirq, trap_frame)
|
||||||
.ok();
|
.ok();
|
||||||
if hwirq.data() == RiscVSbiTimer::TIMER_IRQ.data() {
|
if hwirq.data() == RiscVSbiTimer::TIMER_IRQ.data() {
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
all:
|
|
||||||
|
|
||||||
CFLAGS += -I .
|
|
||||||
|
|
||||||
#HPET.o: HPET/HPET.c
|
|
||||||
# $(CC) $(CFLAGS) -c HPET/HPET.c -o HPET/HPET.o
|
|
@ -61,8 +61,9 @@ fn kenrel_init_freeable() -> Result<(), SystemError> {
|
|||||||
|
|
||||||
/// 切换到用户态
|
/// 切换到用户态
|
||||||
fn switch_to_user() {
|
fn switch_to_user() {
|
||||||
let path = String::from("/bin/dragonreach");
|
const INIT_PROGRAM: &str = "/bin/dragonreach";
|
||||||
let argv = vec![String::from("/bin/dragonreach")];
|
let path = String::from(INIT_PROGRAM);
|
||||||
|
let argv = vec![path.clone()];
|
||||||
let envp = vec![String::from("PATH=/")];
|
let envp = vec![String::from("PATH=/")];
|
||||||
|
|
||||||
unsafe { arch_switch_to_user(path, argv, envp) };
|
unsafe { arch_switch_to_user(path, argv, envp) };
|
||||||
|
@ -145,5 +145,6 @@ pub fn panic(info: &PanicInfo) -> ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
println!("Current PCB:\n\t{:?}", (ProcessManager::current_pcb()));
|
println!("Current PCB:\n\t{:?}", (ProcessManager::current_pcb()));
|
||||||
|
|
||||||
ProcessManager::exit(usize::MAX);
|
ProcessManager::exit(usize::MAX);
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ impl ElfLoader {
|
|||||||
) -> Result<(), ExecError> {
|
) -> Result<(), ExecError> {
|
||||||
let start = self.elf_page_start(start);
|
let start = self.elf_page_start(start);
|
||||||
let end = self.elf_page_align_up(end);
|
let end = self.elf_page_align_up(end);
|
||||||
|
// kdebug!("set_elf_brk: start={:?}, end={:?}", start, end);
|
||||||
if end > start {
|
if end > start {
|
||||||
let r = user_vm_guard.map_anonymous(
|
let r = user_vm_guard.map_anonymous(
|
||||||
start,
|
start,
|
||||||
@ -133,6 +133,7 @@ impl ElfLoader {
|
|||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
// kdebug!("set_elf_brk: map_anonymous: r={:?}", r);
|
||||||
if r.is_err() {
|
if r.is_err() {
|
||||||
kerror!("set_elf_brk: map_anonymous failed, err={:?}", r);
|
kerror!("set_elf_brk: map_anonymous failed, err={:?}", r);
|
||||||
return Err(ExecError::OutOfMemory);
|
return Err(ExecError::OutOfMemory);
|
||||||
@ -254,18 +255,14 @@ impl ElfLoader {
|
|||||||
if total_size != 0 {
|
if total_size != 0 {
|
||||||
let total_size = self.elf_page_align_up(VirtAddr::new(total_size)).data();
|
let total_size = self.elf_page_align_up(VirtAddr::new(total_size)).data();
|
||||||
|
|
||||||
// kdebug!("total_size={}", total_size);
|
|
||||||
|
|
||||||
map_addr = user_vm_guard
|
map_addr = user_vm_guard
|
||||||
.map_anonymous(addr_to_map, total_size, tmp_prot, *map_flags, false, true)
|
.map_anonymous(addr_to_map, total_size, tmp_prot, *map_flags, false, true)
|
||||||
.map_err(map_err_handler)?
|
.map_err(map_err_handler)?
|
||||||
.virt_address();
|
.virt_address();
|
||||||
// kdebug!("map ok: addr_to_map={:?}", addr_to_map);
|
|
||||||
|
|
||||||
let to_unmap = map_addr + map_size;
|
let to_unmap = map_addr + map_size;
|
||||||
let to_unmap_size = total_size - map_size;
|
let to_unmap_size = total_size - map_size;
|
||||||
|
|
||||||
// kdebug!("to_unmap={:?}, to_unmap_size={}", to_unmap, to_unmap_size);
|
|
||||||
user_vm_guard.munmap(
|
user_vm_guard.munmap(
|
||||||
VirtPageFrame::new(to_unmap),
|
VirtPageFrame::new(to_unmap),
|
||||||
PageFrameCount::from_bytes(to_unmap_size).unwrap(),
|
PageFrameCount::from_bytes(to_unmap_size).unwrap(),
|
||||||
@ -554,6 +551,7 @@ impl BinaryLoader for ElfLoader {
|
|||||||
if seg.p_type != PT_INTERP {
|
if seg.p_type != PT_INTERP {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 接下来处理这个 .interpreter 段以及动态链接器
|
// 接下来处理这个 .interpreter 段以及动态链接器
|
||||||
// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#881
|
// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#881
|
||||||
|
|
||||||
@ -582,8 +580,6 @@ impl BinaryLoader for ElfLoader {
|
|||||||
}
|
}
|
||||||
Self::parse_gnu_property()?;
|
Self::parse_gnu_property()?;
|
||||||
|
|
||||||
// kdebug!("loadable_sections = {:?}", loadable_sections);
|
|
||||||
|
|
||||||
let mut elf_brk = VirtAddr::new(0);
|
let mut elf_brk = VirtAddr::new(0);
|
||||||
let mut elf_bss = VirtAddr::new(0);
|
let mut elf_bss = VirtAddr::new(0);
|
||||||
let mut start_code: Option<VirtAddr> = None;
|
let mut start_code: Option<VirtAddr> = None;
|
||||||
@ -606,6 +602,7 @@ impl BinaryLoader for ElfLoader {
|
|||||||
let loadable_sections = phdr_table
|
let loadable_sections = phdr_table
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|seg| seg.p_type == elf::abi::PT_LOAD);
|
.filter(|seg| seg.p_type == elf::abi::PT_LOAD);
|
||||||
|
|
||||||
for seg_to_load in loadable_sections {
|
for seg_to_load in loadable_sections {
|
||||||
min_address = min(
|
min_address = min(
|
||||||
min_address,
|
min_address,
|
||||||
@ -695,7 +692,7 @@ impl BinaryLoader for ElfLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 加载这个段到用户空间
|
// 加载这个段到用户空间
|
||||||
|
// kdebug!("to load elf segment");
|
||||||
let e = self
|
let e = self
|
||||||
.load_elf_segment(
|
.load_elf_segment(
|
||||||
&mut user_vm,
|
&mut user_vm,
|
||||||
@ -706,10 +703,13 @@ impl BinaryLoader for ElfLoader {
|
|||||||
&elf_map_flags,
|
&elf_map_flags,
|
||||||
total_size,
|
total_size,
|
||||||
)
|
)
|
||||||
.map_err(|e| match e {
|
.map_err(|e| {
|
||||||
SystemError::EFAULT => ExecError::BadAddress(None),
|
kerror!("load_elf_segment failed: {:?}", e);
|
||||||
SystemError::ENOMEM => ExecError::OutOfMemory,
|
match e {
|
||||||
_ => ExecError::Other(format!("load_elf_segment failed: {:?}", e)),
|
SystemError::EFAULT => ExecError::BadAddress(None),
|
||||||
|
SystemError::ENOMEM => ExecError::OutOfMemory,
|
||||||
|
_ => ExecError::Other(format!("load_elf_segment failed: {:?}", e)),
|
||||||
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// 如果地址不对,那么就报错
|
// 如果地址不对,那么就报错
|
||||||
|
@ -21,7 +21,7 @@ pub struct PhysPageFrame {
|
|||||||
impl PhysPageFrame {
|
impl PhysPageFrame {
|
||||||
pub fn new(paddr: PhysAddr) -> Self {
|
pub fn new(paddr: PhysAddr) -> Self {
|
||||||
return Self {
|
return Self {
|
||||||
number: paddr.data() / MMArch::PAGE_SIZE,
|
number: paddr.data() >> MMArch::PAGE_SHIFT,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,6 @@ impl KernelMapper {
|
|||||||
|
|
||||||
let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE);
|
let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE);
|
||||||
// kdebug!("kernel mapper: map_phys: vaddr: {vaddr:?}, paddr: {paddr:?}, count: {count:?}, flags: {flags:?}");
|
// kdebug!("kernel mapper: map_phys: vaddr: {vaddr:?}, paddr: {paddr:?}, count: {count:?}, flags: {flags:?}");
|
||||||
|
|
||||||
for _ in 0..count.data() {
|
for _ in 0..count.data() {
|
||||||
let flusher = self.mapper.map_phys(vaddr, paddr, flags).unwrap();
|
let flusher = self.mapper.map_phys(vaddr, paddr, flags).unwrap();
|
||||||
|
|
||||||
|
@ -352,6 +352,11 @@ impl MemBlockManager {
|
|||||||
return self.set_or_clear_flags(base, size, true, MemoryAreaAttr::NOMAP);
|
return self.set_or_clear_flags(base, size, true, MemoryAreaAttr::NOMAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/mm/memblock.c?fi=memblock_mark_mirror#940
|
||||||
|
pub fn mark_mirror(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> {
|
||||||
|
return self.set_or_clear_flags(base, size, true, MemoryAreaAttr::MIRROR);
|
||||||
|
}
|
||||||
|
|
||||||
fn set_or_clear_flags(
|
fn set_or_clear_flags(
|
||||||
&self,
|
&self,
|
||||||
mut base: PhysAddr,
|
mut base: PhysAddr,
|
||||||
|
@ -447,6 +447,8 @@ pub trait MemoryManagementArch: Clone + Copy + Debug {
|
|||||||
const ENTRY_FLAG_PRESENT: usize;
|
const ENTRY_FLAG_PRESENT: usize;
|
||||||
/// 页表项为read only时的值
|
/// 页表项为read only时的值
|
||||||
const ENTRY_FLAG_READONLY: usize;
|
const ENTRY_FLAG_READONLY: usize;
|
||||||
|
/// 页表项的write bit
|
||||||
|
const ENTRY_FLAG_WRITEABLE: usize;
|
||||||
/// 页表项为可读写状态的值
|
/// 页表项为可读写状态的值
|
||||||
const ENTRY_FLAG_READWRITE: usize;
|
const ENTRY_FLAG_READWRITE: usize;
|
||||||
/// 页面项标记页面为user page的值
|
/// 页面项标记页面为user page的值
|
||||||
|
@ -530,9 +530,18 @@ impl<Arch: MemoryManagementArch> PageFlags<Arch> {
|
|||||||
Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE)
|
Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if user {
|
|
||||||
r.set_user(true)
|
#[cfg(target_arch = "x86_64")]
|
||||||
} else {
|
{
|
||||||
|
if user {
|
||||||
|
r.set_user(true)
|
||||||
|
} else {
|
||||||
|
r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "riscv64")]
|
||||||
|
{
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -607,7 +616,9 @@ impl<Arch: MemoryManagementArch> PageFlags<Arch> {
|
|||||||
if value {
|
if value {
|
||||||
return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true);
|
return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true);
|
||||||
} else {
|
} else {
|
||||||
return self.update_flags(Arch::ENTRY_FLAG_READONLY, true);
|
return self
|
||||||
|
.update_flags(Arch::ENTRY_FLAG_READONLY, true)
|
||||||
|
.update_flags(Arch::ENTRY_FLAG_WRITEABLE, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -724,13 +735,25 @@ impl<Arch: MemoryManagementArch> PageFlags<Arch> {
|
|||||||
/// MMIO内存的页表项标志
|
/// MMIO内存的页表项标志
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn mmio_flags() -> Self {
|
pub fn mmio_flags() -> Self {
|
||||||
return Self::new()
|
#[cfg(target_arch = "x86_64")]
|
||||||
.set_user(false)
|
{
|
||||||
.set_write(true)
|
Self::new()
|
||||||
.set_execute(true)
|
.set_user(false)
|
||||||
.set_page_cache_disable(true)
|
.set_write(true)
|
||||||
.set_page_write_through(true)
|
.set_execute(true)
|
||||||
.set_page_global(true);
|
.set_page_cache_disable(true)
|
||||||
|
.set_page_write_through(true)
|
||||||
|
.set_page_global(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "riscv64")]
|
||||||
|
{
|
||||||
|
Self::new()
|
||||||
|
.set_user(false)
|
||||||
|
.set_write(true)
|
||||||
|
.set_execute(true)
|
||||||
|
.set_page_global(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -873,6 +896,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
|||||||
let mut table = self.table();
|
let mut table = self.table();
|
||||||
loop {
|
loop {
|
||||||
let i = table.index_of(virt)?;
|
let i = table.index_of(virt)?;
|
||||||
|
|
||||||
assert!(i < Arch::PAGE_ENTRY_NUM);
|
assert!(i < Arch::PAGE_ENTRY_NUM);
|
||||||
if table.level() == 0 {
|
if table.level() == 0 {
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
@ -891,13 +915,10 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
|||||||
|
|
||||||
// 清空这个页帧
|
// 清空这个页帧
|
||||||
MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
|
MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
|
||||||
|
|
||||||
// 设置页表项的flags
|
// 设置页表项的flags
|
||||||
let flags: PageFlags<Arch> =
|
let flags: PageFlags<Arch> =
|
||||||
PageFlags::new_page_table(virt.kind() == PageTableKind::User);
|
PageFlags::new_page_table(virt.kind() == PageTableKind::User);
|
||||||
|
|
||||||
// kdebug!("Flags: {:?}", flags);
|
|
||||||
|
|
||||||
// 把新分配的页表映射到当前页表
|
// 把新分配的页表映射到当前页表
|
||||||
table.set_entry(i, PageEntry::new(frame, flags));
|
table.set_entry(i, PageEntry::new(frame, flags));
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ pub fn load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, Sys
|
|||||||
.load(param, &head_buf)
|
.load(param, &head_buf)
|
||||||
.unwrap_or_else(|e| panic!("load_binary_file failed: error: {e:?}, param: {param:?}"));
|
.unwrap_or_else(|e| panic!("load_binary_file failed: error: {e:?}, param: {param:?}"));
|
||||||
|
|
||||||
// kdebug!("load_binary_file: load success");
|
// kdebug!("load_binary_file: load success: {result:?}");
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user