44#include "debug/GIC.hh"
45#include "debug/Interrupt.hh"
46#include "params/MuxingKvmGicV2.hh"
57 vm.enableKernelIRQChip();
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;
97 static const bool vcpu2_enabled =
vm.kvm->capIRQLineLayout2();
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));
115 vm.setIRQLine(line, high);
119 const MuxingKvmGicV2Params &
p)
124 kdev.setAttr<uint64_t>(
125 KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V2_ADDR_TYPE_DIST,
p.dist_addr);
126 kdev.setAttr<uint64_t>(
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));
161 auto vcpu =
vm.contextIdToVCpuId(ctx);
162 return getGicReg(KVM_DEV_ARM_VGIC_GRP_DIST_REGS, vcpu, daddr);
168 auto vcpu =
vm.contextIdToVCpuId(ctx);
169 return getGicReg(KVM_DEV_ARM_VGIC_GRP_CPU_REGS, vcpu, daddr);
175 auto vcpu =
vm.contextIdToVCpuId(ctx);
176 setGicReg(KVM_DEV_ARM_VGIC_GRP_DIST_REGS, vcpu, daddr,
data);
182 auto vcpu =
vm.contextIdToVCpuId(ctx);
187#define SZ_64K 0x00000040
191 const MuxingKvmGicV3Params &
p)
196 kdev.setAttr<uint64_t>(
197 KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V3_ADDR_TYPE_DIST,
p.dist_addr);
198 kdev.setAttr<uint64_t>(
199 KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V3_ADDR_TYPE_REDIST,
p.redist_addr);
205 kdev.setAttr<uint64_t>(
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) {
296 kernelGic = new KvmGic(*vm, p);
300template <
class Types>
310 if (
vm &&
vm->validEnvironment()) {
317template <
class Types>
323 return SimGic::drain();
326template <
class Types>
330 SimGic::drainResume();
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);
375template <
class Types>
380 return SimGic::clearInt(num);
386template <
class Types>
391 return SimGic::sendPPInt(num, cpu);
396template <
class Types>
401 return SimGic::clearPPInt(num, cpu);
407template <
class Types>
418template <
class Types>
422 this->copyGicState(
static_cast<SimGic*
>(
this),
426template <
class Types>
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);
uint32_t readCpu(ContextID ctx, Addr daddr) override
const AddrRange distRange
Address range for the distributor.
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.
const AddrRange cpuRange
Address range for the CPU interfaces.
void writeDistributor(ContextID ctx, Addr daddr, uint32_t data) override
KvmKernelGicV2(KvmVM &vm, const MuxingKvmGicV2Params ¶ms)
Instantiate a KVM in-kernel GICv2 model.
const AddrRange distRange
Address range for the distributor.
RegVal readCpu(const ArmISA::Affinity &aff, ArmISA::MiscRegIndex misc_reg) override
void writeRedistributor(const ArmISA::Affinity &aff, Addr daddr, uint32_t data) override
const AddrRange redistRange
Address range for the redistributor.
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.
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.
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
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 Arm Limited 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.