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.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux

Pull RISC-V fixes from Paul Walmsley:

- Close a race during boot between userspace vDSO usage and some
late-initialized vDSO data

- Improve performance on systems with non-CPU-cache-coherent
DMA-capable peripherals by enabling write combining on
pgprot_dmacoherent() allocations

- Add human-readable detail for RISC-V IPI tracing

- Provide more information to zsmalloc on 64-bit RISC-V to improve
allocation

- Silence useless boot messages about CPUs that have been disabled in
DT

- Resolve some compiler and smatch warnings and remove a redundant
macro

* tag 'riscv-for-linus-6.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux:
riscv: hwprobe: avoid uninitialized variable use in hwprobe_arch_id()
riscv: cpufeature: avoid uninitialized variable in has_thead_homogeneous_vlenb()
riscv: hwprobe: Fix stale vDSO data for late-initialized keys at boot
riscv: add a forward declaration for cpuinfo_op
RISC-V: Don't print details of CPUs disabled in DT
riscv: Remove the PER_CPU_OFFSET_SHIFT macro
riscv: mm: Define MAX_POSSIBLE_PHYSMEM_BITS for zsmalloc
riscv: Register IPI IRQs with unique names
ACPI: RIMT: Fix unused function warnings when CONFIG_IOMMU_API is disabled
RISC-V: Define pgprot_dmacoherent() for non-coherent devices

