Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp2380251imm; Thu, 27 Sep 2018 11:50:45 -0700 (PDT) X-Google-Smtp-Source: ACcGV60VkW1Anc1cEhXJue72WJnky0p8ho2TUy/Hs4dGE0hkXVQ1B16ou3hcV3dcS3e48ey9+FMP X-Received: by 2002:a62:45d2:: with SMTP id n79-v6mr12831008pfi.137.1538074245427; Thu, 27 Sep 2018 11:50:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1538074245; cv=none; d=google.com; s=arc-20160816; b=xx8LdSO+4B7HTBl5Cu6JNtkqJViHQa3Fng/Y+YJoQLPCiMuF1O999ZbR8RaBj5laDa LEpeBkfzBIPEhhdFI7FcmYyHrrcUE/UJg8bSrD7pbFSM2DpnsFJQYA396tvgrCLozGIm GH4Mapvt/+9nU8nzmlvrq6HuGSEQr47u0p2qeiHVycdzl9dEwVc7lw7g6StJoVMvDsO9 JLoLfZ5zgTVtg/eLtUDJl1YEYJiYPltZRS3OPgu9Ha2Uc2QkZBlMeUOPh8rmGNooXx14 gmumfYHWbOAwSTkEWyFyaKXWtYhQXj31c5Mt4C646ayOY/YCQHtfSRu0TVP7NeFrjZpT 7SUA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-disposition :content-transfer-encoding:mime-version:robot-unsubscribe:robot-id :git-commit-id:subject:to:references:in-reply-to:reply-to:cc :message-id:from:date; bh=GOqP4JNoETgdTUmRz+yUbYCQldk4G/Sz6mY9cFutI/4=; b=oZobYsSHT1T2r5lSXRcXk6fy5Bk4g8XdHL3mZjLT4w4C79CWEMf6TFlbWSjNEyOFgF zgAndcDRcC4o00kqZBgvMeOfBjLgWebrZL4cEFi/1pxGZVykhIHqacd+zqYYfpmpLKHu A58+jcLn/nzDxwztg0Lq8hon99+enh/9nu7BkB/hgRbUNmpWhsgv3FpU+EuKh6Ihkl1b lnC7dR2zlOnJy3WBIoWWrqrBnLbnKGRj/uis7SbOVAwJpVl87yAQiXa0wp02WrAtDih8 GX6bdQM8hRmXj2ftg2m45kmpZbjFZA31alIAw4JU+nAaGLjZZkm9q3IxmYCcAyI2dfIP e+tg== 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 z127-v6si2794159pgb.455.2018.09.27.11.50.29; Thu, 27 Sep 2018 11:50:45 -0700 (PDT) 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 S1728514AbeI1BIL (ORCPT + 99 others); Thu, 27 Sep 2018 21:08:11 -0400 Received: from terminus.zytor.com ([198.137.202.136]:37447 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727307AbeI1BIL (ORCPT ); Thu, 27 Sep 2018 21:08:11 -0400 Received: from terminus.zytor.com (localhost [127.0.0.1]) by terminus.zytor.com (8.15.2/8.15.2) with ESMTPS id w8RIm12g129480 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 27 Sep 2018 11:48:01 -0700 Received: (from tipbot@localhost) by terminus.zytor.com (8.15.2/8.15.2/Submit) id w8RIm16Y129477; Thu, 27 Sep 2018 11:48:01 -0700 Date: Thu, 27 Sep 2018 11:48:01 -0700 X-Authentication-Warning: terminus.zytor.com: tipbot set sender to tipbot@zytor.com using -f From: tip-bot for Thomas Gleixner Message-ID: Cc: linux-kernel@vger.kernel.org, peterz@infradead.org, mingo@kernel.org, mark.gross@intel.com, bin.yang@intel.com, tglx@linutronix.de, hpa@zytor.com, dave.hansen@intel.com Reply-To: linux-kernel@vger.kernel.org, peterz@infradead.org, mingo@kernel.org, mark.gross@intel.com, bin.yang@intel.com, tglx@linutronix.de, hpa@zytor.com, dave.hansen@intel.com In-Reply-To: <20180917143546.078998733@linutronix.de> References: <20180917143546.078998733@linutronix.de> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/mm] x86/mm/cpa: Add debug mechanism Git-Commit-ID: 4046460b867f8b041c81c26c09d3bcad6d6e814e X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline X-Spam-Status: No, score=-0.9 required=5.0 tests=ALL_TRUSTED,BAYES_00, DATE_IN_FUTURE_24_48 autolearn=no autolearn_force=no version=3.4.1 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on terminus.zytor.com Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: 4046460b867f8b041c81c26c09d3bcad6d6e814e Gitweb: https://git.kernel.org/tip/4046460b867f8b041c81c26c09d3bcad6d6e814e Author: Thomas Gleixner AuthorDate: Mon, 17 Sep 2018 16:29:11 +0200 Committer: Thomas Gleixner CommitDate: Thu, 27 Sep 2018 20:39:38 +0200 x86/mm/cpa: Add debug mechanism The whole static protection magic is silently fixing up anything which is handed in. That's just wrong. The offending call sites need to be fixed. Add a debug mechanism which emits a warning if a requested mapping needs to be fixed up. The DETECT debug mechanism is really not meant to be enabled except for developers, so limit the output hard to the protection fixups. Signed-off-by: Thomas Gleixner Reviewed-by: Dave Hansen Cc: Peter Zijlstra Cc: Bin Yang Cc: Mark Gross Link: https://lkml.kernel.org/r/20180917143546.078998733@linutronix.de --- arch/x86/mm/pageattr.c | 61 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 61ff27848452..1f2519055b30 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -42,6 +42,13 @@ struct cpa_data { struct page **pages; }; +enum cpa_warn { + CPA_PROTECT, + CPA_DETECT, +}; + +static const int cpa_warn_level = CPA_PROTECT; + /* * Serialize cpa() (for !DEBUG_PAGEALLOC which uses large identity mappings) * using cpa_lock. So that we don't allow any other cpu, with stale large tlb @@ -395,6 +402,28 @@ static pgprotval_t protect_kernel_text_ro(unsigned long start, } #endif +static inline bool conflicts(pgprot_t prot, pgprotval_t val) +{ + return (pgprot_val(prot) & ~val) != pgprot_val(prot); +} + +static inline void check_conflict(int warnlvl, pgprot_t prot, pgprotval_t val, + unsigned long start, unsigned long end, + unsigned long pfn, const char *txt) +{ + static const char *lvltxt[] = { + [CPA_PROTECT] = "protect", + [CPA_DETECT] = "detect", + }; + + if (warnlvl > cpa_warn_level || !conflicts(prot, val)) + return; + + pr_warn("CPA %8s %10s: 0x%016lx - 0x%016lx PFN %lx req %016llx prevent %016llx\n", + lvltxt[warnlvl], txt, start, end, pfn, (unsigned long long)pgprot_val(prot), + (unsigned long long)val); +} + /* * Certain areas of memory on x86 require very specific protection flags, * for example the BIOS area or kernel text. Callers don't always get this @@ -402,19 +431,31 @@ static pgprotval_t protect_kernel_text_ro(unsigned long start, * checks and fixes these known static required protection bits. */ static inline pgprot_t static_protections(pgprot_t prot, unsigned long start, - unsigned long pfn, unsigned long npg) + unsigned long pfn, unsigned long npg, + int warnlvl) { - pgprotval_t forbidden; + pgprotval_t forbidden, res; unsigned long end; /* Operate on the virtual address */ end = start + npg * PAGE_SIZE - 1; - forbidden = protect_kernel_text(start, end); - forbidden |= protect_kernel_text_ro(start, end); + + res = protect_kernel_text(start, end); + check_conflict(warnlvl, prot, res, start, end, pfn, "Text NX"); + forbidden = res; + + res = protect_kernel_text_ro(start, end); + check_conflict(warnlvl, prot, res, start, end, pfn, "Text RO"); + forbidden |= res; /* Check the PFN directly */ - forbidden |= protect_pci_bios(pfn, pfn + npg - 1); - forbidden |= protect_rodata(pfn, pfn + npg - 1); + res = protect_pci_bios(pfn, pfn + npg - 1); + check_conflict(warnlvl, prot, res, start, end, pfn, "PCIBIOS NX"); + forbidden |= res; + + res = protect_rodata(pfn, pfn + npg - 1); + check_conflict(warnlvl, prot, res, start, end, pfn, "Rodata RO"); + forbidden |= res; return __pgprot(pgprot_val(prot) & ~forbidden); } @@ -686,10 +727,11 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address, * in it results in a different pgprot than the first one of the * requested range. If yes, then the page needs to be split. */ - new_prot = static_protections(req_prot, address, pfn, 1); + new_prot = static_protections(req_prot, address, pfn, 1, CPA_DETECT); pfn = old_pfn; for (i = 0, addr = lpaddr; i < numpages; i++, addr += PAGE_SIZE, pfn++) { - pgprot_t chk_prot = static_protections(req_prot, addr, pfn, 1); + pgprot_t chk_prot = static_protections(req_prot, addr, pfn, 1, + CPA_DETECT); if (pgprot_val(chk_prot) != pgprot_val(new_prot)) return 1; @@ -1299,7 +1341,8 @@ repeat: pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr); pgprot_val(new_prot) |= pgprot_val(cpa->mask_set); - new_prot = static_protections(new_prot, address, pfn, 1); + new_prot = static_protections(new_prot, address, pfn, 1, + CPA_PROTECT); new_prot = pgprot_clear_protnone_bits(new_prot);