From patchwork Fri Mar 11 21:13:03 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Wilcox, Matthew R" X-Patchwork-Id: 8569181 Return-Path: X-Original-To: patchwork-linux-nvdimm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B79569F38C for ; Fri, 11 Mar 2016 21:13:10 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A488A20361 for ; Fri, 11 Mar 2016 21:13:09 +0000 (UTC) Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B77382034B for ; Fri, 11 Mar 2016 21:13:08 +0000 (UTC) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 60B151A1F86; Fri, 11 Mar 2016 13:13:24 -0800 (PST) X-Original-To: linux-nvdimm@lists.01.org Delivered-To: linux-nvdimm@lists.01.org Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by ml01.01.org (Postfix) with ESMTP id 5D4751A1F81 for ; Fri, 11 Mar 2016 13:13:23 -0800 (PST) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga104.fm.intel.com with ESMTP; 11 Mar 2016 13:13:07 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.24,321,1455004800"; d="scan'208";a="934952949" Received: from jduan1-mobl2.amr.corp.intel.com (HELO thog.int.wil.cx) ([10.252.134.213]) by fmsmga002.fm.intel.com with SMTP; 11 Mar 2016 13:13:06 -0800 Received: by thog.int.wil.cx (Postfix, from userid 1000) id 86CBB5F9BB; Fri, 11 Mar 2016 16:13:05 -0500 (EST) From: Matthew Wilcox To: Dan Williams Subject: [PATCH 2/3] pfn_t: Support for huge PFNs Date: Fri, 11 Mar 2016 16:13:03 -0500 Message-Id: <1457730784-9890-3-git-send-email-matthew.r.wilcox@intel.com> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1457730784-9890-1-git-send-email-matthew.r.wilcox@intel.com> References: <1457730784-9890-1-git-send-email-matthew.r.wilcox@intel.com> Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, Matthew Wilcox , linux-nvdimm@lists.01.org X-BeenThere: linux-nvdimm@lists.01.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "Linux-nvdimm developer list." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: linux-nvdimm-bounces@lists.01.org Sender: "Linux-nvdimm" X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP We need to put entries in the radix tree that represent PMDs and PUDs. Use another bit to determine if this PFN entry represents a huge page or not. If it does, we know the bottom few bits of the PFN are zero, so we can reuse them to distinguish between PMDs and PUDs. Thanks to Neil Brown for suggesting this more compact encoding. Signed-off-by: Matthew Wilcox --- include/linux/pfn_t.h | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/include/linux/pfn_t.h b/include/linux/pfn_t.h index 37c596c..0ff4c4e 100644 --- a/include/linux/pfn_t.h +++ b/include/linux/pfn_t.h @@ -8,14 +8,21 @@ * PFN_SG_LAST - pfn references a page and is the last scatterlist entry * PFN_DEV - pfn is not covered by system memmap by default * PFN_MAP - pfn has a dynamic page mapping established by a device driver + * PFN_HUGE - pfn represents a huge page * * Note that the bottom two bits in the pfn_t match the bottom two bits in the * scatterlist so sg_is_chain() and sg_is_last() work. These bits are also * used by the radix tree for its own purposes, but a PFN cannot be in both a * radix tree and a scatterlist simultaneously. If a PFN is moved between the * two usages, care should be taken to clear/set these bits appropriately. + * + * If PFN_HUGE is set, the bottom PMD_SHIFT-PAGE_SHIFT bits are known to be + * zero. We reuse them to indicate whether the PFN represents a PMD or a PUD. + * + * This scheme supports 27 bits on a 32-bit system (512GB of physical address + * space) and 59 bits on a 64-bit system (2048EB of physical address space). */ -#define PFN_FLAG_BITS 4 +#define PFN_FLAG_BITS 5 #define PFN_FLAGS_MASK ((1 << PFN_FLAG_BITS) - 1) #define __PFN_MAX ((1 << (BITS_PER_LONG - PFN_FLAG_BITS)) - 1) #define PFN_SG_CHAIN 0x01UL @@ -23,6 +30,11 @@ #define PFN_SG_MASK (PFN_SG_CHAIN | PFN_SG_LAST) #define PFN_DEV 0x04UL #define PFN_MAP 0x08UL +#define PFN_HUGE 0x10UL +#define PFN_SIZE_MASK 0x30UL +#define PFN_SIZE_PTE 0x00UL +#define PFN_SIZE_PMD 0x10UL +#define PFN_SIZE_PUD 0x30UL #if 0 #define PFN_T_BUG_ON(x) BUG_ON(x) @@ -35,7 +47,7 @@ static inline pfn_t __pfn_to_pfn_t(unsigned long pfn, u64 flags) pfn_t pfn_t = { .val = (pfn << PFN_FLAG_BITS) | flags }; PFN_T_BUG_ON(pfn & ~__PFN_MAX); - PFN_T_BUG_ON(flags & ~PFN_FLAGS_MASK); + PFN_T_BUG_ON(flags & ~(PFN_FLAGS_MASK | PFN_SIZE_MASK)); return pfn_t; } @@ -46,9 +58,12 @@ static inline pfn_t pfn_to_pfn_t(unsigned long pfn) return __pfn_to_pfn_t(pfn, 0); } +/* The bottom bits of the PFN may be set if PFN_HUGE is set */ static inline unsigned long pfn_t_to_pfn(pfn_t pfn) { unsigned long v = pfn.val; + if (v & PFN_HUGE) + v &= ~PFN_SIZE_MASK; return v >> PFN_FLAG_BITS; }