Skip to content

Commit 0ca84ae

Browse files
committed
LoongArch: Make {virt, phys, page, pfn} translation work with KFENCE
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>
1 parent 0871bc0 commit 0ca84ae

4 files changed

Lines changed: 51 additions & 8 deletions

File tree

arch/loongarch/include/asm/io.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,6 @@
1414
#include <asm/pgtable-bits.h>
1515
#include <asm/string.h>
1616

17-
/*
18-
* Change "struct page" to physical address.
19-
*/
20-
#define page_to_phys(page) ((phys_addr_t)page_to_pfn(page) << PAGE_SHIFT)
21-
2217
extern void __init __iomem *early_ioremap(u64 phys_addr, unsigned long size);
2318
extern void __init early_iounmap(void __iomem *addr, unsigned long size);
2419

@@ -73,6 +68,21 @@ extern void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t
7368

7469
#define __io_aw() mmiowb()
7570

71+
#ifdef CONFIG_KFENCE
72+
#define virt_to_phys(kaddr) \
73+
({ \
74+
(likely((unsigned long)kaddr < vm_map_base)) ? __pa((unsigned long)kaddr) : \
75+
page_to_phys(tlb_virt_to_page((unsigned long)kaddr)) + offset_in_page((unsigned long)kaddr);\
76+
})
77+
78+
#define phys_to_virt(paddr) \
79+
({ \
80+
extern char *__kfence_pool; \
81+
(unlikely(__kfence_pool == NULL)) ? __va((unsigned long)paddr) : \
82+
page_address(phys_to_page((unsigned long)paddr)) + offset_in_page((unsigned long)paddr);\
83+
})
84+
#endif
85+
7686
#include <asm-generic/io.h>
7787

7888
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE

arch/loongarch/include/asm/kfence.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
static inline bool arch_kfence_init_pool(void)
1717
{
1818
int err;
19+
char *kaddr, *vaddr;
1920
char *kfence_pool = __kfence_pool;
2021
struct vm_struct *area;
2122

@@ -35,6 +36,14 @@ static inline bool arch_kfence_init_pool(void)
3536
return false;
3637
}
3738

39+
kaddr = kfence_pool;
40+
vaddr = __kfence_pool;
41+
while (kaddr < kfence_pool + KFENCE_POOL_SIZE) {
42+
set_page_address(virt_to_page(kaddr), vaddr);
43+
kaddr += PAGE_SIZE;
44+
vaddr += PAGE_SIZE;
45+
}
46+
3847
return true;
3948
}
4049

arch/loongarch/include/asm/page.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,38 @@ typedef struct { unsigned long pgprot; } pgprot_t;
7878
struct page *dmw_virt_to_page(unsigned long kaddr);
7979
struct page *tlb_virt_to_page(unsigned long kaddr);
8080

81-
#define virt_to_pfn(kaddr) PFN_DOWN(PHYSADDR(kaddr))
81+
#define pfn_to_phys(pfn) __pfn_to_phys(pfn)
82+
#define phys_to_pfn(paddr) __phys_to_pfn(paddr)
83+
84+
#define page_to_phys(page) pfn_to_phys(page_to_pfn(page))
85+
#define phys_to_page(paddr) pfn_to_page(phys_to_pfn(paddr))
86+
87+
#ifndef CONFIG_KFENCE
88+
89+
#define page_to_virt(page) __va(page_to_phys(page))
90+
#define virt_to_page(kaddr) phys_to_page(__pa(kaddr))
91+
92+
#else
93+
94+
#define WANT_PAGE_VIRTUAL
95+
96+
#define page_to_virt(page) \
97+
({ \
98+
extern char *__kfence_pool; \
99+
(__kfence_pool == NULL) ? __va(page_to_phys(page)) : page_address(page); \
100+
})
82101

83102
#define virt_to_page(kaddr) \
84103
({ \
85104
(likely((unsigned long)kaddr < vm_map_base)) ? \
86105
dmw_virt_to_page((unsigned long)kaddr) : tlb_virt_to_page((unsigned long)kaddr);\
87106
})
88107

108+
#endif
109+
110+
#define pfn_to_virt(pfn) page_to_virt(pfn_to_page(pfn))
111+
#define virt_to_pfn(kaddr) page_to_pfn(virt_to_page(kaddr))
112+
89113
extern int __virt_addr_valid(volatile void *kaddr);
90114
#define virt_addr_valid(kaddr) __virt_addr_valid((volatile void *)(kaddr))
91115

arch/loongarch/mm/pgtable.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111

1212
struct page *dmw_virt_to_page(unsigned long kaddr)
1313
{
14-
return pfn_to_page(virt_to_pfn(kaddr));
14+
return phys_to_page(__pa(kaddr));
1515
}
1616
EXPORT_SYMBOL(dmw_virt_to_page);
1717

1818
struct page *tlb_virt_to_page(unsigned long kaddr)
1919
{
20-
return pfn_to_page(pte_pfn(*virt_to_kpte(kaddr)));
20+
return phys_to_page(pfn_to_phys(pte_pfn(*virt_to_kpte(kaddr))));
2121
}
2222
EXPORT_SYMBOL(tlb_virt_to_page);
2323

0 commit comments

Comments
 (0)