All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH kvmtool v2 00/22] Unify I/O port and MMIO trap handling
@ 2021-02-25  0:58 ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:58 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

Compared to v1 this has a few fixes, as suggested by Alex.
There is a new patch 20/22, which cleans up the ARM memory map
definition and adds some chart to make it more obvious what is going on.
For a changelog, see below.

==============

At the moment we use two separate code paths to handle exits for
KVM_EXIT_IO (ioport.c) and KVM_EXIT_MMIO (mmio.c), even though they
are semantically very similar. Because the trap handler callback routine
is different, devices need to decide on one conduit or need to provide
different handler functions for both of them.

This is not only unnecessary code duplication, but makes switching
devices from I/O port to MMIO a tedious task, even though there is no
real difference between the two, especially on ARM and PowerPC.

For ARM we aim at providing a flexible memory layout, and also have
trouble with the UART and RTC device overlapping with the PCI I/O area,
so it seems indicated to tackle this once and for all.

The first three patches do some cleanup, to simplify things later.

Patch 04/22 lays the groundwork, by extending mmio.c to be able to also
register I/O port trap handlers, using the same callback prototype as
we use for MMIO.

The next 14 patches then convert devices that use the I/O port
interface over to the new joint interface. This requires to rework
the trap handler routine to adhere to the same prototype as the existing
MMIO handlers. For most devices this is done in two steps: a first to
introduce the reworked handler routine, and a second to switch to the new
joint registration routine. For some devices the first step is trivial,
so it's done in one patch.

Patch 19/22 then retires the old I/O port interface, by removing ioport.c
and friends.
Patch 20/22 uses the opportunity to clean up the memory map description,
also declares a new region (from 16MB on), where the final two patches
switch the UART and the RTC device to. They are now registered
on the MMIO "bus", when running on ARM or arm64. This moves them away
from the first 64KB, so they are not in the PCI I/O area anymore.

Please have a look and comment!

Cheers,
Andre

Changelog v1 .. v2:
- rework memory map definition
- add explicit debug output for debug I/O port
- add explicit check for MMIO coalescing on I/O ports
- drop usage of ioport__{read,write}8() from serial
- drop explicit I/O port cleanup routine (to mimic MMIO operation)
- add comment for IOTRAP_BUS_MASK
- minor cleanups / formatting changes

Andre Przywara (22):
  ioport: Remove ioport__setup_arch()
  hw/serial: Use device abstraction for FDT generator function
  ioport: Retire .generate_fdt_node functionality
  mmio: Extend handling to include ioport emulation
  hw/i8042: Clean up data types
  hw/i8042: Refactor trap handler
  hw/i8042: Switch to new trap handlers
  x86/ioport: Refactor trap handlers
  x86/ioport: Switch to new trap handlers
  hw/rtc: Refactor trap handlers
  hw/rtc: Switch to new trap handler
  hw/vesa: Switch trap handling to use MMIO handler
  hw/serial: Refactor trap handler
  hw/serial: Switch to new trap handlers
  vfio: Refactor ioport trap handler
  vfio: Switch to new ioport trap handlers
  virtio: Switch trap handling to use MMIO handler
  pci: Switch trap handling to use MMIO handler
  Remove ioport specific routines
  arm: Reorganise and document memory map
  hw/serial: ARM/arm64: Use MMIO at higher addresses
  hw/rtc: ARM/arm64: Use MMIO at higher addresses

 Makefile                          |   1 -
 arm/include/arm-common/kvm-arch.h |  47 ++++--
 arm/ioport.c                      |   5 -
 hw/i8042.c                        |  94 +++++-------
 hw/rtc.c                          |  91 ++++++------
 hw/serial.c                       | 160 ++++++++++++--------
 hw/vesa.c                         |  19 +--
 include/kvm/i8042.h               |   1 -
 include/kvm/ioport.h              |  32 ----
 include/kvm/kvm.h                 |  49 ++++++-
 ioport.c                          | 235 ------------------------------
 mips/kvm.c                        |   5 -
 mmio.c                            |  65 +++++++--
 pci.c                             |  82 +++--------
 powerpc/ioport.c                  |   6 -
 vfio/core.c                       |  50 ++++---
 virtio/pci.c                      |  46 ++----
 x86/ioport.c                      | 107 +++++++-------
 18 files changed, 433 insertions(+), 662 deletions(-)
 delete mode 100644 ioport.c

-- 
2.17.5


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

* [PATCH kvmtool v2 00/22] Unify I/O port and MMIO trap handling
@ 2021-02-25  0:58 ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:58 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Compared to v1 this has a few fixes, as suggested by Alex.
There is a new patch 20/22, which cleans up the ARM memory map
definition and adds some chart to make it more obvious what is going on.
For a changelog, see below.

==============

At the moment we use two separate code paths to handle exits for
KVM_EXIT_IO (ioport.c) and KVM_EXIT_MMIO (mmio.c), even though they
are semantically very similar. Because the trap handler callback routine
is different, devices need to decide on one conduit or need to provide
different handler functions for both of them.

This is not only unnecessary code duplication, but makes switching
devices from I/O port to MMIO a tedious task, even though there is no
real difference between the two, especially on ARM and PowerPC.

For ARM we aim at providing a flexible memory layout, and also have
trouble with the UART and RTC device overlapping with the PCI I/O area,
so it seems indicated to tackle this once and for all.

The first three patches do some cleanup, to simplify things later.

Patch 04/22 lays the groundwork, by extending mmio.c to be able to also
register I/O port trap handlers, using the same callback prototype as
we use for MMIO.

The next 14 patches then convert devices that use the I/O port
interface over to the new joint interface. This requires to rework
the trap handler routine to adhere to the same prototype as the existing
MMIO handlers. For most devices this is done in two steps: a first to
introduce the reworked handler routine, and a second to switch to the new
joint registration routine. For some devices the first step is trivial,
so it's done in one patch.

Patch 19/22 then retires the old I/O port interface, by removing ioport.c
and friends.
Patch 20/22 uses the opportunity to clean up the memory map description,
also declares a new region (from 16MB on), where the final two patches
switch the UART and the RTC device to. They are now registered
on the MMIO "bus", when running on ARM or arm64. This moves them away
from the first 64KB, so they are not in the PCI I/O area anymore.

Please have a look and comment!

Cheers,
Andre

Changelog v1 .. v2:
- rework memory map definition
- add explicit debug output for debug I/O port
- add explicit check for MMIO coalescing on I/O ports
- drop usage of ioport__{read,write}8() from serial
- drop explicit I/O port cleanup routine (to mimic MMIO operation)
- add comment for IOTRAP_BUS_MASK
- minor cleanups / formatting changes

Andre Przywara (22):
  ioport: Remove ioport__setup_arch()
  hw/serial: Use device abstraction for FDT generator function
  ioport: Retire .generate_fdt_node functionality
  mmio: Extend handling to include ioport emulation
  hw/i8042: Clean up data types
  hw/i8042: Refactor trap handler
  hw/i8042: Switch to new trap handlers
  x86/ioport: Refactor trap handlers
  x86/ioport: Switch to new trap handlers
  hw/rtc: Refactor trap handlers
  hw/rtc: Switch to new trap handler
  hw/vesa: Switch trap handling to use MMIO handler
  hw/serial: Refactor trap handler
  hw/serial: Switch to new trap handlers
  vfio: Refactor ioport trap handler
  vfio: Switch to new ioport trap handlers
  virtio: Switch trap handling to use MMIO handler
  pci: Switch trap handling to use MMIO handler
  Remove ioport specific routines
  arm: Reorganise and document memory map
  hw/serial: ARM/arm64: Use MMIO at higher addresses
  hw/rtc: ARM/arm64: Use MMIO at higher addresses

 Makefile                          |   1 -
 arm/include/arm-common/kvm-arch.h |  47 ++++--
 arm/ioport.c                      |   5 -
 hw/i8042.c                        |  94 +++++-------
 hw/rtc.c                          |  91 ++++++------
 hw/serial.c                       | 160 ++++++++++++--------
 hw/vesa.c                         |  19 +--
 include/kvm/i8042.h               |   1 -
 include/kvm/ioport.h              |  32 ----
 include/kvm/kvm.h                 |  49 ++++++-
 ioport.c                          | 235 ------------------------------
 mips/kvm.c                        |   5 -
 mmio.c                            |  65 +++++++--
 pci.c                             |  82 +++--------
 powerpc/ioport.c                  |   6 -
 vfio/core.c                       |  50 ++++---
 virtio/pci.c                      |  46 ++----
 x86/ioport.c                      | 107 +++++++-------
 18 files changed, 433 insertions(+), 662 deletions(-)
 delete mode 100644 ioport.c

-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 01/22] ioport: Remove ioport__setup_arch()
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:58   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:58 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

Since x86 had a special need for registering tons of special I/O ports,
we had an ioport__setup_arch() callback, to allow each architecture
to do the same. As it turns out no one uses it beside x86, so we remove
that unnecessary abstraction.

The generic function was registered via a device_base_init() call, so
we just do the same for the x86 specific function only, and can remove
the unneeded ioport__setup_arch().

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arm/ioport.c         | 5 -----
 include/kvm/ioport.h | 1 -
 ioport.c             | 6 ------
 mips/kvm.c           | 5 -----
 powerpc/ioport.c     | 6 ------
 x86/ioport.c         | 3 ++-
 6 files changed, 2 insertions(+), 24 deletions(-)

diff --git a/arm/ioport.c b/arm/ioport.c
index 2f0feb9a..24092c9d 100644
--- a/arm/ioport.c
+++ b/arm/ioport.c
@@ -1,11 +1,6 @@
 #include "kvm/ioport.h"
 #include "kvm/irq.h"
 
-int ioport__setup_arch(struct kvm *kvm)
-{
-	return 0;
-}
-
 void ioport__map_irq(u8 *irq)
 {
 	*irq = irq__alloc_line();
diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
index 039633f7..d0213541 100644
--- a/include/kvm/ioport.h
+++ b/include/kvm/ioport.h
@@ -35,7 +35,6 @@ struct ioport_operations {
 							    enum irq_type));
 };
 
-int ioport__setup_arch(struct kvm *kvm);
 void ioport__map_irq(u8 *irq);
 
 int __must_check ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops,
diff --git a/ioport.c b/ioport.c
index 844a832d..a6972179 100644
--- a/ioport.c
+++ b/ioport.c
@@ -221,12 +221,6 @@ out:
 	return !kvm->cfg.ioport_debug;
 }
 
-int ioport__init(struct kvm *kvm)
-{
-	return ioport__setup_arch(kvm);
-}
-dev_base_init(ioport__init);
-
 int ioport__exit(struct kvm *kvm)
 {
 	ioport__unregister_all();
diff --git a/mips/kvm.c b/mips/kvm.c
index 26355930..e110e5d5 100644
--- a/mips/kvm.c
+++ b/mips/kvm.c
@@ -100,11 +100,6 @@ void kvm__irq_trigger(struct kvm *kvm, int irq)
 		die_perror("KVM_IRQ_LINE ioctl");
 }
 
-int ioport__setup_arch(struct kvm *kvm)
-{
-	return 0;
-}
-
 bool kvm__arch_cpu_supports_vm(void)
 {
 	return true;
diff --git a/powerpc/ioport.c b/powerpc/ioport.c
index 0c188b61..a5cff4ee 100644
--- a/powerpc/ioport.c
+++ b/powerpc/ioport.c
@@ -12,12 +12,6 @@
 
 #include <stdlib.h>
 
-int ioport__setup_arch(struct kvm *kvm)
-{
-	/* PPC has no legacy ioports to set up */
-	return 0;
-}
-
 void ioport__map_irq(u8 *irq)
 {
 }
diff --git a/x86/ioport.c b/x86/ioport.c
index 7ad7b8f3..a8d2bb1a 100644
--- a/x86/ioport.c
+++ b/x86/ioport.c
@@ -69,7 +69,7 @@ void ioport__map_irq(u8 *irq)
 {
 }
 
-int ioport__setup_arch(struct kvm *kvm)
+static int ioport__setup_arch(struct kvm *kvm)
 {
 	int r;
 
@@ -150,3 +150,4 @@ int ioport__setup_arch(struct kvm *kvm)
 
 	return 0;
 }
+dev_base_init(ioport__setup_arch);
-- 
2.17.5


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

* [PATCH kvmtool v2 01/22] ioport: Remove ioport__setup_arch()
@ 2021-02-25  0:58   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:58 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Since x86 had a special need for registering tons of special I/O ports,
we had an ioport__setup_arch() callback, to allow each architecture
to do the same. As it turns out no one uses it beside x86, so we remove
that unnecessary abstraction.

The generic function was registered via a device_base_init() call, so
we just do the same for the x86 specific function only, and can remove
the unneeded ioport__setup_arch().

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arm/ioport.c         | 5 -----
 include/kvm/ioport.h | 1 -
 ioport.c             | 6 ------
 mips/kvm.c           | 5 -----
 powerpc/ioport.c     | 6 ------
 x86/ioport.c         | 3 ++-
 6 files changed, 2 insertions(+), 24 deletions(-)

diff --git a/arm/ioport.c b/arm/ioport.c
index 2f0feb9a..24092c9d 100644
--- a/arm/ioport.c
+++ b/arm/ioport.c
@@ -1,11 +1,6 @@
 #include "kvm/ioport.h"
 #include "kvm/irq.h"
 
-int ioport__setup_arch(struct kvm *kvm)
-{
-	return 0;
-}
-
 void ioport__map_irq(u8 *irq)
 {
 	*irq = irq__alloc_line();
diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
index 039633f7..d0213541 100644
--- a/include/kvm/ioport.h
+++ b/include/kvm/ioport.h
@@ -35,7 +35,6 @@ struct ioport_operations {
 							    enum irq_type));
 };
 
-int ioport__setup_arch(struct kvm *kvm);
 void ioport__map_irq(u8 *irq);
 
 int __must_check ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops,
diff --git a/ioport.c b/ioport.c
index 844a832d..a6972179 100644
--- a/ioport.c
+++ b/ioport.c
@@ -221,12 +221,6 @@ out:
 	return !kvm->cfg.ioport_debug;
 }
 
-int ioport__init(struct kvm *kvm)
-{
-	return ioport__setup_arch(kvm);
-}
-dev_base_init(ioport__init);
-
 int ioport__exit(struct kvm *kvm)
 {
 	ioport__unregister_all();
diff --git a/mips/kvm.c b/mips/kvm.c
index 26355930..e110e5d5 100644
--- a/mips/kvm.c
+++ b/mips/kvm.c
@@ -100,11 +100,6 @@ void kvm__irq_trigger(struct kvm *kvm, int irq)
 		die_perror("KVM_IRQ_LINE ioctl");
 }
 
-int ioport__setup_arch(struct kvm *kvm)
-{
-	return 0;
-}
-
 bool kvm__arch_cpu_supports_vm(void)
 {
 	return true;
diff --git a/powerpc/ioport.c b/powerpc/ioport.c
index 0c188b61..a5cff4ee 100644
--- a/powerpc/ioport.c
+++ b/powerpc/ioport.c
@@ -12,12 +12,6 @@
 
 #include <stdlib.h>
 
-int ioport__setup_arch(struct kvm *kvm)
-{
-	/* PPC has no legacy ioports to set up */
-	return 0;
-}
-
 void ioport__map_irq(u8 *irq)
 {
 }
diff --git a/x86/ioport.c b/x86/ioport.c
index 7ad7b8f3..a8d2bb1a 100644
--- a/x86/ioport.c
+++ b/x86/ioport.c
@@ -69,7 +69,7 @@ void ioport__map_irq(u8 *irq)
 {
 }
 
-int ioport__setup_arch(struct kvm *kvm)
+static int ioport__setup_arch(struct kvm *kvm)
 {
 	int r;
 
@@ -150,3 +150,4 @@ int ioport__setup_arch(struct kvm *kvm)
 
 	return 0;
 }
+dev_base_init(ioport__setup_arch);
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 02/22] hw/serial: Use device abstraction for FDT generator function
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:58   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:58 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

At the moment we use the .generate_fdt_node member of the ioport ops
structure to store the function pointer for the FDT node generator
function. ioport__register() will then put a wrapper and this pointer
into the device header.
The serial device is the only device making use of this special ioport
feature, so let's move this over to using the device header directly.

This will allow us to get rid of this .generate_fdt_node member in the
ops and simplify the code.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 hw/serial.c       | 49 +++++++++++++++++++++++++++++++++++++----------
 include/kvm/kvm.h |  2 ++
 2 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/hw/serial.c b/hw/serial.c
index 13c4663e..b0465d99 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -23,6 +23,7 @@
 #define UART_IIR_TYPE_BITS	0xc0
 
 struct serial8250_device {
+	struct device_header	dev_hdr;
 	struct mutex		mutex;
 	u8			id;
 
@@ -53,9 +54,20 @@ struct serial8250_device {
 	.msr			= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS, \
 	.mcr			= UART_MCR_OUT2,
 
+#ifdef CONFIG_HAS_LIBFDT
+static
+void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
+				  fdt_irq_fn irq_fn);
+#else
+#define serial8250_generate_fdt_node	NULL
+#endif
 static struct serial8250_device devices[] = {
 	/* ttyS0 */
 	[0]	= {
+		.dev_hdr = {
+			.bus_type	= DEVICE_BUS_IOPORT,
+			.data		= serial8250_generate_fdt_node,
+		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 0,
@@ -66,6 +78,10 @@ static struct serial8250_device devices[] = {
 	},
 	/* ttyS1 */
 	[1]	= {
+		.dev_hdr = {
+			.bus_type	= DEVICE_BUS_IOPORT,
+			.data		= serial8250_generate_fdt_node,
+		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 1,
@@ -76,6 +92,10 @@ static struct serial8250_device devices[] = {
 	},
 	/* ttyS2 */
 	[2]	= {
+		.dev_hdr = {
+			.bus_type	= DEVICE_BUS_IOPORT,
+			.data		= serial8250_generate_fdt_node,
+		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 2,
@@ -86,6 +106,10 @@ static struct serial8250_device devices[] = {
 	},
 	/* ttyS3 */
 	[3]	= {
+		.dev_hdr = {
+			.bus_type	= DEVICE_BUS_IOPORT,
+			.data		= serial8250_generate_fdt_node,
+		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 3,
@@ -371,13 +395,14 @@ char *fdt_stdout_path = NULL;
 
 #define DEVICE_NAME_MAX_LEN 32
 static
-void serial8250_generate_fdt_node(struct ioport *ioport, void *fdt,
-				  void (*generate_irq_prop)(void *fdt,
-							    u8 irq,
-							    enum irq_type))
+void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
+				  fdt_irq_fn irq_fn)
 {
 	char dev_name[DEVICE_NAME_MAX_LEN];
-	struct serial8250_device *dev = ioport->priv;
+	struct serial8250_device *dev = container_of(dev_hdr,
+						     struct serial8250_device,
+						     dev_hdr);
+
 	u64 addr = KVM_IOPORT_AREA + dev->iobase;
 	u64 reg_prop[] = {
 		cpu_to_fdt64(addr),
@@ -395,24 +420,26 @@ void serial8250_generate_fdt_node(struct ioport *ioport, void *fdt,
 	_FDT(fdt_begin_node(fdt, dev_name));
 	_FDT(fdt_property_string(fdt, "compatible", "ns16550a"));
 	_FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop)));
-	generate_irq_prop(fdt, dev->irq, IRQ_TYPE_LEVEL_HIGH);
+	irq_fn(fdt, dev->irq, IRQ_TYPE_LEVEL_HIGH);
 	_FDT(fdt_property_cell(fdt, "clock-frequency", 1843200));
 	_FDT(fdt_end_node(fdt));
 }
-#else
-#define serial8250_generate_fdt_node	NULL
 #endif
 
 static struct ioport_operations serial8250_ops = {
 	.io_in			= serial8250_in,
 	.io_out			= serial8250_out,
-	.generate_fdt_node	= serial8250_generate_fdt_node,
 };
 
-static int serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev)
+static int serial8250__device_init(struct kvm *kvm,
+				   struct serial8250_device *dev)
 {
 	int r;
 
+	r = device__register(&dev->dev_hdr);
+	if (r < 0)
+		return r;
+
 	ioport__map_irq(&dev->irq);
 	r = ioport__register(kvm, dev->iobase, &serial8250_ops, 8, dev);
 
@@ -438,6 +465,7 @@ cleanup:
 		struct serial8250_device *dev = &devices[j];
 
 		ioport__unregister(kvm, dev->iobase);
+		device__unregister(&dev->dev_hdr);
 	}
 
 	return r;
@@ -455,6 +483,7 @@ int serial8250__exit(struct kvm *kvm)
 		r = ioport__unregister(kvm, dev->iobase);
 		if (r < 0)
 			return r;
+		device__unregister(&dev->dev_hdr);
 	}
 
 	return 0;
diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
index 53373b08..f1f0afd7 100644
--- a/include/kvm/kvm.h
+++ b/include/kvm/kvm.h
@@ -31,6 +31,8 @@
 	.name = #ext,			\
 	.code = ext
 
+typedef void (*fdt_irq_fn)(void *fdt, u8 irq, enum irq_type irq_type);
+
 enum {
 	KVM_VMSTATE_RUNNING,
 	KVM_VMSTATE_PAUSED,
-- 
2.17.5


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

* [PATCH kvmtool v2 02/22] hw/serial: Use device abstraction for FDT generator function
@ 2021-02-25  0:58   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:58 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

At the moment we use the .generate_fdt_node member of the ioport ops
structure to store the function pointer for the FDT node generator
function. ioport__register() will then put a wrapper and this pointer
into the device header.
The serial device is the only device making use of this special ioport
feature, so let's move this over to using the device header directly.

This will allow us to get rid of this .generate_fdt_node member in the
ops and simplify the code.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 hw/serial.c       | 49 +++++++++++++++++++++++++++++++++++++----------
 include/kvm/kvm.h |  2 ++
 2 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/hw/serial.c b/hw/serial.c
index 13c4663e..b0465d99 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -23,6 +23,7 @@
 #define UART_IIR_TYPE_BITS	0xc0
 
 struct serial8250_device {
+	struct device_header	dev_hdr;
 	struct mutex		mutex;
 	u8			id;
 
@@ -53,9 +54,20 @@ struct serial8250_device {
 	.msr			= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS, \
 	.mcr			= UART_MCR_OUT2,
 
+#ifdef CONFIG_HAS_LIBFDT
+static
+void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
+				  fdt_irq_fn irq_fn);
+#else
+#define serial8250_generate_fdt_node	NULL
+#endif
 static struct serial8250_device devices[] = {
 	/* ttyS0 */
 	[0]	= {
+		.dev_hdr = {
+			.bus_type	= DEVICE_BUS_IOPORT,
+			.data		= serial8250_generate_fdt_node,
+		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 0,
@@ -66,6 +78,10 @@ static struct serial8250_device devices[] = {
 	},
 	/* ttyS1 */
 	[1]	= {
+		.dev_hdr = {
+			.bus_type	= DEVICE_BUS_IOPORT,
+			.data		= serial8250_generate_fdt_node,
+		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 1,
@@ -76,6 +92,10 @@ static struct serial8250_device devices[] = {
 	},
 	/* ttyS2 */
 	[2]	= {
+		.dev_hdr = {
+			.bus_type	= DEVICE_BUS_IOPORT,
+			.data		= serial8250_generate_fdt_node,
+		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 2,
@@ -86,6 +106,10 @@ static struct serial8250_device devices[] = {
 	},
 	/* ttyS3 */
 	[3]	= {
+		.dev_hdr = {
+			.bus_type	= DEVICE_BUS_IOPORT,
+			.data		= serial8250_generate_fdt_node,
+		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 3,
@@ -371,13 +395,14 @@ char *fdt_stdout_path = NULL;
 
 #define DEVICE_NAME_MAX_LEN 32
 static
-void serial8250_generate_fdt_node(struct ioport *ioport, void *fdt,
-				  void (*generate_irq_prop)(void *fdt,
-							    u8 irq,
-							    enum irq_type))
+void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
+				  fdt_irq_fn irq_fn)
 {
 	char dev_name[DEVICE_NAME_MAX_LEN];
-	struct serial8250_device *dev = ioport->priv;
+	struct serial8250_device *dev = container_of(dev_hdr,
+						     struct serial8250_device,
+						     dev_hdr);
+
 	u64 addr = KVM_IOPORT_AREA + dev->iobase;
 	u64 reg_prop[] = {
 		cpu_to_fdt64(addr),
@@ -395,24 +420,26 @@ void serial8250_generate_fdt_node(struct ioport *ioport, void *fdt,
 	_FDT(fdt_begin_node(fdt, dev_name));
 	_FDT(fdt_property_string(fdt, "compatible", "ns16550a"));
 	_FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop)));
-	generate_irq_prop(fdt, dev->irq, IRQ_TYPE_LEVEL_HIGH);
+	irq_fn(fdt, dev->irq, IRQ_TYPE_LEVEL_HIGH);
 	_FDT(fdt_property_cell(fdt, "clock-frequency", 1843200));
 	_FDT(fdt_end_node(fdt));
 }
-#else
-#define serial8250_generate_fdt_node	NULL
 #endif
 
 static struct ioport_operations serial8250_ops = {
 	.io_in			= serial8250_in,
 	.io_out			= serial8250_out,
-	.generate_fdt_node	= serial8250_generate_fdt_node,
 };
 
-static int serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev)
+static int serial8250__device_init(struct kvm *kvm,
+				   struct serial8250_device *dev)
 {
 	int r;
 
+	r = device__register(&dev->dev_hdr);
+	if (r < 0)
+		return r;
+
 	ioport__map_irq(&dev->irq);
 	r = ioport__register(kvm, dev->iobase, &serial8250_ops, 8, dev);
 
@@ -438,6 +465,7 @@ cleanup:
 		struct serial8250_device *dev = &devices[j];
 
 		ioport__unregister(kvm, dev->iobase);
+		device__unregister(&dev->dev_hdr);
 	}
 
 	return r;
@@ -455,6 +483,7 @@ int serial8250__exit(struct kvm *kvm)
 		r = ioport__unregister(kvm, dev->iobase);
 		if (r < 0)
 			return r;
+		device__unregister(&dev->dev_hdr);
 	}
 
 	return 0;
diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
index 53373b08..f1f0afd7 100644
--- a/include/kvm/kvm.h
+++ b/include/kvm/kvm.h
@@ -31,6 +31,8 @@
 	.name = #ext,			\
 	.code = ext
 
+typedef void (*fdt_irq_fn)(void *fdt, u8 irq, enum irq_type irq_type);
+
 enum {
 	KVM_VMSTATE_RUNNING,
 	KVM_VMSTATE_PAUSED,
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 03/22] ioport: Retire .generate_fdt_node functionality
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:58   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:58 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

The ioport routines support a special way of registering FDT node
generator functions. There is no reason to have this separate from the
already existing way via the device header.

Now that the only user of this special ioport variety has been
transferred, we can retire this code, to simplify ioport handling.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 include/kvm/ioport.h |  4 ----
 ioport.c             | 34 ----------------------------------
 2 files changed, 38 deletions(-)

diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
index d0213541..a61038e2 100644
--- a/include/kvm/ioport.h
+++ b/include/kvm/ioport.h
@@ -29,10 +29,6 @@ struct ioport {
 struct ioport_operations {
 	bool (*io_in)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size);
 	bool (*io_out)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size);
-	void (*generate_fdt_node)(struct ioport *ioport, void *fdt,
-				  void (*generate_irq_prop)(void *fdt,
-							    u8 irq,
-							    enum irq_type));
 };
 
 void ioport__map_irq(u8 *irq);
diff --git a/ioport.c b/ioport.c
index a6972179..e0123f27 100644
--- a/ioport.c
+++ b/ioport.c
@@ -56,7 +56,6 @@ static struct ioport *ioport_get(struct rb_root *root, u64 addr)
 /* Called with ioport_lock held. */
 static void ioport_unregister(struct rb_root *root, struct ioport *data)
 {
-	device__unregister(&data->dev_hdr);
 	ioport_remove(root, data);
 	free(data);
 }
@@ -70,30 +69,6 @@ static void ioport_put(struct rb_root *root, struct ioport *data)
 	mutex_unlock(&ioport_lock);
 }
 
-#ifdef CONFIG_HAS_LIBFDT
-static void generate_ioport_fdt_node(void *fdt,
-				     struct device_header *dev_hdr,
-				     void (*generate_irq_prop)(void *fdt,
-							       u8 irq,
-							       enum irq_type))
-{
-	struct ioport *ioport = container_of(dev_hdr, struct ioport, dev_hdr);
-	struct ioport_operations *ops = ioport->ops;
-
-	if (ops->generate_fdt_node)
-		ops->generate_fdt_node(ioport, fdt, generate_irq_prop);
-}
-#else
-static void generate_ioport_fdt_node(void *fdt,
-				     struct device_header *dev_hdr,
-				     void (*generate_irq_prop)(void *fdt,
-							       u8 irq,
-							       enum irq_type))
-{
-	die("Unable to generate device tree nodes without libfdt\n");
-}
-#endif
-
 int ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops, int count, void *param)
 {
 	struct ioport *entry;
@@ -107,10 +82,6 @@ int ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops, i
 		.node		= RB_INT_INIT(port, port + count),
 		.ops		= ops,
 		.priv		= param,
-		.dev_hdr	= (struct device_header) {
-			.bus_type	= DEVICE_BUS_IOPORT,
-			.data		= generate_ioport_fdt_node,
-		},
 		/*
 		 * Start from 0 because ioport__unregister() doesn't decrement
 		 * the reference count.
@@ -123,15 +94,10 @@ int ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops, i
 	r = ioport_insert(&ioport_tree, entry);
 	if (r < 0)
 		goto out_free;
-	r = device__register(&entry->dev_hdr);
-	if (r < 0)
-		goto out_remove;
 	mutex_unlock(&ioport_lock);
 
 	return port;
 
-out_remove:
-	ioport_remove(&ioport_tree, entry);
 out_free:
 	free(entry);
 	mutex_unlock(&ioport_lock);
-- 
2.17.5


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

* [PATCH kvmtool v2 03/22] ioport: Retire .generate_fdt_node functionality
@ 2021-02-25  0:58   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:58 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

The ioport routines support a special way of registering FDT node
generator functions. There is no reason to have this separate from the
already existing way via the device header.

Now that the only user of this special ioport variety has been
transferred, we can retire this code, to simplify ioport handling.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 include/kvm/ioport.h |  4 ----
 ioport.c             | 34 ----------------------------------
 2 files changed, 38 deletions(-)

diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
index d0213541..a61038e2 100644
--- a/include/kvm/ioport.h
+++ b/include/kvm/ioport.h
@@ -29,10 +29,6 @@ struct ioport {
 struct ioport_operations {
 	bool (*io_in)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size);
 	bool (*io_out)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size);
-	void (*generate_fdt_node)(struct ioport *ioport, void *fdt,
-				  void (*generate_irq_prop)(void *fdt,
-							    u8 irq,
-							    enum irq_type));
 };
 
 void ioport__map_irq(u8 *irq);
diff --git a/ioport.c b/ioport.c
index a6972179..e0123f27 100644
--- a/ioport.c
+++ b/ioport.c
@@ -56,7 +56,6 @@ static struct ioport *ioport_get(struct rb_root *root, u64 addr)
 /* Called with ioport_lock held. */
 static void ioport_unregister(struct rb_root *root, struct ioport *data)
 {
-	device__unregister(&data->dev_hdr);
 	ioport_remove(root, data);
 	free(data);
 }
@@ -70,30 +69,6 @@ static void ioport_put(struct rb_root *root, struct ioport *data)
 	mutex_unlock(&ioport_lock);
 }
 
-#ifdef CONFIG_HAS_LIBFDT
-static void generate_ioport_fdt_node(void *fdt,
-				     struct device_header *dev_hdr,
-				     void (*generate_irq_prop)(void *fdt,
-							       u8 irq,
-							       enum irq_type))
-{
-	struct ioport *ioport = container_of(dev_hdr, struct ioport, dev_hdr);
-	struct ioport_operations *ops = ioport->ops;
-
-	if (ops->generate_fdt_node)
-		ops->generate_fdt_node(ioport, fdt, generate_irq_prop);
-}
-#else
-static void generate_ioport_fdt_node(void *fdt,
-				     struct device_header *dev_hdr,
-				     void (*generate_irq_prop)(void *fdt,
-							       u8 irq,
-							       enum irq_type))
-{
-	die("Unable to generate device tree nodes without libfdt\n");
-}
-#endif
-
 int ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops, int count, void *param)
 {
 	struct ioport *entry;
@@ -107,10 +82,6 @@ int ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops, i
 		.node		= RB_INT_INIT(port, port + count),
 		.ops		= ops,
 		.priv		= param,
-		.dev_hdr	= (struct device_header) {
-			.bus_type	= DEVICE_BUS_IOPORT,
-			.data		= generate_ioport_fdt_node,
-		},
 		/*
 		 * Start from 0 because ioport__unregister() doesn't decrement
 		 * the reference count.
@@ -123,15 +94,10 @@ int ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops, i
 	r = ioport_insert(&ioport_tree, entry);
 	if (r < 0)
 		goto out_free;
-	r = device__register(&entry->dev_hdr);
-	if (r < 0)
-		goto out_remove;
 	mutex_unlock(&ioport_lock);
 
 	return port;
 
-out_remove:
-	ioport_remove(&ioport_tree, entry);
 out_free:
 	free(entry);
 	mutex_unlock(&ioport_lock);
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 04/22] mmio: Extend handling to include ioport emulation
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:58   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:58 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

In their core functionality MMIO and I/O port traps are not really
different, yet we still have two totally separate code paths for
handling them. Devices need to decide on one conduit or need to provide
different handler functions for each of them.

Extend the existing MMIO emulation to also cover ioport handlers.
This just adds another RB tree root for holding the I/O port handlers,
but otherwise uses the same tree population and lookup code.
"ioport" or "mmio" just become a flag in the registration function.
Provide wrappers to not break existing users, and allow an easy
transition for the existing ioport handlers.

This also means that ioport handlers now can use the same emulation
callback prototype as MMIO handlers, which means we have to migrate them
over. To allow a smooth transition, we hook up the new I/O emulate
function to the end of the existing ioport emulation code.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 include/kvm/kvm.h | 49 ++++++++++++++++++++++++++++++++---
 ioport.c          |  4 +--
 mmio.c            | 65 +++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 102 insertions(+), 16 deletions(-)

diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
index f1f0afd7..306b258a 100644
--- a/include/kvm/kvm.h
+++ b/include/kvm/kvm.h
@@ -27,10 +27,23 @@
 #define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
 #endif
 
+/*
+ * We are reusing the existing DEVICE_BUS_MMIO and DEVICE_BUS_IOPORT constants
+ * from kvm/devices.h to differentiate between registering an I/O port and an
+ * MMIO region.
+ * To avoid collisions with future additions of more bus types, we reserve
+ * a generous 4 bits for the bus mask here.
+ */
+#define IOTRAP_BUS_MASK		0xf
+#define IOTRAP_COALESCE		(1U << 4)
+
 #define DEFINE_KVM_EXT(ext)		\
 	.name = #ext,			\
 	.code = ext
 
+struct kvm_cpu;
+typedef void (*mmio_handler_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+				u32 len, u8 is_write, void *ptr);
 typedef void (*fdt_irq_fn)(void *fdt, u8 irq, enum irq_type irq_type);
 
 enum {
@@ -113,6 +126,8 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
 void kvm__irq_trigger(struct kvm *kvm, int irq);
 bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count);
 bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write);
+bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
+		      int direction, int size, u32 count);
 int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr);
 int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr,
 		      enum kvm_mem_type type);
@@ -136,10 +151,36 @@ static inline int kvm__reserve_mem(struct kvm *kvm, u64 guest_phys, u64 size)
 				 KVM_MEM_TYPE_RESERVED);
 }
 
-int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
-				    void (*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
-				    void *ptr);
-bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
+int __must_check kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 len,
+				      mmio_handler_fn mmio_fn, void *ptr,
+				      unsigned int flags);
+
+static inline
+int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr,
+				    u64 phys_addr_len, bool coalesce,
+				    mmio_handler_fn mmio_fn, void *ptr)
+{
+	return kvm__register_iotrap(kvm, phys_addr, phys_addr_len, mmio_fn, ptr,
+			DEVICE_BUS_MMIO | (coalesce ? IOTRAP_COALESCE : 0));
+}
+static inline
+int __must_check kvm__register_pio(struct kvm *kvm, u16 port, u16 len,
+				   mmio_handler_fn mmio_fn, void *ptr)
+{
+	return kvm__register_iotrap(kvm, port, len, mmio_fn, ptr,
+				    DEVICE_BUS_IOPORT);
+}
+
+bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int flags);
+static inline bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
+{
+	return kvm__deregister_iotrap(kvm, phys_addr, DEVICE_BUS_MMIO);
+}
+static inline bool kvm__deregister_pio(struct kvm *kvm, u16 port)
+{
+	return kvm__deregister_iotrap(kvm, port, DEVICE_BUS_IOPORT);
+}
+
 void kvm__reboot(struct kvm *kvm);
 void kvm__pause(struct kvm *kvm);
 void kvm__continue(struct kvm *kvm);
diff --git a/ioport.c b/ioport.c
index e0123f27..ce29e7e7 100644
--- a/ioport.c
+++ b/ioport.c
@@ -162,7 +162,8 @@ bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction,
 
 	entry = ioport_get(&ioport_tree, port);
 	if (!entry)
-		goto out;
+		return kvm__emulate_pio(vcpu, port, data, direction,
+					size, count);
 
 	ops	= entry->ops;
 
@@ -177,7 +178,6 @@ bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction,
 
 	ioport_put(&ioport_tree, entry);
 
-out:
 	if (ret)
 		return true;
 
diff --git a/mmio.c b/mmio.c
index cd141cd3..75de04ad 100644
--- a/mmio.c
+++ b/mmio.c
@@ -19,13 +19,14 @@ static DEFINE_MUTEX(mmio_lock);
 
 struct mmio_mapping {
 	struct rb_int_node	node;
-	void			(*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr);
+	mmio_handler_fn		mmio_fn;
 	void			*ptr;
 	u32			refcount;
 	bool			remove;
 };
 
 static struct rb_root mmio_tree = RB_ROOT;
+static struct rb_root pio_tree = RB_ROOT;
 
 static struct mmio_mapping *mmio_search(struct rb_root *root, u64 addr, u64 len)
 {
@@ -103,9 +104,14 @@ static void mmio_put(struct kvm *kvm, struct rb_root *root, struct mmio_mapping
 	mutex_unlock(&mmio_lock);
 }
 
-int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
-		       void (*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
-			void *ptr)
+static bool trap_is_mmio(unsigned int flags)
+{
+	return (flags & IOTRAP_BUS_MASK) == DEVICE_BUS_MMIO;
+}
+
+int kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len,
+			 mmio_handler_fn mmio_fn, void *ptr,
+			 unsigned int flags)
 {
 	struct mmio_mapping *mmio;
 	struct kvm_coalesced_mmio_zone zone;
@@ -127,7 +133,7 @@ int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool c
 		.remove		= false,
 	};
 
-	if (coalesce) {
+	if (trap_is_mmio(flags) && (flags & IOTRAP_COALESCE)) {
 		zone = (struct kvm_coalesced_mmio_zone) {
 			.addr	= phys_addr,
 			.size	= phys_addr_len,
@@ -138,19 +144,29 @@ int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool c
 			return -errno;
 		}
 	}
+
 	mutex_lock(&mmio_lock);
-	ret = mmio_insert(&mmio_tree, mmio);
+	if (trap_is_mmio(flags))
+		ret = mmio_insert(&mmio_tree, mmio);
+	else
+		ret = mmio_insert(&pio_tree, mmio);
 	mutex_unlock(&mmio_lock);
 
 	return ret;
 }
 
-bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
+bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int flags)
 {
 	struct mmio_mapping *mmio;
+	struct rb_root *tree;
+
+	if ((flags & IOTRAP_BUS_MASK) == DEVICE_BUS_IOPORT)
+		tree = &pio_tree;
+	else
+		tree = &mmio_tree;
 
 	mutex_lock(&mmio_lock);
-	mmio = mmio_search_single(&mmio_tree, phys_addr);
+	mmio = mmio_search_single(tree, phys_addr);
 	if (mmio == NULL) {
 		mutex_unlock(&mmio_lock);
 		return false;
@@ -167,7 +183,7 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
 	 * called mmio_put(). This will trigger use-after-free errors on VCPU0.
 	 */
 	if (mmio->refcount == 0)
-		mmio_deregister(kvm, &mmio_tree, mmio);
+		mmio_deregister(kvm, tree, mmio);
 	else
 		mmio->remove = true;
 	mutex_unlock(&mmio_lock);
@@ -175,7 +191,8 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
 	return true;
 }
 
-bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write)
+bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data,
+		       u32 len, u8 is_write)
 {
 	struct mmio_mapping *mmio;
 
@@ -194,3 +211,31 @@ bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u
 out:
 	return true;
 }
+
+bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
+		     int direction, int size, u32 count)
+{
+	struct mmio_mapping *mmio;
+	bool is_write = direction == KVM_EXIT_IO_OUT;
+
+	mmio = mmio_get(&pio_tree, port, size);
+	if (!mmio) {
+		if (vcpu->kvm->cfg.ioport_debug) {
+			fprintf(stderr, "IO error: %s port=%x, size=%d, count=%u\n",
+				to_direction(direction), port, size, count);
+
+			return false;
+		}
+		return true;
+	}
+
+	while (count--) {
+		mmio->mmio_fn(vcpu, port, data, size, is_write, mmio->ptr);
+
+		data += size;
+	}
+
+	mmio_put(vcpu->kvm, &pio_tree, mmio);
+
+	return true;
+}
-- 
2.17.5


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

* [PATCH kvmtool v2 04/22] mmio: Extend handling to include ioport emulation
@ 2021-02-25  0:58   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:58 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

In their core functionality MMIO and I/O port traps are not really
different, yet we still have two totally separate code paths for
handling them. Devices need to decide on one conduit or need to provide
different handler functions for each of them.

Extend the existing MMIO emulation to also cover ioport handlers.
This just adds another RB tree root for holding the I/O port handlers,
but otherwise uses the same tree population and lookup code.
"ioport" or "mmio" just become a flag in the registration function.
Provide wrappers to not break existing users, and allow an easy
transition for the existing ioport handlers.

This also means that ioport handlers now can use the same emulation
callback prototype as MMIO handlers, which means we have to migrate them
over. To allow a smooth transition, we hook up the new I/O emulate
function to the end of the existing ioport emulation code.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 include/kvm/kvm.h | 49 ++++++++++++++++++++++++++++++++---
 ioport.c          |  4 +--
 mmio.c            | 65 +++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 102 insertions(+), 16 deletions(-)

diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
index f1f0afd7..306b258a 100644
--- a/include/kvm/kvm.h
+++ b/include/kvm/kvm.h
@@ -27,10 +27,23 @@
 #define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
 #endif
 
+/*
+ * We are reusing the existing DEVICE_BUS_MMIO and DEVICE_BUS_IOPORT constants
+ * from kvm/devices.h to differentiate between registering an I/O port and an
+ * MMIO region.
+ * To avoid collisions with future additions of more bus types, we reserve
+ * a generous 4 bits for the bus mask here.
+ */
+#define IOTRAP_BUS_MASK		0xf
+#define IOTRAP_COALESCE		(1U << 4)
+
 #define DEFINE_KVM_EXT(ext)		\
 	.name = #ext,			\
 	.code = ext
 
+struct kvm_cpu;
+typedef void (*mmio_handler_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+				u32 len, u8 is_write, void *ptr);
 typedef void (*fdt_irq_fn)(void *fdt, u8 irq, enum irq_type irq_type);
 
 enum {
@@ -113,6 +126,8 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
 void kvm__irq_trigger(struct kvm *kvm, int irq);
 bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count);
 bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write);
+bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
+		      int direction, int size, u32 count);
 int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr);
 int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr,
 		      enum kvm_mem_type type);
@@ -136,10 +151,36 @@ static inline int kvm__reserve_mem(struct kvm *kvm, u64 guest_phys, u64 size)
 				 KVM_MEM_TYPE_RESERVED);
 }
 
-int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
-				    void (*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
-				    void *ptr);
-bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
+int __must_check kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 len,
+				      mmio_handler_fn mmio_fn, void *ptr,
+				      unsigned int flags);
+
+static inline
+int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr,
+				    u64 phys_addr_len, bool coalesce,
+				    mmio_handler_fn mmio_fn, void *ptr)
+{
+	return kvm__register_iotrap(kvm, phys_addr, phys_addr_len, mmio_fn, ptr,
+			DEVICE_BUS_MMIO | (coalesce ? IOTRAP_COALESCE : 0));
+}
+static inline
+int __must_check kvm__register_pio(struct kvm *kvm, u16 port, u16 len,
+				   mmio_handler_fn mmio_fn, void *ptr)
+{
+	return kvm__register_iotrap(kvm, port, len, mmio_fn, ptr,
+				    DEVICE_BUS_IOPORT);
+}
+
+bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int flags);
+static inline bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
+{
+	return kvm__deregister_iotrap(kvm, phys_addr, DEVICE_BUS_MMIO);
+}
+static inline bool kvm__deregister_pio(struct kvm *kvm, u16 port)
+{
+	return kvm__deregister_iotrap(kvm, port, DEVICE_BUS_IOPORT);
+}
+
 void kvm__reboot(struct kvm *kvm);
 void kvm__pause(struct kvm *kvm);
 void kvm__continue(struct kvm *kvm);
diff --git a/ioport.c b/ioport.c
index e0123f27..ce29e7e7 100644
--- a/ioport.c
+++ b/ioport.c
@@ -162,7 +162,8 @@ bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction,
 
 	entry = ioport_get(&ioport_tree, port);
 	if (!entry)
-		goto out;
+		return kvm__emulate_pio(vcpu, port, data, direction,
+					size, count);
 
 	ops	= entry->ops;
 
@@ -177,7 +178,6 @@ bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction,
 
 	ioport_put(&ioport_tree, entry);
 
-out:
 	if (ret)
 		return true;
 
diff --git a/mmio.c b/mmio.c
index cd141cd3..75de04ad 100644
--- a/mmio.c
+++ b/mmio.c
@@ -19,13 +19,14 @@ static DEFINE_MUTEX(mmio_lock);
 
 struct mmio_mapping {
 	struct rb_int_node	node;
-	void			(*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr);
+	mmio_handler_fn		mmio_fn;
 	void			*ptr;
 	u32			refcount;
 	bool			remove;
 };
 
 static struct rb_root mmio_tree = RB_ROOT;
+static struct rb_root pio_tree = RB_ROOT;
 
 static struct mmio_mapping *mmio_search(struct rb_root *root, u64 addr, u64 len)
 {
@@ -103,9 +104,14 @@ static void mmio_put(struct kvm *kvm, struct rb_root *root, struct mmio_mapping
 	mutex_unlock(&mmio_lock);
 }
 
-int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
-		       void (*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
-			void *ptr)
+static bool trap_is_mmio(unsigned int flags)
+{
+	return (flags & IOTRAP_BUS_MASK) == DEVICE_BUS_MMIO;
+}
+
+int kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len,
+			 mmio_handler_fn mmio_fn, void *ptr,
+			 unsigned int flags)
 {
 	struct mmio_mapping *mmio;
 	struct kvm_coalesced_mmio_zone zone;
@@ -127,7 +133,7 @@ int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool c
 		.remove		= false,
 	};
 
-	if (coalesce) {
+	if (trap_is_mmio(flags) && (flags & IOTRAP_COALESCE)) {
 		zone = (struct kvm_coalesced_mmio_zone) {
 			.addr	= phys_addr,
 			.size	= phys_addr_len,
@@ -138,19 +144,29 @@ int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool c
 			return -errno;
 		}
 	}
+
 	mutex_lock(&mmio_lock);
-	ret = mmio_insert(&mmio_tree, mmio);
+	if (trap_is_mmio(flags))
+		ret = mmio_insert(&mmio_tree, mmio);
+	else
+		ret = mmio_insert(&pio_tree, mmio);
 	mutex_unlock(&mmio_lock);
 
 	return ret;
 }
 
-bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
+bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int flags)
 {
 	struct mmio_mapping *mmio;
+	struct rb_root *tree;
+
+	if ((flags & IOTRAP_BUS_MASK) == DEVICE_BUS_IOPORT)
+		tree = &pio_tree;
+	else
+		tree = &mmio_tree;
 
 	mutex_lock(&mmio_lock);
-	mmio = mmio_search_single(&mmio_tree, phys_addr);
+	mmio = mmio_search_single(tree, phys_addr);
 	if (mmio == NULL) {
 		mutex_unlock(&mmio_lock);
 		return false;
@@ -167,7 +183,7 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
 	 * called mmio_put(). This will trigger use-after-free errors on VCPU0.
 	 */
 	if (mmio->refcount == 0)
-		mmio_deregister(kvm, &mmio_tree, mmio);
+		mmio_deregister(kvm, tree, mmio);
 	else
 		mmio->remove = true;
 	mutex_unlock(&mmio_lock);
@@ -175,7 +191,8 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
 	return true;
 }
 
-bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write)
+bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data,
+		       u32 len, u8 is_write)
 {
 	struct mmio_mapping *mmio;
 
@@ -194,3 +211,31 @@ bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u
 out:
 	return true;
 }
+
+bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
+		     int direction, int size, u32 count)
+{
+	struct mmio_mapping *mmio;
+	bool is_write = direction == KVM_EXIT_IO_OUT;
+
+	mmio = mmio_get(&pio_tree, port, size);
+	if (!mmio) {
+		if (vcpu->kvm->cfg.ioport_debug) {
+			fprintf(stderr, "IO error: %s port=%x, size=%d, count=%u\n",
+				to_direction(direction), port, size, count);
+
+			return false;
+		}
+		return true;
+	}
+
+	while (count--) {
+		mmio->mmio_fn(vcpu, port, data, size, is_write, mmio->ptr);
+
+		data += size;
+	}
+
+	mmio_put(vcpu->kvm, &pio_tree, mmio);
+
+	return true;
+}
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 05/22] hw/i8042: Clean up data types
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:58   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:58 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

The i8042 is clearly an 8-bit era device, so there is little room for
32-bit registers.
Clean up the data types used.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 hw/i8042.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/hw/i8042.c b/hw/i8042.c
index 37a99a2d..7d1f9772 100644
--- a/hw/i8042.c
+++ b/hw/i8042.c
@@ -64,11 +64,11 @@
 struct kbd_state {
 	struct kvm		*kvm;
 
-	char			kq[QUEUE_SIZE];	/* Keyboard queue */
+	u8			kq[QUEUE_SIZE];	/* Keyboard queue */
 	int			kread, kwrite;	/* Indexes into the queue */
 	int			kcount;		/* number of elements in queue */
 
-	char			mq[QUEUE_SIZE];
+	u8			mq[QUEUE_SIZE];
 	int			mread, mwrite;
 	int			mcount;
 
@@ -82,7 +82,7 @@ struct kbd_state {
 	 * Some commands (on port 0x64) have arguments;
 	 * we store the command here while we wait for the argument
 	 */
-	u32			write_cmd;
+	u8			write_cmd;
 };
 
 static struct kbd_state		state;
@@ -173,9 +173,9 @@ static void kbd_write_command(struct kvm *kvm, u8 val)
 /*
  * Called when the OS reads from port 0x60 (PS/2 data)
  */
-static u32 kbd_read_data(void)
+static u8 kbd_read_data(void)
 {
-	u32 ret;
+	u8 ret;
 	int i;
 
 	if (state.kcount != 0) {
@@ -202,9 +202,9 @@ static u32 kbd_read_data(void)
 /*
  * Called when the OS read from port 0x64, the command port
  */
-static u32 kbd_read_status(void)
+static u8 kbd_read_status(void)
 {
-	return (u32)state.status;
+	return state.status;
 }
 
 /*
@@ -212,7 +212,7 @@ static u32 kbd_read_status(void)
  * Things written here are generally arguments to commands previously
  * written to port 0x64 and stored in state.write_cmd
  */
-static void kbd_write_data(u32 val)
+static void kbd_write_data(u8 val)
 {
 	switch (state.write_cmd) {
 	case I8042_CMD_CTL_WCTR:
@@ -266,8 +266,8 @@ static void kbd_write_data(u32 val)
 			break;
 		default:
 			break;
-	}
-	break;
+		}
+		break;
 	case 0:
 		/* Just send the ID */
 		kbd_queue(RESPONSE_ACK);
@@ -304,8 +304,8 @@ static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *
 		break;
 	}
 	case I8042_DATA_REG: {
-		u32 value = kbd_read_data();
-		ioport__write32(data, value);
+		u8 value = kbd_read_data();
+		ioport__write8(data, value);
 		break;
 	}
 	case I8042_PORT_B_REG: {
@@ -328,7 +328,7 @@ static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void
 		break;
 	}
 	case I8042_DATA_REG: {
-		u32 value = ioport__read32(data);
+		u8 value = ioport__read8(data);
 		kbd_write_data(value);
 		break;
 	}
-- 
2.17.5


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

* [PATCH kvmtool v2 05/22] hw/i8042: Clean up data types
@ 2021-02-25  0:58   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:58 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

The i8042 is clearly an 8-bit era device, so there is little room for
32-bit registers.
Clean up the data types used.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 hw/i8042.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/hw/i8042.c b/hw/i8042.c
index 37a99a2d..7d1f9772 100644
--- a/hw/i8042.c
+++ b/hw/i8042.c
@@ -64,11 +64,11 @@
 struct kbd_state {
 	struct kvm		*kvm;
 
-	char			kq[QUEUE_SIZE];	/* Keyboard queue */
+	u8			kq[QUEUE_SIZE];	/* Keyboard queue */
 	int			kread, kwrite;	/* Indexes into the queue */
 	int			kcount;		/* number of elements in queue */
 
-	char			mq[QUEUE_SIZE];
+	u8			mq[QUEUE_SIZE];
 	int			mread, mwrite;
 	int			mcount;
 
@@ -82,7 +82,7 @@ struct kbd_state {
 	 * Some commands (on port 0x64) have arguments;
 	 * we store the command here while we wait for the argument
 	 */
-	u32			write_cmd;
+	u8			write_cmd;
 };
 
 static struct kbd_state		state;
@@ -173,9 +173,9 @@ static void kbd_write_command(struct kvm *kvm, u8 val)
 /*
  * Called when the OS reads from port 0x60 (PS/2 data)
  */
-static u32 kbd_read_data(void)
+static u8 kbd_read_data(void)
 {
-	u32 ret;
+	u8 ret;
 	int i;
 
 	if (state.kcount != 0) {
@@ -202,9 +202,9 @@ static u32 kbd_read_data(void)
 /*
  * Called when the OS read from port 0x64, the command port
  */
-static u32 kbd_read_status(void)
+static u8 kbd_read_status(void)
 {
-	return (u32)state.status;
+	return state.status;
 }
 
 /*
@@ -212,7 +212,7 @@ static u32 kbd_read_status(void)
  * Things written here are generally arguments to commands previously
  * written to port 0x64 and stored in state.write_cmd
  */
-static void kbd_write_data(u32 val)
+static void kbd_write_data(u8 val)
 {
 	switch (state.write_cmd) {
 	case I8042_CMD_CTL_WCTR:
@@ -266,8 +266,8 @@ static void kbd_write_data(u32 val)
 			break;
 		default:
 			break;
-	}
-	break;
+		}
+		break;
 	case 0:
 		/* Just send the ID */
 		kbd_queue(RESPONSE_ACK);
@@ -304,8 +304,8 @@ static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *
 		break;
 	}
 	case I8042_DATA_REG: {
-		u32 value = kbd_read_data();
-		ioport__write32(data, value);
+		u8 value = kbd_read_data();
+		ioport__write8(data, value);
 		break;
 	}
 	case I8042_PORT_B_REG: {
@@ -328,7 +328,7 @@ static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void
 		break;
 	}
 	case I8042_DATA_REG: {
-		u32 value = ioport__read32(data);
+		u8 value = ioport__read8(data);
 		kbd_write_data(value);
 		break;
 	}
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 06/22] hw/i8042: Refactor trap handler
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:58   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:58 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO
prototype.

Adjust the trap handler to use that new function, and provide shims to
implement the old ioport interface, for now.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 hw/i8042.c | 68 +++++++++++++++++++++++++++---------------------------
 1 file changed, 34 insertions(+), 34 deletions(-)

diff --git a/hw/i8042.c b/hw/i8042.c
index 7d1f9772..ab866662 100644
--- a/hw/i8042.c
+++ b/hw/i8042.c
@@ -292,52 +292,52 @@ static void kbd_reset(void)
 	};
 }
 
-/*
- * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
- */
-static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void kbd_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+		   u8 is_write, void *ptr)
 {
-	switch (port) {
-	case I8042_COMMAND_REG: {
-		u8 value = kbd_read_status();
-		ioport__write8(data, value);
+	u8 value;
+
+	if (is_write)
+		value = ioport__read8(data);
+
+	switch (addr) {
+	case I8042_COMMAND_REG:
+		if (is_write)
+			kbd_write_command(vcpu->kvm, value);
+		else
+			value = kbd_read_status();
 		break;
-	}
-	case I8042_DATA_REG: {
-		u8 value = kbd_read_data();
-		ioport__write8(data, value);
+	case I8042_DATA_REG:
+		if (is_write)
+			kbd_write_data(value);
+		else
+			value = kbd_read_data();
 		break;
-	}
-	case I8042_PORT_B_REG: {
-		ioport__write8(data, 0x20);
+	case I8042_PORT_B_REG:
+		if (!is_write)
+			value = 0x20;
 		break;
-	}
 	default:
-		return false;
+		return;
 	}
 
+	if (!is_write)
+		ioport__write8(data, value);
+}
+
+/*
+ * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
+ */
+static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+{
+	kbd_io(vcpu, port, data, size, 0, NULL);
+
 	return true;
 }
 
 static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
 {
-	switch (port) {
-	case I8042_COMMAND_REG: {
-		u8 value = ioport__read8(data);
-		kbd_write_command(vcpu->kvm, value);
-		break;
-	}
-	case I8042_DATA_REG: {
-		u8 value = ioport__read8(data);
-		kbd_write_data(value);
-		break;
-	}
-	case I8042_PORT_B_REG: {
-		break;
-	}
-	default:
-		return false;
-	}
+	kbd_io(vcpu, port, data, size, 1, NULL);
 
 	return true;
 }
-- 
2.17.5


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

* [PATCH kvmtool v2 06/22] hw/i8042: Refactor trap handler
@ 2021-02-25  0:58   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:58 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO
prototype.

Adjust the trap handler to use that new function, and provide shims to
implement the old ioport interface, for now.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 hw/i8042.c | 68 +++++++++++++++++++++++++++---------------------------
 1 file changed, 34 insertions(+), 34 deletions(-)

diff --git a/hw/i8042.c b/hw/i8042.c
index 7d1f9772..ab866662 100644
--- a/hw/i8042.c
+++ b/hw/i8042.c
@@ -292,52 +292,52 @@ static void kbd_reset(void)
 	};
 }
 
-/*
- * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
- */
-static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void kbd_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+		   u8 is_write, void *ptr)
 {
-	switch (port) {
-	case I8042_COMMAND_REG: {
-		u8 value = kbd_read_status();
-		ioport__write8(data, value);
+	u8 value;
+
+	if (is_write)
+		value = ioport__read8(data);
+
+	switch (addr) {
+	case I8042_COMMAND_REG:
+		if (is_write)
+			kbd_write_command(vcpu->kvm, value);
+		else
+			value = kbd_read_status();
 		break;
-	}
-	case I8042_DATA_REG: {
-		u8 value = kbd_read_data();
-		ioport__write8(data, value);
+	case I8042_DATA_REG:
+		if (is_write)
+			kbd_write_data(value);
+		else
+			value = kbd_read_data();
 		break;
-	}
-	case I8042_PORT_B_REG: {
-		ioport__write8(data, 0x20);
+	case I8042_PORT_B_REG:
+		if (!is_write)
+			value = 0x20;
 		break;
-	}
 	default:
-		return false;
+		return;
 	}
 
+	if (!is_write)
+		ioport__write8(data, value);
+}
+
+/*
+ * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
+ */
+static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+{
+	kbd_io(vcpu, port, data, size, 0, NULL);
+
 	return true;
 }
 
 static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
 {
-	switch (port) {
-	case I8042_COMMAND_REG: {
-		u8 value = ioport__read8(data);
-		kbd_write_command(vcpu->kvm, value);
-		break;
-	}
-	case I8042_DATA_REG: {
-		u8 value = ioport__read8(data);
-		kbd_write_data(value);
-		break;
-	}
-	case I8042_PORT_B_REG: {
-		break;
-	}
-	default:
-		return false;
-	}
+	kbd_io(vcpu, port, data, size, 1, NULL);
 
 	return true;
 }
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 07/22] hw/i8042: Switch to new trap handlers
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

Now that the PC keyboard has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Make the kbd_init() function static on the way.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 hw/i8042.c          | 30 ++++--------------------------
 include/kvm/i8042.h |  1 -
 2 files changed, 4 insertions(+), 27 deletions(-)

diff --git a/hw/i8042.c b/hw/i8042.c
index ab866662..20be36c4 100644
--- a/hw/i8042.c
+++ b/hw/i8042.c
@@ -325,40 +325,18 @@ static void kbd_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
 		ioport__write8(data, value);
 }
 
-/*
- * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
- */
-static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	kbd_io(vcpu, port, data, size, false, NULL);
-
-	return true;
-}
-
-static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	kbd_io(vcpu, port, data, size, true, NULL);
-
-	return true;
-}
-
-static struct ioport_operations kbd_ops = {
-	.io_in		= kbd_in,
-	.io_out		= kbd_out,
-};
-
-int kbd__init(struct kvm *kvm)
+static int kbd__init(struct kvm *kvm)
 {
 	int r;
 
 	kbd_reset();
 	state.kvm = kvm;
-	r = ioport__register(kvm, I8042_DATA_REG, &kbd_ops, 2, NULL);
+	r = kvm__register_pio(kvm, I8042_DATA_REG, 2, kbd_io, NULL);
 	if (r < 0)
 		return r;
-	r = ioport__register(kvm, I8042_COMMAND_REG, &kbd_ops, 2, NULL);
+	r = kvm__register_pio(kvm, I8042_COMMAND_REG, 2, kbd_io, NULL);
 	if (r < 0) {
-		ioport__unregister(kvm, I8042_DATA_REG);
+		kvm__deregister_pio(kvm, I8042_DATA_REG);
 		return r;
 	}
 
diff --git a/include/kvm/i8042.h b/include/kvm/i8042.h
index 3b4ab688..cd4ae6bb 100644
--- a/include/kvm/i8042.h
+++ b/include/kvm/i8042.h
@@ -7,6 +7,5 @@ struct kvm;
 
 void mouse_queue(u8 c);
 void kbd_queue(u8 c);
-int kbd__init(struct kvm *kvm);
 
 #endif
-- 
2.17.5


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

* [PATCH kvmtool v2 07/22] hw/i8042: Switch to new trap handlers
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Now that the PC keyboard has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Make the kbd_init() function static on the way.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 hw/i8042.c          | 30 ++++--------------------------
 include/kvm/i8042.h |  1 -
 2 files changed, 4 insertions(+), 27 deletions(-)

diff --git a/hw/i8042.c b/hw/i8042.c
index ab866662..20be36c4 100644
--- a/hw/i8042.c
+++ b/hw/i8042.c
@@ -325,40 +325,18 @@ static void kbd_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
 		ioport__write8(data, value);
 }
 
-/*
- * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
- */
-static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	kbd_io(vcpu, port, data, size, false, NULL);
-
-	return true;
-}
-
-static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	kbd_io(vcpu, port, data, size, true, NULL);
-
-	return true;
-}
-
-static struct ioport_operations kbd_ops = {
-	.io_in		= kbd_in,
-	.io_out		= kbd_out,
-};
-
-int kbd__init(struct kvm *kvm)
+static int kbd__init(struct kvm *kvm)
 {
 	int r;
 
 	kbd_reset();
 	state.kvm = kvm;
-	r = ioport__register(kvm, I8042_DATA_REG, &kbd_ops, 2, NULL);
+	r = kvm__register_pio(kvm, I8042_DATA_REG, 2, kbd_io, NULL);
 	if (r < 0)
 		return r;
-	r = ioport__register(kvm, I8042_COMMAND_REG, &kbd_ops, 2, NULL);
+	r = kvm__register_pio(kvm, I8042_COMMAND_REG, 2, kbd_io, NULL);
 	if (r < 0) {
-		ioport__unregister(kvm, I8042_DATA_REG);
+		kvm__deregister_pio(kvm, I8042_DATA_REG);
 		return r;
 	}
 
diff --git a/include/kvm/i8042.h b/include/kvm/i8042.h
index 3b4ab688..cd4ae6bb 100644
--- a/include/kvm/i8042.h
+++ b/include/kvm/i8042.h
@@ -7,6 +7,5 @@ struct kvm;
 
 void mouse_queue(u8 c);
 void kbd_queue(u8 c);
-int kbd__init(struct kvm *kvm);
 
 #endif
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 08/22] x86/ioport: Refactor trap handlers
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

With the planned retirement of the special ioport emulation code, we
need to provide emulation functions compatible with the MMIO
prototype.

Adjust the trap handlers to use that new function, and provide shims to
implement the old ioport interface, for now.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 x86/ioport.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/x86/ioport.c b/x86/ioport.c
index a8d2bb1a..78f9a863 100644
--- a/x86/ioport.c
+++ b/x86/ioport.c
@@ -3,8 +3,14 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+		       u8 is_write, void *ptr)
+{
+}
+
 static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
 {
+	dummy_mmio(vcpu, port, data, size, true, NULL);
 	return 0;
 }
 
@@ -12,15 +18,23 @@ static struct ioport_operations debug_ops = {
 	.io_out		= debug_io_out,
 };
 
-static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+			       u32 len, u8 is_write, void *ptr)
 {
 	char ch;
 
+	if (!is_write)
+		return;
+
 	ch = ioport__read8(data);
 
 	putchar(ch);
+}
 
-	return true;
+static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+{
+	seabios_debug_mmio(vcpu, port, data, size, true, NULL);
+	return 0;
 }
 
 static struct ioport_operations seabios_debug_ops = {
@@ -29,11 +43,13 @@ static struct ioport_operations seabios_debug_ops = {
 
 static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
 {
+	dummy_mmio(vcpu, port, data, size, false, NULL);
 	return true;
 }
 
 static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
 {
+	dummy_mmio(vcpu, port, data, size, true, NULL);
 	return true;
 }
 
@@ -50,13 +66,19 @@ static struct ioport_operations dummy_write_only_ioport_ops = {
  * The "fast A20 gate"
  */
 
-static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+			     u8 is_write, void *ptr)
 {
 	/*
 	 * A20 is always enabled.
 	 */
-	ioport__write8(data, 0x02);
+	if (!is_write)
+		ioport__write8(data, 0x02);
+}
 
+static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+{
+	ps2_control_mmio(vcpu, port, data, size, false, NULL);
 	return true;
 }
 
-- 
2.17.5


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

* [PATCH kvmtool v2 08/22] x86/ioport: Refactor trap handlers
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

With the planned retirement of the special ioport emulation code, we
need to provide emulation functions compatible with the MMIO
prototype.

Adjust the trap handlers to use that new function, and provide shims to
implement the old ioport interface, for now.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 x86/ioport.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/x86/ioport.c b/x86/ioport.c
index a8d2bb1a..78f9a863 100644
--- a/x86/ioport.c
+++ b/x86/ioport.c
@@ -3,8 +3,14 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+		       u8 is_write, void *ptr)
+{
+}
+
 static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
 {
+	dummy_mmio(vcpu, port, data, size, true, NULL);
 	return 0;
 }
 
@@ -12,15 +18,23 @@ static struct ioport_operations debug_ops = {
 	.io_out		= debug_io_out,
 };
 
-static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+			       u32 len, u8 is_write, void *ptr)
 {
 	char ch;
 
+	if (!is_write)
+		return;
+
 	ch = ioport__read8(data);
 
 	putchar(ch);
+}
 
-	return true;
+static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+{
+	seabios_debug_mmio(vcpu, port, data, size, true, NULL);
+	return 0;
 }
 
 static struct ioport_operations seabios_debug_ops = {
@@ -29,11 +43,13 @@ static struct ioport_operations seabios_debug_ops = {
 
 static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
 {
+	dummy_mmio(vcpu, port, data, size, false, NULL);
 	return true;
 }
 
 static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
 {
+	dummy_mmio(vcpu, port, data, size, true, NULL);
 	return true;
 }
 
@@ -50,13 +66,19 @@ static struct ioport_operations dummy_write_only_ioport_ops = {
  * The "fast A20 gate"
  */
 
-static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+			     u8 is_write, void *ptr)
 {
 	/*
 	 * A20 is always enabled.
 	 */
-	ioport__write8(data, 0x02);
+	if (!is_write)
+		ioport__write8(data, 0x02);
+}
 
+static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+{
+	ps2_control_mmio(vcpu, port, data, size, false, NULL);
 	return true;
 }
 
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 09/22] x86/ioport: Switch to new trap handlers
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

Now that the x86 I/O ports have trap handlers adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Since the debug output was done in ioport.c, we would lose this
functionality when moving over to the MMIO handlers. So bring this back
here explicitly, by introducing debug_mmio().

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 x86/ioport.c | 102 +++++++++++++++++++--------------------------------
 1 file changed, 37 insertions(+), 65 deletions(-)

diff --git a/x86/ioport.c b/x86/ioport.c
index 78f9a863..9fcbb6c9 100644
--- a/x86/ioport.c
+++ b/x86/ioport.c
@@ -3,21 +3,35 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+static void debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
 		       u8 is_write, void *ptr)
 {
+	if (!vcpu->kvm->cfg.ioport_debug)
+		return;
+
+	fprintf(stderr, "debug port %s from VCPU%lu: port=0x%lx, size=%u",
+		is_write ? "write" : "read", vcpu->cpu_id,
+		(unsigned long)addr, len);
+	if (is_write) {
+		u32 value;
+
+		switch (len) {
+		case 1: value = ioport__read8(data); break;
+		case 2: value = ioport__read16((u16*)data); break;
+		case 4: value = ioport__read32((u32*)data); break;
+		default: value = 0; break;
+		}
+		fprintf(stderr, ", data: 0x%x\n", value);
+	} else {
+		fprintf(stderr, "\n");
+	}
 }
 
-static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+		       u8 is_write, void *ptr)
 {
-	dummy_mmio(vcpu, port, data, size, true, NULL);
-	return 0;
 }
 
-static struct ioport_operations debug_ops = {
-	.io_out		= debug_io_out,
-};
-
 static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
 			       u32 len, u8 is_write, void *ptr)
 {
@@ -31,37 +45,6 @@ static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
 	putchar(ch);
 }
 
-static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	seabios_debug_mmio(vcpu, port, data, size, true, NULL);
-	return 0;
-}
-
-static struct ioport_operations seabios_debug_ops = {
-	.io_out		= seabios_debug_io_out,
-};
-
-static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	dummy_mmio(vcpu, port, data, size, false, NULL);
-	return true;
-}
-
-static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	dummy_mmio(vcpu, port, data, size, true, NULL);
-	return true;
-}
-
-static struct ioport_operations dummy_read_write_ioport_ops = {
-	.io_in		= dummy_io_in,
-	.io_out		= dummy_io_out,
-};
-
-static struct ioport_operations dummy_write_only_ioport_ops = {
-	.io_out		= dummy_io_out,
-};
-
 /*
  * The "fast A20 gate"
  */
@@ -76,17 +59,6 @@ static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
 		ioport__write8(data, 0x02);
 }
 
-static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	ps2_control_mmio(vcpu, port, data, size, false, NULL);
-	return true;
-}
-
-static struct ioport_operations ps2_control_a_ops = {
-	.io_in		= ps2_control_a_io_in,
-	.io_out		= dummy_io_out,
-};
-
 void ioport__map_irq(u8 *irq)
 {
 }
@@ -98,75 +70,75 @@ static int ioport__setup_arch(struct kvm *kvm)
 	/* Legacy ioport setup */
 
 	/* 0000 - 001F - DMA1 controller */
-	r = ioport__register(kvm, 0x0000, &dummy_read_write_ioport_ops, 32, NULL);
+	r = kvm__register_pio(kvm, 0x0000, 32, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* 0x0020 - 0x003F - 8259A PIC 1 */
-	r = ioport__register(kvm, 0x0020, &dummy_read_write_ioport_ops, 2, NULL);
+	r = kvm__register_pio(kvm, 0x0020, 2, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
-	r = ioport__register(kvm, 0x0040, &dummy_read_write_ioport_ops, 4, NULL);
+	r = kvm__register_pio(kvm, 0x0040, 4, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* 0092 - PS/2 system control port A */
-	r = ioport__register(kvm, 0x0092, &ps2_control_a_ops, 1, NULL);
+	r = kvm__register_pio(kvm, 0x0092, 1, ps2_control_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* 0x00A0 - 0x00AF - 8259A PIC 2 */
-	r = ioport__register(kvm, 0x00A0, &dummy_read_write_ioport_ops, 2, NULL);
+	r = kvm__register_pio(kvm, 0x00A0, 2, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* 00C0 - 001F - DMA2 controller */
-	r = ioport__register(kvm, 0x00C0, &dummy_read_write_ioport_ops, 32, NULL);
+	r = kvm__register_pio(kvm, 0x00c0, 32, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* PORT 00E0-00EF are 'motherboard specific' so we use them for our
 	   internal debugging purposes.  */
-	r = ioport__register(kvm, IOPORT_DBG, &debug_ops, 1, NULL);
+	r = kvm__register_pio(kvm, IOPORT_DBG, 1, debug_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* PORT 00ED - DUMMY PORT FOR DELAY??? */
-	r = ioport__register(kvm, 0x00ED, &dummy_write_only_ioport_ops, 1, NULL);
+	r = kvm__register_pio(kvm, 0x00ed, 1, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* 0x00F0 - 0x00FF - Math co-processor */
-	r = ioport__register(kvm, 0x00F0, &dummy_write_only_ioport_ops, 2, NULL);
+	r = kvm__register_pio(kvm, 0x00f0, 2, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* PORT 0278-027A - PARALLEL PRINTER PORT (usually LPT1, sometimes LPT2) */
-	r = ioport__register(kvm, 0x0278, &dummy_read_write_ioport_ops, 3, NULL);
+	r = kvm__register_pio(kvm, 0x0278, 3, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* PORT 0378-037A - PARALLEL PRINTER PORT (usually LPT2, sometimes LPT3) */
-	r = ioport__register(kvm, 0x0378, &dummy_read_write_ioport_ops, 3, NULL);
+	r = kvm__register_pio(kvm, 0x0378, 3, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
-	r = ioport__register(kvm, 0x03D4, &dummy_read_write_ioport_ops, 1, NULL);
+	r = kvm__register_pio(kvm, 0x03d4, 1, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
-	r = ioport__register(kvm, 0x03D5, &dummy_write_only_ioport_ops, 1, NULL);
+	r = kvm__register_pio(kvm, 0x03d5, 1, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
-	r = ioport__register(kvm, 0x402, &seabios_debug_ops, 1, NULL);
+	r = kvm__register_pio(kvm, 0x0402, 1, seabios_debug_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* 0510 - QEMU BIOS configuration register */
-	r = ioport__register(kvm, 0x510, &dummy_read_write_ioport_ops, 2, NULL);
+	r = kvm__register_pio(kvm, 0x0510, 2, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
-- 
2.17.5


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

* [PATCH kvmtool v2 09/22] x86/ioport: Switch to new trap handlers
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Now that the x86 I/O ports have trap handlers adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Since the debug output was done in ioport.c, we would lose this
functionality when moving over to the MMIO handlers. So bring this back
here explicitly, by introducing debug_mmio().

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 x86/ioport.c | 102 +++++++++++++++++++--------------------------------
 1 file changed, 37 insertions(+), 65 deletions(-)

diff --git a/x86/ioport.c b/x86/ioport.c
index 78f9a863..9fcbb6c9 100644
--- a/x86/ioport.c
+++ b/x86/ioport.c
@@ -3,21 +3,35 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+static void debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
 		       u8 is_write, void *ptr)
 {
+	if (!vcpu->kvm->cfg.ioport_debug)
+		return;
+
+	fprintf(stderr, "debug port %s from VCPU%lu: port=0x%lx, size=%u",
+		is_write ? "write" : "read", vcpu->cpu_id,
+		(unsigned long)addr, len);
+	if (is_write) {
+		u32 value;
+
+		switch (len) {
+		case 1: value = ioport__read8(data); break;
+		case 2: value = ioport__read16((u16*)data); break;
+		case 4: value = ioport__read32((u32*)data); break;
+		default: value = 0; break;
+		}
+		fprintf(stderr, ", data: 0x%x\n", value);
+	} else {
+		fprintf(stderr, "\n");
+	}
 }
 
-static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+		       u8 is_write, void *ptr)
 {
-	dummy_mmio(vcpu, port, data, size, true, NULL);
-	return 0;
 }
 
-static struct ioport_operations debug_ops = {
-	.io_out		= debug_io_out,
-};
-
 static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
 			       u32 len, u8 is_write, void *ptr)
 {
@@ -31,37 +45,6 @@ static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
 	putchar(ch);
 }
 
-static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	seabios_debug_mmio(vcpu, port, data, size, true, NULL);
-	return 0;
-}
-
-static struct ioport_operations seabios_debug_ops = {
-	.io_out		= seabios_debug_io_out,
-};
-
-static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	dummy_mmio(vcpu, port, data, size, false, NULL);
-	return true;
-}
-
-static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	dummy_mmio(vcpu, port, data, size, true, NULL);
-	return true;
-}
-
-static struct ioport_operations dummy_read_write_ioport_ops = {
-	.io_in		= dummy_io_in,
-	.io_out		= dummy_io_out,
-};
-
-static struct ioport_operations dummy_write_only_ioport_ops = {
-	.io_out		= dummy_io_out,
-};
-
 /*
  * The "fast A20 gate"
  */
@@ -76,17 +59,6 @@ static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
 		ioport__write8(data, 0x02);
 }
 
-static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	ps2_control_mmio(vcpu, port, data, size, false, NULL);
-	return true;
-}
-
-static struct ioport_operations ps2_control_a_ops = {
-	.io_in		= ps2_control_a_io_in,
-	.io_out		= dummy_io_out,
-};
-
 void ioport__map_irq(u8 *irq)
 {
 }
@@ -98,75 +70,75 @@ static int ioport__setup_arch(struct kvm *kvm)
 	/* Legacy ioport setup */
 
 	/* 0000 - 001F - DMA1 controller */
-	r = ioport__register(kvm, 0x0000, &dummy_read_write_ioport_ops, 32, NULL);
+	r = kvm__register_pio(kvm, 0x0000, 32, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* 0x0020 - 0x003F - 8259A PIC 1 */
-	r = ioport__register(kvm, 0x0020, &dummy_read_write_ioport_ops, 2, NULL);
+	r = kvm__register_pio(kvm, 0x0020, 2, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
-	r = ioport__register(kvm, 0x0040, &dummy_read_write_ioport_ops, 4, NULL);
+	r = kvm__register_pio(kvm, 0x0040, 4, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* 0092 - PS/2 system control port A */
-	r = ioport__register(kvm, 0x0092, &ps2_control_a_ops, 1, NULL);
+	r = kvm__register_pio(kvm, 0x0092, 1, ps2_control_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* 0x00A0 - 0x00AF - 8259A PIC 2 */
-	r = ioport__register(kvm, 0x00A0, &dummy_read_write_ioport_ops, 2, NULL);
+	r = kvm__register_pio(kvm, 0x00A0, 2, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* 00C0 - 001F - DMA2 controller */
-	r = ioport__register(kvm, 0x00C0, &dummy_read_write_ioport_ops, 32, NULL);
+	r = kvm__register_pio(kvm, 0x00c0, 32, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* PORT 00E0-00EF are 'motherboard specific' so we use them for our
 	   internal debugging purposes.  */
-	r = ioport__register(kvm, IOPORT_DBG, &debug_ops, 1, NULL);
+	r = kvm__register_pio(kvm, IOPORT_DBG, 1, debug_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* PORT 00ED - DUMMY PORT FOR DELAY??? */
-	r = ioport__register(kvm, 0x00ED, &dummy_write_only_ioport_ops, 1, NULL);
+	r = kvm__register_pio(kvm, 0x00ed, 1, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* 0x00F0 - 0x00FF - Math co-processor */
-	r = ioport__register(kvm, 0x00F0, &dummy_write_only_ioport_ops, 2, NULL);
+	r = kvm__register_pio(kvm, 0x00f0, 2, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* PORT 0278-027A - PARALLEL PRINTER PORT (usually LPT1, sometimes LPT2) */
-	r = ioport__register(kvm, 0x0278, &dummy_read_write_ioport_ops, 3, NULL);
+	r = kvm__register_pio(kvm, 0x0278, 3, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* PORT 0378-037A - PARALLEL PRINTER PORT (usually LPT2, sometimes LPT3) */
-	r = ioport__register(kvm, 0x0378, &dummy_read_write_ioport_ops, 3, NULL);
+	r = kvm__register_pio(kvm, 0x0378, 3, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
-	r = ioport__register(kvm, 0x03D4, &dummy_read_write_ioport_ops, 1, NULL);
+	r = kvm__register_pio(kvm, 0x03d4, 1, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
-	r = ioport__register(kvm, 0x03D5, &dummy_write_only_ioport_ops, 1, NULL);
+	r = kvm__register_pio(kvm, 0x03d5, 1, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
-	r = ioport__register(kvm, 0x402, &seabios_debug_ops, 1, NULL);
+	r = kvm__register_pio(kvm, 0x0402, 1, seabios_debug_mmio, NULL);
 	if (r < 0)
 		return r;
 
 	/* 0510 - QEMU BIOS configuration register */
-	r = ioport__register(kvm, 0x510, &dummy_read_write_ioport_ops, 2, NULL);
+	r = kvm__register_pio(kvm, 0x0510, 2, dummy_mmio, NULL);
 	if (r < 0)
 		return r;
 
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 10/22] hw/rtc: Refactor trap handlers
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

With the planned retirement of the special ioport emulation code, we
need to provide emulation functions compatible with the MMIO prototype.

Merge the two different trap handlers into one function, checking for
read/write and data/index register inside.
Adjust the trap handlers to use that new function, and provide shims to
implement the old ioport interface, for now.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 hw/rtc.c | 70 ++++++++++++++++++++++++++++----------------------------
 1 file changed, 35 insertions(+), 35 deletions(-)

diff --git a/hw/rtc.c b/hw/rtc.c
index 5483879f..664d4cb0 100644
--- a/hw/rtc.c
+++ b/hw/rtc.c
@@ -42,11 +42,37 @@ static inline unsigned char bin2bcd(unsigned val)
 	return ((val / 10) << 4) + val % 10;
 }
 
-static bool cmos_ram_data_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+			u32 len, u8 is_write, void *ptr)
 {
 	struct tm *tm;
 	time_t ti;
 
+	if (is_write) {
+		if (addr == 0x70) {	/* index register */
+			u8 value = ioport__read8(data);
+
+			vcpu->kvm->nmi_disabled	= value & (1UL << 7);
+			rtc.cmos_idx		= value & ~(1UL << 7);
+
+			return;
+		}
+
+		switch (rtc.cmos_idx) {
+		case RTC_REG_C:
+		case RTC_REG_D:
+			/* Read-only */
+			break;
+		default:
+			rtc.cmos_data[rtc.cmos_idx] = ioport__read8(data);
+			break;
+		}
+		return;
+	}
+
+	if (addr == 0x70)
+		return;
+
 	time(&ti);
 
 	tm = gmtime(&ti);
@@ -92,42 +118,23 @@ static bool cmos_ram_data_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 po
 		ioport__write8(data, rtc.cmos_data[rtc.cmos_idx]);
 		break;
 	}
-
-	return true;
 }
 
-static bool cmos_ram_data_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static bool cmos_ram_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
 {
-	switch (rtc.cmos_idx) {
-	case RTC_REG_C:
-	case RTC_REG_D:
-		/* Read-only */
-		break;
-	default:
-		rtc.cmos_data[rtc.cmos_idx] = ioport__read8(data);
-		break;
-	}
-
+	cmos_ram_io(vcpu, port, data, size, false, NULL);
 	return true;
 }
 
-static struct ioport_operations cmos_ram_data_ioport_ops = {
-	.io_out		= cmos_ram_data_out,
-	.io_in		= cmos_ram_data_in,
-};
-
-static bool cmos_ram_index_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static bool cmos_ram_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
 {
-	u8 value = ioport__read8(data);
-
-	vcpu->kvm->nmi_disabled	= value & (1UL << 7);
-	rtc.cmos_idx		= value & ~(1UL << 7);
-
+	cmos_ram_io(vcpu, port, data, size, true, NULL);
 	return true;
 }
 
-static struct ioport_operations cmos_ram_index_ioport_ops = {
-	.io_out		= cmos_ram_index_out,
+static struct ioport_operations cmos_ram_ioport_ops = {
+	.io_out		= cmos_ram_out,
+	.io_in		= cmos_ram_in,
 };
 
 #ifdef CONFIG_HAS_LIBFDT
@@ -162,21 +169,15 @@ int rtc__init(struct kvm *kvm)
 		return r;
 
 	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-	r = ioport__register(kvm, 0x0070, &cmos_ram_index_ioport_ops, 1, NULL);
+	r = ioport__register(kvm, 0x0070, &cmos_ram_ioport_ops, 2, NULL);
 	if (r < 0)
 		goto out_device;
 
-	r = ioport__register(kvm, 0x0071, &cmos_ram_data_ioport_ops, 1, NULL);
-	if (r < 0)
-		goto out_ioport;
-
 	/* Set the VRT bit in Register D to indicate valid RAM and time */
 	rtc.cmos_data[RTC_REG_D] = RTC_REG_D_VRT;
 
 	return r;
 
-out_ioport:
-	ioport__unregister(kvm, 0x0070);
 out_device:
 	device__unregister(&rtc_dev_hdr);
 
@@ -188,7 +189,6 @@ int rtc__exit(struct kvm *kvm)
 {
 	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
 	ioport__unregister(kvm, 0x0070);
-	ioport__unregister(kvm, 0x0071);
 
 	return 0;
 }
-- 
2.17.5


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

* [PATCH kvmtool v2 10/22] hw/rtc: Refactor trap handlers
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

With the planned retirement of the special ioport emulation code, we
need to provide emulation functions compatible with the MMIO prototype.

Merge the two different trap handlers into one function, checking for
read/write and data/index register inside.
Adjust the trap handlers to use that new function, and provide shims to
implement the old ioport interface, for now.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 hw/rtc.c | 70 ++++++++++++++++++++++++++++----------------------------
 1 file changed, 35 insertions(+), 35 deletions(-)

diff --git a/hw/rtc.c b/hw/rtc.c
index 5483879f..664d4cb0 100644
--- a/hw/rtc.c
+++ b/hw/rtc.c
@@ -42,11 +42,37 @@ static inline unsigned char bin2bcd(unsigned val)
 	return ((val / 10) << 4) + val % 10;
 }
 
-static bool cmos_ram_data_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+			u32 len, u8 is_write, void *ptr)
 {
 	struct tm *tm;
 	time_t ti;
 
+	if (is_write) {
+		if (addr == 0x70) {	/* index register */
+			u8 value = ioport__read8(data);
+
+			vcpu->kvm->nmi_disabled	= value & (1UL << 7);
+			rtc.cmos_idx		= value & ~(1UL << 7);
+
+			return;
+		}
+
+		switch (rtc.cmos_idx) {
+		case RTC_REG_C:
+		case RTC_REG_D:
+			/* Read-only */
+			break;
+		default:
+			rtc.cmos_data[rtc.cmos_idx] = ioport__read8(data);
+			break;
+		}
+		return;
+	}
+
+	if (addr == 0x70)
+		return;
+
 	time(&ti);
 
 	tm = gmtime(&ti);
@@ -92,42 +118,23 @@ static bool cmos_ram_data_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 po
 		ioport__write8(data, rtc.cmos_data[rtc.cmos_idx]);
 		break;
 	}
-
-	return true;
 }
 
-static bool cmos_ram_data_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static bool cmos_ram_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
 {
-	switch (rtc.cmos_idx) {
-	case RTC_REG_C:
-	case RTC_REG_D:
-		/* Read-only */
-		break;
-	default:
-		rtc.cmos_data[rtc.cmos_idx] = ioport__read8(data);
-		break;
-	}
-
+	cmos_ram_io(vcpu, port, data, size, false, NULL);
 	return true;
 }
 
-static struct ioport_operations cmos_ram_data_ioport_ops = {
-	.io_out		= cmos_ram_data_out,
-	.io_in		= cmos_ram_data_in,
-};
-
-static bool cmos_ram_index_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static bool cmos_ram_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
 {
-	u8 value = ioport__read8(data);
-
-	vcpu->kvm->nmi_disabled	= value & (1UL << 7);
-	rtc.cmos_idx		= value & ~(1UL << 7);
-
+	cmos_ram_io(vcpu, port, data, size, true, NULL);
 	return true;
 }
 
-static struct ioport_operations cmos_ram_index_ioport_ops = {
-	.io_out		= cmos_ram_index_out,
+static struct ioport_operations cmos_ram_ioport_ops = {
+	.io_out		= cmos_ram_out,
+	.io_in		= cmos_ram_in,
 };
 
 #ifdef CONFIG_HAS_LIBFDT
@@ -162,21 +169,15 @@ int rtc__init(struct kvm *kvm)
 		return r;
 
 	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-	r = ioport__register(kvm, 0x0070, &cmos_ram_index_ioport_ops, 1, NULL);
+	r = ioport__register(kvm, 0x0070, &cmos_ram_ioport_ops, 2, NULL);
 	if (r < 0)
 		goto out_device;
 
-	r = ioport__register(kvm, 0x0071, &cmos_ram_data_ioport_ops, 1, NULL);
-	if (r < 0)
-		goto out_ioport;
-
 	/* Set the VRT bit in Register D to indicate valid RAM and time */
 	rtc.cmos_data[RTC_REG_D] = RTC_REG_D_VRT;
 
 	return r;
 
-out_ioport:
-	ioport__unregister(kvm, 0x0070);
 out_device:
 	device__unregister(&rtc_dev_hdr);
 
@@ -188,7 +189,6 @@ int rtc__exit(struct kvm *kvm)
 {
 	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
 	ioport__unregister(kvm, 0x0070);
-	ioport__unregister(kvm, 0x0071);
 
 	return 0;
 }
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 11/22] hw/rtc: Switch to new trap handler
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

Now that the RTC device has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 hw/rtc.c | 21 ++-------------------
 1 file changed, 2 insertions(+), 19 deletions(-)

diff --git a/hw/rtc.c b/hw/rtc.c
index 664d4cb0..ee4c9102 100644
--- a/hw/rtc.c
+++ b/hw/rtc.c
@@ -120,23 +120,6 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
 	}
 }
 
-static bool cmos_ram_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	cmos_ram_io(vcpu, port, data, size, false, NULL);
-	return true;
-}
-
-static bool cmos_ram_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	cmos_ram_io(vcpu, port, data, size, true, NULL);
-	return true;
-}
-
-static struct ioport_operations cmos_ram_ioport_ops = {
-	.io_out		= cmos_ram_out,
-	.io_in		= cmos_ram_in,
-};
-
 #ifdef CONFIG_HAS_LIBFDT
 static void generate_rtc_fdt_node(void *fdt,
 				  struct device_header *dev_hdr,
@@ -169,7 +152,7 @@ int rtc__init(struct kvm *kvm)
 		return r;
 
 	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-	r = ioport__register(kvm, 0x0070, &cmos_ram_ioport_ops, 2, NULL);
+	r = kvm__register_pio(kvm, 0x0070, 2, cmos_ram_io, NULL);
 	if (r < 0)
 		goto out_device;
 
@@ -188,7 +171,7 @@ dev_init(rtc__init);
 int rtc__exit(struct kvm *kvm)
 {
 	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-	ioport__unregister(kvm, 0x0070);
+	kvm__deregister_pio(kvm, 0x0070);
 
 	return 0;
 }
-- 
2.17.5


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

* [PATCH kvmtool v2 11/22] hw/rtc: Switch to new trap handler
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Now that the RTC device has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 hw/rtc.c | 21 ++-------------------
 1 file changed, 2 insertions(+), 19 deletions(-)

diff --git a/hw/rtc.c b/hw/rtc.c
index 664d4cb0..ee4c9102 100644
--- a/hw/rtc.c
+++ b/hw/rtc.c
@@ -120,23 +120,6 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
 	}
 }
 
-static bool cmos_ram_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	cmos_ram_io(vcpu, port, data, size, false, NULL);
-	return true;
-}
-
-static bool cmos_ram_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	cmos_ram_io(vcpu, port, data, size, true, NULL);
-	return true;
-}
-
-static struct ioport_operations cmos_ram_ioport_ops = {
-	.io_out		= cmos_ram_out,
-	.io_in		= cmos_ram_in,
-};
-
 #ifdef CONFIG_HAS_LIBFDT
 static void generate_rtc_fdt_node(void *fdt,
 				  struct device_header *dev_hdr,
@@ -169,7 +152,7 @@ int rtc__init(struct kvm *kvm)
 		return r;
 
 	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-	r = ioport__register(kvm, 0x0070, &cmos_ram_ioport_ops, 2, NULL);
+	r = kvm__register_pio(kvm, 0x0070, 2, cmos_ram_io, NULL);
 	if (r < 0)
 		goto out_device;
 
@@ -188,7 +171,7 @@ dev_init(rtc__init);
 int rtc__exit(struct kvm *kvm)
 {
 	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-	ioport__unregister(kvm, 0x0070);
+	kvm__deregister_pio(kvm, 0x0070);
 
 	return 0;
 }
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 12/22] hw/vesa: Switch trap handling to use MMIO handler
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

To be able to use the VESA device with the new generic I/O trap handler,
we need to use the different MMIO handler callback routine.

Replace the existing dummy in and out handlers with a joint dummy
MMIO handler, and register this using the new registration function.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 hw/vesa.c | 19 +++++--------------
 1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/hw/vesa.c b/hw/vesa.c
index 8659a002..7f82cdb4 100644
--- a/hw/vesa.c
+++ b/hw/vesa.c
@@ -43,21 +43,11 @@ static struct framebuffer vesafb = {
 	.mem_size	= VESA_MEM_SIZE,
 };
 
-static bool vesa_pci_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void vesa_pci_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+		        u8 is_write, void *ptr)
 {
-	return true;
 }
 
-static bool vesa_pci_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	return true;
-}
-
-static struct ioport_operations vesa_io_ops = {
-	.io_in			= vesa_pci_io_in,
-	.io_out			= vesa_pci_io_out,
-};
-
 static int vesa__bar_activate(struct kvm *kvm, struct pci_device_header *pci_hdr,
 			      int bar_num, void *data)
 {
@@ -82,7 +72,8 @@ struct framebuffer *vesa__init(struct kvm *kvm)
 	BUILD_BUG_ON(VESA_MEM_SIZE < VESA_BPP/8 * VESA_WIDTH * VESA_HEIGHT);
 
 	vesa_base_addr = pci_get_io_port_block(PCI_IO_SIZE);
-	r = ioport__register(kvm, vesa_base_addr, &vesa_io_ops, PCI_IO_SIZE, NULL);
+	r = kvm__register_pio(kvm, vesa_base_addr, PCI_IO_SIZE, vesa_pci_io,
+			      NULL);
 	if (r < 0)
 		goto out_error;
 
@@ -116,7 +107,7 @@ unmap_dev:
 unregister_device:
 	device__unregister(&vesa_device);
 unregister_ioport:
-	ioport__unregister(kvm, vesa_base_addr);
+	kvm__deregister_pio(kvm, vesa_base_addr);
 out_error:
 	return ERR_PTR(r);
 }
-- 
2.17.5


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

* [PATCH kvmtool v2 12/22] hw/vesa: Switch trap handling to use MMIO handler
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

To be able to use the VESA device with the new generic I/O trap handler,
we need to use the different MMIO handler callback routine.

Replace the existing dummy in and out handlers with a joint dummy
MMIO handler, and register this using the new registration function.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 hw/vesa.c | 19 +++++--------------
 1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/hw/vesa.c b/hw/vesa.c
index 8659a002..7f82cdb4 100644
--- a/hw/vesa.c
+++ b/hw/vesa.c
@@ -43,21 +43,11 @@ static struct framebuffer vesafb = {
 	.mem_size	= VESA_MEM_SIZE,
 };
 
-static bool vesa_pci_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void vesa_pci_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+		        u8 is_write, void *ptr)
 {
-	return true;
 }
 
-static bool vesa_pci_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	return true;
-}
-
-static struct ioport_operations vesa_io_ops = {
-	.io_in			= vesa_pci_io_in,
-	.io_out			= vesa_pci_io_out,
-};
-
 static int vesa__bar_activate(struct kvm *kvm, struct pci_device_header *pci_hdr,
 			      int bar_num, void *data)
 {
@@ -82,7 +72,8 @@ struct framebuffer *vesa__init(struct kvm *kvm)
 	BUILD_BUG_ON(VESA_MEM_SIZE < VESA_BPP/8 * VESA_WIDTH * VESA_HEIGHT);
 
 	vesa_base_addr = pci_get_io_port_block(PCI_IO_SIZE);
-	r = ioport__register(kvm, vesa_base_addr, &vesa_io_ops, PCI_IO_SIZE, NULL);
+	r = kvm__register_pio(kvm, vesa_base_addr, PCI_IO_SIZE, vesa_pci_io,
+			      NULL);
 	if (r < 0)
 		goto out_error;
 
@@ -116,7 +107,7 @@ unmap_dev:
 unregister_device:
 	device__unregister(&vesa_device);
 unregister_ioport:
-	ioport__unregister(kvm, vesa_base_addr);
+	kvm__deregister_pio(kvm, vesa_base_addr);
 out_error:
 	return ERR_PTR(r);
 }
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 13/22] hw/serial: Refactor trap handler
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Adjust the trap handler to use that new function, and provide shims to
implement the old ioport interface, for now.

We drop the usage of ioport__read8/write8 entirely, as this would only
be applicable for I/O port accesses, and does nothing for 8-bit wide
accesses anyway.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 hw/serial.c | 93 +++++++++++++++++++++++++++++++++--------------------
 1 file changed, 58 insertions(+), 35 deletions(-)

diff --git a/hw/serial.c b/hw/serial.c
index b0465d99..c495eac1 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -242,36 +242,31 @@ void serial8250__inject_sysrq(struct kvm *kvm, char sysrq)
 	sysrq_pending = sysrq;
 }
 
-static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port,
-			   void *data, int size)
+static bool serial8250_out(struct serial8250_device *dev, struct kvm_cpu *vcpu,
+			   u16 offset, u8 data)
 {
-	struct serial8250_device *dev = ioport->priv;
-	u16 offset;
 	bool ret = true;
-	char *addr = data;
 
 	mutex_lock(&dev->mutex);
 
-	offset = port - dev->iobase;
-
 	switch (offset) {
 	case UART_TX:
 		if (dev->lcr & UART_LCR_DLAB) {
-			dev->dll = ioport__read8(data);
+			dev->dll = data;
 			break;
 		}
 
 		/* Loopback mode */
 		if (dev->mcr & UART_MCR_LOOP) {
 			if (dev->rxcnt < FIFO_LEN) {
-				dev->rxbuf[dev->rxcnt++] = *addr;
+				dev->rxbuf[dev->rxcnt++] = data;
 				dev->lsr |= UART_LSR_DR;
 			}
 			break;
 		}
 
 		if (dev->txcnt < FIFO_LEN) {
-			dev->txbuf[dev->txcnt++] = *addr;
+			dev->txbuf[dev->txcnt++] = data;
 			dev->lsr &= ~UART_LSR_TEMT;
 			if (dev->txcnt == FIFO_LEN / 2)
 				dev->lsr &= ~UART_LSR_THRE;
@@ -283,18 +278,18 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
 		break;
 	case UART_IER:
 		if (!(dev->lcr & UART_LCR_DLAB))
-			dev->ier = ioport__read8(data) & 0x0f;
+			dev->ier = data & 0x0f;
 		else
-			dev->dlm = ioport__read8(data);
+			dev->dlm = data;
 		break;
 	case UART_FCR:
-		dev->fcr = ioport__read8(data);
+		dev->fcr = data;
 		break;
 	case UART_LCR:
-		dev->lcr = ioport__read8(data);
+		dev->lcr = data;
 		break;
 	case UART_MCR:
-		dev->mcr = ioport__read8(data);
+		dev->mcr = data;
 		break;
 	case UART_LSR:
 		/* Factory test */
@@ -303,7 +298,7 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
 		/* Not used */
 		break;
 	case UART_SCR:
-		dev->scr = ioport__read8(data);
+		dev->scr = data;
 		break;
 	default:
 		ret = false;
@@ -317,7 +312,7 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
 	return ret;
 }
 
-static void serial8250_rx(struct serial8250_device *dev, void *data)
+static void serial8250_rx(struct serial8250_device *dev, u8 *data)
 {
 	if (dev->rxdone == dev->rxcnt)
 		return;
@@ -325,57 +320,54 @@ static void serial8250_rx(struct serial8250_device *dev, void *data)
 	/* Break issued ? */
 	if (dev->lsr & UART_LSR_BI) {
 		dev->lsr &= ~UART_LSR_BI;
-		ioport__write8(data, 0);
+		*data = 0;
 		return;
 	}
 
-	ioport__write8(data, dev->rxbuf[dev->rxdone++]);
+	*data = dev->rxbuf[dev->rxdone++];
 	if (dev->rxcnt == dev->rxdone) {
 		dev->lsr &= ~UART_LSR_DR;
 		dev->rxcnt = dev->rxdone = 0;
 	}
 }
 
-static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static bool serial8250_in(struct serial8250_device *dev, struct kvm_cpu *vcpu,
+			  u16 offset, u8 *data)
 {
-	struct serial8250_device *dev = ioport->priv;
-	u16 offset;
 	bool ret = true;
 
 	mutex_lock(&dev->mutex);
 
-	offset = port - dev->iobase;
-
 	switch (offset) {
 	case UART_RX:
 		if (dev->lcr & UART_LCR_DLAB)
-			ioport__write8(data, dev->dll);
+			*data = dev->dll;
 		else
 			serial8250_rx(dev, data);
 		break;
 	case UART_IER:
 		if (dev->lcr & UART_LCR_DLAB)
-			ioport__write8(data, dev->dlm);
+			*data = dev->dlm;
 		else
-			ioport__write8(data, dev->ier);
+			*data = dev->ier;
 		break;
 	case UART_IIR:
-		ioport__write8(data, dev->iir | UART_IIR_TYPE_BITS);
+		*data = dev->iir | UART_IIR_TYPE_BITS;
 		break;
 	case UART_LCR:
-		ioport__write8(data, dev->lcr);
+		*data = dev->lcr;
 		break;
 	case UART_MCR:
-		ioport__write8(data, dev->mcr);
+		*data = dev->mcr;
 		break;
 	case UART_LSR:
-		ioport__write8(data, dev->lsr);
+		*data = dev->lsr;
 		break;
 	case UART_MSR:
-		ioport__write8(data, dev->msr);
+		*data = dev->msr;
 		break;
 	case UART_SCR:
-		ioport__write8(data, dev->scr);
+		*data = dev->scr;
 		break;
 	default:
 		ret = false;
@@ -389,6 +381,37 @@ static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port,
 	return ret;
 }
 
+static void serial8250_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+			    u8 is_write, void *ptr)
+{
+	struct serial8250_device *dev = ptr;
+
+	if (is_write)
+		serial8250_out(dev, vcpu, addr - dev->iobase, *data);
+	else
+		serial8250_in(dev, vcpu, addr - dev->iobase, data);
+}
+
+static bool serial8250_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
+				  u16 port, void *data, int size)
+{
+	struct serial8250_device *dev = ioport->priv;
+
+	serial8250_mmio(vcpu, port, data, 1, true, dev);
+
+	return true;
+}
+
+static bool serial8250_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
+				 u16 port, void *data, int size)
+{
+	struct serial8250_device *dev = ioport->priv;
+
+	serial8250_mmio(vcpu, port, data, 1, false, dev);
+
+	return true;
+}
+
 #ifdef CONFIG_HAS_LIBFDT
 
 char *fdt_stdout_path = NULL;
@@ -427,8 +450,8 @@ void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
 #endif
 
 static struct ioport_operations serial8250_ops = {
-	.io_in			= serial8250_in,
-	.io_out			= serial8250_out,
+	.io_in			= serial8250_ioport_in,
+	.io_out			= serial8250_ioport_out,
 };
 
 static int serial8250__device_init(struct kvm *kvm,
-- 
2.17.5


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

* [PATCH kvmtool v2 13/22] hw/serial: Refactor trap handler
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Adjust the trap handler to use that new function, and provide shims to
implement the old ioport interface, for now.

We drop the usage of ioport__read8/write8 entirely, as this would only
be applicable for I/O port accesses, and does nothing for 8-bit wide
accesses anyway.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 hw/serial.c | 93 +++++++++++++++++++++++++++++++++--------------------
 1 file changed, 58 insertions(+), 35 deletions(-)

diff --git a/hw/serial.c b/hw/serial.c
index b0465d99..c495eac1 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -242,36 +242,31 @@ void serial8250__inject_sysrq(struct kvm *kvm, char sysrq)
 	sysrq_pending = sysrq;
 }
 
-static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port,
-			   void *data, int size)
+static bool serial8250_out(struct serial8250_device *dev, struct kvm_cpu *vcpu,
+			   u16 offset, u8 data)
 {
-	struct serial8250_device *dev = ioport->priv;
-	u16 offset;
 	bool ret = true;
-	char *addr = data;
 
 	mutex_lock(&dev->mutex);
 
-	offset = port - dev->iobase;
-
 	switch (offset) {
 	case UART_TX:
 		if (dev->lcr & UART_LCR_DLAB) {
-			dev->dll = ioport__read8(data);
+			dev->dll = data;
 			break;
 		}
 
 		/* Loopback mode */
 		if (dev->mcr & UART_MCR_LOOP) {
 			if (dev->rxcnt < FIFO_LEN) {
-				dev->rxbuf[dev->rxcnt++] = *addr;
+				dev->rxbuf[dev->rxcnt++] = data;
 				dev->lsr |= UART_LSR_DR;
 			}
 			break;
 		}
 
 		if (dev->txcnt < FIFO_LEN) {
-			dev->txbuf[dev->txcnt++] = *addr;
+			dev->txbuf[dev->txcnt++] = data;
 			dev->lsr &= ~UART_LSR_TEMT;
 			if (dev->txcnt == FIFO_LEN / 2)
 				dev->lsr &= ~UART_LSR_THRE;
@@ -283,18 +278,18 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
 		break;
 	case UART_IER:
 		if (!(dev->lcr & UART_LCR_DLAB))
-			dev->ier = ioport__read8(data) & 0x0f;
+			dev->ier = data & 0x0f;
 		else
-			dev->dlm = ioport__read8(data);
+			dev->dlm = data;
 		break;
 	case UART_FCR:
-		dev->fcr = ioport__read8(data);
+		dev->fcr = data;
 		break;
 	case UART_LCR:
-		dev->lcr = ioport__read8(data);
+		dev->lcr = data;
 		break;
 	case UART_MCR:
-		dev->mcr = ioport__read8(data);
+		dev->mcr = data;
 		break;
 	case UART_LSR:
 		/* Factory test */
@@ -303,7 +298,7 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
 		/* Not used */
 		break;
 	case UART_SCR:
-		dev->scr = ioport__read8(data);
+		dev->scr = data;
 		break;
 	default:
 		ret = false;
@@ -317,7 +312,7 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
 	return ret;
 }
 
-static void serial8250_rx(struct serial8250_device *dev, void *data)
+static void serial8250_rx(struct serial8250_device *dev, u8 *data)
 {
 	if (dev->rxdone == dev->rxcnt)
 		return;
@@ -325,57 +320,54 @@ static void serial8250_rx(struct serial8250_device *dev, void *data)
 	/* Break issued ? */
 	if (dev->lsr & UART_LSR_BI) {
 		dev->lsr &= ~UART_LSR_BI;
-		ioport__write8(data, 0);
+		*data = 0;
 		return;
 	}
 
-	ioport__write8(data, dev->rxbuf[dev->rxdone++]);
+	*data = dev->rxbuf[dev->rxdone++];
 	if (dev->rxcnt == dev->rxdone) {
 		dev->lsr &= ~UART_LSR_DR;
 		dev->rxcnt = dev->rxdone = 0;
 	}
 }
 
-static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static bool serial8250_in(struct serial8250_device *dev, struct kvm_cpu *vcpu,
+			  u16 offset, u8 *data)
 {
-	struct serial8250_device *dev = ioport->priv;
-	u16 offset;
 	bool ret = true;
 
 	mutex_lock(&dev->mutex);
 
-	offset = port - dev->iobase;
-
 	switch (offset) {
 	case UART_RX:
 		if (dev->lcr & UART_LCR_DLAB)
-			ioport__write8(data, dev->dll);
+			*data = dev->dll;
 		else
 			serial8250_rx(dev, data);
 		break;
 	case UART_IER:
 		if (dev->lcr & UART_LCR_DLAB)
-			ioport__write8(data, dev->dlm);
+			*data = dev->dlm;
 		else
-			ioport__write8(data, dev->ier);
+			*data = dev->ier;
 		break;
 	case UART_IIR:
-		ioport__write8(data, dev->iir | UART_IIR_TYPE_BITS);
+		*data = dev->iir | UART_IIR_TYPE_BITS;
 		break;
 	case UART_LCR:
-		ioport__write8(data, dev->lcr);
+		*data = dev->lcr;
 		break;
 	case UART_MCR:
-		ioport__write8(data, dev->mcr);
+		*data = dev->mcr;
 		break;
 	case UART_LSR:
-		ioport__write8(data, dev->lsr);
+		*data = dev->lsr;
 		break;
 	case UART_MSR:
-		ioport__write8(data, dev->msr);
+		*data = dev->msr;
 		break;
 	case UART_SCR:
-		ioport__write8(data, dev->scr);
+		*data = dev->scr;
 		break;
 	default:
 		ret = false;
@@ -389,6 +381,37 @@ static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port,
 	return ret;
 }
 
+static void serial8250_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+			    u8 is_write, void *ptr)
+{
+	struct serial8250_device *dev = ptr;
+
+	if (is_write)
+		serial8250_out(dev, vcpu, addr - dev->iobase, *data);
+	else
+		serial8250_in(dev, vcpu, addr - dev->iobase, data);
+}
+
+static bool serial8250_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
+				  u16 port, void *data, int size)
+{
+	struct serial8250_device *dev = ioport->priv;
+
+	serial8250_mmio(vcpu, port, data, 1, true, dev);
+
+	return true;
+}
+
+static bool serial8250_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
+				 u16 port, void *data, int size)
+{
+	struct serial8250_device *dev = ioport->priv;
+
+	serial8250_mmio(vcpu, port, data, 1, false, dev);
+
+	return true;
+}
+
 #ifdef CONFIG_HAS_LIBFDT
 
 char *fdt_stdout_path = NULL;
@@ -427,8 +450,8 @@ void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
 #endif
 
 static struct ioport_operations serial8250_ops = {
-	.io_in			= serial8250_in,
-	.io_out			= serial8250_out,
+	.io_in			= serial8250_ioport_in,
+	.io_out			= serial8250_ioport_out,
 };
 
 static int serial8250__device_init(struct kvm *kvm,
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 14/22] hw/serial: Switch to new trap handlers
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

Now that the serial device has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 hw/serial.c | 31 +++----------------------------
 1 file changed, 3 insertions(+), 28 deletions(-)

diff --git a/hw/serial.c b/hw/serial.c
index c495eac1..4be188a1 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -392,26 +392,6 @@ static void serial8250_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
 		serial8250_in(dev, vcpu, addr - dev->iobase, data);
 }
 
-static bool serial8250_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
-				  u16 port, void *data, int size)
-{
-	struct serial8250_device *dev = ioport->priv;
-
-	serial8250_mmio(vcpu, port, data, 1, true, dev);
-
-	return true;
-}
-
-static bool serial8250_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
-				 u16 port, void *data, int size)
-{
-	struct serial8250_device *dev = ioport->priv;
-
-	serial8250_mmio(vcpu, port, data, 1, false, dev);
-
-	return true;
-}
-
 #ifdef CONFIG_HAS_LIBFDT
 
 char *fdt_stdout_path = NULL;
@@ -449,11 +429,6 @@ void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
 }
 #endif
 
-static struct ioport_operations serial8250_ops = {
-	.io_in			= serial8250_ioport_in,
-	.io_out			= serial8250_ioport_out,
-};
-
 static int serial8250__device_init(struct kvm *kvm,
 				   struct serial8250_device *dev)
 {
@@ -464,7 +439,7 @@ static int serial8250__device_init(struct kvm *kvm,
 		return r;
 
 	ioport__map_irq(&dev->irq);
-	r = ioport__register(kvm, dev->iobase, &serial8250_ops, 8, dev);
+	r = kvm__register_pio(kvm, dev->iobase, 8, serial8250_mmio, dev);
 
 	return r;
 }
@@ -487,7 +462,7 @@ cleanup:
 	for (j = 0; j <= i; j++) {
 		struct serial8250_device *dev = &devices[j];
 
-		ioport__unregister(kvm, dev->iobase);
+		kvm__deregister_pio(kvm, dev->iobase);
 		device__unregister(&dev->dev_hdr);
 	}
 
@@ -503,7 +478,7 @@ int serial8250__exit(struct kvm *kvm)
 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
 		struct serial8250_device *dev = &devices[i];
 
-		r = ioport__unregister(kvm, dev->iobase);
+		r = kvm__deregister_pio(kvm, dev->iobase);
 		if (r < 0)
 			return r;
 		device__unregister(&dev->dev_hdr);
-- 
2.17.5


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

* [PATCH kvmtool v2 14/22] hw/serial: Switch to new trap handlers
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Now that the serial device has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 hw/serial.c | 31 +++----------------------------
 1 file changed, 3 insertions(+), 28 deletions(-)

diff --git a/hw/serial.c b/hw/serial.c
index c495eac1..4be188a1 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -392,26 +392,6 @@ static void serial8250_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
 		serial8250_in(dev, vcpu, addr - dev->iobase, data);
 }
 
-static bool serial8250_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
-				  u16 port, void *data, int size)
-{
-	struct serial8250_device *dev = ioport->priv;
-
-	serial8250_mmio(vcpu, port, data, 1, true, dev);
-
-	return true;
-}
-
-static bool serial8250_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
-				 u16 port, void *data, int size)
-{
-	struct serial8250_device *dev = ioport->priv;
-
-	serial8250_mmio(vcpu, port, data, 1, false, dev);
-
-	return true;
-}
-
 #ifdef CONFIG_HAS_LIBFDT
 
 char *fdt_stdout_path = NULL;
@@ -449,11 +429,6 @@ void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
 }
 #endif
 
-static struct ioport_operations serial8250_ops = {
-	.io_in			= serial8250_ioport_in,
-	.io_out			= serial8250_ioport_out,
-};
-
 static int serial8250__device_init(struct kvm *kvm,
 				   struct serial8250_device *dev)
 {
@@ -464,7 +439,7 @@ static int serial8250__device_init(struct kvm *kvm,
 		return r;
 
 	ioport__map_irq(&dev->irq);
-	r = ioport__register(kvm, dev->iobase, &serial8250_ops, 8, dev);
+	r = kvm__register_pio(kvm, dev->iobase, 8, serial8250_mmio, dev);
 
 	return r;
 }
@@ -487,7 +462,7 @@ cleanup:
 	for (j = 0; j <= i; j++) {
 		struct serial8250_device *dev = &devices[j];
 
-		ioport__unregister(kvm, dev->iobase);
+		kvm__deregister_pio(kvm, dev->iobase);
 		device__unregister(&dev->dev_hdr);
 	}
 
@@ -503,7 +478,7 @@ int serial8250__exit(struct kvm *kvm)
 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
 		struct serial8250_device *dev = &devices[i];
 
-		r = ioport__unregister(kvm, dev->iobase);
+		r = kvm__deregister_pio(kvm, dev->iobase);
 		if (r < 0)
 			return r;
 		device__unregister(&dev->dev_hdr);
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 15/22] vfio: Refactor ioport trap handler
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Adjust the I/O port trap handler to use that new function, and provide
shims to implement the old ioport interface, for now.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 vfio/core.c | 51 ++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 36 insertions(+), 15 deletions(-)

diff --git a/vfio/core.c b/vfio/core.c
index 0b45e78b..ddd3c2c7 100644
--- a/vfio/core.c
+++ b/vfio/core.c
@@ -81,15 +81,12 @@ out_free_buf:
 	return ret;
 }
 
-static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
-			   u16 port, void *data, int len)
+static bool _vfio_ioport_in(struct vfio_region *region, u32 offset,
+			    void *data, int len)
 {
-	u32 val;
-	ssize_t nr;
-	struct vfio_region *region = ioport->priv;
 	struct vfio_device *vdev = region->vdev;
-
-	u32 offset = port - region->port_base;
+	ssize_t nr;
+	u32 val;
 
 	if (!(region->info.flags & VFIO_REGION_INFO_FLAG_READ))
 		return false;
@@ -97,7 +94,7 @@ static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
 	nr = pread(vdev->fd, &val, len, region->info.offset + offset);
 	if (nr != len) {
 		vfio_dev_err(vdev, "could not read %d bytes from I/O port 0x%x\n",
-			     len, port);
+			     len, offset + region->port_base);
 		return false;
 	}
 
@@ -118,15 +115,13 @@ static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
 	return true;
 }
 
-static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
-			    u16 port, void *data, int len)
+static bool _vfio_ioport_out(struct vfio_region *region, u32 offset,
+			     void *data, int len)
 {
-	u32 val;
-	ssize_t nr;
-	struct vfio_region *region = ioport->priv;
 	struct vfio_device *vdev = region->vdev;
+	ssize_t nr;
+	u32 val;
 
-	u32 offset = port - region->port_base;
 
 	if (!(region->info.flags & VFIO_REGION_INFO_FLAG_WRITE))
 		return false;
@@ -148,11 +143,37 @@ static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
 	nr = pwrite(vdev->fd, &val, len, region->info.offset + offset);
 	if (nr != len)
 		vfio_dev_err(vdev, "could not write %d bytes to I/O port 0x%x",
-			     len, port);
+			     len, offset + region->port_base);
 
 	return nr == len;
 }
 
+static void vfio_ioport_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+			     u8 is_write, void *ptr)
+{
+	struct vfio_region *region = ptr;
+	u32 offset = addr - region->port_base;
+
+	if (is_write)
+		_vfio_ioport_out(region, offset, data, len);
+	else
+		_vfio_ioport_in(region, offset, data, len);
+}
+
+static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
+			    u16 port, void *data, int len)
+{
+	vfio_ioport_mmio(vcpu, port, data, len, true, ioport->priv);
+	return true;
+}
+
+static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
+			   u16 port, void *data, int len)
+{
+	vfio_ioport_mmio(vcpu, port, data, len, false, ioport->priv);
+	return true;
+}
+
 static struct ioport_operations vfio_ioport_ops = {
 	.io_in	= vfio_ioport_in,
 	.io_out	= vfio_ioport_out,
-- 
2.17.5


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

* [PATCH kvmtool v2 15/22] vfio: Refactor ioport trap handler
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Adjust the I/O port trap handler to use that new function, and provide
shims to implement the old ioport interface, for now.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 vfio/core.c | 51 ++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 36 insertions(+), 15 deletions(-)

diff --git a/vfio/core.c b/vfio/core.c
index 0b45e78b..ddd3c2c7 100644
--- a/vfio/core.c
+++ b/vfio/core.c
@@ -81,15 +81,12 @@ out_free_buf:
 	return ret;
 }
 
-static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
-			   u16 port, void *data, int len)
+static bool _vfio_ioport_in(struct vfio_region *region, u32 offset,
+			    void *data, int len)
 {
-	u32 val;
-	ssize_t nr;
-	struct vfio_region *region = ioport->priv;
 	struct vfio_device *vdev = region->vdev;
-
-	u32 offset = port - region->port_base;
+	ssize_t nr;
+	u32 val;
 
 	if (!(region->info.flags & VFIO_REGION_INFO_FLAG_READ))
 		return false;
@@ -97,7 +94,7 @@ static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
 	nr = pread(vdev->fd, &val, len, region->info.offset + offset);
 	if (nr != len) {
 		vfio_dev_err(vdev, "could not read %d bytes from I/O port 0x%x\n",
-			     len, port);
+			     len, offset + region->port_base);
 		return false;
 	}
 
@@ -118,15 +115,13 @@ static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
 	return true;
 }
 
-static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
-			    u16 port, void *data, int len)
+static bool _vfio_ioport_out(struct vfio_region *region, u32 offset,
+			     void *data, int len)
 {
-	u32 val;
-	ssize_t nr;
-	struct vfio_region *region = ioport->priv;
 	struct vfio_device *vdev = region->vdev;
+	ssize_t nr;
+	u32 val;
 
-	u32 offset = port - region->port_base;
 
 	if (!(region->info.flags & VFIO_REGION_INFO_FLAG_WRITE))
 		return false;
@@ -148,11 +143,37 @@ static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
 	nr = pwrite(vdev->fd, &val, len, region->info.offset + offset);
 	if (nr != len)
 		vfio_dev_err(vdev, "could not write %d bytes to I/O port 0x%x",
-			     len, port);
+			     len, offset + region->port_base);
 
 	return nr == len;
 }
 
+static void vfio_ioport_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+			     u8 is_write, void *ptr)
+{
+	struct vfio_region *region = ptr;
+	u32 offset = addr - region->port_base;
+
+	if (is_write)
+		_vfio_ioport_out(region, offset, data, len);
+	else
+		_vfio_ioport_in(region, offset, data, len);
+}
+
+static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
+			    u16 port, void *data, int len)
+{
+	vfio_ioport_mmio(vcpu, port, data, len, true, ioport->priv);
+	return true;
+}
+
+static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
+			   u16 port, void *data, int len)
+{
+	vfio_ioport_mmio(vcpu, port, data, len, false, ioport->priv);
+	return true;
+}
+
 static struct ioport_operations vfio_ioport_ops = {
 	.io_in	= vfio_ioport_in,
 	.io_out	= vfio_ioport_out,
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 16/22] vfio: Switch to new ioport trap handlers
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

Now that the vfio device has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 vfio/core.c | 37 ++++++++++---------------------------
 1 file changed, 10 insertions(+), 27 deletions(-)

diff --git a/vfio/core.c b/vfio/core.c
index ddd3c2c7..3ff2c0b0 100644
--- a/vfio/core.c
+++ b/vfio/core.c
@@ -81,7 +81,7 @@ out_free_buf:
 	return ret;
 }
 
-static bool _vfio_ioport_in(struct vfio_region *region, u32 offset,
+static bool vfio_ioport_in(struct vfio_region *region, u32 offset,
 			    void *data, int len)
 {
 	struct vfio_device *vdev = region->vdev;
@@ -115,7 +115,7 @@ static bool _vfio_ioport_in(struct vfio_region *region, u32 offset,
 	return true;
 }
 
-static bool _vfio_ioport_out(struct vfio_region *region, u32 offset,
+static bool vfio_ioport_out(struct vfio_region *region, u32 offset,
 			     void *data, int len)
 {
 	struct vfio_device *vdev = region->vdev;
@@ -155,30 +155,11 @@ static void vfio_ioport_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
 	u32 offset = addr - region->port_base;
 
 	if (is_write)
-		_vfio_ioport_out(region, offset, data, len);
+		vfio_ioport_out(region, offset, data, len);
 	else
-		_vfio_ioport_in(region, offset, data, len);
+		vfio_ioport_in(region, offset, data, len);
 }
 
-static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
-			    u16 port, void *data, int len)
-{
-	vfio_ioport_mmio(vcpu, port, data, len, true, ioport->priv);
-	return true;
-}
-
-static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
-			   u16 port, void *data, int len)
-{
-	vfio_ioport_mmio(vcpu, port, data, len, false, ioport->priv);
-	return true;
-}
-
-static struct ioport_operations vfio_ioport_ops = {
-	.io_in	= vfio_ioport_in,
-	.io_out	= vfio_ioport_out,
-};
-
 static void vfio_mmio_access(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
 			     u8 is_write, void *ptr)
 {
@@ -223,9 +204,11 @@ static int vfio_setup_trap_region(struct kvm *kvm, struct vfio_device *vdev,
 				  struct vfio_region *region)
 {
 	if (region->is_ioport) {
-		int port = ioport__register(kvm, region->port_base,
-					   &vfio_ioport_ops, region->info.size,
-					   region);
+		int port;
+
+		port = kvm__register_pio(kvm, region->port_base,
+					 region->info.size, vfio_ioport_mmio,
+					 region);
 		if (port < 0)
 			return port;
 		return 0;
@@ -292,7 +275,7 @@ void vfio_unmap_region(struct kvm *kvm, struct vfio_region *region)
 		munmap(region->host_addr, region->info.size);
 		region->host_addr = NULL;
 	} else if (region->is_ioport) {
-		ioport__unregister(kvm, region->port_base);
+		kvm__deregister_pio(kvm, region->port_base);
 	} else {
 		kvm__deregister_mmio(kvm, region->guest_phys_addr);
 	}
-- 
2.17.5


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

* [PATCH kvmtool v2 16/22] vfio: Switch to new ioport trap handlers
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Now that the vfio device has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 vfio/core.c | 37 ++++++++++---------------------------
 1 file changed, 10 insertions(+), 27 deletions(-)

diff --git a/vfio/core.c b/vfio/core.c
index ddd3c2c7..3ff2c0b0 100644
--- a/vfio/core.c
+++ b/vfio/core.c
@@ -81,7 +81,7 @@ out_free_buf:
 	return ret;
 }
 
-static bool _vfio_ioport_in(struct vfio_region *region, u32 offset,
+static bool vfio_ioport_in(struct vfio_region *region, u32 offset,
 			    void *data, int len)
 {
 	struct vfio_device *vdev = region->vdev;
@@ -115,7 +115,7 @@ static bool _vfio_ioport_in(struct vfio_region *region, u32 offset,
 	return true;
 }
 
-static bool _vfio_ioport_out(struct vfio_region *region, u32 offset,
+static bool vfio_ioport_out(struct vfio_region *region, u32 offset,
 			     void *data, int len)
 {
 	struct vfio_device *vdev = region->vdev;
@@ -155,30 +155,11 @@ static void vfio_ioport_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
 	u32 offset = addr - region->port_base;
 
 	if (is_write)
-		_vfio_ioport_out(region, offset, data, len);
+		vfio_ioport_out(region, offset, data, len);
 	else
-		_vfio_ioport_in(region, offset, data, len);
+		vfio_ioport_in(region, offset, data, len);
 }
 
-static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
-			    u16 port, void *data, int len)
-{
-	vfio_ioport_mmio(vcpu, port, data, len, true, ioport->priv);
-	return true;
-}
-
-static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
-			   u16 port, void *data, int len)
-{
-	vfio_ioport_mmio(vcpu, port, data, len, false, ioport->priv);
-	return true;
-}
-
-static struct ioport_operations vfio_ioport_ops = {
-	.io_in	= vfio_ioport_in,
-	.io_out	= vfio_ioport_out,
-};
-
 static void vfio_mmio_access(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
 			     u8 is_write, void *ptr)
 {
@@ -223,9 +204,11 @@ static int vfio_setup_trap_region(struct kvm *kvm, struct vfio_device *vdev,
 				  struct vfio_region *region)
 {
 	if (region->is_ioport) {
-		int port = ioport__register(kvm, region->port_base,
-					   &vfio_ioport_ops, region->info.size,
-					   region);
+		int port;
+
+		port = kvm__register_pio(kvm, region->port_base,
+					 region->info.size, vfio_ioport_mmio,
+					 region);
 		if (port < 0)
 			return port;
 		return 0;
@@ -292,7 +275,7 @@ void vfio_unmap_region(struct kvm *kvm, struct vfio_region *region)
 		munmap(region->host_addr, region->info.size);
 		region->host_addr = NULL;
 	} else if (region->is_ioport) {
-		ioport__unregister(kvm, region->port_base);
+		kvm__deregister_pio(kvm, region->port_base);
 	} else {
 		kvm__deregister_mmio(kvm, region->guest_phys_addr);
 	}
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 17/22] virtio: Switch trap handling to use MMIO handler
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Adjust the existing MMIO callback routine to automatically determine
the region this trap came through, and call the existing I/O handlers.
Register the ioport region using the new registration function.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 virtio/pci.c | 46 ++++++++++++++--------------------------------
 1 file changed, 14 insertions(+), 32 deletions(-)

diff --git a/virtio/pci.c b/virtio/pci.c
index 6eea6c68..eb91f512 100644
--- a/virtio/pci.c
+++ b/virtio/pci.c
@@ -178,15 +178,6 @@ static bool virtio_pci__data_in(struct kvm_cpu *vcpu, struct virtio_device *vdev
 	return ret;
 }
 
-static bool virtio_pci__io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	struct virtio_device *vdev = ioport->priv;
-	struct virtio_pci *vpci = vdev->virtio;
-	unsigned long offset = port - virtio_pci__port_addr(vpci);
-
-	return virtio_pci__data_in(vcpu, vdev, offset, data, size);
-}
-
 static void update_msix_map(struct virtio_pci *vpci,
 			    struct msix_table *msix_entry, u32 vecnum)
 {
@@ -334,20 +325,6 @@ static bool virtio_pci__data_out(struct kvm_cpu *vcpu, struct virtio_device *vde
 	return ret;
 }
 
-static bool virtio_pci__io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	struct virtio_device *vdev = ioport->priv;
-	struct virtio_pci *vpci = vdev->virtio;
-	unsigned long offset = port - virtio_pci__port_addr(vpci);
-
-	return virtio_pci__data_out(vcpu, vdev, offset, data, size);
-}
-
-static struct ioport_operations virtio_pci__io_ops = {
-	.io_in	= virtio_pci__io_in,
-	.io_out	= virtio_pci__io_out,
-};
-
 static void virtio_pci__msix_mmio_callback(struct kvm_cpu *vcpu,
 					   u64 addr, u8 *data, u32 len,
 					   u8 is_write, void *ptr)
@@ -455,12 +432,19 @@ static void virtio_pci__io_mmio_callback(struct kvm_cpu *vcpu,
 {
 	struct virtio_device *vdev = ptr;
 	struct virtio_pci *vpci = vdev->virtio;
-	u32 mmio_addr = virtio_pci__mmio_addr(vpci);
+	u32 ioport_addr = virtio_pci__port_addr(vpci);
+	u32 base_addr;
+
+	if (addr >= ioport_addr &&
+	    addr < ioport_addr + pci__bar_size(&vpci->pci_hdr, 0))
+		base_addr = ioport_addr;
+	else
+		base_addr = virtio_pci__mmio_addr(vpci);
 
 	if (!is_write)
-		virtio_pci__data_in(vcpu, vdev, addr - mmio_addr, data, len);
+		virtio_pci__data_in(vcpu, vdev, addr - base_addr, data, len);
 	else
-		virtio_pci__data_out(vcpu, vdev, addr - mmio_addr, data, len);
+		virtio_pci__data_out(vcpu, vdev, addr - base_addr, data, len);
 }
 
 static int virtio_pci__bar_activate(struct kvm *kvm,
@@ -478,10 +462,8 @@ static int virtio_pci__bar_activate(struct kvm *kvm,
 
 	switch (bar_num) {
 	case 0:
-		r = ioport__register(kvm, bar_addr, &virtio_pci__io_ops,
-				     bar_size, vdev);
-		if (r > 0)
-			r = 0;
+		r = kvm__register_pio(kvm, bar_addr, bar_size,
+				      virtio_pci__io_mmio_callback, vdev);
 		break;
 	case 1:
 		r =  kvm__register_mmio(kvm, bar_addr, bar_size, false,
@@ -510,7 +492,7 @@ static int virtio_pci__bar_deactivate(struct kvm *kvm,
 
 	switch (bar_num) {
 	case 0:
-		r = ioport__unregister(kvm, bar_addr);
+		r = kvm__deregister_pio(kvm, bar_addr);
 		break;
 	case 1:
 	case 2:
@@ -625,7 +607,7 @@ int virtio_pci__exit(struct kvm *kvm, struct virtio_device *vdev)
 	virtio_pci__reset(kvm, vdev);
 	kvm__deregister_mmio(kvm, virtio_pci__mmio_addr(vpci));
 	kvm__deregister_mmio(kvm, virtio_pci__msix_io_addr(vpci));
-	ioport__unregister(kvm, virtio_pci__port_addr(vpci));
+	kvm__deregister_pio(kvm, virtio_pci__port_addr(vpci));
 
 	return 0;
 }
-- 
2.17.5


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

* [PATCH kvmtool v2 17/22] virtio: Switch trap handling to use MMIO handler
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Adjust the existing MMIO callback routine to automatically determine
the region this trap came through, and call the existing I/O handlers.
Register the ioport region using the new registration function.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 virtio/pci.c | 46 ++++++++++++++--------------------------------
 1 file changed, 14 insertions(+), 32 deletions(-)

diff --git a/virtio/pci.c b/virtio/pci.c
index 6eea6c68..eb91f512 100644
--- a/virtio/pci.c
+++ b/virtio/pci.c
@@ -178,15 +178,6 @@ static bool virtio_pci__data_in(struct kvm_cpu *vcpu, struct virtio_device *vdev
 	return ret;
 }
 
-static bool virtio_pci__io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	struct virtio_device *vdev = ioport->priv;
-	struct virtio_pci *vpci = vdev->virtio;
-	unsigned long offset = port - virtio_pci__port_addr(vpci);
-
-	return virtio_pci__data_in(vcpu, vdev, offset, data, size);
-}
-
 static void update_msix_map(struct virtio_pci *vpci,
 			    struct msix_table *msix_entry, u32 vecnum)
 {
@@ -334,20 +325,6 @@ static bool virtio_pci__data_out(struct kvm_cpu *vcpu, struct virtio_device *vde
 	return ret;
 }
 
-static bool virtio_pci__io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	struct virtio_device *vdev = ioport->priv;
-	struct virtio_pci *vpci = vdev->virtio;
-	unsigned long offset = port - virtio_pci__port_addr(vpci);
-
-	return virtio_pci__data_out(vcpu, vdev, offset, data, size);
-}
-
-static struct ioport_operations virtio_pci__io_ops = {
-	.io_in	= virtio_pci__io_in,
-	.io_out	= virtio_pci__io_out,
-};
-
 static void virtio_pci__msix_mmio_callback(struct kvm_cpu *vcpu,
 					   u64 addr, u8 *data, u32 len,
 					   u8 is_write, void *ptr)
@@ -455,12 +432,19 @@ static void virtio_pci__io_mmio_callback(struct kvm_cpu *vcpu,
 {
 	struct virtio_device *vdev = ptr;
 	struct virtio_pci *vpci = vdev->virtio;
-	u32 mmio_addr = virtio_pci__mmio_addr(vpci);
+	u32 ioport_addr = virtio_pci__port_addr(vpci);
+	u32 base_addr;
+
+	if (addr >= ioport_addr &&
+	    addr < ioport_addr + pci__bar_size(&vpci->pci_hdr, 0))
+		base_addr = ioport_addr;
+	else
+		base_addr = virtio_pci__mmio_addr(vpci);
 
 	if (!is_write)
-		virtio_pci__data_in(vcpu, vdev, addr - mmio_addr, data, len);
+		virtio_pci__data_in(vcpu, vdev, addr - base_addr, data, len);
 	else
-		virtio_pci__data_out(vcpu, vdev, addr - mmio_addr, data, len);
+		virtio_pci__data_out(vcpu, vdev, addr - base_addr, data, len);
 }
 
 static int virtio_pci__bar_activate(struct kvm *kvm,
@@ -478,10 +462,8 @@ static int virtio_pci__bar_activate(struct kvm *kvm,
 
 	switch (bar_num) {
 	case 0:
-		r = ioport__register(kvm, bar_addr, &virtio_pci__io_ops,
-				     bar_size, vdev);
-		if (r > 0)
-			r = 0;
+		r = kvm__register_pio(kvm, bar_addr, bar_size,
+				      virtio_pci__io_mmio_callback, vdev);
 		break;
 	case 1:
 		r =  kvm__register_mmio(kvm, bar_addr, bar_size, false,
@@ -510,7 +492,7 @@ static int virtio_pci__bar_deactivate(struct kvm *kvm,
 
 	switch (bar_num) {
 	case 0:
-		r = ioport__unregister(kvm, bar_addr);
+		r = kvm__deregister_pio(kvm, bar_addr);
 		break;
 	case 1:
 	case 2:
@@ -625,7 +607,7 @@ int virtio_pci__exit(struct kvm *kvm, struct virtio_device *vdev)
 	virtio_pci__reset(kvm, vdev);
 	kvm__deregister_mmio(kvm, virtio_pci__mmio_addr(vpci));
 	kvm__deregister_mmio(kvm, virtio_pci__msix_io_addr(vpci));
-	ioport__unregister(kvm, virtio_pci__port_addr(vpci));
+	kvm__deregister_pio(kvm, virtio_pci__port_addr(vpci));
 
 	return 0;
 }
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 18/22] pci: Switch trap handling to use MMIO handler
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Merge the existing _in and _out handlers to adhere to that MMIO
interface, and register these using the new registration function.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 pci.c | 82 +++++++++++++++++------------------------------------------
 1 file changed, 24 insertions(+), 58 deletions(-)

diff --git a/pci.c b/pci.c
index 2e2c0270..d6da79e0 100644
--- a/pci.c
+++ b/pci.c
@@ -87,29 +87,16 @@ static void *pci_config_address_ptr(u16 port)
 	return base + offset;
 }
 
-static bool pci_config_address_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void pci_config_address_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+				    u32 len, u8 is_write, void *ptr)
 {
-	void *p = pci_config_address_ptr(port);
+	void *p = pci_config_address_ptr(addr);
 
-	memcpy(p, data, size);
-
-	return true;
-}
-
-static bool pci_config_address_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	void *p = pci_config_address_ptr(port);
-
-	memcpy(data, p, size);
-
-	return true;
+	if (is_write)
+		memcpy(p, data, len);
+	else
+		memcpy(data, p, len);
 }
-
-static struct ioport_operations pci_config_address_ops = {
-	.io_in	= pci_config_address_in,
-	.io_out	= pci_config_address_out,
-};
-
 static bool pci_device_exists(u8 bus_number, u8 device_number, u8 function_number)
 {
 	union pci_config_address pci_config_address;
@@ -125,49 +112,27 @@ static bool pci_device_exists(u8 bus_number, u8 device_number, u8 function_numbe
 	return !IS_ERR_OR_NULL(device__find_dev(DEVICE_BUS_PCI, device_number));
 }
 
-static bool pci_config_data_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	union pci_config_address pci_config_address;
-
-	if (size > 4)
-		size = 4;
-
-	pci_config_address.w = ioport__read32(&pci_config_address_bits);
-	/*
-	 * If someone accesses PCI configuration space offsets that are not
-	 * aligned to 4 bytes, it uses ioports to signify that.
-	 */
-	pci_config_address.reg_offset = port - PCI_CONFIG_DATA;
-
-	pci__config_wr(vcpu->kvm, pci_config_address, data, size);
-
-	return true;
-}
-
-static bool pci_config_data_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void pci_config_data_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+				 u32 len, u8 is_write, void *kvm)
 {
 	union pci_config_address pci_config_address;
 
-	if (size > 4)
-		size = 4;
+	if (len > 4)
+		len = 4;
 
 	pci_config_address.w = ioport__read32(&pci_config_address_bits);
 	/*
 	 * If someone accesses PCI configuration space offsets that are not
 	 * aligned to 4 bytes, it uses ioports to signify that.
 	 */
-	pci_config_address.reg_offset = port - PCI_CONFIG_DATA;
+	pci_config_address.reg_offset = addr - PCI_CONFIG_DATA;
 
-	pci__config_rd(vcpu->kvm, pci_config_address, data, size);
-
-	return true;
+	if (is_write)
+		pci__config_wr(vcpu->kvm, pci_config_address, data, len);
+	else
+		pci__config_rd(vcpu->kvm, pci_config_address, data, len);
 }
 
-static struct ioport_operations pci_config_data_ops = {
-	.io_in	= pci_config_data_in,
-	.io_out	= pci_config_data_out,
-};
-
 static int pci_activate_bar(struct kvm *kvm, struct pci_device_header *pci_hdr,
 			    int bar_num)
 {
@@ -512,11 +477,12 @@ int pci__init(struct kvm *kvm)
 {
 	int r;
 
-	r = ioport__register(kvm, PCI_CONFIG_DATA + 0, &pci_config_data_ops, 4, NULL);
+	r = kvm__register_pio(kvm, PCI_CONFIG_DATA, 4,
+				 pci_config_data_mmio, NULL);
 	if (r < 0)
 		return r;
-
-	r = ioport__register(kvm, PCI_CONFIG_ADDRESS + 0, &pci_config_address_ops, 4, NULL);
+	r = kvm__register_pio(kvm, PCI_CONFIG_ADDRESS, 4,
+				 pci_config_address_mmio, NULL);
 	if (r < 0)
 		goto err_unregister_data;
 
@@ -528,17 +494,17 @@ int pci__init(struct kvm *kvm)
 	return 0;
 
 err_unregister_addr:
-	ioport__unregister(kvm, PCI_CONFIG_ADDRESS);
+	kvm__deregister_pio(kvm, PCI_CONFIG_ADDRESS);
 err_unregister_data:
-	ioport__unregister(kvm, PCI_CONFIG_DATA);
+	kvm__deregister_pio(kvm, PCI_CONFIG_DATA);
 	return r;
 }
 dev_base_init(pci__init);
 
 int pci__exit(struct kvm *kvm)
 {
-	ioport__unregister(kvm, PCI_CONFIG_DATA);
-	ioport__unregister(kvm, PCI_CONFIG_ADDRESS);
+	kvm__deregister_pio(kvm, PCI_CONFIG_DATA);
+	kvm__deregister_pio(kvm, PCI_CONFIG_ADDRESS);
 
 	return 0;
 }
-- 
2.17.5


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

* [PATCH kvmtool v2 18/22] pci: Switch trap handling to use MMIO handler
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Merge the existing _in and _out handlers to adhere to that MMIO
interface, and register these using the new registration function.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 pci.c | 82 +++++++++++++++++------------------------------------------
 1 file changed, 24 insertions(+), 58 deletions(-)

diff --git a/pci.c b/pci.c
index 2e2c0270..d6da79e0 100644
--- a/pci.c
+++ b/pci.c
@@ -87,29 +87,16 @@ static void *pci_config_address_ptr(u16 port)
 	return base + offset;
 }
 
-static bool pci_config_address_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void pci_config_address_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+				    u32 len, u8 is_write, void *ptr)
 {
-	void *p = pci_config_address_ptr(port);
+	void *p = pci_config_address_ptr(addr);
 
-	memcpy(p, data, size);
-
-	return true;
-}
-
-static bool pci_config_address_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	void *p = pci_config_address_ptr(port);
-
-	memcpy(data, p, size);
-
-	return true;
+	if (is_write)
+		memcpy(p, data, len);
+	else
+		memcpy(data, p, len);
 }
-
-static struct ioport_operations pci_config_address_ops = {
-	.io_in	= pci_config_address_in,
-	.io_out	= pci_config_address_out,
-};
-
 static bool pci_device_exists(u8 bus_number, u8 device_number, u8 function_number)
 {
 	union pci_config_address pci_config_address;
@@ -125,49 +112,27 @@ static bool pci_device_exists(u8 bus_number, u8 device_number, u8 function_numbe
 	return !IS_ERR_OR_NULL(device__find_dev(DEVICE_BUS_PCI, device_number));
 }
 
-static bool pci_config_data_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
-{
-	union pci_config_address pci_config_address;
-
-	if (size > 4)
-		size = 4;
-
-	pci_config_address.w = ioport__read32(&pci_config_address_bits);
-	/*
-	 * If someone accesses PCI configuration space offsets that are not
-	 * aligned to 4 bytes, it uses ioports to signify that.
-	 */
-	pci_config_address.reg_offset = port - PCI_CONFIG_DATA;
-
-	pci__config_wr(vcpu->kvm, pci_config_address, data, size);
-
-	return true;
-}
-
-static bool pci_config_data_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void pci_config_data_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+				 u32 len, u8 is_write, void *kvm)
 {
 	union pci_config_address pci_config_address;
 
-	if (size > 4)
-		size = 4;
+	if (len > 4)
+		len = 4;
 
 	pci_config_address.w = ioport__read32(&pci_config_address_bits);
 	/*
 	 * If someone accesses PCI configuration space offsets that are not
 	 * aligned to 4 bytes, it uses ioports to signify that.
 	 */
-	pci_config_address.reg_offset = port - PCI_CONFIG_DATA;
+	pci_config_address.reg_offset = addr - PCI_CONFIG_DATA;
 
-	pci__config_rd(vcpu->kvm, pci_config_address, data, size);
-
-	return true;
+	if (is_write)
+		pci__config_wr(vcpu->kvm, pci_config_address, data, len);
+	else
+		pci__config_rd(vcpu->kvm, pci_config_address, data, len);
 }
 
-static struct ioport_operations pci_config_data_ops = {
-	.io_in	= pci_config_data_in,
-	.io_out	= pci_config_data_out,
-};
-
 static int pci_activate_bar(struct kvm *kvm, struct pci_device_header *pci_hdr,
 			    int bar_num)
 {
@@ -512,11 +477,12 @@ int pci__init(struct kvm *kvm)
 {
 	int r;
 
-	r = ioport__register(kvm, PCI_CONFIG_DATA + 0, &pci_config_data_ops, 4, NULL);
+	r = kvm__register_pio(kvm, PCI_CONFIG_DATA, 4,
+				 pci_config_data_mmio, NULL);
 	if (r < 0)
 		return r;
-
-	r = ioport__register(kvm, PCI_CONFIG_ADDRESS + 0, &pci_config_address_ops, 4, NULL);
+	r = kvm__register_pio(kvm, PCI_CONFIG_ADDRESS, 4,
+				 pci_config_address_mmio, NULL);
 	if (r < 0)
 		goto err_unregister_data;
 
@@ -528,17 +494,17 @@ int pci__init(struct kvm *kvm)
 	return 0;
 
 err_unregister_addr:
-	ioport__unregister(kvm, PCI_CONFIG_ADDRESS);
+	kvm__deregister_pio(kvm, PCI_CONFIG_ADDRESS);
 err_unregister_data:
-	ioport__unregister(kvm, PCI_CONFIG_DATA);
+	kvm__deregister_pio(kvm, PCI_CONFIG_DATA);
 	return r;
 }
 dev_base_init(pci__init);
 
 int pci__exit(struct kvm *kvm)
 {
-	ioport__unregister(kvm, PCI_CONFIG_DATA);
-	ioport__unregister(kvm, PCI_CONFIG_ADDRESS);
+	kvm__deregister_pio(kvm, PCI_CONFIG_DATA);
+	kvm__deregister_pio(kvm, PCI_CONFIG_ADDRESS);
 
 	return 0;
 }
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 19/22] Remove ioport specific routines
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

Now that all users of the dedicated ioport trap handler interface are
gone, we can retire the code associated with it.

This removes ioport.c and ioport.h, along with removing prototypes from
other header files.

This also transfers the responsibility for port I/O trap handling
entirely into the new routine in mmio.c.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 Makefile             |   1 -
 include/kvm/ioport.h |  27 ------
 include/kvm/kvm.h    |   2 -
 ioport.c             | 195 -------------------------------------------
 mmio.c               |   2 +-
 5 files changed, 1 insertion(+), 226 deletions(-)
 delete mode 100644 ioport.c

diff --git a/Makefile b/Makefile
index 35bb1182..94ff5da6 100644
--- a/Makefile
+++ b/Makefile
@@ -56,7 +56,6 @@ OBJS	+= framebuffer.o
 OBJS	+= guest_compat.o
 OBJS	+= hw/rtc.o
 OBJS	+= hw/serial.o
-OBJS	+= ioport.o
 OBJS	+= irq.o
 OBJS	+= kvm-cpu.o
 OBJS	+= kvm.o
diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
index a61038e2..b6f579cb 100644
--- a/include/kvm/ioport.h
+++ b/include/kvm/ioport.h
@@ -1,13 +1,8 @@
 #ifndef KVM__IOPORT_H
 #define KVM__IOPORT_H
 
-#include "kvm/devices.h"
 #include "kvm/kvm-cpu.h"
-#include "kvm/rbtree-interval.h"
-#include "kvm/fdt.h"
 
-#include <stdbool.h>
-#include <limits.h>
 #include <asm/types.h>
 #include <linux/types.h>
 #include <linux/byteorder.h>
@@ -15,30 +10,8 @@
 /* some ports we reserve for own use */
 #define IOPORT_DBG			0xe0
 
-struct kvm;
-
-struct ioport {
-	struct rb_int_node		node;
-	struct ioport_operations	*ops;
-	void				*priv;
-	struct device_header		dev_hdr;
-	u32				refcount;
-	bool				remove;
-};
-
-struct ioport_operations {
-	bool (*io_in)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size);
-	bool (*io_out)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size);
-};
-
 void ioport__map_irq(u8 *irq);
 
-int __must_check ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops,
-				  int count, void *param);
-int ioport__unregister(struct kvm *kvm, u16 port);
-int ioport__init(struct kvm *kvm);
-int ioport__exit(struct kvm *kvm);
-
 static inline u8 ioport__read8(u8 *data)
 {
 	return *data;
diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
index 306b258a..6c28afa3 100644
--- a/include/kvm/kvm.h
+++ b/include/kvm/kvm.h
@@ -126,8 +126,6 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
 void kvm__irq_trigger(struct kvm *kvm, int irq);
 bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count);
 bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write);
-bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
-		      int direction, int size, u32 count);
 int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr);
 int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr,
 		      enum kvm_mem_type type);
diff --git a/ioport.c b/ioport.c
deleted file mode 100644
index ce29e7e7..00000000
--- a/ioport.c
+++ /dev/null
@@ -1,195 +0,0 @@
-#include "kvm/ioport.h"
-
-#include "kvm/kvm.h"
-#include "kvm/util.h"
-#include "kvm/rbtree-interval.h"
-#include "kvm/mutex.h"
-
-#include <linux/kvm.h>	/* for KVM_EXIT_* */
-#include <linux/types.h>
-
-#include <stdbool.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define ioport_node(n) rb_entry(n, struct ioport, node)
-
-static DEFINE_MUTEX(ioport_lock);
-
-static struct rb_root		ioport_tree = RB_ROOT;
-
-static struct ioport *ioport_search(struct rb_root *root, u64 addr)
-{
-	struct rb_int_node *node;
-
-	node = rb_int_search_single(root, addr);
-	if (node == NULL)
-		return NULL;
-
-	return ioport_node(node);
-}
-
-static int ioport_insert(struct rb_root *root, struct ioport *data)
-{
-	return rb_int_insert(root, &data->node);
-}
-
-static void ioport_remove(struct rb_root *root, struct ioport *data)
-{
-	rb_int_erase(root, &data->node);
-}
-
-static struct ioport *ioport_get(struct rb_root *root, u64 addr)
-{
-	struct ioport *ioport;
-
-	mutex_lock(&ioport_lock);
-	ioport = ioport_search(root, addr);
-	if (ioport)
-		ioport->refcount++;
-	mutex_unlock(&ioport_lock);
-
-	return ioport;
-}
-
-/* Called with ioport_lock held. */
-static void ioport_unregister(struct rb_root *root, struct ioport *data)
-{
-	ioport_remove(root, data);
-	free(data);
-}
-
-static void ioport_put(struct rb_root *root, struct ioport *data)
-{
-	mutex_lock(&ioport_lock);
-	data->refcount--;
-	if (data->remove && data->refcount == 0)
-		ioport_unregister(root, data);
-	mutex_unlock(&ioport_lock);
-}
-
-int ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops, int count, void *param)
-{
-	struct ioport *entry;
-	int r;
-
-	entry = malloc(sizeof(*entry));
-	if (entry == NULL)
-		return -ENOMEM;
-
-	*entry = (struct ioport) {
-		.node		= RB_INT_INIT(port, port + count),
-		.ops		= ops,
-		.priv		= param,
-		/*
-		 * Start from 0 because ioport__unregister() doesn't decrement
-		 * the reference count.
-		 */
-		.refcount	= 0,
-		.remove		= false,
-	};
-
-	mutex_lock(&ioport_lock);
-	r = ioport_insert(&ioport_tree, entry);
-	if (r < 0)
-		goto out_free;
-	mutex_unlock(&ioport_lock);
-
-	return port;
-
-out_free:
-	free(entry);
-	mutex_unlock(&ioport_lock);
-	return r;
-}
-
-int ioport__unregister(struct kvm *kvm, u16 port)
-{
-	struct ioport *entry;
-
-	mutex_lock(&ioport_lock);
-	entry = ioport_search(&ioport_tree, port);
-	if (!entry) {
-		mutex_unlock(&ioport_lock);
-		return -ENOENT;
-	}
-	/* The same reasoning from kvm__deregister_mmio() applies. */
-	if (entry->refcount == 0)
-		ioport_unregister(&ioport_tree, entry);
-	else
-		entry->remove = true;
-	mutex_unlock(&ioport_lock);
-
-	return 0;
-}
-
-static void ioport__unregister_all(void)
-{
-	struct ioport *entry;
-	struct rb_node *rb;
-	struct rb_int_node *rb_node;
-
-	rb = rb_first(&ioport_tree);
-	while (rb) {
-		rb_node = rb_int(rb);
-		entry = ioport_node(rb_node);
-		ioport_unregister(&ioport_tree, entry);
-		rb = rb_first(&ioport_tree);
-	}
-}
-
-static const char *to_direction(int direction)
-{
-	if (direction == KVM_EXIT_IO_IN)
-		return "IN";
-	else
-		return "OUT";
-}
-
-static void ioport_error(u16 port, void *data, int direction, int size, u32 count)
-{
-	fprintf(stderr, "IO error: %s port=%x, size=%d, count=%u\n", to_direction(direction), port, size, count);
-}
-
-bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count)
-{
-	struct ioport_operations *ops;
-	bool ret = false;
-	struct ioport *entry;
-	void *ptr = data;
-	struct kvm *kvm = vcpu->kvm;
-
-	entry = ioport_get(&ioport_tree, port);
-	if (!entry)
-		return kvm__emulate_pio(vcpu, port, data, direction,
-					size, count);
-
-	ops	= entry->ops;
-
-	while (count--) {
-		if (direction == KVM_EXIT_IO_IN && ops->io_in)
-				ret = ops->io_in(entry, vcpu, port, ptr, size);
-		else if (direction == KVM_EXIT_IO_OUT && ops->io_out)
-				ret = ops->io_out(entry, vcpu, port, ptr, size);
-
-		ptr += size;
-	}
-
-	ioport_put(&ioport_tree, entry);
-
-	if (ret)
-		return true;
-
-	if (kvm->cfg.ioport_debug)
-		ioport_error(port, data, direction, size, count);
-
-	return !kvm->cfg.ioport_debug;
-}
-
-int ioport__exit(struct kvm *kvm)
-{
-	ioport__unregister_all();
-	return 0;
-}
-dev_base_exit(ioport__exit);
diff --git a/mmio.c b/mmio.c
index 75de04ad..9f731dcf 100644
--- a/mmio.c
+++ b/mmio.c
@@ -212,7 +212,7 @@ out:
 	return true;
 }
 
-bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
+bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data,
 		     int direction, int size, u32 count)
 {
 	struct mmio_mapping *mmio;
-- 
2.17.5


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

* [PATCH kvmtool v2 19/22] Remove ioport specific routines
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Now that all users of the dedicated ioport trap handler interface are
gone, we can retire the code associated with it.

This removes ioport.c and ioport.h, along with removing prototypes from
other header files.

This also transfers the responsibility for port I/O trap handling
entirely into the new routine in mmio.c.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 Makefile             |   1 -
 include/kvm/ioport.h |  27 ------
 include/kvm/kvm.h    |   2 -
 ioport.c             | 195 -------------------------------------------
 mmio.c               |   2 +-
 5 files changed, 1 insertion(+), 226 deletions(-)
 delete mode 100644 ioport.c

diff --git a/Makefile b/Makefile
index 35bb1182..94ff5da6 100644
--- a/Makefile
+++ b/Makefile
@@ -56,7 +56,6 @@ OBJS	+= framebuffer.o
 OBJS	+= guest_compat.o
 OBJS	+= hw/rtc.o
 OBJS	+= hw/serial.o
-OBJS	+= ioport.o
 OBJS	+= irq.o
 OBJS	+= kvm-cpu.o
 OBJS	+= kvm.o
diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
index a61038e2..b6f579cb 100644
--- a/include/kvm/ioport.h
+++ b/include/kvm/ioport.h
@@ -1,13 +1,8 @@
 #ifndef KVM__IOPORT_H
 #define KVM__IOPORT_H
 
-#include "kvm/devices.h"
 #include "kvm/kvm-cpu.h"
-#include "kvm/rbtree-interval.h"
-#include "kvm/fdt.h"
 
-#include <stdbool.h>
-#include <limits.h>
 #include <asm/types.h>
 #include <linux/types.h>
 #include <linux/byteorder.h>
@@ -15,30 +10,8 @@
 /* some ports we reserve for own use */
 #define IOPORT_DBG			0xe0
 
-struct kvm;
-
-struct ioport {
-	struct rb_int_node		node;
-	struct ioport_operations	*ops;
-	void				*priv;
-	struct device_header		dev_hdr;
-	u32				refcount;
-	bool				remove;
-};
-
-struct ioport_operations {
-	bool (*io_in)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size);
-	bool (*io_out)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size);
-};
-
 void ioport__map_irq(u8 *irq);
 
-int __must_check ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops,
-				  int count, void *param);
-int ioport__unregister(struct kvm *kvm, u16 port);
-int ioport__init(struct kvm *kvm);
-int ioport__exit(struct kvm *kvm);
-
 static inline u8 ioport__read8(u8 *data)
 {
 	return *data;
diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
index 306b258a..6c28afa3 100644
--- a/include/kvm/kvm.h
+++ b/include/kvm/kvm.h
@@ -126,8 +126,6 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
 void kvm__irq_trigger(struct kvm *kvm, int irq);
 bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count);
 bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write);
-bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
-		      int direction, int size, u32 count);
 int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr);
 int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr,
 		      enum kvm_mem_type type);
diff --git a/ioport.c b/ioport.c
deleted file mode 100644
index ce29e7e7..00000000
--- a/ioport.c
+++ /dev/null
@@ -1,195 +0,0 @@
-#include "kvm/ioport.h"
-
-#include "kvm/kvm.h"
-#include "kvm/util.h"
-#include "kvm/rbtree-interval.h"
-#include "kvm/mutex.h"
-
-#include <linux/kvm.h>	/* for KVM_EXIT_* */
-#include <linux/types.h>
-
-#include <stdbool.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define ioport_node(n) rb_entry(n, struct ioport, node)
-
-static DEFINE_MUTEX(ioport_lock);
-
-static struct rb_root		ioport_tree = RB_ROOT;
-
-static struct ioport *ioport_search(struct rb_root *root, u64 addr)
-{
-	struct rb_int_node *node;
-
-	node = rb_int_search_single(root, addr);
-	if (node == NULL)
-		return NULL;
-
-	return ioport_node(node);
-}
-
-static int ioport_insert(struct rb_root *root, struct ioport *data)
-{
-	return rb_int_insert(root, &data->node);
-}
-
-static void ioport_remove(struct rb_root *root, struct ioport *data)
-{
-	rb_int_erase(root, &data->node);
-}
-
-static struct ioport *ioport_get(struct rb_root *root, u64 addr)
-{
-	struct ioport *ioport;
-
-	mutex_lock(&ioport_lock);
-	ioport = ioport_search(root, addr);
-	if (ioport)
-		ioport->refcount++;
-	mutex_unlock(&ioport_lock);
-
-	return ioport;
-}
-
-/* Called with ioport_lock held. */
-static void ioport_unregister(struct rb_root *root, struct ioport *data)
-{
-	ioport_remove(root, data);
-	free(data);
-}
-
-static void ioport_put(struct rb_root *root, struct ioport *data)
-{
-	mutex_lock(&ioport_lock);
-	data->refcount--;
-	if (data->remove && data->refcount == 0)
-		ioport_unregister(root, data);
-	mutex_unlock(&ioport_lock);
-}
-
-int ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops, int count, void *param)
-{
-	struct ioport *entry;
-	int r;
-
-	entry = malloc(sizeof(*entry));
-	if (entry == NULL)
-		return -ENOMEM;
-
-	*entry = (struct ioport) {
-		.node		= RB_INT_INIT(port, port + count),
-		.ops		= ops,
-		.priv		= param,
-		/*
-		 * Start from 0 because ioport__unregister() doesn't decrement
-		 * the reference count.
-		 */
-		.refcount	= 0,
-		.remove		= false,
-	};
-
-	mutex_lock(&ioport_lock);
-	r = ioport_insert(&ioport_tree, entry);
-	if (r < 0)
-		goto out_free;
-	mutex_unlock(&ioport_lock);
-
-	return port;
-
-out_free:
-	free(entry);
-	mutex_unlock(&ioport_lock);
-	return r;
-}
-
-int ioport__unregister(struct kvm *kvm, u16 port)
-{
-	struct ioport *entry;
-
-	mutex_lock(&ioport_lock);
-	entry = ioport_search(&ioport_tree, port);
-	if (!entry) {
-		mutex_unlock(&ioport_lock);
-		return -ENOENT;
-	}
-	/* The same reasoning from kvm__deregister_mmio() applies. */
-	if (entry->refcount == 0)
-		ioport_unregister(&ioport_tree, entry);
-	else
-		entry->remove = true;
-	mutex_unlock(&ioport_lock);
-
-	return 0;
-}
-
-static void ioport__unregister_all(void)
-{
-	struct ioport *entry;
-	struct rb_node *rb;
-	struct rb_int_node *rb_node;
-
-	rb = rb_first(&ioport_tree);
-	while (rb) {
-		rb_node = rb_int(rb);
-		entry = ioport_node(rb_node);
-		ioport_unregister(&ioport_tree, entry);
-		rb = rb_first(&ioport_tree);
-	}
-}
-
-static const char *to_direction(int direction)
-{
-	if (direction == KVM_EXIT_IO_IN)
-		return "IN";
-	else
-		return "OUT";
-}
-
-static void ioport_error(u16 port, void *data, int direction, int size, u32 count)
-{
-	fprintf(stderr, "IO error: %s port=%x, size=%d, count=%u\n", to_direction(direction), port, size, count);
-}
-
-bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count)
-{
-	struct ioport_operations *ops;
-	bool ret = false;
-	struct ioport *entry;
-	void *ptr = data;
-	struct kvm *kvm = vcpu->kvm;
-
-	entry = ioport_get(&ioport_tree, port);
-	if (!entry)
-		return kvm__emulate_pio(vcpu, port, data, direction,
-					size, count);
-
-	ops	= entry->ops;
-
-	while (count--) {
-		if (direction == KVM_EXIT_IO_IN && ops->io_in)
-				ret = ops->io_in(entry, vcpu, port, ptr, size);
-		else if (direction == KVM_EXIT_IO_OUT && ops->io_out)
-				ret = ops->io_out(entry, vcpu, port, ptr, size);
-
-		ptr += size;
-	}
-
-	ioport_put(&ioport_tree, entry);
-
-	if (ret)
-		return true;
-
-	if (kvm->cfg.ioport_debug)
-		ioport_error(port, data, direction, size, count);
-
-	return !kvm->cfg.ioport_debug;
-}
-
-int ioport__exit(struct kvm *kvm)
-{
-	ioport__unregister_all();
-	return 0;
-}
-dev_base_exit(ioport__exit);
diff --git a/mmio.c b/mmio.c
index 75de04ad..9f731dcf 100644
--- a/mmio.c
+++ b/mmio.c
@@ -212,7 +212,7 @@ out:
 	return true;
 }
 
-bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
+bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data,
 		     int direction, int size, u32 count)
 {
 	struct mmio_mapping *mmio;
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 20/22] arm: Reorganise and document memory map
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

The hardcoded memory map we expose to a guest is currently described
using a series of partially interconnected preprocessor constants,
which is hard to read and follow.

In preparation for moving the UART and RTC to some different MMIO
region, document the current map with some ASCII art, and clean up the
definition of the sections.

No functional change.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arm/include/arm-common/kvm-arch.h | 41 ++++++++++++++++++++++---------
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
index d84e50cd..b12255b0 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -7,14 +7,33 @@
 
 #include "arm-common/gic.h"
 
+/*
+ * The memory map used for ARM guests (not to scale):
+ *
+ * 0      64K  16M     32M     48M            1GB       2GB
+ * +-------+-..-+-------+-------+--....--+-----+--.....--+---......
+ * | (PCI) |////| int.  |       |        |     |         |
+ * |  I/O  |////| MMIO: | Flash | virtio | GIC |   PCI   |  DRAM
+ * | ports |////| UART, |       |  MMIO  |     |  (AXI)  |
+ * |       |////| RTC   |       |        |     |         |
+ * +-------+-..-+-------+-------+--....--+-----+--.....--+---......
+ */
+
 #define ARM_IOPORT_AREA		_AC(0x0000000000000000, UL)
-#define ARM_FLASH_AREA		_AC(0x0000000002000000, UL)
-#define ARM_MMIO_AREA		_AC(0x0000000003000000, UL)
+#define ARM_MMIO_AREA		_AC(0x0000000001000000, UL)
 #define ARM_AXI_AREA		_AC(0x0000000040000000, UL)
 #define ARM_MEMORY_AREA		_AC(0x0000000080000000, UL)
 
-#define ARM_LOMAP_MAX_MEMORY	((1ULL << 32) - ARM_MEMORY_AREA)
-#define ARM_HIMAP_MAX_MEMORY	((1ULL << 40) - ARM_MEMORY_AREA)
+#define KVM_IOPORT_AREA		ARM_IOPORT_AREA
+#define ARM_IOPORT_SIZE		(1U << 16)
+
+
+#define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
+#define KVM_FLASH_MAX_SIZE	0x1000000
+
+#define KVM_VIRTIO_MMIO_AREA	(KVM_FLASH_MMIO_BASE + KVM_FLASH_MAX_SIZE)
+#define ARM_VIRTIO_MMIO_SIZE	(ARM_AXI_AREA - \
+				(KVM_VIRTIO_MMIO_AREA + ARM_GIC_SIZE))
 
 #define ARM_GIC_DIST_BASE	(ARM_AXI_AREA - ARM_GIC_DIST_SIZE)
 #define ARM_GIC_CPUI_BASE	(ARM_GIC_DIST_BASE - ARM_GIC_CPUI_SIZE)
@@ -22,19 +41,17 @@
 #define ARM_GIC_DIST_SIZE	0x10000
 #define ARM_GIC_CPUI_SIZE	0x20000
 
-#define KVM_FLASH_MMIO_BASE	ARM_FLASH_AREA
-#define KVM_FLASH_MAX_SIZE	(ARM_MMIO_AREA - ARM_FLASH_AREA)
 
-#define ARM_IOPORT_SIZE		(1U << 16)
-#define ARM_VIRTIO_MMIO_SIZE	(ARM_AXI_AREA - (ARM_MMIO_AREA + ARM_GIC_SIZE))
+#define KVM_PCI_CFG_AREA	ARM_AXI_AREA
 #define ARM_PCI_CFG_SIZE	(1ULL << 24)
+#define KVM_PCI_MMIO_AREA	(KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
 #define ARM_PCI_MMIO_SIZE	(ARM_MEMORY_AREA - \
 				(ARM_AXI_AREA + ARM_PCI_CFG_SIZE))
 
-#define KVM_IOPORT_AREA		ARM_IOPORT_AREA
-#define KVM_PCI_CFG_AREA	ARM_AXI_AREA
-#define KVM_PCI_MMIO_AREA	(KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
-#define KVM_VIRTIO_MMIO_AREA	ARM_MMIO_AREA
+
+#define ARM_LOMAP_MAX_MEMORY	((1ULL << 32) - ARM_MEMORY_AREA)
+#define ARM_HIMAP_MAX_MEMORY	((1ULL << 40) - ARM_MEMORY_AREA)
+
 
 #define KVM_IOEVENTFD_HAS_PIO	0
 
-- 
2.17.5


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

* [PATCH kvmtool v2 20/22] arm: Reorganise and document memory map
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

The hardcoded memory map we expose to a guest is currently described
using a series of partially interconnected preprocessor constants,
which is hard to read and follow.

In preparation for moving the UART and RTC to some different MMIO
region, document the current map with some ASCII art, and clean up the
definition of the sections.

No functional change.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arm/include/arm-common/kvm-arch.h | 41 ++++++++++++++++++++++---------
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
index d84e50cd..b12255b0 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -7,14 +7,33 @@
 
 #include "arm-common/gic.h"
 
+/*
+ * The memory map used for ARM guests (not to scale):
+ *
+ * 0      64K  16M     32M     48M            1GB       2GB
+ * +-------+-..-+-------+-------+--....--+-----+--.....--+---......
+ * | (PCI) |////| int.  |       |        |     |         |
+ * |  I/O  |////| MMIO: | Flash | virtio | GIC |   PCI   |  DRAM
+ * | ports |////| UART, |       |  MMIO  |     |  (AXI)  |
+ * |       |////| RTC   |       |        |     |         |
+ * +-------+-..-+-------+-------+--....--+-----+--.....--+---......
+ */
+
 #define ARM_IOPORT_AREA		_AC(0x0000000000000000, UL)
-#define ARM_FLASH_AREA		_AC(0x0000000002000000, UL)
-#define ARM_MMIO_AREA		_AC(0x0000000003000000, UL)
+#define ARM_MMIO_AREA		_AC(0x0000000001000000, UL)
 #define ARM_AXI_AREA		_AC(0x0000000040000000, UL)
 #define ARM_MEMORY_AREA		_AC(0x0000000080000000, UL)
 
-#define ARM_LOMAP_MAX_MEMORY	((1ULL << 32) - ARM_MEMORY_AREA)
-#define ARM_HIMAP_MAX_MEMORY	((1ULL << 40) - ARM_MEMORY_AREA)
+#define KVM_IOPORT_AREA		ARM_IOPORT_AREA
+#define ARM_IOPORT_SIZE		(1U << 16)
+
+
+#define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
+#define KVM_FLASH_MAX_SIZE	0x1000000
+
+#define KVM_VIRTIO_MMIO_AREA	(KVM_FLASH_MMIO_BASE + KVM_FLASH_MAX_SIZE)
+#define ARM_VIRTIO_MMIO_SIZE	(ARM_AXI_AREA - \
+				(KVM_VIRTIO_MMIO_AREA + ARM_GIC_SIZE))
 
 #define ARM_GIC_DIST_BASE	(ARM_AXI_AREA - ARM_GIC_DIST_SIZE)
 #define ARM_GIC_CPUI_BASE	(ARM_GIC_DIST_BASE - ARM_GIC_CPUI_SIZE)
@@ -22,19 +41,17 @@
 #define ARM_GIC_DIST_SIZE	0x10000
 #define ARM_GIC_CPUI_SIZE	0x20000
 
-#define KVM_FLASH_MMIO_BASE	ARM_FLASH_AREA
-#define KVM_FLASH_MAX_SIZE	(ARM_MMIO_AREA - ARM_FLASH_AREA)
 
-#define ARM_IOPORT_SIZE		(1U << 16)
-#define ARM_VIRTIO_MMIO_SIZE	(ARM_AXI_AREA - (ARM_MMIO_AREA + ARM_GIC_SIZE))
+#define KVM_PCI_CFG_AREA	ARM_AXI_AREA
 #define ARM_PCI_CFG_SIZE	(1ULL << 24)
+#define KVM_PCI_MMIO_AREA	(KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
 #define ARM_PCI_MMIO_SIZE	(ARM_MEMORY_AREA - \
 				(ARM_AXI_AREA + ARM_PCI_CFG_SIZE))
 
-#define KVM_IOPORT_AREA		ARM_IOPORT_AREA
-#define KVM_PCI_CFG_AREA	ARM_AXI_AREA
-#define KVM_PCI_MMIO_AREA	(KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
-#define KVM_VIRTIO_MMIO_AREA	ARM_MMIO_AREA
+
+#define ARM_LOMAP_MAX_MEMORY	((1ULL << 32) - ARM_MEMORY_AREA)
+#define ARM_HIMAP_MAX_MEMORY	((1ULL << 40) - ARM_MEMORY_AREA)
+
 
 #define KVM_IOEVENTFD_HAS_PIO	0
 
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 21/22] hw/serial: ARM/arm64: Use MMIO at higher addresses
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

Using the UART devices at their legacy I/O addresses as set by IBM in
1981 was a kludge we used for simplicity on ARM platforms as well.
However this imposes problems due to their missing alignment and overlap
with the PCI I/O address space.

Now that we can switch a device easily between using ioports and MMIO,
let's move the UARTs out of the first 4K of memory on ARM platforms.

That should be transparent for well behaved guests, since the change is
naturally reflected in the device tree. Even "earlycon" keeps working,
as the stdout-path property is adjusted automatically.

People providing direct earlycon parameters via the command line need to
adjust it to: "earlycon=uart,mmio,0x1000000".

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arm/include/arm-common/kvm-arch.h |  3 +++
 hw/serial.c                       | 45 ++++++++++++++++++++-----------
 2 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
index b12255b0..633ea8fa 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -28,6 +28,9 @@
 #define ARM_IOPORT_SIZE		(1U << 16)
 
 
+#define ARM_UART_MMIO_BASE	ARM_MMIO_AREA
+#define ARM_UART_MMIO_SIZE	0x10000
+
 #define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
 #define KVM_FLASH_MAX_SIZE	0x1000000
 
diff --git a/hw/serial.c b/hw/serial.c
index 4be188a1..1854add2 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -13,6 +13,17 @@
 
 #include <pthread.h>
 
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#define serial_iobase(nr)	(ARM_UART_MMIO_BASE + (nr) * 0x1000)
+#define serial_irq(nr)		(32 + (nr))
+#define SERIAL8250_BUS_TYPE	DEVICE_BUS_MMIO
+#else
+#define serial_iobase(nr)	((((nr) & 1) ? 0x200 : 0x300) +	\
+				 ((nr) >= 2 ? 0xe8 : 0xf8))
+#define serial_irq(nr)		(((nr) & 1) ? 3 : 4)
+#define SERIAL8250_BUS_TYPE	DEVICE_BUS_IOPORT
+#endif
+
 /*
  * This fakes a U6_16550A. The fifo len needs to be 64 as the kernel
  * expects that for autodetection.
@@ -27,7 +38,7 @@ struct serial8250_device {
 	struct mutex		mutex;
 	u8			id;
 
-	u16			iobase;
+	u32			iobase;
 	u8			irq;
 	u8			irq_state;
 	int			txcnt;
@@ -65,56 +76,56 @@ static struct serial8250_device devices[] = {
 	/* ttyS0 */
 	[0]	= {
 		.dev_hdr = {
-			.bus_type	= DEVICE_BUS_IOPORT,
+			.bus_type	= SERIAL8250_BUS_TYPE,
 			.data		= serial8250_generate_fdt_node,
 		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 0,
-		.iobase			= 0x3f8,
-		.irq			= 4,
+		.iobase			= serial_iobase(0),
+		.irq			= serial_irq(0),
 
 		SERIAL_REGS_SETTING
 	},
 	/* ttyS1 */
 	[1]	= {
 		.dev_hdr = {
-			.bus_type	= DEVICE_BUS_IOPORT,
+			.bus_type	= SERIAL8250_BUS_TYPE,
 			.data		= serial8250_generate_fdt_node,
 		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 1,
-		.iobase			= 0x2f8,
-		.irq			= 3,
+		.iobase			= serial_iobase(1),
+		.irq			= serial_irq(1),
 
 		SERIAL_REGS_SETTING
 	},
 	/* ttyS2 */
 	[2]	= {
 		.dev_hdr = {
-			.bus_type	= DEVICE_BUS_IOPORT,
+			.bus_type	= SERIAL8250_BUS_TYPE,
 			.data		= serial8250_generate_fdt_node,
 		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 2,
-		.iobase			= 0x3e8,
-		.irq			= 4,
+		.iobase			= serial_iobase(2),
+		.irq			= serial_irq(2),
 
 		SERIAL_REGS_SETTING
 	},
 	/* ttyS3 */
 	[3]	= {
 		.dev_hdr = {
-			.bus_type	= DEVICE_BUS_IOPORT,
+			.bus_type	= SERIAL8250_BUS_TYPE,
 			.data		= serial8250_generate_fdt_node,
 		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 3,
-		.iobase			= 0x2e8,
-		.irq			= 3,
+		.iobase			= serial_iobase(3),
+		.irq			= serial_irq(3),
 
 		SERIAL_REGS_SETTING
 	},
@@ -439,7 +450,8 @@ static int serial8250__device_init(struct kvm *kvm,
 		return r;
 
 	ioport__map_irq(&dev->irq);
-	r = kvm__register_pio(kvm, dev->iobase, 8, serial8250_mmio, dev);
+	r = kvm__register_iotrap(kvm, dev->iobase, 8, serial8250_mmio, dev,
+				 SERIAL8250_BUS_TYPE);
 
 	return r;
 }
@@ -462,7 +474,7 @@ cleanup:
 	for (j = 0; j <= i; j++) {
 		struct serial8250_device *dev = &devices[j];
 
-		kvm__deregister_pio(kvm, dev->iobase);
+		kvm__deregister_iotrap(kvm, dev->iobase, SERIAL8250_BUS_TYPE);
 		device__unregister(&dev->dev_hdr);
 	}
 
@@ -478,7 +490,8 @@ int serial8250__exit(struct kvm *kvm)
 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
 		struct serial8250_device *dev = &devices[i];
 
-		r = kvm__deregister_pio(kvm, dev->iobase);
+		r = kvm__deregister_iotrap(kvm, dev->iobase,
+					   SERIAL8250_BUS_TYPE);
 		if (r < 0)
 			return r;
 		device__unregister(&dev->dev_hdr);
-- 
2.17.5


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

* [PATCH kvmtool v2 21/22] hw/serial: ARM/arm64: Use MMIO at higher addresses
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Using the UART devices at their legacy I/O addresses as set by IBM in
1981 was a kludge we used for simplicity on ARM platforms as well.
However this imposes problems due to their missing alignment and overlap
with the PCI I/O address space.

Now that we can switch a device easily between using ioports and MMIO,
let's move the UARTs out of the first 4K of memory on ARM platforms.

That should be transparent for well behaved guests, since the change is
naturally reflected in the device tree. Even "earlycon" keeps working,
as the stdout-path property is adjusted automatically.

People providing direct earlycon parameters via the command line need to
adjust it to: "earlycon=uart,mmio,0x1000000".

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arm/include/arm-common/kvm-arch.h |  3 +++
 hw/serial.c                       | 45 ++++++++++++++++++++-----------
 2 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
index b12255b0..633ea8fa 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -28,6 +28,9 @@
 #define ARM_IOPORT_SIZE		(1U << 16)
 
 
+#define ARM_UART_MMIO_BASE	ARM_MMIO_AREA
+#define ARM_UART_MMIO_SIZE	0x10000
+
 #define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
 #define KVM_FLASH_MAX_SIZE	0x1000000
 
diff --git a/hw/serial.c b/hw/serial.c
index 4be188a1..1854add2 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -13,6 +13,17 @@
 
 #include <pthread.h>
 
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#define serial_iobase(nr)	(ARM_UART_MMIO_BASE + (nr) * 0x1000)
+#define serial_irq(nr)		(32 + (nr))
+#define SERIAL8250_BUS_TYPE	DEVICE_BUS_MMIO
+#else
+#define serial_iobase(nr)	((((nr) & 1) ? 0x200 : 0x300) +	\
+				 ((nr) >= 2 ? 0xe8 : 0xf8))
+#define serial_irq(nr)		(((nr) & 1) ? 3 : 4)
+#define SERIAL8250_BUS_TYPE	DEVICE_BUS_IOPORT
+#endif
+
 /*
  * This fakes a U6_16550A. The fifo len needs to be 64 as the kernel
  * expects that for autodetection.
@@ -27,7 +38,7 @@ struct serial8250_device {
 	struct mutex		mutex;
 	u8			id;
 
-	u16			iobase;
+	u32			iobase;
 	u8			irq;
 	u8			irq_state;
 	int			txcnt;
@@ -65,56 +76,56 @@ static struct serial8250_device devices[] = {
 	/* ttyS0 */
 	[0]	= {
 		.dev_hdr = {
-			.bus_type	= DEVICE_BUS_IOPORT,
+			.bus_type	= SERIAL8250_BUS_TYPE,
 			.data		= serial8250_generate_fdt_node,
 		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 0,
-		.iobase			= 0x3f8,
-		.irq			= 4,
+		.iobase			= serial_iobase(0),
+		.irq			= serial_irq(0),
 
 		SERIAL_REGS_SETTING
 	},
 	/* ttyS1 */
 	[1]	= {
 		.dev_hdr = {
-			.bus_type	= DEVICE_BUS_IOPORT,
+			.bus_type	= SERIAL8250_BUS_TYPE,
 			.data		= serial8250_generate_fdt_node,
 		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 1,
-		.iobase			= 0x2f8,
-		.irq			= 3,
+		.iobase			= serial_iobase(1),
+		.irq			= serial_irq(1),
 
 		SERIAL_REGS_SETTING
 	},
 	/* ttyS2 */
 	[2]	= {
 		.dev_hdr = {
-			.bus_type	= DEVICE_BUS_IOPORT,
+			.bus_type	= SERIAL8250_BUS_TYPE,
 			.data		= serial8250_generate_fdt_node,
 		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 2,
-		.iobase			= 0x3e8,
-		.irq			= 4,
+		.iobase			= serial_iobase(2),
+		.irq			= serial_irq(2),
 
 		SERIAL_REGS_SETTING
 	},
 	/* ttyS3 */
 	[3]	= {
 		.dev_hdr = {
-			.bus_type	= DEVICE_BUS_IOPORT,
+			.bus_type	= SERIAL8250_BUS_TYPE,
 			.data		= serial8250_generate_fdt_node,
 		},
 		.mutex			= MUTEX_INITIALIZER,
 
 		.id			= 3,
-		.iobase			= 0x2e8,
-		.irq			= 3,
+		.iobase			= serial_iobase(3),
+		.irq			= serial_irq(3),
 
 		SERIAL_REGS_SETTING
 	},
@@ -439,7 +450,8 @@ static int serial8250__device_init(struct kvm *kvm,
 		return r;
 
 	ioport__map_irq(&dev->irq);
-	r = kvm__register_pio(kvm, dev->iobase, 8, serial8250_mmio, dev);
+	r = kvm__register_iotrap(kvm, dev->iobase, 8, serial8250_mmio, dev,
+				 SERIAL8250_BUS_TYPE);
 
 	return r;
 }
@@ -462,7 +474,7 @@ cleanup:
 	for (j = 0; j <= i; j++) {
 		struct serial8250_device *dev = &devices[j];
 
-		kvm__deregister_pio(kvm, dev->iobase);
+		kvm__deregister_iotrap(kvm, dev->iobase, SERIAL8250_BUS_TYPE);
 		device__unregister(&dev->dev_hdr);
 	}
 
@@ -478,7 +490,8 @@ int serial8250__exit(struct kvm *kvm)
 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
 		struct serial8250_device *dev = &devices[i];
 
-		r = kvm__deregister_pio(kvm, dev->iobase);
+		r = kvm__deregister_iotrap(kvm, dev->iobase,
+					   SERIAL8250_BUS_TYPE);
 		if (r < 0)
 			return r;
 		device__unregister(&dev->dev_hdr);
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH kvmtool v2 22/22] hw/rtc: ARM/arm64: Use MMIO at higher addresses
  2021-02-25  0:58 ` Andre Przywara
@ 2021-02-25  0:59   ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry
  Cc: Alexandru Elisei, kvm, kvmarm, Marc Zyngier, Sami Mujawar

Using the RTC device at its legacy I/O address as set by IBM in 1981
was a kludge we used for simplicity on ARM platforms as well.
However this imposes problems due to their missing alignment and overlap
with the PCI I/O address space.

Now that we can switch a device easily between using ioports and
MMIO, let's move the RTC out of the first 4K of memory on ARM platforms.

That should be transparent for well behaved guests, since the change is
naturally reflected in the device tree.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arm/include/arm-common/kvm-arch.h |  3 +++
 hw/rtc.c                          | 24 ++++++++++++++++--------
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
index 633ea8fa..02100c48 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -31,6 +31,9 @@
 #define ARM_UART_MMIO_BASE	ARM_MMIO_AREA
 #define ARM_UART_MMIO_SIZE	0x10000
 
+#define ARM_RTC_MMIO_BASE	(ARM_UART_MMIO_BASE + ARM_UART_MMIO_SIZE)
+#define ARM_RTC_MMIO_SIZE	0x10000
+
 #define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
 #define KVM_FLASH_MAX_SIZE	0x1000000
 
diff --git a/hw/rtc.c b/hw/rtc.c
index ee4c9102..aec31c52 100644
--- a/hw/rtc.c
+++ b/hw/rtc.c
@@ -5,6 +5,15 @@
 
 #include <time.h>
 
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#define RTC_BUS_TYPE		DEVICE_BUS_MMIO
+#define RTC_BASE_ADDRESS	ARM_RTC_MMIO_BASE
+#else
+/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
+#define RTC_BUS_TYPE		DEVICE_BUS_IOPORT
+#define RTC_BASE_ADDRESS	0x70
+#endif
+
 /*
  * MC146818 RTC registers
  */
@@ -49,7 +58,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
 	time_t ti;
 
 	if (is_write) {
-		if (addr == 0x70) {	/* index register */
+		if (addr == RTC_BASE_ADDRESS) {	/* index register */
 			u8 value = ioport__read8(data);
 
 			vcpu->kvm->nmi_disabled	= value & (1UL << 7);
@@ -70,7 +79,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
 		return;
 	}
 
-	if (addr == 0x70)
+	if (addr == RTC_BASE_ADDRESS)	/* index register is write-only */
 		return;
 
 	time(&ti);
@@ -127,7 +136,7 @@ static void generate_rtc_fdt_node(void *fdt,
 							    u8 irq,
 							    enum irq_type))
 {
-	u64 reg_prop[2] = { cpu_to_fdt64(0x70), cpu_to_fdt64(2) };
+	u64 reg_prop[2] = { cpu_to_fdt64(RTC_BASE_ADDRESS), cpu_to_fdt64(2) };
 
 	_FDT(fdt_begin_node(fdt, "rtc"));
 	_FDT(fdt_property_string(fdt, "compatible", "motorola,mc146818"));
@@ -139,7 +148,7 @@ static void generate_rtc_fdt_node(void *fdt,
 #endif
 
 struct device_header rtc_dev_hdr = {
-	.bus_type = DEVICE_BUS_IOPORT,
+	.bus_type = RTC_BUS_TYPE,
 	.data = generate_rtc_fdt_node,
 };
 
@@ -151,8 +160,8 @@ int rtc__init(struct kvm *kvm)
 	if (r < 0)
 		return r;
 
-	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-	r = kvm__register_pio(kvm, 0x0070, 2, cmos_ram_io, NULL);
+	r = kvm__register_iotrap(kvm, RTC_BASE_ADDRESS, 2, cmos_ram_io, NULL,
+				 RTC_BUS_TYPE);
 	if (r < 0)
 		goto out_device;
 
@@ -170,8 +179,7 @@ dev_init(rtc__init);
 
 int rtc__exit(struct kvm *kvm)
 {
-	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-	kvm__deregister_pio(kvm, 0x0070);
+	kvm__deregister_iotrap(kvm, RTC_BASE_ADDRESS, RTC_BUS_TYPE);
 
 	return 0;
 }
-- 
2.17.5


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

* [PATCH kvmtool v2 22/22] hw/rtc: ARM/arm64: Use MMIO at higher addresses
@ 2021-02-25  0:59   ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-02-25  0:59 UTC (permalink / raw)
  To: Will Deacon, Julien Thierry; +Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Using the RTC device at its legacy I/O address as set by IBM in 1981
was a kludge we used for simplicity on ARM platforms as well.
However this imposes problems due to their missing alignment and overlap
with the PCI I/O address space.

Now that we can switch a device easily between using ioports and
MMIO, let's move the RTC out of the first 4K of memory on ARM platforms.

That should be transparent for well behaved guests, since the change is
naturally reflected in the device tree.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arm/include/arm-common/kvm-arch.h |  3 +++
 hw/rtc.c                          | 24 ++++++++++++++++--------
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
index 633ea8fa..02100c48 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -31,6 +31,9 @@
 #define ARM_UART_MMIO_BASE	ARM_MMIO_AREA
 #define ARM_UART_MMIO_SIZE	0x10000
 
+#define ARM_RTC_MMIO_BASE	(ARM_UART_MMIO_BASE + ARM_UART_MMIO_SIZE)
+#define ARM_RTC_MMIO_SIZE	0x10000
+
 #define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
 #define KVM_FLASH_MAX_SIZE	0x1000000
 
diff --git a/hw/rtc.c b/hw/rtc.c
index ee4c9102..aec31c52 100644
--- a/hw/rtc.c
+++ b/hw/rtc.c
@@ -5,6 +5,15 @@
 
 #include <time.h>
 
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#define RTC_BUS_TYPE		DEVICE_BUS_MMIO
+#define RTC_BASE_ADDRESS	ARM_RTC_MMIO_BASE
+#else
+/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
+#define RTC_BUS_TYPE		DEVICE_BUS_IOPORT
+#define RTC_BASE_ADDRESS	0x70
+#endif
+
 /*
  * MC146818 RTC registers
  */
@@ -49,7 +58,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
 	time_t ti;
 
 	if (is_write) {
-		if (addr == 0x70) {	/* index register */
+		if (addr == RTC_BASE_ADDRESS) {	/* index register */
 			u8 value = ioport__read8(data);
 
 			vcpu->kvm->nmi_disabled	= value & (1UL << 7);
@@ -70,7 +79,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
 		return;
 	}
 
-	if (addr == 0x70)
+	if (addr == RTC_BASE_ADDRESS)	/* index register is write-only */
 		return;
 
 	time(&ti);
@@ -127,7 +136,7 @@ static void generate_rtc_fdt_node(void *fdt,
 							    u8 irq,
 							    enum irq_type))
 {
-	u64 reg_prop[2] = { cpu_to_fdt64(0x70), cpu_to_fdt64(2) };
+	u64 reg_prop[2] = { cpu_to_fdt64(RTC_BASE_ADDRESS), cpu_to_fdt64(2) };
 
 	_FDT(fdt_begin_node(fdt, "rtc"));
 	_FDT(fdt_property_string(fdt, "compatible", "motorola,mc146818"));
@@ -139,7 +148,7 @@ static void generate_rtc_fdt_node(void *fdt,
 #endif
 
 struct device_header rtc_dev_hdr = {
-	.bus_type = DEVICE_BUS_IOPORT,
+	.bus_type = RTC_BUS_TYPE,
 	.data = generate_rtc_fdt_node,
 };
 
@@ -151,8 +160,8 @@ int rtc__init(struct kvm *kvm)
 	if (r < 0)
 		return r;
 
-	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-	r = kvm__register_pio(kvm, 0x0070, 2, cmos_ram_io, NULL);
+	r = kvm__register_iotrap(kvm, RTC_BASE_ADDRESS, 2, cmos_ram_io, NULL,
+				 RTC_BUS_TYPE);
 	if (r < 0)
 		goto out_device;
 
@@ -170,8 +179,7 @@ dev_init(rtc__init);
 
 int rtc__exit(struct kvm *kvm)
 {
-	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-	kvm__deregister_pio(kvm, 0x0070);
+	kvm__deregister_iotrap(kvm, RTC_BASE_ADDRESS, RTC_BUS_TYPE);
 
 	return 0;
 }
-- 
2.17.5

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 00/22] Unify I/O port and MMIO trap handling
  2021-02-25  0:58 ` Andre Przywara
@ 2021-03-02 17:57   ` Alexandru Elisei
  -1 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-02 17:57 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: kvm, kvmarm, Marc Zyngier, Sami Mujawar

Hi Andre,

I've started to review this iteration and I've come across this error when trying
to apply the patches:

$ git am --reject
patches/unify-ioport-and-mmio/v2/Unify-I-O-port-and-MMIO-trap-handling.patch
Applying: ioport: Remove ioport__setup_arch()
Checking patch arm/ioport.c...
Checking patch include/kvm/ioport.h...
Checking patch ioport.c...
Checking patch mips/kvm.c...
Checking patch powerpc/ioport.c...
Checking patch x86/ioport.c...
Applied patch arm/ioport.c cleanly.
Applied patch include/kvm/ioport.h cleanly.
Applied patch ioport.c cleanly.
Applied patch mips/kvm.c cleanly.
Applied patch powerpc/ioport.c cleanly.
Applied patch x86/ioport.c cleanly.
Applying: hw/serial: Use device abstraction for FDT generator function
Checking patch hw/serial.c...
Checking patch include/kvm/kvm.h...
Applied patch hw/serial.c cleanly.
Applied patch include/kvm/kvm.h cleanly.
Applying: ioport: Retire .generate_fdt_node functionality
Checking patch include/kvm/ioport.h...
Checking patch ioport.c...
Applied patch include/kvm/ioport.h cleanly.
Applied patch ioport.c cleanly.
Applying: mmio: Extend handling to include ioport emulation
Checking patch include/kvm/kvm.h...
Checking patch ioport.c...
Checking patch mmio.c...
Applied patch include/kvm/kvm.h cleanly.
Applied patch ioport.c cleanly.
Applied patch mmio.c cleanly.
Applying: hw/i8042: Clean up data types
Checking patch hw/i8042.c...
Applied patch hw/i8042.c cleanly.
Applying: hw/i8042: Refactor trap handler
Checking patch hw/i8042.c...
Applied patch hw/i8042.c cleanly.
Applying: hw/i8042: Switch to new trap handlers
Checking patch hw/i8042.c...
error: while searching for:
        ioport__write8(data, value);
}

/*
 * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
 */
static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void
*data, int size)
{
    kbd_io(vcpu, port, data, size, false, NULL);

    return true;
}

static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void
*data, int size)
{
    kbd_io(vcpu, port, data, size, true, NULL);

    return true;
}

static struct ioport_operations kbd_ops = {
    .io_in        = kbd_in,
    .io_out        = kbd_out,
};

int kbd__init(struct kvm *kvm)
{
    int r;

    kbd_reset();
    state.kvm = kvm;
    r = ioport__register(kvm, I8042_DATA_REG, &kbd_ops, 2, NULL);
    if (r < 0)
        return r;
    r = ioport__register(kvm, I8042_COMMAND_REG, &kbd_ops, 2, NULL);
    if (r < 0) {
        ioport__unregister(kvm, I8042_DATA_REG);
        return r;
    }


error: patch failed: hw/i8042.c:325
Checking patch include/kvm/i8042.h...
Applying patch hw/i8042.c with 1 reject...
Rejected hunk #1.
Applied patch include/kvm/i8042.h cleanly.
Patch failed at 0007 hw/i8042: Switch to new trap handlers
hint: Use 'git am --show-current-patch=diff' to see the failed patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

where the patch file is from patchwork.kernel.org [1], created when clicking on
the "series" button on the top right. I'm not sure what is causing the error,
everything looks the same to me.

Regardless, I've applied the reject manually and everything looks ok.

[1]
https://patchwork.kernel.org/project/kvm/patch/20210225005915.26423-2-andre.przywara@arm.com/

Thanks,

Alex

On 2/25/21 12:58 AM, Andre Przywara wrote:
> Compared to v1 this has a few fixes, as suggested by Alex.
> There is a new patch 20/22, which cleans up the ARM memory map
> definition and adds some chart to make it more obvious what is going on.
> For a changelog, see below.
>
> ==============
>
> At the moment we use two separate code paths to handle exits for
> KVM_EXIT_IO (ioport.c) and KVM_EXIT_MMIO (mmio.c), even though they
> are semantically very similar. Because the trap handler callback routine
> is different, devices need to decide on one conduit or need to provide
> different handler functions for both of them.
>
> This is not only unnecessary code duplication, but makes switching
> devices from I/O port to MMIO a tedious task, even though there is no
> real difference between the two, especially on ARM and PowerPC.
>
> For ARM we aim at providing a flexible memory layout, and also have
> trouble with the UART and RTC device overlapping with the PCI I/O area,
> so it seems indicated to tackle this once and for all.
>
> The first three patches do some cleanup, to simplify things later.
>
> Patch 04/22 lays the groundwork, by extending mmio.c to be able to also
> register I/O port trap handlers, using the same callback prototype as
> we use for MMIO.
>
> The next 14 patches then convert devices that use the I/O port
> interface over to the new joint interface. This requires to rework
> the trap handler routine to adhere to the same prototype as the existing
> MMIO handlers. For most devices this is done in two steps: a first to
> introduce the reworked handler routine, and a second to switch to the new
> joint registration routine. For some devices the first step is trivial,
> so it's done in one patch.
>
> Patch 19/22 then retires the old I/O port interface, by removing ioport.c
> and friends.
> Patch 20/22 uses the opportunity to clean up the memory map description,
> also declares a new region (from 16MB on), where the final two patches
> switch the UART and the RTC device to. They are now registered
> on the MMIO "bus", when running on ARM or arm64. This moves them away
> from the first 64KB, so they are not in the PCI I/O area anymore.
>
> Please have a look and comment!
>
> Cheers,
> Andre
>
> Changelog v1 .. v2:
> - rework memory map definition
> - add explicit debug output for debug I/O port
> - add explicit check for MMIO coalescing on I/O ports
> - drop usage of ioport__{read,write}8() from serial
> - drop explicit I/O port cleanup routine (to mimic MMIO operation)
> - add comment for IOTRAP_BUS_MASK
> - minor cleanups / formatting changes
>
> Andre Przywara (22):
>   ioport: Remove ioport__setup_arch()
>   hw/serial: Use device abstraction for FDT generator function
>   ioport: Retire .generate_fdt_node functionality
>   mmio: Extend handling to include ioport emulation
>   hw/i8042: Clean up data types
>   hw/i8042: Refactor trap handler
>   hw/i8042: Switch to new trap handlers
>   x86/ioport: Refactor trap handlers
>   x86/ioport: Switch to new trap handlers
>   hw/rtc: Refactor trap handlers
>   hw/rtc: Switch to new trap handler
>   hw/vesa: Switch trap handling to use MMIO handler
>   hw/serial: Refactor trap handler
>   hw/serial: Switch to new trap handlers
>   vfio: Refactor ioport trap handler
>   vfio: Switch to new ioport trap handlers
>   virtio: Switch trap handling to use MMIO handler
>   pci: Switch trap handling to use MMIO handler
>   Remove ioport specific routines
>   arm: Reorganise and document memory map
>   hw/serial: ARM/arm64: Use MMIO at higher addresses
>   hw/rtc: ARM/arm64: Use MMIO at higher addresses
>
>  Makefile                          |   1 -
>  arm/include/arm-common/kvm-arch.h |  47 ++++--
>  arm/ioport.c                      |   5 -
>  hw/i8042.c                        |  94 +++++-------
>  hw/rtc.c                          |  91 ++++++------
>  hw/serial.c                       | 160 ++++++++++++--------
>  hw/vesa.c                         |  19 +--
>  include/kvm/i8042.h               |   1 -
>  include/kvm/ioport.h              |  32 ----
>  include/kvm/kvm.h                 |  49 ++++++-
>  ioport.c                          | 235 ------------------------------
>  mips/kvm.c                        |   5 -
>  mmio.c                            |  65 +++++++--
>  pci.c                             |  82 +++--------
>  powerpc/ioport.c                  |   6 -
>  vfio/core.c                       |  50 ++++---
>  virtio/pci.c                      |  46 ++----
>  x86/ioport.c                      | 107 +++++++-------
>  18 files changed, 433 insertions(+), 662 deletions(-)
>  delete mode 100644 ioport.c
>

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

* Re: [PATCH kvmtool v2 00/22] Unify I/O port and MMIO trap handling
@ 2021-03-02 17:57   ` Alexandru Elisei
  0 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-02 17:57 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Hi Andre,

I've started to review this iteration and I've come across this error when trying
to apply the patches:

$ git am --reject
patches/unify-ioport-and-mmio/v2/Unify-I-O-port-and-MMIO-trap-handling.patch
Applying: ioport: Remove ioport__setup_arch()
Checking patch arm/ioport.c...
Checking patch include/kvm/ioport.h...
Checking patch ioport.c...
Checking patch mips/kvm.c...
Checking patch powerpc/ioport.c...
Checking patch x86/ioport.c...
Applied patch arm/ioport.c cleanly.
Applied patch include/kvm/ioport.h cleanly.
Applied patch ioport.c cleanly.
Applied patch mips/kvm.c cleanly.
Applied patch powerpc/ioport.c cleanly.
Applied patch x86/ioport.c cleanly.
Applying: hw/serial: Use device abstraction for FDT generator function
Checking patch hw/serial.c...
Checking patch include/kvm/kvm.h...
Applied patch hw/serial.c cleanly.
Applied patch include/kvm/kvm.h cleanly.
Applying: ioport: Retire .generate_fdt_node functionality
Checking patch include/kvm/ioport.h...
Checking patch ioport.c...
Applied patch include/kvm/ioport.h cleanly.
Applied patch ioport.c cleanly.
Applying: mmio: Extend handling to include ioport emulation
Checking patch include/kvm/kvm.h...
Checking patch ioport.c...
Checking patch mmio.c...
Applied patch include/kvm/kvm.h cleanly.
Applied patch ioport.c cleanly.
Applied patch mmio.c cleanly.
Applying: hw/i8042: Clean up data types
Checking patch hw/i8042.c...
Applied patch hw/i8042.c cleanly.
Applying: hw/i8042: Refactor trap handler
Checking patch hw/i8042.c...
Applied patch hw/i8042.c cleanly.
Applying: hw/i8042: Switch to new trap handlers
Checking patch hw/i8042.c...
error: while searching for:
        ioport__write8(data, value);
}

/*
 * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
 */
static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void
*data, int size)
{
    kbd_io(vcpu, port, data, size, false, NULL);

    return true;
}

static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void
*data, int size)
{
    kbd_io(vcpu, port, data, size, true, NULL);

    return true;
}

static struct ioport_operations kbd_ops = {
    .io_in        = kbd_in,
    .io_out        = kbd_out,
};

int kbd__init(struct kvm *kvm)
{
    int r;

    kbd_reset();
    state.kvm = kvm;
    r = ioport__register(kvm, I8042_DATA_REG, &kbd_ops, 2, NULL);
    if (r < 0)
        return r;
    r = ioport__register(kvm, I8042_COMMAND_REG, &kbd_ops, 2, NULL);
    if (r < 0) {
        ioport__unregister(kvm, I8042_DATA_REG);
        return r;
    }


error: patch failed: hw/i8042.c:325
Checking patch include/kvm/i8042.h...
Applying patch hw/i8042.c with 1 reject...
Rejected hunk #1.
Applied patch include/kvm/i8042.h cleanly.
Patch failed at 0007 hw/i8042: Switch to new trap handlers
hint: Use 'git am --show-current-patch=diff' to see the failed patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

where the patch file is from patchwork.kernel.org [1], created when clicking on
the "series" button on the top right. I'm not sure what is causing the error,
everything looks the same to me.

Regardless, I've applied the reject manually and everything looks ok.

[1]
https://patchwork.kernel.org/project/kvm/patch/20210225005915.26423-2-andre.przywara@arm.com/

Thanks,

Alex

On 2/25/21 12:58 AM, Andre Przywara wrote:
> Compared to v1 this has a few fixes, as suggested by Alex.
> There is a new patch 20/22, which cleans up the ARM memory map
> definition and adds some chart to make it more obvious what is going on.
> For a changelog, see below.
>
> ==============
>
> At the moment we use two separate code paths to handle exits for
> KVM_EXIT_IO (ioport.c) and KVM_EXIT_MMIO (mmio.c), even though they
> are semantically very similar. Because the trap handler callback routine
> is different, devices need to decide on one conduit or need to provide
> different handler functions for both of them.
>
> This is not only unnecessary code duplication, but makes switching
> devices from I/O port to MMIO a tedious task, even though there is no
> real difference between the two, especially on ARM and PowerPC.
>
> For ARM we aim at providing a flexible memory layout, and also have
> trouble with the UART and RTC device overlapping with the PCI I/O area,
> so it seems indicated to tackle this once and for all.
>
> The first three patches do some cleanup, to simplify things later.
>
> Patch 04/22 lays the groundwork, by extending mmio.c to be able to also
> register I/O port trap handlers, using the same callback prototype as
> we use for MMIO.
>
> The next 14 patches then convert devices that use the I/O port
> interface over to the new joint interface. This requires to rework
> the trap handler routine to adhere to the same prototype as the existing
> MMIO handlers. For most devices this is done in two steps: a first to
> introduce the reworked handler routine, and a second to switch to the new
> joint registration routine. For some devices the first step is trivial,
> so it's done in one patch.
>
> Patch 19/22 then retires the old I/O port interface, by removing ioport.c
> and friends.
> Patch 20/22 uses the opportunity to clean up the memory map description,
> also declares a new region (from 16MB on), where the final two patches
> switch the UART and the RTC device to. They are now registered
> on the MMIO "bus", when running on ARM or arm64. This moves them away
> from the first 64KB, so they are not in the PCI I/O area anymore.
>
> Please have a look and comment!
>
> Cheers,
> Andre
>
> Changelog v1 .. v2:
> - rework memory map definition
> - add explicit debug output for debug I/O port
> - add explicit check for MMIO coalescing on I/O ports
> - drop usage of ioport__{read,write}8() from serial
> - drop explicit I/O port cleanup routine (to mimic MMIO operation)
> - add comment for IOTRAP_BUS_MASK
> - minor cleanups / formatting changes
>
> Andre Przywara (22):
>   ioport: Remove ioport__setup_arch()
>   hw/serial: Use device abstraction for FDT generator function
>   ioport: Retire .generate_fdt_node functionality
>   mmio: Extend handling to include ioport emulation
>   hw/i8042: Clean up data types
>   hw/i8042: Refactor trap handler
>   hw/i8042: Switch to new trap handlers
>   x86/ioport: Refactor trap handlers
>   x86/ioport: Switch to new trap handlers
>   hw/rtc: Refactor trap handlers
>   hw/rtc: Switch to new trap handler
>   hw/vesa: Switch trap handling to use MMIO handler
>   hw/serial: Refactor trap handler
>   hw/serial: Switch to new trap handlers
>   vfio: Refactor ioport trap handler
>   vfio: Switch to new ioport trap handlers
>   virtio: Switch trap handling to use MMIO handler
>   pci: Switch trap handling to use MMIO handler
>   Remove ioport specific routines
>   arm: Reorganise and document memory map
>   hw/serial: ARM/arm64: Use MMIO at higher addresses
>   hw/rtc: ARM/arm64: Use MMIO at higher addresses
>
>  Makefile                          |   1 -
>  arm/include/arm-common/kvm-arch.h |  47 ++++--
>  arm/ioport.c                      |   5 -
>  hw/i8042.c                        |  94 +++++-------
>  hw/rtc.c                          |  91 ++++++------
>  hw/serial.c                       | 160 ++++++++++++--------
>  hw/vesa.c                         |  19 +--
>  include/kvm/i8042.h               |   1 -
>  include/kvm/ioport.h              |  32 ----
>  include/kvm/kvm.h                 |  49 ++++++-
>  ioport.c                          | 235 ------------------------------
>  mips/kvm.c                        |   5 -
>  mmio.c                            |  65 +++++++--
>  pci.c                             |  82 +++--------
>  powerpc/ioport.c                  |   6 -
>  vfio/core.c                       |  50 ++++---
>  virtio/pci.c                      |  46 ++----
>  x86/ioport.c                      | 107 +++++++-------
>  18 files changed, 433 insertions(+), 662 deletions(-)
>  delete mode 100644 ioport.c
>
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 01/22] ioport: Remove ioport__setup_arch()
  2021-02-25  0:58   ` Andre Przywara
@ 2021-03-02 18:02     ` Alexandru Elisei
  -1 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-02 18:02 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: kvm, kvmarm, Marc Zyngier, Sami Mujawar

Hi Andre,

On 2/25/21 12:58 AM, Andre Przywara wrote:
> Since x86 had a special need for registering tons of special I/O ports,
> we had an ioport__setup_arch() callback, to allow each architecture
> to do the same. As it turns out no one uses it beside x86, so we remove
> that unnecessary abstraction.
>
> The generic function was registered via a device_base_init() call, so
> we just do the same for the x86 specific function only, and can remove
> the unneeded ioport__setup_arch().

Looks good, I did a compile test for arm64 and x86, and I grepped the kvmtool
directory for ioport__setup_arch. x86 is the only user left:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arm/ioport.c         | 5 -----
>  include/kvm/ioport.h | 1 -
>  ioport.c             | 6 ------
>  mips/kvm.c           | 5 -----
>  powerpc/ioport.c     | 6 ------
>  x86/ioport.c         | 3 ++-
>  6 files changed, 2 insertions(+), 24 deletions(-)
>
> diff --git a/arm/ioport.c b/arm/ioport.c
> index 2f0feb9a..24092c9d 100644
> --- a/arm/ioport.c
> +++ b/arm/ioport.c
> @@ -1,11 +1,6 @@
>  #include "kvm/ioport.h"
>  #include "kvm/irq.h"
>  
> -int ioport__setup_arch(struct kvm *kvm)
> -{
> -	return 0;
> -}
> -
>  void ioport__map_irq(u8 *irq)
>  {
>  	*irq = irq__alloc_line();
> diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
> index 039633f7..d0213541 100644
> --- a/include/kvm/ioport.h
> +++ b/include/kvm/ioport.h
> @@ -35,7 +35,6 @@ struct ioport_operations {
>  							    enum irq_type));
>  };
>  
> -int ioport__setup_arch(struct kvm *kvm);
>  void ioport__map_irq(u8 *irq);
>  
>  int __must_check ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops,
> diff --git a/ioport.c b/ioport.c
> index 844a832d..a6972179 100644
> --- a/ioport.c
> +++ b/ioport.c
> @@ -221,12 +221,6 @@ out:
>  	return !kvm->cfg.ioport_debug;
>  }
>  
> -int ioport__init(struct kvm *kvm)
> -{
> -	return ioport__setup_arch(kvm);
> -}
> -dev_base_init(ioport__init);
> -
>  int ioport__exit(struct kvm *kvm)
>  {
>  	ioport__unregister_all();
> diff --git a/mips/kvm.c b/mips/kvm.c
> index 26355930..e110e5d5 100644
> --- a/mips/kvm.c
> +++ b/mips/kvm.c
> @@ -100,11 +100,6 @@ void kvm__irq_trigger(struct kvm *kvm, int irq)
>  		die_perror("KVM_IRQ_LINE ioctl");
>  }
>  
> -int ioport__setup_arch(struct kvm *kvm)
> -{
> -	return 0;
> -}
> -
>  bool kvm__arch_cpu_supports_vm(void)
>  {
>  	return true;
> diff --git a/powerpc/ioport.c b/powerpc/ioport.c
> index 0c188b61..a5cff4ee 100644
> --- a/powerpc/ioport.c
> +++ b/powerpc/ioport.c
> @@ -12,12 +12,6 @@
>  
>  #include <stdlib.h>
>  
> -int ioport__setup_arch(struct kvm *kvm)
> -{
> -	/* PPC has no legacy ioports to set up */
> -	return 0;
> -}
> -
>  void ioport__map_irq(u8 *irq)
>  {
>  }
> diff --git a/x86/ioport.c b/x86/ioport.c
> index 7ad7b8f3..a8d2bb1a 100644
> --- a/x86/ioport.c
> +++ b/x86/ioport.c
> @@ -69,7 +69,7 @@ void ioport__map_irq(u8 *irq)
>  {
>  }
>  
> -int ioport__setup_arch(struct kvm *kvm)
> +static int ioport__setup_arch(struct kvm *kvm)
>  {
>  	int r;
>  
> @@ -150,3 +150,4 @@ int ioport__setup_arch(struct kvm *kvm)
>  
>  	return 0;
>  }
> +dev_base_init(ioport__setup_arch);

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

* Re: [PATCH kvmtool v2 01/22] ioport: Remove ioport__setup_arch()
@ 2021-03-02 18:02     ` Alexandru Elisei
  0 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-02 18:02 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Hi Andre,

On 2/25/21 12:58 AM, Andre Przywara wrote:
> Since x86 had a special need for registering tons of special I/O ports,
> we had an ioport__setup_arch() callback, to allow each architecture
> to do the same. As it turns out no one uses it beside x86, so we remove
> that unnecessary abstraction.
>
> The generic function was registered via a device_base_init() call, so
> we just do the same for the x86 specific function only, and can remove
> the unneeded ioport__setup_arch().

Looks good, I did a compile test for arm64 and x86, and I grepped the kvmtool
directory for ioport__setup_arch. x86 is the only user left:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arm/ioport.c         | 5 -----
>  include/kvm/ioport.h | 1 -
>  ioport.c             | 6 ------
>  mips/kvm.c           | 5 -----
>  powerpc/ioport.c     | 6 ------
>  x86/ioport.c         | 3 ++-
>  6 files changed, 2 insertions(+), 24 deletions(-)
>
> diff --git a/arm/ioport.c b/arm/ioport.c
> index 2f0feb9a..24092c9d 100644
> --- a/arm/ioport.c
> +++ b/arm/ioport.c
> @@ -1,11 +1,6 @@
>  #include "kvm/ioport.h"
>  #include "kvm/irq.h"
>  
> -int ioport__setup_arch(struct kvm *kvm)
> -{
> -	return 0;
> -}
> -
>  void ioport__map_irq(u8 *irq)
>  {
>  	*irq = irq__alloc_line();
> diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
> index 039633f7..d0213541 100644
> --- a/include/kvm/ioport.h
> +++ b/include/kvm/ioport.h
> @@ -35,7 +35,6 @@ struct ioport_operations {
>  							    enum irq_type));
>  };
>  
> -int ioport__setup_arch(struct kvm *kvm);
>  void ioport__map_irq(u8 *irq);
>  
>  int __must_check ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops,
> diff --git a/ioport.c b/ioport.c
> index 844a832d..a6972179 100644
> --- a/ioport.c
> +++ b/ioport.c
> @@ -221,12 +221,6 @@ out:
>  	return !kvm->cfg.ioport_debug;
>  }
>  
> -int ioport__init(struct kvm *kvm)
> -{
> -	return ioport__setup_arch(kvm);
> -}
> -dev_base_init(ioport__init);
> -
>  int ioport__exit(struct kvm *kvm)
>  {
>  	ioport__unregister_all();
> diff --git a/mips/kvm.c b/mips/kvm.c
> index 26355930..e110e5d5 100644
> --- a/mips/kvm.c
> +++ b/mips/kvm.c
> @@ -100,11 +100,6 @@ void kvm__irq_trigger(struct kvm *kvm, int irq)
>  		die_perror("KVM_IRQ_LINE ioctl");
>  }
>  
> -int ioport__setup_arch(struct kvm *kvm)
> -{
> -	return 0;
> -}
> -
>  bool kvm__arch_cpu_supports_vm(void)
>  {
>  	return true;
> diff --git a/powerpc/ioport.c b/powerpc/ioport.c
> index 0c188b61..a5cff4ee 100644
> --- a/powerpc/ioport.c
> +++ b/powerpc/ioport.c
> @@ -12,12 +12,6 @@
>  
>  #include <stdlib.h>
>  
> -int ioport__setup_arch(struct kvm *kvm)
> -{
> -	/* PPC has no legacy ioports to set up */
> -	return 0;
> -}
> -
>  void ioport__map_irq(u8 *irq)
>  {
>  }
> diff --git a/x86/ioport.c b/x86/ioport.c
> index 7ad7b8f3..a8d2bb1a 100644
> --- a/x86/ioport.c
> +++ b/x86/ioport.c
> @@ -69,7 +69,7 @@ void ioport__map_irq(u8 *irq)
>  {
>  }
>  
> -int ioport__setup_arch(struct kvm *kvm)
> +static int ioport__setup_arch(struct kvm *kvm)
>  {
>  	int r;
>  
> @@ -150,3 +150,4 @@ int ioport__setup_arch(struct kvm *kvm)
>  
>  	return 0;
>  }
> +dev_base_init(ioport__setup_arch);
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 04/22] mmio: Extend handling to include ioport emulation
  2021-02-25  0:58   ` Andre Przywara
@ 2021-03-03 17:58     ` Alexandru Elisei
  -1 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-03 17:58 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: kvm, kvmarm, Marc Zyngier, Sami Mujawar

Hi Andre,

On 2/25/21 12:58 AM, Andre Przywara wrote:
> In their core functionality MMIO and I/O port traps are not really
> different, yet we still have two totally separate code paths for
> handling them. Devices need to decide on one conduit or need to provide
> different handler functions for each of them.
>
> Extend the existing MMIO emulation to also cover ioport handlers.
> This just adds another RB tree root for holding the I/O port handlers,
> but otherwise uses the same tree population and lookup code.
> "ioport" or "mmio" just become a flag in the registration function.
> Provide wrappers to not break existing users, and allow an easy
> transition for the existing ioport handlers.
>
> This also means that ioport handlers now can use the same emulation
> callback prototype as MMIO handlers, which means we have to migrate them
> over. To allow a smooth transition, we hook up the new I/O emulate
> function to the end of the existing ioport emulation code.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  include/kvm/kvm.h | 49 ++++++++++++++++++++++++++++++++---
>  ioport.c          |  4 +--
>  mmio.c            | 65 +++++++++++++++++++++++++++++++++++++++--------
>  3 files changed, 102 insertions(+), 16 deletions(-)
>
> diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
> index f1f0afd7..306b258a 100644
> --- a/include/kvm/kvm.h
> +++ b/include/kvm/kvm.h
> @@ -27,10 +27,23 @@
>  #define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
>  #endif
>  
> +/*
> + * We are reusing the existing DEVICE_BUS_MMIO and DEVICE_BUS_IOPORT constants
> + * from kvm/devices.h to differentiate between registering an I/O port and an
> + * MMIO region.
> + * To avoid collisions with future additions of more bus types, we reserve
> + * a generous 4 bits for the bus mask here.
> + */
> +#define IOTRAP_BUS_MASK		0xf
> +#define IOTRAP_COALESCE		(1U << 4)
> +
>  #define DEFINE_KVM_EXT(ext)		\
>  	.name = #ext,			\
>  	.code = ext
>  
> +struct kvm_cpu;
> +typedef void (*mmio_handler_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> +				u32 len, u8 is_write, void *ptr);
>  typedef void (*fdt_irq_fn)(void *fdt, u8 irq, enum irq_type irq_type);
>  
>  enum {
> @@ -113,6 +126,8 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
>  void kvm__irq_trigger(struct kvm *kvm, int irq);
>  bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count);
>  bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write);
> +bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
> +		      int direction, int size, u32 count);
>  int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr);
>  int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr,
>  		      enum kvm_mem_type type);
> @@ -136,10 +151,36 @@ static inline int kvm__reserve_mem(struct kvm *kvm, u64 guest_phys, u64 size)
>  				 KVM_MEM_TYPE_RESERVED);
>  }
>  
> -int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
> -				    void (*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
> -				    void *ptr);
> -bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
> +int __must_check kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 len,
> +				      mmio_handler_fn mmio_fn, void *ptr,
> +				      unsigned int flags);
> +
> +static inline
> +int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr,
> +				    u64 phys_addr_len, bool coalesce,
> +				    mmio_handler_fn mmio_fn, void *ptr)
> +{
> +	return kvm__register_iotrap(kvm, phys_addr, phys_addr_len, mmio_fn, ptr,
> +			DEVICE_BUS_MMIO | (coalesce ? IOTRAP_COALESCE : 0));
> +}
> +static inline
> +int __must_check kvm__register_pio(struct kvm *kvm, u16 port, u16 len,
> +				   mmio_handler_fn mmio_fn, void *ptr)
> +{
> +	return kvm__register_iotrap(kvm, port, len, mmio_fn, ptr,
> +				    DEVICE_BUS_IOPORT);
> +}
> +
> +bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int flags);
> +static inline bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
> +{
> +	return kvm__deregister_iotrap(kvm, phys_addr, DEVICE_BUS_MMIO);
> +}
> +static inline bool kvm__deregister_pio(struct kvm *kvm, u16 port)
> +{
> +	return kvm__deregister_iotrap(kvm, port, DEVICE_BUS_IOPORT);
> +}
> +
>  void kvm__reboot(struct kvm *kvm);
>  void kvm__pause(struct kvm *kvm);
>  void kvm__continue(struct kvm *kvm);
> diff --git a/ioport.c b/ioport.c
> index e0123f27..ce29e7e7 100644
> --- a/ioport.c
> +++ b/ioport.c
> @@ -162,7 +162,8 @@ bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction,
>  
>  	entry = ioport_get(&ioport_tree, port);
>  	if (!entry)
> -		goto out;
> +		return kvm__emulate_pio(vcpu, port, data, direction,
> +					size, count);
>  
>  	ops	= entry->ops;
>  
> @@ -177,7 +178,6 @@ bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction,
>  
>  	ioport_put(&ioport_tree, entry);
>  
> -out:
>  	if (ret)
>  		return true;
>  
> diff --git a/mmio.c b/mmio.c
> index cd141cd3..75de04ad 100644
> --- a/mmio.c
> +++ b/mmio.c
> @@ -19,13 +19,14 @@ static DEFINE_MUTEX(mmio_lock);
>  
>  struct mmio_mapping {
>  	struct rb_int_node	node;
> -	void			(*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr);
> +	mmio_handler_fn		mmio_fn;
>  	void			*ptr;
>  	u32			refcount;
>  	bool			remove;
>  };
>  
>  static struct rb_root mmio_tree = RB_ROOT;
> +static struct rb_root pio_tree = RB_ROOT;
>  
>  static struct mmio_mapping *mmio_search(struct rb_root *root, u64 addr, u64 len)
>  {
> @@ -103,9 +104,14 @@ static void mmio_put(struct kvm *kvm, struct rb_root *root, struct mmio_mapping
>  	mutex_unlock(&mmio_lock);
>  }
>  
> -int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
> -		       void (*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
> -			void *ptr)
> +static bool trap_is_mmio(unsigned int flags)
> +{
> +	return (flags & IOTRAP_BUS_MASK) == DEVICE_BUS_MMIO;
> +}
> +
> +int kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len,
> +			 mmio_handler_fn mmio_fn, void *ptr,
> +			 unsigned int flags)
>  {
>  	struct mmio_mapping *mmio;
>  	struct kvm_coalesced_mmio_zone zone;
> @@ -127,7 +133,7 @@ int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool c
>  		.remove		= false,
>  	};
>  
> -	if (coalesce) {
> +	if (trap_is_mmio(flags) && (flags & IOTRAP_COALESCE)) {
>  		zone = (struct kvm_coalesced_mmio_zone) {
>  			.addr	= phys_addr,
>  			.size	= phys_addr_len,
> @@ -138,19 +144,29 @@ int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool c
>  			return -errno;
>  		}
>  	}
> +
>  	mutex_lock(&mmio_lock);
> -	ret = mmio_insert(&mmio_tree, mmio);
> +	if (trap_is_mmio(flags))
> +		ret = mmio_insert(&mmio_tree, mmio);
> +	else
> +		ret = mmio_insert(&pio_tree, mmio);
>  	mutex_unlock(&mmio_lock);
>  
>  	return ret;
>  }
>  
> -bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
> +bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int flags)
>  {
>  	struct mmio_mapping *mmio;
> +	struct rb_root *tree;
> +
> +	if ((flags & IOTRAP_BUS_MASK) == DEVICE_BUS_IOPORT)
> +		tree = &pio_tree;
> +	else
> +		tree = &mmio_tree;

We could swap the conditional branches and use trap_is_mmio(flags) like we do above.

Regardless, the patch looks really good:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

>  
>  	mutex_lock(&mmio_lock);
> -	mmio = mmio_search_single(&mmio_tree, phys_addr);
> +	mmio = mmio_search_single(tree, phys_addr);
>  	if (mmio == NULL) {
>  		mutex_unlock(&mmio_lock);
>  		return false;
> @@ -167,7 +183,7 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
>  	 * called mmio_put(). This will trigger use-after-free errors on VCPU0.
>  	 */
>  	if (mmio->refcount == 0)
> -		mmio_deregister(kvm, &mmio_tree, mmio);
> +		mmio_deregister(kvm, tree, mmio);
>  	else
>  		mmio->remove = true;
>  	mutex_unlock(&mmio_lock);
> @@ -175,7 +191,8 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
>  	return true;
>  }
>  
> -bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write)
> +bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data,
> +		       u32 len, u8 is_write)
>  {
>  	struct mmio_mapping *mmio;
>  
> @@ -194,3 +211,31 @@ bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u
>  out:
>  	return true;
>  }
> +
> +bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
> +		     int direction, int size, u32 count)
> +{
> +	struct mmio_mapping *mmio;
> +	bool is_write = direction == KVM_EXIT_IO_OUT;
> +
> +	mmio = mmio_get(&pio_tree, port, size);
> +	if (!mmio) {
> +		if (vcpu->kvm->cfg.ioport_debug) {
> +			fprintf(stderr, "IO error: %s port=%x, size=%d, count=%u\n",
> +				to_direction(direction), port, size, count);
> +
> +			return false;
> +		}
> +		return true;
> +	}
> +
> +	while (count--) {
> +		mmio->mmio_fn(vcpu, port, data, size, is_write, mmio->ptr);
> +
> +		data += size;
> +	}
> +
> +	mmio_put(vcpu->kvm, &pio_tree, mmio);
> +
> +	return true;
> +}

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

* Re: [PATCH kvmtool v2 04/22] mmio: Extend handling to include ioport emulation
@ 2021-03-03 17:58     ` Alexandru Elisei
  0 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-03 17:58 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Hi Andre,

On 2/25/21 12:58 AM, Andre Przywara wrote:
> In their core functionality MMIO and I/O port traps are not really
> different, yet we still have two totally separate code paths for
> handling them. Devices need to decide on one conduit or need to provide
> different handler functions for each of them.
>
> Extend the existing MMIO emulation to also cover ioport handlers.
> This just adds another RB tree root for holding the I/O port handlers,
> but otherwise uses the same tree population and lookup code.
> "ioport" or "mmio" just become a flag in the registration function.
> Provide wrappers to not break existing users, and allow an easy
> transition for the existing ioport handlers.
>
> This also means that ioport handlers now can use the same emulation
> callback prototype as MMIO handlers, which means we have to migrate them
> over. To allow a smooth transition, we hook up the new I/O emulate
> function to the end of the existing ioport emulation code.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  include/kvm/kvm.h | 49 ++++++++++++++++++++++++++++++++---
>  ioport.c          |  4 +--
>  mmio.c            | 65 +++++++++++++++++++++++++++++++++++++++--------
>  3 files changed, 102 insertions(+), 16 deletions(-)
>
> diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
> index f1f0afd7..306b258a 100644
> --- a/include/kvm/kvm.h
> +++ b/include/kvm/kvm.h
> @@ -27,10 +27,23 @@
>  #define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
>  #endif
>  
> +/*
> + * We are reusing the existing DEVICE_BUS_MMIO and DEVICE_BUS_IOPORT constants
> + * from kvm/devices.h to differentiate between registering an I/O port and an
> + * MMIO region.
> + * To avoid collisions with future additions of more bus types, we reserve
> + * a generous 4 bits for the bus mask here.
> + */
> +#define IOTRAP_BUS_MASK		0xf
> +#define IOTRAP_COALESCE		(1U << 4)
> +
>  #define DEFINE_KVM_EXT(ext)		\
>  	.name = #ext,			\
>  	.code = ext
>  
> +struct kvm_cpu;
> +typedef void (*mmio_handler_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> +				u32 len, u8 is_write, void *ptr);
>  typedef void (*fdt_irq_fn)(void *fdt, u8 irq, enum irq_type irq_type);
>  
>  enum {
> @@ -113,6 +126,8 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
>  void kvm__irq_trigger(struct kvm *kvm, int irq);
>  bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count);
>  bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write);
> +bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
> +		      int direction, int size, u32 count);
>  int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr);
>  int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr,
>  		      enum kvm_mem_type type);
> @@ -136,10 +151,36 @@ static inline int kvm__reserve_mem(struct kvm *kvm, u64 guest_phys, u64 size)
>  				 KVM_MEM_TYPE_RESERVED);
>  }
>  
> -int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
> -				    void (*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
> -				    void *ptr);
> -bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
> +int __must_check kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 len,
> +				      mmio_handler_fn mmio_fn, void *ptr,
> +				      unsigned int flags);
> +
> +static inline
> +int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr,
> +				    u64 phys_addr_len, bool coalesce,
> +				    mmio_handler_fn mmio_fn, void *ptr)
> +{
> +	return kvm__register_iotrap(kvm, phys_addr, phys_addr_len, mmio_fn, ptr,
> +			DEVICE_BUS_MMIO | (coalesce ? IOTRAP_COALESCE : 0));
> +}
> +static inline
> +int __must_check kvm__register_pio(struct kvm *kvm, u16 port, u16 len,
> +				   mmio_handler_fn mmio_fn, void *ptr)
> +{
> +	return kvm__register_iotrap(kvm, port, len, mmio_fn, ptr,
> +				    DEVICE_BUS_IOPORT);
> +}
> +
> +bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int flags);
> +static inline bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
> +{
> +	return kvm__deregister_iotrap(kvm, phys_addr, DEVICE_BUS_MMIO);
> +}
> +static inline bool kvm__deregister_pio(struct kvm *kvm, u16 port)
> +{
> +	return kvm__deregister_iotrap(kvm, port, DEVICE_BUS_IOPORT);
> +}
> +
>  void kvm__reboot(struct kvm *kvm);
>  void kvm__pause(struct kvm *kvm);
>  void kvm__continue(struct kvm *kvm);
> diff --git a/ioport.c b/ioport.c
> index e0123f27..ce29e7e7 100644
> --- a/ioport.c
> +++ b/ioport.c
> @@ -162,7 +162,8 @@ bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction,
>  
>  	entry = ioport_get(&ioport_tree, port);
>  	if (!entry)
> -		goto out;
> +		return kvm__emulate_pio(vcpu, port, data, direction,
> +					size, count);
>  
>  	ops	= entry->ops;
>  
> @@ -177,7 +178,6 @@ bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction,
>  
>  	ioport_put(&ioport_tree, entry);
>  
> -out:
>  	if (ret)
>  		return true;
>  
> diff --git a/mmio.c b/mmio.c
> index cd141cd3..75de04ad 100644
> --- a/mmio.c
> +++ b/mmio.c
> @@ -19,13 +19,14 @@ static DEFINE_MUTEX(mmio_lock);
>  
>  struct mmio_mapping {
>  	struct rb_int_node	node;
> -	void			(*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr);
> +	mmio_handler_fn		mmio_fn;
>  	void			*ptr;
>  	u32			refcount;
>  	bool			remove;
>  };
>  
>  static struct rb_root mmio_tree = RB_ROOT;
> +static struct rb_root pio_tree = RB_ROOT;
>  
>  static struct mmio_mapping *mmio_search(struct rb_root *root, u64 addr, u64 len)
>  {
> @@ -103,9 +104,14 @@ static void mmio_put(struct kvm *kvm, struct rb_root *root, struct mmio_mapping
>  	mutex_unlock(&mmio_lock);
>  }
>  
> -int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
> -		       void (*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
> -			void *ptr)
> +static bool trap_is_mmio(unsigned int flags)
> +{
> +	return (flags & IOTRAP_BUS_MASK) == DEVICE_BUS_MMIO;
> +}
> +
> +int kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len,
> +			 mmio_handler_fn mmio_fn, void *ptr,
> +			 unsigned int flags)
>  {
>  	struct mmio_mapping *mmio;
>  	struct kvm_coalesced_mmio_zone zone;
> @@ -127,7 +133,7 @@ int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool c
>  		.remove		= false,
>  	};
>  
> -	if (coalesce) {
> +	if (trap_is_mmio(flags) && (flags & IOTRAP_COALESCE)) {
>  		zone = (struct kvm_coalesced_mmio_zone) {
>  			.addr	= phys_addr,
>  			.size	= phys_addr_len,
> @@ -138,19 +144,29 @@ int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool c
>  			return -errno;
>  		}
>  	}
> +
>  	mutex_lock(&mmio_lock);
> -	ret = mmio_insert(&mmio_tree, mmio);
> +	if (trap_is_mmio(flags))
> +		ret = mmio_insert(&mmio_tree, mmio);
> +	else
> +		ret = mmio_insert(&pio_tree, mmio);
>  	mutex_unlock(&mmio_lock);
>  
>  	return ret;
>  }
>  
> -bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
> +bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int flags)
>  {
>  	struct mmio_mapping *mmio;
> +	struct rb_root *tree;
> +
> +	if ((flags & IOTRAP_BUS_MASK) == DEVICE_BUS_IOPORT)
> +		tree = &pio_tree;
> +	else
> +		tree = &mmio_tree;

We could swap the conditional branches and use trap_is_mmio(flags) like we do above.

Regardless, the patch looks really good:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

>  
>  	mutex_lock(&mmio_lock);
> -	mmio = mmio_search_single(&mmio_tree, phys_addr);
> +	mmio = mmio_search_single(tree, phys_addr);
>  	if (mmio == NULL) {
>  		mutex_unlock(&mmio_lock);
>  		return false;
> @@ -167,7 +183,7 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
>  	 * called mmio_put(). This will trigger use-after-free errors on VCPU0.
>  	 */
>  	if (mmio->refcount == 0)
> -		mmio_deregister(kvm, &mmio_tree, mmio);
> +		mmio_deregister(kvm, tree, mmio);
>  	else
>  		mmio->remove = true;
>  	mutex_unlock(&mmio_lock);
> @@ -175,7 +191,8 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
>  	return true;
>  }
>  
> -bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write)
> +bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data,
> +		       u32 len, u8 is_write)
>  {
>  	struct mmio_mapping *mmio;
>  
> @@ -194,3 +211,31 @@ bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u
>  out:
>  	return true;
>  }
> +
> +bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
> +		     int direction, int size, u32 count)
> +{
> +	struct mmio_mapping *mmio;
> +	bool is_write = direction == KVM_EXIT_IO_OUT;
> +
> +	mmio = mmio_get(&pio_tree, port, size);
> +	if (!mmio) {
> +		if (vcpu->kvm->cfg.ioport_debug) {
> +			fprintf(stderr, "IO error: %s port=%x, size=%d, count=%u\n",
> +				to_direction(direction), port, size, count);
> +
> +			return false;
> +		}
> +		return true;
> +	}
> +
> +	while (count--) {
> +		mmio->mmio_fn(vcpu, port, data, size, is_write, mmio->ptr);
> +
> +		data += size;
> +	}
> +
> +	mmio_put(vcpu->kvm, &pio_tree, mmio);
> +
> +	return true;
> +}
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 00/22] Unify I/O port and MMIO trap handling
  2021-03-02 17:57   ` Alexandru Elisei
@ 2021-03-03 18:41     ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-03-03 18:41 UTC (permalink / raw)
  To: Alexandru Elisei
  Cc: Will Deacon, Julien Thierry, kvm, kvmarm, Marc Zyngier, Sami Mujawar

On Tue, 2 Mar 2021 17:57:05 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

Hi,

> I've started to review this iteration and I've come across this error when trying
> to apply the patches:
> 
> $ git am --reject
> patches/unify-ioport-and-mmio/v2/Unify-I-O-port-and-MMIO-trap-handling.patch
> Applying: ioport: Remove ioport__setup_arch()
> Checking patch arm/ioport.c...
> Checking patch include/kvm/ioport.h...
> Checking patch ioport.c...
> Checking patch mips/kvm.c...
> Checking patch powerpc/ioport.c...
> Checking patch x86/ioport.c...
> Applied patch arm/ioport.c cleanly.
> Applied patch include/kvm/ioport.h cleanly.
> Applied patch ioport.c cleanly.
> Applied patch mips/kvm.c cleanly.
> Applied patch powerpc/ioport.c cleanly.
> Applied patch x86/ioport.c cleanly.
> Applying: hw/serial: Use device abstraction for FDT generator function
> Checking patch hw/serial.c...
> Checking patch include/kvm/kvm.h...
> Applied patch hw/serial.c cleanly.
> Applied patch include/kvm/kvm.h cleanly.
> Applying: ioport: Retire .generate_fdt_node functionality
> Checking patch include/kvm/ioport.h...
> Checking patch ioport.c...
> Applied patch include/kvm/ioport.h cleanly.
> Applied patch ioport.c cleanly.
> Applying: mmio: Extend handling to include ioport emulation
> Checking patch include/kvm/kvm.h...
> Checking patch ioport.c...
> Checking patch mmio.c...
> Applied patch include/kvm/kvm.h cleanly.
> Applied patch ioport.c cleanly.
> Applied patch mmio.c cleanly.
> Applying: hw/i8042: Clean up data types
> Checking patch hw/i8042.c...
> Applied patch hw/i8042.c cleanly.
> Applying: hw/i8042: Refactor trap handler
> Checking patch hw/i8042.c...
> Applied patch hw/i8042.c cleanly.
> Applying: hw/i8042: Switch to new trap handlers
> Checking patch hw/i8042.c...
> error: while searching for:
>         ioport__write8(data, value);
> }
> 
> /*
>  * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
>  */
> static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void
> *data, int size)
> {
>     kbd_io(vcpu, port, data, size, false, NULL);
> 
>     return true;
> }
> 
> static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void
> *data, int size)
> {
>     kbd_io(vcpu, port, data, size, true, NULL);
> 
>     return true;
> }
> 
> static struct ioport_operations kbd_ops = {
>     .io_in        = kbd_in,
>     .io_out        = kbd_out,
> };
> 
> int kbd__init(struct kvm *kvm)
> {
>     int r;
> 
>     kbd_reset();
>     state.kvm = kvm;
>     r = ioport__register(kvm, I8042_DATA_REG, &kbd_ops, 2, NULL);
>     if (r < 0)
>         return r;
>     r = ioport__register(kvm, I8042_COMMAND_REG, &kbd_ops, 2, NULL);
>     if (r < 0) {
>         ioport__unregister(kvm, I8042_DATA_REG);
>         return r;
>     }
> 
> 
> error: patch failed: hw/i8042.c:325
> Checking patch include/kvm/i8042.h...
> Applying patch hw/i8042.c with 1 reject...
> Rejected hunk #1.
> Applied patch include/kvm/i8042.h cleanly.
> Patch failed at 0007 hw/i8042: Switch to new trap handlers
> hint: Use 'git am --show-current-patch=diff' to see the failed patch
> When you have resolved this problem, run "git am --continue".
> If you prefer to skip this patch, run "git am --skip" instead.
> To restore the original branch and stop patching, run "git am --abort".
> 
> where the patch file is from patchwork.kernel.org [1], created when clicking on
> the "series" button on the top right. I'm not sure what is causing the error,
> everything looks the same to me.

Ah, thanks for the heads up, and sorry for the pain! I can reproduce it,
and see what's going on: I made a last minute change, when creating the
changelog and going over the list of your comments again, and replaced
"false" with 0 in kbd_in() in patch 06/22, but only in the file, not in
the repo. So the follow-up patch - which removes this line again ;-) -
fails to apply.

> Regardless, I've applied the reject manually and everything looks ok.

Oh great, thanks! So I will wait with a resend until you are finished
with the review, and will then also upload to our gitlab.

Apologies for the inconvenience!

Cheers,
Andre


> 
> [1]
> https://patchwork.kernel.org/project/kvm/patch/20210225005915.26423-2-andre.przywara@arm.com/
> 
> Thanks,
> 
> Alex
> 
> On 2/25/21 12:58 AM, Andre Przywara wrote:
> > Compared to v1 this has a few fixes, as suggested by Alex.
> > There is a new patch 20/22, which cleans up the ARM memory map
> > definition and adds some chart to make it more obvious what is going on.
> > For a changelog, see below.
> >
> > ==============
> >
> > At the moment we use two separate code paths to handle exits for
> > KVM_EXIT_IO (ioport.c) and KVM_EXIT_MMIO (mmio.c), even though they
> > are semantically very similar. Because the trap handler callback routine
> > is different, devices need to decide on one conduit or need to provide
> > different handler functions for both of them.
> >
> > This is not only unnecessary code duplication, but makes switching
> > devices from I/O port to MMIO a tedious task, even though there is no
> > real difference between the two, especially on ARM and PowerPC.
> >
> > For ARM we aim at providing a flexible memory layout, and also have
> > trouble with the UART and RTC device overlapping with the PCI I/O area,
> > so it seems indicated to tackle this once and for all.
> >
> > The first three patches do some cleanup, to simplify things later.
> >
> > Patch 04/22 lays the groundwork, by extending mmio.c to be able to also
> > register I/O port trap handlers, using the same callback prototype as
> > we use for MMIO.
> >
> > The next 14 patches then convert devices that use the I/O port
> > interface over to the new joint interface. This requires to rework
> > the trap handler routine to adhere to the same prototype as the existing
> > MMIO handlers. For most devices this is done in two steps: a first to
> > introduce the reworked handler routine, and a second to switch to the new
> > joint registration routine. For some devices the first step is trivial,
> > so it's done in one patch.
> >
> > Patch 19/22 then retires the old I/O port interface, by removing ioport.c
> > and friends.
> > Patch 20/22 uses the opportunity to clean up the memory map description,
> > also declares a new region (from 16MB on), where the final two patches
> > switch the UART and the RTC device to. They are now registered
> > on the MMIO "bus", when running on ARM or arm64. This moves them away
> > from the first 64KB, so they are not in the PCI I/O area anymore.
> >
> > Please have a look and comment!
> >
> > Cheers,
> > Andre
> >
> > Changelog v1 .. v2:
> > - rework memory map definition
> > - add explicit debug output for debug I/O port
> > - add explicit check for MMIO coalescing on I/O ports
> > - drop usage of ioport__{read,write}8() from serial
> > - drop explicit I/O port cleanup routine (to mimic MMIO operation)
> > - add comment for IOTRAP_BUS_MASK
> > - minor cleanups / formatting changes
> >
> > Andre Przywara (22):
> >   ioport: Remove ioport__setup_arch()
> >   hw/serial: Use device abstraction for FDT generator function
> >   ioport: Retire .generate_fdt_node functionality
> >   mmio: Extend handling to include ioport emulation
> >   hw/i8042: Clean up data types
> >   hw/i8042: Refactor trap handler
> >   hw/i8042: Switch to new trap handlers
> >   x86/ioport: Refactor trap handlers
> >   x86/ioport: Switch to new trap handlers
> >   hw/rtc: Refactor trap handlers
> >   hw/rtc: Switch to new trap handler
> >   hw/vesa: Switch trap handling to use MMIO handler
> >   hw/serial: Refactor trap handler
> >   hw/serial: Switch to new trap handlers
> >   vfio: Refactor ioport trap handler
> >   vfio: Switch to new ioport trap handlers
> >   virtio: Switch trap handling to use MMIO handler
> >   pci: Switch trap handling to use MMIO handler
> >   Remove ioport specific routines
> >   arm: Reorganise and document memory map
> >   hw/serial: ARM/arm64: Use MMIO at higher addresses
> >   hw/rtc: ARM/arm64: Use MMIO at higher addresses
> >
> >  Makefile                          |   1 -
> >  arm/include/arm-common/kvm-arch.h |  47 ++++--
> >  arm/ioport.c                      |   5 -
> >  hw/i8042.c                        |  94 +++++-------
> >  hw/rtc.c                          |  91 ++++++------
> >  hw/serial.c                       | 160 ++++++++++++--------
> >  hw/vesa.c                         |  19 +--
> >  include/kvm/i8042.h               |   1 -
> >  include/kvm/ioport.h              |  32 ----
> >  include/kvm/kvm.h                 |  49 ++++++-
> >  ioport.c                          | 235 ------------------------------
> >  mips/kvm.c                        |   5 -
> >  mmio.c                            |  65 +++++++--
> >  pci.c                             |  82 +++--------
> >  powerpc/ioport.c                  |   6 -
> >  vfio/core.c                       |  50 ++++---
> >  virtio/pci.c                      |  46 ++----
> >  x86/ioport.c                      | 107 +++++++-------
> >  18 files changed, 433 insertions(+), 662 deletions(-)
> >  delete mode 100644 ioport.c
> >  


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

* Re: [PATCH kvmtool v2 00/22] Unify I/O port and MMIO trap handling
@ 2021-03-03 18:41     ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-03-03 18:41 UTC (permalink / raw)
  To: Alexandru Elisei; +Cc: kvm, Marc Zyngier, Sami Mujawar, Will Deacon, kvmarm

On Tue, 2 Mar 2021 17:57:05 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

Hi,

> I've started to review this iteration and I've come across this error when trying
> to apply the patches:
> 
> $ git am --reject
> patches/unify-ioport-and-mmio/v2/Unify-I-O-port-and-MMIO-trap-handling.patch
> Applying: ioport: Remove ioport__setup_arch()
> Checking patch arm/ioport.c...
> Checking patch include/kvm/ioport.h...
> Checking patch ioport.c...
> Checking patch mips/kvm.c...
> Checking patch powerpc/ioport.c...
> Checking patch x86/ioport.c...
> Applied patch arm/ioport.c cleanly.
> Applied patch include/kvm/ioport.h cleanly.
> Applied patch ioport.c cleanly.
> Applied patch mips/kvm.c cleanly.
> Applied patch powerpc/ioport.c cleanly.
> Applied patch x86/ioport.c cleanly.
> Applying: hw/serial: Use device abstraction for FDT generator function
> Checking patch hw/serial.c...
> Checking patch include/kvm/kvm.h...
> Applied patch hw/serial.c cleanly.
> Applied patch include/kvm/kvm.h cleanly.
> Applying: ioport: Retire .generate_fdt_node functionality
> Checking patch include/kvm/ioport.h...
> Checking patch ioport.c...
> Applied patch include/kvm/ioport.h cleanly.
> Applied patch ioport.c cleanly.
> Applying: mmio: Extend handling to include ioport emulation
> Checking patch include/kvm/kvm.h...
> Checking patch ioport.c...
> Checking patch mmio.c...
> Applied patch include/kvm/kvm.h cleanly.
> Applied patch ioport.c cleanly.
> Applied patch mmio.c cleanly.
> Applying: hw/i8042: Clean up data types
> Checking patch hw/i8042.c...
> Applied patch hw/i8042.c cleanly.
> Applying: hw/i8042: Refactor trap handler
> Checking patch hw/i8042.c...
> Applied patch hw/i8042.c cleanly.
> Applying: hw/i8042: Switch to new trap handlers
> Checking patch hw/i8042.c...
> error: while searching for:
>         ioport__write8(data, value);
> }
> 
> /*
>  * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
>  */
> static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void
> *data, int size)
> {
>     kbd_io(vcpu, port, data, size, false, NULL);
> 
>     return true;
> }
> 
> static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void
> *data, int size)
> {
>     kbd_io(vcpu, port, data, size, true, NULL);
> 
>     return true;
> }
> 
> static struct ioport_operations kbd_ops = {
>     .io_in        = kbd_in,
>     .io_out        = kbd_out,
> };
> 
> int kbd__init(struct kvm *kvm)
> {
>     int r;
> 
>     kbd_reset();
>     state.kvm = kvm;
>     r = ioport__register(kvm, I8042_DATA_REG, &kbd_ops, 2, NULL);
>     if (r < 0)
>         return r;
>     r = ioport__register(kvm, I8042_COMMAND_REG, &kbd_ops, 2, NULL);
>     if (r < 0) {
>         ioport__unregister(kvm, I8042_DATA_REG);
>         return r;
>     }
> 
> 
> error: patch failed: hw/i8042.c:325
> Checking patch include/kvm/i8042.h...
> Applying patch hw/i8042.c with 1 reject...
> Rejected hunk #1.
> Applied patch include/kvm/i8042.h cleanly.
> Patch failed at 0007 hw/i8042: Switch to new trap handlers
> hint: Use 'git am --show-current-patch=diff' to see the failed patch
> When you have resolved this problem, run "git am --continue".
> If you prefer to skip this patch, run "git am --skip" instead.
> To restore the original branch and stop patching, run "git am --abort".
> 
> where the patch file is from patchwork.kernel.org [1], created when clicking on
> the "series" button on the top right. I'm not sure what is causing the error,
> everything looks the same to me.

Ah, thanks for the heads up, and sorry for the pain! I can reproduce it,
and see what's going on: I made a last minute change, when creating the
changelog and going over the list of your comments again, and replaced
"false" with 0 in kbd_in() in patch 06/22, but only in the file, not in
the repo. So the follow-up patch - which removes this line again ;-) -
fails to apply.

> Regardless, I've applied the reject manually and everything looks ok.

Oh great, thanks! So I will wait with a resend until you are finished
with the review, and will then also upload to our gitlab.

Apologies for the inconvenience!

Cheers,
Andre


> 
> [1]
> https://patchwork.kernel.org/project/kvm/patch/20210225005915.26423-2-andre.przywara@arm.com/
> 
> Thanks,
> 
> Alex
> 
> On 2/25/21 12:58 AM, Andre Przywara wrote:
> > Compared to v1 this has a few fixes, as suggested by Alex.
> > There is a new patch 20/22, which cleans up the ARM memory map
> > definition and adds some chart to make it more obvious what is going on.
> > For a changelog, see below.
> >
> > ==============
> >
> > At the moment we use two separate code paths to handle exits for
> > KVM_EXIT_IO (ioport.c) and KVM_EXIT_MMIO (mmio.c), even though they
> > are semantically very similar. Because the trap handler callback routine
> > is different, devices need to decide on one conduit or need to provide
> > different handler functions for both of them.
> >
> > This is not only unnecessary code duplication, but makes switching
> > devices from I/O port to MMIO a tedious task, even though there is no
> > real difference between the two, especially on ARM and PowerPC.
> >
> > For ARM we aim at providing a flexible memory layout, and also have
> > trouble with the UART and RTC device overlapping with the PCI I/O area,
> > so it seems indicated to tackle this once and for all.
> >
> > The first three patches do some cleanup, to simplify things later.
> >
> > Patch 04/22 lays the groundwork, by extending mmio.c to be able to also
> > register I/O port trap handlers, using the same callback prototype as
> > we use for MMIO.
> >
> > The next 14 patches then convert devices that use the I/O port
> > interface over to the new joint interface. This requires to rework
> > the trap handler routine to adhere to the same prototype as the existing
> > MMIO handlers. For most devices this is done in two steps: a first to
> > introduce the reworked handler routine, and a second to switch to the new
> > joint registration routine. For some devices the first step is trivial,
> > so it's done in one patch.
> >
> > Patch 19/22 then retires the old I/O port interface, by removing ioport.c
> > and friends.
> > Patch 20/22 uses the opportunity to clean up the memory map description,
> > also declares a new region (from 16MB on), where the final two patches
> > switch the UART and the RTC device to. They are now registered
> > on the MMIO "bus", when running on ARM or arm64. This moves them away
> > from the first 64KB, so they are not in the PCI I/O area anymore.
> >
> > Please have a look and comment!
> >
> > Cheers,
> > Andre
> >
> > Changelog v1 .. v2:
> > - rework memory map definition
> > - add explicit debug output for debug I/O port
> > - add explicit check for MMIO coalescing on I/O ports
> > - drop usage of ioport__{read,write}8() from serial
> > - drop explicit I/O port cleanup routine (to mimic MMIO operation)
> > - add comment for IOTRAP_BUS_MASK
> > - minor cleanups / formatting changes
> >
> > Andre Przywara (22):
> >   ioport: Remove ioport__setup_arch()
> >   hw/serial: Use device abstraction for FDT generator function
> >   ioport: Retire .generate_fdt_node functionality
> >   mmio: Extend handling to include ioport emulation
> >   hw/i8042: Clean up data types
> >   hw/i8042: Refactor trap handler
> >   hw/i8042: Switch to new trap handlers
> >   x86/ioport: Refactor trap handlers
> >   x86/ioport: Switch to new trap handlers
> >   hw/rtc: Refactor trap handlers
> >   hw/rtc: Switch to new trap handler
> >   hw/vesa: Switch trap handling to use MMIO handler
> >   hw/serial: Refactor trap handler
> >   hw/serial: Switch to new trap handlers
> >   vfio: Refactor ioport trap handler
> >   vfio: Switch to new ioport trap handlers
> >   virtio: Switch trap handling to use MMIO handler
> >   pci: Switch trap handling to use MMIO handler
> >   Remove ioport specific routines
> >   arm: Reorganise and document memory map
> >   hw/serial: ARM/arm64: Use MMIO at higher addresses
> >   hw/rtc: ARM/arm64: Use MMIO at higher addresses
> >
> >  Makefile                          |   1 -
> >  arm/include/arm-common/kvm-arch.h |  47 ++++--
> >  arm/ioport.c                      |   5 -
> >  hw/i8042.c                        |  94 +++++-------
> >  hw/rtc.c                          |  91 ++++++------
> >  hw/serial.c                       | 160 ++++++++++++--------
> >  hw/vesa.c                         |  19 +--
> >  include/kvm/i8042.h               |   1 -
> >  include/kvm/ioport.h              |  32 ----
> >  include/kvm/kvm.h                 |  49 ++++++-
> >  ioport.c                          | 235 ------------------------------
> >  mips/kvm.c                        |   5 -
> >  mmio.c                            |  65 +++++++--
> >  pci.c                             |  82 +++--------
> >  powerpc/ioport.c                  |   6 -
> >  vfio/core.c                       |  50 ++++---
> >  virtio/pci.c                      |  46 ++----
> >  x86/ioport.c                      | 107 +++++++-------
> >  18 files changed, 433 insertions(+), 662 deletions(-)
> >  delete mode 100644 ioport.c
> >  

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 06/22] hw/i8042: Refactor trap handler
  2021-02-25  0:58   ` Andre Przywara
@ 2021-03-08 17:16     ` Alexandru Elisei
  -1 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-08 17:16 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: kvm, kvmarm, Marc Zyngier, Sami Mujawar

Hi Andre,

On 2/25/21 12:58 AM, Andre Przywara wrote:
> With the planned retirement of the special ioport emulation code, we
> need to provide an emulation function compatible with the MMIO
> prototype.
>
> Adjust the trap handler to use that new function, and provide shims to
> implement the old ioport interface, for now.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  hw/i8042.c | 68 +++++++++++++++++++++++++++---------------------------
>  1 file changed, 34 insertions(+), 34 deletions(-)
>
> diff --git a/hw/i8042.c b/hw/i8042.c
> index 7d1f9772..ab866662 100644
> --- a/hw/i8042.c
> +++ b/hw/i8042.c
> @@ -292,52 +292,52 @@ static void kbd_reset(void)
>  	};
>  }
>  
> -/*
> - * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
> - */
> -static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +static void kbd_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> +		   u8 is_write, void *ptr)
>  {
> -	switch (port) {
> -	case I8042_COMMAND_REG: {
> -		u8 value = kbd_read_status();
> -		ioport__write8(data, value);
> +	u8 value;
> +
> +	if (is_write)
> +		value = ioport__read8(data);
> +
> +	switch (addr) {
> +	case I8042_COMMAND_REG:
> +		if (is_write)
> +			kbd_write_command(vcpu->kvm, value);
> +		else
> +			value = kbd_read_status();
>  		break;
> -	}
> -	case I8042_DATA_REG: {
> -		u8 value = kbd_read_data();
> -		ioport__write8(data, value);
> +	case I8042_DATA_REG:
> +		if (is_write)
> +			kbd_write_data(value);
> +		else
> +			value = kbd_read_data();
>  		break;
> -	}
> -	case I8042_PORT_B_REG: {
> -		ioport__write8(data, 0x20);
> +	case I8042_PORT_B_REG:
> +		if (!is_write)
> +			value = 0x20;
>  		break;
> -	}
>  	default:
> -		return false;
> +		return;
>  	}
>  
> +	if (!is_write)
> +		ioport__write8(data, value);
> +}
> +
> +/*
> + * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
> + */
> +static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +{
> +	kbd_io(vcpu, port, data, size, 0, NULL);
> +
>  	return true;
>  }
>  
>  static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
>  {
> -	switch (port) {
> -	case I8042_COMMAND_REG: {
> -		u8 value = ioport__read8(data);
> -		kbd_write_command(vcpu->kvm, value);
> -		break;
> -	}
> -	case I8042_DATA_REG: {
> -		u8 value = ioport__read8(data);
> -		kbd_write_data(value);
> -		break;
> -	}
> -	case I8042_PORT_B_REG: {
> -		break;
> -	}
> -	default:
> -		return false;
> -	}
> +	kbd_io(vcpu, port, data, size, 1, NULL);

I think I made a mistake when I suggested that is_write should 0 or 1. I followed
the emulation path in kvmtool and it turns out that is_write is supposed to
represent the field with the same name from the anonymous struct mmio from struct
kvm_run (more precisely, the struct defined at line 4980 from
Documentation/virt/kvm/api.rst, Linux tag v5.11). I think the is_write field is
declared in kvm_run as an u8 for compatibility with an userspace which might not
know about the bool type. is_write is also treated as a bool in the MMIO exit path
by KVM (see arch/arm64/kvm/mmio.c::io_mem_abort()).

kvmtool assigns is_write a boolean value everywhere except in this file, would you
mind changing it back to a bool? Sorry for suggesting the wrong thing.

I checked that the code remains functionally identical, with the above change:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

>  
>  	return true;
>  }

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

* Re: [PATCH kvmtool v2 06/22] hw/i8042: Refactor trap handler
@ 2021-03-08 17:16     ` Alexandru Elisei
  0 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-08 17:16 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Hi Andre,

On 2/25/21 12:58 AM, Andre Przywara wrote:
> With the planned retirement of the special ioport emulation code, we
> need to provide an emulation function compatible with the MMIO
> prototype.
>
> Adjust the trap handler to use that new function, and provide shims to
> implement the old ioport interface, for now.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  hw/i8042.c | 68 +++++++++++++++++++++++++++---------------------------
>  1 file changed, 34 insertions(+), 34 deletions(-)
>
> diff --git a/hw/i8042.c b/hw/i8042.c
> index 7d1f9772..ab866662 100644
> --- a/hw/i8042.c
> +++ b/hw/i8042.c
> @@ -292,52 +292,52 @@ static void kbd_reset(void)
>  	};
>  }
>  
> -/*
> - * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
> - */
> -static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +static void kbd_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> +		   u8 is_write, void *ptr)
>  {
> -	switch (port) {
> -	case I8042_COMMAND_REG: {
> -		u8 value = kbd_read_status();
> -		ioport__write8(data, value);
> +	u8 value;
> +
> +	if (is_write)
> +		value = ioport__read8(data);
> +
> +	switch (addr) {
> +	case I8042_COMMAND_REG:
> +		if (is_write)
> +			kbd_write_command(vcpu->kvm, value);
> +		else
> +			value = kbd_read_status();
>  		break;
> -	}
> -	case I8042_DATA_REG: {
> -		u8 value = kbd_read_data();
> -		ioport__write8(data, value);
> +	case I8042_DATA_REG:
> +		if (is_write)
> +			kbd_write_data(value);
> +		else
> +			value = kbd_read_data();
>  		break;
> -	}
> -	case I8042_PORT_B_REG: {
> -		ioport__write8(data, 0x20);
> +	case I8042_PORT_B_REG:
> +		if (!is_write)
> +			value = 0x20;
>  		break;
> -	}
>  	default:
> -		return false;
> +		return;
>  	}
>  
> +	if (!is_write)
> +		ioport__write8(data, value);
> +}
> +
> +/*
> + * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
> + */
> +static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +{
> +	kbd_io(vcpu, port, data, size, 0, NULL);
> +
>  	return true;
>  }
>  
>  static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
>  {
> -	switch (port) {
> -	case I8042_COMMAND_REG: {
> -		u8 value = ioport__read8(data);
> -		kbd_write_command(vcpu->kvm, value);
> -		break;
> -	}
> -	case I8042_DATA_REG: {
> -		u8 value = ioport__read8(data);
> -		kbd_write_data(value);
> -		break;
> -	}
> -	case I8042_PORT_B_REG: {
> -		break;
> -	}
> -	default:
> -		return false;
> -	}
> +	kbd_io(vcpu, port, data, size, 1, NULL);

I think I made a mistake when I suggested that is_write should 0 or 1. I followed
the emulation path in kvmtool and it turns out that is_write is supposed to
represent the field with the same name from the anonymous struct mmio from struct
kvm_run (more precisely, the struct defined at line 4980 from
Documentation/virt/kvm/api.rst, Linux tag v5.11). I think the is_write field is
declared in kvm_run as an u8 for compatibility with an userspace which might not
know about the bool type. is_write is also treated as a bool in the MMIO exit path
by KVM (see arch/arm64/kvm/mmio.c::io_mem_abort()).

kvmtool assigns is_write a boolean value everywhere except in this file, would you
mind changing it back to a bool? Sorry for suggesting the wrong thing.

I checked that the code remains functionally identical, with the above change:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

>  
>  	return true;
>  }
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 07/22] hw/i8042: Switch to new trap handlers
  2021-02-25  0:59   ` Andre Przywara
@ 2021-03-08 17:22     ` Alexandru Elisei
  -1 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-08 17:22 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: kvm, kvmarm, Marc Zyngier, Sami Mujawar

Hi Andre,

On 2/25/21 12:59 AM, Andre Przywara wrote:
> Now that the PC keyboard has a trap handler adhering to the MMIO fault
> handler prototype, let's switch over to the joint registration routine.
>
> This allows us to get rid of the ioport shim routines.
>
> Make the kbd_init() function static on the way.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  hw/i8042.c          | 30 ++++--------------------------
>  include/kvm/i8042.h |  1 -
>  2 files changed, 4 insertions(+), 27 deletions(-)
>
> diff --git a/hw/i8042.c b/hw/i8042.c
> index ab866662..20be36c4 100644
> --- a/hw/i8042.c
> +++ b/hw/i8042.c
> @@ -325,40 +325,18 @@ static void kbd_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
>  		ioport__write8(data, value);
>  }
>  
> -/*
> - * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
> - */
> -static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	kbd_io(vcpu, port, data, size, false, NULL);
> -
> -	return true;
> -}
> -
> -static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	kbd_io(vcpu, port, data, size, true, NULL);
> -
> -	return true;
> -}
> -
> -static struct ioport_operations kbd_ops = {
> -	.io_in		= kbd_in,
> -	.io_out		= kbd_out,
> -};
> -
> -int kbd__init(struct kvm *kvm)
> +static int kbd__init(struct kvm *kvm)
>  {
>  	int r;
>  
>  	kbd_reset();
>  	state.kvm = kvm;
> -	r = ioport__register(kvm, I8042_DATA_REG, &kbd_ops, 2, NULL);
> +	r = kvm__register_pio(kvm, I8042_DATA_REG, 2, kbd_io, NULL);
>  	if (r < 0)
>  		return r;
> -	r = ioport__register(kvm, I8042_COMMAND_REG, &kbd_ops, 2, NULL);
> +	r = kvm__register_pio(kvm, I8042_COMMAND_REG, 2, kbd_io, NULL);
>  	if (r < 0) {
> -		ioport__unregister(kvm, I8042_DATA_REG);
> +		kvm__deregister_pio(kvm, I8042_DATA_REG);
>  		return r;
>  	}
>  
> diff --git a/include/kvm/i8042.h b/include/kvm/i8042.h
> index 3b4ab688..cd4ae6bb 100644
> --- a/include/kvm/i8042.h
> +++ b/include/kvm/i8042.h
> @@ -7,6 +7,5 @@ struct kvm;
>  
>  void mouse_queue(u8 c);
>  void kbd_queue(u8 c);
> -int kbd__init(struct kvm *kvm);
>  
>  #endif

Looks good, I also compile tested the code:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex


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

* Re: [PATCH kvmtool v2 07/22] hw/i8042: Switch to new trap handlers
@ 2021-03-08 17:22     ` Alexandru Elisei
  0 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-08 17:22 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Hi Andre,

On 2/25/21 12:59 AM, Andre Przywara wrote:
> Now that the PC keyboard has a trap handler adhering to the MMIO fault
> handler prototype, let's switch over to the joint registration routine.
>
> This allows us to get rid of the ioport shim routines.
>
> Make the kbd_init() function static on the way.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  hw/i8042.c          | 30 ++++--------------------------
>  include/kvm/i8042.h |  1 -
>  2 files changed, 4 insertions(+), 27 deletions(-)
>
> diff --git a/hw/i8042.c b/hw/i8042.c
> index ab866662..20be36c4 100644
> --- a/hw/i8042.c
> +++ b/hw/i8042.c
> @@ -325,40 +325,18 @@ static void kbd_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
>  		ioport__write8(data, value);
>  }
>  
> -/*
> - * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
> - */
> -static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	kbd_io(vcpu, port, data, size, false, NULL);
> -
> -	return true;
> -}
> -
> -static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	kbd_io(vcpu, port, data, size, true, NULL);
> -
> -	return true;
> -}
> -
> -static struct ioport_operations kbd_ops = {
> -	.io_in		= kbd_in,
> -	.io_out		= kbd_out,
> -};
> -
> -int kbd__init(struct kvm *kvm)
> +static int kbd__init(struct kvm *kvm)
>  {
>  	int r;
>  
>  	kbd_reset();
>  	state.kvm = kvm;
> -	r = ioport__register(kvm, I8042_DATA_REG, &kbd_ops, 2, NULL);
> +	r = kvm__register_pio(kvm, I8042_DATA_REG, 2, kbd_io, NULL);
>  	if (r < 0)
>  		return r;
> -	r = ioport__register(kvm, I8042_COMMAND_REG, &kbd_ops, 2, NULL);
> +	r = kvm__register_pio(kvm, I8042_COMMAND_REG, 2, kbd_io, NULL);
>  	if (r < 0) {
> -		ioport__unregister(kvm, I8042_DATA_REG);
> +		kvm__deregister_pio(kvm, I8042_DATA_REG);
>  		return r;
>  	}
>  
> diff --git a/include/kvm/i8042.h b/include/kvm/i8042.h
> index 3b4ab688..cd4ae6bb 100644
> --- a/include/kvm/i8042.h
> +++ b/include/kvm/i8042.h
> @@ -7,6 +7,5 @@ struct kvm;
>  
>  void mouse_queue(u8 c);
>  void kbd_queue(u8 c);
> -int kbd__init(struct kvm *kvm);
>  
>  #endif

Looks good, I also compile tested the code:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 08/22] x86/ioport: Refactor trap handlers
  2021-02-25  0:59   ` Andre Przywara
@ 2021-03-09 11:49     ` Alexandru Elisei
  -1 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 11:49 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: kvm, kvmarm, Marc Zyngier, Sami Mujawar

Hi Andre,

Regarding the naming of the functions, these are real ioport emulation functions,
which are executed because a KVM_EXIT_IO exit reason from KVM_RUN. Wouldn't naming
the functions something like *_pio or *_io be more appropriate?

Thanks,

Alex

On 2/25/21 12:59 AM, Andre Przywara wrote:
> With the planned retirement of the special ioport emulation code, we
> need to provide emulation functions compatible with the MMIO
> prototype.
>
> Adjust the trap handlers to use that new function, and provide shims to
> implement the old ioport interface, for now.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
> ---
>  x86/ioport.c | 30 ++++++++++++++++++++++++++----
>  1 file changed, 26 insertions(+), 4 deletions(-)
>
> diff --git a/x86/ioport.c b/x86/ioport.c
> index a8d2bb1a..78f9a863 100644
> --- a/x86/ioport.c
> +++ b/x86/ioport.c
> @@ -3,8 +3,14 @@
>  #include <stdlib.h>
>  #include <stdio.h>
>  
> +static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> +		       u8 is_write, void *ptr)
> +{
> +}
> +
>  static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
>  {
> +	dummy_mmio(vcpu, port, data, size, true, NULL);
>  	return 0;
>  }
>  
> @@ -12,15 +18,23 @@ static struct ioport_operations debug_ops = {
>  	.io_out		= debug_io_out,
>  };
>  
> -static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> +			       u32 len, u8 is_write, void *ptr)
>  {
>  	char ch;
>  
> +	if (!is_write)
> +		return;
> +
>  	ch = ioport__read8(data);
>  
>  	putchar(ch);
> +}
>  
> -	return true;
> +static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +{
> +	seabios_debug_mmio(vcpu, port, data, size, true, NULL);
> +	return 0;
>  }
>  
>  static struct ioport_operations seabios_debug_ops = {
> @@ -29,11 +43,13 @@ static struct ioport_operations seabios_debug_ops = {
>  
>  static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
>  {
> +	dummy_mmio(vcpu, port, data, size, false, NULL);
>  	return true;
>  }
>  
>  static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
>  {
> +	dummy_mmio(vcpu, port, data, size, true, NULL);
>  	return true;
>  }
>  
> @@ -50,13 +66,19 @@ static struct ioport_operations dummy_write_only_ioport_ops = {
>   * The "fast A20 gate"
>   */
>  
> -static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> +			     u8 is_write, void *ptr)
>  {
>  	/*
>  	 * A20 is always enabled.
>  	 */
> -	ioport__write8(data, 0x02);
> +	if (!is_write)
> +		ioport__write8(data, 0x02);
> +}
>  
> +static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +{
> +	ps2_control_mmio(vcpu, port, data, size, false, NULL);
>  	return true;
>  }
>  

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

* Re: [PATCH kvmtool v2 08/22] x86/ioport: Refactor trap handlers
@ 2021-03-09 11:49     ` Alexandru Elisei
  0 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 11:49 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Hi Andre,

Regarding the naming of the functions, these are real ioport emulation functions,
which are executed because a KVM_EXIT_IO exit reason from KVM_RUN. Wouldn't naming
the functions something like *_pio or *_io be more appropriate?

Thanks,

Alex

On 2/25/21 12:59 AM, Andre Przywara wrote:
> With the planned retirement of the special ioport emulation code, we
> need to provide emulation functions compatible with the MMIO
> prototype.
>
> Adjust the trap handlers to use that new function, and provide shims to
> implement the old ioport interface, for now.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
> ---
>  x86/ioport.c | 30 ++++++++++++++++++++++++++----
>  1 file changed, 26 insertions(+), 4 deletions(-)
>
> diff --git a/x86/ioport.c b/x86/ioport.c
> index a8d2bb1a..78f9a863 100644
> --- a/x86/ioport.c
> +++ b/x86/ioport.c
> @@ -3,8 +3,14 @@
>  #include <stdlib.h>
>  #include <stdio.h>
>  
> +static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> +		       u8 is_write, void *ptr)
> +{
> +}
> +
>  static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
>  {
> +	dummy_mmio(vcpu, port, data, size, true, NULL);
>  	return 0;
>  }
>  
> @@ -12,15 +18,23 @@ static struct ioport_operations debug_ops = {
>  	.io_out		= debug_io_out,
>  };
>  
> -static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> +			       u32 len, u8 is_write, void *ptr)
>  {
>  	char ch;
>  
> +	if (!is_write)
> +		return;
> +
>  	ch = ioport__read8(data);
>  
>  	putchar(ch);
> +}
>  
> -	return true;
> +static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +{
> +	seabios_debug_mmio(vcpu, port, data, size, true, NULL);
> +	return 0;
>  }
>  
>  static struct ioport_operations seabios_debug_ops = {
> @@ -29,11 +43,13 @@ static struct ioport_operations seabios_debug_ops = {
>  
>  static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
>  {
> +	dummy_mmio(vcpu, port, data, size, false, NULL);
>  	return true;
>  }
>  
>  static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
>  {
> +	dummy_mmio(vcpu, port, data, size, true, NULL);
>  	return true;
>  }
>  
> @@ -50,13 +66,19 @@ static struct ioport_operations dummy_write_only_ioport_ops = {
>   * The "fast A20 gate"
>   */
>  
> -static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> +			     u8 is_write, void *ptr)
>  {
>  	/*
>  	 * A20 is always enabled.
>  	 */
> -	ioport__write8(data, 0x02);
> +	if (!is_write)
> +		ioport__write8(data, 0x02);
> +}
>  
> +static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +{
> +	ps2_control_mmio(vcpu, port, data, size, false, NULL);
>  	return true;
>  }
>  
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 09/22] x86/ioport: Switch to new trap handlers
  2021-02-25  0:59   ` Andre Przywara
@ 2021-03-09 12:09     ` Alexandru Elisei
  -1 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 12:09 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: kvm, kvmarm, Marc Zyngier, Sami Mujawar

Hi Andre,

On 2/25/21 12:59 AM, Andre Przywara wrote:
> Now that the x86 I/O ports have trap handlers adhering to the MMIO fault
> handler prototype, let's switch over to the joint registration routine.
>
> This allows us to get rid of the ioport shim routines.
>
> Since the debug output was done in ioport.c, we would lose this
> functionality when moving over to the MMIO handlers. So bring this back
> here explicitly, by introducing debug_mmio().
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  x86/ioport.c | 102 +++++++++++++++++++--------------------------------
>  1 file changed, 37 insertions(+), 65 deletions(-)
>
> diff --git a/x86/ioport.c b/x86/ioport.c
> index 78f9a863..9fcbb6c9 100644
> --- a/x86/ioport.c
> +++ b/x86/ioport.c
> @@ -3,21 +3,35 @@
>  #include <stdlib.h>
>  #include <stdio.h>
>  
> -static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> +static void debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
>  		       u8 is_write, void *ptr)

Since the function is about ioports (it even checks cfg.ioport_debug), shouldn't
something like debug_io/debug_pio/debug_ioport/<something else ioport related> be
more appropriate?

Otherwise looks good: the only emulation callback that could fail was
debug_ops->debug_io_out, which triggered a print if cfg.ioport_debug was set, and
the callback is replaced by debug_mmio. With the name change:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

>  {
> +	if (!vcpu->kvm->cfg.ioport_debug)
> +		return;
> +
> +	fprintf(stderr, "debug port %s from VCPU%lu: port=0x%lx, size=%u",
> +		is_write ? "write" : "read", vcpu->cpu_id,
> +		(unsigned long)addr, len);
> +	if (is_write) {
> +		u32 value;
> +
> +		switch (len) {
> +		case 1: value = ioport__read8(data); break;
> +		case 2: value = ioport__read16((u16*)data); break;
> +		case 4: value = ioport__read32((u32*)data); break;
> +		default: value = 0; break;
> +		}
> +		fprintf(stderr, ", data: 0x%x\n", value);
> +	} else {
> +		fprintf(stderr, "\n");
> +	}
>  }
>  
> -static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> +		       u8 is_write, void *ptr)
>  {
> -	dummy_mmio(vcpu, port, data, size, true, NULL);
> -	return 0;
>  }
>  
> -static struct ioport_operations debug_ops = {
> -	.io_out		= debug_io_out,
> -};
> -
>  static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
>  			       u32 len, u8 is_write, void *ptr)
>  {
> @@ -31,37 +45,6 @@ static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
>  	putchar(ch);
>  }
>  
> -static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	seabios_debug_mmio(vcpu, port, data, size, true, NULL);
> -	return 0;
> -}
> -
> -static struct ioport_operations seabios_debug_ops = {
> -	.io_out		= seabios_debug_io_out,
> -};
> -
> -static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	dummy_mmio(vcpu, port, data, size, false, NULL);
> -	return true;
> -}
> -
> -static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	dummy_mmio(vcpu, port, data, size, true, NULL);
> -	return true;
> -}
> -
> -static struct ioport_operations dummy_read_write_ioport_ops = {
> -	.io_in		= dummy_io_in,
> -	.io_out		= dummy_io_out,
> -};
> -
> -static struct ioport_operations dummy_write_only_ioport_ops = {
> -	.io_out		= dummy_io_out,
> -};
> -
>  /*
>   * The "fast A20 gate"
>   */
> @@ -76,17 +59,6 @@ static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
>  		ioport__write8(data, 0x02);
>  }
>  
> -static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	ps2_control_mmio(vcpu, port, data, size, false, NULL);
> -	return true;
> -}
> -
> -static struct ioport_operations ps2_control_a_ops = {
> -	.io_in		= ps2_control_a_io_in,
> -	.io_out		= dummy_io_out,
> -};
> -
>  void ioport__map_irq(u8 *irq)
>  {
>  }
> @@ -98,75 +70,75 @@ static int ioport__setup_arch(struct kvm *kvm)
>  	/* Legacy ioport setup */
>  
>  	/* 0000 - 001F - DMA1 controller */
> -	r = ioport__register(kvm, 0x0000, &dummy_read_write_ioport_ops, 32, NULL);
> +	r = kvm__register_pio(kvm, 0x0000, 32, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* 0x0020 - 0x003F - 8259A PIC 1 */
> -	r = ioport__register(kvm, 0x0020, &dummy_read_write_ioport_ops, 2, NULL);
> +	r = kvm__register_pio(kvm, 0x0020, 2, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
> -	r = ioport__register(kvm, 0x0040, &dummy_read_write_ioport_ops, 4, NULL);
> +	r = kvm__register_pio(kvm, 0x0040, 4, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* 0092 - PS/2 system control port A */
> -	r = ioport__register(kvm, 0x0092, &ps2_control_a_ops, 1, NULL);
> +	r = kvm__register_pio(kvm, 0x0092, 1, ps2_control_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* 0x00A0 - 0x00AF - 8259A PIC 2 */
> -	r = ioport__register(kvm, 0x00A0, &dummy_read_write_ioport_ops, 2, NULL);
> +	r = kvm__register_pio(kvm, 0x00A0, 2, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* 00C0 - 001F - DMA2 controller */
> -	r = ioport__register(kvm, 0x00C0, &dummy_read_write_ioport_ops, 32, NULL);
> +	r = kvm__register_pio(kvm, 0x00c0, 32, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* PORT 00E0-00EF are 'motherboard specific' so we use them for our
>  	   internal debugging purposes.  */
> -	r = ioport__register(kvm, IOPORT_DBG, &debug_ops, 1, NULL);
> +	r = kvm__register_pio(kvm, IOPORT_DBG, 1, debug_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* PORT 00ED - DUMMY PORT FOR DELAY??? */
> -	r = ioport__register(kvm, 0x00ED, &dummy_write_only_ioport_ops, 1, NULL);
> +	r = kvm__register_pio(kvm, 0x00ed, 1, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* 0x00F0 - 0x00FF - Math co-processor */
> -	r = ioport__register(kvm, 0x00F0, &dummy_write_only_ioport_ops, 2, NULL);
> +	r = kvm__register_pio(kvm, 0x00f0, 2, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* PORT 0278-027A - PARALLEL PRINTER PORT (usually LPT1, sometimes LPT2) */
> -	r = ioport__register(kvm, 0x0278, &dummy_read_write_ioport_ops, 3, NULL);
> +	r = kvm__register_pio(kvm, 0x0278, 3, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* PORT 0378-037A - PARALLEL PRINTER PORT (usually LPT2, sometimes LPT3) */
> -	r = ioport__register(kvm, 0x0378, &dummy_read_write_ioport_ops, 3, NULL);
> +	r = kvm__register_pio(kvm, 0x0378, 3, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
> -	r = ioport__register(kvm, 0x03D4, &dummy_read_write_ioport_ops, 1, NULL);
> +	r = kvm__register_pio(kvm, 0x03d4, 1, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
> -	r = ioport__register(kvm, 0x03D5, &dummy_write_only_ioport_ops, 1, NULL);
> +	r = kvm__register_pio(kvm, 0x03d5, 1, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
> -	r = ioport__register(kvm, 0x402, &seabios_debug_ops, 1, NULL);
> +	r = kvm__register_pio(kvm, 0x0402, 1, seabios_debug_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* 0510 - QEMU BIOS configuration register */
> -	r = ioport__register(kvm, 0x510, &dummy_read_write_ioport_ops, 2, NULL);
> +	r = kvm__register_pio(kvm, 0x0510, 2, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  

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

* Re: [PATCH kvmtool v2 09/22] x86/ioport: Switch to new trap handlers
@ 2021-03-09 12:09     ` Alexandru Elisei
  0 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 12:09 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Hi Andre,

On 2/25/21 12:59 AM, Andre Przywara wrote:
> Now that the x86 I/O ports have trap handlers adhering to the MMIO fault
> handler prototype, let's switch over to the joint registration routine.
>
> This allows us to get rid of the ioport shim routines.
>
> Since the debug output was done in ioport.c, we would lose this
> functionality when moving over to the MMIO handlers. So bring this back
> here explicitly, by introducing debug_mmio().
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  x86/ioport.c | 102 +++++++++++++++++++--------------------------------
>  1 file changed, 37 insertions(+), 65 deletions(-)
>
> diff --git a/x86/ioport.c b/x86/ioport.c
> index 78f9a863..9fcbb6c9 100644
> --- a/x86/ioport.c
> +++ b/x86/ioport.c
> @@ -3,21 +3,35 @@
>  #include <stdlib.h>
>  #include <stdio.h>
>  
> -static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> +static void debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
>  		       u8 is_write, void *ptr)

Since the function is about ioports (it even checks cfg.ioport_debug), shouldn't
something like debug_io/debug_pio/debug_ioport/<something else ioport related> be
more appropriate?

Otherwise looks good: the only emulation callback that could fail was
debug_ops->debug_io_out, which triggered a print if cfg.ioport_debug was set, and
the callback is replaced by debug_mmio. With the name change:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

>  {
> +	if (!vcpu->kvm->cfg.ioport_debug)
> +		return;
> +
> +	fprintf(stderr, "debug port %s from VCPU%lu: port=0x%lx, size=%u",
> +		is_write ? "write" : "read", vcpu->cpu_id,
> +		(unsigned long)addr, len);
> +	if (is_write) {
> +		u32 value;
> +
> +		switch (len) {
> +		case 1: value = ioport__read8(data); break;
> +		case 2: value = ioport__read16((u16*)data); break;
> +		case 4: value = ioport__read32((u32*)data); break;
> +		default: value = 0; break;
> +		}
> +		fprintf(stderr, ", data: 0x%x\n", value);
> +	} else {
> +		fprintf(stderr, "\n");
> +	}
>  }
>  
> -static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> +		       u8 is_write, void *ptr)
>  {
> -	dummy_mmio(vcpu, port, data, size, true, NULL);
> -	return 0;
>  }
>  
> -static struct ioport_operations debug_ops = {
> -	.io_out		= debug_io_out,
> -};
> -
>  static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
>  			       u32 len, u8 is_write, void *ptr)
>  {
> @@ -31,37 +45,6 @@ static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
>  	putchar(ch);
>  }
>  
> -static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	seabios_debug_mmio(vcpu, port, data, size, true, NULL);
> -	return 0;
> -}
> -
> -static struct ioport_operations seabios_debug_ops = {
> -	.io_out		= seabios_debug_io_out,
> -};
> -
> -static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	dummy_mmio(vcpu, port, data, size, false, NULL);
> -	return true;
> -}
> -
> -static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	dummy_mmio(vcpu, port, data, size, true, NULL);
> -	return true;
> -}
> -
> -static struct ioport_operations dummy_read_write_ioport_ops = {
> -	.io_in		= dummy_io_in,
> -	.io_out		= dummy_io_out,
> -};
> -
> -static struct ioport_operations dummy_write_only_ioport_ops = {
> -	.io_out		= dummy_io_out,
> -};
> -
>  /*
>   * The "fast A20 gate"
>   */
> @@ -76,17 +59,6 @@ static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
>  		ioport__write8(data, 0x02);
>  }
>  
> -static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	ps2_control_mmio(vcpu, port, data, size, false, NULL);
> -	return true;
> -}
> -
> -static struct ioport_operations ps2_control_a_ops = {
> -	.io_in		= ps2_control_a_io_in,
> -	.io_out		= dummy_io_out,
> -};
> -
>  void ioport__map_irq(u8 *irq)
>  {
>  }
> @@ -98,75 +70,75 @@ static int ioport__setup_arch(struct kvm *kvm)
>  	/* Legacy ioport setup */
>  
>  	/* 0000 - 001F - DMA1 controller */
> -	r = ioport__register(kvm, 0x0000, &dummy_read_write_ioport_ops, 32, NULL);
> +	r = kvm__register_pio(kvm, 0x0000, 32, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* 0x0020 - 0x003F - 8259A PIC 1 */
> -	r = ioport__register(kvm, 0x0020, &dummy_read_write_ioport_ops, 2, NULL);
> +	r = kvm__register_pio(kvm, 0x0020, 2, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
> -	r = ioport__register(kvm, 0x0040, &dummy_read_write_ioport_ops, 4, NULL);
> +	r = kvm__register_pio(kvm, 0x0040, 4, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* 0092 - PS/2 system control port A */
> -	r = ioport__register(kvm, 0x0092, &ps2_control_a_ops, 1, NULL);
> +	r = kvm__register_pio(kvm, 0x0092, 1, ps2_control_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* 0x00A0 - 0x00AF - 8259A PIC 2 */
> -	r = ioport__register(kvm, 0x00A0, &dummy_read_write_ioport_ops, 2, NULL);
> +	r = kvm__register_pio(kvm, 0x00A0, 2, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* 00C0 - 001F - DMA2 controller */
> -	r = ioport__register(kvm, 0x00C0, &dummy_read_write_ioport_ops, 32, NULL);
> +	r = kvm__register_pio(kvm, 0x00c0, 32, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* PORT 00E0-00EF are 'motherboard specific' so we use them for our
>  	   internal debugging purposes.  */
> -	r = ioport__register(kvm, IOPORT_DBG, &debug_ops, 1, NULL);
> +	r = kvm__register_pio(kvm, IOPORT_DBG, 1, debug_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* PORT 00ED - DUMMY PORT FOR DELAY??? */
> -	r = ioport__register(kvm, 0x00ED, &dummy_write_only_ioport_ops, 1, NULL);
> +	r = kvm__register_pio(kvm, 0x00ed, 1, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* 0x00F0 - 0x00FF - Math co-processor */
> -	r = ioport__register(kvm, 0x00F0, &dummy_write_only_ioport_ops, 2, NULL);
> +	r = kvm__register_pio(kvm, 0x00f0, 2, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* PORT 0278-027A - PARALLEL PRINTER PORT (usually LPT1, sometimes LPT2) */
> -	r = ioport__register(kvm, 0x0278, &dummy_read_write_ioport_ops, 3, NULL);
> +	r = kvm__register_pio(kvm, 0x0278, 3, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* PORT 0378-037A - PARALLEL PRINTER PORT (usually LPT2, sometimes LPT3) */
> -	r = ioport__register(kvm, 0x0378, &dummy_read_write_ioport_ops, 3, NULL);
> +	r = kvm__register_pio(kvm, 0x0378, 3, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
> -	r = ioport__register(kvm, 0x03D4, &dummy_read_write_ioport_ops, 1, NULL);
> +	r = kvm__register_pio(kvm, 0x03d4, 1, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
> -	r = ioport__register(kvm, 0x03D5, &dummy_write_only_ioport_ops, 1, NULL);
> +	r = kvm__register_pio(kvm, 0x03d5, 1, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
> -	r = ioport__register(kvm, 0x402, &seabios_debug_ops, 1, NULL);
> +	r = kvm__register_pio(kvm, 0x0402, 1, seabios_debug_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
>  	/* 0510 - QEMU BIOS configuration register */
> -	r = ioport__register(kvm, 0x510, &dummy_read_write_ioport_ops, 2, NULL);
> +	r = kvm__register_pio(kvm, 0x0510, 2, dummy_mmio, NULL);
>  	if (r < 0)
>  		return r;
>  
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 15/22] vfio: Refactor ioport trap handler
  2021-02-25  0:59   ` Andre Przywara
@ 2021-03-09 14:21     ` Alexandru Elisei
  -1 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 14:21 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: kvm, kvmarm, Marc Zyngier, Sami Mujawar

Hi Andre,

On 2/25/21 12:59 AM, Andre Przywara wrote:
> With the planned retirement of the special ioport emulation code, we
> need to provide an emulation function compatible with the MMIO prototype.
>
> Adjust the I/O port trap handler to use that new function, and provide
> shims to implement the old ioport interface, for now.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  vfio/core.c | 51 ++++++++++++++++++++++++++++++++++++---------------
>  1 file changed, 36 insertions(+), 15 deletions(-)
>
> diff --git a/vfio/core.c b/vfio/core.c
> index 0b45e78b..ddd3c2c7 100644
> --- a/vfio/core.c
> +++ b/vfio/core.c
> @@ -81,15 +81,12 @@ out_free_buf:
>  	return ret;
>  }
>  
> -static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
> -			   u16 port, void *data, int len)
> +static bool _vfio_ioport_in(struct vfio_region *region, u32 offset,
> +			    void *data, int len)
>  {
> -	u32 val;
> -	ssize_t nr;
> -	struct vfio_region *region = ioport->priv;
>  	struct vfio_device *vdev = region->vdev;
> -
> -	u32 offset = port - region->port_base;
> +	ssize_t nr;
> +	u32 val;
>  
>  	if (!(region->info.flags & VFIO_REGION_INFO_FLAG_READ))
>  		return false;
> @@ -97,7 +94,7 @@ static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
>  	nr = pread(vdev->fd, &val, len, region->info.offset + offset);
>  	if (nr != len) {
>  		vfio_dev_err(vdev, "could not read %d bytes from I/O port 0x%x\n",
> -			     len, port);
> +			     len, offset + region->port_base);
>  		return false;
>  	}
>  
> @@ -118,15 +115,13 @@ static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
>  	return true;
>  }
>  
> -static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
> -			    u16 port, void *data, int len)
> +static bool _vfio_ioport_out(struct vfio_region *region, u32 offset,
> +			     void *data, int len)
>  {
> -	u32 val;
> -	ssize_t nr;
> -	struct vfio_region *region = ioport->priv;
>  	struct vfio_device *vdev = region->vdev;
> +	ssize_t nr;
> +	u32 val;
>  
> -	u32 offset = port - region->port_base;
>  
>  	if (!(region->info.flags & VFIO_REGION_INFO_FLAG_WRITE))
>  		return false;
> @@ -148,11 +143,37 @@ static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
>  	nr = pwrite(vdev->fd, &val, len, region->info.offset + offset);
>  	if (nr != len)
>  		vfio_dev_err(vdev, "could not write %d bytes to I/O port 0x%x",
> -			     len, port);
> +			     len, offset + region->port_base);
>  
>  	return nr == len;
>  }
>  
> +static void vfio_ioport_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> +			     u8 is_write, void *ptr)
> +{
> +	struct vfio_region *region = ptr;
> +	u32 offset = addr - region->port_base;
> +
> +	if (is_write)
> +		_vfio_ioport_out(region, offset, data, len);
> +	else
> +		_vfio_ioport_in(region, offset, data, len);
> +}
> +
> +static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
> +			    u16 port, void *data, int len)
> +{
> +	vfio_ioport_mmio(vcpu, port, data, len, true, ioport->priv);
> +	return true;
> +}
> +
> +static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
> +			   u16 port, void *data, int len)
> +{
> +	vfio_ioport_mmio(vcpu, port, data, len, false, ioport->priv);
> +	return true;
> +}
> +
>  static struct ioport_operations vfio_ioport_ops = {
>  	.io_in	= vfio_ioport_in,
>  	.io_out	= vfio_ioport_out,

The new code looks functionally identical to the old one:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex


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

* Re: [PATCH kvmtool v2 15/22] vfio: Refactor ioport trap handler
@ 2021-03-09 14:21     ` Alexandru Elisei
  0 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 14:21 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Hi Andre,

On 2/25/21 12:59 AM, Andre Przywara wrote:
> With the planned retirement of the special ioport emulation code, we
> need to provide an emulation function compatible with the MMIO prototype.
>
> Adjust the I/O port trap handler to use that new function, and provide
> shims to implement the old ioport interface, for now.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  vfio/core.c | 51 ++++++++++++++++++++++++++++++++++++---------------
>  1 file changed, 36 insertions(+), 15 deletions(-)
>
> diff --git a/vfio/core.c b/vfio/core.c
> index 0b45e78b..ddd3c2c7 100644
> --- a/vfio/core.c
> +++ b/vfio/core.c
> @@ -81,15 +81,12 @@ out_free_buf:
>  	return ret;
>  }
>  
> -static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
> -			   u16 port, void *data, int len)
> +static bool _vfio_ioport_in(struct vfio_region *region, u32 offset,
> +			    void *data, int len)
>  {
> -	u32 val;
> -	ssize_t nr;
> -	struct vfio_region *region = ioport->priv;
>  	struct vfio_device *vdev = region->vdev;
> -
> -	u32 offset = port - region->port_base;
> +	ssize_t nr;
> +	u32 val;
>  
>  	if (!(region->info.flags & VFIO_REGION_INFO_FLAG_READ))
>  		return false;
> @@ -97,7 +94,7 @@ static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
>  	nr = pread(vdev->fd, &val, len, region->info.offset + offset);
>  	if (nr != len) {
>  		vfio_dev_err(vdev, "could not read %d bytes from I/O port 0x%x\n",
> -			     len, port);
> +			     len, offset + region->port_base);
>  		return false;
>  	}
>  
> @@ -118,15 +115,13 @@ static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
>  	return true;
>  }
>  
> -static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
> -			    u16 port, void *data, int len)
> +static bool _vfio_ioport_out(struct vfio_region *region, u32 offset,
> +			     void *data, int len)
>  {
> -	u32 val;
> -	ssize_t nr;
> -	struct vfio_region *region = ioport->priv;
>  	struct vfio_device *vdev = region->vdev;
> +	ssize_t nr;
> +	u32 val;
>  
> -	u32 offset = port - region->port_base;
>  
>  	if (!(region->info.flags & VFIO_REGION_INFO_FLAG_WRITE))
>  		return false;
> @@ -148,11 +143,37 @@ static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
>  	nr = pwrite(vdev->fd, &val, len, region->info.offset + offset);
>  	if (nr != len)
>  		vfio_dev_err(vdev, "could not write %d bytes to I/O port 0x%x",
> -			     len, port);
> +			     len, offset + region->port_base);
>  
>  	return nr == len;
>  }
>  
> +static void vfio_ioport_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> +			     u8 is_write, void *ptr)
> +{
> +	struct vfio_region *region = ptr;
> +	u32 offset = addr - region->port_base;
> +
> +	if (is_write)
> +		_vfio_ioport_out(region, offset, data, len);
> +	else
> +		_vfio_ioport_in(region, offset, data, len);
> +}
> +
> +static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
> +			    u16 port, void *data, int len)
> +{
> +	vfio_ioport_mmio(vcpu, port, data, len, true, ioport->priv);
> +	return true;
> +}
> +
> +static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
> +			   u16 port, void *data, int len)
> +{
> +	vfio_ioport_mmio(vcpu, port, data, len, false, ioport->priv);
> +	return true;
> +}
> +
>  static struct ioport_operations vfio_ioport_ops = {
>  	.io_in	= vfio_ioport_in,
>  	.io_out	= vfio_ioport_out,

The new code looks functionally identical to the old one:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 17/22] virtio: Switch trap handling to use MMIO handler
  2021-02-25  0:59   ` Andre Przywara
@ 2021-03-09 14:43     ` Alexandru Elisei
  -1 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 14:43 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: kvm, kvmarm, Marc Zyngier, Sami Mujawar

Hi Andre,

On 2/25/21 12:59 AM, Andre Przywara wrote:
> With the planned retirement of the special ioport emulation code, we
> need to provide an emulation function compatible with the MMIO prototype.
>
> Adjust the existing MMIO callback routine to automatically determine
> the region this trap came through, and call the existing I/O handlers.
> Register the ioport region using the new registration function.

Looks good to me:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  virtio/pci.c | 46 ++++++++++++++--------------------------------
>  1 file changed, 14 insertions(+), 32 deletions(-)
>
> diff --git a/virtio/pci.c b/virtio/pci.c
> index 6eea6c68..eb91f512 100644
> --- a/virtio/pci.c
> +++ b/virtio/pci.c
> @@ -178,15 +178,6 @@ static bool virtio_pci__data_in(struct kvm_cpu *vcpu, struct virtio_device *vdev
>  	return ret;
>  }
>  
> -static bool virtio_pci__io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	struct virtio_device *vdev = ioport->priv;
> -	struct virtio_pci *vpci = vdev->virtio;
> -	unsigned long offset = port - virtio_pci__port_addr(vpci);
> -
> -	return virtio_pci__data_in(vcpu, vdev, offset, data, size);
> -}
> -
>  static void update_msix_map(struct virtio_pci *vpci,
>  			    struct msix_table *msix_entry, u32 vecnum)
>  {
> @@ -334,20 +325,6 @@ static bool virtio_pci__data_out(struct kvm_cpu *vcpu, struct virtio_device *vde
>  	return ret;
>  }
>  
> -static bool virtio_pci__io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	struct virtio_device *vdev = ioport->priv;
> -	struct virtio_pci *vpci = vdev->virtio;
> -	unsigned long offset = port - virtio_pci__port_addr(vpci);
> -
> -	return virtio_pci__data_out(vcpu, vdev, offset, data, size);
> -}
> -
> -static struct ioport_operations virtio_pci__io_ops = {
> -	.io_in	= virtio_pci__io_in,
> -	.io_out	= virtio_pci__io_out,
> -};
> -
>  static void virtio_pci__msix_mmio_callback(struct kvm_cpu *vcpu,
>  					   u64 addr, u8 *data, u32 len,
>  					   u8 is_write, void *ptr)
> @@ -455,12 +432,19 @@ static void virtio_pci__io_mmio_callback(struct kvm_cpu *vcpu,
>  {
>  	struct virtio_device *vdev = ptr;
>  	struct virtio_pci *vpci = vdev->virtio;
> -	u32 mmio_addr = virtio_pci__mmio_addr(vpci);
> +	u32 ioport_addr = virtio_pci__port_addr(vpci);
> +	u32 base_addr;
> +
> +	if (addr >= ioport_addr &&
> +	    addr < ioport_addr + pci__bar_size(&vpci->pci_hdr, 0))
> +		base_addr = ioport_addr;
> +	else
> +		base_addr = virtio_pci__mmio_addr(vpci);
>  
>  	if (!is_write)
> -		virtio_pci__data_in(vcpu, vdev, addr - mmio_addr, data, len);
> +		virtio_pci__data_in(vcpu, vdev, addr - base_addr, data, len);
>  	else
> -		virtio_pci__data_out(vcpu, vdev, addr - mmio_addr, data, len);
> +		virtio_pci__data_out(vcpu, vdev, addr - base_addr, data, len);
>  }
>  
>  static int virtio_pci__bar_activate(struct kvm *kvm,
> @@ -478,10 +462,8 @@ static int virtio_pci__bar_activate(struct kvm *kvm,
>  
>  	switch (bar_num) {
>  	case 0:
> -		r = ioport__register(kvm, bar_addr, &virtio_pci__io_ops,
> -				     bar_size, vdev);
> -		if (r > 0)
> -			r = 0;
> +		r = kvm__register_pio(kvm, bar_addr, bar_size,
> +				      virtio_pci__io_mmio_callback, vdev);
>  		break;
>  	case 1:
>  		r =  kvm__register_mmio(kvm, bar_addr, bar_size, false,
> @@ -510,7 +492,7 @@ static int virtio_pci__bar_deactivate(struct kvm *kvm,
>  
>  	switch (bar_num) {
>  	case 0:
> -		r = ioport__unregister(kvm, bar_addr);
> +		r = kvm__deregister_pio(kvm, bar_addr);
>  		break;
>  	case 1:
>  	case 2:
> @@ -625,7 +607,7 @@ int virtio_pci__exit(struct kvm *kvm, struct virtio_device *vdev)
>  	virtio_pci__reset(kvm, vdev);
>  	kvm__deregister_mmio(kvm, virtio_pci__mmio_addr(vpci));
>  	kvm__deregister_mmio(kvm, virtio_pci__msix_io_addr(vpci));
> -	ioport__unregister(kvm, virtio_pci__port_addr(vpci));
> +	kvm__deregister_pio(kvm, virtio_pci__port_addr(vpci));
>  
>  	return 0;
>  }

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

* Re: [PATCH kvmtool v2 17/22] virtio: Switch trap handling to use MMIO handler
@ 2021-03-09 14:43     ` Alexandru Elisei
  0 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 14:43 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Hi Andre,

On 2/25/21 12:59 AM, Andre Przywara wrote:
> With the planned retirement of the special ioport emulation code, we
> need to provide an emulation function compatible with the MMIO prototype.
>
> Adjust the existing MMIO callback routine to automatically determine
> the region this trap came through, and call the existing I/O handlers.
> Register the ioport region using the new registration function.

Looks good to me:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  virtio/pci.c | 46 ++++++++++++++--------------------------------
>  1 file changed, 14 insertions(+), 32 deletions(-)
>
> diff --git a/virtio/pci.c b/virtio/pci.c
> index 6eea6c68..eb91f512 100644
> --- a/virtio/pci.c
> +++ b/virtio/pci.c
> @@ -178,15 +178,6 @@ static bool virtio_pci__data_in(struct kvm_cpu *vcpu, struct virtio_device *vdev
>  	return ret;
>  }
>  
> -static bool virtio_pci__io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	struct virtio_device *vdev = ioport->priv;
> -	struct virtio_pci *vpci = vdev->virtio;
> -	unsigned long offset = port - virtio_pci__port_addr(vpci);
> -
> -	return virtio_pci__data_in(vcpu, vdev, offset, data, size);
> -}
> -
>  static void update_msix_map(struct virtio_pci *vpci,
>  			    struct msix_table *msix_entry, u32 vecnum)
>  {
> @@ -334,20 +325,6 @@ static bool virtio_pci__data_out(struct kvm_cpu *vcpu, struct virtio_device *vde
>  	return ret;
>  }
>  
> -static bool virtio_pci__io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> -{
> -	struct virtio_device *vdev = ioport->priv;
> -	struct virtio_pci *vpci = vdev->virtio;
> -	unsigned long offset = port - virtio_pci__port_addr(vpci);
> -
> -	return virtio_pci__data_out(vcpu, vdev, offset, data, size);
> -}
> -
> -static struct ioport_operations virtio_pci__io_ops = {
> -	.io_in	= virtio_pci__io_in,
> -	.io_out	= virtio_pci__io_out,
> -};
> -
>  static void virtio_pci__msix_mmio_callback(struct kvm_cpu *vcpu,
>  					   u64 addr, u8 *data, u32 len,
>  					   u8 is_write, void *ptr)
> @@ -455,12 +432,19 @@ static void virtio_pci__io_mmio_callback(struct kvm_cpu *vcpu,
>  {
>  	struct virtio_device *vdev = ptr;
>  	struct virtio_pci *vpci = vdev->virtio;
> -	u32 mmio_addr = virtio_pci__mmio_addr(vpci);
> +	u32 ioport_addr = virtio_pci__port_addr(vpci);
> +	u32 base_addr;
> +
> +	if (addr >= ioport_addr &&
> +	    addr < ioport_addr + pci__bar_size(&vpci->pci_hdr, 0))
> +		base_addr = ioport_addr;
> +	else
> +		base_addr = virtio_pci__mmio_addr(vpci);
>  
>  	if (!is_write)
> -		virtio_pci__data_in(vcpu, vdev, addr - mmio_addr, data, len);
> +		virtio_pci__data_in(vcpu, vdev, addr - base_addr, data, len);
>  	else
> -		virtio_pci__data_out(vcpu, vdev, addr - mmio_addr, data, len);
> +		virtio_pci__data_out(vcpu, vdev, addr - base_addr, data, len);
>  }
>  
>  static int virtio_pci__bar_activate(struct kvm *kvm,
> @@ -478,10 +462,8 @@ static int virtio_pci__bar_activate(struct kvm *kvm,
>  
>  	switch (bar_num) {
>  	case 0:
> -		r = ioport__register(kvm, bar_addr, &virtio_pci__io_ops,
> -				     bar_size, vdev);
> -		if (r > 0)
> -			r = 0;
> +		r = kvm__register_pio(kvm, bar_addr, bar_size,
> +				      virtio_pci__io_mmio_callback, vdev);
>  		break;
>  	case 1:
>  		r =  kvm__register_mmio(kvm, bar_addr, bar_size, false,
> @@ -510,7 +492,7 @@ static int virtio_pci__bar_deactivate(struct kvm *kvm,
>  
>  	switch (bar_num) {
>  	case 0:
> -		r = ioport__unregister(kvm, bar_addr);
> +		r = kvm__deregister_pio(kvm, bar_addr);
>  		break;
>  	case 1:
>  	case 2:
> @@ -625,7 +607,7 @@ int virtio_pci__exit(struct kvm *kvm, struct virtio_device *vdev)
>  	virtio_pci__reset(kvm, vdev);
>  	kvm__deregister_mmio(kvm, virtio_pci__mmio_addr(vpci));
>  	kvm__deregister_mmio(kvm, virtio_pci__msix_io_addr(vpci));
> -	ioport__unregister(kvm, virtio_pci__port_addr(vpci));
> +	kvm__deregister_pio(kvm, virtio_pci__port_addr(vpci));
>  
>  	return 0;
>  }
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 19/22] Remove ioport specific routines
  2021-02-25  0:59   ` Andre Przywara
@ 2021-03-09 15:13     ` Alexandru Elisei
  -1 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 15:13 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: kvm, kvmarm, Marc Zyngier, Sami Mujawar

Hi Andre,

On 2/25/21 12:59 AM, Andre Przywara wrote:
> Now that all users of the dedicated ioport trap handler interface are
> gone, we can retire the code associated with it.
>
> This removes ioport.c and ioport.h, along with removing prototypes from
> other header files.
>
> This also transfers the responsibility for port I/O trap handling
> entirely into the new routine in mmio.c.

Looks good, and everything compiles on arm64 and x86-64:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  Makefile             |   1 -
>  include/kvm/ioport.h |  27 ------
>  include/kvm/kvm.h    |   2 -
>  ioport.c             | 195 -------------------------------------------
>  mmio.c               |   2 +-
>  5 files changed, 1 insertion(+), 226 deletions(-)
>  delete mode 100644 ioport.c
>
> diff --git a/Makefile b/Makefile
> index 35bb1182..94ff5da6 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -56,7 +56,6 @@ OBJS	+= framebuffer.o
>  OBJS	+= guest_compat.o
>  OBJS	+= hw/rtc.o
>  OBJS	+= hw/serial.o
> -OBJS	+= ioport.o
>  OBJS	+= irq.o
>  OBJS	+= kvm-cpu.o
>  OBJS	+= kvm.o
> diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
> index a61038e2..b6f579cb 100644
> --- a/include/kvm/ioport.h
> +++ b/include/kvm/ioport.h
> @@ -1,13 +1,8 @@
>  #ifndef KVM__IOPORT_H
>  #define KVM__IOPORT_H
>  
> -#include "kvm/devices.h"
>  #include "kvm/kvm-cpu.h"
> -#include "kvm/rbtree-interval.h"
> -#include "kvm/fdt.h"
>  
> -#include <stdbool.h>
> -#include <limits.h>
>  #include <asm/types.h>
>  #include <linux/types.h>
>  #include <linux/byteorder.h>
> @@ -15,30 +10,8 @@
>  /* some ports we reserve for own use */
>  #define IOPORT_DBG			0xe0
>  
> -struct kvm;
> -
> -struct ioport {
> -	struct rb_int_node		node;
> -	struct ioport_operations	*ops;
> -	void				*priv;
> -	struct device_header		dev_hdr;
> -	u32				refcount;
> -	bool				remove;
> -};
> -
> -struct ioport_operations {
> -	bool (*io_in)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size);
> -	bool (*io_out)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size);
> -};
> -
>  void ioport__map_irq(u8 *irq);
>  
> -int __must_check ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops,
> -				  int count, void *param);
> -int ioport__unregister(struct kvm *kvm, u16 port);
> -int ioport__init(struct kvm *kvm);
> -int ioport__exit(struct kvm *kvm);
> -
>  static inline u8 ioport__read8(u8 *data)
>  {
>  	return *data;
> diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
> index 306b258a..6c28afa3 100644
> --- a/include/kvm/kvm.h
> +++ b/include/kvm/kvm.h
> @@ -126,8 +126,6 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
>  void kvm__irq_trigger(struct kvm *kvm, int irq);
>  bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count);
>  bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write);
> -bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
> -		      int direction, int size, u32 count);
>  int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr);
>  int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr,
>  		      enum kvm_mem_type type);
> diff --git a/ioport.c b/ioport.c
> deleted file mode 100644
> index ce29e7e7..00000000
> --- a/ioport.c
> +++ /dev/null
> @@ -1,195 +0,0 @@
> -#include "kvm/ioport.h"
> -
> -#include "kvm/kvm.h"
> -#include "kvm/util.h"
> -#include "kvm/rbtree-interval.h"
> -#include "kvm/mutex.h"
> -
> -#include <linux/kvm.h>	/* for KVM_EXIT_* */
> -#include <linux/types.h>
> -
> -#include <stdbool.h>
> -#include <limits.h>
> -#include <stdlib.h>
> -#include <stdio.h>
> -
> -#define ioport_node(n) rb_entry(n, struct ioport, node)
> -
> -static DEFINE_MUTEX(ioport_lock);
> -
> -static struct rb_root		ioport_tree = RB_ROOT;
> -
> -static struct ioport *ioport_search(struct rb_root *root, u64 addr)
> -{
> -	struct rb_int_node *node;
> -
> -	node = rb_int_search_single(root, addr);
> -	if (node == NULL)
> -		return NULL;
> -
> -	return ioport_node(node);
> -}
> -
> -static int ioport_insert(struct rb_root *root, struct ioport *data)
> -{
> -	return rb_int_insert(root, &data->node);
> -}
> -
> -static void ioport_remove(struct rb_root *root, struct ioport *data)
> -{
> -	rb_int_erase(root, &data->node);
> -}
> -
> -static struct ioport *ioport_get(struct rb_root *root, u64 addr)
> -{
> -	struct ioport *ioport;
> -
> -	mutex_lock(&ioport_lock);
> -	ioport = ioport_search(root, addr);
> -	if (ioport)
> -		ioport->refcount++;
> -	mutex_unlock(&ioport_lock);
> -
> -	return ioport;
> -}
> -
> -/* Called with ioport_lock held. */
> -static void ioport_unregister(struct rb_root *root, struct ioport *data)
> -{
> -	ioport_remove(root, data);
> -	free(data);
> -}
> -
> -static void ioport_put(struct rb_root *root, struct ioport *data)
> -{
> -	mutex_lock(&ioport_lock);
> -	data->refcount--;
> -	if (data->remove && data->refcount == 0)
> -		ioport_unregister(root, data);
> -	mutex_unlock(&ioport_lock);
> -}
> -
> -int ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops, int count, void *param)
> -{
> -	struct ioport *entry;
> -	int r;
> -
> -	entry = malloc(sizeof(*entry));
> -	if (entry == NULL)
> -		return -ENOMEM;
> -
> -	*entry = (struct ioport) {
> -		.node		= RB_INT_INIT(port, port + count),
> -		.ops		= ops,
> -		.priv		= param,
> -		/*
> -		 * Start from 0 because ioport__unregister() doesn't decrement
> -		 * the reference count.
> -		 */
> -		.refcount	= 0,
> -		.remove		= false,
> -	};
> -
> -	mutex_lock(&ioport_lock);
> -	r = ioport_insert(&ioport_tree, entry);
> -	if (r < 0)
> -		goto out_free;
> -	mutex_unlock(&ioport_lock);
> -
> -	return port;
> -
> -out_free:
> -	free(entry);
> -	mutex_unlock(&ioport_lock);
> -	return r;
> -}
> -
> -int ioport__unregister(struct kvm *kvm, u16 port)
> -{
> -	struct ioport *entry;
> -
> -	mutex_lock(&ioport_lock);
> -	entry = ioport_search(&ioport_tree, port);
> -	if (!entry) {
> -		mutex_unlock(&ioport_lock);
> -		return -ENOENT;
> -	}
> -	/* The same reasoning from kvm__deregister_mmio() applies. */
> -	if (entry->refcount == 0)
> -		ioport_unregister(&ioport_tree, entry);
> -	else
> -		entry->remove = true;
> -	mutex_unlock(&ioport_lock);
> -
> -	return 0;
> -}
> -
> -static void ioport__unregister_all(void)
> -{
> -	struct ioport *entry;
> -	struct rb_node *rb;
> -	struct rb_int_node *rb_node;
> -
> -	rb = rb_first(&ioport_tree);
> -	while (rb) {
> -		rb_node = rb_int(rb);
> -		entry = ioport_node(rb_node);
> -		ioport_unregister(&ioport_tree, entry);
> -		rb = rb_first(&ioport_tree);
> -	}
> -}
> -
> -static const char *to_direction(int direction)
> -{
> -	if (direction == KVM_EXIT_IO_IN)
> -		return "IN";
> -	else
> -		return "OUT";
> -}
> -
> -static void ioport_error(u16 port, void *data, int direction, int size, u32 count)
> -{
> -	fprintf(stderr, "IO error: %s port=%x, size=%d, count=%u\n", to_direction(direction), port, size, count);
> -}
> -
> -bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count)
> -{
> -	struct ioport_operations *ops;
> -	bool ret = false;
> -	struct ioport *entry;
> -	void *ptr = data;
> -	struct kvm *kvm = vcpu->kvm;
> -
> -	entry = ioport_get(&ioport_tree, port);
> -	if (!entry)
> -		return kvm__emulate_pio(vcpu, port, data, direction,
> -					size, count);
> -
> -	ops	= entry->ops;
> -
> -	while (count--) {
> -		if (direction == KVM_EXIT_IO_IN && ops->io_in)
> -				ret = ops->io_in(entry, vcpu, port, ptr, size);
> -		else if (direction == KVM_EXIT_IO_OUT && ops->io_out)
> -				ret = ops->io_out(entry, vcpu, port, ptr, size);
> -
> -		ptr += size;
> -	}
> -
> -	ioport_put(&ioport_tree, entry);
> -
> -	if (ret)
> -		return true;
> -
> -	if (kvm->cfg.ioport_debug)
> -		ioport_error(port, data, direction, size, count);
> -
> -	return !kvm->cfg.ioport_debug;
> -}
> -
> -int ioport__exit(struct kvm *kvm)
> -{
> -	ioport__unregister_all();
> -	return 0;
> -}
> -dev_base_exit(ioport__exit);
> diff --git a/mmio.c b/mmio.c
> index 75de04ad..9f731dcf 100644
> --- a/mmio.c
> +++ b/mmio.c
> @@ -212,7 +212,7 @@ out:
>  	return true;
>  }
>  
> -bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
> +bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data,
>  		     int direction, int size, u32 count)
>  {
>  	struct mmio_mapping *mmio;

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

* Re: [PATCH kvmtool v2 19/22] Remove ioport specific routines
@ 2021-03-09 15:13     ` Alexandru Elisei
  0 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 15:13 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Hi Andre,

On 2/25/21 12:59 AM, Andre Przywara wrote:
> Now that all users of the dedicated ioport trap handler interface are
> gone, we can retire the code associated with it.
>
> This removes ioport.c and ioport.h, along with removing prototypes from
> other header files.
>
> This also transfers the responsibility for port I/O trap handling
> entirely into the new routine in mmio.c.

Looks good, and everything compiles on arm64 and x86-64:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  Makefile             |   1 -
>  include/kvm/ioport.h |  27 ------
>  include/kvm/kvm.h    |   2 -
>  ioport.c             | 195 -------------------------------------------
>  mmio.c               |   2 +-
>  5 files changed, 1 insertion(+), 226 deletions(-)
>  delete mode 100644 ioport.c
>
> diff --git a/Makefile b/Makefile
> index 35bb1182..94ff5da6 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -56,7 +56,6 @@ OBJS	+= framebuffer.o
>  OBJS	+= guest_compat.o
>  OBJS	+= hw/rtc.o
>  OBJS	+= hw/serial.o
> -OBJS	+= ioport.o
>  OBJS	+= irq.o
>  OBJS	+= kvm-cpu.o
>  OBJS	+= kvm.o
> diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
> index a61038e2..b6f579cb 100644
> --- a/include/kvm/ioport.h
> +++ b/include/kvm/ioport.h
> @@ -1,13 +1,8 @@
>  #ifndef KVM__IOPORT_H
>  #define KVM__IOPORT_H
>  
> -#include "kvm/devices.h"
>  #include "kvm/kvm-cpu.h"
> -#include "kvm/rbtree-interval.h"
> -#include "kvm/fdt.h"
>  
> -#include <stdbool.h>
> -#include <limits.h>
>  #include <asm/types.h>
>  #include <linux/types.h>
>  #include <linux/byteorder.h>
> @@ -15,30 +10,8 @@
>  /* some ports we reserve for own use */
>  #define IOPORT_DBG			0xe0
>  
> -struct kvm;
> -
> -struct ioport {
> -	struct rb_int_node		node;
> -	struct ioport_operations	*ops;
> -	void				*priv;
> -	struct device_header		dev_hdr;
> -	u32				refcount;
> -	bool				remove;
> -};
> -
> -struct ioport_operations {
> -	bool (*io_in)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size);
> -	bool (*io_out)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size);
> -};
> -
>  void ioport__map_irq(u8 *irq);
>  
> -int __must_check ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops,
> -				  int count, void *param);
> -int ioport__unregister(struct kvm *kvm, u16 port);
> -int ioport__init(struct kvm *kvm);
> -int ioport__exit(struct kvm *kvm);
> -
>  static inline u8 ioport__read8(u8 *data)
>  {
>  	return *data;
> diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
> index 306b258a..6c28afa3 100644
> --- a/include/kvm/kvm.h
> +++ b/include/kvm/kvm.h
> @@ -126,8 +126,6 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
>  void kvm__irq_trigger(struct kvm *kvm, int irq);
>  bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count);
>  bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write);
> -bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
> -		      int direction, int size, u32 count);
>  int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr);
>  int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr,
>  		      enum kvm_mem_type type);
> diff --git a/ioport.c b/ioport.c
> deleted file mode 100644
> index ce29e7e7..00000000
> --- a/ioport.c
> +++ /dev/null
> @@ -1,195 +0,0 @@
> -#include "kvm/ioport.h"
> -
> -#include "kvm/kvm.h"
> -#include "kvm/util.h"
> -#include "kvm/rbtree-interval.h"
> -#include "kvm/mutex.h"
> -
> -#include <linux/kvm.h>	/* for KVM_EXIT_* */
> -#include <linux/types.h>
> -
> -#include <stdbool.h>
> -#include <limits.h>
> -#include <stdlib.h>
> -#include <stdio.h>
> -
> -#define ioport_node(n) rb_entry(n, struct ioport, node)
> -
> -static DEFINE_MUTEX(ioport_lock);
> -
> -static struct rb_root		ioport_tree = RB_ROOT;
> -
> -static struct ioport *ioport_search(struct rb_root *root, u64 addr)
> -{
> -	struct rb_int_node *node;
> -
> -	node = rb_int_search_single(root, addr);
> -	if (node == NULL)
> -		return NULL;
> -
> -	return ioport_node(node);
> -}
> -
> -static int ioport_insert(struct rb_root *root, struct ioport *data)
> -{
> -	return rb_int_insert(root, &data->node);
> -}
> -
> -static void ioport_remove(struct rb_root *root, struct ioport *data)
> -{
> -	rb_int_erase(root, &data->node);
> -}
> -
> -static struct ioport *ioport_get(struct rb_root *root, u64 addr)
> -{
> -	struct ioport *ioport;
> -
> -	mutex_lock(&ioport_lock);
> -	ioport = ioport_search(root, addr);
> -	if (ioport)
> -		ioport->refcount++;
> -	mutex_unlock(&ioport_lock);
> -
> -	return ioport;
> -}
> -
> -/* Called with ioport_lock held. */
> -static void ioport_unregister(struct rb_root *root, struct ioport *data)
> -{
> -	ioport_remove(root, data);
> -	free(data);
> -}
> -
> -static void ioport_put(struct rb_root *root, struct ioport *data)
> -{
> -	mutex_lock(&ioport_lock);
> -	data->refcount--;
> -	if (data->remove && data->refcount == 0)
> -		ioport_unregister(root, data);
> -	mutex_unlock(&ioport_lock);
> -}
> -
> -int ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops, int count, void *param)
> -{
> -	struct ioport *entry;
> -	int r;
> -
> -	entry = malloc(sizeof(*entry));
> -	if (entry == NULL)
> -		return -ENOMEM;
> -
> -	*entry = (struct ioport) {
> -		.node		= RB_INT_INIT(port, port + count),
> -		.ops		= ops,
> -		.priv		= param,
> -		/*
> -		 * Start from 0 because ioport__unregister() doesn't decrement
> -		 * the reference count.
> -		 */
> -		.refcount	= 0,
> -		.remove		= false,
> -	};
> -
> -	mutex_lock(&ioport_lock);
> -	r = ioport_insert(&ioport_tree, entry);
> -	if (r < 0)
> -		goto out_free;
> -	mutex_unlock(&ioport_lock);
> -
> -	return port;
> -
> -out_free:
> -	free(entry);
> -	mutex_unlock(&ioport_lock);
> -	return r;
> -}
> -
> -int ioport__unregister(struct kvm *kvm, u16 port)
> -{
> -	struct ioport *entry;
> -
> -	mutex_lock(&ioport_lock);
> -	entry = ioport_search(&ioport_tree, port);
> -	if (!entry) {
> -		mutex_unlock(&ioport_lock);
> -		return -ENOENT;
> -	}
> -	/* The same reasoning from kvm__deregister_mmio() applies. */
> -	if (entry->refcount == 0)
> -		ioport_unregister(&ioport_tree, entry);
> -	else
> -		entry->remove = true;
> -	mutex_unlock(&ioport_lock);
> -
> -	return 0;
> -}
> -
> -static void ioport__unregister_all(void)
> -{
> -	struct ioport *entry;
> -	struct rb_node *rb;
> -	struct rb_int_node *rb_node;
> -
> -	rb = rb_first(&ioport_tree);
> -	while (rb) {
> -		rb_node = rb_int(rb);
> -		entry = ioport_node(rb_node);
> -		ioport_unregister(&ioport_tree, entry);
> -		rb = rb_first(&ioport_tree);
> -	}
> -}
> -
> -static const char *to_direction(int direction)
> -{
> -	if (direction == KVM_EXIT_IO_IN)
> -		return "IN";
> -	else
> -		return "OUT";
> -}
> -
> -static void ioport_error(u16 port, void *data, int direction, int size, u32 count)
> -{
> -	fprintf(stderr, "IO error: %s port=%x, size=%d, count=%u\n", to_direction(direction), port, size, count);
> -}
> -
> -bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count)
> -{
> -	struct ioport_operations *ops;
> -	bool ret = false;
> -	struct ioport *entry;
> -	void *ptr = data;
> -	struct kvm *kvm = vcpu->kvm;
> -
> -	entry = ioport_get(&ioport_tree, port);
> -	if (!entry)
> -		return kvm__emulate_pio(vcpu, port, data, direction,
> -					size, count);
> -
> -	ops	= entry->ops;
> -
> -	while (count--) {
> -		if (direction == KVM_EXIT_IO_IN && ops->io_in)
> -				ret = ops->io_in(entry, vcpu, port, ptr, size);
> -		else if (direction == KVM_EXIT_IO_OUT && ops->io_out)
> -				ret = ops->io_out(entry, vcpu, port, ptr, size);
> -
> -		ptr += size;
> -	}
> -
> -	ioport_put(&ioport_tree, entry);
> -
> -	if (ret)
> -		return true;
> -
> -	if (kvm->cfg.ioport_debug)
> -		ioport_error(port, data, direction, size, count);
> -
> -	return !kvm->cfg.ioport_debug;
> -}
> -
> -int ioport__exit(struct kvm *kvm)
> -{
> -	ioport__unregister_all();
> -	return 0;
> -}
> -dev_base_exit(ioport__exit);
> diff --git a/mmio.c b/mmio.c
> index 75de04ad..9f731dcf 100644
> --- a/mmio.c
> +++ b/mmio.c
> @@ -212,7 +212,7 @@ out:
>  	return true;
>  }
>  
> -bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
> +bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data,
>  		     int direction, int size, u32 count)
>  {
>  	struct mmio_mapping *mmio;
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 20/22] arm: Reorganise and document memory map
  2021-02-25  0:59   ` Andre Przywara
@ 2021-03-09 15:46     ` Alexandru Elisei
  -1 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 15:46 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: kvm, kvmarm, Marc Zyngier, Sami Mujawar

Hi Andre,

This is a really good idea, thank you for implementing it!

Some comments below.

On 2/25/21 12:59 AM, Andre Przywara wrote:
> The hardcoded memory map we expose to a guest is currently described
> using a series of partially interconnected preprocessor constants,
> which is hard to read and follow.
>
> In preparation for moving the UART and RTC to some different MMIO
> region, document the current map with some ASCII art, and clean up the
> definition of the sections.
>
> No functional change.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arm/include/arm-common/kvm-arch.h | 41 ++++++++++++++++++++++---------
>  1 file changed, 29 insertions(+), 12 deletions(-)
>
> diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
> index d84e50cd..b12255b0 100644
> --- a/arm/include/arm-common/kvm-arch.h
> +++ b/arm/include/arm-common/kvm-arch.h
> @@ -7,14 +7,33 @@
>  
>  #include "arm-common/gic.h"
>  
> +/*
> + * The memory map used for ARM guests (not to scale):
> + *
> + * 0      64K  16M     32M     48M            1GB       2GB
> + * +-------+-..-+-------+-------+--....--+-----+--.....--+---......
> + * | (PCI) |////| int.  |       |        |     |         |
> + * |  I/O  |////| MMIO: | Flash | virtio | GIC |   PCI   |  DRAM
> + * | ports |////| UART, |       |  MMIO  |     |  (AXI)  |
> + * |       |////| RTC   |       |        |     |         |
> + * +-------+-..-+-------+-------+--....--+-----+--.....--+---......
> + */

Nitpick: I searched the PCI Local Bus Specification revision 3.0 (which kvmtool
currently implements) for the term I/O ports, and found one mention in a schematic
for an add-in card. The I/O region is called in the spec I/O Space.

I don't know what "int." means in the region for the UART and RTC.

The comment says that the art is not to scale, so I don't think there's any need
for the "..." between the corners of the regions. To my eyes, it makes the ASCII
art look crooked.

The next patches add the UART and RTC outside the first 64K, I think the region
should be documented in the patches where the changes are made, not here. Another
alternative would be to move this patch to the end of the series instead of
incrementally changing the memory ASCII art (which I imagine is time consuming).

Otherwise, the numbers look OK.

> +
>  #define ARM_IOPORT_AREA		_AC(0x0000000000000000, UL)
> -#define ARM_FLASH_AREA		_AC(0x0000000002000000, UL)
> -#define ARM_MMIO_AREA		_AC(0x0000000003000000, UL)
> +#define ARM_MMIO_AREA		_AC(0x0000000001000000, UL)

The patch says it is *documenting* the memory layout, but here it is *changing*
the layout. Other than that, I like the shuffling of definitions so the kvmtool
global defines are closer to the arch values.

Thanks,

Alex

>  #define ARM_AXI_AREA		_AC(0x0000000040000000, UL)
>  #define ARM_MEMORY_AREA		_AC(0x0000000080000000, UL)
>  
> -#define ARM_LOMAP_MAX_MEMORY	((1ULL << 32) - ARM_MEMORY_AREA)
> -#define ARM_HIMAP_MAX_MEMORY	((1ULL << 40) - ARM_MEMORY_AREA)
> +#define KVM_IOPORT_AREA		ARM_IOPORT_AREA
> +#define ARM_IOPORT_SIZE		(1U << 16)
> +
> +
> +#define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
> +#define KVM_FLASH_MAX_SIZE	0x1000000
> +
> +#define KVM_VIRTIO_MMIO_AREA	(KVM_FLASH_MMIO_BASE + KVM_FLASH_MAX_SIZE)
> +#define ARM_VIRTIO_MMIO_SIZE	(ARM_AXI_AREA - \
> +				(KVM_VIRTIO_MMIO_AREA + ARM_GIC_SIZE))
>  
>  #define ARM_GIC_DIST_BASE	(ARM_AXI_AREA - ARM_GIC_DIST_SIZE)
>  #define ARM_GIC_CPUI_BASE	(ARM_GIC_DIST_BASE - ARM_GIC_CPUI_SIZE)
> @@ -22,19 +41,17 @@
>  #define ARM_GIC_DIST_SIZE	0x10000
>  #define ARM_GIC_CPUI_SIZE	0x20000
>  
> -#define KVM_FLASH_MMIO_BASE	ARM_FLASH_AREA
> -#define KVM_FLASH_MAX_SIZE	(ARM_MMIO_AREA - ARM_FLASH_AREA)
>  
> -#define ARM_IOPORT_SIZE		(1U << 16)
> -#define ARM_VIRTIO_MMIO_SIZE	(ARM_AXI_AREA - (ARM_MMIO_AREA + ARM_GIC_SIZE))
> +#define KVM_PCI_CFG_AREA	ARM_AXI_AREA
>  #define ARM_PCI_CFG_SIZE	(1ULL << 24)
> +#define KVM_PCI_MMIO_AREA	(KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
>  #define ARM_PCI_MMIO_SIZE	(ARM_MEMORY_AREA - \
>  				(ARM_AXI_AREA + ARM_PCI_CFG_SIZE))
>  
> -#define KVM_IOPORT_AREA		ARM_IOPORT_AREA
> -#define KVM_PCI_CFG_AREA	ARM_AXI_AREA
> -#define KVM_PCI_MMIO_AREA	(KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
> -#define KVM_VIRTIO_MMIO_AREA	ARM_MMIO_AREA
> +
> +#define ARM_LOMAP_MAX_MEMORY	((1ULL << 32) - ARM_MEMORY_AREA)
> +#define ARM_HIMAP_MAX_MEMORY	((1ULL << 40) - ARM_MEMORY_AREA)
> +
>  
>  #define KVM_IOEVENTFD_HAS_PIO	0
>  

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

* Re: [PATCH kvmtool v2 20/22] arm: Reorganise and document memory map
@ 2021-03-09 15:46     ` Alexandru Elisei
  0 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 15:46 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Hi Andre,

This is a really good idea, thank you for implementing it!

Some comments below.

On 2/25/21 12:59 AM, Andre Przywara wrote:
> The hardcoded memory map we expose to a guest is currently described
> using a series of partially interconnected preprocessor constants,
> which is hard to read and follow.
>
> In preparation for moving the UART and RTC to some different MMIO
> region, document the current map with some ASCII art, and clean up the
> definition of the sections.
>
> No functional change.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arm/include/arm-common/kvm-arch.h | 41 ++++++++++++++++++++++---------
>  1 file changed, 29 insertions(+), 12 deletions(-)
>
> diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
> index d84e50cd..b12255b0 100644
> --- a/arm/include/arm-common/kvm-arch.h
> +++ b/arm/include/arm-common/kvm-arch.h
> @@ -7,14 +7,33 @@
>  
>  #include "arm-common/gic.h"
>  
> +/*
> + * The memory map used for ARM guests (not to scale):
> + *
> + * 0      64K  16M     32M     48M            1GB       2GB
> + * +-------+-..-+-------+-------+--....--+-----+--.....--+---......
> + * | (PCI) |////| int.  |       |        |     |         |
> + * |  I/O  |////| MMIO: | Flash | virtio | GIC |   PCI   |  DRAM
> + * | ports |////| UART, |       |  MMIO  |     |  (AXI)  |
> + * |       |////| RTC   |       |        |     |         |
> + * +-------+-..-+-------+-------+--....--+-----+--.....--+---......
> + */

Nitpick: I searched the PCI Local Bus Specification revision 3.0 (which kvmtool
currently implements) for the term I/O ports, and found one mention in a schematic
for an add-in card. The I/O region is called in the spec I/O Space.

I don't know what "int." means in the region for the UART and RTC.

The comment says that the art is not to scale, so I don't think there's any need
for the "..." between the corners of the regions. To my eyes, it makes the ASCII
art look crooked.

The next patches add the UART and RTC outside the first 64K, I think the region
should be documented in the patches where the changes are made, not here. Another
alternative would be to move this patch to the end of the series instead of
incrementally changing the memory ASCII art (which I imagine is time consuming).

Otherwise, the numbers look OK.

> +
>  #define ARM_IOPORT_AREA		_AC(0x0000000000000000, UL)
> -#define ARM_FLASH_AREA		_AC(0x0000000002000000, UL)
> -#define ARM_MMIO_AREA		_AC(0x0000000003000000, UL)
> +#define ARM_MMIO_AREA		_AC(0x0000000001000000, UL)

The patch says it is *documenting* the memory layout, but here it is *changing*
the layout. Other than that, I like the shuffling of definitions so the kvmtool
global defines are closer to the arch values.

Thanks,

Alex

>  #define ARM_AXI_AREA		_AC(0x0000000040000000, UL)
>  #define ARM_MEMORY_AREA		_AC(0x0000000080000000, UL)
>  
> -#define ARM_LOMAP_MAX_MEMORY	((1ULL << 32) - ARM_MEMORY_AREA)
> -#define ARM_HIMAP_MAX_MEMORY	((1ULL << 40) - ARM_MEMORY_AREA)
> +#define KVM_IOPORT_AREA		ARM_IOPORT_AREA
> +#define ARM_IOPORT_SIZE		(1U << 16)
> +
> +
> +#define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
> +#define KVM_FLASH_MAX_SIZE	0x1000000
> +
> +#define KVM_VIRTIO_MMIO_AREA	(KVM_FLASH_MMIO_BASE + KVM_FLASH_MAX_SIZE)
> +#define ARM_VIRTIO_MMIO_SIZE	(ARM_AXI_AREA - \
> +				(KVM_VIRTIO_MMIO_AREA + ARM_GIC_SIZE))
>  
>  #define ARM_GIC_DIST_BASE	(ARM_AXI_AREA - ARM_GIC_DIST_SIZE)
>  #define ARM_GIC_CPUI_BASE	(ARM_GIC_DIST_BASE - ARM_GIC_CPUI_SIZE)
> @@ -22,19 +41,17 @@
>  #define ARM_GIC_DIST_SIZE	0x10000
>  #define ARM_GIC_CPUI_SIZE	0x20000
>  
> -#define KVM_FLASH_MMIO_BASE	ARM_FLASH_AREA
> -#define KVM_FLASH_MAX_SIZE	(ARM_MMIO_AREA - ARM_FLASH_AREA)
>  
> -#define ARM_IOPORT_SIZE		(1U << 16)
> -#define ARM_VIRTIO_MMIO_SIZE	(ARM_AXI_AREA - (ARM_MMIO_AREA + ARM_GIC_SIZE))
> +#define KVM_PCI_CFG_AREA	ARM_AXI_AREA
>  #define ARM_PCI_CFG_SIZE	(1ULL << 24)
> +#define KVM_PCI_MMIO_AREA	(KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
>  #define ARM_PCI_MMIO_SIZE	(ARM_MEMORY_AREA - \
>  				(ARM_AXI_AREA + ARM_PCI_CFG_SIZE))
>  
> -#define KVM_IOPORT_AREA		ARM_IOPORT_AREA
> -#define KVM_PCI_CFG_AREA	ARM_AXI_AREA
> -#define KVM_PCI_MMIO_AREA	(KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
> -#define KVM_VIRTIO_MMIO_AREA	ARM_MMIO_AREA
> +
> +#define ARM_LOMAP_MAX_MEMORY	((1ULL << 32) - ARM_MEMORY_AREA)
> +#define ARM_HIMAP_MAX_MEMORY	((1ULL << 40) - ARM_MEMORY_AREA)
> +
>  
>  #define KVM_IOEVENTFD_HAS_PIO	0
>  
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 21/22] hw/serial: ARM/arm64: Use MMIO at higher addresses
  2021-02-25  0:59   ` Andre Przywara
@ 2021-03-09 16:02     ` Alexandru Elisei
  -1 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 16:02 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: kvm, kvmarm, Marc Zyngier, Sami Mujawar

Hi Andre,

I think you forgot to change the way the address is generated in
serial8250_generate_fdt_node, it's still KVM_IOPORT_AREA + dev->iobase. It's
technically correct, as KVM_IOPORT_AREA == ARM_IOPORT_AREA == 0x0, but very
confusing (and prone to breakage is something changes in the memory layout).

One more comment below.

On 2/25/21 12:59 AM, Andre Przywara wrote:
> Using the UART devices at their legacy I/O addresses as set by IBM in
> 1981 was a kludge we used for simplicity on ARM platforms as well.
> However this imposes problems due to their missing alignment and overlap
> with the PCI I/O address space.
>
> Now that we can switch a device easily between using ioports and MMIO,
> let's move the UARTs out of the first 4K of memory on ARM platforms.
>
> That should be transparent for well behaved guests, since the change is
> naturally reflected in the device tree. Even "earlycon" keeps working,
> as the stdout-path property is adjusted automatically.
>
> People providing direct earlycon parameters via the command line need to
> adjust it to: "earlycon=uart,mmio,0x1000000".
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arm/include/arm-common/kvm-arch.h |  3 +++
>  hw/serial.c                       | 45 ++++++++++++++++++++-----------
>  2 files changed, 32 insertions(+), 16 deletions(-)
>
> diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
> index b12255b0..633ea8fa 100644
> --- a/arm/include/arm-common/kvm-arch.h
> +++ b/arm/include/arm-common/kvm-arch.h
> @@ -28,6 +28,9 @@
>  #define ARM_IOPORT_SIZE		(1U << 16)
>  
>  
> +#define ARM_UART_MMIO_BASE	ARM_MMIO_AREA
> +#define ARM_UART_MMIO_SIZE	0x10000
> +
>  #define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
>  #define KVM_FLASH_MAX_SIZE	0x1000000
>  
> diff --git a/hw/serial.c b/hw/serial.c
> index 4be188a1..1854add2 100644
> --- a/hw/serial.c
> +++ b/hw/serial.c
> @@ -13,6 +13,17 @@
>  
>  #include <pthread.h>
>  
> +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
> +#define serial_iobase(nr)	(ARM_UART_MMIO_BASE + (nr) * 0x1000)
> +#define serial_irq(nr)		(32 + (nr))
> +#define SERIAL8250_BUS_TYPE	DEVICE_BUS_MMIO
> +#else
> +#define serial_iobase(nr)	((((nr) & 1) ? 0x200 : 0x300) +	\
> +				 ((nr) >= 2 ? 0xe8 : 0xf8))
> +#define serial_irq(nr)		(((nr) & 1) ? 3 : 4)

Those two defines are hard to read, is there a reason for changing them from v1?
They looked a lot more readable in v1.

Thanks,

Alex

> +#define SERIAL8250_BUS_TYPE	DEVICE_BUS_IOPORT
> +#endif
> +
>  /*
>   * This fakes a U6_16550A. The fifo len needs to be 64 as the kernel
>   * expects that for autodetection.
> @@ -27,7 +38,7 @@ struct serial8250_device {
>  	struct mutex		mutex;
>  	u8			id;
>  
> -	u16			iobase;
> +	u32			iobase;
>  	u8			irq;
>  	u8			irq_state;
>  	int			txcnt;
> @@ -65,56 +76,56 @@ static struct serial8250_device devices[] = {
>  	/* ttyS0 */
>  	[0]	= {
>  		.dev_hdr = {
> -			.bus_type	= DEVICE_BUS_IOPORT,
> +			.bus_type	= SERIAL8250_BUS_TYPE,
>  			.data		= serial8250_generate_fdt_node,
>  		},
>  		.mutex			= MUTEX_INITIALIZER,
>  
>  		.id			= 0,
> -		.iobase			= 0x3f8,
> -		.irq			= 4,
> +		.iobase			= serial_iobase(0),
> +		.irq			= serial_irq(0),
>  
>  		SERIAL_REGS_SETTING
>  	},
>  	/* ttyS1 */
>  	[1]	= {
>  		.dev_hdr = {
> -			.bus_type	= DEVICE_BUS_IOPORT,
> +			.bus_type	= SERIAL8250_BUS_TYPE,
>  			.data		= serial8250_generate_fdt_node,
>  		},
>  		.mutex			= MUTEX_INITIALIZER,
>  
>  		.id			= 1,
> -		.iobase			= 0x2f8,
> -		.irq			= 3,
> +		.iobase			= serial_iobase(1),
> +		.irq			= serial_irq(1),
>  
>  		SERIAL_REGS_SETTING
>  	},
>  	/* ttyS2 */
>  	[2]	= {
>  		.dev_hdr = {
> -			.bus_type	= DEVICE_BUS_IOPORT,
> +			.bus_type	= SERIAL8250_BUS_TYPE,
>  			.data		= serial8250_generate_fdt_node,
>  		},
>  		.mutex			= MUTEX_INITIALIZER,
>  
>  		.id			= 2,
> -		.iobase			= 0x3e8,
> -		.irq			= 4,
> +		.iobase			= serial_iobase(2),
> +		.irq			= serial_irq(2),
>  
>  		SERIAL_REGS_SETTING
>  	},
>  	/* ttyS3 */
>  	[3]	= {
>  		.dev_hdr = {
> -			.bus_type	= DEVICE_BUS_IOPORT,
> +			.bus_type	= SERIAL8250_BUS_TYPE,
>  			.data		= serial8250_generate_fdt_node,
>  		},
>  		.mutex			= MUTEX_INITIALIZER,
>  
>  		.id			= 3,
> -		.iobase			= 0x2e8,
> -		.irq			= 3,
> +		.iobase			= serial_iobase(3),
> +		.irq			= serial_irq(3),
>  
>  		SERIAL_REGS_SETTING
>  	},
> @@ -439,7 +450,8 @@ static int serial8250__device_init(struct kvm *kvm,
>  		return r;
>  
>  	ioport__map_irq(&dev->irq);
> -	r = kvm__register_pio(kvm, dev->iobase, 8, serial8250_mmio, dev);
> +	r = kvm__register_iotrap(kvm, dev->iobase, 8, serial8250_mmio, dev,
> +				 SERIAL8250_BUS_TYPE);
>  
>  	return r;
>  }
> @@ -462,7 +474,7 @@ cleanup:
>  	for (j = 0; j <= i; j++) {
>  		struct serial8250_device *dev = &devices[j];
>  
> -		kvm__deregister_pio(kvm, dev->iobase);
> +		kvm__deregister_iotrap(kvm, dev->iobase, SERIAL8250_BUS_TYPE);
>  		device__unregister(&dev->dev_hdr);
>  	}
>  
> @@ -478,7 +490,8 @@ int serial8250__exit(struct kvm *kvm)
>  	for (i = 0; i < ARRAY_SIZE(devices); i++) {
>  		struct serial8250_device *dev = &devices[i];
>  
> -		r = kvm__deregister_pio(kvm, dev->iobase);
> +		r = kvm__deregister_iotrap(kvm, dev->iobase,
> +					   SERIAL8250_BUS_TYPE);
>  		if (r < 0)
>  			return r;
>  		device__unregister(&dev->dev_hdr);

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

* Re: [PATCH kvmtool v2 21/22] hw/serial: ARM/arm64: Use MMIO at higher addresses
@ 2021-03-09 16:02     ` Alexandru Elisei
  0 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 16:02 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Hi Andre,

I think you forgot to change the way the address is generated in
serial8250_generate_fdt_node, it's still KVM_IOPORT_AREA + dev->iobase. It's
technically correct, as KVM_IOPORT_AREA == ARM_IOPORT_AREA == 0x0, but very
confusing (and prone to breakage is something changes in the memory layout).

One more comment below.

On 2/25/21 12:59 AM, Andre Przywara wrote:
> Using the UART devices at their legacy I/O addresses as set by IBM in
> 1981 was a kludge we used for simplicity on ARM platforms as well.
> However this imposes problems due to their missing alignment and overlap
> with the PCI I/O address space.
>
> Now that we can switch a device easily between using ioports and MMIO,
> let's move the UARTs out of the first 4K of memory on ARM platforms.
>
> That should be transparent for well behaved guests, since the change is
> naturally reflected in the device tree. Even "earlycon" keeps working,
> as the stdout-path property is adjusted automatically.
>
> People providing direct earlycon parameters via the command line need to
> adjust it to: "earlycon=uart,mmio,0x1000000".
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arm/include/arm-common/kvm-arch.h |  3 +++
>  hw/serial.c                       | 45 ++++++++++++++++++++-----------
>  2 files changed, 32 insertions(+), 16 deletions(-)
>
> diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
> index b12255b0..633ea8fa 100644
> --- a/arm/include/arm-common/kvm-arch.h
> +++ b/arm/include/arm-common/kvm-arch.h
> @@ -28,6 +28,9 @@
>  #define ARM_IOPORT_SIZE		(1U << 16)
>  
>  
> +#define ARM_UART_MMIO_BASE	ARM_MMIO_AREA
> +#define ARM_UART_MMIO_SIZE	0x10000
> +
>  #define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
>  #define KVM_FLASH_MAX_SIZE	0x1000000
>  
> diff --git a/hw/serial.c b/hw/serial.c
> index 4be188a1..1854add2 100644
> --- a/hw/serial.c
> +++ b/hw/serial.c
> @@ -13,6 +13,17 @@
>  
>  #include <pthread.h>
>  
> +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
> +#define serial_iobase(nr)	(ARM_UART_MMIO_BASE + (nr) * 0x1000)
> +#define serial_irq(nr)		(32 + (nr))
> +#define SERIAL8250_BUS_TYPE	DEVICE_BUS_MMIO
> +#else
> +#define serial_iobase(nr)	((((nr) & 1) ? 0x200 : 0x300) +	\
> +				 ((nr) >= 2 ? 0xe8 : 0xf8))
> +#define serial_irq(nr)		(((nr) & 1) ? 3 : 4)

Those two defines are hard to read, is there a reason for changing them from v1?
They looked a lot more readable in v1.

Thanks,

Alex

> +#define SERIAL8250_BUS_TYPE	DEVICE_BUS_IOPORT
> +#endif
> +
>  /*
>   * This fakes a U6_16550A. The fifo len needs to be 64 as the kernel
>   * expects that for autodetection.
> @@ -27,7 +38,7 @@ struct serial8250_device {
>  	struct mutex		mutex;
>  	u8			id;
>  
> -	u16			iobase;
> +	u32			iobase;
>  	u8			irq;
>  	u8			irq_state;
>  	int			txcnt;
> @@ -65,56 +76,56 @@ static struct serial8250_device devices[] = {
>  	/* ttyS0 */
>  	[0]	= {
>  		.dev_hdr = {
> -			.bus_type	= DEVICE_BUS_IOPORT,
> +			.bus_type	= SERIAL8250_BUS_TYPE,
>  			.data		= serial8250_generate_fdt_node,
>  		},
>  		.mutex			= MUTEX_INITIALIZER,
>  
>  		.id			= 0,
> -		.iobase			= 0x3f8,
> -		.irq			= 4,
> +		.iobase			= serial_iobase(0),
> +		.irq			= serial_irq(0),
>  
>  		SERIAL_REGS_SETTING
>  	},
>  	/* ttyS1 */
>  	[1]	= {
>  		.dev_hdr = {
> -			.bus_type	= DEVICE_BUS_IOPORT,
> +			.bus_type	= SERIAL8250_BUS_TYPE,
>  			.data		= serial8250_generate_fdt_node,
>  		},
>  		.mutex			= MUTEX_INITIALIZER,
>  
>  		.id			= 1,
> -		.iobase			= 0x2f8,
> -		.irq			= 3,
> +		.iobase			= serial_iobase(1),
> +		.irq			= serial_irq(1),
>  
>  		SERIAL_REGS_SETTING
>  	},
>  	/* ttyS2 */
>  	[2]	= {
>  		.dev_hdr = {
> -			.bus_type	= DEVICE_BUS_IOPORT,
> +			.bus_type	= SERIAL8250_BUS_TYPE,
>  			.data		= serial8250_generate_fdt_node,
>  		},
>  		.mutex			= MUTEX_INITIALIZER,
>  
>  		.id			= 2,
> -		.iobase			= 0x3e8,
> -		.irq			= 4,
> +		.iobase			= serial_iobase(2),
> +		.irq			= serial_irq(2),
>  
>  		SERIAL_REGS_SETTING
>  	},
>  	/* ttyS3 */
>  	[3]	= {
>  		.dev_hdr = {
> -			.bus_type	= DEVICE_BUS_IOPORT,
> +			.bus_type	= SERIAL8250_BUS_TYPE,
>  			.data		= serial8250_generate_fdt_node,
>  		},
>  		.mutex			= MUTEX_INITIALIZER,
>  
>  		.id			= 3,
> -		.iobase			= 0x2e8,
> -		.irq			= 3,
> +		.iobase			= serial_iobase(3),
> +		.irq			= serial_irq(3),
>  
>  		SERIAL_REGS_SETTING
>  	},
> @@ -439,7 +450,8 @@ static int serial8250__device_init(struct kvm *kvm,
>  		return r;
>  
>  	ioport__map_irq(&dev->irq);
> -	r = kvm__register_pio(kvm, dev->iobase, 8, serial8250_mmio, dev);
> +	r = kvm__register_iotrap(kvm, dev->iobase, 8, serial8250_mmio, dev,
> +				 SERIAL8250_BUS_TYPE);
>  
>  	return r;
>  }
> @@ -462,7 +474,7 @@ cleanup:
>  	for (j = 0; j <= i; j++) {
>  		struct serial8250_device *dev = &devices[j];
>  
> -		kvm__deregister_pio(kvm, dev->iobase);
> +		kvm__deregister_iotrap(kvm, dev->iobase, SERIAL8250_BUS_TYPE);
>  		device__unregister(&dev->dev_hdr);
>  	}
>  
> @@ -478,7 +490,8 @@ int serial8250__exit(struct kvm *kvm)
>  	for (i = 0; i < ARRAY_SIZE(devices); i++) {
>  		struct serial8250_device *dev = &devices[i];
>  
> -		r = kvm__deregister_pio(kvm, dev->iobase);
> +		r = kvm__deregister_iotrap(kvm, dev->iobase,
> +					   SERIAL8250_BUS_TYPE);
>  		if (r < 0)
>  			return r;
>  		device__unregister(&dev->dev_hdr);
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 22/22] hw/rtc: ARM/arm64: Use MMIO at higher addresses
  2021-02-25  0:59   ` Andre Przywara
@ 2021-03-09 16:06     ` Alexandru Elisei
  -1 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 16:06 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: kvm, kvmarm, Marc Zyngier, Sami Mujawar

Hi Andre,

On 2/25/21 12:59 AM, Andre Przywara wrote:
> Using the RTC device at its legacy I/O address as set by IBM in 1981
> was a kludge we used for simplicity on ARM platforms as well.
> However this imposes problems due to their missing alignment and overlap
> with the PCI I/O address space.
>
> Now that we can switch a device easily between using ioports and
> MMIO, let's move the RTC out of the first 4K of memory on ARM platforms.
>
> That should be transparent for well behaved guests, since the change is
> naturally reflected in the device tree.

Everything looks correct, compile tested for arm64 and x86-64. Also grep'ed for
0x70 (device ioport address) and DEVICE_BUS_IOPORT, no occurrence in the file
other than in the defines:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arm/include/arm-common/kvm-arch.h |  3 +++
>  hw/rtc.c                          | 24 ++++++++++++++++--------
>  2 files changed, 19 insertions(+), 8 deletions(-)
>
> diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
> index 633ea8fa..02100c48 100644
> --- a/arm/include/arm-common/kvm-arch.h
> +++ b/arm/include/arm-common/kvm-arch.h
> @@ -31,6 +31,9 @@
>  #define ARM_UART_MMIO_BASE	ARM_MMIO_AREA
>  #define ARM_UART_MMIO_SIZE	0x10000
>  
> +#define ARM_RTC_MMIO_BASE	(ARM_UART_MMIO_BASE + ARM_UART_MMIO_SIZE)
> +#define ARM_RTC_MMIO_SIZE	0x10000
> +
>  #define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
>  #define KVM_FLASH_MAX_SIZE	0x1000000
>  
> diff --git a/hw/rtc.c b/hw/rtc.c
> index ee4c9102..aec31c52 100644
> --- a/hw/rtc.c
> +++ b/hw/rtc.c
> @@ -5,6 +5,15 @@
>  
>  #include <time.h>
>  
> +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
> +#define RTC_BUS_TYPE		DEVICE_BUS_MMIO
> +#define RTC_BASE_ADDRESS	ARM_RTC_MMIO_BASE
> +#else
> +/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
> +#define RTC_BUS_TYPE		DEVICE_BUS_IOPORT
> +#define RTC_BASE_ADDRESS	0x70
> +#endif
> +
>  /*
>   * MC146818 RTC registers
>   */
> @@ -49,7 +58,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
>  	time_t ti;
>  
>  	if (is_write) {
> -		if (addr == 0x70) {	/* index register */
> +		if (addr == RTC_BASE_ADDRESS) {	/* index register */
>  			u8 value = ioport__read8(data);
>  
>  			vcpu->kvm->nmi_disabled	= value & (1UL << 7);
> @@ -70,7 +79,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
>  		return;
>  	}
>  
> -	if (addr == 0x70)
> +	if (addr == RTC_BASE_ADDRESS)	/* index register is write-only */
>  		return;
>  
>  	time(&ti);
> @@ -127,7 +136,7 @@ static void generate_rtc_fdt_node(void *fdt,
>  							    u8 irq,
>  							    enum irq_type))
>  {
> -	u64 reg_prop[2] = { cpu_to_fdt64(0x70), cpu_to_fdt64(2) };
> +	u64 reg_prop[2] = { cpu_to_fdt64(RTC_BASE_ADDRESS), cpu_to_fdt64(2) };
>  
>  	_FDT(fdt_begin_node(fdt, "rtc"));
>  	_FDT(fdt_property_string(fdt, "compatible", "motorola,mc146818"));
> @@ -139,7 +148,7 @@ static void generate_rtc_fdt_node(void *fdt,
>  #endif
>  
>  struct device_header rtc_dev_hdr = {
> -	.bus_type = DEVICE_BUS_IOPORT,
> +	.bus_type = RTC_BUS_TYPE,
>  	.data = generate_rtc_fdt_node,
>  };
>  
> @@ -151,8 +160,8 @@ int rtc__init(struct kvm *kvm)
>  	if (r < 0)
>  		return r;
>  
> -	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
> -	r = kvm__register_pio(kvm, 0x0070, 2, cmos_ram_io, NULL);
> +	r = kvm__register_iotrap(kvm, RTC_BASE_ADDRESS, 2, cmos_ram_io, NULL,
> +				 RTC_BUS_TYPE);
>  	if (r < 0)
>  		goto out_device;
>  
> @@ -170,8 +179,7 @@ dev_init(rtc__init);
>  
>  int rtc__exit(struct kvm *kvm)
>  {
> -	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
> -	kvm__deregister_pio(kvm, 0x0070);
> +	kvm__deregister_iotrap(kvm, RTC_BASE_ADDRESS, RTC_BUS_TYPE);
>  
>  	return 0;
>  }

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

* Re: [PATCH kvmtool v2 22/22] hw/rtc: ARM/arm64: Use MMIO at higher addresses
@ 2021-03-09 16:06     ` Alexandru Elisei
  0 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-09 16:06 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Hi Andre,

On 2/25/21 12:59 AM, Andre Przywara wrote:
> Using the RTC device at its legacy I/O address as set by IBM in 1981
> was a kludge we used for simplicity on ARM platforms as well.
> However this imposes problems due to their missing alignment and overlap
> with the PCI I/O address space.
>
> Now that we can switch a device easily between using ioports and
> MMIO, let's move the RTC out of the first 4K of memory on ARM platforms.
>
> That should be transparent for well behaved guests, since the change is
> naturally reflected in the device tree.

Everything looks correct, compile tested for arm64 and x86-64. Also grep'ed for
0x70 (device ioport address) and DEVICE_BUS_IOPORT, no occurrence in the file
other than in the defines:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,

Alex

>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arm/include/arm-common/kvm-arch.h |  3 +++
>  hw/rtc.c                          | 24 ++++++++++++++++--------
>  2 files changed, 19 insertions(+), 8 deletions(-)
>
> diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
> index 633ea8fa..02100c48 100644
> --- a/arm/include/arm-common/kvm-arch.h
> +++ b/arm/include/arm-common/kvm-arch.h
> @@ -31,6 +31,9 @@
>  #define ARM_UART_MMIO_BASE	ARM_MMIO_AREA
>  #define ARM_UART_MMIO_SIZE	0x10000
>  
> +#define ARM_RTC_MMIO_BASE	(ARM_UART_MMIO_BASE + ARM_UART_MMIO_SIZE)
> +#define ARM_RTC_MMIO_SIZE	0x10000
> +
>  #define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
>  #define KVM_FLASH_MAX_SIZE	0x1000000
>  
> diff --git a/hw/rtc.c b/hw/rtc.c
> index ee4c9102..aec31c52 100644
> --- a/hw/rtc.c
> +++ b/hw/rtc.c
> @@ -5,6 +5,15 @@
>  
>  #include <time.h>
>  
> +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
> +#define RTC_BUS_TYPE		DEVICE_BUS_MMIO
> +#define RTC_BASE_ADDRESS	ARM_RTC_MMIO_BASE
> +#else
> +/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
> +#define RTC_BUS_TYPE		DEVICE_BUS_IOPORT
> +#define RTC_BASE_ADDRESS	0x70
> +#endif
> +
>  /*
>   * MC146818 RTC registers
>   */
> @@ -49,7 +58,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
>  	time_t ti;
>  
>  	if (is_write) {
> -		if (addr == 0x70) {	/* index register */
> +		if (addr == RTC_BASE_ADDRESS) {	/* index register */
>  			u8 value = ioport__read8(data);
>  
>  			vcpu->kvm->nmi_disabled	= value & (1UL << 7);
> @@ -70,7 +79,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
>  		return;
>  	}
>  
> -	if (addr == 0x70)
> +	if (addr == RTC_BASE_ADDRESS)	/* index register is write-only */
>  		return;
>  
>  	time(&ti);
> @@ -127,7 +136,7 @@ static void generate_rtc_fdt_node(void *fdt,
>  							    u8 irq,
>  							    enum irq_type))
>  {
> -	u64 reg_prop[2] = { cpu_to_fdt64(0x70), cpu_to_fdt64(2) };
> +	u64 reg_prop[2] = { cpu_to_fdt64(RTC_BASE_ADDRESS), cpu_to_fdt64(2) };
>  
>  	_FDT(fdt_begin_node(fdt, "rtc"));
>  	_FDT(fdt_property_string(fdt, "compatible", "motorola,mc146818"));
> @@ -139,7 +148,7 @@ static void generate_rtc_fdt_node(void *fdt,
>  #endif
>  
>  struct device_header rtc_dev_hdr = {
> -	.bus_type = DEVICE_BUS_IOPORT,
> +	.bus_type = RTC_BUS_TYPE,
>  	.data = generate_rtc_fdt_node,
>  };
>  
> @@ -151,8 +160,8 @@ int rtc__init(struct kvm *kvm)
>  	if (r < 0)
>  		return r;
>  
> -	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
> -	r = kvm__register_pio(kvm, 0x0070, 2, cmos_ram_io, NULL);
> +	r = kvm__register_iotrap(kvm, RTC_BASE_ADDRESS, 2, cmos_ram_io, NULL,
> +				 RTC_BUS_TYPE);
>  	if (r < 0)
>  		goto out_device;
>  
> @@ -170,8 +179,7 @@ dev_init(rtc__init);
>  
>  int rtc__exit(struct kvm *kvm)
>  {
> -	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
> -	kvm__deregister_pio(kvm, 0x0070);
> +	kvm__deregister_iotrap(kvm, RTC_BASE_ADDRESS, RTC_BUS_TYPE);
>  
>  	return 0;
>  }
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 13/22] hw/serial: Refactor trap handler
  2021-02-25  0:59   ` Andre Przywara
@ 2021-03-12 11:29     ` Alexandru Elisei
  -1 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-12 11:29 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: kvm, kvmarm, Marc Zyngier, Sami Mujawar

Hi Andre,

On 2/25/21 12:59 AM, Andre Przywara wrote:
> With the planned retirement of the special ioport emulation code, we
> need to provide an emulation function compatible with the MMIO prototype.
>
> Adjust the trap handler to use that new function, and provide shims to
> implement the old ioport interface, for now.
>
> We drop the usage of ioport__read8/write8 entirely, as this would only
> be applicable for I/O port accesses, and does nothing for 8-bit wide
> accesses anyway.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  hw/serial.c | 93 +++++++++++++++++++++++++++++++++--------------------
>  1 file changed, 58 insertions(+), 35 deletions(-)
>
> diff --git a/hw/serial.c b/hw/serial.c
> index b0465d99..c495eac1 100644
> --- a/hw/serial.c
> +++ b/hw/serial.c
> @@ -242,36 +242,31 @@ void serial8250__inject_sysrq(struct kvm *kvm, char sysrq)
>  	sysrq_pending = sysrq;
>  }
>  
> -static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port,
> -			   void *data, int size)
> +static bool serial8250_out(struct serial8250_device *dev, struct kvm_cpu *vcpu,
> +			   u16 offset, u8 data)
>  {
> -	struct serial8250_device *dev = ioport->priv;
> -	u16 offset;
>  	bool ret = true;
> -	char *addr = data;
>  
>  	mutex_lock(&dev->mutex);
>  
> -	offset = port - dev->iobase;
> -
>  	switch (offset) {
>  	case UART_TX:
>  		if (dev->lcr & UART_LCR_DLAB) {
> -			dev->dll = ioport__read8(data);
> +			dev->dll = data;
>  			break;
>  		}
>  
>  		/* Loopback mode */
>  		if (dev->mcr & UART_MCR_LOOP) {
>  			if (dev->rxcnt < FIFO_LEN) {
> -				dev->rxbuf[dev->rxcnt++] = *addr;
> +				dev->rxbuf[dev->rxcnt++] = data;
>  				dev->lsr |= UART_LSR_DR;
>  			}
>  			break;
>  		}
>  
>  		if (dev->txcnt < FIFO_LEN) {
> -			dev->txbuf[dev->txcnt++] = *addr;
> +			dev->txbuf[dev->txcnt++] = data;
>  			dev->lsr &= ~UART_LSR_TEMT;
>  			if (dev->txcnt == FIFO_LEN / 2)
>  				dev->lsr &= ~UART_LSR_THRE;
> @@ -283,18 +278,18 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
>  		break;
>  	case UART_IER:
>  		if (!(dev->lcr & UART_LCR_DLAB))
> -			dev->ier = ioport__read8(data) & 0x0f;
> +			dev->ier = data & 0x0f;
>  		else
> -			dev->dlm = ioport__read8(data);
> +			dev->dlm = data;
>  		break;
>  	case UART_FCR:
> -		dev->fcr = ioport__read8(data);
> +		dev->fcr = data;
>  		break;
>  	case UART_LCR:
> -		dev->lcr = ioport__read8(data);
> +		dev->lcr = data;
>  		break;
>  	case UART_MCR:
> -		dev->mcr = ioport__read8(data);
> +		dev->mcr = data;
>  		break;
>  	case UART_LSR:
>  		/* Factory test */
> @@ -303,7 +298,7 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
>  		/* Not used */
>  		break;
>  	case UART_SCR:
> -		dev->scr = ioport__read8(data);
> +		dev->scr = data;
>  		break;
>  	default:
>  		ret = false;
> @@ -317,7 +312,7 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
>  	return ret;
>  }
>  
> -static void serial8250_rx(struct serial8250_device *dev, void *data)
> +static void serial8250_rx(struct serial8250_device *dev, u8 *data)
>  {
>  	if (dev->rxdone == dev->rxcnt)
>  		return;
> @@ -325,57 +320,54 @@ static void serial8250_rx(struct serial8250_device *dev, void *data)
>  	/* Break issued ? */
>  	if (dev->lsr & UART_LSR_BI) {
>  		dev->lsr &= ~UART_LSR_BI;
> -		ioport__write8(data, 0);
> +		*data = 0;
>  		return;
>  	}
>  
> -	ioport__write8(data, dev->rxbuf[dev->rxdone++]);
> +	*data = dev->rxbuf[dev->rxdone++];
>  	if (dev->rxcnt == dev->rxdone) {
>  		dev->lsr &= ~UART_LSR_DR;
>  		dev->rxcnt = dev->rxdone = 0;
>  	}
>  }
>  
> -static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +static bool serial8250_in(struct serial8250_device *dev, struct kvm_cpu *vcpu,
> +			  u16 offset, u8 *data)
>  {
> -	struct serial8250_device *dev = ioport->priv;
> -	u16 offset;
>  	bool ret = true;
>  
>  	mutex_lock(&dev->mutex);
>  
> -	offset = port - dev->iobase;
> -
>  	switch (offset) {
>  	case UART_RX:
>  		if (dev->lcr & UART_LCR_DLAB)
> -			ioport__write8(data, dev->dll);
> +			*data = dev->dll;
>  		else
>  			serial8250_rx(dev, data);
>  		break;
>  	case UART_IER:
>  		if (dev->lcr & UART_LCR_DLAB)
> -			ioport__write8(data, dev->dlm);
> +			*data = dev->dlm;
>  		else
> -			ioport__write8(data, dev->ier);
> +			*data = dev->ier;
>  		break;
>  	case UART_IIR:
> -		ioport__write8(data, dev->iir | UART_IIR_TYPE_BITS);
> +		*data = dev->iir | UART_IIR_TYPE_BITS;
>  		break;
>  	case UART_LCR:
> -		ioport__write8(data, dev->lcr);
> +		*data = dev->lcr;
>  		break;
>  	case UART_MCR:
> -		ioport__write8(data, dev->mcr);
> +		*data = dev->mcr;
>  		break;
>  	case UART_LSR:
> -		ioport__write8(data, dev->lsr);
> +		*data = dev->lsr;
>  		break;
>  	case UART_MSR:
> -		ioport__write8(data, dev->msr);
> +		*data = dev->msr;
>  		break;
>  	case UART_SCR:
> -		ioport__write8(data, dev->scr);
> +		*data = dev->scr;
>  		break;
>  	default:
>  		ret = false;
> @@ -389,6 +381,37 @@ static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port,
>  	return ret;
>  }

I'm not sure about replacing ioport_{read,write}8 with pointer dereferencing. They
are functionally equivalent because big-endian and little-endian are about the
order of bytes in memory, not the order of bits, but I don't think the change
makes much sense because:

1. All the other emulated devices use the ioport accessors, even in the case of 8
bit accesses. For example, the RTC device uses ioport accessors and it too is
converted in the end to a MMIO device, just like serial.

2. The patch is about refactoring the emulation callbacks, other (non-trivial)
changes should be a separate patch.

Please let me know if it's something that I'm missing. Other than this change, the
patch looks good.

Thanks,

Alex

>  
> +static void serial8250_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> +			    u8 is_write, void *ptr)
> +{
> +	struct serial8250_device *dev = ptr;
> +
> +	if (is_write)
> +		serial8250_out(dev, vcpu, addr - dev->iobase, *data);
> +	else
> +		serial8250_in(dev, vcpu, addr - dev->iobase, data);
> +}
> +
> +static bool serial8250_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
> +				  u16 port, void *data, int size)
> +{
> +	struct serial8250_device *dev = ioport->priv;
> +
> +	serial8250_mmio(vcpu, port, data, 1, true, dev);
> +
> +	return true;
> +}
> +
> +static bool serial8250_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
> +				 u16 port, void *data, int size)
> +{
> +	struct serial8250_device *dev = ioport->priv;
> +
> +	serial8250_mmio(vcpu, port, data, 1, false, dev);
> +
> +	return true;
> +}
> +
>  #ifdef CONFIG_HAS_LIBFDT
>  
>  char *fdt_stdout_path = NULL;
> @@ -427,8 +450,8 @@ void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
>  #endif
>  
>  static struct ioport_operations serial8250_ops = {
> -	.io_in			= serial8250_in,
> -	.io_out			= serial8250_out,
> +	.io_in			= serial8250_ioport_in,
> +	.io_out			= serial8250_ioport_out,
>  };
>  
>  static int serial8250__device_init(struct kvm *kvm,

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

* Re: [PATCH kvmtool v2 13/22] hw/serial: Refactor trap handler
@ 2021-03-12 11:29     ` Alexandru Elisei
  0 siblings, 0 replies; 88+ messages in thread
From: Alexandru Elisei @ 2021-03-12 11:29 UTC (permalink / raw)
  To: Andre Przywara, Will Deacon, Julien Thierry
  Cc: Marc Zyngier, Sami Mujawar, kvmarm, kvm

Hi Andre,

On 2/25/21 12:59 AM, Andre Przywara wrote:
> With the planned retirement of the special ioport emulation code, we
> need to provide an emulation function compatible with the MMIO prototype.
>
> Adjust the trap handler to use that new function, and provide shims to
> implement the old ioport interface, for now.
>
> We drop the usage of ioport__read8/write8 entirely, as this would only
> be applicable for I/O port accesses, and does nothing for 8-bit wide
> accesses anyway.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  hw/serial.c | 93 +++++++++++++++++++++++++++++++++--------------------
>  1 file changed, 58 insertions(+), 35 deletions(-)
>
> diff --git a/hw/serial.c b/hw/serial.c
> index b0465d99..c495eac1 100644
> --- a/hw/serial.c
> +++ b/hw/serial.c
> @@ -242,36 +242,31 @@ void serial8250__inject_sysrq(struct kvm *kvm, char sysrq)
>  	sysrq_pending = sysrq;
>  }
>  
> -static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port,
> -			   void *data, int size)
> +static bool serial8250_out(struct serial8250_device *dev, struct kvm_cpu *vcpu,
> +			   u16 offset, u8 data)
>  {
> -	struct serial8250_device *dev = ioport->priv;
> -	u16 offset;
>  	bool ret = true;
> -	char *addr = data;
>  
>  	mutex_lock(&dev->mutex);
>  
> -	offset = port - dev->iobase;
> -
>  	switch (offset) {
>  	case UART_TX:
>  		if (dev->lcr & UART_LCR_DLAB) {
> -			dev->dll = ioport__read8(data);
> +			dev->dll = data;
>  			break;
>  		}
>  
>  		/* Loopback mode */
>  		if (dev->mcr & UART_MCR_LOOP) {
>  			if (dev->rxcnt < FIFO_LEN) {
> -				dev->rxbuf[dev->rxcnt++] = *addr;
> +				dev->rxbuf[dev->rxcnt++] = data;
>  				dev->lsr |= UART_LSR_DR;
>  			}
>  			break;
>  		}
>  
>  		if (dev->txcnt < FIFO_LEN) {
> -			dev->txbuf[dev->txcnt++] = *addr;
> +			dev->txbuf[dev->txcnt++] = data;
>  			dev->lsr &= ~UART_LSR_TEMT;
>  			if (dev->txcnt == FIFO_LEN / 2)
>  				dev->lsr &= ~UART_LSR_THRE;
> @@ -283,18 +278,18 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
>  		break;
>  	case UART_IER:
>  		if (!(dev->lcr & UART_LCR_DLAB))
> -			dev->ier = ioport__read8(data) & 0x0f;
> +			dev->ier = data & 0x0f;
>  		else
> -			dev->dlm = ioport__read8(data);
> +			dev->dlm = data;
>  		break;
>  	case UART_FCR:
> -		dev->fcr = ioport__read8(data);
> +		dev->fcr = data;
>  		break;
>  	case UART_LCR:
> -		dev->lcr = ioport__read8(data);
> +		dev->lcr = data;
>  		break;
>  	case UART_MCR:
> -		dev->mcr = ioport__read8(data);
> +		dev->mcr = data;
>  		break;
>  	case UART_LSR:
>  		/* Factory test */
> @@ -303,7 +298,7 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
>  		/* Not used */
>  		break;
>  	case UART_SCR:
> -		dev->scr = ioport__read8(data);
> +		dev->scr = data;
>  		break;
>  	default:
>  		ret = false;
> @@ -317,7 +312,7 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
>  	return ret;
>  }
>  
> -static void serial8250_rx(struct serial8250_device *dev, void *data)
> +static void serial8250_rx(struct serial8250_device *dev, u8 *data)
>  {
>  	if (dev->rxdone == dev->rxcnt)
>  		return;
> @@ -325,57 +320,54 @@ static void serial8250_rx(struct serial8250_device *dev, void *data)
>  	/* Break issued ? */
>  	if (dev->lsr & UART_LSR_BI) {
>  		dev->lsr &= ~UART_LSR_BI;
> -		ioport__write8(data, 0);
> +		*data = 0;
>  		return;
>  	}
>  
> -	ioport__write8(data, dev->rxbuf[dev->rxdone++]);
> +	*data = dev->rxbuf[dev->rxdone++];
>  	if (dev->rxcnt == dev->rxdone) {
>  		dev->lsr &= ~UART_LSR_DR;
>  		dev->rxcnt = dev->rxdone = 0;
>  	}
>  }
>  
> -static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> +static bool serial8250_in(struct serial8250_device *dev, struct kvm_cpu *vcpu,
> +			  u16 offset, u8 *data)
>  {
> -	struct serial8250_device *dev = ioport->priv;
> -	u16 offset;
>  	bool ret = true;
>  
>  	mutex_lock(&dev->mutex);
>  
> -	offset = port - dev->iobase;
> -
>  	switch (offset) {
>  	case UART_RX:
>  		if (dev->lcr & UART_LCR_DLAB)
> -			ioport__write8(data, dev->dll);
> +			*data = dev->dll;
>  		else
>  			serial8250_rx(dev, data);
>  		break;
>  	case UART_IER:
>  		if (dev->lcr & UART_LCR_DLAB)
> -			ioport__write8(data, dev->dlm);
> +			*data = dev->dlm;
>  		else
> -			ioport__write8(data, dev->ier);
> +			*data = dev->ier;
>  		break;
>  	case UART_IIR:
> -		ioport__write8(data, dev->iir | UART_IIR_TYPE_BITS);
> +		*data = dev->iir | UART_IIR_TYPE_BITS;
>  		break;
>  	case UART_LCR:
> -		ioport__write8(data, dev->lcr);
> +		*data = dev->lcr;
>  		break;
>  	case UART_MCR:
> -		ioport__write8(data, dev->mcr);
> +		*data = dev->mcr;
>  		break;
>  	case UART_LSR:
> -		ioport__write8(data, dev->lsr);
> +		*data = dev->lsr;
>  		break;
>  	case UART_MSR:
> -		ioport__write8(data, dev->msr);
> +		*data = dev->msr;
>  		break;
>  	case UART_SCR:
> -		ioport__write8(data, dev->scr);
> +		*data = dev->scr;
>  		break;
>  	default:
>  		ret = false;
> @@ -389,6 +381,37 @@ static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port,
>  	return ret;
>  }

I'm not sure about replacing ioport_{read,write}8 with pointer dereferencing. They
are functionally equivalent because big-endian and little-endian are about the
order of bytes in memory, not the order of bits, but I don't think the change
makes much sense because:

1. All the other emulated devices use the ioport accessors, even in the case of 8
bit accesses. For example, the RTC device uses ioport accessors and it too is
converted in the end to a MMIO device, just like serial.

2. The patch is about refactoring the emulation callbacks, other (non-trivial)
changes should be a separate patch.

Please let me know if it's something that I'm missing. Other than this change, the
patch looks good.

Thanks,

Alex

>  
> +static void serial8250_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> +			    u8 is_write, void *ptr)
> +{
> +	struct serial8250_device *dev = ptr;
> +
> +	if (is_write)
> +		serial8250_out(dev, vcpu, addr - dev->iobase, *data);
> +	else
> +		serial8250_in(dev, vcpu, addr - dev->iobase, data);
> +}
> +
> +static bool serial8250_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
> +				  u16 port, void *data, int size)
> +{
> +	struct serial8250_device *dev = ioport->priv;
> +
> +	serial8250_mmio(vcpu, port, data, 1, true, dev);
> +
> +	return true;
> +}
> +
> +static bool serial8250_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
> +				 u16 port, void *data, int size)
> +{
> +	struct serial8250_device *dev = ioport->priv;
> +
> +	serial8250_mmio(vcpu, port, data, 1, false, dev);
> +
> +	return true;
> +}
> +
>  #ifdef CONFIG_HAS_LIBFDT
>  
>  char *fdt_stdout_path = NULL;
> @@ -427,8 +450,8 @@ void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
>  #endif
>  
>  static struct ioport_operations serial8250_ops = {
> -	.io_in			= serial8250_in,
> -	.io_out			= serial8250_out,
> +	.io_in			= serial8250_ioport_in,
> +	.io_out			= serial8250_ioport_out,
>  };
>  
>  static int serial8250__device_init(struct kvm *kvm,
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 04/22] mmio: Extend handling to include ioport emulation
  2021-03-03 17:58     ` Alexandru Elisei
@ 2021-03-15 12:24       ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-03-15 12:24 UTC (permalink / raw)
  To: Alexandru Elisei
  Cc: Will Deacon, Julien Thierry, kvm, kvmarm, Marc Zyngier, Sami Mujawar

On Wed, 3 Mar 2021 17:58:29 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

Hi Alex,

> On 2/25/21 12:58 AM, Andre Przywara wrote:
> > In their core functionality MMIO and I/O port traps are not really
> > different, yet we still have two totally separate code paths for
> > handling them. Devices need to decide on one conduit or need to provide
> > different handler functions for each of them.
> >
> > Extend the existing MMIO emulation to also cover ioport handlers.
> > This just adds another RB tree root for holding the I/O port handlers,
> > but otherwise uses the same tree population and lookup code.
> > "ioport" or "mmio" just become a flag in the registration function.
> > Provide wrappers to not break existing users, and allow an easy
> > transition for the existing ioport handlers.
> >
> > This also means that ioport handlers now can use the same emulation
> > callback prototype as MMIO handlers, which means we have to migrate them
> > over. To allow a smooth transition, we hook up the new I/O emulate
> > function to the end of the existing ioport emulation code.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> >  include/kvm/kvm.h | 49 ++++++++++++++++++++++++++++++++---
> >  ioport.c          |  4 +--
> >  mmio.c            | 65 +++++++++++++++++++++++++++++++++++++++--------
> >  3 files changed, 102 insertions(+), 16 deletions(-)
> >
> > diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
> > index f1f0afd7..306b258a 100644
> > --- a/include/kvm/kvm.h
> > +++ b/include/kvm/kvm.h
> > @@ -27,10 +27,23 @@
> >  #define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
> >  #endif
> >  
> > +/*
> > + * We are reusing the existing DEVICE_BUS_MMIO and DEVICE_BUS_IOPORT constants
> > + * from kvm/devices.h to differentiate between registering an I/O port and an
> > + * MMIO region.
> > + * To avoid collisions with future additions of more bus types, we reserve
> > + * a generous 4 bits for the bus mask here.
> > + */
> > +#define IOTRAP_BUS_MASK		0xf
> > +#define IOTRAP_COALESCE		(1U << 4)
> > +
> >  #define DEFINE_KVM_EXT(ext)		\
> >  	.name = #ext,			\
> >  	.code = ext
> >  
> > +struct kvm_cpu;
> > +typedef void (*mmio_handler_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> > +				u32 len, u8 is_write, void *ptr);
> >  typedef void (*fdt_irq_fn)(void *fdt, u8 irq, enum irq_type irq_type);
> >  
> >  enum {
> > @@ -113,6 +126,8 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
> >  void kvm__irq_trigger(struct kvm *kvm, int irq);
> >  bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count);
> >  bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write);
> > +bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
> > +		      int direction, int size, u32 count);
> >  int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr);
> >  int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr,
> >  		      enum kvm_mem_type type);
> > @@ -136,10 +151,36 @@ static inline int kvm__reserve_mem(struct kvm *kvm, u64 guest_phys, u64 size)
> >  				 KVM_MEM_TYPE_RESERVED);
> >  }
> >  
> > -int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
> > -				    void (*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
> > -				    void *ptr);
> > -bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
> > +int __must_check kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 len,
> > +				      mmio_handler_fn mmio_fn, void *ptr,
> > +				      unsigned int flags);
> > +
> > +static inline
> > +int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr,
> > +				    u64 phys_addr_len, bool coalesce,
> > +				    mmio_handler_fn mmio_fn, void *ptr)
> > +{
> > +	return kvm__register_iotrap(kvm, phys_addr, phys_addr_len, mmio_fn, ptr,
> > +			DEVICE_BUS_MMIO | (coalesce ? IOTRAP_COALESCE : 0));
> > +}
> > +static inline
> > +int __must_check kvm__register_pio(struct kvm *kvm, u16 port, u16 len,
> > +				   mmio_handler_fn mmio_fn, void *ptr)
> > +{
> > +	return kvm__register_iotrap(kvm, port, len, mmio_fn, ptr,
> > +				    DEVICE_BUS_IOPORT);
> > +}
> > +
> > +bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int flags);
> > +static inline bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
> > +{
> > +	return kvm__deregister_iotrap(kvm, phys_addr, DEVICE_BUS_MMIO);
> > +}
> > +static inline bool kvm__deregister_pio(struct kvm *kvm, u16 port)
> > +{
> > +	return kvm__deregister_iotrap(kvm, port, DEVICE_BUS_IOPORT);
> > +}
> > +
> >  void kvm__reboot(struct kvm *kvm);
> >  void kvm__pause(struct kvm *kvm);
> >  void kvm__continue(struct kvm *kvm);
> > diff --git a/ioport.c b/ioport.c
> > index e0123f27..ce29e7e7 100644
> > --- a/ioport.c
> > +++ b/ioport.c
> > @@ -162,7 +162,8 @@ bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction,
> >  
> >  	entry = ioport_get(&ioport_tree, port);
> >  	if (!entry)
> > -		goto out;
> > +		return kvm__emulate_pio(vcpu, port, data, direction,
> > +					size, count);
> >  
> >  	ops	= entry->ops;
> >  
> > @@ -177,7 +178,6 @@ bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction,
> >  
> >  	ioport_put(&ioport_tree, entry);
> >  
> > -out:
> >  	if (ret)
> >  		return true;
> >  
> > diff --git a/mmio.c b/mmio.c
> > index cd141cd3..75de04ad 100644
> > --- a/mmio.c
> > +++ b/mmio.c
> > @@ -19,13 +19,14 @@ static DEFINE_MUTEX(mmio_lock);
> >  
> >  struct mmio_mapping {
> >  	struct rb_int_node	node;
> > -	void			(*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr);
> > +	mmio_handler_fn		mmio_fn;
> >  	void			*ptr;
> >  	u32			refcount;
> >  	bool			remove;
> >  };
> >  
> >  static struct rb_root mmio_tree = RB_ROOT;
> > +static struct rb_root pio_tree = RB_ROOT;
> >  
> >  static struct mmio_mapping *mmio_search(struct rb_root *root, u64 addr, u64 len)
> >  {
> > @@ -103,9 +104,14 @@ static void mmio_put(struct kvm *kvm, struct rb_root *root, struct mmio_mapping
> >  	mutex_unlock(&mmio_lock);
> >  }
> >  
> > -int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
> > -		       void (*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
> > -			void *ptr)
> > +static bool trap_is_mmio(unsigned int flags)
> > +{
> > +	return (flags & IOTRAP_BUS_MASK) == DEVICE_BUS_MMIO;
> > +}
> > +
> > +int kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len,
> > +			 mmio_handler_fn mmio_fn, void *ptr,
> > +			 unsigned int flags)
> >  {
> >  	struct mmio_mapping *mmio;
> >  	struct kvm_coalesced_mmio_zone zone;
> > @@ -127,7 +133,7 @@ int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool c
> >  		.remove		= false,
> >  	};
> >  
> > -	if (coalesce) {
> > +	if (trap_is_mmio(flags) && (flags & IOTRAP_COALESCE)) {
> >  		zone = (struct kvm_coalesced_mmio_zone) {
> >  			.addr	= phys_addr,
> >  			.size	= phys_addr_len,
> > @@ -138,19 +144,29 @@ int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool c
> >  			return -errno;
> >  		}
> >  	}
> > +
> >  	mutex_lock(&mmio_lock);
> > -	ret = mmio_insert(&mmio_tree, mmio);
> > +	if (trap_is_mmio(flags))
> > +		ret = mmio_insert(&mmio_tree, mmio);
> > +	else
> > +		ret = mmio_insert(&pio_tree, mmio);
> >  	mutex_unlock(&mmio_lock);
> >  
> >  	return ret;
> >  }
> >  
> > -bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
> > +bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int flags)
> >  {
> >  	struct mmio_mapping *mmio;
> > +	struct rb_root *tree;
> > +
> > +	if ((flags & IOTRAP_BUS_MASK) == DEVICE_BUS_IOPORT)
> > +		tree = &pio_tree;
> > +	else
> > +		tree = &mmio_tree;  
> 
> We could swap the conditional branches and use trap_is_mmio(flags) like we do above.

Of course! Fixed that.

> Regardless, the patch looks really good:
> 
> Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks!
Andre

> >  
> >  	mutex_lock(&mmio_lock);
> > -	mmio = mmio_search_single(&mmio_tree, phys_addr);
> > +	mmio = mmio_search_single(tree, phys_addr);
> >  	if (mmio == NULL) {
> >  		mutex_unlock(&mmio_lock);
> >  		return false;
> > @@ -167,7 +183,7 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
> >  	 * called mmio_put(). This will trigger use-after-free errors on VCPU0.
> >  	 */
> >  	if (mmio->refcount == 0)
> > -		mmio_deregister(kvm, &mmio_tree, mmio);
> > +		mmio_deregister(kvm, tree, mmio);
> >  	else
> >  		mmio->remove = true;
> >  	mutex_unlock(&mmio_lock);
> > @@ -175,7 +191,8 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
> >  	return true;
> >  }
> >  
> > -bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write)
> > +bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data,
> > +		       u32 len, u8 is_write)
> >  {
> >  	struct mmio_mapping *mmio;
> >  
> > @@ -194,3 +211,31 @@ bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u
> >  out:
> >  	return true;
> >  }
> > +
> > +bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
> > +		     int direction, int size, u32 count)
> > +{
> > +	struct mmio_mapping *mmio;
> > +	bool is_write = direction == KVM_EXIT_IO_OUT;
> > +
> > +	mmio = mmio_get(&pio_tree, port, size);
> > +	if (!mmio) {
> > +		if (vcpu->kvm->cfg.ioport_debug) {
> > +			fprintf(stderr, "IO error: %s port=%x, size=%d, count=%u\n",
> > +				to_direction(direction), port, size, count);
> > +
> > +			return false;
> > +		}
> > +		return true;
> > +	}
> > +
> > +	while (count--) {
> > +		mmio->mmio_fn(vcpu, port, data, size, is_write, mmio->ptr);
> > +
> > +		data += size;
> > +	}
> > +
> > +	mmio_put(vcpu->kvm, &pio_tree, mmio);
> > +
> > +	return true;
> > +}  


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

* Re: [PATCH kvmtool v2 04/22] mmio: Extend handling to include ioport emulation
@ 2021-03-15 12:24       ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-03-15 12:24 UTC (permalink / raw)
  To: Alexandru Elisei; +Cc: kvm, Marc Zyngier, Sami Mujawar, Will Deacon, kvmarm

On Wed, 3 Mar 2021 17:58:29 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

Hi Alex,

> On 2/25/21 12:58 AM, Andre Przywara wrote:
> > In their core functionality MMIO and I/O port traps are not really
> > different, yet we still have two totally separate code paths for
> > handling them. Devices need to decide on one conduit or need to provide
> > different handler functions for each of them.
> >
> > Extend the existing MMIO emulation to also cover ioport handlers.
> > This just adds another RB tree root for holding the I/O port handlers,
> > but otherwise uses the same tree population and lookup code.
> > "ioport" or "mmio" just become a flag in the registration function.
> > Provide wrappers to not break existing users, and allow an easy
> > transition for the existing ioport handlers.
> >
> > This also means that ioport handlers now can use the same emulation
> > callback prototype as MMIO handlers, which means we have to migrate them
> > over. To allow a smooth transition, we hook up the new I/O emulate
> > function to the end of the existing ioport emulation code.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> >  include/kvm/kvm.h | 49 ++++++++++++++++++++++++++++++++---
> >  ioport.c          |  4 +--
> >  mmio.c            | 65 +++++++++++++++++++++++++++++++++++++++--------
> >  3 files changed, 102 insertions(+), 16 deletions(-)
> >
> > diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
> > index f1f0afd7..306b258a 100644
> > --- a/include/kvm/kvm.h
> > +++ b/include/kvm/kvm.h
> > @@ -27,10 +27,23 @@
> >  #define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
> >  #endif
> >  
> > +/*
> > + * We are reusing the existing DEVICE_BUS_MMIO and DEVICE_BUS_IOPORT constants
> > + * from kvm/devices.h to differentiate between registering an I/O port and an
> > + * MMIO region.
> > + * To avoid collisions with future additions of more bus types, we reserve
> > + * a generous 4 bits for the bus mask here.
> > + */
> > +#define IOTRAP_BUS_MASK		0xf
> > +#define IOTRAP_COALESCE		(1U << 4)
> > +
> >  #define DEFINE_KVM_EXT(ext)		\
> >  	.name = #ext,			\
> >  	.code = ext
> >  
> > +struct kvm_cpu;
> > +typedef void (*mmio_handler_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> > +				u32 len, u8 is_write, void *ptr);
> >  typedef void (*fdt_irq_fn)(void *fdt, u8 irq, enum irq_type irq_type);
> >  
> >  enum {
> > @@ -113,6 +126,8 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
> >  void kvm__irq_trigger(struct kvm *kvm, int irq);
> >  bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count);
> >  bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write);
> > +bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
> > +		      int direction, int size, u32 count);
> >  int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr);
> >  int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr,
> >  		      enum kvm_mem_type type);
> > @@ -136,10 +151,36 @@ static inline int kvm__reserve_mem(struct kvm *kvm, u64 guest_phys, u64 size)
> >  				 KVM_MEM_TYPE_RESERVED);
> >  }
> >  
> > -int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
> > -				    void (*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
> > -				    void *ptr);
> > -bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
> > +int __must_check kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 len,
> > +				      mmio_handler_fn mmio_fn, void *ptr,
> > +				      unsigned int flags);
> > +
> > +static inline
> > +int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr,
> > +				    u64 phys_addr_len, bool coalesce,
> > +				    mmio_handler_fn mmio_fn, void *ptr)
> > +{
> > +	return kvm__register_iotrap(kvm, phys_addr, phys_addr_len, mmio_fn, ptr,
> > +			DEVICE_BUS_MMIO | (coalesce ? IOTRAP_COALESCE : 0));
> > +}
> > +static inline
> > +int __must_check kvm__register_pio(struct kvm *kvm, u16 port, u16 len,
> > +				   mmio_handler_fn mmio_fn, void *ptr)
> > +{
> > +	return kvm__register_iotrap(kvm, port, len, mmio_fn, ptr,
> > +				    DEVICE_BUS_IOPORT);
> > +}
> > +
> > +bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int flags);
> > +static inline bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
> > +{
> > +	return kvm__deregister_iotrap(kvm, phys_addr, DEVICE_BUS_MMIO);
> > +}
> > +static inline bool kvm__deregister_pio(struct kvm *kvm, u16 port)
> > +{
> > +	return kvm__deregister_iotrap(kvm, port, DEVICE_BUS_IOPORT);
> > +}
> > +
> >  void kvm__reboot(struct kvm *kvm);
> >  void kvm__pause(struct kvm *kvm);
> >  void kvm__continue(struct kvm *kvm);
> > diff --git a/ioport.c b/ioport.c
> > index e0123f27..ce29e7e7 100644
> > --- a/ioport.c
> > +++ b/ioport.c
> > @@ -162,7 +162,8 @@ bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction,
> >  
> >  	entry = ioport_get(&ioport_tree, port);
> >  	if (!entry)
> > -		goto out;
> > +		return kvm__emulate_pio(vcpu, port, data, direction,
> > +					size, count);
> >  
> >  	ops	= entry->ops;
> >  
> > @@ -177,7 +178,6 @@ bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction,
> >  
> >  	ioport_put(&ioport_tree, entry);
> >  
> > -out:
> >  	if (ret)
> >  		return true;
> >  
> > diff --git a/mmio.c b/mmio.c
> > index cd141cd3..75de04ad 100644
> > --- a/mmio.c
> > +++ b/mmio.c
> > @@ -19,13 +19,14 @@ static DEFINE_MUTEX(mmio_lock);
> >  
> >  struct mmio_mapping {
> >  	struct rb_int_node	node;
> > -	void			(*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr);
> > +	mmio_handler_fn		mmio_fn;
> >  	void			*ptr;
> >  	u32			refcount;
> >  	bool			remove;
> >  };
> >  
> >  static struct rb_root mmio_tree = RB_ROOT;
> > +static struct rb_root pio_tree = RB_ROOT;
> >  
> >  static struct mmio_mapping *mmio_search(struct rb_root *root, u64 addr, u64 len)
> >  {
> > @@ -103,9 +104,14 @@ static void mmio_put(struct kvm *kvm, struct rb_root *root, struct mmio_mapping
> >  	mutex_unlock(&mmio_lock);
> >  }
> >  
> > -int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
> > -		       void (*mmio_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
> > -			void *ptr)
> > +static bool trap_is_mmio(unsigned int flags)
> > +{
> > +	return (flags & IOTRAP_BUS_MASK) == DEVICE_BUS_MMIO;
> > +}
> > +
> > +int kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len,
> > +			 mmio_handler_fn mmio_fn, void *ptr,
> > +			 unsigned int flags)
> >  {
> >  	struct mmio_mapping *mmio;
> >  	struct kvm_coalesced_mmio_zone zone;
> > @@ -127,7 +133,7 @@ int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool c
> >  		.remove		= false,
> >  	};
> >  
> > -	if (coalesce) {
> > +	if (trap_is_mmio(flags) && (flags & IOTRAP_COALESCE)) {
> >  		zone = (struct kvm_coalesced_mmio_zone) {
> >  			.addr	= phys_addr,
> >  			.size	= phys_addr_len,
> > @@ -138,19 +144,29 @@ int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool c
> >  			return -errno;
> >  		}
> >  	}
> > +
> >  	mutex_lock(&mmio_lock);
> > -	ret = mmio_insert(&mmio_tree, mmio);
> > +	if (trap_is_mmio(flags))
> > +		ret = mmio_insert(&mmio_tree, mmio);
> > +	else
> > +		ret = mmio_insert(&pio_tree, mmio);
> >  	mutex_unlock(&mmio_lock);
> >  
> >  	return ret;
> >  }
> >  
> > -bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
> > +bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int flags)
> >  {
> >  	struct mmio_mapping *mmio;
> > +	struct rb_root *tree;
> > +
> > +	if ((flags & IOTRAP_BUS_MASK) == DEVICE_BUS_IOPORT)
> > +		tree = &pio_tree;
> > +	else
> > +		tree = &mmio_tree;  
> 
> We could swap the conditional branches and use trap_is_mmio(flags) like we do above.

Of course! Fixed that.

> Regardless, the patch looks really good:
> 
> Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks!
Andre

> >  
> >  	mutex_lock(&mmio_lock);
> > -	mmio = mmio_search_single(&mmio_tree, phys_addr);
> > +	mmio = mmio_search_single(tree, phys_addr);
> >  	if (mmio == NULL) {
> >  		mutex_unlock(&mmio_lock);
> >  		return false;
> > @@ -167,7 +183,7 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
> >  	 * called mmio_put(). This will trigger use-after-free errors on VCPU0.
> >  	 */
> >  	if (mmio->refcount == 0)
> > -		mmio_deregister(kvm, &mmio_tree, mmio);
> > +		mmio_deregister(kvm, tree, mmio);
> >  	else
> >  		mmio->remove = true;
> >  	mutex_unlock(&mmio_lock);
> > @@ -175,7 +191,8 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
> >  	return true;
> >  }
> >  
> > -bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write)
> > +bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data,
> > +		       u32 len, u8 is_write)
> >  {
> >  	struct mmio_mapping *mmio;
> >  
> > @@ -194,3 +211,31 @@ bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u
> >  out:
> >  	return true;
> >  }
> > +
> > +bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
> > +		     int direction, int size, u32 count)
> > +{
> > +	struct mmio_mapping *mmio;
> > +	bool is_write = direction == KVM_EXIT_IO_OUT;
> > +
> > +	mmio = mmio_get(&pio_tree, port, size);
> > +	if (!mmio) {
> > +		if (vcpu->kvm->cfg.ioport_debug) {
> > +			fprintf(stderr, "IO error: %s port=%x, size=%d, count=%u\n",
> > +				to_direction(direction), port, size, count);
> > +
> > +			return false;
> > +		}
> > +		return true;
> > +	}
> > +
> > +	while (count--) {
> > +		mmio->mmio_fn(vcpu, port, data, size, is_write, mmio->ptr);
> > +
> > +		data += size;
> > +	}
> > +
> > +	mmio_put(vcpu->kvm, &pio_tree, mmio);
> > +
> > +	return true;
> > +}  

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 08/22] x86/ioport: Refactor trap handlers
  2021-03-09 11:49     ` Alexandru Elisei
@ 2021-03-15 12:26       ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-03-15 12:26 UTC (permalink / raw)
  To: Alexandru Elisei
  Cc: Will Deacon, Julien Thierry, kvm, kvmarm, Marc Zyngier, Sami Mujawar

On Tue, 9 Mar 2021 11:49:47 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

> Hi Andre,
> 
> Regarding the naming of the functions, these are real ioport emulation functions,
> which are executed because a KVM_EXIT_IO exit reason from KVM_RUN. Wouldn't naming
> the functions something like *_pio or *_io be more appropriate?

Yes, indeed these devices here are per definition pure port I/O
devices. I changed the names to _io, to be in line with the later
patches.

Cheers,
Andre
 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > With the planned retirement of the special ioport emulation code, we
> > need to provide emulation functions compatible with the MMIO
> > prototype.
> >
> > Adjust the trap handlers to use that new function, and provide shims to
> > implement the old ioport interface, for now.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
> > ---
> >  x86/ioport.c | 30 ++++++++++++++++++++++++++----
> >  1 file changed, 26 insertions(+), 4 deletions(-)
> >
> > diff --git a/x86/ioport.c b/x86/ioport.c
> > index a8d2bb1a..78f9a863 100644
> > --- a/x86/ioport.c
> > +++ b/x86/ioport.c
> > @@ -3,8 +3,14 @@
> >  #include <stdlib.h>
> >  #include <stdio.h>
> >  
> > +static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> > +		       u8 is_write, void *ptr)
> > +{
> > +}
> > +
> >  static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> >  {
> > +	dummy_mmio(vcpu, port, data, size, true, NULL);
> >  	return 0;
> >  }
> >  
> > @@ -12,15 +18,23 @@ static struct ioport_operations debug_ops = {
> >  	.io_out		= debug_io_out,
> >  };
> >  
> > -static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > +static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> > +			       u32 len, u8 is_write, void *ptr)
> >  {
> >  	char ch;
> >  
> > +	if (!is_write)
> > +		return;
> > +
> >  	ch = ioport__read8(data);
> >  
> >  	putchar(ch);
> > +}
> >  
> > -	return true;
> > +static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > +{
> > +	seabios_debug_mmio(vcpu, port, data, size, true, NULL);
> > +	return 0;
> >  }
> >  
> >  static struct ioport_operations seabios_debug_ops = {
> > @@ -29,11 +43,13 @@ static struct ioport_operations seabios_debug_ops = {
> >  
> >  static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> >  {
> > +	dummy_mmio(vcpu, port, data, size, false, NULL);
> >  	return true;
> >  }
> >  
> >  static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> >  {
> > +	dummy_mmio(vcpu, port, data, size, true, NULL);
> >  	return true;
> >  }
> >  
> > @@ -50,13 +66,19 @@ static struct ioport_operations dummy_write_only_ioport_ops = {
> >   * The "fast A20 gate"
> >   */
> >  
> > -static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > +static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> > +			     u8 is_write, void *ptr)
> >  {
> >  	/*
> >  	 * A20 is always enabled.
> >  	 */
> > -	ioport__write8(data, 0x02);
> > +	if (!is_write)
> > +		ioport__write8(data, 0x02);
> > +}
> >  
> > +static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > +{
> > +	ps2_control_mmio(vcpu, port, data, size, false, NULL);
> >  	return true;
> >  }
> >    


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

* Re: [PATCH kvmtool v2 08/22] x86/ioport: Refactor trap handlers
@ 2021-03-15 12:26       ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-03-15 12:26 UTC (permalink / raw)
  To: Alexandru Elisei; +Cc: kvm, Marc Zyngier, Sami Mujawar, Will Deacon, kvmarm

On Tue, 9 Mar 2021 11:49:47 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

> Hi Andre,
> 
> Regarding the naming of the functions, these are real ioport emulation functions,
> which are executed because a KVM_EXIT_IO exit reason from KVM_RUN. Wouldn't naming
> the functions something like *_pio or *_io be more appropriate?

Yes, indeed these devices here are per definition pure port I/O
devices. I changed the names to _io, to be in line with the later
patches.

Cheers,
Andre
 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > With the planned retirement of the special ioport emulation code, we
> > need to provide emulation functions compatible with the MMIO
> > prototype.
> >
> > Adjust the trap handlers to use that new function, and provide shims to
> > implement the old ioport interface, for now.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
> > ---
> >  x86/ioport.c | 30 ++++++++++++++++++++++++++----
> >  1 file changed, 26 insertions(+), 4 deletions(-)
> >
> > diff --git a/x86/ioport.c b/x86/ioport.c
> > index a8d2bb1a..78f9a863 100644
> > --- a/x86/ioport.c
> > +++ b/x86/ioport.c
> > @@ -3,8 +3,14 @@
> >  #include <stdlib.h>
> >  #include <stdio.h>
> >  
> > +static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> > +		       u8 is_write, void *ptr)
> > +{
> > +}
> > +
> >  static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> >  {
> > +	dummy_mmio(vcpu, port, data, size, true, NULL);
> >  	return 0;
> >  }
> >  
> > @@ -12,15 +18,23 @@ static struct ioport_operations debug_ops = {
> >  	.io_out		= debug_io_out,
> >  };
> >  
> > -static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > +static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> > +			       u32 len, u8 is_write, void *ptr)
> >  {
> >  	char ch;
> >  
> > +	if (!is_write)
> > +		return;
> > +
> >  	ch = ioport__read8(data);
> >  
> >  	putchar(ch);
> > +}
> >  
> > -	return true;
> > +static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > +{
> > +	seabios_debug_mmio(vcpu, port, data, size, true, NULL);
> > +	return 0;
> >  }
> >  
> >  static struct ioport_operations seabios_debug_ops = {
> > @@ -29,11 +43,13 @@ static struct ioport_operations seabios_debug_ops = {
> >  
> >  static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> >  {
> > +	dummy_mmio(vcpu, port, data, size, false, NULL);
> >  	return true;
> >  }
> >  
> >  static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> >  {
> > +	dummy_mmio(vcpu, port, data, size, true, NULL);
> >  	return true;
> >  }
> >  
> > @@ -50,13 +66,19 @@ static struct ioport_operations dummy_write_only_ioport_ops = {
> >   * The "fast A20 gate"
> >   */
> >  
> > -static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > +static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> > +			     u8 is_write, void *ptr)
> >  {
> >  	/*
> >  	 * A20 is always enabled.
> >  	 */
> > -	ioport__write8(data, 0x02);
> > +	if (!is_write)
> > +		ioport__write8(data, 0x02);
> > +}
> >  
> > +static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > +{
> > +	ps2_control_mmio(vcpu, port, data, size, false, NULL);
> >  	return true;
> >  }
> >    

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 09/22] x86/ioport: Switch to new trap handlers
  2021-03-09 12:09     ` Alexandru Elisei
@ 2021-03-15 12:26       ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-03-15 12:26 UTC (permalink / raw)
  To: Alexandru Elisei
  Cc: Will Deacon, Julien Thierry, kvm, kvmarm, Marc Zyngier, Sami Mujawar

On Tue, 9 Mar 2021 12:09:52 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

> Hi Andre,
> 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > Now that the x86 I/O ports have trap handlers adhering to the MMIO fault
> > handler prototype, let's switch over to the joint registration routine.
> >
> > This allows us to get rid of the ioport shim routines.
> >
> > Since the debug output was done in ioport.c, we would lose this
> > functionality when moving over to the MMIO handlers. So bring this back
> > here explicitly, by introducing debug_mmio().
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> >  x86/ioport.c | 102 +++++++++++++++++++--------------------------------
> >  1 file changed, 37 insertions(+), 65 deletions(-)
> >
> > diff --git a/x86/ioport.c b/x86/ioport.c
> > index 78f9a863..9fcbb6c9 100644
> > --- a/x86/ioport.c
> > +++ b/x86/ioport.c
> > @@ -3,21 +3,35 @@
> >  #include <stdlib.h>
> >  #include <stdio.h>
> >  
> > -static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> > +static void debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> >  		       u8 is_write, void *ptr)  
> 
> Since the function is about ioports (it even checks cfg.ioport_debug), shouldn't
> something like debug_io/debug_pio/debug_ioport/<something else ioport related> be
> more appropriate?

Yes, I changed the function to debug_io(), to be in line with the other
functions and the names in the other devices.

> Otherwise looks good: the only emulation callback that could fail was
> debug_ops->debug_io_out, which triggered a print if cfg.ioport_debug was set, and
> the callback is replaced by debug_mmio. With the name change:
> 
> Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks!

Andre

> >  {
> > +	if (!vcpu->kvm->cfg.ioport_debug)
> > +		return;
> > +
> > +	fprintf(stderr, "debug port %s from VCPU%lu: port=0x%lx, size=%u",
> > +		is_write ? "write" : "read", vcpu->cpu_id,
> > +		(unsigned long)addr, len);
> > +	if (is_write) {
> > +		u32 value;
> > +
> > +		switch (len) {
> > +		case 1: value = ioport__read8(data); break;
> > +		case 2: value = ioport__read16((u16*)data); break;
> > +		case 4: value = ioport__read32((u32*)data); break;
> > +		default: value = 0; break;
> > +		}
> > +		fprintf(stderr, ", data: 0x%x\n", value);
> > +	} else {
> > +		fprintf(stderr, "\n");
> > +	}
> >  }
> >  
> > -static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > +static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> > +		       u8 is_write, void *ptr)
> >  {
> > -	dummy_mmio(vcpu, port, data, size, true, NULL);
> > -	return 0;
> >  }
> >  
> > -static struct ioport_operations debug_ops = {
> > -	.io_out		= debug_io_out,
> > -};
> > -
> >  static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> >  			       u32 len, u8 is_write, void *ptr)
> >  {
> > @@ -31,37 +45,6 @@ static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> >  	putchar(ch);
> >  }
> >  
> > -static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > -{
> > -	seabios_debug_mmio(vcpu, port, data, size, true, NULL);
> > -	return 0;
> > -}
> > -
> > -static struct ioport_operations seabios_debug_ops = {
> > -	.io_out		= seabios_debug_io_out,
> > -};
> > -
> > -static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > -{
> > -	dummy_mmio(vcpu, port, data, size, false, NULL);
> > -	return true;
> > -}
> > -
> > -static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > -{
> > -	dummy_mmio(vcpu, port, data, size, true, NULL);
> > -	return true;
> > -}
> > -
> > -static struct ioport_operations dummy_read_write_ioport_ops = {
> > -	.io_in		= dummy_io_in,
> > -	.io_out		= dummy_io_out,
> > -};
> > -
> > -static struct ioport_operations dummy_write_only_ioport_ops = {
> > -	.io_out		= dummy_io_out,
> > -};
> > -
> >  /*
> >   * The "fast A20 gate"
> >   */
> > @@ -76,17 +59,6 @@ static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> >  		ioport__write8(data, 0x02);
> >  }
> >  
> > -static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > -{
> > -	ps2_control_mmio(vcpu, port, data, size, false, NULL);
> > -	return true;
> > -}
> > -
> > -static struct ioport_operations ps2_control_a_ops = {
> > -	.io_in		= ps2_control_a_io_in,
> > -	.io_out		= dummy_io_out,
> > -};
> > -
> >  void ioport__map_irq(u8 *irq)
> >  {
> >  }
> > @@ -98,75 +70,75 @@ static int ioport__setup_arch(struct kvm *kvm)
> >  	/* Legacy ioport setup */
> >  
> >  	/* 0000 - 001F - DMA1 controller */
> > -	r = ioport__register(kvm, 0x0000, &dummy_read_write_ioport_ops, 32, NULL);
> > +	r = kvm__register_pio(kvm, 0x0000, 32, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* 0x0020 - 0x003F - 8259A PIC 1 */
> > -	r = ioport__register(kvm, 0x0020, &dummy_read_write_ioport_ops, 2, NULL);
> > +	r = kvm__register_pio(kvm, 0x0020, 2, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
> > -	r = ioport__register(kvm, 0x0040, &dummy_read_write_ioport_ops, 4, NULL);
> > +	r = kvm__register_pio(kvm, 0x0040, 4, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* 0092 - PS/2 system control port A */
> > -	r = ioport__register(kvm, 0x0092, &ps2_control_a_ops, 1, NULL);
> > +	r = kvm__register_pio(kvm, 0x0092, 1, ps2_control_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* 0x00A0 - 0x00AF - 8259A PIC 2 */
> > -	r = ioport__register(kvm, 0x00A0, &dummy_read_write_ioport_ops, 2, NULL);
> > +	r = kvm__register_pio(kvm, 0x00A0, 2, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* 00C0 - 001F - DMA2 controller */
> > -	r = ioport__register(kvm, 0x00C0, &dummy_read_write_ioport_ops, 32, NULL);
> > +	r = kvm__register_pio(kvm, 0x00c0, 32, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* PORT 00E0-00EF are 'motherboard specific' so we use them for our
> >  	   internal debugging purposes.  */
> > -	r = ioport__register(kvm, IOPORT_DBG, &debug_ops, 1, NULL);
> > +	r = kvm__register_pio(kvm, IOPORT_DBG, 1, debug_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* PORT 00ED - DUMMY PORT FOR DELAY??? */
> > -	r = ioport__register(kvm, 0x00ED, &dummy_write_only_ioport_ops, 1, NULL);
> > +	r = kvm__register_pio(kvm, 0x00ed, 1, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* 0x00F0 - 0x00FF - Math co-processor */
> > -	r = ioport__register(kvm, 0x00F0, &dummy_write_only_ioport_ops, 2, NULL);
> > +	r = kvm__register_pio(kvm, 0x00f0, 2, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* PORT 0278-027A - PARALLEL PRINTER PORT (usually LPT1, sometimes LPT2) */
> > -	r = ioport__register(kvm, 0x0278, &dummy_read_write_ioport_ops, 3, NULL);
> > +	r = kvm__register_pio(kvm, 0x0278, 3, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* PORT 0378-037A - PARALLEL PRINTER PORT (usually LPT2, sometimes LPT3) */
> > -	r = ioport__register(kvm, 0x0378, &dummy_read_write_ioport_ops, 3, NULL);
> > +	r = kvm__register_pio(kvm, 0x0378, 3, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
> > -	r = ioport__register(kvm, 0x03D4, &dummy_read_write_ioport_ops, 1, NULL);
> > +	r = kvm__register_pio(kvm, 0x03d4, 1, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> > -	r = ioport__register(kvm, 0x03D5, &dummy_write_only_ioport_ops, 1, NULL);
> > +	r = kvm__register_pio(kvm, 0x03d5, 1, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> > -	r = ioport__register(kvm, 0x402, &seabios_debug_ops, 1, NULL);
> > +	r = kvm__register_pio(kvm, 0x0402, 1, seabios_debug_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* 0510 - QEMU BIOS configuration register */
> > -	r = ioport__register(kvm, 0x510, &dummy_read_write_ioport_ops, 2, NULL);
> > +	r = kvm__register_pio(kvm, 0x0510, 2, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >    


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

* Re: [PATCH kvmtool v2 09/22] x86/ioport: Switch to new trap handlers
@ 2021-03-15 12:26       ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-03-15 12:26 UTC (permalink / raw)
  To: Alexandru Elisei; +Cc: kvm, Marc Zyngier, Sami Mujawar, Will Deacon, kvmarm

On Tue, 9 Mar 2021 12:09:52 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

> Hi Andre,
> 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > Now that the x86 I/O ports have trap handlers adhering to the MMIO fault
> > handler prototype, let's switch over to the joint registration routine.
> >
> > This allows us to get rid of the ioport shim routines.
> >
> > Since the debug output was done in ioport.c, we would lose this
> > functionality when moving over to the MMIO handlers. So bring this back
> > here explicitly, by introducing debug_mmio().
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> >  x86/ioport.c | 102 +++++++++++++++++++--------------------------------
> >  1 file changed, 37 insertions(+), 65 deletions(-)
> >
> > diff --git a/x86/ioport.c b/x86/ioport.c
> > index 78f9a863..9fcbb6c9 100644
> > --- a/x86/ioport.c
> > +++ b/x86/ioport.c
> > @@ -3,21 +3,35 @@
> >  #include <stdlib.h>
> >  #include <stdio.h>
> >  
> > -static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> > +static void debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> >  		       u8 is_write, void *ptr)  
> 
> Since the function is about ioports (it even checks cfg.ioport_debug), shouldn't
> something like debug_io/debug_pio/debug_ioport/<something else ioport related> be
> more appropriate?

Yes, I changed the function to debug_io(), to be in line with the other
functions and the names in the other devices.

> Otherwise looks good: the only emulation callback that could fail was
> debug_ops->debug_io_out, which triggered a print if cfg.ioport_debug was set, and
> the callback is replaced by debug_mmio. With the name change:
> 
> Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks!

Andre

> >  {
> > +	if (!vcpu->kvm->cfg.ioport_debug)
> > +		return;
> > +
> > +	fprintf(stderr, "debug port %s from VCPU%lu: port=0x%lx, size=%u",
> > +		is_write ? "write" : "read", vcpu->cpu_id,
> > +		(unsigned long)addr, len);
> > +	if (is_write) {
> > +		u32 value;
> > +
> > +		switch (len) {
> > +		case 1: value = ioport__read8(data); break;
> > +		case 2: value = ioport__read16((u16*)data); break;
> > +		case 4: value = ioport__read32((u32*)data); break;
> > +		default: value = 0; break;
> > +		}
> > +		fprintf(stderr, ", data: 0x%x\n", value);
> > +	} else {
> > +		fprintf(stderr, "\n");
> > +	}
> >  }
> >  
> > -static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > +static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> > +		       u8 is_write, void *ptr)
> >  {
> > -	dummy_mmio(vcpu, port, data, size, true, NULL);
> > -	return 0;
> >  }
> >  
> > -static struct ioport_operations debug_ops = {
> > -	.io_out		= debug_io_out,
> > -};
> > -
> >  static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> >  			       u32 len, u8 is_write, void *ptr)
> >  {
> > @@ -31,37 +45,6 @@ static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> >  	putchar(ch);
> >  }
> >  
> > -static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > -{
> > -	seabios_debug_mmio(vcpu, port, data, size, true, NULL);
> > -	return 0;
> > -}
> > -
> > -static struct ioport_operations seabios_debug_ops = {
> > -	.io_out		= seabios_debug_io_out,
> > -};
> > -
> > -static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > -{
> > -	dummy_mmio(vcpu, port, data, size, false, NULL);
> > -	return true;
> > -}
> > -
> > -static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > -{
> > -	dummy_mmio(vcpu, port, data, size, true, NULL);
> > -	return true;
> > -}
> > -
> > -static struct ioport_operations dummy_read_write_ioport_ops = {
> > -	.io_in		= dummy_io_in,
> > -	.io_out		= dummy_io_out,
> > -};
> > -
> > -static struct ioport_operations dummy_write_only_ioport_ops = {
> > -	.io_out		= dummy_io_out,
> > -};
> > -
> >  /*
> >   * The "fast A20 gate"
> >   */
> > @@ -76,17 +59,6 @@ static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> >  		ioport__write8(data, 0x02);
> >  }
> >  
> > -static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > -{
> > -	ps2_control_mmio(vcpu, port, data, size, false, NULL);
> > -	return true;
> > -}
> > -
> > -static struct ioport_operations ps2_control_a_ops = {
> > -	.io_in		= ps2_control_a_io_in,
> > -	.io_out		= dummy_io_out,
> > -};
> > -
> >  void ioport__map_irq(u8 *irq)
> >  {
> >  }
> > @@ -98,75 +70,75 @@ static int ioport__setup_arch(struct kvm *kvm)
> >  	/* Legacy ioport setup */
> >  
> >  	/* 0000 - 001F - DMA1 controller */
> > -	r = ioport__register(kvm, 0x0000, &dummy_read_write_ioport_ops, 32, NULL);
> > +	r = kvm__register_pio(kvm, 0x0000, 32, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* 0x0020 - 0x003F - 8259A PIC 1 */
> > -	r = ioport__register(kvm, 0x0020, &dummy_read_write_ioport_ops, 2, NULL);
> > +	r = kvm__register_pio(kvm, 0x0020, 2, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
> > -	r = ioport__register(kvm, 0x0040, &dummy_read_write_ioport_ops, 4, NULL);
> > +	r = kvm__register_pio(kvm, 0x0040, 4, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* 0092 - PS/2 system control port A */
> > -	r = ioport__register(kvm, 0x0092, &ps2_control_a_ops, 1, NULL);
> > +	r = kvm__register_pio(kvm, 0x0092, 1, ps2_control_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* 0x00A0 - 0x00AF - 8259A PIC 2 */
> > -	r = ioport__register(kvm, 0x00A0, &dummy_read_write_ioport_ops, 2, NULL);
> > +	r = kvm__register_pio(kvm, 0x00A0, 2, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* 00C0 - 001F - DMA2 controller */
> > -	r = ioport__register(kvm, 0x00C0, &dummy_read_write_ioport_ops, 32, NULL);
> > +	r = kvm__register_pio(kvm, 0x00c0, 32, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* PORT 00E0-00EF are 'motherboard specific' so we use them for our
> >  	   internal debugging purposes.  */
> > -	r = ioport__register(kvm, IOPORT_DBG, &debug_ops, 1, NULL);
> > +	r = kvm__register_pio(kvm, IOPORT_DBG, 1, debug_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* PORT 00ED - DUMMY PORT FOR DELAY??? */
> > -	r = ioport__register(kvm, 0x00ED, &dummy_write_only_ioport_ops, 1, NULL);
> > +	r = kvm__register_pio(kvm, 0x00ed, 1, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* 0x00F0 - 0x00FF - Math co-processor */
> > -	r = ioport__register(kvm, 0x00F0, &dummy_write_only_ioport_ops, 2, NULL);
> > +	r = kvm__register_pio(kvm, 0x00f0, 2, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* PORT 0278-027A - PARALLEL PRINTER PORT (usually LPT1, sometimes LPT2) */
> > -	r = ioport__register(kvm, 0x0278, &dummy_read_write_ioport_ops, 3, NULL);
> > +	r = kvm__register_pio(kvm, 0x0278, 3, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* PORT 0378-037A - PARALLEL PRINTER PORT (usually LPT2, sometimes LPT3) */
> > -	r = ioport__register(kvm, 0x0378, &dummy_read_write_ioport_ops, 3, NULL);
> > +	r = kvm__register_pio(kvm, 0x0378, 3, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
> > -	r = ioport__register(kvm, 0x03D4, &dummy_read_write_ioport_ops, 1, NULL);
> > +	r = kvm__register_pio(kvm, 0x03d4, 1, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> > -	r = ioport__register(kvm, 0x03D5, &dummy_write_only_ioport_ops, 1, NULL);
> > +	r = kvm__register_pio(kvm, 0x03d5, 1, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> > -	r = ioport__register(kvm, 0x402, &seabios_debug_ops, 1, NULL);
> > +	r = kvm__register_pio(kvm, 0x0402, 1, seabios_debug_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >  
> >  	/* 0510 - QEMU BIOS configuration register */
> > -	r = ioport__register(kvm, 0x510, &dummy_read_write_ioport_ops, 2, NULL);
> > +	r = kvm__register_pio(kvm, 0x0510, 2, dummy_mmio, NULL);
> >  	if (r < 0)
> >  		return r;
> >    

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 13/22] hw/serial: Refactor trap handler
  2021-03-12 11:29     ` Alexandru Elisei
@ 2021-03-15 12:26       ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-03-15 12:26 UTC (permalink / raw)
  To: Alexandru Elisei
  Cc: Will Deacon, Julien Thierry, kvm, kvmarm, Marc Zyngier, Sami Mujawar

On Fri, 12 Mar 2021 11:29:43 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

> Hi Andre,
> 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > With the planned retirement of the special ioport emulation code, we
> > need to provide an emulation function compatible with the MMIO prototype.
> >
> > Adjust the trap handler to use that new function, and provide shims to
> > implement the old ioport interface, for now.
> >
> > We drop the usage of ioport__read8/write8 entirely, as this would only
> > be applicable for I/O port accesses, and does nothing for 8-bit wide
> > accesses anyway.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> >  hw/serial.c | 93 +++++++++++++++++++++++++++++++++--------------------
> >  1 file changed, 58 insertions(+), 35 deletions(-)
> >
> > diff --git a/hw/serial.c b/hw/serial.c
> > index b0465d99..c495eac1 100644
> > --- a/hw/serial.c
> > +++ b/hw/serial.c
> > @@ -242,36 +242,31 @@ void serial8250__inject_sysrq(struct kvm *kvm, char sysrq)
> >  	sysrq_pending = sysrq;
> >  }
> >  
> > -static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port,
> > -			   void *data, int size)
> > +static bool serial8250_out(struct serial8250_device *dev, struct kvm_cpu *vcpu,
> > +			   u16 offset, u8 data)
> >  {
> > -	struct serial8250_device *dev = ioport->priv;
> > -	u16 offset;
> >  	bool ret = true;
> > -	char *addr = data;
> >  
> >  	mutex_lock(&dev->mutex);
> >  
> > -	offset = port - dev->iobase;
> > -
> >  	switch (offset) {
> >  	case UART_TX:
> >  		if (dev->lcr & UART_LCR_DLAB) {
> > -			dev->dll = ioport__read8(data);
> > +			dev->dll = data;
> >  			break;
> >  		}
> >  
> >  		/* Loopback mode */
> >  		if (dev->mcr & UART_MCR_LOOP) {
> >  			if (dev->rxcnt < FIFO_LEN) {
> > -				dev->rxbuf[dev->rxcnt++] = *addr;
> > +				dev->rxbuf[dev->rxcnt++] = data;
> >  				dev->lsr |= UART_LSR_DR;
> >  			}
> >  			break;
> >  		}
> >  
> >  		if (dev->txcnt < FIFO_LEN) {
> > -			dev->txbuf[dev->txcnt++] = *addr;
> > +			dev->txbuf[dev->txcnt++] = data;
> >  			dev->lsr &= ~UART_LSR_TEMT;
> >  			if (dev->txcnt == FIFO_LEN / 2)
> >  				dev->lsr &= ~UART_LSR_THRE;
> > @@ -283,18 +278,18 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
> >  		break;
> >  	case UART_IER:
> >  		if (!(dev->lcr & UART_LCR_DLAB))
> > -			dev->ier = ioport__read8(data) & 0x0f;
> > +			dev->ier = data & 0x0f;
> >  		else
> > -			dev->dlm = ioport__read8(data);
> > +			dev->dlm = data;
> >  		break;
> >  	case UART_FCR:
> > -		dev->fcr = ioport__read8(data);
> > +		dev->fcr = data;
> >  		break;
> >  	case UART_LCR:
> > -		dev->lcr = ioport__read8(data);
> > +		dev->lcr = data;
> >  		break;
> >  	case UART_MCR:
> > -		dev->mcr = ioport__read8(data);
> > +		dev->mcr = data;
> >  		break;
> >  	case UART_LSR:
> >  		/* Factory test */
> > @@ -303,7 +298,7 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
> >  		/* Not used */
> >  		break;
> >  	case UART_SCR:
> > -		dev->scr = ioport__read8(data);
> > +		dev->scr = data;
> >  		break;
> >  	default:
> >  		ret = false;
> > @@ -317,7 +312,7 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
> >  	return ret;
> >  }
> >  
> > -static void serial8250_rx(struct serial8250_device *dev, void *data)
> > +static void serial8250_rx(struct serial8250_device *dev, u8 *data)
> >  {
> >  	if (dev->rxdone == dev->rxcnt)
> >  		return;
> > @@ -325,57 +320,54 @@ static void serial8250_rx(struct serial8250_device *dev, void *data)
> >  	/* Break issued ? */
> >  	if (dev->lsr & UART_LSR_BI) {
> >  		dev->lsr &= ~UART_LSR_BI;
> > -		ioport__write8(data, 0);
> > +		*data = 0;
> >  		return;
> >  	}
> >  
> > -	ioport__write8(data, dev->rxbuf[dev->rxdone++]);
> > +	*data = dev->rxbuf[dev->rxdone++];
> >  	if (dev->rxcnt == dev->rxdone) {
> >  		dev->lsr &= ~UART_LSR_DR;
> >  		dev->rxcnt = dev->rxdone = 0;
> >  	}
> >  }
> >  
> > -static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > +static bool serial8250_in(struct serial8250_device *dev, struct kvm_cpu *vcpu,
> > +			  u16 offset, u8 *data)
> >  {
> > -	struct serial8250_device *dev = ioport->priv;
> > -	u16 offset;
> >  	bool ret = true;
> >  
> >  	mutex_lock(&dev->mutex);
> >  
> > -	offset = port - dev->iobase;
> > -
> >  	switch (offset) {
> >  	case UART_RX:
> >  		if (dev->lcr & UART_LCR_DLAB)
> > -			ioport__write8(data, dev->dll);
> > +			*data = dev->dll;
> >  		else
> >  			serial8250_rx(dev, data);
> >  		break;
> >  	case UART_IER:
> >  		if (dev->lcr & UART_LCR_DLAB)
> > -			ioport__write8(data, dev->dlm);
> > +			*data = dev->dlm;
> >  		else
> > -			ioport__write8(data, dev->ier);
> > +			*data = dev->ier;
> >  		break;
> >  	case UART_IIR:
> > -		ioport__write8(data, dev->iir | UART_IIR_TYPE_BITS);
> > +		*data = dev->iir | UART_IIR_TYPE_BITS;
> >  		break;
> >  	case UART_LCR:
> > -		ioport__write8(data, dev->lcr);
> > +		*data = dev->lcr;
> >  		break;
> >  	case UART_MCR:
> > -		ioport__write8(data, dev->mcr);
> > +		*data = dev->mcr;
> >  		break;
> >  	case UART_LSR:
> > -		ioport__write8(data, dev->lsr);
> > +		*data = dev->lsr;
> >  		break;
> >  	case UART_MSR:
> > -		ioport__write8(data, dev->msr);
> > +		*data = dev->msr;
> >  		break;
> >  	case UART_SCR:
> > -		ioport__write8(data, dev->scr);
> > +		*data = dev->scr;
> >  		break;
> >  	default:
> >  		ret = false;
> > @@ -389,6 +381,37 @@ static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port,
> >  	return ret;
> >  }  
> 
> I'm not sure about replacing ioport_{read,write}8 with pointer dereferencing. They
> are functionally equivalent because big-endian and little-endian are about the
> order of bytes in memory, not the order of bits, but I don't think the change
> makes much sense because:
> 
> 1. All the other emulated devices use the ioport accessors, even in the case of 8
> bit accesses. For example, the RTC device uses ioport accessors and it too is
> converted in the end to a MMIO device, just like serial.
> 
> 2. The patch is about refactoring the emulation callbacks, other (non-trivial)
> changes should be a separate patch.
> 
> Please let me know if it's something that I'm missing. Other than this change, the
> patch looks good.

Well, I can see merits in both approaches: keeping the wrappers and
ditching them. Don't really have a strong opinion, but I think
eventually we should have the endian conversion in one central place
(in kvm__emulate_io()), where we can easily differentiate between port
I/O, MMIO and PCI accesses. Then all devices just need to dereference
pointers.
But this is indeed something for another time, and having wrappers
should not hurt either way, so I will keep them. Makes the patch smaller
anyway.

Cheers,
Andre

> >  
> > +static void serial8250_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> > +			    u8 is_write, void *ptr)
> > +{
> > +	struct serial8250_device *dev = ptr;
> > +
> > +	if (is_write)
> > +		serial8250_out(dev, vcpu, addr - dev->iobase, *data);
> > +	else
> > +		serial8250_in(dev, vcpu, addr - dev->iobase, data);
> > +}
> > +
> > +static bool serial8250_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
> > +				  u16 port, void *data, int size)
> > +{
> > +	struct serial8250_device *dev = ioport->priv;
> > +
> > +	serial8250_mmio(vcpu, port, data, 1, true, dev);
> > +
> > +	return true;
> > +}
> > +
> > +static bool serial8250_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
> > +				 u16 port, void *data, int size)
> > +{
> > +	struct serial8250_device *dev = ioport->priv;
> > +
> > +	serial8250_mmio(vcpu, port, data, 1, false, dev);
> > +
> > +	return true;
> > +}
> > +
> >  #ifdef CONFIG_HAS_LIBFDT
> >  
> >  char *fdt_stdout_path = NULL;
> > @@ -427,8 +450,8 @@ void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
> >  #endif
> >  
> >  static struct ioport_operations serial8250_ops = {
> > -	.io_in			= serial8250_in,
> > -	.io_out			= serial8250_out,
> > +	.io_in			= serial8250_ioport_in,
> > +	.io_out			= serial8250_ioport_out,
> >  };
> >  
> >  static int serial8250__device_init(struct kvm *kvm,  


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

* Re: [PATCH kvmtool v2 13/22] hw/serial: Refactor trap handler
@ 2021-03-15 12:26       ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-03-15 12:26 UTC (permalink / raw)
  To: Alexandru Elisei; +Cc: kvm, Marc Zyngier, Sami Mujawar, Will Deacon, kvmarm

On Fri, 12 Mar 2021 11:29:43 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

> Hi Andre,
> 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > With the planned retirement of the special ioport emulation code, we
> > need to provide an emulation function compatible with the MMIO prototype.
> >
> > Adjust the trap handler to use that new function, and provide shims to
> > implement the old ioport interface, for now.
> >
> > We drop the usage of ioport__read8/write8 entirely, as this would only
> > be applicable for I/O port accesses, and does nothing for 8-bit wide
> > accesses anyway.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> >  hw/serial.c | 93 +++++++++++++++++++++++++++++++++--------------------
> >  1 file changed, 58 insertions(+), 35 deletions(-)
> >
> > diff --git a/hw/serial.c b/hw/serial.c
> > index b0465d99..c495eac1 100644
> > --- a/hw/serial.c
> > +++ b/hw/serial.c
> > @@ -242,36 +242,31 @@ void serial8250__inject_sysrq(struct kvm *kvm, char sysrq)
> >  	sysrq_pending = sysrq;
> >  }
> >  
> > -static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port,
> > -			   void *data, int size)
> > +static bool serial8250_out(struct serial8250_device *dev, struct kvm_cpu *vcpu,
> > +			   u16 offset, u8 data)
> >  {
> > -	struct serial8250_device *dev = ioport->priv;
> > -	u16 offset;
> >  	bool ret = true;
> > -	char *addr = data;
> >  
> >  	mutex_lock(&dev->mutex);
> >  
> > -	offset = port - dev->iobase;
> > -
> >  	switch (offset) {
> >  	case UART_TX:
> >  		if (dev->lcr & UART_LCR_DLAB) {
> > -			dev->dll = ioport__read8(data);
> > +			dev->dll = data;
> >  			break;
> >  		}
> >  
> >  		/* Loopback mode */
> >  		if (dev->mcr & UART_MCR_LOOP) {
> >  			if (dev->rxcnt < FIFO_LEN) {
> > -				dev->rxbuf[dev->rxcnt++] = *addr;
> > +				dev->rxbuf[dev->rxcnt++] = data;
> >  				dev->lsr |= UART_LSR_DR;
> >  			}
> >  			break;
> >  		}
> >  
> >  		if (dev->txcnt < FIFO_LEN) {
> > -			dev->txbuf[dev->txcnt++] = *addr;
> > +			dev->txbuf[dev->txcnt++] = data;
> >  			dev->lsr &= ~UART_LSR_TEMT;
> >  			if (dev->txcnt == FIFO_LEN / 2)
> >  				dev->lsr &= ~UART_LSR_THRE;
> > @@ -283,18 +278,18 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
> >  		break;
> >  	case UART_IER:
> >  		if (!(dev->lcr & UART_LCR_DLAB))
> > -			dev->ier = ioport__read8(data) & 0x0f;
> > +			dev->ier = data & 0x0f;
> >  		else
> > -			dev->dlm = ioport__read8(data);
> > +			dev->dlm = data;
> >  		break;
> >  	case UART_FCR:
> > -		dev->fcr = ioport__read8(data);
> > +		dev->fcr = data;
> >  		break;
> >  	case UART_LCR:
> > -		dev->lcr = ioport__read8(data);
> > +		dev->lcr = data;
> >  		break;
> >  	case UART_MCR:
> > -		dev->mcr = ioport__read8(data);
> > +		dev->mcr = data;
> >  		break;
> >  	case UART_LSR:
> >  		/* Factory test */
> > @@ -303,7 +298,7 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
> >  		/* Not used */
> >  		break;
> >  	case UART_SCR:
> > -		dev->scr = ioport__read8(data);
> > +		dev->scr = data;
> >  		break;
> >  	default:
> >  		ret = false;
> > @@ -317,7 +312,7 @@ static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port
> >  	return ret;
> >  }
> >  
> > -static void serial8250_rx(struct serial8250_device *dev, void *data)
> > +static void serial8250_rx(struct serial8250_device *dev, u8 *data)
> >  {
> >  	if (dev->rxdone == dev->rxcnt)
> >  		return;
> > @@ -325,57 +320,54 @@ static void serial8250_rx(struct serial8250_device *dev, void *data)
> >  	/* Break issued ? */
> >  	if (dev->lsr & UART_LSR_BI) {
> >  		dev->lsr &= ~UART_LSR_BI;
> > -		ioport__write8(data, 0);
> > +		*data = 0;
> >  		return;
> >  	}
> >  
> > -	ioport__write8(data, dev->rxbuf[dev->rxdone++]);
> > +	*data = dev->rxbuf[dev->rxdone++];
> >  	if (dev->rxcnt == dev->rxdone) {
> >  		dev->lsr &= ~UART_LSR_DR;
> >  		dev->rxcnt = dev->rxdone = 0;
> >  	}
> >  }
> >  
> > -static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
> > +static bool serial8250_in(struct serial8250_device *dev, struct kvm_cpu *vcpu,
> > +			  u16 offset, u8 *data)
> >  {
> > -	struct serial8250_device *dev = ioport->priv;
> > -	u16 offset;
> >  	bool ret = true;
> >  
> >  	mutex_lock(&dev->mutex);
> >  
> > -	offset = port - dev->iobase;
> > -
> >  	switch (offset) {
> >  	case UART_RX:
> >  		if (dev->lcr & UART_LCR_DLAB)
> > -			ioport__write8(data, dev->dll);
> > +			*data = dev->dll;
> >  		else
> >  			serial8250_rx(dev, data);
> >  		break;
> >  	case UART_IER:
> >  		if (dev->lcr & UART_LCR_DLAB)
> > -			ioport__write8(data, dev->dlm);
> > +			*data = dev->dlm;
> >  		else
> > -			ioport__write8(data, dev->ier);
> > +			*data = dev->ier;
> >  		break;
> >  	case UART_IIR:
> > -		ioport__write8(data, dev->iir | UART_IIR_TYPE_BITS);
> > +		*data = dev->iir | UART_IIR_TYPE_BITS;
> >  		break;
> >  	case UART_LCR:
> > -		ioport__write8(data, dev->lcr);
> > +		*data = dev->lcr;
> >  		break;
> >  	case UART_MCR:
> > -		ioport__write8(data, dev->mcr);
> > +		*data = dev->mcr;
> >  		break;
> >  	case UART_LSR:
> > -		ioport__write8(data, dev->lsr);
> > +		*data = dev->lsr;
> >  		break;
> >  	case UART_MSR:
> > -		ioport__write8(data, dev->msr);
> > +		*data = dev->msr;
> >  		break;
> >  	case UART_SCR:
> > -		ioport__write8(data, dev->scr);
> > +		*data = dev->scr;
> >  		break;
> >  	default:
> >  		ret = false;
> > @@ -389,6 +381,37 @@ static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port,
> >  	return ret;
> >  }  
> 
> I'm not sure about replacing ioport_{read,write}8 with pointer dereferencing. They
> are functionally equivalent because big-endian and little-endian are about the
> order of bytes in memory, not the order of bits, but I don't think the change
> makes much sense because:
> 
> 1. All the other emulated devices use the ioport accessors, even in the case of 8
> bit accesses. For example, the RTC device uses ioport accessors and it too is
> converted in the end to a MMIO device, just like serial.
> 
> 2. The patch is about refactoring the emulation callbacks, other (non-trivial)
> changes should be a separate patch.
> 
> Please let me know if it's something that I'm missing. Other than this change, the
> patch looks good.

Well, I can see merits in both approaches: keeping the wrappers and
ditching them. Don't really have a strong opinion, but I think
eventually we should have the endian conversion in one central place
(in kvm__emulate_io()), where we can easily differentiate between port
I/O, MMIO and PCI accesses. Then all devices just need to dereference
pointers.
But this is indeed something for another time, and having wrappers
should not hurt either way, so I will keep them. Makes the patch smaller
anyway.

Cheers,
Andre

> >  
> > +static void serial8250_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> > +			    u8 is_write, void *ptr)
> > +{
> > +	struct serial8250_device *dev = ptr;
> > +
> > +	if (is_write)
> > +		serial8250_out(dev, vcpu, addr - dev->iobase, *data);
> > +	else
> > +		serial8250_in(dev, vcpu, addr - dev->iobase, data);
> > +}
> > +
> > +static bool serial8250_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
> > +				  u16 port, void *data, int size)
> > +{
> > +	struct serial8250_device *dev = ioport->priv;
> > +
> > +	serial8250_mmio(vcpu, port, data, 1, true, dev);
> > +
> > +	return true;
> > +}
> > +
> > +static bool serial8250_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
> > +				 u16 port, void *data, int size)
> > +{
> > +	struct serial8250_device *dev = ioport->priv;
> > +
> > +	serial8250_mmio(vcpu, port, data, 1, false, dev);
> > +
> > +	return true;
> > +}
> > +
> >  #ifdef CONFIG_HAS_LIBFDT
> >  
> >  char *fdt_stdout_path = NULL;
> > @@ -427,8 +450,8 @@ void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
> >  #endif
> >  
> >  static struct ioport_operations serial8250_ops = {
> > -	.io_in			= serial8250_in,
> > -	.io_out			= serial8250_out,
> > +	.io_in			= serial8250_ioport_in,
> > +	.io_out			= serial8250_ioport_out,
> >  };
> >  
> >  static int serial8250__device_init(struct kvm *kvm,  

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 20/22] arm: Reorganise and document memory map
  2021-03-09 15:46     ` Alexandru Elisei
@ 2021-03-15 12:27       ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-03-15 12:27 UTC (permalink / raw)
  To: Alexandru Elisei
  Cc: Will Deacon, Julien Thierry, kvm, kvmarm, Marc Zyngier, Sami Mujawar

On Tue, 9 Mar 2021 15:46:29 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

Hi,

> Hi Andre,
> 
> This is a really good idea, thank you for implementing it!
> 
> Some comments below.
> 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > The hardcoded memory map we expose to a guest is currently described
> > using a series of partially interconnected preprocessor constants,
> > which is hard to read and follow.
> >
> > In preparation for moving the UART and RTC to some different MMIO
> > region, document the current map with some ASCII art, and clean up the
> > definition of the sections.
> >
> > No functional change.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> >  arm/include/arm-common/kvm-arch.h | 41 ++++++++++++++++++++++---------
> >  1 file changed, 29 insertions(+), 12 deletions(-)
> >
> > diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
> > index d84e50cd..b12255b0 100644
> > --- a/arm/include/arm-common/kvm-arch.h
> > +++ b/arm/include/arm-common/kvm-arch.h
> > @@ -7,14 +7,33 @@
> >  
> >  #include "arm-common/gic.h"
> >  
> > +/*
> > + * The memory map used for ARM guests (not to scale):
> > + *
> > + * 0      64K  16M     32M     48M            1GB       2GB
> > + * +-------+-..-+-------+-------+--....--+-----+--.....--+---......
> > + * | (PCI) |////| int.  |       |        |     |         |
> > + * |  I/O  |////| MMIO: | Flash | virtio | GIC |   PCI   |  DRAM
> > + * | ports |////| UART, |       |  MMIO  |     |  (AXI)  |
> > + * |       |////| RTC   |       |        |     |         |
> > + * +-------+-..-+-------+-------+--....--+-----+--.....--+---......
> > + */  
> 
> Nitpick: I searched the PCI Local Bus Specification revision 3.0 (which kvmtool
> currently implements) for the term I/O ports, and found one mention in a schematic
> for an add-in card. The I/O region is called in the spec I/O Space.

Right, will change that.
 
> I don't know what "int." means in the region for the UART and RTC.

It was meant to mean "internal", but this is really nonsensical, so I
will replace it with "plat MMIO".
 
> The comment says that the art is not to scale, so I don't think there's any need
> for the "..." between the corners of the regions. To my eyes, it makes the ASCII
> art look crooked.

fixed.
 
> The next patches add the UART and RTC outside the first 64K, I think the region
> should be documented in the patches where the changes are made, not here. Another
> alternative would be to move this patch to the end of the series instead of
> incrementally changing the memory ASCII art (which I imagine is time consuming).

You passed the scrutiny test ;-)
I noticed this last minute, but didn't feel like changing it then.
Have done it now.

> 
> Otherwise, the numbers look OK.
> 
> > +
> >  #define ARM_IOPORT_AREA		_AC(0x0000000000000000, UL)
> > -#define ARM_FLASH_AREA		_AC(0x0000000002000000, UL)
> > -#define ARM_MMIO_AREA		_AC(0x0000000003000000, UL)
> > +#define ARM_MMIO_AREA		_AC(0x0000000001000000, UL)  
> 
> The patch says it is *documenting* the memory layout, but here it is *changing*
> the layout. Other than that, I like the shuffling of definitions so the kvmtool
> global defines are closer to the arch values.

I amended the commit message to mention that I change the value of
ARM_MMIO_AREA, but that stays internal to that file and doesn't affect
the other definitions.
In fact I imported this header into a C file and printed all
externally used names, before and after: it didn't show any changes.

Cheers,
Andre

> >  #define ARM_AXI_AREA		_AC(0x0000000040000000, UL)
> >  #define ARM_MEMORY_AREA		_AC(0x0000000080000000, UL)
> >  
> > -#define ARM_LOMAP_MAX_MEMORY	((1ULL << 32) - ARM_MEMORY_AREA)
> > -#define ARM_HIMAP_MAX_MEMORY	((1ULL << 40) - ARM_MEMORY_AREA)
> > +#define KVM_IOPORT_AREA		ARM_IOPORT_AREA
> > +#define ARM_IOPORT_SIZE		(1U << 16)
> > +
> > +
> > +#define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
> > +#define KVM_FLASH_MAX_SIZE	0x1000000
> > +
> > +#define KVM_VIRTIO_MMIO_AREA	(KVM_FLASH_MMIO_BASE + KVM_FLASH_MAX_SIZE)
> > +#define ARM_VIRTIO_MMIO_SIZE	(ARM_AXI_AREA - \
> > +				(KVM_VIRTIO_MMIO_AREA + ARM_GIC_SIZE))
> >  
> >  #define ARM_GIC_DIST_BASE	(ARM_AXI_AREA - ARM_GIC_DIST_SIZE)
> >  #define ARM_GIC_CPUI_BASE	(ARM_GIC_DIST_BASE - ARM_GIC_CPUI_SIZE)
> > @@ -22,19 +41,17 @@
> >  #define ARM_GIC_DIST_SIZE	0x10000
> >  #define ARM_GIC_CPUI_SIZE	0x20000
> >  
> > -#define KVM_FLASH_MMIO_BASE	ARM_FLASH_AREA
> > -#define KVM_FLASH_MAX_SIZE	(ARM_MMIO_AREA - ARM_FLASH_AREA)
> >  
> > -#define ARM_IOPORT_SIZE		(1U << 16)
> > -#define ARM_VIRTIO_MMIO_SIZE	(ARM_AXI_AREA - (ARM_MMIO_AREA + ARM_GIC_SIZE))
> > +#define KVM_PCI_CFG_AREA	ARM_AXI_AREA
> >  #define ARM_PCI_CFG_SIZE	(1ULL << 24)
> > +#define KVM_PCI_MMIO_AREA	(KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
> >  #define ARM_PCI_MMIO_SIZE	(ARM_MEMORY_AREA - \
> >  				(ARM_AXI_AREA + ARM_PCI_CFG_SIZE))
> >  
> > -#define KVM_IOPORT_AREA		ARM_IOPORT_AREA
> > -#define KVM_PCI_CFG_AREA	ARM_AXI_AREA
> > -#define KVM_PCI_MMIO_AREA	(KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
> > -#define KVM_VIRTIO_MMIO_AREA	ARM_MMIO_AREA
> > +
> > +#define ARM_LOMAP_MAX_MEMORY	((1ULL << 32) - ARM_MEMORY_AREA)
> > +#define ARM_HIMAP_MAX_MEMORY	((1ULL << 40) - ARM_MEMORY_AREA)
> > +
> >  
> >  #define KVM_IOEVENTFD_HAS_PIO	0
> >    


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

* Re: [PATCH kvmtool v2 20/22] arm: Reorganise and document memory map
@ 2021-03-15 12:27       ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-03-15 12:27 UTC (permalink / raw)
  To: Alexandru Elisei; +Cc: kvm, Marc Zyngier, Sami Mujawar, Will Deacon, kvmarm

On Tue, 9 Mar 2021 15:46:29 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

Hi,

> Hi Andre,
> 
> This is a really good idea, thank you for implementing it!
> 
> Some comments below.
> 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > The hardcoded memory map we expose to a guest is currently described
> > using a series of partially interconnected preprocessor constants,
> > which is hard to read and follow.
> >
> > In preparation for moving the UART and RTC to some different MMIO
> > region, document the current map with some ASCII art, and clean up the
> > definition of the sections.
> >
> > No functional change.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> >  arm/include/arm-common/kvm-arch.h | 41 ++++++++++++++++++++++---------
> >  1 file changed, 29 insertions(+), 12 deletions(-)
> >
> > diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
> > index d84e50cd..b12255b0 100644
> > --- a/arm/include/arm-common/kvm-arch.h
> > +++ b/arm/include/arm-common/kvm-arch.h
> > @@ -7,14 +7,33 @@
> >  
> >  #include "arm-common/gic.h"
> >  
> > +/*
> > + * The memory map used for ARM guests (not to scale):
> > + *
> > + * 0      64K  16M     32M     48M            1GB       2GB
> > + * +-------+-..-+-------+-------+--....--+-----+--.....--+---......
> > + * | (PCI) |////| int.  |       |        |     |         |
> > + * |  I/O  |////| MMIO: | Flash | virtio | GIC |   PCI   |  DRAM
> > + * | ports |////| UART, |       |  MMIO  |     |  (AXI)  |
> > + * |       |////| RTC   |       |        |     |         |
> > + * +-------+-..-+-------+-------+--....--+-----+--.....--+---......
> > + */  
> 
> Nitpick: I searched the PCI Local Bus Specification revision 3.0 (which kvmtool
> currently implements) for the term I/O ports, and found one mention in a schematic
> for an add-in card. The I/O region is called in the spec I/O Space.

Right, will change that.
 
> I don't know what "int." means in the region for the UART and RTC.

It was meant to mean "internal", but this is really nonsensical, so I
will replace it with "plat MMIO".
 
> The comment says that the art is not to scale, so I don't think there's any need
> for the "..." between the corners of the regions. To my eyes, it makes the ASCII
> art look crooked.

fixed.
 
> The next patches add the UART and RTC outside the first 64K, I think the region
> should be documented in the patches where the changes are made, not here. Another
> alternative would be to move this patch to the end of the series instead of
> incrementally changing the memory ASCII art (which I imagine is time consuming).

You passed the scrutiny test ;-)
I noticed this last minute, but didn't feel like changing it then.
Have done it now.

> 
> Otherwise, the numbers look OK.
> 
> > +
> >  #define ARM_IOPORT_AREA		_AC(0x0000000000000000, UL)
> > -#define ARM_FLASH_AREA		_AC(0x0000000002000000, UL)
> > -#define ARM_MMIO_AREA		_AC(0x0000000003000000, UL)
> > +#define ARM_MMIO_AREA		_AC(0x0000000001000000, UL)  
> 
> The patch says it is *documenting* the memory layout, but here it is *changing*
> the layout. Other than that, I like the shuffling of definitions so the kvmtool
> global defines are closer to the arch values.

I amended the commit message to mention that I change the value of
ARM_MMIO_AREA, but that stays internal to that file and doesn't affect
the other definitions.
In fact I imported this header into a C file and printed all
externally used names, before and after: it didn't show any changes.

Cheers,
Andre

> >  #define ARM_AXI_AREA		_AC(0x0000000040000000, UL)
> >  #define ARM_MEMORY_AREA		_AC(0x0000000080000000, UL)
> >  
> > -#define ARM_LOMAP_MAX_MEMORY	((1ULL << 32) - ARM_MEMORY_AREA)
> > -#define ARM_HIMAP_MAX_MEMORY	((1ULL << 40) - ARM_MEMORY_AREA)
> > +#define KVM_IOPORT_AREA		ARM_IOPORT_AREA
> > +#define ARM_IOPORT_SIZE		(1U << 16)
> > +
> > +
> > +#define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
> > +#define KVM_FLASH_MAX_SIZE	0x1000000
> > +
> > +#define KVM_VIRTIO_MMIO_AREA	(KVM_FLASH_MMIO_BASE + KVM_FLASH_MAX_SIZE)
> > +#define ARM_VIRTIO_MMIO_SIZE	(ARM_AXI_AREA - \
> > +				(KVM_VIRTIO_MMIO_AREA + ARM_GIC_SIZE))
> >  
> >  #define ARM_GIC_DIST_BASE	(ARM_AXI_AREA - ARM_GIC_DIST_SIZE)
> >  #define ARM_GIC_CPUI_BASE	(ARM_GIC_DIST_BASE - ARM_GIC_CPUI_SIZE)
> > @@ -22,19 +41,17 @@
> >  #define ARM_GIC_DIST_SIZE	0x10000
> >  #define ARM_GIC_CPUI_SIZE	0x20000
> >  
> > -#define KVM_FLASH_MMIO_BASE	ARM_FLASH_AREA
> > -#define KVM_FLASH_MAX_SIZE	(ARM_MMIO_AREA - ARM_FLASH_AREA)
> >  
> > -#define ARM_IOPORT_SIZE		(1U << 16)
> > -#define ARM_VIRTIO_MMIO_SIZE	(ARM_AXI_AREA - (ARM_MMIO_AREA + ARM_GIC_SIZE))
> > +#define KVM_PCI_CFG_AREA	ARM_AXI_AREA
> >  #define ARM_PCI_CFG_SIZE	(1ULL << 24)
> > +#define KVM_PCI_MMIO_AREA	(KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
> >  #define ARM_PCI_MMIO_SIZE	(ARM_MEMORY_AREA - \
> >  				(ARM_AXI_AREA + ARM_PCI_CFG_SIZE))
> >  
> > -#define KVM_IOPORT_AREA		ARM_IOPORT_AREA
> > -#define KVM_PCI_CFG_AREA	ARM_AXI_AREA
> > -#define KVM_PCI_MMIO_AREA	(KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
> > -#define KVM_VIRTIO_MMIO_AREA	ARM_MMIO_AREA
> > +
> > +#define ARM_LOMAP_MAX_MEMORY	((1ULL << 32) - ARM_MEMORY_AREA)
> > +#define ARM_HIMAP_MAX_MEMORY	((1ULL << 40) - ARM_MEMORY_AREA)
> > +
> >  
> >  #define KVM_IOEVENTFD_HAS_PIO	0
> >    

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH kvmtool v2 21/22] hw/serial: ARM/arm64: Use MMIO at higher addresses
  2021-03-09 16:02     ` Alexandru Elisei
@ 2021-03-15 12:27       ` Andre Przywara
  -1 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-03-15 12:27 UTC (permalink / raw)
  To: Alexandru Elisei
  Cc: Will Deacon, Julien Thierry, kvm, kvmarm, Marc Zyngier, Sami Mujawar

On Tue, 9 Mar 2021 16:02:20 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

> Hi Andre,
> 
> I think you forgot to change the way the address is generated in
> serial8250_generate_fdt_node, it's still KVM_IOPORT_AREA + dev->iobase. It's
> technically correct, as KVM_IOPORT_AREA == ARM_IOPORT_AREA == 0x0, but very
> confusing (and prone to breakage is something changes in the memory layout).

So I moved the addition of KVM_IOPORT_AREA into the definition of
serial_iobase() (at the beginning of the file). This means I can remove
it below, and just use dev->iobase as is.

> One more comment below.
> 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > Using the UART devices at their legacy I/O addresses as set by IBM in
> > 1981 was a kludge we used for simplicity on ARM platforms as well.
> > However this imposes problems due to their missing alignment and overlap
> > with the PCI I/O address space.
> >
> > Now that we can switch a device easily between using ioports and MMIO,
> > let's move the UARTs out of the first 4K of memory on ARM platforms.
> >
> > That should be transparent for well behaved guests, since the change is
> > naturally reflected in the device tree. Even "earlycon" keeps working,
> > as the stdout-path property is adjusted automatically.
> >
> > People providing direct earlycon parameters via the command line need to
> > adjust it to: "earlycon=uart,mmio,0x1000000".
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> >  arm/include/arm-common/kvm-arch.h |  3 +++
> >  hw/serial.c                       | 45 ++++++++++++++++++++-----------
> >  2 files changed, 32 insertions(+), 16 deletions(-)
> >
> > diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
> > index b12255b0..633ea8fa 100644
> > --- a/arm/include/arm-common/kvm-arch.h
> > +++ b/arm/include/arm-common/kvm-arch.h
> > @@ -28,6 +28,9 @@
> >  #define ARM_IOPORT_SIZE		(1U << 16)
> >  
> >  
> > +#define ARM_UART_MMIO_BASE	ARM_MMIO_AREA
> > +#define ARM_UART_MMIO_SIZE	0x10000
> > +
> >  #define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
> >  #define KVM_FLASH_MAX_SIZE	0x1000000
> >  
> > diff --git a/hw/serial.c b/hw/serial.c
> > index 4be188a1..1854add2 100644
> > --- a/hw/serial.c
> > +++ b/hw/serial.c
> > @@ -13,6 +13,17 @@
> >  
> >  #include <pthread.h>
> >  
> > +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
> > +#define serial_iobase(nr)	(ARM_UART_MMIO_BASE + (nr) * 0x1000)
> > +#define serial_irq(nr)		(32 + (nr))
> > +#define SERIAL8250_BUS_TYPE	DEVICE_BUS_MMIO
> > +#else
> > +#define serial_iobase(nr)	((((nr) & 1) ? 0x200 : 0x300) +	\
> > +				 ((nr) >= 2 ? 0xe8 : 0xf8))
> > +#define serial_irq(nr)		(((nr) & 1) ? 3 : 4)  
> 
> Those two defines are hard to read, is there a reason for changing them from v1?
> They looked a lot more readable in v1.

Oh, good catch, must have been a rebase artefact, from the very first
draft version I had. Fixed that.

Cheers,
Andre

> 
> > +#define SERIAL8250_BUS_TYPE	DEVICE_BUS_IOPORT
> > +#endif
> > +
> >  /*
> >   * This fakes a U6_16550A. The fifo len needs to be 64 as the kernel
> >   * expects that for autodetection.
> > @@ -27,7 +38,7 @@ struct serial8250_device {
> >  	struct mutex		mutex;
> >  	u8			id;
> >  
> > -	u16			iobase;
> > +	u32			iobase;
> >  	u8			irq;
> >  	u8			irq_state;
> >  	int			txcnt;
> > @@ -65,56 +76,56 @@ static struct serial8250_device devices[] = {
> >  	/* ttyS0 */
> >  	[0]	= {
> >  		.dev_hdr = {
> > -			.bus_type	= DEVICE_BUS_IOPORT,
> > +			.bus_type	= SERIAL8250_BUS_TYPE,
> >  			.data		= serial8250_generate_fdt_node,
> >  		},
> >  		.mutex			= MUTEX_INITIALIZER,
> >  
> >  		.id			= 0,
> > -		.iobase			= 0x3f8,
> > -		.irq			= 4,
> > +		.iobase			= serial_iobase(0),
> > +		.irq			= serial_irq(0),
> >  
> >  		SERIAL_REGS_SETTING
> >  	},
> >  	/* ttyS1 */
> >  	[1]	= {
> >  		.dev_hdr = {
> > -			.bus_type	= DEVICE_BUS_IOPORT,
> > +			.bus_type	= SERIAL8250_BUS_TYPE,
> >  			.data		= serial8250_generate_fdt_node,
> >  		},
> >  		.mutex			= MUTEX_INITIALIZER,
> >  
> >  		.id			= 1,
> > -		.iobase			= 0x2f8,
> > -		.irq			= 3,
> > +		.iobase			= serial_iobase(1),
> > +		.irq			= serial_irq(1),
> >  
> >  		SERIAL_REGS_SETTING
> >  	},
> >  	/* ttyS2 */
> >  	[2]	= {
> >  		.dev_hdr = {
> > -			.bus_type	= DEVICE_BUS_IOPORT,
> > +			.bus_type	= SERIAL8250_BUS_TYPE,
> >  			.data		= serial8250_generate_fdt_node,
> >  		},
> >  		.mutex			= MUTEX_INITIALIZER,
> >  
> >  		.id			= 2,
> > -		.iobase			= 0x3e8,
> > -		.irq			= 4,
> > +		.iobase			= serial_iobase(2),
> > +		.irq			= serial_irq(2),
> >  
> >  		SERIAL_REGS_SETTING
> >  	},
> >  	/* ttyS3 */
> >  	[3]	= {
> >  		.dev_hdr = {
> > -			.bus_type	= DEVICE_BUS_IOPORT,
> > +			.bus_type	= SERIAL8250_BUS_TYPE,
> >  			.data		= serial8250_generate_fdt_node,
> >  		},
> >  		.mutex			= MUTEX_INITIALIZER,
> >  
> >  		.id			= 3,
> > -		.iobase			= 0x2e8,
> > -		.irq			= 3,
> > +		.iobase			= serial_iobase(3),
> > +		.irq			= serial_irq(3),
> >  
> >  		SERIAL_REGS_SETTING
> >  	},
> > @@ -439,7 +450,8 @@ static int serial8250__device_init(struct kvm *kvm,
> >  		return r;
> >  
> >  	ioport__map_irq(&dev->irq);
> > -	r = kvm__register_pio(kvm, dev->iobase, 8, serial8250_mmio, dev);
> > +	r = kvm__register_iotrap(kvm, dev->iobase, 8, serial8250_mmio, dev,
> > +				 SERIAL8250_BUS_TYPE);
> >  
> >  	return r;
> >  }
> > @@ -462,7 +474,7 @@ cleanup:
> >  	for (j = 0; j <= i; j++) {
> >  		struct serial8250_device *dev = &devices[j];
> >  
> > -		kvm__deregister_pio(kvm, dev->iobase);
> > +		kvm__deregister_iotrap(kvm, dev->iobase, SERIAL8250_BUS_TYPE);
> >  		device__unregister(&dev->dev_hdr);
> >  	}
> >  
> > @@ -478,7 +490,8 @@ int serial8250__exit(struct kvm *kvm)
> >  	for (i = 0; i < ARRAY_SIZE(devices); i++) {
> >  		struct serial8250_device *dev = &devices[i];
> >  
> > -		r = kvm__deregister_pio(kvm, dev->iobase);
> > +		r = kvm__deregister_iotrap(kvm, dev->iobase,
> > +					   SERIAL8250_BUS_TYPE);
> >  		if (r < 0)
> >  			return r;
> >  		device__unregister(&dev->dev_hdr);  


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

* Re: [PATCH kvmtool v2 21/22] hw/serial: ARM/arm64: Use MMIO at higher addresses
@ 2021-03-15 12:27       ` Andre Przywara
  0 siblings, 0 replies; 88+ messages in thread
From: Andre Przywara @ 2021-03-15 12:27 UTC (permalink / raw)
  To: Alexandru Elisei; +Cc: kvm, Marc Zyngier, Sami Mujawar, Will Deacon, kvmarm

On Tue, 9 Mar 2021 16:02:20 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

> Hi Andre,
> 
> I think you forgot to change the way the address is generated in
> serial8250_generate_fdt_node, it's still KVM_IOPORT_AREA + dev->iobase. It's
> technically correct, as KVM_IOPORT_AREA == ARM_IOPORT_AREA == 0x0, but very
> confusing (and prone to breakage is something changes in the memory layout).

So I moved the addition of KVM_IOPORT_AREA into the definition of
serial_iobase() (at the beginning of the file). This means I can remove
it below, and just use dev->iobase as is.

> One more comment below.
> 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > Using the UART devices at their legacy I/O addresses as set by IBM in
> > 1981 was a kludge we used for simplicity on ARM platforms as well.
> > However this imposes problems due to their missing alignment and overlap
> > with the PCI I/O address space.
> >
> > Now that we can switch a device easily between using ioports and MMIO,
> > let's move the UARTs out of the first 4K of memory on ARM platforms.
> >
> > That should be transparent for well behaved guests, since the change is
> > naturally reflected in the device tree. Even "earlycon" keeps working,
> > as the stdout-path property is adjusted automatically.
> >
> > People providing direct earlycon parameters via the command line need to
> > adjust it to: "earlycon=uart,mmio,0x1000000".
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> >  arm/include/arm-common/kvm-arch.h |  3 +++
> >  hw/serial.c                       | 45 ++++++++++++++++++++-----------
> >  2 files changed, 32 insertions(+), 16 deletions(-)
> >
> > diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
> > index b12255b0..633ea8fa 100644
> > --- a/arm/include/arm-common/kvm-arch.h
> > +++ b/arm/include/arm-common/kvm-arch.h
> > @@ -28,6 +28,9 @@
> >  #define ARM_IOPORT_SIZE		(1U << 16)
> >  
> >  
> > +#define ARM_UART_MMIO_BASE	ARM_MMIO_AREA
> > +#define ARM_UART_MMIO_SIZE	0x10000
> > +
> >  #define KVM_FLASH_MMIO_BASE	(ARM_MMIO_AREA + 0x1000000)
> >  #define KVM_FLASH_MAX_SIZE	0x1000000
> >  
> > diff --git a/hw/serial.c b/hw/serial.c
> > index 4be188a1..1854add2 100644
> > --- a/hw/serial.c
> > +++ b/hw/serial.c
> > @@ -13,6 +13,17 @@
> >  
> >  #include <pthread.h>
> >  
> > +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
> > +#define serial_iobase(nr)	(ARM_UART_MMIO_BASE + (nr) * 0x1000)
> > +#define serial_irq(nr)		(32 + (nr))
> > +#define SERIAL8250_BUS_TYPE	DEVICE_BUS_MMIO
> > +#else
> > +#define serial_iobase(nr)	((((nr) & 1) ? 0x200 : 0x300) +	\
> > +				 ((nr) >= 2 ? 0xe8 : 0xf8))
> > +#define serial_irq(nr)		(((nr) & 1) ? 3 : 4)  
> 
> Those two defines are hard to read, is there a reason for changing them from v1?
> They looked a lot more readable in v1.

Oh, good catch, must have been a rebase artefact, from the very first
draft version I had. Fixed that.

Cheers,
Andre

> 
> > +#define SERIAL8250_BUS_TYPE	DEVICE_BUS_IOPORT
> > +#endif
> > +
> >  /*
> >   * This fakes a U6_16550A. The fifo len needs to be 64 as the kernel
> >   * expects that for autodetection.
> > @@ -27,7 +38,7 @@ struct serial8250_device {
> >  	struct mutex		mutex;
> >  	u8			id;
> >  
> > -	u16			iobase;
> > +	u32			iobase;
> >  	u8			irq;
> >  	u8			irq_state;
> >  	int			txcnt;
> > @@ -65,56 +76,56 @@ static struct serial8250_device devices[] = {
> >  	/* ttyS0 */
> >  	[0]	= {
> >  		.dev_hdr = {
> > -			.bus_type	= DEVICE_BUS_IOPORT,
> > +			.bus_type	= SERIAL8250_BUS_TYPE,
> >  			.data		= serial8250_generate_fdt_node,
> >  		},
> >  		.mutex			= MUTEX_INITIALIZER,
> >  
> >  		.id			= 0,
> > -		.iobase			= 0x3f8,
> > -		.irq			= 4,
> > +		.iobase			= serial_iobase(0),
> > +		.irq			= serial_irq(0),
> >  
> >  		SERIAL_REGS_SETTING
> >  	},
> >  	/* ttyS1 */
> >  	[1]	= {
> >  		.dev_hdr = {
> > -			.bus_type	= DEVICE_BUS_IOPORT,
> > +			.bus_type	= SERIAL8250_BUS_TYPE,
> >  			.data		= serial8250_generate_fdt_node,
> >  		},
> >  		.mutex			= MUTEX_INITIALIZER,
> >  
> >  		.id			= 1,
> > -		.iobase			= 0x2f8,
> > -		.irq			= 3,
> > +		.iobase			= serial_iobase(1),
> > +		.irq			= serial_irq(1),
> >  
> >  		SERIAL_REGS_SETTING
> >  	},
> >  	/* ttyS2 */
> >  	[2]	= {
> >  		.dev_hdr = {
> > -			.bus_type	= DEVICE_BUS_IOPORT,
> > +			.bus_type	= SERIAL8250_BUS_TYPE,
> >  			.data		= serial8250_generate_fdt_node,
> >  		},
> >  		.mutex			= MUTEX_INITIALIZER,
> >  
> >  		.id			= 2,
> > -		.iobase			= 0x3e8,
> > -		.irq			= 4,
> > +		.iobase			= serial_iobase(2),
> > +		.irq			= serial_irq(2),
> >  
> >  		SERIAL_REGS_SETTING
> >  	},
> >  	/* ttyS3 */
> >  	[3]	= {
> >  		.dev_hdr = {
> > -			.bus_type	= DEVICE_BUS_IOPORT,
> > +			.bus_type	= SERIAL8250_BUS_TYPE,
> >  			.data		= serial8250_generate_fdt_node,
> >  		},
> >  		.mutex			= MUTEX_INITIALIZER,
> >  
> >  		.id			= 3,
> > -		.iobase			= 0x2e8,
> > -		.irq			= 3,
> > +		.iobase			= serial_iobase(3),
> > +		.irq			= serial_irq(3),
> >  
> >  		SERIAL_REGS_SETTING
> >  	},
> > @@ -439,7 +450,8 @@ static int serial8250__device_init(struct kvm *kvm,
> >  		return r;
> >  
> >  	ioport__map_irq(&dev->irq);
> > -	r = kvm__register_pio(kvm, dev->iobase, 8, serial8250_mmio, dev);
> > +	r = kvm__register_iotrap(kvm, dev->iobase, 8, serial8250_mmio, dev,
> > +				 SERIAL8250_BUS_TYPE);
> >  
> >  	return r;
> >  }
> > @@ -462,7 +474,7 @@ cleanup:
> >  	for (j = 0; j <= i; j++) {
> >  		struct serial8250_device *dev = &devices[j];
> >  
> > -		kvm__deregister_pio(kvm, dev->iobase);
> > +		kvm__deregister_iotrap(kvm, dev->iobase, SERIAL8250_BUS_TYPE);
> >  		device__unregister(&dev->dev_hdr);
> >  	}
> >  
> > @@ -478,7 +490,8 @@ int serial8250__exit(struct kvm *kvm)
> >  	for (i = 0; i < ARRAY_SIZE(devices); i++) {
> >  		struct serial8250_device *dev = &devices[i];
> >  
> > -		r = kvm__deregister_pio(kvm, dev->iobase);
> > +		r = kvm__deregister_iotrap(kvm, dev->iobase,
> > +					   SERIAL8250_BUS_TYPE);
> >  		if (r < 0)
> >  			return r;
> >  		device__unregister(&dev->dev_hdr);  

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

end of thread, other threads:[~2021-03-15 12:28 UTC | newest]

Thread overview: 88+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-25  0:58 [PATCH kvmtool v2 00/22] Unify I/O port and MMIO trap handling Andre Przywara
2021-02-25  0:58 ` Andre Przywara
2021-02-25  0:58 ` [PATCH kvmtool v2 01/22] ioport: Remove ioport__setup_arch() Andre Przywara
2021-02-25  0:58   ` Andre Przywara
2021-03-02 18:02   ` Alexandru Elisei
2021-03-02 18:02     ` Alexandru Elisei
2021-02-25  0:58 ` [PATCH kvmtool v2 02/22] hw/serial: Use device abstraction for FDT generator function Andre Przywara
2021-02-25  0:58   ` Andre Przywara
2021-02-25  0:58 ` [PATCH kvmtool v2 03/22] ioport: Retire .generate_fdt_node functionality Andre Przywara
2021-02-25  0:58   ` Andre Przywara
2021-02-25  0:58 ` [PATCH kvmtool v2 04/22] mmio: Extend handling to include ioport emulation Andre Przywara
2021-02-25  0:58   ` Andre Przywara
2021-03-03 17:58   ` Alexandru Elisei
2021-03-03 17:58     ` Alexandru Elisei
2021-03-15 12:24     ` Andre Przywara
2021-03-15 12:24       ` Andre Przywara
2021-02-25  0:58 ` [PATCH kvmtool v2 05/22] hw/i8042: Clean up data types Andre Przywara
2021-02-25  0:58   ` Andre Przywara
2021-02-25  0:58 ` [PATCH kvmtool v2 06/22] hw/i8042: Refactor trap handler Andre Przywara
2021-02-25  0:58   ` Andre Przywara
2021-03-08 17:16   ` Alexandru Elisei
2021-03-08 17:16     ` Alexandru Elisei
2021-02-25  0:59 ` [PATCH kvmtool v2 07/22] hw/i8042: Switch to new trap handlers Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-03-08 17:22   ` Alexandru Elisei
2021-03-08 17:22     ` Alexandru Elisei
2021-02-25  0:59 ` [PATCH kvmtool v2 08/22] x86/ioport: Refactor " Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-03-09 11:49   ` Alexandru Elisei
2021-03-09 11:49     ` Alexandru Elisei
2021-03-15 12:26     ` Andre Przywara
2021-03-15 12:26       ` Andre Przywara
2021-02-25  0:59 ` [PATCH kvmtool v2 09/22] x86/ioport: Switch to new " Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-03-09 12:09   ` Alexandru Elisei
2021-03-09 12:09     ` Alexandru Elisei
2021-03-15 12:26     ` Andre Przywara
2021-03-15 12:26       ` Andre Przywara
2021-02-25  0:59 ` [PATCH kvmtool v2 10/22] hw/rtc: Refactor " Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-02-25  0:59 ` [PATCH kvmtool v2 11/22] hw/rtc: Switch to new trap handler Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-02-25  0:59 ` [PATCH kvmtool v2 12/22] hw/vesa: Switch trap handling to use MMIO handler Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-02-25  0:59 ` [PATCH kvmtool v2 13/22] hw/serial: Refactor trap handler Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-03-12 11:29   ` Alexandru Elisei
2021-03-12 11:29     ` Alexandru Elisei
2021-03-15 12:26     ` Andre Przywara
2021-03-15 12:26       ` Andre Przywara
2021-02-25  0:59 ` [PATCH kvmtool v2 14/22] hw/serial: Switch to new trap handlers Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-02-25  0:59 ` [PATCH kvmtool v2 15/22] vfio: Refactor ioport trap handler Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-03-09 14:21   ` Alexandru Elisei
2021-03-09 14:21     ` Alexandru Elisei
2021-02-25  0:59 ` [PATCH kvmtool v2 16/22] vfio: Switch to new ioport trap handlers Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-02-25  0:59 ` [PATCH kvmtool v2 17/22] virtio: Switch trap handling to use MMIO handler Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-03-09 14:43   ` Alexandru Elisei
2021-03-09 14:43     ` Alexandru Elisei
2021-02-25  0:59 ` [PATCH kvmtool v2 18/22] pci: " Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-02-25  0:59 ` [PATCH kvmtool v2 19/22] Remove ioport specific routines Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-03-09 15:13   ` Alexandru Elisei
2021-03-09 15:13     ` Alexandru Elisei
2021-02-25  0:59 ` [PATCH kvmtool v2 20/22] arm: Reorganise and document memory map Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-03-09 15:46   ` Alexandru Elisei
2021-03-09 15:46     ` Alexandru Elisei
2021-03-15 12:27     ` Andre Przywara
2021-03-15 12:27       ` Andre Przywara
2021-02-25  0:59 ` [PATCH kvmtool v2 21/22] hw/serial: ARM/arm64: Use MMIO at higher addresses Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-03-09 16:02   ` Alexandru Elisei
2021-03-09 16:02     ` Alexandru Elisei
2021-03-15 12:27     ` Andre Przywara
2021-03-15 12:27       ` Andre Przywara
2021-02-25  0:59 ` [PATCH kvmtool v2 22/22] hw/rtc: " Andre Przywara
2021-02-25  0:59   ` Andre Przywara
2021-03-09 16:06   ` Alexandru Elisei
2021-03-09 16:06     ` Alexandru Elisei
2021-03-02 17:57 ` [PATCH kvmtool v2 00/22] Unify I/O port and MMIO trap handling Alexandru Elisei
2021-03-02 17:57   ` Alexandru Elisei
2021-03-03 18:41   ` Andre Przywara
2021-03-03 18:41     ` Andre Przywara

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.