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