Partial: migrate ACPI to RMM.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user