+170 -102
+1 -7
arch/riscv/include/asm/asm.h
··· 84 84 .endm 85 85 86 86 #ifdef CONFIG_SMP 87 - #ifdef CONFIG_32BIT 88 - #define PER_CPU_OFFSET_SHIFT 2 89 - #else 90 - #define PER_CPU_OFFSET_SHIFT 3 91 - #endif 92 - 93 87 .macro asm_per_cpu dst sym tmp 94 88 lw \tmp, TASK_TI_CPU_NUM(tp) 95 - slli \tmp, \tmp, PER_CPU_OFFSET_SHIFT 89 + slli \tmp, \tmp, RISCV_LGPTR 96 90 la \dst, __per_cpu_offset 97 91 add \dst, \dst, \tmp 98 92 REG_L \tmp, 0(\dst)
+2
arch/riscv/include/asm/cpufeature.h
··· 31 31 32 32 DECLARE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo); 33 33 34 + extern const struct seq_operations cpuinfo_op; 35 + 34 36 /* Per-cpu ISA extensions. */ 35 37 extern struct riscv_isainfo hart_isa[NR_CPUS]; 36 38
+7
arch/riscv/include/asm/hwprobe.h
··· 42 42 return pair->value == other_pair->value; 43 43 } 44 44 45 + #ifdef CONFIG_MMU 46 + void riscv_hwprobe_register_async_probe(void); 47 + void riscv_hwprobe_complete_async_probe(void); 48 + #else 49 + static inline void riscv_hwprobe_register_async_probe(void) {} 50 + static inline void riscv_hwprobe_complete_async_probe(void) {} 51 + #endif 45 52 #endif
+2
arch/riscv/include/asm/pgtable-64.h
··· 69 69 70 70 #define PTRS_PER_PMD (PAGE_SIZE / sizeof(pmd_t)) 71 71 72 + #define MAX_POSSIBLE_PHYSMEM_BITS 56 73 + 72 74 /* 73 75 * rv64 PTE format: 74 76 * | 63 | 62 61 | 60 54 | 53 10 | 9 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
+2
arch/riscv/include/asm/pgtable.h
··· 654 654 return __pgprot(prot); 655 655 } 656 656 657 + #define pgprot_dmacoherent pgprot_writecombine 658 + 657 659 /* 658 660 * Both Svade and Svadu control the hardware behavior when the PTE A/D bits need to be set. By 659 661 * default the M-mode firmware enables the hardware updating scheme when only Svadu is present in
+6
arch/riscv/include/asm/vdso/arch_data.h
··· 12 12 13 13 /* Boolean indicating all CPUs have the same static hwprobe values. */ 14 14 __u8 homogeneous_cpus; 15 + 16 + /* 17 + * A gate to check and see if the hwprobe data is actually ready, as 18 + * probing is deferred to avoid boot slowdowns. 19 + */ 20 + __u8 ready; 15 21 }; 16 22 17 23 #endif /* __RISCV_ASM_VDSO_ARCH_DATA_H */
+1 -3
arch/riscv/kernel/cpu.c
··· 62 62 return -ENODEV; 63 63 } 64 64 65 - if (!of_device_is_available(node)) { 66 - pr_info("CPU with hartid=%lu is not available\n", *hart); 65 + if (!of_device_is_available(node)) 67 66 return -ENODEV; 68 - } 69 67 70 68 if (of_property_read_string(node, "riscv,isa-base", &isa)) 71 69 goto old_interface;
+2 -2
arch/riscv/kernel/cpufeature.c
··· 932 932 { 933 933 int cpu; 934 934 u32 prev_vlenb = 0; 935 - u32 vlenb; 935 + u32 vlenb = 0; 936 936 937 - /* Ignore thead,vlenb property if xtheavector is not enabled in the kernel */ 937 + /* Ignore thead,vlenb property if xtheadvector is not enabled in the kernel */ 938 938 if (!IS_ENABLED(CONFIG_RISCV_ISA_XTHEADVECTOR)) 939 939 return 0; 940 940
+12 -12
arch/riscv/kernel/smp.c
··· 40 40 IPI_MAX 41 41 }; 42 42 43 + static const char * const ipi_names[] = { 44 + [IPI_RESCHEDULE] = "Rescheduling interrupts", 45 + [IPI_CALL_FUNC] = "Function call interrupts", 46 + [IPI_CPU_STOP] = "CPU stop interrupts", 47 + [IPI_CPU_CRASH_STOP] = "CPU stop (for crash dump) interrupts", 48 + [IPI_IRQ_WORK] = "IRQ work interrupts", 49 + [IPI_TIMER] = "Timer broadcast interrupts", 50 + [IPI_CPU_BACKTRACE] = "CPU backtrace interrupts", 51 + [IPI_KGDB_ROUNDUP] = "KGDB roundup interrupts", 52 + }; 53 + 43 54 unsigned long __cpuid_to_hartid_map[NR_CPUS] __ro_after_init = { 44 55 [0 ... NR_CPUS-1] = INVALID_HARTID 45 56 }; ··· 210 199 /* Request IPIs */ 211 200 for (i = 0; i < nr_ipi; i++) { 212 201 err = request_percpu_irq(ipi_virq_base + i, handle_IPI, 213 - "IPI", &ipi_dummy_dev); 202 + ipi_names[i], &ipi_dummy_dev); 214 203 WARN_ON(err); 215 204 216 205 ipi_desc[i] = irq_to_desc(ipi_virq_base + i); ··· 220 209 /* Enabled IPIs for boot CPU immediately */ 221 210 riscv_ipi_enable(); 222 211 } 223 - 224 - static const char * const ipi_names[] = { 225 - [IPI_RESCHEDULE] = "Rescheduling interrupts", 226 - [IPI_CALL_FUNC] = "Function call interrupts", 227 - [IPI_CPU_STOP] = "CPU stop interrupts", 228 - [IPI_CPU_CRASH_STOP] = "CPU stop (for crash dump) interrupts", 229 - [IPI_IRQ_WORK] = "IRQ work interrupts", 230 - [IPI_TIMER] = "Timer broadcast interrupts", 231 - [IPI_CPU_BACKTRACE] = "CPU backtrace interrupts", 232 - [IPI_KGDB_ROUNDUP] = "KGDB roundup interrupts", 233 - }; 234 212 235 213 void show_ipi_stats(struct seq_file *p, int prec) 236 214 {
+66 -14
arch/riscv/kernel/sys_hwprobe.c
··· 5 5 * more details. 6 6 */ 7 7 #include <linux/syscalls.h> 8 + #include <linux/completion.h> 9 + #include <linux/atomic.h> 10 + #include <linux/once.h> 8 11 #include <asm/cacheflush.h> 9 12 #include <asm/cpufeature.h> 10 13 #include <asm/hwprobe.h> ··· 30 27 u64 id = -1ULL; 31 28 bool first = true; 32 29 int cpu; 30 + 31 + if (pair->key != RISCV_HWPROBE_KEY_MVENDORID && 32 + pair->key != RISCV_HWPROBE_KEY_MIMPID && 33 + pair->key != RISCV_HWPROBE_KEY_MARCHID) 34 + goto out; 33 35 34 36 for_each_cpu(cpu, cpus) { 35 37 u64 cpu_id; ··· 66 58 } 67 59 } 68 60 61 + out: 69 62 pair->value = id; 70 63 } 71 64 ··· 463 454 return 0; 464 455 } 465 456 466 - static int do_riscv_hwprobe(struct riscv_hwprobe __user *pairs, 467 - size_t pair_count, size_t cpusetsize, 468 - unsigned long __user *cpus_user, 469 - unsigned int flags) 470 - { 471 - if (flags & RISCV_HWPROBE_WHICH_CPUS) 472 - return hwprobe_get_cpus(pairs, pair_count, cpusetsize, 473 - cpus_user, flags); 474 - 475 - return hwprobe_get_values(pairs, pair_count, cpusetsize, 476 - cpus_user, flags); 477 - } 478 - 479 457 #ifdef CONFIG_MMU 480 458 481 - static int __init init_hwprobe_vdso_data(void) 459 + static DECLARE_COMPLETION(boot_probes_done); 460 + static atomic_t pending_boot_probes = ATOMIC_INIT(1); 461 + 462 + void riscv_hwprobe_register_async_probe(void) 463 + { 464 + atomic_inc(&pending_boot_probes); 465 + } 466 + 467 + void riscv_hwprobe_complete_async_probe(void) 468 + { 469 + if (atomic_dec_and_test(&pending_boot_probes)) 470 + complete(&boot_probes_done); 471 + } 472 + 473 + static int complete_hwprobe_vdso_data(void) 482 474 { 483 475 struct vdso_arch_data *avd = vdso_k_arch_data; 484 476 u64 id_bitsmash = 0; 485 477 struct riscv_hwprobe pair; 486 478 int key; 479 + 480 + if (unlikely(!atomic_dec_and_test(&pending_boot_probes))) 481 + wait_for_completion(&boot_probes_done); 487 482 488 483 /* 489 484 * Initialize vDSO data with the answers for the "all CPUs" case, to ··· 516 503 * vDSO should defer to the kernel for exotic cpu masks. 517 504 */ 518 505 avd->homogeneous_cpus = id_bitsmash != 0 && id_bitsmash != -1; 506 + 507 + /* 508 + * Make sure all the VDSO values are visible before we look at them. 509 + * This pairs with the implicit "no speculativly visible accesses" 510 + * barrier in the VDSO hwprobe code. 511 + */ 512 + smp_wmb(); 513 + avd->ready = true; 514 + return 0; 515 + } 516 + 517 + static int __init init_hwprobe_vdso_data(void) 518 + { 519 + struct vdso_arch_data *avd = vdso_k_arch_data; 520 + 521 + /* 522 + * Prevent the vDSO cached values from being used, as they're not ready 523 + * yet. 524 + */ 525 + avd->ready = false; 519 526 return 0; 520 527 } 521 528 522 529 arch_initcall_sync(init_hwprobe_vdso_data); 523 530 531 + #else 532 + 533 + static int complete_hwprobe_vdso_data(void) { return 0; } 534 + 524 535 #endif /* CONFIG_MMU */ 536 + 537 + static int do_riscv_hwprobe(struct riscv_hwprobe __user *pairs, 538 + size_t pair_count, size_t cpusetsize, 539 + unsigned long __user *cpus_user, 540 + unsigned int flags) 541 + { 542 + DO_ONCE_SLEEPABLE(complete_hwprobe_vdso_data); 543 + 544 + if (flags & RISCV_HWPROBE_WHICH_CPUS) 545 + return hwprobe_get_cpus(pairs, pair_count, cpusetsize, 546 + cpus_user, flags); 547 + 548 + return hwprobe_get_values(pairs, pair_count, cpusetsize, 549 + cpus_user, flags); 550 + } 525 551 526 552 SYSCALL_DEFINE5(riscv_hwprobe, struct riscv_hwprobe __user *, pairs, 527 553 size_t, pair_count, size_t, cpusetsize, unsigned long __user *,
+7 -2
arch/riscv/kernel/unaligned_access_speed.c
··· 379 379 static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) 380 380 { 381 381 schedule_on_each_cpu(check_vector_unaligned_access); 382 + riscv_hwprobe_complete_async_probe(); 382 383 383 384 return 0; 384 385 } ··· 474 473 per_cpu(vector_misaligned_access, cpu) = unaligned_vector_speed_param; 475 474 } else if (!check_vector_unaligned_access_emulated_all_cpus() && 476 475 IS_ENABLED(CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS)) { 477 - kthread_run(vec_check_unaligned_access_speed_all_cpus, 478 - NULL, "vec_check_unaligned_access_speed_all_cpus"); 476 + riscv_hwprobe_register_async_probe(); 477 + if (IS_ERR(kthread_run(vec_check_unaligned_access_speed_all_cpus, 478 + NULL, "vec_check_unaligned_access_speed_all_cpus"))) { 479 + pr_warn("Failed to create vec_unalign_check kthread\n"); 480 + riscv_hwprobe_complete_async_probe(); 481 + } 479 482 } 480 483 481 484 /*
+1 -1
arch/riscv/kernel/vdso/hwprobe.c
··· 27 27 * homogeneous, then this function can handle requests for arbitrary 28 28 * masks. 29 29 */ 30 - if ((flags != 0) || (!all_cpus && !avd->homogeneous_cpus)) 30 + if (flags != 0 || (!all_cpus && !avd->homogeneous_cpus) || unlikely(!avd->ready)) 31 31 return riscv_hwprobe(pairs, pair_count, cpusetsize, cpus, flags); 32 32 33 33 /* This is something we can handle, fill out the pairs. */
+61 -61
drivers/acpi/riscv/rimt.c
··· 61 61 return 0; 62 62 } 63 63 64 - /** 65 - * rimt_get_fwnode() - Retrieve fwnode associated with an RIMT node 66 - * 67 - * @node: RIMT table node to be looked-up 68 - * 69 - * Returns: fwnode_handle pointer on success, NULL on failure 70 - */ 71 - static struct fwnode_handle *rimt_get_fwnode(struct acpi_rimt_node *node) 72 - { 73 - struct fwnode_handle *fwnode = NULL; 74 - struct rimt_fwnode *curr; 75 - 76 - spin_lock(&rimt_fwnode_lock); 77 - list_for_each_entry(curr, &rimt_fwnode_list, list) { 78 - if (curr->rimt_node == node) { 79 - fwnode = curr->fwnode; 80 - break; 81 - } 82 - } 83 - spin_unlock(&rimt_fwnode_lock); 84 - 85 - return fwnode; 86 - } 87 - 88 64 static acpi_status rimt_match_node_callback(struct acpi_rimt_node *node, 89 65 void *context) 90 66 { ··· 178 202 return NULL; 179 203 } 180 204 205 + /* 206 + * RISC-V supports IOMMU as a PCI device or a platform device. 207 + * When it is a platform device, there should be a namespace device as 208 + * well along with RIMT. To create the link between RIMT information and 209 + * the platform device, the IOMMU driver should register itself with the 210 + * RIMT module. This is true for PCI based IOMMU as well. 211 + */ 212 + int rimt_iommu_register(struct device *dev) 213 + { 214 + struct fwnode_handle *rimt_fwnode; 215 + struct acpi_rimt_node *node; 216 + 217 + node = rimt_scan_node(ACPI_RIMT_NODE_TYPE_IOMMU, dev); 218 + if (!node) { 219 + pr_err("Could not find IOMMU node in RIMT\n"); 220 + return -ENODEV; 221 + } 222 + 223 + if (dev_is_pci(dev)) { 224 + rimt_fwnode = acpi_alloc_fwnode_static(); 225 + if (!rimt_fwnode) 226 + return -ENOMEM; 227 + 228 + rimt_fwnode->dev = dev; 229 + if (!dev->fwnode) 230 + dev->fwnode = rimt_fwnode; 231 + 232 + rimt_set_fwnode(node, rimt_fwnode); 233 + } else { 234 + rimt_set_fwnode(node, dev->fwnode); 235 + } 236 + 237 + return 0; 238 + } 239 + 240 + #ifdef CONFIG_IOMMU_API 241 + 242 + /** 243 + * rimt_get_fwnode() - Retrieve fwnode associated with an RIMT node 244 + * 245 + * @node: RIMT table node to be looked-up 246 + * 247 + * Returns: fwnode_handle pointer on success, NULL on failure 248 + */ 249 + static struct fwnode_handle *rimt_get_fwnode(struct acpi_rimt_node *node) 250 + { 251 + struct fwnode_handle *fwnode = NULL; 252 + struct rimt_fwnode *curr; 253 + 254 + spin_lock(&rimt_fwnode_lock); 255 + list_for_each_entry(curr, &rimt_fwnode_list, list) { 256 + if (curr->rimt_node == node) { 257 + fwnode = curr->fwnode; 258 + break; 259 + } 260 + } 261 + spin_unlock(&rimt_fwnode_lock); 262 + 263 + return fwnode; 264 + } 265 + 181 266 static bool rimt_pcie_rc_supports_ats(struct acpi_rimt_node *node) 182 267 { 183 268 struct acpi_rimt_pcie_rc *pci_rc; ··· 326 289 327 290 return NULL; 328 291 } 329 - 330 - /* 331 - * RISC-V supports IOMMU as a PCI device or a platform device. 332 - * When it is a platform device, there should be a namespace device as 333 - * well along with RIMT. To create the link between RIMT information and 334 - * the platform device, the IOMMU driver should register itself with the 335 - * RIMT module. This is true for PCI based IOMMU as well. 336 - */ 337 - int rimt_iommu_register(struct device *dev) 338 - { 339 - struct fwnode_handle *rimt_fwnode; 340 - struct acpi_rimt_node *node; 341 - 342 - node = rimt_scan_node(ACPI_RIMT_NODE_TYPE_IOMMU, dev); 343 - if (!node) { 344 - pr_err("Could not find IOMMU node in RIMT\n"); 345 - return -ENODEV; 346 - } 347 - 348 - if (dev_is_pci(dev)) { 349 - rimt_fwnode = acpi_alloc_fwnode_static(); 350 - if (!rimt_fwnode) 351 - return -ENOMEM; 352 - 353 - rimt_fwnode->dev = dev; 354 - if (!dev->fwnode) 355 - dev->fwnode = rimt_fwnode; 356 - 357 - rimt_set_fwnode(node, rimt_fwnode); 358 - } else { 359 - rimt_set_fwnode(node, dev->fwnode); 360 - } 361 - 362 - return 0; 363 - } 364 - 365 - #ifdef CONFIG_IOMMU_API 366 292 367 293 static struct acpi_rimt_node *rimt_node_map_id(struct acpi_rimt_node *node, 368 294 u32 id_in, u32 *id_out,