lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <3dbb68bb-2aa6-477c-a903-188a26596fb1@arm.com>
Date: Wed, 16 Oct 2024 09:17:16 +0100
From: Ryan Roberts <ryan.roberts@....com>
To: Michael Kelley <mhklinux@...look.com>,
 Andrew Morton <akpm@...ux-foundation.org>,
 Anshuman Khandual <anshuman.khandual@....com>,
 Ard Biesheuvel <ardb@...nel.org>, Catalin Marinas <catalin.marinas@....com>,
 David Hildenbrand <david@...hat.com>, Greg Marsden
 <greg.marsden@...cle.com>, Ivan Ivanov <ivan.ivanov@...e.com>,
 Kalesh Singh <kaleshsingh@...gle.com>, Marc Zyngier <maz@...nel.org>,
 Mark Rutland <mark.rutland@....com>, Matthias Brugger <mbrugger@...e.com>,
 Miroslav Benes <mbenes@...e.cz>, Oliver Upton <oliver.upton@...ux.dev>,
 Will Deacon <will@...nel.org>
Cc: "kvmarm@...ts.linux.dev" <kvmarm@...ts.linux.dev>,
 "linux-arm-kernel@...ts.infradead.org"
 <linux-arm-kernel@...ts.infradead.org>,
 "linux-efi@...r.kernel.org" <linux-efi@...r.kernel.org>,
 "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
 "linux-mm@...ck.org" <linux-mm@...ck.org>
Subject: Re: [RFC PATCH v1 57/57] arm64: Enable boot-time page size selection

On 15/10/2024 18:52, Michael Kelley wrote:
> From: Ryan Roberts <ryan.roberts@....com> Sent: Monday, October 14, 2024 3:59 AM
>>
>> Introduce a new Kconfig, ARM64_BOOT_TIME_PAGE_SIZE, which can be
>> selected instead of a page size. When selected, the resulting kernel's
>> page size can be configured at boot via the command line.
>>
>> For now, boot-time page size kernels are limited to 48-bit VA, since
>> more work is required to support LPA2. Additionally MMAP_RND_BITS and
>> SECTION_SIZE_BITS are configured for the worst case (64K pages). Future
>> work could be implemented to be able to configure these at boot time for
>> optimial page size-specific values.
>>
>> Signed-off-by: Ryan Roberts <ryan.roberts@....com>
>> ---
>>
>> ***NOTE***
>> Any confused maintainers may want to read the cover note here for context:
>> https://lore.kernel.org/all/20241014105514.3206191-1-ryan.roberts@arm.com/
>>
>>  arch/arm64/Kconfig                         | 26 ++++++++++---
>>  arch/arm64/include/asm/kvm_hyp.h           | 11 ++++++
>>  arch/arm64/include/asm/pgtable-geometry.h  | 22 ++++++++++-
>>  arch/arm64/include/asm/pgtable-hwdef.h     |  6 +--
>>  arch/arm64/include/asm/pgtable.h           | 10 ++++-
>>  arch/arm64/include/asm/sparsemem.h         |  4 ++
>>  arch/arm64/kernel/image-vars.h             | 11 ++++++
>>  arch/arm64/kernel/image.h                  |  4 ++
>>  arch/arm64/kernel/pi/map_kernel.c          | 45 ++++++++++++++++++++++
>>  arch/arm64/kvm/arm.c                       | 10 +++++
>>  arch/arm64/kvm/hyp/nvhe/Makefile           |  1 +
>>  arch/arm64/kvm/hyp/nvhe/pgtable-geometry.c | 16 ++++++++
>>  arch/arm64/mm/Makefile                     |  1 +
>>  arch/arm64/mm/pgd.c                        | 10 +++--
>>  arch/arm64/mm/pgtable-geometry.c           | 24 ++++++++++++
>>  drivers/firmware/efi/libstub/arm64.c       |  3 +-
>>  16 files changed, 187 insertions(+), 17 deletions(-)
>>  create mode 100644 arch/arm64/kvm/hyp/nvhe/pgtable-geometry.c
>>  create mode 100644 arch/arm64/mm/pgtable-geometry.c
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index a2f8ff354ca67..573d308741169 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -121,6 +121,7 @@ config ARM64
>>  	select BUILDTIME_TABLE_SORT
>>  	select CLONE_BACKWARDS
>>  	select COMMON_CLK
>> +	select CONSTRUCTORS if ARM64_BOOT_TIME_PAGE_SIZE
>>  	select CPU_PM if (SUSPEND || CPU_IDLE)
>>  	select CPUMASK_OFFSTACK if NR_CPUS > 256
>>  	select CRC32
>> @@ -284,18 +285,20 @@ config MMU
>>
>>  config ARM64_CONT_PTE_SHIFT
>>  	int
>> +	depends on !ARM64_BOOT_TIME_PAGE_SIZE
>>  	default 5 if PAGE_SIZE_64KB
>>  	default 7 if PAGE_SIZE_16KB
>>  	default 4
>>
>>  config ARM64_CONT_PMD_SHIFT
>>  	int
>> +	depends on !ARM64_BOOT_TIME_PAGE_SIZE
>>  	default 5 if PAGE_SIZE_64KB
>>  	default 5 if PAGE_SIZE_16KB
>>  	default 4
>>
>>  config ARCH_MMAP_RND_BITS_MIN
>> -	default 14 if PAGE_SIZE_64KB
>> +	default 14 if ARM64_64K_PAGES || ARM64_BOOT_TIME_PAGE_SIZE
>>  	default 16 if PAGE_SIZE_16KB
>>  	default 18
>>
>> @@ -306,15 +309,15 @@ config ARCH_MMAP_RND_BITS_MAX
>>  	default 24 if ARM64_VA_BITS=39
>>  	default 27 if ARM64_VA_BITS=42
>>  	default 30 if ARM64_VA_BITS=47
>> -	default 29 if ARM64_VA_BITS=48 && ARM64_64K_PAGES
>> +	default 29 if ARM64_VA_BITS=48 && (ARM64_64K_PAGES ||
>> ARM64_BOOT_TIME_PAGE_SIZE)
>>  	default 31 if ARM64_VA_BITS=48 && ARM64_16K_PAGES
>>  	default 33 if ARM64_VA_BITS=48
>> -	default 14 if ARM64_64K_PAGES
>> +	default 14 if ARM64_64K_PAGES || ARM64_BOOT_TIME_PAGE_SIZE
>>  	default 16 if ARM64_16K_PAGES
>>  	default 18
>>
>>  config ARCH_MMAP_RND_COMPAT_BITS_MIN
>> -	default 7 if ARM64_64K_PAGES
>> +	default 7 if ARM64_64K_PAGES || ARM64_BOOT_TIME_PAGE_SIZE
>>  	default 9 if ARM64_16K_PAGES
>>  	default 11
>>
>> @@ -362,6 +365,7 @@ config FIX_EARLYCON_MEM
>>
>>  config PGTABLE_LEVELS
>>  	int
>> +	default 4 if ARM64_BOOT_TIME_PAGE_SIZE # Advertise max supported levels
>>  	default 2 if ARM64_16K_PAGES && ARM64_VA_BITS_36
>>  	default 2 if ARM64_64K_PAGES && ARM64_VA_BITS_42
>>  	default 3 if ARM64_64K_PAGES && (ARM64_VA_BITS_48 ||
>> ARM64_VA_BITS_52)
>> @@ -1316,6 +1320,14 @@ config ARM64_64K_PAGES
>>  	  look-up. AArch32 emulation requires applications compiled
>>  	  with 64K aligned segments.
>>
>> +config ARM64_BOOT_TIME_PAGE_SIZE
>> +	bool "Boot-time selection"
>> +	select HAVE_PAGE_SIZE_64KB # Advertise largest page size to core
>> +	help
>> +	  Select desired page size (4KB, 16KB or 64KB) at boot-time via the
>> +	  kernel command line option "arm64.pagesize=4k", "arm64.pagesize=16k"
>> +	  or "arm64.pagesize=64k".
>> +
>>  endchoice
>>
>>  choice
>> @@ -1348,6 +1360,7 @@ config ARM64_VA_BITS_48
>>  config ARM64_VA_BITS_52
>>  	bool "52-bit"
>>  	depends on ARM64_PAN || !ARM64_SW_TTBR0_PAN
>> +	depends on !ARM64_BOOT_TIME_PAGE_SIZE
>>  	help
>>  	  Enable 52-bit virtual addressing for userspace when explicitly
>>  	  requested via a hint to mmap(). The kernel will also use 52-bit
>> @@ -1588,9 +1601,10 @@ config XEN
>>  # 4K  |       27          |      12      |       15             |         10              |
>>  # 16K |       27          |      14      |       13             |         11              |
>>  # 64K |       29          |      16      |       13             |         13              |
>> +# BOOT|       29          |    16 (max)  |       13             |         13              |
>>  config ARCH_FORCE_MAX_ORDER
>>  	int
>> -	default "13" if ARM64_64K_PAGES
>> +	default "13" if ARM64_64K_PAGES || ARM64_BOOT_TIME_PAGE_SIZE
>>  	default "11" if ARM64_16K_PAGES
>>  	default "10"
>>  	help
>> @@ -1663,7 +1677,7 @@ config ARM64_TAGGED_ADDR_ABI
>>
>>  menuconfig COMPAT
>>  	bool "Kernel support for 32-bit EL0"
>> -	depends on ARM64_4K_PAGES || EXPERT
>> +	depends on ARM64_4K_PAGES || ARM64_BOOT_TIME_PAGE_SIZE || EXPERT
>>  	select HAVE_UID16
>>  	select OLD_SIGSUSPEND3
>>  	select COMPAT_OLD_SIGACTION
>> diff --git a/arch/arm64/include/asm/kvm_hyp.h
>> b/arch/arm64/include/asm/kvm_hyp.h
>> index c838309e4ec47..9397a14642afa 100644
>> --- a/arch/arm64/include/asm/kvm_hyp.h
>> +++ b/arch/arm64/include/asm/kvm_hyp.h
>> @@ -145,4 +145,15 @@ extern unsigned long kvm_nvhe_sym(__icache_flags);
>>  extern unsigned int kvm_nvhe_sym(kvm_arm_vmid_bits);
>>  extern unsigned int kvm_nvhe_sym(kvm_host_sve_max_vl);
>>
>> +#ifdef CONFIG_ARM64_BOOT_TIME_PAGE_SIZE
>> +extern int kvm_nvhe_sym(ptg_page_shift);
>> +extern int kvm_nvhe_sym(ptg_pmd_shift);
>> +extern int kvm_nvhe_sym(ptg_pud_shift);
>> +extern int kvm_nvhe_sym(ptg_p4d_shift);
>> +extern int kvm_nvhe_sym(ptg_pgdir_shift);
>> +extern int kvm_nvhe_sym(ptg_cont_pte_shift);
>> +extern int kvm_nvhe_sym(ptg_cont_pmd_shift);
>> +extern int kvm_nvhe_sym(ptg_pgtable_levels);
>> +#endif /* CONFIG_ARM64_BOOT_TIME_PAGE_SIZE */
>> +
>>  #endif /* __ARM64_KVM_HYP_H__ */
>> diff --git a/arch/arm64/include/asm/pgtable-geometry.h
>> b/arch/arm64/include/asm/pgtable-geometry.h
>> index 62fe125909c08..18a8c8d499ecc 100644
>> --- a/arch/arm64/include/asm/pgtable-geometry.h
>> +++ b/arch/arm64/include/asm/pgtable-geometry.h
>> @@ -6,16 +6,33 @@
>>  #define ARM64_PAGE_SHIFT_16K	14
>>  #define ARM64_PAGE_SHIFT_64K	16
>>
>> +#ifdef CONFIG_ARM64_BOOT_TIME_PAGE_SIZE
>> +#define PAGE_SHIFT_MIN		ARM64_PAGE_SHIFT_4K
>> +#define PAGE_SHIFT_MAX		ARM64_PAGE_SHIFT_64K
>> +#else /* CONFIG_ARM64_BOOT_TIME_PAGE_SIZE */
>>  #define PAGE_SHIFT_MIN		CONFIG_PAGE_SHIFT
>> +#define PAGE_SHIFT_MAX		CONFIG_PAGE_SHIFT
>> +#endif /* CONFIG_ARM64_BOOT_TIME_PAGE_SIZE */
>> +
>>  #define PAGE_SIZE_MIN		(_AC(1, UL) << PAGE_SHIFT_MIN)
>>  #define PAGE_MASK_MIN		(~(PAGE_SIZE_MIN-1))
>> -
>> -#define PAGE_SHIFT_MAX		CONFIG_PAGE_SHIFT
>>  #define PAGE_SIZE_MAX		(_AC(1, UL) << PAGE_SHIFT_MAX)
>>  #define PAGE_MASK_MAX		(~(PAGE_SIZE_MAX-1))
>>
>>  #include <asm-generic/pgtable-geometry.h>
>>
>> +#ifdef CONFIG_ARM64_BOOT_TIME_PAGE_SIZE
>> +#ifndef __ASSEMBLY__
>> +extern int ptg_page_shift;
>> +extern int ptg_pmd_shift;
>> +extern int ptg_pud_shift;
>> +extern int ptg_p4d_shift;
>> +extern int ptg_pgdir_shift;
>> +extern int ptg_cont_pte_shift;
>> +extern int ptg_cont_pmd_shift;
>> +extern int ptg_pgtable_levels;
>> +#endif /* __ASSEMBLY__ */
>> +#else /* CONFIG_ARM64_BOOT_TIME_PAGE_SIZE */
>>  #define ptg_page_shift		CONFIG_PAGE_SHIFT
>>  #define ptg_pmd_shift		ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
>>  #define ptg_pud_shift		ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
>> @@ -24,5 +41,6 @@
>>  #define ptg_cont_pte_shift	(CONFIG_ARM64_CONT_PTE_SHIFT + PAGE_SHIFT)
>>  #define ptg_cont_pmd_shift	(CONFIG_ARM64_CONT_PMD_SHIFT + PMD_SHIFT)
>>  #define ptg_pgtable_levels	CONFIG_PGTABLE_LEVELS
>> +#endif /* CONFIG_ARM64_BOOT_TIME_PAGE_SIZE */
>>
>>  #endif /* ASM_PGTABLE_GEOMETRY_H */
>> diff --git a/arch/arm64/include/asm/pgtable-hwdef.h
>> b/arch/arm64/include/asm/pgtable-hwdef.h
>> index ca8bcbc1fe220..da5404617acbf 100644
>> --- a/arch/arm64/include/asm/pgtable-hwdef.h
>> +++ b/arch/arm64/include/asm/pgtable-hwdef.h
>> @@ -52,7 +52,7 @@
>>  #define PMD_SHIFT		ptg_pmd_shift
>>  #define PMD_SIZE		(_AC(1, UL) << PMD_SHIFT)
>>  #define PMD_MASK		(~(PMD_SIZE-1))
>> -#define PTRS_PER_PMD		(1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_PMD		(ptg_pgtable_levels > 2 ? (1 << (PAGE_SHIFT -
>> 3)) : 1)
>>  #define MAX_PTRS_PER_PMD	(1 << (PAGE_SHIFT_MAX - 3))
>>  #endif
>>
>> @@ -63,7 +63,7 @@
>>  #define PUD_SHIFT		ptg_pud_shift
>>  #define PUD_SIZE		(_AC(1, UL) << PUD_SHIFT)
>>  #define PUD_MASK		(~(PUD_SIZE-1))
>> -#define PTRS_PER_PUD		(1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_PUD		(ptg_pgtable_levels > 3 ? (1 << (PAGE_SHIFT -
>> 3)) : 1)
>>  #define MAX_PTRS_PER_PUD	(1 << (PAGE_SHIFT_MAX - 3))
>>  #endif
>>
>> @@ -71,7 +71,7 @@
>>  #define P4D_SHIFT		ptg_p4d_shift
>>  #define P4D_SIZE		(_AC(1, UL) << P4D_SHIFT)
>>  #define P4D_MASK		(~(P4D_SIZE-1))
>> -#define PTRS_PER_P4D		(1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_P4D		(ptg_pgtable_levels > 4 ? (1 << (PAGE_SHIFT -
>> 3)) : 1)
>>  #define MAX_PTRS_PER_P4D	(1 << (PAGE_SHIFT_MAX - 3))
>>  #endif
>>
>> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
>> index 8ead41da715b0..ad9f75f5cc29a 100644
>> --- a/arch/arm64/include/asm/pgtable.h
>> +++ b/arch/arm64/include/asm/pgtable.h
>> @@ -755,7 +755,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
>>
>>  static __always_inline bool pgtable_l3_enabled(void)
>>  {
>> -	return true;
>> +	return ptg_pgtable_levels > 2;
>>  }
>>
>>  static inline bool mm_pmd_folded(const struct mm_struct *mm)
>> @@ -888,6 +888,8 @@ static inline bool pgtable_l3_enabled(void) { return false; }
>>
>>  static __always_inline bool pgtable_l4_enabled(void)
>>  {
>> +	if (IS_ENABLED(CONFIG_ARM64_BOOT_TIME_PAGE_SIZE))
>> +		return ptg_pgtable_levels > 3;
>>  	if (CONFIG_PGTABLE_LEVELS > 4 || !IS_ENABLED(CONFIG_ARM64_LPA2))
>>  		return true;
>>  	if (!alternative_has_cap_likely(ARM64_ALWAYS_BOOT))
>> @@ -935,6 +937,8 @@ static inline phys_addr_t p4d_page_paddr(p4d_t p4d)
>>
>>  static inline pud_t *p4d_to_folded_pud(p4d_t *p4dp, unsigned long addr)
>>  {
>> +	if (IS_ENABLED(CONFIG_ARM64_BOOT_TIME_PAGE_SIZE))
>> +		return (pud_t *)p4dp;
>>  	return (pud_t *)PTR_ALIGN_DOWN(p4dp, PAGE_SIZE) + pud_index(addr);
>>  }
>>
>> @@ -1014,6 +1018,8 @@ static inline bool pgtable_l4_enabled(void) { return false; }
>>
>>  static __always_inline bool pgtable_l5_enabled(void)
>>  {
>> +	if (IS_ENABLED(CONFIG_ARM64_BOOT_TIME_PAGE_SIZE))
>> +		return ptg_pgtable_levels > 4;
>>  	if (!alternative_has_cap_likely(ARM64_ALWAYS_BOOT))
>>  		return vabits_actual == VA_BITS;
>>  	return alternative_has_cap_unlikely(ARM64_HAS_VA52);
>> @@ -1059,6 +1065,8 @@ static inline phys_addr_t pgd_page_paddr(pgd_t pgd)
>>
>>  static inline p4d_t *pgd_to_folded_p4d(pgd_t *pgdp, unsigned long addr)
>>  {
>> +	if (IS_ENABLED(CONFIG_ARM64_BOOT_TIME_PAGE_SIZE))
>> +		return (p4d_t *)pgdp;
>>  	return (p4d_t *)PTR_ALIGN_DOWN(pgdp, PAGE_SIZE) + p4d_index(addr);
>>  }
>>
>> diff --git a/arch/arm64/include/asm/sparsemem.h
>> b/arch/arm64/include/asm/sparsemem.h
>> index a05fdd54014f7..2daf1263ba638 100644
>> --- a/arch/arm64/include/asm/sparsemem.h
>> +++ b/arch/arm64/include/asm/sparsemem.h
>> @@ -17,6 +17,10 @@
>>   * entries could not be created for vmemmap mappings.
>>   * 16K follows 4K for simplicity.
>>   */
>> +#ifdef CONFIG_ARM64_BOOT_TIME_PAGE_SIZE
>> +#define SECTION_SIZE_BITS	29
>> +#else
>>  #define SECTION_SIZE_BITS	(PAGE_SIZE == SZ_64K ? 29 : 27)
>> +#endif
>>
>>  #endif
>> diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
>> index a168f3337446f..9968320f83bc4 100644
>> --- a/arch/arm64/kernel/image-vars.h
>> +++ b/arch/arm64/kernel/image-vars.h
>> @@ -36,6 +36,17 @@ PROVIDE(__pi___memcpy			=
>> __pi_memcpy);
>>  PROVIDE(__pi___memmove			= __pi_memmove);
>>  PROVIDE(__pi___memset			= __pi_memset);
>>
>> +#ifdef CONFIG_ARM64_BOOT_TIME_PAGE_SIZE
>> +PROVIDE(__pi_ptg_page_shift		= ptg_page_shift);
>> +PROVIDE(__pi_ptg_pmd_shift		= ptg_pmd_shift);
>> +PROVIDE(__pi_ptg_pud_shift		= ptg_pud_shift);
>> +PROVIDE(__pi_ptg_p4d_shift		= ptg_p4d_shift);
>> +PROVIDE(__pi_ptg_pgdir_shift		= ptg_pgdir_shift);
>> +PROVIDE(__pi_ptg_cont_pte_shift		= ptg_cont_pte_shift);
>> +PROVIDE(__pi_ptg_cont_pmd_shift		= ptg_cont_pmd_shift);
>> +PROVIDE(__pi_ptg_pgtable_levels		= ptg_pgtable_levels);
>> +#endif /* CONFIG_ARM64_BOOT_TIME_PAGE_SIZE */
>> +
>>  PROVIDE(__pi_id_aa64isar1_override	= id_aa64isar1_override);
>>  PROVIDE(__pi_id_aa64isar2_override	= id_aa64isar2_override);
>>  PROVIDE(__pi_id_aa64mmfr0_override	= id_aa64mmfr0_override);
>> diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h
>> index 7bc3ba8979019..01502fc3b891b 100644
>> --- a/arch/arm64/kernel/image.h
>> +++ b/arch/arm64/kernel/image.h
>> @@ -47,7 +47,11 @@
>>  #define __HEAD_FLAG_BE		ARM64_IMAGE_FLAG_LE
>>  #endif
>>
>> +#ifdef CONFIG_ARM64_BOOT_TIME_PAGE_SIZE
>> +#define __HEAD_FLAG_PAGE_SIZE	0
>> +#else
>>  #define __HEAD_FLAG_PAGE_SIZE	((PAGE_SHIFT - 10) / 2)
>> +#endif
>>
>>  #define __HEAD_FLAG_PHYS_BASE	1
>>
>> diff --git a/arch/arm64/kernel/pi/map_kernel.c b/arch/arm64/kernel/pi/map_kernel.c
>> index deb8cd50b0b0c..22b3c70e04f9c 100644
>> --- a/arch/arm64/kernel/pi/map_kernel.c
>> +++ b/arch/arm64/kernel/pi/map_kernel.c
>> @@ -221,6 +221,49 @@ static void __init map_fdt(u64 fdt, int page_shift)
>>  	dsb(ishst);
>>  }
>>
>> +#ifdef CONFIG_ARM64_BOOT_TIME_PAGE_SIZE
>> +static void __init ptg_init(int page_shift)
>> +{
>> +	ptg_pgtable_levels =
>> +		__ARM64_HW_PGTABLE_LEVELS(page_shift,
>> CONFIG_ARM64_VA_BITS);
>> +
>> +	ptg_pgdir_shift = __ARM64_HW_PGTABLE_LEVEL_SHIFT(page_shift,
>> +				4 - ptg_pgtable_levels);
>> +
>> +	ptg_p4d_shift = ptg_pgtable_levels >= 5 ?
>> +				__ARM64_HW_PGTABLE_LEVEL_SHIFT(page_shift, 0) :
>> +				ptg_pgdir_shift;
>> +
>> +	ptg_pud_shift = ptg_pgtable_levels >= 4 ?
>> +				__ARM64_HW_PGTABLE_LEVEL_SHIFT(page_shift, 1) :
>> +				ptg_pgdir_shift;
>> +
>> +	ptg_pmd_shift = ptg_pgtable_levels >= 3 ?
>> +				__ARM64_HW_PGTABLE_LEVEL_SHIFT(page_shift, 2) :
>> +				ptg_pgdir_shift;
>> +
>> +	ptg_page_shift = page_shift;
>> +
>> +	switch (page_shift) {
>> +	case ARM64_PAGE_SHIFT_64K:
>> +		ptg_cont_pte_shift = ptg_page_shift + 5;
>> +		ptg_cont_pmd_shift = ptg_pmd_shift + 5;
>> +		break;
>> +	case ARM64_PAGE_SHIFT_16K:
>> +		ptg_cont_pte_shift = ptg_page_shift + 7;
>> +		ptg_cont_pmd_shift = ptg_pmd_shift + 5;
>> +		break;
>> +	default: /* ARM64_PAGE_SHIFT_4K */
>> +		ptg_cont_pte_shift = ptg_page_shift + 4;
>> +		ptg_cont_pmd_shift = ptg_pmd_shift + 4;
>> +	}
>> +}
>> +#else /* CONFIG_ARM64_BOOT_TIME_PAGE_SIZE */
>> +static inline void ptg_init(int page_shift)
>> +{
>> +}
>> +#endif /* CONFIG_ARM64_BOOT_TIME_PAGE_SIZE */
>> +
>>  asmlinkage void __init early_map_kernel(u64 boot_status, void *fdt)
>>  {
>>  	static char const chosen_str[] __initconst = "/chosen";
>> @@ -247,6 +290,8 @@ asmlinkage void __init early_map_kernel(u64 boot_status, void
>> *fdt)
>>  	if (!page_shift)
>>  		page_shift = early_page_shift;
>>
>> +	ptg_init(page_shift);
>> +
>>  	if (va_bits > 48) {
>>  		u64 page_size = early_page_size(page_shift);
>>
>> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
>> index 9bef7638342ef..c835a50b8b768 100644
>> --- a/arch/arm64/kvm/arm.c
>> +++ b/arch/arm64/kvm/arm.c
>> @@ -2424,6 +2424,16 @@ static void kvm_hyp_init_symbols(void)
>>  	kvm_nvhe_sym(id_aa64smfr0_el1_sys_val) =
>> read_sanitised_ftr_reg(SYS_ID_AA64SMFR0_EL1);
>>  	kvm_nvhe_sym(__icache_flags) = __icache_flags;
>>  	kvm_nvhe_sym(kvm_arm_vmid_bits) = kvm_arm_vmid_bits;
>> +#ifdef CONFIG_ARM64_BOOT_TIME_PAGE_SIZE
>> +	kvm_nvhe_sym(ptg_page_shift) = ptg_page_shift;
>> +	kvm_nvhe_sym(ptg_pmd_shift) = ptg_pmd_shift;
>> +	kvm_nvhe_sym(ptg_pud_shift) = ptg_pud_shift;
>> +	kvm_nvhe_sym(ptg_p4d_shift) = ptg_p4d_shift;
>> +	kvm_nvhe_sym(ptg_pgdir_shift) = ptg_pgdir_shift;
>> +	kvm_nvhe_sym(ptg_cont_pte_shift) = ptg_cont_pte_shift;
>> +	kvm_nvhe_sym(ptg_cont_pmd_shift) = ptg_cont_pmd_shift;
>> +	kvm_nvhe_sym(ptg_pgtable_levels) = ptg_pgtable_levels;
>> +#endif /* CONFIG_ARM64_BOOT_TIME_PAGE_SIZE */
>>  }
>>
>>  static int __init kvm_hyp_init_protection(u32 hyp_va_bits)
>> diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile
>> b/arch/arm64/kvm/hyp/nvhe/Makefile
>> index b43426a493df5..a8fcbb84c7996 100644
>> --- a/arch/arm64/kvm/hyp/nvhe/Makefile
>> +++ b/arch/arm64/kvm/hyp/nvhe/Makefile
>> @@ -27,6 +27,7 @@ hyp-obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o hyp-
>> init.o host.o
>>  	 cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o stacktrace.o ffa.o
>>  hyp-obj-y += ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../entry.o \
>>  	 ../fpsimd.o ../hyp-entry.o ../exception.o ../pgtable.o
>> +hyp-obj-$(CONFIG_ARM64_BOOT_TIME_PAGE_SIZE) += pgtable-geometry.o
>>  hyp-obj-$(CONFIG_LIST_HARDENED) += list_debug.o
>>  hyp-obj-y += $(lib-objs)
>>
>> diff --git a/arch/arm64/kvm/hyp/nvhe/pgtable-geometry.c
>> b/arch/arm64/kvm/hyp/nvhe/pgtable-geometry.c
>> new file mode 100644
>> index 0000000000000..17f807450a31a
>> --- /dev/null
>> +++ b/arch/arm64/kvm/hyp/nvhe/pgtable-geometry.c
>> @@ -0,0 +1,16 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (C) 2024 ARM Ltd.
>> + */
>> +
>> +#include <linux/cache.h>
>> +#include <asm/pgtable-geometry.h>
>> +
>> +int ptg_page_shift __ro_after_init;
>> +int ptg_pmd_shift __ro_after_init;
>> +int ptg_pud_shift __ro_after_init;
>> +int ptg_p4d_shift __ro_after_init;
>> +int ptg_pgdir_shift __ro_after_init;
>> +int ptg_cont_pte_shift __ro_after_init;
>> +int ptg_cont_pmd_shift __ro_after_init;
>> +int ptg_pgtable_levels __ro_after_init;
>> diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile
>> index 60454256945b8..2ba30d06b35fe 100644
>> --- a/arch/arm64/mm/Makefile
>> +++ b/arch/arm64/mm/Makefile
>> @@ -3,6 +3,7 @@ obj-y				:= dma-mapping.o extable.o
>> fault.o init.o \
>>  				   cache.o copypage.o flush.o \
>>  				   ioremap.o mmap.o pgd.o mmu.o \
>>  				   context.o proc.o pageattr.o fixmap.o
>> +obj-$(CONFIG_ARM64_BOOT_TIME_PAGE_SIZE) += pgtable-geometry.o
>>  obj-$(CONFIG_ARM64_CONTPTE)	+= contpte.o
>>  obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
>>  obj-$(CONFIG_PTDUMP_CORE)	+= ptdump.o
>> diff --git a/arch/arm64/mm/pgd.c b/arch/arm64/mm/pgd.c
>> index 4b106510358b1..c052d0dcb0c69 100644
>> --- a/arch/arm64/mm/pgd.c
>> +++ b/arch/arm64/mm/pgd.c
>> @@ -21,10 +21,12 @@ static bool pgdir_is_page_size(void)
>>  {
>>  	if (PGD_SIZE == PAGE_SIZE)
>>  		return true;
>> -	if (CONFIG_PGTABLE_LEVELS == 4)
>> -		return !pgtable_l4_enabled();
>> -	if (CONFIG_PGTABLE_LEVELS == 5)
>> -		return !pgtable_l5_enabled();
>> +	if (!IS_ENABLED(CONFIG_ARM64_BOOT_TIME_PAGE_SIZE)) {
>> +		if (CONFIG_PGTABLE_LEVELS == 4)
>> +			return !pgtable_l4_enabled();
>> +		if (CONFIG_PGTABLE_LEVELS == 5)
>> +			return !pgtable_l5_enabled();
>> +	}
>>  	return false;
>>  }
>>
>> diff --git a/arch/arm64/mm/pgtable-geometry.c b/arch/arm64/mm/pgtable-
>> geometry.c
>> new file mode 100644
>> index 0000000000000..ba50637f1e9d0
>> --- /dev/null
>> +++ b/arch/arm64/mm/pgtable-geometry.c
>> @@ -0,0 +1,24 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (C) 2024 ARM Ltd.
>> + */
>> +
>> +#include <linux/cache.h>
>> +#include <asm/pgtable-geometry.h>
>> +
>> +/*
>> + * TODO: These should be __ro_after_init, but we need to write to them from the
>> + * pi code where they are mapped in the early page table as read-only.
>> + * __ro_after_init doesn't become writable until later when the swapper pgtable
>> + * is fully set up. We should update the early page table to map __ro_after_init
>> + * as read-write.
>> + */
>> +
>> +int ptg_page_shift __read_mostly;
>> +int ptg_pmd_shift __read_mostly;
> 
> I found that ptg_page_shift and ptg_pmd_shift need
> EXPORT_SYMBOL_GPL for cases where code compiled
> as a module is using PAGE_SIZE/PAGE_SHIFT or
> PMD_SIZE/PMD_SHIFT. Some of the others below
> might also need EXPORT_SYMBOL_GPL.

Ahh good spot - thanks! I'll fix this in the next version.

I wonder if these should really be EXPORT_SYMBOL() and not limited to GPL? I
guess having access to PAGE_SIZE is a pretty fundamental thing? Anybody know the
policy here?

Thanks,
Ryan

> 
> Michael
> 
>> +int ptg_pud_shift __read_mostly;
>> +int ptg_p4d_shift __read_mostly;
>> +int ptg_pgdir_shift __read_mostly;
>> +int ptg_cont_pte_shift __read_mostly;
>> +int ptg_cont_pmd_shift __read_mostly;
>> +int ptg_pgtable_levels __read_mostly;
>> diff --git a/drivers/firmware/efi/libstub/arm64.c
>> b/drivers/firmware/efi/libstub/arm64.c
>> index e57cd3de0a00f..8db9dba7d5423 100644
>> --- a/drivers/firmware/efi/libstub/arm64.c
>> +++ b/drivers/firmware/efi/libstub/arm64.c
>> @@ -68,7 +68,8 @@ efi_status_t check_platform_features(void)
>>  		efi_novamap = true;
>>
>>  	/* UEFI mandates support for 4 KB granularity, no need to check */
>> -	if (IS_ENABLED(CONFIG_ARM64_4K_PAGES))
>> +	if (IS_ENABLED(CONFIG_ARM64_4K_PAGES) ||
>> +	    IS_ENABLED(CONFIG_ARM64_BOOT_TIME_PAGE_SIZE))
>>  		return EFI_SUCCESS;
>>
>>  	tg = (read_cpuid(ID_AA64MMFR0_EL1) >>
>> ID_AA64MMFR0_EL1_TGRAN_SHIFT) & 0xf;
>> --
>> 2.43.0
>>
> 


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