2018-08-24 03:07:26

by Peng Hao

[permalink] [raw]
Subject: [PATCH V3 0/2] introduce coalesced pio support

Coalesced pio is base on coalesced mmio and can be used for some port
like rtc port, pci-host config port, virtio-pci config port and so on.

Specially in case of rtc as coalesced pio, some versions of windows guest
access rtc frequently because of rtc as system tick. guest access rtc like
this: write register index to 0x70, then write or read data from 0x71.
writing 0x70 port is just as index and do nothing else. So we can use
coalesced pio to handle this scene to reduce VM-EXIT time.

When it starts and closes the virtual machine, it will access pci-host config
port or virtio-pci config port frequently. So setting these port as
coalesced pio can reduce startup and shutdown time. In qemu I just realize
piixfx's pci-host, it is convenient for other pci-host type implementations.

without my patch, get the vm-exit time of accessing rtc 0x70 and piix 0xcf8
using perf tools: (guest OS : windows 7 64bit)
IO Port Access Samples Samples% Time% Min Time Max Time Avg time
0x70:POUT 86 30.99% 74.59% 9us 29us 10.75us (+- 3.41%)
0xcf8:POUT 1119 2.60% 2.12% 2.79us 56.83us 3.41us (+- 2.23%)

with my patch
IO Port Access Samples Samples% Time% Min Time Max Time Avg time
0x70:POUT 106 32.02% 29.47% 0us 10us 1.57us (+- 7.38%)
0xcf8:POUT 1065 1.67% 0.28% 0.41us 65.44us 0.66us (+- 10.55%)

I think there is a need for further consideration in changing coalesecd_mmio's
naming in kernel and qemu together.So maybe another patch does it.


Peng Hao (2):
kvm/x86 : add coalesced pio support
kvm/x86 : add document for coalesced pio

Documentation/virtual/kvm/00-INDEX | 4 ++++
Documentation/virtual/kvm/coalesced-pio.txt | 14 ++++++++++++++
include/uapi/linux/kvm.h | 5 +++--
virt/kvm/coalesced_mmio.c | 8 +++++---
virt/kvm/kvm_main.c | 2 ++
5 files changed, 28 insertions(+), 5 deletions(-)
create mode 100644 Documentation/virtual/kvm/coalesced-pio.txt

--
1.8.3.1



2018-08-24 03:07:27

by Peng Hao

[permalink] [raw]
Subject: [PATCH V3 1/2] kvm/x86 : add coalesced pio support

Signed-off-by: Peng Hao <[email protected]>
---
include/uapi/linux/kvm.h | 5 +++--
virt/kvm/coalesced_mmio.c | 8 +++++---
virt/kvm/kvm_main.c | 2 ++
3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index b6270a3..9cc56d3 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -420,13 +420,13 @@ struct kvm_run {
struct kvm_coalesced_mmio_zone {
__u64 addr;
__u32 size;
- __u32 pad;
+ __u32 pio;
};

struct kvm_coalesced_mmio {
__u64 phys_addr;
__u32 len;
- __u32 pad;
+ __u32 pio;
__u8 data[8];
};

@@ -949,6 +949,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_GET_MSR_FEATURES 153
#define KVM_CAP_HYPERV_EVENTFD 154
#define KVM_CAP_HYPERV_TLBFLUSH 155
+#define KVM_CAP_COALESCED_PIO 156

#ifdef KVM_CAP_IRQ_ROUTING

diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c
index 9e65feb..beea7d1 100644
--- a/virt/kvm/coalesced_mmio.c
+++ b/virt/kvm/coalesced_mmio.c
@@ -83,6 +83,7 @@ static int coalesced_mmio_write(struct kvm_vcpu *vcpu,
ring->coalesced_mmio[ring->last].phys_addr = addr;
ring->coalesced_mmio[ring->last].len = len;
memcpy(ring->coalesced_mmio[ring->last].data, val, len);
+ ring->coalesced_mmio[ring->last].pio = dev->zone.pio;
smp_wmb();
ring->last = (ring->last + 1) % KVM_COALESCED_MMIO_MAX;
spin_unlock(&dev->kvm->ring_lock);
@@ -149,8 +150,8 @@ int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm,
dev->zone = *zone;

mutex_lock(&kvm->slots_lock);
- ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, zone->addr,
- zone->size, &dev->dev);
+ ret = kvm_io_bus_register_dev(kvm,
+ zone->pio ? KVM_PIO_BUS : KVM_MMIO_BUS, zone->size, &dev->dev);
if (ret < 0)
goto out_free_dev;
list_add_tail(&dev->list, &kvm->coalesced_zones);
@@ -174,7 +175,8 @@ int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm,

list_for_each_entry_safe(dev, tmp, &kvm->coalesced_zones, list)
if (coalesced_mmio_in_range(dev, zone->addr, zone->size)) {
- kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &dev->dev);
+ kvm_io_bus_unregister_dev(kvm,
+ zone->pio ? KVM_PIO_BUS : KVM_MMIO_BUS, &dev->dev);
kvm_iodevice_destructor(&dev->dev);
}

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 8b47507f..a587fb9 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2936,6 +2936,8 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
#ifdef CONFIG_KVM_MMIO
case KVM_CAP_COALESCED_MMIO:
return KVM_COALESCED_MMIO_PAGE_OFFSET;
+ case KVM_CAP_COALESCED_PIO:
+ return 1;
#endif
#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
case KVM_CAP_IRQ_ROUTING:
--
1.8.3.1


