All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/8] KVM: x86: vcpu->arch.pio* cleanups
@ 2022-06-24 17:18 Paolo Bonzini
  2022-06-24 17:18 ` [PATCH v2 1/8] KVM: x86: complete fast IN directly with complete_emulator_pio_in() Paolo Bonzini
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Paolo Bonzini @ 2022-06-24 17:18 UTC (permalink / raw)
  To: linux-kernel, kvm

These patches complete the job started by commit 3b27de271839 ("KVM:
x86: split the two parts of emulator_pio_in", 2021-10-22).  The commit
message eloquently said that emulator_pio_in_out "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".  Some time
has passed and it's high time to do it.

After this series, in-kernel PIO does not use vcpu->arch.pio* anymore;
it is only used by complete_emulator_pio_in.

Paolo

v1->v2:
- split out "KVM: x86: complete fast IN directly with complete_emulator_pio_in()"
- remove WARN if emulated PIO performs successful in-kernel iterations before
  falling back to userspace, it is (unfortunately) valid if SRCU changes mid-loop.
- new patch 3 to handle unregistered devices mid-loop, dropping writes and reading
  as zero
- WARN if non-NULL data is passed to emulator_pio_in_out() before the code is
  ready to handle in-kernel PIO without vcpu->arch.pio*
- use "size" in SEV case instead of vcpu->arch.pio_size

Paolo Bonzini (8):
  KVM: x86: complete fast IN directly with complete_emulator_pio_in()
  KVM: x86: inline kernel_pio into its sole caller
  KVM: x86: drop PIO from unregistered devices
  KVM: x86: move all vcpu->arch.pio* setup in emulator_pio_in_out()
  KVM: x86: wean in-kernel PIO from vcpu->arch.pio*
  KVM: x86: wean fast IN from emulator_pio_in
  KVM: x86: de-underscorify __emulator_pio_in
  KVM: SEV-ES: reuse advance_sev_es_emulated_ins for OUT too

 arch/x86/kvm/trace.h |   2 +-
 arch/x86/kvm/x86.c   | 133 ++++++++++++++++++++-----------------------
 2 files changed, 62 insertions(+), 73 deletions(-)

-- 
2.31.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/8] KVM: x86: complete fast IN directly with complete_emulator_pio_in()
  2022-06-24 17:18 [PATCH v2 0/8] KVM: x86: vcpu->arch.pio* cleanups Paolo Bonzini
@ 2022-06-24 17:18 ` Paolo Bonzini
  2022-06-24 17:18 ` [PATCH v2 2/8] KVM: x86: inline kernel_pio into its sole caller Paolo Bonzini
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2022-06-24 17:18 UTC (permalink / raw)
  To: linux-kernel, kvm

Use complete_emulator_pio_in() directly when completing fast PIO, there's
no need to bounce through emulator_pio_in(): the comment about ECX
changing doesn't apply to fast PIO, which isn't used for string I/O.

No functional change intended.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/x86.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d88600e41ff8..d66a873f4427 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -8871,11 +8871,7 @@ static int complete_fast_pio_in(struct kvm_vcpu *vcpu)
 	/* For size less than 4 we merge, else we zero extend */
 	val = (vcpu->arch.pio.size < 4) ? kvm_rax_read(vcpu) : 0;
 
-	/*
-	 * Since vcpu->arch.pio.count == 1 let emulator_pio_in perform
-	 * the copy and tracing
-	 */
-	emulator_pio_in(vcpu, vcpu->arch.pio.size, vcpu->arch.pio.port, &val, 1);
+	complete_emulator_pio_in(vcpu, &val);
 	kvm_rax_write(vcpu, val);
 
 	return kvm_skip_emulated_instruction(vcpu);
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/8] KVM: x86: inline kernel_pio into its sole caller
  2022-06-24 17:18 [PATCH v2 0/8] KVM: x86: vcpu->arch.pio* cleanups Paolo Bonzini
  2022-06-24 17:18 ` [PATCH v2 1/8] KVM: x86: complete fast IN directly with complete_emulator_pio_in() Paolo Bonzini
@ 2022-06-24 17:18 ` Paolo Bonzini
  2022-06-24 17:18 ` [PATCH v2 3/8] KVM: x86: drop PIO from unregistered devices Paolo Bonzini
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2022-06-24 17:18 UTC (permalink / raw)
  To: linux-kernel, kvm

The caller of kernel_pio already has arguments for most of what kernel_pio
fishes out of vcpu->arch.pio.  This is the first step towards ensuring that
vcpu->arch.pio.* is only used when exiting to userspace.

No functional change intended.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/x86.c | 38 ++++++++++++++++----------------------
 1 file changed, 16 insertions(+), 22 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d66a873f4427..524a96d26399 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -7575,37 +7575,31 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
 	return emulator_write_emulated(ctxt, addr, new, bytes, exception);
 }
 
-static int kernel_pio(struct kvm_vcpu *vcpu, void *pd)
-{
-	int r = 0, i;
-
-	for (i = 0; i < vcpu->arch.pio.count; i++) {
-		if (vcpu->arch.pio.in)
-			r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port,
-					    vcpu->arch.pio.size, pd);
-		else
-			r = kvm_io_bus_write(vcpu, KVM_PIO_BUS,
-					     vcpu->arch.pio.port, vcpu->arch.pio.size,
-					     pd);
-		if (r)
-			break;
-		pd += vcpu->arch.pio.size;
-	}
-	return r;
-}
-
 static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
 			       unsigned short port,
 			       unsigned int count, bool in)
 {
+	void *data = vcpu->arch.pio_data;
+	unsigned i;
+	int r;
+
 	vcpu->arch.pio.port = port;
 	vcpu->arch.pio.in = in;
-	vcpu->arch.pio.count  = count;
+	vcpu->arch.pio.count = count;
 	vcpu->arch.pio.size = size;
 
-	if (!kernel_pio(vcpu, vcpu->arch.pio_data))
-		return 1;
+	for (i = 0; i < count; i++) {
+		if (in)
+			r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, port, size, data);
+		else
+			r = kvm_io_bus_write(vcpu, KVM_PIO_BUS, port, size, data);
+		if (r)
+			goto userspace_io;
+		data += size;
+	}
+	return 1;
 
+userspace_io:
 	vcpu->run->exit_reason = KVM_EXIT_IO;
 	vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
 	vcpu->run->io.size = size;
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/8] KVM: x86: drop PIO from unregistered devices
  2022-06-24 17:18 [PATCH v2 0/8] KVM: x86: vcpu->arch.pio* cleanups Paolo Bonzini
  2022-06-24 17:18 ` [PATCH v2 1/8] KVM: x86: complete fast IN directly with complete_emulator_pio_in() Paolo Bonzini
  2022-06-24 17:18 ` [PATCH v2 2/8] KVM: x86: inline kernel_pio into its sole caller Paolo Bonzini
@ 2022-06-24 17:18 ` Paolo Bonzini
  2022-06-24 17:18 ` [PATCH v2 4/8] KVM: x86: move all vcpu->arch.pio* setup in emulator_pio_in_out() Paolo Bonzini
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2022-06-24 17:18 UTC (permalink / raw)
  To: linux-kernel, kvm

KVM protects the device list with SRCU, and therefore different calls
to kvm_io_bus_read()/kvm_io_bus_write() can very well see different
incarnations of kvm->buses.  If userspace unregisters a device while
vCPUs are running there is no well-defined result.  This patch applies
a safe fallback by returning early from emulator_pio_in_out().  This
corresponds to returning zeroes from IN, and dropping the writes on
the floor for OUT.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/x86.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 524a96d26399..5a56d39bd81f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -7593,8 +7593,19 @@ static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
 			r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, port, size, data);
 		else
 			r = kvm_io_bus_write(vcpu, KVM_PIO_BUS, port, size, data);
-		if (r)
-			goto userspace_io;
+
+		if (r) {
+			if (i == 0)
+				goto userspace_io;
+
+			/*
+			 * Userspace must have unregistered the device while PIO
+			 * was running.  Drop writes / read as 0 (the buffer
+			 * was zeroed in __emulator_pio_in).
+			 */
+			break;
+		}
+
 		data += size;
 	}
 	return 1;
@@ -7606,7 +7617,6 @@ static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
 	vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE;
 	vcpu->run->io.count = count;
 	vcpu->run->io.port = port;
-
 	return 0;
 }
 
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 4/8] KVM: x86: move all vcpu->arch.pio* setup in emulator_pio_in_out()
  2022-06-24 17:18 [PATCH v2 0/8] KVM: x86: vcpu->arch.pio* cleanups Paolo Bonzini
                   ` (2 preceding siblings ...)
  2022-06-24 17:18 ` [PATCH v2 3/8] KVM: x86: drop PIO from unregistered devices Paolo Bonzini
@ 2022-06-24 17:18 ` Paolo Bonzini
  2022-06-24 17:18 ` [PATCH v2 5/8] KVM: x86: wean in-kernel PIO from vcpu->arch.pio* Paolo Bonzini
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2022-06-24 17:18 UTC (permalink / raw)
  To: linux-kernel, kvm

For now, this is basically an excuse to add back the void* argument to
the function, while removing some knowledge of vcpu->arch.pio* from
its callers.  The WARN that vcpu->arch.pio.count is zero is also
extended to OUT operations.

The vcpu->arch.pio* fields still need to be filled even when the PIO is
handled in-kernel as __emulator_pio_in() is always followed by
complete_emulator_pio_in().  But after fixing that, it will be possible to
to only populate the vcpu->arch.pio* fields on userspace exits.

No functional change intended.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/trace.h |  2 +-
 arch/x86/kvm/x86.c   | 21 +++++++++++++--------
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
index bc85622e28b2..2120d7c060a9 100644
--- a/arch/x86/kvm/trace.h
+++ b/arch/x86/kvm/trace.h
@@ -154,7 +154,7 @@ TRACE_EVENT(kvm_xen_hypercall,
 
 TRACE_EVENT(kvm_pio,
 	TP_PROTO(unsigned int rw, unsigned int port, unsigned int size,
-		 unsigned int count, void *data),
+		 unsigned int count, const void *data),
 	TP_ARGS(rw, port, size, count, data),
 
 	TP_STRUCT__entry(
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 5a56d39bd81f..368d0d4d56ff 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -7576,17 +7576,25 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
 }
 
 static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
-			       unsigned short port,
+			       unsigned short port, void *data,
 			       unsigned int count, bool in)
 {
-	void *data = vcpu->arch.pio_data;
 	unsigned i;
 	int r;
 
+	WARN_ON_ONCE(vcpu->arch.pio.count);
 	vcpu->arch.pio.port = port;
 	vcpu->arch.pio.in = in;
 	vcpu->arch.pio.count = count;
 	vcpu->arch.pio.size = size;
+	if (in) {
+		/* The buffer is only used in complete_emulator_pio_in().  */
+		WARN_ON(data);
+		memset(vcpu->arch.pio_data, 0, size * count);
+	} else {
+		memcpy(vcpu->arch.pio_data, data, size * count);
+	}
+	data = vcpu->arch.pio_data;
 
 	for (i = 0; i < count; i++) {
 		if (in)
@@ -7623,9 +7631,7 @@ static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
 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);
+	return emulator_pio_in_out(vcpu, size, port, NULL, count, true);
 }
 
 static void complete_emulator_pio_in(struct kvm_vcpu *vcpu, void *val)
