]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/hwpmc/hwpmc_logging.c
pmc(3)/hwpmc(4): update supported Intel processors to rely fully on the
[FreeBSD/FreeBSD.git] / sys / dev / hwpmc / hwpmc_logging.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2005-2007 Joseph Koshy
5  * Copyright (c) 2007 The FreeBSD Foundation
6  * Copyright (c) 2018 Matthew Macy
7  * All rights reserved.
8  *
9  * Portions of this software were developed by A. Joseph Koshy under
10  * sponsorship from the FreeBSD Foundation and Google, Inc.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  */
34
35 /*
36  * Logging code for hwpmc(4)
37  */
38
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD$");
41
42 #include <sys/param.h>
43 #include <sys/capsicum.h>
44 #include <sys/file.h>
45 #include <sys/kernel.h>
46 #include <sys/kthread.h>
47 #include <sys/lock.h>
48 #include <sys/module.h>
49 #include <sys/mutex.h>
50 #include <sys/pmc.h>
51 #include <sys/pmckern.h>
52 #include <sys/pmclog.h>
53 #include <sys/proc.h>
54 #include <sys/sched.h>
55 #include <sys/signalvar.h>
56 #include <sys/smp.h>
57 #include <sys/syscallsubr.h>
58 #include <sys/sysctl.h>
59 #include <sys/systm.h>
60 #include <sys/uio.h>
61 #include <sys/unistd.h>
62 #include <sys/vnode.h>
63
64 #ifdef NUMA
65 #define NDOMAINS vm_ndomains
66 #define curdomain PCPU_GET(domain)
67 #else
68 #define NDOMAINS 1
69 #define curdomain 0
70 #define malloc_domain(size, type, domain, flags) malloc((size), (type), (flags))
71 #define free_domain(addr, type) free(addr, type)
72 #endif
73
74 /*
75  * Sysctl tunables
76  */
77
78 SYSCTL_DECL(_kern_hwpmc);
79
80 /*
81  * kern.hwpmc.logbuffersize -- size of the per-cpu owner buffers.
82  */
83
84 static int pmclog_buffer_size = PMC_LOG_BUFFER_SIZE;
85 #if (__FreeBSD_version < 1100000)
86 TUNABLE_INT(PMC_SYSCTL_NAME_PREFIX "logbuffersize", &pmclog_buffer_size);
87 #endif
88 SYSCTL_INT(_kern_hwpmc, OID_AUTO, logbuffersize, CTLFLAG_RDTUN,
89     &pmclog_buffer_size, 0, "size of log buffers in kilobytes");
90
91 /*
92  * kern.hwpmc.nbuffer -- number of global log buffers
93  */
94
95 static int pmc_nlogbuffers_pcpu = PMC_NLOGBUFFERS_PCPU;
96 #if (__FreeBSD_version < 1100000)
97 TUNABLE_INT(PMC_SYSCTL_NAME_PREFIX "nbuffers", &pmc_nlogbuffers_pcpu);
98 #endif
99 SYSCTL_INT(_kern_hwpmc, OID_AUTO, nbuffers_pcpu, CTLFLAG_RDTUN,
100     &pmc_nlogbuffers_pcpu, 0, "number of log buffers per cpu");
101
102 /*
103  * Global log buffer list and associated spin lock.
104  */
105
106 static struct mtx pmc_kthread_mtx;      /* sleep lock */
107
108 #define PMCLOG_INIT_BUFFER_DESCRIPTOR(D, buf, domain) do {                                              \
109                 (D)->plb_fence = ((char *) (buf)) +     1024*pmclog_buffer_size;                        \
110                 (D)->plb_base  = (D)->plb_ptr = ((char *) (buf));                               \
111                 (D)->plb_domain = domain; \
112         } while (0)
113
114 #define PMCLOG_RESET_BUFFER_DESCRIPTOR(D) do {                  \
115                 (D)->plb_ptr  = (D)->plb_base; \
116         } while (0)
117
118 /*
119  * Log file record constructors.
120  */
121 #define _PMCLOG_TO_HEADER(T,L)                                          \
122         ((PMCLOG_HEADER_MAGIC << 24) |                                  \
123          (PMCLOG_TYPE_ ## T << 16)   |                                  \
124          ((L) & 0xFFFF))
125
126 /* reserve LEN bytes of space and initialize the entry header */
127 #define _PMCLOG_RESERVE_SAFE(PO,TYPE,LEN,ACTION) do {                   \
128                 uint32_t *_le;                                          \
129                 int _len = roundup((LEN), sizeof(uint32_t));    \
130                 if ((_le = pmclog_reserve((PO), _len)) == NULL) {       \
131                         ACTION;                                         \
132                 }                                                       \
133                 *_le = _PMCLOG_TO_HEADER(TYPE,_len);                    \
134                 _le += 3        /* skip over timestamp */
135
136 /* reserve LEN bytes of space and initialize the entry header */
137 #define _PMCLOG_RESERVE(PO,TYPE,LEN,ACTION) do {                        \
138                 uint32_t *_le;                                          \
139                 int _len = roundup((LEN), sizeof(uint32_t));            \
140                 spinlock_enter();                                                                       \
141                 if ((_le = pmclog_reserve((PO), _len)) == NULL) {       \
142                         spinlock_exit();                                                                \
143                         ACTION;                                                                                 \
144                 }                                                                                               \
145                 *_le = _PMCLOG_TO_HEADER(TYPE,_len);                    \
146                 _le += 3        /* skip over timestamp */
147
148
149 #define PMCLOG_RESERVE_SAFE(P,T,L)              _PMCLOG_RESERVE_SAFE(P,T,L,return)
150 #define PMCLOG_RESERVE(P,T,L)           _PMCLOG_RESERVE(P,T,L,return)
151 #define PMCLOG_RESERVE_WITH_ERROR(P,T,L) _PMCLOG_RESERVE(P,T,L,         \
152         error=ENOMEM;goto error)
153
154 #define PMCLOG_EMIT32(V)        do { *_le++ = (V); } while (0)
155 #define PMCLOG_EMIT64(V)        do {                                    \
156                 *_le++ = (uint32_t) ((V) & 0xFFFFFFFF);                 \
157                 *_le++ = (uint32_t) (((V) >> 32) & 0xFFFFFFFF);         \
158         } while (0)
159
160
161 /* Emit a string.  Caution: does NOT update _le, so needs to be last */
162 #define PMCLOG_EMITSTRING(S,L)  do { bcopy((S), _le, (L)); } while (0)
163 #define PMCLOG_EMITNULLSTRING(L) do { bzero(_le, (L)); } while (0)
164
165 #define PMCLOG_DESPATCH_SAFE(PO)                                                \
166             pmclog_release((PO));                                               \
167         } while (0)
168
169 #define PMCLOG_DESPATCH(PO)                                                     \
170             pmclog_release((PO));                                               \
171                 spinlock_exit();                                                        \
172         } while (0)
173
174 #define PMCLOG_DESPATCH_SYNC(PO)                                                \
175             pmclog_schedule_io((PO));                                           \
176                 spinlock_exit();                                                                \
177                 } while (0)
178
179
180 /*
181  * Assertions about the log file format.
182  */
183
184 CTASSERT(sizeof(struct pmclog_callchain) == 8*4 +
185     PMC_CALLCHAIN_DEPTH_MAX*sizeof(uintfptr_t));
186 CTASSERT(sizeof(struct pmclog_closelog) == 4*4);
187 CTASSERT(sizeof(struct pmclog_dropnotify) == 4*4);
188 CTASSERT(sizeof(struct pmclog_map_in) == PATH_MAX +
189     4*4 + sizeof(uintfptr_t));
190 CTASSERT(offsetof(struct pmclog_map_in,pl_pathname) ==
191     4*4 + sizeof(uintfptr_t));
192 CTASSERT(sizeof(struct pmclog_map_out) == 4*4 + 2*sizeof(uintfptr_t));
193 CTASSERT(sizeof(struct pmclog_pmcallocate) == 6*4);
194 CTASSERT(sizeof(struct pmclog_pmcattach) == 6*4 + PATH_MAX);
195 CTASSERT(offsetof(struct pmclog_pmcattach,pl_pathname) == 6*4);
196 CTASSERT(sizeof(struct pmclog_pmcdetach) == 6*4);
197 CTASSERT(sizeof(struct pmclog_proccsw) == 6*4 + 8);
198 CTASSERT(sizeof(struct pmclog_procexec) == 6*4 + PATH_MAX +
199     sizeof(uintfptr_t));
200 CTASSERT(offsetof(struct pmclog_procexec,pl_pathname) == 6*4 +
201     sizeof(uintfptr_t));
202 CTASSERT(sizeof(struct pmclog_procexit) == 6*4 + 8);
203 CTASSERT(sizeof(struct pmclog_procfork) == 6*4);
204 CTASSERT(sizeof(struct pmclog_sysexit) == 4*4);
205 CTASSERT(sizeof(struct pmclog_userdata) == 4*4);
206
207 /*
208  * Log buffer structure
209  */
210
211 struct pmclog_buffer {
212         TAILQ_ENTRY(pmclog_buffer) plb_next;
213         char            *plb_base;
214         char            *plb_ptr;
215         char            *plb_fence;
216         uint16_t         plb_domain;
217 } __aligned(CACHE_LINE_SIZE);
218
219 /*
220  * Prototypes
221  */
222
223 static int pmclog_get_buffer(struct pmc_owner *po);
224 static void pmclog_loop(void *arg);
225 static void pmclog_release(struct pmc_owner *po);
226 static uint32_t *pmclog_reserve(struct pmc_owner *po, int length);
227 static void pmclog_schedule_io(struct pmc_owner *po);
228 static void pmclog_schedule_all(struct pmc_owner *po);
229 static void pmclog_stop_kthread(struct pmc_owner *po);
230
231 /*
232  * Helper functions
233  */
234
235 static inline void
236 pmc_plb_rele_unlocked(struct pmclog_buffer *plb)
237 {
238         TAILQ_INSERT_HEAD(&pmc_dom_hdrs[plb->plb_domain]->pdbh_head, plb, plb_next);
239 }
240
241 static inline void
242 pmc_plb_rele(struct pmclog_buffer *plb)
243 {
244         mtx_lock_spin(&pmc_dom_hdrs[plb->plb_domain]->pdbh_mtx);
245         pmc_plb_rele_unlocked(plb);
246         mtx_unlock_spin(&pmc_dom_hdrs[plb->plb_domain]->pdbh_mtx);
247 }
248
249
250 /*
251  * Get a log buffer
252  */
253
254 static int
255 pmclog_get_buffer(struct pmc_owner *po)
256 {
257         struct pmclog_buffer *plb;
258         int domain;
259
260         KASSERT(po->po_curbuf[curcpu] == NULL,
261             ("[pmclog,%d] po=%p current buffer still valid", __LINE__, po));
262
263         domain = curdomain;
264         MPASS(pmc_dom_hdrs[domain]);
265         mtx_lock_spin(&pmc_dom_hdrs[domain]->pdbh_mtx);
266         if ((plb = TAILQ_FIRST(&pmc_dom_hdrs[domain]->pdbh_head)) != NULL)
267                 TAILQ_REMOVE(&pmc_dom_hdrs[domain]->pdbh_head, plb, plb_next);
268         mtx_unlock_spin(&pmc_dom_hdrs[domain]->pdbh_mtx);
269
270         PMCDBG2(LOG,GTB,1, "po=%p plb=%p", po, plb);
271
272 #ifdef  HWPMC_DEBUG
273         if (plb)
274                 KASSERT(plb->plb_ptr == plb->plb_base &&
275                     plb->plb_base < plb->plb_fence,
276                     ("[pmclog,%d] po=%p buffer invariants: ptr=%p "
277                     "base=%p fence=%p", __LINE__, po, plb->plb_ptr,
278                     plb->plb_base, plb->plb_fence));
279 #endif
280
281         po->po_curbuf[curcpu] = plb;
282
283         /* update stats */
284         counter_u64_add(pmc_stats.pm_buffer_requests, 1);
285         if (plb == NULL)
286                 counter_u64_add(pmc_stats.pm_buffer_requests_failed, 1);
287
288         return (plb ? 0 : ENOMEM);
289 }
290
291 struct pmclog_proc_init_args {
292         struct proc *kthr;
293         struct pmc_owner *po;
294         bool exit;
295         bool acted;
296 };
297
298 int
299 pmclog_proc_create(struct thread *td, void **handlep)
300 {
301         struct pmclog_proc_init_args *ia;
302         int error;
303
304         ia = malloc(sizeof(*ia), M_TEMP, M_WAITOK | M_ZERO);
305         error = kproc_create(pmclog_loop, ia, &ia->kthr,
306             RFHIGHPID, 0, "hwpmc: proc(%d)", td->td_proc->p_pid);
307         if (error == 0)
308                 *handlep = ia;
309         return (error);
310 }
311
312 void
313 pmclog_proc_ignite(void *handle, struct pmc_owner *po)
314 {
315         struct pmclog_proc_init_args *ia;
316
317         ia = handle;
318         mtx_lock(&pmc_kthread_mtx);
319         MPASS(!ia->acted);
320         MPASS(ia->po == NULL);
321         MPASS(!ia->exit);
322         MPASS(ia->kthr != NULL);
323         if (po == NULL) {
324                 ia->exit = true;
325         } else {
326                 ia->po = po;
327                 KASSERT(po->po_kthread == NULL,
328                     ("[pmclog,%d] po=%p kthread (%p) already present",
329                     __LINE__, po, po->po_kthread));
330                 po->po_kthread = ia->kthr;
331         }
332         wakeup(ia);
333         while (!ia->acted)
334                 msleep(ia, &pmc_kthread_mtx, PWAIT, "pmclogw", 0);
335         mtx_unlock(&pmc_kthread_mtx);
336         free(ia, M_TEMP);
337 }
338
339 /*
340  * Log handler loop.
341  *
342  * This function is executed by each pmc owner's helper thread.
343  */
344
345 static void
346 pmclog_loop(void *arg)
347 {
348         struct pmclog_proc_init_args *ia;
349         struct pmc_owner *po;
350         struct pmclog_buffer *lb;
351         struct proc *p;
352         struct ucred *ownercred;
353         struct ucred *mycred;
354         struct thread *td;
355         sigset_t unb;
356         struct uio auio;
357         struct iovec aiov;
358         size_t nbytes;
359         int error;
360
361         td = curthread;
362
363         SIGEMPTYSET(unb);
364         SIGADDSET(unb, SIGHUP);
365         (void)kern_sigprocmask(td, SIG_UNBLOCK, &unb, NULL, 0);
366
367         ia = arg;
368         MPASS(ia->kthr == curproc);
369         MPASS(!ia->acted);
370         mtx_lock(&pmc_kthread_mtx);
371         while (ia->po == NULL && !ia->exit)
372                 msleep(ia, &pmc_kthread_mtx, PWAIT, "pmclogi", 0);
373         if (ia->exit) {
374                 ia->acted = true;
375                 wakeup(ia);
376                 mtx_unlock(&pmc_kthread_mtx);
377                 kproc_exit(0);
378         }
379         MPASS(ia->po != NULL);
380         po = ia->po;
381         ia->acted = true;
382         wakeup(ia);
383         mtx_unlock(&pmc_kthread_mtx);
384         ia = NULL;
385
386         p = po->po_owner;
387         mycred = td->td_ucred;
388
389         PROC_LOCK(p);
390         ownercred = crhold(p->p_ucred);
391         PROC_UNLOCK(p);
392
393         PMCDBG2(LOG,INI,1, "po=%p kt=%p", po, po->po_kthread);
394         KASSERT(po->po_kthread == curthread->td_proc,
395             ("[pmclog,%d] proc mismatch po=%p po/kt=%p curproc=%p", __LINE__,
396                 po, po->po_kthread, curthread->td_proc));
397
398         lb = NULL;
399
400
401         /*
402          * Loop waiting for I/O requests to be added to the owner
403          * struct's queue.  The loop is exited when the log file
404          * is deconfigured.
405          */
406
407         mtx_lock(&pmc_kthread_mtx);
408
409         for (;;) {
410
411                 /* check if we've been asked to exit */
412                 if ((po->po_flags & PMC_PO_OWNS_LOGFILE) == 0)
413                         break;
414
415                 if (lb == NULL) { /* look for a fresh buffer to write */
416                         mtx_lock_spin(&po->po_mtx);
417                         if ((lb = TAILQ_FIRST(&po->po_logbuffers)) == NULL) {
418                                 mtx_unlock_spin(&po->po_mtx);
419
420                                 /* No more buffers and shutdown required. */
421                                 if (po->po_flags & PMC_PO_SHUTDOWN)
422                                         break;
423
424                                 (void) msleep(po, &pmc_kthread_mtx, PWAIT,
425                                     "pmcloop", 0);
426                                 continue;
427                         }
428
429                         TAILQ_REMOVE(&po->po_logbuffers, lb, plb_next);
430                         mtx_unlock_spin(&po->po_mtx);
431                 }
432
433                 mtx_unlock(&pmc_kthread_mtx);
434
435                 /* process the request */
436                 PMCDBG3(LOG,WRI,2, "po=%p base=%p ptr=%p", po,
437                     lb->plb_base, lb->plb_ptr);
438                 /* change our thread's credentials before issuing the I/O */
439
440                 aiov.iov_base = lb->plb_base;
441                 aiov.iov_len  = nbytes = lb->plb_ptr - lb->plb_base;
442
443                 auio.uio_iov    = &aiov;
444                 auio.uio_iovcnt = 1;
445                 auio.uio_offset = -1;
446                 auio.uio_resid  = nbytes;
447                 auio.uio_rw     = UIO_WRITE;
448                 auio.uio_segflg = UIO_SYSSPACE;
449                 auio.uio_td     = td;
450
451                 /* switch thread credentials -- see kern_ktrace.c */
452                 td->td_ucred = ownercred;
453                 error = fo_write(po->po_file, &auio, ownercred, 0, td);
454                 td->td_ucred = mycred;
455
456                 if (error) {
457                         /* XXX some errors are recoverable */
458                         /* send a SIGIO to the owner and exit */
459                         PROC_LOCK(p);
460                         kern_psignal(p, SIGIO);
461                         PROC_UNLOCK(p);
462
463                         mtx_lock(&pmc_kthread_mtx);
464
465                         po->po_error = error; /* save for flush log */
466
467                         PMCDBG2(LOG,WRI,2, "po=%p error=%d", po, error);
468
469                         break;
470                 }
471
472                 mtx_lock(&pmc_kthread_mtx);
473
474                 /* put the used buffer back into the global pool */
475                 PMCLOG_RESET_BUFFER_DESCRIPTOR(lb);
476
477                 pmc_plb_rele(lb);
478                 lb = NULL;
479         }
480
481         wakeup_one(po->po_kthread);
482         po->po_kthread = NULL;
483
484         mtx_unlock(&pmc_kthread_mtx);
485
486         /* return the current I/O buffer to the global pool */
487         if (lb) {
488                 PMCLOG_RESET_BUFFER_DESCRIPTOR(lb);
489
490                 pmc_plb_rele(lb);
491         }
492
493         /*
494          * Exit this thread, signalling the waiter
495          */
496
497         crfree(ownercred);
498
499         kproc_exit(0);
500 }
501
502 /*
503  * Release and log entry and schedule an I/O if needed.
504  */
505
506 static void
507 pmclog_release(struct pmc_owner *po)
508 {
509         struct pmclog_buffer *plb;
510
511         plb = po->po_curbuf[curcpu];
512         KASSERT(plb->plb_ptr >= plb->plb_base,
513             ("[pmclog,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__,
514                 po, plb->plb_ptr, plb->plb_base));
515         KASSERT(plb->plb_ptr <= plb->plb_fence,
516             ("[pmclog,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__,
517                 po, plb->plb_ptr, plb->plb_fence));
518
519         /* schedule an I/O if we've filled a buffer */
520         if (plb->plb_ptr >= plb->plb_fence)
521                 pmclog_schedule_io(po);
522
523         PMCDBG1(LOG,REL,1, "po=%p", po);
524 }
525
526
527 /*
528  * Attempt to reserve 'length' bytes of space in an owner's log
529  * buffer.  The function returns a pointer to 'length' bytes of space
530  * if there was enough space or returns NULL if no space was
531  * available.  Non-null returns do so with the po mutex locked.  The
532  * caller must invoke pmclog_release() on the pmc owner structure
533  * when done.
534  */
535
536 static uint32_t *
537 pmclog_reserve(struct pmc_owner *po, int length)
538 {
539         uintptr_t newptr, oldptr;
540         uint32_t *lh;
541         struct timespec ts;
542         struct pmclog_buffer *plb, **pplb;
543
544         PMCDBG2(LOG,ALL,1, "po=%p len=%d", po, length);
545
546         KASSERT(length % sizeof(uint32_t) == 0,
547             ("[pmclog,%d] length not a multiple of word size", __LINE__));
548
549         /* No more data when shutdown in progress. */
550         if (po->po_flags & PMC_PO_SHUTDOWN)
551                 return (NULL);
552
553         pplb = &po->po_curbuf[curcpu];
554         if (*pplb == NULL && pmclog_get_buffer(po) != 0)
555                 goto fail;
556
557         KASSERT(*pplb != NULL,
558             ("[pmclog,%d] po=%p no current buffer", __LINE__, po));
559
560         plb = *pplb;
561         KASSERT(plb->plb_ptr >= plb->plb_base &&
562             plb->plb_ptr <= plb->plb_fence,
563             ("[pmclog,%d] po=%p buffer invariants: ptr=%p base=%p fence=%p",
564                 __LINE__, po, plb->plb_ptr, plb->plb_base,
565                 plb->plb_fence));
566
567         oldptr = (uintptr_t) plb->plb_ptr;
568         newptr = oldptr + length;
569
570         KASSERT(oldptr != (uintptr_t) NULL,
571             ("[pmclog,%d] po=%p Null log buffer pointer", __LINE__, po));
572
573         /*
574          * If we have space in the current buffer, return a pointer to
575          * available space with the PO structure locked.
576          */
577         if (newptr <= (uintptr_t) plb->plb_fence) {
578                 plb->plb_ptr = (char *) newptr;
579                 goto done;
580         }
581
582         /*
583          * Otherwise, schedule the current buffer for output and get a
584          * fresh buffer.
585          */
586         pmclog_schedule_io(po);
587
588         if (pmclog_get_buffer(po) != 0)
589                 goto fail;
590
591         plb = *pplb;
592         KASSERT(plb != NULL,
593             ("[pmclog,%d] po=%p no current buffer", __LINE__, po));
594
595         KASSERT(plb->plb_ptr != NULL,
596             ("[pmclog,%d] null return from pmc_get_log_buffer", __LINE__));
597
598         KASSERT(plb->plb_ptr == plb->plb_base &&
599             plb->plb_ptr <= plb->plb_fence,
600             ("[pmclog,%d] po=%p buffer invariants: ptr=%p base=%p fence=%p",
601                 __LINE__, po, plb->plb_ptr, plb->plb_base,
602                 plb->plb_fence));
603
604         oldptr = (uintptr_t) plb->plb_ptr;
605
606  done:
607         lh = (uint32_t *) oldptr;
608         lh++;                           /* skip header */
609         getnanotime(&ts);               /* fill in the timestamp */
610         *lh++ = ts.tv_sec & 0xFFFFFFFF;
611         *lh++ = ts.tv_nsec & 0xFFFFFFF;
612         return ((uint32_t *) oldptr);
613  fail:
614         return (NULL);
615 }
616
617 /*
618  * Schedule an I/O.
619  *
620  * Transfer the current buffer to the helper kthread.
621  */
622
623 static void
624 pmclog_schedule_io(struct pmc_owner *po)
625 {
626         struct pmclog_buffer *plb;
627
628         plb = po->po_curbuf[curcpu];
629         po->po_curbuf[curcpu] = NULL;
630         KASSERT(plb != NULL,
631             ("[pmclog,%d] schedule_io with null buffer po=%p", __LINE__, po));
632         KASSERT(plb->plb_ptr >= plb->plb_base,
633             ("[pmclog,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__,
634                 po, plb->plb_ptr, plb->plb_base));
635         KASSERT(plb->plb_ptr <= plb->plb_fence,
636             ("[pmclog,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__,
637                 po, plb->plb_ptr, plb->plb_fence));
638
639         PMCDBG1(LOG,SIO, 1, "po=%p", po);
640
641         /*
642          * Add the current buffer to the tail of the buffer list and
643          * wakeup the helper.
644          */
645         mtx_lock_spin(&po->po_mtx);
646         TAILQ_INSERT_TAIL(&po->po_logbuffers, plb, plb_next);
647         mtx_unlock_spin(&po->po_mtx);
648         wakeup_one(po);
649 }
650
651 /*
652  * Stop the helper kthread.
653  */
654
655 static void
656 pmclog_stop_kthread(struct pmc_owner *po)
657 {
658
659         mtx_lock(&pmc_kthread_mtx);
660         po->po_flags &= ~PMC_PO_OWNS_LOGFILE;
661         if (po->po_kthread != NULL) {
662                 PROC_LOCK(po->po_kthread);
663                 kern_psignal(po->po_kthread, SIGHUP);
664                 PROC_UNLOCK(po->po_kthread);
665         }
666         wakeup_one(po);
667         while (po->po_kthread)
668                 msleep(po->po_kthread, &pmc_kthread_mtx, PPAUSE, "pmckstp", 0);
669         mtx_unlock(&pmc_kthread_mtx);
670 }
671
672 /*
673  * Public functions
674  */
675
676 /*
677  * Configure a log file for pmc owner 'po'.
678  *
679  * Parameter 'logfd' is a file handle referencing an open file in the
680  * owner process.  This file needs to have been opened for writing.
681  */
682
683 int
684 pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
685 {
686         struct proc *p;
687         int error;
688
689         sx_assert(&pmc_sx, SA_XLOCKED);
690         PMCDBG2(LOG,CFG,1, "config po=%p logfd=%d", po, logfd);
691
692         p = po->po_owner;
693
694         /* return EBUSY if a log file was already present */
695         if (po->po_flags & PMC_PO_OWNS_LOGFILE)
696                 return (EBUSY);
697
698         KASSERT(po->po_file == NULL,
699             ("[pmclog,%d] po=%p file (%p) already present", __LINE__, po,
700                 po->po_file));
701
702         /* get a reference to the file state */
703         error = fget_write(curthread, logfd, &cap_write_rights, &po->po_file);
704         if (error)
705                 goto error;
706
707         /* mark process as owning a log file */
708         po->po_flags |= PMC_PO_OWNS_LOGFILE;
709
710         /* mark process as using HWPMCs */
711         PROC_LOCK(p);
712         p->p_flag |= P_HWPMC;
713         PROC_UNLOCK(p);
714
715         /* create a log initialization entry */
716         PMCLOG_RESERVE_WITH_ERROR(po, INITIALIZE,
717             sizeof(struct pmclog_initialize));
718         PMCLOG_EMIT32(PMC_VERSION);
719         PMCLOG_EMIT32(md->pmd_cputype);
720         PMCLOG_DESPATCH_SYNC(po);
721
722         return (0);
723
724  error:
725         KASSERT(po->po_kthread == NULL, ("[pmclog,%d] po=%p kthread not "
726             "stopped", __LINE__, po));
727
728         if (po->po_file)
729                 (void) fdrop(po->po_file, curthread);
730         po->po_file  = NULL;    /* clear file and error state */
731         po->po_error = 0;
732         po->po_flags &= ~PMC_PO_OWNS_LOGFILE;
733
734         return (error);
735 }
736
737
738 /*
739  * De-configure a log file.  This will throw away any buffers queued
740  * for this owner process.
741  */
742
743 int
744 pmclog_deconfigure_log(struct pmc_owner *po)
745 {
746         int error;
747         struct pmclog_buffer *lb;
748
749         PMCDBG1(LOG,CFG,1, "de-config po=%p", po);
750
751         if ((po->po_flags & PMC_PO_OWNS_LOGFILE) == 0)
752                 return (EINVAL);
753
754         KASSERT(po->po_sscount == 0,
755             ("[pmclog,%d] po=%p still owning SS PMCs", __LINE__, po));
756         KASSERT(po->po_file != NULL,
757             ("[pmclog,%d] po=%p no log file", __LINE__, po));
758
759         /* stop the kthread, this will reset the 'OWNS_LOGFILE' flag */
760         pmclog_stop_kthread(po);
761
762         KASSERT(po->po_kthread == NULL,
763             ("[pmclog,%d] po=%p kthread not stopped", __LINE__, po));
764
765         /* return all queued log buffers to the global pool */
766         while ((lb = TAILQ_FIRST(&po->po_logbuffers)) != NULL) {
767                 TAILQ_REMOVE(&po->po_logbuffers, lb, plb_next);
768                 PMCLOG_RESET_BUFFER_DESCRIPTOR(lb);
769                 pmc_plb_rele(lb);
770         }
771         for (int i = 0; i < mp_ncpus; i++) {
772                 thread_lock(curthread);
773                 sched_bind(curthread, i);
774                 thread_unlock(curthread);
775                 /* return the 'current' buffer to the global pool */
776                 if ((lb = po->po_curbuf[curcpu]) != NULL) {
777                         PMCLOG_RESET_BUFFER_DESCRIPTOR(lb);
778                         pmc_plb_rele(lb);
779                 }
780         }
781         thread_lock(curthread);
782         sched_unbind(curthread);
783         thread_unlock(curthread);
784
785         /* drop a reference to the fd */
786         if (po->po_file != NULL) {
787                 error = fdrop(po->po_file, curthread);
788                 po->po_file = NULL;
789         } else
790                 error = 0;
791         po->po_error = 0;
792
793         return (error);
794 }
795
796 /*
797  * Flush a process' log buffer.
798  */
799
800 int
801 pmclog_flush(struct pmc_owner *po)
802 {
803         int error;
804
805         PMCDBG1(LOG,FLS,1, "po=%p", po);
806
807         /*
808          * If there is a pending error recorded by the logger thread,
809          * return that.
810          */
811         if (po->po_error)
812                 return (po->po_error);
813
814         error = 0;
815
816         /*
817          * Check that we do have an active log file.
818          */
819         mtx_lock(&pmc_kthread_mtx);
820         if ((po->po_flags & PMC_PO_OWNS_LOGFILE) == 0) {
821                 error = EINVAL;
822                 goto error;
823         }
824
825         pmclog_schedule_all(po);
826  error:
827         mtx_unlock(&pmc_kthread_mtx);
828
829         return (error);
830 }
831
832 static void
833 pmclog_schedule_one_cond(void *arg)
834 {
835         struct pmc_owner *po = arg;
836         struct pmclog_buffer *plb;
837
838         spinlock_enter();
839         /* tell hardclock not to run again */
840         if (PMC_CPU_HAS_SAMPLES(PCPU_GET(cpuid)))
841                 PMC_CALL_HOOK_UNLOCKED(curthread, PMC_FN_DO_SAMPLES, NULL);
842         plb = po->po_curbuf[curcpu];
843         if (plb && plb->plb_ptr != plb->plb_base)
844                 pmclog_schedule_io(po);
845         spinlock_exit();
846 }
847
848 static void
849 pmclog_schedule_all(struct pmc_owner *po)
850 {
851         /*
852          * Schedule the current buffer if any and not empty.
853          */
854         for (int i = 0; i < mp_ncpus; i++) {
855                 thread_lock(curthread);
856                 sched_bind(curthread, i);
857                 thread_unlock(curthread);
858                 pmclog_schedule_one_cond(po);
859         }
860         thread_lock(curthread);
861         sched_unbind(curthread);
862         thread_unlock(curthread);
863 }
864
865 int
866 pmclog_close(struct pmc_owner *po)
867 {
868
869         PMCDBG1(LOG,CLO,1, "po=%p", po);
870
871         pmclog_process_closelog(po);
872
873         mtx_lock(&pmc_kthread_mtx);
874         /*
875          * Initiate shutdown: no new data queued,
876          * thread will close file on last block.
877          */
878         po->po_flags |= PMC_PO_SHUTDOWN;
879         /* give time for all to see */
880         DELAY(50);
881         
882         /*
883          * Schedule the current buffer.
884          */
885         pmclog_schedule_all(po);
886         wakeup_one(po);
887
888         mtx_unlock(&pmc_kthread_mtx);
889
890         return (0);
891 }
892
893 void
894 pmclog_process_callchain(struct pmc *pm, struct pmc_sample *ps)
895 {
896         int n, recordlen;
897         uint32_t flags;
898         struct pmc_owner *po;
899
900         PMCDBG3(LOG,SAM,1,"pm=%p pid=%d n=%d", pm, ps->ps_pid,
901             ps->ps_nsamples);
902
903         recordlen = offsetof(struct pmclog_callchain, pl_pc) +
904             ps->ps_nsamples * sizeof(uintfptr_t);
905         po = pm->pm_owner;
906         flags = PMC_CALLCHAIN_TO_CPUFLAGS(ps->ps_cpu,ps->ps_flags);
907         PMCLOG_RESERVE_SAFE(po, CALLCHAIN, recordlen);
908         PMCLOG_EMIT32(ps->ps_pid);
909         PMCLOG_EMIT32(ps->ps_tid);
910         PMCLOG_EMIT32(pm->pm_id);
911         PMCLOG_EMIT32(flags);
912         /* unused for now */
913         PMCLOG_EMIT32(0);
914         for (n = 0; n < ps->ps_nsamples; n++)
915                 PMCLOG_EMITADDR(ps->ps_pc[n]);
916         PMCLOG_DESPATCH_SAFE(po);
917 }
918
919 void
920 pmclog_process_closelog(struct pmc_owner *po)
921 {
922         PMCLOG_RESERVE(po,CLOSELOG,sizeof(struct pmclog_closelog));
923         PMCLOG_DESPATCH_SYNC(po);
924 }
925
926 void
927 pmclog_process_dropnotify(struct pmc_owner *po)
928 {
929         PMCLOG_RESERVE(po,DROPNOTIFY,sizeof(struct pmclog_dropnotify));
930         PMCLOG_DESPATCH(po);
931 }
932
933 void
934 pmclog_process_map_in(struct pmc_owner *po, pid_t pid, uintfptr_t start,
935     const char *path)
936 {
937         int pathlen, recordlen;
938
939         KASSERT(path != NULL, ("[pmclog,%d] map-in, null path", __LINE__));
940
941         pathlen = strlen(path) + 1;     /* #bytes for path name */
942         recordlen = offsetof(struct pmclog_map_in, pl_pathname) +
943             pathlen;
944
945         PMCLOG_RESERVE(po, MAP_IN, recordlen);
946         PMCLOG_EMIT32(pid);
947         PMCLOG_EMITADDR(start);
948         PMCLOG_EMITSTRING(path,pathlen);
949         PMCLOG_DESPATCH(po);
950 }
951
952 void
953 pmclog_process_map_out(struct pmc_owner *po, pid_t pid, uintfptr_t start,
954     uintfptr_t end)
955 {
956         KASSERT(start <= end, ("[pmclog,%d] start > end", __LINE__));
957
958         PMCLOG_RESERVE(po, MAP_OUT, sizeof(struct pmclog_map_out));
959         PMCLOG_EMIT32(pid);
960         PMCLOG_EMITADDR(start);
961         PMCLOG_EMITADDR(end);
962         PMCLOG_DESPATCH(po);
963 }
964
965 void
966 pmclog_process_pmcallocate(struct pmc *pm)
967 {
968         struct pmc_owner *po;
969         struct pmc_soft *ps;
970
971         po = pm->pm_owner;
972
973         PMCDBG1(LOG,ALL,1, "pm=%p", pm);
974
975         if (PMC_TO_CLASS(pm) == PMC_CLASS_SOFT) {
976                 PMCLOG_RESERVE(po, PMCALLOCATEDYN,
977                     sizeof(struct pmclog_pmcallocatedyn));
978                 PMCLOG_EMIT32(pm->pm_id);
979                 PMCLOG_EMIT32(pm->pm_event);
980                 PMCLOG_EMIT32(pm->pm_flags);
981                 ps = pmc_soft_ev_acquire(pm->pm_event);
982                 if (ps != NULL)
983                         PMCLOG_EMITSTRING(ps->ps_ev.pm_ev_name,PMC_NAME_MAX);
984                 else
985                         PMCLOG_EMITNULLSTRING(PMC_NAME_MAX);
986                 pmc_soft_ev_release(ps);
987                 PMCLOG_DESPATCH_SYNC(po);
988         } else {
989                 PMCLOG_RESERVE(po, PMCALLOCATE,
990                     sizeof(struct pmclog_pmcallocate));
991                 PMCLOG_EMIT32(pm->pm_id);
992                 PMCLOG_EMIT32(pm->pm_event);
993                 PMCLOG_EMIT32(pm->pm_flags);
994                 PMCLOG_DESPATCH_SYNC(po);
995         }
996 }
997
998 void
999 pmclog_process_pmcattach(struct pmc *pm, pid_t pid, char *path)
1000 {
1001         int pathlen, recordlen;
1002         struct pmc_owner *po;
1003
1004         PMCDBG2(LOG,ATT,1,"pm=%p pid=%d", pm, pid);
1005
1006         po = pm->pm_owner;
1007
1008         pathlen = strlen(path) + 1;     /* #bytes for the string */
1009         recordlen = offsetof(struct pmclog_pmcattach, pl_pathname) + pathlen;
1010
1011         PMCLOG_RESERVE(po, PMCATTACH, recordlen);
1012         PMCLOG_EMIT32(pm->pm_id);
1013         PMCLOG_EMIT32(pid);
1014         PMCLOG_EMIT32(0);
1015         PMCLOG_EMITSTRING(path, pathlen);
1016         PMCLOG_DESPATCH_SYNC(po);
1017 }
1018
1019 void
1020 pmclog_process_pmcdetach(struct pmc *pm, pid_t pid)
1021 {
1022         struct pmc_owner *po;
1023
1024         PMCDBG2(LOG,ATT,1,"!pm=%p pid=%d", pm, pid);
1025
1026         po = pm->pm_owner;
1027
1028         PMCLOG_RESERVE(po, PMCDETACH, sizeof(struct pmclog_pmcdetach));
1029         PMCLOG_EMIT32(pm->pm_id);
1030         PMCLOG_EMIT32(pid);
1031         PMCLOG_DESPATCH_SYNC(po);
1032 }
1033
1034 /*
1035  * Log a context switch event to the log file.
1036  */
1037
1038 void
1039 pmclog_process_proccsw(struct pmc *pm, struct pmc_process *pp, pmc_value_t v, struct thread *td)
1040 {
1041         struct pmc_owner *po;
1042
1043         KASSERT(pm->pm_flags & PMC_F_LOG_PROCCSW,
1044             ("[pmclog,%d] log-process-csw called gratuitously", __LINE__));
1045
1046         PMCDBG3(LOG,SWO,1,"pm=%p pid=%d v=%jx", pm, pp->pp_proc->p_pid,
1047             v);
1048
1049         po = pm->pm_owner;
1050
1051         PMCLOG_RESERVE(po, PROCCSW, sizeof(struct pmclog_proccsw));
1052         PMCLOG_EMIT32(pm->pm_id);
1053         PMCLOG_EMIT64(v);
1054         PMCLOG_EMIT32(pp->pp_proc->p_pid);
1055         PMCLOG_EMIT32(td->td_tid);
1056         PMCLOG_DESPATCH(po);
1057 }
1058
1059 void
1060 pmclog_process_procexec(struct pmc_owner *po, pmc_id_t pmid, pid_t pid,
1061     uintfptr_t startaddr, char *path)
1062 {
1063         int pathlen, recordlen;
1064
1065         PMCDBG3(LOG,EXC,1,"po=%p pid=%d path=\"%s\"", po, pid, path);
1066
1067         pathlen   = strlen(path) + 1;   /* #bytes for the path */
1068         recordlen = offsetof(struct pmclog_procexec, pl_pathname) + pathlen;
1069
1070         PMCLOG_RESERVE(po, PROCEXEC, recordlen);
1071         PMCLOG_EMIT32(pid);
1072         PMCLOG_EMIT32(pmid);
1073         PMCLOG_EMIT32(0);
1074         PMCLOG_EMITADDR(startaddr);
1075         PMCLOG_EMITSTRING(path,pathlen);
1076         PMCLOG_DESPATCH(po);
1077 }
1078
1079 /*
1080  * Log a process exit event (and accumulated pmc value) to the log file.
1081  */
1082
1083 void
1084 pmclog_process_procexit(struct pmc *pm, struct pmc_process *pp)
1085 {
1086         int ri;
1087         struct pmc_owner *po;
1088
1089         ri = PMC_TO_ROWINDEX(pm);
1090         PMCDBG3(LOG,EXT,1,"pm=%p pid=%d v=%jx", pm, pp->pp_proc->p_pid,
1091             pp->pp_pmcs[ri].pp_pmcval);
1092
1093         po = pm->pm_owner;
1094
1095         PMCLOG_RESERVE(po, PROCEXIT, sizeof(struct pmclog_procexit));
1096         PMCLOG_EMIT32(pm->pm_id);
1097         PMCLOG_EMIT32(pp->pp_proc->p_pid);
1098         PMCLOG_EMIT32(0);
1099         PMCLOG_EMIT64(pp->pp_pmcs[ri].pp_pmcval);
1100         PMCLOG_DESPATCH(po);
1101 }
1102
1103 /*
1104  * Log a fork event.
1105  */
1106
1107 void
1108 pmclog_process_procfork(struct pmc_owner *po, pid_t oldpid, pid_t newpid)
1109 {
1110         PMCLOG_RESERVE(po, PROCFORK, sizeof(struct pmclog_procfork));
1111         PMCLOG_EMIT32(oldpid);
1112         PMCLOG_EMIT32(newpid);
1113         PMCLOG_DESPATCH(po);
1114 }
1115
1116 /*
1117  * Log a process exit event of the form suitable for system-wide PMCs.
1118  */
1119
1120 void
1121 pmclog_process_sysexit(struct pmc_owner *po, pid_t pid)
1122 {
1123         PMCLOG_RESERVE(po, SYSEXIT, sizeof(struct pmclog_sysexit));
1124         PMCLOG_EMIT32(pid);
1125         PMCLOG_DESPATCH(po);
1126 }
1127
1128 /*
1129  * Write a user log entry.
1130  */
1131
1132 int
1133 pmclog_process_userlog(struct pmc_owner *po, struct pmc_op_writelog *wl)
1134 {
1135         int error;
1136
1137         PMCDBG2(LOG,WRI,1, "writelog po=%p ud=0x%x", po, wl->pm_userdata);
1138
1139         error = 0;
1140
1141         PMCLOG_RESERVE_WITH_ERROR(po, USERDATA,
1142             sizeof(struct pmclog_userdata));
1143         PMCLOG_EMIT32(wl->pm_userdata);
1144         PMCLOG_DESPATCH(po);
1145
1146  error:
1147         return (error);
1148 }
1149
1150 /*
1151  * Initialization.
1152  *
1153  * Create a pool of log buffers and initialize mutexes.
1154  */
1155
1156 void
1157 pmclog_initialize()
1158 {
1159         int domain;
1160         struct pmclog_buffer *plb;
1161
1162         if (pmclog_buffer_size <= 0 || pmclog_buffer_size > 16*1024) {
1163                 (void) printf("hwpmc: tunable logbuffersize=%d must be "
1164                                           "greater than zero and less than or equal to 16MB.\n",
1165                                           pmclog_buffer_size);
1166                 pmclog_buffer_size = PMC_LOG_BUFFER_SIZE;
1167         }
1168
1169         if (pmc_nlogbuffers_pcpu <= 0) {
1170                 (void) printf("hwpmc: tunable nlogbuffers=%d must be greater "
1171                                           "than zero.\n", pmc_nlogbuffers_pcpu);
1172                 pmc_nlogbuffers_pcpu = PMC_NLOGBUFFERS_PCPU;
1173         }
1174         if (pmc_nlogbuffers_pcpu*pmclog_buffer_size > 32*1024) {
1175                 (void) printf("hwpmc: memory allocated pcpu must be less than 32MB (is %dK).\n",
1176                                           pmc_nlogbuffers_pcpu*pmclog_buffer_size);
1177                 pmc_nlogbuffers_pcpu = PMC_NLOGBUFFERS_PCPU;
1178                 pmclog_buffer_size = PMC_LOG_BUFFER_SIZE;
1179         }
1180         for (domain = 0; domain < NDOMAINS; domain++) {
1181                 int ncpus = pmc_dom_hdrs[domain]->pdbh_ncpus;
1182                 int total = ncpus*pmc_nlogbuffers_pcpu;
1183
1184                 plb = malloc_domain(sizeof(struct pmclog_buffer)*total, M_PMC, domain, M_WAITOK|M_ZERO);
1185                 pmc_dom_hdrs[domain]->pdbh_plbs = plb;
1186                 for (int i = 0; i < total; i++, plb++) {
1187                         void *buf;
1188
1189                         buf = malloc_domain(1024 * pmclog_buffer_size, M_PMC, domain,
1190                                                                 M_WAITOK|M_ZERO);
1191                         PMCLOG_INIT_BUFFER_DESCRIPTOR(plb, buf, domain);
1192                         pmc_plb_rele_unlocked(plb);
1193                 }
1194         }
1195         mtx_init(&pmc_kthread_mtx, "pmc-kthread", "pmc-sleep", MTX_DEF);
1196 }
1197
1198 /*
1199  * Shutdown logging.
1200  *
1201  * Destroy mutexes and release memory back the to free pool.
1202  */
1203
1204 void
1205 pmclog_shutdown()
1206 {
1207         struct pmclog_buffer *plb;
1208         int domain;
1209
1210         mtx_destroy(&pmc_kthread_mtx);
1211
1212         for (domain = 0; domain < NDOMAINS; domain++) {
1213                 while ((plb = TAILQ_FIRST(&pmc_dom_hdrs[domain]->pdbh_head)) != NULL) {
1214                         TAILQ_REMOVE(&pmc_dom_hdrs[domain]->pdbh_head, plb, plb_next);
1215                         free(plb->plb_base, M_PMC);
1216                 }
1217                 free(pmc_dom_hdrs[domain]->pdbh_plbs, M_PMC);
1218         }
1219 }