aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad@kernel.org>2013-07-19 11:51:31 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2013-08-09 10:55:47 -0400
commit6efa20e49b9cb1db1ab66870cc37323474a75a13 (patch)
tree9ac97dbad6dc47c4b531809aff3029545847da7f
parentc095ba7224d8edc71dcef0d655911399a8bd4a3f (diff)
xen: Support 64-bit PV guest receiving NMIs
This is based on a patch that Zhenzhong Duan had sent - which was missing some of the remaining pieces. The kernel has the logic to handle Xen-type-exceptions using the paravirt interface in the assembler code (see PARAVIRT_ADJUST_EXCEPTION_FRAME - pv_irq_ops.adjust_exception_frame and and INTERRUPT_RETURN - pv_cpu_ops.iret). That means the nmi handler (and other exception handlers) use the hypervisor iret. The other changes that would be neccessary for this would be to translate the NMI_VECTOR to one of the entries on the ipi_vector and make xen_send_IPI_mask_allbutself use different events. Fortunately for us commit 1db01b4903639fcfaec213701a494fe3fb2c490b (xen: Clean up apic ipi interface) implemented this and we piggyback on the cleanup such that the apic IPI interface will pass the right vector value for NMI. With this patch we can trigger NMIs within a PV guest (only tested x86_64). For this to work with normal PV guests (not initial domain) we need the domain to be able to use the APIC ops - they are already implemented to use the Xen event channels. For that to be turned on in a PV domU we need to remove the masking of X86_FEATURE_APIC. Incidentally that means kgdb will also now work within a PV guest without using the 'nokgdbroundup' workaround. Note that the 32-bit version is different and this patch does not enable that. CC: Lisa Nguyen <lisa@xenapiadmin.com> CC: Ben Guthro <benjamin.guthro@citrix.com> CC: Zhenzhong Duan <zhenzhong.duan@oracle.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> [v1: Fixed up per David Vrabel comments] Reviewed-by: Ben Guthro <benjamin.guthro@citrix.com> Reviewed-by: David Vrabel <david.vrabel@citrix.com>
-rw-r--r--arch/x86/include/asm/xen/events.h1
-rw-r--r--arch/x86/xen/enlighten.c13
-rw-r--r--arch/x86/xen/setup.c13
-rw-r--r--arch/x86/xen/smp.c6
-rw-r--r--drivers/xen/events.c11
-rw-r--r--include/xen/interface/vcpu.h2
6 files changed, 38 insertions, 8 deletions
diff --git a/arch/x86/include/asm/xen/events.h b/arch/x86/include/asm/xen/events.h
index ca842f2769ef..608a79d5a466 100644
--- a/arch/x86/include/asm/xen/events.h
+++ b/arch/x86/include/asm/xen/events.h
@@ -7,6 +7,7 @@ enum ipi_vector {
7 XEN_CALL_FUNCTION_SINGLE_VECTOR, 7 XEN_CALL_FUNCTION_SINGLE_VECTOR,
8 XEN_SPIN_UNLOCK_VECTOR, 8 XEN_SPIN_UNLOCK_VECTOR,
9 XEN_IRQ_WORK_VECTOR, 9 XEN_IRQ_WORK_VECTOR,
10 XEN_NMI_VECTOR,
10 11
11 XEN_NR_IPIS, 12 XEN_NR_IPIS,
12}; 13};
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 193097ef3d7d..b5a22fa7e249 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -427,8 +427,7 @@ static void __init xen_init_cpuid_mask(void)
427 427
428 if (!xen_initial_domain()) 428 if (!xen_initial_domain())
429 cpuid_leaf1_edx_mask &= 429 cpuid_leaf1_edx_mask &=
430 ~((1 << X86_FEATURE_APIC) | /* disable local APIC */ 430 ~((1 << X86_FEATURE_ACPI)); /* disable ACPI */
431 (1 << X86_FEATURE_ACPI)); /* disable ACPI */
432 431
433 cpuid_leaf1_ecx_mask &= ~(1 << (X86_FEATURE_X2APIC % 32)); 432 cpuid_leaf1_ecx_mask &= ~(1 << (X86_FEATURE_X2APIC % 32));
434 433
@@ -735,8 +734,7 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
735 addr = (unsigned long)xen_int3; 734 addr = (unsigned long)xen_int3;
736 else if (addr == (unsigned long)stack_segment) 735 else if (addr == (unsigned long)stack_segment)
737 addr = (unsigned long)xen_stack_segment; 736 addr = (unsigned long)xen_stack_segment;
738 else if (addr == (unsigned long)double_fault || 737 else if (addr == (unsigned long)double_fault) {
739 addr == (unsigned long)nmi) {
740 /* Don't need to handle these */ 738 /* Don't need to handle these */
741 return 0; 739 return 0;
742#ifdef CONFIG_X86_MCE 740#ifdef CONFIG_X86_MCE
@@ -747,7 +745,12 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
747 */ 745 */
748 ; 746 ;
749#endif 747#endif
750 } else { 748 } else if (addr == (unsigned long)nmi)
749 /*
750 * Use the native version as well.
751 */
752 ;
753 else {
751 /* Some other trap using IST? */ 754 /* Some other trap using IST? */
752 if (WARN_ON(val->ist != 0)) 755 if (WARN_ON(val->ist != 0))
753 return 0; 756 return 0;
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 056d11faef21..403f5cc5415b 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -33,6 +33,9 @@
33/* These are code, but not functions. Defined in entry.S */ 33/* These are code, but not functions. Defined in entry.S */
34extern const char xen_hypervisor_callback[]; 34extern const char xen_hypervisor_callback[];
35extern const char xen_failsafe_callback[]; 35extern const char xen_failsafe_callback[];
36#ifdef CONFIG_X86_64
37extern const char nmi[];
38#endif
36extern void xen_sysenter_target(void); 39extern void xen_sysenter_target(void);
37extern void xen_syscall_target(void); 40extern void xen_syscall_target(void);
38extern void xen_syscall32_target(void); 41extern void xen_syscall32_target(void);
@@ -525,7 +528,13 @@ void xen_enable_syscall(void)
525 } 528 }
526#endif /* CONFIG_X86_64 */ 529#endif /* CONFIG_X86_64 */
527} 530}
528 531void __cpuinit xen_enable_nmi(void)
532{
533#ifdef CONFIG_X86_64
534 if (register_callback(CALLBACKTYPE_nmi, nmi))
535 BUG();
536#endif
537}
529void __init xen_arch_setup(void) 538void __init xen_arch_setup(void)
530{ 539{
531 xen_panic_handler_init(); 540 xen_panic_handler_init();
@@ -543,7 +552,7 @@ void __init xen_arch_setup(void)
543 552
544 xen_enable_sysenter(); 553 xen_enable_sysenter();
545 xen_enable_syscall(); 554 xen_enable_syscall();
546 555 xen_enable_nmi();
547#ifdef CONFIG_ACPI 556#ifdef CONFIG_ACPI
548 if (!(xen_start_info->flags & SIF_INITDOMAIN)) { 557 if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
549 printk(KERN_INFO "ACPI in unprivileged domain disabled\n"); 558 printk(KERN_INFO "ACPI in unprivileged domain disabled\n");
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index ca92754eb846..22759c6d309f 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -572,6 +572,12 @@ static inline int xen_map_vector(int vector)
572 case IRQ_WORK_VECTOR: 572 case IRQ_WORK_VECTOR:
573 xen_vector = XEN_IRQ_WORK_VECTOR; 573 xen_vector = XEN_IRQ_WORK_VECTOR;
574 break; 574 break;
575#ifdef CONFIG_X86_64
576 case NMI_VECTOR:
577 case APIC_DM_NMI: /* Some use that instead of NMI_VECTOR */
578 xen_vector = XEN_NMI_VECTOR;
579 break;
580#endif
575 default: 581 default:
576 xen_vector = -1; 582 xen_vector = -1;
577 printk(KERN_ERR "xen: vector 0x%x is not implemented\n", 583 printk(KERN_ERR "xen: vector 0x%x is not implemented\n",
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index a58ac435a9a4..c8b9d9fc77b5 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -56,6 +56,7 @@
56#include <xen/interface/hvm/params.h> 56#include <xen/interface/hvm/params.h>
57#include <xen/interface/physdev.h> 57#include <xen/interface/physdev.h>
58#include <xen/interface/sched.h> 58#include <xen/interface/sched.h>
59#include <xen/interface/vcpu.h>
59#include <asm/hw_irq.h> 60#include <asm/hw_irq.h>
60 61
61/* 62/*
@@ -1212,7 +1213,15 @@ EXPORT_SYMBOL_GPL(evtchn_put);
1212 1213
1213void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector) 1214void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector)
1214{ 1215{
1215 int irq = per_cpu(ipi_to_irq, cpu)[vector]; 1216 int irq;
1217
1218 if (unlikely(vector == XEN_NMI_VECTOR)) {
1219 int rc = HYPERVISOR_vcpu_op(VCPUOP_send_nmi, cpu, NULL);
1220 if (rc < 0)
1221 printk(KERN_WARNING "Sending nmi to CPU%d failed (rc:%d)\n", cpu, rc);
1222 return;
1223 }
1224 irq = per_cpu(ipi_to_irq, cpu)[vector];
1216 BUG_ON(irq < 0); 1225 BUG_ON(irq < 0);
1217 notify_remote_via_irq(irq); 1226 notify_remote_via_irq(irq);
1218} 1227}
diff --git a/include/xen/interface/vcpu.h b/include/xen/interface/vcpu.h
index 87e6f8a48661..b05288ce3991 100644
--- a/include/xen/interface/vcpu.h
+++ b/include/xen/interface/vcpu.h
@@ -170,4 +170,6 @@ struct vcpu_register_vcpu_info {
170}; 170};
171DEFINE_GUEST_HANDLE_STRUCT(vcpu_register_vcpu_info); 171DEFINE_GUEST_HANDLE_STRUCT(vcpu_register_vcpu_info);
172 172
173/* Send an NMI to the specified VCPU. @extra_arg == NULL. */
174#define VCPUOP_send_nmi 11
173#endif /* __XEN_PUBLIC_VCPU_H__ */ 175#endif /* __XEN_PUBLIC_VCPU_H__ */