19acbbeafSnn /*
29acbbeafSnn  * CDDL HEADER START
39acbbeafSnn  *
49acbbeafSnn  * The contents of this file are subject to the terms of the
59acbbeafSnn  * Common Development and Distribution License (the "License").
69acbbeafSnn  * You may not use this file except in compliance with the License.
79acbbeafSnn  *
89acbbeafSnn  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99acbbeafSnn  * or http://www.opensolaris.org/os/licensing.
109acbbeafSnn  * See the License for the specific language governing permissions
119acbbeafSnn  * and limitations under the License.
129acbbeafSnn  *
139acbbeafSnn  * When distributing Covered Code, include this CDDL HEADER in each
149acbbeafSnn  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159acbbeafSnn  * If applicable, add the following below this CDDL HEADER, with the
169acbbeafSnn  * fields enclosed by brackets "[]" replaced with your own identifying
179acbbeafSnn  * information: Portions Copyright [yyyy] [name of copyright owner]
189acbbeafSnn  *
199acbbeafSnn  * CDDL HEADER END
209acbbeafSnn  */
219acbbeafSnn /*
2259f2ff5cSedp  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
239acbbeafSnn  * Use is subject to license terms.
249acbbeafSnn  */
259acbbeafSnn 
269acbbeafSnn #pragma ident	"%Z%%M%	%I%	%E% SMI"
279acbbeafSnn 
289acbbeafSnn #include <sys/errno.h>
299acbbeafSnn #include <sys/exec.h>
309acbbeafSnn #include <sys/kmem.h>
319acbbeafSnn #include <sys/modctl.h>
329acbbeafSnn #include <sys/model.h>
339acbbeafSnn #include <sys/proc.h>
349acbbeafSnn #include <sys/syscall.h>
359acbbeafSnn #include <sys/systm.h>
369acbbeafSnn #include <sys/thread.h>
379acbbeafSnn #include <sys/cmn_err.h>
389acbbeafSnn #include <sys/archsystm.h>
399acbbeafSnn 
409acbbeafSnn #include <sys/machbrand.h>
419acbbeafSnn #include <sys/brand.h>
429acbbeafSnn #include "sn1_brand.h"
439acbbeafSnn 
449acbbeafSnn char *sn1_emulation_table = NULL;
459acbbeafSnn 
46*319378d9Seh void	sn1_init_brand_data(zone_t *);
47*319378d9Seh void	sn1_free_brand_data(zone_t *);
489acbbeafSnn void	sn1_setbrand(proc_t *);
499acbbeafSnn int	sn1_getattr(zone_t *, int, void *, size_t *);
509acbbeafSnn int	sn1_setattr(zone_t *, int, void *, size_t);
519acbbeafSnn int	sn1_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t,
529acbbeafSnn 		uintptr_t, uintptr_t, uintptr_t);
539acbbeafSnn void	sn1_copy_procdata(proc_t *, proc_t *);
549acbbeafSnn void	sn1_proc_exit(struct proc *, klwp_t *);
559acbbeafSnn void	sn1_exec();
569acbbeafSnn int	sn1_initlwp(klwp_t *);
579acbbeafSnn void	sn1_forklwp(klwp_t *, klwp_t *);
589acbbeafSnn void	sn1_freelwp(klwp_t *);
599acbbeafSnn void	sn1_lwpexit(klwp_t *);
609acbbeafSnn int	sn1_elfexec(vnode_t *, execa_t *, uarg_t *, intpdata_t *, int,
619acbbeafSnn 	long *, int, caddr_t, cred_t *, int);
629acbbeafSnn 
639acbbeafSnn /* sn1 brand */
649acbbeafSnn struct brand_ops sn1_brops = {
65*319378d9Seh 	sn1_init_brand_data,
66*319378d9Seh 	sn1_free_brand_data,
679acbbeafSnn 	sn1_brandsys,
689acbbeafSnn 	sn1_setbrand,
699acbbeafSnn 	sn1_getattr,
709acbbeafSnn 	sn1_setattr,
719acbbeafSnn 	sn1_copy_procdata,
729acbbeafSnn 	sn1_proc_exit,
739acbbeafSnn 	sn1_exec,
749acbbeafSnn 	lwp_setrval,
759acbbeafSnn 	sn1_initlwp,
769acbbeafSnn 	sn1_forklwp,
779acbbeafSnn 	sn1_freelwp,
789acbbeafSnn 	sn1_lwpexit,
799acbbeafSnn 	sn1_elfexec
809acbbeafSnn };
819acbbeafSnn 
829acbbeafSnn #ifdef	sparc
839acbbeafSnn 
849acbbeafSnn struct brand_mach_ops sn1_mops = {
859acbbeafSnn 	sn1_brand_syscall_callback,
869acbbeafSnn 	sn1_brand_syscall_callback
879acbbeafSnn };
889acbbeafSnn 
899acbbeafSnn #else	/* sparc */
909acbbeafSnn 
919acbbeafSnn #ifdef	__amd64
929acbbeafSnn 
939acbbeafSnn struct brand_mach_ops sn1_mops = {
949acbbeafSnn 	sn1_brand_sysenter_callback,
959acbbeafSnn 	NULL,
969acbbeafSnn 	sn1_brand_int91_callback,
979acbbeafSnn 	sn1_brand_syscall_callback,
989acbbeafSnn 	sn1_brand_syscall32_callback,
999acbbeafSnn 	NULL
1009acbbeafSnn };
1019acbbeafSnn 
1029acbbeafSnn #else	/* ! __amd64 */
1039acbbeafSnn 
1049acbbeafSnn struct brand_mach_ops sn1_mops = {
1059acbbeafSnn 	sn1_brand_sysenter_callback,
1069acbbeafSnn 	NULL,
1079acbbeafSnn 	NULL,
1089acbbeafSnn 	sn1_brand_syscall_callback,
1099acbbeafSnn 	NULL,
1109acbbeafSnn 	NULL
1119acbbeafSnn };
1129acbbeafSnn #endif	/* __amd64 */
1139acbbeafSnn 
1149acbbeafSnn #endif	/* _sparc */
1159acbbeafSnn 
1169acbbeafSnn struct brand	sn1_brand = {
1179acbbeafSnn 	BRAND_VER_1,
1189acbbeafSnn 	"sn1",
1199acbbeafSnn 	&sn1_brops,
1209acbbeafSnn 	&sn1_mops
1219acbbeafSnn };
1229acbbeafSnn 
1239acbbeafSnn static struct modlbrand modlbrand = {
1249acbbeafSnn 	&mod_brandops, "Solaris N-1 Brand %I%", &sn1_brand
1259acbbeafSnn };
1269acbbeafSnn 
1279acbbeafSnn static struct modlinkage modlinkage = {
1289acbbeafSnn 	MODREV_1, (void *)&modlbrand, NULL
1299acbbeafSnn };
1309acbbeafSnn 
1319acbbeafSnn void
1329acbbeafSnn sn1_setbrand(proc_t *p)
1339acbbeafSnn {
1349acbbeafSnn 	p->p_brand_data = NULL;
1359acbbeafSnn 	p->p_brand = &sn1_brand;
1369acbbeafSnn }
1379acbbeafSnn 
1389acbbeafSnn /* ARGSUSED */
1399acbbeafSnn int
1409acbbeafSnn sn1_getattr(zone_t *zone, int attr, void *buf, size_t *bufsize)
1419acbbeafSnn {
1429acbbeafSnn 	return (EINVAL);
1439acbbeafSnn }
1449acbbeafSnn 
1459acbbeafSnn /* ARGSUSED */
1469acbbeafSnn int
1479acbbeafSnn sn1_setattr(zone_t *zone, int attr, void *buf, size_t bufsize)
1489acbbeafSnn {
1499acbbeafSnn 	return (EINVAL);
1509acbbeafSnn }
1519acbbeafSnn 
1529acbbeafSnn /*
1539acbbeafSnn  * Get the address of the user-space system call handler from the user
1549acbbeafSnn  * process and attach it to the proc structure.
1559acbbeafSnn  */
1569acbbeafSnn /*ARGSUSED*/
1579acbbeafSnn int
1589acbbeafSnn sn1_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2,
1599acbbeafSnn     uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6)
1609acbbeafSnn {
1619acbbeafSnn 	proc_t *p = curproc;
1629acbbeafSnn 	*rval = 0;
1639acbbeafSnn 
1649acbbeafSnn 	if (cmd == B_REGISTER) {
1659acbbeafSnn 		p->p_brand = &sn1_brand;
1669acbbeafSnn 		p->p_brand_data = (void *) arg1;
1679acbbeafSnn 		return (0);
1689acbbeafSnn 	}
1699acbbeafSnn 
1709acbbeafSnn 	ASSERT(p->p_brand == &sn1_brand);
1719acbbeafSnn 
1729acbbeafSnn 	return (EINVAL);
1739acbbeafSnn }
1749acbbeafSnn 
1759acbbeafSnn /*
1769acbbeafSnn  * Copy the per-process brand data from a parent proc to a child.  In the
1779acbbeafSnn  * sn1 brand, the only per-process state is the address of the user-space
1789acbbeafSnn  * handler.
1799acbbeafSnn  */
1809acbbeafSnn void
1819acbbeafSnn sn1_copy_procdata(proc_t *child, proc_t *parent)
1829acbbeafSnn {
1839acbbeafSnn 	child->p_brand_data = parent->p_brand_data;
1849acbbeafSnn }
1859acbbeafSnn 
1869acbbeafSnn /*ARGSUSED*/
1879acbbeafSnn void
1889acbbeafSnn sn1_proc_exit(struct proc *p, klwp_t *l)
1899acbbeafSnn {
1909acbbeafSnn 	p->p_brand_data = NULL;
1919acbbeafSnn 	p->p_brand = &native_brand;
1929acbbeafSnn }
1939acbbeafSnn 
1949acbbeafSnn void
1959acbbeafSnn sn1_exec()
1969acbbeafSnn {
1979acbbeafSnn 	curproc->p_brand_data = NULL;
1989acbbeafSnn }
1999acbbeafSnn 
2009acbbeafSnn /*ARGSUSED*/
2019acbbeafSnn int
2029acbbeafSnn sn1_initlwp(klwp_t *l)
2039acbbeafSnn {
2049acbbeafSnn 	return (0);
2059acbbeafSnn }
2069acbbeafSnn 
207*319378d9Seh /*ARGSUSED*/
208*319378d9Seh void
209*319378d9Seh sn1_init_brand_data(zone_t *zone)
210*319378d9Seh {
211*319378d9Seh }
212*319378d9Seh 
213*319378d9Seh /*ARGSUSED*/
214*319378d9Seh void
215*319378d9Seh sn1_free_brand_data(zone_t *zone)
216*319378d9Seh {
217*319378d9Seh }
218*319378d9Seh 
2199acbbeafSnn /*ARGSUSED*/
2209acbbeafSnn void
2219acbbeafSnn sn1_forklwp(klwp_t *p, klwp_t *c)
2229acbbeafSnn {
2239acbbeafSnn }
2249acbbeafSnn 
2259acbbeafSnn /*ARGSUSED*/
2269acbbeafSnn void
2279acbbeafSnn sn1_freelwp(klwp_t *l)
2289acbbeafSnn {
2299acbbeafSnn }
2309acbbeafSnn 
2319acbbeafSnn /*ARGSUSED*/
2329acbbeafSnn void
2339acbbeafSnn sn1_lwpexit(klwp_t *l)
2349acbbeafSnn {
2359acbbeafSnn }
2369acbbeafSnn 
2379acbbeafSnn int
2389acbbeafSnn sn1_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
2399acbbeafSnn 	int level, long *execsz, int setid, caddr_t exec_file, cred_t *cred,
2409acbbeafSnn 	int brand_action)
2419acbbeafSnn {
2429acbbeafSnn 	args->brandname = "sn1";
2439acbbeafSnn 	return ((args->execswp->exec_func)(vp, uap, args, idatap, level + 1,
2449acbbeafSnn 	    execsz, setid, exec_file, cred, brand_action));
2459acbbeafSnn }
2469acbbeafSnn 
2479acbbeafSnn 
2489acbbeafSnn int
2499acbbeafSnn _init(void)
2509acbbeafSnn {
2519acbbeafSnn 	int err;
2529acbbeafSnn 
2539acbbeafSnn 	/*
2549acbbeafSnn 	 * Set up the table indicating which system calls we want to
2559acbbeafSnn 	 * interpose on.  We should probably build this automatically from
2569acbbeafSnn 	 * a list of system calls that is shared with the user-space
2579acbbeafSnn 	 * library.
2589acbbeafSnn 	 */
2599acbbeafSnn 	sn1_emulation_table = kmem_zalloc(NSYSCALL, KM_SLEEP);
2609acbbeafSnn 	sn1_emulation_table[SYS_uname] = 1;
2619acbbeafSnn 
2629acbbeafSnn 	err = mod_install(&modlinkage);
2639acbbeafSnn 	if (err) {
2649acbbeafSnn 		cmn_err(CE_WARN, "Couldn't install brand module");
2659acbbeafSnn 		kmem_free(sn1_emulation_table, NSYSCALL);
2669acbbeafSnn 	}
2679acbbeafSnn 
2689acbbeafSnn 	return (err);
2699acbbeafSnn }
2709acbbeafSnn 
2719acbbeafSnn int
2729acbbeafSnn _info(struct modinfo *modinfop)
2739acbbeafSnn {
2749acbbeafSnn 	return (mod_info(&modlinkage, modinfop));
2759acbbeafSnn }
2769acbbeafSnn 
2779acbbeafSnn int
2789acbbeafSnn _fini(void)
2799acbbeafSnn {
2809acbbeafSnn 	int err;
2819acbbeafSnn 
2829acbbeafSnn 	/*
2839acbbeafSnn 	 * If there are any zones using this brand, we can't allow it to be
2849acbbeafSnn 	 * unloaded.
2859acbbeafSnn 	 */
2869acbbeafSnn 	if (brand_zone_count(&sn1_brand))
2879acbbeafSnn 		return (EBUSY);
2889acbbeafSnn 
2899acbbeafSnn 	kmem_free(sn1_emulation_table, NSYSCALL);
2909acbbeafSnn 	sn1_emulation_table = NULL;
2919acbbeafSnn 
2929acbbeafSnn 	err = mod_remove(&modlinkage);
2939acbbeafSnn 	if (err)
2949acbbeafSnn 		cmn_err(CE_WARN, "Couldn't unload sn1 brand module");
2959acbbeafSnn 
2969acbbeafSnn 	return (err);
2979acbbeafSnn }
298