3 Commits

Author SHA1 Message Date
zxq5 8ee4af1a48 someone broke a mod.rs so i fixed it. 2025-03-05 21:10:36 +00:00
zxq5 03c07cb5c4 Merging with origin/unified 2025-03-05 21:04:58 +00:00
zxq5 ef70bcf51e - heap allocator now makes sure virtual memory pages are mapped before using them. this means we no longer have to use page faults to allocate frames, it is done automatically.
- fixed the apic code that caused a page fault. it now writes the correct values at the correct physical address
- improved startup logging including displaying how much RAM is installed.
2025-03-05 20:49:21 +00:00
8 changed files with 204 additions and 159 deletions
+30 -24
View File
@@ -3,12 +3,12 @@
use core::arch::x86_64::__cpuid; use core::arch::x86_64::__cpuid;
use crate::arch::x86_64::memory::mapping::PHYSICAL_MEMORY_OFFSET; use crate::arch::x86_64::memory::mapping::PHYSICAL_MEMORY_OFFSET;
use crate::{serial_print, serial_println}; use crate::{debugln, serial_print, serial_println};
use x86_64::{ use x86_64::{
PhysAddr, VirtAddr, PhysAddr, VirtAddr,
structures::paging::{Mapper, Page, PageTableFlags, PhysFrame, Size4KiB}, structures::paging::{Mapper, Page, PageTableFlags, PhysFrame, Size4KiB},
}; };
use x86_64::structures::paging::Translate;
use crate::arch::x86_64::cpu::msr::*; use crate::arch::x86_64::cpu::msr::*;
use crate::arch::x86_64::memory::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE}; use crate::arch::x86_64::memory::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE};
@@ -28,9 +28,11 @@ const CPUID_FEAT_EDX_APIC: u64 = 1 << 9; // the cpuid instruction will return th
fn set_apic_base_enable(apic: PhysAddr) { fn set_apic_base_enable(apic: PhysAddr) {
let rax = (apic.as_u64() & 0xfffff0000) | IA32_APIC_BASE_MSR_ENABLE; let rax = (apic.as_u64() & 0xfffff0000) | IA32_APIC_BASE_MSR_ENABLE;
debugln!("apic {:?}", PhysAddr::new(rax));
cpu_set_msr(IA32_APIC_BASE_MSR, rax); cpu_set_msr(IA32_APIC_BASE_MSR, rax);
} }
#[allow(dead_code)]
fn set_apic_base_disable(apic: PhysAddr) { fn set_apic_base_disable(apic: PhysAddr) {
let rax = (apic.as_u64() & 0xfffff0000) & IA32_APIC_BASE_MSR_DISABLE; let rax = (apic.as_u64() & 0xfffff0000) & IA32_APIC_BASE_MSR_DISABLE;
cpu_set_msr(IA32_APIC_BASE_MSR, rax); cpu_set_msr(IA32_APIC_BASE_MSR, rax);
@@ -39,22 +41,27 @@ fn set_apic_base_disable(apic: PhysAddr) {
fn get_apic_base() -> PhysAddr { fn get_apic_base() -> PhysAddr {
let mut value: u64 = 0; let mut value: u64 = 0;
cpu_get_msr(IA32_APIC_BASE_MSR, &mut value); cpu_get_msr(IA32_APIC_BASE_MSR, &mut value);
debugln!("apic base {:#x}", value);
PhysAddr::new(value & 0xfffff0000) PhysAddr::new(value & 0xfffff0000)
} }
fn write_apic_register(apic_base: &PhysAddr, reg: u8, value: u32) { fn write_apic_register(apic_base: &PhysAddr, reg: u64, value: u32) {
let apic_base = apic_base.as_u64(); let apic_base = apic_base.as_u64();
let reg_addr = (apic_base & 0xFFFFF0000) + reg as u64; let reg_addr = (apic_base & 0xFFFFF0000) + reg;
let virt_addr = unsafe { phys_to_virt(PhysAddr::new(reg_addr)) }; let virt_addr = unsafe { phys_to_virt(PhysAddr::new(reg_addr)) };
let phys_check = OFFSET_PAGE_TABLE.get().unwrap().lock().translate(virt_addr);
debugln!("{:?}", phys_check);
unsafe { *(virt_addr.as_u64() as *mut u32) = value }; unsafe { *(virt_addr.as_u64() as *mut u32) = value };
} }
fn read_apic_register(apic_base: &PhysAddr, reg: u8) -> u32 { fn read_apic_register(apic_base: &PhysAddr, reg: u64) -> u32 {
let apic_base = apic_base.as_u64(); let apic_base = apic_base.as_u64();
let reg_addr = (apic_base & 0xFFFFF0000) + reg as u64; let reg_addr = (apic_base & 0xFFFFF0000) + reg;
serial_println!("reading: {:?}", VirtAddr::new(reg_addr));
let virt_addr = unsafe { phys_to_virt(PhysAddr::new(reg_addr)) }; let virt_addr = unsafe { phys_to_virt(PhysAddr::new(reg_addr)) };
unsafe { *(virt_addr.as_u64() as *const u32) } unsafe { *(virt_addr.as_u64() as *const u32) }
} }
@@ -72,23 +79,22 @@ unsafe fn phys_to_virt(phys: PhysAddr) -> VirtAddr {
} }
pub fn enable_apic() { pub fn enable_apic() {
let mut mapper = OFFSET_PAGE_TABLE.get().unwrap().lock(); let apic_base_physical_addr = get_apic_base();
let mut frame_allocator = FRAME_ALLOCATOR.get().unwrap().lock(); set_apic_base_enable(apic_base_physical_addr);
let apic_phys_addr = get_apic_base(); debugln!("{:?}", apic_base_physical_addr);
set_apic_base_enable(apic_phys_addr); enable_timer();
// map virt address of apic
let apic_virt = unsafe { phys_to_virt(apic_phys_addr) };
serial_println!("Trying to map: {:?} -> {:?}", apic_virt, apic_phys_addr); write_apic_register(
&apic_base_physical_addr,
0xF0,
read_apic_register(&apic_base_physical_addr, 0xF0) | 0x1FF
);
// FIXME: this causes a page fault
// TODO: map to virtual memory
let reg = read_apic_register(&apic_phys_addr, 0xF0);
write_apic_register(&apic_phys_addr, 0xF0, reg | 0x100);
} }
pub struct Apic {} pub fn enable_timer() {
let apic_base = get_apic_base();
pub enum ApicVector {} let current = read_apic_register(&apic_base, 0x320);
write_apic_register(&get_apic_base(), 0x320, (current & 0xFFFFFF00) | 0x20);
}
+14 -23
View File
@@ -1,13 +1,9 @@
use crate::serial_print; use crate::{debug, serial_print};
use pic8259::ChainedPics; use pic8259::ChainedPics;
use x86_64::registers::control::Cr2; use x86_64::registers::control::Cr2;
use x86_64::structures::idt::{ use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode,
};
use x86_64::structures::paging::mapper::MapperFlushAll; use x86_64::structures::paging::mapper::MapperFlushAll;
use x86_64::structures::paging::{ use x86_64::structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB};
FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB,
};
use super::gdt; use super::gdt;
use crate::arch::x86_64::memory::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE}; use crate::arch::x86_64::memory::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE};
@@ -29,8 +25,7 @@ static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
idt.page_fault.set_handler_fn(page_fault_handler); idt.page_fault.set_handler_fn(page_fault_handler);
idt[InterruptIndex::Timer.as_u8()].set_handler_fn(timer_interrupt_handler); idt[InterruptIndex::Timer.as_u8()].set_handler_fn(timer_interrupt_handler);
idt[InterruptIndex::Keyboard.as_u8()] idt[InterruptIndex::Keyboard.as_u8()].set_handler_fn(keyboard_interrupt_handler);
.set_handler_fn(keyboard_interrupt_handler);
idt idt
}); });
@@ -95,22 +90,19 @@ extern "x86-interrupt" fn double_fault_handler(
panic!("Exception: Double Fault\n{:#?}", stack_frame); panic!("Exception: Double Fault\n{:#?}", stack_frame);
} }
extern "x86-interrupt" fn keyboard_interrupt_handler( extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) {
_stack_frame: InterruptStackFrame,
) {
use pc_keyboard::{HandleControl, Keyboard, ScancodeSet1, layouts}; use pc_keyboard::{HandleControl, Keyboard, ScancodeSet1, layouts};
// use pc_keyboard::DecodedKey; // use pc_keyboard::DecodedKey;
use spin::Mutex; use spin::Mutex;
use x86_64::instructions::port::Port; use x86_64::instructions::port::Port;
static KEYBOARD: Lazy<Mutex<Keyboard<layouts::Uk105Key, ScancodeSet1>>> = static KEYBOARD: Lazy<Mutex<Keyboard<layouts::Uk105Key, ScancodeSet1>>> = Lazy::new(|| {
Lazy::new(|| { Mutex::new(Keyboard::new(
Mutex::new(Keyboard::new( ScancodeSet1::new(),
ScancodeSet1::new(), layouts::Uk105Key,
layouts::Uk105Key, HandleControl::Ignore,
HandleControl::Ignore, ))
)) });
});
let _keyboard = KEYBOARD.lock(); let _keyboard = KEYBOARD.lock();
let mut port = Port::new(0x60); let mut port = Port::new(0x60);
@@ -124,9 +116,8 @@ extern "x86-interrupt" fn keyboard_interrupt_handler(
} }
} }
extern "x86-interrupt" fn timer_interrupt_handler( extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) {
_stack_frame: InterruptStackFrame, debug!("Timer Interrupt");
) {
unsafe { unsafe {
PICS.lock() PICS.lock()
.notify_end_of_interrupt(InterruptIndex::Timer.as_u8()); .notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
@@ -1,27 +1,44 @@
use crate::arch::x86_64::memory::{HEAP_SIZE, HEAP_VIRTUAL_SPACE}; use crate::{debugln, serial_print};
use core::alloc::{GlobalAlloc, Layout}; use core::alloc::{GlobalAlloc, Layout};
use core::ptr; use core::ptr;
use spin::{Mutex, MutexGuard}; use spin::{Mutex, MutexGuard};
use x86_64::structures::paging::{Size4KiB, mapper::MapToError}; use x86_64::structures::paging::{Size4KiB, mapper::MapToError, PageTableFlags};
use x86_64::VirtAddr;
use crate::arch::x86_64::memory::{FRAME_ALLOCATOR, HEAP_SIZE, HEAP_VIRTUAL_SPACE};
use crate::arch::x86_64::memory::allocation::page_alloc::FoundryOSFrameAllocator;
use crate::arch::x86_64::memory::units::MemoryUnits;
use crate::serial_println;
/// We are currently using a linked list heap allocator which uses our /// We are currently using a linked list heap allocator which uses our underlying page allocator.
/// underlying page allocator.
#[global_allocator] #[global_allocator]
/// This is now Rust's global allocator, so we can use stuff requiring heap /// This is now Rust's global allocator, so we can use stuff requiring heap allocations.
/// allocations. static ALLOCATOR: Locked<FoundryAllocator> = Locked::new(FoundryAllocator::new());
static ALLOCATOR: Locked<FoundryAllocator> =
Locked::new(FoundryAllocator::new());
/// Sets up the heap using the backing page frame allocator.
/// Initializes the heap.
///
/// This function must be called once, before any functions that
/// require a heap are called. It sets up the heap by allocating
/// the necessary frames from the page allocator. The heap is
/// then ready for use.
/// ///
/// # Safety /// # Safety
/// ///
/// We do not check whether the given heap start address and size are actually /// This function must be called only once, and must be called before any types
/// valid. /// are constructed that require dynamic memory allocation.
///
/// # Parameters
///
/// None
///
/// # Returns
///
/// Returns a `Result` containing a `MapToError` if the heap
/// could not be initialized, or `Ok` if the heap was
/// initialized successfully.
pub unsafe fn init_heap() -> Result<(), MapToError<Size4KiB>> { pub unsafe fn init_heap() -> Result<(), MapToError<Size4KiB>> {
unsafe { unsafe {
// The code to allocate frames is now done in the page fault interrupt // code to allocate frames is now done in the page fault interrupt handler!
// handler!
ALLOCATOR.lock().init(HEAP_VIRTUAL_SPACE, HEAP_SIZE); ALLOCATOR.lock().init(HEAP_VIRTUAL_SPACE, HEAP_SIZE);
Ok(()) Ok(())
} }
@@ -68,14 +85,15 @@ impl FoundryAllocator {
fallback: Locked::new(FoundryFallbackAllocator::new()), fallback: Locked::new(FoundryFallbackAllocator::new()),
} }
} }
/// Initializes the fallback allocator with the given heap start address and /// Initializes the fallback allocator with the given heap start address and size.
/// size.
/// ///
/// # Safety /// # Safety
/// ///
/// This function is unsafe because it does not check whether the given heap /// This function is unsafe because it does not check whether the given heap start address and size are valid.
/// start address and size are valid.
pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) { pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) {
debugln!(" => Start: {:?}", VirtAddr::new(heap_start as u64));
debugln!(" => Size: {}", MemoryUnits::from_bytes(heap_size));
unsafe { unsafe {
self.fallback.lock().init(heap_start, heap_size); self.fallback.lock().init(heap_start, heap_size);
} }
@@ -100,16 +118,16 @@ unsafe impl GlobalAlloc for Locked<FoundryAllocator> {
match allocator.list_heads[index].take() { match allocator.list_heads[index].take() {
Some(node) => { Some(node) => {
allocator.list_heads[index] = node.next.take(); allocator.list_heads[index] = node.next.take();
node as *mut ListNode as *mut u8 let ptr = node as *mut ListNode as *mut u8;
ensure_mapped(VirtAddr::new(ptr as u64));
ptr
} }
None => { None => {
// no block exists in list => allocate new block // no block exists in list => allocate new block
let block_size = BLOCK_SIZES[index]; let block_size = BLOCK_SIZES[index];
// only works if all block sizes are a power of 2 // only works if all block sizes are a power of 2
let block_align = block_size; let block_align = block_size;
let layout = let layout = Layout::from_size_align(block_size, block_align).unwrap();
Layout::from_size_align(block_size, block_align)
.unwrap();
unsafe { allocator.fallback_alloc(layout) } unsafe { allocator.fallback_alloc(layout) }
} }
} }
@@ -173,22 +191,24 @@ impl FoundryFallbackAllocator {
} }
} }
/// Initialises the Foundry OS fallback allocator. This is currently a /// Initializes the allocator with a given heap start address and size.
/// linked list allocator pulled from the linked_list_allocator crate.
/// ///
/// # Safety /// # Safety
/// ///
/// This function assumes you passed a valid `heap_start` and `heap_size`, /// This function is unsafe because it does not check whether the given heap start address and size are valid.
/// as these are unchecked.
pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) { pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) {
unsafe { self.add_region(heap_start, heap_size) }; unsafe { self.add_region(heap_start, heap_size) };
} }
unsafe fn add_region(&mut self, addr: usize, size: usize) { unsafe fn add_region(&mut self, addr: usize, size: usize) {
let mut node = FallbackListNode::new(size);
node.next = self.head.next.take();
let node_ptr = addr as *mut FallbackListNode;
unsafe { unsafe {
let mut node = FallbackListNode::new(size);
node.next = self.head.next.take();
let virt_addr = VirtAddr::new(addr as u64);
ensure_mapped(virt_addr);
let node_ptr = addr as *mut FallbackListNode;
node_ptr.write(node); node_ptr.write(node);
self.head.next = Some(&mut *node_ptr); self.head.next = Some(&mut *node_ptr);
} }
@@ -202,9 +222,7 @@ impl FoundryFallbackAllocator {
let mut current = &mut self.head; let mut current = &mut self.head;
// look for a large enough memory region in linked list // look for a large enough memory region in linked list
while let Some(ref mut region) = current.next { while let Some(ref mut region) = current.next {
if let Ok(alloc_start) = if let Ok(alloc_start) = Self::alloc_from_region(region, size, align) {
Self::alloc_from_region(region, size, align)
{
// region suitable for allocation -> remove node from list // region suitable for allocation -> remove node from list
let next = region.next.take(); let next = region.next.take();
let ret = Some((current.next.take().unwrap(), alloc_start)); let ret = Some((current.next.take().unwrap(), alloc_start));
@@ -257,14 +275,15 @@ unsafe impl GlobalAlloc for Locked<FoundryFallbackAllocator> {
// perform layout adjustments // perform layout adjustments
let (size, align) = FoundryFallbackAllocator::size_align(layout); let (size, align) = FoundryFallbackAllocator::size_align(layout);
if let Some((region, alloc_start)) = allocator.find_region(size, align) if let Some((region, alloc_start)) = allocator.find_region(size, align) {
{
let alloc_end = alloc_start.checked_add(size).expect("overflow"); let alloc_end = alloc_start.checked_add(size).expect("overflow");
let excess_size = region.end_addr() - alloc_end; let excess_size = region.end_addr() - alloc_end;
if excess_size > 0 { if excess_size > 0 {
unsafe { allocator.add_region(alloc_end, excess_size) }; unsafe { allocator.add_region(alloc_end, excess_size) };
} }
alloc_start as *mut u8 let ptr = alloc_start as *mut u8;
ensure_mapped(VirtAddr::new(ptr as u64));
ptr
} else { } else {
ptr::null_mut() ptr::null_mut()
} }
@@ -275,7 +294,13 @@ unsafe impl GlobalAlloc for Locked<FoundryFallbackAllocator> {
// perform layout adjustments // perform layout adjustments
let (size, _) = FoundryFallbackAllocator::size_align(layout); let (size, _) = FoundryFallbackAllocator::size_align(layout);
unsafe { allocator.add_region(ptr as usize, size) } unsafe { allocator.add_region(ptr as usize, size) }
} }
} }
fn ensure_mapped(virt_addr: VirtAddr) {
if ! FoundryOSFrameAllocator::is_mapped(virt_addr) {
let mut foundry_alloc = FRAME_ALLOCATOR.get().unwrap().lock();
foundry_alloc.allocate_page(virt_addr, PageTableFlags::PRESENT | PageTableFlags::WRITABLE).unwrap();
}
}
@@ -1,12 +1,10 @@
use crate::arch::x86_64::memory::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE}; use x86_64::structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, PhysFrame, Size4KiB, Translate};
use limine::memory_map::EntryType;
use limine::response::MemoryMapResponse; use limine::response::MemoryMapResponse;
use spin::Mutex; use spin::Mutex;
use x86_64::structures::paging::mapper::MapToError; use limine::memory_map::EntryType;
use x86_64::structures::paging::{
FrameAllocator, Mapper, Page, PageTableFlags, PhysFrame, Size4KiB,
};
use x86_64::{PhysAddr, VirtAddr}; use x86_64::{PhysAddr, VirtAddr};
use x86_64::structures::paging::mapper::{MapToError, TranslateResult};
use crate::arch::x86_64::memory::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE};
pub struct FoundryOSFrameAllocator { pub struct FoundryOSFrameAllocator {
memory_map: &'static MemoryMapResponse, memory_map: &'static MemoryMapResponse,
@@ -29,51 +27,45 @@ impl FoundryOSFrameAllocator {
}); });
} }
pub fn count_usable_frames(&self) -> u32 { pub fn count_usable_frames(&self) -> u64 {
self.usable_frames().count() as u32 self.usable_frames().count() as u64
} }
pub fn available_memory(&self) -> u64 { pub fn available_memory(&self) -> u64 {
(self.memory_map.entries().len() * 4096) as u64 // multiply the number of physical frames by 4096 to get the memory size self.memory_map
.entries()
.iter()
.map(|region| region.base..region.base + region.length)
.flat_map(|r| r.step_by(4096)).count() as u64 * 4096
} }
/// An iterator over all usable frames in the memory map. /// An iterator over all usable frames in the memory map.
/// ///
/// Yields one `PhysFrame` for each available 4KiB frame in the memory map. /// Yields one `PhysFrame` for each available 4KiB frame in the memory map.
/// ///
/// This function is used to allocate frames for the pagemap. /// This function is used to allocate frames for the page map.
fn usable_frames(&self) -> impl Iterator<Item = PhysFrame> + use<> { fn usable_frames(&self) -> impl Iterator<Item = PhysFrame> + use<> {
let regions = self.memory_map.entries().iter(); let regions = self.memory_map.entries().iter();
let usable_regions = let usable_regions = regions.filter(|region| region.entry_type == EntryType::USABLE);
regions.filter(|region| region.entry_type == EntryType::USABLE); let addr_ranges = usable_regions.map(|region| region.base..region.base + region.length);
let addr_ranges = usable_regions
.map(|region| region.base..region.base + region.length);
let frame_addresses = addr_ranges.flat_map(|r| r.step_by(4096)); let frame_addresses = addr_ranges.flat_map(|r| r.step_by(4096));
frame_addresses.map(|addr| { frame_addresses.map(|addr| PhysFrame::from_start_address(PhysAddr::new(addr)).unwrap())
PhysFrame::from_start_address(PhysAddr::new(addr)).unwrap()
})
} }
#[expect(unused)] pub(crate) fn is_mapped(virt_addr: VirtAddr) -> bool {
fn allocate_page( let mapper = OFFSET_PAGE_TABLE.get().unwrap().lock();
&mut self, matches!(mapper.translate(virt_addr), TranslateResult::Mapped { .. })
start_addr: VirtAddr, }
flags: PageTableFlags,
) -> Result<(), MapToError<Size4KiB>> { pub(crate) fn allocate_page(&mut self, start_addr: VirtAddr, flags: PageTableFlags) -> Result<(), MapToError<Size4KiB>> {
let page = Page::from_start_address(start_addr) let page = Page::containing_address(start_addr);
.map_err(|_| MapToError::FrameAllocationFailed)?; let frame = self.allocate_frame().ok_or(MapToError::<Size4KiB>::FrameAllocationFailed)?;
let frame = self let mut mapper = OFFSET_PAGE_TABLE.get().unwrap().lock();
.allocate_frame()
.ok_or(MapToError::FrameAllocationFailed)?; unsafe {
let _ = unsafe { mapper.map_to(page, frame, flags, self)?
let mut mapper = OFFSET_PAGE_TABLE.get().unwrap().lock(); }.flush();
mapper.map_to(
page,
frame,
flags,
&mut *FRAME_ALLOCATOR.get().unwrap().lock(),
)?
};
Ok(()) Ok(())
} }
} }
+44 -30
View File
@@ -12,16 +12,20 @@
)] )]
extern crate alloc; extern crate alloc;
use crate::arch::x86_64::cpu::apic::enable_apic;
use crate::{arch::x86_64::memory::init_page_table, prelude::*}; use crate::{arch::x86_64::memory::init_page_table, prelude::*};
use arch::x86_64::memory::allocation::heap_alloc::init_heap; use arch::x86_64::memory::allocation::heap_alloc::init_heap;
use arch::x86_64::memory::allocation::page_alloc::FoundryOSFrameAllocator;
use arch::x86_64::memory::mapping; use arch::x86_64::memory::mapping;
use core::arch::asm; use core::arch::asm;
use limine::BaseRevision; use limine::BaseRevision;
use std::unwind; use std::unwind;
use std::unwind::eh_info::ELF; use std::unwind::eh_info::ELF;
use x86_64::VirtAddr; use x86_64::VirtAddr;
use arch::x86_64::memory::allocation::page_alloc::FoundryOSFrameAllocator;
use crate::arch::x86_64::cpu::apic::enable_apic;
use crate::arch::x86_64::drivers::ascii::screensize_chars;
use crate::arch::x86_64::drivers::framebuffer::display::screensize_px;
use crate::arch::x86_64::memory::FRAME_ALLOCATOR;
use crate::arch::x86_64::memory::units::MemoryUnits;
pub mod arch; pub mod arch;
mod panic; mod panic;
@@ -34,7 +38,9 @@ pub mod prelude {
pub use crate::{ pub use crate::{
eprint, eprintln, print, print_log, println, println_log, serial_print, eprint, eprintln, print, print_log, println, println_log, serial_print,
serial_println, serial_println,
std::io::{_print, _print_err, _print_log, _serial_write}, debug, debugln,
std::io::{_print, _print_log, _serial_write, _print_err},
std::debug::_debug,
}; };
} }
@@ -74,53 +80,61 @@ pub fn boot() -> Result<(), &'static str> {
let memory_map = mapping::get_memory_map(); let memory_map = mapping::get_memory_map();
print_log!(" Initialising Serial... "); print_log!(" Initialising Serial... ");
if arch::x86_64::drivers::serial::init().is_err() { let res = arch::x86_64::drivers::serial::init();
println_log!("[Not Detected]") serial_print!(" Initialising Serial... ");
if res.is_err() {
debugln!("[Not Detected]")
} else { } else {
println_log!("[Success]"); debugln!("[Success]");
} }
print_log!(" Setting Up Global Descriptor Table... "); debugln!(" Display...");
let dimensions = screensize_chars();
let dimensions2 = screensize_px();
debugln!(" => (px) : {}x{} ", dimensions2.0, dimensions2.1);
debugln!(" => (chars) : {}x{} ", dimensions.0, dimensions.1);
debugln!(" [Success]");
debug!(" Setting Up Global Descriptor Table... ");
gdt::init(); gdt::init();
println_log!("[Success]"); debugln!("[Success]");
print_log!(" Setting Up Interrupt Descriptor Table... "); debug!(" Setting Up Interrupt Descriptor Table... ");
interrupts::init_idt(); interrupts::init_idt();
println_log!("[Success]"); debugln!("[Success]");
print_log!(" Initialising Memory Subsystem... "); debugln!(" Initialising Memory Subsystem... ");
let physical_memory_offset = let physical_memory_offset = VirtAddr::new(*mapping::PHYSICAL_MEMORY_OFFSET);
VirtAddr::new(*mapping::PHYSICAL_MEMORY_OFFSET);
init_page_table(physical_memory_offset); init_page_table(physical_memory_offset);
println_log!("[Success]");
print_log!(" Setting Up Page Table... ");
FoundryOSFrameAllocator::init(memory_map); FoundryOSFrameAllocator::init(memory_map);
println_log!("[Success]"); let available_bytes = FRAME_ALLOCATOR.get().unwrap().lock().available_memory();
debugln!(" => Available Memory: {}", MemoryUnits::from_bytes(available_bytes as usize));
print_log!(" Initialising Heap... "); debugln!("[Success]");
debugln!(" Initialising Heap... ");
if unsafe { init_heap() }.is_err() { if unsafe { init_heap() }.is_err() {
return Err("Failed to initialise heap: error"); return Err("Failed to initialise heap: error");
} }
println_log!("[Success]"); debugln!(" [Success]");
// print_log!(" Enabling PICs... "); // debug!(" Enabling PICs... ");
// interrupts::enable_pic(); // interrupts::enable_pic();
// println_log!("[Success]"); // debugln!("[Success]");
// print_log!(" Disabling PICs... "); debug!(" Disabling PICs... ");
// interrupts::disable_pic(); interrupts::disable_pic();
// println_log!("[Success]"); debugln!("[Success]");
print_log!(" Initialising APIC... "); debug!(" Initialising APIC... ");
enable_apic(); enable_apic();
println_log!("[Success]"); debugln!("[Success]");
print_log!(" Enabling Interrupts... "); debug!(" Enabling Interrupts... ");
x86_64::instructions::interrupts::enable(); x86_64::instructions::interrupts::enable();
println_log!("[Success]"); debugln!("[Success]");
print_log!(" Setting up stack unwinder, panic handler... "); debug!(" Setting up stack unwinder, panic handler... ");
// Setup stack traces and proper panic handler. TODO: Handle panics // Setup stack traces and proper panic handler. TODO: Handle panics
// differently if not initialised. // differently if not initialised.
let eh_frame_ptr = ELF let eh_frame_ptr = ELF
@@ -129,7 +143,7 @@ pub fn boot() -> Result<(), &'static str> {
let _eh_info = let _eh_info =
unsafe { unwind::eh_info::EhInfo::from_hdr_ptr(eh_frame_ptr) }; unsafe { unwind::eh_info::EhInfo::from_hdr_ptr(eh_frame_ptr) };
println_log!("[Success]"); debugln!("[Success]");
Ok(()) Ok(())
} }
+1 -7
View File
@@ -15,13 +15,7 @@ extern "C" fn kmain() -> ! {
panic!("{}", err); panic!("{}", err);
} }
println_log!("[ Kernel Initialised Successfully ] "); println_log!(" [ Kernel Initialised Successfully ] ");
let dimensions = screensize_chars();
let dimensions2 = screensize_px();
println!("Dimensions: {}x{} (px)", dimensions2.0, dimensions2.1);
println!("Dimensions: {}x{} (chars)", dimensions.0, dimensions.1);
// println!("TESTING :: Allocation"); // println!("TESTING :: Allocation");
// let somevec = vec![0; 1_000_000]; // let somevec = vec![0; 1_000_000];
+22
View File
@@ -0,0 +1,22 @@
use core::fmt;
use x86_64::instructions::interrupts;
use crate::prelude::{_print_log, _serial_write};
#[macro_export]
macro_rules! debugln {
() => ($crate::print_log!("\n"));
($($arg:tt)*) => ($crate::debug!("{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! debug {
($($arg:tt)*) => ($crate::prelude::_debug(format_args!($($arg)*)));
}
pub fn _debug(args: fmt::Arguments) {
interrupts::without_interrupts(|| {
_print_log(args);
_serial_write(args);
});
}
+1
View File
@@ -4,3 +4,4 @@ pub mod elf;
pub mod io; pub mod io;
pub mod maths; pub mod maths;
pub mod unwind; pub mod unwind;
pub mod debug;