public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
To: arjan@linux.intel.com, mingo@elte.hu, tglx@linutronix.de,
	hpa@zytor.com, andi@firstfloor.org
Cc: linux-kernel@vger.kernel.org,
	Suresh Siddha <suresh.b.siddha@intel.com>,
	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Subject: [patch 1/2] x86: track memtype for RAM in page struct
Date: Fri, 12 Sep 2008 17:00:04 -0700	[thread overview]
Message-ID: <20080913000051.819383000@linux-os.sc.intel.com> (raw)
In-Reply-To: 20080913000003.732756000@linux-os.sc.intel.com

[-- Attachment #1: use_pg_arch_1_for_ram_tracking.patch --]
[-- Type: text/plain, Size: 5650 bytes --]

From: Suresh Siddha <suresh.b.siddha@intel.com>
Subject: [patch 1/2] x86: track memtype for RAM in page struct

Track the memtype for RAM pages in page struct instead of using the memtype
list. This avoids the explosion in the number of entries in memtype list
(of the order of 20,000 with AGP) and makes the PAT tracking simpler. We are
using PG_arch_1 bit in page->flags.

We still use the memtype list for non RAM pages.

Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>

---
 arch/x86/mm/ioremap.c  |   19 +++++++++++
 arch/x86/mm/pat.c      |   83 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/asm-x86/page.h |    1 
 3 files changed, 103 insertions(+)

Index: tip/arch/x86/mm/ioremap.c
===================================================================
--- tip.orig/arch/x86/mm/ioremap.c	2008-09-12 16:03:33.000000000 -0700
+++ tip/arch/x86/mm/ioremap.c	2008-09-12 16:23:33.000000000 -0700
@@ -102,6 +102,25 @@ int page_is_ram(unsigned long pagenr)
 	return 0;
 }
 
+int pagerange_is_ram(unsigned long start, unsigned long end)
+{
+	int ram_page = 0, not_rampage = 0;
+	unsigned long page_nr;
+
+	for (page_nr = (start >> PAGE_SHIFT); page_nr < (end >> PAGE_SHIFT);
+	     ++page_nr) {
+		if (page_is_ram(page_nr))
+			ram_page = 1;
+		else
+			not_rampage = 1;
+
+		if (ram_page == not_rampage)
+			return -1;
+	}
+
+	return ram_page;
+}
+
 /*
  * Fix up the linear direct mapping of the kernel to avoid cache attribute
  * conflicts.
Index: tip/arch/x86/mm/pat.c
===================================================================
--- tip.orig/arch/x86/mm/pat.c	2008-09-12 16:03:33.000000000 -0700
+++ tip/arch/x86/mm/pat.c	2008-09-12 16:23:33.000000000 -0700
@@ -211,6 +211,75 @@ static struct memtype *cached_entry;
 static u64 cached_start;
 
 /*
+ * RED-PEN:  TODO: Add PageReserved() check aswell here,
+ * once we add SetPageReserved() to all the drivers using
+ * set_memory_* or set_pages_*
+ *
+ * This will help prevent accidentally freeing pages
+ * before setting the attribute back to WB.
+ */
+
+/*
+ * For RAM pages, mark the pages with non WB attribute using
+ * PG_arch_1. We allow only one set_memory_uc() or set_memory_wc()
+ * on a RAM page at a time before marking it as WB again. This is ok,
+ * because only one(driver) will be owning the page and doing set_memory_*()
+ * calls.
+ *
+ * For now, we use PG_arch_1 to track that the RAM page is being mapped
+ * as non WB. In future, based on the need we can use one or more flags
+ * (or some other mechanism in page_struct) to keep track of the actual
+ * attribute that the page is mapped to.
+ */
+static int reserve_ram_pages_type(u64 start, u64 end, unsigned long req_type,
+		       unsigned long *new_type)
+{
+	struct page *page;
+	u64 pfn, end_pfn;
+
+	for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) {
+		page = pfn_to_page(pfn);
+		if (page_mapped(page) || test_bit(PG_arch_1, &page->flags))
+			goto out;
+
+		set_bit(PG_arch_1, &page->flags);
+	}
+	return 0;
+
+out:
+	end_pfn = pfn;
+	for (pfn = (start >> PAGE_SHIFT); pfn < end_pfn; ++pfn) {
+		page = pfn_to_page(pfn);
+		clear_bit(PG_arch_1, &page->flags);
+	}
+
+	return -EINVAL;
+}
+
+static int free_ram_pages_type(u64 start, u64 end)
+{
+	struct page *page;
+	u64 pfn, end_pfn;
+
+	for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) {
+		page = pfn_to_page(pfn);
+		if (page_mapped(page) || !test_bit(PG_arch_1, &page->flags))
+			goto out;
+
+		clear_bit(PG_arch_1, &page->flags);
+	}
+	return 0;
+
+out:
+	end_pfn = pfn;
+	for (pfn = (start >> PAGE_SHIFT); pfn < end_pfn; ++pfn) {
+		page = pfn_to_page(pfn);
+		set_bit(PG_arch_1, &page->flags);
+	}
+	return -EINVAL;
+}
+
+/*
  * req_type typically has one of the:
  * - _PAGE_CACHE_WB
  * - _PAGE_CACHE_WC
@@ -232,6 +301,7 @@ int reserve_memtype(u64 start, u64 end, 
 	unsigned long actual_type;
 	struct list_head *where;
 	int err = 0;
+	int is_range_ram;
 
  	BUG_ON(start >= end); /* end is exclusive */
 
