diff --git a/Cargo.lock b/Cargo.lock index c8808ef..e120e07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,14 +81,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67" -[[package]] -name = "irq_safety" -version = "0.1.1" -source = "git+https://github.com/theseus-os/irq_safety.git#11bfab9f410a898df1e42ad6213488612e20c926" -dependencies = [ - "spin", -] - [[package]] name = "lock_api" version = "0.4.11" @@ -140,7 +132,6 @@ dependencies = [ "bitflags 2.5.0", "cfg-if", "fdt", - "irq_safety", "log", "loongArch64", "multiboot", diff --git a/Cargo.toml b/Cargo.toml index 0352d70..29d6d68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ fdt = "0.1.5" bitflags = "2.0.2" cfg-if = "1.0.0" polyhal-macro = { path = "polyhal-macro" } +spin = { version = "0.9.8", features = ["mutex"] } [target.'cfg(target_arch = "riscv64")'.dependencies] riscv = "0.11.0" @@ -29,8 +30,6 @@ sbi-rt = { version = "0.0.2", features = ["legacy"] } [target.'cfg(target_arch = "x86_64")'.dependencies] x86 = "0.52" x86_64 = "0.14" -spin = { version = "0.9.8", features = ["mutex"] } -irq_safety = { git = "https://github.com/theseus-os/irq_safety.git" } multiboot = "0.8.0" x2apic = "0.4" raw-cpuid = "11.0" @@ -39,9 +38,7 @@ raw-cpuid = "11.0" aarch64-cpu = "9.3" arm_pl011 = { git = "https://github.com/Byte-OS/arm_pl011.git" } tock-registers = "0.8" -irq_safety = { git = "https://github.com/theseus-os/irq_safety.git" } arm_gic = { git = "https://github.com/Byte-OS/arm_gic" } [target.'cfg(target_arch = "loongarch64")'.dependencies] -spin = { version = "0.9.8", features = ["mutex"] } loongArch64 = "0.2.2" diff --git a/example/Cargo.lock b/example/Cargo.lock index e02841d..e4a97b0 100644 --- a/example/Cargo.lock +++ b/example/Cargo.lock @@ -112,14 +112,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67" -[[package]] -name = "irq_safety" -version = "0.1.1" -source = "git+https://github.com/theseus-os/irq_safety.git#11bfab9f410a898df1e42ad6213488612e20c926" -dependencies = [ - "spin", -] - [[package]] name = "lock_api" version = "0.4.11" @@ -171,7 +163,6 @@ dependencies = [ "bitflags 2.5.0", "cfg-if", "fdt", - "irq_safety", "log", "loongArch64", "multiboot", diff --git a/polyhal-macro/src/lib.rs b/polyhal-macro/src/lib.rs index 9e8ca9f..02b3350 100644 --- a/polyhal-macro/src/lib.rs +++ b/polyhal-macro/src/lib.rs @@ -4,7 +4,6 @@ use proc_macro::TokenStream; use proc_macro2::Span; use quote::{format_ident, quote}; use syn::{parse_macro_input, Error, ItemFn, ItemStatic}; -use percpu::PERCPU_RESERVED; #[proc_macro_attribute] pub fn arch_entry(_input: TokenStream, annotated_item: TokenStream) -> TokenStream { @@ -112,11 +111,6 @@ pub fn def_percpu(attr: TokenStream, item: TokenStream) -> TokenStream { extern "Rust" { fn __start_percpu(); } - #[cfg(target_arch = "x86_64")] - unsafe { - &#inner_symbol_name as *const _ as usize - __start_percpu as usize + #PERCPU_RESERVED - } - #[cfg(not(target_arch = "x86_64"))] unsafe { &#inner_symbol_name as *const _ as usize - __start_percpu as usize } diff --git a/polyhal-macro/src/percpu.rs b/polyhal-macro/src/percpu.rs index 8ceceeb..3d0a429 100644 --- a/polyhal-macro/src/percpu.rs +++ b/polyhal-macro/src/percpu.rs @@ -1,19 +1,16 @@ -use std::mem::size_of; - use quote::quote; use syn::{Ident, Type}; -/// Reserved for default usage, Just for x86_64 now. -pub const PERCPU_RESERVED: usize = 4 * size_of::(); - pub fn gen_current_ptr(_symbol: &Ident, ty: &Type) -> proc_macro2::TokenStream { // TODO: Move this consts into polyhal crate. quote! { let base: usize; - // The first index is SELF_PTR in the x86_64 format + // The first usize is SELF_PTR in the x86_64 format + // The Second usize is VALID_PTR in the x86_64 format + // The Second usize point to the start of the valid area in the x86_64 format #[cfg(target_arch = "x86_64")] ::core::arch::asm!( - "mov {0}, gs:0", + "mov {0}, gs:1*8", out(reg) base, ); #[cfg(target_arch = "aarch64")] diff --git a/src/aarch64/gic.rs b/src/aarch64/gic.rs index cabb283..8cdd0c9 100644 --- a/src/aarch64/gic.rs +++ b/src/aarch64/gic.rs @@ -1,10 +1,10 @@ use aarch64_cpu::registers::{Readable, DAIF}; use arm_gic::gic_v2::{GicCpuInterface, GicDistributor}; use arm_gic::{translate_irq, InterruptType}; -use irq_safety::MutexIrqSafe; use crate::addr::PhysAddr; use crate::irq::{IRQVector, IRQ}; +use crate::utils::MutexNoIrq; /// The maximum number of IRQs. #[allow(dead_code)] @@ -20,8 +20,8 @@ pub const UART_IRQ_NUM: usize = translate_irq(1, InterruptType::SPI).unwrap(); const GICD_BASE: PhysAddr = PhysAddr::new(0x0800_0000); const GICC_BASE: PhysAddr = PhysAddr::new(0x0801_0000); -static GICD: MutexIrqSafe = - MutexIrqSafe::new(GicDistributor::new(GICD_BASE.get_mut_ptr())); +static GICD: MutexNoIrq = + MutexNoIrq::new(GicDistributor::new(GICD_BASE.get_mut_ptr())); // per-CPU, no lock static GICC: GicCpuInterface = GicCpuInterface::new(GICC_BASE.get_mut_ptr()); diff --git a/src/aarch64/mod.rs b/src/aarch64/mod.rs index 92e84d4..ef846f2 100644 --- a/src/aarch64/mod.rs +++ b/src/aarch64/mod.rs @@ -29,12 +29,15 @@ use polyhal_macro::def_percpu; pub use psci::system_off as shutdown; pub use trap::run_user_task; -use crate::debug::{display_info, println}; -use crate::multicore::MultiCore; -use crate::once::LazyInit; -use crate::pagetable::PageTable; -use crate::percpu::percpu_area_init; -use crate::{clear_bss, CPU_NUM, DTB_BIN, MEM_AREA}; +use crate::{ + clear_bss, + debug::{display_info, println}, + multicore::MultiCore, + pagetable::PageTable, + percpu::percpu_area_init, + utils::LazyInit, + CPU_NUM, DTB_BIN, MEM_AREA, +}; static DTB_PTR: LazyInit = LazyInit::new(); diff --git a/src/aarch64/pl011.rs b/src/aarch64/pl011.rs index be2c7a3..2e2e005 100644 --- a/src/aarch64/pl011.rs +++ b/src/aarch64/pl011.rs @@ -1,13 +1,12 @@ //! PL011 UART. use arm_pl011::pl011::Pl011Uart; -use irq_safety::MutexIrqSafe; -use crate::{addr::PhysAddr, debug::DebugConsole}; +use crate::{addr::PhysAddr, debug::DebugConsole, utils::MutexNoIrq}; const UART_BASE: PhysAddr = PhysAddr(0x0900_0000); -static UART: MutexIrqSafe = MutexIrqSafe::new(Pl011Uart::new(UART_BASE.get_mut_ptr())); +static UART: MutexNoIrq = MutexNoIrq::new(Pl011Uart::new(UART_BASE.get_mut_ptr())); /// Initialize the UART pub fn init_early() { diff --git a/src/lib.rs b/src/lib.rs index e2bc165..108fdab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ #![feature(cfg_version)] #![feature(decl_macro)] #![feature(cfg_match)] +#![feature(offset_of)] #![feature(used_with_arg)] #![cfg_attr(not(version("1.79")), feature(stdsimd))] #![feature(const_mut_refs)] @@ -152,10 +153,10 @@ pub mod irq; pub mod mem; #[cfg(feature = "multicore")] pub mod multicore; -pub mod once; pub mod pagetable; pub mod percpu; pub mod time; +pub mod utils; use core::mem::size_of; use addr::PhysPage; @@ -164,8 +165,8 @@ use alloc::vec::Vec; use consts::STACK_SIZE; use fdt::Fdt; use irq::IRQVector; -use once::LazyInit; use pagetable::PageTable; +use utils::LazyInit; #[cfg_attr(target_arch = "riscv64", path = "riscv64/mod.rs")] #[cfg_attr(target_arch = "aarch64", path = "aarch64/mod.rs")] diff --git a/src/loongarch64/mod.rs b/src/loongarch64/mod.rs index 6f882a2..4af5114 100644 --- a/src/loongarch64/mod.rs +++ b/src/loongarch64/mod.rs @@ -11,7 +11,9 @@ mod timer; mod trap; mod unaligned; -use crate::{clear_bss, multicore::MultiCore, percpu::percpu_area_init, CPU_NUM, DTB_BIN, MEM_AREA}; +use crate::{ + clear_bss, multicore::MultiCore, percpu::percpu_area_init, CPU_NUM, DTB_BIN, MEM_AREA, +}; use alloc::vec::Vec; pub use consts::*; pub use context::TrapFrame; diff --git a/src/percpu.rs b/src/percpu.rs index abcddcf..2526eb4 100644 --- a/src/percpu.rs +++ b/src/percpu.rs @@ -1,5 +1,4 @@ -/// !TIPS: x86_64 will - +/// !TIPS: x86_64 will use core::{alloc::Layout, mem::size_of, ptr::copy_nonoverlapping}; use alloc::alloc::alloc; @@ -14,15 +13,8 @@ static BOOT_PERCPU_DATA_AREA: [u8; PAGE_SIZE] = [0; PAGE_SIZE]; #[used(linker)] static _PERCPU_SEAT: [usize; 0] = [0; 0]; -/// Reserved for default usage. -/// This is related to the [polyhal_macro::percpu::PERCPU_RESERVED] -/// Just for x86_64 now. -/// 0: SELF_PTR -/// 1: USER_RSP -/// 2: KERNEL_RSP -/// 3: USER_CONTEXT #[cfg(target_arch = "x86_64")] -const PERCPU_RESERVED: usize = 4 * size_of::(); +const PERCPU_RESERVED: usize = size_of::(); #[cfg(not(target_arch = "x86_64"))] const PERCPU_RESERVED: usize = 0; @@ -86,8 +78,11 @@ pub fn set_local_thread_pointer(cpu_id: usize) { cfg_if::cfg_if! { if #[cfg(target_arch = "x86_64")] { x86::msr::wrmsr(x86::msr::IA32_GS_BASE, tp as u64); - // Write cpu_local pointer to the per-CPU data area - core::arch::asm!("mov gs:0, {0}", in(reg) tp); + // Write cpu_local pointer to the first usize of the per-CPU data area + // Write the valid address to the second usize of the per-CPU data area + let percpu_reserved = crate::currrent_arch::PerCPUReserved::mut_from_ptr(tp as _); + percpu_reserved.self_ptr = tp; + percpu_reserved.valid_ptr = tp + PERCPU_RESERVED; } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { core::arch::asm!("mv gp, {}", in(reg) tp) } else if #[cfg(target_arch = "aarch64")] { diff --git a/src/riscv64/mod.rs b/src/riscv64/mod.rs index e7674fd..39e926d 100644 --- a/src/riscv64/mod.rs +++ b/src/riscv64/mod.rs @@ -32,7 +32,7 @@ use crate::{ api::frame_alloc, debug::{display_info, println}, multicore::MultiCore, - once::LazyInit, + utils::LazyInit, CPU_NUM, DTB_BIN, MEM_AREA, }; diff --git a/src/once/mod.rs b/src/utils/lazy_init.rs similarity index 100% rename from src/once/mod.rs rename to src/utils/lazy_init.rs diff --git a/src/utils/mod.rs b/src/utils/mod.rs new file mode 100644 index 0000000..4711b57 --- /dev/null +++ b/src/utils/mod.rs @@ -0,0 +1,5 @@ +mod lazy_init; +mod mutex_no_irq; + +pub use lazy_init::LazyInit; +pub use mutex_no_irq::{MutexNoIrq, MutexNoIrqGuard}; diff --git a/src/utils/mutex_no_irq.rs b/src/utils/mutex_no_irq.rs new file mode 100644 index 0000000..21c5649 --- /dev/null +++ b/src/utils/mutex_no_irq.rs @@ -0,0 +1,95 @@ +use core::ops::{Deref, DerefMut}; +use spin::{Mutex, MutexGuard}; + +use crate::irq::IRQ; + +pub struct MutexNoIrq { + lock: Mutex, +} + +/// Irq Status Struct. +/// This structure contains the status of the current IRQ +/// And it will restore irq status after dropping. +struct IrqStatus { + irq_enabled: bool, +} + +/// Restore the IRQ status when dropping +impl Drop for IrqStatus { + fn drop(&mut self) { + if self.irq_enabled { + IRQ::int_enable(); + } + } +} + +unsafe impl Sync for MutexNoIrq {} +unsafe impl Send for MutexNoIrq {} + +impl MutexNoIrq { + pub const fn new(data: T) -> MutexNoIrq { + MutexNoIrq { + lock: Mutex::new(data), + } + } + + #[inline(always)] + pub fn into_inner(self) -> T { + self.lock.into_inner() + } +} + +impl MutexNoIrq { + #[inline] + pub fn lock(&self) -> MutexNoIrqGuard { + loop { + match self.try_lock() { + Some(guard) => return guard, + _ => {} + } + } + } + + #[inline] + pub fn is_locked(&self) -> bool { + self.lock.is_locked() + } + + pub unsafe fn force_unlock(&self) { + self.lock.force_unlock() + } + + #[inline] + pub fn try_lock(&self) -> Option> { + if self.lock.is_locked() { + return None; + } + let _irq_status = IrqStatus { + irq_enabled: IRQ::int_enabled(), + }; + IRQ::int_disable(); + self.lock + .try_lock() + .map(|guard| MutexNoIrqGuard { guard, _irq_status }) + } +} + +/// The Mutex Guard. +pub struct MutexNoIrqGuard<'a, T: ?Sized + 'a> { + guard: MutexGuard<'a, T>, + _irq_status: IrqStatus, +} + +impl<'a, T: ?Sized> Deref for MutexNoIrqGuard<'a, T> { + type Target = T; + + fn deref<'b>(&'b self) -> &'b T { + &*(self.guard) + } +} + +impl<'a, T: ?Sized> DerefMut for MutexNoIrqGuard<'a, T> { + fn deref_mut<'b>(&'b mut self) -> &'b mut T { + &mut *(self.guard) + } +} diff --git a/src/x86_64/apic.rs b/src/x86_64/apic.rs index 9121ad1..1de0f7a 100644 --- a/src/x86_64/apic.rs +++ b/src/x86_64/apic.rs @@ -2,7 +2,6 @@ use core::cmp; -use irq_safety::MutexIrqSafe; use spin::Once; use x2apic::ioapic::{IoApic, RedirectionTableEntry}; use x2apic::lapic::{xapic_base, LocalApic, LocalApicBuilder}; @@ -10,6 +9,7 @@ use x86_64::instructions::port::Port; use self::vectors::*; use super::consts::PIC_VECTOR_OFFSET; +use crate::utils::MutexNoIrq; use crate::VIRT_ADDR_START; pub(super) mod vectors { @@ -28,7 +28,7 @@ const IO_APIC_BASE: u64 = 0xFEC0_0000; static mut LOCAL_APIC: Option = None; static mut IS_X2APIC: bool = false; -static IO_APIC: Once> = Once::new(); +static IO_APIC: Once> = Once::new(); /// Registers an IRQ handler for the given IRQ. /// @@ -54,7 +54,7 @@ pub(super) fn local_apic<'a>() -> &'a mut LocalApic { } /// Get the interrupt controller -pub(super) fn io_apic<'a>() -> &'a MutexIrqSafe { +pub(super) fn io_apic<'a>() -> &'a MutexNoIrq { IO_APIC.get().expect("Can't get io_apic") } @@ -145,5 +145,5 @@ pub(super) fn init() { } // Initialize the IO_APIC - IO_APIC.call_once(|| MutexIrqSafe::new(io_apic)); + IO_APIC.call_once(|| MutexNoIrq::new(io_apic)); } diff --git a/src/x86_64/consts.rs b/src/x86_64/consts.rs index 10ff5f7..e6586f8 100644 --- a/src/x86_64/consts.rs +++ b/src/x86_64/consts.rs @@ -1,12 +1,5 @@ -use core::mem::size_of; - pub const VIRT_ADDR_START: usize = 0xffff_ff80_0000_0000; pub const SYSCALL_VECTOR: usize = 0x33445566; /// The offset of the pic irq. pub(super) const PIC_VECTOR_OFFSET: u8 = 0x20; - -/// Reserved percpu index -pub(super) const PERCPU_USER_RSP_OFFSET: usize = 1 * size_of::(); -pub(super) const PERCPU_KERNEL_RSP_OFFSET: usize = 2 * size_of::(); -pub(super) const PERCPU_USER_CONTEXT_OFFSET: usize = 3 * size_of::(); diff --git a/src/x86_64/interrupt.rs b/src/x86_64/interrupt.rs index 78a0829..570f14d 100644 --- a/src/x86_64/interrupt.rs +++ b/src/x86_64/interrupt.rs @@ -1,5 +1,5 @@ use core::arch::{asm, global_asm}; -use core::mem::size_of; +use core::mem::{offset_of, size_of}; use bitflags::bitflags; use x86_64::registers::model_specific::{Efer, EferFlags, KernelGsBase, LStar, SFMask, Star}; @@ -14,8 +14,9 @@ use crate::currrent_arch::gdt::set_tss_kernel_sp; use crate::{currrent_arch::gdt::GdtStruct, TrapFrame, TrapType}; use super::apic::vectors::APIC_TIMER_VECTOR; -use super::consts::{PERCPU_USER_CONTEXT_OFFSET, PERCPU_USER_RSP_OFFSET, PERCPU_KERNEL_RSP_OFFSET, PIC_VECTOR_OFFSET}; +use super::consts::PIC_VECTOR_OFFSET; use super::context::FxsaveArea; +use super::PerCPUReserved; global_asm!( r" @@ -198,7 +199,8 @@ pub unsafe extern "C" fn uservec() { ret ", - PERCPU_KERNEL_RSP_OFFSET = const PERCPU_KERNEL_RSP_OFFSET, + // PERCPU_KERNEL_RSP_OFFSET = const PERCPU_KERNEL_RSP_OFFSET, + PERCPU_KERNEL_RSP_OFFSET = const offset_of!(PerCPUReserved, kernel_rsp), options(noreturn) ); } @@ -264,7 +266,8 @@ pub extern "C" fn user_restore(context: *mut TrapFrame) { ", syscall_vector = const SYSCALL_VECTOR, sysretq = sym sysretq, - PERCPU_KERNEL_RSP_OFFSET = const PERCPU_KERNEL_RSP_OFFSET, + // PERCPU_KERNEL_RSP_OFFSET = const PERCPU_KERNEL_RSP_OFFSET, + PERCPU_KERNEL_RSP_OFFSET = const offset_of!(PerCPUReserved, kernel_rsp), options(noreturn) ) } @@ -368,9 +371,12 @@ unsafe extern "C" fn syscall_entry() { ret ", syscall_vector = const SYSCALL_VECTOR, - PERCPU_USER_CONTEXT_OFFSET = const PERCPU_USER_CONTEXT_OFFSET, - PERCPU_USER_RSP_OFFSET = const PERCPU_USER_RSP_OFFSET, - PERCPU_KERNEL_RSP_OFFSET = const PERCPU_KERNEL_RSP_OFFSET, + // PERCPU_USER_CONTEXT_OFFSET = const PERCPU_USER_CONTEXT_OFFSET, + // PERCPU_USER_RSP_OFFSET = const PERCPU_USER_RSP_OFFSET, + // PERCPU_KERNEL_RSP_OFFSET = const PERCPU_KERNEL_RSP_OFFSET, + PERCPU_USER_CONTEXT_OFFSET = const offset_of!(PerCPUReserved, user_context), + PERCPU_USER_RSP_OFFSET = const offset_of!(PerCPUReserved, user_rsp), + PERCPU_KERNEL_RSP_OFFSET = const offset_of!(PerCPUReserved, kernel_rsp), options(noreturn) ) } @@ -386,7 +392,8 @@ pub fn run_user_task(context: &mut TrapFrame) -> Option<()> { core::arch::asm!( "mov gs:{USER_CONTEXT}, {0}", in(reg) cx_general_top, - USER_CONTEXT = const PERCPU_USER_CONTEXT_OFFSET + // USER_CONTEXT = const PERCPU_USER_CONTEXT_OFFSET + USER_CONTEXT = const offset_of!(PerCPUReserved, user_context) ); } context.fx_area.restore(); diff --git a/src/x86_64/mod.rs b/src/x86_64/mod.rs index 771ae28..6785cea 100644 --- a/src/x86_64/mod.rs +++ b/src/x86_64/mod.rs @@ -39,8 +39,8 @@ use crate::{ currrent_arch::multiboot::use_multiboot, debug::{display_info, println}, multicore::MultiCore, - once::LazyInit, percpu::set_local_thread_pointer, + utils::LazyInit, CPU_NUM, DTB_BIN, MEM_AREA, }; @@ -92,6 +92,7 @@ fn rust_tmp_main(magic: usize, mboot_ptr: usize) { info!("magic: {magic:#x}, mboot_ptr: {mboot_ptr:#x}"); + // Set the multiboot pointer. MBOOT_PTR.init_by(mboot_ptr); // Print PolyHAL information. @@ -172,3 +173,26 @@ pub fn hart_id() -> usize { impl MultiCore { pub fn boot_all() {} } + +/// Reserved for default usage. +/// This is related to the [polyhal_macro::percpu::PERCPU_RESERVED] +/// Just for x86_64 now. +/// 0: SELF_PTR +/// 1: VALID_PTR +/// 2: USER_RSP +/// 3: KERNEL_RSP +/// 4: USER_CONTEXT +#[repr(C)] +pub(crate) struct PerCPUReserved { + pub self_ptr: usize, + pub valid_ptr: usize, + pub user_rsp: usize, + pub kernel_rsp: usize, + pub user_context: usize, +} + +impl PerCPUReserved { + pub fn mut_from_ptr(ptr: *mut Self) -> &'static mut Self { + unsafe { &mut (*ptr) } + } +} diff --git a/src/x86_64/uart.rs b/src/x86_64/uart.rs index cece2c2..b4d99b2 100644 --- a/src/x86_64/uart.rs +++ b/src/x86_64/uart.rs @@ -1,14 +1,14 @@ //! Uart 16550. -use irq_safety::MutexIrqSafe; +// use irq_safety::MutexIrqSafe; use x86_64::instructions::port::{Port, PortReadOnly, PortWriteOnly}; -use crate::debug::DebugConsole; +use crate::{debug::DebugConsole, utils::MutexNoIrq}; const UART_CLOCK_FACTOR: usize = 16; const OSC_FREQ: usize = 1_843_200; -static COM1: MutexIrqSafe = MutexIrqSafe::new(Uart16550::new(0x3f8)); +static COM1: MutexNoIrq = MutexNoIrq::new(Uart16550::new(0x3f8)); bitflags::bitflags! { /// Line status flags