From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
To: linuxppc-dev@ozlabs.org
Subject: [PATCH 17/20] powerpc/powernv: Machine check and other system interrupts
Date: Tue, 20 Sep 2011 13:45:04 +1000 [thread overview]
Message-ID: <1316490307-28030-17-git-send-email-benh@kernel.crashing.org> (raw)
In-Reply-To: <1316490307-28030-1-git-send-email-benh@kernel.crashing.org>
OPAL can handle various interrupt for us such as Machine Checks (it
performs all sorts of recovery tasks and passes back control to us with
informations about the error), Hardware Management Interrupts and Softpatch
interrupts.
This wires up the mechanisms and prints out specific informations returned
by HAL when a machine check occurs.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/opal.h | 2 +
arch/powerpc/include/asm/paca.h | 8 ++
arch/powerpc/kernel/asm-offsets.c | 10 +++
arch/powerpc/kernel/exceptions-64s.S | 27 ++++++-
arch/powerpc/platforms/powernv/opal.c | 130 ++++++++++++++++++++++++++++++++
arch/powerpc/platforms/powernv/setup.c | 1 +
6 files changed, 174 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 9bb0efd..fca611b 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -436,6 +436,8 @@ extern void opal_get_rtc_time(struct rtc_time *tm);
extern unsigned long opal_get_boot_time(void);
extern void opal_nvram_init(void);
+extern int opal_machine_check(struct pt_regs *regs);
+
#endif /* __ASSEMBLY__ */
#endif /* __OPAL_H */
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 516bfb3..17722c7 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -43,6 +43,7 @@ extern unsigned int debug_smp_processor_id(void); /* from linux/smp.h */
#define get_slb_shadow() (get_paca()->slb_shadow_ptr)
struct task_struct;
+struct opal_machine_check_event;
/*
* Defines the layout of the paca.
@@ -135,6 +136,13 @@ struct paca_struct {
u8 io_sync; /* writel() needs spin_unlock sync */
u8 irq_work_pending; /* IRQ_WORK interrupt while soft-disable */
+#ifdef CONFIG_PPC_POWERNV
+ /* Pointer to OPAL machine check event structure set by the
+ * early exception handler for use by high level C handler
+ */
+ struct opal_machine_check_event *opal_mc_evt;
+#endif
+
/* Stuff for accurate time accounting */
u64 user_time; /* accumulated usermode TB ticks */
u64 system_time; /* accumulated system TB ticks */
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 5f078bc..536ffa8 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -48,6 +48,9 @@
#ifdef CONFIG_PPC_ISERIES
#include <asm/iseries/alpaca.h>
#endif
+#ifdef CONFIG_PPC_POWERNV
+#include <asm/opal.h>
+#endif
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_GUEST)
#include <linux/kvm_host.h>
#endif
@@ -609,5 +612,12 @@ int main(void)
arch.timing_last_enter.tv32.tbl));
#endif
+#ifdef CONFIG_PPC_POWERNV
+ DEFINE(OPAL_MC_GPR3, offsetof(struct opal_machine_check_event, gpr3));
+ DEFINE(OPAL_MC_SRR0, offsetof(struct opal_machine_check_event, srr0));
+ DEFINE(OPAL_MC_SRR1, offsetof(struct opal_machine_check_event, srr1));
+ DEFINE(PACA_OPAL_MC_EVT, offsetof(struct paca_struct, opal_mc_evt));
+#endif
+
return 0;
}
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 41b02c7..d51458f 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1143,7 +1143,7 @@ _GLOBAL(do_stab_bolted)
rfid
b . /* prevent speculative execution */
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
/*
* Data area reserved for FWNMI option.
* This address (0x7000) is fixed by the RPA.
@@ -1151,7 +1151,7 @@ _GLOBAL(do_stab_bolted)
.= 0x7000
.globl fwnmi_data_area
fwnmi_data_area:
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
/* iSeries does not use the FWNMI stuff, so it is safe to put
* this here, even if we later allow kernels that will boot on
@@ -1176,9 +1176,12 @@ xLparMap:
#endif /* CONFIG_PPC_ISERIES */
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
+ /* pseries and powernv need to keep the whole page from
+ * 0x7000 to 0x8000 free for use by the firmware
+ */
. = 0x8000
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
/*
* Space for CPU0's segment table.
@@ -1193,3 +1196,19 @@ xLparMap:
.globl initial_stab
initial_stab:
.space 4096
+#ifdef CONFIG_PPC_POWERNV
+_GLOBAL(opal_mc_secondary_handler)
+ HMT_MEDIUM
+ SET_SCRATCH0(r13)
+ GET_PACA(r13)
+ clrldi r3,r3,2
+ tovirt(r3,r3)
+ std r3,PACA_OPAL_MC_EVT(r13)
+ ld r13,OPAL_MC_SRR0(r3)
+ mtspr SPRN_SRR0,r13
+ ld r13,OPAL_MC_SRR1(r3)
+ mtspr SPRN_SRR1,r13
+ ld r3,OPAL_MC_GPR3(r3)
+ GET_SCRATCH0(r13)
+ b machine_check_pSeries
+#endif /* CONFIG_PPC_POWERNV */
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 5a598ca..aaa0dba 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -27,12 +27,14 @@ struct opal {
static struct device_node *opal_node;
static DEFINE_SPINLOCK(opal_write_lock);
+extern u64 opal_mc_secondary_handler[];
int __init early_init_dt_scan_opal(unsigned long node,
const char *uname, int depth, void *data)
{
const void *basep, *entryp;
unsigned long basesz, entrysz;
+ u64 glue;
if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
return 0;
@@ -59,6 +61,19 @@ int __init early_init_dt_scan_opal(unsigned long node,
printk("OPAL V1 detected !\n");
}
+ /* Hookup some exception handlers. We use the fwnmi area at 0x7000
+ * to provide the glue space to OPAL
+ */
+ glue = 0x7000;
+ opal_register_exception_handler(OPAL_MACHINE_CHECK_HANDLER,
+ __pa(opal_mc_secondary_handler[0]),
+ glue);
+ glue += 128;
+ opal_register_exception_handler(OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
+ 0, glue);
+ glue += 128;
+ opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
+
return 1;
}
@@ -136,6 +151,121 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
return written;
}
+int opal_machine_check(struct pt_regs *regs)
+{
+ struct opal_machine_check_event *opal_evt = get_paca()->opal_mc_evt;
+ struct opal_machine_check_event evt;
+ const char *level, *sevstr, *subtype;
+ static const char *opal_mc_ue_types[] = {
+ "Indeterminate",
+ "Instruction fetch",
+ "Page table walk ifetch",
+ "Load/Store",
+ "Page table walk Load/Store",
+ };
+ static const char *opal_mc_slb_types[] = {
+ "Indeterminate",
+ "Parity",
+ "Multihit",
+ };
+ static const char *opal_mc_erat_types[] = {
+ "Indeterminate",
+ "Parity",
+ "Multihit",
+ };
+ static const char *opal_mc_tlb_types[] = {
+ "Indeterminate",
+ "Parity",
+ "Multihit",
+ };
+
+ /* Copy the event structure and release the original */
+ evt = *opal_evt;
+ opal_evt->in_use = 0;
+
+ /* Print things out */
+ if (evt.version != OpalMCE_V1) {
+ pr_err("Machine Check Exception, Unknown event version %d !\n",
+ evt.version);
+ return 0;
+ }
+ switch(evt.severity) {
+ case OpalMCE_SEV_NO_ERROR:
+ level = KERN_INFO;
+ sevstr = "Harmless";
+ break;
+ case OpalMCE_SEV_WARNING:
+ level = KERN_WARNING;
+ sevstr = "";
+ break;
+ case OpalMCE_SEV_ERROR_SYNC:
+ level = KERN_ERR;
+ sevstr = "Severe";
+ break;
+ case OpalMCE_SEV_FATAL:
+ default:
+ level = KERN_ERR;
+ sevstr = "Fatal";
+ break;
+ }
+
+ printk("%s%s Machine check interrupt [%s]\n", level, sevstr,
+ evt.disposition == OpalMCE_DISPOSITION_RECOVERED ?
+ "Recovered" : "[Not recovered");
+ printk("%s Initiator: %s\n", level,
+ evt.initiator == OpalMCE_INITIATOR_CPU ? "CPU" : "Unknown");
+ switch(evt.error_type) {
+ case OpalMCE_ERROR_TYPE_UE:
+ subtype = evt.u.ue_error.ue_error_type <
+ ARRAY_SIZE(opal_mc_ue_types) ?
+ opal_mc_ue_types[evt.u.ue_error.ue_error_type]
+ : "Unknown";
+ printk("%s Error type: UE [%s]\n", level, subtype);
+ if (evt.u.ue_error.effective_address_provided)
+ printk("%s Effective address: %016llx\n",
+ level, evt.u.ue_error.effective_address);
+ if (evt.u.ue_error.physical_address_provided)
+ printk("%s Physial address: %016llx\n",
+ level, evt.u.ue_error.physical_address);
+ break;
+ case OpalMCE_ERROR_TYPE_SLB:
+ subtype = evt.u.slb_error.slb_error_type <
+ ARRAY_SIZE(opal_mc_slb_types) ?
+ opal_mc_slb_types[evt.u.slb_error.slb_error_type]
+ : "Unknown";
+ printk("%s Error type: SLB [%s]\n", level, subtype);
+ if (evt.u.slb_error.effective_address_provided)
+ printk("%s Effective address: %016llx\n",
+ level, evt.u.slb_error.effective_address);
+ break;
+ case OpalMCE_ERROR_TYPE_ERAT:
+ subtype = evt.u.erat_error.erat_error_type <
+ ARRAY_SIZE(opal_mc_erat_types) ?
+ opal_mc_erat_types[evt.u.erat_error.erat_error_type]
+ : "Unknown";
+ printk("%s Error type: ERAT [%s]\n", level, subtype);
+ if (evt.u.erat_error.effective_address_provided)
+ printk("%s Effective address: %016llx\n",
+ level, evt.u.erat_error.effective_address);
+ break;
+ case OpalMCE_ERROR_TYPE_TLB:
+ subtype = evt.u.tlb_error.tlb_error_type <
+ ARRAY_SIZE(opal_mc_tlb_types) ?
+ opal_mc_tlb_types[evt.u.tlb_error.tlb_error_type]
+ : "Unknown";
+ printk("%s Error type: TLB [%s]\n", level, subtype);
+ if (evt.u.tlb_error.effective_address_provided)
+ printk("%s Effective address: %016llx\n",
+ level, evt.u.tlb_error.effective_address);
+ break;
+ default:
+ case OpalMCE_ERROR_TYPE_UNKNOWN:
+ printk("%s Error type: Unknown\n", level);
+ break;
+ }
+ return evt.severity == OpalMCE_SEV_FATAL ? 0 : 1;
+}
+
static irqreturn_t opal_interrupt(int irq, void *data)
{
uint64_t events;
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index 4a2b2e2..f0242f3 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -141,6 +141,7 @@ static void __init pnv_setup_machdep_opal(void)
ppc_md.restart = pnv_restart;
ppc_md.power_off = pnv_power_off;
ppc_md.halt = pnv_halt;
+ ppc_md.machine_check_exception = opal_machine_check;
}
#ifdef CONFIG_PPC_POWERNV_RTAS
--
1.7.4.1
next prev parent reply other threads:[~2011-09-20 3:46 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-20 3:44 [PATCH 01/20] powerpc/udbg: Fix Kconfig entry for avoiding 44x early debug with KVM Benjamin Herrenschmidt
2011-09-20 3:44 ` [PATCH 02/20] powerpc/smp: More generic support for "soft hotplug" Benjamin Herrenschmidt
2011-09-20 3:44 ` [PATCH 03/20] powerpc/pci: Call pcie_bus_configure_settings() Benjamin Herrenschmidt
2011-09-20 3:44 ` [PATCH 04/20] powerpc/powernv: Don't clobber r9 in relative_toc() Benjamin Herrenschmidt
2011-09-20 3:44 ` [PATCH 05/20] powerpc: Add skeleton PowerNV platform Benjamin Herrenschmidt
2011-09-20 3:44 ` [PATCH 06/20] of: Change logic to overwrite cmd_line with CONFIG_CMDLINE Benjamin Herrenschmidt
2011-09-20 4:30 ` Grant Likely
2011-09-20 4:37 ` Benjamin Herrenschmidt
2011-09-20 4:45 ` Grant Likely
2011-09-20 3:44 ` [PATCH 07/20] powerpc/powernv: Add CPU hotplug support Benjamin Herrenschmidt
2011-09-20 3:44 ` [PATCH 08/20] powerpc/powernv: Add OPAL takeover from PowerVM Benjamin Herrenschmidt
2011-09-20 3:44 ` [PATCH 09/20] powerpc/powernv: Get kernel command line accross OPAL takeover Benjamin Herrenschmidt
2011-09-20 3:44 ` [PATCH 10/20] powerpc/powernv: Basic support for OPAL Benjamin Herrenschmidt
2011-09-20 3:44 ` [PATCH 11/20] powerpc/powernv: Add support for instanciating OPAL v2 from Open Firmware Benjamin Herrenschmidt
2011-09-20 3:44 ` [PATCH 12/20] powerpc/powernv: Support for OPAL console Benjamin Herrenschmidt
2011-09-20 3:45 ` [PATCH 13/20] powerpc/powernv: Hookup reboot and poweroff functions Benjamin Herrenschmidt
2011-09-20 3:45 ` [PATCH 14/20] powerpc/powernv: Add RTC and NVRAM support plus RTAS fallbacks Benjamin Herrenschmidt
2011-09-20 3:45 ` [PATCH 15/20] powerpc/powernv: Add OPAL ICS backend Benjamin Herrenschmidt
2011-09-20 3:45 ` [PATCH 16/20] powerpc/powernv: Register and handle OPAL interrupts Benjamin Herrenschmidt
2011-09-20 3:45 ` Benjamin Herrenschmidt [this message]
2011-09-20 3:45 ` [PATCH 18/20] powerpc/powernv: Add support for p5ioc2 PCI-X and PCIe Benjamin Herrenschmidt
2011-09-20 3:45 ` [PATCH 19/20] powerpc/powernv: Implement MSI support for p5ioc2 PCIe Benjamin Herrenschmidt
2011-09-20 3:45 ` [PATCH 20/20] powerpc/powernv: Handle PCI-X/PCIe reset delay Benjamin Herrenschmidt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1316490307-28030-17-git-send-email-benh@kernel.crashing.org \
--to=benh@kernel.crashing.org \
--cc=linuxppc-dev@ozlabs.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).