45#include "debug/KvmInt.hh"
47#include "params/BaseArmKvmCPU.hh"
48#include "params/GenericTimer.hh"
53using namespace ArmISA;
55#define INTERRUPT_ID(type, vcpu, irq) ( \
56 ((type) << KVM_ARM_IRQ_TYPE_SHIFT) | \
57 ((vcpu) << KVM_ARM_IRQ_VCPU_SHIFT) | \
58 ((irq) << KVM_ARM_IRQ_NUM_SHIFT))
60#define INTERRUPT_VCPU_IRQ(vcpu) \
61 INTERRUPT_ID(KVM_ARM_IRQ_TYPE_CPU, vcpu, KVM_ARM_IRQ_CPU_IRQ)
63#define INTERRUPT_VCPU_FIQ(vcpu) \
64 INTERRUPT_ID(KVM_ARM_IRQ_TYPE_CPU, vcpu, KVM_ARM_IRQ_CPU_FIQ)
77uint64_t vtime_counter = 0;
78UncontendedMutex vtime_mutex;
84 irqAsserted(false), fiqAsserted(false),
85 virtTimerPin(nullptr), prevDeviceIRQLevel(0)
102 struct kvm_vcpu_init target_config;
103 memset(&target_config, 0,
sizeof(target_config));
105 vm->kvmArmPreferredTarget(target_config);
107 target_config.features[0] |= (1 << KVM_ARM_VCPU_EL1_32BIT);
113 ->getGenericTimer()->
params().int_el1_virt->get(
tc);
120 const bool simFIQ(interrupt->checkRaw(
INT_FIQ));
121 const bool simIRQ(interrupt->checkRaw(
INT_IRQ));
125 DPRINTF(KvmInt,
"KVM: Update FIQ state: %i\n", simFIQ);
129 DPRINTF(KvmInt,
"KVM: Update IRQ state: %i\n", simIRQ);
134 "FIQ raised by the simulated interrupt controller " \
135 "despite in-kernel GIC emulation. This is probably a bug.");
138 "IRQ raised by the simulated interrupt controller " \
139 "despite in-kernel GIC emulation. This is probably a bug.");
148 uint64_t device_irq_level =
152 (device_irq_level & KVM_ARM_DEV_EL1_VTIMER)) {
154 DPRINTF(KvmInt,
"In-kernel vtimer IRQ asserted\n");
159 !(device_irq_level & KVM_ARM_DEV_EL1_VTIMER)) {
161 DPRINTF(KvmInt,
"In-kernel vtimer IRQ disasserted\n");
176 std::lock_guard<UncontendedMutex>
l(vtime_mutex);
177 if (vtime_counter++ == 0)
184 std::lock_guard<UncontendedMutex>
l(vtime_mutex);
185 if (--vtime_counter == 0)
186 getOneReg(KVM_REG_ARM_TIMER_CNT, &vtime);
198 kvm_reg_list regs_probe;
204 std::unique_ptr<kvm_reg_list, void(*)(
void *
p)>
205 regs(
nullptr, [](
void *
p) {
operator delete(
p); });
206 const size_t size(
sizeof(kvm_reg_list) +
207 regs_probe.n *
sizeof(uint64_t));
208 regs.reset((kvm_reg_list *)
operator new(size));
209 regs->n = regs_probe.n;
211 panic(
"Failed to determine register list size.\n");
222 if (
ioctl(KVM_ARM_VCPU_INIT, (
void *)&
init) == -1)
223 panic(
"KVM: Failed to initialize vCPU; errno %d (%s)\n",
224 errno, strerror(errno));
230 if (
ioctl(KVM_GET_REG_LIST, (
void *)®s) == -1) {
231 if (errno == E2BIG) {
234 panic(
"KVM: Failed to get vCPU register list (errno: %i)\n",
#define INTERRUPT_VCPU_IRQ(vcpu)
#define INTERRUPT_VCPU_FIQ(vcpu)
virtual void clear()=0
Clear a signalled interrupt.
virtual void raise()=0
Signal an interrupt.
Tick kvmRun(Tick ticks) override
Request KVM to run the guest for a given number of ticks.
void ioctlRun() override
Override for synchronizing state in kvm_run.
bool fiqAsserted
Cached state of the FIQ line.
bool irqAsserted
Cached state of the IRQ line.
const RegIndexVector & getRegList() const
Get a list of registers supported by getOneReg() and setOneReg().
void startup() override
startup() is the final initialization call before simulation.
uint64_t prevDeviceIRQLevel
KVM records whether each in-kernel device IRQ is asserted or disasserted in the kvmRunState->s....
BaseArmKvmCPU(const BaseArmKvmCPUParams ¶ms)
RegIndexVector _regIndexList
Cached copy of the list of registers supported by KVM.
ArmInterruptPin * virtTimerPin
If the user-space GIC and the kernel-space timer are used simultaneously, set up this interrupt pin t...
void kvmArmVCpuInit(const kvm_vcpu_init &init)
Tell the kernel to initialize this CPU.
std::vector< BaseInterrupts * > interrupts
Base class for KVM based CPU models.
long vcpuID
KVM internal ID of the vCPU.
void getOneReg(uint64_t id, void *addr) const
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
struct kvm_run * getKvmRunState()
Get a pointer to the kvm_run structure containing all the input and output parameters from kvmRun().
void startup() override
startup() is the final initialization call before simulation.
virtual Tick kvmRun(Tick ticks)
Request KVM to run the guest for a given number of ticks.
void setOneReg(uint64_t id, const void *addr)
Get/Set single register using the KVM_(SET|GET)_ONE_REG API.
ThreadContext * tc
ThreadContext object, provides an interface for external objects to modify this thread's state.
virtual void ioctlRun()
Execute the KVM_RUN ioctl.
This module implements the global system counter and the local per-CPU architected timers as specifie...
bool hasKernelIRQChip() const
Is in-kernel IRQ chip emulation enabled?
void setIRQLine(uint32_t irq, bool high)
Set the status of an IRQ line using KVM_IRQ_LINE.
int ioctl(int request, long p1) const
vCPU ioctl interface.
#define panic(...)
This implements a cprintf based panic() function.
const Params & params() const
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
const FlagsType init
This Stat is Initialized.
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
uint64_t Tick
Tick count type.