diff mbox

KVM: PPC: Fix emulated MMIO sign-extension

Message ID 20160505061710.GA5559@oak.ozlabs.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Paul Mackerras May 5, 2016, 6:17 a.m. UTC
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>
---
 arch/powerpc/kvm/powerpc.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

Comments

Thomas Huth May 9, 2016, 8:02 a.m. UTC | #1
On 05.05.2016 08:17, Paul Mackerras wrote:
> 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>
> ---
>  arch/powerpc/kvm/powerpc.c | 22 ++++++++++++----------
>  1 file changed, 12 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
> index 6a68730..02416fe 100644
> --- a/arch/powerpc/kvm/powerpc.c
> +++ b/arch/powerpc/kvm/powerpc.c
> @@ -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,
> -		       unsigned int rt, unsigned int bytes,
> -		       int is_default_endian)
> +static int __kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
> +				unsigned int rt, unsigned int bytes,
> +				int is_default_endian, int sign_extend)
>  {
>  	int idx, ret;
>  	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->mmio_needed = 1;
>  	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);
>  
> @@ -844,6 +844,13 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
>  
>  	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);
>  
>  /* 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,
>  			int is_default_endian)
>  {
> -	int r;
> -
> -	vcpu->arch.mmio_sign_extend = 1;
> -	r = kvmppc_handle_load(run, vcpu, rt, bytes, is_default_endian);
> -
> -	return r;
> +	return __kvmppc_handle_load(run, vcpu, rt, bytes, is_default_endian, 1);
>  }
>  
>  int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
> 

Reviewed-by: Thomas Huth <thuth@redhat.com>

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Paul Mackerras May 11, 2016, 11:37 a.m. UTC | #2
On Thu, May 05, 2016 at 04:17:10PM +1000, Paul Mackerras wrote:
> 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>

Applied to my kvm-ppc-next branch.

Paul.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 6a68730..02416fe 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -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,
-		       unsigned int rt, unsigned int bytes,
-		       int is_default_endian)
+static int __kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
+				unsigned int rt, unsigned int bytes,
+				int is_default_endian, int sign_extend)
 {
 	int idx, ret;
 	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->mmio_needed = 1;
 	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);
 
@@ -844,6 +844,13 @@  int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
 	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);
 
 /* 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,
 			int is_default_endian)
 {
-	int r;
-
-	vcpu->arch.mmio_sign_extend = 1;
-	r = kvmppc_handle_load(run, vcpu, rt, bytes, is_default_endian);
-
-	return r;
+	return __kvmppc_handle_load(run, vcpu, rt, bytes, is_default_endian, 1);
 }
 
 int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,