diff --git a/src/arch/x86_64/boot/boot.asm b/src/arch/x86_64/boot/boot.asm index 40cd6e0..ebd1d5c 100644 --- a/src/arch/x86_64/boot/boot.asm +++ b/src/arch/x86_64/boot/boot.asm @@ -1,4 +1,5 @@ global start +global stack_bottom extern long_mode_start section .text @@ -158,7 +159,7 @@ p3_table: p2_table: resb 4096 stack_bottom: - resb 4096 * 4 + resb 4096 * 8 stack_top: section .rodata diff --git a/src/arch/x86_64/boot/entryother.asm b/src/arch/x86_64/boot/entryother.asm index 157bf73..9b8733b 100644 --- a/src/arch/x86_64/boot/entryother.asm +++ b/src/arch/x86_64/boot/entryother.asm @@ -27,67 +27,113 @@ %define STA_R 0x2 ; Readable (executable segments) %define STA_A 0x1 ; Accessed +extern other_main + section .text bits 16 start: - cli + cli - xor ax, ax - mov ds, ax - mov es, ax - mov ss, ax + xor ax, ax + mov ds, ax + mov es, ax + mov ss, ax - lgdt [gdt.desc] - mov eax, cr0 - or eax, CR0_PE - mov cr0, eax + lgdt [gdt.desc] + mov eax, cr0 + or eax, CR0_PE + mov cr0, eax -;PAGEBREAK! - jmp gdt.kcode: start32 + jmp gdt.code: start32 bits 32 start32: - mov ax, gdt.kdata - mov ds, ax - mov es, ax - mov ss, ax - mov ax, 0 - mov fs, ax - mov gs, ax - - ; debug - mov dword [0xb8000], 0x2f4b2f4f - hlt - - ; defer paging until we switch to 64bit mode - ; set ebx=1 so shared boot code knows we're booting a secondary core - mov ebx, 1 - - ; Switch to the stack allocated by startothers() - mov esp, [start-4] - ; Call mpenter() - call [start-8] - - mov ax, 0x8a00 - mov dx, ax - out dx, ax - mov ax, 0x8ae0 - out dx, ax + mov ax, gdt.data + mov ds, ax + mov es, ax + mov ss, ax + mov ax, 0 + mov fs, ax + mov gs, ax + + ; Switch to the stack allocated by startothers() + mov esp, [start-4] + + call enable_paging + + ; load the 64-bit GDT + lgdt [gdt64.pointer] + + jmp gdt64.code: start64 + +error: + mov ax, 0x8a00 + mov dx, ax + out dx, ax + mov ax, 0x8ae0 + out dx, ax spin: - jmp spin + jmp spin + +enable_paging: + ; load P4 to cr3 register (cpu uses this to access the P4 table) + mov eax, [start-8] + mov cr3, eax + + ; enable PAE-flag in cr4 (Physical Address Extension) + mov eax, cr4 + or eax, 1 << 5 + mov cr4, eax + + ; set the long mode bit in the EFER MSR (model specific register) + mov ecx, 0xC0000080 + rdmsr + or eax, 1 << 8 + wrmsr + + ; enable paging in the cr0 register + mov eax, cr0 + or eax, 1 << 31 + mov cr0, eax + + ret + +bits 64 +start64: + ; load 0 into all data segment registers + mov ax, 0 + mov ss, ax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + ; obtain kstack from data block before entryother + mov rsp, [0x7000 - 16] + + mov rax, other_main + call rax ; section .rodata align 4 gdt: - ; NULL - dw 0, 0 - db 0, 0, 0, 0 -.kcode: equ $ - gdt - dw 0xffff, 0 - db 0, (0x90 | STA_X | STA_R), 0xcf, 0 -.kdata: equ $ - gdt - dw 0xffff, 0 - db 0, (0x90 | STA_W), 0xcf, 0 + ; NULL + dw 0, 0 + db 0, 0, 0, 0 +.code: equ $ - gdt + dw 0xffff, 0 + db 0, (0x90 | STA_X | STA_R), 0xcf, 0 +.data: equ $ - gdt + dw 0xffff, 0 + db 0, (0x90 | STA_W), 0xcf, 0 .desc: - dw ($ - gdt - 1) - dq gdt \ No newline at end of file + dw $ - gdt - 1 + dq gdt + +gdt64: + dq 0 ; zero entry +.code: equ $ - gdt64 ; new + dq (1<<43) | (1<<44) | (1<<47) | (1<<53) ; code segment +.pointer: + dw $ - gdt64 - 1 + dq gdt64 \ No newline at end of file diff --git a/src/arch/x86_64/paging/mod.rs b/src/arch/x86_64/paging/mod.rs index 535815b..f913067 100644 --- a/src/arch/x86_64/paging/mod.rs +++ b/src/arch/x86_64/paging/mod.rs @@ -151,8 +151,6 @@ impl ActivePageTable { } pub struct InactivePageTable { - // WARNING: Don't change the struct. - // memory mod use the private p4_frame. p4_frame: Frame, } diff --git a/src/arch/x86_64/smp.rs b/src/arch/x86_64/smp.rs index 2996bda..c16d9ca 100644 --- a/src/arch/x86_64/smp.rs +++ b/src/arch/x86_64/smp.rs @@ -14,12 +14,14 @@ pub fn start_other_cores(acpi: &ACPI_Result, mc: &mut MemoryController) { mc.map_page_identity(entryother_start as usize); mc.map_page_p2v(PhysicalAddress(0)); copy_entryother(); + let args = unsafe{ &mut *(ENTRYOTHER_ADDR as *mut EntryArgs).offset(-1) }; + let page_table = unsafe{ *(0xFFFF_FFFF_FFFF_FFF8 as *const u32) } & 0xFFFF_F000; for i in 1 .. acpi.cpu_num { let apic_id = acpi.cpu_acpi_ids[i as usize]; *args = EntryArgs { kstack: mc.alloc_stack(1).unwrap().top() as u64, - next_code: 0, + page_table: page_table, stack: 0x8000, // just enough stack to get us to entry64mp }; start_ap(apic_id, ENTRYOTHER_ADDR); @@ -28,10 +30,6 @@ pub fn start_other_cores(acpi: &ACPI_Result, mc: &mut MemoryController) { } -fn hello_world() { - println!("Hello world!"); -} - fn copy_entryother() { use rlibc::memmove; let entryother_start = entryother_start as usize; @@ -44,6 +42,6 @@ fn copy_entryother() { #[repr(C)] struct EntryArgs { kstack: u64, - next_code: u32, + page_table: u32, stack: u32, } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index b1e18ab..d94ed31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,6 +80,15 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) { test_end!(); } +#[no_mangle] +pub extern "C" fn other_main() { + // print OK + unsafe{ *(0xb8000 as *mut u32) = 0x2f4b2f4f; } + loop {} + // FIXME: Page Fault + println!("Hello world! from AP!"); +} + use linked_list_allocator::LockedHeap; #[global_allocator] diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 517ec9d..d039ddb 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -132,15 +132,12 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) let old_table = active_table.switch(new_table); println!("NEW TABLE!!!"); - // turn the old p4 page into a guard page - let old_table_p4_frame = unsafe { - &*(&old_table as *const InactivePageTable as *const Frame) - }; - let old_p4_page = Page::containing_address( - old_table_p4_frame.start_address().to_kernel_virtual() - ); - active_table.unmap(old_p4_page, allocator); - println!("guard page at {:#x}", old_p4_page.start_address()); + // turn the stack bottom into a guard page + extern { fn stack_bottom(); } + let stack_bottom = PhysicalAddress(stack_bottom as u64).to_kernel_virtual(); + let stack_bottom_page = Page::containing_address(stack_bottom); + active_table.unmap(stack_bottom_page, allocator); + println!("guard page at {:#x}", stack_bottom_page.start_address()); active_table }