Skip to content

Commit 38371db

Browse files
committed
feat(arm/vgic): add vgic reset functions
Signed-off-by: Jose Martins <[email protected]>
1 parent 5982a8d commit 38371db

File tree

6 files changed

+162
-47
lines changed

6 files changed

+162
-47
lines changed

src/arch/armv8/aarch64/inc/arch/subarch/sysregs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ SYSREG_GEN_ACCESSORS(icc_iar1_el1)
9999
SYSREG_GEN_ACCESSORS(icc_eoir1_el1)
100100
SYSREG_GEN_ACCESSORS(icc_dir_el1)
101101
SYSREG_GEN_ACCESSORS(ich_vtr_el2)
102+
SYSREG_GEN_ACCESSORS(ich_vmcr_el2)
102103
SYSREG_GEN_ACCESSORS(icc_sre_el2)
103104
SYSREG_GEN_ACCESSORS(icc_pmr_el1)
104105
SYSREG_GEN_ACCESSORS(icc_bpr1_el1)

src/arch/armv8/inc/arch/gicv2.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ static inline uint64_t gich_get_elrsr()
5959
return elsr;
6060
}
6161

62+
static inline uint32_t gich_get_vmcr()
63+
{
64+
return gich->VMCR;
65+
}
66+
67+
static inline void gich_set_vmcr(uint32_t vmcr)
68+
{
69+
gich->VMCR = vmcr;
70+
}
71+
6272
static inline uint32_t gicc_iar()
6373
{
6474
return gicc->IAR;

src/arch/armv8/inc/arch/gicv3.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,16 @@ static inline uint64_t gich_get_elrsr()
137137
return sysreg_ich_elrsr_el2_read();
138138
}
139139

140+
static inline uint32_t gich_get_vmcr()
141+
{
142+
return (uint32_t)sysreg_ich_vmcr_el2_read();
143+
}
144+
145+
static inline void gich_set_vmcr(uint32_t vmcr)
146+
{
147+
sysreg_ich_vmcr_el2_write(vmcr);
148+
}
149+
140150
static inline uint32_t gicc_iar()
141151
{
142152
return (uint32_t)sysreg_icc_iar1_el1_read();

src/arch/armv8/inc/arch/vgic.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,7 @@ bool vgic_int_has_other_target(struct vcpu* vcpu, struct vgic_int* interrupt);
126126
uint8_t vgic_int_ptarget_mask(struct vcpu* vcpu, struct vgic_int* interrupt);
127127
void vgic_inject_sgi(struct vcpu* vcpu, struct vgic_int* interrupt, vcpuid_t source);
128128

129+
void vgic_reset(struct vm* vm);
130+
void vgic_cpu_reset(struct vcpu* vcpu);
131+
129132
#endif /* __VGIC_H__ */

src/arch/armv8/vgicv2.c

Lines changed: 68 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <arch/vgic.h>
77
#include <arch/vgicv2.h>
88

9+
#include <arch/gicv2.h>
10+
911
#include <bit.h>
1012
#include <spinlock.h>
1113
#include <cpu.h>
@@ -140,6 +142,69 @@ void vgic_inject_sgi(struct vcpu* vcpu, struct vgic_int* interrupt, vcpuid_t sou
140142
spin_unlock(&interrupt->lock);
141143
}
142144

145+
void vgic_cpu_reset(struct vcpu* vcpu)
146+
{
147+
for (irqid_t i = 0; i < GIC_CPU_PRIV; i++) {
148+
vcpu->arch.vgic_priv.interrupts[i].owner = vcpu;
149+
vcpu->arch.vgic_priv.interrupts[i].lock = SPINLOCK_INITVAL;
150+
vcpu->arch.vgic_priv.interrupts[i].state = INV;
151+
vcpu->arch.vgic_priv.interrupts[i].prio = GIC_LOWEST_PRIO;
152+
vcpu->arch.vgic_priv.interrupts[i].cfg = 0;
153+
vcpu->arch.vgic_priv.interrupts[i].sgi.act = 0;
154+
vcpu->arch.vgic_priv.interrupts[i].sgi.pend = 0;
155+
vcpu->arch.vgic_priv.interrupts[i].in_lr = false;
156+
vcpu->arch.vgic_priv.interrupts[i].enabled = false;
157+
158+
if (vcpu->arch.vgic_priv.interrupts[i].hw) {
159+
gic_set_enable(i, false);
160+
gic_set_prio(i, GIC_LOWEST_PRIO);
161+
gic_set_act(i, false);
162+
gic_set_pend(i, false);
163+
}
164+
}
165+
166+
for (irqid_t i = 0; i < GIC_MAX_SGIS; i++) {
167+
vcpu->arch.vgic_priv.interrupts[i].enabled = true;
168+
}
169+
170+
for (size_t i = 0; i < gich_num_lrs(); i++) {
171+
gich_write_lr(i, 0);
172+
}
173+
174+
// gich_set_hcr(0);
175+
gich_set_vmcr(0);
176+
// TODO: reset gich apr registers
177+
178+
list_init(&vcpu->arch.vgic_spilled);
179+
}
180+
181+
void vgic_reset(struct vm* vm)
182+
{
183+
for (irqid_t i = 0; i < vm->arch.vgicd.int_num; i++) {
184+
vm->arch.vgicd.interrupts[i].owner = NULL;
185+
vm->arch.vgicd.interrupts[i].lock = SPINLOCK_INITVAL;
186+
vm->arch.vgicd.interrupts[i].state = INV;
187+
vm->arch.vgicd.interrupts[i].prio = GIC_LOWEST_PRIO;
188+
vm->arch.vgicd.interrupts[i].cfg = 0;
189+
vm->arch.vgicd.interrupts[i].targets = 0;
190+
vm->arch.vgicd.interrupts[i].in_lr = false;
191+
vm->arch.vgicd.interrupts[i].enabled = false;
192+
193+
if (vm->arch.vgicd.interrupts[i].hw) {
194+
irqid_t id = vm->arch.vgicd.interrupts[i].id;
195+
gic_set_enable(id, false);
196+
gic_set_prio(id, GIC_LOWEST_PRIO);
197+
gic_set_act(id, false);
198+
gic_set_pend(id, false);
199+
}
200+
}
201+
202+
vm->arch.vgicd.CTLR = 0;
203+
204+
list_init(&vm->arch.vgic_spilled);
205+
vm->arch.vgic_spilled_lock = SPINLOCK_INITVAL;
206+
}
207+
143208
void vgic_init(struct vm* vm, const struct vgic_dscrp* vgic_dscrp)
144209
{
145210
vm->arch.vgicd.CTLR = 0;
@@ -160,46 +225,29 @@ void vgic_init(struct vm* vm, const struct vgic_dscrp* vgic_dscrp)
160225
}
161226

162227
for (irqid_t i = 0; i < vm->arch.vgicd.int_num; i++) {
163-
vm->arch.vgicd.interrupts[i].owner = NULL;
164-
vm->arch.vgicd.interrupts[i].lock = SPINLOCK_INITVAL;
165228
vm->arch.vgicd.interrupts[i].id = i + GIC_CPU_PRIV;
166-
vm->arch.vgicd.interrupts[i].state = INV;
167-
vm->arch.vgicd.interrupts[i].prio = GIC_LOWEST_PRIO;
168-
vm->arch.vgicd.interrupts[i].cfg = 0;
169-
vm->arch.vgicd.interrupts[i].targets = 0;
170229
vm->arch.vgicd.interrupts[i].hw = false;
171-
vm->arch.vgicd.interrupts[i].in_lr = false;
172-
vm->arch.vgicd.interrupts[i].enabled = false;
173230
}
174231

175232
vm->arch.vgicd_emul = (struct emul_mem){ .va_base = vgic_dscrp->gicd_addr,
176233
.size = ALIGN(sizeof(struct gicd_hw), PAGE_SIZE),
177234
.handler = vgicd_emul_handler };
178235
vm_emul_add_mem(vm, &vm->arch.vgicd_emul);
179236

180-
list_init(&vm->arch.vgic_spilled);
181-
vm->arch.vgic_spilled_lock = SPINLOCK_INITVAL;
237+
vgic_reset(vm);
182238
}
183239

184240
void vgic_cpu_init(struct vcpu* vcpu)
185241
{
186242
for (irqid_t i = 0; i < GIC_CPU_PRIV; i++) {
187-
vcpu->arch.vgic_priv.interrupts[i].owner = vcpu;
188-
vcpu->arch.vgic_priv.interrupts[i].lock = SPINLOCK_INITVAL;
189243
vcpu->arch.vgic_priv.interrupts[i].id = i;
190-
vcpu->arch.vgic_priv.interrupts[i].state = INV;
191-
vcpu->arch.vgic_priv.interrupts[i].prio = GIC_LOWEST_PRIO;
192-
vcpu->arch.vgic_priv.interrupts[i].cfg = 0;
193-
vcpu->arch.vgic_priv.interrupts[i].sgi.act = 0;
194-
vcpu->arch.vgic_priv.interrupts[i].sgi.pend = 0;
195244
vcpu->arch.vgic_priv.interrupts[i].hw = false;
196-
vcpu->arch.vgic_priv.interrupts[i].in_lr = false;
197-
vcpu->arch.vgic_priv.interrupts[i].enabled = false;
245+
vcpu->arch.vgic_priv.interrupts[i].targets = (uint8_t)(1UL << cpu()->id);
198246
}
199247

200248
for (size_t i = 0; i < GIC_MAX_SGIS; i++) {
201249
vcpu->arch.vgic_priv.interrupts[i].enabled = true;
202250
}
203251

204-
list_init(&vcpu->arch.vgic_spilled);
252+
vgic_cpu_reset(vcpu);
205253
}

src/arch/armv8/vgicv3.c

Lines changed: 70 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <arch/vgic.h>
77
#include <arch/vgicv3.h>
88

9+
#include <arch/gicv3.h>
10+
911
#include <bit.h>
1012
#include <spinlock.h>
1113
#include <cpu.h>
@@ -318,10 +320,75 @@ static bool vgic_icc_sre_handler(struct emul_access* acc)
318320
return true;
319321
}
320322

323+
void vgic_cpu_reset(struct vcpu* vcpu)
324+
{
325+
for (irqid_t i = 0; i < GIC_CPU_PRIV; i++) {
326+
vcpu->arch.vgic_priv.interrupts[i].owner = NULL;
327+
vcpu->arch.vgic_priv.interrupts[i].lock = SPINLOCK_INITVAL;
328+
vcpu->arch.vgic_priv.interrupts[i].state = INV;
329+
vcpu->arch.vgic_priv.interrupts[i].prio = GIC_LOWEST_PRIO;
330+
vcpu->arch.vgic_priv.interrupts[i].cfg = 0;
331+
vcpu->arch.vgic_priv.interrupts[i].route = GICD_IROUTER_INV;
332+
vcpu->arch.vgic_priv.interrupts[i].phys.redist = vcpu->phys_id;
333+
vcpu->arch.vgic_priv.interrupts[i].in_lr = false;
334+
vcpu->arch.vgic_priv.interrupts[i].enabled = false;
335+
336+
if (vcpu->arch.vgic_priv.interrupts[i].hw) {
337+
gic_set_enable(i, false);
338+
gic_set_prio(i, GIC_LOWEST_PRIO);
339+
gic_set_act(i, false);
340+
gic_set_pend(i, false);
341+
// gicd_set_route(i, GICD_IROUTER_INV);
342+
}
343+
}
344+
345+
for (irqid_t i = 0; i < GIC_MAX_SGIS; i++) {
346+
vcpu->arch.vgic_priv.interrupts[i].cfg = 0x2;
347+
}
348+
349+
for (size_t i = 0; i < gich_num_lrs(); i++) {
350+
gich_write_lr(i, 0);
351+
}
352+
353+
// gich_set_hcr(0);
354+
gich_set_vmcr(0);
355+
// TODO: reset gich apr registers
356+
357+
list_init(&vcpu->arch.vgic_spilled);
358+
}
359+
360+
void vgic_reset(struct vm* vm)
361+
{
362+
for (irqid_t i = 0; i < vm->arch.vgicd.int_num; i++) {
363+
vm->arch.vgicd.interrupts[i].owner = NULL;
364+
vm->arch.vgicd.interrupts[i].lock = SPINLOCK_INITVAL;
365+
vm->arch.vgicd.interrupts[i].state = INV;
366+
vm->arch.vgicd.interrupts[i].prio = GIC_LOWEST_PRIO;
367+
vm->arch.vgicd.interrupts[i].cfg = 0;
368+
vm->arch.vgicd.interrupts[i].route = GICD_IROUTER_INV;
369+
vm->arch.vgicd.interrupts[i].phys.route = GICD_IROUTER_INV;
370+
vm->arch.vgicd.interrupts[i].in_lr = false;
371+
vm->arch.vgicd.interrupts[i].enabled = false;
372+
373+
if (vm->arch.vgicd.interrupts[i].hw) {
374+
irqid_t id = i + GIC_CPU_PRIV;
375+
gic_set_enable(id, false);
376+
gic_set_prio(id, GIC_LOWEST_PRIO);
377+
gic_set_act(id, false);
378+
gic_set_pend(id, false);
379+
gicd_set_route(id, GICD_IROUTER_INV);
380+
}
381+
}
382+
383+
vm->arch.vgicd.CTLR = 0;
384+
385+
list_init(&vm->arch.vgic_spilled);
386+
vm->arch.vgic_spilled_lock = SPINLOCK_INITVAL;
387+
}
388+
321389
void vgic_init(struct vm* vm, const struct vgic_dscrp* vgic_dscrp)
322390
{
323391
vm->arch.vgicr_addr = vgic_dscrp->gicr_addr;
324-
vm->arch.vgicd.CTLR = 0;
325392
size_t vtyper_itln = vgic_get_itln(vgic_dscrp);
326393
vm->arch.vgicd.int_num = 32 * (vtyper_itln + 1);
327394
vm->arch.vgicd.TYPER = ((vtyper_itln << GICD_TYPER_ITLN_OFF) & GICD_TYPER_ITLN_MSK) |
@@ -336,17 +403,8 @@ void vgic_init(struct vm* vm, const struct vgic_dscrp* vgic_dscrp)
336403
}
337404

338405
for (irqid_t i = 0; i < vm->arch.vgicd.int_num; i++) {
339-
vm->arch.vgicd.interrupts[i].owner = NULL;
340-
vm->arch.vgicd.interrupts[i].lock = SPINLOCK_INITVAL;
341406
vm->arch.vgicd.interrupts[i].id = i + GIC_CPU_PRIV;
342-
vm->arch.vgicd.interrupts[i].state = INV;
343-
vm->arch.vgicd.interrupts[i].prio = GIC_LOWEST_PRIO;
344-
vm->arch.vgicd.interrupts[i].cfg = 0;
345-
vm->arch.vgicd.interrupts[i].route = GICD_IROUTER_INV;
346-
vm->arch.vgicd.interrupts[i].phys.route = GICD_IROUTER_INV;
347407
vm->arch.vgicd.interrupts[i].hw = false;
348-
vm->arch.vgicd.interrupts[i].in_lr = false;
349-
vm->arch.vgicd.interrupts[i].enabled = false;
350408
}
351409

352410
vm->arch.vgicd_emul = (struct emul_mem){ .va_base = vgic_dscrp->gicd_addr,
@@ -377,29 +435,14 @@ void vgic_init(struct vm* vm, const struct vgic_dscrp* vgic_dscrp)
377435
.handler = vgic_icc_sre_handler };
378436
vm_emul_add_reg(vm, &vm->arch.icc_sre_emul);
379437

380-
list_init(&vm->arch.vgic_spilled);
381-
vm->arch.vgic_spilled_lock = SPINLOCK_INITVAL;
438+
vgic_reset(vm);
382439
}
383440

384441
void vgic_cpu_init(struct vcpu* vcpu)
385442
{
386443
for (irqid_t i = 0; i < GIC_CPU_PRIV; i++) {
387-
vcpu->arch.vgic_priv.interrupts[i].owner = NULL;
388-
vcpu->arch.vgic_priv.interrupts[i].lock = SPINLOCK_INITVAL;
389444
vcpu->arch.vgic_priv.interrupts[i].id = i;
390-
vcpu->arch.vgic_priv.interrupts[i].state = INV;
391-
vcpu->arch.vgic_priv.interrupts[i].prio = GIC_LOWEST_PRIO;
392-
vcpu->arch.vgic_priv.interrupts[i].cfg = 0;
393-
vcpu->arch.vgic_priv.interrupts[i].route = GICD_IROUTER_INV;
394-
vcpu->arch.vgic_priv.interrupts[i].phys.redist = vcpu->phys_id;
395-
vcpu->arch.vgic_priv.interrupts[i].hw = false;
396-
vcpu->arch.vgic_priv.interrupts[i].in_lr = false;
397-
vcpu->arch.vgic_priv.interrupts[i].enabled = false;
398445
}
399446

400-
for (irqid_t i = 0; i < GIC_MAX_SGIS; i++) {
401-
vcpu->arch.vgic_priv.interrupts[i].cfg = 0x2;
402-
}
403-
404-
list_init(&vcpu->arch.vgic_spilled);
447+
vgic_cpu_reset(vcpu);
405448
}

0 commit comments

Comments
 (0)