1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26#include <sys/errno.h>
27#include <sys/exec.h>
28#include <sys/kmem.h>
29#include <sys/modctl.h>
30#include <sys/model.h>
31#include <sys/proc.h>
32#include <sys/syscall.h>
33#include <sys/systm.h>
34#include <sys/thread.h>
35#include <sys/cmn_err.h>
36#include <sys/archsystm.h>
37#include <sys/pathname.h>
38
39#include <sys/machbrand.h>
40#include <sys/brand.h>
41#include "sn1_brand.h"
42
43char *sn1_emulation_table = NULL;
44
45void	sn1_init_brand_data(zone_t *);
46void	sn1_free_brand_data(zone_t *);
47void	sn1_setbrand(proc_t *);
48int	sn1_getattr(zone_t *, int, void *, size_t *);
49int	sn1_setattr(zone_t *, int, void *, size_t);
50int	sn1_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t,
51		uintptr_t, uintptr_t, uintptr_t);
52void	sn1_copy_procdata(proc_t *, proc_t *);
53void	sn1_proc_exit(struct proc *, klwp_t *);
54void	sn1_exec();
55int	sn1_initlwp(klwp_t *);
56void	sn1_forklwp(klwp_t *, klwp_t *);
57void	sn1_freelwp(klwp_t *);
58void	sn1_lwpexit(klwp_t *);
59int	sn1_elfexec(vnode_t *, execa_t *, uarg_t *, intpdata_t *, int,
60	long *, int, caddr_t, cred_t *, int);
61
62/* sn1 brand */
63struct brand_ops sn1_brops = {
64	sn1_init_brand_data,
65	sn1_free_brand_data,
66	sn1_brandsys,
67	sn1_setbrand,
68	sn1_getattr,
69	sn1_setattr,
70	sn1_copy_procdata,
71	sn1_proc_exit,
72	sn1_exec,
73	lwp_setrval,
74	sn1_initlwp,
75	sn1_forklwp,
76	sn1_freelwp,
77	sn1_lwpexit,
78	sn1_elfexec,
79	NULL,
80	NULL,
81	NSIG,
82};
83
84#ifdef	sparc
85
86struct brand_mach_ops sn1_mops = {
87	sn1_brand_syscall_callback,
88	sn1_brand_syscall32_callback
89};
90
91#else	/* sparc */
92
93#ifdef	__amd64
94
95struct brand_mach_ops sn1_mops = {
96	sn1_brand_sysenter_callback,
97	sn1_brand_int91_callback,
98	sn1_brand_syscall_callback,
99	sn1_brand_syscall32_callback
100};
101
102#else	/* ! __amd64 */
103
104struct brand_mach_ops sn1_mops = {
105	sn1_brand_sysenter_callback,
106	NULL,
107	sn1_brand_syscall_callback,
108	NULL
109};
110#endif	/* __amd64 */
111
112#endif	/* _sparc */
113
114struct brand	sn1_brand = {
115	BRAND_VER_1,
116	"sn1",
117	&sn1_brops,
118	&sn1_mops
119};
120
121static struct modlbrand modlbrand = {
122	&mod_brandops,		/* type of module */
123	"Solaris N-1 Brand",	/* description of module */
124	&sn1_brand		/* driver ops */
125};
126
127static struct modlinkage modlinkage = {
128	MODREV_1, (void *)&modlbrand, NULL
129};
130
131void
132sn1_setbrand(proc_t *p)
133{
134	brand_solaris_setbrand(p, &sn1_brand);
135}
136
137/* ARGSUSED */
138int
139sn1_getattr(zone_t *zone, int attr, void *buf, size_t *bufsize)
140{
141	return (EINVAL);
142}
143
144/* ARGSUSED */
145int
146sn1_setattr(zone_t *zone, int attr, void *buf, size_t bufsize)
147{
148	return (EINVAL);
149}
150
151/*ARGSUSED*/
152int
153sn1_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2,
154    uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6)
155{
156	int	res;
157
158	*rval = 0;
159
160	res = brand_solaris_cmd(cmd, arg1, arg2, arg3, &sn1_brand, SN1_VERSION);
161	if (res >= 0)
162		return (res);
163
164	return (EINVAL);
165}
166
167void
168sn1_copy_procdata(proc_t *child, proc_t *parent)
169{
170	brand_solaris_copy_procdata(child, parent, &sn1_brand);
171}
172
173void
174sn1_proc_exit(struct proc *p, klwp_t *l)
175{
176	brand_solaris_proc_exit(p, l, &sn1_brand);
177}
178
179void
180sn1_exec()
181{
182	brand_solaris_exec(&sn1_brand);
183}
184
185int
186sn1_initlwp(klwp_t *l)
187{
188	return (brand_solaris_initlwp(l, &sn1_brand));
189}
190
191void
192sn1_forklwp(klwp_t *p, klwp_t *c)
193{
194	brand_solaris_forklwp(p, c, &sn1_brand);
195}
196
197void
198sn1_freelwp(klwp_t *l)
199{
200	brand_solaris_freelwp(l, &sn1_brand);
201}
202
203void
204sn1_lwpexit(klwp_t *l)
205{
206	brand_solaris_lwpexit(l, &sn1_brand);
207}
208
209/*ARGSUSED*/
210void
211sn1_free_brand_data(zone_t *zone)
212{
213}
214
215/*ARGSUSED*/
216void
217sn1_init_brand_data(zone_t *zone)
218{
219}
220
221int
222sn1_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
223	int level, long *execsz, int setid, caddr_t exec_file, cred_t *cred,
224	int brand_action)
225{
226	return (brand_solaris_elfexec(vp, uap, args, idatap, level, execsz,
227	    setid, exec_file, cred, brand_action, &sn1_brand, SN1_BRANDNAME,
228	    SN1_LIB, SN1_LIB32, SN1_LINKER, SN1_LINKER32));
229}
230
231int
232_init(void)
233{
234	int err;
235
236	/*
237	 * Set up the table indicating which system calls we want to
238	 * interpose on.  We should probably build this automatically from
239	 * a list of system calls that is shared with the user-space
240	 * library.
241	 */
242	sn1_emulation_table = kmem_zalloc(NSYSCALL, KM_SLEEP);
243	sn1_emulation_table[SYS_read] = 1;			/*   3 */
244	sn1_emulation_table[SYS_write] = 1;			/*   4 */
245	sn1_emulation_table[SYS_time] = 1;			/*  13 */
246	sn1_emulation_table[SYS_getpid] = 1;			/*  20 */
247	sn1_emulation_table[SYS_mount] = 1;			/*  21 */
248	sn1_emulation_table[SYS_getuid] = 1;			/*  24 */
249	sn1_emulation_table[SYS_times] = 1;			/*  43 */
250	sn1_emulation_table[SYS_getgid] = 1;			/*  47 */
251	sn1_emulation_table[SYS_utssys] = 1;			/*  57 */
252	sn1_emulation_table[SYS_waitid] = 1;			/* 107 */
253	sn1_emulation_table[SYS_uname] = 1;			/* 135 */
254
255	err = mod_install(&modlinkage);
256	if (err) {
257		cmn_err(CE_WARN, "Couldn't install brand module");
258		kmem_free(sn1_emulation_table, NSYSCALL);
259	}
260
261	return (err);
262}
263
264int
265_info(struct modinfo *modinfop)
266{
267	return (mod_info(&modlinkage, modinfop));
268}
269
270int
271_fini(void)
272{
273	return (brand_solaris_fini(&sn1_emulation_table, &modlinkage,
274	    &sn1_brand));
275}
276