Skip to content

Commit

Permalink
KVM: add initial support for KVM_SET_IOREGION
Browse files Browse the repository at this point in the history
This vm ioctl adds or removes an ioregionfd MMIO/PIO region. Guest
read and write accesses are dispatched through the given ioregionfd
instead of returning from ioctl(KVM_RUN). Regions can be deleted by
setting fds to -1.

Signed-off-by: Elena Afanasova <eafanasova@gmail.com>
  • Loading branch information
sbrksb authored and intel-lab-lkp committed Dec 29, 2020
1 parent e13a691 commit 653378d
Show file tree
Hide file tree
Showing 11 changed files with 350 additions and 3 deletions.
1 change: 1 addition & 0 deletions arch/x86/kvm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ config KVM
select HAVE_KVM_IRQ_BYPASS
select HAVE_KVM_IRQ_ROUTING
select HAVE_KVM_EVENTFD
select KVM_IOREGION
select KVM_ASYNC_PF
select USER_RETURN_NOTIFIER
select KVM_MMIO
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kvm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ KVM := ../../../virt/kvm
kvm-y += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \
$(KVM)/eventfd.o $(KVM)/irqchip.o $(KVM)/vfio.o
kvm-$(CONFIG_KVM_ASYNC_PF) += $(KVM)/async_pf.o
kvm-$(CONFIG_KVM_IOREGION) += $(KVM)/ioregion.o

kvm-y += x86.o emulate.o i8259.o irq.o lapic.o \
i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -3739,6 +3739,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_X86_USER_SPACE_MSR:
case KVM_CAP_X86_MSR_FILTER:
case KVM_CAP_ENFORCE_PV_FEATURE_CPUID:
case KVM_CAP_IOREGIONFD:
r = 1;
break;
case KVM_CAP_SYNC_REGS:
Expand Down
17 changes: 17 additions & 0 deletions include/linux/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,10 @@ struct kvm {
struct mutex resampler_lock;
} irqfds;
struct list_head ioeventfds;
#endif
#ifdef CONFIG_KVM_IOREGION
struct list_head ioregions_mmio;
struct list_head ioregions_pio;
#endif
struct kvm_vm_stat stat;
struct kvm_arch arch;
Expand Down Expand Up @@ -1262,6 +1266,19 @@ static inline int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)

#endif /* CONFIG_HAVE_KVM_EVENTFD */

#ifdef CONFIG_KVM_IOREGION
void kvm_ioregionfd_init(struct kvm *kvm);
int kvm_ioregionfd(struct kvm *kvm, struct kvm_ioregion *args);

#else

static inline void kvm_ioregionfd_init(struct kvm *kvm) {}
static inline int kvm_ioregionfd(struct kvm *kvm, struct kvm_ioregion *args)
{
return -ENOSYS;
}
#endif

void kvm_arch_irq_routing_update(struct kvm *kvm);

static inline void kvm_make_request(int req, struct kvm_vcpu *vcpu)
Expand Down
23 changes: 23 additions & 0 deletions include/uapi/linux/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,27 @@ struct kvm_ioeventfd {
__u8 pad[36];
};

enum {
kvm_ioregion_flag_nr_pio,
kvm_ioregion_flag_nr_posted_writes,
kvm_ioregion_flag_nr_max,
};

#define KVM_IOREGION_PIO (1 << kvm_ioregion_flag_nr_pio)
#define KVM_IOREGION_POSTED_WRITES (1 << kvm_ioregion_flag_nr_posted_writes)

#define KVM_IOREGION_VALID_FLAG_MASK ((1 << kvm_ioregion_flag_nr_max) - 1)

struct kvm_ioregion {
__u64 guest_paddr; /* guest physical address */
__u64 memory_size; /* bytes */
__u64 user_data;
__s32 rfd;
__s32 wfd;
__u32 flags;
__u8 pad[28];
};

#define KVM_X86_DISABLE_EXITS_MWAIT (1 << 0)
#define KVM_X86_DISABLE_EXITS_HLT (1 << 1)
#define KVM_X86_DISABLE_EXITS_PAUSE (1 << 2)
Expand Down Expand Up @@ -1053,6 +1074,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_X86_USER_SPACE_MSR 188
#define KVM_CAP_X86_MSR_FILTER 189
#define KVM_CAP_ENFORCE_PV_FEATURE_CPUID 190
#define KVM_CAP_IOREGIONFD 191

#ifdef KVM_CAP_IRQ_ROUTING

Expand Down Expand Up @@ -1308,6 +1330,7 @@ struct kvm_vfio_spapr_tce {
struct kvm_userspace_memory_region)
#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)
#define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64)
#define KVM_SET_IOREGION _IOW(KVMIO, 0x49, struct kvm_ioregion)

/* enable ucontrol for s390 */
struct kvm_s390_ucas_mapping {
Expand Down
3 changes: 3 additions & 0 deletions virt/kvm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ config HAVE_KVM_EVENTFD
bool
select EVENTFD

config KVM_IOREGION
bool

config KVM_MMIO
bool

Expand Down
25 changes: 25 additions & 0 deletions virt/kvm/eventfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <trace/events/kvm.h>

#include <kvm/iodev.h>
#include "ioregion.h"

#ifdef CONFIG_HAVE_KVM_IRQFD

Expand Down Expand Up @@ -755,6 +756,23 @@ static const struct kvm_io_device_ops ioeventfd_ops = {
.destructor = ioeventfd_destructor,
};

#ifdef CONFIG_KVM_IOREGION
/* assumes kvm->slots_lock held */
bool kvm_eventfd_collides(struct kvm *kvm, int bus_idx,
u64 start, u64 size)
{
struct _ioeventfd *_p;

list_for_each_entry(_p, &kvm->ioeventfds, list)
if (_p->bus_idx == bus_idx &&
overlap(start, size, _p->addr,
!_p->length ? 8 : _p->length))
return true;

return false;
}
#endif

/* assumes kvm->slots_lock held */
static bool
ioeventfd_check_collision(struct kvm *kvm, struct _ioeventfd *p)
Expand All @@ -770,6 +788,13 @@ ioeventfd_check_collision(struct kvm *kvm, struct _ioeventfd *p)
_p->datamatch == p->datamatch))))
return true;

#ifdef CONFIG_KVM_IOREGION
if (p->bus_idx == KVM_MMIO_BUS || p->bus_idx == KVM_PIO_BUS)
if (kvm_ioregion_collides(kvm, p->bus_idx, p->addr,
!p->length ? 8 : p->length))
return true;
#endif

return false;
}

Expand Down
14 changes: 14 additions & 0 deletions virt/kvm/eventfd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __KVM_EVENTFD_H__
#define __KVM_EVENTFD_H__

#ifdef CONFIG_KVM_IOREGION
bool kvm_eventfd_collides(struct kvm *kvm, int bus_idx, u64 start, u64 size);
#else
static inline bool
kvm_eventfd_collides(struct kvm *kvm, int bus_idx, u64 start, u64 size)
{
return false;
}
#endif
#endif
Loading

0 comments on commit 653378d

Please sign in to comment.