From 5cec13f11d3917cf3bceaf68ce23e9fa5f206a35 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 25 Mar 2022 10:27:27 +0100 Subject: parisc: Fix CPU hotplug rendenzvous code Fix the PDC rendenzvous code to clear all pending external intrrupts before entering the waiting loop. Without clearing them before, the CPU was waken up immediately again. This fixes the CPU hotplug on Linux, which can be run with chcpu -d 2 # to disable CPU2 chcpu -e 2 # to wake up CPU2 Signed-off-by: Helge Deller --- src/parisc/head.S | 21 +++++++++++++++++---- src/parisc/parisc.c | 5 +++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/parisc/head.S b/src/parisc/head.S index b4f54a5..eec378b 100644 --- a/src/parisc/head.S +++ b/src/parisc/head.S @@ -122,6 +122,16 @@ ENTRY(enter_smp_idle_loop) /* IDLE LOOP for SMP CPUs - wait for rendenzvous. */ mfctl CPU_HPA_CR_REG, %r25 /* get CPU HPA from cr7 */ +#define PSW_I 1 + rsm PSW_I, %r0 /* disable local irqs */ + + /* EIRR : clear all pending external intr */ +#define CR_EIRR 23 + load32 -1,%r1 + mtctl %r1, CR_EIRR + mfctl CR_EIRR, %r0 + mtctl %r0, CR_EIRR + /* Load IVT for SMT tiny loop exit */ #define CR_IVA 14 load32 BOOTADDR(smp_ivt),%r1 @@ -129,10 +139,9 @@ ENTRY(enter_smp_idle_loop) /* enable CPU local interrupts */ #define CR_EIEM 15 -#define PSW_I 1 load32 1<<31, %r1 /* allow IRQ0 (Timer) */ mtctl %r1, CR_EIEM - ssm PSW_I, %r9 + ssm PSW_I, %r0 /* enable local irqs */ /* endless idle loop, exits to $smp_exit_loop by IRQ only */ $smp_idle_loop: @@ -141,6 +150,10 @@ $smp_idle_loop: $smp_exit_loop: mtctl %r0, CR_EIEM + rsm PSW_I, %r0 /* disable local irqs */ + + /* tell QEMU to drop all local TLB entries. */ + pdtlbe %r0(%sr1,%r0) /* on 64bit: Address of PDCE_PROC for each non-monarch processor in GR26. */ load32 BOOTADDR(pdc_entry), %r26 @@ -148,8 +161,8 @@ $smp_exit_loop: /* jump to rendevouz */ ldw 0x10(%r0),%r3 /* MEM_RENDEZ */ /* ldw 0x28(%r0),%r0 MEM_RENDEZ_HI - assume addr < 4GB */ - bv 0(%r3) - copy %r0,%r2 + load32 enter_smp_idle_loop, %rp + bv,n 0(%r3) $is_monarch_cpu: diff --git a/src/parisc/parisc.c b/src/parisc/parisc.c index e135920..9d96986 100644 --- a/src/parisc/parisc.c +++ b/src/parisc/parisc.c @@ -1195,6 +1195,11 @@ static int pdc_proc(unsigned int *arg) case 1: if (ARG2 != 0) return PDC_BAD_PROC; + if (pdc_debug & DEBUG_PDC) + printf("\nSeaBIOS: CPU%d enters rendenzvous loop.\n", + index_of_CPU_HPA(mfctl(CPU_HPA_CR_REG))); + /* wait until all outstanding timer irqs arrived. */ + msleep(500); /* let the current CPU sleep until rendenzvous. */ enter_smp_idle_loop(); return PDC_OK; -- cgit v1.1