On Mon, 9 Nov 2020 11:04:49 +0800 Ying Fang <fangyi...@huawei.com> wrote:
> Add the CPUCacheInfo structure to hold cpu cache information for ARM cpus. > A classic three level cache topology is used here. The default cache > capacity is given and userspace can overwrite these values. > > Signed-off-by: Ying Fang <fangyi...@huawei.com> I may be missing it another patch, but to add an L3 cache you need to also supply a few CSR values. CLIDR needs to reflect that there is an L3 present and you need a CSIDR[3] entry to describe it. 0xB200123 should work for CLIDR. I'm too lazy to figure out a CSIDR[3] value :) Without those, Linux isn't going to pick up the PPTT entries etc when building cacheinfo. It only uses PPTT to update or supplement the information gained from those CSRs. Jonathan > --- > target/arm/cpu.c | 42 ++++++++++++++++++++++++++++++++++++++++++ > target/arm/cpu.h | 27 +++++++++++++++++++++++++++ > 2 files changed, 69 insertions(+) > > diff --git a/target/arm/cpu.c b/target/arm/cpu.c > index 056319859f..f1bac7452c 100644 > --- a/target/arm/cpu.c > +++ b/target/arm/cpu.c > @@ -27,6 +27,7 @@ > #include "qapi/visitor.h" > #include "cpu.h" > #include "internals.h" > +#include "qemu/units.h" > #include "exec/exec-all.h" > #include "hw/qdev-properties.h" > #if !defined(CONFIG_USER_ONLY) > @@ -997,6 +998,45 @@ uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz) > return (Aff1 << ARM_AFF1_SHIFT) | Aff0; > } > > +static CPUCaches default_cache_info = { > + .l1d_cache = &(CPUCacheInfo) { > + .type = DATA_CACHE, > + .level = 1, > + .size = 64 * KiB, > + .line_size = 64, > + .associativity = 4, > + .sets = 256, > + .attributes = 0x02, > + }, > + .l1i_cache = &(CPUCacheInfo) { > + .type = INSTRUCTION_CACHE, > + .level = 1, > + .size = 64 * KiB, > + .line_size = 64, > + .associativity = 4, > + .sets = 256, > + .attributes = 0x04, > + }, > + .l2_cache = &(CPUCacheInfo) { > + .type = UNIFIED_CACHE, > + .level = 2, > + .size = 512 * KiB, > + .line_size = 64, > + .associativity = 8, > + .sets = 1024, > + .attributes = 0x0a, > + }, > + .l3_cache = &(CPUCacheInfo) { > + .type = UNIFIED_CACHE, > + .level = 3, > + .size = 65536 * KiB, > + .line_size = 64, > + .associativity = 15, > + .sets = 2048, > + .attributes = 0x0a, > + }, > +}; > + > static void cpreg_hashtable_data_destroy(gpointer data) > { > /* > @@ -1841,6 +1881,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error > **errp) > } > } > > + cpu->caches = default_cache_info; > + > qemu_init_vcpu(cs); > cpu_reset(cs); > > diff --git a/target/arm/cpu.h b/target/arm/cpu.h > index cfff1b5c8f..dbc33a9802 100644 > --- a/target/arm/cpu.h > +++ b/target/arm/cpu.h > @@ -746,6 +746,30 @@ typedef enum ARMPSCIState { > > typedef struct ARMISARegisters ARMISARegisters; > > +/* Cache information type */ > +enum CacheType { > + DATA_CACHE, > + INSTRUCTION_CACHE, > + UNIFIED_CACHE > +}; > + > +typedef struct CPUCacheInfo { > + enum CacheType type; /* Cache Type*/ > + uint8_t level; > + uint32_t size; /* Size in bytes */ > + uint16_t line_size; /* Line size in bytes */ > + uint8_t associativity; /* Cache associativity */ > + uint32_t sets; /* Number of sets */ > + uint8_t attributes; /* Cache attributest */ > +} CPUCacheInfo; > + > +typedef struct CPUCaches { > + CPUCacheInfo *l1d_cache; > + CPUCacheInfo *l1i_cache; > + CPUCacheInfo *l2_cache; > + CPUCacheInfo *l3_cache; > +} CPUCaches; > + > /** > * ARMCPU: > * @env: #CPUARMState > @@ -987,6 +1011,9 @@ struct ARMCPU { > > /* Generic timer counter frequency, in Hz */ > uint64_t gt_cntfrq_hz; > + > + /* CPU cache information */ > + CPUCaches caches; > }; > > unsigned int gt_cntfrq_period_ns(ARMCPU *cpu);