Page MenuHomeFreeBSD

D32875.diff
No OneTemporary

D32875.diff

Index: sys/amd64/amd64/machdep.c
===================================================================
--- sys/amd64/amd64/machdep.c
+++ sys/amd64/amd64/machdep.c
@@ -81,6 +81,7 @@
#include <sys/msgbuf.h>
#include <sys/mutex.h>
#include <sys/pcpu.h>
+#include <sys/physmem.h>
#include <sys/ptrace.h>
#include <sys/reboot.h>
#include <sys/reg.h>
@@ -173,7 +174,7 @@
static caddr_t native_parse_preload_data(u_int64_t);
/* Native function to fetch and parse the e820 map */
-static void native_parse_memmap(caddr_t, vm_paddr_t *, int *);
+static void native_parse_memmap(caddr_t);
/* Default init_ops implementation. */
struct init_ops init_ops = {
@@ -197,9 +198,6 @@
int cold = 1;
-long Maxmem = 0;
-long realmem = 0;
-
struct kva_md_info kmi;
struct region_descriptor r_idt;
@@ -633,77 +631,11 @@
u_int basemem;
-static int
-add_physmap_entry(uint64_t base, uint64_t length, vm_paddr_t *physmap,
- int *physmap_idxp)
-{
- int i, insert_idx, physmap_idx;
-
- physmap_idx = *physmap_idxp;
-
- if (length == 0)
- return (1);
-
- /*
- * Find insertion point while checking for overlap. Start off by
- * assuming the new entry will be added to the end.
- *
- * NB: physmap_idx points to the next free slot.
- */
- insert_idx = physmap_idx;
- for (i = 0; i <= physmap_idx; i += 2) {
- if (base < physmap[i + 1]) {
- if (base + 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 && base + length == physmap[insert_idx]) {
- physmap[insert_idx] = base;
- return (1);
- }
-
- /* See if we can append to the previous entry. */
- if (insert_idx > 0 && base == physmap[insert_idx - 1]) {
- physmap[insert_idx - 1] += length;
- return (1);
- }
-
- physmap_idx += 2;
- *physmap_idxp = physmap_idx;
- if (physmap_idx == PHYS_AVAIL_ENTRIES) {
- 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 - 2); i > insert_idx; i -= 2) {
- physmap[i] = physmap[i - 2];
- physmap[i + 1] = physmap[i - 1];
- }
-
- /* Insert the new entry. */
- physmap[insert_idx] = base;
- physmap[insert_idx + 1] = base + length;
- return (1);
-}
-
void
-bios_add_smap_entries(struct bios_smap *smapbase, u_int32_t smapsize,
- vm_paddr_t *physmap, int *physmap_idx)
+bios_add_smap_entries(struct bios_smap *smapbase, u_int32_t smapsize)
{
struct bios_smap *smap, *smapend;
+ int error;
smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize);
@@ -715,20 +647,22 @@
if (smap->type != SMAP_TYPE_MEMORY)
continue;
- if (!add_physmap_entry(smap->base, smap->length, physmap,
- physmap_idx))
+ error = physmem_hardware_region(smap->base, smap->length);
+ if (error == E2BIG) {
+ printf(
+ "Too many holes in the physical address space, giving up\n");
break;
+ }
}
}
static void
-add_efi_map_entries(struct efi_map_header *efihdr, vm_paddr_t *physmap,
- int *physmap_idx)
+add_efi_map_entries(struct efi_map_header *efihdr)
{
struct efi_md *map, *p;
const char *type;
size_t efisz;
- int ndesc, i;
+ int error, i, ndesc;
static const char *types[] = {
"Reserved",
@@ -813,14 +747,18 @@
continue;
}
- if (!add_physmap_entry(p->md_phys, (p->md_pages * PAGE_SIZE),
- physmap, physmap_idx))
+ error = physmem_hardware_region(p->md_phys,
+ (p->md_pages * PAGE_SIZE));
+ if (error == E2BIG) {
+ printf(
+ "Too many holes in the physical address space, giving up\n");
break;
+ }
}
}
static void
-native_parse_memmap(caddr_t kmdp, vm_paddr_t *physmap, int *physmap_idx)
+native_parse_memmap(caddr_t kmdp)
{
struct bios_smap *smap;
struct efi_map_header *efihdr;
@@ -842,21 +780,110 @@
panic("No BIOS smap or EFI map info from loader!");
if (efihdr != NULL) {
- add_efi_map_entries(efihdr, physmap, physmap_idx);
+ add_efi_map_entries(efihdr);
strlcpy(bootmethod, "UEFI", sizeof(bootmethod));
} else {
size = *((u_int32_t *)smap - 1);
- bios_add_smap_entries(smap, size, physmap, physmap_idx);
+ bios_add_smap_entries(smap, size);
strlcpy(bootmethod, "BIOS", sizeof(bootmethod));
}
}
#define PAGES_PER_GB (1024 * 1024 * 1024 / PAGE_SIZE)
+static int
+getmemsize_memtest(vm_paddr_t pa, vm_paddr_t end __unused, void *data)
+{
+ int count, error, *page_counter, tmp;
+ int *ptr = (int *)CADDR1;
+ bool bad;
+
+ /* Skip partial pages. */
+ if ((pa % PAGE_SIZE) != 0 || (end % PAGE_SIZE) != 0)
+ return (0);
+ page_counter = (int *)data;
+ bad = false;
+
+ /*
+ * Print a "." every GB to show we're making
+ * progress.
+ */
+ count = ++(*page_counter);
+ if ((count % PAGES_PER_GB) == 0)
+ printf(".");
+
+ /*
+ * map page into kernel: valid, read/write,non-cacheable
+ */
+ *CMAP1 = pa | PG_V | PG_RW | PG_NC_PWT | PG_NC_PCD;
+ invltlb();
+
+ tmp = *(int *)ptr;
+ /*
+ * Test for alternating 1's and 0's
+ */
+ *(volatile int *)ptr = 0xaaaaaaaa;
+ if (*(volatile int *)ptr != 0xaaaaaaaa) {
+ bad = true;
+ goto out;
+ }
+ /*
+ * Test for alternating 0's and 1's
+ */
+ *(volatile int *)ptr = 0x55555555;
+ if (*(volatile int *)ptr != 0x55555555) {
+ bad = true;
+ goto out;
+ }
+ /*
+ * Test for all 1's
+ */
+ *(volatile int *)ptr = 0xffffffff;
+ if (*(volatile int *)ptr != 0xffffffff) {
+ bad = true;
+ goto out;
+ }
+ /*
+ * Test for all 0's
+ */
+ *(volatile int *)ptr = 0x0;
+ if (*(volatile int *)ptr != 0x0) {
+ bad = true;
+ goto out;
+ }
+
+out:
+ error = 0;
+ if (bad) {
+ error = physmem_exclude_region(pa, PAGE_SIZE,
+ EXFLAG_NOALLOC | EXFLAG_NODUMP);
+ }
+
+ /*
+ * Restore original value.
+ */
+ *(int *)ptr = tmp;
+
+ /*
+ * We'll give up on memtesting if we've maxed out exregions.
+ */
+ if (error == E2BIG) {
+ /*
+ * Still in the middle of a line, suppress the urge to break it.
+ */
+ printf(
+ "too many errors, giving up");
+ } else {
+ error = 0;
+ }
+
+ return (error);
+}
+
/*
- * Populate the (physmap) array with base/bound pairs describing the
- * available physical memory in the system, then test this memory and
- * build the phys_avail array describing the actually-available memory.
+ * Populate physmem regions describing the available physical memory in the
+ * system, optionally test this memory, then build the phys_avail array
+ * describing the actually-available memory.
*
* Total memory size may be set by the kernel environment variable
* hw.physmem or the compile-time define MAXMEM.
@@ -866,10 +893,8 @@
static void
getmemsize(caddr_t kmdp, u_int64_t first)
{
- int i, physmap_idx, pa_indx, da_indx;
- vm_paddr_t pa, physmap[PHYS_AVAIL_ENTRIES];
- u_long physmem_start, physmem_tunable, memtest;
- pt_entry_t *pte;
+ size_t pa_indx;
+ u_long physmem_maxpage, physmem_start, physmem_tunable, memtest;
quad_t dcons_addr, dcons_size;
int page_counter;
@@ -879,28 +904,7 @@
*/
vm_phys_early_add_seg((vm_paddr_t)kernphys, trunc_page(first));
- bzero(physmap, sizeof(physmap));
- physmap_idx = 0;
-
- init_ops.parse_memmap(kmdp, physmap, &physmap_idx);
- physmap_idx -= 2;
-
- /*
- * Find the 'base memory' segment for SMP
- */
- basemem = 0;
- for (i = 0; i <= physmap_idx; i += 2) {
- if (physmap[i] <= 0xA0000) {
- basemem = physmap[i + 1] / 1024;
- break;
- }
- }
- if (basemem == 0 || basemem > 640) {
- if (bootverbose)
- printf(
- "Memory map doesn't contain a basemem segment, faking it");
- basemem = 640;
- }
+ init_ops.parse_memmap(kmdp);
/*
* Maxmem isn't the "maximum memory", it's one larger than the
@@ -908,15 +912,20 @@
* called something like "Maxphyspage". We may adjust this
* based on ``hw.physmem'' and the results of the memory test.
*/
- Maxmem = atop(physmap[physmap_idx + 1]);
-
+ physmem_maxpage = physmem_max_page();
#ifdef MAXMEM
Maxmem = MAXMEM / 4;
#endif
-
- if (TUNABLE_ULONG_FETCH("hw.physmem", &physmem_tunable))
+ if (TUNABLE_LONG_FETCH("hw.physmem", &physmem_tunable))
Maxmem = atop(physmem_tunable);
+ /*
+ * Don't allow MAXMEM or hw.physmem to extend the amount of memory
+ * in the system.
+ */
+ if (Maxmem == 0 || Maxmem > physmem_maxpage)
+ Maxmem = physmem_maxpage;
+
/*
* The boot memory test is disabled by default, as it takes a
* significant amount of time on large-memory systems, and is
@@ -929,17 +938,6 @@
memtest = 0;
TUNABLE_ULONG_FETCH("hw.memtest.tests", &memtest);
- /*
- * Don't allow MAXMEM or hw.physmem to extend the amount of memory
- * in the system.
- */
- if (Maxmem > atop(physmap[physmap_idx + 1]))
- Maxmem = atop(physmap[physmap_idx + 1]);
-
- if (atop(physmap[physmap_idx + 1]) != Maxmem &&
- (boothowto & RB_VERBOSE))
- printf("Physical memory use set to %ldK\n", Maxmem * 4);
-
/* call pmap initialization to make new kernel address space */
pmap_bootstrap(&first);
@@ -952,161 +950,49 @@
*/
physmem_start = (vm_guest > VM_GUEST_NO ? 1 : 16) << PAGE_SHIFT;
TUNABLE_ULONG_FETCH("hw.physmem.start", &physmem_start);
- if (physmap[0] < physmem_start) {
- if (physmem_start < PAGE_SIZE)
- physmap[0] = PAGE_SIZE;
- else if (physmem_start >= physmap[1])
- physmap[0] = round_page(physmap[1] - PAGE_SIZE);
- else
- physmap[0] = round_page(physmem_start);
- }
- pa_indx = 0;
- da_indx = 1;
- phys_avail[pa_indx++] = physmap[0];
- phys_avail[pa_indx] = physmap[0];
- dump_avail[da_indx] = physmap[0];
- pte = CMAP1;
+
+ physmem_exclude_region(0, physmem_start,
+ EXFLAG_NOALLOC | EXFLAG_NODUMP);
/*
- * Get dcons buffer address
+ * Block dcons buffer.
*/
- if (getenv_quad("dcons.addr", &dcons_addr) == 0 ||
- getenv_quad("dcons.size", &dcons_size) == 0)
- dcons_addr = 0;
+ if (getenv_quad("dcons.addr", &dcons_addr) != 0 &&
+ getenv_quad("dcons.size", &dcons_size) != 0)
+ physmem_exclude_region(dcons_addr, dcons_size, EXFLAG_NOALLOC);
/*
- * physmap is in bytes, so when converting to page boundaries,
- * round up the start address and round down the end address.
+ * Block kernel memory.
*/
- page_counter = 0;
- if (memtest != 0)
- printf("Testing system memory");
- for (i = 0; i <= physmap_idx; i += 2) {
- vm_paddr_t end;
-
- end = ptoa((vm_paddr_t)Maxmem);
- if (physmap[i + 1] < end)
- end = trunc_page(physmap[i + 1]);
- for (pa = round_page(physmap[i]); pa < end; pa += PAGE_SIZE) {
- int tmp, page_bad, full;
- int *ptr = (int *)CADDR1;
-
- full = FALSE;
- /*
- * block out kernel memory as not available.
- */
- if (pa >= (vm_paddr_t)kernphys && pa < first)
- goto do_dump_avail;
-
- /*
- * block out dcons buffer
- */
- if (dcons_addr > 0
- && pa >= trunc_page(dcons_addr)
- && pa < dcons_addr + dcons_size)
- goto do_dump_avail;
+ physmem_exclude_region(kernphys, first - kernphys, EXFLAG_NOALLOC);
- page_bad = FALSE;
- if (memtest == 0)
- goto skip_memtest;
+ if (memtest != 0) {
+ page_counter = 0;
+ printf("Testing system memory");
+ physmem_foreach_page(getmemsize_memtest, &page_counter, 0);
- /*
- * Print a "." every GB to show we're making
- * progress.
- */
- page_counter++;
- if ((page_counter % PAGES_PER_GB) == 0)
- printf(".");
+ *CMAP1 = 0;
+ invltlb();
+ printf("\n");
+ }
- /*
- * map page into kernel: valid, read/write,non-cacheable
- */
- *pte = pa | PG_V | PG_RW | PG_NC_PWT | PG_NC_PCD;
- invltlb();
+ physmem_init_kernel_globals(&pa_indx, NULL);
+ pa_indx--;
- tmp = *(int *)ptr;
- /*
- * Test for alternating 1's and 0's
- */
- *(volatile int *)ptr = 0xaaaaaaaa;
- if (*(volatile int *)ptr != 0xaaaaaaaa)
- page_bad = TRUE;
- /*
- * Test for alternating 0's and 1's
- */
- *(volatile int *)ptr = 0x55555555;
- if (*(volatile int *)ptr != 0x55555555)
- page_bad = TRUE;
- /*
- * Test for all 1's
- */
- *(volatile int *)ptr = 0xffffffff;
- if (*(volatile int *)ptr != 0xffffffff)
- page_bad = TRUE;
- /*
- * Test for all 0's
- */
- *(volatile int *)ptr = 0x0;
- if (*(volatile int *)ptr != 0x0)
- page_bad = TRUE;
- /*
- * Restore original value.
- */
- *(int *)ptr = tmp;
+ /*
+ * Find the 'base memory' segment for SMP
+ */
+ basemem = 0;
+ /* phys_avail is sorted. */
+ if (phys_avail[0] <= 0xA0000)
+ basemem = phys_avail[1] / 1024;
-skip_memtest:
- /*
- * Adjust array of valid/good pages.
- */
- if (page_bad == TRUE)
- continue;
- /*
- * 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 we're also doing a speculative memory
- * test and we at or past the end, bump up Maxmem
- * so that we keep going. The first bad page
- * will terminate the loop.
- */
- if (phys_avail[pa_indx] == pa) {
- phys_avail[pa_indx] += PAGE_SIZE;
- } else {
- pa_indx++;
- if (pa_indx == PHYS_AVAIL_ENTRIES) {
- printf(
- "Too many holes in the physical address space, giving up\n");
- pa_indx--;
- full = TRUE;
- goto do_dump_avail;
- }
- phys_avail[pa_indx++] = pa; /* start */
- phys_avail[pa_indx] = pa + PAGE_SIZE; /* end */
- }
- physmem++;
-do_dump_avail:
- if (dump_avail[da_indx] == pa) {
- dump_avail[da_indx] += PAGE_SIZE;
- } else {
- da_indx++;
- if (da_indx == PHYS_AVAIL_ENTRIES) {
- da_indx--;
- goto do_next;
- }
- dump_avail[da_indx++] = pa; /* start */
- dump_avail[da_indx] = pa + PAGE_SIZE; /* end */
- }
-do_next:
- if (full)
- break;
- }
+ if (basemem == 0 || basemem > 640) {
+ if (bootverbose)
+ printf(
+ "Memory map doesn't contain a basemem segment, faking it");
+ basemem = 640;
}
- *pte = 0;
- invltlb();
- if (memtest != 0)
- printf("\n");
/*
* XXX
@@ -1121,8 +1007,13 @@
phys_avail[pa_indx--] = 0;
}
+ /* Collect the final Maxmem. */
Maxmem = atop(phys_avail[pa_indx]);
+ if (bootverbose)
+ printf("Physical memory use set to %ldK\n", Maxmem * 4);
+
+
/* Trim off space for the message buffer. */
phys_avail[pa_indx] -= round_page(msgbufsize);
Index: sys/amd64/include/pc/bios.h
===================================================================
--- sys/amd64/include/pc/bios.h
+++ sys/amd64/include/pc/bios.h
@@ -87,8 +87,7 @@
int bios_oem_strings(struct bios_oem *oem, u_char *buffer, size_t maxlen);
uint32_t bios_sigsearch(uint32_t start, u_char *sig, int siglen, int paralen,
int sigofs);
-void bios_add_smap_entries(struct bios_smap *smapbase, u_int32_t smapsize,
- vm_paddr_t *physmap, int *physmap_idx);
+void bios_add_smap_entries(struct bios_smap *smapbase, u_int32_t smapsize);
#endif
#endif /* _MACHINE_PC_BIOS_H_ */
Index: sys/conf/files.amd64
===================================================================
--- sys/conf/files.amd64
+++ sys/conf/files.amd64
@@ -345,6 +345,7 @@
isa/vga_isa.c optional vga
kern/imgact_aout.c optional compat_aout
kern/link_elf_obj.c standard
+kern/subr_physmem.c standard
#
# IA32 binary support
#
Index: sys/x86/include/init.h
===================================================================
--- sys/x86/include/init.h
+++ sys/x86/include/init.h
@@ -40,7 +40,7 @@
caddr_t (*parse_preload_data)(u_int64_t);
void (*early_clock_source_init)(void);
void (*early_delay)(int);
- void (*parse_memmap)(caddr_t, vm_paddr_t *, int *);
+ void (*parse_memmap)(caddr_t);
};
extern struct init_ops init_ops;
Index: sys/x86/xen/pv.c
===================================================================
--- sys/x86/xen/pv.c
+++ sys/x86/xen/pv.c
@@ -93,7 +93,7 @@
/*--------------------------- Forward Declarations ---------------------------*/
static caddr_t xen_pvh_parse_preload_data(uint64_t);
-static void xen_pvh_parse_memmap(caddr_t, vm_paddr_t *, int *);
+static void xen_pvh_parse_memmap(caddr_t);
/*---------------------------- Extern Declarations ---------------------------*/
/*
@@ -391,7 +391,7 @@
}
static void
-xen_pvh_parse_memmap(caddr_t kmdp, vm_paddr_t *physmap, int *physmap_idx)
+xen_pvh_parse_memmap(caddr_t kmdp)
{
struct xen_memory_map memmap;
u_int32_t size;
@@ -409,5 +409,5 @@
size = memmap.nr_entries * sizeof(xen_smap[0]);
- bios_add_smap_entries(xen_smap, size, physmap, physmap_idx);
+ bios_add_smap_entries(xen_smap, size);
}

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 20, 8:22 PM (20 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14746445
Default Alt Text
D32875.diff (16 KB)

Event Timeline