diff --git a/kernel/src/arch/x86_64/apic/mod.rs b/kernel/src/arch/x86_64/apic/mod.rs new file mode 100644 index 0000000..6899d99 --- /dev/null +++ b/kernel/src/arch/x86_64/apic/mod.rs @@ -0,0 +1,99 @@ +use core::arch::x86_64::__cpuid; + +use x86_64::{ + PhysAddr, VirtAddr, + instructions::port::Port, + registers::model_specific::Msr, + structures::paging::{ + FrameAllocator, Mapper, Page, PageTableFlags, PhysFrame, Size4KiB, Translate, + }, +}; + +use crate::serial_print; + +use super::{ + cpu::model_specific_registers::*, memmap::PHYSICAL_MEMORY_OFFSET, + memory::FoundryOSFrameAllocator, +}; + +const IA32_APIC_BASE_MSR: u32 = 0x1b; +const IA32_APIC_BASE_MSR_BSP: u64 = 0x100; +const IA32_APIC_BASE_MSR_ENABLE: u64 = 0x800; +const IA32_APIC_BASE_MSR_DISABLE: u64 = !IA32_APIC_BASE_MSR_ENABLE; + +const CPUID_FEAT_EDX_APIC: u64 = 1 << 9; // the cpuid instruction will return this flag if it supports APIC + +const APIC_VIRTUAL_ADDRESS: u64 = 0xFEC00000; + +fn set_apic_base_enable(apic: PhysAddr) { + let rax = (apic.as_u64() & 0xfffff0000) | IA32_APIC_BASE_MSR_ENABLE; + cpu_set_msr(IA32_APIC_BASE_MSR, rax); +} + +fn set_apic_base_disable(apic: PhysAddr) { + let rax = (apic.as_u64() & 0xfffff0000) & IA32_APIC_BASE_MSR_DISABLE; + cpu_set_msr(IA32_APIC_BASE_MSR, rax); +} + +fn get_apic_base() -> PhysAddr { + let mut value: u64 = 0; + cpu_get_msr(IA32_APIC_BASE_MSR, &mut value); + PhysAddr::new(value & 0xfffff0000) +} + +fn write_apic_register(apic_base: &VirtAddr, reg: u8, value: u32) { + let apic_base = apic_base.as_u64(); + let reg_addr = (apic_base & 0xFFFFF0000) + reg as u64; + unsafe { *(reg_addr as *mut u32) = value }; +} + +fn read_apic_register(apic_base: &VirtAddr, reg: u8) -> u32 { + let apic_base = apic_base.as_u64(); + + serial_print!("got apic base"); + + let reg_addr = (apic_base & 0xFFFFF0000) + reg as u64; + unsafe { *(reg_addr as *const u32) } +} + +pub fn check_apic() -> bool { + let res = unsafe { __cpuid(1) }; + res.edx as u64 & CPUID_FEAT_EDX_APIC != 0 +} + +#[inline(always)] +unsafe fn phys_to_virt(phys: PhysAddr) -> VirtAddr { + let phys = phys.as_u64(); + match phys.checked_add(*PHYSICAL_MEMORY_OFFSET) { + Some(virt) => VirtAddr::new(virt), + None => panic!("overflow"), + } +} + +pub fn enable_apic() { + let apic_phys_addr = get_apic_base(); + + // let frame = PhysFrame::containing_address(apic_phys_addr); + // let flags: PageTableFlags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; + + // unsafe { + // mapper.map_to(page, frame, flags, frame_allocator); + // } + + set_apic_base_enable(apic_phys_addr); + + // FIXME: this causes a page fault + // TODO: map to virtual memor + + let apic_virt = unsafe { phys_to_virt(apic_phys_addr) }; + + let reg = read_apic_register(&apic_virt, 0xF0); + + serial_print!("ok2"); + + write_apic_register(&apic_virt, 0xF0, reg | 0x100); +} + +pub struct Apic {} + +pub enum ApicVector {} diff --git a/libk/src/drivers/cpu.rs b/kernel/src/arch/x86_64/cpu.rs similarity index 100% rename from libk/src/drivers/cpu.rs rename to kernel/src/arch/x86_64/cpu.rs diff --git a/kernel/src/arch/x86_64/interrupts.rs b/kernel/src/arch/x86_64/interrupts.rs index 2d9dd92..74d6c42 100644 --- a/kernel/src/arch/x86_64/interrupts.rs +++ b/kernel/src/arch/x86_64/interrupts.rs @@ -1,4 +1,3 @@ -use libk::drivers::apic::enable_apic; use libk::prelude::*; use pic8259::ChainedPics; use x86_64::registers::control::Cr2; @@ -6,6 +5,7 @@ use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, Pag use spin::{Lazy, Mutex}; +use super::apic::enable_apic; use super::gdt; static IDT: Lazy = Lazy::new(|| { @@ -52,12 +52,12 @@ impl InterruptIndex { pub fn init_idt() { IDT.load(); - // enable_apic(); + enable_apic(); // TODO: fix apic - unsafe { - PICS.lock().initialize(); - PICS.lock().write_masks(0xfc, 0xff); - } + // unsafe { + // PICS.lock().initialize(); + // PICS.lock().write_masks(0xfc, 0xff); + // } } extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) { diff --git a/kernel/src/arch/x86_64/memory.rs b/kernel/src/arch/x86_64/memory.rs index 09cc345..fe44264 100644 --- a/kernel/src/arch/x86_64/memory.rs +++ b/kernel/src/arch/x86_64/memory.rs @@ -1,17 +1,11 @@ // use lib_alloc::allocator::FoundryAllocator; use limine::{memory_map::EntryType, response::MemoryMapResponse}; use x86_64::{ - PhysAddr, - VirtAddr, - // addr, + PhysAddr, VirtAddr, registers::control::Cr3, structures::paging::{ - // page_table::FrameError, - FrameAllocator, - OffsetPageTable, - PageTable, - PhysFrame, - Size4KiB, + FrameAllocator, Mapper, OffsetPageTable, Page, PageTable, PhysFrame, Size4KiB, + page_table::FrameError, }, }; diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index 7947954..bb3543c 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -5,3 +5,7 @@ pub mod interrupts; pub mod memory; pub mod memmap; + +pub mod apic; + +pub mod cpu; diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 7e60267..ece9c97 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -13,6 +13,7 @@ extern crate alloc; +use arch::x86_64::apic::enable_apic; use core::arch::asm; use limine::BaseRevision; @@ -71,25 +72,29 @@ pub fn boot() -> Result<(), &'static str> { gdt::init(); println_log!("[Success]"); - print_log!(" Setting Up Interrupt Descriptor Table... "); - interrupts::init_idt(); + print_log!(" Initialising Memory Subsystem... "); + let physical_memory_offset = VirtAddr::new(*memmap::PHYSICAL_MEMORY_OFFSET); + let mut l4_table = unsafe { memory::init(physical_memory_offset) }; println_log!("[Success]"); print_log!(" Setting Up Page Table... "); let mut frame_allocator = unsafe { memory::FoundryOSFrameAllocator::init(memory_map) }; println_log!("[Success]"); - print_log!(" Initialising Memory Subsystem... "); - let physical_memory_offset = VirtAddr::new(*memmap::PHYSICAL_MEMORY_OFFSET); - let mut l4_table = unsafe { memory::init(physical_memory_offset) }; - println_log!("[Success]"); - print_log!(" Initialising Heap... "); if init_heap(&mut l4_table, &mut frame_allocator).is_err() { return Err("Failed to initialise heap: error"); } println_log!("[Success]"); + print_log!(" Initialising APIC"); + enable_apic(); + println_log!("[Success]"); + + print_log!(" Setting Up Interrupt Descriptor Table... "); + interrupts::init_idt(); + println_log!("[Success]"); + print_log!(" Enabling Interrupts... "); x86_64::instructions::interrupts::enable(); println_log!("[Success]"); diff --git a/libk/src/drivers/apic/mod.rs b/libk/src/drivers/apic/mod.rs deleted file mode 100644 index 7e47e8f..0000000 --- a/libk/src/drivers/apic/mod.rs +++ /dev/null @@ -1,49 +0,0 @@ -use core::arch::x86_64::__cpuid; - -use x86_64::{PhysAddr, instructions::port::Port, registers::model_specific::Msr}; - -use super::cpu::model_specific_registers::*; - -const IA32_APIC_BASE_MSR: u32 = 0x1b; -const IA32_APIC_BASE_MSR_BSP: u64 = 0x100; -const IA32_APIC_BASE_MSR_ENABLE: u64 = 0x800; - -const CPUID_FEAT_EDX_APIC: u64 = 1 << 9; // the cpuid instruction will return this flag if it supports APIC - -fn set_apic_base(apic: PhysAddr) { - let rax = (apic.as_u64() & 0xfffff0000) | IA32_APIC_BASE_MSR_ENABLE; - cpu_set_msr(IA32_APIC_BASE_MSR, rax); -} - -fn get_apic_base() -> PhysAddr { - let mut value: u64 = 0; - cpu_get_msr(IA32_APIC_BASE_MSR, &mut value); - PhysAddr::new(value & 0xfffff0000) -} - -fn write_apic_register(reg: u8, value: u32) { - let apic_base = get_apic_base().as_u64(); - let reg_addr = (apic_base & 0xFFFFF0000) + reg as u64; - unsafe { *(reg_addr as *mut u32) = value }; -} - -fn read_apic_register(reg: u8) -> u32 { - let apic_base = get_apic_base().as_u64(); - let reg_addr = (apic_base & 0xFFFFF0000) + reg as u64; - unsafe { *(reg_addr as *const u32) } -} - -pub fn check_apic() -> bool { - let res = unsafe { __cpuid(1) }; - res.edx as u64 & CPUID_FEAT_EDX_APIC != 0 -} - -pub fn enable_apic() { - set_apic_base(get_apic_base()); - - write_apic_register(0xF0, read_apic_register(0xF0) | 0x100); -} - -pub struct Apic {} - -pub enum ApicVector {} diff --git a/libk/src/drivers/mod.rs b/libk/src/drivers/mod.rs index 0222bb5..6ad525d 100644 --- a/libk/src/drivers/mod.rs +++ b/libk/src/drivers/mod.rs @@ -1,7 +1,5 @@ pub mod io; pub mod kalloc; -pub mod apic; pub mod async_io; -pub mod cpu; pub mod pic;