aboutsummaryrefslogtreecommitdiff
path: root/target/arm/hvf/hvf.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/arm/hvf/hvf.c')
-rw-r--r--target/arm/hvf/hvf.c302
1 files changed, 154 insertions, 148 deletions
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index eb090e67a2..c1496ad5be 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -1199,57 +1199,61 @@ static bool hvf_sysreg_read_cp(CPUState *cpu, uint32_t reg, uint64_t *val)
return false;
}
-static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt)
+static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint64_t *val)
{
ARMCPU *arm_cpu = ARM_CPU(cpu);
CPUARMState *env = &arm_cpu->env;
- uint64_t val = 0;
+
+ if (arm_feature(env, ARM_FEATURE_PMU)) {
+ switch (reg) {
+ case SYSREG_PMCR_EL0:
+ *val = env->cp15.c9_pmcr;
+ return 0;
+ case SYSREG_PMCCNTR_EL0:
+ pmu_op_start(env);
+ *val = env->cp15.c15_ccnt;
+ pmu_op_finish(env);
+ return 0;
+ case SYSREG_PMCNTENCLR_EL0:
+ *val = env->cp15.c9_pmcnten;
+ return 0;
+ case SYSREG_PMOVSCLR_EL0:
+ *val = env->cp15.c9_pmovsr;
+ return 0;
+ case SYSREG_PMSELR_EL0:
+ *val = env->cp15.c9_pmselr;
+ return 0;
+ case SYSREG_PMINTENCLR_EL1:
+ *val = env->cp15.c9_pminten;
+ return 0;
+ case SYSREG_PMCCFILTR_EL0:
+ *val = env->cp15.pmccfiltr_el0;
+ return 0;
+ case SYSREG_PMCNTENSET_EL0:
+ *val = env->cp15.c9_pmcnten;
+ return 0;
+ case SYSREG_PMUSERENR_EL0:
+ *val = env->cp15.c9_pmuserenr;
+ return 0;
+ case SYSREG_PMCEID0_EL0:
+ case SYSREG_PMCEID1_EL0:
+ /* We can't really count anything yet, declare all events invalid */
+ *val = 0;
+ return 0;
+ }
+ }
switch (reg) {
case SYSREG_CNTPCT_EL0:
- val = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) /
+ *val = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) /
gt_cntfrq_period_ns(arm_cpu);
- break;
- case SYSREG_PMCR_EL0:
- val = env->cp15.c9_pmcr;
- break;
- case SYSREG_PMCCNTR_EL0:
- pmu_op_start(env);
- val = env->cp15.c15_ccnt;
- pmu_op_finish(env);
- break;
- case SYSREG_PMCNTENCLR_EL0:
- val = env->cp15.c9_pmcnten;
- break;
- case SYSREG_PMOVSCLR_EL0:
- val = env->cp15.c9_pmovsr;
- break;
- case SYSREG_PMSELR_EL0:
- val = env->cp15.c9_pmselr;
- break;
- case SYSREG_PMINTENCLR_EL1:
- val = env->cp15.c9_pminten;
- break;
- case SYSREG_PMCCFILTR_EL0:
- val = env->cp15.pmccfiltr_el0;
- break;
- case SYSREG_PMCNTENSET_EL0:
- val = env->cp15.c9_pmcnten;
- break;
- case SYSREG_PMUSERENR_EL0:
- val = env->cp15.c9_pmuserenr;
- break;
- case SYSREG_PMCEID0_EL0:
- case SYSREG_PMCEID1_EL0:
- /* We can't really count anything yet, declare all events invalid */
- val = 0;
- break;
+ return 0;
case SYSREG_OSLSR_EL1:
- val = env->cp15.oslsr_el1;
- break;
+ *val = env->cp15.oslsr_el1;
+ return 0;
case SYSREG_OSDLR_EL1:
/* Dummy register */
- break;
+ return 0;
case SYSREG_ICC_AP0R0_EL1:
case SYSREG_ICC_AP0R1_EL1:
case SYSREG_ICC_AP0R2_EL1:
@@ -1276,9 +1280,8 @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt)
case SYSREG_ICC_SRE_EL1:
case SYSREG_ICC_CTLR_EL1:
/* Call the TCG sysreg handler. This is only safe for GICv3 regs. */
- if (!hvf_sysreg_read_cp(cpu, reg, &val)) {
- hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
- return 1;
+ if (hvf_sysreg_read_cp(cpu, reg, &val)) {
+ return 0;
}
break;
case SYSREG_DBGBVR0_EL1:
@@ -1297,8 +1300,8 @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt)
case SYSREG_DBGBVR13_EL1:
case SYSREG_DBGBVR14_EL1:
case SYSREG_DBGBVR15_EL1:
- val = env->cp15.dbgbvr[SYSREG_CRM(reg)];
- break;
+ *val = env->cp15.dbgbvr[SYSREG_CRM(reg)];
+ return 0;
case SYSREG_DBGBCR0_EL1:
case SYSREG_DBGBCR1_EL1:
case SYSREG_DBGBCR2_EL1:
@@ -1315,8 +1318,8 @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt)
case SYSREG_DBGBCR13_EL1:
case SYSREG_DBGBCR14_EL1:
case SYSREG_DBGBCR15_EL1:
- val = env->cp15.dbgbcr[SYSREG_CRM(reg)];
- break;
+ *val = env->cp15.dbgbcr[SYSREG_CRM(reg)];
+ return 0;
case SYSREG_DBGWVR0_EL1:
case SYSREG_DBGWVR1_EL1:
case SYSREG_DBGWVR2_EL1:
@@ -1333,8 +1336,8 @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt)
case SYSREG_DBGWVR13_EL1:
case SYSREG_DBGWVR14_EL1:
case SYSREG_DBGWVR15_EL1:
- val = env->cp15.dbgwvr[SYSREG_CRM(reg)];
- break;
+ *val = env->cp15.dbgwvr[SYSREG_CRM(reg)];
+ return 0;
case SYSREG_DBGWCR0_EL1:
case SYSREG_DBGWCR1_EL1:
case SYSREG_DBGWCR2_EL1:
@@ -1351,35 +1354,25 @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt)
case SYSREG_DBGWCR13_EL1:
case SYSREG_DBGWCR14_EL1:
case SYSREG_DBGWCR15_EL1:
- val = env->cp15.dbgwcr[SYSREG_CRM(reg)];
- break;
+ *val = env->cp15.dbgwcr[SYSREG_CRM(reg)];
+ return 0;
default:
if (is_id_sysreg(reg)) {
/* ID system registers read as RES0 */
- val = 0;
- break;
+ *val = 0;
+ return 0;
}
- cpu_synchronize_state(cpu);
- trace_hvf_unhandled_sysreg_read(env->pc, reg,
- SYSREG_OP0(reg),
- SYSREG_OP1(reg),
- SYSREG_CRN(reg),
- SYSREG_CRM(reg),
- SYSREG_OP2(reg));
- hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
- return 1;
}
- trace_hvf_sysreg_read(reg,
- SYSREG_OP0(reg),
- SYSREG_OP1(reg),
- SYSREG_CRN(reg),
- SYSREG_CRM(reg),
- SYSREG_OP2(reg),
- val);
- hvf_set_reg(cpu, rt, val);
-
- return 0;
+ cpu_synchronize_state(cpu);
+ trace_hvf_unhandled_sysreg_read(env->pc, reg,
+ SYSREG_OP0(reg),
+ SYSREG_OP1(reg),
+ SYSREG_CRN(reg),
+ SYSREG_CRM(reg),
+ SYSREG_OP2(reg));
+ hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
+ return 1;
}
static void pmu_update_irq(CPUARMState *env)
@@ -1498,70 +1491,75 @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
SYSREG_OP2(reg),
val);
- switch (reg) {
- case SYSREG_PMCCNTR_EL0:
- pmu_op_start(env);
- env->cp15.c15_ccnt = val;
- pmu_op_finish(env);
- break;
- case SYSREG_PMCR_EL0:
- pmu_op_start(env);
-
- if (val & PMCRC) {
- /* The counter has been reset */
- env->cp15.c15_ccnt = 0;
- }
+ if (arm_feature(env, ARM_FEATURE_PMU)) {
+ switch (reg) {
+ case SYSREG_PMCCNTR_EL0:
+ pmu_op_start(env);
+ env->cp15.c15_ccnt = val;
+ pmu_op_finish(env);
+ return 0;
+ case SYSREG_PMCR_EL0:
+ pmu_op_start(env);
+
+ if (val & PMCRC) {
+ /* The counter has been reset */
+ env->cp15.c15_ccnt = 0;
+ }
- if (val & PMCRP) {
- unsigned int i;
- for (i = 0; i < pmu_num_counters(env); i++) {
- env->cp15.c14_pmevcntr[i] = 0;
+ if (val & PMCRP) {
+ unsigned int i;
+ for (i = 0; i < pmu_num_counters(env); i++) {
+ env->cp15.c14_pmevcntr[i] = 0;
+ }
}
- }
- env->cp15.c9_pmcr &= ~PMCR_WRITABLE_MASK;
- env->cp15.c9_pmcr |= (val & PMCR_WRITABLE_MASK);
+ env->cp15.c9_pmcr &= ~PMCR_WRITABLE_MASK;
+ env->cp15.c9_pmcr |= (val & PMCR_WRITABLE_MASK);
+
+ pmu_op_finish(env);
+ return 0;
+ case SYSREG_PMUSERENR_EL0:
+ env->cp15.c9_pmuserenr = val & 0xf;
+ return 0;
+ case SYSREG_PMCNTENSET_EL0:
+ env->cp15.c9_pmcnten |= (val & pmu_counter_mask(env));
+ return 0;
+ case SYSREG_PMCNTENCLR_EL0:
+ env->cp15.c9_pmcnten &= ~(val & pmu_counter_mask(env));
+ return 0;
+ case SYSREG_PMINTENCLR_EL1:
+ pmu_op_start(env);
+ env->cp15.c9_pminten |= val;
+ pmu_op_finish(env);
+ return 0;
+ case SYSREG_PMOVSCLR_EL0:
+ pmu_op_start(env);
+ env->cp15.c9_pmovsr &= ~val;
+ pmu_op_finish(env);
+ return 0;
+ case SYSREG_PMSWINC_EL0:
+ pmu_op_start(env);
+ pmswinc_write(env, val);
+ pmu_op_finish(env);
+ return 0;
+ case SYSREG_PMSELR_EL0:
+ env->cp15.c9_pmselr = val & 0x1f;
+ return 0;
+ case SYSREG_PMCCFILTR_EL0:
+ pmu_op_start(env);
+ env->cp15.pmccfiltr_el0 = val & PMCCFILTR_EL0;
+ pmu_op_finish(env);
+ return 0;
+ }
+ }
- pmu_op_finish(env);
- break;
- case SYSREG_PMUSERENR_EL0:
- env->cp15.c9_pmuserenr = val & 0xf;
- break;
- case SYSREG_PMCNTENSET_EL0:
- env->cp15.c9_pmcnten |= (val & pmu_counter_mask(env));
- break;
- case SYSREG_PMCNTENCLR_EL0:
- env->cp15.c9_pmcnten &= ~(val & pmu_counter_mask(env));
- break;
- case SYSREG_PMINTENCLR_EL1:
- pmu_op_start(env);
- env->cp15.c9_pminten |= val;
- pmu_op_finish(env);
- break;
- case SYSREG_PMOVSCLR_EL0:
- pmu_op_start(env);
- env->cp15.c9_pmovsr &= ~val;
- pmu_op_finish(env);
- break;
- case SYSREG_PMSWINC_EL0:
- pmu_op_start(env);
- pmswinc_write(env, val);
- pmu_op_finish(env);
- break;
- case SYSREG_PMSELR_EL0:
- env->cp15.c9_pmselr = val & 0x1f;
- break;
- case SYSREG_PMCCFILTR_EL0:
- pmu_op_start(env);
- env->cp15.pmccfiltr_el0 = val & PMCCFILTR_EL0;
- pmu_op_finish(env);
- break;
+ switch (reg) {
case SYSREG_OSLAR_EL1:
env->cp15.oslsr_el1 = val & 1;
- break;
+ return 0;
case SYSREG_OSDLR_EL1:
/* Dummy register */
- break;
+ return 0;
case SYSREG_ICC_AP0R0_EL1:
case SYSREG_ICC_AP0R1_EL1:
case SYSREG_ICC_AP0R2_EL1:
@@ -1588,13 +1586,13 @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
case SYSREG_ICC_SGI1R_EL1:
case SYSREG_ICC_SRE_EL1:
/* Call the TCG sysreg handler. This is only safe for GICv3 regs. */
- if (!hvf_sysreg_write_cp(cpu, reg, val)) {
- hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
+ if (hvf_sysreg_write_cp(cpu, reg, val)) {
+ return 0;
}
break;
case SYSREG_MDSCR_EL1:
env->cp15.mdscr_el1 = val;
- break;
+ return 0;
case SYSREG_DBGBVR0_EL1:
case SYSREG_DBGBVR1_EL1:
case SYSREG_DBGBVR2_EL1:
@@ -1612,7 +1610,7 @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
case SYSREG_DBGBVR14_EL1:
case SYSREG_DBGBVR15_EL1:
env->cp15.dbgbvr[SYSREG_CRM(reg)] = val;
- break;
+ return 0;
case SYSREG_DBGBCR0_EL1:
case SYSREG_DBGBCR1_EL1:
case SYSREG_DBGBCR2_EL1:
@@ -1630,7 +1628,7 @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
case SYSREG_DBGBCR14_EL1:
case SYSREG_DBGBCR15_EL1:
env->cp15.dbgbcr[SYSREG_CRM(reg)] = val;
- break;
+ return 0;
case SYSREG_DBGWVR0_EL1:
case SYSREG_DBGWVR1_EL1:
case SYSREG_DBGWVR2_EL1:
@@ -1648,7 +1646,7 @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
case SYSREG_DBGWVR14_EL1:
case SYSREG_DBGWVR15_EL1:
env->cp15.dbgwvr[SYSREG_CRM(reg)] = val;
- break;
+ return 0;
case SYSREG_DBGWCR0_EL1:
case SYSREG_DBGWCR1_EL1:
case SYSREG_DBGWCR2_EL1:
@@ -1666,20 +1664,18 @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
case SYSREG_DBGWCR14_EL1:
case SYSREG_DBGWCR15_EL1:
env->cp15.dbgwcr[SYSREG_CRM(reg)] = val;
- break;
- default:
- cpu_synchronize_state(cpu);
- trace_hvf_unhandled_sysreg_write(env->pc, reg,
- SYSREG_OP0(reg),
- SYSREG_OP1(reg),
- SYSREG_CRN(reg),
- SYSREG_CRM(reg),
- SYSREG_OP2(reg));
- hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
- return 1;
+ return 0;
}
- return 0;
+ cpu_synchronize_state(cpu);
+ trace_hvf_unhandled_sysreg_write(env->pc, reg,
+ SYSREG_OP0(reg),
+ SYSREG_OP1(reg),
+ SYSREG_CRN(reg),
+ SYSREG_CRM(reg),
+ SYSREG_OP2(reg));
+ hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
+ return 1;
}
static int hvf_inject_interrupts(CPUState *cpu)
@@ -1944,7 +1940,17 @@ int hvf_vcpu_exec(CPUState *cpu)
int sysreg_ret = 0;
if (isread) {
- sysreg_ret = hvf_sysreg_read(cpu, reg, rt);
+ sysreg_ret = hvf_sysreg_read(cpu, reg, &val);
+ if (!sysreg_ret) {
+ trace_hvf_sysreg_read(reg,
+ SYSREG_OP0(reg),
+ SYSREG_OP1(reg),
+ SYSREG_CRN(reg),
+ SYSREG_CRM(reg),
+ SYSREG_OP2(reg),
+ val);
+ hvf_set_reg(cpu, rt, val);
+ }
} else {
val = hvf_get_reg(cpu, rt);
sysreg_ret = hvf_sysreg_write(cpu, reg, val);