From: wanghaibin wanghaibin.wang@huawei.com
virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8URKX CVE: NA
------------------------------------------------------------------
Allocate up to 32 IRQs at vcpu creation time if vtimer irqbypass is supported.
Signed-off-by: wanghaibin wanghaibin.wang@huawei.com Signed-off-by: Zenghui Yu yuzenghui@huawei.com Signed-off-by: Kunkun Jiang jiangkunkun@huawei.com Signed-off-by: Dongxu Sun sundongxu3@huawei.com --- drivers/irqchip/irq-gic-v3-its.c | 15 +++++++++++---- drivers/irqchip/irq-gic-v4.c | 23 +++++++++++++++++++---- include/linux/irqchip/arm-gic-v4.h | 6 ++++-- 3 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index d51e3a77df4e..ce5805364110 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -4415,10 +4415,10 @@ static int its_sgi_irq_domain_alloc(struct irq_domain *domain, struct its_vpe *vpe = args; int i;
- /* Yes, we do want 16 SGIs */ - WARN_ON(nr_irqs != 16); + /* We may want 32 IRQs if vtimer irqbypass is supported. */ + WARN_ON(nr_irqs != 16 && nr_irqs != 32);
- for (i = 0; i < 16; i++) { + for (i = 0; i < nr_irqs; i++) { vpe->sgi_config[i].priority = 0; vpe->sgi_config[i].enabled = false; vpe->sgi_config[i].group = false; @@ -5711,6 +5711,7 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists, struct its_node *its; bool has_v4 = false; bool has_v4_1 = false; + bool has_vtimer_irqbypass = false; int err;
gic_rdists = rdists; @@ -5734,12 +5735,17 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists, list_for_each_entry(its, &its_nodes, entry) { has_v4 |= is_v4(its); has_v4_1 |= is_v4_1(its); + has_vtimer_irqbypass |= is_vtimer_irqbypass(its); }
/* Don't bother with inconsistent systems */ if (WARN_ON(!has_v4_1 && rdists->has_rvpeid)) rdists->has_rvpeid = false;
+ /* vtimer irqbypass depends on rvpeid support */ + if (WARN_ON(!has_v4_1 && has_vtimer_irqbypass)) + has_vtimer_irqbypass = false; + if (has_v4 & rdists->has_vlpis) { const struct irq_domain_ops *sgi_ops;
@@ -5749,7 +5755,8 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists, sgi_ops = NULL;
if (its_init_vpe_domain() || - its_init_v4(parent_domain, &its_vpe_domain_ops, sgi_ops)) { + its_init_v4(parent_domain, &its_vpe_domain_ops, + sgi_ops, has_vtimer_irqbypass)) { rdists->has_vlpis = false; pr_err("ITS: Disabling GICv4 support\n"); } diff --git a/drivers/irqchip/irq-gic-v4.c b/drivers/irqchip/irq-gic-v4.c index 94d56a03b175..b804a55efec7 100644 --- a/drivers/irqchip/irq-gic-v4.c +++ b/drivers/irqchip/irq-gic-v4.c @@ -86,6 +86,7 @@ static struct irq_domain *gic_domain; static const struct irq_domain_ops *vpe_domain_ops; static const struct irq_domain_ops *sgi_domain_ops; +static bool vtimer_irqbypass;
#ifdef CONFIG_ARM64 #include <asm/cpufeature.h> @@ -110,6 +111,11 @@ static bool has_v4_1(void) return !!sgi_domain_ops; }
+static bool has_v4_1_vsgi_extend(void) +{ + return has_v4_1() && vtimer_irqbypass; +} + static bool has_v4_1_sgi(void) { return has_v4_1() && gic_cpuif_has_vsgi(); @@ -119,10 +125,14 @@ static int its_alloc_vcpu_sgis(struct its_vpe *vpe, int idx) { char *name; int sgi_base; + int nr_irqs = 16;
if (!has_v4_1_sgi()) return 0;
+ if (has_v4_1_vsgi_extend()) + nr_irqs = 32; + name = kasprintf(GFP_KERNEL, "GICv4-sgi-%d", task_pid_nr(current)); if (!name) goto err; @@ -134,18 +144,20 @@ static int its_alloc_vcpu_sgis(struct its_vpe *vpe, int idx) kfree(name); name = NULL;
- vpe->sgi_domain = irq_domain_create_linear(vpe->fwnode, 16, + vpe->sgi_domain = irq_domain_create_linear(vpe->fwnode, nr_irqs, sgi_domain_ops, vpe); if (!vpe->sgi_domain) goto err;
- sgi_base = irq_domain_alloc_irqs(vpe->sgi_domain, 16, NUMA_NO_NODE, vpe); + vpe->nr_irqs = nr_irqs; + sgi_base = irq_domain_alloc_irqs(vpe->sgi_domain, nr_irqs, NUMA_NO_NODE, vpe); if (sgi_base <= 0) goto err;
return 0;
err: + vpe->nr_irqs = 0; if (vpe->sgi_domain) irq_domain_remove(vpe->sgi_domain); if (vpe->fwnode) @@ -211,7 +223,7 @@ static void its_free_sgi_irqs(struct its_vm *vm) if (WARN_ON(!irq)) continue;
- irq_domain_free_irqs(irq, 16); + irq_domain_free_irqs(irq, vm->vpes[i]->nr_irqs); irq_domain_remove(vm->vpes[i]->sgi_domain); irq_domain_free_fwnode(vm->vpes[i]->fwnode); } @@ -374,13 +386,16 @@ int its_prop_update_vsgi(int irq, u8 priority, bool group)
int its_init_v4(struct irq_domain *domain, const struct irq_domain_ops *vpe_ops, - const struct irq_domain_ops *sgi_ops) + const struct irq_domain_ops *sgi_ops, + bool has_vtimer_irqbypass) { if (domain) { pr_info("ITS: Enabling GICv4 support\n"); gic_domain = domain; vpe_domain_ops = vpe_ops; sgi_domain_ops = sgi_ops; + vtimer_irqbypass = has_vtimer_irqbypass; + return 0; }
diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h index 2c63375bbd43..20b06f4ff7d6 100644 --- a/include/linux/irqchip/arm-gic-v4.h +++ b/include/linux/irqchip/arm-gic-v4.h @@ -57,7 +57,8 @@ struct its_vpe { u8 priority; bool enabled; bool group; - } sgi_config[16]; + } sgi_config[32]; + int nr_irqs; atomic_t vmapp_count; }; }; @@ -143,7 +144,8 @@ int its_prop_update_vsgi(int irq, u8 priority, bool group); struct irq_domain_ops; int its_init_v4(struct irq_domain *domain, const struct irq_domain_ops *vpe_ops, - const struct irq_domain_ops *sgi_ops); + const struct irq_domain_ops *sgi_ops, + bool has_vtimer_irqbypass);
bool gic_cpuif_has_vsgi(void);