Get the APs into rust code, set stack and page table in trampoline

This commit is contained in:
Jeremy Soller 2016-08-16 21:25:48 -06:00
parent a8948fb246
commit 27d5996abf
5 changed files with 82 additions and 42 deletions

View file

@ -12,7 +12,7 @@ bochs: build/harddrive.bin
qemu: build/harddrive.bin qemu: build/harddrive.bin
qemu-system-$(ARCH) -enable-kvm -cpu host -smp 4 -machine q35 \ qemu-system-$(ARCH) -enable-kvm -cpu host -smp 4 -machine q35 \
-serial mon:stdio -drive file=$<,format=raw,index=0,media=disk \ -serial mon:stdio -drive file=$<,format=raw,index=0,media=disk \
-nographic -d guest_errors -nographic -d guest_errors,int,pcall
#-device intel-iommu #-device intel-iommu
FORCE: FORCE:

View file

@ -2,9 +2,12 @@
//! Code to parse the ACPI tables //! Code to parse the ACPI tables
use core::intrinsics::{atomic_load, atomic_store}; use core::intrinsics::{atomic_load, atomic_store};
use x86::controlregs;
use allocator::{HEAP_START, HEAP_SIZE};
use memory::{Frame, FrameAllocator}; use memory::{Frame, FrameAllocator};
use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress}; use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress};
use start::kstart_ap;
use self::local_apic::{LocalApic, LocalApicIcr}; use self::local_apic::{LocalApic, LocalApicIcr};
use self::madt::{Madt, MadtEntry}; use self::madt::{Madt, MadtEntry};
@ -21,7 +24,9 @@ pub mod xsdt;
const TRAMPOLINE: usize = 0x7E00; const TRAMPOLINE: usize = 0x7E00;
const AP_STARTUP: usize = 0x8000; const AP_STARTUP: usize = 0x8000;
pub fn init_sdt(sdt: &'static Sdt) { pub fn init_sdt<A>(sdt: &'static Sdt, allocator: &mut A, active_table: &mut ActivePageTable)
where A: FrameAllocator
{
print!(" "); print!(" ");
for &c in sdt.signature.iter() { for &c in sdt.signature.iter() {
print!("{}", c as char); print!("{}", c as char);
@ -42,11 +47,37 @@ pub fn init_sdt(sdt: &'static Sdt) {
println!(" This is my local APIC"); println!(" This is my local APIC");
} else { } else {
if asp_local_apic.flags & 1 == 1 { 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_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 // Set the ap_ready to 0, volatile
unsafe { atomic_store(ap_ready, 0) }; 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 // Send INIT IPI
{ {
@ -99,18 +130,11 @@ pub unsafe fn init<A>(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 // Search for RSDP
if let Some(rsdp) = RSDP::search(start_addr, end_addr) { if let Some(rsdp) = RSDP::search(start_addr, end_addr) {
println!("{:?}", rsdp); 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() { if active_table.translate_page(Page::containing_address(VirtualAddress::new(sdt_address))).is_none() {
let sdt_frame = Frame::containing_address(PhysicalAddress::new(sdt_address)); let sdt_frame = Frame::containing_address(PhysicalAddress::new(sdt_address));
active_table.identity_map(sdt_frame, entry::PRESENT | entry::NO_EXECUTE, allocator); active_table.identity_map(sdt_frame, entry::PRESENT | entry::NO_EXECUTE, allocator);
@ -118,7 +142,7 @@ pub unsafe fn init<A>(allocator: &mut A, active_table: &mut ActivePageTable) ->
&*(sdt_address as *const Sdt) &*(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() { for &c in rxsdt.signature.iter() {
print!("{}", c as char); print!("{}", c as char);
@ -126,11 +150,13 @@ pub unsafe fn init<A>(allocator: &mut A, active_table: &mut ActivePageTable) ->
println!(":"); println!(":");
if let Some(rsdt) = Rsdt::new(rxsdt) { if let Some(rsdt) = Rsdt::new(rxsdt) {
for sdt_address in rsdt.iter() { 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) { } else if let Some(xsdt) = Xsdt::new(rxsdt) {
for sdt_address in xsdt.iter() { 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 { } else {
println!("UNKNOWN RSDT OR XSDT SIGNATURE"); println!("UNKNOWN RSDT OR XSDT SIGNATURE");

View file

@ -9,7 +9,7 @@ use externs::memset;
use gdt; use gdt;
use idt; use idt;
use memory; use memory;
use paging::{self, Page, VirtualAddress}; use paging::{self, entry, Page, VirtualAddress};
/// Test of zero values in BSS. /// Test of zero values in BSS.
static BSS_TEST_ZERO: usize = 0; static BSS_TEST_ZERO: usize = 0;
@ -21,6 +21,7 @@ extern {
fn kmain() -> !; fn kmain() -> !;
} }
/// The entry to Rust, all things must be initialized
#[no_mangle] #[no_mangle]
pub unsafe extern fn kstart() -> ! { 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)); 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) { 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 // Read ACPI tables
@ -78,3 +79,10 @@ pub unsafe extern fn kstart() -> ! {
asm!("xchg bx, bx" : : : : "intel", "volatile"); asm!("xchg bx, bx" : : : : "intel", "volatile");
kmain(); kmain();
} }
/// Entry to rust for an AP
pub unsafe extern fn kstart_ap() -> ! {
loop {
asm!("hlt");
}
}

View file

@ -65,31 +65,31 @@ load:
mov [DAPACK.count], cx mov [DAPACK.count], cx
mov [DAPACK.seg], dx mov [DAPACK.seg], dx
mov si, loading ; mov si, loading
call print ; call print
mov bx, [DAPACK.addr] ; mov bx, [DAPACK.addr]
call print_num ; call print_num
mov al, '#' ; mov al, '#'
call print_char ; call print_char
;
mov bx, [DAPACK.count] ; mov bx, [DAPACK.count]
call print_num ; call print_num
;
mov al, ' ' ; mov al, ' '
call print_char ; call print_char
;
mov bx, [DAPACK.seg] ; mov bx, [DAPACK.seg]
call print_num ; call print_num
;
mov al, ':' ; mov al, ':'
call print_char ; call print_char
;
mov bx, [DAPACK.buf] ; mov bx, [DAPACK.buf]
call print_num ; call print_num
;
call print_line ; call print_line
mov dl, [disk] mov dl, [disk]
mov si, DAPACK mov si, DAPACK

View file

@ -1,6 +1,8 @@
trampoline: trampoline:
.ready: dq 0 .ready: dq 0
.page_table: dq 0
.stack: dq 0 .stack: dq 0
.code: dq 0
times 512 - ($ - trampoline) db 0 times 512 - ($ - trampoline) db 0
@ -126,10 +128,14 @@ long_mode_ap:
mov gs, rax mov gs, rax
mov ss, rax mov ss, rax
mov rax, [trampoline.page_table]
mov cr3, rax
mov rsp, [trampoline.stack]
mov qword [trampoline.ready], 1 mov qword [trampoline.ready], 1
.lp: mov rax, [trampoline.code]
hlt jmp rax
jmp .lp
gdtr: gdtr:
dw gdt.end + 1 ; size dw gdt.end + 1 ; size