make vfs & filesystems use failable copying
[minix3.git] / kernel / system / do_getinfo.c
blob94818c89d2d69b3d36a5c7574bcb600c0235283f
1 /* The kernel call implemented in this file:
2 * m_type: SYS_GETINFO
4 * The parameters for this kernel call are:
5 * m1_i3: I_REQUEST (what info to get)
6 * m1_p1: I_VAL_PTR (where to put it)
7 * m1_i1: I_VAL_LEN (maximum length expected, optional)
8 * m1_p2: I_VAL_PTR2 (second, optional pointer)
9 * m1_i2: I_VAL_LEN2_E (second length or process nr)
12 #include <string.h>
14 #include "kernel/system.h"
17 #if USE_GETINFO
19 #include <minix/u64.h>
20 #include <sys/resource.h>
22 /*===========================================================================*
23 * update_idle_time *
24 *===========================================================================*/
25 static void update_idle_time(void)
27 int i;
28 struct proc * idl = proc_addr(IDLE);
30 idl->p_cycles = make64(0, 0);
32 for (i = 0; i < CONFIG_MAX_CPUS ; i++) {
33 idl->p_cycles += get_cpu_var(i, idle_proc).p_cycles;
37 /*===========================================================================*
38 * do_getinfo *
39 *===========================================================================*/
40 int do_getinfo(struct proc * caller, message * m_ptr)
42 /* Request system information to be copied to caller's address space. This
43 * call simply copies entire data structures to the caller.
45 size_t length;
46 vir_bytes src_vir;
47 int nr_e, nr, r;
48 int wipe_rnd_bin = -1;
49 struct proc *p;
50 struct rusage r_usage;
52 /* Set source address and length based on request type. */
53 switch (m_ptr->I_REQUEST) {
54 case GET_MACHINE: {
55 length = sizeof(struct machine);
56 src_vir = (vir_bytes) &machine;
57 break;
59 case GET_KINFO: {
60 length = sizeof(struct kinfo);
61 src_vir = (vir_bytes) &kinfo;
62 break;
64 case GET_LOADINFO: {
65 length = sizeof(struct loadinfo);
66 src_vir = (vir_bytes) &kloadinfo;
67 break;
69 case GET_CPUINFO: {
70 length = sizeof(cpu_info);
71 src_vir = (vir_bytes) &cpu_info;
72 break;
74 case GET_HZ: {
75 length = sizeof(system_hz);
76 src_vir = (vir_bytes) &system_hz;
77 break;
79 case GET_IMAGE: {
80 length = sizeof(struct boot_image) * NR_BOOT_PROCS;
81 src_vir = (vir_bytes) image;
82 break;
84 case GET_IRQHOOKS: {
85 length = sizeof(struct irq_hook) * NR_IRQ_HOOKS;
86 src_vir = (vir_bytes) irq_hooks;
87 break;
89 case GET_PROCTAB: {
90 update_idle_time();
91 length = sizeof(struct proc) * (NR_PROCS + NR_TASKS);
92 src_vir = (vir_bytes) proc;
93 break;
95 case GET_PRIVTAB: {
96 length = sizeof(struct priv) * (NR_SYS_PROCS);
97 src_vir = (vir_bytes) priv;
98 break;
100 case GET_PROC: {
101 nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
102 caller->p_endpoint : m_ptr->I_VAL_LEN2_E;
103 if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
104 length = sizeof(struct proc);
105 src_vir = (vir_bytes) proc_addr(nr);
106 break;
108 case GET_PRIV: {
109 nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
110 caller->p_endpoint : m_ptr->I_VAL_LEN2_E;
111 if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
112 length = sizeof(struct priv);
113 src_vir = (vir_bytes) priv_addr(nr_to_id(nr));
114 break;
116 case GET_REGS: {
117 nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
118 caller->p_endpoint : m_ptr->I_VAL_LEN2_E;
119 if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
120 p = proc_addr(nr);
121 length = sizeof(p->p_reg);
122 src_vir = (vir_bytes) &p->p_reg;
123 break;
125 case GET_WHOAMI: {
126 int len;
127 /* GET_WHOAMI uses m3 and only uses the message contents for info. */
128 m_ptr->GIWHO_EP = caller->p_endpoint;
129 len = MIN(sizeof(m_ptr->GIWHO_NAME), sizeof(caller->p_name))-1;
130 strncpy(m_ptr->GIWHO_NAME, caller->p_name, len);
131 m_ptr->GIWHO_NAME[len] = '\0';
132 m_ptr->GIWHO_PRIVFLAGS = priv(caller)->s_flags;
133 return OK;
135 case GET_MONPARAMS: {
136 src_vir = (vir_bytes) kinfo.param_buf;
137 length = sizeof(kinfo.param_buf);
138 break;
140 case GET_RANDOMNESS: {
141 static struct k_randomness copy; /* copy to keep counters */
142 int i;
144 copy = krandom;
145 for (i= 0; i<RANDOM_SOURCES; i++) {
146 krandom.bin[i].r_size = 0; /* invalidate random data */
147 krandom.bin[i].r_next = 0;
149 length = sizeof(copy);
150 src_vir = (vir_bytes) &copy;
151 break;
153 case GET_RANDOMNESS_BIN: {
154 int bin = m_ptr->I_VAL_LEN2_E;
156 if(bin < 0 || bin >= RANDOM_SOURCES) {
157 printf("SYSTEM: GET_RANDOMNESS_BIN: %d out of range\n", bin);
158 return EINVAL;
161 if(krandom.bin[bin].r_size < RANDOM_ELEMENTS)
162 return ENOENT;
164 length = sizeof(krandom.bin[bin]);
165 src_vir = (vir_bytes) &krandom.bin[bin];
167 wipe_rnd_bin = bin;
169 break;
171 case GET_IRQACTIDS: {
172 length = sizeof(irq_actids);
173 src_vir = (vir_bytes) irq_actids;
174 break;
176 case GET_IDLETSC: {
177 struct proc * idl;
178 update_idle_time();
179 idl = proc_addr(IDLE);
180 length = sizeof(idl->p_cycles);
181 src_vir = (vir_bytes) &idl->p_cycles;
182 break;
184 case GET_RUSAGE: {
185 struct proc *target = NULL;
186 int target_slot = 0;
187 u64_t usec;
188 nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
189 caller->p_endpoint : m_ptr->I_VAL_LEN2_E;
191 if (!isokendpt(nr_e, &target_slot))
192 return EINVAL;
194 target = proc_addr(target_slot);
195 if (isemptyp(target))
196 return EINVAL;
198 length = sizeof(r_usage);
199 memset(&r_usage, 0, sizeof(r_usage));
200 usec = target->p_user_time * 1000000 / system_hz;
201 r_usage.ru_utime.tv_sec = usec / 1000000;
202 r_usage.ru_utime.tv_usec = usec % 100000;
203 usec = target->p_sys_time * 1000000 / system_hz;
204 r_usage.ru_stime.tv_sec = usec / 1000000;
205 r_usage.ru_stime.tv_usec = usec % 100000;
206 r_usage.ru_nsignals = target->p_signal_received;
207 src_vir = (vir_bytes) &r_usage;
208 break;
210 default:
211 printf("do_getinfo: invalid request %d\n", m_ptr->I_REQUEST);
212 return(EINVAL);
215 /* Try to make the actual copy for the requested data. */
216 if (m_ptr->I_VAL_LEN > 0 && length > m_ptr->I_VAL_LEN) return (E2BIG);
217 r = data_copy_vmcheck(caller, KERNEL, src_vir, caller->p_endpoint,
218 (vir_bytes) m_ptr->I_VAL_PTR, length);
220 if(r != OK) return r;
222 if(wipe_rnd_bin >= 0 && wipe_rnd_bin < RANDOM_SOURCES) {
223 krandom.bin[wipe_rnd_bin].r_size = 0;
224 krandom.bin[wipe_rnd_bin].r_next = 0;
227 return(OK);
230 #endif /* USE_GETINFO */