panic in bus_dma_tag_destroy()
Chuck Tuffli
chuck_tuffli at agilent.com
Thu Oct 7 18:49:02 PDT 2004
On Wed, Oct 06, 2004 at 07:57:20PM -0700, Matthew Dillon wrote:
. ..
> This looks like a custom driver that we do not have source for (you
> should have said that at the beginning!).
Sorry for not being more clear about this. The driver does nothing
very interesting, but I'd be happy to post/email it if you'd like.
> The panic in free() is definitely due to some sort of corruption,
> either a double-free or some other memory corruption is occuring.
> That's my best guess.
I did some debugging today and this is what I found. The panic occurs
because of an assert in kern_slaballoc.c:free()
/*
* Zone case. Figure out the zone based on the fact that it is
* ZoneSize aligned.
*/
z = (SLZone *)((uintptr_t)ptr & ~(uintptr_t)ZoneMask);
KKASSERT(z->z_Magic == ZALLOC_SLAB_MAGIC);
The problem is that this memory isn't a zone, it's a chunk whose
ku_pagecnt is zero and thus fails the previous block ("Handle
oversized allocations. ...")
{
struct kmemusage *kup;
unsigned long size;
kup = btokup(ptr);
if (kup->ku_pagecnt) {
...
This is how we got here. The driver creates a DMA tag with the max #
of segments set to BUS_SPACE_MAXSIZE_32BIT. bus_dma_tag_create() uses
this value to malloc newtag->segments. The number of bytes it asks
malloc to allocate is (# segments * sizeof(bus_dma_segment_t)) = -8 or
0xfffffff8. malloc() sees this as a large allocation and allocates a
chunk (comment reads "Handle large allocations directly"), ie.
if (size >= ZoneLimit || (size & PAGE_MASK) == 0) {
Here, size (0xfffffff8) is set to zero by the round_page() macro
which is stored in kup->ku_pagecnt which later causes the panic.
Probably, this is a driver bug, which is fine by me, but there are a
couple of disk drivers which do something similar (adv_pci.c,
adw_pci.c, bt_pci.c, mpt_pci.c) and maybe some other non-disk drivers
(didn't look).
--
Chuck Tuffli
Agilent Technologies
More information about the Bugs
mailing list