]> xenbits.xensource.com Git - people/julieng/linux-arm.git/commitdiff
KVM: arm64: Introduce new MMIO region for the ITS base address
authorAndre Przywara <andre.przywara@arm.com>
Fri, 10 Jul 2015 14:21:42 +0000 (15:21 +0100)
committerJulien Grall <julien.grall@citrix.com>
Mon, 28 Sep 2015 11:05:12 +0000 (12:05 +0100)
The ARM GICv3 ITS controller requires a separate register frame to
cover ITS specific registers. Add a new VGIC address type and store
the address in a field in the vgic_dist structure.
Provide a function to check whether userland has provided the address,
so ITS functionality can be guarded by that check.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Vadim Lomovtsev <Vadim.Lomovtsev@caviumnetworks.com>
Documentation/virtual/kvm/devices/arm-vgic.txt
arch/arm64/include/uapi/asm/kvm.h
include/kvm/arm_vgic.h
virt/kvm/arm/vgic-v3-emul.c
virt/kvm/arm/vgic.c
virt/kvm/arm/vgic.h

index 3fb905429e8a43711d137b7efa3e3417ce6d1f5f..ec715f9ec2616e0a8c02dc1d394c1d0b082d35b0 100644 (file)
@@ -39,6 +39,15 @@ Groups:
       Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
       This address needs to be 64K aligned.
 
+    KVM_VGIC_V3_ADDR_TYPE_ITS (rw, 64-bit)
+      Base address in the guest physical address space of the GICv3 ITS
+      control register frame. The ITS allows MSI(-X) interrupts to be
+      injected into guests. This extension is optional, if the kernel
+      does not support the ITS, the call returns -ENODEV.
+      This memory is solely for the guest to access the ITS control
+      registers and does not cover the ITS translation register.
+      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
+      This address needs to be 64K aligned and the region covers 64 KByte.
 
   KVM_DEV_ARM_VGIC_GRP_DIST_REGS
   Attributes:
index 6c4c55672a731ab626fd5bf958fe9957cda38321..8af76fd46da2a11eab929a7ba0792025916a3480 100644 (file)
@@ -82,9 +82,11 @@ struct kvm_regs {
 /* Supported VGICv3 address types  */
 #define KVM_VGIC_V3_ADDR_TYPE_DIST     2
 #define KVM_VGIC_V3_ADDR_TYPE_REDIST   3
+#define KVM_VGIC_V3_ADDR_TYPE_ITS      4
 
 #define KVM_VGIC_V3_DIST_SIZE          SZ_64K
 #define KVM_VGIC_V3_REDIST_SIZE                (2 * SZ_64K)
+#define KVM_VGIC_V3_ITS_SIZE           SZ_64K
 
 #define KVM_ARM_VCPU_POWER_OFF         0 /* CPU is started in OFF state */
 #define KVM_ARM_VCPU_EL1_32BIT         1 /* CPU running a 32bit VM */
index b18e2c56e1c9e56543fc1a29e06d511d754385fc..3ee063b7cc96c386d5626f27637c811cd645b1ed 100644 (file)
@@ -178,6 +178,9 @@ struct vgic_dist {
                phys_addr_t             vgic_redist_base;
        };
 
+       /* The base address of the ITS control register frame */
+       phys_addr_t             vgic_its_base;
+
        /* Distributor enabled */
        u32                     enabled;
 
index 1f42348c2f70e7a2b622e5b79b35e273112b73ae..a8cf669b0c9c32d442206fb8bd238f92ad3b02fe 100644 (file)
@@ -887,6 +887,7 @@ void vgic_v3_init_emulation(struct kvm *kvm)
 
        dist->vgic_dist_base = VGIC_ADDR_UNDEF;
        dist->vgic_redist_base = VGIC_ADDR_UNDEF;
+       dist->vgic_its_base = VGIC_ADDR_UNDEF;
 
        kvm->arch.max_vcpus = KVM_MAX_VCPUS;
 }
@@ -1059,6 +1060,7 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
                        return -ENXIO;
                case KVM_VGIC_V3_ADDR_TYPE_DIST:
                case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+               case KVM_VGIC_V3_ADDR_TYPE_ITS:
                        return 0;
                }
                break;
index 59f1801d3357788fa431f8f0956877c8dcf47a8c..15e447f058bb59175c18728321c90e3d26b61b9a 100644 (file)
@@ -930,6 +930,16 @@ int vgic_register_kvm_io_dev(struct kvm *kvm, gpa_t base, int len,
        return ret;
 }
 
+bool vgic_has_its(struct kvm *kvm)
+{
+       struct vgic_dist *dist = &kvm->arch.vgic;
+
+       if (dist->vgic_model != KVM_DEV_TYPE_ARM_VGIC_V3)
+               return false;
+
+       return !IS_VGIC_ADDR_UNDEF(dist->vgic_its_base);
+}
+
 static int vgic_nr_shared_irqs(struct vgic_dist *dist)
 {
        return dist->nr_irqs - VGIC_NR_PRIVATE_IRQS;
@@ -1927,6 +1937,12 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
                block_size = KVM_VGIC_V3_REDIST_SIZE;
                alignment = SZ_64K;
                break;
+       case KVM_VGIC_V3_ADDR_TYPE_ITS:
+               type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+               addr_ptr = &vgic->vgic_its_base;
+               block_size = KVM_VGIC_V3_ITS_SIZE;
+               alignment = SZ_64K;
+               break;
 #endif
        default:
                r = -ENODEV;
index 0df74cbb6200686ab8cfbc853b11f27cc954b678..a093f5c25ddc4b4908ac5142c98cc025f73b9af3 100644 (file)
@@ -136,5 +136,6 @@ int vgic_get_common_attr(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_init(struct kvm *kvm);
 void vgic_v2_init_emulation(struct kvm *kvm);
 void vgic_v3_init_emulation(struct kvm *kvm);
+bool vgic_has_its(struct kvm *kvm);
 
 #endif