1/*
2 * Copyright (c) 2015-2017 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Andreas Sandberg
38 *          Curtis Dunham
39 */
40
41#ifndef __ARCH_ARM_KVM_GIC_HH__
42#define __ARCH_ARM_KVM_GIC_HH__
43
44#include "arch/arm/system.hh"
45#include "cpu/kvm/device.hh"
46#include "cpu/kvm/vm.hh"
47#include "dev/arm/gic_v2.hh"
48#include "dev/platform.hh"
49
50/**
51 * KVM in-kernel GIC abstraction
52 *
53 * This class defines a high-level interface to the KVM in-kernel GIC
54 * model. It exposes an API that is similar to that of
55 * software-emulated GIC models in gem5.
56 */
57class KvmKernelGicV2 : public BaseGicRegisters
58{
59  public:
60    /**
61     * Instantiate a KVM in-kernel GIC model.
62     *
63     * This constructor instantiates an in-kernel GIC model and wires
64     * it up to the virtual memory system.
65     *
66     * @param vm KVM VM representing this system
67     * @param cpu_addr GIC CPU interface base address
68     * @param dist_addr GIC distributor base address
69     * @param it_lines Number of interrupt lines to support
70     */
71    KvmKernelGicV2(KvmVM &vm, Addr cpu_addr, Addr dist_addr,
72                   unsigned it_lines);
73    virtual ~KvmKernelGicV2();
74
75    KvmKernelGicV2(const KvmKernelGicV2 &other) = delete;
76    KvmKernelGicV2(const KvmKernelGicV2 &&other) = delete;
77    KvmKernelGicV2 &operator=(const KvmKernelGicV2 &&rhs) = delete;
78    KvmKernelGicV2 &operator=(const KvmKernelGicV2 &rhs) = delete;
79
80  public:
81    /**
82     * @{
83     * @name In-kernel GIC API
84     */
85
86    /**
87     * Raise a shared peripheral interrupt
88     *
89     * @param spi SPI number
90     */
91    void setSPI(unsigned spi);
92    /**
93     * Clear a shared peripheral interrupt
94     *
95     * @param spi SPI number
96     */
97    void clearSPI(unsigned spi);
98
99    /**
100     * Raise a private peripheral interrupt
101     *
102     * @param vcpu KVM virtual CPU number
103     * @parma ppi PPI interrupt number
104     */
105    void setPPI(unsigned vcpu, unsigned ppi);
106
107    /**
108     * Clear a private peripheral interrupt
109     *
110     * @param vcpu KVM virtual CPU number
111     * @parma ppi PPI interrupt number
112     */
113    void clearPPI(unsigned vcpu, unsigned ppi);
114
115    /** Address range for the CPU interfaces */
116    const AddrRange cpuRange;
117    /** Address range for the distributor interface */
118    const AddrRange distRange;
119
120    /** BaseGicRegisters interface */
121    uint32_t readDistributor(ContextID ctx, Addr daddr) override;
122    uint32_t readCpu(ContextID ctx, Addr daddr) override;
123
124    void writeDistributor(ContextID ctx, Addr daddr,
125                          uint32_t data) override;
126    void writeCpu(ContextID ctx, Addr daddr, uint32_t data) override;
127
128    /* @} */
129
130  protected:
131    /**
132     * Update the kernel's VGIC interrupt state
133     *
134     * @param type Interrupt type (KVM_ARM_IRQ_TYPE_PPI/KVM_ARM_IRQ_TYPE_SPI)
135     * @param vcpu CPU id within KVM (ignored for SPIs)
136     * @param irq Interrupt number
137     * @param high True to signal an interrupt, false to clear it.
138     */
139    void setIntState(unsigned type, unsigned vcpu, unsigned irq, bool high);
140
141    /**
142     * Get value of GIC register "from" a cpu
143     *
144     * @param group Distributor or CPU (KVM_DEV_ARM_VGIC_GRP_{DIST,CPU}_REGS)
145     * @param vcpu CPU id within KVM
146     * @param offset register offset
147     */
148    uint32_t getGicReg(unsigned group, unsigned vcpu, unsigned offset);
149
150    /**
151     * Set value of GIC register "from" a cpu
152     *
153     * @param group Distributor or CPU (KVM_DEV_ARM_VGIC_GRP_{DIST,CPU}_REGS)
154     * @param vcpu CPU id within KVM
155     * @param offset register offset
156     * @param value value to set register to
157     */
158    void setGicReg(unsigned group, unsigned vcpu, unsigned offset,
159                   unsigned value);
160
161    /** KVM VM in the parent system */
162    KvmVM &vm;
163
164    /** Kernel interface to the GIC */
165    KvmDevice kdev;
166};
167
168
169struct MuxingKvmGicParams;
170
171class MuxingKvmGic : public GicV2
172{
173  public: // SimObject / Serializable / Drainable
174    MuxingKvmGic(const MuxingKvmGicParams *p);
175    ~MuxingKvmGic();
176
177    void startup() override;
178    DrainState drain() override;
179    void drainResume() override;
180
181  public: // PioDevice
182    Tick read(PacketPtr pkt) override;
183    Tick write(PacketPtr pkt) override;
184
185  public: // GicV2
186    void sendInt(uint32_t num) override;
187    void clearInt(uint32_t num) override;
188
189    void sendPPInt(uint32_t num, uint32_t cpu) override;
190    void clearPPInt(uint32_t num, uint32_t cpu) override;
191
192  protected: // GicV2
193    void updateIntState(int hint) override;
194
195  protected:
196    /** System this interrupt controller belongs to */
197    System &system;
198
199    /** Kernel GIC device */
200    KvmKernelGicV2 *kernelGic;
201
202  private:
203    bool usingKvm;
204
205    /** Multiplexing implementation */
206    void fromGicV2ToKvm();
207    void fromKvmToGicV2();
208
209    void copyGicState(BaseGicRegisters* from, BaseGicRegisters* to);
210
211    void copyDistRegister(BaseGicRegisters* from, BaseGicRegisters* to,
212                          ContextID ctx, Addr daddr);
213    void copyCpuRegister(BaseGicRegisters* from, BaseGicRegisters* to,
214                         ContextID ctx, Addr daddr);
215
216    void copyBankedDistRange(BaseGicRegisters* from, BaseGicRegisters* to,
217                             Addr daddr, size_t size);
218    void clearBankedDistRange(BaseGicRegisters* to,
219                              Addr daddr, size_t size);
220    void copyDistRange(BaseGicRegisters* from, BaseGicRegisters* to,
221                       Addr daddr, size_t size);
222    void clearDistRange(BaseGicRegisters* to,
223                        Addr daddr, size_t size);
224};
225
226#endif // __ARCH_ARM_KVM_GIC_HH__
227