Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 22 Sep 2006 07:46:58 +1000
From:      "Jan Mikkelsen" <janm@transactionware.com>
To:        <freebsd-stable@freebsd.org>
Subject:   Patch: sym(4) "VTOBUS FAILED" panics on amd64, amd64/89550
Message-ID:  <002d01c6ddc7$76d10cc0$0202a8c0@transactzbkv04>

index | next in thread | raw e-mail

[-- Attachment #1 --]
Hi,

I posted this to freebsd-amd64, but I've had no replies.

This fixes the sym "VTOBUS FAILED" panics that I got consistently on
6.1-RELEASE/amd64;  see the PR amd64/89550 for dmesg, other reports, etc.

Quick summary:  sym(4) assumes on amd64 that virtual addresses provided by
bus_dmamem_alloc() have the same alignment as the physical addresses (in
this case, 2*PAGE_SIZE).  They don't, and stuff breaks.  This patch works
around that.

I'm looking for someone to take a quick look at it and make sure that the
approach is reasonable.  I would be nice if a fix was committed (not
necessarily mine).

sym(4) is listed as supported in the 6.1/amd64 hardware guide, but it
doesn't seem to be working at all.  For 6.2, I either suggest putting in a
fix so that it is supported, or having a note in the hardware guide.

Sorry about coming along so late in the release cycle, but I first
encountered the problem on Monday.

Thanks,

Jan Mikkelsen

[-- Attachment #2 --]
*** FreeBSD/src/sys/dev/sym/sym_hipd.c	Tue Aug  8 00:43:31 2006
--- /home/janm/sym_hipd.c	Tue Sep 19 15:27:55 2006
***************
*** 439,445 ****
  #define free_pages(p)		free((p), M_DEVBUF)
  #else
  #define get_pages()		contigmalloc(MEMO_CLUSTER_SIZE, M_DEVBUF, \
! 				    0, 0, 1LL << 32, PAGE_SIZE, 1LL << 32)
  #define free_pages(p)		contigfree((p), MEMO_CLUSTER_SIZE, M_DEVBUF)
  #endif
  
--- 439,446 ----
  #define free_pages(p)		free((p), M_DEVBUF)
  #else
  #define get_pages()		contigmalloc(MEMO_CLUSTER_SIZE, M_DEVBUF, \
! 				    0, 0, 1LL << 32, PAGE_SIZE, \
! 				    MEMO_CLUSTER_SIZE)
  #define free_pages(p)		contigfree((p), MEMO_CLUSTER_SIZE, M_DEVBUF)
  #endif
  
***************
*** 453,458 ****
--- 454,462 ----
  	struct m_vtob	*next;
  	bus_dmamap_t	dmamap;	/* Map for this chunk */
  	m_addr_t	vaddr;	/* Virtual address */
+ #if PAGE_SIZE < MEMO_CLUSTER_SIZE
+ 	m_addr_t	adjusted_vaddr;	/* Virtual address adjusted for buddy */
+ #endif
  	m_addr_t	baddr;	/* Bus physical address */
  } m_vtob_s;
  /* Hash this stuff a bit to speed up translations */
