mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 12: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
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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!()
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 => (),
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user