mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 02:30:03 +01:00
Upgrade all hypercalls to use the new guest_handle interface (on the Xen side).
Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
15c0d5d00a
commit
97bdaa5bdf
35 files changed
+265
-265
No files matched your search
@@ -304,8 +304,7 @@ HYPERVISOR_suspend(
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_nmi_op(
|
||||
unsigned long op,
|
||||
unsigned long arg)
|
||||
unsigned long op, void *arg)
|
||||
{
|
||||
return _hypercall2(int, nmi_op, op, arg);
|
||||
}
|
||||
|
||||
@@ -35,12 +35,14 @@ extern void nmi(void);
|
||||
static void __init machine_specific_arch_setup(void)
|
||||
{
|
||||
struct xen_platform_parameters pp;
|
||||
struct xennmi_callback cb;
|
||||
|
||||
HYPERVISOR_set_callbacks(
|
||||
__KERNEL_CS, (unsigned long)hypervisor_callback,
|
||||
__KERNEL_CS, (unsigned long)failsafe_callback);
|
||||
|
||||
HYPERVISOR_nmi_op(XENNMI_register_callback, (unsigned long)&nmi);
|
||||
cb.handler_address = (unsigned long)&nmi;
|
||||
HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
|
||||
|
||||
machine_specific_modify_cpu_capabilities(&boot_cpu_data);
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include <xen/interface/xen.h>
|
||||
#include <xen/interface/sched.h>
|
||||
#include <xen/interface/nmi.h>
|
||||
|
||||
#define __STR(x) #x
|
||||
#define STR(x) __STR(x)
|
||||
@@ -304,8 +305,7 @@ HYPERVISOR_suspend(
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_nmi_op(
|
||||
unsigned long op,
|
||||
unsigned long arg)
|
||||
unsigned long op, void *arg)
|
||||
{
|
||||
return _hypercall2(int, nmi_op, op, arg);
|
||||
}
|
||||
|
||||
@@ -23,13 +23,18 @@ extern void nmi(void);
|
||||
|
||||
static void __init machine_specific_arch_setup(void)
|
||||
{
|
||||
#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);
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
HYPERVISOR_nmi_op(XENNMI_register_callback, (unsigned long)&nmi);
|
||||
cb.handler_address = (unsigned long)&nmi;
|
||||
HYPERVISOR_nmi_op(XENNMI_register_callback, cb);
|
||||
#endif
|
||||
|
||||
machine_specific_modify_cpu_capabilities(&boot_cpu_data);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <xen/config.h>
|
||||
#include <xen/errno.h>
|
||||
#include <asm/vmx_vcpu.h>
|
||||
//#include <public/xen.h>
|
||||
#include <xen/guest_access.h>
|
||||
#include <public/event_channel.h>
|
||||
#include <asm/vmmu.h>
|
||||
#include <asm/tlb.h>
|
||||
@@ -35,9 +35,6 @@
|
||||
#include <asm/dom_fw.h>
|
||||
#include <xen/domain.h>
|
||||
|
||||
extern long do_sched_op(int cmd, unsigned long arg);
|
||||
|
||||
|
||||
void hyper_not_support(void)
|
||||
{
|
||||
VCPU *vcpu=current;
|
||||
@@ -100,7 +97,7 @@ void hyper_dom0_op(void)
|
||||
VCPU *vcpu=current;
|
||||
u64 r32,ret;
|
||||
vcpu_get_gr_nat(vcpu,16,&r32);
|
||||
ret=do_dom0_op((dom0_op_t *)r32);
|
||||
ret=do_dom0_op(guest_handle_from_ptr(r32, dom0_op_t));
|
||||
vcpu_set_gr(vcpu, 8, ret, 0);
|
||||
|
||||
vmx_vcpu_increment_iip(vcpu);
|
||||
@@ -111,7 +108,7 @@ void hyper_event_channel_op(void)
|
||||
VCPU *vcpu=current;
|
||||
u64 r32,ret;
|
||||
vcpu_get_gr_nat(vcpu,16,&r32);
|
||||
ret=do_event_channel_op((evtchn_op_t *)r32);
|
||||
ret=do_event_channel_op(guest_handle_from_ptr(r32, evtchn_op_t));
|
||||
vcpu_set_gr(vcpu, 8, ret, 0);
|
||||
vmx_vcpu_increment_iip(vcpu);
|
||||
}
|
||||
@@ -122,7 +119,7 @@ void hyper_xen_version(void)
|
||||
u64 r32,r33,ret;
|
||||
vcpu_get_gr_nat(vcpu,16,&r32);
|
||||
vcpu_get_gr_nat(vcpu,17,&r33);
|
||||
ret=do_xen_version((int )r32,r33);
|
||||
ret=do_xen_version((int )r32,guest_handle_from_ptr(r33, void));
|
||||
vcpu_set_gr(vcpu, 8, ret, 0);
|
||||
vmx_vcpu_increment_iip(vcpu);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <xen/sched.h>
|
||||
#include <xen/hypercall.h>
|
||||
#include <xen/multicall.h>
|
||||
#include <xen/guest_access.h>
|
||||
|
||||
#include <linux/efi.h> /* FOR EFI_UNIMPLEMENTED */
|
||||
#include <asm/sal.h> /* FOR struct ia64_sal_retval */
|
||||
@@ -175,7 +176,8 @@ ia64_hypercall (struct pt_regs *regs)
|
||||
(int) vcpu_get_gr(v,33));
|
||||
break;
|
||||
case __HYPERVISOR_dom0_op:
|
||||
regs->r8 = do_dom0_op((struct dom0_op *) regs->r14);
|
||||
regs->r8 = do_dom0_op(guest_handle_from_ptr(regs->r14,
|
||||
dom0_op_t));
|
||||
break;
|
||||
|
||||
case __HYPERVISOR_memory_op:
|
||||
@@ -194,30 +196,30 @@ ia64_hypercall (struct pt_regs *regs)
|
||||
regs->r8 = reservation.nr_extents;
|
||||
break;
|
||||
default:
|
||||
regs->r8 = do_memory_op((int) regs->r14, (void *)regs->r15);
|
||||
regs->r8 = do_memory_op((int) regs->r14, guest_handle_from_ptr(regs->r15, void));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case __HYPERVISOR_event_channel_op:
|
||||
regs->r8 = do_event_channel_op((struct evtchn_op *) regs->r14);
|
||||
regs->r8 = do_event_channel_op(guest_handle_from_ptr(regs->r14, evtchn_op_t));
|
||||
break;
|
||||
|
||||
case __HYPERVISOR_grant_table_op:
|
||||
regs->r8 = do_grant_table_op((unsigned int) regs->r14, (void *) regs->r15, (unsigned int) regs->r16);
|
||||
regs->r8 = do_grant_table_op((unsigned int) regs->r14, guest_handle_from_ptr(regs->r15, void), (unsigned int) regs->r16);
|
||||
break;
|
||||
|
||||
case __HYPERVISOR_console_io:
|
||||
regs->r8 = do_console_io((int) regs->r14, (int) regs->r15, (char *) regs->r16);
|
||||
regs->r8 = do_console_io((int) regs->r14, (int) regs->r15, guest_handle_from_ptr(regs->r16, char));
|
||||
break;
|
||||
|
||||
case __HYPERVISOR_xen_version:
|
||||
regs->r8 = do_xen_version((int) regs->r14, (void *) regs->r15);
|
||||
regs->r8 = do_xen_version((int) regs->r14, guest_handle_from_ptr(regs->r15, void));
|
||||
break;
|
||||
|
||||
case __HYPERVISOR_multicall:
|
||||
regs->r8 = do_multicall((struct multicall_entry *) regs->r14, (unsigned int) regs->r15);
|
||||
regs->r8 = do_multicall(guest_handle_from_ptr(regs->r14, multicall_entry_t), (unsigned int) regs->r15);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -825,7 +825,6 @@ unsigned long hypercall_create_continuation(
|
||||
case 'l':
|
||||
arg = (unsigned long)va_arg(args, unsigned long);
|
||||
break;
|
||||
case 'p':
|
||||
case 'h':
|
||||
arg = (unsigned long)va_arg(args, void *);
|
||||
break;
|
||||
|
||||
+37
-1
@@ -451,6 +451,43 @@ int arch_set_info_guest(
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
arch_do_vcpu_op(
|
||||
int cmd, struct vcpu *v, GUEST_HANDLE(void) arg)
|
||||
{
|
||||
long rc = 0;
|
||||
|
||||
switch ( cmd )
|
||||
{
|
||||
case VCPUOP_register_runstate_memory_area:
|
||||
{
|
||||
struct vcpu_register_runstate_memory_area area;
|
||||
|
||||
rc = -EINVAL;
|
||||
if ( v != current )
|
||||
break;
|
||||
|
||||
rc = -EFAULT;
|
||||
if ( copy_from_guest(&area, arg, 1) )
|
||||
break;
|
||||
|
||||
if ( !access_ok(area.addr.v, sizeof(*area.addr.v)) )
|
||||
break;
|
||||
|
||||
rc = 0;
|
||||
v->runstate_guest = area.addr.v;
|
||||
__copy_to_user(v->runstate_guest, &v->runstate, sizeof(v->runstate));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
rc = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void new_thread(struct vcpu *d,
|
||||
unsigned long start_pc,
|
||||
@@ -831,7 +868,6 @@ void sync_vcpu_execstate(struct vcpu *v)
|
||||
{ \
|
||||
case 'i': __arg = (unsigned long)va_arg(args, unsigned int); break; \
|
||||
case 'l': __arg = (unsigned long)va_arg(args, unsigned long); break; \
|
||||
case 'p': __arg = (unsigned long)va_arg(args, void *); break; \
|
||||
case 'h': __arg = (unsigned long)va_arg(args, void *); break; \
|
||||
default: __arg = 0; BUG(); \
|
||||
} \
|
||||
|
||||
+28
-25
@@ -1732,14 +1732,15 @@ static inline cpumask_t vcpumask_to_pcpumask(
|
||||
}
|
||||
|
||||
int do_mmuext_op(
|
||||
struct mmuext_op *uops,
|
||||
GUEST_HANDLE(mmuext_op_t) uops,
|
||||
unsigned int count,
|
||||
unsigned int *pdone,
|
||||
GUEST_HANDLE(uint) pdone,
|
||||
unsigned int foreigndom)
|
||||
{
|
||||
struct mmuext_op op;
|
||||
int rc = 0, i = 0, okay, cpu = smp_processor_id();
|
||||
unsigned long mfn, type, done = 0;
|
||||
unsigned long mfn, type;
|
||||
unsigned int done = 0;
|
||||
struct page_info *page;
|
||||
struct vcpu *v = current;
|
||||
struct domain *d = v->domain;
|
||||
@@ -1751,8 +1752,8 @@ int do_mmuext_op(
|
||||
if ( unlikely(count & MMU_UPDATE_PREEMPTED) )
|
||||
{
|
||||
count &= ~MMU_UPDATE_PREEMPTED;
|
||||
if ( unlikely(pdone != NULL) )
|
||||
(void)get_user(done, pdone);
|
||||
if ( unlikely(!guest_handle_is_null(pdone)) )
|
||||
(void)copy_from_guest(&done, pdone, 1);
|
||||
}
|
||||
|
||||
if ( !set_foreigndom(cpu, foreigndom) )
|
||||
@@ -1761,7 +1762,7 @@ int do_mmuext_op(
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( unlikely(!array_access_ok(uops, count, sizeof(op))) )
|
||||
if ( unlikely(!guest_handle_okay(uops, count)) )
|
||||
{
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
@@ -1772,14 +1773,14 @@ int do_mmuext_op(
|
||||
if ( hypercall_preempt_check() )
|
||||
{
|
||||
rc = hypercall_create_continuation(
|
||||
__HYPERVISOR_mmuext_op, "pipi",
|
||||
__HYPERVISOR_mmuext_op, "hihi",
|
||||
uops, (count - i) | MMU_UPDATE_PREEMPTED, pdone, foreigndom);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( unlikely(__copy_from_user(&op, uops, sizeof(op)) != 0) )
|
||||
if ( unlikely(__copy_from_guest(&op, uops, 1) != 0) )
|
||||
{
|
||||
MEM_LOG("Bad __copy_from_user");
|
||||
MEM_LOG("Bad __copy_from_guest");
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
@@ -1969,24 +1970,25 @@ int do_mmuext_op(
|
||||
break;
|
||||
}
|
||||
|
||||
uops++;
|
||||
guest_handle_add_offset(uops, 1);
|
||||
}
|
||||
|
||||
out:
|
||||
process_deferred_ops(cpu);
|
||||
|
||||
/* Add incremental work we have done to the @done output parameter. */
|
||||
if ( unlikely(pdone != NULL) )
|
||||
__put_user(done + i, pdone);
|
||||
done += i;
|
||||
if ( unlikely(!guest_handle_is_null(pdone)) )
|
||||
copy_to_guest(pdone, &done, 1);
|
||||
|
||||
UNLOCK_BIGLOCK(d);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int do_mmu_update(
|
||||
struct mmu_update *ureqs,
|
||||
GUEST_HANDLE(mmu_update_t) ureqs,
|
||||
unsigned int count,
|
||||
unsigned int *pdone,
|
||||
GUEST_HANDLE(uint) pdone,
|
||||
unsigned int foreigndom)
|
||||
{
|
||||
struct mmu_update req;
|
||||
@@ -2010,8 +2012,8 @@ int do_mmu_update(
|
||||
if ( unlikely(count & MMU_UPDATE_PREEMPTED) )
|
||||
{
|
||||
count &= ~MMU_UPDATE_PREEMPTED;
|
||||
if ( unlikely(pdone != NULL) )
|
||||
(void)get_user(done, pdone);
|
||||
if ( unlikely(!guest_handle_is_null(pdone)) )
|
||||
(void)copy_from_guest(&done, pdone, 1);
|
||||
}
|
||||
|
||||
domain_mmap_cache_init(&mapcache);
|
||||
@@ -2027,7 +2029,7 @@ int do_mmu_update(
|
||||
perfc_addc(num_page_updates, count);
|
||||
perfc_incr_histo(bpt_updates, count, PT_UPDATES);
|
||||
|
||||
if ( unlikely(!array_access_ok(ureqs, count, sizeof(req))) )
|
||||
if ( unlikely(!guest_handle_okay(ureqs, count)) )
|
||||
{
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
@@ -2038,14 +2040,14 @@ int do_mmu_update(
|
||||
if ( hypercall_preempt_check() )
|
||||
{
|
||||
rc = hypercall_create_continuation(
|
||||
__HYPERVISOR_mmu_update, "pipi",
|
||||
__HYPERVISOR_mmu_update, "hihi",
|
||||
ureqs, (count - i) | MMU_UPDATE_PREEMPTED, pdone, foreigndom);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( unlikely(__copy_from_user(&req, ureqs, sizeof(req)) != 0) )
|
||||
if ( unlikely(__copy_from_guest(&req, ureqs, 1) != 0) )
|
||||
{
|
||||
MEM_LOG("Bad __copy_from_user");
|
||||
MEM_LOG("Bad __copy_from_guest");
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
@@ -2212,7 +2214,7 @@ int do_mmu_update(
|
||||
break;
|
||||
}
|
||||
|
||||
ureqs++;
|
||||
guest_handle_add_offset(ureqs, 1);
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -2222,8 +2224,9 @@ int do_mmu_update(
|
||||
process_deferred_ops(cpu);
|
||||
|
||||
/* Add incremental work we have done to the @done output parameter. */
|
||||
if ( unlikely(pdone != NULL) )
|
||||
__put_user(done + i, pdone);
|
||||
done += i;
|
||||
if ( unlikely(!guest_handle_is_null(pdone)) )
|
||||
copy_to_guest(pdone, &done, 1);
|
||||
|
||||
if ( unlikely(shadow_mode_enabled(d)) )
|
||||
check_pagetable(v, "post-mmu"); /* debug */
|
||||
@@ -2684,7 +2687,7 @@ long set_gdt(struct vcpu *v,
|
||||
}
|
||||
|
||||
|
||||
long do_set_gdt(unsigned long *frame_list, unsigned int entries)
|
||||
long do_set_gdt(GUEST_HANDLE(ulong) frame_list, unsigned int entries)
|
||||
{
|
||||
int nr_pages = (entries + 511) / 512;
|
||||
unsigned long frames[16];
|
||||
@@ -2694,7 +2697,7 @@ long do_set_gdt(unsigned long *frame_list, unsigned int entries)
|
||||
if ( entries > FIRST_RESERVED_GDT_ENTRY )
|
||||
return -EINVAL;
|
||||
|
||||
if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) )
|
||||
if ( copy_from_guest((unsigned long *)frames, frame_list, nr_pages) )
|
||||
return -EFAULT;
|
||||
|
||||
LOCK_BIGLOCK(current->domain);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xen/sched.h>
|
||||
#include <xen/irq.h>
|
||||
#include <xen/event.h>
|
||||
#include <xen/guest_access.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/smpboot.h>
|
||||
#include <public/xen.h>
|
||||
@@ -21,13 +22,13 @@ ioapic_guest_write(
|
||||
/*
|
||||
* Demuxing hypercall.
|
||||
*/
|
||||
long do_physdev_op(struct physdev_op *uop)
|
||||
long do_physdev_op(GUEST_HANDLE(physdev_op_t) uop)
|
||||
{
|
||||
struct physdev_op op;
|
||||
long ret;
|
||||
int irq;
|
||||
|
||||
if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
|
||||
if ( unlikely(copy_from_guest(&op, uop, 1) != 0) )
|
||||
return -EFAULT;
|
||||
|
||||
switch ( op.cmd )
|
||||
@@ -101,7 +102,7 @@ long do_physdev_op(struct physdev_op *uop)
|
||||
break;
|
||||
}
|
||||
|
||||
if ( copy_to_user(uop, &op, sizeof(op)) )
|
||||
if ( copy_to_guest(uop, &op, 1) )
|
||||
ret = -EFAULT;
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -1404,14 +1404,14 @@ void __init trap_init(void)
|
||||
}
|
||||
|
||||
|
||||
long do_set_trap_table(struct trap_info *traps)
|
||||
long do_set_trap_table(GUEST_HANDLE(trap_info_t) traps)
|
||||
{
|
||||
struct trap_info cur;
|
||||
struct trap_info *dst = current->arch.guest_context.trap_ctxt;
|
||||
long rc = 0;
|
||||
|
||||
/* If no table is presented then clear the entire virtual IDT. */
|
||||
if ( traps == NULL )
|
||||
if ( guest_handle_is_null(traps) )
|
||||
{
|
||||
memset(dst, 0, 256 * sizeof(*dst));
|
||||
init_int80_direct_trap(current);
|
||||
@@ -1423,11 +1423,11 @@ long do_set_trap_table(struct trap_info *traps)
|
||||
if ( hypercall_preempt_check() )
|
||||
{
|
||||
rc = hypercall_create_continuation(
|
||||
__HYPERVISOR_set_trap_table, "p", traps);
|
||||
__HYPERVISOR_set_trap_table, "h", traps);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( copy_from_user(&cur, traps, sizeof(cur)) )
|
||||
if ( copy_from_guest(&cur, traps, 1) )
|
||||
{
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
@@ -1443,7 +1443,7 @@ long do_set_trap_table(struct trap_info *traps)
|
||||
if ( cur.vector == 0x80 )
|
||||
init_int80_direct_trap(current);
|
||||
|
||||
traps++;
|
||||
guest_handle_add_offset(traps, 1);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
@@ -25,13 +25,14 @@
|
||||
#include <xen/event.h>
|
||||
#include <xen/trace.h>
|
||||
#include <xen/console.h>
|
||||
#include <xen/guest_access.h>
|
||||
#include <asm/shadow.h>
|
||||
#include <public/sched_ctl.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
|
||||
#ifndef ACM_SECURITY
|
||||
|
||||
long do_acm_op(struct acm_op * u_acm_op)
|
||||
long do_acm_op(GUEST_HANDLE(acm_op_t) u_acm_op)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
@@ -56,7 +57,7 @@ int acm_authorize_acm_ops(struct domain *d, enum acm_operation pops)
|
||||
return 0;
|
||||
}
|
||||
|
||||
long do_acm_op(struct acm_op * u_acm_op)
|
||||
long do_acm_op(GUEST_HANDLE(acm_op_t) u_acm_op)
|
||||
{
|
||||
long ret = 0;
|
||||
struct acm_op curop, *op = &curop;
|
||||
@@ -64,7 +65,7 @@ long do_acm_op(struct acm_op * u_acm_op)
|
||||
if (acm_authorize_acm_ops(current->domain, POLICY))
|
||||
return -EPERM;
|
||||
|
||||
if (copy_from_user(op, u_acm_op, sizeof(*op)))
|
||||
if (copy_from_guest(op, u_acm_op, 1))
|
||||
return -EFAULT;
|
||||
|
||||
if (op->interface_version != ACM_INTERFACE_VERSION)
|
||||
@@ -88,7 +89,7 @@ long do_acm_op(struct acm_op * u_acm_op)
|
||||
ret = acm_get_policy(op->u.getpolicy.pullcache,
|
||||
op->u.getpolicy.pullcache_size);
|
||||
if (!ret)
|
||||
copy_to_user(u_acm_op, op, sizeof(*op));
|
||||
copy_to_guest(u_acm_op, op, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -99,7 +100,7 @@ long do_acm_op(struct acm_op * u_acm_op)
|
||||
ret = acm_dump_statistics(op->u.dumpstats.pullcache,
|
||||
op->u.dumpstats.pullcache_size);
|
||||
if (!ret)
|
||||
copy_to_user(u_acm_op, op, sizeof(*op));
|
||||
copy_to_guest(u_acm_op, op, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -139,7 +140,7 @@ long do_acm_op(struct acm_op * u_acm_op)
|
||||
op->u.getssid.ssidbuf,
|
||||
op->u.getssid.ssidbuf_size);
|
||||
if (!ret)
|
||||
copy_to_user(u_acm_op, op, sizeof(*op));
|
||||
copy_to_guest(u_acm_op, op, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -215,7 +216,7 @@ long do_acm_op(struct acm_op * u_acm_op)
|
||||
ret = -ESRCH;
|
||||
|
||||
if (!ret)
|
||||
copy_to_user(u_acm_op, op, sizeof(*op));
|
||||
copy_to_guest(u_acm_op, op, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <xen/errno.h>
|
||||
#include <xen/bitmap.h>
|
||||
#include <xen/bitops.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
/*
|
||||
* bitmaps provide an array of bits, implemented using an an
|
||||
|
||||
+5
-26
@@ -18,6 +18,7 @@
|
||||
#include <xen/domain_page.h>
|
||||
#include <xen/rangeset.h>
|
||||
#include <xen/guest_access.h>
|
||||
#include <xen/hypercall.h>
|
||||
#include <asm/debugger.h>
|
||||
#include <public/dom0_ops.h>
|
||||
#include <public/sched.h>
|
||||
@@ -399,7 +400,7 @@ int boot_vcpu(struct domain *d, int vcpuid, struct vcpu_guest_context *ctxt)
|
||||
return arch_set_info_guest(v, ctxt);
|
||||
}
|
||||
|
||||
long do_vcpu_op(int cmd, int vcpuid, void *arg)
|
||||
long do_vcpu_op(int cmd, int vcpuid, GUEST_HANDLE(void) arg)
|
||||
{
|
||||
struct domain *d = current->domain;
|
||||
struct vcpu *v;
|
||||
@@ -421,7 +422,7 @@ long do_vcpu_op(int cmd, int vcpuid, void *arg)
|
||||
break;
|
||||
}
|
||||
|
||||
if ( copy_from_user(ctxt, arg, sizeof(*ctxt)) )
|
||||
if ( copy_from_guest(ctxt, arg, 1) )
|
||||
{
|
||||
xfree(ctxt);
|
||||
rc = -EFAULT;
|
||||
@@ -457,35 +458,13 @@ long do_vcpu_op(int cmd, int vcpuid, void *arg)
|
||||
{
|
||||
struct vcpu_runstate_info runstate;
|
||||
vcpu_runstate_get(v, &runstate);
|
||||
if ( copy_to_user(arg, &runstate, sizeof(runstate)) )
|
||||
if ( copy_to_guest(arg, &runstate, 1) )
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
case VCPUOP_register_runstate_memory_area:
|
||||
{
|
||||
struct vcpu_register_runstate_memory_area area;
|
||||
|
||||
rc = -EINVAL;
|
||||
if ( v != current )
|
||||
break;
|
||||
|
||||
rc = -EFAULT;
|
||||
if ( copy_from_user(&area, arg, sizeof(area)) )
|
||||
break;
|
||||
|
||||
if ( !access_ok(area.addr.v, sizeof(*area.addr.v)) )
|
||||
break;
|
||||
|
||||
rc = 0;
|
||||
v->runstate_guest = area.addr.v;
|
||||
__copy_to_user(v->runstate_guest, &v->runstate, sizeof(v->runstate));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
rc = -ENOSYS;
|
||||
rc = arch_do_vcpu_op(cmd, v, arg);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <xen/event.h>
|
||||
#include <xen/irq.h>
|
||||
#include <xen/iocap.h>
|
||||
#include <xen/guest_access.h>
|
||||
#include <asm/current.h>
|
||||
|
||||
#include <public/xen.h>
|
||||
@@ -578,12 +579,12 @@ static long evtchn_unmask(evtchn_unmask_t *unmask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
long do_event_channel_op(struct evtchn_op *uop)
|
||||
long do_event_channel_op(GUEST_HANDLE(evtchn_op_t) uop)
|
||||
{
|
||||
long rc;
|
||||
struct evtchn_op op;
|
||||
|
||||
if ( copy_from_user(&op, uop, sizeof(op)) != 0 )
|
||||
if ( copy_from_guest(&op, uop, 1) != 0 )
|
||||
return -EFAULT;
|
||||
|
||||
if (acm_pre_event_channel(&op))
|
||||
@@ -593,31 +594,31 @@ long do_event_channel_op(struct evtchn_op *uop)
|
||||
{
|
||||
case EVTCHNOP_alloc_unbound:
|
||||
rc = evtchn_alloc_unbound(&op.u.alloc_unbound);
|
||||
if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
|
||||
if ( (rc == 0) && (copy_to_guest(uop, &op, 1) != 0) )
|
||||
rc = -EFAULT; /* Cleaning up here would be a mess! */
|
||||
break;
|
||||
|
||||
case EVTCHNOP_bind_interdomain:
|
||||
rc = evtchn_bind_interdomain(&op.u.bind_interdomain);
|
||||
if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
|
||||
if ( (rc == 0) && (copy_to_guest(uop, &op, 1) != 0) )
|
||||
rc = -EFAULT; /* Cleaning up here would be a mess! */
|
||||
break;
|
||||
|
||||
case EVTCHNOP_bind_virq:
|
||||
rc = evtchn_bind_virq(&op.u.bind_virq);
|
||||
if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
|
||||
if ( (rc == 0) && (copy_to_guest(uop, &op, 1) != 0) )
|
||||
rc = -EFAULT; /* Cleaning up here would be a mess! */
|
||||
break;
|
||||
|
||||
case EVTCHNOP_bind_ipi:
|
||||
rc = evtchn_bind_ipi(&op.u.bind_ipi);
|
||||
if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
|
||||
if ( (rc == 0) && (copy_to_guest(uop, &op, 1) != 0) )
|
||||
rc = -EFAULT; /* Cleaning up here would be a mess! */
|
||||
break;
|
||||
|
||||
case EVTCHNOP_bind_pirq:
|
||||
rc = evtchn_bind_pirq(&op.u.bind_pirq);
|
||||
if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
|
||||
if ( (rc == 0) && (copy_to_guest(uop, &op, 1) != 0) )
|
||||
rc = -EFAULT; /* Cleaning up here would be a mess! */
|
||||
break;
|
||||
|
||||
@@ -631,7 +632,7 @@ long do_event_channel_op(struct evtchn_op *uop)
|
||||
|
||||
case EVTCHNOP_status:
|
||||
rc = evtchn_status(&op.u.status);
|
||||
if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
|
||||
if ( (rc == 0) && (copy_to_guest(uop, &op, 1) != 0) )
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
than any actual intention. It doesn't at the moment. */
|
||||
|
||||
#include <xen/lib.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <xen/spinlock.h>
|
||||
#include <xen/serial.h>
|
||||
#include <xen/irq.h>
|
||||
|
||||
+44
-42
@@ -28,8 +28,9 @@
|
||||
#include <xen/sched.h>
|
||||
#include <xen/shadow.h>
|
||||
#include <xen/mm.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
#include <xen/trace.h>
|
||||
#include <xen/guest_access.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
|
||||
#define PIN_FAIL(_lbl, _rc, _f, _a...) \
|
||||
do { \
|
||||
@@ -187,7 +188,7 @@ __gnttab_map_grant_ref(
|
||||
|
||||
/* Merge two 16-bit values into a 32-bit combined update. */
|
||||
/* NB. Endianness! */
|
||||
prev_scombo = scombo = ((u32)sdom << 16) | (u32)sflags;
|
||||
scombo = ((u32)sdom << 16) | (u32)sflags;
|
||||
|
||||
new_scombo = scombo | GTF_reading;
|
||||
if ( !(op->flags & GNTMAP_readonly) )
|
||||
@@ -198,12 +199,7 @@ __gnttab_map_grant_ref(
|
||||
"Attempt to write-pin a r/o grant entry.\n");
|
||||
}
|
||||
|
||||
/* NB. prev_scombo is updated in place to seen value. */
|
||||
if ( unlikely(cmpxchg_user((u32 *)&sha->flags,
|
||||
prev_scombo,
|
||||
new_scombo)) )
|
||||
PIN_FAIL(unlock_out, GNTST_general_error,
|
||||
"Fault while modifying shared flags and domid.\n");
|
||||
prev_scombo = cmpxchg((u32 *)&sha->flags, scombo, new_scombo);
|
||||
|
||||
/* Did the combined update work (did we see what we expected?). */
|
||||
if ( likely(prev_scombo == scombo) )
|
||||
@@ -306,17 +302,17 @@ __gnttab_map_grant_ref(
|
||||
|
||||
static long
|
||||
gnttab_map_grant_ref(
|
||||
struct gnttab_map_grant_ref *uop, unsigned int count)
|
||||
GUEST_HANDLE(gnttab_map_grant_ref_t) uop, unsigned int count)
|
||||
{
|
||||
int i;
|
||||
struct gnttab_map_grant_ref op;
|
||||
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
if ( unlikely(__copy_from_user(&op, &uop[i], sizeof(op))) )
|
||||
if ( unlikely(__copy_from_guest_offset(&op, uop, i, 1)) )
|
||||
return -EFAULT;
|
||||
__gnttab_map_grant_ref(&op);
|
||||
if ( unlikely(__copy_to_user(&uop[i], &op, sizeof(op))) )
|
||||
if ( unlikely(__copy_to_guest_offset(uop, i, &op, 1)) )
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
@@ -443,17 +439,17 @@ __gnttab_unmap_grant_ref(
|
||||
|
||||
static long
|
||||
gnttab_unmap_grant_ref(
|
||||
struct gnttab_unmap_grant_ref *uop, unsigned int count)
|
||||
GUEST_HANDLE(gnttab_unmap_grant_ref_t) uop, unsigned int count)
|
||||
{
|
||||
int i;
|
||||
struct gnttab_unmap_grant_ref op;
|
||||
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
if ( unlikely(__copy_from_user(&op, &uop[i], sizeof(op))) )
|
||||
if ( unlikely(__copy_from_guest_offset(&op, uop, i, 1)) )
|
||||
goto fault;
|
||||
__gnttab_unmap_grant_ref(&op);
|
||||
if ( unlikely(__copy_to_user(&uop[i], &op, sizeof(op))) )
|
||||
if ( unlikely(__copy_to_guest_offset(uop, i, &op, 1)) )
|
||||
goto fault;
|
||||
}
|
||||
|
||||
@@ -467,7 +463,7 @@ fault:
|
||||
|
||||
static long
|
||||
gnttab_setup_table(
|
||||
struct gnttab_setup_table *uop, unsigned int count)
|
||||
GUEST_HANDLE(gnttab_setup_table_t) uop, unsigned int count)
|
||||
{
|
||||
struct gnttab_setup_table op;
|
||||
struct domain *d;
|
||||
@@ -478,7 +474,7 @@ gnttab_setup_table(
|
||||
if ( count != 1 )
|
||||
return -EINVAL;
|
||||
|
||||
if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
|
||||
if ( unlikely(copy_from_guest(&op, uop, 1) != 0) )
|
||||
{
|
||||
DPRINTK("Fault while reading gnttab_setup_table_t.\n");
|
||||
return -EFAULT;
|
||||
@@ -517,14 +513,14 @@ gnttab_setup_table(
|
||||
for ( i = 0; i < op.nr_frames; i++ )
|
||||
{
|
||||
gmfn = gnttab_shared_gmfn(d, d->grant_table, i);
|
||||
(void)copy_to_user(&op.frame_list[i], &gmfn, sizeof(gmfn));
|
||||
(void)copy_to_guest_offset(op.frame_list, i, &gmfn, 1);
|
||||
}
|
||||
}
|
||||
|
||||
put_domain(d);
|
||||
|
||||
out:
|
||||
if ( unlikely(copy_to_user(uop, &op, sizeof(op))) )
|
||||
if ( unlikely(copy_to_guest(uop, &op, 1)) )
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
@@ -572,15 +568,10 @@ gnttab_prepare_for_transfer(
|
||||
|
||||
/* Merge two 16-bit values into a 32-bit combined update. */
|
||||
/* NB. Endianness! */
|
||||
prev_scombo = scombo = ((u32)sdom << 16) | (u32)sflags;
|
||||
scombo = ((u32)sdom << 16) | (u32)sflags;
|
||||
|
||||
/* NB. prev_scombo is updated in place to seen value. */
|
||||
if ( unlikely(cmpxchg_user((u32 *)&sha->flags, prev_scombo,
|
||||
prev_scombo | GTF_transfer_committed)) )
|
||||
{
|
||||
DPRINTK("Fault while modifying shared flags and domid.\n");
|
||||
goto fail;
|
||||
}
|
||||
prev_scombo = cmpxchg((u32 *)&sha->flags, scombo,
|
||||
scombo | GTF_transfer_committed);
|
||||
|
||||
/* Did the combined update work (did we see what we expected?). */
|
||||
if ( likely(prev_scombo == scombo) )
|
||||
@@ -608,7 +599,7 @@ gnttab_prepare_for_transfer(
|
||||
|
||||
static long
|
||||
gnttab_transfer(
|
||||
struct gnttab_transfer *uop, unsigned int count)
|
||||
GUEST_HANDLE(gnttab_transfer_t) uop, unsigned int count)
|
||||
{
|
||||
struct domain *d = current->domain;
|
||||
struct domain *e;
|
||||
@@ -621,7 +612,7 @@ gnttab_transfer(
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
/* Read from caller address space. */
|
||||
if ( unlikely(__copy_from_user(&gop, &uop[i], sizeof(gop))) )
|
||||
if ( unlikely(__copy_from_guest_offset(&gop, uop, i, 1)) )
|
||||
{
|
||||
DPRINTK("gnttab_transfer: error reading req %d/%d\n", i, count);
|
||||
return -EFAULT;
|
||||
@@ -708,7 +699,7 @@ gnttab_transfer(
|
||||
gop.status = GNTST_okay;
|
||||
|
||||
copyback:
|
||||
if ( unlikely(__copy_from_user(&uop[i], &gop, sizeof(gop))) )
|
||||
if ( unlikely(__copy_to_guest_offset(uop, i, &gop, 1)) )
|
||||
{
|
||||
DPRINTK("gnttab_transfer: error writing resp %d/%d\n", i, count);
|
||||
return -EFAULT;
|
||||
@@ -718,9 +709,9 @@ gnttab_transfer(
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
long
|
||||
do_grant_table_op(
|
||||
unsigned int cmd, void *uop, unsigned int count)
|
||||
unsigned int cmd, GUEST_HANDLE(void) uop, unsigned int count)
|
||||
{
|
||||
long rc;
|
||||
struct domain *d = current->domain;
|
||||
@@ -736,27 +727,38 @@ do_grant_table_op(
|
||||
switch ( cmd )
|
||||
{
|
||||
case GNTTABOP_map_grant_ref:
|
||||
if ( unlikely(!array_access_ok(
|
||||
uop, count, sizeof(gnttab_map_grant_ref_t))) )
|
||||
{
|
||||
GUEST_HANDLE(gnttab_map_grant_ref_t) map =
|
||||
guest_handle_cast(uop, gnttab_map_grant_ref_t);
|
||||
if ( unlikely(!guest_handle_okay(map, count)) )
|
||||
goto out;
|
||||
rc = gnttab_map_grant_ref((gnttab_map_grant_ref_t *)uop, count);
|
||||
rc = gnttab_map_grant_ref(map, count);
|
||||
break;
|
||||
}
|
||||
case GNTTABOP_unmap_grant_ref:
|
||||
if ( unlikely(!array_access_ok(
|
||||
uop, count, sizeof(gnttab_unmap_grant_ref_t))) )
|
||||
{
|
||||
GUEST_HANDLE(gnttab_unmap_grant_ref_t) unmap =
|
||||
guest_handle_cast(uop, gnttab_unmap_grant_ref_t);
|
||||
if ( unlikely(!guest_handle_okay(unmap, count)) )
|
||||
goto out;
|
||||
rc = gnttab_unmap_grant_ref(
|
||||
(gnttab_unmap_grant_ref_t *)uop, count);
|
||||
rc = gnttab_unmap_grant_ref(unmap, count);
|
||||
break;
|
||||
}
|
||||
case GNTTABOP_setup_table:
|
||||
rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count);
|
||||
{
|
||||
rc = gnttab_setup_table(
|
||||
guest_handle_cast(uop, gnttab_setup_table_t), count);
|
||||
break;
|
||||
}
|
||||
case GNTTABOP_transfer:
|
||||
if (unlikely(!array_access_ok(
|
||||
uop, count, sizeof(gnttab_transfer_t))))
|
||||
{
|
||||
GUEST_HANDLE(gnttab_transfer_t) transfer =
|
||||
guest_handle_cast(uop, gnttab_transfer_t);
|
||||
if ( unlikely(!guest_handle_okay(transfer, count)) )
|
||||
goto out;
|
||||
rc = gnttab_transfer(uop, count);
|
||||
rc = gnttab_transfer(transfer, count);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
rc = -ENOSYS;
|
||||
break;
|
||||
|
||||
+26
-22
@@ -11,6 +11,7 @@
|
||||
#include <xen/compile.h>
|
||||
#include <xen/sched.h>
|
||||
#include <xen/shadow.h>
|
||||
#include <xen/guest_access.h>
|
||||
#include <asm/current.h>
|
||||
#include <public/nmi.h>
|
||||
#include <public/version.h>
|
||||
@@ -116,7 +117,7 @@ void add_taint(unsigned flag)
|
||||
* Simple hypercalls.
|
||||
*/
|
||||
|
||||
long do_xen_version(int cmd, void *arg)
|
||||
long do_xen_version(int cmd, GUEST_HANDLE(void) arg)
|
||||
{
|
||||
switch ( cmd )
|
||||
{
|
||||
@@ -129,7 +130,7 @@ long do_xen_version(int cmd, void *arg)
|
||||
{
|
||||
xen_extraversion_t extraversion;
|
||||
safe_strcpy(extraversion, XEN_EXTRAVERSION);
|
||||
if ( copy_to_user(arg, extraversion, sizeof(extraversion)) )
|
||||
if ( copy_to_guest(arg, (char *)extraversion, sizeof(extraversion)) )
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
@@ -141,7 +142,7 @@ long do_xen_version(int cmd, void *arg)
|
||||
safe_strcpy(info.compile_by, XEN_COMPILE_BY);
|
||||
safe_strcpy(info.compile_domain, XEN_COMPILE_DOMAIN);
|
||||
safe_strcpy(info.compile_date, XEN_COMPILE_DATE);
|
||||
if ( copy_to_user(arg, &info, sizeof(info)) )
|
||||
if ( copy_to_guest(arg, &info, 1) )
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
@@ -154,7 +155,7 @@ long do_xen_version(int cmd, void *arg)
|
||||
memset(info, 0, sizeof(info));
|
||||
arch_get_xen_caps(info);
|
||||
|
||||
if ( copy_to_user(arg, info, sizeof(info)) )
|
||||
if ( copy_to_guest(arg, (char *)info, sizeof(info)) )
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
@@ -164,7 +165,7 @@ long do_xen_version(int cmd, void *arg)
|
||||
xen_platform_parameters_t params = {
|
||||
.virt_start = HYPERVISOR_VIRT_START
|
||||
};
|
||||
if ( copy_to_user(arg, ¶ms, sizeof(params)) )
|
||||
if ( copy_to_guest(arg, ¶ms, 1) )
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
@@ -174,7 +175,7 @@ long do_xen_version(int cmd, void *arg)
|
||||
{
|
||||
xen_changeset_info_t chgset;
|
||||
safe_strcpy(chgset, XEN_CHANGESET);
|
||||
if ( copy_to_user(arg, chgset, sizeof(chgset)) )
|
||||
if ( copy_to_guest(arg, (char *)chgset, sizeof(chgset)) )
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
@@ -183,7 +184,7 @@ long do_xen_version(int cmd, void *arg)
|
||||
{
|
||||
xen_feature_info_t fi;
|
||||
|
||||
if ( copy_from_user(&fi, arg, sizeof(fi)) )
|
||||
if ( copy_from_guest(&fi, arg, 1) )
|
||||
return -EFAULT;
|
||||
|
||||
switch ( fi.submap_idx )
|
||||
@@ -202,7 +203,7 @@ long do_xen_version(int cmd, void *arg)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ( copy_to_user(arg, &fi, sizeof(fi)) )
|
||||
if ( copy_to_guest(arg, &fi, 1) )
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
@@ -212,31 +213,34 @@ long do_xen_version(int cmd, void *arg)
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
long do_nmi_op(unsigned int cmd, void *arg)
|
||||
long do_nmi_op(unsigned int cmd, GUEST_HANDLE(void) arg)
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
struct domain *d = current->domain;
|
||||
struct xennmi_callback cb;
|
||||
long rc = 0;
|
||||
|
||||
switch ( cmd )
|
||||
{
|
||||
case XENNMI_register_callback:
|
||||
rc = -EINVAL;
|
||||
if ( (d->domain_id != 0) || (v->vcpu_id != 0) )
|
||||
{
|
||||
rc = -EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
v->nmi_addr = (unsigned long)arg;
|
||||
break;
|
||||
|
||||
rc = -EFAULT;
|
||||
if ( copy_from_guest(&cb, arg, 1) )
|
||||
break;
|
||||
|
||||
v->nmi_addr = cb.handler_address;
|
||||
#ifdef CONFIG_X86
|
||||
/*
|
||||
* If no handler was registered we can 'lose the NMI edge'.
|
||||
* Re-assert it now.
|
||||
*/
|
||||
if ( d->shared_info->arch.nmi_reason != 0 )
|
||||
set_bit(_VCPUF_nmi_pending, &v->vcpu_flags);
|
||||
/*
|
||||
* If no handler was registered we can 'lose the NMI edge'. Re-assert
|
||||
* it now.
|
||||
*/
|
||||
if ( d->shared_info->arch.nmi_reason != 0 )
|
||||
set_bit(_VCPUF_nmi_pending, &v->vcpu_flags);
|
||||
#endif
|
||||
}
|
||||
rc = 0;
|
||||
break;
|
||||
case XENNMI_unregister_callback:
|
||||
v->nmi_addr = 0;
|
||||
|
||||
+11
-22
@@ -10,12 +10,15 @@
|
||||
#include <xen/sched.h>
|
||||
#include <xen/event.h>
|
||||
#include <xen/multicall.h>
|
||||
#include <xen/guest_access.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/hardirq.h>
|
||||
|
||||
struct mc_state mc_state[NR_CPUS];
|
||||
|
||||
long do_multicall(struct multicall_entry *call_list, unsigned int nr_calls)
|
||||
long
|
||||
do_multicall(
|
||||
GUEST_HANDLE(multicall_entry_t) call_list, unsigned int nr_calls)
|
||||
{
|
||||
struct mc_state *mcs = &mc_state[smp_processor_id()];
|
||||
unsigned int i;
|
||||
@@ -26,22 +29,13 @@ long do_multicall(struct multicall_entry *call_list, unsigned int nr_calls)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ( unlikely(!array_access_ok(call_list, nr_calls, sizeof(*call_list))) )
|
||||
{
|
||||
DPRINTK("Bad memory range %p for %u*%u bytes.\n",
|
||||
call_list, nr_calls, (unsigned int)sizeof(*call_list));
|
||||
if ( unlikely(!guest_handle_okay(call_list, nr_calls)) )
|
||||
goto fault;
|
||||
}
|
||||
|
||||
for ( i = 0; i < nr_calls; i++ )
|
||||
{
|
||||
if ( unlikely(__copy_from_user(&mcs->call, &call_list[i],
|
||||
sizeof(*call_list))) )
|
||||
{
|
||||
DPRINTK("Error copying from user range %p for %u bytes.\n",
|
||||
&call_list[i], (unsigned int)sizeof(*call_list));
|
||||
if ( unlikely(__copy_from_guest_offset(&mcs->call, call_list, i, 1)) )
|
||||
goto fault;
|
||||
}
|
||||
|
||||
do_multicall_call(&mcs->call);
|
||||
|
||||
@@ -53,17 +47,12 @@ long do_multicall(struct multicall_entry *call_list, unsigned int nr_calls)
|
||||
*/
|
||||
struct multicall_entry corrupt;
|
||||
memset(&corrupt, 0xAA, sizeof(corrupt));
|
||||
(void)__copy_to_user(&call_list[i], &corrupt, sizeof(corrupt));
|
||||
(void)__copy_to_guest_offset(call_list, i, &corrupt, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( unlikely(__copy_to_user(&call_list[i].result,
|
||||
&mcs->call.result,
|
||||
sizeof(mcs->call.result))) )
|
||||
{
|
||||
DPRINTK("Error writing result back to multicall block.\n");
|
||||
if ( unlikely(__copy_to_guest_offset(call_list, i, &mcs->call, 1)) )
|
||||
goto fault;
|
||||
}
|
||||
|
||||
if ( hypercall_preempt_check() )
|
||||
{
|
||||
@@ -74,15 +63,15 @@ long do_multicall(struct multicall_entry *call_list, unsigned int nr_calls)
|
||||
if ( !test_bit(_MCSF_call_preempted, &mcs->flags) )
|
||||
i++;
|
||||
else
|
||||
(void)__copy_to_user(&call_list[i], &mcs->call,
|
||||
sizeof(*call_list));
|
||||
(void)__copy_to_guest_offset(call_list, i, &mcs->call, 1);
|
||||
|
||||
/* Only create a continuation if there is work left to be done. */
|
||||
if ( i < nr_calls )
|
||||
{
|
||||
mcs->flags = 0;
|
||||
guest_handle_add_offset(call_list, i);
|
||||
return hypercall_create_continuation(
|
||||
__HYPERVISOR_multicall, "pi", &call_list[i], nr_calls-i);
|
||||
__HYPERVISOR_multicall, "hi", call_list, nr_calls-i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <xen/mm.h>
|
||||
#include <xen/guest_access.h>
|
||||
#include <public/dom0_ops.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#undef PERFCOUNTER
|
||||
#undef PERFCOUNTER_CPU
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <xen/delay.h>
|
||||
#include <xen/guest_access.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/debugger.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
@@ -320,7 +319,7 @@ static void serial_rx(char c, struct cpu_user_regs *regs)
|
||||
__serial_rx(c, regs);
|
||||
}
|
||||
|
||||
long guest_console_write(char *buffer, int count)
|
||||
static long guest_console_write(GUEST_HANDLE(char) buffer, int count)
|
||||
{
|
||||
char kbuf[128], *kptr;
|
||||
int kcount;
|
||||
@@ -336,11 +335,11 @@ long guest_console_write(char *buffer, int count)
|
||||
|
||||
if ( hypercall_preempt_check() )
|
||||
return hypercall_create_continuation(
|
||||
__HYPERVISOR_console_io, "iip",
|
||||
__HYPERVISOR_console_io, "iih",
|
||||
CONSOLEIO_write, count, buffer);
|
||||
|
||||
kcount = min_t(int, count, sizeof(kbuf)-1);
|
||||
if ( copy_from_user(kbuf, buffer, kcount) )
|
||||
if ( copy_from_guest((char *)kbuf, buffer, kcount) )
|
||||
return -EFAULT;
|
||||
kbuf[kcount] = '\0';
|
||||
|
||||
@@ -349,14 +348,14 @@ long guest_console_write(char *buffer, int count)
|
||||
for ( kptr = kbuf; *kptr != '\0'; kptr++ )
|
||||
putchar_console(*kptr);
|
||||
|
||||
buffer += kcount;
|
||||
count -= kcount;
|
||||
guest_handle_add_offset(buffer, kcount);
|
||||
count -= kcount;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long do_console_io(int cmd, int count, char *buffer)
|
||||
long do_console_io(int cmd, int count, GUEST_HANDLE(char) buffer)
|
||||
{
|
||||
long rc;
|
||||
unsigned int idx, len;
|
||||
@@ -382,7 +381,7 @@ long do_console_io(int cmd, int count, char *buffer)
|
||||
len = SERIAL_RX_SIZE - idx;
|
||||
if ( (rc + len) > count )
|
||||
len = count - rc;
|
||||
if ( copy_to_user(&buffer[rc], &serial_rx_ring[idx], len) )
|
||||
if ( copy_to_guest_offset(buffer, rc, &serial_rx_ring[idx], len) )
|
||||
{
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
(GUEST_HANDLE(type)) { _x }; \
|
||||
})
|
||||
|
||||
#define guest_handle_from_ptr(ptr, type) ((GUEST_HANDLE(type)) { (type *)ptr })
|
||||
|
||||
/*
|
||||
* Copy an array of objects to guest context via a guest handle,
|
||||
* specifying an offset into the guest array.
|
||||
|
||||
@@ -16,4 +16,6 @@ vmx_do_mmu_update(
|
||||
u64 *pdone,
|
||||
u64 foreigndom);
|
||||
|
||||
#define arch_do_vcpu_op(cmd, vcpu, arg) (-ENOSYS)
|
||||
|
||||
#endif /* __ASM_IA64_HYPERCALL_H__ */
|
||||
@@ -75,35 +75,5 @@ extern struct task_struct *vmx_ia64_switch_to (void *next_task);
|
||||
// FIXME SMP... see system.h, does this need to be different?
|
||||
#define switch_to(prev,next,last) __switch_to(prev, next, last)
|
||||
|
||||
#define __cmpxchg_user(ptr, new, old, _size) \
|
||||
({ \
|
||||
register long __gu_r8 asm ("r8"); \
|
||||
asm volatile ("mov ar.ccv=%0;;" :: "rO"(old)); \
|
||||
asm volatile ("mov %1=r0;;\n" \
|
||||
"[1:]\tcmpxchg"_size".acq %0=[%2],%3,ar.ccv\n" \
|
||||
"\t.xdata4 \"__ex_table\", 1b-., 1f-.\n" \
|
||||
"[1:]" \
|
||||
: "=r"(old), "=r"(__gu_r8) : \
|
||||
"r"(ptr), "r"(new) : "memory"); \
|
||||
__gu_r8; \
|
||||
})
|
||||
|
||||
|
||||
// NOTE: Xen defines args as pointer,old,new whereas ia64 uses pointer,new,old
|
||||
// so reverse them here
|
||||
#define cmpxchg_user(_p,_o,_n) \
|
||||
({ \
|
||||
register long _rc; \
|
||||
ia64_mf(); \
|
||||
switch ( sizeof(*(_p)) ) { \
|
||||
case 1: _rc = __cmpxchg_user(_p,_n,_o,"1"); break; \
|
||||
case 2: _rc = __cmpxchg_user(_p,_n,_o,"2"); break; \
|
||||
case 4: _rc = __cmpxchg_user(_p,_n,_o,"4"); break; \
|
||||
case 8: _rc = __cmpxchg_user(_p,_n,_o,"8"); break; \
|
||||
} \
|
||||
ia64_mf(); \
|
||||
_rc; \
|
||||
})
|
||||
|
||||
#endif // __ASSEMBLY__
|
||||
#endif // _ASM_IA64_XENSYSTEM_H
|
||||
@@ -5,22 +5,22 @@
|
||||
#ifndef __ASM_X86_HYPERCALL_H__
|
||||
#define __ASM_X86_HYPERCALL_H__
|
||||
|
||||
struct trap_info;
|
||||
#include <public/physdev.h>
|
||||
|
||||
extern long
|
||||
do_set_trap_table(
|
||||
struct trap_info *traps);
|
||||
GUEST_HANDLE(trap_info_t) traps);
|
||||
|
||||
struct mmu_update;
|
||||
extern int
|
||||
do_mmu_update(
|
||||
struct mmu_update *ureqs,
|
||||
GUEST_HANDLE(mmu_update_t) ureqs,
|
||||
unsigned int count,
|
||||
unsigned int *pdone,
|
||||
GUEST_HANDLE(uint) pdone,
|
||||
unsigned int foreigndom);
|
||||
|
||||
extern long
|
||||
do_set_gdt(
|
||||
unsigned long *frame_list,
|
||||
GUEST_HANDLE(ulong) frame_list,
|
||||
unsigned int entries);
|
||||
|
||||
extern long
|
||||
@@ -52,10 +52,9 @@ do_update_va_mapping(
|
||||
u64 val64,
|
||||
unsigned long flags);
|
||||
|
||||
struct physdev_op;
|
||||
extern long
|
||||
do_physdev_op(
|
||||
struct physdev_op *uop);
|
||||
GUEST_HANDLE(physdev_op_t) uop);
|
||||
|
||||
extern int
|
||||
do_update_va_mapping_otherdomain(
|
||||
@@ -66,15 +65,20 @@ do_update_va_mapping_otherdomain(
|
||||
|
||||
extern int
|
||||
do_mmuext_op(
|
||||
struct mmuext_op *uops,
|
||||
GUEST_HANDLE(mmuext_op_t) uops,
|
||||
unsigned int count,
|
||||
unsigned int *pdone,
|
||||
GUEST_HANDLE(uint) pdone,
|
||||
unsigned int foreigndom);
|
||||
|
||||
extern unsigned long
|
||||
do_iret(
|
||||
void);
|
||||
|
||||
struct vcpu;
|
||||
extern long
|
||||
arch_do_vcpu_op(
|
||||
int cmd, struct vcpu *v, GUEST_HANDLE(void) arg);
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
extern long
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "xen.h"
|
||||
#include "sched_ctl.h"
|
||||
#include "acm.h"
|
||||
|
||||
/*
|
||||
* Make sure you increment the interface version whenever you modify this file!
|
||||
@@ -71,7 +72,7 @@ struct acm_getdecision {
|
||||
int acm_decision; /* out */
|
||||
};
|
||||
|
||||
struct acm_op {
|
||||
typedef struct acm_op {
|
||||
uint32_t cmd;
|
||||
uint32_t interface_version; /* ACM_INTERFACE_VERSION */
|
||||
union {
|
||||
@@ -81,7 +82,8 @@ struct acm_op {
|
||||
struct acm_getssid getssid;
|
||||
struct acm_getdecision getdecision;
|
||||
} u;
|
||||
};
|
||||
} acm_op_t;
|
||||
DEFINE_GUEST_HANDLE(acm_op_t);
|
||||
|
||||
#endif /* __XEN_PUBLIC_ACM_OPS_H__ */
|
||||
|
||||
|
||||
@@ -102,6 +102,7 @@ typedef struct trap_info {
|
||||
uint16_t cs; /* code selector */
|
||||
unsigned long address; /* code offset */
|
||||
} trap_info_t;
|
||||
DEFINE_GUEST_HANDLE(trap_info_t);
|
||||
|
||||
typedef struct cpu_user_regs {
|
||||
uint32_t ebx;
|
||||
@@ -125,6 +126,7 @@ typedef struct cpu_user_regs {
|
||||
uint16_t fs, _pad4;
|
||||
uint16_t gs, _pad5;
|
||||
} cpu_user_regs_t;
|
||||
DEFINE_GUEST_HANDLE(cpu_user_regs_t);
|
||||
|
||||
typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
|
||||
|
||||
|
||||
@@ -136,15 +136,6 @@ struct iret_context {
|
||||
uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
|
||||
/* Bottom of iret stack frame. */
|
||||
};
|
||||
/*
|
||||
* For compatibility with HYPERVISOR_switch_to_user which is the old
|
||||
* name for HYPERVISOR_iret.
|
||||
*/
|
||||
struct switch_to_user {
|
||||
/* Top of stack (%rsp at point of hypercall). */
|
||||
uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
|
||||
/* Bottom of iret stack frame. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Send an array of these to HYPERVISOR_set_trap_table().
|
||||
@@ -166,6 +157,7 @@ typedef struct trap_info {
|
||||
uint16_t cs; /* code selector */
|
||||
unsigned long address; /* code offset */
|
||||
} trap_info_t;
|
||||
DEFINE_GUEST_HANDLE(trap_info_t);
|
||||
|
||||
#ifdef __GNUC__
|
||||
/* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */
|
||||
@@ -205,6 +197,7 @@ typedef struct cpu_user_regs {
|
||||
uint16_t fs, _pad5[3]; /* Non-zero => takes precedence over fs_base. */
|
||||
uint16_t gs, _pad6[3]; /* Non-zero => takes precedence over gs_base_usr. */
|
||||
} cpu_user_regs_t;
|
||||
DEFINE_GUEST_HANDLE(cpu_user_regs_t);
|
||||
|
||||
#undef __DECL_REG
|
||||
|
||||
|
||||
@@ -189,6 +189,7 @@ typedef struct evtchn_op {
|
||||
evtchn_unmask_t unmask;
|
||||
} u;
|
||||
} evtchn_op_t;
|
||||
DEFINE_GUEST_HANDLE(evtchn_op_t);
|
||||
|
||||
#endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */
|
||||
|
||||
|
||||
@@ -167,6 +167,7 @@ typedef struct gnttab_map_grant_ref {
|
||||
grant_handle_t handle;
|
||||
uint64_t dev_bus_addr;
|
||||
} gnttab_map_grant_ref_t;
|
||||
DEFINE_GUEST_HANDLE(gnttab_map_grant_ref_t);
|
||||
|
||||
/*
|
||||
* GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
|
||||
@@ -188,6 +189,7 @@ typedef struct gnttab_unmap_grant_ref {
|
||||
/* OUT parameters. */
|
||||
int16_t status; /* GNTST_* */
|
||||
} gnttab_unmap_grant_ref_t;
|
||||
DEFINE_GUEST_HANDLE(gnttab_unmap_grant_ref_t);
|
||||
|
||||
/*
|
||||
* GNTTABOP_setup_table: Set up a grant table for <dom> comprising at least
|
||||
@@ -205,8 +207,9 @@ typedef struct gnttab_setup_table {
|
||||
uint32_t nr_frames;
|
||||
/* OUT parameters. */
|
||||
int16_t status; /* GNTST_* */
|
||||
unsigned long *frame_list;
|
||||
GUEST_HANDLE(ulong) frame_list;
|
||||
} gnttab_setup_table_t;
|
||||
DEFINE_GUEST_HANDLE(gnttab_setup_table_t);
|
||||
|
||||
/*
|
||||
* GNTTABOP_dump_table: Dump the contents of the grant table to the
|
||||
@@ -219,6 +222,7 @@ typedef struct gnttab_dump_table {
|
||||
/* OUT parameters. */
|
||||
int16_t status; /* GNTST_* */
|
||||
} gnttab_dump_table_t;
|
||||
DEFINE_GUEST_HANDLE(gnttab_dump_table_t);
|
||||
|
||||
/*
|
||||
* GNTTABOP_transfer_grant_ref: Transfer <frame> to a foreign domain. The
|
||||
@@ -237,6 +241,7 @@ typedef struct gnttab_transfer {
|
||||
/* OUT parameters. */
|
||||
int16_t status;
|
||||
} gnttab_transfer_t;
|
||||
DEFINE_GUEST_HANDLE(gnttab_transfer_t);
|
||||
|
||||
/*
|
||||
* Bitfield values for update_pin_status.flags.
|
||||
|
||||
@@ -31,9 +31,14 @@
|
||||
/*
|
||||
* Register NMI callback for this (calling) VCPU. Currently this only makes
|
||||
* sense for domain 0, vcpu 0. All other callers will be returned EINVAL.
|
||||
* arg == address of callback function.
|
||||
* arg == pointer to xennmi_callback structure.
|
||||
*/
|
||||
#define XENNMI_register_callback 0
|
||||
typedef struct xennmi_callback {
|
||||
unsigned long handler_address;
|
||||
unsigned long pad;
|
||||
} xennmi_callback_t;
|
||||
DEFINE_GUEST_HANDLE(xennmi_callback_t);
|
||||
|
||||
/*
|
||||
* Deregister NMI callback for this (calling) VCPU.
|
||||
|
||||
@@ -56,6 +56,7 @@ typedef struct physdev_op {
|
||||
physdevop_irq_t irq_op;
|
||||
} u;
|
||||
} physdev_op_t;
|
||||
DEFINE_GUEST_HANDLE(physdev_op_t);
|
||||
|
||||
#endif /* __XEN_PUBLIC_PHYSDEV_H__ */
|
||||
|
||||
|
||||
@@ -54,8 +54,6 @@
|
||||
#define __HYPERVISOR_vm_assist 21
|
||||
#define __HYPERVISOR_update_va_mapping_otherdomain 22
|
||||
#define __HYPERVISOR_iret 23 /* x86 only */
|
||||
#define __HYPERVISOR_switch_vm86 23 /* x86/32 only (obsolete name) */
|
||||
#define __HYPERVISOR_switch_to_user 23 /* x86/64 only (obsolete name) */
|
||||
#define __HYPERVISOR_vcpu_op 24
|
||||
#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */
|
||||
#define __HYPERVISOR_mmuext_op 26
|
||||
@@ -162,7 +160,7 @@
|
||||
#define MMUEXT_NEW_USER_BASEPTR 15
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
struct mmuext_op {
|
||||
typedef struct mmuext_op {
|
||||
unsigned int cmd;
|
||||
union {
|
||||
/* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR */
|
||||
@@ -176,7 +174,8 @@ struct mmuext_op {
|
||||
/* TLB_FLUSH_MULTI, INVLPG_MULTI */
|
||||
void *vcpumask;
|
||||
} arg2;
|
||||
};
|
||||
} mmuext_op_t;
|
||||
DEFINE_GUEST_HANDLE(mmuext_op_t);
|
||||
#endif
|
||||
|
||||
/* These are passed as 'flags' to update_va_mapping. They can be ORed. */
|
||||
@@ -243,6 +242,7 @@ typedef struct mmu_update {
|
||||
uint64_t ptr; /* Machine address of PTE. */
|
||||
uint64_t val; /* New contents of PTE. */
|
||||
} mmu_update_t;
|
||||
DEFINE_GUEST_HANDLE(mmu_update_t);
|
||||
|
||||
/*
|
||||
* Send an array of these to HYPERVISOR_multicall().
|
||||
@@ -252,6 +252,7 @@ typedef struct multicall_entry {
|
||||
unsigned long op, result;
|
||||
unsigned long args[6];
|
||||
} multicall_entry_t;
|
||||
DEFINE_GUEST_HANDLE(multicall_entry_t);
|
||||
|
||||
/*
|
||||
* Event channel endpoints per domain:
|
||||
|
||||
+11
-14
@@ -9,6 +9,7 @@
|
||||
#include <xen/types.h>
|
||||
#include <xen/time.h>
|
||||
#include <public/xen.h>
|
||||
#include <public/acm_ops.h>
|
||||
#include <asm/hypercall.h>
|
||||
|
||||
extern long
|
||||
@@ -20,46 +21,43 @@ do_sched_op(
|
||||
int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
struct dom0_op;
|
||||
extern long
|
||||
do_dom0_op(
|
||||
struct dom0_op *u_dom0_op);
|
||||
GUEST_HANDLE(dom0_op_t) u_dom0_op);
|
||||
|
||||
extern long
|
||||
do_memory_op(
|
||||
int cmd,
|
||||
void *arg);
|
||||
GUEST_HANDLE(void) arg);
|
||||
|
||||
struct multicall_entry;
|
||||
extern long
|
||||
do_multicall(
|
||||
struct multicall_entry *call_list,
|
||||
GUEST_HANDLE(multicall_entry_t) call_list,
|
||||
unsigned int nr_calls);
|
||||
|
||||
extern long
|
||||
do_set_timer_op(
|
||||
s_time_t timeout);
|
||||
|
||||
struct evtchn_op;
|
||||
extern long
|
||||
do_event_channel_op(
|
||||
struct evtchn_op *uop);
|
||||
GUEST_HANDLE(evtchn_op_t) uop);
|
||||
|
||||
extern long
|
||||
do_xen_version(
|
||||
int cmd,
|
||||
void *arg);
|
||||
GUEST_HANDLE(void) arg);
|
||||
|
||||
extern long
|
||||
do_console_io(
|
||||
int cmd,
|
||||
int count,
|
||||
char *buffer);
|
||||
GUEST_HANDLE(char) buffer);
|
||||
|
||||
extern long
|
||||
do_grant_table_op(
|
||||
unsigned int cmd,
|
||||
void *uop,
|
||||
GUEST_HANDLE(void) uop,
|
||||
unsigned int count);
|
||||
|
||||
extern long
|
||||
@@ -71,16 +69,15 @@ extern long
|
||||
do_vcpu_op(
|
||||
int cmd,
|
||||
int vcpuid,
|
||||
void *arg);
|
||||
GUEST_HANDLE(void) arg);
|
||||
|
||||
struct acm_op;
|
||||
extern long
|
||||
do_acm_op(
|
||||
struct acm_op *u_acm_op);
|
||||
GUEST_HANDLE(acm_op_t) u_acm_op);
|
||||
|
||||
extern long
|
||||
do_nmi_op(
|
||||
unsigned int cmd,
|
||||
void *arg);
|
||||
GUEST_HANDLE(void) arg);
|
||||
|
||||
#endif /* __XEN_HYPERCALL_H__ */
|
||||
@@ -310,7 +310,6 @@ void startup_cpu_idle_loop(void);
|
||||
* It contains one character per argument as follows:
|
||||
* 'i' [unsigned] {char, int}
|
||||
* 'l' [unsigned] long
|
||||
* 'p' pointer (foo *)
|
||||
* 'h' guest handle (GUEST_HANDLE(foo))
|
||||
*/
|
||||
unsigned long hypercall_create_continuation(
|
||||
|
||||