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