1 // SPDX-License-Identifier: GPL-2.0
3 * ARM Generic Interrupt Controller (GIC) support
7 #include <linux/bits.h>
8 #include <linux/sizes.h>
13 #include "gic_private.h"
14 #include "processor.h"
17 static const struct gic_common_ops
*gic_common_ops
;
18 static struct spinlock gic_lock
;
20 static void gic_cpu_init(unsigned int cpu
)
22 gic_common_ops
->gic_cpu_init(cpu
);
25 static void gic_dist_init(enum gic_type type
, unsigned int nr_cpus
)
27 const struct gic_common_ops
*gic_ops
= NULL
;
31 /* Distributor initialization is needed only once per VM */
33 spin_unlock(&gic_lock
);
40 GUEST_ASSERT(gic_ops
);
42 gic_ops
->gic_init(nr_cpus
);
43 gic_common_ops
= gic_ops
;
45 /* Make sure that the initialized data is visible to all the vCPUs */
48 spin_unlock(&gic_lock
);
51 void gic_init(enum gic_type type
, unsigned int nr_cpus
)
53 uint32_t cpu
= guest_get_vcpuid();
55 GUEST_ASSERT(type
< GIC_TYPE_MAX
);
56 GUEST_ASSERT(nr_cpus
);
58 gic_dist_init(type
, nr_cpus
);
62 void gic_irq_enable(unsigned int intid
)
64 GUEST_ASSERT(gic_common_ops
);
65 gic_common_ops
->gic_irq_enable(intid
);
68 void gic_irq_disable(unsigned int intid
)
70 GUEST_ASSERT(gic_common_ops
);
71 gic_common_ops
->gic_irq_disable(intid
);
74 unsigned int gic_get_and_ack_irq(void)
79 GUEST_ASSERT(gic_common_ops
);
81 irqstat
= gic_common_ops
->gic_read_iar();
82 intid
= irqstat
& GENMASK(23, 0);
87 void gic_set_eoi(unsigned int intid
)
89 GUEST_ASSERT(gic_common_ops
);
90 gic_common_ops
->gic_write_eoir(intid
);
93 void gic_set_dir(unsigned int intid
)
95 GUEST_ASSERT(gic_common_ops
);
96 gic_common_ops
->gic_write_dir(intid
);
99 void gic_set_eoi_split(bool split
)
101 GUEST_ASSERT(gic_common_ops
);
102 gic_common_ops
->gic_set_eoi_split(split
);
105 void gic_set_priority_mask(uint64_t pmr
)
107 GUEST_ASSERT(gic_common_ops
);
108 gic_common_ops
->gic_set_priority_mask(pmr
);
111 void gic_set_priority(unsigned int intid
, unsigned int prio
)
113 GUEST_ASSERT(gic_common_ops
);
114 gic_common_ops
->gic_set_priority(intid
, prio
);
117 void gic_irq_set_active(unsigned int intid
)
119 GUEST_ASSERT(gic_common_ops
);
120 gic_common_ops
->gic_irq_set_active(intid
);
123 void gic_irq_clear_active(unsigned int intid
)
125 GUEST_ASSERT(gic_common_ops
);
126 gic_common_ops
->gic_irq_clear_active(intid
);
129 bool gic_irq_get_active(unsigned int intid
)
131 GUEST_ASSERT(gic_common_ops
);
132 return gic_common_ops
->gic_irq_get_active(intid
);
135 void gic_irq_set_pending(unsigned int intid
)
137 GUEST_ASSERT(gic_common_ops
);
138 gic_common_ops
->gic_irq_set_pending(intid
);
141 void gic_irq_clear_pending(unsigned int intid
)
143 GUEST_ASSERT(gic_common_ops
);
144 gic_common_ops
->gic_irq_clear_pending(intid
);
147 bool gic_irq_get_pending(unsigned int intid
)
149 GUEST_ASSERT(gic_common_ops
);
150 return gic_common_ops
->gic_irq_get_pending(intid
);
153 void gic_irq_set_config(unsigned int intid
, bool is_edge
)
155 GUEST_ASSERT(gic_common_ops
);
156 gic_common_ops
->gic_irq_set_config(intid
, is_edge
);