kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [kvm-unit-tests PATCH 0/3] arm64: debug: add migration tests for debug state
@ 2021-12-10 16:58 Ricardo Koller
  2021-12-10 16:58 ` [kvm-unit-tests PATCH 1/3] arm64: debug: add a migration test for breakpoint state Ricardo Koller
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Ricardo Koller @ 2021-12-10 16:58 UTC (permalink / raw)
  To: kvm, kvmarm
  Cc: drjones, Paolo Bonzini, maz, oupton, yuzenghui, jingzhangos,
	pshier, rananta, reijiw, Ricardo Koller

Add some tests for checking that we can migrate debug state correctly: setup
some breakpoints/watchpoints/single-stepping, migrate, and then check that we
get the expected exceptions.

The 3 patches in this series add tests for breakpoints, watchpoints, and
single-stepping one patch at a time.  Each patch adds a migration test and a
sanity test (to test that debugging works with no migration).

Note that this is limited to 64-bits and a single vcpu. Also note that some of
the code, like reset_debug_state, is borrowed from kvm selftests.

Ricardo Koller (3):
  arm64: debug: add a migration test for breakpoint state
  arm64: debug: add a migration test for watchpoint state
  arm64: debug: add a migration test for single-step state

 arm/Makefile.arm64 |   1 +
 arm/debug.c        | 420 +++++++++++++++++++++++++++++++++++++++++++++
 arm/unittests.cfg  |  37 ++++
 3 files changed, 458 insertions(+)
 create mode 100644 arm/debug.c

-- 
2.34.1.173.g76aa8bc2d0-goog


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [kvm-unit-tests PATCH 1/3] arm64: debug: add a migration test for breakpoint state
  2021-12-10 16:58 [kvm-unit-tests PATCH 0/3] arm64: debug: add migration tests for debug state Ricardo Koller
@ 2021-12-10 16:58 ` Ricardo Koller
  2021-12-10 16:58 ` [kvm-unit-tests PATCH 2/3] arm64: debug: add a migration test for watchpoint state Ricardo Koller
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Ricardo Koller @ 2021-12-10 16:58 UTC (permalink / raw)
  To: kvm, kvmarm
  Cc: drjones, Paolo Bonzini, maz, oupton, yuzenghui, jingzhangos,
	pshier, rananta, reijiw, Ricardo Koller

Test the migration of breakpoint state. Program as many breakpoitns as
possible, migrate, and check that we get the corresponding exceptions.

Signed-off-by: Ricardo Koller <ricarkol@google.com>
---
 arm/Makefile.arm64 |   1 +
 arm/debug.c        | 209 +++++++++++++++++++++++++++++++++++++++++++++
 arm/unittests.cfg  |  13 +++
 3 files changed, 223 insertions(+)
 create mode 100644 arm/debug.c

diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64
index e8a38d7..6feac76 100644
--- a/arm/Makefile.arm64
+++ b/arm/Makefile.arm64
@@ -31,6 +31,7 @@ OBJDIRS += lib/arm64
 tests = $(TEST_DIR)/timer.flat
 tests += $(TEST_DIR)/micro-bench.flat
 tests += $(TEST_DIR)/cache.flat
+tests += $(TEST_DIR)/debug.flat
 
 include $(SRCDIR)/$(TEST_DIR)/Makefile.common
 
diff --git a/arm/debug.c b/arm/debug.c
new file mode 100644
index 0000000..fedf4ab
--- /dev/null
+++ b/arm/debug.c
@@ -0,0 +1,209 @@
+#include <libcflat.h>
+#include <errata.h>
+#include <asm/setup.h>
+#include <asm/processor.h>
+#include <asm/delay.h>
+#include <asm/smp.h>
+#include <asm/barrier.h>
+#include <asm/io.h>
+
+#define MDSCR_KDE		(1 << 13)
+#define MDSCR_MDE		(1 << 15)
+
+#define DBGBCR_LEN8		(0xff << 5)
+#define DBGBCR_EXEC		(0x0 << 3)
+#define DBGBCR_EL1		(0x1 << 1)
+#define DBGBCR_E		(0x1 << 0)
+
+#define SPSR_D			(1 << 9)
+
+#define ESR_EC_HW_BP_CURRENT    0x31
+
+#define ID_AA64DFR0_BRPS_SHIFT	12
+#define ID_AA64DFR0_BRPS_MASK	0xf
+
+static volatile uint64_t hw_bp_idx, hw_bp_addr[16];
+
+static void hw_bp_handler(struct pt_regs *regs, unsigned int esr)
+{
+	hw_bp_addr[hw_bp_idx++] = regs->pc;
+	regs->pstate |= SPSR_D;
+}
+
+static int get_num_hw_bp(void)
+{
+	uint64_t reg = read_sysreg(id_aa64dfr0_el1);
+	/* Number of breakpoints, minus 1 */
+	uint8_t brps = (reg >> ID_AA64DFR0_BRPS_SHIFT) & ID_AA64DFR0_BRPS_MASK;
+
+	return brps + 1;
+}
+
+static void write_dbgbcr(int n, uint32_t bcr)
+{
+	switch (n) {
+	case 0:
+		write_sysreg(bcr, dbgbcr0_el1); break;
+	case 1:
+		write_sysreg(bcr, dbgbcr1_el1); break;
+	case 2:
+		write_sysreg(bcr, dbgbcr2_el1); break;
+	case 3:
+		write_sysreg(bcr, dbgbcr3_el1); break;
+	case 4:
+		write_sysreg(bcr, dbgbcr4_el1); break;
+	case 5:
+		write_sysreg(bcr, dbgbcr5_el1); break;
+	case 6:
+		write_sysreg(bcr, dbgbcr6_el1); break;
+	case 7:
+		write_sysreg(bcr, dbgbcr7_el1); break;
+	case 8:
+		write_sysreg(bcr, dbgbcr8_el1); break;
+	case 9:
+		write_sysreg(bcr, dbgbcr9_el1); break;
+	case 10:
+		write_sysreg(bcr, dbgbcr10_el1); break;
+	case 11:
+		write_sysreg(bcr, dbgbcr11_el1); break;
+	case 12:
+		write_sysreg(bcr, dbgbcr12_el1); break;
+	case 13:
+		write_sysreg(bcr, dbgbcr13_el1); break;
+	case 14:
+		write_sysreg(bcr, dbgbcr14_el1); break;
+	case 15:
+		write_sysreg(bcr, dbgbcr15_el1); break;
+	default:
+		report_abort("Invalid bcr");
+	}
+}
+
+static void write_dbgbvr(int n, uint64_t bvr)
+{
+	switch (n) {
+	case 0:
+		write_sysreg(bvr, dbgbvr0_el1); break;
+	case 1:
+		write_sysreg(bvr, dbgbvr1_el1); break;
+	case 2:
+		write_sysreg(bvr, dbgbvr2_el1); break;
+	case 3:
+		write_sysreg(bvr, dbgbvr3_el1); break;
+	case 4:
+		write_sysreg(bvr, dbgbvr4_el1); break;
+	case 5:
+		write_sysreg(bvr, dbgbvr5_el1); break;
+	case 6:
+		write_sysreg(bvr, dbgbvr6_el1); break;
+	case 7:
+		write_sysreg(bvr, dbgbvr7_el1); break;
+	case 8:
+		write_sysreg(bvr, dbgbvr8_el1); break;
+	case 9:
+		write_sysreg(bvr, dbgbvr9_el1); break;
+	case 10:
+		write_sysreg(bvr, dbgbvr10_el1); break;
+	case 11:
+		write_sysreg(bvr, dbgbvr11_el1); break;
+	case 12:
+		write_sysreg(bvr, dbgbvr12_el1); break;
+	case 13:
+		write_sysreg(bvr, dbgbvr13_el1); break;
+	case 14:
+		write_sysreg(bvr, dbgbvr14_el1); break;
+	case 15:
+		write_sysreg(bvr, dbgbvr15_el1); break;
+	default:
+		report_abort("invalid bvr");
+	}
+}
+
+static void reset_debug_state(void)
+{
+	int i, num_bp = get_num_hw_bp();
+
+	asm volatile("msr daifset, #8");
+
+	write_sysreg(0, osdlr_el1);
+	write_sysreg(0, oslar_el1);
+	isb();
+
+	write_sysreg(0, mdscr_el1);
+	for (i = 0; i < num_bp; i++) {
+		write_dbgbvr(i, 0);
+		write_dbgbcr(i, 0);
+	}
+	isb();
+}
+
+static void do_migrate(void)
+{
+	puts("Now migrate the VM, then press a key to continue...\n");
+	(void)getchar();
+	report_info("Migration complete");
+}
+
+static void test_hw_bp(bool migrate)
+{
+	extern unsigned char hw_bp0;
+	uint32_t bcr;
+	uint32_t mdscr;
+	uint64_t addr;
+	int num_bp = get_num_hw_bp();
+	int i;
+
+	install_exception_handler(EL1H_SYNC, ESR_EC_HW_BP_CURRENT, hw_bp_handler);
+
+	reset_debug_state();
+
+	bcr = DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1 | DBGBCR_E;
+	for (i = 0, addr = (uint64_t)&hw_bp0; i < num_bp; i++, addr += 4) {
+		write_dbgbcr(i, bcr);
+		write_dbgbvr(i, addr);
+	}
+	isb();
+
+	asm volatile("msr daifclr, #8");
+
+	mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_MDE;
+	write_sysreg(mdscr, mdscr_el1);
+	isb();
+
+	if (migrate) {
+		do_migrate();
+		report(num_bp == get_num_hw_bp(), "brps match after migrate");
+	}
+
+	hw_bp_idx = 0;
+
+	/* Trap on up to 16 debug exception unmask instructions. */
+	asm volatile("hw_bp0:\n"
+	     "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n"
+	     "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n"
+	     "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n"
+	     "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n");
+
+	for (i = 0, addr = (uint64_t)&hw_bp0; i < num_bp; i++, addr += 4)
+		report(hw_bp_addr[i] == addr, "hw breakpoint: %d", i);
+}
+
+int main(int argc, char **argv)
+{
+	if (argc < 2)
+		report_abort("no test specified");
+
+	if (strcmp(argv[1], "bp") == 0) {
+		report_prefix_push(argv[1]);
+		test_hw_bp(false);
+		report_prefix_pop();
+	} else if (strcmp(argv[1], "bp-migration") == 0) {
+		report_prefix_push(argv[1]);
+		test_hw_bp(true);
+		report_prefix_pop();
+	} else {
+		report_abort("Unknown subtest '%s'", argv[1]);
+	}
+
+	return report_summary();
+}
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
index 945c2d0..896ff87 100644
--- a/arm/unittests.cfg
+++ b/arm/unittests.cfg
@@ -241,3 +241,16 @@ arch = arm64
 file = cache.flat
 arch = arm64
 groups = cache
+
+# Debug tests
+[debug-bp]
+file = debug.flat
+arch = arm64
+extra_params = -append 'bp'
+groups = debug
+
+[debug-bp-migration]
+file = debug.flat
+arch = arm64
+extra_params = -append 'bp-migration'
+groups = debug migration
-- 
2.34.1.173.g76aa8bc2d0-goog


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [kvm-unit-tests PATCH 2/3] arm64: debug: add a migration test for watchpoint state
  2021-12-10 16:58 [kvm-unit-tests PATCH 0/3] arm64: debug: add migration tests for debug state Ricardo Koller
  2021-12-10 16:58 ` [kvm-unit-tests PATCH 1/3] arm64: debug: add a migration test for breakpoint state Ricardo Koller