2018-08-24 03:07:33

by Peng Hao

[permalink] [raw]
Subject: [PATCH V3 2/2] kvm/x86 : add document for coalesced pio

Signed-off-by: Peng Hao <[email protected]>
---
Documentation/virtual/kvm/00-INDEX | 2 ++
Documentation/virtual/kvm/coalesced-pio.txt | 14 ++++++++++++++
2 files changed, 16 insertions(+)
create mode 100644 Documentation/virtual/kvm/coalesced-pio.txt

diff --git a/Documentation/virtual/kvm/00-INDEX b/Documentation/virtual/kvm/00-INDEX
index 3492458..3d68164 100644
--- a/Documentation/virtual/kvm/00-INDEX
+++ b/Documentation/virtual/kvm/00-INDEX
@@ -11,6 +11,8 @@ cpuid.txt
- KVM-specific cpuid leaves (x86).
devices/
- KVM_CAP_DEVICE_CTRL userspace API.
+coalesced-pio.txt
+ - KVM_CAP_COALESCED_PIO
halt-polling.txt
- notes on halt-polling
hypercalls.txt
diff --git a/Documentation/virtual/kvm/coalesced-pio.txt b/Documentation/virtual/kvm/coalesced-pio.txt
new file mode 100644
index 0000000..932d5cd
--- /dev/null
+++ b/Documentation/virtual/kvm/coalesced-pio.txt
@@ -0,0 +1,14 @@
+Linux KVM Coalesced PIO:
+========================
+Coalesced pio is base on coalesced mmio. When the write access to a port
+of a device does a simple work (just like setting a register ID or address
+index), then we can use coalesced pio.
+
+Setting a port as coalesced pio, the write access to the port don't need to
+exit to userspace, and just record the value in shared coalesced ring in kernel.
+Then following access to another port of the same device which relys on the first
+port's setting or a read access to the first port will set the previous write
+value of the first port firstly in usersapce according to the shared coalesced ring.
+
+Coalesced pio can be used for rtc 0x70 port, pci-host config port, virtio-pci config
+port and so on.
--
1.8.3.1


2018-08-29 15:16:02

by Radim Krčmář

[permalink] [raw]
Subject: Re: [PATCH V3 1/2] kvm/x86 : add coalesced pio support

2018-08-24 19:20+0800, Peng Hao:
> Signed-off-by: Peng Hao <[email protected]>
> ---
> include/uapi/linux/kvm.h | 5 +++--
> virt/kvm/coalesced_mmio.c | 8 +++++---
> virt/kvm/kvm_main.c | 2 ++
> 3 files changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index b6270a3..9cc56d3 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -420,13 +420,13 @@ struct kvm_run {
> struct kvm_coalesced_mmio_zone {
> __u64 addr;
> __u32 size;
> - __u32 pad;
> + __u32 pio;

I would prefer to have this as a slightly more compatible

union {
__u32 pad;
__u32 pio;
};

> };
>
> struct kvm_coalesced_mmio {
> __u64 phys_addr;
> __u32 len;
> - __u32 pad;
> + __u32 pio;

Also, please add a check that "pio <= 1".

This would catch most cases where userspace passed garbage in that field
and we'd also make the remaining bits available for future features.

Thanks.