summaryrefslogtreecommitdiff
path: root/arch/parisc/kernel
diff options
context:
space:
mode:
authorSven Schnelle <svens@stackframe.org>2020-10-02 20:07:20 +0200
committerHelge Deller <deller@gmx.de>2021-02-12 16:31:42 +0100
commitc70919bd9d0782a6078ccd37d7f861d514f5481e (patch)
treea6df960dd027e2491a151a87d23022f9c6a3827a /arch/parisc/kernel
parent61c439439cccac7854b9ecac25554ee45175557a (diff)
parisc: Fix IVT checksum calculation wrt HPMC
On my C8000 a HPMC was triggered, but the HPMC handler wasn't called. I got the following chassis codes: <Cpu2> e800009802e00000 0000000000000000 CC_ERR_CHECK_HPMC <Cpu3> e800009803e00000 00000000001b28a3 CC_ERR_CHECK_HPMC <Cpu2> 37000f7302e00000 8400000000800000 CC_ERR_CPU_CHECK_SUMMARY <Cpu3> 37000f7303e00000 8400000000800000 CC_ERR_CPU_CHECK_SUMMARY <Cpu2> f600105e02e00000 fffffff0f0c00000 CC_MC_HPMC_MONARCH_SELECTED <Cpu3> 5600100b03e00000 00000000000001a0 CC_MC_OS_HPMC_LEN_ERR <Cpu2> 140003b202e00000 000000000000000b CC_ERR_HPMC_STATE_ENTRY <Cpu3> 5600106403e00000 fffffff0f043ad20 CC_MC_BR_TO_OS_HPMC_FAILED <Cpu3> 160012cf03e00000 030001001e000007 CC_MPS_CPU_WAITING <Cpu2> 5600100b02e00000 00000000000001a0 CC_MC_OS_HPMC_LEN_ERR <Cpu2> 5600106402e00000 fffffff0f0438e70 CC_MC_BR_TO_OS_HPMC_FAILED <Cpu2> e800009802e00000 0000000000000000 CC_ERR_CHECK_HPMC <Cpu2> 37000f7302e00000 8400000000800000 CC_ERR_CPU_CHECK_SUMMARY <Cpu2> 4000109f02e00000 0000000000000000 CC_MC_HPMC_INITIATED <Cpu2> 4000101902e00000 0000000000000000 CC_MC_MULTIPLE_HPMCS <Cpu2> 030010d502e00000 0000000000000000 CC_CPU_STOP C8000 PDC is complaining about our HPMC handler length, which is 1a0 (second part of the chassis code). Changing that to 0 makes the error go away: <Cpu0> e800009800e00000 0000000000000000 CC_ERR_CHECK_HPMC <Cpu3> e800009803e00000 0000000000000000 CC_ERR_CHECK_HPMC <Cpu1> e800009801e00000 0000000000000000 CC_ERR_CHECK_HPMC <Cpu2> e800009802e00000 0000000000000000 CC_ERR_CHECK_HPMC <Cpu0> 37000f7300e00000 8060004000000000 CC_ERR_CPU_CHECK_SUMMARY <Cpu3> 37000f7303e00000 8060004000000000 CC_ERR_CPU_CHECK_SUMMARY <Cpu1> 37000f7301e00000 8060004000000000 CC_ERR_CPU_CHECK_SUMMARY <Cpu2> 37000f7302e00000 8060004000000000 CC_ERR_CPU_CHECK_SUMMARY <Cpu0> f600105e00e00000 fffffff0f0c00000 CC_MC_HPMC_MONARCH_SELECTED <Cpu3> 5600109b03e00000 00000000001eb024 CC_MC_BR_TO_OS_HPMC <Cpu1> 5600109b01e00000 00000000001eb024 CC_MC_BR_TO_OS_HPMC <Cpu2> 5600109b02e00000 00000000001eb024 CC_MC_BR_TO_OS_HPMC <Cpu0> 140003b200e00000 000000000000000b CC_ERR_HPMC_STATE_ENTRY <Cpu3> 0000000003000000 0000000000000000 <Cpu1> 0000000001000000 0000000000000000 <Cpu2> 0000000002000000 0000000000000000 <Cpu0> 5600109b00e00000 00000000001eb024 CC_MC_BR_TO_OS_HPMC <Cpu0> 0000000000000000 0000000000000000 So at least the HPMC handler is now called, but it hangs. Which isn't really suprising, as the code has at least one comment saying it can't handle multiple CPUs, and here the handler is called on all CPUs. And i'm not sure whether it can handle 64 Bit. So despite what the PDC spec says, C8000 and RP34xx/RP44xx don't want the OS_HPMC length in the vector set, which is odd. I disassembled the firmware and it actually looks like a Bug in PDC. Signed-off-by: Sven Schnelle <svens@stackframe.org> Signed-off-by: Helge Deller <deller@gmx.de>
Diffstat (limited to 'arch/parisc/kernel')
-rw-r--r--arch/parisc/kernel/hpmc.S10
-rw-r--r--arch/parisc/kernel/traps.c9
2 files changed, 2 insertions, 17 deletions
diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S
index 81de5e2b391c..c2981401775c 100644
--- a/arch/parisc/kernel/hpmc.S
+++ b/arch/parisc/kernel/hpmc.S
@@ -289,13 +289,3 @@ os_hpmc_6:
b .
nop
.align 16 /* make function length multiple of 16 bytes */
-.os_hpmc_end:
-
-
- __INITRODATA
-.globl os_hpmc_size
- .align 4
- .type os_hpmc_size, @object
- .size os_hpmc_size, 4
-os_hpmc_size:
- .word .os_hpmc_end-.os_hpmc
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index a52c7abf2ca4..8d8441d4562a 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -798,14 +798,13 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
void __init initialize_ivt(const void *iva)
{
- extern u32 os_hpmc_size;
extern const u32 os_hpmc[];
int i;
u32 check = 0;
u32 *ivap;
u32 *hpmcp;
- u32 length, instr;
+ u32 instr;
if (strcmp((const char *)iva, "cows can fly"))
panic("IVT invalid");
@@ -836,18 +835,14 @@ void __init initialize_ivt(const void *iva)
/* Setup IVA and compute checksum for HPMC handler */
ivap[6] = (u32)__pa(os_hpmc);
- length = os_hpmc_size;
- ivap[7] = length;
hpmcp = (u32 *)os_hpmc;
- for (i=0; i<length/4; i++)
- check += *hpmcp++;
-
for (i=0; i<8; i++)
check += ivap[i];
ivap[5] = -check;
+ pr_debug("initialize_ivt: IVA[6] = 0x%08x\n", ivap[6]);
}