qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [kvm-unit-tests PATCH 1/2] arm/arm64: Add self-modifying co


From: Alexander Spyridakis
Subject: [Qemu-devel] [kvm-unit-tests PATCH 1/2] arm/arm64: Add self-modifying code test
Date: Wed, 2 Sep 2015 11:25:25 +0200

Basic torture test that continuously modifies a single instruction
opcode and checks if all modifications were done and run as expected.

Signed-off-by: Alexander Spyridakis <address@hidden>
---
 arm/self-modifying-test.c    | 109 +++++++++++++++++++++++++++++++++++++++++++
 config/config-arm-common.mak |   2 +
 2 files changed, 111 insertions(+)
 create mode 100644 arm/self-modifying-test.c

diff --git a/arm/self-modifying-test.c b/arm/self-modifying-test.c
new file mode 100644
index 0000000..cab47a0
--- /dev/null
+++ b/arm/self-modifying-test.c
@@ -0,0 +1,109 @@
+/*
+ * Basic self-modifying code test case
+ *
+ * Copyright (C) 2015 Virtual Open Systems SAS
+ * Author: Alexander Spyridakis <address@hidden>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+
+#include <asm/smp.h>
+#include <asm/mmu.h>
+#include <asm/spinlock.h>
+
+#define LOOP_SIZE 100000
+
+int result;
+static cpumask_t smp_test_complete;
+static struct spinlock lock;
+
+void self_modifying_test(void)
+{
+       extern void *smc;
+       static int toggle;
+       int i, cpu = smp_processor_id(), *ptr = (int *)&smc;
+
+       printf("CPU%d starting test\n", cpu);
+
+       for (i = 0; i < LOOP_SIZE; i++) {
+               /* Don't run concurrently with other CPUs*/
+               spin_lock(&lock);
+
+               /* A simple snippet that increments a memory value which
+                  will be modified immediately after. Before running,
+                  invalidate the instruction and data cache for that
+                  specific virtual address */
+#ifdef __arm__
+               asm("mcr        p15, 0, %0, c7, c6, 1\n" /* DCIMVAC */
+                       "mcr    p15, 0, %0, c7, c5, 1\n" /* ICIMVAU */
+#else
+               asm("dc ivac, %0\n"
+                       "ic     ivau, %0\n"
+#endif
+                       "dsb    ish\n"
+                       "isb\n"
+                       "smc:\n"
+                       "add    %1, %1, #1\n"
+                       "str    %1, [%2]\n"
+                       :: "r" (ptr), "r" (result), "r" (&result));
+
+               /* Overwrite the previous labelled opcode,
+                  toggle between incrementing by one or two */
+               toggle ^= 1;
+               if (toggle)
+#ifdef __arm__
+                       *ptr += 1;
+               else
+                       *ptr -= 1;
+#else
+               {
+                       *ptr &= ~(1 << 10);
+                       *ptr |=  (1 << 11);
+               } else {
+                       *ptr |=  (1 << 10);
+                       *ptr &= ~(1 << 11);
+               }
+#endif
+
+               spin_unlock(&lock);
+       }
+
+       cpumask_set_cpu(cpu, &smp_test_complete);
+       if (cpu != 0)
+               halt();
+}
+
+int main(int argc, char **argv)
+{
+       int cpu, calc;
+       (void)argc, (void)argv;
+
+       /* Set memory as writeable, on ARMv7 we need to re-enable the MMU */
+#ifdef __arm__
+       mmu_disable();
+       flush_tlb_all();
+       mmu_set_range_ptes(mmu_idmap, PHYS_OFFSET, PHYS_OFFSET, PHYS_END,
+                       __pgprot(PTE_WBWA));
+       mmu_enable(mmu_idmap);
+#else
+       mmu_set_range_ptes(mmu_idmap, PHYS_OFFSET, PHYS_OFFSET, PHYS_END,
+                       __pgprot(PTE_WBWA));
+       flush_tlb_all();
+#endif
+
+       for_each_present_cpu(cpu) {
+               if (cpu == 0)
+                       continue;
+               smp_boot_secondary(cpu, self_modifying_test);
+       }
+
+       self_modifying_test();
+
+       while (!cpumask_full(&smp_test_complete))
+               cpu_relax();
+
+       calc = LOOP_SIZE * nr_cpus + (LOOP_SIZE * nr_cpus / 2);
+       report("Result: %d - Expected: %d\n", result == calc, result, calc);
+
+       return report_summary();
+}
diff --git a/config/config-arm-common.mak b/config/config-arm-common.mak
index 698555d..74a73e4 100644
--- a/config/config-arm-common.mak
+++ b/config/config-arm-common.mak
@@ -10,6 +10,7 @@ ifeq ($(LOADADDR),)
 endif
 
 tests-common = \
+       $(TEST_DIR)/self-modifying-test.flat \
        $(TEST_DIR)/selftest.flat \
        $(TEST_DIR)/spinlock-test.flat
 
@@ -70,3 +71,4 @@ test_cases: $(generated_files) $(tests-common) $(tests)
 
 $(TEST_DIR)/selftest.elf: $(cstart.o) $(TEST_DIR)/selftest.o
 $(TEST_DIR)/spinlock-test.elf: $(cstart.o) $(TEST_DIR)/spinlock-test.o
+$(TEST_DIR)/self-modifying-test.elf: $(cstart.o) 
$(TEST_DIR)/self-modifying-test.o
-- 
2.1.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]