Add support for powernv POWER9 MMU initialization
The POWER9 MMU (PowerISA 3.0) is slightly different from current configurations, using a partition table even for hypervisor mode, and dropping the SDR1 register. Key off the newly early-enabled CPU features flags for the new architecture, and configure the MMU appropriately. The POWER9 MMU ignores the "PSIZ" field in the PTCR, and expects a 64kB table. As we are enabled for powernv (hypervisor mode, no VMs), only initialize partition table entry 0, and zero out the rest. The actual contents of the register are identical to SDR1 from previous architectures. Along with this, fix a bug in the page table allocation with very large memory. The table can be allocated on any 256k boundary. The bootstrap_alloc alignment argument is an int, and with large amounts of memory passing the size of the table as the alignment will overflow an integer. Hard-code the alignment at 256k as wider alignment is not necessary. Reviewed by: nwhitehorn Tested by: Breno Leitao Relnotes: Yes
This commit is contained in:
parent
66b2a0cd2b
commit
a0a74f77de
@ -159,8 +159,8 @@ struct mtx moea64_slb_mutex;
|
||||
/*
|
||||
* PTEG data.
|
||||
*/
|
||||
u_int moea64_pteg_count;
|
||||
u_int moea64_pteg_mask;
|
||||
u_long moea64_pteg_count;
|
||||
u_long moea64_pteg_mask;
|
||||
|
||||
/*
|
||||
* PVO data.
|
||||
|
@ -81,8 +81,8 @@ extern u_int moea64_pte_overflow;
|
||||
|
||||
extern int moea64_large_page_shift;
|
||||
extern uint64_t moea64_large_page_size;
|
||||
extern u_int moea64_pteg_count;
|
||||
extern u_int moea64_pteg_mask;
|
||||
extern u_long moea64_pteg_count;
|
||||
extern u_long moea64_pteg_mask;
|
||||
extern int n_slbs;
|
||||
|
||||
#endif /* _POWERPC_AIM_MMU_OEA64_H */
|
||||
|
@ -115,6 +115,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_extern.h>
|
||||
#include <vm/vm_pageout.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/mmuvar.h>
|
||||
|
||||
@ -129,6 +130,9 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#define VSID_HASH_MASK 0x0000007fffffffffULL
|
||||
|
||||
/* POWER9 only permits a 64k partition table size. */
|
||||
#define PART_SIZE 0x10000
|
||||
|
||||
static __inline void
|
||||
TLBIE(uint64_t vpn) {
|
||||
#ifndef __powerpc64__
|
||||
@ -183,6 +187,7 @@ TLBIE(uint64_t vpn) {
|
||||
/*
|
||||
* PTEG data.
|
||||
*/
|
||||
static volatile struct pate *moea64_part_table;
|
||||
static volatile struct lpte *moea64_pteg_table;
|
||||
static struct rwlock moea64_eviction_lock;
|
||||
|
||||
@ -400,9 +405,15 @@ moea64_cpu_bootstrap_native(mmu_t mmup, int ap)
|
||||
* Install page table
|
||||
*/
|
||||
|
||||
__asm __volatile ("ptesync; mtsdr1 %0; isync"
|
||||
:: "r"(((uintptr_t)moea64_pteg_table & ~DMAP_BASE_ADDRESS)
|
||||
| (uintptr_t)(flsl(moea64_pteg_mask >> 11))));
|
||||
if (cpu_features2 & PPC_FEATURE2_ARCH_3_00) {
|
||||
mtspr(SPR_PTCR,
|
||||
((uintptr_t)moea64_part_table & ~DMAP_BASE_ADDRESS) |
|
||||
flsl((PART_SIZE >> 12) - 1));
|
||||
} else {
|
||||
__asm __volatile ("ptesync; mtsdr1 %0; isync"
|
||||
:: "r"(((uintptr_t)moea64_pteg_table & ~DMAP_BASE_ADDRESS)
|
||||
| (uintptr_t)(flsl(moea64_pteg_mask >> 11))));
|
||||
}
|
||||
tlbia();
|
||||
}
|
||||
|
||||
@ -433,11 +444,28 @@ moea64_bootstrap_native(mmu_t mmup, vm_offset_t kernelstart,
|
||||
* as a measure of last resort. We do this a couple times.
|
||||
*/
|
||||
|
||||
moea64_pteg_table = (struct lpte *)moea64_bootstrap_alloc(size, size);
|
||||
if (cpu_features2 & PPC_FEATURE2_ARCH_3_00) {
|
||||
moea64_part_table =
|
||||
(struct pate *)moea64_bootstrap_alloc(PART_SIZE, PART_SIZE);
|
||||
if (hw_direct_map)
|
||||
moea64_part_table =
|
||||
(struct pate *)PHYS_TO_DMAP((vm_offset_t)moea64_part_table);
|
||||
}
|
||||
/*
|
||||
* PTEG table must be aligned on a 256k boundary, but can be placed
|
||||
* anywhere with that alignment.
|
||||
*/
|
||||
moea64_pteg_table = (struct lpte *)moea64_bootstrap_alloc(size, 256*1024);
|
||||
if (hw_direct_map)
|
||||
moea64_pteg_table =
|
||||
(struct lpte *)PHYS_TO_DMAP((vm_offset_t)moea64_pteg_table);
|
||||
DISABLE_TRANS(msr);
|
||||
if (cpu_features2 & PPC_FEATURE2_ARCH_3_00) {
|
||||
bzero(__DEVOLATILE(void *, moea64_part_table), PART_SIZE);
|
||||
moea64_part_table[0].pagetab =
|
||||
((uintptr_t)moea64_pteg_table & ~DMAP_BASE_ADDRESS) |
|
||||
(uintptr_t)(flsl((moea64_pteg_count - 1) >> 11));
|
||||
}
|
||||
bzero(__DEVOLATILE(void *, moea64_pteg_table), moea64_pteg_count *
|
||||
sizeof(struct lpteg));
|
||||
ENABLE_TRANS(msr);
|
||||
|
@ -64,6 +64,12 @@ struct lpteg {
|
||||
struct lpte pt[8];
|
||||
};
|
||||
|
||||
/* Partition table entry */
|
||||
struct pate {
|
||||
u_int64_t pagetab;
|
||||
u_int64_t proctab;
|
||||
};
|
||||
|
||||
#endif /* LOCORE */
|
||||
|
||||
/* 32-bit PTE definitions */
|
||||
|
@ -243,6 +243,7 @@
|
||||
#define LPCR_LPES 0x008 /* Bit 60 */
|
||||
#define SPR_LPID 0x13f /* Logical Partitioning Control */
|
||||
|
||||
#define SPR_PTCR 0x1d0 /* Partition Table Control Register */
|
||||
#define SPR_IBAT0U 0x210 /* .68 Instruction BAT Reg 0 Upper */
|
||||
#define SPR_IBAT0U 0x210 /* .6. Instruction BAT Reg 0 Upper */
|
||||
#define SPR_IBAT0L 0x211 /* .6. Instruction BAT Reg 0 Lower */
|
||||
|
@ -403,7 +403,7 @@ mphyp_pte_insert(mmu_t mmu, struct pvo_entry *pvo)
|
||||
return (0);
|
||||
}
|
||||
KASSERT(result == H_PTEG_FULL, ("Page insertion error: %ld "
|
||||
"(ptegidx: %#zx/%#x, PTE %#lx/%#lx", result, pvo->pvo_pte.slot,
|
||||
"(ptegidx: %#zx/%#lx, PTE %#lx/%#lx", result, pvo->pvo_pte.slot,
|
||||
moea64_pteg_count, pte.pte_hi, pte.pte_lo));
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user