Machine Check Support
PATCH 1/2 Machine Check Support
Hi,
This introduces send_guest_trap() as preparation for machine check support. send_guest_trap() is designed to inject any trap into a vcpu from NMI/MCE context. This patch makes NMI use of it.
Signed-off-by Christoph Egger <[email protected]>
Signature · 12 lines
AMD Saxony, Dresden, Germany Operating System Research Center Legal Information: AMD Saxony Limited Liability Company & Co. KG Sitz (Geschäftsanschrift): Wilschdorfer Landstr. 101, 01109 Dresden, Deutschland Registergericht Dresden: HRA 4896 vertretungsberechtigter Komplementär: AMD Saxony LLC (Sitz Wilmington, Delaware, USA) Geschäftsführer der AMD Saxony LLC: Dr. Hans-R. Deppe, Thomas McCoy
xen/arch/x86/traps.c +64 -8
@@ -61,6 +61,7 @@#include <asm/msr.h> #include <asm/shared.h> #include <asm/x86_emulate.h> +#include <asm/traps.h> #include <asm/hvm/vpt.h> #include <public/arch-x86/cpuid.h>
@@ -2678,25 +2679,51 @@ asmlinkage void do_general_protection(stpanic ("GENERAL PROTECTION FAULT\n[error_code=%04x]\n" , regs->error_code); } +static DEFINE_PER_CPU(struct softirq_trap, softirq_trap); +static void nmi_mce_softirq (void ) { -/* Only used to defer wakeup of dom0,vcpu0 to a safe (non-NMI) context. */ -vcpu_kick (dom0->vcpu[0 ]); +int cpu =smp_processor_id (); +struct softirq_trap *st = &per_cpu (softirq_trap, cpu); +cpumask_t affinity; + +BUG_ON (st ==NULL ); +BUG_ON (st->vcpu ==NULL ); + +/* Set the tmp value unconditionally, so that +* the check in the iret hypercall works. */ + st->vcpu->cpu_affinity_tmp = st->vcpu->cpu_affinity; + +if ((cpu != st->processor) + || (st->processor != st->vcpu->processor)) + { +/* We are on a different physical cpu. +* Make sure to wakeup the vcpu on the +* specified processor. +*/ +cpus_clear (affinity); +cpu_set (st->processor, affinity); +vcpu_set_affinity (st->vcpu, &affinity); + +/* Affinity is restored in the iret hypercall. */ + } + +/* Only used to defer wakeup of domain/vcpu to +* a safe (non-NMI/MCE) context. +*/ +vcpu_kick (st->vcpu); }static void nmi_dom0_report (unsigned int reason_idx) { -struct domain *d; -struct vcpu *v; +struct domain *d = dom0; -if ( ((d = dom0) ==NULL ) || ((v = d->vcpu[0 ]) ==NULL ) ) +if ( (d ==NULL ) || (d->vcpu[0 ] ==NULL ) )return ;set_bit (reason_idx,nmi_reason (d)); -/* Not safe to wake a vcpu here, or even to schedule a tasklet! */ -if ( !test_and_set_bool (v->nmi_pending) ) -raise_softirq (NMI_MCE_SOFTIRQ ); +send_guest_trap (d,0 , TRAP_nmi); } asmlinkage void mem_parity_error(struct cpu_user_regs *regs)
@@ -3010,6 +3037,35 @@ long unregister_guest_nmi_callback(void)return 0 ; } +int send_guest_trap (struct domain *d,uint16_t vcpuid,unsigned int trap_nr) +{ +struct vcpu *v; +struct softirq_trap *st; + +BUG_ON (d ==NULL ); +BUG_ON (vcpuid >=MAX_VIRT_CPUS ); + v = d->vcpu[vcpuid]; + +switch (trap_nr) { +case TRAP_nmi: +if ( !test_and_set_bool (v->nmi_pending) ) { + st = &per_cpu (softirq_trap,smp_processor_id ()); + st->domain = dom0; + st->vcpu = dom0->vcpu[0 ]; + st->processor = st->vcpu->processor; + +/* not safe to wake up a vcpu here */ +raise_softirq (NMI_MCE_SOFTIRQ ); +return 0 ; + } +break ; + } + +/* delivery failed */ +return -EIO ; +} + +long do_set_trap_table (XEN_GUEST_HANDLE (const_trap_info_t) traps) {struct trap_info cur;
xen/arch/x86/x86_32/traps.c +4 -0
@@ -255,6 +255,10 @@ unsigned long do_iret(void) goto exit_and_crash; } +/* Restore affinity. */ +if (!cpus_equal (v->cpu_affinity_tmp, v->cpu_affinity)) +vcpu_set_affinity (v, &v->cpu_affinity_tmp); +/* No longer in NMI context. */ v->nmi_masked =0 ;
xen/arch/x86/x86_64/compat/traps.c +4 -0
@@ -120,6 +120,10 @@ unsigned int compat_iret(void) }else regs->_esp +=16 ; + +/* Restore affinity. */ +if (!cpus_equal (v->cpu_affinity_tmp, v->cpu_affinity)) +vcpu_set_affinity (v, &v->cpu_affinity_tmp);/* No longer in NMI context. */ v->nmi_masked =0 ;
xen/arch/x86/x86_64/traps.c +4 -0
@@ -288,6 +288,10 @@ unsigned long do_iret(void) regs->rcx = iret_saved.rcx; } +/* Restore affinity. */ +if (!cpus_equal (v->cpu_affinity_tmp, v->cpu_affinity)) +vcpu_set_affinity (v, &v->cpu_affinity_tmp); +/* No longer in NMI context. */ v->nmi_masked =0 ;
xen/include/asm-x86/traps.h new file +40 -0
@@ -0,0 +1,40 @@ +/* +* +* Copyright (c) 2007 Advanced Micro Devices, Inc. +* Author: Christoph Egger <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef ASM_TRAP_H +#define ASM_TRAP_H + +struct softirq_trap { +struct domain *domain;/* domain to inject trap */ +struct vcpu *vcpu;/* vcpu to inject trap */ +int processor;/* physical cpu to inject trap */ +}; + +/** +* send_guest_trap +* +* delivers trap to guest analogous to send_guest_global_virq +* return 0 on successful delivery +*/ +extern int send_guest_trap (struct domain *d,uint16_t vcpuid, +unsigned int trap_nr); + + +#endif /* ASM_TRAP_H */
xen/include/xen/sched.h +2 -0
@@ -130,6 +130,8 @@ struct vcpu/* Bitmask of CPUs on which this VCPU may run. */ cpumask_t cpu_affinity; +/* Used to change affinity temporarily. */ +cpumask_t cpu_affinity_tmp;/* Bitmask of CPUs which are holding onto this VCPU's state. */ cpumask_t vcpu_dirty_cpumask;
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel