/*
* Copyright (C) 2015, 2016 ARM Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef __ASM_ARM_NEW_VGIC_H
#define __ASM_ARM_NEW_VGIC_H
#include
#include
#include
#include
#include
#define VGIC_V3_MAX_CPUS 255
#define VGIC_V2_MAX_CPUS 8
#define VGIC_NR_SGIS 16
#define VGIC_NR_PPIS 16
#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS)
#define VGIC_MAX_PRIVATE (VGIC_NR_PRIVATE_IRQS - 1)
#define VGIC_MAX_SPI 1019
#define VGIC_MAX_RESERVED 1023
#define VGIC_MIN_LPI 8192
#define irq_is_ppi(irq) ((irq) >= VGIC_NR_SGIS && (irq) < VGIC_NR_PRIVATE_IRQS)
#define irq_is_spi(irq) ((irq) >= VGIC_NR_PRIVATE_IRQS && \
(irq) <= VGIC_MAX_SPI)
enum vgic_type {
VGIC_V2, /* Good ol' GICv2 */
VGIC_V3, /* New fancy GICv3 */
};
#define VGIC_V2_MAX_LRS (1 << 6)
#define VGIC_V3_MAX_LRS 16
#define VGIC_V3_LR_INDEX(lr) (VGIC_V3_MAX_LRS - 1 - (lr))
#define VGIC_CONFIG_EDGE false
#define VGIC_CONFIG_LEVEL true
struct vgic_irq {
struct list_head ap_list;
struct vcpu *vcpu; /*
* SGIs and PPIs: The VCPU
* SPIs and LPIs: The VCPU whose ap_list
* this is queued on.
*/
struct vcpu *target_vcpu; /*
* The VCPU that this interrupt should
* be sent to, as a result of the
* targets reg (v2) or the affinity reg (v3).
*/
spinlock_t irq_lock; /* Protects the content of the struct */
uint32_t intid; /* Guest visible INTID */
atomic_t refcount; /* Used for LPIs */
uint32_t hwintid; /* HW INTID number */
union
{
struct {
uint8_t targets; /* GICv2 target VCPUs mask */
uint8_t source; /* GICv2 SGIs only */
};
uint32_t mpidr; /* GICv3 target VCPU */
};
uint8_t priority;
bool line_level:1; /* Level only */
bool pending_latch:1; /*
* The pending latch state used to
* calculate the pending state for both
* level and edge triggered IRQs.
*/
bool active:1; /* not used for LPIs */
bool enabled:1;
bool hw:1; /* Tied to HW IRQ */
bool config:1; /* Level or edge */
struct list_head lpi_list; /* Used to link all LPIs together */
};
enum iodev_type {
IODEV_DIST,
IODEV_REDIST,
};
struct vgic_io_device {
gfn_t base_fn;
struct vcpu *redist_vcpu;
const struct vgic_register_region *regions;
enum iodev_type iodev_type;
unsigned int nr_regions;
};
struct vgic_dist {
bool ready;
bool initialized;
/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
uint32_t version;
/* Do injected MSIs require an additional device ID? */
bool msis_require_devid;
unsigned int nr_spis;
/* base addresses in guest physical address space: */
paddr_t dbase; /* distributor */
union
{
/* either a GICv2 CPU interface */
paddr_t cbase;
/* or a number of GICv3 redistributor regions */
struct
{
paddr_t vgic_redist_base;
paddr_t vgic_redist_free_offset;
};
};
paddr_t csize; /* CPU interface size */
paddr_t vbase; /* virtual CPU interface base address */
/* distributor enabled */
bool enabled;
struct vgic_irq *spis;
unsigned long *allocated_irqs; /* bitmap of IRQs allocated */
struct vgic_io_device dist_iodev;
bool has_its;
/*
* Contains the attributes and gpa of the LPI configuration table.
* Since we report GICR_TYPER.CommonLPIAff as 0b00, we can share
* one address across all redistributors.
* GICv3 spec: 6.1.2 "LPI Configuration tables"
*/
uint64_t propbaser;
/* Protects the lpi_list and the count value below. */
spinlock_t lpi_list_lock;
struct list_head lpi_list_head;
unsigned int lpi_list_count;
};
struct vgic_cpu {
struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
struct list_head ap_list_head;
spinlock_t ap_list_lock; /* Protects the ap_list */
unsigned int used_lrs;
/*
* List of IRQs that this VCPU should consider because they are either
* Active or Pending (hence the name; AP list), or because they recently
* were one of the two and need to be migrated off this list to another
* VCPU.
*/
/*
* Members below are used with GICv3 emulation only and represent
* parts of the redistributor.
*/
struct vgic_io_device rd_iodev;
struct vgic_io_device sgi_iodev;
/* Contains the attributes and gpa of the LPI pending tables. */
uint64_t pendbaser;
bool lpis_enabled;
/* Cache guest priority bits */
uint32_t num_pri_bits;
/* Cache guest interrupt ID bits */
uint32_t num_id_bits;
};
static inline paddr_t vgic_cpu_base(const struct vgic_dist *vgic)
{
return vgic->cbase;
}
static inline paddr_t vgic_dist_base(const struct vgic_dist *vgic)
{
return vgic->dbase;
}
#endif /* __ASM_ARM_NEW_VGIC_H */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/