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",
|
"limine",
|
||||||
"linked_list_allocator",
|
"linked_list_allocator",
|
||||||
"log",
|
"log",
|
||||||
|
"pic8259",
|
||||||
"slab",
|
"slab",
|
||||||
"spin 0.9.4",
|
"spin 0.9.4",
|
||||||
"uart_16550",
|
"uart_16550",
|
||||||
|
|
|
@ -39,6 +39,7 @@ pub fn init() {
|
||||||
use x86_64::instructions::segmentation::{Segment, CS};
|
use x86_64::instructions::segmentation::{Segment, CS};
|
||||||
use x86_64::instructions::tables::load_tss;
|
use x86_64::instructions::tables::load_tss;
|
||||||
|
|
||||||
|
log::debug!("Initialising GDT");
|
||||||
GDT.0.load();
|
GDT.0.load();
|
||||||
unsafe {
|
unsafe {
|
||||||
CS::set_reg(GDT.1.code_selector);
|
CS::set_reg(GDT.1.code_selector);
|
||||||
|
|
|
@ -17,5 +17,6 @@ features = ["alloc"]
|
||||||
|
|
||||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||||
limine = "0.1"
|
limine = "0.1"
|
||||||
|
pic8259 = "0.10"
|
||||||
uart_16550 = "0.2"
|
uart_16550 = "0.2"
|
||||||
x86_64 = "0.14"
|
x86_64 = "0.14"
|
||||||
|
|
|
@ -12,6 +12,7 @@ use crate::allocator::{HEAP_SIZE, HEAP_START};
|
||||||
static ALLOCATOR: LockedHeap = LockedHeap::empty();
|
static ALLOCATOR: LockedHeap = LockedHeap::empty();
|
||||||
|
|
||||||
pub unsafe fn init_alloc() -> Result<(), MapToError<Size4KiB>> {
|
pub unsafe fn init_alloc() -> Result<(), MapToError<Size4KiB>> {
|
||||||
|
log::info!("Initialising kernel heap allocator");
|
||||||
let page_range = Page::range_inclusive(
|
let page_range = Page::range_inclusive(
|
||||||
Page::containing_address(VirtAddr::new(HEAP_START as u64)),
|
Page::containing_address(VirtAddr::new(HEAP_START as u64)),
|
||||||
Page::containing_address(VirtAddr::new(HEAP_START as u64) + HEAP_SIZE - 1u64),
|
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
|
/// Initialise page table
|
||||||
pub unsafe fn init_pt(phys_base: VirtAddr) {
|
pub unsafe fn init_pt(phys_base: VirtAddr) {
|
||||||
|
log::info!("Retrieving page table");
|
||||||
PAGE_TABLE.call_once(|| {
|
PAGE_TABLE.call_once(|| {
|
||||||
Mutex::new(OffsetPageTable::new(
|
Mutex::new(OffsetPageTable::new(
|
||||||
&mut *((phys_base
|
&mut *((phys_base
|
||||||
|
@ -25,6 +26,7 @@ pub unsafe fn init_pt(phys_base: VirtAddr) {
|
||||||
|
|
||||||
/// Initialise page frame allocator
|
/// Initialise page frame allocator
|
||||||
pub unsafe fn init_falloc(mmap: &'static [LimineMemmapEntry]) {
|
pub unsafe fn init_falloc(mmap: &'static [LimineMemmapEntry]) {
|
||||||
|
log::info!("Initialising frame allocator");
|
||||||
FRAME_ALLOC.call_once(|| Mutex::new(FrameAlloc::new(mmap)));
|
FRAME_ALLOC.call_once(|| Mutex::new(FrameAlloc::new(mmap)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ use uart_16550::SerialPort;
|
||||||
use x86_64::VirtAddr;
|
use x86_64::VirtAddr;
|
||||||
|
|
||||||
mod allocator;
|
mod allocator;
|
||||||
|
mod gdt;
|
||||||
|
mod idt;
|
||||||
mod memory;
|
mod memory;
|
||||||
|
|
||||||
static SERIAL_CONSOLE: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3f8) });
|
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");
|
allocator::init_alloc().expect("tried to initialise allocator");
|
||||||
|
gdt::init();
|
||||||
|
idt::init();
|
||||||
|
|
||||||
crate::kmain::kmain()
|
crate::kmain::kmain()
|
||||||
}
|
}
|
||||||
|
@ -41,5 +45,12 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
||||||
/// Format args to serial console
|
/// Format args to serial console
|
||||||
pub fn serial_fmt(args: core::fmt::Arguments<'_>) -> core::fmt::Result {
|
pub fn serial_fmt(args: core::fmt::Arguments<'_>) -> core::fmt::Result {
|
||||||
use core::fmt::Write;
|
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
|
//! AbleOS Kernel Entrypoint
|
||||||
|
|
||||||
pub fn kmain() -> ! {
|
pub fn kmain() -> ! {
|
||||||
loop {}
|
log::trace!("Entered kmain");
|
||||||
|
crate::arch::sloop()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
//! The ableOS kernel.
|
//! The ableOS kernel.
|
||||||
|
|
||||||
#![feature(alloc_error_handler, prelude_import)]
|
#![feature(
|
||||||
|
abi_x86_interrupt,
|
||||||
|
alloc_error_handler,
|
||||||
|
panic_info_message,
|
||||||
|
prelude_import
|
||||||
|
)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
pub mod allocator;
|
pub mod allocator;
|
||||||
pub mod arch;
|
pub mod arch;
|
||||||
pub mod logger;
|
|
||||||
pub mod kmain;
|
pub mod kmain;
|
||||||
|
pub mod logger;
|
||||||
pub mod task;
|
pub mod task;
|
||||||
|
|
||||||
use versioning::Version;
|
use versioning::Version;
|
||||||
|
@ -22,5 +27,23 @@ pub const VERSION: Version = Version {
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(info: &core::panic::PanicInfo) -> ! {
|
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 {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue