s10_brand_asm.s revision e71ca95ca6de23d33b54cb55cefdef30bc7c969b
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * CDDL HEADER START
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek *
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * The contents of this file are subject to the terms of the
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * Common Development and Distribution License (the "License").
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * You may not use this file except in compliance with the License.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek *
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * or http://www.opensolaris.org/os/licensing.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * See the License for the specific language governing permissions
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * and limitations under the License.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek *
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * When distributing Covered Code, include this CDDL HEADER in each
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * If applicable, add the following below this CDDL HEADER, with the
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * fields enclosed by brackets "[]" replaced with your own identifying
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * information: Portions Copyright [yyyy] [name of copyright owner]
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek *
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * CDDL HEADER END
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * Use is subject to license terms.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#if defined(lint)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#include <sys/systm.h>
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#else /* lint */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#include <sys/asm_linkage.h>
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#include <sys/privregs.h>
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#include <sys/segments.h>
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#include <s10_offsets.h>
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#include "assym.h"
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#endif /* lint */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#ifdef lint
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinekvoid
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelineks10_brand_sysenter_callback(void)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek{
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek}
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinekvoid
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelineks10_brand_syscall_callback(void)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek{
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek}
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#if defined(__amd64)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinekvoid
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelineks10_brand_syscall32_callback(void)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek{
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek}
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#endif /* amd64 */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinekvoid
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelineks10_brand_int91_callback(void)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek{
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek}
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#else /* lint */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#if defined(__amd64)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * When our syscall interposition callback entry point gets invoked the
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * stack looks like this:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * --------------------------------------
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * 40 | user %gs |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * 32 | callback pointer |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * 24 | saved stack pointer |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * | 16 | lwp pointer |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * v 8 | user return address (*) |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * 0 | BRAND_CALLBACK()'s return addr |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * --------------------------------------
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * (*) This is actually just the bottom value from the user's
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * stack. syscall puts this in %rcx instead of the stack,
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * so it's just garbage for that entry point.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_COUNT 6
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_END (CLONGSIZE * 6)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_SSP (CLONGSIZE * 3)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_LWP (CLONGSIZE * 2)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_URET_ADDR (CLONGSIZE * 1)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_CB_ADDR (CLONGSIZE * 0)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define SP_REG %rsp
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#else /* !__amd64 */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * When our syscall interposition callback entry point gets invoked the
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * stack looks like this:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * --------------------------------------
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * | 24 | 'scratch space' |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * | 20 | user's %ebx |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * | 16 | user's %gs selector |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * | 12 | kernel's %gs selector |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * | 8 | lwp pointer |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * v 4 | user return address |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * 0 | callback wrapper return addr |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * --------------------------------------
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_COUNT 7
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_END (CLONGSIZE * 7)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_U_GS (CLONGSIZE * 4)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_K_GS (CLONGSIZE * 3)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_LWP (CLONGSIZE * 2)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_URET_ADDR (CLONGSIZE * 1)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_CB_ADDR (CLONGSIZE * 0)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define SP_REG %esp
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#endif /* !__amd64 */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * The following macros allow us to access to variables/parameters passed
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * in on the stack. They take the following variables:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * sp - a register with the current stack pointer value
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * pcnt - the number of words currently pushed onto the stack
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * var - the variable to lookup
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * reg - a register to read the variable into, or
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * a register to write to the variable
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_OFFSET(pcnt, var) \
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek (var + (pcnt * CLONGSIZE))
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define GET_V(sp, pcnt, var, reg) \
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek mov V_OFFSET(pcnt, var)(sp), reg
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define SET_V(sp, pcnt, var, reg) \
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek mov reg, V_OFFSET(pcnt, var)(sp)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define GET_PROCP(sp, pcnt, reg) \
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_V(sp, pcnt, V_LWP, reg) /* get lwp pointer */ ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek mov LWP_PROCP(reg), reg /* get proc pointer */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define GET_P_BRAND_DATA(sp, pcnt, reg) \
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_PROCP(sp, pcnt, reg) ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek mov P_BRAND_DATA(reg), reg /* get p_brand_data */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * Each of the following macros returns to the standard syscall codepath if
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * it detects that this process is not able, or intended, to emulate this
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * system call. They all assume that the routine provides a 'bail-out'
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * label of '9'.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * See if this process has a user-space hdlr registered for it. For the
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * s10 brand, the per-process brand data holds the address of the handler.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * As shown in the stack diagrams below, the callback code leaves that data
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * at these offsets. So check if s10_proc_data_t->spd_handler is non-NULL.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define CHECK_FOR_HANDLER(scr) \
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_P_BRAND_DATA(SP_REG, 1, scr) /* get p_brand_data */ ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek cmp $0, scr ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek je 9f ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek cmp $0, SPD_HANDLER(scr) /* check spd_handler */ ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek je 9f
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * If the system call number is >= 1024, then it is coming from the
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * emulation support library. As such we should handle it natively instead
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * of sending it back to the emulation library.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define CHECK_FOR_NATIVE(reg) \
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek cmp $1024, reg ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek jl 1f ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek sub $1024, reg ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek jmp 9f ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek1:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * Check to see if we want to interpose on this system call. If not, we
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * jump back into the normal syscall path and pretend nothing happened.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define CHECK_FOR_INTERPOSITION(sysr, scr, scr_low) \
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek lea s10_emulation_table, scr ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek mov (scr), scr ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek add sysr, scr ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movb (scr), scr_low ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek cmpb $0, scr_low ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek je 9f
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define CALLBACK_PROLOGUE(call, scr, scr_low) \
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek push scr /* Save scratch register */ ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek CHECK_FOR_HANDLER(scr) ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek CHECK_FOR_NATIVE(call) ;\
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek CHECK_FOR_INTERPOSITION(call, scr, scr_low)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * The callback routines:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#if defined(__amd64)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * syscall handler for 32-bit user processes:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * %rax - syscall number
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * %ecx - the address of the instruction after the syscall
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald JelinekENTRY(s10_brand_syscall32_callback)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek CALLBACK_PROLOGUE(%rax, %r15, %r15b)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movq %rsp, %r15 /* save our stack pointer */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek /*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * Adjust the user's stack so that the 'ret' from our user-space
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * hdlr takes us to the post-syscall instruction instead of to
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * the routine that called the system call.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_V(%r15, 1, V_SSP, %rsp) /* restore user's stack pointer */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek subq $4, %rsp /* save room for the post-syscall addr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movl %ecx, (%rsp) /* Save post-syscall addr on stack */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek /*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * To 'return' to our user-space handler, we just need to copy
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * its address into %rcx.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_P_BRAND_DATA(%r15, 1, %rcx);/* get p_brand_data ptr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movq SPD_HANDLER(%rcx), %rcx /* get p_brand_data->spd_handler ptr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movq (%r15), %r15 /* Restore scratch register */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek jmp nopop_sys_syscall32_swapgs_sysretl
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek9:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek popq %r15
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek retq
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald JelinekSET_SIZE(s10_brand_syscall32_callback)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * syscall handler for 64-bit user processes:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * %rax - syscall number
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * %rcx - user space %rip
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald JelinekENTRY(s10_brand_syscall_callback)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek CALLBACK_PROLOGUE(%rax, %r15, %r15b)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movq %rsp, %r15 /* save our stack pointer */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_V(%r15, 1, V_SSP, %rsp) /* restore user's stack pointer */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek subq $8, %rsp /* save room for the post-syscall addr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movq %rcx, (%rsp) /* Save post-syscall addr on stack */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek /*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * To 'return' to our user-space handler, we just need to copy
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * its address into %rcx.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_P_BRAND_DATA(%r15, 1, %rcx);/* get p_brand_data ptr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movq SPD_HANDLER(%rcx), %rcx /* get p_brand_data->spd_handler ptr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movq (%r15), %r15 /* Restore scratch register */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek jmp nopop_sys_syscall_swapgs_sysretq
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek9:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek popq %r15
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek retq
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald JelinekSET_SIZE(s10_brand_syscall_callback)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * %eax - syscall number
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * %ecx - user space %esp
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * %edx - user space return address
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald JelinekENTRY(s10_brand_sysenter_callback)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek CALLBACK_PROLOGUE(%rax, %r15, %r15b)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek subl $4, %ecx /* Save room for user ret addr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movl %edx, (%rcx) /* Save current return addr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_P_BRAND_DATA(%rsp, 1, %rdx) /* get p_brand_data */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movq SPD_HANDLER(%rdx), %rdx /* get p_brand_data->spd_handler ptr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek popq %r15 /* Restore scratch register */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek jmp sys_sysenter_swapgs_sysexit
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek9:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek popq %r15
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek ret
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald JelinekSET_SIZE(s10_brand_sysenter_callback)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * The saved stack pointer points at the state saved when we took
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * the interrupt:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * --------------------------------------
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * | 32 | user's %ss |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * | 24 | user's %esp |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * | 16 | EFLAGS register |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * v 8 | user's %cs |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * 0 | user's %eip |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * --------------------------------------
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald JelinekENTRY(s10_brand_int91_callback)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek CALLBACK_PROLOGUE(%rax, %r15, %r15b)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek pushq %rax /* Save scratch register */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_P_BRAND_DATA(%rsp, 2, %r15) /* get p_brand_data */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movq SPD_HANDLER(%r15), %r15 /* get s10_proc_data->spd_handler ptr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_V(%rsp, 2, V_SSP, %rax) /* Get saved %esp */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movq %r15, (%rax) /* replace iret target address with hdlr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek /*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * Adjust the caller's stack so we return to the instruction after
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * the syscall on the next 'ret' in userspace - not to the parent
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * routine.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movq 24(%rax), %r15 /* Get user's %esp */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek subq $4, %r15 /* Make room for new ret addr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movq %r15, 24(%rax) /* Replace current with updated %esp */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_V(%rsp, 2, V_URET_ADDR, %rax)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movl %eax, (%r15) /* Put it on the user's stack */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek popq %rax /* Restore scratch register */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek popq %r15 /* Restore scratch register */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movq V_SSP(%rsp), %rsp /* Remove callback stuff from stack */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek jmp sys_sysint_swapgs_iret
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek9:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek popq %r15
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek retq
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald JelinekSET_SIZE(s10_brand_int91_callback)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#else /* !__amd64 */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * lcall handler for 32-bit OS
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * %eax - syscall number
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek *
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * Above the stack contents common to all callbacks is the
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * int/lcall-specific state:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * --------------------------------------
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * | 44 | user's %ss |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * | 40 | user's %esp |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * | 36 | EFLAGS register |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * v 32 | user's %cs |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * 28 | user's %eip |
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * --------------------------------------
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_U_SS (V_END + (CLONGSIZE * 4))
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_U_ESP (V_END + (CLONGSIZE * 3))
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_EFLAGS (V_END + (CLONGSIZE * 2))
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_U_CS (V_END + (CLONGSIZE * 1))
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#define V_U_EIP (V_END + (CLONGSIZE * 0))
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald JelinekENTRY(s10_brand_syscall_callback)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek CALLBACK_PROLOGUE(%eax, %ebx, %bl)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek pushl %eax /* Save scratch register */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek /* replace iret target address with user-space hdlr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_P_BRAND_DATA(%esp, 2, %ebx) /* get p_brand_data ptr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movl SPD_HANDLER(%ebx), %ebx /* get p_brand_data->spd_handler ptr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek SET_V(%esp, 2, V_U_EIP, %ebx) /* set iret target address to hdlr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek /*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * Adjust the caller's stack so we return to the instruction after
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * the syscall on the next 'ret' in userspace - not to the parent
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * routine.
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_V(%esp, 2, V_URET_ADDR, %ebx) /* Get new post-syscall ret addr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_V(%esp, 2, V_U_ESP, %eax) /* Get user %esp */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek subl $4, %eax /* Make room for new ret addr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek SET_V(%esp, 2, V_U_ESP, %eax) /* Updated user %esp */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movl %ebx, (%eax) /* Put new ret addr on user stack */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_V(%esp, 2, V_U_GS, %ebx) /* grab the the user %gs */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movw %bx, %gs /* restore the user %gs */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek popl %eax /* Restore scratch register */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek popl %ebx /* Restore scratch register */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek addl $V_END, %esp /* Remove all callback stuff from stack */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek jmp nopop_sys_rtt_syscall
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek9:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek popl %ebx
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek ret
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald JelinekSET_SIZE(s10_brand_syscall_callback)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek/*
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * %eax - syscall number
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * %ecx - user space %esp
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek * %edx - user space return address
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald JelinekENTRY(s10_brand_sysenter_callback)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek CALLBACK_PROLOGUE(%eax, %ebx, %bl)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek subl $4, %ecx /* Save room for user ret addr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movl %edx, (%ecx) /* Save current return addr */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_P_BRAND_DATA(%esp, 1, %edx) /* get p_brand_data */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movl SPD_HANDLER(%edx), %edx /* get p_brand_data->spd_handler */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek GET_V(%esp, 1, V_U_GS, %ebx) /* grab the the user %gs */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek movw %bx, %gs /* restore the user %gs */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek popl %ebx /* Restore scratch register */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek sysexit
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek9:
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek popl %ebx
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek ret
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald JelinekSET_SIZE(s10_brand_sysenter_callback)
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#endif /* !__amd64 */
e71ca95ca6de23d33b54cb55cefdef30bc7c969bGerald Jelinek#endif /* lint */