[PATCH v2 11/12] KVM: arm/arm64: rework MMIO abort handling to use KVM MMIO bus

2015-03-23 Thread Andre Przywara
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.przyw...@arm.com
Cc: Nikolay Nikolaev n.nikol...@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;
-   boolis_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 

Re: [PATCH v2 11/12] KVM: arm/arm64: rework MMIO abort handling to use KVM MMIO bus

2015-03-23 Thread Nikolay Nikolaev
On Mon, Mar 23, 2015 at 5:58 PM, Andre Przywara andre.przyw...@arm.com wrote:

 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),
I would vote for the renaming.

Otherwise the patch looks much cleaner and straightforward than what
it was before.

Nikolay Nikolaev

 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.przyw...@arm.com
 Cc: Nikolay Nikolaev n.nikol...@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;
 -   boolis_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.