aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2014-04-24 05:31:37 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2014-07-11 07:57:45 -0400
commitbdfb4b389c8d8f07e2d5b8e1291e01c789ba4aad (patch)
treec8ea6ce76344e6ad816ab89ca2bf280bca88ac28
parente6a9551760623d1703487e8a16bb9c3ea8a7e7a8 (diff)
arm64: KVM: add trap handlers for AArch32 debug registers
Add handlers for all the AArch32 debug registers that are accessible from EL0 or EL1. The code follow the same strategy as the AArch64 counterpart with regards to tracking the dirty state of the debug registers. Reviewed-by: Anup Patel <anup.patel@linaro.org> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r--arch/arm64/include/asm/kvm_asm.h9
-rw-r--r--arch/arm64/kvm/sys_regs.c144
2 files changed, 151 insertions, 2 deletions
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 69027ded5006..483842180f8f 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -95,6 +95,15 @@
95#define c10_AMAIR0 (AMAIR_EL1 * 2) /* Aux Memory Attr Indirection Reg */ 95#define c10_AMAIR0 (AMAIR_EL1 * 2) /* Aux Memory Attr Indirection Reg */
96#define c10_AMAIR1 (c10_AMAIR0 + 1)/* Aux Memory Attr Indirection Reg */ 96#define c10_AMAIR1 (c10_AMAIR0 + 1)/* Aux Memory Attr Indirection Reg */
97#define c14_CNTKCTL (CNTKCTL_EL1 * 2) /* Timer Control Register (PL1) */ 97#define c14_CNTKCTL (CNTKCTL_EL1 * 2) /* Timer Control Register (PL1) */
98
99#define cp14_DBGDSCRext (MDSCR_EL1 * 2)
100#define cp14_DBGBCR0 (DBGBCR0_EL1 * 2)
101#define cp14_DBGBVR0 (DBGBVR0_EL1 * 2)
102#define cp14_DBGBXVR0 (cp14_DBGBVR0 + 1)
103#define cp14_DBGWCR0 (DBGWCR0_EL1 * 2)
104#define cp14_DBGWVR0 (DBGWVR0_EL1 * 2)
105#define cp14_DBGDCCINT (MDCCINT_EL1 * 2)
106
98#define NR_COPRO_REGS (NR_SYS_REGS * 2) 107#define NR_COPRO_REGS (NR_SYS_REGS * 2)
99 108
100#define ARM_EXCEPTION_IRQ 0 109#define ARM_EXCEPTION_IRQ 0
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 8ab47c7326ed..a4fd5267c65b 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -494,12 +494,153 @@ static const struct sys_reg_desc sys_reg_descs[] = {
494 NULL, reset_val, FPEXC32_EL2, 0x70 }, 494 NULL, reset_val, FPEXC32_EL2, 0x70 },
495}; 495};
496 496
497/* Trapped cp14 registers */ 497static bool trap_dbgidr(struct kvm_vcpu *vcpu,
498 const struct sys_reg_params *p,
499 const struct sys_reg_desc *r)
500{
501 if (p->is_write) {
502 return ignore_write(vcpu, p);
503 } else {
504 u64 dfr = read_cpuid(ID_AA64DFR0_EL1);
505 u64 pfr = read_cpuid(ID_AA64PFR0_EL1);
506 u32 el3 = !!((pfr >> 12) & 0xf);
507
508 *vcpu_reg(vcpu, p->Rt) = ((((dfr >> 20) & 0xf) << 28) |
509 (((dfr >> 12) & 0xf) << 24) |
510 (((dfr >> 28) & 0xf) << 20) |
511 (6 << 16) | (el3 << 14) | (el3 << 12));
512 return true;
513 }
514}
515
516static bool trap_debug32(struct kvm_vcpu *vcpu,
517 const struct sys_reg_params *p,
518 const struct sys_reg_desc *r)
519{
520 if (p->is_write) {
521 vcpu_cp14(vcpu, r->reg) = *vcpu_reg(vcpu, p->Rt);
522 vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
523 } else {
524 *vcpu_reg(vcpu, p->Rt) = vcpu_cp14(vcpu, r->reg);
525 }
526
527 return true;
528}
529
530#define DBG_BCR_BVR_WCR_WVR(n) \
531 /* DBGBVRn */ \
532 { Op1( 0), CRn( 0), CRm((n)), Op2( 4), trap_debug32, \
533 NULL, (cp14_DBGBVR0 + (n) * 2) }, \
534 /* DBGBCRn */ \
535 { Op1( 0), CRn( 0), CRm((n)), Op2( 5), trap_debug32, \
536 NULL, (cp14_DBGBCR0 + (n) * 2) }, \
537 /* DBGWVRn */ \
538 { Op1( 0), CRn( 0), CRm((n)), Op2( 6), trap_debug32, \
539 NULL, (cp14_DBGWVR0 + (n) * 2) }, \
540 /* DBGWCRn */ \
541 { Op1( 0), CRn( 0), CRm((n)), Op2( 7), trap_debug32, \
542 NULL, (cp14_DBGWCR0 + (n) * 2) }
543
544#define DBGBXVR(n) \
545 { Op1( 0), CRn( 1), CRm((n)), Op2( 1), trap_debug32, \
546 NULL, cp14_DBGBXVR0 + n * 2 }
547
548/*
549 * Trapped cp14 registers. We generally ignore most of the external
550 * debug, on the principle that they don't really make sense to a
551 * guest. Revisit this one day, whould this principle change.
552 */
498static const struct sys_reg_desc cp14_regs[] = { 553static const struct sys_reg_desc cp14_regs[] = {
554 /* DBGIDR */
555 { Op1( 0), CRn( 0), CRm( 0), Op2( 0), trap_dbgidr },
556 /* DBGDTRRXext */
557 { Op1( 0), CRn( 0), CRm( 0), Op2( 2), trap_raz_wi },
558
559 DBG_BCR_BVR_WCR_WVR(0),
560 /* DBGDSCRint */
561 { Op1( 0), CRn( 0), CRm( 1), Op2( 0), trap_raz_wi },
562 DBG_BCR_BVR_WCR_WVR(1),
563 /* DBGDCCINT */
564 { Op1( 0), CRn( 0), CRm( 2), Op2( 0), trap_debug32 },
565 /* DBGDSCRext */
566 { Op1( 0), CRn( 0), CRm( 2), Op2( 2), trap_debug32 },
567 DBG_BCR_BVR_WCR_WVR(2),
568 /* DBGDTR[RT]Xint */
569 { Op1( 0), CRn( 0), CRm( 3), Op2( 0), trap_raz_wi },
570 /* DBGDTR[RT]Xext */
571 { Op1( 0), CRn( 0), CRm( 3), Op2( 2), trap_raz_wi },
572 DBG_BCR_BVR_WCR_WVR(3),
573 DBG_BCR_BVR_WCR_WVR(4),
574 DBG_BCR_BVR_WCR_WVR(5),
575 /* DBGWFAR */
576 { Op1( 0), CRn( 0), CRm( 6), Op2( 0), trap_raz_wi },
577 /* DBGOSECCR */
578 { Op1( 0), CRn( 0), CRm( 6), Op2( 2), trap_raz_wi },
579 DBG_BCR_BVR_WCR_WVR(6),
580 /* DBGVCR */
581 { Op1( 0), CRn( 0), CRm( 7), Op2( 0), trap_debug32 },
582 DBG_BCR_BVR_WCR_WVR(7),
583 DBG_BCR_BVR_WCR_WVR(8),
584 DBG_BCR_BVR_WCR_WVR(9),
585 DBG_BCR_BVR_WCR_WVR(10),
586 DBG_BCR_BVR_WCR_WVR(11),
587 DBG_BCR_BVR_WCR_WVR(12),
588 DBG_BCR_BVR_WCR_WVR(13),
589 DBG_BCR_BVR_WCR_WVR(14),
590 DBG_BCR_BVR_WCR_WVR(15),
591
592 /* DBGDRAR (32bit) */
593 { Op1( 0), CRn( 1), CRm( 0), Op2( 0), trap_raz_wi },
594
595 DBGBXVR(0),
596 /* DBGOSLAR */
597 { Op1( 0), CRn( 1), CRm( 0), Op2( 4), trap_raz_wi },
598 DBGBXVR(1),
599 /* DBGOSLSR */
600 { Op1( 0), CRn( 1), CRm( 1), Op2( 4), trap_oslsr_el1 },
601 DBGBXVR(2),
602 DBGBXVR(3),
603 /* DBGOSDLR */
604 { Op1( 0), CRn( 1), CRm( 3), Op2( 4), trap_raz_wi },
605 DBGBXVR(4),
606 /* DBGPRCR */
607 { Op1( 0), CRn( 1), CRm( 4), Op2( 4), trap_raz_wi },
608 DBGBXVR(5),
609 DBGBXVR(6),
610 DBGBXVR(7),
611 DBGBXVR(8),
612 DBGBXVR(9),
613 DBGBXVR(10),
614 DBGBXVR(11),
615 DBGBXVR(12),
616 DBGBXVR(13),
617 DBGBXVR(14),
618 DBGBXVR(15),
619
620 /* DBGDSAR (32bit) */
621 { Op1( 0), CRn( 2), CRm( 0), Op2( 0), trap_raz_wi },
622
623 /* DBGDEVID2 */
624 { Op1( 0), CRn( 7), CRm( 0), Op2( 7), trap_raz_wi },
625 /* DBGDEVID1 */
626 { Op1( 0), CRn( 7), CRm( 1), Op2( 7), trap_raz_wi },
627 /* DBGDEVID */
628 { Op1( 0), CRn( 7), CRm( 2), Op2( 7), trap_raz_wi },
629 /* DBGCLAIMSET */
630 { Op1( 0), CRn( 7), CRm( 8), Op2( 6), trap_raz_wi },
631 /* DBGCLAIMCLR */
632 { Op1( 0), CRn( 7), CRm( 9), Op2( 6), trap_raz_wi },
633 /* DBGAUTHSTATUS */
634 { Op1( 0), CRn( 7), CRm(14), Op2( 6), trap_dbgauthstatus_el1 },
499}; 635};
500 636
501/* Trapped cp14 64bit registers */ 637/* Trapped cp14 64bit registers */
502static const struct sys_reg_desc cp14_64_regs[] = { 638static const struct sys_reg_desc cp14_64_regs[] = {
639 /* DBGDRAR (64bit) */
640 { Op1( 0), CRm( 1), .access = trap_raz_wi },
641
642 /* DBGDSAR (64bit) */
643 { Op1( 0), CRm( 2), .access = trap_raz_wi },
503}; 644};
504 645
505/* 646/*
@@ -547,7 +688,6 @@ static const struct sys_reg_desc cp15_regs[] = {
547 { Op1( 0), CRn(10), CRm( 3), Op2( 0), access_vm_reg, NULL, c10_AMAIR0 }, 688 { Op1( 0), CRn(10), CRm( 3), Op2( 0), access_vm_reg, NULL, c10_AMAIR0 },
548 { Op1( 0), CRn(10), CRm( 3), Op2( 1), access_vm_reg, NULL, c10_AMAIR1 }, 689 { Op1( 0), CRn(10), CRm( 3), Op2( 1), access_vm_reg, NULL, c10_AMAIR1 },
549 { Op1( 0), CRn(13), CRm( 0), Op2( 1), access_vm_reg, NULL, c13_CID }, 690 { Op1( 0), CRn(13), CRm( 0), Op2( 1), access_vm_reg, NULL, c13_CID },
550
551}; 691};
552 692
553static const struct sys_reg_desc cp15_64_regs[] = { 693static const struct sys_reg_desc cp15_64_regs[] = {