Skip to content

Commit

Permalink
powerpc/pseries/le: Work around a firmware quirk
Browse files Browse the repository at this point in the history
Some PowerVM firmware when delivering a system reset interrupt to a
little endian OS will mess up SRR registers. They are byteswapped, and
SRR1 is incorrect. An example from a crash:

  NIP: 14dd0900000000c0
  MSR: 1000000200000080

It's possible to detect this pattern in SRR1 (that would never happen
in normal operation), and at least fix the NIP. After this patch, the
same interrupt reports NIP properly:

  NIP [c00000000009dd14] plpar_hcall_norets+0x1c/0x28

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
  • Loading branch information
Nicholas Piggin authored and Michael Ellerman committed Aug 31, 2017
1 parent a3b2cb3 commit bded070
Showing 1 changed file with 15 additions and 0 deletions.
15 changes: 15 additions & 0 deletions arch/powerpc/platforms/pseries/ras.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,21 @@ static void fwnmi_release_errinfo(void)

int pSeries_system_reset_exception(struct pt_regs *regs)
{
#ifdef __LITTLE_ENDIAN__
/*
* Some firmware byteswaps SRR registers and gives incorrect SRR1. Try
* to detect the bad SRR1 pattern here. Flip the NIP back to correct
* endian for reporting purposes. Unfortunately the MSR can't be fixed,
* so clear it. It will be missing MSR_RI so we won't try to recover.
*/
if ((be64_to_cpu(regs->msr) &
(MSR_LE|MSR_RI|MSR_DR|MSR_IR|MSR_ME|MSR_PR|
MSR_ILE|MSR_HV|MSR_SF)) == (MSR_DR|MSR_SF)) {
regs->nip = be64_to_cpu((__be64)regs->nip);
regs->msr = 0;
}
#endif

if (fwnmi_active) {
struct rtas_error_log *errhdr = fwnmi_get_errinfo(regs);
if (errhdr) {
Expand Down

0 comments on commit bded070

Please sign in to comment.