mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 14:16:47 +00:00
parent
7d580ef99d
commit
9b96c5b547
@ -62,7 +62,7 @@ x86_64 = "=0.14.10"
|
||||
|
||||
# target为riscv64时,使用下面的依赖
|
||||
[target.'cfg(target_arch = "riscv64")'.dependencies]
|
||||
riscv = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/riscv.git", revision = "79d27d0f3a", features = [ "s-mode" ] }
|
||||
riscv = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/riscv.git", revision = "01fc40d", features = [ "s-mode" ] }
|
||||
sbi-rt = { version = "=0.0.3", features = ["legacy"] }
|
||||
|
||||
|
||||
|
@ -53,7 +53,7 @@ pub(super) fn local_context() -> &'static PerCpuVar<LocalContext> {
|
||||
///
|
||||
/// - 从用户态进入内核态时,会从sscratch寄存器加载这个结构体的地址到tp寄存器,并把sscratch寄存器清零
|
||||
/// - 从内核态进入用户态时,会将tp寄存器的值保存到sscratch寄存器
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub(super) struct LocalContext {
|
||||
/// 当前cpu的id
|
||||
pub current_cpu: ProcessorId,
|
||||
@ -64,7 +64,7 @@ pub(super) struct LocalContext {
|
||||
}
|
||||
|
||||
impl LocalContext {
|
||||
fn new(cpu: ProcessorId) -> Self {
|
||||
pub fn new(cpu: ProcessorId) -> Self {
|
||||
Self {
|
||||
current_cpu: cpu,
|
||||
kernel_sp: 0,
|
||||
@ -102,6 +102,13 @@ impl LocalContext {
|
||||
// 写入tp寄存器
|
||||
riscv::register::tp::write(ptr);
|
||||
}
|
||||
|
||||
pub fn restore(&mut self, from: &LocalContext) {
|
||||
// 不恢复cpu id
|
||||
|
||||
self.kernel_sp = from.kernel_sp;
|
||||
self.user_sp = from.user_sp;
|
||||
}
|
||||
}
|
||||
|
||||
/// 初始化本地上下文
|
||||
|
@ -61,44 +61,44 @@ impl InterruptArch for RiscV64InterruptArch {
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct TrapFrame {
|
||||
epc: usize,
|
||||
ra: usize,
|
||||
sp: usize,
|
||||
gp: usize,
|
||||
tp: usize,
|
||||
t0: usize,
|
||||
t1: usize,
|
||||
t2: usize,
|
||||
s0: usize,
|
||||
s1: usize,
|
||||
a0: usize,
|
||||
a1: usize,
|
||||
a2: usize,
|
||||
a3: usize,
|
||||
a4: usize,
|
||||
a5: usize,
|
||||
a6: usize,
|
||||
a7: usize,
|
||||
s2: usize,
|
||||
s3: usize,
|
||||
s4: usize,
|
||||
s5: usize,
|
||||
s6: usize,
|
||||
s7: usize,
|
||||
s8: usize,
|
||||
s9: usize,
|
||||
s10: usize,
|
||||
s11: usize,
|
||||
t3: usize,
|
||||
t4: usize,
|
||||
t5: usize,
|
||||
t6: usize,
|
||||
pub epc: usize,
|
||||
pub ra: usize,
|
||||
pub sp: usize,
|
||||
pub gp: usize,
|
||||
pub tp: usize,
|
||||
pub t0: usize,
|
||||
pub t1: usize,
|
||||
pub t2: usize,
|
||||
pub s0: usize,
|
||||
pub s1: usize,
|
||||
pub a0: usize,
|
||||
pub a1: usize,
|
||||
pub a2: usize,
|
||||
pub a3: usize,
|
||||
pub a4: usize,
|
||||
pub a5: usize,
|
||||
pub a6: usize,
|
||||
pub a7: usize,
|
||||
pub s2: usize,
|
||||
pub s3: usize,
|
||||
pub s4: usize,
|
||||
pub s5: usize,
|
||||
pub s6: usize,
|
||||
pub s7: usize,
|
||||
pub s8: usize,
|
||||
pub s9: usize,
|
||||
pub s10: usize,
|
||||
pub s11: usize,
|
||||
pub t3: usize,
|
||||
pub t4: usize,
|
||||
pub t5: usize,
|
||||
pub t6: usize,
|
||||
// 以下是中断发生时自动保存的寄存器
|
||||
status: Sstatus,
|
||||
badaddr: usize,
|
||||
cause: Scause,
|
||||
pub status: Sstatus,
|
||||
pub badaddr: usize,
|
||||
pub cause: Scause,
|
||||
/// a0 value before the syscall
|
||||
origin_a0: usize,
|
||||
pub origin_a0: usize,
|
||||
}
|
||||
|
||||
impl TrapFrame {
|
||||
|
@ -1,19 +1,34 @@
|
||||
use core::{arch::asm, mem::ManuallyDrop};
|
||||
|
||||
use alloc::{
|
||||
string::String,
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use core::{
|
||||
arch::asm,
|
||||
intrinsics::unlikely,
|
||||
mem::ManuallyDrop,
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
};
|
||||
use kdepends::memoffset::offset_of;
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
arch::CurrentIrqArch,
|
||||
exception::InterruptArch,
|
||||
kerror,
|
||||
libs::spinlock::SpinLockGuard,
|
||||
mm::VirtAddr,
|
||||
process::{fork::KernelCloneArgs, KernelStack, ProcessControlBlock, ProcessManager},
|
||||
process::{
|
||||
fork::KernelCloneArgs, KernelStack, ProcessControlBlock, ProcessManager,
|
||||
PROCESS_SWITCH_RESULT,
|
||||
},
|
||||
smp::cpu::ProcessorId,
|
||||
};
|
||||
|
||||
use super::interrupt::TrapFrame;
|
||||
use super::{
|
||||
cpu::{local_context, LocalContext},
|
||||
interrupt::TrapFrame,
|
||||
};
|
||||
|
||||
pub mod idle;
|
||||
pub mod kthread;
|
||||
@ -59,10 +74,123 @@ impl ProcessManager {
|
||||
///
|
||||
/// - `prev`:上一个进程的pcb
|
||||
/// - `next`:下一个进程的pcb
|
||||
///
|
||||
/// 参考: 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>) {
|
||||
// todo: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/include/asm/switch_to.h#76
|
||||
unimplemented!("ProcessManager::switch_process")
|
||||
assert!(!CurrentIrqArch::is_irq_enabled());
|
||||
Self::switch_process_fpu(&prev, &next);
|
||||
Self::switch_local_context(&prev, &next);
|
||||
|
||||
// 切换地址空间
|
||||
let next_addr_space = next.basic().user_vm().as_ref().unwrap().clone();
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
next_addr_space.read().user_mapper.utable.make_current();
|
||||
drop(next_addr_space);
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
// 获取arch info的锁,并强制泄露其守卫(切换上下文后,在switch_finish_hook中会释放锁)
|
||||
let next_arch = SpinLockGuard::leak(next.arch_info_irqsave()) as *mut ArchPCBInfo;
|
||||
let prev_arch = SpinLockGuard::leak(prev.arch_info_irqsave()) as *mut ArchPCBInfo;
|
||||
|
||||
// 恢复当前的 preempt count*2
|
||||
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().next_pcb = Some(next);
|
||||
// kdebug!("switch tss ok");
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
// 正式切换上下文
|
||||
switch_to_inner(prev_arch, next_arch);
|
||||
}
|
||||
|
||||
fn switch_process_fpu(prev: &Arc<ProcessControlBlock>, next: &Arc<ProcessControlBlock>) {
|
||||
let prev_regs = unsafe { Self::task_trapframe(prev) };
|
||||
let next_regs = unsafe { Self::task_trapframe(next) };
|
||||
if unlikely(prev_regs.status.sd()) {
|
||||
prev.arch_info_irqsave().fp_state.save(prev_regs);
|
||||
}
|
||||
next.arch_info_irqsave().fp_state.restore(next_regs);
|
||||
}
|
||||
|
||||
fn switch_local_context(prev: &Arc<ProcessControlBlock>, next: &Arc<ProcessControlBlock>) {
|
||||
prev.arch_info_irqsave().local_context = *local_context().get();
|
||||
local_context()
|
||||
.get_mut()
|
||||
.restore(&next.arch_info_irqsave().local_context);
|
||||
}
|
||||
|
||||
unsafe fn task_trapframe(task: &Arc<ProcessControlBlock>) -> &mut TrapFrame {
|
||||
let mut sp = task.kernel_stack().stack_max_address().data();
|
||||
sp -= core::mem::size_of::<TrapFrame>();
|
||||
return (sp as *mut TrapFrame).as_mut().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// 切换上下文
|
||||
///
|
||||
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/kernel/entry.S#233
|
||||
#[naked]
|
||||
unsafe extern "C" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBInfo) {
|
||||
core::arch::asm!(concat!(
|
||||
"
|
||||
sd ra, {off_ra}(a0)
|
||||
sd sp, {off_sp}(a0)
|
||||
sd s0, {off_s0}(a0)
|
||||
sd s1, {off_s1}(a0)
|
||||
sd s2, {off_s2}(a0)
|
||||
sd s3, {off_s3}(a0)
|
||||
sd s4, {off_s4}(a0)
|
||||
sd s5, {off_s5}(a0)
|
||||
sd s6, {off_s6}(a0)
|
||||
sd s7, {off_s7}(a0)
|
||||
sd s8, {off_s8}(a0)
|
||||
sd s9, {off_s9}(a0)
|
||||
sd s10, {off_s10}(a0)
|
||||
sd s11, {off_s11}(a0)
|
||||
|
||||
|
||||
ld sp, {off_sp}(a1)
|
||||
ld s0, {off_s0}(a1)
|
||||
ld s1, {off_s1}(a1)
|
||||
ld s2, {off_s2}(a1)
|
||||
ld s3, {off_s3}(a1)
|
||||
ld s4, {off_s4}(a1)
|
||||
ld s5, {off_s5}(a1)
|
||||
ld s6, {off_s6}(a1)
|
||||
ld s7, {off_s7}(a1)
|
||||
ld s8, {off_s8}(a1)
|
||||
ld s9, {off_s9}(a1)
|
||||
ld s10, {off_s10}(a1)
|
||||
ld s11, {off_s11}(a1)
|
||||
|
||||
// 将ra设置为标签1,并跳转到{switch_finish_hook}
|
||||
la ra, 1f
|
||||
j {switch_finish_hook}
|
||||
|
||||
1:
|
||||
ld sp, {off_sp}(a1)
|
||||
ld ra, {off_ra}(a1)
|
||||
ret
|
||||
|
||||
"
|
||||
),
|
||||
off_ra = const(offset_of!(ArchPCBInfo, ra)),
|
||||
off_sp = const(offset_of!(ArchPCBInfo, ksp)),
|
||||
off_s0 = const(offset_of!(ArchPCBInfo, s0)),
|
||||
off_s1 = const(offset_of!(ArchPCBInfo, s1)),
|
||||
off_s2 = const(offset_of!(ArchPCBInfo, s2)),
|
||||
off_s3 = const(offset_of!(ArchPCBInfo, s3)),
|
||||
off_s4 = const(offset_of!(ArchPCBInfo, s4)),
|
||||
off_s5 = const(offset_of!(ArchPCBInfo, s5)),
|
||||
off_s6 = const(offset_of!(ArchPCBInfo, s6)),
|
||||
off_s7 = const(offset_of!(ArchPCBInfo, s7)),
|
||||
off_s8 = const(offset_of!(ArchPCBInfo, s8)),
|
||||
off_s9 = const(offset_of!(ArchPCBInfo, s9)),
|
||||
off_s10 = const(offset_of!(ArchPCBInfo, s10)),
|
||||
off_s11 = const(offset_of!(ArchPCBInfo, s11)),
|
||||
switch_finish_hook = sym crate::process::switch_finish_hook,
|
||||
options(noreturn));
|
||||
}
|
||||
|
||||
impl ProcessControlBlock {
|
||||
@ -95,8 +223,25 @@ impl ProcessControlBlock {
|
||||
/// PCB中与架构相关的信息
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
#[repr(C)]
|
||||
pub struct ArchPCBInfo {
|
||||
// todo: add arch related fields
|
||||
ra: usize,
|
||||
ksp: usize,
|
||||
s0: usize,
|
||||
s1: usize,
|
||||
s2: usize,
|
||||
s3: usize,
|
||||
s4: usize,
|
||||
s5: usize,
|
||||
s6: usize,
|
||||
s7: usize,
|
||||
s8: usize,
|
||||
s9: usize,
|
||||
s10: usize,
|
||||
s11: usize,
|
||||
|
||||
fp_state: FpDExtState,
|
||||
local_context: LocalContext,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -111,10 +256,225 @@ impl ArchPCBInfo {
|
||||
///
|
||||
/// 返回一个新的ArchPCBInfo
|
||||
pub fn new(kstack: &KernelStack) -> Self {
|
||||
Self {}
|
||||
Self {
|
||||
ra: 0,
|
||||
ksp: kstack.stack_max_address().data(),
|
||||
s0: 0,
|
||||
s1: 0,
|
||||
s2: 0,
|
||||
s3: 0,
|
||||
s4: 0,
|
||||
s5: 0,
|
||||
s6: 0,
|
||||
s7: 0,
|
||||
s8: 0,
|
||||
s9: 0,
|
||||
s10: 0,
|
||||
s11: 0,
|
||||
fp_state: FpDExtState::new(),
|
||||
local_context: LocalContext::new(ProcessorId::new(0)),
|
||||
}
|
||||
}
|
||||
// ### 从另一个ArchPCBInfo处clone,但是保留部分字段不变
|
||||
pub fn clone_from(&mut self, from: &Self) {
|
||||
unimplemented!("ArchPCBInfo::clone_from")
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
struct FpDExtState {
|
||||
f: [u64; 32],
|
||||
fcsr: u32,
|
||||
}
|
||||
|
||||
impl FpDExtState {
|
||||
/// 创建一个新的FpState
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
f: [0; 32],
|
||||
fcsr: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn save(&mut self, regs: &mut TrapFrame) {
|
||||
if regs.status.fs() == riscv::register::sstatus::FS::Dirty {
|
||||
self.do_save();
|
||||
self.do_clean(regs);
|
||||
}
|
||||
}
|
||||
|
||||
fn restore(&mut self, regs: &mut TrapFrame) {
|
||||
if regs.status.fs() != riscv::register::sstatus::FS::Off {
|
||||
self.do_restore();
|
||||
self.do_clean(regs);
|
||||
}
|
||||
}
|
||||
|
||||
fn do_clean(&mut self, regs: &mut TrapFrame) {
|
||||
regs.status.update_fs(riscv::register::sstatus::FS::Clean);
|
||||
}
|
||||
|
||||
fn do_save(&mut self) {
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
unsafe {
|
||||
riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Initial);
|
||||
asm!("frcsr {0}", lateout(reg) self.fcsr);
|
||||
asm!(concat!(
|
||||
"
|
||||
fsd f0, {0}
|
||||
fsd f1, {1}
|
||||
fsd f2, {2}
|
||||
fsd f3, {3}
|
||||
fsd f4, {4}
|
||||
fsd f5, {5}
|
||||
fsd f6, {6}
|
||||
fsd f7, {7}
|
||||
fsd f8, {8}
|
||||
fsd f9, {9}
|
||||
fsd f10, {10}
|
||||
fsd f11, {11}
|
||||
fsd f12, {12}
|
||||
fsd f13, {13}
|
||||
fsd f14, {14}
|
||||
fsd f15, {15}
|
||||
fsd f16, {16}
|
||||
fsd f17, {17}
|
||||
fsd f18, {18}
|
||||
fsd f19, {19}
|
||||
fsd f20, {20}
|
||||
fsd f21, {21}
|
||||
fsd f22, {22}
|
||||
fsd f23, {23}
|
||||
fsd f24, {24}
|
||||
fsd f25, {25}
|
||||
fsd f26, {26}
|
||||
fsd f27, {27}
|
||||
fsd f28, {28}
|
||||
fsd f29, {29}
|
||||
fsd f30, {30}
|
||||
fsd f31, {31}
|
||||
"
|
||||
),
|
||||
lateout(reg) self.f[0],
|
||||
lateout(reg) self.f[1],
|
||||
lateout(reg) self.f[2],
|
||||
lateout(reg) self.f[3],
|
||||
lateout(reg) self.f[4],
|
||||
lateout(reg) self.f[5],
|
||||
lateout(reg) self.f[6],
|
||||
lateout(reg) self.f[7],
|
||||
lateout(reg) self.f[8],
|
||||
lateout(reg) self.f[9],
|
||||
lateout(reg) self.f[10],
|
||||
lateout(reg) self.f[11],
|
||||
lateout(reg) self.f[12],
|
||||
lateout(reg) self.f[13],
|
||||
lateout(reg) self.f[14],
|
||||
lateout(reg) self.f[15],
|
||||
lateout(reg) self.f[16],
|
||||
lateout(reg) self.f[17],
|
||||
lateout(reg) self.f[18],
|
||||
lateout(reg) self.f[19],
|
||||
lateout(reg) self.f[20],
|
||||
lateout(reg) self.f[21],
|
||||
lateout(reg) self.f[22],
|
||||
lateout(reg) self.f[23],
|
||||
lateout(reg) self.f[24],
|
||||
lateout(reg) self.f[25],
|
||||
lateout(reg) self.f[26],
|
||||
lateout(reg) self.f[27],
|
||||
lateout(reg) self.f[28],
|
||||
lateout(reg) self.f[29],
|
||||
lateout(reg) self.f[30],
|
||||
lateout(reg) self.f[31],
|
||||
|
||||
);
|
||||
riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off);
|
||||
}
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
}
|
||||
|
||||
fn do_restore(&mut self) {
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
let fcsr = self.fcsr;
|
||||
unsafe {
|
||||
riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Initial);
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
asm!(concat!(
|
||||
"
|
||||
fld f0, {0}
|
||||
fld f1, {1}
|
||||
fld f2, {2}
|
||||
fld f3, {3}
|
||||
fld f4, {4}
|
||||
fld f5, {5}
|
||||
fld f6, {6}
|
||||
fld f7, {7}
|
||||
fld f8, {8}
|
||||
fld f9, {9}
|
||||
fld f10, {10}
|
||||
fld f11, {11}
|
||||
fld f12, {12}
|
||||
fld f13, {13}
|
||||
fld f14, {14}
|
||||
fld f15, {15}
|
||||
fld f16, {16}
|
||||
fld f17, {17}
|
||||
fld f18, {18}
|
||||
fld f19, {19}
|
||||
fld f20, {20}
|
||||
fld f21, {21}
|
||||
fld f22, {22}
|
||||
fld f23, {23}
|
||||
fld f24, {24}
|
||||
fld f25, {25}
|
||||
fld f26, {26}
|
||||
fld f27, {27}
|
||||
fld f28, {28}
|
||||
fld f29, {29}
|
||||
fld f30, {30}
|
||||
fld f31, {31}
|
||||
"
|
||||
),
|
||||
in(reg) self.f[0],
|
||||
in(reg) self.f[1],
|
||||
in(reg) self.f[2],
|
||||
in(reg) self.f[3],
|
||||
in(reg) self.f[4],
|
||||
in(reg) self.f[5],
|
||||
in(reg) self.f[6],
|
||||
in(reg) self.f[7],
|
||||
in(reg) self.f[8],
|
||||
in(reg) self.f[9],
|
||||
in(reg) self.f[10],
|
||||
in(reg) self.f[11],
|
||||
in(reg) self.f[12],
|
||||
in(reg) self.f[13],
|
||||
in(reg) self.f[14],
|
||||
in(reg) self.f[15],
|
||||
in(reg) self.f[16],
|
||||
in(reg) self.f[17],
|
||||
in(reg) self.f[18],
|
||||
in(reg) self.f[19],
|
||||
in(reg) self.f[20],
|
||||
in(reg) self.f[21],
|
||||
in(reg) self.f[22],
|
||||
in(reg) self.f[23],
|
||||
in(reg) self.f[24],
|
||||
in(reg) self.f[25],
|
||||
in(reg) self.f[26],
|
||||
in(reg) self.f[27],
|
||||
in(reg) self.f[28],
|
||||
in(reg) self.f[29],
|
||||
in(reg) self.f[30],
|
||||
in(reg) self.f[31],
|
||||
);
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
asm!("fscsr {0}", in(reg) fcsr);
|
||||
riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off);
|
||||
}
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
@ -344,6 +344,7 @@ impl Syscall {
|
||||
Self::rmdir(path)
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
SYS_LINK => {
|
||||
let old = args[0] as *const u8;
|
||||
let new = args[1] as *const u8;
|
||||
|
Loading…
x
Reference in New Issue
Block a user