aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRusty Russell <rusty.russell@linaro.org>2012-09-11 15:40:21 +0930
committerRusty Russell <rusty.russell@linaro.org>2012-09-11 15:40:21 +0930
commitbee93045fb94a93ef0708cb9e293c5eeb1203e6e (patch)
tree193ba5c5f942c8864614bf1c90c09aa383e9a0ea
parent6db30e0609fef90a083e2ef05beee0eb6072333a (diff)
downloadlinux-kvm-arm-testing-wip.tar.gz
patch kvmtest-test-vfp.patchtesting-wip
-rw-r--r--tools/testing/selftests/kvm/arm/vfp-guest.c15
-rw-r--r--tools/testing/selftests/kvm/arm/vfp-host.c101
-rw-r--r--tools/testing/selftests/kvm/arm/vfp_test.h5
3 files changed, 86 insertions, 35 deletions
diff --git a/tools/testing/selftests/kvm/arm/vfp-guest.c b/tools/testing/selftests/kvm/arm/vfp-guest.c
index b5bffe3f79f0d..075d4f7142b37 100644
--- a/tools/testing/selftests/kvm/arm/vfp-guest.c
+++ b/tools/testing/selftests/kvm/arm/vfp-guest.c
@@ -64,5 +64,20 @@ int test(void)
asm volatile("ldr %0, [%1]" : "=r"(val) : "r"(VFP_USE_REG + 16));
assert(d16 == 2.0);
+ /* Now check host ioctl sees register correctly. */
+ d0 = 2.0;
+ asm volatile("ldr %0, [%1]" : "=r"(val) : "r"(VFP_CHECK_REG));
+
+ d0 = 2.0;
+ asm volatile("ldr %0, [%1]" : "=r"(val) : "r"(VFP_SET_REG));
+ assert(d0 == 3.0);
+
+ d16 = 2.0;
+ asm volatile("ldr %0, [%1]" : "=r"(val) : "r"(VFP_CHECK_REG+16));
+
+ d16 = 2.0;
+ asm volatile("ldr %0, [%1]" : "=r"(val) : "r"(VFP_SET_REG+16));
+ assert(d16 == 3.0);
+
return 0;
}
diff --git a/tools/testing/selftests/kvm/arm/vfp-host.c b/tools/testing/selftests/kvm/arm/vfp-host.c
index bf8f03ba097e5..7761f4d1cd753 100644
--- a/tools/testing/selftests/kvm/arm/vfp-host.c
+++ b/tools/testing/selftests/kvm/arm/vfp-host.c
@@ -18,6 +18,9 @@
#include <stdbool.h>
#include <string.h>
#include <linux/kvm.h>
+#include <sys/ioctl.h>
+#include <err.h>
+#include <stdlib.h>
#include "guest-driver.h"
#include "vfp_test.h"
@@ -27,6 +30,8 @@ static bool vfp_test(struct kvm_run *kvm_run, int vcpu_fd)
{
unsigned long phys_addr;
bool is_write;
+ struct kvm_one_reg r;
+ double d;
phys_addr = (unsigned long)kvm_run->mmio.phys_addr;
is_write = kvm_run->mmio.is_write;
@@ -37,104 +42,130 @@ static bool vfp_test(struct kvm_run *kvm_run, int vcpu_fd)
switch (phys_addr) {
case VFP_USE_REG:
asm volatile("fconstd d0, #112");
- break;
+ return true;
case VFP_USE_REG+1:
asm volatile("fconstd d1, #112");
- break;
+ return true;
case VFP_USE_REG+2:
asm volatile("fconstd d2, #112");
- break;
+ return true;
case VFP_USE_REG+3:
asm volatile("fconstd d3, #112");
- break;
+ return true;
case VFP_USE_REG+4:
asm volatile("fconstd d4, #112");
- break;
+ return true;
case VFP_USE_REG+5:
asm volatile("fconstd d5, #112");
- break;
+ return true;
case VFP_USE_REG+6:
asm volatile("fconstd d6, #112");
- break;
+ return true;
case VFP_USE_REG+7:
asm volatile("fconstd d7, #112");
- break;
+ return true;
case VFP_USE_REG+8:
asm volatile("fconstd d8, #112");
- break;
+ return true;
case VFP_USE_REG+9:
asm volatile("fconstd d9, #112");
- break;
+ return true;
case VFP_USE_REG+10:
asm volatile("fconstd d10, #112");
- break;
+ return true;
case VFP_USE_REG+11:
asm volatile("fconstd d11, #112");
- break;
+ return true;
case VFP_USE_REG+12:
asm volatile("fconstd d12, #112");
- break;
+ return true;
case VFP_USE_REG+13:
asm volatile("fconstd d13, #112");
- break;
+ return true;
case VFP_USE_REG+14:
asm volatile("fconstd d14, #112");
- break;
+ return true;
case VFP_USE_REG+15:
asm volatile("fconstd d15, #112");
- break;
+ return true;
case VFP_USE_REG+16:
asm volatile("fconstd d16, #112");
- break;
+ return true;
case VFP_USE_REG+17:
asm volatile("fconstd d17, #112");
- break;
+ return true;
case VFP_USE_REG+18:
asm volatile("fconstd d18, #112");
- break;
+ return true;
case VFP_USE_REG+19:
asm volatile("fconstd d19, #112");
- break;
+ return true;
case VFP_USE_REG+20:
asm volatile("fconstd d20, #112");
- break;
+ return true;
case VFP_USE_REG+21:
asm volatile("fconstd d21, #112");
- break;
+ return true;
case VFP_USE_REG+22:
asm volatile("fconstd d22, #112");
- break;
+ return true;
case VFP_USE_REG+23:
asm volatile("fconstd d23, #112");
- break;
+ return true;
case VFP_USE_REG+24:
asm volatile("fconstd d24, #112");
- break;
+ return true;
case VFP_USE_REG+25:
asm volatile("fconstd d25, #112");
- break;
+ return true;
case VFP_USE_REG+26:
asm volatile("fconstd d26, #112");
- break;
+ return true;
case VFP_USE_REG+27:
asm volatile("fconstd d27, #112");
- break;
+ return true;
case VFP_USE_REG+28:
asm volatile("fconstd d28, #112");
- break;
+ return true;
case VFP_USE_REG+29:
asm volatile("fconstd d29, #112");
- break;
+ return true;
case VFP_USE_REG+30:
asm volatile("fconstd d30, #112");
- break;
+ return true;
case VFP_USE_REG+31:
asm volatile("fconstd d31, #112");
- break;
- default:
- return false;
+ return true;
+ }
+
+ /* Check reg is a particular value. */
+ if (phys_addr >= VFP_CHECK_REG && phys_addr < VFP_CHECK_REG + 32) {
+ r.id = KVM_REG_ARM | KVM_REG_SIZE_U64
+ | KVM_REG_ARM_VFP
+ | (phys_addr - VFP_CHECK_REG);
+ r.addr = (long)&d;
+ if (ioctl(vcpu_fd, KVM_GET_ONE_REG, &r) != 0)
+ err(EXIT_FAILURE, "KVM_GET_ONE_REG(VFP %li) failed",
+ phys_addr - VFP_CHECK_REG);
+ if (d != 2.0)
+ errx(EXIT_FAILURE, "KVM_GET_ONE_REG(VFP %li) == %.lf",
+ phys_addr - VFP_CHECK_REG, d);
+ return true;
}
- return true;
+
+ if (phys_addr >= VFP_SET_REG && phys_addr < VFP_SET_REG + 32) {
+ r.id = KVM_REG_ARM | KVM_REG_SIZE_U64
+ | KVM_REG_ARM_VFP
+ | (phys_addr - VFP_SET_REG);
+ r.addr = (long)&d;
+ d = 3.0;
+ if (ioctl(vcpu_fd, KVM_SET_ONE_REG, &r) != 0)
+ err(EXIT_FAILURE, "KVM_SET_ONE_REG(VFP %li) failed",
+ phys_addr - VFP_CHECK_REG);
+ return true;
+ }
+
+ return false;
}
GUEST_TEST(vfp, vfp_test);
diff --git a/tools/testing/selftests/kvm/arm/vfp_test.h b/tools/testing/selftests/kvm/arm/vfp_test.h
index eedc953b230b4..8a56a80f90d32 100644
--- a/tools/testing/selftests/kvm/arm/vfp_test.h
+++ b/tools/testing/selftests/kvm/arm/vfp_test.h
@@ -1,6 +1,11 @@
#ifndef VFP_TEST_H
#define VFP_TEST_H
+/* This uses reg in host, to check for interference. */
#define VFP_USE_REG (0xc0000000) /* + offset of register number */
+/* This uses ioctl to check register is 2.0. */
+#define VFP_CHECK_REG (0xc0000020) /* + offset of register number */
+/* This uses ioctl to set register to 3.0. */
+#define VFP_SET_REG (0xc0000040) /* + offset of register number */
#endif /* VFP_TEST_H */