KVM: x86: split the two parts of emulator_pio_in
emulator_pio_in handles both the case where the data is pending in
vcpu->arch.pio.count, and the case where I/O has to be done via either
an in-kernel device or a userspace exit.  For SEV-ES we would like
to split these, to identify clearly the moment at which the
sev_pio_data is consumed.  To this end, create two different
functions: __emulator_pio_in fills in vcpu->arch.pio.count, while
complete_emulator_pio_in clears it and releases vcpu->arch.pio.data.
Because this patch has to be backported, things are left a bit messy.
kernel_pio() operates on vcpu->arch.pio, which leads to emulator_pio_in()
having with two calls to complete_emulator_pio_in().  It will be fixed
in the next release.
While at it, remove the unused void* val argument of emulator_pio_in_out.
The function currently hardcodes vcpu->arch.pio_data as the
source/destination buffer, which sucks but will be fixed after the more
severe SEV-ES buffer overflow.
No functional change intended.
Cc: stable@vger.kernel.org
Fixes: 7ed9abfe8e ("KVM: SVM: Support string IO operations for an SEV-ES guest")
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
			
			
This commit is contained in:
		
							parent
							
								
									ea724ea420
								
							
						
					
					
						commit
						3b27de2718
					
				| @ -6906,7 +6906,7 @@ static int kernel_pio(struct kvm_vcpu *vcpu, void *pd) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size, | static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size, | ||||||
| 			       unsigned short port, void *val, | 			       unsigned short port, | ||||||
| 			       unsigned int count, bool in) | 			       unsigned int count, bool in) | ||||||
| { | { | ||||||
| 	vcpu->arch.pio.port = port; | 	vcpu->arch.pio.port = port; | ||||||
| @ -6927,26 +6927,38 @@ static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size, | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int __emulator_pio_in(struct kvm_vcpu *vcpu, int size, | ||||||
|  | 			     unsigned short port, unsigned int count) | ||||||
|  | { | ||||||
|  | 	WARN_ON(vcpu->arch.pio.count); | ||||||
|  | 	memset(vcpu->arch.pio_data, 0, size * count); | ||||||
|  | 	return emulator_pio_in_out(vcpu, size, port, count, true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void complete_emulator_pio_in(struct kvm_vcpu *vcpu, int size, | ||||||
|  | 				    unsigned short port, void *val) | ||||||
|  | { | ||||||
|  | 	memcpy(val, vcpu->arch.pio_data, size * vcpu->arch.pio.count); | ||||||
|  | 	trace_kvm_pio(KVM_PIO_IN, port, size, vcpu->arch.pio.count, vcpu->arch.pio_data); | ||||||
|  | 	vcpu->arch.pio.count = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int emulator_pio_in(struct kvm_vcpu *vcpu, int size, | static int emulator_pio_in(struct kvm_vcpu *vcpu, int size, | ||||||
| 			   unsigned short port, void *val, unsigned int count) | 			   unsigned short port, void *val, unsigned int count) | ||||||
| { | { | ||||||
| 	int ret; | 	if (vcpu->arch.pio.count) { | ||||||
|  | 		/* Complete previous iteration.  */ | ||||||
|  | 	} else { | ||||||
|  | 		int r = __emulator_pio_in(vcpu, size, port, count); | ||||||
|  | 		if (!r) | ||||||
|  | 			return r; | ||||||
| 
 | 
 | ||||||
| 	if (vcpu->arch.pio.count) | 		/* Results already available, fall through.  */ | ||||||
| 		goto data_avail; |  | ||||||
| 
 |  | ||||||
| 	memset(vcpu->arch.pio_data, 0, size * count); |  | ||||||
| 
 |  | ||||||
| 	ret = emulator_pio_in_out(vcpu, size, port, val, count, true); |  | ||||||
| 	if (ret) { |  | ||||||
| data_avail: |  | ||||||
| 		memcpy(val, vcpu->arch.pio_data, size * count); |  | ||||||
| 		trace_kvm_pio(KVM_PIO_IN, port, size, count, vcpu->arch.pio_data); |  | ||||||
| 		vcpu->arch.pio.count = 0; |  | ||||||
| 		return 1; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	WARN_ON(count != vcpu->arch.pio.count); | ||||||
|  | 	complete_emulator_pio_in(vcpu, size, port, val); | ||||||
|  | 	return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt, | static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt, | ||||||
| @ -6965,12 +6977,11 @@ static int emulator_pio_out(struct kvm_vcpu *vcpu, int size, | |||||||
| 
 | 
 | ||||||
| 	memcpy(vcpu->arch.pio_data, val, size * count); | 	memcpy(vcpu->arch.pio_data, val, size * count); | ||||||
| 	trace_kvm_pio(KVM_PIO_OUT, port, size, count, vcpu->arch.pio_data); | 	trace_kvm_pio(KVM_PIO_OUT, port, size, count, vcpu->arch.pio_data); | ||||||
| 	ret = emulator_pio_in_out(vcpu, size, port, (void *)val, count, false); | 	ret = emulator_pio_in_out(vcpu, size, port, count, false); | ||||||
| 	if (ret) | 	if (ret) | ||||||
|                 vcpu->arch.pio.count = 0; |                 vcpu->arch.pio.count = 0; | ||||||
| 
 | 
 | ||||||
|         return ret; |         return ret; | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int emulator_pio_out_emulated(struct x86_emulate_ctxt *ctxt, | static int emulator_pio_out_emulated(struct x86_emulate_ctxt *ctxt, | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user