vap/assembly/ppc32/get_real.S

314 lines
5.4 KiB
ArmAsm
Raw Normal View History

2023-03-13 15:31:06 -07:00
.section .text
// oh how much more powerpc assembly must i write. woe is me
// BAT stuff is completely ripped from helenos
.macro BAT_COMPUTE base size mask lower upper
// less than 128 KB -> no BAT
lis \upper, 0x0002
cmpw \size, \upper
blt no_bat
// mask = total >> 18
li \upper, 18
srw \mask, \size, \upper
// create Block Length mask by replicating
// the leading logical one 14 times
li \upper, 14
mtctr \mask
li \upper, 1
0:
// mask = (mask >> 1) | mask
srw \lower, \mask, \upper
or \mask, \mask, \lower
bdnz 0b
// mask = mask & 0x07ff
// (BAT can map up to 256 MB)
andi. \mask, \mask, 0x07ff
// mask = (mask << 2) | 0x0002
// (priviledged access only)
li \upper, 2
slw \mask, \mask, \upper
ori \mask, \mask, 0x0002
lis \upper, (0x8000 + \base)
or \upper, \upper, \mask
lis \lower, \base
ori \lower, \lower, 0x0002
.endm
.global get_real
get_real:
// r3 = address of the function to call once we're in real mode (physical address)
// r4 = kernel base address (physical address)
// r5 = kernel size
// r6 = final address (physical address)
// r7 translate table (physical address)
// r8 = memory size (physical address)
// r9 = pages to translate
// get msr value
mfmsr 31
// disable interrupts
rlwinm 31,31,0,17,15
// set msr
mtmsr 31
// move r3 into srr0 (so we can jump to it with the rfi instruction)
mtsrr0 3
// set srr1 to the pending msr value we want for real mode
mfmsr 31
lis 30, ~0@h
// "interrupts, instruction relocation, and data relocation"
ori 30, 30, ~((1<<15) | (1<<5) | (1<<4))@l
and 31, 31, 30
mtsrr1 31
// WE'RE GETTING REAL
sync
isync
rfi
#define PAGE_WIDTH 12
#define PAGE_SIZE (1 << PAGE_WIDTH)
.global get_fake
get_fake:
// we want parameters in the format of
// memory_size, translate_table, pages_to_translate, kernel_fake_address, kernel_real_address
// so lets move them into the right registers
mr 31, 4
mr 3, 8
mr 4, 7
mr 5, 9
mr 6, 6
mr 7, 31
// r3 = memory size, r4 = translate table, r5 = pages to translate, r6 = where we jump after finishing
li 31, PAGE_SIZE >> 2 // number of words to copy per page
mr 30, 7 // 30 = beginning of kernel (physical address), we want to copy it to the beginning of the kernel (virtual address)
page_copy:
cmpwi 5, 0 // are pages = 0?
beq page_copy_done
mtctr 31 // load counter with number of words to copy
lwz 29, 0(4) // 29 = address of this page as a physical address
page_copy_loop:
lwz 28, 0(29) // load word from physical address
stw 28, 0(30) // store word to virtual address
dcbst 0, 30 // sync
sync
icbi 0, 30
sync
isync
addi 29, 29, 4 // add 4 to physical address
addi 30, 30, 4 // add 4 to virtual address
bdnz page_copy_loop
// move to next translate table entry
addi 4, 4, 4 // most confusing assembly language award goes to...
subi 5, 5, 1
b page_copy
page_copy_done:
// infinite loop for debugging
debug_loop:
b debug_loop
// fill segment registers
li 31, 0
li 29, 8
mtctr 29
li 30, 0
seg_fill_unpriv:
mtsrin 30, 31
addi 30, 30, 1
addis 31, 31, 0x1000
bdnz seg_fill_unpriv
li 29, 8
mtctr 29
lis 30, 0x4000
ori 30, 30, 8
seg_fill_priv:
mtsrin 30, 31
addi 30, 30, 1
addis 31, 31, 0x1000
bdnz seg_fill_priv
// invalidate bat registers
li 31, 0
mtspr 528, 31
mtspr 529, 31
mtspr 530, 31
mtspr 531, 31
mtspr 532, 31
mtspr 533, 31
mtspr 534, 31
mtspr 535, 31
mtspr 536, 31
mtspr 537, 31
mtspr 538, 31
mtspr 539, 31
mtspr 540, 31
mtspr 541, 31
mtspr 542, 31
mtspr 543, 31
// set up page hash table
lis 31, 65536@h
ori 31, 31, 65536@l
subi 29, 31, 1
sub 30, 3, 31
andc 31, 31, 29
mtsdr1 30
li 29, 2
srw 31, 31, 29
li 29, 0
pht_clear:
stw 29, 0(30)
dcbst 0, 30
sync
isync
addi 30, 30, 4
subi 31, 31, 4
cmpwi 31, 0
beq pht_clear_done
bdnz pht_clear
pht_clear_done:
mr 31, 3
lis 30, 268435456@h
ori 30, 30, 268435456@l // 256MiB
// bat 0
cmpw 31, 30
blt bat0_31
mr 29, 30
b bat0_30
bat0_31:
mr 29, 31
bat0_30:
BAT_COMPUTE 0x0000 29 28 27 26
mtspr 528, 26
mtspr 529, 27
mtspr 536, 26
mtspr 537, 27
// BAT1
sub 31, 31, 29
cmpw 31, 30
blt bat1_r31
mr 29, 30
b bat1_r30
bat1_r31:
mr 29, 31
bat1_r30:
BAT_COMPUTE 0x1000 29 28 27 26
mtspr 530, 26
mtspr 531, 27
mtspr 538, 26
mtspr 539, 27
// BAT2
sub 31, 31, 29
cmpw 31, 30
blt bat2_r31
mr 29, 30
b bat2_r30
bat2_r31:
mr 29, 31
bat2_r30:
BAT_COMPUTE 0x2000 29 28 27 26
mtspr 532, 26
mtspr 533, 27
mtspr 540, 26
mtspr 541, 27
// BAT3
sub 31, 31, 29
cmpw 31, 30
blt bat3_r31
mr 29, 30
b bat3_r30
bat3_r31:
mr 29, 31
bat3_r30:
BAT_COMPUTE 0x3000 29 28 27 26
mtspr 534, 26
mtspr 535, 27
mtspr 542, 26
mtspr 543, 27
no_bat:
// flush tlb
li 31, 0
sync
eieio
tlbsync
sync
// jump to the final function!
mtsrr0 6
li 1, 0 // stack pointer
mfmsr 31
ori 31, 31, ((1<<5) | (1<<4))@l
mtsrr1 31
sync
isync
rfi