Rewrote memory sizing code to generally deal with holes in extended memory.

This code change should allow certain Compaq machines with a 128K hole
at 16MB to work.
This commit is contained in:
David Greenman 1995-07-19 06:37:12 +00:00
parent cef6b9bc3e
commit e9857eee2b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=9578
4 changed files with 202 additions and 100 deletions

View file

@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
* $Id: machdep.c,v 1.131 1995/07/13 08:47:24 davidg Exp $
* $Id: machdep.c,v 1.132 1995/07/16 10:33:38 phk Exp $
*/
#include "npx.h"
@ -180,7 +180,10 @@ long dumplo;
extern int bootdev;
int biosmem;
vm_offset_t phys_avail[6];
vm_offset_t phys_avail[10];
/* must be 2 less so 0 0 can signal end of chunks */
#define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(vm_offset_t)) - 2)
int cpu_class;
@ -202,7 +205,7 @@ cpu_startup()
register caddr_t v;
vm_offset_t maxaddr;
vm_size_t size = 0;
int firstaddr;
int firstaddr, indx;
vm_offset_t minaddr;
if (boothowto & RB_VERBOSE)
@ -225,9 +228,26 @@ cpu_startup()
printf(version);
startrtclock();
identifycpu();
printf("real memory = %d (%d pages)\n", ptoa(physmem), physmem);
if (badpages)
printf("bad memory = %d (%d pages)\n", ptoa(badpages), badpages);
/*
* Display any holes after the first chunk of extended memory.
*/
if (badpages != 0) {
int indx = 1;
/*
* XXX skip reporting ISA hole & unmanaged kernel memory
*/
if (phys_avail[0] == PAGE_SIZE)
indx += 2;
printf("Physical memory hole(s):\n");
for (; phys_avail[indx + 1] != 0; indx += 2) {
int size = phys_avail[indx + 1] - phys_avail[indx];
printf("0x%08x - 0x%08x, %d bytes (%d pages)\n", phys_avail[indx],
phys_avail[indx + 1] - 1, size, size / PAGE_SIZE);
}
}
/*
* Quickly wire in netisrs.
@ -1250,7 +1270,7 @@ init386(first)
/* table descriptors - used to load tables by microp */
struct region_descriptor r_gdt, r_idt;
int pagesinbase, pagesinext;
int target_page;
int target_page, pa_indx;
proc0.p_addr = proc0paddr;
@ -1404,36 +1424,43 @@ init386(first)
/*
* Maxmem isn't the "maximum memory", it's one larger than the
* highest page of of the physical address space. It should be
* called something like "Maxphyspage".
* highest page of of the physical address space. It
*/
Maxmem = pagesinext + 0x100000/PAGE_SIZE;
#ifdef MAXMEM
Maxmem = MAXMEM/4;
#endif
/*
* Calculate number of physical pages, but account for Maxmem
* adjustment above.
*/
physmem = pagesinbase + Maxmem - 0x100000/PAGE_SIZE;
/* call pmap initialization to make new kernel address space */
pmap_bootstrap (first, 0);
/*
* Do a quick, non-destructive check over extended memory to verify
* what the BIOS tells us agrees with reality. Adjust down Maxmem
* if we find that the page can't be correctly written to/read from.
* Size up each available chunk of physical memory.
*/
for (target_page = Maxmem - 1; target_page >= atop(first); target_page--) {
int tmp;
/*
* We currently don't bother testing base memory.
* XXX ...but we probably should.
*/
pa_indx = 0;
badpages = 0;
if (pagesinbase > 1) {
phys_avail[pa_indx++] = PAGE_SIZE; /* skip first page of memory */
phys_avail[pa_indx] = ptoa(pagesinbase);/* memory up to the ISA hole */
physmem = pagesinbase - 1;
} else {
/* point at first chunk end */
pa_indx++;
}
for (target_page = first; target_page < ptoa(Maxmem); target_page += PAGE_SIZE) {
int tmp, page_bad = FALSE;
/*
* map page into kernel: valid, read/write, non-cacheable
*/
*(int *)CMAP1 = PG_V | PG_KW | PG_N | ptoa(target_page);
*(int *)CMAP1 = PG_V | PG_KW | PG_N | target_page;
pmap_update();
tmp = *(int *)CADDR1;
@ -1442,27 +1469,21 @@ init386(first)
*/
*(int *)CADDR1 = 0xaaaaaaaa;
if (*(int *)CADDR1 != 0xaaaaaaaa) {
Maxmem = target_page;
badpages++;
continue;
page_bad = TRUE;
}
/*
* Test for alternating 0's and 1's
*/
*(int *)CADDR1 = 0x55555555;
if (*(int *)CADDR1 != 0x55555555) {
Maxmem = target_page;
badpages++;
continue;
page_bad = TRUE;
}
/*
* Test for all 1's
*/
*(int *)CADDR1 = 0xffffffff;
if (*(int *)CADDR1 != 0xffffffff) {
Maxmem = target_page;
badpages++;
continue;
page_bad = TRUE;
}
/*
* Test for all 0's
@ -1472,35 +1493,65 @@ init386(first)
/*
* test of page failed
*/
Maxmem = target_page;
badpages++;
continue;
page_bad = TRUE;
}
/*
* Restore original value.
*/
*(int *)CADDR1 = tmp;
/*
* Adjust array of valid/good pages.
*/
if (page_bad == FALSE) {
/*
* If this good page is a continuation of the
* previous set of good pages, then just increase
* the end pointer. Otherwise start a new chunk.
* Note that "end" points one higher than end,
* making the range >= start and < end.
*/
if (phys_avail[pa_indx] == target_page) {
phys_avail[pa_indx] += PAGE_SIZE;
} else {
pa_indx++;
if (pa_indx == PHYS_AVAIL_ARRAY_END) {
printf("Too many holes in the physical address space, giving up\n");
pa_indx--;
break;
}
phys_avail[pa_indx++] = target_page; /* start */
phys_avail[pa_indx] = target_page + PAGE_SIZE; /* end */
}
physmem++;
} else {
badpages++;
page_bad = FALSE;
}
}
if (badpages != 0)
printf("WARNING: BIOS extended memory size and reality don't agree.\n");
*(int *)CMAP1 = 0;
pmap_update();
avail_end = (Maxmem << PAGE_SHIFT)
- i386_round_page(sizeof(struct msgbuf));
/*
* Initialize pointers to the two chunks of memory; for use
* later in vm_page_startup.
* XXX
* The last chunk must contain at leat one page plus the message
* buffer to avoid complicating other code (message buffer address
* calculation, etc.).
*/
/* avail_start is initialized in pmap_bootstrap */
x = 0;
if (pagesinbase > 1) {
phys_avail[x++] = NBPG; /* skip first page of memory */
phys_avail[x++] = pagesinbase * NBPG; /* memory up to the ISA hole */
while (phys_avail[pa_indx - 1] + PAGE_SIZE +
round_page(sizeof(struct msgbuf)) >= phys_avail[pa_indx]) {
physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]);
phys_avail[pa_indx--] = 0;
phys_avail[pa_indx--] = 0;
}
phys_avail[x++] = avail_start; /* memory up to the end */
phys_avail[x++] = avail_end;
phys_avail[x++] = 0; /* no more chunks */
phys_avail[x++] = 0;
Maxmem = atop(phys_avail[pa_indx]);
/* Trim off space for the message buffer. */
phys_avail[pa_indx] -= round_page(sizeof(struct msgbuf));
avail_end = phys_avail[pa_indx];
/* now running on new page tables, configured,and u/iom is accessible */

