Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F103014043
D32875.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D32875.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D32875: amd64: switch to the physmem KPI
Attached
Detach File
Event Timeline
Log In to Comment