working apic interrupts
This commit is contained in:
16
Makefile
16
Makefile
@@ -5,11 +5,13 @@ MODE ?= release
|
|||||||
ARCH ?= x86_64
|
ARCH ?= x86_64
|
||||||
MEMORY ?= 512M
|
MEMORY ?= 512M
|
||||||
# In MB
|
# In MB
|
||||||
ISO_SIZE ?= 256
|
ISO_SIZE ?= 512
|
||||||
QEMU_OPTS ?=
|
QEMU_OPTS ?=
|
||||||
MKSQUASHFS_OPTS ?=
|
MKSQUASHFS_OPTS ?=
|
||||||
GDB ?=
|
GDB ?=
|
||||||
ESP_BITS ?= 16
|
CPUS ?= 1
|
||||||
|
# FAT type
|
||||||
|
ESP_BITS ?= 32
|
||||||
|
|
||||||
ISO_PATH = ${ARTIFACTS_PATH}/iso_root
|
ISO_PATH = ${ARTIFACTS_PATH}/iso_root
|
||||||
INITRAMFS_PATH = ${ARTIFACTS_PATH}/initramfs
|
INITRAMFS_PATH = ${ARTIFACTS_PATH}/initramfs
|
||||||
@@ -22,6 +24,10 @@ ifeq (${MODE},release)
|
|||||||
CARGO_OPTS += --release
|
CARGO_OPTS += --release
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (${CPUS},1)
|
||||||
|
QEMU_OPTS += -smp ${CPUS}
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (${GDB},)
|
ifneq (${GDB},)
|
||||||
QEMU_OPTS += -s -S
|
QEMU_OPTS += -s -S
|
||||||
endif
|
endif
|
||||||
@@ -118,16 +124,16 @@ partition-iso: copy-iso-files
|
|||||||
dd if=/dev/zero of=${IMAGE_PATH} bs=1M count=0 seek=${ISO_SIZE}
|
dd if=/dev/zero of=${IMAGE_PATH} bs=1M count=0 seek=${ISO_SIZE}
|
||||||
ifeq (${ISO_PARTITION_TYPE},GPT)
|
ifeq (${ISO_PARTITION_TYPE},GPT)
|
||||||
parted -s ${IMAGE_PATH} mklabel gpt
|
parted -s ${IMAGE_PATH} mklabel gpt
|
||||||
parted -s ${IMAGE_PATH} mkpart ESP fat${ESP_BITS} 2048s 34815s
|
parted -s ${IMAGE_PATH} mkpart ESP fat${ESP_BITS} 2048s 262144s
|
||||||
|
|
||||||
else
|
else
|
||||||
parted -s ${IMAGE_PATH} mklabel msdos
|
parted -s ${IMAGE_PATH} mklabel msdos
|
||||||
parted -s ${IMAGE_PATH} mkpart primary fat${ESP_BITS} 2048s 34815s
|
parted -s ${IMAGE_PATH} mkpart primary fat${ESP_BITS} 2048s 262144s
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Make ISO with 1 partition starting at sector 2048 that is 32768 sectors, or 16MiB, in size
|
# Make ISO with 1 partition starting at sector 2048 that is 32768 sectors, or 16MiB, in size
|
||||||
# Then a second partition spanning the rest of the disk
|
# Then a second partition spanning the rest of the disk
|
||||||
parted -s ${IMAGE_PATH} mkpart primary 34816s 100%
|
parted -s ${IMAGE_PATH} mkpart primary 262145s 100%
|
||||||
parted -s ${IMAGE_PATH} set 1 esp on
|
parted -s ${IMAGE_PATH} set 1 esp on
|
||||||
|
|
||||||
build-iso: partition-iso copy-initramfs-files
|
build-iso: partition-iso copy-initramfs-files
|
||||||
|
|||||||
@@ -34,8 +34,6 @@ struct Registers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn exception_handler(registers: u64) {
|
extern "C" fn exception_handler(registers: u64) {
|
||||||
crate::println!("{:X?}", registers);
|
|
||||||
|
|
||||||
let registers = unsafe { *(registers as *const Registers) };
|
let registers = unsafe { *(registers as *const Registers) };
|
||||||
|
|
||||||
crate::println!("{:X?}", registers);
|
crate::println!("{:X?}", registers);
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
mod exceptions;
|
mod exceptions;
|
||||||
|
|
||||||
use crate::{arch::x86_common::pic::ChainedPics, libs::mutex::Mutex};
|
use crate::{
|
||||||
|
arch::{apic, x86_common::pic::ChainedPics},
|
||||||
|
libs::mutex::Mutex,
|
||||||
|
};
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@@ -74,16 +77,24 @@ pub fn idt_set_gate(num: u8, function_ptr: usize) {
|
|||||||
// If the interrupt with this number occurred with the "null" interrupt handler
|
// If the interrupt with this number occurred with the "null" interrupt handler
|
||||||
// We will need to tell the PIC that interrupt is over, this stops new interrupts
|
// We will need to tell the PIC that interrupt is over, this stops new interrupts
|
||||||
// From never firing because "it was never finished"
|
// From never firing because "it was never finished"
|
||||||
PICS.lock().write().notify_end_of_interrupt(num);
|
signal_end_of_interrupt(num);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn null_interrupt_handler() {}
|
extern "x86-interrupt" fn null_interrupt_handler() {
|
||||||
|
crate::log_info!("Unhandled interrupt!");
|
||||||
|
if apic::APIC.lock().read().is_some() {
|
||||||
|
apic::APIC
|
||||||
|
.lock()
|
||||||
|
.read()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.end_of_interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn timer_handler() {
|
extern "x86-interrupt" fn timer_handler() {
|
||||||
// crate::usr::tty::puts(".");
|
// crate::usr::tty::puts(".");
|
||||||
PICS.lock()
|
signal_end_of_interrupt(InterruptIndex::Timer.as_u8());
|
||||||
.write()
|
|
||||||
.notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn idt_init() {
|
fn idt_init() {
|
||||||
@@ -114,6 +125,19 @@ fn idt_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn signal_end_of_interrupt(int: u8) {
|
||||||
|
if apic::APIC.lock().read().is_some() {
|
||||||
|
apic::APIC
|
||||||
|
.lock()
|
||||||
|
.read()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.end_of_interrupt();
|
||||||
|
} else {
|
||||||
|
PICS.lock().write().notify_end_of_interrupt(int);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[naked]
|
#[naked]
|
||||||
pub extern "C" fn syscall() {
|
pub extern "C" fn syscall() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|||||||
211
src/arch/x86_common/apic.rs
Normal file
211
src/arch/x86_common/apic.rs
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
use core::sync::atomic::AtomicBool;
|
||||||
|
|
||||||
|
use alloc::{boxed::Box, sync::Arc, vec::Vec};
|
||||||
|
|
||||||
|
use crate::{drivers::acpi::SDTHeader, libs::mutex::Mutex};
|
||||||
|
|
||||||
|
use super::{cpu_get_msr, cpu_set_msr, pic::ChainedPics};
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
struct MADT {
|
||||||
|
pub local_apic_address: u32,
|
||||||
|
pub flags: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
struct MADTEntry {}
|
||||||
|
|
||||||
|
impl MADT {
|
||||||
|
pub fn as_ptr(&self) -> *const u8 {
|
||||||
|
core::ptr::addr_of!(self).cast::<u8>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const IA32_APIC_BASE_MSR: u32 = 0x1B;
|
||||||
|
const IA32_APIC_BASE_MSR_ENABLE: usize = 0x800;
|
||||||
|
|
||||||
|
pub fn has_apic() -> bool {
|
||||||
|
return unsafe { core::arch::x86_64::__cpuid_count(1, 0).edx } & 1 << 9 != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_apic_base(apic: usize) {
|
||||||
|
let edx: u32 = 0;
|
||||||
|
let eax = (apic & 0xfffff0000) | IA32_APIC_BASE_MSR_ENABLE;
|
||||||
|
|
||||||
|
unsafe { cpu_set_msr(IA32_APIC_BASE_MSR, &(eax as u32), &edx) };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_apic_base() -> u32 {
|
||||||
|
let mut eax: u32 = 0;
|
||||||
|
let mut edx: u32 = 0;
|
||||||
|
unsafe { cpu_get_msr(IA32_APIC_BASE_MSR, &mut eax, &mut edx) };
|
||||||
|
|
||||||
|
return eax & 0xfffff000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct LAPIC {
|
||||||
|
pub acpi_processor_id: u8,
|
||||||
|
pub apic_id: u8,
|
||||||
|
pub flags: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct IOAPIC {
|
||||||
|
pub ioapic_id: u8,
|
||||||
|
_reserved: u8,
|
||||||
|
pub ptr: *mut u8,
|
||||||
|
pub global_interrupt_base: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct IOAPICSourceOverride {
|
||||||
|
bus_source: u8,
|
||||||
|
irq_source: u8,
|
||||||
|
global_system_interrupt: u32,
|
||||||
|
flags: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct APIC {
|
||||||
|
pub io_apic: IOAPIC,
|
||||||
|
local_apic: *mut u8,
|
||||||
|
pub cpus: Arc<[LAPIC]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl APIC {
|
||||||
|
pub fn new() -> Result<Self, ()> {
|
||||||
|
if !has_apic() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let apic_base = get_apic_base() as usize;
|
||||||
|
|
||||||
|
set_apic_base(apic_base);
|
||||||
|
|
||||||
|
let madt = crate::drivers::acpi::find_table::<MADT>("APIC");
|
||||||
|
|
||||||
|
if madt.is_none() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut cpus: Vec<LAPIC> = Vec::new();
|
||||||
|
|
||||||
|
let madt = madt.unwrap();
|
||||||
|
|
||||||
|
crate::log_info!("MADT located at: {:p}", core::ptr::addr_of!(madt));
|
||||||
|
|
||||||
|
let mut lapic_ptr = madt.inner.local_apic_address as *mut u8;
|
||||||
|
let mut io_apic = None;
|
||||||
|
let mut io_apic_source_override = None;
|
||||||
|
|
||||||
|
let mut ptr = madt.extra.unwrap().as_ptr();
|
||||||
|
let ptr_end = unsafe { ptr.add(madt.header.length as usize - 44) };
|
||||||
|
|
||||||
|
while (ptr as usize) < (ptr_end as usize) {
|
||||||
|
match unsafe { *ptr } {
|
||||||
|
0 => {
|
||||||
|
if unsafe { *(ptr.add(4)) } & 1 != 0 {
|
||||||
|
cpus.push(unsafe { *ptr.add(2).cast::<LAPIC>() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 => unsafe {
|
||||||
|
io_apic = Some(IOAPIC {
|
||||||
|
ioapic_id: *ptr.add(2),
|
||||||
|
_reserved: *ptr.add(3),
|
||||||
|
ptr: (*ptr.add(4).cast::<u32>()) as *mut u8,
|
||||||
|
global_interrupt_base: *ptr.add(8).cast::<u32>(),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
2 => unsafe {
|
||||||
|
io_apic_source_override = Some(IOAPICSourceOverride {
|
||||||
|
bus_source: *ptr.add(2),
|
||||||
|
irq_source: *ptr.add(3),
|
||||||
|
global_system_interrupt: *ptr.add(4).cast::<u32>(),
|
||||||
|
flags: *ptr.add(8).cast::<u16>(),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
5 => lapic_ptr = unsafe { *(ptr.add(4).cast::<u64>()) } as *mut u8,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = unsafe { ptr.add((*ptr.add(1)) as usize) };
|
||||||
|
}
|
||||||
|
|
||||||
|
if io_apic.is_none() || io_apic_source_override.is_none() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let io_apic_ptr = io_apic.unwrap().ptr;
|
||||||
|
|
||||||
|
crate::println!(
|
||||||
|
"Found {} cores, IOAPIC {:p}, LAPIC {lapic_ptr:p}, Processor IDs:",
|
||||||
|
cpus.len(),
|
||||||
|
io_apic_ptr,
|
||||||
|
);
|
||||||
|
|
||||||
|
for apic in &cpus {
|
||||||
|
crate::println!(" {}", apic.acpi_processor_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let apic = Self {
|
||||||
|
io_apic: io_apic.unwrap(),
|
||||||
|
local_apic: lapic_ptr,
|
||||||
|
cpus: cpus.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
apic.write_lapic(0xF0, apic.read_lapic(0xF0) | 0x100);
|
||||||
|
|
||||||
|
let io_apic_ver = apic.read_ioapic(0x01);
|
||||||
|
|
||||||
|
let number_of_inputs = ((io_apic_ver >> 16) & 0xFF) + 1;
|
||||||
|
|
||||||
|
crate::println!("{number_of_inputs}");
|
||||||
|
|
||||||
|
// Take the keyboard vector table, then mask out the top most bit (interrupt mask), then,
|
||||||
|
// mask out the bottom 8 bits, and put the kbd int in it setting the interrupt vector
|
||||||
|
let keyboard_vt = ((apic.read_ioapic(0x12) & 0x7FFF) & 0xFF00) | 0x21;
|
||||||
|
|
||||||
|
// enable keyboard interrupt
|
||||||
|
apic.write_ioapic(0x12, keyboard_vt);
|
||||||
|
|
||||||
|
return Ok(apic);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_ioapic(&self, reg: u32) -> u32 {
|
||||||
|
unsafe {
|
||||||
|
core::ptr::write_volatile(self.io_apic.ptr.cast::<u32>(), reg & 0xff);
|
||||||
|
return core::ptr::read_volatile(self.io_apic.ptr.cast::<u32>().add(4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_ioapic(&self, reg: u32, value: u32) {
|
||||||
|
unsafe {
|
||||||
|
core::ptr::write_volatile(self.io_apic.ptr.cast::<u32>(), reg & 0xff);
|
||||||
|
core::ptr::write_volatile(self.io_apic.ptr.cast::<u32>().add(4), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_lapic(&self, reg: u32) -> u32 {
|
||||||
|
unsafe {
|
||||||
|
return *self.local_apic.add(reg as usize).cast::<u32>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_lapic(&self, reg: u32, value: u32) {
|
||||||
|
unsafe {
|
||||||
|
*self.local_apic.add(reg as usize).cast::<u32>() = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end_of_interrupt(&self) {
|
||||||
|
self.write_lapic(0xB0, 0x00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static APIC: Mutex<Option<APIC>> = Mutex::new(None);
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
pub mod apic;
|
||||||
pub mod io;
|
pub mod io;
|
||||||
pub mod pic;
|
pub mod pic;
|
||||||
pub mod stack_trace;
|
pub mod stack_trace;
|
||||||
@@ -9,3 +10,27 @@ pub fn pause() {
|
|||||||
core::arch::asm!("pause");
|
core::arch::asm!("pause");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn cpu_has_msr() -> bool {
|
||||||
|
return unsafe { core::arch::x86_64::__cpuid_count(1, 0).edx } & 1 << 5 != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn cpu_get_msr(msr: u32, lo: &mut u32, hi: &mut u32) {
|
||||||
|
core::arch::asm!(
|
||||||
|
"rdmsr",
|
||||||
|
in("ecx") msr,
|
||||||
|
inout("eax") *lo,
|
||||||
|
inout("edx") *hi,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn cpu_set_msr(msr: u32, lo: &u32, hi: &u32) {
|
||||||
|
core::arch::asm!(
|
||||||
|
"wrmsr",
|
||||||
|
in("ecx") msr,
|
||||||
|
in("eax") *lo,
|
||||||
|
in("edx") *hi,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use alloc::{borrow::ToOwned, format, string::String, vec::Vec};
|
use alloc::{borrow::ToOwned, string::String, vec::Vec};
|
||||||
|
|
||||||
use crate::drivers::{fs::vfs::VfsFileSystem, serial::write_serial};
|
use crate::drivers::fs::vfs::VfsFileSystem;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
@@ -20,6 +20,13 @@ pub fn print_stack_trace(max_frames: usize, rbp: u64) {
|
|||||||
|
|
||||||
let instruction_pointer = unsafe { (*stackframe).rip };
|
let instruction_pointer = unsafe { (*stackframe).rip };
|
||||||
|
|
||||||
|
if instruction_pointer == 0x0 {
|
||||||
|
unsafe {
|
||||||
|
stackframe = (*stackframe).back;
|
||||||
|
};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
crate::print!(" {:#X} ", instruction_pointer);
|
crate::print!(" {:#X} ", instruction_pointer);
|
||||||
|
|
||||||
let instrcution_info = get_function_name(instruction_pointer);
|
let instrcution_info = get_function_name(instruction_pointer);
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
// TODO: reduce the need to derive(Clone, Copy) everything
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
use alloc::{sync::Arc, vec::Vec};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::io::{inw, outb},
|
arch::io::{inw, outb},
|
||||||
libs::{lazy::Lazy, mutex::Mutex, oncecell::OnceCell},
|
libs::oncecell::OnceCell,
|
||||||
log_info,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
struct SDTHeader {
|
pub struct SDTHeader {
|
||||||
pub signature: [u8; 4],
|
pub signature: [u8; 4],
|
||||||
pub length: u32,
|
pub length: u32,
|
||||||
pub revision: u8,
|
pub revision: u8,
|
||||||
@@ -23,23 +20,40 @@ struct SDTHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SDT<T> {
|
pub struct SDT<'a, T> {
|
||||||
pub header: SDTHeader,
|
pub header: &'a SDTHeader,
|
||||||
pub inner: T,
|
pub inner: &'a T,
|
||||||
|
pub extra: Option<&'a [u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Copy> SDT<T> {
|
impl<'a, T> SDT<'a, T> {
|
||||||
unsafe fn new(pointer: *mut u8) -> Self {
|
unsafe fn new(ptr: *const u8) -> Self {
|
||||||
let header = *(pointer.cast::<SDTHeader>());
|
let length = core::ptr::read_unaligned(ptr.add(4).cast::<u32>());
|
||||||
let inner = *(pointer.add(core::mem::size_of::<SDTHeader>()).cast::<T>());
|
let data = core::slice::from_raw_parts(ptr, length as usize);
|
||||||
|
|
||||||
return Self { header, inner };
|
crate::log_serial!("SDT at: {ptr:p}");
|
||||||
|
|
||||||
|
assert!(data.len() == length as usize);
|
||||||
|
|
||||||
|
let header: &SDTHeader = core::mem::transmute(data[0..].as_ptr());
|
||||||
|
let inner: &T = core::mem::transmute(data[core::mem::size_of::<SDTHeader>()..].as_ptr());
|
||||||
|
let mut extra = None;
|
||||||
|
|
||||||
|
if length as usize > core::mem::size_of::<SDTHeader>() + core::mem::size_of::<T>() {
|
||||||
|
extra = Some(&data[core::mem::size_of::<SDTHeader>() + core::mem::size_of::<T>()..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Self {
|
||||||
|
header,
|
||||||
|
inner,
|
||||||
|
extra,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
struct RSDP {
|
struct RSDP {
|
||||||
signature: [u8; 8],
|
signature: [u8; 8],
|
||||||
checksum: u8,
|
checksum: u8,
|
||||||
@@ -49,6 +63,7 @@ struct RSDP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
|
#[derive(Debug)]
|
||||||
struct XSDP {
|
struct XSDP {
|
||||||
rsdp: RSDP,
|
rsdp: RSDP,
|
||||||
|
|
||||||
@@ -70,17 +85,17 @@ struct XSDT {
|
|||||||
pointers: u64,
|
pointers: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Debug)]
|
||||||
enum RootSDT {
|
enum RootSDT<'a> {
|
||||||
RSDT(SDT<RSDT>),
|
RSDT(SDT<'a, RSDT>),
|
||||||
XSDT(SDT<XSDT>),
|
XSDT(SDT<'a, XSDT>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RootSDT {
|
impl<'a> RootSDT<'a> {
|
||||||
fn header(&self) -> SDTHeader {
|
fn header(&self) -> SDTHeader {
|
||||||
return match self {
|
return match self {
|
||||||
&RootSDT::RSDT(RSDT) => RSDT.header,
|
RootSDT::RSDT(RSDT) => *RSDT.header,
|
||||||
&RootSDT::XSDT(XSDT) => XSDT.header,
|
RootSDT::XSDT(XSDT) => *XSDT.header,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,12 +112,12 @@ impl RootSDT {
|
|||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
|
|
||||||
let root_ptr = match self {
|
let root_ptr = match self {
|
||||||
&RootSDT::RSDT(RSDT) => {
|
RootSDT::RSDT(RSDT) => {
|
||||||
let ptrs = RSDT.inner.pointers as *const u8;
|
let ptrs = RSDT.inner.pointers as *const u8;
|
||||||
assert!(!ptrs.is_null());
|
assert!(!ptrs.is_null());
|
||||||
ptrs.add(offset)
|
ptrs.add(offset)
|
||||||
}
|
}
|
||||||
&RootSDT::XSDT(XSDT) => {
|
RootSDT::XSDT(XSDT) => {
|
||||||
let ptrs = XSDT.inner.pointers as *const u8;
|
let ptrs = XSDT.inner.pointers as *const u8;
|
||||||
assert!(!ptrs.is_null());
|
assert!(!ptrs.is_null());
|
||||||
ptrs.add(offset)
|
ptrs.add(offset)
|
||||||
@@ -110,19 +125,17 @@ impl RootSDT {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for _ in 0..idx {
|
for _ in 0..idx {
|
||||||
let header = *root_ptr.add(offset).cast::<SDTHeader>();
|
let header: &SDTHeader = core::mem::transmute(root_ptr.add(offset).cast::<SDTHeader>());
|
||||||
offset += header.length as usize;
|
offset += header.length as usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::println!("{offset:X?} {idx}");
|
|
||||||
|
|
||||||
return root_ptr.add(offset);
|
return root_ptr.add(offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Debug)]
|
||||||
struct ACPI {
|
struct ACPI<'a> {
|
||||||
root_sdt: RootSDT,
|
root_sdt: RootSDT<'a>,
|
||||||
tables: Vec<[u8; 4]>,
|
tables: Vec<[u8; 4]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,8 +151,6 @@ fn resolve_acpi() {
|
|||||||
|
|
||||||
let rsdp = unsafe { &*rsdp_ptr.unwrap().address.as_ptr().unwrap().cast::<RSDP>() };
|
let rsdp = unsafe { &*rsdp_ptr.unwrap().address.as_ptr().unwrap().cast::<RSDP>() };
|
||||||
|
|
||||||
log_info!("RSDP: {rsdp:X?}");
|
|
||||||
|
|
||||||
// TODO: validate RSDT
|
// TODO: validate RSDT
|
||||||
let root_sdt = {
|
let root_sdt = {
|
||||||
if rsdp.revision == 0 {
|
if rsdp.revision == 0 {
|
||||||
@@ -150,8 +161,6 @@ fn resolve_acpi() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
log_info!("{root_sdt:X?}");
|
|
||||||
|
|
||||||
let tables: Vec<[u8; 4]> = (0..root_sdt.len())
|
let tables: Vec<[u8; 4]> = (0..root_sdt.len())
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
let sdt_ptr = unsafe { root_sdt.get(i) };
|
let sdt_ptr = unsafe { root_sdt.get(i) };
|
||||||
@@ -243,19 +252,35 @@ struct FADT {
|
|||||||
pub fn init_acpi() {
|
pub fn init_acpi() {
|
||||||
resolve_acpi();
|
resolve_acpi();
|
||||||
|
|
||||||
|
crate::log_ok!("Found {} ACPI Tables!", ACPI.tables.len());
|
||||||
|
|
||||||
|
crate::log_serial!("Available serial tables:");
|
||||||
|
for i in 0..ACPI.tables.len() {
|
||||||
|
crate::log_serial!(" {}", core::str::from_utf8(&ACPI.tables[i]).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
let fadt = find_table::<FADT>("FACP").expect("Failed to find FADT");
|
let fadt = find_table::<FADT>("FACP").expect("Failed to find FADT");
|
||||||
|
|
||||||
crate::println!("{fadt:X?}");
|
outb(fadt.inner.smi_cmd_port as u16, fadt.inner.acpi_enable);
|
||||||
|
|
||||||
|
while inw(fadt.inner.pm1a_control_block as u16) & 1 == 0 {}
|
||||||
|
|
||||||
|
crate::arch::interrupts::PICS.lock().write().disable();
|
||||||
|
|
||||||
|
*crate::arch::apic::APIC.lock().write() =
|
||||||
|
Some(crate::arch::apic::APIC::new().expect("Failed to enable APIC!"));
|
||||||
|
|
||||||
|
crate::log_ok!("APIC enabled!");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_table<T: Copy>(table_name: &str) -> Option<SDT<T>> {
|
pub fn find_table<T>(table_name: &str) -> Option<SDT<T>> {
|
||||||
assert_eq!(table_name.len(), 4);
|
assert_eq!(table_name.len(), 4);
|
||||||
|
|
||||||
for (i, table) in ACPI.tables.iter().enumerate() {
|
for (i, table) in ACPI.tables.iter().enumerate() {
|
||||||
if table == table_name.as_bytes() {
|
if table == table_name.as_bytes() {
|
||||||
let ptr = unsafe { ACPI.root_sdt.get(i).cast::<SDT<T>>() };
|
let ptr = unsafe { ACPI.root_sdt.get(i) };
|
||||||
crate::println!("Found {table_name} at index {i} {ptr:p}");
|
|
||||||
let table = unsafe { *ptr };
|
let table = unsafe { SDT::new(ptr) };
|
||||||
return Some(table);
|
return Some(table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,7 @@ static EXTENDED_KEY: AtomicBool = AtomicBool::new(false);
|
|||||||
|
|
||||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||||
pub extern "x86-interrupt" fn keyboard_interrupt_handler() {
|
pub extern "x86-interrupt" fn keyboard_interrupt_handler() {
|
||||||
interrupts::PICS
|
interrupts::signal_end_of_interrupt(InterruptIndex::Keyboard.as_u8());
|
||||||
.lock()
|
|
||||||
.write()
|
|
||||||
.notify_end_of_interrupt(interrupts::InterruptIndex::Keyboard.as_u8());
|
|
||||||
|
|
||||||
let scancode = inb(KBD_DATA_PORT);
|
let scancode = inb(KBD_DATA_PORT);
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||||
pub mod acpi;
|
pub mod acpi;
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
|
|||||||
@@ -42,6 +42,14 @@ pub fn init_serial() -> u8 {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_string(string: &str) {
|
||||||
|
for &ch in string.as_bytes() {
|
||||||
|
write_serial(ch as char);
|
||||||
|
}
|
||||||
|
write_serial('\n');
|
||||||
|
write_serial('\r');
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||||
pub fn init_serial() -> u8 {
|
pub fn init_serial() -> u8 {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -241,6 +241,9 @@ impl ATABus {
|
|||||||
outb(self.io_bar + ATADriveDataRegister::LBA1 as u16, 0);
|
outb(self.io_bar + ATADriveDataRegister::LBA1 as u16, 0);
|
||||||
outb(self.io_bar + ATADriveDataRegister::LBA2 as u16, 0);
|
outb(self.io_bar + ATADriveDataRegister::LBA2 as u16, 0);
|
||||||
|
|
||||||
|
// disable interrupts by setting bit 2 in the control port
|
||||||
|
outb(self.control_bar + 0x0C - 0x0A, 2);
|
||||||
|
|
||||||
self.send_command(ATADriveCommand::Identify);
|
self.send_command(ATADriveCommand::Identify);
|
||||||
|
|
||||||
if self.status() == 0x00 {
|
if self.status() == 0x00 {
|
||||||
|
|||||||
@@ -3,6 +3,13 @@ macro_rules! log_info {
|
|||||||
($($arg:tt)*) => ($crate::println!("\033[97m[ \033[90m? \033[97m]\033[0m {}", &alloc::format!($($arg)*)));
|
($($arg:tt)*) => ($crate::println!("\033[97m[ \033[90m? \033[97m]\033[0m {}", &alloc::format!($($arg)*)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! log_serial {
|
||||||
|
($($arg:tt)*) => (
|
||||||
|
$crate::drivers::serial::write_string(&alloc::format!($($arg)*))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! log_error {
|
macro_rules! log_error {
|
||||||
($($arg:tt)*) => ($crate::println!("\033[97m[ \033[91m! \033[97m]\033[0m {}", &alloc::format!($($arg)*)));
|
($($arg:tt)*) => ($crate::println!("\033[97m[ \033[91m! \033[97m]\033[0m {}", &alloc::format!($($arg)*)));
|
||||||
|
|||||||
@@ -28,10 +28,11 @@ pub extern "C" fn _start() -> ! {
|
|||||||
|
|
||||||
serial::init_serial();
|
serial::init_serial();
|
||||||
|
|
||||||
mem::log_info();
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||||
|
|
||||||
drivers::acpi::init_acpi();
|
drivers::acpi::init_acpi();
|
||||||
|
|
||||||
|
mem::log_info();
|
||||||
|
|
||||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||||
drivers::pci::enumerate_pci_bus();
|
drivers::pci::enumerate_pci_bus();
|
||||||
|
|
||||||
|
|||||||
@@ -137,17 +137,13 @@ pub fn log_memory_map() {
|
|||||||
|
|
||||||
let memmap = memmap_request.unwrap().memmap();
|
let memmap = memmap_request.unwrap().memmap();
|
||||||
|
|
||||||
crate::println!("====== MEMORY MAP ======");
|
crate::log_serial!("====== MEMORY MAP ======");
|
||||||
for entry in memmap.iter() {
|
for entry in memmap.iter() {
|
||||||
let label = (entry.len as usize).label_bytes();
|
let label = (entry.len as usize).label_bytes();
|
||||||
|
|
||||||
crate::println!(
|
crate::log_serial!(
|
||||||
"[ {:#018X?} ] Type: \033[{};m{:?}\033[0;m Size: {}",
|
"[ {:#018X?} ] Type: {:?} Size: {}",
|
||||||
entry.base..entry.base + entry.len,
|
entry.base..entry.base + entry.len,
|
||||||
match entry.typ {
|
|
||||||
limine::MemoryMapEntryType::Usable => 32,
|
|
||||||
_ => 31,
|
|
||||||
},
|
|
||||||
entry.typ,
|
entry.typ,
|
||||||
label
|
label
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user