i'm just trying to figure out this mess.. fml

This commit is contained in:
Jack Halford 2018-05-03 20:27:52 +02:00
parent d3eb0e5138
commit 0aae87eda3
11 changed files with 144 additions and 74 deletions

View file

@ -5,21 +5,22 @@ use x86::*;
use x86::structures::paging::*; use x86::structures::paging::*;
use arch::x86::paging::*; use arch::x86::paging::*;
fn map_heap(active_table: &mut ActivePageTable, offset: usize, size: usize) { fn map_heap(active_table: &mut ActivePageTable, offset: u32, size: u32) {
let heap_start_page = Page::containing_address(VirtAddr::new(offset as u32)); let heap_start_page = Page::containing_address(VirtAddr::new(offset));
let heap_end_page = Page::containing_address(VirtAddr::new(offset as u32 + size as u32 - 1)); let heap_end_page = Page::containing_address(VirtAddr::new(offset + size - 1));
for page in heap_start_page..heap_end_page + 1 { for page in heap_start_page..heap_end_page + 1 {
//we really should only map 1 huge page instead of 1024 small pages
active_table.map(page, PageTableFlags::WRITABLE); active_table.map(page, PageTableFlags::WRITABLE);
} }
} }
/// should be called only once /// should be called only once
pub unsafe fn init(active_table: &mut ActivePageTable) { pub unsafe fn init(active_table: &mut ActivePageTable) {
let offset = ::HEAP_START; let offset = ::KERNEL_HEAP_OFFSET;
let size = ::HEAP_SIZE; let size = ::KERNEL_HEAP_SIZE;
map_heap(active_table, offset, size); map_heap(active_table, offset, size);
Allocator::init(offset, size); Allocator::init(offset as usize, size as usize);
} }

View file

@ -0,0 +1,31 @@
//layout looks like this:
// [kernel 0->4MiB]
// [kernel 4->8MiB]
// [user stack]
// [start of userheap]
// .
// .
// .
// [end of userheap]
// [kernel heap]
// [recursive map] points to first entry
//
// which makes userheap = 4GiB - 4*4MiB (~= 4GiB)
macro_rules! p2 { ($i:expr) => {($i & P2_MASK) / P1_SIZE}}
pub const P2_MASK: u32 = 0xFFC0_0000; //top 10 bits
pub const P1_SIZE: u32 = 0x0040_0000; //4MiB (2**22)
pub const RECURSIVE_PAGE_OFFSET: u32 = (-(P1_SIZE as isize)) as u32;
///1023
pub const RECURSIVE_PAGE_P2: u32 = p2!(RECURSIVE_PAGE_OFFSET);
pub const KERNEL_HEAP_OFFSET: u32 = RECURSIVE_PAGE_OFFSET - P1_SIZE;
///1022
pub const KERNEL_HEAP_P2: u32 = p2!(KERNEL_HEAP_OFFSET);
pub const KERNEL_HEAP_SIZE: u32 = 4 * 1024 * 1024; //4MiB (1 huge page)
pub const USER_OFFSET: u32 = 0x00a0_0000; //3rd page (kernel takes 2 first pages)
pub const USER_P2: u32 = p2!(USER_OFFSET);
pub const USER_STACK_OFFSET: u32 = USER_OFFSET + P1_SIZE;
pub const USER_STACK_2: u32 = p2!(USER_STACK_OFFSET);

View file

