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)
|
bochs -f bochs.$(ARCH)
|
||||||
|
|
||||||
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 2 -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,int,pcall
|
-nographic -d guest_errors,int,pcall
|
||||||
#-device intel-iommu
|
#-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
|
build/libkernel.a: build/libcore.rlib build/liballoc.rlib build/libcollections.rlib FORCE
|
||||||
mkdir -p build
|
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
|
build/kernel.bin: build/libkernel.a
|
||||||
ld -m elf_$(ARCH) --gc-sections -z max-page-size=0x1000 -T bootloader/x86/kernel.ld -o $@ $<
|
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_ready = TRAMPOLINE as *mut u64;
|
||||||
let ap_page_table = unsafe { ap_ready.offset(1) };
|
let ap_stack_start = unsafe { ap_ready.offset(1) };
|
||||||
let ap_stack = unsafe { ap_page_table.offset(1) };
|
let ap_stack_end = unsafe { ap_ready.offset(2) };
|
||||||
let ap_code = unsafe { ap_stack.offset(1) };
|
let ap_code = unsafe { ap_ready.offset(3) };
|
||||||
|
|
||||||
// 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_start, 0x1000) };
|
||||||
unsafe { atomic_store(ap_stack, 0x7C00) };
|
unsafe { atomic_store(ap_stack_end, 0x7000) };
|
||||||
unsafe { atomic_store(ap_code, kstart_ap as u64) };
|
unsafe { atomic_store(ap_code, kstart_ap as u64) };
|
||||||
|
|
||||||
// Send INIT IPI
|
// Send INIT IPI
|
||||||
|
|
|
@ -31,6 +31,11 @@ pub unsafe fn init() {
|
||||||
GDT[GDT_USER_DATA].set_flags(GDT_LONG_MODE);
|
GDT[GDT_USER_DATA].set_flags(GDT_LONG_MODE);
|
||||||
|
|
||||||
GDTR.set_slice(&GDT);
|
GDTR.set_slice(&GDT);
|
||||||
|
|
||||||
|
init_ap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn init_ap() {
|
||||||
GDTR.load();
|
GDTR.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,16 @@ pub unsafe fn init() {
|
||||||
entry.set_offset(8, blank as usize);
|
entry.set_offset(8, blank as usize);
|
||||||
}
|
}
|
||||||
IDTR.set_slice(&IDT);
|
IDTR.set_slice(&IDT);
|
||||||
|
|
||||||
|
init_ap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn init_ap() {
|
||||||
IDTR.load();
|
IDTR.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
interrupt!(blank, {
|
interrupt!(blank, {
|
||||||
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
|
||||||
println!("INTERRUPT");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
interrupt!(exception, {
|
interrupt!(exception, {
|
||||||
|
|
|
@ -44,8 +44,6 @@ macro_rules! interrupt {
|
||||||
$func
|
$func
|
||||||
}
|
}
|
||||||
|
|
||||||
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
|
||||||
|
|
||||||
// Push scratch registers
|
// Push scratch registers
|
||||||
asm!("push rax
|
asm!("push rax
|
||||||
push rcx
|
push rcx
|
||||||
|
@ -87,8 +85,6 @@ macro_rules! interrupt_error {
|
||||||
$func
|
$func
|
||||||
}
|
}
|
||||||
|
|
||||||
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
|
||||||
|
|
||||||
// Push scratch registers, grab stack pointer
|
// Push scratch registers, grab stack pointer
|
||||||
asm!("push rax
|
asm!("push rax
|
||||||
push rcx
|
push rcx
|
||||||
|
@ -159,4 +155,3 @@ pub mod start;
|
||||||
pub mod tss;
|
pub mod tss;
|
||||||
|
|
||||||
pub static ALLOCATOR: Mutex<Option<memory::AreaFrameAllocator>> = Mutex::new(None);
|
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) {
|
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;
|
pub const PAGE_SIZE: usize = 4096;
|
||||||
|
|
||||||
/// Initialize paging
|
/// 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 {
|
extern {
|
||||||
/// The starting byte of the text (code) data segment.
|
/// The starting byte of the text (code) data segment.
|
||||||
static mut __text_start: u8;
|
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 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 mut new_table = {
|
||||||
let frame = allocator.allocate_frame().expect("no more frames");
|
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| {
|
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
|
||||||
let mut remap = |start: usize, end: usize, flags: EntryFlags| {
|
let mut remap = |start: usize, end: usize, flags: EntryFlags| {
|
||||||
/* TODO
|
|
||||||
let start_frame = Frame::containing_address(PhysicalAddress::new(start));
|
let start_frame = Frame::containing_address(PhysicalAddress::new(start));
|
||||||
let end_frame = Frame::containing_address(PhysicalAddress::new(end));
|
let end_frame = Frame::containing_address(PhysicalAddress::new(end - 1));
|
||||||
for frame in Frame::range_inclusive(start_frame, end_frame) {}
|
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));
|
|
||||||
mapper.identity_map(frame, flags, allocator);
|
mapper.identity_map(frame, flags, allocator);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remap stack writable, no execute
|
// 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`
|
// Remap a section with `flags`
|
||||||
let mut remap_section = |start: &u8, end: &u8, flags: EntryFlags| {
|
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.
|
/// Maps the temporary page to the given frame in the active table.
|
||||||
/// Returns the start address of the temporary page.
|
/// Returns the start address of the temporary page.
|
||||||
pub fn map(&mut self, frame: Frame, flags: EntryFlags, active_table: &mut ActivePageTable) -> VirtualAddress {
|
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(),
|
assert!(active_table.translate_page(self.page).is_none(),
|
||||||
"temporary page is already mapped");
|
"temporary page is already mapped");
|
||||||
active_table.map_to(self.page, frame, flags, &mut self.allocator);
|
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.
|
/// Unmaps the temporary page in the active table.
|
||||||
pub fn unmap(&mut self, active_table: &mut ActivePageTable) {
|
pub fn unmap(&mut self, active_table: &mut ActivePageTable) {
|
||||||
|
println!("unmap {:?}", self.page);
|
||||||
active_table.unmap(self.page, &mut self.allocator)
|
active_table.unmap(self.page, &mut self.allocator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +57,7 @@ impl FrameAllocator for TinyAllocator {
|
||||||
fn allocate_frame(&mut self) -> Option<Frame> {
|
fn allocate_frame(&mut self) -> Option<Frame> {
|
||||||
for frame_option in &mut self.0 {
|
for frame_option in &mut self.0 {
|
||||||
if frame_option.is_some() {
|
if frame_option.is_some() {
|
||||||
|
println!("Allocate {:?}", frame_option);
|
||||||
return frame_option.take();
|
return frame_option.take();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,10 +67,15 @@ impl FrameAllocator for TinyAllocator {
|
||||||
fn deallocate_frame(&mut self, frame: Frame) {
|
fn deallocate_frame(&mut self, frame: Frame) {
|
||||||
for frame_option in &mut self.0 {
|
for frame_option in &mut self.0 {
|
||||||
if frame_option.is_none() {
|
if frame_option.is_none() {
|
||||||
|
println!("Deallocate {:?}", frame);
|
||||||
*frame_option = Some(frame);
|
*frame_option = Some(frame);
|
||||||
return;
|
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 externs::memset;
|
||||||
use gdt;
|
use gdt;
|
||||||
use idt;
|
use idt;
|
||||||
use memory;
|
use memory::{self, FrameAllocator};
|
||||||
use paging::{self, entry, Page, VirtualAddress};
|
use paging::{self, entry, Page, VirtualAddress};
|
||||||
|
|
||||||
/// Test of zero values in BSS.
|
/// Test of zero values in BSS.
|
||||||
|
@ -53,35 +53,65 @@ pub unsafe extern fn kstart() -> ! {
|
||||||
idt::init();
|
idt::init();
|
||||||
|
|
||||||
// Initialize memory management
|
// 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
|
// 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_start_page = Page::containing_address(VirtualAddress::new(HEAP_START));
|
||||||
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, entry::WRITABLE | entry::NO_EXECUTE, &mut allocator);
|
active_table.map(page, entry::WRITABLE | entry::NO_EXECUTE, allocator);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read ACPI tables
|
for i in 0..10 {
|
||||||
acpi::init(&mut allocator, &mut active_table);
|
if let Some(ref mut allocator) = *::ALLOCATOR.lock() {
|
||||||
|
println!("BP: {:?}", allocator.allocate_frame());
|
||||||
// Set global allocator
|
}
|
||||||
*::ALLOCATOR.lock() = Some(allocator);
|
|
||||||
|
|
||||||
// Set global page table
|
|
||||||
*::PAGE_TABLE.lock() = Some(active_table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
|
||||||
kmain();
|
kmain();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Entry to rust for an AP
|
/// 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 {
|
loop {
|
||||||
asm!("hlt");
|
asm!("hlt");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
trampoline:
|
trampoline:
|
||||||
.ready: dq 0
|
.ready: dq 0
|
||||||
.page_table: dq 0
|
.stack_start: dq 0
|
||||||
.stack: dq 0
|
.stack_end: dq 0
|
||||||
.code: dq 0
|
.code: dq 0
|
||||||
|
|
||||||
times 512 - ($ - trampoline) db 0
|
times 512 - ($ - trampoline) db 0
|
||||||
|
@ -128,10 +128,11 @@ 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 rdi, [trampoline.stack_start]
|
||||||
|
mov rsi, [trampoline.stack_end]
|
||||||
|
|
||||||
|
lea rsp, [rsi - 16]
|
||||||
|
|
||||||
mov qword [trampoline.ready], 1
|
mov qword [trampoline.ready], 1
|
||||||
mov rax, [trampoline.code]
|
mov rax, [trampoline.code]
|
||||||
|
|
Loading…
Reference in a new issue