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 #endif /* __amd64 */ 95 96 long 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 251 HYPERVISOR_nmi_op(int cmd, void *arg) 252 { 253 return (__hypercall2(__HYPERVISOR_nmi_op, (long)cmd, (ulong_t)arg)); 254 } 255 256 long 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 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 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 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 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 294 HYPERVISOR_xsm_op(struct xen_acmctl *arg) 295 { 296 return (__hypercall1(__HYPERVISOR_xsm_op, (ulong_t)arg)); 297 } 298 299 long 300 HYPERVISOR_sysctl(xen_sysctl_t *sysctl) 301 { 302 return (__hypercall1(__HYPERVISOR_sysctl, (ulong_t)sysctl)); 303 } 304 305 long 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 322 HYPERVISOR_yield(void) 323 { 324 return (HYPERVISOR_sched_op(SCHEDOP_yield, NULL)); 325 } 326 327 long 328 HYPERVISOR_block(void) 329 { 330 return (HYPERVISOR_sched_op(SCHEDOP_block, NULL)); 331 } 332 333 long 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 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 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 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