@ -1,49 +1,38 @@
use x86::structures::gdt; use x86::structures::gdt;
use x86::structures::tss; use x86::structures::tss;
use x86::instructions::segmentation::set_cs; use x86::instructions::segmentation::*;
use x86::instructions::tables::load_tss; use x86::instructions::tables::load_tss;
use x86::registers::control; use x86::*;
use arch::x86::paging::ActivePageTable;
use spin::Once; use spin::Once;
static GDT: Once<gdt::Gdt> = Once::new(); pub static mut GDT: gdt::Gdt = gdt::Gdt::new();
static TSS_MAIN: Once<tss::TaskStateSegment> = Once::new(); pub static mut TSS: tss::TaskStateSegment = tss::TaskStateSegment::new();
static TSS_INT: Once<tss::TaskStateSegment> = Once::new();
pub fn init(mut active_table: &mut ActivePageTable) { pub static GDT_KERNEL_CODE: u16 = 1;
let tss_main = TSS_MAIN.call_once(|| { pub static GDT_KERNEL_DATA: u16 = 1;
let mut tss = tss::TaskStateSegment::new(); pub static GDT_USER_CODE: u16 = 2;
// tss.esp0 = stack.top; pub static GDT_USER_DATA: u16 = 3;
// tss.ss = 0x8;
tss.cr3 = control::Cr3::read_u32();
tss.reserved_iopb = 1; //T debug bit
tss
});
let mut code_selector = gdt::SegmentSelector(0); pub unsafe fn init() {
let mut tss_main_selector = gdt::SegmentSelector(0); TSS.ss0 = gdt::SegmentSelector::new(GDT_KERNEL_CODE, PrivilegeLevel::Ring0).0;
asm!("mov %ebp, $0" : "=r" (TSS.esp0));
let gdt = GDT.call_once(|| { // the following order is important
let mut gdt = gdt::Gdt::new(); let kcode_selector = GDT.add_entry(gdt::Descriptor::kernel_code_segment());
code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment()); let kdata_selector = GDT.add_entry(gdt::Descriptor::kernel_data_segment());
tss_main_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss_main)); let tss_selector = GDT.add_entry(gdt::Descriptor::tss_segment(&TSS));
gdt //I read that the tss should be twice as long
}); //fuck knows why...
//also this doesnt work if the tss is after 3rd spot
//once again: fuck knows why...
GDT.add_entry(gdt::Descriptor(0));
let ucode_selector = GDT.add_entry(gdt::Descriptor::user_code_segment());
let udata_selector = GDT.add_entry(gdt::Descriptor::user_data_segment());
println!("gdt[0]={:#?}", gdt::Descriptor(gdt.table[0])); GDT.load();
println!("gdt[1]={:#?}", gdt::Descriptor(gdt.table[1])); set_cs(kcode_selector);
println!("gdt[2]={:#?}", gdt::Descriptor(gdt.table[2])); load_ds(kdata_selector);
println!("gdt[3]={:#?}", gdt::Descriptor(gdt.table[3])); load_es(kdata_selector);
println!("gdt[4]={:#?}", gdt::Descriptor(gdt.table[4])); load_ss(kdata_selector);
flush!(); load_tss(tss_selector);
gdt.load();
unsafe {
// reload code segment register
// println!("set_cs({:#x})", code_selector.0);
set_cs(code_selector);
// load TSS
// println!("loading tss {:?}", tss_main_selector);
load_tss(tss_main_selector);
}
} }

View file

