Partial: migrate ACPI to RMM.

This commit is contained in:
4lDO2
2022-07-17 14:07:56 +02:00
parent 8970ce1fe7
commit 0aec4d3341
5 changed files with 81 additions and 54 deletions

View File

@@ -3,7 +3,7 @@ use core::{mem, ptr};
use core::intrinsics::{volatile_load, volatile_store};
use crate::memory::Frame;
use crate::paging::{ActivePageTable, PhysicalAddress, Page, PageFlags, VirtualAddress};
use crate::paging::{KernelMapper, PhysicalAddress, PageFlags};
use super::sdt::Sdt;
use super::{ACPI_TABLE, find_sdt};
@@ -35,10 +35,10 @@ pub struct Hpet {
}
impl Hpet {
pub fn init(active_table: &mut ActivePageTable) {
pub fn init() {
let hpet_sdt = find_sdt("HPET");
let hpet = if hpet_sdt.len() == 1 {
Hpet::new(hpet_sdt[0], active_table)
Hpet::new(hpet_sdt[0])
} else {
println!("Unable to find HPET");
return;
@@ -52,10 +52,10 @@ impl Hpet {
}
}
pub fn new(sdt: &'static Sdt, active_table: &mut ActivePageTable) -> Option<Hpet> {
pub fn new(sdt: &'static Sdt) -> Option<Hpet> {
if &sdt.signature == b"HPET" && sdt.length as usize >= mem::size_of::<Hpet>() {
let s = unsafe { ptr::read((sdt as *const Sdt) as *const Hpet) };
unsafe { s.base_address.init(active_table) };
unsafe { s.base_address.init(&mut KernelMapper::lock()) };
Some(s)
} else {
None
@@ -64,18 +64,21 @@ impl Hpet {
}
impl GenericAddressStructure {
pub unsafe fn init(&self, active_table: &mut ActivePageTable) {
let page = Page::containing_address(VirtualAddress::new(self.address as usize));
pub unsafe fn init(&self, mapper: &mut KernelMapper) {
let frame = Frame::containing_address(PhysicalAddress::new(self.address as usize));
let result = active_table.map_to(page, frame, PageFlags::new().write(true));
let (_, result) = mapper
.get_mut()
.expect("KernelMapper locked re-entrant while mapping memory for GenericAddressStructure")
.map_linearly(frame.start_address(), PageFlags::new().write(true))
.expect("failed to map memory for GenericAddressStructure");
result.flush();
}
pub unsafe fn read_u64(&self, offset: usize) -> u64{
volatile_load((self.address as usize + offset) as *const u64)
volatile_load((self.address as usize + offset + crate::PHYS_OFFSET) as *const u64)
}
pub unsafe fn write_u64(&mut self, offset: usize, value: u64) {
volatile_store((self.address as usize + offset) as *mut u64, value);
volatile_store((self.address as usize + offset + crate::PHYS_OFFSET) as *mut u64, value);
}
}

View File

@@ -1,7 +1,7 @@
use core::mem;
use crate::memory::{allocate_frames, Frame};
use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, VirtualAddress};
use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch, VirtualAddress};
use super::sdt::Sdt;
use super::find_sdt;
@@ -28,7 +28,7 @@ pub static mut MADT: Option<Madt> = None;
pub const FLAG_PCAT: u32 = 1;
impl Madt {
pub fn init(active_table: &mut ActivePageTable) {
pub fn init() {
let madt_sdt = find_sdt("APIC");
let madt = if madt_sdt.len() == 1 {
Madt::new(madt_sdt[0])
@@ -53,10 +53,18 @@ impl Madt {
}
if cfg!(feature = "multi_core") {
let mut mapper = KernelMapper::lock();
// Map trampoline
let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE));
let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE));
let result = active_table.map_to(trampoline_page, trampoline_frame, PageFlags::new().execute(true).write(true)); //TODO: do not have writable and executable!
let result = unsafe {
//TODO: do not have writable and executable!
mapper
.get_mut()
.expect("expected kernel page table not to be recursively locked while initializing MADT")
.map_phys(trampoline_page.start_address(), trampoline_frame.start_address(), PageFlags::new().execute(true).write(true))
.expect("failed to map trampoline")
};
result.flush();
// Write trampoline, make sure TRAMPOLINE page is free for use
@@ -90,7 +98,7 @@ impl Madt {
// Set the ap_ready to 0, volatile
unsafe { atomic_store(ap_ready, 0) };
unsafe { atomic_store(ap_cpu_id, ap_local_apic.id as u64) };
unsafe { atomic_store(ap_page_table, active_table.address() as u64) };
unsafe { atomic_store(ap_page_table, mapper.table().phys().data() as u64) };
unsafe { atomic_store(ap_stack_start, stack_start as u64) };
unsafe { atomic_store(ap_stack_end, stack_end as u64) };
unsafe { atomic_store(ap_code, kstart_ap as u64) };
@@ -137,7 +145,7 @@ impl Madt {
}
println!(" Ready");
active_table.flush_all();
unsafe { RmmA::invalidate_all(); }
} else {
println!(" CPU Disabled");
}
@@ -147,8 +155,14 @@ impl Madt {
}
// Unmap trampoline
let (result, _frame) = active_table.unmap_return(trampoline_page, false);
result.flush();
let (_frame, _, flush) = unsafe {
mapper
.get_mut()
.expect("expected kernel page table not to be recursively locked while initializing MADT")
.unmap_phys(trampoline_page.start_address())
.expect("failed to unmap trampoline page")
};
flush.flush();
}
}
}

View File

@@ -10,7 +10,7 @@ use spin::{Once, RwLock};
use crate::log::info;
use crate::memory::Frame;
use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, VirtualAddress};
use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch, VirtualAddress};
use self::madt::Madt;
use self::rsdt::Rsdt;
@@ -28,31 +28,33 @@ mod xsdt;
mod rxsdt;
mod rsdp;
pub fn get_sdt(sdt_address: usize, active_table: &mut ActivePageTable) -> &'static Sdt {
{
let page = Page::containing_address(VirtualAddress::new(sdt_address + crate::PHYS_OFFSET));
if active_table.translate_page(page).is_none() {
let frame = Frame::containing_address(PhysicalAddress::new(sdt_address));
let result = active_table.map_to(page, frame, PageFlags::new());
result.flush();
}
unsafe fn map_linearly(addr: PhysicalAddress, len: usize, mapper: &mut crate::paging::PageMapper) {
let base = PhysicalAddress::new(crate::paging::round_down_pages(addr.data()));
let aligned_len = crate::paging::round_up_pages(len + (addr.data() - base.data()));
for page_idx in 0..aligned_len / crate::memory::PAGE_SIZE {
let (_, flush) = mapper.map_linearly(base.add(page_idx * crate::memory::PAGE_SIZE), PageFlags::new()).expect("failed to linearly map SDT");
flush.flush();
}
}
let sdt = unsafe { &*((sdt_address + crate::PHYS_OFFSET) as *const Sdt) };
pub fn get_sdt(sdt_address: usize, mapper: &mut KernelMapper) -> &'static Sdt {
let mapper = mapper
.get_mut()
.expect("KernelMapper mapper locked re-entrant in get_sdt");
// Map extra SDT frames if required
{
let start_page = Page::containing_address(VirtualAddress::new(sdt_address + 4096 + crate::PHYS_OFFSET));
let end_page = Page::containing_address(VirtualAddress::new(sdt_address + sdt.length as usize + crate::PHYS_OFFSET));
for page in Page::range_inclusive(start_page, end_page) {
if active_table.translate_page(page).is_none() {
let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().data() - crate::PHYS_OFFSET));
let result = active_table.map_to(page, frame, PageFlags::new());
result.flush();
}
}
let physaddr = PhysicalAddress::new(sdt_address);
let sdt;
unsafe {
const SDT_SIZE: usize = core::mem::size_of::<Sdt>();
map_linearly(physaddr, SDT_SIZE, mapper);
sdt = unsafe { &*(RmmA::phys_to_virt(physaddr).data() as *const Sdt) };
map_linearly(physaddr.add(SDT_SIZE), sdt.length as usize - SDT_SIZE, mapper);
}
sdt
}
@@ -72,16 +74,19 @@ impl Rxsdt for RxsdtEnum {
pub static RXSDT_ENUM: Once<RxsdtEnum> = Once::new();
/// Parse the ACPI tables to gather CPU, interrupt, and timer information
pub unsafe fn init(active_table: &mut ActivePageTable, already_supplied_rsdps: Option<(u64, u64)>) {
pub unsafe fn init(already_supplied_rsdps: Option<(u64, u64)>) {
{
let mut sdt_ptrs = SDT_POINTERS.write();
*sdt_ptrs = Some(BTreeMap::new());
}
// Search for RSDP
if let Some(rsdp) = RSDP::get_rsdp(active_table, already_supplied_rsdps) {
let rsdp_opt = RSDP::get_rsdp(&mut KernelMapper::lock(), already_supplied_rsdps);
if let Some(rsdp) = rsdp_opt {
info!("RSDP: {:?}", rsdp);
let rxsdt = get_sdt(rsdp.sdt_address(), active_table);
let rxsdt = get_sdt(rsdp.sdt_address(), &mut KernelMapper::lock());
dbg!();
for &c in rxsdt.signature.iter() {
print!("{}", c as char);
@@ -122,7 +127,7 @@ pub unsafe fn init(active_table: &mut ActivePageTable, already_supplied_rsdps: O
// TODO: Don't touch ACPI tables in kernel?
rxsdt.map_all(active_table);
rxsdt.map_all();
for sdt_address in rxsdt.iter() {
let sdt = &*((sdt_address + crate::PHYS_OFFSET) as *const Sdt);
@@ -135,10 +140,10 @@ pub unsafe fn init(active_table: &mut ActivePageTable, already_supplied_rsdps: O
// TODO: Enumerate processors in userspace, and then provide an ACPI-independent interface
// to initialize enumerated processors to userspace?
Madt::init(active_table);
Madt::init();
// TODO: Let userspace setup HPET, and then provide an interface to specify which timer to
// use?
Hpet::init(active_table);
Hpet::init();
} else {
println!("NO RSDP FOUND");
}

View File

@@ -2,7 +2,7 @@ use core::convert::TryFrom;
use core::mem;
use crate::memory::Frame;
use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, VirtualAddress};
use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, VirtualAddress};
/// RSDP
#[derive(Copy, Clone, Debug)]
@@ -71,16 +71,16 @@ impl RSDP {
None
}
pub fn get_rsdp(active_table: &mut ActivePageTable, already_supplied_rsdps: Option<(u64, u64)>) -> Option<RSDP> {
pub fn get_rsdp(mapper: &mut KernelMapper, already_supplied_rsdps: Option<(u64, u64)>) -> Option<RSDP> {
if let Some((base, size)) = already_supplied_rsdps {
let area = unsafe { core::slice::from_raw_parts(base as usize as *const u8, size as usize) };
Self::get_already_supplied_rsdps(area).or_else(|| Self::get_rsdp_by_searching(active_table))
Self::get_already_supplied_rsdps(area).or_else(|| Self::get_rsdp_by_searching(mapper))
} else {
Self::get_rsdp_by_searching(active_table)
Self::get_rsdp_by_searching(mapper)
}
}
/// Search for the RSDP
pub fn get_rsdp_by_searching(active_table: &mut ActivePageTable) -> Option<RSDP> {
pub fn get_rsdp_by_searching(mapper: &mut KernelMapper) -> Option<RSDP> {
let start_addr = 0xE_0000;
let end_addr = 0xF_FFFF;
@@ -90,7 +90,9 @@ impl RSDP {
let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr));
for frame in Frame::range_inclusive(start_frame, end_frame) {
let page = Page::containing_address(VirtualAddress::new(frame.start_address().data()));
let result = active_table.map_to(page, frame, PageFlags::new());
let result = unsafe {
mapper.get_mut().expect("KernelMapper locked re-entrant while locating RSDPs").map_phys(page.start_address(), frame.start_address(), PageFlags::new()).expect("failed to map page while searching for RSDP")
};
result.flush();
}
}

View File

@@ -1,6 +1,6 @@
use alloc::boxed::Box;
use crate::paging::ActivePageTable;
use crate::paging::KernelMapper;
use super::sdt::Sdt;
use super::get_sdt;
@@ -8,9 +8,12 @@ use super::get_sdt;
pub trait Rxsdt {
fn iter(&self) -> Box<dyn Iterator<Item = usize>>;
fn map_all(&self, active_table: &mut ActivePageTable) {
fn map_all(&self) {
let iter = self.iter();
let mut mapper = KernelMapper::lock();
for sdt in self.iter() {
get_sdt(sdt, active_table);
get_sdt(sdt, &mut mapper);
}
}