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 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/asm_linkage.h> 30 #include <sys/hypervisor.h> 31 #include <sys/privregs.h> 32 #include <sys/segments.h> 33 #include <sys/traptrace.h> 34 #include <sys/trap.h> 35 #include <sys/psw.h> 36 #include <sys/x86_archext.h> 37 #include <sys/asm_misc.h> 38 39 #if !defined(__lint) 40 #include "assym.h" 41 #endif 42 43 #if defined(__lint) 44 45 void 46 xen_failsafe_callback(void) 47 {} 48 49 void 50 xen_callback(void) 51 {} 52 53 #else /* __lint */ 54 55 /* 56 * The stack frame for events is exactly that of an x86 hardware 57 * interrupt. 58 * 59 * The stack frame for a failsafe callback is augmented with saved 60 * values for segment registers: 61 * 62 * i386 63 * %ds, %es, %fs, %gs, %eip, %cs, %eflags [, %oldesp, %oldss ] 64 * 65 * On amd64 the stack frame for events is exactly that of an hardware 66 * interrupt with the addition of rcx and r11. 67 * 68 * The stack frame for a failsafe callback is augmented with saved 69 * values for segment registers: 70 * 71 * amd64 72 * %rcx, %r11, %ds, %es, %fs, %gs, %rip, %cs, %rflags, 73 * [, %oldrsp, %oldss ] 74 * 75 * The hypervisor does this to allow the guest OS to handle returns 76 * to processes which have bad segment registers. 77 * 78 * [See comments in xen/arch/x86/[x86_64,x86_32]/entry.S] 79 * 80 * We will construct a fully fledged 'struct regs' and call trap 81 * with a #gp fault. 82 */ 83 84 #if defined(__amd64) 85 86 ENTRY(xen_failsafe_callback) 87 88 /* 89 * The saved values of rcx and r11 are on the top of the stack. 90 * pop them and let INTR_PUSH save them. We drop ds, es, fs and 91 * gs since the hypervisor will have already loaded these for us. 92 * If any were bad and faulted the hypervisor would have loaded 93 * them with the null selctor. 94 */ 95 XPV_TRAP_POP /* rcx, r11 */ 96 97 /* 98 * XXPV 99 * If the current segregs are provided for us on the stack by 100 * the hypervisor then we should simply move them into their proper 101 * location in the regs struct? 102 */ 103 addq $_CONST(_MUL(4, CLONGSIZE)), %rsp 104 105 /* 106 * XXPV 107 * It would be nice to somehow figure out which selector caused 108 * #gp fault. 109 */ 110 111 pushq $0 /* dummy error */ 112 pushq $T_GPFLT 113 114 INTR_PUSH 115 INTGATE_INIT_KERNEL_FLAGS 116 117 /* 118 * We're here because HYPERVISOR_IRET to userland failed due to a 119 * bad %cs value. Rewrite %cs, %ss and %rip on the stack so trap 120 * will know to handle this with kern_gpfault and kill the currently 121 * running process. 122 */ 123 movq $KCS_SEL, REGOFF_CS(%rsp) 124 movq $KDS_SEL, REGOFF_SS(%rsp) 125 leaq nopop_sys_rtt_syscall(%rip), %rdi 126 movq %rdi, REGOFF_RIP(%rsp) 127 128 TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_EVENT) /* Uses labels 8 and 9 */ 129 TRACE_REGS(%rdi, %rsp, %rbx, %rcx) /* Uses label 9 */ 130 TRACE_STAMP(%rdi) /* Clobbers %eax, %edx, uses 9 */ 131 132 movq %rsp, %rbp 133 134 TRACE_STACK(%rdi) 135 136 movq %rbp, %rdi 137 138 ENABLE_INTR_FLAGS 139 140 movq %rbp, %rdi 141 xorl %esi, %esi 142 movl %gs:CPU_ID, %edx 143 call trap /* trap(rp, addr, cpuid) handles all trap */ 144 jmp _sys_rtt 145 SET_SIZE(xen_failsafe_callback) 146 147 #elif defined(__i386) 148 149 ENTRY(xen_failsafe_callback) 150 151 /* 152 * drop ds, es, fs and gs 153 */ 154 addl $_CONST(_MUL(4, CLONGSIZE)), %esp /* see comment for 64-bit */ 155 156 pushl $0 /* dummy error (see comment for 64-bit) */ 157 pushl $T_GPFLT 158 159 INTR_PUSH 160 INTGATE_INIT_KERNEL_FLAGS /* (set kernel flag values) */ 161 162 /* 163 * The fact were here is because HYPERVISOR_IRET to userland 164 * failed due to a bad %cs value. Rewrite %cs, %ss and %eip 165 * on the stack so trap will know to handle this with 166 * kern_gpfault and kill the currently running process. 167 */ 168 movl $KCS_SEL, REGOFF_CS(%esp) 169 movl $KDS_SEL, REGOFF_SS(%esp) 170 leal nopop_sys_rtt_syscall, %edi 171 movl %edi, REGOFF_EIP(%esp) 172 173 TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_EVENT) /* Uses labels 8 and 9 */ 174 TRACE_REGS(%edi, %esp, %ebx, %ecx) /* Uses label 9 */ 175 TRACE_STAMP(%edi) /* Clobbers %eax, %edx, uses 9 */ 176 177 movl %esp, %ebp 178 179 TRACE_STACK(%edi) 180 181 ENABLE_INTR_FLAGS 182 183 pushl %gs:CPU_ID 184 pushl $0 185 pushl %ebp 186 call trap /* trap(rp, addr, cpuid) handles all traps */ 187 addl $12, %esp 188 jmp _sys_rtt 189 SET_SIZE(xen_failsafe_callback) 190 191 #endif /* __i386 */ 192 193 #if defined(__amd64) 194 195 ENTRY(xen_callback) 196 XPV_TRAP_POP 197 198 pushq $0 /* dummy error */ 199 pushq $T_AST 200 201 INTR_PUSH 202 INTGATE_INIT_KERNEL_FLAGS /* (set kernel flag values) */ 203 204 TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_EVENT) /* Uses labels 8 and 9 */ 205 TRACE_REGS(%rdi, %rsp, %rbx, %rcx) /* Uses label 9 */ 206 TRACE_STAMP(%rdi) /* Clobbers %eax, %edx, uses 9 */ 207 208 movq %rsp, %rbp 209 210 TRACE_STACK(%rdi) 211 212 movq %rdi, %rsi /* rsi = trap trace recode pointer */ 213 movq %rbp, %rdi /* rdi = struct regs pointer */ 214 call xen_callback_handler 215 216 jmp _sys_rtt_ints_disabled 217 /*NOTREACHED*/ 218 219 SET_SIZE(xen_callback) 220 221 #elif defined(__i386) 222 223 ENTRY(xen_callback) 224 pushl $0 /* dummy error */ 225 pushl $T_AST 226 227 INTR_PUSH 228 INTGATE_INIT_KERNEL_FLAGS /* (set kernel flag values) */ 229 230 TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_EVENT) /* Uses labels 8 and 9 */ 231 TRACE_REGS(%edi, %esp, %ebx, %ecx) /* Uses label 9 */ 232 TRACE_STAMP(%edi) /* Clobbers %eax, %edx, uses 9 */ 233 234 movl %esp, %ebp 235 236 TRACE_STACK(%edi) 237 238 pushl %edi /* pass trap trace record pointer */ 239 pushl %ebp /* pass struct regs pointer */ 240 call xen_callback_handler 241 addl $8, %esp 242 243 jmp _sys_rtt_ints_disabled 244 /*NOTREACHED*/ 245 246 SET_SIZE(xen_callback) 247 248 #endif /* __i386 */ 249 #endif /* __lint */