kernel: trap-dependent state restore, trace fixes
[minix.git] / kernel / system / do_getinfo.c
blob19ab73c147ebbc4ddc69190692a0a1572ba381b9
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>
21 /*===========================================================================*
22 * update_idle_time *
23 *===========================================================================*/
24 static void update_idle_time(void)
26 int i;
27 struct proc * idl = proc_addr(IDLE);
29 idl->p_cycles = make64(0, 0);
31 for (i = 0; i < CONFIG_MAX_CPUS ; i++) {
32 idl->p_cycles = add64(idl->p_cycles,
33 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;
51 /* Set source address and length based on request type. */
52 switch (m_ptr->I_REQUEST) {
53 case GET_MACHINE: {
54 length = sizeof(struct machine);
55 src_vir = (vir_bytes) &machine;
56 break;
58 case GET_KINFO: {
59 length = sizeof(struct kinfo);
60 src_vir = (vir_bytes) &kinfo;
61 break;
63 case GET_LOADINFO: {
64 length = sizeof(struct loadinfo);
65 src_vir = (vir_bytes) &kloadinfo;
66 break;
68 case GET_CPUINFO: {
69 length = sizeof(cpu_info);
70 src_vir = (vir_bytes) &cpu_info;
71 break;
73 case GET_HZ: {
74 length = sizeof(system_hz);
75 src_vir = (vir_bytes) &system_hz;
76 break;
78 case GET_IMAGE: {
79 length = sizeof(struct boot_image) * NR_BOOT_PROCS;
80 src_vir = (vir_bytes) image;
81 break;
83 case GET_IRQHOOKS: {
84 length = sizeof(struct irq_hook) * NR_IRQ_HOOKS;
85 src_vir = (vir_bytes) irq_hooks;
86 break;
88 case GET_PROCTAB: {
89 update_idle_time();
90 length = sizeof(struct proc) * (NR_PROCS + NR_TASKS);
91 src_vir = (vir_bytes) proc;
92 break;
94 case GET_PRIVTAB: {
95 length = sizeof(struct priv) * (NR_SYS_PROCS);
96 src_vir = (vir_bytes) priv;
97 break;
99 case GET_PROC: {
100 nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
101 caller->p_endpoint : m_ptr->I_VAL_LEN2_E;
102 if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
103 length = sizeof(struct proc);
104 src_vir = (vir_bytes) proc_addr(nr);
105 break;
107 case GET_PRIV: {
108 nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
109 caller->p_endpoint : m_ptr->I_VAL_LEN2_E;
110 if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
111 length = sizeof(struct priv);
112 src_vir = (vir_bytes) priv_addr(nr_to_id(nr));
113 break;
115 case GET_REGS: {
116 nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
117 caller->p_endpoint : m_ptr->I_VAL_LEN2_E;
118 if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
119 p = proc_addr(nr);
120 length = sizeof(p->p_reg);
121 src_vir = (vir_bytes) &p->p_reg;
122 break;
124 case GET_WHOAMI: {
125 int len;
126 /* GET_WHOAMI uses m3 and only uses the message contents for info. */
127 m_ptr->GIWHO_EP = caller->p_endpoint;
128 len = MIN(sizeof(m_ptr->GIWHO_NAME), sizeof(caller->p_name))-1;
129 strncpy(m_ptr->GIWHO_NAME, caller->p_name, len);
130 m_ptr->GIWHO_NAME[len] = '\0';
131 m_ptr->GIWHO_PRIVFLAGS = priv(caller)->s_flags;
132 return OK;
134 case GET_MONPARAMS: {
135 src_vir = (vir_bytes) kinfo.param_buf;
136 length = sizeof(kinfo.param_buf);
137 break;
139 case GET_RANDOMNESS: {
140 static struct k_randomness copy; /* copy to keep counters */
141 int i;
143 copy = krandom;
144 for (i= 0; i<RANDOM_SOURCES; i++) {
145 krandom.bin[i].r_size = 0; /* invalidate random data */
146 krandom.bin[i].r_next = 0;
148 length = sizeof(copy);
149 src_vir = (vir_bytes) &copy;
150 break;
152 case GET_RANDOMNESS_BIN: {
153 int bin = m_ptr->I_VAL_LEN2_E;
155 if(bin < 0 || bin >= RANDOM_SOURCES) {
156 printf("SYSTEM: GET_RANDOMNESS_BIN: %d out of range\n", bin);
157 return EINVAL;
160 if(krandom.bin[bin].r_size < RANDOM_ELEMENTS)
161 return ENOENT;
163 length = sizeof(krandom.bin[bin]);
164 src_vir = (vir_bytes) &krandom.bin[bin];
166 wipe_rnd_bin = bin;
168 break;
170 case GET_IRQACTIDS: {
171 length = sizeof(irq_actids);
172 src_vir = (vir_bytes) irq_actids;
173 break;
175 case GET_IDLETSC: {
176 struct proc * idl;
177 update_idle_time();
178 idl = proc_addr(IDLE);
179 length = sizeof(idl->p_cycles);
180 src_vir = (vir_bytes) &idl->p_cycles;
181 break;
183 default:
184 printf("do_getinfo: invalid request %d\n", m_ptr->I_REQUEST);
185 return(EINVAL);
188 /* Try to make the actual copy for the requested data. */
189 if (m_ptr->I_VAL_LEN > 0 && length > m_ptr->I_VAL_LEN) return (E2BIG);
190 r = data_copy_vmcheck(caller, KERNEL, src_vir, caller->p_endpoint,
191 (vir_bytes) m_ptr->I_VAL_PTR, length);
193 if(r != OK) return r;
195 if(wipe_rnd_bin >= 0 && wipe_rnd_bin < RANDOM_SOURCES) {
196 krandom.bin[wipe_rnd_bin].r_size = 0;
197 krandom.bin[wipe_rnd_bin].r_next = 0;
200 return(OK);
203 #endif /* USE_GETINFO */