All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] powerpc: Track backing pages used allocated by vmemmap_populate()
@ 2010-03-26  7:12 Mark Nelson
  2010-04-13  4:16 ` [PATCH v2] powerpc: Track backing pages " Mark Nelson
  0 siblings, 1 reply; 7+ messages in thread
From: Mark Nelson @ 2010-03-26  7:12 UTC (permalink / raw)
  To: linuxppc-dev

We need to keep track of the backing pages that get allocated by
vmemmap_populate() so that when we use kdump, the dump-capture kernel can
find these pages in memory.

We use a linked list of structures that contain the physical address of the
backing page and corresponding virtual address to track the backing pages.
And we use a simple spinlock to protect the vmemmap_list.

Signed-off-by: Mark Nelson <markn@au1.ibm.com>
---
 arch/powerpc/include/asm/pgalloc-64.h |    7 +++++++
 arch/powerpc/mm/init_64.c             |   27 +++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

Index: upstream/arch/powerpc/include/asm/pgalloc-64.h
===================================================================
--- upstream.orig/arch/powerpc/include/asm/pgalloc-64.h
+++ upstream/arch/powerpc/include/asm/pgalloc-64.h
@@ -10,6 +10,13 @@
 #include <linux/slab.h>
 #include <linux/cpumask.h>
 #include <linux/percpu.h>
+#include <linux/list.h>
+
+struct vmemmap_backing {
+	unsigned long phys;
+	unsigned long virt_addr;
+	struct list_head list;
+};
 
 /*
  * Functions that deal with pagetables that could be at any level of
Index: upstream/arch/powerpc/mm/init_64.c
===================================================================
--- upstream.orig/arch/powerpc/mm/init_64.c
+++ upstream/arch/powerpc/mm/init_64.c
@@ -42,6 +42,7 @@
 #include <linux/poison.h>
 #include <linux/lmb.h>
 #include <linux/hugetlb.h>
+#include <linux/list.h>
 
 #include <asm/pgalloc.h>
 #include <asm/page.h>
@@ -251,6 +252,30 @@ static void __meminit vmemmap_create_map
 }
 #endif /* CONFIG_PPC_BOOK3E */
 
+LIST_HEAD(vmemmap_list);
+DEFINE_SPINLOCK(vmemmap_list_lock);
+
+static __meminit void vmemmap_list_populate(unsigned long phys,
+					    unsigned long start,
+					    int node)
+{
+	struct vmemmap_backing *vmem_back;
+
+	vmem_back = vmemmap_alloc_block(sizeof(struct vmemmap_backing), node);
+	if (unlikely(!vmem_back)) {
+		WARN_ON(1);
+		return;
+	}
+
+	vmem_back->phys = phys;
+	vmem_back->virt_addr = start;
+	INIT_LIST_HEAD(&vmem_back->list);
+
+	spin_lock(&vmemmap_list_lock);
+	list_add(&vmem_back->list, &vmemmap_list);
+	spin_unlock(&vmemmap_list_lock);
+}
+
 int __meminit vmemmap_populate(struct page *start_page,
 			       unsigned long nr_pages, int node)
 {
@@ -275,6 +300,8 @@ int __meminit vmemmap_populate(struct pa
 		if (!p)
 			return -ENOMEM;
 
+		vmemmap_list_populate(__pa(p), start, node);
+
 		pr_debug("      * %016lx..%016lx allocated at %p\n",
 			 start, start + page_size, p);
 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2] powerpc: Track backing pages allocated by vmemmap_populate()
  2010-03-26  7:12 [PATCH] powerpc: Track backing pages used allocated by vmemmap_populate() Mark Nelson
@ 2010-04-13  4:16 ` Mark Nelson
  2010-04-13  5:24   ` Michael Ellerman
  0 siblings, 1 reply; 7+ messages in thread
From: Mark Nelson @ 2010-04-13  4:16 UTC (permalink / raw)
  To: linuxppc-dev

We need to keep track of the backing pages that get allocated by
vmemmap_populate() so that when we use kdump, the dump-capture kernel knows
where these pages are.

We use a linked list of structures that contain the physical address of the
backing page and corresponding virtual address to track the backing pages.
We can use an hlist to save space, because we never remove nodes.

vmemmap_populate() is called either at boot-time or on a memory hotplug
operation. We don't have to worry about the boot-time calls because they
will be inherently single-threaded, and for a memory hotplug operation
vmemmap_populate() is called through:
sparse_add_one_section()
            |
            V
kmalloc_section_memmap()
            |
            V
sparse_mem_map_populate()
            |
            V
vmemmap_populate()
and in sparse_add_one_section() we're protected by pgdat_resize_lock().
So, we don't need a spinlock to protect the vmemmap_list.

Signed-off-by: Mark Nelson <markn@au1.ibm.com>
---

changes since v1:
 - use an hlist to save space in the structure
 - remove the spinlock because it's not needed

 arch/powerpc/include/asm/pgalloc-64.h |    7 +++++++
 arch/powerpc/mm/init_64.c             |   24 ++++++++++++++++++++++++
 2 files changed, 31 insertions(+)

Index: upstream/arch/powerpc/include/asm/pgalloc-64.h
===================================================================
--- upstream.orig/arch/powerpc/include/asm/pgalloc-64.h
+++ upstream/arch/powerpc/include/asm/pgalloc-64.h
@@ -10,6 +10,13 @@
 #include <linux/slab.h>
 #include <linux/cpumask.h>
 #include <linux/percpu.h>
+#include <linux/list.h>
+
+struct vmemmap_backing {
+	unsigned long phys;
+	unsigned long virt_addr;
+	struct hlist_node hlist;
+};
 
 /*
  * Functions that deal with pagetables that could be at any level of
Index: upstream/arch/powerpc/mm/init_64.c
===================================================================
--- upstream.orig/arch/powerpc/mm/init_64.c
+++ upstream/arch/powerpc/mm/init_64.c
@@ -43,6 +43,7 @@
 #include <linux/lmb.h>
 #include <linux/hugetlb.h>
 #include <linux/slab.h>
+#include <linux/list.h>
 
 #include <asm/pgalloc.h>
 #include <asm/page.h>
@@ -252,6 +253,27 @@ static void __meminit vmemmap_create_map
 }
 #endif /* CONFIG_PPC_BOOK3E */
 
+HLIST_HEAD(vmemmap_list);
+
+static __meminit void vmemmap_list_populate(unsigned long phys,
+					    unsigned long start,
+					    int node)
+{
+	struct vmemmap_backing *vmem_back;
+
+	vmem_back = vmemmap_alloc_block(sizeof(struct vmemmap_backing), node);
+	if (unlikely(!vmem_back)) {
+		WARN_ON(1);
+		return;
+	}
+
+	vmem_back->phys = phys;
+	vmem_back->virt_addr = start;
+	INIT_HLIST_NODE(&vmem_back->hlist);
+
+	hlist_add_head(&vmem_back->hlist, &vmemmap_list);
+}
+
 int __meminit vmemmap_populate(struct page *start_page,
 			       unsigned long nr_pages, int node)
 {
@@ -276,6 +298,8 @@ int __meminit vmemmap_populate(struct pa
 		if (!p)
 			return -ENOMEM;
 
+		vmemmap_list_populate(__pa(p), start, node);
+
 		pr_debug("      * %016lx..%016lx allocated at %p\n",
 			 start, start + page_size, p);
 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] powerpc: Track backing pages allocated by vmemmap_populate()
  2010-04-13  4:16 ` [PATCH v2] powerpc: Track backing pages " Mark Nelson
