diff --git a/kernel/src/arch/riscv/cpu.rs b/kernel/src/arch/riscv/cpu.rs index 9bb2254fe..07b6b23f6 100644 --- a/kernel/src/arch/riscv/cpu.rs +++ b/kernel/src/arch/riscv/cpu.rs @@ -1,7 +1,9 @@ // SPDX-License-Identifier: MPL-2.0 +use alloc::{format, string::String}; + use ostd::{ - cpu::{CpuExceptionInfo, RawGeneralRegs, UserContext}, + cpu::context::{CpuExceptionInfo, RawGeneralRegs, UserContext}, Pod, }; @@ -12,6 +14,10 @@ impl LinuxAbi for UserContext { self.a7() } + fn set_syscall_num(&mut self, num: usize) { + self.set_a7(num); + } + fn syscall_ret(&self) -> usize { 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) + } +} diff --git a/kernel/src/arch/riscv/signal.rs b/kernel/src/arch/riscv/signal.rs index 4abaa3759..5390dbf20 100644 --- a/kernel/src/arch/riscv/signal.rs +++ b/kernel/src/arch/riscv/signal.rs @@ -1,6 +1,6 @@ // 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}; diff --git a/kernel/src/syscall/arch/riscv.rs b/kernel/src/syscall/arch/riscv.rs index 73468906b..e9a25e521 100644 --- a/kernel/src/syscall/arch/riscv.rs +++ b/kernel/src/syscall/arch/riscv.rs @@ -289,7 +289,6 @@ impl_syscall_nums_and_dispatch_fn! { SYS_PREADV2 = 286 => sys_preadv2(args[..5]); SYS_PWRITEV2 = 287 => sys_pwritev2(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_NANOSLEEP = 407 => sys_clock_nanosleep(args[..4]); SYS_TIMER_GETTIME = 408 => sys_timer_gettime(args[..2]); diff --git a/ostd/src/arch/riscv/boot/smp.rs b/ostd/src/arch/riscv/boot/smp.rs index 4c16ee334..24bfa3524 100644 --- a/ostd/src/arch/riscv/boot/smp.rs +++ b/ostd/src/arch/riscv/boot/smp.rs @@ -2,10 +2,12 @@ //! Multiprocessor Boot Support +use crate::{boot::smp::PerApRawInfo, mm::Paddr}; + pub(crate) fn count_processors() -> Option { Some(1) } -pub(crate) fn bringup_all_aps() { - // TODO +pub(crate) fn bringup_all_aps(_info_ptr: *mut PerApRawInfo, _pr_ptr: Paddr, _num_cpus: u32) { + todo!() } diff --git a/ostd/src/arch/riscv/cpu/context.rs b/ostd/src/arch/riscv/cpu/context.rs index 21f09cb8c..9a00739d1 100644 --- a/ostd/src/arch/riscv/cpu/context.rs +++ b/ostd/src/arch/riscv/cpu/context.rs @@ -18,7 +18,7 @@ use crate::{ pub struct UserContext { user_context: RawUserContext, trap: Trap, - fpu_state: (), // TODO + fpu_state: FpuState, cpu_exception_info: CpuExceptionInfo, } @@ -38,7 +38,7 @@ impl Default for UserContext { UserContext { user_context: RawUserContext::default(), trap: Trap::Exception(Exception::Unknown), - fpu_state: (), + fpu_state: FpuState, cpu_exception_info: CpuExceptionInfo::default(), } } @@ -78,12 +78,12 @@ impl UserContext { } /// Returns a reference to the FPU state. - pub fn fpu_state(&self) -> &() { + pub fn fpu_state(&self) -> &FpuState { &self.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 } @@ -228,3 +228,28 @@ cpu_context_impl_getter_setter!( /// CPU 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 + } +} diff --git a/ostd/src/arch/riscv/iommu/mod.rs b/ostd/src/arch/riscv/iommu/mod.rs index a8b2972ca..352528d01 100644 --- a/ostd/src/arch/riscv/iommu/mod.rs +++ b/ostd/src/arch/riscv/iommu/mod.rs @@ -31,3 +31,7 @@ pub(crate) fn init() -> Result<(), IommuError> { pub(crate) fn has_dma_remapping() -> bool { false } + +pub(crate) fn has_interrupt_remapping() -> bool { + false +} diff --git a/ostd/src/arch/riscv/mm/mod.rs b/ostd/src/arch/riscv/mm/mod.rs index 3bdf9dda1..d0544d4fb 100644 --- a/ostd/src/arch/riscv/mm/mod.rs +++ b/ostd/src/arch/riscv/mm/mod.rs @@ -7,7 +7,7 @@ use crate::{ mm::{ page_prop::{CachePolicy, PageFlags, PageProperty, PrivilegedPageFlags as PrivFlags}, page_table::PageTableEntryTrait, - Paddr, PagingConstsTrait, PagingLevel, Vaddr, PAGE_SIZE, + Paddr, PagingConstsTrait, PagingLevel, PodOnce, Vaddr, PAGE_SIZE, }, util::marker::SameSizeAs, Pod, @@ -126,6 +126,8 @@ macro_rules! parse_flags { // SAFETY: `PageTableEntry` has the same size as `usize` unsafe impl SameSizeAs for PageTableEntry {} +impl PodOnce for PageTableEntry {} + impl PageTableEntryTrait for PageTableEntry { fn is_present(&self) -> bool { self.0 & PageTableFlags::VALID.bits() != 0 @@ -188,16 +190,8 @@ impl PageTableEntryTrait for PageTableEntry { PrivFlags::GLOBAL, PageTableFlags::GLOBAL ) - | parse_flags!( - prop.flags.AVAIL1.bits(), - PageFlags::AVAIL1, - PageTableFlags::RSV1 - ) - | parse_flags!( - prop.flags.AVAIL2.bits(), - PageFlags::AVAIL2, - PageTableFlags::RSV2 - ); + | parse_flags!(prop.flags.bits(), PageFlags::AVAIL1, PageTableFlags::RSV1) + | parse_flags!(prop.flags.bits(), PageFlags::AVAIL2, PageTableFlags::RSV2); match prop.cache { CachePolicy::Writeback => (), diff --git a/ostd/src/arch/riscv/mod.rs b/ostd/src/arch/riscv/mod.rs index 29a75805e..a030b5649 100644 --- a/ostd/src/arch/riscv/mod.rs +++ b/ostd/src/arch/riscv/mod.rs @@ -54,6 +54,14 @@ pub fn read_tsc() -> u64 { 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 { + // FIXME: Implement a hardware random number generator on RISC-V platforms. + None +} + pub(crate) fn enable_cpu_features() { unsafe { riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Clean); diff --git a/ostd/src/arch/riscv/pci.rs b/ostd/src/arch/riscv/pci.rs index 6332143f2..8850578cd 100644 --- a/ostd/src/arch/riscv/pci.rs +++ b/ostd/src/arch/riscv/pci.rs @@ -2,10 +2,13 @@ //! PCI bus access +use log::warn; use spin::Once; 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 = Once::new(); @@ -36,7 +39,7 @@ pub(crate) fn init() -> Result<()> { 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"); return Err(Error::IoError); }; @@ -59,6 +62,12 @@ pub(crate) fn init() -> Result<()> { 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. fn encode_as_address_offset(location: &PciDeviceLocation) -> u32 { ((location.bus as u32) << 16) diff --git a/ostd/src/arch/riscv/timer/mod.rs b/ostd/src/arch/riscv/timer/mod.rs index 5c0a687f5..00ac7ec09 100644 --- a/ostd/src/arch/riscv/timer/mod.rs +++ b/ostd/src/arch/riscv/timer/mod.rs @@ -40,6 +40,8 @@ pub(super) fn init() { IoMem::new( (region.starting_address as usize) ..(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); diff --git a/ostd/src/arch/riscv/trap/mod.rs b/ostd/src/arch/riscv/trap/mod.rs index 3c347e1fe..2581a87f7 100644 --- a/ostd/src/arch/riscv/trap/mod.rs +++ b/ostd/src/arch/riscv/trap/mod.rs @@ -4,8 +4,10 @@ mod trap; +use spin::Once; pub use trap::{GeneralRegs, TrapFrame, UserContext}; +use super::cpu::context::CpuExceptionInfo; use crate::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 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); +} diff --git a/ostd/src/arch/x86/pci.rs b/ostd/src/arch/x86/pci.rs index 3bad24392..f748d788f 100644 --- a/ostd/src/arch/x86/pci.rs +++ b/ostd/src/arch/x86/pci.rs @@ -3,7 +3,7 @@ //! PCI bus access 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 = unsafe { IoPort::new(0x0CF8) }; static PCI_DATA_PORT: IoPort = unsafe { IoPort::new(0x0CFC) }; @@ -25,6 +25,25 @@ pub(crate) fn has_pci_bus() -> bool { 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. fn encode_as_port(location: &PciDeviceLocation) -> u32 { // 1 << 31: Configuration enable diff --git a/ostd/src/bus/pci/capability/msix.rs b/ostd/src/bus/pci/capability/msix.rs index b41c6ecb5..30dbef5db 100644 --- a/ostd/src/bus/pci/capability/msix.rs +++ b/ostd/src/bus/pci/capability/msix.rs @@ -8,7 +8,10 @@ use alloc::{sync::Arc, vec::Vec}; use crate::{ - arch::iommu::has_interrupt_remapping, + arch::{ + iommu::has_interrupt_remapping, + pci::{construct_remappable_msix_address, MSIX_DEFAULT_MSG_ADDR}, + }, bus::pci::{ cfg_space::{Bar, Command, MemoryBar}, 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 { pub(super) fn new(dev: &mut PciCommonDevice, cap_ptr: u16) -> Self { // 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 has_interrupt_remapping() { - 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; + let address = construct_remappable_msix_address(&irq); self.table_bar .io_mem() diff --git a/ostd/src/console.rs b/ostd/src/console.rs index a45a5965d..a5db63bb0 100644 --- a/ostd/src/console.rs +++ b/ostd/src/console.rs @@ -30,7 +30,7 @@ pub fn early_print(args: Arguments) { STDOUT.lock().write_fmt(args).unwrap(); }); #[cfg(not(target_arch = "x86_64"))] - crate::arch::serial::print(args); + STDOUT.lock().write_fmt(args).unwrap(); } /// Prints to the console. diff --git a/ostd/src/mm/dma/dma_stream.rs b/ostd/src/mm/dma/dma_stream.rs index c9d25eb76..a9ca2bec3 100644 --- a/ostd/src/mm/dma/dma_stream.rs +++ b/ostd/src/mm/dma/dma_stream.rs @@ -148,7 +148,7 @@ impl DmaStream { if self.inner.is_cache_coherent { 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. for i in _byte_range.step_by(64) { // TODO: Call the cache line flush command in the corresponding architecture. diff --git a/ostd/src/task/mod.rs b/ostd/src/task/mod.rs index a8b0293cb..513d53e42 100644 --- a/ostd/src/task/mod.rs +++ b/ostd/src/task/mod.rs @@ -136,7 +136,6 @@ impl Task { let Some(user_ctx) = self.user_ctx.as_ref() else { return; }; - user_ctx.fpu_state().save(); } @@ -145,7 +144,6 @@ impl Task { let Some(user_ctx) = self.user_ctx.as_ref() else { return; }; - user_ctx.fpu_state().restore(); } }