Commit fc9d8ec3 authored by Marc Zyngier's avatar Marc Zyngier Committed by Will Deacon
Browse files

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: default avatarMarc Zyngier <marc.zyngier@arm.com>
Signed-off-by: default avatarPekka Enberg <penberg@kernel.org>
parent 8ed60bbe
#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;
......
......@@ -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 */
#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;
......
......@@ -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;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment