diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2009-03-20 17:24:29 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2009-03-20 17:24:29 +0000 |
commit | 32e8dd573b4540e9ba040d713c8b38547971d7a0 (patch) | |
tree | b7cefba3fd0ab5dc2794dd7ddbaef27799122ae7 /xen/arch/x86/x86_64/traps.c | |
parent | 2ccae6ea67754ae139ce6b25d928e64b479e9865 (diff) | |
download | xen-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.c | 47 |
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; |