From 27d5996abf3950871ea79aba377b90ffd9dfda11 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 16 Aug 2016 21:25:48 -0600 Subject: [PATCH] Get the APs into rust code, set stack and page table in trampoline --- Makefile | 2 +- arch/x86_64/src/acpi/mod.rs | 52 +++++++++++++++++++++++-------- arch/x86_64/src/start.rs | 12 +++++-- bootloader/x86/bootsector.asm | 46 +++++++++++++-------------- bootloader/x86/startup-x86_64.asm | 12 +++++-- 5 files changed, 82 insertions(+), 42 deletions(-) diff --git a/Makefile b/Makefile index ebd42bc..77bfb57 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ bochs: build/harddrive.bin qemu: build/harddrive.bin qemu-system-$(ARCH) -enable-kvm -cpu host -smp 4 -machine q35 \ -serial mon:stdio -drive file=$<,format=raw,index=0,media=disk \ - -nographic -d guest_errors + -nographic -d guest_errors,int,pcall #-device intel-iommu FORCE: diff --git a/arch/x86_64/src/acpi/mod.rs b/arch/x86_64/src/acpi/mod.rs index eec67cf..81c7b4e 100644 --- a/arch/x86_64/src/acpi/mod.rs +++ b/arch/x86_64/src/acpi/mod.rs @@ -2,9 +2,12 @@ //! Code to parse the ACPI tables use core::intrinsics::{atomic_load, atomic_store}; +use x86::controlregs; +use allocator::{HEAP_START, HEAP_SIZE}; use memory::{Frame, FrameAllocator}; use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress}; +use start::kstart_ap; use self::local_apic::{LocalApic, LocalApicIcr}; use self::madt::{Madt, MadtEntry}; @@ -21,7 +24,9 @@ pub mod xsdt; const TRAMPOLINE: usize = 0x7E00; const AP_STARTUP: usize = 0x8000; -pub fn init_sdt(sdt: &'static Sdt) { +pub fn init_sdt(sdt: &'static Sdt, allocator: &mut A, active_table: &mut ActivePageTable) + where A: FrameAllocator +{ print!(" "); for &c in sdt.signature.iter() { print!("{}", c as char); @@ -42,11 +47,37 @@ pub fn init_sdt(sdt: &'static Sdt) { println!(" This is my local APIC"); } else { if asp_local_apic.flags & 1 == 1 { + // Map trampoline + { + if active_table.translate_page(Page::containing_address(VirtualAddress::new(TRAMPOLINE))).is_none() { + active_table.identity_map(Frame::containing_address(PhysicalAddress::new(TRAMPOLINE)), entry::PRESENT | entry::WRITABLE, allocator); + } + } + + // Map a stack + /* + let stack_start = HEAP_START + HEAP_SIZE + 4096 + (asp_local_apic.id as usize * (1024 * 1024 + 4096)); + let stack_end = stack_start + 1024 * 1024; + { + let start_page = Page::containing_address(VirtualAddress::new(stack_start)); + let end_page = Page::containing_address(VirtualAddress::new(stack_end - 1)); + + for page in Page::range_inclusive(start_page, end_page) { + active_table.map(page, entry::WRITABLE | entry::NO_EXECUTE, allocator); + } + } + */ + let ap_ready = TRAMPOLINE as *mut u64; - let ap_stack = unsafe { ap_ready.offset(1) }; + let ap_page_table = unsafe { ap_ready.offset(1) }; + let ap_stack = unsafe { ap_page_table.offset(1) }; + let ap_code = unsafe { ap_stack.offset(1) }; // Set the ap_ready to 0, volatile unsafe { atomic_store(ap_ready, 0) }; + unsafe { atomic_store(ap_page_table, 0x70000) }; + unsafe { atomic_store(ap_stack, 0x7C00) }; + unsafe { atomic_store(ap_code, kstart_ap as u64) }; // Send INIT IPI { @@ -99,18 +130,11 @@ pub unsafe fn init(allocator: &mut A, active_table: &mut ActivePageTable) -> } } - // Map trampoline - { - if active_table.translate_page(Page::containing_address(VirtualAddress::new(TRAMPOLINE))).is_none() { - active_table.identity_map(Frame::containing_address(PhysicalAddress::new(TRAMPOLINE)), entry::PRESENT | entry::WRITABLE, allocator); - } - } - // Search for RSDP if let Some(rsdp) = RSDP::search(start_addr, end_addr) { println!("{:?}", rsdp); - let mut get_sdt = |sdt_address: usize| -> &'static Sdt { + let get_sdt = |sdt_address: usize, allocator: &mut A, active_table: &mut ActivePageTable| -> &'static Sdt { if active_table.translate_page(Page::containing_address(VirtualAddress::new(sdt_address))).is_none() { let sdt_frame = Frame::containing_address(PhysicalAddress::new(sdt_address)); active_table.identity_map(sdt_frame, entry::PRESENT | entry::NO_EXECUTE, allocator); @@ -118,7 +142,7 @@ pub unsafe fn init(allocator: &mut A, active_table: &mut ActivePageTable) -> &*(sdt_address as *const Sdt) }; - let rxsdt = get_sdt(rsdp.sdt_address()); + let rxsdt = get_sdt(rsdp.sdt_address(), allocator, active_table); for &c in rxsdt.signature.iter() { print!("{}", c as char); @@ -126,11 +150,13 @@ pub unsafe fn init(allocator: &mut A, active_table: &mut ActivePageTable) -> println!(":"); if let Some(rsdt) = Rsdt::new(rxsdt) { for sdt_address in rsdt.iter() { - init_sdt(get_sdt(sdt_address)); + let sdt = get_sdt(sdt_address, allocator, active_table); + init_sdt(sdt, allocator, active_table); } } else if let Some(xsdt) = Xsdt::new(rxsdt) { for sdt_address in xsdt.iter() { - init_sdt(get_sdt(sdt_address)); + let sdt = get_sdt(sdt_address, allocator, active_table); + init_sdt(sdt, allocator, active_table); } } else { println!("UNKNOWN RSDT OR XSDT SIGNATURE"); diff --git a/arch/x86_64/src/start.rs b/arch/x86_64/src/start.rs index d9221dd..04eb62e 100644 --- a/arch/x86_64/src/start.rs +++ b/arch/x86_64/src/start.rs @@ -9,7 +9,7 @@ use externs::memset; use gdt; use idt; use memory; -use paging::{self, Page, VirtualAddress}; +use paging::{self, entry, Page, VirtualAddress}; /// Test of zero values in BSS. static BSS_TEST_ZERO: usize = 0; @@ -21,6 +21,7 @@ extern { fn kmain() -> !; } +/// The entry to Rust, all things must be initialized #[no_mangle] pub unsafe extern fn kstart() -> ! { { @@ -62,7 +63,7 @@ pub unsafe extern fn kstart() -> ! { let heap_end_page = Page::containing_address(VirtualAddress::new(HEAP_START + HEAP_SIZE-1)); for page in Page::range_inclusive(heap_start_page, heap_end_page) { - active_table.map(page, paging::entry::WRITABLE, &mut allocator); + active_table.map(page, entry::WRITABLE | entry::NO_EXECUTE, &mut allocator); } // Read ACPI tables @@ -78,3 +79,10 @@ pub unsafe extern fn kstart() -> ! { asm!("xchg bx, bx" : : : : "intel", "volatile"); kmain(); } + +/// Entry to rust for an AP +pub unsafe extern fn kstart_ap() -> ! { + loop { + asm!("hlt"); + } +} diff --git a/bootloader/x86/bootsector.asm b/bootloader/x86/bootsector.asm index cbf466f..bc50c22 100644 --- a/bootloader/x86/bootsector.asm +++ b/bootloader/x86/bootsector.asm @@ -65,31 +65,31 @@ load: mov [DAPACK.count], cx mov [DAPACK.seg], dx - mov si, loading - call print + ; mov si, loading + ; call print - mov bx, [DAPACK.addr] - call print_num + ; mov bx, [DAPACK.addr] + ; call print_num - mov al, '#' - call print_char - - mov bx, [DAPACK.count] - call print_num - - mov al, ' ' - call print_char - - mov bx, [DAPACK.seg] - call print_num - - mov al, ':' - call print_char - - mov bx, [DAPACK.buf] - call print_num - - call print_line + ; mov al, '#' + ; call print_char + ; + ; mov bx, [DAPACK.count] + ; call print_num + ; + ; mov al, ' ' + ; call print_char + ; + ; mov bx, [DAPACK.seg] + ; call print_num + ; + ; mov al, ':' + ; call print_char + ; + ; mov bx, [DAPACK.buf] + ; call print_num + ; + ; call print_line mov dl, [disk] mov si, DAPACK diff --git a/bootloader/x86/startup-x86_64.asm b/bootloader/x86/startup-x86_64.asm index 8ac8d89..8d27857 100644 --- a/bootloader/x86/startup-x86_64.asm +++ b/bootloader/x86/startup-x86_64.asm @@ -1,6 +1,8 @@ trampoline: .ready: dq 0 + .page_table: dq 0 .stack: dq 0 + .code: dq 0 times 512 - ($ - trampoline) db 0 @@ -126,10 +128,14 @@ long_mode_ap: mov gs, rax mov ss, rax + mov rax, [trampoline.page_table] + mov cr3, rax + + mov rsp, [trampoline.stack] + mov qword [trampoline.ready], 1 -.lp: - hlt - jmp .lp + mov rax, [trampoline.code] + jmp rax gdtr: dw gdt.end + 1 ; size