Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: Cleanup KVM emulated load/store endian handling

Sometimes the KVM code on powerpc needs to emulate load or store
instructions from the guest, which can include both normal and byte
reversed forms.

We currently (AFAICT) handle this correctly, but some variable names are
very misleading. In particular we use "is_bigendian" in several places to
actually mean "is the IO the same endian as the host", but we now support
little-endian powerpc hosts. This also ties into the misleadingly named
ld_le*() and st_le*() functions, which in fact always byteswap, even on
an LE host.

This patch cleans this up by renaming to more accurate "host_swabbed", and
uses the generic swab*() functions instead of the powerpc specific and
misleadingly named ld_le*() and st_le*() functions.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

authored by

David Gibson and committed by
Benjamin Herrenschmidt
d078eed3 7a8bf874

+19 -21
+1 -1
arch/powerpc/include/asm/kvm_host.h
··· 585 585 pgd_t *pgdir; 586 586 587 587 u8 io_gpr; /* GPR used as IO source/target */ 588 - u8 mmio_is_bigendian; 588 + u8 mmio_host_swabbed; 589 589 u8 mmio_sign_extend; 590 590 u8 osi_needed; 591 591 u8 osi_enabled;
+18 -20
arch/powerpc/kvm/powerpc.c
··· 720 720 return; 721 721 } 722 722 723 - if (vcpu->arch.mmio_is_bigendian) { 723 + if (!vcpu->arch.mmio_host_swabbed) { 724 724 switch (run->mmio.len) { 725 725 case 8: gpr = *(u64 *)run->mmio.data; break; 726 726 case 4: gpr = *(u32 *)run->mmio.data; break; ··· 728 728 case 1: gpr = *(u8 *)run->mmio.data; break; 729 729 } 730 730 } else { 731 - /* Convert BE data from userland back to LE. */ 732 731 switch (run->mmio.len) { 733 - case 4: gpr = ld_le32((u32 *)run->mmio.data); break; 734 - case 2: gpr = ld_le16((u16 *)run->mmio.data); break; 732 + case 8: gpr = swab64(*(u64 *)run->mmio.data); break; 733 + case 4: gpr = swab32(*(u32 *)run->mmio.data); break; 734 + case 2: gpr = swab16(*(u16 *)run->mmio.data); break; 735 735 case 1: gpr = *(u8 *)run->mmio.data; break; 736 736 } 737 737 } ··· 780 780 int is_default_endian) 781 781 { 782 782 int idx, ret; 783 - int is_bigendian; 783 + bool host_swabbed; 784 784 785 + /* Pity C doesn't have a logical XOR operator */ 785 786 if (kvmppc_need_byteswap(vcpu)) { 786 - /* Default endianness is "little endian". */ 787 - is_bigendian = !is_default_endian; 787 + host_swabbed = is_default_endian; 788 788 } else { 789 - /* Default endianness is "big endian". */ 790 - is_bigendian = is_default_endian; 789 + host_swabbed = !is_default_endian; 791 790 } 792 791 793 792 if (bytes > sizeof(run->mmio.data)) { ··· 799 800 run->mmio.is_write = 0; 800 801 801 802 vcpu->arch.io_gpr = rt; 802 - vcpu->arch.mmio_is_bigendian = is_bigendian; 803 + vcpu->arch.mmio_host_swabbed = host_swabbed; 803 804 vcpu->mmio_needed = 1; 804 805 vcpu->mmio_is_write = 0; 805 806 vcpu->arch.mmio_sign_extend = 0; ··· 839 840 { 840 841 void *data = run->mmio.data; 841 842 int idx, ret; 842 - int is_bigendian; 843 + bool host_swabbed; 843 844 845 + /* Pity C doesn't have a logical XOR operator */ 844 846 if (kvmppc_need_byteswap(vcpu)) { 845 - /* Default endianness is "little endian". */ 846 - is_bigendian = !is_default_endian; 847 + host_swabbed = is_default_endian; 847 848 } else { 848 - /* Default endianness is "big endian". */ 849 - is_bigendian = is_default_endian; 849 + host_swabbed = !is_default_endian; 850 850 } 851 851 852 852 if (bytes > sizeof(run->mmio.data)) { ··· 860 862 vcpu->mmio_is_write = 1; 861 863 862 864 /* Store the value at the lowest bytes in 'data'. */ 863 - if (is_bigendian) { 865 + if (!host_swabbed) { 864 866 switch (bytes) { 865 867 case 8: *(u64 *)data = val; break; 866 868 case 4: *(u32 *)data = val; break; ··· 868 870 case 1: *(u8 *)data = val; break; 869 871 } 870 872 } else { 871 - /* Store LE value into 'data'. */ 872 873 switch (bytes) { 873 - case 4: st_le32(data, val); break; 874 - case 2: st_le16(data, val); break; 875 - case 1: *(u8 *)data = val; break; 874 + case 8: *(u64 *)data = swab64(val); break; 875 + case 4: *(u32 *)data = swab32(val); break; 876 + case 2: *(u16 *)data = swab16(val); break; 877 + case 1: *(u8 *)data = val; break; 876 878 } 877 879 } 878 880