1843e1988Sjohnlev /*
2843e1988Sjohnlev  * CDDL HEADER START
3843e1988Sjohnlev  *
4843e1988Sjohnlev  * The contents of this file are subject to the terms of the
5843e1988Sjohnlev  * Common Development and Distribution License (the "License").
6843e1988Sjohnlev  * You may not use this file except in compliance with the License.
7843e1988Sjohnlev  *
8843e1988Sjohnlev  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9843e1988Sjohnlev  * or http://www.opensolaris.org/os/licensing.
10843e1988Sjohnlev  * See the License for the specific language governing permissions
11843e1988Sjohnlev  * and limitations under the License.
12843e1988Sjohnlev  *
13843e1988Sjohnlev  * When distributing Covered Code, include this CDDL HEADER in each
14843e1988Sjohnlev  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15843e1988Sjohnlev  * If applicable, add the following below this CDDL HEADER, with the
16843e1988Sjohnlev  * fields enclosed by brackets "[]" replaced with your own identifying
17843e1988Sjohnlev  * information: Portions Copyright [yyyy] [name of copyright owner]
18843e1988Sjohnlev  *
19843e1988Sjohnlev  * CDDL HEADER END
20843e1988Sjohnlev  */
21843e1988Sjohnlev /*
22525b892bSMark Johnson  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23843e1988Sjohnlev  * Use is subject to license terms.
24843e1988Sjohnlev  */
25843e1988Sjohnlev 
26349b53ddSStuart Maybee #include <sys/xpv_user.h>
27349b53ddSStuart Maybee 
28843e1988Sjohnlev #include <sys/types.h>
29843e1988Sjohnlev #include <sys/file.h>
30843e1988Sjohnlev #include <sys/errno.h>
31843e1988Sjohnlev #include <sys/open.h>
32843e1988Sjohnlev #include <sys/cred.h>
33843e1988Sjohnlev #include <sys/conf.h>
34843e1988Sjohnlev #include <sys/stat.h>
35843e1988Sjohnlev #include <sys/modctl.h>
36843e1988Sjohnlev #include <sys/ddi.h>
37843e1988Sjohnlev #include <sys/sunddi.h>
38843e1988Sjohnlev #include <sys/vmsystm.h>
39843e1988Sjohnlev #include <sys/hypervisor.h>
40843e1988Sjohnlev #include <sys/xen_errno.h>
41843e1988Sjohnlev #include <sys/sysmacros.h>
42843e1988Sjohnlev #include <sys/sdt.h>
43843e1988Sjohnlev 
44843e1988Sjohnlev #include <xen/sys/privcmd.h>
45843e1988Sjohnlev #include <sys/privcmd_impl.h>
46843e1988Sjohnlev 
47843e1988Sjohnlev typedef struct import_export {
48843e1988Sjohnlev 	void *			ie_uaddr;
49843e1988Sjohnlev 	void *			ie_kaddr;
50843e1988Sjohnlev 	size_t			ie_size;
51843e1988Sjohnlev 	uint32_t		ie_flags;
52843e1988Sjohnlev } import_export_t;
53843e1988Sjohnlev 
54843e1988Sjohnlev static import_export_t null_ie = {NULL, NULL, 0, 0};
55843e1988Sjohnlev 
56843e1988Sjohnlev #define	IE_IMPORT	0x0001		/* Data needs to be copied in */
57843e1988Sjohnlev #define	IE_EXPORT	0x0002		/* Data needs to be copied out */
58843e1988Sjohnlev #define	IE_FREE		0x0004
59843e1988Sjohnlev #define	IE_IMPEXP	(IE_IMPORT | IE_EXPORT)
60843e1988Sjohnlev 
61349b53ddSStuart Maybee static void *
uaddr_from_handle(void * field)62349b53ddSStuart Maybee uaddr_from_handle(void *field)
63349b53ddSStuart Maybee {
64349b53ddSStuart Maybee 	struct { void *p; } *hdl = field;
65349b53ddSStuart Maybee 	void *ptr;
66349b53ddSStuart Maybee 
67349b53ddSStuart Maybee 	/*LINTED: constant in conditional context*/
68349b53ddSStuart Maybee 	get_xen_guest_handle(ptr, (*hdl));
69349b53ddSStuart Maybee 	return (ptr);
70349b53ddSStuart Maybee }
71349b53ddSStuart Maybee 
72349b53ddSStuart Maybee 
73843e1988Sjohnlev /*
74843e1988Sjohnlev  * Import a buffer from user-space.  If the caller provides a kernel
75843e1988Sjohnlev  * address, we import to that address.  If not, we kmem_alloc() the space
76843e1988Sjohnlev  * ourselves.
77843e1988Sjohnlev  */
78843e1988Sjohnlev static int
import_buffer(import_export_t * iep,void * uaddr,void * kaddr,size_t size,uint32_t flags)79843e1988Sjohnlev import_buffer(import_export_t *iep, void *uaddr, void *kaddr, size_t size,
80843e1988Sjohnlev     uint32_t flags)
81843e1988Sjohnlev {
82843e1988Sjohnlev 	iep->ie_uaddr = uaddr;
83843e1988Sjohnlev 	iep->ie_size = size;
84843e1988Sjohnlev 	iep->ie_flags = flags & IE_EXPORT;
85843e1988Sjohnlev 
86843e1988Sjohnlev 	if (size == 0 || uaddr == NULL) {
87843e1988Sjohnlev 		*iep = null_ie;
88843e1988Sjohnlev 		return (0);
89843e1988Sjohnlev 	}
90843e1988Sjohnlev 
91843e1988Sjohnlev 	if (kaddr == NULL) {
92843e1988Sjohnlev 		iep->ie_kaddr = kmem_alloc(size, KM_SLEEP);
93843e1988Sjohnlev 		iep->ie_flags |= IE_FREE;
94843e1988Sjohnlev 	} else {
95843e1988Sjohnlev 		iep->ie_kaddr = kaddr;
96a576ab5bSrab 		iep->ie_flags &= ~IE_FREE;
97843e1988Sjohnlev 	}
98843e1988Sjohnlev 
99843e1988Sjohnlev 	if ((flags & IE_IMPORT) &&
100843e1988Sjohnlev 	    (ddi_copyin(uaddr, iep->ie_kaddr, size, 0) != 0)) {
101a576ab5bSrab 		if (iep->ie_flags & IE_FREE) {
102843e1988Sjohnlev 			kmem_free(iep->ie_kaddr, iep->ie_size);
103a576ab5bSrab 			iep->ie_kaddr = NULL;
104a576ab5bSrab 			iep->ie_flags = 0;
105a576ab5bSrab 		}
106843e1988Sjohnlev 		return (-X_EFAULT);
107843e1988Sjohnlev 	}
108843e1988Sjohnlev 
109843e1988Sjohnlev 	return (0);
110843e1988Sjohnlev }
111843e1988Sjohnlev 
112843e1988Sjohnlev static void
export_buffer(import_export_t * iep,int * error)113843e1988Sjohnlev export_buffer(import_export_t *iep, int *error)
114843e1988Sjohnlev {
115843e1988Sjohnlev 	int copy_err = 0;
116843e1988Sjohnlev 
117843e1988Sjohnlev 	if (iep->ie_size == 0 || iep->ie_uaddr == NULL)
118843e1988Sjohnlev 		return;
119843e1988Sjohnlev 
120843e1988Sjohnlev 	/*
121843e1988Sjohnlev 	 * If the buffer was marked for export initially, and if the
122843e1988Sjohnlev 	 * hypercall completed successfully, resync the user-space buffer
123843e1988Sjohnlev 	 * with our in-kernel buffer.
124843e1988Sjohnlev 	 */
125843e1988Sjohnlev 	if ((iep->ie_flags & IE_EXPORT) && (*error >= 0) &&
126843e1988Sjohnlev 	    (ddi_copyout(iep->ie_kaddr, iep->ie_uaddr, iep->ie_size, 0) != 0))
127843e1988Sjohnlev 		copy_err = -X_EFAULT;
128a576ab5bSrab 	if (iep->ie_flags & IE_FREE) {
129843e1988Sjohnlev 		kmem_free(iep->ie_kaddr, iep->ie_size);
130a576ab5bSrab 		iep->ie_kaddr = NULL;
131a576ab5bSrab 		iep->ie_flags = 0;
132a576ab5bSrab 	}
133843e1988Sjohnlev 
134843e1988Sjohnlev 	if (copy_err != 0 && *error >= 0)
135843e1988Sjohnlev 		*error = copy_err;
136843e1988Sjohnlev }
137843e1988Sjohnlev 
138843e1988Sjohnlev /*
139843e1988Sjohnlev  * Xen 'op' structures often include pointers disguised as 'handles', which
140843e1988Sjohnlev  * refer to addresses in user space.  This routine copies a buffer
141843e1988Sjohnlev  * associated with an embedded pointer into kernel space, and replaces the
142843e1988Sjohnlev  * pointer to userspace with a pointer to the new kernel buffer.
143843e1988Sjohnlev  *
144843e1988Sjohnlev  * Note: if Xen ever redefines the structure of a 'handle', this routine
145843e1988Sjohnlev  * (specifically the definition of 'hdl') will need to be updated.
146843e1988Sjohnlev  */
147843e1988Sjohnlev static int
import_handle(import_export_t * iep,void * field,size_t size,int flags)148843e1988Sjohnlev import_handle(import_export_t *iep, void *field, size_t size, int flags)
149843e1988Sjohnlev {
150843e1988Sjohnlev 	struct { void *p; } *hdl = field;
151843e1988Sjohnlev 	void *ptr;
152843e1988Sjohnlev 	int err;
153843e1988Sjohnlev 
154349b53ddSStuart Maybee 	ptr = uaddr_from_handle(field);
155843e1988Sjohnlev 	err = import_buffer(iep, ptr, NULL, size, (flags));
156a576ab5bSrab 	if (err == 0) {
157a576ab5bSrab 		/*LINTED: constant in conditional context*/
158a576ab5bSrab 		set_xen_guest_handle((*hdl), (void *)((iep)->ie_kaddr));
159a576ab5bSrab 	}
160843e1988Sjohnlev 	return (err);
161843e1988Sjohnlev }
162843e1988Sjohnlev 
163843e1988Sjohnlev static int
privcmd_HYPERVISOR_mmu_update(mmu_update_t * ureq,int count,int * scount,domid_t domid)164843e1988Sjohnlev privcmd_HYPERVISOR_mmu_update(mmu_update_t *ureq, int count, int *scount,
165843e1988Sjohnlev     domid_t domid)
166843e1988Sjohnlev {
167843e1988Sjohnlev 	mmu_update_t *kreq, single_kreq;
168843e1988Sjohnlev 	import_export_t cnt_ie, req_ie;
169843e1988Sjohnlev 	int error, kscount, bytes;
170843e1988Sjohnlev 
171843e1988Sjohnlev 	bytes = count * sizeof (*kreq);
172843e1988Sjohnlev 	kreq = (count == 1) ? &single_kreq : kmem_alloc(bytes, KM_SLEEP);
173843e1988Sjohnlev 
174843e1988Sjohnlev 	error = import_buffer(&cnt_ie, scount, &kscount, sizeof (kscount),
175843e1988Sjohnlev 	    IE_IMPEXP);
176843e1988Sjohnlev 	if (error != 0)
177843e1988Sjohnlev 		req_ie = null_ie;
178843e1988Sjohnlev 	else
179843e1988Sjohnlev 		error = import_buffer(&req_ie, ureq, kreq, bytes, IE_IMPEXP);
180843e1988Sjohnlev 
181843e1988Sjohnlev 	DTRACE_XPV3(mmu__update__start, int, domid, int, count, mmu_update_t *,
182843e1988Sjohnlev 	    ((error == -X_EFAULT) ? ureq : kreq));
183843e1988Sjohnlev 
184843e1988Sjohnlev 	if (error == 0)
185843e1988Sjohnlev 		error = HYPERVISOR_mmu_update(kreq, count, &kscount, domid);
186843e1988Sjohnlev 	export_buffer(&cnt_ie, &error);
187843e1988Sjohnlev 	export_buffer(&req_ie, &error);
188843e1988Sjohnlev 	if (count != 1)
189843e1988Sjohnlev 		kmem_free(kreq, bytes);
190843e1988Sjohnlev 
191843e1988Sjohnlev 	DTRACE_XPV1(mmu__update__end, int, error);
192843e1988Sjohnlev 	return (error);
193843e1988Sjohnlev }
194843e1988Sjohnlev 
195843e1988Sjohnlev static int
privcmd_HYPERVISOR_domctl(xen_domctl_t * opp)196843e1988Sjohnlev privcmd_HYPERVISOR_domctl(xen_domctl_t *opp)
197843e1988Sjohnlev {
198843e1988Sjohnlev 	xen_domctl_t op;
199843e1988Sjohnlev 	import_export_t op_ie, sub_ie;
200843e1988Sjohnlev 	int error = 0;
201843e1988Sjohnlev 
202843e1988Sjohnlev 	if ((error = import_buffer(&op_ie, opp, &op, sizeof (op),
203843e1988Sjohnlev 	    IE_IMPEXP)) != 0)
204843e1988Sjohnlev 		return (error);
205843e1988Sjohnlev 
206843e1988Sjohnlev 	sub_ie = null_ie;
207843e1988Sjohnlev 
208843e1988Sjohnlev 	/*
209843e1988Sjohnlev 	 * Check this first because our wrapper will forcibly overwrite it.
210843e1988Sjohnlev 	 */
211843e1988Sjohnlev 	if (op.interface_version != XEN_DOMCTL_INTERFACE_VERSION) {
212a576ab5bSrab #ifdef DEBUG
213a576ab5bSrab 		printf("domctl vers mismatch (cmd %d, found 0x%x, need 0x%x\n",
214a576ab5bSrab 		    op.cmd, op.interface_version, XEN_DOMCTL_INTERFACE_VERSION);
215a576ab5bSrab #endif
216843e1988Sjohnlev 		error = -X_EACCES;
217843e1988Sjohnlev 		export_buffer(&op_ie, &error);
218843e1988Sjohnlev 		return (error);
219843e1988Sjohnlev 	}
220843e1988Sjohnlev 
221843e1988Sjohnlev 	/*
222843e1988Sjohnlev 	 * Now handle any domctl ops with embedded pointers elsewhere
223843e1988Sjohnlev 	 * in the user address space that also need to be tacked down
224843e1988Sjohnlev 	 * while the hypervisor futzes with them.
225843e1988Sjohnlev 	 */
226843e1988Sjohnlev 	switch (op.cmd) {
227843e1988Sjohnlev 	case XEN_DOMCTL_createdomain:
228843e1988Sjohnlev 		DTRACE_XPV1(dom__create__start, xen_domctl_t *,
229843e1988Sjohnlev 		    &op.u.createdomain);
230843e1988Sjohnlev 		break;
231843e1988Sjohnlev 
232843e1988Sjohnlev 	case XEN_DOMCTL_destroydomain:
233843e1988Sjohnlev 		DTRACE_XPV1(dom__destroy__start, domid_t, op.domain);
234843e1988Sjohnlev 		break;
235843e1988Sjohnlev 
236843e1988Sjohnlev 	case XEN_DOMCTL_pausedomain:
237843e1988Sjohnlev 		DTRACE_XPV1(dom__pause__start, domid_t, op.domain);
238843e1988Sjohnlev 		break;
239843e1988Sjohnlev 
240843e1988Sjohnlev 	case XEN_DOMCTL_unpausedomain:
241843e1988Sjohnlev 		DTRACE_XPV1(dom__unpause__start, domid_t, op.domain);
242843e1988Sjohnlev 		break;
243843e1988Sjohnlev 
244843e1988Sjohnlev 	case XEN_DOMCTL_getmemlist: {
245843e1988Sjohnlev 		error = import_handle(&sub_ie, &op.u.getmemlist.buffer,
246843e1988Sjohnlev 		    op.u.getmemlist.max_pfns * sizeof (xen_pfn_t), IE_EXPORT);
247843e1988Sjohnlev 		break;
248843e1988Sjohnlev 	}
249843e1988Sjohnlev 
250843e1988Sjohnlev 	case XEN_DOMCTL_getpageframeinfo2: {
251843e1988Sjohnlev 		error = import_handle(&sub_ie, &op.u.getpageframeinfo2.array,
252843e1988Sjohnlev 		    op.u.getpageframeinfo2.num * sizeof (ulong_t), IE_IMPEXP);
253843e1988Sjohnlev 		break;
254843e1988Sjohnlev 	}
255843e1988Sjohnlev 
256843e1988Sjohnlev 	case XEN_DOMCTL_shadow_op: {
257843e1988Sjohnlev 		size_t size;
258843e1988Sjohnlev 
259843e1988Sjohnlev 		size = roundup(howmany(op.u.shadow_op.pages, NBBY),
260843e1988Sjohnlev 		    sizeof (ulong_t));
261a576ab5bSrab 		error = import_handle(&sub_ie,
262a576ab5bSrab 		    &op.u.shadow_op.dirty_bitmap, size, IE_IMPEXP);
263843e1988Sjohnlev 		break;
264843e1988Sjohnlev 	}
265843e1988Sjohnlev 
266843e1988Sjohnlev 	case XEN_DOMCTL_setvcpucontext: {
267843e1988Sjohnlev 		vcpu_guest_context_t *taddr;
268843e1988Sjohnlev 		error = import_handle(&sub_ie, &op.u.vcpucontext.ctxt,
269843e1988Sjohnlev 		    sizeof (vcpu_guest_context_t), IE_IMPORT);
270843e1988Sjohnlev 		if (error == -X_EFAULT)
271843e1988Sjohnlev 			/*LINTED: constant in conditional context*/
272a576ab5bSrab 			get_xen_guest_handle_u(taddr, op.u.vcpucontext.ctxt);
273843e1988Sjohnlev 		else
274843e1988Sjohnlev 			taddr = sub_ie.ie_kaddr;
275843e1988Sjohnlev 		DTRACE_XPV2(setvcpucontext__start, domid_t, op.domain,
276843e1988Sjohnlev 		    vcpu_guest_context_t *, taddr);
277843e1988Sjohnlev 		break;
278843e1988Sjohnlev 	}
279843e1988Sjohnlev 
280843e1988Sjohnlev 	case XEN_DOMCTL_getvcpucontext: {
281843e1988Sjohnlev 		error = import_handle(&sub_ie, &op.u.vcpucontext.ctxt,
282843e1988Sjohnlev 		    sizeof (vcpu_guest_context_t), IE_EXPORT);
283843e1988Sjohnlev 		break;
284843e1988Sjohnlev 	}
285843e1988Sjohnlev 
286a576ab5bSrab 
287a576ab5bSrab 	case XEN_DOMCTL_sethvmcontext: {
288a576ab5bSrab 		error = import_handle(&sub_ie, &op.u.hvmcontext.buffer,
289a576ab5bSrab 		    op.u.hvmcontext.size, IE_IMPORT);
290a576ab5bSrab 		break;
291a576ab5bSrab 	}
292a576ab5bSrab 
293a576ab5bSrab 	case XEN_DOMCTL_gethvmcontext: {
294a576ab5bSrab 		if (op.u.hvmcontext.buffer.p != NULL)
295a576ab5bSrab 			error = import_handle(&sub_ie, &op.u.hvmcontext.buffer,
296a576ab5bSrab 			    op.u.hvmcontext.size, IE_EXPORT);
297a576ab5bSrab 		break;
298a576ab5bSrab 	}
299a576ab5bSrab 
300349b53ddSStuart Maybee 	case XEN_DOMCTL_getdomaininfo:
301349b53ddSStuart Maybee 	case XEN_DOMCTL_getpageframeinfo:
302349b53ddSStuart Maybee 	case XEN_DOMCTL_max_mem:
303a576ab5bSrab 	case XEN_DOMCTL_resumedomain:
304843e1988Sjohnlev 	case XEN_DOMCTL_getvcpuinfo:
305843e1988Sjohnlev 	case XEN_DOMCTL_setvcpuaffinity:
306843e1988Sjohnlev 	case XEN_DOMCTL_getvcpuaffinity:
307843e1988Sjohnlev 	case XEN_DOMCTL_max_vcpus:
308843e1988Sjohnlev 	case XEN_DOMCTL_scheduler_op:
309843e1988Sjohnlev 	case XEN_DOMCTL_setdomainhandle:
310843e1988Sjohnlev 	case XEN_DOMCTL_setdebugging:
311843e1988Sjohnlev 	case XEN_DOMCTL_irq_permission:
312843e1988Sjohnlev 	case XEN_DOMCTL_iomem_permission:
313843e1988Sjohnlev 	case XEN_DOMCTL_ioport_permission:
314843e1988Sjohnlev 	case XEN_DOMCTL_hypercall_init:
315843e1988Sjohnlev 	case XEN_DOMCTL_arch_setup:
316843e1988Sjohnlev 	case XEN_DOMCTL_settimeoffset:
317843e1988Sjohnlev 	case XEN_DOMCTL_real_mode_area:
318a576ab5bSrab 	case XEN_DOMCTL_sendtrigger:
319349b53ddSStuart Maybee 	case XEN_DOMCTL_assign_device:
320349b53ddSStuart Maybee 	case XEN_DOMCTL_bind_pt_irq:
321349b53ddSStuart Maybee 	case XEN_DOMCTL_get_address_size:
322349b53ddSStuart Maybee 	case XEN_DOMCTL_set_address_size:
323349b53ddSStuart Maybee 	case XEN_DOMCTL_get_ext_vcpucontext:
324349b53ddSStuart Maybee 	case XEN_DOMCTL_set_ext_vcpucontext:
325349b53ddSStuart Maybee 	case XEN_DOMCTL_set_opt_feature:
326349b53ddSStuart Maybee 	case XEN_DOMCTL_memory_mapping:
327349b53ddSStuart Maybee 	case XEN_DOMCTL_ioport_mapping:
328349b53ddSStuart Maybee 	case XEN_DOMCTL_pin_mem_cacheattr:
329349b53ddSStuart Maybee 	case XEN_DOMCTL_test_assign_device:
330349b53ddSStuart Maybee 	case XEN_DOMCTL_set_target:
331349b53ddSStuart Maybee 	case XEN_DOMCTL_deassign_device:
332349b53ddSStuart Maybee 	case XEN_DOMCTL_set_cpuid:
333349b53ddSStuart Maybee 	case XEN_DOMCTL_get_device_group:
334349b53ddSStuart Maybee 	case XEN_DOMCTL_get_machine_address_size:
335349b53ddSStuart Maybee 	case XEN_DOMCTL_set_machine_address_size:
336349b53ddSStuart Maybee 	case XEN_DOMCTL_suppress_spurious_page_faults:
337843e1988Sjohnlev 		break;
338843e1988Sjohnlev 
339843e1988Sjohnlev 	default:
340843e1988Sjohnlev #ifdef DEBUG
341843e1988Sjohnlev 		printf("unrecognized HYPERVISOR_domctl %d\n", op.cmd);
342843e1988Sjohnlev #endif
343843e1988Sjohnlev 		error = -X_EINVAL;
344843e1988Sjohnlev 	}
345843e1988Sjohnlev 
346843e1988Sjohnlev 	if (error == 0)
347843e1988Sjohnlev 		error = HYPERVISOR_domctl(&op);
348843e1988Sjohnlev 
349843e1988Sjohnlev 	export_buffer(&op_ie, &error);
350843e1988Sjohnlev 	export_buffer(&sub_ie, &error);
351843e1988Sjohnlev 
352843e1988Sjohnlev 	switch (op.cmd) {
353843e1988Sjohnlev 	case XEN_DOMCTL_createdomain:
354843e1988Sjohnlev 		DTRACE_XPV1(dom__create__end, int, error);
355843e1988Sjohnlev 		break;
356843e1988Sjohnlev 	case XEN_DOMCTL_destroydomain:
357843e1988Sjohnlev 		DTRACE_XPV1(dom__destroy__end, int, error);
358843e1988Sjohnlev 		break;
359843e1988Sjohnlev 	case XEN_DOMCTL_pausedomain:
360843e1988Sjohnlev 		DTRACE_XPV1(dom__pause__end, int, error);
361843e1988Sjohnlev 		break;
362843e1988Sjohnlev 	case XEN_DOMCTL_unpausedomain:
363843e1988Sjohnlev 		DTRACE_XPV1(dom__unpause__end, int, error);
364843e1988Sjohnlev 		break;
365843e1988Sjohnlev 	case XEN_DOMCTL_setvcpucontext:
366843e1988Sjohnlev 		DTRACE_XPV1(setvcpucontext__end, int, error);
367843e1988Sjohnlev 		break;
368843e1988Sjohnlev 	default:
369843e1988Sjohnlev 		;
370843e1988Sjohnlev 	}
371843e1988Sjohnlev 
372843e1988Sjohnlev 	return (error);
373843e1988Sjohnlev }
374843e1988Sjohnlev 
375843e1988Sjohnlev static int
privcmd_HYPERVISOR_sysctl(xen_sysctl_t * opp)376843e1988Sjohnlev privcmd_HYPERVISOR_sysctl(xen_sysctl_t *opp)
377843e1988Sjohnlev {
378349b53ddSStuart Maybee 	xen_sysctl_t op, dop;
37933649781Smrj 	import_export_t op_ie, sub_ie, sub2_ie;
380843e1988Sjohnlev 	int error = 0;
381843e1988Sjohnlev 
382843e1988Sjohnlev 	if (import_buffer(&op_ie, opp, &op, sizeof (op), IE_IMPEXP) != 0)
383843e1988Sjohnlev 		return (-X_EFAULT);
384843e1988Sjohnlev 
385843e1988Sjohnlev 	sub_ie = null_ie;
38633649781Smrj 	sub2_ie = null_ie;
387843e1988Sjohnlev 
388843e1988Sjohnlev 	/*
389843e1988Sjohnlev 	 * Check this first because our wrapper will forcibly overwrite it.
390843e1988Sjohnlev 	 */
391843e1988Sjohnlev 	if (op.interface_version != XEN_SYSCTL_INTERFACE_VERSION) {
392843e1988Sjohnlev 		error = -X_EACCES;
393843e1988Sjohnlev 		export_buffer(&op_ie, &error);
394843e1988Sjohnlev 		return (error);
395843e1988Sjohnlev 	}
396843e1988Sjohnlev 
397843e1988Sjohnlev 	switch (op.cmd) {
398843e1988Sjohnlev 	case XEN_SYSCTL_readconsole: {
399843e1988Sjohnlev 		error = import_handle(&sub_ie, &op.u.readconsole.buffer,
400843e1988Sjohnlev 		    op.u.readconsole.count, IE_EXPORT);
401843e1988Sjohnlev 		break;
402843e1988Sjohnlev 	}
403843e1988Sjohnlev 
404a576ab5bSrab 	case XEN_SYSCTL_debug_keys: {
405a576ab5bSrab 		error = import_handle(&sub_ie, &op.u.debug_keys.keys,
406a576ab5bSrab 		    op.u.debug_keys.nr_keys, IE_IMPORT);
407a576ab5bSrab 		break;
408a576ab5bSrab 	}
409a576ab5bSrab 
410843e1988Sjohnlev 	case XEN_SYSCTL_tbuf_op:
411349b53ddSStuart Maybee 	case XEN_SYSCTL_physinfo: {
412349b53ddSStuart Maybee 		if (uaddr_from_handle(&op.u.physinfo.cpu_to_node) != NULL &&
413349b53ddSStuart Maybee 		    op.u.physinfo.max_cpu_id != 0) {
414349b53ddSStuart Maybee 			error = import_handle(&sub_ie,
415349b53ddSStuart Maybee 			    &op.u.physinfo.cpu_to_node,
416349b53ddSStuart Maybee 			    op.u.physinfo.max_cpu_id * sizeof (uint32_t),
417349b53ddSStuart Maybee 			    IE_EXPORT);
418349b53ddSStuart Maybee 		}
419349b53ddSStuart Maybee 		break;
420349b53ddSStuart Maybee 	}
421843e1988Sjohnlev 	case XEN_SYSCTL_sched_id:
422349b53ddSStuart Maybee 	case XEN_SYSCTL_availheap:
423349b53ddSStuart Maybee 	case XEN_SYSCTL_cpu_hotplug:
424349b53ddSStuart Maybee 		break;
425349b53ddSStuart Maybee 	case XEN_SYSCTL_get_pmstat: {
426349b53ddSStuart Maybee 		unsigned int maxs;
427349b53ddSStuart Maybee 
428349b53ddSStuart Maybee 		switch (op.u.get_pmstat.type) {
429349b53ddSStuart Maybee 		case PMSTAT_get_pxstat:
430349b53ddSStuart Maybee 			/*
431349b53ddSStuart Maybee 			 * This interface is broken. Xen always copies out
432349b53ddSStuart Maybee 			 * all the state information, and the interface
433349b53ddSStuart Maybee 			 * does not specify how much space the caller has
434349b53ddSStuart Maybee 			 * reserved. So, the only thing to do is just mirror
435349b53ddSStuart Maybee 			 * the hypervisor and libxc behavior, and use the
436349b53ddSStuart Maybee 			 * maximum amount of data.
437349b53ddSStuart Maybee 			 */
438349b53ddSStuart Maybee 			dop.cmd = XEN_SYSCTL_get_pmstat;
439349b53ddSStuart Maybee 			dop.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
440349b53ddSStuart Maybee 			dop.u.get_pmstat.cpuid = op.u.get_pmstat.cpuid;
441349b53ddSStuart Maybee 			dop.u.get_pmstat.type = PMSTAT_get_max_px;
442349b53ddSStuart Maybee 			error = HYPERVISOR_sysctl(&dop);
443349b53ddSStuart Maybee 			if (error != 0)
444349b53ddSStuart Maybee 				break;
445349b53ddSStuart Maybee 
446349b53ddSStuart Maybee 			maxs = dop.u.get_pmstat.u.getpx.total;
447349b53ddSStuart Maybee 			if (maxs == 0) {
448349b53ddSStuart Maybee 				error = -X_EINVAL;
449349b53ddSStuart Maybee 				break;
450349b53ddSStuart Maybee 			}
451349b53ddSStuart Maybee 
452349b53ddSStuart Maybee 			error = import_handle(&sub_ie,
453349b53ddSStuart Maybee 			    &op.u.get_pmstat.u.getpx.trans_pt,
454349b53ddSStuart Maybee 			    maxs * maxs * sizeof (uint64_t), IE_EXPORT);
455349b53ddSStuart Maybee 			if (error != 0)
456349b53ddSStuart Maybee 				break;
457349b53ddSStuart Maybee 
458349b53ddSStuart Maybee 			error = import_handle(&sub2_ie,
459349b53ddSStuart Maybee 			    &op.u.get_pmstat.u.getpx.pt,
460349b53ddSStuart Maybee 			    maxs * sizeof (pm_px_val_t), IE_EXPORT);
461349b53ddSStuart Maybee 			break;
462349b53ddSStuart Maybee 		case PMSTAT_get_cxstat:
463349b53ddSStuart Maybee 			/* See above */
464349b53ddSStuart Maybee 			dop.cmd = XEN_SYSCTL_get_pmstat;
465349b53ddSStuart Maybee 			dop.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
466349b53ddSStuart Maybee 			dop.u.get_pmstat.cpuid = op.u.get_pmstat.cpuid;
467349b53ddSStuart Maybee 			dop.u.get_pmstat.type = PMSTAT_get_max_cx;
468349b53ddSStuart Maybee 			error = HYPERVISOR_sysctl(&dop);
469349b53ddSStuart Maybee 			if (error != 0)
470349b53ddSStuart Maybee 				break;
471349b53ddSStuart Maybee 
472349b53ddSStuart Maybee 			maxs = dop.u.get_pmstat.u.getcx.nr;
473349b53ddSStuart Maybee 			if (maxs == 0) {
474349b53ddSStuart Maybee 				error = -X_EINVAL;
475349b53ddSStuart Maybee 				break;
476349b53ddSStuart Maybee 			}
477349b53ddSStuart Maybee 
478349b53ddSStuart Maybee 			error = import_handle(&sub_ie,
479349b53ddSStuart Maybee 			    &op.u.get_pmstat.u.getcx.triggers,
480349b53ddSStuart Maybee 			    maxs * sizeof (uint64_t), IE_EXPORT);
481349b53ddSStuart Maybee 			if (error != 0)
482349b53ddSStuart Maybee 				break;
483349b53ddSStuart Maybee 			error = import_handle(&sub2_ie,
484349b53ddSStuart Maybee 			    &op.u.get_pmstat.u.getcx.residencies,
485349b53ddSStuart Maybee 			    maxs * sizeof (uint64_t), IE_EXPORT);
486349b53ddSStuart Maybee 			break;
487349b53ddSStuart Maybee 
488349b53ddSStuart Maybee 		case PMSTAT_get_max_px:
489349b53ddSStuart Maybee 		case PMSTAT_reset_pxstat:
490349b53ddSStuart Maybee 		case PMSTAT_get_max_cx:
491349b53ddSStuart Maybee 		case PMSTAT_reset_cxstat:
492349b53ddSStuart Maybee 			break;
493349b53ddSStuart Maybee 		default:
494349b53ddSStuart Maybee 			error = -X_EINVAL;
495349b53ddSStuart Maybee 			break;
496349b53ddSStuart Maybee 		}
497843e1988Sjohnlev 		break;
498349b53ddSStuart Maybee 	}
499843e1988Sjohnlev 
500843e1988Sjohnlev 	case XEN_SYSCTL_perfc_op: {
501843e1988Sjohnlev 		xen_sysctl_perfc_desc_t *scdp;
502843e1988Sjohnlev 		/*
503843e1988Sjohnlev 		 * If 'desc' is NULL, then the caller is asking for
504843e1988Sjohnlev 		 * the number of counters.  If 'desc' is non-NULL,
505843e1988Sjohnlev 		 * then we need to know how many counters there are
506843e1988Sjohnlev 		 * before wiring down the output buffer appropriately.
507843e1988Sjohnlev 		 */
508843e1988Sjohnlev 		/*LINTED: constant in conditional context*/
509a576ab5bSrab 		get_xen_guest_handle_u(scdp, op.u.perfc_op.desc);
510843e1988Sjohnlev 		if (scdp != NULL) {
511843e1988Sjohnlev 			static int numcounters = -1;
51233649781Smrj 			static int numvals = -1;
513843e1988Sjohnlev 
514843e1988Sjohnlev 			if (numcounters == -1) {
515843e1988Sjohnlev 				dop.cmd = XEN_SYSCTL_perfc_op;
516843e1988Sjohnlev 				dop.interface_version =
517843e1988Sjohnlev 				    XEN_SYSCTL_INTERFACE_VERSION;
518843e1988Sjohnlev 				dop.u.perfc_op.cmd = XEN_SYSCTL_PERFCOP_query;
51933649781Smrj 				/*LINTED: constant in conditional context*/
52033649781Smrj 				set_xen_guest_handle_u(dop.u.perfc_op.desc,
52133649781Smrj 				    NULL);
52233649781Smrj 				/*LINTED: constant in conditional context*/
52333649781Smrj 				set_xen_guest_handle_u(dop.u.perfc_op.val,
52433649781Smrj 				    NULL);
525843e1988Sjohnlev 
526843e1988Sjohnlev 				error = HYPERVISOR_sysctl(&dop);
527843e1988Sjohnlev 				if (error != 0)
528843e1988Sjohnlev 					break;
529843e1988Sjohnlev 				numcounters = dop.u.perfc_op.nr_counters;
53033649781Smrj 				numvals = dop.u.perfc_op.nr_vals;
531843e1988Sjohnlev 			}
532843e1988Sjohnlev 			ASSERT(numcounters != -1);
53333649781Smrj 			ASSERT(numvals != -1);
534843e1988Sjohnlev 			error = import_handle(&sub_ie, &op.u.perfc_op.desc,
535843e1988Sjohnlev 			    (sizeof (xen_sysctl_perfc_desc_t) * numcounters),
536843e1988Sjohnlev 			    IE_EXPORT);
53733649781Smrj 			error = import_handle(&sub2_ie, &op.u.perfc_op.val,
53833649781Smrj 			    (sizeof (xen_sysctl_perfc_val_t) * numvals),
53933649781Smrj 			    IE_EXPORT);
540843e1988Sjohnlev 		}
541843e1988Sjohnlev 		break;
542843e1988Sjohnlev 	}
543843e1988Sjohnlev 
544843e1988Sjohnlev 	case XEN_SYSCTL_getdomaininfolist: {
545843e1988Sjohnlev 		error = import_handle(&sub_ie, &op.u.getdomaininfolist.buffer,
546843e1988Sjohnlev 		    (op.u.getdomaininfolist.max_domains *
547843e1988Sjohnlev 		    sizeof (xen_domctl_getdomaininfo_t)), IE_EXPORT);
548843e1988Sjohnlev 		break;
549843e1988Sjohnlev 	}
550843e1988Sjohnlev 
551a576ab5bSrab 	case XEN_SYSCTL_getcpuinfo:
552a576ab5bSrab 		error = import_handle(&sub_ie, &op.u.getcpuinfo.info,
553a576ab5bSrab 		    op.u.getcpuinfo.max_cpus *
554a576ab5bSrab 		    sizeof (xen_sysctl_cpuinfo_t), IE_EXPORT);
555a576ab5bSrab 		break;
556843e1988Sjohnlev 	default:
557843e1988Sjohnlev #ifdef DEBUG
558843e1988Sjohnlev 		printf("unrecognized HYPERVISOR_sysctl %d\n", op.cmd);
559843e1988Sjohnlev #endif
560843e1988Sjohnlev 		error = -X_EINVAL;
561843e1988Sjohnlev 	}
562843e1988Sjohnlev 
563843e1988Sjohnlev 	if (error == 0)
564843e1988Sjohnlev 		error = HYPERVISOR_sysctl(&op);
565843e1988Sjohnlev 
566843e1988Sjohnlev 	export_buffer(&op_ie, &error);
567843e1988Sjohnlev 	export_buffer(&sub_ie, &error);
56833649781Smrj 	export_buffer(&sub2_ie, &error);
569843e1988Sjohnlev 
570843e1988Sjohnlev 	return (error);
571843e1988Sjohnlev }
572843e1988Sjohnlev 
573843e1988Sjohnlev static int
privcmd_HYPERVISOR_platform_op(xen_platform_op_t * opp)574843e1988Sjohnlev privcmd_HYPERVISOR_platform_op(xen_platform_op_t *opp)
575843e1988Sjohnlev {
576349b53ddSStuart Maybee 	import_export_t op_ie, sub_ie, sub2_ie;
577843e1988Sjohnlev 	xen_platform_op_t op;
578843e1988Sjohnlev 	int error;
579843e1988Sjohnlev 
580843e1988Sjohnlev 	if (import_buffer(&op_ie, opp, &op, sizeof (op), IE_IMPEXP) != 0)
581843e1988Sjohnlev 		return (-X_EFAULT);
582843e1988Sjohnlev 
583843e1988Sjohnlev 	sub_ie = null_ie;
584349b53ddSStuart Maybee 	sub2_ie = null_ie;
585843e1988Sjohnlev 
586843e1988Sjohnlev 	/*
587843e1988Sjohnlev 	 * Check this first because our wrapper will forcibly overwrite it.
588843e1988Sjohnlev 	 */
589843e1988Sjohnlev 	if (op.interface_version != XENPF_INTERFACE_VERSION) {
590843e1988Sjohnlev 		error = -X_EACCES;
591843e1988Sjohnlev 		export_buffer(&op_ie, &error);
592843e1988Sjohnlev 		return (error);
593843e1988Sjohnlev 	}
594843e1988Sjohnlev 
595843e1988Sjohnlev 	/*
596843e1988Sjohnlev 	 * Now handle any platform ops with embedded pointers elsewhere
597843e1988Sjohnlev 	 * in the user address space that also need to be tacked down
598843e1988Sjohnlev 	 * while the hypervisor futzes with them.
599843e1988Sjohnlev 	 */
600843e1988Sjohnlev 	switch (op.cmd) {
601843e1988Sjohnlev 	case XENPF_settime:
602843e1988Sjohnlev 	case XENPF_add_memtype:
603843e1988Sjohnlev 	case XENPF_del_memtype:
604843e1988Sjohnlev 	case XENPF_read_memtype:
605843e1988Sjohnlev 	case XENPF_platform_quirk:
606349b53ddSStuart Maybee 	case XENPF_enter_acpi_sleep:
607349b53ddSStuart Maybee 	case XENPF_change_freq:
608349b53ddSStuart Maybee 	case XENPF_panic_init:
609843e1988Sjohnlev 		break;
610843e1988Sjohnlev 
611843e1988Sjohnlev 	case XENPF_microcode_update:
612843e1988Sjohnlev 		error = import_handle(&sub_ie, &op.u.microcode.data,
613843e1988Sjohnlev 		    op.u.microcode.length, IE_IMPORT);
614843e1988Sjohnlev 		break;
615349b53ddSStuart Maybee 	case XENPF_getidletime:
616349b53ddSStuart Maybee 		error = import_handle(&sub_ie, &op.u.getidletime.cpumap_bitmap,
617349b53ddSStuart Maybee 		    op.u.getidletime.cpumap_nr_cpus, IE_IMPEXP);
618349b53ddSStuart Maybee 		if (error != 0)
619349b53ddSStuart Maybee 			break;
620843e1988Sjohnlev 
621349b53ddSStuart Maybee 		error = import_handle(&sub2_ie, &op.u.getidletime.idletime,
622349b53ddSStuart Maybee 		    op.u.getidletime.cpumap_nr_cpus * sizeof (uint64_t),
623349b53ddSStuart Maybee 		    IE_EXPORT);
624349b53ddSStuart Maybee 		break;
625349b53ddSStuart Maybee 
626349b53ddSStuart Maybee 	case XENPF_set_processor_pminfo: {
627349b53ddSStuart Maybee 		size_t s;
628349b53ddSStuart Maybee 
629349b53ddSStuart Maybee 		switch (op.u.set_pminfo.type) {
630349b53ddSStuart Maybee 		case XEN_PM_PX:
631349b53ddSStuart Maybee 			s = op.u.set_pminfo.u.perf.state_count *
632349b53ddSStuart Maybee 			    sizeof (xen_processor_px_t);
633349b53ddSStuart Maybee 			if (op.u.set_pminfo.u.perf.flags & XEN_PX_PSS) {
634349b53ddSStuart Maybee 				error = import_handle(&sub_ie,
635349b53ddSStuart Maybee 				    &op.u.set_pminfo.u.perf.states, s,
636349b53ddSStuart Maybee 				    IE_IMPORT);
637349b53ddSStuart Maybee 			}
638349b53ddSStuart Maybee 			break;
639349b53ddSStuart Maybee 		case XEN_PM_CX:
640349b53ddSStuart Maybee 			s = op.u.set_pminfo.u.power.count *
641349b53ddSStuart Maybee 			    sizeof (xen_processor_cx_t);
642349b53ddSStuart Maybee 			error = import_handle(&sub_ie,
643349b53ddSStuart Maybee 			    &op.u.set_pminfo.u.power.states, s, IE_IMPORT);
644349b53ddSStuart Maybee 			break;
645349b53ddSStuart Maybee 		case XEN_PM_TX:
646349b53ddSStuart Maybee 			break;
647349b53ddSStuart Maybee 		default:
648349b53ddSStuart Maybee 			error = -X_EINVAL;
649349b53ddSStuart Maybee 			break;
650349b53ddSStuart Maybee 		}
651349b53ddSStuart Maybee 		break;
652349b53ddSStuart Maybee 	}
653349b53ddSStuart Maybee 	case XENPF_firmware_info: {
654349b53ddSStuart Maybee 		uint16_t len;
655349b53ddSStuart Maybee 		void *uaddr;
656349b53ddSStuart Maybee 
657349b53ddSStuart Maybee 		switch (op.u.firmware_info.type) {
658349b53ddSStuart Maybee 		case XEN_FW_DISK_INFO:
659349b53ddSStuart Maybee 			/*
660349b53ddSStuart Maybee 			 * Ugh.. another hokey interface. The first 16 bits
661349b53ddSStuart Maybee 			 * of the buffer are also used as the (input) length.
662349b53ddSStuart Maybee 			 */
663349b53ddSStuart Maybee 			uaddr = uaddr_from_handle(
664349b53ddSStuart Maybee 			    &op.u.firmware_info.u.disk_info.edd_params);
665349b53ddSStuart Maybee 			error = ddi_copyin(uaddr, &len, sizeof (len), 0);
666349b53ddSStuart Maybee 			if (error != 0)
667349b53ddSStuart Maybee 				break;
668349b53ddSStuart Maybee 			error = import_handle(&sub_ie,
669349b53ddSStuart Maybee 			    &op.u.firmware_info.u.disk_info.edd_params, len,
670349b53ddSStuart Maybee 			    IE_IMPEXP);
671349b53ddSStuart Maybee 			break;
672349b53ddSStuart Maybee 		case XEN_FW_VBEDDC_INFO:
673349b53ddSStuart Maybee 			error = import_handle(&sub_ie,
674349b53ddSStuart Maybee 			    &op.u.firmware_info.u.vbeddc_info.edid, 128,
675349b53ddSStuart Maybee 			    IE_EXPORT);
676349b53ddSStuart Maybee 			break;
677349b53ddSStuart Maybee 		case XEN_FW_DISK_MBR_SIGNATURE:
678349b53ddSStuart Maybee 		default:
679349b53ddSStuart Maybee 			break;
680349b53ddSStuart Maybee 		}
681349b53ddSStuart Maybee 		break;
682349b53ddSStuart Maybee 	}
683843e1988Sjohnlev 	default:
684349b53ddSStuart Maybee 		/* FIXME: see this with non-existed ID 38 ???? */
685843e1988Sjohnlev #ifdef DEBUG
686349b53ddSStuart Maybee 		printf("unrecognized HYPERVISOR_platform_op %d pid %d\n",
687349b53ddSStuart Maybee 		    op.cmd, curthread->t_procp->p_pid);
688843e1988Sjohnlev #endif
689843e1988Sjohnlev 		return (-X_EINVAL);
690843e1988Sjohnlev 	}
691843e1988Sjohnlev 
692843e1988Sjohnlev 	if (error == 0)
693843e1988Sjohnlev 		error = HYPERVISOR_platform_op(&op);
694843e1988Sjohnlev 
695843e1988Sjohnlev 	export_buffer(&op_ie, &error);
696843e1988Sjohnlev 	export_buffer(&sub_ie, &error);
697349b53ddSStuart Maybee 	export_buffer(&sub2_ie, &error);
698843e1988Sjohnlev 
699843e1988Sjohnlev 	return (error);
700843e1988Sjohnlev }
701843e1988Sjohnlev 
702843e1988Sjohnlev static int
privcmd_HYPERVISOR_memory_op(int cmd,void * arg)703843e1988Sjohnlev privcmd_HYPERVISOR_memory_op(int cmd, void *arg)
704843e1988Sjohnlev {
705843e1988Sjohnlev 	int error = 0;
706843e1988Sjohnlev 	import_export_t op_ie, sub_ie, gpfn_ie, mfn_ie;
707843e1988Sjohnlev 	union {
708843e1988Sjohnlev 		domid_t domid;
709843e1988Sjohnlev 		struct xen_memory_reservation resv;
710843e1988Sjohnlev 		struct xen_machphys_mfn_list xmml;
711843e1988Sjohnlev 		struct xen_add_to_physmap xatp;
712843e1988Sjohnlev 		struct xen_memory_map mm;
713843e1988Sjohnlev 		struct xen_foreign_memory_map fmm;
714525b892bSMark Johnson 		struct xen_pod_target pd;
715843e1988Sjohnlev 	} op_arg;
716843e1988Sjohnlev 
717843e1988Sjohnlev 	op_ie = sub_ie = gpfn_ie = mfn_ie = null_ie;
718843e1988Sjohnlev 
719843e1988Sjohnlev 	switch (cmd) {
720843e1988Sjohnlev 	case XENMEM_increase_reservation:
721843e1988Sjohnlev 	case XENMEM_decrease_reservation:
722843e1988Sjohnlev 	case XENMEM_populate_physmap: {
723843e1988Sjohnlev 		ulong_t *taddr;
724843e1988Sjohnlev 
725843e1988Sjohnlev 		if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.resv),
726843e1988Sjohnlev 		    IE_IMPEXP) != 0)
727843e1988Sjohnlev 			return (-X_EFAULT);
728843e1988Sjohnlev 
729843e1988Sjohnlev 		error = import_handle(&sub_ie, &op_arg.resv.extent_start,
730843e1988Sjohnlev 		    (op_arg.resv.nr_extents * sizeof (ulong_t)), IE_IMPEXP);
731843e1988Sjohnlev 
732843e1988Sjohnlev 		if (error == -X_EFAULT)
733843e1988Sjohnlev 			/*LINTED: constant in conditional context*/
734843e1988Sjohnlev 			get_xen_guest_handle(taddr, op_arg.resv.extent_start);
735843e1988Sjohnlev 		else
736843e1988Sjohnlev 			taddr = sub_ie.ie_kaddr;
737843e1988Sjohnlev 
738843e1988Sjohnlev 		switch (cmd) {
739843e1988Sjohnlev 		case XENMEM_increase_reservation:
740843e1988Sjohnlev 			DTRACE_XPV4(increase__reservation__start,
741843e1988Sjohnlev 			    domid_t, op_arg.resv.domid,
742843e1988Sjohnlev 			    ulong_t, op_arg.resv.nr_extents,
743843e1988Sjohnlev 			    uint_t, op_arg.resv.extent_order,
744843e1988Sjohnlev 			    ulong_t *, taddr);
745843e1988Sjohnlev 			break;
746843e1988Sjohnlev 		case XENMEM_decrease_reservation:
747843e1988Sjohnlev 			DTRACE_XPV4(decrease__reservation__start,
748843e1988Sjohnlev 			    domid_t, op_arg.resv.domid,
749843e1988Sjohnlev 			    ulong_t, op_arg.resv.nr_extents,
750843e1988Sjohnlev 			    uint_t, op_arg.resv.extent_order,
751843e1988Sjohnlev 			    ulong_t *, taddr);
752843e1988Sjohnlev 			break;
753843e1988Sjohnlev 		case XENMEM_populate_physmap:
754843e1988Sjohnlev 			DTRACE_XPV3(populate__physmap__start,
755843e1988Sjohnlev 			    domid_t, op_arg.resv.domid,
756843e1988Sjohnlev 			    ulong_t, op_arg.resv.nr_extents,
757843e1988Sjohnlev 			    ulong_t *, taddr);
758843e1988Sjohnlev 			break;
759843e1988Sjohnlev 		}
760843e1988Sjohnlev 
761843e1988Sjohnlev 		break;
762843e1988Sjohnlev 	}
763843e1988Sjohnlev 
764843e1988Sjohnlev 	case XENMEM_maximum_ram_page:
765843e1988Sjohnlev 		break;
766843e1988Sjohnlev 
767843e1988Sjohnlev 	case XENMEM_current_reservation:
768843e1988Sjohnlev 	case XENMEM_maximum_reservation:
769a576ab5bSrab 	case XENMEM_maximum_gpfn:
770843e1988Sjohnlev 		if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.domid),
771843e1988Sjohnlev 		    IE_IMPEXP) != 0)
772843e1988Sjohnlev 			return (-X_EFAULT);
773843e1988Sjohnlev 		break;
774843e1988Sjohnlev 
775843e1988Sjohnlev 	case XENMEM_machphys_mfn_list: {
776843e1988Sjohnlev 		if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.xmml),
777843e1988Sjohnlev 		    IE_IMPEXP) != 0)
778843e1988Sjohnlev 			return (-X_EFAULT);
779843e1988Sjohnlev 
780843e1988Sjohnlev 		error = import_handle(&sub_ie, &op_arg.xmml.extent_start,
781843e1988Sjohnlev 		    (op_arg.xmml.max_extents * sizeof (ulong_t)), IE_IMPEXP);
782843e1988Sjohnlev 		break;
783843e1988Sjohnlev 	}
784843e1988Sjohnlev 
785843e1988Sjohnlev 	case XENMEM_add_to_physmap:
786843e1988Sjohnlev 		if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.xatp),
787843e1988Sjohnlev 		    IE_IMPEXP) != 0)
788843e1988Sjohnlev 			return (-X_EFAULT);
789843e1988Sjohnlev 		DTRACE_XPV4(add__to__physmap__start, domid_t,
790843e1988Sjohnlev 		    op_arg.xatp.domid, uint_t, op_arg.xatp.space, ulong_t,
791843e1988Sjohnlev 		    op_arg.xatp.idx, ulong_t, op_arg.xatp.gpfn);
792843e1988Sjohnlev 		break;
793843e1988Sjohnlev 
794843e1988Sjohnlev 	case XENMEM_memory_map:
795843e1988Sjohnlev 	case XENMEM_machine_memory_map: {
796843e1988Sjohnlev 		if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.mm),
797843e1988Sjohnlev 		    IE_EXPORT) != 0)
798843e1988Sjohnlev 			return (-X_EFAULT);
799843e1988Sjohnlev 
800843e1988Sjohnlev 		/*
801843e1988Sjohnlev 		 * XXPV: ugh. e820entry is packed, but not in the kernel, since
802843e1988Sjohnlev 		 * we remove all attributes; seems like this is a nice way to
803843e1988Sjohnlev 		 * break mysteriously.
804843e1988Sjohnlev 		 */
805843e1988Sjohnlev 		error = import_handle(&sub_ie, &op_arg.mm.buffer,
806843e1988Sjohnlev 		    (op_arg.mm.nr_entries * 20), IE_IMPEXP);
807843e1988Sjohnlev 		break;
808843e1988Sjohnlev 	}
809843e1988Sjohnlev 
810843e1988Sjohnlev 	case XENMEM_set_memory_map: {
811843e1988Sjohnlev 		struct xen_memory_map *taddr;
812843e1988Sjohnlev 		if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.fmm),
813843e1988Sjohnlev 		    IE_IMPORT) != 0)
814843e1988Sjohnlev 			return (-X_EFAULT);
815843e1988Sjohnlev 
816843e1988Sjohnlev 		/*
817843e1988Sjohnlev 		 * As above.
818843e1988Sjohnlev 		 */
819843e1988Sjohnlev 		error = import_handle(&sub_ie, &op_arg.fmm.map.buffer,
820843e1988Sjohnlev 		    (op_arg.fmm.map.nr_entries * 20), IE_IMPEXP);
821843e1988Sjohnlev 
822843e1988Sjohnlev 		if (error == -X_EFAULT)
823843e1988Sjohnlev 			/*LINTED: constant in conditional context*/
824843e1988Sjohnlev 			get_xen_guest_handle(taddr, op_arg.fmm.map.buffer);
825843e1988Sjohnlev 		else
826843e1988Sjohnlev 			taddr = sub_ie.ie_kaddr;
827843e1988Sjohnlev 		DTRACE_XPV3(set__memory__map__start, domid_t,
828843e1988Sjohnlev 		    op_arg.fmm.domid, int, op_arg.fmm.map.nr_entries,
829843e1988Sjohnlev 		    struct xen_memory_map *, taddr);
830843e1988Sjohnlev 		break;
831843e1988Sjohnlev 	}
832843e1988Sjohnlev 
833525b892bSMark Johnson 	case XENMEM_set_pod_target:
834525b892bSMark Johnson 	case XENMEM_get_pod_target:
835525b892bSMark Johnson 		if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.pd),
836525b892bSMark Johnson 		    IE_IMPEXP) != 0)
837525b892bSMark Johnson 			return (-X_EFAULT);
838525b892bSMark Johnson 		break;
839525b892bSMark Johnson 
840843e1988Sjohnlev 	default:
841843e1988Sjohnlev #ifdef DEBUG
842843e1988Sjohnlev 		printf("unrecognized HYPERVISOR_memory_op %d\n", cmd);
843843e1988Sjohnlev #endif
844843e1988Sjohnlev 		return (-X_EINVAL);
845843e1988Sjohnlev 	}
846843e1988Sjohnlev 
847843e1988Sjohnlev 	if (error == 0)
848843e1988Sjohnlev 		error = HYPERVISOR_memory_op(cmd,
849843e1988Sjohnlev 		    (arg == NULL) ? NULL: &op_arg);
850843e1988Sjohnlev 
851843e1988Sjohnlev 	export_buffer(&op_ie, &error);
852843e1988Sjohnlev 	export_buffer(&sub_ie, &error);
853843e1988Sjohnlev 	export_buffer(&gpfn_ie, &error);
854843e1988Sjohnlev 	export_buffer(&mfn_ie, &error);
855843e1988Sjohnlev 
856843e1988Sjohnlev 	switch (cmd) {
857843e1988Sjohnlev 	case XENMEM_increase_reservation:
858843e1988Sjohnlev 		DTRACE_XPV1(increase__reservation__end, int, error);
859843e1988Sjohnlev 		break;
860843e1988Sjohnlev 	case XENMEM_decrease_reservation:
861843e1988Sjohnlev 		DTRACE_XPV1(decrease__reservation__end, int, error);
862843e1988Sjohnlev 		break;
863843e1988Sjohnlev 	case XENMEM_populate_physmap:
864843e1988Sjohnlev 		DTRACE_XPV1(populate__physmap__end, int, error);
865843e1988Sjohnlev 		break;
866843e1988Sjohnlev 	case XENMEM_add_to_physmap:
867843e1988Sjohnlev 		DTRACE_XPV1(add__to__physmap__end, int, error);
868843e1988Sjohnlev 		break;
869843e1988Sjohnlev 	case XENMEM_set_memory_map:
870843e1988Sjohnlev 		DTRACE_XPV1(set__memory__map__end, int, error);
871843e1988Sjohnlev 		break;
872843e1988Sjohnlev 	}
873843e1988Sjohnlev 	return (error);
874843e1988Sjohnlev }
875843e1988Sjohnlev 
876843e1988Sjohnlev static int
privcmd_HYPERVISOR_event_channel_op(int cmd,void * arg)877843e1988Sjohnlev privcmd_HYPERVISOR_event_channel_op(int cmd, void *arg)
878843e1988Sjohnlev {
879843e1988Sjohnlev 	int error;
880843e1988Sjohnlev 	size_t size;
881843e1988Sjohnlev 	import_export_t op_ie;
882843e1988Sjohnlev 	uint32_t flags;
883843e1988Sjohnlev 
884843e1988Sjohnlev 	switch (cmd) {
885843e1988Sjohnlev 	case EVTCHNOP_alloc_unbound:
886843e1988Sjohnlev 		size = sizeof (evtchn_alloc_unbound_t);
887843e1988Sjohnlev 		flags = IE_IMPEXP;
888843e1988Sjohnlev 		break;
889843e1988Sjohnlev 	case EVTCHNOP_bind_interdomain:
890843e1988Sjohnlev 		size = sizeof (evtchn_bind_interdomain_t);
891843e1988Sjohnlev 		flags = IE_IMPEXP;
892843e1988Sjohnlev 		break;
893843e1988Sjohnlev 	case EVTCHNOP_bind_virq:
894843e1988Sjohnlev 		size = sizeof (evtchn_bind_virq_t);
895843e1988Sjohnlev 		flags = IE_IMPEXP;
896843e1988Sjohnlev 		break;
897843e1988Sjohnlev 	case EVTCHNOP_bind_pirq:
898843e1988Sjohnlev 		size = sizeof (evtchn_bind_pirq_t);
899843e1988Sjohnlev 		flags = IE_IMPEXP;
900843e1988Sjohnlev 		break;
901843e1988Sjohnlev 	case EVTCHNOP_bind_ipi:
902843e1988Sjohnlev 		size = sizeof (evtchn_bind_ipi_t);
903843e1988Sjohnlev 		flags = IE_IMPEXP;
904843e1988Sjohnlev 		break;
905843e1988Sjohnlev 	case EVTCHNOP_close:
906843e1988Sjohnlev 		size = sizeof (evtchn_close_t);
907843e1988Sjohnlev 		flags = IE_IMPORT;
908843e1988Sjohnlev 		break;
909843e1988Sjohnlev 	case EVTCHNOP_send:
910843e1988Sjohnlev 		size = sizeof (evtchn_send_t);
911843e1988Sjohnlev 		flags = IE_IMPORT;
912843e1988Sjohnlev 		break;
913843e1988Sjohnlev 	case EVTCHNOP_status:
914843e1988Sjohnlev 		size = sizeof (evtchn_status_t);
915843e1988Sjohnlev 		flags = IE_IMPEXP;
916843e1988Sjohnlev 		break;
917843e1988Sjohnlev 	case EVTCHNOP_bind_vcpu:
918843e1988Sjohnlev 		size = sizeof (evtchn_bind_vcpu_t);
919843e1988Sjohnlev 		flags = IE_IMPORT;
920843e1988Sjohnlev 		break;
921843e1988Sjohnlev 	case EVTCHNOP_unmask:
922843e1988Sjohnlev 		size = sizeof (evtchn_unmask_t);
923843e1988Sjohnlev 		flags = IE_IMPORT;
924843e1988Sjohnlev 		break;
925a576ab5bSrab 	case EVTCHNOP_reset:
926a576ab5bSrab 		size = sizeof (evtchn_reset_t);
927a576ab5bSrab 		flags = IE_IMPORT;
928a576ab5bSrab 		break;
929843e1988Sjohnlev 
930843e1988Sjohnlev 	default:
931843e1988Sjohnlev #ifdef DEBUG
932843e1988Sjohnlev 		printf("unrecognized HYPERVISOR_event_channel op %d\n", cmd);
933843e1988Sjohnlev #endif
934843e1988Sjohnlev 		return (-X_EINVAL);
935843e1988Sjohnlev 	}
936843e1988Sjohnlev 
937843e1988Sjohnlev 	error = import_buffer(&op_ie, arg, NULL, size, flags);
938843e1988Sjohnlev 
939843e1988Sjohnlev 	/*
940843e1988Sjohnlev 	 * If there is sufficient demand, we can replace this void * with
941843e1988Sjohnlev 	 * the proper op structure pointer.
942843e1988Sjohnlev 	 */
943843e1988Sjohnlev 	DTRACE_XPV2(evtchn__op__start, int, cmd, void *,
944843e1988Sjohnlev 	    ((error == -X_EFAULT) ? arg : op_ie.ie_kaddr));
945843e1988Sjohnlev 
946843e1988Sjohnlev 	if (error == 0)
947843e1988Sjohnlev 		error = HYPERVISOR_event_channel_op(cmd, op_ie.ie_kaddr);
948843e1988Sjohnlev 	export_buffer(&op_ie, &error);
949843e1988Sjohnlev 
950843e1988Sjohnlev 	DTRACE_XPV1(evtchn__op__end, int, error);
951843e1988Sjohnlev 
952843e1988Sjohnlev 	return (error);
953843e1988Sjohnlev }
954843e1988Sjohnlev 
955843e1988Sjohnlev static int
privcmd_HYPERVISOR_xen_version(int cmd,void * arg)956843e1988Sjohnlev privcmd_HYPERVISOR_xen_version(int cmd, void *arg)
957843e1988Sjohnlev {
958843e1988Sjohnlev 	int error;
959843e1988Sjohnlev 	int size = 0;
960843e1988Sjohnlev 	import_export_t op_ie;
961843e1988Sjohnlev 	uint32_t flags = IE_EXPORT;
962843e1988Sjohnlev 
963843e1988Sjohnlev 	switch (cmd) {
964843e1988Sjohnlev 	case XENVER_version:
965843e1988Sjohnlev 		break;
966843e1988Sjohnlev 	case XENVER_extraversion:
967843e1988Sjohnlev 		size = sizeof (xen_extraversion_t);
968843e1988Sjohnlev 		break;
969843e1988Sjohnlev 	case XENVER_compile_info:
970843e1988Sjohnlev 		size = sizeof (xen_compile_info_t);
971843e1988Sjohnlev 		break;
972843e1988Sjohnlev 	case XENVER_capabilities:
973843e1988Sjohnlev 		size = sizeof (xen_capabilities_info_t);
974843e1988Sjohnlev 		break;
975843e1988Sjohnlev 	case XENVER_changeset:
976843e1988Sjohnlev 		size = sizeof (xen_changeset_info_t);
977843e1988Sjohnlev 		break;
978843e1988Sjohnlev 	case XENVER_platform_parameters:
979843e1988Sjohnlev 		size = sizeof (xen_platform_parameters_t);
980843e1988Sjohnlev 		break;
981843e1988Sjohnlev 	case XENVER_get_features:
982843e1988Sjohnlev 		flags = IE_IMPEXP;
983843e1988Sjohnlev 		size = sizeof (xen_feature_info_t);
984843e1988Sjohnlev 		break;
985843e1988Sjohnlev 	case XENVER_pagesize:
986843e1988Sjohnlev 		break;
987843e1988Sjohnlev 	case XENVER_guest_handle:
988843e1988Sjohnlev 		size = sizeof (xen_domain_handle_t);
989843e1988Sjohnlev 		break;
990843e1988Sjohnlev 
991843e1988Sjohnlev 	default:
992843e1988Sjohnlev #ifdef DEBUG
993843e1988Sjohnlev 		printf("unrecognized HYPERVISOR_xen_version op %d\n", cmd);
994843e1988Sjohnlev #endif
995843e1988Sjohnlev 		return (-X_EINVAL);
996843e1988Sjohnlev 	}
997843e1988Sjohnlev 
998843e1988Sjohnlev 	error = import_buffer(&op_ie, arg, NULL, size, flags);
999843e1988Sjohnlev 	if (error == 0)
1000843e1988Sjohnlev 		error = HYPERVISOR_xen_version(cmd, op_ie.ie_kaddr);
1001843e1988Sjohnlev 	export_buffer(&op_ie, &error);
1002843e1988Sjohnlev 
1003843e1988Sjohnlev 	return (error);
1004843e1988Sjohnlev }
1005843e1988Sjohnlev 
1006843e1988Sjohnlev static int
privcmd_HYPERVISOR_xsm_op(void * uacmctl)1007349b53ddSStuart Maybee privcmd_HYPERVISOR_xsm_op(void *uacmctl)
1008843e1988Sjohnlev {
1009843e1988Sjohnlev 	int error;
1010a576ab5bSrab 	struct xen_acmctl *acmctl;
1011843e1988Sjohnlev 	import_export_t op_ie;
1012843e1988Sjohnlev 
1013a576ab5bSrab 	error = import_buffer(&op_ie, uacmctl, NULL, sizeof (*acmctl),
1014a576ab5bSrab 	    IE_IMPEXP);
1015a576ab5bSrab 	if (error != 0)
1016a576ab5bSrab 		return (error);
1017a576ab5bSrab 
1018a576ab5bSrab 	acmctl = op_ie.ie_kaddr;
1019a576ab5bSrab 
1020a576ab5bSrab 	if (acmctl->interface_version != ACM_INTERFACE_VERSION) {
1021a576ab5bSrab #ifdef DEBUG
1022a576ab5bSrab 		printf("acm vers mismatch (cmd %d, found 0x%x, need 0x%x\n",
1023a576ab5bSrab 		    acmctl->cmd, acmctl->interface_version,
1024a576ab5bSrab 		    ACM_INTERFACE_VERSION);
1025a576ab5bSrab #endif
1026a576ab5bSrab 		error = -X_EACCES;
1027a576ab5bSrab 		export_buffer(&op_ie, &error);
1028a576ab5bSrab 		return (error);
1029a576ab5bSrab 	}
1030a576ab5bSrab 
1031349b53ddSStuart Maybee 	/* FIXME: flask ops??? */
1032349b53ddSStuart Maybee 
1033a576ab5bSrab 	switch (acmctl->cmd) {
1034843e1988Sjohnlev 	case ACMOP_setpolicy:
1035843e1988Sjohnlev 	case ACMOP_getpolicy:
1036843e1988Sjohnlev 	case ACMOP_dumpstats:
1037843e1988Sjohnlev 	case ACMOP_getssid:
1038843e1988Sjohnlev 	case ACMOP_getdecision:
1039a576ab5bSrab 	case ACMOP_chgpolicy:
1040a576ab5bSrab 	case ACMOP_relabeldoms:
1041349b53ddSStuart Maybee 		/* flags = IE_IMPEXP; */
1042843e1988Sjohnlev 		break;
1043843e1988Sjohnlev 	default:
1044843e1988Sjohnlev #ifdef DEBUG
1045349b53ddSStuart Maybee 		printf("unrecognized HYPERVISOR_xsm_op op %d\n", acmctl->cmd);
1046843e1988Sjohnlev #endif
1047843e1988Sjohnlev 		return (-X_EINVAL);
1048843e1988Sjohnlev 	}
1049843e1988Sjohnlev 
1050843e1988Sjohnlev 	if (error == 0)
1051349b53ddSStuart Maybee 		error = HYPERVISOR_xsm_op(acmctl);
1052843e1988Sjohnlev 	export_buffer(&op_ie, &error);
1053843e1988Sjohnlev 
1054843e1988Sjohnlev 	return (error);
1055843e1988Sjohnlev }
1056843e1988Sjohnlev 
1057843e1988Sjohnlev static int
privcmd_HYPERVISOR_mmuext_op(struct mmuext_op * op,int count,uint_t * scount,domid_t domid)1058843e1988Sjohnlev privcmd_HYPERVISOR_mmuext_op(struct mmuext_op *op, int count, uint_t *scount,
1059843e1988Sjohnlev     domid_t domid)
1060843e1988Sjohnlev {
1061843e1988Sjohnlev 	int error, bytes;
1062843e1988Sjohnlev 	uint_t kscount;
1063843e1988Sjohnlev 	struct mmuext_op *kop, single_kop;
1064843e1988Sjohnlev 	import_export_t op_ie, scnt_ie;
1065843e1988Sjohnlev 
1066*2a9992ecSToomas Soome 	kop = NULL;
1067843e1988Sjohnlev 	op_ie = scnt_ie = null_ie;
1068843e1988Sjohnlev 	error = 0;
1069843e1988Sjohnlev 
1070843e1988Sjohnlev 	if (count >= 1) {
1071843e1988Sjohnlev 		bytes = count * sizeof (*kop);
1072843e1988Sjohnlev 		kop = (count == 1) ? &single_kop : kmem_alloc(bytes, KM_SLEEP);
1073843e1988Sjohnlev 		error = import_buffer(&op_ie, op, kop, bytes, IE_IMPORT);
1074843e1988Sjohnlev 	}
1075843e1988Sjohnlev 
1076843e1988Sjohnlev 	DTRACE_XPV2(mmu__ext__op__start, int, count, struct mmuext_op *,
1077843e1988Sjohnlev 	    ((error == -X_EFAULT) ? op : kop));
1078843e1988Sjohnlev 
1079843e1988Sjohnlev 	if (scount != NULL && error == 0)
1080843e1988Sjohnlev 		error = import_buffer(&scnt_ie, scount, &kscount,
1081843e1988Sjohnlev 		    sizeof (kscount), IE_EXPORT);
1082843e1988Sjohnlev 
1083843e1988Sjohnlev 	if (error == 0)
1084843e1988Sjohnlev 		error = HYPERVISOR_mmuext_op(kop, count, &kscount, domid);
1085843e1988Sjohnlev 	export_buffer(&op_ie, &error);
1086843e1988Sjohnlev 	export_buffer(&scnt_ie, &error);
1087843e1988Sjohnlev 
1088843e1988Sjohnlev 	DTRACE_XPV1(mmu__ext__op__end, int, error);
1089843e1988Sjohnlev 
1090843e1988Sjohnlev 	if (count > 1)
1091843e1988Sjohnlev 		kmem_free(kop, bytes);
1092843e1988Sjohnlev 	return (error);
1093843e1988Sjohnlev }
1094843e1988Sjohnlev 
1095843e1988Sjohnlev static int
privcmd_HYPERVISOR_hvm_op(int cmd,void * arg)1096843e1988Sjohnlev privcmd_HYPERVISOR_hvm_op(int cmd, void *arg)
1097843e1988Sjohnlev {
1098843e1988Sjohnlev 	int error;
1099843e1988Sjohnlev 	int size = 0;
1100843e1988Sjohnlev 	import_export_t arg_ie;
1101843e1988Sjohnlev 	uint32_t flags = IE_IMPORT;
1102843e1988Sjohnlev 
1103843e1988Sjohnlev 	switch (cmd) {
1104843e1988Sjohnlev 	case HVMOP_set_param:
1105843e1988Sjohnlev 	case HVMOP_get_param:
1106843e1988Sjohnlev 		size = sizeof (struct xen_hvm_param);
1107843e1988Sjohnlev 		flags = IE_IMPEXP;
1108843e1988Sjohnlev 		break;
1109843e1988Sjohnlev 	case HVMOP_set_pci_intx_level:
1110843e1988Sjohnlev 		size = sizeof (struct xen_hvm_set_pci_intx_level);
1111843e1988Sjohnlev 		break;
1112843e1988Sjohnlev 	case HVMOP_set_isa_irq_level:
1113843e1988Sjohnlev 		size = sizeof (struct xen_hvm_set_isa_irq_level);
1114843e1988Sjohnlev 		break;
1115843e1988Sjohnlev 	case HVMOP_set_pci_link_route:
1116843e1988Sjohnlev 		size = sizeof (struct xen_hvm_set_pci_link_route);
1117843e1988Sjohnlev 		break;
1118349b53ddSStuart Maybee 	case HVMOP_track_dirty_vram:
1119349b53ddSStuart Maybee 		size = sizeof (struct xen_hvm_track_dirty_vram);
1120349b53ddSStuart Maybee 		break;
1121349b53ddSStuart Maybee 	case HVMOP_modified_memory:
1122349b53ddSStuart Maybee 		size = sizeof (struct xen_hvm_modified_memory);
1123349b53ddSStuart Maybee 		break;
1124349b53ddSStuart Maybee 	case HVMOP_set_mem_type:
1125349b53ddSStuart Maybee 		size = sizeof (struct xen_hvm_set_mem_type);
1126349b53ddSStuart Maybee 		break;
1127843e1988Sjohnlev 
1128843e1988Sjohnlev 	default:
1129843e1988Sjohnlev #ifdef DEBUG
1130843e1988Sjohnlev 		printf("unrecognized HVM op 0x%x\n", cmd);
1131843e1988Sjohnlev #endif
1132843e1988Sjohnlev 		return (-X_EINVAL);
1133843e1988Sjohnlev 	}
1134843e1988Sjohnlev 
1135843e1988Sjohnlev 	error = import_buffer(&arg_ie, arg, NULL, size, flags);
1136843e1988Sjohnlev 	if (error == 0)
1137843e1988Sjohnlev 		error = HYPERVISOR_hvm_op(cmd, arg_ie.ie_kaddr);
1138843e1988Sjohnlev 	export_buffer(&arg_ie, &error);
1139843e1988Sjohnlev 
1140843e1988Sjohnlev 	return (error);
1141843e1988Sjohnlev }
1142843e1988Sjohnlev 
1143843e1988Sjohnlev static int
privcmd_HYPERVISOR_sched_op(int cmd,void * arg)1144843e1988Sjohnlev privcmd_HYPERVISOR_sched_op(int cmd, void *arg)
1145843e1988Sjohnlev {
1146843e1988Sjohnlev 	int error;
1147843e1988Sjohnlev 	int size = 0;
1148843e1988Sjohnlev 	import_export_t op_ie;
1149843e1988Sjohnlev 	struct sched_remote_shutdown op;
1150843e1988Sjohnlev 
1151843e1988Sjohnlev 	switch (cmd) {
1152843e1988Sjohnlev 	case SCHEDOP_remote_shutdown:
1153843e1988Sjohnlev 		size = sizeof (struct sched_remote_shutdown);
1154843e1988Sjohnlev 		break;
1155843e1988Sjohnlev 	default:
1156843e1988Sjohnlev #ifdef DEBUG
1157843e1988Sjohnlev 		printf("unrecognized sched op 0x%x\n", cmd);
1158843e1988Sjohnlev #endif
1159843e1988Sjohnlev 		return (-X_EINVAL);
1160843e1988Sjohnlev 	}
1161843e1988Sjohnlev 
1162843e1988Sjohnlev 	error = import_buffer(&op_ie, arg, &op, size, IE_IMPORT);
1163843e1988Sjohnlev 	if (error == 0)
1164843e1988Sjohnlev 		error = HYPERVISOR_sched_op(cmd, (arg == NULL) ? NULL : &op);
1165843e1988Sjohnlev 	export_buffer(&op_ie, &error);
1166843e1988Sjohnlev 
1167843e1988Sjohnlev 	return (error);
1168843e1988Sjohnlev }
1169843e1988Sjohnlev 
1170843e1988Sjohnlev int allow_all_hypercalls = 0;
1171843e1988Sjohnlev int privcmd_efault_debug = 0;
1172843e1988Sjohnlev 
1173843e1988Sjohnlev /*ARGSUSED*/
1174843e1988Sjohnlev int
do_privcmd_hypercall(void * uarg,int mode,cred_t * cr,int * rval)1175843e1988Sjohnlev do_privcmd_hypercall(void *uarg, int mode, cred_t *cr, int *rval)
1176843e1988Sjohnlev {
1177843e1988Sjohnlev 	privcmd_hypercall_t __hc, *hc = &__hc;
1178843e1988Sjohnlev 	int error;
1179843e1988Sjohnlev 
1180843e1988Sjohnlev 	if (ddi_copyin(uarg, hc, sizeof (*hc), mode))
1181843e1988Sjohnlev 		return (EFAULT);
1182843e1988Sjohnlev 
1183843e1988Sjohnlev 	switch (hc->op) {
1184843e1988Sjohnlev 	case __HYPERVISOR_mmu_update:
1185843e1988Sjohnlev 		error = privcmd_HYPERVISOR_mmu_update(
1186843e1988Sjohnlev 		    (mmu_update_t *)hc->arg[0], (int)hc->arg[1],
1187843e1988Sjohnlev 		    (int *)hc->arg[2], (domid_t)hc->arg[3]);
1188843e1988Sjohnlev 		break;
1189843e1988Sjohnlev 	case __HYPERVISOR_domctl:
1190843e1988Sjohnlev 		error = privcmd_HYPERVISOR_domctl(
1191843e1988Sjohnlev 		    (xen_domctl_t *)hc->arg[0]);
1192843e1988Sjohnlev 		break;
1193843e1988Sjohnlev 	case __HYPERVISOR_sysctl:
1194843e1988Sjohnlev 		error = privcmd_HYPERVISOR_sysctl(
1195843e1988Sjohnlev 		    (xen_sysctl_t *)hc->arg[0]);
1196843e1988Sjohnlev 		break;
1197843e1988Sjohnlev 	case __HYPERVISOR_platform_op:
1198843e1988Sjohnlev 		error = privcmd_HYPERVISOR_platform_op(
1199843e1988Sjohnlev 		    (xen_platform_op_t *)hc->arg[0]);
1200843e1988Sjohnlev 		break;
1201843e1988Sjohnlev 	case __HYPERVISOR_memory_op:
1202843e1988Sjohnlev 		error = privcmd_HYPERVISOR_memory_op(
1203843e1988Sjohnlev 		    (int)hc->arg[0], (void *)hc->arg[1]);
1204843e1988Sjohnlev 		break;
1205843e1988Sjohnlev 	case __HYPERVISOR_event_channel_op:
1206843e1988Sjohnlev 		error = privcmd_HYPERVISOR_event_channel_op(
1207843e1988Sjohnlev 		    (int)hc->arg[0], (void *)hc->arg[1]);
1208843e1988Sjohnlev 		break;
1209843e1988Sjohnlev 	case __HYPERVISOR_xen_version:
1210843e1988Sjohnlev 		error = privcmd_HYPERVISOR_xen_version(
1211843e1988Sjohnlev 		    (int)hc->arg[0], (void *)hc->arg[1]);
1212843e1988Sjohnlev 		break;
1213843e1988Sjohnlev 	case __HYPERVISOR_mmuext_op:
1214843e1988Sjohnlev 		error = privcmd_HYPERVISOR_mmuext_op(
1215843e1988Sjohnlev 		    (struct mmuext_op *)hc->arg[0], (int)hc->arg[1],
1216843e1988Sjohnlev 		    (uint_t *)hc->arg[2], (domid_t)hc->arg[3]);
1217843e1988Sjohnlev 		break;
1218349b53ddSStuart Maybee 	case __HYPERVISOR_xsm_op:
1219349b53ddSStuart Maybee 		error = privcmd_HYPERVISOR_xsm_op((void *)hc->arg[0]);
1220843e1988Sjohnlev 		break;
1221843e1988Sjohnlev 	case __HYPERVISOR_hvm_op:
1222843e1988Sjohnlev 		error = privcmd_HYPERVISOR_hvm_op(
1223843e1988Sjohnlev 		    (int)hc->arg[0], (void *)hc->arg[1]);
1224843e1988Sjohnlev 		break;
1225843e1988Sjohnlev 	case __HYPERVISOR_sched_op:
1226843e1988Sjohnlev 		error = privcmd_HYPERVISOR_sched_op(
1227843e1988Sjohnlev 		    (int)hc->arg[0], (void *)hc->arg[1]);
1228843e1988Sjohnlev 		break;
1229843e1988Sjohnlev 	default:
1230843e1988Sjohnlev 		if (allow_all_hypercalls)
1231843e1988Sjohnlev 			error = __hypercall5(hc->op, hc->arg[0], hc->arg[1],
1232843e1988Sjohnlev 			    hc->arg[2], hc->arg[3], hc->arg[4]);
1233843e1988Sjohnlev 		else {
1234843e1988Sjohnlev #ifdef DEBUG
1235843e1988Sjohnlev 			printf("unrecognized hypercall %ld\n", hc->op);
1236843e1988Sjohnlev #endif
1237843e1988Sjohnlev 			error = -X_EPERM;
1238843e1988Sjohnlev 		}
1239843e1988Sjohnlev 		break;
1240843e1988Sjohnlev 	}
1241843e1988Sjohnlev 
1242843e1988Sjohnlev 	if (error > 0) {
1243843e1988Sjohnlev 		*rval = error;
1244843e1988Sjohnlev 		error = 0;
1245843e1988Sjohnlev 	} else if (error != 0)
1246843e1988Sjohnlev 		error = xen_xlate_errcode(error);
1247843e1988Sjohnlev 
1248843e1988Sjohnlev 	return (error);
1249843e1988Sjohnlev }
1250