* [PATCH v4 0/7] Add ARM Cortex-R52 CPU
@ 2022-10-23 15:36 tobias.roehmel
2022-10-23 15:36 ` [PATCH v4 1/7] target/arm: Don't add all MIDR aliases for cores that immplement PMSA tobias.roehmel
` (7 more replies)
0 siblings, 8 replies; 18+ messages in thread
From: tobias.roehmel @ 2022-10-23 15:36 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Tobias Röhmel
From: Tobias Röhmel <quic_trohmel@quicinc.com>
Thanks again for all the help!
Here is v4:
2. Made patch cleaner
3. Changed commit message
4. Replaced V8_R flag with ARM_FEATURE_PMSA|ARM_FEATURE_V8
5.
Reworked the code to use existing pmsav7 variables
Added migration support
Added VSCTLR:
I didn't add any functionality for it because I think
Qemu doesn't model the behaviour it influences.
6.
Lots of cleanup. I think I overcomplicated this a bit because
of a misunderstanding. I thought HCR_VM is independent of enabling
the different MPUs, but I see now that it doesn't make sense to enable
HCR_VM when the MPUs are not enabled. I also think that there is an Error
in the armv8-r manual supplement in Figure C1-3. With all that figured out
the code for pmsav8r doesn't look that different from pmsav7 :)
Tobias Röhmel (7):
target/arm: Don't add all MIDR aliases for cores that immplement PMSA
target/arm: Make RVBAR available for all ARMv8 CPUs
target/arm: Make stage_2_format for cache attributes optional
target/arm: Enable TTBCR_EAE for ARMv8-R AArch32
target/arm: Add PMSAv8r registers
target/arm: Add PMSAv8r functionality
target/arm: Add ARM Cortex-R52 CPU
target/arm/cpu.c | 32 +++-
target/arm/cpu.h | 12 ++
target/arm/cpu_tcg.c | 42 +++++
target/arm/debug_helper.c | 3 +
target/arm/helper.c | 327 ++++++++++++++++++++++++++++++++++++--
target/arm/internals.h | 4 +
target/arm/machine.c | 28 ++++
target/arm/ptw.c | 148 ++++++++++++++---
target/arm/tlb_helper.c | 3 +
9 files changed, 562 insertions(+), 37 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v4 1/7] target/arm: Don't add all MIDR aliases for cores that immplement PMSA
2022-10-23 15:36 [PATCH v4 0/7] Add ARM Cortex-R52 CPU tobias.roehmel
@ 2022-10-23 15:36 ` tobias.roehmel
2022-10-23 23:06 ` Richard Henderson
2022-10-23 15:36 ` [PATCH v4 2/7] target/arm: Make RVBAR available for all ARMv8 CPUs tobias.roehmel
` (6 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: tobias.roehmel @ 2022-10-23 15:36 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Tobias Röhmel
From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
Cores with PMSA have the MPUIR register which has the
same encoding as the MIDR alias with opc2=4. So we only
add that alias if we are not realizing a core that
implements PMSA.
Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
---
target/arm/helper.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index db3b1ea72d..3c517356e1 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8025,10 +8025,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
.access = PL1_R, .type = ARM_CP_NO_RAW, .resetvalue = cpu->midr,
.fieldoffset = offsetof(CPUARMState, cp15.c0_cpuid),
.readfn = midr_read },
- /* crn = 0 op1 = 0 crm = 0 op2 = 4,7 : AArch32 aliases of MIDR */
- { .name = "MIDR", .type = ARM_CP_ALIAS | ARM_CP_CONST,
- .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 4,
- .access = PL1_R, .resetvalue = cpu->midr },
+ /* crn = 0 op1 = 0 crm = 0 op2 = 7 : AArch32 aliases of MIDR */
{ .name = "MIDR", .type = ARM_CP_ALIAS | ARM_CP_CONST,
.cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 7,
.access = PL1_R, .resetvalue = cpu->midr },
@@ -8038,6 +8035,11 @@ void register_cp_regs_for_features(ARMCPU *cpu)
.accessfn = access_aa64_tid1,
.type = ARM_CP_CONST, .resetvalue = cpu->revidr },
};
+ ARMCPRegInfo id_v8_midr_alias_cp_reginfo = {
+ .name = "MIDR", .type = ARM_CP_ALIAS | ARM_CP_CONST,
+ .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 4,
+ .access = PL1_R, .resetvalue = cpu->midr
+ };
ARMCPRegInfo id_cp_reginfo[] = {
/* These are common to v8 and pre-v8 */
{ .name = "CTR",
@@ -8101,8 +8103,12 @@ void register_cp_regs_for_features(ARMCPU *cpu)
id_mpuir_reginfo.access = PL1_RW;
id_tlbtr_reginfo.access = PL1_RW;
}
+
if (arm_feature(env, ARM_FEATURE_V8)) {
define_arm_cp_regs(cpu, id_v8_midr_cp_reginfo);
+ if (!arm_feature(env, ARM_FEATURE_PMSA)) {
+ define_one_arm_cp_reg(cpu, &id_v8_midr_alias_cp_reginfo);
+ }
} else {
define_arm_cp_regs(cpu, id_pre_v8_midr_cp_reginfo);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 2/7] target/arm: Make RVBAR available for all ARMv8 CPUs
2022-10-23 15:36 [PATCH v4 0/7] Add ARM Cortex-R52 CPU tobias.roehmel
2022-10-23 15:36 ` [PATCH v4 1/7] target/arm: Don't add all MIDR aliases for cores that immplement PMSA tobias.roehmel
@ 2022-10-23 15:36 ` tobias.roehmel
2022-11-14 17:04 ` Peter Maydell
2022-10-23 15:36 ` [PATCH v4 3/7] target/arm: Make stage_2_format for cache attributes optional tobias.roehmel
` (5 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: tobias.roehmel @ 2022-10-23 15:36 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Tobias Röhmel
From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
RVBAR shadows RVBAR_ELx where x is the highest exception
level if the highest EL is not EL3. This patch also allows
ARMv8 CPUs to change the reset address with
the rvbar property.
Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
---
target/arm/cpu.c | 6 +++++-
target/arm/helper.c | 23 +++++++++++++++--------
2 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 94ca6f163f..b642749d6d 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -281,6 +281,10 @@ static void arm_cpu_reset(DeviceState *dev)
env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
CPACR, CP11, 3);
#endif
+ if (arm_feature(env, ARM_FEATURE_V8)) {
+ env->cp15.rvbar = cpu->rvbar_prop;
+ env->regs[15] = cpu->rvbar_prop;
+ }
}
#if defined(CONFIG_USER_ONLY)
@@ -1306,7 +1310,7 @@ void arm_cpu_post_init(Object *obj)
qdev_property_add_static(DEVICE(obj), &arm_cpu_reset_hivecs_property);
}
- if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
object_property_add_uint64_ptr(obj, "rvbar",
&cpu->rvbar_prop,
OBJ_PROP_FLAG_READWRITE);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 3c517356e1..2e9e420d4e 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -7768,8 +7768,8 @@ void register_cp_regs_for_features(ARMCPU *cpu)
if (!arm_feature(env, ARM_FEATURE_EL3) &&
!arm_feature(env, ARM_FEATURE_EL2)) {
ARMCPRegInfo rvbar = {
- .name = "RVBAR_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
+ .name = "RVBAR_EL1", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
.access = PL1_R,
.fieldoffset = offsetof(CPUARMState, cp15.rvbar),
};
@@ -7859,13 +7859,20 @@ void register_cp_regs_for_features(ARMCPU *cpu)
}
/* RVBAR_EL2 is only implemented if EL2 is the highest EL */
if (!arm_feature(env, ARM_FEATURE_EL3)) {
- ARMCPRegInfo rvbar = {
- .name = "RVBAR_EL2", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 1,
- .access = PL2_R,
- .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
+ ARMCPRegInfo rvbar[] = {
+ {
+ .name = "RVBAR_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 1,
+ .access = PL2_R,
+ .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
+ },
+ { .name = "RVBAR", .type = ARM_CP_ALIAS,
+ .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
+ .access = PL2_R,
+ .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
+ },
};
- define_one_arm_cp_reg(cpu, &rvbar);
+ define_arm_cp_regs(cpu, rvbar);
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 3/7] target/arm: Make stage_2_format for cache attributes optional
2022-10-23 15:36 [PATCH v4 0/7] Add ARM Cortex-R52 CPU tobias.roehmel
2022-10-23 15:36 ` [PATCH v4 1/7] target/arm: Don't add all MIDR aliases for cores that immplement PMSA tobias.roehmel
2022-10-23 15:36 ` [PATCH v4 2/7] target/arm: Make RVBAR available for all ARMv8 CPUs tobias.roehmel
@ 2022-10-23 15:36 ` tobias.roehmel
2022-11-14 17:13 ` Peter Maydell
2022-10-23 15:36 ` [PATCH v4 4/7] target/arm: Enable TTBCR_EAE for ARMv8-R AArch32 tobias.roehmel
` (4 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: tobias.roehmel @ 2022-10-23 15:36 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Tobias Röhmel
From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
The v8R PMSAv8 has a two-stage MPU translation process, but, unlike
VMSAv8, the stage 2 attributes are in the same format as the stage 1
attributes (8-bit MAIR format). Rather than converting the MAIR
format to the format used for VMSA stage 2 (bits [5:2] of a VMSA
stage 2 descriptor) and then converting back to do the attribute
combination, allow combined_attrs_nofwb() to accept s2 attributes
that are already in the MAIR format.
We move the assert() to combined_attrs_fwb(), because that function
really does require a VMSA stage 2 attribute format. (We will never
get there for v8R, because PMSAv8 does not implement FEAT_S2FWB.)
Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
---
target/arm/ptw.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 2ddfc028ab..db50715fa7 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -2105,7 +2105,11 @@ static uint8_t combined_attrs_nofwb(CPUARMState *env,
{
uint8_t s1lo, s2lo, s1hi, s2hi, s2_mair_attrs, ret_attrs;
- s2_mair_attrs = convert_stage2_attrs(env, s2.attrs);
+ if (s2.is_s2_format) {
+ s2_mair_attrs = convert_stage2_attrs(env, s2.attrs);
+ } else {
+ s2_mair_attrs = s2.attrs;
+ }
s1lo = extract32(s1.attrs, 0, 4);
s2lo = extract32(s2_mair_attrs, 0, 4);
@@ -2163,6 +2167,8 @@ static uint8_t force_cacheattr_nibble_wb(uint8_t attr)
static uint8_t combined_attrs_fwb(CPUARMState *env,
ARMCacheAttrs s1, ARMCacheAttrs s2)
{
+ assert(s2.is_s2_format && !s1.is_s2_format);
+
switch (s2.attrs) {
case 7:
/* Use stage 1 attributes */
@@ -2212,7 +2218,6 @@ static ARMCacheAttrs combine_cacheattrs(CPUARMState *env,
ARMCacheAttrs ret;
bool tagged = false;
- assert(s2.is_s2_format && !s1.is_s2_format);
ret.is_s2_format = false;
if (s1.attrs == 0xf0) {
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 4/7] target/arm: Enable TTBCR_EAE for ARMv8-R AArch32
2022-10-23 15:36 [PATCH v4 0/7] Add ARM Cortex-R52 CPU tobias.roehmel
` (2 preceding siblings ...)
2022-10-23 15:36 ` [PATCH v4 3/7] target/arm: Make stage_2_format for cache attributes optional tobias.roehmel
@ 2022-10-23 15:36 ` tobias.roehmel
2022-11-14 17:19 ` Peter Maydell
2022-10-23 15:36 ` [PATCH v4 5/7] target/arm: Add PMSAv8r registers tobias.roehmel
` (3 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: tobias.roehmel @ 2022-10-23 15:36 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Tobias Röhmel
From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
ARMv8-R AArch32 CPUs behave as if TTBCR.EAE is always 1 even
tough they don't have the TTBCR register.
See ARM Architecture Reference Manual Supplement - ARMv8, for the ARMv8-R
AArch32 architecture profile Version:A.c section C1.2.
Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
---
target/arm/debug_helper.c | 3 +++
target/arm/internals.h | 4 ++++
target/arm/tlb_helper.c | 3 +++
3 files changed, 10 insertions(+)
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index c21739242c..73665f988b 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -437,6 +437,9 @@ static uint32_t arm_debug_exception_fsr(CPUARMState *env)
if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
using_lpae = true;
+ } else if (arm_feature(env, ARM_FEATURE_PMSA)
+ && arm_feature(env, ARM_FEATURE_V8)) {
+ using_lpae = true;
} else {
if (arm_feature(env, ARM_FEATURE_LPAE) &&
(env->cp15.tcr_el[target_el] & TTBCR_EAE)) {
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 307a596505..e3699421b0 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -253,6 +253,10 @@ unsigned int arm_pamax(ARMCPU *cpu);
static inline bool extended_addresses_enabled(CPUARMState *env)
{
uint64_t tcr = env->cp15.tcr_el[arm_is_secure(env) ? 3 : 1];
+ if (arm_feature(env, ARM_FEATURE_PMSA)
+ && arm_feature(env, ARM_FEATURE_V8)) {
+ return true;
+ }
return arm_el_is_aa64(env, 1) ||
(arm_feature(env, ARM_FEATURE_LPAE) && (tcr & TTBCR_EAE));
}
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
index ad225b1cb2..a2047b0bc6 100644
--- a/target/arm/tlb_helper.c
+++ b/target/arm/tlb_helper.c
@@ -18,6 +18,9 @@ bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
int el = regime_el(env, mmu_idx);
if (el == 2 || arm_el_is_aa64(env, el)) {
return true;
+ } else if (arm_feature(env, ARM_FEATURE_PMSA)
+ && arm_feature(env, ARM_FEATURE_V8)) {
+ return true;
}
if (arm_feature(env, ARM_FEATURE_LPAE)
&& (regime_tcr(env, mmu_idx) & TTBCR_EAE)) {
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 5/7] target/arm: Add PMSAv8r registers
2022-10-23 15:36 [PATCH v4 0/7] Add ARM Cortex-R52 CPU tobias.roehmel
` (3 preceding siblings ...)
2022-10-23 15:36 ` [PATCH v4 4/7] target/arm: Enable TTBCR_EAE for ARMv8-R AArch32 tobias.roehmel
@ 2022-10-23 15:36 ` tobias.roehmel
2022-11-18 13:52 ` Peter Maydell
2022-10-23 15:36 ` [PATCH v4 6/7] target/arm: Add PMSAv8r functionality tobias.roehmel
` (2 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: tobias.roehmel @ 2022-10-23 15:36 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Tobias Röhmel
From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
---
target/arm/cpu.c | 26 +++-
target/arm/cpu.h | 12 ++
target/arm/helper.c | 290 +++++++++++++++++++++++++++++++++++++++++++
target/arm/machine.c | 28 +++++
target/arm/ptw.c | 9 +-
5 files changed, 363 insertions(+), 2 deletions(-)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index b642749d6d..468150ad6c 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -463,6 +463,16 @@ static void arm_cpu_reset(DeviceState *dev)
sizeof(*env->pmsav7.dracr) * cpu->pmsav7_dregion);
}
}
+
+ if (cpu->pmsav8r_hdregion > 0) {
+ memset(env->pmsav8.hprbar[M_REG_NS], 0,
+ sizeof(*env->pmsav8.hprbar[M_REG_NS])
+ * cpu->pmsav8r_hdregion);
+ memset(env->pmsav8.hprlar[M_REG_NS], 0,
+ sizeof(*env->pmsav8.hprlar[M_REG_NS])
+ * cpu->pmsav8r_hdregion);
+ }
+
env->pmsav7.rnr[M_REG_NS] = 0;
env->pmsav7.rnr[M_REG_S] = 0;
env->pmsav8.mair0[M_REG_NS] = 0;
@@ -1965,8 +1975,9 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
*/
if (!cpu->has_mpu) {
cpu->pmsav7_dregion = 0;
+ cpu->pmsav8r_hdregion = 0;
}
- if (cpu->pmsav7_dregion == 0) {
+ if ((cpu->pmsav7_dregion == 0) && (cpu->pmsav8r_hdregion == 0)) {
cpu->has_mpu = false;
}
@@ -1994,6 +2005,19 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
env->pmsav7.dracr = g_new0(uint32_t, nr);
}
}
+
+ if (cpu->pmsav8r_hdregion > 0xFF) {
+ error_setg(errp, "PMSAv8 MPU EL2 #regions invalid %" PRIu32,
+ cpu->pmsav8r_hdregion);
+ return;
+ }
+
+ if (cpu->pmsav8r_hdregion) {
+ env->pmsav8.hprbar[M_REG_NS] = g_new0(uint32_t,
+ cpu->pmsav8r_hdregion);
+ env->pmsav8.hprlar[M_REG_NS] = g_new0(uint32_t,
+ cpu->pmsav8r_hdregion);
+ }
}
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 429ed42eec..1bb3c24db1 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -307,6 +307,13 @@ typedef struct CPUArchState {
};
uint64_t sctlr_el[4];
};
+ union { /* Virtualization System control register. */
+ struct {
+ uint32_t vsctlr_ns;
+ uint32_t vsctlr_s;
+ };
+ uint32_t vsctlr_el[2];
+ };
uint64_t cpacr_el1; /* Architectural feature access control register */
uint64_t cptr_el[4]; /* ARMv8 feature trap registers */
uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
@@ -740,8 +747,11 @@ typedef struct CPUArchState {
*/
uint32_t *rbar[M_REG_NUM_BANKS];
uint32_t *rlar[M_REG_NUM_BANKS];
+ uint32_t *hprbar[M_REG_NUM_BANKS];
+ uint32_t *hprlar[M_REG_NUM_BANKS];
uint32_t mair0[M_REG_NUM_BANKS];
uint32_t mair1[M_REG_NUM_BANKS];
+ uint32_t hprselr[M_REG_NUM_BANKS];
} pmsav8;
/* v8M SAU */
@@ -901,6 +911,8 @@ struct ArchCPU {
bool has_mpu;
/* PMSAv7 MPU number of supported regions */
uint32_t pmsav7_dregion;
+ /* PMSAv8 MPU number of supported hyp regions */
+ uint32_t pmsav8r_hdregion;
/* v8M SAU number of supported regions */
uint32_t sau_sregion;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 2e9e420d4e..6a27a618bc 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3607,6 +3607,215 @@ static void pmsav7_rgnr_write(CPUARMState *env, const ARMCPRegInfo *ri,
raw_write(env, ri, value);
}
+static void prbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ ARMCPU *cpu = env_archcpu(env);
+
+ tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
+ env->pmsav8.rbar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]] = value;
+}
+
+static uint64_t prbar_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ return env->pmsav8.rbar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]];
+}
+
+static void prlar_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ ARMCPU *cpu = env_archcpu(env);
+
+ tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
+ env->pmsav8.rlar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]] = value;
+}
+
+static uint64_t prlar_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ return env->pmsav8.rlar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]];
+}
+
+static void prselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ ARMCPU *cpu = env_archcpu(env);
+
+ /* Ignore writes that would select not implemented region */
+ if (value >= cpu->pmsav7_dregion) {
+ return;
+ }
+
+ env->pmsav7.rnr[M_REG_NS] = value;
+}
+
+static void hprbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ ARMCPU *cpu = env_archcpu(env);
+
+ tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
+ env->pmsav8.hprbar[M_REG_NS][env->pmsav8.hprselr[M_REG_NS]] = value;
+}
+
+static uint64_t hprbar_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ return env->pmsav8.hprbar[M_REG_NS][env->pmsav8.hprselr[M_REG_NS]];
+}
+
+static void hprlar_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ ARMCPU *cpu = env_archcpu(env);
+
+ tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
+ env->pmsav8.hprlar[M_REG_NS][env->pmsav8.hprselr[M_REG_NS]] = value;
+}
+
+static uint64_t hprlar_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ return env->pmsav8.hprlar[M_REG_NS][env->pmsav8.hprselr[M_REG_NS]];
+}
+
+static void hprenr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ uint32_t n;
+ uint32_t bit;
+ ARMCPU *cpu = env_archcpu(env);
+
+ /* Ignore writes to unimplemented regions */
+ value &= (1 << cpu->pmsav8r_hdregion) - 1;
+
+ tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
+
+ /* Register alias is only valid for first 32 indexes */
+ for (n = 0; n < (cpu->pmsav8r_hdregion & 0x1F); ++n) {
+ bit = extract32(value, n, 1);
+ env->pmsav8.hprlar[M_REG_NS][n] = deposit32(
+ env->pmsav8.hprlar[M_REG_NS][n], 0, 1, bit);
+ }
+}
+
+static uint64_t hprenr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ uint32_t n;
+ uint32_t result = 0x0;
+ ARMCPU *cpu = env_archcpu(env);
+
+ /* Register alias is only valid for first 32 indexes */
+ for (n = 0; n < (cpu->pmsav8r_hdregion & 0x1F); ++n) {
+ if (env->pmsav8.hprlar[M_REG_NS][n] & 0x1) {
+ result |= (0x1 << n);
+ }
+ }
+ return result;
+}
+
+static void hprselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ ARMCPU *cpu = env_archcpu(env);
+
+ /* Ignore writes that would select not implemented region */
+ if (value >= cpu->pmsav8r_hdregion) {
+ return;
+ }
+
+ env->pmsav8.hprselr[M_REG_NS] = value;
+}
+
+static void pmsav8r_regn_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ ARMCPU *cpu = env_archcpu(env);
+ uint8_t index = (ri->crm & 0b111) << 1;
+ index |= (ri->opc2 & 1 << 2) >> 2;
+
+ tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
+
+ if (ri->opc1 == 4) {
+ if (index >= cpu->pmsav8r_hdregion) {
+ return;
+ }
+ if (ri->opc2 & 0x1) {
+ env->pmsav8.hprlar[M_REG_NS][index] = value;
+ } else {
+ env->pmsav8.hprbar[M_REG_NS][index] = value;
+ }
+ } else {
+ if (index >= cpu->pmsav7_dregion) {
+ return;
+ }
+ if (ri->opc2 & 0x1) {
+ env->pmsav8.rlar[M_REG_NS][index] = value;
+ } else {
+ env->pmsav8.rbar[M_REG_NS][index] = value;
+ }
+ }
+}
+
+static uint64_t pmsav8r_regn_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ ARMCPU *cpu = env_archcpu(env);
+ uint8_t index = (ri->crm & 0b111) << 1;
+ index |= (ri->opc2 & 1 << 2) >> 2;
+
+ if (ri->opc1 == 4) {
+ if (index >= cpu->pmsav8r_hdregion) {
+ return 0x0;
+ }
+ if (ri->opc2 & 0x1) {
+ return env->pmsav8.hprlar[M_REG_NS][index];
+ } else {
+ return env->pmsav8.hprbar[M_REG_NS][index];
+ }
+ } else {
+ if (index >= cpu->pmsav7_dregion) {
+ return 0x0;
+ }
+ if (ri->opc2 & 0x1) {
+ return env->pmsav8.rlar[M_REG_NS][index];
+ } else {
+ return env->pmsav8.rbar[M_REG_NS][index];
+ }
+ }
+}
+
+static const ARMCPRegInfo pmsav8r_cp_reginfo[] = {
+ { .name = "PRBAR",
+ .cp = 15, .opc1 = 0, .crn = 6, .crm = 3, .opc2 = 0,
+ .access = PL1_RW, .type = ARM_CP_ALIAS,
+ .accessfn = access_tvm_trvm,
+ .readfn = prbar_read, .writefn = prbar_write},
+ { .name = "PRLAR",
+ .cp = 15, .opc1 = 0, .crn = 6, .crm = 3, .opc2 = 1,
+ .access = PL1_RW, .type = ARM_CP_ALIAS,
+ .accessfn = access_tvm_trvm,
+ .readfn = prlar_read, .writefn = prlar_write},
+ { .name = "PRSELR", .resetvalue = 0,
+ .cp = 15, .opc1 = 0, .crn = 6, .crm = 2, .opc2 = 1,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .writefn = prselr_write,
+ .fieldoffset = offsetof(CPUARMState, pmsav7.rnr[M_REG_NS])},
+ { .name = "HPRBAR", .resetvalue = 0,
+ .cp = 15, .opc1 = 4, .crn = 6, .crm = 3, .opc2 = 0,
+ .access = PL2_RW, .type = ARM_CP_ALIAS,
+ .readfn = hprbar_read, .writefn = hprbar_write},
+ { .name = "HPRLAR",
+ .cp = 15, .opc1 = 4, .crn = 6, .crm = 3, .opc2 = 1,
+ .access = PL2_RW, .type = ARM_CP_ALIAS,
+ .readfn = hprlar_read, .writefn = hprlar_write},
+ { .name = "HPRSELR", .resetvalue = 0,
+ .cp = 15, .opc1 = 4, .crn = 6, .crm = 2, .opc2 = 1,
+ .access = PL2_RW,
+ .writefn = hprselr_write,
+ .fieldoffset = offsetof(CPUARMState, pmsav8.hprselr[M_REG_NS])},
+ { .name = "HPRENR",
+ .cp = 15, .opc1 = 4, .crn = 6, .crm = 1, .opc2 = 1,
+ .access = PL2_RW, .type = ARM_CP_ALIAS,
+ .readfn = hprenr_read, .writefn = hprenr_write},
+};
+
static const ARMCPRegInfo pmsav7_cp_reginfo[] = {
/* Reset for all these registers is handled in arm_cpu_reset(),
* because the PMSAv7 is also used by M-profile CPUs, which do
@@ -8079,6 +8288,13 @@ void register_cp_regs_for_features(ARMCPU *cpu)
.access = PL1_R, .type = ARM_CP_CONST,
.resetvalue = cpu->pmsav7_dregion << 8
};
+ /* HMPUIR is specific to PMSA V8 */
+ ARMCPRegInfo id_hmpuir_reginfo = {
+ .name = "HMPUIR",
+ .cp = 15, .crn = 0, .crm = 0, .opc1 = 4, .opc2 = 4,
+ .access = PL2_R, .type = ARM_CP_CONST,
+ .resetvalue = cpu->pmsav8r_hdregion
+ };
static const ARMCPRegInfo crn0_wi_reginfo = {
.name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
.opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
@@ -8122,6 +8338,67 @@ void register_cp_regs_for_features(ARMCPU *cpu)
define_arm_cp_regs(cpu, id_cp_reginfo);
if (!arm_feature(env, ARM_FEATURE_PMSA)) {
define_one_arm_cp_reg(cpu, &id_tlbtr_reginfo);
+ } else if (arm_feature(env, ARM_FEATURE_PMSA)
+ && !arm_feature(env, ARM_FEATURE_M)
+ && arm_feature(env, ARM_FEATURE_V8)) {
+ uint32_t i = 0;
+ g_autofree char *tmp_string;
+
+ define_one_arm_cp_reg(cpu, &id_mpuir_reginfo);
+ define_one_arm_cp_reg(cpu, &id_hmpuir_reginfo);
+ define_arm_cp_regs(cpu, pmsav8r_cp_reginfo);
+
+ /* Register alias is only valid for first 32 indexes */
+ for (i = 0; i < (cpu->pmsav7_dregion & 0x1F); ++i) {
+ uint8_t crm = 0b1000 | ((i & 0b1110) >> 1);
+ uint8_t opc2 = (i & 0x1) << 2;
+
+ tmp_string = g_strdup_printf("PRBAR%u", i);
+ ARMCPRegInfo tmp_prbarn_reginfo = {
+ .name = tmp_string, .type = ARM_CP_ALIAS,
+ .cp = 15, .opc1 = 0, .crn = 6, .crm = crm, .opc2 = opc2,
+ .access = PL1_RW, .resetvalue = 0,
+ .accessfn = access_tvm_trvm,
+ .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
+ };
+ define_one_arm_cp_reg(cpu, &tmp_prbarn_reginfo);
+
+ opc2 = (i & 0x1) << 2 | 0x1;
+ tmp_string = g_strdup_printf("PRLAR%u", i);
+ ARMCPRegInfo tmp_prlarn_reginfo = {
+ .name = tmp_string, .type = ARM_CP_ALIAS,
+ .cp = 15, .opc1 = 0, .crn = 6, .crm = crm, .opc2 = opc2,
+ .access = PL1_RW, .resetvalue = 0,
+ .accessfn = access_tvm_trvm,
+ .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
+ };
+ define_one_arm_cp_reg(cpu, &tmp_prlarn_reginfo);
+ }
+
+ /* Register alias is only valid for first 32 indexes */
+ for (i = 0; i < (cpu->pmsav8r_hdregion & 0x1F); ++i) {
+ uint8_t crm = 0b1000 | ((i & 0b1110) >> 1);
+ uint8_t opc2 = (i & 0x1) << 2;
+
+ tmp_string = g_strdup_printf("HPRBAR%u", i);
+ ARMCPRegInfo tmp_hprbarn_reginfo = {
+ .name = tmp_string, .type = ARM_CP_ALIAS,
+ .cp = 15, .opc1 = 4, .crn = 6, .crm = crm, .opc2 = opc2,
+ .access = PL2_RW, .resetvalue = 0,
+ .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
+ };
+ define_one_arm_cp_reg(cpu, &tmp_hprbarn_reginfo);
+
+ opc2 = (i & 0x1) << 2 | 0x1;
+ tmp_string = g_strdup_printf("HPRLAR%u", i);
+ ARMCPRegInfo tmp_hprlarn_reginfo = {
+ .name = tmp_string, .type = ARM_CP_ALIAS,
+ .cp = 15, .opc1 = 4, .crn = 6, .crm = crm, .opc2 = opc2,
+ .access = PL2_RW, .resetvalue = 0,
+ .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
+ };
+ define_one_arm_cp_reg(cpu, &tmp_hprlarn_reginfo);
+ }
} else if (arm_feature(env, ARM_FEATURE_V7)) {
define_one_arm_cp_reg(cpu, &id_mpuir_reginfo);
}
@@ -8243,6 +8520,19 @@ void register_cp_regs_for_features(ARMCPU *cpu)
sctlr.type |= ARM_CP_SUPPRESS_TB_END;
}
define_one_arm_cp_reg(cpu, &sctlr);
+
+ if (arm_feature(env, ARM_FEATURE_PMSA)
+ && !arm_feature(env, ARM_FEATURE_M)
+ && arm_feature(env, ARM_FEATURE_V8)) {
+ ARMCPRegInfo vsctlr = {
+ .name = "VSCTLR", .state = ARM_CP_STATE_AA32,
+ .cp = 15, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 0,
+ .access = PL2_RW, .resetvalue = 0x0,
+ .bank_fieldoffsets = { offsetof(CPUARMState, cp15.vsctlr_s),
+ offsetof(CPUARMState, cp15.vsctlr_ns) },
+ };
+ define_one_arm_cp_reg(cpu, &vsctlr);
+ }
}
if (cpu_isar_feature(aa64_lor, cpu)) {
diff --git a/target/arm/machine.c b/target/arm/machine.c
index 54c5c62433..923da8d0bc 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -487,6 +487,30 @@ static bool pmsav8_needed(void *opaque)
arm_feature(env, ARM_FEATURE_V8);
}
+static bool pmsav8r_needed(void *opaque)
+{
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
+
+ return arm_feature(env, ARM_FEATURE_PMSA) &&
+ arm_feature(env, ARM_FEATURE_V8) &&
+ !arm_feature(env, ARM_FEATURE_M);
+}
+
+static const VMStateDescription vmstate_pmsav8r = {
+ .name = "cpu/pmsav8/pmsav8r",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = pmsav8r_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_VARRAY_UINT32(env.pmsav8.hprbar[M_REG_NS], ARMCPU,
+ pmsav8r_hdregion, 0, vmstate_info_uint32, uint32_t),
+ VMSTATE_VARRAY_UINT32(env.pmsav8.hprlar[M_REG_NS], ARMCPU,
+ pmsav8r_hdregion, 0, vmstate_info_uint32, uint32_t),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static const VMStateDescription vmstate_pmsav8 = {
.name = "cpu/pmsav8",
.version_id = 1,
@@ -500,6 +524,10 @@ static const VMStateDescription vmstate_pmsav8 = {
VMSTATE_UINT32(env.pmsav8.mair0[M_REG_NS], ARMCPU),
VMSTATE_UINT32(env.pmsav8.mair1[M_REG_NS], ARMCPU),
VMSTATE_END_OF_LIST()
+ },
+ .subsections = (const VMStateDescription * []) {
+ &vmstate_pmsav8r,
+ NULL
}
};
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index db50715fa7..4bd7389fa9 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1718,6 +1718,13 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
bool hit = false;
uint32_t addr_page_base = address & TARGET_PAGE_MASK;
uint32_t addr_page_limit = addr_page_base + (TARGET_PAGE_SIZE - 1);
+ int region_counter;
+
+ if (regime_el(env, mmu_idx) == 2) {
+ region_counter = cpu->pmsav8r_hdregion;
+ } else {
+ region_counter = cpu->pmsav7_dregion;
+ }
result->page_size = TARGET_PAGE_SIZE;
result->phys = address;
@@ -1742,7 +1749,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
hit = true;
}
- for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) {
+ for (n = region_counter - 1; n >= 0; n--) {
/* region search */
/*
* Note that the base address is bits [31:5] from the register
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 6/7] target/arm: Add PMSAv8r functionality
2022-10-23 15:36 [PATCH v4 0/7] Add ARM Cortex-R52 CPU tobias.roehmel
` (4 preceding siblings ...)
2022-10-23 15:36 ` [PATCH v4 5/7] target/arm: Add PMSAv8r registers tobias.roehmel
@ 2022-10-23 15:36 ` tobias.roehmel
2022-11-18 15:03 ` Peter Maydell
2022-10-23 15:36 ` [PATCH v4 7/7] target/arm: Add ARM Cortex-R52 CPU tobias.roehmel
2022-11-18 15:03 ` [PATCH v4 0/7] " Peter Maydell
7 siblings, 1 reply; 18+ messages in thread
From: tobias.roehmel @ 2022-10-23 15:36 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Tobias Röhmel
From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
Add PMSAv8r translation.
Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
---
target/arm/ptw.c | 130 +++++++++++++++++++++++++++++++++++++++--------
1 file changed, 110 insertions(+), 20 deletions(-)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 4bd7389fa9..a5d890c09a 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1503,6 +1503,23 @@ static bool pmsav7_use_background_region(ARMCPU *cpu, ARMMMUIdx mmu_idx,
if (arm_feature(env, ARM_FEATURE_M)) {
return env->v7m.mpu_ctrl[is_secure] & R_V7M_MPU_CTRL_PRIVDEFENA_MASK;
+ } else if (arm_feature(env, ARM_FEATURE_PMSA)) {
+ if (regime_el(env, mmu_idx) == 2) {
+ if (mmu_idx != ARMMMUIdx_E2) {
+ return false;
+ } else if ((mmu_idx == ARMMMUIdx_E2)
+ &&!(regime_sctlr(env, mmu_idx) & SCTLR_BR)) {
+ return false;
+ }
+ } else {
+ if (mmu_idx != ARMMMUIdx_Stage1_E1) {
+ return false;
+ } else if ((mmu_idx == ARMMMUIdx_Stage1_E1)
+ &&!(regime_sctlr(env, mmu_idx) & SCTLR_BR)) {
+ return false;
+ }
+ }
+ return true;
} else {
return regime_sctlr(env, mmu_idx) & SCTLR_BR;
}
@@ -1696,6 +1713,26 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
return !(result->prot & (1 << access_type));
}
+static uint32_t *regime_rbar(CPUARMState *env, ARMMMUIdx mmu_idx,
+ uint32_t secure)
+{
+ if (regime_el(env, mmu_idx) == 2) {
+ return env->pmsav8.hprbar[secure];
+ } else {
+ return env->pmsav8.rbar[secure];
+ }
+}
+
+static uint32_t *regime_rlar(CPUARMState *env, ARMMMUIdx mmu_idx,
+ uint32_t secure)
+{
+ if (regime_el(env, mmu_idx) == 2) {
+ return env->pmsav8.hprlar[secure];
+ } else {
+ return env->pmsav8.rlar[secure];
+ }
+}
+
bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
MMUAccessType access_type, ARMMMUIdx mmu_idx,
bool secure, GetPhysAddrResult *result,
@@ -1733,6 +1770,10 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
*mregion = -1;
}
+ if (mmu_idx == ARMMMUIdx_Stage2) {
+ fi->stage2 = true;
+ }
+
/*
* Unlike the ARM ARM pseudocode, we don't need to check whether this
* was an exception vector read from the vector table (which is always
@@ -1749,17 +1790,27 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
hit = true;
}
+ uint32_t bitmask;
+ if (arm_feature(env, ARM_FEATURE_M)) {
+ bitmask = 0x1f;
+ fi->level = 1;
+ } else {
+ bitmask = 0x3f;
+ fi->level = 0;
+ }
+
for (n = region_counter - 1; n >= 0; n--) {
/* region search */
/*
- * Note that the base address is bits [31:5] from the register
- * with bits [4:0] all zeroes, but the limit address is bits
- * [31:5] from the register with bits [4:0] all ones.
+ * Note that the base address is bits [31:x] from the register
+ * with bits [x-1:0] all zeroes, but the limit address is bits
+ * [31:x] from the register with bits [x:0] all ones. Where x is
+ * 5 for Cortex-M and 6 for Cortex-R
*/
- uint32_t base = env->pmsav8.rbar[secure][n] & ~0x1f;
- uint32_t limit = env->pmsav8.rlar[secure][n] | 0x1f;
+ uint32_t base = regime_rbar(env, mmu_idx, secure)[n] & ~bitmask;
+ uint32_t limit = regime_rlar(env, mmu_idx, secure)[n] | bitmask;
- if (!(env->pmsav8.rlar[secure][n] & 0x1)) {
+ if (!(regime_rlar(env, mmu_idx, secure)[n] & 0x1)) {
/* Region disabled */
continue;
}
@@ -1793,7 +1844,6 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
* PMSAv7 where highest-numbered-region wins)
*/
fi->type = ARMFault_Permission;
- fi->level = 1;
return true;
}
@@ -1803,8 +1853,11 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
}
if (!hit) {
- /* background fault */
- fi->type = ARMFault_Background;
+ if (arm_feature(env, ARM_FEATURE_M)) {
+ fi->type = ARMFault_Background;
+ } else {
+ fi->type = ARMFault_Permission;
+ }
return true;
}
@@ -1812,12 +1865,14 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
/* hit using the background region */
get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->prot);
} else {
- uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2);
- uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1);
+ uint32_t matched_rbar = regime_rbar(env, mmu_idx, secure)[matchregion];
+ uint32_t matched_rlar = regime_rlar(env, mmu_idx, secure)[matchregion];
+ uint32_t ap = extract32(matched_rbar, 1, 2);
+ uint32_t xn = extract32(matched_rbar, 0, 1);
bool pxn = false;
if (arm_feature(env, ARM_FEATURE_V8_1M)) {
- pxn = extract32(env->pmsav8.rlar[secure][matchregion], 4, 1);
+ pxn = extract32(matched_rlar, 4, 1);
}
if (m_is_system_region(env, address)) {
@@ -1825,21 +1880,49 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
xn = 1;
}
- result->prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
+ if (arm_feature(env, ARM_FEATURE_M)) {
+ /*
+ * We don't need to look the attribute up in the MAIR0/MAIR1
+ * registers because that only tells us about cacheability.
+ */
+ result->prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
+ } else {
+ if (regime_el(env, mmu_idx) == 2) {
+ result->prot = simple_ap_to_rw_prot_is_user(ap,
+ mmu_idx != ARMMMUIdx_E2);
+ } else {
+ result->prot = simple_ap_to_rw_prot_is_user(ap,
+ mmu_idx != ARMMMUIdx_Stage1_E1);
+ }
+
+ if (regime_sctlr(env, mmu_idx) & SCTLR_WXN
+ && (result->prot & PAGE_WRITE)) {
+ xn = 0x1;
+ }
+
+ if ((regime_el(env, mmu_idx) == 1) && regime_sctlr(env, mmu_idx)
+ & SCTLR_UWXN && (ap == 0x1)) {
+ xn = 0x1;
+ }
+
+ uint8_t attrindx = extract32(matched_rlar, 1, 3);
+ uint64_t mair = env->cp15.mair_el[regime_el(env, mmu_idx)];
+ uint8_t sh = extract32(matched_rlar, 3, 2);
+ result->cacheattrs.is_s2_format = false;
+ result->cacheattrs.attrs = extract64(mair, attrindx * 8, 8);
+ result->cacheattrs.shareability = sh;
+ }
+
if (result->prot && !xn && !(pxn && !is_user)) {
result->prot |= PAGE_EXEC;
}
- /*
- * We don't need to look the attribute up in the MAIR0/MAIR1
- * registers because that only tells us about cacheability.
- */
+
if (mregion) {
*mregion = matchregion;
}
}
fi->type = ARMFault_Permission;
- fi->level = 1;
return !(result->prot & (1 << access_type));
}
@@ -2348,8 +2431,15 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
cacheattrs1 = result->cacheattrs;
memset(result, 0, sizeof(*result));
- ret = get_phys_addr_lpae(env, ipa, access_type, s2_mmu_idx,
- is_el0, result, fi);
+ /* S1 is done. Now do S2 translation. */
+ if (arm_feature(env, ARM_FEATURE_PMSA)) {
+ ret = get_phys_addr_pmsav8(env, ipa, access_type, s2_mmu_idx,
+ is_secure, result, fi);
+ } else {
+ ret = get_phys_addr_lpae(env, ipa, access_type, s2_mmu_idx,
+ is_el0, result, fi);
+ }
+
fi->s2addr = ipa;
/* Combine the S1 and S2 perms. */
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 7/7] target/arm: Add ARM Cortex-R52 CPU
2022-10-23 15:36 [PATCH v4 0/7] Add ARM Cortex-R52 CPU tobias.roehmel
` (5 preceding siblings ...)
2022-10-23 15:36 ` [PATCH v4 6/7] target/arm: Add PMSAv8r functionality tobias.roehmel
@ 2022-10-23 15:36 ` tobias.roehmel
2022-11-18 14:04 ` Peter Maydell
2022-11-18 15:03 ` [PATCH v4 0/7] " Peter Maydell
7 siblings, 1 reply; 18+ messages in thread
From: tobias.roehmel @ 2022-10-23 15:36 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Tobias Röhmel
From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
All constants are taken from the ARM Cortex-R52 Processor TRM Revision: r1p3
Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
---
target/arm/cpu_tcg.c | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
index 98b5ba2160..52b9d671f7 100644
--- a/target/arm/cpu_tcg.c
+++ b/target/arm/cpu_tcg.c
@@ -851,6 +851,47 @@ static void cortex_r5_initfn(Object *obj)
define_arm_cp_regs(cpu, cortexr5_cp_reginfo);
}
+static void cortex_r52_initfn(Object *obj)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+
+ set_feature(&cpu->env, ARM_FEATURE_V8);
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
+ set_feature(&cpu->env, ARM_FEATURE_PMSA);
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
+ set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
+ cpu->midr = 0x411fd133; /* r1p3 */
+ cpu->revidr = 0x00000000;
+ cpu->reset_fpsid = 0x41034023;
+ cpu->isar.mvfr0 = 0x10110222;
+ cpu->isar.mvfr1 = 0x12111111;
+ cpu->isar.mvfr2 = 0x00000043;
+ cpu->ctr = 0x8144c004;
+ cpu->reset_sctlr = 0x30c50838;
+ cpu->isar.id_pfr0 = 0x00000131;
+ cpu->isar.id_pfr1 = 0x10111001;
+ cpu->isar.id_dfr0 = 0x03010006;
+ cpu->id_afr0 = 0x00000000;
+ cpu->isar.id_mmfr0 = 0x00211040;
+ cpu->isar.id_mmfr1 = 0x40000000;
+ cpu->isar.id_mmfr2 = 0x01200000;
+ cpu->isar.id_mmfr3 = 0xf0102211;
+ cpu->isar.id_mmfr4 = 0x00000010;
+ cpu->isar.id_isar0 = 0x02101110;
+ cpu->isar.id_isar1 = 0x13112111;
+ cpu->isar.id_isar2 = 0x21232142;
+ cpu->isar.id_isar3 = 0x01112131;
+ cpu->isar.id_isar4 = 0x00010142;
+ cpu->isar.id_isar5 = 0x00010001;
+ cpu->isar.dbgdidr = 0x77168000;
+ cpu->clidr = (1 << 27) | (1 << 24) | 0x3;
+ cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */
+ cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */
+
+ cpu->pmsav7_dregion = 16;
+ cpu->pmsav8r_hdregion = 16;
+}
+
static void cortex_r5f_initfn(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
@@ -1159,6 +1200,7 @@ static const ARMCPUInfo arm_tcg_cpus[] = {
.class_init = arm_v7m_class_init },
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
{ .name = "cortex-r5f", .initfn = cortex_r5f_initfn },
+ { .name = "cortex-r52", .initfn = cortex_r52_initfn },
{ .name = "ti925t", .initfn = ti925t_initfn },
{ .name = "sa1100", .initfn = sa1100_initfn },
{ .name = "sa1110", .initfn = sa1110_initfn },
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v4 1/7] target/arm: Don't add all MIDR aliases for cores that immplement PMSA
2022-10-23 15:36 ` [PATCH v4 1/7] target/arm: Don't add all MIDR aliases for cores that immplement PMSA tobias.roehmel
@ 2022-10-23 23:06 ` Richard Henderson
0 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2022-10-23 23:06 UTC (permalink / raw)
To: tobias.roehmel, qemu-devel; +Cc: peter.maydell
On 10/24/22 01:36, tobias.roehmel@rwth-aachen.de wrote:
> From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
Typo "implement" in subject.
> @@ -8038,6 +8035,11 @@ void register_cp_regs_for_features(ARMCPU *cpu)
> .accessfn = access_aa64_tid1,
> .type = ARM_CP_CONST, .resetvalue = cpu->revidr },
> };
> + ARMCPRegInfo id_v8_midr_alias_cp_reginfo = {
> + .name = "MIDR", .type = ARM_CP_ALIAS | ARM_CP_CONST,
> + .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 4,
> + .access = PL1_R, .resetvalue = cpu->midr
> + };
Indentation is off: 6 spaces instead of 4 at this level.
Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 2/7] target/arm: Make RVBAR available for all ARMv8 CPUs
2022-10-23 15:36 ` [PATCH v4 2/7] target/arm: Make RVBAR available for all ARMv8 CPUs tobias.roehmel
@ 2022-11-14 17:04 ` Peter Maydell
0 siblings, 0 replies; 18+ messages in thread
From: Peter Maydell @ 2022-11-14 17:04 UTC (permalink / raw)
To: tobias.roehmel; +Cc: qemu-devel
On Sun, 23 Oct 2022 at 16:37, <tobias.roehmel@rwth-aachen.de> wrote:
>
> From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
>
> RVBAR shadows RVBAR_ELx where x is the highest exception
> level if the highest EL is not EL3. This patch also allows
> ARMv8 CPUs to change the reset address with
> the rvbar property.
>
> Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 3c517356e1..2e9e420d4e 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -7768,8 +7768,8 @@ void register_cp_regs_for_features(ARMCPU *cpu)
> if (!arm_feature(env, ARM_FEATURE_EL3) &&
> !arm_feature(env, ARM_FEATURE_EL2)) {
> ARMCPRegInfo rvbar = {
> - .name = "RVBAR_EL1", .state = ARM_CP_STATE_AA64,
> - .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
> + .name = "RVBAR_EL1", .state = ARM_CP_STATE_BOTH,
> + .opc0 = 3, .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
You don't need to specify .cp for a STATE_BOTH register: 15
is the default.
Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
thanks
-- PMM
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 3/7] target/arm: Make stage_2_format for cache attributes optional
2022-10-23 15:36 ` [PATCH v4 3/7] target/arm: Make stage_2_format for cache attributes optional tobias.roehmel
@ 2022-11-14 17:13 ` Peter Maydell
0 siblings, 0 replies; 18+ messages in thread
From: Peter Maydell @ 2022-11-14 17:13 UTC (permalink / raw)
To: tobias.roehmel; +Cc: qemu-devel
On Sun, 23 Oct 2022 at 16:37, <tobias.roehmel@rwth-aachen.de> wrote:
>
> From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
>
> The v8R PMSAv8 has a two-stage MPU translation process, but, unlike
> VMSAv8, the stage 2 attributes are in the same format as the stage 1
> attributes (8-bit MAIR format). Rather than converting the MAIR
> format to the format used for VMSA stage 2 (bits [5:2] of a VMSA
> stage 2 descriptor) and then converting back to do the attribute
> combination, allow combined_attrs_nofwb() to accept s2 attributes
> that are already in the MAIR format.
>
> We move the assert() to combined_attrs_fwb(), because that function
> really does require a VMSA stage 2 attribute format. (We will never
> get there for v8R, because PMSAv8 does not implement FEAT_S2FWB.)
>
> Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
> ---
> target/arm/ptw.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
> index 2ddfc028ab..db50715fa7 100644
> --- a/target/arm/ptw.c
> +++ b/target/arm/ptw.c
> @@ -2105,7 +2105,11 @@ static uint8_t combined_attrs_nofwb(CPUARMState *env,
> {
> uint8_t s1lo, s2lo, s1hi, s2hi, s2_mair_attrs, ret_attrs;
>
> - s2_mair_attrs = convert_stage2_attrs(env, s2.attrs);
> + if (s2.is_s2_format) {
> + s2_mair_attrs = convert_stage2_attrs(env, s2.attrs);
> + } else {
> + s2_mair_attrs = s2.attrs;
> + }
You'll find when you next rebase that this needs adjustment,
because after a recent refactoring, this function no longer gets
passed the env but instead is passed the effective HCR_EL2 value.
>
> s1lo = extract32(s1.attrs, 0, 4);
> s2lo = extract32(s2_mair_attrs, 0, 4);
> @@ -2163,6 +2167,8 @@ static uint8_t force_cacheattr_nibble_wb(uint8_t attr)
> static uint8_t combined_attrs_fwb(CPUARMState *env,
> ARMCacheAttrs s1, ARMCacheAttrs s2)
> {
> + assert(s2.is_s2_format && !s1.is_s2_format);
> +
> switch (s2.attrs) {
> case 7:
> /* Use stage 1 attributes */
> @@ -2212,7 +2218,6 @@ static ARMCacheAttrs combine_cacheattrs(CPUARMState *env,
> ARMCacheAttrs ret;
> bool tagged = false;
>
> - assert(s2.is_s2_format && !s1.is_s2_format);
I think we should still assert(!s1.is_s2_format) here.
> ret.is_s2_format = false;
>
> if (s1.attrs == 0xf0) {
> --
> 2.34.1
Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
thanks
-- PMM
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 4/7] target/arm: Enable TTBCR_EAE for ARMv8-R AArch32
2022-10-23 15:36 ` [PATCH v4 4/7] target/arm: Enable TTBCR_EAE for ARMv8-R AArch32 tobias.roehmel
@ 2022-11-14 17:19 ` Peter Maydell
2022-11-15 11:37 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 18+ messages in thread
From: Peter Maydell @ 2022-11-14 17:19 UTC (permalink / raw)
To: tobias.roehmel; +Cc: qemu-devel
On Sun, 23 Oct 2022 at 16:37, <tobias.roehmel@rwth-aachen.de> wrote:
>
> From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
>
> ARMv8-R AArch32 CPUs behave as if TTBCR.EAE is always 1 even
> tough they don't have the TTBCR register.
> See ARM Architecture Reference Manual Supplement - ARMv8, for the ARMv8-R
> AArch32 architecture profile Version:A.c section C1.2.
>
> Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
> ---
> target/arm/debug_helper.c | 3 +++
> target/arm/internals.h | 4 ++++
> target/arm/tlb_helper.c | 3 +++
> 3 files changed, 10 insertions(+)
>
> diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
> index c21739242c..73665f988b 100644
> --- a/target/arm/debug_helper.c
> +++ b/target/arm/debug_helper.c
> @@ -437,6 +437,9 @@ static uint32_t arm_debug_exception_fsr(CPUARMState *env)
>
> if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
> using_lpae = true;
> + } else if (arm_feature(env, ARM_FEATURE_PMSA)
> + && arm_feature(env, ARM_FEATURE_V8)) {
Indentation looks wrong here. Generally the second line of a
multiline if (...) condition starts in the column after the '(',
so it lines up with the first part of the condition.
> + using_lpae = true;
> } else {
> if (arm_feature(env, ARM_FEATURE_LPAE) &&
> (env->cp15.tcr_el[target_el] & TTBCR_EAE)) {
For instance this is an example in the existing code.
We are inconsistent about whether we put operators like '&&' at
the end of the first line or beginning of the second line, so
pick whichever you like best, I guess.
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 307a596505..e3699421b0 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -253,6 +253,10 @@ unsigned int arm_pamax(ARMCPU *cpu);
> static inline bool extended_addresses_enabled(CPUARMState *env)
> {
> uint64_t tcr = env->cp15.tcr_el[arm_is_secure(env) ? 3 : 1];
> + if (arm_feature(env, ARM_FEATURE_PMSA)
> + && arm_feature(env, ARM_FEATURE_V8)) {
Indentation is a bit odd here too.
> + return true;
> + }
> return arm_el_is_aa64(env, 1) ||
> (arm_feature(env, ARM_FEATURE_LPAE) && (tcr & TTBCR_EAE));
> }
> diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
> index ad225b1cb2..a2047b0bc6 100644
> --- a/target/arm/tlb_helper.c
> +++ b/target/arm/tlb_helper.c
> @@ -18,6 +18,9 @@ bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
> int el = regime_el(env, mmu_idx);
> if (el == 2 || arm_el_is_aa64(env, el)) {
> return true;
> + } else if (arm_feature(env, ARM_FEATURE_PMSA)
> + && arm_feature(env, ARM_FEATURE_V8)) {
> + return true;
> }
Use an "if ()..." not an "else if" here to match the style
of the other check in this function.
> if (arm_feature(env, ARM_FEATURE_LPAE)
> && (regime_tcr(env, mmu_idx) & TTBCR_EAE)) {
Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
thanks
-- PMM
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 4/7] target/arm: Enable TTBCR_EAE for ARMv8-R AArch32
2022-11-14 17:19 ` Peter Maydell
@ 2022-11-15 11:37 ` Philippe Mathieu-Daudé
2022-11-15 12:01 ` Daniel P. Berrangé
0 siblings, 1 reply; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2022-11-15 11:37 UTC (permalink / raw)
To: Peter Maydell, tobias.roehmel, Eric Blake
Cc: qemu-devel, Daniel P. Berrangé
On 14/11/22 18:19, Peter Maydell wrote:
> On Sun, 23 Oct 2022 at 16:37, <tobias.roehmel@rwth-aachen.de> wrote:
>>
>> From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
>>
>> ARMv8-R AArch32 CPUs behave as if TTBCR.EAE is always 1 even
>> tough they don't have the TTBCR register.
>> See ARM Architecture Reference Manual Supplement - ARMv8, for the ARMv8-R
>> AArch32 architecture profile Version:A.c section C1.2.
>>
>> Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
>> ---
>> target/arm/debug_helper.c | 3 +++
>> target/arm/internals.h | 4 ++++
>> target/arm/tlb_helper.c | 3 +++
>> 3 files changed, 10 insertions(+)
>>
>> diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
>> index c21739242c..73665f988b 100644
>> --- a/target/arm/debug_helper.c
>> +++ b/target/arm/debug_helper.c
>> @@ -437,6 +437,9 @@ static uint32_t arm_debug_exception_fsr(CPUARMState *env)
>>
>> if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
>> using_lpae = true;
>> + } else if (arm_feature(env, ARM_FEATURE_PMSA)
>> + && arm_feature(env, ARM_FEATURE_V8)) {
>
> Indentation looks wrong here. Generally the second line of a
> multiline if (...) condition starts in the column after the '(',
> so it lines up with the first part of the condition.
>
>> + using_lpae = true;
>> } else {
>> if (arm_feature(env, ARM_FEATURE_LPAE) &&
>> (env->cp15.tcr_el[target_el] & TTBCR_EAE)) {
>
> For instance this is an example in the existing code.
>
> We are inconsistent about whether we put operators like '&&' at
> the end of the first line or beginning of the second line, so
> pick whichever you like best, I guess.
Personally I find the operator at the end aesthetically nicer, but
few years ago Eric Blake reasoned that moving it at the beginning
was more explicit (to reviewers) thus safer, and I now I tend to
place it at the beginning.
Maybe part of the justification was cases where copy/pasting new
conditions in pre-existing could introduce a bug when the operator
is at the end?
+Eric/Daniel who usually give such good style advises :)
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 4/7] target/arm: Enable TTBCR_EAE for ARMv8-R AArch32
2022-11-15 11:37 ` Philippe Mathieu-Daudé
@ 2022-11-15 12:01 ` Daniel P. Berrangé
0 siblings, 0 replies; 18+ messages in thread
From: Daniel P. Berrangé @ 2022-11-15 12:01 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Peter Maydell, tobias.roehmel, Eric Blake, qemu-devel
On Tue, Nov 15, 2022 at 12:37:45PM +0100, Philippe Mathieu-Daudé wrote:
> On 14/11/22 18:19, Peter Maydell wrote:
> > On Sun, 23 Oct 2022 at 16:37, <tobias.roehmel@rwth-aachen.de> wrote:
> > >
> > > From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
> > >
> > > ARMv8-R AArch32 CPUs behave as if TTBCR.EAE is always 1 even
> > > tough they don't have the TTBCR register.
> > > See ARM Architecture Reference Manual Supplement - ARMv8, for the ARMv8-R
> > > AArch32 architecture profile Version:A.c section C1.2.
> > >
> > > Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
> > > ---
> > > target/arm/debug_helper.c | 3 +++
> > > target/arm/internals.h | 4 ++++
> > > target/arm/tlb_helper.c | 3 +++
> > > 3 files changed, 10 insertions(+)
> > >
> > > diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
> > > index c21739242c..73665f988b 100644
> > > --- a/target/arm/debug_helper.c
> > > +++ b/target/arm/debug_helper.c
> > > @@ -437,6 +437,9 @@ static uint32_t arm_debug_exception_fsr(CPUARMState *env)
> > >
> > > if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
> > > using_lpae = true;
> > > + } else if (arm_feature(env, ARM_FEATURE_PMSA)
> > > + && arm_feature(env, ARM_FEATURE_V8)) {
> >
> > Indentation looks wrong here. Generally the second line of a
> > multiline if (...) condition starts in the column after the '(',
> > so it lines up with the first part of the condition.
This illustrates the problem with putting '&&' at start of line.
It harms the vertical alignment of the expressions, leading to
the desire to un-indent the block by 3 spaces to get 'arm_feature'
to line up. Understandable, but no editor/code indentors will
preserve this kind of indentation/alignment, so it shouldn't
be done.
Both ways you can choose to line up the indent for operator at
start of line are unpleasant - it is a no-win scenario IMHO.
> > > + using_lpae = true;
> > > } else {
> > > if (arm_feature(env, ARM_FEATURE_LPAE) &&
> > > (env->cp15.tcr_el[target_el] & TTBCR_EAE)) {
> >
> > For instance this is an example in the existing code.
> >
> > We are inconsistent about whether we put operators like '&&' at
> > the end of the first line or beginning of the second line, so
> > pick whichever you like best, I guess.
> Personally I find the operator at the end aesthetically nicer, but
> few years ago Eric Blake reasoned that moving it at the beginning
> was more explicit (to reviewers) thus safer, and I now I tend to
> place it at the beginning.
I'm not convinced that operator at start of line makes any
difference at all to reviewability, and as above it leads
to undesirable indentation choices.
> Maybe part of the justification was cases where copy/pasting new
> conditions in pre-existing could introduce a bug when the operator
> is at the end?
The QEMU defacto standard is operators at end of line, given what
appears as the usage ratio of 6:1
$ git grep -E '^\s*(&&|&|\||\|\|)\s' '*.c' | wc -l
1692
$ git grep -E '\s(&&|&|\||\|\|)\s*$' '*.c' | wc -l
10289
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 5/7] target/arm: Add PMSAv8r registers
2022-10-23 15:36 ` [PATCH v4 5/7] target/arm: Add PMSAv8r registers tobias.roehmel
@ 2022-11-18 13:52 ` Peter Maydell
0 siblings, 0 replies; 18+ messages in thread
From: Peter Maydell @ 2022-11-18 13:52 UTC (permalink / raw)
To: tobias.roehmel; +Cc: qemu-devel
On Sun, 23 Oct 2022 at 16:37, <tobias.roehmel@rwth-aachen.de> wrote:
>
> From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
>
> Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
This patch is basically the right shape, but there's a big
simplification you can make and then a bunch of minor tweaks.
> ---
> target/arm/cpu.c | 26 +++-
> target/arm/cpu.h | 12 ++
> target/arm/helper.c | 290 +++++++++++++++++++++++++++++++++++++++++++
> target/arm/machine.c | 28 +++++
> target/arm/ptw.c | 9 +-
> 5 files changed, 363 insertions(+), 2 deletions(-)
>
> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> index b642749d6d..468150ad6c 100644
> --- a/target/arm/cpu.c
> +++ b/target/arm/cpu.c
> @@ -463,6 +463,16 @@ static void arm_cpu_reset(DeviceState *dev)
> sizeof(*env->pmsav7.dracr) * cpu->pmsav7_dregion);
> }
> }
> +
> + if (cpu->pmsav8r_hdregion > 0) {
> + memset(env->pmsav8.hprbar[M_REG_NS], 0,
> + sizeof(*env->pmsav8.hprbar[M_REG_NS])
> + * cpu->pmsav8r_hdregion);
> + memset(env->pmsav8.hprlar[M_REG_NS], 0,
> + sizeof(*env->pmsav8.hprlar[M_REG_NS])
> + * cpu->pmsav8r_hdregion);
> + }
> +
> env->pmsav7.rnr[M_REG_NS] = 0;
> env->pmsav7.rnr[M_REG_S] = 0;
> env->pmsav8.mair0[M_REG_NS] = 0;
> @@ -1965,8 +1975,9 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
> */
> if (!cpu->has_mpu) {
> cpu->pmsav7_dregion = 0;
> + cpu->pmsav8r_hdregion = 0;
> }
> - if (cpu->pmsav7_dregion == 0) {
> + if ((cpu->pmsav7_dregion == 0) && (cpu->pmsav8r_hdregion == 0)) {
> cpu->has_mpu = false;
> }
>
> @@ -1994,6 +2005,19 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
> env->pmsav7.dracr = g_new0(uint32_t, nr);
> }
> }
> +
> + if (cpu->pmsav8r_hdregion > 0xFF) {
> + error_setg(errp, "PMSAv8 MPU EL2 #regions invalid %" PRIu32,
> + cpu->pmsav8r_hdregion);
> + return;
> + }
> +
> + if (cpu->pmsav8r_hdregion) {
> + env->pmsav8.hprbar[M_REG_NS] = g_new0(uint32_t,
> + cpu->pmsav8r_hdregion);
> + env->pmsav8.hprlar[M_REG_NS] = g_new0(uint32_t,
> + cpu->pmsav8r_hdregion);
> + }
> }
>
> if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 429ed42eec..1bb3c24db1 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -307,6 +307,13 @@ typedef struct CPUArchState {
> };
> uint64_t sctlr_el[4];
> };
> + union { /* Virtualization System control register. */
> + struct {
> + uint32_t vsctlr_ns;
> + uint32_t vsctlr_s;
> + };
> + uint32_t vsctlr_el[2];
> + };
v8R only has a single security state, so you don't need to make this
a union or have _ns and _s versions, you can just have a single field.
We should make the field a uint64_t because this register in
PMSAv8-64 is 64 bits, and having the field be 64 bits to start with will
make life slightly easier if we need to implement that in future. So
uint64_t vsctlr;
> uint64_t cpacr_el1; /* Architectural feature access control register */
> uint64_t cptr_el[4]; /* ARMv8 feature trap registers */
> uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
> @@ -740,8 +747,11 @@ typedef struct CPUArchState {
> */
> uint32_t *rbar[M_REG_NUM_BANKS];
> uint32_t *rlar[M_REG_NUM_BANKS];
> + uint32_t *hprbar[M_REG_NUM_BANKS];
> + uint32_t *hprlar[M_REG_NUM_BANKS];
These don't need to be arrays, so just
uint32_t *hprbar;
uint32_t *hprlar;
(PMSAv8-64 also has these as 64-bit registers, but that is also true
of the existing rbar/rlar. So I think on balance it's better to
keep hprbar/hprlar the same length as rbar/rlar, and if we ever
implement PMSAv8-64 we'll have to sort out extending the length
of both sets of registers at the same time.)
> uint32_t mair0[M_REG_NUM_BANKS];
> uint32_t mair1[M_REG_NUM_BANKS];
> + uint32_t hprselr[M_REG_NUM_BANKS];
Similarly this can just be
uint32_t hprselr;
> } pmsav8;
>
> /* v8M SAU */
> @@ -901,6 +911,8 @@ struct ArchCPU {
> bool has_mpu;
> /* PMSAv7 MPU number of supported regions */
> uint32_t pmsav7_dregion;
> + /* PMSAv8 MPU number of supported hyp regions */
> + uint32_t pmsav8r_hdregion;
> /* v8M SAU number of supported regions */
> uint32_t sau_sregion;
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 2e9e420d4e..6a27a618bc 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -3607,6 +3607,215 @@ static void pmsav7_rgnr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> raw_write(env, ri, value);
> }
>
> +static void prbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
> + uint64_t value)
> +{
> + ARMCPU *cpu = env_archcpu(env);
> +
> + tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
> + env->pmsav8.rbar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]] = value;
> +}
> +
> +static uint64_t prbar_read(CPUARMState *env, const ARMCPRegInfo *ri)
> +{
> + return env->pmsav8.rbar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]];
> +}
> +
> +static void prlar_write(CPUARMState *env, const ARMCPRegInfo *ri,
> + uint64_t value)
> +{
> + ARMCPU *cpu = env_archcpu(env);
> +
> + tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
> + env->pmsav8.rlar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]] = value;
> +}
> +
> +static uint64_t prlar_read(CPUARMState *env, const ARMCPRegInfo *ri)
> +{
> + return env->pmsav8.rlar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]];
> +}
> +
> +static void prselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> + uint64_t value)
> +{
> + ARMCPU *cpu = env_archcpu(env);
> +
> + /* Ignore writes that would select not implemented region */
It's worth mentioning that this is architecturally UNPREDICTABLE.
> + if (value >= cpu->pmsav7_dregion) {
> + return;
> + }
> +
> + env->pmsav7.rnr[M_REG_NS] = value;
> +}
> +
> +static void hprbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
> + uint64_t value)
> +{
> + ARMCPU *cpu = env_archcpu(env);
> +
> + tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
> + env->pmsav8.hprbar[M_REG_NS][env->pmsav8.hprselr[M_REG_NS]] = value;
> +}
> +
> +static uint64_t hprbar_read(CPUARMState *env, const ARMCPRegInfo *ri)
> +{
> + return env->pmsav8.hprbar[M_REG_NS][env->pmsav8.hprselr[M_REG_NS]];
> +}
> +
> +static void hprlar_write(CPUARMState *env, const ARMCPRegInfo *ri,
> + uint64_t value)
> +{
> + ARMCPU *cpu = env_archcpu(env);
> +
> + tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
> + env->pmsav8.hprlar[M_REG_NS][env->pmsav8.hprselr[M_REG_NS]] = value;
> +}
> +
> +static uint64_t hprlar_read(CPUARMState *env, const ARMCPRegInfo *ri)
> +{
> + return env->pmsav8.hprlar[M_REG_NS][env->pmsav8.hprselr[M_REG_NS]];
> +}
> +
> +static void hprenr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> + uint64_t value)
> +{
> + uint32_t n;
> + uint32_t bit;
> + ARMCPU *cpu = env_archcpu(env);
> +
> + /* Ignore writes to unimplemented regions */
> + value &= (1 << cpu->pmsav8r_hdregion) - 1;
This is undefined behaviour if cpu->pmsav8r_hdregion is greater than 31.
I suggest defining a local variable
int rmax = MIN(cpu->pmsav8r_hdregion, 32);
Then you can do
value &= MAKE_64BIT_MASK(0, rmax);
> +
> + tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
> +
> + /* Register alias is only valid for first 32 indexes */
> + for (n = 0; n < (cpu->pmsav8r_hdregion & 0x1F); ++n) {
This isn't the right boundary -- for instance if pmsav8r_hdregion
is 33 then this will only set bit 0. If you take my suggestion
above then you can just use 'rmax' as the upper bound.
> + bit = extract32(value, n, 1);
> + env->pmsav8.hprlar[M_REG_NS][n] = deposit32(
> + env->pmsav8.hprlar[M_REG_NS][n], 0, 1, bit);
> + }
> +}
> +
> +static uint64_t hprenr_read(CPUARMState *env, const ARMCPRegInfo *ri)
> +{
> + uint32_t n;
> + uint32_t result = 0x0;
> + ARMCPU *cpu = env_archcpu(env);
> +
> + /* Register alias is only valid for first 32 indexes */
> + for (n = 0; n < (cpu->pmsav8r_hdregion & 0x1F); ++n) {
Same remark as above about the upper bound.
> + if (env->pmsav8.hprlar[M_REG_NS][n] & 0x1) {
> + result |= (0x1 << n);
> + }
> + }
> + return result;
> +}
> +
> +static void hprselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> + uint64_t value)
> +{
> + ARMCPU *cpu = env_archcpu(env);
> +
> + /* Ignore writes that would select not implemented region */
> + if (value >= cpu->pmsav8r_hdregion) {
> + return;
> + }
> +
> + env->pmsav8.hprselr[M_REG_NS] = value;
> +}
> +
> +static void pmsav8r_regn_write(CPUARMState *env, const ARMCPRegInfo *ri,
> + uint64_t value)
> +{
> + ARMCPU *cpu = env_archcpu(env);
> + uint8_t index = (ri->crm & 0b111) << 1;
> + index |= (ri->opc2 & 1 << 2) >> 2;
This is missing the 5th bit of index, which is in opc0 bit 0.
I would suggest
index = (extract32(ri->opc0, 0, 1) << 4) | (extract32(ri->crm, 0, 3)
<< 1) | extract32(ri->opc2, 2, 1);
> + tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
> +
> + if (ri->opc1 == 4) {
This should be checking (ri->opc1 & 2).
> + if (index >= cpu->pmsav8r_hdregion) {
> + return;
> + }
> + if (ri->opc2 & 0x1) {
> + env->pmsav8.hprlar[M_REG_NS][index] = value;
> + } else {
> + env->pmsav8.hprbar[M_REG_NS][index] = value;
> + }
> + } else {
> + if (index >= cpu->pmsav7_dregion) {
> + return;
> + }
> + if (ri->opc2 & 0x1) {
> + env->pmsav8.rlar[M_REG_NS][index] = value;
> + } else {
> + env->pmsav8.rbar[M_REG_NS][index] = value;
> + }
> + }
> +}
> +
> +static uint64_t pmsav8r_regn_read(CPUARMState *env, const ARMCPRegInfo *ri)
> +{
> + ARMCPU *cpu = env_archcpu(env);
> + uint8_t index = (ri->crm & 0b111) << 1;
> + index |= (ri->opc2 & 1 << 2) >> 2;
Same remarks apply to this function as above.
> +
> + if (ri->opc1 == 4) {
> + if (index >= cpu->pmsav8r_hdregion) {
> + return 0x0;
> + }
> + if (ri->opc2 & 0x1) {
> + return env->pmsav8.hprlar[M_REG_NS][index];
> + } else {
> + return env->pmsav8.hprbar[M_REG_NS][index];
> + }
> + } else {
> + if (index >= cpu->pmsav7_dregion) {
> + return 0x0;
> + }
> + if (ri->opc2 & 0x1) {
> + return env->pmsav8.rlar[M_REG_NS][index];
> + } else {
> + return env->pmsav8.rbar[M_REG_NS][index];
> + }
> + }
> +}
> +
> +static const ARMCPRegInfo pmsav8r_cp_reginfo[] = {
> + { .name = "PRBAR",
> + .cp = 15, .opc1 = 0, .crn = 6, .crm = 3, .opc2 = 0,
Indent here seems odd (even by the ad-hoc standards we apply
to cpreginfo array declarations): generally we make all the '.'s line up.
> + .access = PL1_RW, .type = ARM_CP_ALIAS,
> + .accessfn = access_tvm_trvm,
> + .readfn = prbar_read, .writefn = prbar_write},
We generally put a space before the closing } on this kind of line.
> + { .name = "PRLAR",
> + .cp = 15, .opc1 = 0, .crn = 6, .crm = 3, .opc2 = 1,
> + .access = PL1_RW, .type = ARM_CP_ALIAS,
> + .accessfn = access_tvm_trvm,
> + .readfn = prlar_read, .writefn = prlar_write},
These two should be .type = ARM_CP_NO_RAW
> + { .name = "PRSELR", .resetvalue = 0,
> + .cp = 15, .opc1 = 0, .crn = 6, .crm = 2, .opc2 = 1,
> + .access = PL1_RW, .accessfn = access_tvm_trvm,
> + .writefn = prselr_write,
> + .fieldoffset = offsetof(CPUARMState, pmsav7.rnr[M_REG_NS])},
> + { .name = "HPRBAR", .resetvalue = 0,
> + .cp = 15, .opc1 = 4, .crn = 6, .crm = 3, .opc2 = 0,
> + .access = PL2_RW, .type = ARM_CP_ALIAS,
> + .readfn = hprbar_read, .writefn = hprbar_write},
> + { .name = "HPRLAR",
> + .cp = 15, .opc1 = 4, .crn = 6, .crm = 3, .opc2 = 1,
> + .access = PL2_RW, .type = ARM_CP_ALIAS,
> + .readfn = hprlar_read, .writefn = hprlar_write},
These two also should be ARM_CP_NO_RAW
> + { .name = "HPRSELR", .resetvalue = 0,
> + .cp = 15, .opc1 = 4, .crn = 6, .crm = 2, .opc2 = 1,
> + .access = PL2_RW,
> + .writefn = hprselr_write,
> + .fieldoffset = offsetof(CPUARMState, pmsav8.hprselr[M_REG_NS])},
> + { .name = "HPRENR",
> + .cp = 15, .opc1 = 4, .crn = 6, .crm = 1, .opc2 = 1,
> + .access = PL2_RW, .type = ARM_CP_ALIAS,
> + .readfn = hprenr_read, .writefn = hprenr_write},
> +};
> +
> static const ARMCPRegInfo pmsav7_cp_reginfo[] = {
> /* Reset for all these registers is handled in arm_cpu_reset(),
> * because the PMSAv7 is also used by M-profile CPUs, which do
> @@ -8079,6 +8288,13 @@ void register_cp_regs_for_features(ARMCPU *cpu)
> .access = PL1_R, .type = ARM_CP_CONST,
> .resetvalue = cpu->pmsav7_dregion << 8
> };
> + /* HMPUIR is specific to PMSA V8 */
> + ARMCPRegInfo id_hmpuir_reginfo = {
> + .name = "HMPUIR",
> + .cp = 15, .crn = 0, .crm = 0, .opc1 = 4, .opc2 = 4,
Prefer the order cp, opc1, crn, crm, opc2
> + .access = PL2_R, .type = ARM_CP_CONST,
> + .resetvalue = cpu->pmsav8r_hdregion
> + };
> static const ARMCPRegInfo crn0_wi_reginfo = {
> .name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
> .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
> @@ -8122,6 +8338,67 @@ void register_cp_regs_for_features(ARMCPU *cpu)
> define_arm_cp_regs(cpu, id_cp_reginfo);
> if (!arm_feature(env, ARM_FEATURE_PMSA)) {
> define_one_arm_cp_reg(cpu, &id_tlbtr_reginfo);
> + } else if (arm_feature(env, ARM_FEATURE_PMSA)
> + && !arm_feature(env, ARM_FEATURE_M)
M-profile is checked for at the top of the function and it returns
early and never gets to this code, so you can skip this test.
> + && arm_feature(env, ARM_FEATURE_V8)) {
> + uint32_t i = 0;
> + g_autofree char *tmp_string;
> +
> + define_one_arm_cp_reg(cpu, &id_mpuir_reginfo);
> + define_one_arm_cp_reg(cpu, &id_hmpuir_reginfo);
> + define_arm_cp_regs(cpu, pmsav8r_cp_reginfo);
> +
> + /* Register alias is only valid for first 32 indexes */
> + for (i = 0; i < (cpu->pmsav7_dregion & 0x1F); ++i) {
Bad upper index again.
> + uint8_t crm = 0b1000 | ((i & 0b1110) >> 1);
> + uint8_t opc2 = (i & 0x1) << 2;
Doesn't handle the 5th bit in the index (the one that ends up in opc1).
> +
> + tmp_string = g_strdup_printf("PRBAR%u", i);
> + ARMCPRegInfo tmp_prbarn_reginfo = {
> + .name = tmp_string, .type = ARM_CP_ALIAS,
ARM_CP_NO_RAW
> + .cp = 15, .opc1 = 0, .crn = 6, .crm = crm, .opc2 = opc2,
> + .access = PL1_RW, .resetvalue = 0,
> + .accessfn = access_tvm_trvm,
> + .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
> + };
> + define_one_arm_cp_reg(cpu, &tmp_prbarn_reginfo);
> +
> + opc2 = (i & 0x1) << 2 | 0x1;
> + tmp_string = g_strdup_printf("PRLAR%u", i);
If you're going to use g_autofree, you can't reuse the same variable
for a new string allocation -- this leaks the first string when we
assign to tmp_string again. You need to use separate variables so
that both allocations are auto-freed when they go out of scope.
> + ARMCPRegInfo tmp_prlarn_reginfo = {
> + .name = tmp_string, .type = ARM_CP_ALIAS,
ARM_CP_NO_RAW
> + .cp = 15, .opc1 = 0, .crn = 6, .crm = crm, .opc2 = opc2,
> + .access = PL1_RW, .resetvalue = 0,
> + .accessfn = access_tvm_trvm,
> + .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
> + };
> + define_one_arm_cp_reg(cpu, &tmp_prlarn_reginfo);
> + }
> +
> + /* Register alias is only valid for first 32 indexes */
> + for (i = 0; i < (cpu->pmsav8r_hdregion & 0x1F); ++i) {
> + uint8_t crm = 0b1000 | ((i & 0b1110) >> 1);
> + uint8_t opc2 = (i & 0x1) << 2;
Same comments for the first loop all apply to this loop.
> +
> + tmp_string = g_strdup_printf("HPRBAR%u", i);
> + ARMCPRegInfo tmp_hprbarn_reginfo = {
> + .name = tmp_string, .type = ARM_CP_ALIAS,
> + .cp = 15, .opc1 = 4, .crn = 6, .crm = crm, .opc2 = opc2,
> + .access = PL2_RW, .resetvalue = 0,
> + .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
> + };
> + define_one_arm_cp_reg(cpu, &tmp_hprbarn_reginfo);
> +
> + opc2 = (i & 0x1) << 2 | 0x1;
> + tmp_string = g_strdup_printf("HPRLAR%u", i);
> + ARMCPRegInfo tmp_hprlarn_reginfo = {
> + .name = tmp_string, .type = ARM_CP_ALIAS,
> + .cp = 15, .opc1 = 4, .crn = 6, .crm = crm, .opc2 = opc2,
> + .access = PL2_RW, .resetvalue = 0,
> + .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
> + };
> + define_one_arm_cp_reg(cpu, &tmp_hprlarn_reginfo);
> + }
> } else if (arm_feature(env, ARM_FEATURE_V7)) {
> define_one_arm_cp_reg(cpu, &id_mpuir_reginfo);
> }
> @@ -8243,6 +8520,19 @@ void register_cp_regs_for_features(ARMCPU *cpu)
> sctlr.type |= ARM_CP_SUPPRESS_TB_END;
> }
> define_one_arm_cp_reg(cpu, &sctlr);
> +
> + if (arm_feature(env, ARM_FEATURE_PMSA)
> + && !arm_feature(env, ARM_FEATURE_M)
Don't need to check for not-M.
> + && arm_feature(env, ARM_FEATURE_V8)) {
> + ARMCPRegInfo vsctlr = {
> + .name = "VSCTLR", .state = ARM_CP_STATE_AA32,
> + .cp = 15, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 0,
> + .access = PL2_RW, .resetvalue = 0x0,
> + .bank_fieldoffsets = { offsetof(CPUARMState, cp15.vsctlr_s),
> + offsetof(CPUARMState, cp15.vsctlr_ns) },
This will get simpler when you aren't trying to describe it as
a banked register. Note that if you make the field a uint64_t
as I suggest above then you will want to use offsetoflow32()
rather than plain offsetof() (so that on a big-endian host the
field offset is pointed to the high half of the uint64_t.)
> + };
> + define_one_arm_cp_reg(cpu, &vsctlr);
> + }
> }
>
> if (cpu_isar_feature(aa64_lor, cpu)) {
> diff --git a/target/arm/machine.c b/target/arm/machine.c
> index 54c5c62433..923da8d0bc 100644
> --- a/target/arm/machine.c
> +++ b/target/arm/machine.c
> @@ -487,6 +487,30 @@ static bool pmsav8_needed(void *opaque)
> arm_feature(env, ARM_FEATURE_V8);
> }
>
> +static bool pmsav8r_needed(void *opaque)
> +{
> + ARMCPU *cpu = opaque;
> + CPUARMState *env = &cpu->env;
> +
> + return arm_feature(env, ARM_FEATURE_PMSA) &&
> + arm_feature(env, ARM_FEATURE_V8) &&
> + !arm_feature(env, ARM_FEATURE_M);
> +}
> +
> +static const VMStateDescription vmstate_pmsav8r = {
> + .name = "cpu/pmsav8/pmsav8r",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .needed = pmsav8r_needed,
> + .fields = (VMStateField[]) {
> + VMSTATE_VARRAY_UINT32(env.pmsav8.hprbar[M_REG_NS], ARMCPU,
> + pmsav8r_hdregion, 0, vmstate_info_uint32, uint32_t),
> + VMSTATE_VARRAY_UINT32(env.pmsav8.hprlar[M_REG_NS], ARMCPU,
> + pmsav8r_hdregion, 0, vmstate_info_uint32, uint32_t),
> + VMSTATE_END_OF_LIST()
> + },
> +};
> +
> static const VMStateDescription vmstate_pmsav8 = {
> .name = "cpu/pmsav8",
> .version_id = 1,
> @@ -500,6 +524,10 @@ static const VMStateDescription vmstate_pmsav8 = {
> VMSTATE_UINT32(env.pmsav8.mair0[M_REG_NS], ARMCPU),
> VMSTATE_UINT32(env.pmsav8.mair1[M_REG_NS], ARMCPU),
> VMSTATE_END_OF_LIST()
> + },
> + .subsections = (const VMStateDescription * []) {
> + &vmstate_pmsav8r,
> + NULL
> }
> };
You'll need to adjust the vmstate field array a bit to allow for
hprbar and hprlar not being arrays, but otherwise the vmstate
changes look good.
> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
> index db50715fa7..4bd7389fa9 100644
> --- a/target/arm/ptw.c
> +++ b/target/arm/ptw.c
> @@ -1718,6 +1718,13 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
> bool hit = false;
> uint32_t addr_page_base = address & TARGET_PAGE_MASK;
> uint32_t addr_page_limit = addr_page_base + (TARGET_PAGE_SIZE - 1);
> + int region_counter;
> +
> + if (regime_el(env, mmu_idx) == 2) {
> + region_counter = cpu->pmsav8r_hdregion;
> + } else {
> + region_counter = cpu->pmsav7_dregion;
> + }
>
> result->page_size = TARGET_PAGE_SIZE;
> result->phys = address;
> @@ -1742,7 +1749,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
> hit = true;
> }
>
> - for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) {
> + for (n = region_counter - 1; n >= 0; n--) {
> /* region search */
> /*
> * Note that the base address is bits [31:5] from the register
The changes to ptw.c here should be moved to the following patch.
thanks
-- PMM
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 7/7] target/arm: Add ARM Cortex-R52 CPU
2022-10-23 15:36 ` [PATCH v4 7/7] target/arm: Add ARM Cortex-R52 CPU tobias.roehmel
@ 2022-11-18 14:04 ` Peter Maydell
0 siblings, 0 replies; 18+ messages in thread
From: Peter Maydell @ 2022-11-18 14:04 UTC (permalink / raw)
To: tobias.roehmel; +Cc: qemu-devel
On Sun, 23 Oct 2022 at 16:37, <tobias.roehmel@rwth-aachen.de> wrote:
>
> From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
>
> All constants are taken from the ARM Cortex-R52 Processor TRM Revision: r1p3
>
> Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
> ---
> target/arm/cpu_tcg.c | 42 ++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 42 insertions(+)
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
thanks
-- PMM
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 6/7] target/arm: Add PMSAv8r functionality
2022-10-23 15:36 ` [PATCH v4 6/7] target/arm: Add PMSAv8r functionality tobias.roehmel
@ 2022-11-18 15:03 ` Peter Maydell
0 siblings, 0 replies; 18+ messages in thread
From: Peter Maydell @ 2022-11-18 15:03 UTC (permalink / raw)
To: tobias.roehmel; +Cc: qemu-devel
On Sun, 23 Oct 2022 at 16:37, <tobias.roehmel@rwth-aachen.de> wrote:
>
> From: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
>
> Add PMSAv8r translation.
>
> Signed-off-by: Tobias Röhmel <tobias.roehmel@rwth-aachen.de>
> ---
> target/arm/ptw.c | 130 +++++++++++++++++++++++++++++++++++++++--------
> 1 file changed, 110 insertions(+), 20 deletions(-)
>
> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
> index 4bd7389fa9..a5d890c09a 100644
> --- a/target/arm/ptw.c
> +++ b/target/arm/ptw.c
> @@ -1503,6 +1503,23 @@ static bool pmsav7_use_background_region(ARMCPU *cpu, ARMMMUIdx mmu_idx,
>
> if (arm_feature(env, ARM_FEATURE_M)) {
> return env->v7m.mpu_ctrl[is_secure] & R_V7M_MPU_CTRL_PRIVDEFENA_MASK;
> + } else if (arm_feature(env, ARM_FEATURE_PMSA)) {
> + if (regime_el(env, mmu_idx) == 2) {
> + if (mmu_idx != ARMMMUIdx_E2) {
> + return false;
> + } else if ((mmu_idx == ARMMMUIdx_E2)
> + &&!(regime_sctlr(env, mmu_idx) & SCTLR_BR)) {
> + return false;
> + }
> + } else {
> + if (mmu_idx != ARMMMUIdx_Stage1_E1) {
> + return false;
> + } else if ((mmu_idx == ARMMMUIdx_Stage1_E1)
> + &&!(regime_sctlr(env, mmu_idx) & SCTLR_BR)) {
> + return false;
> + }
> + }
> + return true;
> } else {
> return regime_sctlr(env, mmu_idx) & SCTLR_BR;
> }
This logic seems rather confused:
(1) it's not possible to get to this function unless ARM_FEATURE_PMSA,
so the explicit check for that means the final "else" clause is now
unreachable code.
(2) You check for eg "mmu_idx != ARMMMUIdx_E2" and return early,
but that means that in the following
((mmu_idx == ARMMMUIdx_E2)
&&!(regime_sctlr(env, mmu_idx) & SCTLR_BR))
the first clause of the && is always true and is redundant.
(3) the thing we end up actually checking (SCTLR_BR for the
regime SCTLR) is the same now in all three major branches of
this code, so there's a lot of redundancy.
I think what you actually want here is to identify the set
mmu index values (if any!) that we don't want to do the
SCTLR_BR check for. Then return early for those, and have
a single
return regime_sctlr(env, mmu_idx) & SCTLR_BR;
for all the cases where checking BR is the right thing.
I think it may actually be the case that there is no mmuidx
value where we don't want to do the SCLTR_BR check, in
which case we don't need to change this function at all.
> @@ -1696,6 +1713,26 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
> return !(result->prot & (1 << access_type));
> }
>
> +static uint32_t *regime_rbar(CPUARMState *env, ARMMMUIdx mmu_idx,
> + uint32_t secure)
> +{
> + if (regime_el(env, mmu_idx) == 2) {
> + return env->pmsav8.hprbar[secure];
> + } else {
> + return env->pmsav8.rbar[secure];
> + }
> +}
> +
> +static uint32_t *regime_rlar(CPUARMState *env, ARMMMUIdx mmu_idx,
> + uint32_t secure)
> +{
> + if (regime_el(env, mmu_idx) == 2) {
> + return env->pmsav8.hprlar[secure];
> + } else {
> + return env->pmsav8.rlar[secure];
> + }
> +}
> +
> bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
> MMUAccessType access_type, ARMMMUIdx mmu_idx,
> bool secure, GetPhysAddrResult *result,
> @@ -1733,6 +1770,10 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
> *mregion = -1;
> }
>
> + if (mmu_idx == ARMMMUIdx_Stage2) {
> + fi->stage2 = true;
> + }
> +
> /*
> * Unlike the ARM ARM pseudocode, we don't need to check whether this
> * was an exception vector read from the vector table (which is always
> @@ -1749,17 +1790,27 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
> hit = true;
> }
>
> + uint32_t bitmask;
> + if (arm_feature(env, ARM_FEATURE_M)) {
> + bitmask = 0x1f;
> + fi->level = 1;
> + } else {
> + bitmask = 0x3f;
> + fi->level = 0;
> + }
We could in theory clean this up a bit, because on M-profile the
"FSR" value is not guest-facing; we only use it internally to pass
around some details of the fault cause, so as long as we're consistent
between the code here that sets fi->level and the code in m_helper.c
that looks at the FSC values we can set it to any value that's convenient.
But for this patchset we should definitely leave the existing M-profile
behaviour the way it is. I might come back and tweak the code once
this R-profile series has landed (or I might not think it worth bothering
and leave it indefinitely :-))
> +
> for (n = region_counter - 1; n >= 0; n--) {
> /* region search */
> /*
> - * Note that the base address is bits [31:5] from the register
> - * with bits [4:0] all zeroes, but the limit address is bits
> - * [31:5] from the register with bits [4:0] all ones.
> + * Note that the base address is bits [31:x] from the register
> + * with bits [x-1:0] all zeroes, but the limit address is bits
> + * [31:x] from the register with bits [x:0] all ones. Where x is
> + * 5 for Cortex-M and 6 for Cortex-R
> */
> - uint32_t base = env->pmsav8.rbar[secure][n] & ~0x1f;
> - uint32_t limit = env->pmsav8.rlar[secure][n] | 0x1f;
> + uint32_t base = regime_rbar(env, mmu_idx, secure)[n] & ~bitmask;
> + uint32_t limit = regime_rlar(env, mmu_idx, secure)[n] | bitmask;
>
> - if (!(env->pmsav8.rlar[secure][n] & 0x1)) {
> + if (!(regime_rlar(env, mmu_idx, secure)[n] & 0x1)) {
> /* Region disabled */
> continue;
> }
> @@ -1793,7 +1844,6 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
> * PMSAv7 where highest-numbered-region wins)
> */
> fi->type = ARMFault_Permission;
> - fi->level = 1;
> return true;
> }
>
> @@ -1803,8 +1853,11 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
> }
>
> if (!hit) {
> - /* background fault */
> - fi->type = ARMFault_Background;
> + if (arm_feature(env, ARM_FEATURE_M)) {
> + fi->type = ARMFault_Background;
> + } else {
> + fi->type = ARMFault_Permission;
> + }
> return true;
> }
>
> @@ -1812,12 +1865,14 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
> /* hit using the background region */
> get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->prot);
> } else {
> - uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2);
> - uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1);
> + uint32_t matched_rbar = regime_rbar(env, mmu_idx, secure)[matchregion];
> + uint32_t matched_rlar = regime_rlar(env, mmu_idx, secure)[matchregion];
> + uint32_t ap = extract32(matched_rbar, 1, 2);
> + uint32_t xn = extract32(matched_rbar, 0, 1);
> bool pxn = false;
>
> if (arm_feature(env, ARM_FEATURE_V8_1M)) {
> - pxn = extract32(env->pmsav8.rlar[secure][matchregion], 4, 1);
> + pxn = extract32(matched_rlar, 4, 1);
> }
>
> if (m_is_system_region(env, address)) {
> @@ -1825,21 +1880,49 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
> xn = 1;
> }
>
> - result->prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
> + if (arm_feature(env, ARM_FEATURE_M)) {
> + /*
> + * We don't need to look the attribute up in the MAIR0/MAIR1
> + * registers because that only tells us about cacheability.
> + */
> + result->prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
> + } else {
> + if (regime_el(env, mmu_idx) == 2) {
> + result->prot = simple_ap_to_rw_prot_is_user(ap,
> + mmu_idx != ARMMMUIdx_E2);
> + } else {
> + result->prot = simple_ap_to_rw_prot_is_user(ap,
> + mmu_idx != ARMMMUIdx_Stage1_E1);
This second one should be fine as just
result->prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
I think, because this is the EL1 case.
That in turn means you don't need to have the M-profile case separately,
because M-profile will never have the regime EL be 2.
> + }
> +
> + if (regime_sctlr(env, mmu_idx) & SCTLR_WXN
> + && (result->prot & PAGE_WRITE)) {
> + xn = 0x1;
> + }
I think that this will apply HSCTLR.WXN on the stage 2 check for
EL1/EL0 accesses, which I don't think is correct. In the pseudocode
HSCTLR.WXN is checked only for stage 1 accesses from EL2, not as
part of stage 2 checking (see AArch32.CheckPermission()).
> +
> + if ((regime_el(env, mmu_idx) == 1) && regime_sctlr(env, mmu_idx)
> + & SCTLR_UWXN && (ap == 0x1)) {
Don't break the line like this, it implies that the precedence
of & is less than that of &&, which it isn't.
> + xn = 0x1;
This should be setting pxn = 0x1, because SCTLR.UWXN only means
"unprivileged write permission implies EL1 XN", not "implies XN generally".
> + }
> +
> + uint8_t attrindx = extract32(matched_rlar, 1, 3);
> + uint64_t mair = env->cp15.mair_el[regime_el(env, mmu_idx)];
> + uint8_t sh = extract32(matched_rlar, 3, 2);
> + result->cacheattrs.is_s2_format = false;
> + result->cacheattrs.attrs = extract64(mair, attrindx * 8, 8);
> + result->cacheattrs.shareability = sh;
> + }
> +
> if (result->prot && !xn && !(pxn && !is_user)) {
> result->prot |= PAGE_EXEC;
> }
> - /*
> - * We don't need to look the attribute up in the MAIR0/MAIR1
> - * registers because that only tells us about cacheability.
> - */
> +
> if (mregion) {
> *mregion = matchregion;
> }
> }
>
> fi->type = ARMFault_Permission;
> - fi->level = 1;
> return !(result->prot & (1 << access_type));
> }
>
> @@ -2348,8 +2431,15 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
> cacheattrs1 = result->cacheattrs;
> memset(result, 0, sizeof(*result));
>
> - ret = get_phys_addr_lpae(env, ipa, access_type, s2_mmu_idx,
> - is_el0, result, fi);
> + /* S1 is done. Now do S2 translation. */
> + if (arm_feature(env, ARM_FEATURE_PMSA)) {
> + ret = get_phys_addr_pmsav8(env, ipa, access_type, s2_mmu_idx,
> + is_secure, result, fi);
> + } else {
> + ret = get_phys_addr_lpae(env, ipa, access_type, s2_mmu_idx,
> + is_el0, result, fi);
> + }
> +
This bit of code has unfortunately changed a lot due to a
recent refactoring landing...
> fi->s2addr = ipa;
>
> /* Combine the S1 and S2 perms. */
> --
> 2.34.1
thanks
-- PMM
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 0/7] Add ARM Cortex-R52 CPU
2022-10-23 15:36 [PATCH v4 0/7] Add ARM Cortex-R52 CPU tobias.roehmel
` (6 preceding siblings ...)
2022-10-23 15:36 ` [PATCH v4 7/7] target/arm: Add ARM Cortex-R52 CPU tobias.roehmel
@ 2022-11-18 15:03 ` Peter Maydell
7 siblings, 0 replies; 18+ messages in thread
From: Peter Maydell @ 2022-11-18 15:03 UTC (permalink / raw)
To: tobias.roehmel; +Cc: qemu-devel, Tobias Röhmel
On Sun, 23 Oct 2022 at 16:37, <tobias.roehmel@rwth-aachen.de> wrote:
>
> From: Tobias Röhmel <quic_trohmel@quicinc.com>
>
> Thanks again for all the help!
>
> Here is v4:
> 2. Made patch cleaner
> 3. Changed commit message
> 4. Replaced V8_R flag with ARM_FEATURE_PMSA|ARM_FEATURE_V8
> 5.
> Reworked the code to use existing pmsav7 variables
> Added migration support
> Added VSCTLR:
> I didn't add any functionality for it because I think
> Qemu doesn't model the behaviour it influences.
> 6.
> Lots of cleanup. I think I overcomplicated this a bit because
> of a misunderstanding. I thought HCR_VM is independent of enabling
> the different MPUs, but I see now that it doesn't make sense to enable
> HCR_VM when the MPUs are not enabled. I also think that there is an Error
> in the armv8-r manual supplement in Figure C1-3. With all that figured out
> the code for pmsav8r doesn't look that different from pmsav7 :)
I've now reviewed this version of the patchset; it's getting
quite close now, I think. Sorry it took me so long to get back to it.
-- PMM
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2022-11-18 15:04 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-23 15:36 [PATCH v4 0/7] Add ARM Cortex-R52 CPU tobias.roehmel
2022-10-23 15:36 ` [PATCH v4 1/7] target/arm: Don't add all MIDR aliases for cores that immplement PMSA tobias.roehmel
2022-10-23 23:06 ` Richard Henderson
2022-10-23 15:36 ` [PATCH v4 2/7] target/arm: Make RVBAR available for all ARMv8 CPUs tobias.roehmel
2022-11-14 17:04 ` Peter Maydell
2022-10-23 15:36 ` [PATCH v4 3/7] target/arm: Make stage_2_format for cache attributes optional tobias.roehmel
2022-11-14 17:13 ` Peter Maydell
2022-10-23 15:36 ` [PATCH v4 4/7] target/arm: Enable TTBCR_EAE for ARMv8-R AArch32 tobias.roehmel
2022-11-14 17:19 ` Peter Maydell
2022-11-15 11:37 ` Philippe Mathieu-Daudé
2022-11-15 12:01 ` Daniel P. Berrangé
2022-10-23 15:36 ` [PATCH v4 5/7] target/arm: Add PMSAv8r registers tobias.roehmel
2022-11-18 13:52 ` Peter Maydell
2022-10-23 15:36 ` [PATCH v4 6/7] target/arm: Add PMSAv8r functionality tobias.roehmel
2022-11-18 15:03 ` Peter Maydell
2022-10-23 15:36 ` [PATCH v4 7/7] target/arm: Add ARM Cortex-R52 CPU tobias.roehmel
2022-11-18 14:04 ` Peter Maydell
2022-11-18 15:03 ` [PATCH v4 0/7] " Peter Maydell
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.