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