x86_64: fix L2 RAM mapping issue + incorrect CR3 write

This commit is contained in:
Mark Poliakov 2024-12-28 12:32:14 +02:00
parent 76f1872764
commit 46854c0f81
7 changed files with 46 additions and 23 deletions

View File

@ -230,6 +230,9 @@ fn enable_features(ecx: EcxFeatures, edx: EdxFeatures) {
if ecx.contains(EcxFeatures::PCID) { if ecx.contains(EcxFeatures::PCID) {
CR4.modify(CR4::PCIDE::SET); CR4.modify(CR4::PCIDE::SET);
} }
if edx.contains(EdxFeatures::PSE) {
CR4.modify(CR4::PSE::SET);
}
CR0.modify(CR0::TS::CLEAR); CR0.modify(CR0::TS::CLEAR);
} }

View File

@ -146,7 +146,7 @@ mod cr2 {
} }
mod cr3 { mod cr3 {
use tock_registers::{interfaces::ReadWriteable, register_bitfields}; use tock_registers::{interfaces::Writeable, register_bitfields};
register_bitfields! { register_bitfields! {
usize, usize,
@ -164,7 +164,7 @@ mod cr3 {
impl Reg { impl Reg {
pub fn set_address(&self, address: usize) { pub fn set_address(&self, address: usize) {
assert_eq!(address & 0xFFF, 0); assert_eq!(address & 0xFFF, 0);
self.modify(CR3::ADDR.val(address >> 12)) self.write(CR3::ADDR.val(address >> 12))
} }
} }

View File

@ -1,7 +1,6 @@
use core::{ use core::{
alloc::Layout, alloc::Layout,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
ptr::addr_of,
sync::atomic::{AtomicUsize, Ordering}, sync::atomic::{AtomicUsize, Ordering},
}; };
@ -128,6 +127,7 @@ unsafe fn map_early_pages(physical: PhysicalAddress, count: usize) -> Result<usi
// TODO NX, NC // TODO NX, NC
EARLY_MAPPING_L3[i + l3i] = EARLY_MAPPING_L3[i + l3i] =
PageEntry::page(physical.add(i * L3::SIZE), PageAttributes::WRITABLE); PageEntry::page(physical.add(i * L3::SIZE), PageAttributes::WRITABLE);
flush_tlb_entry(EARLY_MAPPING_OFFSET + (i + l3i) * L3::SIZE);
} }
return Ok(EARLY_MAPPING_OFFSET + l3i * L3::SIZE); return Ok(EARLY_MAPPING_OFFSET + l3i * L3::SIZE);
@ -336,6 +336,15 @@ pub fn clone_kernel_tables(dst: &mut PageTable<L0>) {
} }
} }
pub fn auto_address<T>(pointer: *const T) -> usize {
let address = pointer.addr();
if address < KERNEL_VIRT_OFFSET {
address
} else {
address - KERNEL_VIRT_OFFSET
}
}
/// Sets up the following memory map: /// Sets up the following memory map:
/// ...: KERNEL_TABLES.l0: /// ...: KERNEL_TABLES.l0:
/// * 0xFFFFFF0000000000 .. 0xFFFFFFFF8000000000 : RAM_MAPPING_L1 /// * 0xFFFFFF0000000000 .. 0xFFFFFFFF8000000000 : RAM_MAPPING_L1
@ -354,15 +363,15 @@ 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(); 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 = auto_address(&raw const EARLY_MAPPING_L3);
let device_mapping_l2_phys = addr_of!(DEVICE_MAPPING_L2) as usize - KERNEL_VIRT_OFFSET; let device_mapping_l2_phys = auto_address(&raw const DEVICE_MAPPING_L2);
let ram_mapping_l1_phys = addr_of!(RAM_MAPPING_L1) as usize - KERNEL_VIRT_OFFSET; let ram_mapping_l1_phys = auto_address(&raw const RAM_MAPPING_L1);
for i in 0..DEVICE_MAPPING_L3_COUNT { for i in 0..DEVICE_MAPPING_L3_COUNT {
let device_mapping_l3_phys = PhysicalAddress::from_usize( let device_mapping_l3_phys =
&DEVICE_MAPPING_L3S[i] as *const _ as usize - KERNEL_VIRT_OFFSET, PhysicalAddress::from_usize(auto_address(&raw const DEVICE_MAPPING_L3S[i]));
);
DEVICE_MAPPING_L2[i] = PageEntry::table(device_mapping_l3_phys, PageAttributes::WRITABLE); DEVICE_MAPPING_L2[i] = PageEntry::table(device_mapping_l3_phys, PageAttributes::WRITABLE);
} }
@ -379,7 +388,7 @@ pub unsafe fn init_fixed_tables() {
(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 tables.l0).addr() - KERNEL_VIRT_OFFSET; let cr3 = auto_address(&raw const tables.l0);
CR3.set_address(cr3); CR3.set_address(cr3);
} }

