Skip to contentSkip to conversation

KVM/ARM vGIC support

PATCH Superseded Christoffer Dall 4 participants 19 messages Oct 1, 2012 – Oct 3, 2012

Subsystems (2)

v2 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v2 cover KVM/ARM vGIC support

The following series implements support for the virtual generic interrupt controller architecture for KVM/ARM.

This is an unmodified repost of the previously submitted series.

This patch series can also be pulled from:
git://github.com/virtualopensystems/linux-kvm-arm.git
branch: kvm-arm-v12-vgic

---

Marc Zyngier (10):
ARM: KVM: Keep track of currently running vcpus
ARM: KVM: Initial VGIC infrastructure support
ARM: KVM: Initial VGIC MMIO support code
ARM: KVM: VGIC distributor handling
ARM: KVM: VGIC virtual CPU interface management
ARM: KVM: VGIC interrupt injection
ARM: KVM: VGIC control interface world switch
ARM: KVM: VGIC initialisation code
ARM: KVM: vgic: reduce the number of vcpu kick
ARM: KVM: Add VGIC configuration option

 arch/arm/include/asm/kvm_arm.h  |   12 
 arch/arm/include/asm/kvm_host.h |   16 +
 arch/arm/include/asm/kvm_vgic.h |  301 +++++++++++
 arch/arm/kernel/asm-offsets.c   |   12 
 arch/arm/kvm/Kconfig            |    7 
 arch/arm/kvm/Makefile           |    1 
 arch/arm/kvm/arm.c              |  101 +++-
 arch/arm/kvm/interrupts.S       |    4 
 arch/arm/kvm/interrupts_head.S  |   68 ++
 arch/arm/kvm/mmu.c              |    3 
 arch/arm/kvm/vgic.c             | 1115 +++++++++++++++++++++++++++++++++++++++
 virt/kvm/kvm_main.c             |    5 
 12 files changed, 1640 insertions(+), 5 deletions(-)
 create mode 100644 arch/arm/include/asm/kvm_vgic.h
 create mode 100644 arch/arm/kvm/vgic.c
#1 lore raw

PATCH v2 1/10 ARM: KVM: Keep track of currently running vcpus

From: Marc Zyngier <[email protected]>

When an interrupt occurs for the guest, it is sometimes necessary to find out which vcpu was running at that point.

Keep track of which vcpu is being tun in kvm_arch_vcpu_ioctl_run(), and allow the data to be retrived using either:
- kvm_arm_get_running_vcpu(): returns the vcpu running at this point on the current CPU. Can only be used in a non-preemptable context.
- kvm_arm_get_running_vcpus(): returns the per-CPU variable holding the the running vcpus, useable for per-CPU interrupts.

---
 arch/arm/include/asm/kvm_host.h |    9 +++++++++
 arch/arm/kvm/arm.c              |   30 ++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)
arch/arm/include/asm/kvm_host.h +9 -0
index e4b5352..69a8680 100644
@@ -151,4 +151,13 @@ static inline int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
 {
 	return 0;
 }
+
+struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
+struct kvm_vcpu __percpu **kvm_get_running_vcpus(void);
+
+int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
+unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
+struct kvm_one_reg;
+int kvm_arm_coproc_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
+int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
 #endif /* __ARM_KVM_HOST_H__ */
arch/arm/kvm/arm.c +30 -0
index 50e9585..8764dd0 100644
@@ -53,11 +53,38 @@ static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
 static struct vfp_hard_struct __percpu *kvm_host_vfp_state;
 static unsigned long hyp_default_vectors;
 
+/* Per-CPU variable containing the currently running vcpu. */
+static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu);
+
 /* The VMID used in the VTTBR */
 static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);
 static u8 kvm_next_vmid;
 static DEFINE_SPINLOCK(kvm_vmid_lock);
 
+static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu)
+{
+	BUG_ON(preemptible());
+	__get_cpu_var(kvm_arm_running_vcpu) = vcpu;
+}
+
+/**
+ * kvm_arm_get_running_vcpu - get the vcpu running on the current CPU.
+ * Must be called from non-preemptible context
+ */
+struct kvm_vcpu *kvm_arm_get_running_vcpu(void)
+{
+	BUG_ON(preemptible());
+	return __get_cpu_var(kvm_arm_running_vcpu);
+}
+
+/**
+ * kvm_arm_get_running_vcpus - get the per-CPU array on currently running vcpus.
+ */
+struct kvm_vcpu __percpu **kvm_get_running_vcpus(void)
+{
+	return &kvm_arm_running_vcpu;
+}
+
 int kvm_arch_hardware_enable(void *garbage)
 {
 	return 0;
@@ -296,10 +323,13 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 		cpumask_clear_cpu(cpu, &vcpu->arch.require_dcache_flush);
 		flush_cache_all(); /* We'd really want v7_flush_dcache_all() */
 	}
+
+	kvm_arm_set_running_vcpu(vcpu);
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
+	kvm_arm_set_running_vcpu(NULL);
 }
 
 int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
#2 lore raw

PATCH v2 2/10 ARM: KVM: Initial VGIC infrastructure support

In reply to Christoffer Dall

From: Marc Zyngier <[email protected]>

Wire the basic framework code for VGIC support. Nothing to enable yet.

---
 arch/arm/include/asm/kvm_host.h |    7 ++++
 arch/arm/include/asm/kvm_vgic.h |   65 +++++++++++++++++++++++++++++++++++++++
 arch/arm/kvm/arm.c              |   21 ++++++++++++-
 arch/arm/kvm/interrupts.S       |    4 ++
 arch/arm/kvm/mmu.c              |    3 ++
 virt/kvm/kvm_main.c             |    5 ++-
 6 files changed, 102 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/include/asm/kvm_vgic.h