@@ -7674,9 +7680,8 @@ static int emulator_pio_out(struct kvm_vcpu *vcpu, int size,
 {
 	int ret;
 
-	memcpy(vcpu->arch.pio_data, val, size * count);
-	trace_kvm_pio(KVM_PIO_OUT, port, size, count, vcpu->arch.pio_data);
-	ret = emulator_pio_in_out(vcpu, size, port, count, false);
+	trace_kvm_pio(KVM_PIO_OUT, port, size, count, val);
+	ret = emulator_pio_in_out(vcpu, size, port, (void *)val, count, false);
 	if (ret)
                 vcpu->arch.pio.count = 0;
 
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 5/8] KVM: x86: wean in-kernel PIO from vcpu->arch.pio*
  2022-06-24 17:18 [PATCH v2 0/8] KVM: x86: vcpu->arch.pio* cleanups Paolo Bonzini
                   ` (3 preceding siblings ...)
  2022-06-24 17:18 ` [PATCH v2 4/8] KVM: x86: move all vcpu->arch.pio* setup in emulator_pio_in_out() Paolo Bonzini
@ 2022-06-24 17:18 ` Paolo Bonzini
  2022-06-24 17:18 ` [PATCH v2 6/8] KVM: x86: wean fast IN from emulator_pio_in Paolo Bonzini
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2022-06-24 17:18 UTC (permalink / raw)
  To: linux-kernel, kvm

Make emulator_pio_in_out operate directly on the provided buffer
as long as PIO is handled inside KVM.

For input operations, this means that, in the case of in-kernel
PIO, __emulator_pio_in() does not have to be always followed
by complete_emulator_pio_in().  This affects emulator_pio_in() and
kvm_sev_es_ins(); for the latter, that is why the call moves from
advance_sev_es_emulated_ins() to complete_sev_es_emulated_ins().

For output, it means that vcpu->pio.count is never set unnecessarily
and there is no need to clear it; but also vcpu->pio.size must not
be used in kvm_sev_es_outs(), because it will not be updated for
in-kernel OUT.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/x86.c | 73 ++++++++++++++++++++--------------------------
 1 file changed, 32 insertions(+), 41 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 368d0d4d56ff..716ae5c92687 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -7583,19 +7583,6 @@ static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
 	int r;
 
 	WARN_ON_ONCE(vcpu->arch.pio.count);
-	vcpu->arch.pio.port = port;
-	vcpu->arch.pio.in = in;
-	vcpu->arch.pio.count = count;
-	vcpu->arch.pio.size = size;
-	if (in) {
-		/* The buffer is only used in complete_emulator_pio_in().  */
-		WARN_ON(data);
-		memset(vcpu->arch.pio_data, 0, size * count);
-	} else {
-		memcpy(vcpu->arch.pio_data, data, size * count);
-	}
-	data = vcpu->arch.pio_data;
-
 	for (i = 0; i < count; i++) {
 		if (in)
 			r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, port, size, data);
@@ -7608,9 +7595,10 @@ static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
 
 			/*
 			 * Userspace must have unregistered the device while PIO
-			 * was running.  Drop writes / read as 0 (the buffer
-			 * was zeroed in __emulator_pio_in).
+			 * was running.  Drop writes / read as 0.
 			 */
+			if (in)
+				memset(data, 0, size * (count - i));
 			break;
 		}
 
@@ -7619,6 +7607,16 @@ static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
 	return 1;
 
 userspace_io:
+	vcpu->arch.pio.port = port;
+	vcpu->arch.pio.in = in;
+	vcpu->arch.pio.count = count;
+	vcpu->arch.pio.size = size;
+
+	if (in)
+		memset(vcpu->arch.pio_data, 0, size * count);
+	else
+		memcpy(vcpu->arch.pio_data, data, size * count);
+
 	vcpu->run->exit_reason = KVM_EXIT_IO;
 	vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
 	vcpu->run->io.size = size;
