All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marco Elver <elver@google.com>
To: Zhenhua Huang <quic_zhenhuah@quicinc.com>
Cc: catalin.marinas@arm.com, will@kernel.org, glider@google.com,
	dvyukov@google.com, akpm@linux-foundation.org,
	robin.murphy@arm.com, mark.rutland@arm.com, jianyong.wu@arm.com,
	james.morse@arm.com, wangkefeng.wang@huawei.com,
	linux-arm-kernel@lists.infradead.org, kasan-dev@googlegroups.com,
	linux-mm@kvack.org, quic_pkondeti@quicinc.com,
	quic_guptap@quicinc.com, quic_tingweiz@quicinc.com
Subject: Re: [PATCH v9] mm,kfence: decouple kfence from page granularity mapping judgement
Date: Thu, 16 Mar 2023 11:06:50 +0100	[thread overview]
Message-ID: <ZBLqOv2RTScbydrj@elver.google.com> (raw)
In-Reply-To: <1678956620-26103-1-git-send-email-quic_zhenhuah@quicinc.com>

On Thu, Mar 16, 2023 at 04:50PM +0800, Zhenhua Huang wrote:
> Kfence only needs its pool to be mapped as page granularity, if it is
> inited early. Previous judgement was a bit over protected. From [1], Mark
> suggested to "just map the KFENCE region a page granularity". So I
> decouple it from judgement and do page granularity mapping for kfence
> pool only. Need to be noticed that late init of kfence pool still requires
> page granularity mapping.
> 
> Page granularity mapping in theory cost more(2M per 1GB) memory on arm64
> platform. Like what I've tested on QEMU(emulated 1GB RAM) with
> gki_defconfig, also turning off rodata protection:
> Before:
> [root@liebao ]# cat /proc/meminfo
> MemTotal:         999484 kB
> After:
> [root@liebao ]# cat /proc/meminfo
> MemTotal:        1001480 kB
> 
> To implement this, also relocate the kfence pool allocation before the
> linear mapping setting up, arm64_kfence_alloc_pool is to allocate phys
> addr, __kfence_pool is to be set after linear mapping set up.
> 
> LINK: [1] https://lore.kernel.org/linux-arm-kernel/Y+IsdrvDNILA59UN@FVFF77S0Q05N/
> Suggested-by: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Zhenhua Huang <quic_zhenhuah@quicinc.com>
> ---
>  arch/arm64/include/asm/kfence.h | 16 +++++++++++
>  arch/arm64/mm/mmu.c             | 59 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm64/mm/pageattr.c        |  9 +++++--
>  include/linux/kfence.h          |  1 +
>  mm/kfence/core.c                |  4 +++
>  5 files changed, 87 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kfence.h b/arch/arm64/include/asm/kfence.h
> index aa855c6..8143c91 100644
> --- a/arch/arm64/include/asm/kfence.h
> +++ b/arch/arm64/include/asm/kfence.h
> @@ -10,6 +10,22 @@
>  
>  #include <asm/set_memory.h>
>  
> +extern phys_addr_t early_kfence_pool;

This should not be accessible if !CONFIG_KFENCE.

> +#ifdef CONFIG_KFENCE
> +
> +extern char *__kfence_pool;
> +static inline void kfence_set_pool(phys_addr_t addr)
> +{
> +	__kfence_pool = phys_to_virt(addr);
> +}

kfence_set_pool() is redundant if it's for arm64 only, because we know
where it's needed, and there you could just access __kfence_pool
directly. So let's just remove this function. (Initially I thought you
want to provide it generally, also for other architectures.)

> +#else
> +
> +static inline void kfence_set_pool(phys_addr_t addr) { }
> +
> +#endif
> +
>  static inline bool arch_kfence_init_pool(void) { return true; }
[...]
> +#endif
> +
> +phys_addr_t early_kfence_pool;

This variable now exists in non-KFENCE builds, which is wrong.

