Adjust RISC-V's implementation for recent changes

This commit is contained in:
Zejun Zhao 2025-03-25 19:48:05 +08:00 committed by Tate, Hongliang Tian
parent b097060c5e
commit 14b8c48859
16 changed files with 131 additions and 43 deletions

View File

@ -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)
}
}

View File

@ -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};

View File

@ -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]);

View File

@ -2,10 +2,12 @@
//! Multiprocessor Boot Support
use crate::{boot::smp::PerApRawInfo, mm::Paddr};
pub(crate) fn count_processors() -> Option<u32> {
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!()
}

View File

@ -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
}
}

View File

@ -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
}

View File

@ -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<usize> 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 => (),

View File

@ -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<u64> {
// 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);

View File

@ -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<IoMem> = 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)

View File

@ -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);

View File

@ -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<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);
}

View File

@ -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<u32, WriteOnlyAccess> = unsafe { IoPort::new(0x0CF8) };
static PCI_DATA_PORT: IoPort<u32, ReadWriteAccess> = 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

View File

@ -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()

View File

@ -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.

View File

@ -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.

View File

@ -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();
}
}