[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Add new hypercall "set_callback" taking a callback identifier and the



# HG changeset patch
# User Ian.Campbell@xxxxxxxxxxxxx
# Node ID 67de34c062b5897d1e82995b171be081f976558e
# Parent  d2705953c6d268779a4612b0115dc52b34f4f68c
Add new hypercall "set_callback" taking a callback identifier and the
callback address.

This new hypercall incorporates the functionality of the existing set_callbacks
hypercall in a more flexible manner. set_callbacks is retained for 
compatibility.

Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxxxxx>

diff -r d2705953c6d2 -r 67de34c062b5 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h    Thu Apr 
 6 10:34:14 2006
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h    Thu Apr 
 6 11:03:53 2006
@@ -327,6 +327,14 @@
        unsigned long op, void *arg)
 {
        return _hypercall2(int, nmi_op, op, arg);
+}
+
+static inline int
+HYPERVISOR_callback_op(
+       int cmd,
+       void *arg)
+{
+       return _hypercall2(int, callback_op, cmd, arg);
 }
 
 #endif /* __HYPERCALL_H__ */
diff -r d2705953c6d2 -r 67de34c062b5 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h  Thu Apr 
 6 10:34:14 2006
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h  Thu Apr 
 6 11:03:53 2006
@@ -5,6 +5,8 @@
  *     This is included late in kernel/setup.c so that it can make
  *     use of all of the static functions.
  **/
+
+#include <xen/interface/callback.h>
 
 static char * __init machine_specific_memory_setup(void)
 {
@@ -23,6 +25,14 @@
 static void __init machine_specific_arch_setup(void)
 {
        struct xen_platform_parameters pp;
+       callback_register_t event = {
+               .type = CALLBACKTYPE_event,
+               .address = { __KERNEL_CS, (unsigned long)hypervisor_callback },
+       };
+       callback_register_t failsafe = {
+               .type = CALLBACKTYPE_failsafe,
+               .address = { __KERNEL_CS, (unsigned long)failsafe_callback },
+       };
        struct xennmi_callback cb;
 
        if (xen_feature(XENFEAT_auto_translated_physmap) &&
@@ -32,9 +42,8 @@
                memset(empty_zero_page, 0, sizeof(empty_zero_page));
        }
 
-       HYPERVISOR_set_callbacks(
-           __KERNEL_CS, (unsigned long)hypervisor_callback,
-           __KERNEL_CS, (unsigned long)failsafe_callback);
+       HYPERVISOR_callback_op(CALLBACKOP_register, &event);
+       HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
 
        cb.handler_address = (unsigned long)&nmi;
        HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
diff -r d2705953c6d2 -r 67de34c062b5 
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h  Thu Apr 
 6 10:34:14 2006
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h  Thu Apr 
 6 11:03:53 2006
@@ -328,6 +328,13 @@
        unsigned long op, void *arg)
 {
        return _hypercall2(int, nmi_op, op, arg);
+}
+
+static inline int
+HYPERVISOR_callback_op(
+       int cmd, void *arg)
+{
+       return _hypercall2(int, callback_op, cmd, arg);
 }
 
 #endif /* __HYPERCALL_H__ */
diff -r d2705953c6d2 -r 67de34c062b5 
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h        
Thu Apr  6 10:34:14 2006
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h        
Thu Apr  6 11:03:53 2006
@@ -6,20 +6,33 @@
  *     use of all of the static functions.
  **/
 
+#include <xen/interface/callback.h>
+
 extern void hypervisor_callback(void);
 extern void failsafe_callback(void);
 extern void nmi(void);
 
 static void __init machine_specific_arch_setup(void)
 {
+       callback_register_t event = {
+               .type = CALLBACKTYPE_event,
+               .address = (unsigned long) hypervisor_callback,
+       };
+       callback_register_t failsafe = {
+               .type = CALLBACKTYPE_failsafe,
+               .address = (unsigned long)failsafe_callback,
+       };
+       callback_register_t syscall = {
+               .type = CALLBACKTYPE_syscall,
+               .address = (unsigned long)system_call,
+       };
 #ifdef CONFIG_X86_LOCAL_APIC
        struct xennmi_callback cb;
 #endif
 
-       HYPERVISOR_set_callbacks(
-                (unsigned long) hypervisor_callback,
-                (unsigned long) failsafe_callback,
-                (unsigned long) system_call);
+       HYPERVISOR_callback_op(CALLBACKOP_register, &event);
+       HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
+       HYPERVISOR_callback_op(CALLBACKOP_register, &syscall);
 
 #ifdef CONFIG_X86_LOCAL_APIC
        cb.handler_address = (unsigned long)&nmi;
diff -r d2705953c6d2 -r 67de34c062b5 xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S       Thu Apr  6 10:34:14 2006
+++ b/xen/arch/x86/x86_32/entry.S       Thu Apr  6 11:03:53 2006
@@ -648,6 +648,7 @@
         .long do_acm_op
         .long do_nmi_op
         .long do_arch_sched_op
+        .long do_callback_op        /* 30 */
         .rept NR_hypercalls-((.-hypercall_table)/4)
         .long do_ni_hypercall
         .endr
@@ -683,6 +684,7 @@
         .byte 1 /* do_acm_op            */
         .byte 2 /* do_nmi_op            */
         .byte 2 /* do_arch_sched_op     */
+        .byte 2 /* do_callback_op       */  /* 30 */
         .rept NR_hypercalls-(.-hypercall_args_table)
         .byte 0 /* do_ni_hypercall      */
         .endr
diff -r d2705953c6d2 -r 67de34c062b5 xen/arch/x86/x86_32/traps.c
--- a/xen/arch/x86/x86_32/traps.c       Thu Apr  6 10:34:14 2006
+++ b/xen/arch/x86/x86_32/traps.c       Thu Apr  6 11:03:53 2006
@@ -13,6 +13,8 @@
 #include <asm/flushtlb.h>
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/support.h>
+
+#include <public/callback.h>
 
 /* All CPUs have their own IDT to allow int80 direct trap. */
 idt_entry_t *idt_tables[NR_CPUS] = { 0 };
@@ -315,20 +317,102 @@
         set_int80_direct_trap(v);
 }
 
+static long register_guest_callback(struct callback_register *reg)
+{
+    long ret = 0;
+    struct vcpu *v = current;
+
+    if ( reg->address.cs )
+        fixup_guest_code_selector(reg->address.cs);
+
+    switch ( reg->type )
+    {
+    case CALLBACKTYPE_event:
+        v->arch.guest_context.event_callback_cs     = reg->address.cs;
+        v->arch.guest_context.event_callback_eip    = reg->address.eip;
+        break;
+
+    case CALLBACKTYPE_failsafe:
+        v->arch.guest_context.failsafe_callback_cs  = reg->address.cs;
+        v->arch.guest_context.failsafe_callback_eip = reg->address.eip;
+        break;
+
+    default:
+        ret = -EINVAL;
+        break;
+    }
+
+    return ret;
+}
+
+static long unregister_guest_callback(struct callback_unregister *unreg)
+{
+    long ret;
+
+    switch ( unreg->type )
+    {
+    default:
+        ret = -EINVAL;
+        break;
+    }
+    return ret;
+}
+
+
+long do_callback_op(int cmd, GUEST_HANDLE(void) arg)
+{
+    long ret;
+
+    switch ( cmd )
+    {
+    case CALLBACKOP_register:
+    {
+        struct callback_register reg;
+
+        ret = -EFAULT;
+        if ( copy_from_guest( &reg, arg, 1 ) )
+            break;
+
+        ret = register_guest_callback(&reg);
+    }
+    break;
+
+    case CALLBACKOP_unregister:
+    {
+        struct callback_unregister unreg;
+
+        ret = -EFAULT;
+        if ( copy_from_guest( &unreg, arg, 1 ) )
+            break;
+
+        ret = unregister_guest_callback(&unreg);
+    }
+    break;
+
+    default:
+        ret = -EINVAL;
+        break;
+    }
+
+    return ret;
+}
+
 long do_set_callbacks(unsigned long event_selector,
                       unsigned long event_address,
                       unsigned long failsafe_selector,
                       unsigned long failsafe_address)
 {
-    struct vcpu *d = current;
-
-    fixup_guest_code_selector(event_selector);
-    fixup_guest_code_selector(failsafe_selector);
-
-    d->arch.guest_context.event_callback_cs     = event_selector;
-    d->arch.guest_context.event_callback_eip    = event_address;
-    d->arch.guest_context.failsafe_callback_cs  = failsafe_selector;
-    d->arch.guest_context.failsafe_callback_eip = failsafe_address;
+    struct callback_register event = {
+        .type = CALLBACKTYPE_event,
+        .address = { event_selector, event_address },
+    };
+    struct callback_register failsafe = {
+        .type = CALLBACKTYPE_failsafe,
+        .address = { failsafe_selector, failsafe_address },
+    };
+
+    register_guest_callback(&event);
+    register_guest_callback(&failsafe);
 
     return 0;
 }
diff -r d2705953c6d2 -r 67de34c062b5 xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S       Thu Apr  6 10:34:14 2006
+++ b/xen/arch/x86/x86_64/entry.S       Thu Apr  6 11:03:53 2006
@@ -557,6 +557,7 @@
         .quad do_acm_op
         .quad do_nmi_op
         .quad do_arch_sched_op
+        .quad do_callback_op        /* 30 */
         .rept NR_hypercalls-((.-hypercall_table)/8)
         .quad do_ni_hypercall
         .endr
@@ -592,6 +593,7 @@
         .byte 1 /* do_acm_op            */
         .byte 2 /* do_nmi_op            */
         .byte 2 /* do_arch_sched_op     */
+        .byte 2 /* do_callback_op       */  /* 30 */
         .rept NR_hypercalls-(.-hypercall_args_table)
         .byte 0 /* do_ni_hypercall      */
         .endr
diff -r d2705953c6d2 -r 67de34c062b5 xen/arch/x86/x86_64/traps.c
--- a/xen/arch/x86/x86_64/traps.c       Thu Apr  6 10:34:14 2006
+++ b/xen/arch/x86/x86_64/traps.c       Thu Apr  6 11:03:53 2006
@@ -16,6 +16,8 @@
 #include <asm/shadow.h>
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/support.h>
+
+#include <public/callback.h>
 
 void show_registers(struct cpu_user_regs *regs)
 {
@@ -312,15 +314,105 @@
     wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U);
 }
 
