Index: arch/i386/include/cpu.h =================================================================== RCS file: /cvs/src/sys/arch/i386/include/cpu.h,v retrieving revision 1.135 diff -u -p -r1.135 cpu.h --- arch/i386/include/cpu.h 12 Sep 2014 09:52:45 -0000 1.135 +++ arch/i386/include/cpu.h 16 Oct 2014 11:33:21 -0000 @@ -67,6 +67,7 @@ #include /* will also get LOCKDEBUG */ #include #include +#include struct intrsource; @@ -112,6 +113,7 @@ struct cpu_info { paddr_t ci_idle_pcb_paddr; /* PA of idle PCB */ volatile u_long ci_flags; /* flags; see below */ u_int32_t ci_ipis; /* interprocessor interrupts pending */ + u_long ci_crit; u_int32_t ci_level; u_int32_t ci_vendor[4]; @@ -152,6 +154,8 @@ struct cpu_info { #ifdef GPROF struct gmonparam *ci_gmon; #endif + + struct ktr_ring *ci_ktr; }; /* @@ -512,5 +516,16 @@ void vm86_gpfault(struct proc *, int); #if defined(MULTIPROCESSOR) && defined(_KERNEL) #include #endif + +#define crit_enter_ci(_ci) do { \ + (_ci)->ci_crit = read_eflags(); \ + disable_intr(); \ +} while (0) +#define crit_leave_ci(_ci) do { \ + write_eflags((_ci)->ci_crit); \ +} while (0) + +#define crit_enter() crit_enter_ci(curcpu()) +#define crit_leave() crit_leave_ci(curcpu()) #endif /* !_MACHINE_CPU_H_ */ Index: conf/files =================================================================== RCS file: /cvs/src/sys/conf/files,v retrieving revision 1.582 diff -u -p -r1.582 files --- conf/files 12 Oct 2014 19:33:32 -0000 1.582 +++ conf/files 16 Oct 2014 11:33:22 -0000 @@ -674,6 +674,7 @@ file kern/kern_exit.c file kern/kern_fork.c file kern/kern_kthread.c file kern/kern_ktrace.c ktrace +file kern/kern_ktr.c file kern/kern_lock.c file kern/kern_malloc.c file kern/kern_malloc_debug.c malloc_debug Index: kern/init_main.c =================================================================== RCS file: /cvs/src/sys/kern/init_main.c,v retrieving revision 1.221 diff -u -p -r1.221 init_main.c --- kern/init_main.c 13 Oct 2014 22:42:22 -0000 1.221 +++ kern/init_main.c 16 Oct 2014 11:33:22 -0000 @@ -76,6 +76,7 @@ #include #include #include +#include #include #include @@ -457,6 +458,8 @@ main(void *framep) (void) tsleep((void *)&config_pending, PWAIT, "cfpend", 0); dostartuphooks(); + + ktr_enable(); #if NVSCSI > 0 config_rootfound("vscsi", NULL); Index: kern/kern_ktr.c =================================================================== RCS file: kern/kern_ktr.c diff -N kern/kern_ktr.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ kern/kern_ktr.c 16 Oct 2014 11:33:22 -0000 @@ -0,0 +1,111 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2014 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include + +#include +#include +#include + +void ktr_dump(void); +void ktr_dump_cpu(struct cpu_info *); + +int ktr_enabled = 0; +int ktr_lines = 8; + +void +__ktr_log(const char *file, u_int line, const char *event, int64_t data) +{ + struct cpu_info *ci = curcpu(); + struct ktr_ring *ring = ci->ci_ktr; + struct ktr_entry *e; + u_int i; + extern int ticks; + + crit_enter_ci(ci); + i = ring->r_index++; + ring->r_index %= KTR_ENTRIES; + crit_leave_ci(ci); + + e = &ring->r_entries[i]; + + e->ktr_tick = ticks; + e->ktr_stamp = rdtsc(); + + e->ktr_event = event; + e->ktr_data = data; + + e->ktr_line = line; + /* membar! */ + e->ktr_file = file; +} + +void +ktr_enable(void) +{ + CPU_INFO_ITERATOR cii; + struct cpu_info *ci; + + CPU_INFO_FOREACH(cii, ci) { + ci->ci_ktr = malloc(sizeof(struct ktr_ring), M_DEVBUF, + M_ZERO|M_WAITOK); + } + + ktr_enabled = 1; +} + +void +ktr_dump(void) +{ + CPU_INFO_ITERATOR cii; + struct cpu_info *ci; + + CPU_INFO_FOREACH(cii, ci) + ktr_dump_cpu(ci); +} + +void +ktr_dump_cpu(struct cpu_info *ci) +{ + struct ktr_ring *ring = ci->ci_ktr; + struct ktr_entry *e; + extern int ticks; + u_int i, idx; + + printf("ktr: cpu%d\n", CPU_INFO_UNIT(ci)); + + idx = i = ring->r_index; + + i += KTR_ENTRIES - ktr_lines; + do { + i %= KTR_ENTRIES; + + e = &ring->r_entries[i]; + if (e->ktr_file == NULL) + continue; + + printf(" %d+%llu: \"%s\" %lld(0x%llx) (%s[%u])\n", + e->ktr_tick, e->ktr_stamp, + e->ktr_event, e->ktr_data, e->ktr_data, + e->ktr_file, e->ktr_line); + } while (++i != idx); +} Index: kern/uipc_mbuf.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_mbuf.c,v retrieving revision 1.197 diff -u -p -r1.197 uipc_mbuf.c --- kern/uipc_mbuf.c 3 Oct 2014 02:16:21 -0000 1.197 +++ kern/uipc_mbuf.c 16 Oct 2014 11:33:22 -0000 @@ -86,6 +86,7 @@ #include #include +#include #include @@ -120,8 +121,8 @@ int max_hdr; /* largest link+protocol struct mutex m_extref_mtx = MUTEX_INITIALIZER(IPL_NET); -void m_extfree(struct mbuf *); -struct mbuf *m_copym0(struct mbuf *, int, int, int, int); +void m_extfree(const char *, u_int, struct mbuf *); +struct mbuf *m_copym0(const char *, u_int, struct mbuf *, int, int, int, int); void nmbclust_update(void); void m_zero(struct mbuf *); @@ -194,7 +195,7 @@ nmbclust_update(void) * Space allocation routines. */ struct mbuf * -m_get(int nowait, int type) +__m_get(const char *f, u_int l, int nowait, int type) { struct mbuf *m; @@ -212,6 +213,8 @@ m_get(int nowait, int type) m->m_data = m->m_dat; m->m_flags = 0; + ktr_log(f, l, __func__, (vaddr_t)m); + return (m); } @@ -220,7 +223,7 @@ m_get(int nowait, int type) * may need to change as well. */ struct mbuf * -m_gethdr(int nowait, int type) +__m_gethdr(const char *f, u_int l, int nowait, int type) { struct mbuf *m; @@ -234,6 +237,8 @@ m_gethdr(int nowait, int type) m->m_type = type; + ktr_log(f, l, __func__, (vaddr_t)m); + return (m_inithdr(m)); } @@ -279,7 +284,7 @@ m_clpool(u_int pktlen) } struct mbuf * -m_clget(struct mbuf *m, int how, struct ifnet *ifp, u_int pktlen) +__m_clget(const char *f, u_int l, struct mbuf *m, int how, u_int pktlen) { struct mbuf *m0 = NULL; struct pool *pp; @@ -292,7 +297,7 @@ m_clget(struct mbuf *m, int how, struct #endif if (m == NULL) { - m0 = m_gethdr(how, MT_DATA); + m0 = __m_gethdr(f, l, how, MT_DATA); if (m0 == NULL) return (NULL); @@ -301,10 +306,11 @@ m_clget(struct mbuf *m, int how, struct buf = pool_get(pp, how == M_WAIT ? PR_WAITOK : PR_NOWAIT); if (buf == NULL) { if (m0) - m_freem(m0); + __m_freem(f, l, m0); return (NULL); } + ktr_log(f, l, __func__, (vaddr_t)buf); MEXTADD(m, buf, pp->pr_size, M_EXTWR, m_extfree_pool, pp); return (m); } @@ -316,7 +322,7 @@ m_extfree_pool(caddr_t buf, u_int size, } struct mbuf * -m_free(struct mbuf *m) +__m_free(const char *f, u_int l, struct mbuf *m) { struct mbuf *n; @@ -334,7 +340,9 @@ m_free(struct mbuf *m) if (m->m_flags & M_PKTHDR) m_tag_delete_chain(m); if (m->m_flags & M_EXT) - m_extfree(m); + m_extfree(f, l, m); + + ktr_log(f, l, __func__, (vaddr_t)m); pool_put(&mbpool, m); @@ -382,9 +390,10 @@ m_extunref(struct mbuf *m) } void -m_extfree(struct mbuf *m) +m_extfree(const char *f, u_int l, struct mbuf *m) { if (m_extunref(m) == 0) { + ktr_log(f, l, __func__, (vaddr_t)m->m_ext.ext_buf); (*(m->m_ext.ext_free))(m->m_ext.ext_buf, m->m_ext.ext_size, m->m_ext.ext_arg); } @@ -393,10 +402,10 @@ m_extfree(struct mbuf *m) } void -m_freem(struct mbuf *m) +__m_freem(const char *f, u_int l, struct mbuf *m) { while (m != NULL) - m = m_free(m); + m = __m_free(f, l, m); } /* @@ -433,7 +442,7 @@ m_defrag(struct mbuf *m, int how) m_freem(m->m_next); m->m_next = NULL; if (m->m_flags & M_EXT) - m_extfree(m); + m_extfree(__FILE__, __LINE__, m); /* * Bounce copy mbuf over to the original mbuf and set everything up. @@ -499,9 +508,9 @@ m_prepend(struct mbuf *m, int len, int h * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller. */ struct mbuf * -m_copym(struct mbuf *m, int off, int len, int wait) +__m_copym(const char *f, u_int l, struct mbuf *m, int off, int len, int wait) { - return m_copym0(m, off, len, wait, 0); /* shallow copy on M_EXT */ + return m_copym0(f, l, m, off, len, wait, 0); /* shallow copy on M_EXT */ } /* @@ -509,13 +518,13 @@ m_copym(struct mbuf *m, int off, int len * of merely bumping the reference count. */ struct mbuf * -m_copym2(struct mbuf *m, int off, int len, int wait) +__m_copym2(const char *f, u_int l, struct mbuf *m, int off, int len, int wait) { - return m_copym0(m, off, len, wait, 1); /* deep copy */ + return m_copym0(f, l, m, off, len, wait, 1); /* deep copy */ } struct mbuf * -m_copym0(struct mbuf *m0, int off, int len, int wait, int deep) +m_copym0(const char *f, u_int l, struct mbuf *m0, int off, int len, int wait, int deep) { struct mbuf *m, *n, **np; struct mbuf *top; @@ -535,7 +544,7 @@ m_copym0(struct mbuf *m0, int off, int l panic("m_copym0: m == NULL and not COPYALL"); break; } - MGET(n, wait, m->m_type); + n = __m_get(f, l, wait, m->m_type); *np = n; if (n == NULL) goto nospace; @@ -557,7 +566,7 @@ m_copym0(struct mbuf *m0, int off, int l * we are unsure about the way m was allocated. * copy into multiple MCLBYTES cluster mbufs. */ - MCLGET(n, wait); + n = __m_clget(f, l, n, MCLBYTES, wait); n->m_len = 0; n->m_len = M_TRAILINGSPACE(n); n->m_len = min(n->m_len, len); @@ -583,7 +592,7 @@ m_copym0(struct mbuf *m0, int off, int l } return (top); nospace: - m_freem(top); + __m_freem(f, l, top); return (NULL); } @@ -701,8 +710,11 @@ out: * Any m_pkthdr is not updated. */ void -m_cat(struct mbuf *m, struct mbuf *n) +__m_cat(const char *f, u_int l, struct mbuf *m, struct mbuf *n) { + ktr_log(f, l, __func__, (vaddr_t)m); + if (n) + ktr_log(f, l, __func__, (vaddr_t)n); while (m->m_next) m = m->m_next; while (n) { Index: sys/ktr.h =================================================================== RCS file: sys/ktr.h diff -N sys/ktr.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/ktr.h 16 Oct 2014 11:33:22 -0000 @@ -0,0 +1,53 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2014 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_KTR_H_ +#define _SYS_KTR_H_ + +#define KTR_ENTRIES 2048 + +struct ktr_entry { + u_int64_t ktr_stamp; + int64_t ktr_data; + const char * ktr_event; + const char * ktr_file; + u_int ktr_line; + int ktr_tick; +}; + +struct ktr_ring { + struct ktr_entry r_entries[KTR_ENTRIES]; + u_int r_index; +}; + +extern int ktr_enabled; + +void __ktr_log(const char *, u_int, const char *, int64_t); +void ktr_enable(void); + +#define KTR_LOG(_event, _data) do { \ + if (ktr_enabled) \ + __ktr_log(__FILE__, __LINE__, (_event), (_data)); \ +} while (0) + +#define ktr_log(_f, _l, _event, _data) do { \ + if (ktr_enabled) \ + __ktr_log((_f), (_l), (_event), (_data)); \ +} while (0) + +#endif /* _SYS_KTR_H_ */ Index: sys/mbuf.h =================================================================== RCS file: /cvs/src/sys/sys/mbuf.h,v retrieving revision 1.183 diff -u -p -r1.183 mbuf.h --- sys/mbuf.h 3 Oct 2014 01:02:47 -0000 1.183 +++ sys/mbuf.h 16 Oct 2014 11:33:22 -0000 @@ -397,12 +397,12 @@ extern int max_protohdr; /* largest pro extern int max_hdr; /* largest link+protocol header */ void mbinit(void); -struct mbuf *m_copym2(struct mbuf *, int, int, int); -struct mbuf *m_copym(struct mbuf *, int, int, int); -struct mbuf *m_free(struct mbuf *); -struct mbuf *m_get(int, int); +struct mbuf *__m_copym2(const char *, u_int, struct mbuf *, int, int, int); +struct mbuf *__m_copym(const char *, u_int ,struct mbuf *, int, int, int); +struct mbuf *__m_free(const char *, u_int, struct mbuf *); +struct mbuf *__m_get(const char *, u_int, int, int); struct mbuf *m_getclr(int, int); -struct mbuf *m_gethdr(int, int); +struct mbuf *__m_gethdr(const char *, u_int, int, int); struct mbuf *m_inithdr(struct mbuf *); int m_defrag(struct mbuf *, int); struct mbuf *m_prepend(struct mbuf *, int, int); @@ -413,19 +413,28 @@ struct mbuf *m_inject(struct mbuf *, in struct mbuf *m_getptr(struct mbuf *, int, int *); int m_leadingspace(struct mbuf *); int m_trailingspace(struct mbuf *); -struct mbuf *m_clget(struct mbuf *, int, struct ifnet *, u_int); +struct mbuf *__m_clget(const char *, u_int, struct mbuf *, int, u_int); void m_extref(struct mbuf *, struct mbuf *); void m_extfree_pool(caddr_t, u_int, void *); void m_adj(struct mbuf *, int); int m_copyback(struct mbuf *, int, int, const void *, int); -void m_freem(struct mbuf *); +void __m_freem(const char *, u_int, struct mbuf *); void m_reclaim(void *, int); void m_copydata(struct mbuf *, int, int, caddr_t); -void m_cat(struct mbuf *, struct mbuf *); +void __m_cat(const char *, u_int, struct mbuf *, struct mbuf *); struct mbuf *m_devget(char *, int, int, struct ifnet *); int m_apply(struct mbuf *, int, int, int (*)(caddr_t, caddr_t, unsigned int), caddr_t); int m_dup_pkthdr(struct mbuf *, struct mbuf *, int); + +#define m_copym2(_a, _b, _c, _d) __m_copym2(__FILE__, __LINE__, (_a), (_b), (_c), (_d)) +#define m_copym(_a, _b, _c, _d) __m_copym(__FILE__, __LINE__, (_a), (_b), (_c), (_d)) +#define m_get(_a, _b) __m_get(__FILE__, __LINE__, (_a), (_b)) +#define m_gethdr(_a, _b) __m_gethdr(__FILE__, __LINE__, (_a), (_b)) +#define m_clget(_m, _s, _i, _f) __m_clget(__FILE__, __LINE__, (_m), (_s), (_f)) +#define m_free(_m) __m_free(__FILE__, __LINE__, (_m)) +#define m_freem(_m) __m_freem(__FILE__, __LINE__, (_m)) +#define m_cat(_m, _n) __m_cat(__FILE__, __LINE__, (_m), (_n)) /* Packet tag routines */ struct m_tag *m_tag_get(int, int, int);