mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-30 16:51:41 +00:00
Add some platform KOBJ extensions and continue integrating PowerPC
hypervisor infrastructure support: - Fix coexistence of multiple platform modules in the same kernel - Allow platform modules to provide an SMP topology - PowerPC hypervisors limit the amount of memory accessible in real mode. Allow the platform modules to specify the maximum real-mode address, and modify the bits of the kernel that need to allocate real-mode-accessible buffers to respect this limits.
This commit is contained in:
parent
b13c7dec5f
commit
6413b05739
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=215159
@ -2385,6 +2385,9 @@ moea64_bootstrap_alloc(vm_size_t size, u_int align)
|
||||
if (s < phys_avail[i] || e > phys_avail[i + 1])
|
||||
continue;
|
||||
|
||||
if (s + size > platform_real_maxaddr())
|
||||
continue;
|
||||
|
||||
if (s == phys_avail[i]) {
|
||||
phys_avail[i] += size;
|
||||
} else if (e == phys_avail[i + 1]) {
|
||||
|
@ -692,16 +692,3 @@ OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
|
||||
return (bus_space_map(*tag, addr, size, 0, handle));
|
||||
}
|
||||
|
||||
int
|
||||
mem_valid(vm_offset_t addr, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nOFmem; i++)
|
||||
if ((addr >= OFmem[i].mr_start)
|
||||
&& (addr + len < OFmem[i].mr_start + OFmem[i].mr_size))
|
||||
return (0);
|
||||
|
||||
return (EFAULT);
|
||||
}
|
||||
|
||||
|
@ -36,9 +36,14 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/uma.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_pageout.h>
|
||||
#include <vm/vm_phys.h>
|
||||
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/platform.h>
|
||||
#include <machine/pmap.h>
|
||||
#include <machine/vmparam.h>
|
||||
|
||||
@ -474,6 +479,51 @@ slb_insert_user(pmap_t pm, struct slb *slb)
|
||||
pm->pm_slb[i] = slb;
|
||||
}
|
||||
|
||||
static void *
|
||||
slb_uma_real_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
|
||||
{
|
||||
static vm_offset_t realmax = 0;
|
||||
void *va;
|
||||
vm_page_t m;
|
||||
int pflags;
|
||||
|
||||
if (realmax == 0)
|
||||
realmax = platform_real_maxaddr();
|
||||
|
||||
*flags = UMA_SLAB_PRIV;
|
||||
if ((wait & (M_NOWAIT|M_USE_RESERVE)) == M_NOWAIT)
|
||||
pflags = VM_ALLOC_INTERRUPT | VM_ALLOC_WIRED;
|
||||
else
|
||||
pflags = VM_ALLOC_SYSTEM | VM_ALLOC_WIRED;
|
||||
if (wait & M_ZERO)
|
||||
pflags |= VM_ALLOC_ZERO;
|
||||
|
||||
for (;;) {
|
||||
m = vm_phys_alloc_contig(1, 0, realmax, PAGE_SIZE,
|
||||
PAGE_SIZE);
|
||||
if (m == NULL) {
|
||||
if (wait & M_NOWAIT)
|
||||
return (NULL);
|
||||
VM_WAIT;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
va = (void *) VM_PAGE_TO_PHYS(m);
|
||||
|
||||
if (!hw_direct_map)
|
||||
pmap_kenter((vm_offset_t)va, VM_PAGE_TO_PHYS(m));
|
||||
|
||||
if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0)
|
||||
bzero(va, PAGE_SIZE);
|
||||
|
||||
/* vm_phys_alloc_contig does not track wiring */
|
||||
atomic_add_int(&cnt.v_wire_count, 1);
|
||||
m->wire_count = 1;
|
||||
|
||||
return (va);
|
||||
}
|
||||
|
||||
static void
|
||||
slb_zone_init(void *dummy)
|
||||
{
|
||||
@ -482,6 +532,11 @@ slb_zone_init(void *dummy)
|
||||
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM);
|
||||
slb_cache_zone = uma_zcreate("SLB cache", 64*sizeof(struct slb *),
|
||||
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM);
|
||||
|
||||
if (platform_real_maxaddr() != VM_MAX_ADDRESS) {
|
||||
uma_zone_set_allocf(slb_cache_zone, slb_uma_real_alloc);
|
||||
uma_zone_set_allocf(slbt_zone, slb_uma_real_alloc);
|
||||
}
|
||||
}
|
||||
|
||||
struct slb **
|
||||
|
@ -597,12 +597,3 @@ bzero(void *buf, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX what is the better/proper place for this routine?
|
||||
*/
|
||||
int
|
||||
mem_valid(vm_offset_t addr, int len)
|
||||
{
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ struct mem_region {
|
||||
};
|
||||
|
||||
void mem_regions(struct mem_region **, int *, struct mem_region **, int *);
|
||||
vm_offset_t platform_real_maxaddr(void);
|
||||
|
||||
u_long platform_timebase_freq(struct cpuref *);
|
||||
|
||||
|
@ -98,13 +98,6 @@ machdep_ap_bootstrap(void)
|
||||
sched_throw(NULL);
|
||||
}
|
||||
|
||||
struct cpu_group *
|
||||
cpu_topo(void)
|
||||
{
|
||||
|
||||
return (smp_topo_none());
|
||||
}
|
||||
|
||||
void
|
||||
cpu_mp_setmaxid(void)
|
||||
{
|
||||
|
@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/ktr.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/smp.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -47,6 +48,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_page.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/platform.h>
|
||||
#include <machine/platformvar.h>
|
||||
#include <machine/smp.h>
|
||||
@ -62,11 +64,45 @@ static char plat_name[64] = "";
|
||||
SYSCTL_STRING(_hw, OID_AUTO, platform, CTLFLAG_RD | CTLFLAG_TUN,
|
||||
plat_name, 0, "Platform currently in use");
|
||||
|
||||
static struct mem_region *pregions = NULL;
|
||||
static struct mem_region *aregions = NULL;
|
||||
static int npregions, naregions;
|
||||
|
||||
void
|
||||
mem_regions(struct mem_region **phys, int *physsz, struct mem_region **avail,
|
||||
int *availsz)
|
||||
{
|
||||
PLATFORM_MEM_REGIONS(plat_obj, phys, physsz, avail, availsz);
|
||||
if (pregions == NULL)
|
||||
PLATFORM_MEM_REGIONS(plat_obj, &pregions, &npregions,
|
||||
&aregions, &naregions);
|
||||
|
||||
*phys = pregions;
|
||||
*avail = aregions;
|
||||
*physsz = npregions;
|
||||
*availsz = naregions;
|
||||
}
|
||||
|
||||
int
|
||||
mem_valid(vm_offset_t addr, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pregions == NULL)
|
||||
PLATFORM_MEM_REGIONS(plat_obj, &pregions, &npregions,
|
||||
&aregions, &naregions);
|
||||
|
||||
for (i = 0; i < npregions; i++)
|
||||
if ((addr >= pregions[i].mr_start)
|
||||
&& (addr + len < pregions[i].mr_start + pregions[i].mr_size))
|
||||
return (0);
|
||||
|
||||
return (EFAULT);
|
||||
}
|
||||
|
||||
vm_offset_t
|
||||
platform_real_maxaddr(void)
|
||||
{
|
||||
return (PLATFORM_REAL_MAXADDR(plat_obj));
|
||||
}
|
||||
|
||||
const char *
|
||||
@ -105,6 +141,14 @@ platform_smp_start_cpu(struct pcpu *cpu)
|
||||
return (PLATFORM_SMP_START_CPU(plat_obj, cpu));
|
||||
}
|
||||
|
||||
#ifdef SMP
|
||||
struct cpu_group *
|
||||
cpu_topo(void)
|
||||
{
|
||||
return (PLATFORM_SMP_TOPO(plat_obj));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Reset back to firmware.
|
||||
*/
|
||||
@ -164,9 +208,10 @@ platform_probe_and_attach()
|
||||
}
|
||||
|
||||
/*
|
||||
* We can't free the KOBJ, since it is static. Luckily,
|
||||
* this has no ill effects since it gets reset every time.
|
||||
* We can't free the KOBJ, since it is static. Reset the ops
|
||||
* member of this class so that we can come back later.
|
||||
*/
|
||||
platp->ops = NULL;
|
||||
}
|
||||
|
||||
if (plat_def_impl == NULL)
|
||||
|
@ -30,10 +30,12 @@
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/smp.h>
|
||||
|
||||
#include <machine/platform.h>
|
||||
#include <machine/platformvar.h>
|
||||
#include <machine/smp.h>
|
||||
#include <machine/vmparam.h>
|
||||
|
||||
/**
|
||||
* @defgroup PLATFORM platform - KObj methods for PowerPC platform
|
||||
@ -66,6 +68,18 @@ CODE {
|
||||
{
|
||||
return (ENOENT);
|
||||
}
|
||||
static struct cpu_group *platform_null_smp_topo(platform_t plat)
|
||||
{
|
||||
#ifdef SMP
|
||||
return (smp_topo_none());
|
||||
#else
|
||||
return (NULL);
|
||||
#endif
|
||||
}
|
||||
static vm_offset_t platform_null_real_maxaddr(platform_t plat)
|
||||
{
|
||||
return (VM_MAX_ADDRESS);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -108,6 +122,15 @@ METHOD void mem_regions {
|
||||
int *_availsz;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Return the maximum address accessible in real mode
|
||||
* (for use with hypervisors)
|
||||
*/
|
||||
METHOD vm_offset_t real_maxaddr {
|
||||
platform_t _plat;
|
||||
} DEFAULT platform_null_real_maxaddr;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the CPU's timebase frequency, in ticks per second.
|
||||
*
|
||||
@ -161,6 +184,13 @@ METHOD int smp_start_cpu {
|
||||
struct pcpu *_cpu;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Return SMP topology
|
||||
*/
|
||||
METHOD cpu_group_t smp_topo {
|
||||
platform_t _plat;
|
||||
} DEFAULT platform_null_smp_topo;
|
||||
|
||||
/**
|
||||
* @brief Reset system
|
||||
*/
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
#ifndef LOCORE
|
||||
|
||||
#ifdef SMP
|
||||
|
||||
/*
|
||||
* Topology of a NUMA or HTT system.
|
||||
*
|
||||
@ -41,6 +39,8 @@ struct cpu_group {
|
||||
int8_t cg_flags; /* Traversal modifiers. */
|
||||
};
|
||||
|
||||
typedef struct cpu_group *cpu_group_t;
|
||||
|
||||
/*
|
||||
* Defines common resources for CPUs in the group. The highest level
|
||||
* resource should be used when multiple are shared.
|
||||
@ -60,6 +60,7 @@ struct cpu_group {
|
||||
/*
|
||||
* Convenience routines for building topologies.
|
||||
*/
|
||||
#ifdef SMP
|
||||
struct cpu_group *smp_topo(void);
|
||||
struct cpu_group *smp_topo_none(void);
|
||||
struct cpu_group *smp_topo_1level(int l1share, int l1count, int l1flags);
|
||||
|
Loading…
Reference in New Issue
Block a user