summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/kvm/include/arm64/gic_v5.h
blob: 2d455515563e0a528f96a3cd143aecc003edd501 (plain) (blame)
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef __SELFTESTS_GIC_V5_H
#define __SELFTESTS_GIC_V5_H

#include <asm/barrier.h>
#include <asm/sysreg.h>

#include <linux/bitfield.h>

#include "processor.h"

/* GIC component base address is guest PA space */
#define GICV5_IRS_CONFIG_BASE_GPA	0x8000000ULL
#define GICV5_IRS_CONFIG_BASE_GVA	((volatile void *)GICV5_IRS_CONFIG_BASE_GPA)

#define GICV5_IRS_SIZE			0x20000
#define GICV5_IRS_ALIGN			0x10000

/*
 * IRS register offsets. Keep this selftest copy scoped to the offsets and
 * fields exercised by the userspace API tests.
 */
#define GICV5_IRS_IDR0			0x0000
#define GICV5_IRS_IDR1			0x0004
#define GICV5_IRS_IDR2			0x0008
#define GICV5_IRS_IDR3			0x000c
#define GICV5_IRS_IDR4			0x0010
#define GICV5_IRS_IDR5			0x0014
#define GICV5_IRS_IDR6			0x0018
#define GICV5_IRS_IDR7			0x001c
#define GICV5_IRS_IIDR			0x0040
#define GICV5_IRS_AIDR			0x0044
#define GICV5_IRS_CR0			0x0080
#define GICV5_IRS_CR1			0x0084
#define GICV5_IRS_SYNCR			0x00c0
#define GICV5_IRS_SYNC_STATUSR		0x00c4
#define GICV5_IRS_SPI_VMR		0x0100
#define GICV5_IRS_SPI_SELR		0x0108
#define GICV5_IRS_SPI_DOMAINR		0x010c
#define GICV5_IRS_SPI_RESAMPLER		0x0110
#define GICV5_IRS_SPI_CFGR		0x0114
#define GICV5_IRS_SPI_STATUSR		0x0118
#define GICV5_IRS_PE_SELR		0x0140
#define GICV5_IRS_PE_STATUSR		0x0144
#define GICV5_IRS_PE_CR0		0x0148
#define GICV5_IRS_IST_BASER		0x0180
#define GICV5_IRS_IST_CFGR		0x0190
#define GICV5_IRS_IST_STATUSR		0x0194
#define GICV5_IRS_MAP_L2_ISTR		0x01c0
#define GICV5_IRS_VMT_BASER		0x0200
#define GICV5_IRS_VMT_CFGR		0x0210
#define GICV5_IRS_VMT_STATUSR		0x0214
#define GICV5_IRS_VPE_SELR		0x0240
#define GICV5_IRS_VPE_DBR		0x0248
#define GICV5_IRS_VPE_HPPIR		0x0250
#define GICV5_IRS_VPE_CR0		0x0258
#define GICV5_IRS_VPE_STATUSR		0x025c
#define GICV5_IRS_VM_DBR		0x0280
#define GICV5_IRS_VM_SELR		0x0288
#define GICV5_IRS_VM_STATUSR		0x028c
#define GICV5_IRS_VMAP_L2_VMTR		0x02c0
#define GICV5_IRS_VMAP_VMR		0x02c8
#define GICV5_IRS_VMAP_VISTR		0x02d0
#define GICV5_IRS_VMAP_L2_VISTR		0x02d8
#define GICV5_IRS_VMAP_VPER		0x02e0
#define GICV5_IRS_SAVE_VMR		0x0300
#define GICV5_IRS_SAVE_VM_STATUSR	0x0308
#define GICV5_IRS_MEC_IDR		0x0340
#define GICV5_IRS_MEC_MECID_R		0x0344
#define GICV5_IRS_MPAM_IDR		0x0380
#define GICV5_IRS_MPAM_PARTID_R		0x0384
#define GICV5_IRS_SWERR_STATUSR		0x03c0
#define GICV5_IRS_SWERR_SYNDROMER0	0x03c8
#define GICV5_IRS_SWERR_SYNDROMER1	0x03d0

#define GICV5_IRS_IDR0_SETLPI		BIT(9)
#define GICV5_IRS_IDR0_INT_DOM		GENMASK(1, 0)
#define GICV5_IRS_IDR0_INT_DOM_SECURE		0b00

#define GICV5_IRS_IDR1_PRIORITY_BITS	GENMASK(22, 20)

#define GICV5_IRS_IDR2_ISTMD_SZ	GENMASK(19, 15)
#define GICV5_IRS_IDR2_ISTMD		BIT(14)
#define GICV5_IRS_IDR2_IST_L2SZ	GENMASK(13, 11)
#define GICV5_IRS_IDR2_IST_LEVELS	BIT(10)
#define GICV5_IRS_IDR2_MIN_LPI_ID_BITS	GENMASK(9, 6)
#define GICV5_IRS_IDR2_LPI		BIT(5)
#define GICV5_IRS_IDR2_ID_BITS		GENMASK(4, 0)

#define GICV5_IRS_CR0_IDLE		BIT(1)
#define GICV5_IRS_CR0_IRSEN		BIT(0)

#define GICV5_IRS_SPI_SELR_ID		GENMASK(23, 0)
#define GICV5_IRS_SPI_CFGR_TM		BIT(0)

#define GICV5_IRS_SYNC_STATUSR_IDLE	BIT(0)
#define GICV5_IRS_SPI_STATUSR_IDLE	BIT(0)
#define GICV5_IRS_PE_STATUSR_IDLE	BIT(0)
#define GICV5_IRS_IST_STATUSR_IDLE	BIT(0)

#define GICV5_IRS_IST_BASER_ADDR_MASK	GENMASK_ULL(55, 6)
#define GICV5_IRS_IST_BASER_VALID	BIT_ULL(0)
#define GICV5_IRS_IST_BASER_ADDR_SHIFT	6ULL
#define GICV5_IRS_IST_CFGR_STRUCTURE	BIT(16)
#define GICV5_IRS_IST_CFGR_ISTSZ	GENMASK(8, 7)
#define GICV5_IRS_IST_CFGR_L2SZ	GENMASK(6, 5)
#define GICV5_IRS_IST_CFGR_LPI_ID_BITS	GENMASK(4, 0)
#define GICV5_IRS_IST_CFGR_ISTSZ_4	0b00
#define GICV5_IRS_IST_CFGR_ISTSZ_8	0b01
#define GICV5_IRS_IST_CFGR_ISTSZ_16	0b10

/*
 * Definitions for GICv5 instructions for the Current Domain
 */
#define GICV5_OP_GIC_CDAFF		sys_insn(1, 0, 12, 1, 3)
#define GICV5_OP_GIC_CDDI		sys_insn(1, 0, 12, 2, 0)
#define GICV5_OP_GIC_CDDIS		sys_insn(1, 0, 12, 1, 0)
#define GICV5_OP_GIC_CDHM		sys_insn(1, 0, 12, 2, 1)
#define GICV5_OP_GIC_CDEN		sys_insn(1, 0, 12, 1, 1)
#define GICV5_OP_GIC_CDEOI		sys_insn(1, 0, 12, 1, 7)
#define GICV5_OP_GIC_CDPEND		sys_insn(1, 0, 12, 1, 4)
#define GICV5_OP_GIC_CDPRI		sys_insn(1, 0, 12, 1, 2)
#define GICV5_OP_GIC_CDRCFG		sys_insn(1, 0, 12, 1, 5)
#define GICV5_OP_GICR_CDIA		sys_insn(1, 0, 12, 3, 0)
#define GICV5_OP_GICR_CDNMIA		sys_insn(1, 0, 12, 3, 1)

/* Definitions for GIC CDAFF */
#define GICV5_GIC_CDAFF_IAFFID_MASK	GENMASK_ULL(47, 32)
#define GICV5_GIC_CDAFF_TYPE_MASK	GENMASK_ULL(31, 29)
#define GICV5_GIC_CDAFF_IRM_MASK	BIT_ULL(28)
#define GICV5_GIC_CDAFF_ID_MASK		GENMASK_ULL(23, 0)

/* Definitions for GIC CDDI */
#define GICV5_GIC_CDDI_TYPE_MASK	GENMASK_ULL(31, 29)
#define GICV5_GIC_CDDI_ID_MASK		GENMASK_ULL(23, 0)

/* Definitions for GIC CDDIS */
#define GICV5_GIC_CDDIS_TYPE_MASK	GENMASK_ULL(31, 29)
#define GICV5_GIC_CDDIS_TYPE(r)		FIELD_GET(GICV5_GIC_CDDIS_TYPE_MASK, r)
#define GICV5_GIC_CDDIS_ID_MASK		GENMASK_ULL(23, 0)
#define GICV5_GIC_CDDIS_ID(r)		FIELD_GET(GICV5_GIC_CDDIS_ID_MASK, r)

/* Definitions for GIC CDEN */
#define GICV5_GIC_CDEN_TYPE_MASK	GENMASK_ULL(31, 29)
#define GICV5_GIC_CDEN_ID_MASK		GENMASK_ULL(23, 0)

/* Definitions for GIC CDHM */
#define GICV5_GIC_CDHM_HM_MASK		BIT_ULL(32)
#define GICV5_GIC_CDHM_TYPE_MASK	GENMASK_ULL(31, 29)
#define GICV5_GIC_CDHM_ID_MASK		GENMASK_ULL(23, 0)

