* [RFC PATCH 0/5] ARM: KVM: Enable the ioeventfd capability of KVM on ARM
@ 2014-11-24 21:26 Nikolay Nikolaev
2014-11-24 21:26 ` [RFC PATCH 1/5] KVM: redesing kvm_io_bus_ API to pass VCPU structure to the callbacks Nikolay Nikolaev
` (5 more replies)
0 siblings, 6 replies; 29+ messages in thread
From: Nikolay Nikolaev @ 2014-11-24 21:26 UTC (permalink / raw)
To: linux-arm-kernel
The IOEVENTFD KVM capability is a prerequisite for vhost support,
and is also used to implement improved interrupt handling in VFIO drivers.
This series enables the ioeventfd KVM capability on ARM.
The implementation routes MMIO access in the IO abort handler to the KVM IO bus.
If there is already a registered ioeventfd handler for this address, the file
descriptor will be triggered.
We extended the KVM IO bus API to expose the VCPU struct pointer. Now the VGIC
MMIO access is done through this API. For this to operate the VGIC registers a
kvm_io_device which reprresents the whole MMIO region.
The patches are implemented on top of the latest Andre's vGICv3 work from here:
http://www.linux-arm.org/git?p=linux-ap.git;a=shortlog;h=refs/heads/kvm-gicv3/v4
The code was tested on Dual Cortex-A15 Exynos5250 (ARM Chromebook).
---
Nikolay Nikolaev (5):
KVM: redesing kvm_io_bus_ API to pass VCPU structure to the callbacks.
ARM: on IO mem abort - route the call to KVM MMIO bus
KVM: ARM VGIC add kvm_io_bus_ frontend
ARM: enable linking against eventfd and irqchip
ARM: enable KVM_CAP_IOEVENTFD
arch/arm/kvm/Kconfig | 1 +
arch/arm/kvm/Makefile | 2 +
arch/arm/kvm/arm.c | 3 ++
arch/arm/kvm/mmio.c | 32 ++++++++++++++++
arch/ia64/kvm/kvm-ia64.c | 4 +-
arch/powerpc/kvm/powerpc.c | 4 +-
arch/s390/kvm/diag.c | 2 +
arch/x86/kvm/vmx.c | 2 +
arch/x86/kvm/x86.c | 11 +++---
include/kvm/arm_vgic.h | 3 +-
include/linux/kvm_host.h | 10 +++--
virt/kvm/arm/vgic.c | 88 +++++++++++++++++++++++++++++++++++++-------
virt/kvm/coalesced_mmio.c | 5 ++-
virt/kvm/eventfd.c | 4 +-
virt/kvm/iodev.h | 23 ++++++++----
virt/kvm/kvm_main.c | 32 ++++++++--------
16 files changed, 163 insertions(+), 63 deletions(-)
--
Signature
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 1/5] KVM: redesing kvm_io_bus_ API to pass VCPU structure to the callbacks.
2014-11-24 21:26 [RFC PATCH 0/5] ARM: KVM: Enable the ioeventfd capability of KVM on ARM Nikolay Nikolaev
@ 2014-11-24 21:26 ` Nikolay Nikolaev
2014-11-26 17:03 ` Eric Auger
2014-11-24 21:26 ` [RFC PATCH 2/5] ARM: on IO mem abort - route the call to KVM MMIO bus Nikolay Nikolaev
` (4 subsequent siblings)
5 siblings, 1 reply; 29+ messages in thread
From: Nikolay Nikolaev @ 2014-11-24 21:26 UTC (permalink / raw)
To: linux-arm-kernel
This is needed in e.g. ARM vGIC emulation, where the MMIO handling
depends on the VCPU that does the access.
Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
---
arch/ia64/kvm/kvm-ia64.c | 4 ++--
arch/powerpc/kvm/powerpc.c | 4 ++--
arch/s390/kvm/diag.c | 2 +-
arch/x86/kvm/vmx.c | 2 +-
arch/x86/kvm/x86.c | 11 ++++++-----
include/linux/kvm_host.h | 10 +++++-----
virt/kvm/coalesced_mmio.c | 5 +++--
virt/kvm/eventfd.c | 4 ++--
virt/kvm/iodev.h | 23 +++++++++++++++--------
virt/kvm/kvm_main.c | 32 ++++++++++++++++----------------
10 files changed, 53 insertions(+), 44 deletions(-)
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index ec6b9ac..16f1d26 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -246,10 +246,10 @@ static int handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
return 0;
mmio:
if (p->dir)
- r = kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, p->addr,
+ r = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, p->addr,
p->size, &p->data);
else
- r = kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, p->addr,
+ r = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, p->addr,
p->size, &p->data);
if (r)
printk(KERN_ERR"kvm: No iodevice found! addr:%lx\n", p->addr);
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index c1f8f53..5ac065b 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -814,7 +814,7 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
idx = srcu_read_lock(&vcpu->kvm->srcu);
- ret = kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr,
+ ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, run->mmio.phys_addr,
bytes, &run->mmio.data);
srcu_read_unlock(&vcpu->kvm->srcu, idx);
@@ -887,7 +887,7 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
idx = srcu_read_lock(&vcpu->kvm->srcu);
- ret = kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr,
+ ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, run->mmio.phys_addr,
bytes, &run->mmio.data);
srcu_read_unlock(&vcpu->kvm->srcu, idx);
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
index 9254aff..329ec75 100644
--- a/arch/s390/kvm/diag.c
+++ b/arch/s390/kvm/diag.c
@@ -213,7 +213,7 @@ static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu)
* - gpr 3 contains the virtqueue index (passed as datamatch)
* - gpr 4 contains the index on the bus (optionally)
*/
- ret = kvm_io_bus_write_cookie(vcpu->kvm, KVM_VIRTIO_CCW_NOTIFY_BUS,
+ ret = kvm_io_bus_write_cookie(vcpu, KVM_VIRTIO_CCW_NOTIFY_BUS,
vcpu->run->s.regs.gprs[2] & 0xffffffff,
8, &vcpu->run->s.regs.gprs[3],
vcpu->run->s.regs.gprs[4]);
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 3e556c6..e6d9f01 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -5620,7 +5620,7 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
gpa_t gpa;
gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
- if (!kvm_io_bus_write(vcpu->kvm, KVM_FAST_MMIO_BUS, gpa, 0, NULL)) {
+ if (!kvm_io_bus_write(vcpu, KVM_FAST_MMIO_BUS, gpa, 0, NULL)) {
skip_emulated_instruction(vcpu);
return 1;
}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0033df3..bbf9375 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4053,7 +4053,7 @@ static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len,
n = min(len, 8);
if (!(vcpu->arch.apic &&
!kvm_iodevice_write(&vcpu->arch.apic->dev, addr, n, v))
- && kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
+ && kvm_io_bus_write(vcpu, KVM_MMIO_BUS, addr, n, v))
break;
handled += n;
addr += n;
@@ -4072,8 +4072,9 @@ static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
do {
n = min(len, 8);
if (!(vcpu->arch.apic &&
- !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, n, v))
- && kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
+ !kvm_iodevice_read(vcpu, &vcpu->arch.apic->dev,
+ addr, n, v))
+ && kvm_io_bus_read(vcpu, KVM_MMIO_BUS, addr, n, v))
break;
trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, *(u64 *)v);
handled += n;
@@ -4565,10 +4566,10 @@ static int kernel_pio(struct kvm_vcpu *vcpu, void *pd)
int r;
if (vcpu->arch.pio.in)
- r = kvm_io_bus_read(vcpu->kvm, KVM_PIO_BUS, vcpu->arch.pio.port,
+ r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port,
vcpu->arch.pio.size, pd);
else
- r = kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS,
+ r = kvm_io_bus_write(vcpu, KVM_PIO_BUS,
vcpu->arch.pio.port, vcpu->arch.pio.size,
pd);
return r;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 4a7798e..1d26571 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -168,12 +168,12 @@ enum kvm_bus {
KVM_NR_BUSES
};
-int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+int kvm_io_bus_write(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
int len, const void *val);
-int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
- int len, const void *val, long cookie);
-int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len,
- void *val);
+int kvm_io_bus_write_cookie(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx,
+ gpa_t addr, int len, const void *val, long cookie);
+int kvm_io_bus_read(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
+ int len, void *val);
int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
int len, struct kvm_io_device *dev);
int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c
index 00d8642..c831a40 100644
--- a/virt/kvm/coalesced_mmio.c
+++ b/virt/kvm/coalesced_mmio.c
@@ -60,8 +60,9 @@ static int coalesced_mmio_has_room(struct kvm_coalesced_mmio_dev *dev)
return 1;
}
-static int coalesced_mmio_write(struct kvm_io_device *this,
- gpa_t addr, int len, const void *val)
+static int coalesced_mmio_write(struct kvm_vcpu *vcpu,
+ struct kvm_io_device *this, gpa_t addr,
+ int len, const void *val)
{
struct kvm_coalesced_mmio_dev *dev = to_mmio(this);
struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring;
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index b0fb390..7202039 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -719,8 +719,8 @@ ioeventfd_in_range(struct _ioeventfd *p, gpa_t addr, int len, const void *val)
/* MMIO/PIO writes trigger an event if the addr/val match */
static int
-ioeventfd_write(struct kvm_io_device *this, gpa_t addr, int len,
- const void *val)
+ioeventfd_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this, gpa_t addr,
+ int len, const void *val)
{
struct _ioeventfd *p = to_ioeventfd(this);
diff --git a/virt/kvm/iodev.h b/virt/kvm/iodev.h
index 12fd3ca..7dd88cb 100644
--- a/virt/kvm/iodev.h
+++ b/virt/kvm/iodev.h
@@ -20,6 +20,7 @@
#include <asm/errno.h>
struct kvm_io_device;
+struct kvm_vcpu;
/**
* kvm_io_device_ops are called under kvm slots_lock.
@@ -27,11 +28,13 @@ struct kvm_io_device;
* or non-zero to have it passed to the next device.
**/
struct kvm_io_device_ops {
- int (*read)(struct kvm_io_device *this,
+ int (*read)(struct kvm_vcpu *vcpu,
+ struct kvm_io_device *this,
gpa_t addr,
int len,
void *val);
- int (*write)(struct kvm_io_device *this,
+ int (*write)(struct kvm_vcpu *vcpu,
+ struct kvm_io_device *this,
gpa_t addr,
int len,
const void *val);
@@ -49,16 +52,20 @@ static inline void kvm_iodevice_init(struct kvm_io_device *dev,
dev->ops = ops;
}
-static inline int kvm_iodevice_read(struct kvm_io_device *dev,
- gpa_t addr, int l, void *v)
+static inline int kvm_iodevice_read(struct kvm_vcpu *vcpu,
+ struct kvm_io_device *dev, gpa_t addr,
+ int l, void *v)
{
- return dev->ops->read ? dev->ops->read(dev, addr, l, v) : -EOPNOTSUPP;
+ return dev->ops->read ? dev->ops->read(vcpu, dev, addr, l, v)
+ : -EOPNOTSUPP;
}
-static inline int kvm_iodevice_write(struct kvm_io_device *dev,
- gpa_t addr, int l, const void *v)
+static inline int kvm_iodevice_write(struct kvm_vcpu *vcpu,
+ struct kvm_io_device *dev, gpa_t addr,
+ int l, const void *v)
{
- return dev->ops->write ? dev->ops->write(dev, addr, l, v) : -EOPNOTSUPP;
+ return dev->ops->write ? dev->ops->write(vcpu, dev, addr, l, v)
+ : -EOPNOTSUPP;
}
static inline void kvm_iodevice_destructor(struct kvm_io_device *dev)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 25ffac9..e93fb53 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2924,7 +2924,7 @@ static int kvm_io_bus_get_first_dev(struct kvm_io_bus *bus,
return off;
}
-static int __kvm_io_bus_write(struct kvm_io_bus *bus,
+static int __kvm_io_bus_write(struct kvm_vcpu *vcpu, struct kvm_io_bus *bus,
struct kvm_io_range *range, const void *val)
{
int idx;
@@ -2935,7 +2935,7 @@ static int __kvm_io_bus_write(struct kvm_io_bus *bus,
while (idx < bus->dev_count &&
kvm_io_bus_cmp(range, &bus->range[idx]) == 0) {
- if (!kvm_iodevice_write(bus->range[idx].dev, range->addr,
+ if (!kvm_iodevice_write(vcpu, bus->range[idx].dev, range->addr,
range->len, val))
return idx;
idx++;
@@ -2945,7 +2945,7 @@ static int __kvm_io_bus_write(struct kvm_io_bus *bus,
}
/* kvm_io_bus_write - called under kvm->slots_lock */
-int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+int kvm_io_bus_write(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
int len, const void *val)
{
struct kvm_io_bus *bus;
@@ -2957,14 +2957,14 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
.len = len,
};
- bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
- r = __kvm_io_bus_write(bus, &range, val);
+ bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &kvm->srcu);
+ r = __kvm_io_bus_write(vcpu, bus, &range, val);
return r < 0 ? r : 0;
}
/* kvm_io_bus_write_cookie - called under kvm->slots_lock */
-int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
- int len, const void *val, long cookie)
+int kvm_io_bus_write_cookie(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx,
+ gpa_t addr, int len, const void *val, long cookie)
{
struct kvm_io_bus *bus;
struct kvm_io_range range;
@@ -2974,12 +2974,12 @@ int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
.len = len,
};
- bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
+ bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &kvm->srcu);
/* First try the device referenced by cookie. */
if ((cookie >= 0) && (cookie < bus->dev_count) &&
(kvm_io_bus_cmp(&range, &bus->range[cookie]) == 0))
- if (!kvm_iodevice_write(bus->range[cookie].dev, addr, len,
+ if (!kvm_iodevice_write(vcpu, bus->range[cookie].dev, addr, len,
val))
return cookie;
@@ -2987,11 +2987,11 @@ int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
* cookie contained garbage; fall back to search and return the
* correct cookie value.
*/
- return __kvm_io_bus_write(bus, &range, val);
+ return __kvm_io_bus_write(vcpu, bus, &range, val);
}
-static int __kvm_io_bus_read(struct kvm_io_bus *bus, struct kvm_io_range *range,
- void *val)
+static int __kvm_io_bus_read(struct kvm_vcpu *vcpu, struct kvm_io_bus *bus,
+ struct kvm_io_range *range, void *val)
{
int idx;
@@ -3001,7 +3001,7 @@ static int __kvm_io_bus_read(struct kvm_io_bus *bus, struct kvm_io_range *range,
while (idx < bus->dev_count &&
kvm_io_bus_cmp(range, &bus->range[idx]) == 0) {
- if (!kvm_iodevice_read(bus->range[idx].dev, range->addr,
+ if (!kvm_iodevice_read(vcpu, bus->range[idx].dev, range->addr,
range->len, val))
return idx;
idx++;
@@ -3012,7 +3012,7 @@ static int __kvm_io_bus_read(struct kvm_io_bus *bus, struct kvm_io_range *range,
EXPORT_SYMBOL_GPL(kvm_io_bus_write);
/* kvm_io_bus_read - called under kvm->slots_lock */
-int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+int kvm_io_bus_read(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
int len, void *val)
{
struct kvm_io_bus *bus;
@@ -3024,8 +3024,8 @@ int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
.len = len,
};
- bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
- r = __kvm_io_bus_read(bus, &range, val);
+ bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &kvm->srcu);
+ r = __kvm_io_bus_read(vcpu, bus, &range, val);
return r < 0 ? r : 0;
}
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCH 2/5] ARM: on IO mem abort - route the call to KVM MMIO bus
2014-11-24 21:26 [RFC PATCH 0/5] ARM: KVM: Enable the ioeventfd capability of KVM on ARM Nikolay Nikolaev
2014-11-24 21:26 ` [RFC PATCH 1/5] KVM: redesing kvm_io_bus_ API to pass VCPU structure to the callbacks Nikolay Nikolaev
@ 2014-11-24 21:26 ` Nikolay Nikolaev
2014-11-27 10:19 ` Eric Auger
` (2 more replies)
2014-11-24 21:26 ` [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend Nikolay Nikolaev
` (3 subsequent siblings)
5 siblings, 3 replies; 29+ messages in thread
From: Nikolay Nikolaev @ 2014-11-24 21:26 UTC (permalink / raw)
To: linux-arm-kernel
On IO memory abort, try to handle the MMIO access thorugh the KVM
registered read/write callbacks. This is done by invoking the relevant
kvm_io_bus_* API.
Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
---
arch/arm/kvm/mmio.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 4cb5a93..81230da 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -162,6 +162,36 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
return 0;
}
+/**
+ * kvm_handle_mmio - handle an in-kernel MMIO access
+ * @vcpu: pointer to the vcpu performing the access
+ * @run: pointer to the kvm_run structure
+ * @mmio: pointer to the data describing the access
+ *
+ * returns true if the MMIO access has been performed in kernel space,
+ * and false if it needs to be emulated in user space.
+ */
+static bool handle_kernel_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
+ struct kvm_exit_mmio *mmio)
+{
+ int ret;
+
+ if (mmio->is_write) {
+ ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, mmio->phys_addr,
+ mmio->len, &mmio->data);
+
+ } else {
+ ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, mmio->phys_addr,
+ mmio->len, &mmio->data);
+ }
+ if (!ret) {
+ kvm_prepare_mmio(run, mmio);
+ kvm_handle_mmio_return(vcpu, run);
+ }
+
+ return !ret;
+}
+
int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
phys_addr_t fault_ipa)
{
@@ -200,6 +230,9 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
if (vgic_handle_mmio(vcpu, run, &mmio))
return 1;
+ if (handle_kernel_mmio(vcpu, run, &mmio))
+ return 1;
+
kvm_prepare_mmio(run, &mmio);
return 0;
}
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend
2014-11-24 21:26 [RFC PATCH 0/5] ARM: KVM: Enable the ioeventfd capability of KVM on ARM Nikolay Nikolaev
2014-11-24 21:26 ` [RFC PATCH 1/5] KVM: redesing kvm_io_bus_ API to pass VCPU structure to the callbacks Nikolay Nikolaev
2014-11-24 21:26 ` [RFC PATCH 2/5] ARM: on IO mem abort - route the call to KVM MMIO bus Nikolay Nikolaev
@ 2014-11-24 21:26 ` Nikolay Nikolaev
2014-11-27 10:51 ` Eric Auger
` (4 more replies)
2014-11-24 21:27 ` [RFC PATCH 4/5] ARM: enable linking against eventfd and irqchip Nikolay Nikolaev
` (2 subsequent siblings)
5 siblings, 5 replies; 29+ messages in thread
From: Nikolay Nikolaev @ 2014-11-24 21:26 UTC (permalink / raw)
To: linux-arm-kernel
In io_mem_abort remove the call to vgic_handle_mmio. The target is to have
a single MMIO handling path - that is through the kvm_io_bus_ API.
Register a kvm_io_device in kvm_vgic_init on the whole vGIC MMIO region.
Both read and write calls are redirected to vgic_io_dev_access where
kvm_exit_mmio is composed to pass it to vm_ops.handle_mmio.
Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
---
arch/arm/kvm/mmio.c | 3 --
include/kvm/arm_vgic.h | 3 +-
virt/kvm/arm/vgic.c | 88 ++++++++++++++++++++++++++++++++++++++++--------
3 files changed, 74 insertions(+), 20 deletions(-)
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 81230da..1c44a2b 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -227,9 +227,6 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
if (mmio.is_write)
mmio_write_buf(mmio.data, mmio.len, data);
- if (vgic_handle_mmio(vcpu, run, &mmio))
- return 1;
-
if (handle_kernel_mmio(vcpu, run, &mmio))
return 1;
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index e452ef7..d9b7d2a 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -233,6 +233,7 @@ struct vgic_dist {
unsigned long *irq_pending_on_cpu;
struct vgic_vm_ops vm_ops;
+ struct kvm_io_device *io_dev;
#endif
};
@@ -307,8 +308,6 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
bool level);
void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
-bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
- struct kvm_exit_mmio *mmio);
#define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel))
#define vgic_initialized(k) ((k)->arch.vgic.ready)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 1213da5..3da1115 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -31,6 +31,9 @@
#include <asm/kvm_emulate.h>
#include <asm/kvm_arm.h>
#include <asm/kvm_mmu.h>
+#include <asm/kvm.h>
+
+#include "iodev.h"
/*
* How the whole thing works (courtesy of Christoffer Dall):
@@ -775,28 +778,81 @@ bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
return true;
}
-/**
- * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
- * @vcpu: pointer to the vcpu performing the access
- * @run: pointer to the kvm_run structure
- * @mmio: pointer to the data describing the access
- *
- * returns true if the MMIO access has been performed in kernel space,
- * and false if it needs to be emulated in user space.
- * Calls the actual handling routine for the selected VGIC model.
- */
-bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
- struct kvm_exit_mmio *mmio)
+static int vgic_io_dev_access(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
+ gpa_t addr, int len, void *val, bool is_write)
{
- if (!irqchip_in_kernel(vcpu->kvm))
- return false;
+ struct kvm_exit_mmio mmio;
+ bool ret;
+
+ mmio = (struct kvm_exit_mmio) {
+ .phys_addr = addr,
+ .len = len,
+ .is_write = is_write,
+ };
+
+ if (is_write)
+ memcpy(mmio.data, val, len);
/*
* This will currently call either vgic_v2_handle_mmio() or
* vgic_v3_handle_mmio(), which in turn will call
* vgic_handle_mmio_range() defined above.
*/
- return vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, run, mmio);
+ ret = vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, vcpu->run, &mmio);
+
+ if (!is_write)
+ memcpy(val, mmio.data, len);
+
+ return ret ? 0 : 1;
+}
+
+static int vgic_io_dev_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
+ gpa_t addr, int len, void *val)
+{
+ return vgic_io_dev_access(vcpu, this, addr, len, val, false);
+}
+
+static int vgic_io_dev_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
+ gpa_t addr, int len, const void *val)
+{
+ return vgic_io_dev_access(vcpu, this, addr, len, (void *)val, true);
+}
+
+static const struct kvm_io_device_ops vgic_io_dev_ops = {
+ .read = vgic_io_dev_read,
+ .write = vgic_io_dev_write,
+};
+
+static int vgic_register_kvm_io_dev(struct kvm *kvm)
+{
+ struct kvm_io_device *dev;
+ int ret;
+
+ struct vgic_dist *dist = &kvm->arch.vgic;
+ unsigned long base = dist->vgic_dist_base;
+
+ dev = kzalloc(sizeof(struct kvm_io_device), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ kvm_iodevice_init(dev, &vgic_io_dev_ops);
+
+ mutex_lock(&kvm->slots_lock);
+
+ ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
+ base, KVM_VGIC_V2_DIST_SIZE, dev);
+ if (ret < 0)
+ goto out_free_dev;
+ mutex_unlock(&kvm->slots_lock);
+
+ kvm->arch.vgic.io_dev = dev;
+
+ return 0;
+
+out_free_dev:
+ mutex_unlock(&kvm->slots_lock);
+ kfree(dev);
+ return ret;
}
static int vgic_nr_shared_irqs(struct vgic_dist *dist)
@@ -1545,6 +1601,8 @@ int kvm_vgic_init(struct kvm *kvm)
mutex_lock(&kvm->lock);
+ vgic_register_kvm_io_dev(kvm);
+
if (vgic_initialized(kvm))
goto out;
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCH 4/5] ARM: enable linking against eventfd and irqchip
2014-11-24 21:26 [RFC PATCH 0/5] ARM: KVM: Enable the ioeventfd capability of KVM on ARM Nikolay Nikolaev
` (2 preceding siblings ...)
2014-11-24 21:26 ` [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend Nikolay Nikolaev
@ 2014-11-24 21:27 ` Nikolay Nikolaev
2014-11-26 16:58 ` Eric Auger
` (2 more replies)
2014-11-24 21:27 ` [RFC PATCH 5/5] ARM: enable KVM_CAP_IOEVENTFD Nikolay Nikolaev
2014-11-27 11:01 ` [RFC PATCH 0/5] ARM: KVM: Enable the ioeventfd capability of KVM on ARM Eric Auger
5 siblings, 3 replies; 29+ messages in thread
From: Nikolay Nikolaev @ 2014-11-24 21:27 UTC (permalink / raw)
To: linux-arm-kernel
This enables compilation of the eventfd feature on ARM.
Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
---
arch/arm/kvm/Kconfig | 1 +
arch/arm/kvm/Makefile | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 466bd29..a4b0312 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -20,6 +20,7 @@ config KVM
bool "Kernel-based Virtual Machine (KVM) support"
select PREEMPT_NOTIFIERS
select ANON_INODES
+ select HAVE_KVM_EVENTFD
select HAVE_KVM_CPU_RELAX_INTERCEPT
select KVM_MMIO
select KVM_ARM_HOST
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index 443b8be..539c1a5 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -15,7 +15,7 @@ AFLAGS_init.o := -Wa,-march=armv7-a$(plus_virt)
AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt)
KVM := ../../../virt/kvm
-kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o
+kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o
obj-y += kvm-arm.o init.o interrupts.o
obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCH 5/5] ARM: enable KVM_CAP_IOEVENTFD
2014-11-24 21:26 [RFC PATCH 0/5] ARM: KVM: Enable the ioeventfd capability of KVM on ARM Nikolay Nikolaev
` (3 preceding siblings ...)
2014-11-24 21:27 ` [RFC PATCH 4/5] ARM: enable linking against eventfd and irqchip Nikolay Nikolaev
@ 2014-11-24 21:27 ` Nikolay Nikolaev
2014-11-27 11:01 ` [RFC PATCH 0/5] ARM: KVM: Enable the ioeventfd capability of KVM on ARM Eric Auger
5 siblings, 0 replies; 29+ messages in thread
From: Nikolay Nikolaev @ 2014-11-24 21:27 UTC (permalink / raw)
To: linux-arm-kernel
KVM on arm will support the eventfd extension.
Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
---
arch/arm/kvm/arm.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index c3d0fbd..266b618 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -197,6 +197,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_MAX_VCPUS:
r = KVM_MAX_VCPUS;
break;
+ case KVM_CAP_IOEVENTFD:
+ r = 1;
+ break;
default:
r = kvm_arch_dev_ioctl_check_extension(ext);
break;
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCH 4/5] ARM: enable linking against eventfd and irqchip
2014-11-24 21:27 ` [RFC PATCH 4/5] ARM: enable linking against eventfd and irqchip Nikolay Nikolaev
@ 2014-11-26 16:58 ` Eric Auger
2014-11-29 7:18 ` Shannon Zhao
2014-11-29 11:29 ` Christoffer Dall
2 siblings, 0 replies; 29+ messages in thread
From: Eric Auger @ 2014-11-26 16:58 UTC (permalink / raw)
To: linux-arm-kernel
On 11/24/2014 10:27 PM, Nikolay Nikolaev wrote:
> This enables compilation of the eventfd feature on ARM.
Hi Nikolay,
why irqchip in the title?
Best Regards
Eric
>
> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> ---
> arch/arm/kvm/Kconfig | 1 +
> arch/arm/kvm/Makefile | 2 +-
> 2 files changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
> index 466bd29..a4b0312 100644
> --- a/arch/arm/kvm/Kconfig
> +++ b/arch/arm/kvm/Kconfig
> @@ -20,6 +20,7 @@ config KVM
> bool "Kernel-based Virtual Machine (KVM) support"
> select PREEMPT_NOTIFIERS
> select ANON_INODES
> + select HAVE_KVM_EVENTFD
> select HAVE_KVM_CPU_RELAX_INTERCEPT
> select KVM_MMIO
> select KVM_ARM_HOST
> diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
> index 443b8be..539c1a5 100644
> --- a/arch/arm/kvm/Makefile
> +++ b/arch/arm/kvm/Makefile
> @@ -15,7 +15,7 @@ AFLAGS_init.o := -Wa,-march=armv7-a$(plus_virt)
> AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt)
>
> KVM := ../../../virt/kvm
> -kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o
> +kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o
>
> obj-y += kvm-arm.o init.o interrupts.o
> obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 1/5] KVM: redesing kvm_io_bus_ API to pass VCPU structure to the callbacks.
2014-11-24 21:26 ` [RFC PATCH 1/5] KVM: redesing kvm_io_bus_ API to pass VCPU structure to the callbacks Nikolay Nikolaev
@ 2014-11-26 17:03 ` Eric Auger
0 siblings, 0 replies; 29+ messages in thread
From: Eric Auger @ 2014-11-26 17:03 UTC (permalink / raw)
To: linux-arm-kernel
Hi Nikolay,
typo in the title,
On 11/24/2014 10:26 PM, Nikolay Nikolaev wrote:
> This is needed in e.g. ARM vGIC emulation, where the MMIO handling
> depends on the VCPU that does the access.
>
> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> ---
> arch/ia64/kvm/kvm-ia64.c | 4 ++--
> arch/powerpc/kvm/powerpc.c | 4 ++--
> arch/s390/kvm/diag.c | 2 +-
> arch/x86/kvm/vmx.c | 2 +-
> arch/x86/kvm/x86.c | 11 ++++++-----
> include/linux/kvm_host.h | 10 +++++-----
> virt/kvm/coalesced_mmio.c | 5 +++--
> virt/kvm/eventfd.c | 4 ++--
> virt/kvm/iodev.h | 23 +++++++++++++++--------
> virt/kvm/kvm_main.c | 32 ++++++++++++++++----------------
> 10 files changed, 53 insertions(+), 44 deletions(-)
>
> diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
> index ec6b9ac..16f1d26 100644
> --- a/arch/ia64/kvm/kvm-ia64.c
> +++ b/arch/ia64/kvm/kvm-ia64.c
> @@ -246,10 +246,10 @@ static int handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
> return 0;
> mmio:
> if (p->dir)
> - r = kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, p->addr,
> + r = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, p->addr,
> p->size, &p->data);
> else
> - r = kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, p->addr,
> + r = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, p->addr,
> p->size, &p->data);
> if (r)
> printk(KERN_ERR"kvm: No iodevice found! addr:%lx\n", p->addr);
> diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
> index c1f8f53..5ac065b 100644
> --- a/arch/powerpc/kvm/powerpc.c
> +++ b/arch/powerpc/kvm/powerpc.c
> @@ -814,7 +814,7 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
>
> idx = srcu_read_lock(&vcpu->kvm->srcu);
>
> - ret = kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr,
> + ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, run->mmio.phys_addr,
> bytes, &run->mmio.data);
>
> srcu_read_unlock(&vcpu->kvm->srcu, idx);
> @@ -887,7 +887,7 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
>
> idx = srcu_read_lock(&vcpu->kvm->srcu);
>
> - ret = kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr,
> + ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, run->mmio.phys_addr,
> bytes, &run->mmio.data);
>
> srcu_read_unlock(&vcpu->kvm->srcu, idx);
> diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
> index 9254aff..329ec75 100644
> --- a/arch/s390/kvm/diag.c
> +++ b/arch/s390/kvm/diag.c
> @@ -213,7 +213,7 @@ static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu)
> * - gpr 3 contains the virtqueue index (passed as datamatch)
> * - gpr 4 contains the index on the bus (optionally)
> */
> - ret = kvm_io_bus_write_cookie(vcpu->kvm, KVM_VIRTIO_CCW_NOTIFY_BUS,
> + ret = kvm_io_bus_write_cookie(vcpu, KVM_VIRTIO_CCW_NOTIFY_BUS,
> vcpu->run->s.regs.gprs[2] & 0xffffffff,
> 8, &vcpu->run->s.regs.gprs[3],
> vcpu->run->s.regs.gprs[4]);
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 3e556c6..e6d9f01 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -5620,7 +5620,7 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
> gpa_t gpa;
>
> gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
> - if (!kvm_io_bus_write(vcpu->kvm, KVM_FAST_MMIO_BUS, gpa, 0, NULL)) {
> + if (!kvm_io_bus_write(vcpu, KVM_FAST_MMIO_BUS, gpa, 0, NULL)) {
> skip_emulated_instruction(vcpu);
> return 1;
> }
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 0033df3..bbf9375 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -4053,7 +4053,7 @@ static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len,
> n = min(len, 8);
> if (!(vcpu->arch.apic &&
> !kvm_iodevice_write(&vcpu->arch.apic->dev, addr, n, v))
vcpu param should be added above too.
Eric
> - && kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
> + && kvm_io_bus_write(vcpu, KVM_MMIO_BUS, addr, n, v))
> break;
> handled += n;
> addr += n;
> @@ -4072,8 +4072,9 @@ static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
> do {
> n = min(len, 8);
> if (!(vcpu->arch.apic &&
> - !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, n, v))
> - && kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
> + !kvm_iodevice_read(vcpu, &vcpu->arch.apic->dev,
> + addr, n, v))
> + && kvm_io_bus_read(vcpu, KVM_MMIO_BUS, addr, n, v))
> break;
> trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, *(u64 *)v);
> handled += n;
> @@ -4565,10 +4566,10 @@ static int kernel_pio(struct kvm_vcpu *vcpu, void *pd)
> int r;
>
> if (vcpu->arch.pio.in)
> - r = kvm_io_bus_read(vcpu->kvm, KVM_PIO_BUS, vcpu->arch.pio.port,
> + r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port,
> vcpu->arch.pio.size, pd);
> else
> - r = kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS,
> + r = kvm_io_bus_write(vcpu, KVM_PIO_BUS,
> vcpu->arch.pio.port, vcpu->arch.pio.size,
> pd);
> return r;
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 4a7798e..1d26571 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -168,12 +168,12 @@ enum kvm_bus {
> KVM_NR_BUSES
> };
>
> -int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +int kvm_io_bus_write(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
> int len, const void *val);
> -int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> - int len, const void *val, long cookie);
> -int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len,
> - void *val);
> +int kvm_io_bus_write_cookie(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx,
> + gpa_t addr, int len, const void *val, long cookie);
> +int kvm_io_bus_read(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
> + int len, void *val);
> int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> int len, struct kvm_io_device *dev);
> int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
> diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c
> index 00d8642..c831a40 100644
> --- a/virt/kvm/coalesced_mmio.c
> +++ b/virt/kvm/coalesced_mmio.c
> @@ -60,8 +60,9 @@ static int coalesced_mmio_has_room(struct kvm_coalesced_mmio_dev *dev)
> return 1;
> }
>
> -static int coalesced_mmio_write(struct kvm_io_device *this,
> - gpa_t addr, int len, const void *val)
> +static int coalesced_mmio_write(struct kvm_vcpu *vcpu,
> + struct kvm_io_device *this, gpa_t addr,
> + int len, const void *val)
> {
> struct kvm_coalesced_mmio_dev *dev = to_mmio(this);
> struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring;
> diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
> index b0fb390..7202039 100644
> --- a/virt/kvm/eventfd.c
> +++ b/virt/kvm/eventfd.c
> @@ -719,8 +719,8 @@ ioeventfd_in_range(struct _ioeventfd *p, gpa_t addr, int len, const void *val)
>
> /* MMIO/PIO writes trigger an event if the addr/val match */
> static int
> -ioeventfd_write(struct kvm_io_device *this, gpa_t addr, int len,
> - const void *val)
> +ioeventfd_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this, gpa_t addr,
> + int len, const void *val)
> {
> struct _ioeventfd *p = to_ioeventfd(this);
>
> diff --git a/virt/kvm/iodev.h b/virt/kvm/iodev.h
> index 12fd3ca..7dd88cb 100644
> --- a/virt/kvm/iodev.h
> +++ b/virt/kvm/iodev.h
> @@ -20,6 +20,7 @@
> #include <asm/errno.h>
>
> struct kvm_io_device;
> +struct kvm_vcpu;
>
> /**
> * kvm_io_device_ops are called under kvm slots_lock.
> @@ -27,11 +28,13 @@ struct kvm_io_device;
> * or non-zero to have it passed to the next device.
> **/
> struct kvm_io_device_ops {
> - int (*read)(struct kvm_io_device *this,
> + int (*read)(struct kvm_vcpu *vcpu,
> + struct kvm_io_device *this,
> gpa_t addr,
> int len,
> void *val);
> - int (*write)(struct kvm_io_device *this,
> + int (*write)(struct kvm_vcpu *vcpu,
> + struct kvm_io_device *this,
> gpa_t addr,
> int len,
> const void *val);
> @@ -49,16 +52,20 @@ static inline void kvm_iodevice_init(struct kvm_io_device *dev,
> dev->ops = ops;
> }
>
> -static inline int kvm_iodevice_read(struct kvm_io_device *dev,
> - gpa_t addr, int l, void *v)
> +static inline int kvm_iodevice_read(struct kvm_vcpu *vcpu,
> + struct kvm_io_device *dev, gpa_t addr,
> + int l, void *v)
> {
> - return dev->ops->read ? dev->ops->read(dev, addr, l, v) : -EOPNOTSUPP;
> + return dev->ops->read ? dev->ops->read(vcpu, dev, addr, l, v)
> + : -EOPNOTSUPP;
> }
>
> -static inline int kvm_iodevice_write(struct kvm_io_device *dev,
> - gpa_t addr, int l, const void *v)
> +static inline int kvm_iodevice_write(struct kvm_vcpu *vcpu,
> + struct kvm_io_device *dev, gpa_t addr,
> + int l, const void *v)
> {
> - return dev->ops->write ? dev->ops->write(dev, addr, l, v) : -EOPNOTSUPP;
> + return dev->ops->write ? dev->ops->write(vcpu, dev, addr, l, v)
> + : -EOPNOTSUPP;
> }
>
> static inline void kvm_iodevice_destructor(struct kvm_io_device *dev)
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 25ffac9..e93fb53 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2924,7 +2924,7 @@ static int kvm_io_bus_get_first_dev(struct kvm_io_bus *bus,
> return off;
> }
>
> -static int __kvm_io_bus_write(struct kvm_io_bus *bus,
> +static int __kvm_io_bus_write(struct kvm_vcpu *vcpu, struct kvm_io_bus *bus,
> struct kvm_io_range *range, const void *val)
> {
> int idx;
> @@ -2935,7 +2935,7 @@ static int __kvm_io_bus_write(struct kvm_io_bus *bus,
>
> while (idx < bus->dev_count &&
> kvm_io_bus_cmp(range, &bus->range[idx]) == 0) {
> - if (!kvm_iodevice_write(bus->range[idx].dev, range->addr,
> + if (!kvm_iodevice_write(vcpu, bus->range[idx].dev, range->addr,
> range->len, val))
> return idx;
> idx++;
> @@ -2945,7 +2945,7 @@ static int __kvm_io_bus_write(struct kvm_io_bus *bus,
> }
>
> /* kvm_io_bus_write - called under kvm->slots_lock */
> -int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +int kvm_io_bus_write(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
> int len, const void *val)
> {
> struct kvm_io_bus *bus;
> @@ -2957,14 +2957,14 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> .len = len,
> };
>
> - bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
> - r = __kvm_io_bus_write(bus, &range, val);
> + bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &kvm->srcu);
> + r = __kvm_io_bus_write(vcpu, bus, &range, val);
> return r < 0 ? r : 0;
> }
>
> /* kvm_io_bus_write_cookie - called under kvm->slots_lock */
> -int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> - int len, const void *val, long cookie)
> +int kvm_io_bus_write_cookie(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx,
> + gpa_t addr, int len, const void *val, long cookie)
> {
> struct kvm_io_bus *bus;
> struct kvm_io_range range;
> @@ -2974,12 +2974,12 @@ int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> .len = len,
> };
>
> - bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
> + bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &kvm->srcu);
>
> /* First try the device referenced by cookie. */
> if ((cookie >= 0) && (cookie < bus->dev_count) &&
> (kvm_io_bus_cmp(&range, &bus->range[cookie]) == 0))
> - if (!kvm_iodevice_write(bus->range[cookie].dev, addr, len,
> + if (!kvm_iodevice_write(vcpu, bus->range[cookie].dev, addr, len,
> val))
> return cookie;
>
> @@ -2987,11 +2987,11 @@ int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> * cookie contained garbage; fall back to search and return the
> * correct cookie value.
> */
> - return __kvm_io_bus_write(bus, &range, val);
> + return __kvm_io_bus_write(vcpu, bus, &range, val);
> }
>
> -static int __kvm_io_bus_read(struct kvm_io_bus *bus, struct kvm_io_range *range,
> - void *val)
> +static int __kvm_io_bus_read(struct kvm_vcpu *vcpu, struct kvm_io_bus *bus,
> + struct kvm_io_range *range, void *val)
> {
> int idx;
>
> @@ -3001,7 +3001,7 @@ static int __kvm_io_bus_read(struct kvm_io_bus *bus, struct kvm_io_range *range,
>
> while (idx < bus->dev_count &&
> kvm_io_bus_cmp(range, &bus->range[idx]) == 0) {
> - if (!kvm_iodevice_read(bus->range[idx].dev, range->addr,
> + if (!kvm_iodevice_read(vcpu, bus->range[idx].dev, range->addr,
> range->len, val))
> return idx;
> idx++;
> @@ -3012,7 +3012,7 @@ static int __kvm_io_bus_read(struct kvm_io_bus *bus, struct kvm_io_range *range,
> EXPORT_SYMBOL_GPL(kvm_io_bus_write);
>
> /* kvm_io_bus_read - called under kvm->slots_lock */
> -int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +int kvm_io_bus_read(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
> int len, void *val)
> {
> struct kvm_io_bus *bus;
> @@ -3024,8 +3024,8 @@ int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> .len = len,
> };
>
> - bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
> - r = __kvm_io_bus_read(bus, &range, val);
> + bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &kvm->srcu);
> + r = __kvm_io_bus_read(vcpu, bus, &range, val);
> return r < 0 ? r : 0;
> }
>
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 2/5] ARM: on IO mem abort - route the call to KVM MMIO bus
2014-11-24 21:26 ` [RFC PATCH 2/5] ARM: on IO mem abort - route the call to KVM MMIO bus Nikolay Nikolaev
@ 2014-11-27 10:19 ` Eric Auger
2014-11-29 11:28 ` Christoffer Dall
2014-11-29 11:29 ` Christoffer Dall
2 siblings, 0 replies; 29+ messages in thread
From: Eric Auger @ 2014-11-27 10:19 UTC (permalink / raw)
To: linux-arm-kernel
On 11/24/2014 10:26 PM, Nikolay Nikolaev wrote:
> On IO memory abort, try to handle the MMIO access thorugh the KVM
typo
> registered read/write callbacks. This is done by invoking the relevant
> kvm_io_bus_* API.
>
> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> ---
> arch/arm/kvm/mmio.c | 33 +++++++++++++++++++++++++++++++++
> 1 file changed, 33 insertions(+)
>
> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
> index 4cb5a93..81230da 100644
> --- a/arch/arm/kvm/mmio.c
> +++ b/arch/arm/kvm/mmio.c
> @@ -162,6 +162,36 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
> return 0;
> }
>
> +/**
> + * kvm_handle_mmio - handle an in-kernel MMIO access
handle_kernel_mmio
> + * @vcpu: pointer to the vcpu performing the access
> + * @run: pointer to the kvm_run structure
> + * @mmio: pointer to the data describing the access
> + *
> + * returns true if the MMIO access has been performed in kernel space,
> + * and false if it needs to be emulated in user space.
> + */
> +static bool handle_kernel_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> + struct kvm_exit_mmio *mmio)
> +{
> + int ret;
> +
> + if (mmio->is_write) {
> + ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, mmio->phys_addr,
> + mmio->len, &mmio->data);
> +
> + } else {
> + ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, mmio->phys_addr,
> + mmio->len, &mmio->data);
> + }
> + if (!ret) {
> + kvm_prepare_mmio(run, mmio);
> + kvm_handle_mmio_return(vcpu, run);
Shouldn't the comment associated to kvm_handle_mmio_return saying
the function "should only be called after returning from userspace for
MMIO load emulation" be updated? Here we did kernel emulation and we
call it. also in vgic it is called. Must aknowledge I do not fully
understand what the .rt is.
> + }
> +
> + return !ret;
what if kvm_io_bus_read returned -EOPNOTSUPP?
> +}
> +
> int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> phys_addr_t fault_ipa)
> {
> @@ -200,6 +230,9 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> if (vgic_handle_mmio(vcpu, run, &mmio))
> return 1;
>
> + if (handle_kernel_mmio(vcpu, run, &mmio))
> + return 1;
> +
> kvm_prepare_mmio(run, &mmio);
> return 0;
> }
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend
2014-11-24 21:26 ` [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend Nikolay Nikolaev
@ 2014-11-27 10:51 ` Eric Auger
2014-11-29 7:14 ` Shannon Zhao
` (3 subsequent siblings)
4 siblings, 0 replies; 29+ messages in thread
From: Eric Auger @ 2014-11-27 10:51 UTC (permalink / raw)
To: linux-arm-kernel
On 11/24/2014 10:26 PM, Nikolay Nikolaev wrote:
> In io_mem_abort remove the call to vgic_handle_mmio. The target is to have
> a single MMIO handling path - that is through the kvm_io_bus_ API.
>
> Register a kvm_io_device in kvm_vgic_init on the whole vGIC MMIO region.
> Both read and write calls are redirected to vgic_io_dev_access where
> kvm_exit_mmio is composed to pass it to vm_ops.handle_mmio.
>
>
> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> ---
> arch/arm/kvm/mmio.c | 3 --
> include/kvm/arm_vgic.h | 3 +-
> virt/kvm/arm/vgic.c | 88 ++++++++++++++++++++++++++++++++++++++++--------
> 3 files changed, 74 insertions(+), 20 deletions(-)
>
> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
> index 81230da..1c44a2b 100644
> --- a/arch/arm/kvm/mmio.c
> +++ b/arch/arm/kvm/mmio.c
> @@ -227,9 +227,6 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> if (mmio.is_write)
> mmio_write_buf(mmio.data, mmio.len, data);
>
> - if (vgic_handle_mmio(vcpu, run, &mmio))
> - return 1;
> -
> if (handle_kernel_mmio(vcpu, run, &mmio))
> return 1;
>
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index e452ef7..d9b7d2a 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -233,6 +233,7 @@ struct vgic_dist {
> unsigned long *irq_pending_on_cpu;
>
> struct vgic_vm_ops vm_ops;
> + struct kvm_io_device *io_dev;
> #endif
> };
>
> @@ -307,8 +308,6 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
> bool level);
> void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
> int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> - struct kvm_exit_mmio *mmio);
>
> #define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel))
> #define vgic_initialized(k) ((k)->arch.vgic.ready)
> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
> index 1213da5..3da1115 100644
> --- a/virt/kvm/arm/vgic.c
> +++ b/virt/kvm/arm/vgic.c
> @@ -31,6 +31,9 @@
> #include <asm/kvm_emulate.h>
> #include <asm/kvm_arm.h>
> #include <asm/kvm_mmu.h>
> +#include <asm/kvm.h>
> +
> +#include "iodev.h"
>
> /*
> * How the whole thing works (courtesy of Christoffer Dall):
> @@ -775,28 +778,81 @@ bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
> return true;
> }
>
> -/**
> - * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
> - * @vcpu: pointer to the vcpu performing the access
> - * @run: pointer to the kvm_run structure
> - * @mmio: pointer to the data describing the access
> - *
> - * returns true if the MMIO access has been performed in kernel space,
> - * and false if it needs to be emulated in user space.
> - * Calls the actual handling routine for the selected VGIC model.
> - */
> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> - struct kvm_exit_mmio *mmio)
may be worth to restore some comments
> +static int vgic_io_dev_access(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, void *val, bool is_write)
> {
> - if (!irqchip_in_kernel(vcpu->kvm))
> - return false;
> + struct kvm_exit_mmio mmio;
> + bool ret;
> +
> + mmio = (struct kvm_exit_mmio) {
> + .phys_addr = addr,
> + .len = len,
> + .is_write = is_write,
> + };
> +
> + if (is_write)
> + memcpy(mmio.data, val, len);
>
> /*
> * This will currently call either vgic_v2_handle_mmio() or
> * vgic_v3_handle_mmio(), which in turn will call
> * vgic_handle_mmio_range() defined above.
> */
> - return vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, run, mmio);
> + ret = vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, vcpu->run, &mmio);
> +
> + if (!is_write)
> + memcpy(val, mmio.data, len);
> +
> + return ret ? 0 : 1;
> +}
> +
> +static int vgic_io_dev_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, void *val)
> +{
> + return vgic_io_dev_access(vcpu, this, addr, len, val, false);
> +}
> +
> +static int vgic_io_dev_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, const void *val)
> +{
> + return vgic_io_dev_access(vcpu, this, addr, len, (void *)val, true);
> +}
> +
> +static const struct kvm_io_device_ops vgic_io_dev_ops = {
> + .read = vgic_io_dev_read,
> + .write = vgic_io_dev_write,
> +};
> +
> +static int vgic_register_kvm_io_dev(struct kvm *kvm)
> +{
> + struct kvm_io_device *dev;
> + int ret;
> +
> + struct vgic_dist *dist = &kvm->arch.vgic;
> + unsigned long base = dist->vgic_dist_base;
Nikolay,
are you sure dist->vgic_dist_base was set by the guest?
in vgic_init/vm_ops.vgic_init (vgic_v2_init) it is tested so I think you
should test it here too.
> +
> + dev = kzalloc(sizeof(struct kvm_io_device), GFP_KERNEL);
> + if (!dev)
> + return -ENOMEM;
> +
> + kvm_iodevice_init(dev, &vgic_io_dev_ops);
> +
> + mutex_lock(&kvm->slots_lock);
> +
> + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
> + base, KVM_VGIC_V2_DIST_SIZE, dev);
> + if (ret < 0)
> + goto out_free_dev;
> + mutex_unlock(&kvm->slots_lock);
> +
> + kvm->arch.vgic.io_dev = dev;
> +
> + return 0;
> +
> +out_free_dev:
> + mutex_unlock(&kvm->slots_lock);
> + kfree(dev);
> + return ret;
> }
>
> static int vgic_nr_shared_irqs(struct vgic_dist *dist)
> @@ -1545,6 +1601,8 @@ int kvm_vgic_init(struct kvm *kvm)
>
> mutex_lock(&kvm->lock);
>
> + vgic_register_kvm_io_dev(kvm);
I think you should move this after below test.
Eric
> +
> if (vgic_initialized(kvm))
> goto out;
>
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 0/5] ARM: KVM: Enable the ioeventfd capability of KVM on ARM
2014-11-24 21:26 [RFC PATCH 0/5] ARM: KVM: Enable the ioeventfd capability of KVM on ARM Nikolay Nikolaev
` (4 preceding siblings ...)
2014-11-24 21:27 ` [RFC PATCH 5/5] ARM: enable KVM_CAP_IOEVENTFD Nikolay Nikolaev
@ 2014-11-27 11:01 ` Eric Auger
5 siblings, 0 replies; 29+ messages in thread
From: Eric Auger @ 2014-11-27 11:01 UTC (permalink / raw)
To: linux-arm-kernel
On 11/24/2014 10:26 PM, Nikolay Nikolaev wrote:
> The IOEVENTFD KVM capability is a prerequisite for vhost support,
> and is also used to implement improved interrupt handling in VFIO drivers.
Hi Nikolay
As far as I am aware, irqfd currently is used in vfio context, not
ioeventfd, although they both are implemented in eventfd.c. Could you
elaborate?
>
> This series enables the ioeventfd KVM capability on ARM.
>
> The implementation routes MMIO access in the IO abort handler to the KVM IO bus.
> If there is already a registered ioeventfd handler for this address, the file
> descriptor will be triggered.
>
> We extended the KVM IO bus API to expose the VCPU struct pointer. Now the VGIC
> MMIO access is done through this API. For this to operate the VGIC registers a
> kvm_io_device which reprresents the whole MMIO region.
typo & the whole dist MMIO region?
I think the transformation makes sense and does not bring upheavals in
the vgic code which is good.
Best Regards
Eric
>
> The patches are implemented on top of the latest Andre's vGICv3 work from here:
> http://www.linux-arm.org/git?p=linux-ap.git;a=shortlog;h=refs/heads/kvm-gicv3/v4
>
> The code was tested on Dual Cortex-A15 Exynos5250 (ARM Chromebook).
>
> ---
>
> Nikolay Nikolaev (5):
> KVM: redesing kvm_io_bus_ API to pass VCPU structure to the callbacks.
> ARM: on IO mem abort - route the call to KVM MMIO bus
> KVM: ARM VGIC add kvm_io_bus_ frontend
> ARM: enable linking against eventfd and irqchip
> ARM: enable KVM_CAP_IOEVENTFD
>
>
> arch/arm/kvm/Kconfig | 1 +
> arch/arm/kvm/Makefile | 2 +
> arch/arm/kvm/arm.c | 3 ++
> arch/arm/kvm/mmio.c | 32 ++++++++++++++++
> arch/ia64/kvm/kvm-ia64.c | 4 +-
> arch/powerpc/kvm/powerpc.c | 4 +-
> arch/s390/kvm/diag.c | 2 +
> arch/x86/kvm/vmx.c | 2 +
> arch/x86/kvm/x86.c | 11 +++---
> include/kvm/arm_vgic.h | 3 +-
> include/linux/kvm_host.h | 10 +++--
> virt/kvm/arm/vgic.c | 88 +++++++++++++++++++++++++++++++++++++-------
> virt/kvm/coalesced_mmio.c | 5 ++-
> virt/kvm/eventfd.c | 4 +-
> virt/kvm/iodev.h | 23 ++++++++----
> virt/kvm/kvm_main.c | 32 ++++++++--------
> 16 files changed, 163 insertions(+), 63 deletions(-)
>
> --
> Signature
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend
2014-11-24 21:26 ` [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend Nikolay Nikolaev
2014-11-27 10:51 ` Eric Auger
@ 2014-11-29 7:14 ` Shannon Zhao
2014-11-29 13:58 ` Nikolay Nikolaev
2014-11-29 11:29 ` Christoffer Dall
` (2 subsequent siblings)
4 siblings, 1 reply; 29+ messages in thread
From: Shannon Zhao @ 2014-11-29 7:14 UTC (permalink / raw)
To: linux-arm-kernel
On 2014/11/25 5:26, Nikolay Nikolaev wrote:
> In io_mem_abort remove the call to vgic_handle_mmio. The target is to have
> a single MMIO handling path - that is through the kvm_io_bus_ API.
>
> Register a kvm_io_device in kvm_vgic_init on the whole vGIC MMIO region.
> Both read and write calls are redirected to vgic_io_dev_access where
> kvm_exit_mmio is composed to pass it to vm_ops.handle_mmio.
>
>
> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> ---
> arch/arm/kvm/mmio.c | 3 --
> include/kvm/arm_vgic.h | 3 +-
> virt/kvm/arm/vgic.c | 88 ++++++++++++++++++++++++++++++++++++++++--------
> 3 files changed, 74 insertions(+), 20 deletions(-)
>
> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
> index 81230da..1c44a2b 100644
> --- a/arch/arm/kvm/mmio.c
> +++ b/arch/arm/kvm/mmio.c
> @@ -227,9 +227,6 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> if (mmio.is_write)
> mmio_write_buf(mmio.data, mmio.len, data);
>
> - if (vgic_handle_mmio(vcpu, run, &mmio))
> - return 1;
> -
> if (handle_kernel_mmio(vcpu, run, &mmio))
> return 1;
>
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index e452ef7..d9b7d2a 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -233,6 +233,7 @@ struct vgic_dist {
> unsigned long *irq_pending_on_cpu;
>
> struct vgic_vm_ops vm_ops;
> + struct kvm_io_device *io_dev;
> #endif
> };
>
> @@ -307,8 +308,6 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
> bool level);
> void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
> int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> - struct kvm_exit_mmio *mmio);
>
> #define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel))
> #define vgic_initialized(k) ((k)->arch.vgic.ready)
> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
> index 1213da5..3da1115 100644
> --- a/virt/kvm/arm/vgic.c
> +++ b/virt/kvm/arm/vgic.c
> @@ -31,6 +31,9 @@
> #include <asm/kvm_emulate.h>
> #include <asm/kvm_arm.h>
> #include <asm/kvm_mmu.h>
> +#include <asm/kvm.h>
> +
> +#include "iodev.h"
>
> /*
> * How the whole thing works (courtesy of Christoffer Dall):
> @@ -775,28 +778,81 @@ bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
> return true;
> }
>
> -/**
> - * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
> - * @vcpu: pointer to the vcpu performing the access
> - * @run: pointer to the kvm_run structure
> - * @mmio: pointer to the data describing the access
> - *
> - * returns true if the MMIO access has been performed in kernel space,
> - * and false if it needs to be emulated in user space.
> - * Calls the actual handling routine for the selected VGIC model.
> - */
> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> - struct kvm_exit_mmio *mmio)
> +static int vgic_io_dev_access(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, void *val, bool is_write)
> {
> - if (!irqchip_in_kernel(vcpu->kvm))
> - return false;
> + struct kvm_exit_mmio mmio;
> + bool ret;
> +
> + mmio = (struct kvm_exit_mmio) {
> + .phys_addr = addr,
> + .len = len,
> + .is_write = is_write,
> + };
> +
> + if (is_write)
> + memcpy(mmio.data, val, len);
>
> /*
> * This will currently call either vgic_v2_handle_mmio() or
> * vgic_v3_handle_mmio(), which in turn will call
> * vgic_handle_mmio_range() defined above.
> */
> - return vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, run, mmio);
> + ret = vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, vcpu->run, &mmio);
> +
> + if (!is_write)
> + memcpy(val, mmio.data, len);
> +
> + return ret ? 0 : 1;
> +}
> +
> +static int vgic_io_dev_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, void *val)
> +{
> + return vgic_io_dev_access(vcpu, this, addr, len, val, false);
> +}
> +
> +static int vgic_io_dev_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, const void *val)
> +{
> + return vgic_io_dev_access(vcpu, this, addr, len, (void *)val, true);
> +}
> +
> +static const struct kvm_io_device_ops vgic_io_dev_ops = {
> + .read = vgic_io_dev_read,
> + .write = vgic_io_dev_write,
> +};
> +
> +static int vgic_register_kvm_io_dev(struct kvm *kvm)
> +{
> + struct kvm_io_device *dev;
> + int ret;
> +
> + struct vgic_dist *dist = &kvm->arch.vgic;
> + unsigned long base = dist->vgic_dist_base;
> +
> + dev = kzalloc(sizeof(struct kvm_io_device), GFP_KERNEL);
> + if (!dev)
> + return -ENOMEM;
> +
> + kvm_iodevice_init(dev, &vgic_io_dev_ops);
> +
> + mutex_lock(&kvm->slots_lock);
> +
> + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
> + base, KVM_VGIC_V2_DIST_SIZE, dev);
Should we consider GICv3? I think if applying this patch, it can not run well while creating a vGICv3 for guest.
Thanks,
Shannon
> + if (ret < 0)
> + goto out_free_dev;
> + mutex_unlock(&kvm->slots_lock);
> +
> + kvm->arch.vgic.io_dev = dev;
> +
> + return 0;
> +
> +out_free_dev:
> + mutex_unlock(&kvm->slots_lock);
> + kfree(dev);
> + return ret;
> }
>
> static int vgic_nr_shared_irqs(struct vgic_dist *dist)
> @@ -1545,6 +1601,8 @@ int kvm_vgic_init(struct kvm *kvm)
>
> mutex_lock(&kvm->lock);
>
> + vgic_register_kvm_io_dev(kvm);
> +
> if (vgic_initialized(kvm))
> goto out;
>
>
> _______________________________________________
> kvmarm mailing list
> kvmarm at lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
>
> .
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 4/5] ARM: enable linking against eventfd and irqchip
2014-11-24 21:27 ` [RFC PATCH 4/5] ARM: enable linking against eventfd and irqchip Nikolay Nikolaev
2014-11-26 16:58 ` Eric Auger
@ 2014-11-29 7:18 ` Shannon Zhao
2014-11-29 13:49 ` Nikolay Nikolaev
2014-11-29 11:29 ` Christoffer Dall
2 siblings, 1 reply; 29+ messages in thread
From: Shannon Zhao @ 2014-11-29 7:18 UTC (permalink / raw)
To: linux-arm-kernel
On 2014/11/25 5:27, Nikolay Nikolaev wrote:
> This enables compilation of the eventfd feature on ARM.
>
Only enable on ARM? I think we should enable it on ARM64 as well because the eventfd featrue is common for ARM32 and ARM64.
Thanks,
Shannon
> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> ---
> arch/arm/kvm/Kconfig | 1 +
> arch/arm/kvm/Makefile | 2 +-
> 2 files changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
> index 466bd29..a4b0312 100644
> --- a/arch/arm/kvm/Kconfig
> +++ b/arch/arm/kvm/Kconfig
> @@ -20,6 +20,7 @@ config KVM
> bool "Kernel-based Virtual Machine (KVM) support"
> select PREEMPT_NOTIFIERS
> select ANON_INODES
> + select HAVE_KVM_EVENTFD
> select HAVE_KVM_CPU_RELAX_INTERCEPT
> select KVM_MMIO
> select KVM_ARM_HOST
> diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
> index 443b8be..539c1a5 100644
> --- a/arch/arm/kvm/Makefile
> +++ b/arch/arm/kvm/Makefile
> @@ -15,7 +15,7 @@ AFLAGS_init.o := -Wa,-march=armv7-a$(plus_virt)
> AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt)
>
> KVM := ../../../virt/kvm
> -kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o
> +kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o
>
> obj-y += kvm-arm.o init.o interrupts.o
> obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
>
> _______________________________________________
> kvmarm mailing list
> kvmarm at lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
>
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 2/5] ARM: on IO mem abort - route the call to KVM MMIO bus
2014-11-24 21:26 ` [RFC PATCH 2/5] ARM: on IO mem abort - route the call to KVM MMIO bus Nikolay Nikolaev
2014-11-27 10:19 ` Eric Auger
@ 2014-11-29 11:28 ` Christoffer Dall
2014-12-05 12:06 ` Nikolay Nikolaev
2014-11-29 11:29 ` Christoffer Dall
2 siblings, 1 reply; 29+ messages in thread
From: Christoffer Dall @ 2014-11-29 11:28 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Nov 24, 2014 at 11:26:51PM +0200, Nikolay Nikolaev wrote:
> On IO memory abort, try to handle the MMIO access thorugh the KVM
> registered read/write callbacks. This is done by invoking the relevant
> kvm_io_bus_* API.
>
> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> ---
> arch/arm/kvm/mmio.c | 33 +++++++++++++++++++++++++++++++++
> 1 file changed, 33 insertions(+)
>
> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
> index 4cb5a93..81230da 100644
> --- a/arch/arm/kvm/mmio.c
> +++ b/arch/arm/kvm/mmio.c
> @@ -162,6 +162,36 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
> return 0;
> }
>
> +/**
> + * kvm_handle_mmio - handle an in-kernel MMIO access
> + * @vcpu: pointer to the vcpu performing the access
> + * @run: pointer to the kvm_run structure
> + * @mmio: pointer to the data describing the access
> + *
> + * returns true if the MMIO access has been performed in kernel space,
> + * and false if it needs to be emulated in user space.
> + */
> +static bool handle_kernel_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> + struct kvm_exit_mmio *mmio)
> +{
> + int ret;
> +
> + if (mmio->is_write) {
> + ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, mmio->phys_addr,
> + mmio->len, &mmio->data);
> +
> + } else {
> + ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, mmio->phys_addr,
> + mmio->len, &mmio->data);
> + }
> + if (!ret) {
> + kvm_prepare_mmio(run, mmio);
> + kvm_handle_mmio_return(vcpu, run);
> + }
> +
> + return !ret;
> +}
> +
> int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> phys_addr_t fault_ipa)
> {
> @@ -200,6 +230,9 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> if (vgic_handle_mmio(vcpu, run, &mmio))
> return 1;
>
> + if (handle_kernel_mmio(vcpu, run, &mmio))
> + return 1;
> +
Is this stuff always synchronously handled so that the mmio is properly
populated upon handle_kernel_mmio on reads?
-Christoffer
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 2/5] ARM: on IO mem abort - route the call to KVM MMIO bus
2014-11-24 21:26 ` [RFC PATCH 2/5] ARM: on IO mem abort - route the call to KVM MMIO bus Nikolay Nikolaev
2014-11-27 10:19 ` Eric Auger
2014-11-29 11:28 ` Christoffer Dall
@ 2014-11-29 11:29 ` Christoffer Dall
2 siblings, 0 replies; 29+ messages in thread
From: Christoffer Dall @ 2014-11-29 11:29 UTC (permalink / raw)
To: linux-arm-kernel
The subject could use a KVM: prefix.
On Mon, Nov 24, 2014 at 11:26:51PM +0200, Nikolay Nikolaev wrote:
> On IO memory abort, try to handle the MMIO access thorugh the KVM
> registered read/write callbacks. This is done by invoking the relevant
> kvm_io_bus_* API.
>
> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> ---
> arch/arm/kvm/mmio.c | 33 +++++++++++++++++++++++++++++++++
> 1 file changed, 33 insertions(+)
>
> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
> index 4cb5a93..81230da 100644
> --- a/arch/arm/kvm/mmio.c
> +++ b/arch/arm/kvm/mmio.c
> @@ -162,6 +162,36 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
> return 0;
> }
>
> +/**
> + * kvm_handle_mmio - handle an in-kernel MMIO access
> + * @vcpu: pointer to the vcpu performing the access
> + * @run: pointer to the kvm_run structure
> + * @mmio: pointer to the data describing the access
> + *
> + * returns true if the MMIO access has been performed in kernel space,
> + * and false if it needs to be emulated in user space.
> + */
> +static bool handle_kernel_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> + struct kvm_exit_mmio *mmio)
> +{
> + int ret;
> +
> + if (mmio->is_write) {
> + ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, mmio->phys_addr,
> + mmio->len, &mmio->data);
> +
> + } else {
> + ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, mmio->phys_addr,
> + mmio->len, &mmio->data);
> + }
> + if (!ret) {
> + kvm_prepare_mmio(run, mmio);
> + kvm_handle_mmio_return(vcpu, run);
> + }
> +
> + return !ret;
> +}
> +
> int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> phys_addr_t fault_ipa)
> {
> @@ -200,6 +230,9 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> if (vgic_handle_mmio(vcpu, run, &mmio))
> return 1;
>
> + if (handle_kernel_mmio(vcpu, run, &mmio))
> + return 1;
> +
> kvm_prepare_mmio(run, &mmio);
> return 0;
> }
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend
2014-11-24 21:26 ` [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend Nikolay Nikolaev
2014-11-27 10:51 ` Eric Auger
2014-11-29 7:14 ` Shannon Zhao
@ 2014-11-29 11:29 ` Christoffer Dall
2014-11-29 11:29 ` Christoffer Dall
2014-11-29 11:29 ` Christoffer Dall
4 siblings, 0 replies; 29+ messages in thread
From: Christoffer Dall @ 2014-11-29 11:29 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Nov 24, 2014 at 11:26:58PM +0200, Nikolay Nikolaev wrote:
> In io_mem_abort remove the call to vgic_handle_mmio. The target is to have
> a single MMIO handling path - that is through the kvm_io_bus_ API.
>
> Register a kvm_io_device in kvm_vgic_init on the whole vGIC MMIO region.
> Both read and write calls are redirected to vgic_io_dev_access where
> kvm_exit_mmio is composed to pass it to vm_ops.handle_mmio.
>
>
> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> ---
> arch/arm/kvm/mmio.c | 3 --
> include/kvm/arm_vgic.h | 3 +-
> virt/kvm/arm/vgic.c | 88 ++++++++++++++++++++++++++++++++++++++++--------
> 3 files changed, 74 insertions(+), 20 deletions(-)
>
> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
> index 81230da..1c44a2b 100644
> --- a/arch/arm/kvm/mmio.c
> +++ b/arch/arm/kvm/mmio.c
> @@ -227,9 +227,6 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> if (mmio.is_write)
> mmio_write_buf(mmio.data, mmio.len, data);
>
> - if (vgic_handle_mmio(vcpu, run, &mmio))
> - return 1;
> -
> if (handle_kernel_mmio(vcpu, run, &mmio))
> return 1;
>
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index e452ef7..d9b7d2a 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -233,6 +233,7 @@ struct vgic_dist {
> unsigned long *irq_pending_on_cpu;
>
> struct vgic_vm_ops vm_ops;
> + struct kvm_io_device *io_dev;
> #endif
> };
>
> @@ -307,8 +308,6 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
> bool level);
> void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
> int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> - struct kvm_exit_mmio *mmio);
>
> #define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel))
> #define vgic_initialized(k) ((k)->arch.vgic.ready)
> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
> index 1213da5..3da1115 100644
> --- a/virt/kvm/arm/vgic.c
> +++ b/virt/kvm/arm/vgic.c
> @@ -31,6 +31,9 @@
> #include <asm/kvm_emulate.h>
> #include <asm/kvm_arm.h>
> #include <asm/kvm_mmu.h>
> +#include <asm/kvm.h>
> +
> +#include "iodev.h"
>
> /*
> * How the whole thing works (courtesy of Christoffer Dall):
> @@ -775,28 +778,81 @@ bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
> return true;
> }
>
> -/**
> - * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
> - * @vcpu: pointer to the vcpu performing the access
> - * @run: pointer to the kvm_run structure
> - * @mmio: pointer to the data describing the access
> - *
> - * returns true if the MMIO access has been performed in kernel space,
> - * and false if it needs to be emulated in user space.
> - * Calls the actual handling routine for the selected VGIC model.
> - */
> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> - struct kvm_exit_mmio *mmio)
> +static int vgic_io_dev_access(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, void *val, bool is_write)
> {
> - if (!irqchip_in_kernel(vcpu->kvm))
> - return false;
> + struct kvm_exit_mmio mmio;
> + bool ret;
> +
> + mmio = (struct kvm_exit_mmio) {
> + .phys_addr = addr,
> + .len = len,
> + .is_write = is_write,
> + };
> +
> + if (is_write)
> + memcpy(mmio.data, val, len);
>
> /*
> * This will currently call either vgic_v2_handle_mmio() or
> * vgic_v3_handle_mmio(), which in turn will call
> * vgic_handle_mmio_range() defined above.
> */
> - return vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, run, mmio);
> + ret = vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, vcpu->run, &mmio);
> +
> + if (!is_write)
> + memcpy(val, mmio.data, len);
> +
> + return ret ? 0 : 1;
> +}
> +
> +static int vgic_io_dev_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, void *val)
> +{
> + return vgic_io_dev_access(vcpu, this, addr, len, val, false);
> +}
> +
> +static int vgic_io_dev_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, const void *val)
> +{
> + return vgic_io_dev_access(vcpu, this, addr, len, (void *)val, true);
> +}
> +
> +static const struct kvm_io_device_ops vgic_io_dev_ops = {
> + .read = vgic_io_dev_read,
> + .write = vgic_io_dev_write,
> +};
> +
> +static int vgic_register_kvm_io_dev(struct kvm *kvm)
> +{
> + struct kvm_io_device *dev;
> + int ret;
> +
> + struct vgic_dist *dist = &kvm->arch.vgic;
> + unsigned long base = dist->vgic_dist_base;
> +
> + dev = kzalloc(sizeof(struct kvm_io_device), GFP_KERNEL);
when is this freed?
-Christoffer
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend
2014-11-24 21:26 ` [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend Nikolay Nikolaev
` (2 preceding siblings ...)
2014-11-29 11:29 ` Christoffer Dall
@ 2014-11-29 11:29 ` Christoffer Dall
2014-11-29 13:54 ` Nikolay Nikolaev
2014-11-29 11:29 ` Christoffer Dall
4 siblings, 1 reply; 29+ messages in thread
From: Christoffer Dall @ 2014-11-29 11:29 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Nov 24, 2014 at 11:26:58PM +0200, Nikolay Nikolaev wrote:
> In io_mem_abort remove the call to vgic_handle_mmio. The target is to have
> a single MMIO handling path - that is through the kvm_io_bus_ API.
>
> Register a kvm_io_device in kvm_vgic_init on the whole vGIC MMIO region.
> Both read and write calls are redirected to vgic_io_dev_access where
> kvm_exit_mmio is composed to pass it to vm_ops.handle_mmio.
>
>
> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> ---
> arch/arm/kvm/mmio.c | 3 --
> include/kvm/arm_vgic.h | 3 +-
> virt/kvm/arm/vgic.c | 88 ++++++++++++++++++++++++++++++++++++++++--------
> 3 files changed, 74 insertions(+), 20 deletions(-)
>
> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
> index 81230da..1c44a2b 100644
> --- a/arch/arm/kvm/mmio.c
> +++ b/arch/arm/kvm/mmio.c
> @@ -227,9 +227,6 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> if (mmio.is_write)
> mmio_write_buf(mmio.data, mmio.len, data);
>
> - if (vgic_handle_mmio(vcpu, run, &mmio))
> - return 1;
> -
> if (handle_kernel_mmio(vcpu, run, &mmio))
> return 1;
>
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index e452ef7..d9b7d2a 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -233,6 +233,7 @@ struct vgic_dist {
> unsigned long *irq_pending_on_cpu;
>
> struct vgic_vm_ops vm_ops;
> + struct kvm_io_device *io_dev;
> #endif
> };
>
> @@ -307,8 +308,6 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
> bool level);
> void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
> int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> - struct kvm_exit_mmio *mmio);
>
> #define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel))
> #define vgic_initialized(k) ((k)->arch.vgic.ready)
> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
> index 1213da5..3da1115 100644
> --- a/virt/kvm/arm/vgic.c
> +++ b/virt/kvm/arm/vgic.c
> @@ -31,6 +31,9 @@
> #include <asm/kvm_emulate.h>
> #include <asm/kvm_arm.h>
> #include <asm/kvm_mmu.h>
> +#include <asm/kvm.h>
> +
> +#include "iodev.h"
>
> /*
> * How the whole thing works (courtesy of Christoffer Dall):
> @@ -775,28 +778,81 @@ bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
> return true;
> }
>
> -/**
> - * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
> - * @vcpu: pointer to the vcpu performing the access
> - * @run: pointer to the kvm_run structure
> - * @mmio: pointer to the data describing the access
> - *
> - * returns true if the MMIO access has been performed in kernel space,
> - * and false if it needs to be emulated in user space.
> - * Calls the actual handling routine for the selected VGIC model.
> - */
> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> - struct kvm_exit_mmio *mmio)
> +static int vgic_io_dev_access(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, void *val, bool is_write)
> {
> - if (!irqchip_in_kernel(vcpu->kvm))
> - return false;
> + struct kvm_exit_mmio mmio;
> + bool ret;
> +
> + mmio = (struct kvm_exit_mmio) {
> + .phys_addr = addr,
> + .len = len,
> + .is_write = is_write,
> + };
> +
> + if (is_write)
> + memcpy(mmio.data, val, len);
>
> /*
> * This will currently call either vgic_v2_handle_mmio() or
> * vgic_v3_handle_mmio(), which in turn will call
> * vgic_handle_mmio_range() defined above.
> */
> - return vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, run, mmio);
> + ret = vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, vcpu->run, &mmio);
> +
> + if (!is_write)
> + memcpy(val, mmio.data, len);
> +
> + return ret ? 0 : 1;
> +}
> +
> +static int vgic_io_dev_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, void *val)
> +{
> + return vgic_io_dev_access(vcpu, this, addr, len, val, false);
> +}
> +
> +static int vgic_io_dev_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, const void *val)
> +{
> + return vgic_io_dev_access(vcpu, this, addr, len, (void *)val, true);
> +}
> +
> +static const struct kvm_io_device_ops vgic_io_dev_ops = {
> + .read = vgic_io_dev_read,
> + .write = vgic_io_dev_write,
> +};
> +
> +static int vgic_register_kvm_io_dev(struct kvm *kvm)
> +{
> + struct kvm_io_device *dev;
> + int ret;
> +
> + struct vgic_dist *dist = &kvm->arch.vgic;
> + unsigned long base = dist->vgic_dist_base;
> +
> + dev = kzalloc(sizeof(struct kvm_io_device), GFP_KERNEL);
> + if (!dev)
> + return -ENOMEM;
> +
Do you even need a dynamic allocation here or can you just have it
statically allocated as part of the kvm/vgic struct?
-Christoffer
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 4/5] ARM: enable linking against eventfd and irqchip
2014-11-24 21:27 ` [RFC PATCH 4/5] ARM: enable linking against eventfd and irqchip Nikolay Nikolaev
2014-11-26 16:58 ` Eric Auger
2014-11-29 7:18 ` Shannon Zhao
@ 2014-11-29 11:29 ` Christoffer Dall
2014-12-05 12:14 ` Nikolay Nikolaev
2 siblings, 1 reply; 29+ messages in thread
From: Christoffer Dall @ 2014-11-29 11:29 UTC (permalink / raw)
To: linux-arm-kernel
Inidicate KVM in the subject please.
On Mon, Nov 24, 2014 at 11:27:06PM +0200, Nikolay Nikolaev wrote:
> This enables compilation of the eventfd feature on ARM.
does this enable anything else than the ioeventfd stuff so that
everything is in place to do this safely now?
-Christoffer
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend
2014-11-24 21:26 ` [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend Nikolay Nikolaev
` (3 preceding siblings ...)
2014-11-29 11:29 ` Christoffer Dall
@ 2014-11-29 11:29 ` Christoffer Dall
4 siblings, 0 replies; 29+ messages in thread
From: Christoffer Dall @ 2014-11-29 11:29 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Nov 24, 2014 at 11:26:58PM +0200, Nikolay Nikolaev wrote:
> In io_mem_abort remove the call to vgic_handle_mmio. The target is to have
> a single MMIO handling path - that is through the kvm_io_bus_ API.
>
> Register a kvm_io_device in kvm_vgic_init on the whole vGIC MMIO region.
> Both read and write calls are redirected to vgic_io_dev_access where
> kvm_exit_mmio is composed to pass it to vm_ops.handle_mmio.
>
>
> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> ---
> arch/arm/kvm/mmio.c | 3 --
> include/kvm/arm_vgic.h | 3 +-
> virt/kvm/arm/vgic.c | 88 ++++++++++++++++++++++++++++++++++++++++--------
> 3 files changed, 74 insertions(+), 20 deletions(-)
>
> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
> index 81230da..1c44a2b 100644
> --- a/arch/arm/kvm/mmio.c
> +++ b/arch/arm/kvm/mmio.c
> @@ -227,9 +227,6 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> if (mmio.is_write)
> mmio_write_buf(mmio.data, mmio.len, data);
>
> - if (vgic_handle_mmio(vcpu, run, &mmio))
> - return 1;
> -
> if (handle_kernel_mmio(vcpu, run, &mmio))
> return 1;
>
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index e452ef7..d9b7d2a 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -233,6 +233,7 @@ struct vgic_dist {
> unsigned long *irq_pending_on_cpu;
>
> struct vgic_vm_ops vm_ops;
> + struct kvm_io_device *io_dev;
> #endif
> };
>
> @@ -307,8 +308,6 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
> bool level);
> void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
> int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> - struct kvm_exit_mmio *mmio);
>
> #define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel))
> #define vgic_initialized(k) ((k)->arch.vgic.ready)
> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
> index 1213da5..3da1115 100644
> --- a/virt/kvm/arm/vgic.c
> +++ b/virt/kvm/arm/vgic.c
> @@ -31,6 +31,9 @@
> #include <asm/kvm_emulate.h>
> #include <asm/kvm_arm.h>
> #include <asm/kvm_mmu.h>
> +#include <asm/kvm.h>
> +
> +#include "iodev.h"
>
> /*
> * How the whole thing works (courtesy of Christoffer Dall):
> @@ -775,28 +778,81 @@ bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
> return true;
> }
>
> -/**
> - * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
> - * @vcpu: pointer to the vcpu performing the access
> - * @run: pointer to the kvm_run structure
> - * @mmio: pointer to the data describing the access
> - *
> - * returns true if the MMIO access has been performed in kernel space,
> - * and false if it needs to be emulated in user space.
> - * Calls the actual handling routine for the selected VGIC model.
> - */
> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> - struct kvm_exit_mmio *mmio)
> +static int vgic_io_dev_access(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, void *val, bool is_write)
> {
> - if (!irqchip_in_kernel(vcpu->kvm))
> - return false;
> + struct kvm_exit_mmio mmio;
> + bool ret;
> +
> + mmio = (struct kvm_exit_mmio) {
> + .phys_addr = addr,
> + .len = len,
> + .is_write = is_write,
> + };
> +
> + if (is_write)
> + memcpy(mmio.data, val, len);
>
> /*
> * This will currently call either vgic_v2_handle_mmio() or
> * vgic_v3_handle_mmio(), which in turn will call
> * vgic_handle_mmio_range() defined above.
> */
> - return vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, run, mmio);
> + ret = vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, vcpu->run, &mmio);
> +
> + if (!is_write)
> + memcpy(val, mmio.data, len);
> +
> + return ret ? 0 : 1;
> +}
> +
> +static int vgic_io_dev_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, void *val)
> +{
> + return vgic_io_dev_access(vcpu, this, addr, len, val, false);
> +}
> +
> +static int vgic_io_dev_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> + gpa_t addr, int len, const void *val)
> +{
> + return vgic_io_dev_access(vcpu, this, addr, len, (void *)val, true);
> +}
> +
> +static const struct kvm_io_device_ops vgic_io_dev_ops = {
> + .read = vgic_io_dev_read,
> + .write = vgic_io_dev_write,
> +};
> +
> +static int vgic_register_kvm_io_dev(struct kvm *kvm)
> +{
> + struct kvm_io_device *dev;
> + int ret;
> +
> + struct vgic_dist *dist = &kvm->arch.vgic;
> + unsigned long base = dist->vgic_dist_base;
> +
> + dev = kzalloc(sizeof(struct kvm_io_device), GFP_KERNEL);
> + if (!dev)
> + return -ENOMEM;
> +
> + kvm_iodevice_init(dev, &vgic_io_dev_ops);
> +
> + mutex_lock(&kvm->slots_lock);
> +
> + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
> + base, KVM_VGIC_V2_DIST_SIZE, dev);
you said this was rebased on Andre's GICv3 series but this only
registers a handler for the GICv2 range?
-Christoffer
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 4/5] ARM: enable linking against eventfd and irqchip
2014-11-29 7:18 ` Shannon Zhao
@ 2014-11-29 13:49 ` Nikolay Nikolaev
2014-11-29 14:32 ` Christoffer Dall
0 siblings, 1 reply; 29+ messages in thread
From: Nikolay Nikolaev @ 2014-11-29 13:49 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, Nov 29, 2014 at 9:18 AM, Shannon Zhao <zhaoshenglong@huawei.com> wrote:
>
> On 2014/11/25 5:27, Nikolay Nikolaev wrote:
> > This enables compilation of the eventfd feature on ARM.
> >
>
> Only enable on ARM? I think we should enable it on ARM64 as well because the eventfd featrue is common for ARM32 and ARM64.
If course - thanks for pointing this out.
regards,
Nikolay Nikolaev
>
> Thanks,
> Shannon
>
> > Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> > ---
> > arch/arm/kvm/Kconfig | 1 +
> > arch/arm/kvm/Makefile | 2 +-
> > 2 files changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
> > index 466bd29..a4b0312 100644
> > --- a/arch/arm/kvm/Kconfig
> > +++ b/arch/arm/kvm/Kconfig
> > @@ -20,6 +20,7 @@ config KVM
> > bool "Kernel-based Virtual Machine (KVM) support"
> > select PREEMPT_NOTIFIERS
> > select ANON_INODES
> > + select HAVE_KVM_EVENTFD
> > select HAVE_KVM_CPU_RELAX_INTERCEPT
> > select KVM_MMIO
> > select KVM_ARM_HOST
> > diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
> > index 443b8be..539c1a5 100644
> > --- a/arch/arm/kvm/Makefile
> > +++ b/arch/arm/kvm/Makefile
> > @@ -15,7 +15,7 @@ AFLAGS_init.o := -Wa,-march=armv7-a$(plus_virt)
> > AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt)
> >
> > KVM := ../../../virt/kvm
> > -kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o
> > +kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o
> >
> > obj-y += kvm-arm.o init.o interrupts.o
> > obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
> >
> > _______________________________________________
> > kvmarm mailing list
> > kvmarm at lists.cs.columbia.edu
> > https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
> >
> >
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend
2014-11-29 11:29 ` Christoffer Dall
@ 2014-11-29 13:54 ` Nikolay Nikolaev
2014-12-05 12:10 ` Nikolay Nikolaev
0 siblings, 1 reply; 29+ messages in thread
From: Nikolay Nikolaev @ 2014-11-29 13:54 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, Nov 29, 2014 at 1:29 PM, Christoffer Dall
<christoffer.dall@linaro.org> wrote:
> On Mon, Nov 24, 2014 at 11:26:58PM +0200, Nikolay Nikolaev wrote:
>> In io_mem_abort remove the call to vgic_handle_mmio. The target is to have
>> a single MMIO handling path - that is through the kvm_io_bus_ API.
>>
>> Register a kvm_io_device in kvm_vgic_init on the whole vGIC MMIO region.
>> Both read and write calls are redirected to vgic_io_dev_access where
>> kvm_exit_mmio is composed to pass it to vm_ops.handle_mmio.
>>
>>
>> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
>> ---
>> arch/arm/kvm/mmio.c | 3 --
>> include/kvm/arm_vgic.h | 3 +-
>> virt/kvm/arm/vgic.c | 88 ++++++++++++++++++++++++++++++++++++++++--------
>> 3 files changed, 74 insertions(+), 20 deletions(-)
>>
>> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
>> index 81230da..1c44a2b 100644
>> --- a/arch/arm/kvm/mmio.c
>> +++ b/arch/arm/kvm/mmio.c
>> @@ -227,9 +227,6 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
>> if (mmio.is_write)
>> mmio_write_buf(mmio.data, mmio.len, data);
>>
>> - if (vgic_handle_mmio(vcpu, run, &mmio))
>> - return 1;
>> -
>> if (handle_kernel_mmio(vcpu, run, &mmio))
>> return 1;
>>
>> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
>> index e452ef7..d9b7d2a 100644
>> --- a/include/kvm/arm_vgic.h
>> +++ b/include/kvm/arm_vgic.h
>> @@ -233,6 +233,7 @@ struct vgic_dist {
>> unsigned long *irq_pending_on_cpu;
>>
>> struct vgic_vm_ops vm_ops;
>> + struct kvm_io_device *io_dev;
>> #endif
>> };
>>
>> @@ -307,8 +308,6 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
>> bool level);
>> void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
>> int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
>> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
>> - struct kvm_exit_mmio *mmio);
>>
>> #define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel))
>> #define vgic_initialized(k) ((k)->arch.vgic.ready)
>> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
>> index 1213da5..3da1115 100644
>> --- a/virt/kvm/arm/vgic.c
>> +++ b/virt/kvm/arm/vgic.c
>> @@ -31,6 +31,9 @@
>> #include <asm/kvm_emulate.h>
>> #include <asm/kvm_arm.h>
>> #include <asm/kvm_mmu.h>
>> +#include <asm/kvm.h>
>> +
>> +#include "iodev.h"
>>
>> /*
>> * How the whole thing works (courtesy of Christoffer Dall):
>> @@ -775,28 +778,81 @@ bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
>> return true;
>> }
>>
>> -/**
>> - * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
>> - * @vcpu: pointer to the vcpu performing the access
>> - * @run: pointer to the kvm_run structure
>> - * @mmio: pointer to the data describing the access
>> - *
>> - * returns true if the MMIO access has been performed in kernel space,
>> - * and false if it needs to be emulated in user space.
>> - * Calls the actual handling routine for the selected VGIC model.
>> - */
>> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
>> - struct kvm_exit_mmio *mmio)
>> +static int vgic_io_dev_access(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
>> + gpa_t addr, int len, void *val, bool is_write)
>> {
>> - if (!irqchip_in_kernel(vcpu->kvm))
>> - return false;
>> + struct kvm_exit_mmio mmio;
>> + bool ret;
>> +
>> + mmio = (struct kvm_exit_mmio) {
>> + .phys_addr = addr,
>> + .len = len,
>> + .is_write = is_write,
>> + };
>> +
>> + if (is_write)
>> + memcpy(mmio.data, val, len);
>>
>> /*
>> * This will currently call either vgic_v2_handle_mmio() or
>> * vgic_v3_handle_mmio(), which in turn will call
>> * vgic_handle_mmio_range() defined above.
>> */
>> - return vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, run, mmio);
>> + ret = vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, vcpu->run, &mmio);
>> +
>> + if (!is_write)
>> + memcpy(val, mmio.data, len);
>> +
>> + return ret ? 0 : 1;
>> +}
>> +
>> +static int vgic_io_dev_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
>> + gpa_t addr, int len, void *val)
>> +{
>> + return vgic_io_dev_access(vcpu, this, addr, len, val, false);
>> +}
>> +
>> +static int vgic_io_dev_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
>> + gpa_t addr, int len, const void *val)
>> +{
>> + return vgic_io_dev_access(vcpu, this, addr, len, (void *)val, true);
>> +}
>> +
>> +static const struct kvm_io_device_ops vgic_io_dev_ops = {
>> + .read = vgic_io_dev_read,
>> + .write = vgic_io_dev_write,
>> +};
>> +
>> +static int vgic_register_kvm_io_dev(struct kvm *kvm)
>> +{
>> + struct kvm_io_device *dev;
>> + int ret;
>> +
>> + struct vgic_dist *dist = &kvm->arch.vgic;
>> + unsigned long base = dist->vgic_dist_base;
>> +
>> + dev = kzalloc(sizeof(struct kvm_io_device), GFP_KERNEL);
>> + if (!dev)
>> + return -ENOMEM;
>> +
> Do you even need a dynamic allocation here or can you just have it
> statically allocated as part of the kvm/vgic struct?
Right - static allocation should be just fine - will do
Thanks
Nikolay Nikolaev
>
> -Christoffer
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend
2014-11-29 7:14 ` Shannon Zhao
@ 2014-11-29 13:58 ` Nikolay Nikolaev
0 siblings, 0 replies; 29+ messages in thread
From: Nikolay Nikolaev @ 2014-11-29 13:58 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, Nov 29, 2014 at 9:14 AM, Shannon Zhao <zhaoshenglong@huawei.com> wrote:
> On 2014/11/25 5:26, Nikolay Nikolaev wrote:
>> In io_mem_abort remove the call to vgic_handle_mmio. The target is to have
>> a single MMIO handling path - that is through the kvm_io_bus_ API.
>>
>> Register a kvm_io_device in kvm_vgic_init on the whole vGIC MMIO region.
>> Both read and write calls are redirected to vgic_io_dev_access where
>> kvm_exit_mmio is composed to pass it to vm_ops.handle_mmio.
>>
>>
>> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
>> ---
>> arch/arm/kvm/mmio.c | 3 --
>> include/kvm/arm_vgic.h | 3 +-
>> virt/kvm/arm/vgic.c | 88 ++++++++++++++++++++++++++++++++++++++++--------
>> 3 files changed, 74 insertions(+), 20 deletions(-)
>>
>> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
>> index 81230da..1c44a2b 100644
>> --- a/arch/arm/kvm/mmio.c
>> +++ b/arch/arm/kvm/mmio.c
>> @@ -227,9 +227,6 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
>> if (mmio.is_write)
>> mmio_write_buf(mmio.data, mmio.len, data);
>>
>> - if (vgic_handle_mmio(vcpu, run, &mmio))
>> - return 1;
>> -
>> if (handle_kernel_mmio(vcpu, run, &mmio))
>> return 1;
>>
>> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
>> index e452ef7..d9b7d2a 100644
>> --- a/include/kvm/arm_vgic.h
>> +++ b/include/kvm/arm_vgic.h
>> @@ -233,6 +233,7 @@ struct vgic_dist {
>> unsigned long *irq_pending_on_cpu;
>>
>> struct vgic_vm_ops vm_ops;
>> + struct kvm_io_device *io_dev;
>> #endif
>> };
>>
>> @@ -307,8 +308,6 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
>> bool level);
>> void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
>> int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
>> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
>> - struct kvm_exit_mmio *mmio);
>>
>> #define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel))
>> #define vgic_initialized(k) ((k)->arch.vgic.ready)
>> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
>> index 1213da5..3da1115 100644
>> --- a/virt/kvm/arm/vgic.c
>> +++ b/virt/kvm/arm/vgic.c
>> @@ -31,6 +31,9 @@
>> #include <asm/kvm_emulate.h>
>> #include <asm/kvm_arm.h>
>> #include <asm/kvm_mmu.h>
>> +#include <asm/kvm.h>
>> +
>> +#include "iodev.h"
>>
>> /*
>> * How the whole thing works (courtesy of Christoffer Dall):
>> @@ -775,28 +778,81 @@ bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
>> return true;
>> }
>>
>> -/**
>> - * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
>> - * @vcpu: pointer to the vcpu performing the access
>> - * @run: pointer to the kvm_run structure
>> - * @mmio: pointer to the data describing the access
>> - *
>> - * returns true if the MMIO access has been performed in kernel space,
>> - * and false if it needs to be emulated in user space.
>> - * Calls the actual handling routine for the selected VGIC model.
>> - */
>> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
>> - struct kvm_exit_mmio *mmio)
>> +static int vgic_io_dev_access(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
>> + gpa_t addr, int len, void *val, bool is_write)
>> {
>> - if (!irqchip_in_kernel(vcpu->kvm))
>> - return false;
>> + struct kvm_exit_mmio mmio;
>> + bool ret;
>> +
>> + mmio = (struct kvm_exit_mmio) {
>> + .phys_addr = addr,
>> + .len = len,
>> + .is_write = is_write,
>> + };
>> +
>> + if (is_write)
>> + memcpy(mmio.data, val, len);
>>
>> /*
>> * This will currently call either vgic_v2_handle_mmio() or
>> * vgic_v3_handle_mmio(), which in turn will call
>> * vgic_handle_mmio_range() defined above.
>> */
>> - return vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, run, mmio);
>> + ret = vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, vcpu->run, &mmio);
>> +
>> + if (!is_write)
>> + memcpy(val, mmio.data, len);
>> +
>> + return ret ? 0 : 1;
>> +}
>> +
>> +static int vgic_io_dev_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
>> + gpa_t addr, int len, void *val)
>> +{
>> + return vgic_io_dev_access(vcpu, this, addr, len, val, false);
>> +}
>> +
>> +static int vgic_io_dev_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
>> + gpa_t addr, int len, const void *val)
>> +{
>> + return vgic_io_dev_access(vcpu, this, addr, len, (void *)val, true);
>> +}
>> +
>> +static const struct kvm_io_device_ops vgic_io_dev_ops = {
>> + .read = vgic_io_dev_read,
>> + .write = vgic_io_dev_write,
>> +};
>> +
>> +static int vgic_register_kvm_io_dev(struct kvm *kvm)
>> +{
>> + struct kvm_io_device *dev;
>> + int ret;
>> +
>> + struct vgic_dist *dist = &kvm->arch.vgic;
>> + unsigned long base = dist->vgic_dist_base;
>> +
>> + dev = kzalloc(sizeof(struct kvm_io_device), GFP_KERNEL);
>> + if (!dev)
>> + return -ENOMEM;
>> +
>> + kvm_iodevice_init(dev, &vgic_io_dev_ops);
>> +
>> + mutex_lock(&kvm->slots_lock);
>> +
>> + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
>> + base, KVM_VGIC_V2_DIST_SIZE, dev);
>
> Should we consider GICv3? I think if applying this patch, it can not run well while creating a vGICv3 for guest.
Agree. Christofer also pointed this out. Will select the dist size
depending on the vgic_model.
Thanks.
Nikolay Nikolay
>
> Thanks,
> Shannon
>> + if (ret < 0)
>> + goto out_free_dev;
>> + mutex_unlock(&kvm->slots_lock);
>> +
>> + kvm->arch.vgic.io_dev = dev;
>> +
>> + return 0;
>> +
>> +out_free_dev:
>> + mutex_unlock(&kvm->slots_lock);
>> + kfree(dev);
>> + return ret;
>> }
>>
>> static int vgic_nr_shared_irqs(struct vgic_dist *dist)
>> @@ -1545,6 +1601,8 @@ int kvm_vgic_init(struct kvm *kvm)
>>
>> mutex_lock(&kvm->lock);
>>
>> + vgic_register_kvm_io_dev(kvm);
>> +
>> if (vgic_initialized(kvm))
>> goto out;
>>
>>
>> _______________________________________________
>> kvmarm mailing list
>> kvmarm at lists.cs.columbia.edu
>> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
>>
>> .
>>
>
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 4/5] ARM: enable linking against eventfd and irqchip
2014-11-29 13:49 ` Nikolay Nikolaev
@ 2014-11-29 14:32 ` Christoffer Dall
0 siblings, 0 replies; 29+ messages in thread
From: Christoffer Dall @ 2014-11-29 14:32 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, Nov 29, 2014 at 03:49:37PM +0200, Nikolay Nikolaev wrote:
> On Sat, Nov 29, 2014 at 9:18 AM, Shannon Zhao <zhaoshenglong@huawei.com> wrote:
> >
> > On 2014/11/25 5:27, Nikolay Nikolaev wrote:
> > > This enables compilation of the eventfd feature on ARM.
> > >
> >
> > Only enable on ARM? I think we should enable it on ARM64 as well because the eventfd featrue is common for ARM32 and ARM64.
>
> If course - thanks for pointing this out.
>
Please remember testing if this breaks anything on arm64 :)
-Christoffer
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 2/5] ARM: on IO mem abort - route the call to KVM MMIO bus
2014-11-29 11:28 ` Christoffer Dall
@ 2014-12-05 12:06 ` Nikolay Nikolaev
2015-01-12 16:21 ` Eric Auger
0 siblings, 1 reply; 29+ messages in thread
From: Nikolay Nikolaev @ 2014-12-05 12:06 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, Nov 29, 2014 at 1:28 PM, Christoffer Dall
<christoffer.dall@linaro.org> wrote:
> On Mon, Nov 24, 2014 at 11:26:51PM +0200, Nikolay Nikolaev wrote:
>> On IO memory abort, try to handle the MMIO access thorugh the KVM
>> registered read/write callbacks. This is done by invoking the relevant
>> kvm_io_bus_* API.
>>
>> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
>> ---
>> arch/arm/kvm/mmio.c | 33 +++++++++++++++++++++++++++++++++
>> 1 file changed, 33 insertions(+)
>>
>> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
>> index 4cb5a93..81230da 100644
>> --- a/arch/arm/kvm/mmio.c
>> +++ b/arch/arm/kvm/mmio.c
>> @@ -162,6 +162,36 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>> return 0;
>> }
>>
>> +/**
>> + * kvm_handle_mmio - handle an in-kernel MMIO access
>> + * @vcpu: pointer to the vcpu performing the access
>> + * @run: pointer to the kvm_run structure
>> + * @mmio: pointer to the data describing the access
>> + *
>> + * returns true if the MMIO access has been performed in kernel space,
>> + * and false if it needs to be emulated in user space.
>> + */
>> +static bool handle_kernel_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
>> + struct kvm_exit_mmio *mmio)
>> +{
>> + int ret;
>> +
>> + if (mmio->is_write) {
>> + ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, mmio->phys_addr,
>> + mmio->len, &mmio->data);
>> +
>> + } else {
>> + ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, mmio->phys_addr,
>> + mmio->len, &mmio->data);
>> + }
>> + if (!ret) {
>> + kvm_prepare_mmio(run, mmio);
>> + kvm_handle_mmio_return(vcpu, run);
>> + }
>> +
>> + return !ret;
>> +}
>> +
>> int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
>> phys_addr_t fault_ipa)
>> {
>> @@ -200,6 +230,9 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
>> if (vgic_handle_mmio(vcpu, run, &mmio))
>> return 1;
>>
>> + if (handle_kernel_mmio(vcpu, run, &mmio))
>> + return 1;
>> +
>
> Is this stuff always synchronously handled so that the mmio is properly
> populated upon handle_kernel_mmio on reads?
If I get it right the kvm_io_bus_ API is intended to work
synchronously. Of course it probably depends
on how the registered device handles the read/write call.
Or maybe I misunderstand your question? Please clarify in that case.
regards,
Nikolay Nikolaev
>
> -Christoffer
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend
2014-11-29 13:54 ` Nikolay Nikolaev
@ 2014-12-05 12:10 ` Nikolay Nikolaev
2014-12-08 10:51 ` Christoffer Dall
0 siblings, 1 reply; 29+ messages in thread
From: Nikolay Nikolaev @ 2014-12-05 12:10 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, Nov 29, 2014 at 3:54 PM, Nikolay Nikolaev
<n.nikolaev@virtualopensystems.com> wrote:
> On Sat, Nov 29, 2014 at 1:29 PM, Christoffer Dall
> <christoffer.dall@linaro.org> wrote:
>> On Mon, Nov 24, 2014 at 11:26:58PM +0200, Nikolay Nikolaev wrote:
>>> In io_mem_abort remove the call to vgic_handle_mmio. The target is to have
>>> a single MMIO handling path - that is through the kvm_io_bus_ API.
>>>
>>> Register a kvm_io_device in kvm_vgic_init on the whole vGIC MMIO region.
>>> Both read and write calls are redirected to vgic_io_dev_access where
>>> kvm_exit_mmio is composed to pass it to vm_ops.handle_mmio.
>>>
>>>
>>> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
>>> ---
>>> arch/arm/kvm/mmio.c | 3 --
>>> include/kvm/arm_vgic.h | 3 +-
>>> virt/kvm/arm/vgic.c | 88 ++++++++++++++++++++++++++++++++++++++++--------
>>> 3 files changed, 74 insertions(+), 20 deletions(-)
>>>
>>> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
>>> index 81230da..1c44a2b 100644
>>> --- a/arch/arm/kvm/mmio.c
>>> +++ b/arch/arm/kvm/mmio.c
>>> @@ -227,9 +227,6 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
>>> if (mmio.is_write)
>>> mmio_write_buf(mmio.data, mmio.len, data);
>>>
>>> - if (vgic_handle_mmio(vcpu, run, &mmio))
>>> - return 1;
>>> -
>>> if (handle_kernel_mmio(vcpu, run, &mmio))
>>> return 1;
>>>
>>> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
>>> index e452ef7..d9b7d2a 100644
>>> --- a/include/kvm/arm_vgic.h
>>> +++ b/include/kvm/arm_vgic.h
>>> @@ -233,6 +233,7 @@ struct vgic_dist {
>>> unsigned long *irq_pending_on_cpu;
>>>
>>> struct vgic_vm_ops vm_ops;
>>> + struct kvm_io_device *io_dev;
>>> #endif
>>> };
>>>
>>> @@ -307,8 +308,6 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
>>> bool level);
>>> void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
>>> int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
>>> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
>>> - struct kvm_exit_mmio *mmio);
>>>
>>> #define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel))
>>> #define vgic_initialized(k) ((k)->arch.vgic.ready)
>>> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
>>> index 1213da5..3da1115 100644
>>> --- a/virt/kvm/arm/vgic.c
>>> +++ b/virt/kvm/arm/vgic.c
>>> @@ -31,6 +31,9 @@
>>> #include <asm/kvm_emulate.h>
>>> #include <asm/kvm_arm.h>
>>> #include <asm/kvm_mmu.h>
>>> +#include <asm/kvm.h>
>>> +
>>> +#include "iodev.h"
>>>
>>> /*
>>> * How the whole thing works (courtesy of Christoffer Dall):
>>> @@ -775,28 +778,81 @@ bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
>>> return true;
>>> }
>>>
>>> -/**
>>> - * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
>>> - * @vcpu: pointer to the vcpu performing the access
>>> - * @run: pointer to the kvm_run structure
>>> - * @mmio: pointer to the data describing the access
>>> - *
>>> - * returns true if the MMIO access has been performed in kernel space,
>>> - * and false if it needs to be emulated in user space.
>>> - * Calls the actual handling routine for the selected VGIC model.
>>> - */
>>> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
>>> - struct kvm_exit_mmio *mmio)
>>> +static int vgic_io_dev_access(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
>>> + gpa_t addr, int len, void *val, bool is_write)
>>> {
>>> - if (!irqchip_in_kernel(vcpu->kvm))
>>> - return false;
>>> + struct kvm_exit_mmio mmio;
>>> + bool ret;
>>> +
>>> + mmio = (struct kvm_exit_mmio) {
>>> + .phys_addr = addr,
>>> + .len = len,
>>> + .is_write = is_write,
>>> + };
>>> +
>>> + if (is_write)
>>> + memcpy(mmio.data, val, len);
>>>
>>> /*
>>> * This will currently call either vgic_v2_handle_mmio() or
>>> * vgic_v3_handle_mmio(), which in turn will call
>>> * vgic_handle_mmio_range() defined above.
>>> */
>>> - return vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, run, mmio);
>>> + ret = vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, vcpu->run, &mmio);
>>> +
>>> + if (!is_write)
>>> + memcpy(val, mmio.data, len);
>>> +
>>> + return ret ? 0 : 1;
>>> +}
>>> +
>>> +static int vgic_io_dev_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
>>> + gpa_t addr, int len, void *val)
>>> +{
>>> + return vgic_io_dev_access(vcpu, this, addr, len, val, false);
>>> +}
>>> +
>>> +static int vgic_io_dev_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
>>> + gpa_t addr, int len, const void *val)
>>> +{
>>> + return vgic_io_dev_access(vcpu, this, addr, len, (void *)val, true);
>>> +}
>>> +
>>> +static const struct kvm_io_device_ops vgic_io_dev_ops = {
>>> + .read = vgic_io_dev_read,
>>> + .write = vgic_io_dev_write,
>>> +};
>>> +
>>> +static int vgic_register_kvm_io_dev(struct kvm *kvm)
>>> +{
>>> + struct kvm_io_device *dev;
>>> + int ret;
>>> +
>>> + struct vgic_dist *dist = &kvm->arch.vgic;
>>> + unsigned long base = dist->vgic_dist_base;
>>> +
>>> + dev = kzalloc(sizeof(struct kvm_io_device), GFP_KERNEL);
>>> + if (!dev)
>>> + return -ENOMEM;
>>> +
>> Do you even need a dynamic allocation here or can you just have it
>> statically allocated as part of the kvm/vgic struct?
> Right - static allocation should be just fine - will do
Actually static allocation requires inclusion of virt/kvm/iodev.h in
include/kvm/arm_vgic.h
This creates more compilation problems than it's worth. So I am adding
a proper device/unregister kfree upon vgic destroy.
regardsm
Nikolay Nikolaev
> Thanks
> Nikolay Nikolaev
>
>>
>> -Christoffer
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 4/5] ARM: enable linking against eventfd and irqchip
2014-11-29 11:29 ` Christoffer Dall
@ 2014-12-05 12:14 ` Nikolay Nikolaev
0 siblings, 0 replies; 29+ messages in thread
From: Nikolay Nikolaev @ 2014-12-05 12:14 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, Nov 29, 2014 at 1:29 PM, Christoffer Dall
<christoffer.dall@linaro.org> wrote:
> Inidicate KVM in the subject please.
>
> On Mon, Nov 24, 2014 at 11:27:06PM +0200, Nikolay Nikolaev wrote:
>> This enables compilation of the eventfd feature on ARM.
>
> does this enable anything else than the ioeventfd stuff so that
> everything is in place to do this safely now?
Inspecting the eventfd.c I see that there is the IRQFD code
conditionally compiled when CONFIG_HAVE_KVM_IRQFD is defined.
I think this is enabled for arm/arm64 in Eric's IRQFD patcheries, so
we should be safe now.
regards,
Nikolay Nikolaev
>
> -Christoffer
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend
2014-12-05 12:10 ` Nikolay Nikolaev
@ 2014-12-08 10:51 ` Christoffer Dall
0 siblings, 0 replies; 29+ messages in thread
From: Christoffer Dall @ 2014-12-08 10:51 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Dec 05, 2014 at 02:10:26PM +0200, Nikolay Nikolaev wrote:
> On Sat, Nov 29, 2014 at 3:54 PM, Nikolay Nikolaev
> <n.nikolaev@virtualopensystems.com> wrote:
> > On Sat, Nov 29, 2014 at 1:29 PM, Christoffer Dall
> > <christoffer.dall@linaro.org> wrote:
> >> On Mon, Nov 24, 2014 at 11:26:58PM +0200, Nikolay Nikolaev wrote:
> >>> In io_mem_abort remove the call to vgic_handle_mmio. The target is to have
> >>> a single MMIO handling path - that is through the kvm_io_bus_ API.
> >>>
> >>> Register a kvm_io_device in kvm_vgic_init on the whole vGIC MMIO region.
> >>> Both read and write calls are redirected to vgic_io_dev_access where
> >>> kvm_exit_mmio is composed to pass it to vm_ops.handle_mmio.
> >>>
> >>>
> >>> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> >>> ---
> >>> arch/arm/kvm/mmio.c | 3 --
> >>> include/kvm/arm_vgic.h | 3 +-
> >>> virt/kvm/arm/vgic.c | 88 ++++++++++++++++++++++++++++++++++++++++--------
> >>> 3 files changed, 74 insertions(+), 20 deletions(-)
> >>>
> >>> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
> >>> index 81230da..1c44a2b 100644
> >>> --- a/arch/arm/kvm/mmio.c
> >>> +++ b/arch/arm/kvm/mmio.c
> >>> @@ -227,9 +227,6 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> >>> if (mmio.is_write)
> >>> mmio_write_buf(mmio.data, mmio.len, data);
> >>>
> >>> - if (vgic_handle_mmio(vcpu, run, &mmio))
> >>> - return 1;
> >>> -
> >>> if (handle_kernel_mmio(vcpu, run, &mmio))
> >>> return 1;
> >>>
> >>> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> >>> index e452ef7..d9b7d2a 100644
> >>> --- a/include/kvm/arm_vgic.h
> >>> +++ b/include/kvm/arm_vgic.h
> >>> @@ -233,6 +233,7 @@ struct vgic_dist {
> >>> unsigned long *irq_pending_on_cpu;
> >>>
> >>> struct vgic_vm_ops vm_ops;
> >>> + struct kvm_io_device *io_dev;
> >>> #endif
> >>> };
> >>>
> >>> @@ -307,8 +308,6 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
> >>> bool level);
> >>> void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
> >>> int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
> >>> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> >>> - struct kvm_exit_mmio *mmio);
> >>>
> >>> #define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel))
> >>> #define vgic_initialized(k) ((k)->arch.vgic.ready)
> >>> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
> >>> index 1213da5..3da1115 100644
> >>> --- a/virt/kvm/arm/vgic.c
> >>> +++ b/virt/kvm/arm/vgic.c
> >>> @@ -31,6 +31,9 @@
> >>> #include <asm/kvm_emulate.h>
> >>> #include <asm/kvm_arm.h>
> >>> #include <asm/kvm_mmu.h>
> >>> +#include <asm/kvm.h>
> >>> +
> >>> +#include "iodev.h"
> >>>
> >>> /*
> >>> * How the whole thing works (courtesy of Christoffer Dall):
> >>> @@ -775,28 +778,81 @@ bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
> >>> return true;
> >>> }
> >>>
> >>> -/**
> >>> - * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
> >>> - * @vcpu: pointer to the vcpu performing the access
> >>> - * @run: pointer to the kvm_run structure
> >>> - * @mmio: pointer to the data describing the access
> >>> - *
> >>> - * returns true if the MMIO access has been performed in kernel space,
> >>> - * and false if it needs to be emulated in user space.
> >>> - * Calls the actual handling routine for the selected VGIC model.
> >>> - */
> >>> -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> >>> - struct kvm_exit_mmio *mmio)
> >>> +static int vgic_io_dev_access(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> >>> + gpa_t addr, int len, void *val, bool is_write)
> >>> {
> >>> - if (!irqchip_in_kernel(vcpu->kvm))
> >>> - return false;
> >>> + struct kvm_exit_mmio mmio;
> >>> + bool ret;
> >>> +
> >>> + mmio = (struct kvm_exit_mmio) {
> >>> + .phys_addr = addr,
> >>> + .len = len,
> >>> + .is_write = is_write,
> >>> + };
> >>> +
> >>> + if (is_write)
> >>> + memcpy(mmio.data, val, len);
> >>>
> >>> /*
> >>> * This will currently call either vgic_v2_handle_mmio() or
> >>> * vgic_v3_handle_mmio(), which in turn will call
> >>> * vgic_handle_mmio_range() defined above.
> >>> */
> >>> - return vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, run, mmio);
> >>> + ret = vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, vcpu->run, &mmio);
> >>> +
> >>> + if (!is_write)
> >>> + memcpy(val, mmio.data, len);
> >>> +
> >>> + return ret ? 0 : 1;
> >>> +}
> >>> +
> >>> +static int vgic_io_dev_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> >>> + gpa_t addr, int len, void *val)
> >>> +{
> >>> + return vgic_io_dev_access(vcpu, this, addr, len, val, false);
> >>> +}
> >>> +
> >>> +static int vgic_io_dev_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> >>> + gpa_t addr, int len, const void *val)
> >>> +{
> >>> + return vgic_io_dev_access(vcpu, this, addr, len, (void *)val, true);
> >>> +}
> >>> +
> >>> +static const struct kvm_io_device_ops vgic_io_dev_ops = {
> >>> + .read = vgic_io_dev_read,
> >>> + .write = vgic_io_dev_write,
> >>> +};
> >>> +
> >>> +static int vgic_register_kvm_io_dev(struct kvm *kvm)
> >>> +{
> >>> + struct kvm_io_device *dev;
> >>> + int ret;
> >>> +
> >>> + struct vgic_dist *dist = &kvm->arch.vgic;
> >>> + unsigned long base = dist->vgic_dist_base;
> >>> +
> >>> + dev = kzalloc(sizeof(struct kvm_io_device), GFP_KERNEL);
> >>> + if (!dev)
> >>> + return -ENOMEM;
> >>> +
> >> Do you even need a dynamic allocation here or can you just have it
> >> statically allocated as part of the kvm/vgic struct?
> > Right - static allocation should be just fine - will do
>
> Actually static allocation requires inclusion of virt/kvm/iodev.h in
> include/kvm/arm_vgic.h
> This creates more compilation problems than it's worth. So I am adding
> a proper device/unregister kfree upon vgic destroy.
>
What are the problems?
-Christoffer
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 2/5] ARM: on IO mem abort - route the call to KVM MMIO bus
2014-12-05 12:06 ` Nikolay Nikolaev
@ 2015-01-12 16:21 ` Eric Auger
2015-01-23 22:38 ` Nikolay Nikolaev
0 siblings, 1 reply; 29+ messages in thread
From: Eric Auger @ 2015-01-12 16:21 UTC (permalink / raw)
To: linux-arm-kernel
On 12/05/2014 01:06 PM, Nikolay Nikolaev wrote:
> On Sat, Nov 29, 2014 at 1:28 PM, Christoffer Dall
> <christoffer.dall@linaro.org> wrote:
>> On Mon, Nov 24, 2014 at 11:26:51PM +0200, Nikolay Nikolaev wrote:
>>> On IO memory abort, try to handle the MMIO access thorugh the KVM
>>> registered read/write callbacks. This is done by invoking the relevant
>>> kvm_io_bus_* API.
>>>
>>> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
>>> ---
>>> arch/arm/kvm/mmio.c | 33 +++++++++++++++++++++++++++++++++
>>> 1 file changed, 33 insertions(+)
>>>
>>> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
>>> index 4cb5a93..81230da 100644
>>> --- a/arch/arm/kvm/mmio.c
>>> +++ b/arch/arm/kvm/mmio.c
>>> @@ -162,6 +162,36 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>>> return 0;
>>> }
>>>
>>> +/**
>>> + * kvm_handle_mmio - handle an in-kernel MMIO access
>>> + * @vcpu: pointer to the vcpu performing the access
>>> + * @run: pointer to the kvm_run structure
>>> + * @mmio: pointer to the data describing the access
>>> + *
>>> + * returns true if the MMIO access has been performed in kernel space,
>>> + * and false if it needs to be emulated in user space.
>>> + */
>>> +static bool handle_kernel_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
>>> + struct kvm_exit_mmio *mmio)
>>> +{
>>> + int ret;
>>> +
>>> + if (mmio->is_write) {
>>> + ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, mmio->phys_addr,
>>> + mmio->len, &mmio->data);
>>> +
>>> + } else {
>>> + ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, mmio->phys_addr,
>>> + mmio->len, &mmio->data);
>>> + }
>>> + if (!ret) {
>>> + kvm_prepare_mmio(run, mmio);
>>> + kvm_handle_mmio_return(vcpu, run);
>>> + }
>>> +
>>> + return !ret;
>>> +}
>>> +
>>> int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
>>> phys_addr_t fault_ipa)
>>> {
>>> @@ -200,6 +230,9 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
>>> if (vgic_handle_mmio(vcpu, run, &mmio))
>>> return 1;
>>>
>>> + if (handle_kernel_mmio(vcpu, run, &mmio))
>>> + return 1;
>>> +
>>
>> Is this stuff always synchronously handled so that the mmio is properly
>> populated upon handle_kernel_mmio on reads?
>
> If I get it right the kvm_io_bus_ API is intended to work
> synchronously. Of course it probably depends
> on how the registered device handles the read/write call.
> Or maybe I misunderstand your question? Please clarify in that case.
in case of ioeventfd implementation it is not the case since the write
is deferred in the kernel thread which handles the eventfd.
Best Regards
Eric
>
> regards,
> Nikolay Nikolaev
>
>>
>> -Christoffer
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH 2/5] ARM: on IO mem abort - route the call to KVM MMIO bus
2015-01-12 16:21 ` Eric Auger
@ 2015-01-23 22:38 ` Nikolay Nikolaev
0 siblings, 0 replies; 29+ messages in thread
From: Nikolay Nikolaev @ 2015-01-23 22:38 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Jan 12, 2015 at 6:21 PM, Eric Auger <eric.auger@linaro.org> wrote:
>
> On 12/05/2014 01:06 PM, Nikolay Nikolaev wrote:
> > On Sat, Nov 29, 2014 at 1:28 PM, Christoffer Dall
> > <christoffer.dall@linaro.org> wrote:
> >> On Mon, Nov 24, 2014 at 11:26:51PM +0200, Nikolay Nikolaev wrote:
> >>> On IO memory abort, try to handle the MMIO access thorugh the KVM
> >>> registered read/write callbacks. This is done by invoking the relevant
> >>> kvm_io_bus_* API.
> >>>
> >>> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> >>> ---
> >>> arch/arm/kvm/mmio.c | 33 +++++++++++++++++++++++++++++++++
> >>> 1 file changed, 33 insertions(+)
> >>>
> >>> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
> >>> index 4cb5a93..81230da 100644
> >>> --- a/arch/arm/kvm/mmio.c
> >>> +++ b/arch/arm/kvm/mmio.c
> >>> @@ -162,6 +162,36 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
> >>> return 0;
> >>> }
> >>>
> >>> +/**
> >>> + * kvm_handle_mmio - handle an in-kernel MMIO access
> >>> + * @vcpu: pointer to the vcpu performing the access
> >>> + * @run: pointer to the kvm_run structure
> >>> + * @mmio: pointer to the data describing the access
> >>> + *
> >>> + * returns true if the MMIO access has been performed in kernel space,
> >>> + * and false if it needs to be emulated in user space.
> >>> + */
> >>> +static bool handle_kernel_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
> >>> + struct kvm_exit_mmio *mmio)
> >>> +{
> >>> + int ret;
> >>> +
> >>> + if (mmio->is_write) {
> >>> + ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, mmio->phys_addr,
> >>> + mmio->len, &mmio->data);
> >>> +
> >>> + } else {
> >>> + ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, mmio->phys_addr,
> >>> + mmio->len, &mmio->data);
> >>> + }
> >>> + if (!ret) {
> >>> + kvm_prepare_mmio(run, mmio);
> >>> + kvm_handle_mmio_return(vcpu, run);
> >>> + }
> >>> +
> >>> + return !ret;
> >>> +}
> >>> +
> >>> int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> >>> phys_addr_t fault_ipa)
> >>> {
> >>> @@ -200,6 +230,9 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> >>> if (vgic_handle_mmio(vcpu, run, &mmio))
> >>> return 1;
> >>>
> >>> + if (handle_kernel_mmio(vcpu, run, &mmio))
> >>> + return 1;
> >>> +
> >>
> >> Is this stuff always synchronously handled so that the mmio is properly
> >> populated upon handle_kernel_mmio on reads?
> >
> > If I get it right the kvm_io_bus_ API is intended to work
> > synchronously. Of course it probably depends
> > on how the registered device handles the read/write call.
> > Or maybe I misunderstand your question? Please clarify in that case.
>
> in case of ioeventfd implementation it is not the case since the write
> is deferred in the kernel thread which handles the eventfd.
Christofer was asking about reads. I guess about writes it does not
make any diiference as long as the needed values are copied into the
new thread.
regards,
Nikolay Nikolaev
>
> Best Regards
>
> Eric
> >
> > regards,
> > Nikolay Nikolaev
> >
> >>
> >> -Christoffer
>
^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2015-01-23 22:38 UTC | newest]
Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-24 21:26 [RFC PATCH 0/5] ARM: KVM: Enable the ioeventfd capability of KVM on ARM Nikolay Nikolaev
2014-11-24 21:26 ` [RFC PATCH 1/5] KVM: redesing kvm_io_bus_ API to pass VCPU structure to the callbacks Nikolay Nikolaev
2014-11-26 17:03 ` Eric Auger
2014-11-24 21:26 ` [RFC PATCH 2/5] ARM: on IO mem abort - route the call to KVM MMIO bus Nikolay Nikolaev
2014-11-27 10:19 ` Eric Auger
2014-11-29 11:28 ` Christoffer Dall
2014-12-05 12:06 ` Nikolay Nikolaev
2015-01-12 16:21 ` Eric Auger
2015-01-23 22:38 ` Nikolay Nikolaev
2014-11-29 11:29 ` Christoffer Dall
2014-11-24 21:26 ` [RFC PATCH 3/5] KVM: ARM VGIC add kvm_io_bus_ frontend Nikolay Nikolaev
2014-11-27 10:51 ` Eric Auger
2014-11-29 7:14 ` Shannon Zhao
2014-11-29 13:58 ` Nikolay Nikolaev
2014-11-29 11:29 ` Christoffer Dall
2014-11-29 11:29 ` Christoffer Dall
2014-11-29 13:54 ` Nikolay Nikolaev
2014-12-05 12:10 ` Nikolay Nikolaev
2014-12-08 10:51 ` Christoffer Dall
2014-11-29 11:29 ` Christoffer Dall
2014-11-24 21:27 ` [RFC PATCH 4/5] ARM: enable linking against eventfd and irqchip Nikolay Nikolaev
2014-11-26 16:58 ` Eric Auger
2014-11-29 7:18 ` Shannon Zhao
2014-11-29 13:49 ` Nikolay Nikolaev
2014-11-29 14:32 ` Christoffer Dall
2014-11-29 11:29 ` Christoffer Dall
2014-12-05 12:14 ` Nikolay Nikolaev
2014-11-24 21:27 ` [RFC PATCH 5/5] ARM: enable KVM_CAP_IOEVENTFD Nikolay Nikolaev
2014-11-27 11:01 ` [RFC PATCH 0/5] ARM: KVM: Enable the ioeventfd capability of KVM on ARM Eric Auger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).