diff options
Diffstat (limited to 'big-little')
-rw-r--r-- | big-little/include/misc.h | 2 | ||||
-rw-r--r-- | big-little/virtualisor/cache_geom.c | 65 | ||||
-rw-r--r-- | big-little/virtualisor/cpus/a15/a15.c | 102 | ||||
-rw-r--r-- | big-little/virtualisor/cpus/a7/a7.c | 29 | ||||
-rw-r--r-- | big-little/virtualisor/include/cache_geom.h | 33 | ||||
-rw-r--r-- | big-little/virtualisor/virt_handle.c | 29 |
6 files changed, 202 insertions, 58 deletions
diff --git a/big-little/include/misc.h b/big-little/include/misc.h index e1957aa..0b15d5a 100644 --- a/big-little/include/misc.h +++ b/big-little/include/misc.h @@ -347,6 +347,8 @@ #define SMC_SEC_SHUTDOWN 0x2 #define MAX_CACHE_LEVELS 0x8 +/* Data/unified and instruction cache */ +#define MAX_CACHE_VARIANTS 0x2 #define CRN_C0 0x0 #define CRN_C7 0x7 #define CRN_C9 0x9 diff --git a/big-little/virtualisor/cache_geom.c b/big-little/virtualisor/cache_geom.c index 17c3ee6..7bcb42b 100644 --- a/big-little/virtualisor/cache_geom.c +++ b/big-little/virtualisor/cache_geom.c @@ -36,51 +36,50 @@ static unsigned cm_ignline_cnt[NUM_CPUS][MAX_CACHE_LEVELS] = { 0 }; static unsigned cm_extline_cnt[NUM_CPUS][MAX_CACHE_LEVELS] = { 0 }; /* - * Iterate through all the implemented cache - * levels and save the geometry at each level. + * Iterate through all the implemented cache levels and save the geometry at + * each level. * */ void find_cache_geometry(cache_geometry * cg_ptr) { - unsigned ctr, clidr, ccsidr, csselr, old_csselr; + unsigned ctr, csselr; - /* Save Cache size selection register */ - old_csselr = read_csselr(); - clidr = read_clidr(); - cg_ptr->clidr = clidr; + /* Save cache size selection register */ + csselr = read_csselr(); - for (ctr = 0; ctr < MAX_CACHE_LEVELS; ctr++) { - unsigned cache_type = get_cache_type(clidr, ctr); + cg_ptr->clidr = read_clidr(); - /* Only seperate and Unifiied caches */ - if (cache_type >= 0x3) { - /* - * Choose the cache level & Data or Unified cache - * as there are no set/way operations on the ICache - */ - csselr = ctr << 1; - write_csselr(csselr); + for (ctr = 0; ctr < MAX_CACHE_LEVELS; ctr++) { + unsigned cache_type = get_cache_type(cg_ptr->clidr, ctr); + if (cache_type == 0x03) { + /* instruction cache */ + write_csselr((ctr << 1) | CIND_INST); isb(); - + cg_ptr->ccsidr[ctr][CIND_INST] = read_ccsidr(); + /* data cache */ + write_csselr(ctr << 1); + isb(); + cg_ptr->ccsidr[ctr][CIND_DATA] = read_ccsidr(); + } + else if (cache_type == 0x04) { + /* unified cache */ + write_csselr(ctr << 1); + isb(); + cg_ptr->ccsidr[ctr][CIND_UNIF] = read_ccsidr(); + } + else { /* - * Read the CCSIDR to record information about this - * cache level. - */ - ccsidr = read_ccsidr(); - cg_ptr->ccsidr[ctr] = ccsidr; - - } else { - /* - * Stop scanning at the first invalid/unsupported - * cache level + * Stop scanning at the first invalid/unsupported cache + * level */ break; } + } - /* Restore Cache size selection register */ - write_csselr(old_csselr); + /* Restore cache size selection register */ + write_csselr(csselr); return; } @@ -203,7 +202,7 @@ unsigned map_cache_geometries(cache_geometry * hcg_ptr, /* * Enable bit for trapping set/way operations & - * Cache identification regs + * cache identification registers */ hcr = read_hcr(); hcr |= HCR_TSW | HCR_TID2; @@ -212,7 +211,6 @@ unsigned map_cache_geometries(cache_geometry * hcg_ptr, isb(); } else { - /* Find the cache geometry on the target cpu */ find_cache_geometry(tcg_ptr); @@ -235,7 +233,8 @@ unsigned map_cache_geometries(cache_geometry * hcg_ptr, void handle_cm_op(unsigned reg, void (*op_handler) (unsigned), cache_geometry * hcg_ptr, - cache_geometry * tcg_ptr, cache_diff * cd_ptr) + cache_geometry * tcg_ptr, + cache_diff * cd_ptr) { unsigned clvl = 0, cpu_id = read_cpuid(); unsigned tc_assoc = 0, tc_numsets = 0, tc_linesz = 0; diff --git a/big-little/virtualisor/cpus/a15/a15.c b/big-little/virtualisor/cpus/a15/a15.c index 17c91a4..213ae67 100644 --- a/big-little/virtualisor/cpus/a15/a15.c +++ b/big-little/virtualisor/cpus/a15/a15.c @@ -22,17 +22,56 @@ #include "bl.h" #include "virtualisor.h" +#include "cache_geom.h" #include "a15.h" /* Forward declaration */ static virt_descriptor a15_virt_desc; +extern cache_geometry host_cache_geometry[]; +extern cache_geometry target_cache_geometry[]; + /* - * Dummy functions for setting up any cpu - * specific traps. + * Functions to handle, save, restore and setup any CPU specific traps. */ unsigned a15_trap_handle(gp_regs * regs, unsigned hsr, unsigned sibling_cpu) { + /* + * Correct the L1 instruction cache CCSIDR value which was incorrectly + * set in the default CP15 trap handle function. + */ + if (hsr >> 26 == TRAP_CP15_32) { + unsigned Op1, Op2, CRn, CRm, Rt, csselr, level, ind; + + Op2 = (hsr >> 17) & 0x7; + Op1 = (hsr >> 14) & 0x7; + CRn = (hsr >> 10) & 0xf; + Rt = (hsr >> 5) & 0xf; + CRm = (hsr >> 1) & 0xf; + + csselr = read_csselr(); + level = get_cache_level(csselr); + ind = get_cache_ind(csselr); + + if (CRn == CRN_C0 && Op1 == 1 && CRm == 0 && Op2 == CCSIDR && + level == 0 && ind == CIND_INST) { + unsigned cpu_id = read_cpuid(); + + /* + * Initialize cg_ptr to host_cache_geometry for system + * configuration [BC=x, TC=A15, HC=A7] and to + * target_cache_geometry for Virtualizer configuration + * [BC=x, TC=A7, HC=A15] + */ + + cache_geometry * cg_ptr = (IS_TGT_CLUSTER) ? + &host_cache_geometry[cpu_id] : + &target_cache_geometry[cpu_id]; + + regs->r[Rt] = cg_ptr->ccsidr[level][ind]; + } + } + return 0; } @@ -43,6 +82,22 @@ unsigned a15_trap_save(unsigned first_cpu, unsigned sibling_cpu) unsigned a15_trap_restore(unsigned first_cpu, unsigned sibling_cpu) { + if (sibling_cpu == A7) { + unsigned hcr = read_hcr(); + + /* + * Restore (enable) bit for trapping cache identification + * registers. This is a necessary step on Virtualizer + * configuration [BC=x, TC=A15, HC=A7] and a redundant + * step on Virtualizer configuration + * [BC=x, TC=A7, HC=A15]. + */ + + hcr |= HCR_TID2; + write_hcr(hcr); + dsb(); + isb(); + } return 0; } @@ -50,6 +105,49 @@ unsigned a15_trap_setup(unsigned first_cpu, unsigned sibling_cpu) { if (switcher) { + if (sibling_cpu == A7) { + unsigned hcr = read_hcr(); + + /* + * Initialize the L1 instruction cache CSSIDR value on + * the boot cluster statically because the Virtualizer + * relies on this information even before the + * counterpart cluster is initialized dynamically. + */ + + if (IS_BOOT_CLUSTER) { + unsigned cpu_id = read_cpuid(); + + /* + * Initialize cg_ptr to host_cache_geometry for + * Virtualizer configuration + * [BC=x, TC=A15, HC=A7] and to + * target_cache_geometry for Virtualizer + * configuration [BC=x, TC=A7, HC=A15]. + */ + + cache_geometry * cg_ptr = (IS_TGT_CLUSTER) ? + &host_cache_geometry[cpu_id] : + &target_cache_geometry[cpu_id]; + + + cg_ptr->ccsidr[0][CIND_INST] = + CACHE_A7_L1_INST_CCSIDR; + } + + /* + * Enable bit for trapping cache identification + * registers. This is a necessary step on Virtualizer + * configuration [BC=x, TC=A15, HC=A7] and a redundant + * step on Virtualizer configuration + * [BC=x, TC=A7, HC=A15]. + */ + + hcr |= HCR_TID2; + write_hcr(hcr); + dsb(); + isb(); + } } else { /* Always on */ } diff --git a/big-little/virtualisor/cpus/a7/a7.c b/big-little/virtualisor/cpus/a7/a7.c index e9e16af..d39f857 100644 --- a/big-little/virtualisor/cpus/a7/a7.c +++ b/big-little/virtualisor/cpus/a7/a7.c @@ -22,17 +22,42 @@ #include "bl.h" #include "virtualisor.h" +#include "cache_geom.h" #include "a7.h" /* Forward declaration */ static virt_descriptor a7_virt_desc; +extern cache_geometry host_cache_geometry[]; +extern cache_geometry target_cache_geometry[]; + /* - * Dummy functions for setting up any cpu - * specific traps. + * Functions to handle, save, restore and setup any CPU specific traps. */ unsigned a7_trap_handle(gp_regs * regs, unsigned hsr, unsigned sibling_cpu) { + /* + * Correct the L1 instruction cache CCSIDR value which was incorrectly + * set in the default CP15 trap handle function. + */ + if (hsr >> 26 == TRAP_CP15_32) { + unsigned Op1, Op2, CRn, CRm, Rt, csselr, level, ind; + + Op2 = (hsr >> 17) & 0x7; + Op1 = (hsr >> 14) & 0x7; + CRn = (hsr >> 10) & 0xf; + Rt = (hsr >> 5) & 0xf; + CRm = (hsr >> 1) & 0xf; + + csselr = read_csselr(); + level = get_cache_level(csselr); + ind = get_cache_ind(csselr); + + if (CRn == CRN_C0 && Op1 == 1 && CRm == 0 && Op2 == CCSIDR && + level == 0 && ind == CIND_INST) + regs->r[Rt] = read_ccsidr(); + } + return 0; } diff --git a/big-little/virtualisor/include/cache_geom.h b/big-little/virtualisor/include/cache_geom.h index 654a0f0..f162337 100644 --- a/big-little/virtualisor/include/cache_geom.h +++ b/big-little/virtualisor/include/cache_geom.h @@ -23,19 +23,28 @@ #ifndef __CACHE_GEOM_H__ #define __CACHE_GEOM_H__ -#define MAX_CACHE_LEVELS 0x8 +#include "misc.h" /* Target cpu cache relative to host cpu cache size */ #define TCSZ_EQUAL 0x0 #define TCSZ_SMALL 0x1 #define TCSZ_BIG 0x2 +/* Cache Instruction not Data bit, CSSELR[0] */ +#define CIND_DATA 0x0 /* Data cache */ +#define CIND_UNIF CIND_DATA /* Unified cache */ +#define CIND_INST 0x1 /* Instruction cache */ + +/* A7 L1 instruction cache CCSIDR value */ +#define CACHE_A7_L1_INST_CCSIDR 0x203FE009 + #define get_setway_reg(a, b , c, d, e) ((a << __clz(b)) | (c << (d + 4)) | (e << 1)) #define get_cache_type(clidr, lvl) ((clidr >> (lvl * 0x3)) & 0x7) -#define get_cache_level(reg) (reg >> 1) & 0x7 -#define get_cache_linesz(cg, lvl) (cg->ccsidr[lvl] & 0x7) -#define get_cache_assoc(cg, lvl) ((cg->ccsidr[lvl] >> 3) & 0x3ff) -#define get_cache_numsets(cg, lvl) ((cg->ccsidr[lvl] >> 13) & 0x7fff) +#define get_cache_level(reg) ((reg >> 1) & 0x7) +#define get_cache_ind(reg) (reg & 0x1) +#define get_cache_linesz(cg, lvl) (cg->ccsidr[lvl][CIND_DATA] & 0x7) +#define get_cache_assoc(cg, lvl) ((cg->ccsidr[lvl][CIND_DATA] >> 3) & 0x3ff) +#define get_cache_numsets(cg, lvl) ((cg->ccsidr[lvl][CIND_DATA] >> 13) & 0x7fff) /* * Data structure that stores the foreseeable differences @@ -76,8 +85,8 @@ typedef struct cache_geom { * the OS thinks its operating on. */ unsigned csselr; - /* One for each cache level */ - unsigned ccsidr[MAX_CACHE_LEVELS]; + /* One for each cache level and variant */ + unsigned ccsidr[MAX_CACHE_LEVELS][MAX_CACHE_VARIANTS]; } cache_geometry; /* @@ -91,12 +100,12 @@ typedef struct cache_stats { unsigned cmpl_cmop_cnt; } cache_stats; -extern unsigned map_cache_geometries(cache_geometry *, - cache_geometry *, cache_diff *); +extern unsigned map_cache_geometries(cache_geometry *, cache_geometry *, + cache_diff *); extern void find_cache_geometry(cache_geometry *); extern void find_cache_diff(cache_geometry *, cache_geometry *, cache_diff *); -extern void handle_cm_op(unsigned, - void (*)(unsigned), - cache_geometry *, cache_geometry *, cache_diff *); +extern void handle_cm_op(unsigned, void (*)(unsigned), cache_geometry *, + cache_geometry *, cache_diff *); +//extern void stat_init_host_cache_geometry(cache_geometry *); #endif /* __CACHE_GEOM_H__ */ diff --git a/big-little/virtualisor/virt_handle.c b/big-little/virtualisor/virt_handle.c index 092af67..da163cf 100644 --- a/big-little/virtualisor/virt_handle.c +++ b/big-little/virtualisor/virt_handle.c @@ -180,20 +180,32 @@ void trap_cp15_mrc_mcr_handle(unsigned hsr, gp_regs * regs) switch (CRm) { case 0: switch (Op2) { + unsigned csselr, level, ind; case CCSIDR: if (write) goto error; + /* + * The L1 instruction cache CCSIDR + * value is incorrectly set on A7 and + * A15 for Virtualizer configuration + * [BC=x, TC=A15, HC=A7]. + * The error is later corrected in the + * A7 or A15 specific trap function. + */ + csselr = target_cache_geometry[cpu_id]. + csselr; + level = get_cache_level(csselr); + ind = get_cache_ind(csselr); regs->r[Rt] = - target_cache_geometry[cpu_id].ccsidr - [get_cache_level - (target_cache_geometry - [cpu_id].csselr)]; + target_cache_geometry[cpu_id]. + ccsidr[level][ind]; break; case CLIDR: if (write) goto error; regs->r[Rt] = - target_cache_geometry[cpu_id].clidr; + target_cache_geometry[cpu_id]. + clidr; break; case AIDR: if (write) @@ -215,14 +227,13 @@ void trap_cp15_mrc_mcr_handle(unsigned hsr, gp_regs * regs) case CSSELR: if (write) { target_cache_geometry - [cpu_id].csselr = - regs->r[Rt]; + [cpu_id].csselr = regs->r[Rt]; write_csselr(regs->r[Rt]); } else regs->r[Rt] = - target_cache_geometry - [cpu_id].csselr; + target_cache_geometry + [cpu_id].csselr; break; default: goto error; |