Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp2517683pxj; Mon, 10 May 2021 05:03:06 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy2IHkE58+qB39gZMGQJCOQo9d7Q/7FH+OILfhbY5jY59Upd6Xf+AjtXtkeYMu4z8QoHxlF X-Received: by 2002:a05:6402:350d:: with SMTP id b13mr28992705edd.21.1620648185986; Mon, 10 May 2021 05:03:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1620648185; cv=none; d=google.com; s=arc-20160816; b=mfobFpyqCLxdInzwVIYQ4HALBry4/iOPx8sxpfVhauUDQr+YjbF2WpWfQNCIZVZkXC 9HPMa259CrvKbll0Ma7gYFY9LCqO8VaKtMdZhpF1Y87Ix+5d5CdL3oVmk2wLBZks+K7D txc+y17PHH5erg3x7eEbuucYjUvxoj/o0+LBsHk7l6MvbXljfNIH7J/muu0eSV/7TzKf huxwXdYAakbwdaIuf7glKLHjIiZxJLJb9M2NCNnLliEJVTgm1XWUEiqvgt5z9YErA15l HxxRf/xzfO476WAN+0nt7KG/48+tmLMIRUaymKSh+dcly0Gq6RGGgpiV55L9svUl3Z4j yOpA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=saw12R83GwaKBrx1gDaTHDgbDh3mordfTfg0l0rPeqw=; b=QG+FEHWmPV+4dovfS6tC1HhmlhgQiudNz+g2iOG3v5HFTgnJnZxaORg24swk0rukWF d7PBoDgRLaVt878x7UtTntB65uud1vAhUG6i5QQwT95epCtwzkHD4rwKBpPPdtUCNiTo RwDdFUjIgL7usk5obxq6ErKdDAfjpD+8Wf1k9xtyVyQ9iTaKR0O398/HS3ULY4aoEUEh leJWzYSyhTXoI1shaTCnZPaE+iUkfkxGCUQPhyvvSHg4AsHSz+NpRQBmiKxEVSImRU6z /fwDQQ3YaZL6pAPlqyWhCxodzwsYpqaoUr6znU1qL0GtFwoVpCIaXqpv04Ccou8Pb2Mz xHwA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=xFjdUrRy; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id n2si12692259edv.130.2021.05.10.05.02.40; Mon, 10 May 2021 05:03:05 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=xFjdUrRy; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235726AbhEJLxJ (ORCPT + 99 others); Mon, 10 May 2021 07:53:09 -0400 Received: from mail.kernel.org ([198.145.29.99]:39736 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233413AbhEJLDY (ORCPT ); Mon, 10 May 2021 07:03:24 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 28C356191A; Mon, 10 May 2021 10:54:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1620644060; bh=qEAZwf33f4+0K31n2LAtyuviAMwGTjTrupPYT6lXrm8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=xFjdUrRyVlQ/lmV+6w399G+IkB0SqbpUs+tsoJ1PUsgKrmXB2mscCJM8/h0URkYUC A+q9vRjgX3nLR1brC4lxidPEkTYuqKqFrCLpJtuDe4WV5ZguCO4Db5BON9eZTbtQhi jM9Juz4ElklIr4a/K1XfA+MDidnwebk/nHwWNHkE= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, David Woodhouse , Lu Baolu , Nadav Amit , Alex Williamson , Joerg Roedel , Kevin Tian , "Gonglei (Arei)" , "Longpeng(Mike)" , Joerg Roedel Subject: [PATCH 5.11 271/342] iommu/vt-d: Force to flush iotlb before creating superpage Date: Mon, 10 May 2021 12:21:01 +0200 Message-Id: <20210510102019.051377362@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210510102010.096403571@linuxfoundation.org> References: <20210510102010.096403571@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Longpeng(Mike) commit 38c527aeb41926c71902dd42f788a8b093b21416 upstream. The translation caches may preserve obsolete data when the mapping size is changed, suppose the following sequence which can reveal the problem with high probability. 1.mmap(4GB,MAP_HUGETLB) 2. while (1) { (a) DMA MAP 0,0xa0000 (b) DMA UNMAP 0,0xa0000 (c) DMA MAP 0,0xc0000000 * DMA read IOVA 0 may failure here (Not present) * if the problem occurs. (d) DMA UNMAP 0,0xc0000000 } The page table(only focus on IOVA 0) after (a) is: PML4: 0x19db5c1003 entry:0xffff899bdcd2f000 PDPE: 0x1a1cacb003 entry:0xffff89b35b5c1000 PDE: 0x1a30a72003 entry:0xffff89b39cacb000 PTE: 0x21d200803 entry:0xffff89b3b0a72000 The page table after (b) is: PML4: 0x19db5c1003 entry:0xffff899bdcd2f000 PDPE: 0x1a1cacb003 entry:0xffff89b35b5c1000 PDE: 0x1a30a72003 entry:0xffff89b39cacb000 PTE: 0x0 entry:0xffff89b3b0a72000 The page table after (c) is: PML4: 0x19db5c1003 entry:0xffff899bdcd2f000 PDPE: 0x1a1cacb003 entry:0xffff89b35b5c1000 PDE: 0x21d200883 entry:0xffff89b39cacb000 (*) Because the PDE entry after (b) is present, it won't be flushed even if the iommu driver flush cache when unmap, so the obsolete data may be preserved in cache, which would cause the wrong translation at end. However, we can see the PDE entry is finally switch to 2M-superpage mapping, but it does not transform to 0x21d200883 directly: 1. PDE: 0x1a30a72003 2. __domain_mapping dma_pte_free_pagetable Set the PDE entry to ZERO Set the PDE entry to 0x21d200883 So we must flush the cache after the entry switch to ZERO to avoid the obsolete info be preserved. Cc: David Woodhouse Cc: Lu Baolu Cc: Nadav Amit Cc: Alex Williamson Cc: Joerg Roedel Cc: Kevin Tian Cc: Gonglei (Arei) Fixes: 6491d4d02893 ("intel-iommu: Free old page tables before creating superpage") Cc: # v3.0+ Link: https://lore.kernel.org/linux-iommu/670baaf8-4ff8-4e84-4be3-030b95ab5a5e@huawei.com/ Suggested-by: Lu Baolu Signed-off-by: Longpeng(Mike) Acked-by: Lu Baolu Link: https://lore.kernel.org/r/20210415004628.1779-1-longpeng2@huawei.com Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel/iommu.c | 52 ++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 14 deletions(-) --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -2294,6 +2294,41 @@ static inline int hardware_largepage_cap return level; } +/* + * Ensure that old small page tables are removed to make room for superpage(s). + * We're going to add new large pages, so make sure we don't remove their parent + * tables. The IOTLB/devTLBs should be flushed if any PDE/PTEs are cleared. + */ +static void switch_to_super_page(struct dmar_domain *domain, + unsigned long start_pfn, + unsigned long end_pfn, int level) +{ + unsigned long lvl_pages = lvl_to_nr_pages(level); + struct dma_pte *pte = NULL; + int i; + + while (start_pfn <= end_pfn) { + if (!pte) + pte = pfn_to_dma_pte(domain, start_pfn, &level); + + if (dma_pte_present(pte)) { + dma_pte_free_pagetable(domain, start_pfn, + start_pfn + lvl_pages - 1, + level + 1); + + for_each_domain_iommu(i, domain) + iommu_flush_iotlb_psi(g_iommus[i], domain, + start_pfn, lvl_pages, + 0, 0); + } + + pte++; + start_pfn += lvl_pages; + if (first_pte_in_page(pte)) + pte = NULL; + } +} + static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, unsigned long phys_pfn, unsigned long nr_pages, int prot) @@ -2327,22 +2362,11 @@ __domain_mapping(struct dmar_domain *dom return -ENOMEM; /* It is large page*/ if (largepage_lvl > 1) { - unsigned long nr_superpages, end_pfn; + unsigned long end_pfn; pteval |= DMA_PTE_LARGE_PAGE; - lvl_pages = lvl_to_nr_pages(largepage_lvl); - - nr_superpages = nr_pages / lvl_pages; - end_pfn = iov_pfn + nr_superpages * lvl_pages - 1; - - /* - * Ensure that old small page tables are - * removed to make room for superpage(s). - * We're adding new large pages, so make sure - * we don't remove their parent tables. - */ - dma_pte_free_pagetable(domain, iov_pfn, end_pfn, - largepage_lvl + 1); + end_pfn = ((iov_pfn + nr_pages) & level_mask(largepage_lvl)) - 1; + switch_to_super_page(domain, iov_pfn, end_pfn, largepage_lvl); } else { pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE; }