summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm/kvm/gic.cc94
-rw-r--r--src/arch/arm/kvm/gic.hh115
2 files changed, 158 insertions, 51 deletions
diff --git a/src/arch/arm/kvm/gic.cc b/src/arch/arm/kvm/gic.cc
index a0e0e7899..bed13ec2c 100644
--- a/src/arch/arm/kvm/gic.cc
+++ b/src/arch/arm/kvm/gic.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 ARM Limited
+ * Copyright (c) 2015-2016 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -44,21 +44,69 @@
#include "debug/Interrupt.hh"
#include "params/KvmGic.hh"
+
+KvmKernelGicV2::KvmKernelGicV2(KvmVM &_vm, Addr cpu_addr, Addr dist_addr)
+ : cpuRange(RangeSize(cpu_addr, KVM_VGIC_V2_CPU_SIZE)),
+ distRange(RangeSize(dist_addr, KVM_VGIC_V2_DIST_SIZE)),
+ vm(_vm),
+ kdev(vm.createDevice(KVM_DEV_TYPE_ARM_VGIC_V2))
+{
+ kdev.setAttr<uint64_t>(
+ KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V2_ADDR_TYPE_DIST, dist_addr);
+ kdev.setAttr<uint64_t>(
+ KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V2_ADDR_TYPE_CPU, cpu_addr);
+}
+
+KvmKernelGicV2::~KvmKernelGicV2()
+{
+}
+
+void
+KvmKernelGicV2::setSPI(unsigned spi)
+{
+ setIntState(KVM_ARM_IRQ_TYPE_SPI, 0, spi, true);
+}
+
+void
+KvmKernelGicV2::clearSPI(unsigned spi)
+{
+ setIntState(KVM_ARM_IRQ_TYPE_SPI, 0, spi, false);
+}
+
+void
+KvmKernelGicV2::setPPI(unsigned vcpu, unsigned ppi)
+{
+ setIntState(KVM_ARM_IRQ_TYPE_PPI, vcpu, ppi, true);
+}
+
+void
+KvmKernelGicV2::clearPPI(unsigned vcpu, unsigned ppi)
+{
+ setIntState(KVM_ARM_IRQ_TYPE_PPI, vcpu, ppi, false);
+}
+
+void
+KvmKernelGicV2::setIntState(unsigned type, unsigned vcpu, unsigned irq,
+ bool high)
+{
+ assert(type <= KVM_ARM_IRQ_TYPE_MASK);
+ assert(vcpu <= KVM_ARM_IRQ_VCPU_MASK);
+ assert(irq <= KVM_ARM_IRQ_NUM_MASK);
+ const uint32_t line(
+ (type << KVM_ARM_IRQ_TYPE_SHIFT) |
+ (vcpu << KVM_ARM_IRQ_VCPU_SHIFT) |
+ (irq << KVM_ARM_IRQ_NUM_SHIFT));
+
+ vm.setIRQLine(line, high);
+}
+
+
KvmGic::KvmGic(const KvmGicParams *p)
: BaseGic(p),
system(*p->system),
- vm(*p->kvmVM),
- kdev(vm.createDevice(KVM_DEV_TYPE_ARM_VGIC_V2)),
- distRange(RangeSize(p->dist_addr, KVM_VGIC_V2_DIST_SIZE)),
- cpuRange(RangeSize(p->cpu_addr, KVM_VGIC_V2_CPU_SIZE)),
- addrRanges{distRange, cpuRange}
+ kernelGic(*p->kvmVM, p->cpu_addr, p->dist_addr),
+ addrRanges{kernelGic.distRange, kernelGic.cpuRange}
{
- kdev.setAttr<uint64_t>(
- KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V2_ADDR_TYPE_DIST,
- p->dist_addr);
- kdev.setAttr<uint64_t>(
- KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V2_ADDR_TYPE_CPU,
- p->cpu_addr);
}
KvmGic::~KvmGic()
@@ -93,28 +141,28 @@ void
KvmGic::sendInt(uint32_t num)
{
DPRINTF(Interrupt, "Set SPI %d\n", num);
- setIntState(KVM_ARM_IRQ_TYPE_SPI, 0, num, true);
+ kernelGic.setSPI(num);
}
void
KvmGic::clearInt(uint32_t num)
{
DPRINTF(Interrupt, "Clear SPI %d\n", num);
- setIntState(KVM_ARM_IRQ_TYPE_SPI, 0, num, false);
+ kernelGic.clearSPI(num);
}
void
KvmGic::sendPPInt(uint32_t num, uint32_t cpu)
{
DPRINTF(Interrupt, "Set PPI %d:%d\n", cpu, num);
- setIntState(KVM_ARM_IRQ_TYPE_PPI, cpu, num, true);
+ kernelGic.setPPI(cpu, num);
}
void
KvmGic::clearPPInt(uint32_t num, uint32_t cpu)
{
DPRINTF(Interrupt, "Clear PPI %d:%d\n", cpu, num);
- setIntState(KVM_ARM_IRQ_TYPE_PPI, cpu, num, false);
+ kernelGic.clearPPI(cpu, num);
}
void
@@ -126,20 +174,6 @@ KvmGic::verifyMemoryMode() const
}
}
-void
-KvmGic::setIntState(uint8_t type, uint8_t vcpu, uint16_t irq, bool high)
-{
- assert(type < KVM_ARM_IRQ_TYPE_MASK);
- assert(vcpu < KVM_ARM_IRQ_VCPU_MASK);
- assert(irq < KVM_ARM_IRQ_NUM_MASK);
- const uint32_t line(
- (type << KVM_ARM_IRQ_TYPE_SHIFT) |
- (vcpu << KVM_ARM_IRQ_VCPU_SHIFT) |
- (irq << KVM_ARM_IRQ_NUM_SHIFT));
-
- vm.setIRQLine(line, high);
-}
-
KvmGic *
KvmGicParams::create()
diff --git a/src/arch/arm/kvm/gic.hh b/src/arch/arm/kvm/gic.hh
index f6360858b..77a7b5e53 100644
--- a/src/arch/arm/kvm/gic.hh
+++ b/src/arch/arm/kvm/gic.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 ARM Limited
+ * Copyright (c) 2015-2016 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -46,7 +46,95 @@
#include "dev/arm/base_gic.hh"
#include "dev/platform.hh"
-class KvmGicParams;
+/**
+ * KVM in-kernel GIC abstraction
+ *
+ * This class defines a high-level interface to the KVM in-kernel GIC
+ * model. It exposes an API that is similar to that of
+ * software-emulated GIC models in gem5.
+ */
+class KvmKernelGicV2
+{
+ public:
+ /**
+ * Instantiate a KVM in-kernel GIC model.
+ *
+ * This constructor instantiates an in-kernel GIC model and wires
+ * it up to the virtual memory system.
+ *
+ * @param vm KVM VM representing this system
+ * @param cpu_addr GIC CPU interface base address
+ * @param dist_addr GIC distributor base address
+ */
+ KvmKernelGicV2(KvmVM &vm, Addr cpu_addr, Addr dist_addr);
+ virtual ~KvmKernelGicV2();
+
+ KvmKernelGicV2(const KvmKernelGicV2 &other) = delete;
+ KvmKernelGicV2(const KvmKernelGicV2 &&other) = delete;
+ KvmKernelGicV2 &operator=(const KvmKernelGicV2 &&rhs) = delete;
+ KvmKernelGicV2 &operator=(const KvmKernelGicV2 &rhs) = delete;
+
+ public:
+ /**
+ * @{
+ * @name In-kernel GIC API
+ */
+
+ /**
+ * Raise a shared peripheral interrupt
+ *
+ * @param spi SPI number
+ */
+ void setSPI(unsigned spi);
+ /**
+ * Clear a shared peripheral interrupt
+ *
+ * @param spi SPI number
+ */
+ void clearSPI(unsigned spi);
+
+ /**
+ * Raise a private peripheral interrupt
+ *
+ * @param vcpu KVM virtual CPU number
+ * @parma ppi PPI interrupt number
+ */
+ void setPPI(unsigned vcpu, unsigned ppi);
+
+ /**
+ * Clear a private peripheral interrupt
+ *
+ * @param vcpu KVM virtual CPU number
+ * @parma ppi PPI interrupt number
+ */
+ void clearPPI(unsigned vcpu, unsigned ppi);
+
+ /** Address range for the CPU interfaces */
+ const AddrRange cpuRange;
+ /** Address range for the distributor interface */
+ const AddrRange distRange;
+
+ /* @} */
+
+ protected:
+ /**
+ * Update the kernel's VGIC interrupt state
+ *
+ * @param type Interrupt type (KVM_ARM_IRQ_TYPE_PPI/KVM_ARM_IRQ_TYPE_SPI)
+ * @param vcpu CPU id within KVM (ignored for SPIs)
+ * @param irq Interrupt number
+ * @param high True to signal an interrupt, false to clear it.
+ */
+ void setIntState(unsigned type, unsigned vcpu, unsigned irq, bool high);
+
+ /** KVM VM in the parent system */
+ KvmVM &vm;
+
+ /** Kernel interface to the GIC */
+ KvmDevice kdev;
+};
+
+struct KvmGicParams;
/**
* In-kernel GIC model.
@@ -80,7 +168,7 @@ class KvmGic : public BaseGic
void drainResume() override { verifyMemoryMode(); }
void serialize(CheckpointOut &cp) const override;
- void unserialize(CheckpointIn &cp) override;
+ void unserialize(CheckpointIn &cp) override;
public: // PioDevice
AddrRangeList getAddrRanges() const { return addrRanges; }
@@ -105,27 +193,12 @@ class KvmGic : public BaseGic
*/
void verifyMemoryMode() const;
- /**
- * Update the kernel's VGIC interrupt state
- *
- * @param type Interrupt type (KVM_ARM_IRQ_TYPE_PPI/KVM_ARM_IRQ_TYPE_SPI)
- * @param vcpu CPU id within KVM (ignored for SPIs)
- * @param irq Interrupt number
- * @param high True to signal an interrupt, false to clear it.
- */
- void setIntState(uint8_t type, uint8_t vcpu, uint16_t irq, bool high);
-
/** System this interrupt controller belongs to */
System &system;
- /** VM for this system */
- KvmVM &vm;
- /** Kernel interface to the GIC */
- KvmDevice kdev;
- /** Address range for the distributor interface */
- const AddrRange distRange;
- /** Address range for the CPU interfaces */
- const AddrRange cpuRange;
+ /** Kernel GIC device */
+ KvmKernelGicV2 kernelGic;
+
/** Union of all memory */
const AddrRangeList addrRanges;
};