Print this page
OS-5510 remove lwp_brand_syscall_fast handler
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Lint-clean syscall_asm_amd64.s
OS-4961 lxbrand want fasttrap-like brand hook
Reviewed by: Joshua M. Clulow <jmc@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
OS-3937 lxbrand incorrect stack alignment for lx_syscall_enter()
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
OS-3561 lxbrand emulation library should execute on alternate stack
OS-3558 lxbrand add support for full in-kernel syscall handling
OS-3545 lx_syscall_regs should not walk stack
OS-3868 many LTP testcases now hang
OS-3901 lxbrand lx_recvmsg fails to translate control messages when 64-bit
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Bryan Cantrill <bryan@joyent.com>
OS-3215 32bit syscalls with more than 6 parameters re-use arg0/arg1 as arg6/arg7
OS-3223 Passing arg6 and arg7 can't clobber the stack for ap-style calls
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Keith M Wesolowski <wesolows@foobazco.org>
back out OS-3215: causes OS-3223
OS-3215 32bit syscalls with more than 6 parameters re-use arg0/arg1 as arg6/arg7
OS-2834 ship lx brand

*** 18,45 **** * * CDDL HEADER END */ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. ! * Copyright 2015 Joyent, Inc. */ #include <sys/asm_linkage.h> #include <sys/asm_misc.h> #include <sys/regset.h> #include <sys/privregs.h> #include <sys/psw.h> - #include <sys/machbrand.h> #if defined(__lint) #include <sys/types.h> #include <sys/thread.h> #include <sys/systm.h> #else /* __lint */ #include <sys/segments.h> #include <sys/pcb.h> #include <sys/trap.h> #include <sys/ftrace.h> #include <sys/traptrace.h> --- 18,45 ---- * * CDDL HEADER END */ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. ! * Copyright 2016 Joyent, Inc. */ #include <sys/asm_linkage.h> #include <sys/asm_misc.h> #include <sys/regset.h> #include <sys/privregs.h> #include <sys/psw.h> #if defined(__lint) #include <sys/types.h> #include <sys/thread.h> #include <sys/systm.h> #else /* __lint */ + #include <sys/machbrand.h> #include <sys/segments.h> #include <sys/pcb.h> #include <sys/trap.h> #include <sys/ftrace.h> #include <sys/traptrace.h>
*** 501,510 **** --- 501,511 ---- movq %rsp, %rbp movq T_LWP(%r15), %r14 ASSERT_NO_RUPDATE_PENDING(%r14) + ENABLE_INTR_FLAGS MSTATE_TRANSITION(LMS_USER, LMS_SYSTEM) movl REGOFF_RAX(%rsp), %eax /* (%rax damaged by mstate call) */
*** 514,523 **** --- 515,546 ---- incq LWP_RU_SYSC(%r14) movb $NORMALRETURN, LWP_EOSYS(%r14) incq %gs:CPU_STATS_SYS_SYSCALL + /* + * If our LWP has an alternate system call handler, run that instead of + * the regular system call path. + */ + movq LWP_BRAND_SYSCALL(%r14), %rdi + testq %rdi, %rdi + jz _syscall_no_brand + + pushq %rax + subq $8, %rsp /* align stack for call to C */ + call *%rdi + addq $8, %rsp + + /* + * If the alternate handler returns 0, we skip straight to the return to + * usermode. Otherwise, we resume regular system call processing. + */ + testl %eax, %eax + popq %rax + jz _syscall_after_brand + + _syscall_no_brand: movw %ax, T_SYSNUM(%r15) movzbl T_PRE_SYS(%r15), %ebx ORL_SYSCALLTRACE(%ebx) testl %ebx, %ebx jne _syscall_pre
*** 548,557 **** --- 571,582 ---- je 5f movq %r12, %r13 shrq $32, %r13 /* upper 32-bits into %edx */ movl %r12d, %r12d /* lower 32-bits into %eax */ 5: + + _syscall_after_brand: /* * Optimistically assume that there's no post-syscall * work to do. (This is to avoid having to call syscall_mstate() * with interrupts disabled) */
*** 793,807 **** --- 818,858 ---- ASSERT_LWPTOREGS(%r14, %rsp) incq %gs:CPU_STATS_SYS_SYSCALL /* + * If our lwp has an alternate system call handler, run that instead + * of the regular system call path. + */ + movq LWP_BRAND_SYSCALL(%r14), %rax + testq %rax, %rax + jz _syscall32_no_brand + + movb $LWP_SYS, LWP_STATE(%r14) + call *%rax + + /* + * If the alternate handler returns 0, we skip straight to the return + * to usermode. Otherwise, we resume regular system call processing. + */ + testl %eax, %eax + jz _syscall32_after_brand + + _syscall32_no_brand: + /* * Make some space for MAXSYSARGS (currently 8) 32-bit args placed * into 64-bit (long) arg slots, maintaining 16 byte alignment. Or * more succinctly: * * SA(MAXSYSARGS * sizeof (long)) == 64 + * + * Note, this space is used both to copy in the arguments from user + * land, but also to as part of the old UNIX style syscall_ap() method. + * syscall_entry expects that we do not change the values of this space + * that we give it. However, this means that when we end up in the more + * recent model of passing the arguments based on the calling + * conventions, we'll need to save an additional 16 bytes of stack. */ #define SYS_DROP 64 /* drop for args */ subq $SYS_DROP, %rsp movb $LWP_SYS, LWP_STATE(%r14) movq %r15, %rdi
*** 825,840 **** * Lots of ideas here, but they won't really help with bringup B-) * Correctness can't wait, performance can wait a little longer .. */ movq %rax, %rbx ! movl 0(%rsp), %edi ! movl 8(%rsp), %esi ! movl 0x10(%rsp), %edx ! movl 0x18(%rsp), %ecx ! movl 0x20(%rsp), %r8d ! movl 0x28(%rsp), %r9d call *SY_CALLC(%rbx) movq %rbp, %rsp /* pop the args */ --- 876,895 ---- * Lots of ideas here, but they won't really help with bringup B-) * Correctness can't wait, performance can wait a little longer .. */ movq %rax, %rbx ! movl 0x0(%rsp), %edi /* arg0 */ ! movl 0x8(%rsp), %esi /* arg1 */ ! movl 0x10(%rsp), %edx /* arg2 */ ! movl 0x38(%rsp), %eax /* arg7 load */ ! movl 0x18(%rsp), %ecx /* arg3 */ ! pushq %rax /* arg7 saved to stack */ ! movl 0x28(%rsp), %r8d /* arg4 */ ! movl 0x38(%rsp), %eax /* arg6 load */ ! movl 0x30(%rsp), %r9d /* arg5 */ ! pushq %rax /* arg6 saved to stack */ call *SY_CALLC(%rbx) movq %rbp, %rsp /* pop the args */
*** 848,857 **** --- 903,914 ---- */ movq %rax, %r13 shrq $32, %r13 /* upper 32-bits into %edx */ movl %eax, %r12d /* lower 32-bits into %eax */ + _syscall32_after_brand: + /* * Optimistically assume that there's no post-syscall * work to do. (This is to avoid having to call syscall_mstate() * with interrupts disabled) */
*** 1077,1095 **** call syscall_entry /* * Fetch the arguments copied onto the kernel stack and put * them in the right registers to invoke a C-style syscall handler. ! * %rax contains the handler address. */ movq %rax, %rbx ! movl 0(%rsp), %edi ! movl 8(%rsp), %esi ! movl 0x10(%rsp), %edx ! movl 0x18(%rsp), %ecx ! movl 0x20(%rsp), %r8d ! movl 0x28(%rsp), %r9d call *SY_CALLC(%rbx) movq %rbp, %rsp /* pop the args */ --- 1134,1157 ---- call syscall_entry /* * Fetch the arguments copied onto the kernel stack and put * them in the right registers to invoke a C-style syscall handler. ! * %rax contains the handler address. For the last two arguments, we ! * push them onto the stack -- we can't clobber the old arguments. */ movq %rax, %rbx ! movl 0x0(%rsp), %edi /* arg0 */ ! movl 0x8(%rsp), %esi /* arg1 */ ! movl 0x10(%rsp), %edx /* arg2 */ ! movl 0x38(%rsp), %eax /* arg7 load */ ! movl 0x18(%rsp), %ecx /* arg3 */ ! pushq %rax /* arg7 saved to stack */ ! movl 0x28(%rsp), %r8d /* arg4 */ ! movl 0x38(%rsp), %eax /* arg6 load */ ! movl 0x30(%rsp), %r9d /* arg5 */ ! pushq %rax /* arg6 saved to stack */ call *SY_CALLC(%rbx) movq %rbp, %rsp /* pop the args */
*** 1158,1168 **** --- 1220,1296 ---- SET_SIZE(_sys_sysenter_post_swapgs) SET_SIZE(brand_sys_sysenter) #endif /* __lint */ + #if defined(__lint) /* + * System call via an int80. This entry point is only used by the Linux + * application environment. Unlike the other entry points, there is no + * default action to take if no callback is registered for this process. + */ + void + sys_int80() + {} + + #else /* __lint */ + + ENTRY_NP(brand_sys_int80) + SWAPGS /* kernel gsbase */ + XPV_TRAP_POP + + /* + * We first attempt to call the "b_int80" handler from the "struct + * brand_mach_ops" for this brand. If no handler function is installed + * for this brand, the BRAND_CALLBACK() macro returns here and we + * check the lwp for a "lwp_brand_syscall" handler. + */ + BRAND_CALLBACK(BRAND_CB_INT80, BRAND_URET_FROM_INTR_STACK()) + + /* + * Check to see if this lwp provides "lwp_brand_syscall". If so, we + * will route this int80 through the regular system call handling path. + */ + movq %r15, %gs:CPU_RTMP_R15 + movq %gs:CPU_THREAD, %r15 + movq T_LWP(%r15), %r15 + movq LWP_BRAND_SYSCALL(%r15), %r15 + testq %r15, %r15 + movq %gs:CPU_RTMP_R15, %r15 + jnz nopop_syscall_int + + /* + * The brand provided neither a "b_int80", nor a "lwp_brand_syscall" + * function, and has thus opted out of handling this trap. + */ + SWAPGS /* user gsbase */ + jmp nopop_int80 + + ENTRY_NP(sys_int80) + /* + * We hit an int80, but this process isn't of a brand with an int80 + * handler. Bad process! Make it look as if the INT failed. + * Modify %rip to point before the INT, push the expected error + * code and fake a GP fault. Note on 64-bit hypervisor we need + * 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. + */ + XPV_TRAP_POP + nopop_int80: + subq $2, (%rsp) /* int insn 2-bytes */ + pushq $_CONST(_MUL(T_INT80, GATE_DESC_SIZE) + 2) + #if defined(__xpv) + push %r11 + push %rcx + #endif + jmp gptrap / GP fault + SET_SIZE(sys_int80) + SET_SIZE(brand_sys_int80) + #endif /* __lint */ + + + /* * This is the destination of the "int $T_SYSCALLINT" interrupt gate, used by * the generic i386 libc to do system calls. We do a small amount of setup * before jumping into the existing sys_syscall32 path. */ #if defined(__lint)