summaryrefslogtreecommitdiff
path: root/big-little
diff options
context:
space:
mode:
Diffstat (limited to 'big-little')
-rw-r--r--big-little/include/misc.h2
-rw-r--r--big-little/virtualisor/cache_geom.c65
-rw-r--r--big-little/virtualisor/cpus/a15/a15.c102
-rw-r--r--big-little/virtualisor/cpus/a7/a7.c29
-rw-r--r--big-little/virtualisor/include/cache_geom.h33
-rw-r--r--big-little/virtualisor/virt_handle.c29
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;