Changeset View
Changeset View
Standalone View
Standalone View
head/sys/powerpc/ofw/ofwcall64.S
Show All 36 Lines | |||||
/* | /* | ||||
* Globals | * Globals | ||||
*/ | */ | ||||
.data | .data | ||||
.align 4 | .align 4 | ||||
ofwstk: | ofwstk: | ||||
.space OFWSTKSZ | .space OFWSTKSZ | ||||
rtas_regsave: | rtas_regsave: | ||||
.space 24 /* 3 * sizeof(register_t) */ | .space 32 /* 4 * sizeof(register_t) */ | ||||
GLOBAL(ofmsr) | GLOBAL(ofmsr) | ||||
.llong 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */ | .llong 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */ | ||||
GLOBAL(rtasmsr) | GLOBAL(rtasmsr) | ||||
.llong 0 | .llong 0 | ||||
GLOBAL(openfirmware_entry) | GLOBAL(openfirmware_entry) | ||||
.llong 0 /* Open Firmware entry point */ | .llong 0 /* Open Firmware entry point */ | ||||
GLOBAL(rtas_entry) | GLOBAL(rtas_entry) | ||||
.llong 0 /* RTAS entry point */ | .llong 0 /* RTAS entry point */ | ||||
TOC_ENTRY(ofmsr) | TOC_ENTRY(ofmsr) | ||||
TOC_ENTRY(ofwstk) | TOC_ENTRY(ofwstk) | ||||
TOC_ENTRY(rtasmsr) | TOC_ENTRY(rtasmsr) | ||||
TOC_ENTRY(openfirmware_entry) | TOC_ENTRY(openfirmware_entry) | ||||
TOC_ENTRY(rtas_entry) | TOC_ENTRY(rtas_entry) | ||||
TOC_ENTRY(rtas_regsave) | TOC_ENTRY(rtas_regsave) | ||||
/* | /* | ||||
* Open Firmware Real-mode Entry Point. This is a huge pain. | * Open Firmware Real-mode Entry Point. This is a huge pain. | ||||
*/ | */ | ||||
ASENTRY_NOPROF(ofwcall) | ASENTRY_NOPROF(ofwcall) | ||||
mflr %r0 | mflr %r8 | ||||
std %r0,16(%r1) | std %r8,16(%r1) | ||||
stdu %r1,-208(%r1) | stdu %r1,-208(%r1) | ||||
/* | /* | ||||
* We need to save the following, because OF's register save/ | * We need to save the following, because OF's register save/ | ||||
* restore code assumes that the contents of registers are | * restore code assumes that the contents of registers are | ||||
* at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These | * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These | ||||
* get placed in that order in the stack. | * get placed in that order in the stack. | ||||
*/ | */ | ||||
Show All 24 Lines | ASENTRY_NOPROF(ofwcall) | ||||
mfmsr %r6 | mfmsr %r6 | ||||
/* read client interface handler */ | /* read client interface handler */ | ||||
ld %r4,TOC_REF(openfirmware_entry)(%r2) | ld %r4,TOC_REF(openfirmware_entry)(%r2) | ||||
ld %r4,0(%r4) | ld %r4,0(%r4) | ||||
/* Get OF stack pointer */ | /* Get OF stack pointer */ | ||||
ld %r7,TOC_REF(ofwstk)(%r2) | ld %r7,TOC_REF(ofwstk)(%r2) | ||||
addi %r7,%r7,OFWSTKSZ-32 | addi %r7,%r7,OFWSTKSZ-40 | ||||
/* | /* | ||||
* Set the MSR to the OF value. This has the side effect of disabling | * Set the MSR to the OF value. This has the side effect of disabling | ||||
* exceptions, which is important for the next few steps. | * exceptions, which is important for the next few steps. | ||||
*/ | */ | ||||
ld %r5,TOC_REF(ofmsr)(%r2) | ld %r5,TOC_REF(ofmsr)(%r2) | ||||
ld %r5,0(%r5) | ld %r5,0(%r5) | ||||
mtmsrd %r5 | mtmsrd %r5 | ||||
isync | isync | ||||
/* | /* | ||||
* Set up OF stack. This needs to be accessible in real mode and | * Set up OF stack. This needs to be accessible in real mode and | ||||
* use the 32-bit ABI stack frame format. The pointer to the current | * use the 32-bit ABI stack frame format. The pointer to the current | ||||
* kernel stack is placed at the very top of the stack along with | * kernel stack is placed at the very top of the stack along with | ||||
* the old MSR so we can get them back later. | * the old MSR so we can get them back later. | ||||
*/ | */ | ||||
mr %r5,%r1 | mr %r5,%r1 | ||||
mr %r1,%r7 | mr %r1,%r7 | ||||
std %r5,8(%r1) /* Save real stack pointer */ | std %r5,8(%r1) /* Save real stack pointer */ | ||||
std %r2,16(%r1) /* Save old TOC */ | std %r2,16(%r1) /* Save old TOC */ | ||||
std %r6,24(%r1) /* Save old MSR */ | std %r6,24(%r1) /* Save old MSR */ | ||||
std %r8,32(%r1) /* Save high 32-bits of the kernel's PC */ | |||||
li %r5,0 | li %r5,0 | ||||
stw %r5,4(%r1) | stw %r5,4(%r1) | ||||
stw %r5,0(%r1) | stw %r5,0(%r1) | ||||
/* Finally, branch to OF */ | /* Finally, branch to OF */ | ||||
mtctr %r4 | mtctr %r4 | ||||
bctrl | bctrl | ||||
/* Reload stack pointer and MSR from the OFW stack */ | /* Reload stack pointer, MSR, and reference PC from the OFW stack */ | ||||
ld %r7,32(%r1) | |||||
ld %r6,24(%r1) | ld %r6,24(%r1) | ||||
ld %r2,16(%r1) | ld %r2,16(%r1) | ||||
ld %r1,8(%r1) | ld %r1,8(%r1) | ||||
/* Now set the real MSR */ | /* Get back to the MSR/PC we want, using the cached high bits of PC */ | ||||
mtmsrd %r6 | mtsrr1 %r6 | ||||
isync | clrrdi %r7,%r7,32 | ||||
bl 1f | |||||
1: mflr %r8 | |||||
or %r8,%r8,%r7 | |||||
addi %r8,%r8,2f-1b | |||||
mtsrr0 %r8 | |||||
rfid /* Turn on MMU, exceptions, and 64-bit mode */ | |||||
2: | |||||
/* Sign-extend the return value from OF */ | /* Sign-extend the return value from OF */ | ||||
extsw %r3,%r3 | extsw %r3,%r3 | ||||
/* Restore all the non-volatile registers */ | /* Restore all the non-volatile registers */ | ||||
ld %r5,48(%r1) | ld %r5,48(%r1) | ||||
mtcr %r5 | mtcr %r5 | ||||
ld %r13,56(%r1) | ld %r13,56(%r1) | ||||
ld %r14,64(%r1) | ld %r14,64(%r1) | ||||
Show All 24 Lines | |||||
/* | /* | ||||
* RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate | * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate | ||||
* stack) | * stack) | ||||
* | * | ||||
* C prototype: int rtascall(void *callbuffer, void *rtas_privdat); | * C prototype: int rtascall(void *callbuffer, void *rtas_privdat); | ||||
*/ | */ | ||||
ASENTRY_NOPROF(rtascall) | ASENTRY_NOPROF(rtascall) | ||||
mflr %r0 | mflr %r9 | ||||
std %r0,16(%r1) | std %r9,16(%r1) | ||||
stdu %r1,-208(%r1) | stdu %r1,-208(%r1) | ||||
/* | /* | ||||
* We need to save the following, because RTAS's register save/ | * We need to save the following, because RTAS's register save/ | ||||
* restore code assumes that the contents of registers are | * restore code assumes that the contents of registers are | ||||
* at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These | * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These | ||||
* get placed in that order in the stack. | * get placed in that order in the stack. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | ASENTRY_NOPROF(rtascall) | ||||
* Put this in r1, since RTAS is obliged to save it. Kernel globals | * Put this in r1, since RTAS is obliged to save it. Kernel globals | ||||
* are below 4 GB, so this is safe. | * are below 4 GB, so this is safe. | ||||
*/ | */ | ||||
mr %r7,%r1 | mr %r7,%r1 | ||||
mr %r1,%r8 | mr %r1,%r8 | ||||
std %r7,0(%r1) /* Save 64-bit stack pointer */ | std %r7,0(%r1) /* Save 64-bit stack pointer */ | ||||
std %r2,8(%r1) /* Save TOC */ | std %r2,8(%r1) /* Save TOC */ | ||||
std %r6,16(%r1) /* Save MSR */ | std %r6,16(%r1) /* Save MSR */ | ||||
std %r9,24(%r1) /* Save reference PC for high 32 bits */ | |||||
/* Finally, branch to RTAS */ | /* Finally, branch to RTAS */ | ||||
mtctr %r5 | mtctr %r5 | ||||
bctrl | bctrl | ||||
/* | /* | ||||
* Reload stack pointer and MSR from the reg save area in r1. We are | * Reload stack pointer, MSR, reg PC from the reg save area in r1. We | ||||
* running in 32-bit mode at this point, so it doesn't matter if r1 | * are running in 32-bit mode at this point, so it doesn't matter if r1 | ||||
* has become sign-extended. | * has become sign-extended. | ||||
*/ | */ | ||||
ld %r7,24(%r1) | |||||
ld %r6,16(%r1) | ld %r6,16(%r1) | ||||
ld %r2,8(%r1) | ld %r2,8(%r1) | ||||
ld %r1,0(%r1) | ld %r1,0(%r1) | ||||
/* Now set the real MSR */ | /* | ||||
mtmsrd %r6 | * Get back to the right PC. We need to atomically re-enable | ||||
isync | * exceptions, 64-bit mode, and the MMU. One thing that has likely | ||||
* happened is that, if we were running in the high-memory direct | |||||
* map, we no longer are as a result of LR truncation in RTAS. | |||||
* Fix this by copying the high-order bits of the LR at function | |||||
* entry onto the current PC and then jumping there while flipping | |||||
* all the MSR bits. | |||||
*/ | |||||
mtsrr1 %r6 | |||||
clrrdi %r7,%r7,32 | |||||
bl 1f | |||||
1: mflr %r8 | |||||
or %r8,%r8,%r7 | |||||
addi %r8,%r8,2f-1b | |||||
mtsrr0 %r8 | |||||
rfid /* Turn on MMU, exceptions, and 64-bit mode */ | |||||
2: | |||||
/* Sign-extend the return value from RTAS */ | /* Sign-extend the return value from RTAS */ | ||||
extsw %r3,%r3 | extsw %r3,%r3 | ||||
/* Restore all the non-volatile registers */ | /* Restore all the non-volatile registers */ | ||||
ld %r5,48(%r1) | ld %r5,48(%r1) | ||||
mtcr %r5 | mtcr %r5 | ||||
ld %r13,56(%r1) | ld %r13,56(%r1) | ||||
ld %r14,64(%r1) | ld %r14,64(%r1) | ||||
Show All 24 Lines |