/* Definitions for GIC CDPEND */
#define GICV5_GIC_CDPEND_PENDING_MASK	BIT_ULL(32)
#define GICV5_GIC_CDPEND_TYPE_MASK	GENMASK_ULL(31, 29)
#define GICV5_GIC_CDPEND_ID_MASK	GENMASK_ULL(23, 0)

/* Definitions for GIC CDPRI */
#define GICV5_GIC_CDPRI_PRIORITY_MASK	GENMASK_ULL(39, 35)
#define GICV5_GIC_CDPRI_TYPE_MASK	GENMASK_ULL(31, 29)
#define GICV5_GIC_CDPRI_ID_MASK		GENMASK_ULL(23, 0)

/* Definitions for GIC CDRCFG */
#define GICV5_GIC_CDRCFG_TYPE_MASK	GENMASK_ULL(31, 29)
#define GICV5_GIC_CDRCFG_ID_MASK	GENMASK_ULL(23, 0)

/* Definitions for GICR CDIA */
#define GICV5_GICR_CDIA_VALID_MASK	BIT_ULL(32)
#define GICV5_GICR_CDIA_VALID(r)	FIELD_GET(GICV5_GICR_CDIA_VALID_MASK, r)
#define GICV5_GICR_CDIA_TYPE_MASK	GENMASK_ULL(31, 29)
#define GICV5_GICR_CDIA_ID_MASK		GENMASK_ULL(23, 0)
#define GICV5_GICR_CDIA_INTID		GENMASK_ULL(31, 0)

/* Definitions for GICR CDNMIA */
#define GICV5_GICR_CDNMIA_VALID_MASK	BIT_ULL(32)
#define GICV5_GICR_CDNMIA_VALID(r)	FIELD_GET(GICV5_GICR_CDNMIA_VALID_MASK, r)
#define GICV5_GICR_CDNMIA_TYPE_MASK	GENMASK_ULL(31, 29)
#define GICV5_GICR_CDNMIA_ID_MASK	GENMASK_ULL(23, 0)

#define GICV5_HWIRQ_TYPE		GENMASK_ULL(31, 29)
#define GICV5_HWIRQ_ID			GENMASK_ULL(23, 0)
#define GICV5_HWIRQ_TYPE_LPI		0x2
#define GICV5_HWIRQ_TYPE_SPI		0x3

#define gicr_insn(insn)			read_sysreg_s(GICV5_OP_GICR_##insn)
#define gic_insn(v, insn)		write_sysreg_s(v, GICV5_OP_GIC_##insn)

#define __GIC_BARRIER_INSN(op0, op1, CRn, CRm, op2, Rt)			\
	__emit_inst(0xd5000000					|	\
		    sys_insn((op0), (op1), (CRn), (CRm), (op2))	|	\
		    ((Rt) & 0x1f))

#define GSB_SYS_BARRIER_INSN		__GIC_BARRIER_INSN(1, 0, 12, 0, 0, 31)
#define GSB_ACK_BARRIER_INSN		__GIC_BARRIER_INSN(1, 0, 12, 0, 1, 31)

#define gsb_ack()	asm volatile(GSB_ACK_BARRIER_INSN : : : "memory")
#define gsb_sys()	asm volatile(GSB_SYS_BARRIER_INSN : : : "memory")

#define REPEAT_BYTE(x)	((~0ul / 0xff) * (x))

#define GICV5_IRQ_DEFAULT_PRI 0b10000

#define GICV5_ARCH_PPI_SW_PPI		0x3

void gicv5_ppi_priority_init(void)
{
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR0_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR1_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR2_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR3_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR4_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR5_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR6_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR7_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR8_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR9_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR10_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR11_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR12_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR13_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR14_EL1);
	write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR15_EL1);

	/*
	 * Context syncronization required to make sure system register writes
	 * effects are synchronised.
	 */
	isb();
}

void gicv5_cpu_disable_interrupts(void)
{
	u64 cr0;

	cr0 = FIELD_PREP(ICC_CR0_EL1_EN, 0);
	write_sysreg_s(cr0, SYS_ICC_CR0_EL1);
}

void gicv5_cpu_enable_interrupts(void)
{
	u64 cr0, pcr;

	write_sysreg_s(0, SYS_ICC_PPI_ENABLER0_EL1);
	write_sysreg_s(0, SYS_ICC_PPI_ENABLER1_EL1);

	gicv5_ppi_priority_init();

	pcr = FIELD_PREP(ICC_PCR_EL1_PRIORITY, GICV5_IRQ_DEFAULT_PRI);
	write_sysreg_s(pcr, SYS_ICC_PCR_EL1);

	cr0 = FIELD_PREP(ICC_CR0_EL1_EN, 1);
	write_sysreg_s(cr0, SYS_ICC_CR0_EL1);
}

#endif