+static long register_guest_callback(struct callback_register *reg)
+{
+    long ret = 0;
+    struct vcpu *v = current;
+
+    switch ( reg->type )
+    {
+    case CALLBACKTYPE_event:
+        v->arch.guest_context.event_callback_eip    = reg->address;
+        break;
+
+    case CALLBACKTYPE_failsafe:
+        v->arch.guest_context.failsafe_callback_eip = reg->address;
+        break;
+
+    case CALLBACKTYPE_syscall:
+        v->arch.guest_context.syscall_callback_eip  = reg->address;
+        break;
+
+    default:
+        ret = -EINVAL;
+        break;
+    }
+
+    return ret;
+}
+
+static long unregister_guest_callback(struct callback_unregister *unreg)
+{
+    long ret;
+
+    switch ( unreg->type )
+    {
+    default:
+        ret = -EINVAL;
+        break;
+    }
+    return ret;
+}
+
+
+long do_callback_op(int cmd, GUEST_HANDLE(void) arg)
+{
+    long ret;
+
+    switch ( cmd )
+    {
+    case CALLBACKOP_register:
+    {
+        struct callback_register reg;
+
+        ret = -EFAULT;
+        if ( copy_from_guest( &reg, arg, 1 ) )
+            break;
+
+        ret = register_guest_callback(&reg);
+    }
+    break;
+
+    case CALLBACKOP_unregister:
+    {
+        struct callback_unregister unreg;
+
+        ret = -EFAULT;
+        if ( copy_from_guest( &unreg, arg, 1 ) )
+            break;
+
+        ret = unregister_guest_callback(&unreg);
+    }
+    break;
+
+    default:
+        ret = -EINVAL;
+        break;
+    }
+
+    return ret;
+}
+
 long do_set_callbacks(unsigned long event_address,
                       unsigned long failsafe_address,
                       unsigned long syscall_address)
 {
-    struct vcpu *d = current;
-
-    d->arch.guest_context.event_callback_eip    = event_address;
-    d->arch.guest_context.failsafe_callback_eip = failsafe_address;
-    d->arch.guest_context.syscall_callback_eip  = syscall_address;
+    callback_register_t event = {
+        .type = CALLBACKTYPE_event,
+        .address = event_address,
+    };
+    callback_register_t failsafe = {
+        .type = CALLBACKTYPE_failsafe,
+        .address = failsafe_address,
+    };
+    callback_register_t syscall = {
+        .type = CALLBACKTYPE_syscall,
+        .address = syscall_address,
+    };
+
+    register_guest_callback(&event);
+    register_guest_callback(&failsafe);
+    register_guest_callback(&syscall);
 
     return 0;
 }
