Mercurial > illumos > illumos-gate
changeset 11685:95082903303d
6887823 brandz on x86 should ignore %gs and simplify brand hooks
author | <gerald.jelinek@sun.com> |
---|---|
date | Thu, 18 Feb 2010 07:03:00 -0700 |
parents | e1daec51bef4 |
children | ee97d7ce1deb |
files | usr/src/uts/common/brand/lx/os/lx_misc.c usr/src/uts/common/brand/lx/sys/lx_brand.h usr/src/uts/i86pc/ml/syscall_asm.s usr/src/uts/i86pc/ml/syscall_asm_amd64.s usr/src/uts/intel/brand/common/brand_asm.h usr/src/uts/intel/brand/lx/lx_brand_asm.s usr/src/uts/intel/brand/sn1/sn1_brand_asm.s usr/src/uts/intel/brand/solaris10/s10_brand_asm.s usr/src/uts/intel/genassym/offsets.in |
diffstat | 9 files changed, 414 insertions(+), 740 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/brand/lx/os/lx_misc.c Thu Feb 18 13:36:37 2010 +0000 +++ b/usr/src/uts/common/brand/lx/os/lx_misc.c Thu Feb 18 07:03:00 2010 -0700 @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/errno.h> #include <sys/systm.h> #include <sys/archsystm.h> @@ -341,24 +339,14 @@ /* * Brand-specific routine to check if given non-Solaris standard segment - * register values should be used as-is or if they should be modified to other - * values. + * register values should be modified to other values. */ /*ARGSUSED*/ greg_t lx_fixsegreg(greg_t sr, model_t datamodel) { - struct lx_lwp_data *lxlwp = ttolxlwp(curthread); - - /* - * If the segreg is the same as the %gs the brand callback was last - * entered with, allow it to be used unmodified. - */ ASSERT(sr == (sr & 0xffff)); - if (sr == (lxlwp->br_ugs & 0xffff)) - return (sr); - /* * Force the SR into the LDT in ring 3 for 32-bit processes. *
--- a/usr/src/uts/common/brand/lx/sys/lx_brand.h Thu Feb 18 13:36:37 2010 +0000 +++ b/usr/src/uts/common/brand/lx/sys/lx_brand.h Thu Feb 18 07:03:00 2010 -0700 @@ -19,15 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _LX_BRAND_H #define _LX_BRAND_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifndef _ASM #include <sys/types.h> #include <sys/cpuvar.h> @@ -199,12 +197,6 @@ */ void *br_clone_args; - /* - * Space to save off userland Linux %gs pointer so we can restore it - * before calling signal handlers. - */ - greg_t br_ugs; - uint_t br_ptrace; /* ptrace is active for this LWP */ } lx_lwp_data_t;
--- a/usr/src/uts/i86pc/ml/syscall_asm.s Thu Feb 18 13:36:37 2010 +0000 +++ b/usr/src/uts/i86pc/ml/syscall_asm.s Thu Feb 18 07:03:00 2010 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -115,28 +115,35 @@ /* * Check if a brand_mach_ops callback is defined for the specified callback_id - * type. If so invoke it with the kernel's %gs value loaded and the following + * type. If so invoke it with the user's %gs value loaded and the following * data on the stack: * -------------------------------------- - * | 'scratch space' | - * | user's %ebx | - * | user's %gs selector | - * | | kernel's %gs selector | - * | | lwp pointer | - * v | user return address | + * | user's %ss | + * | | user's %esp | + * | | EFLAGS register | + * | | user's %cs | + * | | user's %eip (user return address) | + * | | 'scratch space' | + * | | user's %ebx | + * | | user's %gs selector | + * v | lwp pointer | * | callback wrapper return addr | * -------------------------------------- * - * The lx brand (at least) uses each of these fields. * If the brand code returns, we assume that we are meant to execute the * normal system call path. + * + * The interface to the brand callbacks on the 32-bit kernel assumes %ebx + * is available as a scratch register within the callback. If the callback + * returns within the kernel then this macro will restore %ebx. If the + * callback is going to return directly to userland then it should restore + * %ebx before returning to userland. */ #define BRAND_CALLBACK(callback_id) \ subl $4, %esp /* save some scratch space */ ;\ pushl %ebx /* save %ebx to use for scratch */ ;\ pushl %gs /* save the user %gs */ ;\ movl $KGS_SEL, %ebx ;\ - pushl %ebx /* push kernel's %gs */ ;\ movw %bx, %gs /* switch to the kernel's %gs */ ;\ movl %gs:CPU_THREAD, %ebx /* load the thread pointer */ ;\ movl T_LWP(%ebx), %ebx /* load the lwp pointer */ ;\ @@ -147,15 +154,14 @@ movl _CONST(_MUL(callback_id, CPTRSIZE))(%ebx), %ebx ;\ cmpl $0, %ebx ;\ je 1f ;\ - movl %ebx, 16(%esp) /* save callback to scratch */ ;\ - movl 12(%esp), %ebx /* restore %ebx */ ;\ - pushl 20(%esp) /* push the return address */ ;\ - call *20(%esp) /* call callback */ ;\ - addl $4, %esp /* get rid of ret addr */ ;\ -1: movl 8(%esp), %ebx /* grab the the user %gs */ ;\ + movl %ebx, 12(%esp) /* save callback to scratch */ ;\ + movl 4(%esp), %ebx /* grab the user %gs */ ;\ movw %bx, %gs /* restore the user %gs */ ;\ - movl 12(%esp), %ebx /* restore user's %ebx */ ;\ - addl $20, %esp /* restore stack ptr */ + call *12(%esp) /* call callback in scratch */ ;\ +1: movl 4(%esp), %ebx /* restore user %gs (re-do if */ ;\ + movw %bx, %gs /* branch due to no callback) */ ;\ + movl 8(%esp), %ebx /* restore user's %ebx */ ;\ + addl $16, %esp /* restore stack ptr */ #define MSTATE_TRANSITION(from, to) \ pushl $to; \
--- a/usr/src/uts/i86pc/ml/syscall_asm_amd64.s Thu Feb 18 13:36:37 2010 +0000 +++ b/usr/src/uts/i86pc/ml/syscall_asm_amd64.s Thu Feb 18 07:03:00 2010 -0700 @@ -132,7 +132,6 @@ * data on the stack: * * stack: -------------------------------------- - * 40 | user %gs | * 32 | callback pointer | * | 24 | user (or interrupt) stack pointer | * | 16 | lwp pointer | @@ -161,6 +160,12 @@ * BRAND_URET_FROM_REG or BRAND_URET_FROM_INTR_STACK macro. These macros are * used to generate the proper code to get the userland return address for * each syscall entry point. + * + * The interface to the brand callbacks on the 64-bit kernel assumes %r15 + * is available as a scratch register within the callback. If the callback + * returns within the kernel then this macro will restore %r15. If the + * callback is going to return directly to userland then it should restore + * %r15 before returning to userland. */ #define BRAND_URET_FROM_REG(rip_reg) \ pushq rip_reg /* push the return address */ @@ -178,7 +183,7 @@ movq %r15, %gs:CPU_RTMP_R15 /* save %r15 */ ;\ movq %gs:CPU_THREAD, %r15 /* load the thread pointer */ ;\ movq T_STACK(%r15), %rsp /* switch to the kernel stack */ ;\ - subq $24, %rsp /* save space for 3 pointers */ ;\ + subq $16, %rsp /* save space for 2 pointers */ ;\ pushq %r14 /* save %r14 */ ;\ movq %gs:CPU_RTMP_RSP, %r14 ;\ movq %r14, 8(%rsp) /* stash the user stack pointer */ ;\ @@ -193,11 +198,6 @@ je 1f ;\ movq %r15, 16(%rsp) /* save the callback pointer */ ;\ push_userland_ret /* push the return address */ ;\ - SWAPGS /* user gsbase */ ;\ - mov %gs, %r15 /* get %gs */ ;\ - movq %r15, 32(%rsp) /* save %gs on stack */ ;\ - SWAPGS /* kernel gsbase */ ;\ - movq %gs:CPU_RTMP_R15, %r15 /* restore %r15 */ ;\ call *24(%rsp) /* call callback */ ;\ 1: movq %gs:CPU_RTMP_R15, %r15 /* restore %r15 */ ;\ movq %gs:CPU_RTMP_RSP, %rsp /* restore the stack pointer */ @@ -425,18 +425,13 @@ SWAPGS /* kernel gsbase */ XPV_SYSCALL_PROD BRAND_CALLBACK(BRAND_CB_SYSCALL, BRAND_URET_FROM_REG(%rcx)) - SWAPGS /* user gsbase */ + jmp noprod_sys_syscall -#if defined(__xpv) - jmp noprod_sys_syscall -#endif - ALTENTRY(sys_syscall) SWAPGS /* kernel gsbase */ XPV_SYSCALL_PROD noprod_sys_syscall: - movq %r15, %gs:CPU_RTMP_R15 movq %rsp, %gs:CPU_RTMP_RSP @@ -702,20 +697,13 @@ SWAPGS /* kernel gsbase */ XPV_TRAP_POP BRAND_CALLBACK(BRAND_CB_SYSCALL32, BRAND_URET_FROM_REG(%rcx)) - SWAPGS /* user gsbase */ - -#if defined(__xpv) jmp nopop_sys_syscall32 -#endif ALTENTRY(sys_syscall32) SWAPGS /* kernel gsbase */ + XPV_TRAP_POP -#if defined(__xpv) - XPV_TRAP_POP nopop_sys_syscall32: -#endif - movl %esp, %r10d movq %gs:CPU_THREAD, %r15 movq T_STACK(%r15), %rsp @@ -1162,9 +1150,7 @@ XPV_TRAP_POP BRAND_CALLBACK(BRAND_CB_INT80, BRAND_URET_FROM_INTR_STACK()) SWAPGS /* user gsbase */ -#if defined(__xpv) jmp nopop_int80 -#endif ENTRY_NP(sys_int80) /* @@ -1175,10 +1161,8 @@ * to undo the XPV_TRAP_POP and push rcx and r11 back on the stack * because gptrap will pop them again with its own XPV_TRAP_POP. */ -#if defined(__xpv) XPV_TRAP_POP nopop_int80: -#endif subq $2, (%rsp) /* int insn 2-bytes */ pushq $_CONST(_MUL(T_INT80, GATE_DESC_SIZE) + 2) #if defined(__xpv) @@ -1209,20 +1193,13 @@ SWAPGS /* kernel gsbase */ XPV_TRAP_POP BRAND_CALLBACK(BRAND_CB_INT91, BRAND_URET_FROM_INTR_STACK()) - SWAPGS /* user gsbase */ - -#if defined(__xpv) jmp nopop_syscall_int -#endif ALTENTRY(sys_syscall_int) SWAPGS /* kernel gsbase */ + XPV_TRAP_POP -#if defined(__xpv) - XPV_TRAP_POP nopop_syscall_int: -#endif - movq %gs:CPU_THREAD, %r15 movq T_STACK(%r15), %rsp movl %eax, %eax
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/intel/brand/common/brand_asm.h Thu Feb 18 07:03:00 2010 -0700 @@ -0,0 +1,304 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _COMMON_BRAND_ASM_H +#define _COMMON_BRAND_ASM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef lint + +#include <sys/asm_linkage.h> +#include <sys/privregs.h> +#include <sys/segments.h> +#include "assym.h" + +#endif /* lint */ + +#ifdef _ASM /* The remainder of this file is only for assembly files */ + +#if defined(__amd64) +/* + * Common to all 64-bit callbacks: + * + * We're running on the kernel's %gs. + * + * We return directly to userland, bypassing the _update_sregs logic, so + * the routine must NOT do anything that could cause a context switch. + * + * %rax - syscall number + * + * When called, all general registers, except for %r15, are as they were when + * the user process made the system call. %r15 is available to the callback as + * a scratch register. If the callback returns to the kernel path, %r15 does + * not have to be restored to the user value. If the callback returns to the + * userlevel emulation code, the callback should restore %r15 if the emulation + * depends on the original userlevel value. + * + * 64-BIT INTERPOSITION STACK + * On entry to the callback the stack looks like this: + * -------------------------------------- + * 32 | callback pointer | + * 24 | saved stack pointer | + * | 16 | lwp pointer | + * v 8 | user return address | + * 0 | BRAND_CALLBACK()'s return addr | + * -------------------------------------- + */ + +#define V_COUNT 5 +#define V_END (CLONGSIZE * 5) +#define V_SSP (CLONGSIZE * 3) +#define V_LWP (CLONGSIZE * 2) +#define V_URET_ADDR (CLONGSIZE * 1) +#define V_CB_ADDR (CLONGSIZE * 0) + +#define SP_REG %rsp +#define SCR_REG %r15 +#define SCR_REGB %r15b +#define SYSCALL_REG %rax + +/* + * 64-BIT INT STACK + * For int callbacks (e.g. int91) the saved stack pointer (V_SSP) points at + * the state saved when we took the interrupt: + * -------------------------------------- + * | 32 | user's %ss | + * | 24 | user's %esp | + * | 16 | EFLAGS register | + * v 8 | user's %cs | + * 0 | user's %eip (user return address) | + * -------------------------------------- + */ +#define V_U_EIP (CLONGSIZE * 0) + +#else /* !__amd64 */ +/* + * 32-BIT INTERPOSITION STACK + * When our syscall interposition callback entry point gets invoked the + * stack looks like this: + * -------------------------------------- + * | 16 | 'scratch space' | + * | 12 | user's %ebx | + * | 8 | user's %gs selector | + * v 4 | lwp pointer | + * 0 | callback wrapper return addr | + * -------------------------------------- + */ + +#define V_COUNT 5 +#define V_END (CLONGSIZE * 5) +#define V_U_EBX (CLONGSIZE * 3) +#define V_LWP (CLONGSIZE * 1) +#define V_CB_ADDR (CLONGSIZE * 0) + +#define SP_REG %esp +#define SCR_REG %ebx +#define SCR_REGB %bl +#define SYSCALL_REG %eax + +/* + * 32-BIT INT STACK + * For the lcall handler for 32-bit OS (i.e. xxx_brand_syscall_callback) + * above the stack contents common to all callbacks is the int/lcall-specific + * state: + * -------------------------------------- + * | 36 | user's %ss | + * | 32 | user's %esp | + * | 28 | EFLAGS register | + * v 24 | user's %cs | + * 20 | user's %eip (user return address) | + * -------------------------------------- + */ +#define V_U_EIP (V_END + (CLONGSIZE * 0)) + +#endif /* !__amd64 */ + +/* + * The following macros allow us to access to variables/parameters passed + * in on the stack. They take the following variables: + * sp - a register with the current stack pointer value + * pcnt - the number of words currently pushed onto the stack + * var - the variable to lookup + * reg - a register to read the variable into, or + * a register to write to the variable + */ +#define V_OFFSET(pcnt, var) \ + (var + (pcnt * CLONGSIZE)) + +#define GET_V(sp, pcnt, var, reg) \ + mov V_OFFSET(pcnt, var)(sp), reg + +#define SET_V(sp, pcnt, var, reg) \ + mov reg, V_OFFSET(pcnt, var)(sp) + +#define GET_PROCP(sp, pcnt, reg) \ + GET_V(sp, pcnt, V_LWP, reg); /* get lwp pointer */ \ + mov LWP_PROCP(reg), reg /* get proc pointer */ + +#define GET_P_BRAND_DATA(sp, pcnt, reg) \ + GET_PROCP(sp, pcnt, reg); \ + mov P_BRAND_DATA(reg), reg /* get p_brand_data */ + +/* + * Each of the following macros returns to the standard syscall codepath if + * it detects that this process is not able, or intended, to emulate this + * system call. They all assume that the routine provides a 'bail-out' + * label of '9'. + */ + +/* + * See if this process has a user-space handler registered for it. For the + * brand, the per-process brand data holds the address of the handler. + * As shown in the stack diagrams above, the callback code leaves the lwp + * pointer at well-defined offsets, so check if proc_data_t->X_handler is + * non-NULL. For each brand, the handler parameter refers to the brand's + * user-space handler variable name. + */ +#define CHECK_FOR_HANDLER(scr, handler) \ + GET_P_BRAND_DATA(SP_REG, 0, scr); /* get p_brand_data */ \ + cmp $0, scr; \ + je 9f; \ + cmp $0, handler(scr); /* check handler */ \ + je 9f + +/* + * If the system call number is >= 1024, then it is coming from the + * emulation support library. As such we should handle it natively instead + * of sending it back to the emulation library. + */ +#define CHECK_FOR_NATIVE(reg) \ + cmp $1024, reg; \ + jl 1f; \ + sub $1024, reg; \ + jmp 9f; \ +1: + +/* + * Check to see if we want to interpose on this system call. If not, we + * jump back into the normal syscall path and pretend nothing happened. + * This macro is usable for brands which have the same number of syscalls + * as the base OS. + */ +#define CHECK_FOR_INTERPOSITION(emul_table, call, scr, scr_low) \ + cmp $NSYSCALL, call; /* is 0 <= syscall <= MAX? */ \ + ja 9f; /* no, take normal ret path */ \ + lea emul_table, scr; \ + /*CSTYLED*/ \ + mov (scr), scr; \ + add call, scr; \ + /*CSTYLED*/ \ + movb (scr), scr_low; \ + cmpb $0, scr_low; \ + je 9f /* no, take normal ret path */ + +#define CALLBACK_PROLOGUE(emul_table, handler, call, scr, scr_low) \ + CHECK_FOR_HANDLER(scr, handler); \ + CHECK_FOR_NATIVE(call); \ + CHECK_FOR_INTERPOSITION(emul_table, call, scr, scr_low) + +/* + * Rather than returning to the instruction after the syscall, we need to + * transfer control into the brand library's handler table at + * table_addr + (16 * syscall_num), thus encoding the system call number in the + * instruction pointer. The CALC_TABLE_ADDR macro performs that calculation. + * + * This macro assumes the syscall number is in SYSCALL_REG and it clobbers + * that register. It leaves the calculated handler table return address in + * the scratch reg. + */ +#define CALC_TABLE_ADDR(scr, handler) \ + GET_P_BRAND_DATA(SP_REG, 0, scr); /* get p_brand_data ptr */ \ + mov handler(scr), scr; /* get p_brand_data->XX_handler */ \ + shl $4, SYSCALL_REG; /* syscall_num * 16 */ \ + add SYSCALL_REG, scr /* leave return addr in scr reg. */ + +#if defined(__amd64) + +/* + * To 'return' to our user-space handler, we just need to place its address + * into 'retreg'. The original return address is passed back in SYSCALL_REG. + */ +#define SYSCALL_EMUL(emul_table, handler, retreg) \ + CALLBACK_PROLOGUE(emul_table, handler, SYSCALL_REG, SCR_REG, SCR_REGB);\ + CALC_TABLE_ADDR(SCR_REG, handler); \ + mov retreg, SYSCALL_REG; /* save orig return addr in syscall_reg */\ + mov SCR_REG, retreg; /* place new return addr in retreg */\ + mov %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */\ + mov V_SSP(SP_REG), SP_REG /* restore user stack pointer */ + +/* + * To 'return' to our user-space handler we need to update the user's %eip + * pointer in the saved interrupt state on the stack. The interrupt state was + * pushed onto our stack automatically when the interrupt occured; see the + * comments above. The original return address is passed back in SYSCALL_REG. + */ +#define INT_EMUL(emul_table, handler) \ + CALLBACK_PROLOGUE(emul_table, handler, SYSCALL_REG, SCR_REG, SCR_REGB);\ + CALC_TABLE_ADDR(SCR_REG, handler); /* new return addr is in scratch */ \ + mov SCR_REG, SYSCALL_REG; /* place new ret addr in syscallreg */ \ + mov %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */ \ + mov V_SSP(SP_REG), SP_REG; /* restore intr stack pointer */ \ + /*CSTYLED*/ \ + xchg (SP_REG), SYSCALL_REG /* swap new and orig. return addrs */ + +#else /* !__amd64 */ + +/* + * To 'return' to our user-space handler, we just need to place its address + * into 'retreg'. The original return address is passed back in SYSCALL_REG. + */ +#define SYSCALL_EMUL(emul_table, handler, retreg) \ + CALLBACK_PROLOGUE(emul_table, handler, SYSCALL_REG, SCR_REG, SCR_REGB);\ + mov retreg, SCR_REG; /* save orig return addr in scr reg */ \ + CALC_TABLE_ADDR(retreg, handler); /* new return addr is in retreg */ \ + mov SCR_REG, SYSCALL_REG; /* save orig return addr in %eax */ \ + GET_V(SP_REG, 0, V_U_EBX, SCR_REG) /* restore scratch register */ + +/* + * To 'return' to our user-space handler, we need to replace the + * iret target address. + * The original return address is passed back in %eax. + */ +#define INT_EMUL(emul_table, handler) \ + CALLBACK_PROLOGUE(emul_table, handler, SYSCALL_REG, SCR_REG, SCR_REGB);\ + CALC_TABLE_ADDR(SCR_REG, handler); /* new return addr is in scratch */ \ + mov SCR_REG, SYSCALL_REG; /* place new ret addr in syscallreg */ \ + GET_V(SP_REG, 0, V_U_EBX, SCR_REG); /* restore scratch register */ \ + add $V_END, SP_REG; /* restore intr stack pointer */ \ + /*CSTYLED*/ \ + xchg (SP_REG), SYSCALL_REG /* swap new and orig. return addrs */ + +#endif /* !__amd64 */ + +#endif /* _ASM */ + +#ifdef __cplusplus +} +#endif + +#endif /* _COMMON_BRAND_ASM_H */
--- a/usr/src/uts/intel/brand/lx/lx_brand_asm.s Thu Feb 18 13:36:37 2010 +0000 +++ b/usr/src/uts/intel/brand/lx/lx_brand_asm.s Thu Feb 18 07:03:00 2010 -0700 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -30,11 +30,8 @@ #else /* __lint */ -#include <sys/asm_linkage.h> -#include <sys/privregs.h> -#include <sys/segments.h> -#include "assym.h" #include "genassym.h" +#include "../common/brand_asm.h" #endif /* __lint */ @@ -48,70 +45,29 @@ #else /* __lint */ #if defined(__amd64) - /* - * lx brand callback for the int $0x80 trap handler. - * - * We're running on the kernel's %gs. - * - * We return directly to userland, bypassing the _update_sregs logic, so - * this routine must NOT do anything that could cause a context switch. - * - * %rax - syscall number - * - * When called, all general registers are as they were when - * the user process made the system call. The %gs register has the - * kernel value. The stack looks like this: - * - * -------------------------------------- - * 40 | user %gs | - * 32 | callback pointer | - * 24 | saved stack pointer | - * | 16 | lwp pointer | - * v 8 | user return address (*) | - * 0 | caller's return addr (sys_int80) | - * ------------------------------------- - */ - ENTRY(lx_brand_int80_callback) - movq 16(%rsp), %r15 /* grab the lwp */ - movq LWP_PROCP(%r15), %r15 /* grab the proc pointer */ - pushq %r15 /* push the proc pointer */ + +/* + * See "64-BIT INTERPOSITION STACK" in brand_asm.h. + */ +ENTRY(lx_brand_int80_callback) + GET_PROCP(SP_REG, 0, %r15) movq P_ZONE(%r15), %r15 /* grab the zone pointer */ + /* grab the 'max syscall num' for this process from 'zone brand data' */ movq ZONE_BRAND_DATA(%r15), %r15 /* grab the zone brand ptr */ - pushq %rax /* save the syscall num */ - movl LXZD_MAX_SYSCALL(%r15), %eax /* load the 'max sysnum' word */ - xchgq (%rsp), %rax /* swap %rax and stack value */ - movq 32(%rsp), %r15 /* re-load the lwp pointer */ - movq LWP_BRAND(%r15), %r15 /* grab the lwp brand data */ - pushq %rax /* save %rax on stack */ - movq 64(%rsp), %rax /* get user %gs */ - mov %eax, BR_UGS(%r15) /* save user %gs */ - popq %rax /* restore %rax from stack */ - - /* grab the 'max syscall num' for this process from 'zone brand data' */ - cmpq (%rsp), %rax /* is 0 <= syscall <= MAX? */ + movl LXZD_MAX_SYSCALL(%r15), %r15d /* get the 'max sysnum' word */ + cmpq %r15, %rax /* is 0 <= syscall <= MAX? */ jbe 0f /* yes, syscall is OK */ xorl %eax, %eax /* no, zero syscall number */ 0: - movq 8(%rsp), %r15 /* get the proc pointer */ - movq P_BRAND_DATA(%r15), %r15 /* grab the proc brand data */ .lx_brand_int80_patch_point: jmp .lx_brand_int80_notrace .lx_brand_int80_notrace: - movq L_HANDLER(%r15), %r15 /* load the base address */ - + CALC_TABLE_ADDR(%r15, L_HANDLER) 1: - /* - * Rather than returning to the instruction after the int 80, we - * transfer control into the brand library's handler table at - * table_addr + (16 * syscall_num) thus encoding the system - * call number in the instruction pointer. The original return address - * is passed in %eax. - */ - shlq $4, %rax - addq %r15, %rax - movq 40(%rsp), %rsp /* restore user stack pointer */ + movq %r15, %rax + GET_V(%rsp, 0, V_SSP, %rsp) /* restore intr. stack pointer */ xchgq (%rsp), %rax /* swap %rax and return addr */ jmp sys_sysint_swapgs_iret @@ -120,100 +76,68 @@ * If tracing is active, we vector to an alternate trace-enabling * handler table instead. */ - movq L_TRACEHANDLER(%r15), %r15 /* load trace handler address */ + CALC_TABLE_ADDR(%r15, L_TRACEHANDLER) jmp 1b - SET_SIZE(lx_brand_int80_callback) +SET_SIZE(lx_brand_int80_callback) #define PATCH_POINT _CONST(.lx_brand_int80_patch_point + 1) #define PATCH_VAL _CONST(.lx_brand_int80_trace - .lx_brand_int80_notrace) - ENTRY(lx_brand_int80_enable) +ENTRY(lx_brand_int80_enable) movl $1, lx_systrace_brand_enabled(%rip) movq $PATCH_POINT, %r8 movb $PATCH_VAL, (%r8) ret - SET_SIZE(lx_brand_int80_enable) +SET_SIZE(lx_brand_int80_enable) - ENTRY(lx_brand_int80_disable) +ENTRY(lx_brand_int80_disable) movq $PATCH_POINT, %r8 movb $0, (%r8) movl $0, lx_systrace_brand_enabled(%rip) ret - SET_SIZE(lx_brand_int80_disable) +SET_SIZE(lx_brand_int80_disable) #elif defined(__i386) - /* - * %eax - syscall number - * - * When called, all general registers are as they were when - * the user process made the system call. The %gs register has the - * kernel value. The stack looks like this: - * - * -------------------------------------- - * | 44 | user's %ss | - * | 40 | user's %esp | - * | 36 | EFLAGS register | - * | 32 | user's %cs | - * | 28 | user's %eip | - * | 24 | 'scratch space' | - * | 20 | user's %ebx | - * | 16 | user's %gs selector | - * | 12 | kernel's %gs selector | - * | 8 | lwp pointer | - * v 4 | user return address | - * 0 | callback wrapper return addr | - * ------------------------------------- - */ - ENTRY(lx_brand_int80_callback) - pushl %ebx /* save for use as scratch */ - movl 12(%esp), %ebx /* grab the lwp pointer */ - movl LWP_PROCP(%ebx), %ebx /* grab the proc pointer */ - pushl %ebx /* push the proc pointer */ + +/* + * See "32-BIT INTERPOSITION STACK" in brand_asm.h. + */ +ENTRY(lx_brand_int80_callback) + GET_PROCP(SP_REG, 0, %ebx) movl P_ZONE(%ebx), %ebx /* grab the zone pointer */ + /* grab the 'max syscall num' for this process from 'zone brand data' */ movl ZONE_BRAND_DATA(%ebx), %ebx /* grab the zone brand data */ - pushl LXZD_MAX_SYSCALL(%ebx) /* push the max sysnum */ - movl 28(%esp), %ebx /* grab the the user %gs */ - movw %bx, %gs /* restore the user %gs */ - movl 20(%esp), %ebx /* re-load the lwp pointer */ - movl LWP_BRAND(%ebx), %ebx /* grab the lwp brand data */ - movw %gs, BR_UGS(%ebx) /* save user %gs */ + movl LXZD_MAX_SYSCALL(%ebx), %ebx /* get the max sysnum */ - /* grab the 'max syscall num' for this process from 'zone brand data' */ - cmpl (%esp), %eax /* is 0 <= syscall <= MAX? */ + cmpl %ebx, %eax /* is 0 <= syscall <= MAX? */ jbe 0f /* yes, syscall is OK */ xorl %eax, %eax /* no, zero syscall number */ 0: - movl 4(%esp), %ebx /* get the proc pointer */ - movl P_BRAND_DATA(%ebx), %ebx /* grab the proc brand data */ .lx_brand_int80_patch_point: jmp .lx_brand_int80_notrace .lx_brand_int80_notrace: - movl L_HANDLER(%ebx), %ebx /* load the base address */ + CALC_TABLE_ADDR(%ebx, L_HANDLER) 1: - /* - * See the corresponding comment in the amd64 version above. - */ - shll $4, %eax - addl %ebx, %eax - movl 8(%esp), %ebx /* restore %ebx */ - addl $40, %esp - xchgl (%esp), %eax /* swap %eax and return addr */ + movl %ebx, %eax + GET_V(%esp, 0, V_U_EBX, %ebx) /* restore scratch register */ + addl $V_END, %esp /* restore intr. stack ptr */ + xchgl (%esp), %eax /* swap new and orig. return addrs */ jmp nopop_sys_rtt_syscall .lx_brand_int80_trace: - movl L_TRACEHANDLER(%ebx), %ebx /* load trace handler address */ + CALC_TABLE_ADDR(%ebx, L_TRACEHANDLER) jmp 1b - SET_SIZE(lx_brand_int80_callback) +SET_SIZE(lx_brand_int80_callback) #define PATCH_POINT _CONST(.lx_brand_int80_patch_point + 1) #define PATCH_VAL _CONST(.lx_brand_int80_trace - .lx_brand_int80_notrace) - ENTRY(lx_brand_int80_enable) +ENTRY(lx_brand_int80_enable) pushl %ebx pushl %eax movl $1, lx_systrace_brand_enabled @@ -223,16 +147,16 @@ popl %eax popl %ebx ret - SET_SIZE(lx_brand_int80_enable) +SET_SIZE(lx_brand_int80_enable) - ENTRY(lx_brand_int80_disable) +ENTRY(lx_brand_int80_disable) pushl %ebx movl $PATCH_POINT, %ebx movb $0, (%ebx) movl $0, lx_systrace_brand_enabled popl %ebx ret - SET_SIZE(lx_brand_int80_disable) +SET_SIZE(lx_brand_int80_disable) #endif /* __i386 */ #endif /* __lint */
--- a/usr/src/uts/intel/brand/sn1/sn1_brand_asm.s Thu Feb 18 13:36:37 2010 +0000 +++ b/usr/src/uts/intel/brand/sn1/sn1_brand_asm.s Thu Feb 18 07:03:00 2010 -0700 @@ -29,11 +29,8 @@ #else /* lint */ -#include <sys/asm_linkage.h> -#include <sys/privregs.h> -#include <sys/segments.h> #include <sn1_offsets.h> -#include "assym.h" +#include "../common/brand_asm.h" #endif /* lint */ @@ -64,325 +61,72 @@ #else /* lint */ #if defined(__amd64) -/* - * When our syscall interposition callback entry point gets invoked the - * stack looks like this: - * -------------------------------------- - * 40 | user %gs | - * 32 | callback pointer | - * 24 | saved stack pointer | - * | 16 | lwp pointer | - * v 8 | user return address | - * 0 | BRAND_CALLBACK()'s return addr | - * -------------------------------------- - */ - -#define V_COUNT 6 -#define V_END (CLONGSIZE * 6) -#define V_SSP (CLONGSIZE * 3) -#define V_LWP (CLONGSIZE * 2) -#define V_URET_ADDR (CLONGSIZE * 1) -#define V_CB_ADDR (CLONGSIZE * 0) - -#define SP_REG %rsp -#define SYSCALL_REG %rax - -#else /* !__amd64 */ -/* - * When our syscall interposition callback entry point gets invoked the - * stack looks like this: - * -------------------------------------- - * | 24 | 'scratch space' | - * | 20 | user's %ebx | - * | 16 | user's %gs selector | - * | 12 | kernel's %gs selector | - * | 8 | lwp pointer | - * v 4 | user return address | - * 0 | callback wrapper return addr | - * -------------------------------------- - */ - -#define V_COUNT 7 -#define V_END (CLONGSIZE * 7) -#define V_U_GS (CLONGSIZE * 4) -#define V_K_GS (CLONGSIZE * 3) -#define V_LWP (CLONGSIZE * 2) -#define V_URET_ADDR (CLONGSIZE * 1) -#define V_CB_ADDR (CLONGSIZE * 0) - -#define SP_REG %esp -#define SYSCALL_REG %eax - -#endif /* !__amd64 */ - -/* - * The following macros allow us to access to variables/parameters passed - * in on the stack. They take the following variables: - * sp - a register with the current stack pointer value - * pcnt - the number of words currently pushed onto the stack - * var - the variable to lookup - * reg - a register to read the variable into, or - * a register to write to the variable - */ -#define V_OFFSET(pcnt, var) \ - (var + (pcnt * CLONGSIZE)) - -#define GET_V(sp, pcnt, var, reg) \ - mov V_OFFSET(pcnt, var)(sp), reg - -#define SET_V(sp, pcnt, var, reg) \ - mov reg, V_OFFSET(pcnt, var)(sp) - -#define GET_PROCP(sp, pcnt, reg) \ - GET_V(sp, pcnt, V_LWP, reg) /* get lwp pointer */ ;\ - mov LWP_PROCP(reg), reg /* get proc pointer */ - -#define GET_P_BRAND_DATA(sp, pcnt, reg) \ - GET_PROCP(sp, pcnt, reg) ;\ - mov P_BRAND_DATA(reg), reg /* get p_brand_data */ - -/* - * Each of the following macros returns to the standard syscall codepath if - * it detects that this process is not able, or intended, to emulate this - * system call. They all assume that the routine provides a 'bail-out' - * label of '9'. - */ - -/* - * See if this process has a user-space hdlr registered for it. For the - * sn1 brand, the per-process brand data holds the address of the handler. - * As shown in the stack diagrams below, the callback code leaves that data - * at these offsets. So check if sn1_proc_data_t->spd_handler is non-NULL. - */ -#define CHECK_FOR_HANDLER(scr) \ - GET_P_BRAND_DATA(SP_REG, 1, scr) /* get p_brand_data */ ;\ - cmp $0, scr ;\ - je 9f ;\ - cmp $0, SPD_HANDLER(scr) /* check spd_handler */ ;\ - je 9f - -/* - * If the system call number is >= 1024, then it is coming from the - * emulation support library. As such we should handle it natively instead - * of sending it back to the emulation library. - */ -#define CHECK_FOR_NATIVE(reg) \ - cmp $1024, reg ;\ - jl 1f ;\ - sub $1024, reg ;\ - jmp 9f ;\ -1: - -/* - * Check to see if we want to interpose on this system call. If not, we - * jump back into the normal syscall path and pretend nothing happened. - */ -#define CHECK_FOR_INTERPOSITION(sysr, scr, scr_low) \ - cmp $NSYSCALL, sysr /* is 0 <= syscall <= MAX? */ ;\ - ja 9f /* no, take normal err path */ ;\ - lea sn1_emulation_table, scr ;\ - mov (scr), scr ;\ - add sysr, scr ;\ - movb (scr), scr_low ;\ - cmpb $0, scr_low ;\ - je 9f - -#define CALLBACK_PROLOGUE(call, scr, scr_low) \ - push scr /* Save scratch register */ ;\ - CHECK_FOR_HANDLER(scr) ;\ - CHECK_FOR_NATIVE(call) ;\ - CHECK_FOR_INTERPOSITION(call, scr, scr_low) - -/* - * Rather than returning to the instruction after the syscall, we need to - * transfer control into the brand library's handler table at - * table_addr + (16 * syscall_num), thus encoding the system call number in the - * instruction pointer. The CALC_TABLE_ADDR macro performs that calculation. - * - * This macro assumes the syscall number is in SYSCALL_REG and it clobbers - * that register. It leaves the calculated handler table return address in - * the scratch reg. - */ -#define CALC_TABLE_ADDR(scr) \ - GET_P_BRAND_DATA(SP_REG, 1, scr) /* get p_brand_data ptr */ ;\ - mov SPD_HANDLER(scr), scr /* get p_brand_data->spd_handler */ ;\ - shl $4, SYSCALL_REG /* syscall_num * 16 */ ;\ - add SYSCALL_REG, scr /* leave return addr in scr reg. */ - -/* - * To 'return' to our user-space handler, we just need to place its address - * into 'retreg'. The original return address is passed in SYSCALL_REG. - */ -#define SETUP_RET_DATA(scr, retreg) \ - CALC_TABLE_ADDR(scr) ;\ - mov retreg, SYSCALL_REG /* save orig return addr in %rax */ ;\ - mov scr, retreg /* save new return addr in ret reg */ ;\ - pop scr /* restore scratch register */ - -/* - * The callback routines: - */ - -#if defined(__amd64) /* * syscall handler for 32-bit user processes: - * %rax - syscall number - * %ecx - the address of the instruction after the syscall + * %rcx - the address of the instruction after the syscall + * See "64-BIT INTERPOSITION STACK" in brand_asm.h. */ ENTRY(sn1_brand_syscall32_callback) - - CALLBACK_PROLOGUE(%rax, %r15, %r15b) - - SETUP_RET_DATA(%r15, %rcx) - GET_V(%rsp, 0, V_SSP, %rsp) /* restore user's stack pointer */ + SYSCALL_EMUL(sn1_emulation_table, SPD_HANDLER, %rcx) jmp nopop_sys_syscall32_swapgs_sysretl 9: - popq %r15 retq SET_SIZE(sn1_brand_syscall32_callback) /* * syscall handler for 64-bit user processes: - * %rax - syscall number - * %rcx - user space %rip + * %rcx - the address of the instruction after the syscall + * See "64-BIT INTERPOSITION STACK" in brand_asm.h. */ ENTRY(sn1_brand_syscall_callback) - - CALLBACK_PROLOGUE(%rax, %r15, %r15b) - - SETUP_RET_DATA(%r15, %rcx) - GET_V(%rsp, 0, V_SSP, %rsp) /* restore user's stack pointer */ + SYSCALL_EMUL(sn1_emulation_table, SPD_HANDLER, %rcx) jmp nopop_sys_syscall_swapgs_sysretq 9: - popq %r15 retq - SET_SIZE(sn1_brand_syscall_callback) /* - * %eax - syscall number - * %ecx - user space %esp - * %edx - user space return address + * %rdx - user space return address + * See "64-BIT INTERPOSITION STACK" in brand_asm.h. */ ENTRY(sn1_brand_sysenter_callback) - - CALLBACK_PROLOGUE(%rax, %r15, %r15b) - - SETUP_RET_DATA(%r15, %rdx) + SYSCALL_EMUL(sn1_emulation_table, SPD_HANDLER, %rdx) jmp sys_sysenter_swapgs_sysexit 9: - popq %r15 ret SET_SIZE(sn1_brand_sysenter_callback) /* - * The saved stack pointer points at the state saved when we took - * the interrupt: - * -------------------------------------- - * | 32 | user's %ss | - * | 24 | user's %esp | - * | 16 | EFLAGS register | - * v 8 | user's %cs | - * 0 | user's %eip | - * -------------------------------------- + * See "64-BIT INTERPOSITION STACK" and "64-BIT INT STACK" in brand_asm.h. */ -#define V_U_EIP (CLONGSIZE * 0) - ENTRY(sn1_brand_int91_callback) - - CALLBACK_PROLOGUE(%rax, %r15, %r15b) - - /* - * To 'return' to our user-space handler we need to update the user's - * %eip pointer in the saved interrupt state. The interrupt state was - * pushed onto our stack automatically when the interrupt occured; see - * the comments above. The original return address is passed in %rax. - */ - CALC_TABLE_ADDR(%r15) - GET_V(%rsp, 1, V_SSP, %rax) /* get saved stack pointer */ - SET_V(%rax, 0, V_U_EIP, %r15) /* save new return addr in %eip */ - GET_V(%rsp, 1, V_URET_ADDR, %rax) /* %rax has orig. return addr. */ - - popq %r15 /* Restore scratch register */ - movq V_SSP(%rsp), %rsp /* Remove callback stuff from stack */ + INT_EMUL(sn1_emulation_table, SPD_HANDLER) jmp sys_sysint_swapgs_iret 9: - popq %r15 retq SET_SIZE(sn1_brand_int91_callback) #else /* !__amd64 */ /* - * lcall handler for 32-bit OS - * %eax - syscall number - * - * Above the stack contents common to all callbacks is the - * int/lcall-specific state: - * -------------------------------------- - * | 44 | user's %ss | - * | 40 | user's %esp | - * | 36 | EFLAGS register | - * v 32 | user's %cs | - * 28 | user's %eip | - * -------------------------------------- + * See "32-BIT INTERPOSITION STACK" and "32-BIT INT STACK" in brand_asm.h. */ -#define V_U_SS (V_END + (CLONGSIZE * 4)) -#define V_U_ESP (V_END + (CLONGSIZE * 3)) -#define V_EFLAGS (V_END + (CLONGSIZE * 2)) -#define V_U_CS (V_END + (CLONGSIZE * 1)) -#define V_U_EIP (V_END + (CLONGSIZE * 0)) - ENTRY(sn1_brand_syscall_callback) - - CALLBACK_PROLOGUE(%eax, %ebx, %bl) - - /* - * To 'return' to our user-space handler, we need to replace the - * iret target address. - * The original return address is passed in %eax. - */ - CALC_TABLE_ADDR(%ebx) /* new return addr is in %ebx */ - SET_V(%esp, 1, V_U_EIP, %ebx) /* set iret target address to hdlr */ - GET_V(%esp, 1, V_URET_ADDR, %eax) /* save orig return addr in %eax */ - - GET_V(%esp, 1, V_U_GS, %ebx) /* grab the the user %gs */ - movw %bx, %gs /* restore the user %gs */ - - popl %ebx /* Restore scratch register */ - addl $V_END, %esp /* Remove all callback stuff from stack */ + INT_EMUL(sn1_emulation_table, SPD_HANDLER) jmp nopop_sys_rtt_syscall 9: - popl %ebx ret SET_SIZE(sn1_brand_syscall_callback) /* - * %eax - syscall number - * %ecx - user space %esp * %edx - user space return address + * See "32-BIT INTERPOSITION STACK" in brand_asm.h. */ ENTRY(sn1_brand_sysenter_callback) - - CALLBACK_PROLOGUE(%eax, %ebx, %bl) - - /* - * To 'return' to our user-space handler, we just need to place its - * address into %edx. - * The original return address is passed in %eax. - */ - movl %edx, %ebx /* save orig return addr in tmp reg */ - CALC_TABLE_ADDR(%edx) /* new return addr is in %edx */ - movl %ebx, %eax /* save orig return addr in %eax */ - - GET_V(%esp, 1, V_U_GS, %ebx) /* grab the the user %gs */ - movw %bx, %gs /* restore the user %gs */ - - popl %ebx /* restore scratch register */ + SYSCALL_EMUL(sn1_emulation_table, SPD_HANDLER, %edx) sysexit 9: - popl %ebx ret SET_SIZE(sn1_brand_sysenter_callback)
--- a/usr/src/uts/intel/brand/solaris10/s10_brand_asm.s Thu Feb 18 13:36:37 2010 +0000 +++ b/usr/src/uts/intel/brand/solaris10/s10_brand_asm.s Thu Feb 18 07:03:00 2010 -0700 @@ -29,11 +29,8 @@ #else /* lint */ -#include <sys/asm_linkage.h> -#include <sys/privregs.h> -#include <sys/segments.h> #include <s10_offsets.h> -#include "assym.h" +#include "../common/brand_asm.h" #endif /* lint */ @@ -64,325 +61,72 @@ #else /* lint */ #if defined(__amd64) -/* - * When our syscall interposition callback entry point gets invoked the - * stack looks like this: - * -------------------------------------- - * 40 | user %gs | - * 32 | callback pointer | - * 24 | saved stack pointer | - * | 16 | lwp pointer | - * v 8 | user return address | - * 0 | BRAND_CALLBACK()'s return addr | - * -------------------------------------- - */ - -#define V_COUNT 6 -#define V_END (CLONGSIZE * 6) -#define V_SSP (CLONGSIZE * 3) -#define V_LWP (CLONGSIZE * 2) -#define V_URET_ADDR (CLONGSIZE * 1) -#define V_CB_ADDR (CLONGSIZE * 0) - -#define SP_REG %rsp -#define SYSCALL_REG %rax - -#else /* !__amd64 */ -/* - * When our syscall interposition callback entry point gets invoked the - * stack looks like this: - * -------------------------------------- - * | 24 | 'scratch space' | - * | 20 | user's %ebx | - * | 16 | user's %gs selector | - * | 12 | kernel's %gs selector | - * | 8 | lwp pointer | - * v 4 | user return address | - * 0 | callback wrapper return addr | - * -------------------------------------- - */ - -#define V_COUNT 7 -#define V_END (CLONGSIZE * 7) -#define V_U_GS (CLONGSIZE * 4) -#define V_K_GS (CLONGSIZE * 3) -#define V_LWP (CLONGSIZE * 2) -#define V_URET_ADDR (CLONGSIZE * 1) -#define V_CB_ADDR (CLONGSIZE * 0) - -#define SP_REG %esp -#define SYSCALL_REG %eax - -#endif /* !__amd64 */ - -/* - * The following macros allow us to access to variables/parameters passed - * in on the stack. They take the following variables: - * sp - a register with the current stack pointer value - * pcnt - the number of words currently pushed onto the stack - * var - the variable to lookup - * reg - a register to read the variable into, or - * a register to write to the variable - */ -#define V_OFFSET(pcnt, var) \ - (var + (pcnt * CLONGSIZE)) - -#define GET_V(sp, pcnt, var, reg) \ - mov V_OFFSET(pcnt, var)(sp), reg - -#define SET_V(sp, pcnt, var, reg) \ - mov reg, V_OFFSET(pcnt, var)(sp) - -#define GET_PROCP(sp, pcnt, reg) \ - GET_V(sp, pcnt, V_LWP, reg) /* get lwp pointer */ ;\ - mov LWP_PROCP(reg), reg /* get proc pointer */ - -#define GET_P_BRAND_DATA(sp, pcnt, reg) \ - GET_PROCP(sp, pcnt, reg) ;\ - mov P_BRAND_DATA(reg), reg /* get p_brand_data */ - -/* - * Each of the following macros returns to the standard syscall codepath if - * it detects that this process is not able, or intended, to emulate this - * system call. They all assume that the routine provides a 'bail-out' - * label of '9'. - */ - -/* - * See if this process has a user-space hdlr registered for it. For the - * s10 brand, the per-process brand data holds the address of the handler. - * As shown in the stack diagrams below, the callback code leaves that data - * at these offsets. So check if s10_proc_data_t->spd_handler is non-NULL. - */ -#define CHECK_FOR_HANDLER(scr) \ - GET_P_BRAND_DATA(SP_REG, 1, scr) /* get p_brand_data */ ;\ - cmp $0, scr ;\ - je 9f ;\ - cmp $0, SPD_HANDLER(scr) /* check spd_handler */ ;\ - je 9f - -/* - * If the system call number is >= 1024, then it is coming from the - * emulation support library. As such we should handle it natively instead - * of sending it back to the emulation library. - */ -#define CHECK_FOR_NATIVE(reg) \ - cmp $1024, reg ;\ - jl 1f ;\ - sub $1024, reg ;\ - jmp 9f ;\ -1: - -/* - * Check to see if we want to interpose on this system call. If not, we - * jump back into the normal syscall path and pretend nothing happened. - */ -#define CHECK_FOR_INTERPOSITION(sysr, scr, scr_low) \ - cmp $NSYSCALL, sysr /* is 0 <= syscall <= MAX? */ ;\ - ja 9f /* no, take normal err path */ ;\ - lea s10_emulation_table, scr ;\ - mov (scr), scr ;\ - add sysr, scr ;\ - movb (scr), scr_low ;\ - cmpb $0, scr_low ;\ - je 9f - -#define CALLBACK_PROLOGUE(call, scr, scr_low) \ - push scr /* Save scratch register */ ;\ - CHECK_FOR_HANDLER(scr) ;\ - CHECK_FOR_NATIVE(call) ;\ - CHECK_FOR_INTERPOSITION(call, scr, scr_low) - -/* - * Rather than returning to the instruction after the syscall, we need to - * transfer control into the brand library's handler table at - * table_addr + (16 * syscall_num), thus encoding the system call number in the - * instruction pointer. The CALC_TABLE_ADDR macro performs that calculation. - * - * This macro assumes the syscall number is in SYSCALL_REG and it clobbers - * that register. It leaves the calculated handler table return address in - * the scratch reg. - */ -#define CALC_TABLE_ADDR(scr) \ - GET_P_BRAND_DATA(SP_REG, 1, scr) /* get p_brand_data ptr */ ;\ - mov SPD_HANDLER(scr), scr /* get p_brand_data->spd_handler */ ;\ - shl $4, SYSCALL_REG /* syscall_num * 16 */ ;\ - add SYSCALL_REG, scr /* leave return addr in scr reg. */ - -/* - * To 'return' to our user-space handler, we just need to place its address - * into 'retreg'. The original return address is passed in SYSCALL_REG. - */ -#define SETUP_RET_DATA(scr, retreg) \ - CALC_TABLE_ADDR(scr) ;\ - mov retreg, SYSCALL_REG /* save orig return addr in %rax */ ;\ - mov scr, retreg /* save new return addr in ret reg */ ;\ - pop scr /* restore scratch register */ - -/* - * The callback routines: - */ - -#if defined(__amd64) /* * syscall handler for 32-bit user processes: - * %rax - syscall number - * %ecx - the address of the instruction after the syscall + * %rcx - the address of the instruction after the syscall + * See "64-BIT INTERPOSITION STACK" in brand_asm.h. */ ENTRY(s10_brand_syscall32_callback) - - CALLBACK_PROLOGUE(%rax, %r15, %r15b) - - SETUP_RET_DATA(%r15, %rcx) - GET_V(%rsp, 0, V_SSP, %rsp) /* restore user's stack pointer */ + SYSCALL_EMUL(s10_emulation_table, SPD_HANDLER, %rcx) jmp nopop_sys_syscall32_swapgs_sysretl 9: - popq %r15 retq SET_SIZE(s10_brand_syscall32_callback) /* * syscall handler for 64-bit user processes: - * %rax - syscall number - * %rcx - user space %rip + * %rcx - the address of the instruction after the syscall + * See "64-BIT INTERPOSITION STACK" in brand_asm.h. */ ENTRY(s10_brand_syscall_callback) - - CALLBACK_PROLOGUE(%rax, %r15, %r15b) - - SETUP_RET_DATA(%r15, %rcx) - GET_V(%rsp, 0, V_SSP, %rsp) /* restore user's stack pointer */ + SYSCALL_EMUL(s10_emulation_table, SPD_HANDLER, %rcx) jmp nopop_sys_syscall_swapgs_sysretq 9: - popq %r15 retq - SET_SIZE(s10_brand_syscall_callback) /* - * %eax - syscall number - * %ecx - user space %esp - * %edx - user space return address + * %rdx - user space return address + * See "64-BIT INTERPOSITION STACK" in brand_asm.h. */ ENTRY(s10_brand_sysenter_callback) - - CALLBACK_PROLOGUE(%rax, %r15, %r15b) - - SETUP_RET_DATA(%r15, %rdx) + SYSCALL_EMUL(s10_emulation_table, SPD_HANDLER, %rdx) jmp sys_sysenter_swapgs_sysexit 9: - popq %r15 ret SET_SIZE(s10_brand_sysenter_callback) /* - * The saved stack pointer points at the state saved when we took - * the interrupt: - * -------------------------------------- - * | 32 | user's %ss | - * | 24 | user's %esp | - * | 16 | EFLAGS register | - * v 8 | user's %cs | - * 0 | user's %eip | - * -------------------------------------- + * See "64-BIT INTERPOSITION STACK" and "64-BIT INT STACK" in brand_asm.h. */ -#define V_U_EIP (CLONGSIZE * 0) - ENTRY(s10_brand_int91_callback) - - CALLBACK_PROLOGUE(%rax, %r15, %r15b) - - /* - * To 'return' to our user-space handler we need to update the user's - * %eip pointer in the saved interrupt state. The interrupt state was - * pushed onto our stack automatically when the interrupt occured; see - * the comments above. The original return address is passed in %rax. - */ - CALC_TABLE_ADDR(%r15) - GET_V(%rsp, 1, V_SSP, %rax) /* get saved stack pointer */ - SET_V(%rax, 0, V_U_EIP, %r15) /* save new return addr in %eip */ - GET_V(%rsp, 1, V_URET_ADDR, %rax) /* %rax has orig. return addr. */ - - popq %r15 /* Restore scratch register */ - movq V_SSP(%rsp), %rsp /* Remove callback stuff from stack */ + INT_EMUL(s10_emulation_table, SPD_HANDLER) jmp sys_sysint_swapgs_iret 9: - popq %r15 retq SET_SIZE(s10_brand_int91_callback) #else /* !__amd64 */ /* - * lcall handler for 32-bit OS - * %eax - syscall number - * - * Above the stack contents common to all callbacks is the - * int/lcall-specific state: - * -------------------------------------- - * | 44 | user's %ss | - * | 40 | user's %esp | - * | 36 | EFLAGS register | - * v 32 | user's %cs | - * 28 | user's %eip | - * -------------------------------------- + * See "32-BIT INTERPOSITION STACK" and "32-BIT INT STACK" in brand_asm.h. */ -#define V_U_SS (V_END + (CLONGSIZE * 4)) -#define V_U_ESP (V_END + (CLONGSIZE * 3)) -#define V_EFLAGS (V_END + (CLONGSIZE * 2)) -#define V_U_CS (V_END + (CLONGSIZE * 1)) -#define V_U_EIP (V_END + (CLONGSIZE * 0)) - ENTRY(s10_brand_syscall_callback) - - CALLBACK_PROLOGUE(%eax, %ebx, %bl) - - /* - * To 'return' to our user-space handler, we need to replace the - * iret target address. - * The original return address is passed in %eax. - */ - CALC_TABLE_ADDR(%ebx) /* new return addr is in %ebx */ - SET_V(%esp, 1, V_U_EIP, %ebx) /* set iret target address to hdlr */ - GET_V(%esp, 1, V_URET_ADDR, %eax) /* save orig return addr in %eax */ - - GET_V(%esp, 1, V_U_GS, %ebx) /* grab the the user %gs */ - movw %bx, %gs /* restore the user %gs */ - - popl %ebx /* Restore scratch register */ - addl $V_END, %esp /* Remove all callback stuff from stack */ + INT_EMUL(s10_emulation_table, SPD_HANDLER) jmp nopop_sys_rtt_syscall 9: - popl %ebx ret SET_SIZE(s10_brand_syscall_callback) /* - * %eax - syscall number - * %ecx - user space %esp * %edx - user space return address + * See "32-BIT INTERPOSITION STACK" in brand_asm.h. */ ENTRY(s10_brand_sysenter_callback) - - CALLBACK_PROLOGUE(%eax, %ebx, %bl) - - /* - * To 'return' to our user-space handler, we just need to place its - * address into %edx. - * The original return address is passed in %eax. - */ - movl %edx, %ebx /* save orig return addr in tmp reg */ - CALC_TABLE_ADDR(%edx) /* new return addr is in %edx */ - movl %ebx, %eax /* save orig return addr in %eax */ - - GET_V(%esp, 1, V_U_GS, %ebx) /* grab the the user %gs */ - movw %bx, %gs /* restore the user %gs */ - - popl %ebx /* restore scratch register */ + SYSCALL_EMUL(s10_emulation_table, SPD_HANDLER, %edx) sysexit 9: - popl %ebx ret SET_SIZE(s10_brand_sysenter_callback)
--- a/usr/src/uts/intel/genassym/offsets.in Thu Feb 18 13:36:37 2010 +0000 +++ b/usr/src/uts/intel/genassym/offsets.in Thu Feb 18 07:03:00 2010 -0700 @@ -19,12 +19,10 @@ \ CDDL HEADER END \ \ -\ Copyright 2006 Sun Microsystems, Inc. All rights reserved. +\ Copyright 2010 Sun Microsystems, Inc. All rights reserved. \ Use is subject to license terms. \ -#pragma ident "%Z%%M% %I% %E% SMI" - \ \ offsets.in: input file to produce the architecture-dependent genassym.h \ using the ctfstabs program @@ -36,9 +34,6 @@ #include <sys/lx_brand.h> -lx_lwp_data - br_ugs - lx_proc_data l_handler l_tracehandler