Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 Jan 2003 23:55:18 +0100
From:      Thomas Moestl <tmoestl@gmx.net>
To:        Roderick van Domburg <r.s.a.vandomburg@student.utwente.nl>
Cc:        freebsd-sparc64@freebsd.org
Subject:   Re: panic: trap: fast data access mmu miss
Message-ID:  <20030112225517.GB278@crow.dom2ip.de>
In-Reply-To: <LJEKLJEBPDDLMNCFCIOGAENLCAAA.r.s.a.vandomburg@student.utwente.nl>
References:  <20030112010950.GA56998@crow.dom2ip.de> <LJEKLJEBPDDLMNCFCIOGAENLCAAA.r.s.a.vandomburg@student.utwente.nl>

next in thread | previous in thread | raw e-mail | index | archive | help

--XsQoSWH+UP9D9v3l
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Sun, 2003/01/12 at 16:13:20 +0100, Roderick van Domburg wrote:
> > > Running on a Sun Enterprise 250 with a single UltraSparc-II
> > > CPU, 512 MB RAM and three Fujitsu SCSI-II hard disks. I've had
> > > this same problem with sources over the past few (three?) days.
> > > I had to copy this dmesg by hand, so please bear with any
> > > possible typos.
> >
> > Please try the attached diff. The crash was due to what I consider a
> > driver bug (not checking the error in the bus_dmamap_load() callback),
> > however due to the FreeBSD busdma API being largely undocumented it is
> > a bit difficult to tell what should be considered legal. Much more
> > problematic is to assume that the first segment's bus address will be
> > 0 in the error case. This is not currently guaranteed by any
> > implementation.
> >
> > The attached patch fixes that, and also passes a valid pointer to the
> > callback for maximum compatability. It also fixes some other bugs I
> > came across.
> >
> > This does however still not address the reason for the
> > bus_dmamap_load() failure; I'm not really sure why this does
> > happen. Please look for messages like:
> >  __sym_calloc2: failed to allocate ...
> > and tell me if you see any of them.
> 
> Thanks for the patches! Unfortunately however, it still doesn't seem to
> attach sym1 quite right, I believe. Your patches did make the booting
> process advance further, but the kernel failed to mount root. Here is the
> dmesg, once again manually copied. That __sym_calloc2 message is right on
> the second line.

Hmmm, that's what I expected. Can you please try the attached patch
instead? It adds some more error reporting, so I should be able to see
what exactly is going wrong. Please mail me any new lines of output
appearing directly above the __sym_calloc2 message.

I think I've already ruled out most causes; I'm suspecting that
malloc() might be failing due to massive use of M_NOWAIT in the
related code.

	- Thomas

-- 
Thomas Moestl <tmoestl@gmx.net>	http://www.tu-bs.de/~y0015675/
              <tmm@FreeBSD.org>	http://people.FreeBSD.org/~tmm/
PGP fingerprint: 1C97 A604 2BD0 E492 51D0  9C0F 1FE6 4F1D 419C 776C

--XsQoSWH+UP9D9v3l
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="iommu-errbd.diff"

