Skip to content

Commit 17ce617

Browse files
Ricardo KollerMarc Zyngier
authored andcommitted
KVM: selftests: aarch64: Add GICv3 register accessor library functions
Add library functions for accessing GICv3 registers: DIR, PMR, CTLR, ISACTIVER, ISPENDR. Signed-off-by: Ricardo Koller <[email protected]> Acked-by: Andrew Jones <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 7450683 commit 17ce617

File tree

5 files changed

+189
-6
lines changed

5 files changed

+189
-6
lines changed

tools/testing/selftests/kvm/include/aarch64/gic.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,21 @@ void gic_irq_enable(unsigned int intid);
1717
void gic_irq_disable(unsigned int intid);
1818
unsigned int gic_get_and_ack_irq(void);
1919
void gic_set_eoi(unsigned int intid);
20+
void gic_set_dir(unsigned int intid);
21+
22+
/*
23+
* Sets the EOI mode. When split is false, EOI just drops the priority. When
24+
* split is true, EOI drops the priority and deactivates the interrupt.
25+
*/
26+
void gic_set_eoi_split(bool split);
27+
void gic_set_priority_mask(uint64_t mask);
28+
void gic_set_priority(uint32_t intid, uint32_t prio);
29+
void gic_irq_set_active(unsigned int intid);
30+
void gic_irq_clear_active(unsigned int intid);
31+
bool gic_irq_get_active(unsigned int intid);
32+
void gic_irq_set_pending(unsigned int intid);
33+
void gic_irq_clear_pending(unsigned int intid);
34+
bool gic_irq_get_pending(unsigned int intid);
35+
void gic_irq_set_config(unsigned int intid, bool is_edge);
2036

2137
#endif /* SELFTEST_KVM_GIC_H */

tools/testing/selftests/kvm/include/aarch64/gic_v3.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@
1616
#define GICD_IGROUPR 0x0080
1717
#define GICD_ISENABLER 0x0100
1818
#define GICD_ICENABLER 0x0180
19+
#define GICD_ISPENDR 0x0200
20+
#define GICD_ICPENDR 0x0280
1921
#define GICD_ICACTIVER 0x0380
22+
#define GICD_ISACTIVER 0x0300
2023
#define GICD_IPRIORITYR 0x0400
24+
#define GICD_ICFGR 0x0C00
2125

2226
/*
2327
* The assumption is that the guest runs in a non-secure mode.
@@ -49,16 +53,24 @@
4953
#define GICR_IGROUPR0 GICD_IGROUPR
5054
#define GICR_ISENABLER0 GICD_ISENABLER
5155
#define GICR_ICENABLER0 GICD_ICENABLER
56+
#define GICR_ISPENDR0 GICD_ISPENDR
57+
#define GICR_ISACTIVER0 GICD_ISACTIVER
5258
#define GICR_ICACTIVER0 GICD_ICACTIVER
59+
#define GICR_ICENABLER GICD_ICENABLER
60+
#define GICR_ICACTIVER GICD_ICACTIVER
5361
#define GICR_IPRIORITYR0 GICD_IPRIORITYR
5462

5563
/* CPU interface registers */
5664
#define SYS_ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0)
5765
#define SYS_ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
5866
#define SYS_ICC_EOIR1_EL1 sys_reg(3, 0, 12, 12, 1)
67+
#define SYS_ICC_DIR_EL1 sys_reg(3, 0, 12, 11, 1)
68+
#define SYS_ICC_CTLR_EL1 sys_reg(3, 0, 12, 12, 4)
5969
#define SYS_ICC_SRE_EL1 sys_reg(3, 0, 12, 12, 5)
6070
#define SYS_ICC_GRPEN1_EL1 sys_reg(3, 0, 12, 12, 7)
6171

72+
#define SYS_ICV_AP1R0_EL1 sys_reg(3, 0, 12, 9, 0)
73+
6274
#define ICC_PMR_DEF_PRIO 0xf0
6375

6476
#define ICC_SRE_EL1_SRE (1U << 0)

