1 /*
2  * MCA implementation for AMD CPUs
3  * Copyright (c) 2007-2012 Advanced Micro Devices, Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef X86_MCA_H
20 #define X86_MCA_H
21 
22 #include <public/arch-x86/xen-mca.h>
23 
24 /* The MCA/MCE MSRs should not be used anywhere else.
25  * They are cpu family/model specific and are only for use
26  * in terms of machine check handling.
27  * So we define them here rather in <asm/msr.h>.
28  */
29 
30 
31 /* Bitfield of the MSR_IA32_MCG_CAP register */
32 #define MCG_CAP_COUNT           0x00000000000000ffULL
33 #define MCG_CTL_P               (1ULL<<8)
34 #define MCG_EXT_P               (1ULL<<9)  /* Intel specific */
35 #define MCG_CMCI_P              (1ULL<<10) /* Intel specific */
36 #define MCG_TES_P               (1ULL<<11) /* Intel specific */
37 #define MCG_EXT_CNT             16         /* Intel specific */
38 #define MCG_SER_P               (1ULL<<24) /* Intel specific */
39 #define MCG_LMCE_P              (1ULL<<27) /* Intel specific */
40 /* Other bits are reserved */
41 
42 /* Bitfield of the MSR_IA32_MCG_STATUS register */
43 #define MCG_STATUS_RIPV         0x0000000000000001ULL
44 #define MCG_STATUS_EIPV         0x0000000000000002ULL
45 #define MCG_STATUS_MCIP         0x0000000000000004ULL
46 #define MCG_STATUS_LMCE         0x0000000000000008ULL  /* Intel specific */
47 /* Bits 3-63 are reserved on CPU not supporting LMCE */
48 /* Bits 4-63 are reserved on CPU supporting LMCE */
49 
50 /* Bitfield of MSR_IA32_MCG_EXT_CTL register (Intel Specific) */
51 #define MCG_EXT_CTL_LMCE_EN     (1ULL<<0)
52 /* Other bits are reserved */
53 
54 /* Bitfield of MSR_K8_MCi_STATUS registers */
55 /* MCA error code */
56 #define MCi_STATUS_MCA          0x000000000000ffffULL
57 /* model-specific error code */
58 #define MCi_STATUS_MSEC         0x00000000ffff0000ULL
59 /* Other information */
60 #define MCi_STATUS_OTHER        0x01ffffff00000000ULL
61 /* Action Required flag */
62 #define MCi_STATUS_AR           0x0080000000000000ULL  /* Intel specific */
63 /* Signaling flag */
64 #define MCi_STATUS_S            0x0100000000000000ULL  /* Intel specific */
65 /* processor context corrupt */
66 #define MCi_STATUS_PCC          0x0200000000000000ULL
67 /* MSR_K8_MCi_ADDR register valid */
68 #define MCi_STATUS_ADDRV        0x0400000000000000ULL
69 /* MSR_K8_MCi_MISC register valid */
70 #define MCi_STATUS_MISCV        0x0800000000000000ULL
71 /* error condition enabled */
72 #define MCi_STATUS_EN           0x1000000000000000ULL
73 /* uncorrected error */
74 #define MCi_STATUS_UC           0x2000000000000000ULL
75 /* status register overflow */
76 #define MCi_STATUS_OVER         0x4000000000000000ULL
77 /* valid */
78 #define MCi_STATUS_VAL          0x8000000000000000ULL
79 
80 /* Bitfield of MSi_STATUS_OTHER field */
81 /* reserved bits */
82 #define MCi_STATUS_OTHER_RESERVED1      0x00001fff00000000ULL
83 /* uncorrectable ECC error */
84 #define MCi_STATUS_OTEHR_UC_ECC         0x0000200000000000ULL
85 /* correctable ECC error */
86 #define MCi_STATUS_OTHER_C_ECC          0x0000400000000000ULL
87 /* ECC syndrome of an ECC error */
88 #define MCi_STATUS_OTHER_ECC_SYNDROME   0x007f800000000000ULL
89 /* reserved bits */
90 #define MCi_STATUS_OTHER_RESERVED2      0x0180000000000000ULL
91 
92 /* Bitfield of MSR_K8_HWCR register */
93 #define K8_HWCR_MCi_STATUS_WREN		(1ULL << 18)
94 
95 /*Intel Specific bitfield*/
96 #define MCi_MISC_ADDRMOD_MASK (0x7UL << 6)
97 #define MCi_MISC_PHYSMOD    (0x2UL << 6)
98 
99 #include <asm/domain.h>
100 
101 struct mca_banks
102 {
103     int num;
104     unsigned long *bank_map;
105 };
106 
mcabanks_clear(int bit,struct mca_banks * banks)107 static inline void mcabanks_clear(int bit, struct mca_banks *banks)
108 {
109     if (!banks || !banks->bank_map || bit >= banks->num)
110         return ;
111     clear_bit(bit, banks->bank_map);
112 }
113 
mcabanks_set(int bit,struct mca_banks * banks)114 static inline void mcabanks_set(int bit, struct mca_banks* banks)
115 {
116     if (!banks || !banks->bank_map || bit >= banks->num)
117         return;
118     set_bit(bit, banks->bank_map);
119 }
120 
mcabanks_test(int bit,struct mca_banks * banks)121 static inline int mcabanks_test(int bit, struct mca_banks* banks)
122 {
123     if (!banks || !banks->bank_map || bit >= banks->num)
124         return 0;
125     return test_bit(bit, banks->bank_map);
126 }
127 
128 struct mca_banks *mcabanks_alloc(void);
129 void mcabanks_free(struct mca_banks *banks);
130 extern struct mca_banks *mca_allbanks;
131 
132 /* Keep bank so that we can get status even if mib is NULL */
133 struct mca_binfo {
134     int bank;
135     struct mcinfo_global *mig;
136     struct mcinfo_bank *mib;
137     struct mc_info *mi;
138     struct cpu_user_regs *regs;
139 };
140 
141 enum mce_result
142 {
143     MCER_NOERROR,
144     MCER_RECOVERED,
145     /* Not recovered, but can continue */
146     MCER_CONTINUE,
147     MCER_RESET,
148 };
149 
150 struct mca_error_handler
151 {
152     /* Assume corresponding recovery action could be uniquely
153      * identified by mca_code. Otherwise, we might need to have
154      * a seperate function to decode the corresponding actions
155      * for the particular mca error later.
156      */
157     bool (*owned_error)(uint64_t status);
158     void (*recovery_handler)(struct mca_binfo *binfo,
159                     enum mce_result *result, const struct cpu_user_regs *regs);
160 };
161 
162 /* Global variables */
163 extern bool opt_mce;
164 
165 #endif /* X86_MCA_H */
166