[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCHv2] valgrind support for Xen privcmd ioctls / hypercalls
Below is an updated version of my patch to valgrind to allow it to understand privcmd ioctls and some hypercalls. I have implemented a bunch more hypercalls, including all those I saw when creating a pv or hvm domain with my particular configuration. As before I bailed on the normal valgrind policy of duplicating the interface headers so usage is still: ./configure --with-xen=/path/to/headers The path needs to be to an installed set of xen headers, such that "#include <xen/xen.h>" is valid e.g. dist/install/usr/include in your built Xen tree or /usr/include or something equivalent (e.g. libxen-dev installed under Debian etc.) Not extensively tested, caveat emptor etc etc. diff --git a/configure.in b/configure.in index 62e1837..e71ecd6 100644 --- a/configure.in +++ b/configure.in @@ -1558,6 +1558,11 @@ elif test x$VGCONF_PLATFORM_SEC_CAPS = xPPC32_AIX5 ; then mflag_secondary=-q32 fi +AC_ARG_WITH(xen, + [ --with-xen= Specify location of Xen headers], + XEN_CFLAGS=-I$withval +) +AC_SUBST(XEN_CFLAGS) AC_ARG_WITH(mpicc, [ --with-mpicc= Specify name of MPI2-ised C compiler], diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index d9d1bca..d7216f9 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -211,6 +211,7 @@ noinst_HEADERS = \ m_syswrap/priv_syswrap-aix5.h \ m_syswrap/priv_syswrap-darwin.h \ m_syswrap/priv_syswrap-main.h \ + m_syswrap/priv_syswrap-xen.h \ m_ume/priv_ume.h #---------------------------------------------------------------------------- @@ -338,6 +339,7 @@ COREGRIND_SOURCES_COMMON = \ m_syswrap/syswrap-ppc64-aix5.c \ m_syswrap/syswrap-x86-darwin.c \ m_syswrap/syswrap-amd64-darwin.c \ + m_syswrap/syswrap-xen.c \ m_ume/elf.c \ m_ume/macho.c \ m_ume/main.c \ @@ -350,7 +352,7 @@ nodist_libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_SOURCES = \ libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS = \ $(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS = \ - $(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) + $(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) @XEN_CFLAGS@ libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CCASFLAGS = \ $(AM_CCASFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) if VGCONF_HAVE_PLATFORM_SEC diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c index 08babd0..5272fae 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -637,6 +637,11 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV ) if (!filename) return 0; + if (strncmp(filename, "/proc/xen/", 10) == 0) { + //VG_(printf)("ignoring mmap of %s\n", filename); + return 0; + } + if (debug) VG_(printf)("di_notify_mmap-2: %s\n", filename); diff --git a/coregrind/m_syswrap/priv_syswrap-xen.h b/coregrind/m_syswrap/priv_syswrap-xen.h new file mode 100644 index 0000000..42505bb --- /dev/null +++ b/coregrind/m_syswrap/priv_syswrap-xen.h @@ -0,0 +1,13 @@ +#ifndef __PRIV_SYSWRAP_XEN_H +#define __PRIV_SYSWRAP_XEN_H + +DECL_TEMPLATE(xen, ioctl_privcmd_hypercall); +DECL_TEMPLATE(xen, ioctl_privcmd_mmap); +DECL_TEMPLATE(xen, ioctl_privcmd_mmapbatch); +DECL_TEMPLATE(xen, ioctl_privcmd_mmapbatch_v2); + +#endif // __PRIV_SYSWRAP_XEN_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 247402d..baa33c2 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -57,7 +57,7 @@ #include "priv_types_n_macros.h" #include "priv_syswrap-generic.h" #include "priv_syswrap-linux.h" - +#include "priv_syswrap-xen.h" // Run a thread from beginning to end and return the thread's // scheduler-return-code. @@ -4821,6 +4821,20 @@ PRE(sys_ioctl) } break; + + case VKI_XEN_IOCTL_PRIVCMD_HYPERCALL: + WRAPPER_PRE_NAME(xen, ioctl_privcmd_hypercall)(tid, layout, arrghs, status, flags); + break; + case VKI_XEN_IOCTL_PRIVCMD_MMAP: + WRAPPER_PRE_NAME(xen, ioctl_privcmd_mmap)(tid, layout, arrghs, status, flags); + break; + case VKI_XEN_IOCTL_PRIVCMD_MMAPBATCH: + WRAPPER_PRE_NAME(xen, ioctl_privcmd_mmapbatch)(tid, layout, arrghs, status, flags); + break; + case VKI_XEN_IOCTL_PRIVCMD_MMAPBATCH_V2: + WRAPPER_PRE_NAME(xen, ioctl_privcmd_mmapbatch_v2)(tid, layout, arrghs, status, flags); + break; + default: /* EVIOC* are variable length and return size written on success */ switch (ARG2 & ~(_VKI_IOC_SIZEMASK << _VKI_IOC_SIZESHIFT)) { @@ -5633,6 +5647,19 @@ POST(sys_ioctl) } break; + case VKI_XEN_IOCTL_PRIVCMD_HYPERCALL: + WRAPPER_POST_NAME(xen, ioctl_privcmd_hypercall)(tid, arrghs, status); + break; + case VKI_XEN_IOCTL_PRIVCMD_MMAP: + WRAPPER_POST_NAME(xen, ioctl_privcmd_mmap)(tid, arrghs, status); + break; + case VKI_XEN_IOCTL_PRIVCMD_MMAPBATCH: + WRAPPER_POST_NAME(xen, ioctl_privcmd_mmapbatch)(tid, arrghs, status); + break; + case VKI_XEN_IOCTL_PRIVCMD_MMAPBATCH_V2: + WRAPPER_POST_NAME(xen, ioctl_privcmd_mmapbatch_v2)(tid, arrghs, status); + break; + default: /* EVIOC* are variable length and return size written on success */ switch (ARG2 & ~(_VKI_IOC_SIZEMASK << _VKI_IOC_SIZESHIFT)) { diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c new file mode 100644 index 0000000..5e87f8e --- /dev/null +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -0,0 +1,751 @@ +#include "pub_core_basics.h" +#include "pub_core_vki.h" +#include "pub_core_vkiscnums.h" +#include "pub_core_threadstate.h" +#include "pub_core_aspacemgr.h" +#include "pub_core_debuginfo.h" // VG_(di_notify_*) +#include "pub_core_transtab.h" // VG_(discard_translations) +#include "pub_core_xarray.h" +#include "pub_core_clientstate.h" +#include "pub_core_debuglog.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" +#include "pub_core_libcprint.h" +#include "pub_core_libcproc.h" +#include "pub_core_libcsignal.h" +#include "pub_core_mallocfree.h" +#include "pub_core_tooliface.h" +#include "pub_core_options.h" +#include "pub_core_scheduler.h" +#include "pub_core_signals.h" +#include "pub_core_syscall.h" +#include "pub_core_syswrap.h" + +#include "priv_types_n_macros.h" +#include "priv_syswrap-generic.h" +#include "priv_syswrap-xen.h" + +#include <stdint.h> + +#define __XEN_TOOLS__ + +#include <xen/xen.h> +#include <xen/sysctl.h> +#include <xen/domctl.h> +#include <xen/memory.h> +#include <xen/event_channel.h> +#include <xen/version.h> + +#include <xen/hvm/hvm_op.h> + +#define PRE(name) DEFN_PRE_TEMPLATE(xen, name) +#define POST(name) DEFN_POST_TEMPLATE(xen, name) + +PRE(ioctl_privcmd_hypercall) +{ + struct vki_xen_privcmd_hypercall *args = (struct vki_xen_privcmd_hypercall *)(ARG3); + + if (!args) + return; + + + switch (args->op) { + case __HYPERVISOR_memory_op: + PRINT("__HYPERVISOR_memory_op ( %lld, %llx )", args->arg[0], args->arg[1]); + + switch (args->arg[0]) { + case XENMEM_set_memory_map: { + xen_foreign_memory_map_t *arg = (xen_foreign_memory_map_t *)(unsigned int)args->arg[1]; + PRE_MEM_READ("XENMEM_set_memory_map", (Addr)&arg->domid, sizeof(arg->domid)); + PRE_MEM_READ("XENMEM_set_memory_map", (Addr)&arg->map, sizeof(arg->map)); + break; + } + case XENMEM_increase_reservation: + case XENMEM_decrease_reservation: + case XENMEM_populate_physmap: { + struct xen_memory_reservation *memory_reservation = (struct xen_memory_reservation *)(unsigned int)args->arg[1]; + char *which; + + switch (args->arg[0]) { + case XENMEM_increase_reservation: + which = "XENMEM_increase_reservation"; + break; + case XENMEM_decrease_reservation: + which = "XENMEM_decrease_reservation"; + PRE_MEM_READ(which, (Addr)memory_reservation->extent_start.p, sizeof(xen_pfn_t) * memory_reservation->nr_extents); + case XENMEM_populate_physmap: + which = "XENMEM_populate_physmap"; + PRE_MEM_READ(which, (Addr)memory_reservation->extent_start.p, sizeof(xen_pfn_t) * memory_reservation->nr_extents); + break; + default: + which = "XENMEM_unknown"; + break; + } + + PRE_MEM_READ(which, (Addr)&memory_reservation->extent_start, sizeof(memory_reservation->extent_start)); + PRE_MEM_READ(which, (Addr)&memory_reservation->nr_extents, sizeof(memory_reservation->nr_extents)); + PRE_MEM_READ(which, (Addr)&memory_reservation->extent_order, sizeof(memory_reservation->extent_order)); + PRE_MEM_READ(which, (Addr)&memory_reservation->mem_flags, sizeof(memory_reservation->mem_flags)); + PRE_MEM_READ(which, (Addr)&memory_reservation->domid, sizeof(memory_reservation->domid)); + + break; + } + + default: + VG_(printf)("pre __HYPERVISOR_memory_op unknown command %lld\n", args->arg[0]); + break; + } + break; + + case __HYPERVISOR_mmuext_op: { + mmuext_op_t *ops = (void *)(unsigned int)args->arg[0]; + unsigned int i, nr = args->arg[1]; + //unsigned int *pdone = (void *)(unsigned int)args->arg[2]; + //unsigned int foreigndom = args->arg[3]; + //VG_(printf)("HYPERVISOR_mmuext_op %d ops at %p on dom%d done at %p\n", nr, ops, foreigndom, pdone); + for (i=0; i<nr; i++) { + mmuext_op_t *op = ops + i; + PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP", (Addr)&op->cmd, sizeof(op->cmd)); + switch(op->cmd) { + case MMUEXT_PIN_L1_TABLE: + case MMUEXT_PIN_L2_TABLE: + case MMUEXT_PIN_L3_TABLE: + case MMUEXT_PIN_L4_TABLE: + case MMUEXT_UNPIN_TABLE: + case MMUEXT_NEW_BASEPTR: + case MMUEXT_CLEAR_PAGE: + case MMUEXT_COPY_PAGE: + case MMUEXT_MARK_SUPER: + case MMUEXT_UNMARK_SUPER: + PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg1.mfn", (Addr)&op->arg1.mfn, sizeof(op->arg1.mfn)); + break; + + case MMUEXT_INVLPG_LOCAL: + case MMUEXT_INVLPG_ALL: + case MMUEXT_SET_LDT: + PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg1.mfn", (Addr)&op->arg1.linear_addr, sizeof(op->arg1.linear_addr)); + break; + + case MMUEXT_TLB_FLUSH_LOCAL: + case MMUEXT_TLB_FLUSH_MULTI: + case MMUEXT_INVLPG_MULTI: + case MMUEXT_TLB_FLUSH_ALL: + case MMUEXT_FLUSH_CACHE: + case MMUEXT_NEW_USER_BASEPTR: + case MMUEXT_FLUSH_CACHE_GLOBAL: + /* None */ + break; + } + + switch(op->cmd) { + case MMUEXT_SET_LDT: + PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.nr_ents", (Addr)&op->arg2.nr_ents, sizeof(op->arg2.nr_ents)); + break; + + case MMUEXT_TLB_FLUSH_MULTI: + case MMUEXT_INVLPG_MULTI: + /* How many??? */ + PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.vcpumask", (Addr)&op->arg2.vcpumask, sizeof(op->arg2.vcpumask)); + break; + + case MMUEXT_COPY_PAGE: + PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.src_mfn", (Addr)&op->arg2.src_mfn, sizeof(op->arg2.src_mfn)); + break; + + case MMUEXT_PIN_L1_TABLE: + case MMUEXT_PIN_L2_TABLE: + case MMUEXT_PIN_L3_TABLE: + case MMUEXT_PIN_L4_TABLE: + case MMUEXT_UNPIN_TABLE: + case MMUEXT_NEW_BASEPTR: + case MMUEXT_TLB_FLUSH_LOCAL: + case MMUEXT_INVLPG_LOCAL: + case MMUEXT_TLB_FLUSH_ALL: + case MMUEXT_INVLPG_ALL: + case MMUEXT_FLUSH_CACHE: + case MMUEXT_NEW_USER_BASEPTR: + case MMUEXT_CLEAR_PAGE: + case MMUEXT_FLUSH_CACHE_GLOBAL: + case MMUEXT_MARK_SUPER: + case MMUEXT_UNMARK_SUPER: + /* None */ + break; + } + } + break; + } + + case __HYPERVISOR_event_channel_op: + case __HYPERVISOR_event_channel_op_compat: { + __vki_u32 cmd; + void *arg; + int compat = 0; + + if (args->op == __HYPERVISOR_event_channel_op) { + cmd = args->arg[0]; + arg = (void *)(unsigned int)args->arg[1]; + } else { + struct evtchn_op *evtchn = (struct evtchn_op *)(unsigned int)args->arg[0]; + cmd = evtchn->cmd; + arg = &evtchn->u; + compat = 1; + } + PRINT("__HYPERVISOR_event_channel_op ( %d, %p )%s", cmd, arg, compat ? " compat" : ""); + + switch (cmd) { + case EVTCHNOP_alloc_unbound: { + struct evtchn_alloc_unbound *alloc_unbound = arg; + PRE_MEM_READ("EVTCHNOP_alloc_unbound", (Addr)&alloc_unbound->dom, sizeof(alloc_unbound->dom)); + PRE_MEM_READ("EVTCHNOP_alloc_unbound", (Addr)&alloc_unbound->remote_dom, sizeof(alloc_unbound->remote_dom)); + break; + } + default: + VG_(printf)("pre __HYPERVISOR_event_channel_op unknown command %d\n", cmd); + break; + } + break; + } + + case __HYPERVISOR_xen_version: + PRINT("__HYPERVISOR_xen_version ( %lld, %llx )", args->arg[0], args->arg[1]); + + switch (args->arg[0]) { + case XENVER_version: + case XENVER_extraversion: + case XENVER_compile_info: + case XENVER_capabilities: + case XENVER_changeset: + case XENVER_platform_parameters: + case XENVER_get_features: + case XENVER_pagesize: + case XENVER_guest_handle: + case XENVER_commandline: + /* No inputs */ + break; + + default: + VG_(printf)("pre __HYPERVISOR_xen_version unknown command %lld\n", args->arg[0]); + break; + } + break; + break; + case __HYPERVISOR_sysctl: { + struct xen_sysctl *sysctl = (struct xen_sysctl *)(unsigned int)args->arg[0]; + + PRINT("__HYPERVISOR_sysctl ( %d )", sysctl->cmd); + + /* Single argument hypercall */ + PRE_MEM_READ("hypercall", ARG3, 8 + ( 8 * 1 ) ); + + /* + * Common part of xen_sysctl: + * uint32_t cmd; + * uint32_t interface_version; + */ + PRE_MEM_READ("__HYPERVISOR_sysctl", args->arg[0], sizeof(uint32_t) + sizeof(uint32_t)); + + if (!sysctl || sysctl->interface_version != XEN_SYSCTL_INTERFACE_VERSION) + /* BUG ? */ + return; + +#define __PRE_XEN_SYSCTL_READ(_sysctl, _union, _field) PRE_MEM_READ("XEN_SYSCTL_" # _sysctl, \ + (Addr)&sysctl->u._union._field, \ + sizeof(sysctl->u._union._field)) +#define PRE_XEN_SYSCTL_READ(_sysctl, _field) __PRE_XEN_SYSCTL_READ(_sysctl, _sysctl, _field) + switch (sysctl->cmd) { + case XEN_SYSCTL_getdomaininfolist: + PRE_XEN_SYSCTL_READ(getdomaininfolist, first_domain); + PRE_XEN_SYSCTL_READ(getdomaininfolist, max_domains); + PRE_XEN_SYSCTL_READ(getdomaininfolist, buffer); + break; + + case XEN_SYSCTL_cpupool_op: + /* yes the interface is this fucking barking */ + PRE_XEN_SYSCTL_READ(cpupool_op, op); + + switch(sysctl->u.cpupool_op.op) { + case XEN_SYSCTL_CPUPOOL_OP_CREATE: + case XEN_SYSCTL_CPUPOOL_OP_DESTROY: + case XEN_SYSCTL_CPUPOOL_OP_INFO: + case XEN_SYSCTL_CPUPOOL_OP_ADDCPU: + case XEN_SYSCTL_CPUPOOL_OP_RMCPU: + case XEN_SYSCTL_CPUPOOL_OP_MOVEDOMAIN: + PRE_XEN_SYSCTL_READ(cpupool_op, cpupool_id); + } + + if (sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_CREATE) + PRE_XEN_SYSCTL_READ(cpupool_op, sched_id); + + if (sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_MOVEDOMAIN) + PRE_XEN_SYSCTL_READ(cpupool_op, domid); + + if (sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_ADDCPU || + sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_RMCPU) + PRE_XEN_SYSCTL_READ(cpupool_op, cpu); + + break; + + case XEN_SYSCTL_physinfo: + /* No input params */ + break; + + default: + VG_(printf)("pre sysctl version %x unknown cmd %d\n", + sysctl->interface_version, sysctl->cmd); + break; + } +#undef PRE_XEN_SYSCTL_READ +#undef __PRE_XEN_SYSCTL_READ + } + break; + + case __HYPERVISOR_domctl: { + struct xen_domctl *domctl = (struct xen_domctl *)(unsigned int)args->arg[0]; + + PRINT("__HYPERVISOR_domctl ( %d )", domctl->cmd); + + /* Single argument hypercall */ + PRE_MEM_READ("hypercall", ARG3, 8 + ( 8 * 1 ) ); + + /* + * Common part of xen_domctl: + * uint32_t cmd; + * uint32_t interface_version; + * domid_t domain; + */ + PRE_MEM_READ("__HYPERVISOR_domctl", args->arg[0], sizeof(uint32_t) + sizeof(uint32_t) + sizeof(domid_t)); + + if (!domctl || domctl->interface_version != XEN_DOMCTL_INTERFACE_VERSION) + /* BUG ? */ + return; + + //PRE_REG_READ1(long, "__HYPERVISOR_domctl",); +#define __PRE_XEN_DOMCTL_READ(_domctl, _union, _field) PRE_MEM_READ("XEN_DOMCTL_" # _domctl, \ + (Addr)&domctl->u._union._field, \ + sizeof(domctl->u._union._field)) +#define PRE_XEN_DOMCTL_READ(_domctl, _field) __PRE_XEN_DOMCTL_READ(_domctl, _domctl, _field) + + switch (domctl->cmd) { + case XEN_DOMCTL_destroydomain: + case XEN_DOMCTL_pausedomain: + case XEN_DOMCTL_max_vcpus: + case XEN_DOMCTL_get_address_size: + case XEN_DOMCTL_gettscinfo: + case XEN_DOMCTL_getdomaininfo: + case XEN_DOMCTL_unpausedomain: + /* No input fields. */ + break; + + case XEN_DOMCTL_createdomain: + PRE_XEN_DOMCTL_READ(createdomain, ssidref); + PRE_XEN_DOMCTL_READ(createdomain, handle); + PRE_XEN_DOMCTL_READ(createdomain, flags); + break; + + case XEN_DOMCTL_max_mem: + PRE_XEN_DOMCTL_READ(max_mem, max_memkb); + break; + + case XEN_DOMCTL_set_address_size: + __PRE_XEN_DOMCTL_READ(set_address_size, address_size, size); + break; + + case XEN_DOMCTL_settscinfo: + __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info, info.tsc_mode); + __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info, info.gtsc_khz); + __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info, info.incarnation); + __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info, info.elapsed_nsec); + break; + + case XEN_DOMCTL_hypercall_init: + PRE_XEN_DOMCTL_READ(hypercall_init, gmfn); + break; + + case XEN_DOMCTL_getvcpuinfo: + PRE_XEN_DOMCTL_READ(getvcpuinfo, vcpu); + break; + + case XEN_DOMCTL_getvcpuaffinity: + __PRE_XEN_DOMCTL_READ(getvcpuaffinity, vcpuaffinity, vcpu); + break; + + case XEN_DOMCTL_setvcpuaffinity: + __PRE_XEN_DOMCTL_READ(setvcpuaffinity, vcpuaffinity, vcpu); + PRE_MEM_READ("XEN_DOMCTL_setvcpuaffinity", + (Addr)domctl->u.vcpuaffinity.cpumap.bitmap.p, + domctl->u.vcpuaffinity.cpumap.nr_cpus / 8); + break; + + case XEN_DOMCTL_getvcpucontext: + __PRE_XEN_DOMCTL_READ(getvcpucontext, vcpucontext, vcpu); + break; + + case XEN_DOMCTL_setvcpucontext: + __PRE_XEN_DOMCTL_READ(setvcpucontext, vcpucontext, vcpu); + __PRE_XEN_DOMCTL_READ(setvcpucontext, vcpucontext, ctxt.p); + break; + + case XEN_DOMCTL_set_cpuid: + PRE_MEM_READ("XEN_DOMCTL_set_cpuid", (Addr)&domctl->u.cpuid, sizeof(domctl->u.cpuid)); + break; + default: + VG_(printf)("pre domctl version %x unknown cmd %d on domain %d\n", + domctl->interface_version, domctl->cmd, domctl->domain); + break; + } +#undef PRE_XEN_DOMCTL_READ +#undef __PRE_XEN_DOMCTL_READ + } + break; + + case __HYPERVISOR_hvm_op: { + unsigned long op = args->arg[0]; + void *arg = (void *)(unsigned long)args->arg[1]; + + PRINT("__HYPERVISOR_hvm_op ( %ld, %p )", op, arg); + + //PRE_REG_READ1(long, "__HYPERVISOR_hvm_op",); +#define __PRE_XEN_HVMOP_READ(_hvm_op, _type, _field) PRE_MEM_READ("XEN_HVMOP_" # _hvm_op, \ + (Addr)&((_type*)arg)->_field, \ + sizeof(((_type*)arg)->_field)) +#define PRE_XEN_HVMOP_READ(_hvm_op, _field) __PRE_XEN_HVMOP_READ(_hvm_op, "xen_hvm_" # _hvm_op "_t", _field) + + switch (op) { + case HVMOP_set_param: + __PRE_XEN_HVMOP_READ(set_param, xen_hvm_param_t, domid); + __PRE_XEN_HVMOP_READ(set_param, xen_hvm_param_t, index); + __PRE_XEN_HVMOP_READ(set_param, xen_hvm_param_t, value); + break; + + case HVMOP_get_param: + __PRE_XEN_HVMOP_READ(get_param, xen_hvm_param_t, domid); + __PRE_XEN_HVMOP_READ(get_param, xen_hvm_param_t, index); + break; + + default: + VG_(printf)("pre hvm_op unknown OP %ld\n", op); + break; +#undef __PRE_XEN_HVMOP_READ +#undef PRE_XEN_HVMOP_READ + } + } + break; + + default: + VG_(printf)("pre unknown hypercall %lld ( %#llx, %#llx, %#llx, %#llx, %#llx )\n", + args->op, args->arg[0], args->arg[1], args->arg[2], args->arg[3], args->arg[4]); + } +} + +POST(ioctl_privcmd_hypercall) +{ + struct vki_xen_privcmd_hypercall *args = (struct vki_xen_privcmd_hypercall *)(ARG3); + + if (!args) + return; + + switch (args->op) { + case __HYPERVISOR_memory_op: + switch (args->arg[0]) { + case XENMEM_set_memory_map: + case XENMEM_decrease_reservation: + /* No outputs */ + break; + case XENMEM_increase_reservation: + case XENMEM_populate_physmap: { + struct xen_memory_reservation *memory_reservation = (struct xen_memory_reservation *)(unsigned int)args->arg[1]; + + POST_MEM_WRITE((Addr)memory_reservation->extent_start.p, sizeof(xen_pfn_t) * ARG1); + } + break; + + default: + VG_(printf)("post __HYPERVISOR_memory_op unknown command %lld\n", args->arg[0]); + break; + } + break; + + case __HYPERVISOR_mmuext_op: { + //mmuext_op_t *ops = (void *)(unsigned int)args->arg[0]; + //unsigned int nr = args->arg[1]; + unsigned int *pdone = (void *)(unsigned int)args->arg[2]; + //unsigned int foreigndom = args->arg[3]; + /* simplistic */ + POST_MEM_WRITE((Addr)pdone, sizeof(*pdone)); + break; + } + + case __HYPERVISOR_event_channel_op: + case __HYPERVISOR_event_channel_op_compat: { + __vki_u32 cmd; + void *arg; + + if (args->op == __HYPERVISOR_event_channel_op) { + cmd = args->arg[0]; + arg = (void *)(unsigned int)args->arg[1]; + } else { + struct evtchn_op *evtchn = (struct evtchn_op *)(unsigned int)args->arg[0]; + cmd = evtchn->cmd; + arg = &evtchn->u; + } + switch (cmd) { + case EVTCHNOP_alloc_unbound: { + struct evtchn_alloc_unbound *alloc_unbound = arg; + POST_MEM_WRITE((Addr)&alloc_unbound->port, sizeof(alloc_unbound->port)); + break; + } + default: + VG_(printf)("post __HYPERVISOR_event_channel_op unknown command %d\n", cmd); + break; + } + break; + + } + + case __HYPERVISOR_xen_version: + switch (args->arg[0]) { + case XENVER_version: + /* No outputs */ + break; + case XENVER_extraversion: + POST_MEM_WRITE((Addr)args->arg[1], sizeof(xen_extraversion_t)); + break; + case XENVER_compile_info: + POST_MEM_WRITE((Addr)args->arg[1], sizeof(xen_compile_info_t)); + break; + case XENVER_capabilities: + POST_MEM_WRITE((Addr)args->arg[1], sizeof(xen_capabilities_info_t)); + break; + case XENVER_changeset: + POST_MEM_WRITE((Addr)args->arg[1], sizeof(xen_changeset_info_t)); + break; + case XENVER_platform_parameters: + POST_MEM_WRITE((Addr)args->arg[1], sizeof(xen_platform_parameters_t)); + break; + case XENVER_get_features: + POST_MEM_WRITE((Addr)args->arg[1], sizeof(xen_feature_info_t)); + break; + case XENVER_pagesize: + /* No outputs */ + break; + case XENVER_guest_handle: + POST_MEM_WRITE((Addr)args->arg[1], sizeof(xen_domain_handle_t)); + break; + case XENVER_commandline: + POST_MEM_WRITE((Addr)args->arg[1], sizeof(xen_commandline_t)); + break; + default: + VG_(printf)("post __HYPERVISOR_xen_version unknown command %lld\n", args->arg[0]); + break; + } + break; + + case __HYPERVISOR_sysctl: { + struct xen_sysctl *sysctl = (struct xen_sysctl *)(unsigned int)args->arg[0]; + + if (!sysctl || sysctl->interface_version != XEN_SYSCTL_INTERFACE_VERSION) + return; + +#define __POST_XEN_SYSCTL_WRITE(_sysctl, _union, _field) POST_MEM_WRITE((Addr)&sysctl->u._union._field, sizeof(sysctl->u._union._field)); +#define POST_XEN_SYSCTL_WRITE(_sysctl, _field) __POST_XEN_SYSCTL_WRITE(_sysctl, _sysctl, _field) + switch (sysctl->cmd) { + case XEN_SYSCTL_getdomaininfolist: + POST_XEN_SYSCTL_WRITE(getdomaininfolist, num_domains); + POST_MEM_WRITE((Addr)sysctl->u.getdomaininfolist.buffer.p, + sizeof(xen_domctl_getdomaininfo_t) * sysctl->u.getdomaininfolist.num_domains); + break; + + case XEN_SYSCTL_cpupool_op: + if (sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_CREATE || + sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_INFO) + POST_XEN_SYSCTL_WRITE(cpupool_op, cpupool_id); + if (sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_INFO) { + POST_XEN_SYSCTL_WRITE(cpupool_op, sched_id); + POST_XEN_SYSCTL_WRITE(cpupool_op, n_dom); + } + if (sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_INFO || + sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_FREEINFO) + POST_XEN_SYSCTL_WRITE(cpupool_op, cpumap); + break; + + case XEN_SYSCTL_physinfo: + POST_XEN_SYSCTL_WRITE(physinfo, threads_per_core); + POST_XEN_SYSCTL_WRITE(physinfo, cores_per_socket); + POST_XEN_SYSCTL_WRITE(physinfo, nr_cpus); + POST_XEN_SYSCTL_WRITE(physinfo, max_cpu_id); + POST_XEN_SYSCTL_WRITE(physinfo, nr_nodes); + POST_XEN_SYSCTL_WRITE(physinfo, max_node_id); + POST_XEN_SYSCTL_WRITE(physinfo, cpu_khz); + POST_XEN_SYSCTL_WRITE(physinfo, total_pages); + POST_XEN_SYSCTL_WRITE(physinfo, free_pages); + POST_XEN_SYSCTL_WRITE(physinfo, scrub_pages); + POST_XEN_SYSCTL_WRITE(physinfo, hw_cap[8]); + POST_XEN_SYSCTL_WRITE(physinfo, capabilities); + break; + + default: + VG_(printf)("post sysctl version %x cmd %d\n", + sysctl->interface_version, sysctl->cmd); + break; + } +#undef POST_XEN_SYSCTL_WRITE +#undef __POST_XEN_SYSCTL_WRITE + break; + } + + case __HYPERVISOR_domctl: { + struct xen_domctl *domctl = (struct xen_domctl *)(unsigned int)args->arg[0]; + + if (!domctl || domctl->interface_version != XEN_DOMCTL_INTERFACE_VERSION) + return; + +#define __POST_XEN_DOMCTL_WRITE(_domctl, _union, _field) POST_MEM_WRITE((Addr)&domctl->u._union._field, sizeof(domctl->u._union._field)); +#define POST_XEN_DOMCTL_WRITE(_domctl, _field) __POST_XEN_DOMCTL_WRITE(_domctl, _domctl, _field) + switch (domctl->cmd) { + case XEN_DOMCTL_createdomain: + case XEN_DOMCTL_destroydomain: + case XEN_DOMCTL_pausedomain: + case XEN_DOMCTL_max_mem: + case XEN_DOMCTL_set_address_size: + case XEN_DOMCTL_settscinfo: + case XEN_DOMCTL_hypercall_init: + case XEN_DOMCTL_setvcpuaffinity: + case XEN_DOMCTL_setvcpucontext: + case XEN_DOMCTL_set_cpuid: + case XEN_DOMCTL_unpausedomain: + /* No output fields */ + break; + + case XEN_DOMCTL_max_vcpus: + POST_XEN_DOMCTL_WRITE(max_vcpus, max); + + case XEN_DOMCTL_get_address_size: + __POST_XEN_DOMCTL_WRITE(get_address_size, address_size, size); + break; + + case XEN_DOMCTL_gettscinfo: + __POST_XEN_DOMCTL_WRITE(settscinfo, tsc_info, info.tsc_mode); + __POST_XEN_DOMCTL_WRITE(settscinfo, tsc_info, info.gtsc_khz); + __POST_XEN_DOMCTL_WRITE(settscinfo, tsc_info, info.incarnation); + __POST_XEN_DOMCTL_WRITE(settscinfo, tsc_info, info.elapsed_nsec); + break; + + case XEN_DOMCTL_getvcpuinfo: + POST_XEN_DOMCTL_WRITE(getvcpuinfo, online); + POST_XEN_DOMCTL_WRITE(getvcpuinfo, blocked); + POST_XEN_DOMCTL_WRITE(getvcpuinfo, running); + POST_XEN_DOMCTL_WRITE(getvcpuinfo, cpu_time); + POST_XEN_DOMCTL_WRITE(getvcpuinfo, cpu); + break; + + case XEN_DOMCTL_getvcpuaffinity: + POST_MEM_WRITE((Addr)domctl->u.vcpuaffinity.cpumap.bitmap.p, + domctl->u.vcpuaffinity.cpumap.nr_cpus / 8); + break; + + case XEN_DOMCTL_getdomaininfo: + POST_XEN_DOMCTL_WRITE(getdomaininfo, domain); + POST_XEN_DOMCTL_WRITE(getdomaininfo, flags); + POST_XEN_DOMCTL_WRITE(getdomaininfo, tot_pages); + POST_XEN_DOMCTL_WRITE(getdomaininfo, max_pages); + POST_XEN_DOMCTL_WRITE(getdomaininfo, shr_pages); + POST_XEN_DOMCTL_WRITE(getdomaininfo, shared_info_frame); + POST_XEN_DOMCTL_WRITE(getdomaininfo, cpu_time); + POST_XEN_DOMCTL_WRITE(getdomaininfo, nr_online_vcpus); + POST_XEN_DOMCTL_WRITE(getdomaininfo, max_vcpu_id); + POST_XEN_DOMCTL_WRITE(getdomaininfo, ssidref); + POST_XEN_DOMCTL_WRITE(getdomaininfo, handle); + POST_XEN_DOMCTL_WRITE(getdomaininfo, cpupool); + break; + + case XEN_DOMCTL_getvcpucontext: + __POST_XEN_DOMCTL_WRITE(getvcpucontext, vcpucontext, ctxt.p); + break; + + default: + VG_(printf)("post domctl version %x cmd %d on domain %d\n", + domctl->interface_version, domctl->cmd, domctl->domain); + break; + } +#undef POST_XEN_DOMCTL_WRITE +#undef __POST_XEN_DOMCTL_WRITE + break; + } + + + case __HYPERVISOR_hvm_op: { + unsigned long op = args->arg[0]; + void *arg = (void *)(unsigned long)args->arg[1]; + +#define __POST_XEN_HVMOP_WRITE(_hvm_op, _type, _field) POST_MEM_WRITE((Addr)&((_type*)arg)->_field, \ + sizeof(((_type*)arg)->_field)) +#define POST_XEN_HVMOP_WRITE(_hvm_op, _field) __PRE_XEN_HVMOP_READ(_hvm_op, "xen_hvm_" # _hvm_op "_t", _field) + switch (op) { + case HVMOP_set_param: + /* No output paramters */ + break; + + case HVMOP_get_param: + __POST_XEN_HVMOP_WRITE(get_param, xen_hvm_param_t, value); + break; + + default: + VG_(printf)("post hvm_op unknown OP %ld\n", op); + break; +#undef __POST_XEN_HVMOP_WRITE +#undef POST_XEN_HVMOP_WRITE + } + } + break; + + default: + VG_(printf)("post unknown hypercall %lld ( %#llx, %#llx, %#llx, %#llx, %#llx )\n", + args->op, args->arg[0], args->arg[1], args->arg[2], args->arg[3], args->arg[4]); + break; + } +} + + +PRE(ioctl_privcmd_mmap) +{ + struct vki_xen_privcmd_mmap *args = (struct vki_xen_privcmd_mmap *)(ARG3); + PRE_MEM_READ("VKI_XEN_IOCTL_PRIVCMD_MMAP", (Addr)&args->num, sizeof(args->num)); + PRE_MEM_READ("VKI_XEN_IOCTL_PRIVCMD_MMAP", (Addr)&args->dom, sizeof(args->dom)); + PRE_MEM_READ("VKI_XEN_IOCTL_PRIVCMD_MMAP", (Addr)args->entry, sizeof(*(args->entry)) * args->num); +} + +PRE(ioctl_privcmd_mmapbatch) +{ + struct vki_xen_privcmd_mmapbatch *args = (struct vki_xen_privcmd_mmapbatch *)(ARG3); + PRE_MEM_READ("VKI_XEN_IOCTL_PRIVCMD_MMAPBATCH", (Addr)&args->num, sizeof(args->num)); + PRE_MEM_READ("VKI_XEN_IOCTL_PRIVCMD_MMAPBATCH", (Addr)&args->dom, sizeof(args->dom)); + PRE_MEM_READ("VKI_XEN_IOCTL_PRIVCMD_MMAPBATCH", (Addr)&args->addr, sizeof(args->addr)); + PRE_MEM_READ("VKI_XEN_IOCTL_PRIVCMD_MMAPBATCH", (Addr)args->arr, sizeof(*(args->arr)) * args->num); +} + +PRE(ioctl_privcmd_mmapbatch_v2) +{ + struct vki_xen_privcmd_mmapbatch_v2 *args = (struct vki_xen_privcmd_mmapbatch_v2 *)(ARG3); + PRE_MEM_READ("VKI_XEN_IOCTL_PRIVCMD_MMAPBATCH_V2", (Addr)&args->num, sizeof(args->num)); + PRE_MEM_READ("VKI_XEN_IOCTL_PRIVCMD_MMAPBATCH_V2", (Addr)&args->dom, sizeof(args->dom)); + PRE_MEM_READ("VKI_XEN_IOCTL_PRIVCMD_MMAPBATCH_V2", (Addr)&args->addr, sizeof(args->addr)); + PRE_MEM_READ("VKI_XEN_IOCTL_PRIVCMD_MMAPBATCH_V2", (Addr)args->arr, sizeof(*(args->arr)) * args->num); +} + +POST(ioctl_privcmd_mmap) +{ + //struct vki_xen_privcmd_mmap *args = (struct vki_xen_privcmd_mmap *)(ARG3); +} + +POST(ioctl_privcmd_mmapbatch) +{ + struct vki_xen_privcmd_mmapbatch *args = (struct vki_xen_privcmd_mmapbatch *)(ARG3); + POST_MEM_WRITE((Addr)args->arr, sizeof(*(args->arr)) * args->num); +} + +POST(ioctl_privcmd_mmapbatch_v2) +{ + struct vki_xen_privcmd_mmapbatch_v2 *args = (struct vki_xen_privcmd_mmapbatch_v2 *)(ARG3); + POST_MEM_WRITE((Addr)args->err, sizeof(*(args->err)) * args->num); +} diff --git a/include/Makefile.am b/include/Makefile.am index 33d0857..22bffa7 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -54,7 +54,8 @@ nobase_pkginclude_HEADERS = \ vki/vki-scnums-ppc64-linux.h \ vki/vki-scnums-x86-linux.h \ vki/vki-scnums-arm-linux.h \ - vki/vki-scnums-darwin.h + vki/vki-scnums-darwin.h + vki/vki-xen.h noinst_HEADERS = \ vki/vki-ppc32-aix5.h \ diff --git a/include/pub_tool_vki.h b/include/pub_tool_vki.h index 73a4174..c4c117f 100644 --- a/include/pub_tool_vki.h +++ b/include/pub_tool_vki.h @@ -47,6 +47,7 @@ #if defined(VGO_linux) # include "vki/vki-linux.h" +# include "vki/vki-xen.h" #elif defined(VGP_ppc32_aix5) # include "vki/vki-ppc32-aix5.h" #elif defined(VGP_ppc64_aix5) diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h index beff378..1214300 100644 --- a/include/vki/vki-linux.h +++ b/include/vki/vki-linux.h @@ -2709,6 +2709,51 @@ struct vki_getcpu_cache { #define VKI_EV_MAX 0x1f #define VKI_EV_CNT (VKI_EV_MAX+1) +//---------------------------------------------------------------------- +// Xen privcmd IOCTL +//---------------------------------------------------------------------- + +typedef unsigned long __vki_xen_pfn_t; + +struct vki_xen_privcmd_hypercall { + __vki_u64 op; + __vki_u64 arg[5]; +}; + +struct vki_xen_privcmd_mmap_entry { + __vki_u64 va; + __vki_u64 mfn; + __vki_u64 npages; +}; + +struct vki_xen_privcmd_mmap { + int num; + __vki_u16 dom; /* target domain */ + struct vki_xen_privcmd_mmap_entry *entry; +}; + +struct vki_xen_privcmd_mmapbatch { + int num; /* number of pages to populate */ + __vki_u16 dom; /* target domain */ + __vki_u64 addr; /* virtual address */ + __vki_xen_pfn_t *arr; /* array of mfns - top nibble set on err */ +}; + +struct vki_xen_privcmd_mmapbatch_v2 { + unsigned int num; /* number of pages to populate */ + __vki_u16 dom; /* target domain */ + __vki_u64 addr; /* virtual address */ + const __vki_xen_pfn_t *arr; /* array of mfns */ + int __user *err; /* array of error codes */ +}; + +#define VKI_XEN_IOCTL_PRIVCMD_HYPERCALL _VKI_IOC(_VKI_IOC_NONE, 'P', 0, sizeof(struct vki_xen_privcmd_hypercall)) +#define VKI_XEN_IOCTL_PRIVCMD_MMAP _VKI_IOC(_VKI_IOC_NONE, 'P', 2, sizeof(struct vki_xen_privcmd_mmap)) + +#define VKI_XEN_IOCTL_PRIVCMD_MMAPBATCH _VKI_IOC(_VKI_IOC_NONE, 'P', 3, sizeof(struct vki_xen_privcmd_mmapbatch)) +#define VKI_XEN_IOCTL_PRIVCMD_MMAPBATCH_V2 _VKI_IOC(_VKI_IOC_NONE, 'P', 4, sizeof(struct vki_xen_privcmd_mmapbatch_v2)) + + #endif // __VKI_LINUX_H /*--------------------------------------------------------------------*/ diff --git a/include/vki/vki-xen.h b/include/vki/vki-xen.h new file mode 100644 index 0000000..7842cc9 --- /dev/null +++ b/include/vki/vki-xen.h @@ -0,0 +1,8 @@ +#ifndef __VKI_XEN_H +#define __VKI_XEN_H + +#endif // __VKI_XEN_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ -- Ian Campbell Current Noise: Iron Monkey - 666 Pack Ask not for whom the telephone bell tolls... if thou art in the bathtub, it tolls for thee. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |