OpenSolaris_b135/uts/intel/brand/lx/lx_brand_asm.s

/*
 * 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
 * or http://www.opensolaris.org/os/licensing.
 * 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.
 */

#if defined(__lint)

#include <sys/systm.h>

#else	/* __lint */

#include "genassym.h"
#include "../common/brand_asm.h"

#endif	/* __lint */

#ifdef	__lint

void
lx_brand_int80_callback(void)
{
}

#else	/* __lint */

#if defined(__amd64)

/*
 * See "64-BIT INTERPOSITION STACK" in brand_asm.h.
 */
ENTRY(lx_brand_int80_callback)
	GET_PROCP(SP_REG, 0, %r15)
	movq	P_ZONE(%r15), %r15		/* grab the zone pointer */
	/* grab the 'max syscall num' for this process from 'zone brand data' */
	movq	ZONE_BRAND_DATA(%r15), %r15	/* grab the zone brand ptr */
	movl	LXZD_MAX_SYSCALL(%r15), %r15d	/* get the 'max sysnum' word */
	cmpq	%r15, %rax			/* is 0 <= syscall <= MAX? */
	jbe	0f				/* yes, syscall is OK */
	xorl    %eax, %eax			/* no, zero syscall number */
0:

.lx_brand_int80_patch_point:
	jmp	.lx_brand_int80_notrace

.lx_brand_int80_notrace:
	CALC_TABLE_ADDR(%r15, L_HANDLER)
1:
	movq	%r15, %rax
	GET_V(%rsp, 0, V_SSP, %rsp)	/* restore intr. stack pointer */
	xchgq	(%rsp), %rax		/* swap %rax and return addr */
	jmp	sys_sysint_swapgs_iret

.lx_brand_int80_trace:
	/*
	 * If tracing is active, we vector to an alternate trace-enabling
	 * handler table instead.
	 */
	CALC_TABLE_ADDR(%r15, L_TRACEHANDLER)
	jmp	1b
SET_SIZE(lx_brand_int80_callback)

#define	PATCH_POINT	_CONST(.lx_brand_int80_patch_point + 1)
#define	PATCH_VAL	_CONST(.lx_brand_int80_trace - .lx_brand_int80_notrace)

ENTRY(lx_brand_int80_enable)
	movl	$1, lx_systrace_brand_enabled(%rip)
	movq	$PATCH_POINT, %r8
	movb	$PATCH_VAL, (%r8)
	ret
SET_SIZE(lx_brand_int80_enable)

ENTRY(lx_brand_int80_disable)
	movq	$PATCH_POINT, %r8
	movb	$0, (%r8)
	movl	$0, lx_systrace_brand_enabled(%rip)
	ret
SET_SIZE(lx_brand_int80_disable)


#elif defined(__i386)

/*
 * See "32-BIT INTERPOSITION STACK" in brand_asm.h.
 */
ENTRY(lx_brand_int80_callback)
	GET_PROCP(SP_REG, 0, %ebx)
	movl	P_ZONE(%ebx), %ebx		/* grab the zone pointer */
	/* grab the 'max syscall num' for this process from 'zone brand data' */
	movl	ZONE_BRAND_DATA(%ebx), %ebx	/* grab the zone brand data */
	movl	LXZD_MAX_SYSCALL(%ebx), %ebx	/* get the max sysnum */

	cmpl	%ebx, %eax 			/* is 0 <= syscall <= MAX? */
	jbe	0f				/* yes, syscall is OK */
	xorl    %eax, %eax		     	/* no, zero syscall number */	
0:

.lx_brand_int80_patch_point:
	jmp	.lx_brand_int80_notrace

.lx_brand_int80_notrace:
	CALC_TABLE_ADDR(%ebx, L_HANDLER)

1:
	movl	%ebx, %eax
	GET_V(%esp, 0, V_U_EBX, %ebx)		/* restore scratch register */
	addl	$V_END, %esp		/* restore intr. stack ptr */
	xchgl	(%esp), %eax		/* swap new and orig. return addrs */
	jmp	nopop_sys_rtt_syscall

.lx_brand_int80_trace:
	CALC_TABLE_ADDR(%ebx, L_TRACEHANDLER)
	jmp	1b
SET_SIZE(lx_brand_int80_callback)


#define	PATCH_POINT	_CONST(.lx_brand_int80_patch_point + 1)
#define	PATCH_VAL	_CONST(.lx_brand_int80_trace - .lx_brand_int80_notrace)

ENTRY(lx_brand_int80_enable)
	pushl	%ebx
	pushl	%eax
	movl	$1, lx_systrace_brand_enabled
	movl	$PATCH_POINT, %ebx
	movl	$PATCH_VAL, %eax
	movb	%al, (%ebx)
	popl	%eax
	popl	%ebx
	ret
SET_SIZE(lx_brand_int80_enable)

ENTRY(lx_brand_int80_disable)
	pushl	%ebx
	movl	$PATCH_POINT, %ebx
	movb	$0, (%ebx)
	movl	$0, lx_systrace_brand_enabled
	popl	%ebx
	ret
SET_SIZE(lx_brand_int80_disable)

#endif	/* __i386 */
#endif	/* __lint */