forked from koniifer/ableos
Added GDT, IDT, sloop and some logging
This commit is contained in:
parent
b3954e3533
commit
a9aa31f087
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -586,6 +586,7 @@ dependencies = [
|
|||
"limine",
|
||||
"linked_list_allocator",
|
||||
"log",
|
||||
"pic8259",
|
||||
"slab",
|
||||
"spin 0.9.4",
|
||||
"uart_16550",
|
||||
|
|
|
@ -39,6 +39,7 @@ pub fn init() {
|
|||
use x86_64::instructions::segmentation::{Segment, CS};
|
||||
use x86_64::instructions::tables::load_tss;
|
||||
|
||||
log::debug!("Initialising GDT");
|
||||
GDT.0.load();
|
||||
unsafe {
|
||||
CS::set_reg(GDT.1.code_selector);
|
||||
|
|
|
@ -17,5 +17,6 @@ features = ["alloc"]
|
|||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||
limine = "0.1"
|
||||
pic8259 = "0.10"
|
||||
uart_16550 = "0.2"
|
||||
x86_64 = "0.14"
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::allocator::{HEAP_SIZE, HEAP_START};
|
|||
static ALLOCATOR: LockedHeap = LockedHeap::empty();
|
||||
|
||||
pub unsafe fn init_alloc() -> Result<(), MapToError<Size4KiB>> {
|
||||
log::info!("Initialising kernel heap allocator");
|
||||
let page_range = Page::range_inclusive(
|
||||
Page::containing_address(VirtAddr::new(HEAP_START as u64)),
|
||||
Page::containing_address(VirtAddr::new(HEAP_START as u64) + HEAP_SIZE - 1u64),
|
||||
|
|
57
kernel/src/arch/x86_64/gdt.rs
Normal file
57
kernel/src/arch/x86_64/gdt.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
use spin::Lazy;
|
||||
use x86_64::{
|
||||
structures::{
|
||||
gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector},
|
||||
tss::TaskStateSegment,
|
||||
},
|
||||
VirtAddr,
|
||||
};
|
||||
|
||||
pub const DOUBLE_FAULT_IX: u16 = 0;
|
||||
|
||||
pub unsafe fn init() {
|
||||
use x86_64::instructions::segmentation::{Segment, CS, DS};
|
||||
use x86_64::instructions::tables::load_tss;
|
||||
|
||||
log::info!("Initialising GDT");
|
||||
GDT.0.load();
|
||||
unsafe {
|
||||
CS::set_reg(GDT.1.kcode);
|
||||
DS::set_reg(GDT.1.kdata);
|
||||
load_tss(GDT.1.tss);
|
||||
}
|
||||
}
|
||||
|
||||
struct Selectors {
|
||||
kcode: SegmentSelector,
|
||||
kdata: SegmentSelector,
|
||||
tss: SegmentSelector,
|
||||
udata: SegmentSelector,
|
||||
ucode: SegmentSelector,
|
||||
}
|
||||
|
||||
static TSS: Lazy<TaskStateSegment> = Lazy::new(|| {
|
||||
let mut tss = TaskStateSegment::new();
|
||||
tss.interrupt_stack_table[usize::from(DOUBLE_FAULT_IX)] = {
|
||||
const SIZE: usize = 5 * 1024;
|
||||
let stack = unsafe {
|
||||
alloc::alloc::alloc_zeroed(
|
||||
alloc::alloc::Layout::from_size_align(SIZE, 1).expect("stack pointer"),
|
||||
)
|
||||
};
|
||||
VirtAddr::from_ptr(stack) + SIZE
|
||||
};
|
||||
tss
|
||||
});
|
||||
|
||||
static GDT: Lazy<(GlobalDescriptorTable, Selectors)> = Lazy::new(|| {
|
||||
let mut gdt = GlobalDescriptorTable::new();
|
||||
let sels = Selectors {
|
||||
kcode: gdt.add_entry(Descriptor::kernel_code_segment()),
|
||||
kdata: gdt.add_entry(Descriptor::kernel_data_segment()),
|
||||
tss: gdt.add_entry(Descriptor::tss_segment(&TSS)),
|
||||
udata: gdt.add_entry(Descriptor::user_data_segment()),
|
||||
ucode: gdt.add_entry(Descriptor::user_code_segment()),
|
||||
};
|
||||
(gdt, sels)
|
||||
});
|
52
kernel/src/arch/x86_64/idt.rs
Normal file
52
kernel/src/arch/x86_64/idt.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
use pic8259::ChainedPics;
|
||||
use spin::{Lazy, Mutex};
|
||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
|
||||
|
||||
pub const PIC_1_OFFSET: u8 = 32;
|
||||
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
|
||||
|
||||
static PICS: Mutex<ChainedPics> =
|
||||
Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
|
||||
|
||||
pub unsafe fn init() {
|
||||
log::info!("Initialising IDT");
|
||||
IDT.load();
|
||||
PICS.lock().initialize();
|
||||
x86_64::instructions::interrupts::enable();
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
enum Interrupt {
|
||||
Timer = PIC_1_OFFSET,
|
||||
}
|
||||
|
||||
static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
|
||||
let mut idt = InterruptDescriptorTable::new();
|
||||
unsafe {
|
||||
idt.double_fault
|
||||
.set_handler_fn(double_fault)
|
||||
.set_stack_index(super::gdt::DOUBLE_FAULT_IX);
|
||||
}
|
||||
idt.page_fault.set_handler_fn(page_fault);
|
||||
idt[Interrupt::Timer as usize].set_handler_fn(timer);
|
||||
idt
|
||||
});
|
||||
|
||||
extern "x86-interrupt" fn double_fault(stack_frame: InterruptStackFrame, error_code: u64) -> ! {
|
||||
panic!("Double fault: error code {error_code} \n{stack_frame:#?}")
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn page_fault(
|
||||
stack_frame: InterruptStackFrame,
|
||||
error_code: PageFaultErrorCode,
|
||||
) {
|
||||
panic!("Page fault ({error_code:?}): {stack_frame:?}")
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn timer(_: InterruptStackFrame) {
|
||||
unsafe { eoi(Interrupt::Timer as u8) };
|
||||
}
|
||||
|
||||
unsafe fn eoi(i: u8) {
|
||||
PICS.lock().notify_end_of_interrupt(i);
|
||||
}
|
|
@ -10,6 +10,7 @@ pub static FRAME_ALLOC: Once<Mutex<FrameAlloc>> = Once::new();
|
|||
|
||||
/// Initialise page table
|
||||
pub unsafe fn init_pt(phys_base: VirtAddr) {
|
||||
log::info!("Retrieving page table");
|
||||
PAGE_TABLE.call_once(|| {
|
||||
Mutex::new(OffsetPageTable::new(
|
||||
&mut *((phys_base
|
||||
|
@ -25,6 +26,7 @@ pub unsafe fn init_pt(phys_base: VirtAddr) {
|
|||
|
||||
/// Initialise page frame allocator
|
||||
pub unsafe fn init_falloc(mmap: &'static [LimineMemmapEntry]) {
|
||||
log::info!("Initialising frame allocator");
|
||||
FRAME_ALLOC.call_once(|| Mutex::new(FrameAlloc::new(mmap)));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ use uart_16550::SerialPort;
|
|||
use x86_64::VirtAddr;
|
||||
|
||||
mod allocator;
|
||||
mod gdt;
|
||||
mod idt;
|
||||
mod memory;
|
||||
|
||||
static SERIAL_CONSOLE: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3f8) });
|
||||
|
@ -34,6 +36,8 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
|||
);
|
||||
|
||||
allocator::init_alloc().expect("tried to initialise allocator");
|
||||
gdt::init();
|
||||
idt::init();
|
||||
|
||||
crate::kmain::kmain()
|
||||
}
|
||||
|
@ -41,5 +45,12 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
|||
/// Format args to serial console
|
||||
pub fn serial_fmt(args: core::fmt::Arguments<'_>) -> core::fmt::Result {
|
||||
use core::fmt::Write;
|
||||
SERIAL_CONSOLE.lock().write_fmt(args)
|
||||
x86_64::instructions::interrupts::without_interrupts(|| SERIAL_CONSOLE.lock().write_fmt(args))
|
||||
}
|
||||
|
||||
/// Spin loop
|
||||
pub fn sloop() -> ! {
|
||||
loop {
|
||||
x86_64::instructions::hlt();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! AbleOS Kernel Entrypoint
|
||||
|
||||
pub fn kmain() -> ! {
|
||||
loop {}
|
||||
log::trace!("Entered kmain");
|
||||
crate::arch::sloop()
|
||||
}
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
//! The ableOS kernel.
|
||||
|
||||
#![feature(alloc_error_handler, prelude_import)]
|
||||
#![feature(
|
||||
abi_x86_interrupt,
|
||||
alloc_error_handler,
|
||||
panic_info_message,
|
||||
prelude_import
|
||||
)]
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
pub mod allocator;
|
||||
pub mod arch;
|
||||
pub mod logger;
|
||||
pub mod kmain;
|
||||
pub mod logger;
|
||||
pub mod task;
|
||||
|
||||
use versioning::Version;
|
||||
|
@ -22,5 +27,23 @@ pub const VERSION: Version = Version {
|
|||
|
||||
#[panic_handler]
|
||||
fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||
// TODO: Better panic handler
|
||||
let _ = crate::arch::serial_fmt(format_args!(
|
||||
"\x1b[1m\x1b[4m\x1b[38;5;125mKernel Panic\x1b[0m\r\n",
|
||||
));
|
||||
|
||||
if let Some(loc) = info.location() {
|
||||
let _ = crate::arch::serial_fmt(format_args!(
|
||||
"Location: {} : {} / {}\r\n",
|
||||
loc.file(),
|
||||
loc.line(),
|
||||
loc.column()
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(msg) = info.message() {
|
||||
let _ = crate::arch::serial_fmt(format_args!("{msg}\r\n"));
|
||||
}
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue