File Index
Files and directories
Sign in
FILE

gic.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/kvm/lib/arm64/gic.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * ARM Generic Interrupt Controller (GIC) support
  4 */
  5
  6#include <errno.h>
  7#include <linux/bits.h>
  8#include <linux/sizes.h>
  9
 10#include "kvm_util.h"
 11
 12#include <gic.h>
 13#include "gic_private.h"
 14#include "processor.h"
 15#include "spinlock.h"
 16
 17static const struct gic_common_ops *gic_common_ops;
 18static struct spinlock gic_lock;
 19
 20static void gic_cpu_init(unsigned int cpu)
 21{
 22	gic_common_ops->gic_cpu_init(cpu);
 23}
 24
 25static void gic_dist_init(enum gic_type type, unsigned int nr_cpus)
 26{
 27	const struct gic_common_ops *gic_ops = NULL;
 28
 29	spin_lock(&gic_lock);
 30
 31	/* Distributor initialization is needed only once per VM */
 32	if (gic_common_ops) {
 33		spin_unlock(&gic_lock);
 34		return;
 35	}
 36
 37	if (type == GIC_V3)
 38		gic_ops = &gicv3_ops;
 39
 40	GUEST_ASSERT(gic_ops);
 41
 42	gic_ops->gic_init(nr_cpus);
 43	gic_common_ops = gic_ops;
 44
 45	/* Make sure that the initialized data is visible to all the vCPUs */
 46	dsb(sy);
 47
 48	spin_unlock(&gic_lock);
 49}
 50
 51void gic_init(enum gic_type type, unsigned int nr_cpus)
 52{
 53	uint32_t cpu = guest_get_vcpuid();
 54
 55	GUEST_ASSERT(type < GIC_TYPE_MAX);
 56	GUEST_ASSERT(nr_cpus);
 57
 58	gic_dist_init(type, nr_cpus);
 59	gic_cpu_init(cpu);
 60}
 61
 62void gic_irq_enable(unsigned int intid)
 63{
 64	GUEST_ASSERT(gic_common_ops);
 65	gic_common_ops->gic_irq_enable(intid);
 66}
 67
 68void gic_irq_disable(unsigned int intid)
 69{
 70	GUEST_ASSERT(gic_common_ops);
 71	gic_common_ops->gic_irq_disable(intid);
 72}
 73
 74unsigned int gic_get_and_ack_irq(void)
 75{
 76	uint64_t irqstat;
 77	unsigned int intid;
 78
 79	GUEST_ASSERT(gic_common_ops);
 80
 81	irqstat = gic_common_ops->gic_read_iar();
 82	intid = irqstat & GENMASK(23, 0);
 83
 84	return intid;
 85}
 86
 87void gic_set_eoi(unsigned int intid)
 88{
 89	GUEST_ASSERT(gic_common_ops);
 90	gic_common_ops->gic_write_eoir(intid);
 91}
 92
 93void gic_set_dir(unsigned int intid)
 94{
 95	GUEST_ASSERT(gic_common_ops);
 96	gic_common_ops->gic_write_dir(intid);
 97}
 98
 99void gic_set_eoi_split(bool split)
100{
101	GUEST_ASSERT(gic_common_ops);
102	gic_common_ops->gic_set_eoi_split(split);
103}
104
105void gic_set_priority_mask(uint64_t pmr)
106{
107	GUEST_ASSERT(gic_common_ops);
108	gic_common_ops->gic_set_priority_mask(pmr);
109}
110
111void gic_set_priority(unsigned int intid, unsigned int prio)
112{
113	GUEST_ASSERT(gic_common_ops);
114	gic_common_ops->gic_set_priority(intid, prio);
115}
116
117void gic_irq_set_active(unsigned int intid)
118{
119	GUEST_ASSERT(gic_common_ops);
120	gic_common_ops->gic_irq_set_active(intid);
121}
122
123void gic_irq_clear_active(unsigned int intid)
124{
125	GUEST_ASSERT(gic_common_ops);
126	gic_common_ops->gic_irq_clear_active(intid);
127}
128
129bool gic_irq_get_active(unsigned int intid)
130{
131	GUEST_ASSERT(gic_common_ops);
132	return gic_common_ops->gic_irq_get_active(intid);
133}
134
135void gic_irq_set_pending(unsigned int intid)
136{
137	GUEST_ASSERT(gic_common_ops);
138	gic_common_ops->gic_irq_set_pending(intid);
139}
140
141void gic_irq_clear_pending(unsigned int intid)
142{
143	GUEST_ASSERT(gic_common_ops);
144	gic_common_ops->gic_irq_clear_pending(intid);
145}
146
147bool gic_irq_get_pending(unsigned int intid)
148{
149	GUEST_ASSERT(gic_common_ops);
150	return gic_common_ops->gic_irq_get_pending(intid);
151}
152
153void gic_irq_set_config(unsigned int intid, bool is_edge)
154{
155	GUEST_ASSERT(gic_common_ops);
156	gic_common_ops->gic_irq_set_config(intid, is_edge);
157}
158
159void gic_irq_set_group(unsigned int intid, bool group)
160{
161	GUEST_ASSERT(gic_common_ops);
162	gic_common_ops->gic_irq_set_group(intid, group);
163}
~/ Read-only file preview.