> 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