* Re: [PATCH v5 08/14] memory-hotplug: Common APIs to support page tables hot-remove
From: Tang Chen @ 2012-12-26 2:49 UTC (permalink / raw)
To: Jianguo Wu
Cc: linux-ia64, linux-sh, linux-mm, paulus, hpa, sparclinux, cl,
linux-s390, x86, linux-acpi, isimatu.yasuaki, linfeng, mgorman,
kosaki.motohiro, rientjes, liuj97, len.brown, wency, cmetcalf,
yinghai, laijs, linux-kernel, minchan.kim, akpm, linuxppc-dev
In-Reply-To: <50D96116.1070305@huawei.com>
On 12/25/2012 04:17 PM, Jianguo Wu wrote:
>> +
>> +static void __meminit free_pagetable(struct page *page, int order)
>> +{
>> + struct zone *zone;
>> + bool bootmem = false;
>> + unsigned long magic;
>> +
>> + /* bootmem page has reserved flag */
>> + if (PageReserved(page)) {
>> + __ClearPageReserved(page);
>> + bootmem = true;
>> +
>> + magic = (unsigned long)page->lru.next;
>> + if (magic == SECTION_INFO || magic == MIX_SECTION_INFO)
>> + put_page_bootmem(page);
>
> Hi Tang,
>
> For removing memmap of sparse-vmemmap, in cpu_has_pse case, if magic == SECTION_INFO,
> the order will be get_order(PMD_SIZE), so we need a loop here to put all the 512 pages.
>
Hi Wu,
Thanks for reminding me that. I truely missed it.
And since in register_page_bootmem_info_section(), a whole memory
section will be set as SECTION_INFO, I think we don't need to check
the page magic one by one, just the first one is enough. :)
I will fix it, thanks. :)
^ permalink raw reply
* Re: [PATCH v5 01/14] memory-hotplug: try to offline the memory twice to avoid dependence
From: Glauber Costa @ 2012-12-25 8:35 UTC (permalink / raw)
To: Tang Chen
Cc: linux-ia64, linux-sh, linux-mm, paulus, hpa, sparclinux, cl,
linux-s390, x86, linux-acpi, isimatu.yasuaki, linfeng, mgorman,
kosaki.motohiro, rientjes, liuj97, len.brown, wency, cmetcalf,
wujianguo, yinghai, laijs, linux-kernel, minchan.kim, akpm,
linuxppc-dev
In-Reply-To: <1356350964-13437-2-git-send-email-tangchen@cn.fujitsu.com>
On 12/24/2012 04:09 PM, Tang Chen wrote:
> From: Wen Congyang <wency@cn.fujitsu.com>
>
> memory can't be offlined when CONFIG_MEMCG is selected.
> For example: there is a memory device on node 1. The address range
> is [1G, 1.5G). You will find 4 new directories memory8, memory9, memory10,
> and memory11 under the directory /sys/devices/system/memory/.
>
> If CONFIG_MEMCG is selected, we will allocate memory to store page cgroup
> when we online pages. When we online memory8, the memory stored page cgroup
> is not provided by this memory device. But when we online memory9, the memory
> stored page cgroup may be provided by memory8. So we can't offline memory8
> now. We should offline the memory in the reversed order.
>
> When the memory device is hotremoved, we will auto offline memory provided
> by this memory device. But we don't know which memory is onlined first, so
> offlining memory may fail. In such case, iterate twice to offline the memory.
> 1st iterate: offline every non primary memory block.
> 2nd iterate: offline primary (i.e. first added) memory block.
>
> This idea is suggested by KOSAKI Motohiro.
>
> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Maybe there is something here that I am missing - I admit that I came
late to this one, but this really sounds like a very ugly hack, that
really has no place in here.
Retrying, of course, may make sense, if we have reasonable belief that
we may now succeed. If this is the case, you need to document - in the
code - while is that.
The memcg argument, however, doesn't really cut it. Why can't we make
all page_cgroup allocations local to the node they are describing? If
memcg is the culprit here, we should fix it, and not retry. If there is
still any benefit in retrying, then we retry being very specific about why.
^ permalink raw reply
* Re: [PATCH v5 08/14] memory-hotplug: Common APIs to support page tables hot-remove
From: Jianguo Wu @ 2012-12-25 8:17 UTC (permalink / raw)
To: Tang Chen
Cc: linux-ia64, linux-sh, linux-mm, paulus, hpa, sparclinux, cl,
linux-s390, x86, linux-acpi, isimatu.yasuaki, linfeng, mgorman,
kosaki.motohiro, rientjes, liuj97, len.brown, wency, cmetcalf,
yinghai, laijs, linux-kernel, minchan.kim, akpm, linuxppc-dev
In-Reply-To: <1356350964-13437-9-git-send-email-tangchen@cn.fujitsu.com>
On 2012/12/24 20:09, Tang Chen wrote:
> From: Wen Congyang <wency@cn.fujitsu.com>
>
> When memory is removed, the corresponding pagetables should alse be removed.
> This patch introduces some common APIs to support vmemmap pagetable and x86_64
> architecture pagetable removing.
>
> All pages of virtual mapping in removed memory cannot be freedi if some pages
> used as PGD/PUD includes not only removed memory but also other memory. So the
> patch uses the following way to check whether page can be freed or not.
>
> 1. When removing memory, the page structs of the revmoved memory are filled
> with 0FD.
> 2. All page structs are filled with 0xFD on PT/PMD, PT/PMD can be cleared.
> In this case, the page used as PT/PMD can be freed.
>
> Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
> Signed-off-by: Jianguo Wu <wujianguo@huawei.com>
> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
> Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
> ---
> arch/x86/include/asm/pgtable_types.h | 1 +
> arch/x86/mm/init_64.c | 297 ++++++++++++++++++++++++++++++++++
> arch/x86/mm/pageattr.c | 47 +++---
> include/linux/bootmem.h | 1 +
> 4 files changed, 324 insertions(+), 22 deletions(-)
>
> diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
> index 3c32db8..4b6fd2a 100644
> --- a/arch/x86/include/asm/pgtable_types.h
> +++ b/arch/x86/include/asm/pgtable_types.h
> @@ -352,6 +352,7 @@ static inline void update_page_count(int level, unsigned long pages) { }
> * as a pte too.
> */
> extern pte_t *lookup_address(unsigned long address, unsigned int *level);
> +extern int __split_large_page(pte_t *kpte, unsigned long address, pte_t *pbase);
>
> #endif /* !__ASSEMBLY__ */
>
> diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
> index aeaa27e..b30df3c 100644
> --- a/arch/x86/mm/init_64.c
> +++ b/arch/x86/mm/init_64.c
> @@ -682,6 +682,303 @@ int arch_add_memory(int nid, u64 start, u64 size)
> }
> EXPORT_SYMBOL_GPL(arch_add_memory);
>
> +#define PAGE_INUSE 0xFD
> +
> +static void __meminit free_pagetable(struct page *page, int order)
> +{
> + struct zone *zone;
> + bool bootmem = false;
> + unsigned long magic;
> +
> + /* bootmem page has reserved flag */
> + if (PageReserved(page)) {
> + __ClearPageReserved(page);
> + bootmem = true;
> +
> + magic = (unsigned long)page->lru.next;
> + if (magic == SECTION_INFO || magic == MIX_SECTION_INFO)
> + put_page_bootmem(page);
Hi Tang,
For removing memmap of sparse-vmemmap, in cpu_has_pse case, if magic == SECTION_INFO,
the order will be get_order(PMD_SIZE), so we need a loop here to put all the 512 pages.
Thanks,
Jianguo Wu
> + else
> + __free_pages_bootmem(page, order);
> + } else
> + free_pages((unsigned long)page_address(page), order);
> +
> + /*
> + * SECTION_INFO pages and MIX_SECTION_INFO pages
> + * are all allocated by bootmem.
> + */
> + if (bootmem) {
> + zone = page_zone(page);
> + zone_span_writelock(zone);
> + zone->present_pages++;
> + zone_span_writeunlock(zone);
> + totalram_pages++;
> + }
> +}
> +
> +static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd)
> +{
> + pte_t *pte;
> + int i;
> +
> + for (i = 0; i < PTRS_PER_PTE; i++) {
> + pte = pte_start + i;
> + if (pte_val(*pte))
> + return;
> + }
> +
> + /* free a pte talbe */
> + free_pagetable(pmd_page(*pmd), 0);
> + spin_lock(&init_mm.page_table_lock);
> + pmd_clear(pmd);
> + spin_unlock(&init_mm.page_table_lock);
> +}
> +
> +static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud)
> +{
> + pmd_t *pmd;
> + int i;
> +
> + for (i = 0; i < PTRS_PER_PMD; i++) {
> + pmd = pmd_start + i;
> + if (pmd_val(*pmd))
> + return;
> + }
> +
> + /* free a pmd talbe */
> + free_pagetable(pud_page(*pud), 0);
> + spin_lock(&init_mm.page_table_lock);
> + pud_clear(pud);
> + spin_unlock(&init_mm.page_table_lock);
> +}
> +
> +/* Return true if pgd is changed, otherwise return false. */
> +static bool __meminit free_pud_table(pud_t *pud_start, pgd_t *pgd)
> +{
> + pud_t *pud;
> + int i;
> +
> + for (i = 0; i < PTRS_PER_PUD; i++) {
> + pud = pud_start + i;
> + if (pud_val(*pud))
> + return false;
> + }
> +
> + /* free a pud table */
> + free_pagetable(pgd_page(*pgd), 0);
> + spin_lock(&init_mm.page_table_lock);
> + pgd_clear(pgd);
> + spin_unlock(&init_mm.page_table_lock);
> +
> + return true;
> +}
> +
> +static void __meminit
> +remove_pte_table(pte_t *pte_start, unsigned long addr, unsigned long end,
> + bool direct)
> +{
> + unsigned long next, pages = 0;
> + pte_t *pte;
> + void *page_addr;
> + phys_addr_t phys_addr;
> +
> + pte = pte_start + pte_index(addr);
> + for (; addr < end; addr = next, pte++) {
> + next = (addr + PAGE_SIZE) & PAGE_MASK;
> + if (next > end)
> + next = end;
> +
> + if (!pte_present(*pte))
> + continue;
> +
> + /*
> + * We mapped [0,1G) memory as identity mapping when
> + * initializing, in arch/x86/kernel/head_64.S. These
> + * pagetables cannot be removed.
> + */
> + phys_addr = pte_val(*pte) + (addr & PAGE_MASK);
> + if (phys_addr < (phys_addr_t)0x40000000)
> + return;
> +
> + if (IS_ALIGNED(addr, PAGE_SIZE) &&
> + IS_ALIGNED(next, PAGE_SIZE)) {
> + if (!direct) {
> + free_pagetable(pte_page(*pte), 0);
> + pages++;
> + }
> +
> + spin_lock(&init_mm.page_table_lock);
> + pte_clear(&init_mm, addr, pte);
> + spin_unlock(&init_mm.page_table_lock);
> + } else {
> + /*
> + * If we are not removing the whole page, it means
> + * other ptes in this page are being used and we canot
> + * remove them. So fill the unused ptes with 0xFD, and
> + * remove the page when it is wholly filled with 0xFD.
> + */
> + memset((void *)addr, PAGE_INUSE, next - addr);
> + page_addr = page_address(pte_page(*pte));
> +
> + if (!memchr_inv(page_addr, PAGE_INUSE, PAGE_SIZE)) {
> + free_pagetable(pte_page(*pte), 0);
> + pages++;
> +
> + spin_lock(&init_mm.page_table_lock);
> + pte_clear(&init_mm, addr, pte);
> + spin_unlock(&init_mm.page_table_lock);
> + }
> + }
> + }
> +
> + /* Call free_pte_table() in remove_pmd_table(). */
> + flush_tlb_all();
> + if (direct)
> + update_page_count(PG_LEVEL_4K, -pages);
> +}
> +
> +static void __meminit
> +remove_pmd_table(pmd_t *pmd_start, unsigned long addr, unsigned long end,
> + bool direct)
> +{
> + unsigned long pte_phys, next, pages = 0;
> + pte_t *pte_base;
> + pmd_t *pmd;
> +
> + pmd = pmd_start + pmd_index(addr);
> + for (; addr < end; addr = next, pmd++) {
> + next = pmd_addr_end(addr, end);
> +
> + if (!pmd_present(*pmd))
> + continue;
> +
> + if (pmd_large(*pmd)) {
> + if (IS_ALIGNED(addr, PMD_SIZE) &&
> + IS_ALIGNED(next, PMD_SIZE)) {
> + if (!direct) {
> + free_pagetable(pmd_page(*pmd),
> + get_order(PMD_SIZE));
> + pages++;
> + }
> +
> + spin_lock(&init_mm.page_table_lock);
> + pmd_clear(pmd);
> + spin_unlock(&init_mm.page_table_lock);
> + continue;
> + }
> +
> + /*
> + * We use 2M page, but we need to remove part of them,
> + * so split 2M page to 4K page.
> + */
> + pte_base = (pte_t *)alloc_low_page(&pte_phys);
> + BUG_ON(!pte_base);
> + __split_large_page((pte_t *)pmd, addr,
> + (pte_t *)pte_base);
> +
> + spin_lock(&init_mm.page_table_lock);
> + pmd_populate_kernel(&init_mm, pmd, __va(pte_phys));
> + spin_unlock(&init_mm.page_table_lock);
> +
> + flush_tlb_all();
> + }
> +
> + pte_base = (pte_t *)map_low_page((pte_t *)pmd_page_vaddr(*pmd));
> + remove_pte_table(pte_base, addr, next, direct);
> + free_pte_table(pte_base, pmd);
> + unmap_low_page(pte_base);
> + }
> +
> + /* Call free_pmd_table() in remove_pud_table(). */
> + if (direct)
> + update_page_count(PG_LEVEL_2M, -pages);
> +}
> +
> +static void __meminit
> +remove_pud_table(pud_t *pud_start, unsigned long addr, unsigned long end,
> + bool direct)
> +{
> + unsigned long pmd_phys, next, pages = 0;
> + pmd_t *pmd_base;
> + pud_t *pud;
> +
> + pud = pud_start + pud_index(addr);
> + for (; addr < end; addr = next, pud++) {
> + next = pud_addr_end(addr, end);
> +
> + if (!pud_present(*pud))
> + continue;
> +
> + if (pud_large(*pud)) {
> + if (IS_ALIGNED(addr, PUD_SIZE) &&
> + IS_ALIGNED(next, PUD_SIZE)) {
> + if (!direct) {
> + free_pagetable(pud_page(*pud),
> + get_order(PUD_SIZE));
> + pages++;
> + }
> +
> + spin_lock(&init_mm.page_table_lock);
> + pud_clear(pud);
> + spin_unlock(&init_mm.page_table_lock);
> + continue;
> + }
> +
> + /*
> + * We use 1G page, but we need to remove part of them,
> + * so split 1G page to 2M page.
> + */
> + pmd_base = (pmd_t *)alloc_low_page(&pmd_phys);
> + BUG_ON(!pmd_base);
> + __split_large_page((pte_t *)pud, addr,
> + (pte_t *)pmd_base);
> +
> + spin_lock(&init_mm.page_table_lock);
> + pud_populate(&init_mm, pud, __va(pmd_phys));
> + spin_unlock(&init_mm.page_table_lock);
> +
> + flush_tlb_all();
> + }
> +
> + pmd_base = (pmd_t *)map_low_page((pmd_t *)pud_page_vaddr(*pud));
> + remove_pmd_table(pmd_base, addr, next, direct);
> + free_pmd_table(pmd_base, pud);
> + unmap_low_page(pmd_base);
> + }
> +
> + if (direct)
> + update_page_count(PG_LEVEL_1G, -pages);
> +}
> +
> +/* start and end are both virtual address. */
> +static void __meminit
> +remove_pagetable(unsigned long start, unsigned long end, bool direct)
> +{
> + unsigned long next;
> + pgd_t *pgd;
> + pud_t *pud;
> + bool pgd_changed = false;
> +
> + for (; start < end; start = next) {
> + pgd = pgd_offset_k(start);
> + if (!pgd_present(*pgd))
> + continue;
> +
> + next = pgd_addr_end(start, end);
> +
> + pud = (pud_t *)map_low_page((pud_t *)pgd_page_vaddr(*pgd));
> + remove_pud_table(pud, start, next, direct);
> + if (free_pud_table(pud, pgd))
> + pgd_changed = true;
> + unmap_low_page(pud);
> + }
> +
> + if (pgd_changed)
> + sync_global_pgds(start, end - 1);
> +
> + flush_tlb_all();
> +}
> +
> #ifdef CONFIG_MEMORY_HOTREMOVE
> int __ref arch_remove_memory(u64 start, u64 size)
> {
> diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
> index a718e0d..7dcb6f9 100644
> --- a/arch/x86/mm/pageattr.c
> +++ b/arch/x86/mm/pageattr.c
> @@ -501,21 +501,13 @@ out_unlock:
> return do_split;
> }
>
> -static int split_large_page(pte_t *kpte, unsigned long address)
> +int __split_large_page(pte_t *kpte, unsigned long address, pte_t *pbase)
> {
> unsigned long pfn, pfninc = 1;
> unsigned int i, level;
> - pte_t *pbase, *tmp;
> + pte_t *tmp;
> pgprot_t ref_prot;
> - struct page *base;
> -
> - if (!debug_pagealloc)
> - spin_unlock(&cpa_lock);
> - base = alloc_pages(GFP_KERNEL | __GFP_NOTRACK, 0);
> - if (!debug_pagealloc)
> - spin_lock(&cpa_lock);
> - if (!base)
> - return -ENOMEM;
> + struct page *base = virt_to_page(pbase);
>
> spin_lock(&pgd_lock);
> /*
> @@ -523,10 +515,11 @@ static int split_large_page(pte_t *kpte, unsigned long address)
> * up for us already:
> */
> tmp = lookup_address(address, &level);
> - if (tmp != kpte)
> - goto out_unlock;
> + if (tmp != kpte) {
> + spin_unlock(&pgd_lock);
> + return 1;
> + }
>
> - pbase = (pte_t *)page_address(base);
> paravirt_alloc_pte(&init_mm, page_to_pfn(base));
> ref_prot = pte_pgprot(pte_clrhuge(*kpte));
> /*
> @@ -579,17 +572,27 @@ static int split_large_page(pte_t *kpte, unsigned long address)
> * going on.
> */
> __flush_tlb_all();
> + spin_unlock(&pgd_lock);
>
> - base = NULL;
> + return 0;
> +}
>
> -out_unlock:
> - /*
> - * If we dropped out via the lookup_address check under
> - * pgd_lock then stick the page back into the pool:
> - */
> - if (base)
> +static int split_large_page(pte_t *kpte, unsigned long address)
> +{
> + pte_t *pbase;
> + struct page *base;
> +
> + if (!debug_pagealloc)
> + spin_unlock(&cpa_lock);
> + base = alloc_pages(GFP_KERNEL | __GFP_NOTRACK, 0);
> + if (!debug_pagealloc)
> + spin_lock(&cpa_lock);
> + if (!base)
> + return -ENOMEM;
> +
> + pbase = (pte_t *)page_address(base);
> + if (__split_large_page(kpte, address, pbase))
> __free_page(base);
> - spin_unlock(&pgd_lock);
>
> return 0;
> }
> diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
> index 3f778c2..190ff06 100644
> --- a/include/linux/bootmem.h
> +++ b/include/linux/bootmem.h
> @@ -53,6 +53,7 @@ extern void free_bootmem_node(pg_data_t *pgdat,
> unsigned long size);
> extern void free_bootmem(unsigned long physaddr, unsigned long size);
> extern void free_bootmem_late(unsigned long physaddr, unsigned long size);
> +extern void __free_pages_bootmem(struct page *page, unsigned int order);
>
> /*
> * Flags for reserve_bootmem (also if CONFIG_HAVE_ARCH_BOOTMEM_NODE,
^ permalink raw reply
* Re: [PATCH v5 06/14] memory-hotplug: implement register_page_bootmem_info_section of sparse-vmemmap
From: Jianguo Wu @ 2012-12-25 8:09 UTC (permalink / raw)
To: Tang Chen
Cc: linux-ia64, linux-sh, linux-mm, paulus, hpa, sparclinux, cl,
linux-s390, x86, linux-acpi, isimatu.yasuaki, linfeng, mgorman,
kosaki.motohiro, rientjes, liuj97, len.brown, wency, cmetcalf,
yinghai, laijs, linux-kernel, minchan.kim, akpm, linuxppc-dev
In-Reply-To: <1356350964-13437-7-git-send-email-tangchen@cn.fujitsu.com>
On 2012/12/24 20:09, Tang Chen wrote:
> From: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
>
> For removing memmap region of sparse-vmemmap which is allocated bootmem,
> memmap region of sparse-vmemmap needs to be registered by get_page_bootmem().
> So the patch searches pages of virtual mapping and registers the pages by
> get_page_bootmem().
>
> Note: register_page_bootmem_memmap() is not implemented for ia64, ppc, s390,
> and sparc.
>
> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
> Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
> ---
> arch/ia64/mm/discontig.c | 6 ++++
> arch/powerpc/mm/init_64.c | 6 ++++
> arch/s390/mm/vmem.c | 6 ++++
> arch/sparc/mm/init_64.c | 6 ++++
> arch/x86/mm/init_64.c | 52 ++++++++++++++++++++++++++++++++++++++++
> include/linux/memory_hotplug.h | 11 +-------
> include/linux/mm.h | 3 +-
> mm/memory_hotplug.c | 33 ++++++++++++++++++++++---
> 8 files changed, 109 insertions(+), 14 deletions(-)
>
> diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
> index c641333..33943db 100644
> --- a/arch/ia64/mm/discontig.c
> +++ b/arch/ia64/mm/discontig.c
> @@ -822,4 +822,10 @@ int __meminit vmemmap_populate(struct page *start_page,
> {
> return vmemmap_populate_basepages(start_page, size, node);
> }
> +
> +void register_page_bootmem_memmap(unsigned long section_nr,
> + struct page *start_page, unsigned long size)
> +{
> + /* TODO */
> +}
> #endif
> diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
> index 95a4529..6466440 100644
> --- a/arch/powerpc/mm/init_64.c
> +++ b/arch/powerpc/mm/init_64.c
> @@ -297,5 +297,11 @@ int __meminit vmemmap_populate(struct page *start_page,
>
> return 0;
> }
> +
> +void register_page_bootmem_memmap(unsigned long section_nr,
> + struct page *start_page, unsigned long size)
> +{
> + /* TODO */
> +}
> #endif /* CONFIG_SPARSEMEM_VMEMMAP */
>
> diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
> index 6ed1426..2c14bc2 100644
> --- a/arch/s390/mm/vmem.c
> +++ b/arch/s390/mm/vmem.c
> @@ -272,6 +272,12 @@ out:
> return ret;
> }
>
> +void register_page_bootmem_memmap(unsigned long section_nr,
> + struct page *start_page, unsigned long size)
> +{
> + /* TODO */
> +}
> +
> /*
> * Add memory segment to the segment list if it doesn't overlap with
> * an already present segment.
> diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
> index 85be1ca..7e28c9e 100644
> --- a/arch/sparc/mm/init_64.c
> +++ b/arch/sparc/mm/init_64.c
> @@ -2231,6 +2231,12 @@ void __meminit vmemmap_populate_print_last(void)
> node_start = 0;
> }
> }
> +
> +void register_page_bootmem_memmap(unsigned long section_nr,
> + struct page *start_page, unsigned long size)
> +{
> + /* TODO */
> +}
> #endif /* CONFIG_SPARSEMEM_VMEMMAP */
>
> static void prot_init_common(unsigned long page_none,
> diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
> index f78509c..aeaa27e 100644
> --- a/arch/x86/mm/init_64.c
> +++ b/arch/x86/mm/init_64.c
> @@ -1000,6 +1000,58 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node)
> return 0;
> }
>
> +void register_page_bootmem_memmap(unsigned long section_nr,
> + struct page *start_page, unsigned long size)
> +{
> + unsigned long addr = (unsigned long)start_page;
> + unsigned long end = (unsigned long)(start_page + size);
> + unsigned long next;
> + pgd_t *pgd;
> + pud_t *pud;
> + pmd_t *pmd;
> +
> + for (; addr < end; addr = next) {
> + pte_t *pte = NULL;
> +
> + pgd = pgd_offset_k(addr);
> + if (pgd_none(*pgd)) {
> + next = (addr + PAGE_SIZE) & PAGE_MASK;
> + continue;
> + }
> + get_page_bootmem(section_nr, pgd_page(*pgd), MIX_SECTION_INFO);
> +
> + pud = pud_offset(pgd, addr);
> + if (pud_none(*pud)) {
> + next = (addr + PAGE_SIZE) & PAGE_MASK;
> + continue;
> + }
> + get_page_bootmem(section_nr, pud_page(*pud), MIX_SECTION_INFO);
> +
> + if (!cpu_has_pse) {
> + next = (addr + PAGE_SIZE) & PAGE_MASK;
> + pmd = pmd_offset(pud, addr);
> + if (pmd_none(*pmd))
> + continue;
> + get_page_bootmem(section_nr, pmd_page(*pmd),
> + MIX_SECTION_INFO);
> +
> + pte = pte_offset_kernel(pmd, addr);
> + if (pte_none(*pte))
> + continue;
> + get_page_bootmem(section_nr, pte_page(*pte),
> + SECTION_INFO);
> + } else {
> + next = pmd_addr_end(addr, end);
> +
> + pmd = pmd_offset(pud, addr);
> + if (pmd_none(*pmd))
> + continue;
> + get_page_bootmem(section_nr, pmd_page(*pmd),
> + SECTION_INFO);
Hi Tang,
In this case, pmd maps 512 pages, but you only get_page_bootmem() on the first page.
I think the whole 512 pages should be get_page_bootmem(), what do you think?
Thanks,
Jianguo Wu
> + }
> + }
> +}
> +
> void __meminit vmemmap_populate_print_last(void)
> {
> if (p_start) {
> diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
> index 31a563b..2441f36 100644
> --- a/include/linux/memory_hotplug.h
> +++ b/include/linux/memory_hotplug.h
> @@ -174,17 +174,10 @@ static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
> #endif /* CONFIG_NUMA */
> #endif /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */
>
> -#ifdef CONFIG_SPARSEMEM_VMEMMAP
> -static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
> -{
> -}
> -static inline void put_page_bootmem(struct page *page)
> -{
> -}
> -#else
> extern void register_page_bootmem_info_node(struct pglist_data *pgdat);
> extern void put_page_bootmem(struct page *page);
> -#endif
> +extern void get_page_bootmem(unsigned long ingo, struct page *page,
> + unsigned long type);
>
> /*
> * Lock for memory hotplug guarantees 1) all callbacks for memory hotplug
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 6320407..1eca498 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -1709,7 +1709,8 @@ int vmemmap_populate_basepages(struct page *start_page,
> unsigned long pages, int node);
> int vmemmap_populate(struct page *start_page, unsigned long pages, int node);
> void vmemmap_populate_print_last(void);
> -
> +void register_page_bootmem_memmap(unsigned long section_nr, struct page *map,
> + unsigned long size);
>
> enum mf_flags {
> MF_COUNT_INCREASED = 1 << 0,
> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
> index 2c5d734..34c656b 100644
> --- a/mm/memory_hotplug.c
> +++ b/mm/memory_hotplug.c
> @@ -91,9 +91,8 @@ static void release_memory_resource(struct resource *res)
> }
>
> #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
> -#ifndef CONFIG_SPARSEMEM_VMEMMAP
> -static void get_page_bootmem(unsigned long info, struct page *page,
> - unsigned long type)
> +void get_page_bootmem(unsigned long info, struct page *page,
> + unsigned long type)
> {
> page->lru.next = (struct list_head *) type;
> SetPagePrivate(page);
> @@ -128,6 +127,7 @@ void __ref put_page_bootmem(struct page *page)
>
> }
>
> +#ifndef CONFIG_SPARSEMEM_VMEMMAP
> static void register_page_bootmem_info_section(unsigned long start_pfn)
> {
> unsigned long *usemap, mapsize, section_nr, i;
> @@ -161,6 +161,32 @@ static void register_page_bootmem_info_section(unsigned long start_pfn)
> get_page_bootmem(section_nr, page, MIX_SECTION_INFO);
>
> }
> +#else
> +static void register_page_bootmem_info_section(unsigned long start_pfn)
> +{
> + unsigned long *usemap, mapsize, section_nr, i;
> + struct mem_section *ms;
> + struct page *page, *memmap;
> +
> + if (!pfn_valid(start_pfn))
> + return;
> +
> + section_nr = pfn_to_section_nr(start_pfn);
> + ms = __nr_to_section(section_nr);
> +
> + memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr);
> +
> + register_page_bootmem_memmap(section_nr, memmap, PAGES_PER_SECTION);
> +
> + usemap = __nr_to_section(section_nr)->pageblock_flags;
> + page = virt_to_page(usemap);
> +
> + mapsize = PAGE_ALIGN(usemap_size()) >> PAGE_SHIFT;
> +
> + for (i = 0; i < mapsize; i++, page++)
> + get_page_bootmem(section_nr, page, MIX_SECTION_INFO);
> +}
> +#endif
>
> void register_page_bootmem_info_node(struct pglist_data *pgdat)
> {
> @@ -203,7 +229,6 @@ void register_page_bootmem_info_node(struct pglist_data *pgdat)
> register_page_bootmem_info_section(pfn);
> }
> }
> -#endif /* !CONFIG_SPARSEMEM_VMEMMAP */
>
> static void grow_zone_span(struct zone *zone, unsigned long start_pfn,
> unsigned long end_pfn)
^ permalink raw reply
* Re: PROBLEM: Linux 3.6.2 fails to boot on IBM Cell
From: Dennis Schridde @ 2012-12-24 13:39 UTC (permalink / raw)
To: Grant Likely; +Cc: Thomas Gleixner, linuxppc-dev
In-Reply-To: <20121115175835.652C43E197F@localhost>
[-- Attachment #1.1: Type: text/plain, Size: 369 bytes --]
Am Donnerstag, 15. November 2012, 17:58:35 schrieb Grant Likely:
> Anyway, here is a real patch.
Thanks a lot, Grant!
Your patch improves the situation significantly. However, it is still not
entirely fixed:
irq: irq-93==>hwirq-0x5d mapping failed: -22
There are a lot less error messages than before, though. Please see attached
log.
Best regards,
Dennis Schridde
[-- Attachment #1.2: boot.log --]
[-- Type: text/x-log, Size: 53932 bytes --]
Please wait, loading kernel...
Bootloader 2.0
Reading MAC address from device: 00:1a:64:b8:07:fa
Requesting IP address via DHCP: 192.168.100.53
Requesting file "/images/gentoo-ppc64-3.6/vmlinux-3.6.11-aufs" via TFTP from 192.168.100.1
Receiving data: 8738 KBytes
TFTP: Received /images/gentoo-ppc64-3.6/vmlinux-3.6.11-aufs (8738 KBytes)
Elf64 kernel loaded...
Loading ramdisk...
Bootloader 2.0
Reading MAC address from device: 00:1a:64:b8:07:fa
Requesting IP address via DHCP: 192.168.100.53
Requesting file "/images/gentoo-ppc64-3.6/initramfs-3.6.11-aufs.img" via TFTP from 192.168.100.1
Receiving data: 7018 KBytes
TFTP: Received /images/gentoo-ppc64-3.6/initramfs-3.6.11-aufs.img (7018 KBytes)
ramdisk loaded at 03000000, size: 7018 Kbytes
OF stdout device is: /axon@10000000000/plb5/plb4/opb/serial@40000200
Preparing to boot Linux version 3.6.11-aufs (root@blade00) (gcc version 4.7.2 (Gentoo 4.7.2 p1.3, pie-0.5.5) ) #2 SMP Mon Dec 24 12:34:21 CET 2012
Detected machine type: 0000000000000500
command line: ksdevice=bootif lang= loglevel=8 text
memory layout at init:
memory_limit : 0000000000000000 (16 MB aligned)
alloc_bottom : 00000000036db000
alloc_top : 0000000030000000
alloc_top_hi : 0000000200000000
rmo_top : 0000000030000000
ram_top : 0000000200000000
instantiating rtas at 0x000000002fff3000... done
boot cpu hw idx 0
starting cpu hw idx 2... done
copying OF device tree...
Building dt strings...
Building dt structure...
Device tree strings 0x00000000037dc000 -> 0x00000000037dc8e3
Device tree struct 0x00000000037dd000 -> 0x00000000037e6000
[ 0.000000] Allocated 20480 bytes for 32 pacas at c00000000fffb000
[ 0.000000] Using Cell machine description
[ 0.000000] Page orders: linear mapping = 24, virtual = 12, io = 12, vmemmap = 24
[ 0.000000] Found initrd at 0xc000000003000000:0xc0000000036da850
[ 0.000000] Found legacy serial port 0 for /axon@10000000000/plb5/plb4/opb/serial@40000200
[ 0.000000] mem=14540000200, taddr=14540000200, irq=0, clk=14745600, speed=19200
[ 0.000000] Found legacy serial port 1 for /axon@10000000000/plb5/plb4/opb/serial@40000300
[ 0.000000] mem=14540000300, taddr=14540000300, irq=0, clk=14745600, speed=115200
[ 0.000000] Found legacy serial port 2 for /axon@30000000000/plb5/plb4/opb/serial@40000200
[ 0.000000] mem=34540000200, taddr=34540000200, irq=0, clk=14745600, speed=-1
[ 0.000000] Found legacy serial port 3 for /axon@30000000000/plb5/plb4/opb/serial@40000300
[ 0.000000] mem=34540000300, taddr=34540000300, irq=0, clk=14745600, speed=-1
[ 0.000000] bootconsole [udbg0] enabled
[ 0.000000] CPU maps initialized for 2 threads per core
[ 0.000000] (thread shift is 1)
[ 0.000000] Freed 16384 bytes for unused pacas
[ 0.000000] Starting Linux PPC64 #2 SMP Mon Dec 24 12:34:21 CET 2012
[ 0.000000] -----------------------------------------------------
[ 0.000000] ppc64_pft_size = 0x0
[ 0.000000] physicalMemorySize = 0x200000000
[ 0.000000] htab_address = 0xc000000078000000
[ 0.000000] htab_hash_mask = 0xfffff
[ 0.000000] -----------------------------------------------------
[ 0.000000] Linux version 3.6.11-aufs (root@blade00) (gcc version 4.7.2 (Gentoo 4.7.2 p1.3, pie-0.5.5) ) #2 SMP Mon Dec 24 12:34:21 CET 2012
[ 0.000000] *** 0000 : CF000012
[ 0.000000]
[ 0.000000] *** 0000 : Setup Arch
[ 0.000000] [boot]0012 Setup Arch
[ 0.000000] Node 0 Memory: 0x0-0x100000000
[ 0.000000] Node 1 Memory: 0x100000000-0x200000000
[ 0.000000] mmio NVRAM, 1020k at 0x14502000000 mapped to d000080080008000
[ 0.000000] Zone ranges:
[ 0.000000] DMA [mem 0x00000000-0x1ffffffff]
[ 0.000000] Normal empty
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x00000000-0xffffffff]
[ 0.000000] node 1: [mem 0x100000000-0x1ffffffff]
[ 0.000000] On node 0 totalpages: 1048576
[ 0.000000] DMA zone: 14336 pages used for memmap
[ 0.000000] DMA zone: 0 pages reserved
[ 0.000000] DMA zone: 1034240 pages, LIFO batch:31
[ 0.000000] On node 1 totalpages: 1048576
[ 0.000000] DMA zone: 14336 pages used for memmap
[ 0.000000] DMA zone: 0 pages reserved
[ 0.000000] DMA zone: 1034240 pages, LIFO batch:31
[ 0.000000] *** 0000 : CF000015
[ 0.000000]
[ 0.000000] *** 0000 : Setup Done
[ 0.000000] [boot]0015 Setup Done
[ 0.000000] PERCPU: Embedded 11 pages/cpu @c000000000700000 s14720 r0 d30336 u262144
[ 0.000000] pcpu-alloc: s14720 r0 d30336 u262144 alloc=1*1048576
[ 0.000000] pcpu-alloc: [0] 0 1 2 3
[ 0.000000] Built 2 zonelists in Node order, mobility grouping on. Total pages: 2068480
[ 0.000000] Policy zone: DMA
[ 0.000000] Kernel command line: ksdevice=bootif lang= loglevel=8 text
[ 0.000000] PID hash table entries: 4096 (order: 3, 32768 bytes)
[ 0.000000] freeing bootmem node 0
[ 0.000000] freeing bootmem node 1
[ 0.000000] Memory: 8127828k/8388608k available (5980k kernel code, 260780k reserved, 644k data, 424k bss, 2016k init)
[ 0.000000] SLUB: Genslabs=15, HWalign=128, Order=0-3, MinObjects=0, CPUs=4, Nodes=256
[ 0.000000] Hierarchical RCU implementation.
[ 0.000000] RCU restricting CPUs from NR_CPUS=32 to nr_cpu_ids=4.
[ 0.000000] NR_IRQS:512 nr_irqs:512 16
[ 0.000000] IIC for CPU 0 target id 0xe : /be@20000000000/interrupt-controller@508400
[ 0.000000] IIC for CPU 1 target id 0xf : /be@20000000000/interrupt-controller@508400
[ 0.000000] IIC for CPU 2 target id 0x1e : /be@20100000000/interrupt-controller@508400
[ 0.000000] IIC for CPU 3 target id 0x1f : /be@20100000000/interrupt-controller@508400
[ 0.000000] mpic: Setting up MPIC " MPIC " version 1.2 at 0, max 4 CPUs
[ 0.000000] mpic: ISU size: 128, shift: 7, mask: 7f
[ 0.000000] mpic: Initializing for 128 sources
[ 0.000000] /axon@10000000000/interrupt-controller: hooking up to IRQ 43
[ 0.000000] mpic: Setting up MPIC " MPIC " version 1.2 at 0, max 4 CPUs
[ 0.000000] mpic: ISU size: 128, shift: 7, mask: 7f
[ 0.000000] mpic: Initializing for 128 sources
[ 0.000000] /axon@30000000000/interrupt-controller: hooking up to IRQ 299
[ 0.000000] time_init: decrementer frequency = 26.664580 MHz
[ 0.000000] time_init: processor frequency = 3200.000000 MHz
[ 0.000000] clocksource: timebase mult[2580c052] shift[24] registered
[ 0.000000] clockevent: decrementer mult[6d37d6b] shift[32] cpu[0]
[ 0.000000] Console: colour dummy device 80x25
[ 0.102201] pid_max: default: 32768 minimum: 301
[ 0.132364] Dentry cache hash table entries: 1048576 (order: 11, 8388608 bytes)
[ 0.187768] Inode-cache hash table entries: 524288 (order: 10, 4194304 bytes)
[ 0.235629] Mount-cache hash table entries: 256
[ 0.265044] Brought up 4 CPUs
[ 0.282347] Node 0 CPUs: 0-1
[ 0.299528] Node 1 CPUs: 2-3
[ 0.317296] devtmpfs: initialized
[ 0.363359] NET: Registered protocol family 16
[ 0.389798] iommu: node 0, dynamic window 0x0-0x80000000 fixed window 0x80000000-0x280000000
[ 0.441355] IOMMU: Using strong ordering for fixed mapping
[ 0.475729] IOMMU table initialized, virtual merging enabled
[ 0.509230] iommu: node 1, dynamic window 0x0-0x80000000 fixed window 0x80000000-0x280000000
[ 0.561925] IOMMU: Using strong ordering for fixed mapping
[ 0.602829] PCI: Probing PCI hardware
[ 0.624284] PCI: Probing PCI hardware done
[ 0.649080] irq: irq-93==>hwirq-0x5d mapping failed: -22
[ 0.680551] ------------[ cut here ]------------
[ 0.708129] WARNING: at /usr/src/linux-3.6.11-aufs/kernel/irq/irqdomain.c:444
[ 0.750838] Modules linked in:
[ 0.769070] NIP: c0000000000ba93c LR: c0000000000ba938 CTR: c0000000000254b0
[ 0.811259] REGS: c0000000fe65b370 TRAP: 0700 Not tainted (3.6.11-aufs)
[ 0.852403] MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI> CR: 44000024 XER: 00000000
[ 0.899279] SOFTE: 1
[ 0.912302] TASK = c0000000fe650000[1] 'swapper/0' THREAD: c0000000fe658000 CPU: 0
GPR00: c0000000000ba938 c0000000fe65b5f0 c000000000668808 000000000000002c
GPR04: 0000000000000000 000000007c05ba71 0000000000000008 0000000000000000
GPR08: 000000007c123f36 0000000000000000 0000000000000000 0000000000000000
GPR12: d000070000000000 c00000000fffb000 ffffffffffffffff 0000000002c0f498
GPR16: 0000000000000060 000000000ead9738 0000000002c0f498 00000000037db028
GPR20: 00000000037dc012 0000000000000000 c0000000fe006078 000000000000005e
GPR24: 0000000000000174 000000000000005d 000000000000005d c0000000fe64ba00
GPR28: c0000000fe006060 000000000000005d c000000000614b20 000000000000005d
[ 1.278470] NIP [c0000000000ba93c] .irq_domain_associate_many+0x264/0x290
[ 1.319087] LR [c0000000000ba938] .irq_domain_associate_many+0x260/0x290
[ 1.359188] Call Trace:
[ 1.373776] [c0000000fe65b5f0] [c0000000000ba938] .irq_domain_associate_many+0x260/0x290 (unreliable)
[ 1.428987] [c0000000fe65b6c0] [c0000000000bb3b8] .irq_create_mapping+0xc8/0x1d0
[ 1.473258] [c0000000fe65b760] [c0000000000bb568] .irq_create_of_mapping+0xa8/0x170
[ 1.519096] [c0000000fe65b810] [c0000000002777b0] .irq_of_parse_and_map+0x40/0x58
[ 1.563886] [c0000000fe65b8a0] [c0000000002778e0] .of_irq_count+0x30/0x58
[ 1.604511] [c0000000fe65b930] [c000000000278204] .of_device_alloc+0x94/0x238
[ 1.647222] [c0000000fe65ba30] [c0000000002783fc] .of_platform_device_create_pdata+0x54/0xf8
[ 1.697744] [c0000000fe65bad0] [c0000000002785e4] .of_platform_bus_create+0x144/0x1e0
[ 1.744620] [c0000000fe65bbc0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 1.791496] [c0000000fe65bcb0] [c000000000278830] .of_platform_bus_probe+0xd0/0x140
[ 1.837334] [c0000000fe65bd50] [c0000000003f0444] .__machine_initcall_cell_cell_publish_devices+0x54/0x1ac
[ 1.895149] [c0000000fe65be20] [c000000000009a70] .do_one_initcall+0x168/0x1d0
[ 1.938379] [c0000000fe65bee0] [c0000000003dfb74] .kernel_init+0x14c/0x1f4
[ 1.979527] [c0000000fe65bf90] [c00000000001b478] .kernel_thread+0x54/0x70
[ 2.020666] Instruction dump:
[ 2.038375] 7fa4eb78 7ca507b4 482709ed 60000000 0fe00000 3860ffea 4bffff80 e87e8020
[ 2.084730] 7fa4eb78 7fe5fb78 482709cd 60000000 <0fe00000> 39200000 7f83e378 7f44d378
[ 2.132140] ---[ end trace a23e1daeebb82ff6 ]---
[ 2.160223] irq: irq-59==>hwirq-0x3b mapping failed: -22
[ 2.191570] ------------[ cut here ]------------
[ 2.219163] WARNING: at /usr/src/linux-3.6.11-aufs/kernel/irq/irqdomain.c:444
[ 2.261870] Modules linked in:
[ 2.280102] NIP: c0000000000ba93c LR: c0000000000ba938 CTR: c0000000000254b0
[ 2.322292] REGS: c0000000fe65b190 TRAP: 0700 Tainted: G W (3.6.11-aufs)
[ 2.369166] MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI> CR: 44000024 XER: 00000000
[ 2.416042] SOFTE: 1
[ 2.429064] TASK = c0000000fe650000[1] 'swapper/0' THREAD: c0000000fe658000 CPU: 0
GPR00: c0000000000ba938 c0000000fe65b410 c000000000668808 000000000000002c
GPR04: 0000000000000000 000000007e6c8024 0000000000000008 0000000000000000
GPR08: 000000007e790a3c 0000000000000000 0000000000000000 0000000000000000
GPR12: d000070000000000 c00000000fffb000 ffffffffffffffff 0000000002c0f498
GPR16: 0000000000000060 000000000ead9738 0000000002c0f498 00000000037db028
GPR20: 00000000037dc012 0000000000000000 c0000000fe006078 000000000000003c
GPR24: 00000000000000ec 000000000000003b 000000000000003b c0000000fe64bf00
GPR28: c0000000fe006060 000000000000003b c000000000614b20 000000000000003b
[ 2.795224] NIP [c0000000000ba93c] .irq_domain_associate_many+0x264/0x290
[ 2.835850] LR [c0000000000ba938] .irq_domain_associate_many+0x260/0x290
[ 2.875951] Call Trace:
[ 2.890539] [c0000000fe65b410] [c0000000000ba938] .irq_domain_associate_many+0x260/0x290 (unreliable)
[ 2.945748] [c0000000fe65b4e0] [c0000000000bb3b8] .irq_create_mapping+0xc8/0x1d0
[ 2.990020] [c0000000fe65b580] [c0000000000bb568] .irq_create_of_mapping+0xa8/0x170
[ 3.035856] [c0000000fe65b630] [c0000000002777b0] .irq_of_parse_and_map+0x40/0x58
[ 3.080648] [c0000000fe65b6c0] [c0000000002778e0] .of_irq_count+0x30/0x58
[ 3.121275] [c0000000fe65b750] [c000000000278204] .of_device_alloc+0x94/0x238
[ 3.163985] [c0000000fe65b850] [c0000000002783fc] .of_platform_device_create_pdata+0x54/0xf8
[ 3.214507] [c0000000fe65b8f0] [c0000000002785e4] .of_platform_bus_create+0x144/0x1e0
[ 3.261382] [c0000000fe65b9e0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 3.308259] [c0000000fe65bad0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 3.355136] [c0000000fe65bbc0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 3.402011] [c0000000fe65bcb0] [c000000000278830] .of_platform_bus_probe+0xd0/0x140
[ 3.447847] [c0000000fe65bd50] [c0000000003f0444] .__machine_initcall_cell_cell_publish_devices+0x54/0x1ac
[ 3.505661] [c0000000fe65be20] [c000000000009a70] .do_one_initcall+0x168/0x1d0
[ 3.548892] [c0000000fe65bee0] [c0000000003dfb74] .kernel_init+0x14c/0x1f4
[ 3.590039] [c0000000fe65bf90] [c00000000001b478] .kernel_thread+0x54/0x70
[ 3.631181] Instruction dump:
[ 3.648890] 7fa4eb78 7ca507b4 482709ed 60000000 0fe00000 3860ffea 4bffff80 e87e8020
[ 3.695246] 7fa4eb78 7fe5fb78 482709cd 60000000 <0fe00000> 39200000 7f83e378 7f44d378
[ 3.742644] ---[ end trace a23e1daeebb82ff7 ]---
[ 3.771196] irq: irq-18==>hwirq-0x2 mapping failed: -22
[ 3.802033] ------------[ cut here ]------------
[ 3.829627] WARNING: at /usr/src/linux-3.6.11-aufs/kernel/irq/irqdomain.c:444
[ 3.872334] Modules linked in:
[ 3.890566] NIP: c0000000000ba93c LR: c0000000000ba938 CTR: c0000000000254b0
[ 3.932755] REGS: c0000000fe65b0a0 TRAP: 0700 Tainted: G W (3.6.11-aufs)
[ 3.979630] MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI> CR: 84000024 XER: 00000000
[ 4.026506] SOFTE: 1
[ 4.039528] TASK = c0000000fe650000[1] 'swapper/0' THREAD: c0000000fe658000 CPU: 0
GPR00: c0000000000ba938 c0000000fe65b320 c000000000668808 000000000000002b
GPR04: 0000000000000000 0000000080fbc4fa 0000000000000008 0000000000000000
GPR08: 00000000810849bd 0000000000000000 0000000000000000 0000000000000000
GPR12: d000070000000000 c00000000fffb000 ffffffffffffffff 0000000002c0f498
GPR16: 0000000000000060 000000000ead9738 0000000002c0f498 00000000037db028
GPR20: 00000000037dc012 0000000000000000 c0000000fe006078 0000000000000013
GPR24: 0000000000000008 0000000000000002 0000000000000012 c0000000fe7d1300
GPR28: c0000000fe006060 0000000000000012 c000000000614b20 0000000000000002
[ 4.405688] NIP [c0000000000ba93c] .irq_domain_associate_many+0x264/0x290
[ 4.446313] LR [c0000000000ba938] .irq_domain_associate_many+0x260/0x290
[ 4.486415] Call Trace:
[ 4.501003] [c0000000fe65b320] [c0000000000ba938] .irq_domain_associate_many+0x260/0x290 (unreliable)
[ 4.556212] [c0000000fe65b3f0] [c0000000000bb3b8] .irq_create_mapping+0xc8/0x1d0
[ 4.600484] [c0000000fe65b490] [c0000000000bb568] .irq_create_of_mapping+0xa8/0x170
[ 4.646320] [c0000000fe65b540] [c0000000002777b0] .irq_of_parse_and_map+0x40/0x58
[ 4.691111] [c0000000fe65b5d0] [c0000000002778e0] .of_irq_count+0x30/0x58
[ 4.731738] [c0000000fe65b660] [c000000000278204] .of_device_alloc+0x94/0x238
[ 4.774448] [c0000000fe65b760] [c0000000002783fc] .of_platform_device_create_pdata+0x54/0xf8
[ 4.824970] [c0000000fe65b800] [c0000000002785e4] .of_platform_bus_create+0x144/0x1e0
[ 4.871846] [c0000000fe65b8f0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 4.918723] [c0000000fe65b9e0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 4.965599] [c0000000fe65bad0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 5.012475] [c0000000fe65bbc0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 5.059351] [c0000000fe65bcb0] [c000000000278830] .of_platform_bus_probe+0xd0/0x140
[ 5.105187] [c0000000fe65bd50] [c0000000003f0444] .__machine_initcall_cell_cell_publish_devices+0x54/0x1ac
[ 5.163001] [c0000000fe65be20] [c000000000009a70] .do_one_initcall+0x168/0x1d0
[ 5.206231] [c0000000fe65bee0] [c0000000003dfb74] .kernel_init+0x14c/0x1f4
[ 5.247378] [c0000000fe65bf90] [c00000000001b478] .kernel_thread+0x54/0x70
[ 5.288521] Instruction dump:
[ 5.306230] 7fa4eb78 7ca507b4 482709ed 60000000 0fe00000 3860ffea 4bffff80 e87e8020
[ 5.352586] 7fa4eb78 7fe5fb78 482709cd 60000000 <0fe00000> 39200000 7f83e378 7f44d378
[ 5.399984] ---[ end trace a23e1daeebb82ff8 ]---
[ 5.429311] irq: irq-102==>hwirq-0x66 mapping failed: -22
[ 5.461194] ------------[ cut here ]------------
[ 5.488789] WARNING: at /usr/src/linux-3.6.11-aufs/kernel/irq/irqdomain.c:444
[ 5.531497] Modules linked in:
[ 5.549729] NIP: c0000000000ba93c LR: c0000000000ba938 CTR: c0000000000254b0
[ 5.591918] REGS: c0000000fe65b280 TRAP: 0700 Tainted: G W (3.6.11-aufs)
[ 5.638793] MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI> CR: 84000024 XER: 00000000
[ 5.685669] SOFTE: 1
[ 5.698691] TASK = c0000000fe650000[1] 'swapper/0' THREAD: c0000000fe658000 CPU: 0
GPR00: c0000000000ba938 c0000000fe65b500 c000000000668808 000000000000002d
GPR04: 0000000000000000 00000000839e7fc2 0000000000000008 0000000000000000
GPR08: 0000000083ab59b2 0000000000000000 0000000000000000 0000000000000000
GPR12: d000070000000000 c00000000fffb000 ffffffffffffffff 0000000002c0f498
GPR16: 0000000000000060 000000000ead9738 0000000002c0f498 00000000037db028
GPR20: 00000000037dc012 0000000000000000 c0000000fe006078 0000000000000067
GPR24: 0000000000000198 0000000000000066 0000000000000066 c0000000fe7d7d00
GPR28: c0000000fe006060 0000000000000066 c000000000614b20 0000000000000066
[ 6.064852] NIP [c0000000000ba93c] .irq_domain_associate_many+0x264/0x290
[ 6.105476] LR [c0000000000ba938] .irq_domain_associate_many+0x260/0x290
[ 6.145578] Call Trace:
[ 6.160165] [c0000000fe65b500] [c0000000000ba938] .irq_domain_associate_many+0x260/0x290 (unreliable)
[ 6.215375] [c0000000fe65b5d0] [c0000000000bb3b8] .irq_create_mapping+0xc8/0x1d0
[ 6.259648] [c0000000fe65b670] [c0000000000bb568] .irq_create_of_mapping+0xa8/0x170
[ 6.305482] [c0000000fe65b720] [c0000000002777b0] .irq_of_parse_and_map+0x40/0x58
[ 6.350274] [c0000000fe65b7b0] [c0000000002778e0] .of_irq_count+0x30/0x58
[ 6.390901] [c0000000fe65b840] [c000000000278204] .of_device_alloc+0x94/0x238
[ 6.433611] [c0000000fe65b940] [c0000000002783fc] .of_platform_device_create_pdata+0x54/0xf8
[ 6.484133] [c0000000fe65b9e0] [c0000000002785e4] .of_platform_bus_create+0x144/0x1e0
[ 6.531009] [c0000000fe65bad0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 6.577885] [c0000000fe65bbc0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 6.624761] [c0000000fe65bcb0] [c000000000278830] .of_platform_bus_probe+0xd0/0x140
[ 6.670598] [c0000000fe65bd50] [c0000000003f0444] .__machine_initcall_cell_cell_publish_devices+0x54/0x1ac
[ 6.728411] [c0000000fe65be20] [c000000000009a70] .do_one_initcall+0x168/0x1d0
[ 6.771642] [c0000000fe65bee0] [c0000000003dfb74] .kernel_init+0x14c/0x1f4
[ 6.812789] [c0000000fe65bf90] [c00000000001b478] .kernel_thread+0x54/0x70
[ 6.853932] Instruction dump:
[ 6.871641] 7fa4eb78 7ca507b4 482709ed 60000000 0fe00000 3860ffea 4bffff80 e87e8020
[ 6.917996] 7fa4eb78 7fe5fb78 482709cd 60000000 <0fe00000> 39200000 7f83e378 7f44d378
[ 6.965394] ---[ end trace a23e1daeebb82ff9 ]---
[ 6.993163] irq: irq-110==>hwirq-0x6e mapping failed: -22
[ 7.025301] ------------[ cut here ]------------
[ 7.052898] WARNING: at /usr/src/linux-3.6.11-aufs/kernel/irq/irqdomain.c:444
[ 7.095605] Modules linked in:
[ 7.113837] NIP: c0000000000ba93c LR: c0000000000ba938 CTR: c0000000000254b0
[ 7.156026] REGS: c0000000fe65b280 TRAP: 0700 Tainted: G W (3.6.11-aufs)
[ 7.202901] MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI> CR: 84000024 XER: 00000000
[ 7.249777] SOFTE: 1
[ 7.262799] TASK = c0000000fe650000[1] 'swapper/0' THREAD: c0000000fe658000 CPU: 0
GPR00: c0000000000ba938 c0000000fe65b500 c000000000668808 000000000000002d
GPR04: 0000000000000000 00000000861b01e7 0000000000000008 0000000000000000
GPR08: 000000008627bcd9 0000000000000000 0000000000000000 0000000000000000
GPR12: d000070000000000 c00000000fffb000 ffffffffffffffff 0000000002c0f498
GPR16: 0000000000000060 000000000ead9738 0000000002c0f498 00000000037db028
GPR20: 00000000037dc012 0000000000000000 c0000000fe006078 000000000000006f
GPR24: 00000000000001b8 000000000000006e 000000000000006e c0000000fe7d7d00
GPR28: c0000000fe006060 000000000000006e c000000000614b20 000000000000006e
[ 7.628959] NIP [c0000000000ba93c] .irq_domain_associate_many+0x264/0x290
[ 7.669584] LR [c0000000000ba938] .irq_domain_associate_many+0x260/0x290
[ 7.709686] Call Trace:
[ 7.724273] [c0000000fe65b500] [c0000000000ba938] .irq_domain_associate_many+0x260/0x290 (unreliable)
[ 7.779483] [c0000000fe65b5d0] [c0000000000bb3b8] .irq_create_mapping+0xc8/0x1d0
[ 7.823756] [c0000000fe65b670] [c0000000000bb568] .irq_create_of_mapping+0xa8/0x170
[ 7.869590] [c0000000fe65b720] [c0000000002777b0] .irq_of_parse_and_map+0x40/0x58
[ 7.914382] [c0000000fe65b7b0] [c0000000002778e0] .of_irq_count+0x30/0x58
[ 7.955009] [c0000000fe65b840] [c000000000278204] .of_device_alloc+0x94/0x238
[ 7.997719] [c0000000fe65b940] [c0000000002783fc] .of_platform_device_create_pdata+0x54/0xf8
[ 8.048241] [c0000000fe65b9e0] [c0000000002785e4] .of_platform_bus_create+0x144/0x1e0
[ 8.095118] [c0000000fe65bad0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 8.141994] [c0000000fe65bbc0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 8.188870] [c0000000fe65bcb0] [c000000000278830] .of_platform_bus_probe+0xd0/0x140
[ 8.234705] [c0000000fe65bd50] [c0000000003f0444] .__machine_initcall_cell_cell_publish_devices+0x54/0x1ac
[ 8.292519] [c0000000fe65be20] [c000000000009a70] .do_one_initcall+0x168/0x1d0
[ 8.335749] [c0000000fe65bee0] [c0000000003dfb74] .kernel_init+0x14c/0x1f4
[ 8.376896] [c0000000fe65bf90] [c00000000001b478] .kernel_thread+0x54/0x70
[ 8.418040] Instruction dump:
[ 8.435749] 7fa4eb78 7ca507b4 482709ed 60000000 0fe00000 3860ffea 4bffff80 e87e8020
[ 8.482104] 7fa4eb78 7fe5fb78 482709cd 60000000 <0fe00000> 39200000 7f83e378 7f44d378
[ 8.529503] ---[ end trace a23e1daeebb82ffa ]---
[ 8.557296] irq: irq-39==>hwirq-0x27 mapping failed: -22
[ 8.588889] ------------[ cut here ]------------
[ 8.616484] WARNING: at /usr/src/linux-3.6.11-aufs/kernel/irq/irqdomain.c:444
[ 8.659193] Modules linked in:
[ 8.677424] NIP: c0000000000ba93c LR: c0000000000ba938 CTR: c0000000000254b0
[ 8.719613] REGS: c0000000fe65b280 TRAP: 0700 Tainted: G W (3.6.11-aufs)
[ 8.766488] MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI> CR: 84000024 XER: 00000000
[ 8.813364] SOFTE: 1
[ 8.826387] TASK = c0000000fe650000[1] 'swapper/0' THREAD: c0000000fe658000 CPU: 0
GPR00: c0000000000ba938 c0000000fe65b500 c000000000668808 000000000000002c
GPR04: 0000000000000000 0000000088976500 0000000000000008 0000000000000000
GPR08: 0000000088a3e9d1 0000000000000000 0000000000000000 0000000000000000
GPR12: d000070000000000 c00000000fffb000 ffffffffffffffff 0000000002c0f498
GPR16: 0000000000000060 000000000ead9738 0000000002c0f498 00000000037db028
GPR20: 00000000037dc012 0000000000000000 c0000000fe006078 0000000000000028
GPR24: 000000000000009c 0000000000000027 0000000000000027 c0000000fe7d7e00
GPR28: c0000000fe006060 0000000000000027 c000000000614b20 0000000000000027
[ 9.192547] NIP [c0000000000ba93c] .irq_domain_associate_many+0x264/0x290
[ 9.233171] LR [c0000000000ba938] .irq_domain_associate_many+0x260/0x290
[ 9.273273] Call Trace:
[ 9.287860] [c0000000fe65b500] [c0000000000ba938] .irq_domain_associate_many+0x260/0x290 (unreliable)
[ 9.343070] [c0000000fe65b5d0] [c0000000000bb3b8] .irq_create_mapping+0xc8/0x1d0
[ 9.387343] [c0000000fe65b670] [c0000000000bb568] .irq_create_of_mapping+0xa8/0x170
[ 9.433177] [c0000000fe65b720] [c0000000002777b0] .irq_of_parse_and_map+0x40/0x58
[ 9.477969] [c0000000fe65b7b0] [c0000000002778e0] .of_irq_count+0x30/0x58
[ 9.518597] [c0000000fe65b840] [c000000000278204] .of_device_alloc+0x94/0x238
[ 9.561305] [c0000000fe65b940] [c0000000002783fc] .of_platform_device_create_pdata+0x54/0xf8
[ 9.611828] [c0000000fe65b9e0] [c0000000002785e4] .of_platform_bus_create+0x144/0x1e0
[ 9.658704] [c0000000fe65bad0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 9.705580] [c0000000fe65bbc0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 9.752458] [c0000000fe65bcb0] [c000000000278830] .of_platform_bus_probe+0xd0/0x140
[ 9.798293] [c0000000fe65bd50] [c0000000003f0444] .__machine_initcall_cell_cell_publish_devices+0x54/0x1ac
[ 9.856106] [c0000000fe65be20] [c000000000009a70] .do_one_initcall+0x168/0x1d0
[ 9.899337] [c0000000fe65bee0] [c0000000003dfb74] .kernel_init+0x14c/0x1f4
[ 9.940483] [c0000000fe65bf90] [c00000000001b478] .kernel_thread+0x54/0x70
[ 9.981627] Instruction dump:
[ 9.999336] 7fa4eb78 7ca507b4 482709ed 60000000 0fe00000 3860ffea 4bffff80 e87e8020
[ 10.045691] 7fa4eb78 7fe5fb78 482709cd 60000000 <0fe00000> 39200000 7f83e378 7f44d378
[ 10.093090] ---[ end trace a23e1daeebb82ffb ]---
[ 10.121125] irq: irq-93==>hwirq-0x5d mapping failed: -22
[ 10.152477] ------------[ cut here ]------------
[ 10.180072] WARNING: at /usr/src/linux-3.6.11-aufs/kernel/irq/irqdomain.c:444
[ 10.222780] Modules linked in:
[ 10.241012] NIP: c0000000000ba93c LR: c0000000000ba938 CTR: c0000000000254b0
[ 10.283201] REGS: c0000000fe65b370 TRAP: 0700 Tainted: G W (3.6.11-aufs)
[ 10.330075] MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI> CR: 84000024 XER: 00000000
[ 10.376951] SOFTE: 1
[ 10.389974] TASK = c0000000fe650000[1] 'swapper/0' THREAD: c0000000fe658000 CPU: 0
GPR00: c0000000000ba938 c0000000fe65b5f0 c000000000668808 000000000000002c
GPR04: 0000000000000000 000000008b1391f6 0000000000000008 0000000000000000
GPR08: 000000008b2016b5 0000000000000000 0000000000000000 0000000000000000
GPR12: d000070000000000 c00000000fffb000 ffffffffffffffff 0000000002c0f498
GPR16: 0000000000000060 000000000ead9738 0000000002c0f498 00000000037db028
GPR20: 00000000037dc012 0000000000000000 c0000001fe001018 000000000000005e
GPR24: 0000000000000174 000000000000005d 000000000000005d c0000001fe7a2100
GPR28: c0000001fe001000 000000000000005d c000000000614b20 000000000000005d
[ 10.756134] NIP [c0000000000ba93c] .irq_domain_associate_many+0x264/0x290
[ 10.796759] LR [c0000000000ba938] .irq_domain_associate_many+0x260/0x290
[ 10.836860] Call Trace:
[ 10.851448] [c0000000fe65b5f0] [c0000000000ba938] .irq_domain_associate_many+0x260/0x290 (unreliable)
[ 10.906658] [c0000000fe65b6c0] [c0000000000bb3b8] .irq_create_mapping+0xc8/0x1d0
[ 10.950930] [c0000000fe65b760] [c0000000000bb568] .irq_create_of_mapping+0xa8/0x170
[ 10.996764] [c0000000fe65b810] [c0000000002777b0] .irq_of_parse_and_map+0x40/0x58
[ 11.041557] [c0000000fe65b8a0] [c0000000002778e0] .of_irq_count+0x30/0x58
[ 11.082184] [c0000000fe65b930] [c000000000278204] .of_device_alloc+0x94/0x238
[ 11.124894] [c0000000fe65ba30] [c0000000002783fc] .of_platform_device_create_pdata+0x54/0xf8
[ 11.175415] [c0000000fe65bad0] [c0000000002785e4] .of_platform_bus_create+0x144/0x1e0
[ 11.222292] [c0000000fe65bbc0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 11.269168] [c0000000fe65bcb0] [c000000000278830] .of_platform_bus_probe+0xd0/0x140
[ 11.315003] [c0000000fe65bd50] [c0000000003f0444] .__machine_initcall_cell_cell_publish_devices+0x54/0x1ac
[ 11.372818] [c0000000fe65be20] [c000000000009a70] .do_one_initcall+0x168/0x1d0
[ 11.416049] [c0000000fe65bee0] [c0000000003dfb74] .kernel_init+0x14c/0x1f4
[ 11.457196] [c0000000fe65bf90] [c00000000001b478] .kernel_thread+0x54/0x70
[ 11.498338] Instruction dump:
[ 11.516047] 7fa4eb78 7ca507b4 482709ed 60000000 0fe00000 3860ffea 4bffff80 e87e8020
[ 11.562403] 7fa4eb78 7fe5fb78 482709cd 60000000 <0fe00000> 39200000 7f83e378 7f44d378
[ 11.609801] ---[ end trace a23e1daeebb82ffc ]---
[ 11.637919] irq: irq-59==>hwirq-0x3b mapping failed: -22
[ 11.669293] ------------[ cut here ]------------
[ 11.696887] WARNING: at /usr/src/linux-3.6.11-aufs/kernel/irq/irqdomain.c:444
[ 11.739595] Modules linked in:
[ 11.757826] NIP: c0000000000ba93c LR: c0000000000ba938 CTR: c0000000000254b0
[ 11.800016] REGS: c0000000fe65b190 TRAP: 0700 Tainted: G W (3.6.11-aufs)
[ 11.846890] MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI> CR: 84000024 XER: 00000000
[ 11.893767] SOFTE: 1
[ 11.906789] TASK = c0000000fe650000[1] 'swapper/0' THREAD: c0000000fe658000 CPU: 0
GPR00: c0000000000ba938 c0000000fe65b410 c000000000668808 000000000000002c
GPR04: 0000000000000000 000000008d7cac57 0000000000000008 0000000000000000
GPR08: 000000008d893bed 0000000000000000 0000000000000000 0000000000000000
GPR12: d000070000000000 c00000000fffb000 ffffffffffffffff 0000000002c0f498
GPR16: 0000000000000060 000000000ead9738 0000000002c0f498 00000000037db028
GPR20: 00000000037dc012 0000000000000000 c0000001fe001018 000000000000003c
GPR24: 00000000000000ec 000000000000003b 000000000000003b c0000001fe7a2600
GPR28: c0000001fe001000 000000000000003b c000000000614b20 000000000000003b
[ 12.272949] NIP [c0000000000ba93c] .irq_domain_associate_many+0x264/0x290
[ 12.313574] LR [c0000000000ba938] .irq_domain_associate_many+0x260/0x290
[ 12.353675] Call Trace:
[ 12.368263] [c0000000fe65b410] [c0000000000ba938] .irq_domain_associate_many+0x260/0x290 (unreliable)
[ 12.423473] [c0000000fe65b4e0] [c0000000000bb3b8] .irq_create_mapping+0xc8/0x1d0
[ 12.467745] [c0000000fe65b580] [c0000000000bb568] .irq_create_of_mapping+0xa8/0x170
[ 12.513579] [c0000000fe65b630] [c0000000002777b0] .irq_of_parse_and_map+0x40/0x58
[ 12.558372] [c0000000fe65b6c0] [c0000000002778e0] .of_irq_count+0x30/0x58
[ 12.599002] [c0000000fe65b750] [c000000000278204] .of_device_alloc+0x94/0x238
[ 12.641708] [c0000000fe65b850] [c0000000002783fc] .of_platform_device_create_pdata+0x54/0xf8
[ 12.692231] [c0000000fe65b8f0] [c0000000002785e4] .of_platform_bus_create+0x144/0x1e0
[ 12.739107] [c0000000fe65b9e0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 12.785983] [c0000000fe65bad0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 12.832860] [c0000000fe65bbc0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 12.879736] [c0000000fe65bcb0] [c000000000278830] .of_platform_bus_probe+0xd0/0x140
[ 12.925572] [c0000000fe65bd50] [c0000000003f0444] .__machine_initcall_cell_cell_publish_devices+0x54/0x1ac
[ 12.983385] [c0000000fe65be20] [c000000000009a70] .do_one_initcall+0x168/0x1d0
[ 13.026616] [c0000000fe65bee0] [c0000000003dfb74] .kernel_init+0x14c/0x1f4
[ 13.067764] [c0000000fe65bf90] [c00000000001b478] .kernel_thread+0x54/0x70
[ 13.108905] Instruction dump:
[ 13.126614] 7fa4eb78 7ca507b4 482709ed 60000000 0fe00000 3860ffea 4bffff80 e87e8020
[ 13.172970] 7fa4eb78 7fe5fb78 482709cd 60000000 <0fe00000> 39200000 7f83e378 7f44d378
[ 13.220369] ---[ end trace a23e1daeebb82ffd ]---
[ 13.248514] irq: irq-20==>hwirq-0x2 mapping failed: -22
[ 13.279339] ------------[ cut here ]------------
[ 13.306933] WARNING: at /usr/src/linux-3.6.11-aufs/kernel/irq/irqdomain.c:444
[ 13.349642] Modules linked in:
[ 13.367873] NIP: c0000000000ba93c LR: c0000000000ba938 CTR: c0000000000254b0
[ 13.410062] REGS: c0000000fe65b0a0 TRAP: 0700 Tainted: G W (3.6.11-aufs)
[ 13.456937] MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI> CR: 84000024 XER: 00000000
[ 13.503813] SOFTE: 1
[ 13.516836] TASK = c0000000fe650000[1] 'swapper/0' THREAD: c0000000fe658000 CPU: 0
GPR00: c0000000000ba938 c0000000fe65b320 c000000000668808 000000000000002b
GPR04: 0000000000000000 00000000900bf6b2 0000000000000008 0000000000000000
GPR08: 0000000090185006 0000000000000000 0000000000000000 0000000000000000
GPR12: d000070000000000 c00000000fffb000 ffffffffffffffff 0000000002c0f498
GPR16: 0000000000000060 000000000ead9738 0000000002c0f498 00000000037db028
GPR20: 00000000037dc012 0000000000000000 c0000001fe001018 0000000000000015
GPR24: 0000000000000008 0000000000000002 0000000000000014 c0000001fe7a2900
GPR28: c0000001fe001000 0000000000000014 c000000000614b20 0000000000000002
[ 13.882996] NIP [c0000000000ba93c] .irq_domain_associate_many+0x264/0x290
[ 13.923620] LR [c0000000000ba938] .irq_domain_associate_many+0x260/0x290
[ 13.963723] Call Trace:
[ 13.978310] [c0000000fe65b320] [c0000000000ba938] .irq_domain_associate_many+0x260/0x290 (unreliable)
[ 14.033520] [c0000000fe65b3f0] [c0000000000bb3b8] .irq_create_mapping+0xc8/0x1d0
[ 14.077792] [c0000000fe65b490] [c0000000000bb568] .irq_create_of_mapping+0xa8/0x170
[ 14.123627] [c0000000fe65b540] [c0000000002777b0] .irq_of_parse_and_map+0x40/0x58
[ 14.168419] [c0000000fe65b5d0] [c0000000002778e0] .of_irq_count+0x30/0x58
[ 14.209046] [c0000000fe65b660] [c000000000278204] .of_device_alloc+0x94/0x238
[ 14.251756] [c0000000fe65b760] [c0000000002783fc] .of_platform_device_create_pdata+0x54/0xf8
[ 14.302277] [c0000000fe65b800] [c0000000002785e4] .of_platform_bus_create+0x144/0x1e0
[ 14.349154] [c0000000fe65b8f0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 14.396031] [c0000000fe65b9e0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 14.442906] [c0000000fe65bad0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 14.489783] [c0000000fe65bbc0] [c [c00000000001b478] .kernel_thread+0x54/0x70
[ 14.765829] Instruction dump:
[ 14.783538] 7fa4eb78 7ca507b4 482709ed 60000000 0fe00000 3860ffea 4bffff80 e87e8020
[ 14.829893] 7fa4eb78 7fe5fb78 482709cd 60000000 <0fe00000> 39200000 7f83e378 7f44d378
[ 14.877292] ---[ end trace a23e1daeebb82ffe ]---
[ 14.906827] irq: irq-108==>hwirq-0x66 mapping failed: -22
[ 14.938714] ------------[ cut here ]------------
[ 14.966305] WARNING: at /usr/src/linux-3.6.11-aufs/kernel/irq/irqdomain.c:444
[ 15.009014] Modules linked in:
[ 15.027245] NIP: c0000000000ba93c LR: c0000000000ba938 CTR: c0000000000254b0
[ 15.069434] REGS: c0000000fe65b280 TRAP: 0700 Tainted: G W (3.6.11-aufs)
[ 15.116308] MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI> CR: 84000024 XER: 00000000
[ 15.163184] SOFTE: 1
[ 15.176207] TASK = c0000000fe650000[1] 'swapper/0' THREAD: c0000000fe658000 CPU: 0
GPR00: c0000000000ba938 c0000000fe65b500 c000000000668808 000000000000002d
GPR04: 0000000000000000 0000000092ae860b 0000000000000008 0000000000000000
GPR08: 0000000092bb75bd 0000000000000000 0000000000000000 0000000000000000
GPR12: d000070000000000 c00000000fffb000 ffffffffffffffff 0000000002c0f498
GPR16: 0000000000000060 000000000ead9738 0000000002c0f498 00000000037db028
GPR20: 00000000037dc012 0000000000000000 c0000001fe001018 000000000000006d
GPR24: 0000000000000198 0000000000000066 000000000000006c c0000001fe7a6400
GPR28: c0000001fe001000 000000000000006c c000000000614b20 0000000000000066
[ 15.542368] NIP [c0000000000ba93c] .irq_domain_associate_many+0x264/0x290
[ 15.582992] LR [c0000000000ba938] .irq_domain_associate_many+0x260/0x290
[ 15.623094] Call Trace:
[ 15.637681] [c0000000fe65b500] [c0000000000ba938] .irq_domain_associate_many+0x260/0x290 (unreliable)
[ 15.692891] [c0000000fe65b5d0] [c0000000000bb3b8] .irq_create_mapping+0xc8/0x1d0
[ 15.737164] [c0000000fe65b670] [c0000000000bb568] .irq_create_of_mapping+0xa8/0x170
[ 15.782998] [c0000000fe65b720] [c0000000002777b0] .irq_of_parse_and_map+0x40/0x58
[ 15.827791] [c0000000fe65b7b0] [c0000000002778e0] .of_irq_count+0x30/0x58
[ 15.868417] [c0000000fe65b840] [c000000000278204] .of_device_alloc+0x94/0x238
[ 15.911126] [c0000000fe65b940] [c0000000002783fc] .of_platform_device_create_pdata+0x54/0xf8
[ 15.961649] [c0000000fe65b9e0] [c0000000002785e4] .of_platform_bus_create+0x144/0x1e0
[ 16.008525] [c0000000fe65bad0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 16.055402] [c0000000fe65bbc0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 16.102278] [c0000000fe65bcb0] [c000000000278830] .of_platform_bus_probe+0xd0/0x140
[ 16.148114] [c0000000fe65bd50] [c0000000003f0444] .__machine_initcall_cell_cell_publish_devices+0x54/0x1ac
[ 16.205928] [c0000000fe65be20] [c000000000009a70] .do_one_initcall+0x168/0x1d0
[ 16.249158] [c0000000fe65bee0] [c0000000003dfb74] .kernel_init+0x14c/0x1f4
[ 16.290306] [c0000000fe65bf90] [c00000000001b478] .kernel_thread+0x54/0x70
[ 16.331448] Instrucn6475] NIP [c0000000000ba93c] .irq_domain_associate_many+0x264/0x290
[ 17.147100] LR [c0000000000ba938] .irq_domain_associate_many+0x260/0x290
[ 17.187202] Call Trace:
[ 17.201789] [c0000000fe65b500] [c0000000000ba938] .irq_domain_associate_many+0x260/0x290 (unreliable)
[ 17.256999] [c0000000fe65b5d0] [c0000000000bb3b8] .irq_create_mapping+0xc8/0x1d0
[ 17.301272] [c0000000fe65b670] [c0000000000bb568] .irq_create_of_mapping+0xa8/0x170
[ 17.347106] [c0000000fe65b720] [c0000000002777b0] .irq_of_parse_and_map+0x40/0x58
[ 17.391898] [c0000000fe65b7b0] [c0000000002778e0] .of_irq_count+0x30/0x58
[ 17.432525] [c0000000fe65b840] [c000000000278204] .of_device_alloc+0x94/0x238
[ 17.475235] [c0000000fe65b940] [c0000000002783fc] .of_platform_device_create_pdata+0x54/0xf8
[ 17.525757] [c0000000fe65b9e0] [c0000000002785e4] .of_platform_bus_create+0x144/0x1e0
[ 17.572634] [c0000000fe65bad0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 17.619510] [c0000000fe65bbc0] [c000000000278640] .of_platform_bus_create+0x1a0/0x1e0
[ 17.666387] [c0000000fe65bcb0] [c000000000278830] .of_platform_bus_probe+0xd0/0x140
[ 17.712221] [c0000000fe65bd50] [c0000000003f0444] .__machine_initcall_cell_cell_publish_devices+0x54/0x1ac
[ 17.770036] [c0000000fe65be20] [c000000000009a70] .do_one_initcall+0x168/0x1d0
[ 17.813266] [c0000000fe65bee0] [c0000000003dfb74] .kernel_init+0x14c/0x1f4
[ 17.854415] [c0000000fe65bf90] [c00000000001b478] .kernel_thread+0x54/0x70
[ 17.895556] Instruction dump:
[ 17.913265] 7fa4eb78 7ca507b4 482709ed 60000000 0fe00000 3860ffea 4bffff80 e87e8020
[ 17.959621] 7fa4eb78 7fe5fb78 482709cd 60000000 <0fe00000> 39200000 7f83e378 7f44d378
[ 18.007019] ---[ end trace a23e1daeebb83000 ]---
[ 18.034834] irq: irq-42==>hwirq-0x27 mapping failed: -22
[ 18.066406] ------------[ cut here ]------------
[ 18.094000] WARNING: at /usr/src/linux-3.6.11-aufs/kernel/irq/irqdomain.c:444
[ 18.136709] Modules linked in:
[ 18.154940] NIP: c0000000000ba93c LR: c0000000000ba938 CTR: c0000000000254b0
[ 18.197130] REGS: c0000000fe65b280 TRAP: 0700 Tainted: G W (3.6.11-aufs)
[ 18.244004] MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI> CR: 84000024 XER: 00000000
[ 18.290880] SOFTE: 1
[ 18.303903] TASK = c0000000fe650000[1] 'swapper/0' THREAD: c0000000fe658000 CPU: 0
GPR00: c0000000000ba938 c0000000fe65b500 c000000000668808 000000000000002c
GPR04: 0000000000000000 0000000097a78110 0000000000000008 0000000000000000
GPR08: 0000000097b405d5 0000000000000000 0000000000000000 0000000000000000
GPR12: d000070000000000 c00000000fffb000 ffffffffffffffff 0000000002c0f498
GPR16: 0000000000000060 000000000ead9738 0000000002c0f498 00000000037db028
GPR20: 00000000037dc012 0000000000000000 c0000001fe001018 000000000000002b
GPR24: 000000000000009c 0000000000000027 000000000000002a c0000001fe7a6500
GPR28: c0000001fe001000 000000000000002a c000000000614b20 0000000000000027
[ 18.670062] NIP [c0000000000ba93c] .irq_domain_associate_many+0x264/0x290
[9.376854] [c0000000fe65bee0] [c0000000003dfb74] .kernel_init+0x14c/0x1f4
[ 19.418000] [c0000000fe65bf90] [c00000000001b478] .kernel_thread+0x54/0x70
[ 19.459143] Instruction dump:
[ 19.476852] 7fa4eb78 7ca507b4 482709ed 60000000 0fe00000 3860ffea 4bffff80 e87e8020
[ 19.523208] 7fa4eb78 7fe5fb78 482709cd 60000000 <0fe00000> 39200000 7f83e378 7f44d378
[ 19.570606] ---[ end trace a23e1daeebb83001 ]---
[ 19.598449] iommu: missing iommu for <no-node> (node -1)
[ 19.630031] iommu: missing iommu for <no-node> (node -1)
[ 19.661896] axon_msi: setup MSIC on /axon@10000000000/plb5/msic@4000004400003000
[ 19.706220] axon_msi: setup MSIC on /axon@30000000000/plb5/msic@4000004400003000
[ 19.751382] bio: create slab <bio-0> at 0
[ 19.775232] vgaarb: loaded
[ 19.791382] Switching to clocksource timebase
[ 19.823496] NET: Registered protocol family 2
[ 19.851983] TCP established hash table entries: 524288 (order: 11, 8388608 bytes)
[ 19.904057] TCP bind hash table entries: 65536 (order: 8, 1048576 bytes)
[ 19.946030] TCP: Hash tables configured (established 524288 bind 65536)
[ 19.985278] TCP: reno registered
[ 20.004540] UDP hash table entries: 4096 (order: 5, 131072 bytes)
[ 20.041124] UDP-Lite hash table entries: 4096 (order: 5, 131072 bytes)
[ 20.080321] PCI: CLS 0 bytes, default 128
[ 20.104111] Unpacking initramfs...
[ 22.854958] Freeing initrd memory: 7020k freed
[ 22.882363] iommu: missing iommu for <no-node> (node -1)
[ 22.913895] Setting up PCI bus /axon@10000000000/plb5/plb4/pcix@4000004600000000
[ 22.958055] PCI host bridge /axon@10000000000/plb5/plb4/pcix@4000004600000000 ranges:
[ 23.005414] IO 0x0000014608000000..0x000001460800ffff -> 0x0000000000000000
[ 23.048120] MEM 0x0000014780000000..0x00000147bfffffff -> 0x0000000080000000
[ 23.091360] MEM 0x00000147c0000000..0x00000147ffffffff -> 0x00000000c0000000 Prefetch
[ 23.138865] of-pci 14600000000.pcix: PCI host bridge to bus 0000:00
[ 23.176252] pci_bus 0000:00: root bus resource [io 0x10000-0x1ffff] (bus address [0x0000-0xffff])
[ 23.229893] pci_bus 0000:00: root bus resource [mem 0x14780000000-0x147bfffffff] (bus address [0x80000000-0xbfffffff])
[ 23.293958] pci_bus 0000:00: root bus resource [mem 0x147c0000000-0x147ffffffff pref] (bus address [0xc0000000-0xffffffff])
[ 23.360632] pci_bus 0000:00: busn_res: [bus 00-ff] is inserted under domain [bus 00-ff]
[ 23.408542] pci_bus 0000:00: root bus resource [bus 00-ff]
[ 23.441357] pci_bus 0000:00: busn_res: [bus 00-ff] end is updated to ff
[ 23.481038] pci 0000:00:01.0: [14e4:16a8] type 00 class 0x020000
[ 23.516978] pci 0000:00:01.0: reg 10: [mem 0x14780000000-0x1478000ffff 64bit]
[ 23.560015] pci 0000:00:01.0: PME# supported from D3hot D3cold
[ 23.594619] pci 0000:00:01.1: [14e4:16a8] type 00 class 0x020000
[ 23.630519] pci 0000:00:01.1: reg 10: [mem 0x14780010000-0x1478001ffff 64bit]
[ 23.673553] pci 0000:00:01.1: PME# supported from D3hot D3cold
[ 23.708197] pci_bus 0000:00: busn_res: [bus 00-ff] end is updated to 00
[ 23.747817] Setting up PCI bus /axon@10000000000/plb5/pciex@a00000a000000000
[ 23.789821] PCI host bridge /axon@10000000000/plb5/pciex@a00000a000000000 ranges:
[ 23.835121] IO 0x000001a100000000..0x000001a10000ffff -> 0x0000000000000000
[ 23.877831] MEM 0x000001c080000000..0x000001c0bfffffff -> 0x0000000080000000
[ 23.921065] MEM 0x000001c0c0000000..0x000001c0ffffffff -> 0x00000000c0000000 Prefetch
[ 23.968536] of-pci D18000002400.pciex: PCI host bridge to bus 0001:00
[ 24.007001] pci_bus 0001:00: root bus resource [io 0x21000-0x30fff] (bus address [0x0000-0xffff])
[ 24.060648] pci_bus 0001:00: root bus resource [mem 0x1c080000000-0x1c0bfffffff] (bus address [0x80000000-0xbfffffff])
[ 24.124712] pci_bus 0001:00: root bus resource [mem 0x1c0c0000000-0x1c0ffffffff pref] (bus address [0xc0000000-0xffffffff])
[ 24.191383] pci_bus 0001:00: busn_res: [bus 00-ff] is inserted under domain [bus 00-ff]
[ 24.239295] pci_bus 0001:00: root bus resource [bus 00-ff]
[ 24.272109] pci_bus 0001:00: busn_res: [bus 00-ff] end is updated to ff
[ 24.311780] pci 0001:00:00.0: [1014:032c] type 01 class 0x060400
[ 24.347720] pci 0001:00:00.0: reg 10: [mem 0x00000000-0x7fffffff 64bit pref]
[ 24.389867] pci 0001:00:00.0: reg 38: [mem 0x1c0ffff8000-0x1c0ffffffff pref]
[ 24.432068] PCI: Hiding resources on Axon PCIE RC 0001:00:00.0
[ 24.467137] pci 0001:00:00.0: supports D1 D2
[ 24.492427] pci 0001:00:00.0: PME# supported from D0 D1 D2 D3hot D3cold
[ 24.532148] irq: no irq domain found for /axon@10000000000/plb5/pciex-utl@a00000a000004000 !
[ 24.582772] pci_bus 0001:01: busn_res: [bus 01] is inserted under [bus 00-ff]
[ 24.625247] pci 0001:00:00.0: PCI bridge to [bus 01]
[ 24.655032] pci_bus 0001:00: busn_res: [bus 00-ff] end is updated to 01
[ 24.694651] Setting up PCI bus /axon@10000000000/plb5/pciex@a00000a200000000
[ 24.736724] PCI host bridge /axon@10000000000/plb5/pciex@a00000a200000000 ranges:
[ 24.782024] IO 0x000001a300000000..0x000001a30000ffff -> 0x0000000000000000
[ 24.824734] MEM 0x000001d080000000..0x000001d0bfffffff -> 0x0000000080000000
[ 24.867963] MEM 0x000001d0c0000000..0x000001d0ffffffff -> 0x00000000c0000000 Prefetch
[ 24.915433] of-pci D18000002800.pciex: PCI host bridge to bus 0002:00
[ 24.953903] pci_bus 0002:00: root bus resource [io 0x32000-0x41fff] (bus address [0x0000-0xffff])
[ 25.007553] pci_bus 0002:00: root bus resource [mem 0x1d080000000-0x1d0bfffffff] (bus address [0x80000000-0xbfffffff])
[ 25.071614] pci_bus 0002:00: root bus resource [mem 0x1d0c0000000-0x1d0ffffffff pref] (bus address [0xc0000000-0xffffffff])
[ 25.138283] pci_bus 0002:00: busn_res: [bus 00-ff] is inserted under domain [bus 00-ff]
[ 25.186198] pci_bus 0002:00: root bus resource [bus 00-ff]
[ 25.219012] pci_bus 0002:00: busn_res: [bus 00-ff] end is updated to ff
[ 25.258682] pci 0002:00:00.0: [1014:032c] type 01 class 0x060400
[ 25.294623] pci 0002:00:00.0: reg 10: [mem 0x00000000-0x7fffffff 64bit pref]
[ 25.336770] pci 0002:00:00.0: reg 38: [mem 0x1d0ffff8000-0x1d0ffffffff pref]
[ 25.378971] PCI: Hiding resources on Axon PCIE RC 0002:00:00.0
[ 25.414030] pci 0002:00:00.0: supports D1 D2
[ 25.439331] pci 0002:00:00.0: PME# supported from D0 D1 D2 D3hot D3cold
[ 25.479038] irq: no irq domain found for /axon@10000000000/plb5/pciex-utl@a00000a200004000 !
[ 25.529676] pci_bus 0002:01: busn_res: [bus 01] is inserted under [bus 00-ff]
[ 25.572151] pci 0002:00:00.0: PCI bridge to [bus 01]
[ 25.601933] pci_bus 0002:00: busn_res: [bus 00-ff] end is updated to 01
[ 25.641567] Setting up PCI bus /axon@30000000000/plb5/plb4/pcix@4000004600000000
[ 25.685712] PCI host bridge /axon@30000000000/plb5/plb4/pcix@4000004600000000 ranges:
[ 25.733096] IO 0x0000034608000000..0x000003460800ffff -> 0x0000000000000000
[ 25.775804] MEM 0x0000034780000000..0x00000347bfffffff -> 0x0000000080000000
[ 25.819034] MEM 0x00000347c0000000..0x00000347ffffffff -> 0x00000000c0000000 Prefetch
[ 25.866515] of-pci 34600000000.pcix: PCI host bridge to bus 0003:00
[ 25.903931] pci_bus 0003:00: root bus resource [io 0x43000-0x52fff] (bus address [0x0000-0xffff])
[ 25.957577] pci_bus 0003:00: root bus resource [mem 0x34780000000-0x347bfffffff] (bus address [0x80000000-0xbfffffff])
[ 26.021642] pci_bus 0003:00: root bus resource [mem 0x347c0000000-0x347ffffffff pref] (bus address [0xc0000000-0xffffffff])
[ 26.088311] pci_bus 0003:00: busn_res: [bus 00-ff] is inserted under domain [bus 00-ff]
[ 26.136228] pci_bus 0003:00: root bus resource [bus 00-ff]
[ 26.169040] pci_bus 0003:00: busn_res: [bus 00-ff] end is updated to ff
[ 26.208674] pci 0003:00:01.0: [1033:0035] type 00 class 0x0c0310
[ 26.244638] pci 0003:00:01.0: reg 10: [mem 0x34780000000-0x34780000fff]
[ 26.284501] pci 0003:00:01.0: supports D1 D2
[ 26.309668] pci 0003:00:01.0: PME# supported from D0 D1 D2 D3hot
[ 26.345691] pci 0003:00:01.1: [1033:0035] type 00 class 0x0c0310
[ 26.381620] pci 0003:00:01.1: reg 10: [mem 0x34780001000-0x34780001fff]
[ 26.421491] pci 0003:00:01.1: supports D1 D2
[ 26.446651] pci 0003:00:01.1: PME# supported from D0 D1 D2 D3hot
[ 26.482675] pci 0003:00:01.2: [1033:00e0] type 00 class 0x0c0320
[ 26.518603] pci 0003:00:01.2: reg 10: [mem 0x34780002000-0x347800020ff]
[ 26.558472] pci 0003:00:01.2: supports D1 D2
[ 26.583635] pci 0003:00:01.2: PME# supported from D0 D1 D2 D3hot
[ 26.619724] pci_bus 0003:00: busn_res: [bus 00-ff] end is updated to 00
[ 26.761253] pci 0003:00:01.2: enabling device (0140 -> 0142)
[ 26.794828] Setting up PCI bus /axon@30000000000/plb5/pciex@a00000a000000000
[ 26.836889] PCI host bridge /axon@30000000000/plb5/pciex@a00000a000000000 ranges:
[ 26.882190] IO 0x000003a100000000..0x000003a10000ffff -> 0x0000000000000000
[ 26.924899] MEM 0x000003c080000000..0x000003c0bfffffff -> 0x0000000080000000
[ 26.968134] MEM 0x000003c0c0000000..0x000003c0ffffffff -> 0x00000000c0000000 Prefetch
[ 27.015609] of-pci D38000002400.pciex: PCI host bridge to bus 0004:00
[ 27.054072] pci_bus 0004:00: root bus resource [io 0x54000-0x63fff] (bus address [0x0000-0xffff])
[ 27.107717] pci_bus 0004:00: root bus resource [mem 0x3c080000000-0x3c0bfffffff] (bus address [0x80000000-0xbfffffff])
[ 27.171780] pci_bus 0004:00: root bus resource [mem 0x3c0c0000000-0x3c0ffffffff pref] (bus address [0xc0000000-0xffffffff])
[ 27.238449] pci_bus 0004:00: busn_res: [bus 00-ff] is inserted under domain [bus 00-ff]
[ 27.286363] pci_bus 0004:00: root bus resource [bus 00-ff]
[ 27.319179] pci_bus 0004:00: busn_res: [bus 00-ff] end is updated to ff
[ 27.358854] pci 0004:00:00.0: [1014:032c] type 01 class 0x060400
[ 27.394794] pci 0004:00:00.0: reg 10: [mem 0x00000000-0x7fffffff 64bit pref]
[ 27.436939] pci 0004:00:00.0: reg 38: [mem 0x3c0ffff8000-0x3c0ffffffff pref]
[ 27.479145] PCI: Hiding resources on Axon PCIE RC 0004:00:00.0
[ 27.514218] pci 0004:00:00.0: supports D1 D2
[ 27.539495] pci 0004:00:00.0: PME# supported from D0 D1 D2 D3hot D3cold
[ 27.579230] irq: no irq domain found for /axon@30000000000/plb5/pciex-utl@a00000a000004000 !
[ 27.629860] pci_bus 0004:01: busn_res: [bus 01] is inserted under [bus 00-ff]
[ 27.672314] pci 0004:00:00.0: PCI bridge to [bus 01]
[ 27.702107] pci_bus 0004:00: busn_res: [bus 00-ff] end is updated to 01
[ 27.741724] Setting up PCI bus /axon@30000000000/plb5/pciex@a00000a200000000
[ 27.783790] PCI host bridge /axon@30000000000/plb5/pciex@a00000a200000000 ranges:
[ 27.829092] IO 0x000003a300000000..0x000003a30000ffff -> 0x0000000000000000
[ 27.871803] MEM 0x000003d080000000..0x000003d0bfffffff -> 0x0000000080000000
[ 27.915031] MEM 0x000003d0c0000000..0x000003d0ffffffff -> 0x00000000c0000000 Prefetch
[ 27.962516] of-pci D38000002800.pciex: PCI host bridge to bus 0005:00
[ 28.000971] pci_bus 0005:00: root bus resource [io 0x65000-0x74fff] (bus address [0x0000-0xffff])
[ 28.054618] pci_bus 0005:00: root bus resource [mem 0x3d080000000-0x3d0bfffffff] (bus address [0x80000000-0xbfffffff])
[ 28.118682] pci_bus 0005:00: root bus resource [mem 0x3d0c0000000-0x3d0ffffffff pref] (bus address [0xc0000000-0xffffffff])
[ 28.185353] pci_bus 0005:00: busn_res: [bus 00-ff] is inserted under domain [bus 00-ff]
[ 28.233267] pci_bus 0005:00: root bus resource [bus 00-ff]
[ 28.266080] pci_bus 0005:00: busn_res: [bus 00-ff] end is updated to ff
[ 28.305755] pci 0005:00:00.0: [1014:032c] type 01 class 0x060400
[ 28.341695] pci 0005:00:00.0: reg 10: [mem 0x00000000-0x7fffffff 64bit pref]
[ 28.383842] pci 0005:00:00.0: reg 38: [mem 0x3d0ffff8000-0x3d0ffffffff pref]
[ 28.426043] PCI: Hiding resources on Axon PCIE RC 0005:00:00.0
[ 28.461115] pci 0005:00:00.0: supports D1 D2
[ 28.486398] pci 0005:00:00.0: PME# supported from D0 D1 D2 D3hot D3cold
[ 28.526116] irq: no irq domain found for /axon@30000000000/plb5/pciex-utl@a00000a200004000 !
[ 28.576762] pci_bus 0005:01: busn_res: [bus 01] is inserted under [bus 00-ff]
[ 28.619382] pci 0005:01:00.0: [15b3:634a] type 00 class 0x0c0600
[ 28.655326] pci 0005:01:00.0: reg 10: [mem 0x3d080000000-0x3d0800fffff 64bit]
[ 28.698001] pci 0005:01:00.0: reg 18: [mem 0x3d0c0000000-0x3d0c1ffffff 64bit pref]
[ 28.744181] pci 0005:00:00.0: PCI bridge to [bus 01]
[ 28.773481] pci 0005:00:00.0: bridge window [mem 0x3d080000000-0x3d0800fffff]
[ 28.817219] pci 0005:00:00.0: bridge window [mem 0x3d0c0000000-0x3d0c1ffffff 64bit pref]
[ 28.866752] pci_bus 0005:00: busn_res: [bus 00-ff] end is updated to 01
[ 28.906596] iommu: missing iommu for <no-node> (node -1)
[ 28.942003] iommu: missing iommu for <no-node> (node -1)
[ 28.979542] msgmni has been set to 15888
[ 29.002740] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
[ 29.046837] io scheduler noop registered
[ 29.070268] io scheduler deadline registered
[ 29.095984] io scheduler cfq registered (default)
[ 29.168736] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[ 29.206481] iommu: missing iommu for <no-node> (node -1)
[ 29.259915] serial8250.0: ttyS0 at MMIO 0x14540000200 (irq = 16) is a U6_16550A
[ 29.303338] console [ttyS0] enabled, bootconsole disabled
[ 29.303338] console [ttyS0] enabled, bootconsole disabled
[ 29.389162] serial8250.0: ttyS1 at MMIO 0x14540000300 (irq = 17) is a U6_16550A
[ 29.454303] serial8250.0: ttyS2 at MMIO 0x34540000200 (irq = 18) is a U6_16550A
[ 29.519453] serial8250.0: ttyS3 at MMIO 0x34540000300 (irq = 19) is a U6_16550A
[ 29.563961] mousedev: PS/2 mouse device common for all mice
[ 29.597418] cpuidle: using governor ladder
[ 29.621974] cpuidle: using governor menu
[ 29.645908] TCP: cubic registered
[ 29.665828] Key type dns_resolver registered
[ 29.693738] /usr/src/linux-3.6.11-aufs/drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
[ 29.749311] Freeing unused kernel memory: 2016k freed
[ 30.040855] dracut: dracut-dracut-024-3246731
[ 30.272613] dracut: FATAL: No or empty root= argument
[ 30.302997] dracut: Refusing to continue
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* [PATCH v5 12/14] memory-hotplug: memory_hotplug: clear zone when removing the memory
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
In-Reply-To: <1356350964-13437-1-git-send-email-tangchen@cn.fujitsu.com>
From: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
When a memory is added, we update zone's and pgdat's start_pfn and
spanned_pages in the function __add_zone(). So we should revert them
when the memory is removed.
The patch adds a new function __remove_zone() to do this.
Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
---
mm/memory_hotplug.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 207 insertions(+), 0 deletions(-)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 71cb656..a1b0632 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -430,8 +430,211 @@ static int __meminit __add_section(int nid, struct zone *zone,
return register_new_memory(nid, __pfn_to_section(phys_start_pfn));
}
+/* find the smallest valid pfn in the range [start_pfn, end_pfn) */
+static int find_smallest_section_pfn(int nid, struct zone *zone,
+ unsigned long start_pfn,
+ unsigned long end_pfn)
+{
+ struct mem_section *ms;
+
+ for (; start_pfn < end_pfn; start_pfn += PAGES_PER_SECTION) {
+ ms = __pfn_to_section(start_pfn);
+
+ if (unlikely(!valid_section(ms)))
+ continue;
+
+ if (unlikely(pfn_to_nid(start_pfn) != nid))
+ continue;
+
+ if (zone && zone != page_zone(pfn_to_page(start_pfn)))
+ continue;
+
+ return start_pfn;
+ }
+
+ return 0;
+}
+
+/* find the biggest valid pfn in the range [start_pfn, end_pfn). */
+static int find_biggest_section_pfn(int nid, struct zone *zone,
+ unsigned long start_pfn,
+ unsigned long end_pfn)
+{
+ struct mem_section *ms;
+ unsigned long pfn;
+
+ /* pfn is the end pfn of a memory section. */
+ pfn = end_pfn - 1;
+ for (; pfn >= start_pfn; pfn -= PAGES_PER_SECTION) {
+ ms = __pfn_to_section(pfn);
+
+ if (unlikely(!valid_section(ms)))
+ continue;
+
+ if (unlikely(pfn_to_nid(pfn) != nid))
+ continue;
+
+ if (zone && zone != page_zone(pfn_to_page(pfn)))
+ continue;
+
+ return pfn;
+ }
+
+ return 0;
+}
+
+static void shrink_zone_span(struct zone *zone, unsigned long start_pfn,
+ unsigned long end_pfn)
+{
+ unsigned long zone_start_pfn = zone->zone_start_pfn;
+ unsigned long zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
+ unsigned long pfn;
+ struct mem_section *ms;
+ int nid = zone_to_nid(zone);
+
+ zone_span_writelock(zone);
+ if (zone_start_pfn == start_pfn) {
+ /*
+ * If the section is smallest section in the zone, it need
+ * shrink zone->zone_start_pfn and zone->zone_spanned_pages.
+ * In this case, we find second smallest valid mem_section
+ * for shrinking zone.
+ */
+ pfn = find_smallest_section_pfn(nid, zone, end_pfn,
+ zone_end_pfn);
+ if (pfn) {
+ zone->zone_start_pfn = pfn;
+ zone->spanned_pages = zone_end_pfn - pfn;
+ }
+ } else if (zone_end_pfn == end_pfn) {
+ /*
+ * If the section is biggest section in the zone, it need
+ * shrink zone->spanned_pages.
+ * In this case, we find second biggest valid mem_section for
+ * shrinking zone.
+ */
+ pfn = find_biggest_section_pfn(nid, zone, zone_start_pfn,
+ start_pfn);
+ if (pfn)
+ zone->spanned_pages = pfn - zone_start_pfn + 1;
+ }
+
+ /*
+ * The section is not biggest or smallest mem_section in the zone, it
+ * only creates a hole in the zone. So in this case, we need not
+ * change the zone. But perhaps, the zone has only hole data. Thus
+ * it check the zone has only hole or not.
+ */
+ pfn = zone_start_pfn;
+ for (; pfn < zone_end_pfn; pfn += PAGES_PER_SECTION) {
+ ms = __pfn_to_section(pfn);
+
+ if (unlikely(!valid_section(ms)))
+ continue;
+
+ if (page_zone(pfn_to_page(pfn)) != zone)
+ continue;
+
+ /* If the section is current section, it continues the loop */
+ if (start_pfn == pfn)
+ continue;
+
+ /* If we find valid section, we have nothing to do */
+ zone_span_writeunlock(zone);
+ return;
+ }
+
+ /* The zone has no valid section */
+ zone->zone_start_pfn = 0;
+ zone->spanned_pages = 0;
+ zone_span_writeunlock(zone);
+}
+
+static void shrink_pgdat_span(struct pglist_data *pgdat,
+ unsigned long start_pfn, unsigned long end_pfn)
+{
+ unsigned long pgdat_start_pfn = pgdat->node_start_pfn;
+ unsigned long pgdat_end_pfn =
+ pgdat->node_start_pfn + pgdat->node_spanned_pages;
+ unsigned long pfn;
+ struct mem_section *ms;
+ int nid = pgdat->node_id;
+
+ if (pgdat_start_pfn == start_pfn) {
+ /*
+ * If the section is smallest section in the pgdat, it need
+ * shrink pgdat->node_start_pfn and pgdat->node_spanned_pages.
+ * In this case, we find second smallest valid mem_section
+ * for shrinking zone.
+ */
+ pfn = find_smallest_section_pfn(nid, NULL, end_pfn,
+ pgdat_end_pfn);
+ if (pfn) {
+ pgdat->node_start_pfn = pfn;
+ pgdat->node_spanned_pages = pgdat_end_pfn - pfn;
+ }
+ } else if (pgdat_end_pfn == end_pfn) {
+ /*
+ * If the section is biggest section in the pgdat, it need
+ * shrink pgdat->node_spanned_pages.
+ * In this case, we find second biggest valid mem_section for
+ * shrinking zone.
+ */
+ pfn = find_biggest_section_pfn(nid, NULL, pgdat_start_pfn,
+ start_pfn);
+ if (pfn)
+ pgdat->node_spanned_pages = pfn - pgdat_start_pfn + 1;
+ }
+
+ /*
+ * If the section is not biggest or smallest mem_section in the pgdat,
+ * it only creates a hole in the pgdat. So in this case, we need not
+ * change the pgdat.
+ * But perhaps, the pgdat has only hole data. Thus it check the pgdat
+ * has only hole or not.
+ */
+ pfn = pgdat_start_pfn;
+ for (; pfn < pgdat_end_pfn; pfn += PAGES_PER_SECTION) {
+ ms = __pfn_to_section(pfn);
+
+ if (unlikely(!valid_section(ms)))
+ continue;
+
+ if (pfn_to_nid(pfn) != nid)
+ continue;
+
+ /* If the section is current section, it continues the loop */
+ if (start_pfn == pfn)
+ continue;
+
+ /* If we find valid section, we have nothing to do */
+ return;
+ }
+
+ /* The pgdat has no valid section */
+ pgdat->node_start_pfn = 0;
+ pgdat->node_spanned_pages = 0;
+}
+
+static void __remove_zone(struct zone *zone, unsigned long start_pfn)
+{
+ struct pglist_data *pgdat = zone->zone_pgdat;
+ int nr_pages = PAGES_PER_SECTION;
+ int zone_type;
+ unsigned long flags;
+
+ zone_type = zone - pgdat->node_zones;
+
+ pgdat_resize_lock(zone->zone_pgdat, &flags);
+ shrink_zone_span(zone, start_pfn, start_pfn + nr_pages);
+ shrink_pgdat_span(pgdat, start_pfn, start_pfn + nr_pages);
+ pgdat_resize_unlock(zone->zone_pgdat, &flags);
+}
+
static int __remove_section(struct zone *zone, struct mem_section *ms)
{
+ unsigned long start_pfn;
+ int scn_nr;
int ret = -EINVAL;
if (!valid_section(ms))
@@ -441,6 +644,10 @@ static int __remove_section(struct zone *zone, struct mem_section *ms)
if (ret)
return ret;
+ scn_nr = __section_nr(ms);
+ start_pfn = section_nr_to_pfn(scn_nr);
+ __remove_zone(zone, start_pfn);
+
sparse_remove_one_section(zone, ms);
return 0;
}
--
1.7.1
^ permalink raw reply related
* [PATCH v5 13/14] memory-hotplug: remove sysfs file of node
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
In-Reply-To: <1356350964-13437-1-git-send-email-tangchen@cn.fujitsu.com>
This patch introduces a new function try_offline_node() to
remove sysfs file of node when all memory sections of this
node are removed. If some memory sections of this node are
not removed, this function does nothing.
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
---
drivers/acpi/acpi_memhotplug.c | 8 ++++-
include/linux/memory_hotplug.h | 2 +-
mm/memory_hotplug.c | 58 ++++++++++++++++++++++++++++++++++++++-
3 files changed, 63 insertions(+), 5 deletions(-)
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index eb30e5a..9c53cc6 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -295,9 +295,11 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
{
- int result = 0;
+ int result = 0, nid;
struct acpi_memory_info *info, *n;
+ nid = acpi_get_node(mem_device->device->handle);
+
list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
if (info->failed)
/* The kernel does not use this memory block */
@@ -310,7 +312,9 @@ static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
*/
return -EBUSY;
- result = remove_memory(info->start_addr, info->length);
+ if (nid < 0)
+ nid = memory_add_physaddr_to_nid(info->start_addr);
+ result = remove_memory(nid, info->start_addr, info->length);
if (result)
return result;
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 2441f36..f60e728 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -242,7 +242,7 @@ extern int arch_add_memory(int nid, u64 start, u64 size);
extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages);
extern int offline_memory_block(struct memory_block *mem);
extern bool is_memblock_offlined(struct memory_block *mem);
-extern int remove_memory(u64 start, u64 size);
+extern int remove_memory(int nid, u64 start, u64 size);
extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
int nr_pages);
extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index a1b0632..f8a1d2f 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -29,6 +29,7 @@
#include <linux/suspend.h>
#include <linux/mm_inline.h>
#include <linux/firmware-map.h>
+#include <linux/stop_machine.h>
#include <asm/tlbflush.h>
@@ -1659,7 +1660,58 @@ static int is_memblock_offlined_cb(struct memory_block *mem, void *arg)
return ret;
}
-int __ref remove_memory(u64 start, u64 size)
+static int check_cpu_on_node(void *data)
+{
+ struct pglist_data *pgdat = data;
+ int cpu;
+
+ for_each_present_cpu(cpu) {
+ if (cpu_to_node(cpu) == pgdat->node_id)
+ /*
+ * the cpu on this node isn't removed, and we can't
+ * offline this node.
+ */
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+/* offline the node if all memory sections of this node are removed */
+static void try_offline_node(int nid)
+{
+ unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn;
+ unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages;
+ unsigned long pfn;
+
+ for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+ unsigned long section_nr = pfn_to_section_nr(pfn);
+
+ if (!present_section_nr(section_nr))
+ continue;
+
+ if (pfn_to_nid(pfn) != nid)
+ continue;
+
+ /*
+ * some memory sections of this node are not removed, and we
+ * can't offline node now.
+ */
+ return;
+ }
+
+ if (stop_machine(check_cpu_on_node, NODE_DATA(nid), NULL))
+ return;
+
+ /*
+ * all memory/cpu of this node are removed, we can offline this
+ * node now.
+ */
+ node_set_offline(nid);
+ unregister_one_node(nid);
+}
+
+int __ref remove_memory(int nid, u64 start, u64 size)
{
unsigned long start_pfn, end_pfn;
int ret = 0;
@@ -1706,6 +1758,8 @@ repeat:
arch_remove_memory(start, size);
+ try_offline_node(nid);
+
unlock_memory_hotplug();
return 0;
@@ -1715,7 +1769,7 @@ int offline_pages(unsigned long start_pfn, unsigned long nr_pages)
{
return -EINVAL;
}
-int remove_memory(u64 start, u64 size)
+int remove_memory(int nid, u64 start, u64 size)
{
return -EINVAL;
}
--
1.7.1
^ permalink raw reply related
* [PATCH v5 11/14] memory-hotplug: Integrated __remove_section() of CONFIG_SPARSEMEM_VMEMMAP.
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
In-Reply-To: <1356350964-13437-1-git-send-email-tangchen@cn.fujitsu.com>
Currently __remove_section for SPARSEMEM_VMEMMAP does nothing. But even if
we use SPARSEMEM_VMEMMAP, we can unregister the memory_section.
Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
---
mm/memory_hotplug.c | 11 -----------
1 files changed, 0 insertions(+), 11 deletions(-)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index c12bd55..71cb656 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -430,16 +430,6 @@ static int __meminit __add_section(int nid, struct zone *zone,
return register_new_memory(nid, __pfn_to_section(phys_start_pfn));
}
-#ifdef CONFIG_SPARSEMEM_VMEMMAP
-static int __remove_section(struct zone *zone, struct mem_section *ms)
-{
- /*
- * XXX: Freeing memmap with vmemmap is not implement yet.
- * This should be removed later.
- */
- return -EBUSY;
-}
-#else
static int __remove_section(struct zone *zone, struct mem_section *ms)
{
int ret = -EINVAL;
@@ -454,7 +444,6 @@ static int __remove_section(struct zone *zone, struct mem_section *ms)
sparse_remove_one_section(zone, ms);
return 0;
}
-#endif
/*
* Reasonably generic function for adding memory. It is
--
1.7.1
^ permalink raw reply related
* [PATCH v5 14/14] memory-hotplug: free node_data when a node is offlined
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
In-Reply-To: <1356350964-13437-1-git-send-email-tangchen@cn.fujitsu.com>
From: Wen Congyang <wency@cn.fujitsu.com>
We call hotadd_new_pgdat() to allocate memory to store node_data. So we
should free it when removing a node.
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
---
mm/memory_hotplug.c | 20 +++++++++++++++++++-
1 files changed, 19 insertions(+), 1 deletions(-)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index f8a1d2f..447fa24 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1680,9 +1680,12 @@ static int check_cpu_on_node(void *data)
/* offline the node if all memory sections of this node are removed */
static void try_offline_node(int nid)
{
+ pg_data_t *pgdat = NODE_DATA(nid);
unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn;
- unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages;
+ unsigned long end_pfn = start_pfn + pgdat->node_spanned_pages;
unsigned long pfn;
+ struct page *pgdat_page = virt_to_page(pgdat);
+ int i;
for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
unsigned long section_nr = pfn_to_section_nr(pfn);
@@ -1709,6 +1712,21 @@ static void try_offline_node(int nid)
*/
node_set_offline(nid);
unregister_one_node(nid);
+
+ if (!PageSlab(pgdat_page) && !PageCompound(pgdat_page))
+ /* node data is allocated from boot memory */
+ return;
+
+ /* free waittable in each zone */
+ for (i = 0; i < MAX_NR_ZONES; i++) {
+ struct zone *zone = pgdat->node_zones + i;
+
+ if (zone->wait_table)
+ vfree(zone->wait_table);
+ }
+
+ arch_refresh_nodedata(nid, NULL);
+ arch_free_nodedata(pgdat);
}
int __ref remove_memory(int nid, u64 start, u64 size)
--
1.7.1
^ permalink raw reply related
* [PATCH v5 08/14] memory-hotplug: Common APIs to support page tables hot-remove
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
In-Reply-To: <1356350964-13437-1-git-send-email-tangchen@cn.fujitsu.com>
From: Wen Congyang <wency@cn.fujitsu.com>
When memory is removed, the corresponding pagetables should alse be removed.
This patch introduces some common APIs to support vmemmap pagetable and x86_64
architecture pagetable removing.
All pages of virtual mapping in removed memory cannot be freedi if some pages
used as PGD/PUD includes not only removed memory but also other memory. So the
patch uses the following way to check whether page can be freed or not.
1. When removing memory, the page structs of the revmoved memory are filled
with 0FD.
2. All page structs are filled with 0xFD on PT/PMD, PT/PMD can be cleared.
In this case, the page used as PT/PMD can be freed.
Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Signed-off-by: Jianguo Wu <wujianguo@huawei.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
---
arch/x86/include/asm/pgtable_types.h | 1 +
arch/x86/mm/init_64.c | 297 ++++++++++++++++++++++++++++++++++
arch/x86/mm/pageattr.c | 47 +++---
include/linux/bootmem.h | 1 +
4 files changed, 324 insertions(+), 22 deletions(-)
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index 3c32db8..4b6fd2a 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -352,6 +352,7 @@ static inline void update_page_count(int level, unsigned long pages) { }
* as a pte too.
*/
extern pte_t *lookup_address(unsigned long address, unsigned int *level);
+extern int __split_large_page(pte_t *kpte, unsigned long address, pte_t *pbase);
#endif /* !__ASSEMBLY__ */
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index aeaa27e..b30df3c 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -682,6 +682,303 @@ int arch_add_memory(int nid, u64 start, u64 size)
}
EXPORT_SYMBOL_GPL(arch_add_memory);
+#define PAGE_INUSE 0xFD
+
+static void __meminit free_pagetable(struct page *page, int order)
+{
+ struct zone *zone;
+ bool bootmem = false;
+ unsigned long magic;
+
+ /* bootmem page has reserved flag */
+ if (PageReserved(page)) {
+ __ClearPageReserved(page);
+ bootmem = true;
+
+ magic = (unsigned long)page->lru.next;
+ if (magic == SECTION_INFO || magic == MIX_SECTION_INFO)
+ put_page_bootmem(page);
+ else
+ __free_pages_bootmem(page, order);
+ } else
+ free_pages((unsigned long)page_address(page), order);
+
+ /*
+ * SECTION_INFO pages and MIX_SECTION_INFO pages
+ * are all allocated by bootmem.
+ */
+ if (bootmem) {
+ zone = page_zone(page);
+ zone_span_writelock(zone);
+ zone->present_pages++;
+ zone_span_writeunlock(zone);
+ totalram_pages++;
+ }
+}
+
+static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd)
+{
+ pte_t *pte;
+ int i;
+
+ for (i = 0; i < PTRS_PER_PTE; i++) {
+ pte = pte_start + i;
+ if (pte_val(*pte))
+ return;
+ }
+
+ /* free a pte talbe */
+ free_pagetable(pmd_page(*pmd), 0);
+ spin_lock(&init_mm.page_table_lock);
+ pmd_clear(pmd);
+ spin_unlock(&init_mm.page_table_lock);
+}
+
+static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud)
+{
+ pmd_t *pmd;
+ int i;
+
+ for (i = 0; i < PTRS_PER_PMD; i++) {
+ pmd = pmd_start + i;
+ if (pmd_val(*pmd))
+ return;
+ }
+
+ /* free a pmd talbe */
+ free_pagetable(pud_page(*pud), 0);
+ spin_lock(&init_mm.page_table_lock);
+ pud_clear(pud);
+ spin_unlock(&init_mm.page_table_lock);
+}
+
+/* Return true if pgd is changed, otherwise return false. */
+static bool __meminit free_pud_table(pud_t *pud_start, pgd_t *pgd)
+{
+ pud_t *pud;
+ int i;
+
+ for (i = 0; i < PTRS_PER_PUD; i++) {
+ pud = pud_start + i;
+ if (pud_val(*pud))
+ return false;
+ }
+
+ /* free a pud table */
+ free_pagetable(pgd_page(*pgd), 0);
+ spin_lock(&init_mm.page_table_lock);
+ pgd_clear(pgd);
+ spin_unlock(&init_mm.page_table_lock);
+
+ return true;
+}
+
+static void __meminit
+remove_pte_table(pte_t *pte_start, unsigned long addr, unsigned long end,
+ bool direct)
+{
+ unsigned long next, pages = 0;
+ pte_t *pte;
+ void *page_addr;
+ phys_addr_t phys_addr;
+
+ pte = pte_start + pte_index(addr);
+ for (; addr < end; addr = next, pte++) {
+ next = (addr + PAGE_SIZE) & PAGE_MASK;
+ if (next > end)
+ next = end;
+
+ if (!pte_present(*pte))
+ continue;
+
+ /*
+ * We mapped [0,1G) memory as identity mapping when
+ * initializing, in arch/x86/kernel/head_64.S. These
+ * pagetables cannot be removed.
+ */
+ phys_addr = pte_val(*pte) + (addr & PAGE_MASK);
+ if (phys_addr < (phys_addr_t)0x40000000)
+ return;
+
+ if (IS_ALIGNED(addr, PAGE_SIZE) &&
+ IS_ALIGNED(next, PAGE_SIZE)) {
+ if (!direct) {
+ free_pagetable(pte_page(*pte), 0);
+ pages++;
+ }
+
+ spin_lock(&init_mm.page_table_lock);
+ pte_clear(&init_mm, addr, pte);
+ spin_unlock(&init_mm.page_table_lock);
+ } else {
+ /*
+ * If we are not removing the whole page, it means
+ * other ptes in this page are being used and we canot
+ * remove them. So fill the unused ptes with 0xFD, and
+ * remove the page when it is wholly filled with 0xFD.
+ */
+ memset((void *)addr, PAGE_INUSE, next - addr);
+ page_addr = page_address(pte_page(*pte));
+
+ if (!memchr_inv(page_addr, PAGE_INUSE, PAGE_SIZE)) {
+ free_pagetable(pte_page(*pte), 0);
+ pages++;
+
+ spin_lock(&init_mm.page_table_lock);
+ pte_clear(&init_mm, addr, pte);
+ spin_unlock(&init_mm.page_table_lock);
+ }
+ }
+ }
+
+ /* Call free_pte_table() in remove_pmd_table(). */
+ flush_tlb_all();
+ if (direct)
+ update_page_count(PG_LEVEL_4K, -pages);
+}
+
+static void __meminit
+remove_pmd_table(pmd_t *pmd_start, unsigned long addr, unsigned long end,
+ bool direct)
+{
+ unsigned long pte_phys, next, pages = 0;
+ pte_t *pte_base;
+ pmd_t *pmd;
+
+ pmd = pmd_start + pmd_index(addr);
+ for (; addr < end; addr = next, pmd++) {
+ next = pmd_addr_end(addr, end);
+
+ if (!pmd_present(*pmd))
+ continue;
+
+ if (pmd_large(*pmd)) {
+ if (IS_ALIGNED(addr, PMD_SIZE) &&
+ IS_ALIGNED(next, PMD_SIZE)) {
+ if (!direct) {
+ free_pagetable(pmd_page(*pmd),
+ get_order(PMD_SIZE));
+ pages++;
+ }
+
+ spin_lock(&init_mm.page_table_lock);
+ pmd_clear(pmd);
+ spin_unlock(&init_mm.page_table_lock);
+ continue;
+ }
+
+ /*
+ * We use 2M page, but we need to remove part of them,
+ * so split 2M page to 4K page.
+ */
+ pte_base = (pte_t *)alloc_low_page(&pte_phys);
+ BUG_ON(!pte_base);
+ __split_large_page((pte_t *)pmd, addr,
+ (pte_t *)pte_base);
+
+ spin_lock(&init_mm.page_table_lock);
+ pmd_populate_kernel(&init_mm, pmd, __va(pte_phys));
+ spin_unlock(&init_mm.page_table_lock);
+
+ flush_tlb_all();
+ }
+
+ pte_base = (pte_t *)map_low_page((pte_t *)pmd_page_vaddr(*pmd));
+ remove_pte_table(pte_base, addr, next, direct);
+ free_pte_table(pte_base, pmd);
+ unmap_low_page(pte_base);
+ }
+
+ /* Call free_pmd_table() in remove_pud_table(). */
+ if (direct)
+ update_page_count(PG_LEVEL_2M, -pages);
+}
+
+static void __meminit
+remove_pud_table(pud_t *pud_start, unsigned long addr, unsigned long end,
+ bool direct)
+{
+ unsigned long pmd_phys, next, pages = 0;
+ pmd_t *pmd_base;
+ pud_t *pud;
+
+ pud = pud_start + pud_index(addr);
+ for (; addr < end; addr = next, pud++) {
+ next = pud_addr_end(addr, end);
+
+ if (!pud_present(*pud))
+ continue;
+
+ if (pud_large(*pud)) {
+ if (IS_ALIGNED(addr, PUD_SIZE) &&
+ IS_ALIGNED(next, PUD_SIZE)) {
+ if (!direct) {
+ free_pagetable(pud_page(*pud),
+ get_order(PUD_SIZE));
+ pages++;
+ }
+
+ spin_lock(&init_mm.page_table_lock);
+ pud_clear(pud);
+ spin_unlock(&init_mm.page_table_lock);
+ continue;
+ }
+
+ /*
+ * We use 1G page, but we need to remove part of them,
+ * so split 1G page to 2M page.
+ */
+ pmd_base = (pmd_t *)alloc_low_page(&pmd_phys);
+ BUG_ON(!pmd_base);
+ __split_large_page((pte_t *)pud, addr,
+ (pte_t *)pmd_base);
+
+ spin_lock(&init_mm.page_table_lock);
+ pud_populate(&init_mm, pud, __va(pmd_phys));
+ spin_unlock(&init_mm.page_table_lock);
+
+ flush_tlb_all();
+ }
+
+ pmd_base = (pmd_t *)map_low_page((pmd_t *)pud_page_vaddr(*pud));
+ remove_pmd_table(pmd_base, addr, next, direct);
+ free_pmd_table(pmd_base, pud);
+ unmap_low_page(pmd_base);
+ }
+
+ if (direct)
+ update_page_count(PG_LEVEL_1G, -pages);
+}
+
+/* start and end are both virtual address. */
+static void __meminit
+remove_pagetable(unsigned long start, unsigned long end, bool direct)
+{
+ unsigned long next;
+ pgd_t *pgd;
+ pud_t *pud;
+ bool pgd_changed = false;
+
+ for (; start < end; start = next) {
+ pgd = pgd_offset_k(start);
+ if (!pgd_present(*pgd))
+ continue;
+
+ next = pgd_addr_end(start, end);
+
+ pud = (pud_t *)map_low_page((pud_t *)pgd_page_vaddr(*pgd));
+ remove_pud_table(pud, start, next, direct);
+ if (free_pud_table(pud, pgd))
+ pgd_changed = true;
+ unmap_low_page(pud);
+ }
+
+ if (pgd_changed)
+ sync_global_pgds(start, end - 1);
+
+ flush_tlb_all();
+}
+
#ifdef CONFIG_MEMORY_HOTREMOVE
int __ref arch_remove_memory(u64 start, u64 size)
{
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index a718e0d..7dcb6f9 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -501,21 +501,13 @@ out_unlock:
return do_split;
}
-static int split_large_page(pte_t *kpte, unsigned long address)
+int __split_large_page(pte_t *kpte, unsigned long address, pte_t *pbase)
{
unsigned long pfn, pfninc = 1;
unsigned int i, level;
- pte_t *pbase, *tmp;
+ pte_t *tmp;
pgprot_t ref_prot;
- struct page *base;
-
- if (!debug_pagealloc)
- spin_unlock(&cpa_lock);
- base = alloc_pages(GFP_KERNEL | __GFP_NOTRACK, 0);
- if (!debug_pagealloc)
- spin_lock(&cpa_lock);
- if (!base)
- return -ENOMEM;
+ struct page *base = virt_to_page(pbase);
spin_lock(&pgd_lock);
/*
@@ -523,10 +515,11 @@ static int split_large_page(pte_t *kpte, unsigned long address)
* up for us already:
*/
tmp = lookup_address(address, &level);
- if (tmp != kpte)
- goto out_unlock;
+ if (tmp != kpte) {
+ spin_unlock(&pgd_lock);
+ return 1;
+ }
- pbase = (pte_t *)page_address(base);
paravirt_alloc_pte(&init_mm, page_to_pfn(base));
ref_prot = pte_pgprot(pte_clrhuge(*kpte));
/*
@@ -579,17 +572,27 @@ static int split_large_page(pte_t *kpte, unsigned long address)
* going on.
*/
__flush_tlb_all();
+ spin_unlock(&pgd_lock);
- base = NULL;
+ return 0;
+}
-out_unlock:
- /*
- * If we dropped out via the lookup_address check under
- * pgd_lock then stick the page back into the pool:
- */
- if (base)
+static int split_large_page(pte_t *kpte, unsigned long address)
+{
+ pte_t *pbase;
+ struct page *base;
+
+ if (!debug_pagealloc)
+ spin_unlock(&cpa_lock);
+ base = alloc_pages(GFP_KERNEL | __GFP_NOTRACK, 0);
+ if (!debug_pagealloc)
+ spin_lock(&cpa_lock);
+ if (!base)
+ return -ENOMEM;
+
+ pbase = (pte_t *)page_address(base);
+ if (__split_large_page(kpte, address, pbase))
__free_page(base);
- spin_unlock(&pgd_lock);
return 0;
}
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index 3f778c2..190ff06 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -53,6 +53,7 @@ extern void free_bootmem_node(pg_data_t *pgdat,
unsigned long size);
extern void free_bootmem(unsigned long physaddr, unsigned long size);
extern void free_bootmem_late(unsigned long physaddr, unsigned long size);
+extern void __free_pages_bootmem(struct page *page, unsigned int order);
/*
* Flags for reserve_bootmem (also if CONFIG_HAVE_ARCH_BOOTMEM_NODE,
--
1.7.1
^ permalink raw reply related
* [PATCH v5 10/14] memory-hotplug: remove memmap of sparse-vmemmap
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
In-Reply-To: <1356350964-13437-1-git-send-email-tangchen@cn.fujitsu.com>
This patch introduces a new API vmemmap_free() to free and remove
vmemmap pagetables. Since pagetable implements are different, each
architecture has to provide its own version of vmemmap_free(), just
like vmemmap_populate().
Note: vmemmap_free() are not implemented for ia64, ppc, s390, and sparc.
Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Signed-off-by: Jianguo Wu <wujianguo@huawei.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
---
arch/arm64/mm/mmu.c | 3 +++
arch/ia64/mm/discontig.c | 4 ++++
arch/powerpc/mm/init_64.c | 4 ++++
arch/s390/mm/vmem.c | 4 ++++
arch/sparc/mm/init_64.c | 4 ++++
arch/x86/mm/init_64.c | 8 ++++++++
include/linux/mm.h | 1 +
mm/sparse.c | 3 ++-
8 files changed, 30 insertions(+), 1 deletions(-)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index a6885d8..9834886 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -392,4 +392,7 @@ int __meminit vmemmap_populate(struct page *start_page,
return 0;
}
#endif /* CONFIG_ARM64_64K_PAGES */
+void vmemmap_free(struct page *memmap, unsigned long nr_pages)
+{
+}
#endif /* CONFIG_SPARSEMEM_VMEMMAP */
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 33943db..882a0fd 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -823,6 +823,10 @@ int __meminit vmemmap_populate(struct page *start_page,
return vmemmap_populate_basepages(start_page, size, node);
}
+void vmemmap_free(struct page *memmap, unsigned long nr_pages)
+{
+}
+
void register_page_bootmem_memmap(unsigned long section_nr,
struct page *start_page, unsigned long size)
{
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 6466440..2969591 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -298,6 +298,10 @@ int __meminit vmemmap_populate(struct page *start_page,
return 0;
}
+void vmemmap_free(struct page *memmap, unsigned long nr_pages)
+{
+}
+
void register_page_bootmem_memmap(unsigned long section_nr,
struct page *start_page, unsigned long size)
{
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 2c14bc2..81e6ba3 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -272,6 +272,10 @@ out:
return ret;
}
+void vmemmap_free(struct page *memmap, unsigned long nr_pages)
+{
+}
+
void register_page_bootmem_memmap(unsigned long section_nr,
struct page *start_page, unsigned long size)
{
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 7e28c9e..9cd1ec0 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -2232,6 +2232,10 @@ void __meminit vmemmap_populate_print_last(void)
}
}
+void vmemmap_free(struct page *memmap, unsigned long nr_pages)
+{
+}
+
void register_page_bootmem_memmap(unsigned long section_nr,
struct page *start_page, unsigned long size)
{
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 4b160d8..029c0b9 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -1307,6 +1307,14 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node)
return 0;
}
+void __ref vmemmap_free(struct page *memmap, unsigned long nr_pages)
+{
+ unsigned long start = (unsigned long)memmap;
+ unsigned long end = (unsigned long)(memmap + nr_pages);
+
+ remove_pagetable(start, end, false);
+}
+
void register_page_bootmem_memmap(unsigned long section_nr,
struct page *start_page, unsigned long size)
{
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 1eca498..31d5e5d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1709,6 +1709,7 @@ int vmemmap_populate_basepages(struct page *start_page,
unsigned long pages, int node);
int vmemmap_populate(struct page *start_page, unsigned long pages, int node);
void vmemmap_populate_print_last(void);
+void vmemmap_free(struct page *memmap, unsigned long nr_pages);
void register_page_bootmem_memmap(unsigned long section_nr, struct page *map,
unsigned long size);
diff --git a/mm/sparse.c b/mm/sparse.c
index 05ca73a..cff9796 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -615,10 +615,11 @@ static inline struct page *kmalloc_section_memmap(unsigned long pnum, int nid,
}
static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
{
- return; /* XXX: Not implemented yet */
+ vmemmap_free(memmap, nr_pages);
}
static void free_map_bootmem(struct page *memmap, unsigned long nr_pages)
{
+ vmemmap_free(memmap, nr_pages);
}
#else
static struct page *__kmalloc_section_memmap(unsigned long nr_pages)
--
1.7.1
^ permalink raw reply related
* [PATCH v5 07/14] memory-hotplug: move pgdat_resize_lock into sparse_remove_one_section()
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
In-Reply-To: <1356350964-13437-1-git-send-email-tangchen@cn.fujitsu.com>
In __remove_section(), we locked pgdat_resize_lock when calling
sparse_remove_one_section(). This lock will disable irq. But we don't need
to lock the whole function. If we do some work to free pagetables in
free_section_usemap(), we need to call flush_tlb_all(), which need
irq enabled. Otherwise the WARN_ON_ONCE() in smp_call_function_many()
will be triggered.
Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
---
mm/memory_hotplug.c | 4 ----
mm/sparse.c | 5 ++++-
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 34c656b..c12bd55 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -442,8 +442,6 @@ static int __remove_section(struct zone *zone, struct mem_section *ms)
#else
static int __remove_section(struct zone *zone, struct mem_section *ms)
{
- unsigned long flags;
- struct pglist_data *pgdat = zone->zone_pgdat;
int ret = -EINVAL;
if (!valid_section(ms))
@@ -453,9 +451,7 @@ static int __remove_section(struct zone *zone, struct mem_section *ms)
if (ret)
return ret;
- pgdat_resize_lock(pgdat, &flags);
sparse_remove_one_section(zone, ms);
- pgdat_resize_unlock(pgdat, &flags);
return 0;
}
#endif
diff --git a/mm/sparse.c b/mm/sparse.c
index aadbb2a..05ca73a 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -796,8 +796,10 @@ static inline void clear_hwpoisoned_pages(struct page *memmap, int nr_pages)
void sparse_remove_one_section(struct zone *zone, struct mem_section *ms)
{
struct page *memmap = NULL;
- unsigned long *usemap = NULL;
+ unsigned long *usemap = NULL, flags;
+ struct pglist_data *pgdat = zone->zone_pgdat;
+ pgdat_resize_lock(pgdat, &flags);
if (ms->section_mem_map) {
usemap = ms->pageblock_flags;
memmap = sparse_decode_mem_map(ms->section_mem_map,
@@ -805,6 +807,7 @@ void sparse_remove_one_section(struct zone *zone, struct mem_section *ms)
ms->section_mem_map = 0;
ms->pageblock_flags = NULL;
}
+ pgdat_resize_unlock(pgdat, &flags);
clear_hwpoisoned_pages(memmap, PAGES_PER_SECTION);
free_section_usemap(memmap, usemap);
--
1.7.1
^ permalink raw reply related
* [PATCH v5 06/14] memory-hotplug: implement register_page_bootmem_info_section of sparse-vmemmap
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
In-Reply-To: <1356350964-13437-1-git-send-email-tangchen@cn.fujitsu.com>
From: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
For removing memmap region of sparse-vmemmap which is allocated bootmem,
memmap region of sparse-vmemmap needs to be registered by get_page_bootmem().
So the patch searches pages of virtual mapping and registers the pages by
get_page_bootmem().
Note: register_page_bootmem_memmap() is not implemented for ia64, ppc, s390,
and sparc.
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
---
arch/ia64/mm/discontig.c | 6 ++++
arch/powerpc/mm/init_64.c | 6 ++++
arch/s390/mm/vmem.c | 6 ++++
arch/sparc/mm/init_64.c | 6 ++++
arch/x86/mm/init_64.c | 52 ++++++++++++++++++++++++++++++++++++++++
include/linux/memory_hotplug.h | 11 +-------
include/linux/mm.h | 3 +-
mm/memory_hotplug.c | 33 ++++++++++++++++++++++---
8 files changed, 109 insertions(+), 14 deletions(-)
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index c641333..33943db 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -822,4 +822,10 @@ int __meminit vmemmap_populate(struct page *start_page,
{
return vmemmap_populate_basepages(start_page, size, node);
}
+
+void register_page_bootmem_memmap(unsigned long section_nr,
+ struct page *start_page, unsigned long size)
+{
+ /* TODO */
+}
#endif
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 95a4529..6466440 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -297,5 +297,11 @@ int __meminit vmemmap_populate(struct page *start_page,
return 0;
}
+
+void register_page_bootmem_memmap(unsigned long section_nr,
+ struct page *start_page, unsigned long size)
+{
+ /* TODO */
+}
#endif /* CONFIG_SPARSEMEM_VMEMMAP */
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 6ed1426..2c14bc2 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -272,6 +272,12 @@ out:
return ret;
}
+void register_page_bootmem_memmap(unsigned long section_nr,
+ struct page *start_page, unsigned long size)
+{
+ /* TODO */
+}
+
/*
* Add memory segment to the segment list if it doesn't overlap with
* an already present segment.
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 85be1ca..7e28c9e 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -2231,6 +2231,12 @@ void __meminit vmemmap_populate_print_last(void)
node_start = 0;
}
}
+
+void register_page_bootmem_memmap(unsigned long section_nr,
+ struct page *start_page, unsigned long size)
+{
+ /* TODO */
+}
#endif /* CONFIG_SPARSEMEM_VMEMMAP */
static void prot_init_common(unsigned long page_none,
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index f78509c..aeaa27e 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -1000,6 +1000,58 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node)
return 0;
}
+void register_page_bootmem_memmap(unsigned long section_nr,
+ struct page *start_page, unsigned long size)
+{
+ unsigned long addr = (unsigned long)start_page;
+ unsigned long end = (unsigned long)(start_page + size);
+ unsigned long next;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+
+ for (; addr < end; addr = next) {
+ pte_t *pte = NULL;
+
+ pgd = pgd_offset_k(addr);
+ if (pgd_none(*pgd)) {
+ next = (addr + PAGE_SIZE) & PAGE_MASK;
+ continue;
+ }
+ get_page_bootmem(section_nr, pgd_page(*pgd), MIX_SECTION_INFO);
+
+ pud = pud_offset(pgd, addr);
+ if (pud_none(*pud)) {
+ next = (addr + PAGE_SIZE) & PAGE_MASK;
+ continue;
+ }
+ get_page_bootmem(section_nr, pud_page(*pud), MIX_SECTION_INFO);
+
+ if (!cpu_has_pse) {
+ next = (addr + PAGE_SIZE) & PAGE_MASK;
+ pmd = pmd_offset(pud, addr);
+ if (pmd_none(*pmd))
+ continue;
+ get_page_bootmem(section_nr, pmd_page(*pmd),
+ MIX_SECTION_INFO);
+
+ pte = pte_offset_kernel(pmd, addr);
+ if (pte_none(*pte))
+ continue;
+ get_page_bootmem(section_nr, pte_page(*pte),
+ SECTION_INFO);
+ } else {
+ next = pmd_addr_end(addr, end);
+
+ pmd = pmd_offset(pud, addr);
+ if (pmd_none(*pmd))
+ continue;
+ get_page_bootmem(section_nr, pmd_page(*pmd),
+ SECTION_INFO);
+ }
+ }
+}
+
void __meminit vmemmap_populate_print_last(void)
{
if (p_start) {
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 31a563b..2441f36 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -174,17 +174,10 @@ static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
#endif /* CONFIG_NUMA */
#endif /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */
-#ifdef CONFIG_SPARSEMEM_VMEMMAP
-static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
-{
-}
-static inline void put_page_bootmem(struct page *page)
-{
-}
-#else
extern void register_page_bootmem_info_node(struct pglist_data *pgdat);
extern void put_page_bootmem(struct page *page);
-#endif
+extern void get_page_bootmem(unsigned long ingo, struct page *page,
+ unsigned long type);
/*
* Lock for memory hotplug guarantees 1) all callbacks for memory hotplug
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 6320407..1eca498 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1709,7 +1709,8 @@ int vmemmap_populate_basepages(struct page *start_page,
unsigned long pages, int node);
int vmemmap_populate(struct page *start_page, unsigned long pages, int node);
void vmemmap_populate_print_last(void);
-
+void register_page_bootmem_memmap(unsigned long section_nr, struct page *map,
+ unsigned long size);
enum mf_flags {
MF_COUNT_INCREASED = 1 << 0,
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 2c5d734..34c656b 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -91,9 +91,8 @@ static void release_memory_resource(struct resource *res)
}
#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
-#ifndef CONFIG_SPARSEMEM_VMEMMAP
-static void get_page_bootmem(unsigned long info, struct page *page,
- unsigned long type)
+void get_page_bootmem(unsigned long info, struct page *page,
+ unsigned long type)
{
page->lru.next = (struct list_head *) type;
SetPagePrivate(page);
@@ -128,6 +127,7 @@ void __ref put_page_bootmem(struct page *page)
}
+#ifndef CONFIG_SPARSEMEM_VMEMMAP
static void register_page_bootmem_info_section(unsigned long start_pfn)
{
unsigned long *usemap, mapsize, section_nr, i;
@@ -161,6 +161,32 @@ static void register_page_bootmem_info_section(unsigned long start_pfn)
get_page_bootmem(section_nr, page, MIX_SECTION_INFO);
}
+#else
+static void register_page_bootmem_info_section(unsigned long start_pfn)
+{
+ unsigned long *usemap, mapsize, section_nr, i;
+ struct mem_section *ms;
+ struct page *page, *memmap;
+
+ if (!pfn_valid(start_pfn))
+ return;
+
+ section_nr = pfn_to_section_nr(start_pfn);
+ ms = __nr_to_section(section_nr);
+
+ memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr);
+
+ register_page_bootmem_memmap(section_nr, memmap, PAGES_PER_SECTION);
+
+ usemap = __nr_to_section(section_nr)->pageblock_flags;
+ page = virt_to_page(usemap);
+
+ mapsize = PAGE_ALIGN(usemap_size()) >> PAGE_SHIFT;
+
+ for (i = 0; i < mapsize; i++, page++)
+ get_page_bootmem(section_nr, page, MIX_SECTION_INFO);
+}
+#endif
void register_page_bootmem_info_node(struct pglist_data *pgdat)
{
@@ -203,7 +229,6 @@ void register_page_bootmem_info_node(struct pglist_data *pgdat)
register_page_bootmem_info_section(pfn);
}
}
-#endif /* !CONFIG_SPARSEMEM_VMEMMAP */
static void grow_zone_span(struct zone *zone, unsigned long start_pfn,
unsigned long end_pfn)
--
1.7.1
^ permalink raw reply related
* [PATCH v5 05/14] memory-hotplug: introduce new function arch_remove_memory() for removing page table depends on architecture
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
In-Reply-To: <1356350964-13437-1-git-send-email-tangchen@cn.fujitsu.com>
From: Wen Congyang <wency@cn.fujitsu.com>
For removing memory, we need to remove page table. But it depends
on architecture. So the patch introduce arch_remove_memory() for
removing page table. Now it only calls __remove_pages().
Note: __remove_pages() for some archtecuture is not implemented
(I don't know how to implement it for s390).
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
---
arch/ia64/mm/init.c | 18 ++++++++++++++++++
arch/powerpc/mm/mem.c | 12 ++++++++++++
arch/s390/mm/init.c | 12 ++++++++++++
arch/sh/mm/init.c | 17 +++++++++++++++++
arch/tile/mm/init.c | 8 ++++++++
arch/x86/mm/init_32.c | 12 ++++++++++++
arch/x86/mm/init_64.c | 15 +++++++++++++++
include/linux/memory_hotplug.h | 1 +
mm/memory_hotplug.c | 2 ++
9 files changed, 97 insertions(+), 0 deletions(-)
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 082e383..e333822 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -689,6 +689,24 @@ int arch_add_memory(int nid, u64 start, u64 size)
return ret;
}
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+int arch_remove_memory(u64 start, u64 size)
+{
+ unsigned long start_pfn = start >> PAGE_SHIFT;
+ unsigned long nr_pages = size >> PAGE_SHIFT;
+ struct zone *zone;
+ int ret;
+
+ zone = page_zone(pfn_to_page(start_pfn));
+ ret = __remove_pages(zone, start_pfn, nr_pages);
+ if (ret)
+ pr_warn("%s: Problem encountered in __remove_pages() as"
+ " ret=%d\n", __func__, ret);
+
+ return ret;
+}
+#endif
#endif
/*
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 0dba506..09c6451 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -133,6 +133,18 @@ int arch_add_memory(int nid, u64 start, u64 size)
return __add_pages(nid, zone, start_pfn, nr_pages);
}
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+int arch_remove_memory(u64 start, u64 size)
+{
+ unsigned long start_pfn = start >> PAGE_SHIFT;
+ unsigned long nr_pages = size >> PAGE_SHIFT;
+ struct zone *zone;
+
+ zone = page_zone(pfn_to_page(start_pfn));
+ return __remove_pages(zone, start_pfn, nr_pages);
+}
+#endif
#endif /* CONFIG_MEMORY_HOTPLUG */
/*
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index ae672f4..49ce6bb 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -228,4 +228,16 @@ int arch_add_memory(int nid, u64 start, u64 size)
vmem_remove_mapping(start, size);
return rc;
}
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+int arch_remove_memory(u64 start, u64 size)
+{
+ /*
+ * There is no hardware or firmware interface which could trigger a
+ * hot memory remove on s390. So there is nothing that needs to be
+ * implemented.
+ */
+ return -EBUSY;
+}
+#endif
#endif /* CONFIG_MEMORY_HOTPLUG */
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 82cc576..1057940 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -558,4 +558,21 @@ int memory_add_physaddr_to_nid(u64 addr)
EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
#endif
+#ifdef CONFIG_MEMORY_HOTREMOVE
+int arch_remove_memory(u64 start, u64 size)
+{
+ unsigned long start_pfn = start >> PAGE_SHIFT;
+ unsigned long nr_pages = size >> PAGE_SHIFT;
+ struct zone *zone;
+ int ret;
+
+ zone = page_zone(pfn_to_page(start_pfn));
+ ret = __remove_pages(zone, start_pfn, nr_pages);
+ if (unlikely(ret))
+ pr_warn("%s: Failed, __remove_pages() == %d\n", __func__,
+ ret);
+
+ return ret;
+}
+#endif
#endif /* CONFIG_MEMORY_HOTPLUG */
diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c
index ef29d6c..2749515 100644
--- a/arch/tile/mm/init.c
+++ b/arch/tile/mm/init.c
@@ -935,6 +935,14 @@ int remove_memory(u64 start, u64 size)
{
return -EINVAL;
}
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+int arch_remove_memory(u64 start, u64 size)
+{
+ /* TODO */
+ return -EBUSY;
+}
+#endif
#endif
struct kmem_cache *pgd_cache;
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 745d66b..3166e78 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -836,6 +836,18 @@ int arch_add_memory(int nid, u64 start, u64 size)
return __add_pages(nid, zone, start_pfn, nr_pages);
}
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+int arch_remove_memory(u64 start, u64 size)
+{
+ unsigned long start_pfn = start >> PAGE_SHIFT;
+ unsigned long nr_pages = size >> PAGE_SHIFT;
+ struct zone *zone;
+
+ zone = page_zone(pfn_to_page(start_pfn));
+ return __remove_pages(zone, start_pfn, nr_pages);
+}
+#endif
#endif
/*
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index e779e0b..f78509c 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -682,6 +682,21 @@ int arch_add_memory(int nid, u64 start, u64 size)
}
EXPORT_SYMBOL_GPL(arch_add_memory);
+#ifdef CONFIG_MEMORY_HOTREMOVE
+int __ref arch_remove_memory(u64 start, u64 size)
+{
+ unsigned long start_pfn = start >> PAGE_SHIFT;
+ unsigned long nr_pages = size >> PAGE_SHIFT;
+ struct zone *zone;
+ int ret;
+
+ zone = page_zone(pfn_to_page(start_pfn));
+ ret = __remove_pages(zone, start_pfn, nr_pages);
+ WARN_ON_ONCE(ret);
+
+ return ret;
+}
+#endif
#endif /* CONFIG_MEMORY_HOTPLUG */
static struct kcore_list kcore_vsyscall;
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 8dd0950..31a563b 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -96,6 +96,7 @@ extern void __online_page_free(struct page *page);
#ifdef CONFIG_MEMORY_HOTREMOVE
extern bool is_pageblock_removable_nolock(struct page *page);
+extern int arch_remove_memory(u64 start, u64 size);
#endif /* CONFIG_MEMORY_HOTREMOVE */
/* reasonably generic interface to expand the physical pages in a zone */
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 1f5b5bb..2c5d734 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1487,6 +1487,8 @@ repeat:
/* remove memmap entry */
firmware_map_remove(start, start + size, "System RAM");
+ arch_remove_memory(start, size);
+
unlock_memory_hotplug();
return 0;
--
1.7.1
^ permalink raw reply related
* [PATCH v5 09/14] memory-hotplug: remove page table of x86_64 architecture
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
In-Reply-To: <1356350964-13437-1-git-send-email-tangchen@cn.fujitsu.com>
This patch searches a page table about the removed memory, and clear
page table for x86_64 architecture.
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Jianguo Wu <wujianguo@huawei.com>
Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
---
arch/x86/mm/init_64.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index b30df3c..4b160d8 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -979,6 +979,15 @@ remove_pagetable(unsigned long start, unsigned long end, bool direct)
flush_tlb_all();
}
+void __meminit
+kernel_physical_mapping_remove(unsigned long start, unsigned long end)
+{
+ start = (unsigned long)__va(start);
+ end = (unsigned long)__va(end);
+
+ remove_pagetable(start, end, true);
+}
+
#ifdef CONFIG_MEMORY_HOTREMOVE
int __ref arch_remove_memory(u64 start, u64 size)
{
@@ -988,6 +997,7 @@ int __ref arch_remove_memory(u64 start, u64 size)
int ret;
zone = page_zone(pfn_to_page(start_pfn));
+ kernel_physical_mapping_remove(start, start + size);
ret = __remove_pages(zone, start_pfn, nr_pages);
WARN_ON_ONCE(ret);
--
1.7.1
^ permalink raw reply related
* [PATCH v5 03/14] memory-hotplug: remove redundant codes
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
In-Reply-To: <1356350964-13437-1-git-send-email-tangchen@cn.fujitsu.com>
From: Wen Congyang <wency@cn.fujitsu.com>
offlining memory blocks and checking whether memory blocks are offlined
are very similar. This patch introduces a new function to remove
redundant codes.
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
---
mm/memory_hotplug.c | 101 ++++++++++++++++++++++++++++-----------------------
1 files changed, 55 insertions(+), 46 deletions(-)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index d43d97b..dbb04d8 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1381,20 +1381,14 @@ int offline_pages(unsigned long start_pfn, unsigned long nr_pages)
return __offline_pages(start_pfn, start_pfn + nr_pages, 120 * HZ);
}
-int remove_memory(u64 start, u64 size)
+static int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn,
+ void *arg, int (*func)(struct memory_block *, void *))
{
struct memory_block *mem = NULL;
struct mem_section *section;
- unsigned long start_pfn, end_pfn;
unsigned long pfn, section_nr;
int ret;
- int return_on_error = 0;
- int retry = 0;
-
- start_pfn = PFN_DOWN(start);
- end_pfn = start_pfn + PFN_DOWN(size);
-repeat:
for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
section_nr = pfn_to_section_nr(pfn);
if (!present_section_nr(section_nr))
@@ -1411,22 +1405,61 @@ repeat:
if (!mem)
continue;
- ret = offline_memory_block(mem);
+ ret = func(mem, arg);
if (ret) {
- if (return_on_error) {
- kobject_put(&mem->dev.kobj);
- return ret;
- } else {
- retry = 1;
- }
+ kobject_put(&mem->dev.kobj);
+ return ret;
}
}
if (mem)
kobject_put(&mem->dev.kobj);
- if (retry) {
- return_on_error = 1;
+ return 0;
+}
+
+static int offline_memory_block_cb(struct memory_block *mem, void *arg)
+{
+ int *ret = arg;
+ int error = offline_memory_block(mem);
+
+ if (error != 0 && *ret == 0)
+ *ret = error;
+
+ return 0;
+}
+
+static int is_memblock_offlined_cb(struct memory_block *mem, void *arg)
+{
+ int ret = !is_memblock_offlined(mem);
+
+ if (unlikely(ret))
+ pr_warn("removing memory fails, because memory "
+ "[%#010llx-%#010llx] is onlined\n",
+ PFN_PHYS(section_nr_to_pfn(mem->start_section_nr)),
+ PFN_PHYS(section_nr_to_pfn(mem->end_section_nr + 1))-1);
+
+ return ret;
+}
+
+int remove_memory(u64 start, u64 size)
+{
+ unsigned long start_pfn, end_pfn;
+ int ret = 0;
+ int retry = 1;
+
+ start_pfn = PFN_DOWN(start);
+ end_pfn = start_pfn + PFN_DOWN(size);
+
+repeat:
+ walk_memory_range(start_pfn, end_pfn, &ret,
+ offline_memory_block_cb);
+ if (ret) {
+ if (!retry)
+ return ret;
+
+ retry = 0;
+ ret = 0;
goto repeat;
}
@@ -1444,37 +1477,13 @@ repeat:
* memory blocks are offlined.
*/
- for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
- section_nr = pfn_to_section_nr(pfn);
- if (!present_section_nr(section_nr))
- continue;
-
- section = __nr_to_section(section_nr);
- /* same memblock? */
- if (mem)
- if ((section_nr >= mem->start_section_nr) &&
- (section_nr <= mem->end_section_nr))
- continue;
-
- mem = find_memory_block_hinted(section, mem);
- if (!mem)
- continue;
-
- ret = is_memblock_offlined(mem);
- if (!ret) {
- pr_warn("removing memory fails, because memory "
- "[%#010llx-%#010llx] is onlined\n",
- PFN_PHYS(section_nr_to_pfn(mem->start_section_nr)),
- PFN_PHYS(section_nr_to_pfn(mem->end_section_nr + 1)) - 1);
-
- kobject_put(&mem->dev.kobj);
- unlock_memory_hotplug();
- return ret;
- }
+ ret = walk_memory_range(start_pfn, end_pfn, NULL,
+ is_memblock_offlined_cb);
+ if (ret) {
+ unlock_memory_hotplug();
+ return ret;
}
- if (mem)
- kobject_put(&mem->dev.kobj);
unlock_memory_hotplug();
return 0;
--
1.7.1
^ permalink raw reply related
* [PATCH v5 02/14] memory-hotplug: check whether all memory blocks are offlined or not when removing memory
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
In-Reply-To: <1356350964-13437-1-git-send-email-tangchen@cn.fujitsu.com>
From: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
We remove the memory like this:
1. lock memory hotplug
2. offline a memory block
3. unlock memory hotplug
4. repeat 1-3 to offline all memory blocks
5. lock memory hotplug
6. remove memory(TODO)
7. unlock memory hotplug
All memory blocks must be offlined before removing memory. But we don't hold
the lock in the whole operation. So we should check whether all memory blocks
are offlined before step6. Otherwise, kernel maybe panicked.
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
---
drivers/base/memory.c | 6 +++++
include/linux/memory_hotplug.h | 1 +
mm/memory_hotplug.c | 47 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 987604d..8300a18 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -693,6 +693,12 @@ int offline_memory_block(struct memory_block *mem)
return ret;
}
+/* return true if the memory block is offlined, otherwise, return false */
+bool is_memblock_offlined(struct memory_block *mem)
+{
+ return mem->state == MEM_OFFLINE;
+}
+
/*
* Initialize the sysfs support for memory devices...
*/
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 4a45c4e..8dd0950 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -247,6 +247,7 @@ extern int add_memory(int nid, u64 start, u64 size);
extern int arch_add_memory(int nid, u64 start, u64 size);
extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages);
extern int offline_memory_block(struct memory_block *mem);
+extern bool is_memblock_offlined(struct memory_block *mem);
extern int remove_memory(u64 start, u64 size);
extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
int nr_pages);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 62e04c9..d43d97b 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1430,6 +1430,53 @@ repeat:
goto repeat;
}
+ lock_memory_hotplug();
+
+ /*
+ * we have offlined all memory blocks like this:
+ * 1. lock memory hotplug
+ * 2. offline a memory block
+ * 3. unlock memory hotplug
+ *
+ * repeat step1-3 to offline the memory block. All memory blocks
+ * must be offlined before removing memory. But we don't hold the
+ * lock in the whole operation. So we should check whether all
+ * memory blocks are offlined.
+ */
+
+ for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+ section_nr = pfn_to_section_nr(pfn);
+ if (!present_section_nr(section_nr))
+ continue;
+
+ section = __nr_to_section(section_nr);
+ /* same memblock? */
+ if (mem)
+ if ((section_nr >= mem->start_section_nr) &&
+ (section_nr <= mem->end_section_nr))
+ continue;
+
+ mem = find_memory_block_hinted(section, mem);
+ if (!mem)
+ continue;
+
+ ret = is_memblock_offlined(mem);
+ if (!ret) {
+ pr_warn("removing memory fails, because memory "
+ "[%#010llx-%#010llx] is onlined\n",
+ PFN_PHYS(section_nr_to_pfn(mem->start_section_nr)),
+ PFN_PHYS(section_nr_to_pfn(mem->end_section_nr + 1)) - 1);
+
+ kobject_put(&mem->dev.kobj);
+ unlock_memory_hotplug();
+ return ret;
+ }
+ }
+
+ if (mem)
+ kobject_put(&mem->dev.kobj);
+ unlock_memory_hotplug();
+
return 0;
}
#else
--
1.7.1
^ permalink raw reply related
* [PATCH v5 01/14] memory-hotplug: try to offline the memory twice to avoid dependence
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
In-Reply-To: <1356350964-13437-1-git-send-email-tangchen@cn.fujitsu.com>
From: Wen Congyang <wency@cn.fujitsu.com>
memory can't be offlined when CONFIG_MEMCG is selected.
For example: there is a memory device on node 1. The address range
is [1G, 1.5G). You will find 4 new directories memory8, memory9, memory10,
and memory11 under the directory /sys/devices/system/memory/.
If CONFIG_MEMCG is selected, we will allocate memory to store page cgroup
when we online pages. When we online memory8, the memory stored page cgroup
is not provided by this memory device. But when we online memory9, the memory
stored page cgroup may be provided by memory8. So we can't offline memory8
now. We should offline the memory in the reversed order.
When the memory device is hotremoved, we will auto offline memory provided
by this memory device. But we don't know which memory is onlined first, so
offlining memory may fail. In such case, iterate twice to offline the memory.
1st iterate: offline every non primary memory block.
2nd iterate: offline primary (i.e. first added) memory block.
This idea is suggested by KOSAKI Motohiro.
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
---
mm/memory_hotplug.c | 16 ++++++++++++++--
1 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index d04ed87..62e04c9 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1388,10 +1388,13 @@ int remove_memory(u64 start, u64 size)
unsigned long start_pfn, end_pfn;
unsigned long pfn, section_nr;
int ret;
+ int return_on_error = 0;
+ int retry = 0;
start_pfn = PFN_DOWN(start);
end_pfn = start_pfn + PFN_DOWN(size);
+repeat:
for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
section_nr = pfn_to_section_nr(pfn);
if (!present_section_nr(section_nr))
@@ -1410,14 +1413,23 @@ int remove_memory(u64 start, u64 size)
ret = offline_memory_block(mem);
if (ret) {
- kobject_put(&mem->dev.kobj);
- return ret;
+ if (return_on_error) {
+ kobject_put(&mem->dev.kobj);
+ return ret;
+ } else {
+ retry = 1;
+ }
}
}
if (mem)
kobject_put(&mem->dev.kobj);
+ if (retry) {
+ return_on_error = 1;
+ goto repeat;
+ }
+
return 0;
}
#else
--
1.7.1
^ permalink raw reply related
* [PATCH v5 04/14] memory-hotplug: remove /sys/firmware/memmap/X sysfs
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
In-Reply-To: <1356350964-13437-1-git-send-email-tangchen@cn.fujitsu.com>
From: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
When (hot)adding memory into system, /sys/firmware/memmap/X/{end, start, type}
sysfs files are created. But there is no code to remove these files. The patch
implements the function to remove them.
Note: The code does not free firmware_map_entry which is allocated by bootmem.
So the patch makes memory leak. But I think the memory leak size is
very samll. And it does not affect the system.
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
---
drivers/firmware/memmap.c | 98 +++++++++++++++++++++++++++++++++++++++++-
include/linux/firmware-map.h | 6 +++
mm/memory_hotplug.c | 5 ++-
3 files changed, 106 insertions(+), 3 deletions(-)
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
index 90723e6..49be12a 100644
--- a/drivers/firmware/memmap.c
+++ b/drivers/firmware/memmap.c
@@ -21,6 +21,7 @@
#include <linux/types.h>
#include <linux/bootmem.h>
#include <linux/slab.h>
+#include <linux/mm.h>
/*
* Data types ------------------------------------------------------------------
@@ -41,6 +42,7 @@ struct firmware_map_entry {
const char *type; /* type of the memory range */
struct list_head list; /* entry for the linked list */
struct kobject kobj; /* kobject for each entry */
+ unsigned int bootmem:1; /* allocated from bootmem */
};
/*
@@ -79,7 +81,26 @@ static const struct sysfs_ops memmap_attr_ops = {
.show = memmap_attr_show,
};
+
+static inline struct firmware_map_entry *
+to_memmap_entry(struct kobject *kobj)
+{
+ return container_of(kobj, struct firmware_map_entry, kobj);
+}
+
+static void release_firmware_map_entry(struct kobject *kobj)
+{
+ struct firmware_map_entry *entry = to_memmap_entry(kobj);
+
+ if (entry->bootmem)
+ /* There is no way to free memory allocated from bootmem */
+ return;
+
+ kfree(entry);
+}
+
static struct kobj_type memmap_ktype = {
+ .release = release_firmware_map_entry,
.sysfs_ops = &memmap_attr_ops,
.default_attrs = def_attrs,
};
@@ -94,6 +115,7 @@ static struct kobj_type memmap_ktype = {
* in firmware initialisation code in one single thread of execution.
*/
static LIST_HEAD(map_entries);
+static DEFINE_SPINLOCK(map_entries_lock);
/**
* firmware_map_add_entry() - Does the real work to add a firmware memmap entry.
@@ -118,11 +140,25 @@ static int firmware_map_add_entry(u64 start, u64 end,
INIT_LIST_HEAD(&entry->list);
kobject_init(&entry->kobj, &memmap_ktype);
+ spin_lock(&map_entries_lock);
list_add_tail(&entry->list, &map_entries);
+ spin_unlock(&map_entries_lock);
return 0;
}
+/**
+ * firmware_map_remove_entry() - Does the real work to remove a firmware
+ * memmap entry.
+ * @entry: removed entry.
+ **/
+static inline void firmware_map_remove_entry(struct firmware_map_entry *entry)
+{
+ spin_lock(&map_entries_lock);
+ list_del(&entry->list);
+ spin_unlock(&map_entries_lock);
+}
+
/*
* Add memmap entry on sysfs
*/
@@ -144,6 +180,35 @@ static int add_sysfs_fw_map_entry(struct firmware_map_entry *entry)
return 0;
}
+/*
+ * Remove memmap entry on sysfs
+ */
+static inline void remove_sysfs_fw_map_entry(struct firmware_map_entry *entry)
+{
+ kobject_put(&entry->kobj);
+}
+
+/*
+ * Search memmap entry
+ */
+
+static struct firmware_map_entry * __meminit
+firmware_map_find_entry(u64 start, u64 end, const char *type)
+{
+ struct firmware_map_entry *entry;
+
+ spin_lock(&map_entries_lock);
+ list_for_each_entry(entry, &map_entries, list)
+ if ((entry->start == start) && (entry->end == end) &&
+ (!strcmp(entry->type, type))) {
+ spin_unlock(&map_entries_lock);
+ return entry;
+ }
+
+ spin_unlock(&map_entries_lock);
+ return NULL;
+}
+
/**
* firmware_map_add_hotplug() - Adds a firmware mapping entry when we do
* memory hotplug.
@@ -193,9 +258,36 @@ int __init firmware_map_add_early(u64 start, u64 end, const char *type)
if (WARN_ON(!entry))
return -ENOMEM;
+ entry->bootmem = 1;
return firmware_map_add_entry(start, end, type, entry);
}
+/**
+ * firmware_map_remove() - remove a firmware mapping entry
+ * @start: Start of the memory range.
+ * @end: End of the memory range.
+ * @type: Type of the memory range.
+ *
+ * removes a firmware mapping entry.
+ *
+ * Returns 0 on success, or -EINVAL if no entry.
+ **/
+int __meminit firmware_map_remove(u64 start, u64 end, const char *type)
+{
+ struct firmware_map_entry *entry;
+
+ entry = firmware_map_find_entry(start, end - 1, type);
+ if (!entry)
+ return -EINVAL;
+
+ firmware_map_remove_entry(entry);
+
+ /* remove the memmap entry */
+ remove_sysfs_fw_map_entry(entry);
+
+ return 0;
+}
+
/*
* Sysfs functions -------------------------------------------------------------
*/
@@ -217,8 +309,10 @@ static ssize_t type_show(struct firmware_map_entry *entry, char *buf)
return snprintf(buf, PAGE_SIZE, "%s\n", entry->type);
}
-#define to_memmap_attr(_attr) container_of(_attr, struct memmap_attribute, attr)
-#define to_memmap_entry(obj) container_of(obj, struct firmware_map_entry, kobj)
+static inline struct memmap_attribute *to_memmap_attr(struct attribute *attr)
+{
+ return container_of(attr, struct memmap_attribute, attr);
+}
static ssize_t memmap_attr_show(struct kobject *kobj,
struct attribute *attr, char *buf)
diff --git a/include/linux/firmware-map.h b/include/linux/firmware-map.h
index 43fe52f..71d4fa7 100644
--- a/include/linux/firmware-map.h
+++ b/include/linux/firmware-map.h
@@ -25,6 +25,7 @@
int firmware_map_add_early(u64 start, u64 end, const char *type);
int firmware_map_add_hotplug(u64 start, u64 end, const char *type);
+int firmware_map_remove(u64 start, u64 end, const char *type);
#else /* CONFIG_FIRMWARE_MEMMAP */
@@ -38,6 +39,11 @@ static inline int firmware_map_add_hotplug(u64 start, u64 end, const char *type)
return 0;
}
+static inline int firmware_map_remove(u64 start, u64 end, const char *type)
+{
+ return 0;
+}
+
#endif /* CONFIG_FIRMWARE_MEMMAP */
#endif /* _LINUX_FIRMWARE_MAP_H */
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index dbb04d8..1f5b5bb 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1442,7 +1442,7 @@ static int is_memblock_offlined_cb(struct memory_block *mem, void *arg)
return ret;
}
-int remove_memory(u64 start, u64 size)
+int __ref remove_memory(u64 start, u64 size)
{
unsigned long start_pfn, end_pfn;
int ret = 0;
@@ -1484,6 +1484,9 @@ repeat:
return ret;
}
+ /* remove memmap entry */
+ firmware_map_remove(start, start + size, "System RAM");
+
unlock_memory_hotplug();
return 0;
--
1.7.1
^ permalink raw reply related
* [PATCH v5 00/14] memory-hotplug: hot-remove physical memory
From: Tang Chen @ 2012-12-24 12:09 UTC (permalink / raw)
To: akpm, rientjes, liuj97, len.brown, benh, paulus, cl, minchan.kim,
kosaki.motohiro, isimatu.yasuaki, wujianguo, wency, tangchen, hpa,
linfeng, laijs, mgorman, yinghai
Cc: linux-s390, linux-ia64, linux-acpi, linux-sh, x86, linux-kernel,
cmetcalf, linux-mm, sparclinux, linuxppc-dev
Hi Andrew,
Here is the physical memory hot-remove patch-set based on 3.8rc-1.
This patch-set aims to implement physical memory hot-removing.
The patches can free/remove the following things:
- /sys/firmware/memmap/X/{end, start, type} : [PATCH 4/14]
- memmap of sparse-vmemmap : [PATCH 6,7,8,10/14]
- page table of removed memory : [RFC PATCH 7,8,10/14]
- node and related sysfs files : [RFC PATCH 13-14/14]
How to test this patchset?
1. apply this patchset and build the kernel. MEMORY_HOTPLUG, MEMORY_HOTREMOVE,
ACPI_HOTPLUG_MEMORY must be selected.
2. load the module acpi_memhotplug
3. hotplug the memory device(it depends on your hardware)
You will see the memory device under the directory /sys/bus/acpi/devices/.
Its name is PNP0C80:XX.
4. online/offline pages provided by this memory device
You can write online/offline to /sys/devices/system/memory/memoryX/state to
online/offline pages provided by this memory device
5. hotremove the memory device
You can hotremove the memory device by the hardware, or writing 1 to
/sys/bus/acpi/devices/PNP0C80:XX/eject.
Note: if the memory provided by the memory device is used by the kernel, it
can't be offlined. It is not a bug.
Changelogs from v4 to v5:
Patch7: new patch, move pgdat_resize_lock into sparse_remove_one_section() to
avoid disabling irq because we need flush tlb when free pagetables.
Patch8: new patch, pick up some common APIs that are used to free direct mapping
and vmemmap pagetables.
Patch9: free direct mapping pagetables on x86_64 arch.
Patch10: free vmemmap pagetables.
Patch11: since freeing memmap with vmemmap has been implemented, the config
macro CONFIG_SPARSEMEM_VMEMMAP when defining __remove_section() is
no longer needed.
Patch13: no need to modify acpi_memory_disable_device() since it was removed,
and add nid parameter when calling remove_memory().
Changelogs from v3 to v4:
Patch7: remove unused codes.
Patch8: fix nr_pages that is passed to free_map_bootmem()
Changelogs from v2 to v3:
Patch9: call sync_global_pgds() if pgd is changed
Patch10: fix a problem int the patch
Changelogs from v1 to v2:
Patch1: new patch, offline memory twice. 1st iterate: offline every non primary
memory block. 2nd iterate: offline primary (i.e. first added) memory
block.
Patch3: new patch, no logical change, just remove reduntant codes.
Patch9: merge the patch from wujianguo into this patch. flush tlb on all cpu
after the pagetable is changed.
Patch12: new patch, free node_data when a node is offlined.
Tang Chen (5):
memory-hotplug: move pgdat_resize_lock into
sparse_remove_one_section()
memory-hotplug: remove page table of x86_64 architecture
memory-hotplug: remove memmap of sparse-vmemmap
memory-hotplug: Integrated __remove_section() of
CONFIG_SPARSEMEM_VMEMMAP.
memory-hotplug: remove sysfs file of node
Wen Congyang (5):
memory-hotplug: try to offline the memory twice to avoid dependence
memory-hotplug: remove redundant codes
memory-hotplug: introduce new function arch_remove_memory() for
removing page table depends on architecture
memory-hotplug: Common APIs to support page tables hot-remove
memory-hotplug: free node_data when a node is offlined
Yasuaki Ishimatsu (4):
memory-hotplug: check whether all memory blocks are offlined or not
when removing memory
memory-hotplug: remove /sys/firmware/memmap/X sysfs
memory-hotplug: implement register_page_bootmem_info_section of
sparse-vmemmap
memory-hotplug: memory_hotplug: clear zone when removing the memory
arch/arm64/mm/mmu.c | 3 +
arch/ia64/mm/discontig.c | 10 +
arch/ia64/mm/init.c | 18 ++
arch/powerpc/mm/init_64.c | 10 +
arch/powerpc/mm/mem.c | 12 +
arch/s390/mm/init.c | 12 +
arch/s390/mm/vmem.c | 10 +
arch/sh/mm/init.c | 17 ++
arch/sparc/mm/init_64.c | 10 +
arch/tile/mm/init.c | 8 +
arch/x86/include/asm/pgtable_types.h | 1 +
arch/x86/mm/init_32.c | 12 +
arch/x86/mm/init_64.c | 382 ++++++++++++++++++++++++++++++++
arch/x86/mm/pageattr.c | 47 ++--
drivers/acpi/acpi_memhotplug.c | 8 +-
drivers/base/memory.c | 6 +
drivers/firmware/memmap.c | 98 ++++++++-
include/linux/bootmem.h | 1 +
include/linux/firmware-map.h | 6 +
include/linux/memory_hotplug.h | 15 +-
include/linux/mm.h | 4 +-
mm/memory_hotplug.c | 406 ++++++++++++++++++++++++++++++++--
mm/sparse.c | 8 +-
23 files changed, 1043 insertions(+), 61 deletions(-)
^ permalink raw reply
* Re: [REGRESSION][3.8.-rc1][ INFO: possible circular locking dependency detected ]
From: Christian Kujau @ 2012-12-23 21:34 UTC (permalink / raw)
To: Maciej Rutecki; +Cc: Cong Wang, linuxppc-dev, LKML, zhong
In-Reply-To: <201212221628.26640.maciej.rutecki@gmail.com>
On Sat, 22 Dec 2012 at 16:28, Maciej Rutecki wrote:
> Got during suspend to disk:
I got a similar message on a powerpc G4 system, right after bootup (no
suspend involved):
http://nerdbynature.de/bits/3.8.0-rc1/
[ 97.803049] ======================================================
[ 97.803051] [ INFO: possible circular locking dependency detected ]
[ 97.803059] 3.8.0-rc1-dirty #2 Not tainted
[ 97.803060] -------------------------------------------------------
[ 97.803066] kworker/0:1/235 is trying to acquire lock:
[ 97.803097] ((fb_notifier_list).rwsem){.+.+.+}, at: [<c00606a0>] __blocking_notifier_call_chain+0x44/0x88
[ 97.803099]
[ 97.803099] but task is already holding lock:
[ 97.803110] (console_lock){+.+.+.}, at: [<c03b9fd0>] console_callback+0x20/0x194
[ 97.803112]
[ 97.803112] which lock already depends on the new lock.
...and on it goes. Please see the URL above for the whole dmesg and
.config.
@Li Zhong: I have applied your fix for the "MAX_STACK_TRACE_ENTRIES too
low" warning[0] to 3.8-rc1 (hence the -dirty flag), but in the
backtrace "ret_from_kernel_thread" shows up again. FWIW, your
patch helped to make the "MAX_STACK_TRACE_ENTRIES too low"
warning go away in 3.7.0-rc7 and it did not re-appear ever
since.
Thanks,
Christian.
[0] http://lkml.indiana.edu/hypermail/linux/kernel/1211.3/01917.html
> [ 269.784867] [ INFO: possible circular locking dependency detected ]
> [ 269.784869] 3.8.0-rc1 #1 Not tainted
> [ 269.784870] -------------------------------------------------------
> [ 269.784871] kworker/u:3/56 is trying to acquire lock:
> [ 269.784878] ((fb_notifier_list).rwsem){.+.+.+}, at: [<ffffffff81062a1d>]
> __blocking_notifier_call_chain+0x49/0x80
> [ 269.784879]
> [ 269.784879] but task is already holding lock:
> [ 269.784884] (console_lock){+.+.+.}, at: [<ffffffff812ee4ce>]
> i915_drm_freeze+0x9e/0xbb
> [ 269.784884]
> [ 269.784884] which lock already depends on the new lock.
> [ 269.784884]
> [ 269.784885]
> [ 269.784885] the existing dependency chain (in reverse order) is:
> [ 269.784887]
> [ 269.784887] -> #1 (console_lock){+.+.+.}:
> [ 269.784890] [<ffffffff810890e4>] lock_acquire+0x95/0x105
> [ 269.784893] [<ffffffff810405a1>] console_lock+0x59/0x5b
> [ 269.784897] [<ffffffff812ba125>] register_con_driver+0x36/0x128
> [ 269.784899] [<ffffffff812bb27e>] take_over_console+0x1e/0x45
> [ 269.784903] [<ffffffff81257a04>] fbcon_takeover+0x56/0x98
> [ 269.784906] [<ffffffff8125b857>] fbcon_event_notify+0x2c1/0x5ea
> [ 269.784909] [<ffffffff8149a211>] notifier_call_chain+0x67/0x92
> [ 269.784911] [<ffffffff81062a33>] __blocking_notifier_call_chain+0x5f/0x80
> [ 269.784912] [<ffffffff81062a63>] blocking_notifier_call_chain+0xf/0x11
> [ 269.784915] [<ffffffff8124e85e>] fb_notifier_call_chain+0x16/0x18
> [ 269.784917] [<ffffffff812505d7>] register_framebuffer+0x20a/0x26e
> [ 269.784920] [<ffffffff812d3ca0>]
> drm_fb_helper_single_fb_probe+0x1ce/0x297
> [ 269.784922] [<ffffffff812d3f40>] drm_fb_helper_initial_config+0x1d7/0x1ef
> [ 269.784924] [<ffffffff8132cee2>] intel_fbdev_init+0x6f/0x82
> [ 269.784927] [<ffffffff812f22f6>] i915_driver_load+0xa9e/0xc78
> [ 269.784929] [<ffffffff812e020c>] drm_get_pci_dev+0x165/0x26d
> [ 269.784931] [<ffffffff812ee8da>] i915_pci_probe+0x60/0x69
> [ 269.784933] [<ffffffff8123fe8e>] local_pci_probe+0x39/0x61
> [ 269.784935] [<ffffffff812400f5>] pci_device_probe+0xba/0xe0
> [ 269.784938] [<ffffffff8133d3b6>] driver_probe_device+0x99/0x1c4
> [ 269.784940] [<ffffffff8133d52f>] __driver_attach+0x4e/0x6f
> [ 269.784942] [<ffffffff8133bae1>] bus_for_each_dev+0x52/0x84
> [ 269.784944] [<ffffffff8133cec6>] driver_attach+0x19/0x1b
> [ 269.784946] [<ffffffff8133cb65>] bus_add_driver+0xdf/0x203
> [ 269.784948] [<ffffffff8133dad3>] driver_register+0x8e/0x114
> [ 269.784952] [<ffffffff8123f581>] __pci_register_driver+0x5d/0x62
> [ 269.784953] [<ffffffff812e0395>] drm_pci_init+0x81/0xe6
> [ 269.784957] [<ffffffff81af7612>] i915_init+0x66/0x68
> [ 269.784959] [<ffffffff810020b4>] do_one_initcall+0x7a/0x136
> [ 269.784962] [<ffffffff8147ceaa>] kernel_init+0x141/0x296
> [ 269.784964] [<ffffffff8149c7bc>] ret_from_fork+0x7c/0xb0
> [ 269.784966]
> [ 269.784966] -> #0 ((fb_notifier_list).rwsem){.+.+.+}:
> [ 269.784967] [<ffffffff81088955>] __lock_acquire+0xa7e/0xddd
> [ 269.784969] [<ffffffff810890e4>] lock_acquire+0x95/0x105
> [ 269.784971] [<ffffffff81495092>] down_read+0x34/0x43
> [ 269.784973] [<ffffffff81062a1d>] __blocking_notifier_call_chain+0x49/0x80
> [ 269.784975] [<ffffffff81062a63>] blocking_notifier_call_chain+0xf/0x11
> [ 269.784977] [<ffffffff8124e85e>] fb_notifier_call_chain+0x16/0x18
> [ 269.784979] [<ffffffff8124ec47>] fb_set_suspend+0x22/0x4d
> [ 269.784981] [<ffffffff8132cfe3>] intel_fbdev_set_suspend+0x20/0x22
> [ 269.784983] [<ffffffff812ee4db>] i915_drm_freeze+0xab/0xbb
> [ 269.784985] [<ffffffff812eea82>] i915_pm_freeze+0x3d/0x41
> [ 269.784987] [<ffffffff8123f759>] pci_pm_freeze+0x65/0x8d
> [ 269.784990] [<ffffffff81342f20>] dpm_run_callback.isra.3+0x27/0x56
> [ 269.784993] [<ffffffff81343085>] __device_suspend+0x136/0x1b1
> [ 269.784995] [<ffffffff8134311a>] async_suspend+0x1a/0x58
> [ 269.784997] [<ffffffff81063a6b>] async_run_entry_fn+0xa4/0x17c
> [ 269.785000] [<ffffffff81058df2>] process_one_work+0x1cf/0x38e
> [ 269.785002] [<ffffffff81059290>] worker_thread+0x12e/0x1cc
> [ 269.785004] [<ffffffff8105d416>] kthread+0xac/0xb4
> [ 269.785006] [<ffffffff8149c7bc>] ret_from_fork+0x7c/0xb0
> [ 269.785006]
> [ 269.785006] other info that might help us debug this:
> [ 269.785006]
> [ 269.785007] Possible unsafe locking scenario:
> [ 269.785007]
> [ 269.785008] CPU0 CPU1
> [ 269.785008] ---- ----
> [ 269.785009] lock(console_lock);
> [ 269.785010] lock((fb_notifier_list).rwsem);
> [ 269.785012] lock(console_lock);
> [ 269.785013] lock((fb_notifier_list).rwsem);
> [ 269.785013]
> [ 269.785013] *** DEADLOCK ***
> [ 269.785013]
> [ 269.785014] 4 locks held by kworker/u:3/56:
> [ 269.785018] #0: (events_unbound){.+.+.+}, at: [<ffffffff81058d77>]
> process_one_work+0x154/0x38e
> [ 269.785021] #1: ((&entry->work)){+.+.+.}, at: [<ffffffff81058d77>]
> process_one_work+0x154/0x38e
> [ 269.785024] #2: (&__lockdep_no_validate__){......}, at: [<ffffffff81342d85>]
> device_lock+0xf/0x11
> [ 269.785027] #3: (console_lock){+.+.+.}, at: [<ffffffff812ee4ce>]
> i915_drm_freeze+0x9e/0xbb
> [ 269.785028]
> [ 269.785028] stack backtrace:
> [ 269.785029] Pid: 56, comm: kworker/u:3 Not tainted 3.8.0-rc1 #1
> [ 269.785030] Call Trace:
> [ 269.785035] [<ffffffff8148fcb5>] print_circular_bug+0x1f8/0x209
> [ 269.785036] [<ffffffff81088955>] __lock_acquire+0xa7e/0xddd
> [ 269.785038] [<ffffffff810890e4>] lock_acquire+0x95/0x105
> [ 269.785040] [<ffffffff81062a1d>] ? __blocking_notifier_call_chain+0x49/0x80
> [ 269.785042] [<ffffffff81495092>] down_read+0x34/0x43
> [ 269.785044] [<ffffffff81062a1d>] ? __blocking_notifier_call_chain+0x49/0x80
> [ 269.785046] [<ffffffff81062a1d>] __blocking_notifier_call_chain+0x49/0x80
> [ 269.785047] [<ffffffff81062a63>] blocking_notifier_call_chain+0xf/0x11
> [ 269.785050] [<ffffffff8124e85e>] fb_notifier_call_chain+0x16/0x18
> [ 269.785052] [<ffffffff8124ec47>] fb_set_suspend+0x22/0x4d
> [ 269.785054] [<ffffffff8132cfe3>] intel_fbdev_set_suspend+0x20/0x22
> [ 269.785055] [<ffffffff812ee4db>] i915_drm_freeze+0xab/0xbb
> [ 269.785057] [<ffffffff812eea82>] i915_pm_freeze+0x3d/0x41
> [ 269.785060] [<ffffffff8123f759>] pci_pm_freeze+0x65/0x8d
> [ 269.785062] [<ffffffff8123f6f4>] ? pci_pm_poweroff+0x9c/0x9c
> [ 269.785064] [<ffffffff81342f20>] dpm_run_callback.isra.3+0x27/0x56
> [ 269.785066] [<ffffffff81343085>] __device_suspend+0x136/0x1b1
> [ 269.785068] [<ffffffff81089563>] ? trace_hardirqs_on_caller+0x117/0x173
> [ 269.785070] [<ffffffff8134311a>] async_suspend+0x1a/0x58
> [ 269.785072] [<ffffffff81063a6b>] async_run_entry_fn+0xa4/0x17c
> [ 269.785074] [<ffffffff81058df2>] process_one_work+0x1cf/0x38e
> [ 269.785076] [<ffffffff81058d77>] ? process_one_work+0x154/0x38e
> [ 269.785078] [<ffffffff810639c7>] ? async_schedule+0x12/0x12
> [ 269.785080] [<ffffffff8105679f>] ? spin_lock_irq+0x9/0xb
> [ 269.785082] [<ffffffff81059290>] worker_thread+0x12e/0x1cc
> [ 269.785084] [<ffffffff81059162>] ? rescuer_thread+0x187/0x187
> [ 269.785085] [<ffffffff8105d416>] kthread+0xac/0xb4
> [ 269.785088] [<ffffffff8105d36a>] ? __kthread_parkme+0x60/0x60
> [ 269.785090] [<ffffffff8149c7bc>] ret_from_fork+0x7c/0xb0
> [ 269.785091] [<ffffffff8105d36a>] ? __kthread_parkme+0x60/0x60
>
>
> Config:
> http://mrutecki.pl/download/kernel/3.8.0-rc1/s2disk/config-3.8.0-rc1
>
> dmesg:
> http://mrutecki.pl/download/kernel/3.8.0-rc1/s2disk/dmesg-3.8.0-rc1.txt
>
>
> Found similar report:
> http://marc.info/?l=linux-kernel&m=135546308908700&w=2
>
> Regards
>
> --
> Maciej Rutecki
> http://www.mrutecki.pl
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
--
BOFH excuse #435:
Internet shut down due to maintenance
^ permalink raw reply
* Re: [PATCH 1/2] powerpc/perf: Fix finding overflowed PMC in interrupt
From: Sukadev Bhattiprolu @ 2012-12-22 1:07 UTC (permalink / raw)
To: Michael Neuling
Cc: Linux PPC dev, Paul Mackerras, Anton Blanchard,
Benjamin Herrenschmidt
In-Reply-To: <1352164118-19450-1-git-send-email-mikey@neuling.org>
Ben
Will these two patches be pushed upstream or are they waiting for
review/test ?
They fix a hang that we get with some perf events.
Thanks,
Sukadev
Michael Neuling [mikey@neuling.org] wrote:
| If a PMC is about to overflow on a counter that's on an active perf event
| (ie. less than 256 from the end) and a _different_ PMC overflows just at this
| time (a PMC that's not on an active perf event), we currently mark the event as
| found, but in reality it's not as it's likely the other PMC that caused the
| IRQ. Since we mark it as found the second catch all for overflows doesn't run,
| and we don't reset the overflowing PMC ever. Hence we keep hitting that same
| PMC IRQ over and over and don't reset the actual overflowing counter.
|
| This is a rewrite of the perf interrupt handler for book3s to get around this.
| We now check to see if any of the PMCs have actually overflowed (ie >=
| 0x80000000). If yes, record it for active counters and just reset it for
| inactive counters. If it's not overflowed, then we check to see if it's one of
| the buggy power7 counters and if it is, record it and continue. If none of the
| PMCs match this, then we make note that we couldn't find the PMC that caused
| the IRQ.
|
| Signed-off-by: Michael Neuling <mikey@neuling.org>
| Reviewed-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
| cc: Paul Mackerras <paulus@samba.org>
| cc: Anton Blanchard <anton@samba.org>
| cc: Linux PPC dev <linuxppc-dev@ozlabs.org>
| ---
| arch/powerpc/perf/core-book3s.c | 83 +++++++++++++++++++++++++--------------
| 1 file changed, 54 insertions(+), 29 deletions(-)
|
| diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
| index aa2465e..3575def 100644
| --- a/arch/powerpc/perf/core-book3s.c
| +++ b/arch/powerpc/perf/core-book3s.c
| @@ -1412,11 +1412,8 @@ unsigned long perf_instruction_pointer(struct pt_regs *regs)
| return regs->nip;
| }
|
| -static bool pmc_overflow(unsigned long val)
| +static bool pmc_overflow_power7(unsigned long val)
| {
| - if ((int)val < 0)
| - return true;
| -
| /*
| * Events on POWER7 can roll back if a speculative event doesn't
| * eventually complete. Unfortunately in some rare cases they will
| @@ -1428,7 +1425,15 @@ static bool pmc_overflow(unsigned long val)
| * PMCs because a user might set a period of less than 256 and we
| * don't want to mistakenly reset them.
| */
| - if (pvr_version_is(PVR_POWER7) && ((0x80000000 - val) <= 256))
| + if ((0x80000000 - val) <= 256)
| + return true;
| +
| + return false;
| +}
| +
| +static bool pmc_overflow(unsigned long val)
| +{
| + if ((int)val < 0)
| return true;
|
| return false;
| @@ -1439,11 +1444,11 @@ static bool pmc_overflow(unsigned long val)
| */
| static void perf_event_interrupt(struct pt_regs *regs)
| {
| - int i;
| + int i, j;
| struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
| struct perf_event *event;
| - unsigned long val;
| - int found = 0;
| + unsigned long val[8];
| + int found, active;
| int nmi;
|
| if (cpuhw->n_limited)
| @@ -1458,33 +1463,53 @@ static void perf_event_interrupt(struct pt_regs *regs)
| else
| irq_enter();
|
| - for (i = 0; i < cpuhw->n_events; ++i) {
| - event = cpuhw->event[i];
| - if (!event->hw.idx || is_limited_pmc(event->hw.idx))
| + /* Read all the PMCs since we'll need them a bunch of times */
| + for (i = 0; i < ppmu->n_counter; ++i)
| + val[i] = read_pmc(i + 1);
| +
| + /* Try to find what caused the IRQ */
| + found = 0;
| + for (i = 0; i < ppmu->n_counter; ++i) {
| + if (!pmc_overflow(val[i]))
| continue;
| - val = read_pmc(event->hw.idx);
| - if ((int)val < 0) {
| - /* event has overflowed */
| - found = 1;
| - record_and_restart(event, val, regs);
| + if (is_limited_pmc(i + 1))
| + continue; /* these won't generate IRQs */
| + /*
| + * We've found one that's overflowed. For active
| + * counters we need to log this. For inactive
| + * counters, we need to reset it anyway
| + */
| + found = 1;
| + active = 0;
| + for (j = 0; j < cpuhw->n_events; ++j) {
| + event = cpuhw->event[j];
| + if (event->hw.idx == (i + 1)) {
| + active = 1;
| + record_and_restart(event, val[i], regs);
| + break;
| + }
| }
| + if (!active)
| + /* reset non active counters that have overflowed */
| + write_pmc(i + 1, 0);
| }
| -
| - /*
| - * In case we didn't find and reset the event that caused
| - * the interrupt, scan all events and reset any that are
| - * negative, to avoid getting continual interrupts.
| - * Any that we processed in the previous loop will not be negative.
| - */
| - if (!found) {
| - for (i = 0; i < ppmu->n_counter; ++i) {
| - if (is_limited_pmc(i + 1))
| + if (!found && pvr_version_is(PVR_POWER7)) {
| + /* check active counters for special buggy p7 overflow */
| + for (i = 0; i < cpuhw->n_events; ++i) {
| + event = cpuhw->event[i];
| + if (!event->hw.idx || is_limited_pmc(event->hw.idx))
| continue;
| - val = read_pmc(i + 1);
| - if (pmc_overflow(val))
| - write_pmc(i + 1, 0);
| + if (pmc_overflow_power7(val[event->hw.idx - 1])) {
| + /* event has overflowed in a buggy way*/
| + found = 1;
| + record_and_restart(event,
| + val[event->hw.idx - 1],
| + regs);
| + }
| }
| }
| + if (!found)
| + printk(KERN_WARNING "Can't find PMC that caused IRQ\n");
|
| /*
| * Reset MMCR0 to its normal value. This will set PMXE and
| --
| 1.7.9.5
^ permalink raw reply
* Re: [v1][PATCH 3/6] book3e/kgdb: update thread's dbcr0
From: tiejun.chen @ 2012-12-21 2:02 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, linux-kernel, jason.wessel
In-Reply-To: <A47C9236-0744-45BC-B25A-3DDEB05CD8A1@kernel.crashing.org>
On 12/21/2012 02:41 AM, Kumar Gala wrote:
>
> On Dec 20, 2012, at 3:08 AM, Tiejun Chen wrote:
>
>> gdb always need to generate a single step properly to invoke
>> a kgdb state. But with lazy interrupt, book3e can't always
>> trigger a debug exception with a single step since the current
>> is blocked for handling those pending exception, then we miss
>> that expected dbcr configuration at last to generate a debug
>> exception.
>>
>> So here we also update thread's dbcr0 to make sure the current
>> can go back with that missed dbcr0 configuration.
>>
>> Signed-off-by: Tiejun Chen <tiejun.chen@windriver.com>
>> ---
>> arch/powerpc/kernel/kgdb.c | 10 ++++++++++
>> 1 file changed, 10 insertions(+)
>>
>> diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
>> index c470a40..516b44b 100644
>> --- a/arch/powerpc/kernel/kgdb.c
>> +++ b/arch/powerpc/kernel/kgdb.c
>> @@ -426,8 +426,18 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,
>> /* set the trace bit if we're stepping */
>> if (remcom_in_buffer[0] == 's') {
>> #ifdef CONFIG_PPC_ADV_DEBUG_REGS
>> +#ifdef CONFIG_PPC_BOOK3E
>
> Should this really be CONFIG_PPC64 or CONFIG_PPC_BOOK3E_64?
Yes, I think CONFIG_PPC_BOOK3E_64 is better currently. Because I didn't validate
this on power arch since I have no a real machine :)
>
>> + /* With lazy interrut we have to update thread dbcr0 here
>> + * to make sure we can set debug properly at last to invoke
>> + * kgdb again to work well.
>> + */
>> + current->thread.dbcr0 =
>> + mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM;
>> + mtspr(SPRN_DBCR0, current->thread.dbcr0);
>> +#else
>> mtspr(SPRN_DBCR0,
>> mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
>> +#endif
>
> Can we code this so we don't need the #else?
I guess you're saying something like this:
---
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
index c470a40..b2df42a 100644
--- a/arch/powerpc/kernel/kgdb.c
+++ b/arch/powerpc/kernel/kgdb.c
@@ -409,7 +409,7 @@ int kgdb_arch_handle_exception(int vector, int signo, int
err_code,
struct pt_regs *linux_regs)
{
char *ptr = &remcom_in_buffer[1];
- unsigned long addr;
+ unsigned long addr, dbcr0;
switch (remcom_in_buffer[0]) {
/*
@@ -426,8 +426,15 @@ int kgdb_arch_handle_exception(int vector, int signo, int
err_code,
/* set the trace bit if we're stepping */
if (remcom_in_buffer[0] == 's') {
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
- mtspr(SPRN_DBCR0,
- mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
+ dbcr0 = mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM;
+ mtspr(SPRN_DBCR0, dbcr0);
+#ifdef CONFIG_PPC_BOOK3E_64
+ /* With lazy interrut we have to update thread dbcr0 here
+ * to make sure we can set debug properly at last to invoke
+ * kgdb again to work well.
+ */
+ current->thread.dbcr0 = dbcr0;
+#endif
linux_regs->msr |= MSR_DE;
#else
linux_regs->msr |= MSR_SE;
--
1.7.9.5
Tiejun
^ permalink raw reply related
* RE: [PATCH 0/4] iommu/fsl: Freescale PAMU driver and IOMMU API implementation.
From: Sethi Varun-B16395 @ 2012-12-21 1:46 UTC (permalink / raw)
To: Joerg Roedel
Cc: Wood Scott-B07421, joerg.roedel@amd.com, Tabi Timur-B04825,
linux-kernel@vger.kernel.org, iommu@lists.linux-foundation.org,
Sethi Varun-B16395, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1355493114-21776-1-git-send-email-Varun.Sethi@freescale.com>
ping!!
> -----Original Message-----
> From: Sethi Varun-B16395
> Sent: Friday, December 14, 2012 7:22 PM
> To: joerg.roedel@amd.com; iommu@lists.linux-foundation.org; linuxppc-
> dev@lists.ozlabs.org; linux-kernel@vger.kernel.org; Tabi Timur-B04825;
> Wood Scott-B07421
> Cc: Sethi Varun-B16395
> Subject: [PATCH 0/4] iommu/fsl: Freescale PAMU driver and IOMMU API
> implementation.
>=20
> This patchset provides the Freescale PAMU (Peripheral Access Management
> Unit) driver and the corresponding IOMMU API implementation. PAMU is the
> IOMMU present on Freescale QorIQ platforms. PAMU can authorize memory
> access, remap the memory address, and remap the I/O transaction type.
>=20
> This set consists of the following patches:
> 1. Addition of new field in the device (powerpc) archdata structure for
> storing iommu domain information
> pointer. This pointer is stored when the device is attached to a
> particular iommu domain.
> 2. Add PAMU bypass enable register to the ccsr_guts structure.
> 3. Addition of domain attributes required by the PAMU driver IOMMU API.
> 4. PAMU driver and IOMMU API implementation.
>=20
> This patch set is based on the next branch of the iommu git tree
> maintained by Joerg.
>=20
> Varun Sethi (4):
> store iommu domain info in device arch data.
> add pamu bypass enable register to guts.
> Add iommu attributes for PAMU
> FSL PAMU driver.
>=20
> arch/powerpc/include/asm/device.h | 4 +
> arch/powerpc/include/asm/fsl_guts.h | 4 +-
> drivers/iommu/Kconfig | 8 +
> drivers/iommu/Makefile | 1 +
> drivers/iommu/fsl_pamu.c | 1152
> +++++++++++++++++++++++++++++++++++
> drivers/iommu/fsl_pamu.h | 398 ++++++++++++
> drivers/iommu/fsl_pamu_domain.c | 1033
> +++++++++++++++++++++++++++++++
> drivers/iommu/fsl_pamu_domain.h | 96 +++
> include/linux/iommu.h | 49 ++
> 9 files changed, 2744 insertions(+), 1 deletions(-) create mode 100644
> drivers/iommu/fsl_pamu.c create mode 100644 drivers/iommu/fsl_pamu.h
> create mode 100644 drivers/iommu/fsl_pamu_domain.c create mode 100644
> drivers/iommu/fsl_pamu_domain.h
>=20
> --
> 1.7.4.1
^ permalink raw reply
* [PATCH 7/7] powerpc: Add the DAWR support to the set_break()
From: Michael Neuling @ 2012-12-21 0:06 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: Michael Neuling, linuxppc-dev, Ian Munsie
In-Reply-To: <1356048405-20560-1-git-send-email-mikey@neuling.org>
This adds DAWR supoprt to the set_break().
It does both bare metal and PAPR versions of setting the DAWR.
There is still some work we can do to make full use of the watchpoint but that
will come later.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/include/asm/machdep.h | 4 ++++
arch/powerpc/kernel/process.c | 23 +++++++++++++++++++++++
arch/powerpc/platforms/pseries/setup.c | 12 ++++++++++++
3 files changed, 39 insertions(+)
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 19d9d96..3d6b410 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -180,6 +180,10 @@ struct machdep_calls {
int (*set_dabr)(unsigned long dabr,
unsigned long dabrx);
+ /* Set DAWR for this platform, leave empty for default implemenation */
+ int (*set_dawr)(unsigned long dawr,
+ unsigned long dawrx);
+
#ifdef CONFIG_PPC32 /* XXX for now */
/* A general init function, called by ppc_init in init/main.c.
May be NULL. */
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 5a64028..fec5f46 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -412,10 +412,33 @@ static inline int set_dabr(struct arch_hw_breakpoint *brk)
return 0;
}
+static inline int set_dawr(struct arch_hw_breakpoint *brk)
+{
+ unsigned long dawr, dawrx;
+
+ dawr = brk->address;
+
+ dawrx = (brk->type & (HW_BRK_TYPE_READ | HW_BRK_TYPE_WRITE)) \
+ << (63 - 58); //* read/write bits */
+ dawrx |= ((brk->type & (HW_BRK_TYPE_TRANSLATE)) >> 2) \
+ << (63 - 59); //* translate */
+ dawrx |= (brk->type & (HW_BRK_TYPE_PRIV_ALL)) \
+ >> 3; //* PRIM bits */
+
+ if (ppc_md.set_dawr)
+ return ppc_md.set_dawr(dawr, dawrx);
+ mtspr(SPRN_DAWR, dawr);
+ mtspr(SPRN_DAWRX, dawrx);
+ return 0;
+}
+
int set_break(struct arch_hw_breakpoint *brk)
{
__get_cpu_var(current_brk) = *brk;
+ if (cpu_has_feature(CPU_FTR_DAWR))
+ return set_dawr(brk);
+
return set_dabr(brk);
}
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 1890730..b1f60d1 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -65,6 +65,7 @@
#include <asm/smp.h>
#include <asm/firmware.h>
#include <asm/eeh.h>
+#include <asm/reg.h>
#include "plpar_wrappers.h"
#include "pseries.h"
@@ -500,6 +501,14 @@ static int pseries_set_xdabr(unsigned long dabr, unsigned long dabrx)
return plpar_hcall_norets(H_SET_XDABR, dabr, dabrx);
}
+static int pseries_set_dawr(unsigned long dawr, unsigned long dawrx)
+{
+ /* PAPR says we can't set HYP */
+ dawrx &= ~DAWRX_HYP;
+
+ return plapr_set_watchpoint0(dawr, dawrx);
+}
+
#define CMO_CHARACTERISTICS_TOKEN 44
#define CMO_MAXLENGTH 1026
@@ -606,6 +615,9 @@ static void __init pSeries_init_early(void)
else if (firmware_has_feature(FW_FEATURE_DABR))
ppc_md.set_dabr = pseries_set_dabr;
+ if (firmware_has_feature(FW_FEATURE_SET_MODE))
+ ppc_md.set_dawr = pseries_set_dawr;
+
pSeries_cmo_feature_init();
iommu_init_early_pSeries();
--
1.7.10.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox