Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 50de596d authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Michael Ellerman
Browse files

powerpc/mm/hash: Add support for Power9 Hash



PowerISA 3.0 adds a parition table indexed by LPID. Parition table
allows us to specify the MMU model that will be used for guest and host
translation.

This patch adds support with SLB based hash model (UPRT = 0). What is
required with this model is to support the new hash page table entry
format and also setup partition table such that we use hash table for
address translation.

We don't have segment table support yet.

In order to make sure we don't load KVM module on Power9 (since we don't
have kvm support yet) this patch also disables KVM on Power9.

Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent e9983344
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -78,6 +78,10 @@
#define HPTE_V_SECONDARY	ASM_CONST(0x0000000000000002)
#define HPTE_V_VALID		ASM_CONST(0x0000000000000001)

/*
 * ISA 3.0 have a different HPTE format.
 */
#define HPTE_R_3_0_SSIZE_SHIFT	58
#define HPTE_R_PP0		ASM_CONST(0x8000000000000000)
#define HPTE_R_TS		ASM_CONST(0x4000000000000000)
#define HPTE_R_KEY_HI		ASM_CONST(0x3000000000000000)
@@ -224,6 +228,7 @@ static inline unsigned long hpte_encode_avpn(unsigned long vpn, int psize,
	 */
	v = (vpn >> (23 - VPN_SHIFT)) & ~(mmu_psize_defs[psize].avpnm);
	v <<= HPTE_V_AVPN_SHIFT;
	if (!cpu_has_feature(CPU_FTR_ARCH_300))
		v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
	return v;
}
@@ -248,8 +253,12 @@ static inline unsigned long hpte_encode_v(unsigned long vpn, int base_psize,
 * aligned for the requested page size
 */
static inline unsigned long hpte_encode_r(unsigned long pa, int base_psize,
					  int actual_psize)
					  int actual_psize, int ssize)
{

	if (cpu_has_feature(CPU_FTR_ARCH_300))
		pa |= ((unsigned long) ssize) << HPTE_R_3_0_SSIZE_SHIFT;

	/* A 4K page needs no special encoding */
	if (actual_psize == MMU_PAGE_4K)
		return pa & HPTE_R_RPN;
+6 −0
Original line number Diff line number Diff line
@@ -3271,6 +3271,12 @@ static int kvmppc_core_check_processor_compat_hv(void)
	if (!cpu_has_feature(CPU_FTR_HVMODE) ||
	    !cpu_has_feature(CPU_FTR_ARCH_206))
		return -EIO;
	/*
	 * Disable KVM for Power9, untill the required bits merged.
	 */
	if (cpu_has_feature(CPU_FTR_ARCH_300))
		return -EIO;

	return 0;
}

+5 −1
Original line number Diff line number Diff line
@@ -1683,7 +1683,11 @@ static void kvmppc_core_destroy_vm_pr(struct kvm *kvm)

static int kvmppc_core_check_processor_compat_pr(void)
{
	/* we are always compatible */
	/*
	 * Disable KVM for Power9 untill the required bits merged.
	 */
	if (cpu_has_feature(CPU_FTR_ARCH_300))
		return -EIO;
	return 0;
}

+10 −1
Original line number Diff line number Diff line
@@ -221,7 +221,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn,
		return -1;

	hpte_v = hpte_encode_v(vpn, psize, apsize, ssize) | vflags | HPTE_V_VALID;
	hpte_r = hpte_encode_r(pa, psize, apsize) | rflags;
	hpte_r = hpte_encode_r(pa, psize, apsize, ssize) | rflags;

	if (!(vflags & HPTE_V_BOLTED)) {
		DBG_LOW(" i=%x hpte_v=%016lx, hpte_r=%016lx\n",
@@ -719,6 +719,12 @@ static void native_flush_hash_range(unsigned long number, int local)
	local_irq_restore(flags);
}

static int native_update_partition_table(u64 patb1)
{
	partition_tb->patb1 = cpu_to_be64(patb1);
	return 0;
}

void __init hpte_init_native(void)
{
	ppc_md.hpte_invalidate	= native_hpte_invalidate;
@@ -729,4 +735,7 @@ void __init hpte_init_native(void)
	ppc_md.hpte_clear_all	= native_hpte_clear;
	ppc_md.flush_hash_range = native_flush_hash_range;
	ppc_md.hugepage_invalidate   = native_hugepage_invalidate;

	if (cpu_has_feature(CPU_FTR_ARCH_300))
		ppc_md.update_partition_table = native_update_partition_table;
}
+40 −2
Original line number Diff line number Diff line
@@ -676,6 +676,41 @@ int remove_section_mapping(unsigned long start, unsigned long end)
}
#endif /* CONFIG_MEMORY_HOTPLUG */

static void __init hash_init_partition_table(phys_addr_t hash_table,
					     unsigned long pteg_count)
{
	unsigned long ps_field;
	unsigned long htab_size;
	unsigned long patb_size = 1UL << PATB_SIZE_SHIFT;

	/*
	 * slb llp encoding for the page size used in VPM real mode.
	 * We can ignore that for lpid 0
	 */
	ps_field = 0;
	htab_size =  __ilog2(pteg_count) - 11;

	BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 24), "Partition table size too large.");
	partition_tb = __va(memblock_alloc_base(patb_size, patb_size,
						MEMBLOCK_ALLOC_ANYWHERE));

	/* Initialize the Partition Table with no entries */
	memset((void *)partition_tb, 0, patb_size);
	partition_tb->patb0 = cpu_to_be64(ps_field | hash_table | htab_size);
	/*
	 * FIXME!! This should be done via update_partition table
	 * For now UPRT is 0 for us.
	 */
	partition_tb->patb1 = 0;
	DBG("Partition table %p\n", partition_tb);
	/*
	 * update partition table control register,
	 * 64 K size.
	 */
	mtspr(SPRN_PTCR, __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));

}

static void __init htab_initialize(void)
{
	unsigned long table;
@@ -744,8 +779,11 @@ static void __init htab_initialize(void)
		/* Initialize the HPT with no entries */
		memset((void *)table, 0, htab_size_bytes);

		if (!cpu_has_feature(CPU_FTR_ARCH_300))
			/* Set SDR1 */
			mtspr(SPRN_SDR1, _SDR1);
		else
			hash_init_partition_table(table, pteg_count);
	}

	prot = pgprot_val(PAGE_KERNEL);
Loading