diff --git a/libsel4vm/arch_include/arm/sel4vm/arch/guest_vm_arch.h b/libsel4vm/arch_include/arm/sel4vm/arch/guest_vm_arch.h index e49dcf060..c99bc2e63 100644 --- a/libsel4vm/arch_include/arm/sel4vm/arch/guest_vm_arch.h +++ b/libsel4vm/arch_include/arm/sel4vm/arch/guest_vm_arch.h @@ -23,7 +23,14 @@ typedef int (*unhandled_vcpu_fault_callback_fn)(vm_vcpu_t *vcpu, uint32_t hsr, v #define VM_FAULT_EP_SLOT 1 #define VM_CSPACE_SLOT VM_FAULT_EP_SLOT + CONFIG_MAX_NUM_NODES -struct vm_arch {}; +struct vm_arch { + + /* Details about the GIC context are implementation specific and thus + * completely opaque. All we can provide in the VM data structure is space + * for a context pointer. + */ + void *vgic_context; +}; /*** * @struct vm_vcpu_arch diff --git a/libsel4vm/src/arch/arm/vgic/gicv2.h b/libsel4vm/src/arch/arm/vgic/gicv2.h index da7a122e6..5584b134e 100644 --- a/libsel4vm/src/arch/arm/vgic/gicv2.h +++ b/libsel4vm/src/arch/arm/vgic/gicv2.h @@ -89,3 +89,27 @@ struct gic_dist_map { uint32_t periph_id[12]; /* [0xFC0, 0xFF0) */ uint32_t component_id[4]; /* [0xFF0, 0xFFF] */ }; + +static inline bool gic_dist_is_enabled(vgic_t *vgic) +{ + return (0 != vgic->dist->enable); +} + +static inline void vgic_dist_set_ctlr(vgic_t *vgic, uint32_t data) +{ + /* ToDo: we should care about bit 0 only and ignore all the others. */ + + switch (data) { + case 0: + DDIST("disabling gic distributor\n"); + vgic->dist->enable = 0; + break; + case 1: + DDIST("enabling gic distributor\n"); + vgic->dist->enable = 1; + break; + default: + ZF_LOGE("Unknown dist ctlr encoding 0x%x", data); + break; + } +} diff --git a/libsel4vm/src/arch/arm/vgic/vdist.h b/libsel4vm/src/arch/arm/vgic/vdist.h index 35b971a51..7ccb496d9 100644 --- a/libsel4vm/src/arch/arm/vgic/vdist.h +++ b/libsel4vm/src/arch/arm/vgic/vdist.h @@ -27,139 +27,121 @@ #define IRQ_BIT(irq) (1U << ((irq) % 32)) -static inline void set_sgi_ppi_pending(struct gic_dist_map *gic_dist, int irq, bool set_pending, int vcpu_id) +static inline void set_sgi_ppi_pending(vgic_t *vgic, int irq, bool set_pending, int vcpu_id) { if (set_pending) { - gic_dist->pending_set0[vcpu_id] |= IRQ_BIT(irq); - gic_dist->pending_clr0[vcpu_id] |= IRQ_BIT(irq); + vgic->dist->pending_set0[vcpu_id] |= IRQ_BIT(irq); + vgic->dist->pending_clr0[vcpu_id] |= IRQ_BIT(irq); } else { - gic_dist->pending_set0[vcpu_id] &= ~IRQ_BIT(irq); - gic_dist->pending_clr0[vcpu_id] &= ~IRQ_BIT(irq); + vgic->dist->pending_set0[vcpu_id] &= ~IRQ_BIT(irq); + vgic->dist->pending_clr0[vcpu_id] &= ~IRQ_BIT(irq); } } -static inline void set_spi_pending(struct gic_dist_map *gic_dist, int irq, bool set_pending) +static inline void set_spi_pending(vgic_t *vgic, int irq, bool set_pending) { if (set_pending) { - gic_dist->pending_set[IRQ_IDX(irq)] |= IRQ_BIT(irq); - gic_dist->pending_clr[IRQ_IDX(irq)] |= IRQ_BIT(irq); + vgic->dist->pending_set[IRQ_IDX(irq)] |= IRQ_BIT(irq); + vgic->dist->pending_clr[IRQ_IDX(irq)] |= IRQ_BIT(irq); } else { - gic_dist->pending_set[IRQ_IDX(irq)] &= ~IRQ_BIT(irq); - gic_dist->pending_clr[IRQ_IDX(irq)] &= ~IRQ_BIT(irq); + vgic->dist->pending_set[IRQ_IDX(irq)] &= ~IRQ_BIT(irq); + vgic->dist->pending_clr[IRQ_IDX(irq)] &= ~IRQ_BIT(irq); } } -static inline void set_pending(struct gic_dist_map *gic_dist, int irq, bool set_pending, int vcpu_id) +static inline void set_pending(vgic_t *vgic, int irq, bool set_pending, int vcpu_id) { if (irq < NUM_VCPU_LOCAL_VIRQS) { - set_sgi_ppi_pending(gic_dist, irq, set_pending, vcpu_id); + set_sgi_ppi_pending(vgic->dist, irq, set_pending, vcpu_id); return; } - set_spi_pending(gic_dist, irq, set_pending); + set_spi_pending(vgic->dist, irq, set_pending); } -static inline bool is_sgi_ppi_pending(struct gic_dist_map *gic_dist, int irq, int vcpu_id) +static inline bool is_sgi_ppi_pending(vgic_t *vgic, int irq, int vcpu_id) { - return !!(gic_dist->pending_set0[vcpu_id] & IRQ_BIT(irq)); + return !!(vgic->dist->pending_set0[vcpu_id] & IRQ_BIT(irq)); } -static inline bool is_spi_pending(struct gic_dist_map *gic_dist, int irq) +static inline bool is_spi_pending(vgic_t *vgic, int irq) { - return !!(gic_dist->pending_set[IRQ_IDX(irq)] & IRQ_BIT(irq)); + return !!(vgic->dist->pending_set[IRQ_IDX(irq)] & IRQ_BIT(irq)); } -static inline bool is_pending(struct gic_dist_map *gic_dist, int irq, int vcpu_id) +static inline bool is_pending(vgic_t *vgic, int irq, int vcpu_id) { if (irq < NUM_VCPU_LOCAL_VIRQS) { - return is_sgi_ppi_pending(gic_dist, irq, vcpu_id); + return is_sgi_ppi_pending(vgic, irq, vcpu_id); } - return is_spi_pending(gic_dist, irq); + return is_spi_pending(vgic, irq); } -static inline void set_sgi_ppi_enable(struct gic_dist_map *gic_dist, int irq, bool set_enable, int vcpu_id) +static inline void set_sgi_ppi_enable(vgic_t *vgic, int irq, bool set_enable, int vcpu_id) { if (set_enable) { - gic_dist->enable_set0[vcpu_id] |= IRQ_BIT(irq); - gic_dist->enable_clr0[vcpu_id] |= IRQ_BIT(irq); + vgic->dist->enable_set0[vcpu_id] |= IRQ_BIT(irq); + vgic->dist->enable_clr0[vcpu_id] |= IRQ_BIT(irq); } else { - gic_dist->enable_set0[vcpu_id] &= ~IRQ_BIT(irq); - gic_dist->enable_clr0[vcpu_id] &= ~IRQ_BIT(irq); + vgic->dist->enable_set0[vcpu_id] &= ~IRQ_BIT(irq); + vgic->dist->enable_clr0[vcpu_id] &= ~IRQ_BIT(irq); } } -static inline void set_spi_enable(struct gic_dist_map *gic_dist, int irq, bool set_enable) +static inline void set_spi_enable(vgic_t *vgic, int irq, bool set_enable) { if (set_enable) { - gic_dist->enable_set[IRQ_IDX(irq)] |= IRQ_BIT(irq); - gic_dist->enable_clr[IRQ_IDX(irq)] |= IRQ_BIT(irq); + vgic->dist->enable_set[IRQ_IDX(irq)] |= IRQ_BIT(irq); + vgic->dist->enable_clr[IRQ_IDX(irq)] |= IRQ_BIT(irq); } else { - gic_dist->enable_set[IRQ_IDX(irq)] &= ~IRQ_BIT(irq); - gic_dist->enable_clr[IRQ_IDX(irq)] &= ~IRQ_BIT(irq); + vgic->dist->enable_set[IRQ_IDX(irq)] &= ~IRQ_BIT(irq); + vgic->dist->enable_clr[IRQ_IDX(irq)] &= ~IRQ_BIT(irq); } } -static inline void set_enable(struct gic_dist_map *gic_dist, int irq, bool set_enable, int vcpu_id) +static inline void set_enable(vgic_t *vgic, int irq, bool set_enable, int vcpu_id) { if (irq < NUM_VCPU_LOCAL_VIRQS) { - set_sgi_ppi_enable(gic_dist, irq, set_enable, vcpu_id); + set_sgi_ppi_enable(vgic->dist, irq, set_enable, vcpu_id); return; } - set_spi_enable(gic_dist, irq, set_enable); + set_spi_enable(vgic->dist, irq, set_enable); } -static inline bool is_sgi_ppi_enabled(struct gic_dist_map *gic_dist, int irq, int vcpu_id) +static inline bool is_sgi_ppi_enabled(vgic_t *vgic, int irq, int vcpu_id) { - return !!(gic_dist->enable_set0[vcpu_id] & IRQ_BIT(irq)); + return !!(vgic->dist->enable_set0[vcpu_id] & IRQ_BIT(irq)); } -static inline bool is_spi_enabled(struct gic_dist_map *gic_dist, int irq) +static inline bool is_spi_enabled(vgic_t *vgic, int irq) { - return !!(gic_dist->enable_set[IRQ_IDX(irq)] & IRQ_BIT(irq)); + return !!(vgic->dist->enable_set[IRQ_IDX(irq)] & IRQ_BIT(irq)); } -static inline bool is_enabled(struct gic_dist_map *gic_dist, int irq, int vcpu_id) +static inline bool is_enabled(vgic_t *vgic, int irq, int vcpu_id) { if (irq < NUM_VCPU_LOCAL_VIRQS) { - return is_sgi_ppi_enabled(gic_dist, irq, vcpu_id); + return is_sgi_ppi_enabled(vgic, irq, vcpu_id); } - return is_spi_enabled(gic_dist, irq); + return is_spi_enabled(vgic, irq); } -static inline bool is_sgi_ppi_active(struct gic_dist_map *gic_dist, int irq, int vcpu_id) +static inline bool is_sgi_ppi_active(vgic_t *vgic, int irq, int vcpu_id) { - return !!(gic_dist->active0[vcpu_id] & IRQ_BIT(irq)); + return !!(vgic->dist->active0[vcpu_id] & IRQ_BIT(irq)); } -static inline bool is_spi_active(struct gic_dist_map *gic_dist, int irq) +static inline bool is_spi_active(vgic_t *vgic, int irq) { - return !!(gic_dist->active[IRQ_IDX(irq)] & IRQ_BIT(irq)); + return !!(vgic->dist->active[IRQ_IDX(irq)] & IRQ_BIT(irq)); } -static inline bool is_active(struct gic_dist_map *gic_dist, int irq, int vcpu_id) +static inline bool is_active(vgic_t *vgic, int irq, int vcpu_id) { if (irq < NUM_VCPU_LOCAL_VIRQS) { - return is_sgi_ppi_active(gic_dist, irq, vcpu_id); + return is_sgi_ppi_active(vgic, irq, vcpu_id); } - return is_spi_active(gic_dist, irq); -} - -static int vgic_dist_enable(vgic_t *vgic, vm_t *vm) -{ - assert(vgic); - assert(vgic->dist); - DDIST("enabling gic distributor\n"); - vgic->dist->enable = 1; - return 0; -} - -static int vgic_dist_disable(vgic_t *vgic, vm_t *vm) -{ - assert(vgic); - assert(vgic->dist); - DDIST("disabling gic distributor\n"); - vgic->dist->enable = 0; - return 0; + return is_spi_active(vgic, irq); } static void vgic_dist_enable_irq(vgic_t *vgic, vm_vcpu_t *vcpu, int irq) @@ -171,7 +153,7 @@ static void vgic_dist_enable_irq(vgic_t *vgic, vm_vcpu_t *vcpu, int irq) struct virq_handle *virq_data = virq_find_irq_data(vgic, vcpu, irq); if (virq_data) { /* STATE b) */ - if (!is_pending(vgic->dist, virq_data->virq, vcpu->vcpu_id)) { + if (!is_pending(vgic, virq_data->virq, vcpu->vcpu_id)) { virq_ack(vcpu, virq_data); } } else { @@ -207,12 +189,12 @@ static int vgic_dist_set_pending_irq(vgic_t *vgic, vm_vcpu_t *vcpu, int irq) struct virq_handle *virq_data = virq_find_irq_data(vgic, vcpu, irq); - if (!virq_data || !vgic->dist->enable || !is_enabled(vgic->dist, irq, vcpu->vcpu_id)) { + if (!virq_data || !gic_dist_is_enabled(vgic) || !is_enabled(vgic->dist, irq, vcpu->vcpu_id)) { DDIST("IRQ not enabled (%d) on vcpu %d\n", irq, vcpu->vcpu_id); return -1; } - if (is_pending(vgic->dist, virq_data->virq, vcpu->vcpu_id)) { + if (is_pending(vgic, virq_data->virq, vcpu->vcpu_id)) { return 0; } @@ -254,8 +236,8 @@ static int vgic_dist_clr_pending_irq(vgic_t *vgic, vm_vcpu_t *vcpu, int irq) return 0; } -static memory_fault_result_t vgic_dist_reg_read(vm_t *vm, vm_vcpu_t *vcpu, - vgic_t *vgic, seL4_Word offset) +static memory_fault_result_t vgic_dist_reg_read(vgic_t *vgic, vm_vcpu_t *vcpu, + seL4_Word offset) { int err = 0; fault_t *fault = vcpu->vcpu_arch.fault; @@ -411,8 +393,8 @@ static inline void emulate_reg_write_access(uint32_t *vreg, fault_t *fault) *vreg = fault_emulate(fault, *vreg); } -static memory_fault_result_t vgic_dist_reg_write(vm_t *vm, vm_vcpu_t *vcpu, - vgic_t *vgic, seL4_Word offset) +static memory_fault_result_t vgic_dist_reg_write(vgic_t *vgic, vm_vcpu_t *vcpu, + seL4_Word offset) { int err = 0; fault_t *fault = vcpu->vcpu_arch.fault; @@ -424,14 +406,7 @@ static memory_fault_result_t vgic_dist_reg_write(vm_t *vm, vm_vcpu_t *vcpu, uint32_t data; switch (offset) { case RANGE32(GIC_DIST_CTLR, GIC_DIST_CTLR): - data = fault_get_data(fault); - if (data == 1) { - vgic_dist_enable(vgic, vm); - } else if (data == 0) { - vgic_dist_disable(vgic, vm); - } else { - ZF_LOGE("Unknown enable register encoding"); - } + vgic_dist_set_ctlr(vgic, fault_get_data(fault)); break; case RANGE32(GIC_DIST_TYPER, GIC_DIST_TYPER): break; @@ -590,6 +565,9 @@ static memory_fault_result_t handle_vgic_dist_fault(vm_t *vm, vm_vcpu_t *vcpu, u size_t fault_length, void *cookie) { + /* The vcpu has a vm reference, it must match the vm parameter. */ + assert(vm == vcpu->vm); + /* There is a fault object per vcpu with much more context, the parameters * fault_addr and fault_length are no longer used. */ @@ -598,15 +576,13 @@ static memory_fault_result_t handle_vgic_dist_fault(vm_t *vm, vm_vcpu_t *vcpu, u assert(fault_addr == fault_get_address(vcpu->vcpu_arch.fault)); assert(cookie); - struct vgic_dist_device *d = (typeof(d))cookie; - vgic_t *vgic = d->vgic; - assert(vgic->dist); + vgic_t *vgic = (typeof(vgic))cookie; seL4_Word addr = fault_get_address(fault); - assert(addr >= d->pstart); - seL4_Word offset = addr - d->pstart; - assert(offset < PAGE_SIZE_4K); + assert(addr >= vgic->mapped_dist.paddr); + seL4_Word offset = addr - vgic->mapped_dist.paddr; + assert(offset < vgic->mapped_dist.size); - return fault_is_read(fault) ? vgic_dist_reg_read(vm, vcpu, vgic, offset) - : vgic_dist_reg_write(vm, vcpu, vgic, offset); + return fault_is_read(fault) ? vgic_dist_reg_read(vgic, vcpu, offset) + : vgic_dist_reg_write(vgic, vcpu, offset); } diff --git a/libsel4vm/src/arch/arm/vgic/vgic.h b/libsel4vm/src/arch/arm/vgic/vgic.h index d054263a0..0d6d529b6 100644 --- a/libsel4vm/src/arch/arm/vgic/vgic.h +++ b/libsel4vm/src/arch/arm/vgic/vgic.h @@ -6,15 +6,21 @@ #include -typedef struct vgic vgic_t; - -struct vgic_dist_device { - uintptr_t pstart; +typedef struct { + uintptr_t paddr; size_t size; - vgic_t *vgic; -}; + vm_memory_reservation_t *vm_res; +} vm_mapping_t; -extern const struct vgic_dist_device dev_vgic_dist; +typedef struct vgic vgic_t; int vm_install_vgic(vm_t *vm); int vm_vgic_maintenance_handler(vm_vcpu_t *vcpu); + +static inline vgic_t *get_vgic_from_vm(vm_t *vm) +{ + assert(vm); + vgic_t *vgic = (typeof(vgic))(vm->arch.vgic_context); + assert(vgic); + return vgic; +} diff --git a/libsel4vm/src/arch/arm/vgic/vgic_v2.c b/libsel4vm/src/arch/arm/vgic/vgic_v2.c index 6d219758b..3e2e467eb 100644 --- a/libsel4vm/src/arch/arm/vgic/vgic_v2.c +++ b/libsel4vm/src/arch/arm/vgic/vgic_v2.c @@ -59,22 +59,11 @@ #include "vdist.h" -static struct vgic_dist_device *vgic_dist; - -static inline struct gic_dist_map *vgic_priv_get_dist(struct vgic_dist_device *d) -{ - assert(d); - assert(d->vgic); - return d->vgic->dist; -} - - int handle_vgic_maintenance(vm_vcpu_t *vcpu, int idx) { /* STATE d) */ - assert(vgic_dist); - struct gic_dist_map *gic_dist = vgic_priv_get_dist(vgic_dist); - vgic_t *vgic = vgic_dist->vgic; + assert(vcpu); + vgic_t *vgic = get_vgic_from_vm(vcpu->vm); assert(vgic); vgic_vcpu_t *vgic_vcpu = get_vgic_vcpu(vgic, vcpu->vcpu_id); assert(vgic_vcpu); @@ -98,10 +87,9 @@ int handle_vgic_maintenance(vm_vcpu_t *vcpu, int idx) } -static void vgic_dist_reset(struct vgic_dist_device *d) +static void vgic_dist_reset(vgic_t *vgic) { - struct gic_dist_map *gic_dist; - gic_dist = vgic_priv_get_dist(d); + struct gic_dist_map *gic_dist = vgic->dist; memset(gic_dist, 0, sizeof(*gic_dist)); gic_dist->ic_type = 0x0000fce7; /* RO */ gic_dist->dist_ident = 0x0200043b; /* RO */ @@ -155,7 +143,8 @@ static void vgic_dist_reset(struct vgic_dist_device *d) int vm_register_irq(vm_vcpu_t *vcpu, int irq, irq_ack_fn_t ack_fn, void *cookie) { - struct vgic *vgic = vgic_dist->vgic; + assert(vcpu); + vgic_t *vgic = get_vgic_from_vm(vcpu->vm); assert(vgic); struct virq_handle *virq_data = calloc(1, sizeof(*virq_data)); @@ -178,7 +167,8 @@ int vm_inject_irq(vm_vcpu_t *vcpu, int irq) { // vm->lock(); - struct vgic *vgic = vgic_dist->vgic; + assert(vcpu); + vgic_t *vgic = get_vgic_from_vm(vcpu->vm); assert(vgic); DIRQ("VM received IRQ %d\n", irq); @@ -208,6 +198,7 @@ static vm_frame_t vgic_vcpu_iterator(uintptr_t addr, void *cookie) cspacepath_t frame; vm_frame_t frame_result = { seL4_CapNull, seL4_NoRights, 0, 0 }; vm_t *vm = (vm_t *)cookie; + vgic_t *vgic = get_vgic_from_vm(vm); int err = vka_cspace_alloc_path(vm->vka, &frame); if (err) { @@ -225,7 +216,8 @@ static vm_frame_t vgic_vcpu_iterator(uintptr_t addr, void *cookie) } frame_result.cptr = frame.capPtr; frame_result.rights = seL4_AllRights; - frame_result.vaddr = GIC_CPU_PADDR; + frame_result.vaddr = vgic->mapped_cpu_if.paddr; + assert(vgic->mapped_cpu_if.size == BIT(seL4_PageBits)); frame_result.size_bits = seL4_PageBits; return frame_result; } @@ -241,33 +233,42 @@ int vm_install_vgic(vm_t *vm) assert(!"Unable to calloc memory for VGIC"); return -1; } - /* vgic doesn't require further initialization, having all fields set to - * zero is fine. + /* vgic doesn't require much further initialization, having all fields set + * to zero is fine. */ - - /* Distributor */ - vgic_dist = (struct vgic_dist_device *)calloc(1, sizeof(struct vgic_dist_device)); - if (!vgic_dist) { + vgic->dist = calloc(1, sizeof(*(vgic->dist))); + if (!vgic->dist) { + assert(!"Unable to calloc memory for distributor"); + free(vgic); return -1; } - memcpy(vgic_dist, &dev_vgic_dist, sizeof(struct vgic_dist_device)); - vgic->dist = calloc(1, sizeof(struct gic_dist_map)); - assert(vgic->dist); - if (vgic->dist == NULL) { - return -1; - } - vm_memory_reservation_t *vgic_dist_res = vm_reserve_memory_at(vm, GIC_DIST_PADDR, PAGE_SIZE_4K, - handle_vgic_dist_fault, (void *)vgic_dist); - vgic_dist->vgic = vgic; - vgic_dist_reset(vgic_dist); + vgic_dist_reset(vgic); + + vm->arch.vgic_context = vgic; + + vgic->mapped_dist.paddr = GIC_DIST_PADDR; + vgic->mapped_dist.size = PAGE_SIZE_4K; + vgic->mapped_dist.vm_res = vm_reserve_memory_at(vm, + vgic->mapped_dist.paddr, + vgic->mapped_dist.size, + handle_vgic_dist_fault, + (void *)vgic); /* Remap VCPU to CPU */ - vm_memory_reservation_t *vgic_vcpu_reservation = vm_reserve_memory_at(vm, GIC_CPU_PADDR, PAGE_SIZE_4K, - handle_vgic_vcpu_fault, NULL); - int err = vm_map_reservation(vm, vgic_vcpu_reservation, vgic_vcpu_iterator, (void *)vm); + vgic->mapped_cpu_if.paddr = GIC_CPU_PADDR; + vgic->mapped_cpu_if.size = PAGE_SIZE_4K; + vgic->mapped_cpu_if.vm_res = vm_reserve_memory_at(vm, + vgic->mapped_cpu_if.paddr, + vgic->mapped_cpu_if.size, + handle_vgic_vcpu_fault, + NULL); + int err = vm_map_reservation(vm, vgic->mapped_cpu_if.vm_res, + vgic_vcpu_iterator, (void *)vm); if (err) { - free(vgic_dist->vgic); + vm->arch.vgic_context = NULL; + free(vgic->dist); + free(vgic); return -1; } diff --git a/libsel4vm/src/arch/arm/vgic/virq.h b/libsel4vm/src/arch/arm/vgic/virq.h index 813ba04c1..c74761c78 100644 --- a/libsel4vm/src/arch/arm/vgic/virq.h +++ b/libsel4vm/src/arch/arm/vgic/virq.h @@ -73,6 +73,8 @@ typedef struct vgic_vcpu { /* GIC global interrupt context */ typedef struct vgic { + vm_mapping_t mapped_cpu_if; + vm_mapping_t mapped_dist; /* virtual distributor registers */ struct gic_dist_map *dist; /* registered global interrupts (SPI) */ @@ -206,10 +208,16 @@ static inline int vgic_vcpu_load_list_reg(vgic_t *vgic, vm_vcpu_t *vcpu, int idx assert(vgic_vcpu); assert((idx >= 0) && (idx < ARRAY_SIZE(vgic_vcpu->lr_shadow))); - int err = seL4_ARM_VCPU_InjectIRQ(vcpu->vcpu.cptr, irq->virq, 0, group, idx); - if (err) { - ZF_LOGF("Failure loading vGIC list register (error %d)", err); - return err; + assert(group == (seL4_Uint8)group); + assert(idx = (seL4_Uint8)idx); + seL4_Error err = seL4_ARM_VCPU_InjectIRQ(vcpu->vcpu.cptr, irq->virq, 0, + (seL4_Uint8)group, + (seL4_Uint8)idx); + if (seL4_NoError != err) { + ZF_LOGE("Failure loading vGIC list register %d on vCPU %d, sel4 error %d", + idx, vcpu->vcpu_id, err); + /* Return a generic error, the caller doesn't understand seL4 errors. */ + return -1; } vgic_vcpu->lr_shadow[idx] = irq;