View File

@ -5,7 +5,6 @@ use libk::vfs::Metadata;
use yggdrasil_abi::{ use yggdrasil_abi::{
bitflags, bitflags,
io::{FileMode, FileType, GroupId, UserId}, io::{FileMode, FileType, GroupId, UserId},
time::SystemTime,
}; };
use crate::Ext2Fs; use crate::Ext2Fs;

View File

@ -10,7 +10,7 @@ use alloc::{
use libk_util::sync::IrqSafeSpinlock; use libk_util::sync::IrqSafeSpinlock;
use yggdrasil_abi::{ use yggdrasil_abi::{
error::Error, error::Error,
io::{FileMode, FileType, GroupId, OpenOptions, UserId}, io::{FileMode, FileType, OpenOptions},
}; };
use crate::vfs::{DirectoryOpenPosition, InstanceData}; use crate::vfs::{DirectoryOpenPosition, InstanceData};

View File

@ -15,7 +15,6 @@ use yggdrasil_abi::{
bitflags, bitflags,
error::Error, error::Error,
io::{FileMode, FileType, GroupId, UserId}, io::{FileMode, FileType, GroupId, UserId},
time::SystemTime,
}; };
mod access; mod access;

View File

@ -13,9 +13,9 @@ use kernel_arch_x86::{
}; };
use kernel_arch_x86_64::{ use kernel_arch_x86_64::{
mem::{ mem::{
init_fixed_tables, flush_tlb_entry, init_fixed_tables,
table::{PageAttributes, PageEntry, PageTable, L1, L2, L3}, table::{PageAttributes, PageEntry, PageTable, L1, L2, L3},
EarlyMapping, MEMORY_LIMIT, RAM_MAPPING_L1, EarlyMapping, MEMORY_LIMIT, RAM_MAPPING_L1, RAM_MAPPING_OFFSET,
}, },
PerCpuData, PerCpuData,
}; };
@ -203,9 +203,11 @@ impl X86_64 {
RAM_MAPPING_L1[l1i] = PageEntry::<L1>::table(l2_phys_addr, PageAttributes::WRITABLE) RAM_MAPPING_L1[l1i] = PageEntry::<L1>::table(l2_phys_addr, PageAttributes::WRITABLE)
}; };
unsafe { flush_tlb_entry(RAM_MAPPING_OFFSET + (l1i << L1::SHIFT)) };
intrinsics::flush_cpu_cache(); intrinsics::flush_cpu_cache();
// The EarlyMapping is then dropped // The EarlyMapping is then dropped
} }
// } // }
Ok(()) Ok(())
@ -246,13 +248,15 @@ impl X86_64 {
} }
unsafe fn init_platform(&'static self, cpu_id: usize) -> Result<(), Error> { unsafe fn init_platform(&'static self, cpu_id: usize) -> Result<(), Error> {
let (available_features, enabled_features) = self.init_cpu_features();
if cpu_id == 0 { if cpu_id == 0 {
PLATFORM PLATFORM
.init_memory_management() .init_memory_management()
.expect("Could not initialize memory management"); .expect("Could not initialize memory management");
} }
self.init_local_cpu(cpu_id); self.init_local_cpu(cpu_id, available_features, enabled_features);
if cpu_id == 0 { if cpu_id == 0 {
x86::register_pci_drivers(); x86::register_pci_drivers();
@ -293,11 +297,7 @@ impl X86_64 {
Ok(timer) Ok(timer)
} }
unsafe fn init_local_cpu(&self, cpu_id: usize) { unsafe fn init_cpu_features(&self) -> (CpuFeatures, CpuFeatures) {
let local_apic = Box::new(LocalApic::new());
let tss_address = gdt::init();
exception::init_exceptions(cpu_id);
let (have_features, will_features) = cpuid::setup_features( let (have_features, will_features) = cpuid::setup_features(
CpuFeatures { CpuFeatures {
ecx: EcxFeatures::SSE3 ecx: EcxFeatures::SSE3
@ -317,13 +317,26 @@ impl X86_64 {
); );
let will_features = will_features.expect("Could not initialize CPU features"); let will_features = will_features.expect("Could not initialize CPU features");
(have_features, will_features)
}
unsafe fn init_local_cpu(
&self,
cpu_id: usize,
available_features: CpuFeatures,
enabled_features: CpuFeatures,
) {
let local_apic = Box::new(LocalApic::new());
let tss_address = gdt::init();
exception::init_exceptions(cpu_id);
let cpu_data = PerCpuData { let cpu_data = PerCpuData {
this: null_mut(), this: null_mut(),
tss_address, tss_address,
tmp_address: 0, tmp_address: 0,
local_apic, local_apic,
available_features: have_features, available_features,
enabled_features: will_features, enabled_features,
}; };
Cpu::init_local(Some(cpu_id as _), cpu_data); Cpu::init_local(Some(cpu_id as _), cpu_data);