To implement the get/set_irqchip_state callbacks (limited to the PENDING state), we have to use a particular set of hacks: - Reading the pending state is done by using a pair of new redistributor registers (GICR_VSGIR, GICR_VSGIPENDR), which allow the 16 interrupts state to be retrieved. - Setting the pending state is done by generating it as we'd otherwise do for a guest (writing to GITS_SGIR). - Clearing the pending state is done by emitting a VSGI command with the "clear" bit set. This requires some interesting locking though: - When talking to the redistributor, we must make sure that the VPE affinity doesn't change, hence taking the VPE lock. - At the same time, we must ensure that nobody accesses the same redistributor's GICR_VSGIR registers for a different VPE, which would corrupt the reading of the pending bits. We thus take the per-RD spinlock. Much fun.
Showing the changes to include/linux (1 of 2 files). Show all
Unified · Split
| @@ -345,6 +345,15 @@ · 344 unmodified lines | ||
| 345 | 345 | #define GICR_VPENDBASER_4_1_VGRP1EN (1ULL << 58) |
| 346 | 346 | #define GICR_VPENDBASER_4_1_VPEID GENMASK_ULL(15, 0) |
| 347 | 347 | |
| 348 | +#define GICR_VSGIR 0x0080 | |
| 349 | + | |
| 350 | +#define GICR_VSGIR_VPEID GENMASK(15, 0) | |
| 351 | + | |
| 352 | +#define GICR_VSGIPENDR 0x0088 | |
| 353 | + | |
| 354 | +#define GICR_VSGIPENDR_BUSY (1U << 31) | |
| 355 | +#define GICR_VSGIPENDR_PENDING GENMASK(15, 0) | |
| 356 | + | |
| 348 | 357 | /* |
| 349 | 358 | * ITS registers, offsets from ITS_base |
| 350 | 359 | */ |
| @@ -368,6 +377,11 @@ · 17 unmodified lines | ||
| 368 | 377 | |
| 369 | 378 | #define GITS_TRANSLATER 0x10040 |
| 370 | 379 | |
| 380 | +#define GITS_SGIR 0x20020 | |
| 381 | + | |
| 382 | +#define GITS_SGIR_VPEID GENMASK_ULL(47, 32) | |
| 383 | +#define GITS_SGIR_VINTID GENMASK_ULL(3, 0) | |
| 384 | + | |
| 371 | 385 | #define GITS_CTLR_ENABLE (1U << 0) |
| 372 | 386 | #define GITS_CTLR_ImDe (1U << 1) |
| 373 | 387 | #define GITS_CTLR_ITS_NUMBER_SHIFT 4 |