put memory mapper and frame allocator into mutex

This commit is contained in:
fekhesk 2022-10-27 10:29:58 -07:00
parent 50970fa2cc
commit 5f130d43e1
No known key found for this signature in database
GPG key ID: D17BA3F38ED319DF
4 changed files with 49 additions and 33 deletions

View file

@ -47,23 +47,23 @@ pub fn get_apic_base() -> usize {
((edx as usize) << 32) | (eax as usize) ((edx as usize) << 32) | (eax as usize)
} }
pub fn enable_apic(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator) { pub fn enable_apic() {
// PIC should be disabled by now // PIC should be disabled by now
// now enable local apic // now enable local apic
// 1. set bit 8 of spurious interrupt vector register // 1. set bit 8 of spurious interrupt vector register
let sivr_addr = 0xfee000f0; let sivr_addr = 0xfee000f0;
let sivr = read_phys_memory32(mem_mapper, frame_alloc, sivr_addr); let sivr = read_phys_memory32(sivr_addr);
write_phys_memory32(mem_mapper, frame_alloc, sivr_addr, sivr | (1 << 8)); write_phys_memory32(sivr_addr, sivr | (1 << 8));
} }
pub fn apic_read_io(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize, reg: u32) -> u32 { pub fn apic_read_io(ioapicaddr: usize, reg: u32) -> u32 {
write_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32, reg); write_phys_memory32(ioapicaddr as u32, reg);
read_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32 + 0x10) read_phys_memory32(ioapicaddr as u32 + 0x10)
} }
pub fn apic_write_io(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize, reg: u32, val: u32) { pub fn apic_write_io(ioapicaddr: usize, reg: u32, val: u32) {
write_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32, reg); write_phys_memory32(ioapicaddr as u32, reg);
write_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32 + 0x10, val); write_phys_memory32(ioapicaddr as u32 + 0x10, val);
} }
pub fn disable_pic() { pub fn disable_pic() {
@ -83,17 +83,17 @@ pub fn disable_pic() {
command(0xa1, 0xff); command(0xa1, 0xff);
} }
pub fn ioapic_set_irq(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize, irq: u8, apic_id: u64, vector:u8) { pub fn ioapic_set_irq(ioapicaddr: usize, irq: u8, apic_id: u64, vector:u8) {
let lo_index: u32 = (0x10 + irq*2 ) as u32; let lo_index: u32 = (0x10 + irq*2 ) as u32;
let hi_index: u32 = (0x10 + irq*2 + 1) as u32; let hi_index: u32 = (0x10 + irq*2 + 1) as u32;
let mut high = apic_read_io(mem_mapper, frame_alloc, ioapicaddr, hi_index); let mut high = apic_read_io(ioapicaddr, hi_index);
// set apic id // set apic id
high &= !(0xff000000); high &= !(0xff000000);
high |= (apic_id as u32) << 24; high |= (apic_id as u32) << 24;
apic_write_io(mem_mapper, frame_alloc, ioapicaddr, hi_index, high); apic_write_io(ioapicaddr, hi_index, high);
let mut low = apic_read_io(mem_mapper, frame_alloc, ioapicaddr, lo_index); let mut low = apic_read_io( ioapicaddr, lo_index);
// unmask // unmask
low &= !(1 << 16); low &= !(1 << 16);
@ -105,7 +105,7 @@ pub fn ioapic_set_irq(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootIn
low &= !(0xff); low &= !(0xff);
low |= vector as u32; low |= vector as u32;
apic_write_io(mem_mapper, frame_alloc, ioapicaddr, lo_index, low); apic_write_io(ioapicaddr, lo_index, low);
} }
pub fn apic_eoi() { pub fn apic_eoi() {
@ -136,7 +136,7 @@ pub extern "x86-interrupt" fn keyboard_irq(stack_frame: InterruptStackFrame) {
} }
// todo! we should abstract this away // todo! we should abstract this away
pub fn setup_apic_interrupts(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize) { pub fn setup_apic_interrupts(ioapicaddr: usize) {
// set keyboard irq to interrupt 40 // set keyboard irq to interrupt 40
ioapic_set_irq(mem_mapper, frame_alloc, ioapicaddr, 1, 0, 40); ioapic_set_irq(ioapicaddr, 1, 0, 40);
} }

View file

@ -25,6 +25,7 @@ use x86_64::registers::segmentation::{CS, Segment, SS};
use x86_64::structures::paging::Translate; use x86_64::structures::paging::Translate;
use crate::boot::KernelInfo; use crate::boot::KernelInfo;
use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::*; use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::*;
use crate::memory::{FRAME_ALLOC, MEM_MAPPER};
use crate::serial::terminal::ST; use crate::serial::terminal::ST;
mod font; mod font;
@ -165,17 +166,15 @@ pub extern fn kernel_main(args: KernelArgs) -> ! {
let kern_info = Mutex::new(KernelInfo::init_from_kernel_args(args)); let kern_info = Mutex::new(KernelInfo::init_from_kernel_args(args));
// memory stuff // memory stuff
let mut mapper = None;
let mut frame_allocator = None;
{ {
print!("initialising mapper..."); print!("initialising mapper...");
mapper = Some(unsafe { memory::init(VirtAddr::new(0)) }); MEM_MAPPER.lock().replace(unsafe { memory::init(VirtAddr::new(0)) });
println!("[OK]"); println!("[OK]");
print!("initialising frame allocator..."); print!("initialising frame allocator...");
frame_allocator = Some(unsafe { memory::BootInfoFrameAllocator::init(kern_info) }); FRAME_ALLOC.lock().replace(unsafe { memory::BootInfoFrameAllocator::init(kern_info) });
println!("[OK]"); println!("[OK]");
print!("initialising heap..."); print!("initialising heap...");
memory::allocator::init_heap(mapper.as_mut().unwrap(), frame_allocator.as_mut().unwrap()).expect("heap init failed"); memory::allocator::init_heap(MEM_MAPPER.lock().as_mut().unwrap(), FRAME_ALLOC.lock().as_mut().unwrap()).expect("heap init failed");
println!("[OK]"); println!("[OK]");
print!("testing heap..."); print!("testing heap...");
@ -206,10 +205,10 @@ pub extern fn kernel_main(args: KernelArgs) -> ! {
unsafe { internals::cpu::disable_pic() }; unsafe { internals::cpu::disable_pic() };
println!("[OK]"); println!("[OK]");
print!("initialising apic..."); print!("initialising apic...");
unsafe { internals::cpu::enable_apic(mapper.as_mut().unwrap(), frame_allocator.as_mut().unwrap()) }; unsafe { internals::cpu::enable_apic() };
println!("[OK]"); println!("[OK]");
print!("setting up apic interrupts..."); print!("setting up apic interrupts...");
unsafe { internals::cpu::setup_apic_interrupts(mapper.as_mut().unwrap(), frame_allocator.as_mut().unwrap()) }; unsafe { internals::cpu::setup_apic_interrupts() };
println!("[OK]"); println!("[OK]");
// enable interrupts // enable interrupts
x86_64::instructions::interrupts::enable(); x86_64::instructions::interrupts::enable();

View file

@ -2,9 +2,15 @@ pub mod allocator;
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::sync::Arc; use alloc::sync::Arc;
use lazy_static::lazy_static;
use x86_64::structures::paging::{FrameAllocator, Mapper, OffsetPageTable, PageTable, PhysFrame, Size4KiB, Translate}; use x86_64::structures::paging::{FrameAllocator, Mapper, OffsetPageTable, PageTable, PhysFrame, Size4KiB, Translate};
use x86_64::{PhysAddr, VirtAddr}; use x86_64::{PhysAddr, VirtAddr};
lazy_static!{
pub static ref MEM_MAPPER: Mutex<Option<OffsetPageTable>> = Mutex::new(None);
pub static ref FRAME_ALLOC: Mutex<Option<BootInfoFrameAllocator>> = Mutex::new(None);
}
pub struct Locked<A> { pub struct Locked<A> {
inner: spin::Mutex<A>, inner: spin::Mutex<A>,
} }
@ -86,26 +92,26 @@ unsafe impl FrameAllocator<Size4KiB> for BootInfoFrameAllocator {
} }
} }
pub fn read_phys_memory32(mem_mapper: &mut OffsetPageTable, frame_allocator: &mut BootInfoFrameAllocator, addr: u32) -> u32 { pub fn read_phys_memory32(addr: u32) -> u32 {
let initaladdr = VirtAddr::new(addr as u64); let initaladdr = VirtAddr::new(addr as u64);
let addr = unsafe { mem_mapper.translate_addr(initaladdr) }; let addr = unsafe { MEM_MAPPER.lock().as_mut().unwrap().translate_addr(initaladdr) };
if let Some(addr) = addr { if let Some(addr) = addr {
let addr = addr.as_u64() as *const u32; let addr = addr.as_u64() as *const u32;
unsafe { *addr } unsafe { *addr }
} else { } else {
debug!("read_phys_memory32: addr {:x} not mapped", initaladdr.as_u64()); debug!("read_phys_memory32: addr {:x} not mapped", initaladdr.as_u64());
// map the page // map the page
let frame = frame_allocator.allocate_frame().unwrap(); let frame = FRAME_ALLOC.lock().as_mut().unwrap().allocate_frame().unwrap();
debug!("allocated frame: {:?}", frame); debug!("allocated frame: {:?}", frame);
let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE; let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE;
let page = x86_64::structures::paging::Page::containing_address(initaladdr); let page = x86_64::structures::paging::Page::containing_address(initaladdr);
debug!("mapped page: {:?}", page); debug!("mapped page: {:?}", page);
let map_to_result = unsafe { mem_mapper.map_to(page, frame, flags, frame_allocator) }; 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); debug!("map_to_result: {:?}", map_to_result);
if map_to_result.is_err() { if map_to_result.is_err() {
panic!("Failed to map page"); panic!("Failed to map page");
} }
let addr = unsafe { mem_mapper.translate_addr(initaladdr) }; let addr = unsafe { MEM_MAPPER.lock().as_mut().unwrap().translate_addr(initaladdr) };
if let Some(addr) = addr { if let Some(addr) = addr {
let addr = addr.as_u64() as *const u32; let addr = addr.as_u64() as *const u32;
unsafe { *addr } unsafe { *addr }
@ -115,26 +121,26 @@ pub fn read_phys_memory32(mem_mapper: &mut OffsetPageTable, frame_allocator: &mu
} }
} }
pub fn write_phys_memory32(mem_mapper: &mut OffsetPageTable, frame_allocator: &mut BootInfoFrameAllocator, addr: u32, value: u32) { pub fn write_phys_memory32(addr: u32, value: u32) {
let initaladdr = VirtAddr::new(addr as u64); let initaladdr = VirtAddr::new(addr as u64);
let addr = unsafe { mem_mapper.translate_addr(initaladdr) }; let addr = unsafe { MEM_MAPPER.lock().as_mut().unwrap().translate_addr(initaladdr) };
if let Some(addr) = addr { if let Some(addr) = addr {
let addr = addr.as_u64() as *mut u32; let addr = addr.as_u64() as *mut u32;
unsafe { *addr = value }; unsafe { *addr = value };
} else { } else {
debug!("write_phys_memory32: addr {:x} not mapped", initaladdr.as_u64()); debug!("write_phys_memory32: addr {:x} not mapped", initaladdr.as_u64());
// map the page // map the page
let frame = frame_allocator.allocate_frame().unwrap(); let frame = FRAME_ALLOC.lock().as_mut().unwrap().allocate_frame().unwrap();
debug!("allocated frame: {:?}", frame); debug!("allocated frame: {:?}", frame);
let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE; let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE;
let page = x86_64::structures::paging::Page::containing_address(initaladdr); let page = x86_64::structures::paging::Page::containing_address(initaladdr);
debug!("mapped page: {:?}", page); debug!("mapped page: {:?}", page);
let map_to_result = unsafe { mem_mapper.map_to(page, frame, flags, frame_allocator) }; 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); debug!("map_to_result: {:?}", map_to_result);
if map_to_result.is_err() { if map_to_result.is_err() {
panic!("Failed to map page"); panic!("Failed to map page");
} }
let addr = unsafe { mem_mapper.translate_addr(initaladdr) }; let addr = unsafe { MEM_MAPPER.lock().as_mut().unwrap().translate_addr(initaladdr) };
if let Some(addr) = addr { if let Some(addr) = addr {
let addr = addr.as_u64() as *mut u32; let addr = addr.as_u64() as *mut u32;
unsafe { *addr = value }; unsafe { *addr = value };

View file

@ -74,6 +74,17 @@ pub fn read(port: u16) -> u8 {
data data
} }
// dummy functions for non-x86
#[cfg(not(any(target_arch="x86", target_arch="x86_64")))]
pub fn command(port: u16, data: u8) {
unimplemented!()
}
#[cfg(not(any(target_arch="x86", target_arch="x86_64")))]
pub fn read(port: u16) -> u8 {
unimplemented!()
}
impl Port { impl Port {
fn is_transmit_empty(&self) -> bool { fn is_transmit_empty(&self) -> bool {
let status = read(self.base as u16 + serial_offsets::LINE_STATUS as u16); let status = read(self.base as u16 + serial_offsets::LINE_STATUS as u16);