162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2015, 2016 ARM Ltd.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#ifndef __KVM_ARM_VGIC_H
662306a36Sopenharmony_ci#define __KVM_ARM_VGIC_H
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/bits.h>
962306a36Sopenharmony_ci#include <linux/kvm.h>
1062306a36Sopenharmony_ci#include <linux/irqreturn.h>
1162306a36Sopenharmony_ci#include <linux/kref.h>
1262306a36Sopenharmony_ci#include <linux/mutex.h>
1362306a36Sopenharmony_ci#include <linux/spinlock.h>
1462306a36Sopenharmony_ci#include <linux/static_key.h>
1562306a36Sopenharmony_ci#include <linux/types.h>
1662306a36Sopenharmony_ci#include <kvm/iodev.h>
1762306a36Sopenharmony_ci#include <linux/list.h>
1862306a36Sopenharmony_ci#include <linux/jump_label.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include <linux/irqchip/arm-gic-v4.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define VGIC_V3_MAX_CPUS	512
2362306a36Sopenharmony_ci#define VGIC_V2_MAX_CPUS	8
2462306a36Sopenharmony_ci#define VGIC_NR_IRQS_LEGACY     256
2562306a36Sopenharmony_ci#define VGIC_NR_SGIS		16
2662306a36Sopenharmony_ci#define VGIC_NR_PPIS		16
2762306a36Sopenharmony_ci#define VGIC_NR_PRIVATE_IRQS	(VGIC_NR_SGIS + VGIC_NR_PPIS)
2862306a36Sopenharmony_ci#define VGIC_MAX_PRIVATE	(VGIC_NR_PRIVATE_IRQS - 1)
2962306a36Sopenharmony_ci#define VGIC_MAX_SPI		1019
3062306a36Sopenharmony_ci#define VGIC_MAX_RESERVED	1023
3162306a36Sopenharmony_ci#define VGIC_MIN_LPI		8192
3262306a36Sopenharmony_ci#define KVM_IRQCHIP_NUM_PINS	(1020 - 32)
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define irq_is_ppi(irq) ((irq) >= VGIC_NR_SGIS && (irq) < VGIC_NR_PRIVATE_IRQS)
3562306a36Sopenharmony_ci#define irq_is_spi(irq) ((irq) >= VGIC_NR_PRIVATE_IRQS && \
3662306a36Sopenharmony_ci			 (irq) <= VGIC_MAX_SPI)
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cienum vgic_type {
3962306a36Sopenharmony_ci	VGIC_V2,		/* Good ol' GICv2 */
4062306a36Sopenharmony_ci	VGIC_V3,		/* New fancy GICv3 */
4162306a36Sopenharmony_ci};
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/* same for all guests, as depending only on the _host's_ GIC model */
4462306a36Sopenharmony_cistruct vgic_global {
4562306a36Sopenharmony_ci	/* type of the host GIC */
4662306a36Sopenharmony_ci	enum vgic_type		type;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	/* Physical address of vgic virtual cpu interface */
4962306a36Sopenharmony_ci	phys_addr_t		vcpu_base;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	/* GICV mapping, kernel VA */
5262306a36Sopenharmony_ci	void __iomem		*vcpu_base_va;
5362306a36Sopenharmony_ci	/* GICV mapping, HYP VA */
5462306a36Sopenharmony_ci	void __iomem		*vcpu_hyp_va;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	/* virtual control interface mapping, kernel VA */
5762306a36Sopenharmony_ci	void __iomem		*vctrl_base;
5862306a36Sopenharmony_ci	/* virtual control interface mapping, HYP VA */
5962306a36Sopenharmony_ci	void __iomem		*vctrl_hyp;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	/* Number of implemented list registers */
6262306a36Sopenharmony_ci	int			nr_lr;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	/* Maintenance IRQ number */
6562306a36Sopenharmony_ci	unsigned int		maint_irq;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	/* maximum number of VCPUs allowed (GICv2 limits us to 8) */
6862306a36Sopenharmony_ci	int			max_gic_vcpus;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	/* Only needed for the legacy KVM_CREATE_IRQCHIP */
7162306a36Sopenharmony_ci	bool			can_emulate_gicv2;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	/* Hardware has GICv4? */
7462306a36Sopenharmony_ci	bool			has_gicv4;
7562306a36Sopenharmony_ci	bool			has_gicv4_1;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	/* Pseudo GICv3 from outer space */
7862306a36Sopenharmony_ci	bool			no_hw_deactivation;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	/* GIC system register CPU interface */
8162306a36Sopenharmony_ci	struct static_key_false gicv3_cpuif;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	u32			ich_vtr_el2;
8462306a36Sopenharmony_ci};
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ciextern struct vgic_global kvm_vgic_global_state;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci#define VGIC_V2_MAX_LRS		(1 << 6)
8962306a36Sopenharmony_ci#define VGIC_V3_MAX_LRS		16
9062306a36Sopenharmony_ci#define VGIC_V3_LR_INDEX(lr)	(VGIC_V3_MAX_LRS - 1 - lr)
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cienum vgic_irq_config {
9362306a36Sopenharmony_ci	VGIC_CONFIG_EDGE = 0,
9462306a36Sopenharmony_ci	VGIC_CONFIG_LEVEL
9562306a36Sopenharmony_ci};
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci/*
9862306a36Sopenharmony_ci * Per-irq ops overriding some common behavious.
9962306a36Sopenharmony_ci *
10062306a36Sopenharmony_ci * Always called in non-preemptible section and the functions can use
10162306a36Sopenharmony_ci * kvm_arm_get_running_vcpu() to get the vcpu pointer for private IRQs.
10262306a36Sopenharmony_ci */
10362306a36Sopenharmony_cistruct irq_ops {
10462306a36Sopenharmony_ci	/* Per interrupt flags for special-cased interrupts */
10562306a36Sopenharmony_ci	unsigned long flags;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci#define VGIC_IRQ_SW_RESAMPLE	BIT(0)	/* Clear the active state for resampling */
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	/*
11062306a36Sopenharmony_ci	 * Callback function pointer to in-kernel devices that can tell us the
11162306a36Sopenharmony_ci	 * state of the input level of mapped level-triggered IRQ faster than
11262306a36Sopenharmony_ci	 * peaking into the physical GIC.
11362306a36Sopenharmony_ci	 */
11462306a36Sopenharmony_ci	bool (*get_input_level)(int vintid);
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistruct vgic_irq {
11862306a36Sopenharmony_ci	raw_spinlock_t irq_lock;	/* Protects the content of the struct */
11962306a36Sopenharmony_ci	struct list_head lpi_list;	/* Used to link all LPIs together */
12062306a36Sopenharmony_ci	struct list_head ap_list;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	struct kvm_vcpu *vcpu;		/* SGIs and PPIs: The VCPU
12362306a36Sopenharmony_ci					 * SPIs and LPIs: The VCPU whose ap_list
12462306a36Sopenharmony_ci					 * this is queued on.
12562306a36Sopenharmony_ci					 */
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	struct kvm_vcpu *target_vcpu;	/* The VCPU that this interrupt should
12862306a36Sopenharmony_ci					 * be sent to, as a result of the
12962306a36Sopenharmony_ci					 * targets reg (v2) or the
13062306a36Sopenharmony_ci					 * affinity reg (v3).
13162306a36Sopenharmony_ci					 */
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	u32 intid;			/* Guest visible INTID */
13462306a36Sopenharmony_ci	bool line_level;		/* Level only */
13562306a36Sopenharmony_ci	bool pending_latch;		/* The pending latch state used to calculate
13662306a36Sopenharmony_ci					 * the pending state for both level
13762306a36Sopenharmony_ci					 * and edge triggered IRQs. */
13862306a36Sopenharmony_ci	bool active;			/* not used for LPIs */
13962306a36Sopenharmony_ci	bool enabled;
14062306a36Sopenharmony_ci	bool hw;			/* Tied to HW IRQ */
14162306a36Sopenharmony_ci	struct kref refcount;		/* Used for LPIs */
14262306a36Sopenharmony_ci	u32 hwintid;			/* HW INTID number */
14362306a36Sopenharmony_ci	unsigned int host_irq;		/* linux irq corresponding to hwintid */
14462306a36Sopenharmony_ci	union {
14562306a36Sopenharmony_ci		u8 targets;			/* GICv2 target VCPUs mask */
14662306a36Sopenharmony_ci		u32 mpidr;			/* GICv3 target VCPU */
14762306a36Sopenharmony_ci	};
14862306a36Sopenharmony_ci	u8 source;			/* GICv2 SGIs only */
14962306a36Sopenharmony_ci	u8 active_source;		/* GICv2 SGIs only */
15062306a36Sopenharmony_ci	u8 priority;
15162306a36Sopenharmony_ci	u8 group;			/* 0 == group 0, 1 == group 1 */
15262306a36Sopenharmony_ci	enum vgic_irq_config config;	/* Level or edge */
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	struct irq_ops *ops;
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	void *owner;			/* Opaque pointer to reserve an interrupt
15762306a36Sopenharmony_ci					   for in-kernel devices. */
15862306a36Sopenharmony_ci};
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic inline bool vgic_irq_needs_resampling(struct vgic_irq *irq)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	return irq->ops && (irq->ops->flags & VGIC_IRQ_SW_RESAMPLE);
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistruct vgic_register_region;
16662306a36Sopenharmony_cistruct vgic_its;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cienum iodev_type {
16962306a36Sopenharmony_ci	IODEV_CPUIF,
17062306a36Sopenharmony_ci	IODEV_DIST,
17162306a36Sopenharmony_ci	IODEV_REDIST,
17262306a36Sopenharmony_ci	IODEV_ITS
17362306a36Sopenharmony_ci};
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_cistruct vgic_io_device {
17662306a36Sopenharmony_ci	gpa_t base_addr;
17762306a36Sopenharmony_ci	union {
17862306a36Sopenharmony_ci		struct kvm_vcpu *redist_vcpu;
17962306a36Sopenharmony_ci		struct vgic_its *its;
18062306a36Sopenharmony_ci	};
18162306a36Sopenharmony_ci	const struct vgic_register_region *regions;
18262306a36Sopenharmony_ci	enum iodev_type iodev_type;
18362306a36Sopenharmony_ci	int nr_regions;
18462306a36Sopenharmony_ci	struct kvm_io_device dev;
18562306a36Sopenharmony_ci};
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_cistruct vgic_its {
18862306a36Sopenharmony_ci	/* The base address of the ITS control register frame */
18962306a36Sopenharmony_ci	gpa_t			vgic_its_base;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	bool			enabled;
19262306a36Sopenharmony_ci	struct vgic_io_device	iodev;
19362306a36Sopenharmony_ci	struct kvm_device	*dev;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	/* These registers correspond to GITS_BASER{0,1} */
19662306a36Sopenharmony_ci	u64			baser_device_table;
19762306a36Sopenharmony_ci	u64			baser_coll_table;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	/* Protects the command queue */
20062306a36Sopenharmony_ci	struct mutex		cmd_lock;
20162306a36Sopenharmony_ci	u64			cbaser;
20262306a36Sopenharmony_ci	u32			creadr;
20362306a36Sopenharmony_ci	u32			cwriter;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	/* migration ABI revision in use */
20662306a36Sopenharmony_ci	u32			abi_rev;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	/* Protects the device and collection lists */
20962306a36Sopenharmony_ci	struct mutex		its_lock;
21062306a36Sopenharmony_ci	struct list_head	device_list;
21162306a36Sopenharmony_ci	struct list_head	collection_list;
21262306a36Sopenharmony_ci};
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_cistruct vgic_state_iter;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_cistruct vgic_redist_region {
21762306a36Sopenharmony_ci	u32 index;
21862306a36Sopenharmony_ci	gpa_t base;
21962306a36Sopenharmony_ci	u32 count; /* number of redistributors or 0 if single region */
22062306a36Sopenharmony_ci	u32 free_index; /* index of the next free redistributor */
22162306a36Sopenharmony_ci	struct list_head list;
22262306a36Sopenharmony_ci};
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistruct vgic_dist {
22562306a36Sopenharmony_ci	bool			in_kernel;
22662306a36Sopenharmony_ci	bool			ready;
22762306a36Sopenharmony_ci	bool			initialized;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
23062306a36Sopenharmony_ci	u32			vgic_model;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	/* Implementation revision as reported in the GICD_IIDR */
23362306a36Sopenharmony_ci	u32			implementation_rev;
23462306a36Sopenharmony_ci#define KVM_VGIC_IMP_REV_2	2 /* GICv2 restorable groups */
23562306a36Sopenharmony_ci#define KVM_VGIC_IMP_REV_3	3 /* GICv3 GICR_CTLR.{IW,CES,RWP} */
23662306a36Sopenharmony_ci#define KVM_VGIC_IMP_REV_LATEST	KVM_VGIC_IMP_REV_3
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	/* Userspace can write to GICv2 IGROUPR */
23962306a36Sopenharmony_ci	bool			v2_groups_user_writable;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	/* Do injected MSIs require an additional device ID? */
24262306a36Sopenharmony_ci	bool			msis_require_devid;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	int			nr_spis;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	/* base addresses in guest physical address space: */
24762306a36Sopenharmony_ci	gpa_t			vgic_dist_base;		/* distributor */
24862306a36Sopenharmony_ci	union {
24962306a36Sopenharmony_ci		/* either a GICv2 CPU interface */
25062306a36Sopenharmony_ci		gpa_t			vgic_cpu_base;
25162306a36Sopenharmony_ci		/* or a number of GICv3 redistributor regions */
25262306a36Sopenharmony_ci		struct list_head rd_regions;
25362306a36Sopenharmony_ci	};
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	/* distributor enabled */
25662306a36Sopenharmony_ci	bool			enabled;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	/* Wants SGIs without active state */
25962306a36Sopenharmony_ci	bool			nassgireq;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	struct vgic_irq		*spis;
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	struct vgic_io_device	dist_iodev;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	bool			has_its;
26662306a36Sopenharmony_ci	bool			table_write_in_progress;
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	/*
26962306a36Sopenharmony_ci	 * Contains the attributes and gpa of the LPI configuration table.
27062306a36Sopenharmony_ci	 * Since we report GICR_TYPER.CommonLPIAff as 0b00, we can share
27162306a36Sopenharmony_ci	 * one address across all redistributors.
27262306a36Sopenharmony_ci	 * GICv3 spec: IHI 0069E 6.1.1 "LPI Configuration tables"
27362306a36Sopenharmony_ci	 */
27462306a36Sopenharmony_ci	u64			propbaser;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	/* Protects the lpi_list and the count value below. */
27762306a36Sopenharmony_ci	raw_spinlock_t		lpi_list_lock;
27862306a36Sopenharmony_ci	struct list_head	lpi_list_head;
27962306a36Sopenharmony_ci	int			lpi_list_count;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	/* LPI translation cache */
28262306a36Sopenharmony_ci	struct list_head	lpi_translation_cache;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/* used by vgic-debug */
28562306a36Sopenharmony_ci	struct vgic_state_iter *iter;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	/*
28862306a36Sopenharmony_ci	 * GICv4 ITS per-VM data, containing the IRQ domain, the VPE
28962306a36Sopenharmony_ci	 * array, the property table pointer as well as allocation
29062306a36Sopenharmony_ci	 * data. This essentially ties the Linux IRQ core and ITS
29162306a36Sopenharmony_ci	 * together, and avoids leaking KVM's data structures anywhere
29262306a36Sopenharmony_ci	 * else.
29362306a36Sopenharmony_ci	 */
29462306a36Sopenharmony_ci	struct its_vm		its_vm;
29562306a36Sopenharmony_ci};
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_cistruct vgic_v2_cpu_if {
29862306a36Sopenharmony_ci	u32		vgic_hcr;
29962306a36Sopenharmony_ci	u32		vgic_vmcr;
30062306a36Sopenharmony_ci	u32		vgic_apr;
30162306a36Sopenharmony_ci	u32		vgic_lr[VGIC_V2_MAX_LRS];
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	unsigned int used_lrs;
30462306a36Sopenharmony_ci};
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_cistruct vgic_v3_cpu_if {
30762306a36Sopenharmony_ci	u32		vgic_hcr;
30862306a36Sopenharmony_ci	u32		vgic_vmcr;
30962306a36Sopenharmony_ci	u32		vgic_sre;	/* Restored only, change ignored */
31062306a36Sopenharmony_ci	u32		vgic_ap0r[4];
31162306a36Sopenharmony_ci	u32		vgic_ap1r[4];
31262306a36Sopenharmony_ci	u64		vgic_lr[VGIC_V3_MAX_LRS];
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	/*
31562306a36Sopenharmony_ci	 * GICv4 ITS per-VPE data, containing the doorbell IRQ, the
31662306a36Sopenharmony_ci	 * pending table pointer, the its_vm pointer and a few other
31762306a36Sopenharmony_ci	 * HW specific things. As for the its_vm structure, this is
31862306a36Sopenharmony_ci	 * linking the Linux IRQ subsystem and the ITS together.
31962306a36Sopenharmony_ci	 */
32062306a36Sopenharmony_ci	struct its_vpe	its_vpe;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	unsigned int used_lrs;
32362306a36Sopenharmony_ci};
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_cistruct vgic_cpu {
32662306a36Sopenharmony_ci	/* CPU vif control registers for world switch */
32762306a36Sopenharmony_ci	union {
32862306a36Sopenharmony_ci		struct vgic_v2_cpu_if	vgic_v2;
32962306a36Sopenharmony_ci		struct vgic_v3_cpu_if	vgic_v3;
33062306a36Sopenharmony_ci	};
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	raw_spinlock_t ap_list_lock;	/* Protects the ap_list */
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	/*
33762306a36Sopenharmony_ci	 * List of IRQs that this VCPU should consider because they are either
33862306a36Sopenharmony_ci	 * Active or Pending (hence the name; AP list), or because they recently
33962306a36Sopenharmony_ci	 * were one of the two and need to be migrated off this list to another
34062306a36Sopenharmony_ci	 * VCPU.
34162306a36Sopenharmony_ci	 */
34262306a36Sopenharmony_ci	struct list_head ap_list_head;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	/*
34562306a36Sopenharmony_ci	 * Members below are used with GICv3 emulation only and represent
34662306a36Sopenharmony_ci	 * parts of the redistributor.
34762306a36Sopenharmony_ci	 */
34862306a36Sopenharmony_ci	struct vgic_io_device	rd_iodev;
34962306a36Sopenharmony_ci	struct vgic_redist_region *rdreg;
35062306a36Sopenharmony_ci	u32 rdreg_index;
35162306a36Sopenharmony_ci	atomic_t syncr_busy;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	/* Contains the attributes and gpa of the LPI pending tables. */
35462306a36Sopenharmony_ci	u64 pendbaser;
35562306a36Sopenharmony_ci	/* GICR_CTLR.{ENABLE_LPIS,RWP} */
35662306a36Sopenharmony_ci	atomic_t ctlr;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	/* Cache guest priority bits */
35962306a36Sopenharmony_ci	u32 num_pri_bits;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	/* Cache guest interrupt ID bits */
36262306a36Sopenharmony_ci	u32 num_id_bits;
36362306a36Sopenharmony_ci};
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ciextern struct static_key_false vgic_v2_cpuif_trap;
36662306a36Sopenharmony_ciextern struct static_key_false vgic_v3_cpuif_trap;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ciint kvm_set_legacy_vgic_v2_addr(struct kvm *kvm, struct kvm_arm_device_addr *dev_addr);
36962306a36Sopenharmony_civoid kvm_vgic_early_init(struct kvm *kvm);
37062306a36Sopenharmony_ciint kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu);
37162306a36Sopenharmony_ciint kvm_vgic_create(struct kvm *kvm, u32 type);
37262306a36Sopenharmony_civoid kvm_vgic_destroy(struct kvm *kvm);
37362306a36Sopenharmony_civoid kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
37462306a36Sopenharmony_ciint kvm_vgic_map_resources(struct kvm *kvm);
37562306a36Sopenharmony_ciint kvm_vgic_hyp_init(void);
37662306a36Sopenharmony_civoid kvm_vgic_init_cpu_hardware(void);
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ciint kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
37962306a36Sopenharmony_ci			bool level, void *owner);
38062306a36Sopenharmony_ciint kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
38162306a36Sopenharmony_ci			  u32 vintid, struct irq_ops *ops);
38262306a36Sopenharmony_ciint kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid);
38362306a36Sopenharmony_ciint kvm_vgic_get_map(struct kvm_vcpu *vcpu, unsigned int vintid);
38462306a36Sopenharmony_cibool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ciint kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_civoid kvm_vgic_load(struct kvm_vcpu *vcpu);
38962306a36Sopenharmony_civoid kvm_vgic_put(struct kvm_vcpu *vcpu);
39062306a36Sopenharmony_civoid kvm_vgic_vmcr_sync(struct kvm_vcpu *vcpu);
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci#define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
39362306a36Sopenharmony_ci#define vgic_initialized(k)	((k)->arch.vgic.initialized)
39462306a36Sopenharmony_ci#define vgic_ready(k)		((k)->arch.vgic.ready)
39562306a36Sopenharmony_ci#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
39662306a36Sopenharmony_ci			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_cibool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
39962306a36Sopenharmony_civoid kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
40062306a36Sopenharmony_civoid kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
40162306a36Sopenharmony_civoid kvm_vgic_reset_mapped_irq(struct kvm_vcpu *vcpu, u32 vintid);
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_civoid vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg, bool allow_group1);
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci/**
40662306a36Sopenharmony_ci * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
40762306a36Sopenharmony_ci *
40862306a36Sopenharmony_ci * The host's GIC naturally limits the maximum amount of VCPUs a guest
40962306a36Sopenharmony_ci * can use.
41062306a36Sopenharmony_ci */
41162306a36Sopenharmony_cistatic inline int kvm_vgic_get_max_vcpus(void)
41262306a36Sopenharmony_ci{
41362306a36Sopenharmony_ci	return kvm_vgic_global_state.max_gic_vcpus;
41462306a36Sopenharmony_ci}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci/**
41762306a36Sopenharmony_ci * kvm_vgic_setup_default_irq_routing:
41862306a36Sopenharmony_ci * Setup a default flat gsi routing table mapping all SPIs
41962306a36Sopenharmony_ci */
42062306a36Sopenharmony_ciint kvm_vgic_setup_default_irq_routing(struct kvm *kvm);
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ciint kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner);
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_cistruct kvm_kernel_irq_routing_entry;
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ciint kvm_vgic_v4_set_forwarding(struct kvm *kvm, int irq,
42762306a36Sopenharmony_ci			       struct kvm_kernel_irq_routing_entry *irq_entry);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ciint kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int irq,
43062306a36Sopenharmony_ci				 struct kvm_kernel_irq_routing_entry *irq_entry);
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ciint vgic_v4_load(struct kvm_vcpu *vcpu);
43362306a36Sopenharmony_civoid vgic_v4_commit(struct kvm_vcpu *vcpu);
43462306a36Sopenharmony_ciint vgic_v4_put(struct kvm_vcpu *vcpu);
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci/* CPU HP callbacks */
43762306a36Sopenharmony_civoid kvm_vgic_cpu_up(void);
43862306a36Sopenharmony_civoid kvm_vgic_cpu_down(void);
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci#endif /* __KVM_ARM_VGIC_H */
441