> Date: Mon, 9 Sep 2019 13:29:32 +0200
> From: Alexander Bluhm <[email protected]>
> 
> On Sat, Sep 07, 2019 at 04:07:22PM +0200, Mark Kettenis wrote:
> > The diff below should fix one of the issues uncovered by the
> > acpipci(4) changes that I just backed out.
> >
> > On some systems, ACPI specifies overlapping regions of address space
> > that gets forwarded to the PCI bus.  Since we use extent_free(9) to
> > make those regions of address space available, that code needs to be
> > able to handle overlaps.
> >
> > Since the acpipci(4) has been backed out, I attach the diff (with
> > debug print code) below.  Alexander, it would be great if you can test
> > this on that SuperMicro box.
> 
> No strange errors in dmesg anymore.  Regress passes.
> Dmesg and pcidump without and with this diff attached.

Thanks.  Good!  That means I'd like to see some ok's now ;).



Index: sys/kern/subr_extent.c
===================================================================
RCS file: /cvs/src/sys/kern/subr_extent.c,v
retrieving revision 1.61
diff -u -p -r1.61 subr_extent.c
--- sys/kern/subr_extent.c      28 Aug 2019 22:22:43 -0000      1.61
+++ sys/kern/subr_extent.c      7 Sep 2019 13:55:01 -0000
@@ -962,6 +962,7 @@ int
 extent_free(struct extent *ex, u_long start, u_long size, int flags)
 {
        struct extent_region *rp, *nrp = NULL;
+       struct extent_region *tmp;
        u_long end = start + (size - 1);
        int exflags;
        int error = 0;
@@ -1019,8 +1020,12 @@ extent_free(struct extent *ex, u_long st
         *
         * Cases 2, 3, and 4 require that the EXF_NOCOALESCE flag
         * is not set.
+        *
+        * If the EX_CONFLICTOK flag is set, partially overlapping
+        * regions are allowed.  This is handled in cases 1a, 2a and
+        * 3a below.
         */
-       LIST_FOREACH(rp, &ex->ex_regions, er_link) {
+       LIST_FOREACH_SAFE(rp, &ex->ex_regions, er_link, tmp) {
                /*
                 * Save ourselves some comparisons; does the current
                 * region end before chunk to be freed begins?  If so,
@@ -1080,12 +1085,28 @@ extent_free(struct extent *ex, u_long st
                        nrp = NULL;
                        goto done;
                }
+
+               if ((flags & EX_CONFLICTOK) == 0)
+                       continue;
+
+               /* Case 1a. */
+               if ((start <= rp->er_start && end >= rp->er_end)) {
+                       LIST_REMOVE(rp, er_link);
+                       extent_free_region_descriptor(ex, rp);
+                       continue;
+               }
+
+               /* Case 2a. */
+               if ((start <= rp->er_start) && (end >= rp->er_start))
+                       rp->er_start = (end + 1);
+
+               /* Case 3a. */
+               if ((start <= rp->er_end) && (end >= rp->er_end))
+                       rp->er_end = (start - 1);
        }
 
-       if (flags & EX_CONFLICTOK) {
-               error = EINVAL;
+       if (flags & EX_CONFLICTOK)
                goto done;
-       }
 
        /* Region not found, or request otherwise invalid. */
 #if defined(DIAGNOSTIC) || defined(DDB)
Index: regress/sys/kern/extent/extest.awk
===================================================================
RCS file: /cvs/src/regress/sys/kern/extent/extest.awk,v
retrieving revision 1.2
diff -u -p -r1.2 extest.awk
--- regress/sys/kern/extent/extest.awk  10 Apr 2009 20:57:04 -0000      1.2
+++ regress/sys/kern/extent/extest.awk  7 Sep 2019 13:55:01 -0000
@@ -67,7 +67,12 @@ $1 == "alloc_subregion" {
 }
 
 $1 == "free" {
-       printf("error = extent_free(ex, %s, %s, 0);\n", $2, $3)
+       if ($4 == "") {
+               flags = "0";
+       } else {
+               flags = $4;
+       }
+       printf("error = extent_free(ex, %s, %s, %s);\n", $2, $3, flags)
        printf("if (error)\n\tprintf(\"error: %%s\\n\", strerror(error));\n")
 }
 
Index: regress/sys/kern/extent/extest.exp
===================================================================
RCS file: /cvs/src/regress/sys/kern/extent/extest.exp,v
retrieving revision 1.4
diff -u -p -r1.4 extest.exp
--- regress/sys/kern/extent/extest.exp  13 Oct 2009 20:53:40 -0000      1.4
+++ regress/sys/kern/extent/extest.exp  7 Sep 2019 13:55:01 -0000
@@ -92,3 +92,13 @@ extent `test16' (0x0 - 0xffffffff), flag
 output for test17
 extent `test17' (0x0 - 0xffffffffffffffff), flags = 0x0
      0x0 - 0xffffffffffffffff
+output for test18
+extent `test18' (0x0 - 0xffff), flags = 0x0
+     0x0 - 0xcff
+     0xf000 - 0xffff
+output for test19
+extent `test19' (0x0 - 0xffff), flags = 0x0
+     0x0 - 0xcff
+output for test20
+extent `test20' (0x0 - 0xffff), flags = 0x0
+     0xf000 - 0xffff
Index: regress/sys/kern/extent/tests
===================================================================
RCS file: /cvs/src/regress/sys/kern/extent/tests,v
retrieving revision 1.5
diff -u -p -r1.5 tests
--- regress/sys/kern/extent/tests       13 Oct 2009 20:53:40 -0000      1.5
+++ regress/sys/kern/extent/tests       7 Sep 2019 13:55:01 -0000
@@ -136,3 +136,19 @@ print
 extent test17 0x00000000 -1L EX_FILLED
 alloc_region 0 0x4000 EX_CONFLICTOK
 print
+
+# Check freeing overkapping regions from a filled extent
+extent test18 0x0000 0xffff EX_FILLED
+free 0x164e 0x2
+free 0x0d00 0xe300 EX_CONFLICTOK
+print
+
+extent test19 0x0000 0xffff EX_FILLED
+free 0x164e 0x2
+free 0x0d00 0xf300 EX_CONFLICTOK
+print
+
+extent test20 0x0000 0xffff EX_FILLED
+free 0x164e 0x2
+free 0x0000 0xf000 EX_CONFLICTOK
+print

Reply via email to