aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@arm.com>2015-03-26 10:39:34 -0400
committerMarc Zyngier <marc.zyngier@arm.com>2015-03-26 17:43:14 -0400
commit6777f77f0f544f686ee3158ff0db6a7d81b7d3a2 (patch)
tree6000815254750f2d1f85d3308ffee420af9844a9 /virt
parent9f199d0a0eeb8efb564ff41a6b9f819c4c0285ea (diff)
KVM: arm/arm64: implement kvm_io_bus MMIO handling for the VGIC
Currently we use a lot of VGIC specific code to do the MMIO dispatching. Use the previous reworks to add kvm_io_bus style MMIO handlers. Those are not yet called by the MMIO abort handler, also the actual VGIC emulator function do not make use of it yet, but will be enabled with the following patches. Signed-off-by: Andre Przywara <andre.przywara@arm.com> Reviewed-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/arm/vgic.c129
-rw-r--r--virt/kvm/arm/vgic.h7
2 files changed, 136 insertions, 0 deletions
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 8802ad73467f..e968179e592f 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -32,6 +32,8 @@
32#include <asm/kvm_arm.h> 32#include <asm/kvm_arm.h>
33#include <asm/kvm_mmu.h> 33#include <asm/kvm_mmu.h>
34#include <trace/events/kvm.h> 34#include <trace/events/kvm.h>
35#include <asm/kvm.h>
36#include <kvm/iodev.h>
35 37
36/* 38/*
37 * How the whole thing works (courtesy of Christoffer Dall): 39 * How the whole thing works (courtesy of Christoffer Dall):
@@ -837,6 +839,66 @@ bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
837} 839}
838 840
839/** 841/**
842 * vgic_handle_mmio_access - handle an in-kernel MMIO access
843 * This is called by the read/write KVM IO device wrappers below.
844 * @vcpu: pointer to the vcpu performing the access
845 * @this: pointer to the KVM IO device in charge
846 * @addr: guest physical address of the access
847 * @len: size of the access
848 * @val: pointer to the data region
849 * @is_write: read or write access
850 *
851 * returns true if the MMIO access could be performed
852 */
853static int vgic_handle_mmio_access(struct kvm_vcpu *vcpu,
854 struct kvm_io_device *this, gpa_t addr,
855 int len, void *val, bool is_write)
856{
857 struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
858 struct vgic_io_device *iodev = container_of(this,
859 struct vgic_io_device, dev);
860 struct kvm_run *run = vcpu->run;
861 const struct vgic_io_range *range;
862 struct kvm_exit_mmio mmio;
863 bool updated_state;
864 gpa_t offset;
865
866 offset = addr - iodev->addr;
867 range = vgic_find_range(iodev->reg_ranges, len, offset);
868 if (unlikely(!range || !range->handle_mmio)) {
869 pr_warn("Unhandled access %d %08llx %d\n", is_write, addr, len);
870 return -ENXIO;
871 }
872
873 mmio.phys_addr = addr;
874 mmio.len = len;
875 mmio.is_write = is_write;
876 if (is_write)
877 memcpy(mmio.data, val, len);
878 mmio.private = iodev->redist_vcpu;
879
880 spin_lock(&dist->lock);
881 offset -= range->base;
882 if (vgic_validate_access(dist, range, offset)) {
883 updated_state = call_range_handler(vcpu, &mmio, offset, range);
884 if (!is_write)
885 memcpy(val, mmio.data, len);
886 } else {
887 if (!is_write)
888 memset(val, 0, len);
889 updated_state = false;
890 }
891 spin_unlock(&dist->lock);
892 kvm_prepare_mmio(run, &mmio);
893 kvm_handle_mmio_return(vcpu, run);
894
895 if (updated_state)
896 vgic_kick_vcpus(vcpu->kvm);
897
898 return 0;
899}
900
901/**
840 * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation 902 * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
841 * @vcpu: pointer to the vcpu performing the access 903 * @vcpu: pointer to the vcpu performing the access
842 * @run: pointer to the kvm_run structure 904 * @run: pointer to the kvm_run structure
@@ -860,6 +922,73 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
860 return vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, run, mmio); 922 return vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, run, mmio);
861} 923}
862 924
925static int vgic_handle_mmio_read(struct kvm_vcpu *vcpu,
926 struct kvm_io_device *this,
927 gpa_t addr, int len, void *val)
928{
929 return vgic_handle_mmio_access(vcpu, this, addr, len, val, false);
930}
931
932static int vgic_handle_mmio_write(struct kvm_vcpu *vcpu,
933 struct kvm_io_device *this,
934 gpa_t addr, int len, const void *val)
935{
936 return vgic_handle_mmio_access(vcpu, this, addr, len, (void *)val,
937 true);
938}
939
940struct kvm_io_device_ops vgic_io_ops = {
941 .read = vgic_handle_mmio_read,
942 .write = vgic_handle_mmio_write,
943};
944
945/**
946 * vgic_register_kvm_io_dev - register VGIC register frame on the KVM I/O bus
947 * @kvm: The VM structure pointer
948 * @base: The (guest) base address for the register frame
949 * @len: Length of the register frame window
950 * @ranges: Describing the handler functions for each register
951 * @redist_vcpu_id: The VCPU ID to pass on to the handlers on call
952 * @iodev: Points to memory to be passed on to the handler
953 *
954 * @iodev stores the parameters of this function to be usable by the handler
955 * respectively the dispatcher function (since the KVM I/O bus framework lacks
956 * an opaque parameter). Initialization is done in this function, but the
957 * reference should be valid and unique for the whole VGIC lifetime.
958 * If the register frame is not mapped for a specific VCPU, pass -1 to
959 * @redist_vcpu_id.
960 */
961int vgic_register_kvm_io_dev(struct kvm *kvm, gpa_t base, int len,
962 const struct vgic_io_range *ranges,
963 int redist_vcpu_id,
964 struct vgic_io_device *iodev)
965{
966 struct kvm_vcpu *vcpu = NULL;
967 int ret;
968
969 if (redist_vcpu_id >= 0)
970 vcpu = kvm_get_vcpu(kvm, redist_vcpu_id);
971
972 iodev->addr = base;
973 iodev->len = len;
974 iodev->reg_ranges = ranges;
975 iodev->redist_vcpu = vcpu;
976
977 kvm_iodevice_init(&iodev->dev, &vgic_io_ops);
978
979 mutex_lock(&kvm->slots_lock);
980
981 ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, base, len,
982 &iodev->dev);
983 mutex_unlock(&kvm->slots_lock);
984
985 /* Mark the iodev as invalid if registration fails. */
986 if (ret)
987 iodev->dev.ops = NULL;
988
989 return ret;
990}
991
863static int vgic_nr_shared_irqs(struct vgic_dist *dist) 992static int vgic_nr_shared_irqs(struct vgic_dist *dist)
864{ 993{
865 return dist->nr_irqs - VGIC_NR_PRIVATE_IRQS; 994 return dist->nr_irqs - VGIC_NR_PRIVATE_IRQS;
diff --git a/virt/kvm/arm/vgic.h b/virt/kvm/arm/vgic.h
index 01aa6228f88b..28fa3aaf6367 100644
--- a/virt/kvm/arm/vgic.h
+++ b/virt/kvm/arm/vgic.h
@@ -20,6 +20,8 @@
20#ifndef __KVM_VGIC_H__ 20#ifndef __KVM_VGIC_H__
21#define __KVM_VGIC_H__ 21#define __KVM_VGIC_H__
22 22
23#include <kvm/iodev.h>
24
23#define VGIC_ADDR_UNDEF (-1) 25#define VGIC_ADDR_UNDEF (-1)
24#define IS_VGIC_ADDR_UNDEF(_x) ((_x) == VGIC_ADDR_UNDEF) 26#define IS_VGIC_ADDR_UNDEF(_x) ((_x) == VGIC_ADDR_UNDEF)
25 27
@@ -82,6 +84,11 @@ struct vgic_io_range {
82 phys_addr_t offset); 84 phys_addr_t offset);
83}; 85};
84 86
87int vgic_register_kvm_io_dev(struct kvm *kvm, gpa_t base, int len,
88 const struct vgic_io_range *ranges,
89 int redist_id,
90 struct vgic_io_device *iodev);
91
85static inline bool is_in_range(phys_addr_t addr, unsigned long len, 92static inline bool is_in_range(phys_addr_t addr, unsigned long len,
86 phys_addr_t baseaddr, unsigned long size) 93 phys_addr_t baseaddr, unsigned long size)
87{ 94{