diff --git a/Cargo.toml b/Cargo.toml index 47c6e1fc..084d3dd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,8 @@ memtables = { path = "lib/memtables" } vmalloc = { path = "lib/vmalloc" } device-api-macros = { path = "lib/device-api/macros" } +kernel-arch = { path = "arch" } + # Drivers ygg_driver_pci = { path = "driver/bus/pci" } ygg_driver_block = { path = "driver/block/core" } diff --git a/arch/Cargo.toml b/arch/Cargo.toml new file mode 100644 index 00000000..0ac2a342 --- /dev/null +++ b/arch/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "kernel-arch" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[target.'cfg(target_arch = "x86_64")'.dependencies] +kernel-arch-x86_64 = { path = "x86_64" } + +[target.'cfg(target_arch = "aarch64")'.dependencies] +kernel-arch-aarch64 = { path = "aarch64" } + +[dependencies] +kernel-arch-interface = { path = "interface" } + +cfg-if = "1.0.0" diff --git a/arch/aarch64/Cargo.toml b/arch/aarch64/Cargo.toml new file mode 100644 index 00000000..50af2b8a --- /dev/null +++ b/arch/aarch64/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "kernel-arch-aarch64" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +kernel-arch-interface = { path = "../interface" } + +aarch64-cpu = "9.3.1" +tock-registers = "0.8.1" diff --git a/arch/aarch64/src/lib.rs b/arch/aarch64/src/lib.rs new file mode 100644 index 00000000..7f85495b --- /dev/null +++ b/arch/aarch64/src/lib.rs @@ -0,0 +1,27 @@ +#![no_std] + +use aarch64_cpu::registers::DAIF; +use kernel_arch_interface::Architecture; +use tock_registers::interfaces::{ReadWriteable, Readable}; + +pub struct ArchitectureImpl; + +impl Architecture for ArchitectureImpl { + fn interrupt_mask() -> bool { + DAIF.read(DAIF::I) != 0 + } + + unsafe fn set_interrupt_mask(mask: bool) -> bool { + let old = Self::interrupt_mask(); + if mask { + DAIF.modify(DAIF::I::SET); + } else { + DAIF.modify(DAIF::I::CLEAR); + } + old + } + + fn wait_for_interrupt() { + aarch64_cpu::asm::wfi(); + } +} diff --git a/arch/interface/Cargo.toml b/arch/interface/Cargo.toml new file mode 100644 index 00000000..8714e738 --- /dev/null +++ b/arch/interface/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "kernel-arch-interface" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/arch/interface/src/lib.rs b/arch/interface/src/lib.rs new file mode 100644 index 00000000..f1aed0c8 --- /dev/null +++ b/arch/interface/src/lib.rs @@ -0,0 +1,9 @@ +#![no_std] + +pub trait Architecture { + fn interrupt_mask() -> bool; + + unsafe fn set_interrupt_mask(mask: bool) -> bool; + + fn wait_for_interrupt(); +} diff --git a/arch/src/lib.rs b/arch/src/lib.rs new file mode 100644 index 00000000..1a53ef3e --- /dev/null +++ b/arch/src/lib.rs @@ -0,0 +1,34 @@ +#![no_std] + +use cfg_if::cfg_if; + +pub use kernel_arch_interface::Architecture; + +/// Returns an absolute address to the given symbol +#[macro_export] +macro_rules! absolute_address { + ($sym:expr) => {{ + let mut _x: usize; + #[cfg(target_arch = "aarch64")] + unsafe { + core::arch::asm!("ldr {0}, ={1}", out(reg) _x, sym $sym); + } + #[cfg(target_arch = "x86_64")] + unsafe { + core::arch::asm!("movabsq ${1}, {0}", out(reg) _x, sym $sym, options(att_syntax)); + } + _x + }}; +} + +cfg_if! { + if #[cfg(target_arch = "aarch64")] { + extern crate kernel_arch_aarch64 as imp; + } else if #[cfg(target_arch = "x86_64")] { + extern crate kernel_arch_x86_64 as imp; + } else { + compile_error!("Unsupported architecture"); + } +} + +pub use imp::ArchitectureImpl; diff --git a/arch/x86_64/Cargo.toml b/arch/x86_64/Cargo.toml new file mode 100644 index 00000000..9501db4a --- /dev/null +++ b/arch/x86_64/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "kernel-arch-x86_64" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +kernel-arch-interface = { path = "../interface" } diff --git a/arch/x86_64/src/lib.rs b/arch/x86_64/src/lib.rs new file mode 100644 index 00000000..bff7e580 --- /dev/null +++ b/arch/x86_64/src/lib.rs @@ -0,0 +1,33 @@ +#![no_std] + +use kernel_arch_interface::Architecture; + +pub struct ArchitectureImpl; + +impl Architecture for ArchitectureImpl { + fn interrupt_mask() -> bool { + let mut flags: u64; + unsafe { + core::arch::asm!("pushfq; pop {0}", out(reg) flags, options(att_syntax)); + } + // If IF is zero, interrupts are disabled (masked) + flags & (1 << 9) == 0 + } + + unsafe fn set_interrupt_mask(mask: bool) -> bool { + let old = Self::interrupt_mask(); + if mask { + core::arch::asm!("cli"); + } else { + core::arch::asm!("sti"); + } + old + } + + #[inline] + fn wait_for_interrupt() { + unsafe { + core::arch::asm!("hlt"); + } + } +} diff --git a/libk-util/Cargo.toml b/libk-util/Cargo.toml index e019bed6..fe3e89b2 100644 --- a/libk-util/Cargo.toml +++ b/libk-util/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" } +kernel-arch = { path = "../arch" } log = "0.4.20" crossbeam-queue = { version = "0.3.8", default-features = false, features = ["alloc"] } diff --git a/libk-util/src/api.rs b/libk-util/src/api.rs deleted file mode 100644 index 85f8d31f..00000000 --- a/libk-util/src/api.rs +++ /dev/null @@ -1,4 +0,0 @@ -extern "Rust" { - pub fn __acquire_irq_guard() -> bool; - pub fn __release_irq_guard(mask: bool); -} diff --git a/libk-util/src/lib.rs b/libk-util/src/lib.rs index 3f6bd0f5..1e7aec4b 100644 --- a/libk-util/src/lib.rs +++ b/libk-util/src/lib.rs @@ -11,8 +11,6 @@ use core::{ sync::atomic::{AtomicUsize, Ordering}, }; -pub(crate) mod api; - pub mod event; pub mod queue; pub mod ring; diff --git a/libk-util/src/sync/guard.rs b/libk-util/src/sync/guard.rs index d2db9036..8b4625a2 100644 --- a/libk-util/src/sync/guard.rs +++ b/libk-util/src/sync/guard.rs @@ -1,4 +1,4 @@ -use crate::api; +use kernel_arch::{Architecture, ArchitectureImpl}; /// Token type used to prevent IRQs from firing during some critical section. Normal IRQ operation /// (if enabled before) is resumed when [IrqGuard]'s lifetime is over. @@ -8,12 +8,15 @@ pub struct IrqGuard(bool); impl IrqGuard { /// Saves the current IRQ state and masks them pub fn acquire() -> Self { - Self(unsafe { api::__acquire_irq_guard() }) + let mask = unsafe { ArchitectureImpl::set_interrupt_mask(true) }; + Self(mask) } } impl Drop for IrqGuard { fn drop(&mut self) { - unsafe { api::__release_irq_guard(self.0) } + unsafe { + ArchitectureImpl::set_interrupt_mask(self.0); + } } } diff --git a/libk/src/runtime/task_queue.rs b/libk/src/runtime/task_queue.rs index c7d01496..fa5cf6fe 100644 --- a/libk/src/runtime/task_queue.rs +++ b/libk/src/runtime/task_queue.rs @@ -41,7 +41,7 @@ impl TaskQueue { pub fn dequeue(&self) -> Result, Error> { let thread = Thread::current(); - // assert!(ArchitectureImpl::interrupt_mask()); + // assert!(PlatformImpl::interrupt_mask()); loop { if let Some(task) = self.task_queue.pop() { return Ok(task); diff --git a/src/arch/aarch64/boot/mod.rs b/src/arch/aarch64/boot/mod.rs index f17d608d..131ea423 100644 --- a/src/arch/aarch64/boot/mod.rs +++ b/src/arch/aarch64/boot/mod.rs @@ -5,6 +5,8 @@ use aarch64_cpu::{ asm::barrier, registers::{CPACR_EL1, ID_AA64MMFR0_EL1, MAIR_EL1, SCTLR_EL1, TCR_EL1, TTBR0_EL1}, }; +use kernel_arch::absolute_address; +use kernel_arch::{Architecture, ArchitectureImpl}; use kernel_fs::devfs; use libk::runtime; use libk_mm::{ @@ -14,11 +16,11 @@ use libk_mm::{ use tock_registers::interfaces::{ReadWriteable, Readable, Writeable}; use super::{ - exception, mem::load_fixed_tables, smp::CPU_COUNT, AArch64, BootStack, ARCHITECTURE, - BOOT_STACK_SIZE, + exception, mem::load_fixed_tables, smp::CPU_COUNT, AArch64, BootStack, BOOT_STACK_SIZE, + PLATFORM, }; use crate::{ - arch::{aarch64::mem::table::L3, Architecture}, + arch::{aarch64::mem::table::L3, Platform}, kernel_main, kernel_secondary_main, mem::{phys, KERNEL_VIRT_OFFSET}, }; @@ -75,7 +77,7 @@ unsafe fn enter_higher_half(sp: usize, elr: usize, x0: usize) -> ! { // NOTE executes in "lower-half" address space, MMU not yet enabled unsafe extern "C" fn __aarch64_el1_bsp_lower_entry(dtb: PhysicalAddress) -> ! { - AArch64::set_interrupt_mask(true); + ArchitectureImpl::set_interrupt_mask(true); // Don't trap FP operations CPACR_EL1.modify(CPACR_EL1::FPEN::TrapNothing); @@ -98,7 +100,7 @@ unsafe extern "C" fn __aarch64_bsp_upper_entry(dtb: PhysicalAddress) -> ! { TTBR0_EL1.set(0); // Setup the "runtime" part of the kernel tables - ARCHITECTURE + PLATFORM .init_memory_management(dtb) .expect("Could not initialize memory management"); barrier::isb(barrier::SY); @@ -110,7 +112,7 @@ unsafe extern "C" fn __aarch64_bsp_upper_entry(dtb: PhysicalAddress) -> ! { runtime::init_task_queue(); // Initialize the BSP CPU + the devices - ARCHITECTURE + PLATFORM .init_platform(true) .expect("Could not initialize the platform"); @@ -119,7 +121,7 @@ unsafe extern "C" fn __aarch64_bsp_upper_entry(dtb: PhysicalAddress) -> ! { unsafe extern "C" fn __aarch64_el1_ap_lower_entry() -> ! { const AP_STACK_PAGES: usize = 8; - AArch64::set_interrupt_mask(true); + ArchitectureImpl::set_interrupt_mask(true); // Unmask FP operations CPACR_EL1.modify(CPACR_EL1::FPEN::TrapNothing); @@ -149,7 +151,7 @@ extern "C" fn __aarch64_ap_upper_entry() -> ! { exception::init_exceptions(); unsafe { - ARCHITECTURE + PLATFORM .init_platform(false) .expect("Could not initialize the AP"); } diff --git a/src/arch/aarch64/exception.rs b/src/arch/aarch64/exception.rs index 5962b9a1..b784f86f 100644 --- a/src/arch/aarch64/exception.rs +++ b/src/arch/aarch64/exception.rs @@ -13,16 +13,17 @@ use abi::{ process::{Signal, SignalEntryData}, syscall::SyscallFunction, }; +use kernel_arch::{Architecture, ArchitectureImpl}; use tock_registers::interfaces::{Readable, Writeable}; use crate::{ - arch::{Architecture, ArchitectureImpl}, + arch::{Platform, PlatformImpl}, debug::LogLevel, syscall::raw_syscall_handler, task::{context::TaskFrame, thread::Thread}, }; -use super::ARCHITECTURE; +use super::PLATFORM; /// Struct for register values saved when taking an exception #[repr(C)] @@ -351,7 +352,7 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) { } fn irq_common() { - ARCHITECTURE + PLATFORM .external_interrupt_controller() .handle_pending_irqs(); } diff --git a/src/arch/aarch64/gic/mod.rs b/src/arch/aarch64/gic/mod.rs index 03730947..46c0c0d1 100644 --- a/src/arch/aarch64/gic/mod.rs +++ b/src/arch/aarch64/gic/mod.rs @@ -20,11 +20,11 @@ use libk_mm::{ }; use libk_util::{sync::IrqSafeSpinlock, OneTimeInit}; -use crate::arch::{aarch64::IrqNumber, Architecture, CpuAccess, CpuMessage}; +use crate::arch::{aarch64::IrqNumber, CpuAccess, CpuMessage, Platform}; use self::{gicc::Gicc, gicd::Gicd}; -use super::{cpu::Cpu, smp::CPU_COUNT, ARCHITECTURE}; +use super::{cpu::Cpu, smp::CPU_COUNT, PLATFORM}; const MAX_IRQ: usize = 300; const IPI_VECTOR: u64 = 1; @@ -68,9 +68,9 @@ impl Device for Gic { self.gicd.init(gicd); self.gicc.init(gicc); - ARCHITECTURE.register_external_interrupt_controller(self)?; - ARCHITECTURE.register_local_interrupt_controller(self)?; - ARCHITECTURE.register_message_interrupt_controller(self)?; + PLATFORM.register_external_interrupt_controller(self)?; + PLATFORM.register_local_interrupt_controller(self)?; + PLATFORM.register_message_interrupt_controller(self)?; Ok(()) } diff --git a/src/arch/aarch64/mod.rs b/src/arch/aarch64/mod.rs index 04f6dab3..910a0fed 100644 --- a/src/arch/aarch64/mod.rs +++ b/src/arch/aarch64/mod.rs @@ -43,7 +43,7 @@ use crate::{ use self::mem::{table::L1, EarlyMapping}; -use super::{Architecture, CpuMessage}; +use super::{CpuMessage, Platform}; pub mod boot; pub mod context; @@ -78,7 +78,7 @@ pub struct AArch64 { initrd: OneTimeInit>, } -impl Architecture for AArch64 { +impl Platform for AArch64 { const KERNEL_VIRT_OFFSET: usize = 0xFFFFFF8000000000; type IrqNumber = IrqNumber; @@ -96,22 +96,6 @@ impl Architecture for AArch64 { smp::CPU_COUNT.load(Ordering::Acquire) } - unsafe fn set_interrupt_mask(mask: bool) { - if mask { - DAIF.modify(DAIF::I::SET); - } else { - DAIF.modify(DAIF::I::CLEAR); - } - } - - fn interrupt_mask() -> bool { - DAIF.read(DAIF::I) != 0 - } - - fn wait_for_interrupt() { - aarch64_cpu::asm::wfi(); - } - unsafe fn map_device_memory( &self, base: PhysicalAddress, @@ -455,7 +439,7 @@ impl AArch64 { } /// AArch64 implementation value -pub static ARCHITECTURE: AArch64 = AArch64 { +pub static PLATFORM: AArch64 = AArch64 { dt: OneTimeInit::new(), initrd: OneTimeInit::new(), diff --git a/src/arch/aarch64/smp.rs b/src/arch/aarch64/smp.rs index f3144442..829793e4 100644 --- a/src/arch/aarch64/smp.rs +++ b/src/arch/aarch64/smp.rs @@ -5,7 +5,7 @@ use abi::error::Error; use device_api::CpuBringupDevice; use device_tree::dt::{DevTreeIndexNodePropGet, DeviceTree}; -use crate::arch::ARCHITECTURE; +use crate::arch::PLATFORM; use crate::mem::KERNEL_VIRT_OFFSET; use super::{BootStack, BOOT_STACK_SIZE}; @@ -50,7 +50,7 @@ impl CpuEnableMethod { unsafe fn start_cpu(&self, id: usize, ip: usize, sp: usize) -> Result<(), Error> { match self { Self::Psci => { - let psci = ARCHITECTURE.psci.try_get().ok_or_else(|| { + let psci = PLATFORM.psci.try_get().ok_or_else(|| { warnln!( "cpu{} has to be enabled through PSCI, but no PSCI found", id diff --git a/src/arch/aarch64/timer.rs b/src/arch/aarch64/timer.rs index b20087d2..d06113d4 100644 --- a/src/arch/aarch64/timer.rs +++ b/src/arch/aarch64/timer.rs @@ -10,7 +10,7 @@ use device_tree::device_tree_driver; use libk::runtime; use tock_registers::interfaces::{ReadWriteable, Readable, Writeable}; -use crate::arch::{aarch64::IrqNumber, Architecture, CpuAccess, ARCHITECTURE}; +use crate::arch::{aarch64::IrqNumber, CpuAccess, Platform, PLATFORM}; use super::cpu::Cpu; @@ -53,12 +53,12 @@ impl Device for ArmTimer { unsafe fn init(&'static self) -> Result<(), Error> { CNTP_CTL_EL0.write(CNTP_CTL_EL0::ENABLE::SET + CNTP_CTL_EL0::IMASK::SET); - ARCHITECTURE.register_monotonic_timer(self)?; + PLATFORM.register_monotonic_timer(self)?; Ok(()) } unsafe fn init_irq(&'static self) -> Result<(), Error> { - let intc = ARCHITECTURE.external_interrupt_controller(); + let intc = PLATFORM.external_interrupt_controller(); intc.register_irq(self.irq, Default::default(), self)?; diff --git a/src/arch/mod.rs b/src/arch/mod.rs index d133c3d8..51532302 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -4,23 +4,6 @@ use core::{ops::DerefMut, time::Duration}; use abi::error::Error; -/// Returns an absolute address to the given symbol -#[macro_export] -macro_rules! absolute_address { - ($sym:expr) => {{ - let mut _x: usize; - #[cfg(target_arch = "aarch64")] - unsafe { - core::arch::asm!("ldr {0}, ={1}", out(reg) _x, sym $sym); - } - #[cfg(target_arch = "x86_64")] - unsafe { - core::arch::asm!("movabsq ${1}, {0}", out(reg) _x, sym $sym, options(att_syntax)); - } - _x - }}; -} - use cfg_if::cfg_if; use device_api::{ interrupt::{ @@ -30,6 +13,7 @@ use device_api::{ timer::MonotonicTimestampProviderDevice, ResetDevice, }; +use kernel_arch::{Architecture, ArchitectureImpl}; use libk_mm::{ address::PhysicalAddress, device::{DeviceMemoryAttributes, RawDeviceMemoryMapping}, @@ -44,18 +28,18 @@ cfg_if! { if #[cfg(target_arch = "aarch64")] { pub mod aarch64; - pub use aarch64::{AArch64 as ArchitectureImpl, ARCHITECTURE}; + pub use aarch64::{AArch64 as PlatformImpl, PLATFORM}; } else if #[cfg(target_arch = "x86_64")] { pub mod x86_64; - pub use x86_64::{X86_64 as ArchitectureImpl, ARCHITECTURE}; + pub use x86_64::{X86_64 as PlatformImpl, PLATFORM}; } else { compile_error!("Architecture is not supported"); } } /// Architecture-specific lowest level of page mapping -pub type L3 = ::L3; +pub type L3 = ::L3; // Architecture interfaces @@ -72,7 +56,7 @@ pub enum CpuMessage { /// Interface for an architecture-specific facilities #[allow(unused)] -pub trait Architecture { +pub trait Platform { /// Address, to which "zero" address is mapped in the virtual address space const KERNEL_VIRT_OFFSET: usize; @@ -125,20 +109,6 @@ pub trait Architecture { // Architecture intrinsics - /// Suspends CPU until an interrupt is received - fn wait_for_interrupt(); - - /// Sets the local CPU's interrupt mask. - /// - /// # Safety - /// - /// Enabling interrupts may lead to unexpected behavior unless the context explicitly expects - /// them. - unsafe fn set_interrupt_mask(mask: bool); - - /// Returns the local CPU's interrupt mask - fn interrupt_mask() -> bool; - /// Returns the count of present CPUs, including the BSP fn cpu_count() -> usize; @@ -225,9 +195,9 @@ pub trait Architecture { /// The caller must ensure it is actually safe to reset, i.e. no critical processes will be /// aborted and no data will be lost. unsafe fn reset(&self) -> ! { - Self::set_interrupt_mask(true); + ArchitectureImpl::set_interrupt_mask(true); loop { - Self::wait_for_interrupt(); + ArchitectureImpl::wait_for_interrupt(); } } } @@ -300,22 +270,6 @@ pub trait CpuAccess: Sized { // External API for architecture specifics -#[no_mangle] -fn __acquire_irq_guard() -> bool { - let mask = ArchitectureImpl::interrupt_mask(); - unsafe { - ArchitectureImpl::set_interrupt_mask(true); - } - mask -} - -#[no_mangle] -fn __release_irq_guard(mask: bool) { - unsafe { - ArchitectureImpl::set_interrupt_mask(mask); - } -} - #[no_mangle] fn __cpu_index() -> usize { Cpu::local().id() as _ @@ -323,17 +277,17 @@ fn __cpu_index() -> usize { #[no_mangle] fn __cpu_count() -> usize { - ArchitectureImpl::cpu_count() + PlatformImpl::cpu_count() } #[no_mangle] fn __virtualize(addr: u64) -> usize { - ArchitectureImpl::virtualize(addr) + PlatformImpl::virtualize(addr) } #[no_mangle] fn __physicalize(addr: usize) -> u64 { - ArchitectureImpl::physicalize(addr) + PlatformImpl::physicalize(addr) } #[no_mangle] @@ -342,21 +296,21 @@ fn __map_device_pages( count: usize, attrs: DeviceMemoryAttributes, ) -> Result { - unsafe { ARCHITECTURE.map_device_memory(base, count, attrs) } + unsafe { PLATFORM.map_device_memory(base, count, attrs) } } #[no_mangle] fn __unmap_device_pages(mapping: &RawDeviceMemoryMapping) { - unsafe { ARCHITECTURE.unmap_device_memory(mapping) } + unsafe { PLATFORM.unmap_device_memory(mapping) } } #[no_mangle] fn __monotonic_timestamp() -> Result { - ARCHITECTURE.monotonic_timer().monotonic_timestamp() + PLATFORM.monotonic_timer().monotonic_timestamp() } #[no_mangle] fn __message_interrupt_controller() -> &'static dyn MessageInterruptController { - ARCHITECTURE.message_interrupt_controller() + PLATFORM.message_interrupt_controller() } #[no_mangle] @@ -365,7 +319,7 @@ fn __register_global_interrupt( options: IrqOptions, handler: &'static dyn InterruptHandler, ) -> Result<(), Error> { - let intc = ARCHITECTURE.external_interrupt_controller(); + let intc = PLATFORM.external_interrupt_controller(); let irq = { #[cfg(target_arch = "aarch64")] diff --git a/src/arch/x86_64/acpi.rs b/src/arch/x86_64/acpi.rs index b679e643..323f7d70 100644 --- a/src/arch/x86_64/acpi.rs +++ b/src/arch/x86_64/acpi.rs @@ -25,7 +25,7 @@ use yggdrasil_abi::error::Error; use crate::{ arch::{ x86_64::{smp::CPU_COUNT, IrqNumber, SHUTDOWN_FENCE}, - Architecture, CpuMessage, ARCHITECTURE, + CpuMessage, Platform, PLATFORM, }, mem::{heap::GLOBAL_HEAP, read_memory, write_memory}, }; @@ -169,7 +169,7 @@ impl acpi_system::Handler for AcpiHandlerImpl { fn install_interrupt_handler(irq: u32) -> Result<(), AcpiSystemError> { infoln!("Installing ACPI SCI handler at IRQ #{}", irq); - let intc = ARCHITECTURE.external_interrupt_controller(); + let intc = PLATFORM.external_interrupt_controller(); let handler = Box::leak(Box::new(SciHandler)); let irq = IrqNumber::Isa(irq as _); @@ -360,7 +360,7 @@ pub fn init_acpi(tables: &'static AcpiTables) -> Result<(), Err // 7. Actually enter the S5 state unsafe { - ARCHITECTURE + PLATFORM .send_ipi(IpiDeliveryTarget::OtherCpus, CpuMessage::Shutdown) .unwrap(); } diff --git a/src/arch/x86_64/apic/mod.rs b/src/arch/x86_64/apic/mod.rs index d816d388..d4a3132c 100644 --- a/src/arch/x86_64/apic/mod.rs +++ b/src/arch/x86_64/apic/mod.rs @@ -5,13 +5,13 @@ use core::arch::global_asm; use static_assertions::{const_assert, const_assert_eq}; use crate::{ - arch::{x86_64::cpu::Cpu, Architecture, CpuAccess}, + arch::{x86_64::cpu::Cpu, CpuAccess, Platform}, task::thread::Thread, }; use super::{ exception::{self, IrqFrame}, - ARCHITECTURE, + PLATFORM, }; pub mod ioapic; @@ -67,7 +67,7 @@ unsafe extern "C" fn irq_handler(vector: usize, frame: *mut IrqFrame) { let cpu = Cpu::local(); let frame = &mut *frame; - ARCHITECTURE + PLATFORM .external_interrupt_controller() .handle_specific_irq(vector); cpu.local_apic().clear_interrupt(); @@ -85,7 +85,7 @@ unsafe extern "C" fn msi_handler(vector: usize, frame: *mut IrqFrame) { let cpu = Cpu::local(); let frame = &mut *frame; - ARCHITECTURE + PLATFORM .message_interrupt_controller() .handle_msi(vector); cpu.local_apic().clear_interrupt(); diff --git a/src/arch/x86_64/boot/mod.rs b/src/arch/x86_64/boot/mod.rs index a19ce8f7..8d6c03e8 100644 --- a/src/arch/x86_64/boot/mod.rs +++ b/src/arch/x86_64/boot/mod.rs @@ -15,7 +15,7 @@ use crate::{ mem::KERNEL_VIRT_OFFSET, }; -use super::{cpuid::init_cpuid, exception, ARCHITECTURE}; +use super::{cpuid::init_cpuid, exception, PLATFORM}; pub enum BootData { YBoot(&'static LoadProtocolV1), @@ -79,14 +79,14 @@ extern "C" fn __x86_64_upper_entry() -> ! { init_dummy_cpu(); } - ARCHITECTURE.set_boot_data(BootData::YBoot(&YBOOT_DATA)); + PLATFORM.set_boot_data(BootData::YBoot(&YBOOT_DATA)); // Gather available CPU features init_cpuid(); // Setup memory management: kernel virtual memory tables, physical page manager and heap unsafe { - ARCHITECTURE + PLATFORM .init_memory_management() .expect("Could not initialize memory management"); } @@ -102,7 +102,7 @@ extern "C" fn __x86_64_upper_entry() -> ! { // Initializes: local CPU, platform devices (timers/serials/etc), debug output unsafe { - ARCHITECTURE + PLATFORM .init_platform(0) .expect("Could not initialize the platform"); } @@ -125,7 +125,7 @@ pub extern "C" fn __x86_64_ap_entry() -> ! { // syscall::init_syscall(); exception::init_exceptions(cpu_id); - ARCHITECTURE + PLATFORM .init_platform(cpu_id) .expect("Could not initialize the platform (AP)"); } diff --git a/src/arch/x86_64/exception.rs b/src/arch/x86_64/exception.rs index 3ac46a63..93ad15c4 100644 --- a/src/arch/x86_64/exception.rs +++ b/src/arch/x86_64/exception.rs @@ -13,7 +13,7 @@ use crate::{ task::{context::TaskFrame, thread::Thread, Cpu}, }; -use super::ARCHITECTURE; +use super::PLATFORM; primitive_enum! { enum ExceptionKind: u64 { @@ -404,7 +404,7 @@ extern "C" fn __x86_64_exception_handler(frame: *mut ExceptionFrame) { if let Some(msg) = cpu.get_ipi() { unsafe { - ARCHITECTURE.handle_ipi(msg); + PLATFORM.handle_ipi(msg); } } } diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index 7506261c..9f9283b8 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -73,7 +73,7 @@ use self::{ smp::CPU_COUNT, }; -use super::{Architecture, CpuAccess, CpuMessage}; +use super::{CpuAccess, CpuMessage, Platform}; /// x86-64-specific interrupt number #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] @@ -100,7 +100,7 @@ pub struct X86_64 { static SHUTDOWN_FENCE: SpinFence = SpinFence::new(); /// Global x86-64 architecture value -pub static ARCHITECTURE: X86_64 = X86_64 { +pub static PLATFORM: X86_64 = X86_64 { boot_data: OneTimeInit::new(), acpi: OneTimeInit::new(), @@ -111,7 +111,7 @@ pub static ARCHITECTURE: X86_64 = X86_64 { timer: OneTimeInit::new(), }; -impl Architecture for X86_64 { +impl Platform for X86_64 { const KERNEL_VIRT_OFFSET: usize = 0xFFFFFF8000000000; type IrqNumber = IrqNumber; type L3 = mem::table::L3; @@ -134,29 +134,6 @@ impl Architecture for X86_64 { CPU_COUNT.load(Ordering::Acquire) } - unsafe fn set_interrupt_mask(mask: bool) { - if mask { - core::arch::asm!("cli"); - } else { - core::arch::asm!("sti"); - } - } - - fn interrupt_mask() -> bool { - let mut flags: u64; - unsafe { - core::arch::asm!("pushfq; pop {0}", out(reg) flags, options(att_syntax)); - } - // If IF is zero, interrupts are disabled (masked) - flags & (1 << 9) == 0 - } - - fn wait_for_interrupt() { - unsafe { - core::arch::asm!("hlt"); - } - } - #[inline] unsafe fn map_device_memory( &self, diff --git a/src/arch/x86_64/peripherals/i8253.rs b/src/arch/x86_64/peripherals/i8253.rs index 3ee5357d..dbe63084 100644 --- a/src/arch/x86_64/peripherals/i8253.rs +++ b/src/arch/x86_64/peripherals/i8253.rs @@ -10,7 +10,7 @@ use crate::arch::{ intrinsics::{IoPort, IoPortAccess}, IrqNumber, }, - Architecture, ARCHITECTURE, + Platform, PLATFORM, }; const FREQUENCY: u32 = 1193180; @@ -62,7 +62,7 @@ impl Device for I8253 { } unsafe fn init_irq(&'static self) -> Result<(), Error> { - let intc = ARCHITECTURE.external_interrupt_controller(); + let intc = PLATFORM.external_interrupt_controller(); let inner = self.inner.lock(); let div: u16 = (FREQUENCY / 1000).try_into().unwrap(); diff --git a/src/arch/x86_64/peripherals/ps2/mod.rs b/src/arch/x86_64/peripherals/ps2/mod.rs index 77964744..c78be67f 100644 --- a/src/arch/x86_64/peripherals/ps2/mod.rs +++ b/src/arch/x86_64/peripherals/ps2/mod.rs @@ -13,7 +13,7 @@ use crate::{ peripherals::ps2::codeset::{CODE_SET_1_00, CODE_SET_1_E0}, IrqNumber, }, - Architecture, ARCHITECTURE, + Platform, PLATFORM, }, device::input, }; @@ -121,7 +121,7 @@ impl Device for PS2Controller { unsafe fn init_irq(&'static self) -> Result<(), Error> { let mut inner = self.inner.lock(); // let intc = PLATFORM.interrupt_controller(); - let intc = ARCHITECTURE.external_interrupt_controller(); + let intc = PLATFORM.external_interrupt_controller(); intc.register_irq(self.primary_irq, Default::default(), self)?; diff --git a/src/arch/x86_64/smp.rs b/src/arch/x86_64/smp.rs index d1066e66..c594cf89 100644 --- a/src/arch/x86_64/smp.rs +++ b/src/arch/x86_64/smp.rs @@ -2,6 +2,7 @@ use core::sync::atomic::{AtomicUsize, Ordering}; use acpi_lib::platform::{ProcessorInfo, ProcessorState}; +use kernel_arch::{Architecture, ArchitectureImpl}; use libk_mm::{ address::{AsPhysicalAddress, FromRaw, IntoRaw, PhysicalAddress}, pointer::PhysicalRefMut, @@ -17,7 +18,7 @@ use crate::{ KERNEL_TABLES, }, }, - Architecture, ArchitectureImpl, CpuAccess, + CpuAccess, }, mem::phys, task::Cpu, diff --git a/src/device/power/arm_psci.rs b/src/device/power/arm_psci.rs index ca578752..140b44c0 100644 --- a/src/device/power/arm_psci.rs +++ b/src/device/power/arm_psci.rs @@ -4,8 +4,9 @@ use abi::error::Error; use alloc::boxed::Box; use device_api::{CpuBringupDevice, Device, ResetDevice}; use device_tree::{device_tree_driver, dt::DevTreeIndexNodePropGet}; +use kernel_arch::{Architecture, ArchitectureImpl}; -use crate::arch::{Architecture, ArchitectureImpl, ARCHITECTURE}; +use crate::arch::{Platform, PlatformImpl, PLATFORM}; enum CallMethod { Hvc, @@ -28,7 +29,7 @@ impl Device for Psci { } unsafe fn init(&'static self) -> Result<(), Error> { - ARCHITECTURE.psci.init(self); + PLATFORM.psci.init(self); Ok(()) } } diff --git a/src/device/power/sunxi_rwdog.rs b/src/device/power/sunxi_rwdog.rs index 450b5145..a8868427 100644 --- a/src/device/power/sunxi_rwdog.rs +++ b/src/device/power/sunxi_rwdog.rs @@ -9,7 +9,7 @@ use tock_registers::{ }; use crate::{ - arch::{Architecture, ARCHITECTURE}, + arch::{Architecture, PLATFORM}, device::devtree::{self, DevTreeIndexNodePropGet, DevTreeIndexPropExt}, device_tree_driver, mem::device::DeviceMemoryIo, @@ -81,7 +81,7 @@ impl Device for RWdog { self.inner.init(IrqSafeSpinlock::new(Inner { regs })); - ARCHITECTURE.register_reset_device(self)?; + PLATFORM.register_reset_device(self)?; Ok(()) } diff --git a/src/device/serial/pl011.rs b/src/device/serial/pl011.rs index cb57042c..fb6e0133 100644 --- a/src/device/serial/pl011.rs +++ b/src/device/serial/pl011.rs @@ -19,7 +19,7 @@ use tock_registers::{ use vfs::{CharDevice, FileReadiness}; use crate::{ - arch::{aarch64::IrqNumber, Architecture, ARCHITECTURE}, + arch::{aarch64::IrqNumber, Platform, PLATFORM}, debug::{self, DebugSink, LogLevel}, device::tty::{TtyContext, TtyDevice}, task::process::ProcessId, @@ -221,7 +221,7 @@ impl Device for Pl011 { } unsafe fn init_irq(&'static self) -> Result<(), Error> { - let intc = ARCHITECTURE.external_interrupt_controller(); + let intc = PLATFORM.external_interrupt_controller(); intc.register_irq(self.irq, Default::default(), self)?; self.inner.get().lock().regs.IMSC.modify(IMSC::RXIM::SET); diff --git a/src/device/serial/sunxi_uart.rs b/src/device/serial/sunxi_uart.rs index e340fd69..79fac776 100644 --- a/src/device/serial/sunxi_uart.rs +++ b/src/device/serial/sunxi_uart.rs @@ -12,7 +12,7 @@ use tock_registers::{ use vfs::CharDevice; use crate::{ - arch::{aarch64::IrqNumber, Architecture, ARCHITECTURE}, + arch::{aarch64::IrqNumber, Architecture, PLATFORM}, debug::{self, DebugSink, LogLevel}, device::{ devtree::{self, DevTreeIndexPropExt}, @@ -173,7 +173,7 @@ impl Device for SunxiUart { } unsafe fn init_irq(&'static self) -> Result<(), Error> { - let intc = ARCHITECTURE.external_interrupt_controller(); + let intc = PLATFORM.external_interrupt_controller(); intc.register_irq(self.irq, Default::default(), self)?; intc.enable_irq(self.irq)?; diff --git a/src/main.rs b/src/main.rs index 385ffed2..0631189f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -38,11 +38,11 @@ #![no_std] #![no_main] -use arch::Architecture; +use arch::Platform; use libk_util::sync::SpinFence; use crate::{ - arch::{ArchitectureImpl, ARCHITECTURE}, + arch::{PlatformImpl, PLATFORM}, fs::sysfs, mem::heap, task::{spawn_kernel_closure, Cpu}, @@ -74,7 +74,7 @@ static CPU_INIT_FENCE: SpinFence = SpinFence::new(); pub fn kernel_secondary_main() -> ! { // Synchronize the CPUs to this point CPU_INIT_FENCE.signal(); - CPU_INIT_FENCE.wait_all(ArchitectureImpl::cpu_count()); + CPU_INIT_FENCE.wait_all(PlatformImpl::cpu_count()); unsafe { task::enter(); @@ -100,14 +100,14 @@ pub fn kernel_main() -> ! { fs::add_pseudo_devices().unwrap(); unsafe { - ARCHITECTURE.start_application_processors(); + PLATFORM.start_application_processors(); } Cpu::init_ipi_queues(); // Wait until all APs initialize CPU_INIT_FENCE.signal(); - CPU_INIT_FENCE.wait_all(ArchitectureImpl::cpu_count()); + CPU_INIT_FENCE.wait_all(PlatformImpl::cpu_count()); task::init().expect("Failed to initialize the scheduler"); diff --git a/src/mem/mod.rs b/src/mem/mod.rs index 8d63b161..7ee410ae 100644 --- a/src/mem/mod.rs +++ b/src/mem/mod.rs @@ -9,7 +9,7 @@ use core::{ use abi::error::Error; use libk_mm::{address::PhysicalAddress, device::DeviceMemoryMapping}; -use crate::arch::{Architecture, ArchitectureImpl}; +use crate::arch::{PlatformImpl, Platform}; pub mod address; pub mod heap; @@ -20,7 +20,7 @@ pub mod table; use self::process::ProcessAddressSpace; /// Offset applied to the physical kernel image when translating it into the virtual address space -pub const KERNEL_VIRT_OFFSET: usize = ArchitectureImpl::KERNEL_VIRT_OFFSET; +pub const KERNEL_VIRT_OFFSET: usize = PlatformImpl::KERNEL_VIRT_OFFSET; /// Reads a value from an arbitrary physical address. /// diff --git a/src/mem/phys/mod.rs b/src/mem/phys/mod.rs index 98eb1506..00dbae0b 100644 --- a/src/mem/phys/mod.rs +++ b/src/mem/phys/mod.rs @@ -1,6 +1,7 @@ //! Physical memory management utilities use abi::{error::Error, system::SystemMemoryStats}; +use kernel_arch::absolute_address; use libk_mm::{ address::{FromRaw, IntoRaw, PhysicalAddress}, phys::PhysicalMemoryRegion, @@ -8,7 +9,7 @@ use libk_mm::{ use libk_util::{sync::IrqSafeSpinlock, OneTimeInit}; use crate::{ - arch::{Architecture, ARCHITECTURE}, + arch::{Platform, PLATFORM}, mem::phys::reserved::is_reserved, }; @@ -122,7 +123,7 @@ pub unsafe fn init_from_iter + Clone>( reserve_region("kernel", kernel_physical_memory_region()); - ARCHITECTURE.map_physical_memory(it.clone(), phys_start, phys_end)?; + PLATFORM.map_physical_memory(it.clone(), phys_start, phys_end)?; let total_count = (phys_end - phys_start) / 0x1000; let page_bitmap_size = (total_count + BITMAP_WORD_SIZE - 1) / (BITMAP_WORD_SIZE / 8); diff --git a/src/panic.rs b/src/panic.rs index e1c880cd..35a63aa2 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -2,10 +2,11 @@ use core::sync::atomic::{AtomicBool, AtomicU32, Ordering}; use device_api::interrupt::IpiDeliveryTarget; +use kernel_arch::{Architecture, ArchitectureImpl}; use libk_util::sync::{hack_locks, SpinFence}; use crate::{ - arch::{Architecture, ArchitectureImpl, CpuAccess, CpuMessage, ARCHITECTURE}, + arch::{CpuAccess, CpuMessage, Platform, PlatformImpl, PLATFORM}, debug::{debug_internal, LogLevel}, device::display::console::flush_consoles, task::Cpu, @@ -53,12 +54,12 @@ fn panic_handler(pi: &core::panic::PanicInfo) -> ! { { // Let other CPUs know we're screwed unsafe { - ARCHITECTURE + PLATFORM .send_ipi(IpiDeliveryTarget::OtherCpus, CpuMessage::Panic) .ok(); } - let ap_count = ArchitectureImpl::cpu_count() - 1; + let ap_count = PlatformImpl::cpu_count() - 1; PANIC_HANDLED_FENCE.wait_all(ap_count); unsafe { @@ -101,7 +102,7 @@ fn panic_handler(pi: &core::panic::PanicInfo) -> ! { PANIC_SEQUENCE.fetch_add(1, Ordering::Release); unsafe { - ARCHITECTURE.reset(); + PLATFORM.reset(); } } diff --git a/src/proc/random.rs b/src/proc/random.rs index 2f8c3ddb..c9340947 100644 --- a/src/proc/random.rs +++ b/src/proc/random.rs @@ -2,7 +2,7 @@ use libk_util::{sync::IrqSafeSpinlock, OneTimeInit}; -use crate::arch::{Architecture, ARCHITECTURE}; +use crate::arch::{Platform, PLATFORM}; const BUFFER_SIZE: usize = 1024; @@ -67,7 +67,7 @@ pub fn read(buf: &mut [u8]) { /// Initializes the random generator state pub fn init() { - let now = ARCHITECTURE + let now = PLATFORM .monotonic_timer() .monotonic_timestamp() .unwrap(); diff --git a/src/task/mod.rs b/src/task/mod.rs index e40dc062..2df94a87 100644 --- a/src/task/mod.rs +++ b/src/task/mod.rs @@ -8,7 +8,7 @@ use libk::{runtime, thread::Termination}; use libk_util::sync::SpinFence; use crate::{ - arch::{Architecture, ArchitectureImpl, CpuAccess}, + arch::{PlatformImpl, CpuAccess, Platform}, task::{sched::CpuQueue, thread::Thread}, }; @@ -35,7 +35,7 @@ pub fn spawn_kernel_closure, T: Termination, F: Fn() -> T + Send /// Sets up CPU queues and gives them some processes to run pub fn init() -> Result<(), Error> { - let cpu_count = ArchitectureImpl::cpu_count(); + let cpu_count = PlatformImpl::cpu_count(); // Create a queue for each CPU sched::init_queues(Vec::from_iter((0..cpu_count).map(CpuQueue::new))); diff --git a/src/task/sched.rs b/src/task/sched.rs index 2e1be619..7ba464e1 100644 --- a/src/task/sched.rs +++ b/src/task/sched.rs @@ -5,12 +5,10 @@ use core::cell::Cell; use alloc::{sync::Arc, vec::Vec}; use cfg_if::cfg_if; use crossbeam_queue::SegQueue; +use kernel_arch::{Architecture, ArchitectureImpl}; use libk_util::{sync::IrqGuard, OneTimeInit}; -use crate::{ - arch::{Architecture, ArchitectureImpl, CpuAccess}, - task::thread::ThreadState, -}; +use crate::{arch::CpuAccess, task::thread::ThreadState}; use super::{ context::TaskContextImpl,