diff --git a/Makefile b/Makefile index 77bfb57..d1486b6 100644 --- a/Makefile +++ b/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 $@ $< diff --git a/arch/x86_64/src/acpi/mod.rs b/arch/x86_64/src/acpi/mod.rs index 81c7b4e..9198806 100644 --- a/arch/x86_64/src/acpi/mod.rs +++ b/arch/x86_64/src/acpi/mod.rs @@ -69,14 +69,14 @@ pub fn init_sdt(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 diff --git a/arch/x86_64/src/gdt.rs b/arch/x86_64/src/gdt.rs index 8abd61a..00457f9 100644 --- a/arch/x86_64/src/gdt.rs +++ b/arch/x86_64/src/gdt.rs @@ -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(); } diff --git a/arch/x86_64/src/idt.rs b/arch/x86_64/src/idt.rs index 2d45561..dcbc8b4 100644 --- a/arch/x86_64/src/idt.rs +++ b/arch/x86_64/src/idt.rs @@ -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, { diff --git a/arch/x86_64/src/lib.rs b/arch/x86_64/src/lib.rs index 6fde0ae..b3e600d 100644 --- a/arch/x86_64/src/lib.rs +++ b/arch/x86_64/src/lib.rs @@ -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> = Mutex::new(None); -pub static PAGE_TABLE: Mutex> = Mutex::new(None); diff --git a/arch/x86_64/src/memory/area_frame_alloc.rs b/arch/x86_64/src/memory/area_frame_alloc.rs index dd93b62..e85f86c 100644 --- a/arch/x86_64/src/memory/area_frame_alloc.rs +++ b/arch/x86_64/src/memory/area_frame_alloc.rs @@ -76,6 +76,6 @@ impl FrameAllocator for AreaFrameAllocator { } fn deallocate_frame(&mut self, frame: Frame) { - unimplemented!() + println!("Leak frame: {:?}", frame); } } diff --git a/arch/x86_64/src/paging/mod.rs b/arch/x86_64/src/paging/mod.rs index 1de6233..50a90ab 100644 --- a/arch/x86_64/src/paging/mod.rs +++ b/arch/x86_64/src/paging/mod.rs @@ -21,7 +21,7 @@ pub const ENTRY_COUNT: usize = 512; pub const PAGE_SIZE: usize = 4096; /// Initialize paging -pub unsafe fn init(allocator: &mut A) -> ActivePageTable where A: FrameAllocator { +pub unsafe fn init(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(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(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| { diff --git a/arch/x86_64/src/paging/temporary_page.rs b/arch/x86_64/src/paging/temporary_page.rs index 13ad2c2..8f79fcc 100644 --- a/arch/x86_64/src/paging/temporary_page.rs +++ b/arch/x86_64/src/paging/temporary_page.rs @@ -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 { 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); } } diff --git a/arch/x86_64/src/start.rs b/arch/x86_64/src/start.rs index 04eb62e..1be6e78 100644 --- a/arch/x86_64/src/start.rs +++ b/arch/x86_64/src/start.rs @@ -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)); - // Initialize paging - let mut active_table = paging::init(&mut allocator); + if let Some(ref mut allocator) = *::ALLOCATOR.lock() { + // TODO: allocate a stack + let stack_start = 0x00080000; + let stack_end = 0x0009F000; - // Initialize 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)); + // Initialize paging + let mut active_table = paging::init(stack_start, stack_end, allocator); - for page in Page::range_inclusive(heap_start_page, heap_end_page) { - active_table.map(page, entry::WRITABLE | entry::NO_EXECUTE, &mut allocator); + // 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, allocator); + } + } + } + + for i in 0..10 { + if let Some(ref mut allocator) = *::ALLOCATOR.lock() { + println!("BP: {:?}", allocator.allocate_frame()); } - - // 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); } - 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"); } diff --git a/bootloader/x86/startup-x86_64.asm b/bootloader/x86/startup-x86_64.asm index 8d27857..1e4c57a 100644 --- a/bootloader/x86/startup-x86_64.asm +++ b/bootloader/x86/startup-x86_64.asm @@ -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]