*theoretically* we are getting the ioapic addr

This commit is contained in:
fekhesk 2022-10-27 10:46:49 -07:00
parent 5f130d43e1
commit eb1e469fdc
No known key found for this signature in database
GPG key ID: D17BA3F38ED319DF
3 changed files with 68 additions and 60 deletions

View file

@ -1,12 +1,13 @@
use alloc::sync::Arc;
use core::marker::PhantomData;
use acpi::{AcpiHandler, PhysicalMapping};
use crate::{debug, KernelArgs};
use core::ptr::NonNull;
use acpi::{AcpiHandler, InterruptModel, PhysicalMapping};
use crate::{debug, KernelArgs, println};
#[cfg(feature = "f_multiboot2")]
use multiboot2::{load, MemoryMapTag, BootInformation};
use x86_64::structures::paging::{FrameAllocator, OffsetPageTable};
use crate::memory::BootInfoFrameAllocator;
use x86_64::structures::paging::{FrameAllocator, Mapper, OffsetPageTable, Translate};
use crate::memory::{BootInfoFrameAllocator, FRAME_ALLOC, MEM_MAPPER};
pub struct KernelInfo {
kernel_start: u64,
@ -16,6 +17,48 @@ pub struct KernelInfo {
boot_info: BootInformation,
}
#[derive(Clone)]
struct Handler;
impl AcpiHandler for Handler {
unsafe fn map_physical_region<T>(&self, physical_address: usize, size: usize) -> PhysicalMapping<Self, T> {
// todo! check if size is too big
debug!("read_phys_memory32: addr {:x} not mapped", physical_address);
// map the page
let frame = FRAME_ALLOC.lock().as_mut().unwrap().allocate_frame().unwrap();
debug!("allocated frame: {:?}", frame);
let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE;
let page = x86_64::structures::paging::Page::containing_address(initaladdr);
debug!("mapped page: {:?}", page);
let map_to_result = unsafe { MEM_MAPPER.lock().as_mut().unwrap().map_to(page, frame, flags, FRAME_ALLOC.lock().as_mut().unwrap()) };
debug!("map_to_result: {:?}", map_to_result);
if map_to_result.is_err() {
panic!("Failed to map page");
}
let addr = unsafe { MEM_MAPPER.lock().as_mut().unwrap().translate_addr(initaladdr) };
if let Some(addr) = addr {
// physical start, virtual start, region length, mapped length, Self
PhysicalMapping::new(
physical_address,
NonNull::new_unchecked(addr.as_u64() as *mut T),
size, size,
Self)
} else {
panic!("Failed to map page");
}
}
fn unmap_physical_region<T>(region: &PhysicalMapping<Self, T>) {
// get page
let page = x86_64::structures::paging::Page::containing_address(region.start_address());
// unmap page
let res = unsafe { MEM_MAPPER.lock().as_mut().unwrap().unmap(page) };
// it isn't *that* important if we don't unmap successfully at the moment, so just write a warning if we fail
if res.is_err() {
println!("[WARN] failed to unmap page");
}
}
}
impl KernelInfo {
pub fn init_from_kernel_args(args: KernelArgs) -> Self {
#[cfg(feature = "f_multiboot2")]
@ -56,64 +99,29 @@ impl KernelInfo {
self.safe_mem_start
}
pub fn acpi_get_ioapic_addr(&self, mem_mapper: &mut OffsetPageTable, frame_allocator: &mut BootInfoFrameAllocator) -> u64 {
pub fn acpi_get_ioapic_addr(&self) -> u32 {
#[cfg(feature = "f_multiboot2")]
{
let acpi_tag = self.boot_info.rsdp_v1_tag().expect("no acpi tag");
let rsdp = acpi_tag;
let rsdp = unsafe { &*rsdp };
let rsdt = rsdp.rsdt_address();
#[derive(Clone)]
struct Handler<'a> {
mem_mapper: Arc<&'a mut OffsetPageTable<'a>>,
frame_allocator: Arc<&'a mut BootInfoFrameAllocator>,
let rsdt = unsafe {
acpi::AcpiTables::from_rsdt(
AcpiHandler, 0,
rsdt)
.expect("failed to get acpi tables")
};
let platform_info = rsdt.platform_info().expect("failed to get platform info");
let interrupt_model = platform_info.interrupt_model;
if let InterruptModel::Apic(apic) = interrupt_model {
let ioapics = apic.io_apics;
let ioapic = ioapics.first().expect("no ioapics");
let ioapic_addr = ioapic.address;
ioapic_addr
} else {
panic!("no ioapic");
}
impl<'a> AcpiHandler for Handler<'a> {
unsafe fn map_physical_region<T>(&self, physical_address: usize, size: usize) -> PhysicalMapping<Self, T> {
let frame_allocator = self.frame_allocator.clone();
debug!("read_phys_memory32: addr {:x} not mapped", physical_address);
// map the page
let frame = frame_allocator.allocate_frame().unwrap();
debug!("allocated frame: {:?}", frame);
let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE;
let page = x86_64::structures::paging::Page::containing_address(initaladdr);
debug!("mapped page: {:?}", page);
let map_to_result = unsafe { mem_mapper.map_to(page, frame, flags, frame_allocator) };
debug!("map_to_result: {:?}", map_to_result);
if map_to_result.is_err() {
panic!("Failed to map page");
}
let addr = unsafe { mem_mapper.translate_addr(initaladdr) };
if let Some(addr) = addr {
let addr = addr.as_u64() as *const u32;
unsafe { *addr }
} else {
panic!("Failed to map page");
}
}
fn unmap_physical_region<T>(region: &PhysicalMapping<Self, T>) {
todo!()
}
}
let rsdt = acpi::AcpiTables::from_rsdt(rsdt).expect("failed to get acpi tables");
let mut ioapic_addr = 0;
for entry in rsdt.entries() {
let entry = unsafe { &*entry };
if entry.signature() == *b"APIC" {
let apic = entry.as_apic();
let apic = unsafe { &*apic };
for entry in apic.entries() {
let entry = unsafe { &*entry };
if entry.signature() == *b"IOAP" {
let ioapic = entry.as_ioapic();
let ioapic = unsafe { &*ioapic };
ioapic_addr = ioapic.address();
}
}
}
}
ioapic_addr
}
}
}

View file

@ -56,12 +56,12 @@ pub fn enable_apic() {
write_phys_memory32(sivr_addr, sivr | (1 << 8));
}
pub fn apic_read_io(ioapicaddr: usize, reg: u32) -> u32 {
pub fn apic_read_io(ioapicaddr: u32, reg: u32) -> u32 {
write_phys_memory32(ioapicaddr as u32, reg);
read_phys_memory32(ioapicaddr as u32 + 0x10)
}
pub fn apic_write_io(ioapicaddr: usize, reg: u32, val: u32) {
pub fn apic_write_io(ioapicaddr: u32, reg: u32, val: u32) {
write_phys_memory32(ioapicaddr as u32, reg);
write_phys_memory32(ioapicaddr as u32 + 0x10, val);
}
@ -83,7 +83,7 @@ pub fn disable_pic() {
command(0xa1, 0xff);
}
pub fn ioapic_set_irq(ioapicaddr: usize, irq: u8, apic_id: u64, vector:u8) {
pub fn ioapic_set_irq(ioapicaddr: u32, irq: u8, apic_id: u64, vector:u8) {
let lo_index: u32 = (0x10 + irq*2 ) as u32;
let hi_index: u32 = (0x10 + irq*2 + 1) as u32;
@ -136,7 +136,7 @@ pub extern "x86-interrupt" fn keyboard_irq(stack_frame: InterruptStackFrame) {
}
// todo! we should abstract this away
pub fn setup_apic_interrupts(ioapicaddr: usize) {
pub fn setup_apic_interrupts(ioapicaddr: u32) {
// set keyboard irq to interrupt 40
ioapic_set_irq(ioapicaddr, 1, 0, 40);
}

View file

@ -208,7 +208,7 @@ pub extern fn kernel_main(args: KernelArgs) -> ! {
unsafe { internals::cpu::enable_apic() };
println!("[OK]");
print!("setting up apic interrupts...");
unsafe { internals::cpu::setup_apic_interrupts() };
unsafe { internals::cpu::setup_apic_interrupts(kern_info.lock().acpi_get_ioapic_addr()) };
println!("[OK]");
// enable interrupts
x86_64::instructions::interrupts::enable();