mirror of
https://github.com/realmicrosoft/windows.git
synced 2024-08-14 22:46:44 +00:00
wtf double fault ):
This commit is contained in:
parent
8af40d0414
commit
d11d5ddd97
6 changed files with 143 additions and 80 deletions
|
@ -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 }
|
||||
|
|
45
serial.log
45
serial.log
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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
|
||||
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,
|
||||
NonNull::new_unchecked(addr.as_u64() as *mut T),
|
||||
physical_address as usize,
|
||||
NonNull::new_unchecked(physical_address as *mut T),
|
||||
size, size,
|
||||
Self)
|
||||
} else {
|
||||
panic!("Failed to map page");
|
||||
}
|
||||
}
|
||||
|
||||
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)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,3 +67,16 @@ 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
|
||||
}
|
|
@ -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());
|
||||
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));
|
||||
|
||||
WAPICManager {
|
||||
xapic,
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
24
src/main.rs
24
src/main.rs
|
@ -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 {
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue