xref: /illumos-gate/usr/src/lib/libproc/common/pr_meminfo.c (revision 1da57d551424de5a9d469760be7c4b4d4f10a755)
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, Version 1.0 only
6   * (the "License").  You may not use this file except in compliance
7   * with the License.
8   *
9   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10   * or http://www.opensolaris.org/os/licensing.
11   * See the License for the specific language governing permissions
12   * and limitations under the License.
13   *
14   * When distributing Covered Code, include this CDDL HEADER in each
15   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16   * If applicable, add the following below this CDDL HEADER, with the
17   * fields enclosed by brackets "[]" replaced with your own identifying
18   * information: Portions Copyright [yyyy] [name of copyright owner]
19   *
20   * CDDL HEADER END
21   */
22  /*
23   * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
24   * Use is subject to license terms.
25   */
26  
27  #include <stdlib.h>
28  #include <unistd.h>
29  #include <errno.h>
30  #include <sys/types.h>
31  #include <sys/mman.h>
32  #include "libproc.h"
33  #include "Pcontrol.h"
34  #include "Putil.h"
35  
36  
37  int
pr_meminfo(struct ps_prochandle * Pr,const uint64_t * addrs,int addr_count,const uint_t * info,int info_count,uint64_t * outdata,uint_t * validity)38  pr_meminfo(struct ps_prochandle *Pr, const uint64_t *addrs,
39  	int addr_count, const uint_t *info, int info_count,
40  	uint64_t *outdata, uint_t *validity)
41  {
42  
43  
44  	int error;
45  	sysret_t rval;
46  	argdes_t argd[7];
47  	argdes_t *adp = &argd[0];
48  	struct meminfo m;
49  #ifdef _LP64
50  	struct meminfo32 m32;
51  	int model;
52  #endif
53  	int retval = -1;
54  	uintptr_t inaddr, infoaddr, outaddr, validityaddr;
55  	size_t outarraysize, infoarraysize;
56  	size_t inarraysize, validityarraysize;
57  	size_t totalsize;
58  	char *totalmap = MAP_FAILED;
59  
60  	inarraysize = addr_count * sizeof (uint64_t);
61  	outarraysize = sizeof (uint64_t) * addr_count * info_count;
62  	infoarraysize = info_count * sizeof (uint_t);
63  	validityarraysize = sizeof (uint_t) * addr_count;
64  
65  
66  	totalsize = inarraysize + outarraysize + infoarraysize +
67  		validityarraysize;
68  
69  	if ((totalmap  = pr_zmap(Pr, 0, totalsize, PROT_READ | PROT_WRITE,
70  		MAP_PRIVATE)) == MAP_FAILED) {
71  		dprintf("pr_meminfo: mmap failed\n");
72  		goto out;
73  	}
74  
75  	inaddr = (uintptr_t)totalmap;
76  
77  	outaddr = inaddr + inarraysize;
78  
79  	infoaddr = outaddr + outarraysize;
80  
81  	validityaddr = infoaddr + infoarraysize;
82  
83  	if (Pwrite(Pr, addrs, inarraysize, inaddr) != inarraysize) {
84  		dprintf("pr_meminfo: Pwrite inaddr failed \n");
85  		goto out;
86  	}
87  
88  	if (Pwrite(Pr, info, infoarraysize, infoaddr) !=
89  	    infoarraysize) {
90  		dprintf("pr_meminfo: Pwrite info failed \n");
91  		goto out;
92  	}
93  
94  #ifdef _LP64
95  	model = Pr->status.pr_dmodel;
96  	if (model == PR_MODEL_ILP32) {
97  		m32.mi_info_count = info_count;
98  		m32.mi_inaddr = (caddr32_t)inaddr;
99  		m32.mi_outdata = (caddr32_t)outaddr;
100  		m32.mi_info_req = (caddr32_t)infoaddr;
101  		m32.mi_validity = (caddr32_t)validityaddr;
102  	} else
103  #endif
104  	{
105  		m.mi_info_count = info_count;
106  		m.mi_inaddr = (uint64_t *)inaddr;
107  		m.mi_outdata = (uint64_t *)outaddr;
108  		m.mi_info_req = (uint_t *)infoaddr;
109  		m.mi_validity = (uint_t *)validityaddr;
110  	}
111  
112  
113  	/*
114  	 * initial command
115  	 */
116  
117  	adp->arg_value = MISYS_MEMINFO;
118  	adp->arg_object = NULL;
119  	adp->arg_type = AT_BYVAL;
120  	adp->arg_inout = AI_INPUT;
121  	adp->arg_size = 0;
122  	adp++;
123  
124  	/*
125  	 * length of input address vector
126  	 */
127  
128  	adp->arg_value = addr_count;
129  	adp->arg_object = NULL;
130  	adp->arg_type = AT_BYVAL;
131  	adp->arg_inout = AI_INPUT;
132  	adp->arg_size = 0;
133  	adp++;
134  
135  	/*
136  	 * information wanted vector
137  	 */
138  
139  	adp->arg_value = 0;
140  #ifdef _LP64
141  	if (model == PR_MODEL_ILP32) {
142  		adp->arg_object = &m32;
143  		adp->arg_size = sizeof (struct meminfo32);
144  	} else
145  #endif
146  	{
147  		adp->arg_object = &m;
148  		adp->arg_size = sizeof (struct meminfo);
149  	}
150  	adp->arg_type = AT_BYREF;
151  	adp->arg_inout = AI_INPUT;
152  
153  
154  	error = Psyscall(Pr,  &rval, SYS_meminfosys, 3, &argd[0]);
155  
156  	if (error) {
157  		errno = (error > 0) ? error: ENOSYS;
158  		goto out;
159  	}
160  
161  	/* syscall was successful, copy out the data */
162  
163  	if ((Pread(Pr, outdata, outarraysize, outaddr)) != outarraysize) {
164  		dprintf("pr_meminfo: Pread of outarray failed\n");
165  		goto out;
166  	}
167  
168  	if (Pread(Pr, validity, validityarraysize, validityaddr)
169  	    != validityarraysize) {
170  		dprintf("pr_meminfo: Pread of validity array failed\n");
171  		goto out;
172  	}
173  
174  	retval = rval.sys_rval1;
175  
176  out:
177  
178  	if (totalmap != MAP_FAILED &&
179  	    pr_munmap(Pr, totalmap, totalsize) == -1) {
180  			dprintf("pr_meminfo: munmap failed\n");
181  			retval = -1;
182  		}
183  
184  	return (retval);
185  
186  }
187