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