>  static void __init map_mem(pgd_t *pgdp)
>  {
>  	static const u64 direct_map_end = _PAGE_END(VA_BITS_MIN);
> @@ -543,6 +587,10 @@ static void __init map_mem(pgd_t *pgdp)
>  	 */
>  	BUILD_BUG_ON(pgd_index(direct_map_end - 1) == pgd_index(direct_map_end));
>  
> +	early_kfence_pool = arm64_kfence_alloc_pool();
> +	if (early_kfence_pool)
> +		memblock_mark_nomap(early_kfence_pool, KFENCE_POOL_SIZE);
> +
>  	if (can_set_direct_map())
>  		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
>  
> @@ -608,6 +656,17 @@ static void __init map_mem(pgd_t *pgdp)
>  		}
>  	}
>  #endif
> +
> +	/* Kfence pool needs page-level mapping */
> +	if (early_kfence_pool) {
> +		__map_memblock(pgdp, early_kfence_pool,
> +			early_kfence_pool + KFENCE_POOL_SIZE,
> +			pgprot_tagged(PAGE_KERNEL),
> +			NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS);
> +		memblock_clear_nomap(early_kfence_pool, KFENCE_POOL_SIZE);
> +		/* kfence_pool really mapped now */
> +		kfence_set_pool(early_kfence_pool);
> +	}

This whole piece of code could also be wrapped in another function,
which becomes a no-op if !CONFIG_KFENCE. Then you also don't need to
provide the KFENCE_POOL_SIZE define for 0 if !CONFIG_KFENCE.

[...]
> +	 *
> +	 * Kfence pool requires page granularity mapping also if we init it
> +	 * late.
>  	 */
>  	return (rodata_enabled && rodata_full) || debug_pagealloc_enabled() ||
> -		IS_ENABLED(CONFIG_KFENCE);
> +	    (IS_ENABLED(CONFIG_KFENCE) && !early_kfence_pool);

Accessing a non-existent variable if !CONFIG_KFENCE works because the
compiler optimizes out the access, but is generally bad style.


I think the only issue that I have is that the separation between KFENCE
and non-KFENCE builds is not great.

At the end of the email are is a diff against your patch which would be
my suggested changes (while at it, I fixed up a bunch of other issues).
Untested, so if you decide to adopt these changes, please test.

Thanks,
-- Marco

------ >8 ------


diff --git a/arch/arm64/include/asm/kfence.h b/arch/arm64/include/asm/kfence.h
index 8143c91854e1..a81937fae9f6 100644
--- a/arch/arm64/include/asm/kfence.h
+++ b/arch/arm64/include/asm/kfence.h
@@ -10,22 +10,6 @@
 
 #include <asm/set_memory.h>
 
-extern phys_addr_t early_kfence_pool;
-
-#ifdef CONFIG_KFENCE
-
-extern char *__kfence_pool;
-static inline void kfence_set_pool(phys_addr_t addr)
-{
-	__kfence_pool = phys_to_virt(addr);
-}
-
-#else
-
-static inline void kfence_set_pool(phys_addr_t addr) { }
-
-#endif
-
 static inline bool arch_kfence_init_pool(void) { return true; }
 
 static inline bool kfence_protect_page(unsigned long addr, bool protect)
@@ -35,4 +19,14 @@ static inline bool kfence_protect_page(unsigned long addr, bool protect)
 	return true;
 }
 
+#ifdef CONFIG_KFENCE
+extern bool kfence_early_init;
+static inline bool arm64_kfence_can_set_direct_map(void)
+{
+	return !kfence_early_init;
+}
+#else /* CONFIG_KFENCE */
+static inline bool arm64_kfence_can_set_direct_map(void) { return false; }
+#endif /* CONFIG_KFENCE */
+
 #endif /* __ASM_KFENCE_H */
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 61944c7091f0..683958616ac1 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -528,17 +528,14 @@ static int __init enable_crash_mem_map(char *arg)
 early_param("crashkernel", enable_crash_mem_map);
 
 #ifdef CONFIG_KFENCE
+bool kfence_early_init = !!CONFIG_KFENCE_SAMPLE_INTERVAL;
 
-static bool kfence_early_init __initdata = !!CONFIG_KFENCE_SAMPLE_INTERVAL;
-/*
- * early_param can be parsed before linear mapping
- * set up
- */
-static int __init parse_kfence_early_init(char *p)
+/* early_param() will be parsed before map_mem() below. */
+static int __init parse_kfence_early_init(char *arg)
 {
 	int val;
 
-	if (get_option(&p, &val))
+	if (get_option(&arg, &val))
 		kfence_early_init = !!val;
 	return 0;
 }