arch/arm/include/asm/kvm_host.h +7 -0
index 69a8680..d65faea 100644
@@ -22,6 +22,7 @@
 #include <asm/kvm.h>
 #include <asm/kvm_asm.h>
 #include <asm/fpstate.h>
+#include <asm/kvm_vgic.h>
 
 #define KVM_MAX_VCPUS NR_CPUS
 #define KVM_MEMORY_SLOTS 32
@@ -52,6 +53,9 @@ struct kvm_arch {
 
 	/* VTTBR value associated with above pgd and vmid */
 	u64    vttbr;
+
+	/* Interrupt controller */
+	struct vgic_dist	vgic;
 };
 
 #define KVM_NR_MEM_OBJS     40
@@ -87,6 +91,9 @@ struct kvm_vcpu_arch {
 	struct vfp_hard_struct vfp_guest;
 	struct vfp_hard_struct *vfp_host;
 
+	/* VGIC state */
+	struct vgic_cpu vgic_cpu;
+
 	/*
 	 * Anything that is not used directly from assembly code goes
 	 * here.
arch/arm/include/asm/kvm_vgic.h new file +65 -0

65 lines not on this page · raw message

arch/arm/kvm/arm.c +20 -1
index 8764dd0..cf13340 100644
@@ -183,6 +183,9 @@ int kvm_dev_ioctl_check_extension(long ext)
 {
 	int r;
 	switch (ext) {
+#ifdef CONFIG_KVM_ARM_VGIC
+	case KVM_CAP_IRQCHIP:
+#endif
 	case KVM_CAP_USER_MEMORY:
 	case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
 	case KVM_CAP_ONE_REG:
@@ -301,6 +304,10 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
 	/* Force users to call KVM_ARM_VCPU_INIT */
 	vcpu->arch.target = -1;
+
+	/* Set up VGIC */
+	kvm_vgic_vcpu_init(vcpu);
+
 	return 0;
 }
 
@@ -360,7 +367,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
  */
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 {
-	return !!v->arch.irq_lines;
+	return !!v->arch.irq_lines || kvm_vgic_vcpu_pending_irq(v);
 }
 
 int kvm_arch_vcpu_in_guest_mode(struct kvm_vcpu *v)
@@ -629,6 +636,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 		update_vttbr(vcpu->kvm);
 
+		kvm_vgic_sync_to_cpu(vcpu);
+
 		local_irq_disable();
 
 		/*
@@ -641,6 +650,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 		if (ret <= 0 || need_new_vmid_gen(vcpu->kvm)) {
 			local_irq_enable();
+			kvm_vgic_sync_from_cpu(vcpu);
 			continue;
 		}
 
@@ -679,6 +689,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		 * Back from guest
 		 *************************************************************/
 
+		kvm_vgic_sync_from_cpu(vcpu);
+
 		ret = handle_exit(vcpu, run, ret);
 	}
 
@@ -942,6 +954,13 @@ static int init_hyp_mode(void)
 		}
 	}
 
+	/*
+	 * Init HYP view of VGIC
+	 */
+	err = kvm_vgic_hyp_init();
+	if (err)
+		goto out_free_mappings;
+
 	return 0;
 out_free_vfp:
 	free_percpu(kvm_host_vfp_state);
arch/arm/kvm/interrupts.S +4 -0
index 90347d2..914c7f2 100644
@@ -104,6 +104,8 @@ ENTRY(__kvm_vcpu_run)
 	store_mode_state sp, irq
 	store_mode_state sp, fiq
 
+	restore_vgic_state r0
+
 	@ Store hardware CP15 state and load guest state
 	read_cp15_state
 	write_cp15_state 1, r0
@@ -221,6 +223,8 @@ after_vfp_restore:
 	read_cp15_state 1, r1
 	write_cp15_state
 
+	save_vgic_state	r1
+
 	load_mode_state sp, fiq
 	load_mode_state sp, irq
 	load_mode_state sp, und
arch/arm/kvm/mmu.c +3 -0
index 0ab6ea3..5394a52 100644
@@ -830,6 +830,9 @@ static int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 	if (mmio.is_write)
 		memcpy(mmio.data, vcpu_reg(vcpu, rd), mmio.len);
 
+	if (vgic_handle_mmio(vcpu, run, &mmio))
+		return 1;
+
 	kvm_prepare_mmio(run, &mmio);
 	return 0;
 }
virt/kvm/kvm_main.c +3 -2
index c353b45..e7b0c68 100644
@@ -1883,12 +1883,13 @@ static long kvm_vcpu_ioctl(struct file *filp,
 	if (vcpu->kvm->mm != current->mm)
 		return -EIO;
 
-#if defined(CONFIG_S390) || defined(CONFIG_PPC)
+#if defined(CONFIG_S390) || defined(CONFIG_PPC) || defined(CONFIG_ARM)
 	/*
 	 * Special cases: vcpu ioctls that are asynchronous to vcpu execution,
 	 * so vcpu_load() would break it.
 	 */
-	if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_INTERRUPT)
+	if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_INTERRUPT ||
+	    ioctl == KVM_IRQ_LINE)
 		return kvm_arch_vcpu_ioctl(filp, ioctl, arg);
 #endif
 
#3 lore raw

PATCH v2 3/10 ARM: KVM: Initial VGIC MMIO support code

In reply to Christoffer Dall

From: Marc Zyngier <[email protected]>

Wire the initial in-kernel MMIO support code for the VGIC, used for the distributor emulation.

---
 arch/arm/include/asm/kvm_vgic.h |    6 +-
 arch/arm/kvm/Makefile           |    1 
 arch/arm/kvm/vgic.c             |  138 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 144 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/kvm/vgic.c
arch/arm/include/asm/kvm_vgic.h +5 -1
index e1fd530..a87ec6c 100644
@@ -30,7 +30,11 @@ struct kvm_vcpu;
 struct kvm_run;
 struct kvm_exit_mmio;
 