@ 2010-04-13  5:24   ` Michael Ellerman
  2010-04-13  6:02     ` Mark Nelson
  0 siblings, 1 reply; 7+ messages in thread
From: Michael Ellerman @ 2010-04-13  5:24 UTC (permalink / raw)
  To: Mark Nelson; +Cc: linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 548 bytes --]

On Tue, 2010-04-13 at 14:16 +1000, Mark Nelson wrote:
> We need to keep track of the backing pages that get allocated by
> vmemmap_populate() so that when we use kdump, the dump-capture kernel knows
> where these pages are.
> 
> We use a linked list of structures that contain the physical address of the
> backing page and corresponding virtual address to track the backing pages.
> We can use an hlist to save space, because we never remove nodes.

What if we remove_memory() ? Or does that not do what I think it does?

cheers




[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] powerpc: Track backing pages allocated by vmemmap_populate()
  2010-04-13  5:24   ` Michael Ellerman
@ 2010-04-13  6:02     ` Mark Nelson
  2010-04-13 11:16       ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 7+ messages in thread
From: Mark Nelson @ 2010-04-13  6:02 UTC (permalink / raw)
  To: michael; +Cc: linuxppc-dev

On Tuesday 13 April 2010 15:24:17 Michael Ellerman wrote:
> On Tue, 2010-04-13 at 14:16 +1000, Mark Nelson wrote:
> > We need to keep track of the backing pages that get allocated by
> > vmemmap_populate() so that when we use kdump, the dump-capture kernel knows
> > where these pages are.
> > 
> > We use a linked list of structures that contain the physical address of the
> > backing page and corresponding virtual address to track the backing pages.
> > We can use an hlist to save space, because we never remove nodes.
> 
> What if we remove_memory() ? Or does that not do what I think it does?

