s10_brand.c revision 794f0adb050e571bbfde4d2a19b9f88b852079dd
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/*
2N/A * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <sys/errno.h>
2N/A#include <sys/exec.h>
2N/A#include <sys/file.h>
2N/A#include <sys/kmem.h>
2N/A#include <sys/modctl.h>
2N/A#include <sys/model.h>
2N/A#include <sys/proc.h>
2N/A#include <sys/syscall.h>
2N/A#include <sys/systm.h>
2N/A#include <sys/thread.h>
2N/A#include <sys/cmn_err.h>
2N/A#include <sys/archsystm.h>
2N/A#include <sys/pathname.h>
2N/A#include <sys/sunddi.h>
2N/A
2N/A#include <sys/machbrand.h>
2N/A#include <sys/brand.h>
2N/A#include "s10_brand.h"
2N/A
2N/Achar *s10_emulation_table = NULL;
2N/A
2N/Avoid s10_init_brand_data(zone_t *);
2N/Avoid s10_free_brand_data(zone_t *);
2N/Avoid s10_setbrand(proc_t *);
2N/Aint s10_getattr(zone_t *, int, void *, size_t *);
2N/Aint s10_setattr(zone_t *, int, void *, size_t);
2N/Aint s10_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t,
2N/A uintptr_t, uintptr_t, uintptr_t);
2N/Avoid s10_copy_procdata(proc_t *, proc_t *);
2N/Avoid s10_proc_exit(struct proc *, klwp_t *);
2N/Avoid s10_exec();
2N/Aint s10_initlwp(klwp_t *);
2N/Avoid s10_forklwp(klwp_t *, klwp_t *);
2N/Avoid s10_freelwp(klwp_t *);
2N/Avoid s10_lwpexit(klwp_t *);
2N/Aint s10_elfexec(vnode_t *, execa_t *, uarg_t *, intpdata_t *, int,
2N/A long *, int, caddr_t, cred_t *, int);
2N/Avoid s10_sigset_native_to_s10(sigset_t *);
2N/Avoid s10_sigset_s10_to_native(sigset_t *);
2N/A
2N/A/* s10 brand */
2N/Astruct brand_ops s10_brops = {
2N/A s10_init_brand_data,
2N/A s10_free_brand_data,
2N/A s10_brandsys,
2N/A s10_setbrand,
2N/A s10_getattr,
2N/A s10_setattr,
2N/A s10_copy_procdata,
2N/A s10_proc_exit,
2N/A s10_exec,
2N/A lwp_setrval,
2N/A s10_initlwp,
2N/A s10_forklwp,
2N/A s10_freelwp,
2N/A s10_lwpexit,
2N/A s10_elfexec,
2N/A s10_sigset_native_to_s10,
2N/A s10_sigset_s10_to_native,
2N/A S10_NSIG,
2N/A};
2N/A
2N/A#ifdef sparc
2N/A
2N/Astruct brand_mach_ops s10_mops = {
2N/A s10_brand_syscall_callback,
2N/A s10_brand_syscall32_callback
2N/A};
2N/A
2N/A#else /* sparc */
2N/A
2N/A#ifdef __amd64
2N/A
2N/Astruct brand_mach_ops s10_mops = {
2N/A s10_brand_sysenter_callback,
2N/A s10_brand_int91_callback,
2N/A s10_brand_syscall_callback,
2N/A s10_brand_syscall32_callback
2N/A};
2N/A
2N/A#else /* ! __amd64 */
2N/A
2N/Astruct brand_mach_ops s10_mops = {
2N/A s10_brand_sysenter_callback,
2N/A NULL,
2N/A s10_brand_syscall_callback,
2N/A NULL
2N/A};
2N/A#endif /* __amd64 */
2N/A
2N/A#endif /* _sparc */
2N/A
2N/Astruct brand s10_brand = {
2N/A BRAND_VER_1,
2N/A "solaris10",
2N/A &s10_brops,
2N/A &s10_mops
2N/A};
2N/A
2N/Astatic struct modlbrand modlbrand = {
2N/A &mod_brandops, /* type of module */
2N/A "Solaris 10 Brand", /* description of module */
2N/A &s10_brand /* driver ops */
2N/A};
2N/A
2N/Astatic struct modlinkage modlinkage = {
2N/A MODREV_1, (void *)&modlbrand, NULL
2N/A};
2N/A
2N/Avoid
2N/As10_setbrand(proc_t *p)
2N/A{
2N/A brand_solaris_setbrand(p, &s10_brand);
2N/A}
2N/A
2N/A/*ARGSUSED*/
2N/Aint
2N/As10_getattr(zone_t *zone, int attr, void *buf, size_t *bufsize)
2N/A{
2N/A ASSERT(zone->zone_brand == &s10_brand);
2N/A if (attr == S10_EMUL_BITMAP) {
2N/A if (buf == NULL || *bufsize != sizeof (s10_emul_bitmap_t))
2N/A return (EINVAL);
2N/A if (copyout(((s10_zone_data_t *)zone->zone_brand_data)->
2N/A emul_bitmap, buf, sizeof (s10_emul_bitmap_t)) != 0)
2N/A return (EFAULT);
2N/A return (0);
2N/A }
2N/A
2N/A return (EINVAL);
2N/A}
2N/A
2N/Aint
2N/As10_setattr(zone_t *zone, int attr, void *buf, size_t bufsize)
2N/A{
2N/A ASSERT(zone->zone_brand == &s10_brand);
2N/A if (attr == S10_EMUL_BITMAP) {
2N/A if (buf == NULL || bufsize != sizeof (s10_emul_bitmap_t))
2N/A return (EINVAL);
2N/A if (copyin(buf, ((s10_zone_data_t *)zone->zone_brand_data)->
2N/A emul_bitmap, sizeof (s10_emul_bitmap_t)) != 0)
2N/A return (EFAULT);
2N/A return (0);
2N/A }
2N/A
2N/A return (EINVAL);
2N/A}
2N/A
2N/A#ifdef __amd64
2N/A/*
2N/A * The Nevada kernel clears %fs for threads in 64-bit x86 processes but S10's
2N/A * libc expects %fs to be nonzero. This causes some committed
2N/A * libc/libthread interfaces (e.g., thr_main()) to fail, which impacts several
2N/A * libraries, including libdoor. This function sets the specified LWP's %fs
2N/A * register to the legacy S10 selector value (LWPFS_SEL).
2N/A *
2N/A * The best solution to the aforementioned problem is backporting CRs
2N/A * 6467491 to Solaris 10 so that 64-bit x86 Solaris 10 processes
2N/A * would accept zero for %fs. Backporting the CRs is a requirement for running
2N/A * S10 Containers in PV domUs because 64-bit Xen clears %fsbase when %fs is
2N/A * nonzero. Such behavior breaks 64-bit processes because Xen has to fetch the
2N/A * FS segments' base addresses from the LWPs' GDTs, which are only capable of
2N/A * 32-bit addressing.
2N/A */
2N/A/*ARGSUSED*/
2N/Astatic void
2N/As10_amd64_correct_fsreg(klwp_t *l)
2N/A{
2N/A if (lwp_getdatamodel(l) == DATAMODEL_NATIVE) {
2N/A kpreempt_disable();
2N/A l->lwp_pcb.pcb_fs = LWPFS_SEL;
2N/A l->lwp_pcb.pcb_rupdate = 1;
2N/A lwptot(l)->t_post_sys = 1; /* Guarantee update_sregs() */
2N/A kpreempt_enable();
2N/A }
2N/A}
2N/A#endif /* __amd64 */
2N/A
2N/A/*
2N/A * The native ld.so.1 is invoked with a set of -e options which we also want to
2N/A * strip off. This function assumes the set of -e options immediately follows
2N/A * the native ld.so.1 command and is contiguous. This is OK, since we control
2N/A * the code in s10_isaexec_wrapper. We do it this way so we don't accidently
2N/A * strip a -e option from the native command itself. The format of an ld.so.1
2N/A * -e option looks like:
2N/A * -e LD_NOENVIRON=1
2N/A */
2N/Achar *
2N/Arm_e_options(char *args)
2N/A{
2N/A char *p;
2N/A
2N/A while (strncmp(args, "-e ", 3) == 0) {
2N/A args += 3;
2N/A if ((p = strchr(args, ' ')) != NULL)
2N/A args = p + 1;
2N/A }
2N/A
2N/A return (args);
2N/A}
2N/A
2N/Aint
2N/As10_native()
2N/A{
2N/A struct user *up = PTOU(curproc);
2N/A char *args_new, *comm_new, *p;
2N/A int len;
2N/A
2N/A /*
2N/A * len has an extra value for the trailing '\0' so this covers the
2N/A * appended " " in the following strcmps.
2N/A */
2N/A len = sizeof (BRAND_NATIVE_LINKER32);
2N/A
2N/A /*
2N/A * Make sure that the process' interpreter is the native dynamic linker.
2N/A * Convention dictates that native processes executing within solaris10-
2N/A * branded zones are interpreted by the native dynamic linker (the
2N/A * process and its arguments are specified as arguments to the dynamic
2N/A * linker). If this convention is violated (i.e.,
2N/A * brandsys(B_S10_NATIVE, ...) is invoked by a process that shouldn't be
2N/A * native), then do nothing and silently indicate success.
2N/A */
2N/A if (strcmp(up->u_comm, S10_LINKER_NAME) != 0)
2N/A return (0);
2N/A if (strncmp(up->u_psargs, BRAND_NATIVE_LINKER64 " ", len + 3) == 0)
2N/A len += 3; /* to account for "/64" in the path */
2N/A else if (strncmp(up->u_psargs, BRAND_NATIVE_LINKER32 " ", len) != 0)
2N/A return (0);
2N/A
2N/A args_new = strdup(rm_e_options(&up->u_psargs[len]));
2N/A if ((p = strchr(args_new, ' ')) != NULL)
2N/A *p = '\0';
2N/A if ((comm_new = strrchr(args_new, '/')) != NULL)
2N/A comm_new = strdup(comm_new + 1);
2N/A else
2N/A comm_new = strdup(args_new);
2N/A if (p != NULL)
2N/A *p = ' ';
2N/A
2N/A if ((strlen(args_new) != 0) && (strlen(comm_new) != 0)) {
2N/A mutex_enter(&curproc->p_lock);
2N/A (void) strlcpy(up->u_comm, comm_new, MAXCOMLEN+1);
2N/A (void) strlcpy(up->u_psargs, args_new, PSARGSZ);
2N/A mutex_exit(&curproc->p_lock);
2N/A }
2N/A
2N/A strfree(args_new);
2N/A strfree(comm_new);
2N/A return (0);
2N/A}
2N/A
2N/A/*ARGSUSED*/
2N/Aint
2N/As10_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2,
2N/A uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6)
2N/A{
2N/A proc_t *p = curproc;
2N/A int res;
2N/A
2N/A *rval = 0;
2N/A
2N/A if (cmd == B_S10_NATIVE)
2N/A return (s10_native());
2N/A
2N/A res = brand_solaris_cmd(cmd, arg1, arg2, arg3, &s10_brand, S10_VERSION);
2N/A if (res >= 0)
2N/A return (res);
2N/A
2N/A switch ((cmd)) {
2N/A case B_S10_PIDINFO:
2N/A /*
2N/A * The s10 brand needs to be able to get the pid of the
2N/A * current process and the pid of the zone's init, and it
2N/A * needs to do this on every process startup. Early in
2N/A * brand startup, we can't call getpid() because calls to
2N/A * getpid() represent a magical signal to some old-skool
2N/A * debuggers. By merging all of this into one call, we
2N/A * make this quite a bit cheaper and easier to handle in
2N/A * the brand module.
2N/A */
2N/A if (copyout(&p->p_pid, (void *)arg1, sizeof (pid_t)) != 0)
2N/A return (EFAULT);
2N/A if (copyout(&p->p_zone->zone_proc_initpid, (void *)arg2,
2N/A sizeof (pid_t)) != 0)
2N/A return (EFAULT);
2N/A return (0);
2N/A
2N/A case B_S10_ISFDXATTRDIR: {
2N/A /*
2N/A * This subcommand enables the userland brand emulation library
2N/A * to determine whether a file descriptor refers to an extended
2N/A * file attributes directory. There is no standard syscall or
2N/A * libc function that can make such a determination.
2N/A */
2N/A file_t *dir_filep;
2N/A
2N/A dir_filep = getf((int)arg1);
2N/A if (dir_filep == NULL)
2N/A return (EBADF);
2N/A ASSERT(dir_filep->f_vnode != NULL);
2N/A *rval = IS_XATTRDIR(dir_filep->f_vnode);
2N/A releasef((int)arg1);
2N/A return (0);
2N/A }
2N/A
2N/A#ifdef __amd64
2N/A case B_S10_FSREGCORRECTION:
2N/A /*
2N/A * This subcommand exists so that the SYS_lwp_private and
2N/A * SYS_lwp_create syscalls can manually set the current thread's
2N/A * %fs register to the legacy S10 selector value for 64-bit x86
2N/A * processes.
2N/A */
2N/A s10_amd64_correct_fsreg(ttolwp(curthread));
2N/A return (0);
2N/A#endif /* __amd64 */
2N/A }
2N/A
2N/A return (EINVAL);
2N/A}
2N/A
2N/Avoid
2N/As10_copy_procdata(proc_t *child, proc_t *parent)
2N/A{
2N/A brand_solaris_copy_procdata(child, parent, &s10_brand);
2N/A}
2N/A
2N/Avoid
2N/As10_proc_exit(struct proc *p, klwp_t *l)
2N/A{
2N/A brand_solaris_proc_exit(p, l, &s10_brand);
2N/A}
2N/A
2N/Avoid
2N/As10_exec()
2N/A{
2N/A brand_solaris_exec(&s10_brand);
2N/A}
2N/A
2N/Aint
2N/As10_initlwp(klwp_t *l)
2N/A{
2N/A return (brand_solaris_initlwp(l, &s10_brand));
2N/A}
2N/A
2N/Avoid
2N/As10_forklwp(klwp_t *p, klwp_t *c)
2N/A{
2N/A brand_solaris_forklwp(p, c, &s10_brand);
2N/A
2N/A#ifdef __amd64
2N/A /*
2N/A * Only correct the child's %fs register if the parent's %fs register
2N/A * is LWPFS_SEL. If the parent's %fs register is zero, then the Solaris
2N/A * 10 environment that we're emulating uses a version of libc that
2N/A * works when %fs is zero (i.e., it contains backports of CRs 6467491
2N/A * and 6501650).
2N/A */
2N/A if (p->lwp_pcb.pcb_fs == LWPFS_SEL)
2N/A s10_amd64_correct_fsreg(c);
2N/A#endif /* __amd64 */
2N/A}
2N/A
2N/Avoid
2N/As10_freelwp(klwp_t *l)
2N/A{
2N/A brand_solaris_freelwp(l, &s10_brand);
2N/A}
2N/A
2N/Avoid
2N/As10_lwpexit(klwp_t *l)
2N/A{
2N/A brand_solaris_lwpexit(l, &s10_brand);
2N/A}
2N/A
2N/Avoid
2N/As10_free_brand_data(zone_t *zone)
2N/A{
2N/A kmem_free(zone->zone_brand_data, sizeof (s10_zone_data_t));
2N/A}
2N/A
2N/Avoid
2N/As10_init_brand_data(zone_t *zone)
2N/A{
2N/A ASSERT(zone->zone_brand == &s10_brand);
2N/A ASSERT(zone->zone_brand_data == NULL);
2N/A zone->zone_brand_data = kmem_zalloc(sizeof (s10_zone_data_t), KM_SLEEP);
2N/A}
2N/A
2N/Aint
2N/As10_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
2N/A int level, long *execsz, int setid, caddr_t exec_file, cred_t *cred,
2N/A int brand_action)
2N/A{
2N/A return (brand_solaris_elfexec(vp, uap, args, idatap, level, execsz,
2N/A setid, exec_file, cred, brand_action, &s10_brand, S10_BRANDNAME,
2N/A S10_LIB, S10_LIB32, S10_LINKER, S10_LINKER32));
2N/A}
2N/A
2N/Avoid
2N/As10_sigset_native_to_s10(sigset_t *set)
2N/A{
2N/A int nativesig;
2N/A int s10sig;
2N/A sigset_t s10set;
2N/A
2N/A /*
2N/A * Shortcut: we know the first 32 signals are the same in both
2N/A * s10 and native Solaris. Just assign the first word.
2N/A */
2N/A s10set.__sigbits[0] = set->__sigbits[0];
2N/A s10set.__sigbits[1] = 0;
2N/A s10set.__sigbits[2] = 0;
2N/A s10set.__sigbits[3] = 0;
2N/A
2N/A /*
2N/A * Copy the remainder of the initial set of common signals.
2N/A */
2N/A for (nativesig = 33; nativesig < S10_SIGRTMIN; nativesig++)
2N/A if (sigismember(set, nativesig))
2N/A sigaddset(&s10set, nativesig);
2N/A
2N/A /*
2N/A * Convert any native RT signals to their S10 values.
2N/A */
2N/A for (nativesig = _SIGRTMIN, s10sig = S10_SIGRTMIN;
2N/A nativesig <= _SIGRTMAX && s10sig <= S10_SIGRTMAX;
2N/A nativesig++, s10sig++) {
2N/A if (sigismember(set, nativesig))
2N/A sigaddset(&s10set, s10sig);
2N/A }
2N/A
2N/A *set = s10set;
2N/A}
2N/A
2N/Avoid
2N/As10_sigset_s10_to_native(sigset_t *set)
2N/A{
2N/A int s10sig;
2N/A int nativesig;
2N/A sigset_t nativeset;
2N/A
2N/A /*
2N/A * Shortcut: we know the first 32 signals are the same in both
2N/A * s10 and native Solaris. Just assign the first word.
2N/A */
nativeset.__sigbits[0] = set->__sigbits[0];
nativeset.__sigbits[1] = 0;
nativeset.__sigbits[2] = 0;
nativeset.__sigbits[3] = 0;
/*
* Copy the remainder of the initial set of common signals.
*/
for (s10sig = 33; s10sig < S10_SIGRTMIN; s10sig++)
if (sigismember(set, s10sig))
sigaddset(&nativeset, s10sig);
/*
* Convert any S10 RT signals to their native values.
*/
for (s10sig = S10_SIGRTMIN, nativesig = _SIGRTMIN;
s10sig <= S10_SIGRTMAX && nativesig <= _SIGRTMAX;
s10sig++, nativesig++) {
if (sigismember(set, s10sig))
sigaddset(&nativeset, nativesig);
}
*set = nativeset;
}
int
_init(void)
{
int err;
/*
* Set up the table indicating which system calls we want to
* interpose on. We should probably build this automatically from
* a list of system calls that is shared with the user-space
* library.
*/
s10_emulation_table = kmem_zalloc(NSYSCALL, KM_SLEEP);
s10_emulation_table[S10_SYS_forkall] = 1; /* 2 */
s10_emulation_table[S10_SYS_open] = 1; /* 5 */
s10_emulation_table[S10_SYS_wait] = 1; /* 7 */
s10_emulation_table[S10_SYS_creat] = 1; /* 8 */
s10_emulation_table[S10_SYS_link] = 1; /* 9 */
s10_emulation_table[S10_SYS_unlink] = 1; /* 10 */
s10_emulation_table[S10_SYS_exec] = 1; /* 11 */
s10_emulation_table[S10_SYS_mknod] = 1; /* 14 */
s10_emulation_table[S10_SYS_chmod] = 1; /* 15 */
s10_emulation_table[S10_SYS_chown] = 1; /* 16 */
s10_emulation_table[S10_SYS_stat] = 1; /* 18 */
s10_emulation_table[S10_SYS_umount] = 1; /* 22 */
s10_emulation_table[S10_SYS_fstat] = 1; /* 28 */
s10_emulation_table[S10_SYS_utime] = 1; /* 30 */
s10_emulation_table[S10_SYS_access] = 1; /* 33 */
s10_emulation_table[SYS_kill] = 1; /* 37 */
s10_emulation_table[S10_SYS_dup] = 1; /* 41 */
s10_emulation_table[SYS_ioctl] = 1; /* 54 */
s10_emulation_table[SYS_execve] = 1; /* 59 */
s10_emulation_table[SYS_acctctl] = 1; /* 71 */
s10_emulation_table[S10_SYS_issetugid] = 1; /* 75 */
s10_emulation_table[S10_SYS_fsat] = 1; /* 76 */
s10_emulation_table[S10_SYS_rmdir] = 1; /* 79 */
s10_emulation_table[S10_SYS_mkdir] = 1; /* 80 */
s10_emulation_table[SYS_getdents] = 1; /* 81 */
s10_emulation_table[S10_SYS_poll] = 1; /* 87 */
s10_emulation_table[S10_SYS_lstat] = 1; /* 88 */
s10_emulation_table[S10_SYS_symlink] = 1; /* 89 */
s10_emulation_table[S10_SYS_readlink] = 1; /* 90 */
s10_emulation_table[S10_SYS_fchmod] = 1; /* 93 */
s10_emulation_table[S10_SYS_fchown] = 1; /* 94 */
s10_emulation_table[SYS_sigprocmask] = 1; /* 95 */
s10_emulation_table[SYS_sigsuspend] = 1; /* 96 */
s10_emulation_table[SYS_sigaction] = 1; /* 98 */
s10_emulation_table[SYS_sigpending] = 1; /* 99 */
s10_emulation_table[SYS_waitid] = 1; /* 107 */
s10_emulation_table[SYS_sigsendsys] = 1; /* 108 */
#if defined(__x86)
s10_emulation_table[S10_SYS_xstat] = 1; /* 123 */
s10_emulation_table[S10_SYS_lxstat] = 1; /* 124 */
s10_emulation_table[S10_SYS_fxstat] = 1; /* 125 */
s10_emulation_table[S10_SYS_xmknod] = 1; /* 126 */
#endif
s10_emulation_table[S10_SYS_lchown] = 1; /* 130 */
s10_emulation_table[S10_SYS_rename] = 1; /* 134 */
s10_emulation_table[SYS_uname] = 1; /* 135 */
s10_emulation_table[SYS_sysconfig] = 1; /* 137 */
s10_emulation_table[SYS_systeminfo] = 1; /* 139 */
s10_emulation_table[S10_SYS_fork1] = 1; /* 143 */
s10_emulation_table[SYS_sigtimedwait] = 1; /* 144 */
s10_emulation_table[S10_SYS_lwp_sema_wait] = 1; /* 147 */
s10_emulation_table[S10_SYS_utimes] = 1; /* 154 */
s10_emulation_table[SYS_lwp_create] = 1; /* 159 */
s10_emulation_table[SYS_lwp_kill] = 1; /* 163 */
s10_emulation_table[SYS_lwp_sigmask] = 1; /* 165 */
#if defined(__amd64)
s10_emulation_table[SYS_lwp_private] = 1; /* 166 */
#endif /* __amd64 */
s10_emulation_table[S10_SYS_lwp_mutex_lock] = 1; /* 169 */
s10_emulation_table[SYS_pwrite] = 1; /* 174 */
s10_emulation_table[SYS_acl] = 1; /* 185 */
s10_emulation_table[SYS_auditsys] = 1; /* 186 */
s10_emulation_table[SYS_sigqueue] = 1; /* 190 */
s10_emulation_table[SYS_facl] = 1; /* 200 */
s10_emulation_table[SYS_signotify] = 1; /* 205 */
s10_emulation_table[SYS_lwp_mutex_timedlock] = 1; /* 210 */
s10_emulation_table[SYS_getdents64] = 1; /* 213 */
s10_emulation_table[S10_SYS_stat64] = 1; /* 215 */
s10_emulation_table[S10_SYS_lstat64] = 1; /* 216 */
s10_emulation_table[S10_SYS_fstat64] = 1; /* 217 */
s10_emulation_table[SYS_pwrite64] = 1; /* 223 */
s10_emulation_table[S10_SYS_creat64] = 1; /* 224 */
s10_emulation_table[S10_SYS_open64] = 1; /* 225 */
s10_emulation_table[SYS_zone] = 1; /* 227 */
s10_emulation_table[SYS_lwp_mutex_trylock] = 1; /* 251 */
err = mod_install(&modlinkage);
if (err) {
cmn_err(CE_WARN, "Couldn't install brand module");
kmem_free(s10_emulation_table, NSYSCALL);
}
return (err);
}
int
_info(struct modinfo *modinfop)
{
return (mod_info(&modlinkage, modinfop));
}
int
_fini(void)
{
return (brand_solaris_fini(&s10_emulation_table, &modlinkage,
&s10_brand));
}