1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * ARM Generic Interrupt Controller (GIC) v3 host support 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/kvm.h> 8 #include <linux/sizes.h> 9 #include <asm/cputype.h> 10 #include <asm/kvm_para.h> 11 #include <asm/kvm.h> 12 13 #include "kvm_util.h" 14 #include "vgic.h" 15 #include "gic.h" 16 #include "gic_v3.h" 17 18 bool kvm_supports_vgic_v3(void) 19 { 20 struct kvm_vm *vm = vm_create_barebones(); 21 int r; 22 23 r = __kvm_test_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3); 24 kvm_vm_free(vm); 25 26 return !r; 27 } 28 29 /* 30 * vGIC-v3 default host setup 31 * 32 * Input args: 33 * vm - KVM VM 34 * nr_vcpus - Number of vCPUs supported by this VM 35 * 36 * Output args: None 37 * 38 * Return: GIC file-descriptor or negative error code upon failure 39 * 40 * The function creates a vGIC-v3 device and maps the distributor and 41 * redistributor regions of the guest. Since it depends on the number of 42 * vCPUs for the VM, it must be called after all the vCPUs have been created. 43 */ 44 int __vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs) 45 { 46 int gic_fd; 47 uint64_t attr; 48 unsigned int nr_gic_pages; 49 50 /* Distributor setup */ 51 gic_fd = __kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3); 52 if (gic_fd < 0) 53 return gic_fd; 54 55 kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, &nr_irqs); 56 57 attr = GICD_BASE_GPA; 58 kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, 59 KVM_VGIC_V3_ADDR_TYPE_DIST, &attr); 60 nr_gic_pages = vm_calc_num_guest_pages(vm->mode, KVM_VGIC_V3_DIST_SIZE); 61 virt_map(vm, GICD_BASE_GPA, GICD_BASE_GPA, nr_gic_pages); 62 63 /* Redistributor setup */ 64 attr = REDIST_REGION_ATTR_ADDR(nr_vcpus, GICR_BASE_GPA, 0, 0); 65 kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, 66 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &attr); 67 nr_gic_pages = vm_calc_num_guest_pages(vm->mode, 68 KVM_VGIC_V3_REDIST_SIZE * nr_vcpus); 69 virt_map(vm, GICR_BASE_GPA, GICR_BASE_GPA, nr_gic_pages); 70 71 return gic_fd; 72 } 73 74 void __vgic_v3_init(int fd) 75 { 76 kvm_device_attr_set(fd, KVM_DEV_ARM_VGIC_GRP_CTRL, 77 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL); 78 } 79 80 int vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs) 81 { 82 unsigned int nr_vcpus_created = 0; 83 struct list_head *iter; 84 int fd; 85 86 TEST_ASSERT(nr_vcpus, "Number of vCPUs cannot be empty"); 87 88 /* 89 * Make sure that the caller is infact calling this 90 * function after all the vCPUs are added. 91 */ 92 list_for_each(iter, &vm->vcpus) 93 nr_vcpus_created++; 94 TEST_ASSERT(nr_vcpus == nr_vcpus_created, 95 "Number of vCPUs requested (%u) doesn't match with the ones created for the VM (%u)", 96 nr_vcpus, nr_vcpus_created); 97 98 fd = __vgic_v3_setup(vm, nr_vcpus, nr_irqs); 99 if (fd < 0) 100 return fd; 101 102 __vgic_v3_init(fd); 103 return fd; 104 } 105 106 /* should only work for level sensitive interrupts */ 107 int _kvm_irq_set_level_info(int gic_fd, uint32_t intid, int level) 108 { 109 uint64_t attr = 32 * (intid / 32); 110 uint64_t index = intid % 32; 111 uint64_t val; 112 int ret; 113 114 ret = __kvm_device_attr_get(gic_fd, KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO, 115 attr, &val); 116 if (ret != 0) 117 return ret; 118 119 val |= 1U << index; 120 ret = __kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO, 121 attr, &val); 122 return ret; 123 } 124 125 void kvm_irq_set_level_info(int gic_fd, uint32_t intid, int level) 126 { 127 int ret = _kvm_irq_set_level_info(gic_fd, intid, level); 128 129 TEST_ASSERT(!ret, KVM_IOCTL_ERROR(KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO, ret)); 130 } 131 132 int _kvm_arm_irq_line(struct kvm_vm *vm, uint32_t intid, int level) 133 { 134 uint32_t irq = intid & KVM_ARM_IRQ_NUM_MASK; 135 136 TEST_ASSERT(!INTID_IS_SGI(intid), "KVM_IRQ_LINE's interface itself " 137 "doesn't allow injecting SGIs. There's no mask for it."); 138 139 if (INTID_IS_PPI(intid)) 140 irq |= KVM_ARM_IRQ_TYPE_PPI << KVM_ARM_IRQ_TYPE_SHIFT; 141 else 142 irq |= KVM_ARM_IRQ_TYPE_SPI << KVM_ARM_IRQ_TYPE_SHIFT; 143 144 return _kvm_irq_line(vm, irq, level); 145 } 146 147 void kvm_arm_irq_line(struct kvm_vm *vm, uint32_t intid, int level) 148 { 149 int ret = _kvm_arm_irq_line(vm, intid, level); 150 151 TEST_ASSERT(!ret, KVM_IOCTL_ERROR(KVM_IRQ_LINE, ret)); 152 } 153 154 static void vgic_poke_irq(int gic_fd, uint32_t intid, struct kvm_vcpu *vcpu, 155 uint64_t reg_off) 156 { 157 uint64_t reg = intid / 32; 158 uint64_t index = intid % 32; 159 uint64_t attr = reg_off + reg * 4; 160 uint64_t val; 161 bool intid_is_private = INTID_IS_SGI(intid) || INTID_IS_PPI(intid); 162 163 uint32_t group = intid_is_private ? KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 164 : KVM_DEV_ARM_VGIC_GRP_DIST_REGS; 165 166 if (intid_is_private) { 167 /* TODO: only vcpu 0 implemented for now. */ 168 assert(vcpu->id == 0); 169 attr += SZ_64K; 170 } 171 172 /* Check that the addr part of the attr is within 32 bits. */ 173 assert((attr & ~KVM_DEV_ARM_VGIC_OFFSET_MASK) == 0); 174 175 /* 176 * All calls will succeed, even with invalid intid's, as long as the 177 * addr part of the attr is within 32 bits (checked above). An invalid 178 * intid will just make the read/writes point to above the intended 179 * register space (i.e., ICPENDR after ISPENDR). 180 */ 181 kvm_device_attr_get(gic_fd, group, attr, &val); 182 val |= 1ULL << index; 183 kvm_device_attr_set(gic_fd, group, attr, &val); 184 } 185 186 void kvm_irq_write_ispendr(int gic_fd, uint32_t intid, struct kvm_vcpu *vcpu) 187 { 188 vgic_poke_irq(gic_fd, intid, vcpu, GICD_ISPENDR); 189 } 190 191 void kvm_irq_write_isactiver(int gic_fd, uint32_t intid, struct kvm_vcpu *vcpu) 192 { 193 vgic_poke_irq(gic_fd, intid, vcpu, GICD_ISACTIVER); 194 } 195 196 int vgic_its_setup(struct kvm_vm *vm) 197 { 198 int its_fd = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_ITS); 199 u64 attr; 200 201 attr = GITS_BASE_GPA; 202 kvm_device_attr_set(its_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, 203 KVM_VGIC_ITS_ADDR_TYPE, &attr); 204 205 kvm_device_attr_set(its_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, 206 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL); 207 208 virt_map(vm, GITS_BASE_GPA, GITS_BASE_GPA, 209 vm_calc_num_guest_pages(vm->mode, KVM_VGIC_V3_ITS_SIZE)); 210 211 return its_fd; 212 } 213