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