| From 47392944abe283cce3412d06b5dd0f4e79103419 Mon Sep 17 00:00:00 2001 |
| From: Zenghui Yu <yuzenghui@huawei.com> |
| Date: Wed, 23 Oct 2019 03:46:26 +0000 |
| Subject: [PATCH] irqchip/gic-v3-its: Use the exact ITSList for VMOVP |
| |
| commit 8424312516e5d9baeeb0a95d0e4523579b7aa395 upstream. |
| |
| 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: Zenghui Yu <yuzenghui@huawei.com> |
| Signed-off-by: Marc Zyngier <maz@kernel.org> |
| Link: https://lore.kernel.org/r/1571802386-2680-1-git-send-email-yuzenghui@huawei.com |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c |
| index fca8b9002852..d70badb3ab14 100644 |
| --- a/drivers/irqchip/irq-gic-v3-its.c |
| +++ b/drivers/irqchip/irq-gic-v3-its.c |
| @@ -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_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, |
| u32 event) |
| { |
| @@ -976,17 +992,15 @@ static void its_send_vmapp(struct its_node *its, |
| |
| static void its_send_vmovp(struct its_vpe *vpe) |
| { |
| - struct its_cmd_desc desc; |
| + struct its_cmd_desc desc = {}; |
| struct its_node *its; |
| unsigned long flags; |
| int col_id = vpe->col_idx; |
| |
| desc.its_vmovp_cmd.vpe = vpe; |
| - desc.its_vmovp_cmd.its_list = (u16)its_list_map; |
| |
| if (!its_list_map) { |
| 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]; |
| its_send_single_vcommand(its, its_build_vmovp_cmd, &desc); |
| return; |
| @@ -1003,6 +1017,7 @@ static void its_send_vmovp(struct its_vpe *vpe) |
| raw_spin_lock_irqsave(&vmovp_lock, flags); |
| |
| desc.its_vmovp_cmd.seq_num = vmovp_seq_num++; |
| + desc.its_vmovp_cmd.its_list = get_its_list(vpe->its_vm); |
| |
| /* Emit VMOVPs */ |
| list_for_each_entry(its, &its_nodes, entry) { |
| -- |
| 2.7.4 |
| |