Indeed, this is one of the problem I workaround with the patch.
One not much intrusive solution that I see now is to decouple the AArch64
definitions from AArch32. For example we can make add_cpreg_to_hashtable()
aware of the processor architecture with something like:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 90f85f1..7fd8dc8 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2232,6 +2232,13 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
/* Private utility function for define_one_arm_cp_reg_with_opaque():
* add a single reginfo struct to the hash table.
*/
+ int is_a64 = (&cpu->env)->aarch64;
+ if (r->state == ARM_CP_STATE_BOTH && state == ARM_CP_STATE_AA64
+ && !is_a64) {
+ /* no need of the AArch64 cp definition */
+ return;
+ }
+
uint32_t *key = g_new(uint32_t, 1);
ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
@@ -2241,9 +2248,14 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
* view handles that. AArch64 also handles reset.
* We assume it is a cp15 register.
*/
+ if (is_a64) {
+ /* this is an AArch32 view */
+ r2->type |= ARM_CP_NO_MIGRATE;
+ r2->resetfn = arm_cp_reset_ignore;
+ } else {
+ /* this is the AArch32 register itself */
+ }
r2->cp = 15;
- r2->type |= ARM_CP_NO_MIGRATE;
- r2->resetfn = arm_cp_reset_ignore;
#ifdef HOST_WORDS_BIGENDIAN
if (r2->fieldoffset) {
r2->fieldoffset += sizeof(uint32_t);
So, if the processor does not start in AArch64 mode, we only add the AArch32
version of the ARM_CP_STATE_BOTH register to the hashtable, otherwise nothing
changes and we add the two views of the register. This approach works only
if all the 64bit CPUs will always start in 64 bit mode.
In my opinion, other solutions would require to revisit the idea of
ARM_CP_STATE_BOTH in favour of distinct definitions of the registers with
multiple views (like VBAR for AArch32 and VBAR_EL1 for AArch64).
Regards,
alvise