powerpc: Track backing pages used allocated by vmemmap_populate()
PATCH 1/1 powerpc: Track backing pages used allocated by vmemmap_populate()
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.
--- arch/powerpc/include/asm/pgalloc-64.h | 7 +++++++ arch/powerpc/mm/init_64.c | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+)
arch/powerpc/include/asm/pgalloc-64.h +7 -0
@@ -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
arch/powerpc/mm/init_64.c +27 -0
@@ -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 paif (!p)return -ENOMEM ; +vmemmap_list_populate (__pa (p), start, node); +pr_debug (" * %016lx..%016lx allocated at %p\n" , start, start + page_size, p);
PATCH v2 1/1 powerpc: Track backing pages allocated by vmemmap_populate()
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()
|
Vvmemmap_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.
---
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(+)
arch/powerpc/include/asm/pgalloc-64.h +7 -0
@@ -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
arch/powerpc/mm/init_64.c +24 -0
@@ -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 paif (!p)return -ENOMEM ; +vmemmap_list_populate (__pa (p), start, node); +pr_debug (" * %016lx..%016lx allocated at %p\n" , start, start + page_size, p);
Re: [PATCH v2] powerpc: Track backing pages allocated by vmemmap_populate()
Quoted 7 lines · Mark Nelson
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
Re: [PATCH v2] powerpc: Track backing pages allocated by vmemmap_populate()
Quoted 10 lines · On Tuesday 13 April 2010 15:24:17 Michael Ellerman wrote:
Quoted 7 lines · Mark Nelson
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.
Re: [PATCH v2] powerpc: Track backing pages allocated by vmemmap_populate()
Quoted 9 lines · Mark Nelson
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()frommm/memory_hotplug.cand ifCONFIG_SPARSEMEM_VMEMMAPis 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.
Re: [PATCH v2] powerpc: Track backing pages allocated by vmemmap_populate()
Quoted 9 lines · On Tuesday 13 April 2010 21:16:44 Benjamin Herrenschmidt wrote:
Quoted 8 lines · Mark Nelson
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()frommm/memory_hotplug.cand ifCONFIG_SPARSEMEM_VMEMMAPis enabled we just return EBUSY as freeing memmap with vmemmap isn't implemented yet.
Quoted 7 lines
Quoted 1 line
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.
PATCH v3 1/1 powerpc: Track backing pages allocated by vmemmap_populate()
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()
|
Vvmemmap_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.
---
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(+)
arch/powerpc/include/asm/pgalloc-64.h +6 -0
@@ -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
arch/powerpc/mm/init_64.c +43 -0
55 lines not on this page · raw message