44#include "debug/GIC.hh"
45#include "debug/Interrupt.hh"
46#include "params/MuxingKvmGicV2.hh"
53 kdev(
vm.createDevice(dev))
59 kdev.
setAttr<uint32_t>(KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, it_lines);
87 setIntState(KVM_ARM_IRQ_TYPE_PPI, vcpu, ppi,
false);
94 const unsigned vcpu_index = vcpu & 0xff;
95 const unsigned vcpu2_index = (vcpu >> 8) & 0xff;
98 uint32_t kvm_vcpu = (vcpu_index << KVM_ARM_IRQ_VCPU_SHIFT);
100#if defined(KVM_ARM_IRQ_VCPU2_SHIFT)
102 kvm_vcpu |= vcpu2_index << KVM_ARM_IRQ_VCPU2_SHIFT;
105 panic_if((!vcpu2_enabled && vcpu2_index) || kvm_vcpu > 0xffff,
106 "VCPU out of range");
108 assert(
type <= KVM_ARM_IRQ_TYPE_MASK);
109 assert(
irq <= KVM_ARM_IRQ_NUM_MASK);
112 (
type << KVM_ARM_IRQ_TYPE_SHIFT) |
113 (
irq << KVM_ARM_IRQ_NUM_SHIFT));
119 const MuxingKvmGicV2Params &
p)
121 cpuRange(
RangeSize(
p.cpu_addr, KVM_VGIC_V2_CPU_SIZE)),
122 distRange(
RangeSize(
p.dist_addr, KVM_VGIC_V2_DIST_SIZE))
125 KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V2_ADDR_TYPE_DIST,
p.dist_addr);
127 KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V2_ADDR_TYPE_CPU,
p.cpu_addr);
135 assert(vcpu <= KVM_ARM_IRQ_VCPU_MASK);
137 ((uint64_t)vcpu << KVM_DEV_ARM_VGIC_CPUID_SHIFT) |
138 (
offset << KVM_DEV_ARM_VGIC_OFFSET_SHIFT));
141 return (uint32_t)
reg;
148 uint64_t
reg = value;
150 assert(vcpu <= KVM_ARM_IRQ_VCPU_MASK);
152 ((uint64_t)vcpu << KVM_DEV_ARM_VGIC_CPUID_SHIFT) |
153 (
offset << KVM_DEV_ARM_VGIC_OFFSET_SHIFT));
162 return getGicReg(KVM_DEV_ARM_VGIC_GRP_DIST_REGS, vcpu, daddr);
169 return getGicReg(KVM_DEV_ARM_VGIC_GRP_CPU_REGS, vcpu, daddr);
176 setGicReg(KVM_DEV_ARM_VGIC_GRP_DIST_REGS, vcpu, daddr,
data);
187#define SZ_64K 0x00000040
191 const MuxingKvmGicV3Params &
p)
193 redistRange(
RangeSize(
p.redist_addr, KVM_VGIC_V3_REDIST_SIZE)),
194 distRange(
RangeSize(
p.dist_addr, KVM_VGIC_V3_DIST_SIZE))
197 KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V3_ADDR_TYPE_DIST,
p.dist_addr);
199 KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V3_ADDR_TYPE_REDIST,
p.redist_addr);
206 KVM_DEV_ARM_VGIC_GRP_CTRL, KVM_DEV_ARM_VGIC_CTRL_INIT, 0);
209template <
typename Ret>
215 assert(mpidr <= KVM_DEV_ARM_VGIC_V3_MPIDR_MASK);
217 ((uint64_t)mpidr << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT) |
218 (
offset << KVM_DEV_ARM_VGIC_OFFSET_SHIFT));
224template <
typename Arg>
231 assert(mpidr <= KVM_DEV_ARM_VGIC_V3_MPIDR_MASK);
233 ((uint64_t)mpidr << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT) |
234 (
offset << KVM_DEV_ARM_VGIC_OFFSET_SHIFT));
255 std::optional<ArmISA::MiscRegNum64> sys_reg =
257 panic_if(!sys_reg.has_value(),
"Invalid system register");
259 sys_reg.value().packed());
280 std::optional<ArmISA::MiscRegNum64> sys_reg =
282 panic_if(!sys_reg.has_value(),
"Invalid system register");
284 sys_reg.value().packed(),
data);
287template <
class Types>
295 if (
vm && !
p.simulate_gic) {
300template <
class Types>
310 if (
vm &&
vm->validEnvironment()) {
317template <
class Types>
323 return SimGic::drain();
326template <
class Types>
330 SimGic::drainResume();
334 if (use_kvm != usingKvm) {
344template <
class Types>
349 return SimGic::read(pkt);
351 panic(
"MuxingKvmGic: PIO from gem5 is currently unsupported\n");
354template <
class Types>
359 return SimGic::write(pkt);
361 panic(
"MuxingKvmGic: PIO from gem5 is currently unsupported\n");
364template <
class Types>
369 return SimGic::sendInt(num);
372 kernelGic->setSPI(num);
375template <
class Types>
380 return SimGic::clearInt(num);
383 kernelGic->clearSPI(num);
386template <
class Types>
391 return SimGic::sendPPInt(num, cpu);
393 kernelGic->setPPI(cpu, num);
396template <
class Types>
401 return SimGic::clearPPInt(num, cpu);
404 kernelGic->clearPPI(cpu, num);
407template <
class Types>
418template <
class Types>
422 this->copyGicState(
static_cast<SimGic*
>(
this),
423 static_cast<KvmGic*
>(kernelGic));
426template <
class Types>
430 this->copyGicState(
static_cast<KvmGic*
>(kernelGic),
431 static_cast<SimGic*
>(
this));
437 if constexpr(std::is_same<SimGic, GicV2>::value) {
438 for (
int cpu = 0; cpu <
system.threads.size(); ++cpu) {
439 this->cpuPriority[cpu] <<= 3;
440 assert((this->cpuPriority[cpu] & ~0xff) == 0);
void getAttrPtr(uint32_t group, uint64_t attr, void *data) const
void setAttrPtr(uint32_t group, uint64_t attr, const void *data) const
void setAttr(uint32_t group, uint64_t attr, const T &data) const
Get the value of an attribute.
uint32_t readCpu(ContextID ctx, Addr daddr) override
void setGicReg(unsigned group, unsigned vcpu, unsigned offset, unsigned value)
Set value of GIC register "from" a cpu.
void writeCpu(ContextID ctx, Addr daddr, uint32_t data) override
uint32_t readDistributor(ContextID ctx, Addr daddr) override
uint32_t getGicReg(unsigned group, unsigned vcpu, unsigned offset)
Get value of GIC register "from" a cpu.
void writeDistributor(ContextID ctx, Addr daddr, uint32_t data) override
KvmKernelGicV2(KvmVM &vm, const MuxingKvmGicV2Params ¶ms)
Instantiate a KVM in-kernel GICv2 model.
RegVal readCpu(const ArmISA::Affinity &aff, ArmISA::MiscRegIndex misc_reg) override
void writeRedistributor(const ArmISA::Affinity &aff, Addr daddr, uint32_t data) override
void writeDistributor(Addr daddr, uint32_t data) override
Ret getGicReg(unsigned group, unsigned mpidr, unsigned offset)
Get value of GIC register "from" a cpu.
uint32_t readRedistributor(const ArmISA::Affinity &aff, Addr daddr) override
void writeCpu(const ArmISA::Affinity &aff, ArmISA::MiscRegIndex misc_reg, RegVal data) override
uint32_t readDistributor(Addr daddr) override
void setGicReg(unsigned group, unsigned mpidr, unsigned offset, Arg value)
Set value of GIC register "from" a cpu.
KvmKernelGicV3(KvmVM &vm, const MuxingKvmGicV3Params ¶ms)
Instantiate a KVM in-kernel GICv3 model.
KVM in-kernel GIC abstraction.
void setPPI(unsigned vcpu, unsigned ppi)
Raise a private peripheral interrupt.
void setSPI(unsigned spi)
Raise a shared peripheral interrupt.
KvmKernelGic(KvmVM &vm, uint32_t dev, unsigned it_lines)
Instantiate a KVM in-kernel GIC model.
void clearPPI(unsigned vcpu, unsigned ppi)
Clear a private peripheral interrupt.
KvmDevice kdev
Kernel interface to the GIC.
void setIntState(unsigned type, unsigned vcpu, unsigned irq, bool high)
Update the kernel's VGIC interrupt state.
void clearSPI(unsigned spi)
Clear a shared peripheral interrupt.
KvmVM & vm
KVM VM in the parent system.
long contextIdToVCpuId(ContextID ctx) const
Get the VCPUID for a given context.
bool validEnvironment() const
Verify gem5 configuration will support KVM emulation.
Kvm * kvm
Global KVM interface.
bool capIRQLineLayout2() const
Support for ARM IRQ line layout 2.
System & system
System this interrupt controller belongs to.
void sendInt(uint32_t num) override
Tick write(PacketPtr pkt) override
KvmKernelGic * kernelGic
Kernel GIC device.
MuxingKvmGic(const Params &p)
typename Types::KvmGic KvmGic
bool blockIntUpdate() const override
Tick read(PacketPtr pkt) override
DrainState drain() override
void clearInt(uint32_t num) override
void clearPPInt(uint32_t num, uint32_t cpu) override
void drainResume() override
typename Types::Params Params
typename Types::SimGic SimGic
void fromGicToKvm()
Multiplexing implementation.
void sendPPInt(uint32_t num, uint32_t cpu) override
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
KvmVM * getKvmVM() const
Get a pointer to the Kernel Virtual Machine (KVM) SimObject, if present.
void setIRQLine(uint32_t irq, bool high)
Set the status of an IRQ line using KVM_IRQ_LINE.
void enableKernelIRQChip()
Tell the VM and VCPUs to use an in-kernel IRQ chip for interrupt delivery.
AddrRange RangeSize(Addr start, Addr size)
DrainState
Object drain/handover states.
#define panic(...)
This implements a cprintf based panic() function.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
std::optional< MiscRegNum64 > encodeAArch64SysReg(MiscRegIndex misc_reg)
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
uint64_t Tick
Tick count type.
int ContextID
Globally unique thread context ID.