@ 2021-12-10 16:58 ` Ricardo Koller
  2021-12-10 16:58 ` [kvm-unit-tests PATCH 3/3] arm64: debug: add a migration test for single-step state Ricardo Koller
  2021-12-14 13:34 ` [kvm-unit-tests PATCH 0/3] arm64: debug: add migration tests for debug state Andrew Jones
  3 siblings, 0 replies; 5+ messages in thread
From: Ricardo Koller @ 2021-12-10 16:58 UTC (permalink / raw)
  To: kvm, kvmarm
  Cc: drjones, Paolo Bonzini, maz, oupton, yuzenghui, jingzhangos,
	pshier, rananta, reijiw, Ricardo Koller

Test the migration of watchpoint state. Program as many watchpoints as
possible, migrate, and check that we get the corresponding exceptions.

Signed-off-by: Ricardo Koller <ricarkol@google.com>
---
 arm/debug.c       | 164 ++++++++++++++++++++++++++++++++++++++++++++++
 arm/unittests.cfg |  12 ++++
 2 files changed, 176 insertions(+)

diff --git a/arm/debug.c b/arm/debug.c
index fedf4ab..b2240d7 100644
--- a/arm/debug.c
+++ b/arm/debug.c
@@ -9,20 +9,31 @@
 
 #define MDSCR_KDE		(1 << 13)
 #define MDSCR_MDE		(1 << 15)
+#define MDSCR_SS		(1 << 0)
 
 #define DBGBCR_LEN8		(0xff << 5)
 #define DBGBCR_EXEC		(0x0 << 3)
 #define DBGBCR_EL1		(0x1 << 1)
 #define DBGBCR_E		(0x1 << 0)
 
+#define DBGWCR_LEN8		(0xff << 5)
+#define DBGWCR_RD		(0x1 << 3)
+#define DBGWCR_WR		(0x2 << 3)
+#define DBGWCR_EL1		(0x1 << 1)
+#define DBGWCR_E		(0x1 << 0)
+
 #define SPSR_D			(1 << 9)
 
 #define ESR_EC_HW_BP_CURRENT    0x31
+#define ESR_EC_WP_CURRENT       0x35
 
 #define ID_AA64DFR0_BRPS_SHIFT	12
 #define ID_AA64DFR0_BRPS_MASK	0xf
+#define ID_AA64DFR0_WRPS_SHIFT	20
+#define ID_AA64DFR0_WRPS_MASK	0xf
 
 static volatile uint64_t hw_bp_idx, hw_bp_addr[16];
+static volatile uint64_t wp_idx, wp_data_addr[16];
 
 static void hw_bp_handler(struct pt_regs *regs, unsigned int esr)
 {
@@ -30,6 +41,12 @@ static void hw_bp_handler(struct pt_regs *regs, unsigned int esr)
 	regs->pstate |= SPSR_D;
 }
 
+static void wp_handler(struct pt_regs *regs, unsigned int esr)
+{
+	wp_data_addr[wp_idx++] = read_sysreg(far_el1);
+	regs->pstate |= SPSR_D;
+}
+
 static int get_num_hw_bp(void)
 {
 	uint64_t reg = read_sysreg(id_aa64dfr0_el1);
@@ -39,6 +56,15 @@ static int get_num_hw_bp(void)
 	return brps + 1;
 }
 
+static int get_num_wp(void)
+{
+	uint64_t reg = read_sysreg(id_aa64dfr0_el1);
+	/* Number of watchpoints, minus 1 */
+	uint8_t wrps = (reg >> ID_AA64DFR0_WRPS_SHIFT) & ID_AA64DFR0_WRPS_MASK;
+
+	return wrps + 1;
+}
+
 static void write_dbgbcr(int n, uint32_t bcr)
 {
 	switch (n) {
@@ -119,9 +145,90 @@ static void write_dbgbvr(int n, uint64_t bvr)
 	}
 }
 
+static void write_dbgwcr(int n, uint32_t wcr)
+{
+	switch (n) {
+	case 0:
+		write_sysreg(wcr, dbgwcr0_el1); break;
+	case 1:
+		write_sysreg(wcr, dbgwcr1_el1); break;
+	case 2:
+		write_sysreg(wcr, dbgwcr2_el1); break;
+	case 3:
+		write_sysreg(wcr, dbgwcr3_el1); break;
+	case 4:
+		write_sysreg(wcr, dbgwcr4_el1); break;
+	case 5:
+		write_sysreg(wcr, dbgwcr5_el1); break;
+	case 6:
+		write_sysreg(wcr, dbgwcr6_el1); break;
+	case 7:
+		write_sysreg(wcr, dbgwcr7_el1); break;
+	case 8:
+		write_sysreg(wcr, dbgwcr8_el1); break;
+	case 9:
+		write_sysreg(wcr, dbgwcr9_el1); break;
+	case 10:
+		write_sysreg(wcr, dbgwcr10_el1); break;
+	case 11:
+		write_sysreg(wcr, dbgwcr11_el1); break;
+	case 12:
+		write_sysreg(wcr, dbgwcr12_el1); break;
+	case 13:
+		write_sysreg(wcr, dbgwcr13_el1); break;
+	case 14:
+		write_sysreg(wcr, dbgwcr14_el1); break;
+	case 15:
+		write_sysreg(wcr, dbgwcr15_el1); break;
+	default:
+		report_abort("Invalid wcr");
+	}
+}
+
+static void write_dbgwvr(int n, uint64_t wvr)
+{
+	switch (n) {
+	case 0:
+		write_sysreg(wvr, dbgwvr0_el1); break;
+	case 1:
+		write_sysreg(wvr, dbgwvr1_el1); break;
+	case 2:
+		write_sysreg(wvr, dbgwvr2_el1); break;
+	case 3:
+		write_sysreg(wvr, dbgwvr3_el1); break;
+	case 4:
+		write_sysreg(wvr, dbgwvr4_el1); break;
+	case 5:
+		write_sysreg(wvr, dbgwvr5_el1); break;
+	case 6:
+		write_sysreg(wvr, dbgwvr6_el1); break;
+	case 7:
+		write_sysreg(wvr, dbgwvr7_el1); break;
+	case 8:
+		write_sysreg(wvr, dbgwvr8_el1); break;
+	case 9:
+		write_sysreg(wvr, dbgwvr9_el1); break;
+	case 10:
+		write_sysreg(wvr, dbgwvr10_el1); break;
+	case 11:
+		write_sysreg(wvr, dbgwvr11_el1); break;
+	case 12:
+		write_sysreg(wvr, dbgwvr12_el1); break;
+	case 13:
+		write_sysreg(wvr, dbgwvr13_el1); break;
+	case 14:
+		write_sysreg(wvr, dbgwvr14_el1); break;
+	case 15:
+		write_sysreg(wvr, dbgwvr15_el1); break;
+	default:
+		report_abort("invalid wvr");
+	}
+}
+
 static void reset_debug_state(void)
 {
 	int i, num_bp = get_num_hw_bp();
+	int num_wp = get_num_wp();
 
 	asm volatile("msr daifset, #8");
 
@@ -134,6 +241,10 @@ static void reset_debug_state(void)
 		write_dbgbvr(i, 0);
 		write_dbgbcr(i, 0);
 	}
+	for (i = 0; i < num_wp; i++) {
+		write_dbgwvr(i, 0);
+		write_dbgwcr(i, 0);
+	}
 	isb();
 }
 
@@ -188,6 +299,51 @@ static void test_hw_bp(bool migrate)
 		report(hw_bp_addr[i] == addr, "hw breakpoint: %d", i);
 }
 
+static volatile char write_data[16];
+
+static void test_wp(bool migrate)
+{
+	uint32_t wcr;
+	uint32_t mdscr;
+	int num_wp = get_num_wp();
+	int i;
+
+	install_exception_handler(EL1H_SYNC, ESR_EC_WP_CURRENT, wp_handler);
+
+	reset_debug_state();
+
+	wcr = DBGWCR_LEN8 | DBGWCR_RD | DBGWCR_WR | DBGWCR_EL1 | DBGWCR_E;
+	for (i = 0; i < num_wp; i++) {
+		write_dbgwcr(i, wcr);
+		write_dbgwvr(i, (uint64_t)&write_data[i]);
+	}
+	isb();
+
+	asm volatile("msr daifclr, #8");
+
+	mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_MDE;
+	write_sysreg(mdscr, mdscr_el1);
+	isb();
+
+	if (migrate) {
+		do_migrate();
+		report(num_wp == get_num_wp(), "wrps match after migrate");
+	}
+
+	wp_idx = 0;
+
+	for (i = 0; i < num_wp; i++) {
+		write_data[i] = i;
+		asm volatile("msr daifclr, #8");
+	}
+
+	for (i = 0; i < num_wp; i++) {
+		report(wp_data_addr[i] == (uint64_t)&write_data[i],
+			"watchpoint received: %d", i);
+		report(write_data[i] == i, "watchpoint data: %d", i);
+	}
+}
+
 int main(int argc, char **argv)
 {
 	if (argc < 2)
@@ -201,6 +357,14 @@ int main(int argc, char **argv)
 		report_prefix_push(argv[1]);
 		test_hw_bp(true);
 		report_prefix_pop();
+	} else if (strcmp(argv[1], "wp") == 0) {
+		report_prefix_push(argv[1]);
+		test_wp(false);
+		report_prefix_pop();
+	} else if (strcmp(argv[1], "wp-migration") == 0) {
+		report_prefix_push(argv[1]);
+		test_wp(true);
+		report_prefix_pop();
 	} else {
 		report_abort("Unknown subtest '%s'", argv[1]);
 	}
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
index 896ff87..bca2fad 100644
--- a/arm/unittests.cfg
+++ b/arm/unittests.cfg
@@ -254,3 +254,15 @@ file = debug.flat
 arch = arm64
 extra_params = -append 'bp-migration'
 groups = debug migration
+
+[debug-wp]
+file = debug.flat
+arch = arm64
+extra_params = -append 'wp'
+groups = debug
+
+[debug-wp-migration]
+file = debug.flat
+arch = arm64
+extra_params = -append 'wp-migration'
+groups = debug migration
-- 
2.34.1.173.g76aa8bc2d0-goog


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [kvm-unit-tests PATCH 3/3] arm64: debug: add a migration test for single-step state
  2021-12-10 16:58 [kvm-unit-tests PATCH 0/3] arm64: debug: add migration tests for debug state Ricardo Koller
  2021-12-10 16:58 ` [kvm-unit-tests PATCH 1/3] arm64: debug: add a migration test for breakpoint state Ricardo Koller
  2021-12-10 16:58 ` [kvm-unit-tests PATCH 2/3] arm64: debug: add a migration test for watchpoint state Ricardo Koller
@ 2021-12-10 16:58 ` Ricardo Koller
  2021-12-14 13:34 ` [kvm-unit-tests PATCH 0/3] arm64: debug: add migration tests for debug state Andrew Jones
  3 siblings, 0 replies; 5+ messages in thread
From: Ricardo Koller @ 2021-12-10 16:58 UTC (permalink / raw)
  To: kvm, kvmarm
  Cc: drjones, Paolo Bonzini, maz, oupton, yuzenghui, jingzhangos,
	pshier, rananta, reijiw, Ricardo Koller

Test the migration of single-step state. Setup single-stepping, migrate,
and check that we are actually single-stepping.

Signed-off-by: Ricardo Koller <ricarkol@google.com>
---
 arm/debug.c       | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 arm/unittests.cfg | 12 ++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/arm/debug.c b/arm/debug.c
index b2240d7..54f059d 100644
--- a/arm/debug.c
+++ b/arm/debug.c
@@ -23,8 +23,10 @@
 #define DBGWCR_E		(0x1 << 0)
 
 #define SPSR_D			(1 << 9)
+#define SPSR_SS			(1 << 21)
 
 #define ESR_EC_HW_BP_CURRENT    0x31
+#define ESR_EC_SSTEP_CURRENT    0x33
 #define ESR_EC_WP_CURRENT       0x35
 
 #define ID_AA64DFR0_BRPS_SHIFT	12
@@ -34,6 +36,7 @@
 
 static volatile uint64_t hw_bp_idx, hw_bp_addr[16];
 static volatile uint64_t wp_idx, wp_data_addr[16];
+static volatile uint64_t ss_addr[4], ss_idx;
 
 static void hw_bp_handler(struct pt_regs *regs, unsigned int esr)
 {
@@ -47,6 +50,12 @@ static void wp_handler(struct pt_regs *regs, unsigned int esr)
 	regs->pstate |= SPSR_D;
 }
 
+static void ss_handler(struct pt_regs *regs, unsigned int esr)
+{
+	ss_addr[ss_idx++] = regs->pc;
+	regs->pstate |= SPSR_SS;
+}
+
 static int get_num_hw_bp(void)
 {
 	uint64_t reg = read_sysreg(id_aa64dfr0_el1);
@@ -344,6 +353,36 @@ static void test_wp(bool migrate)
 	}
 }
 
+static void test_ss(bool migrate)
+{
+	extern unsigned char ss_start;
+	uint32_t mdscr;
+
+	install_exception_handler(EL1H_SYNC, ESR_EC_SSTEP_CURRENT, ss_handler);
+
+	reset_debug_state();
+
+	ss_idx = 0;
+
+	mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_SS;
+	write_sysreg(mdscr, mdscr_el1);
+	isb();
+
+	if (migrate) {
+		do_migrate();
+	}
+
+	asm volatile("msr daifclr, #8");
+
+	asm volatile("ss_start:\n"
+			"mrs x0, esr_el1\n"
+			"add x0, x0, #1\n"
+			"msr daifset, #8\n"
+			: : : "x0");
+
+	report(ss_addr[0] == (uint64_t)&ss_start, "single step");
+}
+
 int main(int argc, char **argv)
 {
 	if (argc < 2)
@@ -365,6 +404,14 @@ int main(int argc, char **argv)
 		report_prefix_push(argv[1]);
 		test_wp(true);
 		report_prefix_pop();
+	} else if (strcmp(argv[1], "ss") == 0) {
+		report_prefix_push(argv[1]);
+		test_ss(false);
+		report_prefix_pop();
+	} else if (strcmp(argv[1], "ss-migration") == 0) {
+		report_prefix_push(argv[1]);
+		test_ss(true);
+		report_prefix_pop();
 	} else {
 		report_abort("Unknown subtest '%s'", argv[1]);
 	}
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
index bca2fad..c8c51d2 100644
--- a/arm/unittests.cfg
+++ b/arm/unittests.cfg
@@ -266,3 +266,15 @@ file = debug.flat
 arch = arm64
 extra_params = -append 'wp-migration'
 groups = debug migration
+
+[debug-sstep]
+file = debug.flat
+arch = arm64
+extra_params = -append 'ss'
+groups = debug
+
+[debug-sstep-migration]
+file = debug.flat
+arch = arm64
+extra_params = -append 'ss-migration'
+groups = debug migration
-- 
2.34.1.173.g76aa8bc2d0-goog


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [kvm-unit-tests PATCH 0/3] arm64: debug: add migration tests for debug state
  2021-12-10 16:58 [kvm-unit-tests PATCH 0/3] arm64: debug: add migration tests for debug state Ricardo Koller
                   ` (2 preceding siblings ...)
  2021-12-10 16:58 ` [kvm-unit-tests PATCH 3/3] arm64: debug: add a migration test for single-step state Ricardo Koller
@ 2021-12-14 13:34 ` Andrew Jones
  3 siblings, 0 replies; 5+ messages in thread
From: Andrew Jones @ 2021-12-14 13:34 UTC (permalink / raw)
  To: Ricardo Koller
  Cc: kvm, kvmarm, Paolo Bonzini, maz, oupton, yuzenghui, jingzhangos,
	pshier, rananta, reijiw

On Fri, Dec 10, 2021 at 08:58:01AM -0800, Ricardo Koller wrote:
> Add some tests for checking that we can migrate debug state correctly: setup
> some breakpoints/watchpoints/single-stepping, migrate, and then check that we
> get the expected exceptions.
> 
> The 3 patches in this series add tests for breakpoints, watchpoints, and
> single-stepping one patch at a time.  Each patch adds a migration test and a
> sanity test (to test that debugging works with no migration).
> 
> Note that this is limited to 64-bits and a single vcpu. Also note that some of
> the code, like reset_debug_state, is borrowed from kvm selftests.
> 
> Ricardo Koller (3):
>   arm64: debug: add a migration test for breakpoint state
>   arm64: debug: add a migration test for watchpoint state
>   arm64: debug: add a migration test for single-step state
> 
>  arm/Makefile.arm64 |   1 +
>  arm/debug.c        | 420 +++++++++++++++++++++++++++++++++++++++++++++
>  arm/unittests.cfg  |  37 ++++
>  3 files changed, 458 insertions(+)
>  create mode 100644 arm/debug.c
> 
> -- 
> 2.34.1.173.g76aa8bc2d0-goog
>

Applied to https://gitlab.com/rhdrjones/kvm-unit-tests/-/commits/arm/queue

Thanks,
drew 


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-12-14 13:34 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-10 16:58 [kvm-unit-tests PATCH 0/3] arm64: debug: add migration tests for debug state Ricardo Koller
2021-12-10 16:58 ` [kvm-unit-tests PATCH 1/3] arm64: debug: add a migration test for breakpoint state Ricardo Koller
2021-12-10 16:58 ` [kvm-unit-tests PATCH 2/3] arm64: debug: add a migration test for watchpoint state Ricardo Koller
2021-12-10 16:58 ` [kvm-unit-tests PATCH 3/3] arm64: debug: add a migration test for single-step state Ricardo Koller
2021-12-14 13:34 ` [kvm-unit-tests PATCH 0/3] arm64: debug: add migration tests for debug state Andrew Jones

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).