That's a good question, and one that I probably should have added to the
commit message.
But, following through, it looks like we end up calling into
__remove_section() from mm/memory_hotplug.c and if
CONFIG_SPARSEMEM_VMEMMAP is enabled we just return EBUSY as freeing
memmap with vmemmap isn't implemented yet.

So for the moment, I'm not sure we have to worry about it.

Thanks!
Mark.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] powerpc: Track backing pages allocated by vmemmap_populate()
  2010-04-13  6:02     ` Mark Nelson
@ 2010-04-13 11:16       ` Benjamin Herrenschmidt
  2010-04-13 23:38         ` Mark Nelson
  0 siblings, 1 reply; 7+ messages in thread
From: Benjamin Herrenschmidt @ 2010-04-13 11:16 UTC (permalink / raw)
  To: Mark Nelson; +Cc: linuxppc-dev

On Tue, 2010-04-13 at 16:02 +1000, Mark Nelson wrote:
> That's a good question, and one that I probably should have added to
> the
> commit message.
> But, following through, it looks like we end up calling into
> __remove_section() from mm/memory_hotplug.c and if
> CONFIG_SPARSEMEM_VMEMMAP is enabled we just return EBUSY as freeing
> memmap with vmemmap isn't implemented yet.
> 
> So for the moment, I'm not sure we have to worry about it.

We probably don't. IE. The vmemmap will remain for those struct pages,
which means they won't need to be allocated again if some memory is
plugged back there. If not, we just waste a bit of memory. Not a big
deal.

Cheers,
Ben.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] powerpc: Track backing pages allocated by vmemmap_populate()
  2010-04-13 11:16       ` Benjamin Herrenschmidt
@ 2010-04-13 23:38         ` Mark Nelson
  2010-04-22  2:21           ` [PATCH v3] " Mark Nelson
  0 siblings, 1 reply; 7+ messages in thread
From: Mark Nelson @ 2010-04-13 23:38 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev

On Tuesday 13 April 2010 21:16:44 Benjamin Herrenschmidt wrote:
> On Tue, 2010-04-13 at 16:02 +1000, Mark Nelson wrote:
> > That's a good question, and one that I probably should have added to
> > the
> > commit message.
> > But, following through, it looks like we end up calling into
> > __remove_section() from mm/memory_hotplug.c and if
> > CONFIG_SPARSEMEM_VMEMMAP is enabled we just return EBUSY as freeing
> > memmap with vmemmap isn't implemented yet.
> > 
> > So for the moment, I'm not sure we have to worry about it.
> 
> We probably don't. IE. The vmemmap will remain for those struct pages,
> which means they won't need to be allocated again if some memory is
> plugged back there. If not, we just waste a bit of memory. Not a big
> deal.
> 
Excellent! That makes sense.

Thanks Ben!

Mark.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3] powerpc: Track backing pages allocated by vmemmap_populate()
  2010-04-13 23:38         ` Mark Nelson
@ 2010-04-22  2:21           ` Mark Nelson
  0 siblings, 0 replies; 7+ messages in thread
From: Mark Nelson @ 2010-04-22  2:21 UTC (permalink / raw)
  To: linuxppc-dev

We need to keep track of the backing pages that get allocated by
vmemmap_populate() so that when we use kdump, the dump-capture kernel knows
where these pages are.

We use a simple linked list of structures that contain the physical address
of the backing page and corresponding virtual address to track the backing
pages.
To save space, we just use a pointer to the next struct vmemmap_backing. We
can also do this because we never remove nodes.  We call the pointer "list"
to be compatible with changes made to the crash utility.

vmemmap_populate() is called either at boot-time or on a memory hotplug
operation. We don't have to worry about the boot-time calls because they
will be inherently single-threaded, and for a memory hotplug operation
vmemmap_populate() is called through:
sparse_add_one_section()
            |
            V
kmalloc_section_memmap()
            |
            V
sparse_mem_map_populate()
            |
            V
vmemmap_populate()
and in sparse_add_one_section() we're protected by pgdat_resize_lock().
So, we don't need a spinlock to protect the vmemmap_list.

We allocate space for the vmemmap_backing structs by allocating whole pages
in vmemmap_list_alloc() and then handing out chunks of this to
vmemmap_list_populate().

This means that we waste at most just under one page, but this keeps the code
is simple.

Signed-off-by: Mark Nelson <markn@au1.ibm.com>
---

changes since v2:
 - use a pointer to the next struct vmemmap_backing instead of an hlist
 - add vmemmap_list_alloc() to allocate space for vmemmap_backing structs
   a page at-a-time when needed 

changes since v1:
 - use an hlist to save space in the structure
 - remove the spinlock because it's not needed

 arch/powerpc/include/asm/pgalloc-64.h |    6 ++++
 arch/powerpc/mm/init_64.c             |   43 ++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

Index: upstream/arch/powerpc/include/asm/pgalloc-64.h
===================================================================
--- upstream.orig/arch/powerpc/include/asm/pgalloc-64.h
+++ upstream/arch/powerpc/include/asm/pgalloc-64.h
@@ -11,6 +11,12 @@
 #include <linux/cpumask.h>
 #include <linux/percpu.h>
 
+struct vmemmap_backing {
+	struct vmemmap_backing *list;
+	unsigned long phys;
+	unsigned long virt_addr;
+};
+
 /*
  * Functions that deal with pagetables that could be at any level of
  * the table need to be passed an "index_size" so they know how to
Index: upstream/arch/powerpc/mm/init_64.c
===================================================================
--- upstream.orig/arch/powerpc/mm/init_64.c
+++ upstream/arch/powerpc/mm/init_64.c
@@ -252,6 +252,47 @@ static void __meminit vmemmap_create_map
 }
 #endif /* CONFIG_PPC_BOOK3E */
 
+struct vmemmap_backing *vmemmap_list;
+
+static __meminit struct vmemmap_backing * vmemmap_list_alloc(int node)
+{
+	static struct vmemmap_backing *next;
+	static int num_left;
+
+	/* allocate a page when required and hand out chunks */
+	if (!next || !num_left) {
+		next = vmemmap_alloc_block(PAGE_SIZE, node);
+		if (unlikely(!next)) {
+			WARN_ON(1);
+			return NULL;
+		}
+		num_left = PAGE_SIZE / sizeof(struct vmemmap_backing);
+	}
+
+	num_left--;
+
+	return next++;
+}
+
+static __meminit void vmemmap_list_populate(unsigned long phys,
+					    unsigned long start,
+					    int node)
+{
+	struct vmemmap_backing *vmem_back;
+
+	vmem_back = vmemmap_list_alloc(node);
+	if (unlikely(!vmem_back)) {
+		WARN_ON(1);
+		return;
+	}
+
+	vmem_back->phys = phys;
+	vmem_back->virt_addr = start;
+	vmem_back->list = vmemmap_list;
+
+	vmemmap_list = vmem_back;
+}
+
 int __meminit vmemmap_populate(struct page *start_page,
 			       unsigned long nr_pages, int node)
 {
@@ -276,6 +317,8 @@ int __meminit vmemmap_populate(struct pa
 		if (!p)
 			return -ENOMEM;
 
+		vmemmap_list_populate(__pa(p), start, node);
+
 		pr_debug("      * %016lx..%016lx allocated at %p\n",
 			 start, start + page_size, p);
 

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2010-04-22  2:17 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-26  7:12 [PATCH] powerpc: Track backing pages used allocated by vmemmap_populate() Mark Nelson
2010-04-13  4:16 ` [PATCH v2] powerpc: Track backing pages " Mark Nelson
2010-04-13  5:24   ` Michael Ellerman
2010-04-13  6:02     ` Mark Nelson
2010-04-13 11:16       ` Benjamin Herrenschmidt
2010-04-13 23:38         ` Mark Nelson
2010-04-22  2:21           ` [PATCH v3] " Mark Nelson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.