MFC: Use the SMAP data from the loader if it is provided.
This commit is contained in:
parent
303513927d
commit
664b0cf23f
@ -114,6 +114,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <machine/cputypes.h>
|
#include <machine/cputypes.h>
|
||||||
#include <machine/intr_machdep.h>
|
#include <machine/intr_machdep.h>
|
||||||
#include <machine/md_var.h>
|
#include <machine/md_var.h>
|
||||||
|
#include <machine/metadata.h>
|
||||||
#include <machine/pc/bios.h>
|
#include <machine/pc/bios.h>
|
||||||
#include <machine/pcb.h>
|
#include <machine/pcb.h>
|
||||||
#include <machine/pcb_ext.h>
|
#include <machine/pcb_ext.h>
|
||||||
@ -1640,6 +1641,57 @@ sdtossd(sd, ssd)
|
|||||||
ssd->ssd_gran = sd->sd_gran;
|
ssd->ssd_gran = sd->sd_gran;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp)
|
||||||
|
{
|
||||||
|
int i, physmap_idx;
|
||||||
|
|
||||||
|
physmap_idx = *physmap_idxp;
|
||||||
|
|
||||||
|
if (boothowto & RB_VERBOSE)
|
||||||
|
printf("SMAP type=%02x base=%016llx len=%016llx\n",
|
||||||
|
smap->type, smap->base, smap->length);
|
||||||
|
|
||||||
|
if (smap->type != SMAP_TYPE_MEMORY)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
if (smap->length == 0)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
#ifndef PAE
|
||||||
|
if (smap->base >= 0xffffffff) {
|
||||||
|
printf("%uK of memory above 4GB ignored\n",
|
||||||
|
(u_int)(smap->length / 1024));
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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");
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (smap->base == physmap[physmap_idx + 1]) {
|
||||||
|
physmap[physmap_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);
|
||||||
|
}
|
||||||
|
physmap[physmap_idx] = smap->base;
|
||||||
|
physmap[physmap_idx + 1] = smap->base + smap->length;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Populate the (physmap) array with base/bound pairs describing the
|
* Populate the (physmap) array with base/bound pairs describing the
|
||||||
* available physical memory in the system, then test this memory and
|
* available physical memory in the system, then test this memory and
|
||||||
@ -1664,8 +1716,10 @@ getmemsize(int first)
|
|||||||
struct vm86context vmc;
|
struct vm86context vmc;
|
||||||
vm_paddr_t pa, physmap[PHYSMAP_SIZE];
|
vm_paddr_t pa, physmap[PHYSMAP_SIZE];
|
||||||
pt_entry_t *pte;
|
pt_entry_t *pte;
|
||||||
struct bios_smap *smap;
|
struct bios_smap *smap, *smapbase, *smapend;
|
||||||
|
u_int32_t smapsize;
|
||||||
quad_t dcons_addr, dcons_size;
|
quad_t dcons_addr, dcons_size;
|
||||||
|
caddr_t kmdp;
|
||||||
|
|
||||||
#ifdef XBOX
|
#ifdef XBOX
|
||||||
if (arch_i386_is_xbox) {
|
if (arch_i386_is_xbox) {
|
||||||
@ -1744,69 +1798,54 @@ getmemsize(int first)
|
|||||||
|
|
||||||
int15e820:
|
int15e820:
|
||||||
/*
|
/*
|
||||||
* map page 1 R/W into the kernel page table so we can use it
|
* Fetch the memory map with INT 15:E820. First, check to see
|
||||||
* as a buffer. The kernel will unmap this page later.
|
* if the loader supplied it and use that if so. Otherwise,
|
||||||
|
* use vm86 to invoke the BIOS call directly.
|
||||||
*/
|
*/
|
||||||
pmap_kenter(KERNBASE + (1 << PAGE_SHIFT), 1 << PAGE_SHIFT);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get memory map with INT 15:E820
|
|
||||||
*/
|
|
||||||
vmc.npages = 0;
|
|
||||||
smap = (void *)vm86_addpage(&vmc, 1, KERNBASE + (1 << PAGE_SHIFT));
|
|
||||||
vm86_getptr(&vmc, (vm_offset_t)smap, &vmf.vmf_es, &vmf.vmf_di);
|
|
||||||
|
|
||||||
physmap_idx = 0;
|
physmap_idx = 0;
|
||||||
vmf.vmf_ebx = 0;
|
smapbase = NULL;
|
||||||
do {
|
kmdp = preload_search_by_type("elf kernel");
|
||||||
vmf.vmf_eax = 0xE820;
|
if (kmdp == NULL)
|
||||||
vmf.vmf_edx = SMAP_SIG;
|
kmdp = preload_search_by_type("elf32 kernel");
|
||||||
vmf.vmf_ecx = sizeof(struct bios_smap);
|
if (kmdp != NULL)
|
||||||
i = vm86_datacall(0x15, &vmf, &vmc);
|
smapbase = (struct bios_smap *)preload_search_info(kmdp,
|
||||||
if (i || vmf.vmf_eax != SMAP_SIG)
|
MODINFO_METADATA | MODINFOMD_SMAP);
|
||||||
break;
|
if (smapbase != NULL) {
|
||||||
if (boothowto & RB_VERBOSE)
|
/* subr_module.c says:
|
||||||
printf("SMAP type=%02x base=%016llx len=%016llx\n",
|
* "Consumer may safely assume that size value precedes data."
|
||||||
smap->type, smap->base, smap->length);
|
* ie: an int32_t immediately precedes smap.
|
||||||
|
*/
|
||||||
|
smapsize = *((u_int32_t *)smapbase - 1);
|
||||||
|
smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize);
|
||||||
has_smap = 1;
|
has_smap = 1;
|
||||||
|
|
||||||
if (smap->type != SMAP_TYPE_MEMORY)
|
for (smap = smapbase; smap < smapend; smap++)
|
||||||
continue;
|
if (!add_smap_entry(smap, physmap, &physmap_idx))
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* map page 1 R/W into the kernel page table so we can use it
|
||||||
|
* as a buffer. The kernel will unmap this page later.
|
||||||
|
*/
|
||||||
|
pmap_kenter(KERNBASE + (1 << PAGE_SHIFT), 1 << PAGE_SHIFT);
|
||||||
|
vmc.npages = 0;
|
||||||
|
smap = (void *)vm86_addpage(&vmc, 1, KERNBASE +
|
||||||
|
(1 << PAGE_SHIFT));
|
||||||
|
vm86_getptr(&vmc, (vm_offset_t)smap, &vmf.vmf_es, &vmf.vmf_di);
|
||||||
|
|
||||||
if (smap->length == 0)
|
vmf.vmf_ebx = 0;
|
||||||
continue;
|
do {
|
||||||
|
vmf.vmf_eax = 0xE820;
|
||||||
#ifndef PAE
|
vmf.vmf_edx = SMAP_SIG;
|
||||||
if (smap->base >= 0xffffffff) {
|
vmf.vmf_ecx = sizeof(struct bios_smap);
|
||||||
printf("%uK of memory above 4GB ignored\n",
|
i = vm86_datacall(0x15, &vmf, &vmc);
|
||||||
(u_int)(smap->length / 1024));
|
if (i || vmf.vmf_eax != SMAP_SIG)
|
||||||
continue;
|
break;
|
||||||
}
|
has_smap = 1;
|
||||||
#endif
|
if (!add_smap_entry(smap, physmap, &physmap_idx))
|
||||||
|
break;
|
||||||
for (i = 0; i <= physmap_idx; i += 2) {
|
} while (vmf.vmf_ebx != 0);
|
||||||
if (smap->base < physmap[i + 1]) {
|
}
|
||||||
if (boothowto & RB_VERBOSE)
|
|
||||||
printf(
|
|
||||||
"Overlapping or non-montonic 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");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
physmap[physmap_idx] = smap->base;
|
|
||||||
physmap[physmap_idx + 1] = smap->base + smap->length;
|
|
||||||
} while (vmf.vmf_ebx != 0);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform "base memory" related probes & setup based on SMAP
|
* Perform "base memory" related probes & setup based on SMAP
|
||||||
|
Loading…
x
Reference in New Issue
Block a user