Skip to content

Commit 0804c84

Browse files
Peng Haobonzini
authored andcommitted
kvm/x86 : add coalesced pio support
Coalesced pio is based on coalesced mmio and can be used for some port like rtc port, pci-host 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 starting and closing a virtual machine, it will access pci-host config port frequently. So setting these port as coalesced pio can reduce startup and shutdown time. 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%) Signed-off-by: Peng Hao <peng.hao2@zte.com.cn> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 9943450 commit 0804c84

File tree

4 files changed

+30
-11
lines changed

4 files changed

+30
-11
lines changed

Documentation/virtual/kvm/api.txt

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3683,27 +3683,31 @@ the definition of struct kvm_nested_state, see KVM_GET_NESTED_STATE.
36833683

36843684
4.116 KVM_(UN)REGISTER_COALESCED_MMIO
36853685

3686-
Capability: KVM_CAP_COALESCED_MMIO
3686+
Capability: KVM_CAP_COALESCED_MMIO (for coalesced mmio)
3687+
KVM_CAP_COALESCED_PIO (for coalesced pio)
36873688
Architectures: all
36883689
Type: vm ioctl
36893690
Parameters: struct kvm_coalesced_mmio_zone
36903691
Returns: 0 on success, < 0 on error
36913692

3692-
Coalesced mmio is a performance optimization that defers hardware
3693+
Coalesced I/O is a performance optimization that defers hardware
36933694
register write emulation so that userspace exits are avoided. It is
36943695
typically used to reduce the overhead of emulating frequently accessed
36953696
hardware registers.
36963697

3697-
When a hardware register is configured for coalesced mmio, write accesses
3698+
When a hardware register is configured for coalesced I/O, write accesses
36983699
do not exit to userspace and their value is recorded in a ring buffer
36993700
that is shared between kernel and userspace.
37003701

3701-
Coalesced mmio is used if one or more write accesses to a hardware
3702+
Coalesced I/O is used if one or more write accesses to a hardware
37023703
register can be deferred until a read or a write to another hardware
37033704
register on the same device. This last access will cause a vmexit and
37043705
userspace will process accesses from the ring buffer before emulating
3705-
it. That will avoid exiting to userspace on repeated writes to the
3706-
first register.
3706+
it. That will avoid exiting to userspace on repeated writes.
3707+
3708+
Coalesced pio is based on coalesced mmio. There is little difference
3709+
between coalesced mmio and pio except that coalesced pio records accesses
3710+
to I/O ports.
37073711

37083712
5. The kvm_run structure
37093713
------------------------

include/uapi/linux/kvm.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,13 +420,19 @@ struct kvm_run {
420420
struct kvm_coalesced_mmio_zone {
421421
__u64 addr;
422422
__u32 size;
423-
__u32 pad;
423+
union {
424+
__u32 pad;
425+
__u32 pio;
426+
};
424427
};
425428

426429
struct kvm_coalesced_mmio {
427430
__u64 phys_addr;
428431
__u32 len;
429-
__u32 pad;
432+
union {
433+
__u32 pad;
434+
__u32 pio;
435+
};
430436
__u8 data[8];
431437
};
432438

@@ -956,6 +962,7 @@ struct kvm_ppc_resize_hpt {
956962
#define KVM_CAP_MSR_PLATFORM_INFO 159
957963
#define KVM_CAP_PPC_NESTED_HV 160
958964
#define KVM_CAP_HYPERV_SEND_IPI 161
965+
#define KVM_CAP_COALESCED_PIO 162
959966

960967
#ifdef KVM_CAP_IRQ_ROUTING
961968

virt/kvm/coalesced_mmio.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ static int coalesced_mmio_write(struct kvm_vcpu *vcpu,
8383
ring->coalesced_mmio[ring->last].phys_addr = addr;
8484
ring->coalesced_mmio[ring->last].len = len;
8585
memcpy(ring->coalesced_mmio[ring->last].data, val, len);
86+
ring->coalesced_mmio[ring->last].pio = dev->zone.pio;
8687
smp_wmb();
8788
ring->last = (ring->last + 1) % KVM_COALESCED_MMIO_MAX;
8889
spin_unlock(&dev->kvm->ring_lock);
@@ -140,6 +141,9 @@ int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm,
140141
int ret;
141142
struct kvm_coalesced_mmio_dev *dev;
142143

144+
if (zone->pio != 1 && zone->pio != 0)
145+
return -EINVAL;
146+
143147
dev = kzalloc(sizeof(struct kvm_coalesced_mmio_dev), GFP_KERNEL);
144148
if (!dev)
145149
return -ENOMEM;
@@ -149,8 +153,9 @@ int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm,
149153
dev->zone = *zone;
150154

151155
mutex_lock(&kvm->slots_lock);
152-
ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, zone->addr,
153-
zone->size, &dev->dev);
156+
ret = kvm_io_bus_register_dev(kvm,
157+
zone->pio ? KVM_PIO_BUS : KVM_MMIO_BUS,
158+
zone->addr, zone->size, &dev->dev);
154159
if (ret < 0)
155160
goto out_free_dev;
156161
list_add_tail(&dev->list, &kvm->coalesced_zones);
@@ -174,7 +179,8 @@ int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm,
174179

175180
list_for_each_entry_safe(dev, tmp, &kvm->coalesced_zones, list)
176181
if (coalesced_mmio_in_range(dev, zone->addr, zone->size)) {
177-
kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &dev->dev);
182+
kvm_io_bus_unregister_dev(kvm,
183+
zone->pio ? KVM_PIO_BUS : KVM_MMIO_BUS, &dev->dev);
178184
kvm_iodevice_destructor(&dev->dev);
179185
}
180186

virt/kvm/kvm_main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2949,6 +2949,8 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
29492949
#ifdef CONFIG_KVM_MMIO
29502950
case KVM_CAP_COALESCED_MMIO:
29512951
return KVM_COALESCED_MMIO_PAGE_OFFSET;
2952+
case KVM_CAP_COALESCED_PIO:
2953+
return 1;
29522954
#endif
29532955
#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
29542956
case KVM_CAP_IRQ_ROUTING:

0 commit comments

Comments
 (0)