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

Merge branch 'for-next/svm' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux into for-joerg/arm-smmu/updates

Pull in core arm64 changes required to enable Shared Virtual Memory
(SVM) using SMMUv3. This brings us increasingly closer to being able to
share page-tables directly between user-space tasks running on the CPU
and their corresponding contexts on coherent devices performing DMA
through the SMMU.

Signed-off-by: Will Deacon <will@kernel.org>

+113 -7
+3
arch/arm64/include/asm/mmu.h
··· 17 17 18 18 #ifndef __ASSEMBLY__ 19 19 20 + #include <linux/refcount.h> 21 + 20 22 typedef struct { 21 23 atomic64_t id; 22 24 #ifdef CONFIG_COMPAT 23 25 void *sigpage; 24 26 #endif 27 + refcount_t pinned; 25 28 void *vdso; 26 29 unsigned long flags; 27 30 } mm_context_t;
+10 -1
arch/arm64/include/asm/mmu_context.h
··· 177 177 #define destroy_context(mm) do { } while(0) 178 178 void check_and_switch_context(struct mm_struct *mm); 179 179 180 - #define init_new_context(tsk,mm) ({ atomic64_set(&(mm)->context.id, 0); 0; }) 180 + static inline int 181 + init_new_context(struct task_struct *tsk, struct mm_struct *mm) 182 + { 183 + atomic64_set(&mm->context.id, 0); 184 + refcount_set(&mm->context.pinned, 0); 185 + return 0; 186 + } 181 187 182 188 #ifdef CONFIG_ARM64_SW_TTBR0_PAN 183 189 static inline void update_saved_ttbr0(struct task_struct *tsk, ··· 253 247 254 248 void verify_cpu_asid_bits(void); 255 249 void post_ttbr_update_workaround(void); 250 + 251 + unsigned long arm64_mm_context_get(struct mm_struct *mm); 252 + void arm64_mm_context_put(struct mm_struct *mm); 256 253 257 254 #endif /* !__ASSEMBLY__ */ 258 255
+1
arch/arm64/kernel/cpufeature.c
··· 1111 1111 return 0; 1112 1112 return regp->sys_val; 1113 1113 } 1114 + EXPORT_SYMBOL_GPL(read_sanitised_ftr_reg); 1114 1115 1115 1116 #define read_sysreg_case(r) \ 1116 1117 case r: return read_sysreg_s(r)
+99 -6
arch/arm64/mm/context.c
··· 27 27 static DEFINE_PER_CPU(u64, reserved_asids); 28 28 static cpumask_t tlb_flush_pending; 29 29 30 + static unsigned long max_pinned_asids; 31 + static unsigned long nr_pinned_asids; 32 + static unsigned long *pinned_asid_map; 33 + 30 34 #define ASID_MASK (~GENMASK(asid_bits - 1, 0)) 31 35 #define ASID_FIRST_VERSION (1UL << asid_bits) 32 36 ··· 76 72 } 77 73 } 78 74 79 - static void set_kpti_asid_bits(void) 75 + static void set_kpti_asid_bits(unsigned long *map) 80 76 { 81 77 unsigned int len = BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(unsigned long); 82 78 /* ··· 85 81 * is set, then the ASID will map only userspace. Thus 86 82 * mark even as reserved for kernel. 87 83 */ 88 - memset(asid_map, 0xaa, len); 84 + memset(map, 0xaa, len); 89 85 } 90 86 91 87 static void set_reserved_asid_bits(void) 92 88 { 93 - if (arm64_kernel_unmapped_at_el0()) 94 - set_kpti_asid_bits(); 89 + if (pinned_asid_map) 90 + bitmap_copy(asid_map, pinned_asid_map, NUM_USER_ASIDS); 91 + else if (arm64_kernel_unmapped_at_el0()) 92 + set_kpti_asid_bits(asid_map); 95 93 else 96 94 bitmap_clear(asid_map, 0, NUM_USER_ASIDS); 97 95 } ··· 169 163 * can continue to use it and this was just a false alarm. 170 164 */ 171 165 if (check_update_reserved_asid(asid, newasid)) 166 + return newasid; 167 + 168 + /* 169 + * If it is pinned, we can keep using it. Note that reserved 170 + * takes priority, because even if it is also pinned, we need to 171 + * update the generation into the reserved_asids. 172 + */ 173 + if (refcount_read(&mm->context.pinned)) 172 174 return newasid; 173 175 174 176 /* ··· 270 256 cpu_switch_mm(mm->pgd, mm); 271 257 } 272 258 259 + unsigned long arm64_mm_context_get(struct mm_struct *mm) 260 + { 261 + unsigned long flags; 262 + u64 asid; 263 + 264 + if (!pinned_asid_map) 265 + return 0; 266 + 267 + raw_spin_lock_irqsave(&cpu_asid_lock, flags); 268 + 269 + asid = atomic64_read(&mm->context.id); 270 + 271 + if (refcount_inc_not_zero(&mm->context.pinned)) 272 + goto out_unlock; 273 + 274 + if (nr_pinned_asids >= max_pinned_asids) { 275 + asid = 0; 276 + goto out_unlock; 277 + } 278 + 279 + if (!asid_gen_match(asid)) { 280 + /* 281 + * We went through one or more rollover since that ASID was 282 + * used. Ensure that it is still valid, or generate a new one. 283 + */ 284 + asid = new_context(mm); 285 + atomic64_set(&mm->context.id, asid); 286 + } 287 + 288 + nr_pinned_asids++; 289 + __set_bit(asid2idx(asid), pinned_asid_map); 290 + refcount_set(&mm->context.pinned, 1); 291 + 292 + out_unlock: 293 + raw_spin_unlock_irqrestore(&cpu_asid_lock, flags); 294 + 295 + asid &= ~ASID_MASK; 296 + 297 + /* Set the equivalent of USER_ASID_BIT */ 298 + if (asid && arm64_kernel_unmapped_at_el0()) 299 + asid |= 1; 300 + 301 + return asid; 302 + } 303 + EXPORT_SYMBOL_GPL(arm64_mm_context_get); 304 + 305 + void arm64_mm_context_put(struct mm_struct *mm) 306 + { 307 + unsigned long flags; 308 + u64 asid = atomic64_read(&mm->context.id); 309 + 310 + if (!pinned_asid_map) 311 + return; 312 + 313 + raw_spin_lock_irqsave(&cpu_asid_lock, flags); 314 + 315 + if (refcount_dec_and_test(&mm->context.pinned)) { 316 + __clear_bit(asid2idx(asid), pinned_asid_map); 317 + nr_pinned_asids--; 318 + } 319 + 320 + raw_spin_unlock_irqrestore(&cpu_asid_lock, flags); 321 + } 322 + EXPORT_SYMBOL_GPL(arm64_mm_context_put); 323 + 273 324 /* Errata workaround post TTBRx_EL1 update. */ 274 325 asmlinkage void post_ttbr_update_workaround(void) 275 326 { ··· 375 296 { 376 297 unsigned long num_available_asids = NUM_USER_ASIDS; 377 298 378 - if (arm64_kernel_unmapped_at_el0()) 299 + if (arm64_kernel_unmapped_at_el0()) { 379 300 num_available_asids /= 2; 301 + if (pinned_asid_map) 302 + set_kpti_asid_bits(pinned_asid_map); 303 + } 380 304 /* 381 305 * Expect allocation after rollover to fail if we don't have at least 382 306 * one more ASID than CPUs. ASID #0 is reserved for init_mm. ··· 387 305 WARN_ON(num_available_asids - 1 <= num_possible_cpus()); 388 306 pr_info("ASID allocator initialised with %lu entries\n", 389 307 num_available_asids); 308 + 309 + /* 310 + * There must always be an ASID available after rollover. Ensure that, 311 + * even if all CPUs have a reserved ASID and the maximum number of ASIDs 312 + * are pinned, there still is at least one empty slot in the ASID map. 313 + */ 314 + max_pinned_asids = num_available_asids - num_possible_cpus() - 2; 390 315 return 0; 391 316 } 392 317 arch_initcall(asids_update_limit); ··· 408 319 panic("Failed to allocate bitmap for %lu ASIDs\n", 409 320 NUM_USER_ASIDS); 410 321 322 + pinned_asid_map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS), 323 + sizeof(*pinned_asid_map), GFP_KERNEL); 324 + nr_pinned_asids = 0; 325 + 411 326 /* 412 327 * We cannot call set_reserved_asid_bits() here because CPU 413 328 * caps are not finalized yet, so it is safer to assume KPTI 414 329 * and reserve kernel ASID's from beginning. 415 330 */ 416 331 if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) 417 - set_kpti_asid_bits(); 332 + set_kpti_asid_bits(asid_map); 418 333 return 0; 419 334 } 420 335 early_initcall(asids_init);