diff --git a/assembly/ppc32/get_real.S b/assembly/ppc32/get_real.S index 2d709dd..c3100b0 100644 --- a/assembly/ppc32/get_real.S +++ b/assembly/ppc32/get_real.S @@ -20,18 +20,12 @@ vap_get_real: // enter real mode mtsrr0 5 mfmsr 31 - // MSR_IR (1 << 5) = 0 - // MSR_DR (1 << 4) = 0 - // MSR_EE (1 << 15) = 0 - lis 30, ~0@h - ori 30, 30, ~((1 << 15) | (1 << 5) | (1 << 4))@l - and 31, 31, 30 - mtsrr1 31 + li 31, (1 << ((32-1) - 19)) + mtmsr 31 // now we can rfi to so_real sync isync - rfi .global vap_get_fake .extern VAP_KERN_BASE .extern VAP_KERN_PHOF @@ -39,44 +33,7 @@ vap_get_real: vap_get_fake: // we are now in actual real mode, the registers shouldn't have changed - // first things first, use the translation table to remap the kernel's memory - - #define PAGE_WIDTH 12 - #define PAGE_SIZE (1 << PAGE_WIDTH) - - // some values for page copying, very much inspired by helenos's ppc32 port - li 31, PAGE_SIZE >> 2 - li 30, 0 - - page_copy: - cmpwi 4, 0 // are we at 0 pages (done)? - beq page_copy_done // if so, jump to the end - - mtctr 31 // set the counter to PAGE_SIZE >> 2 - lwz 29, 0(3) // load the physical address of the page to copy - - page_copy_loop: - lwz 28, 0(29) // load the word to copy - stw 28, 0(30) // store the word to the new page - - // ensure everything's synced - dcbst 0, 30 - sync - icbi 0, 30 - sync - isync - - addi 29, 29, 4 // increment the source pointer - addi 30, 30, 4 // increment the destination pointer - bdnz page_copy_loop // loop - // end of page_copy_loop - // increment the translation table pointer - addi 3, 3, 4 - // decrement the number of pages left - subi 4, 4, 1 - b page_copy // loop - - page_copy_done: + // for the first 256MiB, virtual=physical // normally i'd write register names as their true values, but with the bat registers // that'd just make things purely unreadable @@ -116,138 +73,24 @@ vap_get_fake: mtspr dbat3u, 30 mtspr dbat3l, 30 - // here we define a macro for calculating the bat register values - // the bat registers are referred to as "upper" and "lower" registers - // the upper register contains the virtual address of the page, and the lower register contains - // the physical address of the page, as well as some other information - // if you want to learn more about this, i'd recommend reading this pdf: - // http://www.cs.cmu.edu/~412-s05/projects/9mac/PowerPC_Memory.pdf - // there are two notable things about this macro: - // 1. lower and upper are registers that the lower and upper bat registers should be set to - // their initial values do not matter - // 2. i kinda just stole this from helenos, i'm sorry ): -.macro BAT_COMPUTE base size mask lower upper kern_base - lis \upper, 0x0002 - cmpw \size, \upper // check if we have less than 128kib remaining to map - blt finish_bat // if so, jump to the end + // now we can set up the bat registers + li 7, ((0x7FF<<2)|2) + li 8, ((2<<3)|2) - li \upper, 18 - srw \mask, \size, \upper // calculate the mask (size >> 18) + sync + isync - // create the block length mask by duplicating the leading 1 14 times - // the block length mask indicates the length by number of bits set - li \upper, 14 - mtctr \upper - li \upper, 1 - 0: - srw \lower, \mask, \upper - or \mask, \mask, \lower - bdnz 0b - // end of 0: - // & the mask with 0x07ff to assure that we map at most 256mib - andi. \mask, \mask, 0x07ff + mtspr dbat0u, 7 + mtspr dbat0l, 8 + sync + isync + mtspr ibat0u, 7 + mtspr ibat0l, 8 + sync + isync - // calculate the upper register - // the upper register contains: - // 1. the virtual address of the page - // 2. the block length mask - // 3. kernel access bit (1 << 2) - // 4. user access bit (1 << 1) - // we don't have a userspace yet! so we'll just set the kernel access bit to 1 - // and the user access bit to 0 - li \upper, 2 - slw \mask, \mask, \upper - ori \mask, \mask, 0x0002 + // zero the rest - lis \upper, (\kern_base + \base)@l - or \upper, \upper, \mask - - // calculate the lower register - // the lower register contains: - // 1. the physical address of the page - // 2. storage access controls - // 3. protection bits - lis \lower, \base - ori \lower, \lower, 0x0002 -.endm - - // now we are finally ready to set the bat registers! - // we will load into r29 either 256MiB or the remaining memory amount, whichever is smaller - lis 30, 268435456@h - ori 30, 30, 268435456@l - // reminder that r7 contains the amount of memory we have - cmpw 7, 30 - blt bat0_memsmaller - - // 256mib is smaller - mr 29, 30 - b bat0_constsmaller - - bat0_memsmaller: - mr 29, 7 - bat0_constsmaller: - BAT_COMPUTE 0x0000 29 28 27 26 VAP_KERN_PHOF - mtspr ibat0u, 26 - mtspr ibat0l, 27 - mtspr dbat0u, 26 - mtspr dbat0l, 27 - - // now we will do the same thing for bat 1 - sub 7, 7, 29 // decrement the amount of memory left - - cmpw 7, 30 - blt bat1_memsmaller - - // 256mib is smaller - mr 29, 30 - b bat1_constsmaller - - bat1_memsmaller: - mr 29, 7 - bat1_constsmaller: - BAT_COMPUTE 0x1000 29 28 27 26 VAP_KERN_PHOF - mtspr ibat1u, 26 - mtspr ibat1l, 27 - mtspr dbat1u, 26 - mtspr dbat1l, 27 - - // now we will do the same thing for bat 2 - sub 7, 7, 29 // decrement the amount of memory left - - cmpw 7, 30 - blt bat2_memsmaller - - // 256mib is smaller - mr 29, 30 - b bat2_constsmaller - - bat2_memsmaller: - mr 29, 7 - bat2_constsmaller: - BAT_COMPUTE 0x2000 29 28 27 26 VAP_KERN_PHOF - mtspr ibat2u, 26 - mtspr ibat2l, 27 - mtspr dbat2u, 26 - mtspr dbat2l, 27 - - // now we will do the same thing for bat 3 - sub 7, 7, 29 // decrement the amount of memory left - - cmpw 7, 30 - blt bat3_memsmaller - - // 256mib is smaller - mr 29, 30 - b bat3_constsmaller - - bat3_memsmaller: - mr 29, 7 - bat3_constsmaller: - BAT_COMPUTE 0x3000 29 28 27 26 VAP_KERN_PHOF - mtspr ibat3u, 26 - mtspr ibat3l, 27 - mtspr dbat3u, 26 - mtspr dbat3l, 27 finish_bat: // theoretically, we should be done with the bat registers now @@ -260,7 +103,8 @@ vap_get_fake: // we need to set the srr1 register to the value of the msr register // but also re-enable MSR_IR and MSR_DR so that we can use the bat registers mfmsr 31 - ori 31, 31, ((1 << 5) | (1 << 4))@l + li 31, ((1 << ((32-1) - 19)) | (1 << ((32-1) - 26)) | (1 << ((32-1) - 27))) + // enable bit 30 to allow system resets to be recoverable mtsrr1 31 //mr 1, 8 // restore the stack pointer diff --git a/src/bootstrap.rs b/src/bootstrap.rs index 15eda9e..5d2022a 100644 --- a/src/bootstrap.rs +++ b/src/bootstrap.rs @@ -55,12 +55,7 @@ pub fn bootstrap() -> ! { debug!("phys_translation_table: {:x}", phys_translation_table); debug!("page_count: {:x}", page_count); - debug!("kernal base: {:x}", VAP_KERN_BASE as usize); - debug!("vap_get_real: {:x}", vap_get_real as usize); - debug!("phys_get_fake: {:x}", phys_get_fake); - debug!("vap_get_fake: {:x}", vap_get_fake as usize); - debug!("so_fake: {:x}", so_fake as usize); - debug!("phys_so_fake: {:x}", translate_to_phys(so_fake as usize).unwrap()); + debug!("phys_vap_get_fake: {:x}", phys_vap_get_fake); debug!("mem_size: {:x}", mem_size); debug!("vap_stack: {:x}", VAP_STACK as usize); debug!("openfirmware entry fn: {:x}", unsafe { @@ -70,7 +65,7 @@ pub fn bootstrap() -> ! { debug!("filled vap allocator with available memory, see you on the flip side!"); unsafe { - vap_get_real(phys_translation_table, page_count, phys_get_fake, so_fake as usize, mem_size, VAP_STACK as usize); + vap_get_real(phys_translation_table, page_count, phys_vap_get_fake, finalize_bootstrapping as usize, mem_size); } } @@ -85,9 +80,11 @@ extern "C" fn test1() { #[no_mangle] pub extern "C" fn finalize_bootstrapping() -> ! { - //test1(); - panic!("test"); - memory::ppc32::allocation::VapAllocator::init(); + // we made it! + debug!("hiiii"); + let available = get_available_memory(); + debug!("available memory: {:?}", available); + memory::VapAllocator::init(available); debug!("initialised vap allocator"); debug!("patching interrupt vectors"); patch_interrupt_vectors(); diff --git a/src/main.rs b/src/main.rs index cdc16e9..8321d1f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ #![feature(lang_items)] #![feature(asm_experimental_arch)] #![feature(once_cell)] +#![feature(lazy_cell)] #![no_std] #![no_main] @@ -252,6 +253,12 @@ pub fn kernel_main() -> ! { stack_pointer }; - println!("bootstrapping"); - bootstrap::bootstrap(); + println!("initializing scheduler"); + scheduling::add_task(None, kernel_callback).expect("failed to add kernel callback task"); + + //debug!("constructing terminal window"); + //terminal::construct_terminal_window(); + //macros::USE_RAW.store(false, core::sync::atomic::Ordering::SeqCst); + unsafe { scheduling::init_scheduler() }; + loop {} } \ No newline at end of file diff --git a/src/scheduling.rs b/src/scheduling.rs index cc1586d..b0f6e8d 100644 --- a/src/scheduling.rs +++ b/src/scheduling.rs @@ -137,6 +137,7 @@ pub extern "C" fn scheduler_callback(savestate: *const SaveState) -> ! { // set the stack pointer to the end of the stack task.savestate.sp = stack as u32 + 0x100000; task.stack_base = stack as usize; + //debug!("added task {} to scheduler", task.uuid); // if the next task points to a task that isn't empty, then we need to push the task if scheduler.tasks.get(scheduler.next_task as usize).is_none() || scheduler.tasks[scheduler.next_task as usize].is_some() { @@ -227,8 +228,7 @@ pub extern "C" fn scheduler_callback(savestate: *const SaveState) -> ! { // reset the last_run value of the task with the highest priority scheduler.tasks[index_with_highest_priority].as_mut().unwrap().last_run = 0; - // set the current task to the task with the highest priority - scheduler.current_task = scheduler.tasks[index_with_highest_priority].as_mut().unwrap().uuid; + //debug!("now running task {} with srr0 {:x}", scheduler.current_task, scheduler.tasks[index_with_highest_priority].as_mut().unwrap().savestate.srr0); // return to the task with the highest priority unsafe {