Index: sparc64/sparc64/iommu.c
===================================================================
RCS file: /ncvs/src/sys/sparc64/sparc64/iommu.c,v
retrieving revision 1.14
diff -u -r1.14 iommu.c
--- sparc64/sparc64/iommu.c	6 Jan 2003 21:59:54 -0000	1.14
+++ sparc64/sparc64/iommu.c	12 Jan 2003 22:43:59 -0000
@@ -517,10 +517,13 @@
 {
 	struct resource *res;
 	struct bus_dmamap_res *bdr;
-	bus_size_t align, bound, sgsize;
+	bus_size_t align, sgsize;
 
-	if ((bdr = malloc(sizeof(*bdr), M_IOMMU, M_NOWAIT)) == NULL)
+	if ((bdr = malloc(sizeof(*bdr), M_IOMMU, M_NOWAIT)) == NULL) {
+		printf("iommu_dvma_valloc: res descriptor allocation "
+		    "failed.\n");
 		return (EAGAIN);
+	}
 	/*
 	 * If a boundary is specified, a map cannot be larger than it; however
 	 * we do not clip currently, as that does not play well with the lazy
@@ -531,12 +534,13 @@
 	sgsize = round_io_page(size) >> IO_PAGE_SHIFT;
 	if (t->dt_boundary > 0 && t->dt_boundary < IO_PAGE_SIZE)
 		panic("iommu_dvmamap_load: illegal boundary specified");
-	bound = ulmax(t->dt_boundary >> IO_PAGE_SHIFT, 1);
 	res = rman_reserve_resource_bound(&iommu_dvma_rman, 0L,
-	    t->dt_lowaddr, sgsize, bound >> IO_PAGE_SHIFT,
+	    t->dt_lowaddr, sgsize, t->dt_boundary >> IO_PAGE_SHIFT,
 	    RF_ACTIVE | rman_make_alignment_flags(align), NULL);
-	if (res == NULL)
+	if (res == NULL) {
+		printf("iommu_dvma_valloc: out of DVMA space.\n");
 		return (ENOMEM);
+	}
 
 	bdr->dr_res = res;
 	bdr->dr_used = 0;
@@ -766,8 +770,10 @@
 	pmap_t pmap = NULL;
 
 	KASSERT(buflen != 0, ("iommu_dvmamap_load_buffer: buflen == 0!"));
-	if (buflen > dt->dt_maxsize)
+	if (buflen > dt->dt_maxsize) {
+		printf("iommu_dvmamap_load_buffer: buffer too long.\n");
 		return (EINVAL);
+	}
 
 	if (td != NULL)
 		pmap = vmspace_pmap(td->td_proc->p_vmspace);
@@ -813,6 +819,8 @@
 			sgcnt++;
 			if (sgcnt >= dt->dt_nsegments ||
 			    sgcnt >= BUS_DMAMAP_NSEGS) {
+				printf("iommu_dvmamap_load_buffer: too many "
+				    "segments.\n");
 				error = EFBIG;
 				break;
 			}
@@ -860,7 +868,7 @@
 
 	if (error != 0) {
 		iommu_dvmamap_vunload(is, map);
-		(*cb)(cba, NULL, 0, error);
+		(*cb)(cba, sgs, 0, error);
 	} else {
 		/* Move the map to the end of the LRU queue. */
 		iommu_map_insq(map);
Index: dev/sym/sym_hipd.c
===================================================================
RCS file: /ncvs/src/sys/dev/sym/sym_hipd.c,v
retrieving revision 1.38
diff -u -r1.38 sym_hipd.c
--- dev/sym/sym_hipd.c	1 Jan 2003 18:48:52 -0000	1.38
+++ dev/sym/sym_hipd.c	12 Jan 2003 01:05:21 -0000
@@ -712,7 +712,10 @@
 {
 	bus_addr_t *baddr;
 	baddr = (bus_addr_t *)arg;
-	*baddr = segs->ds_addr;
+	if (error != 0)
+		*baddr = 0;
+	else
+		*baddr = segs->ds_addr;
 }
 
 static m_addr_t ___dma_getp(m_pool_s *mp)
@@ -728,8 +731,9 @@
 	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 (bus_dmamap_load(mp->dmat, vbp->dmamap, vaddr,
+			    MEMO_CLUSTER_SIZE, getbaddrcb, &baddr, 0))
+		goto out_err;
 	if (baddr) {
 		int hc = VTOB_HASH_CODE(vaddr);
 		vbp->vaddr = (m_addr_t) vaddr;
@@ -744,8 +748,6 @@
 		bus_dmamap_unload(mp->dmat, vbp->dmamap);
 	if (vaddr)
 		bus_dmamem_free(mp->dmat, vaddr, vbp->dmamap);
-	if (vbp->dmamap)
-		bus_dmamap_destroy(mp->dmat, vbp->dmamap);
 	if (vbp)
 		__sym_mfree(&mp0, vbp, sizeof(*vbp), "VTOB");
 	return 0;
Index: kern/subr_rman.c
===================================================================
RCS file: /ncvs/src/sys/kern/subr_rman.c,v
retrieving revision 1.27
diff -u -r1.27 subr_rman.c
--- kern/subr_rman.c	27 Nov 2002 03:55:22 -0000	1.27
+++ kern/subr_rman.c	12 Jan 2003 22:45:20 -0000
@@ -229,7 +229,7 @@
 		 */
 		do {
 			rstart = (rstart + amask) & ~amask;
-			if (((rstart ^ (rstart + count)) & bmask) != 0)
+			if (((rstart ^ (rstart + count - 1)) & bmask) != 0)
 				rstart += bound - (rstart & ~bmask);
 		} while ((rstart & amask) != 0 && rstart < end &&
 		    rstart < s->r_end);
@@ -263,8 +263,11 @@
 			 * two new allocations; the second requires but one.
 			 */
 			rv = malloc(sizeof *rv, M_RMAN, M_NOWAIT | M_ZERO);
-			if (rv == 0)
+			if (rv == 0) {
+				printf("rman_reserve_resource: out of "
+				    "memory.\n");
 				goto out;
+			}
 			rv->r_start = rstart;
 			rv->r_end = rstart + count - 1;
 			rv->r_flags = flags | RF_ALLOCATED;
@@ -282,6 +285,8 @@
 				 */
 				r = malloc(sizeof *r, M_RMAN, M_NOWAIT|M_ZERO);
 				if (r == 0) {
+					printf("rman_reserve_resource: out of "
+					    "memory.\n");
 					free(rv, M_RMAN);
 					rv = 0;
 					goto out;

--XsQoSWH+UP9D9v3l--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-sparc" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030112225517.GB278>