svn commit: r197484 - in stable/8/sys: . amd64/amd64
amd64/include/xen cddl/contrib/opensolaris contrib/dev/acpica
contrib/pf dev/xen/xenpci i386/i386
John Baldwin
jhb at FreeBSD.org
Fri Sep 25 15:08:26 UTC 2009
Author: jhb
Date: Fri Sep 25 15:08:26 2009
New Revision: 197484
URL: http://svn.freebsd.org/changeset/base/197484
Log:
MFC 197410:
- 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.
Approved by: re (kib)
Modified:
stable/8/sys/ (props changed)
stable/8/sys/amd64/amd64/machdep.c
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
stable/8/sys/dev/xen/xenpci/ (props changed)
stable/8/sys/i386/i386/machdep.c
Modified: stable/8/sys/amd64/amd64/machdep.c
==============================================================================
--- stable/8/sys/amd64/amd64/machdep.c Fri Sep 25 14:58:30 2009 (r197483)
+++ stable/8/sys/amd64/amd64/machdep.c Fri Sep 25 15:08:26 2009 (r197484)
@@ -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: stable/8/sys/i386/i386/machdep.c
==============================================================================
--- stable/8/sys/i386/i386/machdep.c Fri Sep 25 14:58:30 2009 (r197483)
+++ stable/8/sys/i386/i386/machdep.c Fri Sep 25 15:08:26 2009 (r197484)
@@ -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);
}
More information about the svn-src-stable-8
mailing list