summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_handler.s55
-rw-r--r--usr/src/lib/brand/sn1/sn1_brand/common/sn1_brand.c6
-rw-r--r--usr/src/lib/brand/sn1/sn1_brand/i386/sn1_handler.s54
-rw-r--r--usr/src/lib/brand/sn1/sn1_brand/sys/sn1_misc.h3
-rw-r--r--usr/src/lib/brand/solaris10/s10_brand/amd64/s10_handler.s55
-rw-r--r--usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c7
-rw-r--r--usr/src/lib/brand/solaris10/s10_brand/i386/s10_handler.s54
-rw-r--r--usr/src/lib/brand/solaris10/s10_brand/sys/s10_misc.h3
8 files changed, 197 insertions, 40 deletions
diff --git a/usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_handler.s b/usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_handler.s
index f899a08eae..1853801302 100644
--- a/usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_handler.s
+++ b/usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_handler.s
@@ -19,27 +19,55 @@
* 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.
*/
#include <sn1_misc.h>
+/*
+ * Each JMP must occupy 16 bytes
+ */
+#define JMP \
+ pushq $_CONST(. - sn1_handler_table); \
+ jmp sn1_handler; \
+ .align 16;
+
+#define JMP4 JMP; JMP; JMP; JMP
+#define JMP16 JMP4; JMP4; JMP4; JMP4
+#define JMP64 JMP16; JMP16; JMP16; JMP16
+#define JMP256 JMP64; JMP64; JMP64; JMP64
+
#if defined(lint)
void
+sn1_handler_table(void)
+{}
+
+void
sn1_handler(void)
{
}
#else /* lint */
+
/*
- * %rax - syscall number
+ * 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
+ ENTRY_NP(sn1_handler_table)
+ JMP256
+ SET_SIZE(sn1_handler_table)
+
+ /*
+ * %rax - userland return address
* stack contains:
- * --------------------------------------
- * | 16 | syscall arguments |
- * v 8 | syscall wrapper return address |
- * %rsp+0 | syscall return address |
+ * | --------------------------------------
+ * v 8 | syscall arguments |
+ * %rsp+0 | syscall number |
* --------------------------------------
*/
ENTRY_NP(sn1_handler)
@@ -59,7 +87,6 @@ sn1_handler(void)
movq %r8, EH_LOCALS_GREG(REG_R8)(%rbp)
movq %rdi, EH_LOCALS_GREG(REG_RDI)(%rbp)
movq %rsi, EH_LOCALS_GREG(REG_RSI)(%rbp)
- movq %rax, EH_LOCALS_GREG(REG_RAX)(%rbp)
movq %rbx, EH_LOCALS_GREG(REG_RBX)(%rbp)
movq %rcx, EH_LOCALS_GREG(REG_RCX)(%rbp)
movq %rdx, EH_LOCALS_GREG(REG_RDX)(%rbp)
@@ -84,13 +111,23 @@ sn1_handler(void)
movq %rbp, %r12 /* save syscall rsp */
addq $CPTRSIZE, %r12
movq %r12, EH_LOCALS_GREG(REG_RSP)(%rbp)
- movq EH_ARGS_OFFSET(1)(%rbp), %r12 /* save syscall ret address */
- movq %r12, EH_LOCALS_GREG(REG_RIP)(%rbp)
movq %fs:0, %r12 /* save syscall fsbase */
movq %r12, EH_LOCALS_GREG(REG_FSBASE)(%rbp)
movq $0, EH_LOCALS_GREG(REG_GSBASE)(%rbp)
/*
+ * The kernel drops us into the middle of the sn1_handle_table
+ * above that then pushes that table offset onto the stack, and calls
+ * into sn1_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.
+ */
+ xchgq CPTRSIZE(%rbp), %rax /* swap JMP table offset and ret addr */
+ shrq $4, %rax /* table_offset/size = syscall num */
+ movq %rax, EH_LOCALS_GREG(REG_RAX)(%rbp) /* save syscall num */
+
+ /*
* 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
diff --git a/usr/src/lib/brand/sn1/sn1_brand/common/sn1_brand.c b/usr/src/lib/brand/sn1/sn1_brand/common/sn1_brand.c
index 775d8144c5..816ef31df2 100644
--- a/usr/src/lib/brand/sn1/sn1_brand/common/sn1_brand.c
+++ b/usr/src/lib/brand/sn1/sn1_brand/common/sn1_brand.c
@@ -19,7 +19,7 @@
* 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.
*/
@@ -352,7 +352,11 @@ sn1_init(int argc, char *argv[], char *envp[])
* syscall.
*/
reg.sbr_version = SN1_VERSION;
+#ifdef __x86
+ reg.sbr_handler = (caddr_t)sn1_handler_table;
+#else /* !__x86 */
reg.sbr_handler = (caddr_t)sn1_handler;
+#endif /* !__x86 */
if ((err = __systemcall(&rval, SYS_brand, B_REGISTER, &reg)) != 0) {
sn1_abort(err, "Failed to brand current process");
/*NOTREACHED*/
diff --git a/usr/src/lib/brand/sn1/sn1_brand/i386/sn1_handler.s b/usr/src/lib/brand/sn1/sn1_brand/i386/sn1_handler.s
index ecce5b7dbb..66bef79ad1 100644
--- a/usr/src/lib/brand/sn1/sn1_brand/i386/sn1_handler.s
+++ b/usr/src/lib/brand/sn1/sn1_brand/i386/sn1_handler.s
@@ -20,21 +20,49 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sn1_misc.h>
+/*
+ * Each JMP must occupy 16 bytes
+ */
+#define JMP \
+ pushl $_CONST(. - sn1_handler_table); \
+ jmp sn1_handler; \
+ .align 16;
+
+#define JMP4 JMP; JMP; JMP; JMP
+#define JMP16 JMP4; JMP4; JMP4; JMP4
+#define JMP64 JMP16; JMP16; JMP16; JMP16
+#define JMP256 JMP64; JMP64; JMP64; JMP64
+
#if defined(lint)
void
+sn1_handler_table(void)
+{}
+
+void
sn1_handler(void)
{
}
#else /* lint */
+ /*
+ * On entry to this table, %eax 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
+ ENTRY_NP(sn1_handler_table)
+ JMP256
+ SET_SIZE(sn1_handler_table)
+
#define PIC_SETUP(r) \
call 9f; \
9: \
@@ -42,12 +70,11 @@ sn1_handler(void)
addl $_GLOBAL_OFFSET_TABLE_ + [. - 9b], r
/*
- * %eax - syscall number
+ * %eax - userland return address
* stack contains:
- * --------------------------------------
- * | 8 | syscall arguments |
- * v 4 | syscall wrapper return address |
- * %esp+0 | syscall return address |
+ * | --------------------------------------
+ * v 4 | syscall arguments |
+ * %esp+0 | syscall number |
* --------------------------------------
*/
ENTRY_NP(sn1_handler)
@@ -57,7 +84,6 @@ sn1_handler(void)
/* Save registers at the time of the syscall. */
movl $0, EH_LOCALS_GREG(TRAPNO)(%ebp)
movl $0, EH_LOCALS_GREG(ERR)(%ebp)
- movl %eax, EH_LOCALS_GREG(EAX)(%ebp)
movl %ebx, EH_LOCALS_GREG(EBX)(%ebp)
movl %ecx, EH_LOCALS_GREG(ECX)(%ebp)
movl %edx, EH_LOCALS_GREG(EDX)(%ebp)
@@ -76,8 +102,18 @@ sn1_handler(void)
movl %ebp, %ecx /* save syscall esp */
addl $CPTRSIZE, %ecx
movl %ecx, EH_LOCALS_GREG(ESP)(%ebp)
- movl EH_ARGS_OFFSET(1)(%ebp), %ecx /* save syscall ret address */
- movl %ecx, EH_LOCALS_GREG(EIP)(%ebp)
+
+ /*
+ * The kernel drops us into the middle of the sn1_handle_table
+ * above that then pushes that table offset onto the stack, and calls
+ * into sn1_handler. That offset indicates the system call number while
+ * %eax 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.
+ */
+ xchgl CPTRSIZE(%ebp), %eax /* swap JMP table offset and ret addr */
+ shrl $4, %eax /* table_offset/size = syscall num */
+ movl %eax, EH_LOCALS_GREG(EAX)(%ebp) /* save syscall num */
/*
* Finish setting up our stack frame. We would normally do this
diff --git a/usr/src/lib/brand/sn1/sn1_brand/sys/sn1_misc.h b/usr/src/lib/brand/sn1/sn1_brand/sys/sn1_misc.h
index 0ea4313008..7a420b168c 100644
--- a/usr/src/lib/brand/sn1/sn1_brand/sys/sn1_misc.h
+++ b/usr/src/lib/brand/sn1/sn1_brand/sys/sn1_misc.h
@@ -19,7 +19,7 @@
* 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.
*/
@@ -155,6 +155,7 @@ extern void sn1_runexe(void *, ulong_t);
/*
* From sn1_handler.s
*/
+extern void sn1_handler_table(void);
extern void sn1_handler(void);
extern void sn1_error(void);
extern void sn1_success(void);
diff --git a/usr/src/lib/brand/solaris10/s10_brand/amd64/s10_handler.s b/usr/src/lib/brand/solaris10/s10_brand/amd64/s10_handler.s
index 5d676d421b..76b2dcfe1e 100644
--- a/usr/src/lib/brand/solaris10/s10_brand/amd64/s10_handler.s
+++ b/usr/src/lib/brand/solaris10/s10_brand/amd64/s10_handler.s
@@ -19,27 +19,55 @@
* 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.
*/
#include <s10_misc.h>
+/*
+ * Each JMP must occupy 16 bytes
+ */
+#define JMP \
+ pushq $_CONST(. - s10_handler_table); \
+ jmp s10_handler; \
+ .align 16;
+
+#define JMP4 JMP; JMP; JMP; JMP
+#define JMP16 JMP4; JMP4; JMP4; JMP4
+#define JMP64 JMP16; JMP16; JMP16; JMP16
+#define JMP256 JMP64; JMP64; JMP64; JMP64
+
#if defined(lint)
void
+s10_handler_table(void)
+{}
+
+void
s10_handler(void)
{
}
#else /* lint */
+
/*
- * %rax - syscall number
+ * 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
+ ENTRY_NP(s10_handler_table)
+ JMP256
+ SET_SIZE(s10_handler_table)
+
+ /*
+ * %rax - userland return address
* stack contains:
- * --------------------------------------
- * | 16 | syscall arguments |
- * v 8 | syscall wrapper return address |
- * %rsp+0 | syscall return address |
+ * | --------------------------------------
+ * v 8 | syscall arguments |
+ * %rsp+0 | syscall number |
* --------------------------------------
*/
ENTRY_NP(s10_handler)
@@ -59,7 +87,6 @@ s10_handler(void)
movq %r8, EH_LOCALS_GREG(REG_R8)(%rbp)
movq %rdi, EH_LOCALS_GREG(REG_RDI)(%rbp)
movq %rsi, EH_LOCALS_GREG(REG_RSI)(%rbp)
- movq %rax, EH_LOCALS_GREG(REG_RAX)(%rbp)
movq %rbx, EH_LOCALS_GREG(REG_RBX)(%rbp)
movq %rcx, EH_LOCALS_GREG(REG_RCX)(%rbp)
movq %rdx, EH_LOCALS_GREG(REG_RDX)(%rbp)
@@ -84,13 +111,23 @@ s10_handler(void)
movq %rbp, %r12 /* save syscall rsp */
addq $CPTRSIZE, %r12
movq %r12, EH_LOCALS_GREG(REG_RSP)(%rbp)
- movq EH_ARGS_OFFSET(1)(%rbp), %r12 /* save syscall ret address */
- movq %r12, EH_LOCALS_GREG(REG_RIP)(%rbp)
movq %fs:0, %r12 /* save syscall fsbase */
movq %r12, EH_LOCALS_GREG(REG_FSBASE)(%rbp)
movq $0, EH_LOCALS_GREG(REG_GSBASE)(%rbp)
/*
+ * 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.
+ */
+ xchgq CPTRSIZE(%rbp), %rax /* swap JMP table offset and ret addr */
+ shrq $4, %rax /* table_offset/size = syscall num */
+ movq %rax, EH_LOCALS_GREG(REG_RAX)(%rbp) /* save syscall num */
+
+ /*
* 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
diff --git a/usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c b/usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c
index 596291a538..d3b6955288 100644
--- a/usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c
+++ b/usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c
@@ -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.
*/
@@ -1839,7 +1839,12 @@ s10_init(int argc, char *argv[], char *envp[])
* syscall.
*/
reg.sbr_version = S10_VERSION;
+#ifdef __x86
+ reg.sbr_handler = (caddr_t)s10_handler_table;
+#else /* !__x86 */
reg.sbr_handler = (caddr_t)s10_handler;
+#endif /* !__x86 */
+
if ((err = __systemcall(&rval, SYS_brand, B_REGISTER, &reg)) != 0) {
s10_abort(err, "Failed to brand current process");
/*NOTREACHED*/
diff --git a/usr/src/lib/brand/solaris10/s10_brand/i386/s10_handler.s b/usr/src/lib/brand/solaris10/s10_brand/i386/s10_handler.s
index 30571c7769..1b2f5e5313 100644
--- a/usr/src/lib/brand/solaris10/s10_brand/i386/s10_handler.s
+++ b/usr/src/lib/brand/solaris10/s10_brand/i386/s10_handler.s
@@ -19,21 +19,49 @@
* 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.
*/
#include <s10_misc.h>
+/*
+ * Each JMP must occupy 16 bytes
+ */
+#define JMP \
+ pushl $_CONST(. - s10_handler_table); \
+ jmp s10_handler; \
+ .align 16;
+
+#define JMP4 JMP; JMP; JMP; JMP
+#define JMP16 JMP4; JMP4; JMP4; JMP4
+#define JMP64 JMP16; JMP16; JMP16; JMP16
+#define JMP256 JMP64; JMP64; JMP64; JMP64
+
#if defined(lint)
void
+s10_handler_table(void)
+{}
+
+void
s10_handler(void)
{
}
#else /* lint */
+ /*
+ * On entry to this table, %eax 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
+ ENTRY_NP(s10_handler_table)
+ JMP256
+ SET_SIZE(s10_handler_table)
+
#define PIC_SETUP(r) \
call 9f; \
9: \
@@ -41,12 +69,11 @@ s10_handler(void)
addl $_GLOBAL_OFFSET_TABLE_ + [. - 9b], r
/*
- * %eax - syscall number
+ * %eax - userland return address
* stack contains:
- * --------------------------------------
- * | 8 | syscall arguments |
- * v 4 | syscall wrapper return address |
- * %esp+0 | syscall return address |
+ * | --------------------------------------
+ * v 4 | syscall arguments |
+ * %esp+0 | syscall number |
* --------------------------------------
*/
ENTRY_NP(s10_handler)
@@ -56,7 +83,6 @@ s10_handler(void)
/* Save registers at the time of the syscall. */
movl $0, EH_LOCALS_GREG(TRAPNO)(%ebp)
movl $0, EH_LOCALS_GREG(ERR)(%ebp)
- movl %eax, EH_LOCALS_GREG(EAX)(%ebp)
movl %ebx, EH_LOCALS_GREG(EBX)(%ebp)
movl %ecx, EH_LOCALS_GREG(ECX)(%ebp)
movl %edx, EH_LOCALS_GREG(EDX)(%ebp)
@@ -75,8 +101,18 @@ s10_handler(void)
movl %ebp, %ecx /* save syscall esp */
addl $CPTRSIZE, %ecx
movl %ecx, EH_LOCALS_GREG(ESP)(%ebp)
- movl EH_ARGS_OFFSET(1)(%ebp), %ecx /* save syscall ret address */
- movl %ecx, EH_LOCALS_GREG(EIP)(%ebp)
+
+ /*
+ * 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
+ * %eax 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.
+ */
+ xchgl CPTRSIZE(%ebp), %eax /* swap JMP table offset and ret addr */
+ shrl $4, %eax /* table_offset/size = syscall num */
+ movl %eax, EH_LOCALS_GREG(EAX)(%ebp) /* save syscall num */
/*
* Finish setting up our stack frame. We would normally do this
diff --git a/usr/src/lib/brand/solaris10/s10_brand/sys/s10_misc.h b/usr/src/lib/brand/solaris10/s10_brand/sys/s10_misc.h
index 62e4adb2ac..926873347f 100644
--- a/usr/src/lib/brand/solaris10/s10_brand/sys/s10_misc.h
+++ b/usr/src/lib/brand/solaris10/s10_brand/sys/s10_misc.h
@@ -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.
*/
@@ -181,6 +181,7 @@ extern void s10_runexe(void *, ulong_t);
/*
* From s10_handler.s
*/
+extern void s10_handler_table(void);
extern void s10_handler(void);
extern void s10_error(void);
extern void s10_success(void);