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