ia64/xen-unstable
changeset 9610:67de34c062b5
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@xensource.com>
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@xensource.com>
line diff
1.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h Thu Apr 06 11:34:14 2006 +0100 1.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h Thu Apr 06 12:03:53 2006 +0100 1.3 @@ -329,6 +329,14 @@ HYPERVISOR_nmi_op( 1.4 return _hypercall2(int, nmi_op, op, arg); 1.5 } 1.6 1.7 +static inline int 1.8 +HYPERVISOR_callback_op( 1.9 + int cmd, 1.10 + void *arg) 1.11 +{ 1.12 + return _hypercall2(int, callback_op, cmd, arg); 1.13 +} 1.14 + 1.15 #endif /* __HYPERCALL_H__ */ 1.16 1.17 /*
2.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h Thu Apr 06 11:34:14 2006 +0100 2.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h Thu Apr 06 12:03:53 2006 +0100 2.3 @@ -6,6 +6,8 @@ 2.4 * use of all of the static functions. 2.5 **/ 2.6 2.7 +#include <xen/interface/callback.h> 2.8 + 2.9 static char * __init machine_specific_memory_setup(void) 2.10 { 2.11 unsigned long max_pfn = xen_start_info->nr_pages; 2.12 @@ -23,6 +25,14 @@ extern void nmi(void); 2.13 static void __init machine_specific_arch_setup(void) 2.14 { 2.15 struct xen_platform_parameters pp; 2.16 + callback_register_t event = { 2.17 + .type = CALLBACKTYPE_event, 2.18 + .address = { __KERNEL_CS, (unsigned long)hypervisor_callback }, 2.19 + }; 2.20 + callback_register_t failsafe = { 2.21 + .type = CALLBACKTYPE_failsafe, 2.22 + .address = { __KERNEL_CS, (unsigned long)failsafe_callback }, 2.23 + }; 2.24 struct xennmi_callback cb; 2.25 2.26 if (xen_feature(XENFEAT_auto_translated_physmap) && 2.27 @@ -32,9 +42,8 @@ static void __init machine_specific_arch 2.28 memset(empty_zero_page, 0, sizeof(empty_zero_page)); 2.29 } 2.30 2.31 - HYPERVISOR_set_callbacks( 2.32 - __KERNEL_CS, (unsigned long)hypervisor_callback, 2.33 - __KERNEL_CS, (unsigned long)failsafe_callback); 2.34 + HYPERVISOR_callback_op(CALLBACKOP_register, &event); 2.35 + HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe); 2.36 2.37 cb.handler_address = (unsigned long)&nmi; 2.38 HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
3.1 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h Thu Apr 06 11:34:14 2006 +0100 3.2 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h Thu Apr 06 12:03:53 2006 +0100 3.3 @@ -330,6 +330,13 @@ HYPERVISOR_nmi_op( 3.4 return _hypercall2(int, nmi_op, op, arg); 3.5 } 3.6 3.7 +static inline int 3.8 +HYPERVISOR_callback_op( 3.9 + int cmd, void *arg) 3.10 +{ 3.11 + return _hypercall2(int, callback_op, cmd, arg); 3.12 +} 3.13 + 3.14 #endif /* __HYPERCALL_H__ */ 3.15 3.16 /*
4.1 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h Thu Apr 06 11:34:14 2006 +0100 4.2 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h Thu Apr 06 12:03:53 2006 +0100 4.3 @@ -6,20 +6,33 @@ 4.4 * use of all of the static functions. 4.5 **/ 4.6 4.7 +#include <xen/interface/callback.h> 4.8 + 4.9 extern void hypervisor_callback(void); 4.10 extern void failsafe_callback(void); 4.11 extern void nmi(void); 4.12 4.13 static void __init machine_specific_arch_setup(void) 4.14 { 4.15 + callback_register_t event = { 4.16 + .type = CALLBACKTYPE_event, 4.17 + .address = (unsigned long) hypervisor_callback, 4.18 + }; 4.19 + callback_register_t failsafe = { 4.20 + .type = CALLBACKTYPE_failsafe, 4.21 + .address = (unsigned long)failsafe_callback, 4.22 + }; 4.23 + callback_register_t syscall = { 4.24 + .type = CALLBACKTYPE_syscall, 4.25 + .address = (unsigned long)system_call, 4.26 + }; 4.27 #ifdef CONFIG_X86_LOCAL_APIC 4.28 struct xennmi_callback cb; 4.29 #endif 4.30 4.31 - HYPERVISOR_set_callbacks( 4.32 - (unsigned long) hypervisor_callback, 4.33 - (unsigned long) failsafe_callback, 4.34 - (unsigned long) system_call); 4.35 + HYPERVISOR_callback_op(CALLBACKOP_register, &event); 4.36 + HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe); 4.37 + HYPERVISOR_callback_op(CALLBACKOP_register, &syscall); 4.38 4.39 #ifdef CONFIG_X86_LOCAL_APIC 4.40 cb.handler_address = (unsigned long)&nmi;
5.1 --- a/xen/arch/x86/x86_32/entry.S Thu Apr 06 11:34:14 2006 +0100 5.2 +++ b/xen/arch/x86/x86_32/entry.S Thu Apr 06 12:03:53 2006 +0100 5.3 @@ -648,6 +648,7 @@ ENTRY(hypercall_table) 5.4 .long do_acm_op 5.5 .long do_nmi_op 5.6 .long do_arch_sched_op 5.7 + .long do_callback_op /* 30 */ 5.8 .rept NR_hypercalls-((.-hypercall_table)/4) 5.9 .long do_ni_hypercall 5.10 .endr 5.11 @@ -683,6 +684,7 @@ ENTRY(hypercall_args_table) 5.12 .byte 1 /* do_acm_op */ 5.13 .byte 2 /* do_nmi_op */ 5.14 .byte 2 /* do_arch_sched_op */ 5.15 + .byte 2 /* do_callback_op */ /* 30 */ 5.16 .rept NR_hypercalls-(.-hypercall_args_table) 5.17 .byte 0 /* do_ni_hypercall */ 5.18 .endr
6.1 --- a/xen/arch/x86/x86_32/traps.c Thu Apr 06 11:34:14 2006 +0100 6.2 +++ b/xen/arch/x86/x86_32/traps.c Thu Apr 06 12:03:53 2006 +0100 6.3 @@ -14,6 +14,8 @@ 6.4 #include <asm/hvm/hvm.h> 6.5 #include <asm/hvm/support.h> 6.6 6.7 +#include <public/callback.h> 6.8 + 6.9 /* All CPUs have their own IDT to allow int80 direct trap. */ 6.10 idt_entry_t *idt_tables[NR_CPUS] = { 0 }; 6.11 6.12 @@ -315,20 +317,102 @@ void init_int80_direct_trap(struct vcpu 6.13 set_int80_direct_trap(v); 6.14 } 6.15 6.16 +static long register_guest_callback(struct callback_register *reg) 6.17 +{ 6.18 + long ret = 0; 6.19 + struct vcpu *v = current; 6.20 + 6.21 + if ( reg->address.cs ) 6.22 + fixup_guest_code_selector(reg->address.cs); 6.23 + 6.24 + switch ( reg->type ) 6.25 + { 6.26 + case CALLBACKTYPE_event: 6.27 + v->arch.guest_context.event_callback_cs = reg->address.cs; 6.28 + v->arch.guest_context.event_callback_eip = reg->address.eip; 6.29 + break; 6.30 + 6.31 + case CALLBACKTYPE_failsafe: 6.32 + v->arch.guest_context.failsafe_callback_cs = reg->address.cs; 6.33 + v->arch.guest_context.failsafe_callback_eip = reg->address.eip; 6.34 + break; 6.35 + 6.36 + default: 6.37 + ret = -EINVAL; 6.38 + break; 6.39 + } 6.40 + 6.41 + return ret; 6.42 +} 6.43 + 6.44 +static long unregister_guest_callback(struct callback_unregister *unreg) 6.45 +{ 6.46 + long ret; 6.47 + 6.48 + switch ( unreg->type ) 6.49 + { 6.50 + default: 6.51 + ret = -EINVAL; 6.52 + break; 6.53 + } 6.54 + return ret; 6.55 +} 6.56 + 6.57 + 6.58 +long do_callback_op(int cmd, GUEST_HANDLE(void) arg) 6.59 +{ 6.60 + long ret; 6.61 + 6.62 + switch ( cmd ) 6.63 + { 6.64 + case CALLBACKOP_register: 6.65 + { 6.66 + struct callback_register reg; 6.67 + 6.68 + ret = -EFAULT; 6.69 + if ( copy_from_guest( ®, arg, 1 ) ) 6.70 + break; 6.71 + 6.72 + ret = register_guest_callback(®); 6.73 + } 6.74 + break; 6.75 + 6.76 + case CALLBACKOP_unregister: 6.77 + { 6.78 + struct callback_unregister unreg; 6.79 + 6.80 + ret = -EFAULT; 6.81 + if ( copy_from_guest( &unreg, arg, 1 ) ) 6.82 + break; 6.83 + 6.84 + ret = unregister_guest_callback(&unreg); 6.85 + } 6.86 + break; 6.87 + 6.88 + default: 6.89 + ret = -EINVAL; 6.90 + break; 6.91 + } 6.92 + 6.93 + return ret; 6.94 +} 6.95 + 6.96 long do_set_callbacks(unsigned long event_selector, 6.97 unsigned long event_address, 6.98 unsigned long failsafe_selector, 6.99 unsigned long failsafe_address) 6.100 { 6.101 - struct vcpu *d = current; 6.102 - 6.103 - fixup_guest_code_selector(event_selector); 6.104 - fixup_guest_code_selector(failsafe_selector); 6.105 + struct callback_register event = { 6.106 + .type = CALLBACKTYPE_event, 6.107 + .address = { event_selector, event_address }, 6.108 + }; 6.109 + struct callback_register failsafe = { 6.110 + .type = CALLBACKTYPE_failsafe, 6.111 + .address = { failsafe_selector, failsafe_address }, 6.112 + }; 6.113 6.114 - d->arch.guest_context.event_callback_cs = event_selector; 6.115 - d->arch.guest_context.event_callback_eip = event_address; 6.116 - d->arch.guest_context.failsafe_callback_cs = failsafe_selector; 6.117 - d->arch.guest_context.failsafe_callback_eip = failsafe_address; 6.118 + register_guest_callback(&event); 6.119 + register_guest_callback(&failsafe); 6.120 6.121 return 0; 6.122 }
7.1 --- a/xen/arch/x86/x86_64/entry.S Thu Apr 06 11:34:14 2006 +0100 7.2 +++ b/xen/arch/x86/x86_64/entry.S Thu Apr 06 12:03:53 2006 +0100 7.3 @@ -557,6 +557,7 @@ ENTRY(hypercall_table) 7.4 .quad do_acm_op 7.5 .quad do_nmi_op 7.6 .quad do_arch_sched_op 7.7 + .quad do_callback_op /* 30 */ 7.8 .rept NR_hypercalls-((.-hypercall_table)/8) 7.9 .quad do_ni_hypercall 7.10 .endr 7.11 @@ -592,6 +593,7 @@ ENTRY(hypercall_args_table) 7.12 .byte 1 /* do_acm_op */ 7.13 .byte 2 /* do_nmi_op */ 7.14 .byte 2 /* do_arch_sched_op */ 7.15 + .byte 2 /* do_callback_op */ /* 30 */ 7.16 .rept NR_hypercalls-(.-hypercall_args_table) 7.17 .byte 0 /* do_ni_hypercall */ 7.18 .endr
8.1 --- a/xen/arch/x86/x86_64/traps.c Thu Apr 06 11:34:14 2006 +0100 8.2 +++ b/xen/arch/x86/x86_64/traps.c Thu Apr 06 12:03:53 2006 +0100 8.3 @@ -17,6 +17,8 @@ 8.4 #include <asm/hvm/hvm.h> 8.5 #include <asm/hvm/support.h> 8.6 8.7 +#include <public/callback.h> 8.8 + 8.9 void show_registers(struct cpu_user_regs *regs) 8.10 { 8.11 struct cpu_user_regs fault_regs = *regs; 8.12 @@ -312,15 +314,105 @@ void __init percpu_traps_init(void) 8.13 wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U); 8.14 } 8.15 8.16 +static long register_guest_callback(struct callback_register *reg) 8.17 +{ 8.18 + long ret = 0; 8.19 + struct vcpu *v = current; 8.20 + 8.21 + switch ( reg->type ) 8.22 + { 8.23 + case CALLBACKTYPE_event: 8.24 + v->arch.guest_context.event_callback_eip = reg->address; 8.25 + break; 8.26 + 8.27 + case CALLBACKTYPE_failsafe: 8.28 + v->arch.guest_context.failsafe_callback_eip = reg->address; 8.29 + break; 8.30 + 8.31 + case CALLBACKTYPE_syscall: 8.32 + v->arch.guest_context.syscall_callback_eip = reg->address; 8.33 + break; 8.34 + 8.35 + default: 8.36 + ret = -EINVAL; 8.37 + break; 8.38 + } 8.39 + 8.40 + return ret; 8.41 +} 8.42 + 8.43 +static long unregister_guest_callback(struct callback_unregister *unreg) 8.44 +{ 8.45 + long ret; 8.46 + 8.47 + switch ( unreg->type ) 8.48 + { 8.49 + default: 8.50 + ret = -EINVAL; 8.51 + break; 8.52 + } 8.53 + return ret; 8.54 +} 8.55 + 8.56 + 8.57 +long do_callback_op(int cmd, GUEST_HANDLE(void) arg) 8.58 +{ 8.59 + long ret; 8.60 + 8.61 + switch ( cmd ) 8.62 + { 8.63 + case CALLBACKOP_register: 8.64 + { 8.65 + struct callback_register reg; 8.66 + 8.67 + ret = -EFAULT; 8.68 + if ( copy_from_guest( ®, arg, 1 ) ) 8.69 + break; 8.70 + 8.71 + ret = register_guest_callback(®); 8.72 + } 8.73 + break; 8.74 + 8.75 + case CALLBACKOP_unregister: 8.76 + { 8.77 + struct callback_unregister unreg; 8.78 + 8.79 + ret = -EFAULT; 8.80 + if ( copy_from_guest( &unreg, arg, 1 ) ) 8.81 + break; 8.82 + 8.83 + ret = unregister_guest_callback(&unreg); 8.84 + } 8.85 + break; 8.86 + 8.87 + default: 8.88 + ret = -EINVAL; 8.89 + break; 8.90 + } 8.91 + 8.92 + return ret; 8.93 +} 8.94 + 8.95 long do_set_callbacks(unsigned long event_address, 8.96 unsigned long failsafe_address, 8.97 unsigned long syscall_address) 8.98 { 8.99 - struct vcpu *d = current; 8.100 + callback_register_t event = { 8.101 + .type = CALLBACKTYPE_event, 8.102 + .address = event_address, 8.103 + }; 8.104 + callback_register_t failsafe = { 8.105 + .type = CALLBACKTYPE_failsafe, 8.106 + .address = failsafe_address, 8.107 + }; 8.108 + callback_register_t syscall = { 8.109 + .type = CALLBACKTYPE_syscall, 8.110 + .address = syscall_address, 8.111 + }; 8.112 8.113 - d->arch.guest_context.event_callback_eip = event_address; 8.114 - d->arch.guest_context.failsafe_callback_eip = failsafe_address; 8.115 - d->arch.guest_context.syscall_callback_eip = syscall_address; 8.116 + register_guest_callback(&event); 8.117 + register_guest_callback(&failsafe); 8.118 + register_guest_callback(&syscall); 8.119 8.120 return 0; 8.121 }
9.1 --- a/xen/include/public/arch-x86_32.h Thu Apr 06 11:34:14 2006 +0100 9.2 +++ b/xen/include/public/arch-x86_32.h Thu Apr 06 12:03:53 2006 +0100 9.3 @@ -168,6 +168,11 @@ typedef struct { 9.4 unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */ 9.5 } arch_vcpu_info_t; 9.6 9.7 +typedef struct { 9.8 + unsigned long cs; 9.9 + unsigned long eip; 9.10 +} xen_callback_t; 9.11 + 9.12 #endif /* !__ASSEMBLY__ */ 9.13 9.14 /*
10.1 --- a/xen/include/public/arch-x86_64.h Thu Apr 06 11:34:14 2006 +0100 10.2 +++ b/xen/include/public/arch-x86_64.h Thu Apr 06 12:03:53 2006 +0100 10.3 @@ -244,6 +244,8 @@ typedef struct { 10.4 unsigned long pad; /* sizeof(vcpu_info_t) == 64 */ 10.5 } arch_vcpu_info_t; 10.6 10.7 +typedef unsigned long xen_callback_t; 10.8 + 10.9 #endif /* !__ASSEMBLY__ */ 10.10 10.11 /*
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/xen/include/public/callback.h Thu Apr 06 12:03:53 2006 +0100 11.3 @@ -0,0 +1,57 @@ 11.4 +/****************************************************************************** 11.5 + * callback.h 11.6 + * 11.7 + * Register guest OS callbacks with Xen. 11.8 + * 11.9 + * Copyright (c) 2006, Ian Campbell 11.10 + */ 11.11 + 11.12 +#ifndef __XEN_PUBLIC_CALLBACK_H__ 11.13 +#define __XEN_PUBLIC_CALLBACK_H__ 11.14 + 11.15 +#include "xen.h" 11.16 + 11.17 +/* 11.18 + * Prototype for this hypercall is: 11.19 + * long callback_op(int cmd, void *extra_args) 11.20 + * @cmd == CALLBACKOP_??? (callback operation). 11.21 + * @extra_args == Operation-specific extra arguments (NULL if none). 11.22 + */ 11.23 + 11.24 +#define CALLBACKTYPE_event 0 11.25 +#define CALLBACKTYPE_failsafe 1 11.26 +#define CALLBACKTYPE_syscall 2 /* x86_64 only */ 11.27 + 11.28 +/* 11.29 + * Register a callback. 11.30 + */ 11.31 +#define CALLBACKOP_register 0 11.32 +typedef struct callback_register { 11.33 + int type; 11.34 + xen_callback_t address; 11.35 +} callback_register_t; 11.36 +DEFINE_GUEST_HANDLE(callback_register_t); 11.37 + 11.38 +/* 11.39 + * Unregister a callback. 11.40 + * 11.41 + * Not all callbacks can be unregistered. -EINVAL will be returned if 11.42 + * you attempt to unregister such a callback. 11.43 + */ 11.44 +#define CALLBACKOP_unregister 1 11.45 +typedef struct callback_unregister { 11.46 + int type; 11.47 +} callback_unregister_t; 11.48 +DEFINE_GUEST_HANDLE(callback_unregister_t); 11.49 + 11.50 +#endif /* __XEN_PUBLIC_CALLBACK_H__ */ 11.51 + 11.52 +/* 11.53 + * Local variables: 11.54 + * mode: C 11.55 + * c-set-style: "BSD" 11.56 + * c-basic-offset: 4 11.57 + * tab-width: 4 11.58 + * indent-tabs-mode: nil 11.59 + * End: 11.60 + */
12.1 --- a/xen/include/public/xen.h Thu Apr 06 11:34:14 2006 +0100 12.2 +++ b/xen/include/public/xen.h Thu Apr 06 12:03:53 2006 +0100 12.3 @@ -60,6 +60,7 @@ 12.4 #define __HYPERVISOR_acm_op 27 12.5 #define __HYPERVISOR_nmi_op 28 12.6 #define __HYPERVISOR_sched_op 29 12.7 +#define __HYPERVISOR_callback_op 30 12.8 12.9 /* 12.10 * VIRTUAL INTERRUPTS