WIP: IDT in rust

This commit is contained in:
Jeremy Soller 2016-08-13 18:58:31 -06:00
parent ae34f7b5db
commit dea137be73
10 changed files with 152 additions and 16 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
Cargo.lock
build
target

View file

@ -1,6 +1,10 @@
ARCH?=x86_64
run: qemu
all: build/harddrive.bin
list: build/kernel.list
run: bochs
bochs: build/harddrive.bin
bochs -f bochs.$(ARCH)
@ -11,12 +15,15 @@ qemu: build/harddrive.bin
FORCE:
build/libkernel.a: FORCE
rustc --crate-type staticlib src/lib.rs -o $@
rustc --crate-type staticlib -C lto -O src/lib.rs -o $@
#--target $(ARCH)-unknown-none.json
build/kernel.bin: build/libkernel.a
ld -m elf_$(ARCH) -o $@ -T bootloader/x86/kernel.ld -z max-page-size=0x1000 $<
build/kernel.list: build/kernel.bin
objdump -C -M intel -D $< > $@
build/harddrive.bin: build/kernel.bin
nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/x86/ -ibuild/ bootloader/x86/harddrive.asm

View file

@ -67,21 +67,13 @@ long_mode:
mov gs, rax
mov ss, rax
; load long mode IDT
lidt [idtr]
mov rsp, 0x800000 - 128
mov rax, gdt.tss
ltr ax
;rust init
xor rax, rax
mov eax, [kernel_base + 0x18]
mov [interrupts.handler], rax
mov rax, gdtr
mov rbx, idtr
mov rcx, tss
int 0xFF
mov rbx, gdtr
jmp rax
.lp:
sti
hlt

View file

@ -183,8 +183,8 @@ vesa:
.minx dw 640
.miny dw 480
.required:
.requiredx dw 0 ;1024 ;USE THESE WITH CAUTION
.requiredy dw 0 ;768
.requiredx dw 1024 ;USE THESE WITH CAUTION
.requiredy dw 768
.requiredmode dw 0
.noedidmsg db "EDID not supported.",10,13,0

31
src/arch/x86_64/gdt.rs Normal file
View file

@ -0,0 +1,31 @@
pub const GDT_NULL: usize = 0;
pub const GDT_KERNEL_CODE: usize = 1;
pub const GDT_KERNEL_DATA: usize = 2;
pub const GDT_USER_CODE: usize = 3;
pub const GDT_USER_DATA: usize = 4;
pub const GDT_USER_TLS: usize = 5;
pub const GDT_TSS: usize = 6;
#[repr(packed)]
pub struct GdtDescriptor {
pub size: u16,
pub ptr: u64
}
#[repr(packed)]
pub struct GdtEntry {
pub limitl: u16,
pub basel: u16,
pub basem: u8,
pub attribute: u8,
pub flags_limith: u8,
pub baseh: u8
}
impl GdtEntry {
pub fn set_base(&mut self, base: usize) {
self.basel = base as u16;
self.basem = (base >> 16) as u8;
self.baseh = (base >> 24) as u8;
}
}

53
src/arch/x86_64/idt.rs Normal file
View file

@ -0,0 +1,53 @@
use core::mem;
pub static mut IDTR: IdtDescriptor = IdtDescriptor {
size: 0,
offset: 0
};
pub static mut IDT: [IdtEntry; 256] = [IdtEntry::new(); 256];
#[repr(packed)]
pub struct IdtDescriptor {
pub size: u16,
pub offset: u64
}
impl IdtDescriptor {
pub fn set_slice(&mut self, slice: &'static [IdtEntry]) {
self.size = (slice.len() * mem::size_of::<IdtEntry>() - 1) as u16;
self.offset = slice.as_ptr() as u64;
}
}
#[derive(Copy, Clone, Debug)]
#[repr(packed)]
pub struct IdtEntry {
pub offsetl: u16,
pub selector: u16,
pub zero: u8,
pub attribute: u8,
pub offsetm: u16,
pub offseth: u32,
pub zero2: u32
}
impl IdtEntry {
pub const fn new() -> IdtEntry {
IdtEntry {
offsetl: 0,
selector: 0,
zero: 0,
attribute: 0,
offsetm: 0,
offseth: 0,
zero2: 0
}
}
pub fn set_offset(&mut self, base: usize) {
self.offsetl = base as u16;
self.offsetm = (base >> 16) as u16;
self.offseth = (base >> 32) as u32;
}
}

View file

@ -2,10 +2,35 @@
/// It is increcibly unsafe, and should be minimal in nature
/// It must create the IDT with the correct entries, those entries are
/// defined in other files inside of the `arch` module
use super::idt::{IDTR, IDT};
#[naked]
#[no_mangle]
pub unsafe extern fn kmain() {
asm!("xchg bx, bx" : : : : "intel", "volatile");
loop{}
for entry in IDT.iter_mut() {
entry.attribute = 1 << 7 | 0xE;
entry.selector = 8;
entry.set_offset(&blank as *const _ as usize);
entry.zero = 0;
entry.zero2 = 0;
}
IDTR.set_slice(&IDT);
asm!("lidt [rax]" : : "{rax}"(&IDTR as *const _ as usize) : : "intel", "volatile");
asm!("xchg bx, bx" : : : : "intel", "volatile");
asm!("int 0xFF" : : : : "intel", "volatile");
loop{
asm!("hlt" : : : : "intel", "volatile");
}
}
#[naked]
pub unsafe extern fn blank() {
asm!("xchg bx, bx" : : : : "intel", "volatile");
asm!("iretq" : : : : "intel", "volatile");
}

View file

@ -1,3 +1,9 @@
/// Global descriptor table
pub mod gdt;
/// Interrupt descriptor table
pub mod idt;
/// IRQ Handling
pub mod irq;

20
src/arch/x86_64/tss.rs Normal file
View file

@ -0,0 +1,20 @@
#[repr(packed)]
pub struct Tss {
pub reserved1: u32,
pub sp0: u64,
pub sp1: u64,
pub sp2: u64,
pub reserved2: u32,
pub reserved3: u32,
pub ist1: u64,
pub ist2: u64,
pub ist3: u64,
pub ist4: u64,
pub ist5: u64,
pub ist6: u64,
pub ist7: u64,
pub reserved4: u32,
pub reserved5: u32,
pub reserved6: u16,
pub iomap_base: u16,
}

View file

@ -65,6 +65,7 @@
//! In this case, it is recommended to add one page, 4096 bytes, to the buffer and retry.
#![feature(asm)]
#![feature(const_fn)]
#![feature(lang_items)]
#![feature(naked_functions)]
#![no_std]