***************
*** 674,685 ****
  	if (bus_dmamem_alloc(mp->dmat, &vaddr,
  			      BUS_DMA_NOWAIT, &vbp->dmamap))
  		goto out_err;
  	bus_dmamap_load(mp->dmat, vbp->dmamap, vaddr,
  			MEMO_CLUSTER_SIZE, getbaddrcb, &baddr, 0);
  	if (baddr) {
! 		int hc = VTOB_HASH_CODE(vaddr);
  		vbp->vaddr = (m_addr_t) vaddr;
  		vbp->baddr = (m_addr_t) baddr;
  		vbp->next = mp->vtob[hc];
  		mp->vtob[hc] = vbp;
  		++mp->nump;
--- 678,711 ----
  	if (bus_dmamem_alloc(mp->dmat, &vaddr,
  			      BUS_DMA_NOWAIT, &vbp->dmamap))
  		goto out_err;
+ #if PAGE_SIZE < MEMO_CLUSTER_SIZE
+ 	bus_dmamap_load(mp->dmat, vbp->dmamap, vaddr,
+ 			MEMO_CLUSTER_SIZE * 2, getbaddrcb, &baddr, 0);
+ #else
  	bus_dmamap_load(mp->dmat, vbp->dmamap, vaddr,
  			MEMO_CLUSTER_SIZE, getbaddrcb, &baddr, 0);
+ #endif
  	if (baddr) {
! 		int hc;
! 
  		vbp->vaddr = (m_addr_t) vaddr;
  		vbp->baddr = (m_addr_t) baddr;
+ #if PAGE_SIZE < MEMO_CLUSTER_SIZE
+ 		/*
+ 		 * Adjusting vaddr is OK here because we do not error out.
+ 		 * If that changes, the bus_dmamem_free() call below would
+ 		 * need to be fixed.
+ 		 *
+ 		 * This code assumes that we will be at most one page away
+ 		 * from having things aligned the way we want.
+ 		 */
+ 
+ 		if (((m_addr_t) vaddr & ~MEMO_CLUSTER_MASK) != (m_addr_t) vaddr)
+ 			vaddr = (void*) ((m_addr_t) vaddr + PAGE_SIZE);
+ 
+ 		vbp->adjusted_vaddr = (m_addr_t) vaddr;
+ #endif
+ 	       	hc = VTOB_HASH_CODE(vaddr);
  		vbp->next = mp->vtob[hc];
  		mp->vtob[hc] = vbp;
  		++mp->nump;
***************
*** 733,744 ****
  	mp = __sym_calloc(&mp0, sizeof(*mp), "MPOOL");
  	if (mp) {
  		mp->dev_dmat = dev_dmat;
! 		if (!bus_dma_tag_create(dev_dmat, 1, MEMO_CLUSTER_SIZE,
  			       BUS_SPACE_MAXADDR_32BIT,
  			       BUS_SPACE_MAXADDR_32BIT,
  			       NULL, NULL, MEMO_CLUSTER_SIZE, 1,
  			       MEMO_CLUSTER_SIZE, 0,
  			       busdma_lock_mutex, &Giant, &mp->dmat)) {
  			mp->getp = ___dma_getp;
  #ifdef	MEMO_FREE_UNUSED
  			mp->freep = ___dma_freep;
--- 759,779 ----
  	mp = __sym_calloc(&mp0, sizeof(*mp), "MPOOL");
  	if (mp) {
  		mp->dev_dmat = dev_dmat;
! #if PAGE_SIZE < MEMO_CLUSTER_SIZE
! 		if (!bus_dma_tag_create(dev_dmat, 1, MEMO_CLUSTER_SIZE * 2,
  			       BUS_SPACE_MAXADDR_32BIT,
+ 			       BUS_SPACE_MAXADDR,
+ 			       NULL, NULL, MEMO_CLUSTER_SIZE * 2, 1,
+ 			       MEMO_CLUSTER_SIZE * 2, 0,
+ 			       busdma_lock_mutex, &Giant, &mp->dmat)) {
+ #else
+ 		if (!bus_dma_tag_create(dev_dmat, 1, MEMO_CLUSTER_SIZE,
  			       BUS_SPACE_MAXADDR_32BIT,
+ 			       BUS_SPACE_MAXADDR,
  			       NULL, NULL, MEMO_CLUSTER_SIZE, 1,
  			       MEMO_CLUSTER_SIZE, 0,
  			       busdma_lock_mutex, &Giant, &mp->dmat)) {
+ #endif
  			mp->getp = ___dma_getp;
  #ifdef	MEMO_FREE_UNUSED
  			mp->freep = ___dma_freep;
***************
*** 815,827 ****
  	mp = ___get_dma_pool(dev_dmat);
  	if (mp) {
  		vp = mp->vtob[hc];
  		while (vp && (m_addr_t) vp->vaddr != a)
  			vp = vp->next;
  	}
  	/* Unlock */
  	if (!vp)
  		panic("sym: VTOBUS FAILED!\n");
! 	return vp ? vp->baddr + (((m_addr_t) m) - a) : 0;
  }
  
  
--- 850,872 ----
  	mp = ___get_dma_pool(dev_dmat);
  	if (mp) {
  		vp = mp->vtob[hc];
+ #if (PAGE_SIZE < MEMO_CLUSTER_SIZE)
+ 		while (vp && (m_addr_t) vp->adjusted_vaddr != a)
+ #else
  		while (vp && (m_addr_t) vp->vaddr != a)
+ #endif
  			vp = vp->next;
  	}
+ 
  	/* Unlock */
  	if (!vp)
  		panic("sym: VTOBUS FAILED!\n");
! #if (PAGE_SIZE < MEMO_CLUSTER_SIZE)
! 	return vp->baddr + (((m_addr_t) m) - a) +
! 		(vp->adjusted_vaddr - vp->vaddr);
! #else
! 	return vp->baddr + (((m_addr_t) m) - a);
! #endif
  }
  
  
home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?002d01c6ddc7$76d10cc0$0202a8c0>