i'm just trying to figure out this mess.. fml
This commit is contained in:
parent
d3eb0e5138
commit
0aae87eda3
11 changed files with 144 additions and 74 deletions
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
kernel-rs/src/arch/x86/consts.rs
Normal file
31
kernel-rs/src/arch/x86/consts.rs
Normal 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);
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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!();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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!();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ x86_start:
|
||||||
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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in a new issue