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
34#if defined(ENABLE_XEN)
35
36#include "pub_core_vkiscnums.h"
37#include "pub_core_threadstate.h"
38#include "pub_core_aspacemgr.h"
39#include "pub_core_debuginfo.h"    // VG_(di_notify_*)
40#include "pub_core_transtab.h"     // VG_(discard_translations)
41#include "pub_core_xarray.h"
42#include "pub_core_clientstate.h"
43#include "pub_core_debuglog.h"
44#include "pub_core_libcbase.h"
45#include "pub_core_libcassert.h"
46#include "pub_core_libcfile.h"
47#include "pub_core_libcprint.h"
48#include "pub_core_libcproc.h"
49#include "pub_core_libcsignal.h"
50#include "pub_core_mallocfree.h"
51#include "pub_core_tooliface.h"
52#include "pub_core_options.h"
53#include "pub_core_scheduler.h"
54#include "pub_core_signals.h"
55#include "pub_core_syscall.h"
56#include "pub_core_syswrap.h"
57#include "pub_core_stacktrace.h"    // For VG_(get_and_pp_StackTrace)()
58
59#include "priv_types_n_macros.h"
60#include "priv_syswrap-generic.h"
61#include "priv_syswrap-xen.h"
62
63#include <inttypes.h>
64
65#define PRE(name) static DEFN_PRE_TEMPLATE(xen, name)
66#define POST(name) static DEFN_POST_TEMPLATE(xen, name)
67
68static void bad_subop ( ThreadId              tid,
69                        SyscallArgLayout*     layout,
70                        /*MOD*/SyscallArgs*   args,
71                        /*OUT*/SyscallStatus* status,
72                        /*OUT*/UWord*         flags,
73                        const HChar*           hypercall,
74                        UWord                 subop)
75{
76   VG_(dmsg)("WARNING: unhandled %s subop: %ld\n",
77             hypercall, subop);
78   if (VG_(clo_verbosity) > 1) {
79      VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
80   }
81   VG_(dmsg)("You may be able to write your own handler.\n");
82   VG_(dmsg)("Read the file README_MISSING_SYSCALL_OR_IOCTL.\n");
83   VG_(dmsg)("Nevertheless we consider this a bug.  Please report\n");
84   VG_(dmsg)("it at http://valgrind.org/support/bug_reports.html &\n");
85   VG_(dmsg)("http://wiki.xen.org/wiki/Reporting_Bugs_against_Xen.\n");
86
87   SET_STATUS_Failure(VKI_ENOSYS);
88}
89
90PRE(memory_op)
91{
92   PRINT("__HYPERVISOR_memory_op ( %ld, %lx )", ARG1, ARG2);
93
94   switch (ARG1) {
95
96   case VKI_XENMEM_maximum_ram_page:
97       /* No inputs */
98       break;
99
100   case VKI_XENMEM_maximum_gpfn:
101       PRE_MEM_READ("XENMEM_maximum_gpfn domid",
102                    (Addr)ARG2, sizeof(vki_xen_domid_t));
103       break;
104
105   case VKI_XENMEM_machphys_mfn_list: {
106       struct vki_xen_machphys_mfn_list *arg =
107           (struct vki_xen_machphys_mfn_list *)ARG2;
108       PRE_MEM_READ("XENMEM_machphys_mfn_list max_extents",
109                    (Addr)&arg->max_extents, sizeof(arg->max_extents));
110       PRE_MEM_READ("XENMEM_machphys_mfn_list extent_start",
111                    (Addr)&arg->extent_start, sizeof(arg->extent_start));
112       break;
113   }
114
115   case VKI_XENMEM_set_memory_map: {
116      struct vki_xen_foreign_memory_map *arg =
117	      (struct vki_xen_foreign_memory_map *)ARG2;
118      PRE_MEM_READ("XENMEM_set_memory_map domid",
119                   (Addr)&arg->domid, sizeof(arg->domid));
120      PRE_MEM_READ("XENMEM_set_memory_map map",
121                   (Addr)&arg->map, sizeof(arg->map));
122      break;
123   }
124   case VKI_XENMEM_increase_reservation:
125   case VKI_XENMEM_decrease_reservation:
126   case VKI_XENMEM_populate_physmap:
127   case VKI_XENMEM_claim_pages: {
128      struct xen_memory_reservation *memory_reservation =
129         (struct xen_memory_reservation *)ARG2;
130      const HChar *which;
131
132      switch (ARG1) {
133      case VKI_XENMEM_increase_reservation:
134         which = "XENMEM_increase_reservation";
135         break;
136      case VKI_XENMEM_decrease_reservation:
137         which = "XENMEM_decrease_reservation";
138         PRE_MEM_READ(which,
139                      (Addr)memory_reservation->extent_start.p,
140                      sizeof(vki_xen_pfn_t) * memory_reservation->nr_extents);
141	 break;
142      case VKI_XENMEM_populate_physmap:
143         which = "XENMEM_populate_physmap";
144         PRE_MEM_READ(which,
145                      (Addr)memory_reservation->extent_start.p,
146                      sizeof(vki_xen_pfn_t) * memory_reservation->nr_extents);
147         break;
148      case VKI_XENMEM_claim_pages:
149         which = "XENMEM_claim_pages";
150         break;
151      default:
152         which = "XENMEM_unknown";
153         break;
154      }
155
156      PRE_MEM_READ(which,
157                   (Addr)&memory_reservation->extent_start,
158                   sizeof(memory_reservation->extent_start));
159      PRE_MEM_READ(which,
160                   (Addr)&memory_reservation->nr_extents,
161                   sizeof(memory_reservation->nr_extents));
162      PRE_MEM_READ(which,
163                   (Addr)&memory_reservation->extent_order,
164                   sizeof(memory_reservation->extent_order));
165      PRE_MEM_READ(which,
166                   (Addr)&memory_reservation->mem_flags,
167                   sizeof(memory_reservation->mem_flags));
168      PRE_MEM_READ(which,
169                   (Addr)&memory_reservation->domid,
170                   sizeof(memory_reservation->domid));
171      break;
172   }
173
174   case VKI_XENMEM_add_to_physmap: {
175       struct vki_xen_add_to_physmap *arg =
176           (struct vki_xen_add_to_physmap *)ARG2;
177       PRE_MEM_READ("XENMEM_add_to_physmap domid",
178                    (Addr)&arg->domid, sizeof(arg->domid));
179       PRE_MEM_READ("XENMEM_add_to_physmap size",
180                    (Addr)&arg->size, sizeof(arg->size));
181       PRE_MEM_READ("XENMEM_add_to_physmap space",
182                    (Addr)&arg->space, sizeof(arg->space));
183       PRE_MEM_READ("XENMEM_add_to_physmap idx",
184                    (Addr)&arg->idx, sizeof(arg->idx));
185       PRE_MEM_READ("XENMEM_add_to_physmap gpfn",
186                    (Addr)&arg->gpfn, sizeof(arg->gpfn));
187       break;
188   }
189
190   case VKI_XENMEM_remove_from_physmap: {
191       struct vki_xen_remove_from_physmap *arg =
192           (struct vki_xen_remove_from_physmap *)ARG2;
193       PRE_MEM_READ("XENMEM_remove_from_physmap domid",
194                    (Addr)&arg->domid, sizeof(arg->domid));
195       PRE_MEM_READ("XENMEM_remove_from_physmap gpfn",
196                    (Addr)&arg->gpfn, sizeof(arg->gpfn));
197       break;
198   }
199
200   case VKI_XENMEM_get_sharing_freed_pages:
201   case VKI_XENMEM_get_sharing_shared_pages:
202      break;
203
204   case VKI_XENMEM_access_op: {
205       struct vki_xen_mem_event_op *arg =
206            (struct vki_xen_mem_event_op *)ARG2;
207       PRE_MEM_READ("XENMEM_access_op domid",
208                    (Addr)&arg->domain, sizeof(arg->domain));
209       PRE_MEM_READ("XENMEM_access_op op",
210                    (Addr)&arg->op, sizeof(arg->op));
211       PRE_MEM_READ("XENMEM_access_op gfn",
212                    (Addr)&arg->gfn, sizeof(arg->gfn));
213       break;
214   }
215   default:
216      bad_subop(tid, layout, arrghs, status, flags,
217                "__HYPERVISOR_memory_op", ARG1);
218      break;
219   }
220}
221
222PRE(mmuext_op)
223{
224   struct vki_xen_mmuext_op *ops = (struct vki_xen_mmuext_op *)ARG1;
225   unsigned int i, nr = ARG2;
226
227   for (i=0; i<nr; i++) {
228      struct vki_xen_mmuext_op *op = ops + i;
229      PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP cmd",
230                   (Addr)&op->cmd, sizeof(op->cmd));
231      switch(op->cmd) {
232      case VKI_XEN_MMUEXT_PIN_L1_TABLE:
233      case VKI_XEN_MMUEXT_PIN_L2_TABLE:
234      case VKI_XEN_MMUEXT_PIN_L3_TABLE:
235      case VKI_XEN_MMUEXT_PIN_L4_TABLE:
236      case VKI_XEN_MMUEXT_UNPIN_TABLE:
237      case VKI_XEN_MMUEXT_NEW_BASEPTR:
238      case VKI_XEN_MMUEXT_CLEAR_PAGE:
239      case VKI_XEN_MMUEXT_COPY_PAGE:
240      case VKI_XEN_MMUEXT_MARK_SUPER:
241      case VKI_XEN_MMUEXT_UNMARK_SUPER:
242         PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg1.mfn",
243                      (Addr)&op->arg1.mfn,
244                      sizeof(op->arg1.mfn));
245         break;
246
247      case VKI_XEN_MMUEXT_INVLPG_LOCAL:
248      case VKI_XEN_MMUEXT_INVLPG_ALL:
249      case VKI_XEN_MMUEXT_SET_LDT:
250         PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg1.mfn",
251                      (Addr)&op->arg1.linear_addr,
252                      sizeof(op->arg1.linear_addr));
253         break;
254
255      case VKI_XEN_MMUEXT_TLB_FLUSH_LOCAL:
256      case VKI_XEN_MMUEXT_TLB_FLUSH_MULTI:
257      case VKI_XEN_MMUEXT_INVLPG_MULTI:
258      case VKI_XEN_MMUEXT_TLB_FLUSH_ALL:
259      case VKI_XEN_MMUEXT_FLUSH_CACHE:
260      case VKI_XEN_MMUEXT_NEW_USER_BASEPTR:
261      case VKI_XEN_MMUEXT_FLUSH_CACHE_GLOBAL:
262         /* None */
263         break;
264      }
265
266      switch(op->cmd) {
267      case VKI_XEN_MMUEXT_SET_LDT:
268         PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.nr_ents",
269                      (Addr)&op->arg2.nr_ents,
270                      sizeof(op->arg2.nr_ents));
271         break;
272
273      case VKI_XEN_MMUEXT_TLB_FLUSH_MULTI:
274      case VKI_XEN_MMUEXT_INVLPG_MULTI:
275         /* How many??? */
276         PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.vcpumask",
277                      (Addr)&op->arg2.vcpumask,
278                      sizeof(op->arg2.vcpumask));
279         break;
280
281      case VKI_XEN_MMUEXT_COPY_PAGE:
282         PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.src_mfn",
283                      (Addr)&op->arg2.src_mfn,
284                      sizeof(op->arg2.src_mfn));
285         break;
286
287      case VKI_XEN_MMUEXT_PIN_L1_TABLE:
288      case VKI_XEN_MMUEXT_PIN_L2_TABLE:
289      case VKI_XEN_MMUEXT_PIN_L3_TABLE:
290      case VKI_XEN_MMUEXT_PIN_L4_TABLE:
291      case VKI_XEN_MMUEXT_UNPIN_TABLE:
292      case VKI_XEN_MMUEXT_NEW_BASEPTR:
293      case VKI_XEN_MMUEXT_TLB_FLUSH_LOCAL:
294      case VKI_XEN_MMUEXT_INVLPG_LOCAL:
295      case VKI_XEN_MMUEXT_TLB_FLUSH_ALL:
296      case VKI_XEN_MMUEXT_INVLPG_ALL:
297      case VKI_XEN_MMUEXT_FLUSH_CACHE:
298      case VKI_XEN_MMUEXT_NEW_USER_BASEPTR:
299      case VKI_XEN_MMUEXT_CLEAR_PAGE:
300      case VKI_XEN_MMUEXT_FLUSH_CACHE_GLOBAL:
301      case VKI_XEN_MMUEXT_MARK_SUPER:
302      case VKI_XEN_MMUEXT_UNMARK_SUPER:
303         /* None */
304         break;
305      }
306   }
307}
308
309static void pre_evtchn_op(ThreadId tid,
310                          SyscallArgLayout*     layout,
311                          /*MOD*/SyscallArgs*   arrghs,
312                          /*OUT*/SyscallStatus* status,
313                          /*OUT*/UWord*         flags,
314                          __vki_u32 cmd, void *arg, int compat)
315{
316   PRINT("__HYPERVISOR_event_channel_op%s ( %d, %p )",
317         compat ? "_compat" : "", cmd, arg);
318
319   switch (cmd) {
320   case VKI_XEN_EVTCHNOP_alloc_unbound: {
321      struct vki_xen_evtchn_alloc_unbound *alloc_unbound = arg;
322      PRE_MEM_READ("EVTCHNOP_alloc_unbound dom",
323                   (Addr)&alloc_unbound->dom, sizeof(alloc_unbound->dom));
324      PRE_MEM_READ("EVTCHNOP_alloc_unbound remote_dom",
325                   (Addr)&alloc_unbound->remote_dom,
326                   sizeof(alloc_unbound->remote_dom));
327      break;
328   }
329   default:
330      if ( compat )
331         bad_subop(tid, layout, arrghs, status, flags,
332                   "__HYPERVISOR_event_channel_op_compat", cmd);
333      else
334         bad_subop(tid, layout, arrghs, status, flags,
335                   "__HYPERVISOR_event_channel_op", cmd);
336      break;
337   }
338}
339
340PRE(evtchn_op)
341{
342   pre_evtchn_op(tid, layout, arrghs, status, flags,
343                 ARG1, (void *)ARG2, 0);
344}
345
346PRE(evtchn_op_compat)
347{
348   struct vki_xen_evtchn_op *evtchn = (struct vki_xen_evtchn_op *)ARG1;
349   PRE_MEM_READ("__HYPERVISOR_event_channel_op_compat",
350                ARG1, sizeof(*evtchn));
351
352   pre_evtchn_op(tid, layout, arrghs, status, flags,
353                 evtchn->cmd, &evtchn->u, 1);
354}
355
356PRE(xen_version)
357{
358   PRINT("__HYPERVISOR_xen_version ( %ld, %lx )", ARG1, ARG2);
359
360   switch (ARG1) {
361   case VKI_XENVER_version:
362   case VKI_XENVER_extraversion:
363   case VKI_XENVER_compile_info:
364   case VKI_XENVER_capabilities:
365   case VKI_XENVER_changeset:
366   case VKI_XENVER_platform_parameters:
367   case VKI_XENVER_get_features:
368   case VKI_XENVER_pagesize:
369   case VKI_XENVER_guest_handle:
370   case VKI_XENVER_commandline:
371      /* No inputs */
372      break;
373
374   default:
375      bad_subop(tid, layout, arrghs, status, flags,
376                "__HYPERVISOR_xen_version", ARG1);
377      break;
378   }
379}
380
381PRE(grant_table_op)
382{
383   PRINT("__HYPERVISOR_grant_table_op ( %ld, 0x%lx, %ld )", ARG1, ARG2, ARG3);
384   switch (ARG1) {
385   case VKI_XEN_GNTTABOP_setup_table: {
386      struct vki_xen_gnttab_setup_table *gst =
387	      (struct vki_xen_gnttab_setup_table*)ARG2;
388      PRE_MEM_READ("VKI_XEN_GNTTABOP_setup_table dom",
389		   (Addr)&gst->dom, sizeof(gst->dom));
390      PRE_MEM_READ("VKI_XEN_GNTTABOP_setup_table nr_frames",
391                   (Addr)&gst->nr_frames, sizeof(gst->nr_frames));
392      break;
393   }
394   default:
395      bad_subop(tid, layout, arrghs, status, flags,
396                "__HYPERVISOR_grant_table_op", ARG1);
397      break;
398   }
399}
400
401PRE(sysctl) {
402   struct vki_xen_sysctl *sysctl = (struct vki_xen_sysctl *)ARG1;
403
404   PRINT("__HYPERVISOR_sysctl ( %d )", sysctl->cmd);
405
406   /*
407    * Common part of xen_sysctl:
408    *    uint32_t cmd;
409    *    uint32_t interface_version;
410    */
411   PRE_MEM_READ("__HYPERVISOR_sysctl", ARG1,
412                sizeof(vki_uint32_t) + sizeof(vki_uint32_t));
413
414   if (!sysctl)
415      return;
416
417   switch (sysctl->interface_version)
418   {
419   case 0x00000008:
420   case 0x00000009:
421   case 0x0000000a:
422	   break;
423   default:
424      VG_(dmsg)("WARNING: sysctl version %"PRIx32" not supported\n",
425                sysctl->interface_version);
426      if (VG_(clo_verbosity) > 1) {
427         VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
428      }
429      VG_(dmsg)("You may be able to write your own handler.\n");
430      VG_(dmsg)("Read the file README_MISSING_SYSCALL_OR_IOCTL.\n");
431      VG_(dmsg)("Nevertheless we consider this a bug.  Please report\n");
432      VG_(dmsg)("it at http://valgrind.org/support/bug_reports.html &\n");
433      VG_(dmsg)("http://wiki.xen.org/wiki/Reporting_Bugs_against_Xen.\n");
434
435      SET_STATUS_Failure(VKI_EINVAL);
436      return;
437   }
438
439#define __PRE_XEN_SYSCTL_READ(_sysctl, _union, _field)			\
440      PRE_MEM_READ("XEN_SYSCTL_" #_sysctl " u." #_union "." #_field,	\
441                   (Addr)&sysctl->u._union._field,			\
442                   sizeof(sysctl->u._union._field))
443#define PRE_XEN_SYSCTL_READ(_sysctl, _field) \
444      __PRE_XEN_SYSCTL_READ(_sysctl, _sysctl, _field)
445
446   switch (sysctl->cmd) {
447   case VKI_XEN_SYSCTL_readconsole:
448       /* These are all unconditionally read */
449       PRE_XEN_SYSCTL_READ(readconsole, clear);
450       PRE_XEN_SYSCTL_READ(readconsole, incremental);
451       PRE_XEN_SYSCTL_READ(readconsole, buffer);
452       PRE_XEN_SYSCTL_READ(readconsole, count);
453
454       /* 'index' only read if 'incremental' is nonzero */
455       if (sysctl->u.readconsole.incremental)
456           PRE_XEN_SYSCTL_READ(readconsole, index);
457       break;
458
459   case VKI_XEN_SYSCTL_getdomaininfolist:
460      switch (sysctl->interface_version)
461      {
462      case 0x00000008:
463	 PRE_XEN_SYSCTL_READ(getdomaininfolist_00000008, first_domain);
464	 PRE_XEN_SYSCTL_READ(getdomaininfolist_00000008, max_domains);
465	 PRE_XEN_SYSCTL_READ(getdomaininfolist_00000008, buffer);
466	 break;
467      case 0x00000009:
468	 PRE_XEN_SYSCTL_READ(getdomaininfolist_00000009, first_domain);
469	 PRE_XEN_SYSCTL_READ(getdomaininfolist_00000009, max_domains);
470	 PRE_XEN_SYSCTL_READ(getdomaininfolist_00000009, buffer);
471	 break;
472      case 0x0000000a:
473	 PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, first_domain);
474	 PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, max_domains);
475	 PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, buffer);
476	 break;
477      default:
478          VG_(dmsg)("WARNING: XEN_SYSCTL_getdomaininfolist for sysctl version "
479                    "%"PRIx32" not implemented yet\n",
480                    sysctl->interface_version);
481          SET_STATUS_Failure(VKI_EINVAL);
482          return;
483      }
484      break;
485
486   case VKI_XEN_SYSCTL_debug_keys:
487       PRE_XEN_SYSCTL_READ(debug_keys, keys);
488       PRE_XEN_SYSCTL_READ(debug_keys, nr_keys);
489       PRE_MEM_READ("XEN_SYSCTL_debug_keys *keys",
490                    (Addr)sysctl->u.debug_keys.keys.p,
491                    sysctl->u.debug_keys.nr_keys * sizeof(char));
492       break;
493
494   case VKI_XEN_SYSCTL_sched_id:
495       /* No inputs */
496       break;
497
498   case VKI_XEN_SYSCTL_cpupool_op:
499      PRE_XEN_SYSCTL_READ(cpupool_op, op);
500
501      switch(sysctl->u.cpupool_op.op) {
502      case VKI_XEN_SYSCTL_CPUPOOL_OP_CREATE:
503      case VKI_XEN_SYSCTL_CPUPOOL_OP_DESTROY:
504      case VKI_XEN_SYSCTL_CPUPOOL_OP_INFO:
505      case VKI_XEN_SYSCTL_CPUPOOL_OP_ADDCPU:
506      case VKI_XEN_SYSCTL_CPUPOOL_OP_RMCPU:
507      case VKI_XEN_SYSCTL_CPUPOOL_OP_MOVEDOMAIN:
508         PRE_XEN_SYSCTL_READ(cpupool_op, cpupool_id);
509      }
510
511      if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_CREATE)
512         PRE_XEN_SYSCTL_READ(cpupool_op, sched_id);
513
514      if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_MOVEDOMAIN)
515         PRE_XEN_SYSCTL_READ(cpupool_op, domid);
516
517      if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_ADDCPU ||
518          sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_RMCPU)
519         PRE_XEN_SYSCTL_READ(cpupool_op, cpu);
520
521      break;
522
523   case VKI_XEN_SYSCTL_physinfo:
524      /* No input params */
525      break;
526
527   case VKI_XEN_SYSCTL_topologyinfo:
528      PRE_XEN_SYSCTL_READ(topologyinfo, max_cpu_index);
529      PRE_XEN_SYSCTL_READ(topologyinfo, cpu_to_core);
530      PRE_XEN_SYSCTL_READ(topologyinfo, cpu_to_socket);
531      PRE_XEN_SYSCTL_READ(topologyinfo, cpu_to_node);
532      break;
533
534   case VKI_XEN_SYSCTL_numainfo:
535      PRE_XEN_SYSCTL_READ(numainfo, max_node_index);
536      PRE_XEN_SYSCTL_READ(numainfo, node_to_memsize);
537      PRE_XEN_SYSCTL_READ(numainfo, node_to_memfree);
538      PRE_XEN_SYSCTL_READ(numainfo, node_to_node_distance);
539      break;
540
541   default:
542      bad_subop(tid, layout, arrghs, status, flags,
543                "__HYPERVISOR_sysctl", sysctl->cmd);
544      break;
545   }
546#undef PRE_XEN_SYSCTL_READ
547#undef __PRE_XEN_SYSCTL_READ
548}
549
550PRE(domctl)
551{
552   struct vki_xen_domctl *domctl = (struct vki_xen_domctl *)ARG1;
553
554   PRINT("__HYPERVISOR_domctl ( %d ) on dom%d", domctl->cmd, domctl->domain);
555
556   /*
557    * Common part of xen_domctl:
558    *    vki_uint32_t cmd;
559    *    vki_uint32_t interface_version;
560    *    vki_xen_domid_t  domain;
561    */
562   PRE_MEM_READ("__HYPERVISOR_domctl", ARG1,
563                sizeof(vki_uint32_t) + sizeof(vki_uint32_t)
564		+ sizeof(vki_xen_domid_t));
565
566   if (!domctl)
567      return;
568
569   switch (domctl->interface_version)
570   {
571   case 0x00000007:
572   case 0x00000008:
573   case 0x00000009:
574	   break;
575   default:
576      VG_(dmsg)("WARNING: domctl version %"PRIx32" not supported\n",
577                domctl->interface_version);
578      if (VG_(clo_verbosity) > 1) {
579         VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
580      }
581      VG_(dmsg)("You may be able to write your own handler.\n");
582      VG_(dmsg)("Read the file README_MISSING_SYSCALL_OR_IOCTL.\n");
583      VG_(dmsg)("Nevertheless we consider this a bug.  Please report\n");
584      VG_(dmsg)("it at http://valgrind.org/support/bug_reports.html &\n");
585      VG_(dmsg)("http://wiki.xen.org/wiki/Reporting_Bugs_against_Xen.\n");
586
587      SET_STATUS_Failure(VKI_EINVAL);
588      return;
589   }
590
591#define __PRE_XEN_DOMCTL_READ(_domctl, _union, _field)			\
592      PRE_MEM_READ("XEN_DOMCTL_" #_domctl " u." #_union "." #_field,	\
593                   (Addr)&domctl->u._union._field,			\
594                   sizeof(domctl->u._union._field))
595#define PRE_XEN_DOMCTL_READ(_domctl, _field) \
596      __PRE_XEN_DOMCTL_READ(_domctl, _domctl, _field)
597
598   switch (domctl->cmd) {
599   case VKI_XEN_DOMCTL_destroydomain:
600   case VKI_XEN_DOMCTL_pausedomain:
601   case VKI_XEN_DOMCTL_max_vcpus:
602   case VKI_XEN_DOMCTL_get_address_size:
603   case VKI_XEN_DOMCTL_gettscinfo:
604   case VKI_XEN_DOMCTL_getdomaininfo:
605   case VKI_XEN_DOMCTL_unpausedomain:
606   case VKI_XEN_DOMCTL_resumedomain:
607      /* No input fields. */
608      break;
609
610   case VKI_XEN_DOMCTL_createdomain:
611      PRE_XEN_DOMCTL_READ(createdomain, ssidref);
612      PRE_XEN_DOMCTL_READ(createdomain, handle);
613      PRE_XEN_DOMCTL_READ(createdomain, flags);
614      break;
615
616   case VKI_XEN_DOMCTL_gethvmcontext:
617       /* Xen unconditionally reads the 'buffer' pointer */
618       __PRE_XEN_DOMCTL_READ(gethvmcontext, hvmcontext, buffer);
619       /* Xen only consumes 'size' if 'buffer' is non NULL. A NULL
620        * buffer is a request for the required size. */
621       if ( domctl->u.hvmcontext.buffer.p )
622           __PRE_XEN_DOMCTL_READ(gethvmcontext, hvmcontext, size);
623       break;
624
625   case VKI_XEN_DOMCTL_sethvmcontext:
626       __PRE_XEN_DOMCTL_READ(sethvmcontext, hvmcontext, size);
627       __PRE_XEN_DOMCTL_READ(sethvmcontext, hvmcontext, buffer);
628       PRE_MEM_READ("XEN_DOMCTL_sethvmcontext *buffer",
629                    (Addr)domctl->u.hvmcontext.buffer.p,
630                    domctl->u.hvmcontext.size);
631       break;
632
633   case VKI_XEN_DOMCTL_gethvmcontext_partial:
634       __PRE_XEN_DOMCTL_READ(gethvmcontext_partial, hvmcontext_partial, type);
635       __PRE_XEN_DOMCTL_READ(gethvmcontext_partial, hvmcontext_partial, instance);
636       __PRE_XEN_DOMCTL_READ(gethvmcontext_partial, hvmcontext_partial, buffer);
637
638       switch (domctl->u.hvmcontext_partial.type) {
639       case VKI_HVM_SAVE_CODE(CPU):
640           if ( domctl->u.hvmcontext_partial.buffer.p )
641                PRE_MEM_WRITE("XEN_DOMCTL_gethvmcontext_partial *buffer",
642                   (Addr)domctl->u.hvmcontext_partial.buffer.p,
643                   VKI_HVM_SAVE_LENGTH(CPU));
644           break;
645       default:
646           bad_subop(tid, layout, arrghs, status, flags,
647                         "__HYPERVISOR_domctl_gethvmcontext_partial type",
648                         domctl->u.hvmcontext_partial.type);
649           break;
650       }
651       break;
652
653   case VKI_XEN_DOMCTL_max_mem:
654      PRE_XEN_DOMCTL_READ(max_mem, max_memkb);
655      break;
656
657   case VKI_XEN_DOMCTL_set_address_size:
658      __PRE_XEN_DOMCTL_READ(set_address_size, address_size, size);
659      break;
660
661   case VKI_XEN_DOMCTL_settscinfo:
662      __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info, info.tsc_mode);
663      __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info, info.gtsc_khz);
664      __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info, info.incarnation);
665      __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info, info.elapsed_nsec);
666      break;
667
668   case VKI_XEN_DOMCTL_ioport_permission:
669      PRE_XEN_DOMCTL_READ(ioport_permission, first_port);
670      PRE_XEN_DOMCTL_READ(ioport_permission, nr_ports);
671      PRE_XEN_DOMCTL_READ(ioport_permission, allow_access);
672      break;
673
674   case VKI_XEN_DOMCTL_hypercall_init:
675      PRE_XEN_DOMCTL_READ(hypercall_init, gmfn);
676      break;
677
678   case VKI_XEN_DOMCTL_settimeoffset:
679       PRE_XEN_DOMCTL_READ(settimeoffset, time_offset_seconds);
680       break;
681
682   case VKI_XEN_DOMCTL_getvcpuinfo:
683      PRE_XEN_DOMCTL_READ(getvcpuinfo, vcpu);
684      break;
685
686   case VKI_XEN_DOMCTL_scheduler_op:
687      PRE_XEN_DOMCTL_READ(scheduler_op, sched_id);
688      PRE_XEN_DOMCTL_READ(scheduler_op, cmd);
689      if ( domctl->u.scheduler_op.cmd == VKI_XEN_DOMCTL_SCHEDOP_putinfo ) {
690         switch(domctl->u.scheduler_op.sched_id) {
691         case VKI_XEN_SCHEDULER_SEDF:
692            PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.period);
693            PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.slice);
694            PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.latency);
695            PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.extratime);
696            PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.weight);
697            break;
698         case VKI_XEN_SCHEDULER_CREDIT:
699            PRE_XEN_DOMCTL_READ(scheduler_op, u.credit.weight);
700            PRE_XEN_DOMCTL_READ(scheduler_op, u.credit.cap);
701            break;
702         case VKI_XEN_SCHEDULER_CREDIT2:
703            PRE_XEN_DOMCTL_READ(scheduler_op, u.credit2.weight);
704            break;
705         case VKI_XEN_SCHEDULER_ARINC653:
706            break;
707         }
708      }
709      break;
710
711   case VKI_XEN_DOMCTL_getvcpuaffinity:
712      __PRE_XEN_DOMCTL_READ(getvcpuaffinity, vcpuaffinity, vcpu);
713      break;
714
715   case VKI_XEN_DOMCTL_setvcpuaffinity:
716      __PRE_XEN_DOMCTL_READ(setvcpuaffinity, vcpuaffinity, vcpu);
717      PRE_MEM_READ("XEN_DOMCTL_setvcpuaffinity u.vcpuaffinity.cpumap.bitmap",
718                   (Addr)domctl->u.vcpuaffinity.cpumap.bitmap.p,
719                   domctl->u.vcpuaffinity.cpumap.nr_bits / 8);
720      break;
721
722   case VKI_XEN_DOMCTL_getnodeaffinity:
723      __PRE_XEN_DOMCTL_READ(nodeaffinity, nodeaffinity, nodemap.nr_bits);
724      break;
725   case VKI_XEN_DOMCTL_setnodeaffinity:
726      __PRE_XEN_DOMCTL_READ(nodeaffinity, nodeaffinity, nodemap.nr_bits);
727      PRE_MEM_READ("XEN_DOMCTL_setnodeaffinity u.nodeaffinity.cpumap.bitmap",
728                   (Addr)domctl->u.nodeaffinity.nodemap.bitmap.p,
729                   domctl->u.nodeaffinity.nodemap.nr_bits / 8);
730      break;
731
732   case VKI_XEN_DOMCTL_getvcpucontext:
733      __PRE_XEN_DOMCTL_READ(getvcpucontext, vcpucontext, vcpu);
734      break;
735
736   case VKI_XEN_DOMCTL_setvcpucontext:
737      __PRE_XEN_DOMCTL_READ(setvcpucontext, vcpucontext, vcpu);
738      __PRE_XEN_DOMCTL_READ(setvcpucontext, vcpucontext, ctxt.p);
739      break;
740
741   case VKI_XEN_DOMCTL_set_cpuid:
742      PRE_MEM_READ("XEN_DOMCTL_set_cpuid u.cpuid",
743                   (Addr)&domctl->u.cpuid, sizeof(domctl->u.cpuid));
744      break;
745
746   case VKI_XEN_DOMCTL_getpageframeinfo3:
747       PRE_XEN_DOMCTL_READ(getpageframeinfo3, num);
748       PRE_XEN_DOMCTL_READ(getpageframeinfo3, array.p);
749       PRE_MEM_READ("XEN_DOMCTL_getpageframeinfo3 *u.getpageframeinfo3.array.p",
750                    (Addr)domctl->u.getpageframeinfo3.array.p,
751                    domctl->u.getpageframeinfo3.num * sizeof(vki_xen_pfn_t));
752       break;
753
754   case VKI_XEN_DOMCTL_getvcpuextstate:
755      __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, vcpu);
756      __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, xfeature_mask);
757      __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, size);
758      __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, buffer);
759      break;
760
761   case VKI_XEN_DOMCTL_shadow_op:
762       PRE_XEN_DOMCTL_READ(shadow_op, op);
763
764       switch(domctl->u.shadow_op.op)
765       {
766       case VKI_XEN_DOMCTL_SHADOW_OP_OFF:
767           /* No further inputs */
768           break;
769
770       case VKI_XEN_DOMCTL_SHADOW_OP_ENABLE:
771           PRE_XEN_DOMCTL_READ(shadow_op, mode);
772           switch(domctl->u.shadow_op.mode)
773           {
774           case XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY:
775               goto domctl_shadow_op_enable_logdirty;
776
777
778           default:
779               bad_subop(tid, layout, arrghs, status, flags,
780                         "__HYPERVISOR_domctl shadowop mode",
781                         domctl->u.shadow_op.mode);
782               break;
783           }
784
785       case VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY:
786       domctl_shadow_op_enable_logdirty:
787           /* No further inputs */
788           break;
789
790       case VKI_XEN_DOMCTL_SHADOW_OP_CLEAN:
791       case VKI_XEN_DOMCTL_SHADOW_OP_PEEK:
792           PRE_XEN_DOMCTL_READ(shadow_op, dirty_bitmap);
793           PRE_XEN_DOMCTL_READ(shadow_op, pages);
794           break;
795
796       default:
797           bad_subop(tid, layout, arrghs, status, flags,
798                     "__HYPERVISOR_domctl shadow(10)",
799                     domctl->u.shadow_op.op);
800           break;
801       }
802       break;
803
804   case VKI_XEN_DOMCTL_set_max_evtchn:
805      PRE_XEN_DOMCTL_READ(set_max_evtchn, max_port);
806      break;
807
808   case VKI_XEN_DOMCTL_cacheflush:
809      PRE_XEN_DOMCTL_READ(cacheflush, start_pfn);
810      PRE_XEN_DOMCTL_READ(cacheflush, nr_pfns);
811      break;
812
813   case VKI_XEN_DOMCTL_set_access_required:
814      PRE_XEN_DOMCTL_READ(access_required, access_required);
815      break;
816
817   case VKI_XEN_DOMCTL_mem_event_op:
818      PRE_XEN_DOMCTL_READ(mem_event_op, op);
819      PRE_XEN_DOMCTL_READ(mem_event_op, mode);
820      break;
821
822   case VKI_XEN_DOMCTL_debug_op:
823      PRE_XEN_DOMCTL_READ(debug_op, op);
824      PRE_XEN_DOMCTL_READ(debug_op, vcpu);
825      break;
826
827   default:
828      bad_subop(tid, layout, arrghs, status, flags,
829                "__HYPERVISOR_domctl", domctl->cmd);
830      break;
831   }
832#undef PRE_XEN_DOMCTL_READ
833#undef __PRE_XEN_DOMCTL_READ
834}
835
836PRE(hvm_op)
837{
838   unsigned long op = ARG1;
839   void *arg = (void *)(unsigned long)ARG2;
840
841   PRINT("__HYPERVISOR_hvm_op ( %ld, %p )", op, arg);
842
843#define __PRE_XEN_HVMOP_READ(_hvm_op, _type, _field)    \
844   PRE_MEM_READ("XEN_HVMOP_" # _hvm_op " " #_field,     \
845                (Addr)&((_type*)arg)->_field,           \
846                sizeof(((_type*)arg)->_field))
847#define PRE_XEN_HVMOP_READ(_hvm_op, _field)                             \
848   __PRE_XEN_HVMOP_READ(_hvm_op, vki_xen_hvm_ ## _hvm_op ## _t, _field)
849
850   switch (op) {
851   case VKI_XEN_HVMOP_set_param:
852      __PRE_XEN_HVMOP_READ(set_param, struct vki_xen_hvm_param, domid);
853      __PRE_XEN_HVMOP_READ(set_param, struct vki_xen_hvm_param, index);
854      __PRE_XEN_HVMOP_READ(set_param, struct vki_xen_hvm_param, value);
855      break;
856
857   case VKI_XEN_HVMOP_get_param:
858      __PRE_XEN_HVMOP_READ(get_param, struct vki_xen_hvm_param, domid);
859      __PRE_XEN_HVMOP_READ(get_param, struct vki_xen_hvm_param, index);
860      break;
861
862   case VKI_XEN_HVMOP_set_isa_irq_level:
863       PRE_XEN_HVMOP_READ(set_isa_irq_level, domid);
864       PRE_XEN_HVMOP_READ(set_isa_irq_level, isa_irq);
865       PRE_XEN_HVMOP_READ(set_isa_irq_level, level);
866       break;
867
868   case VKI_XEN_HVMOP_set_pci_link_route:
869       PRE_XEN_HVMOP_READ(set_pci_link_route, domid);
870       PRE_XEN_HVMOP_READ(set_pci_link_route, link);
871       PRE_XEN_HVMOP_READ(set_pci_link_route, isa_irq);
872       break;
873
874   case VKI_XEN_HVMOP_set_mem_type:
875       PRE_XEN_HVMOP_READ(set_mem_type, domid);
876       PRE_XEN_HVMOP_READ(set_mem_type, hvmmem_type);
877       PRE_XEN_HVMOP_READ(set_mem_type, nr);
878       PRE_XEN_HVMOP_READ(set_mem_type, first_pfn);
879       break;
880
881   case VKI_XEN_HVMOP_set_mem_access:
882       PRE_XEN_HVMOP_READ(set_mem_access, domid);
883       PRE_XEN_HVMOP_READ(set_mem_access, hvmmem_access);
884       PRE_XEN_HVMOP_READ(set_mem_access, first_pfn);
885       /* if default access */
886       if ( ((vki_xen_hvm_set_mem_access_t*)arg)->first_pfn != ~0ULL)
887           PRE_XEN_HVMOP_READ(set_mem_access, nr);
888       break;
889
890   case VKI_XEN_HVMOP_get_mem_access:
891       PRE_XEN_HVMOP_READ(get_mem_access, domid);
892       PRE_XEN_HVMOP_READ(get_mem_access, pfn);
893
894       PRE_MEM_WRITE("XEN_HVMOP_get_mem_access *hvmmem_access",
895                   (Addr)&(((vki_xen_hvm_get_mem_access_t*)arg)->hvmmem_access),
896                   sizeof(vki_uint16_t));
897       break;
898
899   case VKI_XEN_HVMOP_inject_trap:
900       PRE_XEN_HVMOP_READ(inject_trap, domid);
901       PRE_XEN_HVMOP_READ(inject_trap, vcpuid);
902       PRE_XEN_HVMOP_READ(inject_trap, vector);
903       PRE_XEN_HVMOP_READ(inject_trap, type);
904       PRE_XEN_HVMOP_READ(inject_trap, error_code);
905       PRE_XEN_HVMOP_READ(inject_trap, insn_len);
906       PRE_XEN_HVMOP_READ(inject_trap, cr2);
907       break;
908
909   default:
910      bad_subop(tid, layout, arrghs, status, flags,
911                "__HYPERVISOR_hvm_op", op);
912      break;
913   }
914#undef __PRE_XEN_HVMOP_READ
915#undef PRE_XEN_HVMOP_READ
916}
917
918PRE(tmem_op)
919{
920    struct vki_xen_tmem_op *tmem = (struct vki_xen_tmem_op *)ARG1;
921
922    PRINT("__HYPERVISOR_tmem_op ( %d )", tmem->cmd);
923
924    /* Common part for xen_tmem_op:
925     *    vki_uint32_t cmd;
926     */
927    PRE_MEM_READ("__HYPERVISOR_tmem_op cmd", ARG1, sizeof(vki_uint32_t));
928
929
930#define __PRE_XEN_TMEMOP_READ(_tmem, _union, _field)                    \
931    PRE_MEM_READ("XEN_tmem_op_" #_tmem " u." #_union "." #_field,       \
932                 (Addr)&tmem->u._union._field,                          \
933                 sizeof(tmem->u._union._field))
934#define PRE_XEN_TMEMOP_READ(_tmem, _field)                              \
935    __PRE_XEN_TMEMOP_READ(_tmem, _tmem, _field)
936
937    switch(tmem->cmd) {
938
939    case VKI_XEN_TMEM_control:
940
941        /* Common part for control hypercall:
942         *    vki_int32_t pool_id;
943         *    vki_uint32_t subop;
944         */
945        PRE_MEM_READ("__HYPERVISOR_tmem_op pool_id",
946                     (Addr)&tmem->pool_id, sizeof(&tmem->pool_id));
947        PRE_XEN_TMEMOP_READ(ctrl, subop);
948
949        switch (tmem->u.ctrl.subop) {
950
951        case VKI_XEN_TMEMC_save_begin:
952            PRE_XEN_TMEMOP_READ(ctrl, cli_id);
953            PRE_XEN_TMEMOP_READ(ctrl, arg1);
954            PRE_XEN_TMEMOP_READ(ctrl, buf);
955            break;
956
957        default:
958            bad_subop(tid, layout, arrghs, status, flags,
959                      "__HYPERVISOR_tmem_op_control", tmem->u.ctrl.subop);
960        }
961
962        break;
963
964    default:
965        bad_subop(tid, layout, arrghs, status, flags,
966                  "__HYPERVISOR_tmem_op", ARG1);
967    }
968
969#undef PRE_XEN_TMEMOP_READ
970#undef __PRE_XEN_TMEMOP_READ
971}
972
973POST(memory_op)
974{
975   switch (ARG1) {
976   case VKI_XENMEM_maximum_ram_page:
977   case VKI_XENMEM_set_memory_map:
978   case VKI_XENMEM_decrease_reservation:
979   case VKI_XENMEM_claim_pages:
980   case VKI_XENMEM_maximum_gpfn:
981   case VKI_XENMEM_remove_from_physmap:
982   case VKI_XENMEM_access_op:
983      /* No outputs */
984      break;
985   case VKI_XENMEM_increase_reservation:
986   case VKI_XENMEM_populate_physmap: {
987      struct xen_memory_reservation *memory_reservation =
988         (struct xen_memory_reservation *)ARG2;
989
990      POST_MEM_WRITE((Addr)memory_reservation->extent_start.p,
991                     sizeof(vki_xen_pfn_t) * memory_reservation->nr_extents);
992      break;
993   }
994
995   case VKI_XENMEM_machphys_mfn_list: {
996       struct vki_xen_machphys_mfn_list *arg =
997           (struct vki_xen_machphys_mfn_list *)ARG2;
998       POST_MEM_WRITE((Addr)&arg->nr_extents, sizeof(arg->nr_extents));
999       POST_MEM_WRITE((Addr)arg->extent_start.p,
1000                      sizeof(vki_xen_pfn_t) * arg->nr_extents);
1001       break;
1002   }
1003
1004   case VKI_XENMEM_add_to_physmap: {
1005       struct vki_xen_add_to_physmap *arg =
1006           (struct vki_xen_add_to_physmap *)ARG2;
1007       if (arg->space == VKI_XENMAPSPACE_gmfn_range)
1008           POST_MEM_WRITE(ARG2, sizeof(*arg));
1009   }
1010
1011   case VKI_XENMEM_get_sharing_freed_pages:
1012   case VKI_XENMEM_get_sharing_shared_pages:
1013       /* No outputs */
1014       break;
1015   }
1016}
1017
1018POST(mmuext_op)
1019{
1020   unsigned int *pdone = (unsigned int *)ARG3;
1021   /* simplistic */
1022   POST_MEM_WRITE((Addr)pdone, sizeof(*pdone));
1023}
1024
1025static void post_evtchn_op(ThreadId tid, __vki_u32 cmd, void *arg, int compat)
1026{
1027   switch (cmd) {
1028   case VKI_XEN_EVTCHNOP_alloc_unbound: {
1029      struct vki_xen_evtchn_alloc_unbound *alloc_unbound = arg;
1030      POST_MEM_WRITE((Addr)&alloc_unbound->port, sizeof(alloc_unbound->port));
1031      break;
1032   }
1033   }
1034}
1035
1036POST(evtchn_op)
1037{
1038   post_evtchn_op(tid, ARG1, (void *)ARG2, 0);
1039}
1040
1041POST(evtchn_op_compat)
1042{
1043   struct vki_xen_evtchn_op *evtchn = (struct vki_xen_evtchn_op *)ARG1;
1044   post_evtchn_op(tid, evtchn->cmd, &evtchn->u, 1);
1045}
1046
1047POST(xen_version)
1048{
1049   switch (ARG1) {
1050   case VKI_XENVER_version:
1051      /* No outputs */
1052      break;
1053   case VKI_XENVER_extraversion:
1054      POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_extraversion_t));
1055      break;
1056   case VKI_XENVER_compile_info:
1057      POST_MEM_WRITE((Addr)ARG2, sizeof(struct vki_xen_compile_info));
1058      break;
1059   case VKI_XENVER_capabilities:
1060      POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_capabilities_info_t));
1061      break;
1062   case VKI_XENVER_changeset:
1063      POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_changeset_info_t));
1064      break;
1065   case VKI_XENVER_platform_parameters:
1066      POST_MEM_WRITE((Addr)ARG2, sizeof(struct vki_xen_platform_parameters));
1067      break;
1068   case VKI_XENVER_get_features:
1069      POST_MEM_WRITE((Addr)ARG2, sizeof(struct vki_xen_feature_info));
1070      break;
1071   case VKI_XENVER_pagesize:
1072      /* No outputs */
1073      break;
1074   case VKI_XENVER_guest_handle:
1075      POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_domain_handle_t));
1076      break;
1077   case VKI_XENVER_commandline:
1078      POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_commandline_t));
1079      break;
1080   }
1081}
1082
1083POST(grant_table_op)
1084{
1085   switch (ARG1) {
1086   case VKI_XEN_GNTTABOP_setup_table: {
1087      struct vki_xen_gnttab_setup_table *gst =
1088	      (struct vki_xen_gnttab_setup_table*)ARG2;
1089      PRE_MEM_WRITE("VKI_XEN_GNTTABOP_setup_table",
1090                    (Addr)&gst->status, sizeof(gst->status));
1091      PRE_MEM_WRITE("VKI_XEN_GNTTABOP_setup_table",
1092                    (Addr)gst->frame_list.p,
1093                    sizeof(*gst->frame_list.p) & gst->nr_frames);
1094      break;
1095   }
1096   }
1097}
1098
1099POST(sysctl)
1100{
1101   struct vki_xen_sysctl *sysctl = (struct vki_xen_sysctl *)ARG1;
1102
1103   switch (sysctl->interface_version)
1104   {
1105   case 0x00000008:
1106   case 0x00000009:
1107   case 0x0000000a:
1108	   break;
1109   default:
1110      return;
1111   }
1112
1113#define __POST_XEN_SYSCTL_WRITE(_sysctl, _union, _field)        \
1114      POST_MEM_WRITE((Addr)&sysctl->u._union._field,            \
1115                     sizeof(sysctl->u._union._field))
1116#define POST_XEN_SYSCTL_WRITE(_sysctl, _field) \
1117      __POST_XEN_SYSCTL_WRITE(_sysctl, _sysctl, _field)
1118
1119   switch (sysctl->cmd) {
1120   case VKI_XEN_SYSCTL_readconsole:
1121       POST_MEM_WRITE((Addr)sysctl->u.readconsole.buffer.p,
1122                      sysctl->u.readconsole.count * sizeof(char));
1123       break;
1124
1125   case VKI_XEN_SYSCTL_getdomaininfolist:
1126      switch (sysctl->interface_version)
1127      {
1128      case 0x00000008:
1129	 POST_XEN_SYSCTL_WRITE(getdomaininfolist_00000008, num_domains);
1130	 POST_MEM_WRITE((Addr)sysctl->u.getdomaininfolist_00000008.buffer.p,
1131			sizeof(*sysctl->u.getdomaininfolist_00000008.buffer.p)
1132			* sysctl->u.getdomaininfolist_00000008.num_domains);
1133	 break;
1134      case 0x00000009:
1135	 POST_XEN_SYSCTL_WRITE(getdomaininfolist_00000009, num_domains);
1136	 POST_MEM_WRITE((Addr)sysctl->u.getdomaininfolist_00000009.buffer.p,
1137			sizeof(*sysctl->u.getdomaininfolist_00000009.buffer.p)
1138			* sysctl->u.getdomaininfolist_00000009.num_domains);
1139	 break;
1140      case 0x0000000a:
1141	 POST_XEN_SYSCTL_WRITE(getdomaininfolist_0000000a, num_domains);
1142	 POST_MEM_WRITE((Addr)sysctl->u.getdomaininfolist_0000000a.buffer.p,
1143			sizeof(*sysctl->u.getdomaininfolist_0000000a.buffer.p)
1144			* sysctl->u.getdomaininfolist_0000000a.num_domains);
1145	 break;
1146      }
1147      break;
1148
1149   case VKI_XEN_SYSCTL_sched_id:
1150       POST_XEN_SYSCTL_WRITE(sched_id, sched_id);
1151       break;
1152
1153   case VKI_XEN_SYSCTL_cpupool_op:
1154      if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_CREATE ||
1155          sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_INFO)
1156         POST_XEN_SYSCTL_WRITE(cpupool_op, cpupool_id);
1157      if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_INFO) {
1158         POST_XEN_SYSCTL_WRITE(cpupool_op, sched_id);
1159         POST_XEN_SYSCTL_WRITE(cpupool_op, n_dom);
1160      }
1161      if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_INFO ||
1162          sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_FREEINFO)
1163         POST_XEN_SYSCTL_WRITE(cpupool_op, cpumap);
1164      break;
1165
1166   case VKI_XEN_SYSCTL_physinfo:
1167      switch (sysctl->interface_version)
1168      {
1169      case 0x00000008:
1170      case 0x00000009: /* Unchanged from version 8 */
1171         POST_XEN_SYSCTL_WRITE(physinfo_00000008, threads_per_core);
1172         POST_XEN_SYSCTL_WRITE(physinfo_00000008, cores_per_socket);
1173         POST_XEN_SYSCTL_WRITE(physinfo_00000008, nr_cpus);
1174         POST_XEN_SYSCTL_WRITE(physinfo_00000008, max_cpu_id);
1175         POST_XEN_SYSCTL_WRITE(physinfo_00000008, nr_nodes);
1176         POST_XEN_SYSCTL_WRITE(physinfo_00000008, max_node_id);
1177         POST_XEN_SYSCTL_WRITE(physinfo_00000008, cpu_khz);
1178         POST_XEN_SYSCTL_WRITE(physinfo_00000008, total_pages);
1179         POST_XEN_SYSCTL_WRITE(physinfo_00000008, free_pages);
1180         POST_XEN_SYSCTL_WRITE(physinfo_00000008, scrub_pages);
1181         POST_XEN_SYSCTL_WRITE(physinfo_00000008, hw_cap[8]);
1182         POST_XEN_SYSCTL_WRITE(physinfo_00000008, capabilities);
1183         break;
1184      case 0x0000000a:
1185         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, threads_per_core);
1186         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, cores_per_socket);
1187         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, nr_cpus);
1188         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, max_cpu_id);
1189         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, nr_nodes);
1190         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, max_node_id);
1191         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, cpu_khz);
1192         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, total_pages);
1193         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, free_pages);
1194         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, scrub_pages);
1195         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, outstanding_pages);
1196         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, hw_cap[8]);
1197         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, capabilities);
1198         break;
1199      }
1200      break;
1201
1202   case VKI_XEN_SYSCTL_topologyinfo:
1203      POST_XEN_SYSCTL_WRITE(topologyinfo, max_cpu_index);
1204      if (sysctl->u.topologyinfo.cpu_to_core.p)
1205         POST_MEM_WRITE((Addr)sysctl->u.topologyinfo.cpu_to_core.p,
1206                     sizeof(uint32_t) * sysctl->u.topologyinfo.max_cpu_index);
1207      if (sysctl->u.topologyinfo.cpu_to_socket.p)
1208         POST_MEM_WRITE((Addr)sysctl->u.topologyinfo.cpu_to_socket.p,
1209                     sizeof(uint32_t) * sysctl->u.topologyinfo.max_cpu_index);
1210      if (sysctl->u.topologyinfo.cpu_to_node.p)
1211         POST_MEM_WRITE((Addr)sysctl->u.topologyinfo.cpu_to_node.p,
1212                     sizeof(uint32_t) * sysctl->u.topologyinfo.max_cpu_index);
1213      break;
1214
1215   case VKI_XEN_SYSCTL_numainfo:
1216      POST_XEN_SYSCTL_WRITE(numainfo, max_node_index);
1217      POST_MEM_WRITE((Addr)sysctl->u.numainfo.node_to_memsize.p,
1218                     sizeof(uint64_t) * sysctl->u.numainfo.max_node_index);
1219      POST_MEM_WRITE((Addr)sysctl->u.numainfo.node_to_memfree.p,
1220                     sizeof(uint64_t) * sysctl->u.numainfo.max_node_index);
1221      POST_MEM_WRITE((Addr)sysctl->u.numainfo.node_to_node_distance.p,
1222                     sizeof(uint32_t) * sysctl->u.numainfo.max_node_index);
1223      break;
1224
1225   /* No outputs */
1226   case VKI_XEN_SYSCTL_debug_keys:
1227       break;
1228   }
1229#undef POST_XEN_SYSCTL_WRITE
1230#undef __POST_XEN_SYSCTL_WRITE
1231}
1232
1233POST(domctl){
1234   struct vki_xen_domctl *domctl = (struct vki_xen_domctl *)ARG1;
1235
1236   switch (domctl->interface_version) {
1237   case 0x00000007:
1238   case 0x00000008:
1239   case 0x00000009:
1240	   break;
1241   default:
1242	   return;
1243   }
1244
1245#define __POST_XEN_DOMCTL_WRITE(_domctl, _union, _field)        \
1246   POST_MEM_WRITE((Addr)&domctl->u._union._field,               \
1247                  sizeof(domctl->u._union._field));
1248#define POST_XEN_DOMCTL_WRITE(_domctl, _field)          \
1249   __POST_XEN_DOMCTL_WRITE(_domctl, _domctl, _field)
1250
1251   switch (domctl->cmd) {
1252   case VKI_XEN_DOMCTL_createdomain:
1253   case VKI_XEN_DOMCTL_destroydomain:
1254   case VKI_XEN_DOMCTL_pausedomain:
1255   case VKI_XEN_DOMCTL_max_mem:
1256   case VKI_XEN_DOMCTL_set_address_size:
1257   case VKI_XEN_DOMCTL_settscinfo:
1258   case VKI_XEN_DOMCTL_ioport_permission:
1259   case VKI_XEN_DOMCTL_hypercall_init:
1260   case VKI_XEN_DOMCTL_setvcpuaffinity:
1261   case VKI_XEN_DOMCTL_setvcpucontext:
1262   case VKI_XEN_DOMCTL_setnodeaffinity:
1263   case VKI_XEN_DOMCTL_set_cpuid:
1264   case VKI_XEN_DOMCTL_unpausedomain:
1265   case VKI_XEN_DOMCTL_sethvmcontext:
1266   case VKI_XEN_DOMCTL_debug_op:
1267   case VKI_XEN_DOMCTL_set_max_evtchn:
1268   case VKI_XEN_DOMCTL_cacheflush:
1269   case VKI_XEN_DOMCTL_resumedomain:
1270   case VKI_XEN_DOMCTL_set_access_required:
1271      /* No output fields */
1272      break;
1273
1274   case VKI_XEN_DOMCTL_max_vcpus:
1275      POST_XEN_DOMCTL_WRITE(max_vcpus, max);
1276      break;
1277
1278   case VKI_XEN_DOMCTL_get_address_size:
1279      __POST_XEN_DOMCTL_WRITE(get_address_size, address_size, size);
1280      break;
1281
1282   case VKI_XEN_DOMCTL_gettscinfo:
1283      __POST_XEN_DOMCTL_WRITE(settscinfo, tsc_info, info.tsc_mode);
1284      __POST_XEN_DOMCTL_WRITE(settscinfo, tsc_info, info.gtsc_khz);
1285      __POST_XEN_DOMCTL_WRITE(settscinfo, tsc_info, info.incarnation);
1286      __POST_XEN_DOMCTL_WRITE(settscinfo, tsc_info, info.elapsed_nsec);
1287      break;
1288
1289   case VKI_XEN_DOMCTL_getvcpuinfo:
1290      POST_XEN_DOMCTL_WRITE(getvcpuinfo, online);
1291      POST_XEN_DOMCTL_WRITE(getvcpuinfo, blocked);
1292      POST_XEN_DOMCTL_WRITE(getvcpuinfo, running);
1293      POST_XEN_DOMCTL_WRITE(getvcpuinfo, cpu_time);
1294      POST_XEN_DOMCTL_WRITE(getvcpuinfo, cpu);
1295      break;
1296
1297   case VKI_XEN_DOMCTL_gethvmcontext:
1298       /* Xen unconditionally writes size... */
1299       __POST_XEN_DOMCTL_WRITE(gethvmcontext, hvmcontext, size);
1300       /* ...but only writes to the buffer if it was non NULL */
1301       if ( domctl->u.hvmcontext.buffer.p )
1302           POST_MEM_WRITE((Addr)domctl->u.hvmcontext.buffer.p,
1303                          sizeof(*domctl->u.hvmcontext.buffer.p)
1304                          * domctl->u.hvmcontext.size);
1305       break;
1306
1307   case VKI_XEN_DOMCTL_gethvmcontext_partial:
1308       switch (domctl->u.hvmcontext_partial.type) {
1309       case VKI_HVM_SAVE_CODE(CPU):
1310           if ( domctl->u.hvmcontext_partial.buffer.p )
1311                POST_MEM_WRITE((Addr)domctl->u.hvmcontext_partial.buffer.p,
1312                   VKI_HVM_SAVE_LENGTH(CPU));
1313           break;
1314       }
1315       break;
1316
1317   case VKI_XEN_DOMCTL_scheduler_op:
1318      if ( domctl->u.scheduler_op.cmd == VKI_XEN_DOMCTL_SCHEDOP_getinfo ) {
1319         switch(domctl->u.scheduler_op.sched_id) {
1320         case VKI_XEN_SCHEDULER_SEDF:
1321            POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.period);
1322            POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.slice);
1323            POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.latency);
1324            POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.extratime);
1325            POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.weight);
1326            break;
1327         case VKI_XEN_SCHEDULER_CREDIT:
1328            POST_XEN_DOMCTL_WRITE(scheduler_op, u.credit.weight);
1329            POST_XEN_DOMCTL_WRITE(scheduler_op, u.credit.cap);
1330            break;
1331         case VKI_XEN_SCHEDULER_CREDIT2:
1332            POST_XEN_DOMCTL_WRITE(scheduler_op, u.credit2.weight);
1333            break;
1334         case VKI_XEN_SCHEDULER_ARINC653:
1335            break;
1336         }
1337      }
1338      break;
1339
1340   case VKI_XEN_DOMCTL_getvcpuaffinity:
1341      POST_MEM_WRITE((Addr)domctl->u.vcpuaffinity.cpumap.bitmap.p,
1342                     domctl->u.vcpuaffinity.cpumap.nr_bits / 8);
1343      break;
1344
1345   case VKI_XEN_DOMCTL_getnodeaffinity:
1346      POST_MEM_WRITE((Addr)domctl->u.nodeaffinity.nodemap.bitmap.p,
1347                     domctl->u.nodeaffinity.nodemap.nr_bits / 8);
1348      break;
1349
1350   case VKI_XEN_DOMCTL_getdomaininfo:
1351      switch (domctl->interface_version) {
1352      case 0x00000007:
1353	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, domain);
1354	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, flags);
1355	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, tot_pages);
1356	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, max_pages);
1357	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, shr_pages);
1358	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, shared_info_frame);
1359	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, cpu_time);
1360	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, nr_online_vcpus);
1361	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, max_vcpu_id);
1362	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, ssidref);
1363	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, handle);
1364	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, cpupool);
1365      break;
1366      case 0x00000008:
1367	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, domain);
1368	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, flags);
1369	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, tot_pages);
1370	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, max_pages);
1371	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, shr_pages);
1372	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, paged_pages);
1373	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, shared_info_frame);
1374	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, cpu_time);
1375	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, nr_online_vcpus);
1376	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, max_vcpu_id);
1377	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, ssidref);
1378	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, handle);
1379	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, cpupool);
1380      break;
1381      case 0x00000009:
1382	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, domain);
1383	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, flags);
1384	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, tot_pages);
1385	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, max_pages);
1386	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, outstanding_pages);
1387	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, shr_pages);
1388	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, paged_pages);
1389	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, shared_info_frame);
1390	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, cpu_time);
1391	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, nr_online_vcpus);
1392	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, max_vcpu_id);
1393	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, ssidref);
1394	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, handle);
1395	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, cpupool);
1396      break;
1397      }
1398      break;
1399   case VKI_XEN_DOMCTL_getvcpucontext:
1400      __POST_XEN_DOMCTL_WRITE(getvcpucontext, vcpucontext, ctxt.p);
1401      break;
1402
1403   case VKI_XEN_DOMCTL_getpageframeinfo3:
1404       POST_MEM_WRITE((Addr)domctl->u.getpageframeinfo3.array.p,
1405                      domctl->u.getpageframeinfo3.num * sizeof(vki_xen_pfn_t));
1406       break;
1407
1408
1409   case VKI_XEN_DOMCTL_getvcpuextstate:
1410      __POST_XEN_DOMCTL_WRITE(getvcpuextstate, vcpuextstate, xfeature_mask);
1411      __POST_XEN_DOMCTL_WRITE(getvcpuextstate, vcpuextstate, size);
1412      POST_MEM_WRITE((Addr)domctl->u.vcpuextstate.buffer.p,
1413                     domctl->u.vcpuextstate.size);
1414      break;
1415
1416   case VKI_XEN_DOMCTL_shadow_op:
1417       switch(domctl->u.shadow_op.op)
1418       {
1419       case VKI_XEN_DOMCTL_SHADOW_OP_OFF:
1420           /* No outputs */
1421           break;
1422
1423       case VKI_XEN_DOMCTL_SHADOW_OP_CLEAN:
1424       case VKI_XEN_DOMCTL_SHADOW_OP_PEEK:
1425           POST_XEN_DOMCTL_WRITE(shadow_op, pages);
1426           POST_XEN_DOMCTL_WRITE(shadow_op, stats.fault_count);
1427           POST_XEN_DOMCTL_WRITE(shadow_op, stats.dirty_count);
1428           if(domctl->u.shadow_op.dirty_bitmap.p)
1429               POST_MEM_WRITE((Addr)domctl->u.shadow_op.dirty_bitmap.p,
1430                              domctl->u.shadow_op.pages * sizeof(vki_uint8_t));
1431           break;
1432
1433       default:
1434           break;
1435       }
1436       break;
1437   case VKI_XEN_DOMCTL_mem_event_op:
1438       POST_XEN_DOMCTL_WRITE(mem_event_op, port);
1439
1440       break;
1441   }
1442#undef POST_XEN_DOMCTL_WRITE
1443#undef __POST_XEN_DOMCTL_WRITE
1444}
1445
1446POST(hvm_op)
1447{
1448   unsigned long op = ARG1;
1449   void *arg = (void *)(unsigned long)ARG2;
1450
1451#define __POST_XEN_HVMOP_WRITE(_hvm_op, _type, _field)  \
1452      POST_MEM_WRITE((Addr)&((_type*)arg)->_field,      \
1453                     sizeof(((_type*)arg)->_field))
1454#define POST_XEN_HVMOP_WRITE(_hvm_op, _field) \
1455      __POST_XEN_HVMOP_WRITE(_hvm_op, vki_xen_hvm_ ## _hvm_op ## _t, _field)
1456
1457   switch (op) {
1458   case VKI_XEN_HVMOP_set_param:
1459   case VKI_XEN_HVMOP_set_isa_irq_level:
1460   case VKI_XEN_HVMOP_set_pci_link_route:
1461   case VKI_XEN_HVMOP_set_mem_type:
1462   case VKI_XEN_HVMOP_set_mem_access:
1463   case VKI_XEN_HVMOP_inject_trap:
1464      /* No output paramters */
1465      break;
1466
1467   case VKI_XEN_HVMOP_get_param:
1468      __POST_XEN_HVMOP_WRITE(get_param, struct vki_xen_hvm_param, value);
1469      break;
1470
1471   case VKI_XEN_HVMOP_get_mem_access:
1472      POST_XEN_HVMOP_WRITE(get_mem_access, hvmmem_access);
1473      break;
1474   }
1475#undef __POST_XEN_HVMOP_WRITE
1476#undef POST_XEN_HVMOP_WRITE
1477}
1478
1479POST(tmem_op)
1480{
1481    struct vki_xen_tmem_op *tmem = (struct vki_xen_tmem_op *)ARG1;
1482
1483    switch(tmem->cmd) {
1484
1485    case VKI_XEN_TMEM_control:
1486
1487        switch(tmem->u.ctrl.subop) {
1488            /* No outputs */
1489            case VKI_XEN_TMEMC_save_begin:
1490                break;
1491        }
1492
1493        break;
1494    }
1495}
1496
1497typedef
1498   struct {
1499      SyscallTableEntry entry;
1500      int nr_args;
1501   }
1502   XenHypercallTableEntry;
1503
1504#define HYPX_(const, name, nr_args) \
1505   [const] = { { vgSysWrap_xen_##name##_before, NULL }, nr_args }
1506#define HYPXY(const, name, nr_args)                     \
1507   [const] = { { vgSysWrap_xen_##name##_before,         \
1508                 vgSysWrap_xen_##name##_after },        \
1509               nr_args }
1510
1511static XenHypercallTableEntry hypercall_table[] = {
1512   //    __VKI_XEN_set_trap_table                                  // 0
1513   //    __VKI_XEN_mmu_update                                      // 1
1514   //    __VKI_XEN_set_gdt                                         // 2
1515   //    __VKI_XEN_stack_switch                                    // 3
1516   //    __VKI_XEN_set_callbacks                                   // 4
1517
1518   //    __VKI_XEN_fpu_taskswitch                                  // 5
1519   //    __VKI_XEN_sched_op_compat                                 // 6
1520   //    __VKI_XEN_platform_op                                     // 7
1521   //    __VKI_XEN_set_debugreg                                    // 8
1522   //    __VKI_XEN_get_debugreg                                    // 9
1523
1524   //    __VKI_XEN_update_descriptor                               // 10
1525   //                                                                 // 11
1526   HYPXY(__VKI_XEN_memory_op,               memory_op,         2), // 12
1527   //    __VKI_XEN_multicall                                       // 13
1528   //    __VKI_XEN_update_va_mapping                               // 14
1529
1530   //    __VKI_XEN_set_timer_op                                    // 15
1531   HYPXY(__VKI_XEN_event_channel_op_compat, evtchn_op_compat,  1), // 16
1532   HYPXY(__VKI_XEN_xen_version,             xen_version,       2), // 17
1533   //    __VKI_XEN_console_io                                      // 18
1534   //    __VKI_XEN_physdev_op_compat                               // 19
1535
1536   HYPXY(__VKI_XEN_grant_table_op,          grant_table_op,    3), // 20
1537   //    __VKI_XEN_vm_assist                                       // 21
1538   //    __VKI_XEN_update_va_mapping_otherdomain                   // 22
1539   //    __VKI_XEN_iret,                    iret                   // 23
1540   //    __VKI_XEN_vcpu_op,                 vcpu_op                // 24
1541
1542   //    __VKI_XEN_set_segment_base                                // 25
1543   HYPXY(__VKI_XEN_mmuext_op,               mmuext_op,         2), // 26
1544   //    __VKI_XEN_xsm_op                                          // 27
1545   //    __VKI_XEN_nmi_op                                          // 28
1546   //    __VKI_XEN_sched_op                                        // 29
1547
1548   //    __VKI_XEN_callback_op                                     // 30
1549   //    __VKI_XEN_xenoprof_op                                     // 31
1550   HYPXY(__VKI_XEN_event_channel_op,        evtchn_op,         2), // 32
1551   //    __VKI_XEN_physdev_op                                      // 33
1552   HYPXY(__VKI_XEN_hvm_op,                  hvm_op,            2), // 34
1553
1554   HYPXY(__VKI_XEN_sysctl,                  sysctl,            1), // 35
1555   HYPXY(__VKI_XEN_domctl,                  domctl,            1), // 36
1556   //    __VKI_XEN_kexec_op                                        // 37
1557   HYPXY(__VKI_XEN_tmem_op,                 tmem_op,           1), // 38
1558};
1559
1560static void bad_before ( ThreadId              tid,
1561                         SyscallArgLayout*     layout,
1562                         /*MOD*/SyscallArgs*   args,
1563                         /*OUT*/SyscallStatus* status,
1564                         /*OUT*/UWord*         flags )
1565{
1566   VG_(dmsg)("WARNING: unhandled hypercall: %s\n",
1567      VG_SYSNUM_STRING(args->sysno));
1568   if (VG_(clo_verbosity) > 1) {
1569      VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
1570   }
1571   VG_(dmsg)("You may be able to write your own handler.\n");
1572   VG_(dmsg)("Read the file README_MISSING_SYSCALL_OR_IOCTL.\n");
1573   VG_(dmsg)("Nevertheless we consider this a bug.  Please report\n");
1574   VG_(dmsg)("it at http://valgrind.org/support/bug_reports.html &\n");
1575   VG_(dmsg)("http://wiki.xen.org/wiki/Reporting_Bugs_against_Xen.\n");
1576
1577   SET_STATUS_Failure(VKI_ENOSYS);
1578}
1579
1580static XenHypercallTableEntry bad_hyper =
1581{ { bad_before, NULL }, 0 };
1582
1583static XenHypercallTableEntry* ML_(get_xen_hypercall_entry) ( UInt sysno )
1584{
1585   XenHypercallTableEntry *ret = &bad_hyper;
1586
1587   const UInt hypercall_table_size
1588      = sizeof(hypercall_table) / sizeof(hypercall_table[0]);
1589
1590   /* Is it in the contiguous initial section of the table? */
1591   if (sysno < hypercall_table_size) {
1592      XenHypercallTableEntry* ent = &hypercall_table[sysno];
1593      if (ent->entry.before != NULL)
1594         ret = ent;
1595   }
1596
1597   /* Can't find a wrapper */
1598   return ret;
1599}
1600
1601DEFN_PRE_TEMPLATE(xen, hypercall)
1602{
1603   XenHypercallTableEntry *ent = ML_(get_xen_hypercall_entry)(SYSNO);
1604
1605   /* Return number of arguments consumed */
1606   ARG8 = ent->nr_args;
1607
1608   vg_assert(ent);
1609   vg_assert(ent->entry.before);
1610   (ent->entry.before)( tid, layout, arrghs, status, flags );
1611
1612}
1613
1614DEFN_POST_TEMPLATE(xen, hypercall)
1615{
1616   XenHypercallTableEntry *ent = ML_(get_xen_hypercall_entry)(SYSNO);
1617
1618   /* Return number of arguments consumed */
1619   ARG8 = ent->nr_args;
1620
1621   vg_assert(ent);
1622   if (ent->entry.after)
1623      (ent->entry.after)( tid, arrghs, status );
1624}
1625
1626#endif // defined(ENABLE_XEN)
1627