@ -4,7 +4,7 @@ macro_rules! exception {
($name:ident, $func:block) => { ($name:ident, $func:block) => {
pub extern "x86-interrupt" fn $name(stack_frame: &mut ExceptionStackFrame) pub extern "x86-interrupt" fn $name(stack_frame: &mut ExceptionStackFrame)
{ {
println!("Exception: {}", stringify!($name)); println!("#{}", stringify!($name));
println!("{:#?}", stack_frame); println!("{:#?}", stack_frame);
flush!(); flush!();
@ -20,9 +20,9 @@ macro_rules! exception {
macro_rules! exception_err { macro_rules! exception_err {
($name:ident, $func:block) => { ($name:ident, $func:block) => {
pub extern "x86-interrupt" fn $name( pub extern "x86-interrupt" fn $name(
stack_frame: &mut ExceptionStackFrame, _error_code: u32) stack_frame: &mut ExceptionStackFrame, error_code: u32)
{ {
println!("Exception: {}", stringify!($name)); println!("#{}({})", stringify!($name), error_code);
println!("{:#?}", stack_frame); println!("{:#?}", stack_frame);
flush!(); flush!();

View file

@ -4,7 +4,7 @@ extern crate x86;
pub mod paging; pub mod paging;
pub mod interrupt; pub mod interrupt;
pub mod device; pub mod device;
pub mod pti; pub mod consts;
pub mod gdt; pub mod gdt;
pub mod idt; pub mod idt;
@ -40,7 +40,7 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) {
idt::init(); idt::init();
// fill and load gdt // fill and load gdt
gdt::init(&mut active_table); gdt::init();
// set up heap // set up heap
::allocator::init(&mut active_table); ::allocator::init(&mut active_table);
@ -51,3 +51,37 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) {
// primary CPU entry point // primary CPU entry point
::kmain(); ::kmain();
} }
pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! {
asm!("push r10
push r11
push r12
push r13
push r14
push r15
"
: //no output
: "{r10}"(gdt::GDT_USER_DATA << 3 | 3),
"{r11}"(sp),
"{r12}"(1 << 9) // interrupt enable flag
"{r13}"(gdt::GDT_USER_CODE << 3 | 3),
"{r14}"(ip),
"{r15}"(arg)
: //no clobbers
: "intel", "volatile"
);
asm!("mov ds, r14d
mov es, r14d
mov fs, r15d
mov gs, r14d
fninit
iret"
: //no output (never returns)
: "{r14}"(gdt::GDT_USER_DATA << 3 | 3),
"{r15}"(gdt::GDT_USER_CODE << 3 | 3)
: //no clobbers (never returns)
: "intel", "volatile"
);
unreachable!();
}

View file

@ -4,10 +4,11 @@ extern x86_rust_start
section .text section .text
bits 32 bits 32
x86_start: x86_start:
mov ax, 0x10 ; 16 bytes (0x10) is where the offset for data section (gdt_ds) mov ax, 0x10 ; 16 bytes (0x10) is where the offset for data section (gdt_ds)
mov ds, ax mov ds, ax
mov ss, ax mov ss, ax
mov es, ax mov es, ax
mov ax, 0x0 ; fuck fs & gs, fuck them.
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax

View file

@ -186,9 +186,25 @@ pub fn acpi_info() -> Result<(), &'static str> {
/// Dump control registers /// Dump control registers
pub fn regs() -> Result<(), &'static str> { pub fn regs() -> Result<(), &'static str> {
use x86::registers::control::*; use x86::registers::control::*;
use x86::instructions::tables::tr;
use x86::instructions::segmentation::*;
use x86::structures::gdt;
println!("cr0 = {:?}", Cr0::read()); println!("cr0 = {:?}", Cr0::read());
println!("cr3 = {:?}", Cr3::read()); println!("cr3 = {:?}", Cr3::read());
println!("cr4 = {:?}", Cr4::read()); println!("cr4 = {:?}", Cr4::read());
println!("tr = {:?}", tr());
println!("ss = {:?}", ss());
println!("cs = {:?}", cs());
println!("ds = {:?}", ds());
println!("es = {:?}", es());
println!("fs = {:?}", fs());
println!("gs = {:?}", gs());
unsafe {
println!(
"tss = {:#?}",
gdt::Descriptor(::arch::x86::gdt::GDT.table[tr().index() as usize])
);
}
flush!(); flush!();
Ok(()) Ok(())
} }

View file

@ -43,6 +43,7 @@ pub mod allocator;
pub mod memory; pub mod memory;
/// arch specific entry points /// arch specific entry points
pub mod arch; pub mod arch;
pub use arch::x86::consts::*;
// use core::mem; // use core::mem;
// use x86::structures::idt::*; // use x86::structures::idt::*;
@ -83,8 +84,5 @@ pub extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line:
loop {} loop {}
} }
pub const HEAP_START: usize = (1 << 22 + 2); //third entry of p2
pub const HEAP_SIZE: usize = 10 * 4096 * 8; //~ 100 KiB
#[global_allocator] #[global_allocator]
static HEAP_ALLOCATOR: allocator::Allocator = allocator::Allocator; static HEAP_ALLOCATOR: allocator::Allocator = allocator::Allocator;

View file

@ -53,7 +53,7 @@ pub fn init(boot_info: &multiboot2::BootInformation) {
let frame_allocator = RecycleAllocator::new(bump_allocator); let frame_allocator = RecycleAllocator::new(bump_allocator);
let heap_end_page = let heap_end_page =
Page::containing_address(VirtAddr::new(::HEAP_START as u32 + ::HEAP_SIZE as u32 - 1)); Page::containing_address(VirtAddr::new(::KERNEL_HEAP_OFFSET + ::KERNEL_HEAP_SIZE - 1));
let stack_allocator = { let stack_allocator = {
let stack_alloc_start = heap_end_page + 1; let stack_alloc_start = heap_end_page + 1;

View file

@ -199,24 +199,24 @@ impl fmt::Write for Writer {
} }
pub fn init() { pub fn init() {
set_color!(Yellow, Red); // set_color!(Yellow, Red);
print!( // print!(
"{}{}{}{}{}{}{}{}{}{}{}{}{}{}", // "{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
format_args!("{: ^80}", r#" ,--, "#), // format_args!("{: ^80}", r#" ,--, "#),
format_args!("{: ^80}", r#" ,--.'| ,----, "#), // format_args!("{: ^80}", r#" ,--.'| ,----, "#),
format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), // format_args!("{: ^80}", r#" ,--, | : .' .' \ "#),
format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), // format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#),
format_args!("{: ^80}", r#"; : | | ; | : . ; "#), // format_args!("{: ^80}", r#"; : | | ; | : . ; "#),
format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), // format_args!("{: ^80}", r#"| | : _' | ; |.' / "#),
format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), // format_args!("{: ^80}", r#": : |.' | `----'/ ; "#),
format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), // format_args!("{: ^80}", r#"| ' ' ; : / ; / "#),
format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), // format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#),
format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), // format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#),
format_args!("{: ^80}", r#" ' ; |./__; : "#), // format_args!("{: ^80}", r#" ' ; |./__; : "#),
format_args!("{: ^80}", r#" | : ;| : .' "#), // format_args!("{: ^80}", r#" | : ;| : .' "#),
format_args!("{: ^80}", r#" ' ,/ ; | .' "#), // format_args!("{: ^80}", r#" ' ,/ ; | .' "#),
format_args!("{: ^80}", r#" '--' `---' "#) // format_args!("{: ^80}", r#" '--' `---' "#)
); // );
unsafe { unsafe {
VGA.prompt(); VGA.prompt();
} }

@ -1 +1 @@
Subproject commit 830c0b770873e8f96b0fbdab484579e15cfd8b73 Subproject commit 73a83239073de4acb5b18bacad049553a086ce3f