-#ifndef CONFIG_KVM_ARM_VGIC
+#ifdef CONFIG_KVM_ARM_VGIC
+bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
+		      struct kvm_exit_mmio *mmio);
+
+#else
 static inline int kvm_vgic_hyp_init(void)
 {
 	return 0;
arch/arm/kvm/Makefile +1 -0
index ea5b282..89608c0 100644
@@ -20,3 +20,4 @@ obj-$(CONFIG_KVM_ARM_HOST) += $(addprefix ../../../virt/kvm/, kvm_main.o coalesc
 
 obj-$(CONFIG_KVM_ARM_HOST) += arm.o guest.o mmu.o emulate.o reset.o
 obj-$(CONFIG_KVM_ARM_HOST) += coproc.o coproc_a15.o
+obj-$(CONFIG_KVM_ARM_VGIC) += vgic.o
arch/arm/kvm/vgic.c new file +138 -0

138 lines not on this page · raw message

#4 lore raw

PATCH v2 4/10 ARM: KVM: VGIC distributor handling

In reply to Christoffer Dall

From: Marc Zyngier <[email protected]>

Add the GIC distributor emulation code. A number of the GIC features are simply ignored as they are not required to boot a Linux guest.

---
 arch/arm/include/asm/kvm_vgic.h |  170 ++++++++++++++
 arch/arm/kvm/vgic.c             |  475 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 644 insertions(+), 1 deletion(-)
arch/arm/include/asm/kvm_vgic.h +170 -0
index a87ec6c..a82699f 100644
@@ -19,7 +19,177 @@
 #ifndef __ASM_ARM_KVM_VGIC_H
 #define __ASM_ARM_KVM_VGIC_H
 
+#include <linux/kernel.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/irqreturn.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#define VGIC_NR_IRQS		128
+#define VGIC_NR_SHARED_IRQS	(VGIC_NR_IRQS - 32)
+#define VGIC_MAX_CPUS		NR_CPUS
+
+/* Sanity checks... */
+#if (VGIC_MAX_CPUS > 8)
+#error	Invalid number of CPU interfaces
+#endif
+
+#if (VGIC_NR_IRQS & 31)
+#error "VGIC_NR_IRQS must be a multiple of 32"
+#endif
+
+#if (VGIC_NR_IRQS > 1024)
+#error "VGIC_NR_IRQS must be <= 1024"
+#endif
+
+/*
+ * The GIC distributor registers describing interrupts have two parts:
+ * - 32 per-CPU interrupts (SGI + PPI)
+ * - a bunch of shared interrups (SPI)
+ */
+struct vgic_bitmap {
+	union {
+		u32 reg[1];
+		unsigned long reg_ul[0];
+	} percpu[VGIC_MAX_CPUS];
+	union {
+		u32 reg[VGIC_NR_SHARED_IRQS / 32];
+		unsigned long reg_ul[0];
+	} shared;
+};
+
+static inline u32 *vgic_bitmap_get_reg(struct vgic_bitmap *x,
+				       int cpuid, u32 offset)
+{
+	offset >>= 2;
+	BUG_ON(offset > (VGIC_NR_IRQS / 32));
+	if (!offset)
+		return x->percpu[cpuid].reg;
+	else
+		return x->shared.reg + offset - 1;
+}
+
+static inline int vgic_bitmap_get_irq_val(struct vgic_bitmap *x,
+					 int cpuid, int irq)
+{
+	if (irq < 32)
+		return test_bit(irq, x->percpu[cpuid].reg_ul);
+
+	return test_bit(irq - 32, x->shared.reg_ul);
+}
+
+static inline void vgic_bitmap_set_irq_val(struct vgic_bitmap *x,
+					   int cpuid, int irq, int val)
+{
+	unsigned long *reg;
+
+	if (irq < 32)
+		reg = x->percpu[cpuid].reg_ul;
+	else {
+		reg =  x->shared.reg_ul;
+		irq -= 32;
+	}
+
+	if (val)
+		set_bit(irq, reg);
+	else
+		clear_bit(irq, reg);
+}
+
+static inline unsigned long *vgic_bitmap_get_cpu_map(struct vgic_bitmap *x,
+						     int cpuid)
+{
+	if (unlikely(cpuid >= VGIC_MAX_CPUS))
+		return NULL;
+	return x->percpu[cpuid].reg_ul;
+}
+
+static inline unsigned long *vgic_bitmap_get_shared_map(struct vgic_bitmap *x)
+{
+	return x->shared.reg_ul;
+}
+
+struct vgic_bytemap {
+	union {
+		u32 reg[8];
+		unsigned long reg_ul[0];
+	} percpu[VGIC_MAX_CPUS];
+	union {
+		u32 reg[VGIC_NR_SHARED_IRQS  / 4];
+		unsigned long reg_ul[0];
+	} shared;
+};
+
+static inline u32 *vgic_bytemap_get_reg(struct vgic_bytemap *x,
+					int cpuid, u32 offset)
+{
+	offset >>= 2;
+	BUG_ON(offset > (VGIC_NR_IRQS / 4));
+	if (offset < 4)
+		return x->percpu[cpuid].reg + offset;
+	else
+		return x->shared.reg + offset - 8;
+}
+
+static inline int vgic_bytemap_get_irq_val(struct vgic_bytemap *x,
+					   int cpuid, int irq)
+{
+	u32 *reg, shift;
+	shift = (irq & 3) * 8;
+	reg = vgic_bytemap_get_reg(x, cpuid, irq);
+	return (*reg >> shift) & 0xff;
+}
+
+static inline void vgic_bytemap_set_irq_val(struct vgic_bytemap *x,
+					    int cpuid, int irq, int val)
+{
+	u32 *reg, shift;
+	shift = (irq & 3) * 8;
+	reg = vgic_bytemap_get_reg(x, cpuid, irq);
+	*reg &= ~(0xff << shift);
+	*reg |= (val & 0xff) << shift;
+}
+
 struct vgic_dist {
+#ifdef CONFIG_KVM_ARM_VGIC
+	spinlock_t		lock;
+
+	/* Virtual control interface mapping */
+	void __iomem		*vctrl_base;
+
+	/* Distributor mapping in the guest */
+	unsigned long		vgic_dist_base;
+	unsigned long		vgic_dist_size;
+
+	/* Distributor enabled */
+	u32			enabled;
+
+	/* Interrupt enabled (one bit per IRQ) */
+	struct vgic_bitmap	irq_enabled;
+
+	/* Interrupt 'pin' level */
+	struct vgic_bitmap	irq_state;
+
+	/* Level-triggered interrupt in progress */
+	struct vgic_bitmap	irq_active;
+
+	/* Interrupt priority. Not used yet. */
+	struct vgic_bytemap	irq_priority;
+
+	/* Level/edge triggered */
+	struct vgic_bitmap	irq_cfg;
+
+	/* Source CPU per SGI and target CPU */
+	u8			irq_sgi_sources[VGIC_MAX_CPUS][16];
+
+	/* Target CPU for each IRQ */
+	u8			irq_spi_cpu[VGIC_NR_SHARED_IRQS];
+	struct vgic_bitmap	irq_spi_target[VGIC_MAX_CPUS];
+
+	/* Bitmap indicating which CPU has something pending */
+	unsigned long		irq_pending_on_cpu;
+#endif
 };
 
 struct vgic_cpu {
arch/arm/kvm/vgic.c +474 -1

503 lines not on this page · raw message

#5 lore raw

PATCH v2 5/10 ARM: KVM: VGIC virtual CPU interface management

In reply to Christoffer Dall

From: Marc Zyngier <[email protected]>

Add VGIC virtual CPU interface code, picking pending interrupts from the distributor and stashing them in the VGIC control interface list registers.

---
 arch/arm/include/asm/kvm_vgic.h |   41 +++++++
 arch/arm/kvm/vgic.c             |  224 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 264 insertions(+), 1 deletion(-)
arch/arm/include/asm/kvm_vgic.h +41 -0
index a82699f..bb67076 100644
@@ -193,17 +193,58 @@ struct vgic_dist {
 };
 
 struct vgic_cpu {
+#ifdef CONFIG_KVM_ARM_VGIC
+	/* per IRQ to LR mapping */
+	u8		vgic_irq_lr_map[VGIC_NR_IRQS];
+
+	/* Pending interrupts on this VCPU */
+	DECLARE_BITMAP(	pending, VGIC_NR_IRQS);
+
+	/* Bitmap of used/free list registers */
+	DECLARE_BITMAP(	lr_used, 64);
+
+	/* Number of list registers on this CPU */
+	int		nr_lr;
+
+	/* CPU vif control registers for world switch */
+	u32		vgic_hcr;
+	u32		vgic_vmcr;
+	u32		vgic_misr;	/* Saved only */
+	u32		vgic_eisr[2];	/* Saved only */
+	u32		vgic_elrsr[2];	/* Saved only */
+	u32		vgic_apr;
+	u32		vgic_lr[64];	/* A15 has only 4... */
+#endif
 };
 
+#define VGIC_HCR_EN		(1 << 0)
+#define VGIC_HCR_UIE		(1 << 1)
+
+#define VGIC_LR_VIRTUALID	(0x3ff << 0)
+#define VGIC_LR_PHYSID_CPUID	(7 << 10)
+#define VGIC_LR_STATE		(3 << 28)
+#define VGIC_LR_PENDING_BIT	(1 << 28)
+#define VGIC_LR_ACTIVE_BIT	(1 << 29)
+#define VGIC_LR_EOI		(1 << 19)
+
+#define VGIC_MISR_EOI		(1 << 0)
+#define VGIC_MISR_U		(1 << 1)
+
+#define LR_EMPTY	0xff
+
 struct kvm;
 struct kvm_vcpu;
 struct kvm_run;
 struct kvm_exit_mmio;
 
 #ifdef CONFIG_KVM_ARM_VGIC
+void kvm_vgic_sync_to_cpu(struct kvm_vcpu *vcpu);
+void kvm_vgic_sync_from_cpu(struct kvm_vcpu *vcpu);
+int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		      struct kvm_exit_mmio *mmio);
 
+#define irqchip_in_kernel(k)	(!!((k)->arch.vgic.vctrl_base))
 #else
 static inline int kvm_vgic_hyp_init(void)
 {
arch/arm/kvm/vgic.c +223 -1

233 lines not on this page · raw message

#6 lore raw

PATCH v2 6/10 ARM: KVM: VGIC interrupt injection

In reply to Christoffer Dall

From: Marc Zyngier <[email protected]>

Plug the interrupt injection code. Interrupts can now be generated from user space.

---
 arch/arm/include/asm/kvm_vgic.h |    8 ++++
 arch/arm/kvm/arm.c              |   36 ++++++++++++++++++
 arch/arm/kvm/vgic.c             |   77 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 120 insertions(+), 1 deletion(-)
arch/arm/include/asm/kvm_vgic.h +8 -0
index bb67076..9740f1f 100644
@@ -240,6 +240,8 @@ struct kvm_exit_mmio;
 #ifdef CONFIG_KVM_ARM_VGIC
 void kvm_vgic_sync_to_cpu(struct kvm_vcpu *vcpu);
 void kvm_vgic_sync_from_cpu(struct kvm_vcpu *vcpu);
+int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
+			bool level);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		      struct kvm_exit_mmio *mmio);
@@ -260,6 +262,12 @@ static inline void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) {}
 static inline void kvm_vgic_sync_to_cpu(struct kvm_vcpu *vcpu) {}
 static inline void kvm_vgic_sync_from_cpu(struct kvm_vcpu *vcpu) {}
 
+static inline int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid,
+				      const struct kvm_irq_level *irq)
+{
+	return 0;
+}
+
 static inline int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
 {
 	return 0;
arch/arm/kvm/arm.c +35 -1
index cf13340..be593220 100644
@@ -758,10 +758,31 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level)
 
 	switch (irq_type) {
 	case KVM_ARM_IRQ_TYPE_CPU:
+		if (irqchip_in_kernel(kvm))
+			return -ENXIO;
+
 		if (irq_num > KVM_ARM_IRQ_CPU_FIQ)
 			return -EINVAL;
 
 		return vcpu_interrupt_line(vcpu, irq_num, level);
+#ifdef CONFIG_KVM_ARM_VGIC
+	case KVM_ARM_IRQ_TYPE_PPI:
+		if (!irqchip_in_kernel(kvm))
+			return -ENXIO;
+
+		if (irq_num < 16 || irq_num > 31)
+			return -EINVAL;
+
+		return kvm_vgic_inject_irq(kvm, vcpu->vcpu_id, irq_num, level);
+	case KVM_ARM_IRQ_TYPE_SPI:
+		if (!irqchip_in_kernel(kvm))
+			return -ENXIO;
+
+		if (irq_num < 32 || irq_num > KVM_ARM_IRQ_GIC_MAX)
+			return -EINVAL;
+
+		return kvm_vgic_inject_irq(kvm, 0, irq_num, level);
+#endif
 	}
 
 	return -EINVAL;
@@ -821,7 +842,20 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
 long kvm_arch_vm_ioctl(struct file *filp,
 		       unsigned int ioctl, unsigned long arg)
 {
-	return -EINVAL;
+
+	switch (ioctl) {
+#ifdef CONFIG_KVM_ARM_VGIC
+	case KVM_CREATE_IRQCHIP: {
+		struct kvm *kvm = filp->private_data;
+		if (vgic_present)
+			return kvm_vgic_init(kvm);
+		else
+			return -EINVAL;
+	}
+#endif
+	default:
+		return -EINVAL;
+	}
 }
 
 static void cpu_init_hyp_mode(void *vector)
arch/arm/kvm/vgic.c +77 -0

92 lines not on this page · raw message

#7 lore raw

PATCH v2 7/10 ARM: KVM: VGIC control interface world switch

In reply to Christoffer Dall

From: Marc Zyngier <[email protected]>

Enable the VGIC control interface to be save-restored on world switch.

---
 arch/arm/include/asm/kvm_arm.h |   12 +++++++
 arch/arm/kernel/asm-offsets.c  |   12 +++++++
 arch/arm/kvm/interrupts_head.S |   68 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 92 insertions(+)
arch/arm/include/asm/kvm_arm.h +12 -0
index 4f1bb01..e1e39d6 100644
@@ -188,4 +188,16 @@
 #define HSR_EC_DABT	(0x24)
 #define HSR_EC_DABT_HYP	(0x25)
 
+/* GICH offsets */
+#define GICH_HCR	0x0
+#define GICH_VTR	0x4
+#define GICH_VMCR	0x8
+#define GICH_MISR	0x10
+#define GICH_EISR0 	0x20
+#define GICH_EISR1 	0x24
+#define GICH_ELRSR0 	0x30
+#define GICH_ELRSR1 	0x34
+#define GICH_APR	0xf0
+#define GICH_LR0	0x100
+
 #endif /* __ARM_KVM_ARM_H__ */
arch/arm/kernel/asm-offsets.c +12 -0
index d020e6aa..1f4a894 100644
@@ -166,6 +166,18 @@ int main(void)
   DEFINE(VCPU_HIFAR,		offsetof(struct kvm_vcpu, arch.hifar));
   DEFINE(VCPU_HPFAR,		offsetof(struct kvm_vcpu, arch.hpfar));
   DEFINE(VCPU_HYP_PC,		offsetof(struct kvm_vcpu, arch.hyp_pc));
+#ifdef CONFIG_KVM_ARM_VGIC
+  DEFINE(VCPU_VGIC_CPU,		offsetof(struct kvm_vcpu, arch.vgic_cpu));
+  DEFINE(VGIC_CPU_HCR,		offsetof(struct vgic_cpu, vgic_hcr));
+  DEFINE(VGIC_CPU_VMCR,		offsetof(struct vgic_cpu, vgic_vmcr));
+  DEFINE(VGIC_CPU_MISR,		offsetof(struct vgic_cpu, vgic_misr));
+  DEFINE(VGIC_CPU_EISR,		offsetof(struct vgic_cpu, vgic_eisr));
+  DEFINE(VGIC_CPU_ELRSR,	offsetof(struct vgic_cpu, vgic_elrsr));
+  DEFINE(VGIC_CPU_APR,		offsetof(struct vgic_cpu, vgic_apr));
+  DEFINE(VGIC_CPU_LR,		offsetof(struct vgic_cpu, vgic_lr));
+  DEFINE(VGIC_CPU_NR_LR,	offsetof(struct vgic_cpu, nr_lr));
+  DEFINE(KVM_VGIC_VCTRL,	offsetof(struct kvm, arch.vgic.vctrl_base));
+#endif
   DEFINE(KVM_VTTBR,		offsetof(struct kvm, arch.vttbr));
 #endif
   return 0; 
arch/arm/kvm/interrupts_head.S +68 -0

80 lines not on this page · raw message

#8 lore raw

PATCH v2 8/10 ARM: KVM: VGIC initialisation code

In reply to Christoffer Dall

From: Marc Zyngier <[email protected]>

Add the init code for the hypervisor, the virtual machine, and the virtual CPUs.

An interrupt handler is also wired to allow the VGIC maintenance interrupts, used to deal with level triggered interrupts and LR underflows.

---
 arch/arm/include/asm/kvm_vgic.h |    3 +
 arch/arm/kvm/arm.c              |    8 +-
 arch/arm/kvm/vgic.c             |  199 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 208 insertions(+), 2 deletions(-)
arch/arm/include/asm/kvm_vgic.h +3 -0
index 9740f1f..c8327f3 100644
@@ -238,6 +238,9 @@ struct kvm_run;
 struct kvm_exit_mmio;
 
 #ifdef CONFIG_KVM_ARM_VGIC
+int kvm_vgic_hyp_init(void);
+int kvm_vgic_init(struct kvm *kvm);
+void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu);
 void kvm_vgic_sync_to_cpu(struct kvm_vcpu *vcpu);
 void kvm_vgic_sync_from_cpu(struct kvm_vcpu *vcpu);
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
arch/arm/kvm/arm.c +6 -2
index be593220..f88fd18 100644
@@ -61,6 +61,8 @@ static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);
 static u8 kvm_next_vmid;
 static DEFINE_SPINLOCK(kvm_vmid_lock);
 
+static bool vgic_present;
+
 static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu)
 {
 	BUG_ON(preemptible());
@@ -185,6 +187,8 @@ int kvm_dev_ioctl_check_extension(long ext)
 	switch (ext) {
 #ifdef CONFIG_KVM_ARM_VGIC
 	case KVM_CAP_IRQCHIP:
+		r = vgic_present;
+		break;
 #endif
 	case KVM_CAP_USER_MEMORY:
 	case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
@@ -992,8 +996,8 @@ static int init_hyp_mode(void)
 	 * Init HYP view of VGIC
 	 */
 	err = kvm_vgic_hyp_init();
-	if (err)
-		goto out_free_mappings;
+	if (!err)
+		vgic_present = true;
 
 	return 0;
 out_free_vfp:
arch/arm/kvm/vgic.c +199 -0

215 lines not on this page · raw message

#9 lore raw

Re: [PATCH v2 08/10] ARM: KVM: VGIC initialisation code

Quoted 12 lines · Christoffer Dall

From: Marc Zyngier <[email protected]>

Add the init code for the hypervisor, the virtual machine, and the virtual CPUs.

An interrupt handler is also wired to allow the VGIC maintenance interrupts, used to deal with level triggered interrupts and LR underflows.

---

[...]

Quoted 20 lines
arch/arm/kvm/vgic.c +7 -0
index b52d4c2..fc2a138 100644
@@ -20,7 +20,14 @@
 #include <linux/kvm_host.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
 #include <asm/kvm_emulate.h>
+#include <asm/hardware/gic.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_mmu.h>
 
 /*
  * How the whole thing works (courtesy of Christoffer Dall):

arch/arm/kvm/vgic.c line 72

Quoted 5 lines
arch/arm/kvm/vgic.c +2 -0
@@ -61,6 +68,13 @@
 /* Temporary hacks, need to be provided by userspace emulation */
 #define VGIC_DIST_BASE		0x2c001000
 #define VGIC_DIST_SIZE		0x1000
+#define VGIC_CPU_BASE		0x2c002000
+#define VGIC_CPU_SIZE		0x2000

We really don't want the physical memory map for the guest hardwired in the kernel. Please find a way to parameterise this from userspace.

Will

#10 lore raw

Re: [PATCH v2 08/10] ARM: KVM: VGIC initialisation code

Quoted 33 lines · Will Deacon
Quoted 12 lines · Christoffer Dall

From: Marc Zyngier <[email protected]>

Add the init code for the hypervisor, the virtual machine, and the virtual CPUs.

An interrupt handler is also wired to allow the VGIC maintenance interrupts, used to deal with level triggered interrupts and LR underflows.

---

[...]

Quoted 17 lines
arch/arm/kvm/vgic.c +7 -0
index b52d4c2..fc2a138 100644
@@ -20,7 +20,14 @@
 #include <linux/kvm_host.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
 #include <asm/kvm_emulate.h>
+#include <asm/hardware/gic.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_mmu.h>
 
Quoted 10 lines

arch/arm/kvm/vgic.c line 72

Quoted 8 lines
arch/arm/kvm/vgic.c +2 -0
 /*
  * How the whole thing works (courtesy of Christoffer Dall):
@@ -61,6 +68,13 @@
 /* Temporary hacks, need to be provided by userspace emulation */
 #define VGIC_DIST_BASE		0x2c001000
 #define VGIC_DIST_SIZE		0x1000
+#define VGIC_CPU_BASE		0x2c002000
+#define VGIC_CPU_SIZE		0x2000

We really don't want the physical memory map for the guest hardwired in

the

Quoted 1 line

kernel. Please find a way to parameterise this from userspace.

Yes, this is a known problem. KVM doesn't offer a standard way of passing the address of an interrupt controller (none of the other architectures have it memory mapped).

We probably need a separate ioctl for that...

        M.
Signature · 1 line
Fast, cheap, reliable. Pick two.
#11 lore raw

Re: [PATCH v2 08/10] ARM: KVM: VGIC initialisation code

Quoted 45 lines · Marc Zyngier
Quoted 33 lines · Will Deacon
Quoted 12 lines · Christoffer Dall

From: Marc Zyngier <[email protected]>

Add the init code for the hypervisor, the virtual machine, and the virtual CPUs.

An interrupt handler is also wired to allow the VGIC maintenance interrupts, used to deal with level triggered interrupts and LR underflows.

---

[...]

Quoted 17 lines
arch/arm/kvm/vgic.c +7 -0
index b52d4c2..fc2a138 100644
@@ -20,7 +20,14 @@
 #include <linux/kvm_host.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
 #include <asm/kvm_emulate.h>
+#include <asm/hardware/gic.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_mmu.h>
 
Quoted 10 lines

arch/arm/kvm/vgic.c line 72

Quoted 8 lines
arch/arm/kvm/vgic.c +2 -0
 /*
 * How the whole thing works (courtesy of Christoffer Dall):
@@ -61,6 +68,13 @@
 /* Temporary hacks, need to be provided by userspace emulation */
 #define VGIC_DIST_BASE        0x2c001000
 #define VGIC_DIST_SIZE        0x1000
+#define VGIC_CPU_BASE        0x2c002000
+#define VGIC_CPU_SIZE        0x2000

We really don't want the physical memory map for the guest hardwired in

Quoted 8 lines

the

Quoted 1 line

kernel. Please find a way to parameterise this from userspace.

Yes, this is a known problem. KVM doesn't offer a standard way of passing the address of an interrupt controller (none of the other architectures have it memory mapped).

We probably need a separate ioctl

Thoughts on how to make this API flexible enough?

Can we somehow provide a device tree to the host kernel, which would be the same device tree the guest uses, which may also describe virtio features, or is this completely sci fi?

-Christoffer

#12 lore raw

Re: [kvmarm] [PATCH v2 08/10] ARM: KVM: VGIC initialisation code

Quoted 10 lines · Christoffer Dall
Quoted 9 lines · Marc Zyngier

On Tue, 2 Oct 2012 10:24:13 +0100, Will Deacon <[email protected]>

Quoted 1 line

We really don't want the physical memory map for the guest hardwired in

the

Quoted 1 line

kernel. Please find a way to parameterise this from userspace.

Yes, this is a known problem. KVM doesn't offer a standard way of passing the address of an interrupt controller (none of the other architectures have it memory mapped).

Quoted 7 lines
Quoted 1 line

We probably need a separate ioctl

Thoughts on how to make this API flexible enough?

Can we somehow provide a device tree to the host kernel, which would be the same device tree the guest uses, which may also describe virtio features, or is this completely sci fi?

I'm not really in favour of trying to shoehorn device trees in here (among other things, the virtual machine we create should be the actual machine matching the hardware, not something randomly generated from the device tree. Also requiring userspace to manufacture a device tree from scratch is kind of awkward: there's no reason the guest has to be using one, and it's a lot of effort to go to to pass a single address into the kernel...)

We probably want to be passing in the "base of the cpu-internal peripherals", rather than "base of the GIC" specifically. For the A15 these are the same thing, but that's not inherent [compare the A9 which has more devices at fixed offsets from a configurable base address].

On hardware this is done by having an input signal that's sampled at reset that tells the CPU where the peripherals are; is there an equivalent of that for any other CPU properties that we have already in the KVM API?

-- PMM

#13 lore raw

Re: [kvmarm] [PATCH v2 08/10] ARM: KVM: VGIC initialisation code

Quoted 5 lines · Peter Maydell

We probably want to be passing in the "base of the cpu-internal peripherals", rather than "base of the GIC" specifically. For the A15 these are the same thing, but that's not inherent [compare the A9 which has more devices at fixed offsets from a configurable base address].

If you do that, userspace will need a way to probe the emulated CPU so that is knows exactly which set of peripherals there are and which ones it needs to emulate. This feels pretty nasty, given that the vgic is handled more or less completely by the kernel-side of things.

Will

#14 lore raw

Re: [kvmarm] [PATCH v2 08/10] ARM: KVM: VGIC initialisation code

Quoted 11 lines · Will Deacon
Quoted 5 lines · Peter Maydell

We probably want to be passing in the "base of the cpu-internal peripherals", rather than "base of the GIC" specifically. For the A15 these are the same thing, but that's not inherent [compare the A9 which has more devices at fixed offsets from a configurable base address].

If you do that, userspace will need a way to probe the emulated CPU so that is knows exactly which set of peripherals there are and which ones it needs to emulate. This feels pretty nasty, given that the vgic is handled more or less completely by the kernel-side of things.

Userspace knows what the emulated CPU is because it tells the kernel which CPU to provide -- the kernel can say "yes" or "no" but it can't provide a different CPU to the one we ask for, or one with bits mising...

-- PMM

#15 lore raw

Re: [kvmarm] [PATCH v2 08/10] ARM: KVM: VGIC initialisation code

Quoted 13 lines · Peter Maydell
Quoted 11 lines · Will Deacon
Quoted 5 lines · Peter Maydell

We probably want to be passing in the "base of the cpu-internal peripherals", rather than "base of the GIC" specifically. For the A15 these are the same thing, but that's not inherent [compare the A9 which has more devices at fixed offsets from a configurable base address].

If you do that, userspace will need a way to probe the emulated CPU so that is knows exactly which set of peripherals there are and which ones it needs to emulate. This feels pretty nasty, given that the vgic is handled more or less completely by the kernel-side of things.

Quoted 4 lines

Userspace knows what the emulated CPU is because it tells the kernel which CPU to provide -- the kernel can say "yes" or "no" but it can't provide a different CPU to the one we ask for, or one with bits mising...

Aha, ok, I didn't realise that's how it works. Does userspace just pass the CPUID or is there an identifier provided by kvm?

/me jumps back into the code.

Thanks,

Will

#16 lore raw

Re: [kvmarm] [PATCH v2 08/10] ARM: KVM: VGIC initialisation code

Quoted 19 lines · Will Deacon
Quoted 13 lines · Peter Maydell
Quoted 11 lines · Will Deacon
Quoted 5 lines · Peter Maydell

We probably want to be passing in the "base of the cpu-internal peripherals", rather than "base of the GIC" specifically. For the A15 these are the same thing, but that's not inherent [compare the A9 which has more devices at fixed offsets from a configurable base address].

If you do that, userspace will need a way to probe the emulated CPU so that is knows exactly which set of peripherals there are and which ones it needs to emulate. This feels pretty nasty, given that the vgic is handled more or less completely by the kernel-side of things.

Quoted 4 lines

Userspace knows what the emulated CPU is because it tells the kernel which CPU to provide -- the kernel can say "yes" or "no" but it can't provide a different CPU to the one we ask for, or one with bits mising...

Quoted 5 lines

Aha, ok, I didn't realise that's how it works. Does userspace just pass the CPUID or is there an identifier provided by kvm?

/me jumps back into the code.

Userspace provides an identifier (0 for Cortex-A15). This changed in the last patch series, so as to only have one (public and internal) identifier used to index into the array of core-specific coprocessor handlings.

#17 lore raw

PATCH v2 9/10 ARM: KVM: vgic: reduce the number of vcpu kick

In reply to Christoffer Dall

From: Marc Zyngier <[email protected]>

If we have level interrupts already programmed to fire on a vcpu, there is no reason to kick it after injecting a new interrupt, as we're guaranteed that we'll exit when the level interrupt will be EOId (VGIC_LR_EOI is set).

The exit will force a reload of the VGIC, injecting the new interrupts.

---
 arch/arm/include/asm/kvm_vgic.h |   10 ++++++++++
 arch/arm/kvm/arm.c              |   10 +++++++++-
 arch/arm/kvm/vgic.c             |   10 ++++++++--
 3 files changed, 27 insertions(+), 3 deletions(-)
arch/arm/include/asm/kvm_vgic.h +10 -0
index c8327f3..588c637 100644
@@ -214,6 +214,9 @@ struct vgic_cpu {
 	u32		vgic_elrsr[2];	/* Saved only */
 	u32		vgic_apr;
 	u32		vgic_lr[64];	/* A15 has only 4... */
+
+	/* Number of level-triggered interrupt in progress */
+	atomic_t	irq_active_count;
 #endif
 };
 
@@ -250,6 +253,8 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		      struct kvm_exit_mmio *mmio);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.vctrl_base))
+#define vgic_active_irq(v)	(atomic_read(&(v)->arch.vgic_cpu.irq_active_count) == 0)
+
 #else
 static inline int kvm_vgic_hyp_init(void)
 {
@@ -286,6 +291,11 @@ static inline int irqchip_in_kernel(struct kvm *kvm)
 {
 	return 0;
 }
+
+static inline int vgic_active_irq(struct kvm_vcpu *vcpu)
+{
+	return 0;
+}
 #endif
 
 #endif
arch/arm/kvm/arm.c +9 -1
index f88fd18..b03e604 100644
@@ -94,7 +94,15 @@ int kvm_arch_hardware_enable(void *garbage)
 
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
 {
-	return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
+	if (kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE) {
+		if (vgic_active_irq(vcpu) &&
+		    cmpxchg(&vcpu->mode, EXITING_GUEST_MODE, IN_GUEST_MODE) == EXITING_GUEST_MODE)
+			return 0;
+
+		return 1;
+	}
+
+	return 0;
 }
 
 void kvm_arch_hardware_disable(void *garbage)
arch/arm/kvm/vgic.c +8 -2
index fc2a138..63fe0dd 100644
@@ -674,8 +674,10 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
 		kvm_debug("LR%d piggyback for IRQ%d %x\n", lr, irq, vgic_cpu->vgic_lr[lr]);
 		BUG_ON(!test_bit(lr, vgic_cpu->lr_used));
 		vgic_cpu->vgic_lr[lr] |= VGIC_LR_PENDING_BIT;
-		if (is_level)
+		if (is_level) {
 			vgic_cpu->vgic_lr[lr] |= VGIC_LR_EOI;
+			atomic_inc(&vgic_cpu->irq_active_count);
+		}
 		return true;
 	}
 
