kvm, arm: Refactor KVM GIC device
authorAndreas Sandberg <andreas.sandberg@arm.com>
Wed, 27 Apr 2016 14:34:31 +0000 (15:34 +0100)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Wed, 27 Apr 2016 14:34:31 +0000 (15:34 +0100)
Factor out the kernel device wrapper from the KvmGIC and put it in a
separate class. This will simplify a future kernel/gem5 hybrid GIC.

Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Radhika Jagtap <radhika.jagtap@arm.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
src/arch/arm/kvm/gic.cc
src/arch/arm/kvm/gic.hh

index a0e0e789973730cc7042f8f3381cd6c273304954..bed13ec2c973ef550a7825513ce497344fdbe541 100644 (file)
@@ -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
 #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()
index f6360858b20f00157f52b8fd43069dc79acaff56..77a7b5e53029fcd476996408c481b53257261712 100644 (file)
@@ -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
 #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;
 };