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

Merge tag 'cacheinfo-updates-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into driver-core-next

Sudeep writes:

cacheinfo and arch_topology updates for v6.4

The cache information can be extracted from either a Device Tree(DT),
the PPTT ACPI table, or arch registers (clidr_el1 for arm64).

When the DT is used but no cache properties are advertised, the current
code doesn't correctly fallback to using arch information. The changes
fixes the same and also assuse the that L1 data/instruction caches
are private and L2/higher caches are shared when the cache information
is missing in DT/ACPI and is derived form clidr_el1/arch registers.

Currently the cacheinfo is built from the primary CPU prior to secondary
CPUs boot, if the DT/ACPI description contains cache information.
However, if not present, it still reverts to the old behavior, which
allocates the cacheinfo memory on each secondary CPUs which causes
RT kernels to triggers a "BUG: sleeping function called from invalid
context".

The changes here attempts to enable automatic detection for RT kernels
when no DT/ACPI cache information is available, by pre-allocating
cacheinfo memory on the primary CPU.

* tag 'cacheinfo-updates-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
cacheinfo: Add use_arch[|_cache]_info field/function
arch_topology: Remove early cacheinfo error message if -ENOENT
cacheinfo: Check cache properties are present in DT
cacheinfo: Check sib_leaf in cache_leaves_are_shared()
cacheinfo: Allow early level detection when DT/ACPI info is missing/broken
cacheinfo: Add arm64 early level initializer implementation
cacheinfo: Add arch specific early level initializer

+139 -41
+22 -3
arch/arm64/kernel/cacheinfo.c
··· 38 38 this_leaf->type = type; 39 39 } 40 40 41 - int init_cache_level(unsigned int cpu) 41 + static void detect_cache_level(unsigned int *level_p, unsigned int *leaves_p) 42 42 { 43 43 unsigned int ctype, level, leaves; 44 - int fw_level, ret; 45 - struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); 46 44 47 45 for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) { 48 46 ctype = get_cache_type(level); ··· 51 53 /* Separate instruction and data caches */ 52 54 leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1; 53 55 } 56 + 57 + *level_p = level; 58 + *leaves_p = leaves; 59 + } 60 + 61 + int early_cache_level(unsigned int cpu) 62 + { 63 + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); 64 + 65 + detect_cache_level(&this_cpu_ci->num_levels, &this_cpu_ci->num_leaves); 66 + 67 + return 0; 68 + } 69 + 70 + int init_cache_level(unsigned int cpu) 71 + { 72 + unsigned int level, leaves; 73 + int fw_level, ret; 74 + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); 75 + 76 + detect_cache_level(&level, &leaves); 54 77 55 78 if (acpi_disabled) { 56 79 fw_level = of_find_last_cache_level(cpu);
+6 -5
drivers/base/arch_topology.c
··· 835 835 if (ret) { 836 836 /* 837 837 * Discard anything that was parsed if we hit an error so we 838 - * don't use partial information. 838 + * don't use partial information. But do not return yet to give 839 + * arch-specific early cache level detection a chance to run. 839 840 */ 840 841 reset_cpu_topology(); 841 - return; 842 842 } 843 843 844 844 for_each_possible_cpu(cpu) { 845 845 ret = fetch_cache_info(cpu); 846 - if (ret) { 846 + if (!ret) 847 + continue; 848 + else if (ret != -ENOENT) 847 849 pr_err("Early cacheinfo failed, ret = %d\n", ret); 848 - break; 849 - } 850 + return; 850 851 } 851 852 } 852 853
+103 -33
drivers/base/cacheinfo.c
··· 28 28 #define per_cpu_cacheinfo_idx(cpu, idx) \ 29 29 (per_cpu_cacheinfo(cpu) + (idx)) 30 30 31 + /* Set if no cache information is found in DT/ACPI. */ 32 + static bool use_arch_info; 33 + 31 34 struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu) 32 35 { 33 36 return ci_cacheinfo(cpu); ··· 41 38 { 42 39 /* 43 40 * For non DT/ACPI systems, assume unique level 1 caches, 44 - * system-wide shared caches for all other levels. This will be used 45 - * only if arch specific code has not populated shared_cpu_map 41 + * system-wide shared caches for all other levels. 46 42 */ 47 - if (!(IS_ENABLED(CONFIG_OF) || IS_ENABLED(CONFIG_ACPI))) 48 - return !(this_leaf->level == 1); 43 + if (!(IS_ENABLED(CONFIG_OF) || IS_ENABLED(CONFIG_ACPI)) || 44 + use_arch_info) 45 + return (this_leaf->level != 1) && (sib_leaf->level != 1); 49 46 50 47 if ((sib_leaf->attributes & CACHE_ID) && 51 48 (this_leaf->attributes & CACHE_ID)) ··· 82 79 } 83 80 84 81 #ifdef CONFIG_OF 82 + 83 + static bool of_check_cache_nodes(struct device_node *np); 84 + 85 85 /* OF properties to query for a given cache type */ 86 86 struct cache_type_info { 87 87 const char *size_prop; ··· 212 206 return -ENOENT; 213 207 } 214 208 209 + if (!of_check_cache_nodes(np)) { 210 + of_node_put(np); 211 + return -ENOENT; 212 + } 213 + 215 214 prev = np; 216 215 217 216 while (index < cache_leaves(cpu)) { ··· 239 228 return -ENOENT; 240 229 241 230 return 0; 231 + } 232 + 233 + static bool of_check_cache_nodes(struct device_node *np) 234 + { 235 + struct device_node *next; 236 + 237 + if (of_property_present(np, "cache-size") || 238 + of_property_present(np, "i-cache-size") || 239 + of_property_present(np, "d-cache-size") || 240 + of_property_present(np, "cache-unified")) 241 + return true; 242 + 243 + next = of_find_next_cache_node(np); 244 + if (next) { 245 + of_node_put(next); 246 + return true; 247 + } 248 + 249 + return false; 242 250 } 243 251 244 252 static int of_count_cache_leaves(struct device_node *np) ··· 290 260 struct device_node *np = of_cpu_device_node_get(cpu); 291 261 struct device_node *prev = NULL; 292 262 unsigned int levels = 0, leaves, level; 263 + 264 + if (!of_check_cache_nodes(np)) { 265 + of_node_put(np); 266 + return -ENOENT; 267 + } 293 268 294 269 leaves = of_count_cache_leaves(np); 295 270 if (leaves > 0) ··· 347 312 else if (!acpi_disabled) 348 313 ret = cache_setup_acpi(cpu); 349 314 315 + // Assume there is no cache information available in DT/ACPI from now. 316 + if (ret && use_arch_cache_info()) 317 + use_arch_info = true; 318 + 350 319 return ret; 351 320 } 352 321 ··· 369 330 * to update the shared cpu_map if the cache attributes were 370 331 * populated early before all the cpus are brought online 371 332 */ 372 - if (!last_level_cache_is_valid(cpu)) { 333 + if (!last_level_cache_is_valid(cpu) && !use_arch_info) { 373 334 ret = cache_setup_properties(cpu); 374 335 if (ret) 375 336 return ret; ··· 437 398 cache_shared_cpu_map_remove(cpu); 438 399 } 439 400 401 + int __weak early_cache_level(unsigned int cpu) 402 + { 403 + return -ENOENT; 404 + } 405 + 440 406 int __weak init_cache_level(unsigned int cpu) 441 407 { 442 408 return -ENOENT; ··· 467 423 468 424 int fetch_cache_info(unsigned int cpu) 469 425 { 470 - struct cpu_cacheinfo *this_cpu_ci; 426 + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); 471 427 unsigned int levels = 0, split_levels = 0; 472 428 int ret; 473 429 474 430 if (acpi_disabled) { 475 431 ret = init_of_cache_level(cpu); 476 - if (ret < 0) 477 - return ret; 478 432 } else { 479 433 ret = acpi_get_cache_info(cpu, &levels, &split_levels); 480 - if (ret < 0) 434 + if (!ret) { 435 + this_cpu_ci->num_levels = levels; 436 + /* 437 + * This assumes that: 438 + * - there cannot be any split caches (data/instruction) 439 + * above a unified cache 440 + * - data/instruction caches come by pair 441 + */ 442 + this_cpu_ci->num_leaves = levels + split_levels; 443 + } 444 + } 445 + 446 + if (ret || !cache_leaves(cpu)) { 447 + ret = early_cache_level(cpu); 448 + if (ret) 481 449 return ret; 482 450 483 - this_cpu_ci = get_cpu_cacheinfo(cpu); 484 - this_cpu_ci->num_levels = levels; 485 - /* 486 - * This assumes that: 487 - * - there cannot be any split caches (data/instruction) 488 - * above a unified cache 489 - * - data/instruction caches come by pair 490 - */ 491 - this_cpu_ci->num_leaves = levels + split_levels; 451 + if (!cache_leaves(cpu)) 452 + return -ENOENT; 453 + 454 + this_cpu_ci->early_ci_levels = true; 492 455 } 493 - if (!cache_leaves(cpu)) 456 + 457 + return allocate_cache_info(cpu); 458 + } 459 + 460 + static inline int init_level_allocate_ci(unsigned int cpu) 461 + { 462 + unsigned int early_leaves = cache_leaves(cpu); 463 + 464 + /* Since early initialization/allocation of the cacheinfo is allowed 465 + * via fetch_cache_info() and this also gets called as CPU hotplug 466 + * callbacks via cacheinfo_cpu_online, the init/alloc can be skipped 467 + * as it will happen only once (the cacheinfo memory is never freed). 468 + * Just populate the cacheinfo. However, if the cacheinfo has been 469 + * allocated early through the arch-specific early_cache_level() call, 470 + * there is a chance the info is wrong (this can happen on arm64). In 471 + * that case, call init_cache_level() anyway to give the arch-specific 472 + * code a chance to make things right. 473 + */ 474 + if (per_cpu_cacheinfo(cpu) && !ci_cacheinfo(cpu)->early_ci_levels) 475 + return 0; 476 + 477 + if (init_cache_level(cpu) || !cache_leaves(cpu)) 494 478 return -ENOENT; 495 479 480 + /* 481 + * Now that we have properly initialized the cache level info, make 482 + * sure we don't try to do that again the next time we are called 483 + * (e.g. as CPU hotplug callbacks). 484 + */ 485 + ci_cacheinfo(cpu)->early_ci_levels = false; 486 + 487 + if (cache_leaves(cpu) <= early_leaves) 488 + return 0; 489 + 490 + kfree(per_cpu_cacheinfo(cpu)); 496 491 return allocate_cache_info(cpu); 497 492 } 498 493 ··· 539 456 { 540 457 int ret; 541 458 542 - /* Since early initialization/allocation of the cacheinfo is allowed 543 - * via fetch_cache_info() and this also gets called as CPU hotplug 544 - * callbacks via cacheinfo_cpu_online, the init/alloc can be skipped 545 - * as it will happen only once (the cacheinfo memory is never freed). 546 - * Just populate the cacheinfo. 547 - */ 548 - if (per_cpu_cacheinfo(cpu)) 549 - goto populate_leaves; 550 - 551 - if (init_cache_level(cpu) || !cache_leaves(cpu)) 552 - return -ENOENT; 553 - 554 - ret = allocate_cache_info(cpu); 459 + ret = init_level_allocate_ci(cpu); 555 460 if (ret) 556 461 return ret; 557 462 558 - populate_leaves: 559 463 /* 560 464 * If LLC is valid the cache leaves were already populated so just go to 561 465 * update the cpu map.
+8
include/linux/cacheinfo.h
··· 76 76 unsigned int num_levels; 77 77 unsigned int num_leaves; 78 78 bool cpu_map_populated; 79 + bool early_ci_levels; 79 80 }; 80 81 81 82 struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu); 83 + int early_cache_level(unsigned int cpu); 82 84 int init_cache_level(unsigned int cpu); 83 85 int init_of_cache_level(unsigned int cpu); 84 86 int populate_cache_leaves(unsigned int cpu); ··· 130 128 131 129 return -1; 132 130 } 131 + 132 + #ifdef CONFIG_ARM64 133 + #define use_arch_cache_info() (true) 134 + #else 135 + #define use_arch_cache_info() (false) 136 + #endif 133 137 134 138 #endif /* _LINUX_CACHEINFO_H */