Fix and simplify SMP

master
WangRunji 7 years ago
parent 2e9ffb84fa
commit 8d6663edb0

@ -57,7 +57,7 @@ start32:
mov gs, ax
; Switch to the stack allocated by startothers()
mov esp, [start-4]
mov esp, [top - 4]
call enable_paging
@ -77,7 +77,7 @@ spin:
enable_paging:
; load P4 to cr3 register (cpu uses this to access the P4 table)
mov eax, [start-8]
mov eax, [top - 8]
mov cr3, eax
; enable PAE-flag in cr4 (Physical Address Extension)
@ -109,7 +109,7 @@ start64:
mov gs, ax
; obtain kstack from data block before entryother
mov rsp, [0x7000 - 16]
mov rsp, [top - 16]
mov rax, other_main
call rax
@ -137,3 +137,5 @@ gdt64:
.pointer:
dw $ - gdt64 - 1
dq gdt64
top: equ start + 0x1000

@ -6,14 +6,29 @@ KERNEL_OFFSET = 0xffffff0000000000;
SECTIONS {
/* ensure that the multiboot header is at the beginning */
.multiboot_header :
{
KEEP(*(.multiboot_header))
}
/* bootloader for other processors */
. = OTHER_OFFSET;
.text.other : AT(OTHER_OFFSET)
{
KEEP(*/entryother.o (.text))
. = ALIGN(4K);
}
/* bootloader for first processor */
. = BOOT_OFFSET;
.rodata.32 :
{
/* ensure that the multiboot header is at the beginning */
KEEP(*(.multiboot_header))
*/boot.o (.rodata)
. = ALIGN(4K);
}
@ -29,18 +44,6 @@ SECTIONS {
. = ALIGN(4K);
}
/* bootloader for other processors */
entryother_start = .; /* backup va */
. = OTHER_OFFSET;
.text.other : AT(entryother_start)
{
KEEP(*/entryother.o (.text))
. = ALIGN(4K);
}
entryother_end = . - OTHER_OFFSET + entryother_start;
. = entryother_end; /* recover va */
/* kernel */
. += KERNEL_OFFSET;

@ -3,28 +3,21 @@ use memory::*;
use core::ptr::{read_volatile, write_volatile};
use x86_64::registers::control_regs::cr3;
extern {
fn entryother_start(); // physical addr of entryother
fn entryother_end();
}
const ENTRYOTHER_ADDR: u32 = 0x7000;
pub fn start_other_cores(acpi: &AcpiResult, ms: &mut MemorySet) {
use consts::KERNEL_OFFSET;
ms.push(MemoryArea::new_identity(ENTRYOTHER_ADDR as usize - 1, ENTRYOTHER_ADDR as usize + 1, MemoryAttr::default(), "entry_other"));
ms.push(MemoryArea::new_identity(entryother_start as usize, entryother_start as usize + 1, MemoryAttr::default(), "entry_other"));
ms.push(MemoryArea::new_kernel(KERNEL_OFFSET, KERNEL_OFFSET + 1, MemoryAttr::default(), "entry_other3"));
copy_entryother();
ms.push(MemoryArea::new_identity(ENTRYOTHER_ADDR as usize, ENTRYOTHER_ADDR as usize + 1, MemoryAttr::default().execute(), "entry_other.text"));
ms.push(MemoryArea::new_kernel(KERNEL_OFFSET, KERNEL_OFFSET + 1, MemoryAttr::default(), "entry_other.ctrl"));
let args = unsafe{ &mut *(ENTRYOTHER_ADDR as *mut EntryArgs).offset(-1) };
let args = unsafe { &mut *(0x8000 as *mut EntryArgs).offset(-1) };
for i in 1 .. acpi.cpu_num {
let apic_id = acpi.cpu_acpi_ids[i as usize];
let ms = MemorySet::new(7);
*args = EntryArgs {
kstack: ms.kstack_top() as u64,
page_table: ms._page_table_addr().0 as u32,
stack: 0x8000, // just enough stack to get us to entry64mp
page_table: cr3().0 as u32,
stack: args as *const _ as u32, // just enough stack to get us to entry64mp
};
unsafe { MS = Some(ms); }
start_ap(apic_id, ENTRYOTHER_ADDR);
@ -32,16 +25,6 @@ pub fn start_other_cores(acpi: &AcpiResult, ms: &mut MemorySet) {
}
}
fn copy_entryother() {
use rlibc::memmove;
let entryother_start = entryother_start as usize;
let entryother_end = entryother_end as usize;
let size = entryother_end - entryother_start;
assert!(size <= 0x1000, "entryother code is too large, not supported.");
unsafe{ memmove(ENTRYOTHER_ADDR as *mut u8, entryother_start as *mut u8, size); }
debug!("smp: copied entryother code to 0x7000");
}
#[repr(C)]
#[derive(Debug)]
struct EntryArgs {

@ -84,8 +84,7 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) -> ! {
kernel_memory.push(MemoryArea::new_identity(addr, addr + count * 0x1000, MemoryAttr::default(), "acpi"))
});
// FIXME: PageFault when SMP
// arch::smp::start_other_cores(&acpi, &mut kernel_memory);
arch::smp::start_other_cores(&acpi, &mut kernel_memory);
process::init(kernel_memory);
fs::load_sfs();
@ -128,8 +127,9 @@ pub extern "C" fn other_main() -> ! {
arch::idt::init();
arch::driver::apic::other_init();
let cpu_id = arch::driver::apic::lapic_id();
println!("Hello world! from CPU {}!", arch::driver::apic::lapic_id());
let ms = unsafe { arch::smp::notify_started(cpu_id) };
ms.switch();
println!("Hello world! from CPU {}!", arch::driver::apic::lapic_id());
// unsafe{ let a = *(0xdeadbeaf as *const u8); } // Page fault
loop {}
}

Loading…
Cancel
Save