Initial work on paging, also complete ish interrupt registration
This commit is contained in:
39
kernel/Cargo.lock
generated
39
kernel/Cargo.lock
generated
@@ -2,14 +2,53 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "buddyalloc"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5ded974e2422fae8075cb72650eae5b12f076e480eb44930571f6bddf325b31"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hash32"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heapless"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "25ba4bd83f9415b58b4ed8dc5714c76e626a105be4646c02630ad730ad3b5aa4"
|
||||||
|
dependencies = [
|
||||||
|
"hash32",
|
||||||
|
"stable_deref_trait",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kernel"
|
name = "kernel"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"buddyalloc",
|
||||||
|
"heapless",
|
||||||
"uefi",
|
"uefi",
|
||||||
"x86_drivers",
|
"x86_drivers",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stable_deref_trait"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uefi"
|
name = "uefi"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|||||||
@@ -4,5 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
buddyalloc = "0.1.5"
|
||||||
|
heapless = "0.9.3"
|
||||||
uefi = {path = "../uefi"}
|
uefi = {path = "../uefi"}
|
||||||
x86_drivers = {path = "../x86_drivers"}
|
x86_drivers = {path = "../x86_drivers"}
|
||||||
|
|||||||
25
kernel/src/handler.rs
Normal file
25
kernel/src/handler.rs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
use x86_drivers::idt::InterruptStackFrame;
|
||||||
|
|
||||||
|
pub extern "x86-interrupt" fn page_fault(f: InterruptStackFrame, err: u64) {
|
||||||
|
let cr2: u64;
|
||||||
|
unsafe {
|
||||||
|
core::arch::asm!("mov {}, cr2", out(reg) cr2, options(nomem, nostack, preserves_flags));
|
||||||
|
}
|
||||||
|
panic!("PAGE FAULT addr={:#x} err={:#x} ip={:#x}", cr2, err, f.ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern "x86-interrupt" fn double_fault(f: InterruptStackFrame, _err: u64) -> ! {
|
||||||
|
panic!("DOUBLE FAULT ip={:#x}", f.ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern "x86-interrupt" fn gp_fault(f: InterruptStackFrame, err: u64) {
|
||||||
|
panic!("GP FAULT err={:#x} ip={:#x}", err, f.ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern "x86-interrupt" fn invalid_opcode(f: InterruptStackFrame) {
|
||||||
|
panic!("INVALID OPCODE ip={:#x}", f.ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern "x86-interrupt" fn divide(f: InterruptStackFrame) {
|
||||||
|
panic!("DIVIDE ip={:#x}", f.ip);
|
||||||
|
}
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![deny(clippy::perf, clippy::all, clippy::pedantic)]
|
#![deny(clippy::perf, clippy::all, clippy::pedantic)]
|
||||||
|
#![feature(abi_x86_interrupt)]
|
||||||
|
|
||||||
|
pub mod handler;
|
||||||
|
pub mod paging;
|
||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
mem::MaybeUninit,
|
mem::MaybeUninit,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
use uefi::{EfiMemoryType, EfiSystemTable, ExitBootServicesKey, Handle, UefiStatus};
|
use uefi::{EfiMemoryType, EfiSystemTable, ExitBootServicesKey, Handle, UefiStatus};
|
||||||
|
|
||||||
use kernel::print;
|
use kernel::{handler, paging::create_region_map, print};
|
||||||
use x86_drivers::gdt::{DPL, GdtEntry, GdtPointer, GdtSelector};
|
use x86_drivers::gdt::{DPL, GdtEntry, GdtPointer, GdtSelector};
|
||||||
pub use x86_drivers::prelude::*;
|
pub use x86_drivers::prelude::*;
|
||||||
|
|
||||||
@@ -32,10 +32,9 @@ extern "efiapi" fn efi_main(handle: Handle, table: *mut EfiSystemTable) -> UefiS
|
|||||||
.boot_services()
|
.boot_services()
|
||||||
.memory_map(arena)
|
.memory_map(arena)
|
||||||
.expect("memory map failed");
|
.expect("memory map failed");
|
||||||
for el in map
|
|
||||||
.filter_map(|segment| segment.memory_type.interpret().map(|f| (f, segment)))
|
let map = create_region_map::<1024>(map);
|
||||||
.filter(|(t, _segment)| *t == EfiMemoryType::ConventionalMemory)
|
for el in map {
|
||||||
{
|
|
||||||
print!("Map element {:?}\r\n", el);
|
print!("Map element {:?}\r\n", el);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +56,61 @@ extern "efiapi" fn efi_main(handle: Handle, table: *mut EfiSystemTable) -> UefiS
|
|||||||
);
|
);
|
||||||
gdt_init();
|
gdt_init();
|
||||||
print!("Initiated GDT");
|
print!("Initiated GDT");
|
||||||
|
|
||||||
|
let mut idt = Idt::new().set_table();
|
||||||
|
print!("Set idt :)");
|
||||||
|
|
||||||
|
named_isr::PageFault::register_handler(
|
||||||
|
&mut idt,
|
||||||
|
handler::page_fault,
|
||||||
|
GDT_KERNEL_CODE_SELECTOR,
|
||||||
|
Ist::Idx0,
|
||||||
|
Gate::Interrupt,
|
||||||
|
DPL::Kernel,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
named_isr::DoubleFault::register_handler(
|
||||||
|
&mut idt,
|
||||||
|
handler::double_fault,
|
||||||
|
GDT_KERNEL_CODE_SELECTOR,
|
||||||
|
Ist::Idx0,
|
||||||
|
Gate::Interrupt,
|
||||||
|
DPL::Kernel,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
named_isr::GeneralProtectionFault::register_handler(
|
||||||
|
&mut idt,
|
||||||
|
handler::gp_fault,
|
||||||
|
GDT_KERNEL_CODE_SELECTOR,
|
||||||
|
Ist::Idx0,
|
||||||
|
Gate::Interrupt,
|
||||||
|
DPL::Kernel,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
named_isr::InvalidOpcode::register_handler(
|
||||||
|
&mut idt,
|
||||||
|
handler::invalid_opcode,
|
||||||
|
GDT_KERNEL_CODE_SELECTOR,
|
||||||
|
Ist::Idx0,
|
||||||
|
Gate::Interrupt,
|
||||||
|
DPL::Kernel,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
named_isr::DivisionError::register_handler(
|
||||||
|
&mut idt,
|
||||||
|
handler::divide,
|
||||||
|
GDT_KERNEL_CODE_SELECTOR,
|
||||||
|
Ist::Idx0,
|
||||||
|
Gate::Interrupt,
|
||||||
|
DPL::Kernel,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
print!("Set all ISRs :)");
|
||||||
|
|
||||||
#[allow(clippy::empty_loop)]
|
#[allow(clippy::empty_loop)]
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|||||||
107
kernel/src/paging.rs
Normal file
107
kernel/src/paging.rs
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
use uefi::{EfiMemoryType, PageIter};
|
||||||
|
|
||||||
|
use crate::print;
|
||||||
|
|
||||||
|
#[repr(C, align(4096))]
|
||||||
|
pub struct Page {
|
||||||
|
data: [u8; 4096],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct Region {
|
||||||
|
start: *const Page,
|
||||||
|
count: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Region {
|
||||||
|
pub const fn null() -> Self {
|
||||||
|
Self {
|
||||||
|
start: core::ptr::null(),
|
||||||
|
count: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn new(start: *const Page, count: usize) -> Self {
|
||||||
|
Self { start, count }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn size(&self) -> usize {
|
||||||
|
self.count * core::mem::size_of::<Page>()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end_addr(&self) -> usize {
|
||||||
|
self.start as usize + self.count * core::mem::size_of::<Page>()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn can_coalesce(&self, other: &Self) -> bool {
|
||||||
|
let end = self.end_addr();
|
||||||
|
other.start as usize == end
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn coalesce(self, other: Self) -> Self {
|
||||||
|
// TODO: make type system track this
|
||||||
|
assert!(self.can_coalesce(&other), "Must be able to coaless regions");
|
||||||
|
Self::new(self.start, self.count + other.count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_region_map<const BUFFER_SIZE: usize>(
|
||||||
|
iter: PageIter<'_>,
|
||||||
|
) -> heapless::Vec<Region, BUFFER_SIZE> {
|
||||||
|
let mut vec = heapless::Vec::<_, BUFFER_SIZE>::from_iter(
|
||||||
|
iter.filter(|t| {
|
||||||
|
matches!(
|
||||||
|
t.memory_type.interpret(),
|
||||||
|
Some(
|
||||||
|
EfiMemoryType::ConventionalMemory
|
||||||
|
| EfiMemoryType::BootServicesCode
|
||||||
|
| EfiMemoryType::BootServicesData
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.map(|t| Region::new(t.physical_start.raw_ptr(), t.number_of_pages as usize)),
|
||||||
|
);
|
||||||
|
|
||||||
|
vec.sort_unstable_by_key(|f| f.start);
|
||||||
|
|
||||||
|
for start in (0..(vec.len().saturating_sub(1))).rev() {
|
||||||
|
let potential_join = start + 1;
|
||||||
|
let possible = vec[start].can_coalesce(&vec[potential_join]);
|
||||||
|
|
||||||
|
if !possible {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let joinable = vec.remove(potential_join);
|
||||||
|
vec[start] = vec[start].coalesce(joinable);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RegionAllocator<const MAX_REGIONS: usize> {
|
||||||
|
allocators: heapless::Vec<Zone, MAX_REGIONS>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Zone {
|
||||||
|
region: Region,
|
||||||
|
allocator: buddyalloc::Heap<24>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const MAX_REGIONS: usize> RegionAllocator<MAX_REGIONS> {
|
||||||
|
pub fn new(regions: heapless::Vec<Region, MAX_REGIONS>) -> Self {
|
||||||
|
let allocators = heapless::Vec::from_iter(regions.into_iter().map(|region| Zone {
|
||||||
|
allocator: unsafe {
|
||||||
|
buddyalloc::Heap::new(
|
||||||
|
core::ptr::NonNull::new(region.start.cast_mut().cast()).unwrap(),
|
||||||
|
region.size(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
region,
|
||||||
|
}));
|
||||||
|
Self { allocators }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn request_pages
|
||||||
|
}
|
||||||
@@ -97,3 +97,12 @@ impl TryFrom<u32> for EfiMemoryType {
|
|||||||
Self::from_u32(value).ok_or(value)
|
Self::from_u32(value).ok_or(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl EfiPhysicalAddress {
|
||||||
|
pub const fn raw_ptr<T>(&self) -> *const T {
|
||||||
|
self.0 as *const _
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn raw(&self) -> u64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ impl Flags {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct GdtSelector {
|
pub struct GdtSelector {
|
||||||
inner: u16,
|
inner: u16,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,68 @@
|
|||||||
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
use crate::gdt::{DPL, GdtSelector};
|
use crate::gdt::{DPL, GdtSelector};
|
||||||
|
|
||||||
|
pub mod vectors;
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
|
#[must_use]
|
||||||
pub struct InterruptTableDescriptor {
|
pub struct InterruptTableDescriptor {
|
||||||
size: u16,
|
size: u16,
|
||||||
offset: u64,
|
offset: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
#[must_use]
|
||||||
pub struct IdtTableEntry {
|
pub struct IdtTableEntry {
|
||||||
inner: u128,
|
inner: u128,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ISR = extern "x86-interrupt" fn(InterruptStackFrame) -> ();
|
pub type ISR = extern "x86-interrupt" fn(InterruptStackFrame) -> ();
|
||||||
|
pub type ISRWithIdx = extern "x86-interrupt" fn(InterruptStackFrame, u64) -> ();
|
||||||
|
pub type ISRWithIdxNeverReturns = extern "x86-interrupt" fn(InterruptStackFrame, u64) -> !;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
#[must_use]
|
||||||
pub struct InterruptStackFrame {
|
pub struct InterruptStackFrame {
|
||||||
ip: usize,
|
pub ip: usize,
|
||||||
cs: usize,
|
pub cs: usize,
|
||||||
flags: usize,
|
pub flags: usize,
|
||||||
sp: usize,
|
pub sp: usize,
|
||||||
ss: usize,
|
pub ss: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
#[must_use]
|
||||||
pub enum Gate {
|
pub enum Gate {
|
||||||
Interrupt = 0b1110,
|
Interrupt = 0b1110,
|
||||||
Trap = 0b1111,
|
Trap = 0b1111,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IdtTableEntry {
|
#[repr(u8)]
|
||||||
pub fn new(isr: ISR, selector: GdtSelector, ist: u8, gate: Gate, priority: DPL) -> Self {
|
#[must_use]
|
||||||
let mut inner = 0b0;
|
pub enum Ist {
|
||||||
let offset = (isr as *const ()) as u64;
|
Idx0 = 0,
|
||||||
|
Idx1 = 1,
|
||||||
|
Idx2 = 2,
|
||||||
|
Idx3 = 3,
|
||||||
|
Idx4 = 4,
|
||||||
|
Idx5 = 5,
|
||||||
|
Idx6 = 6,
|
||||||
|
Idx7 = 7,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IdtTableEntry {
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
|
const fn build(
|
||||||
|
offset: u64,
|
||||||
|
selector: GdtSelector,
|
||||||
|
ist: Ist,
|
||||||
|
gate: Gate,
|
||||||
|
priority: DPL,
|
||||||
|
) -> Self {
|
||||||
|
let mut inner = 0;
|
||||||
let bytes = (offset >> 32) as u32;
|
let bytes = (offset >> 32) as u32;
|
||||||
inner |= (bytes as u128) << 64;
|
inner |= (bytes as u128) << 64;
|
||||||
|
|
||||||
@@ -44,8 +74,6 @@ impl IdtTableEntry {
|
|||||||
|
|
||||||
inner |= (selector.raw() as u128) << 16;
|
inner |= (selector.raw() as u128) << 16;
|
||||||
|
|
||||||
assert!(ist <= 0b111);
|
|
||||||
|
|
||||||
inner |= (ist as u128) << 32;
|
inner |= (ist as u128) << 32;
|
||||||
inner |= (gate as u128) << 40;
|
inner |= (gate as u128) << 40;
|
||||||
inner |= (priority as u128) << 45;
|
inner |= (priority as u128) << 45;
|
||||||
@@ -53,4 +81,98 @@ impl IdtTableEntry {
|
|||||||
|
|
||||||
Self { inner }
|
Self { inner }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn null() -> Self {
|
||||||
|
Self { inner: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(isr: ISR, selector: GdtSelector, ist: Ist, gate: Gate, priority: DPL) -> Self {
|
||||||
|
let offset = (isr as *const ()) as u64;
|
||||||
|
Self::build(offset, selector, ist, gate, priority)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Make the type system check ist valid here.
|
||||||
|
pub fn with_idx(
|
||||||
|
isr: ISRWithIdx,
|
||||||
|
selector: GdtSelector,
|
||||||
|
ist: Ist,
|
||||||
|
gate: Gate,
|
||||||
|
priority: DPL,
|
||||||
|
) -> Self {
|
||||||
|
let offset = (isr as *const ()) as u64;
|
||||||
|
Self::build(offset, selector, ist, gate, priority)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static mut IDT: [IdtTableEntry; 256] = [IdtTableEntry::null(); _];
|
||||||
|
static ASSIGNED: [AtomicBool; 256] = [const { AtomicBool::new(false) }; 256];
|
||||||
|
#[allow(static_mut_refs)]
|
||||||
|
const IDT_SIZE: u16 = unsafe { (core::mem::size_of_val(&IDT) - 1) as u16 };
|
||||||
|
static IDT_INITIATED: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub struct Idt<const TABLE_SPECIFIED: bool>;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[must_use]
|
||||||
|
pub enum Error {
|
||||||
|
InvalidVectorIndex,
|
||||||
|
VectorAlreadyAssigned,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const TABLE_SPECIFIED: bool> Idt<TABLE_SPECIFIED> {
|
||||||
|
/// Registers a new handler
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This function is safe assuming that this is the only [`Idt`] that exists. This assumption
|
||||||
|
/// holds given that the user does not forcibly create one.
|
||||||
|
pub fn register_handler(
|
||||||
|
&mut self,
|
||||||
|
vector: usize,
|
||||||
|
entry: IdtTableEntry,
|
||||||
|
) -> Result<&mut Self, Error> {
|
||||||
|
if vector >= ASSIGNED.len() {
|
||||||
|
return Err(Error::InvalidVectorIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ASSIGNED[vector].swap(true, Ordering::AcqRel) {
|
||||||
|
return Err(Error::VectorAlreadyAssigned);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { IDT[vector] = entry };
|
||||||
|
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(static_mut_refs)]
|
||||||
|
fn table(&self) -> InterruptTableDescriptor {
|
||||||
|
let addr = unsafe { IDT.as_ptr() as *const _ as u64 };
|
||||||
|
InterruptTableDescriptor {
|
||||||
|
size: IDT_SIZE,
|
||||||
|
offset: addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Idt<false> {
|
||||||
|
pub fn set_table(self) -> Idt<true> {
|
||||||
|
let ptr = self.table();
|
||||||
|
unsafe {
|
||||||
|
core::arch::asm!(
|
||||||
|
"lidt [{}]",
|
||||||
|
in(reg) &ptr,
|
||||||
|
options(readonly,nostack,preserves_flags)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Idt
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new() -> Self {
|
||||||
|
assert!(
|
||||||
|
!IDT_INITIATED.swap(true, Ordering::AcqRel),
|
||||||
|
"IDT already initiated"
|
||||||
|
);
|
||||||
|
Self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
73
x86_drivers/src/idt/vectors.rs
Normal file
73
x86_drivers/src/idt/vectors.rs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
use crate::idt::{
|
||||||
|
DPL, Error, Gate, GdtSelector, ISR, ISRWithIdx, ISRWithIdxNeverReturns, Idt, IdtTableEntry, Ist,
|
||||||
|
};
|
||||||
|
|
||||||
|
macro_rules! vector {
|
||||||
|
($(
|
||||||
|
$(~$idx_:literal)?
|
||||||
|
$($idx:literal: $name:ident => $type:ty)?
|
||||||
|
);*) => {
|
||||||
|
pub trait Vector {
|
||||||
|
type FunctionSignature;
|
||||||
|
const IDX:usize;
|
||||||
|
fn register_handler<const REGISTERD:bool>(table:&mut Idt<REGISTERD>, isr: Self::FunctionSignature, selector: GdtSelector, ist: Ist, gate: Gate, priority: DPL) -> Result<&mut Idt<REGISTERD>,Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod named_isr {
|
||||||
|
$(
|
||||||
|
$(pub struct $name;)?
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
$(
|
||||||
|
$(
|
||||||
|
impl Vector for named_isr::$name {
|
||||||
|
type FunctionSignature = $type;
|
||||||
|
const IDX:usize = $idx;
|
||||||
|
|
||||||
|
fn register_handler<const REGISTERD:bool>(table:&mut Idt<REGISTERD>, isr: Self::FunctionSignature, selector: GdtSelector, ist: Ist, gate: Gate, priority: DPL) -> Result<&mut Idt<REGISTERD>,Error> {
|
||||||
|
let offset = (isr as *const ()) as u64;
|
||||||
|
let desc = IdtTableEntry::build(offset, selector, ist, gate, priority);
|
||||||
|
table.register_handler(Self::IDX, desc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)?
|
||||||
|
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector!(
|
||||||
|
0: DivisionError => ISR;
|
||||||
|
1: Debug => ISR;
|
||||||
|
2: NonMaskableInterrupt => ISR;
|
||||||
|
3: Breakpoint => ISR;
|
||||||
|
4: Overflow => ISR;
|
||||||
|
5: BoundRangeExceeded => ISR;
|
||||||
|
6: InvalidOpcode => ISR;
|
||||||
|
7: DeviceNotAvailable => ISR;
|
||||||
|
8: DoubleFault => ISRWithIdxNeverReturns;
|
||||||
|
9: CoprocessorSegmentOverrun => ISR;
|
||||||
|
10: InvalidTSS => ISRWithIdx;
|
||||||
|
11: SegmentNotPresent => ISRWithIdx;
|
||||||
|
12: StackSegmentFault => ISRWithIdx;
|
||||||
|
13: GeneralProtectionFault => ISRWithIdx;
|
||||||
|
14: PageFault => ISRWithIdx;
|
||||||
|
~15;
|
||||||
|
16: X87FloatingPointException => ISR;
|
||||||
|
17: AlignmentCheck => ISRWithIdx;
|
||||||
|
18: MachineCheck => ISR;
|
||||||
|
19: SIMDFloatingPointException => ISR;
|
||||||
|
20: VirtualizationException => ISR;
|
||||||
|
21: ControlProtectionException => ISRWithIdx;
|
||||||
|
~22;
|
||||||
|
~23;
|
||||||
|
~24;
|
||||||
|
~25;
|
||||||
|
~26;
|
||||||
|
~27;
|
||||||
|
28: HypervisorInjectionException => ISR;
|
||||||
|
29: VMMCommunicationException => ISRWithIdx;
|
||||||
|
30: SecurityException => ISRWithIdx;
|
||||||
|
~31;
|
||||||
|
);
|
||||||
@@ -23,7 +23,8 @@
|
|||||||
clippy::unused_self,
|
clippy::unused_self,
|
||||||
clippy::must_use_candidate,
|
clippy::must_use_candidate,
|
||||||
clippy::new_without_default,
|
clippy::new_without_default,
|
||||||
clippy::cast_possible_truncation
|
clippy::cast_possible_truncation,
|
||||||
|
clippy::missing_errors_doc
|
||||||
)]
|
)]
|
||||||
pub mod uart;
|
pub mod uart;
|
||||||
|
|
||||||
@@ -38,5 +39,7 @@ mod private {
|
|||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::core::Core;
|
pub use crate::core::Core;
|
||||||
|
pub use crate::idt::vectors::*;
|
||||||
|
pub use crate::idt::*;
|
||||||
pub use crate::uart::{InitUart, Uart};
|
pub use crate::uart::{InitUart, Uart};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user