DO NOT MERGE: Luserspace control knob for the ITS cache
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 9a50771..775625c 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -315,6 +315,7 @@
#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2
#define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3
#define KVM_DEV_ARM_ITS_CTRL_RESET 4
+#define KVM_DEV_ARM_VGIC_PCPU_LPI_CACHE_SIZE 5
/* Device Control API on vcpu fd */
#define KVM_ARM_VCPU_PMU_V3_CTRL 0
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 298cfc3..eef69b5 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -251,6 +251,7 @@
/* LPI translation cache */
struct list_head lpi_translation_cache;
+ u32 lpi_pcpu_cache_size;
/* used by vgic-debug */
struct vgic_state_iter *iter;
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 2be6b66b..5f2ad74 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1827,13 +1827,16 @@
void vgic_lpi_translation_cache_init(struct kvm *kvm)
{
struct vgic_dist *dist = &kvm->arch.vgic;
- unsigned int sz;
+ unsigned int sz = dist->lpi_pcpu_cache_size;
int i;
if (!list_empty(&dist->lpi_translation_cache))
return;
- sz = atomic_read(&kvm->online_vcpus) * LPI_DEFAULT_PCPU_CACHE_SIZE;
+ if (!sz)
+ sz = LPI_DEFAULT_PCPU_CACHE_SIZE;
+
+ sz *= atomic_read(&kvm->online_vcpus);
for (i = 0; i < sz; i++) {
struct vgic_translation_cache_entry *cte;
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 4441967..45e8033 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -642,6 +642,21 @@
unlock_all_vcpus(dev->kvm);
mutex_unlock(&dev->kvm->lock);
return ret;
+
+ case KVM_DEV_ARM_VGIC_PCPU_LPI_CACHE_SIZE: {
+ u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+ u32 val;
+
+ if (get_user(val, uaddr))
+ return -EFAULT;
+
+ /* YAAL: Yet Another Arbitrary Limit */
+ if (val > 256)
+ return -E2BIG;
+
+ dev->kvm->arch.vgic.lpi_pcpu_cache_size = val;
+ return 0;
+ }
}
break;
}
@@ -691,6 +706,17 @@
tmp32 = reg;
return put_user(tmp32, uaddr);
}
+ case KVM_DEV_ARM_VGIC_GRP_CTRL: {
+ switch (attr->attr) {
+ case KVM_DEV_ARM_VGIC_PCPU_LPI_CACHE_SIZE: {
+ u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+
+ return put_user(dev->kvm->arch.vgic.lpi_pcpu_cache_size,
+ uaddr);
+ }
+ }
+ break;
+ }
}
return -ENXIO;
}
@@ -726,6 +752,8 @@
return 0;
case KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES:
return 0;
+ case KVM_DEV_ARM_VGIC_PCPU_LPI_CACHE_SIZE:
+ return 0;
}
}
return -ENXIO;