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  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2019 Joyent, Inc.
  24  */
  25 
  26 /*
  27  * This is an assembly file that gets #include-ed into the brand-specific
  28  * assembly files (e.g. sn1_brand_asm.s) for Solaris-derived brands.
  29  * We can't make these into functions since in the trap context there's
  30  * no easy place to save the extra parameters that would be required, so
  31  * each brand module needs its own copy of this code.  We #include this and
  32  * use brand-specific #defines to replace the XXX_brand_... definitions.
  33  */
  34 
  35 #include <sys/asm_linkage.h>
  36 #include <sys/privregs.h>
  37 #include <sys/segments.h>
  38 #include "assym.h"
  39 #include "brand_asm.h"
  40 
  41 #ifdef _ASM     /* The remainder of this file is only for assembly files */
  42 
  43 /*
  44  * syscall handler for 32-bit user processes:
  45  * See "64-BIT INTERPOSITION STACK" in brand_asm.h.
  46  * To 'return' to our user-space handler, we just need to place its address
  47  * into %rcx.  The original return address is passed back in SYSCALL_REG.
  48  */
  49 ENTRY(XXX_brand_syscall32_callback)
  50         CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG,
  51             SCR_REG, SCR_REGB);
  52         CALC_TABLE_ADDR(SCR_REG, SPD_HANDLER);
  53         mov     %rcx, SYSCALL_REG; /* save orig return addr in syscall_reg */
  54         mov     SCR_REG, %rcx;  /* place new return addr in %rcx */
  55         mov     %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */
  56         call    x86_md_clear            /* Flush micro-arch state */
  57         mov     V_SSP(SP_REG), SP_REG   /* restore user stack pointer */
  58         jmp     nopop_sys_syscall32_swapgs_sysretl
  59 9:
  60         retq
  61 SET_SIZE(XXX_brand_syscall32_callback)
  62 
  63 /*
  64  * syscall handler for 64-bit user processes:
  65  * See "64-BIT INTERPOSITION STACK" in brand_asm.h.
  66  * To 'return' to our user-space handler, we just need to place its address
  67  * into %rcx.  The original return address is passed back in SYSCALL_REG.
  68  */
  69 ENTRY(XXX_brand_syscall_callback)
  70         CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG,
  71             SCR_REG, SCR_REGB);
  72         CALC_TABLE_ADDR(SCR_REG, SPD_HANDLER);
  73         mov     %rcx, SYSCALL_REG; /* save orig return addr in syscall_reg */
  74         mov     SCR_REG, %rcx;  /* place new return addr in %rcx */
  75         mov     %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */
  76         call    x86_md_clear            /* Flush micro-arch state */
  77         mov     V_SSP(SP_REG), SP_REG   /* restore user stack pointer */
  78         jmp     nopop_sys_syscall_swapgs_sysretq
  79 9:
  80         retq
  81 SET_SIZE(XXX_brand_syscall_callback)
  82 
  83 /*
  84  * See "64-BIT INTERPOSITION STACK" in brand_asm.h.
  85  * To 'return' to our user-space handler, we just need to place its address
  86  * into %rdx.  The original return address is passed back in SYSCALL_REG.
  87  */
  88 ENTRY(XXX_brand_sysenter_callback)
  89         CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG,
  90             SCR_REG, SCR_REGB);
  91         CALC_TABLE_ADDR(SCR_REG, SPD_HANDLER);
  92         mov     %rdx, SYSCALL_REG; /* save orig return addr in syscall_reg */
  93         mov     SCR_REG, %rdx;  /* place new return addr in %rdx */
  94         mov     %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */
  95         mov     V_SSP(SP_REG), SP_REG   /* restore user stack pointer */
  96         jmp     sys_sysenter_swapgs_sysexit
  97 9:
  98         ret
  99 SET_SIZE(XXX_brand_sysenter_callback)
 100 
 101 /*
 102  * To 'return' to our user-space handler we need to update the user's %eip
 103  * pointer in the saved interrupt state on the stack.  The interrupt state was
 104  * pushed onto our stack automatically when the interrupt occured; see the
 105  * comments above.  The original return address is passed back in SYSCALL_REG.
 106  * See "64-BIT INTERPOSITION STACK" and "64-BIT INT STACK" in brand_asm.h.
 107  */
 108 ENTRY(XXX_brand_int91_callback)
 109         CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG,
 110             SCR_REG, SCR_REGB);
 111         CALC_TABLE_ADDR(SCR_REG, SPD_HANDLER); /* new ret addr is in scratch */
 112         mov     SCR_REG, SYSCALL_REG;   /* place new ret addr in syscallreg */
 113         mov     %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */
 114         mov     V_SSP(SP_REG), SP_REG;  /* restore intr stack pointer */
 115         /*CSTYLED*/
 116         xchg    (SP_REG), SYSCALL_REG   /* swap new and orig. return addrs */
 117         jmp     sys_sysint_swapgs_iret
 118 9:
 119         retq
 120 SET_SIZE(XXX_brand_int91_callback)
 121 
 122 #endif  /* _ASM */