Added GDT, IDT, sloop and some logging

This commit is contained in:
Erin 2022-12-08 01:26:43 +01:00 committed by ondra05
parent b3954e3533
commit a9aa31f087
10 changed files with 154 additions and 4 deletions

1
Cargo.lock generated
View file

@ -586,6 +586,7 @@ dependencies = [
"limine",
"linked_list_allocator",
"log",
"pic8259",
"slab",
"spin 0.9.4",
"uart_16550",

View file

@ -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);

View file

@ -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"

View file

@ -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),

View 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)
});

View 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);
}

View file

@ -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)));
}

View file

@ -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();
}
}

View file

@ -1,5 +1,6 @@
//! AbleOS Kernel Entrypoint
pub fn kmain() -> ! {
loop {}
log::trace!("Entered kmain");
crate::arch::sloop()
}

View file

@ -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 {}
}