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 /* 22*525b892bSMark 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 * 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 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 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 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) { 157843e1988Sjohnlev /*LINTED: constant in conditional context*/ 158843e1988Sjohnlev set_xen_guest_handle((*hdl), (void *)((iep)->ie_kaddr)); 159a576ab5bSrab } 160843e1988Sjohnlev return (err); 161843e1988Sjohnlev } 162843e1988Sjohnlev 163843e1988Sjohnlev static int 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 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 !defined(__GNUC__) && defined(__i386__) 295a576ab5bSrab if (op.u.hvmcontext.buffer.u.p != NULL) 296a576ab5bSrab #else 297a576ab5bSrab if (op.u.hvmcontext.buffer.p != NULL) 298a576ab5bSrab #endif 299a576ab5bSrab error = import_handle(&sub_ie, &op.u.hvmcontext.buffer, 300a576ab5bSrab op.u.hvmcontext.size, IE_EXPORT); 301a576ab5bSrab break; 302a576ab5bSrab } 303a576ab5bSrab 304349b53ddSStuart Maybee case XEN_DOMCTL_getdomaininfo: 305349b53ddSStuart Maybee case XEN_DOMCTL_getpageframeinfo: 306349b53ddSStuart Maybee case XEN_DOMCTL_max_mem: 307a576ab5bSrab case XEN_DOMCTL_resumedomain: 308843e1988Sjohnlev case XEN_DOMCTL_getvcpuinfo: 309843e1988Sjohnlev case XEN_DOMCTL_setvcpuaffinity: 310843e1988Sjohnlev case XEN_DOMCTL_getvcpuaffinity: 311843e1988Sjohnlev case XEN_DOMCTL_max_vcpus: 312843e1988Sjohnlev case XEN_DOMCTL_scheduler_op: 313843e1988Sjohnlev case XEN_DOMCTL_setdomainhandle: 314843e1988Sjohnlev case XEN_DOMCTL_setdebugging: 315843e1988Sjohnlev case XEN_DOMCTL_irq_permission: 316843e1988Sjohnlev case XEN_DOMCTL_iomem_permission: 317843e1988Sjohnlev case XEN_DOMCTL_ioport_permission: 318843e1988Sjohnlev case XEN_DOMCTL_hypercall_init: 319843e1988Sjohnlev case XEN_DOMCTL_arch_setup: 320843e1988Sjohnlev case XEN_DOMCTL_settimeoffset: 321843e1988Sjohnlev case XEN_DOMCTL_real_mode_area: 322a576ab5bSrab case XEN_DOMCTL_sendtrigger: 323349b53ddSStuart Maybee case XEN_DOMCTL_assign_device: 324349b53ddSStuart Maybee case XEN_DOMCTL_bind_pt_irq: 325349b53ddSStuart Maybee case XEN_DOMCTL_get_address_size: 326349b53ddSStuart Maybee case XEN_DOMCTL_set_address_size: 327349b53ddSStuart Maybee case XEN_DOMCTL_get_ext_vcpucontext: 328349b53ddSStuart Maybee case XEN_DOMCTL_set_ext_vcpucontext: 329349b53ddSStuart Maybee case XEN_DOMCTL_set_opt_feature: 330349b53ddSStuart Maybee case XEN_DOMCTL_memory_mapping: 331349b53ddSStuart Maybee case XEN_DOMCTL_ioport_mapping: 332349b53ddSStuart Maybee case XEN_DOMCTL_pin_mem_cacheattr: 333349b53ddSStuart Maybee case XEN_DOMCTL_test_assign_device: 334349b53ddSStuart Maybee case XEN_DOMCTL_set_target: 335349b53ddSStuart Maybee case XEN_DOMCTL_deassign_device: 336349b53ddSStuart Maybee case XEN_DOMCTL_set_cpuid: 337349b53ddSStuart Maybee case XEN_DOMCTL_get_device_group: 338349b53ddSStuart Maybee case XEN_DOMCTL_get_machine_address_size: 339349b53ddSStuart Maybee case XEN_DOMCTL_set_machine_address_size: 340349b53ddSStuart Maybee case XEN_DOMCTL_suppress_spurious_page_faults: 341843e1988Sjohnlev break; 342843e1988Sjohnlev 343843e1988Sjohnlev default: 344843e1988Sjohnlev #ifdef DEBUG 345843e1988Sjohnlev printf("unrecognized HYPERVISOR_domctl %d\n", op.cmd); 346843e1988Sjohnlev #endif 347843e1988Sjohnlev error = -X_EINVAL; 348843e1988Sjohnlev } 349843e1988Sjohnlev 350843e1988Sjohnlev if (error == 0) 351843e1988Sjohnlev error = HYPERVISOR_domctl(&op); 352843e1988Sjohnlev 353843e1988Sjohnlev export_buffer(&op_ie, &error); 354843e1988Sjohnlev export_buffer(&sub_ie, &error); 355843e1988Sjohnlev 356843e1988Sjohnlev switch (op.cmd) { 357843e1988Sjohnlev case XEN_DOMCTL_createdomain: 358843e1988Sjohnlev DTRACE_XPV1(dom__create__end, int, error); 359843e1988Sjohnlev break; 360843e1988Sjohnlev case XEN_DOMCTL_destroydomain: 361843e1988Sjohnlev DTRACE_XPV1(dom__destroy__end, int, error); 362843e1988Sjohnlev break; 363843e1988Sjohnlev case XEN_DOMCTL_pausedomain: 364843e1988Sjohnlev DTRACE_XPV1(dom__pause__end, int, error); 365843e1988Sjohnlev break; 366843e1988Sjohnlev case XEN_DOMCTL_unpausedomain: 367843e1988Sjohnlev DTRACE_XPV1(dom__unpause__end, int, error); 368843e1988Sjohnlev break; 369843e1988Sjohnlev case XEN_DOMCTL_setvcpucontext: 370843e1988Sjohnlev DTRACE_XPV1(setvcpucontext__end, int, error); 371843e1988Sjohnlev break; 372843e1988Sjohnlev default: 373843e1988Sjohnlev ; 374843e1988Sjohnlev } 375843e1988Sjohnlev 376843e1988Sjohnlev return (error); 377843e1988Sjohnlev } 378843e1988Sjohnlev 379843e1988Sjohnlev static int 380843e1988Sjohnlev privcmd_HYPERVISOR_sysctl(xen_sysctl_t *opp) 381843e1988Sjohnlev { 382349b53ddSStuart Maybee xen_sysctl_t op, dop; 38333649781Smrj import_export_t op_ie, sub_ie, sub2_ie; 384843e1988Sjohnlev int error = 0; 385843e1988Sjohnlev 386843e1988Sjohnlev if (import_buffer(&op_ie, opp, &op, sizeof (op), IE_IMPEXP) != 0) 387843e1988Sjohnlev return (-X_EFAULT); 388843e1988Sjohnlev 389843e1988Sjohnlev sub_ie = null_ie; 39033649781Smrj sub2_ie = null_ie; 391843e1988Sjohnlev 392843e1988Sjohnlev /* 393843e1988Sjohnlev * Check this first because our wrapper will forcibly overwrite it. 394843e1988Sjohnlev */ 395843e1988Sjohnlev if (op.interface_version != XEN_SYSCTL_INTERFACE_VERSION) { 396843e1988Sjohnlev error = -X_EACCES; 397843e1988Sjohnlev export_buffer(&op_ie, &error); 398843e1988Sjohnlev return (error); 399843e1988Sjohnlev } 400843e1988Sjohnlev 401843e1988Sjohnlev switch (op.cmd) { 402843e1988Sjohnlev case XEN_SYSCTL_readconsole: { 403843e1988Sjohnlev error = import_handle(&sub_ie, &op.u.readconsole.buffer, 404843e1988Sjohnlev op.u.readconsole.count, IE_EXPORT); 405843e1988Sjohnlev break; 406843e1988Sjohnlev } 407843e1988Sjohnlev 408a576ab5bSrab case XEN_SYSCTL_debug_keys: { 409a576ab5bSrab error = import_handle(&sub_ie, &op.u.debug_keys.keys, 410a576ab5bSrab op.u.debug_keys.nr_keys, IE_IMPORT); 411a576ab5bSrab break; 412a576ab5bSrab } 413a576ab5bSrab 414843e1988Sjohnlev case XEN_SYSCTL_tbuf_op: 415349b53ddSStuart Maybee case XEN_SYSCTL_physinfo: { 416349b53ddSStuart Maybee if (uaddr_from_handle(&op.u.physinfo.cpu_to_node) != NULL && 417349b53ddSStuart Maybee op.u.physinfo.max_cpu_id != 0) { 418349b53ddSStuart Maybee error = import_handle(&sub_ie, 419349b53ddSStuart Maybee &op.u.physinfo.cpu_to_node, 420349b53ddSStuart Maybee op.u.physinfo.max_cpu_id * sizeof (uint32_t), 421349b53ddSStuart Maybee IE_EXPORT); 422349b53ddSStuart Maybee } 423843e1988Sjohnlev break; 424349b53ddSStuart Maybee } 425349b53ddSStuart Maybee case XEN_SYSCTL_sched_id: 426349b53ddSStuart Maybee case XEN_SYSCTL_availheap: 427349b53ddSStuart Maybee case XEN_SYSCTL_cpu_hotplug: 428349b53ddSStuart Maybee break; 429349b53ddSStuart Maybee case XEN_SYSCTL_get_pmstat: { 430349b53ddSStuart Maybee unsigned int maxs; 431349b53ddSStuart Maybee 432349b53ddSStuart Maybee switch (op.u.get_pmstat.type) { 433349b53ddSStuart Maybee case PMSTAT_get_pxstat: 434349b53ddSStuart Maybee /* 435349b53ddSStuart Maybee * This interface is broken. Xen always copies out 436349b53ddSStuart Maybee * all the state information, and the interface 437349b53ddSStuart Maybee * does not specify how much space the caller has 438349b53ddSStuart Maybee * reserved. So, the only thing to do is just mirror 439349b53ddSStuart Maybee * the hypervisor and libxc behavior, and use the 440349b53ddSStuart Maybee * maximum amount of data. 441349b53ddSStuart Maybee */ 442349b53ddSStuart Maybee dop.cmd = XEN_SYSCTL_get_pmstat; 443349b53ddSStuart Maybee dop.interface_version = XEN_SYSCTL_INTERFACE_VERSION; 444349b53ddSStuart Maybee dop.u.get_pmstat.cpuid = op.u.get_pmstat.cpuid; 445349b53ddSStuart Maybee dop.u.get_pmstat.type = PMSTAT_get_max_px; 446349b53ddSStuart Maybee error = HYPERVISOR_sysctl(&dop); 447349b53ddSStuart Maybee if (error != 0) 448349b53ddSStuart Maybee break; 449349b53ddSStuart Maybee 450349b53ddSStuart Maybee maxs = dop.u.get_pmstat.u.getpx.total; 451349b53ddSStuart Maybee if (maxs == 0) { 452349b53ddSStuart Maybee error = -X_EINVAL; 453349b53ddSStuart Maybee break; 454349b53ddSStuart Maybee } 455349b53ddSStuart Maybee 456349b53ddSStuart Maybee error = import_handle(&sub_ie, 457349b53ddSStuart Maybee &op.u.get_pmstat.u.getpx.trans_pt, 458349b53ddSStuart Maybee maxs * maxs * sizeof (uint64_t), IE_EXPORT); 459349b53ddSStuart Maybee if (error != 0) 460349b53ddSStuart Maybee break; 461349b53ddSStuart Maybee 462349b53ddSStuart Maybee error = import_handle(&sub2_ie, 463349b53ddSStuart Maybee &op.u.get_pmstat.u.getpx.pt, 464349b53ddSStuart Maybee maxs * sizeof (pm_px_val_t), IE_EXPORT); 465349b53ddSStuart Maybee break; 466349b53ddSStuart Maybee case PMSTAT_get_cxstat: 467349b53ddSStuart Maybee /* See above */ 468349b53ddSStuart Maybee dop.cmd = XEN_SYSCTL_get_pmstat; 469349b53ddSStuart Maybee dop.interface_version = XEN_SYSCTL_INTERFACE_VERSION; 470349b53ddSStuart Maybee dop.u.get_pmstat.cpuid = op.u.get_pmstat.cpuid; 471349b53ddSStuart Maybee dop.u.get_pmstat.type = PMSTAT_get_max_cx; 472349b53ddSStuart Maybee error = HYPERVISOR_sysctl(&dop); 473349b53ddSStuart Maybee if (error != 0) 474349b53ddSStuart Maybee break; 475349b53ddSStuart Maybee 476349b53ddSStuart Maybee maxs = dop.u.get_pmstat.u.getcx.nr; 477349b53ddSStuart Maybee if (maxs == 0) { 478349b53ddSStuart Maybee error = -X_EINVAL; 479349b53ddSStuart Maybee break; 480349b53ddSStuart Maybee } 481349b53ddSStuart Maybee 482349b53ddSStuart Maybee error = import_handle(&sub_ie, 483349b53ddSStuart Maybee &op.u.get_pmstat.u.getcx.triggers, 484349b53ddSStuart Maybee maxs * sizeof (uint64_t), IE_EXPORT); 485349b53ddSStuart Maybee if (error != 0) 486349b53ddSStuart Maybee break; 487349b53ddSStuart Maybee error = import_handle(&sub2_ie, 488349b53ddSStuart Maybee &op.u.get_pmstat.u.getcx.residencies, 489349b53ddSStuart Maybee maxs * sizeof (uint64_t), IE_EXPORT); 490349b53ddSStuart Maybee break; 491349b53ddSStuart Maybee 492349b53ddSStuart Maybee case PMSTAT_get_max_px: 493349b53ddSStuart Maybee case PMSTAT_reset_pxstat: 494349b53ddSStuart Maybee case PMSTAT_get_max_cx: 495349b53ddSStuart Maybee case PMSTAT_reset_cxstat: 496349b53ddSStuart Maybee break; 497349b53ddSStuart Maybee default: 498349b53ddSStuart Maybee error = -X_EINVAL; 499349b53ddSStuart Maybee break; 500349b53ddSStuart Maybee } 501349b53ddSStuart Maybee break; 502349b53ddSStuart Maybee } 503843e1988Sjohnlev 504843e1988Sjohnlev case XEN_SYSCTL_perfc_op: { 505843e1988Sjohnlev xen_sysctl_perfc_desc_t *scdp; 506843e1988Sjohnlev /* 507843e1988Sjohnlev * If 'desc' is NULL, then the caller is asking for 508843e1988Sjohnlev * the number of counters. If 'desc' is non-NULL, 509843e1988Sjohnlev * then we need to know how many counters there are 510843e1988Sjohnlev * before wiring down the output buffer appropriately. 511843e1988Sjohnlev */ 512843e1988Sjohnlev /*LINTED: constant in conditional context*/ 513a576ab5bSrab get_xen_guest_handle_u(scdp, op.u.perfc_op.desc); 514843e1988Sjohnlev if (scdp != NULL) { 515843e1988Sjohnlev static int numcounters = -1; 51633649781Smrj static int numvals = -1; 517843e1988Sjohnlev 518843e1988Sjohnlev if (numcounters == -1) { 519843e1988Sjohnlev dop.cmd = XEN_SYSCTL_perfc_op; 520843e1988Sjohnlev dop.interface_version = 521843e1988Sjohnlev XEN_SYSCTL_INTERFACE_VERSION; 522843e1988Sjohnlev dop.u.perfc_op.cmd = XEN_SYSCTL_PERFCOP_query; 52333649781Smrj /*LINTED: constant in conditional context*/ 52433649781Smrj set_xen_guest_handle_u(dop.u.perfc_op.desc, 52533649781Smrj NULL); 52633649781Smrj /*LINTED: constant in conditional context*/ 52733649781Smrj set_xen_guest_handle_u(dop.u.perfc_op.val, 52833649781Smrj NULL); 529843e1988Sjohnlev 530843e1988Sjohnlev error = HYPERVISOR_sysctl(&dop); 531843e1988Sjohnlev if (error != 0) 532843e1988Sjohnlev break; 533843e1988Sjohnlev numcounters = dop.u.perfc_op.nr_counters; 53433649781Smrj numvals = dop.u.perfc_op.nr_vals; 535843e1988Sjohnlev } 536843e1988Sjohnlev ASSERT(numcounters != -1); 53733649781Smrj ASSERT(numvals != -1); 538843e1988Sjohnlev error = import_handle(&sub_ie, &op.u.perfc_op.desc, 539843e1988Sjohnlev (sizeof (xen_sysctl_perfc_desc_t) * numcounters), 540843e1988Sjohnlev IE_EXPORT); 54133649781Smrj error = import_handle(&sub2_ie, &op.u.perfc_op.val, 54233649781Smrj (sizeof (xen_sysctl_perfc_val_t) * numvals), 54333649781Smrj IE_EXPORT); 544843e1988Sjohnlev } 545843e1988Sjohnlev break; 546843e1988Sjohnlev } 547843e1988Sjohnlev 548843e1988Sjohnlev case XEN_SYSCTL_getdomaininfolist: { 549843e1988Sjohnlev error = import_handle(&sub_ie, &op.u.getdomaininfolist.buffer, 550843e1988Sjohnlev (op.u.getdomaininfolist.max_domains * 551843e1988Sjohnlev sizeof (xen_domctl_getdomaininfo_t)), IE_EXPORT); 552843e1988Sjohnlev break; 553843e1988Sjohnlev } 554843e1988Sjohnlev 555a576ab5bSrab case XEN_SYSCTL_getcpuinfo: 556a576ab5bSrab error = import_handle(&sub_ie, &op.u.getcpuinfo.info, 557a576ab5bSrab op.u.getcpuinfo.max_cpus * 558a576ab5bSrab sizeof (xen_sysctl_cpuinfo_t), IE_EXPORT); 559a576ab5bSrab break; 560843e1988Sjohnlev default: 561843e1988Sjohnlev #ifdef DEBUG 562843e1988Sjohnlev printf("unrecognized HYPERVISOR_sysctl %d\n", op.cmd); 563843e1988Sjohnlev #endif 564843e1988Sjohnlev error = -X_EINVAL; 565843e1988Sjohnlev } 566843e1988Sjohnlev 567843e1988Sjohnlev if (error == 0) 568843e1988Sjohnlev error = HYPERVISOR_sysctl(&op); 569843e1988Sjohnlev 570843e1988Sjohnlev export_buffer(&op_ie, &error); 571843e1988Sjohnlev export_buffer(&sub_ie, &error); 57233649781Smrj export_buffer(&sub2_ie, &error); 573843e1988Sjohnlev 574843e1988Sjohnlev return (error); 575843e1988Sjohnlev } 576843e1988Sjohnlev 577843e1988Sjohnlev static int 578843e1988Sjohnlev privcmd_HYPERVISOR_platform_op(xen_platform_op_t *opp) 579843e1988Sjohnlev { 580349b53ddSStuart Maybee import_export_t op_ie, sub_ie, sub2_ie; 581843e1988Sjohnlev xen_platform_op_t op; 582843e1988Sjohnlev int error; 583843e1988Sjohnlev 584843e1988Sjohnlev if (import_buffer(&op_ie, opp, &op, sizeof (op), IE_IMPEXP) != 0) 585843e1988Sjohnlev return (-X_EFAULT); 586843e1988Sjohnlev 587843e1988Sjohnlev sub_ie = null_ie; 588349b53ddSStuart Maybee sub2_ie = null_ie; 589843e1988Sjohnlev 590843e1988Sjohnlev /* 591843e1988Sjohnlev * Check this first because our wrapper will forcibly overwrite it. 592843e1988Sjohnlev */ 593843e1988Sjohnlev if (op.interface_version != XENPF_INTERFACE_VERSION) { 594843e1988Sjohnlev error = -X_EACCES; 595843e1988Sjohnlev export_buffer(&op_ie, &error); 596843e1988Sjohnlev return (error); 597843e1988Sjohnlev } 598843e1988Sjohnlev 599843e1988Sjohnlev /* 600843e1988Sjohnlev * Now handle any platform ops with embedded pointers elsewhere 601843e1988Sjohnlev * in the user address space that also need to be tacked down 602843e1988Sjohnlev * while the hypervisor futzes with them. 603843e1988Sjohnlev */ 604843e1988Sjohnlev switch (op.cmd) { 605843e1988Sjohnlev case XENPF_settime: 606843e1988Sjohnlev case XENPF_add_memtype: 607843e1988Sjohnlev case XENPF_del_memtype: 608843e1988Sjohnlev case XENPF_read_memtype: 609843e1988Sjohnlev case XENPF_platform_quirk: 610349b53ddSStuart Maybee case XENPF_enter_acpi_sleep: 611349b53ddSStuart Maybee case XENPF_change_freq: 612349b53ddSStuart Maybee case XENPF_panic_init: 613843e1988Sjohnlev break; 614843e1988Sjohnlev 615843e1988Sjohnlev case XENPF_microcode_update: 616843e1988Sjohnlev error = import_handle(&sub_ie, &op.u.microcode.data, 617843e1988Sjohnlev op.u.microcode.length, IE_IMPORT); 618843e1988Sjohnlev break; 619349b53ddSStuart Maybee case XENPF_getidletime: 620349b53ddSStuart Maybee error = import_handle(&sub_ie, &op.u.getidletime.cpumap_bitmap, 621349b53ddSStuart Maybee op.u.getidletime.cpumap_nr_cpus, IE_IMPEXP); 622349b53ddSStuart Maybee if (error != 0) 623349b53ddSStuart Maybee break; 624843e1988Sjohnlev 625349b53ddSStuart Maybee error = import_handle(&sub2_ie, &op.u.getidletime.idletime, 626349b53ddSStuart Maybee op.u.getidletime.cpumap_nr_cpus * sizeof (uint64_t), 627349b53ddSStuart Maybee IE_EXPORT); 628349b53ddSStuart Maybee break; 629349b53ddSStuart Maybee 630349b53ddSStuart Maybee case XENPF_set_processor_pminfo: { 631349b53ddSStuart Maybee size_t s; 632349b53ddSStuart Maybee 633349b53ddSStuart Maybee switch (op.u.set_pminfo.type) { 634349b53ddSStuart Maybee case XEN_PM_PX: 635349b53ddSStuart Maybee s = op.u.set_pminfo.u.perf.state_count * 636349b53ddSStuart Maybee sizeof (xen_processor_px_t); 637349b53ddSStuart Maybee if (op.u.set_pminfo.u.perf.flags & XEN_PX_PSS) { 638349b53ddSStuart Maybee error = import_handle(&sub_ie, 639349b53ddSStuart Maybee &op.u.set_pminfo.u.perf.states, s, 640349b53ddSStuart Maybee IE_IMPORT); 641349b53ddSStuart Maybee } 642349b53ddSStuart Maybee break; 643349b53ddSStuart Maybee case XEN_PM_CX: 644349b53ddSStuart Maybee s = op.u.set_pminfo.u.power.count * 645349b53ddSStuart Maybee sizeof (xen_processor_cx_t); 646349b53ddSStuart Maybee error = import_handle(&sub_ie, 647349b53ddSStuart Maybee &op.u.set_pminfo.u.power.states, s, IE_IMPORT); 648349b53ddSStuart Maybee break; 649349b53ddSStuart Maybee case XEN_PM_TX: 650349b53ddSStuart Maybee break; 651843e1988Sjohnlev default: 652349b53ddSStuart Maybee error = -X_EINVAL; 653349b53ddSStuart Maybee break; 654349b53ddSStuart Maybee } 655349b53ddSStuart Maybee break; 656349b53ddSStuart Maybee } 657349b53ddSStuart Maybee case XENPF_firmware_info: { 658349b53ddSStuart Maybee uint16_t len; 659349b53ddSStuart Maybee void *uaddr; 660349b53ddSStuart Maybee 661349b53ddSStuart Maybee switch (op.u.firmware_info.type) { 662349b53ddSStuart Maybee case XEN_FW_DISK_INFO: 663349b53ddSStuart Maybee /* 664349b53ddSStuart Maybee * Ugh.. another hokey interface. The first 16 bits 665349b53ddSStuart Maybee * of the buffer are also used as the (input) length. 666349b53ddSStuart Maybee */ 667349b53ddSStuart Maybee uaddr = uaddr_from_handle( 668349b53ddSStuart Maybee &op.u.firmware_info.u.disk_info.edd_params); 669349b53ddSStuart Maybee error = ddi_copyin(uaddr, &len, sizeof (len), 0); 670349b53ddSStuart Maybee if (error != 0) 671349b53ddSStuart Maybee break; 672349b53ddSStuart Maybee error = import_handle(&sub_ie, 673349b53ddSStuart Maybee &op.u.firmware_info.u.disk_info.edd_params, len, 674349b53ddSStuart Maybee IE_IMPEXP); 675349b53ddSStuart Maybee break; 676349b53ddSStuart Maybee case XEN_FW_VBEDDC_INFO: 677349b53ddSStuart Maybee error = import_handle(&sub_ie, 678349b53ddSStuart Maybee &op.u.firmware_info.u.vbeddc_info.edid, 128, 679349b53ddSStuart Maybee IE_EXPORT); 680349b53ddSStuart Maybee break; 681349b53ddSStuart Maybee case XEN_FW_DISK_MBR_SIGNATURE: 682349b53ddSStuart Maybee default: 683349b53ddSStuart Maybee break; 684349b53ddSStuart Maybee } 685349b53ddSStuart Maybee break; 686349b53ddSStuart Maybee } 687349b53ddSStuart Maybee default: 688349b53ddSStuart Maybee /* FIXME: see this with non-existed ID 38 ???? */ 689843e1988Sjohnlev #ifdef DEBUG 690349b53ddSStuart Maybee printf("unrecognized HYPERVISOR_platform_op %d pid %d\n", 691349b53ddSStuart Maybee op.cmd, curthread->t_procp->p_pid); 692843e1988Sjohnlev #endif 693843e1988Sjohnlev return (-X_EINVAL); 694843e1988Sjohnlev } 695843e1988Sjohnlev 696843e1988Sjohnlev if (error == 0) 697843e1988Sjohnlev error = HYPERVISOR_platform_op(&op); 698843e1988Sjohnlev 699843e1988Sjohnlev export_buffer(&op_ie, &error); 700843e1988Sjohnlev export_buffer(&sub_ie, &error); 701349b53ddSStuart Maybee export_buffer(&sub2_ie, &error); 702843e1988Sjohnlev 703843e1988Sjohnlev return (error); 704843e1988Sjohnlev } 705843e1988Sjohnlev 706843e1988Sjohnlev static int 707843e1988Sjohnlev privcmd_HYPERVISOR_memory_op(int cmd, void *arg) 708843e1988Sjohnlev { 709843e1988Sjohnlev int error = 0; 710843e1988Sjohnlev import_export_t op_ie, sub_ie, gpfn_ie, mfn_ie; 711843e1988Sjohnlev union { 712843e1988Sjohnlev domid_t domid; 713843e1988Sjohnlev struct xen_memory_reservation resv; 714843e1988Sjohnlev struct xen_machphys_mfn_list xmml; 715843e1988Sjohnlev struct xen_add_to_physmap xatp; 716843e1988Sjohnlev struct xen_memory_map mm; 717843e1988Sjohnlev struct xen_foreign_memory_map fmm; 718*525b892bSMark Johnson struct xen_pod_target pd; 719843e1988Sjohnlev } op_arg; 720843e1988Sjohnlev 721843e1988Sjohnlev op_ie = sub_ie = gpfn_ie = mfn_ie = null_ie; 722843e1988Sjohnlev 723843e1988Sjohnlev switch (cmd) { 724843e1988Sjohnlev case XENMEM_increase_reservation: 725843e1988Sjohnlev case XENMEM_decrease_reservation: 726843e1988Sjohnlev case XENMEM_populate_physmap: { 727843e1988Sjohnlev ulong_t *taddr; 728843e1988Sjohnlev 729843e1988Sjohnlev if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.resv), 730843e1988Sjohnlev IE_IMPEXP) != 0) 731843e1988Sjohnlev return (-X_EFAULT); 732843e1988Sjohnlev 733843e1988Sjohnlev error = import_handle(&sub_ie, &op_arg.resv.extent_start, 734843e1988Sjohnlev (op_arg.resv.nr_extents * sizeof (ulong_t)), IE_IMPEXP); 735843e1988Sjohnlev 736843e1988Sjohnlev if (error == -X_EFAULT) 737843e1988Sjohnlev /*LINTED: constant in conditional context*/ 738843e1988Sjohnlev get_xen_guest_handle(taddr, op_arg.resv.extent_start); 739843e1988Sjohnlev else 740843e1988Sjohnlev taddr = sub_ie.ie_kaddr; 741843e1988Sjohnlev 742843e1988Sjohnlev switch (cmd) { 743843e1988Sjohnlev case XENMEM_increase_reservation: 744843e1988Sjohnlev DTRACE_XPV4(increase__reservation__start, 745843e1988Sjohnlev domid_t, op_arg.resv.domid, 746843e1988Sjohnlev ulong_t, op_arg.resv.nr_extents, 747843e1988Sjohnlev uint_t, op_arg.resv.extent_order, 748843e1988Sjohnlev ulong_t *, taddr); 749843e1988Sjohnlev break; 750843e1988Sjohnlev case XENMEM_decrease_reservation: 751843e1988Sjohnlev DTRACE_XPV4(decrease__reservation__start, 752843e1988Sjohnlev domid_t, op_arg.resv.domid, 753843e1988Sjohnlev ulong_t, op_arg.resv.nr_extents, 754843e1988Sjohnlev uint_t, op_arg.resv.extent_order, 755843e1988Sjohnlev ulong_t *, taddr); 756843e1988Sjohnlev break; 757843e1988Sjohnlev case XENMEM_populate_physmap: 758843e1988Sjohnlev DTRACE_XPV3(populate__physmap__start, 759843e1988Sjohnlev domid_t, op_arg.resv.domid, 760843e1988Sjohnlev ulong_t, op_arg.resv.nr_extents, 761843e1988Sjohnlev ulong_t *, taddr); 762843e1988Sjohnlev break; 763843e1988Sjohnlev } 764843e1988Sjohnlev 765843e1988Sjohnlev break; 766843e1988Sjohnlev } 767843e1988Sjohnlev 768843e1988Sjohnlev case XENMEM_maximum_ram_page: 769843e1988Sjohnlev break; 770843e1988Sjohnlev 771843e1988Sjohnlev case XENMEM_current_reservation: 772843e1988Sjohnlev case XENMEM_maximum_reservation: 773a576ab5bSrab case XENMEM_maximum_gpfn: 774843e1988Sjohnlev if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.domid), 775843e1988Sjohnlev IE_IMPEXP) != 0) 776843e1988Sjohnlev return (-X_EFAULT); 777843e1988Sjohnlev break; 778843e1988Sjohnlev 779843e1988Sjohnlev case XENMEM_machphys_mfn_list: { 780843e1988Sjohnlev if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.xmml), 781843e1988Sjohnlev IE_IMPEXP) != 0) 782843e1988Sjohnlev return (-X_EFAULT); 783843e1988Sjohnlev 784843e1988Sjohnlev error = import_handle(&sub_ie, &op_arg.xmml.extent_start, 785843e1988Sjohnlev (op_arg.xmml.max_extents * sizeof (ulong_t)), IE_IMPEXP); 786843e1988Sjohnlev break; 787843e1988Sjohnlev } 788843e1988Sjohnlev 789843e1988Sjohnlev case XENMEM_add_to_physmap: 790843e1988Sjohnlev if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.xatp), 791843e1988Sjohnlev IE_IMPEXP) != 0) 792843e1988Sjohnlev return (-X_EFAULT); 793843e1988Sjohnlev DTRACE_XPV4(add__to__physmap__start, domid_t, 794843e1988Sjohnlev op_arg.xatp.domid, uint_t, op_arg.xatp.space, ulong_t, 795843e1988Sjohnlev op_arg.xatp.idx, ulong_t, op_arg.xatp.gpfn); 796843e1988Sjohnlev break; 797843e1988Sjohnlev 798843e1988Sjohnlev case XENMEM_memory_map: 799843e1988Sjohnlev case XENMEM_machine_memory_map: { 800843e1988Sjohnlev if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.mm), 801843e1988Sjohnlev IE_EXPORT) != 0) 802843e1988Sjohnlev return (-X_EFAULT); 803843e1988Sjohnlev 804843e1988Sjohnlev /* 805843e1988Sjohnlev * XXPV: ugh. e820entry is packed, but not in the kernel, since 806843e1988Sjohnlev * we remove all attributes; seems like this is a nice way to 807843e1988Sjohnlev * break mysteriously. 808843e1988Sjohnlev */ 809843e1988Sjohnlev error = import_handle(&sub_ie, &op_arg.mm.buffer, 810843e1988Sjohnlev (op_arg.mm.nr_entries * 20), IE_IMPEXP); 811843e1988Sjohnlev break; 812843e1988Sjohnlev } 813843e1988Sjohnlev 814843e1988Sjohnlev case XENMEM_set_memory_map: { 815843e1988Sjohnlev struct xen_memory_map *taddr; 816843e1988Sjohnlev if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.fmm), 817843e1988Sjohnlev IE_IMPORT) != 0) 818843e1988Sjohnlev return (-X_EFAULT); 819843e1988Sjohnlev 820843e1988Sjohnlev /* 821843e1988Sjohnlev * As above. 822843e1988Sjohnlev */ 823843e1988Sjohnlev error = import_handle(&sub_ie, &op_arg.fmm.map.buffer, 824843e1988Sjohnlev (op_arg.fmm.map.nr_entries * 20), IE_IMPEXP); 825843e1988Sjohnlev 826843e1988Sjohnlev if (error == -X_EFAULT) 827843e1988Sjohnlev /*LINTED: constant in conditional context*/ 828843e1988Sjohnlev get_xen_guest_handle(taddr, op_arg.fmm.map.buffer); 829843e1988Sjohnlev else 830843e1988Sjohnlev taddr = sub_ie.ie_kaddr; 831843e1988Sjohnlev DTRACE_XPV3(set__memory__map__start, domid_t, 832843e1988Sjohnlev op_arg.fmm.domid, int, op_arg.fmm.map.nr_entries, 833843e1988Sjohnlev struct xen_memory_map *, taddr); 834843e1988Sjohnlev break; 835843e1988Sjohnlev } 836843e1988Sjohnlev 837*525b892bSMark Johnson case XENMEM_set_pod_target: 838*525b892bSMark Johnson case XENMEM_get_pod_target: 839*525b892bSMark Johnson if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.pd), 840*525b892bSMark Johnson IE_IMPEXP) != 0) 841*525b892bSMark Johnson return (-X_EFAULT); 842*525b892bSMark Johnson break; 843*525b892bSMark Johnson 844843e1988Sjohnlev default: 845843e1988Sjohnlev #ifdef DEBUG 846843e1988Sjohnlev printf("unrecognized HYPERVISOR_memory_op %d\n", cmd); 847843e1988Sjohnlev #endif 848843e1988Sjohnlev return (-X_EINVAL); 849843e1988Sjohnlev } 850843e1988Sjohnlev 851843e1988Sjohnlev if (error == 0) 852843e1988Sjohnlev error = HYPERVISOR_memory_op(cmd, 853843e1988Sjohnlev (arg == NULL) ? NULL: &op_arg); 854843e1988Sjohnlev 855843e1988Sjohnlev export_buffer(&op_ie, &error); 856843e1988Sjohnlev export_buffer(&sub_ie, &error); 857843e1988Sjohnlev export_buffer(&gpfn_ie, &error); 858843e1988Sjohnlev export_buffer(&mfn_ie, &error); 859843e1988Sjohnlev 860843e1988Sjohnlev switch (cmd) { 861843e1988Sjohnlev case XENMEM_increase_reservation: 862843e1988Sjohnlev DTRACE_XPV1(increase__reservation__end, int, error); 863843e1988Sjohnlev break; 864843e1988Sjohnlev case XENMEM_decrease_reservation: 865843e1988Sjohnlev DTRACE_XPV1(decrease__reservation__end, int, error); 866843e1988Sjohnlev break; 867843e1988Sjohnlev case XENMEM_populate_physmap: 868843e1988Sjohnlev DTRACE_XPV1(populate__physmap__end, int, error); 869843e1988Sjohnlev break; 870843e1988Sjohnlev case XENMEM_add_to_physmap: 871843e1988Sjohnlev DTRACE_XPV1(add__to__physmap__end, int, error); 872843e1988Sjohnlev break; 873843e1988Sjohnlev case XENMEM_set_memory_map: 874843e1988Sjohnlev DTRACE_XPV1(set__memory__map__end, int, error); 875843e1988Sjohnlev break; 876843e1988Sjohnlev } 877843e1988Sjohnlev return (error); 878843e1988Sjohnlev } 879843e1988Sjohnlev 880843e1988Sjohnlev static int 881843e1988Sjohnlev privcmd_HYPERVISOR_event_channel_op(int cmd, void *arg) 882843e1988Sjohnlev { 883843e1988Sjohnlev int error; 884843e1988Sjohnlev size_t size; 885843e1988Sjohnlev import_export_t op_ie; 886843e1988Sjohnlev uint32_t flags; 887843e1988Sjohnlev 888843e1988Sjohnlev switch (cmd) { 889843e1988Sjohnlev case EVTCHNOP_alloc_unbound: 890843e1988Sjohnlev size = sizeof (evtchn_alloc_unbound_t); 891843e1988Sjohnlev flags = IE_IMPEXP; 892843e1988Sjohnlev break; 893843e1988Sjohnlev case EVTCHNOP_bind_interdomain: 894843e1988Sjohnlev size = sizeof (evtchn_bind_interdomain_t); 895843e1988Sjohnlev flags = IE_IMPEXP; 896843e1988Sjohnlev break; 897843e1988Sjohnlev case EVTCHNOP_bind_virq: 898843e1988Sjohnlev size = sizeof (evtchn_bind_virq_t); 899843e1988Sjohnlev flags = IE_IMPEXP; 900843e1988Sjohnlev break; 901843e1988Sjohnlev case EVTCHNOP_bind_pirq: 902843e1988Sjohnlev size = sizeof (evtchn_bind_pirq_t); 903843e1988Sjohnlev flags = IE_IMPEXP; 904843e1988Sjohnlev break; 905843e1988Sjohnlev case EVTCHNOP_bind_ipi: 906843e1988Sjohnlev size = sizeof (evtchn_bind_ipi_t); 907843e1988Sjohnlev flags = IE_IMPEXP; 908843e1988Sjohnlev break; 909843e1988Sjohnlev case EVTCHNOP_close: 910843e1988Sjohnlev size = sizeof (evtchn_close_t); 911843e1988Sjohnlev flags = IE_IMPORT; 912843e1988Sjohnlev break; 913843e1988Sjohnlev case EVTCHNOP_send: 914843e1988Sjohnlev size = sizeof (evtchn_send_t); 915843e1988Sjohnlev flags = IE_IMPORT; 916843e1988Sjohnlev break; 917843e1988Sjohnlev case EVTCHNOP_status: 918843e1988Sjohnlev size = sizeof (evtchn_status_t); 919843e1988Sjohnlev flags = IE_IMPEXP; 920843e1988Sjohnlev break; 921843e1988Sjohnlev case EVTCHNOP_bind_vcpu: 922843e1988Sjohnlev size = sizeof (evtchn_bind_vcpu_t); 923843e1988Sjohnlev flags = IE_IMPORT; 924843e1988Sjohnlev break; 925843e1988Sjohnlev case EVTCHNOP_unmask: 926843e1988Sjohnlev size = sizeof (evtchn_unmask_t); 927843e1988Sjohnlev flags = IE_IMPORT; 928843e1988Sjohnlev break; 929a576ab5bSrab case EVTCHNOP_reset: 930a576ab5bSrab size = sizeof (evtchn_reset_t); 931a576ab5bSrab flags = IE_IMPORT; 932a576ab5bSrab break; 933843e1988Sjohnlev 934843e1988Sjohnlev default: 935843e1988Sjohnlev #ifdef DEBUG 936843e1988Sjohnlev printf("unrecognized HYPERVISOR_event_channel op %d\n", cmd); 937843e1988Sjohnlev #endif 938843e1988Sjohnlev return (-X_EINVAL); 939843e1988Sjohnlev } 940843e1988Sjohnlev 941843e1988Sjohnlev error = import_buffer(&op_ie, arg, NULL, size, flags); 942843e1988Sjohnlev 943843e1988Sjohnlev /* 944843e1988Sjohnlev * If there is sufficient demand, we can replace this void * with 945843e1988Sjohnlev * the proper op structure pointer. 946843e1988Sjohnlev */ 947843e1988Sjohnlev DTRACE_XPV2(evtchn__op__start, int, cmd, void *, 948843e1988Sjohnlev ((error == -X_EFAULT) ? arg : op_ie.ie_kaddr)); 949843e1988Sjohnlev 950843e1988Sjohnlev if (error == 0) 951843e1988Sjohnlev error = HYPERVISOR_event_channel_op(cmd, op_ie.ie_kaddr); 952843e1988Sjohnlev export_buffer(&op_ie, &error); 953843e1988Sjohnlev 954843e1988Sjohnlev DTRACE_XPV1(evtchn__op__end, int, error); 955843e1988Sjohnlev 956843e1988Sjohnlev return (error); 957843e1988Sjohnlev } 958843e1988Sjohnlev 959843e1988Sjohnlev static int 960843e1988Sjohnlev privcmd_HYPERVISOR_xen_version(int cmd, void *arg) 961843e1988Sjohnlev { 962843e1988Sjohnlev int error; 963843e1988Sjohnlev int size = 0; 964843e1988Sjohnlev import_export_t op_ie; 965843e1988Sjohnlev uint32_t flags = IE_EXPORT; 966843e1988Sjohnlev 967843e1988Sjohnlev switch (cmd) { 968843e1988Sjohnlev case XENVER_version: 969843e1988Sjohnlev break; 970843e1988Sjohnlev case XENVER_extraversion: 971843e1988Sjohnlev size = sizeof (xen_extraversion_t); 972843e1988Sjohnlev break; 973843e1988Sjohnlev case XENVER_compile_info: 974843e1988Sjohnlev size = sizeof (xen_compile_info_t); 975843e1988Sjohnlev break; 976843e1988Sjohnlev case XENVER_capabilities: 977843e1988Sjohnlev size = sizeof (xen_capabilities_info_t); 978843e1988Sjohnlev break; 979843e1988Sjohnlev case XENVER_changeset: 980843e1988Sjohnlev size = sizeof (xen_changeset_info_t); 981843e1988Sjohnlev break; 982843e1988Sjohnlev case XENVER_platform_parameters: 983843e1988Sjohnlev size = sizeof (xen_platform_parameters_t); 984843e1988Sjohnlev break; 985843e1988Sjohnlev case XENVER_get_features: 986843e1988Sjohnlev flags = IE_IMPEXP; 987843e1988Sjohnlev size = sizeof (xen_feature_info_t); 988843e1988Sjohnlev break; 989843e1988Sjohnlev case XENVER_pagesize: 990843e1988Sjohnlev break; 991843e1988Sjohnlev case XENVER_guest_handle: 992843e1988Sjohnlev size = sizeof (xen_domain_handle_t); 993843e1988Sjohnlev break; 994843e1988Sjohnlev 995843e1988Sjohnlev default: 996843e1988Sjohnlev #ifdef DEBUG 997843e1988Sjohnlev printf("unrecognized HYPERVISOR_xen_version op %d\n", cmd); 998843e1988Sjohnlev #endif 999843e1988Sjohnlev return (-X_EINVAL); 1000843e1988Sjohnlev } 1001843e1988Sjohnlev 1002843e1988Sjohnlev error = import_buffer(&op_ie, arg, NULL, size, flags); 1003843e1988Sjohnlev if (error == 0) 1004843e1988Sjohnlev error = HYPERVISOR_xen_version(cmd, op_ie.ie_kaddr); 1005843e1988Sjohnlev export_buffer(&op_ie, &error); 1006843e1988Sjohnlev 1007843e1988Sjohnlev return (error); 1008843e1988Sjohnlev } 1009843e1988Sjohnlev 1010843e1988Sjohnlev static int 1011349b53ddSStuart Maybee privcmd_HYPERVISOR_xsm_op(void *uacmctl) 1012843e1988Sjohnlev { 1013843e1988Sjohnlev int error; 1014a576ab5bSrab struct xen_acmctl *acmctl; 1015843e1988Sjohnlev import_export_t op_ie; 1016843e1988Sjohnlev 1017a576ab5bSrab error = import_buffer(&op_ie, uacmctl, NULL, sizeof (*acmctl), 1018a576ab5bSrab IE_IMPEXP); 1019a576ab5bSrab if (error != 0) 1020a576ab5bSrab return (error); 1021a576ab5bSrab 1022a576ab5bSrab acmctl = op_ie.ie_kaddr; 1023a576ab5bSrab 1024a576ab5bSrab if (acmctl->interface_version != ACM_INTERFACE_VERSION) { 1025a576ab5bSrab #ifdef DEBUG 1026a576ab5bSrab printf("acm vers mismatch (cmd %d, found 0x%x, need 0x%x\n", 1027a576ab5bSrab acmctl->cmd, acmctl->interface_version, 1028a576ab5bSrab ACM_INTERFACE_VERSION); 1029a576ab5bSrab #endif 1030a576ab5bSrab error = -X_EACCES; 1031a576ab5bSrab export_buffer(&op_ie, &error); 1032a576ab5bSrab return (error); 1033a576ab5bSrab } 1034a576ab5bSrab 1035349b53ddSStuart Maybee /* FIXME: flask ops??? */ 1036349b53ddSStuart Maybee 1037a576ab5bSrab switch (acmctl->cmd) { 1038843e1988Sjohnlev case ACMOP_setpolicy: 1039843e1988Sjohnlev case ACMOP_getpolicy: 1040843e1988Sjohnlev case ACMOP_dumpstats: 1041843e1988Sjohnlev case ACMOP_getssid: 1042843e1988Sjohnlev case ACMOP_getdecision: 1043a576ab5bSrab case ACMOP_chgpolicy: 1044a576ab5bSrab case ACMOP_relabeldoms: 1045349b53ddSStuart Maybee /* flags = IE_IMPEXP; */ 1046843e1988Sjohnlev break; 1047843e1988Sjohnlev default: 1048843e1988Sjohnlev #ifdef DEBUG 1049349b53ddSStuart Maybee printf("unrecognized HYPERVISOR_xsm_op op %d\n", acmctl->cmd); 1050843e1988Sjohnlev #endif 1051843e1988Sjohnlev return (-X_EINVAL); 1052843e1988Sjohnlev } 1053843e1988Sjohnlev 1054843e1988Sjohnlev if (error == 0) 1055349b53ddSStuart Maybee error = HYPERVISOR_xsm_op(acmctl); 1056843e1988Sjohnlev export_buffer(&op_ie, &error); 1057843e1988Sjohnlev 1058843e1988Sjohnlev return (error); 1059843e1988Sjohnlev } 1060843e1988Sjohnlev 1061843e1988Sjohnlev static int 1062843e1988Sjohnlev privcmd_HYPERVISOR_mmuext_op(struct mmuext_op *op, int count, uint_t *scount, 1063843e1988Sjohnlev domid_t domid) 1064843e1988Sjohnlev { 1065843e1988Sjohnlev int error, bytes; 1066843e1988Sjohnlev uint_t kscount; 1067843e1988Sjohnlev struct mmuext_op *kop, single_kop; 1068843e1988Sjohnlev import_export_t op_ie, scnt_ie; 1069843e1988Sjohnlev 1070843e1988Sjohnlev op_ie = scnt_ie = null_ie; 1071843e1988Sjohnlev error = 0; 1072843e1988Sjohnlev 1073843e1988Sjohnlev if (count >= 1) { 1074843e1988Sjohnlev bytes = count * sizeof (*kop); 1075843e1988Sjohnlev kop = (count == 1) ? &single_kop : kmem_alloc(bytes, KM_SLEEP); 1076843e1988Sjohnlev error = import_buffer(&op_ie, op, kop, bytes, IE_IMPORT); 1077843e1988Sjohnlev } 1078843e1988Sjohnlev 1079843e1988Sjohnlev DTRACE_XPV2(mmu__ext__op__start, int, count, struct mmuext_op *, 1080843e1988Sjohnlev ((error == -X_EFAULT) ? op : kop)); 1081843e1988Sjohnlev 1082843e1988Sjohnlev if (scount != NULL && error == 0) 1083843e1988Sjohnlev error = import_buffer(&scnt_ie, scount, &kscount, 1084843e1988Sjohnlev sizeof (kscount), IE_EXPORT); 1085843e1988Sjohnlev 1086843e1988Sjohnlev if (error == 0) 1087843e1988Sjohnlev error = HYPERVISOR_mmuext_op(kop, count, &kscount, domid); 1088843e1988Sjohnlev export_buffer(&op_ie, &error); 1089843e1988Sjohnlev export_buffer(&scnt_ie, &error); 1090843e1988Sjohnlev 1091843e1988Sjohnlev DTRACE_XPV1(mmu__ext__op__end, int, error); 1092843e1988Sjohnlev 1093843e1988Sjohnlev if (count > 1) 1094843e1988Sjohnlev kmem_free(kop, bytes); 1095843e1988Sjohnlev return (error); 1096843e1988Sjohnlev } 1097843e1988Sjohnlev 1098843e1988Sjohnlev static int 1099843e1988Sjohnlev privcmd_HYPERVISOR_hvm_op(int cmd, void *arg) 1100843e1988Sjohnlev { 1101843e1988Sjohnlev int error; 1102843e1988Sjohnlev int size = 0; 1103843e1988Sjohnlev import_export_t arg_ie; 1104843e1988Sjohnlev uint32_t flags = IE_IMPORT; 1105843e1988Sjohnlev 1106843e1988Sjohnlev switch (cmd) { 1107843e1988Sjohnlev case HVMOP_set_param: 1108843e1988Sjohnlev case HVMOP_get_param: 1109843e1988Sjohnlev size = sizeof (struct xen_hvm_param); 1110843e1988Sjohnlev flags = IE_IMPEXP; 1111843e1988Sjohnlev break; 1112843e1988Sjohnlev case HVMOP_set_pci_intx_level: 1113843e1988Sjohnlev size = sizeof (struct xen_hvm_set_pci_intx_level); 1114843e1988Sjohnlev break; 1115843e1988Sjohnlev case HVMOP_set_isa_irq_level: 1116843e1988Sjohnlev size = sizeof (struct xen_hvm_set_isa_irq_level); 1117843e1988Sjohnlev break; 1118843e1988Sjohnlev case HVMOP_set_pci_link_route: 1119843e1988Sjohnlev size = sizeof (struct xen_hvm_set_pci_link_route); 1120843e1988Sjohnlev break; 1121349b53ddSStuart Maybee case HVMOP_track_dirty_vram: 1122349b53ddSStuart Maybee size = sizeof (struct xen_hvm_track_dirty_vram); 1123349b53ddSStuart Maybee break; 1124349b53ddSStuart Maybee case HVMOP_modified_memory: 1125349b53ddSStuart Maybee size = sizeof (struct xen_hvm_modified_memory); 1126349b53ddSStuart Maybee break; 1127349b53ddSStuart Maybee case HVMOP_set_mem_type: 1128349b53ddSStuart Maybee size = sizeof (struct xen_hvm_set_mem_type); 1129349b53ddSStuart Maybee break; 1130843e1988Sjohnlev 1131843e1988Sjohnlev default: 1132843e1988Sjohnlev #ifdef DEBUG 1133843e1988Sjohnlev printf("unrecognized HVM op 0x%x\n", cmd); 1134843e1988Sjohnlev #endif 1135843e1988Sjohnlev return (-X_EINVAL); 1136843e1988Sjohnlev } 1137843e1988Sjohnlev 1138843e1988Sjohnlev error = import_buffer(&arg_ie, arg, NULL, size, flags); 1139843e1988Sjohnlev if (error == 0) 1140843e1988Sjohnlev error = HYPERVISOR_hvm_op(cmd, arg_ie.ie_kaddr); 1141843e1988Sjohnlev export_buffer(&arg_ie, &error); 1142843e1988Sjohnlev 1143843e1988Sjohnlev return (error); 1144843e1988Sjohnlev } 1145843e1988Sjohnlev 1146843e1988Sjohnlev static int 1147843e1988Sjohnlev privcmd_HYPERVISOR_sched_op(int cmd, void *arg) 1148843e1988Sjohnlev { 1149843e1988Sjohnlev int error; 1150843e1988Sjohnlev int size = 0; 1151843e1988Sjohnlev import_export_t op_ie; 1152843e1988Sjohnlev struct sched_remote_shutdown op; 1153843e1988Sjohnlev 1154843e1988Sjohnlev switch (cmd) { 1155843e1988Sjohnlev case SCHEDOP_remote_shutdown: 1156843e1988Sjohnlev size = sizeof (struct sched_remote_shutdown); 1157843e1988Sjohnlev break; 1158843e1988Sjohnlev default: 1159843e1988Sjohnlev #ifdef DEBUG 1160843e1988Sjohnlev printf("unrecognized sched op 0x%x\n", cmd); 1161843e1988Sjohnlev #endif 1162843e1988Sjohnlev return (-X_EINVAL); 1163843e1988Sjohnlev } 1164843e1988Sjohnlev 1165843e1988Sjohnlev error = import_buffer(&op_ie, arg, &op, size, IE_IMPORT); 1166843e1988Sjohnlev if (error == 0) 1167843e1988Sjohnlev error = HYPERVISOR_sched_op(cmd, (arg == NULL) ? NULL : &op); 1168843e1988Sjohnlev export_buffer(&op_ie, &error); 1169843e1988Sjohnlev 1170843e1988Sjohnlev return (error); 1171843e1988Sjohnlev } 1172843e1988Sjohnlev 1173843e1988Sjohnlev int allow_all_hypercalls = 0; 1174843e1988Sjohnlev int privcmd_efault_debug = 0; 1175843e1988Sjohnlev 1176843e1988Sjohnlev /*ARGSUSED*/ 1177843e1988Sjohnlev int 1178843e1988Sjohnlev do_privcmd_hypercall(void *uarg, int mode, cred_t *cr, int *rval) 1179843e1988Sjohnlev { 1180843e1988Sjohnlev privcmd_hypercall_t __hc, *hc = &__hc; 1181843e1988Sjohnlev int error; 1182843e1988Sjohnlev 1183843e1988Sjohnlev if (ddi_copyin(uarg, hc, sizeof (*hc), mode)) 1184843e1988Sjohnlev return (EFAULT); 1185843e1988Sjohnlev 1186843e1988Sjohnlev switch (hc->op) { 1187843e1988Sjohnlev case __HYPERVISOR_mmu_update: 1188843e1988Sjohnlev error = privcmd_HYPERVISOR_mmu_update( 1189843e1988Sjohnlev (mmu_update_t *)hc->arg[0], (int)hc->arg[1], 1190843e1988Sjohnlev (int *)hc->arg[2], (domid_t)hc->arg[3]); 1191843e1988Sjohnlev break; 1192843e1988Sjohnlev case __HYPERVISOR_domctl: 1193843e1988Sjohnlev error = privcmd_HYPERVISOR_domctl( 1194843e1988Sjohnlev (xen_domctl_t *)hc->arg[0]); 1195843e1988Sjohnlev break; 1196843e1988Sjohnlev case __HYPERVISOR_sysctl: 1197843e1988Sjohnlev error = privcmd_HYPERVISOR_sysctl( 1198843e1988Sjohnlev (xen_sysctl_t *)hc->arg[0]); 1199843e1988Sjohnlev break; 1200843e1988Sjohnlev case __HYPERVISOR_platform_op: 1201843e1988Sjohnlev error = privcmd_HYPERVISOR_platform_op( 1202843e1988Sjohnlev (xen_platform_op_t *)hc->arg[0]); 1203843e1988Sjohnlev break; 1204843e1988Sjohnlev case __HYPERVISOR_memory_op: 1205843e1988Sjohnlev error = privcmd_HYPERVISOR_memory_op( 1206843e1988Sjohnlev (int)hc->arg[0], (void *)hc->arg[1]); 1207843e1988Sjohnlev break; 1208843e1988Sjohnlev case __HYPERVISOR_event_channel_op: 1209843e1988Sjohnlev error = privcmd_HYPERVISOR_event_channel_op( 1210843e1988Sjohnlev (int)hc->arg[0], (void *)hc->arg[1]); 1211843e1988Sjohnlev break; 1212843e1988Sjohnlev case __HYPERVISOR_xen_version: 1213843e1988Sjohnlev error = privcmd_HYPERVISOR_xen_version( 1214843e1988Sjohnlev (int)hc->arg[0], (void *)hc->arg[1]); 1215843e1988Sjohnlev break; 1216843e1988Sjohnlev case __HYPERVISOR_mmuext_op: 1217843e1988Sjohnlev error = privcmd_HYPERVISOR_mmuext_op( 1218843e1988Sjohnlev (struct mmuext_op *)hc->arg[0], (int)hc->arg[1], 1219843e1988Sjohnlev (uint_t *)hc->arg[2], (domid_t)hc->arg[3]); 1220843e1988Sjohnlev break; 1221349b53ddSStuart Maybee case __HYPERVISOR_xsm_op: 1222349b53ddSStuart Maybee error = privcmd_HYPERVISOR_xsm_op((void *)hc->arg[0]); 1223843e1988Sjohnlev break; 1224843e1988Sjohnlev case __HYPERVISOR_hvm_op: 1225843e1988Sjohnlev error = privcmd_HYPERVISOR_hvm_op( 1226843e1988Sjohnlev (int)hc->arg[0], (void *)hc->arg[1]); 1227843e1988Sjohnlev break; 1228843e1988Sjohnlev case __HYPERVISOR_sched_op: 1229843e1988Sjohnlev error = privcmd_HYPERVISOR_sched_op( 1230843e1988Sjohnlev (int)hc->arg[0], (void *)hc->arg[1]); 1231843e1988Sjohnlev break; 1232843e1988Sjohnlev default: 1233843e1988Sjohnlev if (allow_all_hypercalls) 1234843e1988Sjohnlev error = __hypercall5(hc->op, hc->arg[0], hc->arg[1], 1235843e1988Sjohnlev hc->arg[2], hc->arg[3], hc->arg[4]); 1236843e1988Sjohnlev else { 1237843e1988Sjohnlev #ifdef DEBUG 1238843e1988Sjohnlev printf("unrecognized hypercall %ld\n", hc->op); 1239843e1988Sjohnlev #endif 1240843e1988Sjohnlev error = -X_EPERM; 1241843e1988Sjohnlev } 1242843e1988Sjohnlev break; 1243843e1988Sjohnlev } 1244843e1988Sjohnlev 1245843e1988Sjohnlev if (error > 0) { 1246843e1988Sjohnlev *rval = error; 1247843e1988Sjohnlev error = 0; 1248843e1988Sjohnlev } else if (error != 0) 1249843e1988Sjohnlev error = xen_xlate_errcode(error); 1250843e1988Sjohnlev 1251843e1988Sjohnlev return (error); 1252843e1988Sjohnlev } 1253