diff options
Diffstat (limited to 'usr/src/lib')
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, ®)) != 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, ®)) != 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); |