From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alexander Spyridakis Subject: [kvm-unit-tests PATCH 1/2] arm/arm64: Add self-modifying code test Date: Wed, 2 Sep 2015 11:25:25 +0200 Message-ID: <1441185926-61587-2-git-send-email-a.spyridakis@virtualopensystems.com> References: <1441185926-61587-1-git-send-email-a.spyridakis@virtualopensystems.com> Cc: kvm@vger.kernel.org, qemu-devel@nongnu.org, drjones@redhat.com, alex.bennee@linaro.org, fred.konrad@greensocs.com, mark.burton@greensocs.com, a.rigo@virtualopensystems.com, claudio.fontana@huawei.com, Jani.Kokkonen@huawei.com, Alexander Spyridakis To: mttcg@listserver.greensocs.com Return-path: Received: from mail-wi0-f174.google.com ([209.85.212.174]:32955 "EHLO mail-wi0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752082AbbIBJZp (ORCPT ); Wed, 2 Sep 2015 05:25:45 -0400 Received: by wicmc4 with SMTP id mc4so59217601wic.0 for ; Wed, 02 Sep 2015 02:25:44 -0700 (PDT) In-Reply-To: <1441185926-61587-1-git-send-email-a.spyridakis@virtualopensystems.com> Sender: kvm-owner@vger.kernel.org List-ID: 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 --- 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 + * + * This work is licensed under the terms of the GNU LGPL, version 2. + */ + +#include +#include +#include + +#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 From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35448) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZX4If-0006U8-Cw for qemu-devel@nongnu.org; Wed, 02 Sep 2015 05:25:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZX4Ib-0003b1-5P for qemu-devel@nongnu.org; Wed, 02 Sep 2015 05:25:49 -0400 Received: from mail-wi0-f180.google.com ([209.85.212.180]:34739) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZX4Ia-0003ar-NE for qemu-devel@nongnu.org; Wed, 02 Sep 2015 05:25:45 -0400 Received: by wicfx3 with SMTP id fx3so10730244wic.1 for ; Wed, 02 Sep 2015 02:25:44 -0700 (PDT) From: Alexander Spyridakis Date: Wed, 2 Sep 2015 11:25:25 +0200 Message-Id: <1441185926-61587-2-git-send-email-a.spyridakis@virtualopensystems.com> In-Reply-To: <1441185926-61587-1-git-send-email-a.spyridakis@virtualopensystems.com> References: <1441185926-61587-1-git-send-email-a.spyridakis@virtualopensystems.com> Subject: [Qemu-devel] [kvm-unit-tests PATCH 1/2] arm/arm64: Add self-modifying code test List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: mttcg@listserver.greensocs.com Cc: drjones@redhat.com, kvm@vger.kernel.org, claudio.fontana@huawei.com, mark.burton@greensocs.com, qemu-devel@nongnu.org, a.rigo@virtualopensystems.com, Alexander Spyridakis , Jani.Kokkonen@huawei.com, alex.bennee@linaro.org, fred.konrad@greensocs.com 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 --- 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 + * + * This work is licensed under the terms of the GNU LGPL, version 2. + */ + +#include +#include +#include + +#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