1*5741Smrj /* 2*5741Smrj * CDDL HEADER START 3*5741Smrj * 4*5741Smrj * The contents of this file are subject to the terms of the 5*5741Smrj * Common Development and Distribution License (the "License"). 6*5741Smrj * You may not use this file except in compliance with the License. 7*5741Smrj * 8*5741Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5741Smrj * or http://www.opensolaris.org/os/licensing. 10*5741Smrj * See the License for the specific language governing permissions 11*5741Smrj * and limitations under the License. 12*5741Smrj * 13*5741Smrj * When distributing Covered Code, include this CDDL HEADER in each 14*5741Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5741Smrj * If applicable, add the following below this CDDL HEADER, with the 16*5741Smrj * fields enclosed by brackets "[]" replaced with your own identifying 17*5741Smrj * information: Portions Copyright [yyyy] [name of copyright owner] 18*5741Smrj * 19*5741Smrj * CDDL HEADER END 20*5741Smrj */ 21*5741Smrj 22*5741Smrj /* 23*5741Smrj * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*5741Smrj * Use is subject to license terms. 25*5741Smrj */ 26*5741Smrj 27*5741Smrj #pragma ident "%Z%%M% %I% %E% SMI" 28*5741Smrj 29*5741Smrj /* 30*5741Smrj * Provides basic C wrappers around hypervisor invocation. 31*5741Smrj * 32*5741Smrj * i386: eax = vector: ebx, ecx, edx, esi, edi = args 1-5 33*5741Smrj * eax = return value 34*5741Smrj * (argument registers may be clobbered on return) 35*5741Smrj * 36*5741Smrj * amd64:rax = vector: rdi, rsi, rdx, r10, r8, r9 = args 1-6 37*5741Smrj * rax = return value 38*5741Smrj * (arguments registers not clobbered on return; rcx, r11 are) 39*5741Smrj */ 40*5741Smrj 41*5741Smrj #include <sys/types.h> 42*5741Smrj #ifdef XPV_HVM_DRIVER 43*5741Smrj #include <sys/xpv_support.h> 44*5741Smrj #endif 45*5741Smrj 46*5741Smrj #include <sys/hypervisor.h> 47*5741Smrj #include <xen/public/sched.h> 48*5741Smrj #include <sys/debug.h> 49*5741Smrj #include <sys/archsystm.h> 50*5741Smrj 51*5741Smrj long 52*5741Smrj HYPERVISOR_set_trap_table(trap_info_t *table) 53*5741Smrj { 54*5741Smrj return (__hypercall1(__HYPERVISOR_set_trap_table, (ulong_t)table)); 55*5741Smrj } 56*5741Smrj 57*5741Smrj int 58*5741Smrj HYPERVISOR_mmu_update(mmu_update_t *req, int count, int *success_count, 59*5741Smrj domid_t domain_id) 60*5741Smrj { 61*5741Smrj return (__hypercall4_int(__HYPERVISOR_mmu_update, 62*5741Smrj (ulong_t)req, (long)count, (ulong_t)success_count, 63*5741Smrj (ulong_t)domain_id)); 64*5741Smrj } 65*5741Smrj 66*5741Smrj long 67*5741Smrj HYPERVISOR_set_gdt(ulong_t *frame_list, int entries) 68*5741Smrj { 69*5741Smrj return (__hypercall2( 70*5741Smrj __HYPERVISOR_set_gdt, (ulong_t)frame_list, (long)entries)); 71*5741Smrj } 72*5741Smrj 73*5741Smrj /* 74*5741Smrj * XXPV Seems like "sp" would be a better name for both amd64 and i386? 75*5741Smrj * For now stay consistent with xen project source. 76*5741Smrj */ 77*5741Smrj long 78*5741Smrj HYPERVISOR_stack_switch(ulong_t ss, ulong_t esp) 79*5741Smrj { 80*5741Smrj return (__hypercall2(__HYPERVISOR_stack_switch, ss, esp)); 81*5741Smrj } 82*5741Smrj 83*5741Smrj #if defined(__amd64) 84*5741Smrj 85*5741Smrj long 86*5741Smrj HYPERVISOR_set_callbacks(ulong_t event_address, ulong_t failsafe_address, 87*5741Smrj ulong_t syscall_address) 88*5741Smrj { 89*5741Smrj return (__hypercall3(__HYPERVISOR_set_callbacks, 90*5741Smrj event_address, failsafe_address, syscall_address)); 91*5741Smrj } 92*5741Smrj 93*5741Smrj #elif defined(__i386) 94*5741Smrj 95*5741Smrj long 96*5741Smrj HYPERVISOR_set_callbacks( 97*5741Smrj ulong_t event_selector, ulong_t event_address, 98*5741Smrj ulong_t failsafe_selector, ulong_t failsafe_address) 99*5741Smrj { 100*5741Smrj return (__hypercall4(__HYPERVISOR_set_callbacks, 101*5741Smrj event_selector, event_address, 102*5741Smrj failsafe_selector, failsafe_address)); 103*5741Smrj } 104*5741Smrj 105*5741Smrj #endif /* __amd64 */ 106*5741Smrj 107*5741Smrj long 108*5741Smrj HYPERVISOR_fpu_taskswitch(int set) 109*5741Smrj { 110*5741Smrj return (__hypercall1(__HYPERVISOR_fpu_taskswitch, (long)set)); 111*5741Smrj } 112*5741Smrj 113*5741Smrj /* *** __HYPERVISOR_sched_op_compat *** OBSOLETED */ 114*5741Smrj 115*5741Smrj long 116*5741Smrj HYPERVISOR_platform_op(xen_platform_op_t *platform_op) 117*5741Smrj { 118*5741Smrj return (__hypercall1(__HYPERVISOR_platform_op, (ulong_t)platform_op)); 119*5741Smrj } 120*5741Smrj 121*5741Smrj /* *** __HYPERVISOR_set_debugreg *** NOT IMPLEMENTED */ 122*5741Smrj 123*5741Smrj /* *** __HYPERVISOR_get_debugreg *** NOT IMPLEMENTED */ 124*5741Smrj 125*5741Smrj long 126*5741Smrj HYPERVISOR_update_descriptor(maddr_t ma, uint64_t desc) 127*5741Smrj { 128*5741Smrj #if defined(__amd64) 129*5741Smrj 130*5741Smrj return (__hypercall2(__HYPERVISOR_update_descriptor, ma, desc)); 131*5741Smrj 132*5741Smrj #elif defined(__i386) 133*5741Smrj 134*5741Smrj return (__hypercall4(__HYPERVISOR_update_descriptor, 135*5741Smrj (ulong_t)ma, (ulong_t)(ma >>32), 136*5741Smrj (ulong_t)desc, (ulong_t)(desc >> 32))); 137*5741Smrj 138*5741Smrj #endif 139*5741Smrj } 140*5741Smrj 141*5741Smrj long 142*5741Smrj HYPERVISOR_memory_op(int cmd, void *arg) 143*5741Smrj { 144*5741Smrj return (__hypercall2(__HYPERVISOR_memory_op, (long)cmd, 145*5741Smrj (ulong_t)arg)); 146*5741Smrj } 147*5741Smrj 148*5741Smrj long 149*5741Smrj HYPERVISOR_multicall(void *call_list, uint_t nr_calls) 150*5741Smrj { 151*5741Smrj return (__hypercall2(__HYPERVISOR_multicall, 152*5741Smrj (ulong_t)call_list, (ulong_t)nr_calls)); 153*5741Smrj } 154*5741Smrj 155*5741Smrj int 156*5741Smrj HYPERVISOR_update_va_mapping(ulong_t va, uint64_t new_pte, ulong_t flags) 157*5741Smrj { 158*5741Smrj #if !defined(_BOOT) 159*5741Smrj if (IN_XPV_PANIC()) 160*5741Smrj return (0); 161*5741Smrj #endif 162*5741Smrj #if defined(__amd64) 163*5741Smrj 164*5741Smrj return (__hypercall3_int(__HYPERVISOR_update_va_mapping, va, 165*5741Smrj new_pte, flags)); 166*5741Smrj 167*5741Smrj #elif defined(__i386) 168*5741Smrj 169*5741Smrj return (__hypercall4_int(__HYPERVISOR_update_va_mapping, va, 170*5741Smrj (ulong_t)new_pte, (ulong_t)(new_pte >> 32), flags)); 171*5741Smrj 172*5741Smrj #endif /* __i386 */ 173*5741Smrj } 174*5741Smrj 175*5741Smrj /* 176*5741Smrj * Note: this timeout must be the Xen system time not hrtime (see 177*5741Smrj * xpv_timestamp.c). 178*5741Smrj */ 179*5741Smrj long 180*5741Smrj HYPERVISOR_set_timer_op(uint64_t timeout) 181*5741Smrj { 182*5741Smrj #if defined(__amd64) 183*5741Smrj 184*5741Smrj return (__hypercall1(__HYPERVISOR_set_timer_op, timeout)); 185*5741Smrj 186*5741Smrj #elif defined(__i386) 187*5741Smrj 188*5741Smrj uint32_t timeout_hi = (uint32_t)(timeout >> 32); 189*5741Smrj uint32_t timeout_lo = (uint32_t)timeout; 190*5741Smrj return (__hypercall2(__HYPERVISOR_set_timer_op, 191*5741Smrj (ulong_t)timeout_lo, (ulong_t)timeout_hi)); 192*5741Smrj 193*5741Smrj #endif /* __i386 */ 194*5741Smrj } 195*5741Smrj 196*5741Smrj /* *** __HYPERVISOR_event_channel_op_compat *** OBSOLETED */ 197*5741Smrj 198*5741Smrj long 199*5741Smrj HYPERVISOR_xen_version(int cmd, void *arg) 200*5741Smrj { 201*5741Smrj return (__hypercall2(__HYPERVISOR_xen_version, (long)cmd, 202*5741Smrj (ulong_t)arg)); 203*5741Smrj } 204*5741Smrj 205*5741Smrj long 206*5741Smrj HYPERVISOR_console_io(int cmd, int count, char *str) 207*5741Smrj { 208*5741Smrj return (__hypercall3(__HYPERVISOR_console_io, (long)cmd, (long)count, 209*5741Smrj (ulong_t)str)); 210*5741Smrj } 211*5741Smrj 212*5741Smrj /* *** __HYPERVISOR_physdev_op_compat *** OBSOLETED */ 213*5741Smrj 214*5741Smrj long 215*5741Smrj HYPERVISOR_grant_table_op(uint_t cmd, void *uop, uint_t count) 216*5741Smrj { 217*5741Smrj int ret_val; 218*5741Smrj ret_val = __hypercall3(__HYPERVISOR_grant_table_op, 219*5741Smrj (long)cmd, (ulong_t)uop, (ulong_t)count); 220*5741Smrj 221*5741Smrj #if !defined(_BOOT) && !defined(XPV_HVM_DRIVER) 222*5741Smrj /* 223*5741Smrj * XXPV -- 224*5741Smrj * The map_grant_ref call suffers a poor design flaw. 225*5741Smrj * It's the only hypervisor interface that creates page table mappings 226*5741Smrj * that doesn't take an entire PTE. Hence we can't create the 227*5741Smrj * mapping with a particular setting of the software PTE bits, NX, etc. 228*5741Smrj * 229*5741Smrj * Until the interface is fixed, we need to minimize the possiblity 230*5741Smrj * of dtrace or kmdb blowing up on a foreign mapping that doesn't 231*5741Smrj * have a correct setting for the soft bits. We'll force them here. 232*5741Smrj */ 233*5741Smrj if (ret_val == 0 && cmd == GNTTABOP_map_grant_ref) { 234*5741Smrj extern void xen_fix_foreign(uint64_t); 235*5741Smrj gnttab_map_grant_ref_t *mapops = (gnttab_map_grant_ref_t *)uop; 236*5741Smrj uint_t i; 237*5741Smrj for (i = 0; i < count; ++i) { 238*5741Smrj if (mapops[i].status == GNTST_okay) 239*5741Smrj xen_fix_foreign(mapops[i].host_addr); 240*5741Smrj } 241*5741Smrj } 242*5741Smrj #endif 243*5741Smrj return (ret_val); 244*5741Smrj } 245*5741Smrj 246*5741Smrj long 247*5741Smrj HYPERVISOR_vm_assist(uint_t cmd, uint_t type) 248*5741Smrj { 249*5741Smrj return (__hypercall2(__HYPERVISOR_vm_assist, 250*5741Smrj (ulong_t)cmd, (ulong_t)type)); 251*5741Smrj } 252*5741Smrj 253*5741Smrj int 254*5741Smrj HYPERVISOR_update_va_mapping_otherdomain(ulong_t va, 255*5741Smrj uint64_t new_pte, ulong_t flags, domid_t domain_id) 256*5741Smrj { 257*5741Smrj #if defined(__amd64) 258*5741Smrj 259*5741Smrj return (__hypercall4_int(__HYPERVISOR_update_va_mapping_otherdomain, 260*5741Smrj va, new_pte, flags, (ulong_t)domain_id)); 261*5741Smrj 262*5741Smrj #elif defined(__i386) 263*5741Smrj 264*5741Smrj return (__hypercall5_int(__HYPERVISOR_update_va_mapping_otherdomain, 265*5741Smrj va, (ulong_t)new_pte, (ulong_t)(new_pte >> 32), flags, 266*5741Smrj (ulong_t)domain_id)); 267*5741Smrj 268*5741Smrj #endif /* __i386 */ 269*5741Smrj } 270*5741Smrj 271*5741Smrj /* 272*5741Smrj * *** __HYPERVISOR_iret *** 273*5741Smrj * see HYPERVISOR_IRET() macro in i86xpv/sys/machprivregs.h 274*5741Smrj */ 275*5741Smrj 276*5741Smrj long 277*5741Smrj HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args) 278*5741Smrj { 279*5741Smrj return (__hypercall3(__HYPERVISOR_vcpu_op, (long)cmd, (long)vcpuid, 280*5741Smrj (ulong_t)extra_args)); 281*5741Smrj } 282*5741Smrj 283*5741Smrj #if defined(__amd64) 284*5741Smrj 285*5741Smrj long 286*5741Smrj HYPERVISOR_set_segment_base(int reg, ulong_t value) 287*5741Smrj { 288*5741Smrj return (__hypercall2(__HYPERVISOR_set_segment_base, (long)reg, value)); 289*5741Smrj } 290*5741Smrj 291*5741Smrj #endif /* __amd64 */ 292*5741Smrj 293*5741Smrj int 294*5741Smrj HYPERVISOR_mmuext_op(struct mmuext_op *req, int count, uint_t *success_count, 295*5741Smrj domid_t domain_id) 296*5741Smrj { 297*5741Smrj return (__hypercall4_int(__HYPERVISOR_mmuext_op, 298*5741Smrj (ulong_t)req, (long)count, (ulong_t)success_count, 299*5741Smrj (ulong_t)domain_id)); 300*5741Smrj } 301*5741Smrj 302*5741Smrj long 303*5741Smrj HYPERVISOR_acm_op(int cmd, void *arg) 304*5741Smrj { 305*5741Smrj return (__hypercall2(__HYPERVISOR_acm_op, (long)cmd, (ulong_t)arg)); 306*5741Smrj } 307*5741Smrj 308*5741Smrj long 309*5741Smrj HYPERVISOR_nmi_op(int cmd, void *arg) 310*5741Smrj { 311*5741Smrj return (__hypercall2(__HYPERVISOR_nmi_op, (long)cmd, (ulong_t)arg)); 312*5741Smrj } 313*5741Smrj 314*5741Smrj long 315*5741Smrj HYPERVISOR_sched_op(int cmd, void *arg) 316*5741Smrj { 317*5741Smrj return (__hypercall2(__HYPERVISOR_sched_op, 318*5741Smrj (ulong_t)cmd, (ulong_t)arg)); 319*5741Smrj } 320*5741Smrj 321*5741Smrj long 322*5741Smrj HYPERVISOR_callback_op(int cmd, void *arg) 323*5741Smrj { 324*5741Smrj return (__hypercall2(__HYPERVISOR_callback_op, 325*5741Smrj (ulong_t)cmd, (ulong_t)arg)); 326*5741Smrj } 327*5741Smrj 328*5741Smrj /* *** __HYPERVISOR_xenoprof_op *** NOT IMPLEMENTED */ 329*5741Smrj 330*5741Smrj long 331*5741Smrj HYPERVISOR_event_channel_op(int cmd, void *arg) 332*5741Smrj { 333*5741Smrj return (__hypercall2(__HYPERVISOR_event_channel_op, (long)cmd, 334*5741Smrj (ulong_t)arg)); 335*5741Smrj } 336*5741Smrj 337*5741Smrj long 338*5741Smrj HYPERVISOR_physdev_op(int cmd, void *arg) 339*5741Smrj { 340*5741Smrj return (__hypercall2(__HYPERVISOR_physdev_op, (long)cmd, 341*5741Smrj (ulong_t)arg)); 342*5741Smrj } 343*5741Smrj 344*5741Smrj long 345*5741Smrj HYPERVISOR_hvm_op(int cmd, void *arg) 346*5741Smrj { 347*5741Smrj return (__hypercall2(__HYPERVISOR_hvm_op, (long)cmd, (ulong_t)arg)); 348*5741Smrj } 349*5741Smrj 350*5741Smrj long 351*5741Smrj HYPERVISOR_sysctl(xen_sysctl_t *sysctl) 352*5741Smrj { 353*5741Smrj return (__hypercall1(__HYPERVISOR_sysctl, (ulong_t)sysctl)); 354*5741Smrj } 355*5741Smrj 356*5741Smrj long 357*5741Smrj HYPERVISOR_domctl(xen_domctl_t *domctl) 358*5741Smrj { 359*5741Smrj return (__hypercall1(__HYPERVISOR_domctl, (ulong_t)domctl)); 360*5741Smrj } 361*5741Smrj 362*5741Smrj /* *** __HYPERVISOR_kexec_op *** NOT IMPLEMENTED */ 363*5741Smrj 364*5741Smrj /* 365*5741Smrj * 366*5741Smrj * HYPERCALL HELPER ROUTINES 367*5741Smrj * These don't have there own unique hypercalls. 368*5741Smrj * 369*5741Smrj */ 370*5741Smrj 371*5741Smrj long 372*5741Smrj HYPERVISOR_yield(void) 373*5741Smrj { 374*5741Smrj return (HYPERVISOR_sched_op(SCHEDOP_yield, NULL)); 375*5741Smrj } 376*5741Smrj 377*5741Smrj long 378*5741Smrj HYPERVISOR_block(void) 379*5741Smrj { 380*5741Smrj return (HYPERVISOR_sched_op(SCHEDOP_block, NULL)); 381*5741Smrj } 382*5741Smrj 383*5741Smrj long 384*5741Smrj HYPERVISOR_shutdown(uint_t reason) 385*5741Smrj { 386*5741Smrj struct sched_shutdown sched_shutdown; 387*5741Smrj 388*5741Smrj sched_shutdown.reason = reason; 389*5741Smrj 390*5741Smrj return (HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown)); 391*5741Smrj } 392*5741Smrj 393*5741Smrj /* 394*5741Smrj * Poll one or more event-channel ports, and return when pending. 395*5741Smrj * An optional timeout (in nanoseconds, absolute time since boot) may be 396*5741Smrj * specified. Note: this timeout must be the Xen system time not hrtime (see 397*5741Smrj * xpv_timestamp.c). 398*5741Smrj */ 399*5741Smrj long 400*5741Smrj HYPERVISOR_poll(evtchn_port_t *ports, uint_t nr_ports, uint64_t timeout) 401*5741Smrj { 402*5741Smrj struct sched_poll sched_poll; 403*5741Smrj 404*5741Smrj /*LINTED: constant in conditional context*/ 405*5741Smrj set_xen_guest_handle(sched_poll.ports, ports); 406*5741Smrj sched_poll.nr_ports = nr_ports; 407*5741Smrj sched_poll.timeout = timeout; 408*5741Smrj 409*5741Smrj return (HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll)); 410*5741Smrj } 411*5741Smrj 412*5741Smrj long 413*5741Smrj HYPERVISOR_suspend(ulong_t start_info_mfn) 414*5741Smrj { 415*5741Smrj struct sched_shutdown sched_shutdown; 416*5741Smrj 417*5741Smrj sched_shutdown.reason = SHUTDOWN_suspend; 418*5741Smrj 419*5741Smrj return (__hypercall3(__HYPERVISOR_sched_op, SCHEDOP_shutdown, 420*5741Smrj (ulong_t)&sched_shutdown, start_info_mfn)); 421*5741Smrj } 422