Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'riscv-for-linus-6.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux

Pull RISC-V fixes from Palmer Dabbelt:

- fixes to the ASID allocator to avoid leaking stale mappings between
tasks

- fix the vmalloc fault handler to tolerate huge pages

* tag 'riscv-for-linus-6.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux:
RISC-V: mm: Support huge page in vmalloc_fault()
riscv: asid: Fixup stale TLB entry cause application crash
Revert "riscv: mm: notify remote harts about mmu cache updates"

+42 -51
-2
arch/riscv/include/asm/mmu.h
··· 19 19 #ifdef CONFIG_SMP 20 20 /* A local icache flush is needed before user execution can resume. */ 21 21 cpumask_t icache_stale_mask; 22 - /* A local tlb flush is needed before user execution can resume. */ 23 - cpumask_t tlb_stale_mask; 24 22 #endif 25 23 } mm_context_t; 26 24
-18
arch/riscv/include/asm/tlbflush.h
··· 22 22 { 23 23 ALT_FLUSH_TLB_PAGE(__asm__ __volatile__ ("sfence.vma %0" : : "r" (addr) : "memory")); 24 24 } 25 - 26 - static inline void local_flush_tlb_all_asid(unsigned long asid) 27 - { 28 - __asm__ __volatile__ ("sfence.vma x0, %0" 29 - : 30 - : "r" (asid) 31 - : "memory"); 32 - } 33 - 34 - static inline void local_flush_tlb_page_asid(unsigned long addr, 35 - unsigned long asid) 36 - { 37 - __asm__ __volatile__ ("sfence.vma %0, %1" 38 - : 39 - : "r" (addr), "r" (asid) 40 - : "memory"); 41 - } 42 - 43 25 #else /* CONFIG_MMU */ 44 26 #define local_flush_tlb_all() do { } while (0) 45 27 #define local_flush_tlb_page(addr) do { } while (0)
+20 -20
arch/riscv/mm/context.c
··· 196 196 197 197 if (need_flush_tlb) 198 198 local_flush_tlb_all(); 199 - #ifdef CONFIG_SMP 200 - else { 201 - cpumask_t *mask = &mm->context.tlb_stale_mask; 202 - 203 - if (cpumask_test_cpu(cpu, mask)) { 204 - cpumask_clear_cpu(cpu, mask); 205 - local_flush_tlb_all_asid(cntx & asid_mask); 206 - } 207 - } 208 - #endif 209 199 } 210 200 211 201 static void set_mm_noasid(struct mm_struct *mm) ··· 205 215 local_flush_tlb_all(); 206 216 } 207 217 208 - static inline void set_mm(struct mm_struct *mm, unsigned int cpu) 218 + static inline void set_mm(struct mm_struct *prev, 219 + struct mm_struct *next, unsigned int cpu) 209 220 { 210 - if (static_branch_unlikely(&use_asid_allocator)) 211 - set_mm_asid(mm, cpu); 212 - else 213 - set_mm_noasid(mm); 221 + /* 222 + * The mm_cpumask indicates which harts' TLBs contain the virtual 223 + * address mapping of the mm. Compared to noasid, using asid 224 + * can't guarantee that stale TLB entries are invalidated because 225 + * the asid mechanism wouldn't flush TLB for every switch_mm for 226 + * performance. So when using asid, keep all CPUs footmarks in 227 + * cpumask() until mm reset. 228 + */ 229 + cpumask_set_cpu(cpu, mm_cpumask(next)); 230 + if (static_branch_unlikely(&use_asid_allocator)) { 231 + set_mm_asid(next, cpu); 232 + } else { 233 + cpumask_clear_cpu(cpu, mm_cpumask(prev)); 234 + set_mm_noasid(next); 235 + } 214 236 } 215 237 216 238 static int __init asids_init(void) ··· 276 274 } 277 275 early_initcall(asids_init); 278 276 #else 279 - static inline void set_mm(struct mm_struct *mm, unsigned int cpu) 277 + static inline void set_mm(struct mm_struct *prev, 278 + struct mm_struct *next, unsigned int cpu) 280 279 { 281 280 /* Nothing to do here when there is no MMU */ 282 281 } ··· 330 327 */ 331 328 cpu = smp_processor_id(); 332 329 333 - cpumask_clear_cpu(cpu, mm_cpumask(prev)); 334 - cpumask_set_cpu(cpu, mm_cpumask(next)); 335 - 336 - set_mm(next, cpu); 330 + set_mm(prev, next, cpu); 337 331 338 332 flush_icache_deferred(next, cpu); 339 333 }
+5
arch/riscv/mm/fault.c
··· 143 143 no_context(regs, addr); 144 144 return; 145 145 } 146 + if (pud_leaf(*pud_k)) 147 + goto flush_tlb; 146 148 147 149 /* 148 150 * Since the vmalloc area is global, it is unnecessary ··· 155 153 no_context(regs, addr); 156 154 return; 157 155 } 156 + if (pmd_leaf(*pmd_k)) 157 + goto flush_tlb; 158 158 159 159 /* 160 160 * Make sure the actual PTE exists as well to ··· 176 172 * ordering constraint, not a cache flush; it is 177 173 * necessary even after writing invalid entries. 178 174 */ 175 + flush_tlb: 179 176 local_flush_tlb_page(addr); 180 177 } 181 178
+17 -11
arch/riscv/mm/tlbflush.c
··· 5 5 #include <linux/sched.h> 6 6 #include <asm/sbi.h> 7 7 #include <asm/mmu_context.h> 8 - #include <asm/tlbflush.h> 8 + 9 + static inline void local_flush_tlb_all_asid(unsigned long asid) 10 + { 11 + __asm__ __volatile__ ("sfence.vma x0, %0" 12 + : 13 + : "r" (asid) 14 + : "memory"); 15 + } 16 + 17 + static inline void local_flush_tlb_page_asid(unsigned long addr, 18 + unsigned long asid) 19 + { 20 + __asm__ __volatile__ ("sfence.vma %0, %1" 21 + : 22 + : "r" (addr), "r" (asid) 23 + : "memory"); 24 + } 9 25 10 26 void flush_tlb_all(void) 11 27 { ··· 31 15 static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start, 32 16 unsigned long size, unsigned long stride) 33 17 { 34 - struct cpumask *pmask = &mm->context.tlb_stale_mask; 35 18 struct cpumask *cmask = mm_cpumask(mm); 36 19 unsigned int cpuid; 37 20 bool broadcast; ··· 43 28 broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids; 44 29 if (static_branch_unlikely(&use_asid_allocator)) { 45 30 unsigned long asid = atomic_long_read(&mm->context.id); 46 - 47 - /* 48 - * TLB will be immediately flushed on harts concurrently 49 - * executing this MM context. TLB flush on other harts 50 - * is deferred until this MM context migrates there. 51 - */ 52 - cpumask_setall(pmask); 53 - cpumask_clear_cpu(cpuid, pmask); 54 - cpumask_andnot(pmask, pmask, cmask); 55 31 56 32 if (broadcast) { 57 33 sbi_remote_sfence_vma_asid(cmask, start, size, asid);