Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp4063090imm; Mon, 17 Sep 2018 07:39:15 -0700 (PDT) X-Google-Smtp-Source: ANB0VdZKdJOP0jrxvcOsPLOQe4MWq0llcBUsVMZXBLqDH2N1viYvf9UYiUzkt95s0vmPLfaNfBpv X-Received: by 2002:a62:225d:: with SMTP id i90-v6mr26223084pfi.246.1537195155133; Mon, 17 Sep 2018 07:39:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1537195155; cv=none; d=google.com; s=arc-20160816; b=EiPj4zGQ1OnrqjFJbnnOs3EEV7dXcxaDaYXakRIqwuhO1eqnkwS1dE3MYQvBI6Vw9c 8OME69md+QJ4qnjLcKI0MKlzy52X6C8i8jQIYvR3FLons7EQDV6k/hxN8EErcVG2JKmr SLBeRKFsMBkmw5qDrcCNzB4wzTnxYEYWjxzZ7Nz8XsT7FunUrt+t3hFIL30N8gLGKH73 Fru1mWZ216l1StDWT+0ZEtk9YuGCHw+r8VPgWnl1kkKQcYURkGRIPBET4GRxlDIXkyYT OHKalgkYMH329xvfSIJFJ+DoM9t20Kv5hERlCNEO5+gz9t7MHFZv19YHq5H5EdOHno0n S8TQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-disposition:mime-version :references:subject:cc:to:from:date:user-agent:message-id; bh=z9c40A0yzVU7FzirLDUgRB5baLRiQEXPUmXxrLWSfPw=; b=VOexb8G/bmR6TtawwtP0wQ051y4MMgENghVHNrQlaDv72vMTmMCaDM4mQL6K07fzVj GtW4g3QWAmRxwUtdX6tFSfI95HMTViN1eSNsrq3GOpPmlTAoPvpYnW1dV810AhaVsRhH tLEZyBXZ44cw+jka1EkvAKc/uUk3p4wpYYeV9ieTiZysFC5+hSzW5MRMsQS2vD4g0yLe Zo1TuTTIl0P6sYR5iLiFtpsettro1c8D2AYQBU1040YdhTxJzcXqBI8SeUOdaXoGbfYj KRwHfN0Q71fMzREWJqxUhD2vQkFON0HR4uhYsMLdJsKwD7nCVYaq9I0lU/BYZ03yyZ3Q l0VQ== 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 d16-v6si15493988pfe.267.2018.09.17.07.38.42; Mon, 17 Sep 2018 07:39:15 -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 S1729000AbeIQUFZ (ORCPT + 99 others); Mon, 17 Sep 2018 16:05:25 -0400 Received: from Galois.linutronix.de ([146.0.238.70]:55207 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728840AbeIQUEm (ORCPT ); Mon, 17 Sep 2018 16:04:42 -0400 Received: from localhost ([127.0.0.1] helo=nanos.tec.linutronix.de) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1g1ue8-0008Sd-NA; Mon, 17 Sep 2018 16:37:04 +0200 Message-Id: <20180917143546.078998733@linutronix.de> User-Agent: quilt/0.65 Date: Mon, 17 Sep 2018 16:29:11 +0200 From: Thomas Gleixner To: LKML Cc: x86@kernel.org, Peter Zijlstra , Bin Yang , Dave Hansen , Mark Gross Subject: [patch V3 05/11] x86/mm/cpa: Add debug mechanism References: <20180917142906.384767038@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline; filename=x86-mm-cpa--Add-proper-debug-output.patch Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- arch/x86/mm/pageattr.c | 61 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 9 deletions(-) --- 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 @@ -392,6 +399,28 @@ static pgprotval_t protect_kernel_text_r } #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 @@ -399,19 +428,31 @@ static pgprotval_t protect_kernel_text_r * 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); } @@ -683,10 +724,11 @@ static int __should_split_large_page(pte * 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; @@ -1296,7 +1338,8 @@ static int __change_page_attr(struct cpa 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);