Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp1996701imu; Thu, 24 Jan 2019 05:39:31 -0800 (PST) X-Google-Smtp-Source: ALg8bN6Mh4emCiYpFT9s76l4CpqlAkBAK8HRAorXxBpzvtyod4EV5pdCqTFGXw/1iWLl3BTxdgU/ X-Received: by 2002:a17:902:7c85:: with SMTP id y5mr6535355pll.63.1548337171533; Thu, 24 Jan 2019 05:39:31 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1548337171; cv=none; d=google.com; s=arc-20160816; b=S+VYmUcwOyEX0Al1J/T0Be/9ZYRyZf4jaX34xiztaoSmIultbFNiKOCzaJTdJGuX4O ZDFn+ljRxx10U0+RsoxCrWx+Q7B8HlfP0P8b6gwcO13+LM0FsFJcn6tL5GeHoYad5TBs G6IuteR4/9th6bchIRmLnw/9kNwtCqDoe5Jj4iR3ZeabcCimw4i0kDYqf8lSsvsuTyv4 CSyvwN5iQGM88s39wVVqcFN6JY6sThLvcCxNRtpzf0zZA960fgA6Uq0UsTbt1pPL8mVk HLTDiBmaIRWW+JX1ez0gPK5TzHAB/VHupStXNFLXdTRFtQHx6LRN2BlcQgnJ2Ubexbti 7x9A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:message-id:date:subject:cc :to:from; bh=gvqY1/pv1/otnaTrXvcS2q55IDfi2F6nnLOxEaK7kp8=; b=z7UCE8JVQokryHfu2wanC4SJNSTkeh5VtbRgBDqvn0RTeJGhAVMqNrCVlX73JeFAk+ fLclGLu5SjEIfL/HxtHlcLGIALcPEGTiv4Pqp2x8cce/Tke2NPGIjIXI3JhTUEwjAlVW I4ptnIjV5BhgCLrw3XhnXrwVr5hVDvwAfqcyLH82Zk7eaBYcYaodmMPMgmO1XGkvThjj Y6eQW0ECkh5ilIpOlR0mDaeSzkCVcbwVXHpXg71xpb0Ax3MMghAm137Gt8qhKN1JFhn2 K1DGNPAiR5BqIvw4fWvF61RNoDJJW+CrPeTu2b3U0ovMV5scRnp1pbbiMKqQDhpQ/kbm aaxQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l94si3272849plb.416.2019.01.24.05.39.08; Thu, 24 Jan 2019 05:39:31 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728070AbfAXNia (ORCPT + 99 others); Thu, 24 Jan 2019 08:38:30 -0500 Received: from szxga07-in.huawei.com ([45.249.212.35]:41822 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727556AbfAXNia (ORCPT ); Thu, 24 Jan 2019 08:38:30 -0500 Received: from DGGEMS410-HUB.china.huawei.com (unknown [172.30.72.58]) by Forcepoint Email with ESMTP id 6AC12CF927D2602464EB; Thu, 24 Jan 2019 21:38:28 +0800 (CST) Received: from linux-fhAnjn.huawei.com (10.175.104.222) by DGGEMS410-HUB.china.huawei.com (10.3.19.210) with Microsoft SMTP Server id 14.3.408.0; Thu, 24 Jan 2019 21:38:18 +0800 From: Heyi Guo To: CC: Thomas Gleixner , Jason Cooper , Marc Zyngier , , Subject: [PATCH v2] irqchip/gic-v4: fix occasional VLPI drop Date: Thu, 24 Jan 2019 21:37:08 +0800 Message-ID: <1548337028-21801-1-git-send-email-guoheyi@huawei.com> X-Mailer: git-send-email 1.8.3.1 MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.175.104.222] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 1. In current implementation, every VLPI will temporarily be mapped to the first CPU in system (normally CPU0) and then moved to the real scheduled CPU later. 2. So there is a time window and a VLPI may be sent to CPU0 instead of the real scheduled vCPU, in a multi-CPU virtual machine. 3. However, CPU0 may have not been scheduled as a virtual CPU after system boots up, so the value of its GICR_VPROPBASER is unknown at that moment. 4. If the INTID of VLPI is larger than 2^(GICR_VPROPBASER.IDbits+1), while IDbits is also in unknown state, GIC will behave as if the VLPI is out of range and simply drop it, which results in interrupt missing in Guest. As no code will clear GICR_VPROPBASER at runtime, we can safely initialize the IDbits field at boot time for each CPU to get rid of this issue. We also clear Valid bit of GICR_VPENDBASER in case any ancient programming gets left in and causes memory corrupting. A new function its_clear_vpend_valid() is added to reuse the code in its_vpe_deschedule(). Signed-off-by: Heyi Guo Signed-off-by: Heyi Guo --- Notes: v2: - Also wait GICR_VPENDBASER.Dirty bit to be 0 in initialization [Marc] - Add a new function to reuse the code in its_vpe_deschedule() [Marc] drivers/irqchip/irq-gic-v3-its.c | 66 +++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 3365d44..531e945 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -2060,6 +2060,29 @@ static int __init allocate_lpi_tables(void) return 0; } +static u64 its_clear_vpend_valid(void __iomem *vlpi_base) +{ + u32 count = 1000000; /* 1s! */ + bool clean; + u64 val; + + val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER); + val &= ~GICR_VPENDBASER_Valid; + gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER); + + do { + val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER); + clean = !(val & GICR_VPENDBASER_Dirty); + if (!clean) { + count--; + cpu_relax(); + udelay(1); + } + } while (!clean && count); + + return val; +} + static void its_cpu_init_lpis(void) { void __iomem *rbase = gic_data_rdist_rd_base(); @@ -2145,6 +2168,30 @@ static void its_cpu_init_lpis(void) val |= GICR_CTLR_ENABLE_LPIS; writel_relaxed(val, rbase + GICR_CTLR); + if (gic_rdists->has_vlpis) { + void __iomem *vlpi_base = gic_data_rdist_vlpi_base(); + + /* + * It's possible for CPU to receive VLPIs before it is + * sheduled as a vPE, especially for the first CPU, and the + * VLPI with INTID larger than 2^(IDbits+1) will be considered + * as out of range and dropped by GIC. + * So we initialize IDbits to known value to avoid VLPI drop. + */ + val = (LPI_NRBITS - 1) & GICR_VPROPBASER_IDBITS_MASK; + pr_debug("GICv4: CPU%d: Init IDbits to 0x%llx for GICR_VPROPBASER\n", + smp_processor_id(), val); + gits_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER); + + /* + * Also clear Valid bit of GICR_VPENDBASER, in case some + * ancient programming gets left in and has possibility of + * corrupting memory. + */ + val = its_clear_vpend_valid(vlpi_base); + WARN_ON(val & GICR_VPENDBASER_Dirty); + } + /* Make sure the GIC has seen the above */ dsb(sy); out: @@ -2757,26 +2804,11 @@ static void its_vpe_schedule(struct its_vpe *vpe) static void its_vpe_deschedule(struct its_vpe *vpe) { void __iomem *vlpi_base = gic_data_rdist_vlpi_base(); - u32 count = 1000000; /* 1s! */ - bool clean; u64 val; - /* We're being scheduled out */ - val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER); - val &= ~GICR_VPENDBASER_Valid; - gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER); - - do { - val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER); - clean = !(val & GICR_VPENDBASER_Dirty); - if (!clean) { - count--; - cpu_relax(); - udelay(1); - } - } while (!clean && count); + val = its_clear_vpend_valid(vlpi_base); - if (unlikely(!clean && !count)) { + if (unlikely(val & GICR_VPENDBASER_Dirty)) { pr_err_ratelimited("ITS virtual pending table not cleaning\n"); vpe->idai = false; vpe->pending_last = true; -- 1.8.3.1