Map kernel in AP, WIP
This commit is contained in:
		
							parent
							
								
									27d5996abf
								
							
						
					
					
						commit
						ebf9766ef5
					
				
					 10 changed files with 89 additions and 50 deletions
				
			
		
							
								
								
									
										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)); | ||||
| 
 | ||||
|         // 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"); | ||||
|     } | ||||
|  |  | |||
|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jeremy Soller
						Jeremy Soller