@@ -552,22 +549,34 @@ static phys_addr_t arm64_kfence_alloc_pool(void)
 		return 0;
 
 	kfence_pool = memblock_phys_alloc(KFENCE_POOL_SIZE, PAGE_SIZE);
-	if (!kfence_pool)
+	if (!kfence_pool) {
 		pr_err("failed to allocate kfence pool\n");
+		kfence_early_init = false;
+		return 0;
+	}
+
+	/* Temporarily mark as NOMAP. */
+	memblock_mark_nomap(kfence_pool, KFENCE_POOL_SIZE);
 
 	return kfence_pool;
 }
 
-#else
-
-static phys_addr_t arm64_kfence_alloc_pool(void)
+static void arm64_kfence_map_pool(phys_addr_t kfence_pool, pgd_t *pgdp)
 {
-	return 0;
-}
-
-#endif
+	if (!kfence_pool)
+		return;
 
-phys_addr_t early_kfence_pool;
+	/* KFENCE pool needs page-level mapping. */
+	__map_memblock(pgdp, kfence_pool, kfence_pool + KFENCE_POOL_SIZE,
+		       pgprot_tagged(PAGE_KERNEL),
+		       NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS);
+	memblock_clear_nomap(kfence_pool, KFENCE_POOL_SIZE);
+	__kfence_pool = phys_to_virt(kfence_pool);
+}
+#else /* CONFIG_KFENCE */
+static inline phys_addr_t arm64_kfence_alloc_pool(void) { return 0; }
+static inline void arm64_kfence_map_pool(phys_addr_t kfence_pool, pgd_t *pgdp) { }
+#endif /* CONFIG_KFENCE */
 
 static void __init map_mem(pgd_t *pgdp)
 {
@@ -575,6 +584,7 @@ static void __init map_mem(pgd_t *pgdp)
 	phys_addr_t kernel_start = __pa_symbol(_stext);
 	phys_addr_t kernel_end = __pa_symbol(__init_begin);
 	phys_addr_t start, end;
+	phys_addr_t early_kfence_pool;
 	int flags = NO_EXEC_MAPPINGS;
 	u64 i;
 
@@ -588,8 +598,6 @@ static void __init map_mem(pgd_t *pgdp)
 	BUILD_BUG_ON(pgd_index(direct_map_end - 1) == pgd_index(direct_map_end));
 
 	early_kfence_pool = arm64_kfence_alloc_pool();
-	if (early_kfence_pool)
-		memblock_mark_nomap(early_kfence_pool, KFENCE_POOL_SIZE);
 
 	if (can_set_direct_map())
 		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
@@ -656,17 +664,7 @@ static void __init map_mem(pgd_t *pgdp)
 		}
 	}
 #endif
-
-	/* Kfence pool needs page-level mapping */
-	if (early_kfence_pool) {
-		__map_memblock(pgdp, early_kfence_pool,
-			early_kfence_pool + KFENCE_POOL_SIZE,
-			pgprot_tagged(PAGE_KERNEL),
-			NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS);
-		memblock_clear_nomap(early_kfence_pool, KFENCE_POOL_SIZE);
-		/* kfence_pool really mapped now */
-		kfence_set_pool(early_kfence_pool);
-	}
+	arm64_kfence_map_pool(early_kfence_pool, pgdp);
 }
 
 void mark_rodata_ro(void)
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
index 7ce5295cc6fb..aa8fd12cc96f 100644
--- a/arch/arm64/mm/pageattr.c
+++ b/arch/arm64/mm/pageattr.c
@@ -7,7 +7,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/vmalloc.h>
-#include <linux/kfence.h>
 
 #include <asm/cacheflush.h>
 #include <asm/set_memory.h>
@@ -28,11 +27,10 @@ bool can_set_direct_map(void)
 	 * mapped at page granularity, so that it is possible to
 	 * protect/unprotect single pages.
 	 *
-	 * Kfence pool requires page granularity mapping also if we init it
-	 * late.
+	 * KFENCE pool requires page-granular mapping if initialized late.
 	 */
 	return (rodata_enabled && rodata_full) || debug_pagealloc_enabled() ||
-	    (IS_ENABLED(CONFIG_KFENCE) && !early_kfence_pool);
+	       arm64_kfence_can_set_direct_map();
 }
 
 static int change_page_range(pte_t *ptep, unsigned long addr, void *data)
diff --git a/include/linux/kfence.h b/include/linux/kfence.h
index 91cbcc98e293..726857a4b680 100644
--- a/include/linux/kfence.h
+++ b/include/linux/kfence.h
@@ -222,7 +222,6 @@ bool __kfence_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *sla
 
 #else /* CONFIG_KFENCE */
 
-#define KFENCE_POOL_SIZE 0
 static inline bool is_kfence_address(const void *addr) { return false; }
 static inline void kfence_alloc_pool(void) { }
 static inline void kfence_init(void) { }
diff --git a/mm/kfence/core.c b/mm/kfence/core.c
index fab087d39633..e7f22af5e710 100644
--- a/mm/kfence/core.c
+++ b/mm/kfence/core.c
@@ -818,7 +818,7 @@ void __init kfence_alloc_pool(void)
 	if (!kfence_sample_interval)
 		return;
 
-	/* if the pool has already been initialized by arch, skip the below */
+	/* If the pool has already been initialized by arch, skip the below. */
 	if (__kfence_pool)
 		return;
 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

WARNING: multiple messages have this Message-ID (diff)
From: Marco Elver <elver@google.com>
To: Zhenhua Huang <quic_zhenhuah@quicinc.com>
Cc: catalin.marinas@arm.com, will@kernel.org, glider@google.com,
	dvyukov@google.com, akpm@linux-foundation.org,
	robin.murphy@arm.com, mark.rutland@arm.com, jianyong.wu@arm.com,
	james.morse@arm.com, wangkefeng.wang@huawei.com,
	linux-arm-kernel@lists.infradead.org, kasan-dev@googlegroups.com,
	linux-mm@kvack.org, quic_pkondeti@quicinc.com,
	quic_guptap@quicinc.com, quic_tingweiz@quicinc.com
Subject: Re: [PATCH v9] mm,kfence: decouple kfence from page granularity mapping judgement
Date: Thu, 16 Mar 2023 11:06:50 +0100	[thread overview]
Message-ID: <ZBLqOv2RTScbydrj@elver.google.com> (raw)
In-Reply-To: <1678956620-26103-1-git-send-email-quic_zhenhuah@quicinc.com>

On Thu, Mar 16, 2023 at 04:50PM +0800, Zhenhua Huang wrote:
> Kfence only needs its pool to be mapped as page granularity, if it is
> inited early. Previous judgement was a bit over protected. From [1], Mark
> suggested to "just map the KFENCE region a page granularity". So I
> decouple it from judgement and do page granularity mapping for kfence
> pool only. Need to be noticed that late init of kfence pool still requires
> page granularity mapping.
> 
> Page granularity mapping in theory cost more(2M per 1GB) memory on arm64
> platform. Like what I've tested on QEMU(emulated 1GB RAM) with
> gki_defconfig, also turning off rodata protection:
> Before:
> [root@liebao ]# cat /proc/meminfo
> MemTotal:         999484 kB
> After:
> [root@liebao ]# cat /proc/meminfo
> MemTotal:        1001480 kB
> 
> To implement this, also relocate the kfence pool allocation before the
> linear mapping setting up, arm64_kfence_alloc_pool is to allocate phys
> addr, __kfence_pool is to be set after linear mapping set up.
> 
> LINK: [1] https://lore.kernel.org/linux-arm-kernel/Y+IsdrvDNILA59UN@FVFF77S0Q05N/
> Suggested-by: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Zhenhua Huang <quic_zhenhuah@quicinc.com>
> ---
>  arch/arm64/include/asm/kfence.h | 16 +++++++++++
>  arch/arm64/mm/mmu.c             | 59 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm64/mm/pageattr.c        |  9 +++++--
>  include/linux/kfence.h          |  1 +
>  mm/kfence/core.c                |  4 +++
>  5 files changed, 87 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kfence.h b/arch/arm64/include/asm/kfence.h
> index aa855c6..8143c91 100644
> --- a/arch/arm64/include/asm/kfence.h
> +++ b/arch/arm64/include/asm/kfence.h
> @@ -10,6 +10,22 @@
>  
>  #include <asm/set_memory.h>
>  
> +extern phys_addr_t early_kfence_pool;

