314 lines
5.4 KiB
ArmAsm
314 lines
5.4 KiB
ArmAsm
|
.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
|