|
@@ -720,7 +720,7 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (vcpu->arch.mmio_is_bigendian) {
|
|
|
+ if (!vcpu->arch.mmio_host_swabbed) {
|
|
|
switch (run->mmio.len) {
|
|
|
case 8: gpr = *(u64 *)run->mmio.data; break;
|
|
|
case 4: gpr = *(u32 *)run->mmio.data; break;
|
|
@@ -728,10 +728,10 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
|
|
|
case 1: gpr = *(u8 *)run->mmio.data; break;
|
|
|
}
|
|
|
} else {
|
|
|
- /* Convert BE data from userland back to LE. */
|
|
|
switch (run->mmio.len) {
|
|
|
- case 4: gpr = ld_le32((u32 *)run->mmio.data); break;
|
|
|
- case 2: gpr = ld_le16((u16 *)run->mmio.data); break;
|
|
|
+ case 8: gpr = swab64(*(u64 *)run->mmio.data); break;
|
|
|
+ case 4: gpr = swab32(*(u32 *)run->mmio.data); break;
|
|
|
+ case 2: gpr = swab16(*(u16 *)run->mmio.data); break;
|
|
|
case 1: gpr = *(u8 *)run->mmio.data; break;
|
|
|
}
|
|
|
}
|
|
@@ -780,14 +780,13 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
|
|
int is_default_endian)
|
|
|
{
|
|
|
int idx, ret;
|
|
|
- int is_bigendian;
|
|
|
+ bool host_swabbed;
|
|
|
|
|
|
+ /* Pity C doesn't have a logical XOR operator */
|
|
|
if (kvmppc_need_byteswap(vcpu)) {
|
|
|
- /* Default endianness is "little endian". */
|
|
|
- is_bigendian = !is_default_endian;
|
|
|
+ host_swabbed = is_default_endian;
|
|
|
} else {
|
|
|
- /* Default endianness is "big endian". */
|
|
|
- is_bigendian = is_default_endian;
|
|
|
+ host_swabbed = !is_default_endian;
|
|
|
}
|
|
|
|
|
|
if (bytes > sizeof(run->mmio.data)) {
|
|
@@ -800,7 +799,7 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
|
|
run->mmio.is_write = 0;
|
|
|
|
|
|
vcpu->arch.io_gpr = rt;
|
|
|
- vcpu->arch.mmio_is_bigendian = is_bigendian;
|
|
|
+ vcpu->arch.mmio_host_swabbed = host_swabbed;
|
|
|
vcpu->mmio_needed = 1;
|
|
|
vcpu->mmio_is_write = 0;
|
|
|
vcpu->arch.mmio_sign_extend = 0;
|
|
@@ -840,14 +839,13 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
|
|
{
|
|
|
void *data = run->mmio.data;
|
|
|
int idx, ret;
|
|
|
- int is_bigendian;
|
|
|
+ bool host_swabbed;
|
|
|
|
|
|
+ /* Pity C doesn't have a logical XOR operator */
|
|
|
if (kvmppc_need_byteswap(vcpu)) {
|
|
|
- /* Default endianness is "little endian". */
|
|
|
- is_bigendian = !is_default_endian;
|
|
|
+ host_swabbed = is_default_endian;
|
|
|
} else {
|
|
|
- /* Default endianness is "big endian". */
|
|
|
- is_bigendian = is_default_endian;
|
|
|
+ host_swabbed = !is_default_endian;
|
|
|
}
|
|
|
|
|
|
if (bytes > sizeof(run->mmio.data)) {
|
|
@@ -862,7 +860,7 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
|
|
vcpu->mmio_is_write = 1;
|
|
|
|
|
|
/* Store the value at the lowest bytes in 'data'. */
|
|
|
- if (is_bigendian) {
|
|
|
+ if (!host_swabbed) {
|
|
|
switch (bytes) {
|
|
|
case 8: *(u64 *)data = val; break;
|
|
|
case 4: *(u32 *)data = val; break;
|
|
@@ -870,11 +868,11 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
|
|
case 1: *(u8 *)data = val; break;
|
|
|
}
|
|
|
} else {
|
|
|
- /* Store LE value into 'data'. */
|
|
|
switch (bytes) {
|
|
|
- case 4: st_le32(data, val); break;
|
|
|
- case 2: st_le16(data, val); break;
|
|
|
- case 1: *(u8 *)data = val; break;
|
|
|
+ case 8: *(u64 *)data = swab64(val); break;
|
|
|
+ case 4: *(u32 *)data = swab32(val); break;
|
|
|
+ case 2: *(u16 *)data = swab16(val); break;
|
|
|
+ case 1: *(u8 *)data = val; break;
|
|
|
}
|
|
|
}
|
|
|
|