|
|
@@ -626,7 +626,7 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
|
|
|
*/
|
|
|
val = ((pmcr & ~ARMV8_PMU_PMCR_MASK)
|
|
|
| (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E);
|
|
|
- __vcpu_sys_reg(vcpu, PMCR_EL0) = val;
|
|
|
+ __vcpu_sys_reg(vcpu, r->reg) = val;
|
|
|
}
|
|
|
|
|
|
static bool check_pmu_access_disabled(struct kvm_vcpu *vcpu, u64 flags)
|
|
|
@@ -968,13 +968,13 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
|
|
|
/* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */
|
|
|
#define DBG_BCR_BVR_WCR_WVR_EL1(n) \
|
|
|
{ SYS_DESC(SYS_DBGBVRn_EL1(n)), \
|
|
|
- trap_bvr, reset_bvr, n, 0, get_bvr, set_bvr }, \
|
|
|
+ trap_bvr, reset_bvr, 0, 0, get_bvr, set_bvr }, \
|
|
|
{ SYS_DESC(SYS_DBGBCRn_EL1(n)), \
|
|
|
- trap_bcr, reset_bcr, n, 0, get_bcr, set_bcr }, \
|
|
|
+ trap_bcr, reset_bcr, 0, 0, get_bcr, set_bcr }, \
|
|
|
{ SYS_DESC(SYS_DBGWVRn_EL1(n)), \
|
|
|
- trap_wvr, reset_wvr, n, 0, get_wvr, set_wvr }, \
|
|
|
+ trap_wvr, reset_wvr, 0, 0, get_wvr, set_wvr }, \
|
|
|
{ SYS_DESC(SYS_DBGWCRn_EL1(n)), \
|
|
|
- trap_wcr, reset_wcr, n, 0, get_wcr, set_wcr }
|
|
|
+ trap_wcr, reset_wcr, 0, 0, get_wcr, set_wcr }
|
|
|
|
|
|
/* Macro to expand the PMEVCNTRn_EL0 register */
|
|
|
#define PMU_PMEVCNTR_EL0(n) \
|
|
|
@@ -1359,7 +1359,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
|
|
|
|
|
{ SYS_DESC(SYS_CSSELR_EL1), NULL, reset_unknown, CSSELR_EL1 },
|
|
|
|
|
|
- { SYS_DESC(SYS_PMCR_EL0), access_pmcr, reset_pmcr, },
|
|
|
+ { SYS_DESC(SYS_PMCR_EL0), access_pmcr, reset_pmcr, PMCR_EL0 },
|
|
|
{ SYS_DESC(SYS_PMCNTENSET_EL0), access_pmcnten, reset_unknown, PMCNTENSET_EL0 },
|
|
|
{ SYS_DESC(SYS_PMCNTENCLR_EL0), access_pmcnten, NULL, PMCNTENSET_EL0 },
|
|
|
{ SYS_DESC(SYS_PMOVSCLR_EL0), access_pmovs, NULL, PMOVSSET_EL0 },
|
|
|
@@ -2072,13 +2072,19 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu,
|
|
|
}
|
|
|
|
|
|
static void reset_sys_reg_descs(struct kvm_vcpu *vcpu,
|
|
|
- const struct sys_reg_desc *table, size_t num)
|
|
|
+ const struct sys_reg_desc *table, size_t num,
|
|
|
+ unsigned long *bmap)
|
|
|
{
|
|
|
unsigned long i;
|
|
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
- if (table[i].reset)
|
|
|
+ if (table[i].reset) {
|
|
|
+ int reg = table[i].reg;
|
|
|
+
|
|
|
table[i].reset(vcpu, &table[i]);
|
|
|
+ if (reg > 0 && reg < NR_SYS_REGS)
|
|
|
+ set_bit(reg, bmap);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -2576,18 +2582,16 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
|
|
|
{
|
|
|
size_t num;
|
|
|
const struct sys_reg_desc *table;
|
|
|
-
|
|
|
- /* Catch someone adding a register without putting in reset entry. */
|
|
|
- memset(&vcpu->arch.ctxt.sys_regs, 0x42, sizeof(vcpu->arch.ctxt.sys_regs));
|
|
|
+ DECLARE_BITMAP(bmap, NR_SYS_REGS) = { 0, };
|
|
|
|
|
|
/* Generic chip reset first (so target could override). */
|
|
|
- reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
|
|
|
+ reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs), bmap);
|
|
|
|
|
|
table = get_target_table(vcpu->arch.target, true, &num);
|
|
|
- reset_sys_reg_descs(vcpu, table, num);
|
|
|
+ reset_sys_reg_descs(vcpu, table, num, bmap);
|
|
|
|
|
|
for (num = 1; num < NR_SYS_REGS; num++) {
|
|
|
- if (WARN(__vcpu_sys_reg(vcpu, num) == 0x4242424242424242,
|
|
|
+ if (WARN(!test_bit(num, bmap),
|
|
|
"Didn't reset __vcpu_sys_reg(%zi)\n", num))
|
|
|
break;
|
|
|
}
|