This should not be accessible if !CONFIG_KFENCE.

> +#ifdef CONFIG_KFENCE
> +
> +extern char *__kfence_pool;
> +static inline void kfence_set_pool(phys_addr_t addr)
> +{
> +	__kfence_pool = phys_to_virt(addr);
> +}

kfence_set_pool() is redundant if it's for arm64 only, because we know
where it's needed, and there you could just access __kfence_pool
directly. So let's just remove this function. (Initially I thought you
want to provide it generally, also for other architectures.)

> +#else
> +
> +static inline void kfence_set_pool(phys_addr_t addr) { }
> +
> +#endif
> +
>  static inline bool arch_kfence_init_pool(void) { return true; }
[...]
> +#endif
> +
> +phys_addr_t early_kfence_pool;

This variable now exists in non-KFENCE builds, which is wrong.

>  static void __init map_mem(pgd_t *pgdp)
>  {
>  	static const u64 direct_map_end = _PAGE_END(VA_BITS_MIN);
> @@ -543,6 +587,10 @@ static void __init map_mem(pgd_t *pgdp)
>  	 */
>  	BUILD_BUG_ON(pgd_index(direct_map_end - 1) == pgd_index(direct_map_end));
>  
> +	early_kfence_pool = arm64_kfence_alloc_pool();
> +	if (early_kfence_pool)
> +		memblock_mark_nomap(early_kfence_pool, KFENCE_POOL_SIZE);
> +
>  	if (can_set_direct_map())
>  		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
>  
> @@ -608,6 +656,17 @@ static void __init map_mem(pgd_t *pgdp)
>  		}
>  	}
>  #endif
> +
> +	/* Kfence pool needs page-level mapping */
> +	if (early_kfence_pool) {
> +		__map_memblock(pgdp, early_kfence_pool,
> +			early_kfence_pool + KFENCE_POOL_SIZE,
> +			pgprot_tagged(PAGE_KERNEL),
> +			NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS);
> +		memblock_clear_nomap(early_kfence_pool, KFENCE_POOL_SIZE);
> +		/* kfence_pool really mapped now */
> +		kfence_set_pool(early_kfence_pool);
> +	}

This whole piece of code could also be wrapped in another function,
which becomes a no-op if !CONFIG_KFENCE. Then you also don't need to
provide the KFENCE_POOL_SIZE define for 0 if !CONFIG_KFENCE.

[...]
> +	 *
> +	 * Kfence pool requires page granularity mapping also if we init it
> +	 * late.
>  	 */
>  	return (rodata_enabled && rodata_full) || debug_pagealloc_enabled() ||
> -		IS_ENABLED(CONFIG_KFENCE);
> +	    (IS_ENABLED(CONFIG_KFENCE) && !early_kfence_pool);

Accessing a non-existent variable if !CONFIG_KFENCE works because the
compiler optimizes out the access, but is generally bad style.


I think the only issue that I have is that the separation between KFENCE
and non-KFENCE builds is not great.

At the end of the email are is a diff against your patch which would be
my suggested changes (while at it, I fixed up a bunch of other issues).
Untested, so if you decide to adopt these changes, please test.

Thanks,
-- Marco

------ >8 ------


diff --git a/arch/arm64/include/asm/kfence.h b/arch/arm64/include/asm/kfence.h
index 8143c91854e1..a81937fae9f6 100644
--- a/arch/arm64/include/asm/kfence.h
+++ b/arch/arm64/include/asm/kfence.h
@@ -10,22 +10,6 @@
 
 #include <asm/set_memory.h>
 
-extern phys_addr_t early_kfence_pool;
-
-#ifdef CONFIG_KFENCE
-
-extern char *__kfence_pool;
-static inline void kfence_set_pool(phys_addr_t addr)
-{
-	__kfence_pool = phys_to_virt(addr);
-}
-
-#else
-
-static inline void kfence_set_pool(phys_addr_t addr) { }
-
-#endif
-
 static inline bool arch_kfence_init_pool(void) { return true; }
 
 static inline bool kfence_protect_page(unsigned long addr, bool protect)
@@ -35,4 +19,14 @@ static inline bool kfence_protect_page(unsigned long addr, bool protect)
 	return true;
 }
 
