[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [POWERPC][XEN] Track HID4[RM_CI] state for machine check



# HG changeset patch
# User Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
# Node ID 2ebf55e419c917e66cbd5dae804dd05739e1f39e
# Parent  e7c55ba4de2ee6b0c3bd760ef92130a326630917
[POWERPC][XEN] Track HID4[RM_CI] state for machine check

This patch creates a PIR indexed character array so we can note when a
processor is in RM_CI mode.  Machine checks can happen here and we
need to at least report it (and maybe one day) recover from it. Also
some fun with the SCOM.

Signed-off-by: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx>
---
 xen/arch/powerpc/powerpc64/exceptions.S        |   42 ++++++++++--
 xen/arch/powerpc/powerpc64/io.S                |   26 ++++++--
 xen/arch/powerpc/powerpc64/ppc970.c            |   57 ++++++++++++++---
 xen/include/asm-powerpc/percpu.h               |   16 ++++
 xen/include/asm-powerpc/powerpc64/ppc970-hid.h |   81 +++++++++++++++++++++++++
 xen/include/asm-powerpc/processor.h            |    7 ++
 6 files changed, 206 insertions(+), 23 deletions(-)

diff -r e7c55ba4de2e -r 2ebf55e419c9 xen/arch/powerpc/powerpc64/exceptions.S
--- a/xen/arch/powerpc/powerpc64/exceptions.S   Thu Sep 07 12:09:18 2006 -0400
+++ b/xen/arch/powerpc/powerpc64/exceptions.S   Thu Sep 07 21:46:33 2006 -0400
@@ -1,27 +1,30 @@
 /*
- * Copyright (C) 2005 Jimi Xenidis <jimix@xxxxxxxxxxxxxx>, IBM Corporation
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
+ * Copyright (C) IBM Corp. 2005, 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ *          Hollis Blanchard <hollisb@xxxxxxxxxx>
  */
-
+ 
 #include <asm/config.h>
 #include <asm/asm-offsets.h>
 #include <asm/reg_defs.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
+#include <asm/percpu.h>
 
 .macro SAVE_GPR regno uregs
 std \regno, (UREGS_gprs + GPR_WIDTH * \regno)(\uregs)
@@ -190,6 +193,14 @@ zero:
     li r0, 0x0 /* exception vector for GDB stub */
     bctr
 
+    /* The following byte array is where any per-CPU state flags 
+     * that can be be used across interrupts.  Currently it is only used
+     * to track Cache Inhibited Mode when a Machine Check occurs. */
+     /* NOTE: This array is indexed by PIR NOT CPUID */
+    . = MCK_CPU_STAT_BASE
+    .space NR_CPUS
+    . = MCK_GOOD_HID4
+    .quad 0        
     . = 0x100 # System Reset
 ex_reset:
     /* XXX thread initialization */
@@ -200,8 +211,19 @@ ex_reset:
 
     . = 0x200 # Machine Check
 ex_machcheck:
-    GET_STACK r13 SPRN_SRR1
-    EXCEPTION_HEAD r13 ex_program_continued
+    /* Restore HID4 to a known state early, we do not recover from
+     * machine check yet, but when we do we shoul dbe able to restore
+     * HID4 to it proper value */
+    mtspr SPRN_HSPRG1, r13
+    ld r13, MCK_GOOD_HID4(0)
+    sync
+    mtspr SPRN_HID4, r13
+    isync
+    /* Hopefully we don't have to worry about the ERAT */
+    mfspr r13, SPRN_HSPRG1
+    /* and now back to our regularly schedualed program */
+    GET_STACK r13 SPRN_SRR1
+    EXCEPTION_HEAD r13 ex_machcheck_continued
     li r0, 0x200 /* exception vector for GDB stub */
     bctr
 
@@ -336,6 +358,10 @@ exception_vectors_end:
     HRFID
     b .                         /* prevent speculative icache fetch */
 .endm
+
+/* Not a whole lot just yet */
+ex_machcheck_continued:
+
 
 /* We enter with the exception number in r0. The EXCEPTION_SAVE_STATE macro
  * clobbers r0 though, so we have to move it around a little bit. Not ideal,
diff -r e7c55ba4de2e -r 2ebf55e419c9 xen/arch/powerpc/powerpc64/io.S
--- a/xen/arch/powerpc/powerpc64/io.S   Thu Sep 07 12:09:18 2006 -0400
+++ b/xen/arch/powerpc/powerpc64/io.S   Thu Sep 07 21:46:33 2006 -0400
@@ -1,23 +1,27 @@
 /*
- * Copyright (C) 2005 Hollis Blanchard <hollisb@xxxxxxxxxx>, IBM Corporation
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (C) IBM Corp. 2005, 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ *          Hollis Blanchard <hollisb@xxxxxxxxxx>
  */
 
 #include <asm/config.h>
 #include <asm/processor.h>
+#include <asm/percpu.h>
 
 /* Xen runs in real mode (i.e. untranslated, MMU disabled). This avoids TLB
  * flushes and also makes it easy to access all domains' memory. However, on
@@ -54,6 +58,12 @@
        sync
        mtspr SPRN_HID4, r5
        isync
+
+       /* Mark the processor as "in CI mode" */
+       mfspr r5, SPRN_PIR
+       li r6, MCK_CPU_STAT_CI
+       stb r6, MCK_CPU_STAT_BASE(r5)
+       sync
 .endm
 
 .macro ENABLE_DCACHE addr
@@ -63,6 +73,12 @@
        mtspr SPRN_HID4, r9
        isync
 
+       /* Mark the processor as "out of CI mode" */
+       mfspr r5, SPRN_PIR
+       li r6, 0
+       stb r6, MCK_CPU_STAT_BASE(r5)
+       sync
+       
        /* re-enable interrupts */
        mtmsr r8
 .endm
diff -r e7c55ba4de2e -r 2ebf55e419c9 xen/arch/powerpc/powerpc64/ppc970.c
--- a/xen/arch/powerpc/powerpc64/ppc970.c       Thu Sep 07 12:09:18 2006 -0400
+++ b/xen/arch/powerpc/powerpc64/ppc970.c       Thu Sep 07 21:46:33 2006 -0400
@@ -103,19 +103,28 @@ int cpu_io_mfn(ulong mfn)
     return 0;
 }
 
