aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2014-05-08 10:32:48 +0100
committerWill Deacon <will.deacon@arm.com>2015-06-01 16:39:55 +0100
commitfc9d8ec3e459b744c012b9c82924aa397099ab19 (patch)
treef5283c3acccdf6b84779e560605eda8ba2a0e615
parent8ed60bbe615309b2220b4c36db7a50e3f9a9d4b0 (diff)
downloadkvmtool-fc9d8ec3e459b744c012b9c82924aa397099ab19.tar.gz
kvmtool: virtio: enable arm/arm64 support for bi-endianness
Implement the kvm_cpu__get_endianness call for both AArch32 and AArch64, and advertise the bi-endianness support. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r--arm/aarch32/kvm-cpu.c14
-rw-r--r--arm/aarch64/include/kvm/kvm-cpu-arch.h2
-rw-r--r--arm/aarch64/kvm-cpu.c43
-rw-r--r--arm/include/arm-common/kvm-arch.h2
4 files changed, 61 insertions, 0 deletions
diff --git a/arm/aarch32/kvm-cpu.c b/arm/aarch32/kvm-cpu.c
index bd71037e..464b473d 100644
--- a/arm/aarch32/kvm-cpu.c
+++ b/arm/aarch32/kvm-cpu.c
@@ -1,5 +1,6 @@
#include "kvm/kvm-cpu.h"
#include "kvm/kvm.h"
+#include "kvm/virtio.h"
#include <asm/ptrace.h>
@@ -76,6 +77,19 @@ void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu)
die_perror("KVM_SET_ONE_REG failed (pc)");
}
+int kvm_cpu__get_endianness(struct kvm_cpu *vcpu)
+{
+ struct kvm_one_reg reg;
+ u32 data;
+
+ reg.id = ARM_CORE_REG(usr_regs.ARM_cpsr);
+ reg.addr = (u64)(unsigned long)&data;
+ if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+ die("KVM_GET_ONE_REG failed (cpsr)");
+
+ return (data & PSR_E_BIT) ? VIRTIO_ENDIAN_BE : VIRTIO_ENDIAN_LE;
+}
+
void kvm_cpu__show_code(struct kvm_cpu *vcpu)
{
struct kvm_one_reg reg;
diff --git a/arm/aarch64/include/kvm/kvm-cpu-arch.h b/arm/aarch64/include/kvm/kvm-cpu-arch.h
index 7d70c3ba..2ffa7ad2 100644
--- a/arm/aarch64/include/kvm/kvm-cpu-arch.h
+++ b/arm/aarch64/include/kvm/kvm-cpu-arch.h
@@ -13,5 +13,7 @@
#define ARM_MPIDR_HWID_BITMASK 0xFF00FFFFFFUL
#define ARM_CPU_ID 3, 0, 0, 0
#define ARM_CPU_ID_MPIDR 5
+#define ARM_CPU_CTRL 3, 0, 1, 0
+#define ARM_CPU_CTRL_SCTLR_EL1 0
#endif /* KVM__KVM_CPU_ARCH_H */
diff --git a/arm/aarch64/kvm-cpu.c b/arm/aarch64/kvm-cpu.c
index 059e42c1..71a2a3a7 100644
--- a/arm/aarch64/kvm-cpu.c
+++ b/arm/aarch64/kvm-cpu.c
@@ -1,12 +1,17 @@
#include "kvm/kvm-cpu.h"
#include "kvm/kvm.h"
+#include "kvm/virtio.h"
#include <asm/ptrace.h>
#define COMPAT_PSR_F_BIT 0x00000040
#define COMPAT_PSR_I_BIT 0x00000080
+#define COMPAT_PSR_E_BIT 0x00000200
#define COMPAT_PSR_MODE_SVC 0x00000013
+#define SCTLR_EL1_E0E_MASK (1 << 24)
+#define SCTLR_EL1_EE_MASK (1 << 25)
+
#define ARM64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
@@ -133,6 +138,44 @@ void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu)
return reset_vcpu_aarch64(vcpu);
}
+int kvm_cpu__get_endianness(struct kvm_cpu *vcpu)
+{
+ struct kvm_one_reg reg;
+ u64 psr;
+ u64 sctlr;
+
+ /*
+ * Quoting the definition given by Peter Maydell:
+ *
+ * "Endianness of the CPU which does the virtio reset at the
+ * point when it does that reset"
+ *
+ * We first check for an AArch32 guest: its endianness can
+ * change when using SETEND, which affects the CPSR.E bit.
+ *
+ * If we're AArch64, use SCTLR_EL1.E0E if access comes from
+ * EL0, and SCTLR_EL1.EE if access comes from EL1.
+ */
+ reg.id = ARM64_CORE_REG(regs.pstate);
+ reg.addr = (u64)&psr;
+ if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+ die("KVM_GET_ONE_REG failed (spsr[EL1])");
+
+ if (psr & PSR_MODE32_BIT)
+ return (psr & COMPAT_PSR_E_BIT) ? VIRTIO_ENDIAN_BE : VIRTIO_ENDIAN_LE;
+
+ reg.id = ARM64_SYS_REG(ARM_CPU_CTRL, ARM_CPU_CTRL_SCTLR_EL1);
+ reg.addr = (u64)&sctlr;
+ if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+ die("KVM_GET_ONE_REG failed (SCTLR_EL1)");
+
+ if ((psr & PSR_MODE_MASK) == PSR_MODE_EL0t)
+ sctlr &= SCTLR_EL1_E0E_MASK;
+ else
+ sctlr &= SCTLR_EL1_EE_MASK;
+ return sctlr ? VIRTIO_ENDIAN_BE : VIRTIO_ENDIAN_LE;
+}
+
void kvm_cpu__show_code(struct kvm_cpu *vcpu)
{
struct kvm_one_reg reg;
diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
index b6c4bf8d..5d2fab2f 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -35,6 +35,8 @@
#define VIRTIO_DEFAULT_TRANS(kvm) \
((kvm)->cfg.arch.virtio_trans_pci ? VIRTIO_PCI : VIRTIO_MMIO)
+#define VIRTIO_RING_ENDIAN (VIRTIO_ENDIAN_LE | VIRTIO_ENDIAN_BE)
+
static inline bool arm_addr_in_ioport_region(u64 phys_addr)
{
u64 limit = KVM_IOPORT_AREA + ARM_IOPORT_SIZE;