summaryrefslogtreecommitdiff
path: root/include/linux/irqchip/arm-gic-v4.h
blob: 6976b8331b60439cc131033777412ccfdf2d31bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2016,2017 ARM Limited, All Rights Reserved.
 * Author: Marc Zyngier <marc.zyngier@arm.com>
 */

#ifndef __LINUX_IRQCHIP_ARM_GIC_V4_H
#define __LINUX_IRQCHIP_ARM_GIC_V4_H

struct its_vpe;

/*
 * Maximum number of ITTs when GITS_TYPER.VMOVP == 0, using the
 * ITSList mechanism to perform inter-ITS synchronization.
 */
#define GICv4_ITS_LIST_MAX		16

/* Embedded in kvm.arch */
struct its_vm {
	struct fwnode_handle	*fwnode;
	struct irq_domain	*domain;
	struct page		*vprop_page;
	struct its_vpe		**vpes;
	int			nr_vpes;
	irq_hw_number_t		db_lpi_base;
	unsigned long		*db_bitmap;
	int			nr_db_lpis;
	u32			vlpi_count[GICv4_ITS_LIST_MAX];
};

/* Embedded in kvm_vcpu.arch */
struct its_vpe {
	struct page 		*vpt_page;
	struct its_vm		*its_vm;
	/* per-vPE VLPI tracking */
	atomic_t		vlpi_count;
	/* Doorbell interrupt */
	int			irq;
	irq_hw_number_t		vpe_db_lpi;
	/* VPE resident */
	bool			resident;
	union {
		/* GICv4.0 implementations */
		struct {
			/* VPE proxy mapping */
			int	vpe_proxy_event;
			/* Implementation Defined Area Invalid */
			bool	idai;
		};
		/* GICv4.1 implementations */
		struct {
			struct fwnode_handle	*fwnode;
			struct irq_domain	*sgi_domain;
			struct {
				u8	priority;
				bool	enabled;
				bool	group;
			}			sgi_config[16];
			atomic_t vmapp_count;
		};
	};

	/*
	 * Ensures mutual exclusion between affinity setting of the
	 * vPE and vLPI operations using vpe->col_idx.
	 */
	raw_spinlock_t		vpe_lock;
	/*
	 * This collection ID is used to indirect the target
	 * redistributor for this VPE. The ID itself isn't involved in
	 * programming of the ITS.
	 */
	u16			col_idx;
	/* Unique (system-wide) VPE identifier */
	u16			vpe_id;
	/* Pending VLPIs on schedule out? */
	bool			pending_last;
};

/*
 * struct its_vlpi_map: structure describing the mapping of a
 * VLPI. Only to be interpreted in the context of a physical interrupt
 * it complements.  To be used as the vcpu_info passed to
 * irq_set_vcpu_affinity().
 *
 * @vm:		Pointer to the GICv4 notion of a VM
 * @vpe:	Pointer to the GICv4 notion of a virtual CPU (VPE)
 * @vintid:	Virtual LPI number
 * @properties:	Priority and enable bits (as written in the prop table)
 * @db_enabled:	Is the VPE doorbell to be generated?
 */
struct its_vlpi_map {
	struct its_vm		*vm;
	struct its_vpe		*vpe;
	u32			vintid;
	u8			properties;
	bool			db_enabled;
};

enum its_vcpu_info_cmd_type {
	MAP_VLPI,
	GET_VLPI,
	PROP_UPDATE_VLPI,
	PROP_UPDATE_AND_INV_VLPI,
	SCHEDULE_VPE,
	DESCHEDULE_VPE,
	INVALL_VPE,
	PROP_UPDATE_VSGI,
};

struct its_cmd_info {
	enum its_vcpu_info_cmd_type	cmd_type;
	union {
		struct its_vlpi_map	*map;
		u8			config;
		bool			req_db;
		struct {
			bool		g0en;
			bool		g1en;
		};
		struct {
			u8		priority;
			bool		group;
		};
	};
};

int its_alloc_vcpu_irqs(struct its_vm *vm);
void its_free_vcpu_irqs(struct its_vm *vm);
int its_make_vpe_resident(struct its_vpe *vpe, bool g0en, bool g1en);
int its_make_vpe_non_resident(struct its_vpe *vpe, bool db);
int its_invall_vpe(struct its_vpe *vpe);
int its_map_vlpi(int irq, struct its_vlpi_map *map);
int its_get_vlpi(int irq, struct its_vlpi_map *map);
int its_unmap_vlpi(int irq);
int its_prop_update_vlpi(int irq, u8 config, bool inv);
int its_prop_update_vsgi(int irq, u8 priority, bool group);

struct irq_domain_ops;
int its_init_v4(struct irq_domain *domain,
		const struct irq_domain_ops *vpe_ops,
		const struct irq_domain_ops *sgi_ops);

#endif