PERFORCE change 191104 for review

John Baldwin jhb at FreeBSD.org
Wed Apr 6 19:17:29 UTC 2011


http://p4web.freebsd.org/@@191104?ac=10

Change 191104 by jhb at jhb_jhbbsd on 2011/04/06 19:16:53

	Fix a few bugs to get this to work when the PCI-PCI bridges are
	all purposefully sabotaged:
	- Fix an off-by-one error in the "is this allocation impossible"
	  check.
	- Properly mask off the right set of bits when aligning a new
	  candidate start address.
	- Add some more bootverbose printfs to help debug issues in the
	  future.
	- Actually update the rman to let it know about newly valid address
	  space when growing the window.
	- Check for underflow and overflow when calculating the front and
	  back regions and throw out the front or back attempt if it occurs.
	  (If it happens it means there isn't enough room at that end of
	  the window.)
	- Stubbed out code to sabotage the PCI-PCI bridges for testing.

Affected files ...

.. //depot/projects/pci/sys/dev/pci/pci_pci.c#10 edit

Differences ...

==== //depot/projects/pci/sys/dev/pci/pci_pci.c#10 (text+ko) ====

@@ -208,6 +208,20 @@
 
 	dev = sc->dev;
 
+#if 0
+	/* XXX: Gross hack, disable all windows for testing. */
+	pci_write_config(dev, PCIR_IOBASEL_1, 0xff, 1);
+	pci_write_config(dev, PCIR_IOBASEH_1, 0xffff, 2);
+	pci_write_config(dev, PCIR_IOLIMITL_1, 0, 1);
+	pci_write_config(dev, PCIR_IOLIMITH_1, 0, 2);
+	pci_write_config(dev, PCIR_MEMBASE_1, 0xffff, 2);
+	pci_write_config(dev, PCIR_MEMLIMIT_1, 0, 2);
+	pci_write_config(dev, PCIR_PMBASEL_1, 0xffff, 2);
+	pci_write_config(dev, PCIR_PMBASEH_1, 0xffffffff, 4);
+	pci_write_config(dev, PCIR_PMLIMITL_1, 0, 2);
+	pci_write_config(dev, PCIR_PMLIMITH_1, 0, 4);
+#endif
+
 	/* Determine if the I/O port window is implemented. */
 	val = pci_read_config(dev, PCIR_IOBASEL_1, 1);
 	if (val == 0) {
@@ -834,7 +848,7 @@
 		return (EINVAL);
 	if (end > w->rman.rm_end)
 		end = w->rman.rm_end;
-	if (start + count > end || start + count < start)
+	if (start + count - 1 > end || start + count < start)
 		return (EINVAL);
 
 	/*
@@ -846,20 +860,35 @@
 			flags &= ~RF_ALIGNMENT_MASK;
 			flags |= RF_ALIGNMENT_LOG2(w->step);
 		}
-		start &= ((1ul << w->step) - 1);
+		start &= ~((1ul << w->step) - 1);
 		end |= ((1ul << w->step) - 1);
-		if (count < (1ul << w->step))
-			count = 1ul << w->step;
+		count = roundup2(count, 1ul << w->step);
 		rid = w->reg;
 		w->res = bus_alloc_resource(sc->dev, type, &rid, start, end,
 		    count, flags);
-		if (w->res == NULL)
+		if (w->res == NULL) {
+			if (bootverbose)
+				device_printf(sc->dev,
+		    "failed to allocate initial %s window (%#lx-%#lx,%#lx)\n",
+				    w->name, start, end, count);
 			return (ENXIO);
+		}
 		if (bootverbose)
 			device_printf(sc->dev,
 			    "allocated initial %s window of %#lx-%#lx\n",
 			    w->name, rman_get_start(w->res),
 			    rman_get_end(w->res));
+		error = rman_manage_region(&w->rman, rman_get_start(w->res),
+		    rman_get_end(w->res));
+		if (error) {
+			if (bootverbose)
+				device_printf(sc->dev,
+				    "failed to add initial %s window to rman\n",
+				    w->name);
+			bus_release_resource(sc->dev, type, w->reg, w->res);
+			w->res = NULL;
+			return (error);
+		}
 		goto updatewin;
 	}
 
@@ -890,7 +919,7 @@
 			end_free = end;
 
 		/* Move end_free down until it is properly aligned. */
-		end_free &= (align - 1);
+		end_free &= ~(align - 1);
 		front = end_free - count;
 
 		/*
@@ -898,8 +927,9 @@
 		 * end_free).  Ensure that fits in the (start, end)
 		 * bounds.  end_free is checked above.  If 'front' is
 		 * ok, ensure it is properly aligned for this window.
+		 * Also check for underflow.
 		 */
-		if (front >= start) {
+		if (front >= start && front <= end_free) {
 			if (bootverbose)
 				printf("\tfront candidate range: %#lx-%#lx\n",
 				    front, end_free);
@@ -925,8 +955,9 @@
 		 * back).  Ensure that fits in the (start, end)
 		 * bounds.  start_free is checked above.  If 'back' is
 		 * ok, ensure it is properly aligned for this window.
+		 * Also check for overflow.
 		 */
-		if (back <= end) {
+		if (back <= end && start_free <= back) {
 			if (bootverbose)
 				printf("\tback candidate range: %#lx-%#lx\n",
 				    start_free, back);
@@ -966,6 +997,25 @@
 		device_printf(sc->dev, "grew %s window to %#lx-%#lx\n",
 		    w->name, rman_get_start(w->res), rman_get_end(w->res));
 
+	/* Add the newly allocated region to the resource manager. */
+	if (w->base != rman_get_start(w->res)) {
+		KASSERT(w->limit == rman_get_end(w->res), ("both ends moved"));
+		error = rman_manage_region(&w->rman, rman_get_start(w->res),
+		    w->base - 1);
+	} else {
+		KASSERT(w->limit != rman_get_end(w->res),
+		    ("neither end moved"));
+		error = rman_manage_region(&w->rman, w->limit + 1,
+		    rman_get_end(w->res));
+	}
+	if (error) {
+		if (bootverbose)
+			device_printf(sc->dev,
+			    "failed to expand %s resource manager\n", w->name);
+		bus_adjust_resource(sc->dev, type, w->res, w->base, w->limit);
+		return (error);
+	}
+
 updatewin:
 	/* Save the new window. */
 	w->base = rman_get_start(w->res);
@@ -1008,6 +1058,9 @@
 	/*
 	 * XXX: Need similar handling for ISA resources subject to the
 	 * ISA enable bit.
+	 *
+	 * XXX: Err, no.  What we need to do is block access to specific
+	 * I/O port ranges when ISA enable is set.
 	 */
 #ifdef notyet
 	if ((type == SYS_RES_IOPORT && pci_is_isa_ioport_range(start, end)) ||


More information about the p4-projects mailing list