|
@@ -68,6 +68,45 @@ struct its_itte {
|
|
|
*/
|
|
|
#define CBASER_ADDRESS(x) ((x) & GENMASK_ULL(47, 12))
|
|
|
#define PENDBASER_ADDRESS(x) ((x) & GENMASK_ULL(47, 16))
|
|
|
+#define PROPBASER_ADDRESS(x) ((x) & GENMASK_ULL(47, 12))
|
|
|
+
|
|
|
+#define GIC_LPI_OFFSET 8192
|
|
|
+
|
|
|
+#define LPI_PROP_ENABLE_BIT(p) ((p) & LPI_PROP_ENABLED)
|
|
|
+#define LPI_PROP_PRIORITY(p) ((p) & 0xfc)
|
|
|
+
|
|
|
+/*
|
|
|
+ * Reads the configuration data for a given LPI from guest memory and
|
|
|
+ * updates the fields in struct vgic_irq.
|
|
|
+ * If filter_vcpu is not NULL, applies only if the IRQ is targeting this
|
|
|
+ * VCPU. Unconditionally applies if filter_vcpu is NULL.
|
|
|
+ */
|
|
|
+static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
|
|
|
+ struct kvm_vcpu *filter_vcpu)
|
|
|
+{
|
|
|
+ u64 propbase = PROPBASER_ADDRESS(kvm->arch.vgic.propbaser);
|
|
|
+ u8 prop;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = kvm_read_guest(kvm, propbase + irq->intid - GIC_LPI_OFFSET,
|
|
|
+ &prop, 1);
|
|
|
+
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ spin_lock(&irq->irq_lock);
|
|
|
+
|
|
|
+ if (!filter_vcpu || filter_vcpu == irq->target_vcpu) {
|
|
|
+ irq->priority = LPI_PROP_PRIORITY(prop);
|
|
|
+ irq->enabled = LPI_PROP_ENABLE_BIT(prop);
|
|
|
+
|
|
|
+ vgic_queue_irq_unlock(kvm, irq);
|
|
|
+ } else {
|
|
|
+ spin_unlock(&irq->irq_lock);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
/*
|
|
|
* Create a snapshot of the current LPI list, so that we can enumerate all
|