linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Make {virt, phys, page, pfn} translation work with KFENCE for LoongArch
@ 2024-04-04 13:36 Huacai Chen
  2024-04-04 13:36 ` [PATCH 1/3] mm: Move lowmem_page_address() a little later Huacai Chen
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Huacai Chen @ 2024-04-04 13:36 UTC (permalink / raw)
  To: Andrew Morton, Huacai Chen
  Cc: loongarch, linux-mm, Xuefeng Li, Guo Ren, Xuerui Wang,
	Jiaxun Yang, linux-kernel, loongson-kernel, Huacai Chen

On LoongArch kmalloc() range is DMW-mapped rather than TLB-mapped, so
KFENCE remap __kfence_pool to the TLB-mappd range.

To make all drivers work, {virt, phys, page, pfn} translation functions
are overriden (part of them already done, others done in this series):
1, virt_to_pfn()/pfn_to_virt();
2, virt_to_page()/page_to_virt();
3, virt_to_phys()/phys_to_virt().
 
Since LoongArch overrides page_to_virt() which use page_address() in the
KFENCE case (by defining WANT_PAGE_VIRTUAL/HASHED_PAGE_VIRTUAL). So move
lowmem_page_address() a little later to avoid such build errors:

error: implicit declaration of function ‘page_address’.

Huacai Chen(3):
 mm: Move lowmem_page_address() a little later.
 LoongArch: Make {virt, phys, page, pfn} translation work with KFENCE
 LoongArch: Make virt_addr_valid()/__virt_addr_valid() work with KFENCE

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
2.27.0



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] mm: Move lowmem_page_address() a little later
  2024-04-04 13:36 [PATCH 0/3] Make {virt, phys, page, pfn} translation work with KFENCE for LoongArch Huacai Chen
@ 2024-04-04 13:36 ` Huacai Chen
  2024-04-04 18:25   ` Andrew Morton
  2024-04-04 13:36 ` [PATCH 2/3] LoongArch: Make {virt, phys, page, pfn} translation work with KFENCE Huacai Chen
  2024-04-04 13:36 ` [PATCH 3/3] LoongArch: Make virt_addr_valid()/__virt_addr_valid() " Huacai Chen
  2 siblings, 1 reply; 6+ messages in thread
From: Huacai Chen @ 2024-04-04 13:36 UTC (permalink / raw)
  To: Andrew Morton, Huacai Chen
  Cc: loongarch, linux-mm, Xuefeng Li, Guo Ren, Xuerui Wang,
	Jiaxun Yang, linux-kernel, loongson-kernel, Huacai Chen

LoongArch will override page_to_virt() which use page_address() in the
KFENCE case (by defining WANT_PAGE_VIRTUAL/HASHED_PAGE_VIRTUAL). So move
lowmem_page_address() a little later to avoid such build errors:

error: implicit declaration of function 'page_address'.

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 include/linux/mm.h | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 0436b919f1c7..7b0ee64225de 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2207,11 +2207,6 @@ static inline int arch_make_folio_accessible(struct folio *folio)
  */
 #include <linux/vmstat.h>
 
-static __always_inline void *lowmem_page_address(const struct page *page)
-{
-	return page_to_virt(page);
-}
-
 #if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL)
 #define HASHED_PAGE_VIRTUAL
 #endif
@@ -2234,6 +2229,11 @@ void set_page_address(struct page *page, void *virtual);
 void page_address_init(void);
 #endif
 
+static __always_inline void *lowmem_page_address(const struct page *page)
+{
+	return page_to_virt(page);
+}
+
 #if !defined(HASHED_PAGE_VIRTUAL) && !defined(WANT_PAGE_VIRTUAL)
 #define page_address(page) lowmem_page_address(page)
 #define set_page_address(page, address)  do { } while(0)
-- 
2.43.0



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 2/3] LoongArch: Make {virt, phys, page, pfn} translation work with KFENCE
  2024-04-04 13:36 [PATCH 0/3] Make {virt, phys, page, pfn} translation work with KFENCE for LoongArch Huacai Chen
  2024-04-04 13:36 ` [PATCH 1/3] mm: Move lowmem_page_address() a little later Huacai Chen
@ 2024-04-04 13:36 ` Huacai Chen
  2024-04-04 13:36 ` [PATCH 3/3] LoongArch: Make virt_addr_valid()/__virt_addr_valid() " Huacai Chen
  2 siblings, 0 replies; 6+ messages in thread
From: Huacai Chen @ 2024-04-04 13:36 UTC (permalink / raw)
  To: Andrew Morton, Huacai Chen
  Cc: loongarch, linux-mm, Xuefeng Li, Guo Ren, Xuerui Wang,
	Jiaxun Yang, linux-kernel, loongson-kernel, Huacai Chen

KFENCE changes virt_to_page() to be able to translate tlb mapped virtual
addresses, but forget to change virt_to_phys()/phys_to_virt() and other
translation functions as well. This patch fix it, otherwise some drivers
(such as nvme and virtio-blk) cannot work with KFENCE.

All {virt, phys, page, pfn} translation functions are updated:
1, virt_to_pfn()/pfn_to_virt();
2, virt_to_page()/page_to_virt();
3, virt_to_phys()/phys_to_virt().

DMW/TLB mapped addresses are distinguished by comparing the vaddress
with vm_map_base in virt_to_xyz(), and we define WANT_PAGE_VIRTUAL in
the KFENCE case for the reverse translations, xyz_to_virt().

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 arch/loongarch/include/asm/io.h     | 20 +++++++++++++++-----
 arch/loongarch/include/asm/kfence.h |  9 +++++++++
 arch/loongarch/include/asm/page.h   | 26 +++++++++++++++++++++++++-
 arch/loongarch/mm/pgtable.c         |  4 ++--
 4 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/arch/loongarch/include/asm/io.h b/arch/loongarch/include/asm/io.h
index 4a8adcca329b..c2f9979b2979 100644
--- a/arch/loongarch/include/asm/io.h
+++ b/arch/loongarch/include/asm/io.h
@@ -14,11 +14,6 @@
 #include <asm/pgtable-bits.h>
 #include <asm/string.h>
 
-/*
- * Change "struct page" to physical address.
- */
-#define page_to_phys(page)	((phys_addr_t)page_to_pfn(page) << PAGE_SHIFT)
-
 extern void __init __iomem *early_ioremap(u64 phys_addr, unsigned long size);
 extern void __init early_iounmap(void __iomem *addr, unsigned long size);
 
@@ -73,6 +68,21 @@ extern void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t
 
 #define __io_aw() mmiowb()
 
+#ifdef CONFIG_KFENCE
+#define virt_to_phys(kaddr)								\
+({											\
+	(likely((unsigned long)kaddr < vm_map_base)) ? __pa((unsigned long)kaddr) :	\
+	page_to_phys(tlb_virt_to_page((unsigned long)kaddr)) + offset_in_page((unsigned long)kaddr);\
+})
+
+#define phys_to_virt(paddr)								\
+({											\
+	extern char *__kfence_pool;							\
+	(unlikely(__kfence_pool == NULL)) ? __va((unsigned long)paddr) :		\
+	page_address(phys_to_page((unsigned long)paddr)) + offset_in_page((unsigned long)paddr);\
+})
+#endif
+
 #include <asm-generic/io.h>
 
 #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
diff --git a/arch/loongarch/include/asm/kfence.h b/arch/loongarch/include/asm/kfence.h
index 6c82aea1c993..a6a5760da3a3 100644
--- a/arch/loongarch/include/asm/kfence.h
+++ b/arch/loongarch/include/asm/kfence.h
@@ -16,6 +16,7 @@
 static inline bool arch_kfence_init_pool(void)
 {
 	int err;
+	char *kaddr, *vaddr;
 	char *kfence_pool = __kfence_pool;
 	struct vm_struct *area;
 
@@ -35,6 +36,14 @@ static inline bool arch_kfence_init_pool(void)
 		return false;
 	}
 
+	kaddr = kfence_pool;
+	vaddr = __kfence_pool;
+	while (kaddr < kfence_pool + KFENCE_POOL_SIZE) {
+		set_page_address(virt_to_page(kaddr), vaddr);
+		kaddr += PAGE_SIZE;
+		vaddr += PAGE_SIZE;
+	}
+
 	return true;
 }
 
diff --git a/arch/loongarch/include/asm/page.h b/arch/loongarch/include/asm/page.h
index 44027060c54a..e85df33f11c7 100644
--- a/arch/loongarch/include/asm/page.h
+++ b/arch/loongarch/include/asm/page.h
@@ -78,7 +78,26 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 struct page *dmw_virt_to_page(unsigned long kaddr);
 struct page *tlb_virt_to_page(unsigned long kaddr);
 
