Map kernel in AP, WIP
This commit is contained in:
parent
27d5996abf
commit
ebf9766ef5
4
Makefile
4
Makefile
|
@ -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 $@ $<
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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, {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -76,6 +76,6 @@ impl FrameAllocator for AreaFrameAllocator {
|
|||
}
|
||||
|
||||
fn deallocate_frame(&mut self, frame: Frame) {
|
||||
unimplemented!()
|
||||
println!("Leak frame: {:?}", frame);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Reference in a new issue