cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gic.c (3302B)


      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, void *redist_base)
     21{
     22	gic_common_ops->gic_cpu_init(cpu, redist_base);
     23}
     24
     25static void
     26gic_dist_init(enum gic_type type, unsigned int nr_cpus, void *dist_base)
     27{
     28	const struct gic_common_ops *gic_ops = NULL;
     29
     30	spin_lock(&gic_lock);
     31
     32	/* Distributor initialization is needed only once per VM */
     33	if (gic_common_ops) {
     34		spin_unlock(&gic_lock);
     35		return;
     36	}
     37
     38	if (type == GIC_V3)
     39		gic_ops = &gicv3_ops;
     40
     41	GUEST_ASSERT(gic_ops);
     42
     43	gic_ops->gic_init(nr_cpus, dist_base);
     44	gic_common_ops = gic_ops;
     45
     46	/* Make sure that the initialized data is visible to all the vCPUs */
     47	dsb(sy);
     48
     49	spin_unlock(&gic_lock);
     50}
     51
     52void gic_init(enum gic_type type, unsigned int nr_cpus,
     53		void *dist_base, void *redist_base)
     54{
     55	uint32_t cpu = guest_get_vcpuid();
     56
     57	GUEST_ASSERT(type < GIC_TYPE_MAX);
     58	GUEST_ASSERT(dist_base);
     59	GUEST_ASSERT(redist_base);
     60	GUEST_ASSERT(nr_cpus);
     61
     62	gic_dist_init(type, nr_cpus, dist_base);
     63	gic_cpu_init(cpu, redist_base);
     64}
     65
     66void gic_irq_enable(unsigned int intid)
     67{
     68	GUEST_ASSERT(gic_common_ops);
     69	gic_common_ops->gic_irq_enable(intid);
     70}
     71
     72void gic_irq_disable(unsigned int intid)
     73{
     74	GUEST_ASSERT(gic_common_ops);
     75	gic_common_ops->gic_irq_disable(intid);
     76}
     77
     78unsigned int gic_get_and_ack_irq(void)
     79{
     80	uint64_t irqstat;
     81	unsigned int intid;
     82
     83	GUEST_ASSERT(gic_common_ops);
     84
     85	irqstat = gic_common_ops->gic_read_iar();
     86	intid = irqstat & GENMASK(23, 0);
     87
     88	return intid;
     89}
     90
     91void gic_set_eoi(unsigned int intid)
     92{
     93	GUEST_ASSERT(gic_common_ops);
     94	gic_common_ops->gic_write_eoir(intid);
     95}
     96
     97void gic_set_dir(unsigned int intid)
     98{
     99	GUEST_ASSERT(gic_common_ops);
    100	gic_common_ops->gic_write_dir(intid);
    101}
    102
    103void gic_set_eoi_split(bool split)
    104{
    105	GUEST_ASSERT(gic_common_ops);
    106	gic_common_ops->gic_set_eoi_split(split);
    107}
    108
    109void gic_set_priority_mask(uint64_t pmr)
    110{
    111	GUEST_ASSERT(gic_common_ops);
    112	gic_common_ops->gic_set_priority_mask(pmr);
    113}
    114
    115void gic_set_priority(unsigned int intid, unsigned int prio)
    116{
    117	GUEST_ASSERT(gic_common_ops);
    118	gic_common_ops->gic_set_priority(intid, prio);
    119}
    120
    121void gic_irq_set_active(unsigned int intid)
    122{
    123	GUEST_ASSERT(gic_common_ops);
    124	gic_common_ops->gic_irq_set_active(intid);
    125}
    126
    127void gic_irq_clear_active(unsigned int intid)
    128{
    129	GUEST_ASSERT(gic_common_ops);
    130	gic_common_ops->gic_irq_clear_active(intid);
    131}
    132
    133bool gic_irq_get_active(unsigned int intid)
    134{
    135	GUEST_ASSERT(gic_common_ops);
    136	return gic_common_ops->gic_irq_get_active(intid);
    137}
    138
    139void gic_irq_set_pending(unsigned int intid)
    140{
    141	GUEST_ASSERT(gic_common_ops);
    142	gic_common_ops->gic_irq_set_pending(intid);
    143}
    144
    145void gic_irq_clear_pending(unsigned int intid)
    146{
    147	GUEST_ASSERT(gic_common_ops);
    148	gic_common_ops->gic_irq_clear_pending(intid);
    149}
    150
    151bool gic_irq_get_pending(unsigned int intid)
    152{
    153	GUEST_ASSERT(gic_common_ops);
    154	return gic_common_ops->gic_irq_get_pending(intid);
    155}
    156
    157void gic_irq_set_config(unsigned int intid, bool is_edge)
    158{
    159	GUEST_ASSERT(gic_common_ops);
    160	gic_common_ops->gic_irq_set_config(intid, is_edge);
    161}