diff options
author | Jason Thorpe <thorpej@me.com> | 2021-06-02 20:53:17 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2021-06-06 13:26:29 -0700 |
commit | 5e915346477f4f2f33345c7dbe711be828b58730 (patch) | |
tree | 4b7eea9639a68b7a5dddf8272ffb3a8b582d8303 | |
parent | b5bee8227775b91e12c0b6635977d44f2d7fa376 (diff) | |
download | qemu-palcode-5e915346477f4f2f33345c7dbe711be828b58730.zip qemu-palcode-5e915346477f4f2f33345c7dbe711be828b58730.tar.gz qemu-palcode-5e915346477f4f2f33345c7dbe711be828b58730.tar.bz2 |
Fixes for secondary CPU start-up.
Changes to make secondary CPU start-up work on NetBSD, which depends
on some specific behavior in the architecture specification:
- Change the internal swppal() function to take the new VPTPTR and
Procedure Value as explicit arguments. Adapt do_start() to the
new the new swppal() signature.
- In do_start_wait(), extract the new VPTPTR and PV from the relevant
HWRPB fields, which will have been initialized by the OS, and pass
them to swppal().
- In the SWPPAL PAL call, get the value to stuff into PV (r27) from
a4 (r20), and add a comment describing why this implementation detail
is allowed by the architecture specification.
Signed-off-by: Jason Thorpe <thorpej@me.com>
Message-Id: <20210603035317.6814-9-thorpej@me.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r-- | init.c | 25 | ||||
-rw-r--r-- | pal.S | 13 |
2 files changed, 25 insertions, 13 deletions
@@ -288,14 +288,16 @@ init_i8259 (void) } static void __attribute__((noreturn)) -swppal(void *entry, void *pcb) +swppal(void *entry, void *pcb, unsigned long vptptr, unsigned long pv) { register int variant __asm__("$16") = 2; /* OSF/1 PALcode */ register void *pc __asm__("$17") = entry; register unsigned long pa_pcb __asm__("$18") = PA(pcb); - register unsigned long vptptr __asm__("$19") = VPTPTR; + register unsigned long newvptptr __asm__("$19") = vptptr; + register unsigned long newpv __asm__("$20") = pv; - asm("call_pal 0x0a" : : "r"(variant), "r"(pc), "r"(pa_pcb), "r"(vptptr)); + asm("call_pal 0x0a" : : + "r"(variant), "r"(pc), "r"(pa_pcb), "r"(newvptptr), "r"(newpv)); __builtin_unreachable (); } @@ -313,7 +315,9 @@ do_start(unsigned long memsize, void (*kernel_entry)(void), unsigned long cpus) pci_setup(); vgahw_init(); - swppal(kernel_entry ? kernel_entry : do_console, &pcb); + void *new_pc = kernel_entry ? kernel_entry : do_console; + + swppal(new_pc, &pcb, VPTPTR, (unsigned long)new_pc); } void @@ -328,14 +332,16 @@ do_start_wait(unsigned long cpuid) { /* ??? The only message I know of is "START\r\n". I can't be bothered to verify more than 4 characters. */ - /* ??? The Linux kernel fills in, but does not require, - CPU_restart_data. It just sets that to the same address - as CPU_restart itself. Our swppal *does* put the PC into - $26 and $27, the latter of which the kernel does rely upon. */ + + /* Use use a private extension to SWPPAL to get the + CPU_restart_data into $27. Linux fills it in, but does + not require it. Other operating systems, however, do use + CPU_restart_data as part of secondary CPU start-up. */ unsigned int len = hwrpb.processor[cpuid].ipc_buffer[0]; unsigned int msg = hwrpb.processor[cpuid].ipc_buffer[1]; void *CPU_restart = hwrpb.hwrpb.CPU_restart; + unsigned long CPU_restart_data = hwrpb.hwrpb.CPU_restart_data; __sync_synchronize(); hwrpb.hwrpb.rxrdy = 0; @@ -343,7 +349,8 @@ do_start_wait(unsigned long cpuid) { /* Set bootstrap in progress */ hwrpb.processor[cpuid].flags |= 1; - swppal(CPU_restart, hwrpb.processor[cpuid].hwpcb); + swppal(CPU_restart, hwrpb.processor[cpuid].hwpcb, + hwrpb.hwrpb.vptb, CPU_restart_data); } } } @@ -566,6 +566,8 @@ ENDFN CallPal_Cserve_Cont * r17 (a1) = New PC * r18 (a2) = New PCB * r19 (a3) = New VptPtr + * r20 (a4) = New Procedure Value (to place into $27) + * (Non-standard; See note below.) * * OUTPUT PARAMETERS: * @@ -574,11 +576,14 @@ ENDFN CallPal_Cserve_Cont * 1 - Unknown PALcode variant * 2 - Known PALcode variant, but PALcode not loaded * - * r26 (ra) = r27 (pv) = New PC + * r26 (ra) = New PC + * r27 (pv) = From r20 * Note that this is non-architected, but is relied on by * the usage of SwpPal within our own console code in order - * to simplify its use within C code. - * + * to simplify its use within C code. We can get away with + * the extra non-standard argument (in $20) because as + * architected, all registers except SP and R0 are + * UNPREDICTABLE; therefore private internal usage is fine. */ ORG_CALL_PAL_PRIV(0x0A) CallPal_SwpPal: @@ -624,7 +629,7 @@ CallPal_SwpPal_Cont: mtpr $31, qemu_tbia // Flush TLB for new PTBR mov a1, $26 - mov a1, $27 + mov a4, $27 hw_ret (a1) ENDFN CallPal_SwpPal_Cont .previous |