.section .text .global vap_get_real vap_get_real: // switches the kernel from relying on openfirmware's virtual memory // to its own BAT-mapped memory // r3 = "translation table" (array of addresses of physical pages, starting at the virtual page with address 0) // r4 = "translation table" size (in pages) // r5 = vap_get_fake // r6 = so_fake (pointer to the function to call after the kernel has been remapped (IN VIRTUAL MEMORY)) // r7 = amount of memory this system has (in bytes) // r8 = stack pointer (IN VIRTUAL MEMORY) // all pointer arguments are physical addresses unless otherwise specified // disable interrupts mfmsr 31 rlwinm 31, 31, 0, 17, 15 mtmsr 31 // enter real mode mtsrr0 5 mfmsr 31 li 31, (1 << ((32-1) - 19)) mtmsr 31 // now we can rfi to so_real sync isync .global vap_get_fake .extern VAP_KERN_BASE .extern VAP_KERN_PHOF .extern VAP_KERN_END vap_get_fake: // we are now in actual real mode, the registers shouldn't have changed // 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 #define ibat0u 528 #define ibat0l 529 #define ibat1u 530 #define ibat1l 531 #define ibat2u 532 #define ibat2l 533 #define ibat3u 534 #define ibat3l 535 #define dbat0u 536 #define dbat0l 537 #define dbat1u 538 #define dbat1l 539 #define dbat2u 540 #define dbat2l 541 #define dbat3u 542 #define dbat3l 543 // here we will give all of the bat registers an initial value of 0 li 30, 0 mtspr ibat0u, 30 mtspr ibat0l, 30 mtspr ibat1u, 30 mtspr ibat1l, 30 mtspr ibat2u, 30 mtspr ibat2l, 30 mtspr ibat3u, 30 mtspr ibat3l, 30 mtspr dbat0u, 30 mtspr dbat0l, 30 mtspr dbat1u, 30 mtspr dbat1l, 30 mtspr dbat2u, 30 mtspr dbat2l, 30 mtspr dbat3u, 30 mtspr dbat3l, 30 // now we can set up the bat registers li 7, ((0x7FF<<2)|2) li 8, ((2<<3)|2) sync isync mtspr dbat0u, 7 mtspr dbat0l, 8 sync isync mtspr ibat0u, 7 mtspr ibat0l, 8 sync isync // zero the rest finish_bat: // theoretically, we should be done with the bat registers now // we can now rfi to so_real (who's address should still be in r6) // this function is in virtual memory, but this shouldn't matter as we have set up the bat registers // to map said virtual memory to the same physical memory mtsrr0 6 // 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 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 // now we can rfi to so_real sync isync rfi .extern finalize_bootstrapping .global so_fake // this is the function that we will rfi to so_fake: //li 0, 0 // load 0 into r0 //// make sure the pointer is aligned to 16 bytes to grow downwards //addi 1, 1, 0xf //// store r0 into the stack //stw 0, 0(1) //stwu 1, -32(1) // new stack frame lis 3, finalize_bootstrapping@ha // load the address of finalize_bootstrapping into r3 ori 3, 3, finalize_bootstrapping@l // load the address of finalize_bootstrapping into r3 mtlr 3 // load the address of finalize_bootstrapping into the link register blrl // call finalize_bootstrapping .section VAP_STACK_SECTION, "aw", @progbits .global VAP_STACK .align 4 .space 0x2000 VAP_STACK: