syswrap-xen.c revision 0ab84fe82d1e25c2e0544d08826df42caa44ded1
1 2/*--------------------------------------------------------------------*/ 3/*--- Xen Hypercalls syswrap-xen.c ---*/ 4/*--------------------------------------------------------------------*/ 5 6/* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2012 Citrix Systems 11 ian.campbell@citrix.com 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26 02111-1307, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29*/ 30 31#include "pub_core_basics.h" 32#include "pub_core_vki.h" 33#include "pub_core_vkiscnums.h" 34#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy 35#include "pub_core_threadstate.h" 36#include "pub_core_aspacemgr.h" 37#include "pub_core_debuginfo.h" // VG_(di_notify_*) 38#include "pub_core_transtab.h" // VG_(discard_translations) 39#include "pub_core_xarray.h" 40#include "pub_core_clientstate.h" 41#include "pub_core_debuglog.h" 42#include "pub_core_libcbase.h" 43#include "pub_core_libcassert.h" 44#include "pub_core_libcfile.h" 45#include "pub_core_libcprint.h" 46#include "pub_core_libcproc.h" 47#include "pub_core_libcsignal.h" 48#include "pub_core_mallocfree.h" 49#include "pub_core_tooliface.h" 50#include "pub_core_options.h" 51#include "pub_core_scheduler.h" 52#include "pub_core_signals.h" 53#include "pub_core_syscall.h" 54#include "pub_core_syswrap.h" 55#include "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)() 56 57#include "priv_types_n_macros.h" 58#include "priv_syswrap-generic.h" 59#include "priv_syswrap-xen.h" 60 61#include <stdint.h> 62 63#define __XEN_TOOLS__ 64 65#include <xen/xen.h> 66#include <xen/sysctl.h> 67#include <xen/domctl.h> 68#include <xen/memory.h> 69#include <xen/event_channel.h> 70#include <xen/version.h> 71 72#include <xen/hvm/hvm_op.h> 73 74#define PRE(name) static DEFN_PRE_TEMPLATE(xen, name) 75#define POST(name) static DEFN_POST_TEMPLATE(xen, name) 76 77static void bad_subop ( ThreadId tid, 78 SyscallArgLayout* layout, 79 /*MOD*/SyscallArgs* args, 80 /*OUT*/SyscallStatus* status, 81 /*OUT*/UWord* flags, 82 const char* hypercall, 83 UWord subop) 84{ 85 VG_(dmsg)("WARNING: unhandled %s subop: %ld\n", 86 hypercall, subop); 87 if (VG_(clo_verbosity) > 1) { 88 VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size)); 89 } 90 VG_(dmsg)("You may be able to write your own handler.\n"); 91 VG_(dmsg)("Read the file README_MISSING_SYSCALL_OR_IOCTL.\n"); 92 VG_(dmsg)("Nevertheless we consider this a bug. Please report\n"); 93 VG_(dmsg)("it at http://valgrind.org/support/bug_reports.html &\n"); 94 VG_(dmsg)("http://wiki.xen.org/wiki/Reporting_Bugs_against_Xen.\n"); 95 96 SET_STATUS_Failure(VKI_ENOSYS); 97} 98 99PRE(memory_op) 100{ 101 PRINT("__HYPERVISOR_memory_op ( %ld, %lx )", ARG1, ARG2); 102 103 switch (ARG1) { 104 case XENMEM_set_memory_map: { 105 xen_foreign_memory_map_t *arg = 106 (xen_foreign_memory_map_t *)(unsigned int)ARG2; 107 PRE_MEM_READ("XENMEM_set_memory_map", 108 (Addr)&arg->domid, sizeof(arg->domid)); 109 PRE_MEM_READ("XENMEM_set_memory_map", 110 (Addr)&arg->map, sizeof(arg->map)); 111 break; 112 } 113 case XENMEM_increase_reservation: 114 case XENMEM_decrease_reservation: 115 case XENMEM_populate_physmap: { 116 struct xen_memory_reservation *memory_reservation = 117 (struct xen_memory_reservation *)(unsigned int)ARG2; 118 char *which; 119 120 switch (ARG1) { 121 case XENMEM_increase_reservation: 122 which = "XENMEM_increase_reservation"; 123 break; 124 case XENMEM_decrease_reservation: 125 which = "XENMEM_decrease_reservation"; 126 PRE_MEM_READ(which, 127 (Addr)memory_reservation->extent_start.p, 128 sizeof(xen_pfn_t) * memory_reservation->nr_extents); 129 case XENMEM_populate_physmap: 130 which = "XENMEM_populate_physmap"; 131 PRE_MEM_READ(which, 132 (Addr)memory_reservation->extent_start.p, 133 sizeof(xen_pfn_t) * memory_reservation->nr_extents); 134 break; 135 default: 136 which = "XENMEM_unknown"; 137 break; 138 } 139 140 PRE_MEM_READ(which, 141 (Addr)&memory_reservation->extent_start, 142 sizeof(memory_reservation->extent_start)); 143 PRE_MEM_READ(which, 144 (Addr)&memory_reservation->nr_extents, 145 sizeof(memory_reservation->nr_extents)); 146 PRE_MEM_READ(which, 147 (Addr)&memory_reservation->extent_order, 148 sizeof(memory_reservation->extent_order)); 149 PRE_MEM_READ(which, 150 (Addr)&memory_reservation->mem_flags, 151 sizeof(memory_reservation->mem_flags)); 152 PRE_MEM_READ(which, 153 (Addr)&memory_reservation->domid, 154 sizeof(memory_reservation->domid)); 155 break; 156 } 157 158 default: 159 bad_subop(tid, layout, arrghs, status, flags, 160 "__HYPERVISOR_memory_op", ARG1); 161 break; 162 } 163} 164 165PRE(mmuext_op) 166{ 167 mmuext_op_t *ops = (void *)(unsigned int)ARG1; 168 unsigned int i, nr = ARG2; 169 170 171 for (i=0; i<nr; i++) { 172 mmuext_op_t *op = ops + i; 173 PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP", 174 (Addr)&op->cmd, sizeof(op->cmd)); 175 switch(op->cmd) { 176 case MMUEXT_PIN_L1_TABLE: 177 case MMUEXT_PIN_L2_TABLE: 178 case MMUEXT_PIN_L3_TABLE: 179 case MMUEXT_PIN_L4_TABLE: 180 case MMUEXT_UNPIN_TABLE: 181 case MMUEXT_NEW_BASEPTR: 182 case MMUEXT_CLEAR_PAGE: 183 case MMUEXT_COPY_PAGE: 184 case MMUEXT_MARK_SUPER: 185 case MMUEXT_UNMARK_SUPER: 186 PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg1.mfn", 187 (Addr)&op->arg1.mfn, 188 sizeof(op->arg1.mfn)); 189 break; 190 191 case MMUEXT_INVLPG_LOCAL: 192 case MMUEXT_INVLPG_ALL: 193 case MMUEXT_SET_LDT: 194 PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg1.mfn", 195 (Addr)&op->arg1.linear_addr, 196 sizeof(op->arg1.linear_addr)); 197 break; 198 199 case MMUEXT_TLB_FLUSH_LOCAL: 200 case MMUEXT_TLB_FLUSH_MULTI: 201 case MMUEXT_INVLPG_MULTI: 202 case MMUEXT_TLB_FLUSH_ALL: 203 case MMUEXT_FLUSH_CACHE: 204 case MMUEXT_NEW_USER_BASEPTR: 205 case MMUEXT_FLUSH_CACHE_GLOBAL: 206 /* None */ 207 break; 208 } 209 210 switch(op->cmd) { 211 case MMUEXT_SET_LDT: 212 PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.nr_ents", 213 (Addr)&op->arg2.nr_ents, 214 sizeof(op->arg2.nr_ents)); 215 break; 216 217 case MMUEXT_TLB_FLUSH_MULTI: 218 case MMUEXT_INVLPG_MULTI: 219 /* How many??? */ 220 PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.vcpumask", 221 (Addr)&op->arg2.vcpumask, 222 sizeof(op->arg2.vcpumask)); 223 break; 224 225 case MMUEXT_COPY_PAGE: 226 PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.src_mfn", 227 (Addr)&op->arg2.src_mfn, 228 sizeof(op->arg2.src_mfn)); 229 break; 230 231 case MMUEXT_PIN_L1_TABLE: 232 case MMUEXT_PIN_L2_TABLE: 233 case MMUEXT_PIN_L3_TABLE: 234 case MMUEXT_PIN_L4_TABLE: 235 case MMUEXT_UNPIN_TABLE: 236 case MMUEXT_NEW_BASEPTR: 237 case MMUEXT_TLB_FLUSH_LOCAL: 238 case MMUEXT_INVLPG_LOCAL: 239 case MMUEXT_TLB_FLUSH_ALL: 240 case MMUEXT_INVLPG_ALL: 241 case MMUEXT_FLUSH_CACHE: 242 case MMUEXT_NEW_USER_BASEPTR: 243 case MMUEXT_CLEAR_PAGE: 244 case MMUEXT_FLUSH_CACHE_GLOBAL: 245 case MMUEXT_MARK_SUPER: 246 case MMUEXT_UNMARK_SUPER: 247 /* None */ 248 break; 249 } 250 } 251} 252 253static void pre_evtchn_op(ThreadId tid, 254 SyscallArgLayout* layout, 255 /*MOD*/SyscallArgs* arrghs, 256 /*OUT*/SyscallStatus* status, 257 /*OUT*/UWord* flags, 258 __vki_u32 cmd, void *arg, int compat) 259{ 260 PRINT("__HYPERVISOR_event_channel_op%s ( %d, %p )", 261 compat ? "_compat" : "", cmd, arg); 262 263 switch (cmd) { 264 case EVTCHNOP_alloc_unbound: { 265 struct evtchn_alloc_unbound *alloc_unbound = arg; 266 PRE_MEM_READ("EVTCHNOP_alloc_unbound", 267 (Addr)&alloc_unbound->dom, sizeof(alloc_unbound->dom)); 268 PRE_MEM_READ("EVTCHNOP_alloc_unbound", 269 (Addr)&alloc_unbound->remote_dom, 270 sizeof(alloc_unbound->remote_dom)); 271 break; 272 } 273 default: 274 if ( compat ) 275 bad_subop(tid, layout, arrghs, status, flags, 276 "__HYPERVISOR_event_channel_op_compat", cmd); 277 else 278 bad_subop(tid, layout, arrghs, status, flags, 279 "__HYPERVISOR_event_channel_op", cmd); 280 break; 281 } 282} 283 284PRE(evtchn_op) 285{ 286 pre_evtchn_op(tid, layout, arrghs, status, flags, 287 ARG1, (void *)(unsigned int)ARG2, 0); 288} 289 290PRE(evtchn_op_compat) 291{ 292 struct evtchn_op *evtchn = (struct evtchn_op *)(unsigned int)ARG1; 293 PRE_MEM_READ("__HYPERVISOR_event_channel_op_compat", 294 ARG1, sizeof(*evtchn)); 295 296 pre_evtchn_op(tid, layout, arrghs, status, flags, 297 evtchn->cmd, &evtchn->u, 1); 298} 299 300PRE(xen_version) 301{ 302 PRINT("__HYPERVISOR_xen_version ( %ld, %lx )", ARG1, ARG2); 303 304 switch (ARG1) { 305 case XENVER_version: 306 case XENVER_extraversion: 307 case XENVER_compile_info: 308 case XENVER_capabilities: 309 case XENVER_changeset: 310 case XENVER_platform_parameters: 311 case XENVER_get_features: 312 case XENVER_pagesize: 313 case XENVER_guest_handle: 314 case XENVER_commandline: 315 /* No inputs */ 316 break; 317 318 default: 319 bad_subop(tid, layout, arrghs, status, flags, 320 "__HYPERVISOR_xen_version", ARG1); 321 break; 322 } 323} 324 325PRE(grant_table_op) 326{ 327 PRINT("__HYPERVISOR_grant_table_op ( %ld, 0x%lx, %ld )", ARG1, ARG2, ARG3); 328 switch (ARG1) { 329 case GNTTABOP_setup_table: { 330 struct gnttab_setup_table *gst = (void *)(intptr_t)ARG2; 331 PRE_MEM_READ("GNTTABOP_setup_table", (Addr)&gst->dom, sizeof(gst->dom)); 332 PRE_MEM_READ("GNTTABOP_setup_table", 333 (Addr)&gst->nr_frames, sizeof(gst->nr_frames)); 334 break; 335 } 336 default: 337 bad_subop(tid, layout, arrghs, status, flags, 338 "__HYPERVISOR_grant_table_op", ARG1); 339 break; 340 } 341} 342 343PRE(sysctl) { 344 struct xen_sysctl *sysctl = (struct xen_sysctl *)(unsigned int)ARG1; 345 346 PRINT("__HYPERVISOR_sysctl ( %d )", sysctl->cmd); 347 348 /* 349 * Common part of xen_sysctl: 350 * uint32_t cmd; 351 * uint32_t interface_version; 352 */ 353 PRE_MEM_READ("__HYPERVISOR_sysctl", ARG1, 354 sizeof(uint32_t) + sizeof(uint32_t)); 355 356 if (!sysctl || sysctl->interface_version != XEN_SYSCTL_INTERFACE_VERSION) 357 /* BUG ? */ 358 return; 359 360#define __PRE_XEN_SYSCTL_READ(_sysctl, _union, _field) \ 361 PRE_MEM_READ("XEN_SYSCTL_" # _sysctl, \ 362 (Addr)&sysctl->u._union._field, \ 363 sizeof(sysctl->u._union._field)) 364#define PRE_XEN_SYSCTL_READ(_sysctl, _field) \ 365 __PRE_XEN_SYSCTL_READ(_sysctl, _sysctl, _field) 366 367 switch (sysctl->cmd) { 368 case XEN_SYSCTL_getdomaininfolist: 369 PRE_XEN_SYSCTL_READ(getdomaininfolist, first_domain); 370 PRE_XEN_SYSCTL_READ(getdomaininfolist, max_domains); 371 PRE_XEN_SYSCTL_READ(getdomaininfolist, buffer); 372 break; 373 374 case XEN_SYSCTL_cpupool_op: 375 PRE_XEN_SYSCTL_READ(cpupool_op, op); 376 377 switch(sysctl->u.cpupool_op.op) { 378 case XEN_SYSCTL_CPUPOOL_OP_CREATE: 379 case XEN_SYSCTL_CPUPOOL_OP_DESTROY: 380 case XEN_SYSCTL_CPUPOOL_OP_INFO: 381 case XEN_SYSCTL_CPUPOOL_OP_ADDCPU: 382 case XEN_SYSCTL_CPUPOOL_OP_RMCPU: 383 case XEN_SYSCTL_CPUPOOL_OP_MOVEDOMAIN: 384 PRE_XEN_SYSCTL_READ(cpupool_op, cpupool_id); 385 } 386 387 if (sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_CREATE) 388 PRE_XEN_SYSCTL_READ(cpupool_op, sched_id); 389 390 if (sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_MOVEDOMAIN) 391 PRE_XEN_SYSCTL_READ(cpupool_op, domid); 392 393 if (sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_ADDCPU || 394 sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_RMCPU) 395 PRE_XEN_SYSCTL_READ(cpupool_op, cpu); 396 397 break; 398 399 case XEN_SYSCTL_physinfo: 400 /* No input params */ 401 break; 402 403 case XEN_SYSCTL_topologyinfo: 404 PRE_XEN_SYSCTL_READ(topologyinfo, max_cpu_index); 405 PRE_XEN_SYSCTL_READ(topologyinfo, cpu_to_core); 406 PRE_XEN_SYSCTL_READ(topologyinfo, cpu_to_socket); 407 PRE_XEN_SYSCTL_READ(topologyinfo, cpu_to_node); 408 break; 409 410 case XEN_SYSCTL_numainfo: 411 PRE_XEN_SYSCTL_READ(numainfo, max_node_index); 412 PRE_XEN_SYSCTL_READ(numainfo, node_to_memsize); 413 PRE_XEN_SYSCTL_READ(numainfo, node_to_memfree); 414 PRE_XEN_SYSCTL_READ(numainfo, node_to_node_distance); 415 break; 416 417 default: 418 bad_subop(tid, layout, arrghs, status, flags, 419 "__HYPERVISOR_sysctl", sysctl->cmd); 420 break; 421 } 422#undef PRE_XEN_SYSCTL_READ 423#undef __PRE_XEN_SYSCTL_READ 424} 425 426PRE(domctl) 427{ 428 struct xen_domctl *domctl = (struct xen_domctl *)(unsigned int)ARG1; 429 430 PRINT("__HYPERVISOR_domctl ( %d ) on dom%d", domctl->cmd, domctl->domain); 431 432 /* 433 * Common part of xen_domctl: 434 * uint32_t cmd; 435 * uint32_t interface_version; 436 * domid_t domain; 437 */ 438 PRE_MEM_READ("__HYPERVISOR_domctl", ARG1, 439 sizeof(uint32_t) + sizeof(uint32_t) + sizeof(domid_t)); 440 441 if (!domctl || domctl->interface_version != XEN_DOMCTL_INTERFACE_VERSION) 442 /* BUG ? */ 443 return; 444 445#define __PRE_XEN_DOMCTL_READ(_domctl, _union, _field) \ 446 PRE_MEM_READ("XEN_DOMCTL_" # _domctl, \ 447 (Addr)&domctl->u._union._field, \ 448 sizeof(domctl->u._union._field)) 449#define PRE_XEN_DOMCTL_READ(_domctl, _field) \ 450 __PRE_XEN_DOMCTL_READ(_domctl, _domctl, _field) 451 452 switch (domctl->cmd) { 453 case XEN_DOMCTL_destroydomain: 454 case XEN_DOMCTL_pausedomain: 455 case XEN_DOMCTL_max_vcpus: 456 case XEN_DOMCTL_get_address_size: 457 case XEN_DOMCTL_gettscinfo: 458 case XEN_DOMCTL_getdomaininfo: 459 case XEN_DOMCTL_unpausedomain: 460 /* No input fields. */ 461 break; 462 463 case XEN_DOMCTL_createdomain: 464 PRE_XEN_DOMCTL_READ(createdomain, ssidref); 465 PRE_XEN_DOMCTL_READ(createdomain, handle); 466 PRE_XEN_DOMCTL_READ(createdomain, flags); 467 break; 468 469 case XEN_DOMCTL_max_mem: 470 PRE_XEN_DOMCTL_READ(max_mem, max_memkb); 471 break; 472 473 case XEN_DOMCTL_set_address_size: 474 __PRE_XEN_DOMCTL_READ(set_address_size, address_size, size); 475 break; 476 477 case XEN_DOMCTL_settscinfo: 478 __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info, info.tsc_mode); 479 __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info, info.gtsc_khz); 480 __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info, info.incarnation); 481 __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info, info.elapsed_nsec); 482 break; 483 484 case XEN_DOMCTL_hypercall_init: 485 PRE_XEN_DOMCTL_READ(hypercall_init, gmfn); 486 break; 487 488 case XEN_DOMCTL_getvcpuinfo: 489 PRE_XEN_DOMCTL_READ(getvcpuinfo, vcpu); 490 break; 491 492 case XEN_DOMCTL_scheduler_op: 493 PRE_XEN_DOMCTL_READ(scheduler_op, sched_id); 494 PRE_XEN_DOMCTL_READ(scheduler_op, cmd); 495 if ( domctl->u.scheduler_op.cmd == XEN_DOMCTL_SCHEDOP_putinfo ) { 496 switch(domctl->u.scheduler_op.sched_id) { 497 case XEN_SCHEDULER_SEDF: 498 PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.period); 499 PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.slice); 500 PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.latency); 501 PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.extratime); 502 PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.weight); 503 break; 504 case XEN_SCHEDULER_CREDIT: 505 PRE_XEN_DOMCTL_READ(scheduler_op, u.credit.weight); 506 PRE_XEN_DOMCTL_READ(scheduler_op, u.credit.cap); 507 break; 508 case XEN_SCHEDULER_CREDIT2: 509 PRE_XEN_DOMCTL_READ(scheduler_op, u.credit2.weight); 510 break; 511 case XEN_SCHEDULER_ARINC653: 512 break; 513 } 514 } 515 break; 516 517 case XEN_DOMCTL_getvcpuaffinity: 518 __PRE_XEN_DOMCTL_READ(getvcpuaffinity, vcpuaffinity, vcpu); 519 break; 520 521 case XEN_DOMCTL_setvcpuaffinity: 522 __PRE_XEN_DOMCTL_READ(setvcpuaffinity, vcpuaffinity, vcpu); 523 PRE_MEM_READ("XEN_DOMCTL_setvcpuaffinity", 524 (Addr)domctl->u.vcpuaffinity.cpumap.bitmap.p, 525 domctl->u.vcpuaffinity.cpumap.nr_cpus / 8); 526 break; 527 528 case XEN_DOMCTL_getvcpucontext: 529 __PRE_XEN_DOMCTL_READ(getvcpucontext, vcpucontext, vcpu); 530 break; 531 532 case XEN_DOMCTL_setvcpucontext: 533 __PRE_XEN_DOMCTL_READ(setvcpucontext, vcpucontext, vcpu); 534 __PRE_XEN_DOMCTL_READ(setvcpucontext, vcpucontext, ctxt.p); 535 break; 536 537 case XEN_DOMCTL_set_cpuid: 538 PRE_MEM_READ("XEN_DOMCTL_set_cpuid", 539 (Addr)&domctl->u.cpuid, sizeof(domctl->u.cpuid)); 540 break; 541 542 case XEN_DOMCTL_getvcpuextstate: 543 __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, vcpu); 544 __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, xfeature_mask); 545 __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, size); 546 __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, buffer); 547 break; 548 549 default: 550 bad_subop(tid, layout, arrghs, status, flags, 551 "__HYPERVISOR_domctl", domctl->cmd); 552 break; 553 } 554#undef PRE_XEN_DOMCTL_READ 555#undef __PRE_XEN_DOMCTL_READ 556} 557 558PRE(hvm_op) 559{ 560 unsigned long op = ARG1; 561 void *arg = (void *)(unsigned long)ARG2; 562 563 PRINT("__HYPERVISOR_hvm_op ( %ld, %p )", op, arg); 564 565#define __PRE_XEN_HVMOP_READ(_hvm_op, _type, _field) \ 566 PRE_MEM_READ("XEN_HVMOP_" # _hvm_op, \ 567 (Addr)&((_type*)arg)->_field, \ 568 sizeof(((_type*)arg)->_field)) 569#define PRE_XEN_HVMOP_READ(_hvm_op, _field) \ 570 __PRE_XEN_HVMOP_READ(_hvm_op, "xen_hvm_" # _hvm_op "_t", _field) 571 572 switch (op) { 573 case HVMOP_set_param: 574 __PRE_XEN_HVMOP_READ(set_param, xen_hvm_param_t, domid); 575 __PRE_XEN_HVMOP_READ(set_param, xen_hvm_param_t, index); 576 __PRE_XEN_HVMOP_READ(set_param, xen_hvm_param_t, value); 577 break; 578 579 case HVMOP_get_param: 580 __PRE_XEN_HVMOP_READ(get_param, xen_hvm_param_t, domid); 581 __PRE_XEN_HVMOP_READ(get_param, xen_hvm_param_t, index); 582 break; 583 584 default: 585 bad_subop(tid, layout, arrghs, status, flags, 586 "__HYPERVISOR_hvm_op", op); 587 break; 588 } 589#undef __PRE_XEN_HVMOP_READ 590#undef PRE_XEN_HVMOP_READ 591} 592 593POST(memory_op) 594{ 595 switch (ARG1) { 596 case XENMEM_set_memory_map: 597 case XENMEM_decrease_reservation: 598 /* No outputs */ 599 break; 600 case XENMEM_increase_reservation: 601 case XENMEM_populate_physmap: { 602 struct xen_memory_reservation *memory_reservation = 603 (struct xen_memory_reservation *)(unsigned int)ARG2; 604 605 POST_MEM_WRITE((Addr)memory_reservation->extent_start.p, 606 sizeof(xen_pfn_t) * memory_reservation->nr_extents); 607 break; 608 } 609 } 610} 611 612POST(mmuext_op) 613{ 614 unsigned int *pdone = (void *)(unsigned int)ARG3; 615 /* simplistic */ 616 POST_MEM_WRITE((Addr)pdone, sizeof(*pdone)); 617} 618 619static void post_evtchn_op(ThreadId tid, __vki_u32 cmd, void *arg, int compat) 620{ 621 switch (cmd) { 622 case EVTCHNOP_alloc_unbound: { 623 struct evtchn_alloc_unbound *alloc_unbound = arg; 624 POST_MEM_WRITE((Addr)&alloc_unbound->port, sizeof(alloc_unbound->port)); 625 break; 626 } 627 } 628} 629 630POST(evtchn_op) 631{ 632 post_evtchn_op(tid, ARG1, (void *)(unsigned int)ARG2, 0); 633} 634 635POST(evtchn_op_compat) 636{ 637 struct evtchn_op *evtchn = (struct evtchn_op *)(unsigned int)ARG1; 638 post_evtchn_op(tid, evtchn->cmd, &evtchn->u, 1); 639} 640 641POST(xen_version) 642{ 643 switch (ARG1) { 644 case XENVER_version: 645 /* No outputs */ 646 break; 647 case XENVER_extraversion: 648 POST_MEM_WRITE((Addr)ARG2, sizeof(xen_extraversion_t)); 649 break; 650 case XENVER_compile_info: 651 POST_MEM_WRITE((Addr)ARG2, sizeof(xen_compile_info_t)); 652 break; 653 case XENVER_capabilities: 654 POST_MEM_WRITE((Addr)ARG2, sizeof(xen_capabilities_info_t)); 655 break; 656 case XENVER_changeset: 657 POST_MEM_WRITE((Addr)ARG2, sizeof(xen_changeset_info_t)); 658 break; 659 case XENVER_platform_parameters: 660 POST_MEM_WRITE((Addr)ARG2, sizeof(xen_platform_parameters_t)); 661 break; 662 case XENVER_get_features: 663 POST_MEM_WRITE((Addr)ARG2, sizeof(xen_feature_info_t)); 664 break; 665 case XENVER_pagesize: 666 /* No outputs */ 667 break; 668 case XENVER_guest_handle: 669 POST_MEM_WRITE((Addr)ARG2, sizeof(xen_domain_handle_t)); 670 break; 671 case XENVER_commandline: 672 POST_MEM_WRITE((Addr)ARG2, sizeof(xen_commandline_t)); 673 break; 674 } 675} 676 677POST(grant_table_op) 678{ 679 switch (ARG1) { 680 case GNTTABOP_setup_table: { 681 struct gnttab_setup_table *gst = (void *)(uintptr_t)ARG2; 682 PRE_MEM_WRITE("GNTTABOP_setup_table", 683 (Addr)&gst->status, sizeof(gst->status)); 684 PRE_MEM_WRITE("GNTTABOP_setup_table", 685 (Addr)gst->frame_list.p, 686 sizeof(*gst->frame_list.p) & gst->nr_frames); 687 break; 688 } 689 } 690} 691 692POST(sysctl) 693{ 694 struct xen_sysctl *sysctl = (struct xen_sysctl *)(unsigned int)ARG1; 695 696 if (!sysctl || sysctl->interface_version != XEN_SYSCTL_INTERFACE_VERSION) 697 return; 698 699#define __POST_XEN_SYSCTL_WRITE(_sysctl, _union, _field) \ 700 POST_MEM_WRITE((Addr)&sysctl->u._union._field, \ 701 sizeof(sysctl->u._union._field)) 702#define POST_XEN_SYSCTL_WRITE(_sysctl, _field) \ 703 __POST_XEN_SYSCTL_WRITE(_sysctl, _sysctl, _field) 704 705 switch (sysctl->cmd) { 706 case XEN_SYSCTL_getdomaininfolist: 707 POST_XEN_SYSCTL_WRITE(getdomaininfolist, num_domains); 708 POST_MEM_WRITE((Addr)sysctl->u.getdomaininfolist.buffer.p, 709 sizeof(xen_domctl_getdomaininfo_t) 710 * sysctl->u.getdomaininfolist.num_domains); 711 break; 712 713 case XEN_SYSCTL_cpupool_op: 714 if (sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_CREATE || 715 sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_INFO) 716 POST_XEN_SYSCTL_WRITE(cpupool_op, cpupool_id); 717 if (sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_INFO) { 718 POST_XEN_SYSCTL_WRITE(cpupool_op, sched_id); 719 POST_XEN_SYSCTL_WRITE(cpupool_op, n_dom); 720 } 721 if (sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_INFO || 722 sysctl->u.cpupool_op.op == XEN_SYSCTL_CPUPOOL_OP_FREEINFO) 723 POST_XEN_SYSCTL_WRITE(cpupool_op, cpumap); 724 break; 725 726 case XEN_SYSCTL_physinfo: 727 POST_XEN_SYSCTL_WRITE(physinfo, threads_per_core); 728 POST_XEN_SYSCTL_WRITE(physinfo, cores_per_socket); 729 POST_XEN_SYSCTL_WRITE(physinfo, nr_cpus); 730 POST_XEN_SYSCTL_WRITE(physinfo, max_cpu_id); 731 POST_XEN_SYSCTL_WRITE(physinfo, nr_nodes); 732 POST_XEN_SYSCTL_WRITE(physinfo, max_node_id); 733 POST_XEN_SYSCTL_WRITE(physinfo, cpu_khz); 734 POST_XEN_SYSCTL_WRITE(physinfo, total_pages); 735 POST_XEN_SYSCTL_WRITE(physinfo, free_pages); 736 POST_XEN_SYSCTL_WRITE(physinfo, scrub_pages); 737 POST_XEN_SYSCTL_WRITE(physinfo, hw_cap[8]); 738 POST_XEN_SYSCTL_WRITE(physinfo, capabilities); 739 break; 740 741 case XEN_SYSCTL_topologyinfo: 742 POST_XEN_SYSCTL_WRITE(topologyinfo, max_cpu_index); 743 POST_MEM_WRITE((Addr)sysctl->u.topologyinfo.cpu_to_core.p, 744 sizeof(uint32_t) * sysctl->u.topologyinfo.max_cpu_index); 745 POST_MEM_WRITE((Addr)sysctl->u.topologyinfo.cpu_to_socket.p, 746 sizeof(uint32_t) * sysctl->u.topologyinfo.max_cpu_index); 747 POST_MEM_WRITE((Addr)sysctl->u.topologyinfo.cpu_to_node.p, 748 sizeof(uint32_t) * sysctl->u.topologyinfo.max_cpu_index); 749 break; 750 751 case XEN_SYSCTL_numainfo: 752 POST_XEN_SYSCTL_WRITE(numainfo, max_node_index); 753 POST_MEM_WRITE((Addr)sysctl->u.numainfo.node_to_memsize.p, 754 sizeof(uint64_t) * sysctl->u.numainfo.max_node_index); 755 POST_MEM_WRITE((Addr)sysctl->u.numainfo.node_to_memfree.p, 756 sizeof(uint64_t) * sysctl->u.numainfo.max_node_index); 757 POST_MEM_WRITE((Addr)sysctl->u.numainfo.node_to_node_distance.p, 758 sizeof(uint32_t) * sysctl->u.numainfo.max_node_index); 759 } 760#undef POST_XEN_SYSCTL_WRITE 761#undef __POST_XEN_SYSCTL_WRITE 762} 763 764POST(domctl){ 765 struct xen_domctl *domctl = (struct xen_domctl *)(unsigned int)ARG1; 766 767 if (!domctl || domctl->interface_version != XEN_DOMCTL_INTERFACE_VERSION) 768 return; 769 770#define __POST_XEN_DOMCTL_WRITE(_domctl, _union, _field) \ 771 POST_MEM_WRITE((Addr)&domctl->u._union._field, \ 772 sizeof(domctl->u._union._field)); 773#define POST_XEN_DOMCTL_WRITE(_domctl, _field) \ 774 __POST_XEN_DOMCTL_WRITE(_domctl, _domctl, _field) 775 776 switch (domctl->cmd) { 777 case XEN_DOMCTL_createdomain: 778 case XEN_DOMCTL_destroydomain: 779 case XEN_DOMCTL_pausedomain: 780 case XEN_DOMCTL_max_mem: 781 case XEN_DOMCTL_set_address_size: 782 case XEN_DOMCTL_settscinfo: 783 case XEN_DOMCTL_hypercall_init: 784 case XEN_DOMCTL_setvcpuaffinity: 785 case XEN_DOMCTL_setvcpucontext: 786 case XEN_DOMCTL_set_cpuid: 787 case XEN_DOMCTL_unpausedomain: 788 /* No output fields */ 789 break; 790 791 case XEN_DOMCTL_max_vcpus: 792 POST_XEN_DOMCTL_WRITE(max_vcpus, max); 793 794 case XEN_DOMCTL_get_address_size: 795 __POST_XEN_DOMCTL_WRITE(get_address_size, address_size, size); 796 break; 797 798 case XEN_DOMCTL_gettscinfo: 799 __POST_XEN_DOMCTL_WRITE(settscinfo, tsc_info, info.tsc_mode); 800 __POST_XEN_DOMCTL_WRITE(settscinfo, tsc_info, info.gtsc_khz); 801 __POST_XEN_DOMCTL_WRITE(settscinfo, tsc_info, info.incarnation); 802 __POST_XEN_DOMCTL_WRITE(settscinfo, tsc_info, info.elapsed_nsec); 803 break; 804 805 case XEN_DOMCTL_getvcpuinfo: 806 POST_XEN_DOMCTL_WRITE(getvcpuinfo, online); 807 POST_XEN_DOMCTL_WRITE(getvcpuinfo, blocked); 808 POST_XEN_DOMCTL_WRITE(getvcpuinfo, running); 809 POST_XEN_DOMCTL_WRITE(getvcpuinfo, cpu_time); 810 POST_XEN_DOMCTL_WRITE(getvcpuinfo, cpu); 811 break; 812 813 case XEN_DOMCTL_scheduler_op: 814 if ( domctl->u.scheduler_op.cmd == XEN_DOMCTL_SCHEDOP_getinfo ) { 815 switch(domctl->u.scheduler_op.sched_id) { 816 case XEN_SCHEDULER_SEDF: 817 POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.period); 818 POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.slice); 819 POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.latency); 820 POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.extratime); 821 POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.weight); 822 break; 823 case XEN_SCHEDULER_CREDIT: 824 POST_XEN_DOMCTL_WRITE(scheduler_op, u.credit.weight); 825 POST_XEN_DOMCTL_WRITE(scheduler_op, u.credit.cap); 826 break; 827 case XEN_SCHEDULER_CREDIT2: 828 POST_XEN_DOMCTL_WRITE(scheduler_op, u.credit2.weight); 829 break; 830 case XEN_SCHEDULER_ARINC653: 831 break; 832 } 833 } 834 break; 835 836 case XEN_DOMCTL_getvcpuaffinity: 837 POST_MEM_WRITE((Addr)domctl->u.vcpuaffinity.cpumap.bitmap.p, 838 domctl->u.vcpuaffinity.cpumap.nr_cpus / 8); 839 break; 840 841 case XEN_DOMCTL_getdomaininfo: 842 POST_XEN_DOMCTL_WRITE(getdomaininfo, domain); 843 POST_XEN_DOMCTL_WRITE(getdomaininfo, flags); 844 POST_XEN_DOMCTL_WRITE(getdomaininfo, tot_pages); 845 POST_XEN_DOMCTL_WRITE(getdomaininfo, max_pages); 846 POST_XEN_DOMCTL_WRITE(getdomaininfo, shr_pages); 847 POST_XEN_DOMCTL_WRITE(getdomaininfo, shared_info_frame); 848 POST_XEN_DOMCTL_WRITE(getdomaininfo, cpu_time); 849 POST_XEN_DOMCTL_WRITE(getdomaininfo, nr_online_vcpus); 850 POST_XEN_DOMCTL_WRITE(getdomaininfo, max_vcpu_id); 851 POST_XEN_DOMCTL_WRITE(getdomaininfo, ssidref); 852 POST_XEN_DOMCTL_WRITE(getdomaininfo, handle); 853 POST_XEN_DOMCTL_WRITE(getdomaininfo, cpupool); 854 break; 855 856 case XEN_DOMCTL_getvcpucontext: 857 __POST_XEN_DOMCTL_WRITE(getvcpucontext, vcpucontext, ctxt.p); 858 break; 859 860 case XEN_DOMCTL_getvcpuextstate: 861 __POST_XEN_DOMCTL_WRITE(getvcpuextstate, vcpuextstate, xfeature_mask); 862 __POST_XEN_DOMCTL_WRITE(getvcpuextstate, vcpuextstate, size); 863 POST_MEM_WRITE((Addr)domctl->u.vcpuextstate.buffer.p, 864 domctl->u.vcpuextstate.size); 865 break; 866 867 } 868#undef POST_XEN_DOMCTL_WRITE 869#undef __POST_XEN_DOMCTL_WRITE 870} 871 872POST(hvm_op) 873{ 874 unsigned long op = ARG1; 875 void *arg = (void *)(unsigned long)ARG2; 876 877#define __POST_XEN_HVMOP_WRITE(_hvm_op, _type, _field) \ 878 POST_MEM_WRITE((Addr)&((_type*)arg)->_field, \ 879 sizeof(((_type*)arg)->_field)) 880#define POST_XEN_HVMOP_WRITE(_hvm_op, _field) \ 881 __PRE_XEN_HVMOP_READ(_hvm_op, "xen_hvm_" # _hvm_op "_t", _field) 882 883 switch (op) { 884 case HVMOP_set_param: 885 /* No output paramters */ 886 break; 887 888 case HVMOP_get_param: 889 __POST_XEN_HVMOP_WRITE(get_param, xen_hvm_param_t, value); 890 break; 891 } 892#undef __POST_XEN_HVMOP_WRITE 893#undef POST_XEN_HVMOP_WRITE 894} 895 896typedef 897 struct { 898 SyscallTableEntry entry; 899 int nr_args; 900 } 901 XenHypercallTableEntry; 902 903#define HYPX_(const, name, nr_args) \ 904 [const] = { { vgSysWrap_xen_##name##_before, NULL }, nr_args } 905#define HYPXY(const, name, nr_args) \ 906 [const] = { { vgSysWrap_xen_##name##_before, \ 907 vgSysWrap_xen_##name##_after }, \ 908 nr_args } 909 910static XenHypercallTableEntry hypercall_table[] = { 911 // __HYPERVISOR_set_trap_table // 0 912 // __HYPERVISOR_mmu_update // 1 913 // __HYPERVISOR_set_gdt // 2 914 // __HYPERVISOR_stack_switch // 3 915 // __HYPERVISOR_set_callbacks // 4 916 917 // __HYPERVISOR_fpu_taskswitch // 5 918 // __HYPERVISOR_sched_op_compat // 6 919 // __HYPERVISOR_platform_op // 7 920 // __HYPERVISOR_set_debugreg // 8 921 // __HYPERVISOR_get_debugreg // 9 922 923 // __HYPERVISOR_update_descriptor // 10 924 // // 11 925 HYPXY(__HYPERVISOR_memory_op, memory_op, 2), // 12 926 // __HYPERVISOR_multicall // 13 927 // __HYPERVISOR_update_va_mapping // 14 928 929 // __HYPERVISOR_set_timer_op // 15 930 HYPXY(__HYPERVISOR_event_channel_op_compat, evtchn_op_compat, 1), // 16 931 HYPXY(__HYPERVISOR_xen_version, xen_version, 2), // 17 932 // __HYPERVISOR_console_io // 18 933 // __HYPERVISOR_physdev_op_compat // 19 934 935 HYPXY(__HYPERVISOR_grant_table_op, grant_table_op, 3), // 20 936 // __HYPERVISOR_vm_assist // 21 937 // __HYPERVISOR_update_va_mapping_otherdomain // 22 938 // __HYPERVISOR_iret, iret // 23 939 // __HYPERVISOR_vcpu_op, vcpu_op // 24 940 941 // __HYPERVISOR_set_segment_base // 25 942 HYPXY(__HYPERVISOR_mmuext_op, mmuext_op, 2), // 26 943 // __HYPERVISOR_xsm_op // 27 944 // __HYPERVISOR_nmi_op // 28 945 // __HYPERVISOR_sched_op // 29 946 947 // __HYPERVISOR_callback_op // 30 948 // __HYPERVISOR_xenoprof_op // 31 949 HYPXY(__HYPERVISOR_event_channel_op, evtchn_op, 2), // 32 950 // __HYPERVISOR_physdev_op // 33 951 HYPXY(__HYPERVISOR_hvm_op, hvm_op, 2), // 34 952 953 HYPXY(__HYPERVISOR_sysctl, sysctl, 1), // 35 954 HYPXY(__HYPERVISOR_domctl, domctl, 1), // 36 955 // __HYPERVISOR_kexec_op // 37 956 // __HYPERVISOR_tmem_op // 38 957}; 958 959static void bad_before ( ThreadId tid, 960 SyscallArgLayout* layout, 961 /*MOD*/SyscallArgs* args, 962 /*OUT*/SyscallStatus* status, 963 /*OUT*/UWord* flags ) 964{ 965 VG_(dmsg)("WARNING: unhandled hypercall: %s\n", 966 VG_SYSNUM_STRING_EXTRA(args->sysno)); 967 if (VG_(clo_verbosity) > 1) { 968 VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size)); 969 } 970 VG_(dmsg)("You may be able to write your own handler.\n"); 971 VG_(dmsg)("Read the file README_MISSING_SYSCALL_OR_IOCTL.\n"); 972 VG_(dmsg)("Nevertheless we consider this a bug. Please report\n"); 973 VG_(dmsg)("it at http://valgrind.org/support/bug_reports.html &\n"); 974 VG_(dmsg)("http://wiki.xen.org/wiki/Reporting_Bugs_against_Xen.\n"); 975 976 SET_STATUS_Failure(VKI_ENOSYS); 977} 978 979static XenHypercallTableEntry bad_hyper = 980{ { bad_before, NULL }, 0 }; 981 982static XenHypercallTableEntry* ML_(get_xen_hypercall_entry) ( UInt sysno ) 983{ 984 XenHypercallTableEntry *ret = &bad_hyper; 985 986 const UInt hypercall_table_size 987 = sizeof(hypercall_table) / sizeof(hypercall_table[0]); 988 989 /* Is it in the contiguous initial section of the table? */ 990 if (sysno < hypercall_table_size) { 991 XenHypercallTableEntry* ent = &hypercall_table[sysno]; 992 if (ent->entry.before != NULL) 993 ret = ent; 994 } 995 996 /* Can't find a wrapper */ 997 return ret; 998} 999 1000DEFN_PRE_TEMPLATE(xen, hypercall) 1001{ 1002 XenHypercallTableEntry *ent = ML_(get_xen_hypercall_entry)(SYSNO); 1003 1004 /* Return number of arguments consumed */ 1005 ARG8 = ent->nr_args; 1006 1007 vg_assert(ent); 1008 vg_assert(ent->entry.before); 1009 (ent->entry.before)( tid, layout, arrghs, status, flags ); 1010 1011} 1012 1013DEFN_POST_TEMPLATE(xen, hypercall) 1014{ 1015 XenHypercallTableEntry *ent = ML_(get_xen_hypercall_entry)(SYSNO); 1016 1017 /* Return number of arguments consumed */ 1018 ARG8 = ent->nr_args; 1019 1020 vg_assert(ent); 1021 if (ent->entry.after) 1022 (ent->entry.after)( tid, arrghs, status ); 1023} 1024