+#ifdef CONFIG_KFENCE
+extern bool kfence_early_init;
+static inline bool arm64_kfence_can_set_direct_map(void)
+{
+	return !kfence_early_init;
+}
+#else /* CONFIG_KFENCE */
+static inline bool arm64_kfence_can_set_direct_map(void) { return false; }
+#endif /* CONFIG_KFENCE */
+
 #endif /* __ASM_KFENCE_H */
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 61944c7091f0..683958616ac1 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -528,17 +528,14 @@ static int __init enable_crash_mem_map(char *arg)
 early_param("crashkernel", enable_crash_mem_map);
 
 #ifdef CONFIG_KFENCE
+bool kfence_early_init = !!CONFIG_KFENCE_SAMPLE_INTERVAL;
 
-static bool kfence_early_init __initdata = !!CONFIG_KFENCE_SAMPLE_INTERVAL;
-/*
- * early_param can be parsed before linear mapping
- * set up
- */
-static int __init parse_kfence_early_init(char *p)
+/* early_param() will be parsed before map_mem() below. */
+static int __init parse_kfence_early_init(char *arg)
 {
 	int val;
 
-	if (get_option(&p, &val))
+	if (get_option(&arg, &val))
 		kfence_early_init = !!val;
 	return 0;
 }
@@ -552,22 +549,34 @@ static phys_addr_t arm64_kfence_alloc_pool(void)
 		return 0;
 
 	kfence_pool = memblock_phys_alloc(KFENCE_POOL_SIZE, PAGE_SIZE);
-	if (!kfence_pool)
+	if (!kfence_pool) {
 		pr_err("failed to allocate kfence pool\n");
+		kfence_early_init = false;
+		return 0;
+	}
+
+	/* Temporarily mark as NOMAP. */
+	memblock_mark_nomap(kfence_pool, KFENCE_POOL_SIZE);
 
 	return kfence_pool;
 }
 
-#else
-
-static phys_addr_t arm64_kfence_alloc_pool(void)
+static void arm64_kfence_map_pool(phys_addr_t kfence_pool, pgd_t *pgdp)
 {
-	return 0;
-}
-
-#endif
+	if (!kfence_pool)
+		return;
 
-phys_addr_t early_kfence_pool;
+	/* KFENCE pool needs page-level mapping. */
+	__map_memblock(pgdp, kfence_pool, kfence_pool + KFENCE_POOL_SIZE,
+		       pgprot_tagged(PAGE_KERNEL),
+		       NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS);
+	memblock_clear_nomap(kfence_pool, KFENCE_POOL_SIZE);
+	__kfence_pool = phys_to_virt(kfence_pool);
+}
+#else /* CONFIG_KFENCE */
+static inline phys_addr_t arm64_kfence_alloc_pool(void) { return 0; }
+static inline void arm64_kfence_map_pool(phys_addr_t kfence_pool, pgd_t *pgdp) { }
+#endif /* CONFIG_KFENCE */
 
 static void __init map_mem(pgd_t *pgdp)
 {
@@ -575,6 +584,7 @@ static void __init map_mem(pgd_t *pgdp)
 	phys_addr_t kernel_start = __pa_symbol(_stext);
 	phys_addr_t kernel_end = __pa_symbol(__init_begin);
 	phys_addr_t start, end;
+	phys_addr_t early_kfence_pool;
 	int flags = NO_EXEC_MAPPINGS;
 	u64 i;
 
@@ -588,8 +598,6 @@ static void __init map_mem(pgd_t *pgdp)
 	BUILD_BUG_ON(pgd_index(direct_map_end - 1) == pgd_index(direct_map_end));
 
 	early_kfence_pool = arm64_kfence_alloc_pool();
-	if (early_kfence_pool)
-		memblock_mark_nomap(early_kfence_pool, KFENCE_POOL_SIZE);
 
 	if (can_set_direct_map())
 		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
@@ -656,17 +664,7 @@ static void __init map_mem(pgd_t *pgdp)
 		}
 	}
 #endif
