direct-io.hg

changeset 11501:2ebf55e419c9

[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@watson.ibm.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Jimi Xenidis <jimix@watson.ibm.com>
date Thu Sep 07 21:46:33 2006 -0400 (2006-09-07)
parents e7c55ba4de2e
children a22a7797e0ba
files xen/arch/powerpc/powerpc64/exceptions.S xen/arch/powerpc/powerpc64/io.S xen/arch/powerpc/powerpc64/ppc970.c xen/include/asm-powerpc/percpu.h xen/include/asm-powerpc/powerpc64/ppc970-hid.h xen/include/asm-powerpc/processor.h
line diff
     1.1 --- a/xen/arch/powerpc/powerpc64/exceptions.S	Thu Sep 07 12:09:18 2006 -0400
     1.2 +++ b/xen/arch/powerpc/powerpc64/exceptions.S	Thu Sep 07 21:46:33 2006 -0400
     1.3 @@ -1,27 +1,30 @@
     1.4  /*
     1.5 - * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation
     1.6 - *
     1.7   * This program is free software; you can redistribute it and/or modify
     1.8   * it under the terms of the GNU General Public License as published by
     1.9   * the Free Software Foundation; either version 2 of the License, or
    1.10   * (at your option) any later version.
    1.11 - * 
    1.12 + *
    1.13   * This program is distributed in the hope that it will be useful,
    1.14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.16   * GNU General Public License for more details.
    1.17 - * 
    1.18 + *
    1.19   * You should have received a copy of the GNU General Public License
    1.20   * along with this program; if not, write to the Free Software
    1.21 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    1.22 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    1.23 + *
    1.24 + * Copyright (C) IBM Corp. 2005, 2006
    1.25   *
    1.26 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
    1.27 + *          Hollis Blanchard <hollisb@us.ibm.com>
    1.28   */
    1.29 -
    1.30 + 
    1.31  #include <asm/config.h>
    1.32  #include <asm/asm-offsets.h>
    1.33  #include <asm/reg_defs.h>
    1.34  #include <asm/msr.h>
    1.35  #include <asm/processor.h>
    1.36 +#include <asm/percpu.h>
    1.37  
    1.38  .macro SAVE_GPR regno uregs
    1.39  std \regno, (UREGS_gprs + GPR_WIDTH * \regno)(\uregs)
    1.40 @@ -190,6 +193,14 @@ zero:
    1.41      li r0, 0x0 /* exception vector for GDB stub */
    1.42      bctr
    1.43  
    1.44 +    /* The following byte array is where any per-CPU state flags 
    1.45 +     * that can be be used across interrupts.  Currently it is only used
    1.46 +     * to track Cache Inhibited Mode when a Machine Check occurs. */
    1.47 +     /* NOTE: This array is indexed by PIR NOT CPUID */
    1.48 +    . = MCK_CPU_STAT_BASE
    1.49 +    .space NR_CPUS
    1.50 +    . = MCK_GOOD_HID4
    1.51 +    .quad 0        
    1.52      . = 0x100 # System Reset
    1.53  ex_reset:
    1.54      /* XXX thread initialization */
    1.55 @@ -200,8 +211,19 @@ ex_reset:
    1.56  
    1.57      . = 0x200 # Machine Check
    1.58  ex_machcheck:
    1.59 +    /* Restore HID4 to a known state early, we do not recover from
    1.60 +     * machine check yet, but when we do we shoul dbe able to restore
    1.61 +     * HID4 to it proper value */
    1.62 +    mtspr SPRN_HSPRG1, r13
    1.63 +    ld r13, MCK_GOOD_HID4(0)
    1.64 +    sync
    1.65 +    mtspr SPRN_HID4, r13
    1.66 +    isync
    1.67 +    /* Hopefully we don't have to worry about the ERAT */
    1.68 +    mfspr r13, SPRN_HSPRG1
    1.69 +    /* and now back to our regularly schedualed program */
    1.70      GET_STACK r13 SPRN_SRR1
    1.71 -    EXCEPTION_HEAD r13 ex_program_continued
    1.72 +    EXCEPTION_HEAD r13 ex_machcheck_continued
    1.73      li r0, 0x200 /* exception vector for GDB stub */
    1.74      bctr
    1.75  
    1.76 @@ -337,6 +359,10 @@ exception_vectors_end:
    1.77      b .                         /* prevent speculative icache fetch */
    1.78  .endm
    1.79  
    1.80 +/* Not a whole lot just yet */
    1.81 +ex_machcheck_continued:
    1.82 +
    1.83 +
    1.84  /* We enter with the exception number in r0. The EXCEPTION_SAVE_STATE macro
    1.85   * clobbers r0 though, so we have to move it around a little bit. Not ideal,
    1.86   * but hopefully program exception is not performance-critical... Maybe there's
     2.1 --- a/xen/arch/powerpc/powerpc64/io.S	Thu Sep 07 12:09:18 2006 -0400
     2.2 +++ b/xen/arch/powerpc/powerpc64/io.S	Thu Sep 07 21:46:33 2006 -0400
     2.3 @@ -1,23 +1,27 @@
     2.4  /*
     2.5 - * Copyright (C) 2005 Hollis Blanchard <hollisb@us.ibm.com>, IBM Corporation
     2.6 - *
     2.7   * This program is free software; you can redistribute it and/or modify
     2.8   * it under the terms of the GNU General Public License as published by
     2.9   * the Free Software Foundation; either version 2 of the License, or
    2.10   * (at your option) any later version.
    2.11 - * 
    2.12 + *
    2.13   * This program is distributed in the hope that it will be useful,
    2.14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.16   * GNU General Public License for more details.
    2.17 - * 
    2.18 + *
    2.19   * You should have received a copy of the GNU General Public License
    2.20   * along with this program; if not, write to the Free Software
    2.21 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    2.22 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    2.23 + *
    2.24 + * Copyright (C) IBM Corp. 2005, 2006
    2.25 + *
    2.26 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
    2.27 + *          Hollis Blanchard <hollisb@us.ibm.com>
    2.28   */
    2.29  
    2.30  #include <asm/config.h>
    2.31  #include <asm/processor.h>
    2.32 +#include <asm/percpu.h>
    2.33  
    2.34  /* Xen runs in real mode (i.e. untranslated, MMU disabled). This avoids TLB
    2.35   * flushes and also makes it easy to access all domains' memory. However, on
    2.36 @@ -54,6 +58,12 @@
    2.37  	sync
    2.38  	mtspr SPRN_HID4, r5
    2.39  	isync
    2.40 +
    2.41 +	/* Mark the processor as "in CI mode" */
    2.42 +	mfspr r5, SPRN_PIR
    2.43 +	li r6, MCK_CPU_STAT_CI
    2.44 +	stb r6, MCK_CPU_STAT_BASE(r5)
    2.45 +	sync
    2.46  .endm
    2.47  
    2.48  .macro ENABLE_DCACHE addr
    2.49 @@ -63,6 +73,12 @@
    2.50  	mtspr SPRN_HID4, r9
    2.51  	isync
    2.52  
    2.53 +	/* Mark the processor as "out of CI mode" */
    2.54 +	mfspr r5, SPRN_PIR
    2.55 +	li r6, 0
    2.56 +	stb r6, MCK_CPU_STAT_BASE(r5)
    2.57 +	sync
    2.58 +	
    2.59  	/* re-enable interrupts */
    2.60  	mtmsr r8
    2.61  .endm
     3.1 --- a/xen/arch/powerpc/powerpc64/ppc970.c	Thu Sep 07 12:09:18 2006 -0400
     3.2 +++ b/xen/arch/powerpc/powerpc64/ppc970.c	Thu Sep 07 21:46:33 2006 -0400
     3.3 @@ -103,20 +103,29 @@ int cpu_io_mfn(ulong mfn)
     3.4      return 0;
     3.5  }
     3.6  
     3.7 +#ifdef DEBUG
     3.8 +static void scom_init(void)
     3.9 +{
    3.10 +    write_scom(SCOM_AMCS_AND_MASK, 0);
    3.11 +    
    3.12 +    printk("scom MCKE: 0x%016lx\n", read_scom(SCOM_CMCE));
    3.13 +    write_scom(SCOM_CMCE, ~0UL);
    3.14 +    printk("scom MCKE: 0x%016lx\n", read_scom(SCOM_CMCE));
    3.15 +}
    3.16 +#else
    3.17 +#define scom_init()
    3.18 +#endif
    3.19 +
    3.20  static u64 cpu0_hids[6];
    3.21  static u64 cpu0_hior;
    3.22  
    3.23  void cpu_initialize(int cpuid)
    3.24  {
    3.25 -    ulong r1, r2;
    3.26      union hid0 hid0;
    3.27      union hid1 hid1;
    3.28      union hid4 hid4;
    3.29      union hid5 hid5;
    3.30  
    3.31 -    __asm__ __volatile__ ("mr %0, 1" : "=r" (r1));
    3.32 -    __asm__ __volatile__ ("mr %0, 2" : "=r" (r2));
    3.33 -
    3.34      if (cpuid == 0) {
    3.35          /* we can assume that these are sane to start with.  We
    3.36           * _do_not_ store the results in case we want to mess with them
    3.37 @@ -139,6 +148,19 @@ void cpu_initialize(int cpuid)
    3.38  
    3.39      mthsprg0((ulong)parea); /* now ready for exceptions */
    3.40  
    3.41 +    printk("CPU[PIR:%u IPI:%u Logical:%u] Hello World!\n",
    3.42 +           mfpir(), raw_smp_processor_id(), smp_processor_id());
    3.43 +
    3.44 +#ifdef DEBUG
    3.45 +    {
    3.46 +        ulong r1, r2;
    3.47 +
    3.48 +        asm volatile ("mr %0, 1" : "=r" (r1));
    3.49 +        asm volatile ("mr %0, 2" : "=r" (r2));
    3.50 +        printk("  SP = %lx TOC = %lx\n",  r1, r2);
    3.51 +    }
    3.52 +#endif
    3.53 +
    3.54      /* Set decrementers for 1 second to keep them out of the way during
    3.55       * intialization. */
    3.56      /* XXX make tickless */
    3.57 @@ -147,11 +169,12 @@ void cpu_initialize(int cpuid)
    3.58  
    3.59      hid0.bits.nap = 1;      /* NAP */
    3.60      hid0.bits.dpm = 1;      /* Dynamic Power Management */
    3.61 -    hid0.bits.nhr = 0;      /* ! Not Hard Reset */
    3.62 +    hid0.bits.nhr = 1;      /* Not Hard Reset */
    3.63      hid0.bits.hdice_en = 1; /* enable HDEC */
    3.64      hid0.bits.en_therm = 0; /* ! Enable ext thermal ints */
    3.65      /* onlu debug Xen should do this */
    3.66 -    hid0.bits.en_attn = 1; /* Enable attn instruction */
    3.67 +    hid0.bits.en_attn = 1;  /* Enable attn instruction */
    3.68 +    hid0.bits.en_mck = 1;   /* Enable external machine check interrupts */
    3.69  
    3.70  #ifdef SERIALIZE
    3.71      hid0.bits.one_ppc = 1;
    3.72 @@ -162,9 +185,6 @@ void cpu_initialize(int cpuid)
    3.73      hid0.bits.ser-gp = 1;
    3.74  #endif
    3.75  
    3.76 -    printk("CPU #%d: Hello World! SP = %lx TOC = %lx HID0 = %lx\n", 
    3.77 -           smp_processor_id(), r1, r2, hid0.word);
    3.78 -
    3.79      mthid0(hid0.word);
    3.80  
    3.81      hid1.bits.bht_pm = 7; /* branch history table prediction mode */
    3.82 @@ -188,6 +208,7 @@ void cpu_initialize(int cpuid)
    3.83      hid4.bits.lg_pg_dis = 0;    /* make sure we enable large pages */
    3.84      mthid4(hid4.word);
    3.85  
    3.86 +    hid5.bits.DC_mck = 1; /* Machine check enabled for dcache errors */
    3.87      hid5.bits.DCBZ_size = 0; /* make dcbz size 32 bytes */
    3.88      hid5.bits.DCBZ32_ill = 0; /* make dzbz 32byte illeagal */
    3.89      mthid5(hid5.word);
    3.90 @@ -200,12 +221,27 @@ void cpu_initialize(int cpuid)
    3.91             mfhid0(), mfhid1(), mfhid4(), mfhid5());
    3.92  #endif
    3.93  
    3.94 +    /* Make sure firmware has not left this dirty */
    3.95      mthior(cpu0_hior);
    3.96  
    3.97 +    /* some machine check goodness */
    3.98 +    /* save this for checkstop processing */
    3.99 +    if (cpuid == 0)
   3.100 +        *mck_good_hid4 = hid4.word;
   3.101 +
   3.102 +    if (mfpir() > NR_CPUS)
   3.103 +        panic("we do not expect a processor to have a PIR (%u) "
   3.104 +              "to be larger that NR_CPUS(%u)\n",
   3.105 +              mfpir(), NR_CPUS);
   3.106 +
   3.107 +    scom_init();
   3.108 +
   3.109 +    /* initialize the SLB */
   3.110  #ifdef DEBUG
   3.111      dump_segments(1);
   3.112  #endif
   3.113      flush_segments();
   3.114 +    local_flush_tlb();
   3.115  }
   3.116  
   3.117  void cpu_init_vcpu(struct vcpu *v)
   3.118 @@ -252,6 +288,9 @@ int cpu_machinecheck(struct cpu_user_reg
   3.119          recover = 1;
   3.120  
   3.121      printk("MACHINE CHECK: %s Recoverable\n", recover ? "IS": "NOT");
   3.122 +    if (mck_cpu_stats[mfpir()] != 0)
   3.123 +        printk("While in CI IO\n");
   3.124 +
   3.125      printk("SRR1: 0x%016lx\n", regs->msr);
   3.126      if (regs->msr & MCK_SRR1_INSN_FETCH_UNIT)
   3.127          printk("42: Exception caused by Instruction Fetch Unit (IFU) "
     4.1 --- a/xen/include/asm-powerpc/percpu.h	Thu Sep 07 12:09:18 2006 -0400
     4.2 +++ b/xen/include/asm-powerpc/percpu.h	Thu Sep 07 21:46:33 2006 -0400
     4.3 @@ -6,6 +6,20 @@
     4.4  #define PERCPU_SHIFT 12
     4.5  #define PERCPU_SIZE  (1UL << PERCPU_SHIFT)
     4.6  
     4.7 +/* We care out NR_CPUS bytes below the reset vector (0x100) so we can
     4.8 + * track per-cpu state that we wish we had a register for. Currently
     4.9 + * it is only used to track Cache Inhibited Mode when a Machine Check
    4.10 + * occurs. */
    4.11 +/* NOTE: This array is indexed by PIR NOT CPUID */
    4.12 +#define MCK_GOOD_HID4 (0x100 - 8)
    4.13 +#define MCK_CPU_STAT_BASE (MCK_GOOD_HID4 - NR_CPUS) /* accomodate a hid4 */
    4.14 +/* Currently, the only state we track, so lets make it easy */
    4.15 +#define MCK_CPU_STAT_CI -1
    4.16 +
    4.17 +#ifndef __ASSEMBLY__
    4.18 +#define mck_cpu_stats ((char *)MCK_CPU_STAT_BASE)
    4.19 +#define mck_good_hid4 ((ulong *)MCK_GOOD_HID4)
    4.20 +
    4.21  /* Separate out the type, so (int[3], foo) works. */
    4.22  #define DEFINE_PER_CPU(type, name)                      \
    4.23      __attribute__((__section__(".data.percpu")))        \
    4.24 @@ -18,5 +32,5 @@
    4.25      (per_cpu(var, smp_processor_id()))
    4.26  
    4.27  #define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name
    4.28 -
    4.29 +#endif  /* __ASSEMBLY__ */
    4.30  #endif /* __PPC_PERCPU_H__ */
     5.1 --- a/xen/include/asm-powerpc/powerpc64/ppc970-hid.h	Thu Sep 07 12:09:18 2006 -0400
     5.2 +++ b/xen/include/asm-powerpc/powerpc64/ppc970-hid.h	Thu Sep 07 21:46:33 2006 -0400
     5.3 @@ -158,4 +158,85 @@ union hid5 {
     5.4  #define MCK_DSISR_TLB_PAR           0x00000400 /* 21 */
     5.5  #define MCK_DSISR_SLB_PAR           0x00000100 /* 23 */
     5.6  
     5.7 +#define SPRN_SCOMC 276
     5.8 +#define SPRN_SCOMD 277
     5.9 +
    5.10 +static inline void mtscomc(ulong scomc)
    5.11 +{
    5.12 +    __asm__ __volatile__ ("mtspr %1, %0" : : "r" (scomc), "i"(SPRN_SCOMC));
    5.13 +}
    5.14 +
    5.15 +static inline ulong mfscomc(void)
    5.16 +{
    5.17 +    ulong scomc;
    5.18 +    __asm__ __volatile__ ("mfspr %0, %1" : "=r" (scomc): "i"(SPRN_SCOMC));
    5.19 +    return scomc;
    5.20 +}
    5.21 +
    5.22 +static inline void mtscomd(ulong scomd)
    5.23 +{
    5.24 +    __asm__ __volatile__ ("mtspr %1, %0" : : "r" (scomd), "i"(SPRN_SCOMD));
    5.25 +}
    5.26 +
    5.27 +static inline ulong mfscomd(void)
    5.28 +{
    5.29 +    ulong scomd;
    5.30 +    __asm__ __volatile__ ("mfspr %0, %1" : "=r" (scomd): "i"(SPRN_SCOMD));
    5.31 +    return scomd;
    5.32 +}
    5.33 +
    5.34 +union scomc {
    5.35 +    struct scomc_bits {
    5.36 +        ulong _reserved_0_31: 32;
    5.37 +        ulong addr:           16;
    5.38 +        ulong RW:              1;
    5.39 +        ulong _reserved_49_55: 7;
    5.40 +        ulong _reserved_56_57: 2;
    5.41 +        ulong addr_error:      1;
    5.42 +        ulong iface_error:     1;
    5.43 +        ulong disabled:        1;
    5.44 +        ulong _reserved_61_62: 2;
    5.45 +        ulong failure:         1;
    5.46 +    } bits;
    5.47 +    ulong word;
    5.48 +};
    5.49 +
    5.50 +
    5.51 +static inline ulong read_scom(ulong addr)
    5.52 +{
    5.53 +    union scomc c;
    5.54 +    ulong d;
    5.55 +
    5.56 +    c.word = 0;
    5.57 +    c.bits.addr = addr;
    5.58 +    c.bits.RW = 0;
    5.59 +
    5.60 +    mtscomc(c.word);
    5.61 +    d = mfscomd();
    5.62 +    c.word = mfscomc();
    5.63 +    if (c.bits.failure)
    5.64 +        panic("scom status: 0x%016lx\n", c.word);
    5.65 +
    5.66 +    return d;
    5.67 +}
    5.68 +
    5.69 +static inline void write_scom(ulong addr, ulong val)
    5.70 +{
    5.71 +    union scomc c;
    5.72 +
    5.73 +    c.word = 0;
    5.74 +    c.bits.addr = addr;
    5.75 +    c.bits.RW = 0;
    5.76 +
    5.77 +    mtscomd(val);
    5.78 +    mtscomc(c.word);
    5.79 +    c.word = mfscomc();
    5.80 +    if (c.bits.failure)
    5.81 +        panic("scom status: 0x%016lx\n", c.word);
    5.82 +}
    5.83 +
    5.84 +#define SCOM_AMCS_REG      0x022601
    5.85 +#define SCOM_AMCS_AND_MASK 0x022700
    5.86 +#define SCOM_AMCS_OR_MASK  0x022800
    5.87 +#define SCOM_CMCE          0x030901
    5.88  #endif
     6.1 --- a/xen/include/asm-powerpc/processor.h	Thu Sep 07 12:09:18 2006 -0400
     6.2 +++ b/xen/include/asm-powerpc/processor.h	Thu Sep 07 21:46:33 2006 -0400
     6.3 @@ -84,6 +84,13 @@ static inline void nop(void) {
     6.4  }
     6.5  #define cpu_relax() nop()
     6.6  
     6.7 +static inline unsigned int mfpir(void)
     6.8 +{
     6.9 +    unsigned int pir;
    6.10 +    __asm__ __volatile__ ("mfspr %0, %1" : "=r" (pir): "i"(SPRN_PIR));
    6.11 +    return pir;
    6.12 +}
    6.13 +
    6.14  static inline unsigned int mftbu(void)
    6.15  {
    6.16      unsigned int tbu;