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_intf_version ( ThreadId              tid,
69                               SyscallArgLayout*     layout,
70                               /*MOD*/SyscallArgs*   args,
71                               /*OUT*/SyscallStatus* status,
72                               /*OUT*/UWord*         flags,
73                               const HChar*          hypercall,
74                               UWord                 version)
75{
76   VG_(dmsg)("WARNING: %s version %#lx not supported\n",
77             hypercall, version);
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
90static void bad_subop ( ThreadId              tid,
91                        SyscallArgLayout*     layout,
92                        /*MOD*/SyscallArgs*   args,
93                        /*OUT*/SyscallStatus* status,
94                        /*OUT*/UWord*         flags,
95                        const HChar*          hypercall,
96                        UWord                 subop)
97{
98   VG_(dmsg)("WARNING: unhandled %s subop: %lu\n",
99             hypercall, subop);
100   if (VG_(clo_verbosity) > 1) {
101      VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
102   }
103   VG_(dmsg)("You may be able to write your own handler.\n");
104   VG_(dmsg)("Read the file README_MISSING_SYSCALL_OR_IOCTL.\n");
105   VG_(dmsg)("Nevertheless we consider this a bug.  Please report\n");
106   VG_(dmsg)("it at http://valgrind.org/support/bug_reports.html &\n");
107   VG_(dmsg)("http://wiki.xen.org/wiki/Reporting_Bugs_against_Xen.\n");
108
109   SET_STATUS_Failure(VKI_ENOSYS);
110}
111
112PRE(memory_op)
113{
114   PRINT("__HYPERVISOR_memory_op ( %lu, %#lx )", ARG1, ARG2);
115
116   switch (ARG1) {
117
118   case VKI_XENMEM_maximum_ram_page:
119       /* No inputs */
120       break;
121
122   case VKI_XENMEM_maximum_gpfn:
123       PRE_MEM_READ("XENMEM_maximum_gpfn domid",
124                    (Addr)ARG2, sizeof(vki_xen_domid_t));
125       break;
126
127   case VKI_XENMEM_machphys_mfn_list:
128   case VKI_XENMEM_machphys_compat_mfn_list: {
129       struct vki_xen_machphys_mfn_list *arg =
130           (struct vki_xen_machphys_mfn_list *)ARG2;
131       PRE_MEM_READ("XENMEM_machphys_mfn_list max_extents",
132                    (Addr)&arg->max_extents, sizeof(arg->max_extents));
133       PRE_MEM_READ("XENMEM_machphys_mfn_list extent_start",
134                    (Addr)&arg->extent_start, sizeof(arg->extent_start));
135       break;
136   }
137
138   case VKI_XENMEM_set_memory_map: {
139      struct vki_xen_foreign_memory_map *arg =
140	      (struct vki_xen_foreign_memory_map *)ARG2;
141      PRE_MEM_READ("XENMEM_set_memory_map domid",
142                   (Addr)&arg->domid, sizeof(arg->domid));
143      PRE_MEM_READ("XENMEM_set_memory_map map",
144                   (Addr)&arg->map, sizeof(arg->map));
145      break;
146   }
147
148   case VKI_XENMEM_memory_map:
149   case VKI_XENMEM_machine_memory_map: {
150      struct vki_xen_memory_map *arg =
151	      (struct vki_xen_memory_map *)ARG2;
152      PRE_MEM_READ("XENMEM_memory_map nr_entries",
153                   (Addr)&arg->nr_entries, sizeof(arg->nr_entries));
154      break;
155   }
156
157   case VKI_XENMEM_increase_reservation:
158   case VKI_XENMEM_decrease_reservation:
159   case VKI_XENMEM_populate_physmap:
160   case VKI_XENMEM_claim_pages: {
161      struct xen_memory_reservation *memory_reservation =
162         (struct xen_memory_reservation *)ARG2;
163      const HChar *which;
164
165      switch (ARG1) {
166      case VKI_XENMEM_increase_reservation:
167         which = "XENMEM_increase_reservation";
168         break;
169      case VKI_XENMEM_decrease_reservation:
170         which = "XENMEM_decrease_reservation";
171         PRE_MEM_READ(which,
172                      (Addr)memory_reservation->extent_start.p,
173                      sizeof(vki_xen_pfn_t) * memory_reservation->nr_extents);
174	 break;
175      case VKI_XENMEM_populate_physmap:
176         which = "XENMEM_populate_physmap";
177         PRE_MEM_READ(which,
178                      (Addr)memory_reservation->extent_start.p,
179                      sizeof(vki_xen_pfn_t) * memory_reservation->nr_extents);
180         break;
181      case VKI_XENMEM_claim_pages:
182         which = "XENMEM_claim_pages";
183         break;
184      default:
185         which = "XENMEM_unknown";
186         break;
187      }
188
189      PRE_MEM_READ(which,
190                   (Addr)&memory_reservation->extent_start,
191                   sizeof(memory_reservation->extent_start));
192      PRE_MEM_READ(which,
193                   (Addr)&memory_reservation->nr_extents,
194                   sizeof(memory_reservation->nr_extents));
195      PRE_MEM_READ(which,
196                   (Addr)&memory_reservation->extent_order,
197                   sizeof(memory_reservation->extent_order));
198      PRE_MEM_READ(which,
199                   (Addr)&memory_reservation->mem_flags,
200                   sizeof(memory_reservation->mem_flags));
201      PRE_MEM_READ(which,
202                   (Addr)&memory_reservation->domid,
203                   sizeof(memory_reservation->domid));
204      break;
205   }
206
207   case VKI_XENMEM_add_to_physmap: {
208       struct vki_xen_add_to_physmap *arg =
209           (struct vki_xen_add_to_physmap *)ARG2;
210       PRE_MEM_READ("XENMEM_add_to_physmap domid",
211                    (Addr)&arg->domid, sizeof(arg->domid));
212       PRE_MEM_READ("XENMEM_add_to_physmap size",
213                    (Addr)&arg->size, sizeof(arg->size));
214       PRE_MEM_READ("XENMEM_add_to_physmap space",
215                    (Addr)&arg->space, sizeof(arg->space));
216       PRE_MEM_READ("XENMEM_add_to_physmap idx",
217                    (Addr)&arg->idx, sizeof(arg->idx));
218       PRE_MEM_READ("XENMEM_add_to_physmap gpfn",
219                    (Addr)&arg->gpfn, sizeof(arg->gpfn));
220       break;
221   }
222
223   case VKI_XENMEM_remove_from_physmap: {
224       struct vki_xen_remove_from_physmap *arg =
225           (struct vki_xen_remove_from_physmap *)ARG2;
226       PRE_MEM_READ("XENMEM_remove_from_physmap domid",
227                    (Addr)&arg->domid, sizeof(arg->domid));
228       PRE_MEM_READ("XENMEM_remove_from_physmap gpfn",
229                    (Addr)&arg->gpfn, sizeof(arg->gpfn));
230       break;
231   }
232
233   case VKI_XENMEM_get_sharing_freed_pages:
234   case VKI_XENMEM_get_sharing_shared_pages:
235      break;
236
237   case VKI_XENMEM_access_op: {
238       struct vki_xen_mem_event_op *arg =
239            (struct vki_xen_mem_event_op *)ARG2;
240       PRE_MEM_READ("XENMEM_access_op domid",
241                    (Addr)&arg->domain, sizeof(arg->domain));
242       PRE_MEM_READ("XENMEM_access_op op",
243                    (Addr)&arg->op, sizeof(arg->op));
244       PRE_MEM_READ("XENMEM_access_op gfn",
245                    (Addr)&arg->gfn, sizeof(arg->gfn));
246       break;
247   }
248   default:
249      bad_subop(tid, layout, arrghs, status, flags,
250                "__HYPERVISOR_memory_op", ARG1);
251      break;
252   }
253}
254
255PRE(mmuext_op)
256{
257   PRINT("__HYPERVISOR_mmuext_op ( %#lx, %ld, %#lx, %lu )",
258         ARG1, SARG2, ARG3, ARG4);
259
260   struct vki_xen_mmuext_op *ops = (struct vki_xen_mmuext_op *)ARG1;
261   unsigned int i, nr = ARG2;
262
263   for (i=0; i<nr; i++) {
264      struct vki_xen_mmuext_op *op = ops + i;
265      PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP cmd",
266                   (Addr)&op->cmd, sizeof(op->cmd));
267      switch(op->cmd) {
268      case VKI_XEN_MMUEXT_PIN_L1_TABLE:
269      case VKI_XEN_MMUEXT_PIN_L2_TABLE:
270      case VKI_XEN_MMUEXT_PIN_L3_TABLE:
271      case VKI_XEN_MMUEXT_PIN_L4_TABLE:
272      case VKI_XEN_MMUEXT_UNPIN_TABLE:
273      case VKI_XEN_MMUEXT_NEW_BASEPTR:
274      case VKI_XEN_MMUEXT_CLEAR_PAGE:
275      case VKI_XEN_MMUEXT_COPY_PAGE:
276      case VKI_XEN_MMUEXT_MARK_SUPER:
277      case VKI_XEN_MMUEXT_UNMARK_SUPER:
278         PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg1.mfn",
279                      (Addr)&op->arg1.mfn,
280                      sizeof(op->arg1.mfn));
281         break;
282
283      case VKI_XEN_MMUEXT_INVLPG_LOCAL:
284      case VKI_XEN_MMUEXT_INVLPG_ALL:
285      case VKI_XEN_MMUEXT_SET_LDT:
286         PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg1.mfn",
287                      (Addr)&op->arg1.linear_addr,
288                      sizeof(op->arg1.linear_addr));
289         break;
290
291      case VKI_XEN_MMUEXT_TLB_FLUSH_LOCAL:
292      case VKI_XEN_MMUEXT_TLB_FLUSH_MULTI:
293      case VKI_XEN_MMUEXT_INVLPG_MULTI:
294      case VKI_XEN_MMUEXT_TLB_FLUSH_ALL:
295      case VKI_XEN_MMUEXT_FLUSH_CACHE:
296      case VKI_XEN_MMUEXT_NEW_USER_BASEPTR:
297      case VKI_XEN_MMUEXT_FLUSH_CACHE_GLOBAL:
298         /* None */
299         break;
300      }
301
302      switch(op->cmd) {
303      case VKI_XEN_MMUEXT_SET_LDT:
304         PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.nr_ents",
305                      (Addr)&op->arg2.nr_ents,
306                      sizeof(op->arg2.nr_ents));
307         break;
308
309      case VKI_XEN_MMUEXT_TLB_FLUSH_MULTI:
310      case VKI_XEN_MMUEXT_INVLPG_MULTI:
311         /* How many??? */
312         PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.vcpumask",
313                      (Addr)&op->arg2.vcpumask,
314                      sizeof(op->arg2.vcpumask));
315         break;
316
317      case VKI_XEN_MMUEXT_COPY_PAGE:
318         PRE_MEM_READ("__HYPERVISOR_MMUEXT_OP arg2.src_mfn",
319                      (Addr)&op->arg2.src_mfn,
320                      sizeof(op->arg2.src_mfn));
321         break;
322
323      case VKI_XEN_MMUEXT_PIN_L1_TABLE:
324      case VKI_XEN_MMUEXT_PIN_L2_TABLE:
325      case VKI_XEN_MMUEXT_PIN_L3_TABLE:
326      case VKI_XEN_MMUEXT_PIN_L4_TABLE:
327      case VKI_XEN_MMUEXT_UNPIN_TABLE:
328      case VKI_XEN_MMUEXT_NEW_BASEPTR:
329      case VKI_XEN_MMUEXT_TLB_FLUSH_LOCAL:
330      case VKI_XEN_MMUEXT_INVLPG_LOCAL:
331      case VKI_XEN_MMUEXT_TLB_FLUSH_ALL:
332      case VKI_XEN_MMUEXT_INVLPG_ALL:
333      case VKI_XEN_MMUEXT_FLUSH_CACHE:
334      case VKI_XEN_MMUEXT_NEW_USER_BASEPTR:
335      case VKI_XEN_MMUEXT_CLEAR_PAGE:
336      case VKI_XEN_MMUEXT_FLUSH_CACHE_GLOBAL:
337      case VKI_XEN_MMUEXT_MARK_SUPER:
338      case VKI_XEN_MMUEXT_UNMARK_SUPER:
339         /* None */
340         break;
341      }
342   }
343}
344
345PRE(xsm_op)
346{
347   /* XXX assuming flask, only actual XSM right now */
348   struct vki_xen_flask_op *op = (struct vki_xen_flask_op *)ARG1;
349
350   PRINT("__HYPERVISOR_xsm_op ( %u )", op->cmd);
351
352   /*
353    * Common part of xen_flask_op:
354    *    vki_uint32_t cmd;
355    *    vki_uint32_t interface_version;
356    */
357   PRE_MEM_READ("__HYPERVISOR_xsm_op", ARG1,
358                sizeof(vki_uint32_t) + sizeof(vki_uint32_t));
359
360   if (!op)
361      return;
362
363   switch (op->interface_version) {
364   case 0x00000001:
365      break;
366   default:
367      bad_intf_version(tid, layout, arrghs, status, flags,
368                       "__HYPERVISOR_xsm_op", op->interface_version);
369      return;
370   }
371
372#define PRE_XEN_XSM_OP_READ(_xsm_op, _union, _field)            \
373   PRE_MEM_READ("FLASK_" #_xsm_op " u." #_union "." #_field,    \
374                (Addr)&op->u._union._field,                     \
375                sizeof(op->u._union._field))
376
377   switch (op->cmd) {
378   case VKI_FLASK_SID_TO_CONTEXT:
379      PRE_XEN_XSM_OP_READ(SID_TO_CONTEXT, sid_context, sid);
380      PRE_XEN_XSM_OP_READ(SID_TO_CONTEXT, sid_context, size);
381      PRE_XEN_XSM_OP_READ(SID_TO_CONTEXT, sid_context, context.p);
382      break;
383   default:
384      bad_subop(tid, layout, arrghs, status, flags,
385                "__HYPERVISOR_xsm_op", op->cmd);
386      break;
387   }
388#undef __PRE_XEN_XSM_OP_READ
389#undef PRE_XEN_XSM_OP_READ
390}
391
392PRE(sched_op)
393{
394   PRINT("__HYPERVISOR_sched_op ( %ld, %#lx )", SARG1, ARG2);
395   void *arg = (void *)(unsigned long)ARG2;
396
397#define __PRE_XEN_SCHEDOP_READ(_schedop, _type, _field) \
398   PRE_MEM_READ("XEN_SCHEDOP_" # _schedop " " #_field,  \
399                (Addr)&((_type*)arg)->_field,           \
400                sizeof(((_type*)arg)->_field))
401#define PRE_XEN_SCHEDOP_READ(_schedop, _field)                          \
402   __PRE_XEN_SCHEDOP_READ(_schedop, vki_xen_ ## _schedop ## _t, _field)
403
404   switch (ARG1) {
405   case VKI_XEN_SCHEDOP_remote_shutdown:
406      PRE_XEN_SCHEDOP_READ(remote_shutdown, domain_id);
407      PRE_XEN_SCHEDOP_READ(remote_shutdown, reason);
408      break;
409
410   default:
411      bad_subop(tid, layout, arrghs, status, flags,
412                "__HYPERVISOR_sched_op", ARG1);
413      break;
414   }
415#undef __PRE_XEN_SCHEDOP_READ
416#undef PRE_XEN_SCHEDOP_READ
417}
418
419static void pre_evtchn_op(ThreadId tid,
420                          SyscallArgLayout*     layout,
421                          /*MOD*/SyscallArgs*   arrghs,
422                          /*OUT*/SyscallStatus* status,
423                          /*OUT*/UWord*         flags,
424                          __vki_u32 cmd, void *arg, int compat)
425{
426   PRINT("__HYPERVISOR_event_channel_op%s ( %u, %p )",
427         compat ? "_compat" : "", cmd, arg);
428
429   switch (cmd) {
430   case VKI_XEN_EVTCHNOP_alloc_unbound: {
431      struct vki_xen_evtchn_alloc_unbound *alloc_unbound = arg;
432      PRE_MEM_READ("EVTCHNOP_alloc_unbound dom",
433                   (Addr)&alloc_unbound->dom, sizeof(alloc_unbound->dom));
434      PRE_MEM_READ("EVTCHNOP_alloc_unbound remote_dom",
435                   (Addr)&alloc_unbound->remote_dom,
436                   sizeof(alloc_unbound->remote_dom));
437      break;
438   }
439   default:
440      if ( compat )
441         bad_subop(tid, layout, arrghs, status, flags,
442                   "__HYPERVISOR_event_channel_op_compat", cmd);
443      else
444         bad_subop(tid, layout, arrghs, status, flags,
445                   "__HYPERVISOR_event_channel_op", cmd);
446      break;
447   }
448}
449
450PRE(evtchn_op)
451{
452   pre_evtchn_op(tid, layout, arrghs, status, flags,
453                 ARG1, (void *)ARG2, 0);
454}
455
456PRE(evtchn_op_compat)
457{
458   struct vki_xen_evtchn_op *evtchn = (struct vki_xen_evtchn_op *)ARG1;
459   PRE_MEM_READ("__HYPERVISOR_event_channel_op_compat",
460                ARG1, sizeof(*evtchn));
461
462   pre_evtchn_op(tid, layout, arrghs, status, flags,
463                 evtchn->cmd, &evtchn->u, 1);
464}
465
466PRE(physdev_op)
467{
468   int cmd = ARG1;
469
470   PRINT("__HYPERVISOR_physdev_op ( %ld, %#lx )", SARG1, ARG2);
471
472#define PRE_XEN_PHYSDEVOP_READ(_op, _field)		\
473   PRE_MEM_READ("XEN_PHYSDEVOP_" #_op " ." #_field,	\
474                (Addr)&arg->_field,			\
475                sizeof(arg->_field))
476
477   switch (cmd) {
478   case VKI_XEN_PHYSDEVOP_map_pirq: {
479      struct vki_xen_physdev_map_pirq *arg =
480         (struct vki_xen_physdev_map_pirq *)ARG2;
481
482      PRE_XEN_PHYSDEVOP_READ("map_pirq", domid);
483      PRE_XEN_PHYSDEVOP_READ("map_pirq", type);
484
485      PRE_XEN_PHYSDEVOP_READ("map_pirq", bus);
486      PRE_XEN_PHYSDEVOP_READ("map_pirq", devfn);
487      PRE_XEN_PHYSDEVOP_READ("map_pirq", entry_nr);
488      PRE_XEN_PHYSDEVOP_READ("map_pirq", table_base);
489
490      switch(arg->type) {
491      case VKI_XEN_MAP_PIRQ_TYPE_MSI:
492         PRE_XEN_PHYSDEVOP_READ("map_pirq", index);
493         break;
494      case VKI_XEN_MAP_PIRQ_TYPE_GSI:
495         PRE_XEN_PHYSDEVOP_READ("map_pirq", index);
496         PRE_XEN_PHYSDEVOP_READ("map_pirq", pirq);
497         break;
498      case VKI_XEN_MAP_PIRQ_TYPE_MSI_SEG:
499         PRE_XEN_PHYSDEVOP_READ("map_pirq", index);
500         break;
501      case VKI_XEN_MAP_PIRQ_TYPE_MULTI_MSI:
502         break;
503      }
504      break;
505   }
506   case VKI_XEN_PHYSDEVOP_unmap_pirq: {
507      struct vki_xen_physdev_unmap_pirq *arg =
508         (struct vki_xen_physdev_unmap_pirq *)ARG2;
509      PRE_XEN_PHYSDEVOP_READ("unmap_pirq", domid);
510      PRE_XEN_PHYSDEVOP_READ("unmap_pirq", pirq);
511      break;
512   }
513   default:
514      bad_subop(tid, layout, arrghs, status, flags,
515                "__HYPERVISOR_physdev_op", cmd);
516   }
517#undef PRE_XEN_PHYSDEVOP_READ
518}
519
520PRE(xen_version)
521{
522   PRINT("__HYPERVISOR_xen_version ( %ld, %#lx )", SARG1, ARG2);
523
524   switch (ARG1) {
525   case VKI_XENVER_version:
526   case VKI_XENVER_extraversion:
527   case VKI_XENVER_compile_info:
528   case VKI_XENVER_capabilities:
529   case VKI_XENVER_changeset:
530   case VKI_XENVER_platform_parameters:
531   case VKI_XENVER_get_features:
532   case VKI_XENVER_pagesize:
533   case VKI_XENVER_guest_handle:
534   case VKI_XENVER_commandline:
535      /* No inputs */
536      break;
537
538   default:
539      bad_subop(tid, layout, arrghs, status, flags,
540                "__HYPERVISOR_xen_version", ARG1);
541      break;
542   }
543}
544
545PRE(grant_table_op)
546{
547   PRINT("__HYPERVISOR_grant_table_op ( %lu, %#lx, %lu )", ARG1, ARG2, ARG3);
548   switch (ARG1) {
549   case VKI_XEN_GNTTABOP_setup_table: {
550      struct vki_xen_gnttab_setup_table *gst =
551	      (struct vki_xen_gnttab_setup_table*)ARG2;
552      PRE_MEM_READ("VKI_XEN_GNTTABOP_setup_table dom",
553		   (Addr)&gst->dom, sizeof(gst->dom));
554      PRE_MEM_READ("VKI_XEN_GNTTABOP_setup_table nr_frames",
555                   (Addr)&gst->nr_frames, sizeof(gst->nr_frames));
556      break;
557   }
558   default:
559      bad_subop(tid, layout, arrghs, status, flags,
560                "__HYPERVISOR_grant_table_op", ARG1);
561      break;
562   }
563}
564
565PRE(sysctl) {
566   struct vki_xen_sysctl *sysctl = (struct vki_xen_sysctl *)ARG1;
567
568   PRINT("__HYPERVISOR_sysctl ( %u )", sysctl->cmd);
569
570   /*
571    * Common part of xen_sysctl:
572    *    uint32_t cmd;
573    *    uint32_t interface_version;
574    */
575   PRE_MEM_READ("__HYPERVISOR_sysctl", ARG1,
576                sizeof(vki_uint32_t) + sizeof(vki_uint32_t));
577
578   if (!sysctl)
579      return;
580
581   switch (sysctl->interface_version)
582   {
583   case 0x00000008:
584   case 0x00000009:
585   case 0x0000000a:
586   case 0x0000000b:
587	   break;
588   default:
589      bad_intf_version(tid, layout, arrghs, status, flags,
590                       "__HYPERVISOR_sysctl", sysctl->interface_version);
591      return;
592   }
593
594#define __PRE_XEN_SYSCTL_READ(_sysctl, _union, _field)			\
595      PRE_MEM_READ("XEN_SYSCTL_" #_sysctl " u." #_union "." #_field,	\
596                   (Addr)&sysctl->u._union._field,			\
597                   sizeof(sysctl->u._union._field))
598#define PRE_XEN_SYSCTL_READ(_sysctl, _field) \
599      __PRE_XEN_SYSCTL_READ(_sysctl, _sysctl, _field)
600
601   switch (sysctl->cmd) {
602   case VKI_XEN_SYSCTL_readconsole:
603       /* These are all unconditionally read */
604       PRE_XEN_SYSCTL_READ(readconsole, clear);
605       PRE_XEN_SYSCTL_READ(readconsole, incremental);
606       PRE_XEN_SYSCTL_READ(readconsole, buffer);
607       PRE_XEN_SYSCTL_READ(readconsole, count);
608
609       /* 'index' only read if 'incremental' is nonzero */
610       if (sysctl->u.readconsole.incremental)
611           PRE_XEN_SYSCTL_READ(readconsole, index);
612       break;
613
614   case VKI_XEN_SYSCTL_getdomaininfolist:
615      switch (sysctl->interface_version)
616      {
617      case 0x00000008:
618	 PRE_XEN_SYSCTL_READ(getdomaininfolist_00000008, first_domain);
619	 PRE_XEN_SYSCTL_READ(getdomaininfolist_00000008, max_domains);
620	 PRE_XEN_SYSCTL_READ(getdomaininfolist_00000008, buffer);
621	 break;
622      case 0x00000009:
623	 PRE_XEN_SYSCTL_READ(getdomaininfolist_00000009, first_domain);
624	 PRE_XEN_SYSCTL_READ(getdomaininfolist_00000009, max_domains);
625	 PRE_XEN_SYSCTL_READ(getdomaininfolist_00000009, buffer);
626	 break;
627      case 0x0000000a:
628      case 0x0000000b:
629	 PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, first_domain);
630	 PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, max_domains);
631	 PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, buffer);
632	 break;
633      default:
634          VG_(dmsg)("WARNING: XEN_SYSCTL_getdomaininfolist for sysctl version "
635                    "%"PRIx32" not implemented yet\n",
636                    sysctl->interface_version);
637          SET_STATUS_Failure(VKI_EINVAL);
638          return;
639      }
640      break;
641
642   case VKI_XEN_SYSCTL_debug_keys:
643       PRE_XEN_SYSCTL_READ(debug_keys, keys);
644       PRE_XEN_SYSCTL_READ(debug_keys, nr_keys);
645       PRE_MEM_READ("XEN_SYSCTL_debug_keys *keys",
646                    (Addr)sysctl->u.debug_keys.keys.p,
647                    sysctl->u.debug_keys.nr_keys * sizeof(char));
648       break;
649
650   case VKI_XEN_SYSCTL_sched_id:
651       /* No inputs */
652       break;
653
654   case VKI_XEN_SYSCTL_cpupool_op:
655      PRE_XEN_SYSCTL_READ(cpupool_op, op);
656
657      switch(sysctl->u.cpupool_op.op) {
658      case VKI_XEN_SYSCTL_CPUPOOL_OP_CREATE:
659      case VKI_XEN_SYSCTL_CPUPOOL_OP_DESTROY:
660      case VKI_XEN_SYSCTL_CPUPOOL_OP_INFO:
661      case VKI_XEN_SYSCTL_CPUPOOL_OP_ADDCPU:
662      case VKI_XEN_SYSCTL_CPUPOOL_OP_RMCPU:
663      case VKI_XEN_SYSCTL_CPUPOOL_OP_MOVEDOMAIN:
664         PRE_XEN_SYSCTL_READ(cpupool_op, cpupool_id);
665      }
666
667      if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_CREATE)
668         PRE_XEN_SYSCTL_READ(cpupool_op, sched_id);
669
670      if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_MOVEDOMAIN)
671         PRE_XEN_SYSCTL_READ(cpupool_op, domid);
672
673      if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_ADDCPU ||
674          sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_RMCPU)
675         PRE_XEN_SYSCTL_READ(cpupool_op, cpu);
676
677      break;
678
679   case VKI_XEN_SYSCTL_physinfo:
680      /* No input params */
681      break;
682
683   case VKI_XEN_SYSCTL_topologyinfo:
684      PRE_XEN_SYSCTL_READ(topologyinfo, max_cpu_index);
685      PRE_XEN_SYSCTL_READ(topologyinfo, cpu_to_core);
686      PRE_XEN_SYSCTL_READ(topologyinfo, cpu_to_socket);
687      PRE_XEN_SYSCTL_READ(topologyinfo, cpu_to_node);
688      break;
689
690   case VKI_XEN_SYSCTL_numainfo:
691      PRE_XEN_SYSCTL_READ(numainfo, max_node_index);
692      PRE_XEN_SYSCTL_READ(numainfo, node_to_memsize);
693      PRE_XEN_SYSCTL_READ(numainfo, node_to_memfree);
694      PRE_XEN_SYSCTL_READ(numainfo, node_to_node_distance);
695      break;
696
697   default:
698      bad_subop(tid, layout, arrghs, status, flags,
699                "__HYPERVISOR_sysctl", sysctl->cmd);
700      break;
701   }
702#undef PRE_XEN_SYSCTL_READ
703#undef __PRE_XEN_SYSCTL_READ
704}
705
706PRE(domctl)
707{
708   struct vki_xen_domctl *domctl = (struct vki_xen_domctl *)ARG1;
709
710   PRINT("__HYPERVISOR_domctl ( %u ) on dom%d", domctl->cmd, domctl->domain);
711
712   /*
713    * Common part of xen_domctl:
714    *    vki_uint32_t cmd;
715    *    vki_uint32_t interface_version;
716    *    vki_xen_domid_t  domain;
717    */
718   PRE_MEM_READ("__HYPERVISOR_domctl", ARG1,
719                sizeof(vki_uint32_t) + sizeof(vki_uint32_t)
720		+ sizeof(vki_xen_domid_t));
721
722   if (!domctl)
723      return;
724
725   switch (domctl->interface_version)
726   {
727   case 0x00000007:
728   case 0x00000008:
729   case 0x00000009:
730   case 0x0000000a:
731   case 0x0000000b:
732   case 0x0000000c:
733	   break;
734   default:
735      bad_intf_version(tid, layout, arrghs, status, flags,
736                       "__HYPERVISOR_domctl", domctl->interface_version);
737      return;
738   }
739
740#define __PRE_XEN_DOMCTL_READ(_domctl, _union, _field)			\
741      PRE_MEM_READ("XEN_DOMCTL_" #_domctl " u." #_union "." #_field,	\
742                   (Addr)&domctl->u._union._field,			\
743                   sizeof(domctl->u._union._field))
744#define PRE_XEN_DOMCTL_READ(_domctl, _field) \
745      __PRE_XEN_DOMCTL_READ(_domctl, _domctl, _field)
746
747   switch (domctl->cmd) {
748   case VKI_XEN_DOMCTL_destroydomain:
749   case VKI_XEN_DOMCTL_pausedomain:
750   case VKI_XEN_DOMCTL_max_vcpus:
751   case VKI_XEN_DOMCTL_get_address_size:
752   case VKI_XEN_DOMCTL_gettscinfo:
753   case VKI_XEN_DOMCTL_getdomaininfo:
754   case VKI_XEN_DOMCTL_unpausedomain:
755   case VKI_XEN_DOMCTL_resumedomain:
756      /* No input fields. */
757      break;
758
759   case VKI_XEN_DOMCTL_createdomain:
760      PRE_XEN_DOMCTL_READ(createdomain, ssidref);
761      PRE_XEN_DOMCTL_READ(createdomain, handle);
762      PRE_XEN_DOMCTL_READ(createdomain, flags);
763      break;
764
765   case VKI_XEN_DOMCTL_gethvmcontext:
766       /* Xen unconditionally reads the 'buffer' pointer */
767       __PRE_XEN_DOMCTL_READ(gethvmcontext, hvmcontext, buffer);
768       /* Xen only consumes 'size' if 'buffer' is non NULL. A NULL
769        * buffer is a request for the required size. */
770       if ( domctl->u.hvmcontext.buffer.p )
771           __PRE_XEN_DOMCTL_READ(gethvmcontext, hvmcontext, size);
772       break;
773
774   case VKI_XEN_DOMCTL_sethvmcontext:
775       __PRE_XEN_DOMCTL_READ(sethvmcontext, hvmcontext, size);
776       __PRE_XEN_DOMCTL_READ(sethvmcontext, hvmcontext, buffer);
777       PRE_MEM_READ("XEN_DOMCTL_sethvmcontext *buffer",
778                    (Addr)domctl->u.hvmcontext.buffer.p,
779                    domctl->u.hvmcontext.size);
780       break;
781
782   case VKI_XEN_DOMCTL_gethvmcontext_partial:
783       __PRE_XEN_DOMCTL_READ(gethvmcontext_partial, hvmcontext_partial, type);
784       __PRE_XEN_DOMCTL_READ(gethvmcontext_partial, hvmcontext_partial, instance);
785       __PRE_XEN_DOMCTL_READ(gethvmcontext_partial, hvmcontext_partial, buffer);
786
787       switch (domctl->u.hvmcontext_partial.type) {
788       case VKI_HVM_SAVE_CODE(CPU):
789           if ( domctl->u.hvmcontext_partial.buffer.p )
790                PRE_MEM_WRITE("XEN_DOMCTL_gethvmcontext_partial *buffer",
791                   (Addr)domctl->u.hvmcontext_partial.buffer.p,
792                   VKI_HVM_SAVE_LENGTH(CPU));
793           break;
794       case VKI_HVM_SAVE_CODE(MTRR):
795           if ( domctl->u.hvmcontext_partial.buffer.p )
796	        PRE_MEM_WRITE("XEN_DOMCTL_gethvmcontext_partial *buffer",
797		   (Addr)domctl->u.hvmcontext_partial.buffer.p,
798		   VKI_HVM_SAVE_LENGTH(MTRR));
799           break;
800       default:
801           bad_subop(tid, layout, arrghs, status, flags,
802                         "__HYPERVISOR_domctl_gethvmcontext_partial type",
803                         domctl->u.hvmcontext_partial.type);
804           break;
805       }
806       break;
807
808   case VKI_XEN_DOMCTL_max_mem:
809      PRE_XEN_DOMCTL_READ(max_mem, max_memkb);
810      break;
811
812   case VKI_XEN_DOMCTL_set_address_size:
813      __PRE_XEN_DOMCTL_READ(set_address_size, address_size, size);
814      break;
815
816   case VKI_XEN_DOMCTL_test_assign_device:
817      switch (domctl->interface_version) {
818      case 0x00000007: /* pre-4.6 */
819      case 0x00000008:
820      case 0x00000009:
821      case 0x0000000a:
822         __PRE_XEN_DOMCTL_READ(test_assign_device, assign_device_00000007, machine_sbdf);
823         break;
824      case 0x0000000b:
825         __PRE_XEN_DOMCTL_READ(test_assign_device, assign_device_0000000b, dev);
826         __PRE_XEN_DOMCTL_READ(test_assign_device, assign_device_0000000b, flag);
827         switch (domctl->u.assign_device_0000000b.dev) {
828         case VKI_XEN_DOMCTL_DEV_PCI:
829            __PRE_XEN_DOMCTL_READ(test_assign_device, assign_device_0000000b, u.pci);
830            break;
831         case VKI_XEN_DOMCTL_DEV_DT:
832            __PRE_XEN_DOMCTL_READ(test_assign_device, assign_device_0000000b, u.dt);
833            PRE_MEM_READ("XEN_DOMTCL_test_assign_device.dt",
834                          (Addr)domctl->u.assign_device_0000000b.u.dt.path.p,
835                          domctl->u.assign_device_0000000b.u.dt.size);
836            break;
837         default:
838            bad_subop(tid, layout, arrghs, status, flags,
839                         "__HYPERVISOR_domctl_test_assign_device dev",
840                         domctl->u.assign_device_0000000b.dev);
841            break;
842         }
843         break;
844      }
845      break;
846   case VKI_XEN_DOMCTL_assign_device:
847      switch (domctl->interface_version) {
848      case 0x00000007: /* pre-4.6 */
849      case 0x00000008:
850      case 0x00000009:
851      case 0x0000000a:
852         __PRE_XEN_DOMCTL_READ(assign_device, assign_device_00000007, machine_sbdf);
853         break;
854      case 0x0000000b:
855         __PRE_XEN_DOMCTL_READ(assign_device, assign_device_0000000b, dev);
856         __PRE_XEN_DOMCTL_READ(assign_device, assign_device_0000000b, flag);
857         switch (domctl->u.assign_device_0000000b.dev) {
858         case VKI_XEN_DOMCTL_DEV_PCI:
859            __PRE_XEN_DOMCTL_READ(assign_device, assign_device_0000000b, u.pci);
860            break;
861         case VKI_XEN_DOMCTL_DEV_DT:
862            __PRE_XEN_DOMCTL_READ(assign_device, assign_device_0000000b, u.dt);
863            PRE_MEM_READ("XEN_DOMTCL_assign_device.dt",
864                          (Addr)domctl->u.assign_device_0000000b.u.dt.path.p,
865                          domctl->u.assign_device_0000000b.u.dt.size);
866            break;
867         default:
868            bad_subop(tid, layout, arrghs, status, flags,
869                         "__HYPERVISOR_domctl_assign_device dev",
870                         domctl->u.assign_device_0000000b.dev);
871            break;
872         }
873         break;
874      }
875      break;
876   case VKI_XEN_DOMCTL_deassign_device:
877      switch (domctl->interface_version) {
878      case 0x00000007: /* pre-4.6 */
879      case 0x00000008:
880      case 0x00000009:
881      case 0x0000000a:
882         __PRE_XEN_DOMCTL_READ(deassign_device, assign_device_00000007, machine_sbdf);
883         break;
884      case 0x0000000b:
885         __PRE_XEN_DOMCTL_READ(deassign_device, assign_device_0000000b, dev);
886         __PRE_XEN_DOMCTL_READ(deassign_device, assign_device_0000000b, flag);
887         switch (domctl->u.assign_device_0000000b.dev) {
888         case VKI_XEN_DOMCTL_DEV_PCI:
889            __PRE_XEN_DOMCTL_READ(deassign_device, assign_device_0000000b, u.pci);
890            break;
891         case VKI_XEN_DOMCTL_DEV_DT:
892            __PRE_XEN_DOMCTL_READ(deassign_device, assign_device_0000000b, u.dt);
893            PRE_MEM_READ("XEN_DOMTCL_assign_device.dt",
894                          (Addr)domctl->u.assign_device_0000000b.u.dt.path.p,
895                          domctl->u.assign_device_0000000b.u.dt.size);
896            break;
897         default:
898            bad_subop(tid, layout, arrghs, status, flags,
899                         "__HYPERVISOR_domctl_deassign_device dev",
900                         domctl->u.assign_device_0000000b.dev);
901            break;
902         }
903         break;
904      }
905      break;
906
907   case VKI_XEN_DOMCTL_settscinfo:
908      switch (domctl->interface_version) {
909      case 0x00000007: /* pre-4.6 */
910      case 0x00000008:
911      case 0x00000009:
912      case 0x0000000a:
913         __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_00000007, info.tsc_mode);
914         __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_00000007, info.gtsc_khz);
915         __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_00000007, info.incarnation);
916         __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_00000007, info.elapsed_nsec);
917         break;
918      case 0x0000000b:
919         __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_0000000b, tsc_mode);
920         __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_0000000b, gtsc_khz);
921         __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_0000000b, incarnation);
922         __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info_0000000b, elapsed_nsec);
923         break;
924      }
925      break;
926
927   case VKI_XEN_DOMCTL_irq_permission:
928      PRE_XEN_DOMCTL_READ(irq_permission, pirq);
929      PRE_XEN_DOMCTL_READ(irq_permission, allow_access);
930      break;
931
932   case VKI_XEN_DOMCTL_iomem_permission:
933      PRE_XEN_DOMCTL_READ(iomem_permission, first_mfn);
934      PRE_XEN_DOMCTL_READ(iomem_permission, nr_mfns);
935      PRE_XEN_DOMCTL_READ(iomem_permission, allow_access);
936      break;
937
938   case VKI_XEN_DOMCTL_ioport_permission:
939      PRE_XEN_DOMCTL_READ(ioport_permission, first_port);
940      PRE_XEN_DOMCTL_READ(ioport_permission, nr_ports);
941      PRE_XEN_DOMCTL_READ(ioport_permission, allow_access);
942      break;
943
944   case VKI_XEN_DOMCTL_hypercall_init:
945      PRE_XEN_DOMCTL_READ(hypercall_init, gmfn);
946      break;
947
948   case VKI_XEN_DOMCTL_settimeoffset:
949       PRE_XEN_DOMCTL_READ(settimeoffset, time_offset_seconds);
950       break;
951
952   case VKI_XEN_DOMCTL_getvcpuinfo:
953      PRE_XEN_DOMCTL_READ(getvcpuinfo, vcpu);
954      break;
955
956   case VKI_XEN_DOMCTL_scheduler_op:
957      PRE_XEN_DOMCTL_READ(scheduler_op, sched_id);
958      PRE_XEN_DOMCTL_READ(scheduler_op, cmd);
959      if ( domctl->u.scheduler_op.cmd == VKI_XEN_DOMCTL_SCHEDOP_putinfo ) {
960         switch(domctl->u.scheduler_op.sched_id) {
961         case VKI_XEN_SCHEDULER_SEDF:
962            PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.period);
963            PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.slice);
964            PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.latency);
965            PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.extratime);
966            PRE_XEN_DOMCTL_READ(scheduler_op, u.sedf.weight);
967            break;
968         case VKI_XEN_SCHEDULER_CREDIT:
969            PRE_XEN_DOMCTL_READ(scheduler_op, u.credit.weight);
970            PRE_XEN_DOMCTL_READ(scheduler_op, u.credit.cap);
971            break;
972         case VKI_XEN_SCHEDULER_CREDIT2:
973            PRE_XEN_DOMCTL_READ(scheduler_op, u.credit2.weight);
974            break;
975         case VKI_XEN_SCHEDULER_RTDS:
976            PRE_XEN_DOMCTL_READ(scheduler_op, u.rtds.period);
977            PRE_XEN_DOMCTL_READ(scheduler_op, u.rtds.budget);
978            break;
979         case VKI_XEN_SCHEDULER_ARINC653:
980            break;
981         }
982      }
983      break;
984
985   case VKI_XEN_DOMCTL_getvcpuaffinity:
986      switch (domctl->interface_version) {
987      case 0x00000007:
988      case 0x00000008:
989      case 0x00000009:
990         __PRE_XEN_DOMCTL_READ(getvcpuaffinity, vcpuaffinity_00000009, vcpu);
991         __PRE_XEN_DOMCTL_READ(getvcpuaffinity, vcpuaffinity_00000009, cpumap.nr_bits);
992         break;
993      case 0x0000000a:
994         __PRE_XEN_DOMCTL_READ(getvcpuaffinity, vcpuaffinity_0000000a, vcpu);
995         if (domctl->u.vcpuaffinity_0000000a.flags & VKI_XEN_VCPUAFFINITY_HARD)
996            __PRE_XEN_DOMCTL_READ(
997               setvcpuaffinity, vcpuaffinity_0000000a, cpumap_hard.nr_bits);
998         if (domctl->u.vcpuaffinity_0000000a.flags & VKI_XEN_VCPUAFFINITY_SOFT)
999            __PRE_XEN_DOMCTL_READ(
1000               setvcpuaffinity, vcpuaffinity_0000000a, cpumap_soft.nr_bits);
1001         break;
1002      }
1003      break;
1004
1005   case VKI_XEN_DOMCTL_setvcpuaffinity:
1006      switch (domctl->interface_version) {
1007      case 0x00000007:
1008      case 0x00000008:
1009      case 0x00000009:
1010         __PRE_XEN_DOMCTL_READ(setvcpuaffinity, vcpuaffinity_00000009, vcpu);
1011         __PRE_XEN_DOMCTL_READ(setvcpuaffinity, vcpuaffinity_00000009, cpumap.nr_bits);
1012         PRE_MEM_READ("XEN_DOMCTL_setvcpuaffinity u.vcpuaffinity.cpumap.bitmap",
1013                      (Addr)domctl->u.vcpuaffinity_00000009.cpumap.bitmap.p,
1014                      domctl->u.vcpuaffinity_00000009.cpumap.nr_bits / 8);
1015         break;
1016      case 0x0000000a:
1017         __PRE_XEN_DOMCTL_READ(setvcpuaffinity, vcpuaffinity_0000000a, vcpu);
1018         __PRE_XEN_DOMCTL_READ(setvcpuaffinity, vcpuaffinity_0000000a, flags);
1019         if (domctl->u.vcpuaffinity_0000000a.flags & VKI_XEN_VCPUAFFINITY_HARD) {
1020            __PRE_XEN_DOMCTL_READ(
1021               setvcpuaffinity, vcpuaffinity_0000000a, cpumap_hard.nr_bits);
1022            PRE_MEM_READ(
1023               "XEN_DOMCTL_setvcpuaffinity u.vcpuaffinity.cpumap_hard.bitmap",
1024               (Addr)domctl->u.vcpuaffinity_0000000a.cpumap_hard.bitmap.p,
1025               domctl->u.vcpuaffinity_0000000a.cpumap_hard.nr_bits / 8);
1026         }
1027         if (domctl->u.vcpuaffinity_0000000a.flags & VKI_XEN_VCPUAFFINITY_SOFT) {
1028            __PRE_XEN_DOMCTL_READ(
1029               setvcpuaffinity, vcpuaffinity_0000000a, cpumap_soft.nr_bits);
1030            PRE_MEM_READ(
1031               "XEN_DOMCTL_setvcpuaffinity u.vcpuaffinity.cpumap_soft.bitmap",
1032               (Addr)domctl->u.vcpuaffinity_0000000a.cpumap_soft.bitmap.p,
1033               domctl->u.vcpuaffinity_0000000a.cpumap_soft.nr_bits / 8);
1034         }
1035      break;
1036      }
1037      break;
1038
1039   case VKI_XEN_DOMCTL_getnodeaffinity:
1040      __PRE_XEN_DOMCTL_READ(nodeaffinity, nodeaffinity, nodemap.nr_bits);
1041      break;
1042   case VKI_XEN_DOMCTL_setnodeaffinity:
1043      __PRE_XEN_DOMCTL_READ(nodeaffinity, nodeaffinity, nodemap.nr_bits);
1044      PRE_MEM_READ("XEN_DOMCTL_setnodeaffinity u.nodeaffinity.cpumap.bitmap",
1045                   (Addr)domctl->u.nodeaffinity.nodemap.bitmap.p,
1046                   domctl->u.nodeaffinity.nodemap.nr_bits / 8);
1047      break;
1048
1049   case VKI_XEN_DOMCTL_getvcpucontext:
1050      __PRE_XEN_DOMCTL_READ(getvcpucontext, vcpucontext, vcpu);
1051      break;
1052
1053   case VKI_XEN_DOMCTL_setvcpucontext:
1054      __PRE_XEN_DOMCTL_READ(setvcpucontext, vcpucontext, vcpu);
1055      __PRE_XEN_DOMCTL_READ(setvcpucontext, vcpucontext, ctxt.p);
1056      break;
1057
1058   case VKI_XEN_DOMCTL_pin_mem_cacheattr:
1059      PRE_XEN_DOMCTL_READ(pin_mem_cacheattr, start);
1060      PRE_XEN_DOMCTL_READ(pin_mem_cacheattr, end);
1061      PRE_XEN_DOMCTL_READ(pin_mem_cacheattr, type);
1062      break;
1063
1064   case VKI_XEN_DOMCTL_get_ext_vcpucontext:
1065      switch (domctl->interface_version)
1066      {
1067      case 0x00000007:
1068      case 0x00000008:
1069         __PRE_XEN_DOMCTL_READ(get_ext_vcpucontext, ext_vcpucontext_00000008, vcpu);
1070         break;
1071
1072      case 0x00000009:
1073         __PRE_XEN_DOMCTL_READ(get_ext_vcpucontext, ext_vcpucontext_00000009, vcpu);
1074         break;
1075
1076      default:
1077         VG_(dmsg)("WARNING: VKI_XEN_DOMCTL_get_ext_vcpucontext  domctl version %#"
1078                   PRIx32" not implemented\n", domctl->interface_version);
1079         SET_STATUS_Failure(VKI_EINVAL);
1080         break;
1081      }
1082      break;
1083
1084   case VKI_XEN_DOMCTL_set_ext_vcpucontext:
1085       switch (domctl->interface_version)
1086       {
1087       case 0x00000007:
1088       case 0x00000008:
1089           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008, vcpu);
1090           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008, size);
1091#if defined(__i386__) || defined(__x86_64__)
1092           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008,
1093                                 syscall32_callback_eip);
1094           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008,
1095                                 sysenter_callback_eip);
1096           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008,
1097                                 syscall32_callback_cs);
1098           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008,
1099                                 sysenter_callback_cs);
1100           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008,
1101                                 syscall32_disables_events);
1102           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008,
1103                                 sysenter_disables_events);
1104
1105           if ( domctl->u.ext_vcpucontext_00000008.size >=
1106                offsetof(struct vki_xen_domctl_ext_vcpucontext_00000008, mcg_cap) )
1107               __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000008,
1108                                     mcg_cap);
1109#endif
1110           break;
1111
1112       case 0x00000009:
1113           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009, vcpu);
1114           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009, size);
1115#if defined(__i386__) || defined(__x86_64__)
1116           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009,
1117                                 syscall32_callback_eip);
1118           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009,
1119                                 sysenter_callback_eip);
1120           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009,
1121                                 syscall32_callback_cs);
1122           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009,
1123                                 sysenter_callback_cs);
1124           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009,
1125                                 syscall32_disables_events);
1126           __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009,
1127                                 sysenter_disables_events);
1128
1129           if ( domctl->u.ext_vcpucontext_00000009.size >=
1130                offsetof(struct vki_xen_domctl_ext_vcpucontext_00000009, caps) )
1131           {
1132               __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009,
1133                                     caps);
1134               __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009,
1135                                     mci_ctl2_bank0);
1136               __PRE_XEN_DOMCTL_READ(set_ext_vcpucontext, ext_vcpucontext_00000009,
1137                                     mci_ctl2_bank1);
1138           }
1139#endif
1140	   break;
1141
1142       default:
1143           VG_(dmsg)("WARNING: VKI_XEN_DOMCTL_set_ext_vcpucontext  domctl version %#"
1144                     PRIx32" not implemented\n", domctl->interface_version);
1145           SET_STATUS_Failure(VKI_EINVAL);
1146           break;
1147       }
1148       break;
1149
1150   case VKI_XEN_DOMCTL_set_cpuid:
1151      PRE_MEM_READ("XEN_DOMCTL_set_cpuid u.cpuid",
1152                   (Addr)&domctl->u.cpuid, sizeof(domctl->u.cpuid));
1153      break;
1154
1155   case VKI_XEN_DOMCTL_getpageframeinfo3:
1156       PRE_XEN_DOMCTL_READ(getpageframeinfo3, num);
1157       PRE_XEN_DOMCTL_READ(getpageframeinfo3, array.p);
1158       PRE_MEM_READ("XEN_DOMCTL_getpageframeinfo3 *u.getpageframeinfo3.array.p",
1159                    (Addr)domctl->u.getpageframeinfo3.array.p,
1160                    domctl->u.getpageframeinfo3.num * sizeof(vki_xen_pfn_t));
1161       break;
1162
1163   case VKI_XEN_DOMCTL_setvcpuextstate:
1164      __PRE_XEN_DOMCTL_READ(setvcpuextstate, vcpuextstate, vcpu);
1165      __PRE_XEN_DOMCTL_READ(setvcpuextstate, vcpuextstate, size);
1166      __PRE_XEN_DOMCTL_READ(setvcpuextstate, vcpuextstate, buffer);
1167      PRE_MEM_READ("XEN_DOMCTL_setvcpuextstate *u.vcpuextstate.buffer.p",
1168                   (Addr)domctl->u.vcpuextstate.buffer.p,
1169                   domctl->u.vcpuextstate.size);
1170      break;
1171
1172   case VKI_XEN_DOMCTL_getvcpuextstate:
1173      __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, vcpu);
1174      __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, xfeature_mask);
1175      __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, size);
1176      __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, buffer);
1177      break;
1178
1179   case VKI_XEN_DOMCTL_shadow_op:
1180       PRE_XEN_DOMCTL_READ(shadow_op, op);
1181
1182       switch(domctl->u.shadow_op.op)
1183       {
1184       case VKI_XEN_DOMCTL_SHADOW_OP_OFF:
1185       case VKI_XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION:
1186           /* No further inputs */
1187           break;
1188
1189       case VKI_XEN_DOMCTL_SHADOW_OP_ENABLE:
1190           PRE_XEN_DOMCTL_READ(shadow_op, mode);
1191           switch(domctl->u.shadow_op.mode)
1192           {
1193           case XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY:
1194               goto domctl_shadow_op_enable_logdirty;
1195
1196
1197           default:
1198               bad_subop(tid, layout, arrghs, status, flags,
1199                         "__HYPERVISOR_domctl shadowop mode",
1200                         domctl->u.shadow_op.mode);
1201               break;
1202           }
1203
1204       case VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY:
1205       domctl_shadow_op_enable_logdirty:
1206           /* No further inputs */
1207           break;
1208
1209       case VKI_XEN_DOMCTL_SHADOW_OP_CLEAN:
1210       case VKI_XEN_DOMCTL_SHADOW_OP_PEEK:
1211           PRE_XEN_DOMCTL_READ(shadow_op, dirty_bitmap);
1212           PRE_XEN_DOMCTL_READ(shadow_op, pages);
1213           break;
1214
1215       case VKI_XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION:
1216           PRE_XEN_DOMCTL_READ(shadow_op, mb);
1217           break;
1218
1219       default:
1220           bad_subop(tid, layout, arrghs, status, flags,
1221                     "__HYPERVISOR_domctl shadow(10)",
1222                     domctl->u.shadow_op.op);
1223           break;
1224       }
1225       break;
1226
1227   case VKI_XEN_DOMCTL_set_max_evtchn:
1228      PRE_XEN_DOMCTL_READ(set_max_evtchn, max_port);
1229      break;
1230
1231   case VKI_XEN_DOMCTL_cacheflush:
1232      PRE_XEN_DOMCTL_READ(cacheflush, start_pfn);
1233      PRE_XEN_DOMCTL_READ(cacheflush, nr_pfns);
1234      break;
1235
1236   case VKI_XEN_DOMCTL_set_access_required:
1237      PRE_XEN_DOMCTL_READ(access_required, access_required);
1238      break;
1239
1240   case VKI_XEN_DOMCTL_mem_event_op:
1241   //case VKI_XEN_DOMCTL_vm_event_op: /* name change in 4.6 */
1242      switch (domctl->interface_version) {
1243      case 0x00000007: /* pre-4.6 */
1244      case 0x00000008:
1245      case 0x00000009:
1246      case 0x0000000a:
1247         __PRE_XEN_DOMCTL_READ(mem_event_op, mem_event_op_00000007, op);
1248         __PRE_XEN_DOMCTL_READ(mem_event_op, mem_event_op_00000007, mode);
1249         break;
1250      case 0x0000000b:
1251         __PRE_XEN_DOMCTL_READ(vm_event_op, vm_event_op_0000000b, op);
1252         __PRE_XEN_DOMCTL_READ(vm_event_op, vm_event_op_0000000b, mode);
1253         break;
1254      }
1255      break;
1256
1257   case VKI_XEN_DOMCTL_debug_op:
1258      PRE_XEN_DOMCTL_READ(debug_op, op);
1259      PRE_XEN_DOMCTL_READ(debug_op, vcpu);
1260      break;
1261
1262   case VKI_XEN_DOMCTL_get_vcpu_msrs:
1263      __PRE_XEN_DOMCTL_READ(get_vcpu_msrs, vcpu_msrs, vcpu);
1264      __PRE_XEN_DOMCTL_READ(get_vcpu_msrs, vcpu_msrs, msr_count);
1265      __PRE_XEN_DOMCTL_READ(get_vcpu_msrs, vcpu_msrs, msrs);
1266      break;
1267
1268   case VKI_XEN_DOMCTL_set_vcpu_msrs:
1269      __PRE_XEN_DOMCTL_READ(set_vcpu_msrs, vcpu_msrs, vcpu);
1270      __PRE_XEN_DOMCTL_READ(set_vcpu_msrs, vcpu_msrs, msr_count);
1271      __PRE_XEN_DOMCTL_READ(set_vcpu_msrs, vcpu_msrs, msrs);
1272      PRE_MEM_READ("XEN_DOMCTL_set_vcpu_msrs *u.vcpu_msrs.msrs.p",
1273                   (Addr)domctl->u.vcpu_msrs.msrs.p,
1274                   sizeof(vki_xen_domctl_vcpu_msr_t) *
1275                   domctl->u.vcpu_msrs.msr_count);
1276      break;
1277
1278   case VKI_XEN_DOMCTL_monitor_op:
1279      switch (domctl->interface_version) {
1280      case 0x000000b:
1281          if (domctl->u.monitor_op_0000000b.op == VKI_XEN_DOMCTL_MONITOR_OP_ENABLE ||
1282              domctl->u.monitor_op_0000000b.op == VKI_XEN_DOMCTL_MONITOR_OP_ENABLE) {
1283             switch (domctl->u.monitor_op_0000000b.event) {
1284             case VKI_XEN_DOMCTL_MONITOR_EVENT_WRITE_CTRLREG:
1285                __PRE_XEN_DOMCTL_READ(monitor_op, monitor_op_0000000b, u.mov_to_cr);
1286                break;
1287             case VKI_XEN_DOMCTL_MONITOR_EVENT_MOV_TO_MSR:
1288                __PRE_XEN_DOMCTL_READ(monitor_op, monitor_op_0000000b, u.mov_to_msr);
1289                break;
1290             case VKI_XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST:
1291                __PRE_XEN_DOMCTL_READ(monitor_op, monitor_op_0000000b, u.guest_request);
1292                break;
1293             case VKI_XEN_DOMCTL_MONITOR_OP_GET_CAPABILITIES:
1294                break;
1295             }
1296          }
1297
1298         break;
1299      }
1300      break;
1301
1302   default:
1303      bad_subop(tid, layout, arrghs, status, flags,
1304                "__HYPERVISOR_domctl", domctl->cmd);
1305      break;
1306   }
1307#undef PRE_XEN_DOMCTL_READ
1308#undef __PRE_XEN_DOMCTL_READ
1309}
1310
1311PRE(hvm_op)
1312{
1313   unsigned long op = ARG1;
1314   void *arg = (void *)(unsigned long)ARG2;
1315
1316   PRINT("__HYPERVISOR_hvm_op ( %ld, %#lx )", SARG1, ARG2);
1317
1318#define __PRE_XEN_HVMOP_READ(_hvm_op, _type, _field)    \
1319   PRE_MEM_READ("XEN_HVMOP_" # _hvm_op " " #_field,     \
1320                (Addr)&((_type*)arg)->_field,           \
1321                sizeof(((_type*)arg)->_field))
1322#define PRE_XEN_HVMOP_READ(_hvm_op, _field)                             \
1323   __PRE_XEN_HVMOP_READ(_hvm_op, vki_xen_hvm_ ## _hvm_op ## _t, _field)
1324
1325   switch (op) {
1326   case VKI_XEN_HVMOP_set_param:
1327      __PRE_XEN_HVMOP_READ(set_param, struct vki_xen_hvm_param, domid);
1328      __PRE_XEN_HVMOP_READ(set_param, struct vki_xen_hvm_param, index);
1329      __PRE_XEN_HVMOP_READ(set_param, struct vki_xen_hvm_param, value);
1330      break;
1331
1332   case VKI_XEN_HVMOP_get_param:
1333      __PRE_XEN_HVMOP_READ(get_param, struct vki_xen_hvm_param, domid);
1334      __PRE_XEN_HVMOP_READ(get_param, struct vki_xen_hvm_param, index);
1335      break;
1336
1337   case VKI_XEN_HVMOP_set_pci_intx_level:
1338      PRE_XEN_HVMOP_READ(set_pci_intx_level, domid);
1339      PRE_XEN_HVMOP_READ(set_pci_intx_level, domain);
1340      PRE_XEN_HVMOP_READ(set_pci_intx_level, bus);
1341      PRE_XEN_HVMOP_READ(set_pci_intx_level, device);
1342      PRE_XEN_HVMOP_READ(set_pci_intx_level, level);
1343      break;
1344
1345   case VKI_XEN_HVMOP_set_isa_irq_level:
1346      PRE_XEN_HVMOP_READ(set_isa_irq_level, domid);
1347      PRE_XEN_HVMOP_READ(set_isa_irq_level, isa_irq);
1348      PRE_XEN_HVMOP_READ(set_isa_irq_level, level);
1349      break;
1350
1351   case VKI_XEN_HVMOP_set_pci_link_route:
1352      PRE_XEN_HVMOP_READ(set_pci_link_route, domid);
1353      PRE_XEN_HVMOP_READ(set_pci_link_route, link);
1354      PRE_XEN_HVMOP_READ(set_pci_link_route, isa_irq);
1355      break;
1356
1357   case VKI_XEN_HVMOP_track_dirty_vram: {
1358      vki_xen_hvm_track_dirty_vram_t *Arg =
1359         (vki_xen_hvm_track_dirty_vram_t*)ARG2;
1360      PRE_XEN_HVMOP_READ(track_dirty_vram, domid);
1361      PRE_XEN_HVMOP_READ(track_dirty_vram, nr);
1362      if ( Arg->nr ) {
1363         PRE_XEN_HVMOP_READ(track_dirty_vram, first_pfn);
1364         PRE_XEN_HVMOP_READ(track_dirty_vram, dirty_bitmap);
1365      }
1366      break;
1367   }
1368
1369   case VKI_XEN_HVMOP_set_mem_type:
1370      PRE_XEN_HVMOP_READ(set_mem_type, domid);
1371      PRE_XEN_HVMOP_READ(set_mem_type, hvmmem_type);
1372      PRE_XEN_HVMOP_READ(set_mem_type, nr);
1373      PRE_XEN_HVMOP_READ(set_mem_type, first_pfn);
1374      break;
1375
1376   case VKI_XEN_HVMOP_set_mem_access:
1377      PRE_XEN_HVMOP_READ(set_mem_access, domid);
1378      PRE_XEN_HVMOP_READ(set_mem_access, hvmmem_access);
1379      PRE_XEN_HVMOP_READ(set_mem_access, first_pfn);
1380      /* if default access */
1381      if ( ((vki_xen_hvm_set_mem_access_t*)arg)->first_pfn != ~0ULL)
1382         PRE_XEN_HVMOP_READ(set_mem_access, nr);
1383      break;
1384
1385   case VKI_XEN_HVMOP_get_mem_access:
1386      PRE_XEN_HVMOP_READ(get_mem_access, domid);
1387      PRE_XEN_HVMOP_READ(get_mem_access, pfn);
1388
1389      PRE_MEM_WRITE("XEN_HVMOP_get_mem_access *hvmmem_access",
1390                    (Addr)&(((vki_xen_hvm_get_mem_access_t*)arg)->hvmmem_access),
1391                    sizeof(vki_uint16_t));
1392      break;
1393
1394   case VKI_XEN_HVMOP_inject_trap:
1395      PRE_XEN_HVMOP_READ(inject_trap, domid);
1396      PRE_XEN_HVMOP_READ(inject_trap, vcpuid);
1397      PRE_XEN_HVMOP_READ(inject_trap, vector);
1398      PRE_XEN_HVMOP_READ(inject_trap, type);
1399      PRE_XEN_HVMOP_READ(inject_trap, error_code);
1400      PRE_XEN_HVMOP_READ(inject_trap, insn_len);
1401      PRE_XEN_HVMOP_READ(inject_trap, cr2);
1402      break;
1403
1404   default:
1405      bad_subop(tid, layout, arrghs, status, flags,
1406                "__HYPERVISOR_hvm_op", op);
1407      break;
1408   }
1409#undef __PRE_XEN_HVMOP_READ
1410#undef PRE_XEN_HVMOP_READ
1411}
1412
1413PRE(tmem_op)
1414{
1415    struct vki_xen_tmem_op *tmem = (struct vki_xen_tmem_op *)ARG1;
1416
1417    PRINT("__HYPERVISOR_tmem_op ( %u )", tmem->cmd);
1418
1419    /* Common part for xen_tmem_op:
1420     *    vki_uint32_t cmd;
1421     */
1422    PRE_MEM_READ("__HYPERVISOR_tmem_op cmd", ARG1, sizeof(vki_uint32_t));
1423
1424
1425#define __PRE_XEN_TMEMOP_READ(_tmem, _union, _field)                    \
1426    PRE_MEM_READ("XEN_tmem_op_" #_tmem " u." #_union "." #_field,       \
1427                 (Addr)&tmem->u._union._field,                          \
1428                 sizeof(tmem->u._union._field))
1429#define PRE_XEN_TMEMOP_READ(_tmem, _field)                              \
1430    __PRE_XEN_TMEMOP_READ(_tmem, _tmem, _field)
1431
1432    switch(tmem->cmd) {
1433
1434    case VKI_XEN_TMEM_control:
1435
1436        /* Common part for control hypercall:
1437         *    vki_int32_t pool_id;
1438         *    vki_uint32_t subop;
1439         */
1440        PRE_MEM_READ("__HYPERVISOR_tmem_op pool_id",
1441                     (Addr)&tmem->pool_id, sizeof(tmem->pool_id));
1442        PRE_XEN_TMEMOP_READ(ctrl, subop);
1443
1444        switch (tmem->u.ctrl.subop) {
1445
1446        case VKI_XEN_TMEMC_save_begin:
1447            PRE_XEN_TMEMOP_READ(ctrl, cli_id);
1448            PRE_XEN_TMEMOP_READ(ctrl, arg1);
1449            PRE_XEN_TMEMOP_READ(ctrl, buf);
1450            break;
1451
1452        default:
1453            bad_subop(tid, layout, arrghs, status, flags,
1454                      "__HYPERVISOR_tmem_op_control", tmem->u.ctrl.subop);
1455        }
1456
1457        break;
1458
1459    default:
1460        bad_subop(tid, layout, arrghs, status, flags,
1461                  "__HYPERVISOR_tmem_op", ARG1);
1462    }
1463
1464#undef PRE_XEN_TMEMOP_READ
1465#undef __PRE_XEN_TMEMOP_READ
1466}
1467
1468POST(memory_op)
1469{
1470   switch (ARG1) {
1471   case VKI_XENMEM_maximum_ram_page:
1472   case VKI_XENMEM_set_memory_map:
1473   case VKI_XENMEM_decrease_reservation:
1474   case VKI_XENMEM_claim_pages:
1475   case VKI_XENMEM_maximum_gpfn:
1476   case VKI_XENMEM_remove_from_physmap:
1477   case VKI_XENMEM_access_op:
1478      /* No outputs */
1479      break;
1480   case VKI_XENMEM_increase_reservation:
1481   case VKI_XENMEM_populate_physmap: {
1482      struct xen_memory_reservation *memory_reservation =
1483         (struct xen_memory_reservation *)ARG2;
1484
1485      POST_MEM_WRITE((Addr)memory_reservation->extent_start.p,
1486                     sizeof(vki_xen_pfn_t) * memory_reservation->nr_extents);
1487      break;
1488   }
1489
1490   case VKI_XENMEM_machphys_mfn_list:
1491   case VKI_XENMEM_machphys_compat_mfn_list: {
1492       struct vki_xen_machphys_mfn_list *arg =
1493           (struct vki_xen_machphys_mfn_list *)ARG2;
1494       POST_MEM_WRITE((Addr)&arg->nr_extents, sizeof(arg->nr_extents));
1495       POST_MEM_WRITE((Addr)arg->extent_start.p,
1496                      sizeof(vki_xen_pfn_t) * arg->nr_extents);
1497       break;
1498   }
1499
1500   case VKI_XENMEM_memory_map:
1501   case VKI_XENMEM_machine_memory_map: {
1502      struct vki_xen_memory_map *arg =
1503         (struct vki_xen_memory_map *)ARG2;
1504      POST_MEM_WRITE(arg->nr_entries, sizeof(arg->nr_entries));
1505      POST_MEM_WRITE((Addr)arg->buffer.p,
1506                     arg->nr_entries * 20 /* size of an e820 entry */);
1507      break;
1508   }
1509
1510   case VKI_XENMEM_add_to_physmap: {
1511       struct vki_xen_add_to_physmap *arg =
1512           (struct vki_xen_add_to_physmap *)ARG2;
1513       if (arg->space == VKI_XENMAPSPACE_gmfn_range)
1514           POST_MEM_WRITE(ARG2, sizeof(*arg));
1515   }
1516
1517   case VKI_XENMEM_get_sharing_freed_pages:
1518   case VKI_XENMEM_get_sharing_shared_pages:
1519       /* No outputs */
1520       break;
1521   }
1522}
1523
1524POST(mmuext_op)
1525{
1526   unsigned int *pdone = (unsigned int *)ARG3;
1527   /* simplistic */
1528   POST_MEM_WRITE((Addr)pdone, sizeof(*pdone));
1529}
1530
1531POST(xsm_op)
1532{
1533   /* XXX assuming flask, only actual XSM right now */
1534   struct vki_xen_flask_op *op = (struct vki_xen_flask_op *)ARG1;
1535
1536   switch (op->interface_version) {
1537   case 0x00000001:
1538      break;
1539   default:
1540      return;
1541   }
1542
1543#define POST_XEN_XSM_OP_WRITE(_xsm_op, _union, _field)        \
1544      POST_MEM_WRITE((Addr)&op->u._union._field,              \
1545                     sizeof(op->u._union._field))
1546
1547   switch (op->cmd) {
1548   case VKI_FLASK_SID_TO_CONTEXT:
1549      POST_XEN_XSM_OP_WRITE(SID_TO_CONTEXT, sid_context, size);
1550      POST_MEM_WRITE((Addr)op->u.sid_context.context.p,
1551                     op->u.sid_context.size);
1552   }
1553}
1554
1555static void post_evtchn_op(ThreadId tid, __vki_u32 cmd, void *arg, int compat)
1556{
1557   switch (cmd) {
1558   case VKI_XEN_EVTCHNOP_alloc_unbound: {
1559      struct vki_xen_evtchn_alloc_unbound *alloc_unbound = arg;
1560      POST_MEM_WRITE((Addr)&alloc_unbound->port, sizeof(alloc_unbound->port));
1561      break;
1562   }
1563   }
1564}
1565
1566POST(sched_op)
1567{
1568   switch (ARG1) {
1569   case VKI_XEN_SCHEDOP_remote_shutdown:
1570      /* No outputs */
1571      break;
1572   }
1573}
1574
1575POST(evtchn_op)
1576{
1577   post_evtchn_op(tid, ARG1, (void *)ARG2, 0);
1578}
1579
1580POST(evtchn_op_compat)
1581{
1582   struct vki_xen_evtchn_op *evtchn = (struct vki_xen_evtchn_op *)ARG1;
1583   post_evtchn_op(tid, evtchn->cmd, &evtchn->u, 1);
1584}
1585
1586POST(physdev_op)
1587{
1588   int cmd = ARG1;
1589
1590#define POST_XEN_PHYSDEVOP_WRITE(_op, _field)                   \
1591   POST_MEM_WRITE((Addr)&arg->_field, sizeof(arg->_field))
1592
1593   switch (cmd) {
1594   case VKI_XEN_PHYSDEVOP_unmap_pirq:
1595      /* No outputs */
1596      break;
1597
1598   case VKI_XEN_PHYSDEVOP_map_pirq: {
1599      struct vki_xen_physdev_map_pirq *arg =
1600         (struct vki_xen_physdev_map_pirq *)ARG2;
1601      if (arg->type == VKI_XEN_MAP_PIRQ_TYPE_MULTI_MSI)
1602         POST_XEN_PHYSDEVOP_WRITE("map_pirq", entry_nr);
1603      POST_XEN_PHYSDEVOP_WRITE("map_pirq", pirq);
1604      break;
1605   }
1606#undef POST_XEN_PHYSDEVOP_WRITE
1607
1608   default:
1609      break;
1610   }
1611}
1612
1613POST(xen_version)
1614{
1615   switch (ARG1) {
1616   case VKI_XENVER_version:
1617      /* No outputs */
1618      break;
1619   case VKI_XENVER_extraversion:
1620      POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_extraversion_t));
1621      break;
1622   case VKI_XENVER_compile_info:
1623      POST_MEM_WRITE((Addr)ARG2, sizeof(struct vki_xen_compile_info));
1624      break;
1625   case VKI_XENVER_capabilities:
1626      POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_capabilities_info_t));
1627      break;
1628   case VKI_XENVER_changeset:
1629      POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_changeset_info_t));
1630      break;
1631   case VKI_XENVER_platform_parameters:
1632      POST_MEM_WRITE((Addr)ARG2, sizeof(struct vki_xen_platform_parameters));
1633      break;
1634   case VKI_XENVER_get_features:
1635      POST_MEM_WRITE((Addr)ARG2, sizeof(struct vki_xen_feature_info));
1636      break;
1637   case VKI_XENVER_pagesize:
1638      /* No outputs */
1639      break;
1640   case VKI_XENVER_guest_handle:
1641      POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_domain_handle_t));
1642      break;
1643   case VKI_XENVER_commandline:
1644      POST_MEM_WRITE((Addr)ARG2, sizeof(vki_xen_commandline_t));
1645      break;
1646   }
1647}
1648
1649POST(grant_table_op)
1650{
1651   switch (ARG1) {
1652   case VKI_XEN_GNTTABOP_setup_table: {
1653      struct vki_xen_gnttab_setup_table *gst =
1654	      (struct vki_xen_gnttab_setup_table*)ARG2;
1655      PRE_MEM_WRITE("VKI_XEN_GNTTABOP_setup_table",
1656                    (Addr)&gst->status, sizeof(gst->status));
1657      PRE_MEM_WRITE("VKI_XEN_GNTTABOP_setup_table",
1658                    (Addr)gst->frame_list.p,
1659                    sizeof(*gst->frame_list.p) & gst->nr_frames);
1660      break;
1661   }
1662   }
1663}
1664
1665POST(sysctl)
1666{
1667   struct vki_xen_sysctl *sysctl = (struct vki_xen_sysctl *)ARG1;
1668
1669   switch (sysctl->interface_version)
1670   {
1671   case 0x00000008:
1672   case 0x00000009:
1673   case 0x0000000a:
1674   case 0x0000000b:
1675	   break;
1676   default:
1677      return;
1678   }
1679
1680#define __POST_XEN_SYSCTL_WRITE(_sysctl, _union, _field)        \
1681      POST_MEM_WRITE((Addr)&sysctl->u._union._field,            \
1682                     sizeof(sysctl->u._union._field))
1683#define POST_XEN_SYSCTL_WRITE(_sysctl, _field) \
1684      __POST_XEN_SYSCTL_WRITE(_sysctl, _sysctl, _field)
1685
1686   switch (sysctl->cmd) {
1687   case VKI_XEN_SYSCTL_readconsole:
1688       POST_MEM_WRITE((Addr)sysctl->u.readconsole.buffer.p,
1689                      sysctl->u.readconsole.count * sizeof(char));
1690       break;
1691
1692   case VKI_XEN_SYSCTL_getdomaininfolist:
1693      switch (sysctl->interface_version)
1694      {
1695      case 0x00000008:
1696	 POST_XEN_SYSCTL_WRITE(getdomaininfolist_00000008, num_domains);
1697	 POST_MEM_WRITE((Addr)sysctl->u.getdomaininfolist_00000008.buffer.p,
1698			sizeof(*sysctl->u.getdomaininfolist_00000008.buffer.p)
1699			* sysctl->u.getdomaininfolist_00000008.num_domains);
1700	 break;
1701      case 0x00000009:
1702	 POST_XEN_SYSCTL_WRITE(getdomaininfolist_00000009, num_domains);
1703	 POST_MEM_WRITE((Addr)sysctl->u.getdomaininfolist_00000009.buffer.p,
1704			sizeof(*sysctl->u.getdomaininfolist_00000009.buffer.p)
1705			* sysctl->u.getdomaininfolist_00000009.num_domains);
1706	 break;
1707      case 0x0000000a:
1708      case 0x0000000b:
1709	 POST_XEN_SYSCTL_WRITE(getdomaininfolist_0000000a, num_domains);
1710	 POST_MEM_WRITE((Addr)sysctl->u.getdomaininfolist_0000000a.buffer.p,
1711			sizeof(*sysctl->u.getdomaininfolist_0000000a.buffer.p)
1712			* sysctl->u.getdomaininfolist_0000000a.num_domains);
1713	 break;
1714      }
1715      break;
1716
1717   case VKI_XEN_SYSCTL_sched_id:
1718       POST_XEN_SYSCTL_WRITE(sched_id, sched_id);
1719       break;
1720
1721   case VKI_XEN_SYSCTL_cpupool_op:
1722      if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_CREATE ||
1723          sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_INFO)
1724         POST_XEN_SYSCTL_WRITE(cpupool_op, cpupool_id);
1725      if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_INFO) {
1726         POST_XEN_SYSCTL_WRITE(cpupool_op, sched_id);
1727         POST_XEN_SYSCTL_WRITE(cpupool_op, n_dom);
1728      }
1729      if (sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_INFO ||
1730          sysctl->u.cpupool_op.op == VKI_XEN_SYSCTL_CPUPOOL_OP_FREEINFO)
1731         POST_XEN_SYSCTL_WRITE(cpupool_op, cpumap);
1732      break;
1733
1734   case VKI_XEN_SYSCTL_physinfo:
1735      switch (sysctl->interface_version)
1736      {
1737      case 0x00000008:
1738      case 0x00000009: /* Unchanged from version 8 */
1739         POST_XEN_SYSCTL_WRITE(physinfo_00000008, threads_per_core);
1740         POST_XEN_SYSCTL_WRITE(physinfo_00000008, cores_per_socket);
1741         POST_XEN_SYSCTL_WRITE(physinfo_00000008, nr_cpus);
1742         POST_XEN_SYSCTL_WRITE(physinfo_00000008, max_cpu_id);
1743         POST_XEN_SYSCTL_WRITE(physinfo_00000008, nr_nodes);
1744         POST_XEN_SYSCTL_WRITE(physinfo_00000008, max_node_id);
1745         POST_XEN_SYSCTL_WRITE(physinfo_00000008, cpu_khz);
1746         POST_XEN_SYSCTL_WRITE(physinfo_00000008, total_pages);
1747         POST_XEN_SYSCTL_WRITE(physinfo_00000008, free_pages);
1748         POST_XEN_SYSCTL_WRITE(physinfo_00000008, scrub_pages);
1749         POST_XEN_SYSCTL_WRITE(physinfo_00000008, hw_cap[8]);
1750         POST_XEN_SYSCTL_WRITE(physinfo_00000008, capabilities);
1751         break;
1752      case 0x0000000a:
1753      case 0x0000000b:
1754         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, threads_per_core);
1755         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, cores_per_socket);
1756         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, nr_cpus);
1757         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, max_cpu_id);
1758         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, nr_nodes);
1759         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, max_node_id);
1760         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, cpu_khz);
1761         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, total_pages);
1762         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, free_pages);
1763         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, scrub_pages);
1764         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, outstanding_pages);
1765         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, hw_cap[8]);
1766         POST_XEN_SYSCTL_WRITE(physinfo_0000000a, capabilities);
1767         break;
1768      }
1769      break;
1770
1771   case VKI_XEN_SYSCTL_topologyinfo:
1772      POST_XEN_SYSCTL_WRITE(topologyinfo, max_cpu_index);
1773      if (sysctl->u.topologyinfo.cpu_to_core.p)
1774         POST_MEM_WRITE((Addr)sysctl->u.topologyinfo.cpu_to_core.p,
1775                     sizeof(uint32_t) * sysctl->u.topologyinfo.max_cpu_index);
1776      if (sysctl->u.topologyinfo.cpu_to_socket.p)
1777         POST_MEM_WRITE((Addr)sysctl->u.topologyinfo.cpu_to_socket.p,
1778                     sizeof(uint32_t) * sysctl->u.topologyinfo.max_cpu_index);
1779      if (sysctl->u.topologyinfo.cpu_to_node.p)
1780         POST_MEM_WRITE((Addr)sysctl->u.topologyinfo.cpu_to_node.p,
1781                     sizeof(uint32_t) * sysctl->u.topologyinfo.max_cpu_index);
1782      break;
1783
1784   case VKI_XEN_SYSCTL_numainfo:
1785      POST_XEN_SYSCTL_WRITE(numainfo, max_node_index);
1786      POST_MEM_WRITE((Addr)sysctl->u.numainfo.node_to_memsize.p,
1787                     sizeof(uint64_t) * sysctl->u.numainfo.max_node_index);
1788      POST_MEM_WRITE((Addr)sysctl->u.numainfo.node_to_memfree.p,
1789                     sizeof(uint64_t) * sysctl->u.numainfo.max_node_index);
1790      POST_MEM_WRITE((Addr)sysctl->u.numainfo.node_to_node_distance.p,
1791                     sizeof(uint32_t) * sysctl->u.numainfo.max_node_index);
1792      break;
1793
1794   /* No outputs */
1795   case VKI_XEN_SYSCTL_debug_keys:
1796       break;
1797   }
1798#undef POST_XEN_SYSCTL_WRITE
1799#undef __POST_XEN_SYSCTL_WRITE
1800}
1801
1802POST(domctl){
1803   struct vki_xen_domctl *domctl = (struct vki_xen_domctl *)ARG1;
1804
1805   switch (domctl->interface_version) {
1806   case 0x00000007:
1807   case 0x00000008:
1808   case 0x00000009:
1809   case 0x0000000a:
1810   case 0x0000000b:
1811	   break;
1812   default:
1813	   return;
1814   }
1815
1816#define __POST_XEN_DOMCTL_WRITE(_domctl, _union, _field)        \
1817   POST_MEM_WRITE((Addr)&domctl->u._union._field,               \
1818                  sizeof(domctl->u._union._field));
1819#define POST_XEN_DOMCTL_WRITE(_domctl, _field)          \
1820   __POST_XEN_DOMCTL_WRITE(_domctl, _domctl, _field)
1821
1822   switch (domctl->cmd) {
1823   case VKI_XEN_DOMCTL_createdomain:
1824   case VKI_XEN_DOMCTL_destroydomain:
1825   case VKI_XEN_DOMCTL_pausedomain:
1826   case VKI_XEN_DOMCTL_max_mem:
1827   case VKI_XEN_DOMCTL_setvcpuextstate:
1828   case VKI_XEN_DOMCTL_set_address_size:
1829   case VKI_XEN_DOMCTL_test_assign_device:
1830   case VKI_XEN_DOMCTL_assign_device:
1831   case VKI_XEN_DOMCTL_deassign_device:
1832   case VKI_XEN_DOMCTL_settscinfo:
1833   case VKI_XEN_DOMCTL_irq_permission:
1834   case VKI_XEN_DOMCTL_iomem_permission:
1835   case VKI_XEN_DOMCTL_ioport_permission:
1836   case VKI_XEN_DOMCTL_hypercall_init:
1837   case VKI_XEN_DOMCTL_setvcpucontext:
1838   case VKI_XEN_DOMCTL_pin_mem_cacheattr:
1839   case VKI_XEN_DOMCTL_set_ext_vcpucontext:
1840   case VKI_XEN_DOMCTL_setnodeaffinity:
1841   case VKI_XEN_DOMCTL_set_cpuid:
1842   case VKI_XEN_DOMCTL_unpausedomain:
1843   case VKI_XEN_DOMCTL_sethvmcontext:
1844   case VKI_XEN_DOMCTL_debug_op:
1845   case VKI_XEN_DOMCTL_set_max_evtchn:
1846   case VKI_XEN_DOMCTL_cacheflush:
1847   case VKI_XEN_DOMCTL_resumedomain:
1848   case VKI_XEN_DOMCTL_set_vcpu_msrs:
1849   case VKI_XEN_DOMCTL_set_access_required:
1850      /* No output fields */
1851      break;
1852
1853   case VKI_XEN_DOMCTL_max_vcpus:
1854      POST_XEN_DOMCTL_WRITE(max_vcpus, max);
1855      break;
1856
1857   case VKI_XEN_DOMCTL_get_address_size:
1858      __POST_XEN_DOMCTL_WRITE(get_address_size, address_size, size);
1859      break;
1860
1861   case VKI_XEN_DOMCTL_gettscinfo:
1862      switch (domctl->interface_version) {
1863      case 0x00000007: /* pre-4.6 */
1864      case 0x00000008:
1865      case 0x00000009:
1866      case 0x0000000a:
1867         __POST_XEN_DOMCTL_WRITE(gettscinfo, tsc_info_00000007, out_info);
1868         POST_MEM_WRITE((Addr)domctl->u.tsc_info_00000007.out_info.p,
1869                        sizeof(vki_xen_guest_tsc_info_t));
1870         break;
1871      case 0x0000000b:
1872         __POST_XEN_DOMCTL_WRITE(gettscinfo, tsc_info_0000000b, tsc_mode);
1873         __POST_XEN_DOMCTL_WRITE(gettscinfo, tsc_info_0000000b, gtsc_khz);
1874         __POST_XEN_DOMCTL_WRITE(gettscinfo, tsc_info_0000000b, incarnation);
1875         __POST_XEN_DOMCTL_WRITE(gettscinfo, tsc_info_0000000b, elapsed_nsec);
1876         break;
1877      }
1878      break;
1879      break;
1880
1881   case VKI_XEN_DOMCTL_getvcpuinfo:
1882      POST_XEN_DOMCTL_WRITE(getvcpuinfo, online);
1883      POST_XEN_DOMCTL_WRITE(getvcpuinfo, blocked);
1884      POST_XEN_DOMCTL_WRITE(getvcpuinfo, running);
1885      POST_XEN_DOMCTL_WRITE(getvcpuinfo, cpu_time);
1886      POST_XEN_DOMCTL_WRITE(getvcpuinfo, cpu);
1887      break;
1888
1889   case VKI_XEN_DOMCTL_gethvmcontext:
1890       /* Xen unconditionally writes size... */
1891       __POST_XEN_DOMCTL_WRITE(gethvmcontext, hvmcontext, size);
1892       /* ...but only writes to the buffer if it was non NULL */
1893       if ( domctl->u.hvmcontext.buffer.p )
1894           POST_MEM_WRITE((Addr)domctl->u.hvmcontext.buffer.p,
1895                          sizeof(*domctl->u.hvmcontext.buffer.p)
1896                          * domctl->u.hvmcontext.size);
1897       break;
1898
1899   case VKI_XEN_DOMCTL_gethvmcontext_partial:
1900       switch (domctl->u.hvmcontext_partial.type) {
1901       case VKI_HVM_SAVE_CODE(CPU):
1902           if ( domctl->u.hvmcontext_partial.buffer.p )
1903                POST_MEM_WRITE((Addr)domctl->u.hvmcontext_partial.buffer.p,
1904                   VKI_HVM_SAVE_LENGTH(CPU));
1905           break;
1906       }
1907       break;
1908
1909   case VKI_XEN_DOMCTL_scheduler_op:
1910      if ( domctl->u.scheduler_op.cmd == VKI_XEN_DOMCTL_SCHEDOP_getinfo ) {
1911         switch(domctl->u.scheduler_op.sched_id) {
1912         case VKI_XEN_SCHEDULER_SEDF:
1913            POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.period);
1914            POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.slice);
1915            POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.latency);
1916            POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.extratime);
1917            POST_XEN_DOMCTL_WRITE(scheduler_op, u.sedf.weight);
1918            break;
1919         case VKI_XEN_SCHEDULER_CREDIT:
1920            POST_XEN_DOMCTL_WRITE(scheduler_op, u.credit.weight);
1921            POST_XEN_DOMCTL_WRITE(scheduler_op, u.credit.cap);
1922            break;
1923         case VKI_XEN_SCHEDULER_CREDIT2:
1924            POST_XEN_DOMCTL_WRITE(scheduler_op, u.credit2.weight);
1925            break;
1926         case VKI_XEN_SCHEDULER_ARINC653:
1927            break;
1928         case VKI_XEN_SCHEDULER_RTDS:
1929            POST_XEN_DOMCTL_WRITE(scheduler_op, u.rtds.period);
1930            POST_XEN_DOMCTL_WRITE(scheduler_op, u.rtds.budget);
1931            break;
1932         }
1933      }
1934      break;
1935
1936   case VKI_XEN_DOMCTL_getvcpuaffinity:
1937   case VKI_XEN_DOMCTL_setvcpuaffinity: /* Writes back actual result */
1938      switch (domctl->interface_version) {
1939      case 0x00000007:
1940      case 0x00000008:
1941      case 0x00000009:
1942         POST_MEM_WRITE((Addr)domctl->u.vcpuaffinity_00000009.cpumap.bitmap.p,
1943                        domctl->u.vcpuaffinity_00000009.cpumap.nr_bits / 8);
1944         break;
1945      case 0x0000000a:
1946         if (domctl->u.vcpuaffinity_0000000a.flags & VKI_XEN_VCPUAFFINITY_HARD)
1947            POST_MEM_WRITE(
1948               (Addr)domctl->u.vcpuaffinity_0000000a.cpumap_hard.bitmap.p,
1949               domctl->u.vcpuaffinity_0000000a.cpumap_hard.nr_bits / 8);
1950         if (domctl->u.vcpuaffinity_0000000a.flags & VKI_XEN_VCPUAFFINITY_SOFT)
1951            POST_MEM_WRITE(
1952               (Addr)domctl->u.vcpuaffinity_0000000a.cpumap_soft.bitmap.p,
1953               domctl->u.vcpuaffinity_0000000a.cpumap_soft.nr_bits / 8);
1954      }
1955      break;
1956
1957   case VKI_XEN_DOMCTL_getnodeaffinity:
1958      POST_MEM_WRITE((Addr)domctl->u.nodeaffinity.nodemap.bitmap.p,
1959                     domctl->u.nodeaffinity.nodemap.nr_bits / 8);
1960      break;
1961
1962   case VKI_XEN_DOMCTL_getdomaininfo:
1963      switch (domctl->interface_version) {
1964      case 0x00000007:
1965	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, domain);
1966	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, flags);
1967	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, tot_pages);
1968	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, max_pages);
1969	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, shr_pages);
1970	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, shared_info_frame);
1971	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, cpu_time);
1972	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, nr_online_vcpus);
1973	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, max_vcpu_id);
1974	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, ssidref);
1975	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, handle);
1976	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000007, cpupool);
1977      break;
1978      case 0x00000008:
1979	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, domain);
1980	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, flags);
1981	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, tot_pages);
1982	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, max_pages);
1983	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, shr_pages);
1984	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, paged_pages);
1985	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, shared_info_frame);
1986	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, cpu_time);
1987	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, nr_online_vcpus);
1988	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, max_vcpu_id);
1989	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, ssidref);
1990	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, handle);
1991	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000008, cpupool);
1992      break;
1993      case 0x00000009:
1994      case 0x0000000a:
1995	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, domain);
1996	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, flags);
1997	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, tot_pages);
1998	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, max_pages);
1999	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, outstanding_pages);
2000	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, shr_pages);
2001	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, paged_pages);
2002	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, shared_info_frame);
2003	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, cpu_time);
2004	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, nr_online_vcpus);
2005	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, max_vcpu_id);
2006	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, ssidref);
2007	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, handle);
2008	 POST_XEN_DOMCTL_WRITE(getdomaininfo_00000009, cpupool);
2009      break;
2010      }
2011      break;
2012   case VKI_XEN_DOMCTL_getvcpucontext:
2013      __POST_XEN_DOMCTL_WRITE(getvcpucontext, vcpucontext, ctxt.p);
2014      break;
2015
2016   case VKI_XEN_DOMCTL_getpageframeinfo3:
2017       POST_MEM_WRITE((Addr)domctl->u.getpageframeinfo3.array.p,
2018                      domctl->u.getpageframeinfo3.num * sizeof(vki_xen_pfn_t));
2019       break;
2020
2021   case VKI_XEN_DOMCTL_get_ext_vcpucontext:
2022       switch (domctl->interface_version)
2023       {
2024       case 0x00000007:
2025       case 0x00000008:
2026           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008, size);
2027#if defined(__i386__) || defined(__x86_64__)
2028           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008,
2029                                   syscall32_callback_eip);
2030           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008,
2031                                   sysenter_callback_eip);
2032           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008,
2033                                   syscall32_callback_cs);
2034           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008,
2035                                   sysenter_callback_cs);
2036           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008,
2037                                   syscall32_disables_events);
2038           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008,
2039                                   sysenter_disables_events);
2040
2041           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000008,
2042                                   mcg_cap);
2043#endif
2044           break;
2045
2046       case 0x00000009:
2047           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009, size);
2048#if defined(__i386__) || defined(__x86_64__)
2049           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009,
2050                                   syscall32_callback_eip);
2051           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009,
2052                                   sysenter_callback_eip);
2053           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009,
2054                                   syscall32_callback_cs);
2055           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009,
2056                                   sysenter_callback_cs);
2057           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009,
2058                                   syscall32_disables_events);
2059           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009,
2060                                   sysenter_disables_events);
2061
2062           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009,
2063                                   caps);
2064           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009,
2065                                   mci_ctl2_bank0);
2066           __POST_XEN_DOMCTL_WRITE(get_ext_vcpucontext, ext_vcpucontext_00000009,
2067                                   mci_ctl2_bank1);
2068#endif
2069	   break;
2070       }
2071       break;
2072
2073
2074   case VKI_XEN_DOMCTL_getvcpuextstate:
2075      if (domctl->u.vcpuextstate.buffer.p)
2076         POST_MEM_WRITE((Addr)domctl->u.vcpuextstate.buffer.p,
2077                        domctl->u.vcpuextstate.size);
2078      break;
2079
2080   case VKI_XEN_DOMCTL_shadow_op:
2081       switch(domctl->u.shadow_op.op)
2082       {
2083       case VKI_XEN_DOMCTL_SHADOW_OP_OFF:
2084       case VKI_XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION:
2085           /* No outputs */
2086           break;
2087
2088       case VKI_XEN_DOMCTL_SHADOW_OP_CLEAN:
2089       case VKI_XEN_DOMCTL_SHADOW_OP_PEEK:
2090           POST_XEN_DOMCTL_WRITE(shadow_op, pages);
2091           POST_XEN_DOMCTL_WRITE(shadow_op, stats.fault_count);
2092           POST_XEN_DOMCTL_WRITE(shadow_op, stats.dirty_count);
2093           if(domctl->u.shadow_op.dirty_bitmap.p)
2094               POST_MEM_WRITE((Addr)domctl->u.shadow_op.dirty_bitmap.p,
2095                              domctl->u.shadow_op.pages * sizeof(vki_uint8_t));
2096           break;
2097
2098       case VKI_XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION:
2099           POST_XEN_DOMCTL_WRITE(shadow_op, mb);
2100           break;
2101
2102       default:
2103           break;
2104       }
2105       break;
2106   case VKI_XEN_DOMCTL_get_vcpu_msrs:
2107      if (domctl->u.vcpu_msrs.msrs.p)
2108         POST_MEM_WRITE((Addr)domctl->u.vcpu_msrs.msrs.p,
2109                        sizeof(vki_xen_domctl_vcpu_msr_t) *
2110                        domctl->u.vcpu_msrs.msr_count);
2111      break;
2112
2113   case VKI_XEN_DOMCTL_mem_event_op:
2114   //case VKI_XEN_DOMCTL_vm_event_op: /* name change in 4.6 */
2115      switch (domctl->interface_version) {
2116      case 0x00000007: /* pre-4.6 */
2117      case 0x00000008:
2118      case 0x00000009:
2119      case 0x0000000a:
2120         __POST_XEN_DOMCTL_WRITE(mem_event_op, mem_event_op_00000007, port);
2121         break;
2122      case 0x0000000b:
2123         __POST_XEN_DOMCTL_WRITE(vm_event_op, vm_event_op_0000000b, port);
2124         break;
2125      }
2126      break;
2127
2128   case VKI_XEN_DOMCTL_monitor_op:
2129      switch (domctl->interface_version) {
2130      case 0x000000b:
2131          if (domctl->u.monitor_op_0000000b.op == VKI_XEN_DOMCTL_MONITOR_OP_GET_CAPABILITIES) {
2132             switch(domctl->u.monitor_op_0000000b.event) {
2133             case VKI_XEN_DOMCTL_MONITOR_EVENT_WRITE_CTRLREG:
2134                __POST_XEN_DOMCTL_WRITE(monitor_op, monitor_op_0000000b, u.mov_to_cr);
2135                break;
2136             case VKI_XEN_DOMCTL_MONITOR_EVENT_MOV_TO_MSR:
2137                __POST_XEN_DOMCTL_WRITE(monitor_op, monitor_op_0000000b, u.mov_to_msr);
2138                break;
2139             case VKI_XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST:
2140                __POST_XEN_DOMCTL_WRITE(monitor_op, monitor_op_0000000b, u.guest_request);
2141                break;
2142             }
2143          }
2144
2145         break;
2146      }
2147      break;
2148   }
2149
2150#undef POST_XEN_DOMCTL_WRITE
2151#undef __POST_XEN_DOMCTL_WRITE
2152}
2153
2154POST(hvm_op)
2155{
2156   unsigned long op = ARG1;
2157   void *arg = (void *)(unsigned long)ARG2;
2158
2159#define __POST_XEN_HVMOP_WRITE(_hvm_op, _type, _field)  \
2160      POST_MEM_WRITE((Addr)&((_type*)arg)->_field,      \
2161                     sizeof(((_type*)arg)->_field))
2162#define POST_XEN_HVMOP_WRITE(_hvm_op, _field) \
2163      __POST_XEN_HVMOP_WRITE(_hvm_op, vki_xen_hvm_ ## _hvm_op ## _t, _field)
2164
2165   switch (op) {
2166   case VKI_XEN_HVMOP_set_param:
2167   case VKI_XEN_HVMOP_set_pci_intx_level:
2168   case VKI_XEN_HVMOP_set_isa_irq_level:
2169   case VKI_XEN_HVMOP_set_pci_link_route:
2170   case VKI_XEN_HVMOP_set_mem_type:
2171   case VKI_XEN_HVMOP_set_mem_access:
2172   case VKI_XEN_HVMOP_inject_trap:
2173      /* No output parameters */
2174      break;
2175
2176   case VKI_XEN_HVMOP_get_param:
2177      __POST_XEN_HVMOP_WRITE(get_param, struct vki_xen_hvm_param, value);
2178      break;
2179
2180   case VKI_XEN_HVMOP_get_mem_access:
2181      POST_XEN_HVMOP_WRITE(get_mem_access, hvmmem_access);
2182      break;
2183   }
2184#undef __POST_XEN_HVMOP_WRITE
2185#undef POST_XEN_HVMOP_WRITE
2186}
2187
2188POST(tmem_op)
2189{
2190    struct vki_xen_tmem_op *tmem = (struct vki_xen_tmem_op *)ARG1;
2191
2192    switch(tmem->cmd) {
2193
2194    case VKI_XEN_TMEM_control:
2195
2196        switch(tmem->u.ctrl.subop) {
2197            /* No outputs */
2198            case VKI_XEN_TMEMC_save_begin:
2199                break;
2200        }
2201
2202        break;
2203    }
2204}
2205
2206typedef
2207   struct {
2208      SyscallTableEntry entry;
2209      int nr_args;
2210   }
2211   XenHypercallTableEntry;
2212
2213#define HYPX_(const, name, nr_args) \
2214   [const] = { { vgSysWrap_xen_##name##_before, NULL }, nr_args }
2215#define HYPXY(const, name, nr_args)                     \
2216   [const] = { { vgSysWrap_xen_##name##_before,         \
2217                 vgSysWrap_xen_##name##_after },        \
2218               nr_args }
2219
2220static XenHypercallTableEntry hypercall_table[] = {
2221   //    __VKI_XEN_set_trap_table                                  // 0
2222   //    __VKI_XEN_mmu_update                                      // 1
2223   //    __VKI_XEN_set_gdt                                         // 2
2224   //    __VKI_XEN_stack_switch                                    // 3
2225   //    __VKI_XEN_set_callbacks                                   // 4
2226
2227   //    __VKI_XEN_fpu_taskswitch                                  // 5
2228   //    __VKI_XEN_sched_op_compat                                 // 6
2229   //    __VKI_XEN_platform_op                                     // 7
2230   //    __VKI_XEN_set_debugreg                                    // 8
2231   //    __VKI_XEN_get_debugreg                                    // 9
2232
2233   //    __VKI_XEN_update_descriptor                               // 10
2234   //                                                                 // 11
2235   HYPXY(__VKI_XEN_memory_op,               memory_op,         2), // 12
2236   //    __VKI_XEN_multicall                                       // 13
2237   //    __VKI_XEN_update_va_mapping                               // 14
2238
2239   //    __VKI_XEN_set_timer_op                                    // 15
2240   HYPXY(__VKI_XEN_event_channel_op_compat, evtchn_op_compat,  1), // 16
2241   HYPXY(__VKI_XEN_xen_version,             xen_version,       2), // 17
2242   //    __VKI_XEN_console_io                                      // 18
2243   //    __VKI_XEN_physdev_op_compat                               // 19
2244
2245   HYPXY(__VKI_XEN_grant_table_op,          grant_table_op,    3), // 20
2246   //    __VKI_XEN_vm_assist                                       // 21
2247   //    __VKI_XEN_update_va_mapping_otherdomain                   // 22
2248   //    __VKI_XEN_iret,                    iret                   // 23
2249   //    __VKI_XEN_vcpu_op,                 vcpu_op                // 24
2250
2251   //    __VKI_XEN_set_segment_base                                // 25
2252   HYPXY(__VKI_XEN_mmuext_op,               mmuext_op,         2), // 26
2253   HYPXY(__VKI_XEN_xsm_op,                  xsm_op,            1), // 27
2254   //    __VKI_XEN_nmi_op                                          // 28
2255   HYPXY(__VKI_XEN_sched_op,                sched_op,          2), // 29
2256
2257   //    __VKI_XEN_callback_op                                     // 30
2258   //    __VKI_XEN_xenoprof_op                                     // 31
2259   HYPXY(__VKI_XEN_event_channel_op,        evtchn_op,         2), // 32
2260   HYPXY(__VKI_XEN_physdev_op,              physdev_op,        2), // 33
2261   HYPXY(__VKI_XEN_hvm_op,                  hvm_op,            2), // 34
2262
2263   HYPXY(__VKI_XEN_sysctl,                  sysctl,            1), // 35
2264   HYPXY(__VKI_XEN_domctl,                  domctl,            1), // 36
2265   //    __VKI_XEN_kexec_op                                        // 37
2266   HYPXY(__VKI_XEN_tmem_op,                 tmem_op,           1), // 38
2267};
2268
2269static void bad_before ( ThreadId              tid,
2270                         SyscallArgLayout*     layout,
2271                         /*MOD*/SyscallArgs*   args,
2272                         /*OUT*/SyscallStatus* status,
2273                         /*OUT*/UWord*         flags )
2274{
2275   VG_(dmsg)("WARNING: unhandled hypercall: %s\n",
2276      VG_SYSNUM_STRING(args->sysno));
2277   if (VG_(clo_verbosity) > 1) {
2278      VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
2279   }
2280   VG_(dmsg)("You may be able to write your own handler.\n");
2281   VG_(dmsg)("Read the file README_MISSING_SYSCALL_OR_IOCTL.\n");
2282   VG_(dmsg)("Nevertheless we consider this a bug.  Please report\n");
2283   VG_(dmsg)("it at http://valgrind.org/support/bug_reports.html &\n");
2284   VG_(dmsg)("http://wiki.xen.org/wiki/Reporting_Bugs_against_Xen.\n");
2285
2286   SET_STATUS_Failure(VKI_ENOSYS);
2287}
2288
2289static XenHypercallTableEntry bad_hyper =
2290{ { bad_before, NULL }, 0 };
2291
2292static XenHypercallTableEntry* ML_(get_xen_hypercall_entry) ( UInt sysno )
2293{
2294   XenHypercallTableEntry *ret = &bad_hyper;
2295
2296   const UInt hypercall_table_size
2297      = sizeof(hypercall_table) / sizeof(hypercall_table[0]);
2298
2299   /* Is it in the contiguous initial section of the table? */
2300   if (sysno < hypercall_table_size) {
2301      XenHypercallTableEntry* ent = &hypercall_table[sysno];
2302      if (ent->entry.before != NULL)
2303         ret = ent;
2304   }
2305
2306   /* Can't find a wrapper */
2307   return ret;
2308}
2309
2310DEFN_PRE_TEMPLATE(xen, hypercall)
2311{
2312   XenHypercallTableEntry *ent = ML_(get_xen_hypercall_entry)(SYSNO);
2313
2314   /* Return number of arguments consumed */
2315   ARG8 = ent->nr_args;
2316
2317   vg_assert(ent);
2318   vg_assert(ent->entry.before);
2319   (ent->entry.before)( tid, layout, arrghs, status, flags );
2320
2321}
2322
2323DEFN_POST_TEMPLATE(xen, hypercall)
2324{
2325   XenHypercallTableEntry *ent = ML_(get_xen_hypercall_entry)(SYSNO);
2326
2327   /* Return number of arguments consumed */
2328   ARG8 = ent->nr_args;
2329
2330   vg_assert(ent);
2331   if (ent->entry.after)
2332      (ent->entry.after)( tid, arrghs, status );
2333}
2334
2335#endif // defined(ENABLE_XEN)
2336