Skip to content

Commit

Permalink
irqchip/gic-v4.1: Add VSGI allocation/teardown
Browse files Browse the repository at this point in the history
Allocate per-VPE SGIs when initializing the GIC-specific part of the
VPE data structure.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
Link: https://lore.kernel.org/r/20200304203330.4967-15-maz@kernel.org
  • Loading branch information
Marc Zyngier committed Mar 24, 2020
1 parent ae699ad commit 6d31b6f
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
68 changes: 67 additions & 1 deletion drivers/irqchip/irq-gic-v4.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,47 @@ static bool has_v4_1(void)
return !!sgi_domain_ops;
}

static int its_alloc_vcpu_sgis(struct its_vpe *vpe, int idx)
{
char *name;
int sgi_base;

if (!has_v4_1())
return 0;

name = kasprintf(GFP_KERNEL, "GICv4-sgi-%d", task_pid_nr(current));
if (!name)
goto err;

vpe->fwnode = irq_domain_alloc_named_id_fwnode(name, idx);
if (!vpe->fwnode)
goto err;

kfree(name);
name = NULL;

vpe->sgi_domain = irq_domain_create_linear(vpe->fwnode, 16,
sgi_domain_ops, vpe);
if (!vpe->sgi_domain)
goto err;

sgi_base = __irq_domain_alloc_irqs(vpe->sgi_domain, -1, 16,
NUMA_NO_NODE, vpe,
false, NULL);
if (sgi_base <= 0)
goto err;

return 0;

err:
if (vpe->sgi_domain)
irq_domain_remove(vpe->sgi_domain);
if (vpe->fwnode)
irq_domain_free_fwnode(vpe->fwnode);
kfree(name);
return -ENOMEM;
}

int its_alloc_vcpu_irqs(struct its_vm *vm)
{
int vpe_base_irq, i;
Expand All @@ -118,8 +159,13 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
if (vpe_base_irq <= 0)
goto err;

for (i = 0; i < vm->nr_vpes; i++)
for (i = 0; i < vm->nr_vpes; i++) {
int ret;
vm->vpes[i]->irq = vpe_base_irq + i;
ret = its_alloc_vcpu_sgis(vm->vpes[i], i);
if (ret)
goto err;
}

return 0;

Expand All @@ -132,8 +178,28 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
return -ENOMEM;
}

static void its_free_sgi_irqs(struct its_vm *vm)
{
int i;

if (!has_v4_1())
return;

for (i = 0; i < vm->nr_vpes; i++) {
unsigned int irq = irq_find_mapping(vm->vpes[i]->sgi_domain, 0);

if (WARN_ON(!irq))
continue;

irq_domain_free_irqs(irq, 16);
irq_domain_remove(vm->vpes[i]->sgi_domain);
irq_domain_free_fwnode(vm->vpes[i]->fwnode);
}
}

void its_free_vcpu_irqs(struct its_vm *vm)
{
its_free_sgi_irqs(vm);
irq_domain_free_irqs(vm->vpes[0]->irq, vm->nr_vpes);
irq_domain_remove(vm->domain);
irq_domain_free_fwnode(vm->fwnode);
Expand Down
2 changes: 2 additions & 0 deletions include/linux/irqchip/arm-gic-v4.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ struct its_vpe {
};
/* GICv4.1 implementations */
struct {
struct fwnode_handle *fwnode;
struct irq_domain *sgi_domain;
struct {
u8 priority;
bool enabled;
Expand Down

0 comments on commit 6d31b6f

Please sign in to comment.