From: Andre Przywara <andre.przywara@arm.com>
To: marc.zyngier@arm.com, christoffer.dall@linaro.org, pbonzini@redhat.com
Cc: linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org,
kvmarm@lists.cs.columbia.edu
Subject: [PATCH v2 11/12] KVM: arm/arm64: rework MMIO abort handling to use KVM MMIO bus
Date: Mon, 23 Mar 2015 15:58:28 +0000 [thread overview]
Message-ID: <1427126309-11223-12-git-send-email-andre.przywara@arm.com> (raw)
In-Reply-To: <1427126309-11223-1-git-send-email-andre.przywara@arm.com>
Currently we have struct kvm_exit_mmio for encapsulating MMIO abort
data to be passed on from syndrome decoding all the way down to the
VGIC register handlers. Now as we switch the MMIO handling to be
routed through the KVM MMIO bus, it does not make sense anymore to
use that structure already from the beginning. So we put the data into
kvm_run very early and use that encapsulation till the MMIO bus call.
Then we fill kvm_exit_mmio in the VGIC only, making it a VGIC private
structure. On that way we replace the data buffer in that structure
with a pointer pointing to a single location in kvm_run, so we get
rid of some copying on the way.
I didn't bother to rename kvm_exit_mmio (to vgic_mmio or something),
because that touches a lot of code lines without any good reason.
This is based on an original patch by Nikolay.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Cc: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
---
arch/arm/include/asm/kvm_mmio.h | 22 --------------
arch/arm/kvm/mmio.c | 60 ++++++++++++++++++++++++++-----------
arch/arm64/include/asm/kvm_mmio.h | 22 --------------
include/kvm/arm_vgic.h | 3 --
virt/kvm/arm/vgic.c | 18 +++--------
virt/kvm/arm/vgic.h | 8 +++++
6 files changed, 55 insertions(+), 78 deletions(-)
diff --git a/arch/arm/include/asm/kvm_mmio.h b/arch/arm/include/asm/kvm_mmio.h
index 3f83db2..d8e90c8 100644
--- a/arch/arm/include/asm/kvm_mmio.h
+++ b/arch/arm/include/asm/kvm_mmio.h
@@ -28,28 +28,6 @@ struct kvm_decode {
bool sign_extend;
};
-/*
- * The in-kernel MMIO emulation code wants to use a copy of run->mmio,
- * which is an anonymous type. Use our own type instead.
- */
-struct kvm_exit_mmio {
- phys_addr_t phys_addr;
- u8 data[8];
- u32 len;
- bool is_write;
- void *private;
-};
-
-static inline void kvm_prepare_mmio(struct kvm_run *run,
- struct kvm_exit_mmio *mmio)
-{
- run->mmio.phys_addr = mmio->phys_addr;
- run->mmio.len = mmio->len;
- run->mmio.is_write = mmio->is_write;
- memcpy(run->mmio.data, mmio->data, mmio->len);
- run->exit_reason = KVM_EXIT_MMIO;
-}
-
int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
phys_addr_t fault_ipa);
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 5d3bfc0..bb2ab44 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -122,7 +122,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
}
static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
- struct kvm_exit_mmio *mmio)
+ struct kvm_run *run)
{
unsigned long rt;
int len;
@@ -148,9 +148,9 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
sign_extend = kvm_vcpu_dabt_issext(vcpu);
rt = kvm_vcpu_dabt_get_rd(vcpu);
- mmio->is_write = is_write;
- mmio->phys_addr = fault_ipa;
- mmio->len = len;
+ run->mmio.is_write = is_write;
+ run->mmio.phys_addr = fault_ipa;
+ run->mmio.len = len;
vcpu->arch.mmio_decode.sign_extend = sign_extend;
vcpu->arch.mmio_decode.rt = rt;
@@ -162,23 +162,49 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
return 0;
}
+/**
+ * handle_kernel_mmio - handle an in-kernel MMIO access
+ * @vcpu: pointer to the vcpu performing the access
+ * @run: pointer to the kvm_run structure
+ *
+ * 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)
+{
+ int ret;
+
+ if (run->mmio.is_write) {
+ ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, run->mmio.phys_addr,
+ run->mmio.len, run->mmio.data);
+
+ } else {
+ ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, run->mmio.phys_addr,
+ run->mmio.len, run->mmio.data);
+ }
+ if (!ret) {
+ kvm_handle_mmio_return(vcpu, run);
+ return true;
+ }
+
+ return false;
+}
+
int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
phys_addr_t fault_ipa)
{
- struct kvm_exit_mmio mmio;
unsigned long data;
unsigned long rt;
int ret;
/*
- * Prepare MMIO operation. First stash it in a private
- * structure that we can use for in-kernel emulation. If the
- * kernel can't handle it, copy it into run->mmio and let user
- * space do its magic.
+ * Prepare MMIO operation. First put the MMIO data into run->mmio.
+ * Then try if some in-kernel emulation feels responsible, otherwise
+ * let user space do its magic.
*/
if (kvm_vcpu_dabt_isvalid(vcpu)) {
- ret = decode_hsr(vcpu, fault_ipa, &mmio);
+ ret = decode_hsr(vcpu, fault_ipa, run);
if (ret)
return ret;
} else {
@@ -188,21 +214,21 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
rt = vcpu->arch.mmio_decode.rt;
- if (mmio.is_write) {
+ if (run->mmio.is_write) {
data = vcpu_data_guest_to_host(vcpu, *vcpu_reg(vcpu, rt),
- mmio.len);
+ run->mmio.len);
- trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, mmio.len,
+ trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, run->mmio.len,
fault_ipa, data);
- mmio_write_buf(mmio.data, mmio.len, data);
+ mmio_write_buf(run->mmio.data, run->mmio.len, data);
} else {
- trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, mmio.len,
+ trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, run->mmio.len,
fault_ipa, 0);
}
- if (vgic_handle_mmio(vcpu, run, &mmio))
+ if (handle_kernel_mmio(vcpu, run))
return 1;
- kvm_prepare_mmio(run, &mmio);
+ run->exit_reason = KVM_EXIT_MMIO;
return 0;
}
diff --git a/arch/arm64/include/asm/kvm_mmio.h b/arch/arm64/include/asm/kvm_mmio.h
index 9f52beb..889c908 100644
--- a/arch/arm64/include/asm/kvm_mmio.h
+++ b/arch/arm64/include/asm/kvm_mmio.h
@@ -31,28 +31,6 @@ struct kvm_decode {
bool sign_extend;
};
-/*
- * The in-kernel MMIO emulation code wants to use a copy of run->mmio,
- * which is an anonymous type. Use our own type instead.
- */
-struct kvm_exit_mmio {
- phys_addr_t phys_addr;
- u8 data[8];
- u32 len;
- bool is_write;
- void *private;
-};
-
-static inline void kvm_prepare_mmio(struct kvm_run *run,
- struct kvm_exit_mmio *mmio)
-{
- run->mmio.phys_addr = mmio->phys_addr;
- run->mmio.len = mmio->len;
- run->mmio.is_write = mmio->is_write;
- memcpy(run->mmio.data, mmio->data, mmio->len);
- run->exit_reason = KVM_EXIT_MMIO;
-}
-
int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
phys_addr_t fault_ipa);
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index d6705f4..14853d8 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -314,7 +314,6 @@ struct vgic_cpu {
struct kvm;
struct kvm_vcpu;
struct kvm_run;
-struct kvm_exit_mmio;
int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
int kvm_vgic_hyp_init(void);
@@ -330,8 +329,6 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
int kvm_vgic_vcpu_active_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.nr_cpus))
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 9cbb55f4..2598fe8 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -758,7 +758,6 @@ static bool call_range_handler(struct kvm_vcpu *vcpu,
unsigned long offset,
const struct vgic_io_range *range)
{
- u32 *data32 = (void *)mmio->data;
struct kvm_exit_mmio mmio32;
bool ret;
@@ -775,18 +774,12 @@ static bool call_range_handler(struct kvm_vcpu *vcpu,
mmio32.private = mmio->private;
mmio32.phys_addr = mmio->phys_addr + 4;
- if (mmio->is_write)
- *(u32 *)mmio32.data = data32[1];
+ mmio32.data = &((u32 *)mmio->data)[1];
ret = range->handle_mmio(vcpu, &mmio32, offset + 4);
- if (!mmio->is_write)
- data32[1] = *(u32 *)mmio32.data;
mmio32.phys_addr = mmio->phys_addr;
- if (mmio->is_write)
- *(u32 *)mmio32.data = data32[0];
+ mmio32.data = &((u32 *)mmio->data)[0];
ret |= range->handle_mmio(vcpu, &mmio32, offset);
- if (!mmio->is_write)
- data32[0] = *(u32 *)mmio32.data;
return ret;
}
@@ -873,23 +866,20 @@ static int vgic_handle_mmio_access(struct kvm_vcpu *vcpu,
mmio.phys_addr = addr;
mmio.len = len;
mmio.is_write = is_write;
- if (is_write)
- memcpy(mmio.data, val, len);
+ mmio.data = val;
mmio.private = iodev->redist_vcpu;
spin_lock(&dist->lock);
offset -= range->base;
if (vgic_validate_access(dist, range, offset)) {
updated_state = call_range_handler(vcpu, &mmio, offset, range);
- if (!is_write)
- memcpy(val, mmio.data, len);
} else {
if (!is_write)
memset(val, 0, len);
updated_state = false;
}
spin_unlock(&dist->lock);
- kvm_prepare_mmio(run, &mmio);
+ run->exit_reason = KVM_EXIT_MMIO;
kvm_handle_mmio_return(vcpu, run);
if (updated_state)
diff --git a/virt/kvm/arm/vgic.h b/virt/kvm/arm/vgic.h
index 28fa3aa..fc73103 100644
--- a/virt/kvm/arm/vgic.h
+++ b/virt/kvm/arm/vgic.h
@@ -59,6 +59,14 @@ void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq);
void vgic_unqueue_irqs(struct kvm_vcpu *vcpu);
+struct kvm_exit_mmio {
+ phys_addr_t phys_addr;
+ void *data;
+ u32 len;
+ bool is_write;
+ void *private;
+};
+
void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg,
phys_addr_t offset, int mode);
bool handle_mmio_raz_wi(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio,
--
1.7.9.5
next prev parent reply other threads:[~2015-03-23 15:51 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-23 15:58 [PATCH v2 00/12] KVM: arm/arm64: move VGIC MMIO to kvm_io_bus Andre Przywara
2015-03-23 15:58 ` [PATCH v2 01/12] KVM: Redesign kvm_io_bus_ API to pass VCPU structure to the callbacks Andre Przywara
2015-03-25 16:56 ` Marc Zyngier
2015-03-23 15:58 ` [PATCH v2 02/12] KVM: move iodev.h from virt/kvm/ to include/kvm Andre Przywara
2015-03-25 17:00 ` Marc Zyngier
2015-03-25 21:41 ` Marcelo Tosatti
2015-03-23 15:58 ` [PATCH v2 03/12] KVM: arm/arm64: remove now unneeded include directory from Makefile Andre Przywara
2015-03-25 17:00 ` Marc Zyngier
2015-03-23 15:58 ` [PATCH v2 04/12] KVM: x86: " Andre Przywara
2015-03-25 17:01 ` Marc Zyngier
2015-03-25 21:41 ` Marcelo Tosatti
2015-03-23 15:58 ` [PATCH v2 05/12] KVM: arm/arm64: rename struct kvm_mmio_range to vgic_io_range Andre Przywara
2015-03-25 17:02 ` Marc Zyngier
2015-03-23 15:58 ` [PATCH v2 06/12] KVM: mark kvm->buses as empty once they were destroyed Andre Przywara
2015-03-25 17:09 ` Marc Zyngier
2015-03-25 21:59 ` Marcelo Tosatti
2015-03-26 12:41 ` Andre Przywara
2015-03-27 1:31 ` Marcelo Tosatti
2015-03-27 2:10 ` Chen, Tiejun
2015-03-23 15:58 ` [PATCH v2 07/12] KVM: arm/arm64: simplify vgic_find_range() and callers Andre Przywara
2015-03-25 17:13 ` Marc Zyngier
2015-03-23 15:58 ` [PATCH v2 08/12] KVM: arm/arm64: implement kvm_io_bus MMIO handling for the VGIC Andre Przywara
2015-03-25 17:18 ` Marc Zyngier
2015-03-23 15:58 ` [PATCH v2 09/12] KVM: arm/arm64: prepare GICv2 emulation to be handled by kvm_io_bus Andre Przywara
2015-03-25 17:21 ` Marc Zyngier
2015-03-23 15:58 ` [PATCH v2 10/12] KVM: arm/arm64: prepare GICv3 emulation to use kvm_io_bus MMIO handling Andre Przywara
2015-03-25 17:36 ` Marc Zyngier
2015-03-23 15:58 ` Andre Przywara [this message]
2015-03-23 21:43 ` [PATCH v2 11/12] KVM: arm/arm64: rework MMIO abort handling to use KVM MMIO bus Nikolay Nikolaev
2015-03-24 16:03 ` [PATCH] KVM: arm/arm64: fix MMIO handling on userland induced accesses Andre Przywara
2015-03-25 17:37 ` Marc Zyngier
2015-03-23 15:58 ` [PATCH v2 12/12] KVM: arm/arm64: remove now obsolete VGIC specific MMIO handling code Andre Przywara
2015-03-25 17:36 ` Marc Zyngier
2015-03-27 9:33 ` Marc Zyngier
2015-03-23 21:50 ` [PATCH v2 00/12] KVM: arm/arm64: move VGIC MMIO to kvm_io_bus Nikolay Nikolaev
2015-03-24 10:10 ` Marc Zyngier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1427126309-11223-12-git-send-email-andre.przywara@arm.com \
--to=andre.przywara@arm.com \
--cc=christoffer.dall@linaro.org \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.cs.columbia.edu \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=marc.zyngier@arm.com \
--cc=pbonzini@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox