RISC-V: use physmem to manage physical memory
Replace our hand-rolled functions with the generic ones provided by kern/subr_physmem.c. This greatly simplifies the initialization of physical memory regions and kernel globals. Tested by: nick Differential Revision: https://reviews.freebsd.org/D24154
This commit is contained in:
parent
9957fe2008
commit
6acffac915
@ -20,6 +20,7 @@ kern/pic_if.m standard
|
||||
kern/subr_devmap.c standard
|
||||
kern/subr_dummy_vdso_tc.c standard
|
||||
kern/subr_intr.c standard
|
||||
kern/subr_physmem.c standard
|
||||
libkern/bcmp.c standard
|
||||
libkern/bcopy.c standard
|
||||
libkern/ffs.c standard
|
||||
|
@ -44,7 +44,7 @@ struct riscv_bootparams {
|
||||
vm_offset_t dtbp_virt; /* Device tree blob virtual addr */
|
||||
};
|
||||
|
||||
extern vm_paddr_t physmap[];
|
||||
extern vm_paddr_t physmap[PHYS_AVAIL_ENTRIES];
|
||||
extern u_int physmap_idx;
|
||||
|
||||
vm_offset_t fake_preload_metadata(struct riscv_bootparams *rbp);
|
||||
|
@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/linker.h>
|
||||
#include <sys/msgbuf.h>
|
||||
#include <sys/pcpu.h>
|
||||
#include <sys/physmem.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/reboot.h>
|
||||
@ -108,8 +109,6 @@ static struct trapframe proc0_tf;
|
||||
|
||||
int early_boot = 1;
|
||||
int cold = 1;
|
||||
long realmem = 0;
|
||||
long Maxmem = 0;
|
||||
|
||||
#define DTB_SIZE_MAX (1024 * 1024)
|
||||
|
||||
@ -673,74 +672,6 @@ init_proc0(vm_offset_t kstack)
|
||||
pcpup->pc_curpcb = thread0.td_pcb;
|
||||
}
|
||||
|
||||
static int
|
||||
add_physmap_entry(uint64_t base, uint64_t length, vm_paddr_t *physmap,
|
||||
u_int *physmap_idxp)
|
||||
{
|
||||
u_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.
|
||||
*/
|
||||
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; 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;
|
||||
|
||||
printf("physmap[%d] = 0x%016lx\n", insert_idx, base);
|
||||
printf("physmap[%d] = 0x%016lx\n", insert_idx + 1, base + length);
|
||||
return (1);
|
||||
}
|
||||
|
||||
#ifdef FDT
|
||||
static void
|
||||
try_load_dtb(caddr_t kmdp)
|
||||
@ -864,7 +795,6 @@ initriscv(struct riscv_bootparams *rvbp)
|
||||
vm_offset_t lastaddr;
|
||||
vm_size_t kernlen;
|
||||
caddr_t kmdp;
|
||||
int i;
|
||||
|
||||
TSRAW(&thread0, TS_ENTER, __func__, NULL);
|
||||
|
||||
@ -896,20 +826,12 @@ initriscv(struct riscv_bootparams *rvbp)
|
||||
|
||||
#ifdef FDT
|
||||
try_load_dtb(kmdp);
|
||||
#endif
|
||||
|
||||
/* Load the physical memory ranges */
|
||||
physmap_idx = 0;
|
||||
|
||||
#ifdef FDT
|
||||
/* Grab physical memory regions information from device tree. */
|
||||
if (fdt_get_mem_regions(mem_regions, &mem_regions_sz, NULL) != 0)
|
||||
if (fdt_get_mem_regions(mem_regions, &mem_regions_sz, NULL) != 0) {
|
||||
panic("Cannot get physical memory regions");
|
||||
|
||||
for (i = 0; i < mem_regions_sz; i++) {
|
||||
add_physmap_entry(mem_regions[i].mr_start,
|
||||
mem_regions[i].mr_size, physmap, &physmap_idx);
|
||||
}
|
||||
physmem_hardware_regions(mem_regions, mem_regions_sz);
|
||||
#endif
|
||||
|
||||
/* Do basic tuning, hz etc */
|
||||
@ -921,6 +843,8 @@ initriscv(struct riscv_bootparams *rvbp)
|
||||
kernlen = (lastaddr - KERNBASE);
|
||||
pmap_bootstrap(rvbp->kern_l1pt, mem_regions[0].mr_start, kernlen);
|
||||
|
||||
physmem_init_kernel_globals();
|
||||
|
||||
/* Establish static device mappings */
|
||||
devmap_bootstrap(0, NULL);
|
||||
|
||||
@ -933,6 +857,9 @@ initriscv(struct riscv_bootparams *rvbp)
|
||||
init_param2(physmem);
|
||||
kdb_init();
|
||||
|
||||
if (boothowto & RB_VERBOSE)
|
||||
physmem_print_tables();
|
||||
|
||||
early_boot = 0;
|
||||
|
||||
TSEXIT();
|
||||
|
@ -129,6 +129,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mman.h>
|
||||
#include <sys/msgbuf.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/physmem.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/sbuf.h>
|
||||
@ -554,10 +555,10 @@ pmap_bootstrap_l3(vm_offset_t l1pt, vm_offset_t va, vm_offset_t l3_start)
|
||||
void
|
||||
pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen)
|
||||
{
|
||||
u_int l1_slot, l2_slot, avail_slot, map_slot;
|
||||
u_int l1_slot, l2_slot;
|
||||
vm_offset_t freemempos;
|
||||
vm_offset_t dpcpu, msgbufpv;
|
||||
vm_paddr_t end, max_pa, min_pa, pa, start;
|
||||
vm_paddr_t max_pa, min_pa, pa;
|
||||
pt_entry_t *l2p;
|
||||
int i;
|
||||
|
||||
@ -576,6 +577,9 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen)
|
||||
/* Assume the address we were loaded to is a valid physical address. */
|
||||
min_pa = max_pa = kernstart;
|
||||
|
||||
physmap_idx = physmem_avail(physmap, nitems(physmap));
|
||||
physmap_idx /= 2;
|
||||
|
||||
/*
|
||||
* Find the minimum physical address. physmap is sorted,
|
||||
* but may contain empty ranges.
|
||||
@ -641,46 +645,7 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen)
|
||||
|
||||
pa = pmap_early_vtophys(l1pt, freemempos);
|
||||
|
||||
/* Initialize phys_avail and dump_avail. */
|
||||
for (avail_slot = map_slot = physmem = 0; map_slot < physmap_idx * 2;
|
||||
map_slot += 2) {
|
||||
start = physmap[map_slot];
|
||||
end = physmap[map_slot + 1];
|
||||
|
||||
if (start == end)
|
||||
continue;
|
||||
dump_avail[map_slot] = start;
|
||||
dump_avail[map_slot + 1] = end;
|
||||
realmem += atop((vm_offset_t)(end - start));
|
||||
|
||||
if (start >= kernstart && end <= pa)
|
||||
continue;
|
||||
|
||||
if (start < kernstart && end > kernstart)
|
||||
end = kernstart;
|
||||
else if (start < pa && end > pa)
|
||||
start = pa;
|
||||
phys_avail[avail_slot] = start;
|
||||
phys_avail[avail_slot + 1] = end;
|
||||
physmem += (end - start) >> PAGE_SHIFT;
|
||||
avail_slot += 2;
|
||||
|
||||
if (end != physmap[map_slot + 1] && end > pa) {
|
||||
phys_avail[avail_slot] = pa;
|
||||
phys_avail[avail_slot + 1] = physmap[map_slot + 1];
|
||||
physmem += (physmap[map_slot + 1] - pa) >> PAGE_SHIFT;
|
||||
avail_slot += 2;
|
||||
}
|
||||
}
|
||||
phys_avail[avail_slot] = 0;
|
||||
phys_avail[avail_slot + 1] = 0;
|
||||
|
||||
/*
|
||||
* Maxmem isn't the "maximum memory", it's one larger than the
|
||||
* highest page of the physical address space. It should be
|
||||
* called something like "Maxphyspage".
|
||||
*/
|
||||
Maxmem = atop(phys_avail[avail_slot - 1]);
|
||||
physmem_exclude_region(kernstart, pa - kernstart, EXFLAG_NOALLOC);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user