mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 17:57:38 -04:00
arm/arm64: KVM: allow userland to request a virtual GICv3
With all of the GICv3 code in place now we allow userland to ask the kernel for using a virtual GICv3 in the guest. Also we provide the necessary support for guests setting the memory addresses for the virtual distributor and redistributors. This requires some userland code to make use of that feature and explicitly ask for a virtual GICv3. Document that KVM_CREATE_IRQCHIP only works for GICv2, but is considered legacy and using KVM_CREATE_DEVICE is preferred. Signed-off-by: Andre Przywara <andre.przywara@arm.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
This commit is contained in:
committed by
Christoffer Dall
parent
b5d84ff600
commit
ac3d373564
@@ -1007,6 +1007,9 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
|
||||
case KVM_VGIC_V2_ADDR_TYPE_DIST:
|
||||
case KVM_VGIC_V2_ADDR_TYPE_CPU:
|
||||
return -ENXIO;
|
||||
case KVM_VGIC_V3_ADDR_TYPE_DIST:
|
||||
case KVM_VGIC_V3_ADDR_TYPE_REDIST:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
|
||||
|
||||
@@ -1667,7 +1667,7 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
|
||||
/**
|
||||
* kvm_vgic_addr - set or get vgic VM base addresses
|
||||
* @kvm: pointer to the vm struct
|
||||
* @type: the VGIC addr type, one of KVM_VGIC_V2_ADDR_TYPE_XXX
|
||||
* @type: the VGIC addr type, one of KVM_VGIC_V[23]_ADDR_TYPE_XXX
|
||||
* @addr: pointer to address value
|
||||
* @write: if true set the address in the VM address space, if false read the
|
||||
* address
|
||||
@@ -1681,29 +1681,49 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
|
||||
{
|
||||
int r = 0;
|
||||
struct vgic_dist *vgic = &kvm->arch.vgic;
|
||||
int type_needed;
|
||||
phys_addr_t *addr_ptr, block_size;
|
||||
|
||||
mutex_lock(&kvm->lock);
|
||||
switch (type) {
|
||||
case KVM_VGIC_V2_ADDR_TYPE_DIST:
|
||||
if (write) {
|
||||
r = vgic_ioaddr_assign(kvm, &vgic->vgic_dist_base,
|
||||
*addr, KVM_VGIC_V2_DIST_SIZE);
|
||||
} else {
|
||||
*addr = vgic->vgic_dist_base;
|
||||
}
|
||||
type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
|
||||
addr_ptr = &vgic->vgic_dist_base;
|
||||
block_size = KVM_VGIC_V2_DIST_SIZE;
|
||||
break;
|
||||
case KVM_VGIC_V2_ADDR_TYPE_CPU:
|
||||
if (write) {
|
||||
r = vgic_ioaddr_assign(kvm, &vgic->vgic_cpu_base,
|
||||
*addr, KVM_VGIC_V2_CPU_SIZE);
|
||||
} else {
|
||||
*addr = vgic->vgic_cpu_base;
|
||||
}
|
||||
type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
|
||||
addr_ptr = &vgic->vgic_cpu_base;
|
||||
block_size = KVM_VGIC_V2_CPU_SIZE;
|
||||
break;
|
||||
#ifdef CONFIG_ARM_GIC_V3
|
||||
case KVM_VGIC_V3_ADDR_TYPE_DIST:
|
||||
type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
|
||||
addr_ptr = &vgic->vgic_dist_base;
|
||||
block_size = KVM_VGIC_V3_DIST_SIZE;
|
||||
break;
|
||||
case KVM_VGIC_V3_ADDR_TYPE_REDIST:
|
||||
type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
|
||||
addr_ptr = &vgic->vgic_redist_base;
|
||||
block_size = KVM_VGIC_V3_REDIST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
r = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (vgic->vgic_model != type_needed) {
|
||||
r = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (write)
|
||||
r = vgic_ioaddr_assign(kvm, addr_ptr, *addr, block_size);
|
||||
else
|
||||
*addr = *addr_ptr;
|
||||
|
||||
out:
|
||||
mutex_unlock(&kvm->lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user