Path: blob/master/tools/testing/selftests/kvm/lib/arm64/gic.c
49679 views
// SPDX-License-Identifier: GPL-2.01/*2* ARM Generic Interrupt Controller (GIC) support3*/45#include <errno.h>6#include <linux/bits.h>7#include <linux/sizes.h>89#include "kvm_util.h"1011#include <gic.h>12#include "gic_private.h"13#include "processor.h"14#include "spinlock.h"1516static const struct gic_common_ops *gic_common_ops;17static struct spinlock gic_lock;1819static void gic_cpu_init(unsigned int cpu)20{21gic_common_ops->gic_cpu_init(cpu);22}2324static void gic_dist_init(enum gic_type type, unsigned int nr_cpus)25{26const struct gic_common_ops *gic_ops = NULL;2728spin_lock(&gic_lock);2930/* Distributor initialization is needed only once per VM */31if (gic_common_ops) {32spin_unlock(&gic_lock);33return;34}3536if (type == GIC_V3)37gic_ops = &gicv3_ops;3839GUEST_ASSERT(gic_ops);4041gic_ops->gic_init(nr_cpus);42gic_common_ops = gic_ops;4344/* Make sure that the initialized data is visible to all the vCPUs */45dsb(sy);4647spin_unlock(&gic_lock);48}4950void gic_init(enum gic_type type, unsigned int nr_cpus)51{52uint32_t cpu = guest_get_vcpuid();5354GUEST_ASSERT(type < GIC_TYPE_MAX);55GUEST_ASSERT(nr_cpus);5657gic_dist_init(type, nr_cpus);58gic_cpu_init(cpu);59}6061void gic_irq_enable(unsigned int intid)62{63GUEST_ASSERT(gic_common_ops);64gic_common_ops->gic_irq_enable(intid);65}6667void gic_irq_disable(unsigned int intid)68{69GUEST_ASSERT(gic_common_ops);70gic_common_ops->gic_irq_disable(intid);71}7273unsigned int gic_get_and_ack_irq(void)74{75uint64_t irqstat;76unsigned int intid;7778GUEST_ASSERT(gic_common_ops);7980irqstat = gic_common_ops->gic_read_iar();81intid = irqstat & GENMASK(23, 0);8283return intid;84}8586void gic_set_eoi(unsigned int intid)87{88GUEST_ASSERT(gic_common_ops);89gic_common_ops->gic_write_eoir(intid);90}9192void gic_set_dir(unsigned int intid)93{94GUEST_ASSERT(gic_common_ops);95gic_common_ops->gic_write_dir(intid);96}9798void gic_set_eoi_split(bool split)99{100GUEST_ASSERT(gic_common_ops);101gic_common_ops->gic_set_eoi_split(split);102}103104void gic_set_priority_mask(uint64_t pmr)105{106GUEST_ASSERT(gic_common_ops);107gic_common_ops->gic_set_priority_mask(pmr);108}109110void gic_set_priority(unsigned int intid, unsigned int prio)111{112GUEST_ASSERT(gic_common_ops);113gic_common_ops->gic_set_priority(intid, prio);114}115116void gic_irq_set_active(unsigned int intid)117{118GUEST_ASSERT(gic_common_ops);119gic_common_ops->gic_irq_set_active(intid);120}121122void gic_irq_clear_active(unsigned int intid)123{124GUEST_ASSERT(gic_common_ops);125gic_common_ops->gic_irq_clear_active(intid);126}127128bool gic_irq_get_active(unsigned int intid)129{130GUEST_ASSERT(gic_common_ops);131return gic_common_ops->gic_irq_get_active(intid);132}133134void gic_irq_set_pending(unsigned int intid)135{136GUEST_ASSERT(gic_common_ops);137gic_common_ops->gic_irq_set_pending(intid);138}139140void gic_irq_clear_pending(unsigned int intid)141{142GUEST_ASSERT(gic_common_ops);143gic_common_ops->gic_irq_clear_pending(intid);144}145146bool gic_irq_get_pending(unsigned int intid)147{148GUEST_ASSERT(gic_common_ops);149return gic_common_ops->gic_irq_get_pending(intid);150}151152void gic_irq_set_config(unsigned int intid, bool is_edge)153{154GUEST_ASSERT(gic_common_ops);155gic_common_ops->gic_irq_set_config(intid, is_edge);156}157158void gic_irq_set_group(unsigned int intid, bool group)159{160GUEST_ASSERT(gic_common_ops);161gic_common_ops->gic_irq_set_group(intid, group);162}163164165