15741Smrj /* 25741Smrj * CDDL HEADER START 35741Smrj * 45741Smrj * The contents of this file are subject to the terms of the 55741Smrj * Common Development and Distribution License (the "License"). 65741Smrj * You may not use this file except in compliance with the License. 75741Smrj * 85741Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95741Smrj * or http://www.opensolaris.org/os/licensing. 105741Smrj * See the License for the specific language governing permissions 115741Smrj * and limitations under the License. 125741Smrj * 135741Smrj * When distributing Covered Code, include this CDDL HEADER in each 145741Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155741Smrj * If applicable, add the following below this CDDL HEADER, with the 165741Smrj * fields enclosed by brackets "[]" replaced with your own identifying 175741Smrj * information: Portions Copyright [yyyy] [name of copyright owner] 185741Smrj * 195741Smrj * CDDL HEADER END 205741Smrj */ 215741Smrj 225741Smrj /* 236144Srab * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 245741Smrj * Use is subject to license terms. 255741Smrj */ 265741Smrj 275741Smrj /* 285741Smrj * Provides basic C wrappers around hypervisor invocation. 295741Smrj * 305741Smrj * i386: eax = vector: ebx, ecx, edx, esi, edi = args 1-5 315741Smrj * eax = return value 325741Smrj * (argument registers may be clobbered on return) 335741Smrj * 345741Smrj * amd64:rax = vector: rdi, rsi, rdx, r10, r8, r9 = args 1-6 355741Smrj * rax = return value 365741Smrj * (arguments registers not clobbered on return; rcx, r11 are) 375741Smrj */ 385741Smrj 395741Smrj #include <sys/types.h> 405741Smrj #ifdef XPV_HVM_DRIVER 415741Smrj #include <sys/xpv_support.h> 425741Smrj #endif 435741Smrj 445741Smrj #include <sys/hypervisor.h> 455741Smrj #include <xen/public/sched.h> 465741Smrj #include <sys/debug.h> 475741Smrj #include <sys/archsystm.h> 485741Smrj 495741Smrj long 505741Smrj HYPERVISOR_set_trap_table(trap_info_t *table) 515741Smrj { 525741Smrj return (__hypercall1(__HYPERVISOR_set_trap_table, (ulong_t)table)); 535741Smrj } 545741Smrj 555741Smrj int 565741Smrj HYPERVISOR_mmu_update(mmu_update_t *req, int count, int *success_count, 575741Smrj domid_t domain_id) 585741Smrj { 595741Smrj return (__hypercall4_int(__HYPERVISOR_mmu_update, 605741Smrj (ulong_t)req, (long)count, (ulong_t)success_count, 615741Smrj (ulong_t)domain_id)); 625741Smrj } 635741Smrj 645741Smrj long 655741Smrj HYPERVISOR_set_gdt(ulong_t *frame_list, int entries) 665741Smrj { 675741Smrj return (__hypercall2( 685741Smrj __HYPERVISOR_set_gdt, (ulong_t)frame_list, (long)entries)); 695741Smrj } 705741Smrj 715741Smrj /* 725741Smrj * XXPV Seems like "sp" would be a better name for both amd64 and i386? 735741Smrj * For now stay consistent with xen project source. 745741Smrj */ 755741Smrj long 765741Smrj HYPERVISOR_stack_switch(ulong_t ss, ulong_t esp) 775741Smrj { 785741Smrj return (__hypercall2(__HYPERVISOR_stack_switch, ss, esp)); 795741Smrj } 805741Smrj 815741Smrj #if defined(__amd64) 825741Smrj 835741Smrj long 845741Smrj HYPERVISOR_set_callbacks(ulong_t event_address, ulong_t failsafe_address, 855741Smrj ulong_t syscall_address) 865741Smrj { 875741Smrj return (__hypercall3(__HYPERVISOR_set_callbacks, 885741Smrj event_address, failsafe_address, syscall_address)); 895741Smrj } 905741Smrj 915741Smrj #elif defined(__i386) 925741Smrj 935741Smrj long 945741Smrj HYPERVISOR_set_callbacks( 955741Smrj ulong_t event_selector, ulong_t event_address, 965741Smrj ulong_t failsafe_selector, ulong_t failsafe_address) 975741Smrj { 985741Smrj return (__hypercall4(__HYPERVISOR_set_callbacks, 995741Smrj event_selector, event_address, 1005741Smrj failsafe_selector, failsafe_address)); 1015741Smrj } 1025741Smrj 1035741Smrj #endif /* __amd64 */ 1045741Smrj 1055741Smrj long 1065741Smrj HYPERVISOR_fpu_taskswitch(int set) 1075741Smrj { 1085741Smrj return (__hypercall1(__HYPERVISOR_fpu_taskswitch, (long)set)); 1095741Smrj } 1105741Smrj 1115741Smrj /* *** __HYPERVISOR_sched_op_compat *** OBSOLETED */ 1125741Smrj 1135741Smrj long 1145741Smrj HYPERVISOR_platform_op(xen_platform_op_t *platform_op) 1155741Smrj { 1165741Smrj return (__hypercall1(__HYPERVISOR_platform_op, (ulong_t)platform_op)); 1175741Smrj } 1185741Smrj 1195741Smrj /* *** __HYPERVISOR_set_debugreg *** NOT IMPLEMENTED */ 1205741Smrj 1215741Smrj /* *** __HYPERVISOR_get_debugreg *** NOT IMPLEMENTED */ 1225741Smrj 1235741Smrj long 1245741Smrj HYPERVISOR_update_descriptor(maddr_t ma, uint64_t desc) 1255741Smrj { 1265741Smrj #if defined(__amd64) 1275741Smrj 1285741Smrj return (__hypercall2(__HYPERVISOR_update_descriptor, ma, desc)); 1295741Smrj 1305741Smrj #elif defined(__i386) 1315741Smrj 1325741Smrj return (__hypercall4(__HYPERVISOR_update_descriptor, 1335741Smrj (ulong_t)ma, (ulong_t)(ma >>32), 1345741Smrj (ulong_t)desc, (ulong_t)(desc >> 32))); 1355741Smrj 1365741Smrj #endif 1375741Smrj } 1385741Smrj 1395741Smrj long 1405741Smrj HYPERVISOR_memory_op(int cmd, void *arg) 1415741Smrj { 1425741Smrj return (__hypercall2(__HYPERVISOR_memory_op, (long)cmd, 1435741Smrj (ulong_t)arg)); 1445741Smrj } 1455741Smrj 1465741Smrj long 1475741Smrj HYPERVISOR_multicall(void *call_list, uint_t nr_calls) 1485741Smrj { 1495741Smrj return (__hypercall2(__HYPERVISOR_multicall, 1505741Smrj (ulong_t)call_list, (ulong_t)nr_calls)); 1515741Smrj } 1525741Smrj 1535741Smrj int 1545741Smrj HYPERVISOR_update_va_mapping(ulong_t va, uint64_t new_pte, ulong_t flags) 1555741Smrj { 1565741Smrj #if !defined(_BOOT) 1575741Smrj if (IN_XPV_PANIC()) 1585741Smrj return (0); 1595741Smrj #endif 1605741Smrj #if defined(__amd64) 1615741Smrj 1625741Smrj return (__hypercall3_int(__HYPERVISOR_update_va_mapping, va, 1635741Smrj new_pte, flags)); 1645741Smrj 1655741Smrj #elif defined(__i386) 1665741Smrj 1675741Smrj return (__hypercall4_int(__HYPERVISOR_update_va_mapping, va, 1685741Smrj (ulong_t)new_pte, (ulong_t)(new_pte >> 32), flags)); 1695741Smrj 1705741Smrj #endif /* __i386 */ 1715741Smrj } 1725741Smrj 1735741Smrj /* 1745741Smrj * Note: this timeout must be the Xen system time not hrtime (see 1755741Smrj * xpv_timestamp.c). 1765741Smrj */ 1775741Smrj long 1785741Smrj HYPERVISOR_set_timer_op(uint64_t timeout) 1795741Smrj { 1805741Smrj #if defined(__amd64) 1815741Smrj 1825741Smrj return (__hypercall1(__HYPERVISOR_set_timer_op, timeout)); 1835741Smrj 1845741Smrj #elif defined(__i386) 1855741Smrj 1865741Smrj uint32_t timeout_hi = (uint32_t)(timeout >> 32); 1875741Smrj uint32_t timeout_lo = (uint32_t)timeout; 1885741Smrj return (__hypercall2(__HYPERVISOR_set_timer_op, 1895741Smrj (ulong_t)timeout_lo, (ulong_t)timeout_hi)); 1905741Smrj 1915741Smrj #endif /* __i386 */ 1925741Smrj } 1935741Smrj 1945741Smrj /* *** __HYPERVISOR_event_channel_op_compat *** OBSOLETED */ 1955741Smrj 1965741Smrj long 1975741Smrj HYPERVISOR_xen_version(int cmd, void *arg) 1985741Smrj { 1995741Smrj return (__hypercall2(__HYPERVISOR_xen_version, (long)cmd, 2005741Smrj (ulong_t)arg)); 2015741Smrj } 2025741Smrj 2035741Smrj long 2045741Smrj HYPERVISOR_console_io(int cmd, int count, char *str) 2055741Smrj { 2065741Smrj return (__hypercall3(__HYPERVISOR_console_io, (long)cmd, (long)count, 2075741Smrj (ulong_t)str)); 2085741Smrj } 2095741Smrj 2105741Smrj /* *** __HYPERVISOR_physdev_op_compat *** OBSOLETED */ 2115741Smrj 2125741Smrj long 2135741Smrj HYPERVISOR_grant_table_op(uint_t cmd, void *uop, uint_t count) 2145741Smrj { 2155741Smrj int ret_val; 2165741Smrj ret_val = __hypercall3(__HYPERVISOR_grant_table_op, 2175741Smrj (long)cmd, (ulong_t)uop, (ulong_t)count); 2185741Smrj 2195741Smrj #if !defined(_BOOT) && !defined(XPV_HVM_DRIVER) 2205741Smrj /* 2215741Smrj * XXPV -- 2225741Smrj * The map_grant_ref call suffers a poor design flaw. 2235741Smrj * It's the only hypervisor interface that creates page table mappings 2245741Smrj * that doesn't take an entire PTE. Hence we can't create the 2255741Smrj * mapping with a particular setting of the software PTE bits, NX, etc. 2265741Smrj * 2275741Smrj * Until the interface is fixed, we need to minimize the possiblity 2285741Smrj * of dtrace or kmdb blowing up on a foreign mapping that doesn't 2295741Smrj * have a correct setting for the soft bits. We'll force them here. 2305741Smrj */ 2315741Smrj if (ret_val == 0 && cmd == GNTTABOP_map_grant_ref) { 2325741Smrj extern void xen_fix_foreign(uint64_t); 2335741Smrj gnttab_map_grant_ref_t *mapops = (gnttab_map_grant_ref_t *)uop; 2345741Smrj uint_t i; 2355741Smrj for (i = 0; i < count; ++i) { 2365741Smrj if (mapops[i].status == GNTST_okay) 2375741Smrj xen_fix_foreign(mapops[i].host_addr); 2385741Smrj } 2395741Smrj } 2405741Smrj #endif 2415741Smrj return (ret_val); 2425741Smrj } 2435741Smrj 2445741Smrj long 2455741Smrj HYPERVISOR_vm_assist(uint_t cmd, uint_t type) 2465741Smrj { 2475741Smrj return (__hypercall2(__HYPERVISOR_vm_assist, 2485741Smrj (ulong_t)cmd, (ulong_t)type)); 2495741Smrj } 2505741Smrj 2515741Smrj int 2525741Smrj HYPERVISOR_update_va_mapping_otherdomain(ulong_t va, 2535741Smrj uint64_t new_pte, ulong_t flags, domid_t domain_id) 2545741Smrj { 2555741Smrj #if defined(__amd64) 2565741Smrj 2575741Smrj return (__hypercall4_int(__HYPERVISOR_update_va_mapping_otherdomain, 2585741Smrj va, new_pte, flags, (ulong_t)domain_id)); 2595741Smrj 2605741Smrj #elif defined(__i386) 2615741Smrj 2625741Smrj return (__hypercall5_int(__HYPERVISOR_update_va_mapping_otherdomain, 2635741Smrj va, (ulong_t)new_pte, (ulong_t)(new_pte >> 32), flags, 2645741Smrj (ulong_t)domain_id)); 2655741Smrj 2665741Smrj #endif /* __i386 */ 2675741Smrj } 2685741Smrj 2695741Smrj /* 2705741Smrj * *** __HYPERVISOR_iret *** 2715741Smrj * see HYPERVISOR_IRET() macro in i86xpv/sys/machprivregs.h 2725741Smrj */ 2735741Smrj 2745741Smrj long 2755741Smrj HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args) 2765741Smrj { 2775741Smrj return (__hypercall3(__HYPERVISOR_vcpu_op, (long)cmd, (long)vcpuid, 2785741Smrj (ulong_t)extra_args)); 2795741Smrj } 2805741Smrj 2815741Smrj #if defined(__amd64) 2825741Smrj 2835741Smrj long 2845741Smrj HYPERVISOR_set_segment_base(int reg, ulong_t value) 2855741Smrj { 2865741Smrj return (__hypercall2(__HYPERVISOR_set_segment_base, (long)reg, value)); 2875741Smrj } 2885741Smrj 2895741Smrj #endif /* __amd64 */ 2905741Smrj 2915741Smrj int 2925741Smrj HYPERVISOR_mmuext_op(struct mmuext_op *req, int count, uint_t *success_count, 2935741Smrj domid_t domain_id) 2945741Smrj { 2955741Smrj return (__hypercall4_int(__HYPERVISOR_mmuext_op, 2965741Smrj (ulong_t)req, (long)count, (ulong_t)success_count, 2975741Smrj (ulong_t)domain_id)); 2985741Smrj } 2995741Smrj 3005741Smrj long 3016144Srab HYPERVISOR_acm_op(struct xen_acmctl *arg) 3025741Smrj { 3036144Srab return (__hypercall1(__HYPERVISOR_acm_op, (ulong_t)arg)); 3045741Smrj } 3055741Smrj 3065741Smrj long 3075741Smrj HYPERVISOR_nmi_op(int cmd, void *arg) 3085741Smrj { 3095741Smrj return (__hypercall2(__HYPERVISOR_nmi_op, (long)cmd, (ulong_t)arg)); 3105741Smrj } 3115741Smrj 3125741Smrj long 3135741Smrj HYPERVISOR_sched_op(int cmd, void *arg) 3145741Smrj { 3155741Smrj return (__hypercall2(__HYPERVISOR_sched_op, 3165741Smrj (ulong_t)cmd, (ulong_t)arg)); 3175741Smrj } 3185741Smrj 3195741Smrj long 3205741Smrj HYPERVISOR_callback_op(int cmd, void *arg) 3215741Smrj { 3225741Smrj return (__hypercall2(__HYPERVISOR_callback_op, 3235741Smrj (ulong_t)cmd, (ulong_t)arg)); 3245741Smrj } 3255741Smrj 3265741Smrj /* *** __HYPERVISOR_xenoprof_op *** NOT IMPLEMENTED */ 3275741Smrj 3285741Smrj long 3295741Smrj HYPERVISOR_event_channel_op(int cmd, void *arg) 3305741Smrj { 3315741Smrj return (__hypercall2(__HYPERVISOR_event_channel_op, (long)cmd, 3325741Smrj (ulong_t)arg)); 3335741Smrj } 3345741Smrj 3355741Smrj long 3365741Smrj HYPERVISOR_physdev_op(int cmd, void *arg) 3375741Smrj { 3385741Smrj return (__hypercall2(__HYPERVISOR_physdev_op, (long)cmd, 3395741Smrj (ulong_t)arg)); 3405741Smrj } 3415741Smrj 3425741Smrj long 3435741Smrj HYPERVISOR_hvm_op(int cmd, void *arg) 3445741Smrj { 3455741Smrj return (__hypercall2(__HYPERVISOR_hvm_op, (long)cmd, (ulong_t)arg)); 3465741Smrj } 3475741Smrj 3485741Smrj long 3495741Smrj HYPERVISOR_sysctl(xen_sysctl_t *sysctl) 3505741Smrj { 3515741Smrj return (__hypercall1(__HYPERVISOR_sysctl, (ulong_t)sysctl)); 3525741Smrj } 3535741Smrj 3545741Smrj long 3555741Smrj HYPERVISOR_domctl(xen_domctl_t *domctl) 3565741Smrj { 3575741Smrj return (__hypercall1(__HYPERVISOR_domctl, (ulong_t)domctl)); 3585741Smrj } 3595741Smrj 3605741Smrj /* *** __HYPERVISOR_kexec_op *** NOT IMPLEMENTED */ 3615741Smrj 3625741Smrj /* 3635741Smrj * 3645741Smrj * HYPERCALL HELPER ROUTINES 3655741Smrj * These don't have there own unique hypercalls. 3665741Smrj * 3675741Smrj */ 3685741Smrj 3695741Smrj long 3705741Smrj HYPERVISOR_yield(void) 3715741Smrj { 3725741Smrj return (HYPERVISOR_sched_op(SCHEDOP_yield, NULL)); 3735741Smrj } 3745741Smrj 3755741Smrj long 3765741Smrj HYPERVISOR_block(void) 3775741Smrj { 3785741Smrj return (HYPERVISOR_sched_op(SCHEDOP_block, NULL)); 3795741Smrj } 3805741Smrj 3815741Smrj long 3825741Smrj HYPERVISOR_shutdown(uint_t reason) 3835741Smrj { 3845741Smrj struct sched_shutdown sched_shutdown; 3855741Smrj 3865741Smrj sched_shutdown.reason = reason; 3875741Smrj 3885741Smrj return (HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown)); 3895741Smrj } 3905741Smrj 3915741Smrj /* 3925741Smrj * Poll one or more event-channel ports, and return when pending. 3935741Smrj * An optional timeout (in nanoseconds, absolute time since boot) may be 3945741Smrj * specified. Note: this timeout must be the Xen system time not hrtime (see 3955741Smrj * xpv_timestamp.c). 3965741Smrj */ 3975741Smrj long 3985741Smrj HYPERVISOR_poll(evtchn_port_t *ports, uint_t nr_ports, uint64_t timeout) 3995741Smrj { 4005741Smrj struct sched_poll sched_poll; 4015741Smrj 4025741Smrj /*LINTED: constant in conditional context*/ 4035741Smrj set_xen_guest_handle(sched_poll.ports, ports); 4045741Smrj sched_poll.nr_ports = nr_ports; 4055741Smrj sched_poll.timeout = timeout; 4065741Smrj 4075741Smrj return (HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll)); 4085741Smrj } 4095741Smrj 4105741Smrj long 4115741Smrj HYPERVISOR_suspend(ulong_t start_info_mfn) 4125741Smrj { 4135741Smrj struct sched_shutdown sched_shutdown; 4145741Smrj 4155741Smrj sched_shutdown.reason = SHUTDOWN_suspend; 4165741Smrj 4175741Smrj return (__hypercall3(__HYPERVISOR_sched_op, SCHEDOP_shutdown, 4185741Smrj (ulong_t)&sched_shutdown, start_info_mfn)); 4195741Smrj } 420*7532SSean.Ye@Sun.COM 421*7532SSean.Ye@Sun.COM long 422*7532SSean.Ye@Sun.COM HYPERVISOR_mca(uint32_t cmd, xen_mc_arg_t *arg) 423*7532SSean.Ye@Sun.COM { 424*7532SSean.Ye@Sun.COM xen_mc_t xmc; 425*7532SSean.Ye@Sun.COM long rv; 426*7532SSean.Ye@Sun.COM 427*7532SSean.Ye@Sun.COM switch (cmd) { 428*7532SSean.Ye@Sun.COM case XEN_MC_CMD_fetch: 429*7532SSean.Ye@Sun.COM case XEN_MC_CMD_physcpuinfo: 430*7532SSean.Ye@Sun.COM case XEN_MC_CMD_msrinject: 431*7532SSean.Ye@Sun.COM case XEN_MC_CMD_mceinject: 432*7532SSean.Ye@Sun.COM case XEN_MC_CMD_offlinecpu: 433*7532SSean.Ye@Sun.COM if (arg == NULL) 434*7532SSean.Ye@Sun.COM return (EINVAL); 435*7532SSean.Ye@Sun.COM break; 436*7532SSean.Ye@Sun.COM 437*7532SSean.Ye@Sun.COM case XEN_MC_CMD_notifydomain: 438*7532SSean.Ye@Sun.COM return (ENOTSUP); 439*7532SSean.Ye@Sun.COM 440*7532SSean.Ye@Sun.COM default: 441*7532SSean.Ye@Sun.COM return (EINVAL); 442*7532SSean.Ye@Sun.COM } 443*7532SSean.Ye@Sun.COM 444*7532SSean.Ye@Sun.COM xmc.interface_version = XEN_MCA_INTERFACE_VERSION; 445*7532SSean.Ye@Sun.COM xmc.cmd = cmd; 446*7532SSean.Ye@Sun.COM if (arg != NULL) 447*7532SSean.Ye@Sun.COM xmc.u = *arg; 448*7532SSean.Ye@Sun.COM 449*7532SSean.Ye@Sun.COM rv = __hypercall1(__HYPERVISOR_mca, (ulong_t)&xmc); 450*7532SSean.Ye@Sun.COM 451*7532SSean.Ye@Sun.COM if (rv == XEN_MC_HCALL_SUCCESS && arg != NULL) 452*7532SSean.Ye@Sun.COM *arg = xmc.u; 453*7532SSean.Ye@Sun.COM 454*7532SSean.Ye@Sun.COM return (rv); 455*7532SSean.Ye@Sun.COM } 456