Map kernel in AP, WIP

This commit is contained in:
Jeremy Soller 2016-08-17 15:47:54 -06:00
parent 27d5996abf
commit ebf9766ef5
10 changed files with 89 additions and 50 deletions

View file

@ -10,7 +10,7 @@ bochs: build/harddrive.bin
bochs -f bochs.$(ARCH)
qemu: build/harddrive.bin
qemu-system-$(ARCH) -enable-kvm -cpu host -smp 4 -machine q35 \
qemu-system-$(ARCH) -enable-kvm -cpu host -smp 2 -machine q35 \
-serial mon:stdio -drive file=$<,format=raw,index=0,media=disk \
-nographic -d guest_errors,int,pcall
#-device intel-iommu
@ -35,7 +35,7 @@ build/libcollections.rlib: rust/src/libcollections/lib.rs build/libcore.rlib bui
build/libkernel.a: build/libcore.rlib build/liballoc.rlib build/libcollections.rlib FORCE
mkdir -p build
RUSTC="./rustc.sh" cargo rustc --verbose --target $(ARCH)-unknown-none.json -- -C soft-float -o $@
RUSTC="./rustc.sh" cargo rustc --target $(ARCH)-unknown-none.json -- -C soft-float -o $@
build/kernel.bin: build/libkernel.a
ld -m elf_$(ARCH) --gc-sections -z max-page-size=0x1000 -T bootloader/x86/kernel.ld -o $@ $<

View file

@ -69,14 +69,14 @@ pub fn init_sdt<A>(sdt: &'static Sdt, allocator: &mut A, active_table: &mut Acti
*/
let ap_ready = TRAMPOLINE as *mut u64;
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) };
let ap_stack_start = unsafe { ap_ready.offset(1) };
let ap_stack_end = unsafe { ap_ready.offset(2) };
let ap_code = unsafe { ap_ready.offset(3) };
// 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_stack_start, 0x1000) };
unsafe { atomic_store(ap_stack_end, 0x7000) };
unsafe { atomic_store(ap_code, kstart_ap as u64) };
// Send INIT IPI

View file

@ -31,6 +31,11 @@ pub unsafe fn init() {
GDT[GDT_USER_DATA].set_flags(GDT_LONG_MODE);
GDTR.set_slice(&GDT);
init_ap();
}
pub unsafe fn init_ap() {
GDTR.load();
}

View file

