libk: move trivial arch stuff to kernel-arch
This commit is contained in:
parent
72b8967339
commit
b653ec3c4a
@ -20,6 +20,8 @@ memtables = { path = "lib/memtables" }
|
|||||||
vmalloc = { path = "lib/vmalloc" }
|
vmalloc = { path = "lib/vmalloc" }
|
||||||
device-api-macros = { path = "lib/device-api/macros" }
|
device-api-macros = { path = "lib/device-api/macros" }
|
||||||
|
|
||||||
|
kernel-arch = { path = "arch" }
|
||||||
|
|
||||||
# Drivers
|
# Drivers
|
||||||
ygg_driver_pci = { path = "driver/bus/pci" }
|
ygg_driver_pci = { path = "driver/bus/pci" }
|
||||||
ygg_driver_block = { path = "driver/block/core" }
|
ygg_driver_block = { path = "driver/block/core" }
|
||||||
|
17
arch/Cargo.toml
Normal file
17
arch/Cargo.toml
Normal file
@ -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"
|
12
arch/aarch64/Cargo.toml
Normal file
12
arch/aarch64/Cargo.toml
Normal file
@ -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"
|
27
arch/aarch64/src/lib.rs
Normal file
27
arch/aarch64/src/lib.rs
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
8
arch/interface/Cargo.toml
Normal file
8
arch/interface/Cargo.toml
Normal file
@ -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]
|
9
arch/interface/src/lib.rs
Normal file
9
arch/interface/src/lib.rs
Normal file
@ -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();
|
||||||
|
}
|
34
arch/src/lib.rs
Normal file
34
arch/src/lib.rs
Normal file
@ -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;
|
9
arch/x86_64/Cargo.toml
Normal file
9
arch/x86_64/Cargo.toml
Normal file
@ -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" }
|
33
arch/x86_64/src/lib.rs
Normal file
33
arch/x86_64/src/lib.rs
Normal file
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" }
|
yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" }
|
||||||
|
kernel-arch = { path = "../arch" }
|
||||||
|
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
crossbeam-queue = { version = "0.3.8", default-features = false, features = ["alloc"] }
|
crossbeam-queue = { version = "0.3.8", default-features = false, features = ["alloc"] }
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
extern "Rust" {
|
|
||||||
pub fn __acquire_irq_guard() -> bool;
|
|
||||||
pub fn __release_irq_guard(mask: bool);
|
|
||||||
}
|
|
@ -11,8 +11,6 @@ use core::{
|
|||||||
sync::atomic::{AtomicUsize, Ordering},
|
sync::atomic::{AtomicUsize, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) mod api;
|
|
||||||
|
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod queue;
|
pub mod queue;
|
||||||
pub mod ring;
|
pub mod ring;
|
||||||
|
@ -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
|
/// 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.
|
/// (if enabled before) is resumed when [IrqGuard]'s lifetime is over.
|
||||||
@ -8,12 +8,15 @@ pub struct IrqGuard(bool);
|
|||||||
impl IrqGuard {
|
impl IrqGuard {
|
||||||
/// Saves the current IRQ state and masks them
|
/// Saves the current IRQ state and masks them
|
||||||
pub fn acquire() -> Self {
|
pub fn acquire() -> Self {
|
||||||
Self(unsafe { api::__acquire_irq_guard() })
|
let mask = unsafe { ArchitectureImpl::set_interrupt_mask(true) };
|
||||||
|
Self(mask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for IrqGuard {
|
impl Drop for IrqGuard {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe { api::__release_irq_guard(self.0) }
|
unsafe {
|
||||||
|
ArchitectureImpl::set_interrupt_mask(self.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ impl TaskQueue {
|
|||||||
|
|
||||||
pub fn dequeue(&self) -> Result<Arc<Task>, Error> {
|
pub fn dequeue(&self) -> Result<Arc<Task>, Error> {
|
||||||
let thread = Thread::current();
|
let thread = Thread::current();
|
||||||
// assert!(ArchitectureImpl::interrupt_mask());
|
// assert!(PlatformImpl::interrupt_mask());
|
||||||
loop {
|
loop {
|
||||||
if let Some(task) = self.task_queue.pop() {
|
if let Some(task) = self.task_queue.pop() {
|
||||||
return Ok(task);
|
return Ok(task);
|
||||||
|
@ -5,6 +5,8 @@ use aarch64_cpu::{
|
|||||||
asm::barrier,
|
asm::barrier,
|
||||||
registers::{CPACR_EL1, ID_AA64MMFR0_EL1, MAIR_EL1, SCTLR_EL1, TCR_EL1, TTBR0_EL1},
|
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 kernel_fs::devfs;
|
||||||
use libk::runtime;
|
use libk::runtime;
|
||||||
use libk_mm::{
|
use libk_mm::{
|
||||||
@ -14,11 +16,11 @@ use libk_mm::{
|
|||||||
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
|
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
exception, mem::load_fixed_tables, smp::CPU_COUNT, AArch64, BootStack, ARCHITECTURE,
|
exception, mem::load_fixed_tables, smp::CPU_COUNT, AArch64, BootStack, BOOT_STACK_SIZE,
|
||||||
BOOT_STACK_SIZE,
|
PLATFORM,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{aarch64::mem::table::L3, Architecture},
|
arch::{aarch64::mem::table::L3, Platform},
|
||||||
kernel_main, kernel_secondary_main,
|
kernel_main, kernel_secondary_main,
|
||||||
mem::{phys, KERNEL_VIRT_OFFSET},
|
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
|
// NOTE executes in "lower-half" address space, MMU not yet enabled
|
||||||
unsafe extern "C" fn __aarch64_el1_bsp_lower_entry(dtb: PhysicalAddress) -> ! {
|
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
|
// Don't trap FP operations
|
||||||
CPACR_EL1.modify(CPACR_EL1::FPEN::TrapNothing);
|
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);
|
TTBR0_EL1.set(0);
|
||||||
|
|
||||||
// Setup the "runtime" part of the kernel tables
|
// Setup the "runtime" part of the kernel tables
|
||||||
ARCHITECTURE
|
PLATFORM
|
||||||
.init_memory_management(dtb)
|
.init_memory_management(dtb)
|
||||||
.expect("Could not initialize memory management");
|
.expect("Could not initialize memory management");
|
||||||
barrier::isb(barrier::SY);
|
barrier::isb(barrier::SY);
|
||||||
@ -110,7 +112,7 @@ unsafe extern "C" fn __aarch64_bsp_upper_entry(dtb: PhysicalAddress) -> ! {
|
|||||||
runtime::init_task_queue();
|
runtime::init_task_queue();
|
||||||
|
|
||||||
// Initialize the BSP CPU + the devices
|
// Initialize the BSP CPU + the devices
|
||||||
ARCHITECTURE
|
PLATFORM
|
||||||
.init_platform(true)
|
.init_platform(true)
|
||||||
.expect("Could not initialize the platform");
|
.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() -> ! {
|
unsafe extern "C" fn __aarch64_el1_ap_lower_entry() -> ! {
|
||||||
const AP_STACK_PAGES: usize = 8;
|
const AP_STACK_PAGES: usize = 8;
|
||||||
AArch64::set_interrupt_mask(true);
|
ArchitectureImpl::set_interrupt_mask(true);
|
||||||
|
|
||||||
// Unmask FP operations
|
// Unmask FP operations
|
||||||
CPACR_EL1.modify(CPACR_EL1::FPEN::TrapNothing);
|
CPACR_EL1.modify(CPACR_EL1::FPEN::TrapNothing);
|
||||||
@ -149,7 +151,7 @@ extern "C" fn __aarch64_ap_upper_entry() -> ! {
|
|||||||
exception::init_exceptions();
|
exception::init_exceptions();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ARCHITECTURE
|
PLATFORM
|
||||||
.init_platform(false)
|
.init_platform(false)
|
||||||
.expect("Could not initialize the AP");
|
.expect("Could not initialize the AP");
|
||||||
}
|
}
|
||||||
|
@ -13,16 +13,17 @@ use abi::{
|
|||||||
process::{Signal, SignalEntryData},
|
process::{Signal, SignalEntryData},
|
||||||
syscall::SyscallFunction,
|
syscall::SyscallFunction,
|
||||||
};
|
};
|
||||||
|
use kernel_arch::{Architecture, ArchitectureImpl};
|
||||||
use tock_registers::interfaces::{Readable, Writeable};
|
use tock_registers::interfaces::{Readable, Writeable};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{Architecture, ArchitectureImpl},
|
arch::{Platform, PlatformImpl},
|
||||||
debug::LogLevel,
|
debug::LogLevel,
|
||||||
syscall::raw_syscall_handler,
|
syscall::raw_syscall_handler,
|
||||||
task::{context::TaskFrame, thread::Thread},
|
task::{context::TaskFrame, thread::Thread},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::ARCHITECTURE;
|
use super::PLATFORM;
|
||||||
|
|
||||||
/// Struct for register values saved when taking an exception
|
/// Struct for register values saved when taking an exception
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -351,7 +352,7 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn irq_common() {
|
fn irq_common() {
|
||||||
ARCHITECTURE
|
PLATFORM
|
||||||
.external_interrupt_controller()
|
.external_interrupt_controller()
|
||||||
.handle_pending_irqs();
|
.handle_pending_irqs();
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,11 @@ use libk_mm::{
|
|||||||
};
|
};
|
||||||
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
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 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 MAX_IRQ: usize = 300;
|
||||||
const IPI_VECTOR: u64 = 1;
|
const IPI_VECTOR: u64 = 1;
|
||||||
@ -68,9 +68,9 @@ impl Device for Gic {
|
|||||||
self.gicd.init(gicd);
|
self.gicd.init(gicd);
|
||||||
self.gicc.init(gicc);
|
self.gicc.init(gicc);
|
||||||
|
|
||||||
ARCHITECTURE.register_external_interrupt_controller(self)?;
|
PLATFORM.register_external_interrupt_controller(self)?;
|
||||||
ARCHITECTURE.register_local_interrupt_controller(self)?;
|
PLATFORM.register_local_interrupt_controller(self)?;
|
||||||
ARCHITECTURE.register_message_interrupt_controller(self)?;
|
PLATFORM.register_message_interrupt_controller(self)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ use crate::{
|
|||||||
|
|
||||||
use self::mem::{table::L1, EarlyMapping};
|
use self::mem::{table::L1, EarlyMapping};
|
||||||
|
|
||||||
use super::{Architecture, CpuMessage};
|
use super::{CpuMessage, Platform};
|
||||||
|
|
||||||
pub mod boot;
|
pub mod boot;
|
||||||
pub mod context;
|
pub mod context;
|
||||||
@ -78,7 +78,7 @@ pub struct AArch64 {
|
|||||||
initrd: OneTimeInit<PhysicalRef<'static, [u8]>>,
|
initrd: OneTimeInit<PhysicalRef<'static, [u8]>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Architecture for AArch64 {
|
impl Platform for AArch64 {
|
||||||
const KERNEL_VIRT_OFFSET: usize = 0xFFFFFF8000000000;
|
const KERNEL_VIRT_OFFSET: usize = 0xFFFFFF8000000000;
|
||||||
|
|
||||||
type IrqNumber = IrqNumber;
|
type IrqNumber = IrqNumber;
|
||||||
@ -96,22 +96,6 @@ impl Architecture for AArch64 {
|
|||||||
smp::CPU_COUNT.load(Ordering::Acquire)
|
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(
|
unsafe fn map_device_memory(
|
||||||
&self,
|
&self,
|
||||||
base: PhysicalAddress,
|
base: PhysicalAddress,
|
||||||
@ -455,7 +439,7 @@ impl AArch64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// AArch64 implementation value
|
/// AArch64 implementation value
|
||||||
pub static ARCHITECTURE: AArch64 = AArch64 {
|
pub static PLATFORM: AArch64 = AArch64 {
|
||||||
dt: OneTimeInit::new(),
|
dt: OneTimeInit::new(),
|
||||||
initrd: OneTimeInit::new(),
|
initrd: OneTimeInit::new(),
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ use abi::error::Error;
|
|||||||
use device_api::CpuBringupDevice;
|
use device_api::CpuBringupDevice;
|
||||||
use device_tree::dt::{DevTreeIndexNodePropGet, DeviceTree};
|
use device_tree::dt::{DevTreeIndexNodePropGet, DeviceTree};
|
||||||
|
|
||||||
use crate::arch::ARCHITECTURE;
|
use crate::arch::PLATFORM;
|
||||||
use crate::mem::KERNEL_VIRT_OFFSET;
|
use crate::mem::KERNEL_VIRT_OFFSET;
|
||||||
|
|
||||||
use super::{BootStack, BOOT_STACK_SIZE};
|
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> {
|
unsafe fn start_cpu(&self, id: usize, ip: usize, sp: usize) -> Result<(), Error> {
|
||||||
match self {
|
match self {
|
||||||
Self::Psci => {
|
Self::Psci => {
|
||||||
let psci = ARCHITECTURE.psci.try_get().ok_or_else(|| {
|
let psci = PLATFORM.psci.try_get().ok_or_else(|| {
|
||||||
warnln!(
|
warnln!(
|
||||||
"cpu{} has to be enabled through PSCI, but no PSCI found",
|
"cpu{} has to be enabled through PSCI, but no PSCI found",
|
||||||
id
|
id
|
||||||
|
@ -10,7 +10,7 @@ use device_tree::device_tree_driver;
|
|||||||
use libk::runtime;
|
use libk::runtime;
|
||||||
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
|
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;
|
use super::cpu::Cpu;
|
||||||
|
|
||||||
@ -53,12 +53,12 @@ impl Device for ArmTimer {
|
|||||||
|
|
||||||
unsafe fn init(&'static self) -> Result<(), Error> {
|
unsafe fn init(&'static self) -> Result<(), Error> {
|
||||||
CNTP_CTL_EL0.write(CNTP_CTL_EL0::ENABLE::SET + CNTP_CTL_EL0::IMASK::SET);
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn init_irq(&'static self) -> Result<(), Error> {
|
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.register_irq(self.irq, Default::default(), self)?;
|
||||||
|
|
||||||
|
@ -4,23 +4,6 @@ use core::{ops::DerefMut, time::Duration};
|
|||||||
|
|
||||||
use abi::error::Error;
|
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 cfg_if::cfg_if;
|
||||||
use device_api::{
|
use device_api::{
|
||||||
interrupt::{
|
interrupt::{
|
||||||
@ -30,6 +13,7 @@ use device_api::{
|
|||||||
timer::MonotonicTimestampProviderDevice,
|
timer::MonotonicTimestampProviderDevice,
|
||||||
ResetDevice,
|
ResetDevice,
|
||||||
};
|
};
|
||||||
|
use kernel_arch::{Architecture, ArchitectureImpl};
|
||||||
use libk_mm::{
|
use libk_mm::{
|
||||||
address::PhysicalAddress,
|
address::PhysicalAddress,
|
||||||
device::{DeviceMemoryAttributes, RawDeviceMemoryMapping},
|
device::{DeviceMemoryAttributes, RawDeviceMemoryMapping},
|
||||||
@ -44,18 +28,18 @@ cfg_if! {
|
|||||||
if #[cfg(target_arch = "aarch64")] {
|
if #[cfg(target_arch = "aarch64")] {
|
||||||
pub mod 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")] {
|
} else if #[cfg(target_arch = "x86_64")] {
|
||||||
pub mod 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 {
|
} else {
|
||||||
compile_error!("Architecture is not supported");
|
compile_error!("Architecture is not supported");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Architecture-specific lowest level of page mapping
|
/// Architecture-specific lowest level of page mapping
|
||||||
pub type L3 = <ArchitectureImpl as Architecture>::L3;
|
pub type L3 = <PlatformImpl as Platform>::L3;
|
||||||
|
|
||||||
// Architecture interfaces
|
// Architecture interfaces
|
||||||
|
|
||||||
@ -72,7 +56,7 @@ pub enum CpuMessage {
|
|||||||
|
|
||||||
/// Interface for an architecture-specific facilities
|
/// Interface for an architecture-specific facilities
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub trait Architecture {
|
pub trait Platform {
|
||||||
/// Address, to which "zero" address is mapped in the virtual address space
|
/// Address, to which "zero" address is mapped in the virtual address space
|
||||||
const KERNEL_VIRT_OFFSET: usize;
|
const KERNEL_VIRT_OFFSET: usize;
|
||||||
|
|
||||||
@ -125,20 +109,6 @@ pub trait Architecture {
|
|||||||
|
|
||||||
// Architecture intrinsics
|
// 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
|
/// Returns the count of present CPUs, including the BSP
|
||||||
fn cpu_count() -> usize;
|
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
|
/// The caller must ensure it is actually safe to reset, i.e. no critical processes will be
|
||||||
/// aborted and no data will be lost.
|
/// aborted and no data will be lost.
|
||||||
unsafe fn reset(&self) -> ! {
|
unsafe fn reset(&self) -> ! {
|
||||||
Self::set_interrupt_mask(true);
|
ArchitectureImpl::set_interrupt_mask(true);
|
||||||
loop {
|
loop {
|
||||||
Self::wait_for_interrupt();
|
ArchitectureImpl::wait_for_interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -300,22 +270,6 @@ pub trait CpuAccess: Sized {
|
|||||||
|
|
||||||
// External API for architecture specifics
|
// 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]
|
#[no_mangle]
|
||||||
fn __cpu_index() -> usize {
|
fn __cpu_index() -> usize {
|
||||||
Cpu::local().id() as _
|
Cpu::local().id() as _
|
||||||
@ -323,17 +277,17 @@ fn __cpu_index() -> usize {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn __cpu_count() -> usize {
|
fn __cpu_count() -> usize {
|
||||||
ArchitectureImpl::cpu_count()
|
PlatformImpl::cpu_count()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn __virtualize(addr: u64) -> usize {
|
fn __virtualize(addr: u64) -> usize {
|
||||||
ArchitectureImpl::virtualize(addr)
|
PlatformImpl::virtualize(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn __physicalize(addr: usize) -> u64 {
|
fn __physicalize(addr: usize) -> u64 {
|
||||||
ArchitectureImpl::physicalize(addr)
|
PlatformImpl::physicalize(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -342,21 +296,21 @@ fn __map_device_pages(
|
|||||||
count: usize,
|
count: usize,
|
||||||
attrs: DeviceMemoryAttributes,
|
attrs: DeviceMemoryAttributes,
|
||||||
) -> Result<RawDeviceMemoryMapping, Error> {
|
) -> Result<RawDeviceMemoryMapping, Error> {
|
||||||
unsafe { ARCHITECTURE.map_device_memory(base, count, attrs) }
|
unsafe { PLATFORM.map_device_memory(base, count, attrs) }
|
||||||
}
|
}
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn __unmap_device_pages(mapping: &RawDeviceMemoryMapping) {
|
fn __unmap_device_pages(mapping: &RawDeviceMemoryMapping) {
|
||||||
unsafe { ARCHITECTURE.unmap_device_memory(mapping) }
|
unsafe { PLATFORM.unmap_device_memory(mapping) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn __monotonic_timestamp() -> Result<Duration, Error> {
|
fn __monotonic_timestamp() -> Result<Duration, Error> {
|
||||||
ARCHITECTURE.monotonic_timer().monotonic_timestamp()
|
PLATFORM.monotonic_timer().monotonic_timestamp()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn __message_interrupt_controller() -> &'static dyn MessageInterruptController {
|
fn __message_interrupt_controller() -> &'static dyn MessageInterruptController {
|
||||||
ARCHITECTURE.message_interrupt_controller()
|
PLATFORM.message_interrupt_controller()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -365,7 +319,7 @@ fn __register_global_interrupt(
|
|||||||
options: IrqOptions,
|
options: IrqOptions,
|
||||||
handler: &'static dyn InterruptHandler,
|
handler: &'static dyn InterruptHandler,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let intc = ARCHITECTURE.external_interrupt_controller();
|
let intc = PLATFORM.external_interrupt_controller();
|
||||||
|
|
||||||
let irq = {
|
let irq = {
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
@ -25,7 +25,7 @@ use yggdrasil_abi::error::Error;
|
|||||||
use crate::{
|
use crate::{
|
||||||
arch::{
|
arch::{
|
||||||
x86_64::{smp::CPU_COUNT, IrqNumber, SHUTDOWN_FENCE},
|
x86_64::{smp::CPU_COUNT, IrqNumber, SHUTDOWN_FENCE},
|
||||||
Architecture, CpuMessage, ARCHITECTURE,
|
CpuMessage, Platform, PLATFORM,
|
||||||
},
|
},
|
||||||
mem::{heap::GLOBAL_HEAP, read_memory, write_memory},
|
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> {
|
fn install_interrupt_handler(irq: u32) -> Result<(), AcpiSystemError> {
|
||||||
infoln!("Installing ACPI SCI handler at IRQ #{}", irq);
|
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 handler = Box::leak(Box::new(SciHandler));
|
||||||
let irq = IrqNumber::Isa(irq as _);
|
let irq = IrqNumber::Isa(irq as _);
|
||||||
|
|
||||||
@ -360,7 +360,7 @@ pub fn init_acpi(tables: &'static AcpiTables<AcpiHandlerImpl>) -> Result<(), Err
|
|||||||
// 7. Actually enter the S5 state
|
// 7. Actually enter the S5 state
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ARCHITECTURE
|
PLATFORM
|
||||||
.send_ipi(IpiDeliveryTarget::OtherCpus, CpuMessage::Shutdown)
|
.send_ipi(IpiDeliveryTarget::OtherCpus, CpuMessage::Shutdown)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,13 @@ use core::arch::global_asm;
|
|||||||
use static_assertions::{const_assert, const_assert_eq};
|
use static_assertions::{const_assert, const_assert_eq};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{x86_64::cpu::Cpu, Architecture, CpuAccess},
|
arch::{x86_64::cpu::Cpu, CpuAccess, Platform},
|
||||||
task::thread::Thread,
|
task::thread::Thread,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
exception::{self, IrqFrame},
|
exception::{self, IrqFrame},
|
||||||
ARCHITECTURE,
|
PLATFORM,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod ioapic;
|
pub mod ioapic;
|
||||||
@ -67,7 +67,7 @@ unsafe extern "C" fn irq_handler(vector: usize, frame: *mut IrqFrame) {
|
|||||||
let cpu = Cpu::local();
|
let cpu = Cpu::local();
|
||||||
let frame = &mut *frame;
|
let frame = &mut *frame;
|
||||||
|
|
||||||
ARCHITECTURE
|
PLATFORM
|
||||||
.external_interrupt_controller()
|
.external_interrupt_controller()
|
||||||
.handle_specific_irq(vector);
|
.handle_specific_irq(vector);
|
||||||
cpu.local_apic().clear_interrupt();
|
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 cpu = Cpu::local();
|
||||||
let frame = &mut *frame;
|
let frame = &mut *frame;
|
||||||
|
|
||||||
ARCHITECTURE
|
PLATFORM
|
||||||
.message_interrupt_controller()
|
.message_interrupt_controller()
|
||||||
.handle_msi(vector);
|
.handle_msi(vector);
|
||||||
cpu.local_apic().clear_interrupt();
|
cpu.local_apic().clear_interrupt();
|
||||||
|
@ -15,7 +15,7 @@ use crate::{
|
|||||||
mem::KERNEL_VIRT_OFFSET,
|
mem::KERNEL_VIRT_OFFSET,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{cpuid::init_cpuid, exception, ARCHITECTURE};
|
use super::{cpuid::init_cpuid, exception, PLATFORM};
|
||||||
|
|
||||||
pub enum BootData {
|
pub enum BootData {
|
||||||
YBoot(&'static LoadProtocolV1),
|
YBoot(&'static LoadProtocolV1),
|
||||||
@ -79,14 +79,14 @@ extern "C" fn __x86_64_upper_entry() -> ! {
|
|||||||
init_dummy_cpu();
|
init_dummy_cpu();
|
||||||
}
|
}
|
||||||
|
|
||||||
ARCHITECTURE.set_boot_data(BootData::YBoot(&YBOOT_DATA));
|
PLATFORM.set_boot_data(BootData::YBoot(&YBOOT_DATA));
|
||||||
|
|
||||||
// Gather available CPU features
|
// Gather available CPU features
|
||||||
init_cpuid();
|
init_cpuid();
|
||||||
|
|
||||||
// Setup memory management: kernel virtual memory tables, physical page manager and heap
|
// Setup memory management: kernel virtual memory tables, physical page manager and heap
|
||||||
unsafe {
|
unsafe {
|
||||||
ARCHITECTURE
|
PLATFORM
|
||||||
.init_memory_management()
|
.init_memory_management()
|
||||||
.expect("Could not initialize 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
|
// Initializes: local CPU, platform devices (timers/serials/etc), debug output
|
||||||
unsafe {
|
unsafe {
|
||||||
ARCHITECTURE
|
PLATFORM
|
||||||
.init_platform(0)
|
.init_platform(0)
|
||||||
.expect("Could not initialize the platform");
|
.expect("Could not initialize the platform");
|
||||||
}
|
}
|
||||||
@ -125,7 +125,7 @@ pub extern "C" fn __x86_64_ap_entry() -> ! {
|
|||||||
// syscall::init_syscall();
|
// syscall::init_syscall();
|
||||||
exception::init_exceptions(cpu_id);
|
exception::init_exceptions(cpu_id);
|
||||||
|
|
||||||
ARCHITECTURE
|
PLATFORM
|
||||||
.init_platform(cpu_id)
|
.init_platform(cpu_id)
|
||||||
.expect("Could not initialize the platform (AP)");
|
.expect("Could not initialize the platform (AP)");
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ use crate::{
|
|||||||
task::{context::TaskFrame, thread::Thread, Cpu},
|
task::{context::TaskFrame, thread::Thread, Cpu},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::ARCHITECTURE;
|
use super::PLATFORM;
|
||||||
|
|
||||||
primitive_enum! {
|
primitive_enum! {
|
||||||
enum ExceptionKind: u64 {
|
enum ExceptionKind: u64 {
|
||||||
@ -404,7 +404,7 @@ extern "C" fn __x86_64_exception_handler(frame: *mut ExceptionFrame) {
|
|||||||
|
|
||||||
if let Some(msg) = cpu.get_ipi() {
|
if let Some(msg) = cpu.get_ipi() {
|
||||||
unsafe {
|
unsafe {
|
||||||
ARCHITECTURE.handle_ipi(msg);
|
PLATFORM.handle_ipi(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ use self::{
|
|||||||
smp::CPU_COUNT,
|
smp::CPU_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Architecture, CpuAccess, CpuMessage};
|
use super::{CpuAccess, CpuMessage, Platform};
|
||||||
|
|
||||||
/// x86-64-specific interrupt number
|
/// x86-64-specific interrupt number
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||||
@ -100,7 +100,7 @@ pub struct X86_64 {
|
|||||||
static SHUTDOWN_FENCE: SpinFence = SpinFence::new();
|
static SHUTDOWN_FENCE: SpinFence = SpinFence::new();
|
||||||
|
|
||||||
/// Global x86-64 architecture value
|
/// Global x86-64 architecture value
|
||||||
pub static ARCHITECTURE: X86_64 = X86_64 {
|
pub static PLATFORM: X86_64 = X86_64 {
|
||||||
boot_data: OneTimeInit::new(),
|
boot_data: OneTimeInit::new(),
|
||||||
acpi: OneTimeInit::new(),
|
acpi: OneTimeInit::new(),
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ pub static ARCHITECTURE: X86_64 = X86_64 {
|
|||||||
timer: OneTimeInit::new(),
|
timer: OneTimeInit::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Architecture for X86_64 {
|
impl Platform for X86_64 {
|
||||||
const KERNEL_VIRT_OFFSET: usize = 0xFFFFFF8000000000;
|
const KERNEL_VIRT_OFFSET: usize = 0xFFFFFF8000000000;
|
||||||
type IrqNumber = IrqNumber;
|
type IrqNumber = IrqNumber;
|
||||||
type L3 = mem::table::L3;
|
type L3 = mem::table::L3;
|
||||||
@ -134,29 +134,6 @@ impl Architecture for X86_64 {
|
|||||||
CPU_COUNT.load(Ordering::Acquire)
|
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]
|
#[inline]
|
||||||
unsafe fn map_device_memory(
|
unsafe fn map_device_memory(
|
||||||
&self,
|
&self,
|
||||||
|
@ -10,7 +10,7 @@ use crate::arch::{
|
|||||||
intrinsics::{IoPort, IoPortAccess},
|
intrinsics::{IoPort, IoPortAccess},
|
||||||
IrqNumber,
|
IrqNumber,
|
||||||
},
|
},
|
||||||
Architecture, ARCHITECTURE,
|
Platform, PLATFORM,
|
||||||
};
|
};
|
||||||
|
|
||||||
const FREQUENCY: u32 = 1193180;
|
const FREQUENCY: u32 = 1193180;
|
||||||
@ -62,7 +62,7 @@ impl Device for I8253 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn init_irq(&'static self) -> Result<(), Error> {
|
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 inner = self.inner.lock();
|
||||||
|
|
||||||
let div: u16 = (FREQUENCY / 1000).try_into().unwrap();
|
let div: u16 = (FREQUENCY / 1000).try_into().unwrap();
|
||||||
|
@ -13,7 +13,7 @@ use crate::{
|
|||||||
peripherals::ps2::codeset::{CODE_SET_1_00, CODE_SET_1_E0},
|
peripherals::ps2::codeset::{CODE_SET_1_00, CODE_SET_1_E0},
|
||||||
IrqNumber,
|
IrqNumber,
|
||||||
},
|
},
|
||||||
Architecture, ARCHITECTURE,
|
Platform, PLATFORM,
|
||||||
},
|
},
|
||||||
device::input,
|
device::input,
|
||||||
};
|
};
|
||||||
@ -121,7 +121,7 @@ impl Device for PS2Controller {
|
|||||||
unsafe fn init_irq(&'static self) -> Result<(), Error> {
|
unsafe fn init_irq(&'static self) -> Result<(), Error> {
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
// let intc = PLATFORM.interrupt_controller();
|
// 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)?;
|
intc.register_irq(self.primary_irq, Default::default(), self)?;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
use acpi_lib::platform::{ProcessorInfo, ProcessorState};
|
use acpi_lib::platform::{ProcessorInfo, ProcessorState};
|
||||||
|
use kernel_arch::{Architecture, ArchitectureImpl};
|
||||||
use libk_mm::{
|
use libk_mm::{
|
||||||
address::{AsPhysicalAddress, FromRaw, IntoRaw, PhysicalAddress},
|
address::{AsPhysicalAddress, FromRaw, IntoRaw, PhysicalAddress},
|
||||||
pointer::PhysicalRefMut,
|
pointer::PhysicalRefMut,
|
||||||
@ -17,7 +18,7 @@ use crate::{
|
|||||||
KERNEL_TABLES,
|
KERNEL_TABLES,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Architecture, ArchitectureImpl, CpuAccess,
|
CpuAccess,
|
||||||
},
|
},
|
||||||
mem::phys,
|
mem::phys,
|
||||||
task::Cpu,
|
task::Cpu,
|
||||||
|
@ -4,8 +4,9 @@ use abi::error::Error;
|
|||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use device_api::{CpuBringupDevice, Device, ResetDevice};
|
use device_api::{CpuBringupDevice, Device, ResetDevice};
|
||||||
use device_tree::{device_tree_driver, dt::DevTreeIndexNodePropGet};
|
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 {
|
enum CallMethod {
|
||||||
Hvc,
|
Hvc,
|
||||||
@ -28,7 +29,7 @@ impl Device for Psci {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn init(&'static self) -> Result<(), Error> {
|
unsafe fn init(&'static self) -> Result<(), Error> {
|
||||||
ARCHITECTURE.psci.init(self);
|
PLATFORM.psci.init(self);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ use tock_registers::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{Architecture, ARCHITECTURE},
|
arch::{Architecture, PLATFORM},
|
||||||
device::devtree::{self, DevTreeIndexNodePropGet, DevTreeIndexPropExt},
|
device::devtree::{self, DevTreeIndexNodePropGet, DevTreeIndexPropExt},
|
||||||
device_tree_driver,
|
device_tree_driver,
|
||||||
mem::device::DeviceMemoryIo,
|
mem::device::DeviceMemoryIo,
|
||||||
@ -81,7 +81,7 @@ impl Device for RWdog {
|
|||||||
|
|
||||||
self.inner.init(IrqSafeSpinlock::new(Inner { regs }));
|
self.inner.init(IrqSafeSpinlock::new(Inner { regs }));
|
||||||
|
|
||||||
ARCHITECTURE.register_reset_device(self)?;
|
PLATFORM.register_reset_device(self)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ use tock_registers::{
|
|||||||
use vfs::{CharDevice, FileReadiness};
|
use vfs::{CharDevice, FileReadiness};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{aarch64::IrqNumber, Architecture, ARCHITECTURE},
|
arch::{aarch64::IrqNumber, Platform, PLATFORM},
|
||||||
debug::{self, DebugSink, LogLevel},
|
debug::{self, DebugSink, LogLevel},
|
||||||
device::tty::{TtyContext, TtyDevice},
|
device::tty::{TtyContext, TtyDevice},
|
||||||
task::process::ProcessId,
|
task::process::ProcessId,
|
||||||
@ -221,7 +221,7 @@ impl Device for Pl011 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn init_irq(&'static self) -> Result<(), Error> {
|
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.register_irq(self.irq, Default::default(), self)?;
|
||||||
self.inner.get().lock().regs.IMSC.modify(IMSC::RXIM::SET);
|
self.inner.get().lock().regs.IMSC.modify(IMSC::RXIM::SET);
|
||||||
|
@ -12,7 +12,7 @@ use tock_registers::{
|
|||||||
use vfs::CharDevice;
|
use vfs::CharDevice;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{aarch64::IrqNumber, Architecture, ARCHITECTURE},
|
arch::{aarch64::IrqNumber, Architecture, PLATFORM},
|
||||||
debug::{self, DebugSink, LogLevel},
|
debug::{self, DebugSink, LogLevel},
|
||||||
device::{
|
device::{
|
||||||
devtree::{self, DevTreeIndexPropExt},
|
devtree::{self, DevTreeIndexPropExt},
|
||||||
@ -173,7 +173,7 @@ impl Device for SunxiUart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn init_irq(&'static self) -> Result<(), Error> {
|
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.register_irq(self.irq, Default::default(), self)?;
|
||||||
intc.enable_irq(self.irq)?;
|
intc.enable_irq(self.irq)?;
|
||||||
|
10
src/main.rs
10
src/main.rs
@ -38,11 +38,11 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use arch::Architecture;
|
use arch::Platform;
|
||||||
use libk_util::sync::SpinFence;
|
use libk_util::sync::SpinFence;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{ArchitectureImpl, ARCHITECTURE},
|
arch::{PlatformImpl, PLATFORM},
|
||||||
fs::sysfs,
|
fs::sysfs,
|
||||||
mem::heap,
|
mem::heap,
|
||||||
task::{spawn_kernel_closure, Cpu},
|
task::{spawn_kernel_closure, Cpu},
|
||||||
@ -74,7 +74,7 @@ static CPU_INIT_FENCE: SpinFence = SpinFence::new();
|
|||||||
pub fn kernel_secondary_main() -> ! {
|
pub fn kernel_secondary_main() -> ! {
|
||||||
// Synchronize the CPUs to this point
|
// Synchronize the CPUs to this point
|
||||||
CPU_INIT_FENCE.signal();
|
CPU_INIT_FENCE.signal();
|
||||||
CPU_INIT_FENCE.wait_all(ArchitectureImpl::cpu_count());
|
CPU_INIT_FENCE.wait_all(PlatformImpl::cpu_count());
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
task::enter();
|
task::enter();
|
||||||
@ -100,14 +100,14 @@ pub fn kernel_main() -> ! {
|
|||||||
fs::add_pseudo_devices().unwrap();
|
fs::add_pseudo_devices().unwrap();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ARCHITECTURE.start_application_processors();
|
PLATFORM.start_application_processors();
|
||||||
}
|
}
|
||||||
|
|
||||||
Cpu::init_ipi_queues();
|
Cpu::init_ipi_queues();
|
||||||
|
|
||||||
// Wait until all APs initialize
|
// Wait until all APs initialize
|
||||||
CPU_INIT_FENCE.signal();
|
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");
|
task::init().expect("Failed to initialize the scheduler");
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ use core::{
|
|||||||
use abi::error::Error;
|
use abi::error::Error;
|
||||||
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryMapping};
|
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryMapping};
|
||||||
|
|
||||||
use crate::arch::{Architecture, ArchitectureImpl};
|
use crate::arch::{PlatformImpl, Platform};
|
||||||
|
|
||||||
pub mod address;
|
pub mod address;
|
||||||
pub mod heap;
|
pub mod heap;
|
||||||
@ -20,7 +20,7 @@ pub mod table;
|
|||||||
use self::process::ProcessAddressSpace;
|
use self::process::ProcessAddressSpace;
|
||||||
|
|
||||||
/// Offset applied to the physical kernel image when translating it into the virtual address space
|
/// 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.
|
/// Reads a value from an arbitrary physical address.
|
||||||
///
|
///
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! Physical memory management utilities
|
//! Physical memory management utilities
|
||||||
|
|
||||||
use abi::{error::Error, system::SystemMemoryStats};
|
use abi::{error::Error, system::SystemMemoryStats};
|
||||||
|
use kernel_arch::absolute_address;
|
||||||
use libk_mm::{
|
use libk_mm::{
|
||||||
address::{FromRaw, IntoRaw, PhysicalAddress},
|
address::{FromRaw, IntoRaw, PhysicalAddress},
|
||||||
phys::PhysicalMemoryRegion,
|
phys::PhysicalMemoryRegion,
|
||||||
@ -8,7 +9,7 @@ use libk_mm::{
|
|||||||
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{Architecture, ARCHITECTURE},
|
arch::{Platform, PLATFORM},
|
||||||
mem::phys::reserved::is_reserved,
|
mem::phys::reserved::is_reserved,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,7 +123,7 @@ pub unsafe fn init_from_iter<I: Iterator<Item = PhysicalMemoryRegion> + Clone>(
|
|||||||
|
|
||||||
reserve_region("kernel", kernel_physical_memory_region());
|
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 total_count = (phys_end - phys_start) / 0x1000;
|
||||||
let page_bitmap_size = (total_count + BITMAP_WORD_SIZE - 1) / (BITMAP_WORD_SIZE / 8);
|
let page_bitmap_size = (total_count + BITMAP_WORD_SIZE - 1) / (BITMAP_WORD_SIZE / 8);
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
use core::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
use core::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
||||||
|
|
||||||
use device_api::interrupt::IpiDeliveryTarget;
|
use device_api::interrupt::IpiDeliveryTarget;
|
||||||
|
use kernel_arch::{Architecture, ArchitectureImpl};
|
||||||
use libk_util::sync::{hack_locks, SpinFence};
|
use libk_util::sync::{hack_locks, SpinFence};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{Architecture, ArchitectureImpl, CpuAccess, CpuMessage, ARCHITECTURE},
|
arch::{CpuAccess, CpuMessage, Platform, PlatformImpl, PLATFORM},
|
||||||
debug::{debug_internal, LogLevel},
|
debug::{debug_internal, LogLevel},
|
||||||
device::display::console::flush_consoles,
|
device::display::console::flush_consoles,
|
||||||
task::Cpu,
|
task::Cpu,
|
||||||
@ -53,12 +54,12 @@ fn panic_handler(pi: &core::panic::PanicInfo) -> ! {
|
|||||||
{
|
{
|
||||||
// Let other CPUs know we're screwed
|
// Let other CPUs know we're screwed
|
||||||
unsafe {
|
unsafe {
|
||||||
ARCHITECTURE
|
PLATFORM
|
||||||
.send_ipi(IpiDeliveryTarget::OtherCpus, CpuMessage::Panic)
|
.send_ipi(IpiDeliveryTarget::OtherCpus, CpuMessage::Panic)
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
let ap_count = ArchitectureImpl::cpu_count() - 1;
|
let ap_count = PlatformImpl::cpu_count() - 1;
|
||||||
PANIC_HANDLED_FENCE.wait_all(ap_count);
|
PANIC_HANDLED_FENCE.wait_all(ap_count);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -101,7 +102,7 @@ fn panic_handler(pi: &core::panic::PanicInfo) -> ! {
|
|||||||
PANIC_SEQUENCE.fetch_add(1, Ordering::Release);
|
PANIC_SEQUENCE.fetch_add(1, Ordering::Release);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ARCHITECTURE.reset();
|
PLATFORM.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
||||||
|
|
||||||
use crate::arch::{Architecture, ARCHITECTURE};
|
use crate::arch::{Platform, PLATFORM};
|
||||||
|
|
||||||
const BUFFER_SIZE: usize = 1024;
|
const BUFFER_SIZE: usize = 1024;
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ pub fn read(buf: &mut [u8]) {
|
|||||||
|
|
||||||
/// Initializes the random generator state
|
/// Initializes the random generator state
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
let now = ARCHITECTURE
|
let now = PLATFORM
|
||||||
.monotonic_timer()
|
.monotonic_timer()
|
||||||
.monotonic_timestamp()
|
.monotonic_timestamp()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -8,7 +8,7 @@ use libk::{runtime, thread::Termination};
|
|||||||
use libk_util::sync::SpinFence;
|
use libk_util::sync::SpinFence;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{Architecture, ArchitectureImpl, CpuAccess},
|
arch::{PlatformImpl, CpuAccess, Platform},
|
||||||
task::{sched::CpuQueue, thread::Thread},
|
task::{sched::CpuQueue, thread::Thread},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ pub fn spawn_kernel_closure<S: Into<String>, T: Termination, F: Fn() -> T + Send
|
|||||||
|
|
||||||
/// Sets up CPU queues and gives them some processes to run
|
/// Sets up CPU queues and gives them some processes to run
|
||||||
pub fn init() -> Result<(), Error> {
|
pub fn init() -> Result<(), Error> {
|
||||||
let cpu_count = ArchitectureImpl::cpu_count();
|
let cpu_count = PlatformImpl::cpu_count();
|
||||||
|
|
||||||
// Create a queue for each CPU
|
// Create a queue for each CPU
|
||||||
sched::init_queues(Vec::from_iter((0..cpu_count).map(CpuQueue::new)));
|
sched::init_queues(Vec::from_iter((0..cpu_count).map(CpuQueue::new)));
|
||||||
|
@ -5,12 +5,10 @@ use core::cell::Cell;
|
|||||||
use alloc::{sync::Arc, vec::Vec};
|
use alloc::{sync::Arc, vec::Vec};
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use crossbeam_queue::SegQueue;
|
use crossbeam_queue::SegQueue;
|
||||||
|
use kernel_arch::{Architecture, ArchitectureImpl};
|
||||||
use libk_util::{sync::IrqGuard, OneTimeInit};
|
use libk_util::{sync::IrqGuard, OneTimeInit};
|
||||||
|
|
||||||
use crate::{
|
use crate::{arch::CpuAccess, task::thread::ThreadState};
|
||||||
arch::{Architecture, ArchitectureImpl, CpuAccess},
|
|
||||||
task::thread::ThreadState,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
context::TaskContextImpl,
|
context::TaskContextImpl,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user