Message ID | 20220331055906.3552337-1-alistair.francis@opensource.wdc.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v3] riscv: Ensure only ASIDLEN is used for sfence.vma | expand |
On Thu, Mar 31, 2022 at 11:29 AM Alistair Francis <alistair.francis@opensource.wdc.com> wrote: > > From: Alistair Francis <alistair.francis@wdc.com> > > When we set the value of context.id using __new_context() we set both > the asid and the current_version with this return statement in > __new_context(): > > return asid | ver; > > This means that when local_flush_tlb_all_asid() is called with the asid > specified from context.id we can write the incorrect value. > > We get away with this as hardware ignores the extra bits, as the RISC-V > specification states: > > "bits SXLEN-1:ASIDMAX of the value held in rs2 are reserved for future > standard use. Until their use is defined by a standard extension, they > should be zeroed by software and ignored by current implementations." > > but it is still a bug and worth addressing as we are incorrectly setting > extra bits. > > This patch uses asid_mask when calling sfence.vma to ensure the asid is > always the correct len (ASIDLEN). This is similar to what we do in > arch/riscv/mm/context.c. > > Fixes: 3f1e782998cd ("riscv: add ASID-based tlbflushing methods") > Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Looks good to me. Reviewed-by: Anup Patel <anup@brainfault.org> Regards, Anup > --- > v3: > - Use helper function > v2: > - Pass in pre-masked value > > arch/riscv/include/asm/mmu_context.h | 2 ++ > arch/riscv/mm/context.c | 5 +++++ > arch/riscv/mm/tlbflush.c | 2 +- > 3 files changed, 8 insertions(+), 1 deletion(-) > > diff --git a/arch/riscv/include/asm/mmu_context.h b/arch/riscv/include/asm/mmu_context.h > index 7030837adc1a..94e82c9e17eb 100644 > --- a/arch/riscv/include/asm/mmu_context.h > +++ b/arch/riscv/include/asm/mmu_context.h > @@ -16,6 +16,8 @@ > void switch_mm(struct mm_struct *prev, struct mm_struct *next, > struct task_struct *task); > > +unsigned long get_mm_asid(struct mm_struct *mm); > + > #define activate_mm activate_mm > static inline void activate_mm(struct mm_struct *prev, > struct mm_struct *next) > diff --git a/arch/riscv/mm/context.c b/arch/riscv/mm/context.c > index 7acbfbd14557..14aec5bacbc1 100644 > --- a/arch/riscv/mm/context.c > +++ b/arch/riscv/mm/context.c > @@ -302,6 +302,11 @@ static inline void flush_icache_deferred(struct mm_struct *mm, unsigned int cpu) > #endif > } > > +unsigned long get_mm_asid(struct mm_struct *mm) > +{ > + return atomic_long_read(&mm->context.id) & asid_mask; > +} > + > void switch_mm(struct mm_struct *prev, struct mm_struct *next, > struct task_struct *task) > { > diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c > index 37ed760d007c..9c89c4951bee 100644 > --- a/arch/riscv/mm/tlbflush.c > +++ b/arch/riscv/mm/tlbflush.c > @@ -42,7 +42,7 @@ static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start, > /* check if the tlbflush needs to be sent to other CPUs */ > broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids; > if (static_branch_unlikely(&use_asid_allocator)) { > - unsigned long asid = atomic_long_read(&mm->context.id); > + unsigned long asid = get_mm_asid(mm); > > if (broadcast) { > sbi_remote_sfence_vma_asid(cmask, start, size, asid); > -- > 2.35.1 >
Reviewed-by: Guo Ren <guoren@kernel.org> On Thu, Mar 31, 2022 at 1:59 PM Alistair Francis <alistair.francis@opensource.wdc.com> wrote: > > From: Alistair Francis <alistair.francis@wdc.com> > > When we set the value of context.id using __new_context() we set both > the asid and the current_version with this return statement in > __new_context(): > > return asid | ver; > > This means that when local_flush_tlb_all_asid() is called with the asid > specified from context.id we can write the incorrect value. > > We get away with this as hardware ignores the extra bits, as the RISC-V > specification states: > > "bits SXLEN-1:ASIDMAX of the value held in rs2 are reserved for future > standard use. Until their use is defined by a standard extension, they > should be zeroed by software and ignored by current implementations." > > but it is still a bug and worth addressing as we are incorrectly setting > extra bits. > > This patch uses asid_mask when calling sfence.vma to ensure the asid is > always the correct len (ASIDLEN). This is similar to what we do in > arch/riscv/mm/context.c. > > Fixes: 3f1e782998cd ("riscv: add ASID-based tlbflushing methods") > Signed-off-by: Alistair Francis <alistair.francis@wdc.com> > --- > v3: > - Use helper function > v2: > - Pass in pre-masked value > > arch/riscv/include/asm/mmu_context.h | 2 ++ > arch/riscv/mm/context.c | 5 +++++ > arch/riscv/mm/tlbflush.c | 2 +- > 3 files changed, 8 insertions(+), 1 deletion(-) > > diff --git a/arch/riscv/include/asm/mmu_context.h b/arch/riscv/include/asm/mmu_context.h > index 7030837adc1a..94e82c9e17eb 100644 > --- a/arch/riscv/include/asm/mmu_context.h > +++ b/arch/riscv/include/asm/mmu_context.h > @@ -16,6 +16,8 @@ > void switch_mm(struct mm_struct *prev, struct mm_struct *next, > struct task_struct *task); > > +unsigned long get_mm_asid(struct mm_struct *mm); > + > #define activate_mm activate_mm > static inline void activate_mm(struct mm_struct *prev, > struct mm_struct *next) > diff --git a/arch/riscv/mm/context.c b/arch/riscv/mm/context.c > index 7acbfbd14557..14aec5bacbc1 100644 > --- a/arch/riscv/mm/context.c > +++ b/arch/riscv/mm/context.c > @@ -302,6 +302,11 @@ static inline void flush_icache_deferred(struct mm_struct *mm, unsigned int cpu) > #endif > } > > +unsigned long get_mm_asid(struct mm_struct *mm) > +{ > + return atomic_long_read(&mm->context.id) & asid_mask; > +} > + > void switch_mm(struct mm_struct *prev, struct mm_struct *next, > struct task_struct *task) > { > diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c > index 37ed760d007c..9c89c4951bee 100644 > --- a/arch/riscv/mm/tlbflush.c > +++ b/arch/riscv/mm/tlbflush.c > @@ -42,7 +42,7 @@ static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start, > /* check if the tlbflush needs to be sent to other CPUs */ > broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids; > if (static_branch_unlikely(&use_asid_allocator)) { > - unsigned long asid = atomic_long_read(&mm->context.id); > + unsigned long asid = get_mm_asid(mm); > > if (broadcast) { > sbi_remote_sfence_vma_asid(cmask, start, size, asid); > -- > 2.35.1 >
Hi Alistair, Thank you for the patch! Yet something to improve: [auto build test ERROR on linus/master] [also build test ERROR on v5.17 next-20220331] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/intel-lab-lkp/linux/commits/Alistair-Francis/riscv-Ensure-only-ASIDLEN-is-used-for-sfence-vma/20220331-140116 base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 787af64d05cd528aac9ad16752d11bb1c6061bb9 config: riscv-nommu_k210_defconfig (https://download.01.org/0day-ci/archive/20220331/202203311731.xi8xw0gy-lkp@intel.com/config) compiler: riscv64-linux-gcc (GCC) 11.2.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/162147030f410152d028af446a7383e3c9410f55 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Alistair-Francis/riscv-Ensure-only-ASIDLEN-is-used-for-sfence-vma/20220331-140116 git checkout 162147030f410152d028af446a7383e3c9410f55 # save the config file to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=riscv SHELL=/bin/bash arch/riscv/mm/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): arch/riscv/mm/context.c: In function 'get_mm_asid': >> arch/riscv/mm/context.c:307:45: error: 'mm_context_t' has no member named 'id' 307 | return atomic_long_read(&mm->context.id) & asid_mask; | ^ >> arch/riscv/mm/context.c:307:52: error: 'asid_mask' undeclared (first use in this function); did you mean 'pid_task'? 307 | return atomic_long_read(&mm->context.id) & asid_mask; | ^~~~~~~~~ | pid_task arch/riscv/mm/context.c:307:52: note: each undeclared identifier is reported only once for each function it appears in arch/riscv/mm/context.c:308:1: error: control reaches end of non-void function [-Werror=return-type] 308 | } | ^ cc1: some warnings being treated as errors vim +307 arch/riscv/mm/context.c 304 305 unsigned long get_mm_asid(struct mm_struct *mm) 306 { > 307 return atomic_long_read(&mm->context.id) & asid_mask; 308 } 309
Hi Alistair, Thank you for the patch! Yet something to improve: [auto build test ERROR on linus/master] [also build test ERROR on v5.17 next-20220331] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/intel-lab-lkp/linux/commits/Alistair-Francis/riscv-Ensure-only-ASIDLEN-is-used-for-sfence-vma/20220331-140116 base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 787af64d05cd528aac9ad16752d11bb1c6061bb9 config: riscv-randconfig-c006-20220331 (https://download.01.org/0day-ci/archive/20220331/202203312110.VamttjhO-lkp@intel.com/config) compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 881350a92d821d4f8e4fa648443ed1d17e251188) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install riscv cross compiling tool for clang build # apt-get install binutils-riscv64-linux-gnu # https://github.com/intel-lab-lkp/linux/commit/162147030f410152d028af446a7383e3c9410f55 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Alistair-Francis/riscv-Ensure-only-ASIDLEN-is-used-for-sfence-vma/20220331-140116 git checkout 162147030f410152d028af446a7383e3c9410f55 # save the config file to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=riscv SHELL=/bin/bash arch/riscv/mm/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): >> arch/riscv/mm/context.c:307:39: error: no member named 'id' in 'mm_context_t' return atomic_long_read(&mm->context.id) & asid_mask; ~~~~~~~~~~~ ^ >> arch/riscv/mm/context.c:307:45: error: use of undeclared identifier 'asid_mask' return atomic_long_read(&mm->context.id) & asid_mask; ^ 2 errors generated. vim +307 arch/riscv/mm/context.c 304 305 unsigned long get_mm_asid(struct mm_struct *mm) 306 { > 307 return atomic_long_read(&mm->context.id) & asid_mask; 308 } 309
On Wed, 30 Mar 2022 22:59:06 PDT (-0700), alistair.francis@opensource.wdc.com wrote: > From: Alistair Francis <alistair.francis@wdc.com> > > When we set the value of context.id using __new_context() we set both > the asid and the current_version with this return statement in > __new_context(): > > return asid | ver; > > This means that when local_flush_tlb_all_asid() is called with the asid > specified from context.id we can write the incorrect value. > > We get away with this as hardware ignores the extra bits, as the RISC-V > specification states: > > "bits SXLEN-1:ASIDMAX of the value held in rs2 are reserved for future > standard use. Until their use is defined by a standard extension, they > should be zeroed by software and ignored by current implementations." > > but it is still a bug and worth addressing as we are incorrectly setting > extra bits. > > This patch uses asid_mask when calling sfence.vma to ensure the asid is > always the correct len (ASIDLEN). This is similar to what we do in > arch/riscv/mm/context.c. > > Fixes: 3f1e782998cd ("riscv: add ASID-based tlbflushing methods") > Signed-off-by: Alistair Francis <alistair.francis@wdc.com> > --- > v3: > - Use helper function > v2: > - Pass in pre-masked value > > arch/riscv/include/asm/mmu_context.h | 2 ++ > arch/riscv/mm/context.c | 5 +++++ > arch/riscv/mm/tlbflush.c | 2 +- > 3 files changed, 8 insertions(+), 1 deletion(-) > > diff --git a/arch/riscv/include/asm/mmu_context.h b/arch/riscv/include/asm/mmu_context.h > index 7030837adc1a..94e82c9e17eb 100644 > --- a/arch/riscv/include/asm/mmu_context.h > +++ b/arch/riscv/include/asm/mmu_context.h > @@ -16,6 +16,8 @@ > void switch_mm(struct mm_struct *prev, struct mm_struct *next, > struct task_struct *task); > > +unsigned long get_mm_asid(struct mm_struct *mm); > + > #define activate_mm activate_mm > static inline void activate_mm(struct mm_struct *prev, > struct mm_struct *next) > diff --git a/arch/riscv/mm/context.c b/arch/riscv/mm/context.c > index 7acbfbd14557..14aec5bacbc1 100644 > --- a/arch/riscv/mm/context.c > +++ b/arch/riscv/mm/context.c > @@ -302,6 +302,11 @@ static inline void flush_icache_deferred(struct mm_struct *mm, unsigned int cpu) > #endif > } > > +unsigned long get_mm_asid(struct mm_struct *mm) > +{ > + return atomic_long_read(&mm->context.id) & asid_mask; > +} > + > void switch_mm(struct mm_struct *prev, struct mm_struct *next, > struct task_struct *task) > { > diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c > index 37ed760d007c..9c89c4951bee 100644 > --- a/arch/riscv/mm/tlbflush.c > +++ b/arch/riscv/mm/tlbflush.c > @@ -42,7 +42,7 @@ static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start, > /* check if the tlbflush needs to be sent to other CPUs */ > broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids; > if (static_branch_unlikely(&use_asid_allocator)) { > - unsigned long asid = atomic_long_read(&mm->context.id); > + unsigned long asid = get_mm_asid(mm); > > if (broadcast) { > sbi_remote_sfence_vma_asid(cmask, start, size, asid); > -- > 2.35.1 The autobuilders are finding some failures. I think this diff --git a/arch/riscv/mm/context.c b/arch/riscv/mm/context.c index 6df4f22f0a3c..8a9c7bc2297a 100644 --- a/arch/riscv/mm/context.c +++ b/arch/riscv/mm/context.c @@ -12,6 +12,7 @@ #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/static_key.h> +#include <asm/atomic.h> #include <asm/tlbflush.h> #include <asm/cacheflush.h> #include <asm/mmu_context.h> should do it, I've squashed that in and put it on palmer/riscv-asidlen so the autobuilders can find it. It's going to be too late for rc1, but this seems fine for fixes so it's no big deal. Feel free to send a v4 if there's anything else, but if that's enough to fix it then no need to. If there's no v4 and nothing goes wrong, I'll cherry-pick it past rc1 when I re-fork my fixes tree. Thanks!
diff --git a/arch/riscv/include/asm/mmu_context.h b/arch/riscv/include/asm/mmu_context.h index 7030837adc1a..94e82c9e17eb 100644 --- a/arch/riscv/include/asm/mmu_context.h +++ b/arch/riscv/include/asm/mmu_context.h @@ -16,6 +16,8 @@ void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *task); +unsigned long get_mm_asid(struct mm_struct *mm); + #define activate_mm activate_mm static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) diff --git a/arch/riscv/mm/context.c b/arch/riscv/mm/context.c index 7acbfbd14557..14aec5bacbc1 100644 --- a/arch/riscv/mm/context.c +++ b/arch/riscv/mm/context.c @@ -302,6 +302,11 @@ static inline void flush_icache_deferred(struct mm_struct *mm, unsigned int cpu) #endif } +unsigned long get_mm_asid(struct mm_struct *mm) +{ + return atomic_long_read(&mm->context.id) & asid_mask; +} + void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *task) { diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c index 37ed760d007c..9c89c4951bee 100644 --- a/arch/riscv/mm/tlbflush.c +++ b/arch/riscv/mm/tlbflush.c @@ -42,7 +42,7 @@ static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start, /* check if the tlbflush needs to be sent to other CPUs */ broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids; if (static_branch_unlikely(&use_asid_allocator)) { - unsigned long asid = atomic_long_read(&mm->context.id); + unsigned long asid = get_mm_asid(mm); if (broadcast) { sbi_remote_sfence_vma_asid(cmask, start, size, asid);