+#ifdef DEBUG
+static void scom_init(void)
+{
+    write_scom(SCOM_AMCS_AND_MASK, 0);
+    
+    printk("scom MCKE: 0x%016lx\n", read_scom(SCOM_CMCE));
+    write_scom(SCOM_CMCE, ~0UL);
+    printk("scom MCKE: 0x%016lx\n", read_scom(SCOM_CMCE));
+}
+#else
+#define scom_init()
+#endif
+
 static u64 cpu0_hids[6];
 static u64 cpu0_hior;
 
 void cpu_initialize(int cpuid)
 {
-    ulong r1, r2;
     union hid0 hid0;
     union hid1 hid1;
     union hid4 hid4;
     union hid5 hid5;
-
-    __asm__ __volatile__ ("mr %0, 1" : "=r" (r1));
-    __asm__ __volatile__ ("mr %0, 2" : "=r" (r2));
 
     if (cpuid == 0) {
         /* we can assume that these are sane to start with.  We
@@ -139,6 +148,19 @@ void cpu_initialize(int cpuid)
 
     mthsprg0((ulong)parea); /* now ready for exceptions */
 
+    printk("CPU[PIR:%u IPI:%u Logical:%u] Hello World!\n",
+           mfpir(), raw_smp_processor_id(), smp_processor_id());
+
+#ifdef DEBUG
+    {
+        ulong r1, r2;
+
+        asm volatile ("mr %0, 1" : "=r" (r1));
+        asm volatile ("mr %0, 2" : "=r" (r2));
+        printk("  SP = %lx TOC = %lx\n",  r1, r2);
+    }
+#endif
+
     /* Set decrementers for 1 second to keep them out of the way during
      * intialization. */
     /* XXX make tickless */
@@ -147,11 +169,12 @@ void cpu_initialize(int cpuid)
 
     hid0.bits.nap = 1;      /* NAP */
     hid0.bits.dpm = 1;      /* Dynamic Power Management */
-    hid0.bits.nhr = 0;      /* ! Not Hard Reset */
+    hid0.bits.nhr = 1;      /* Not Hard Reset */
     hid0.bits.hdice_en = 1; /* enable HDEC */
     hid0.bits.en_therm = 0; /* ! Enable ext thermal ints */
     /* onlu debug Xen should do this */
-    hid0.bits.en_attn = 1; /* Enable attn instruction */
+    hid0.bits.en_attn = 1;  /* Enable attn instruction */
+    hid0.bits.en_mck = 1;   /* Enable external machine check interrupts */
 
 #ifdef SERIALIZE
     hid0.bits.one_ppc = 1;
@@ -162,9 +185,6 @@ void cpu_initialize(int cpuid)
     hid0.bits.ser-gp = 1;
 #endif
 
-    printk("CPU #%d: Hello World! SP = %lx TOC = %lx HID0 = %lx\n", 
-           smp_processor_id(), r1, r2, hid0.word);
-
     mthid0(hid0.word);
 
     hid1.bits.bht_pm = 7; /* branch history table prediction mode */
@@ -188,6 +208,7 @@ void cpu_initialize(int cpuid)
     hid4.bits.lg_pg_dis = 0;    /* make sure we enable large pages */
     mthid4(hid4.word);
 
+    hid5.bits.DC_mck = 1; /* Machine check enabled for dcache errors */
     hid5.bits.DCBZ_size = 0; /* make dcbz size 32 bytes */
     hid5.bits.DCBZ32_ill = 0; /* make dzbz 32byte illeagal */
     mthid5(hid5.word);
@@ -200,12 +221,27 @@ void cpu_initialize(int cpuid)
            mfhid0(), mfhid1(), mfhid4(), mfhid5());
 #endif
 
+    /* Make sure firmware has not left this dirty */
     mthior(cpu0_hior);
 
+    /* some machine check goodness */
+    /* save this for checkstop processing */
+    if (cpuid == 0)
+        *mck_good_hid4 = hid4.word;
+
+    if (mfpir() > NR_CPUS)
+        panic("we do not expect a processor to have a PIR (%u) "
+              "to be larger that NR_CPUS(%u)\n",
+              mfpir(), NR_CPUS);
+
+    scom_init();
+
+    /* initialize the SLB */
 #ifdef DEBUG
     dump_segments(1);
 #endif
     flush_segments();
+    local_flush_tlb();
 }
 
 void cpu_init_vcpu(struct vcpu *v)
