17c478bd9Sstevel@tonic-gate/* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 59acbbeafSnn35248 * Common Development and Distribution License (the "License"). 69acbbeafSnn35248 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate/* 22*eb5a5c78SSurya Prakki * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ 267c478bd9Sstevel@tonic-gate/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ 277c478bd9Sstevel@tonic-gate/* All Rights Reserved */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate/* Copyright (c) 1987, 1988 Microsoft Corporation */ 307c478bd9Sstevel@tonic-gate/* All Rights Reserved */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h> 337c478bd9Sstevel@tonic-gate#include <sys/asm_misc.h> 347c478bd9Sstevel@tonic-gate#include <sys/regset.h> 357c478bd9Sstevel@tonic-gate#include <sys/psw.h> 367c478bd9Sstevel@tonic-gate#include <sys/x86_archext.h> 379acbbeafSnn35248#include <sys/machbrand.h> 38ae115bc7Smrj#include <sys/privregs.h> 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate#if defined(__lint) 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate#include <sys/types.h> 437c478bd9Sstevel@tonic-gate#include <sys/thread.h> 447c478bd9Sstevel@tonic-gate#include <sys/systm.h> 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate#else /* __lint */ 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate#include <sys/segments.h> 497c478bd9Sstevel@tonic-gate#include <sys/pcb.h> 507c478bd9Sstevel@tonic-gate#include <sys/trap.h> 517c478bd9Sstevel@tonic-gate#include <sys/ftrace.h> 527c478bd9Sstevel@tonic-gate#include <sys/traptrace.h> 537c478bd9Sstevel@tonic-gate#include <sys/clock.h> 547c478bd9Sstevel@tonic-gate#include <sys/panic.h> 557c478bd9Sstevel@tonic-gate#include "assym.h" 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate#endif /* __lint */ 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate/* 607c478bd9Sstevel@tonic-gate * We implement two flavours of system call entry points 617c478bd9Sstevel@tonic-gate * 627c478bd9Sstevel@tonic-gate * - {int,lcall}/iret (i386) 637c478bd9Sstevel@tonic-gate * - sysenter/sysexit (Pentium II and beyond) 647c478bd9Sstevel@tonic-gate * 657c478bd9Sstevel@tonic-gate * The basic pattern used in the handlers is to check to see if we can 667c478bd9Sstevel@tonic-gate * do fast (simple) version of the system call; if we can't we use various 677c478bd9Sstevel@tonic-gate * C routines that handle corner cases and debugging. 687c478bd9Sstevel@tonic-gate * 697c478bd9Sstevel@tonic-gate * To reduce the amount of assembler replication, yet keep the system call 707c478bd9Sstevel@tonic-gate * implementations vaguely comprehensible, the common code in the body 717c478bd9Sstevel@tonic-gate * of the handlers is broken up into a set of preprocessor definitions 727c478bd9Sstevel@tonic-gate * below. 737c478bd9Sstevel@tonic-gate */ 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate/* 767c478bd9Sstevel@tonic-gate * When we have SYSCALLTRACE defined, we sneak an extra 777c478bd9Sstevel@tonic-gate * predicate into a couple of tests. 787c478bd9Sstevel@tonic-gate */ 797c478bd9Sstevel@tonic-gate#if defined(SYSCALLTRACE) 807c478bd9Sstevel@tonic-gate#define ORL_SYSCALLTRACE(r32) \ 817c478bd9Sstevel@tonic-gate orl syscalltrace, r32 827c478bd9Sstevel@tonic-gate#else 837c478bd9Sstevel@tonic-gate#define ORL_SYSCALLTRACE(r32) 847c478bd9Sstevel@tonic-gate#endif 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate/* 877c478bd9Sstevel@tonic-gate * This check is false whenever we want to go fast i.e. 887c478bd9Sstevel@tonic-gate * 897c478bd9Sstevel@tonic-gate * if (code >= NSYSCALL || 907c478bd9Sstevel@tonic-gate * t->t_pre_sys || (t->t_proc_flag & TP_WATCHPT) != 0) 917c478bd9Sstevel@tonic-gate * do full version 927c478bd9Sstevel@tonic-gate * #ifdef SYSCALLTRACE 937c478bd9Sstevel@tonic-gate * if (syscalltrace) 947c478bd9Sstevel@tonic-gate * do full version 957c478bd9Sstevel@tonic-gate * #endif 967c478bd9Sstevel@tonic-gate * 977c478bd9Sstevel@tonic-gate * Preconditions: 987c478bd9Sstevel@tonic-gate * - t curthread 997c478bd9Sstevel@tonic-gate * - code contains the syscall number 1007c478bd9Sstevel@tonic-gate * Postconditions: 1017c478bd9Sstevel@tonic-gate * - %ecx and %edi are smashed 1027c478bd9Sstevel@tonic-gate * - condition code flag ZF is cleared if pre-sys is too complex 1037c478bd9Sstevel@tonic-gate */ 1047c478bd9Sstevel@tonic-gate#define CHECK_PRESYS_NE(t, code) \ 1057c478bd9Sstevel@tonic-gate movzbl T_PRE_SYS(t), %edi; \ 1067c478bd9Sstevel@tonic-gate movzwl T_PROC_FLAG(t), %ecx; \ 1077c478bd9Sstevel@tonic-gate andl $TP_WATCHPT, %ecx; \ 1087c478bd9Sstevel@tonic-gate orl %ecx, %edi; \ 1097c478bd9Sstevel@tonic-gate cmpl $NSYSCALL, code; \ 1107c478bd9Sstevel@tonic-gate setae %cl; \ 1117c478bd9Sstevel@tonic-gate movzbl %cl, %ecx; \ 1127c478bd9Sstevel@tonic-gate orl %ecx, %edi; \ 1137c478bd9Sstevel@tonic-gate ORL_SYSCALLTRACE(%edi) 1147c478bd9Sstevel@tonic-gate 1159acbbeafSnn35248/* 11665488c97S * Check if a brand_mach_ops callback is defined for the specified callback_id 11706b6cf06S * type. If so invoke it with the user's %gs value loaded and the following 11865488c97S * data on the stack: 1199acbbeafSnn35248 * -------------------------------------- 12006b6cf06S * | user's %ss | 12106b6cf06S * | | user's %esp | 12206b6cf06S * | | EFLAGS register | 12306b6cf06S * | | user's %cs | 12406b6cf06S * | | user's %eip (user return address) | 12506b6cf06S * | | 'scratch space' | 12606b6cf06S * | | user's %ebx | 12706b6cf06S * | | user's %gs selector | 12806b6cf06S * v | lwp pointer | 1299acbbeafSnn35248 * | callback wrapper return addr | 1309acbbeafSnn35248 * -------------------------------------- 1319acbbeafSnn35248 * 1329acbbeafSnn35248 * If the brand code returns, we assume that we are meant to execute the 1339acbbeafSnn35248 * normal system call path. 13406b6cf06S * 13506b6cf06S * The interface to the brand callbacks on the 32-bit kernel assumes %ebx 13606b6cf06S * is available as a scratch register within the callback. If the callback 13706b6cf06S * returns within the kernel then this macro will restore %ebx. If the 13806b6cf06S * callback is going to return directly to userland then it should restore 13906b6cf06S * %ebx before returning to userland. 1409acbbeafSnn35248 */ 1419acbbeafSnn35248#define BRAND_CALLBACK(callback_id) \ 1429acbbeafSnn35248 subl $4, %esp /* save some scratch space */ ;\ 1439acbbeafSnn35248 pushl %ebx /* save %ebx to use for scratch */ ;\ 1449acbbeafSnn35248 pushl %gs /* save the user %gs */ ;\ 1459acbbeafSnn35248 movl $KGS_SEL, %ebx ;\ 1465f8e1617Snn35248 movw %bx, %gs /* switch to the kernel's %gs */ ;\ 1479acbbeafSnn35248 movl %gs:CPU_THREAD, %ebx /* load the thread pointer */ ;\ 1489acbbeafSnn35248 movl T_LWP(%ebx), %ebx /* load the lwp pointer */ ;\ 149c7cf3afeSsp92102 pushl %ebx /* push the lwp pointer */ ;\ 1509acbbeafSnn35248 movl LWP_PROCP(%ebx), %ebx /* load the proc pointer */ ;\ 1519acbbeafSnn35248 movl P_BRAND(%ebx), %ebx /* load the brand pointer */ ;\ 1529acbbeafSnn35248 movl B_MACHOPS(%ebx), %ebx /* load the machops pointer */ ;\ 1539acbbeafSnn35248 movl _CONST(_MUL(callback_id, CPTRSIZE))(%ebx), %ebx ;\ 1549acbbeafSnn35248 cmpl $0, %ebx ;\ 1559acbbeafSnn35248 je 1f ;\ 15606b6cf06S movl %ebx, 12(%esp) /* save callback to scratch */ ;\ 15706b6cf06S movl 4(%esp), %ebx /* grab the user %gs */ ;\ 1585f8e1617Snn35248 movw %bx, %gs /* restore the user %gs */ ;\ 15906b6cf06S call *12(%esp) /* call callback in scratch */ ;\ 16006b6cf06S1: movl 4(%esp), %ebx /* restore user %gs (re-do if */ ;\ 16106b6cf06S movw %bx, %gs /* branch due to no callback) */ ;\ 16206b6cf06S movl 8(%esp), %ebx /* restore user's %ebx */ ;\ 16306b6cf06S addl $16, %esp /* restore stack ptr */ 1649acbbeafSnn35248 1657c478bd9Sstevel@tonic-gate#define MSTATE_TRANSITION(from, to) \ 1667c478bd9Sstevel@tonic-gate pushl $to; \ 1677c478bd9Sstevel@tonic-gate pushl $from; \ 1687c478bd9Sstevel@tonic-gate call syscall_mstate; \ 1697c478bd9Sstevel@tonic-gate addl $0x8, %esp 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate/* 1727c478bd9Sstevel@tonic-gate * aka CPU_STATS_ADDQ(CPU, sys.syscall, 1) 1737c478bd9Sstevel@tonic-gate * This must be called with interrupts or preemption disabled. 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate#define CPU_STATS_SYS_SYSCALL_INC \ 1767c478bd9Sstevel@tonic-gate addl $1, %gs:CPU_STATS_SYS_SYSCALL; \ 1777c478bd9Sstevel@tonic-gate adcl $0, %gs:CPU_STATS_SYS_SYSCALL+4; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate#if !defined(__lint) 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate/* 1827c478bd9Sstevel@tonic-gate * ASSERT(lwptoregs(lwp) == rp); 1837c478bd9Sstevel@tonic-gate * 1847c478bd9Sstevel@tonic-gate * this may seem obvious, but very odd things happen if this 1857c478bd9Sstevel@tonic-gate * assertion is false 1867c478bd9Sstevel@tonic-gate * 1877c478bd9Sstevel@tonic-gate * Preconditions: 1887c478bd9Sstevel@tonic-gate * -none- 1897c478bd9Sstevel@tonic-gate * Postconditions (if assertion is true): 1907c478bd9Sstevel@tonic-gate * %esi and %edi are smashed 1917c478bd9Sstevel@tonic-gate */ 1927c478bd9Sstevel@tonic-gate#if defined(DEBUG) 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate__lwptoregs_msg: 195613b2871SRichard Bean .string "syscall_asm.s:%d lwptoregs(%p) [%p] != rp [%p]" 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate#define ASSERT_LWPTOREGS(t, rp) \ 1987c478bd9Sstevel@tonic-gate movl T_LWP(t), %esi; \ 1997c478bd9Sstevel@tonic-gate movl LWP_REGS(%esi), %edi; \ 2007c478bd9Sstevel@tonic-gate cmpl rp, %edi; \ 2017c478bd9Sstevel@tonic-gate je 7f; \ 2027c478bd9Sstevel@tonic-gate pushl rp; \ 2037c478bd9Sstevel@tonic-gate pushl %edi; \ 2047c478bd9Sstevel@tonic-gate pushl %esi; \ 2057c478bd9Sstevel@tonic-gate pushl $__LINE__; \ 2067c478bd9Sstevel@tonic-gate pushl $__lwptoregs_msg; \ 2077c478bd9Sstevel@tonic-gate call panic; \ 2087c478bd9Sstevel@tonic-gate7: 2097c478bd9Sstevel@tonic-gate#else 2107c478bd9Sstevel@tonic-gate#define ASSERT_LWPTOREGS(t, rp) 2117c478bd9Sstevel@tonic-gate#endif 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate#endif /* __lint */ 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate/* 2167c478bd9Sstevel@tonic-gate * This is an assembler version of this fragment: 2177c478bd9Sstevel@tonic-gate * 2187c478bd9Sstevel@tonic-gate * lwp->lwp_state = LWP_SYS; 2197c478bd9Sstevel@tonic-gate * lwp->lwp_ru.sysc++; 2207c478bd9Sstevel@tonic-gate * lwp->lwp_eosys = NORMALRETURN; 2217c478bd9Sstevel@tonic-gate * lwp->lwp_ap = argp; 2227c478bd9Sstevel@tonic-gate * 2237c478bd9Sstevel@tonic-gate * Preconditions: 2247c478bd9Sstevel@tonic-gate * -none- 2257c478bd9Sstevel@tonic-gate * Postconditions: 2267c478bd9Sstevel@tonic-gate * -none- 2277c478bd9Sstevel@tonic-gate */ 2287c478bd9Sstevel@tonic-gate#define SET_LWP(lwp, argp) \ 2297c478bd9Sstevel@tonic-gate movb $LWP_SYS, LWP_STATE(lwp); \ 2307c478bd9Sstevel@tonic-gate addl $1, LWP_RU_SYSC(lwp); \ 2317c478bd9Sstevel@tonic-gate adcl $0, LWP_RU_SYSC+4(lwp); \ 2327c478bd9Sstevel@tonic-gate movb $NORMALRETURN, LWP_EOSYS(lwp); \ 2337c478bd9Sstevel@tonic-gate movl argp, LWP_AP(lwp) 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate/* 2367c478bd9Sstevel@tonic-gate * Set up the thread, lwp, find the handler, and copy 2377c478bd9Sstevel@tonic-gate * in the arguments from userland to the kernel stack. 2387c478bd9Sstevel@tonic-gate * 2397c478bd9Sstevel@tonic-gate * Preconditions: 2407c478bd9Sstevel@tonic-gate * - %eax contains the syscall number 2417c478bd9Sstevel@tonic-gate * Postconditions: 2427c478bd9Sstevel@tonic-gate * - %eax contains a pointer to the sysent structure 2437c478bd9Sstevel@tonic-gate * - %ecx is zeroed 2447c478bd9Sstevel@tonic-gate * - %esi, %edi are smashed 2457c478bd9Sstevel@tonic-gate * - %esp is SYS_DROPped ready for the syscall 2467c478bd9Sstevel@tonic-gate */ 2477c478bd9Sstevel@tonic-gate#define SIMPLE_SYSCALL_PRESYS(t, faultlabel) \ 2487c478bd9Sstevel@tonic-gate movl T_LWP(t), %esi; \ 2497c478bd9Sstevel@tonic-gate movw %ax, T_SYSNUM(t); \ 2507c478bd9Sstevel@tonic-gate subl $SYS_DROP, %esp; \ 2517c478bd9Sstevel@tonic-gate shll $SYSENT_SIZE_SHIFT, %eax; \ 2527c478bd9Sstevel@tonic-gate SET_LWP(%esi, %esp); \ 2537c478bd9Sstevel@tonic-gate leal sysent(%eax), %eax; \ 2547c478bd9Sstevel@tonic-gate movzbl SY_NARG(%eax), %ecx; \ 2557c478bd9Sstevel@tonic-gate testl %ecx, %ecx; \ 2567c478bd9Sstevel@tonic-gate jz 4f; \ 2577c478bd9Sstevel@tonic-gate movl %esp, %edi; \ 2587c478bd9Sstevel@tonic-gate movl SYS_DROP + REGOFF_UESP(%esp), %esi; \ 2597c478bd9Sstevel@tonic-gate movl $faultlabel, T_LOFAULT(t); \ 2607c478bd9Sstevel@tonic-gate addl $4, %esi; \ 2617c478bd9Sstevel@tonic-gate rep; \ 2627c478bd9Sstevel@tonic-gate smovl; \ 2637c478bd9Sstevel@tonic-gate movl %ecx, T_LOFAULT(t); \ 2647c478bd9Sstevel@tonic-gate4: 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate/* 2677c478bd9Sstevel@tonic-gate * Check to see if a simple return is possible i.e. 2687c478bd9Sstevel@tonic-gate * 2697c478bd9Sstevel@tonic-gate * if ((t->t_post_sys_ast | syscalltrace) != 0) 2707c478bd9Sstevel@tonic-gate * do full version; 2717c478bd9Sstevel@tonic-gate * 2727c478bd9Sstevel@tonic-gate * Preconditions: 2737c478bd9Sstevel@tonic-gate * - t is curthread 2747c478bd9Sstevel@tonic-gate * Postconditions: 2757c478bd9Sstevel@tonic-gate * - condition code NE is set if post-sys is too complex 2767c478bd9Sstevel@tonic-gate * - rtmp is zeroed if it isn't (we rely on this!) 2777c478bd9Sstevel@tonic-gate */ 2787c478bd9Sstevel@tonic-gate#define CHECK_POSTSYS_NE(t, rtmp) \ 2797c478bd9Sstevel@tonic-gate xorl rtmp, rtmp; \ 2807c478bd9Sstevel@tonic-gate ORL_SYSCALLTRACE(rtmp); \ 2817c478bd9Sstevel@tonic-gate orl T_POST_SYS_AST(t), rtmp; \ 2827c478bd9Sstevel@tonic-gate cmpl $0, rtmp 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate/* 2857c478bd9Sstevel@tonic-gate * Fix up the lwp, thread, and eflags for a successful return 2867c478bd9Sstevel@tonic-gate * 2877c478bd9Sstevel@tonic-gate * Preconditions: 2887c478bd9Sstevel@tonic-gate * - zwreg contains zero 2897c478bd9Sstevel@tonic-gate * Postconditions: 2907c478bd9Sstevel@tonic-gate * - %esp has been unSYS_DROPped 2917c478bd9Sstevel@tonic-gate * - %esi is smashed (points to lwp) 2927c478bd9Sstevel@tonic-gate */ 2937c478bd9Sstevel@tonic-gate#define SIMPLE_SYSCALL_POSTSYS(t, zwreg) \ 2947c478bd9Sstevel@tonic-gate movl T_LWP(t), %esi; \ 2957c478bd9Sstevel@tonic-gate addl $SYS_DROP, %esp; \ 2967c478bd9Sstevel@tonic-gate movw zwreg, T_SYSNUM(t); \ 2977c478bd9Sstevel@tonic-gate movb $LWP_USER, LWP_STATE(%esi); \ 2987c478bd9Sstevel@tonic-gate andb $_CONST(0xffff - PS_C), REGOFF_EFL(%esp) 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate/* 3017c478bd9Sstevel@tonic-gate * System call handler. This is the destination of both the call 3027c478bd9Sstevel@tonic-gate * gate (lcall 0x27) _and_ the interrupt gate (int 0x91). For our purposes, 3037c478bd9Sstevel@tonic-gate * there are two significant differences between an interrupt gate and a call 3047c478bd9Sstevel@tonic-gate * gate: 3057c478bd9Sstevel@tonic-gate * 3067c478bd9Sstevel@tonic-gate * 1) An interrupt gate runs the handler with interrupts disabled, whereas a 3077c478bd9Sstevel@tonic-gate * call gate runs the handler with whatever EFLAGS settings were in effect at 3087c478bd9Sstevel@tonic-gate * the time of the call. 3097c478bd9Sstevel@tonic-gate * 3107c478bd9Sstevel@tonic-gate * 2) An interrupt gate pushes the contents of the EFLAGS register at the time 3117c478bd9Sstevel@tonic-gate * of the interrupt onto the stack, whereas a call gate does not. 3127c478bd9Sstevel@tonic-gate * 3137c478bd9Sstevel@tonic-gate * Because we use the following code sequence to handle system calls made from 3147c478bd9Sstevel@tonic-gate * _both_ a call gate _and_ an interrupt gate, these two differences must be 3157c478bd9Sstevel@tonic-gate * respected. In regards to number 1) above, the handler must ensure that a sane 3167c478bd9Sstevel@tonic-gate * EFLAGS snapshot is stored on the stack so that when the kernel returns back 3177c478bd9Sstevel@tonic-gate * to the user via iret (which returns to user with the EFLAGS value saved on 3187c478bd9Sstevel@tonic-gate * the stack), interrupts are re-enabled. 3197c478bd9Sstevel@tonic-gate * 3207c478bd9Sstevel@tonic-gate * In regards to number 2) above, the handler must always put a current snapshot 3217c478bd9Sstevel@tonic-gate * of EFLAGS onto the stack in the appropriate place. If we came in via an 3227c478bd9Sstevel@tonic-gate * interrupt gate, we will be clobbering the EFLAGS value that was pushed by 3237c478bd9Sstevel@tonic-gate * the interrupt gate. This is OK, as the only bit that was changed by the 3247c478bd9Sstevel@tonic-gate * hardware was the IE (interrupt enable) bit, which for an interrupt gate is 3257c478bd9Sstevel@tonic-gate * now off. If we were to do nothing, the stack would contain an EFLAGS with 3267c478bd9Sstevel@tonic-gate * IE off, resulting in us eventually returning back to the user with interrupts 3277c478bd9Sstevel@tonic-gate * disabled. The solution is to turn on the IE bit in the EFLAGS value saved on 3287c478bd9Sstevel@tonic-gate * the stack. 3297c478bd9Sstevel@tonic-gate * 3307c478bd9Sstevel@tonic-gate * Another subtlety which deserves mention is the difference between the two 3317c478bd9Sstevel@tonic-gate * descriptors. The call gate descriptor is set to instruct the hardware to copy 3327c478bd9Sstevel@tonic-gate * one parameter from the user stack to the kernel stack, whereas the interrupt 3337c478bd9Sstevel@tonic-gate * gate descriptor doesn't use the parameter passing mechanism at all. The 3347c478bd9Sstevel@tonic-gate * kernel doesn't actually use the parameter that is copied by the hardware; the 3357c478bd9Sstevel@tonic-gate * only reason it does this is so that there is a space on the stack large 3367c478bd9Sstevel@tonic-gate * enough to hold an EFLAGS register value, which happens to be in the correct 3377c478bd9Sstevel@tonic-gate * place for use by iret when we go back to userland. How convenient. 3387c478bd9Sstevel@tonic-gate * 3397c478bd9Sstevel@tonic-gate * Stack frame description in syscall() and callees. 3407c478bd9Sstevel@tonic-gate * 3417c478bd9Sstevel@tonic-gate * |------------| 3427c478bd9Sstevel@tonic-gate * | regs | +(8*4)+4 registers 3437c478bd9Sstevel@tonic-gate * |------------| 3447c478bd9Sstevel@tonic-gate * | 8 args | <- %esp MAXSYSARGS (currently 8) arguments 3457c478bd9Sstevel@tonic-gate * |------------| 3467c478bd9Sstevel@tonic-gate * 3477c478bd9Sstevel@tonic-gate */ 3487c478bd9Sstevel@tonic-gate#define SYS_DROP _CONST(_MUL(MAXSYSARGS, 4)) 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate#if defined(__lint) 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 3537c478bd9Sstevel@tonic-gatevoid 3547c478bd9Sstevel@tonic-gatesys_call() 3557c478bd9Sstevel@tonic-gate{} 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gatevoid 3587c478bd9Sstevel@tonic-gate_allsyscalls() 3597c478bd9Sstevel@tonic-gate{} 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gatesize_t _allsyscalls_size; 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate#else /* __lint */ 3647c478bd9Sstevel@tonic-gate 3659acbbeafSnn35248 ENTRY_NP2(brand_sys_call, _allsyscalls) 3669acbbeafSnn35248 BRAND_CALLBACK(BRAND_CB_SYSCALL) 3677c478bd9Sstevel@tonic-gate 3689acbbeafSnn35248 ALTENTRY(sys_call) 3697c478bd9Sstevel@tonic-gate / on entry eax = system call number 3709acbbeafSnn35248 3717c478bd9Sstevel@tonic-gate / set up the stack to look as in reg.h 3727c478bd9Sstevel@tonic-gate subl $8, %esp / pad the stack with ERRCODE and TRAPNO 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate SYSCALL_PUSH 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE 3777c478bd9Sstevel@tonic-gate TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_SYSCALL) / Uses labels "8" and "9" 3787c478bd9Sstevel@tonic-gate TRACE_REGS(%edi, %esp, %ebx, %ecx) / Uses label "9" 3797c478bd9Sstevel@tonic-gate pushl %eax 3807c478bd9Sstevel@tonic-gate TRACE_STAMP(%edi) / Clobbers %eax, %edx, uses "9" 3817c478bd9Sstevel@tonic-gate popl %eax 3827c478bd9Sstevel@tonic-gate movl %eax, TTR_SYSNUM(%edi) 3837c478bd9Sstevel@tonic-gate#endif 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate_watch_do_syscall: 3867c478bd9Sstevel@tonic-gate movl %esp, %ebp 3877c478bd9Sstevel@tonic-gate 388ae115bc7Smrj / Interrupts may be enabled here, so we must make sure this thread 389ae115bc7Smrj / doesn't migrate off the CPU while it updates the CPU stats. 390ae115bc7Smrj / 391ae115bc7Smrj / XXX This is only true if we got here via call gate thru the LDT for 392ae115bc7Smrj / old style syscalls. Perhaps this preempt++-- will go away soon? 393ae115bc7Smrj movl %gs:CPU_THREAD, %ebx 394ae115bc7Smrj addb $1, T_PREEMPT(%ebx) 395ae115bc7Smrj CPU_STATS_SYS_SYSCALL_INC 396ae115bc7Smrj subb $1, T_PREEMPT(%ebx) 397ae115bc7Smrj 398ae115bc7Smrj ENABLE_INTR_FLAGS 399ae115bc7Smrj 4007c478bd9Sstevel@tonic-gate pushl %eax / preserve across mstate call 4017c478bd9Sstevel@tonic-gate MSTATE_TRANSITION(LMS_USER, LMS_SYSTEM) 4027c478bd9Sstevel@tonic-gate popl %eax 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate movl %gs:CPU_THREAD, %ebx 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate ASSERT_LWPTOREGS(%ebx, %esp) 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate CHECK_PRESYS_NE(%ebx, %eax) 4097c478bd9Sstevel@tonic-gate jne _full_syscall_presys 4107c478bd9Sstevel@tonic-gate SIMPLE_SYSCALL_PRESYS(%ebx, _syscall_fault) 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate_syslcall_call: 4137c478bd9Sstevel@tonic-gate call *SY_CALLC(%eax) 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate_syslcall_done: 4167c478bd9Sstevel@tonic-gate CHECK_POSTSYS_NE(%ebx, %ecx) 4177c478bd9Sstevel@tonic-gate jne _full_syscall_postsys 4187c478bd9Sstevel@tonic-gate SIMPLE_SYSCALL_POSTSYS(%ebx, %cx) 4197c478bd9Sstevel@tonic-gate movl %eax, REGOFF_EAX(%esp) 4207c478bd9Sstevel@tonic-gate movl %edx, REGOFF_EDX(%esp) 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate MSTATE_TRANSITION(LMS_SYSTEM, LMS_USER) 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate / 4257c478bd9Sstevel@tonic-gate / get back via iret 4267c478bd9Sstevel@tonic-gate / 427ae115bc7Smrj CLI(%edx) 428ae115bc7Smrj jmp sys_rtt_syscall 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate_full_syscall_presys: 4317c478bd9Sstevel@tonic-gate movl T_LWP(%ebx), %esi 4327c478bd9Sstevel@tonic-gate subl $SYS_DROP, %esp 4337c478bd9Sstevel@tonic-gate movb $LWP_SYS, LWP_STATE(%esi) 4347c478bd9Sstevel@tonic-gate pushl %esp 4357c478bd9Sstevel@tonic-gate pushl %ebx 4367c478bd9Sstevel@tonic-gate call syscall_entry 4377c478bd9Sstevel@tonic-gate addl $8, %esp 4387c478bd9Sstevel@tonic-gate jmp _syslcall_call 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate_full_syscall_postsys: 4417c478bd9Sstevel@tonic-gate addl $SYS_DROP, %esp 4427c478bd9Sstevel@tonic-gate pushl %edx 4437c478bd9Sstevel@tonic-gate pushl %eax 4447c478bd9Sstevel@tonic-gate pushl %ebx 4457c478bd9Sstevel@tonic-gate call syscall_exit 4467c478bd9Sstevel@tonic-gate addl $12, %esp 4477c478bd9Sstevel@tonic-gate MSTATE_TRANSITION(LMS_SYSTEM, LMS_USER) 448ae115bc7Smrj jmp _sys_rtt 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate_syscall_fault: 4517c478bd9Sstevel@tonic-gate push $0xe / EFAULT 4527c478bd9Sstevel@tonic-gate call set_errno 4537c478bd9Sstevel@tonic-gate addl $4, %esp 4547c478bd9Sstevel@tonic-gate xorl %eax, %eax / fake syscall_err() 4557c478bd9Sstevel@tonic-gate xorl %edx, %edx 4567c478bd9Sstevel@tonic-gate jmp _syslcall_done 4577c478bd9Sstevel@tonic-gate SET_SIZE(sys_call) 4589acbbeafSnn35248 SET_SIZE(brand_sys_call) 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate#endif /* __lint */ 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate/* 4637c478bd9Sstevel@tonic-gate * System call handler via the sysenter instruction 4647c478bd9Sstevel@tonic-gate * 4657c478bd9Sstevel@tonic-gate * Here's how syscall entry usually works (see sys_call for details). 4667c478bd9Sstevel@tonic-gate * 4677c478bd9Sstevel@tonic-gate * There, the caller (lcall or int) in userland has arranged that: 4687c478bd9Sstevel@tonic-gate * 4697c478bd9Sstevel@tonic-gate * - %eax contains the syscall number 4707c478bd9Sstevel@tonic-gate * - the user stack contains the args to the syscall 4717c478bd9Sstevel@tonic-gate * 4727c478bd9Sstevel@tonic-gate * Normally the lcall instruction into the call gate causes the processor 4737c478bd9Sstevel@tonic-gate * to push %ss, %esp, <top-of-stack>, %cs, %eip onto the kernel stack. 4747c478bd9Sstevel@tonic-gate * The sys_call handler then leaves space for r_trapno and r_err, and 4757c478bd9Sstevel@tonic-gate * pusha's {%eax, %ecx, %edx, %ebx, %esp, %ebp, %esi, %edi}, followed 4767c478bd9Sstevel@tonic-gate * by %ds, %es, %fs and %gs to capture a 'struct regs' on the stack. 4777c478bd9Sstevel@tonic-gate * Then the kernel sets %ds, %es and %gs to kernel selectors, and finally 4787c478bd9Sstevel@tonic-gate * extracts %efl and puts it into r_efl (which happens to live at the offset 4797c478bd9Sstevel@tonic-gate * that <top-of-stack> was copied into). Note that the value in r_efl has 4807c478bd9Sstevel@tonic-gate * the IF (interrupt enable) flag turned on. (The int instruction into the 4817c478bd9Sstevel@tonic-gate * interrupt gate does essentially the same thing, only instead of 4827c478bd9Sstevel@tonic-gate * <top-of-stack> we get eflags - see comment above.) 4837c478bd9Sstevel@tonic-gate * 4847c478bd9Sstevel@tonic-gate * In the sysenter case, things are a lot more primitive. 4857c478bd9Sstevel@tonic-gate * 4867c478bd9Sstevel@tonic-gate * The caller in userland has arranged that: 4877c478bd9Sstevel@tonic-gate * 4887c478bd9Sstevel@tonic-gate * - %eax contains the syscall number 4897c478bd9Sstevel@tonic-gate * - %ecx contains the user %esp 4907c478bd9Sstevel@tonic-gate * - %edx contains the return %eip 4917c478bd9Sstevel@tonic-gate * - the user stack contains the args to the syscall 4927c478bd9Sstevel@tonic-gate * 4937c478bd9Sstevel@tonic-gate * e.g. 4947c478bd9Sstevel@tonic-gate * <args on the stack> 4957c478bd9Sstevel@tonic-gate * mov $SYS_callnum, %eax 4967c478bd9Sstevel@tonic-gate * mov $1f, %edx / return %eip 4977c478bd9Sstevel@tonic-gate * mov %esp, %ecx / return %esp 4987c478bd9Sstevel@tonic-gate * sysenter 4997c478bd9Sstevel@tonic-gate * 1: 5007c478bd9Sstevel@tonic-gate * 5017c478bd9Sstevel@tonic-gate * Hardware and (privileged) initialization code have arranged that by 5027c478bd9Sstevel@tonic-gate * the time the sysenter instructions completes: 5037c478bd9Sstevel@tonic-gate * 5047c478bd9Sstevel@tonic-gate * - %eip is pointing to sys_sysenter (below). 5057c478bd9Sstevel@tonic-gate * - %cs and %ss are set to kernel text and stack (data) selectors. 5067c478bd9Sstevel@tonic-gate * - %esp is pointing at the lwp's stack 5077c478bd9Sstevel@tonic-gate * - Interrupts have been disabled. 5087c478bd9Sstevel@tonic-gate * 5097c478bd9Sstevel@tonic-gate * The task for the sysenter handler is: 5107c478bd9Sstevel@tonic-gate * 5117c478bd9Sstevel@tonic-gate * - recreate the same regs structure on the stack and the same 5127c478bd9Sstevel@tonic-gate * kernel state as if we'd come in on an lcall 5137c478bd9Sstevel@tonic-gate * - do the normal work of a syscall 5147c478bd9Sstevel@tonic-gate * - execute the system call epilogue, use sysexit to return to userland. 5157c478bd9Sstevel@tonic-gate * 5167c478bd9Sstevel@tonic-gate * Note that we are unable to return both "rvals" to userland with this 5177c478bd9Sstevel@tonic-gate * call, as %edx is used by the sysexit instruction. 5189acbbeafSnn35248 * 5199acbbeafSnn35248 * One final complication in this routine is its interaction with 5209acbbeafSnn35248 * single-stepping in a debugger. For most of the system call mechanisms, 5219acbbeafSnn35248 * the CPU automatically clears the single-step flag before we enter the 5229acbbeafSnn35248 * kernel. The sysenter mechanism does not clear the flag, so a user 5239acbbeafSnn35248 * single-stepping through a libc routine may suddenly find him/herself 5249acbbeafSnn35248 * single-stepping through the kernel. To detect this, kmdb compares the 5259acbbeafSnn35248 * trap %pc to the [brand_]sys_enter addresses on each single-step trap. 5269acbbeafSnn35248 * If it finds that we have single-stepped to a sysenter entry point, it 5279acbbeafSnn35248 * explicitly clears the flag and executes the sys_sysenter routine. 5289acbbeafSnn35248 * 5299acbbeafSnn35248 * One final complication in this final complication is the fact that we 5309acbbeafSnn35248 * have two different entry points for sysenter: brand_sys_sysenter and 5319acbbeafSnn35248 * sys_sysenter. If we enter at brand_sys_sysenter and start single-stepping 5329acbbeafSnn35248 * through the kernel with kmdb, we will eventually hit the instruction at 5339acbbeafSnn35248 * sys_sysenter. kmdb cannot distinguish between that valid single-step 5349acbbeafSnn35248 * and the undesirable one mentioned above. To avoid this situation, we 5359acbbeafSnn35248 * simply add a jump over the instruction at sys_sysenter to make it 5369acbbeafSnn35248 * impossible to single-step to it. 5377c478bd9Sstevel@tonic-gate */ 5387c478bd9Sstevel@tonic-gate#if defined(__lint) 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gatevoid 5417c478bd9Sstevel@tonic-gatesys_sysenter() 5427c478bd9Sstevel@tonic-gate{} 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate#else /* __lint */ 5457c478bd9Sstevel@tonic-gate 5469acbbeafSnn35248 ENTRY_NP(brand_sys_sysenter) 5479acbbeafSnn35248 pushl %edx 5489acbbeafSnn35248 BRAND_CALLBACK(BRAND_CB_SYSENTER) 5499acbbeafSnn35248 popl %edx 5509acbbeafSnn35248 /* 5519acbbeafSnn35248 * Jump over sys_sysenter to allow single-stepping as described 5529acbbeafSnn35248 * above. 5539acbbeafSnn35248 */ 5549acbbeafSnn35248 ja 1f 5559acbbeafSnn35248 5569acbbeafSnn35248 ALTENTRY(sys_sysenter) 5579acbbeafSnn35248 nop 5589acbbeafSnn352481: 5597c478bd9Sstevel@tonic-gate / 5607c478bd9Sstevel@tonic-gate / do what the call gate would've done to the stack .. 5617c478bd9Sstevel@tonic-gate / 5627c478bd9Sstevel@tonic-gate pushl $UDS_SEL / (really %ss, but it's the same ..) 5637c478bd9Sstevel@tonic-gate pushl %ecx / userland makes this a copy of %esp 5647c478bd9Sstevel@tonic-gate pushfl 5657c478bd9Sstevel@tonic-gate orl $PS_IE, (%esp) / turn interrupts on when we return to user 5667c478bd9Sstevel@tonic-gate pushl $UCS_SEL 5677c478bd9Sstevel@tonic-gate pushl %edx / userland makes this a copy of %eip 5687c478bd9Sstevel@tonic-gate / 5697c478bd9Sstevel@tonic-gate / done. finish building the stack frame 5707c478bd9Sstevel@tonic-gate / 5717c478bd9Sstevel@tonic-gate subl $8, %esp / leave space for ERR and TRAPNO 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate SYSENTER_PUSH 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE 5767c478bd9Sstevel@tonic-gate TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_SYSENTER) / uses labels 8 and 9 5777c478bd9Sstevel@tonic-gate TRACE_REGS(%edi, %esp, %ebx, %ecx) / uses label 9 5787c478bd9Sstevel@tonic-gate pushl %eax 5797c478bd9Sstevel@tonic-gate TRACE_STAMP(%edi) / clobbers %eax, %edx, uses label 9 5807c478bd9Sstevel@tonic-gate popl %eax 5817c478bd9Sstevel@tonic-gate movl %eax, TTR_SYSNUM(%edi) 5827c478bd9Sstevel@tonic-gate#endif 5837c478bd9Sstevel@tonic-gate movl %esp, %ebp 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate CPU_STATS_SYS_SYSCALL_INC 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate ENABLE_INTR_FLAGS 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate pushl %eax / preserve across mstate call 5907c478bd9Sstevel@tonic-gate MSTATE_TRANSITION(LMS_USER, LMS_SYSTEM) 5917c478bd9Sstevel@tonic-gate popl %eax 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate movl %gs:CPU_THREAD, %ebx 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate ASSERT_LWPTOREGS(%ebx, %esp) 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate CHECK_PRESYS_NE(%ebx, %eax) 5987c478bd9Sstevel@tonic-gate jne _full_syscall_presys 5997c478bd9Sstevel@tonic-gate SIMPLE_SYSCALL_PRESYS(%ebx, _syscall_fault) 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate_sysenter_call: 6027c478bd9Sstevel@tonic-gate call *SY_CALLC(%eax) 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate_sysenter_done: 6057c478bd9Sstevel@tonic-gate CHECK_POSTSYS_NE(%ebx, %ecx) 6067c478bd9Sstevel@tonic-gate jne _full_syscall_postsys 6077c478bd9Sstevel@tonic-gate SIMPLE_SYSCALL_POSTSYS(%ebx, %cx) 6087c478bd9Sstevel@tonic-gate / 6097c478bd9Sstevel@tonic-gate / sysexit uses %edx to restore %eip, so we can't use it 6107c478bd9Sstevel@tonic-gate / to return a value, sigh. 6117c478bd9Sstevel@tonic-gate / 6127c478bd9Sstevel@tonic-gate movl %eax, REGOFF_EAX(%esp) 6137c478bd9Sstevel@tonic-gate / movl %edx, REGOFF_EDX(%esp) 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate / Interrupts will be turned on by the 'sti' executed just before 6167c478bd9Sstevel@tonic-gate / sysexit. The following ensures that restoring the user's EFLAGS 6177c478bd9Sstevel@tonic-gate / doesn't enable interrupts too soon. 6187c478bd9Sstevel@tonic-gate andl $_BITNOT(PS_IE), REGOFF_EFL(%esp) 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate MSTATE_TRANSITION(LMS_SYSTEM, LMS_USER) 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate cli 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate SYSCALL_POP 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate popl %edx / sysexit: %edx -> %eip 6277c478bd9Sstevel@tonic-gate addl $4, %esp / get CS off the stack 6287c478bd9Sstevel@tonic-gate popfl / EFL 6297c478bd9Sstevel@tonic-gate popl %ecx / sysexit: %ecx -> %esp 6307c478bd9Sstevel@tonic-gate sti 6317c478bd9Sstevel@tonic-gate sysexit 6327c478bd9Sstevel@tonic-gate SET_SIZE(sys_sysenter) 6339acbbeafSnn35248 SET_SIZE(brand_sys_sysenter) 6349acbbeafSnn35248 6357c478bd9Sstevel@tonic-gate/* 6367c478bd9Sstevel@tonic-gate * Declare a uintptr_t which covers the entire pc range of syscall 6377c478bd9Sstevel@tonic-gate * handlers for the stack walkers that need this. 6387c478bd9Sstevel@tonic-gate */ 6397c478bd9Sstevel@tonic-gate .align CPTRSIZE 6407c478bd9Sstevel@tonic-gate .globl _allsyscalls_size 6417c478bd9Sstevel@tonic-gate .type _allsyscalls_size, @object 6427c478bd9Sstevel@tonic-gate_allsyscalls_size: 6437c478bd9Sstevel@tonic-gate .NWORD . - _allsyscalls 6447c478bd9Sstevel@tonic-gate SET_SIZE(_allsyscalls_size) 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate#endif /* __lint */ 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate/* 6497c478bd9Sstevel@tonic-gate * These are the thread context handlers for lwps using sysenter/sysexit. 6507c478bd9Sstevel@tonic-gate */ 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate#if defined(__lint) 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 6557c478bd9Sstevel@tonic-gatevoid 6567c478bd9Sstevel@tonic-gatesep_save(void *ksp) 6577c478bd9Sstevel@tonic-gate{} 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 6607c478bd9Sstevel@tonic-gatevoid 6617c478bd9Sstevel@tonic-gatesep_restore(void *ksp) 6627c478bd9Sstevel@tonic-gate{} 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate#else /* __lint */ 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate /* 6677c478bd9Sstevel@tonic-gate * setting this value to zero as we switch away causes the 6687c478bd9Sstevel@tonic-gate * stack-pointer-on-sysenter to be NULL, ensuring that we 6697c478bd9Sstevel@tonic-gate * don't silently corrupt another (preempted) thread stack 6707c478bd9Sstevel@tonic-gate * when running an lwp that (somehow) didn't get sep_restore'd 6717c478bd9Sstevel@tonic-gate */ 6727c478bd9Sstevel@tonic-gate ENTRY_NP(sep_save) 6737c478bd9Sstevel@tonic-gate xorl %edx, %edx 6747c478bd9Sstevel@tonic-gate xorl %eax, %eax 6757c478bd9Sstevel@tonic-gate movl $MSR_INTC_SEP_ESP, %ecx 6767c478bd9Sstevel@tonic-gate wrmsr 6777c478bd9Sstevel@tonic-gate ret 6787c478bd9Sstevel@tonic-gate SET_SIZE(sep_save) 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate /* 6817c478bd9Sstevel@tonic-gate * Update the kernel stack pointer as we resume onto this cpu. 6827c478bd9Sstevel@tonic-gate */ 6837c478bd9Sstevel@tonic-gate ENTRY_NP(sep_restore) 6847c478bd9Sstevel@tonic-gate movl 4(%esp), %eax /* per-lwp kernel sp */ 6857c478bd9Sstevel@tonic-gate xorl %edx, %edx 6867c478bd9Sstevel@tonic-gate movl $MSR_INTC_SEP_ESP, %ecx 6877c478bd9Sstevel@tonic-gate wrmsr 6887c478bd9Sstevel@tonic-gate ret 6897c478bd9Sstevel@tonic-gate SET_SIZE(sep_restore) 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate#endif /* __lint */ 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate/* 6947c478bd9Sstevel@tonic-gate * Call syscall(). Called from trap() on watchpoint at lcall 0,7 6957c478bd9Sstevel@tonic-gate */ 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate#if defined(__lint) 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gatevoid 7007c478bd9Sstevel@tonic-gatewatch_syscall(void) 7017c478bd9Sstevel@tonic-gate{} 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate#else /* __lint */ 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate ENTRY_NP(watch_syscall) 706ae115bc7Smrj CLI(%eax) 7077c478bd9Sstevel@tonic-gate movl %gs:CPU_THREAD, %ebx 7087c478bd9Sstevel@tonic-gate movl T_STACK(%ebx), %esp / switch to the thread stack 7097c478bd9Sstevel@tonic-gate movl REGOFF_EAX(%esp), %eax / recover original syscall# 7107c478bd9Sstevel@tonic-gate jmp _watch_do_syscall 7117c478bd9Sstevel@tonic-gate SET_SIZE(watch_syscall) 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate#endif /* __lint */ 714