@ -21,12 +21,16 @@ pub unsafe fn init() {
entry.set_offset(8, blank as usize);
}
IDTR.set_slice(&IDT);
init_ap();
}
pub unsafe fn init_ap() {
IDTR.load();
}
interrupt!(blank, {
asm!("xchg bx, bx" : : : : "intel", "volatile");
println!("INTERRUPT");
});
interrupt!(exception, {

View file

@ -44,8 +44,6 @@ macro_rules! interrupt {
$func
}
asm!("xchg bx, bx" : : : : "intel", "volatile");
// Push scratch registers
asm!("push rax
push rcx
@ -87,8 +85,6 @@ macro_rules! interrupt_error {
$func
}
asm!("xchg bx, bx" : : : : "intel", "volatile");
// Push scratch registers, grab stack pointer
asm!("push rax
push rcx
@ -159,4 +155,3 @@ pub mod start;
pub mod tss;
pub static ALLOCATOR: Mutex<Option<memory::AreaFrameAllocator>> = Mutex::new(None);
pub static PAGE_TABLE: Mutex<Option<paging::ActivePageTable>> = Mutex::new(None);

View file

@ -76,6 +76,6 @@ impl FrameAllocator for AreaFrameAllocator {
}
fn deallocate_frame(&mut self, frame: Frame) {
unimplemented!()
println!("Leak frame: {:?}", frame);
}
}

View file

@ -21,7 +21,7 @@ pub const ENTRY_COUNT: usize = 512;
pub const PAGE_SIZE: usize = 4096;
/// Initialize paging
pub unsafe fn init<A>(allocator: &mut A) -> ActivePageTable where A: FrameAllocator {
pub unsafe fn init<A>(stack_start: usize, stack_end: usize, allocator: &mut A) -> ActivePageTable where A: FrameAllocator {
extern {
/// The starting byte of the text (code) data segment.
static mut __text_start: u8;
@ -43,7 +43,7 @@ pub unsafe fn init<A>(allocator: &mut A) -> ActivePageTable where A: FrameAlloca
let mut active_table = ActivePageTable::new();
let mut temporary_page = TemporaryPage::new(Page { number: 0x80000000 }, allocator);
let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(0x80000000)), allocator);
let mut new_table = {
let frame = allocator.allocate_frame().expect("no more frames");
@ -52,19 +52,15 @@ pub unsafe fn init<A>(allocator: &mut A) -> ActivePageTable where A: FrameAlloca
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let mut remap = |start: usize, end: usize, flags: EntryFlags| {
/* TODO
let start_frame = Frame::containing_address(PhysicalAddress::new(start));
let end_frame = Frame::containing_address(PhysicalAddress::new(end));
for frame in Frame::range_inclusive(start_frame, end_frame) {}
*/
for i in 0..(end - start + PAGE_SIZE - 1)/PAGE_SIZE {
let frame = Frame::containing_address(PhysicalAddress::new(start + i * PAGE_SIZE));
let end_frame = Frame::containing_address(PhysicalAddress::new(end - 1));
for frame in Frame::range_inclusive(start_frame, end_frame) {
mapper.identity_map(frame, flags, allocator);
}
};
// Remap stack writable, no execute
remap(0x00080000, 0x0009F000, PRESENT | WRITABLE | NO_EXECUTE);
remap(stack_start, stack_end, PRESENT | WRITABLE | NO_EXECUTE);
// Remap a section with `flags`
let mut remap_section = |start: &u8, end: &u8, flags: EntryFlags| {

View file

@ -23,6 +23,7 @@ impl TemporaryPage {
/// Maps the temporary page to the given frame in the active table.
/// Returns the start address of the temporary page.
pub fn map(&mut self, frame: Frame, flags: EntryFlags, active_table: &mut ActivePageTable) -> VirtualAddress {
println!("map {:?}", frame);
assert!(active_table.translate_page(self.page).is_none(),
"temporary page is already mapped");
active_table.map_to(self.page, frame, flags, &mut self.allocator);
@ -37,6 +38,7 @@ impl TemporaryPage {
/// Unmaps the temporary page in the active table.
pub fn unmap(&mut self, active_table: &mut ActivePageTable) {
println!("unmap {:?}", self.page);
active_table.unmap(self.page, &mut self.allocator)
}
}
@ -55,6 +57,7 @@ impl FrameAllocator for TinyAllocator {
fn allocate_frame(&mut self) -> Option<Frame> {
for frame_option in &mut self.0 {
if frame_option.is_some() {
println!("Allocate {:?}", frame_option);
return frame_option.take();
}
}
@ -64,10 +67,15 @@ impl FrameAllocator for TinyAllocator {
fn deallocate_frame(&mut self, frame: Frame) {
for frame_option in &mut self.0 {
if frame_option.is_none() {
println!("Deallocate {:?}", frame);
*frame_option = Some(frame);
return;
}
}
panic!("Tiny allocator can hold only 3 frames.");
println!("Cannot dealloc {:?}", frame);
for frame_option in &self.0 {
println!("Already dealloc {:?}", frame_option)
}
//panic!("Tiny allocator can hold only 3 frames. {:?}", frame);
}
}

View file

@ -8,7 +8,7 @@ use allocator::{HEAP_START, HEAP_SIZE};
use externs::memset;
use gdt;
use idt;
use memory;
use memory::{self, FrameAllocator};
use paging::{self, entry, Page, VirtualAddress};
/// Test of zero values in BSS.
@ -53,35 +53,65 @@ pub unsafe extern fn kstart() -> ! {
idt::init();
// Initialize memory management
let mut allocator = memory::init(0, &__bss_end as *const u8 as usize);
*::ALLOCATOR.lock() = Some(memory::init(0, &__bss_end as *const u8 as usize));
if let Some(ref mut allocator) = *::ALLOCATOR.lock() {
// TODO: allocate a stack
let stack_start = 0x00080000;
let stack_end = 0x0009F000;
// Initialize paging
let mut active_table = paging::init(&mut allocator);
let mut active_table = paging::init(stack_start, stack_end, allocator);
// Initialize heap
// Read ACPI tables
acpi::init(allocator, &mut active_table);
// Map heap
let heap_start_page = Page::containing_address(VirtualAddress::new(HEAP_START));
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, entry::WRITABLE | entry::NO_EXECUTE, &mut allocator);
active_table.map(page, entry::WRITABLE | entry::NO_EXECUTE, allocator);
}
}
}
// Read ACPI tables
acpi::init(&mut allocator, &mut active_table);
// Set global allocator
*::ALLOCATOR.lock() = Some(allocator);
// Set global page table
*::PAGE_TABLE.lock() = Some(active_table);
for i in 0..10 {
if let Some(ref mut allocator) = *::ALLOCATOR.lock() {
println!("BP: {:?}", allocator.allocate_frame());
}
}
asm!("xchg bx, bx" : : : : "intel", "volatile");
kmain();
}
/// Entry to rust for an AP
pub unsafe extern fn kstart_ap() -> ! {
pub unsafe extern fn kstart_ap(stack_start: usize, stack_end: usize) -> ! {
// Set up GDT for AP
gdt::init_ap();
// Set up IDT for aP
idt::init_ap();
if let Some(ref mut allocator) = *::ALLOCATOR.lock() {
// Initialize paging
let mut active_table = paging::init(stack_start, stack_end, allocator);
// Map heap
let heap_start_page = Page::containing_address(VirtualAddress::new(HEAP_START));
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, entry::WRITABLE | entry::NO_EXECUTE, allocator);
}
}
for i in 0..10 {
if let Some(ref mut allocator) = *::ALLOCATOR.lock() {
println!("AP: {:?}", allocator.allocate_frame());
}
}
loop {
asm!("hlt");
}

View file

@ -1,7 +1,7 @@
trampoline:
.ready: dq 0
.page_table: dq 0
.stack: dq 0
.stack_start: dq 0
.stack_end: dq 0
.code: dq 0
times 512 - ($ - trampoline) db 0
@ -128,10 +128,11 @@ long_mode_ap:
mov gs, rax
mov ss, rax
mov rax, [trampoline.page_table]
mov cr3, rax
mov rsp, [trampoline.stack]
mov rdi, [trampoline.stack_start]
mov rsi, [trampoline.stack_end]
lea rsp, [rsi - 16]
mov qword [trampoline.ready], 1
mov rax, [trampoline.code]