-#define virt_to_pfn(kaddr)	PFN_DOWN(PHYSADDR(kaddr))
+#define pfn_to_phys(pfn)	__pfn_to_phys(pfn)
+#define phys_to_pfn(paddr)	__phys_to_pfn(paddr)
+
+#define page_to_phys(page)	pfn_to_phys(page_to_pfn(page))
+#define phys_to_page(paddr)	pfn_to_page(phys_to_pfn(paddr))
+
+#ifndef CONFIG_KFENCE
+
+#define page_to_virt(page)	__va(page_to_phys(page))
+#define virt_to_page(kaddr)	phys_to_page(__pa(kaddr))
+
+#else
+
+#define WANT_PAGE_VIRTUAL
+
+#define page_to_virt(page)								\
+({											\
+	extern char *__kfence_pool;							\
+	(__kfence_pool == NULL) ? __va(page_to_phys(page)) : page_address(page);	\
+})
 
 #define virt_to_page(kaddr)								\
 ({											\
@@ -86,6 +105,11 @@ struct page *tlb_virt_to_page(unsigned long kaddr);
 	dmw_virt_to_page((unsigned long)kaddr) : tlb_virt_to_page((unsigned long)kaddr);\
 })
 
+#endif
+
+#define pfn_to_virt(pfn)	page_to_virt(pfn_to_page(pfn))
+#define virt_to_pfn(kaddr)	page_to_pfn(virt_to_page(kaddr))
+
 extern int __virt_addr_valid(volatile void *kaddr);
 #define virt_addr_valid(kaddr)	__virt_addr_valid((volatile void *)(kaddr))
 
diff --git a/arch/loongarch/mm/pgtable.c b/arch/loongarch/mm/pgtable.c
index 2aae72e63871..bda018150000 100644
--- a/arch/loongarch/mm/pgtable.c
+++ b/arch/loongarch/mm/pgtable.c
@@ -11,13 +11,13 @@
 
 struct page *dmw_virt_to_page(unsigned long kaddr)
 {
-	return pfn_to_page(virt_to_pfn(kaddr));
+	return phys_to_page(__pa(kaddr));
 }
 EXPORT_SYMBOL(dmw_virt_to_page);
 
 struct page *tlb_virt_to_page(unsigned long kaddr)
 {
-	return pfn_to_page(pte_pfn(*virt_to_kpte(kaddr)));
+	return phys_to_page(pfn_to_phys(pte_pfn(*virt_to_kpte(kaddr))));
 }
 EXPORT_SYMBOL(tlb_virt_to_page);
 
-- 
2.43.0



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 3/3] LoongArch: Make virt_addr_valid()/__virt_addr_valid() work with KFENCE
  2024-04-04 13:36 [PATCH 0/3] Make {virt, phys, page, pfn} translation work with KFENCE for LoongArch Huacai Chen
  2024-04-04 13:36 ` [PATCH 1/3] mm: Move lowmem_page_address() a little later Huacai Chen
  2024-04-04 13:36 ` [PATCH 2/3] LoongArch: Make {virt, phys, page, pfn} translation work with KFENCE Huacai Chen