View file

@ -42,7 +42,7 @@
*
* from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90
* from: @(#)pmap.h 7.4 (Berkeley) 5/12/91
* $Id: pmap.h,v 1.26 1995/05/30 08:00:48 rgrimes Exp $
* $Id: pmap.h,v 1.27 1995/07/13 08:47:33 davidg Exp $
*/
#ifndef _MACHINE_PMAP_H_
@ -193,7 +193,7 @@ extern caddr_t CADDR1;
extern pt_entry_t *CMAP1;
extern vm_offset_t avail_end;
extern vm_offset_t avail_start;
extern vm_offset_t phys_avail[6];
extern vm_offset_t phys_avail[];
extern pv_entry_t pv_table; /* array of entries, one per page */
extern vm_offset_t virtual_avail;
extern vm_offset_t virtual_end;

View file

@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
* $Id: machdep.c,v 1.131 1995/07/13 08:47:24 davidg Exp $
* $Id: machdep.c,v 1.132 1995/07/16 10:33:38 phk Exp $
*/
#include "npx.h"
@ -180,7 +180,10 @@ long dumplo;
extern int bootdev;
int biosmem;
vm_offset_t phys_avail[6];
vm_offset_t phys_avail[10];
/* must be 2 less so 0 0 can signal end of chunks */
#define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(vm_offset_t)) - 2)
int cpu_class;
@ -202,7 +205,7 @@ cpu_startup()
register caddr_t v;
vm_offset_t maxaddr;
vm_size_t size = 0;
int firstaddr;
int firstaddr, indx;
vm_offset_t minaddr;
if (boothowto & RB_VERBOSE)
@ -225,9 +228,26 @@ cpu_startup()
printf(version);
startrtclock();
identifycpu();
printf("real memory = %d (%d pages)\n", ptoa(physmem), physmem);
if (badpages)
printf("bad memory = %d (%d pages)\n", ptoa(badpages), badpages);
/*
* Display any holes after the first chunk of extended memory.
*/
if (badpages != 0) {
int indx = 1;
/*
* XXX skip reporting ISA hole & unmanaged kernel memory
*/
if (phys_avail[0] == PAGE_SIZE)
indx += 2;
printf("Physical memory hole(s):\n");
for (; phys_avail[indx + 1] != 0; indx += 2) {
int size = phys_avail[indx + 1] - phys_avail[indx];
printf("0x%08x - 0x%08x, %d bytes (%d pages)\n", phys_avail[indx],
phys_avail[indx + 1] - 1, size, size / PAGE_SIZE);
}
}
/*
* Quickly wire in netisrs.
@ -1250,7 +1270,7 @@ init386(first)
/* table descriptors - used to load tables by microp */
struct region_descriptor r_gdt, r_idt;
int pagesinbase, pagesinext;
int target_page;
int target_page, pa_indx;
proc0.p_addr = proc0paddr;
@ -1404,36 +1424,43 @@ init386(first)
/*
* Maxmem isn't the "maximum memory", it's one larger than the
* highest page of of the physical address space. It should be
* called something like "Maxphyspage".
* highest page of of the physical address space. It
*/
Maxmem = pagesinext + 0x100000/PAGE_SIZE;
#ifdef MAXMEM
Maxmem = MAXMEM/4;
#endif
/*
* Calculate number of physical pages, but account for Maxmem
* adjustment above.
*/
physmem = pagesinbase + Maxmem - 0x100000/PAGE_SIZE;
/* call pmap initialization to make new kernel address space */
pmap_bootstrap (first, 0);
/*
* Do a quick, non-destructive check over extended memory to verify
* what the BIOS tells us agrees with reality. Adjust down Maxmem
* if we find that the page can't be correctly written to/read from.
* Size up each available chunk of physical memory.
*/
for (target_page = Maxmem - 1; target_page >= atop(first); target_page--) {
int tmp;
/*
* We currently don't bother testing base memory.
* XXX ...but we probably should.
*/
pa_indx = 0;
badpages = 0;
if (pagesinbase > 1) {
phys_avail[pa_indx++] = PAGE_SIZE; /* skip first page of memory */
phys_avail[pa_indx] = ptoa(pagesinbase);/* memory up to the ISA hole */
physmem = pagesinbase - 1;
} else {
/* point at first chunk end */
pa_indx++;
}
for (target_page = first; target_page < ptoa(Maxmem); target_page += PAGE_SIZE) {
int tmp, page_bad = FALSE;
/*
* map page into kernel: valid, read/write, non-cacheable
*/
*(int *)CMAP1 = PG_V | PG_KW | PG_N | ptoa(target_page);
*(int *)CMAP1 = PG_V | PG_KW | PG_N | target_page;
pmap_update();
tmp = *(int *)CADDR1;
@ -1442,27 +1469,21 @@ init386(first)
*/
*(int *)CADDR1 = 0xaaaaaaaa;
if (*(int *)CADDR1 != 0xaaaaaaaa) {
Maxmem = target_page;
badpages++;
continue;
page_bad = TRUE;
}
/*
* Test for alternating 0's and 1's
*/
*(int *)CADDR1 = 0x55555555;
if (*(int *)CADDR1 != 0x55555555) {
Maxmem = target_page;
badpages++;
continue;
page_bad = TRUE;
}
/*
* Test for all 1's
*/
*(int *)CADDR1 = 0xffffffff;
if (*(int *)CADDR1 != 0xffffffff) {
Maxmem = target_page;
badpages++;
continue;
page_bad = TRUE;
}
/*
* Test for all 0's
@ -1472,35 +1493,65 @@ init386(first)
/*
* test of page failed
*/
Maxmem = target_page;
badpages++;
continue;
page_bad = TRUE;
}
/*
* Restore original value.
*/
*(int *)CADDR1 = tmp;
/*
* Adjust array of valid/good pages.
*/
if (page_bad == FALSE) {
/*
* If this good page is a continuation of the
* previous set of good pages, then just increase
* the end pointer. Otherwise start a new chunk.
* Note that "end" points one higher than end,
* making the range >= start and < end.
*/
if (phys_avail[pa_indx] == target_page) {
phys_avail[pa_indx] += PAGE_SIZE;
} else {
pa_indx++;
if (pa_indx == PHYS_AVAIL_ARRAY_END) {
printf("Too many holes in the physical address space, giving up\n");
pa_indx--;
break;
}
phys_avail[pa_indx++] = target_page; /* start */
phys_avail[pa_indx] = target_page + PAGE_SIZE; /* end */
}
physmem++;
} else {
badpages++;
page_bad = FALSE;
}
}
if (badpages != 0)
printf("WARNING: BIOS extended memory size and reality don't agree.\n");
*(int *)CMAP1 = 0;
pmap_update();
avail_end = (Maxmem << PAGE_SHIFT)
- i386_round_page(sizeof(struct msgbuf));
/*
* Initialize pointers to the two chunks of memory; for use
* later in vm_page_startup.
* XXX
* The last chunk must contain at leat one page plus the message
* buffer to avoid complicating other code (message buffer address
* calculation, etc.).
*/
/* avail_start is initialized in pmap_bootstrap */
x = 0;
if (pagesinbase > 1) {
phys_avail[x++] = NBPG; /* skip first page of memory */
phys_avail[x++] = pagesinbase * NBPG; /* memory up to the ISA hole */
while (phys_avail[pa_indx - 1] + PAGE_SIZE +
round_page(sizeof(struct msgbuf)) >= phys_avail[pa_indx]) {
physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]);
phys_avail[pa_indx--] = 0;
phys_avail[pa_indx--] = 0;
}
phys_avail[x++] = avail_start; /* memory up to the end */
phys_avail[x++] = avail_end;
phys_avail[x++] = 0; /* no more chunks */
phys_avail[x++] = 0;
Maxmem = atop(phys_avail[pa_indx]);
/* Trim off space for the message buffer. */
phys_avail[pa_indx] -= round_page(sizeof(struct msgbuf));
avail_end = phys_avail[pa_indx];
/* now running on new page tables, configured,and u/iom is accessible */

View file

@ -42,7 +42,7 @@
*
* from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90
* from: @(#)pmap.h 7.4 (Berkeley) 5/12/91
* $Id: pmap.h,v 1.26 1995/05/30 08:00:48 rgrimes Exp $
* $Id: pmap.h,v 1.27 1995/07/13 08:47:33 davidg Exp $
*/
#ifndef _MACHINE_PMAP_H_
@ -193,7 +193,7 @@ extern caddr_t CADDR1;
extern pt_entry_t *CMAP1;
extern vm_offset_t avail_end;
extern vm_offset_t avail_start;
extern vm_offset_t phys_avail[6];
extern vm_offset_t phys_avail[];
extern pv_entry_t pv_table; /* array of entries, one per page */
extern vm_offset_t virtual_avail;
extern vm_offset_t virtual_end;