xref: /illumos-gate/usr/src/uts/common/os/subr.c (revision e5803b76927480e8f9b67b22201c484ccf4c2bcf)
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  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27 /*	  All Rights Reserved  	*/
28 
29 #include <sys/types.h>
30 #include <sys/sysmacros.h>
31 #include <sys/param.h>
32 #include <sys/vmparam.h>
33 #include <sys/systm.h>
34 #include <sys/cred.h>
35 #include <sys/user.h>
36 #include <sys/proc.h>
37 #include <sys/conf.h>
38 #include <sys/tuneable.h>
39 #include <sys/cpuvar.h>
40 #include <sys/archsystm.h>
41 #include <sys/vmem.h>
42 #include <vm/seg_kmem.h>
43 #include <sys/errno.h>
44 #include <sys/cmn_err.h>
45 #include <sys/debug.h>
46 #include <sys/atomic.h>
47 #include <sys/model.h>
48 #include <sys/kmem.h>
49 #include <sys/memlist.h>
50 #include <sys/autoconf.h>
51 #include <sys/ontrap.h>
52 #include <sys/utsname.h>
53 #include <sys/zone.h>
54 
55 #ifdef __sparc
56 #include <sys/membar.h>
57 #endif
58 
59 /*
60  * Routine which sets a user error; placed in
61  * illegal entries in the bdevsw and cdevsw tables.
62  */
63 
64 int
65 nodev()
66 {
67 	return (curthread->t_lwp ?
68 	    ttolwp(curthread)->lwp_error = ENXIO : ENXIO);
69 }
70 
71 /*
72  * Null routine; placed in insignificant entries
73  * in the bdevsw and cdevsw tables.
74  */
75 
76 int
77 nulldev()
78 {
79 	return (0);
80 }
81 
82 static kmutex_t udevlock;
83 
84 /*
85  * Generate an unused major device number.
86  */
87 major_t
88 getudev()
89 {
90 	static major_t next = 0;
91 	major_t ret;
92 
93 	/*
94 	 * Ensure that we start allocating major numbers above the 'devcnt'
95 	 * count.  The only limit we place on the number is that it should be a
96 	 * legal 32-bit SVR4 major number and be greater than or equal to devcnt
97 	 * in the current system).
98 	 */
99 	mutex_enter(&udevlock);
100 	if (next == 0)
101 		next = devcnt;
102 	if (next <= L_MAXMAJ32 && next >= devcnt)
103 		ret = next++;
104 	else {
105 		/*
106 		 * If we fail to allocate a major number because devcnt has
107 		 * reached L_MAXMAJ32, we may be the victim of a sparsely
108 		 * populated devnames array.  We scan the array backwards
109 		 * looking for an empty slot;  if we find one, mark it as
110 		 * DN_GETUDEV so it doesn't get taken by subsequent consumers
111 		 * users of the devnames array, and issue a warning.
112 		 * It is vital for this routine to take drastic measures to
113 		 * succeed, since the kernel really needs it to boot.
114 		 */
115 		int i;
116 		for (i = devcnt - 1; i >= 0; i--) {
117 			LOCK_DEV_OPS(&devnamesp[i].dn_lock);
118 			if (devnamesp[i].dn_name == NULL &&
119 			    ((devnamesp[i].dn_flags & DN_TAKEN_GETUDEV) == 0))
120 				break;
121 			UNLOCK_DEV_OPS(&devnamesp[i].dn_lock);
122 		}
123 		if (i != -1) {
124 			cmn_err(CE_WARN, "Reusing device major number %d.", i);
125 			ASSERT(i >= 0 && i < devcnt);
126 			devnamesp[i].dn_flags |= DN_TAKEN_GETUDEV;
127 			UNLOCK_DEV_OPS(&devnamesp[i].dn_lock);
128 			ret = (major_t)i;
129 		} else {
130 			ret = DDI_MAJOR_T_NONE;
131 		}
132 	}
133 	mutex_exit(&udevlock);
134 	return (ret);
135 }
136 
137 
138 /*
139  * Compress 'long' device number encoding to 32-bit device number
140  * encoding.  If it won't fit, we return failure, but set the
141  * device number to 32-bit NODEV for the sake of our callers.
142  */
143 int
144 cmpldev(dev32_t *dst, dev_t dev)
145 {
146 #if defined(_LP64)
147 	if (dev == NODEV) {
148 		*dst = NODEV32;
149 	} else {
150 		major_t major = dev >> L_BITSMINOR;
151 		minor_t minor = dev & L_MAXMIN;
152 
153 		if (major > L_MAXMAJ32 || minor > L_MAXMIN32) {
154 			*dst = NODEV32;
155 			return (0);
156 		}
157 
158 		*dst = (dev32_t)((major << L_BITSMINOR32) | minor);
159 	}
160 #else
161 	*dst = (dev32_t)dev;
162 #endif
163 	return (1);
164 }
165 
166 /*
167  * Expand 32-bit dev_t's to long dev_t's.  Expansion always "fits"
168  * into the return type, but we're careful to expand NODEV explicitly.
169  */
170 dev_t
171 expldev(dev32_t dev32)
172 {
173 #ifdef _LP64
174 	if (dev32 == NODEV32)
175 		return (NODEV);
176 	return (makedevice((dev32 >> L_BITSMINOR32) & L_MAXMAJ32,
177 	    dev32 & L_MAXMIN32));
178 #else
179 	return ((dev_t)dev32);
180 #endif
181 }
182 
183 #ifndef _LP64
184 /*
185  * Keep these entry points for 32-bit systems but enforce the use
186  * of MIN/MAX macros on 64-bit systems.  The DDI header files already
187  * define min/max as macros so drivers shouldn't need these functions.
188  */
189 
190 int
191 min(int a, int b)
192 {
193 	return (a < b ? a : b);
194 }
195 
196 int
197 max(int a, int b)
198 {
199 	return (a > b ? a : b);
200 }
201 
202 uint_t
203 umin(uint_t a, uint_t b)
204 {
205 	return (a < b ? a : b);
206 }
207 
208 uint_t
209 umax(uint_t a, uint_t b)
210 {
211 	return (a > b ? a : b);
212 }
213 
214 #endif /* !_LP64 */
215 
216 /*
217  * Parse suboptions from a string.
218  * Same as getsubopt(3C).
219  */
220 int
221 getsubopt(char **optionsp, char * const *tokens, char **valuep)
222 {
223 	char *s = *optionsp, *p;
224 	int i;
225 	size_t optlen;
226 
227 	*valuep = NULL;
228 	if (*s == '\0')
229 		return (-1);
230 	p = strchr(s, ',');		/* find next option */
231 	if (p == NULL) {
232 		p = s + strlen(s);
233 	} else {
234 		*p++ = '\0';		/* mark end and point to next */
235 	}
236 	*optionsp = p;			/* point to next option */
237 	p = strchr(s, '=');		/* find value */
238 	if (p == NULL) {
239 		optlen = strlen(s);
240 		*valuep = NULL;
241 	} else {
242 		optlen = p - s;
243 		*valuep = ++p;
244 	}
245 	for (i = 0; tokens[i] != NULL; i++) {
246 		if ((optlen == strlen(tokens[i])) &&
247 		    (strncmp(s, tokens[i], optlen) == 0))
248 			return (i);
249 	}
250 	/* no match, point value at option and return error */
251 	*valuep = s;
252 	return (-1);
253 }
254 
255 /*
256  * Append the suboption string 'opt' starting at the position 'str'
257  * within the buffer defined by 'buf' and 'len'. If 'buf' is not null,
258  * a comma is appended first.
259  * Return a pointer to the end of the resulting string (the null byte).
260  * Return NULL if there isn't enough space left to append 'opt'.
261  */
262 char *
263 append_subopt(const char *buf, size_t len, char *str, const char *opt)
264 {
265 	size_t l = strlen(opt);
266 
267 	/*
268 	 * Include a ',' if this is not the first option.
269 	 * Include space for the null byte.
270 	 */
271 	if (strlen(buf) + (buf[0] != '\0') + l + 1 > len)
272 		return (NULL);
273 
274 	if (buf[0] != '\0')
275 		*str++ = ',';
276 	(void) strcpy(str, opt);
277 	return (str + l);
278 }
279 
280 /*
281  * Tables to convert a single byte to/from binary-coded decimal (BCD).
282  */
283 uchar_t byte_to_bcd[256] = {
284 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
285 	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
286 	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
287 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
288 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
289 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
290 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
291 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
292 	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
293 	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
294 };
295 
296 uchar_t bcd_to_byte[256] = {		/* CSTYLED */
297 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0,  0,  0,  0,  0,  0,
298 	10, 11, 12, 13, 14, 15, 16, 17, 18, 19,  0,  0,  0,  0,  0,  0,
299 	20, 21, 22, 23, 24, 25, 26, 27, 28, 29,  0,  0,  0,  0,  0,  0,
300 	30, 31, 32, 33, 34, 35, 36, 37, 38, 39,  0,  0,  0,  0,  0,  0,
301 	40, 41, 42, 43, 44, 45, 46, 47, 48, 49,  0,  0,  0,  0,  0,  0,
302 	50, 51, 52, 53, 54, 55, 56, 57, 58, 59,  0,  0,  0,  0,  0,  0,
303 	60, 61, 62, 63, 64, 65, 66, 67, 68, 69,  0,  0,  0,  0,  0,  0,
304 	70, 71, 72, 73, 74, 75, 76, 77, 78, 79,  0,  0,  0,  0,  0,  0,
305 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89,  0,  0,  0,  0,  0,  0,
306 	90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
307 };
308 
309 /*
310  * Hot-patch a single instruction in the kernel's text.
311  * If you want to patch multiple instructions you must
312  * arrange to do it so that all intermediate stages are
313  * sane -- we don't stop other cpus while doing this.
314  * Size must be 1, 2, or 4 bytes with iaddr aligned accordingly.
315  */
316 void
317 hot_patch_kernel_text(caddr_t iaddr, uint32_t new_instr, uint_t size)
318 {
319 	caddr_t vaddr;
320 	page_t **ppp;
321 	uintptr_t off = (uintptr_t)iaddr & PAGEOFFSET;
322 
323 	vaddr = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
324 
325 	(void) as_pagelock(&kas, &ppp, iaddr - off, PAGESIZE, S_WRITE);
326 
327 	hat_devload(kas.a_hat, vaddr, PAGESIZE,
328 	    hat_getpfnum(kas.a_hat, iaddr - off),
329 	    PROT_READ | PROT_WRITE, HAT_LOAD_LOCK | HAT_LOAD_NOCONSIST);
330 
331 	switch (size) {
332 	case 1:
333 		*(uint8_t *)(vaddr + off) = new_instr;
334 		break;
335 	case 2:
336 		*(uint16_t *)(vaddr + off) = new_instr;
337 		break;
338 	case 4:
339 		*(uint32_t *)(vaddr + off) = new_instr;
340 		break;
341 	default:
342 		panic("illegal hot-patch");
343 	}
344 
345 	membar_enter();
346 	sync_icache(vaddr + off, size);
347 	sync_icache(iaddr, size);
348 	as_pageunlock(&kas, ppp, iaddr - off, PAGESIZE, S_WRITE);
349 	hat_unload(kas.a_hat, vaddr, PAGESIZE, HAT_UNLOAD_UNLOCK);
350 	vmem_free(heap_arena, vaddr, PAGESIZE);
351 }
352 
353 /*
354  * Routine to report an attempt to execute non-executable data.  If the
355  * address executed lies in the stack, explicitly say so.
356  */
357 void
358 report_stack_exec(proc_t *p, caddr_t addr)
359 {
360 	if (!noexec_user_stack_log)
361 		return;
362 
363 	if (addr < p->p_usrstack && addr >= (p->p_usrstack - p->p_stksize)) {
364 		cmn_err(CE_NOTE, "%s[%d] attempt to execute code "
365 		    "on stack by uid %d", p->p_user.u_comm,
366 		    p->p_pid, crgetruid(p->p_cred));
367 	} else {
368 		cmn_err(CE_NOTE, "%s[%d] attempt to execute non-executable "
369 		    "data at 0x%p by uid %d", p->p_user.u_comm,
370 		    p->p_pid, (void *) addr, crgetruid(p->p_cred));
371 	}
372 
373 	delay(hz / 50);
374 }
375 
376 /*
377  * Determine whether the address range [addr, addr + len) is in memlist mp.
378  */
379 int
380 address_in_memlist(struct memlist *mp, uint64_t addr, size_t len)
381 {
382 	while (mp != 0)	 {
383 		if ((addr >= mp->ml_address) &&
384 		    (addr + len <= mp->ml_address + mp->ml_size))
385 			return (1);	 /* TRUE */
386 		mp = mp->ml_next;
387 	}
388 	return (0);	/* FALSE */
389 }
390 
391 /*
392  * Pop the topmost element from the t_ontrap stack, removing the current set of
393  * on_trap() protections.  Refer to <sys/ontrap.h> for more info.  If the
394  * stack is already empty, no_trap() just returns.
395  */
396 void
397 no_trap(void)
398 {
399 	if (curthread->t_ontrap != NULL) {
400 #ifdef __sparc
401 		membar_sync(); /* deferred error barrier (see sparcv9_subr.s) */
402 #endif
403 		curthread->t_ontrap = curthread->t_ontrap->ot_prev;
404 	}
405 }
406 
407 /*
408  * Return utsname.nodename outside a zone, or the zone name within.
409  */
410 char *
411 uts_nodename(void)
412 {
413 	if (curproc == NULL)
414 		return (utsname.nodename);
415 	return (curproc->p_zone->zone_nodename);
416 }
417