From 10d0cdfc6e66db8fb00fc54a9c874e9ee7890b6d Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Sat, 5 May 2018 16:00:02 +0000 Subject: [PATCH] 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 --- sys/powerpc/aim/mmu_oea64.c | 4 ++-- sys/powerpc/aim/mmu_oea64.h | 4 ++-- sys/powerpc/aim/moea64_native.c | 36 +++++++++++++++++++++++++++++---- sys/powerpc/include/pte.h | 6 ++++++ sys/powerpc/include/spr.h | 1 + sys/powerpc/pseries/mmu_phyp.c | 2 +- 6 files changed, 44 insertions(+), 9 deletions(-) diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c index 3cb5543101d2..89848e584e77 100644 --- a/sys/powerpc/aim/mmu_oea64.c +++ b/sys/powerpc/aim/mmu_oea64.c @@ -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. diff --git a/sys/powerpc/aim/mmu_oea64.h b/sys/powerpc/aim/mmu_oea64.h index 43dc646cf28b..ba300049ed4b 100644 --- a/sys/powerpc/aim/mmu_oea64.h +++ b/sys/powerpc/aim/mmu_oea64.h @@ -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 */ diff --git a/sys/powerpc/aim/moea64_native.c b/sys/powerpc/aim/moea64_native.c index cb27cfca34ce..e29fe89b7771 100644 --- a/sys/powerpc/aim/moea64_native.c +++ b/sys/powerpc/aim/moea64_native.c @@ -115,6 +115,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -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); diff --git a/sys/powerpc/include/pte.h b/sys/powerpc/include/pte.h index fb986ce4b749..32eecaedb922 100644 --- a/sys/powerpc/include/pte.h +++ b/sys/powerpc/include/pte.h @@ -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 */ diff --git a/sys/powerpc/include/spr.h b/sys/powerpc/include/spr.h index a80a9006f939..8a868d5dd054 100644 --- a/sys/powerpc/include/spr.h +++ b/sys/powerpc/include/spr.h @@ -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 */ diff --git a/sys/powerpc/pseries/mmu_phyp.c b/sys/powerpc/pseries/mmu_phyp.c index 6705ad22341d..e171d399db7e 100644 --- a/sys/powerpc/pseries/mmu_phyp.c +++ b/sys/powerpc/pseries/mmu_phyp.c @@ -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)); /*