Wrote stack unwinder. NEEDTO: fix NoUnwindInfo

Probably incorrect PC was set.
This commit is contained in:
2025-03-05 22:21:38 +00:00
parent 8ee4af1a48
commit b26dc6de01
15 changed files with 435 additions and 175 deletions
+6 -6
View File
@@ -2,15 +2,15 @@
use core::arch::x86_64::__cpuid;
use crate::arch::x86_64::cpu::msr::*;
use crate::arch::x86_64::memory::mapping::PHYSICAL_MEMORY_OFFSET;
use crate::arch::x86_64::memory::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE};
use crate::{debugln, serial_print, serial_println};
use x86_64::structures::paging::Translate;
use x86_64::{
PhysAddr, VirtAddr,
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::memory::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE};
const IA32_APIC_BASE_MSR: u32 = 0x1b;
const IA32_APIC_BASE_MSR_BSP: u64 = 0x100;
@@ -53,7 +53,8 @@ fn write_apic_register(apic_base: &PhysAddr, reg: u64, value: u32) {
let virt_addr = unsafe { phys_to_virt(PhysAddr::new(reg_addr)) };
let phys_check = OFFSET_PAGE_TABLE.get().unwrap().lock().translate(virt_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 };
@@ -88,9 +89,8 @@ pub fn enable_apic() {
write_apic_register(
&apic_base_physical_addr,
0xF0,
read_apic_register(&apic_base_physical_addr, 0xF0) | 0x1FF
read_apic_register(&apic_base_physical_addr, 0xF0) | 0x1FF,
);
}
pub fn enable_timer() {
+22 -12
View File
@@ -1,9 +1,13 @@
use crate::{debug, serial_print};
use pic8259::ChainedPics;
use x86_64::registers::control::Cr2;
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
use x86_64::structures::idt::{
InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode,
};
use x86_64::structures::paging::mapper::MapperFlushAll;
use x86_64::structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB};
use x86_64::structures::paging::{
FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB,
};
use super::gdt;
use crate::arch::x86_64::memory::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE};
@@ -25,7 +29,8 @@ static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
idt.page_fault.set_handler_fn(page_fault_handler);
idt[InterruptIndex::Timer.as_u8()].set_handler_fn(timer_interrupt_handler);
idt[InterruptIndex::Keyboard.as_u8()].set_handler_fn(keyboard_interrupt_handler);
idt[InterruptIndex::Keyboard.as_u8()]
.set_handler_fn(keyboard_interrupt_handler);
idt
});
@@ -90,19 +95,22 @@ extern "x86-interrupt" fn double_fault_handler(
panic!("Exception: Double Fault\n{:#?}", stack_frame);
}
extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) {
extern "x86-interrupt" fn keyboard_interrupt_handler(
_stack_frame: InterruptStackFrame,
) {
use pc_keyboard::{HandleControl, Keyboard, ScancodeSet1, layouts};
// use pc_keyboard::DecodedKey;
use spin::Mutex;
use x86_64::instructions::port::Port;
static KEYBOARD: Lazy<Mutex<Keyboard<layouts::Uk105Key, ScancodeSet1>>> = Lazy::new(|| {
Mutex::new(Keyboard::new(
ScancodeSet1::new(),
layouts::Uk105Key,
HandleControl::Ignore,
))
});
static KEYBOARD: Lazy<Mutex<Keyboard<layouts::Uk105Key, ScancodeSet1>>> =
Lazy::new(|| {
Mutex::new(Keyboard::new(
ScancodeSet1::new(),
layouts::Uk105Key,
HandleControl::Ignore,
))
});
let _keyboard = KEYBOARD.lock();
let mut port = Port::new(0x60);
@@ -116,7 +124,9 @@ extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStac
}
}
extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) {
extern "x86-interrupt" fn timer_interrupt_handler(
_stack_frame: InterruptStackFrame,
) {
debug!("Timer Interrupt");
unsafe {
PICS.lock()
@@ -1,19 +1,25 @@
use crate::arch::x86_64::memory::allocation::page_alloc::FoundryOSFrameAllocator;
use crate::arch::x86_64::memory::units::MemoryUnits;
use crate::arch::x86_64::memory::{
FRAME_ALLOCATOR, HEAP_SIZE, HEAP_VIRTUAL_SPACE,
};
use crate::serial_println;
use crate::{debugln, serial_print};
use core::alloc::{GlobalAlloc, Layout};
use core::ptr;
use spin::{Mutex, MutexGuard};
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;
use x86_64::structures::paging::{
PageTableFlags, Size4KiB, mapper::MapToError,
};
/// We are currently using a linked list heap allocator which uses our underlying page allocator.
/// We are currently using a linked list heap allocator which uses our
/// underlying page allocator.
#[global_allocator]
/// This is now Rust's global allocator, so we can use stuff requiring heap allocations.
static ALLOCATOR: Locked<FoundryAllocator> = Locked::new(FoundryAllocator::new());
/// This is now Rust's global allocator, so we can use stuff requiring heap
/// allocations.
static ALLOCATOR: Locked<FoundryAllocator> =
Locked::new(FoundryAllocator::new());
/// Initializes the heap.
///
@@ -38,7 +44,8 @@ static ALLOCATOR: Locked<FoundryAllocator> = Locked::new(FoundryAllocator::new()
/// initialized successfully.
pub unsafe fn init_heap() -> Result<(), MapToError<Size4KiB>> {
unsafe {
// code to allocate frames is now done in the page fault interrupt handler!
// code to allocate frames is now done in the page fault interrupt
// handler!
ALLOCATOR.lock().init(HEAP_VIRTUAL_SPACE, HEAP_SIZE);
Ok(())
}
@@ -85,15 +92,17 @@ impl FoundryAllocator {
fallback: Locked::new(FoundryFallbackAllocator::new()),
}
}
/// Initializes the fallback allocator with the given heap start address and size.
/// Initializes the fallback allocator with the given heap start address and
/// size.
///
/// # Safety
///
/// This function is unsafe because it does not check whether the given heap start address and size are valid.
/// This function is unsafe because it does not check whether the given heap
/// start address and size are valid.
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 {
self.fallback.lock().init(heap_start, heap_size);
}
@@ -127,7 +136,9 @@ unsafe impl GlobalAlloc for Locked<FoundryAllocator> {
let block_size = BLOCK_SIZES[index];
// only works if all block sizes are a power of 2
let block_align = block_size;
let layout = Layout::from_size_align(block_size, block_align).unwrap();
let layout =
Layout::from_size_align(block_size, block_align)
.unwrap();
unsafe { allocator.fallback_alloc(layout) }
}
}
@@ -195,7 +206,8 @@ impl FoundryFallbackAllocator {
///
/// # Safety
///
/// This function is unsafe because it does not check whether the given heap start address and size are valid.
/// This function is unsafe because it does not check whether the given heap
/// start address and size are valid.
pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) {
unsafe { self.add_region(heap_start, heap_size) };
}
@@ -222,7 +234,9 @@ impl FoundryFallbackAllocator {
let mut current = &mut self.head;
// look for a large enough memory region in linked list
while let Some(ref mut region) = current.next {
if let Ok(alloc_start) = Self::alloc_from_region(region, size, align) {
if let Ok(alloc_start) =
Self::alloc_from_region(region, size, align)
{
// region suitable for allocation -> remove node from list
let next = region.next.take();
let ret = Some((current.next.take().unwrap(), alloc_start));
@@ -275,7 +289,8 @@ unsafe impl GlobalAlloc for Locked<FoundryFallbackAllocator> {
// perform layout adjustments
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 excess_size = region.end_addr() - alloc_end;
if excess_size > 0 {
@@ -291,7 +306,7 @@ unsafe impl GlobalAlloc for Locked<FoundryFallbackAllocator> {
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
let mut allocator = self.lock();
// perform layout adjustments
let (size, _) = FoundryFallbackAllocator::size_align(layout);
unsafe { allocator.add_region(ptr as usize, size) }
@@ -299,8 +314,13 @@ unsafe impl GlobalAlloc for Locked<FoundryFallbackAllocator> {
}
fn ensure_mapped(virt_addr: VirtAddr) {
if ! FoundryOSFrameAllocator::is_mapped(virt_addr) {
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();
foundry_alloc
.allocate_page(
virt_addr,
PageTableFlags::PRESENT | PageTableFlags::WRITABLE,
)
.unwrap();
}
}
}
@@ -1,10 +1,13 @@
use x86_64::structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, PhysFrame, Size4KiB, Translate};
use crate::arch::x86_64::memory::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE};
use limine::memory_map::EntryType;
use limine::response::MemoryMapResponse;
use spin::Mutex;
use limine::memory_map::EntryType;
use x86_64::{PhysAddr, VirtAddr};
use x86_64::structures::paging::mapper::{MapToError, TranslateResult};
use crate::arch::x86_64::memory::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE};
use x86_64::structures::paging::{
FrameAllocator, Mapper, Page, PageTableFlags, PhysFrame, Size4KiB,
Translate,
};
use x86_64::{PhysAddr, VirtAddr};
pub struct FoundryOSFrameAllocator {
memory_map: &'static MemoryMapResponse,
@@ -36,7 +39,9 @@ impl FoundryOSFrameAllocator {
.entries()
.iter()
.map(|region| region.base..region.base + region.length)
.flat_map(|r| r.step_by(4096)).count() as u64 * 4096
.flat_map(|r| r.step_by(4096))
.count() as u64
* 4096
}
/// An iterator over all usable frames in the memory map.
@@ -46,10 +51,14 @@ impl FoundryOSFrameAllocator {
/// This function is used to allocate frames for the page map.
fn usable_frames(&self) -> impl Iterator<Item = PhysFrame> + use<> {
let regions = self.memory_map.entries().iter();
let usable_regions = regions.filter(|region| region.entry_type == EntryType::USABLE);
let addr_ranges = usable_regions.map(|region| region.base..region.base + region.length);
let usable_regions =
regions.filter(|region| region.entry_type == EntryType::USABLE);
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));
frame_addresses.map(|addr| PhysFrame::from_start_address(PhysAddr::new(addr)).unwrap())
frame_addresses.map(|addr| {
PhysFrame::from_start_address(PhysAddr::new(addr)).unwrap()
})
}
pub(crate) fn is_mapped(virt_addr: VirtAddr) -> bool {
@@ -57,14 +66,18 @@ impl FoundryOSFrameAllocator {
matches!(mapper.translate(virt_addr), TranslateResult::Mapped { .. })
}
pub(crate) fn allocate_page(&mut self, 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::containing_address(start_addr);
let frame = self.allocate_frame().ok_or(MapToError::<Size4KiB>::FrameAllocationFailed)?;
let frame = self
.allocate_frame()
.ok_or(MapToError::<Size4KiB>::FrameAllocationFailed)?;
let mut mapper = OFFSET_PAGE_TABLE.get().unwrap().lock();
unsafe {
mapper.map_to(page, frame, flags, self)?
}.flush();
unsafe { mapper.map_to(page, frame, flags, self)? }.flush();
Ok(())
}
@@ -86,4 +99,4 @@ unsafe impl FrameAllocator<Size4KiB> for FoundryOSFrameAllocator {
self.next += 1;
frame
}
}
}