2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#ifndef _BRAND_MISC_H
2N/A#define _BRAND_MISC_H
2N/A
2N/A#ifdef __cplusplus
2N/Aextern "C" {
2N/A#endif
2N/A
2N/A/*
2N/A * This header file must uses _ASM defines to allow it to be included
2N/A * in assmebly source files
2N/A */
2N/A#include <sys/asm_linkage.h>
2N/A#include <sys/regset.h>
2N/A#include <sys/syscall.h>
2N/A#if !defined(_ASM)
2N/A#include <sys/brand.h>
2N/A#endif
2N/A#include "assym.h"
2N/A
2N/A/*
2N/A * Our syscall emulation callback handler adds one argument to each
2N/A * system call, so we'll need to allocate space for one more argument
2N/A * above the maximum number of arguments that a system call can normally
2N/A * take. Also, we assume that each syscall argument is a long, ie, we
2N/A * don't support long long syscall parameters.
2N/A */
2N/A#if defined(__sparc)
2N/A/*
2N/A * 32-bit and 64-bit sparc syscalls can take up to 8 arguments.
2N/A * 32-bit sparc indirect syscalls can take up to 9 arguments.
2N/A * Arguments 1 - 6 are passed via %o0 - %o5.
2N/A * Additional arguments are passed on the stack.
2N/A * So make space for 4 arguments on the stack.
2N/A */
2N/A#define EH_ARGS_COUNT 4
2N/A#elif defined(__amd64)
2N/A/*
2N/A * amd64 syscalls can take up to 8 arguments.
2N/A * Arguments 1 - 6 are passed via: %rdi, %rsi, %rdx, %r10, %r8, %r9
2N/A * Additional arguments are passed on the stack.
2N/A * So make space for 3 arguments on the stack.
2N/A */
2N/A#define EH_ARGS_COUNT 3
2N/A#else /* !__sparc && !__amd64 */
2N/A/*
2N/A * ia32 syscalls can take up to 8 arguments.
2N/A * All arguments are passed on the stack.
2N/A * So make space for 9 arguments on the stack.
2N/A */
2N/A#define EH_ARGS_COUNT 9
2N/A#endif /* !__sparc && !__amd64 */
2N/A
2N/A
2N/A#define EH_ARGS_SIZE (CPTRSIZE * EH_ARGS_COUNT)
2N/A#define EH_ARGS_OFFSET(x) (STACK_BIAS + MINFRAME + (CPTRSIZE * (x)))
2N/A#define EH_LOCALS_SIZE (EH_ARGS_SIZE + SIZEOF_GREGSET_T + \
2N/A SIZEOF_SYSRET_T + CPTRSIZE)
2N/A
2N/A#if defined(__sparc)
2N/A/*
2N/A * On sparc, all emulation callback handler variable access is done
2N/A * relative to %sp, so access offsets are positive.
2N/A */
2N/A#define EH_LOCALS_START (STACK_BIAS + MINFRAME + EH_ARGS_SIZE)
2N/A#define EH_LOCALS_END_TGT (STACK_BIAS + MINFRAME + EH_LOCALS_SIZE)
2N/A#else /* !__sparc */
2N/A/*
2N/A * On x86, all emulation callback handler variable access is done
2N/A * relative to %ebp/%rbp, so access offsets are negative.
2N/A */
2N/A#define EH_LOCALS_START (-(EH_LOCALS_SIZE - \
2N/A (STACK_BIAS + MINFRAME + EH_ARGS_SIZE)))
2N/A#define EH_LOCALS_END_TGT 0
2N/A#endif /* !__sparc */
2N/A
2N/A/*
2N/A * In our emulation callback handler, our stack will look like:
2N/A * -------------------------------------------------
2N/A * %bp | long rvflag |
2N/A * | | sysret_t sysret |
2N/A * v | gregset_t gregs |
2N/A * %sp | long callback args[EH_ARGS_COUNT] |
2N/A * -------------------------------------------------
2N/A * For ia32, use %ebp and %esp instead of %bp and %sp.
2N/A * For amd64, use %rbp and %rsp instead of %bp and %sp.
2N/A *
2N/A * Our emulation callback handler always saves enough space to hold the
2N/A * maximum number of stack arguments to a system call. This is architecture
2N/A * specific and is defined via EH_ARGS_COUNT.
2N/A */
2N/A#define EH_LOCALS_GREGS (EH_LOCALS_START)
2N/A#define EH_LOCALS_GREG(x) (EH_LOCALS_GREGS + (SIZEOF_GREG_T * (x)))
2N/A#define EH_LOCALS_SYSRET (EH_LOCALS_GREGS + SIZEOF_GREGSET_T)
2N/A#define EH_LOCALS_SYSRET1 (EH_LOCALS_SYSRET)
2N/A#define EH_LOCALS_SYSRET2 (EH_LOCALS_SYSRET + CPTRSIZE)
2N/A#define EH_LOCALS_RVFLAG (EH_LOCALS_SYSRET + SIZEOF_SYSRET_T)
2N/A#define EH_LOCALS_END (EH_LOCALS_RVFLAG + CPTRSIZE)
2N/A
2N/A#if (EH_LOCALS_END != EH_LOCALS_END_TGT)
2N/A#error "brand_misc.h EH_LOCALS_* macros don't add up"
2N/A#endif /* (EH_LOCALS_END != EH_LOCALS_END_TGT) */
2N/A
2N/A/*
2N/A * The second parameter of each entry in the {BRAND}_sysent_table
2N/A * contains the number of parameters and flags that describe the
2N/A * syscall return value encoding.
2N/A *
2N/A * When declaring new syscall emulation functions, it is very important
2N/A * to to set the proper RV_* flags in the brand_sysent_table. Upon failure,
2N/A * syscall emulation fuctions should return an errno value. Upon success
2N/A * syscall emulation functions should return 0 and set the sysret_t return
2N/A * value parameters accordingly.
2N/A *
2N/A * There are five possible syscall macro wrappers used in the kernel's system
2N/A * call sysent table. These turn into the following return values:
2N/A * SYSENT_CL -> SYSENT_C or SYSENT_CI
2N/A * SYSENT_C SE_64RVAL RV_DEFAULT
2N/A * SYSENT_CI SE_32RVAL1 RV_DEFAULT
2N/A * SYSENT_2CI SE_32RVAL1|SE_32RVAL2 RV_32RVAL2
2N/A * SYSENT_AP SE_64RVAL RV_64RVAL
2N/A *
2N/A */
2N/A#define NARGS_MASK 0x000000FF /* Mask for syscalls argument count */
2N/A#define RV_MASK 0x0000FF00 /* Mask for return value flags */
2N/A#define RV_DEFAULT 0x00000100 /* syscall returns "default" values */
2N/A#define RV_32RVAL2 0x00000200 /* syscall returns two 32-bit values */
2N/A#define RV_64RVAL 0x00000400 /* syscall returns a 64-bit value */
2N/A
2N/A#if !defined(_ASM)
2N/A
2N/A/*
2N/A * We define our own version of assert because the default one will
2N/A * try to emit a localized message. That is bad because first, we can't
2N/A * emit messages to random file descriptors, and second localizing a message
2N/A * requires allocating memory and we can't do that either.
2N/A */
2N/A#define brand_assert(ex) (void)((ex) || \
2N/A (_brand_abort(0, #ex, __FILE__, __LINE__), 0))
2N/A#define brand_abort(err, msg) _brand_abort((err), (msg), __FILE__, __LINE__)
2N/A#define EMULATE(cb, args) { (sysent_cb_t)(cb), (args) }
2N/A#define NOSYS EMULATE(brand_unimpl, (0 | RV_DEFAULT))
2N/A
2N/Atypedef long (*sysent_cb_t)();
2N/Atypedef struct brand_sysent_table {
2N/A sysent_cb_t st_callc;
2N/A uintptr_t st_args;
2N/A} brand_sysent_table_t;
2N/A
2N/A/*
2N/A * These macros invoke a brandsys subcommand, B_TRUSS_POINT, used to expose
2N/A * a call to an interpositioned syscall that would have otherwise gone
2N/A * unnoticed by truss(1) because the interpositioned system call did not call
2N/A * any system calls before returning.
2N/A */
2N/A#define B_TRUSS_POINT_5(rval, syscall_num, err, a0, a1, a2, a3, a4) \
2N/A __systemcall(rval, SYS_brand + 1024, \
2N/A B_TRUSS_POINT, (syscall_num), (err), (a0), (a1), (a2), (a3), \
2N/A (a4))
2N/A
2N/A#define B_TRUSS_POINT_4(rval, syscall_num, err, a0, a1, a2, a3) \
2N/A B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), (a2), (a3), 0)
2N/A
2N/A#define B_TRUSS_POINT_3(rval, syscall_num, err, a0, a1, a2) \
2N/A B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), (a2), 0, 0)
2N/A
2N/A#define B_TRUSS_POINT_2(rval, syscall_num, err, a0, a1) \
2N/A B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), 0, 0, 0)
2N/A
2N/A#define B_TRUSS_POINT_1(rval, syscall_num, err, a0) \
2N/A B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), 0, 0, 0, 0)
2N/A
2N/A#define B_TRUSS_POINT_0(rval, syscall_num, err) \
2N/A B_TRUSS_POINT_5(rval, (syscall_num), (err), 0, 0, 0, 0, 0)
2N/A
2N/A/*
2N/A * From runexe.s
2N/A */
2N/Aextern void brand_runexe(void *, ulong_t);
2N/A
2N/A/*
2N/A * From handler.s
2N/A */
2N/Aextern void brand_handler_table(void);
2N/Aextern void brand_handler(void);
2N/Aextern void brand_error(void);
2N/Aextern void brand_success(void);
2N/A
2N/A/*
2N/A * From brand_util.c
2N/A */
2N/Aextern long brand_unimpl(sysret_t *rv, uintptr_t p1);
2N/Aextern void _brand_abort(int, const char *, const char *, int);
2N/Aextern int brand_uucopy(const void *, void *, size_t);
2N/Aextern int brand_uucopystr(const void *, void *, size_t);
2N/Aextern void brand_pre_init();
2N/Aextern ulong_t brand_post_init(int, int, char **, char **);
2N/A#if defined(__sparc) && !defined(__sparcv9)
2N/Aextern long brand_indir(sysret_t *, int, uintptr_t, uintptr_t, uintptr_t,
2N/A uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
2N/A#endif /* __sparc && !__sparcv9 */
2N/A
2N/A#endif /* !_ASM */
2N/A
2N/A#ifdef __cplusplus
2N/A}
2N/A#endif
2N/A
2N/A#endif /* _BRAND_MISC_H */