0001
0002
0003
0004
0005
0006 #include <errno.h>
0007 #include <linux/bits.h>
0008 #include <linux/sizes.h>
0009
0010 #include "kvm_util.h"
0011
0012 #include <gic.h>
0013 #include "gic_private.h"
0014 #include "processor.h"
0015 #include "spinlock.h"
0016
0017 static const struct gic_common_ops *gic_common_ops;
0018 static struct spinlock gic_lock;
0019
0020 static void gic_cpu_init(unsigned int cpu, void *redist_base)
0021 {
0022 gic_common_ops->gic_cpu_init(cpu, redist_base);
0023 }
0024
0025 static void
0026 gic_dist_init(enum gic_type type, unsigned int nr_cpus, void *dist_base)
0027 {
0028 const struct gic_common_ops *gic_ops = NULL;
0029
0030 spin_lock(&gic_lock);
0031
0032
0033 if (gic_common_ops) {
0034 spin_unlock(&gic_lock);
0035 return;
0036 }
0037
0038 if (type == GIC_V3)
0039 gic_ops = &gicv3_ops;
0040
0041 GUEST_ASSERT(gic_ops);
0042
0043 gic_ops->gic_init(nr_cpus, dist_base);
0044 gic_common_ops = gic_ops;
0045
0046
0047 dsb(sy);
0048
0049 spin_unlock(&gic_lock);
0050 }
0051
0052 void gic_init(enum gic_type type, unsigned int nr_cpus,
0053 void *dist_base, void *redist_base)
0054 {
0055 uint32_t cpu = guest_get_vcpuid();
0056
0057 GUEST_ASSERT(type < GIC_TYPE_MAX);
0058 GUEST_ASSERT(dist_base);
0059 GUEST_ASSERT(redist_base);
0060 GUEST_ASSERT(nr_cpus);
0061
0062 gic_dist_init(type, nr_cpus, dist_base);
0063 gic_cpu_init(cpu, redist_base);
0064 }
0065
0066 void gic_irq_enable(unsigned int intid)
0067 {
0068 GUEST_ASSERT(gic_common_ops);
0069 gic_common_ops->gic_irq_enable(intid);
0070 }
0071
0072 void gic_irq_disable(unsigned int intid)
0073 {
0074 GUEST_ASSERT(gic_common_ops);
0075 gic_common_ops->gic_irq_disable(intid);
0076 }
0077
0078 unsigned int gic_get_and_ack_irq(void)
0079 {
0080 uint64_t irqstat;
0081 unsigned int intid;
0082
0083 GUEST_ASSERT(gic_common_ops);
0084
0085 irqstat = gic_common_ops->gic_read_iar();
0086 intid = irqstat & GENMASK(23, 0);
0087
0088 return intid;
0089 }
0090
0091 void gic_set_eoi(unsigned int intid)
0092 {
0093 GUEST_ASSERT(gic_common_ops);
0094 gic_common_ops->gic_write_eoir(intid);
0095 }
0096
0097 void gic_set_dir(unsigned int intid)
0098 {
0099 GUEST_ASSERT(gic_common_ops);
0100 gic_common_ops->gic_write_dir(intid);
0101 }
0102
0103 void gic_set_eoi_split(bool split)
0104 {
0105 GUEST_ASSERT(gic_common_ops);
0106 gic_common_ops->gic_set_eoi_split(split);
0107 }
0108
0109 void gic_set_priority_mask(uint64_t pmr)
0110 {
0111 GUEST_ASSERT(gic_common_ops);
0112 gic_common_ops->gic_set_priority_mask(pmr);
0113 }
0114
0115 void gic_set_priority(unsigned int intid, unsigned int prio)
0116 {
0117 GUEST_ASSERT(gic_common_ops);
0118 gic_common_ops->gic_set_priority(intid, prio);
0119 }
0120
0121 void gic_irq_set_active(unsigned int intid)
0122 {
0123 GUEST_ASSERT(gic_common_ops);
0124 gic_common_ops->gic_irq_set_active(intid);
0125 }
0126
0127 void gic_irq_clear_active(unsigned int intid)
0128 {
0129 GUEST_ASSERT(gic_common_ops);
0130 gic_common_ops->gic_irq_clear_active(intid);
0131 }
0132
0133 bool gic_irq_get_active(unsigned int intid)
0134 {
0135 GUEST_ASSERT(gic_common_ops);
0136 return gic_common_ops->gic_irq_get_active(intid);
0137 }
0138
0139 void gic_irq_set_pending(unsigned int intid)
0140 {
0141 GUEST_ASSERT(gic_common_ops);
0142 gic_common_ops->gic_irq_set_pending(intid);
0143 }
0144
0145 void gic_irq_clear_pending(unsigned int intid)
0146 {
0147 GUEST_ASSERT(gic_common_ops);
0148 gic_common_ops->gic_irq_clear_pending(intid);
0149 }
0150
0151 bool gic_irq_get_pending(unsigned int intid)
0152 {
0153 GUEST_ASSERT(gic_common_ops);
0154 return gic_common_ops->gic_irq_get_pending(intid);
0155 }
0156
0157 void gic_irq_set_config(unsigned int intid, bool is_edge)
0158 {
0159 GUEST_ASSERT(gic_common_ops);
0160 gic_common_ops->gic_irq_set_config(intid, is_edge);
0161 }