s10_brand_asm.s revision b72c368a02e0464faeef362bc5a1cf0fc69981da
/*
* 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
* 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.
*/
#if defined(lint)
#else /* lint */
#include <sys/asm_linkage.h>
#include <sys/privregs.h>
#include <sys/segments.h>
#include <s10_offsets.h>
#include "assym.h"
#endif /* lint */
#ifdef lint
void
{
}
void
{
}
#if defined(__amd64)
void
{
}
#endif /* amd64 */
void
s10_brand_int91_callback(void)
{
}
#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 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 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
*/
/*
* 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) \
je 9f ;\
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) \
jl 1f ;\
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.
*/
je 9f
CHECK_FOR_HANDLER(scr) ;\
CHECK_FOR_NATIVE(call) ;\
/*
* 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) \
/*
* 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.
*/
CALC_TABLE_ADDR(scr) ;\
/*
* 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
*/
9:
/*
* syscall handler for 64-bit user processes:
* %rax - syscall number
* %rcx - user space %rip
*/
9:
/*
* %eax - syscall number
* %ecx - user space %esp
* %edx - user space return address
*/
9:
/*
* 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 |
* --------------------------------------
*/
/*
* 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.
*/
9:
#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 |
* --------------------------------------
*/
/*
* To 'return' to our user-space handler, we need to replace the
* iret target address.
* The original return address is passed in %eax.
*/
9:
/*
* %eax - syscall number
* %ecx - user space %esp
* %edx - user space return address
*/
/*
* To 'return' to our user-space handler, we just need to place its
* address into %edx.
* The original return address is passed in %eax.
*/
9:
#endif /* !__amd64 */
#endif /* lint */