aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>2014-07-25 00:11:44 +0530
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-07-25 14:10:52 +1000
commite02dd7f7d86f54273a512a4546c716ce659a38c8 (patch)
treea91f8ec4c12eceee44a9a55080313bda273cf15b
parent1096aa250f0043df478e3d182018ff2218e89a4b (diff)
downloadskiboot-e02dd7f7d86f54273a512a4546c716ce659a38c8.zip
skiboot-e02dd7f7d86f54273a512a4546c716ce659a38c8.tar.gz
skiboot-e02dd7f7d86f54273a512a4546c716ce659a38c8.tar.bz2
opal: Move HMI handler to new file core/hmi.c
Move the original hmi handler to new file core/hmi.c. No functionality change, just a code movement and variable name change. Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--core/Makefile.inc2
-rw-r--r--core/exceptions.c48
-rw-r--r--core/hmi.c176
-rw-r--r--include/opal.h5
4 files changed, 187 insertions, 44 deletions
diff --git a/core/Makefile.inc b/core/Makefile.inc
index 843ce05..1068315 100644
--- a/core/Makefile.inc
+++ b/core/Makefile.inc
@@ -5,7 +5,7 @@ CORE_OBJS = relocate.o console.o backtrace.o init.o chip.o mem_region.o
CORE_OBJS += malloc.o lock.o cpu.o utils.o fdt.o opal.o interrupts.o
CORE_OBJS += timebase.o opal-msg.o pci.o pci-opal.o fast-reboot.o
CORE_OBJS += device.o exceptions.o trace.o affinity.o vpd.o
-CORE_OBJS += hostservices.o platform.o nvram.o flash-nvram.o
+CORE_OBJS += hostservices.o platform.o nvram.o flash-nvram.o hmi.o
CORE=core/built-in.o
$(CORE): $(CORE_OBJS:%=core/%)
diff --git a/core/exceptions.c b/core/exceptions.c
index 995ca92..2b2aa6c 100644
--- a/core/exceptions.c
+++ b/core/exceptions.c
@@ -362,50 +362,12 @@ void handle_hmi(struct stack_frame *stack);
void handle_hmi(struct stack_frame *stack)
{
- uint64_t hmer, orig_hmer;
- bool assert = false;
-
- orig_hmer = hmer = mfspr(SPR_HMER);
- printf("HMI: Received HMI interrupt: HMER = 0x%016llx\n", hmer);
- if (hmer & (SPR_HMER_PROC_RECV_DONE
- | SPR_HMER_PROC_RECV_ERROR_MASKED)) {
- hmer &= ~(SPR_HMER_PROC_RECV_DONE
- | SPR_HMER_PROC_RECV_ERROR_MASKED);
- printf("HMI: Processor recovery Done.\n");
- }
- if (hmer & SPR_HMER_PROC_RECV_AGAIN) {
- hmer &= ~SPR_HMER_PROC_RECV_AGAIN;
- printf("HMI: Processor recovery occurred again before"
- "bit2 was cleared\n");
- }
- /* Assert if we see malfunction alert, we can not continue. */
- if (hmer & SPR_HMER_MALFUNCTION_ALERT) {
- hmer &= ~SPR_HMER_MALFUNCTION_ALERT;
- assert = true;
- }
+ uint64_t orig_hmer;
+ int recover;
- /* Assert if we see Hypervisor resource error, we can not continue. */
- if (hmer & SPR_HMER_HYP_RESOURCE_ERR) {
- hmer &= ~SPR_HMER_HYP_RESOURCE_ERR;
- assert = true;
- }
-
- /*
- * Assert for now for all TOD errors. In future we need to decode
- * TFMR and take corrective action wherever required.
- */
- if (hmer & (SPR_HMER_TFAC_ERROR | SPR_HMER_TFMR_PARITY_ERROR)) {
- hmer &= ~(SPR_HMER_TFAC_ERROR | SPR_HMER_TFMR_PARITY_ERROR);
- assert = true;
- }
-
- /*
- * HMER bits are sticky, once set to 1 they remain set to 1 until
- * they are set to 0. Reset the error source bit to 0, otherwise
- * we keep getting HMI interrupt again and again.
- */
- mtspr(SPR_HMER, hmer);
- if (!assert)
+ orig_hmer = mfspr(SPR_HMER);
+ recover = handle_hmi_exception(orig_hmer);
+ if (recover)
return;
/*
diff --git a/core/hmi.c b/core/hmi.c
new file mode 100644
index 0000000..5f6ddd6
--- /dev/null
+++ b/core/hmi.c
@@ -0,0 +1,176 @@
+/* (C) Copyright IBM Corp., 2013 and provided pursuant to the Technology
+ * Licensing Agreement between Google Inc. and International Business
+ * Machines Corporation, IBM License Reference Number AA130103030256 and
+ * confidentiality governed by the Parties’ Mutual Nondisclosure Agreement
+ * number V032404DR, executed by the parties on November 6, 2007, and
+ * Supplement V032404DR-3 dated August 16, 2012 (the “NDA”). */
+#include <skiboot.h>
+#include <opal.h>
+#include <processor.h>
+
+/*
+ * HMER register layout:
+ * +===+==========+============================+========+===================+
+ * |Bit|Name |Description |PowerKVM|Action |
+ * | | | |HMI | |
+ * | | | |enabled | |
+ * | | | |for this| |
+ * | | | |bit ? | |
+ * +===+==========+============================+========+===================+
+ * |0 |malfunctio|A processor core in the |Yes |Raise attn from |
+ * | |n_allert |system has checkstopped | |sapphire resulting |
+ * | | |(failed recovery) and has | |xstop |
+ * | | |requested a CP Sparing | | |
+ * | | |to occur. This is | | |
+ * | | |broadcasted to every | | |
+ * | | |processor in the system | | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |1 |Reserved |reserved |n/a | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |2 |proc_recv_|Processor recovery occurred |Yes |Log message and |
+ * | |done |error-bit in fir not masked | |continue working. |
+ * | | |(see bit 11) | | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |3 |proc_recv_|Processor went through |Yes |Log message and |
+ * | |error_mask|recovery for an error which | |continue working. |
+ * | |ed |is actually masked for | | |
+ * | | |reporting | | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |4 | |Timer facility experienced |Yes |Raise attn from |
+ * | |tfac_error|an error. | |sapphire resulting |
+ * | | |TB, DEC, HDEC, PURR or SPURR| |xstop |
+ * | | |may be corrupted (details in| | |
+ * | | |TFMR) | | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |5 | |TFMR SPR itself is |Yes |Raise attn from |
+ * | |tfmr_parit|corrupted. | |sapphire resulting |
+ * | |y_error |Entire timing facility may | |xstop |
+ * | | |be compromised. | | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |6 |ha_overflo| UPS (Uniterrupted Power |No |N/A |
+ * | |w_warning |System) Overflow indication | | |
+ * | | |indicating that the UPS | | |
+ * | | |DirtyAddrTable has | | |
+ * | | |reached a limit where it | | |
+ * | | |requires PHYP unload support| | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |7 |reserved |reserved |n/a |n/a |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |8 |xscom_fail|An XSCOM operation caused by|No |We handle it by |
+ * | | |a cache inhibited load/store| |manually reading |
+ * | | |from this thread failed. A | |HMER register. |
+ * | | |trap register is | | |
+ * | | |available. | | |
+ * | | | | | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |9 |xscom_done|An XSCOM operation caused by|No |We handle it by |
+ * | | |a cache inhibited load/store| |manually reading |
+ * | | |from this thread completed. | |HMER register. |
+ * | | |If hypervisor | | |
+ * | | |intends to use this bit, it | | |
+ * | | |is responsible for clearing | | |
+ * | | |it before performing the | | |
+ * | | |xscom operation. | | |
+ * | | |NOTE: this bit should always| | |
+ * | | |be masked in HMEER | | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |10 |reserved |reserved |n/a |n/a |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |11 |proc_recv_|Processor recovery occurred |y |Log message and |
+ * | |again |again before bit2 or bit3 | |continue working. |
+ * | | |was cleared | | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |12-|reserved |was temperature sensor |n/a |n/a |
+ * |15 | |passed the critical point on| | |
+ * | | |the way up | | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |16 | |SCOM has set a reserved FIR |No |n/a |
+ * | |scom_fir_h|bit to cause recovery | | |
+ * | |m | | | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |17 |trig_fir_h|Debug trigger has set a |No |n/a |
+ * | |mi |reserved FIR bit to cause | | |
+ * | | |recovery | | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |18 |reserved |reserved |n/a |n/a |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |19 |reserved |reserved |n/a |n/a |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |20 |hyp_resour|A hypervisor resource error |y |Raise attn from |
+ * | |ce_err |occurred: data parity error | |sapphire resulting |
+ * | | |on, SPRC0:3; SPR_Modereg or | |xstop. |
+ * | | |HMEER. | | |
+ * | | |Note: this bit will cause an| | |
+ * | | |check_stop when (HV=1, PR=0 | | |
+ * | | |and EE=0) | | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |21-| |if bit 8 is active, the |No |We handle it by |
+ * |23 |xscom_stat|reason will be detailed in | |Manually reading |
+ * | |us |these bits. see chapter 11.1| |HMER register. |
+ * | | |This bits are information | | |
+ * | | |only and always masked | | |
+ * | | |(mask = '0') | | |
+ * | | |If hypervisor intends to use| | |
+ * | | |this bit, it is responsible | | |
+ * | | |for clearing it before | | |
+ * | | |performing the xscom | | |
+ * | | |operation. | | |
+ * |---+----------+----------------------------+--------+-------------------|
+ * |24-|Not |Not implemented |n/a |n/a |
+ * |63 |implemente| | | |
+ * | |d | | | |
+ * +-- +----------+----------------------------+--------+-------------------+
+ *
+ * Above HMER bits can be enabled/disabled by modifying
+ * SPR_HMEER_HMI_ENABLE_MASK #define in include/processor.h
+ * If you modify support for any of the bits listed above, please make sure
+ * you change the above table to refelct that.
+ *
+ * NOTE: Per Dave Larson, never enable 8,9,21-23
+ */
+
+int handle_hmi_exception(uint64_t hmer)
+{
+ int recover = 1;
+
+ printf("HMI: Received HMI interrupt: HMER = 0x%016llx\n", hmer);
+ if (hmer & (SPR_HMER_PROC_RECV_DONE
+ | SPR_HMER_PROC_RECV_ERROR_MASKED)) {
+ hmer &= ~(SPR_HMER_PROC_RECV_DONE
+ | SPR_HMER_PROC_RECV_ERROR_MASKED);
+ printf("HMI: Processor recovery Done.\n");
+ }
+ if (hmer & SPR_HMER_PROC_RECV_AGAIN) {
+ hmer &= ~SPR_HMER_PROC_RECV_AGAIN;
+ printf("HMI: Processor recovery occurred again before"
+ "bit2 was cleared\n");
+ }
+ /* Assert if we see malfunction alert, we can not continue. */
+ if (hmer & SPR_HMER_MALFUNCTION_ALERT) {
+ hmer &= ~SPR_HMER_MALFUNCTION_ALERT;
+ recover = 0;
+ }
+
+ /* Assert if we see Hypervisor resource error, we can not continue. */
+ if (hmer & SPR_HMER_HYP_RESOURCE_ERR) {
+ hmer &= ~SPR_HMER_HYP_RESOURCE_ERR;
+ recover = 0;
+ }
+
+ /*
+ * Assert for now for all TOD errors. In future we need to decode
+ * TFMR and take corrective action wherever required.
+ */
+ if (hmer & (SPR_HMER_TFAC_ERROR | SPR_HMER_TFMR_PARITY_ERROR)) {
+ hmer &= ~(SPR_HMER_TFAC_ERROR | SPR_HMER_TFMR_PARITY_ERROR);
+ recover = 0;
+ }
+
+ /*
+ * HMER bits are sticky, once set to 1 they remain set to 1 until
+ * they are set to 0. Reset the error source bit to 0, otherwise
+ * we keep getting HMI interrupt again and again.
+ */
+ mtspr(SPR_HMER, hmer);
+ return recover;
+}
diff --git a/include/opal.h b/include/opal.h
index 5c03057..22f6a9f 100644
--- a/include/opal.h
+++ b/include/opal.h
@@ -828,5 +828,10 @@ extern void opal_run_pollers(void);
extern void opal_add_host_sync_notifier(bool (*notify)(void *data), void *data);
extern void opal_del_host_sync_notifier(bool (*notify)(void *data));
+/*
+ * Opal internal function prototype
+ */
+extern int handle_hmi_exception(uint64_t hmer);
+
#endif /* __ASSEMBLY__ */
#endif /* __OPAL_H */