tools/testing/selftests/kvm/lib/aarch64/gic.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,69 @@ void gic_set_eoi(unsigned int intid)
9393
GUEST_ASSERT(gic_common_ops);
9494
gic_common_ops->gic_write_eoir(intid);
9595
}
96+
97+
void gic_set_dir(unsigned int intid)
98+
{
99+
GUEST_ASSERT(gic_common_ops);
100+
gic_common_ops->gic_write_dir(intid);
101+
}
102+
103+
void gic_set_eoi_split(bool split)
104+
{
105+
GUEST_ASSERT(gic_common_ops);
106+
gic_common_ops->gic_set_eoi_split(split);
107+
}
108+
109+
void gic_set_priority_mask(uint64_t pmr)
110+
{
111+
GUEST_ASSERT(gic_common_ops);
112+
gic_common_ops->gic_set_priority_mask(pmr);
113+
}
114+
115+
void gic_set_priority(unsigned int intid, unsigned int prio)
116+
{
117+
GUEST_ASSERT(gic_common_ops);
118+
gic_common_ops->gic_set_priority(intid, prio);
119+
}
120+
121+
void gic_irq_set_active(unsigned int intid)
122+
{
123+
GUEST_ASSERT(gic_common_ops);
124+
gic_common_ops->gic_irq_set_active(intid);
125+
}
126+
127+
void gic_irq_clear_active(unsigned int intid)
128+
{
129+
GUEST_ASSERT(gic_common_ops);
130+
gic_common_ops->gic_irq_clear_active(intid);
131+
}
132+
133+
bool gic_irq_get_active(unsigned int intid)
134+
{
135+
GUEST_ASSERT(gic_common_ops);
136+
return gic_common_ops->gic_irq_get_active(intid);
137+
}
138+
139+
void gic_irq_set_pending(unsigned int intid)
140+
{
141+
GUEST_ASSERT(gic_common_ops);
142+
gic_common_ops->gic_irq_set_pending(intid);
143+
}
144+
145+
void gic_irq_clear_pending(unsigned int intid)
146+
{
147+
GUEST_ASSERT(gic_common_ops);
148+
gic_common_ops->gic_irq_clear_pending(intid);
149+
}
150+
151+
bool gic_irq_get_pending(unsigned int intid)
152+
{
153+
GUEST_ASSERT(gic_common_ops);
154+
return gic_common_ops->gic_irq_get_pending(intid);
155+
}
156+
157+
void gic_irq_set_config(unsigned int intid, bool is_edge)
158+
{
159+
GUEST_ASSERT(gic_common_ops);
160+
gic_common_ops->gic_irq_set_config(intid, is_edge);
161+
}

tools/testing/selftests/kvm/lib/aarch64/gic_private.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ struct gic_common_ops {
1414
void (*gic_irq_disable)(unsigned int intid);
1515
uint64_t (*gic_read_iar)(void);
1616
void (*gic_write_eoir)(uint32_t irq);
17+
void (*gic_write_dir)(uint32_t irq);
18+
void (*gic_set_eoi_split)(bool split);
19+
void (*gic_set_priority_mask)(uint64_t mask);
20+
void (*gic_set_priority)(uint32_t intid, uint32_t prio);
21+
void (*gic_irq_set_active)(uint32_t intid);
22+
void (*gic_irq_clear_active)(uint32_t intid);
23+
bool (*gic_irq_get_active)(uint32_t intid);
24+
void (*gic_irq_set_pending)(uint32_t intid);
25+
void (*gic_irq_clear_pending)(uint32_t intid);
26+
bool (*gic_irq_get_pending)(uint32_t intid);
27+
void (*gic_irq_set_config)(uint32_t intid, bool is_edge);
1728
};
1829

1930
extern const struct gic_common_ops gicv3_ops;

tools/testing/selftests/kvm/lib/aarch64/gic_v3.c

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,29 @@ static void gicv3_write_eoir(uint32_t irq)
9090
isb();
9191
}
9292

