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) © 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