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 #include <sys/panic.h>
  39 
  40 #if !defined(__lint)
  41 #include "assym.h"
  42 #endif
  43 
  44 #if defined(__lint)
  45 
  46 void
  47 xpv_panic_callback(void)
  48 {}
  49 
  50 /* ARGSUSED */
  51 void
  52 xpv_panic_setcr3(ulong_t cr3)
  53 {}
  54 
  55 void
  56 xpv_panic_reload_cr3(void)
  57 {}
  58 
  59 void
  60 xpv_resetgs(void)
  61 {}
  62 
  63 #else   /* __lint */
  64 
  65 #if defined(__amd64)
  66         ENTRY_NP(xpv_panic_getcr3)
  67         movq    %cr3, %rax
  68         ret
  69         SET_SIZE(xpv_panic_getcr3)
  70 
  71         ENTRY_NP(xpv_panic_setcr3)
  72         movq    %rdi, %cr3
  73         ret
  74         SET_SIZE(xpv_panic_setcr3)
  75 
  76         ENTRY(xpv_panic_reload_cr3)
  77         movq    %cr3, %rdi
  78         movq    %rdi, %cr3
  79         ret
  80         SET_SIZE(xpv_panic_reload_cr3)
  81 
  82         ENTRY_NP(xpv_panic_prep)
  83         pushq   %rbp
  84         movq    %rsp, %rbp
  85 
  86         subq    $REGSIZE, %rsp
  87         movq    %rax, REGOFF_RAX(%rsp)
  88         movq    %rbx, REGOFF_RBX(%rsp)
  89         movq    %rsp, %rax
  90         addq    $REGSIZE, %rax
  91         movq    (%rax), %rbx
  92         movq    %rbx, REGOFF_RBP(%rsp)
  93         movq    8(%rax), %rbx
  94         movq    %rbx, REGOFF_TRAPNO(%rsp)
  95         movq    16(%rax), %rbx
  96         movq    %rbx, REGOFF_ERR(%rsp)
  97         movq    24(%rax), %rbx
  98         movq    %rbx, REGOFF_RIP(%rsp)
  99         movq    32(%rax), %rbx
 100         movq    %rbx, REGOFF_CS(%rsp)
 101         movq    40(%rax), %rbx
 102         movq    %rbx, REGOFF_RFL(%rsp)
 103         addq    $56, %rax
 104         movq    %rax, REGOFF_RSP(%rsp)
 105         xorl    %eax, %eax
 106         movw    %gs, %ax
 107         mov     %rax, REGOFF_GS(%rsp)
 108         movw    %fs, %ax
 109         mov     %rax, REGOFF_FS(%rsp)
 110         movw    %es, %ax
 111         mov     %rax, REGOFF_ES(%rsp)
 112         movw    %ds, %ax
 113         mov     %rax, REGOFF_DS(%rsp)
 114         movw    %ss, %ax
 115         mov     %rax, REGOFF_SS(%rsp)
 116         movq    %rcx, REGOFF_RCX(%rsp)
 117         movq    %rdx, REGOFF_RDX(%rsp)
 118         movq    %rdi, REGOFF_RDI(%rsp)
 119         movq    %rsi, REGOFF_RSI(%rsp)
 120         movq    %r8, REGOFF_R8(%rsp)
 121         movq    %r9, REGOFF_R9(%rsp)
 122         movq    %r10, REGOFF_R10(%rsp)
 123         movq    %r11, REGOFF_R11(%rsp)
 124         movq    %r12, REGOFF_R12(%rsp)
 125         movq    %r13, REGOFF_R13(%rsp)
 126         movq    %r14, REGOFF_R14(%rsp)
 127         movq    %r15, REGOFF_R15(%rsp)
 128 
 129         movq    %rsp, %rdi
 130         call    xpv_die
 131         SET_SIZE(xpv_panic_prep)
 132 
 133         /*
 134          * Switch to the Solaris panic stack and jump into the Xen panic
 135          * handling code.
 136          */
 137         ENTRY_NP(xpv_panic_hdlr)
 138         leaq    panic_stack(%rip), %rsp
 139         addq    $PANICSTKSIZE, %rsp
 140         call    xpv_do_panic
 141         SET_SIZE(xpv_panic_hdlr)
 142 
 143         ENTRY_NP(xpv_surprise_intr)
 144         pushq   %rbp
 145         movq    %rsp, %rbp
 146         subq    $REGOFF_TRAPNO, %rsp
 147         __SAVE_REGS
 148         movq    %rsp, %rdi
 149         addq    $REGOFF_TRAPNO, %rdi
 150         call    xpv_interrupt
 151         __RESTORE_REGS
 152         addq    $REGOFF_TRAPNO, %rsp
 153         popq    %rbp
 154         iretq
 155         SET_SIZE(xpv_surprise_intr)
 156 
 157         ENTRY_NP(xpv_timer_trap)
 158         pushq   %rbp
 159         movq    %rsp, %rbp
 160         subq    $REGOFF_TRAPNO, %rsp
 161         __SAVE_REGS
 162         movq    %rsp, %rdi
 163         addq    $REGOFF_TRAPNO, %rdi
 164         call    xpv_timer_tick
 165         __RESTORE_REGS
 166         addq    $REGOFF_TRAPNO, %rsp
 167         popq    %rbp
 168         iretq
 169         SET_SIZE(xpv_timer_trap)
 170 
 171 #elif defined(__i386)
 172 
 173         ENTRY_NP(xpv_panic_setcr3)
 174         movl    4(%esp), %eax
 175         movl    %eax, %cr3
 176         ret
 177         SET_SIZE(xpv_panic_setcr3)
 178 
 179         ENTRY(xpv_panic_reload_cr3)
 180         movl    %cr3, %eax
 181         movl    %eax, %cr3
 182         ret
 183         SET_SIZE(xpv_panic_reload_cr3)
 184 
 185         /*
 186          * Stack on entry:
 187          *  +------------+
 188          *  |   EFLAGS  |
 189          *  |   CS      |
 190          *  |   EIP     |
 191          *  |   Error   |
 192          *  |   Trap    |   <---- %esp
 193          *  +------------+
 194          */
 195         ENTRY_NP(xpv_panic_prep)
 196         pushl   %ebp
 197         movl    %esp, %ebp
 198 
 199         subl    $REGSIZE, %esp
 200         movl    %eax, REGOFF_EAX(%esp)
 201         movl    %ebx, REGOFF_EBX(%esp)
 202         movl    %esp, %eax
 203         addl    $REGSIZE, %eax
 204         movl    (%eax), %ebx
 205         movl    %ebx, REGOFF_EBP(%esp)
 206         movl    4(%eax), %ebx
 207         movl    %ebx, REGOFF_TRAPNO(%esp)
 208         movl    8(%eax), %ebx
 209         movl    %ebx, REGOFF_ERR(%esp)
 210         movl    12(%eax), %ebx
 211         movl    %ebx, REGOFF_EIP(%esp)
 212         movl    16(%eax), %ebx
 213         movl    %ebx, REGOFF_CS(%esp)
 214         movl    20(%eax), %ebx
 215         movl    %ebx, REGOFF_EFL(%esp)
 216         addl    $28, %eax
 217         movl    %eax, REGOFF_ESP(%esp)
 218         xorl    %eax, %eax
 219         movw    %gs, %ax
 220         mov     %eax, REGOFF_GS(%esp)
 221         movw    %fs, %ax
 222         mov     %eax, REGOFF_FS(%esp)
 223         movw    %es, %ax
 224         mov     %eax, REGOFF_ES(%esp)
 225         movw    %ds, %ax
 226         mov     %eax, REGOFF_DS(%esp)
 227         movw    %ss, %ax
 228         mov     %eax, REGOFF_SS(%esp)
 229         movl    %ecx, REGOFF_ECX(%esp)
 230         movl    %edx, REGOFF_EDX(%esp)
 231         movl    %edi, REGOFF_EDI(%esp)
 232         movl    %esi, REGOFF_ESI(%esp)
 233         pushl   %esp
 234         call    xpv_die
 235         SET_SIZE(xpv_panic_prep)
 236 
 237         /*
 238          * Switch to the Solaris panic stack and jump into the Xen panic
 239          * handling code.
 240          */
 241         ENTRY_NP(xpv_panic_hdlr)
 242         movl    4(%esp), %eax
 243         lea     panic_stack, %esp
 244         add     $PANICSTKSIZE, %esp
 245         pushl   %eax
 246         call    xpv_do_panic
 247         SET_SIZE(xpv_panic_hdlr)
 248 
 249         ENTRY_NP(xpv_surprise_intr)
 250         push    %ebp
 251         movl    %esp, %ebp
 252         pusha
 253         call    xpv_interrupt
 254         popa
 255         pop     %ebp
 256         iret
 257         SET_SIZE(xpv_surprise_intr)
 258 
 259         ENTRY_NP(xpv_timer_trap)
 260         push    %ebp
 261         movl    %esp, %ebp
 262         pusha
 263         call    xpv_timer_tick
 264         popa
 265         pop     %ebp
 266         iret
 267         SET_SIZE(xpv_timer_trap)
 268 
 269 #endif  /* __i386 */
 270 
 271         ENTRY_NP(xpv_panic_sti)
 272         sti
 273         ret
 274         SET_SIZE(xpv_panic_sti)
 275 
 276         ENTRY_NP(xpv_panic_halt)
 277         sti
 278         hlt
 279         ret
 280         SET_SIZE(xpv_panic_halt)
 281 
 282         ENTRY_NP(xpv_panic_resetgs)
 283         movl    $KGS_SEL, %eax
 284         movw    %ax, %gs
 285         ret
 286         SET_SIZE(xpv_panic_resetgs)
 287 
 288         ENTRY_NP(xpv_invaltrap)
 289         push    $0xbad0
 290         push    $0x0bad
 291         jmp     xpv_panic_prep
 292         SET_SIZE(xpv_invaltrap) 
 293 
 294         ENTRY_NP(xpv_div0trap)
 295         push    $0
 296         push    $T_ZERODIV
 297         jmp     xpv_panic_prep
 298         SET_SIZE(xpv_div0trap)
 299 
 300         ENTRY_NP(xpv_dbgtrap)
 301         push    $0
 302         push    $T_SGLSTP
 303         jmp     xpv_panic_prep
 304         SET_SIZE(xpv_dbgtrap)
 305 
 306         ENTRY_NP(xpv_nmiint)
 307         push    $0
 308         push    $T_NMIFLT
 309         jmp     xpv_panic_prep
 310         SET_SIZE(xpv_nmiint)
 311 
 312         ENTRY_NP(xpv_brktrap)
 313         /* XXX: check for error */
 314         push    $T_BPTFLT
 315         jmp     xpv_panic_prep
 316         SET_SIZE(xpv_brktrap)
 317 
 318         ENTRY_NP(xpv_ovflotrap)
 319         push    $0
 320         push    $T_OVFLW
 321         jmp     xpv_panic_prep
 322         SET_SIZE(xpv_ovflotrap)
 323 
 324         ENTRY_NP(xpv_boundstrap)
 325         push    $0
 326         push    $T_BOUNDFLT
 327         jmp     xpv_panic_prep
 328         SET_SIZE(xpv_boundstrap)
 329 
 330         ENTRY_NP(xpv_invoptrap)
 331         push    $T_ILLINST
 332         jmp     xpv_panic_prep
 333         SET_SIZE(xpv_invoptrap)
 334 
 335         ENTRY_NP(xpv_ndptrap)
 336         push    $0
 337         push    $T_NOEXTFLT
 338         jmp     xpv_panic_prep
 339         SET_SIZE(xpv_ndptrap)
 340 
 341         ENTRY_NP(xpv_syserrtrap)
 342         /* XXX: check for error */
 343         push    $T_DBLFLT
 344         jmp     xpv_panic_prep
 345         SET_SIZE(xpv_syserrtrap)
 346 
 347         ENTRY_NP(xpv_invtsstrap)
 348         push    $T_TSSFLT
 349         jmp     xpv_panic_prep
 350         SET_SIZE(xpv_invtsstrap)
 351 
 352         ENTRY_NP(xpv_segnptrap)
 353         push    $T_SEGFLT
 354         jmp     xpv_panic_prep
 355         SET_SIZE(xpv_segnptrap)
 356 
 357         ENTRY_NP(xpv_stktrap)
 358         push    $T_STKFLT
 359         jmp     xpv_panic_prep
 360         SET_SIZE(xpv_stktrap)
 361 
 362         ENTRY_NP(xpv_gptrap)
 363         push    $T_GPFLT
 364         jmp     xpv_panic_prep
 365         SET_SIZE(xpv_gptrap)
 366 
 367         ENTRY_NP(xpv_pftrap)
 368         push    $T_PGFLT
 369         jmp     xpv_panic_prep
 370         SET_SIZE(xpv_pftrap)
 371 
 372         ENTRY_NP(xpv_ndperr)
 373         push    $0
 374         push    $T_EXTERRFLT
 375         jmp     xpv_panic_prep
 376         SET_SIZE(xpv_ndperr)
 377 
 378         ENTRY_NP(xpv_achktrap)
 379         push    $T_ALIGNMENT
 380         jmp     xpv_panic_prep
 381         SET_SIZE(xpv_achktrap)
 382 
 383         ENTRY_NP(xpv_mcetrap)
 384         push    $0
 385         push    $T_MCE
 386         jmp     xpv_panic_prep
 387         SET_SIZE(xpv_mcetrap)
 388 
 389         ENTRY_NP(xpv_xmtrap)
 390         push    $0
 391         push    $T_SIMDFPE
 392         jmp     xpv_panic_prep
 393         SET_SIZE(xpv_xmtrap)
 394 
 395 #endif  /* __lint */