kvm-$(CONFIG_KVM_ARM_HOST) += vgic-v2-switch.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3-emul.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/its-emul.o
kvm-$(CONFIG_KVM_ARM_HOST) += vgic-v3-switch.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
struct kvm_io_device dev;
};
+struct vgic_its {
+ bool enabled;
+ spinlock_t lock;
+};
+
struct vgic_dist {
spinlock_t lock;
bool in_kernel;
u64 *pendbaser;
bool lpis_enabled;
+ struct vgic_its its;
};
struct vgic_v2_cpu_if {
#define GITS_CWRITER 0x0088
#define GITS_CREADR 0x0090
#define GITS_BASER 0x0100
+#define GITS_IDREGS_BASE 0xffd0
#define GITS_PIDR2 GICR_PIDR2
#define GITS_TRANSLATER 0x10040
--- /dev/null
+/*
+ * GICv3 ITS emulation
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ * Author: Andre Przywara <andre.przywara@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/cpu.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/interrupt.h>
+
+#include <linux/irqchip/arm-gic-v3.h>
+#include <kvm/arm_vgic.h>
+
+#include <asm/kvm_emulate.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_mmu.h>
+
+#include "vgic.h"
+#include "its-emul.h"
+
+static bool handle_mmio_misc_gits(struct kvm_vcpu *vcpu,
+ struct kvm_exit_mmio *mmio,
+ phys_addr_t offset)
+{
+ return false;
+}
+
+static bool handle_mmio_gits_idregs(struct kvm_vcpu *vcpu,
+ struct kvm_exit_mmio *mmio,
+ phys_addr_t offset)
+{
+ return false;
+}
+
+static bool handle_mmio_gits_cbaser(struct kvm_vcpu *vcpu,
+ struct kvm_exit_mmio *mmio,
+ phys_addr_t offset)
+{
+ return false;
+}
+
+static bool handle_mmio_gits_cwriter(struct kvm_vcpu *vcpu,
+ struct kvm_exit_mmio *mmio,
+ phys_addr_t offset)
+{
+ return false;
+}
+
+static bool handle_mmio_gits_creadr(struct kvm_vcpu *vcpu,
+ struct kvm_exit_mmio *mmio,
+ phys_addr_t offset)
+{
+ return false;
+}
+
+static const struct vgic_io_range vgicv3_its_ranges[] = {
+ {
+ .base = GITS_CTLR,
+ .len = 0x10,
+ .bits_per_irq = 0,
+ .handle_mmio = handle_mmio_misc_gits,
+ },
+ {
+ .base = GITS_CBASER,
+ .len = 0x08,
+ .bits_per_irq = 0,
+ .handle_mmio = handle_mmio_gits_cbaser,
+ },
+ {
+ .base = GITS_CWRITER,
+ .len = 0x08,
+ .bits_per_irq = 0,
+ .handle_mmio = handle_mmio_gits_cwriter,
+ },
+ {
+ .base = GITS_CREADR,
+ .len = 0x08,
+ .bits_per_irq = 0,
+ .handle_mmio = handle_mmio_gits_creadr,
+ },
+ {
+ /* We don't need any memory from the guest. */
+ .base = GITS_BASER,
+ .len = 0x40,
+ .bits_per_irq = 0,
+ .handle_mmio = handle_mmio_raz_wi,
+ },
+ {
+ .base = GITS_IDREGS_BASE,
+ .len = 0x30,
+ .bits_per_irq = 0,
+ .handle_mmio = handle_mmio_gits_idregs,
+ },
+};
+
+/* This is called on setting the LPI enable bit in the redistributor. */
+void vgic_enable_lpis(struct kvm_vcpu *vcpu)
+{
+}
+
+int vits_init(struct kvm *kvm)
+{
+ struct vgic_dist *dist = &kvm->arch.vgic;
+ struct vgic_its *its = &dist->its;
+
+ spin_lock_init(&its->lock);
+
+ its->enabled = false;
+
+ return -ENXIO;
+}
--- /dev/null
+/*
+ * GICv3 ITS emulation definitions
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ * Author: Andre Przywara <andre.przywara@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __KVM_ITS_EMUL_H__
+#define __KVM_ITS_EMUL_H__
+
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+#include <asm/kvm_emulate.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_mmu.h>
+
+#include "vgic.h"
+
+void vgic_enable_lpis(struct kvm_vcpu *vcpu);
+int vits_init(struct kvm *kvm);
+
+#endif
#include <asm/kvm_mmu.h>
#include "vgic.h"
+#include "its-emul.h"
static bool handle_mmio_rao_wi(struct kvm_vcpu *vcpu,
struct kvm_exit_mmio *mmio, phys_addr_t offset)
struct kvm_exit_mmio *mmio,
phys_addr_t offset)
{
- /* since we don't support LPIs, this register is zero for now */
- vgic_reg_access(mmio, NULL, offset,
- ACCESS_READ_RAZ | ACCESS_WRITE_IGNORED);
+ struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+ u32 reg;
+
+ if (!vgic_has_its(vcpu->kvm)) {
+ vgic_reg_access(mmio, NULL, offset,
+ ACCESS_READ_RAZ | ACCESS_WRITE_IGNORED);
+ return false;
+ }
+ reg = dist->lpis_enabled ? GICR_CTLR_ENABLE_LPIS : 0;
+ vgic_reg_access(mmio, ®, offset,
+ ACCESS_READ_VALUE | ACCESS_WRITE_VALUE);
+ if (!dist->lpis_enabled && (reg & GICR_CTLR_ENABLE_LPIS)) {
+ /* Eventually do something */
+ }
return false;
}
rdbase += GIC_V3_REDIST_SIZE;
}
+ if (vgic_has_its(kvm)) {
+ ret = vits_init(kvm);
+ if (ret)
+ goto out_unregister;
+ }
+
dist->redist_iodevs = iodevs;
dist->ready = true;
goto out;