Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/arm64/kvm/hyp/vgic-v5-sr.c
170959 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Copyright (C) 2025, 2026 - Arm Ltd
4
*/
5
6
#include <linux/irqchip/arm-gic-v5.h>
7
8
#include <asm/kvm_hyp.h>
9
10
void __vgic_v5_save_apr(struct vgic_v5_cpu_if *cpu_if)
11
{
12
cpu_if->vgic_apr = read_sysreg_s(SYS_ICH_APR_EL2);
13
}
14
15
static void __vgic_v5_compat_mode_disable(void)
16
{
17
sysreg_clear_set_s(SYS_ICH_VCTLR_EL2, ICH_VCTLR_EL2_V3, 0);
18
isb();
19
}
20
21
void __vgic_v5_restore_vmcr_apr(struct vgic_v5_cpu_if *cpu_if)
22
{
23
__vgic_v5_compat_mode_disable();
24
25
write_sysreg_s(cpu_if->vgic_vmcr, SYS_ICH_VMCR_EL2);
26
write_sysreg_s(cpu_if->vgic_apr, SYS_ICH_APR_EL2);
27
}
28
29
void __vgic_v5_save_ppi_state(struct vgic_v5_cpu_if *cpu_if)
30
{
31
/*
32
* The following code assumes that the bitmap storage that we have for
33
* PPIs is either 64 (architected PPIs, only) or 128 bits (architected &
34
* impdef PPIs).
35
*/
36
BUILD_BUG_ON(VGIC_V5_NR_PRIVATE_IRQS % 64);
37
38
bitmap_write(host_data_ptr(vgic_v5_ppi_state)->activer_exit,
39
read_sysreg_s(SYS_ICH_PPI_ACTIVER0_EL2), 0, 64);
40
bitmap_write(host_data_ptr(vgic_v5_ppi_state)->pendr,
41
read_sysreg_s(SYS_ICH_PPI_PENDR0_EL2), 0, 64);
42
43
cpu_if->vgic_ppi_priorityr[0] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR0_EL2);
44
cpu_if->vgic_ppi_priorityr[1] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR1_EL2);
45
cpu_if->vgic_ppi_priorityr[2] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR2_EL2);
46
cpu_if->vgic_ppi_priorityr[3] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR3_EL2);
47
cpu_if->vgic_ppi_priorityr[4] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR4_EL2);
48
cpu_if->vgic_ppi_priorityr[5] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR5_EL2);
49
cpu_if->vgic_ppi_priorityr[6] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR6_EL2);
50
cpu_if->vgic_ppi_priorityr[7] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR7_EL2);
51
52
if (VGIC_V5_NR_PRIVATE_IRQS == 128) {
53
bitmap_write(host_data_ptr(vgic_v5_ppi_state)->activer_exit,
54
read_sysreg_s(SYS_ICH_PPI_ACTIVER1_EL2), 64, 64);
55
bitmap_write(host_data_ptr(vgic_v5_ppi_state)->pendr,
56
read_sysreg_s(SYS_ICH_PPI_PENDR1_EL2), 64, 64);
57
58
cpu_if->vgic_ppi_priorityr[8] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR8_EL2);
59
cpu_if->vgic_ppi_priorityr[9] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR9_EL2);
60
cpu_if->vgic_ppi_priorityr[10] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR10_EL2);
61
cpu_if->vgic_ppi_priorityr[11] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR11_EL2);
62
cpu_if->vgic_ppi_priorityr[12] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR12_EL2);
63
cpu_if->vgic_ppi_priorityr[13] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR13_EL2);
64
cpu_if->vgic_ppi_priorityr[14] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR14_EL2);
65
cpu_if->vgic_ppi_priorityr[15] = read_sysreg_s(SYS_ICH_PPI_PRIORITYR15_EL2);
66
}
67
68
/* Now that we are done, disable DVI */
69
write_sysreg_s(0, SYS_ICH_PPI_DVIR0_EL2);
70
write_sysreg_s(0, SYS_ICH_PPI_DVIR1_EL2);
71
}
72
73
void __vgic_v5_restore_ppi_state(struct vgic_v5_cpu_if *cpu_if)
74
{
75
DECLARE_BITMAP(pendr, VGIC_V5_NR_PRIVATE_IRQS);
76
77
/* We assume 64 or 128 PPIs - see above comment */
78
BUILD_BUG_ON(VGIC_V5_NR_PRIVATE_IRQS % 64);
79
80
/* Enable DVI so that the guest's interrupt config takes over */
81
write_sysreg_s(bitmap_read(cpu_if->vgic_ppi_dvir, 0, 64),
82
SYS_ICH_PPI_DVIR0_EL2);
83
84
write_sysreg_s(bitmap_read(cpu_if->vgic_ppi_activer, 0, 64),
85
SYS_ICH_PPI_ACTIVER0_EL2);
86
write_sysreg_s(bitmap_read(cpu_if->vgic_ppi_enabler, 0, 64),
87
SYS_ICH_PPI_ENABLER0_EL2);
88
89
/* Update the pending state of the NON-DVI'd PPIs, only */
90
bitmap_andnot(pendr, host_data_ptr(vgic_v5_ppi_state)->pendr,
91
cpu_if->vgic_ppi_dvir, VGIC_V5_NR_PRIVATE_IRQS);
92
write_sysreg_s(bitmap_read(pendr, 0, 64), SYS_ICH_PPI_PENDR0_EL2);
93
94
write_sysreg_s(cpu_if->vgic_ppi_priorityr[0],
95
SYS_ICH_PPI_PRIORITYR0_EL2);
96
write_sysreg_s(cpu_if->vgic_ppi_priorityr[1],
97
SYS_ICH_PPI_PRIORITYR1_EL2);
98
write_sysreg_s(cpu_if->vgic_ppi_priorityr[2],
99
SYS_ICH_PPI_PRIORITYR2_EL2);
100
write_sysreg_s(cpu_if->vgic_ppi_priorityr[3],
101
SYS_ICH_PPI_PRIORITYR3_EL2);
102
write_sysreg_s(cpu_if->vgic_ppi_priorityr[4],
103
SYS_ICH_PPI_PRIORITYR4_EL2);
104
write_sysreg_s(cpu_if->vgic_ppi_priorityr[5],
105
SYS_ICH_PPI_PRIORITYR5_EL2);
106
write_sysreg_s(cpu_if->vgic_ppi_priorityr[6],
107
SYS_ICH_PPI_PRIORITYR6_EL2);
108
write_sysreg_s(cpu_if->vgic_ppi_priorityr[7],
109
SYS_ICH_PPI_PRIORITYR7_EL2);
110
111
if (VGIC_V5_NR_PRIVATE_IRQS == 128) {
112
/* Enable DVI so that the guest's interrupt config takes over */
113
write_sysreg_s(bitmap_read(cpu_if->vgic_ppi_dvir, 64, 64),
114
SYS_ICH_PPI_DVIR1_EL2);
115
116
write_sysreg_s(bitmap_read(cpu_if->vgic_ppi_activer, 64, 64),
117
SYS_ICH_PPI_ACTIVER1_EL2);
118
write_sysreg_s(bitmap_read(cpu_if->vgic_ppi_enabler, 64, 64),
119
SYS_ICH_PPI_ENABLER1_EL2);
120
write_sysreg_s(bitmap_read(pendr, 64, 64),
121
SYS_ICH_PPI_PENDR1_EL2);
122
123
write_sysreg_s(cpu_if->vgic_ppi_priorityr[8],
124
SYS_ICH_PPI_PRIORITYR8_EL2);
125
write_sysreg_s(cpu_if->vgic_ppi_priorityr[9],
126
SYS_ICH_PPI_PRIORITYR9_EL2);
127
write_sysreg_s(cpu_if->vgic_ppi_priorityr[10],
128
SYS_ICH_PPI_PRIORITYR10_EL2);
129
write_sysreg_s(cpu_if->vgic_ppi_priorityr[11],
130
SYS_ICH_PPI_PRIORITYR11_EL2);
131
write_sysreg_s(cpu_if->vgic_ppi_priorityr[12],
132
SYS_ICH_PPI_PRIORITYR12_EL2);
133
write_sysreg_s(cpu_if->vgic_ppi_priorityr[13],
134
SYS_ICH_PPI_PRIORITYR13_EL2);
135
write_sysreg_s(cpu_if->vgic_ppi_priorityr[14],
136
SYS_ICH_PPI_PRIORITYR14_EL2);
137
write_sysreg_s(cpu_if->vgic_ppi_priorityr[15],
138
SYS_ICH_PPI_PRIORITYR15_EL2);
139
} else {
140
write_sysreg_s(0, SYS_ICH_PPI_DVIR1_EL2);
141
142
write_sysreg_s(0, SYS_ICH_PPI_ACTIVER1_EL2);
143
write_sysreg_s(0, SYS_ICH_PPI_ENABLER1_EL2);
144
write_sysreg_s(0, SYS_ICH_PPI_PENDR1_EL2);
145
146
write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR8_EL2);
147
write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR9_EL2);
148
write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR10_EL2);
149
write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR11_EL2);
150
write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR12_EL2);
151
write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR13_EL2);
152
write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR14_EL2);
153
write_sysreg_s(0, SYS_ICH_PPI_PRIORITYR15_EL2);
154
}
155
}
156
157
void __vgic_v5_save_state(struct vgic_v5_cpu_if *cpu_if)
158
{
159
cpu_if->vgic_vmcr = read_sysreg_s(SYS_ICH_VMCR_EL2);
160
cpu_if->vgic_icsr = read_sysreg_s(SYS_ICC_ICSR_EL1);
161
}
162
163
void __vgic_v5_restore_state(struct vgic_v5_cpu_if *cpu_if)
164
{
165
write_sysreg_s(cpu_if->vgic_icsr, SYS_ICC_ICSR_EL1);
166
}
167
168