Skip to content

Commit 166cba7

Browse files
author
Marc Zyngier
committed
irqchip/gic-v4.1: Plumb skeletal VSGI irqchip
Since GICv4.1 has the capability to inject 16 SGIs into each VPE, and that I'm keen not to invent too many specific interfaces to manipulate these interrupts, let's pretend that each of these SGIs is an actual Linux interrupt. For that matter, let's introduce a minimal irqchip and irqdomain setup that will get fleshed up in the following patches. Signed-off-by: Marc Zyngier <[email protected]> Reviewed-by: Zenghui Yu <[email protected]> Reviewed-by: Eric Auger <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 5e46a48 commit 166cba7

File tree

3 files changed

+88
-4
lines changed

3 files changed

+88
-4
lines changed

drivers/irqchip/irq-gic-v3-its.c

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3870,6 +3870,72 @@ static struct irq_chip its_vpe_4_1_irq_chip = {
38703870
.irq_set_vcpu_affinity = its_vpe_4_1_set_vcpu_affinity,
38713871
};
38723872

3873+
static int its_sgi_set_affinity(struct irq_data *d,
3874+
const struct cpumask *mask_val,
3875+
bool force)
3876+
{
3877+
/*
3878+
* There is no notion of affinity for virtual SGIs, at least
3879+
* not on the host (since they can only be targetting a vPE).
3880+
* Tell the kernel we've done whatever it asked for.
3881+
*/
3882+
return IRQ_SET_MASK_OK;
3883+
}
3884+
3885+
static struct irq_chip its_sgi_irq_chip = {
3886+
.name = "GICv4.1-sgi",
3887+
.irq_set_affinity = its_sgi_set_affinity,
3888+
};
3889+
3890+
static int its_sgi_irq_domain_alloc(struct irq_domain *domain,
3891+
unsigned int virq, unsigned int nr_irqs,
3892+
void *args)
3893+
{
3894+
struct its_vpe *vpe = args;
3895+
int i;
3896+
3897+
/* Yes, we do want 16 SGIs */
3898+
WARN_ON(nr_irqs != 16);
3899+
3900+
for (i = 0; i < 16; i++) {
3901+
vpe->sgi_config[i].priority = 0;
3902+
vpe->sgi_config[i].enabled = false;
3903+
vpe->sgi_config[i].group = false;
3904+
3905+
irq_domain_set_hwirq_and_chip(domain, virq + i, i,
3906+
&its_sgi_irq_chip, vpe);
3907+
irq_set_status_flags(virq + i, IRQ_DISABLE_UNLAZY);
3908+
}
3909+
3910+
return 0;
3911+
}
3912+
3913+
static void its_sgi_irq_domain_free(struct irq_domain *domain,
3914+
unsigned int virq,
3915+
unsigned int nr_irqs)
3916+
{
3917+
/* Nothing to do */
3918+
}
3919+
3920+
static int its_sgi_irq_domain_activate(struct irq_domain *domain,
3921+
struct irq_data *d, bool reserve)
3922+
{
3923+
return 0;
3924+
}
3925+
3926+
static void its_sgi_irq_domain_deactivate(struct irq_domain *domain,
3927+
struct irq_data *d)
3928+
{
3929+
/* Nothing to do */
3930+
}
3931+
3932+
static const struct irq_domain_ops its_sgi_domain_ops = {
3933+
.alloc = its_sgi_irq_domain_alloc,
3934+
.free = its_sgi_irq_domain_free,
3935+
.activate = its_sgi_irq_domain_activate,
3936+
.deactivate = its_sgi_irq_domain_deactivate,
3937+
};
3938+
38733939
static int its_vpe_id_alloc(void)
38743940
{
38753941
return ida_simple_get(&its_vpeid_ida, 0, ITS_MAX_VPEID, GFP_KERNEL);
@@ -4912,8 +4978,15 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
49124978
rdists->has_rvpeid = false;
49134979

49144980
if (has_v4 & rdists->has_vlpis) {
4981+
const struct irq_domain_ops *sgi_ops;
4982+
4983+
if (has_v4_1)
4984+
sgi_ops = &its_sgi_domain_ops;
4985+
else
4986+
sgi_ops = NULL;
4987+
49154988
if (its_init_vpe_domain() ||
4916-
its_init_v4(parent_domain, &its_vpe_domain_ops)) {
4989+
its_init_v4(parent_domain, &its_vpe_domain_ops, sgi_ops)) {
49174990
rdists->has_vlpis = false;
49184991
pr_err("ITS: Disabling GICv4 support\n");
49194992
}

drivers/irqchip/irq-gic-v4.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585

8686
static struct irq_domain *gic_domain;
8787
static const struct irq_domain_ops *vpe_domain_ops;
88+
static const struct irq_domain_ops *sgi_domain_ops;
8889

8990
int its_alloc_vcpu_irqs(struct its_vm *vm)
9091
{
@@ -216,12 +217,15 @@ int its_prop_update_vlpi(int irq, u8 config, bool inv)
216217
return irq_set_vcpu_affinity(irq, &info);
217218
}
218219

219-
int its_init_v4(struct irq_domain *domain, const struct irq_domain_ops *ops)
220+
int its_init_v4(struct irq_domain *domain,
221+
const struct irq_domain_ops *vpe_ops,
222+
const struct irq_domain_ops *sgi_ops)
220223
{
221224
if (domain) {
222225
pr_info("ITS: Enabling GICv4 support\n");
223226
gic_domain = domain;
224-
vpe_domain_ops = ops;
227+
vpe_domain_ops = vpe_ops;
228+
sgi_domain_ops = sgi_ops;
225229
return 0;
226230
}
227231

include/linux/irqchip/arm-gic-v4.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ struct its_vpe {
4949
};
5050
/* GICv4.1 implementations */
5151
struct {
52+
struct {
53+
u8 priority;
54+
bool enabled;
55+
bool group;
56+
} sgi_config[16];
5257
atomic_t vmapp_count;
5358
};
5459
};
@@ -123,6 +128,8 @@ int its_unmap_vlpi(int irq);
123128
int its_prop_update_vlpi(int irq, u8 config, bool inv);
124129

125130
struct irq_domain_ops;
126-
int its_init_v4(struct irq_domain *domain, const struct irq_domain_ops *ops);
131+
int its_init_v4(struct irq_domain *domain,
132+
const struct irq_domain_ops *vpe_ops,
133+
const struct irq_domain_ops *sgi_ops);
127134

128135
#endif

0 commit comments

Comments
 (0)