Skip to content

Commit e252cf8

Browse files
author
Marc Zyngier
committed
irqchip/gic-v4.1: Add initial SGI configuration
The GICv4.1 ITS has yet another new command (VSGI) which allows a VPE-targeted SGI to be configured (or have its pending state cleared). Add support for this command and plumb it into the activate irqdomain callback so that it is ready to be used. Signed-off-by: Marc Zyngier <[email protected]> Reviewed-by: Zenghui Yu <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 166cba7 commit e252cf8

File tree

2 files changed

+93
-2
lines changed

2 files changed

+93
-2
lines changed

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

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,15 @@ struct its_cmd_desc {
380380
struct {
381381
struct its_vpe *vpe;
382382
} its_invdb_cmd;
383+
384+
struct {
385+
struct its_vpe *vpe;
386+
u8 sgi;
387+
u8 priority;
388+
bool enable;
389+
bool group;
390+
bool clear;
391+
} its_vsgi_cmd;
383392
};
384393
};
385394

@@ -528,6 +537,31 @@ static void its_encode_db(struct its_cmd_block *cmd, bool db)
528537
its_mask_encode(&cmd->raw_cmd[2], db, 63, 63);
529538
}
530539

540+
static void its_encode_sgi_intid(struct its_cmd_block *cmd, u8 sgi)
541+
{
542+
its_mask_encode(&cmd->raw_cmd[0], sgi, 35, 32);
543+
}
544+
545+
static void its_encode_sgi_priority(struct its_cmd_block *cmd, u8 prio)
546+
{
547+
its_mask_encode(&cmd->raw_cmd[0], prio >> 4, 23, 20);
548+
}
549+
550+
static void its_encode_sgi_group(struct its_cmd_block *cmd, bool grp)
551+
{
552+
its_mask_encode(&cmd->raw_cmd[0], grp, 10, 10);
553+
}
554+
555+
static void its_encode_sgi_clear(struct its_cmd_block *cmd, bool clr)
556+
{
557+
its_mask_encode(&cmd->raw_cmd[0], clr, 9, 9);
558+
}
559+
560+
static void its_encode_sgi_enable(struct its_cmd_block *cmd, bool en)
561+
{
562+
its_mask_encode(&cmd->raw_cmd[0], en, 8, 8);
563+
}
564+
531565
static inline void its_fixup_cmd(struct its_cmd_block *cmd)
532566
{
533567
/* Let's fixup BE commands */
@@ -893,6 +927,26 @@ static struct its_vpe *its_build_invdb_cmd(struct its_node *its,
893927
return valid_vpe(its, desc->its_invdb_cmd.vpe);
894928
}
895929

930+
static struct its_vpe *its_build_vsgi_cmd(struct its_node *its,
931+
struct its_cmd_block *cmd,
932+
struct its_cmd_desc *desc)
933+
{
934+
if (WARN_ON(!is_v4_1(its)))
935+
return NULL;
936+
937+
its_encode_cmd(cmd, GITS_CMD_VSGI);
938+
its_encode_vpeid(cmd, desc->its_vsgi_cmd.vpe->vpe_id);
939+
its_encode_sgi_intid(cmd, desc->its_vsgi_cmd.sgi);
940+
its_encode_sgi_priority(cmd, desc->its_vsgi_cmd.priority);
941+
its_encode_sgi_group(cmd, desc->its_vsgi_cmd.group);
942+
its_encode_sgi_clear(cmd, desc->its_vsgi_cmd.clear);
943+
its_encode_sgi_enable(cmd, desc->its_vsgi_cmd.enable);
944+
945+
its_fixup_cmd(cmd);
946+
947+
return valid_vpe(its, desc->its_vsgi_cmd.vpe);
948+
}
949+
896950
static u64 its_cmd_ptr_to_offset(struct its_node *its,
897951
struct its_cmd_block *ptr)
898952
{
@@ -3870,6 +3924,26 @@ static struct irq_chip its_vpe_4_1_irq_chip = {
38703924
.irq_set_vcpu_affinity = its_vpe_4_1_set_vcpu_affinity,
38713925
};
38723926

3927+
static void its_configure_sgi(struct irq_data *d, bool clear)
3928+
{
3929+
struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
3930+
struct its_cmd_desc desc;
3931+
3932+
desc.its_vsgi_cmd.vpe = vpe;
3933+
desc.its_vsgi_cmd.sgi = d->hwirq;
3934+
desc.its_vsgi_cmd.priority = vpe->sgi_config[d->hwirq].priority;
3935+
desc.its_vsgi_cmd.enable = vpe->sgi_config[d->hwirq].enabled;
3936+
desc.its_vsgi_cmd.group = vpe->sgi_config[d->hwirq].group;
3937+
desc.its_vsgi_cmd.clear = clear;
3938+
3939+
/*
3940+
* GICv4.1 allows us to send VSGI commands to any ITS as long as the
3941+
* destination VPE is mapped there. Since we map them eagerly at
3942+
* activation time, we're pretty sure the first GICv4.1 ITS will do.
3943+
*/
3944+
its_send_single_vcommand(find_4_1_its(), its_build_vsgi_cmd, &desc);
3945+
}
3946+
38733947
static int its_sgi_set_affinity(struct irq_data *d,
38743948
const struct cpumask *mask_val,
38753949
bool force)
@@ -3920,13 +3994,29 @@ static void its_sgi_irq_domain_free(struct irq_domain *domain,
39203994
static int its_sgi_irq_domain_activate(struct irq_domain *domain,
39213995
struct irq_data *d, bool reserve)
39223996
{
3997+
/* Write out the initial SGI configuration */
3998+
its_configure_sgi(d, false);
39233999
return 0;
39244000
}
39254001

39264002
static void its_sgi_irq_domain_deactivate(struct irq_domain *domain,
39274003
struct irq_data *d)
39284004
{
3929-
/* Nothing to do */
4005+
struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
4006+
4007+
/*
4008+
* The VSGI command is awkward:
4009+
*
4010+
* - To change the configuration, CLEAR must be set to false,
4011+
* leaving the pending bit unchanged.
4012+
* - To clear the pending bit, CLEAR must be set to true, leaving
4013+
* the configuration unchanged.
4014+
*
4015+
* You just can't do both at once, hence the two commands below.
4016+
*/
4017+
vpe->sgi_config[d->hwirq].enabled = false;
4018+
its_configure_sgi(d, false);
4019+
its_configure_sgi(d, true);
39304020
}
39314021

39324022
static const struct irq_domain_ops its_sgi_domain_ops = {

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,9 @@
502502
#define GITS_CMD_VMAPTI GITS_CMD_GICv4(GITS_CMD_MAPTI)
503503
#define GITS_CMD_VMOVI GITS_CMD_GICv4(GITS_CMD_MOVI)
504504
#define GITS_CMD_VSYNC GITS_CMD_GICv4(GITS_CMD_SYNC)
505-
/* VMOVP and INVDB are the odd ones, as they dont have a physical counterpart */
505+
/* VMOVP, VSGI and INVDB are the odd ones, as they dont have a physical counterpart */
506506
#define GITS_CMD_VMOVP GITS_CMD_GICv4(2)
507+
#define GITS_CMD_VSGI GITS_CMD_GICv4(3)
507508
#define GITS_CMD_INVDB GITS_CMD_GICv4(0xe)
508509

509510
/*

0 commit comments

Comments
 (0)