-
-	/* Kfence pool needs page-level mapping */
-	if (early_kfence_pool) {
-		__map_memblock(pgdp, early_kfence_pool,
-			early_kfence_pool + KFENCE_POOL_SIZE,
-			pgprot_tagged(PAGE_KERNEL),
-			NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS);
-		memblock_clear_nomap(early_kfence_pool, KFENCE_POOL_SIZE);
-		/* kfence_pool really mapped now */
-		kfence_set_pool(early_kfence_pool);
-	}
+	arm64_kfence_map_pool(early_kfence_pool, pgdp);
 }
 
 void mark_rodata_ro(void)
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
index 7ce5295cc6fb..aa8fd12cc96f 100644
--- a/arch/arm64/mm/pageattr.c
+++ b/arch/arm64/mm/pageattr.c
@@ -7,7 +7,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/vmalloc.h>
-#include <linux/kfence.h>
 
 #include <asm/cacheflush.h>
 #include <asm/set_memory.h>
@@ -28,11 +27,10 @@ bool can_set_direct_map(void)
 	 * mapped at page granularity, so that it is possible to
 	 * protect/unprotect single pages.
 	 *
-	 * Kfence pool requires page granularity mapping also if we init it
-	 * late.
+	 * KFENCE pool requires page-granular mapping if initialized late.
 	 */
 	return (rodata_enabled && rodata_full) || debug_pagealloc_enabled() ||
-	    (IS_ENABLED(CONFIG_KFENCE) && !early_kfence_pool);
+	       arm64_kfence_can_set_direct_map();
 }
 
 static int change_page_range(pte_t *ptep, unsigned long addr, void *data)
diff --git a/include/linux/kfence.h b/include/linux/kfence.h
index 91cbcc98e293..726857a4b680 100644
--- a/include/linux/kfence.h
+++ b/include/linux/kfence.h
@@ -222,7 +222,6 @@ bool __kfence_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *sla
 
 #else /* CONFIG_KFENCE */
 
-#define KFENCE_POOL_SIZE 0
 static inline bool is_kfence_address(const void *addr) { return false; }
 static inline void kfence_alloc_pool(void) { }
 static inline void kfence_init(void) { }
diff --git a/mm/kfence/core.c b/mm/kfence/core.c
index fab087d39633..e7f22af5e710 100644
--- a/mm/kfence/core.c
+++ b/mm/kfence/core.c
@@ -818,7 +818,7 @@ void __init kfence_alloc_pool(void)
 	if (!kfence_sample_interval)
 		return;
 
-	/* if the pool has already been initialized by arch, skip the below */
+	/* If the pool has already been initialized by arch, skip the below. */
 	if (__kfence_pool)
 		return;
 


  parent reply	other threads:[~2023-03-16 10:09 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-16  8:50 [PATCH v9] mm,kfence: decouple kfence from page granularity mapping judgement Zhenhua Huang
2023-03-16  8:50 ` Zhenhua Huang
2023-03-16  9:58 ` Pavan Kondeti
2023-03-16  9:58   ` Pavan Kondeti
2023-03-16 10:44   ` Zhenhua Huang
2023-03-16 10:44     ` Zhenhua Huang
2023-03-16 10:56     ` Alexander Potapenko
2023-03-16 11:17       ` Zhenhua Huang
2023-03-16 11:17         ` Zhenhua Huang
2023-03-16 10:06 ` Marco Elver [this message]
2023-03-16 10:06   ` Marco Elver
2023-03-16 10:36   ` Zhenhua Huang
2023-03-16 10:36     ` Zhenhua Huang
2023-03-16 12:19     ` Zhenhua Huang
2023-03-16 12:19       ` Zhenhua Huang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZBLqOv2RTScbydrj@elver.google.com \
    --to=elver@google.com \
    --cc=akpm@linux-foundation.org \
    --cc=catalin.marinas@arm.com \
    --cc=dvyukov@google.com \
    --cc=glider@google.com \
    --cc=james.morse@arm.com \
    --cc=jianyong.wu@arm.com \
    --cc=kasan-dev@googlegroups.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-mm@kvack.org \
    --cc=mark.rutland@arm.com \
    --cc=quic_guptap@quicinc.com \
    --cc=quic_pkondeti@quicinc.com \
    --cc=quic_tingweiz@quicinc.com \
    --cc=quic_zhenhuah@quicinc.com \
    --cc=robin.murphy@arm.com \
    --cc=wangkefeng.wang@huawei.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.