qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 8/8] Fixes for seconday CPU start-up.


From: Jason Thorpe
Subject: [PATCH 8/8] Fixes for seconday CPU start-up.
Date: Wed, 2 Jun 2021 20:53:17 -0700

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>
---
 init.c | 25 ++++++++++++++++---------
 pal.S  | 13 ++++++++++---
 2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/init.c b/init.c
index aee5cef..bfe4d96 100644
--- a/init.c
+++ b/init.c
@@ -313,14 +313,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 ();
 }
 
@@ -339,7 +341,9 @@ do_start(unsigned long memsize, void (*kernel_entry)(void),
   vgahw_init();
   init_hwrpb(memsize, config);
 
-  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
@@ -354,14 +358,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;
 
@@ -369,7 +375,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);
            }
        }
     }
diff --git a/pal.S b/pal.S
index 015a829..7e3a62c 100644
--- a/pal.S
+++ b/pal.S
@@ -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,10 +576,15 @@ 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)
@@ -624,7 +631,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
-- 
2.30.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]