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