aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
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{