@@ -270,6 +340,12 @@ int reserve_memtype(u64 start, u64 end, 
 		actual_type = pat_x_mtrr_type(start, end,
 					      req_type & _PAGE_CACHE_MASK);
 
+	is_range_ram = pagerange_is_ram(start,end);
+	if (is_range_ram == 1)
+		return reserve_ram_pages_type(start, end, req_type, new_type);
+	else if (is_range_ram < 0)
+		return -EINVAL;
+
 	new  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
 	if (!new)
 		return -ENOMEM;
@@ -358,6 +434,7 @@ int free_memtype(u64 start, u64 end)
 {
 	struct memtype *entry;
 	int err = -EINVAL;
+	int is_range_ram;
 
 	if (!pat_enabled)
 		return 0;
@@ -366,6 +443,12 @@ int free_memtype(u64 start, u64 end)
 	if (is_ISA_range(start, end - 1))
 		return 0;
 
+	is_range_ram = pagerange_is_ram(start,end);
+	if (is_range_ram == 1)
+		return free_ram_pages_type(start, end);
+	else if (is_range_ram < 0)
+		return -EINVAL;
+
 	spin_lock(&memtype_lock);
 	list_for_each_entry(entry, &memtype_list, nd) {
 		if (entry->start == start && entry->end == end) {
Index: tip/include/asm-x86/page.h
===================================================================
--- tip.orig/include/asm-x86/page.h	2008-09-12 16:03:33.000000000 -0700
+++ tip/include/asm-x86/page.h	2008-09-12 16:23:33.000000000 -0700
@@ -57,6 +57,7 @@ typedef struct { pgdval_t pgd; } pgd_t;
 typedef struct { pgprotval_t pgprot; } pgprot_t;
 
 extern int page_is_ram(unsigned long pagenr);
+extern int pagerange_is_ram(unsigned long start, unsigned long end);
 extern int devmem_is_allowed(unsigned long pagenr);
 extern void map_devmem(unsigned long pfn, unsigned long size,
 		       pgprot_t vma_prot);

-- 


  reply	other threads:[~2008-09-13  0:10 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-13  0:00 [patch 0/2] PAT fix/optimization Venkatesh Pallipadi
2008-09-13  0:00 ` Venkatesh Pallipadi [this message]
2008-09-13 17:03   ` [patch 1/2] x86: track memtype for RAM in page struct Jeremy Fitzhardinge
2008-09-14 13:29     ` Ingo Molnar
2008-09-14 14:18       ` Jeremy Fitzhardinge
2008-09-14 14:22         ` Ingo Molnar
2008-09-23 21:46           ` Venki Pallipadi
2008-09-23 21:59             ` Christoph Lameter
2008-09-24 15:53               ` [patch 1/2] x86: track memtype for RAM in page struct - v3 Venki Pallipadi
2008-09-27 17:59                 ` Ingo Molnar
2008-09-30  7:28                 ` Nick Piggin
2008-09-30 11:21                   ` Ingo Molnar
2008-09-30 21:14                     ` Suresh Siddha
2008-10-01  9:29                       ` Ingo Molnar
2008-10-02  2:27                       ` Nick Piggin
2008-09-13 17:24   ` [patch 1/2] x86: track memtype for RAM in page struct Frans Pop
2008-09-14 14:12   ` Ingo Molnar
2008-09-23 21:48     ` Pallipadi, Venkatesh
2008-09-13  0:00 ` [patch 2/2] x86: Handle error returns in set_memory_* Venkatesh Pallipadi
2008-09-14 13:27   ` Ingo Molnar
2008-09-14 14:35     ` Frans Pop
2008-09-14 14:10   ` Ingo Molnar
2008-09-30  8:36     ` Frans Pop
2008-09-30 21:29       ` Suresh Siddha

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080913000051.819383000@linux-os.sc.intel.com \
    --to=venkatesh.pallipadi@intel.com \
    --cc=andi@firstfloor.org \
    --cc=arjan@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=suresh.b.siddha@intel.com \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox