wtf double fault ):

This commit is contained in:
fekhesk 2022-10-27 20:08:32 -07:00
parent 8af40d0414
commit d11d5ddd97
No known key found for this signature in database
GPG key ID: 6B3D8CB511646891
6 changed files with 143 additions and 80 deletions

View file

@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
spin = "0.9.1"
x86_64 = "0.14.10"
x86 = "0.52.0"
x2apic = "0.4.1"
rlibc = "1.0"
limine = { version = "0.1.9", optional = true }
acpi = { version = "4.1.1", optional = true }

View file

@ -12,7 +12,50 @@ debug: IDT loaded
welcome to wukkOS!
(c) 2022 Real Microsoft, LLC
initialising mapper...[OK]
initialising mapper...[debug] kernel physical address: 0x19b3d000
[debug] kernel virtual address: 0xffffffff80000000
[OK]
initialising frame allocator...[OK]
initialising heap...[OK]
testing heap...[OK]
checking for apic compatibility...[OK]
initialising apic...[debug] Mapping physical region: 1fb7e014 - 1fb7e038
[debug] Mapping physical region: 1fb7d0e8 - 1fb7d10c
[WARN] failed to unmap page (this is normal)
[debug] Mapping physical region: 1fb7d0e8 - 1fb7d134
[debug] Mapping physical region: 1fb7a000 - 1fb7a024
[WARN] failed to unmap page (this is normal)
[debug] Mapping physical region: 1fb7a000 - 1fb7a114
[debug] Mapping physical region: 1fb7b000 - 1fb7b024
[WARN] failed to unmap page (this is normal)
[WARN] failed to unmap page (this is normal)
[debug] Mapping physical region: 1fb79000 - 1fb79024
[WARN] failed to unmap page (this is normal)
[debug] Mapping physical region: 1fb78000 - 1fb78024
[WARN] failed to unmap page (this is normal)
[debug] Mapping physical region: 1fb77000 - 1fb77024
[WARN] failed to unmap page (this is normal)
[debug] Mapping physical region: 1fb76000 - 1fb76024
[WARN] failed to unmap page (this is normal)
[WARN] failed to unmap page (this is normal)
[WARN] failed to unmap page (this is normal)
[debug] Mapping physical region: 1fb7a000 - 1fb7a074
[debug] Mapping physical region: 1fb79000 - 1fb79078
[WARN] failed to unmap page (this is normal)
[WARN] failed to unmap page (this is normal)
[OK]
setting up apic interrupts...[debug] ioapicaddr: 0xfec00000
[OK]
---KERNEL FUCKY WUKKY UWU---
double fault!
stack frame: InterruptStackFrame {
instruction_pointer: VirtAddr(
0xffffffff80004729,
),
code_segment: 8,
cpu_flags: 0x282,
stack_pointer: VirtAddr(
0xffff800019b3bd00,
),
stack_segment: 16,
}

View file

@ -1,39 +1,36 @@
use alloc::sync::Arc;
use core::marker::PhantomData;
use core::ptr::NonNull;
use acpi::{AcpiHandler, InterruptModel, PhysicalMapping};
use limine::LimineTerminalResponse;
use crate::{debug, println, TERMINAL_REQUEST};
use acpi::{AcpiHandler, AcpiTables, InterruptModel, PhysicalMapping};
use limine::{LimineBootInfoRequest, LimineKernelAddressRequest, LimineMemmapRequest, LimineTerminalRequest, LimineTerminalResponse, LimineRsdpRequest};
use crate::{debug, println};
#[cfg(feature = "f_multiboot2")]
use multiboot2::{load, MemoryMapTag, BootInformation};
use x86_64::structures::paging::{FrameAllocator, Mapper, OffsetPageTable, Page, Translate};
use x86_64::VirtAddr;
use crate::memory::{BootInfoFrameAllocator, FRAME_ALLOC, MEM_MAPPER, PageSize, read_phys_memory32};
use crate::memory::{BootInfoFrameAllocator, FRAME_ALLOC, MEM_MAPPER, PageSize, read_phys_memory32, VIRT_MEM_OFFSET};
use crate::serial::terminal::ST;
pub static BOOTLOADER_INFO: LimineBootInfoRequest = LimineBootInfoRequest::new(0);
pub static TERMINAL_REQUEST: LimineTerminalRequest = LimineTerminalRequest::new(0);
pub static MEM_MAP: LimineMemmapRequest = LimineMemmapRequest::new(0);
pub static RSDP_REQUEST: LimineRsdpRequest = LimineRsdpRequest::new(0);
pub static KERNEL_ADDRESS: LimineKernelAddressRequest = LimineKernelAddressRequest::new(0);
#[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);
let mut i = 0;
while i < size {
let _ = read_phys_memory32(physical_address as u32 + i as u32);
i += 4;
}
let addr = unsafe { MEM_MAPPER.lock().as_mut().unwrap().translate_addr(VirtAddr::new(physical_address as u64)) };
if let Some(addr) = addr.clone() {
// 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");
}
unsafe fn map_physical_region<T>(&self, physical_address: usize, size: usize) -> PhysicalMapping<Self, T> { // todo! check if size is too big
// only get lower 32 bits of physical address
let physical_address = physical_address as u32;
debug!("Mapping physical region: {:x} - {:x}", physical_address, physical_address + size as u32);
let _ = read_phys_memory32(physical_address as u32) as usize;
PhysicalMapping::new(
physical_address as usize,
NonNull::new_unchecked(physical_address as *mut T),
size, size,
Self)
}
fn unmap_physical_region<T>(region: &PhysicalMapping<Self, T>) {
@ -42,8 +39,9 @@ impl AcpiHandler for Handler {
// 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");
println!("[WARN] failed to unmap page (this is normal)");
}
}
}
@ -68,4 +66,17 @@ impl core::fmt::Write for LimineWriter {
}
Ok(())
}
}
pub fn get_ioapic_addr() -> u32 {
let rsdp = RSDP_REQUEST.get_response().get().unwrap();
let rsdp_ptr = rsdp.address.get().unwrap() as *const u8;
let tables = unsafe { AcpiTables::from_rsdp(Handler, rsdp_ptr as usize).unwrap() };
let platform_info = tables.platform_info().expect("no platform info");
let interrupt_model = platform_info.interrupt_model;
let ioapic_addr = match interrupt_model {
InterruptModel::Apic(apic) => apic.io_apics[0].address,
_ => panic!("unsupported interrupt model"),
};
ioapic_addr
}

View file

@ -1,5 +1,6 @@
use core::arch::asm;
use x86::apic::{xapic::XAPIC, ioapic::IoApic, ApicControl};
use x2apic::ioapic::{IoApic, IrqFlags, IrqMode, RedirectionTableEntry};
use x2apic::lapic::{LocalApicBuilder, xapic_base};
use x86_64::PhysAddr;
use x86_64::structures::idt::InterruptStackFrame;
use x86_64::structures::paging::PhysFrame;
@ -9,15 +10,6 @@ use crate::serial::{command, read};
// todo! maybe abstract this into different sections for different parts of cpu func?
pub struct WAPICManager {
pub xapic: XAPIC,
pub id: u32,
}
pub struct WIOAPICManager {
pub ioapic: IoApic,
}
pub fn check_apic_compat() -> bool {
unsafe {
let mut eax: u32;
@ -31,34 +23,35 @@ pub fn check_apic_compat() -> bool {
}
}
pub fn enable_apic() -> WAPICManager {
pub fn enable_apic() {
// we need to get the xapic region
let mut XAPIC_REGION: &'static mut [u32] = unsafe {
// region should be FFFE0000H to FFFE0FFFH
let region_start = 0xFFFE_0000u32;
let region_end = 0xFFFE_0FFFu32;
let region_size = region_end - region_start;
let region_size = region_size as usize;
let region_start = region_start as *mut u32;
// read to make sure it gets mapped
let _ = read_phys_memory32(region_start as u32);
let _ = read_phys_memory32(region_end as u32);
core::slice::from_raw_parts_mut(region_start, region_size)
};
let mut xapic = unsafe { XAPIC::new(XAPIC_REGION) };
xapic.attach();
let phys_addr = unsafe { xapic_base() };
// get xapic id to ensure it's working
let id = xapic.id();
debug!("xapic id: {}", id);
debug!("xapic version: {}", xapic.version());
WAPICManager {
xapic,
id,
let mut lapic = LocalApicBuilder::new()
.timer_vector(0x40)
.error_vector(0x41)
.spurious_vector(0x42)
.set_xapic_base(phys_addr)
.build()
.unwrap_or_else(|e| panic!("failed to build local apic: {}", e));
unsafe {
lapic.enable();
}
}
pub extern "x86-interrupt" fn timer(stack_frame: InterruptStackFrame) {
println!("timer interrupt");
}
pub extern "x86-interrupt" fn error(stack_frame: InterruptStackFrame) {
println!("error interrupt");
}
pub extern "x86-interrupt" fn spurious(stack_frame: InterruptStackFrame) {
println!("spurious interrupt");
}
// todo! in the future this will be removed, it is only for testing basic apic functionality
pub extern "x86-interrupt" fn keyboard_irq(stack_frame: InterruptStackFrame) {
debug!("keyboard interrupt");
@ -76,16 +69,21 @@ pub extern "x86-interrupt" fn keyboard_irq(stack_frame: InterruptStackFrame) {
}
// todo! we should abstract this away
pub fn setup_ioapic(ioapicaddr: u32) -> WIOAPICManager {
let mut ioapic = unsafe { IoApic::new(ioapicaddr as usize) };
let _ = read_phys_memory32(ioapicaddr);
// assert that supported interrupts is greater than 1
debug!("ioapic supported interrupts: {}", ioapic.supported_interrupts());
// setup keyboard irq (interrupt 0x40)
ioapic.enable(1, 0x40);
pub fn setup_ioapic(ioapicaddr: u32) {
let mut ioapic = unsafe {
IoApic::new(ioapicaddr as u64)
};
// setup keyboard interrupt
unsafe {
// init with irq offset
ioapic.init(0x50);
let mut entry = RedirectionTableEntry::default();
entry.set_mode(IrqMode::Fixed);
entry.set_flags(IrqFlags::LEVEL_TRIGGERED | IrqFlags::LOW_ACTIVE | IrqFlags::MASKED);
entry.set_dest(0);
ioapic.set_table_entry(1, entry);
// return
WIOAPICManager {
ioapic,
ioapic.enable_irq(1);
}
}

View file

@ -24,6 +24,7 @@ use x86_64::structures::tss::TaskStateSegment;
use x86_64::{PhysAddr, VirtAddr};
use x86_64::registers::segmentation::{CS, Segment, SS};
use x86_64::structures::paging::Translate;
use crate::boot::{get_ioapic_addr, KERNEL_ADDRESS};
use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::*;
use crate::memory::{FRAME_ALLOC, MEM_MAPPER};
use crate::serial::terminal::ST;
@ -36,10 +37,6 @@ mod boot;
mod memory;
mod macros;
static BOOTLOADER_INFO: LimineBootInfoRequest = LimineBootInfoRequest::new(0);
static TERMINAL_REQUEST: LimineTerminalRequest = LimineTerminalRequest::new(0);
static MEM_MAP: LimineMemmapRequest = LimineMemmapRequest::new(0);
lazy_static! {
//pub static ref KERN_INFO: Mutex<Option<KernelInfo>> = Mutex::new(None);
static ref GDT: Mutex<GlobalDescriptorTable> = {
@ -51,7 +48,11 @@ lazy_static! {
idt.breakpoint.set_handler_fn(internals::errors::breakpoint_exception);
idt.double_fault.set_handler_fn(internals::errors::double_fault);
idt.page_fault.set_handler_fn(internals::errors::page_fault);
idt[40].set_handler_fn(internals::cpu::keyboard_irq);
idt[40].set_handler_fn(internals::cpu::timer);
idt[41].set_handler_fn(internals::cpu::error);
idt[42].set_handler_fn(internals::cpu::spurious);
idt[50].set_handler_fn(internals::cpu::timer);
idt[51].set_handler_fn(internals::cpu::keyboard_irq);
idt
};
}
@ -168,6 +169,11 @@ pub extern "C" fn kernel_main() -> ! {
// memory stuff
{
print!("initialising mapper...");
let kernel_physical_address = KERNEL_ADDRESS.get_response().get().unwrap().physical_base;
let kernel_virtual_address = KERNEL_ADDRESS.get_response().get().unwrap().virtual_base;
debug!("kernel physical address: {:#x}", kernel_physical_address);
debug!("kernel virtual address: {:#x}", kernel_virtual_address);
let offset = (kernel_virtual_address as i64) as usize;// - kernel_physical_address as i64) as usize;
MEM_MAPPER.lock().replace(unsafe { memory::init(VirtAddr::new(0)) });
println!("[OK]");
print!("initialising frame allocator...");
@ -192,7 +198,7 @@ pub extern "C" fn kernel_main() -> ! {
}
// apic stuff
/*{
{
print!("checking for apic compatibility...");
let apic_compatible = unsafe { internals::cpu::check_apic_compat() };
if apic_compatible {
@ -202,16 +208,16 @@ pub extern "C" fn kernel_main() -> ! {
panic!("apic required at the moment");
}
print!("initialising apic...");
let ioapicaddr = get_ioapic_addr();
unsafe { internals::cpu::enable_apic() };
println!("[OK]");
print!("setting up apic interrupts...");
let ioapicaddr = KERN_INFO.lock().as_ref().unwrap().acpi_get_ioapic_addr();
debug!("ioapicaddr: {:#x}", ioapicaddr);
unsafe { internals::cpu::setup_ioapic(ioapicaddr) };
println!("[OK]");
// enable interrupts
x86_64::instructions::interrupts::enable();
}*/
//x86_64::instructions::interrupts::enable();
}
loop {
}

View file

@ -3,7 +3,8 @@ pub mod allocator;
use alloc::boxed::Box;
use alloc::sync::Arc;
use lazy_static::lazy_static;
use x86_64::structures::paging::{FrameAllocator, Mapper, OffsetPageTable, PageTable, PhysFrame, Size4KiB, Translate};
use limine::LimineMemoryMapEntryType;
use x86_64::structures::paging::{FrameAllocator, Mapper, OffsetPageTable, Page, PageTable, PageTableFlags, PhysFrame, Size4KiB, Translate};
use x86_64::{PhysAddr, VirtAddr};
lazy_static!{
@ -11,6 +12,8 @@ lazy_static!{
pub static ref FRAME_ALLOC: Mutex<Option<BootInfoFrameAllocator>> = Mutex::new(None);
}
pub const VIRT_MEM_OFFSET: u64 = 0xffffffff80000000;
pub type PageSize = Size4KiB;
pub struct Locked<A> {
@ -47,7 +50,8 @@ unsafe fn active_level_4_table(phys_mem_offset: VirtAddr) -> &'static mut PageTa
}
use spin::Mutex;
use crate::{debug, MEM_MAP, print, println};
use crate::{debug, print, println};
use crate::boot::{KERNEL_ADDRESS, MEM_MAP};
pub struct BootInfoFrameAllocator {
next: usize,
@ -67,6 +71,7 @@ unsafe impl FrameAllocator<Size4KiB> for BootInfoFrameAllocator {
let mmap = MEM_MAP.get_response().get().expect("failed to get memory map")
.memmap();
let mut usable_frames = mmap.iter()
.filter(|entry| entry.typ == LimineMemoryMapEntryType::Usable)
.map(|area| {
let frame_addr = area.base;
let frame_end = area.base + area.len;