Commit 84243125 authored by Zenghui Yu's avatar Zenghui Yu Committed by Marc Zyngier

irqchip/gic-v3-its: Use the exact ITSList for VMOVP

On a system without Single VMOVP support (say GITS_TYPER.VMOVP == 0),
we will map vPEs only on ITSs that will actually control interrupts
for the given VM.  And when moving a vPE, the VMOVP command will be
issued only for those ITSs.

But when issuing VMOVPs we seemed fail to present the exact ITSList
to ITSs who are actually included in the synchronization operation.
The its_list_map we're currently using includes all ITSs in the system,
even though some of them don't have the corresponding vPE mapping at all.

Introduce get_its_list() to get the per-VM its_list_map, to indicate
which ITSs have vPE mappings for the given VM, and use this map as
the expected ITSList when building VMOVP. This is hopefully a performance
gain not to do some synchronization with those unsuspecting ITSs.
And initialize the whole command descriptor to zero at beginning, since
the seq_num and its_list should be RES0 when GITS_TYPER.VMOVP == 1.
Signed-off-by: default avatarZenghui Yu <yuzenghui@huawei.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/1571802386-2680-1-git-send-email-yuzenghui@huawei.com
parent bb0fed1c
...@@ -175,6 +175,22 @@ static DEFINE_IDA(its_vpeid_ida); ...@@ -175,6 +175,22 @@ static DEFINE_IDA(its_vpeid_ida);
#define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base)
#define gic_data_rdist_vlpi_base() (gic_data_rdist_rd_base() + SZ_128K) #define gic_data_rdist_vlpi_base() (gic_data_rdist_rd_base() + SZ_128K)
static u16 get_its_list(struct its_vm *vm)
{
struct its_node *its;
unsigned long its_list = 0;
list_for_each_entry(its, &its_nodes, entry) {
if (!its->is_v4)
continue;
if (vm->vlpi_count[its->list_nr])
__set_bit(its->list_nr, &its_list);
}
return (u16)its_list;
}
static struct its_collection *dev_event_to_col(struct its_device *its_dev, static struct its_collection *dev_event_to_col(struct its_device *its_dev,
u32 event) u32 event)
{ {
...@@ -976,17 +992,15 @@ static void its_send_vmapp(struct its_node *its, ...@@ -976,17 +992,15 @@ static void its_send_vmapp(struct its_node *its,
static void its_send_vmovp(struct its_vpe *vpe) static void its_send_vmovp(struct its_vpe *vpe)
{ {
struct its_cmd_desc desc; struct its_cmd_desc desc = {};
struct its_node *its; struct its_node *its;
unsigned long flags; unsigned long flags;
int col_id = vpe->col_idx; int col_id = vpe->col_idx;
desc.its_vmovp_cmd.vpe = vpe; desc.its_vmovp_cmd.vpe = vpe;
desc.its_vmovp_cmd.its_list = (u16)its_list_map;
if (!its_list_map) { if (!its_list_map) {
its = list_first_entry(&its_nodes, struct its_node, entry); its = list_first_entry(&its_nodes, struct its_node, entry);
desc.its_vmovp_cmd.seq_num = 0;
desc.its_vmovp_cmd.col = &its->collections[col_id]; desc.its_vmovp_cmd.col = &its->collections[col_id];
its_send_single_vcommand(its, its_build_vmovp_cmd, &desc); its_send_single_vcommand(its, its_build_vmovp_cmd, &desc);
return; return;
...@@ -1003,6 +1017,7 @@ static void its_send_vmovp(struct its_vpe *vpe) ...@@ -1003,6 +1017,7 @@ static void its_send_vmovp(struct its_vpe *vpe)
raw_spin_lock_irqsave(&vmovp_lock, flags); raw_spin_lock_irqsave(&vmovp_lock, flags);
desc.its_vmovp_cmd.seq_num = vmovp_seq_num++; desc.its_vmovp_cmd.seq_num = vmovp_seq_num++;
desc.its_vmovp_cmd.its_list = get_its_list(vpe->its_vm);
/* Emit VMOVPs */ /* Emit VMOVPs */
list_for_each_entry(its, &its_nodes, entry) { list_for_each_entry(its, &its_nodes, entry) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment