summaryrefslogtreecommitdiff
path: root/arch/powerpc/include/asm/kvm_book3s.h
diff options
context:
space:
mode:
authorCédric Le Goater <clg@fr.ibm.com>2014-01-09 14:51:16 +0400
committerAlexander Graf <agraf@suse.de>2014-01-27 19:00:39 +0400
commit736017752d2f6ed0d64f5e15cf48e79779b11c85 (patch)
treef8f11f7b4daf14e76e8e3d716c85f5a56a949476 /arch/powerpc/include/asm/kvm_book3s.h
parent7a8ff56be68239bd36a2b639cb40bfbcfc58dad3 (diff)
downloadlinux-736017752d2f6ed0d64f5e15cf48e79779b11c85.tar.xz
KVM: PPC: Book3S: MMIO emulation support for little endian guests
MMIO emulation reads the last instruction executed by the guest and then emulates. If the guest is running in Little Endian order, or more generally in a different endian order of the host, the instruction needs to be byte-swapped before being emulated. This patch adds a helper routine which tests the endian order of the host and the guest in order to decide whether a byteswap is needed or not. It is then used to byteswap the last instruction of the guest in the endian order of the host before MMIO emulation is performed. Finally, kvmppc_handle_load() of kvmppc_handle_store() are modified to reverse the endianness of the MMIO if required. Signed-off-by: Cédric Le Goater <clg@fr.ibm.com> [agraf: add booke handling] Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/include/asm/kvm_book3s.h')
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h8
1 files changed, 7 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index f8b23201c105..1e9c26f45d18 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -264,6 +264,11 @@ static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu)
return vcpu->arch.pc;
}
+static inline bool kvmppc_need_byteswap(struct kvm_vcpu *vcpu)
+{
+ return (vcpu->arch.shared->msr & MSR_LE) != (MSR_KERNEL & MSR_LE);
+}
+
static inline u32 kvmppc_get_last_inst_internal(struct kvm_vcpu *vcpu, ulong pc)
{
/* Load the instruction manually if it failed to do so in the
@@ -271,7 +276,8 @@ static inline u32 kvmppc_get_last_inst_internal(struct kvm_vcpu *vcpu, ulong pc)
if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED)
kvmppc_ld(vcpu, &pc, sizeof(u32), &vcpu->arch.last_inst, false);
- return vcpu->arch.last_inst;
+ return kvmppc_need_byteswap(vcpu) ? swab32(vcpu->arch.last_inst) :
+ vcpu->arch.last_inst;
}
static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu)