arm64: tlbflush: avoid writing RES0 bits
PATCH v3 1/1 arm64: tlbflush: avoid writing RES0 bits
Several of the bits of the TLBI register operand are RES0 per the ARM ARM, so TLBI operations should avoid writing non-zero values to these bits.
This patch adds a macro __TLBI_VADDR(addr, asid) that creates the operand register in the correct format and honors the RES0 bits.
--- arch/arm64/include/asm/tlbflush.h | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-)
arch/arm64/include/asm/tlbflush.h +17 -8
@@ -60,6 +60,15 @@__tlbi (op, (arg) |USER_ASID_FLAG ); \ }while (0 ) +/* This macro creates a properly formatted VA operand for the TLBI */ +#define __TLBI_VADDR(addr, asid) \ + ({ \ +unsigned long __ta = (addr) >>12 ; \ + __ta &=GENMASK_ULL (43 ,0 ); \ + __ta |= (unsigned long )(asid) <<48 ; \ + __ta; \ + }) +/* * TLB Management * ==============
@@ -117,7 +126,7 @@ static inline void flush_tlb_all(void)static inline void flush_tlb_mm (struct mm_struct *mm) { -unsigned long asid =ASID (mm) <<48 ; +unsigned long asid =__TLBI_VADDR (0 ,ASID (mm));dsb (ishst);__tlbi (aside1is, asid);
@@ -128,7 +137,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm)static inline void flush_tlb_page (struct vm_area_struct *vma,unsigned long uaddr) { -unsigned long addr = uaddr >>12 | (ASID (vma->vm_mm) <<48 ); +unsigned long addr =__TLBI_VADDR (uaddr,ASID (vma->vm_mm));dsb (ishst);__tlbi (vale1is, addr);
@@ -146,7 +155,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end, bool last_level) { - unsigned long asid = ASID(vma->vm_mm) << 48; + unsigned long asid = ASID(vma->vm_mm);unsigned long addr;if ((end - start) >MAX_TLB_RANGE ) {
@@ -154,8 +163,8 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,return ; } - start = asid | (start >>12 ); - end = asid | (end >>12 ); + start =__TLBI_VADDR (start, asid); + end =__TLBI_VADDR (end, asid);dsb (ishst);for (addr = start; addr < end; addr +=1 << (PAGE_SHIFT -12 )) {
@@ -185,8 +194,8 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long endreturn ; } - start >>=12 ; - end >>=12 ; + start =__TLBI_VADDR (start,0 ); + end =__TLBI_VADDR (end,0 );dsb (ishst);for (addr = start; addr < end; addr +=1 << (PAGE_SHIFT -12 ))
@@ -202,7 +211,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long endstatic inline void __flush_tlb_pgtable (struct mm_struct *mm,unsigned long uaddr) { -unsigned long addr = uaddr >>12 | (ASID (mm) <<48 ); +unsigned long addr =__TLBI_VADDR (uaddr,ASID (mm));__tlbi (vae1is, addr);__tlbi_user (vae1is, addr);
Signature · 3 lines
Qualcomm Datacenter Technologies as an affiliate of Qualcomm Technologies, Inc. Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
Quoted 18 lines · Philip Elcan
Several of the bits of the TLBI register operand are RES0 per the ARM ARM, so TLBI operations should avoid writing non-zero values to these bits.
This patch adds a macro
__TLBI_VADDR(addr, asid)that creates the operand register in the correct format and honors the RES0 bits.Signed-off-by Philip Elcan <[email protected]>--- arch/arm64/include/asm/tlbflush.h | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-)arch/arm64/include/asm/tlbflush.h +0
-0@@ -60,6 +60,15 @@__tlbi (op, (arg) |USER_ASID_FLAG ); \
arch/arm64/include/asm/tlbflush.h line 70
Quoted 10 lines
arch/arm64/include/asm/tlbflush.h +8
-0}while (0 ) +/* This macro creates a properly formatted VA operand for the TLBI */ +#define __TLBI_VADDR(addr, asid) \ + ({ \ +unsigned long __ta = (addr) >>12 ; \ + __ta &=GENMASK_ULL (43 ,0 ); \ + __ta |= (unsigned long )(asid) <<48 ; \ + __ta; \ + })
As a minor nit, we typically don't indent the start of the macro function body, and we could drop the leading tab on each line, but either way:
Thanks,
Mark.
Quoted 67 lines
arch/arm64/include/asm/tlbflush.h +9
-8+/* * TLB Management * ============== @@ -117,7 +126,7 @@ static inline void flush_tlb_all(void)static inline void flush_tlb_mm (struct mm_struct *mm) { -unsigned long asid =ASID (mm) <<48 ; +unsigned long asid =__TLBI_VADDR (0 ,ASID (mm));dsb (ishst);__tlbi (aside1is, asid);@@ -128,7 +137,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm)static inline void flush_tlb_page (struct vm_area_struct *vma,unsigned long uaddr) { -unsigned long addr = uaddr >>12 | (ASID (vma->vm_mm) <<48 ); +unsigned long addr =__TLBI_VADDR (uaddr,ASID (vma->vm_mm));dsb (ishst);__tlbi (vale1is, addr);@@ -146,7 +155,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end, bool last_level) { - unsigned long asid = ASID(vma->vm_mm) << 48; + unsigned long asid = ASID(vma->vm_mm);unsigned long addr;if ((end - start) >MAX_TLB_RANGE ) {@@ -154,8 +163,8 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,return ; } - start = asid | (start >>12 ); - end = asid | (end >>12 ); + start =__TLBI_VADDR (start, asid); + end =__TLBI_VADDR (end, asid);dsb (ishst);for (addr = start; addr < end; addr +=1 << (PAGE_SHIFT -12 )) {@@ -185,8 +194,8 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long endreturn ; } - start >>=12 ; - end >>=12 ; + start =__TLBI_VADDR (start,0 ); + end =__TLBI_VADDR (end,0 );dsb (ishst);for (addr = start; addr < end; addr +=1 << (PAGE_SHIFT -12 ))@@ -202,7 +211,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long endstatic inline void __flush_tlb_pgtable (struct mm_struct *mm,unsigned long uaddr) { -unsigned long addr = uaddr >>12 | (ASID (mm) <<48 ); +unsigned long addr =__TLBI_VADDR (uaddr,ASID (mm));__tlbi (vae1is, addr);__tlbi_user (vae1is, addr);Signature · 3 lines
Qualcomm Datacenter Technologies as an affiliate of Qualcomm Technologies, Inc. Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.