[PPC64] Support QEMU/KVM pseries without hugepages

This set of changes make it possible to run FreeBSD for PowerPC64/pseries,
under QEMU/KVM, without requiring the host to make hugepages available to the
guest.

While there was already this possibility, by means of setting hw_direct_map to
0, on PowerPC64 there were a couple of issues/wrong assumptions that prevented
this from working, before this changelist.

Reviewed by:	jhibbits
Differential Revision:	https://reviews.freebsd.org/D20522
This commit is contained in:
Leandro Lupori 2019-06-07 17:58:59 +00:00
parent 007d50155f
commit b934fc7468
4 changed files with 64 additions and 18 deletions

View File

@ -638,7 +638,7 @@ moea64_setup_direct_map(mmu_t mmup, vm_offset_t kernelstart,
{
struct pvo_entry *pvo;
register_t msr;
vm_paddr_t pa;
vm_paddr_t pa, pkernelstart, pkernelend;
vm_offset_t size, off;
uint64_t pte_lo;
int i;
@ -686,9 +686,11 @@ moea64_setup_direct_map(mmu_t mmup, vm_offset_t kernelstart,
*/
if (!hw_direct_map || kernelstart < DMAP_BASE_ADDRESS) {
for (pa = kernelstart & ~PAGE_MASK; pa < kernelend;
pkernelstart = kernelstart & ~DMAP_BASE_ADDRESS;
pkernelend = kernelend & ~DMAP_BASE_ADDRESS;
for (pa = pkernelstart & ~PAGE_MASK; pa < pkernelend;
pa += PAGE_SIZE)
moea64_kenter(mmup, pa, pa);
moea64_kenter(mmup, pa | DMAP_BASE_ADDRESS, pa);
}
if (!hw_direct_map) {
@ -696,6 +698,10 @@ moea64_setup_direct_map(mmu_t mmup, vm_offset_t kernelstart,
off = (vm_offset_t)(moea64_bpvo_pool);
for (pa = off; pa < off + size; pa += PAGE_SIZE)
moea64_kenter(mmup, pa, pa);
/* Map exception vectors */
for (pa = EXC_RSVD; pa < EXC_LAST; pa += PAGE_SIZE)
moea64_kenter(mmup, pa | DMAP_BASE_ADDRESS, pa);
}
ENABLE_TRANS(msr);
@ -875,7 +881,7 @@ moea64_mid_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
* Initialise the bootstrap pvo pool.
*/
moea64_bpvo_pool = (struct pvo_entry *)moea64_bootstrap_alloc(
moea64_bpvo_pool_size*sizeof(struct pvo_entry), 0);
moea64_bpvo_pool_size*sizeof(struct pvo_entry), PAGE_SIZE);
moea64_bpvo_pool_index = 0;
/* Place at address usable through the direct map */
@ -1169,15 +1175,19 @@ moea64_unwire(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva)
*/
static __inline
void moea64_set_scratchpage_pa(mmu_t mmup, int which, vm_paddr_t pa) {
void moea64_set_scratchpage_pa(mmu_t mmup, int which, vm_paddr_t pa)
{
struct pvo_entry *pvo;
KASSERT(!hw_direct_map, ("Using OEA64 scratchpage with a direct map!"));
mtx_assert(&moea64_scratchpage_mtx, MA_OWNED);
moea64_scratchpage_pvo[which]->pvo_pte.pa =
pvo = moea64_scratchpage_pvo[which];
PMAP_LOCK(pvo->pvo_pmap);
pvo->pvo_pte.pa =
moea64_calc_wimg(pa, VM_MEMATTR_DEFAULT) | (uint64_t)pa;
MOEA64_PTE_REPLACE(mmup, moea64_scratchpage_pvo[which],
MOEA64_PTE_INVALIDATE);
MOEA64_PTE_REPLACE(mmup, pvo, MOEA64_PTE_INVALIDATE);
PMAP_UNLOCK(pvo->pvo_pmap);
isync();
}

View File

@ -81,6 +81,7 @@ extern u_int moea64_pte_overflow;
extern int moea64_large_page_shift;
extern uint64_t moea64_large_page_size;
extern uint64_t moea64_large_page_mask;
extern u_long moea64_pteg_count;
extern u_long moea64_pteg_mask;
extern int n_slbs;

View File

@ -500,10 +500,12 @@ slb_uma_real_alloc(uma_zone_t zone, vm_size_t bytes, int domain,
if (m == NULL)
return (NULL);
va = (void *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
if (!hw_direct_map)
if (hw_direct_map)
va = (void *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
else {
va = (void *)(VM_PAGE_TO_PHYS(m) | DMAP_BASE_ADDRESS);
pmap_kenter((vm_offset_t)va, VM_PAGE_TO_PHYS(m));
}
if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0)
bzero(va, PAGE_SIZE);

View File

@ -59,6 +59,16 @@ __FBSDID("$FreeBSD$");
#include "phyp-hvcall.h"
#define MMU_PHYP_DEBUG 0
#define MMU_PHYP_ID "mmu_phyp: "
#if MMU_PHYP_DEBUG
#define dprintf(fmt, ...) printf(fmt, ## __VA_ARGS__)
#define dprintf0(fmt, ...) dprintf(MMU_PHYP_ID fmt, ## __VA_ARGS__)
#else
#define dprintf(fmt, args...) do { ; } while(0)
#define dprintf0(fmt, args...) do { ; } while(0)
#endif
static struct rmlock mphyp_eviction_lock;
/*
@ -149,6 +159,7 @@ mphyp_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
res = OF_getencprop(node, "ibm,slb-size", prop, sizeof(prop[0]));
if (res > 0)
n_slbs = prop[0];
dprintf0("slb-size=%i\n", n_slbs);
moea64_pteg_count = final_pteg_count / sizeof(struct lpteg);
@ -185,11 +196,22 @@ mphyp_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
shift = arr[idx];
slb_encoding = arr[idx + 1];
nptlp = arr[idx + 2];
dprintf0("Segment Page Size: "
"%uKB, slb_enc=0x%X: {size, encoding}[%u] =",
shift > 10? 1 << (shift-10) : 0,
slb_encoding, nptlp);
idx += 3;
len -= 3;
while (len > 0 && nptlp) {
lp_size = arr[idx];
lp_encoding = arr[idx+1];
dprintf(" {%uKB, 0x%X}",
lp_size > 10? 1 << (lp_size-10) : 0,
lp_encoding);
if (slb_encoding == SLBV_L && lp_encoding == 0)
break;
@ -197,17 +219,28 @@ mphyp_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
len -= 2;
nptlp--;
}
dprintf("\n");
if (nptlp && slb_encoding == SLBV_L && lp_encoding == 0)
break;
}
if (len == 0)
panic("Standard large pages (SLB[L] = 1, PTE[LP] = 0) "
"not supported by this system. Please enable huge "
"page backing if running under PowerKVM.");
moea64_large_page_shift = shift;
moea64_large_page_size = 1ULL << lp_size;
if (len > 0) {
moea64_large_page_shift = shift;
moea64_large_page_size = 1ULL << lp_size;
moea64_large_page_mask = moea64_large_page_size - 1;
hw_direct_map = 1;
printf(MMU_PHYP_ID
"Support for hugepages of %uKB detected\n",
moea64_large_page_shift > 10?
1 << (moea64_large_page_shift-10) : 0);
} else {
moea64_large_page_size = 0;
moea64_large_page_shift = 0;
moea64_large_page_mask = 0;
hw_direct_map = 0;
printf(MMU_PHYP_ID
"Support for hugepages not found\n");
}
}
moea64_mid_bootstrap(mmup, kernelstart, kernelend);