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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/systm.h>
28 #include <vm/page.h>
29 #include <sys/errno.h>
30 
31 /*
32  * Return supported page sizes.
33  */
34 int
getpagesizes(int legacy,size_t * buf,int nelem)35 getpagesizes(int legacy, size_t *buf, int nelem)
36 {
37 	int i, pagesizes = page_num_user_pagesizes(legacy);
38 	size_t *pgsza;
39 
40 	if (nelem < 0) {
41 		return (set_errno(EINVAL));
42 	}
43 	if (nelem == 0 && buf != NULL) {
44 		return (set_errno(EINVAL));
45 	}
46 	if (nelem == 0 && buf == NULL) {
47 		return (pagesizes);
48 	}
49 	if (buf == NULL) {
50 		return (set_errno(EINVAL));
51 	}
52 	if (nelem > pagesizes) {
53 		nelem = pagesizes;
54 	}
55 	pgsza = kmem_alloc(sizeof (*pgsza) * nelem, KM_SLEEP);
56 	for (i = 0; i < nelem; i++) {
57 		pgsza[i] = page_get_user_pagesize(i);
58 	}
59 	if (copyout(pgsza, buf, nelem * sizeof (*pgsza)) != 0) {
60 		kmem_free(pgsza, sizeof (*pgsza) * nelem);
61 		return (set_errno(EFAULT));
62 	}
63 	kmem_free(pgsza, sizeof (*pgsza) * nelem);
64 	return (nelem);
65 }
66 
67 #if defined(_SYSCALL32_IMPL)
68 
69 /*
70  * Some future platforms will support page sizes larger than
71  * a 32-bit address space.
72  */
73 int
getpagesizes32(int legacy,size32_t * buf,int nelem)74 getpagesizes32(int legacy, size32_t *buf, int nelem)
75 {
76 	int i, pagesizes = page_num_user_pagesizes(legacy);
77 	size32_t *pgsza32;
78 	size_t pgsz;
79 	int rc;
80 
81 	if (nelem < 0) {
82 		return (set_errno(EINVAL));
83 	}
84 	if (nelem == 0 && buf != NULL) {
85 		return (set_errno(EINVAL));
86 	}
87 
88 	pgsza32 = kmem_alloc(sizeof (*pgsza32) * pagesizes, KM_SLEEP);
89 	for (i = 0; i < pagesizes; i++) {
90 		pgsz = page_get_user_pagesize(i);
91 		pgsza32[i] = (size32_t)pgsz;
92 		if (pgsz > (size32_t)-1) {
93 			pagesizes = i - 1;
94 			break;
95 		}
96 	}
97 	ASSERT(pagesizes > 0);
98 	ASSERT(page_get_user_pagesize(pagesizes - 1) <= (size32_t)-1);
99 	if (nelem > pagesizes) {
100 		nelem = pagesizes;
101 	}
102 	if (nelem == 0 && buf == NULL) {
103 		rc = pagesizes;
104 		goto done;
105 	}
106 	if (buf == NULL) {
107 		rc = set_errno(EINVAL);
108 		goto done;
109 	}
110 	if (copyout(pgsza32, buf, nelem * sizeof (*pgsza32)) != 0) {
111 		rc = set_errno(EFAULT);
112 		goto done;
113 	}
114 	rc = nelem;
115 done:
116 	kmem_free(pgsza32, sizeof (*pgsza32) *
117 	    page_num_user_pagesizes(legacy));
118 	return (rc);
119 }
120 #endif
121