|
|
1.1 root 1: /******************************************************************************
2: * arch-x86/mca.h
3: *
4: * Contributed by Advanced Micro Devices, Inc.
5: * Author: Christoph Egger <[email protected]>
6: *
7: * Guest OS machine check interface to x86 Xen.
8: *
9: * Permission is hereby granted, free of charge, to any person obtaining a copy
10: * of this software and associated documentation files (the "Software"), to
11: * deal in the Software without restriction, including without limitation the
12: * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13: * sell copies of the Software, and to permit persons to whom the Software is
14: * furnished to do so, subject to the following conditions:
15: *
16: * The above copyright notice and this permission notice shall be included in
17: * all copies or substantial portions of the Software.
18: *
19: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25: * DEALINGS IN THE SOFTWARE.
26: */
27:
28: /* Full MCA functionality has the following Usecases from the guest side:
29: *
30: * Must have's:
31: * 1. Dom0 and DomU register machine check trap callback handlers
32: * (already done via "set_trap_table" hypercall)
33: * 2. Dom0 registers machine check event callback handler
34: * (doable via EVTCHNOP_bind_virq)
35: * 3. Dom0 and DomU fetches machine check data
36: * 4. Dom0 wants Xen to notify a DomU
37: * 5. Dom0 gets DomU ID from physical address
38: * 6. Dom0 wants Xen to kill DomU (already done for "xm destroy")
39: *
40: * Nice to have's:
41: * 7. Dom0 wants Xen to deactivate a physical CPU
42: * This is better done as separate task, physical CPU hotplugging,
43: * and hypercall(s) should be sysctl's
44: * 8. Page migration proposed from Xen NUMA work, where Dom0 can tell Xen to
45: * move a DomU (or Dom0 itself) away from a malicious page
46: * producing correctable errors.
47: * 9. offlining physical page:
48: * Xen free's and never re-uses a certain physical page.
49: * 10. Testfacility: Allow Dom0 to write values into machine check MSR's
50: * and tell Xen to trigger a machine check
51: */
52:
53: #ifndef __XEN_PUBLIC_ARCH_X86_MCA_H__
54: #define __XEN_PUBLIC_ARCH_X86_MCA_H__
55:
56: /* Hypercall */
57: #define __HYPERVISOR_mca __HYPERVISOR_arch_0
58:
59: #define XEN_MCA_INTERFACE_VERSION 0x03000001
60:
61: /* IN: Dom0 calls hypercall from MC event handler. */
62: #define XEN_MC_CORRECTABLE 0x0
63: /* IN: Dom0/DomU calls hypercall from MC trap handler. */
64: #define XEN_MC_TRAP 0x1
65: /* XEN_MC_CORRECTABLE and XEN_MC_TRAP are mutually exclusive. */
66:
67: /* OUT: All is ok */
68: #define XEN_MC_OK 0x0
69: /* OUT: Domain could not fetch data. */
70: #define XEN_MC_FETCHFAILED 0x1
71: /* OUT: There was no machine check data to fetch. */
72: #define XEN_MC_NODATA 0x2
73: /* OUT: Between notification time and this hypercall an other
74: * (most likely) correctable error happened. The fetched data,
75: * does not match the original machine check data. */
76: #define XEN_MC_NOMATCH 0x4
77:
78: /* OUT: DomU did not register MC NMI handler. Try something else. */
79: #define XEN_MC_CANNOTHANDLE 0x8
80: /* OUT: Notifying DomU failed. Retry later or try something else. */
81: #define XEN_MC_NOTDELIVERED 0x10
82: /* Note, XEN_MC_CANNOTHANDLE and XEN_MC_NOTDELIVERED are mutually exclusive. */
83:
84:
85: #ifndef __ASSEMBLY__
86:
87: #define VIRQ_MCA VIRQ_ARCH_0 /* G. (DOM0) Machine Check Architecture */
88:
89: /*
90: * Machine Check Architecure:
91: * structs are read-only and used to report all kinds of
92: * correctable and uncorrectable errors detected by the HW.
93: * Dom0 and DomU: register a handler to get notified.
94: * Dom0 only: Correctable errors are reported via VIRQ_MCA
95: * Dom0 and DomU: Uncorrectable errors are reported via nmi handlers
96: */
97: #define MC_TYPE_GLOBAL 0
98: #define MC_TYPE_BANK 1
99: #define MC_TYPE_EXTENDED 2
100:
101: struct mcinfo_common {
102: uint16_t type; /* structure type */
103: uint16_t size; /* size of this struct in bytes */
104: };
105:
106:
107: #define MC_FLAG_CORRECTABLE (1 << 0)
108: #define MC_FLAG_UNCORRECTABLE (1 << 1)
109:
110: /* contains global x86 mc information */
111: struct mcinfo_global {
112: struct mcinfo_common common;
113:
114: /* running domain at the time in error (most likely the impacted one) */
115: uint16_t mc_domid;
116: uint32_t mc_socketid; /* physical socket of the physical core */
117: uint16_t mc_coreid; /* physical impacted core */
118: uint16_t mc_core_threadid; /* core thread of physical core */
119: uint16_t mc_vcpuid; /* virtual cpu scheduled for mc_domid */
120: uint64_t mc_gstatus; /* global status */
121: uint32_t mc_flags;
122: };
123:
124: /* contains bank local x86 mc information */
125: struct mcinfo_bank {
126: struct mcinfo_common common;
127:
128: uint16_t mc_bank; /* bank nr */
129: uint16_t mc_domid; /* Usecase 5: domain referenced by mc_addr on dom0
130: * and if mc_addr is valid. Never valid on DomU. */
131: uint64_t mc_status; /* bank status */
132: uint64_t mc_addr; /* bank address, only valid
133: * if addr bit is set in mc_status */
134: uint64_t mc_misc;
135: };
136:
137:
138: struct mcinfo_msr {
139: uint64_t reg; /* MSR */
140: uint64_t value; /* MSR value */
141: };
142:
143: /* contains mc information from other
144: * or additional mc MSRs */
145: struct mcinfo_extended {
146: struct mcinfo_common common;
147:
148: /* You can fill up to five registers.
149: * If you need more, then use this structure
150: * multiple times. */
151:
152: uint32_t mc_msrs; /* Number of msr with valid values. */
153: struct mcinfo_msr mc_msr[5];
154: };
155:
156: #define MCINFO_HYPERCALLSIZE 1024
157: #define MCINFO_MAXSIZE 768
158:
159: struct mc_info {
160: /* Number of mcinfo_* entries in mi_data */
161: uint32_t mi_nentries;
162:
163: uint8_t mi_data[MCINFO_MAXSIZE - sizeof(uint32_t)];
164: };
165: typedef struct mc_info mc_info_t;
166:
167:
168:
169: /*
170: * OS's should use these instead of writing their own lookup function
171: * each with its own bugs and drawbacks.
172: * We use macros instead of static inline functions to allow guests
173: * to include this header in assembly files (*.S).
174: */
175: /* Prototype:
176: * uint32_t x86_mcinfo_nentries(struct mc_info *mi);
177: */
178: #define x86_mcinfo_nentries(_mi) \
179: (_mi)->mi_nentries
180: /* Prototype:
181: * struct mcinfo_common *x86_mcinfo_first(struct mc_info *mi);
182: */
183: #define x86_mcinfo_first(_mi) \
184: (struct mcinfo_common *)((_mi)->mi_data)
185: /* Prototype:
186: * struct mcinfo_common *x86_mcinfo_next(struct mcinfo_common *mic);
187: */
188: #define x86_mcinfo_next(_mic) \
189: (struct mcinfo_common *)((uint8_t *)(_mic) + (_mic)->size)
190:
191: /* Prototype:
192: * void x86_mcinfo_lookup(void *ret, struct mc_info *mi, uint16_t type);
193: */
194: #define x86_mcinfo_lookup(_ret, _mi, _type) \
195: do { \
196: uint32_t found, i; \
197: struct mcinfo_common *_mic; \
198: \
199: found = 0; \
200: (_ret) = NULL; \
201: if (_mi == NULL) break; \
202: _mic = x86_mcinfo_first(_mi); \
203: for (i = 0; i < x86_mcinfo_nentries(_mi); i++) { \
204: if (_mic->type == (_type)) { \
205: found = 1; \
206: break; \
207: } \
208: _mic = x86_mcinfo_next(_mic); \
209: } \
210: (_ret) = found ? _mic : NULL; \
211: } while (0)
212:
213:
214: /* Usecase 1
215: * Register machine check trap callback handler
216: * (already done via "set_trap_table" hypercall)
217: */
218:
219: /* Usecase 2
220: * Dom0 registers machine check event callback handler
221: * done by EVTCHNOP_bind_virq
222: */
223:
224: /* Usecase 3
225: * Fetch machine check data from hypervisor.
226: * Note, this hypercall is special, because both Dom0 and DomU must use this.
227: */
228: #define XEN_MC_fetch 1
229: struct xen_mc_fetch {
230: /* IN/OUT variables. */
231: uint32_t flags;
232:
233: /* IN: XEN_MC_CORRECTABLE, XEN_MC_TRAP */
234: /* OUT: XEN_MC_OK, XEN_MC_FETCHFAILED, XEN_MC_NODATA, XEN_MC_NOMATCH */
235:
236: /* OUT variables. */
237: uint32_t fetch_idx; /* only useful for Dom0 for the notify hypercall */
238: struct mc_info mc_info;
239: };
240: typedef struct xen_mc_fetch xen_mc_fetch_t;
241: DEFINE_XEN_GUEST_HANDLE(xen_mc_fetch_t);
242:
243:
244: /* Usecase 4
245: * This tells the hypervisor to notify a DomU about the machine check error
246: */
247: #define XEN_MC_notifydomain 2
248: struct xen_mc_notifydomain {
249: /* IN variables. */
250: uint16_t mc_domid; /* The unprivileged domain to notify. */
251: uint16_t mc_vcpuid; /* The vcpu in mc_domid to notify.
252: * Usually echo'd value from the fetch hypercall. */
253: uint32_t fetch_idx; /* echo'd value from the fetch hypercall. */
254:
255: /* IN/OUT variables. */
256: uint32_t flags;
257:
258: /* IN: XEN_MC_CORRECTABLE, XEN_MC_TRAP */
259: /* OUT: XEN_MC_OK, XEN_MC_CANNOTHANDLE, XEN_MC_NOTDELIVERED, XEN_MC_NOMATCH */
260: };
261: typedef struct xen_mc_notifydomain xen_mc_notifydomain_t;
262: DEFINE_XEN_GUEST_HANDLE(xen_mc_notifydomain_t);
263:
264:
265: struct xen_mc {
266: uint32_t cmd;
267: uint32_t interface_version; /* XEN_MCA_INTERFACE_VERSION */
268: union {
269: struct xen_mc_fetch mc_fetch;
270: struct xen_mc_notifydomain mc_notifydomain;
271: uint8_t pad[MCINFO_HYPERCALLSIZE];
272: } u;
273: };
274: typedef struct xen_mc xen_mc_t;
275: DEFINE_XEN_GUEST_HANDLE(xen_mc_t);
276:
277: #endif /* __ASSEMBLY__ */
278:
279: #endif /* __XEN_PUBLIC_ARCH_X86_MCA_H__ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.