s10_handler.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.
*/
#include <s10_misc.h>
/*
* Each JMP must occupy 16 bytes
*/
#define JMP \
jmp s10_handler; \
.align 16;
#if defined(lint)
void
s10_handler_table(void)
{}
void
s10_handler(void)
{
}
#else /* lint */
/*
* On entry to this table, %rax will hold the return address. The
* location where we enter the table is a function of the system
* call number. The table needs the same alignment as the individual
* entries.
*/
.align 16
/*
* %rax - userland return address
* stack contains:
* | --------------------------------------
* v 8 | syscall arguments |
* %rsp+0 | syscall number |
* --------------------------------------
*/
/* Save registers at the time of the syscall. */
pushfq /* save syscall flags */
/*
* The kernel drops us into the middle of the s10_handle_table
* above that then pushes that table offset onto the stack, and calls
* into s10_handler. That offset indicates the system call number while
* %rax holds the return address for the system call. We replace the
* value on the stack with the return address, and use the value to
* compute the system call number by dividing by the table entry size.
*/
/*
* Finish setting up our stack frame. We would normally do this
* upon entry to this function, but in this case we delayed it
* because a "sub" operation can modify flags and we wanted to
* save the flags into the gregset_t above before they get modified.
*
* Our stack frame format is documented in s10_misc.h.
*/
/* Look up the system call's entry in the sysent table */
/*
* Get the return value flag and the number of arguments from the
* sysent table.
*/
/*
* Setup arguments for our emulation call. Our input arguments,
* 0 to N, will become emulation call arguments 1 to N+1.
*
* Note: Syscall argument passing is different from function call
* argument passing on amd64. For function calls, the fourth arg
* is passed via %rcx, but for system calls the 4th argument is
* passed via %r10. This is because in amd64, the syscall
* instruction puts lower 32 bit of %rflags in %r11 and puts the
* %rip value to %rcx.
*/
/*
* The first parameter to the emulation callback function is a
* pointer to a sysret_t structure.
*/
/* invoke the emulation routine */
/* restore scratch and parameter registers */
/* Check for syscall emulation success or failure */
stc /* failure, set carry flag */
jmp return /* return, %rax == errno */
/* There is always at least one return value. */
clc /* success, clear carry flag */
return:
ret /* ret to instr after syscall */
#endif /* lint */