ia64/xen-unstable

changeset 16185:42d8dadb5864

x86: Allow NMI callback CS to be specified via set_trap_table()
hypercall.
Based on a patch by Jan Beulich.
Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Mon Oct 22 13:04:32 2007 +0100 (2007-10-22)
parents 183a2d6eaadf
children 3e7c86602c70
files xen/arch/x86/traps.c xen/arch/x86/x86_32/asm-offsets.c xen/arch/x86/x86_32/entry.S xen/arch/x86/x86_64/asm-offsets.c xen/arch/x86/x86_64/compat/entry.S xen/arch/x86/x86_64/compat/traps.c xen/common/kernel.c xen/include/asm-ia64/linux-null/asm/nmi.h xen/include/asm-powerpc/nmi.h xen/include/asm-x86/nmi.h xen/include/xen/nmi.h xen/include/xen/sched.h
line diff
     1.1 --- a/xen/arch/x86/traps.c	Mon Oct 22 11:11:04 2007 +0100
     1.2 +++ b/xen/arch/x86/traps.c	Mon Oct 22 13:04:32 2007 +0100
     1.3 @@ -2229,6 +2229,37 @@ void __init trap_init(void)
     1.4      open_softirq(NMI_SOFTIRQ, nmi_softirq);
     1.5  }
     1.6  
     1.7 +long register_guest_nmi_callback(unsigned long address)
     1.8 +{
     1.9 +    struct vcpu *v = current;
    1.10 +    struct domain *d = current->domain;
    1.11 +    struct trap_info *t = &v->arch.guest_context.trap_ctxt[TRAP_nmi];
    1.12 +
    1.13 +    t->vector  = TRAP_nmi;
    1.14 +    t->flags   = 0;
    1.15 +    t->cs      = !IS_COMPAT(d) ? FLAT_KERNEL_CS : FLAT_COMPAT_KERNEL_CS;
    1.16 +    t->address = address;
    1.17 +    TI_SET_IF(t, 1);
    1.18 +
    1.19 +    /*
    1.20 +     * If no handler was registered we can 'lose the NMI edge'. Re-assert it
    1.21 +     * now.
    1.22 +     */
    1.23 +    if ( (v->vcpu_id == 0) && (arch_get_nmi_reason(d) != 0) )
    1.24 +        v->nmi_pending = 1;
    1.25 +
    1.26 +    return 0;
    1.27 +}
    1.28 +
    1.29 +long unregister_guest_nmi_callback(void)
    1.30 +{
    1.31 +    struct vcpu *v = current;
    1.32 +    struct trap_info *t = &v->arch.guest_context.trap_ctxt[TRAP_nmi];
    1.33 +
    1.34 +    memset(t, 0, sizeof(*t));
    1.35 +
    1.36 +    return 0;
    1.37 +}
    1.38  
    1.39  long do_set_trap_table(XEN_GUEST_HANDLE(trap_info_t) traps)
    1.40  {
    1.41 @@ -2262,6 +2293,12 @@ long do_set_trap_table(XEN_GUEST_HANDLE(
    1.42          if ( cur.address == 0 )
    1.43              break;
    1.44  
    1.45 +        if ( (cur.vector == TRAP_nmi) && !TI_GET_IF(&cur) )
    1.46 +        {
    1.47 +            rc = -EINVAL;
    1.48 +            break;
    1.49 +        }
    1.50 +
    1.51          fixup_guest_code_selector(current->domain, cur.cs);
    1.52  
    1.53          memcpy(&dst[cur.vector], &cur, sizeof(cur));
     2.1 --- a/xen/arch/x86/x86_32/asm-offsets.c	Mon Oct 22 11:11:04 2007 +0100
     2.2 +++ b/xen/arch/x86/x86_32/asm-offsets.c	Mon Oct 22 13:04:32 2007 +0100
     2.3 @@ -66,7 +66,10 @@ void __dummy__(void)
     2.4             arch.guest_context.kernel_sp);
     2.5      OFFSET(VCPU_guest_context_flags, struct vcpu, arch.guest_context.flags);
     2.6      OFFSET(VCPU_arch_guest_fpu_ctxt, struct vcpu, arch.guest_context.fpu_ctxt);
     2.7 -    OFFSET(VCPU_nmi_addr, struct vcpu, nmi_addr);
     2.8 +    OFFSET(VCPU_nmi_cs, struct vcpu,
     2.9 +           arch.guest_context.trap_ctxt[TRAP_nmi].cs);
    2.10 +    OFFSET(VCPU_nmi_addr, struct vcpu,
    2.11 +           arch.guest_context.trap_ctxt[TRAP_nmi].address);
    2.12      OFFSET(VCPU_nmi_pending, struct vcpu, nmi_pending);
    2.13      OFFSET(VCPU_nmi_masked, struct vcpu, nmi_masked);
    2.14      DEFINE(_VGCF_failsafe_disables_events, _VGCF_failsafe_disables_events);
     3.1 --- a/xen/arch/x86/x86_32/entry.S	Mon Oct 22 11:11:04 2007 +0100
     3.2 +++ b/xen/arch/x86/x86_32/entry.S	Mon Oct 22 13:04:32 2007 +0100
     3.3 @@ -257,13 +257,15 @@ process_nmi:
     3.4          testb $1,VCPU_nmi_masked(%ebx)
     3.5          jnz  test_guest_events
     3.6          movb $0,VCPU_nmi_pending(%ebx)
     3.7 -        movl VCPU_nmi_addr(%ebx),%eax
     3.8 +        movzwl VCPU_nmi_cs(%ebx),%eax
     3.9 +        movl VCPU_nmi_addr(%ebx),%ecx
    3.10          test %eax,%eax
    3.11          jz   test_guest_events
    3.12          movb $1,VCPU_nmi_masked(%ebx)
    3.13          sti
    3.14          leal VCPU_trap_bounce(%ebx),%edx
    3.15 -        movl %eax,TRAPBOUNCE_eip(%edx)
    3.16 +        movw %ax,TRAPBOUNCE_cs(%edx)
    3.17 +        movl %ecx,TRAPBOUNCE_eip(%edx)
    3.18          movw $FLAT_KERNEL_CS,TRAPBOUNCE_cs(%edx)
    3.19          movb $TBF_INTERRUPT,TRAPBOUNCE_flags(%edx)
    3.20          call create_bounce_frame
     4.1 --- a/xen/arch/x86/x86_64/asm-offsets.c	Mon Oct 22 11:11:04 2007 +0100
     4.2 +++ b/xen/arch/x86/x86_64/asm-offsets.c	Mon Oct 22 13:04:32 2007 +0100
     4.3 @@ -75,7 +75,10 @@ void __dummy__(void)
     4.4      OFFSET(VCPU_kernel_ss, struct vcpu, arch.guest_context.kernel_ss);
     4.5      OFFSET(VCPU_guest_context_flags, struct vcpu, arch.guest_context.flags);
     4.6      OFFSET(VCPU_arch_guest_fpu_ctxt, struct vcpu, arch.guest_context.fpu_ctxt);
     4.7 -    OFFSET(VCPU_nmi_addr, struct vcpu, nmi_addr);
     4.8 +    OFFSET(VCPU_nmi_cs, struct vcpu,
     4.9 +           arch.guest_context.trap_ctxt[TRAP_nmi].cs);
    4.10 +    OFFSET(VCPU_nmi_addr, struct vcpu,
    4.11 +           arch.guest_context.trap_ctxt[TRAP_nmi].address);
    4.12      OFFSET(VCPU_nmi_pending, struct vcpu, nmi_pending);
    4.13      OFFSET(VCPU_nmi_masked, struct vcpu, nmi_masked);
    4.14      DEFINE(_VGCF_failsafe_disables_events, _VGCF_failsafe_disables_events);
     5.1 --- a/xen/arch/x86/x86_64/compat/entry.S	Mon Oct 22 11:11:04 2007 +0100
     5.2 +++ b/xen/arch/x86/x86_64/compat/entry.S	Mon Oct 22 13:04:32 2007 +0100
     5.3 @@ -131,13 +131,15 @@ compat_process_nmi:
     5.4          testb $1,VCPU_nmi_masked(%rbx)
     5.5          jnz   compat_test_guest_events
     5.6          movb  $0,VCPU_nmi_pending(%rbx)
     5.7 -        movl  VCPU_nmi_addr(%rbx),%eax
     5.8 +        movzwl VCPU_nmi_cs(%rbx),%eax
     5.9 +        movl  VCPU_nmi_addr(%rbx),%ecx
    5.10          testl %eax,%eax
    5.11          jz    compat_test_guest_events
    5.12          movb  $1,VCPU_nmi_masked(%rbx)
    5.13          sti
    5.14          leaq  VCPU_trap_bounce(%rbx),%rdx
    5.15 -        movl  %eax,TRAPBOUNCE_eip(%rdx)
    5.16 +        movw  %ax,TRAPBOUNCE_cs(%rdx)
    5.17 +        movl  %ecx,TRAPBOUNCE_eip(%rdx)
    5.18          movw  $FLAT_COMPAT_KERNEL_CS,TRAPBOUNCE_cs(%rdx)
    5.19          movb  $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx)
    5.20          call  compat_create_bounce_frame
     6.1 --- a/xen/arch/x86/x86_64/compat/traps.c	Mon Oct 22 11:11:04 2007 +0100
     6.2 +++ b/xen/arch/x86/x86_64/compat/traps.c	Mon Oct 22 13:04:32 2007 +0100
     6.3 @@ -294,6 +294,12 @@ int compat_set_trap_table(XEN_GUEST_HAND
     6.4          if ( cur.address == 0 )
     6.5              break;
     6.6  
     6.7 +        if ( (cur.vector == TRAP_nmi) && !TI_GET_IF(&cur) )
     6.8 +        {
     6.9 +            rc = -EINVAL;
    6.10 +            break;
    6.11 +        }
    6.12 +
    6.13          fixup_guest_code_selector(current->domain, cur.cs);
    6.14  
    6.15          XLAT_trap_info(dst + cur.vector, &cur);
     7.1 --- a/xen/common/kernel.c	Mon Oct 22 11:11:04 2007 +0100
     7.2 +++ b/xen/common/kernel.c	Mon Oct 22 13:04:32 2007 +0100
     7.3 @@ -247,40 +247,6 @@ DO(xen_version)(int cmd, XEN_GUEST_HANDL
     7.4      return -ENOSYS;
     7.5  }
     7.6  
     7.7 -#ifndef COMPAT
     7.8 -
     7.9 -long register_guest_nmi_callback(unsigned long address)
    7.10 -{
    7.11 -    struct vcpu *v = current;
    7.12 -    struct domain *d = current->domain;
    7.13 -
    7.14 -    if ( (d->domain_id != 0) || (v->vcpu_id != 0) )
    7.15 -        return -EINVAL;
    7.16 -
    7.17 -    v->nmi_addr = address;
    7.18 -#ifdef CONFIG_X86
    7.19 -    /*
    7.20 -     * If no handler was registered we can 'lose the NMI edge'. Re-assert it
    7.21 -     * now.
    7.22 -     */
    7.23 -    if ( arch_get_nmi_reason(d) != 0 )
    7.24 -        v->nmi_pending = 1;
    7.25 -#endif
    7.26 -
    7.27 -    return 0;
    7.28 -}
    7.29 -
    7.30 -long unregister_guest_nmi_callback(void)
    7.31 -{
    7.32 -    struct vcpu *v = current;
    7.33 -
    7.34 -    v->nmi_addr = 0;
    7.35 -
    7.36 -    return 0;
    7.37 -}
    7.38 -
    7.39 -#endif
    7.40 -
    7.41  DO(nmi_op)(unsigned int cmd, XEN_GUEST_HANDLE(void) arg)
    7.42  {
    7.43      struct xennmi_callback cb;
     8.1 --- a/xen/include/asm-ia64/linux-null/asm/nmi.h	Mon Oct 22 11:11:04 2007 +0100
     8.2 +++ b/xen/include/asm-ia64/linux-null/asm/nmi.h	Mon Oct 22 13:04:32 2007 +0100
     8.3 @@ -1,1 +1,7 @@
     8.4 -/* This file is intentionally left empty. */
     8.5 +#ifndef __IA64_NMI_H__
     8.6 +#define __IA64_NMI_H__
     8.7 +
     8.8 +#define register_guest_nmi_callback(a)  (-ENOSYS)
     8.9 +#define unregister_guest_nmi_callback() (-ENOSYS)
    8.10 +
    8.11 +#endif /* __IA64_NMI_H__ */
     9.1 --- a/xen/include/asm-powerpc/nmi.h	Mon Oct 22 11:11:04 2007 +0100
     9.2 +++ b/xen/include/asm-powerpc/nmi.h	Mon Oct 22 13:04:32 2007 +0100
     9.3 @@ -3,4 +3,7 @@
     9.4  
     9.5  #include <public/nmi.h>
     9.6  
     9.7 +#define register_guest_nmi_callback(a)  (-ENOSYS)
     9.8 +#define unregister_guest_nmi_callback() (-ENOSYS)
     9.9 +
    9.10  #endif /* ASM_NMI_H */
    10.1 --- a/xen/include/asm-x86/nmi.h	Mon Oct 22 11:11:04 2007 +0100
    10.2 +++ b/xen/include/asm-x86/nmi.h	Mon Oct 22 13:04:32 2007 +0100
    10.3 @@ -23,4 +23,19 @@ void set_nmi_callback(nmi_callback_t cal
    10.4   */
    10.5  void unset_nmi_callback(void);
    10.6   
    10.7 +/**
    10.8 + * register_guest_nmi_callback
    10.9 + *
   10.10 + * The default NMI handler passes the NMI to a guest callback. This
   10.11 + * function registers the address of that callback.
   10.12 + */
   10.13 +long register_guest_nmi_callback(unsigned long address);
   10.14 +
   10.15 +/**
   10.16 + * unregister_guest_nmi_callback
   10.17 + *
   10.18 + * Unregister a guest NMI handler.
   10.19 + */
   10.20 +long unregister_guest_nmi_callback(void);
   10.21 +
   10.22  #endif /* ASM_NMI_H */
    11.1 --- a/xen/include/xen/nmi.h	Mon Oct 22 11:11:04 2007 +0100
    11.2 +++ b/xen/include/xen/nmi.h	Mon Oct 22 13:04:32 2007 +0100
    11.3 @@ -11,19 +11,4 @@
    11.4  
    11.5  #include <asm/nmi.h>
    11.6  
    11.7 -/**
    11.8 - * register_guest_nmi_callback
    11.9 - *
   11.10 - * The default NMI handler passes the NMI to a guest callback. This
   11.11 - * function registers the address of that callback.
   11.12 - */
   11.13 -extern long register_guest_nmi_callback(unsigned long address);
   11.14 -
   11.15 -/**
   11.16 - * unregister_guest_nmi_callback
   11.17 - *
   11.18 - * Unregister a guest NMI handler.
   11.19 - */
   11.20 -extern long unregister_guest_nmi_callback(void);
   11.21 -
   11.22  #endif /* __XEN_NMI_H__ */
    12.1 --- a/xen/include/xen/sched.h	Mon Oct 22 11:11:04 2007 +0100
    12.2 +++ b/xen/include/xen/sched.h	Mon Oct 22 13:04:32 2007 +0100
    12.3 @@ -131,8 +131,6 @@ struct vcpu
    12.4      /* Bitmask of CPUs on which this VCPU may run. */
    12.5      cpumask_t        cpu_affinity;
    12.6  
    12.7 -    unsigned long    nmi_addr;      /* NMI callback address. */
    12.8 -
    12.9      /* Bitmask of CPUs which are holding onto this VCPU's state. */
   12.10      cpumask_t        vcpu_dirty_cpumask;
   12.11