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