Commit 80edb965 authored by wanghaibin's avatar wanghaibin Committed by Dongxu Sun
Browse files

irqchip/gic-v4.1: Rework its_alloc_vcpu_sgis() to support vPPI allocation

virt inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8K89F


CVE: NA

------------------------------------------------------------------

Allocate up to 32 IRQs at vcpu creation time if vtimer irqbypass is supported.

Signed-off-by: default avatarwanghaibin <wanghaibin.wang@huawei.com>
Signed-off-by: default avatarZenghui Yu <yuzenghui@huawei.com>
Signed-off-by: default avatarKunkun Jiang <jiangkunkun@huawei.com>
Signed-off-by: default avatarDongxu Sun <sundongxu3@huawei.com>
parent a00b87c1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -5547,7 +5547,7 @@ int __init phytium_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, false)) {
			rdists->has_vlpis = false;
			pr_err("ITS: Disabling GICv4 support\n");
		}
+11 −4
Original line number Diff line number Diff line
@@ -4647,10 +4647,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;
@@ -5744,6 +5744,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;
@@ -5767,12 +5768,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;

@@ -5782,7 +5788,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");
		}
+19 −4
Original line number Diff line number Diff line
@@ -86,20 +86,30 @@
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;

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 int its_alloc_vcpu_sgis(struct its_vpe *vpe, int idx)
{
	char *name;
	int sgi_base;
	int nr_irqs = 16;

	if (!has_v4_1())
		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;
@@ -111,12 +121,13 @@ 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, -1, 16,
	vpe->nr_irqs = nr_irqs;
	sgi_base = __irq_domain_alloc_irqs(vpe->sgi_domain, -1, nr_irqs,
					       NUMA_NO_NODE, vpe,
					       false, NULL);
	if (sgi_base <= 0)
@@ -125,6 +136,7 @@ static int its_alloc_vcpu_sgis(struct its_vpe *vpe, int idx)
	return 0;

err:
	vpe->nr_irqs = 0;
	if (vpe->sgi_domain)
		irq_domain_remove(vpe->sgi_domain);
	if (vpe->fwnode)
@@ -191,7 +203,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);
	}
@@ -354,13 +366,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;
	}

+4 −2
Original line number Diff line number Diff line
@@ -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,6 +144,7 @@ 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);

#endif