xref: /illumos-gate/usr/src/uts/common/xen/os/hypercall.c (revision 0803869a9bc0aff1c81287ac6eae15943cbba545)
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
53 HYPERVISOR_set_trap_table(trap_info_t *table)
54 {
55 	return (__hypercall1(__HYPERVISOR_set_trap_table, (ulong_t)table));
56 }
57 
58 int
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
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
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
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 #elif defined(__i386)
95 
96 long
97 HYPERVISOR_set_callbacks(
98     ulong_t event_selector, ulong_t event_address,
99     ulong_t failsafe_selector, ulong_t failsafe_address)
100 {
101 	return (__hypercall4(__HYPERVISOR_set_callbacks,
102 	    event_selector, event_address,
103 	    failsafe_selector, failsafe_address));
104 }
105 
106 #endif	/* __amd64 */
107 
108 long
109 HYPERVISOR_fpu_taskswitch(int set)
110 {
111 	return (__hypercall1(__HYPERVISOR_fpu_taskswitch, (long)set));
112 }
113 
114 /* *** __HYPERVISOR_sched_op_compat *** OBSOLETED */
115 
116 long
117 HYPERVISOR_platform_op(xen_platform_op_t *platform_op)
118 {
119 	return (__hypercall1(__HYPERVISOR_platform_op, (ulong_t)platform_op));
120 }
121 
122 /* *** __HYPERVISOR_set_debugreg *** NOT IMPLEMENTED */
123 
124 /* *** __HYPERVISOR_get_debugreg *** NOT IMPLEMENTED */
125 
126 long
127 HYPERVISOR_update_descriptor(maddr_t ma, uint64_t desc)
128 {
129 #if defined(__amd64)
130 
131 	return (__hypercall2(__HYPERVISOR_update_descriptor, ma, desc));
132 
133 #elif defined(__i386)
134 
135 	return (__hypercall4(__HYPERVISOR_update_descriptor,
136 	    (ulong_t)ma, (ulong_t)(ma >>32),
137 	    (ulong_t)desc, (ulong_t)(desc >> 32)));
138 
139 #endif
140 }
141 
142 long
143 HYPERVISOR_memory_op(int cmd, void *arg)
144 {
145 	return (__hypercall2(__HYPERVISOR_memory_op, (long)cmd,
146 	    (ulong_t)arg));
147 }
148 
149 long
150 HYPERVISOR_multicall(void *call_list, uint_t nr_calls)
151 {
152 	return (__hypercall2(__HYPERVISOR_multicall,
153 	    (ulong_t)call_list, (ulong_t)nr_calls));
154 }
155 
156 int
157 HYPERVISOR_update_va_mapping(ulong_t va, uint64_t new_pte, ulong_t flags)
158 {
159 #if !defined(_BOOT)
160 	if (IN_XPV_PANIC())
161 		return (0);
162 #endif
163 #if defined(__amd64)
164 
165 	return (__hypercall3_int(__HYPERVISOR_update_va_mapping, va,
166 	    new_pte, flags));
167 
168 #elif defined(__i386)
169 
170 	return (__hypercall4_int(__HYPERVISOR_update_va_mapping, va,
171 	    (ulong_t)new_pte, (ulong_t)(new_pte >> 32), flags));
172 
173 #endif	/* __i386 */
174 }
175 
176 /*
177  * Note: this timeout must be the Xen system time not hrtime (see
178  * xpv_timestamp.c).
179  */
180 long
181 HYPERVISOR_set_timer_op(uint64_t timeout)
182 {
183 #if defined(__amd64)
184 
185 	return (__hypercall1(__HYPERVISOR_set_timer_op, timeout));
186 
187 #elif defined(__i386)
188 
189 	uint32_t timeout_hi = (uint32_t)(timeout >> 32);
190 	uint32_t timeout_lo = (uint32_t)timeout;
191 	return (__hypercall2(__HYPERVISOR_set_timer_op,
192 	    (ulong_t)timeout_lo, (ulong_t)timeout_hi));
193 
194 #endif	/* __i386 */
195 }
196 
197 /* *** __HYPERVISOR_event_channel_op_compat *** OBSOLETED */
198 
199 long
200 HYPERVISOR_xen_version(int cmd, void *arg)
201 {
202 	return (__hypercall2(__HYPERVISOR_xen_version, (long)cmd,
203 	    (ulong_t)arg));
204 }
205 
206 long
207 HYPERVISOR_console_io(int cmd, int count, char *str)
208 {
209 	return (__hypercall3(__HYPERVISOR_console_io, (long)cmd, (long)count,
210 	    (ulong_t)str));
211 }
212 
213 /* *** __HYPERVISOR_physdev_op_compat *** OBSOLETED */
214 
215 /*
216  * ****
217  * NOTE: this hypercall should not be called directly for a
218  * GNTTABOP_map_grant_ref. Instead xen_map_gref() should be called.
219  * ****
220  */
221 long
222 HYPERVISOR_grant_table_op(uint_t cmd, void *uop, uint_t count)
223 {
224 	int ret_val;
225 	ret_val = __hypercall3(__HYPERVISOR_grant_table_op,
226 	    (long)cmd, (ulong_t)uop, (ulong_t)count);
227 	return (ret_val);
228 }
229 
230 long
231 HYPERVISOR_vm_assist(uint_t cmd, uint_t type)
232 {
233 	return (__hypercall2(__HYPERVISOR_vm_assist,
234 	    (ulong_t)cmd, (ulong_t)type));
235 }
236 
237 int
238 HYPERVISOR_update_va_mapping_otherdomain(ulong_t va,
239     uint64_t new_pte, ulong_t flags, domid_t domain_id)
240 {
241 #if defined(__amd64)
242 
243 	return (__hypercall4_int(__HYPERVISOR_update_va_mapping_otherdomain,
244 	    va, new_pte, flags, (ulong_t)domain_id));
245 
246 #elif defined(__i386)
247 
248 	return (__hypercall5_int(__HYPERVISOR_update_va_mapping_otherdomain,
249 	    va, (ulong_t)new_pte, (ulong_t)(new_pte >> 32), flags,
250 	    (ulong_t)domain_id));
251 
252 #endif	/* __i386 */
253 }
254 
255 /*
256  * *** __HYPERVISOR_iret ***
257  *   see HYPERVISOR_IRET() macro in i86xpv/sys/machprivregs.h
258  */
259 
260 long
261 HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
262 {
263 	return (__hypercall3(__HYPERVISOR_vcpu_op, (long)cmd, (long)vcpuid,
264 	    (ulong_t)extra_args));
265 }
266 
267 #if defined(__amd64)
268 
269 long
270 HYPERVISOR_set_segment_base(int reg, ulong_t value)
271 {
272 	return (__hypercall2(__HYPERVISOR_set_segment_base, (long)reg, value));
273 }
274 
275 #endif	/* __amd64 */
276 
277 int
278 HYPERVISOR_mmuext_op(struct mmuext_op *req, int count, uint_t *success_count,
279     domid_t domain_id)
280 {
281 	return (__hypercall4_int(__HYPERVISOR_mmuext_op,
282 	    (ulong_t)req, (long)count, (ulong_t)success_count,
283 	    (ulong_t)domain_id));
284 }
285 
286 long
287 HYPERVISOR_nmi_op(int cmd, void *arg)
288 {
289 	return (__hypercall2(__HYPERVISOR_nmi_op, (long)cmd, (ulong_t)arg));
290 }
291 
292 long
293 HYPERVISOR_sched_op(int cmd, void *arg)
294 {
295 	return (__hypercall2(__HYPERVISOR_sched_op,
296 	    (ulong_t)cmd, (ulong_t)arg));
297 }
298 
299 long
300 HYPERVISOR_callback_op(int cmd, void *arg)
301 {
302 	return (__hypercall2(__HYPERVISOR_callback_op,
303 	    (ulong_t)cmd, (ulong_t)arg));
304 }
305 
306 /* *** __HYPERVISOR_xenoprof_op *** NOT IMPLEMENTED */
307 
308 long
309 HYPERVISOR_event_channel_op(int cmd, void *arg)
310 {
311 	return (__hypercall2(__HYPERVISOR_event_channel_op, (long)cmd,
312 	    (ulong_t)arg));
313 }
314 
315 long
316 HYPERVISOR_physdev_op(int cmd, void *arg)
317 {
318 	return (__hypercall2(__HYPERVISOR_physdev_op, (long)cmd,
319 	    (ulong_t)arg));
320 }
321 
322 long
323 HYPERVISOR_hvm_op(int cmd, void *arg)
324 {
325 	return (__hypercall2(__HYPERVISOR_hvm_op, (long)cmd, (ulong_t)arg));
326 }
327 
328 #if defined(__xpv)
329 long
330 HYPERVISOR_xsm_op(struct xen_acmctl *arg)
331 {
332 	return (__hypercall1(__HYPERVISOR_xsm_op, (ulong_t)arg));
333 }
334 
335 long
336 HYPERVISOR_sysctl(xen_sysctl_t *sysctl)
337 {
338 	return (__hypercall1(__HYPERVISOR_sysctl, (ulong_t)sysctl));
339 }
340 
341 long
342 HYPERVISOR_domctl(xen_domctl_t *domctl)
343 {
344 	return (__hypercall1(__HYPERVISOR_domctl, (ulong_t)domctl));
345 }
346 #endif /* __xpv */
347 
348 /* *** __HYPERVISOR_kexec_op *** NOT IMPLEMENTED */
349 
350 /*
351  *
352  * HYPERCALL HELPER ROUTINES
353  *    These don't have there own unique hypercalls.
354  *
355  */
356 
357 long
358 HYPERVISOR_yield(void)
359 {
360 	return (HYPERVISOR_sched_op(SCHEDOP_yield, NULL));
361 }
362 
363 long
364 HYPERVISOR_block(void)
365 {
366 	return (HYPERVISOR_sched_op(SCHEDOP_block, NULL));
367 }
368 
369 long
370 HYPERVISOR_shutdown(uint_t reason)
371 {
372 	struct sched_shutdown sched_shutdown;
373 
374 	sched_shutdown.reason = reason;
375 
376 	return (HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown));
377 }
378 
379 /*
380  * Poll one or more event-channel ports, and return when pending.
381  * An optional timeout (in nanoseconds, absolute time since boot) may be
382  * specified. Note: this timeout must be the Xen system time not hrtime (see
383  * xpv_timestamp.c).
384  */
385 long
386 HYPERVISOR_poll(evtchn_port_t *ports, uint_t nr_ports, uint64_t timeout)
387 {
388 	struct sched_poll sched_poll;
389 
390 	/*LINTED: constant in conditional context*/
391 	set_xen_guest_handle(sched_poll.ports, ports);
392 	sched_poll.nr_ports = nr_ports;
393 	sched_poll.timeout = timeout;
394 
395 	return (HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll));
396 }
397 
398 long
399 HYPERVISOR_suspend(ulong_t start_info_mfn)
400 {
401 	struct sched_shutdown sched_shutdown;
402 
403 	sched_shutdown.reason = SHUTDOWN_suspend;
404 
405 	return (__hypercall3(__HYPERVISOR_sched_op, SCHEDOP_shutdown,
406 	    (ulong_t)&sched_shutdown, start_info_mfn));
407 }
408 
409 long
410 HYPERVISOR_mca(uint32_t cmd, xen_mc_t *xmcp)
411 {
412 	long rv;
413 
414 	switch (cmd) {
415 	case XEN_MC_fetch:
416 	case XEN_MC_physcpuinfo:
417 	case XEN_MC_msrinject:
418 	case XEN_MC_mceinject:
419 		break;
420 
421 	case XEN_MC_notifydomain:
422 		return (ENOTSUP);
423 
424 	default:
425 		return (EINVAL);
426 	}
427 
428 	xmcp->interface_version = XEN_MCA_INTERFACE_VERSION;
429 	xmcp->cmd = cmd;
430 
431 	rv = __hypercall1(__HYPERVISOR_mca, (ulong_t)xmcp);
432 
433 	return (rv);
434 }
435