mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-10 13:56:48 +00:00
Adjust RISC-V's implementation for recent changes
This commit is contained in:
parent
b097060c5e
commit
14b8c48859
@ -1,7 +1,9 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use alloc::{format, string::String};
|
||||||
|
|
||||||
use ostd::{
|
use ostd::{
|
||||||
cpu::{CpuExceptionInfo, RawGeneralRegs, UserContext},
|
cpu::context::{CpuExceptionInfo, RawGeneralRegs, UserContext},
|
||||||
Pod,
|
Pod,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -12,6 +14,10 @@ impl LinuxAbi for UserContext {
|
|||||||
self.a7()
|
self.a7()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_syscall_num(&mut self, num: usize) {
|
||||||
|
self.set_a7(num);
|
||||||
|
}
|
||||||
|
|
||||||
fn syscall_ret(&self) -> usize {
|
fn syscall_ret(&self) -> usize {
|
||||||
self.a0()
|
self.a0()
|
||||||
}
|
}
|
||||||
@ -146,3 +152,22 @@ impl TryFrom<&CpuExceptionInfo> for PageFaultInfo {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CPU Information structure.
|
||||||
|
// TODO: Implement CPU information retrieval on RISC-V platforms.
|
||||||
|
pub struct CpuInfo {
|
||||||
|
processor: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CpuInfo {
|
||||||
|
pub fn new(processor_id: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
processor: processor_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collect and format CPU information into a `String`.
|
||||||
|
pub fn collect_cpu_info(&self) -> String {
|
||||||
|
format!("processor\t: {}\n", self.processor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use ostd::cpu::{CpuExceptionInfo, UserContext};
|
use ostd::cpu::context::{CpuExceptionInfo, UserContext};
|
||||||
|
|
||||||
use crate::process::signal::{sig_num::SigNum, signals::fault::FaultSignal, SignalContext};
|
use crate::process::signal::{sig_num::SigNum, signals::fault::FaultSignal, SignalContext};
|
||||||
|
|
||||||
|
@ -289,7 +289,6 @@ impl_syscall_nums_and_dispatch_fn! {
|
|||||||
SYS_PREADV2 = 286 => sys_preadv2(args[..5]);
|
SYS_PREADV2 = 286 => sys_preadv2(args[..5]);
|
||||||
SYS_PWRITEV2 = 287 => sys_pwritev2(args[..5]);
|
SYS_PWRITEV2 = 287 => sys_pwritev2(args[..5]);
|
||||||
SYS_STATX = 291 => sys_statx(args[..5]);
|
SYS_STATX = 291 => sys_statx(args[..5]);
|
||||||
SYS_PRLIMIT64 = 302 => sys_prlimit64(args[..4]);
|
|
||||||
SYS_CLOCK_GETTIME = 403 => sys_clock_gettime(args[..2]);
|
SYS_CLOCK_GETTIME = 403 => sys_clock_gettime(args[..2]);
|
||||||
SYS_CLOCK_NANOSLEEP = 407 => sys_clock_nanosleep(args[..4]);
|
SYS_CLOCK_NANOSLEEP = 407 => sys_clock_nanosleep(args[..4]);
|
||||||
SYS_TIMER_GETTIME = 408 => sys_timer_gettime(args[..2]);
|
SYS_TIMER_GETTIME = 408 => sys_timer_gettime(args[..2]);
|
||||||
|
@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
//! Multiprocessor Boot Support
|
//! Multiprocessor Boot Support
|
||||||
|
|
||||||
|
use crate::{boot::smp::PerApRawInfo, mm::Paddr};
|
||||||
|
|
||||||
pub(crate) fn count_processors() -> Option<u32> {
|
pub(crate) fn count_processors() -> Option<u32> {
|
||||||
Some(1)
|
Some(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn bringup_all_aps() {
|
pub(crate) fn bringup_all_aps(_info_ptr: *mut PerApRawInfo, _pr_ptr: Paddr, _num_cpus: u32) {
|
||||||
// TODO
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ use crate::{
|
|||||||
pub struct UserContext {
|
pub struct UserContext {
|
||||||
user_context: RawUserContext,
|
user_context: RawUserContext,
|
||||||
trap: Trap,
|
trap: Trap,
|
||||||
fpu_state: (), // TODO
|
fpu_state: FpuState,
|
||||||
cpu_exception_info: CpuExceptionInfo,
|
cpu_exception_info: CpuExceptionInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ impl Default for UserContext {
|
|||||||
UserContext {
|
UserContext {
|
||||||
user_context: RawUserContext::default(),
|
user_context: RawUserContext::default(),
|
||||||
trap: Trap::Exception(Exception::Unknown),
|
trap: Trap::Exception(Exception::Unknown),
|
||||||
fpu_state: (),
|
fpu_state: FpuState,
|
||||||
cpu_exception_info: CpuExceptionInfo::default(),
|
cpu_exception_info: CpuExceptionInfo::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,12 +78,12 @@ impl UserContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to the FPU state.
|
/// Returns a reference to the FPU state.
|
||||||
pub fn fpu_state(&self) -> &() {
|
pub fn fpu_state(&self) -> &FpuState {
|
||||||
&self.fpu_state
|
&self.fpu_state
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a mutable reference to the FPU state.
|
/// Returns a mutable reference to the FPU state.
|
||||||
pub fn fpu_state_mut(&mut self) -> &mut () {
|
pub fn fpu_state_mut(&mut self) -> &mut FpuState {
|
||||||
&mut self.fpu_state
|
&mut self.fpu_state
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,3 +228,28 @@ cpu_context_impl_getter_setter!(
|
|||||||
|
|
||||||
/// CPU exception.
|
/// CPU exception.
|
||||||
pub type CpuException = Exception;
|
pub type CpuException = Exception;
|
||||||
|
|
||||||
|
/// The FPU state of user task.
|
||||||
|
///
|
||||||
|
/// This could be used for saving both legacy and modern state format.
|
||||||
|
// FIXME: Implement FPU state on RISC-V platforms.
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct FpuState;
|
||||||
|
|
||||||
|
impl FpuState {
|
||||||
|
/// Saves CPU's current FPU state into this instance.
|
||||||
|
pub fn save(&self) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Restores CPU's FPU state from this instance.
|
||||||
|
pub fn restore(&self) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FpuState {
|
||||||
|
fn default() -> Self {
|
||||||
|
FpuState
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -31,3 +31,7 @@ pub(crate) fn init() -> Result<(), IommuError> {
|
|||||||
pub(crate) fn has_dma_remapping() -> bool {
|
pub(crate) fn has_dma_remapping() -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn has_interrupt_remapping() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
mm::{
|
mm::{
|
||||||
page_prop::{CachePolicy, PageFlags, PageProperty, PrivilegedPageFlags as PrivFlags},
|
page_prop::{CachePolicy, PageFlags, PageProperty, PrivilegedPageFlags as PrivFlags},
|
||||||
page_table::PageTableEntryTrait,
|
page_table::PageTableEntryTrait,
|
||||||
Paddr, PagingConstsTrait, PagingLevel, Vaddr, PAGE_SIZE,
|
Paddr, PagingConstsTrait, PagingLevel, PodOnce, Vaddr, PAGE_SIZE,
|
||||||
},
|
},
|
||||||
util::marker::SameSizeAs,
|
util::marker::SameSizeAs,
|
||||||
Pod,
|
Pod,
|
||||||
@ -126,6 +126,8 @@ macro_rules! parse_flags {
|
|||||||
// SAFETY: `PageTableEntry` has the same size as `usize`
|
// SAFETY: `PageTableEntry` has the same size as `usize`
|
||||||
unsafe impl SameSizeAs<usize> for PageTableEntry {}
|
unsafe impl SameSizeAs<usize> for PageTableEntry {}
|
||||||
|
|
||||||
|
impl PodOnce for PageTableEntry {}
|
||||||
|
|
||||||
impl PageTableEntryTrait for PageTableEntry {
|
impl PageTableEntryTrait for PageTableEntry {
|
||||||
fn is_present(&self) -> bool {
|
fn is_present(&self) -> bool {
|
||||||
self.0 & PageTableFlags::VALID.bits() != 0
|
self.0 & PageTableFlags::VALID.bits() != 0
|
||||||
@ -188,16 +190,8 @@ impl PageTableEntryTrait for PageTableEntry {
|
|||||||
PrivFlags::GLOBAL,
|
PrivFlags::GLOBAL,
|
||||||
PageTableFlags::GLOBAL
|
PageTableFlags::GLOBAL
|
||||||
)
|
)
|
||||||
| parse_flags!(
|
| parse_flags!(prop.flags.bits(), PageFlags::AVAIL1, PageTableFlags::RSV1)
|
||||||
prop.flags.AVAIL1.bits(),
|
| parse_flags!(prop.flags.bits(), PageFlags::AVAIL2, PageTableFlags::RSV2);
|
||||||
PageFlags::AVAIL1,
|
|
||||||
PageTableFlags::RSV1
|
|
||||||
)
|
|
||||||
| parse_flags!(
|
|
||||||
prop.flags.AVAIL2.bits(),
|
|
||||||
PageFlags::AVAIL2,
|
|
||||||
PageTableFlags::RSV2
|
|
||||||
);
|
|
||||||
|
|
||||||
match prop.cache {
|
match prop.cache {
|
||||||
CachePolicy::Writeback => (),
|
CachePolicy::Writeback => (),
|
||||||
|
@ -54,6 +54,14 @@ pub fn read_tsc() -> u64 {
|
|||||||
riscv::register::time::read64()
|
riscv::register::time::read64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reads a hardware generated 64-bit random value.
|
||||||
|
///
|
||||||
|
/// Returns None if no random value was generated.
|
||||||
|
pub fn read_random() -> Option<u64> {
|
||||||
|
// FIXME: Implement a hardware random number generator on RISC-V platforms.
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn enable_cpu_features() {
|
pub(crate) fn enable_cpu_features() {
|
||||||
unsafe {
|
unsafe {
|
||||||
riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Clean);
|
riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Clean);
|
||||||
|
@ -2,10 +2,13 @@
|
|||||||
|
|
||||||
//! PCI bus access
|
//! PCI bus access
|
||||||
|
|
||||||
|
use log::warn;
|
||||||
use spin::Once;
|
use spin::Once;
|
||||||
|
|
||||||
use super::boot::DEVICE_TREE;
|
use super::boot::DEVICE_TREE;
|
||||||
use crate::{bus::pci::PciDeviceLocation, io::IoMem, mm::VmIoOnce, prelude::*, Error};
|
use crate::{
|
||||||
|
bus::pci::PciDeviceLocation, io::IoMem, mm::VmIoOnce, prelude::*, trap::IrqLine, Error,
|
||||||
|
};
|
||||||
|
|
||||||
static PCI_BASE_ADDR: Once<IoMem> = Once::new();
|
static PCI_BASE_ADDR: Once<IoMem> = Once::new();
|
||||||
|
|
||||||
@ -36,7 +39,7 @@ pub(crate) fn init() -> Result<()> {
|
|||||||
|
|
||||||
let mut reg = pci.reg().ok_or(Error::IoError)?;
|
let mut reg = pci.reg().ok_or(Error::IoError)?;
|
||||||
|
|
||||||
let Ok(region) = reg.next() else {
|
let Some(region) = reg.next() else {
|
||||||
warn!("PCI node should have exactly one `reg` property, but found zero `reg`s");
|
warn!("PCI node should have exactly one `reg` property, but found zero `reg`s");
|
||||||
return Err(Error::IoError);
|
return Err(Error::IoError);
|
||||||
};
|
};
|
||||||
@ -59,6 +62,12 @@ pub(crate) fn init() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) const MSIX_DEFAULT_MSG_ADDR: u32 = 0x2400_0000;
|
||||||
|
|
||||||
|
pub(crate) fn construct_remappable_msix_address(irq: &IrqLine) -> u32 {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
/// Encodes the bus, device, and function into an address offset in the PCI MMIO region.
|
/// Encodes the bus, device, and function into an address offset in the PCI MMIO region.
|
||||||
fn encode_as_address_offset(location: &PciDeviceLocation) -> u32 {
|
fn encode_as_address_offset(location: &PciDeviceLocation) -> u32 {
|
||||||
((location.bus as u32) << 16)
|
((location.bus as u32) << 16)
|
||||||
|
@ -40,6 +40,8 @@ pub(super) fn init() {
|
|||||||
IoMem::new(
|
IoMem::new(
|
||||||
(region.starting_address as usize)
|
(region.starting_address as usize)
|
||||||
..(region.starting_address as usize) + region.size.unwrap(),
|
..(region.starting_address as usize) + region.size.unwrap(),
|
||||||
|
crate::mm::page_prop::PageFlags::RW,
|
||||||
|
crate::mm::page_prop::CachePolicy::Uncacheable,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
GOLDFISH_IO_MEM.call_once(|| io_mem);
|
GOLDFISH_IO_MEM.call_once(|| io_mem);
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
|
|
||||||
mod trap;
|
mod trap;
|
||||||
|
|
||||||
|
use spin::Once;
|
||||||
pub use trap::{GeneralRegs, TrapFrame, UserContext};
|
pub use trap::{GeneralRegs, TrapFrame, UserContext};
|
||||||
|
|
||||||
|
use super::cpu::context::CpuExceptionInfo;
|
||||||
use crate::cpu_local_cell;
|
use crate::cpu_local_cell;
|
||||||
|
|
||||||
cpu_local_cell! {
|
cpu_local_cell! {
|
||||||
@ -43,3 +45,15 @@ extern "C" fn trap_handler(f: &mut TrapFrame) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::type_complexity)]
|
||||||
|
static USER_PAGE_FAULT_HANDLER: Once<fn(&CpuExceptionInfo) -> core::result::Result<(), ()>> =
|
||||||
|
Once::new();
|
||||||
|
|
||||||
|
/// Injects a custom handler for page faults that occur in the kernel and
|
||||||
|
/// are caused by user-space address.
|
||||||
|
pub fn inject_user_page_fault_handler(
|
||||||
|
handler: fn(info: &CpuExceptionInfo) -> core::result::Result<(), ()>,
|
||||||
|
) {
|
||||||
|
USER_PAGE_FAULT_HANDLER.call_once(|| handler);
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
//! PCI bus access
|
//! PCI bus access
|
||||||
|
|
||||||
use super::device::io_port::{ReadWriteAccess, WriteOnlyAccess};
|
use super::device::io_port::{ReadWriteAccess, WriteOnlyAccess};
|
||||||
use crate::{bus::pci::PciDeviceLocation, io::IoPort, prelude::*};
|
use crate::{bus::pci::PciDeviceLocation, io::IoPort, prelude::*, trap::IrqLine};
|
||||||
|
|
||||||
static PCI_ADDRESS_PORT: IoPort<u32, WriteOnlyAccess> = unsafe { IoPort::new(0x0CF8) };
|
static PCI_ADDRESS_PORT: IoPort<u32, WriteOnlyAccess> = unsafe { IoPort::new(0x0CF8) };
|
||||||
static PCI_DATA_PORT: IoPort<u32, ReadWriteAccess> = unsafe { IoPort::new(0x0CFC) };
|
static PCI_DATA_PORT: IoPort<u32, ReadWriteAccess> = unsafe { IoPort::new(0x0CFC) };
|
||||||
@ -25,6 +25,25 @@ pub(crate) fn has_pci_bus() -> bool {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) const MSIX_DEFAULT_MSG_ADDR: u32 = 0xFEE0_0000;
|
||||||
|
|
||||||
|
pub(crate) fn construct_remappable_msix_address(irq: &IrqLine) -> u32 {
|
||||||
|
let mut handle = irq.inner_irq().bind_remapping_entry().unwrap().lock();
|
||||||
|
|
||||||
|
// Enable irt entry
|
||||||
|
let irt_entry_mut = handle.irt_entry_mut().unwrap();
|
||||||
|
irt_entry_mut.enable_default(irq.num() as u32);
|
||||||
|
|
||||||
|
// Use remappable format. The bits[4:3] should be always set to 1 according to the manual.
|
||||||
|
let mut address = MSIX_DEFAULT_MSG_ADDR | 0b1_1000;
|
||||||
|
|
||||||
|
// Interrupt index[14:0] is on address[19:5] and interrupt index[15] is on address[2].
|
||||||
|
address |= (handle.index() as u32 & 0x7FFF) << 5;
|
||||||
|
address |= (handle.index() as u32 & 0x8000) >> 13;
|
||||||
|
|
||||||
|
address
|
||||||
|
}
|
||||||
|
|
||||||
/// Encodes the bus, device, and function into a port address for use with the PCI I/O port.
|
/// Encodes the bus, device, and function into a port address for use with the PCI I/O port.
|
||||||
fn encode_as_port(location: &PciDeviceLocation) -> u32 {
|
fn encode_as_port(location: &PciDeviceLocation) -> u32 {
|
||||||
// 1 << 31: Configuration enable
|
// 1 << 31: Configuration enable
|
||||||
|
@ -8,7 +8,10 @@
|
|||||||
use alloc::{sync::Arc, vec::Vec};
|
use alloc::{sync::Arc, vec::Vec};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::iommu::has_interrupt_remapping,
|
arch::{
|
||||||
|
iommu::has_interrupt_remapping,
|
||||||
|
pci::{construct_remappable_msix_address, MSIX_DEFAULT_MSG_ADDR},
|
||||||
|
},
|
||||||
bus::pci::{
|
bus::pci::{
|
||||||
cfg_space::{Bar, Command, MemoryBar},
|
cfg_space::{Bar, Command, MemoryBar},
|
||||||
common_device::PciCommonDevice,
|
common_device::PciCommonDevice,
|
||||||
@ -51,9 +54,6 @@ impl Clone for CapabilityMsixData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
const MSIX_DEFAULT_MSG_ADDR: u32 = 0xFEE0_0000;
|
|
||||||
|
|
||||||
impl CapabilityMsixData {
|
impl CapabilityMsixData {
|
||||||
pub(super) fn new(dev: &mut PciCommonDevice, cap_ptr: u16) -> Self {
|
pub(super) fn new(dev: &mut PciCommonDevice, cap_ptr: u16) -> Self {
|
||||||
// Get Table and PBA offset, provide functions to modify them
|
// Get Table and PBA offset, provide functions to modify them
|
||||||
@ -166,18 +166,7 @@ impl CapabilityMsixData {
|
|||||||
|
|
||||||
// If interrupt remapping is enabled, then we need to change the value of the message address.
|
// If interrupt remapping is enabled, then we need to change the value of the message address.
|
||||||
if has_interrupt_remapping() {
|
if has_interrupt_remapping() {
|
||||||
let mut handle = irq.inner_irq().bind_remapping_entry().unwrap().lock();
|
let address = construct_remappable_msix_address(&irq);
|
||||||
|
|
||||||
// Enable irt entry
|
|
||||||
let irt_entry_mut = handle.irt_entry_mut().unwrap();
|
|
||||||
irt_entry_mut.enable_default(irq.num() as u32);
|
|
||||||
|
|
||||||
// Use remappable format. The bits[4:3] should be always set to 1 according to the manual.
|
|
||||||
let mut address = MSIX_DEFAULT_MSG_ADDR | 0b1_1000;
|
|
||||||
|
|
||||||
// Interrupt index[14:0] is on address[19:5] and interrupt index[15] is on address[2].
|
|
||||||
address |= (handle.index() as u32 & 0x7FFF) << 5;
|
|
||||||
address |= (handle.index() as u32 & 0x8000) >> 13;
|
|
||||||
|
|
||||||
self.table_bar
|
self.table_bar
|
||||||
.io_mem()
|
.io_mem()
|
||||||
|
@ -30,7 +30,7 @@ pub fn early_print(args: Arguments) {
|
|||||||
STDOUT.lock().write_fmt(args).unwrap();
|
STDOUT.lock().write_fmt(args).unwrap();
|
||||||
});
|
});
|
||||||
#[cfg(not(target_arch = "x86_64"))]
|
#[cfg(not(target_arch = "x86_64"))]
|
||||||
crate::arch::serial::print(args);
|
STDOUT.lock().write_fmt(args).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prints to the console.
|
/// Prints to the console.
|
||||||
|
@ -148,7 +148,7 @@ impl DmaStream {
|
|||||||
if self.inner.is_cache_coherent {
|
if self.inner.is_cache_coherent {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let start_va = crate::mm::paddr_to_vaddr(self.inner.segment.paddr()) as *const u8;
|
let start_va = crate::mm::paddr_to_vaddr(self.inner.segment.start_paddr()) as *const u8;
|
||||||
// TODO: Query the CPU for the cache line size via CPUID, we use 64 bytes as the cache line size here.
|
// TODO: Query the CPU for the cache line size via CPUID, we use 64 bytes as the cache line size here.
|
||||||
for i in _byte_range.step_by(64) {
|
for i in _byte_range.step_by(64) {
|
||||||
// TODO: Call the cache line flush command in the corresponding architecture.
|
// TODO: Call the cache line flush command in the corresponding architecture.
|
||||||
|
@ -136,7 +136,6 @@ impl Task {
|
|||||||
let Some(user_ctx) = self.user_ctx.as_ref() else {
|
let Some(user_ctx) = self.user_ctx.as_ref() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
user_ctx.fpu_state().save();
|
user_ctx.fpu_state().save();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +144,6 @@ impl Task {
|
|||||||
let Some(user_ctx) = self.user_ctx.as_ref() else {
|
let Some(user_ctx) = self.user_ctx.as_ref() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
user_ctx.fpu_state().restore();
|
user_ctx.fpu_state().restore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user