mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
parent
7d580ef99d
commit
9b96c5b547
@ -62,7 +62,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 = "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"] }
|
sbi-rt = { version = "=0.0.3", features = ["legacy"] }
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ pub(super) fn local_context() -> &'static PerCpuVar<LocalContext> {
|
|||||||
///
|
///
|
||||||
/// - 从用户态进入内核态时,会从sscratch寄存器加载这个结构体的地址到tp寄存器,并把sscratch寄存器清零
|
/// - 从用户态进入内核态时,会从sscratch寄存器加载这个结构体的地址到tp寄存器,并把sscratch寄存器清零
|
||||||
/// - 从内核态进入用户态时,会将tp寄存器的值保存到sscratch寄存器
|
/// - 从内核态进入用户态时,会将tp寄存器的值保存到sscratch寄存器
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub(super) struct LocalContext {
|
pub(super) struct LocalContext {
|
||||||
/// 当前cpu的id
|
/// 当前cpu的id
|
||||||
pub current_cpu: ProcessorId,
|
pub current_cpu: ProcessorId,
|
||||||
@ -64,7 +64,7 @@ pub(super) struct LocalContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LocalContext {
|
impl LocalContext {
|
||||||
fn new(cpu: ProcessorId) -> Self {
|
pub fn new(cpu: ProcessorId) -> Self {
|
||||||
Self {
|
Self {
|
||||||
current_cpu: cpu,
|
current_cpu: cpu,
|
||||||
kernel_sp: 0,
|
kernel_sp: 0,
|
||||||
@ -102,6 +102,13 @@ impl LocalContext {
|
|||||||
// 写入tp寄存器
|
// 写入tp寄存器
|
||||||
riscv::register::tp::write(ptr);
|
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)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct TrapFrame {
|
pub struct TrapFrame {
|
||||||
epc: usize,
|
pub epc: usize,
|
||||||
ra: usize,
|
pub ra: usize,
|
||||||
sp: usize,
|
pub sp: usize,
|
||||||
gp: usize,
|
pub gp: usize,
|
||||||
tp: usize,
|
pub tp: usize,
|
||||||
t0: usize,
|
pub t0: usize,
|
||||||
t1: usize,
|
pub t1: usize,
|
||||||
t2: usize,
|
pub t2: usize,
|
||||||
s0: usize,
|
pub s0: usize,
|
||||||
s1: usize,
|
pub s1: usize,
|
||||||
a0: usize,
|
pub a0: usize,
|
||||||
a1: usize,
|
pub a1: usize,
|
||||||
a2: usize,
|
pub a2: usize,
|
||||||
a3: usize,
|
pub a3: usize,
|
||||||
a4: usize,
|
pub a4: usize,
|
||||||
a5: usize,
|
pub a5: usize,
|
||||||
a6: usize,
|
pub a6: usize,
|
||||||
a7: usize,
|
pub a7: usize,
|
||||||
s2: usize,
|
pub s2: usize,
|
||||||
s3: usize,
|
pub s3: usize,
|
||||||
s4: usize,
|
pub s4: usize,
|
||||||
s5: usize,
|
pub s5: usize,
|
||||||
s6: usize,
|
pub s6: usize,
|
||||||
s7: usize,
|
pub s7: usize,
|
||||||
s8: usize,
|
pub s8: usize,
|
||||||
s9: usize,
|
pub s9: usize,
|
||||||
s10: usize,
|
pub s10: usize,
|
||||||
s11: usize,
|
pub s11: usize,
|
||||||
t3: usize,
|
pub t3: usize,
|
||||||
t4: usize,
|
pub t4: usize,
|
||||||
t5: usize,
|
pub t5: usize,
|
||||||
t6: usize,
|
pub t6: usize,
|
||||||
// 以下是中断发生时自动保存的寄存器
|
// 以下是中断发生时自动保存的寄存器
|
||||||
status: Sstatus,
|
pub status: Sstatus,
|
||||||
badaddr: usize,
|
pub badaddr: usize,
|
||||||
cause: Scause,
|
pub cause: Scause,
|
||||||
/// a0 value before the syscall
|
/// a0 value before the syscall
|
||||||
origin_a0: usize,
|
pub origin_a0: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TrapFrame {
|
impl TrapFrame {
|
||||||
|
@ -1,19 +1,34 @@
|
|||||||
use core::{arch::asm, mem::ManuallyDrop};
|
|
||||||
|
|
||||||
use alloc::{
|
use alloc::{
|
||||||
string::String,
|
string::String,
|
||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
vec::Vec,
|
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 system_error::SystemError;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
arch::CurrentIrqArch,
|
||||||
|
exception::InterruptArch,
|
||||||
kerror,
|
kerror,
|
||||||
|
libs::spinlock::SpinLockGuard,
|
||||||
mm::VirtAddr,
|
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 idle;
|
||||||
pub mod kthread;
|
pub mod kthread;
|
||||||
@ -59,10 +74,123 @@ impl ProcessManager {
|
|||||||
///
|
///
|
||||||
/// - `prev`:上一个进程的pcb
|
/// - `prev`:上一个进程的pcb
|
||||||
/// - `next`:下一个进程的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>) {
|
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
|
assert!(!CurrentIrqArch::is_irq_enabled());
|
||||||
unimplemented!("ProcessManager::switch_process")
|
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 {
|
impl ProcessControlBlock {
|
||||||
@ -95,8 +223,25 @@ impl ProcessControlBlock {
|
|||||||
/// PCB中与架构相关的信息
|
/// PCB中与架构相关的信息
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
#[repr(C)]
|
||||||
pub struct ArchPCBInfo {
|
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)]
|
#[allow(dead_code)]
|
||||||
@ -111,10 +256,225 @@ impl ArchPCBInfo {
|
|||||||
///
|
///
|
||||||
/// 返回一个新的ArchPCBInfo
|
/// 返回一个新的ArchPCBInfo
|
||||||
pub fn new(kstack: &KernelStack) -> Self {
|
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,但是保留部分字段不变
|
// ### 从另一个ArchPCBInfo处clone,但是保留部分字段不变
|
||||||
pub fn clone_from(&mut self, from: &Self) {
|
pub fn clone_from(&mut self, from: &Self) {
|
||||||
unimplemented!("ArchPCBInfo::clone_from")
|
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)
|
Self::rmdir(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
SYS_LINK => {
|
SYS_LINK => {
|
||||||
let old = args[0] as *const u8;
|
let old = args[0] as *const u8;
|
||||||
let new = args[1] as *const u8;
|
let new = args[1] as *const u8;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user