refactor: put KERNEL_TABLES under a lock

This commit is contained in:
Mark Poliakov 2024-11-03 12:34:38 +02:00
parent a8a6192627
commit 98816e0ebc
15 changed files with 174 additions and 146 deletions

32
Cargo.lock generated
View File

@ -17,7 +17,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.87",
"thiserror", "thiserror",
] ]
@ -168,7 +168,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.87",
] ]
[[package]] [[package]]
@ -179,7 +179,7 @@ checksum = "99e1aca718ea7b89985790c94aad72d77533063fe00bc497bb79a7c2dae6a661"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.87",
] ]
[[package]] [[package]]
@ -266,7 +266,7 @@ checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.87",
] ]
[[package]] [[package]]
@ -337,7 +337,7 @@ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.87",
] ]
[[package]] [[package]]
@ -405,7 +405,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.87",
] ]
[[package]] [[package]]
@ -473,7 +473,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.87",
] ]
[[package]] [[package]]
@ -686,7 +686,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.87",
] ]
[[package]] [[package]]
@ -1266,7 +1266,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"syn 2.0.85", "syn 2.0.87",
] ]
[[package]] [[package]]
@ -1522,7 +1522,7 @@ checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.87",
] ]
[[package]] [[package]]
@ -1586,9 +1586,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.85" version = "2.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1642,7 +1642,7 @@ checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.87",
] ]
[[package]] [[package]]
@ -1834,7 +1834,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.87",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1856,7 +1856,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.87",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -2309,5 +2309,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.87",
] ]

View File

@ -9,12 +9,12 @@ use core::{
use aarch64_cpu::registers::{TTBR0_EL1, TTBR1_EL1}; use aarch64_cpu::registers::{TTBR0_EL1, TTBR1_EL1};
use kernel_arch_interface::{ use kernel_arch_interface::{
mem::{DeviceMemoryAttributes, KernelTableManager, RawDeviceMemoryMapping}, mem::{DeviceMemoryAttributes, KernelTableManager, RawDeviceMemoryMapping},
sync::split_spinlock,
KERNEL_VIRT_OFFSET, KERNEL_VIRT_OFFSET,
}; };
use libk_mm_interface::{ use libk_mm_interface::{
address::PhysicalAddress, address::PhysicalAddress,
table::{page_index, EntryLevel, EntryLevelExt}, table::{page_index, EntryLevel, EntryLevelExt},
KernelImageObject,
}; };
use memtables::aarch64::{FixedTables, KERNEL_L3_COUNT}; use memtables::aarch64::{FixedTables, KERNEL_L3_COUNT};
use static_assertions::const_assert_eq; use static_assertions::const_assert_eq;
@ -66,9 +66,15 @@ static mut DEVICE_MAPPING_L3S: [PageTable<L3>; DEVICE_MAPPING_L3_COUNT] =
pub const RAM_MAPPING_OFFSET: usize = MAPPING_OFFSET | (RAM_MAPPING_START_L1I * L1::SIZE); pub const RAM_MAPPING_OFFSET: usize = MAPPING_OFFSET | (RAM_MAPPING_START_L1I * L1::SIZE);
pub static MEMORY_LIMIT: AtomicUsize = AtomicUsize::new(0); pub static MEMORY_LIMIT: AtomicUsize = AtomicUsize::new(0);
#[link_section = ".data.tables"] split_spinlock! {
pub static mut KERNEL_TABLES: KernelImageObject<FixedTables> = use crate::ArchitectureImpl;
unsafe { KernelImageObject::new(FixedTables::zeroed()) }; use crate::mem::FixedTables;
use libk_mm_interface::KernelImageObject;
#[link_section = ".data.tables"]
static KERNEL_TABLES<lock: ArchitectureImpl>: KernelImageObject<FixedTables> =
unsafe { KernelImageObject::new(FixedTables::zeroed()) };
}
impl KernelTableManager for KernelTableManagerImpl { impl KernelTableManager for KernelTableManagerImpl {
fn virtualize(address: u64) -> usize { fn virtualize(address: u64) -> usize {
@ -221,9 +227,10 @@ pub unsafe fn map_ram_l1(index: usize) {
if index >= RAM_MAPPING_L1_COUNT { if index >= RAM_MAPPING_L1_COUNT {
todo!() todo!()
} }
assert_eq!(KERNEL_TABLES.l1.data[index + RAM_MAPPING_START_L1I], 0); let mut tables = KERNEL_TABLES.lock();
assert_eq!(tables.l1.data[index + RAM_MAPPING_START_L1I], 0);
KERNEL_TABLES.l1.data[index + RAM_MAPPING_START_L1I] = tables.l1.data[index + RAM_MAPPING_START_L1I] =
((index * L1::SIZE) as u64) | ram_block_flags().bits(); ((index * L1::SIZE) as u64) | ram_block_flags().bits();
} }
@ -363,8 +370,7 @@ pub fn tlb_flush_vaae1(mut page: usize) {
/// ///
/// Unsafe, must only be called by BSP during its early init while still in "lower-half" /// Unsafe, must only be called by BSP during its early init while still in "lower-half"
pub unsafe fn load_fixed_tables() { pub unsafe fn load_fixed_tables() {
#[allow(static_mut_refs)] let ttbr0 = KERNEL_TABLES.lock().l1.data.as_ptr().addr() as u64;
let ttbr0 = KERNEL_TABLES.l1.data.as_ptr() as u64;
TTBR0_EL1.set(ttbr0); TTBR0_EL1.set(ttbr0);
TTBR1_EL1.set(ttbr0); TTBR1_EL1.set(ttbr0);
} }
@ -376,6 +382,7 @@ pub unsafe fn load_fixed_tables() {
/// Unsafe, must only be called by BSP during its early init, must already be in "higher-half" /// Unsafe, must only be called by BSP during its early init, must already be in "higher-half"
pub unsafe fn init_fixed_tables() { pub unsafe fn init_fixed_tables() {
// TODO this could be built in compile-time too? // TODO this could be built in compile-time too?
let mut tables = KERNEL_TABLES.lock();
let early_mapping_l3_phys = addr_of!(EARLY_MAPPING_L3) as usize - KERNEL_VIRT_OFFSET; let early_mapping_l3_phys = addr_of!(EARLY_MAPPING_L3) as usize - KERNEL_VIRT_OFFSET;
let device_mapping_l2_phys = addr_of!(DEVICE_MAPPING_L2) as usize - KERNEL_VIRT_OFFSET; let device_mapping_l2_phys = addr_of!(DEVICE_MAPPING_L2) as usize - KERNEL_VIRT_OFFSET;
@ -386,11 +393,11 @@ pub unsafe fn init_fixed_tables() {
DEVICE_MAPPING_L2[i] = PageEntry::table(device_mapping_l3_phys, PageAttributes::empty()); DEVICE_MAPPING_L2[i] = PageEntry::table(device_mapping_l3_phys, PageAttributes::empty());
} }
assert_eq!(KERNEL_TABLES.l2.data[EARLY_MAPPING_L2I], 0); assert_eq!(tables.l2.data[EARLY_MAPPING_L2I], 0);
KERNEL_TABLES.l2.data[EARLY_MAPPING_L2I] = tables.l2.data[EARLY_MAPPING_L2I] =
(early_mapping_l3_phys as u64) | kernel_table_flags().bits(); (early_mapping_l3_phys as u64) | kernel_table_flags().bits();
assert_eq!(KERNEL_TABLES.l1.data[DEVICE_MAPPING_L1I], 0); assert_eq!(tables.l1.data[DEVICE_MAPPING_L1I], 0);
KERNEL_TABLES.l1.data[DEVICE_MAPPING_L1I] = tables.l1.data[DEVICE_MAPPING_L1I] =
(device_mapping_l2_phys as u64) | kernel_table_flags().bits(); (device_mapping_l2_phys as u64) | kernel_table_flags().bits();
} }

View File

@ -11,7 +11,7 @@ use yggdrasil_abi::{arch::SavedFrame, error::Error};
use crate::{ use crate::{
gdt::{self, TSS}, gdt::{self, TSS},
mem::kernel_tables, mem::KERNEL_TABLES,
}; };
#[allow(unused)] #[allow(unused)]
@ -156,7 +156,8 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
let sp = stack.build(); let sp = stack.build();
let cr3 = unsafe { let cr3 = unsafe {
kernel_tables() KERNEL_TABLES
.lock()
.as_physical_address() .as_physical_address()
.try_into_u32() .try_into_u32()
.unwrap() .unwrap()

View File

@ -1,4 +1,4 @@
#![feature(never_type, naked_functions)] #![feature(never_type, naked_functions, trace_macros)]
#![no_std] #![no_std]
extern crate alloc; extern crate alloc;

View File

@ -8,8 +8,8 @@ use crate::{
}; };
use super::{ use super::{
kernel_tables,
table::{PageEntry, PageTable, L0, L3}, table::{PageEntry, PageTable, L0, L3},
KERNEL_TABLES,
}; };
pub const KERNEL_SPLIT_L0: usize = KERNEL_VIRT_OFFSET >> 22; pub const KERNEL_SPLIT_L0: usize = KERNEL_VIRT_OFFSET >> 22;
@ -130,7 +130,7 @@ impl KernelDynamic {
} }
pub fn clone_kernel_tables(dst: &mut PageTable<L0>) { pub fn clone_kernel_tables(dst: &mut PageTable<L0>) {
let tables = kernel_tables(); let tables = KERNEL_TABLES.lock();
for (i, entry) in tables.l0.kernel.iter().enumerate() { for (i, entry) in tables.l0.kernel.iter().enumerate() {
dst[i + KERNEL_SPLIT_L0] = *entry; dst[i + KERNEL_SPLIT_L0] = *entry;
} }

View File

@ -1,18 +1,12 @@
use core::{
cell::UnsafeCell,
ops::{Deref, DerefMut},
};
use fixed::FixedTables; use fixed::FixedTables;
use kernel_arch_interface::{ use kernel_arch_interface::{
mem::{DeviceMemoryAttributes, KernelTableManager, RawDeviceMemoryMapping}, mem::{DeviceMemoryAttributes, KernelTableManager, RawDeviceMemoryMapping},
sync::{IrqSafeSpinlock, IrqSafeSpinlockGuard}, sync::split_spinlock,
KERNEL_VIRT_OFFSET, KERNEL_VIRT_OFFSET,
}; };
use libk_mm_interface::{ use libk_mm_interface::{
address::{AsPhysicalAddress, PhysicalAddress}, address::{AsPhysicalAddress, PhysicalAddress},
table::{page_count, EntryLevel}, table::{page_count, EntryLevel},
KernelImageObject,
}; };
use table::{PageAttributes, PageEntry, L0, L3}; use table::{PageAttributes, PageEntry, L0, L3};
use yggdrasil_abi::error::Error; use yggdrasil_abi::error::Error;
@ -23,59 +17,18 @@ pub mod table;
pub use process::ProcessAddressSpaceImpl; pub use process::ProcessAddressSpaceImpl;
use crate::ArchitectureImpl;
#[derive(Debug)] #[derive(Debug)]
pub struct KernelTableManagerImpl; pub struct KernelTableManagerImpl;
#[link_section = ".data.tables"] split_spinlock! {
pub static KERNEL_TABLES: KernelTablesInner = KernelTablesInner::new(); use libk_mm_interface::KernelImageObject;
static KERNEL_TABLES_LOCK: IrqSafeSpinlock<ArchitectureImpl, ()> = IrqSafeSpinlock::new(()); use crate::mem::FixedTables;
use crate::ArchitectureImpl;
#[repr(C, align(0x1000))] #[link_section = ".data.tables"]
pub struct KernelTablesInner { static KERNEL_TABLES<lock: ArchitectureImpl>: KernelImageObject<FixedTables> = unsafe {
inner: UnsafeCell<KernelImageObject<FixedTables>>, KernelImageObject::new(FixedTables::zeroed())
} };
impl KernelTablesInner {
const fn new() -> Self {
Self {
inner: unsafe { UnsafeCell::new(KernelImageObject::new(FixedTables::zeroed())) },
}
}
}
unsafe impl Sync for KernelTablesInner {}
pub struct KernelTablesGuard<'a> {
inner: &'a KernelTablesInner,
_guard: IrqSafeSpinlockGuard<'a, ArchitectureImpl, ()>,
}
pub fn kernel_tables<'a>() -> KernelTablesGuard<'a> {
let _guard = KERNEL_TABLES_LOCK.lock();
let inner = &KERNEL_TABLES;
KernelTablesGuard { inner, _guard }
}
impl AsPhysicalAddress for KernelTablesGuard<'_> {
unsafe fn as_physical_address(&self) -> PhysicalAddress {
(*self.inner.inner.get()).as_physical_address()
}
}
impl Deref for KernelTablesGuard<'_> {
type Target = KernelImageObject<FixedTables>;
fn deref(&self) -> &Self::Target {
unsafe { &*self.inner.inner.get() }
}
}
impl DerefMut for KernelTablesGuard<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.inner.inner.get() }
}
} }
impl KernelTableManager for KernelTableManagerImpl { impl KernelTableManager for KernelTableManagerImpl {
@ -97,7 +50,7 @@ impl KernelTableManager for KernelTableManagerImpl {
assert_eq!(base & 0xFFF, 0); assert_eq!(base & 0xFFF, 0);
log::info!("map_device_pages({:#x}, {})", base, count); log::info!("map_device_pages({:#x}, {})", base, count);
let page_count = page_count::<L3>(count); let page_count = page_count::<L3>(count);
let virt = kernel_tables().map_dynamic_memory(base, page_count)?; let virt = KERNEL_TABLES.lock().map_dynamic_memory(base, page_count)?;
Ok(RawDeviceMemoryMapping::from_raw_parts( Ok(RawDeviceMemoryMapping::from_raw_parts(
virt, virt, page_count, 0, virt, virt, page_count, 0,
@ -110,11 +63,14 @@ impl KernelTableManager for KernelTableManagerImpl {
} }
fn virtualize(phys: u64) -> usize { fn virtualize(phys: u64) -> usize {
kernel_tables().virtualize(PhysicalAddress::from_u64(phys)) KERNEL_TABLES
.lock()
.virtualize(PhysicalAddress::from_u64(phys))
} }
fn physicalize(virt: usize) -> u64 { fn physicalize(virt: usize) -> u64 {
kernel_tables() KERNEL_TABLES
.lock()
.physicalize(virt) .physicalize(virt)
.expect("Invalid virtual address") .expect("Invalid virtual address")
.into_u64() .into_u64()
@ -137,7 +93,7 @@ impl KernelTableManager for KernelTableManagerImpl {
/// ///
/// Only meant to be called once during early OS init. /// Only meant to be called once during early OS init.
pub unsafe fn init_fixed_tables() { pub unsafe fn init_fixed_tables() {
let mut tables = kernel_tables(); let mut tables = KERNEL_TABLES.lock();
// Unmap lower stuff // Unmap lower stuff
for (i, entry) in tables.l0.lower.iter_mut().enumerate() { for (i, entry) in tables.l0.lower.iter_mut().enumerate() {

View File

@ -1,5 +1,5 @@
#![no_std] #![no_std]
#![feature(step_trait, const_trait_impl, never_type)] #![feature(step_trait, const_trait_impl, never_type, decl_macro)]
#![allow(clippy::new_without_default)] #![allow(clippy::new_without_default)]
use alloc::vec::Vec; use alloc::vec::Vec;

View File

@ -153,3 +153,67 @@ impl<'a, A: Architecture, T> DerefMut for IrqSafeSpinlockGuard<'a, A, T> {
self.inner.deref_mut() self.inner.deref_mut()
} }
} }
/// Helper macro to implement "split" locks. This may be needed when a very specific storage
/// layout for the locked type is required.
pub macro split_spinlock(
$(use $use:path;)*
$(#[$meta:meta])*
static $name:ident<$lock:ident: $arch:ty>: $ty:ty = $init:expr;
) {
pub use $name::$name;
#[allow(non_snake_case)]
pub mod $name {
$(use $use;)*
use core::cell::UnsafeCell;
use core::marker::PhantomData;
use core::sync::atomic::{AtomicBool, Ordering};
$(#[$meta])*
pub static $name: __Wrapper = __Wrapper {
inner: UnsafeCell::new($init)
};
static __LOCK: AtomicBool = AtomicBool::new(false);
#[repr(transparent)]
pub struct __Wrapper {
inner: UnsafeCell<$ty>
}
pub struct __Guard($crate::guard::IrqGuard<$arch>);
impl __Wrapper {
pub fn $lock(&self) -> __Guard {
let irq = $crate::guard::IrqGuard::acquire();
while __LOCK.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() {
core::hint::spin_loop();
}
__Guard(irq)
}
}
unsafe impl Sync for __Wrapper {}
impl core::ops::Deref for __Guard {
type Target = $ty;
fn deref(&self) -> &Self::Target {
unsafe { &*$name.inner.get() }
}
}
impl core::ops::DerefMut for __Guard {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *$name.inner.get() }
}
}
impl Drop for __Guard {
fn drop(&mut self) {
__LOCK.store(false, Ordering::Release)
}
}
}
}

View File

@ -423,10 +423,7 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
setup_common_context( setup_common_context(
&mut stack, &mut stack,
__x86_64_task_enter_kernel as _, __x86_64_task_enter_kernel as _,
#[allow(static_mut_refs)] unsafe { KERNEL_TABLES.lock().as_physical_address() }.into(),
unsafe {
KERNEL_TABLES.as_physical_address().into_u64()
},
0, 0,
); );

View File

@ -5,14 +5,14 @@ use core::{
sync::atomic::{AtomicUsize, Ordering}, sync::atomic::{AtomicUsize, Ordering},
}; };
use kernel_arch_interface::mem::{ use kernel_arch_interface::{
DeviceMemoryAttributes, KernelTableManager, RawDeviceMemoryMapping, mem::{DeviceMemoryAttributes, KernelTableManager, RawDeviceMemoryMapping},
sync::split_spinlock,
}; };
use kernel_arch_x86::registers::CR3; use kernel_arch_x86::registers::CR3;
use libk_mm_interface::{ use libk_mm_interface::{
address::PhysicalAddress, address::PhysicalAddress,
table::{page_index, EntryLevel, EntryLevelExt}, table::{page_index, EntryLevel, EntryLevelExt},
KernelImageObject,
}; };
use memtables::x86_64::FixedTables; use memtables::x86_64::FixedTables;
use static_assertions::{const_assert_eq, const_assert_ne}; use static_assertions::{const_assert_eq, const_assert_ne};
@ -50,9 +50,15 @@ const RAM_MAPPING_L0I: usize = KERNEL_L0_INDEX - 1;
const DEVICE_MAPPING_L3_COUNT: usize = 4; const DEVICE_MAPPING_L3_COUNT: usize = 4;
#[link_section = ".data.tables"] split_spinlock! {
pub static mut KERNEL_TABLES: KernelImageObject<FixedTables> = use crate::ArchitectureImpl;
unsafe { KernelImageObject::new(FixedTables::zeroed()) }; use crate::mem::FixedTables;
use libk_mm_interface::KernelImageObject;
#[link_section = ".data.tables"]
static KERNEL_TABLES<lock: ArchitectureImpl>: KernelImageObject<FixedTables> =
unsafe { KernelImageObject::new(FixedTables::zeroed()) };
}
// 2MiB for early mappings // 2MiB for early mappings
const EARLY_MAPPING_OFFSET: usize = CANONICAL_ADDRESS_MASK const EARLY_MAPPING_OFFSET: usize = CANONICAL_ADDRESS_MASK
@ -336,9 +342,10 @@ impl<'a, T: ?Sized> Drop for EarlyMapping<'a, T> {
} }
pub fn clone_kernel_tables(dst: &mut PageTable<L0>) { pub fn clone_kernel_tables(dst: &mut PageTable<L0>) {
let tables = KERNEL_TABLES.lock();
unsafe { unsafe {
dst[KERNEL_L0_INDEX] = PageEntry::from_raw(KERNEL_TABLES.l0.data[KERNEL_L0_INDEX]); dst[KERNEL_L0_INDEX] = PageEntry::from_raw(tables.l0.data[KERNEL_L0_INDEX]);
dst[RAM_MAPPING_L0I] = PageEntry::from_raw(KERNEL_TABLES.l0.data[RAM_MAPPING_L0I]); dst[RAM_MAPPING_L0I] = PageEntry::from_raw(tables.l0.data[RAM_MAPPING_L0I]);
} }
} }
@ -359,6 +366,7 @@ pub fn clone_kernel_tables(dst: &mut PageTable<L0>) {
/// ///
/// Unsafe, must only be called by BSP during its early init, must already be in "higher-half" /// Unsafe, must only be called by BSP during its early init, must already be in "higher-half"
pub unsafe fn init_fixed_tables() { pub unsafe fn init_fixed_tables() {
let mut tables = KERNEL_TABLES.lock();
// TODO this could be built in compile-time too? // TODO this could be built in compile-time too?
let early_mapping_l3_phys = addr_of!(EARLY_MAPPING_L3) as usize - KERNEL_VIRT_OFFSET; let early_mapping_l3_phys = addr_of!(EARLY_MAPPING_L3) as usize - KERNEL_VIRT_OFFSET;
let device_mapping_l2_phys = addr_of!(DEVICE_MAPPING_L2) as usize - KERNEL_VIRT_OFFSET; let device_mapping_l2_phys = addr_of!(DEVICE_MAPPING_L2) as usize - KERNEL_VIRT_OFFSET;
@ -371,20 +379,20 @@ pub unsafe fn init_fixed_tables() {
DEVICE_MAPPING_L2[i] = PageEntry::table(device_mapping_l3_phys, PageAttributes::WRITABLE); DEVICE_MAPPING_L2[i] = PageEntry::table(device_mapping_l3_phys, PageAttributes::WRITABLE);
} }
assert_eq!(KERNEL_TABLES.kernel_l2.data[EARLY_MAPPING_L2I], 0); assert_eq!(tables.kernel_l2.data[EARLY_MAPPING_L2I], 0);
KERNEL_TABLES.kernel_l2.data[EARLY_MAPPING_L2I] = (early_mapping_l3_phys as u64) tables.kernel_l2.data[EARLY_MAPPING_L2I] = (early_mapping_l3_phys as u64)
| (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits(); | (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits();
assert_eq!(KERNEL_TABLES.kernel_l1.data[DEVICE_MAPPING_L1I], 0); assert_eq!(tables.kernel_l1.data[DEVICE_MAPPING_L1I], 0);
KERNEL_TABLES.kernel_l1.data[DEVICE_MAPPING_L1I] = (device_mapping_l2_phys as u64) tables.kernel_l1.data[DEVICE_MAPPING_L1I] = (device_mapping_l2_phys as u64)
| (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits(); | (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits();
assert_eq!(KERNEL_TABLES.l0.data[RAM_MAPPING_L0I], 0); assert_eq!(tables.l0.data[RAM_MAPPING_L0I], 0);
KERNEL_TABLES.l0.data[RAM_MAPPING_L0I] = tables.l0.data[RAM_MAPPING_L0I] =
(ram_mapping_l1_phys as u64) | (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits(); (ram_mapping_l1_phys as u64) | (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits();
// TODO ENABLE EFER.NXE // TODO ENABLE EFER.NXE
let cr3 = &raw const KERNEL_TABLES.l0 as usize - KERNEL_VIRT_OFFSET; let cr3 = (&raw const tables.l0).addr() - KERNEL_VIRT_OFFSET;
CR3.set_address(cr3); CR3.set_address(cr3);
} }

View File

@ -14,18 +14,6 @@ use kernel_arch_interface::mem::KernelTableManager;
#[repr(transparent)] #[repr(transparent)]
pub struct PhysicalAddress(pub(crate) u64); pub struct PhysicalAddress(pub(crate) u64);
// /// Interface for converting addresses from their raw values to more specific types
// pub trait FromRaw<T> {
// /// Converts a raw value into the address wrapper type
// fn from_raw(value: T) -> Self;
// }
//
// /// Interface for converting wrapper types into their raw address representations
// pub trait IntoRaw<T> {
// /// Converts a wrapper type value into its raw address
// fn into_raw(self) -> T;
// }
/// Interface for obtaining physical addresses of values /// Interface for obtaining physical addresses of values
pub trait AsPhysicalAddress { pub trait AsPhysicalAddress {
/// Returns the value's physical address. /// Returns the value's physical address.

View File

@ -1,9 +1,10 @@
use core::{arch::global_asm, ptr::addr_of}; use core::arch::global_asm;
use abi::{primitive_enum, process::Signal, SyscallFunction}; use abi::{primitive_enum, process::Signal, SyscallFunction};
use kernel_arch_i686::context::{ExceptionFrame, SyscallFrame}; use kernel_arch_i686::context::{ExceptionFrame, SyscallFrame};
use kernel_arch_x86::registers::{CR2, CR3}; use kernel_arch_x86::registers::{CR2, CR3};
use libk::task::thread::Thread; use libk::task::thread::Thread;
use libk_util::sync::spin_rwlock::IrqSafeRwLock;
use tock_registers::interfaces::Readable; use tock_registers::interfaces::Readable;
use crate::{arch::x86::peripherals::i8259, syscall}; use crate::{arch::x86::peripherals::i8259, syscall};
@ -147,7 +148,7 @@ impl Entry {
} }
} }
static mut IDT: [Entry; SIZE] = [Entry::NULL; SIZE]; static IDT: IrqSafeRwLock<[Entry; SIZE]> = IrqSafeRwLock::new([Entry::NULL; SIZE]);
fn dump_user_exception(kind: ExceptionKind, frame: &ExceptionFrame) { fn dump_user_exception(kind: ExceptionKind, frame: &ExceptionFrame) {
let thread = Thread::current(); let thread = Thread::current();
@ -267,11 +268,13 @@ pub unsafe fn init_exceptions() {
fn __i686_syscall_vector(); fn __i686_syscall_vector();
} }
let mut idt = IDT.write();
for (i, &entry) in __i686_exception_vectors.iter().enumerate() { for (i, &entry) in __i686_exception_vectors.iter().enumerate() {
IDT[i] = Entry::new(entry, 0x08, Entry::PRESENT | Entry::INT32); idt[i] = Entry::new(entry, 0x08, Entry::PRESENT | Entry::INT32);
} }
for entry in IDT.iter_mut().skip(32) { for entry in idt.iter_mut().skip(32) {
*entry = Entry::new( *entry = Entry::new(
__i686_dummy_vector as usize, __i686_dummy_vector as usize,
0x08, 0x08,
@ -279,17 +282,17 @@ pub unsafe fn init_exceptions() {
); );
} }
i8259::setup_vectors(&mut IDT[32..]); i8259::setup_vectors(&mut idt[32..]);
IDT[0x80] = Entry::new( idt[0x80] = Entry::new(
__i686_syscall_vector as usize, __i686_syscall_vector as usize,
0x08, 0x08,
Entry::PRESENT | Entry::INT32 | Entry::DPL3, Entry::PRESENT | Entry::INT32 | Entry::DPL3,
); );
let idtr = Pointer { let idtr = Pointer {
limit: (IDT.len() * size_of::<Entry>()) as u16 - 1, limit: (idt.len() * size_of::<Entry>()) as u16 - 1,
offset: addr_of!(IDT) as usize, offset: idt.as_ptr().addr(),
}; };
core::arch::asm!("wbinvd; lidt ({0})", in(reg) &idtr, options(att_syntax)); core::arch::asm!("wbinvd; lidt ({0})", in(reg) &idtr, options(att_syntax));

View File

@ -1,10 +1,11 @@
//! x86-64 exception and interrupt handling //! x86-64 exception and interrupt handling
use core::{arch::global_asm, mem::size_of, ptr::addr_of}; use core::{arch::global_asm, mem::size_of};
use abi::{primitive_enum, process::Signal}; use abi::{primitive_enum, process::Signal};
use kernel_arch_x86::registers::{CR2, CR3}; use kernel_arch_x86::registers::{CR2, CR3};
use kernel_arch_x86_64::context::ExceptionFrame; use kernel_arch_x86_64::context::ExceptionFrame;
use libk::{arch::Cpu, task::thread::Thread}; use libk::{arch::Cpu, task::thread::Thread};
use libk_util::sync::spin_rwlock::IrqSafeRwLock;
use tock_registers::interfaces::Readable; use tock_registers::interfaces::Readable;
use crate::arch::x86_64::apic; use crate::arch::x86_64::apic;
@ -111,7 +112,7 @@ impl Entry {
} }
} }
static mut IDT: [Entry; SIZE] = [Entry::NULL; SIZE]; static IDT: IrqSafeRwLock<[Entry; SIZE]> = IrqSafeRwLock::new([Entry::NULL; SIZE]);
fn dump_user_exception(kind: ExceptionKind, frame: &ExceptionFrame) { fn dump_user_exception(kind: ExceptionKind, frame: &ExceptionFrame) {
let thread = Thread::current(); let thread = Thread::current();
@ -215,20 +216,22 @@ extern "C" fn __x86_64_exception_handler(frame: *mut ExceptionFrame) {
/// Only meant to be called once per each CPU during their init. /// Only meant to be called once per each CPU during their init.
pub unsafe fn init_exceptions(cpu_index: usize) { pub unsafe fn init_exceptions(cpu_index: usize) {
if cpu_index == 0 { if cpu_index == 0 {
let mut idt = IDT.write();
extern "C" { extern "C" {
static __x86_64_exception_vectors: [usize; 32]; static __x86_64_exception_vectors: [usize; 32];
} }
for (i, &entry) in __x86_64_exception_vectors.iter().enumerate() { for (i, &entry) in __x86_64_exception_vectors.iter().enumerate() {
IDT[i] = Entry::new(entry, 0x08, Entry::PRESENT | Entry::INT32); idt[i] = Entry::new(entry, 0x08, Entry::PRESENT | Entry::INT32);
} }
apic::setup_vectors(&mut IDT[32..]); apic::setup_vectors(&mut idt[32..]);
} }
let idt = IDT.read();
let idtr = Pointer { let idtr = Pointer {
limit: (IDT.len() * size_of::<Entry>()) as u16 - 1, limit: (idt.len() * size_of::<Entry>()) as u16 - 1,
offset: addr_of!(IDT) as usize, offset: idt.as_ptr().addr(),
}; };
core::arch::asm!("wbinvd; lidt ({0})", in(reg) &idtr, options(att_syntax)); core::arch::asm!("wbinvd; lidt ({0})", in(reg) &idtr, options(att_syntax));

View File

@ -44,7 +44,7 @@ unsafe fn start_ap_core(apic_id: u32) {
let bsp_cpu = Cpu::local(); let bsp_cpu = Cpu::local();
let bsp_apic = bsp_cpu.local_apic(); let bsp_apic = bsp_cpu.local_apic();
let cr3 = KERNEL_TABLES.as_physical_address(); let cr3 = KERNEL_TABLES.lock().as_physical_address();
let stack_base = phys::alloc_pages_contiguous(AP_STACK_PAGES) let stack_base = phys::alloc_pages_contiguous(AP_STACK_PAGES)
.unwrap() .unwrap()
.virtualize(); .virtualize();
@ -93,9 +93,12 @@ pub unsafe fn start_ap_cores(info: &ProcessorInfo<AcpiAllocator>) {
PageEntry::<L1>::table(identity_l2.as_physical_address(), PageAttributes::WRITABLE); PageEntry::<L1>::table(identity_l2.as_physical_address(), PageAttributes::WRITABLE);
identity_l2[0] = PageEntry::<L2>::block(PhysicalAddress::ZERO, PageAttributes::WRITABLE); identity_l2[0] = PageEntry::<L2>::block(PhysicalAddress::ZERO, PageAttributes::WRITABLE);
assert_eq!(KERNEL_TABLES.l0.data[0], 0); {
KERNEL_TABLES.l0.data[0] = identity_l1.as_physical_address().into_u64() let mut tables = KERNEL_TABLES.lock();
| (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits(); assert_eq!(tables.l0.data[0], 0);
tables.l0.data[0] = identity_l1.as_physical_address().into_u64()
| (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits();
}
// Load AP_BOOTSTRAP_CODE // Load AP_BOOTSTRAP_CODE
let mut code_ref = PhysicalRefMut::map_slice(AP_BOOTSTRAP_CODE, AP_BOOTSTRAP_BIN.len()); let mut code_ref = PhysicalRefMut::map_slice(AP_BOOTSTRAP_CODE, AP_BOOTSTRAP_BIN.len());
@ -110,7 +113,7 @@ pub unsafe fn start_ap_cores(info: &ProcessorInfo<AcpiAllocator>) {
// Remove the identity-map // Remove the identity-map
identity_l2[0] = PageEntry::INVALID; identity_l2[0] = PageEntry::INVALID;
flush_tlb_entry(0); flush_tlb_entry(0);
KERNEL_TABLES.l0.data[0] = 0; KERNEL_TABLES.lock().l0.data[0] = 0;
PageTable::free::<TableAllocatorImpl>(identity_l1); PageTable::free::<TableAllocatorImpl>(identity_l1);
PageTable::free::<TableAllocatorImpl>(identity_l2); PageTable::free::<TableAllocatorImpl>(identity_l2);

View File

@ -33,8 +33,6 @@
#![deny(missing_docs)] #![deny(missing_docs)]
#![no_std] #![no_std]
#![no_main] #![no_main]
// XXX FIXME TODO
#![allow(static_mut_refs)]
use arch::Platform; use arch::Platform;
use kernel_arch::{Architecture, ArchitectureImpl}; use kernel_arch::{Architecture, ArchitectureImpl};