diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index a31b7eeda580..54cd40b0f44a 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -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 */ diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h index 654f4bad0911..9d4c8ea02420 100644 --- a/sys/amd64/include/pmap.h +++ b/sys/amd64/include/pmap.h @@ -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; diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index a31b7eeda580..54cd40b0f44a 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -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 */ diff --git a/sys/i386/include/pmap.h b/sys/i386/include/pmap.h index 654f4bad0911..9d4c8ea02420 100644 --- a/sys/i386/include/pmap.h +++ b/sys/i386/include/pmap.h @@ -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;