exo2: implement smc cpu off
This commit is contained in:
@@ -59,6 +59,40 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
void FlushDataCacheFrom(int loc) {
|
||||
for (int level = loc - 1; level >= 0; --level) {
|
||||
/* Set the selection register. */
|
||||
{
|
||||
util::BitPack32 csselr = {};
|
||||
csselr.Set<hw::CsselrEl1::InD>(0);
|
||||
csselr.Set<hw::CsselrEl1::Level>(level);
|
||||
HW_CPU_SET_CSSELR_EL1(csselr);
|
||||
}
|
||||
|
||||
/* Ensure that reordering doesn't occur around this operation. */
|
||||
hw::InstructionSynchronizationBarrier();
|
||||
|
||||
/* Get ccsidr. */
|
||||
util::BitPack32 ccsidr;
|
||||
HW_CPU_GET_CCSIDR_EL1(ccsidr);
|
||||
|
||||
/* Get cache size id info. */
|
||||
const int num_sets = ccsidr.Get<hw::CcsidrEl1::NumSets>() + 1;
|
||||
const int num_ways = ccsidr.Get<hw::CcsidrEl1::Associativity>() + 1;
|
||||
const int line_size = ccsidr.Get<hw::CcsidrEl1::LineSize>() + 4;
|
||||
|
||||
const int way_shift = 32 - FloorLog2(num_ways);
|
||||
const int set_shift = line_size;
|
||||
|
||||
for (int way = 0; way <= num_ways; way++) {
|
||||
for (int set = 0; set <= num_sets; set++) {
|
||||
const u64 value = (static_cast<u64>(way) << way_shift) | (static_cast<u64>(set) << set_shift) | (static_cast<u64>(level) << 1);
|
||||
__asm__ __volatile__("dc cisw, %[value]" :: [value]"r"(value) : "memory");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InvalidateDataCacheTo(int loc) {
|
||||
for (int level = 0; level < loc; ++level) {
|
||||
/* Set the selection register. */
|
||||
@@ -101,6 +135,12 @@ void FlushEntireDataCache() {
|
||||
FlushDataCacheTo(clidr.Get<hw::ClidrEl1::Loc>());
|
||||
}
|
||||
|
||||
void FlushEntireDataCacheLocal() {
|
||||
util::BitPack32 clidr;
|
||||
HW_CPU_GET_CLIDR_EL1(clidr);
|
||||
FlushDataCacheFrom(clidr.Get<hw::ClidrEl1::Louis>());
|
||||
}
|
||||
|
||||
void InvalidateEntireDataCache() {
|
||||
util::BitPack32 clidr;
|
||||
HW_CPU_GET_CLIDR_EL1(clidr);
|
||||
|
||||
Reference in New Issue
Block a user