ITS FUCKING WORKING OH MY GOD

This commit is contained in:
fekhesk 2022-10-27 21:58:36 -07:00
parent d11d5ddd97
commit 314189882b
No known key found for this signature in database
GPG Key ID: 6B3D8CB511646891
8 changed files with 216 additions and 94 deletions

View File

@ -11,12 +11,13 @@ rlibc = "1.0"
limine = { version = "0.1.9", optional = true }
acpi = { version = "4.1.1", optional = true }
linked_list_allocator = { version = "0.9.0", optional = true }
pc-keyboard = "0.6.1"
[dependencies.lazy_static]
version = "1.4.0"
features = ["spin_no_std"]
[features]
default = ["f_limine", "f_ll_alloc", "f_debug_verbose"]
default = ["f_limine", "f_ll_alloc"]#, "f_debug_verbose"]
f_debug_verbose = []
f_limine = ["dep:limine", "dep:acpi"]
f_ll_alloc = ["dep:linked_list_allocator"]

View File

@ -12,50 +12,14 @@ debug: IDT loaded
welcome to wukkOS!
(c) 2022 Real Microsoft, LLC
initialising mapper...[debug] kernel physical address: 0x19b3d000
[debug] kernel virtual address: 0xffffffff80000000
[OK]
initialising mapper...[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,
}
initialising apic...[OK]
setting up apic interrupts...[OK]
hello world i am typing this using the legacy keyboard driver thingy in the apic from ioapic irq 1!
wukkOS moment, probably gonna swap this out for a real keyboard driver eventually but this is funny so (:
top ten wukkooOS moments

View File

@ -1,8 +1,10 @@
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::marker::PhantomData;
use core::ptr::NonNull;
use acpi::{AcpiHandler, AcpiTables, InterruptModel, PhysicalMapping};
use limine::{LimineBootInfoRequest, LimineKernelAddressRequest, LimineMemmapRequest, LimineTerminalRequest, LimineTerminalResponse, LimineRsdpRequest};
use acpi::platform::interrupt::InterruptSourceOverride;
use limine::{LimineBootInfoRequest, LimineKernelAddressRequest, LimineMemmapRequest, LimineTerminalRequest, LimineTerminalResponse, LimineRsdpRequest, LimineSmpRequest};
use crate::{debug, println};
#[cfg(feature = "f_multiboot2")]
@ -17,6 +19,7 @@ pub static TERMINAL_REQUEST: LimineTerminalRequest = LimineTerminalRequest::new(
pub static MEM_MAP: LimineMemmapRequest = LimineMemmapRequest::new(0);
pub static RSDP_REQUEST: LimineRsdpRequest = LimineRsdpRequest::new(0);
pub static KERNEL_ADDRESS: LimineKernelAddressRequest = LimineKernelAddressRequest::new(0);
pub static SMP_REQUEST: LimineSmpRequest = LimineSmpRequest::new(0);
#[derive(Clone)]
struct Handler;
@ -24,7 +27,7 @@ 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
// 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);
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,
@ -40,8 +43,8 @@ impl AcpiHandler for Handler {
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 (this is normal)");
if let Err(e) = res {
debug!("(THIS IS NORMAL) failed to unmap physical region: {:?}", e);
}
}
}
@ -68,15 +71,18 @@ impl core::fmt::Write for LimineWriter {
}
}
pub fn get_ioapic_addr() -> u32 {
pub fn get_ioapic_info() -> (u32, Vec<InterruptSourceOverride>) {
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,
let apic = match interrupt_model {
InterruptModel::Apic(apic) => apic,
_ => panic!("unsupported interrupt model"),
};
ioapic_addr
let ioapic = apic.io_apics.first().expect("no ioapic");
let address = ioapic.address;
let overrides = apic.interrupt_source_overrides;
(address, overrides)
}

View File

@ -1,15 +1,46 @@
use alloc::vec::Vec;
use core::arch::asm;
use acpi::platform::interrupt::InterruptSourceOverride;
use lazy_static::lazy_static;
use spin::Mutex;
use x2apic::ioapic::{IoApic, IrqFlags, IrqMode, RedirectionTableEntry};
use x2apic::lapic::{LocalApicBuilder, xapic_base};
use x2apic::lapic::{LocalApic, LocalApicBuilder, xapic_base};
use x86_64::PhysAddr;
use x86_64::structures::idt::InterruptStackFrame;
use x86_64::structures::paging::PhysFrame;
use crate::{debug, print, println};
use crate::memory::{BootInfoFrameAllocator, read_phys_memory32, write_phys_memory32};
use crate::serial::{command, read};
use crate::serial::simplifiers::handle_scancode;
// todo! maybe abstract this into different sections for different parts of cpu func?
pub const APIC_INTERRUPT_OFFSET: usize = 32;
pub const TIMER_IRQ: usize = 0 + APIC_INTERRUPT_OFFSET;
pub const ERROR_IRQ: usize = 1 + APIC_INTERRUPT_OFFSET;
pub const SPURIOUS_IRQ: usize = 2 + APIC_INTERRUPT_OFFSET;
pub const IOAPIC_IRQ_OFFSET: usize = 42;
pub const FALLBACK_KEYBOARD_IRQ: usize = 1 + IOAPIC_IRQ_OFFSET;
lazy_static!{
static ref LAPIC: Mutex<LocalApic> = {
// we need to get the xapic region
let phys_addr = unsafe { xapic_base() };
let mut lapic = LocalApicBuilder::new()
.timer_vector(TIMER_IRQ as usize)
.spurious_vector(SPURIOUS_IRQ as usize)
.error_vector(ERROR_IRQ as usize)
.set_xapic_base(phys_addr)
.build()
.unwrap_or_else(|e| panic!("failed to build local apic: {}", e));
Mutex::new(lapic)
};
}
pub fn check_apic_compat() -> bool {
unsafe {
let mut eax: u32;
@ -23,42 +54,54 @@ pub fn check_apic_compat() -> bool {
}
}
pub fn enable_apic() {
// we need to get the xapic region
let phys_addr = unsafe { xapic_base() };
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));
pub fn tell_pic8259a_to_f_off() {
unsafe {
lapic.enable();
asm!("cli");
asm!("out dx, al", in("dx") 0x20, in("al") 0x11i8);
asm!("out dx, al", in("dx") 0xA0, in("al") 0x11i8);
asm!("out dx, al", in("dx") 0x21, in("al") 0x20i8);
asm!("out dx, al", in("dx") 0xA1, in("al") 0x28i8);
asm!("out dx, al", in("dx") 0x21, in("al") 0x04i8);
asm!("out dx, al", in("dx") 0xA1, in("al") 0x02i8);
asm!("out dx, al", in("dx") 0x21, in("al") 0x01i8);
asm!("out dx, al", in("dx") 0xA1, in("al") 0x01i8);
asm!("out dx, al", in("dx") 0x21, in("al") 0x0i8);
asm!("out dx, al", in("dx") 0xA1, in("al") 0x0i8);
asm!("sti");
}
}
pub fn enable_apic() {
unsafe {
LAPIC.lock().enable();
}
}
pub extern "x86-interrupt" fn timer(stack_frame: InterruptStackFrame) {
println!("timer interrupt");
end_of_interupt();
}
pub extern "x86-interrupt" fn error(stack_frame: InterruptStackFrame) {
println!("error interrupt");
end_of_interupt();
}
pub extern "x86-interrupt" fn spurious(stack_frame: InterruptStackFrame) {
println!("spurious interrupt");
end_of_interupt();
}
fn end_of_interupt() {
unsafe {
LAPIC.lock().end_of_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");
unsafe { asm!("iretq"); }
let scancode = read(0x60);
print!("ksc: {},", scancode);
handle_scancode(scancode);
// reset keyboard controller
let mut a = read(0x61);
@ -66,21 +109,27 @@ pub extern "x86-interrupt" fn keyboard_irq(stack_frame: InterruptStackFrame) {
command(0x61, a);
a &= 0x7f;
command(0x61, a);
end_of_interupt();
}
// todo! we should abstract this away
pub fn setup_ioapic(ioapicaddr: u32) {
pub fn setup_ioapic(ioapicaddr: u32, isos: Vec<InterruptSourceOverride>) {
let mut ioapic = unsafe {
IoApic::new(ioapicaddr as u64)
};
// setup keyboard interrupt
unsafe {
// FIXME! only for testing that this works, abstract ASAP!
let gsi_keyboard = isos.iter().find(|iso| iso.isa_source == 1)
.map(|iso| iso.global_system_interrupt).unwrap_or(1);
// init with irq offset
ioapic.init(0x50);
ioapic.init(IOAPIC_IRQ_OFFSET as u8);
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);
entry.set_vector(gsi_keyboard as u8 + IOAPIC_IRQ_OFFSET as u8);
ioapic.set_table_entry(1, entry);
ioapic.enable_irq(1);

View File

@ -14,10 +14,11 @@ pub extern "x86-interrupt" fn breakpoint_exception(stack_frame: InterruptStackFr
println!("stack frame: {:#?}", stack_frame);
}
pub extern "x86-interrupt" fn double_fault(stack_frame: InterruptStackFrame, _error_code: u64) -> ! {
pub extern "x86-interrupt" fn double_fault(stack_frame: InterruptStackFrame, error_code: u64) -> ! {
println!("---KERNEL FUCKY WUKKY UWU---");
println!("double fault!");
println!("stack frame: {:#?}", stack_frame);
println!("error code: {}", error_code);
loop {}
}
@ -28,4 +29,12 @@ pub extern "x86-interrupt" fn page_fault(stack_frame: InterruptStackFrame, error
println!("error code: {:?}", error_code);
println!("stack frame: {:#?}", stack_frame);
loop {}
}
pub fn unhandled(stack_frame: InterruptStackFrame, index: u8, error_code: Option<u64>) {
println!("---KERNEL FUCKY WUKKY UWU---");
println!("unhandled interrupt: {}", index);
println!("error code: {:?}", error_code);
println!("stack frame: {:#?}", stack_frame);
loop {}
}

View File

@ -21,10 +21,10 @@ use spin::Mutex;
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
use x86_64::structures::gdt::{GlobalDescriptorTable, Descriptor};
use x86_64::structures::tss::TaskStateSegment;
use x86_64::{PhysAddr, VirtAddr};
use x86_64::{PhysAddr, set_general_handler, 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::boot::{get_ioapic_info, KERNEL_ADDRESS};
use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::*;
use crate::memory::{FRAME_ALLOC, MEM_MAPPER};
use crate::serial::terminal::ST;
@ -45,14 +45,17 @@ lazy_static! {
};
static ref IDT: InterruptDescriptorTable = {
let mut idt = InterruptDescriptorTable::new();
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::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);
unsafe {
use internals::errors::unhandled;
set_general_handler!(&mut idt, unhandled);
idt.breakpoint.set_handler_fn(internals::errors::breakpoint_exception).set_stack_index(0);
idt.double_fault.set_handler_fn(internals::errors::double_fault).set_stack_index(0);
idt.page_fault.set_handler_fn(internals::errors::page_fault).set_stack_index(0);
idt[internals::cpu::TIMER_IRQ].set_handler_fn(internals::cpu::timer).set_stack_index(1);
idt[internals::cpu::ERROR_IRQ].set_handler_fn(internals::cpu::error).set_stack_index(1);
idt[internals::cpu::SPURIOUS_IRQ].set_handler_fn(internals::cpu::spurious).set_stack_index(1);
idt[internals::cpu::FALLBACK_KEYBOARD_IRQ].set_handler_fn(internals::cpu::keyboard_irq).set_stack_index(1);
}
idt
};
}
@ -74,7 +77,7 @@ fn panic(info: &PanicInfo) -> ! {
println!("no panic payload")
};
if let Some(msg) = info.message() {
println!("panic msg: {}", msg.as_str().unwrap_or("no message"))
println!("panic msg: {}", msg)
} else {
println!("no message");
}
@ -112,13 +115,80 @@ pub extern "C" fn kernel_main() -> ! {
static mut tss: TaskStateSegment = TaskStateSegment::new();
{
unsafe {
tss.interrupt_stack_table[0] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
let stack_end = stack_start + STACK_SIZE;
stack_end
};
{
tss.interrupt_stack_table[0] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
let stack_end = stack_start + STACK_SIZE;
stack_end
};
tss.interrupt_stack_table[1] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
let stack_end = stack_start + STACK_SIZE;
stack_end
};
tss.interrupt_stack_table[2] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
let stack_end = stack_start + STACK_SIZE;
stack_end
};
tss.interrupt_stack_table[3] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
let stack_end = stack_start + STACK_SIZE;
stack_end
};
tss.interrupt_stack_table[4] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
let stack_end = stack_start + STACK_SIZE;
stack_end
};
tss.interrupt_stack_table[5] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
let stack_end = stack_start + STACK_SIZE;
stack_end
};
tss.interrupt_stack_table[6] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
let stack_end = stack_start + STACK_SIZE;
stack_end
};
}
{
tss.privilege_stack_table[0] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
let stack_end = stack_start + STACK_SIZE;
stack_end
};
tss.privilege_stack_table[1] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
let stack_end = stack_start + STACK_SIZE;
stack_end
};
tss.privilege_stack_table[2] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
let stack_end = stack_start + STACK_SIZE;
stack_end
};
}
// set word at offset 102 to 0x68 and last two bytes of the tss to 0xffff
// this is a hack to make the tss valid
let tss_ptr = &tss as *const TaskStateSegment as *mut u8;
@ -208,17 +278,19 @@ pub extern "C" fn kernel_main() -> ! {
panic!("apic required at the moment");
}
print!("initialising apic...");
let ioapicaddr = get_ioapic_addr();
//internals::cpu::tell_pic8259a_to_f_off();
let (addr, isos) = get_ioapic_info();
unsafe { internals::cpu::enable_apic() };
println!("[OK]");
print!("setting up apic interrupts...");
debug!("ioapicaddr: {:#x}", ioapicaddr);
unsafe { internals::cpu::setup_ioapic(ioapicaddr) };
debug!("ioapicaddr: {:#x}", addr);
unsafe { internals::cpu::setup_ioapic(addr, isos) };
println!("[OK]");
// enable interrupts
//x86_64::instructions::interrupts::enable();
}
loop {
x86_64::instructions::hlt();
}
}

View File

@ -6,6 +6,7 @@ use core::ops::Deref;
pub mod terminal_helpers;
pub mod terminal;
pub mod simplifiers;
#[derive(Clone, Copy, PartialEq)]
pub enum potential_serial_ports {

20
src/serial/simplifiers.rs Normal file
View File

@ -0,0 +1,20 @@
use lazy_static::lazy_static;
use pc_keyboard::{Keyboard, layouts, ScancodeSet1, HandleControl};
use pc_keyboard::DecodedKey::Unicode;
use spin::Mutex;
use crate::print;
lazy_static!{
static ref KBD: Mutex<Keyboard<layouts::Us104Key, ScancodeSet1>> = Mutex::new(Keyboard::new(HandleControl::MapLettersToUnicode));
}
pub fn handle_scancode(scancode: u8) {
let mut kbd = KBD.lock();
if let Ok(Some(key_event)) = kbd.add_byte(scancode) {
if let Some(key) = kbd.process_keyevent(key_event) {
if let Unicode(c) = key {
print!("{}", c);
}
}
}
}