@@ -687,8 +689,10 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
 
 	kvm_debug("LR%d allocated for IRQ%d %x\n", lr, irq, sgi_source_id);
 	vgic_cpu->vgic_lr[lr] = MK_LR_PEND(sgi_source_id, irq);
-	if (is_level)
+	if (is_level) {
 		vgic_cpu->vgic_lr[lr] |= VGIC_LR_EOI;
+		atomic_inc(&vgic_cpu->irq_active_count);
+	}
 
 	vgic_cpu->vgic_irq_lr_map[irq] = lr;
 	clear_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr);
@@ -963,6 +967,8 @@ static irqreturn_t vgic_maintenance_handler(int irq, void *data)
 
 			vgic_bitmap_set_irq_val(&dist->irq_active,
 						vcpu->vcpu_id, irq, 0);
+			atomic_dec(&vgic_cpu->irq_active_count);
+			smp_mb();
 			vgic_cpu->vgic_lr[lr] &= ~VGIC_LR_EOI;
 			writel_relaxed(vgic_cpu->vgic_lr[lr],
 				       dist->vctrl_base + GICH_LR0 + (lr << 2));
#18 lore raw

PATCH v2 10/10 ARM: KVM: Add VGIC configuration option

In reply to Christoffer Dall

From: Marc Zyngier <[email protected]>

It is now possible to select the VGIC configuration option.

---
 arch/arm/kvm/Kconfig |    7 +++++++
 1 file changed, 7 insertions(+)
arch/arm/kvm/Kconfig +7 -0
index 47c5500..867551e 100644
@@ -40,6 +40,13 @@ config KVM_ARM_HOST
 	---help---
 	  Provides host support for ARM processors.
 
+config KVM_ARM_VGIC
+        bool "KVM support for Virtual GIC"
+	depends on KVM_ARM_HOST && OF
+	select HAVE_KVM_IRQCHIP
+	---help---
+	  Adds support for a hardware assisted, in-kernel GIC emulation.
+
 source drivers/virtio/Kconfig
 
 endif # VIRTUALIZATION