diff options
author | Rusty Russell <rusty.russell@linaro.org> | 2012-08-01 15:39:15 +0930 |
---|---|---|
committer | Rusty Russell <rusty.russell@linaro.org> | 2012-08-01 15:39:15 +0930 |
commit | fb478010ecc5747b06431124046695bd40171227 (patch) | |
tree | a0b9fa7a396829bd8a9d79d95345e06b1fc2ba1c | |
parent | b5c1cc563fdf5962869983e1033fccdf870e4beb (diff) | |
download | linux-kvm-arm-test-code.tar.gz |
tools/kvm/arm: cp15 test.test-code
We catch undef faults, so we can test that we get them where we expect.
-rw-r--r-- | tools/kvm/arm/Makefile | 2 | ||||
-rw-r--r-- | tools/kvm/arm/cp15-guest.c | 83 | ||||
-rw-r--r-- | tools/kvm/arm/cp15-host.c | 8 | ||||
-rw-r--r-- | tools/kvm/arm/guest.h | 4 |
4 files changed, 96 insertions, 1 deletions
diff --git a/tools/kvm/arm/Makefile b/tools/kvm/arm/Makefile index 016b25a5a9df8..175773b7242fa 100644 --- a/tools/kvm/arm/Makefile +++ b/tools/kvm/arm/Makefile @@ -24,7 +24,7 @@ LDFLAGS = -static CFLAGS = -Wall -I../../../include -I../../../arch/arm/include -D__EXPORTED_HEADERS__ -marm -TESTS=mmio vfp +TESTS=mmio vfp cp15 GUESTS=$(TESTS:%=%-guest) HOST_DRIVERS=$(TESTS:%=%-host.o) diff --git a/tools/kvm/arm/cp15-guest.c b/tools/kvm/arm/cp15-guest.c new file mode 100644 index 0000000000000..a1d8149e4f3ef --- /dev/null +++ b/tools/kvm/arm/cp15-guest.c @@ -0,0 +1,83 @@ +#include "guest.h" + +extern u32 mcr_insn, mrc_insn, mcrr_insn, mrrc_insn; + +/* Alter mcr or mrc instruction */ +static void alter_insn32(u32 *insn, + unsigned int opc1, + unsigned int crn, + unsigned int crm, + unsigned int opc2) +{ + /* This actually works in both ARM and Thumb mode. */ + *insn &= 0xFF10FF10; + *insn |= (opc1 << 21) | (crn << 16) | (opc2 << 5) | crm; + /* ICIALLU */ + asm("mcr p15, 0, %0, c7, c5, 0" : : "r" (0)); +} + +/* Alter mcrr or mrrc instruction */ +static void alter_insn64(u32 *insn, + unsigned int opc1, + unsigned int crm) +{ + /* This actually works in both ARM and Thumb mode. */ + *insn &= 0xFFFFFF00; + *insn |= (opc1 << 4) | crm; + /* ICIALLU */ + asm("mcr p15, 0, %0, c7, c5, 0" : : "r" (0)); +} + +static bool cp15_write(unsigned int opc1, + unsigned int crn, + unsigned int crm, + unsigned int opc2, + u32 val) +{ + alter_insn32(&mcr_insn, opc1, crn, crm, opc2); + + skip_undef++; + undef_count = 0; + asm volatile(".globl mcr_insn\n" + "mcr_insn:\n" + " mcr p15, 0, %0, c0, c0, 0" : : "r"(val) : "memory"); + skip_undef--; + + /* This is incremented if we fault. */ + return undef_count; +} + +static bool cp15_read(unsigned int opc1, + unsigned int crn, + unsigned int crm, + unsigned int opc2, + u32 *val) +{ + alter_insn32(&mrc_insn, opc1, crn, crm, opc2); + *val = 0xdeadbeef; + + skip_undef++; + undef_count = 0; + asm volatile(".globl mrc_insn\n" + "mrc_insn:\n" + " mrc p15, 0, %0, c0, c0, 0" : "=r"(val) : : "memory"); + skip_undef--; + + /* This is incremented if we fault. */ + return undef_count; +} + +int test(void) +{ + bool faulted; + + print("Perform an mrc\n"); + faulted = cp15_write(0, 0, 0, 0, 100); + + if (faulted) + print("IT FAULTED\n"); + else + print("IT DID NOT FAULT\n"); + + return 0; +} diff --git a/tools/kvm/arm/cp15-host.c b/tools/kvm/arm/cp15-host.c new file mode 100644 index 0000000000000..f0f21c74c61b3 --- /dev/null +++ b/tools/kvm/arm/cp15-host.c @@ -0,0 +1,8 @@ +#include <stdbool.h> +#include <string.h> +#include <linux/kvm.h> + +#include "guest-driver.h" + +/* We don't have any special mmio addresses for cp15 testing. */ +GUEST_TEST(cp15, NULL); diff --git a/tools/kvm/arm/guest.h b/tools/kvm/arm/guest.h index 1d9d8bd2eca4d..e8574404ebe31 100644 --- a/tools/kvm/arm/guest.h +++ b/tools/kvm/arm/guest.h @@ -1,5 +1,7 @@ #ifndef GUEST_H #define GUEST_H +#include <stdint.h> +#include <stdbool.h> void ok(void); void fail(void); @@ -26,6 +28,8 @@ static inline void print(const char *p) ok(); \ } while(0) +typedef uint32_t u32; + /* Each guest needs to write this. */ int test(void); #endif /* GUEST_H */ |