1551bc2a6Smrj/* 2551bc2a6Smrj * CDDL HEADER START 3551bc2a6Smrj * 4551bc2a6Smrj * The contents of this file are subject to the terms of the 5551bc2a6Smrj * Common Development and Distribution License (the "License"). 6551bc2a6Smrj * You may not use this file except in compliance with the License. 7551bc2a6Smrj * 8551bc2a6Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9551bc2a6Smrj * or http://www.opensolaris.org/os/licensing. 10551bc2a6Smrj * See the License for the specific language governing permissions 11551bc2a6Smrj * and limitations under the License. 12551bc2a6Smrj * 13551bc2a6Smrj * When distributing Covered Code, include this CDDL HEADER in each 14551bc2a6Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15551bc2a6Smrj * If applicable, add the following below this CDDL HEADER, with the 16551bc2a6Smrj * fields enclosed by brackets "[]" replaced with your own identifying 17551bc2a6Smrj * information: Portions Copyright [yyyy] [name of copyright owner] 18551bc2a6Smrj * 19551bc2a6Smrj * CDDL HEADER END 20551bc2a6Smrj */ 21551bc2a6Smrj 22551bc2a6Smrj/* 23*349b53ddSStuart Maybee * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24551bc2a6Smrj * Use is subject to license terms. 25551bc2a6Smrj */ 26551bc2a6Smrj 27551bc2a6Smrj#include <sys/asm_linkage.h> 28*349b53ddSStuart Maybee#ifndef __xpv 29551bc2a6Smrj#include <sys/xpv_support.h> 30551bc2a6Smrj#endif 31551bc2a6Smrj#include <sys/hypervisor.h> 32551bc2a6Smrj 33551bc2a6Smrj/* 34551bc2a6Smrj * Hypervisor "system calls" 35551bc2a6Smrj * 36551bc2a6Smrj * i386 37551bc2a6Smrj * %eax == call number 38551bc2a6Smrj * args in registers (%ebx, %ecx, %edx, %esi, %edi) 39551bc2a6Smrj * 40551bc2a6Smrj * amd64 41551bc2a6Smrj * %rax == call number 42551bc2a6Smrj * args in registers (%rdi, %rsi, %rdx, %r10, %r8, %r9) 43551bc2a6Smrj * 44551bc2a6Smrj * Note that for amd64 we use %r10 instead of %rcx for passing 4th argument 45551bc2a6Smrj * as in C calling convention since the "syscall" instruction clobbers %rcx. 46551bc2a6Smrj * 47551bc2a6Smrj * (These calls can be done more efficiently as gcc-style inlines, but 48551bc2a6Smrj * for simplicity and help with initial debugging, we use these primitives 49551bc2a6Smrj * to build the hypervisor calls up from C wrappers.) 50551bc2a6Smrj */ 51551bc2a6Smrj 52551bc2a6Smrj#if defined(__lint) 53551bc2a6Smrj 54551bc2a6Smrj/*ARGSUSED*/ 55551bc2a6Smrjlong 56551bc2a6Smrj__hypercall0(int callnum) 57551bc2a6Smrj{ return (0); } 58551bc2a6Smrj 59551bc2a6Smrj/*ARGSUSED*/ 60551bc2a6Smrjlong 61551bc2a6Smrj__hypercall1(int callnum, ulong_t a1) 62551bc2a6Smrj{ return (0); } 63551bc2a6Smrj 64551bc2a6Smrj/*ARGSUSED*/ 65551bc2a6Smrjlong 66551bc2a6Smrj__hypercall2(int callnum, ulong_t a1, ulong_t a2) 67551bc2a6Smrj{ return (0); } 68551bc2a6Smrj 69551bc2a6Smrj/*ARGSUSED*/ 70551bc2a6Smrjlong 71551bc2a6Smrj__hypercall3(int callnum, ulong_t a1, ulong_t a2, ulong_t a3) 72551bc2a6Smrj{ return (0); } 73551bc2a6Smrj 74551bc2a6Smrj/*ARGSUSED*/ 75551bc2a6Smrjlong 76551bc2a6Smrj__hypercall4(int callnum, ulong_t a1, ulong_t a2, ulong_t a3, ulong_t a4) 77551bc2a6Smrj{ return (0); } 78551bc2a6Smrj 79551bc2a6Smrj/*ARGSUSED*/ 80551bc2a6Smrjlong 81551bc2a6Smrj__hypercall5(int callnum, 82551bc2a6Smrj ulong_t a1, ulong_t a2, ulong_t a3, ulong_t a4, ulong_t a5) 83551bc2a6Smrj{ return (0); } 84551bc2a6Smrj 85551bc2a6Smrj/*ARGSUSED*/ 86551bc2a6Smrjint 87551bc2a6Smrj__hypercall0_int(int callnum) 88551bc2a6Smrj{ return (0); } 89551bc2a6Smrj 90551bc2a6Smrj/*ARGSUSED*/ 91551bc2a6Smrjint 92551bc2a6Smrj__hypercall1_int(int callnum, ulong_t a1) 93551bc2a6Smrj{ return (0); } 94551bc2a6Smrj 95551bc2a6Smrj/*ARGSUSED*/ 96551bc2a6Smrjint 97551bc2a6Smrj__hypercall2_int(int callnum, ulong_t a1, ulong_t a2) 98551bc2a6Smrj{ return (0); } 99551bc2a6Smrj 100551bc2a6Smrj/*ARGSUSED*/ 101551bc2a6Smrjint 102551bc2a6Smrj__hypercall3_int(int callnum, ulong_t a1, ulong_t a2, ulong_t a3) 103551bc2a6Smrj{ return (0); } 104551bc2a6Smrj 105551bc2a6Smrj/*ARGSUSED*/ 106551bc2a6Smrjint 107551bc2a6Smrj__hypercall4_int(int callnum, ulong_t a1, ulong_t a2, ulong_t a3, ulong_t a4) 108551bc2a6Smrj{ return (0); } 109551bc2a6Smrj 110551bc2a6Smrj/*ARGSUSED*/ 111551bc2a6Smrjint 112551bc2a6Smrj__hypercall5_int(int callnum, 113551bc2a6Smrj ulong_t a1, ulong_t a2, ulong_t a3, ulong_t a4, ulong_t a5) 114551bc2a6Smrj{ return (0); } 115551bc2a6Smrj 116551bc2a6Smrj#else /* __lint */ 117551bc2a6Smrj 118551bc2a6Smrj/* 119551bc2a6Smrj * XXPV grr - assembler can't deal with an instruction in a quoted string 120551bc2a6Smrj */ 121551bc2a6Smrj#undef TRAP_INSTR /* cause it's currently "int $0x82" */ 122551bc2a6Smrj 123551bc2a6Smrj/* 124551bc2a6Smrj * The method for issuing a hypercall (i.e. a system call to the 125551bc2a6Smrj * hypervisor) varies from platform to platform. In 32-bit PV domains, an 126551bc2a6Smrj * 'int 82' triggers the call. In 64-bit PV domains, a 'syscall' does the 127551bc2a6Smrj * trick. 128551bc2a6Smrj * 129551bc2a6Smrj * HVM domains are more complicated. In all cases, we want to issue a 130551bc2a6Smrj * VMEXIT instruction, but AMD and Intel use different opcodes to represent 131551bc2a6Smrj * that instruction. Rather than build CPU-specific modules with the 132551bc2a6Smrj * different opcodes, we use the 'hypercall page' provided by Xen. This 133551bc2a6Smrj * page contains a collection of code stubs that do nothing except issue 134551bc2a6Smrj * hypercalls using the proper instructions for this machine. To keep the 135551bc2a6Smrj * wrapper code as simple and efficient as possible, we preallocate that 136551bc2a6Smrj * page below. When the module is loaded, we ask Xen to remap the 137551bc2a6Smrj * underlying PFN to that of the hypercall page. 138551bc2a6Smrj * 139551bc2a6Smrj * Note: this same mechanism could be used in PV domains, but using 140551bc2a6Smrj * hypercall page requires a call and several more instructions than simply 141551bc2a6Smrj * issuing the proper trap. 142551bc2a6Smrj */ 143*349b53ddSStuart Maybee#if !defined(__xpv) 144551bc2a6Smrj 145551bc2a6Smrj#define HYPERCALL_PAGESIZE 0x1000 146*349b53ddSStuart Maybee#define HYPERCALL_SHINFO_PAGESIZE 0x1000 147*349b53ddSStuart Maybee 148*349b53ddSStuart Maybee .data 149*349b53ddSStuart Maybee .align HYPERCALL_SHINFO_PAGESIZE 150*349b53ddSStuart Maybee .globl hypercall_shared_info_page 151*349b53ddSStuart Maybee .type hypercall_shared_info_page, @object 152*349b53ddSStuart Maybee .size hypercall_shared_info_page, HYPERCALL_SHINFO_PAGESIZE 153*349b53ddSStuart Maybeehypercall_shared_info_page: 154*349b53ddSStuart Maybee .skip HYPERCALL_SHINFO_PAGESIZE 155*349b53ddSStuart Maybee 156551bc2a6Smrj .text 157551bc2a6Smrj .align HYPERCALL_PAGESIZE 158551bc2a6Smrj .globl hypercall_page 159551bc2a6Smrj .type hypercall_page, @function 160551bc2a6Smrjhypercall_page: 161551bc2a6Smrj .skip HYPERCALL_PAGESIZE 162551bc2a6Smrj .size hypercall_page, HYPERCALL_PAGESIZE 163551bc2a6Smrj#if defined(__amd64) 164551bc2a6Smrj#define TRAP_INSTR \ 165551bc2a6Smrj shll $5, %eax; \ 166551bc2a6Smrj addq $hypercall_page, %rax; \ 167551bc2a6Smrj jmp *%rax 168551bc2a6Smrj#else 169551bc2a6Smrj#define TRAP_INSTR \ 170551bc2a6Smrj shll $5, %eax; \ 171551bc2a6Smrj addl $hypercall_page, %eax; \ 172551bc2a6Smrj call *%eax 173551bc2a6Smrj#endif 174551bc2a6Smrj 175*349b53ddSStuart Maybee#else /* !_xpv */ 176551bc2a6Smrj 177551bc2a6Smrj#if defined(__amd64) 178551bc2a6Smrj#define TRAP_INSTR syscall 179551bc2a6Smrj#elif defined(__i386) 180551bc2a6Smrj#define TRAP_INSTR int $0x82 181551bc2a6Smrj#endif 182*349b53ddSStuart Maybee#endif /* !__xpv */ 183551bc2a6Smrj 184551bc2a6Smrj 185551bc2a6Smrj#if defined(__amd64) 186551bc2a6Smrj 187551bc2a6Smrj ENTRY_NP(__hypercall0) 188551bc2a6Smrj ALTENTRY(__hypercall0_int) 189551bc2a6Smrj movl %edi, %eax 190551bc2a6Smrj TRAP_INSTR 191551bc2a6Smrj ret 192551bc2a6Smrj SET_SIZE(__hypercall0) 193551bc2a6Smrj 194551bc2a6Smrj ENTRY_NP(__hypercall1) 195551bc2a6Smrj ALTENTRY(__hypercall1_int) 196551bc2a6Smrj movl %edi, %eax 197551bc2a6Smrj movq %rsi, %rdi /* arg 1 */ 198551bc2a6Smrj TRAP_INSTR 199551bc2a6Smrj ret 200551bc2a6Smrj SET_SIZE(__hypercall1) 201551bc2a6Smrj 202551bc2a6Smrj ENTRY_NP(__hypercall2) 203551bc2a6Smrj ALTENTRY(__hypercall2_int) 204551bc2a6Smrj movl %edi, %eax 205551bc2a6Smrj movq %rsi, %rdi /* arg 1 */ 206551bc2a6Smrj movq %rdx, %rsi /* arg 2 */ 207551bc2a6Smrj TRAP_INSTR 208551bc2a6Smrj ret 209551bc2a6Smrj SET_SIZE(__hypercall2) 210551bc2a6Smrj 211551bc2a6Smrj ENTRY_NP(__hypercall3) 212551bc2a6Smrj ALTENTRY(__hypercall3_int) 213551bc2a6Smrj movl %edi, %eax 214551bc2a6Smrj movq %rsi, %rdi /* arg 1 */ 215551bc2a6Smrj movq %rdx, %rsi /* arg 2 */ 216551bc2a6Smrj movq %rcx, %rdx /* arg 3 */ 217551bc2a6Smrj TRAP_INSTR 218551bc2a6Smrj ret 219551bc2a6Smrj SET_SIZE(__hypercall3) 220551bc2a6Smrj 221551bc2a6Smrj ENTRY_NP(__hypercall4) 222551bc2a6Smrj ALTENTRY(__hypercall4_int) 223551bc2a6Smrj movl %edi, %eax 224551bc2a6Smrj movq %rsi, %rdi /* arg 1 */ 225551bc2a6Smrj movq %rdx, %rsi /* arg 2 */ 226551bc2a6Smrj movq %rcx, %rdx /* arg 3 */ 227551bc2a6Smrj movq %r8, %r10 /* r10 = 4th arg */ 228551bc2a6Smrj TRAP_INSTR 229551bc2a6Smrj ret 230551bc2a6Smrj SET_SIZE(__hypercall4) 231551bc2a6Smrj 232551bc2a6Smrj ENTRY_NP(__hypercall5) 233551bc2a6Smrj ALTENTRY(__hypercall5_int) 234551bc2a6Smrj movl %edi, %eax 235551bc2a6Smrj movq %rsi, %rdi /* arg 1 */ 236551bc2a6Smrj movq %rdx, %rsi /* arg 2 */ 237551bc2a6Smrj movq %rcx, %rdx /* arg 3 */ 238551bc2a6Smrj movq %r8, %r10 /* r10 = 4th arg */ 239551bc2a6Smrj movq %r9, %r8 /* arg 5 */ 240551bc2a6Smrj TRAP_INSTR 241551bc2a6Smrj ret 242551bc2a6Smrj SET_SIZE(__hypercall5) 243551bc2a6Smrj 244551bc2a6Smrj#elif defined(__i386) 245551bc2a6Smrj 246551bc2a6Smrj ENTRY_NP(__hypercall0) 247551bc2a6Smrj ALTENTRY(__hypercall0_int) 248551bc2a6Smrj movl 4(%esp), %eax 249551bc2a6Smrj TRAP_INSTR 250551bc2a6Smrj ret 251551bc2a6Smrj SET_SIZE(__hypercall0) 252551bc2a6Smrj 253551bc2a6Smrj ENTRY_NP(__hypercall1) 254551bc2a6Smrj ALTENTRY(__hypercall1_int) 255551bc2a6Smrj pushl %ebx 256551bc2a6Smrj movl 8(%esp), %eax 257551bc2a6Smrj movl 12(%esp), %ebx 258551bc2a6Smrj TRAP_INSTR 259551bc2a6Smrj popl %ebx 260551bc2a6Smrj ret 261551bc2a6Smrj SET_SIZE(__hypercall1) 262551bc2a6Smrj 263551bc2a6Smrj ENTRY_NP(__hypercall2) 264551bc2a6Smrj ALTENTRY(__hypercall2_int) 265551bc2a6Smrj pushl %ebx 266551bc2a6Smrj movl 8(%esp), %eax 267551bc2a6Smrj movl 12(%esp), %ebx 268551bc2a6Smrj movl 16(%esp), %ecx 269551bc2a6Smrj TRAP_INSTR 270551bc2a6Smrj popl %ebx 271551bc2a6Smrj ret 272551bc2a6Smrj SET_SIZE(__hypercall2) 273551bc2a6Smrj 274551bc2a6Smrj ENTRY_NP(__hypercall3) 275551bc2a6Smrj ALTENTRY(__hypercall3_int) 276551bc2a6Smrj pushl %ebx 277551bc2a6Smrj movl 8(%esp), %eax 278551bc2a6Smrj movl 12(%esp), %ebx 279551bc2a6Smrj movl 16(%esp), %ecx 280551bc2a6Smrj movl 20(%esp), %edx 281551bc2a6Smrj TRAP_INSTR 282551bc2a6Smrj popl %ebx 283551bc2a6Smrj ret 284551bc2a6Smrj SET_SIZE(__hypercall3) 285551bc2a6Smrj 286551bc2a6Smrj ENTRY_NP(__hypercall4) 287551bc2a6Smrj ALTENTRY(__hypercall4_int) 288551bc2a6Smrj pushl %ebx 289551bc2a6Smrj pushl %esi 290551bc2a6Smrj movl 12(%esp), %eax 291551bc2a6Smrj movl 16(%esp), %ebx 292551bc2a6Smrj movl 20(%esp), %ecx 293551bc2a6Smrj movl 24(%esp), %edx 294551bc2a6Smrj movl 28(%esp), %esi 295551bc2a6Smrj TRAP_INSTR 296551bc2a6Smrj popl %esi 297551bc2a6Smrj popl %ebx 298551bc2a6Smrj ret 299551bc2a6Smrj SET_SIZE(__hypercall4) 300551bc2a6Smrj 301551bc2a6Smrj ENTRY_NP(__hypercall5) 302551bc2a6Smrj ALTENTRY(__hypercall5_int) 303551bc2a6Smrj pushl %ebx 304551bc2a6Smrj pushl %esi 305551bc2a6Smrj pushl %edi 306551bc2a6Smrj movl 16(%esp), %eax 307551bc2a6Smrj movl 20(%esp), %ebx 308551bc2a6Smrj movl 24(%esp), %ecx 309551bc2a6Smrj movl 28(%esp), %edx 310551bc2a6Smrj movl 32(%esp), %esi 311551bc2a6Smrj movl 36(%esp), %edi 312551bc2a6Smrj TRAP_INSTR 313551bc2a6Smrj popl %edi 314551bc2a6Smrj popl %esi 315551bc2a6Smrj popl %ebx 316551bc2a6Smrj ret 317551bc2a6Smrj SET_SIZE(__hypercall5) 318551bc2a6Smrj 319551bc2a6Smrj#endif /* __i386 */ 320551bc2a6Smrj 321551bc2a6Smrj#endif /* lint */ 322