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