aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/x86_64/traps.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-03-20 17:24:29 +0000
committerKeir Fraser <keir.fraser@citrix.com>2009-03-20 17:24:29 +0000
commit32e8dd573b4540e9ba040d713c8b38547971d7a0 (patch)
treeb7cefba3fd0ab5dc2794dd7ddbaef27799122ae7 /xen/arch/x86/x86_64/traps.c
parent2ccae6ea67754ae139ce6b25d928e64b479e9865 (diff)
downloadxen-32e8dd573b4540e9ba040d713c8b38547971d7a0.tar.gz
xen-32e8dd573b4540e9ba040d713c8b38547971d7a0.tar.bz2
xen-32e8dd573b4540e9ba040d713c8b38547971d7a0.zip
x86: Core support for Intel MCA support
Those patches based on AMD and SUN's MCA related jobs. We have latest rebase after SUN's latest improvements. We will have late following patches for recovery actions. This is a basic framework for Intel. Some implementation notes: 1) When error happens, if the error is fatal (pcc = 1) or can't be recovered (pcc = 0, yet no good recovery methods), for avoiding losing logs in DOM0, we will reset machine immediately. Most of MCA MSRs are sticky. After reboot, MCA polling mechanism will send vIRQ to DOM0 for logging. 2) When MCE# happens, all CPUs enter MCA context. The first CPU who read&clear the error MSR bank will be this MCE# owner. Necessary locks/synchronization will help to judge the owner and select most severe error. 3) For convenience, we will select the most offending CPU to do most of processing&recovery job. 4) MCE# happens, we will do three jobs: a. Send vIRQ to DOM0 for logging b. Send vMCE# to Impacted Guest (Currently Only inject to impacted DOM0) c. Guest vMCE MSR virtualization 5) Some further improvement/adds for newer CPUs might be done later a) Connection with recovery actions (cpu/memory online/offline) b) More software-recovery identification in severity_scan c) More refines and tests for HVM might be done when needed. This patch Enable basic MCA support For Intel Signed-off-by: Jiang, Yunhong<yunhong.jiang@intel.com> Signed-off-by: Ke, Liping <Liping.ke@intel.com>
Diffstat (limited to 'xen/arch/x86/x86_64/traps.c')
-rw-r--r--xen/arch/x86/x86_64/traps.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c
index 34f4ecf59c..70fef66f84 100644
--- a/xen/arch/x86/x86_64/traps.c
+++ b/xen/arch/x86/x86_64/traps.c
@@ -14,6 +14,8 @@
#include <xen/nmi.h>
#include <asm/current.h>
#include <asm/flushtlb.h>
+#include <asm/traps.h>
+#include <asm/event.h>
#include <asm/msr.h>
#include <asm/page.h>
#include <asm/shared.h>
@@ -265,6 +267,9 @@ unsigned long do_iret(void)
struct cpu_user_regs *regs = guest_cpu_user_regs();
struct iret_context iret_saved;
struct vcpu *v = current;
+ struct domain *d = v->domain;
+ struct bank_entry *entry;
+ int cpu = smp_processor_id();
if ( unlikely(copy_from_user(&iret_saved, (void *)regs->rsp,
sizeof(iret_saved))) )
@@ -304,6 +309,48 @@ unsigned long do_iret(void)
&& !cpus_equal(v->cpu_affinity_tmp, v->cpu_affinity))
vcpu_set_affinity(v, &v->cpu_affinity_tmp);
+ /*Currently, only inject vMCE to DOM0.*/
+ if (v->trap_priority >= VCPU_TRAP_NMI) {
+ printk(KERN_DEBUG "MCE: Return from vMCE# trap!");
+ if (d->domain_id == 0 && v->vcpu_id == 0) {
+ if ( !d->arch.vmca_msrs.nr_injection ) {
+ printk(KERN_WARNING "MCE: Ret from vMCE#, nr_injection is 0\n");
+ goto end;
+ }
+
+ d->arch.vmca_msrs.nr_injection--;
+ if (!list_empty(&d->arch.vmca_msrs.impact_header)) {
+ entry = list_entry(d->arch.vmca_msrs.impact_header.next,
+ struct bank_entry, list);
+ printk(KERN_DEBUG "MCE: Delete last injection Node\n");
+ list_del(&entry->list);
+ }
+ else
+ printk(KERN_DEBUG "MCE: Not found last injection "
+ "Node, something Wrong!\n");
+
+ /* futher injection*/
+ if ( d->arch.vmca_msrs.nr_injection > 0) {
+ if ( d->arch.vmca_msrs.nr_injection > 0 &&
+ guest_has_trap_callback(d, v->vcpu_id,
+ TRAP_machine_check) &&
+ !test_and_set_bool(dom0->vcpu[0]->mce_pending)) {
+ cpumask_t affinity;
+
+ dom0->vcpu[0]->cpu_affinity_tmp =
+ dom0->vcpu[0]->cpu_affinity;
+ cpus_clear(affinity);
+ cpu_set(cpu, affinity);
+ printk(KERN_DEBUG "MCE: CPU%d set affinity, old %d\n", cpu,
+ dom0->vcpu[0]->processor);
+ vcpu_set_affinity(dom0->vcpu[0], &affinity);
+ vcpu_kick(dom0->vcpu[0]);
+ }
+ }
+ }
+ } /* end of outer-if */
+
+end:
/* Restore previous trap priority */
v->trap_priority = v->old_trap_priority;