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:
mhorne 2020-04-19 00:18:16 +00:00
parent 9957fe2008
commit 6acffac915
4 changed files with 17 additions and 124 deletions

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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);
}
/*