/* 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 *intothev7cachemaintenanceoperationsduringsuspend/resume
*/ #define RAC_SUSPENDED 1
/* Initialization flag to avoid checking for b15_rac_base, and to prevent *multi-platformkernelsfromcrashinghereaswell.
*/ 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 *tocleanoutstandingwrites,andforcesanidlecycle *tobeinserted.
*/
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 *hardwareaftertheintegratedL2cacheoftheB15CPUcomplexwhosepurpose *istoprefetchinstructionand/ordatawithalinesizeofeither64bytes *or256bytes.Therationaleisthatthedata-busoftheCPUinterfaceis *optimizedfor256-bytestransactions,andenablingthereadaheadcache *providesasignificantperformanceboostwewantitenabled(typically *twicetheperformanceforamemcpybenchmarkapplication). * *ThereadaheadcacheistransparentforModifiedVirtualAddresses *cachemaintenanceoperations:ICIMVAU,DCIMVAC,DCCMVAC,DCCMVAUand *DCCIMVAC. * *Itishowevernottransparentforthefollowingcachemaintenance *operations:DCISW,DCCSW,DCCISW,ICIALLUISandICIALLUwhichisprecisely *whatwearepatchingherewithourBUILD_RAC_CACHE_OPhere.
*/
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 *makesureweareSMPsafehere.OncetheRACisdisabled,flagitas *suspendedsuchthatthehotplugnotifierreturnsearly.
*/ 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 *surethattheRACisdisabledfortheentiresystempriortohavingaCPU *die,inparticularpriortothisdyingCPUhavingexitedthecoherency *domain. * *OncethisCPUismarkeddead,wecansafelyre-enabletheRACforthe *remainingCPUsinthesystemwhicharestillonline. * *OffliningaCPUistheproblematiccase,onliningaCPUisnotmuchofan *issuesincetheCPUanditscache-levelhierarchywillstartfillingwith *theRACdisabled,soL1andL2only. * *Inthisfunction,weshouldNOThavetoverifyanyunsafesetting/condition *b15_rac_base: * *ItisprotectedbytheRAC_ENABLEDflagwhichisclearedbydefault,and *beingclearedwheninitialprocedureisdone.b15_rac_basehadbeensetat *thattime. * *RAC_ENABLED: *Thereisasmalltimingwindows,inb15_rac_init(),between *cpuhp_setup_state_*() *... *setRAC_ENABLED *However,thereisnohotplugactivitybasedontheLinuxbootingprocedure. * *SincewehavetodisableRACforallcores,wekeepRAConaslongasas *possible(disableitaslateaspossible)togainthecachebenefit. * *Thus,dying/deadstatesarechosenhere * *WearechoosingnotdodisabletheRAConaper-CPUbasis,here,ifwedid *wewouldwanttoconsiderdisablingitasearlyaspossibletobenefitthe *otheractiveCPUs.
*/
/* Running on the dying CPU */ staticint b15_rac_dying_cpu(unsignedint cpu)
{ /* During kexec/reboot, the RAC is disabled via the reboot notifier *returnearlyhere.
*/ if (test_bit(RAC_SUSPENDED, &b15_rac_flags)) return0;
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);
return0;
}
/* Running on a non-dying CPU */ staticint b15_rac_dead_cpu(unsignedint cpu)
{ /* During kexec/reboot, the RAC is disabled via the reboot notifier *returnearlyhere.
*/ if (test_bit(RAC_SUSPENDED, &b15_rac_flags)) return0;
spin_lock(&rac_lock);
/* And enable it */
__b15_rac_enable(rac_config0_reg);
__set_bit(RAC_ENABLED, &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.