Commit 5d721b78 authored by Alexander Graf's avatar Alexander Graf Committed by Peter Maydell
Browse files

ARM: KVM: Enable in-kernel timers with user space gic



When running with KVM enabled, you can choose between emulating the
gic in kernel or user space. If the kernel supports in-kernel virtualization
of the interrupt controller, it will default to that. If not, if will
default to user space emulation.

Unfortunately when running in user mode gic emulation, we miss out on
interrupt events which are only available from kernel space, such as the timer.
This patch leverages the new kernel/user space pending line synchronization for
timer events. It does not handle PMU events yet.

Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
Reviewed-by: default avatarAndrew Jones <drjones@redhat.com>
Message-id: 1498577737-130264-1-git-send-email-agraf@suse.de
Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parent f986ee1d
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -2274,6 +2274,11 @@ int kvm_has_intx_set_mask(void)
    return kvm_state->intx_set_mask;
}

bool kvm_arm_supports_user_irq(void)
{
    return kvm_check_extension(kvm_state, KVM_CAP_ARM_USER_IRQ);
}

#ifdef KVM_CAP_SET_GUEST_DEBUG
struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu,
                                                 target_ulong pc)
+5 −0
Original line number Diff line number Diff line
@@ -155,4 +155,9 @@ void kvm_init_cpu_signals(CPUState *cpu)
{
    abort();
}

bool kvm_arm_supports_user_irq(void)
{
    return false;
}
#endif
+7 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include "qom/cpu.h"
#include "qemu/log.h"
#include "trace.h"
#include "sysemu/kvm.h"

/* #define DEBUG_GIC */

@@ -1412,6 +1413,12 @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
        return;
    }

    if (kvm_enabled() && !kvm_arm_supports_user_irq()) {
        error_setg(errp, "KVM with user space irqchip only works when the "
                         "host kernel supports KVM_CAP_ARM_USER_IRQ");
        return;
    }

    /* This creates distributor and main CPU interface (s->cpuiomem[0]) */
    gic_init_irqs_and_mmio(s, gic_set_irq, gic_ops);

+11 −0
Original line number Diff line number Diff line
@@ -220,6 +220,17 @@ int kvm_init_vcpu(CPUState *cpu);
int kvm_cpu_exec(CPUState *cpu);
int kvm_destroy_vcpu(CPUState *cpu);

/**
 * kvm_arm_supports_user_irq
 *
 * Not all KVM implementations support notifications for kernel generated
 * interrupt events to user space. This function indicates whether the current
 * KVM implementation does support them.
 *
 * Returns: true if KVM supports using kernel generated IRQs from user space
 */
bool kvm_arm_supports_user_irq(void);

#ifdef NEED_CPU_H
#include "cpu.h"

+3 −0
Original line number Diff line number Diff line
@@ -706,6 +706,9 @@ struct ARMCPU {
    void *el_change_hook_opaque;

    int32_t node_id; /* NUMA node this CPU belongs to */

    /* Used to synchronize KVM and QEMU in-kernel device levels */
    uint8_t device_irq_level;
};

static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
Loading