/* RAC register offsets, relative to the HIF_CPU_BIUCTRL register base */ #define RAC_CONFIG0_REG (0x78) #define RACENPREF_MASK (0x3) #define RACPREFINST_SHIFT (0) #define RACENINST_SHIFT (2) #define RACPREFDATA_SHIFT (4) #define RACENDATA_SHIFT (6) #define RAC_CPU_SHIFT (8) #define RACCFG_MASK (0xff) #define RAC_CONFIG1_REG (0x7c) /* Brahma-B15 is a quad-core only design */ #define B15_RAC_FLUSH_REG (0x80) /* Brahma-B53 is an octo-core design */ #define B53_RAC_FLUSH_REG (0x84) #define FLUSH_RAC (1 << 0)
/* Bitmask to enable instruction and data prefetching with a 256-bytes stride */ #define RAC_DATA_INST_EN_MASK (1 << RACPREFINST_SHIFT | \
RACENPREF_MASK << RACENINST_SHIFT | \
1 << RACPREFDATA_SHIFT | \
RACENPREF_MASK << RACENDATA_SHIFT)
#define RAC_ENABLED 0 /* Special state where we want to bypass the spinlock and call directly * into the v7 cache maintenance operations during suspend/resume
*/ #define RAC_SUSPENDED 1
/* Initialization flag to avoid checking for b15_rac_base, and to prevent * multi-platform kernels from crashing here as well.
*/ staticunsignedlong b15_rac_flags;
__raw_writel(FLUSH_RAC, b15_rac_base + rac_flush_offset); do { /* This dmb() is required to force the Bus Interface Unit * to clean outstanding writes, and forces an idle cycle * to be inserted.
*/
dmb();
reg = __raw_readl(b15_rac_base + rac_flush_offset);
} while (reg & FLUSH_RAC);
}
staticinlinevoid __b15_rac_enable(u32 val)
{
__raw_writel(val, b15_rac_base + RAC_CONFIG0_REG); /* dsb() is required here to be consistent with __flush_icache_all() */
dsb();
}
/* The readahead cache present in the Brahma-B15 CPU is a special piece of * hardware after the integrated L2 cache of the B15 CPU complex whose purpose * is to prefetch instruction and/or data with a line size of either 64 bytes * or 256 bytes. The rationale is that the data-bus of the CPU interface is * optimized for 256-bytes transactions, and enabling the readahead cache * provides a significant performance boost we want it enabled (typically * twice the performance for a memcpy benchmark application). * * The readahead cache is transparent for Modified Virtual Addresses * cache maintenance operations: ICIMVAU, DCIMVAC, DCCMVAC, DCCMVAU and * DCCIMVAC. * * It is however not transparent for the following cache maintenance * operations: DCISW, DCCSW, DCCISW, ICIALLUIS and ICIALLU which is precisely * what we are patching here with our BUILD_RAC_CACHE_OP here.
*/
BUILD_RAC_CACHE_OP(kern_cache_all, nobarrier);
staticint b15_rac_reboot_notifier(struct notifier_block *nb, unsignedlong action, void *data)
{ /* During kexec, we are not yet migrated on the boot CPU, so we need to * make sure we are SMP safe here. Once the RAC is disabled, flag it as * suspended such that the hotplug notifier returns early.
*/ if (action == SYS_RESTART) {
spin_lock(&rac_lock);
b15_rac_disable_and_flush();
clear_bit(RAC_ENABLED, &b15_rac_flags);
set_bit(RAC_SUSPENDED, &b15_rac_flags);
spin_unlock(&rac_lock);
}
/* The CPU hotplug case is the most interesting one, we basically need to make * sure that the RAC is disabled for the entire system prior to having a CPU * die, in particular prior to this dying CPU having exited the coherency * domain. * * Once this CPU is marked dead, we can safely re-enable the RAC for the * remaining CPUs in the system which are still online. * * Offlining a CPU is the problematic case, onlining a CPU is not much of an * issue since the CPU and its cache-level hierarchy will start filling with * the RAC disabled, so L1 and L2 only. * * In this function, we should NOT have to verify any unsafe setting/condition * b15_rac_base: * * It is protected by the RAC_ENABLED flag which is cleared by default, and * being cleared when initial procedure is done. b15_rac_base had been set at * that time. * * RAC_ENABLED: * There is a small timing windows, in b15_rac_init(), between * cpuhp_setup_state_*() * ... * set RAC_ENABLED * However, there is no hotplug activity based on the Linux booting procedure. * * Since we have to disable RAC for all cores, we keep RAC on as long as as * possible (disable it as late as possible) to gain the cache benefit. * * Thus, dying/dead states are chosen here * * We are choosing not do disable the RAC on a per-CPU basis, here, if we did * we would want to consider disabling it as early as possible to benefit the * other active CPUs.
*/
/* Running on the dying CPU */ staticint b15_rac_dying_cpu(unsignedint cpu)
{ /* During kexec/reboot, the RAC is disabled via the reboot notifier * return early here.
*/ if (test_bit(RAC_SUSPENDED, &b15_rac_flags)) return 0;
spin_lock(&rac_lock);
/* Indicate that we are starting a hotplug procedure */
__clear_bit(RAC_ENABLED, &b15_rac_flags);
/* Disable the readahead cache and save its value to a global */
rac_config0_reg = b15_rac_disable_and_flush();
spin_unlock(&rac_lock);
return 0;
}
/* Running on a non-dying CPU */ staticint b15_rac_dead_cpu(unsignedint cpu)
{ /* During kexec/reboot, the RAC is disabled via the reboot notifier * return early here.
*/ if (test_bit(RAC_SUSPENDED, &b15_rac_flags)) return 0;
spin_lock(&rac_lock);
/* And enable it */
__b15_rac_enable(rac_config0_reg);
__set_bit(RAC_ENABLED, &b15_rac_flags);
spin_unlock(&rac_lock);
return 0;
}
staticint b15_rac_suspend(void)
{ /* Suspend the read-ahead cache oeprations, forcing our cache * implementation to fallback to the regular ARMv7 calls. * * We are guaranteed to be running on the boot CPU at this point and * with every other CPU quiesced, so setting RAC_SUSPENDED is not racy * here.
*/
rac_config0_reg = b15_rac_disable_and_flush();
set_bit(RAC_SUSPENDED, &b15_rac_flags);
return 0;
}
staticvoid b15_rac_resume(void)
{ /* Coming out of a S3 suspend/resume cycle, the read-ahead cache * register RAC_CONFIG0_REG will be restored to its default value, make * sure we re-enable it and set the enable flag, we are also guaranteed * to run on the boot CPU, so not racy again.
*/
__b15_rac_enable(rac_config0_reg);
clear_bit(RAC_SUSPENDED, &b15_rac_flags);
}
ret = register_reboot_notifier(&b15_rac_reboot_nb); if (ret) {
pr_err("failed to register reboot notifier\n");
iounmap(b15_rac_base); goto out;
}
if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) {
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CACHE_B15_RAC_DEAD, "arm/cache-b15-rac:dead",
NULL, b15_rac_dead_cpu); if (ret) goto out_unmap;
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CACHE_B15_RAC_DYING, "arm/cache-b15-rac:dying",
NULL, b15_rac_dying_cpu); if (ret) goto out_cpu_dead;
}
if (IS_ENABLED(CONFIG_PM_SLEEP))
register_syscore_ops(&b15_rac_syscore_ops);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.