xref: /minix3/minix/kernel/system/do_getinfo.c (revision 4f89addcc198bff2fc614da2f8f4a7beb4b6cb7d)
1 /* The kernel call implemented in this file:
2  *   m_type:	SYS_GETINFO
3  *
4  * The parameters for this kernel call are:
5  *   m_lsys_krn_sys_getinfo.request	(what info to get)
6  *   m_lsys_krn_sys_getinfo.val_ptr 	(where to put it)
7  *   m_lsys_krn_sys_getinfo.val_len 	(maximum length expected, optional)
8  *   m_lsys_krn_sys_getinfo.val_ptr2	(second, optional pointer)
9  *   m_lsys_krn_sys_getinfo.val_len2_e	(second length or process nr)
10  *
11  * Upon return of the GETWHOAMI request the following parameters are used:
12  *   m_krn_lsys_sys_getwhoami.endpt	(the caller endpoint)
13  *   m_krn_lsys_sys_getwhoami.privflags	(the caller priviledes)
14  *   m_krn_lsys_sys_getwhoami.name	(the caller process name)
15  *
16  */
17 
18 #include <string.h>
19 
20 #include "kernel/system.h"
21 
22 
23 #if USE_GETINFO
24 
25 #include <minix/u64.h>
26 #include <sys/resource.h>
27 
28 /*===========================================================================*
29  *			        update_idle_time			     *
30  *===========================================================================*/
31 static void update_idle_time(void)
32 {
33 	int i;
34 	struct proc * idl = proc_addr(IDLE);
35 
36 	idl->p_cycles = make64(0, 0);
37 
38 	for (i = 0; i < CONFIG_MAX_CPUS ; i++) {
39 		idl->p_cycles += get_cpu_var(i, idle_proc).p_cycles;
40 	}
41 }
42 
43 /*===========================================================================*
44  *			        do_getinfo				     *
45  *===========================================================================*/
46 int do_getinfo(struct proc * caller, message * m_ptr)
47 {
48 /* Request system information to be copied to caller's address space. This
49  * call simply copies entire data structures to the caller.
50  */
51   size_t length;
52   vir_bytes src_vir;
53   int nr_e, nr, r;
54   int wipe_rnd_bin = -1;
55   struct proc *p;
56   struct rusage r_usage;
57 
58   /* Set source address and length based on request type. */
59   switch (m_ptr->m_lsys_krn_sys_getinfo.request) {
60     case GET_MACHINE: {
61         length = sizeof(struct machine);
62         src_vir = (vir_bytes) &machine;
63         break;
64     }
65     case GET_KINFO: {
66         length = sizeof(struct kinfo);
67         src_vir = (vir_bytes) &kinfo;
68         break;
69     }
70     case GET_LOADINFO: {
71         length = sizeof(struct loadinfo);
72         src_vir = (vir_bytes) &kloadinfo;
73         break;
74     }
75     case GET_CPUINFO: {
76         length = sizeof(cpu_info);
77         src_vir = (vir_bytes) &cpu_info;
78         break;
79     }
80     case GET_HZ: {
81         length = sizeof(system_hz);
82         src_vir = (vir_bytes) &system_hz;
83         break;
84     }
85     case GET_IMAGE: {
86         length = sizeof(struct boot_image) * NR_BOOT_PROCS;
87         src_vir = (vir_bytes) image;
88         break;
89     }
90     case GET_IRQHOOKS: {
91         length = sizeof(struct irq_hook) * NR_IRQ_HOOKS;
92         src_vir = (vir_bytes) irq_hooks;
93         break;
94     }
95     case GET_PROCTAB: {
96 	update_idle_time();
97         length = sizeof(struct proc) * (NR_PROCS + NR_TASKS);
98         src_vir = (vir_bytes) proc;
99         break;
100     }
101     case GET_PRIVTAB: {
102         length = sizeof(struct priv) * (NR_SYS_PROCS);
103         src_vir = (vir_bytes) priv;
104         break;
105     }
106     case GET_PROC: {
107         nr_e = (m_ptr->m_lsys_krn_sys_getinfo.val_len2_e == SELF) ?
108 		caller->p_endpoint : m_ptr->m_lsys_krn_sys_getinfo.val_len2_e;
109 	if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
110         length = sizeof(struct proc);
111         src_vir = (vir_bytes) proc_addr(nr);
112         break;
113     }
114     case GET_PRIV: {
115         nr_e = (m_ptr->m_lsys_krn_sys_getinfo.val_len2_e == SELF) ?
116             caller->p_endpoint : m_ptr->m_lsys_krn_sys_getinfo.val_len2_e;
117         if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
118         length = sizeof(struct priv);
119         src_vir = (vir_bytes) priv_addr(nr_to_id(nr));
120         break;
121     }
122     case GET_REGS: {
123         nr_e = (m_ptr->m_lsys_krn_sys_getinfo.val_len2_e == SELF) ?
124             caller->p_endpoint : m_ptr->m_lsys_krn_sys_getinfo.val_len2_e;
125         if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
126         p = proc_addr(nr);
127         length = sizeof(p->p_reg);
128         src_vir = (vir_bytes) &p->p_reg;
129         break;
130     }
131     case GET_WHOAMI: {
132 	int len;
133 	m_ptr->m_krn_lsys_sys_getwhoami.endpt = caller->p_endpoint;
134 	len = MIN(sizeof(m_ptr->m_krn_lsys_sys_getwhoami.name),
135 		sizeof(caller->p_name))-1;
136 	strncpy(m_ptr->m_krn_lsys_sys_getwhoami.name, caller->p_name, len);
137 	m_ptr->m_krn_lsys_sys_getwhoami.name[len] = '\0';
138 	m_ptr->m_krn_lsys_sys_getwhoami.privflags = priv(caller)->s_flags;
139 	return OK;
140     }
141     case GET_MONPARAMS: {
142         src_vir = (vir_bytes) kinfo.param_buf;
143 	length = sizeof(kinfo.param_buf);
144         break;
145     }
146     case GET_RANDOMNESS: {
147         static struct k_randomness copy;	/* copy to keep counters */
148 	int i;
149 
150         copy = krandom;
151         for (i= 0; i<RANDOM_SOURCES; i++) {
152   		krandom.bin[i].r_size = 0;	/* invalidate random data */
153   		krandom.bin[i].r_next = 0;
154 	}
155     	length = sizeof(copy);
156     	src_vir = (vir_bytes) &copy;
157     	break;
158     }
159     case GET_RANDOMNESS_BIN: {
160 	int bin = m_ptr->m_lsys_krn_sys_getinfo.val_len2_e;
161 
162 	if(bin < 0 || bin >= RANDOM_SOURCES) {
163 		printf("SYSTEM: GET_RANDOMNESS_BIN: %d out of range\n", bin);
164 		return EINVAL;
165 	}
166 
167 	if(krandom.bin[bin].r_size < RANDOM_ELEMENTS)
168 		return ENOENT;
169 
170     	length = sizeof(krandom.bin[bin]);
171     	src_vir = (vir_bytes) &krandom.bin[bin];
172 
173 	wipe_rnd_bin = bin;
174 
175     	break;
176     }
177     case GET_IRQACTIDS: {
178         length = sizeof(irq_actids);
179         src_vir = (vir_bytes) irq_actids;
180         break;
181     }
182     case GET_IDLETSC: {
183 	struct proc * idl;
184 	update_idle_time();
185 	idl = proc_addr(IDLE);
186         length = sizeof(idl->p_cycles);
187         src_vir = (vir_bytes) &idl->p_cycles;
188         break;
189     }
190     case GET_RUSAGE: {
191 	struct proc *target = NULL;
192 	int target_slot = 0;
193 	u64_t usec;
194         nr_e = (m_ptr->m_lsys_krn_sys_getinfo.val_len2_e == SELF) ?
195             caller->p_endpoint : m_ptr->m_lsys_krn_sys_getinfo.val_len2_e;
196 
197 	if (!isokendpt(nr_e, &target_slot))
198 		return EINVAL;
199 
200 	target = proc_addr(target_slot);
201 	if (isemptyp(target))
202 		return EINVAL;
203 
204 	length = sizeof(r_usage);
205 	memset(&r_usage, 0, sizeof(r_usage));
206 	usec = target->p_user_time * 1000000 / system_hz;
207 	r_usage.ru_utime.tv_sec = usec / 1000000;
208 	r_usage.ru_utime.tv_usec = usec % 1000000;
209 	usec = target->p_sys_time * 1000000 / system_hz;
210 	r_usage.ru_stime.tv_sec = usec / 1000000;
211 	r_usage.ru_stime.tv_usec = usec % 1000000;
212 	r_usage.ru_nsignals = target->p_signal_received;
213 	src_vir = (vir_bytes) &r_usage;
214 	break;
215     }
216     default:
217 	printf("do_getinfo: invalid request %d\n",
218 		m_ptr->m_lsys_krn_sys_getinfo.request);
219         return(EINVAL);
220   }
221 
222   /* Try to make the actual copy for the requested data. */
223   if (m_ptr->m_lsys_krn_sys_getinfo.val_len > 0 &&
224 	length > m_ptr->m_lsys_krn_sys_getinfo.val_len)
225 	return (E2BIG);
226 
227   r = data_copy_vmcheck(caller, KERNEL, src_vir, caller->p_endpoint,
228 	m_ptr->m_lsys_krn_sys_getinfo.val_ptr, length);
229 
230   if(r != OK) return r;
231 
232 	if(wipe_rnd_bin >= 0 && wipe_rnd_bin < RANDOM_SOURCES) {
233 		krandom.bin[wipe_rnd_bin].r_size = 0;
234 		krandom.bin[wipe_rnd_bin].r_next = 0;
235 	}
236 
237   return(OK);
238 }
239 
240 #endif /* USE_GETINFO */
241 
242