@@ -252,6 +288,9 @@ int cpu_machinecheck(struct cpu_user_reg
         recover = 1;
 
     printk("MACHINE CHECK: %s Recoverable\n", recover ? "IS": "NOT");
+    if (mck_cpu_stats[mfpir()] != 0)
+        printk("While in CI IO\n");
+
     printk("SRR1: 0x%016lx\n", regs->msr);
     if (regs->msr & MCK_SRR1_INSN_FETCH_UNIT)
         printk("42: Exception caused by Instruction Fetch Unit (IFU) "
diff -r e7c55ba4de2e -r 2ebf55e419c9 xen/include/asm-powerpc/percpu.h
--- a/xen/include/asm-powerpc/percpu.h  Thu Sep 07 12:09:18 2006 -0400
+++ b/xen/include/asm-powerpc/percpu.h  Thu Sep 07 21:46:33 2006 -0400
@@ -5,6 +5,20 @@
 
 #define PERCPU_SHIFT 12
 #define PERCPU_SIZE  (1UL << PERCPU_SHIFT)
+
+/* We care out NR_CPUS bytes below the reset vector (0x100) so we can
+ * track per-cpu state that we wish we had a register for. Currently
+ * it is only used to track Cache Inhibited Mode when a Machine Check
+ * occurs. */
+/* NOTE: This array is indexed by PIR NOT CPUID */
+#define MCK_GOOD_HID4 (0x100 - 8)
+#define MCK_CPU_STAT_BASE (MCK_GOOD_HID4 - NR_CPUS) /* accomodate a hid4 */
+/* Currently, the only state we track, so lets make it easy */
+#define MCK_CPU_STAT_CI -1
+
+#ifndef __ASSEMBLY__
+#define mck_cpu_stats ((char *)MCK_CPU_STAT_BASE)
+#define mck_good_hid4 ((ulong *)MCK_GOOD_HID4)
 
 /* Separate out the type, so (int[3], foo) works. */
 #define DEFINE_PER_CPU(type, name)                      \
@@ -18,5 +32,5 @@
     (per_cpu(var, smp_processor_id()))
 
 #define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name
-
+#endif  /* __ASSEMBLY__ */
 #endif /* __PPC_PERCPU_H__ */
diff -r e7c55ba4de2e -r 2ebf55e419c9 
xen/include/asm-powerpc/powerpc64/ppc970-hid.h
--- a/xen/include/asm-powerpc/powerpc64/ppc970-hid.h    Thu Sep 07 12:09:18 
2006 -0400
+++ b/xen/include/asm-powerpc/powerpc64/ppc970-hid.h    Thu Sep 07 21:46:33 
2006 -0400
@@ -158,4 +158,85 @@ union hid5 {
 #define MCK_DSISR_TLB_PAR           0x00000400 /* 21 */
 #define MCK_DSISR_SLB_PAR           0x00000100 /* 23 */
 
+#define SPRN_SCOMC 276
+#define SPRN_SCOMD 277
+
+static inline void mtscomc(ulong scomc)
+{
+    __asm__ __volatile__ ("mtspr %1, %0" : : "r" (scomc), "i"(SPRN_SCOMC));
+}
+
+static inline ulong mfscomc(void)
+{
+    ulong scomc;
+    __asm__ __volatile__ ("mfspr %0, %1" : "=r" (scomc): "i"(SPRN_SCOMC));
+    return scomc;
+}
+
+static inline void mtscomd(ulong scomd)
+{
+    __asm__ __volatile__ ("mtspr %1, %0" : : "r" (scomd), "i"(SPRN_SCOMD));
+}
+
+static inline ulong mfscomd(void)
+{
+    ulong scomd;
+    __asm__ __volatile__ ("mfspr %0, %1" : "=r" (scomd): "i"(SPRN_SCOMD));
+    return scomd;
+}
+
+union scomc {
+    struct scomc_bits {
+        ulong _reserved_0_31: 32;
+        ulong addr:           16;
+        ulong RW:              1;
+        ulong _reserved_49_55: 7;
+        ulong _reserved_56_57: 2;
+        ulong addr_error:      1;
+        ulong iface_error:     1;
+        ulong disabled:        1;
+        ulong _reserved_61_62: 2;
+        ulong failure:         1;
+    } bits;
+    ulong word;
+};
+
+
+static inline ulong read_scom(ulong addr)
+{
+    union scomc c;
+    ulong d;
+
+    c.word = 0;
+    c.bits.addr = addr;
+    c.bits.RW = 0;
+
+    mtscomc(c.word);
+    d = mfscomd();
+    c.word = mfscomc();
+    if (c.bits.failure)
+        panic("scom status: 0x%016lx\n", c.word);
+
+    return d;
+}
+
+static inline void write_scom(ulong addr, ulong val)
+{
+    union scomc c;
+
+    c.word = 0;
+    c.bits.addr = addr;
+    c.bits.RW = 0;
+
+    mtscomd(val);
+    mtscomc(c.word);
+    c.word = mfscomc();
+    if (c.bits.failure)
+        panic("scom status: 0x%016lx\n", c.word);
+}
+
+#define SCOM_AMCS_REG      0x022601
+#define SCOM_AMCS_AND_MASK 0x022700
+#define SCOM_AMCS_OR_MASK  0x022800
+#define SCOM_CMCE          0x030901
 #endif
diff -r e7c55ba4de2e -r 2ebf55e419c9 xen/include/asm-powerpc/processor.h
--- a/xen/include/asm-powerpc/processor.h       Thu Sep 07 12:09:18 2006 -0400
+++ b/xen/include/asm-powerpc/processor.h       Thu Sep 07 21:46:33 2006 -0400
@@ -84,6 +84,13 @@ static inline void nop(void) {
 }
 #define cpu_relax() nop()
 
+static inline unsigned int mfpir(void)
+{
+    unsigned int pir;
+    __asm__ __volatile__ ("mfspr %0, %1" : "=r" (pir): "i"(SPRN_PIR));
+    return pir;
+}
+
 static inline unsigned int mftbu(void)
 {
     unsigned int tbu;

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.