amd64/138220: commit references a PR
dfilter service
dfilter at FreeBSD.ORG
Tue Sep 22 17:00:06 UTC 2009
The following reply was made to PR amd64/138220; it has been noted by GNATS.
From: dfilter at FreeBSD.ORG (dfilter service)
To: bug-followup at FreeBSD.org
Cc:
Subject: Re: amd64/138220: commit references a PR
Date: Tue, 22 Sep 2009 16:51:14 +0000 (UTC)
Author: jhb
Date: Tue Sep 22 16:51:00 2009
New Revision: 197410
URL: http://svn.freebsd.org/changeset/base/197410
Log:
- Split the logic to parse an SMAP entry out into a separate function on
amd64 similar to i386. This fixes a bug on amd64 where overlapping
entries would not cause the SMAP parsing to stop.
- Change the SMAP parsing code to do a sorted insertion into physmap[]
instead of an append to support systems with out-of-order SMAP entries.
PR: amd64/138220
Reported by: James R. Van Artsdalen james of jrv org
MFC after: 3 days
Modified:
head/sys/amd64/amd64/machdep.c
head/sys/i386/i386/machdep.c
Modified: head/sys/amd64/amd64/machdep.c
==============================================================================
--- head/sys/amd64/amd64/machdep.c Tue Sep 22 16:28:07 2009 (r197409)
+++ head/sys/amd64/amd64/machdep.c Tue Sep 22 16:51:00 2009 (r197410)
@@ -1192,6 +1192,77 @@ isa_irq_pending(void)
u_int basemem;
+static int
+add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp)
+{
+ int i, insert_idx, physmap_idx;
+
+ physmap_idx = *physmap_idxp;
+
+ if (boothowto & RB_VERBOSE)
+ printf("SMAP type=%02x base=%016lx len=%016lx\n",
+ smap->type, smap->base, smap->length);
+
+ if (smap->type != SMAP_TYPE_MEMORY)
+ return (1);
+
+ if (smap->length == 0)
+ return (0);
+
+ /*
+ * Find insertion point while checking for overlap. Start off by
+ * assuming the new entry will be added to the end.
+ */
+ insert_idx = physmap_idx + 2;
+ for (i = 0; i <= physmap_idx; i += 2) {
+ if (smap->base < physmap[i + 1]) {
+ if (smap->base + smap->length <= physmap[i]) {
+ insert_idx = i;
+ break;
+ }
+ if (boothowto & RB_VERBOSE)
+ printf(
+ "Overlapping memory regions, ignoring second region\n");
+ return (1);
+ }
+ }
+
+ /* See if we can prepend to the next entry. */
+ if (insert_idx <= physmap_idx &&
+ smap->base + smap->length == physmap[insert_idx]) {
+ physmap[insert_idx] = smap->base;
+ return (1);
+ }
+
+ /* See if we can append to the previous entry. */
+ if (insert_idx > 0 && smap->base == physmap[insert_idx - 1]) {
+ physmap[insert_idx - 1] += smap->length;
+ return (1);
+ }
+
+ physmap_idx += 2;
+ *physmap_idxp = physmap_idx;
+ if (physmap_idx == PHYSMAP_SIZE) {
+ printf(
+ "Too many segments in the physical address map, giving up\n");
+ return (0);
+ }
+
+ /*
+ * Move the last 'N' entries down to make room for the new
+ * entry if needed.
+ */
+ for (i = physmap_idx; i > insert_idx; i -= 2) {
+ physmap[i] = physmap[i - 2];
+ physmap[i + 1] = physmap[i - 1];
+ }
+
+ /* Insert the new entry. */
+ physmap[insert_idx] = smap->base;
+ physmap[insert_idx + 1] = smap->base + smap->length;
+ return (1);
+}
+
/*
* Populate the (physmap) array with base/bound pairs describing the
* available physical memory in the system, then test this memory and
@@ -1235,40 +1306,9 @@ getmemsize(caddr_t kmdp, u_int64_t first
smapsize = *((u_int32_t *)smapbase - 1);
smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize);
- for (smap = smapbase; smap < smapend; smap++) {
- if (boothowto & RB_VERBOSE)
- printf("SMAP type=%02x base=%016lx len=%016lx\n",
- smap->type, smap->base, smap->length);
-
- if (smap->type != SMAP_TYPE_MEMORY)
- continue;
-
- if (smap->length == 0)
- continue;
-
- for (i = 0; i <= physmap_idx; i += 2) {
- if (smap->base < physmap[i + 1]) {
- if (boothowto & RB_VERBOSE)
- printf(
- "Overlapping or non-monotonic memory region, ignoring second region\n");
- continue;
- }
- }
-
- if (smap->base == physmap[physmap_idx + 1]) {
- physmap[physmap_idx + 1] += smap->length;
- continue;
- }
-
- physmap_idx += 2;
- if (physmap_idx == PHYSMAP_SIZE) {
- printf(
- "Too many segments in the physical address map, giving up\n");
+ for (smap = smapbase; smap < smapend; smap++)
+ if (!add_smap_entry(smap, physmap, &physmap_idx))
break;
- }
- physmap[physmap_idx] = smap->base;
- physmap[physmap_idx + 1] = smap->base + smap->length;
- }
/*
* Find the 'base memory' segment for SMP
Modified: head/sys/i386/i386/machdep.c
==============================================================================
--- head/sys/i386/i386/machdep.c Tue Sep 22 16:28:07 2009 (r197409)
+++ head/sys/i386/i386/machdep.c Tue Sep 22 16:51:00 2009 (r197410)
@@ -1946,7 +1946,7 @@ sdtossd(sd, ssd)
static int
add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp)
{
- int i, physmap_idx;
+ int i, insert_idx, physmap_idx;
physmap_idx = *physmap_idxp;
@@ -1968,17 +1968,34 @@ add_smap_entry(struct bios_smap *smap, v
}
#endif
+ /*
+ * Find insertion point while checking for overlap. Start off by
+ * assuming the new entry will be added to the end.
+ */
+ insert_idx = physmap_idx + 2;
for (i = 0; i <= physmap_idx; i += 2) {
if (smap->base < physmap[i + 1]) {
+ if (smap->base + smap->length <= physmap[i]) {
+ insert_idx = i;
+ break;
+ }
if (boothowto & RB_VERBOSE)
printf(
- "Overlapping or non-monotonic memory region, ignoring second region\n");
+ "Overlapping memory regions, ignoring second region\n");
return (1);
}
}
- if (smap->base == physmap[physmap_idx + 1]) {
- physmap[physmap_idx + 1] += smap->length;
+ /* See if we can prepend to the next entry. */
+ if (insert_idx <= physmap_idx &&
+ smap->base + smap->length == physmap[insert_idx]) {
+ physmap[insert_idx] = smap->base;
+ return (1);
+ }
+
+ /* See if we can append to the previous entry. */
+ if (insert_idx > 0 && smap->base == physmap[insert_idx - 1]) {
+ physmap[insert_idx - 1] += smap->length;
return (1);
}
@@ -1989,8 +2006,19 @@ add_smap_entry(struct bios_smap *smap, v
"Too many segments in the physical address map, giving up\n");
return (0);
}
- physmap[physmap_idx] = smap->base;
- physmap[physmap_idx + 1] = smap->base + smap->length;
+
+ /*
+ * Move the last 'N' entries down to make room for the new
+ * entry if needed.
+ */
+ for (i = physmap_idx; i > insert_idx; i -= 2) {
+ physmap[i] = physmap[i - 2];
+ physmap[i + 1] = physmap[i - 1];
+ }
+
+ /* Insert the new entry. */
+ physmap[insert_idx] = smap->base;
+ physmap[insert_idx + 1] = smap->base + smap->length;
return (1);
}
_______________________________________________
svn-src-all at freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe at freebsd.org"
More information about the freebsd-amd64
mailing list