93+
static void gicv3_write_dir(uint32_t irq)
94+
{
95+
write_sysreg_s(irq, SYS_ICC_DIR_EL1);
96+
isb();
97+
}
98+
99+
static void gicv3_set_priority_mask(uint64_t mask)
100+
{
101+
write_sysreg_s(mask, SYS_ICC_PMR_EL1);
102+
}
103+
104+
static void gicv3_set_eoi_split(bool split)
105+
{
106+
uint32_t val;
107+
108+
/* All other fields are read-only, so no need to read CTLR first. In
109+
* fact, the kernel does the same.
110+
*/
111+
val = split ? (1U << 1) : 0;
112+
write_sysreg_s(val, SYS_ICC_CTLR_EL1);
113+
isb();
114+
}
115+
93116
uint32_t gicv3_reg_readl(uint32_t cpu_or_dist, uint64_t offset)
94117
{
95118
void *base = cpu_or_dist & DIST_BIT ? gicv3_data.dist_base
@@ -174,26 +197,70 @@ static uint32_t gicv3_read_reg(uint32_t intid, uint64_t offset,
174197
return val;
175198
}
176199

177-
static void gicv3_irq_enable(unsigned int intid)
200+
static void gicv3_set_priority(uint32_t intid, uint32_t prio)
201+
{
202+
gicv3_write_reg(intid, GICD_IPRIORITYR, 32, 8, prio);
203+
}
204+
205+
/* Sets the intid to be level-sensitive or edge-triggered. */
206+
static void gicv3_irq_set_config(uint32_t intid, bool is_edge)
207+
{
208+
uint32_t val;
209+
210+
/* N/A for private interrupts. */
211+
GUEST_ASSERT(get_intid_range(intid) == SPI_RANGE);
212+
val = is_edge ? 2 : 0;
213+
gicv3_write_reg(intid, GICD_ICFGR, 32, 2, val);
214+
}
215+
216+
static void gicv3_irq_enable(uint32_t intid)
178217
{
179218
bool is_spi = get_intid_range(intid) == SPI_RANGE;
180-
unsigned int val = 1;
181219
uint32_t cpu = guest_get_vcpuid();
182220

183-
gicv3_write_reg(intid, GICD_ISENABLER, 32, 1, val);
221+
gicv3_write_reg(intid, GICD_ISENABLER, 32, 1, 1);
184222
gicv3_wait_for_rwp(is_spi ? DIST_BIT : cpu);
185223
}
186224

187-
static void gicv3_irq_disable(unsigned int intid)
225+
static void gicv3_irq_disable(uint32_t intid)
188226
{
189227
bool is_spi = get_intid_range(intid) == SPI_RANGE;
190-
uint32_t val = 1;
191228
uint32_t cpu = guest_get_vcpuid();
192229

193-
gicv3_write_reg(intid, GICD_ICENABLER, 32, 1, val);
230+
gicv3_write_reg(intid, GICD_ICENABLER, 32, 1, 1);
194231
gicv3_wait_for_rwp(is_spi ? DIST_BIT : cpu);
195232
}
196233

234+
static void gicv3_irq_set_active(uint32_t intid)
235+
{
236+
gicv3_write_reg(intid, GICD_ISACTIVER, 32, 1, 1);
237+
}
238+
239+
static void gicv3_irq_clear_active(uint32_t intid)
240+
{
241+
gicv3_write_reg(intid, GICD_ICACTIVER, 32, 1, 1);
242+
}
243+
244+
static bool gicv3_irq_get_active(uint32_t intid)
245+
{
246+
return gicv3_read_reg(intid, GICD_ISACTIVER, 32, 1);
247+
}
248+
249+
static void gicv3_irq_set_pending(uint32_t intid)
250+
{
251+
gicv3_write_reg(intid, GICD_ISPENDR, 32, 1, 1);
252+
}
253+
254+
static void gicv3_irq_clear_pending(uint32_t intid)
255+
{
256+
gicv3_write_reg(intid, GICD_ICPENDR, 32, 1, 1);
257+
}
258+
259+
static bool gicv3_irq_get_pending(uint32_t intid)
260+
{
261+
return gicv3_read_reg(intid, GICD_ISPENDR, 32, 1);
262+
}
263+
197264
static void gicv3_enable_redist(void *redist_base)
198265
{
199266
uint32_t val = readl(redist_base + GICR_WAKER);
@@ -315,4 +382,15 @@ const struct gic_common_ops gicv3_ops = {
315382
.gic_irq_disable = gicv3_irq_disable,
316383
.gic_read_iar = gicv3_read_iar,
317384
.gic_write_eoir = gicv3_write_eoir,
385+
.gic_write_dir = gicv3_write_dir,
386+
.gic_set_priority_mask = gicv3_set_priority_mask,
387+
.gic_set_eoi_split = gicv3_set_eoi_split,
388+
.gic_set_priority = gicv3_set_priority,
389+
.gic_irq_set_active = gicv3_irq_set_active,
390+
.gic_irq_clear_active = gicv3_irq_clear_active,
391+
.gic_irq_get_active = gicv3_irq_get_active,
392+
.gic_irq_set_pending = gicv3_irq_set_pending,
393+
.gic_irq_clear_pending = gicv3_irq_clear_pending,
394+
.gic_irq_get_pending = gicv3_irq_get_pending,
395+
.gic_irq_set_config = gicv3_irq_set_config,
318396
};

0 commit comments

Comments
 (0)