Commit 1f911c3a authored by Catalin Marinas's avatar Catalin Marinas
Browse files

Merge branch 'for-next/52-bit-pa' into for-next/core

* for-next/52-bit-pa:
  arm64: enable 52-bit physical address support
  arm64: allow ID map to be extended to 52 bits
  arm64: handle 52-bit physical addresses in page table entries
  arm64: don't open code page table entry creation
  arm64: head.S: handle 52-bit PAs in PTEs in early page table setup
  arm64: handle 52-bit addresses in TTBR
  arm64: limit PA size to supported range
  arm64: add kconfig symbol to configure physical address size
parents 6aef0fdd f77d2817
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -211,6 +211,11 @@ static inline bool __kvm_cpu_uses_extended_idmap(void)
	return false;
}

static inline unsigned long __kvm_idmap_ptrs_per_pgd(void)
{
	return PTRS_PER_PGD;
}

static inline void __kvm_extend_hypmap(pgd_t *boot_hyp_pgd,
				       pgd_t *hyp_pgd,
				       pgd_t *merged_hyp_pgd,
@@ -221,6 +226,8 @@ static inline unsigned int kvm_get_vmid_bits(void)
	return 8;
}

#define kvm_phys_to_vttbr(addr)		(addr)

#endif	/* !__ASSEMBLY__ */

#endif /* __ARM_KVM_MMU_H__ */
+29 −0
Original line number Diff line number Diff line
@@ -639,6 +639,35 @@ config ARM64_VA_BITS
	default 47 if ARM64_VA_BITS_47
	default 48 if ARM64_VA_BITS_48

choice
	prompt "Physical address space size"
	default ARM64_PA_BITS_48
	help
	  Choose the maximum physical address range that the kernel will
	  support.

config ARM64_PA_BITS_48
	bool "48-bit"

config ARM64_PA_BITS_52
	bool "52-bit (ARMv8.2)"
	depends on ARM64_64K_PAGES
	depends on ARM64_PAN || !ARM64_SW_TTBR0_PAN
	help
	  Enable support for a 52-bit physical address space, introduced as
	  part of the ARMv8.2-LPA extension.

	  With this enabled, the kernel will also continue to work on CPUs that
	  do not support ARMv8.2-LPA, but with some added memory overhead (and
	  minor performance overhead).

endchoice

config ARM64_PA_BITS
	int
	default 48 if ARM64_PA_BITS_48
	default 52 if ARM64_PA_BITS_52

config CPU_BIG_ENDIAN
       bool "Build big-endian kernel"
       help
+34 −2
Original line number Diff line number Diff line
@@ -343,10 +343,26 @@ alternative_endif
 * tcr_set_idmap_t0sz - update TCR.T0SZ so that we can load the ID map
 */
	.macro	tcr_set_idmap_t0sz, valreg, tmpreg
#ifndef CONFIG_ARM64_VA_BITS_48
	ldr_l	\tmpreg, idmap_t0sz
	bfi	\valreg, \tmpreg, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH
#endif
	.endm

/*
 * tcr_compute_pa_size - set TCR.(I)PS to the highest supported
 * ID_AA64MMFR0_EL1.PARange value
 *
 *	tcr:		register with the TCR_ELx value to be updated
 *	pos:		PARange bitfield position
 *	tmp{0,1}:	temporary registers
 */
	.macro	tcr_compute_pa_size, tcr, pos, tmp0, tmp1
	mrs	\tmp0, ID_AA64MMFR0_EL1
	// Narrow PARange to fit the PS field in TCR_ELx
	ubfx	\tmp0, \tmp0, #ID_AA64MMFR0_PARANGE_SHIFT, #3
	mov	\tmp1, #ID_AA64MMFR0_PARANGE_MAX
	cmp	\tmp0, \tmp1
	csel	\tmp0, \tmp1, \tmp0, hi
	bfi	\tcr, \tmp0, \pos, #3
	.endm

/*
@@ -489,4 +505,20 @@ alternative_else_nop_endif
#endif
	.endm

/*
 * Arrange a physical address in a TTBR register, taking care of 52-bit
 * addresses.
 *
 * 	phys:	physical address, preserved
 * 	ttbr:	returns the TTBR value
 */
	.macro	phys_to_ttbr, phys, ttbr
#ifdef CONFIG_ARM64_PA_BITS_52
	orr	\ttbr, \phys, \phys, lsr #46
	and	\ttbr, \ttbr, #TTBR_BADDR_MASK_52
#else
	mov	\ttbr, \phys
#endif
	.endm

#endif	/* __ASM_ASSEMBLER_H */
+18 −3
Original line number Diff line number Diff line
@@ -273,15 +273,26 @@ void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled);

static inline bool __kvm_cpu_uses_extended_idmap(void)
{
	return __cpu_uses_extended_idmap();
	return __cpu_uses_extended_idmap_level();
}

static inline unsigned long __kvm_idmap_ptrs_per_pgd(void)
{
	return idmap_ptrs_per_pgd;
}

/*
 * Can't use pgd_populate here, because the extended idmap adds an extra level
 * above CONFIG_PGTABLE_LEVELS (which is 2 or 3 if we're using the extended
 * idmap), and pgd_populate is only available if CONFIG_PGTABLE_LEVELS = 4.
 */
static inline void __kvm_extend_hypmap(pgd_t *boot_hyp_pgd,
				       pgd_t *hyp_pgd,
				       pgd_t *merged_hyp_pgd,
				       unsigned long hyp_idmap_start)
{
	int idmap_idx;
	u64 pgd_addr;

	/*
	 * Use the first entry to access the HYP mappings. It is
@@ -289,7 +300,8 @@ static inline void __kvm_extend_hypmap(pgd_t *boot_hyp_pgd,
	 * extended idmap.
	 */
	VM_BUG_ON(pgd_val(merged_hyp_pgd[0]));
	merged_hyp_pgd[0] = __pgd(__pa(hyp_pgd) | PMD_TYPE_TABLE);
	pgd_addr = __phys_to_pgd_val(__pa(hyp_pgd));
	merged_hyp_pgd[0] = __pgd(pgd_addr | PMD_TYPE_TABLE);

	/*
	 * Create another extended level entry that points to the boot HYP map,
@@ -299,7 +311,8 @@ static inline void __kvm_extend_hypmap(pgd_t *boot_hyp_pgd,
	 */
	idmap_idx = hyp_idmap_start >> VA_BITS;
	VM_BUG_ON(pgd_val(merged_hyp_pgd[idmap_idx]));
	merged_hyp_pgd[idmap_idx] = __pgd(__pa(boot_hyp_pgd) | PMD_TYPE_TABLE);
	pgd_addr = __phys_to_pgd_val(__pa(boot_hyp_pgd));
	merged_hyp_pgd[idmap_idx] = __pgd(pgd_addr | PMD_TYPE_TABLE);
}

static inline unsigned int kvm_get_vmid_bits(void)
@@ -309,5 +322,7 @@ static inline unsigned int kvm_get_vmid_bits(void)
	return (cpuid_feature_extract_unsigned_field(reg, ID_AA64MMFR1_VMIDBITS_SHIFT) == 2) ? 16 : 8;
}

#define kvm_phys_to_vttbr(addr)		phys_to_ttbr(addr)

#endif /* __ASSEMBLY__ */
#endif /* __ARM64_KVM_MMU_H__ */
+11 −1
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ static inline void contextidr_thread_switch(struct task_struct *next)
 */
static inline void cpu_set_reserved_ttbr0(void)
{
	unsigned long ttbr = __pa_symbol(empty_zero_page);
	unsigned long ttbr = phys_to_ttbr(__pa_symbol(empty_zero_page));

	write_sysreg(ttbr, ttbr0_el1);
	isb();
@@ -68,6 +68,7 @@ static inline void cpu_switch_mm(pgd_t *pgd, struct mm_struct *mm)
 * physical memory, in which case it will be smaller.
 */
extern u64 idmap_t0sz;
extern u64 idmap_ptrs_per_pgd;

static inline bool __cpu_uses_extended_idmap(void)
{
@@ -75,6 +76,15 @@ static inline bool __cpu_uses_extended_idmap(void)
		unlikely(idmap_t0sz != TCR_T0SZ(VA_BITS)));
}

/*
 * True if the extended ID map requires an extra level of translation table
 * to be configured.
 */
static inline bool __cpu_uses_extended_idmap_level(void)
{
	return ARM64_HW_PGTABLE_LEVELS((64 - idmap_t0sz)) > CONFIG_PGTABLE_LEVELS;
}

/*
 * Set TCR.T0SZ to its default value (based on VA_BITS)
 */
Loading