[RFC PATCH 03/10] powerpc/powernv: Use OPAL_REPORT_TRAP to cope with trap interrupts from OPAL
Nicholas Piggin
npiggin at gmail.com
Sat May 2 21:19:07 AEST 2020
This isn't used yet, because OPAL is nice enough not to cause unexpected
program check interrupts to the OS. A future patch will allow OPAL to
start using traps. Like so.
[OPAL] < assert failed at core/opal.c:814 >
[OPAL] .
[OPAL] .
[OPAL] .
[OPAL] OO__)
[OPAL] <"__/
[OPAL] ^ ^
cpu 0x0: Vector: 700 (Program Check) at [c000000080287770]
pc: 000000003002f360: opal_poll_events+0x54/0x174 [OPAL]
lr: 000000003002f344: opal_poll_events+0x38/0x174 [OPAL]
sp: c000000080287a00
msr: 9000000000021033
current = 0xc0000000016fa100
paca = 0xc0000000012c0000^I irqmask: 0x03^I irq_happened: 0x01
pid = 19, comm = kopald
Linux version 5.7.0-rc3-00053-g2d9c3c965178-dirty
enter ? for help
[c000000080287a80] 000000003002e6b8 opal_v4_le_entry+0x224/0x29c [OPAL]
[c000000080287b50] c000000000096ce8 opal_call+0x1c8/0x580
[c000000080287c90] c000000000097448 opal_poll_events+0x28/0x40
[c000000080287d00] c0000000000a26e0 opal_handle_events+0x70/0x140
[c000000080287d50] c00000000009a198 kopald+0x98/0x140
[c000000080287db0] c00000000012139c kthread+0x18c/0x1a0
[c000000080287e20] c00000000000cc28 ret_from_kernel_thread+0x5c/0x74
Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
arch/powerpc/include/asm/opal-api.h | 7 +++-
arch/powerpc/include/asm/opal.h | 2 ++
arch/powerpc/kernel/traps.c | 39 ++++++++++++++++------
arch/powerpc/platforms/powernv/opal-call.c | 1 +
4 files changed, 37 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
index 8eb31b9aeb27..018d4734c323 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -216,7 +216,8 @@
#define OPAL_SECVAR_ENQUEUE_UPDATE 178
#define OPAL_ADDR_TO_SYM 181
#define OPAL_SYM_TO_ADDR 182
-#define OPAL_LAST 182
+#define OPAL_REPORT_TRAP 183
+#define OPAL_LAST 183
#define QUIESCE_HOLD 1 /* Spin all calls at entry */
#define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
@@ -1184,6 +1185,10 @@ struct opal_mpipl_fadump {
struct opal_mpipl_region region[];
} __packed;
+#define OPAL_TRAP_FATAL 1
+#define OPAL_TRAP_WARN 2
+#define OPAL_TRAP_PANIC 3
+
#endif /* __ASSEMBLY__ */
#endif /* __OPAL_API_H */
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 56b6994aefb7..dc77c2d5e036 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -314,6 +314,8 @@ s64 opal_quiesce(u64 shutdown_type, s32 cpu);
int64_t opal_addr_to_sym(uint64_t addr, __be64 *symaddr, __be64 *symsize, char *namebuf, uint64_t buflen);
int64_t opal_sym_to_addr(const char *name, __be64 *symaddr, __be64 *symsize);
+int64_t opal_report_trap(uint64_t nip);
+
/* Internal functions */
extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 3fca22276bb1..0274ae7b8a03 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -52,6 +52,7 @@
#endif
#ifdef CONFIG_PPC64
#include <asm/firmware.h>
+#include <asm/opal.h>
#include <asm/processor.h>
#include <asm/tm.h>
#endif
@@ -1471,7 +1472,6 @@ void program_check_exception(struct pt_regs *regs)
goto bail;
}
if (reason & REASON_TRAP) {
- unsigned long bugaddr;
/* Debugger is first in line to stop recursive faults in
* rcu_lock, notify_die, or atomic_notifier_call_chain */
if (debugger_bpt(regs))
@@ -1485,18 +1485,35 @@ void program_check_exception(struct pt_regs *regs)
== NOTIFY_STOP)
goto bail;
- bugaddr = regs->nip;
- /*
- * Fixup bugaddr for BUG_ON() in real mode
- */
- if (!is_kernel_addr(bugaddr) && !(regs->msr & MSR_IR))
- bugaddr += PAGE_OFFSET;
+ if (!(regs->msr & MSR_PR)) { /* not user-mode */
+ unsigned long bugaddr;
+ enum bug_trap_type t;
+
+ /*
+ * Fixup bugaddr for BUG_ON() in real mode
+ */
+ bugaddr = regs->nip;
+ if (!is_kernel_addr(bugaddr) && !(regs->msr & MSR_IR))
+ bugaddr += PAGE_OFFSET;
+ t = report_bug(bugaddr, regs);
+ if (t == BUG_TRAP_TYPE_WARN) {
+ regs->nip += 4;
+ goto bail;
+ }
+ if (t == BUG_TRAP_TYPE_BUG)
+ goto bug;
- if (!(regs->msr & MSR_PR) && /* not user-mode */
- report_bug(bugaddr, regs) == BUG_TRAP_TYPE_WARN) {
- regs->nip += 4;
- goto bail;
+ if (firmware_has_feature(FW_FEATURE_OPAL)) {
+ int64_t ret;
+
+ ret = opal_report_trap(regs->nip);
+ if (ret == OPAL_TRAP_WARN) {
+ regs->nip += 4;
+ goto bail;
+ }
+ }
}
+bug:
_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
goto bail;
}
diff --git a/arch/powerpc/platforms/powernv/opal-call.c b/arch/powerpc/platforms/powernv/opal-call.c
index 2233a58924cb..506b1798081a 100644
--- a/arch/powerpc/platforms/powernv/opal-call.c
+++ b/arch/powerpc/platforms/powernv/opal-call.c
@@ -295,3 +295,4 @@ OPAL_CALL(opal_secvar_get_next, OPAL_SECVAR_GET_NEXT);
OPAL_CALL(opal_secvar_enqueue_update, OPAL_SECVAR_ENQUEUE_UPDATE);
OPAL_CALL(opal_addr_to_sym, OPAL_ADDR_TO_SYM);
OPAL_CALL(opal_sym_to_addr, OPAL_SYM_TO_ADDR);
+OPAL_CALL(opal_report_trap, OPAL_REPORT_TRAP);
--
2.23.0
More information about the Linuxppc-dev
mailing list