aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRusty Russell <rusty.russell@linaro.org>2012-08-01 15:39:15 +0930
committerRusty Russell <rusty.russell@linaro.org>2012-08-01 15:39:15 +0930
commitfb478010ecc5747b06431124046695bd40171227 (patch)
treea0b9fa7a396829bd8a9d79d95345e06b1fc2ba1c
parentb5c1cc563fdf5962869983e1033fccdf870e4beb (diff)
downloadlinux-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/Makefile2
-rw-r--r--tools/kvm/arm/cp15-guest.c83
-rw-r--r--tools/kvm/arm/cp15-host.c8
-rw-r--r--tools/kvm/arm/guest.h4
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 */