diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2016-11-02 03:29:49 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2016-11-02 03:29:49 +0000 |
commit | 2af617f9257fa3f94e18023b7d1da0043246fdf6 (patch) | |
tree | ea0e5c7385d64fd0503854eb2394103ae3c12afb | |
parent | cd7c60f2333956b16c16af8d23f1aba958214fee (diff) |
add poisoning of items on the per cpu caches.
it copies the existing pool code, except it works on pool_list
structures instead of pool_item structures.
after this id like to poison the words used by the TAILQ_ENTRY in
the pool_list struct that arent used until a list of items is moved
into the global depot.
-rw-r--r-- | sys/kern/subr_pool.c | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/sys/kern/subr_pool.c b/sys/kern/subr_pool.c index 536ea29701c..2d1e8e4e6c7 100644 --- a/sys/kern/subr_pool.c +++ b/sys/kern/subr_pool.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_pool.c,v 1.200 2016/11/02 01:58:07 dlg Exp $ */ +/* $OpenBSD: subr_pool.c,v 1.201 2016/11/02 03:29:48 dlg Exp $ */ /* $NetBSD: subr_pool.c,v 1.61 2001/09/26 07:14:56 chs Exp $ */ /*- @@ -104,6 +104,15 @@ struct pool_list { TAILQ_ENTRY(pool_list) pl_nextl; /* list of lists */ }; +#define POOL_LIST_NITEMS_MASK 0x7ffffffUL +#define POOL_LIST_NITEMS_POISON 0x8000000UL + +#define POOL_LIST_POISONED(_pl) \ + ISSET((_pl)->pl_nitems, POOL_LIST_NITEMS_POISON) + +#define POOL_LIST_NITEMS(_pl) \ + ((_pl)->pl_nitems & POOL_LIST_NITEMS_MASK) + struct pool_cache { struct pool_list *pc_actv; unsigned long pc_nactv; /* cache pc_actv nitems */ @@ -1678,12 +1687,29 @@ pool_cache_get(struct pool *pp) } pc->pc_actv = pl->pl_next; - pc->pc_nactv = pl->pl_nitems - 1; + pc->pc_nactv = POOL_LIST_NITEMS(pl) - 1; pc->pc_gets++; pc->pc_nout++; + done: pool_cache_leave(pp, pc, s); +#ifdef DIAGNOSTIC + if (pool_debug && pl != NULL && POOL_LIST_POISONED(pl)) { + size_t pidx; + uint32_t pval; + + if (poison_check(pl + 1, pp->pr_size - sizeof(*pl), + &pidx, &pval)) { + int *ip = (int *)(pl + 1); + panic("%s: %s cpu free list modified: " + "item addr %p; offset 0x%zx=0x%x", + __func__, pp->pr_wchan, pl, + pidx * sizeof(int) + sizeof(*pl), ip[pidx]); + } + } +#endif + return (pl); } @@ -1692,14 +1718,19 @@ pool_cache_put(struct pool *pp, void *v) { struct pool_cache *pc; struct pool_list *pl = v; - unsigned long cache_items = pp->pr_cache_items; unsigned long nitems; int s; +#ifdef DIAGNOSTIC + int poison = pool_debug && pp->pr_size > sizeof(*pl); + + if (poison) + poison_mem(pl + 1, pp->pr_size - sizeof(*pl)); +#endif pc = pool_cache_enter(pp, &s); nitems = pc->pc_nactv; - if (nitems >= cache_items) { + if (nitems >= pp->pr_cache_items) { if (pc->pc_prev != NULL) pool_list_free(pp, pc, pc->pc_prev); @@ -1712,6 +1743,9 @@ pool_cache_put(struct pool *pp, void *v) pl->pl_next = pc->pc_actv; pl->pl_nitems = ++nitems; +#ifdef DIAGNOSTIC + pl->pl_nitems |= poison ? POOL_LIST_NITEMS_POISON : 0; +#endif pc->pc_actv = pl; pc->pc_nactv = nitems; |