brintos

brintos / linux-shallow public Read only

0
0
Text · 3.1 KiB · 7abbf88 Raw
158 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * ARM Generic Interrupt Controller (GIC) support4 */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