1183375Skmacy/****************************************************************************** 2183375Skmacy * arch-x86/mca.h 3183375Skmacy * 4183375Skmacy * Contributed by Advanced Micro Devices, Inc. 5183375Skmacy * Author: Christoph Egger <Christoph.Egger@amd.com> 6183375Skmacy * 7183375Skmacy * Guest OS machine check interface to x86 Xen. 8183375Skmacy * 9183375Skmacy * Permission is hereby granted, free of charge, to any person obtaining a copy 10183375Skmacy * of this software and associated documentation files (the "Software"), to 11183375Skmacy * deal in the Software without restriction, including without limitation the 12183375Skmacy * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 13183375Skmacy * sell copies of the Software, and to permit persons to whom the Software is 14183375Skmacy * furnished to do so, subject to the following conditions: 15183375Skmacy * 16183375Skmacy * The above copyright notice and this permission notice shall be included in 17183375Skmacy * all copies or substantial portions of the Software. 18183375Skmacy * 19183375Skmacy * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20183375Skmacy * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21183375Skmacy * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22183375Skmacy * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23183375Skmacy * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24183375Skmacy * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25183375Skmacy * DEALINGS IN THE SOFTWARE. 26183375Skmacy */ 27183375Skmacy 28183375Skmacy/* Full MCA functionality has the following Usecases from the guest side: 29183375Skmacy * 30183375Skmacy * Must have's: 31183375Skmacy * 1. Dom0 and DomU register machine check trap callback handlers 32183375Skmacy * (already done via "set_trap_table" hypercall) 33183375Skmacy * 2. Dom0 registers machine check event callback handler 34183375Skmacy * (doable via EVTCHNOP_bind_virq) 35183375Skmacy * 3. Dom0 and DomU fetches machine check data 36183375Skmacy * 4. Dom0 wants Xen to notify a DomU 37183375Skmacy * 5. Dom0 gets DomU ID from physical address 38183375Skmacy * 6. Dom0 wants Xen to kill DomU (already done for "xm destroy") 39183375Skmacy * 40183375Skmacy * Nice to have's: 41183375Skmacy * 7. Dom0 wants Xen to deactivate a physical CPU 42183375Skmacy * This is better done as separate task, physical CPU hotplugging, 43183375Skmacy * and hypercall(s) should be sysctl's 44183375Skmacy * 8. Page migration proposed from Xen NUMA work, where Dom0 can tell Xen to 45183375Skmacy * move a DomU (or Dom0 itself) away from a malicious page 46183375Skmacy * producing correctable errors. 47183375Skmacy * 9. offlining physical page: 48183375Skmacy * Xen free's and never re-uses a certain physical page. 49183375Skmacy * 10. Testfacility: Allow Dom0 to write values into machine check MSR's 50183375Skmacy * and tell Xen to trigger a machine check 51183375Skmacy */ 52183375Skmacy 53183375Skmacy#ifndef __XEN_PUBLIC_ARCH_X86_MCA_H__ 54183375Skmacy#define __XEN_PUBLIC_ARCH_X86_MCA_H__ 55183375Skmacy 56183375Skmacy/* Hypercall */ 57183375Skmacy#define __HYPERVISOR_mca __HYPERVISOR_arch_0 58183375Skmacy 59183375Skmacy#define XEN_MCA_INTERFACE_VERSION 0x03000001 60183375Skmacy 61183375Skmacy/* IN: Dom0 calls hypercall from MC event handler. */ 62183375Skmacy#define XEN_MC_CORRECTABLE 0x0 63183375Skmacy/* IN: Dom0/DomU calls hypercall from MC trap handler. */ 64183375Skmacy#define XEN_MC_TRAP 0x1 65183375Skmacy/* XEN_MC_CORRECTABLE and XEN_MC_TRAP are mutually exclusive. */ 66183375Skmacy 67183375Skmacy/* OUT: All is ok */ 68183375Skmacy#define XEN_MC_OK 0x0 69183375Skmacy/* OUT: Domain could not fetch data. */ 70183375Skmacy#define XEN_MC_FETCHFAILED 0x1 71183375Skmacy/* OUT: There was no machine check data to fetch. */ 72183375Skmacy#define XEN_MC_NODATA 0x2 73183375Skmacy/* OUT: Between notification time and this hypercall an other 74183375Skmacy * (most likely) correctable error happened. The fetched data, 75183375Skmacy * does not match the original machine check data. */ 76183375Skmacy#define XEN_MC_NOMATCH 0x4 77183375Skmacy 78183375Skmacy/* OUT: DomU did not register MC NMI handler. Try something else. */ 79183375Skmacy#define XEN_MC_CANNOTHANDLE 0x8 80183375Skmacy/* OUT: Notifying DomU failed. Retry later or try something else. */ 81183375Skmacy#define XEN_MC_NOTDELIVERED 0x10 82183375Skmacy/* Note, XEN_MC_CANNOTHANDLE and XEN_MC_NOTDELIVERED are mutually exclusive. */ 83183375Skmacy 84183375Skmacy 85183375Skmacy#ifndef __ASSEMBLY__ 86183375Skmacy 87183375Skmacy#define VIRQ_MCA VIRQ_ARCH_0 /* G. (DOM0) Machine Check Architecture */ 88183375Skmacy 89183375Skmacy/* 90183375Skmacy * Machine Check Architecure: 91183375Skmacy * structs are read-only and used to report all kinds of 92183375Skmacy * correctable and uncorrectable errors detected by the HW. 93183375Skmacy * Dom0 and DomU: register a handler to get notified. 94183375Skmacy * Dom0 only: Correctable errors are reported via VIRQ_MCA 95183375Skmacy * Dom0 and DomU: Uncorrectable errors are reported via nmi handlers 96183375Skmacy */ 97183375Skmacy#define MC_TYPE_GLOBAL 0 98183375Skmacy#define MC_TYPE_BANK 1 99183375Skmacy#define MC_TYPE_EXTENDED 2 100183375Skmacy 101183375Skmacystruct mcinfo_common { 102183375Skmacy uint16_t type; /* structure type */ 103183375Skmacy uint16_t size; /* size of this struct in bytes */ 104183375Skmacy}; 105183375Skmacy 106183375Skmacy 107183375Skmacy#define MC_FLAG_CORRECTABLE (1 << 0) 108183375Skmacy#define MC_FLAG_UNCORRECTABLE (1 << 1) 109183375Skmacy 110183375Skmacy/* contains global x86 mc information */ 111183375Skmacystruct mcinfo_global { 112183375Skmacy struct mcinfo_common common; 113183375Skmacy 114183375Skmacy /* running domain at the time in error (most likely the impacted one) */ 115183375Skmacy uint16_t mc_domid; 116183375Skmacy uint32_t mc_socketid; /* physical socket of the physical core */ 117183375Skmacy uint16_t mc_coreid; /* physical impacted core */ 118183375Skmacy uint16_t mc_core_threadid; /* core thread of physical core */ 119183375Skmacy uint16_t mc_vcpuid; /* virtual cpu scheduled for mc_domid */ 120183375Skmacy uint64_t mc_gstatus; /* global status */ 121183375Skmacy uint32_t mc_flags; 122183375Skmacy}; 123183375Skmacy 124183375Skmacy/* contains bank local x86 mc information */ 125183375Skmacystruct mcinfo_bank { 126183375Skmacy struct mcinfo_common common; 127183375Skmacy 128183375Skmacy uint16_t mc_bank; /* bank nr */ 129183375Skmacy uint16_t mc_domid; /* Usecase 5: domain referenced by mc_addr on dom0 130183375Skmacy * and if mc_addr is valid. Never valid on DomU. */ 131183375Skmacy uint64_t mc_status; /* bank status */ 132183375Skmacy uint64_t mc_addr; /* bank address, only valid 133183375Skmacy * if addr bit is set in mc_status */ 134183375Skmacy uint64_t mc_misc; 135183375Skmacy}; 136183375Skmacy 137183375Skmacy 138183375Skmacystruct mcinfo_msr { 139183375Skmacy uint64_t reg; /* MSR */ 140183375Skmacy uint64_t value; /* MSR value */ 141183375Skmacy}; 142183375Skmacy 143183375Skmacy/* contains mc information from other 144183375Skmacy * or additional mc MSRs */ 145183375Skmacystruct mcinfo_extended { 146183375Skmacy struct mcinfo_common common; 147183375Skmacy 148183375Skmacy /* You can fill up to five registers. 149183375Skmacy * If you need more, then use this structure 150183375Skmacy * multiple times. */ 151183375Skmacy 152183375Skmacy uint32_t mc_msrs; /* Number of msr with valid values. */ 153183375Skmacy struct mcinfo_msr mc_msr[5]; 154183375Skmacy}; 155183375Skmacy 156183375Skmacy#define MCINFO_HYPERCALLSIZE 1024 157183375Skmacy#define MCINFO_MAXSIZE 768 158183375Skmacy 159183375Skmacystruct mc_info { 160183375Skmacy /* Number of mcinfo_* entries in mi_data */ 161183375Skmacy uint32_t mi_nentries; 162183375Skmacy 163183375Skmacy uint8_t mi_data[MCINFO_MAXSIZE - sizeof(uint32_t)]; 164183375Skmacy}; 165183375Skmacytypedef struct mc_info mc_info_t; 166183375Skmacy 167183375Skmacy 168183375Skmacy 169183375Skmacy/* 170183375Skmacy * OS's should use these instead of writing their own lookup function 171183375Skmacy * each with its own bugs and drawbacks. 172183375Skmacy * We use macros instead of static inline functions to allow guests 173183375Skmacy * to include this header in assembly files (*.S). 174183375Skmacy */ 175183375Skmacy/* Prototype: 176183375Skmacy * uint32_t x86_mcinfo_nentries(struct mc_info *mi); 177183375Skmacy */ 178183375Skmacy#define x86_mcinfo_nentries(_mi) \ 179183375Skmacy (_mi)->mi_nentries 180183375Skmacy/* Prototype: 181183375Skmacy * struct mcinfo_common *x86_mcinfo_first(struct mc_info *mi); 182183375Skmacy */ 183183375Skmacy#define x86_mcinfo_first(_mi) \ 184183375Skmacy (struct mcinfo_common *)((_mi)->mi_data) 185183375Skmacy/* Prototype: 186183375Skmacy * struct mcinfo_common *x86_mcinfo_next(struct mcinfo_common *mic); 187183375Skmacy */ 188183375Skmacy#define x86_mcinfo_next(_mic) \ 189183375Skmacy (struct mcinfo_common *)((uint8_t *)(_mic) + (_mic)->size) 190183375Skmacy 191183375Skmacy/* Prototype: 192183375Skmacy * void x86_mcinfo_lookup(void *ret, struct mc_info *mi, uint16_t type); 193183375Skmacy */ 194183375Skmacy#define x86_mcinfo_lookup(_ret, _mi, _type) \ 195183375Skmacy do { \ 196183375Skmacy uint32_t found, i; \ 197183375Skmacy struct mcinfo_common *_mic; \ 198183375Skmacy \ 199183375Skmacy found = 0; \ 200183375Skmacy (_ret) = NULL; \ 201183375Skmacy if (_mi == NULL) break; \ 202183375Skmacy _mic = x86_mcinfo_first(_mi); \ 203183375Skmacy for (i = 0; i < x86_mcinfo_nentries(_mi); i++) { \ 204183375Skmacy if (_mic->type == (_type)) { \ 205183375Skmacy found = 1; \ 206183375Skmacy break; \ 207183375Skmacy } \ 208183375Skmacy _mic = x86_mcinfo_next(_mic); \ 209183375Skmacy } \ 210183375Skmacy (_ret) = found ? _mic : NULL; \ 211183375Skmacy } while (0) 212183375Skmacy 213183375Skmacy 214183375Skmacy/* Usecase 1 215183375Skmacy * Register machine check trap callback handler 216183375Skmacy * (already done via "set_trap_table" hypercall) 217183375Skmacy */ 218183375Skmacy 219183375Skmacy/* Usecase 2 220183375Skmacy * Dom0 registers machine check event callback handler 221183375Skmacy * done by EVTCHNOP_bind_virq 222183375Skmacy */ 223183375Skmacy 224183375Skmacy/* Usecase 3 225183375Skmacy * Fetch machine check data from hypervisor. 226183375Skmacy * Note, this hypercall is special, because both Dom0 and DomU must use this. 227183375Skmacy */ 228183375Skmacy#define XEN_MC_fetch 1 229183375Skmacystruct xen_mc_fetch { 230183375Skmacy /* IN/OUT variables. */ 231183375Skmacy uint32_t flags; 232183375Skmacy 233183375Skmacy/* IN: XEN_MC_CORRECTABLE, XEN_MC_TRAP */ 234183375Skmacy/* OUT: XEN_MC_OK, XEN_MC_FETCHFAILED, XEN_MC_NODATA, XEN_MC_NOMATCH */ 235183375Skmacy 236183375Skmacy /* OUT variables. */ 237183375Skmacy uint32_t fetch_idx; /* only useful for Dom0 for the notify hypercall */ 238183375Skmacy struct mc_info mc_info; 239183375Skmacy}; 240183375Skmacytypedef struct xen_mc_fetch xen_mc_fetch_t; 241183375SkmacyDEFINE_XEN_GUEST_HANDLE(xen_mc_fetch_t); 242183375Skmacy 243183375Skmacy 244183375Skmacy/* Usecase 4 245183375Skmacy * This tells the hypervisor to notify a DomU about the machine check error 246183375Skmacy */ 247183375Skmacy#define XEN_MC_notifydomain 2 248183375Skmacystruct xen_mc_notifydomain { 249183375Skmacy /* IN variables. */ 250183375Skmacy uint16_t mc_domid; /* The unprivileged domain to notify. */ 251183375Skmacy uint16_t mc_vcpuid; /* The vcpu in mc_domid to notify. 252183375Skmacy * Usually echo'd value from the fetch hypercall. */ 253183375Skmacy uint32_t fetch_idx; /* echo'd value from the fetch hypercall. */ 254183375Skmacy 255183375Skmacy /* IN/OUT variables. */ 256183375Skmacy uint32_t flags; 257183375Skmacy 258183375Skmacy/* IN: XEN_MC_CORRECTABLE, XEN_MC_TRAP */ 259183375Skmacy/* OUT: XEN_MC_OK, XEN_MC_CANNOTHANDLE, XEN_MC_NOTDELIVERED, XEN_MC_NOMATCH */ 260183375Skmacy}; 261183375Skmacytypedef struct xen_mc_notifydomain xen_mc_notifydomain_t; 262183375SkmacyDEFINE_XEN_GUEST_HANDLE(xen_mc_notifydomain_t); 263183375Skmacy 264183375Skmacy 265183375Skmacystruct xen_mc { 266183375Skmacy uint32_t cmd; 267183375Skmacy uint32_t interface_version; /* XEN_MCA_INTERFACE_VERSION */ 268183375Skmacy union { 269183375Skmacy struct xen_mc_fetch mc_fetch; 270183375Skmacy struct xen_mc_notifydomain mc_notifydomain; 271183375Skmacy uint8_t pad[MCINFO_HYPERCALLSIZE]; 272183375Skmacy } u; 273183375Skmacy}; 274183375Skmacytypedef struct xen_mc xen_mc_t; 275183375SkmacyDEFINE_XEN_GUEST_HANDLE(xen_mc_t); 276183375Skmacy 277183375Skmacy#endif /* __ASSEMBLY__ */ 278183375Skmacy 279183375Skmacy#endif /* __XEN_PUBLIC_ARCH_X86_MCA_H__ */ 280