Currently, the debug-exceptions test doesn't have a test case for
a linked breakpoint. Add a test case for the linked breakpoint to
the test. The new test case uses a pair of breakpoints. One is the
higiest numbered context-aware breakpoint (for Context ID match),
and the other one is the breakpoint#0 (for Address Match), which
is linked to the context-aware breakpoint.

Signed-off-by: Reiji Watanabe <rei...@google.com>
---
 .../selftests/kvm/aarch64/debug-exceptions.c  | 63 +++++++++++++++++--
 1 file changed, 57 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/kvm/aarch64/debug-exceptions.c 
b/tools/testing/selftests/kvm/aarch64/debug-exceptions.c
index 72ec9bb16682..362e7668a978 100644
--- a/tools/testing/selftests/kvm/aarch64/debug-exceptions.c
+++ b/tools/testing/selftests/kvm/aarch64/debug-exceptions.c
@@ -12,6 +12,10 @@
 #define DBGBCR_EXEC    (0x0 << 3)
 #define DBGBCR_EL1     (0x1 << 1)
 #define DBGBCR_E       (0x1 << 0)
+#define DBGBCR_LBN_SHIFT       16
+#define DBGBCR_BT_SHIFT                20
+#define DBGBCR_BT_ADDR_LINK_CTX        (0x1 << DBGBCR_BT_SHIFT)
+#define DBGBCR_BT_CTX_LINK     (0x3 << DBGBCR_BT_SHIFT)
 
 #define DBGWCR_LEN8    (0xff << 5)
 #define DBGWCR_RD      (0x1 << 3)
@@ -22,7 +26,7 @@
 #define SPSR_D         (1 << 9)
 #define SPSR_SS                (1 << 21)
 
-extern unsigned char sw_bp, sw_bp2, hw_bp, hw_bp2, bp_svc, bp_brk, hw_wp, 
ss_start;
+extern unsigned char sw_bp, sw_bp2, hw_bp, hw_bp2, bp_svc, bp_brk, hw_wp, 
ss_start, hw_bp_ctx;
 extern unsigned char iter_ss_begin, iter_ss_end;
 static volatile uint64_t sw_bp_addr, hw_bp_addr;
 static volatile uint64_t wp_addr, wp_data_addr;
@@ -105,6 +109,7 @@ static void reset_debug_state(void)
        isb();
 
        write_sysreg(0, mdscr_el1);
+       write_sysreg(0, contextidr_el1);
 
        /* Reset all bcr/bvr/wcr/wvr registers */
        dfr0 = read_sysreg(id_aa64dfr0_el1);
@@ -166,6 +171,31 @@ static void install_hw_bp(uint8_t bpn, uint64_t addr)
        enable_monitor_debug_exceptions();
 }
 
+void install_hw_bp_ctx(uint8_t addr_bp, uint8_t ctx_bp, uint64_t addr,
+                      uint64_t ctx)
+{
+       uint32_t addr_bcr, ctx_bcr;
+
+       /* Setup a context-aware breakpoint for Linked Context ID Match */
+       ctx_bcr = DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1 | DBGBCR_E |
+                 DBGBCR_BT_CTX_LINK;
+       write_dbgbcr(ctx_bp, ctx_bcr);
+       write_dbgbvr(ctx_bp, ctx);
+
+       /*
+        * Setup a normal breakpoint for Linked Address Match, and link it
+        * to the context-aware breakpoint.
+        */
+       addr_bcr = DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1 | DBGBCR_E |
+                  DBGBCR_BT_ADDR_LINK_CTX |
+                  ((uint32_t)ctx_bp << DBGBCR_LBN_SHIFT);
+       write_dbgbcr(addr_bp, addr_bcr);
+       write_dbgbvr(addr_bp, addr);
+       isb();
+
+       enable_monitor_debug_exceptions();
+}
+
 static void install_ss(void)
 {
        uint32_t mdscr;
@@ -179,8 +209,10 @@ static void install_ss(void)
 
 static volatile char write_data;
 
-static void guest_code(uint8_t bpn, uint8_t wpn)
+static void guest_code(uint8_t bpn, uint8_t wpn, uint8_t ctx_bpn)
 {
+       uint64_t ctx = 0xabcdef;        /* a random context number */
+
        /* Software-breakpoint */
        reset_debug_state();
        asm volatile("sw_bp: brk #0");
@@ -263,6 +295,17 @@ static void guest_code(uint8_t bpn, uint8_t wpn)
                     : : : "x0");
        GUEST_ASSERT_EQ(ss_addr[0], 0);
 
+       /* Linked hardware-breakpoint */
+       hw_bp_addr = 0;
+       reset_debug_state();
+       install_hw_bp_ctx(bpn, ctx_bpn, PC(hw_bp_ctx), ctx);
+       /* Set context id */
+       write_sysreg(ctx, contextidr_el1);
+       isb();
+       asm volatile("hw_bp_ctx: nop");
+       write_sysreg(0, contextidr_el1);
+       GUEST_ASSERT_EQ(hw_bp_addr, PC(hw_bp_ctx));
+
        GUEST_DONE();
 }
 
@@ -342,11 +385,12 @@ static int debug_version(uint64_t id_aa64dfr0)
        return FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_DEBUGVER), id_aa64dfr0);
 }
 
-static void test_guest_debug_exceptions(void)
+static void test_guest_debug_exceptions(uint64_t aa64dfr0)
 {
        struct kvm_vcpu *vcpu;
        struct kvm_vm *vm;
        struct ucall uc;
+       uint8_t brp_num;
 
        vm = vm_create_with_one_vcpu(&vcpu, guest_code);
        ucall_init(vm, NULL);
@@ -365,8 +409,15 @@ static void test_guest_debug_exceptions(void)
        vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
                                ESR_EC_SVC64, guest_svc_handler);
 
-       /* Run tests with breakpoint#0 and watchpoint#0. */
-       vcpu_args_set(vcpu, 2, 0, 0);
+       /* Number of breakpoints */
+       brp_num = FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_BRPS), aa64dfr0) + 1;
+       __TEST_REQUIRE(brp_num >= 2, "At least two breakpoints are required");
+
+       /*
+        * Run tests with breakpoint#0, watchpoint#0, and the higiest
+        * numbered (context-aware) breakpoint.
+        */
+       vcpu_args_set(vcpu, 3, 0, 0, brp_num - 1);
 
        vcpu_run(vcpu);
        switch (get_ucall(vcpu, &uc)) {
@@ -483,7 +534,7 @@ int main(int argc, char *argv[])
                }
        }
 
-       test_guest_debug_exceptions();
+       test_guest_debug_exceptions(aa64dfr0);
        test_single_step_from_userspace(ss_iteration);
 
        return 0;
-- 
2.38.0.413.g74048e4d9e-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

Reply via email to