KVM: PPC: Fix emulated MMIO sign-extension
When the guest does a sign-extending load instruction (such as lha or lwa) to an emulated MMIO location, it results in a call to kvmppc_handle_loads() in the host. That function sets the vcpu->arch.mmio_sign_extend flag and calls kvmppc_handle_load() to do the rest of the work. However, kvmppc_handle_load() sets the mmio_sign_extend flag to 0 unconditionally, so the sign extension never gets done. To fix this, we rename kvmppc_handle_load to __kvmppc_handle_load and add an explicit parameter to indicate whether sign extension is required. kvmppc_handle_load() and kvmppc_handle_loads() then become 1-line functions that just call __kvmppc_handle_load() with the extra parameter. Reported-by: Bin Lu <lblulb@linux.vnet.ibm.com> Signed-off-by: Paul Mackerras <paulus@ozlabs.org> Reviewed-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
ade3ac660a
commit
eb8b056016
|
@ -800,9 +800,9 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
static int __kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||||
unsigned int rt, unsigned int bytes,
|
unsigned int rt, unsigned int bytes,
|
||||||
int is_default_endian)
|
int is_default_endian, int sign_extend)
|
||||||
{
|
{
|
||||||
int idx, ret;
|
int idx, ret;
|
||||||
bool host_swabbed;
|
bool host_swabbed;
|
||||||
|
@ -827,7 +827,7 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||||
vcpu->arch.mmio_host_swabbed = host_swabbed;
|
vcpu->arch.mmio_host_swabbed = host_swabbed;
|
||||||
vcpu->mmio_needed = 1;
|
vcpu->mmio_needed = 1;
|
||||||
vcpu->mmio_is_write = 0;
|
vcpu->mmio_is_write = 0;
|
||||||
vcpu->arch.mmio_sign_extend = 0;
|
vcpu->arch.mmio_sign_extend = sign_extend;
|
||||||
|
|
||||||
idx = srcu_read_lock(&vcpu->kvm->srcu);
|
idx = srcu_read_lock(&vcpu->kvm->srcu);
|
||||||
|
|
||||||
|
@ -844,6 +844,13 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||||
|
|
||||||
return EMULATE_DO_MMIO;
|
return EMULATE_DO_MMIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||||
|
unsigned int rt, unsigned int bytes,
|
||||||
|
int is_default_endian)
|
||||||
|
{
|
||||||
|
return __kvmppc_handle_load(run, vcpu, rt, bytes, is_default_endian, 0);
|
||||||
|
}
|
||||||
EXPORT_SYMBOL_GPL(kvmppc_handle_load);
|
EXPORT_SYMBOL_GPL(kvmppc_handle_load);
|
||||||
|
|
||||||
/* Same as above, but sign extends */
|
/* Same as above, but sign extends */
|
||||||
|
@ -851,12 +858,7 @@ int kvmppc_handle_loads(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||||
unsigned int rt, unsigned int bytes,
|
unsigned int rt, unsigned int bytes,
|
||||||
int is_default_endian)
|
int is_default_endian)
|
||||||
{
|
{
|
||||||
int r;
|
return __kvmppc_handle_load(run, vcpu, rt, bytes, is_default_endian, 1);
|
||||||
|
|
||||||
vcpu->arch.mmio_sign_extend = 1;
|
|
||||||
r = kvmppc_handle_load(run, vcpu, rt, bytes, is_default_endian);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||||
|
|
Loading…
Reference in New Issue