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.
|
||||
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]]
|
||||
name = "kernel"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"buddyalloc",
|
||||
"heapless",
|
||||
"uefi",
|
||||
"x86_drivers",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||
|
||||
[[package]]
|
||||
name = "uefi"
|
||||
version = "0.1.0"
|
||||
|
||||
@@ -4,5 +4,7 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
buddyalloc = "0.1.5"
|
||||
heapless = "0.9.3"
|
||||
uefi = {path = "../uefi"}
|
||||
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]
|
||||
#![deny(clippy::perf, clippy::all, clippy::pedantic)]
|
||||
#![feature(abi_x86_interrupt)]
|
||||
|
||||
pub mod handler;
|
||||
pub mod paging;
|
||||
|
||||
use core::{
|
||||
mem::MaybeUninit,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
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};
|
||||
pub use x86_drivers::prelude::*;
|
||||
|
||||
@@ -32,10 +32,9 @@ extern "efiapi" fn efi_main(handle: Handle, table: *mut EfiSystemTable) -> UefiS
|
||||
.boot_services()
|
||||
.memory_map(arena)
|
||||
.expect("memory map failed");
|
||||
for el in map
|
||||
.filter_map(|segment| segment.memory_type.interpret().map(|f| (f, segment)))
|
||||
.filter(|(t, _segment)| *t == EfiMemoryType::ConventionalMemory)
|
||||
{
|
||||
|
||||
let map = create_region_map::<1024>(map);
|
||||
for el in map {
|
||||
print!("Map element {:?}\r\n", el);
|
||||
}
|
||||
|
||||
@@ -57,6 +56,61 @@ extern "efiapi" fn efi_main(handle: Handle, table: *mut EfiSystemTable) -> UefiS
|
||||
);
|
||||
gdt_init();
|
||||
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)]
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user