KVM: arm/arm64: vgic-new: vgic_kvm_device: implement kvm_vgic_addr
kvm_vgic_addr is used by the userspace to set the base address of the following register regions, as seen by the guest: - distributor(v2 and v3), - re-distributors (v3), - CPU interface (v2). Signed-off-by: Eric Auger <eric.auger@linaro.org> Signed-off-by: Andre Przywara <andre.przywara@arm.com> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
This commit is contained in:
parent
afcc7c50ce
commit
e2c1f9abff
|
@ -194,6 +194,8 @@ struct vgic_cpu {
|
|||
u64 live_lrs;
|
||||
};
|
||||
|
||||
int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
|
||||
|
||||
int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
|
||||
bool level);
|
||||
|
||||
|
|
|
@ -16,10 +16,96 @@
|
|||
#include <linux/kvm_host.h>
|
||||
#include <kvm/arm_vgic.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/kvm_mmu.h>
|
||||
#include "vgic.h"
|
||||
|
||||
/* common helpers */
|
||||
|
||||
static int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
|
||||
phys_addr_t addr, phys_addr_t alignment)
|
||||
{
|
||||
if (addr & ~KVM_PHYS_MASK)
|
||||
return -E2BIG;
|
||||
|
||||
if (!IS_ALIGNED(addr, alignment))
|
||||
return -EINVAL;
|
||||
|
||||
if (!IS_VGIC_ADDR_UNDEF(*ioaddr))
|
||||
return -EEXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_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
|
||||
*
|
||||
* Set or get the vgic base addresses for the distributor and the virtual CPU
|
||||
* interface in the VM physical address space. These addresses are properties
|
||||
* of the emulated core/SoC and therefore user space initially knows this
|
||||
* information.
|
||||
* Check them for sanity (alignment, double assignment). We can't check for
|
||||
* overlapping regions in case of a virtual GICv3 here, since we don't know
|
||||
* the number of VCPUs yet, so we defer this check to map_resources().
|
||||
*/
|
||||
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, alignment;
|
||||
|
||||
mutex_lock(&kvm->lock);
|
||||
switch (type) {
|
||||
case KVM_VGIC_V2_ADDR_TYPE_DIST:
|
||||
type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
|
||||
addr_ptr = &vgic->vgic_dist_base;
|
||||
alignment = SZ_4K;
|
||||
break;
|
||||
case KVM_VGIC_V2_ADDR_TYPE_CPU:
|
||||
type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
|
||||
addr_ptr = &vgic->vgic_cpu_base;
|
||||
alignment = SZ_4K;
|
||||
break;
|
||||
#ifdef CONFIG_KVM_ARM_VGIC_V3
|
||||
case KVM_VGIC_V3_ADDR_TYPE_DIST:
|
||||
type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
|
||||
addr_ptr = &vgic->vgic_dist_base;
|
||||
alignment = SZ_64K;
|
||||
break;
|
||||
case KVM_VGIC_V3_ADDR_TYPE_REDIST:
|
||||
type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
|
||||
addr_ptr = &vgic->vgic_redist_base;
|
||||
alignment = SZ_64K;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
r = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (vgic->vgic_model != type_needed) {
|
||||
r = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (write) {
|
||||
r = vgic_check_ioaddr(kvm, addr_ptr, *addr, alignment);
|
||||
if (!r)
|
||||
*addr_ptr = *addr;
|
||||
} else {
|
||||
*addr = *addr_ptr;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&kvm->lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int vgic_set_common_attr(struct kvm_device *dev,
|
||||
struct kvm_device_attr *attr)
|
||||
{
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#define PRODUCT_ID_KVM 0x4b /* ASCII code K */
|
||||
#define IMPLEMENTER_ARM 0x43b
|
||||
|
||||
#define VGIC_ADDR_UNDEF (-1)
|
||||
#define IS_VGIC_ADDR_UNDEF(_x) ((_x) == VGIC_ADDR_UNDEF)
|
||||
|
||||
#define INTERRUPT_ID_BITS_SPIS 10
|
||||
#define VGIC_PRI_BITS 5
|
||||
|
||||
|
|
Loading…
Reference in New Issue