bge: Avoid accessing invalid internal memory region on BCM5906
[dragonfly.git] / sys / kern / kern_kinfo.c
1 /*-
2  * Copyright (c) 2007 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Simon 'corecode' Schubert <corecode@fs.ei.tum.de>
6  * by Thomas E. Spanjaard <tgen@netphreax.net>
7  * 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  * 3. Neither the name of The DragonFly Project nor the names of its
19  *    contributors may be used to endorse or promote products derived
20  *    from this software without specific, prior written permission.
21  * 
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
26  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  * 
35  * $DragonFly: src/sys/kern/kern_kinfo.c,v 1.17 2008/01/07 23:41:55 dillon Exp $
36  */
37
38 /*
39  * This is a source file used by both the kernel and libkvm.
40  */
41
42 #ifndef _KERNEL
43 #define _KERNEL_STRUCTURES
44 #endif
45
46 #include <sys/proc.h>
47 #include <vm/vm_map.h>
48 #include <sys/kinfo.h>
49 #include <sys/tty.h>
50 #include <sys/conf.h>
51 #include <sys/jail.h>
52 #include <sys/mplock2.h>
53 #include <sys/globaldata.h>
54 #ifdef _KERNEL
55 #include <sys/systm.h>
56 #include <sys/sysref.h>
57 #include <sys/sysref2.h>
58 #else
59 #include <string.h>
60
61 dev_t dev2udev(cdev_t dev);     /* kvm_proc.c */
62 #endif
63
64
65 /*
66  * Fill in a struct kinfo_proc.
67  *
68  * NOTE!  We may be asked to fill in kinfo_proc for a zombied process, and
69  * the process may be in the middle of being deallocated.  Check all pointers
70  * for NULL.
71  *
72  * Caller must hold p->p_token
73  */
74 void
75 fill_kinfo_proc(struct proc *p, struct kinfo_proc *kp)
76 {
77         struct session *sess;
78         struct pgrp *pgrp;
79         struct vmspace *vm;
80
81         pgrp = p->p_pgrp;
82         sess = pgrp ? pgrp->pg_session : NULL;
83
84         bzero(kp, sizeof(*kp));
85
86         kp->kp_paddr = (uintptr_t)p;
87         kp->kp_fd = (uintptr_t)p->p_fd;
88
89         kp->kp_flags = p->p_flags;
90         kp->kp_stat = p->p_stat;
91         kp->kp_lock = p->p_lock;
92         kp->kp_acflag = p->p_acflag;
93         kp->kp_traceflag = p->p_traceflag;
94         kp->kp_siglist = p->p_siglist;
95         if (p->p_sigacts) {
96                 kp->kp_sigignore = p->p_sigignore;      /* p_sigacts-> */
97                 kp->kp_sigcatch = p->p_sigcatch;        /* p_sigacts-> */
98                 kp->kp_sigflag = p->p_sigacts->ps_flag;
99         }
100         kp->kp_start = p->p_start;
101
102         strncpy(kp->kp_comm, p->p_comm, sizeof(kp->kp_comm) - 1);
103         kp->kp_comm[sizeof(kp->kp_comm) - 1] = 0;
104
105         if (p->p_ucred) {
106                 kp->kp_uid = p->p_ucred->cr_uid;
107                 kp->kp_ngroups = p->p_ucred->cr_ngroups;
108                 if (p->p_ucred->cr_groups) {
109                         bcopy(p->p_ucred->cr_groups, kp->kp_groups,
110                               NGROUPS * sizeof(kp->kp_groups[0]));
111                 }
112                 kp->kp_ruid = p->p_ucred->cr_ruid;
113                 kp->kp_svuid = p->p_ucred->cr_svuid;
114                 kp->kp_rgid = p->p_ucred->cr_rgid;
115                 kp->kp_svgid = p->p_ucred->cr_svgid;
116         }
117
118         kp->kp_pid = p->p_pid;
119         if (p->p_oppid != 0)
120                 kp->kp_ppid = p->p_oppid;
121         else
122                 kp->kp_ppid = p->p_pptr != NULL ? p->p_pptr->p_pid : -1;
123         if (pgrp) {
124                 kp->kp_pgid = pgrp->pg_id;
125                 kp->kp_jobc = pgrp->pg_jobc;
126         }
127         if (sess) {
128                 kp->kp_sid = sess->s_sid;
129                 bcopy(sess->s_login, kp->kp_login, MAXLOGNAME);
130                 if (sess->s_ttyvp != NULL)
131                         kp->kp_auxflags |= KI_CTTY;
132                 if ((p->p_session != NULL) && SESS_LEADER(p))
133                         kp->kp_auxflags |= KI_SLEADER;
134         }
135         if (sess && (p->p_flags & P_CONTROLT) != 0 && sess->s_ttyp != NULL) {
136                 kp->kp_tdev = dev2udev(sess->s_ttyp->t_dev);
137                 if (sess->s_ttyp->t_pgrp != NULL)
138                         kp->kp_tpgid = sess->s_ttyp->t_pgrp->pg_id;
139                 else
140                         kp->kp_tpgid = -1;
141                 if (sess->s_ttyp->t_session != NULL)
142                         kp->kp_tsid = sess->s_ttyp->t_session->s_sid;
143                 else
144                         kp->kp_tsid = -1;
145         } else {
146                 kp->kp_tdev = NOUDEV;
147         }
148         kp->kp_exitstat = p->p_xstat;
149         kp->kp_nthreads = p->p_nthreads;
150         kp->kp_nice = p->p_nice;
151         kp->kp_swtime = p->p_swtime;
152
153         if ((vm = p->p_vmspace) != NULL) {
154 #ifdef _KERNEL
155                 /*sysref_get(&vm->vm_sysref);*/
156                 /*lwkt_gettoken(&vm->vm_map.token);*/
157 #endif
158                 kp->kp_vm_map_size = vm->vm_map.size;
159                 kp->kp_vm_rssize = vmspace_resident_count(vm);
160 #ifdef _KERNEL
161                 /*XXX MP RACES */
162                 /*kp->kp_vm_prssize = vmspace_president_count(vm);*/
163 #endif
164                 kp->kp_vm_swrss = vm->vm_swrss;
165                 kp->kp_vm_tsize = vm->vm_tsize;
166                 kp->kp_vm_dsize = vm->vm_dsize;
167                 kp->kp_vm_ssize = vm->vm_ssize;
168 #ifdef _KERNEL
169                 /*lwkt_reltoken(&vm->vm_map.token);*/
170                 /*sysref_put(&vm->vm_sysref);*/
171 #endif
172         }
173
174         if (p->p_ucred && jailed(p->p_ucred))
175                 kp->kp_jailid = p->p_ucred->cr_prison->pr_id;
176
177         kp->kp_ru = p->p_ru;
178         kp->kp_cru = p->p_cru;
179 }
180
181 /*
182  * Fill in a struct kinfo_lwp.
183  */
184 void
185 fill_kinfo_lwp(struct lwp *lwp, struct kinfo_lwp *kl)
186 {
187         bzero(kl, sizeof(*kl));
188
189         kl->kl_pid = lwp->lwp_proc->p_pid;
190         kl->kl_tid = lwp->lwp_tid;
191
192         kl->kl_flags = lwp->lwp_flags;
193         kl->kl_stat = lwp->lwp_stat;
194         kl->kl_lock = lwp->lwp_lock;
195         kl->kl_tdflags = lwp->lwp_thread->td_flags;
196
197         /*
198          * The process/lwp stat may not reflect whether the process is
199          * actually sleeping or not if the related thread was directly
200          * descheduled by LWKT.  Adjust the stat if the thread is not
201          * runnable and not waiting to be scheduled on a cpu by the
202          * user process scheduler.
203          */
204         if (kl->kl_stat == LSRUN) {
205                 if ((kl->kl_tdflags & TDF_RUNQ) == 0 &&
206                     (lwp->lwp_mpflags & LWP_MP_ONRUNQ) == 0) {
207                         kl->kl_stat = LSSLEEP;
208                 }
209         }
210 #ifdef SMP
211         kl->kl_mpcount = get_mplock_count(lwp->lwp_thread);
212 #else
213         kl->kl_mpcount = 0;
214 #endif
215
216         kl->kl_prio = lwp->lwp_usdata.bsd4.priority;    /* XXX TGEN dangerous assumption */
217         kl->kl_tdprio = lwp->lwp_thread->td_pri;
218         kl->kl_rtprio = lwp->lwp_rtprio;
219
220         kl->kl_uticks = lwp->lwp_thread->td_uticks;
221         kl->kl_sticks = lwp->lwp_thread->td_sticks;
222         kl->kl_iticks = lwp->lwp_thread->td_iticks;
223         kl->kl_cpticks = lwp->lwp_cpticks;
224         kl->kl_pctcpu = lwp->lwp_pctcpu;
225         kl->kl_slptime = lwp->lwp_slptime;
226         kl->kl_origcpu = lwp->lwp_usdata.bsd4.batch;
227         kl->kl_estcpu = lwp->lwp_usdata.bsd4.estcpu;
228         kl->kl_cpuid = lwp->lwp_thread->td_gd->gd_cpuid;
229
230         kl->kl_ru = lwp->lwp_ru;
231
232         kl->kl_siglist = lwp->lwp_siglist;
233         kl->kl_sigmask = lwp->lwp_sigmask;
234
235         kl->kl_wchan = (uintptr_t)lwp->lwp_thread->td_wchan;
236         if (lwp->lwp_thread->td_wmesg) {
237                 strncpy(kl->kl_wmesg, lwp->lwp_thread->td_wmesg, WMESGLEN);
238                 kl->kl_wmesg[WMESGLEN] = 0;
239         }
240 }
241
242 /*
243  * Fill in a struct kinfo_proc for kernel threads (i.e. those without proc).
244  */
245 void
246 fill_kinfo_proc_kthread(struct thread *td, struct kinfo_proc *kp)
247 {
248         bzero(kp, sizeof(*kp));
249
250         /*
251          * Fill in fake proc information and semi-fake lwp info.
252          */
253         kp->kp_pid = -1;
254         kp->kp_tdev = NOUDEV;
255         strncpy(kp->kp_comm, td->td_comm, sizeof(kp->kp_comm) - 1);
256         kp->kp_comm[sizeof(kp->kp_comm) - 1] = 0;
257         kp->kp_flags = P_SYSTEM;
258         kp->kp_stat = SACTIVE;
259
260         kp->kp_lwp.kl_pid = -1;
261         kp->kp_lwp.kl_tid = -1;
262         kp->kp_lwp.kl_tdflags = td->td_flags;
263 #ifdef SMP
264         kp->kp_lwp.kl_mpcount = get_mplock_count(td);
265 #else /* !SMP */
266         kp->kp_lwp.kl_mpcount = 0;
267 #endif /* SMP */
268
269         kp->kp_lwp.kl_tdprio = td->td_pri;
270         kp->kp_lwp.kl_rtprio.type = RTP_PRIO_THREAD;
271         kp->kp_lwp.kl_rtprio.prio = td->td_pri;
272
273         kp->kp_lwp.kl_uticks = td->td_uticks;
274         kp->kp_lwp.kl_sticks = td->td_sticks;
275         kp->kp_lwp.kl_iticks = td->td_iticks;
276         kp->kp_lwp.kl_cpuid = td->td_gd->gd_cpuid;
277
278         kp->kp_lwp.kl_wchan = (uintptr_t)td->td_wchan;
279         if (td->td_flags & TDF_RUNQ)
280                 kp->kp_lwp.kl_stat = LSRUN;
281         else 
282                 kp->kp_lwp.kl_stat = LSSLEEP;
283         if (td->td_wmesg) {
284                 strncpy(kp->kp_lwp.kl_wmesg, td->td_wmesg, WMESGLEN);
285                 kp->kp_lwp.kl_wmesg[WMESGLEN] = 0;
286         }
287 }