diff -r d2705953c6d2 -r 67de34c062b5 xen/include/public/arch-x86_32.h
--- a/xen/include/public/arch-x86_32.h  Thu Apr  6 10:34:14 2006
+++ b/xen/include/public/arch-x86_32.h  Thu Apr  6 11:03:53 2006
@@ -168,6 +168,11 @@
     unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */
 } arch_vcpu_info_t;
 
+typedef struct {
+    unsigned long cs;
+    unsigned long eip;
+} xen_callback_t;
+
 #endif /* !__ASSEMBLY__ */
 
 /*
diff -r d2705953c6d2 -r 67de34c062b5 xen/include/public/arch-x86_64.h
--- a/xen/include/public/arch-x86_64.h  Thu Apr  6 10:34:14 2006
+++ b/xen/include/public/arch-x86_64.h  Thu Apr  6 11:03:53 2006
@@ -244,6 +244,8 @@
     unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
 } arch_vcpu_info_t;
 
+typedef unsigned long xen_callback_t;
+
 #endif /* !__ASSEMBLY__ */
 
 /*
diff -r d2705953c6d2 -r 67de34c062b5 xen/include/public/xen.h
--- a/xen/include/public/xen.h  Thu Apr  6 10:34:14 2006
+++ b/xen/include/public/xen.h  Thu Apr  6 11:03:53 2006
@@ -60,6 +60,7 @@
 #define __HYPERVISOR_acm_op               27
 #define __HYPERVISOR_nmi_op               28
 #define __HYPERVISOR_sched_op             29
+#define __HYPERVISOR_callback_op          30
 
 /* 
  * VIRTUAL INTERRUPTS
diff -r d2705953c6d2 -r 67de34c062b5 xen/include/public/callback.h
--- /dev/null   Thu Apr  6 10:34:14 2006
+++ b/xen/include/public/callback.h     Thu Apr  6 11:03:53 2006
@@ -0,0 +1,57 @@
+/******************************************************************************
+ * callback.h
+ *
+ * Register guest OS callbacks with Xen.
+ *
+ * Copyright (c) 2006, Ian Campbell
+ */
+
+#ifndef __XEN_PUBLIC_CALLBACK_H__
+#define __XEN_PUBLIC_CALLBACK_H__
+
+#include "xen.h"
+
+/*
+ * Prototype for this hypercall is:
+ *   long callback_op(int cmd, void *extra_args)
+ * @cmd        == CALLBACKOP_??? (callback operation).
+ * @extra_args == Operation-specific extra arguments (NULL if none).
+ */
+
+#define CALLBACKTYPE_event                 0
+#define CALLBACKTYPE_failsafe              1
+#define CALLBACKTYPE_syscall               2 /* x86_64 only */
+
+/*
+ * Register a callback.
+ */
+#define CALLBACKOP_register                0
+typedef struct callback_register {
+     int type;
+     xen_callback_t address;
+} callback_register_t;
+DEFINE_GUEST_HANDLE(callback_register_t);
+
+/*
+ * Unregister a callback.
+ *
+ * Not all callbacks can be unregistered. -EINVAL will be returned if
+ * you attempt to unregister such a callback.
+ */
+#define CALLBACKOP_unregister              1
+typedef struct callback_unregister {
+     int type;
+} callback_unregister_t;
+DEFINE_GUEST_HANDLE(callback_unregister_t);
+
+#endif /* __XEN_PUBLIC_CALLBACK_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.