|
34 | 34 | #include <asm/kvm_emulate.h>
|
35 | 35 | #include <asm/kvm_host.h>
|
36 | 36 | #include <asm/kvm_mmu.h>
|
| 37 | +#include <asm/perf_event.h> |
37 | 38 |
|
38 | 39 | #include <trace/events/kvm.h>
|
39 | 40 |
|
@@ -439,6 +440,43 @@ static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
|
439 | 440 | vcpu_sys_reg(vcpu, MPIDR_EL1) = (1ULL << 31) | mpidr;
|
440 | 441 | }
|
441 | 442 |
|
| 443 | +static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) |
| 444 | +{ |
| 445 | + u64 pmcr, val; |
| 446 | + |
| 447 | + asm volatile("mrs %0, pmcr_el0\n" : "=r" (pmcr)); |
| 448 | + /* Writable bits of PMCR_EL0 (ARMV8_PMU_PMCR_MASK) is reset to UNKNOWN |
| 449 | + * except PMCR.E resetting to zero. |
| 450 | + */ |
| 451 | + val = ((pmcr & ~ARMV8_PMU_PMCR_MASK) |
| 452 | + | (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E); |
| 453 | + vcpu_sys_reg(vcpu, PMCR_EL0) = val; |
| 454 | +} |
| 455 | + |
| 456 | +static bool access_pmcr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, |
| 457 | + const struct sys_reg_desc *r) |
| 458 | +{ |
| 459 | + u64 val; |
| 460 | + |
| 461 | + if (!kvm_arm_pmu_v3_ready(vcpu)) |
| 462 | + return trap_raz_wi(vcpu, p, r); |
| 463 | + |
| 464 | + if (p->is_write) { |
| 465 | + /* Only update writeable bits of PMCR */ |
| 466 | + val = vcpu_sys_reg(vcpu, PMCR_EL0); |
| 467 | + val &= ~ARMV8_PMU_PMCR_MASK; |
| 468 | + val |= p->regval & ARMV8_PMU_PMCR_MASK; |
| 469 | + vcpu_sys_reg(vcpu, PMCR_EL0) = val; |
| 470 | + } else { |
| 471 | + /* PMCR.P & PMCR.C are RAZ */ |
| 472 | + val = vcpu_sys_reg(vcpu, PMCR_EL0) |
| 473 | + & ~(ARMV8_PMU_PMCR_P | ARMV8_PMU_PMCR_C); |
| 474 | + p->regval = val; |
| 475 | + } |
| 476 | + |
| 477 | + return true; |
| 478 | +} |
| 479 | + |
442 | 480 | /* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */
|
443 | 481 | #define DBG_BCR_BVR_WCR_WVR_EL1(n) \
|
444 | 482 | /* DBGBVRn_EL1 */ \
|
@@ -623,7 +661,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
623 | 661 |
|
624 | 662 | /* PMCR_EL0 */
|
625 | 663 | { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b000),
|
626 |
| - trap_raz_wi }, |
| 664 | + access_pmcr, reset_pmcr, }, |
627 | 665 | /* PMCNTENSET_EL0 */
|
628 | 666 | { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b001),
|
629 | 667 | trap_raz_wi },
|
@@ -885,7 +923,7 @@ static const struct sys_reg_desc cp15_regs[] = {
|
885 | 923 | { Op1( 0), CRn( 7), CRm(14), Op2( 2), access_dcsw },
|
886 | 924 |
|
887 | 925 | /* PMU */
|
888 |
| - { Op1( 0), CRn( 9), CRm(12), Op2( 0), trap_raz_wi }, |
| 926 | + { Op1( 0), CRn( 9), CRm(12), Op2( 0), access_pmcr }, |
889 | 927 | { Op1( 0), CRn( 9), CRm(12), Op2( 1), trap_raz_wi },
|
890 | 928 | { Op1( 0), CRn( 9), CRm(12), Op2( 2), trap_raz_wi },
|
891 | 929 | { Op1( 0), CRn( 9), CRm(12), Op2( 3), trap_raz_wi },
|
|
0 commit comments