/*--------------------------------------------------------------------*/ /*--- Xen Hypercalls syswrap-xen.c ---*/ /*--------------------------------------------------------------------*/ /* This file is part of Valgrind, a dynamic binary instrumentation framework. Copyright (C) 2012 Citrix Systems ian.campbell@citrix.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. The GNU General Public License is contained in the file COPYING. */ #include "pub_core_basics.h" #include "pub_core_vki.h" #if defined(ENABLE_XEN) #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 "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)() #include "priv_types_n_macros.h" #include "priv_syswrap-generic.h" #include "priv_syswrap-xen.h" #include <inttypes.h> #define PRE(name) static DEFN_PRE_TEMPLATE(xen, name) #define POST(name) static DEFN_POST_TEMPLATE(xen, name) static void bad_intf_version ( ThreadId tid, SyscallArgLayout* layout, /*MOD*/SyscallArgs* args, /*OUT*/SyscallStatus* status, /*OUT*/UWord* flags, const HChar* hypercall, UWord version) { VG_(dmsg)("WARNING: %s version %#lx not supported\n", hypercall, version); if (VG_(clo_verbosity) > 1) { VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size)); } VG_(dmsg)("You may be able to write your own handler.\n"); VG_(dmsg)("Read the file README_MISSING_SYSCALL_OR_IOCTL.\n"); VG_(dmsg)("Nevertheless we consider this a bug. Please report\n"); VG_(dmsg)("it at http://valgrind.org/support/bug_reports.html &\n"); VG_(dmsg)("http://wiki.xen.org/wiki/Reporting_Bugs_against_Xen.\n"); SET_STATUS_Failure(VKI_ENOSYS); } static void bad_subop ( ThreadId tid, SyscallArgLayout* layout, /*MOD*/SyscallArgs* args, /*OUT*/SyscallStatus* status, /*OUT*/UWord* flags, const HChar* hypercall, UWord subop) { VG_(dmsg)("WARNING: unhandled %s subop: %lu\n", hypercall, subop); if (VG_(clo_verbosity) > 1) { VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size)); } VG_(dmsg)("You may be able to write your own handler.\n"); VG_(dmsg)("Read the file README_MISSING_SYSCALL_OR_IOCTL.\n"); VG_(dmsg)("Nevertheless we consider this a bug. Please report\n"); VG_(dmsg)("it at http://valgrind.org/support/bug_reports.html &\n"); VG_(dmsg)("http://wiki.xen.org/wiki/Reporting_Bugs_against_Xen.\n"); SET_STATUS_Failure(VKI_ENOSYS); } PRE(memory_op) { PRINT("__HYPERVISOR_memory_op ( %lu, %#lx )", ARG1, ARG2); switch (ARG1) { case VKI_XENMEM_maximum_ram_page: /* No inputs */ break; case VKI_XENMEM_maximum_gpfn: PRE_MEM_READ("XENMEM_maximum_gpfn domid", (Addr)ARG2, sizeof(vki_xen_domid_t)); break; case VKI_XENMEM_machphys_mfn_list: case VKI_XENMEM_machphys_compat_mfn_list: { struct vki_xen_machphys_mfn_list *arg = (struct vki_xen_machphys_mfn_list *)ARG2; PRE_MEM_READ("XENMEM_machphys_mfn_list max_extents", (Addr)&arg->max_extents, sizeof(arg->max_extents)); PRE_MEM_READ("XENMEM_machphys_mfn_list extent_start", (Addr)&arg->extent_start, sizeof(arg->extent_start)); break; } case VKI_XENMEM_set_memory_map: { struct vki_xen_foreign_memory_map *arg = (struct vki_xen_foreign_memory_map *)ARG2; PRE_MEM_READ("XENMEM_set_memory_map domid", (Addr)&arg->domid, sizeof(arg->domid)); PRE_MEM_READ("XENMEM_set_memory_map map", (Addr)&arg->map, sizeof(arg->map)); break; } case VKI_XENMEM_memory_map: case VKI_XENMEM_machine_memory_map: { struct vki_xen_memory_map *arg = (struct vki_xen_memory_map *)ARG2; PRE_MEM_READ("XENMEM_memory_map nr_entries", (Addr)&arg->nr_entries, sizeof(arg->nr_entries)); break; } case VKI_XENMEM_increase_reservation: case VKI_XENMEM_decrease_reservation: case VKI_XENMEM_populate_physmap: case VKI_XENMEM_claim_pages: { struct xen_memory_reservation *memory_reservation = (struct xen_memory_reservation *)ARG2; const HChar *which; switch (ARG1) { case VKI_XENMEM_increase_reservation: which = "XENMEM_increase_reservation"; break; case VKI_XENMEM_decrease_reservation: which = "XENMEM_decrease_reservation"; PRE_MEM_READ(which, (Addr)memory_reservation->extent_start.p, sizeof(vki_xen_pfn_t) * memory_reservation->nr_extents); break; case VKI_XENMEM_populate_physmap: which = "XENMEM_populate_physmap"; PRE_MEM_READ(which, (Addr)memory_reservation->extent_start.p, sizeof(vki_xen_pfn_t) * memory_reservation->nr_extents); break; case VKI_XENMEM_claim_pages: which = "XENMEM_claim_pages"; 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; } case VKI_XENMEM_add_to_physmap: { struct vki_xen_add_to_physmap *arg = (struct vki_xen_add_to_physmap *)ARG2; PRE_MEM_READ("XENMEM_add_to_physmap domid", (Addr)&arg->domid, sizeof(arg->domid)); PRE_MEM_READ("XENMEM_add_to_physmap size", (Addr)&arg->size, sizeof(arg->size)); PRE_MEM_READ("XENMEM_add_to_physmap space", (Addr)&arg->space, sizeof(arg->space)); PRE_MEM_READ("XENMEM_add_to_physmap idx", (Addr)&arg->idx, sizeof(arg->idx)); PRE_MEM_READ("XENMEM_add_to_physmap gpfn", (Addr)&arg->gpfn, sizeof(arg->gpfn)); break; } case VKI_XENMEM_remove_from_physmap: { struct vki_xen_remove_from_physmap *arg = (struct vki_xen_remove_from_physmap *)ARG2; PRE_MEM_READ("XENMEM_remove_from_physmap domid", (Addr)&arg->domid, sizeof(arg->domid)); PRE_MEM_READ("XENMEM_remove_from_physmap gpfn", (Addr)&arg->gpfn, sizeof(arg->gpfn)); break; } case VKI_XENMEM_get_sharing_freed_pages: case VKI_XENMEM_get_sharing_shared_pages: break; case VKI_XENMEM_access_op: { struct vki_xen_mem_event_op *arg = (struct vki_xen_mem_event_op *)ARG2; PRE_MEM_READ("XENMEM_access_op domid", (Addr)&arg->domain, sizeof(arg->domain)); PRE_MEM_READ("XENMEM_access_op op", (Addr)&arg->op, sizeof(arg->op)); PRE_MEM_READ("XENMEM_access_op gfn", (Addr)&arg->gfn, sizeof(arg->gfn)); break; } default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_memory_op", ARG1); break; } } PRE(mmuext_op) { PRINT("__HYPERVISOR_mmuext_op ( %#lx, %ld, %#lx, %lu )", ARG1, SARG2, ARG3, ARG4); struct vki_xen_mmuext_op *ops = (struct vki_xen_mmuext_op *)ARG1; unsigned int i, nr = ARG2; for (i=0; i<nr; i++) { struct vki_xen_mmuext_op *op = ops + i; PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP cmd", (Addr)&op->cmd, sizeof(op->cmd)); switch(op->cmd) { case VKI_XEN_MMUEXT_PIN_L1_TABLE: case VKI_XEN_MMUEXT_PIN_L2_TABLE: case VKI_XEN_MMUEXT_PIN_L3_TABLE: case VKI_XEN_MMUEXT_PIN_L4_TABLE: case VKI_XEN_MMUEXT_UNPIN_TABLE: case VKI_XEN_MMUEXT_NEW_BASEPTR: case VKI_XEN_MMUEXT_CLEAR_PAGE: case VKI_XEN_MMUEXT_COPY_PAGE: case VKI_XEN_MMUEXT_MARK_SUPER: case VKI_XEN_MMUEXT_UNMARK_SUPER: PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg1.mfn", (Addr)&op->arg1.mfn, sizeof(op->arg1.mfn)); break; case VKI_XEN_MMUEXT_INVLPG_LOCAL: case VKI_XEN_MMUEXT_INVLPG_ALL: case VKI_XEN_MMUEXT_SET_LDT: PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg1.mfn", (Addr)&op->arg1.linear_addr, sizeof(op->arg1.linear_addr)); break; case VKI_XEN_MMUEXT_TLB_FLUSH_LOCAL: case VKI_XEN_MMUEXT_TLB_FLUSH_MULTI: case VKI_XEN_MMUEXT_INVLPG_MULTI: case VKI_XEN_MMUEXT_TLB_FLUSH_ALL: case VKI_XEN_MMUEXT_FLUSH_CACHE: case VKI_XEN_MMUEXT_NEW_USER_BASEPTR: case VKI_XEN_MMUEXT_FLUSH_CACHE_GLOBAL: /* None */ break; } switch(op->cmd) { case VKI_XEN_MMUEXT_SET_LDT: PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.nr_ents", (Addr)&op->arg2.nr_ents, sizeof(op->arg2.nr_ents)); break; case VKI_XEN_MMUEXT_TLB_FLUSH_MULTI: case VKI_XEN_MMUEXT_INVLPG_MULTI: /* How many??? */ PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.vcpumask", (Addr)&op->arg2.vcpumask, sizeof(op->arg2.vcpumask)); break; case VKI_XEN_MMUEXT_COPY_PAGE: PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.src_mfn", (Addr)&op->arg2.src_mfn, sizeof(op->arg2.src_mfn)); break; case VKI_XEN_MMUEXT_PIN_L1_TABLE: case VKI_XEN_MMUEXT_PIN_L2_TABLE: case VKI_XEN_MMUEXT_PIN_L3_TABLE: case VKI_XEN_MMUEXT_PIN_L4_TABLE: case VKI_XEN_MMUEXT_UNPIN_TABLE: case VKI_XEN_MMUEXT_NEW_BASEPTR: case VKI_XEN_MMUEXT_TLB_FLUSH_LOCAL: case VKI_XEN_MMUEXT_INVLPG_LOCAL: case VKI_XEN_MMUEXT_TLB_FLUSH_ALL: case VKI_XEN_MMUEXT_INVLPG_ALL: case VKI_XEN_MMUEXT_FLUSH_CACHE: case VKI_XEN_MMUEXT_NEW_USER_BASEPTR: case VKI_XEN_MMUEXT_CLEAR_PAGE: case VKI_XEN_MMUEXT_FLUSH_CACHE_GLOBAL: case VKI_XEN_MMUEXT_MARK_SUPER: case VKI_XEN_MMUEXT_UNMARK_SUPER: /* None */ break; } } } PRE(xsm_op) { /* XXX assuming flask, only actual XSM right now */ struct vki_xen_flask_op *op = (struct vki_xen_flask_op *)ARG1; PRINT("__HYPERVISOR_xsm_op ( %u )", op->cmd); /* * Common part of xen_flask_op: * vki_uint32_t cmd; * vki_uint32_t interface_version; */ PRE_MEM_READ("__HYPERVISOR_xsm_op", ARG1, sizeof(vki_uint32_t) + sizeof(vki_uint32_t)); if (!op) return; switch (op->interface_version) { case 0x00000001: break; default: bad_intf_version(tid, layout, arrghs, status, flags, "__HYPERVISOR_xsm_op", op->interface_version); return; } #define PRE_XEN_XSM_OP_READ(_xsm_op, _union, _field) \ PRE_MEM_READ("FLASK_" #_xsm_op " u." #_union "." #_field, \ (Addr)&op->u._union._field, \ sizeof(op->u._union._field)) switch (op->cmd) { case VKI_FLASK_SID_TO_CONTEXT: PRE_XEN_XSM_OP_READ(SID_TO_CONTEXT, sid_context, sid); PRE_XEN_XSM_OP_READ(SID_TO_CONTEXT, sid_context, size); PRE_XEN_XSM_OP_READ(SID_TO_CONTEXT, sid_context, context.p); break; default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_xsm_op", op->cmd); break; } #undef __PRE_XEN_XSM_OP_READ #undef PRE_XEN_XSM_OP_READ } PRE(sched_op) { PRINT("__HYPERVISOR_sched_op ( %ld, %#lx )", SARG1, ARG2); void *arg = (void *)(unsigned long)ARG2; #define __PRE_XEN_SCHEDOP_READ(_schedop, _type, _field) \ PRE_MEM_READ("XEN_SCHEDOP_" # _schedop " " #_field, \ (Addr)&((_type*)arg)->_field, \ sizeof(((_type*)arg)->_field)) #define PRE_XEN_SCHEDOP_READ(_schedop, _field) \ __PRE_XEN_SCHEDOP_READ(_schedop, vki_xen_ ## _schedop ## _t, _field) switch (ARG1) { case VKI_XEN_SCHEDOP_remote_shutdown: PRE_XEN_SCHEDOP_READ(remote_shutdown, domain_id); PRE_XEN_SCHEDOP_READ(remote_shutdown, reason); break; default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_sched_op", ARG1); break; } #undef __PRE_XEN_SCHEDOP_READ #undef PRE_XEN_SCHEDOP_READ } static void pre_evtchn_op(ThreadId tid, SyscallArgLayout* layout, /*MOD*/SyscallArgs* arrghs, /*OUT*/SyscallStatus* status, /*OUT*/UWord* flags, __vki_u32 cmd, void *arg, int compat) { PRINT("__HYPERVISOR_event_channel_op%s ( %u, %p )", compat ? "_compat" : "", cmd, arg); switch (cmd) { case VKI_XEN_EVTCHNOP_alloc_unbound: { struct vki_xen_evtchn_alloc_unbound *alloc_unbound = arg; PRE_MEM_READ("EVTCHNOP_alloc_unbound dom", (Addr)&alloc_unbound->dom, sizeof(alloc_unbound->dom)); PRE_MEM_READ("EVTCHNOP_alloc_unbound remote_dom", (Addr)&alloc_unbound->remote_dom, sizeof(alloc_unbound->remote_dom)); break; } default: if ( compat ) bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_event_channel_op_compat", cmd); else bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_event_channel_op", cmd); break; } } PRE(evtchn_op) { pre_evtchn_op(tid, layout, arrghs, status, flags, ARG1, (void *)ARG2, 0); } PRE(evtchn_op_compat) { struct vki_xen_evtchn_op *evtchn = (struct vki_xen_evtchn_op *)ARG1; PRE_MEM_READ("__HYPERVISOR_event_channel_op_compat", ARG1, sizeof(*evtchn)); pre_evtchn_op(tid, layout, arrghs, status, flags, evtchn->cmd, &evtchn->u, 1); } PRE(physdev_op) { int cmd = ARG1; PRINT("__HYPERVISOR_physdev_op ( %ld, %#lx )", SARG1, ARG2); #define PRE_XEN_PHYSDEVOP_READ(_op, _field) \ PRE_MEM_READ("XEN_PHYSDEVOP_" #_op " ." #_field, \ (Addr)&arg->_field, \ sizeof(arg->_field)) switch (cmd) { case VKI_XEN_PHYSDEVOP_map_pirq: { struct vki_xen_physdev_map_pirq *arg = (struct vki_xen_physdev_map_pirq *)ARG2; PRE_XEN_PHYSDEVOP_READ("map_pirq", domid); PRE_XEN_PHYSDEVOP_READ("map_pirq", type); PRE_XEN_PHYSDEVOP_READ("map_pirq", bus); PRE_XEN_PHYSDEVOP_READ("map_pirq", devfn); PRE_XEN_PHYSDEVOP_READ("map_pirq", entry_nr); PRE_XEN_PHYSDEVOP_READ("map_pirq", table_base); switch(arg->type) { case VKI_XEN_MAP_PIRQ_TYPE_MSI: PRE_XEN_PHYSDEVOP_READ("map_pirq", index); break; case VKI_XEN_MAP_PIRQ_TYPE_GSI: PRE_XEN_PHYSDEVOP_READ("map_pirq", index); PRE_XEN_PHYSDEVOP_READ("map_pirq", pirq); break; case VKI_XEN_MAP_PIRQ_TYPE_MSI_SEG: PRE_XEN_PHYSDEVOP_READ("map_pirq", index); break; case VKI_XEN_MAP_PIRQ_TYPE_MULTI_MSI: break; } break; } case VKI_XEN_PHYSDEVOP_unmap_pirq: { struct vki_xen_physdev_unmap_pirq *arg = (struct vki_xen_physdev_unmap_pirq *)ARG2; PRE_XEN_PHYSDEVOP_READ("unmap_pirq", domid); PRE_XEN_PHYSDEVOP_READ("unmap_pirq", pirq); break; } default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_physdev_op", cmd); } #undef PRE_XEN_PHYSDEVOP_READ } PRE(xen_version) { PRINT("__HYPERVISOR_xen_version ( %ld, %#lx )", SARG1, ARG2); switch (ARG1) { case VKI_XENVER_version: case VKI_XENVER_extraversion: case VKI_XENVER_compile_info: case VKI_XENVER_capabilities: case VKI_XENVER_changeset: case VKI_XENVER_platform_parameters: case VKI_XENVER_get_features: case VKI_XENVER_pagesize: case VKI_XENVER_guest_handle: case VKI_XENVER_commandline: /* No inputs */ break; default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_xen_version", ARG1); break; } } PRE(grant_table_op) { PRINT("__HYPERVISOR_grant_table_op ( %lu, %#lx, %lu )", ARG1, ARG2, ARG3); switch (ARG1) { case VKI_XEN_GNTTABOP_setup_table: { struct vki_xen_gnttab_setup_table *gst = (struct vki_xen_gnttab_setup_table*)ARG2; PRE_MEM_READ("VKI_XEN_GNTTABOP_setup_table dom", (Addr)&gst->dom, sizeof(gst->dom)); PRE_MEM_READ("VKI_XEN_GNTTABOP_setup_table nr_frames", (Addr)&gst->nr_frames, sizeof(gst->nr_frames)); break; } default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_grant_table_op", ARG1); break; } } PRE(sysctl) { struct vki_xen_sysctl *sysctl = (struct vki_xen_sysctl *)ARG1; PRINT("__HYPERVISOR_sysctl ( %u )", sysctl->cmd); /* * Common part of xen_sysctl: * uint32_t cmd; * uint32_t interface_version; */ PRE_MEM_READ("__HYPERVISOR_sysctl", ARG1, sizeof(vki_uint32_t) + sizeof(vki_uint32_t)); if (!sysctl) return; switch (sysctl->interface_version) { case 0x00000008: case 0x00000009: case 0x0000000a: case 0x0000000b: break; default: bad_intf_version(tid, layout, arrghs, status, flags, "__HYPERVISOR_sysctl", sysctl->interface_version); return; } #define __PRE_XEN_SYSCTL_READ(_sysctl, _union, _field) \ PRE_MEM_READ("XEN_SYSCTL_" #_sysctl " u." #_union "." #_field, \ (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 VKI_XEN_SYSCTL_readconsole: /* These are all unconditionally read */ PRE_XEN_SYSCTL_READ(readconsole, clear); PRE_XEN_SYSCTL_READ(readconsole, incremental); PRE_XEN_SYSCTL_READ(readconsole, buffer); PRE_XEN_SYSCTL_READ(readconsole, count); /* 'index' only read if 'incremental' is nonzero */ if (sysctl->u.readconsole.incremental) PRE_XEN_SYSCTL_READ(readconsole, index); break; case VKI_XEN_SYSCTL_getdomaininfolist: switch (sysctl->interface_version) { case 0x00000008: PRE_XEN_SYSCTL_READ(getdomaininfolist_00000008, first_domain); PRE_XEN_SYSCTL_READ(getdomaininfolist_00000008, max_domains); PRE_XEN_SYSCTL_READ(getdomaininfolist_00000008, buffer); break; case 0x00000009: PRE_XEN_SYSCTL_READ(getdomaininfolist_00000009, first_domain); PRE_XEN_SYSCTL_READ(getdomaininfolist_00000009, max_domains); PRE_XEN_SYSCTL_READ(getdomaininfolist_00000009, buffer); break; case 0x0000000a: case 0x0000000b: PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, first_domain); PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, max_domains); PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, buffer); break; default: VG_(dmsg)("WARNING: XEN_SYSCTL_getdomaininfolist for sysctl version " "%"PRIx32" not implemented yet\n", sysctl->interface_version); SET_STATUS_Failure(VKI_EINVAL); return; } break; case VKI_XEN_SYSCTL_debug_keys: PRE_XEN_SYSCTL_READ(debug_keys, keys); PRE_XEN_SYSCTL_READ(debug_keys, nr_keys); PRE_MEM_READ("XEN_SYSCTL_debug_keys *keys", (Addr)sysctl->u.debug_keys.keys.p, sysctl->u.debug_keys.nr_keys * sizeof(char)); break; case VKI_XEN_SYSCTL_sched_id: /* No inputs */ break; case VKI_XEN_SYSCTL_cpupool_op: PRE_XEN_SYSCTL_READ(cpupool_op, op); switch(sysctl->u.cpupool_op.op) { case VKI_XEN_SYSCTL_CPUPOOL_OP_CREATE: case VKI_XEN_SYSCTL_CPUPOOL_OP_DESTROY: case VKI_XEN_SYSCTL_CPUPOOL_OP_INFO: case VKI_XEN_SYSCTL_CPUPOOL_OP_ADDCPU: case VKI_XEN_SYSCTL_CPUPOOL_OP_RMCPU: case VKI_XEN_SYSCTL_CPUPOOL_OP_MOVEDOMAIN: PRE_XEN_SYSCTL_READ(cpupool_op, cpupool_id); } if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_CREATE) PRE_XEN_SYSCTL_READ(cpupool_op, sched_id); if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_MOVEDOMAIN) PRE_XEN_SYSCTL_READ(cpupool_op, domid); if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_ADDCPU || sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_RMCPU) PRE_XEN_SYSCTL_READ(cpupool_op, cpu); break; case VKI_XEN_SYSCTL_physinfo: /* No input params */ break; case VKI_XEN_SYSCTL_topologyinfo: PRE_XEN_SYSCTL_READ(topologyinfo, max_cpu_index); PRE_XEN_SYSCTL_READ(topologyinfo, cpu_to_core); PRE_XEN_SYSCTL_READ(topologyinfo, cpu_to_socket); PRE_XEN_SYSCTL_READ(topologyinfo, cpu_to_node); break; case VKI_XEN_SYSCTL_numainfo: PRE_XEN_SYSCTL_READ(numainfo, max_node_index); PRE_XEN_SYSCTL_READ(numainfo, node_to_memsize); PRE_XEN_SYSCTL_READ(numainfo, node_to_memfree); PRE_XEN_SYSCTL_READ(numainfo, node_to_node_distance); break; default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_sysctl", sysctl->cmd); break; } #undef PRE_XEN_SYSCTL_READ #undef __PRE_XEN_SYSCTL_READ } PRE(domctl) { struct vki_xen_domctl *domctl = (struct vki_xen_domctl *)ARG1; PRINT("__HYPERVISOR_domctl ( %u ) on dom%d", domctl->cmd, domctl->domain); /* * Common part of xen_domctl: * vki_uint32_t cmd; * vki_uint32_t interface_version; * vki_xen_domid_t domain; */ PRE_MEM_READ("__HYPERVISOR_domctl", ARG1, sizeof(vki_uint32_t) + sizeof(vki_uint32_t) + sizeof(vki_xen_domid_t)); if (!domctl) return; switch (domctl->interface_version) { case 0x00000007: case 0x00000008: case 0x00000009: case 0x0000000a: case 0x0000000b: case 0x0000000c: break; default: bad_intf_version(tid, layout, arrghs, status, flags, "__HYPERVISOR_domctl", domctl->interface_version); return; } #define __PRE_XEN_DOMCTL_READ(_domctl, _union, _field) \ PRE_MEM_READ("XEN_DOMCTL_" #_domctl " u." #_union "." #_field, \ (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 VKI_XEN_DOMCTL_destroydomain: case VKI_XEN_DOMCTL_pausedomain: case VKI_XEN_DOMCTL_max_vcpus: case VKI_XEN_DOMCTL_get_address_size: case VKI_XEN_DOMCTL_gettscinfo: case VKI_XEN_DOMCTL_getdomaininfo: case VKI_XEN_DOMCTL_unpausedomain: case VKI_XEN_DOMCTL_resumedomain: /* No input fields. */ break; case VKI_XEN_DOMCTL_createdomain: PRE_XEN_DOMCTL_READ(createdomain, ssidref); PRE_XEN_DOMCTL_READ(createdomain, handle); PRE_XEN_DOMCTL_READ(createdomain, flags); break; case VKI_XEN_DOMCTL_gethvmcontext: /* Xen unconditionally reads the 'buffer' pointer */ __PRE_XEN_DOMCTL_READ(gethvmcontext, hvmcontext, buffer); /* Xen only consumes 'size' if 'buffer' is non NULL. A NULL * buffer is a request for the required size. */ if ( domctl->u.hvmcontext.buffer.p ) __PRE_XEN_DOMCTL_READ(gethvmcontext, hvmcontext, size); break; case VKI_XEN_DOMCTL_sethvmcontext: __PRE_XEN_DOMCTL_READ(sethvmcontext, hvmcontext, size); __PRE_XEN_DOMCTL_READ(sethvmcontext, hvmcontext, buffer); PRE_MEM_READ("XEN_DOMCTL_sethvmcontext *buffer", (Addr)domctl->u.hvmcontext.buffer.p, domctl->u.hvmcontext.size); break; case VKI_XEN_DOMCTL_gethvmcontext_partial: __PRE_XEN_DOMCTL_READ(gethvmcontext_partial, hvmcontext_partial, type); __PRE_XEN_DOMCTL_READ(gethvmcontext_partial, hvmcontext_partial, instance); __PRE_XEN_DOMCTL_READ(gethvmcontext_partial, hvmcontext_partial, buffer); switch (domctl->u.hvmcontext_partial.type) { case VKI_HVM_SAVE_CODE(CPU): if ( domctl->u.hvmcontext_partial.buffer.p ) PRE_MEM_WRITE("XEN_DOMCTL_gethvmcontext_partial *buffer", (Addr)domctl->u.hvmcontext_partial.buffer.p, VKI_HVM_SAVE_LENGTH(CPU)); break; case VKI_HVM_SAVE_CODE(MTRR): if ( domctl->u.hvmcontext_partial.buffer.p ) PRE_MEM_WRITE("XEN_DOMCTL_gethvmcontext_partial *buffer", (Addr)domctl->u.hvmcontext_partial.buffer.p, VKI_HVM_SAVE_LENGTH(MTRR)); break; default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_domctl_gethvmcontext_partial type", domctl->u.hvmcontext_partial.type); break; } break; case VKI_XEN_DOMCTL_max_mem: PRE_XEN_DOMCTL_READ(max_mem, max_memkb); break; case VKI_XEN_DOMCTL_set_address_size: __PRE_XEN_DOMCTL_READ(set_address_size, address_size, size); break; case VKI_XEN_DOMCTL_test_assign_device: switch (domctl->interface_version) { case 0x00000007: /* pre-4.6 */ case 0x00000008: case 0x00000009: case 0x0000000a: __PRE_XEN_DOMCTL_READ(test_assign_device, assign_device_00000007, machine_sbdf); break; case 0x0000000b: __PRE_XEN_DOMCTL_READ(test_assign_device, assign_device_0000000b, dev); __PRE_XEN_DOMCTL_READ(test_assign_device, assign_device_0000000b, flag); switch (domctl->u.assign_device_0000000b.dev) { case VKI_XEN_DOMCTL_DEV_PCI: __PRE_XEN_DOMCTL_READ(test_assign_device, assign_device_0000000b, u.pci); break; case VKI_XEN_DOMCTL_DEV_DT: __PRE_XEN_DOMCTL_READ(test_assign_device, assign_device_0000000b, u.dt); PRE_MEM_READ("XEN_DOMTCL_test_assign_device.dt", (Addr)domctl->u.assign_device_0000000b.u.dt.path.p, domctl->u.assign_device_0000000b.u.dt.size); break; default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_domctl_test_assign_device dev", domctl->u.assign_device_0000000b.dev); break; } break; } break; case VKI_XEN_DOMCTL_assign_device: switch (domctl->interface_version) { case 0x00000007: /* pre-4.6 */ case 0x00000008: case 0x00000009: case 0x0000000a: __PRE_XEN_DOMCTL_READ(assign_device, assign_device_00000007, machine_sbdf); break; case 0x0000000b: __PRE_XEN_DOMCTL_READ(assign_device, assign_device_0000000b, dev); __PRE_XEN_DOMCTL_READ(assign_device, assign_device_0000000b, flag); switch (domctl->u.assign_device_0000000b.dev) { case VKI_XEN_DOMCTL_DEV_PCI: __PRE_XEN_DOMCTL_READ(assign_device, assign_device_0000000b, u.pci); break; case VKI_XEN_DOMCTL_DEV_DT: __PRE_XEN_DOMCTL_READ(assign_device, assign_device_0000000b, u.dt); PRE_MEM_READ("XEN_DOMTCL_assign_device.dt", (Addr)domctl->u.assign_device_0000000b.u.dt.path.p, domctl->u.assign_device_0000000b.u.dt.size); break; default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_domctl_assign_device dev", domctl->u.assign_device_0000000b.dev); break; } break; } break; case VKI_XEN_DOMCTL_deassign_device: switch (domctl->interface_version) { case 0x00000007: /* pre-4.6 */ case 0x00000008: case 0x00000009: case 0x0000000a: __PRE_XEN_DOMCTL_READ(deassign_device, assign_device_00000007, machine_sbdf); break; case 0x0000000b: __PRE_XEN_DOMCTL_READ(deassign_device, assign_device_0000000b, dev); __PRE_XEN_DOMCTL_READ(deassign_device, assign_device_0000000b, flag); switch (domctl->u.assign_device_0000000b.dev) { case VKI_XEN_DOMCTL_DEV_PCI: __PRE_XEN_DOMCTL_READ(deassign_device, assign_device_0000000b, u.pci); break; case VKI_XEN_DOMCTL_DEV_DT: __PRE_XEN_DOMCTL_READ(deassign_device, assign_device_0000000b, u.dt); PRE_MEM_READ("XEN_DOMTCL_assign_device.dt", (Addr)domctl->u.assign_device_0000000b.u.dt.path.p, domctl->u.assign_device_0000000b.u.dt.size); break; default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_domctl_deassign_device dev", domctl->u.assign_device_0000000b.dev); break; } break; } break; case VKI_XEN_DOMCTL_settscinfo: switch (domctl->interface_version) { case 0x00000007: /* pre-4.6 */ case 0x00000008: case 0x00000009: case 0x0000000a: __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_00000007, info.tsc_mode); __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_00000007, info.gtsc_khz); __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_00000007, info.incarnation); __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_00000007, info.elapsed_nsec); break; case 0x0000000b: __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_0000000b, tsc_mode); __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_0000000b, gtsc_khz); __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_0000000b, incarnation); __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_0000000b, elapsed_nsec); break; } break; case VKI_XEN_DOMCTL_irq_permission: PRE_XEN_DOMCTL_READ(irq_permission, pirq); PRE_XEN_DOMCTL_READ(irq_permission, allow_access); break; case VKI_XEN_DOMCTL_iomem_permission: PRE_XEN_DOMCTL_READ(iomem_permission, first_mfn); PRE_XEN_DOMCTL_READ(iomem_permission, nr_mfns); PRE_XEN_DOMCTL_READ(iomem_permission, allow_access); break; case VKI_XEN_DOMCTL_ioport_permission: PRE_XEN_DOMCTL_READ(ioport_permission, first_port); PRE_XEN_DOMCTL_READ(ioport_permission, nr_ports); PRE_XEN_DOMCTL_READ(ioport_permission, allow_access); break; case VKI_XEN_DOMCTL_hypercall_init: PRE_XEN_DOMCTL_READ(hypercall_init, gmfn); break; case VKI_XEN_DOMCTL_settimeoffset: PRE_XEN_DOMCTL_READ(settimeoffset, time_offset_seconds); break; case VKI_XEN_DOMCTL_getvcpuinfo: PRE_XEN_DOMCTL_READ(getvcpuinfo, vcpu); break; case VKI_XEN_DOMCTL_scheduler_op: PRE_XEN_DOMCTL_READ(scheduler_op, sched_id); PRE_XEN_DOMCTL_READ(scheduler_op, cmd); if ( domctl->u.scheduler_op.cmd == VKI_XEN_DOMCTL_SCHEDOP_putinfo ) { switch(domctl->u.scheduler_op.sched_id) { case VKI_XEN_SCHEDULER_SEDF: PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.period); PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.slice); PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.latency); PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.extratime); PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.weight); break; case VKI_XEN_SCHEDULER_CREDIT: PRE_XEN_DOMCTL_READ(scheduler_op, u.credit.weight); PRE_XEN_DOMCTL_READ(scheduler_op, u.credit.cap); break; case VKI_XEN_SCHEDULER_CREDIT2: PRE_XEN_DOMCTL_READ(scheduler_op, u.credit2.weight); break; case VKI_XEN_SCHEDULER_RTDS: PRE_XEN_DOMCTL_READ(scheduler_op, u.rtds.period); PRE_XEN_DOMCTL_READ(scheduler_op, u.rtds.budget); break; case VKI_XEN_SCHEDULER_ARINC653: break; } } break; case VKI_XEN_DOMCTL_getvcpuaffinity: switch (domctl->interface_version) { case 0x00000007: case 0x00000008: case 0x00000009: __PRE_XEN_DOMCTL_READ(getvcpuaffinity, vcpuaffinity_00000009, vcpu); __PRE_XEN_DOMCTL_READ(getvcpuaffinity, vcpuaffinity_00000009, cpumap.nr_bits); break; case 0x0000000a: __PRE_XEN_DOMCTL_READ(getvcpuaffinity, vcpuaffinity_0000000a, vcpu); if (domctl->u.vcpuaffinity_0000000a.flags & VKI_XEN_VCPUAFFINITY_HARD) __PRE_XEN_DOMCTL_READ( setvcpuaffinity, vcpuaffinity_0000000a, cpumap_hard.nr_bits); if (domctl->u.vcpuaffinity_0000000a.flags & VKI_XEN_VCPUAFFINITY_SOFT) __PRE_XEN_DOMCTL_READ( setvcpuaffinity, vcpuaffinity_0000000a, cpumap_soft.nr_bits); break; } break; case VKI_XEN_DOMCTL_setvcpuaffinity: switch (domctl->interface_version) { case 0x00000007: case 0x00000008: case 0x00000009: __PRE_XEN_DOMCTL_READ(setvcpuaffinity, vcpuaffinity_00000009, vcpu); __PRE_XEN_DOMCTL_READ(setvcpuaffinity, vcpuaffinity_00000009, cpumap.nr_bits); PRE_MEM_READ("XEN_DOMCTL_setvcpuaffinity u.vcpuaffinity.cpumap.bitmap", (Addr)domctl->u.vcpuaffinity_00000009.cpumap.bitmap.p, domctl->u.vcpuaffinity_00000009.cpumap.nr_bits / 8); break; case 0x0000000a: __PRE_XEN_DOMCTL_READ(setvcpuaffinity, vcpuaffinity_0000000a, vcpu); __PRE_XEN_DOMCTL_READ(setvcpuaffinity, vcpuaffinity_0000000a, flags); if (domctl->u.vcpuaffinity_0000000a.flags & VKI_XEN_VCPUAFFINITY_HARD) { __PRE_XEN_DOMCTL_READ( setvcpuaffinity, vcpuaffinity_0000000a, cpumap_hard.nr_bits); PRE_MEM_READ( "XEN_DOMCTL_setvcpuaffinity u.vcpuaffinity.cpumap_hard.bitmap", (Addr)domctl->u.vcpuaffinity_0000000a.cpumap_hard.bitmap.p, domctl->u.vcpuaffinity_0000000a.cpumap_hard.nr_bits / 8); } if (domctl->u.vcpuaffinity_0000000a.flags & VKI_XEN_VCPUAFFINITY_SOFT) { __PRE_XEN_DOMCTL_READ( setvcpuaffinity, vcpuaffinity_0000000a, cpumap_soft.nr_bits); PRE_MEM_READ( "XEN_DOMCTL_setvcpuaffinity u.vcpuaffinity.cpumap_soft.bitmap", (Addr)domctl->u.vcpuaffinity_0000000a.cpumap_soft.bitmap.p, domctl->u.vcpuaffinity_0000000a.cpumap_soft.nr_bits / 8); } break; } break; case VKI_XEN_DOMCTL_getnodeaffinity: __PRE_XEN_DOMCTL_READ(nodeaffinity, nodeaffinity, nodemap.nr_bits); break; case VKI_XEN_DOMCTL_setnodeaffinity: __PRE_XEN_DOMCTL_READ(nodeaffinity, nodeaffinity, nodemap.nr_bits); PRE_MEM_READ("XEN_DOMCTL_setnodeaffinity u.nodeaffinity.cpumap.bitmap", (Addr)domctl->u.nodeaffinity.nodemap.bitmap.p, domctl->u.nodeaffinity.nodemap.nr_bits / 8); break; case VKI_XEN_DOMCTL_getvcpucontext: __PRE_XEN_DOMCTL_READ(getvcpucontext, vcpucontext, vcpu); break; case VKI_XEN_DOMCTL_setvcpucontext: __PRE_XEN_DOMCTL_READ(setvcpucontext, vcpucontext, vcpu); __PRE_XEN_DOMCTL_READ(setvcpucontext, vcpucontext, ctxt.p); break; case VKI_XEN_DOMCTL_pin_mem_cacheattr: PRE_XEN_DOMCTL_READ(pin_mem_cacheattr, start); PRE_XEN_DOMCTL_READ(pin_mem_cacheattr, end); PRE_XEN_DOMCTL_READ(pin_mem_cacheattr, type); break; case VKI_XEN_DOMCTL_get_ext_vcpucontext: switch (domctl->interface_version) { case 0x00000007: case 0x00000008: __PRE_XEN_DOMCTL_READ(get_ext_vcpucontext, ext_vcpucontext_00000008, vcpu); break; case 0x00000009: __PRE_XEN_DOMCTL_READ(get_ext_vcpucontext, ext_vcpucontext_00000009, vcpu); break; default: VG_(dmsg)("WARNING: VKI_XEN_DOMCTL_get_ext_vcpucontext domctl version %#" PRIx32" not implemented\n", domctl->interface_version); SET_STATUS_Failure(VKI_EINVAL); break; } break; case VKI_XEN_DOMCTL_set_ext_vcpucontext: switch (domctl->interface_version) { case 0x00000007: case 0x00000008: __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008, vcpu); __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008, size); #if defined(__i386__) || defined(__x86_64__) __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008, syscall32_callback_eip); __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008, sysenter_callback_eip); __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008, syscall32_callback_cs); __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008, sysenter_callback_cs); __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008, syscall32_disables_events); __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008, sysenter_disables_events); if ( domctl->u.ext_vcpucontext_00000008.size >= offsetof(struct vki_xen_domctl_ext_vcpucontext_00000008, mcg_cap) ) __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008, mcg_cap); #endif break; case 0x00000009: __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009, vcpu); __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009, size); #if defined(__i386__) || defined(__x86_64__) __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009, syscall32_callback_eip); __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009, sysenter_callback_eip); __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009, syscall32_callback_cs); __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009, sysenter_callback_cs); __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009, syscall32_disables_events); __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009, sysenter_disables_events); if ( domctl->u.ext_vcpucontext_00000009.size >= offsetof(struct vki_xen_domctl_ext_vcpucontext_00000009, caps) ) { __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009, caps); __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009, mci_ctl2_bank0); __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009, mci_ctl2_bank1); } #endif break; default: VG_(dmsg)("WARNING: VKI_XEN_DOMCTL_set_ext_vcpucontext domctl version %#" PRIx32" not implemented\n", domctl->interface_version); SET_STATUS_Failure(VKI_EINVAL); break; } break; case VKI_XEN_DOMCTL_set_cpuid: PRE_MEM_READ("XEN_DOMCTL_set_cpuid u.cpuid", (Addr)&domctl->u.cpuid, sizeof(domctl->u.cpuid)); break; case VKI_XEN_DOMCTL_getpageframeinfo3: PRE_XEN_DOMCTL_READ(getpageframeinfo3, num); PRE_XEN_DOMCTL_READ(getpageframeinfo3, array.p); PRE_MEM_READ("XEN_DOMCTL_getpageframeinfo3 *u.getpageframeinfo3.array.p", (Addr)domctl->u.getpageframeinfo3.array.p, domctl->u.getpageframeinfo3.num * sizeof(vki_xen_pfn_t)); break; case VKI_XEN_DOMCTL_setvcpuextstate: __PRE_XEN_DOMCTL_READ(setvcpuextstate, vcpuextstate, vcpu); __PRE_XEN_DOMCTL_READ(setvcpuextstate, vcpuextstate, size); __PRE_XEN_DOMCTL_READ(setvcpuextstate, vcpuextstate, buffer); PRE_MEM_READ("XEN_DOMCTL_setvcpuextstate *u.vcpuextstate.buffer.p", (Addr)domctl->u.vcpuextstate.buffer.p, domctl->u.vcpuextstate.size); break; case VKI_XEN_DOMCTL_getvcpuextstate: __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, vcpu); __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, xfeature_mask); __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, size); __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, buffer); break; case VKI_XEN_DOMCTL_shadow_op: PRE_XEN_DOMCTL_READ(shadow_op, op); switch(domctl->u.shadow_op.op) { case VKI_XEN_DOMCTL_SHADOW_OP_OFF: case VKI_XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION: /* No further inputs */ break; case VKI_XEN_DOMCTL_SHADOW_OP_ENABLE: PRE_XEN_DOMCTL_READ(shadow_op, mode); switch(domctl->u.shadow_op.mode) { case XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY: goto domctl_shadow_op_enable_logdirty; default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_domctl shadowop mode", domctl->u.shadow_op.mode); break; } case VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY: domctl_shadow_op_enable_logdirty: /* No further inputs */ break; case VKI_XEN_DOMCTL_SHADOW_OP_CLEAN: case VKI_XEN_DOMCTL_SHADOW_OP_PEEK: PRE_XEN_DOMCTL_READ(shadow_op, dirty_bitmap); PRE_XEN_DOMCTL_READ(shadow_op, pages); break; case VKI_XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION: PRE_XEN_DOMCTL_READ(shadow_op, mb); break; default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_domctl shadow(10)", domctl->u.shadow_op.op); break; } break; case VKI_XEN_DOMCTL_set_max_evtchn: PRE_XEN_DOMCTL_READ(set_max_evtchn, max_port); break; case VKI_XEN_DOMCTL_cacheflush: PRE_XEN_DOMCTL_READ(cacheflush, start_pfn); PRE_XEN_DOMCTL_READ(cacheflush, nr_pfns); break; case VKI_XEN_DOMCTL_set_access_required: PRE_XEN_DOMCTL_READ(access_required, access_required); break; case VKI_XEN_DOMCTL_mem_event_op: //case VKI_XEN_DOMCTL_vm_event_op: /* name change in 4.6 */ switch (domctl->interface_version) { case 0x00000007: /* pre-4.6 */ case 0x00000008: case 0x00000009: case 0x0000000a: __PRE_XEN_DOMCTL_READ(mem_event_op, mem_event_op_00000007, op); __PRE_XEN_DOMCTL_READ(mem_event_op, mem_event_op_00000007, mode); break; case 0x0000000b: __PRE_XEN_DOMCTL_READ(vm_event_op, vm_event_op_0000000b, op); __PRE_XEN_DOMCTL_READ(vm_event_op, vm_event_op_0000000b, mode); break; } break; case VKI_XEN_DOMCTL_debug_op: PRE_XEN_DOMCTL_READ(debug_op, op); PRE_XEN_DOMCTL_READ(debug_op, vcpu); break; case VKI_XEN_DOMCTL_get_vcpu_msrs: __PRE_XEN_DOMCTL_READ(get_vcpu_msrs, vcpu_msrs, vcpu); __PRE_XEN_DOMCTL_READ(get_vcpu_msrs, vcpu_msrs, msr_count); __PRE_XEN_DOMCTL_READ(get_vcpu_msrs, vcpu_msrs, msrs); break; case VKI_XEN_DOMCTL_set_vcpu_msrs: __PRE_XEN_DOMCTL_READ(set_vcpu_msrs, vcpu_msrs, vcpu); __PRE_XEN_DOMCTL_READ(set_vcpu_msrs, vcpu_msrs, msr_count); __PRE_XEN_DOMCTL_READ(set_vcpu_msrs, vcpu_msrs, msrs); PRE_MEM_READ("XEN_DOMCTL_set_vcpu_msrs *u.vcpu_msrs.msrs.p", (Addr)domctl->u.vcpu_msrs.msrs.p, sizeof(vki_xen_domctl_vcpu_msr_t) * domctl->u.vcpu_msrs.msr_count); break; case VKI_XEN_DOMCTL_monitor_op: switch (domctl->interface_version) { case 0x000000b: if (domctl->u.monitor_op_0000000b.op == VKI_XEN_DOMCTL_MONITOR_OP_ENABLE || domctl->u.monitor_op_0000000b.op == VKI_XEN_DOMCTL_MONITOR_OP_ENABLE) { switch (domctl->u.monitor_op_0000000b.event) { case VKI_XEN_DOMCTL_MONITOR_EVENT_WRITE_CTRLREG: __PRE_XEN_DOMCTL_READ(monitor_op, monitor_op_0000000b, u.mov_to_cr); break; case VKI_XEN_DOMCTL_MONITOR_EVENT_MOV_TO_MSR: __PRE_XEN_DOMCTL_READ(monitor_op, monitor_op_0000000b, u.mov_to_msr); break; case VKI_XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST: __PRE_XEN_DOMCTL_READ(monitor_op, monitor_op_0000000b, u.guest_request); break; case VKI_XEN_DOMCTL_MONITOR_OP_GET_CAPABILITIES: break; } } break; } break; default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_domctl", domctl->cmd); break; } #undef PRE_XEN_DOMCTL_READ #undef __PRE_XEN_DOMCTL_READ } PRE(hvm_op) { unsigned long op = ARG1; void *arg = (void *)(unsigned long)ARG2; PRINT("__HYPERVISOR_hvm_op ( %ld, %#lx )", SARG1, ARG2); #define __PRE_XEN_HVMOP_READ(_hvm_op, _type, _field) \ PRE_MEM_READ("XEN_HVMOP_" # _hvm_op " " #_field, \ (Addr)&((_type*)arg)->_field, \ sizeof(((_type*)arg)->_field)) #define PRE_XEN_HVMOP_READ(_hvm_op, _field) \ __PRE_XEN_HVMOP_READ(_hvm_op, vki_xen_hvm_ ## _hvm_op ## _t, _field) switch (op) { case VKI_XEN_HVMOP_set_param: __PRE_XEN_HVMOP_READ(set_param, struct vki_xen_hvm_param, domid); __PRE_XEN_HVMOP_READ(set_param, struct vki_xen_hvm_param, index); __PRE_XEN_HVMOP_READ(set_param, struct vki_xen_hvm_param, value); break; case VKI_XEN_HVMOP_get_param: __PRE_XEN_HVMOP_READ(get_param, struct vki_xen_hvm_param, domid); __PRE_XEN_HVMOP_READ(get_param, struct vki_xen_hvm_param, index); break; case VKI_XEN_HVMOP_set_pci_intx_level: PRE_XEN_HVMOP_READ(set_pci_intx_level, domid); PRE_XEN_HVMOP_READ(set_pci_intx_level, domain); PRE_XEN_HVMOP_READ(set_pci_intx_level, bus); PRE_XEN_HVMOP_READ(set_pci_intx_level, device); PRE_XEN_HVMOP_READ(set_pci_intx_level, level); break; case VKI_XEN_HVMOP_set_isa_irq_level: PRE_XEN_HVMOP_READ(set_isa_irq_level, domid); PRE_XEN_HVMOP_READ(set_isa_irq_level, isa_irq); PRE_XEN_HVMOP_READ(set_isa_irq_level, level); break; case VKI_XEN_HVMOP_set_pci_link_route: PRE_XEN_HVMOP_READ(set_pci_link_route, domid); PRE_XEN_HVMOP_READ(set_pci_link_route, link); PRE_XEN_HVMOP_READ(set_pci_link_route, isa_irq); break; case VKI_XEN_HVMOP_track_dirty_vram: { vki_xen_hvm_track_dirty_vram_t *Arg = (vki_xen_hvm_track_dirty_vram_t*)ARG2; PRE_XEN_HVMOP_READ(track_dirty_vram, domid); PRE_XEN_HVMOP_READ(track_dirty_vram, nr); if ( Arg->nr ) { PRE_XEN_HVMOP_READ(track_dirty_vram, first_pfn); PRE_XEN_HVMOP_READ(track_dirty_vram, dirty_bitmap); } break; } case VKI_XEN_HVMOP_set_mem_type: PRE_XEN_HVMOP_READ(set_mem_type, domid); PRE_XEN_HVMOP_READ(set_mem_type, hvmmem_type); PRE_XEN_HVMOP_READ(set_mem_type, nr); PRE_XEN_HVMOP_READ(set_mem_type, first_pfn); break; case VKI_XEN_HVMOP_set_mem_access: PRE_XEN_HVMOP_READ(set_mem_access, domid); PRE_XEN_HVMOP_READ(set_mem_access, hvmmem_access); PRE_XEN_HVMOP_READ(set_mem_access, first_pfn); /* if default access */ if ( ((vki_xen_hvm_set_mem_access_t*)arg)->first_pfn != ~0ULL) PRE_XEN_HVMOP_READ(set_mem_access, nr); break; case VKI_XEN_HVMOP_get_mem_access: PRE_XEN_HVMOP_READ(get_mem_access, domid); PRE_XEN_HVMOP_READ(get_mem_access, pfn); PRE_MEM_WRITE("XEN_HVMOP_get_mem_access *hvmmem_access", (Addr)&(((vki_xen_hvm_get_mem_access_t*)arg)->hvmmem_access), sizeof(vki_uint16_t)); break; case VKI_XEN_HVMOP_inject_trap: PRE_XEN_HVMOP_READ(inject_trap, domid); PRE_XEN_HVMOP_READ(inject_trap, vcpuid); PRE_XEN_HVMOP_READ(inject_trap, vector); PRE_XEN_HVMOP_READ(inject_trap, type); PRE_XEN_HVMOP_READ(inject_trap, error_code); PRE_XEN_HVMOP_READ(inject_trap, insn_len); PRE_XEN_HVMOP_READ(inject_trap, cr2); break; default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_hvm_op", op); break; } #undef __PRE_XEN_HVMOP_READ #undef PRE_XEN_HVMOP_READ } PRE(tmem_op) { struct vki_xen_tmem_op *tmem = (struct vki_xen_tmem_op *)ARG1; PRINT("__HYPERVISOR_tmem_op ( %u )", tmem->cmd); /* Common part for xen_tmem_op: * vki_uint32_t cmd; */ PRE_MEM_READ("__HYPERVISOR_tmem_op cmd", ARG1, sizeof(vki_uint32_t)); #define __PRE_XEN_TMEMOP_READ(_tmem, _union, _field) \ PRE_MEM_READ("XEN_tmem_op_" #_tmem " u." #_union "." #_field, \ (Addr)&tmem->u._union._field, \ sizeof(tmem->u._union._field)) #define PRE_XEN_TMEMOP_READ(_tmem, _field) \ __PRE_XEN_TMEMOP_READ(_tmem, _tmem, _field) switch(tmem->cmd) { case VKI_XEN_TMEM_control: /* Common part for control hypercall: * vki_int32_t pool_id; * vki_uint32_t subop; */ PRE_MEM_READ("__HYPERVISOR_tmem_op pool_id", (Addr)&tmem->pool_id, sizeof(tmem->pool_id)); PRE_XEN_TMEMOP_READ(ctrl, subop); switch (tmem->u.ctrl.subop) { case VKI_XEN_TMEMC_save_begin: PRE_XEN_TMEMOP_READ(ctrl, cli_id); PRE_XEN_TMEMOP_READ(ctrl, arg1); PRE_XEN_TMEMOP_READ(ctrl, buf); break; default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_tmem_op_control", tmem->u.ctrl.subop); } break; default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_tmem_op", ARG1); } #undef PRE_XEN_TMEMOP_READ #undef __PRE_XEN_TMEMOP_READ } POST(memory_op) { switch (ARG1) { case VKI_XENMEM_maximum_ram_page: case VKI_XENMEM_set_memory_map: case VKI_XENMEM_decrease_reservation: case VKI_XENMEM_claim_pages: case VKI_XENMEM_maximum_gpfn: case VKI_XENMEM_remove_from_physmap: case VKI_XENMEM_access_op: /* No outputs */ break; case VKI_XENMEM_increase_reservation: case VKI_XENMEM_populate_physmap: { struct xen_memory_reservation *memory_reservation = (struct xen_memory_reservation *)ARG2; POST_MEM_WRITE((Addr)memory_reservation->extent_start.p, sizeof(vki_xen_pfn_t) * memory_reservation->nr_extents); break; } case VKI_XENMEM_machphys_mfn_list: case VKI_XENMEM_machphys_compat_mfn_list: { struct vki_xen_machphys_mfn_list *arg = (struct vki_xen_machphys_mfn_list *)ARG2; POST_MEM_WRITE((Addr)&arg->nr_extents, sizeof(arg->nr_extents)); POST_MEM_WRITE((Addr)arg->extent_start.p, sizeof(vki_xen_pfn_t) * arg->nr_extents); break; } case VKI_XENMEM_memory_map: case VKI_XENMEM_machine_memory_map: { struct vki_xen_memory_map *arg = (struct vki_xen_memory_map *)ARG2; POST_MEM_WRITE(arg->nr_entries, sizeof(arg->nr_entries)); POST_MEM_WRITE((Addr)arg->buffer.p, arg->nr_entries * 20 /* size of an e820 entry */); break; } case VKI_XENMEM_add_to_physmap: { struct vki_xen_add_to_physmap *arg = (struct vki_xen_add_to_physmap *)ARG2; if (arg->space == VKI_XENMAPSPACE_gmfn_range) POST_MEM_WRITE(ARG2, sizeof(*arg)); } case VKI_XENMEM_get_sharing_freed_pages: case VKI_XENMEM_get_sharing_shared_pages: /* No outputs */ break; } } POST(mmuext_op) { unsigned int *pdone = (unsigned int *)ARG3; /* simplistic */ POST_MEM_WRITE((Addr)pdone, sizeof(*pdone)); } POST(xsm_op) { /* XXX assuming flask, only actual XSM right now */ struct vki_xen_flask_op *op = (struct vki_xen_flask_op *)ARG1; switch (op->interface_version) { case 0x00000001: break; default: return; } #define POST_XEN_XSM_OP_WRITE(_xsm_op, _union, _field) \ POST_MEM_WRITE((Addr)&op->u._union._field, \ sizeof(op->u._union._field)) switch (op->cmd) { case VKI_FLASK_SID_TO_CONTEXT: POST_XEN_XSM_OP_WRITE(SID_TO_CONTEXT, sid_context, size); POST_MEM_WRITE((Addr)op->u.sid_context.context.p, op->u.sid_context.size); } } static void post_evtchn_op(ThreadId tid, __vki_u32 cmd, void *arg, int compat) { switch (cmd) { case VKI_XEN_EVTCHNOP_alloc_unbound: { struct vki_xen_evtchn_alloc_unbound *alloc_unbound = arg; POST_MEM_WRITE((Addr)&alloc_unbound->port, sizeof(alloc_unbound->port)); break; } } } POST(sched_op) { switch (ARG1) { case VKI_XEN_SCHEDOP_remote_shutdown: /* No outputs */ break; } } POST(evtchn_op) { post_evtchn_op(tid, ARG1, (void *)ARG2, 0); } POST(evtchn_op_compat) { struct vki_xen_evtchn_op *evtchn = (struct vki_xen_evtchn_op *)ARG1; post_evtchn_op(tid, evtchn->cmd, &evtchn->u, 1); } POST(physdev_op) { int cmd = ARG1; #define POST_XEN_PHYSDEVOP_WRITE(_op, _field) \ POST_MEM_WRITE((Addr)&arg->_field, sizeof(arg->_field)) switch (cmd) { case VKI_XEN_PHYSDEVOP_unmap_pirq: /* No outputs */ break; case VKI_XEN_PHYSDEVOP_map_pirq: { struct vki_xen_physdev_map_pirq *arg = (struct vki_xen_physdev_map_pirq *)ARG2; if (arg->type == VKI_XEN_MAP_PIRQ_TYPE_MULTI_MSI) POST_XEN_PHYSDEVOP_WRITE("map_pirq", entry_nr); POST_XEN_PHYSDEVOP_WRITE("map_pirq", pirq); break; } #undef POST_XEN_PHYSDEVOP_WRITE default: break; } } POST(xen_version) { switch (ARG1) { case VKI_XENVER_version: /* No outputs */ break; case VKI_XENVER_extraversion: POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_extraversion_t)); break; case VKI_XENVER_compile_info: POST_MEM_WRITE((Addr)ARG2, sizeof(struct vki_xen_compile_info)); break; case VKI_XENVER_capabilities: POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_capabilities_info_t)); break; case VKI_XENVER_changeset: POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_changeset_info_t)); break; case VKI_XENVER_platform_parameters: POST_MEM_WRITE((Addr)ARG2, sizeof(struct vki_xen_platform_parameters)); break; case VKI_XENVER_get_features: POST_MEM_WRITE((Addr)ARG2, sizeof(struct vki_xen_feature_info)); break; case VKI_XENVER_pagesize: /* No outputs */ break; case VKI_XENVER_guest_handle: POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_domain_handle_t)); break; case VKI_XENVER_commandline: POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_commandline_t)); break; } } POST(grant_table_op) { switch (ARG1) { case VKI_XEN_GNTTABOP_setup_table: { struct vki_xen_gnttab_setup_table *gst = (struct vki_xen_gnttab_setup_table*)ARG2; PRE_MEM_WRITE("VKI_XEN_GNTTABOP_setup_table", (Addr)&gst->status, sizeof(gst->status)); PRE_MEM_WRITE("VKI_XEN_GNTTABOP_setup_table", (Addr)gst->frame_list.p, sizeof(*gst->frame_list.p) & gst->nr_frames); break; } } } POST(sysctl) { struct vki_xen_sysctl *sysctl = (struct vki_xen_sysctl *)ARG1; switch (sysctl->interface_version) { case 0x00000008: case 0x00000009: case 0x0000000a: case 0x0000000b: break; default: 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 VKI_XEN_SYSCTL_readconsole: POST_MEM_WRITE((Addr)sysctl->u.readconsole.buffer.p, sysctl->u.readconsole.count * sizeof(char)); break; case VKI_XEN_SYSCTL_getdomaininfolist: switch (sysctl->interface_version) { case 0x00000008: POST_XEN_SYSCTL_WRITE(getdomaininfolist_00000008, num_domains); POST_MEM_WRITE((Addr)sysctl->u.getdomaininfolist_00000008.buffer.p, sizeof(*sysctl->u.getdomaininfolist_00000008.buffer.p) * sysctl->u.getdomaininfolist_00000008.num_domains); break; case 0x00000009: POST_XEN_SYSCTL_WRITE(getdomaininfolist_00000009, num_domains); POST_MEM_WRITE((Addr)sysctl->u.getdomaininfolist_00000009.buffer.p, sizeof(*sysctl->u.getdomaininfolist_00000009.buffer.p) * sysctl->u.getdomaininfolist_00000009.num_domains); break; case 0x0000000a: case 0x0000000b: POST_XEN_SYSCTL_WRITE(getdomaininfolist_0000000a, num_domains); POST_MEM_WRITE((Addr)sysctl->u.getdomaininfolist_0000000a.buffer.p, sizeof(*sysctl->u.getdomaininfolist_0000000a.buffer.p) * sysctl->u.getdomaininfolist_0000000a.num_domains); break; } break; case VKI_XEN_SYSCTL_sched_id: POST_XEN_SYSCTL_WRITE(sched_id, sched_id); break; case VKI_XEN_SYSCTL_cpupool_op: if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_CREATE || sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_INFO) POST_XEN_SYSCTL_WRITE(cpupool_op, cpupool_id); if (sysctl->u.cpupool_op.op == VKI_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 == VKI_XEN_SYSCTL_CPUPOOL_OP_INFO || sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_FREEINFO) POST_XEN_SYSCTL_WRITE(cpupool_op, cpumap); break; case VKI_XEN_SYSCTL_physinfo: switch (sysctl->interface_version) { case 0x00000008: case 0x00000009: /* Unchanged from version 8 */ POST_XEN_SYSCTL_WRITE(physinfo_00000008, threads_per_core); POST_XEN_SYSCTL_WRITE(physinfo_00000008, cores_per_socket); POST_XEN_SYSCTL_WRITE(physinfo_00000008, nr_cpus); POST_XEN_SYSCTL_WRITE(physinfo_00000008, max_cpu_id); POST_XEN_SYSCTL_WRITE(physinfo_00000008, nr_nodes); POST_XEN_SYSCTL_WRITE(physinfo_00000008, max_node_id); POST_XEN_SYSCTL_WRITE(physinfo_00000008, cpu_khz); POST_XEN_SYSCTL_WRITE(physinfo_00000008, total_pages); POST_XEN_SYSCTL_WRITE(physinfo_00000008, free_pages); POST_XEN_SYSCTL_WRITE(physinfo_00000008, scrub_pages); POST_XEN_SYSCTL_WRITE(physinfo_00000008, hw_cap[8]); POST_XEN_SYSCTL_WRITE(physinfo_00000008, capabilities); break; case 0x0000000a: case 0x0000000b: POST_XEN_SYSCTL_WRITE(physinfo_0000000a, threads_per_core); POST_XEN_SYSCTL_WRITE(physinfo_0000000a, cores_per_socket); POST_XEN_SYSCTL_WRITE(physinfo_0000000a, nr_cpus); POST_XEN_SYSCTL_WRITE(physinfo_0000000a, max_cpu_id); POST_XEN_SYSCTL_WRITE(physinfo_0000000a, nr_nodes); POST_XEN_SYSCTL_WRITE(physinfo_0000000a, max_node_id); POST_XEN_SYSCTL_WRITE(physinfo_0000000a, cpu_khz); POST_XEN_SYSCTL_WRITE(physinfo_0000000a, total_pages); POST_XEN_SYSCTL_WRITE(physinfo_0000000a, free_pages); POST_XEN_SYSCTL_WRITE(physinfo_0000000a, scrub_pages); POST_XEN_SYSCTL_WRITE(physinfo_0000000a, outstanding_pages); POST_XEN_SYSCTL_WRITE(physinfo_0000000a, hw_cap[8]); POST_XEN_SYSCTL_WRITE(physinfo_0000000a, capabilities); break; } break; case VKI_XEN_SYSCTL_topologyinfo: POST_XEN_SYSCTL_WRITE(topologyinfo, max_cpu_index); if (sysctl->u.topologyinfo.cpu_to_core.p) POST_MEM_WRITE((Addr)sysctl->u.topologyinfo.cpu_to_core.p, sizeof(uint32_t) * sysctl->u.topologyinfo.max_cpu_index); if (sysctl->u.topologyinfo.cpu_to_socket.p) POST_MEM_WRITE((Addr)sysctl->u.topologyinfo.cpu_to_socket.p, sizeof(uint32_t) * sysctl->u.topologyinfo.max_cpu_index); if (sysctl->u.topologyinfo.cpu_to_node.p) POST_MEM_WRITE((Addr)sysctl->u.topologyinfo.cpu_to_node.p, sizeof(uint32_t) * sysctl->u.topologyinfo.max_cpu_index); break; case VKI_XEN_SYSCTL_numainfo: POST_XEN_SYSCTL_WRITE(numainfo, max_node_index); POST_MEM_WRITE((Addr)sysctl->u.numainfo.node_to_memsize.p, sizeof(uint64_t) * sysctl->u.numainfo.max_node_index); POST_MEM_WRITE((Addr)sysctl->u.numainfo.node_to_memfree.p, sizeof(uint64_t) * sysctl->u.numainfo.max_node_index); POST_MEM_WRITE((Addr)sysctl->u.numainfo.node_to_node_distance.p, sizeof(uint32_t) * sysctl->u.numainfo.max_node_index); break; /* No outputs */ case VKI_XEN_SYSCTL_debug_keys: break; } #undef POST_XEN_SYSCTL_WRITE #undef __POST_XEN_SYSCTL_WRITE } POST(domctl){ struct vki_xen_domctl *domctl = (struct vki_xen_domctl *)ARG1; switch (domctl->interface_version) { case 0x00000007: case 0x00000008: case 0x00000009: case 0x0000000a: case 0x0000000b: break; default: 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 VKI_XEN_DOMCTL_createdomain: case VKI_XEN_DOMCTL_destroydomain: case VKI_XEN_DOMCTL_pausedomain: case VKI_XEN_DOMCTL_max_mem: case VKI_XEN_DOMCTL_setvcpuextstate: case VKI_XEN_DOMCTL_set_address_size: case VKI_XEN_DOMCTL_test_assign_device: case VKI_XEN_DOMCTL_assign_device: case VKI_XEN_DOMCTL_deassign_device: case VKI_XEN_DOMCTL_settscinfo: case VKI_XEN_DOMCTL_irq_permission: case VKI_XEN_DOMCTL_iomem_permission: case VKI_XEN_DOMCTL_ioport_permission: case VKI_XEN_DOMCTL_hypercall_init: case VKI_XEN_DOMCTL_setvcpucontext: case VKI_XEN_DOMCTL_pin_mem_cacheattr: case VKI_XEN_DOMCTL_set_ext_vcpucontext: case VKI_XEN_DOMCTL_setnodeaffinity: case VKI_XEN_DOMCTL_set_cpuid: case VKI_XEN_DOMCTL_unpausedomain: case VKI_XEN_DOMCTL_sethvmcontext: case VKI_XEN_DOMCTL_debug_op: case VKI_XEN_DOMCTL_set_max_evtchn: case VKI_XEN_DOMCTL_cacheflush: case VKI_XEN_DOMCTL_resumedomain: case VKI_XEN_DOMCTL_set_vcpu_msrs: case VKI_XEN_DOMCTL_set_access_required: /* No output fields */ break; case VKI_XEN_DOMCTL_max_vcpus: POST_XEN_DOMCTL_WRITE(max_vcpus, max); break; case VKI_XEN_DOMCTL_get_address_size: __POST_XEN_DOMCTL_WRITE(get_address_size, address_size, size); break; case VKI_XEN_DOMCTL_gettscinfo: switch (domctl->interface_version) { case 0x00000007: /* pre-4.6 */ case 0x00000008: case 0x00000009: case 0x0000000a: __POST_XEN_DOMCTL_WRITE(gettscinfo, tsc_info_00000007, out_info); POST_MEM_WRITE((Addr)domctl->u.tsc_info_00000007.out_info.p, sizeof(vki_xen_guest_tsc_info_t)); break; case 0x0000000b: __POST_XEN_DOMCTL_WRITE(gettscinfo, tsc_info_0000000b, tsc_mode); __POST_XEN_DOMCTL_WRITE(gettscinfo, tsc_info_0000000b, gtsc_khz); __POST_XEN_DOMCTL_WRITE(gettscinfo, tsc_info_0000000b, incarnation); __POST_XEN_DOMCTL_WRITE(gettscinfo, tsc_info_0000000b, elapsed_nsec); break; } break; break; case VKI_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 VKI_XEN_DOMCTL_gethvmcontext: /* Xen unconditionally writes size... */ __POST_XEN_DOMCTL_WRITE(gethvmcontext, hvmcontext, size); /* ...but only writes to the buffer if it was non NULL */ if ( domctl->u.hvmcontext.buffer.p ) POST_MEM_WRITE((Addr)domctl->u.hvmcontext.buffer.p, sizeof(*domctl->u.hvmcontext.buffer.p) * domctl->u.hvmcontext.size); break; case VKI_XEN_DOMCTL_gethvmcontext_partial: switch (domctl->u.hvmcontext_partial.type) { case VKI_HVM_SAVE_CODE(CPU): if ( domctl->u.hvmcontext_partial.buffer.p ) POST_MEM_WRITE((Addr)domctl->u.hvmcontext_partial.buffer.p, VKI_HVM_SAVE_LENGTH(CPU)); break; } break; case VKI_XEN_DOMCTL_scheduler_op: if ( domctl->u.scheduler_op.cmd == VKI_XEN_DOMCTL_SCHEDOP_getinfo ) { switch(domctl->u.scheduler_op.sched_id) { case VKI_XEN_SCHEDULER_SEDF: POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.period); POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.slice); POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.latency); POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.extratime); POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.weight); break; case VKI_XEN_SCHEDULER_CREDIT: POST_XEN_DOMCTL_WRITE(scheduler_op, u.credit.weight); POST_XEN_DOMCTL_WRITE(scheduler_op, u.credit.cap); break; case VKI_XEN_SCHEDULER_CREDIT2: POST_XEN_DOMCTL_WRITE(scheduler_op, u.credit2.weight); break; case VKI_XEN_SCHEDULER_ARINC653: break; case VKI_XEN_SCHEDULER_RTDS: POST_XEN_DOMCTL_WRITE(scheduler_op, u.rtds.period); POST_XEN_DOMCTL_WRITE(scheduler_op, u.rtds.budget); break; } } break; case VKI_XEN_DOMCTL_getvcpuaffinity: case VKI_XEN_DOMCTL_setvcpuaffinity: /* Writes back actual result */ switch (domctl->interface_version) { case 0x00000007: case 0x00000008: case 0x00000009: POST_MEM_WRITE((Addr)domctl->u.vcpuaffinity_00000009.cpumap.bitmap.p, domctl->u.vcpuaffinity_00000009.cpumap.nr_bits / 8); break; case 0x0000000a: if (domctl->u.vcpuaffinity_0000000a.flags & VKI_XEN_VCPUAFFINITY_HARD) POST_MEM_WRITE( (Addr)domctl->u.vcpuaffinity_0000000a.cpumap_hard.bitmap.p, domctl->u.vcpuaffinity_0000000a.cpumap_hard.nr_bits / 8); if (domctl->u.vcpuaffinity_0000000a.flags & VKI_XEN_VCPUAFFINITY_SOFT) POST_MEM_WRITE( (Addr)domctl->u.vcpuaffinity_0000000a.cpumap_soft.bitmap.p, domctl->u.vcpuaffinity_0000000a.cpumap_soft.nr_bits / 8); } break; case VKI_XEN_DOMCTL_getnodeaffinity: POST_MEM_WRITE((Addr)domctl->u.nodeaffinity.nodemap.bitmap.p, domctl->u.nodeaffinity.nodemap.nr_bits / 8); break; case VKI_XEN_DOMCTL_getdomaininfo: switch (domctl->interface_version) { case 0x00000007: POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, domain); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, flags); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, tot_pages); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, max_pages); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, shr_pages); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, shared_info_frame); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, cpu_time); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, nr_online_vcpus); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, max_vcpu_id); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, ssidref); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, handle); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, cpupool); break; case 0x00000008: POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, domain); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, flags); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, tot_pages); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, max_pages); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, shr_pages); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, paged_pages); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, shared_info_frame); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, cpu_time); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, nr_online_vcpus); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, max_vcpu_id); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, ssidref); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, handle); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, cpupool); break; case 0x00000009: case 0x0000000a: POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, domain); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, flags); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, tot_pages); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, max_pages); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, outstanding_pages); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, shr_pages); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, paged_pages); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, shared_info_frame); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, cpu_time); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, nr_online_vcpus); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, max_vcpu_id); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, ssidref); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, handle); POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, cpupool); break; } break; case VKI_XEN_DOMCTL_getvcpucontext: __POST_XEN_DOMCTL_WRITE(getvcpucontext, vcpucontext, ctxt.p); break; case VKI_XEN_DOMCTL_getpageframeinfo3: POST_MEM_WRITE((Addr)domctl->u.getpageframeinfo3.array.p, domctl->u.getpageframeinfo3.num * sizeof(vki_xen_pfn_t)); break; case VKI_XEN_DOMCTL_get_ext_vcpucontext: switch (domctl->interface_version) { case 0x00000007: case 0x00000008: __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008, size); #if defined(__i386__) || defined(__x86_64__) __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008, syscall32_callback_eip); __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008, sysenter_callback_eip); __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008, syscall32_callback_cs); __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008, sysenter_callback_cs); __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008, syscall32_disables_events); __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008, sysenter_disables_events); __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008, mcg_cap); #endif break; case 0x00000009: __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009, size); #if defined(__i386__) || defined(__x86_64__) __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009, syscall32_callback_eip); __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009, sysenter_callback_eip); __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009, syscall32_callback_cs); __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009, sysenter_callback_cs); __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009, syscall32_disables_events); __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009, sysenter_disables_events); __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009, caps); __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009, mci_ctl2_bank0); __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009, mci_ctl2_bank1); #endif break; } break; case VKI_XEN_DOMCTL_getvcpuextstate: if (domctl->u.vcpuextstate.buffer.p) POST_MEM_WRITE((Addr)domctl->u.vcpuextstate.buffer.p, domctl->u.vcpuextstate.size); break; case VKI_XEN_DOMCTL_shadow_op: switch(domctl->u.shadow_op.op) { case VKI_XEN_DOMCTL_SHADOW_OP_OFF: case VKI_XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION: /* No outputs */ break; case VKI_XEN_DOMCTL_SHADOW_OP_CLEAN: case VKI_XEN_DOMCTL_SHADOW_OP_PEEK: POST_XEN_DOMCTL_WRITE(shadow_op, pages); POST_XEN_DOMCTL_WRITE(shadow_op, stats.fault_count); POST_XEN_DOMCTL_WRITE(shadow_op, stats.dirty_count); if(domctl->u.shadow_op.dirty_bitmap.p) POST_MEM_WRITE((Addr)domctl->u.shadow_op.dirty_bitmap.p, domctl->u.shadow_op.pages * sizeof(vki_uint8_t)); break; case VKI_XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION: POST_XEN_DOMCTL_WRITE(shadow_op, mb); break; default: break; } break; case VKI_XEN_DOMCTL_get_vcpu_msrs: if (domctl->u.vcpu_msrs.msrs.p) POST_MEM_WRITE((Addr)domctl->u.vcpu_msrs.msrs.p, sizeof(vki_xen_domctl_vcpu_msr_t) * domctl->u.vcpu_msrs.msr_count); break; case VKI_XEN_DOMCTL_mem_event_op: //case VKI_XEN_DOMCTL_vm_event_op: /* name change in 4.6 */ switch (domctl->interface_version) { case 0x00000007: /* pre-4.6 */ case 0x00000008: case 0x00000009: case 0x0000000a: __POST_XEN_DOMCTL_WRITE(mem_event_op, mem_event_op_00000007, port); break; case 0x0000000b: __POST_XEN_DOMCTL_WRITE(vm_event_op, vm_event_op_0000000b, port); break; } break; case VKI_XEN_DOMCTL_monitor_op: switch (domctl->interface_version) { case 0x000000b: if (domctl->u.monitor_op_0000000b.op == VKI_XEN_DOMCTL_MONITOR_OP_GET_CAPABILITIES) { switch(domctl->u.monitor_op_0000000b.event) { case VKI_XEN_DOMCTL_MONITOR_EVENT_WRITE_CTRLREG: __POST_XEN_DOMCTL_WRITE(monitor_op, monitor_op_0000000b, u.mov_to_cr); break; case VKI_XEN_DOMCTL_MONITOR_EVENT_MOV_TO_MSR: __POST_XEN_DOMCTL_WRITE(monitor_op, monitor_op_0000000b, u.mov_to_msr); break; case VKI_XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST: __POST_XEN_DOMCTL_WRITE(monitor_op, monitor_op_0000000b, u.guest_request); break; } } break; } break; } #undef POST_XEN_DOMCTL_WRITE #undef __POST_XEN_DOMCTL_WRITE } POST(hvm_op) { unsigned long op = ARG1; void *arg = (void *)(unsigned long)ARG2; #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) \ __POST_XEN_HVMOP_WRITE(_hvm_op, vki_xen_hvm_ ## _hvm_op ## _t, _field) switch (op) { case VKI_XEN_HVMOP_set_param: case VKI_XEN_HVMOP_set_pci_intx_level: case VKI_XEN_HVMOP_set_isa_irq_level: case VKI_XEN_HVMOP_set_pci_link_route: case VKI_XEN_HVMOP_set_mem_type: case VKI_XEN_HVMOP_set_mem_access: case VKI_XEN_HVMOP_inject_trap: /* No output parameters */ break; case VKI_XEN_HVMOP_get_param: __POST_XEN_HVMOP_WRITE(get_param, struct vki_xen_hvm_param, value); break; case VKI_XEN_HVMOP_get_mem_access: POST_XEN_HVMOP_WRITE(get_mem_access, hvmmem_access); break; } #undef __POST_XEN_HVMOP_WRITE #undef POST_XEN_HVMOP_WRITE } POST(tmem_op) { struct vki_xen_tmem_op *tmem = (struct vki_xen_tmem_op *)ARG1; switch(tmem->cmd) { case VKI_XEN_TMEM_control: switch(tmem->u.ctrl.subop) { /* No outputs */ case VKI_XEN_TMEMC_save_begin: break; } break; } } typedef struct { SyscallTableEntry entry; int nr_args; } XenHypercallTableEntry; #define HYPX_(const, name, nr_args) \ [const] = { { vgSysWrap_xen_##name##_before, NULL }, nr_args } #define HYPXY(const, name, nr_args) \ [const] = { { vgSysWrap_xen_##name##_before, \ vgSysWrap_xen_##name##_after }, \ nr_args } static XenHypercallTableEntry hypercall_table[] = { // __VKI_XEN_set_trap_table // 0 // __VKI_XEN_mmu_update // 1 // __VKI_XEN_set_gdt // 2 // __VKI_XEN_stack_switch // 3 // __VKI_XEN_set_callbacks // 4 // __VKI_XEN_fpu_taskswitch // 5 // __VKI_XEN_sched_op_compat // 6 // __VKI_XEN_platform_op // 7 // __VKI_XEN_set_debugreg // 8 // __VKI_XEN_get_debugreg // 9 // __VKI_XEN_update_descriptor // 10 // // 11 HYPXY(__VKI_XEN_memory_op, memory_op, 2), // 12 // __VKI_XEN_multicall // 13 // __VKI_XEN_update_va_mapping // 14 // __VKI_XEN_set_timer_op // 15 HYPXY(__VKI_XEN_event_channel_op_compat, evtchn_op_compat, 1), // 16 HYPXY(__VKI_XEN_xen_version, xen_version, 2), // 17 // __VKI_XEN_console_io // 18 // __VKI_XEN_physdev_op_compat // 19 HYPXY(__VKI_XEN_grant_table_op, grant_table_op, 3), // 20 // __VKI_XEN_vm_assist // 21 // __VKI_XEN_update_va_mapping_otherdomain // 22 // __VKI_XEN_iret, iret // 23 // __VKI_XEN_vcpu_op, vcpu_op // 24 // __VKI_XEN_set_segment_base // 25 HYPXY(__VKI_XEN_mmuext_op, mmuext_op, 2), // 26 HYPXY(__VKI_XEN_xsm_op, xsm_op, 1), // 27 // __VKI_XEN_nmi_op // 28 HYPXY(__VKI_XEN_sched_op, sched_op, 2), // 29 // __VKI_XEN_callback_op // 30 // __VKI_XEN_xenoprof_op // 31 HYPXY(__VKI_XEN_event_channel_op, evtchn_op, 2), // 32 HYPXY(__VKI_XEN_physdev_op, physdev_op, 2), // 33 HYPXY(__VKI_XEN_hvm_op, hvm_op, 2), // 34 HYPXY(__VKI_XEN_sysctl, sysctl, 1), // 35 HYPXY(__VKI_XEN_domctl, domctl, 1), // 36 // __VKI_XEN_kexec_op // 37 HYPXY(__VKI_XEN_tmem_op, tmem_op, 1), // 38 }; static void bad_before ( ThreadId tid, SyscallArgLayout* layout, /*MOD*/SyscallArgs* args, /*OUT*/SyscallStatus* status, /*OUT*/UWord* flags ) { VG_(dmsg)("WARNING: unhandled hypercall: %s\n", VG_SYSNUM_STRING(args->sysno)); if (VG_(clo_verbosity) > 1) { VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size)); } VG_(dmsg)("You may be able to write your own handler.\n"); VG_(dmsg)("Read the file README_MISSING_SYSCALL_OR_IOCTL.\n"); VG_(dmsg)("Nevertheless we consider this a bug. Please report\n"); VG_(dmsg)("it at http://valgrind.org/support/bug_reports.html &\n"); VG_(dmsg)("http://wiki.xen.org/wiki/Reporting_Bugs_against_Xen.\n"); SET_STATUS_Failure(VKI_ENOSYS); } static XenHypercallTableEntry bad_hyper = { { bad_before, NULL }, 0 }; static XenHypercallTableEntry* ML_(get_xen_hypercall_entry) ( UInt sysno ) { XenHypercallTableEntry *ret = &bad_hyper; const UInt hypercall_table_size = sizeof(hypercall_table) / sizeof(hypercall_table[0]); /* Is it in the contiguous initial section of the table? */ if (sysno < hypercall_table_size) { XenHypercallTableEntry* ent = &hypercall_table[sysno]; if (ent->entry.before != NULL) ret = ent; } /* Can't find a wrapper */ return ret; } DEFN_PRE_TEMPLATE(xen, hypercall) { XenHypercallTableEntry *ent = ML_(get_xen_hypercall_entry)(SYSNO); /* Return number of arguments consumed */ ARG8 = ent->nr_args; vg_assert(ent); vg_assert(ent->entry.before); (ent->entry.before)( tid, layout, arrghs, status, flags ); } DEFN_POST_TEMPLATE(xen, hypercall) { XenHypercallTableEntry *ent = ML_(get_xen_hypercall_entry)(SYSNO); /* Return number of arguments consumed */ ARG8 = ent->nr_args; vg_assert(ent); if (ent->entry.after) (ent->entry.after)( tid, arrghs, status ); } #endif // defined(ENABLE_XEN)