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] [dependencies]
spin = "0.9.1" spin = "0.9.1"
x86_64 = "0.14.10" x86_64 = "0.14.10"
x86 = "0.52.0" x2apic = "0.4.1"
rlibc = "1.0" rlibc = "1.0"
limine = { version = "0.1.9", optional = true } limine = { version = "0.1.9", optional = true }
acpi = { version = "4.1.1", optional = true } acpi = { version = "4.1.1", optional = true }

View file

@ -12,7 +12,50 @@ debug: IDT loaded
welcome to wukkOS! welcome to wukkOS!
(c) 2022 Real Microsoft, LLC (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 frame allocator...[OK]
initialising heap...[OK] initialising heap...[OK]
testing 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 alloc::sync::Arc;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::ptr::NonNull; use core::ptr::NonNull;
use acpi::{AcpiHandler, InterruptModel, PhysicalMapping}; use acpi::{AcpiHandler, AcpiTables, InterruptModel, PhysicalMapping};
use limine::LimineTerminalResponse; use limine::{LimineBootInfoRequest, LimineKernelAddressRequest, LimineMemmapRequest, LimineTerminalRequest, LimineTerminalResponse, LimineRsdpRequest};
use crate::{debug, println, TERMINAL_REQUEST}; use crate::{debug, println};
#[cfg(feature = "f_multiboot2")] #[cfg(feature = "f_multiboot2")]
use multiboot2::{load, MemoryMapTag, BootInformation}; use multiboot2::{load, MemoryMapTag, BootInformation};
use x86_64::structures::paging::{FrameAllocator, Mapper, OffsetPageTable, Page, Translate}; use x86_64::structures::paging::{FrameAllocator, Mapper, OffsetPageTable, Page, Translate};
use x86_64::VirtAddr; 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; 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)] #[derive(Clone)]
struct Handler; struct Handler;
impl AcpiHandler for Handler { impl AcpiHandler for Handler {
unsafe fn map_physical_region<T>(&self, physical_address: usize, size: usize) -> PhysicalMapping<Self, T> { unsafe fn map_physical_region<T>(&self, physical_address: usize, size: usize) -> PhysicalMapping<Self, T> { // todo! check if size is too big
// todo! check if size is too big // only get lower 32 bits of physical address
debug!("read_phys_memory32: addr {:x} not mapped", physical_address); let physical_address = physical_address as u32;
let mut i = 0; debug!("Mapping physical region: {:x} - {:x}", physical_address, physical_address + size as u32);
while i < size { let _ = read_phys_memory32(physical_address as u32) as usize;
let _ = read_phys_memory32(physical_address as u32 + i as u32); PhysicalMapping::new(
i += 4; physical_address as usize,
} NonNull::new_unchecked(physical_address as *mut T),
let addr = unsafe { MEM_MAPPER.lock().as_mut().unwrap().translate_addr(VirtAddr::new(physical_address as u64)) }; size, size,
if let Some(addr) = addr.clone() { Self)
// 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>) { fn unmap_physical_region<T>(region: &PhysicalMapping<Self, T>) {
@ -42,8 +39,9 @@ impl AcpiHandler for Handler {
// unmap page // unmap page
let res = unsafe { MEM_MAPPER.lock().as_mut().unwrap().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 // 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() { 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(()) 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 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::PhysAddr;
use x86_64::structures::idt::InterruptStackFrame; use x86_64::structures::idt::InterruptStackFrame;
use x86_64::structures::paging::PhysFrame; 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? // 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 { pub fn check_apic_compat() -> bool {
unsafe { unsafe {
let mut eax: u32; 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 // we need to get the xapic region
let mut XAPIC_REGION: &'static mut [u32] = unsafe { let phys_addr = unsafe { xapic_base() };
// 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();
// get xapic id to ensure it's working let mut lapic = LocalApicBuilder::new()
let id = xapic.id(); .timer_vector(0x40)
debug!("xapic id: {}", id); .error_vector(0x41)
debug!("xapic version: {}", xapic.version()); .spurious_vector(0x42)
.set_xapic_base(phys_addr)
WAPICManager { .build()
xapic, .unwrap_or_else(|e| panic!("failed to build local apic: {}", e));
id,
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 // 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) { pub extern "x86-interrupt" fn keyboard_irq(stack_frame: InterruptStackFrame) {
debug!("keyboard interrupt"); debug!("keyboard interrupt");
@ -76,16 +69,21 @@ 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_ioapic(ioapicaddr: u32) -> WIOAPICManager { pub fn setup_ioapic(ioapicaddr: u32) {
let mut ioapic = unsafe { IoApic::new(ioapicaddr as usize) }; let mut ioapic = unsafe {
let _ = read_phys_memory32(ioapicaddr); IoApic::new(ioapicaddr as u64)
// assert that supported interrupts is greater than 1 };
debug!("ioapic supported interrupts: {}", ioapic.supported_interrupts()); // setup keyboard interrupt
// setup keyboard irq (interrupt 0x40) unsafe {
ioapic.enable(1, 0x40); // 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 ioapic.enable_irq(1);
WIOAPICManager {
ioapic,
} }
} }

View file

@ -24,6 +24,7 @@ use x86_64::structures::tss::TaskStateSegment;
use x86_64::{PhysAddr, VirtAddr}; use x86_64::{PhysAddr, VirtAddr};
use x86_64::registers::segmentation::{CS, Segment, SS}; use x86_64::registers::segmentation::{CS, Segment, SS};
use x86_64::structures::paging::Translate; use x86_64::structures::paging::Translate;
use crate::boot::{get_ioapic_addr, KERNEL_ADDRESS};
use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::*; use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::*;
use crate::memory::{FRAME_ALLOC, MEM_MAPPER}; use crate::memory::{FRAME_ALLOC, MEM_MAPPER};
use crate::serial::terminal::ST; use crate::serial::terminal::ST;
@ -36,10 +37,6 @@ mod boot;
mod memory; mod memory;
mod macros; 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! { lazy_static! {
//pub static ref KERN_INFO: Mutex<Option<KernelInfo>> = Mutex::new(None); //pub static ref KERN_INFO: Mutex<Option<KernelInfo>> = Mutex::new(None);
static ref GDT: Mutex<GlobalDescriptorTable> = { static ref GDT: Mutex<GlobalDescriptorTable> = {
@ -51,7 +48,11 @@ lazy_static! {
idt.breakpoint.set_handler_fn(internals::errors::breakpoint_exception); idt.breakpoint.set_handler_fn(internals::errors::breakpoint_exception);
idt.double_fault.set_handler_fn(internals::errors::double_fault); idt.double_fault.set_handler_fn(internals::errors::double_fault);
idt.page_fault.set_handler_fn(internals::errors::page_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 idt
}; };
} }
@ -168,6 +169,11 @@ pub extern "C" fn kernel_main() -> ! {
// memory stuff // memory stuff
{ {
print!("initialising mapper..."); 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)) }); MEM_MAPPER.lock().replace(unsafe { memory::init(VirtAddr::new(0)) });
println!("[OK]"); println!("[OK]");
print!("initialising frame allocator..."); print!("initialising frame allocator...");
@ -192,7 +198,7 @@ pub extern "C" fn kernel_main() -> ! {
} }
// apic stuff // apic stuff
/*{ {
print!("checking for apic compatibility..."); print!("checking for apic compatibility...");
let apic_compatible = unsafe { internals::cpu::check_apic_compat() }; let apic_compatible = unsafe { internals::cpu::check_apic_compat() };
if apic_compatible { if apic_compatible {
@ -202,16 +208,16 @@ pub extern "C" fn kernel_main() -> ! {
panic!("apic required at the moment"); panic!("apic required at the moment");
} }
print!("initialising apic..."); print!("initialising apic...");
let ioapicaddr = get_ioapic_addr();
unsafe { internals::cpu::enable_apic() }; unsafe { internals::cpu::enable_apic() };
println!("[OK]"); println!("[OK]");
print!("setting up apic interrupts..."); print!("setting up apic interrupts...");
let ioapicaddr = KERN_INFO.lock().as_ref().unwrap().acpi_get_ioapic_addr();
debug!("ioapicaddr: {:#x}", ioapicaddr); debug!("ioapicaddr: {:#x}", ioapicaddr);
unsafe { internals::cpu::setup_ioapic(ioapicaddr) }; unsafe { internals::cpu::setup_ioapic(ioapicaddr) };
println!("[OK]"); println!("[OK]");
// enable interrupts // enable interrupts
x86_64::instructions::interrupts::enable(); //x86_64::instructions::interrupts::enable();
}*/ }
loop { loop {
} }

View file

@ -3,7 +3,8 @@ 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 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}; use x86_64::{PhysAddr, VirtAddr};
lazy_static!{ lazy_static!{
@ -11,6 +12,8 @@ lazy_static!{
pub static ref FRAME_ALLOC: Mutex<Option<BootInfoFrameAllocator>> = Mutex::new(None); pub static ref FRAME_ALLOC: Mutex<Option<BootInfoFrameAllocator>> = Mutex::new(None);
} }
pub const VIRT_MEM_OFFSET: u64 = 0xffffffff80000000;
pub type PageSize = Size4KiB; pub type PageSize = Size4KiB;
pub struct Locked<A> { 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 spin::Mutex;
use crate::{debug, MEM_MAP, print, println}; use crate::{debug, print, println};
use crate::boot::{KERNEL_ADDRESS, MEM_MAP};
pub struct BootInfoFrameAllocator { pub struct BootInfoFrameAllocator {
next: usize, 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") let mmap = MEM_MAP.get_response().get().expect("failed to get memory map")
.memmap(); .memmap();
let mut usable_frames = mmap.iter() let mut usable_frames = mmap.iter()
.filter(|entry| entry.typ == LimineMemoryMapEntryType::Usable)
.map(|area| { .map(|area| {
let frame_addr = area.base; let frame_addr = area.base;
let frame_end = area.base + area.len; let frame_end = area.base + area.len;