@ 2024-04-04 13:36 ` Huacai Chen
  2 siblings, 0 replies; 6+ messages in thread
From: Huacai Chen @ 2024-04-04 13:36 UTC (permalink / raw)
  To: Andrew Morton, Huacai Chen
  Cc: loongarch, linux-mm, Xuefeng Li, Guo Ren, Xuerui Wang,
	Jiaxun Yang, linux-kernel, loongson-kernel, Huacai Chen,
	Guenter Roeck

When enabling both CONFIG_KFENCE and CONFIG_DEBUG_SG, I get the
following backtraces when running LongArch kernels.

[    2.496257] kernel BUG at include/linux/scatterlist.h:187!
...
[    2.501925] Call Trace:
[    2.501950] [<9000000004ad59c4>] sg_init_one+0xac/0xc0
[    2.502204] [<9000000004a438f8>] do_test_kpp+0x278/0x6e4
[    2.502353] [<9000000004a43dd4>] alg_test_kpp+0x70/0xf4
[    2.502494] [<9000000004a41b48>] alg_test+0x128/0x690
[    2.502631] [<9000000004a3d898>] cryptomgr_test+0x20/0x40
[    2.502775] [<90000000041b4508>] kthread+0x138/0x158
[    2.502912] [<9000000004161c48>] ret_from_kernel_thread+0xc/0xa4

The backtrace is always similar but not exactly the same. It is always
triggered from cryptomgr_test, but not always from the same test.

Analysis shows that with CONFIG_KFENCE active, the address returned from
kmalloc() and friends is not always below vm_map_base. It is allocated
by kfence_alloc() which at least sometimes seems to get its memory from
an address space above vm_map_base. This causes __virt_addr_valid() to
return false for the affected objects.

Let __virt_addr_valid() return 1 for kfence pool addresses, this make
virt_addr_valid()/__virt_addr_valid() work with KFENCE.

Reported-by: Guenter Roeck <linux@roeck-us.net>
Suggested-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 arch/loongarch/mm/mmap.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/loongarch/mm/mmap.c b/arch/loongarch/mm/mmap.c
index a9630a81b38a..89af7c12e8c0 100644
--- a/arch/loongarch/mm/mmap.c
+++ b/arch/loongarch/mm/mmap.c
@@ -4,6 +4,7 @@
  */
 #include <linux/export.h>
 #include <linux/io.h>
+#include <linux/kfence.h>
 #include <linux/memblock.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
@@ -111,6 +112,9 @@ int __virt_addr_valid(volatile void *kaddr)
 {
 	unsigned long vaddr = (unsigned long)kaddr;
 
+	if (is_kfence_address((void *)kaddr))
+		return 1;
+
 	if ((vaddr < PAGE_OFFSET) || (vaddr >= vm_map_base))
 		return 0;
 
-- 
2.43.0



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] mm: Move lowmem_page_address() a little later
  2024-04-04 13:36 ` [PATCH 1/3] mm: Move lowmem_page_address() a little later Huacai Chen
@ 2024-04-04 18:25   ` Andrew Morton
  2024-04-05  9:21     ` Huacai Chen
  0 siblings, 1 reply; 6+ messages in thread
From: Andrew Morton @ 2024-04-04 18:25 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Huacai Chen, loongarch, linux-mm, Xuefeng Li, Guo Ren,
	Xuerui Wang, Jiaxun Yang, linux-kernel, loongson-kernel

On Thu,  4 Apr 2024 21:36:34 +0800 Huacai Chen <chenhuacai@loongson.cn> wrote:

> LoongArch will override page_to_virt() which use page_address() in the
> KFENCE case (by defining WANT_PAGE_VIRTUAL/HASHED_PAGE_VIRTUAL). So move
> lowmem_page_address() a little later to avoid such build errors:
> 
> error: implicit declaration of function 'page_address'.
> 

Acked-by: Andrew Morton <akpm@linux-foundation.org>

Please ensure that it spends adequate time in linux-next for the
compilation testing.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] mm: Move lowmem_page_address() a little later
  2024-04-04 18:25   ` Andrew Morton
@ 2024-04-05  9:21     ` Huacai Chen
  0 siblings, 0 replies; 6+ messages in thread
From: Huacai Chen @ 2024-04-05  9:21 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Huacai Chen, loongarch, linux-mm, Xuefeng Li, Guo Ren,
	Xuerui Wang, Jiaxun Yang, linux-kernel, loongson-kernel

On Fri, Apr 5, 2024 at 2:25 AM Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Thu,  4 Apr 2024 21:36:34 +0800 Huacai Chen <chenhuacai@loongson.cn> wrote:
>
> > LoongArch will override page_to_virt() which use page_address() in the
> > KFENCE case (by defining WANT_PAGE_VIRTUAL/HASHED_PAGE_VIRTUAL). So move
> > lowmem_page_address() a little later to avoid such build errors:
> >
> > error: implicit declaration of function 'page_address'.
> >
>
> Acked-by: Andrew Morton <akpm@linux-foundation.org>
>
> Please ensure that it spends adequate time in linux-next for the
> compilation testing.
OK, thanks.

Huacai


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2024-04-05  9:21 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-04 13:36 [PATCH 0/3] Make {virt, phys, page, pfn} translation work with KFENCE for LoongArch Huacai Chen
2024-04-04 13:36 ` [PATCH 1/3] mm: Move lowmem_page_address() a little later Huacai Chen
2024-04-04 18:25   ` Andrew Morton
2024-04-05  9:21     ` Huacai Chen
2024-04-04 13:36 ` [PATCH 2/3] LoongArch: Make {virt, phys, page, pfn} translation work with KFENCE Huacai Chen
2024-04-04 13:36 ` [PATCH 3/3] LoongArch: Make virt_addr_valid()/__virt_addr_valid() " Huacai Chen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox