aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/powerpc.c
diff options
context:
space:
mode:
authorCédric Le Goater <clg@fr.ibm.com>2014-01-09 05:51:16 -0500
committerAlexander Graf <agraf@suse.de>2014-01-27 10:00:39 -0500
commit736017752d2f6ed0d64f5e15cf48e79779b11c85 (patch)
treef8f11f7b4daf14e76e8e3d716c85f5a56a949476 /arch/powerpc/kvm/powerpc.c
parent7a8ff56be68239bd36a2b639cb40bfbcfc58dad3 (diff)
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/kvm/powerpc.c')
-rw-r--r--arch/powerpc/kvm/powerpc.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 7ca9e0a80499..026dfaaa4772 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -673,9 +673,19 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
673} 673}
674 674
675int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, 675int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
676 unsigned int rt, unsigned int bytes, int is_bigendian) 676 unsigned int rt, unsigned int bytes,
677 int is_default_endian)
677{ 678{
678 int idx, ret; 679 int idx, ret;
680 int is_bigendian;
681
682 if (kvmppc_need_byteswap(vcpu)) {
683 /* Default endianness is "little endian". */
684 is_bigendian = !is_default_endian;
685 } else {
686 /* Default endianness is "big endian". */
687 is_bigendian = is_default_endian;
688 }
679 689
680 if (bytes > sizeof(run->mmio.data)) { 690 if (bytes > sizeof(run->mmio.data)) {
681 printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__, 691 printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__,
@@ -711,21 +721,31 @@ EXPORT_SYMBOL_GPL(kvmppc_handle_load);
711 721
712/* Same as above, but sign extends */ 722/* Same as above, but sign extends */
713int kvmppc_handle_loads(struct kvm_run *run, struct kvm_vcpu *vcpu, 723int kvmppc_handle_loads(struct kvm_run *run, struct kvm_vcpu *vcpu,
714 unsigned int rt, unsigned int bytes, int is_bigendian) 724 unsigned int rt, unsigned int bytes,
725 int is_default_endian)
715{ 726{
716 int r; 727 int r;
717 728
718 vcpu->arch.mmio_sign_extend = 1; 729 vcpu->arch.mmio_sign_extend = 1;
719 r = kvmppc_handle_load(run, vcpu, rt, bytes, is_bigendian); 730 r = kvmppc_handle_load(run, vcpu, rt, bytes, is_default_endian);
720 731
721 return r; 732 return r;
722} 733}
723 734
724int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, 735int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
725 u64 val, unsigned int bytes, int is_bigendian) 736 u64 val, unsigned int bytes, int is_default_endian)
726{ 737{
727 void *data = run->mmio.data; 738 void *data = run->mmio.data;
728 int idx, ret; 739 int idx, ret;
740 int is_bigendian;
741
742 if (kvmppc_need_byteswap(vcpu)) {
743 /* Default endianness is "little endian". */
744 is_bigendian = !is_default_endian;
745 } else {
746 /* Default endianness is "big endian". */
747 is_bigendian = is_default_endian;
748 }
729 749
730 if (bytes > sizeof(run->mmio.data)) { 750 if (bytes > sizeof(run->mmio.data)) {
731 printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__, 751 printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__,