1
0
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:
Nathan Whitehorn 2010-11-12 04:18:19 +00:00
parent b13c7dec5f
commit 6413b05739
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=215159
9 changed files with 140 additions and 34 deletions

View File

@ -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]) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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