@@ -7629,15 +7627,19 @@ static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
 }
 
 static int __emulator_pio_in(struct kvm_vcpu *vcpu, int size,
-			     unsigned short port, unsigned int count)
+			     unsigned short port, void *val, unsigned int count)
 {
-	return emulator_pio_in_out(vcpu, size, port, NULL, count, true);
+	int r = emulator_pio_in_out(vcpu, size, port, val, count, true);
+	if (r)
+		trace_kvm_pio(KVM_PIO_IN, port, size, count, val);
+
+	return r;
 }
 
 static void complete_emulator_pio_in(struct kvm_vcpu *vcpu, void *val)
 {
 	int size = vcpu->arch.pio.size;
-	unsigned count = vcpu->arch.pio.count;
+	unsigned int count = vcpu->arch.pio.count;
 	memcpy(val, vcpu->arch.pio_data, size * count);
 	trace_kvm_pio(KVM_PIO_IN, vcpu->arch.pio.port, size, count, vcpu->arch.pio_data);
 	vcpu->arch.pio.count = 0;
@@ -7654,16 +7656,11 @@ static int emulator_pio_in(struct kvm_vcpu *vcpu, int size,
 		 * shenanigans as KVM doesn't support modifying the rep count,
 		 * and the emulator ensures @count doesn't overflow the buffer.
 		 */
-	} else {
-		int r = __emulator_pio_in(vcpu, size, port, count);
-		if (!r)
-			return r;
-
-		/* Results already available, fall through.  */
+		complete_emulator_pio_in(vcpu, val);
+		return 1;
 	}
 
-	complete_emulator_pio_in(vcpu, val);
-	return 1;
+	return __emulator_pio_in(vcpu, size, port, val, count);
 }
 
 static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt,
@@ -7678,14 +7675,8 @@ static int emulator_pio_out(struct kvm_vcpu *vcpu, int size,
 			    unsigned short port, const void *val,
 			    unsigned int count)
 {
-	int ret;
-
 	trace_kvm_pio(KVM_PIO_OUT, port, size, count, val);
-	ret = emulator_pio_in_out(vcpu, size, port, (void *)val, count, false);
-	if (ret)
-                vcpu->arch.pio.count = 0;
-
-        return ret;
+	return emulator_pio_in_out(vcpu, size, port, (void *)val, count, false);
 }
 
 static int emulator_pio_out_emulated(struct x86_emulate_ctxt *ctxt,
@@ -13245,7 +13236,7 @@ static int kvm_sev_es_outs(struct kvm_vcpu *vcpu, unsigned int size,
 
 		/* memcpy done already by emulator_pio_out.  */
 		vcpu->arch.sev_pio_count -= count;
-		vcpu->arch.sev_pio_data += count * vcpu->arch.pio.size;
+		vcpu->arch.sev_pio_data += count * size;
 		if (!ret)
 			break;
 
@@ -13261,20 +13252,20 @@ static int kvm_sev_es_outs(struct kvm_vcpu *vcpu, unsigned int size,
 static int kvm_sev_es_ins(struct kvm_vcpu *vcpu, unsigned int size,
 			  unsigned int port);
 
-static void advance_sev_es_emulated_ins(struct kvm_vcpu *vcpu)
+static void advance_sev_es_emulated_ins(struct kvm_vcpu *vcpu, unsigned count, int size)
 {
-	unsigned count = vcpu->arch.pio.count;
-	complete_emulator_pio_in(vcpu, vcpu->arch.sev_pio_data);
 	vcpu->arch.sev_pio_count -= count;
-	vcpu->arch.sev_pio_data += count * vcpu->arch.pio.size;
+	vcpu->arch.sev_pio_data += count * size;
 }
 
 static int complete_sev_es_emulated_ins(struct kvm_vcpu *vcpu)
 {
+	unsigned count = vcpu->arch.pio.count;
 	int size = vcpu->arch.pio.size;
 	int port = vcpu->arch.pio.port;
 
-	advance_sev_es_emulated_ins(vcpu);
+	complete_emulator_pio_in(vcpu, vcpu->arch.sev_pio_data);
+	advance_sev_es_emulated_ins(vcpu, count, size);
 	if (vcpu->arch.sev_pio_count)
 		return kvm_sev_es_ins(vcpu, size, port);
 	return 1;
@@ -13286,11 +13277,11 @@ static int kvm_sev_es_ins(struct kvm_vcpu *vcpu, unsigned int size,
 	for (;;) {
 		unsigned int count =
 			min_t(unsigned int, PAGE_SIZE / size, vcpu->arch.sev_pio_count);
-		if (!__emulator_pio_in(vcpu, size, port, count))
+		if (!__emulator_pio_in(vcpu, size, port, vcpu->arch.sev_pio_data, count))
 			break;
 
 		/* Emulation done by the kernel.  */
-		advance_sev_es_emulated_ins(vcpu);
+		advance_sev_es_emulated_ins(vcpu, count, size);
 		if (!vcpu->arch.sev_pio_count)
 			return 1;
 	}
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 6/8] KVM: x86: wean fast IN from emulator_pio_in
  2022-06-24 17:18 [PATCH v2 0/8] KVM: x86: vcpu->arch.pio* cleanups Paolo Bonzini
                   ` (4 preceding siblings ...)
  2022-06-24 17:18 ` [PATCH v2 5/8] KVM: x86: wean in-kernel PIO from vcpu->arch.pio* Paolo Bonzini
@ 2022-06-24 17:18 ` Paolo Bonzini
  2022-06-24 17:18 ` [PATCH v2 7/8] KVM: x86: de-underscorify __emulator_pio_in Paolo Bonzini
  2022-06-24 17:18 ` [PATCH v2 8/8] KVM: SEV-ES: reuse advance_sev_es_emulated_ins for OUT too Paolo Bonzini
  7 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2022-06-24 17:18 UTC (permalink / raw)
  To: linux-kernel, kvm

Use __emulator_pio_in() directly for fast PIO instead of bouncing through
emulator_pio_in() now that __emulator_pio_in() fills "val" when handling
in-kernel PIO.  vcpu->arch.pio.count is guaranteed to be '0', so this a
pure nop.

emulator_pio_in_emulated is now the last caller of emulator_pio_in.

No functional change intended.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/x86.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 716ae5c92687..b824ffc63b17 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -8886,7 +8886,7 @@ static int kvm_fast_pio_in(struct kvm_vcpu *vcpu, int size,
 	/* For size less than 4 we merge, else we zero extend */
 	val = (size < 4) ? kvm_rax_read(vcpu) : 0;
 
-	ret = emulator_pio_in(vcpu, size, port, &val, 1);
+	ret = __emulator_pio_in(vcpu, size, port, &val, 1);
 	if (ret) {
 		kvm_rax_write(vcpu, val);
 		return ret;
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 7/8] KVM: x86: de-underscorify __emulator_pio_in
  2022-06-24 17:18 [PATCH v2 0/8] KVM: x86: vcpu->arch.pio* cleanups Paolo Bonzini
                   ` (5 preceding siblings ...)
  2022-06-24 17:18 ` [PATCH v2 6/8] KVM: x86: wean fast IN from emulator_pio_in Paolo Bonzini
@ 2022-06-24 17:18 ` Paolo Bonzini
  2022-06-24 17:18 ` [PATCH v2 8/8] KVM: SEV-ES: reuse advance_sev_es_emulated_ins for OUT too Paolo Bonzini
  7 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2022-06-24 17:18 UTC (permalink / raw)
  To: linux-kernel, kvm

Now all callers except emulator_pio_in_emulated are using
__emulator_pio_in/complete_emulator_pio_in explicitly.
Move the "either copy the result or attempt PIO" logic in
emulator_pio_in_emulated, and rename __emulator_pio_in to
just emulator_pio_in.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/x86.c | 24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index b824ffc63b17..1a017a5a680b 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -7626,8 +7626,8 @@ static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
 	return 0;
 }
 
-static int __emulator_pio_in(struct kvm_vcpu *vcpu, int size,
-			     unsigned short port, void *val, unsigned int count)
+static int emulator_pio_in(struct kvm_vcpu *vcpu, int size,
+      			   unsigned short port, void *val, unsigned int count)
 {
 	int r = emulator_pio_in_out(vcpu, size, port, val, count, true);
 	if (r)
@@ -7645,9 +7645,11 @@ static void complete_emulator_pio_in(struct kvm_vcpu *vcpu, void *val)
 	vcpu->arch.pio.count = 0;
 }
 
-static int emulator_pio_in(struct kvm_vcpu *vcpu, int size,
-			   unsigned short port, void *val, unsigned int count)
+static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt,
+				    int size, unsigned short port, void *val,
+				    unsigned int count)
 {
+	struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
 	if (vcpu->arch.pio.count) {
 		/*
 		 * Complete a previous iteration that required userspace I/O.
@@ -7660,15 +7662,7 @@ static int emulator_pio_in(struct kvm_vcpu *vcpu, int size,
 		return 1;
 	}
 
-	return __emulator_pio_in(vcpu, size, port, val, count);
-}
-
-static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt,
-				    int size, unsigned short port, void *val,
-				    unsigned int count)
-{
-	return emulator_pio_in(emul_to_vcpu(ctxt), size, port, val, count);
-
+	return emulator_pio_in(vcpu, size, port, val, count);
 }
 
 static int emulator_pio_out(struct kvm_vcpu *vcpu, int size,
@@ -8886,7 +8880,7 @@ static int kvm_fast_pio_in(struct kvm_vcpu *vcpu, int size,
 	/* For size less than 4 we merge, else we zero extend */
 	val = (size < 4) ? kvm_rax_read(vcpu) : 0;
 
-	ret = __emulator_pio_in(vcpu, size, port, &val, 1);
+	ret = emulator_pio_in(vcpu, size, port, &val, 1);
 	if (ret) {
 		kvm_rax_write(vcpu, val);
 		return ret;
@@ -13277,7 +13271,7 @@ static int kvm_sev_es_ins(struct kvm_vcpu *vcpu, unsigned int size,
 	for (;;) {
 		unsigned int count =
 			min_t(unsigned int, PAGE_SIZE / size, vcpu->arch.sev_pio_count);
-		if (!__emulator_pio_in(vcpu, size, port, vcpu->arch.sev_pio_data, count))
+		if (!emulator_pio_in(vcpu, size, port, vcpu->arch.sev_pio_data, count))
 			break;
 
 		/* Emulation done by the kernel.  */
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 8/8] KVM: SEV-ES: reuse advance_sev_es_emulated_ins for OUT too
  2022-06-24 17:18 [PATCH v2 0/8] KVM: x86: vcpu->arch.pio* cleanups Paolo Bonzini
                   ` (6 preceding siblings ...)
  2022-06-24 17:18 ` [PATCH v2 7/8] KVM: x86: de-underscorify __emulator_pio_in Paolo Bonzini
@ 2022-06-24 17:18 ` Paolo Bonzini
  7 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2022-06-24 17:18 UTC (permalink / raw)
  To: linux-kernel, kvm

complete_emulator_pio_in() only has to be called by
complete_sev_es_emulated_ins() now; therefore, all that the function does
now is adjust sev_pio_count and sev_pio_data.  Which is the same for
both IN and OUT.

No functional change intended.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/x86.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 1a017a5a680b..567d13405445 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -13206,6 +13206,12 @@ int kvm_sev_es_mmio_read(struct kvm_vcpu *vcpu, gpa_t gpa, unsigned int bytes,
 }
 EXPORT_SYMBOL_GPL(kvm_sev_es_mmio_read);
 
+static void advance_sev_es_emulated_pio(struct kvm_vcpu *vcpu, unsigned count, int size)
+{
+	vcpu->arch.sev_pio_count -= count;
+	vcpu->arch.sev_pio_data += count * size;
+}
+
 static int kvm_sev_es_outs(struct kvm_vcpu *vcpu, unsigned int size,
 			   unsigned int port);
 
@@ -13229,8 +13235,7 @@ static int kvm_sev_es_outs(struct kvm_vcpu *vcpu, unsigned int size,
 		int ret = emulator_pio_out(vcpu, size, port, vcpu->arch.sev_pio_data, count);
 
 		/* memcpy done already by emulator_pio_out.  */
-		vcpu->arch.sev_pio_count -= count;
-		vcpu->arch.sev_pio_data += count * size;
+		advance_sev_es_emulated_pio(vcpu, count, size);
 		if (!ret)
 			break;
 
@@ -13246,12 +13251,6 @@ static int kvm_sev_es_outs(struct kvm_vcpu *vcpu, unsigned int size,
 static int kvm_sev_es_ins(struct kvm_vcpu *vcpu, unsigned int size,
 			  unsigned int port);
 
-static void advance_sev_es_emulated_ins(struct kvm_vcpu *vcpu, unsigned count, int size)
-{
-	vcpu->arch.sev_pio_count -= count;
-	vcpu->arch.sev_pio_data += count * size;
-}
-
 static int complete_sev_es_emulated_ins(struct kvm_vcpu *vcpu)
 {
 	unsigned count = vcpu->arch.pio.count;
@@ -13259,7 +13258,7 @@ static int complete_sev_es_emulated_ins(struct kvm_vcpu *vcpu)
 	int port = vcpu->arch.pio.port;
 
 	complete_emulator_pio_in(vcpu, vcpu->arch.sev_pio_data);
-	advance_sev_es_emulated_ins(vcpu, count, size);
+	advance_sev_es_emulated_pio(vcpu, count, size);
 	if (vcpu->arch.sev_pio_count)
 		return kvm_sev_es_ins(vcpu, size, port);
 	return 1;
@@ -13275,7 +13274,7 @@ static int kvm_sev_es_ins(struct kvm_vcpu *vcpu, unsigned int size,
 			break;
 
 		/* Emulation done by the kernel.  */
-		advance_sev_es_emulated_ins(vcpu, count, size);
+		advance_sev_es_emulated_pio(vcpu, count, size);
 		if (!vcpu->arch.sev_pio_count)
 			return 1;
 	}
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-06-24 17:19 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-24 17:18 [PATCH v2 0/8] KVM: x86: vcpu->arch.pio* cleanups Paolo Bonzini
2022-06-24 17:18 ` [PATCH v2 1/8] KVM: x86: complete fast IN directly with complete_emulator_pio_in() Paolo Bonzini
2022-06-24 17:18 ` [PATCH v2 2/8] KVM: x86: inline kernel_pio into its sole caller Paolo Bonzini
2022-06-24 17:18 ` [PATCH v2 3/8] KVM: x86: drop PIO from unregistered devices Paolo Bonzini
2022-06-24 17:18 ` [PATCH v2 4/8] KVM: x86: move all vcpu->arch.pio* setup in emulator_pio_in_out() Paolo Bonzini
2022-06-24 17:18 ` [PATCH v2 5/8] KVM: x86: wean in-kernel PIO from vcpu->arch.pio* Paolo Bonzini
2022-06-24 17:18 ` [PATCH v2 6/8] KVM: x86: wean fast IN from emulator_pio_in Paolo Bonzini
2022-06-24 17:18 ` [PATCH v2 7/8] KVM: x86: de-underscorify __emulator_pio_in Paolo Bonzini
2022-06-24 17:18 ` [PATCH v2 8/8] KVM: SEV-ES: reuse advance_sev_es_emulated_ins for OUT too Paolo Bonzini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.