[PATCH 1/2][v2] powerpc: Move free_initmem to common code

2011-06-18 Thread Dave Carroll
From: Dave Carroll dcarr...@astekcorp.com

The free_initmem function is basically duplicated in mm/init_32,
and init_64, and is moved to the common 32/64-bit mm/mem.c.

All other sections except init were removed in v2.6.15 by
6c45ab992e4299c869fb26427944a8f8ea177024 (powerpc: Remove section
free() and linker script bits), and therefore the bulk of the executed
code is identical.

This patch also removes updating ppc_md.progress to NULL in the powermac
late_initcall.

Suggested-by: Milton Miller milt...@bga.com
Suggested-by: Benjamin Herrenschmidt b...@kernel.crashing.org
Signed-off-by: Dave Carroll dcarr...@astekcorp.com
---
 [v2] This is a rebase of the original patch to Linus' current tree
 
 arch/powerpc/mm/init_32.c   |   32 ---
 arch/powerpc/mm/init_64.c   |   16 ---
 arch/powerpc/mm/mem.c   |   19 ++
 arch/powerpc/platforms/powermac/setup.c |3 --
 4 files changed, 19 insertions(+), 51 deletions(-)

diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 5de0f25..c77fef5 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -191,38 +191,6 @@ void __init *early_get_page(void)
return __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
 }
 
-/* Free up now-unused memory */
-static void free_sec(unsigned long start, unsigned long end, const char *name)
-{
-   unsigned long cnt = 0;
-
-   while (start  end) {
-   ClearPageReserved(virt_to_page(start));
-   init_page_count(virt_to_page(start));
-   free_page(start);
-   cnt++;
-   start += PAGE_SIZE;
-   }
-   if (cnt) {
-   printk( %ldk %s, cnt  (PAGE_SHIFT - 10), name);
-   totalram_pages += cnt;
-   }
-}
-
-void free_initmem(void)
-{
-#define FREESEC(TYPE) \
-   free_sec((unsigned long)(__ ## TYPE ## _begin), \
-(unsigned long)(__ ## TYPE ## _end), \
-#TYPE);
-
-   printk (Freeing unused kernel memory:);
-   FREESEC(init);
-   printk(\n);
-   ppc_md.progress = NULL;
-#undef FREESEC
-}
-
 #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size)
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index f6dbb4c..e94b57f 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -83,22 +83,6 @@ EXPORT_SYMBOL_GPL(memstart_addr);
 phys_addr_t kernstart_addr;
 EXPORT_SYMBOL_GPL(kernstart_addr);
 
-void free_initmem(void)
-{
-   unsigned long addr;
-
-   addr = (unsigned long)__init_begin;
-   for (; addr  (unsigned long)__init_end; addr += PAGE_SIZE) {
-   memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
-   ClearPageReserved(virt_to_page(addr));
-   init_page_count(virt_to_page(addr));
-   free_page(addr);
-   totalram_pages++;
-   }
-   printk (Freeing unused kernel memory: %luk freed\n,
-   ((unsigned long)__init_end - (unsigned long)__init_begin)  
10);
-}
-
 static void pgd_ctor(void *addr)
 {
memset(addr, 0, PGD_TABLE_SIZE);
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 29d4dde..f4e6408 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -382,6 +382,25 @@ void __init mem_init(void)
mem_init_done = 1;
 }
 
+void free_initmem(void)
+{
+   unsigned long addr;
+
+   ppc_md.progress = NULL;
+
+   addr = (unsigned long)__init_begin;
+   for (; addr  (unsigned long)__init_end; addr += PAGE_SIZE) {
+   memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
+   ClearPageReserved(virt_to_page(addr));
+   init_page_count(virt_to_page(addr));
+   free_page(addr);
+   totalram_pages++;
+   }
+   pr_info(Freeing unused kernel memory: %luk freed\n,
+   ((unsigned long)__init_end -
+   (unsigned long)__init_begin)  10);
+}
+
 #ifdef CONFIG_BLK_DEV_INITRD
 void __init free_initrd_mem(unsigned long start, unsigned long end)
 {
diff --git a/arch/powerpc/platforms/powermac/setup.c 
b/arch/powerpc/platforms/powermac/setup.c
index aa45281..a028f08 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -355,9 +355,6 @@ static int initializing = 1;
 static int pmac_late_init(void)
 {
initializing = 0;
-   /* this is udbg (which is __init) and we can later use it during
-* cpu hotplug (in smp_core99_kick_cpu) */
-   ppc_md.progress = NULL;
return 0;
 }
 machine_late_initcall(powermac, pmac_late_init);
-- 
1.7.5

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 2/2][v2] powerpc: Add printk companion for ppc_md.progress

2011-06-18 Thread Dave Carroll
From: Dave Carroll dcarr...@astekcorp.com

This patch adds a printk companion to replace the udbg progress function
when initmem is freed.

Suggested-by: Milton Miller milt...@bga.com
Suggested-by: Benjamin Herrenschmidt b...@kernel.crashing.org
Signed-off-by: Dave Carroll dcarr...@astekcorp.com
---
 [v2] This is a rebase of the original patch to Linus' current tree
 
 arch/powerpc/include/asm/setup.h   |2 ++
 arch/powerpc/kernel/setup-common.c |5 +
 arch/powerpc/mm/mem.c  |2 +-
 3 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h
index dae1934..c77cb7a 100644
--- a/arch/powerpc/include/asm/setup.h
+++ b/arch/powerpc/include/asm/setup.h
@@ -3,4 +3,6 @@
 
 #include asm-generic/setup.h
 
+extern void ppc_printk_progress(char *s, unsigned short hex);
+
 #endif /* _ASM_POWERPC_SETUP_H */
diff --git a/arch/powerpc/kernel/setup-common.c 
b/arch/powerpc/kernel/setup-common.c
index 79fca26..e053b16 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -704,6 +704,11 @@ static int powerpc_debugfs_init(void)
 arch_initcall(powerpc_debugfs_init);
 #endif
 
+void ppc_printk_progress(char *s, unsigned short hex)
+{
+   pr_info(%s\n, s);
+}
+
 static int ppc_dflt_bus_notify(struct notifier_block *nb,
unsigned long action, void *data)
 {
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index f4e6408..e0d2aa0 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -386,7 +386,7 @@ void free_initmem(void)
 {
unsigned long addr;
 
-   ppc_md.progress = NULL;
+   ppc_md.progress = ppc_printk_progress;
 
addr = (unsigned long)__init_begin;
for (; addr  (unsigned long)__init_end; addr += PAGE_SIZE) {
-- 
1.7.5

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 1/2] powerpc: Move free_initmem to common code

2011-06-10 Thread Dave Carroll
From: Dave Carroll dcarr...@astekcorp.com

The free_initmem function is basically duplicated in mm/init_32,
and init_64, and is moved to the common 32/64-bit mm/mem.c.

All other sections except init were removed in v2.6.15 by
6c45ab992e4299c869fb26427944a8f8ea177024 (powerpc: Remove section
free() and linker script bits), and therefore the bulk of the executed
code is identical.

This patch also removes updating ppc_md.progress to NULL in the powermac
late_initcall.

Suggested-by: Milton Miller milt...@bga.com
Suggested-by: Benjamin Herrenschmidt b...@kernel.crashing.org
Signed-off-by: Dave Carroll dcarr...@astekcorp.com
---
 arch/powerpc/mm/init_32.c   |   32 ---
 arch/powerpc/mm/init_64.c   |   16 ---
 arch/powerpc/mm/mem.c   |   19 ++
 arch/powerpc/platforms/powermac/setup.c |3 --
 4 files changed, 19 insertions(+), 51 deletions(-)

diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 5de0f25..c77fef5 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -191,38 +191,6 @@ void __init *early_get_page(void)
return __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
 }
 
-/* Free up now-unused memory */
-static void free_sec(unsigned long start, unsigned long end, const char *name)
-{
-   unsigned long cnt = 0;
-
-   while (start  end) {
-   ClearPageReserved(virt_to_page(start));
-   init_page_count(virt_to_page(start));
-   free_page(start);
-   cnt++;
-   start += PAGE_SIZE;
-   }
-   if (cnt) {
-   printk( %ldk %s, cnt  (PAGE_SHIFT - 10), name);
-   totalram_pages += cnt;
-   }
-}
-
-void free_initmem(void)
-{
-#define FREESEC(TYPE) \
-   free_sec((unsigned long)(__ ## TYPE ## _begin), \
-(unsigned long)(__ ## TYPE ## _end), \
-#TYPE);
-
-   printk (Freeing unused kernel memory:);
-   FREESEC(init);
-   printk(\n);
-   ppc_md.progress = NULL;
-#undef FREESEC
-}
-
 #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size)
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index f6dbb4c..e94b57f 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -83,22 +83,6 @@ EXPORT_SYMBOL_GPL(memstart_addr);
 phys_addr_t kernstart_addr;
 EXPORT_SYMBOL_GPL(kernstart_addr);
 
-void free_initmem(void)
-{
-   unsigned long addr;
-
-   addr = (unsigned long)__init_begin;
-   for (; addr  (unsigned long)__init_end; addr += PAGE_SIZE) {
-   memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
-   ClearPageReserved(virt_to_page(addr));
-   init_page_count(virt_to_page(addr));
-   free_page(addr);
-   totalram_pages++;
-   }
-   printk (Freeing unused kernel memory: %luk freed\n,
-   ((unsigned long)__init_end - (unsigned long)__init_begin)  
10);
-}
-
 static void pgd_ctor(void *addr)
 {
memset(addr, 0, PGD_TABLE_SIZE);
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 29d4dde..f4e6408 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -382,6 +382,25 @@ void __init mem_init(void)
mem_init_done = 1;
 }
 
+void free_initmem(void)
+{
+   unsigned long addr;
+
+   ppc_md.progress = NULL;
+
+   addr = (unsigned long)__init_begin;
+   for (; addr  (unsigned long)__init_end; addr += PAGE_SIZE) {
+   memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
+   ClearPageReserved(virt_to_page(addr));
+   init_page_count(virt_to_page(addr));
+   free_page(addr);
+   totalram_pages++;
+   }
+   pr_info(Freeing unused kernel memory: %luk freed\n,
+   ((unsigned long)__init_end -
+   (unsigned long)__init_begin)  10);
+}
+
 #ifdef CONFIG_BLK_DEV_INITRD
 void __init free_initrd_mem(unsigned long start, unsigned long end)
 {
diff --git a/arch/powerpc/platforms/powermac/setup.c 
b/arch/powerpc/platforms/powermac/setup.c
index aa45281..a028f08 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -355,9 +355,6 @@ static int initializing = 1;
 static int pmac_late_init(void)
 {
initializing = 0;
-   /* this is udbg (which is __init) and we can later use it during
-* cpu hotplug (in smp_core99_kick_cpu) */
-   ppc_md.progress = NULL;
return 0;
 }
 machine_late_initcall(powermac, pmac_late_init);
-- 
1.7.4

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 2/2] powerpc: Add printk companion for ppc_md.progress

2011-06-10 Thread Dave Carroll
From: Dave Carroll dcarr...@astekcorp.com

This patch adds a printk companion to replace the udbg progress function
when initmem is freed.

Suggested-by: Milton Miller milt...@bga.com
Suggested-by: Benjamin Herrenschmidt b...@kernel.crashing.org
Signed-off-by: Dave Carroll dcarr...@astekcorp.com
---
 arch/powerpc/include/asm/setup.h   |2 ++
 arch/powerpc/kernel/setup-common.c |5 +
 arch/powerpc/mm/mem.c  |2 +-
 3 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h
index dae1934..c77cb7a 100644
--- a/arch/powerpc/include/asm/setup.h
+++ b/arch/powerpc/include/asm/setup.h
@@ -3,4 +3,6 @@
 
 #include asm-generic/setup.h
 
+extern void ppc_printk_progress(char *s, unsigned short hex);
+
 #endif /* _ASM_POWERPC_SETUP_H */
diff --git a/arch/powerpc/kernel/setup-common.c 
b/arch/powerpc/kernel/setup-common.c
index 79fca26..e053b16 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -704,6 +704,11 @@ static int powerpc_debugfs_init(void)
 arch_initcall(powerpc_debugfs_init);
 #endif
 
+void ppc_printk_progress(char *s, unsigned short hex)
+{
+   pr_info(%s\n, s);
+}
+
 static int ppc_dflt_bus_notify(struct notifier_block *nb,
unsigned long action, void *data)
 {
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index f4e6408..e0d2aa0 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -386,7 +386,7 @@ void free_initmem(void)
 {
unsigned long addr;
 
-   ppc_md.progress = NULL;
+   ppc_md.progress = ppc_printk_progress;
 
addr = (unsigned long)__init_begin;
for (; addr  (unsigned long)__init_end; addr += PAGE_SIZE) {
-- 
1.7.4

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH v8] powerpc: Force page alignment for initrd reserved memory

2011-05-26 Thread Dave Carroll
From: Dave Carroll dcarr...@astekcorp.com

When using 64K pages with a separate cpio rootfs, U-Boot will align
the rootfs on a 4K page boundary. When the memory is reserved, and
subsequent early memblock_alloc is called, it will allocate memory
between the 64K page alignment and reserved memory. When the reserved
memory is subsequently freed, it is done so by pages, causing the
early memblock_alloc requests to be re-used, which in my case, caused
the device-tree to be clobbered.

This patch forces the reserved memory for initrd to be kernel page
aligned, and will move the device tree if it overlaps with the range
extension of initrd. This patch will also consolidate the identical
function free_initrd_mem() from mm/init_32.c, init_64.c to mm/mem.c,
and adds the same range extension when freeing initrd. free_initrd_mem()
is also moved to the __init section.

Many thanks to Milton Miller for his input on this patch.

Signed-off-by: Dave Carroll dcarr...@astekcorp.com
Cc: Benjamin Herrenschmidt b...@kernel.crashing.org
---
 arch/powerpc/kernel/prom.c |   23 ---
 arch/powerpc/mm/init_32.c  |   15 ---
 arch/powerpc/mm/init_64.c  |   14 --
 arch/powerpc/mm/mem.c  |   19 +++
 4 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 48aeb55..fba012a 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -82,11 +82,25 @@ static int __init early_parse_mem(char *p)
 }
 early_param(mem, early_parse_mem);
 
+/*
+ * overlaps_initrd - check for overlap with page aligned extension of
+ * initrd.
+ */
+static inline int overlaps_initrd(unsigned long start, unsigned long size)
+{
+   if (!initrd_start)
+   return 0;
+
+   return  (start + size)  _ALIGN_DOWN(initrd_start, PAGE_SIZE) 
+   start = _ALIGN_UP(initrd_end, PAGE_SIZE);
+}
+
 /**
  * move_device_tree - move tree to an unused area, if needed.
  *
  * The device tree may be allocated beyond our memory limit, or inside the
- * crash kernel region for kdump. If so, move it out of the way.
+ * crash kernel region for kdump, or within the page aligned range of initrd.
+ * If so, move it out of the way.
  */
 static void __init move_device_tree(void)
 {
@@ -99,7 +113,8 @@ static void __init move_device_tree(void)
size = be32_to_cpu(initial_boot_params-totalsize);
 
if ((memory_limit  (start + size)  PHYSICAL_START + memory_limit) ||
-   overlaps_crashkernel(start, size)) {
+   overlaps_crashkernel(start, size) ||
+   overlaps_initrd(start, size)) {
p = __va(memblock_alloc(size, PAGE_SIZE));
memcpy(p, initial_boot_params, size);
initial_boot_params = (struct boot_param_header *)p;
@@ -555,7 +570,9 @@ static void __init early_reserve_mem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
/* then reserve the initrd, if any */
if (initrd_start  (initrd_end  initrd_start))
-   memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
+   memblock_reserve(_ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE),
+   _ALIGN_UP(initrd_end, PAGE_SIZE) -
+   _ALIGN_DOWN(initrd_start, PAGE_SIZE));
 #endif /* CONFIG_BLK_DEV_INITRD */
 
 #ifdef CONFIG_PPC32
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index d65b591..5de0f25 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -223,21 +223,6 @@ void free_initmem(void)
 #undef FREESEC
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-   if (start  end)
-   printk (Freeing initrd memory: %ldk freed\n, (end - start)  
10);
-   for (; start  end; start += PAGE_SIZE) {
-   ClearPageReserved(virt_to_page(start));
-   init_page_count(virt_to_page(start));
-   free_page(start);
-   totalram_pages++;
-   }
-}
-#endif
-
-
 #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size)
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 6374b21..f6dbb4c 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -99,20 +99,6 @@ void free_initmem(void)
((unsigned long)__init_end - (unsigned long)__init_begin)  
10);
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-   if (start  end)
-   printk (Freeing initrd memory: %ldk freed\n, (end - start)  
10);
-   for (; start  end; start += PAGE_SIZE) {
-   ClearPageReserved(virt_to_page(start));
-   init_page_count(virt_to_page(start));
-   free_page(start

[PATCH v6] powerpc: Force page alignment for initrd reserved memory

2011-05-25 Thread Dave Carroll
From: Dave Carroll dcarr...@astekcorp.com

When using 64K pages with a separate cpio rootfs, U-Boot will align
the rootfs on a 4K page boundary. When the memory is reserved, and
subsequent early memblock_alloc is called, it will allocate memory
between the 64K page alignment and reserved memory. When the reserved
memory is subsequently freed, it is done so by pages, causing the
early memblock_alloc requests to be re-used, which in my case, caused
the device-tree to be clobbered.

This patch forces the reserved memory for initrd to be kernel page
aligned, and will move the device tree if it overlaps with the range
extension of initrd. This patch will also consolidate the identical
function free_initrd_mem() from mm/init_32.c, init_64.c to mm/mem.c,
and adds the same range extension when freeing initrd.

Many thanks to Milton Miller for his input on this patch.

Signed-off-by: Dave Carroll dcarr...@astekcorp.com
Cc: Benjamin Herrenschmidt b...@kernel.crashing.org

---
 arch/powerpc/kernel/prom.c |   21 ++---
 arch/powerpc/mm/init_32.c  |   15 ---
 arch/powerpc/mm/init_64.c  |   13 -
 arch/powerpc/mm/mem.c  |   19 +++
 4 files changed, 37 insertions(+), 31 deletions(-)

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 48aeb55..86966a0 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -81,12 +81,24 @@ static int __init early_parse_mem(char *p)
return 0;
 }
 early_param(mem, early_parse_mem);
+/**
+ * overlaps_initrd - check for overlap with page aligned extension of
+ * initrd.
+ */
+static inline int overlaps_initrd(unsigned long start, unsigned long end)
+{
+   if (!initrd_start)
+   return 0;
 
+   return  (start + size)  _ALIGN_DOWN(initrd_start, PAGE_SIZE) 
+   start = _ALIGN_UP(initrd_end, PAGE_SIZE);
+}
 /**
  * move_device_tree - move tree to an unused area, if needed.
  *
  * The device tree may be allocated beyond our memory limit, or inside the
- * crash kernel region for kdump. If so, move it out of the way.
+ * crash kernel region for kdump, or within the page aligned range of initrd.
+ * If so, move it out of the way.
  */
 static void __init move_device_tree(void)
 {
@@ -99,7 +111,8 @@ static void __init move_device_tree(void)
size = be32_to_cpu(initial_boot_params-totalsize);
 
if ((memory_limit  (start + size)  PHYSICAL_START + memory_limit) ||
-   overlaps_crashkernel(start, size)) {
+   overlaps_crashkernel(start, size) ||
+   overlaps_initrd(start, size) {
p = __va(memblock_alloc(size, PAGE_SIZE));
memcpy(p, initial_boot_params, size);
initial_boot_params = (struct boot_param_header *)p;
@@ -555,7 +568,9 @@ static void __init early_reserve_mem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
/* then reserve the initrd, if any */
if (initrd_start  (initrd_end  initrd_start))
-   memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
+   memblock_reserve(_ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE),
+   _ALIGN_UP(initrd_end, PAGE_SIZE) -
+   _ALIGN_DOWN(initrd_start, PAGE_SIZE));
 #endif /* CONFIG_BLK_DEV_INITRD */
 
 #ifdef CONFIG_PPC32
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index d65b591..5de0f25 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -223,21 +223,6 @@ void free_initmem(void)
 #undef FREESEC
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-   if (start  end)
-   printk (Freeing initrd memory: %ldk freed\n, (end - start)  
10);
-   for (; start  end; start += PAGE_SIZE) {
-   ClearPageReserved(virt_to_page(start));
-   init_page_count(virt_to_page(start));
-   free_page(start);
-   totalram_pages++;
-   }
-}
-#endif
-
-
 #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size)
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 6374b21..7591a97 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -99,19 +99,6 @@ void free_initmem(void)
((unsigned long)__init_end - (unsigned long)__init_begin)  
10);
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-   if (start  end)
-   printk (Freeing initrd memory: %ldk freed\n, (end - start)  
10);
-   for (; start  end; start += PAGE_SIZE) {
-   ClearPageReserved(virt_to_page(start));
-   init_page_count(virt_to_page(start));
-   free_page(start);
-   totalram_pages++;
-   }
-}
-#endif
 
 static void

[PATCH v7] powerpc: Force page alignment for initrd reserved memory

2011-05-25 Thread Dave Carroll
From: Dave Carroll dcarr...@astekcorp.com

When using 64K pages with a separate cpio rootfs, U-Boot will align
the rootfs on a 4K page boundary. When the memory is reserved, and
subsequent early memblock_alloc is called, it will allocate memory
between the 64K page alignment and reserved memory. When the reserved
memory is subsequently freed, it is done so by pages, causing the
early memblock_alloc requests to be re-used, which in my case, caused
the device-tree to be clobbered.

This patch forces the reserved memory for initrd to be kernel page
aligned, and will move the device tree if it overlaps with the range
extension of initrd. This patch will also consolidate the identical
function free_initrd_mem() from mm/init_32.c, init_64.c to mm/mem.c,
and adds the same range extension when freeing initrd.

Many thanks to Milton Miller for his input on this patch.

Signed-off-by: Dave Carroll dcarr...@astekcorp.com
Cc: Benjamin Herrenschmidt b...@kernel.crashing.org

---
 * The previous patch [v6] was the wrong copy, sorry ...
 
 arch/powerpc/kernel/prom.c |   21 ++---
 arch/powerpc/mm/init_32.c  |   15 ---
 arch/powerpc/mm/init_64.c  |   13 -
 arch/powerpc/mm/mem.c  |   19 +++
 4 files changed, 37 insertions(+), 31 deletions(-)

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 48aeb55..86966a0 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -81,12 +81,24 @@ static int __init early_parse_mem(char *p)
return 0;
 }
 early_param(mem, early_parse_mem);
+/**
+ * overlaps_initrd - check for overlap with page aligned extension of
+ * initrd.
+ */
+static inline int overlaps_initrd(unsigned long start, unsigned long size)
+{
+   if (!initrd_start)
+   return 0;
 
+   return  (start + size)  _ALIGN_DOWN(initrd_start, PAGE_SIZE) 
+   start = _ALIGN_UP(initrd_end, PAGE_SIZE);
+}
 /**
  * move_device_tree - move tree to an unused area, if needed.
  *
  * The device tree may be allocated beyond our memory limit, or inside the
- * crash kernel region for kdump. If so, move it out of the way.
+ * crash kernel region for kdump, or within the page aligned range of initrd.
+ * If so, move it out of the way.
  */
 static void __init move_device_tree(void)
 {
@@ -99,7 +111,8 @@ static void __init move_device_tree(void)
size = be32_to_cpu(initial_boot_params-totalsize);
 
if ((memory_limit  (start + size)  PHYSICAL_START + memory_limit) ||
-   overlaps_crashkernel(start, size)) {
+   overlaps_crashkernel(start, size) ||
+   overlaps_initrd(start, size)) {
p = __va(memblock_alloc(size, PAGE_SIZE));
memcpy(p, initial_boot_params, size);
initial_boot_params = (struct boot_param_header *)p;
@@ -555,7 +568,9 @@ static void __init early_reserve_mem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
/* then reserve the initrd, if any */
if (initrd_start  (initrd_end  initrd_start))
-   memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
+   memblock_reserve(_ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE),
+   _ALIGN_UP(initrd_end, PAGE_SIZE) -
+   _ALIGN_DOWN(initrd_start, PAGE_SIZE));
 #endif /* CONFIG_BLK_DEV_INITRD */
 
 #ifdef CONFIG_PPC32
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index d65b591..5de0f25 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -223,21 +223,6 @@ void free_initmem(void)
 #undef FREESEC
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-   if (start  end)
-   printk (Freeing initrd memory: %ldk freed\n, (end - start)  
10);
-   for (; start  end; start += PAGE_SIZE) {
-   ClearPageReserved(virt_to_page(start));
-   init_page_count(virt_to_page(start));
-   free_page(start);
-   totalram_pages++;
-   }
-}
-#endif
-
-
 #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size)
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 6374b21..7591a97 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -99,19 +99,6 @@ void free_initmem(void)
((unsigned long)__init_end - (unsigned long)__init_begin)  
10);
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-   if (start  end)
-   printk (Freeing initrd memory: %ldk freed\n, (end - start)  
10);
-   for (; start  end; start += PAGE_SIZE) {
-   ClearPageReserved(virt_to_page(start));
-   init_page_count(virt_to_page(start));
-   free_page(start

RE: [ v4] powerpc: Force page alignment for initrd reserved memory

2011-05-23 Thread Dave Carroll

I'm withdrawing this patch for the moment, due to two areas that need further 
research;

1) An adjacent FDT blob, as mentioned by Milton Miller, and

2) Potential interaction with the crash kernel, as used in
init/initramfs.c

If anyone sees other interactions, please feel free to let me know ...

Thanks,
-Dave Carroll
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH v5] powerpc: Force page alignment for initrd reserved memory

2011-05-23 Thread Dave Carroll
When using 64K pages with a separate cpio rootfs, U-Boot will align
the rootfs on a 4K page boundary. When the memory is reserved, and
subsequent early memblock_alloc is called, it will allocate memory
between the 64K page alignment and reserved memory. When the reserved
memory is subsequently freed, it is done so by pages, causing the
early memblock_alloc requests to be re-used, which in my case, caused
the device-tree to be clobbered.

This patch forces the reserved memory for initrd to be kernel page
aligned, and adds the same range extension when freeing initrd. It
will also move the device tree if it overlaps with the reserved memory
for initrd.

Many thanks to Milton Miller for his input on this patch.

Signed-off-by: Dave Carroll dcarr...@astekcorp.com
---
 * This patch is based on Linus' current tree

 arch/powerpc/kernel/prom.c |   11 ---
 arch/powerpc/mm/init_32.c  |5 -
 arch/powerpc/mm/init_64.c  |5 -
 3 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 48aeb55..58871df 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -86,7 +86,8 @@ early_param(mem, early_parse_mem);
  * move_device_tree - move tree to an unused area, if needed.
  *
  * The device tree may be allocated beyond our memory limit, or inside the
- * crash kernel region for kdump. If so, move it out of the way.
+ * crash kernel region for kdump, or within the page aligned range of initrd.
+ * If so, move it out of the way.
  */
 static void __init move_device_tree(void)
 {
@@ -99,7 +100,9 @@ static void __init move_device_tree(void)
size = be32_to_cpu(initial_boot_params-totalsize);

if ((memory_limit  (start + size)  PHYSICAL_START + memory_limit) ||
-   overlaps_crashkernel(start, size)) {
+   overlaps_crashkernel(start, size) ||
+   ((start + size)  _ALIGN_DOWN(initrd_start, PAGE_SIZE)
+start = _ALIGN_UP(initrd_end, PAGE_SIZE))) {
p = __va(memblock_alloc(size, PAGE_SIZE));
memcpy(p, initial_boot_params, size);
initial_boot_params = (struct boot_param_header *)p;
@@ -555,7 +558,9 @@ static void __init early_reserve_mem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
/* then reserve the initrd, if any */
if (initrd_start  (initrd_end  initrd_start))
-   memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
+   memblock_reserve(_ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE),
+   _ALIGN_UP(initrd_end, PAGE_SIZE) -
+   _ALIGN_DOWN(initrd_start, PAGE_SIZE));
 #endif /* CONFIG_BLK_DEV_INITRD */

 #ifdef CONFIG_PPC32
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index d65b591..4835c4f 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -226,8 +226,11 @@ void free_initmem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-   if (start  end)
+   if (start  end) {
+   start = _ALIGN_DOWN(start, PAGE_SIZE);
+   end = _ALIGN_UP(end, PAGE_SIZE);
printk (Freeing initrd memory: %ldk freed\n, (end - start)  
10);
+   }
for (; start  end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
init_page_count(virt_to_page(start));
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 6374b21..060c952 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -102,8 +102,11 @@ void free_initmem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-   if (start  end)
+   if (start  end) {
+   start = _ALIGN_DOWN(start, PAGE_SIZE);
+   end = _ALIGN_UP(end, PAGE_SIZE);
printk (Freeing initrd memory: %ldk freed\n, (end - start)  
10);
+   }
for (; start  end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
init_page_count(virt_to_page(start));
--
1.7.4


___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


RE: [PATCH v3] powerpc: Force page alignment for initrd reserved memory

2011-05-22 Thread Dave Carroll
On Sun, 22 May 2011 about 15:17, Milton Miller wrote:
On Sat, 21 May 2011 about 11:05:27 -0600, Dave Carroll wrote:
 When using 64K pages with a separate cpio rootfs, U-Boot will align
 the rootfs on a 4K page boundary. When the memory is reserved, and
 subsequent early memblock_alloc is called, it will allocate memory
 between the 64K page alignment and reserved memory. When the reserved
 memory is subsequently freed, it is done so by pages, causing the
 early memblock_alloc requests to be re-used, which in my case, caused
 the device-tree to be clobbered.

 This patch forces the reserved memory for initrd to be kernel page
 aligned, and adds the same range extension when freeing initrd.

Getting better, but



 Signed-off-by: Dave Carroll dcarr...@astekcorp.com
 ---
  arch/powerpc/kernel/prom.c |4 +++-
  arch/powerpc/mm/init_32.c  |3 +++
  arch/powerpc/mm/init_64.c  |3 +++
  3 files changed, 9 insertions(+), 1 deletions(-)

 diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
 index 48aeb55..397d4a0 100644
 --- a/arch/powerpc/kernel/prom.c
 +++ b/arch/powerpc/kernel/prom.c
 @@ -555,7 +555,9 @@ static void __init early_reserve_mem(void)
  #ifdef CONFIG_BLK_DEV_INITRD
 /* then reserve the initrd, if any */
 if (initrd_start  (initrd_end  initrd_start))

Here you test the unaligned values

  void free_initrd_mem(unsigned long start, unsigned long end)
  {
 +   start = _ALIGN_DOWN(start, PAGE_SIZE);
 +   end = _ALIGN_UP(end, PAGE_SIZE);
 +
 if (start  end)
 printk (Freeing initrd memory: %ldk freed\n, (end - start) 
  10);

But here you test the aligned values.  And they are aligned with
opposite bias.  Which means that if start == end (or is less than,
but within the same page), a page that wasn't reserved (same
32 and 64 bit) gets freed.


Agreed ... I'll have the but shortly ...

I thought what happens if we are within a page of end, could we
free the last page of bss?, but then I checked vmlinux.lds and we
align end to page size.  I thought other allocations should be safe,
but then remembered:

The flattened device tree (of which we continue to use the string
table after boot) could be a problem.


I had previouly looked at free_initrd_mem, and thought the same conditions
should be used to handle the memory release, but as for the explicit alignment
of the release areas, that seemed to be handled by the fact that all of the
releases are specifically page aligned. The remainder of the free_initrd_mem
routine:

for (; start  end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
init_page_count(virt_to_page(start));
free_page(start);
totalram_pages++;
}

implicitly aligns down start to a page boundary, and also would implicitly align
up the end address. While I would be a proponent of something like;

if (start  (start  end)) do { remainder of free_initrd_mem }

I'm not sure of the goal in explicitly attempting to align the addresses in the
routine as you proposed.

As for the FDT, if the FDT is packed contiguous with initrd, and the alignment 
is on
4K page boundaries, it would have been released before this patch. In my case 
(U-Boot),
they are not near each other.

Thanks,
-Dave

milton

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH v4] powerpc: Force page alignment for initrd reserved memory

2011-05-22 Thread Dave Carroll
When using 64K pages with a separate cpio rootfs, U-Boot will align
the rootfs on a 4K page boundary. When the memory is reserved, and
subsequent early memblock_alloc is called, it will allocate memory
between the 64K page alignment and reserved memory. When the reserved
memory is subsequently freed, it is done so by pages, causing the
early memblock_alloc requests to be re-used, which in my case, caused
the device-tree to be clobbered.

This patch forces the reserved memory for initrd to be kernel page
aligned, and adds the same range extension when freeing initrd.

Signed-off-by: Dave Carroll dcarr...@astekcorp.com
---

* I think this handles Milton's concerns with the exception of
  a packed FDT next to initrd with mismatched page sizes. That
  would require coordination with the bootloader.

 arch/powerpc/kernel/prom.c |4 +++-
 arch/powerpc/mm/init_32.c  |   15 +--
 arch/powerpc/mm/init_64.c  |   15 +--
 3 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 48aeb55..387e5c9 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -555,7 +555,9 @@ static void __init early_reserve_mem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
/* then reserve the initrd, if any */
if (initrd_start  (initrd_end  initrd_start))
-   memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
+   memblock_reserve(_ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE),
+   _ALIGN_UP(initrd_end, PAGE_SIZE) -
+   _ALIGN_DOWN(initrd_start, PAGE_SIZE));
 #endif /* CONFIG_BLK_DEV_INITRD */

 #ifdef CONFIG_PPC32
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index d65b591..1aad444 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -226,13 +226,16 @@ void free_initmem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-   if (start  end)
+   if (start  (start  end)) {
+   start = _ALIGN_DOWN(start, PAGE_SIZE);
+   end = _ALIGN_UP(end, PAGE_SIZE);
printk (Freeing initrd memory: %ldk freed\n, (end - start)  
10);
-   for (; start  end; start += PAGE_SIZE) {
-   ClearPageReserved(virt_to_page(start));
-   init_page_count(virt_to_page(start));
-   free_page(start);
-   totalram_pages++;
+   for (; start  end; start += PAGE_SIZE) {
+   ClearPageReserved(virt_to_page(start));
+   init_page_count(virt_to_page(start));
+   free_page(start);
+   totalram_pages++;
+   }
}
 }
 #endif
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 6374b21..fa9586b 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -102,13 +102,16 @@ void free_initmem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-   if (start  end)
+   if (start  (start  end)) {
+   start = _ALIGN_DOWN(start, PAGE_SIZE);
+   end = _ALIGN_UP(end, PAGE_SIZE);
printk (Freeing initrd memory: %ldk freed\n, (end - start)  
10);
-   for (; start  end; start += PAGE_SIZE) {
-   ClearPageReserved(virt_to_page(start));
-   init_page_count(virt_to_page(start));
-   free_page(start);
-   totalram_pages++;
+   for (; start  end; start += PAGE_SIZE) {
+   ClearPageReserved(virt_to_page(start));
+   init_page_count(virt_to_page(start));
+   free_page(start);
+   totalram_pages++;
+   }
}
 }
 #endif
--
1.7.4

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH v3] powerpc: Force page alignment for initrd reserved memory

2011-05-21 Thread Dave Carroll

When using 64K pages with a separate cpio rootfs, U-Boot will align
the rootfs on a 4K page boundary. When the memory is reserved, and
subsequent early memblock_alloc is called, it will allocate memory
between the 64K page alignment and reserved memory. When the reserved
memory is subsequently freed, it is done so by pages, causing the
early memblock_alloc requests to be re-used, which in my case, caused
the device-tree to be clobbered.

This patch forces the reserved memory for initrd to be kernel page
aligned, and adds the same range extension when freeing initrd.


Signed-off-by: Dave Carroll dcarr...@astekcorp.com
---
 arch/powerpc/kernel/prom.c |4 +++-
 arch/powerpc/mm/init_32.c  |3 +++
 arch/powerpc/mm/init_64.c  |3 +++
 3 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 48aeb55..397d4a0 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -555,7 +555,9 @@ static void __init early_reserve_mem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
/* then reserve the initrd, if any */
if (initrd_start  (initrd_end  initrd_start))
-   memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
+   memblock_reserve(_ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE),
+   _ALIGN_UP(initrd_end, PAGE_SIZE) -
+   _ALIGN_DOWN(initrd_start, PAGE_SIZE));
 #endif /* CONFIG_BLK_DEV_INITRD */

 #ifdef CONFIG_PPC32
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index d65b591..b0791cb 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -226,6 +226,9 @@ void free_initmem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
+   start = _ALIGN_DOWN(start, PAGE_SIZE);
+   end = _ALIGN_UP(end, PAGE_SIZE);
+
if (start  end)
printk (Freeing initrd memory: %ldk freed\n, (end - start)  
10);
for (; start  end; start += PAGE_SIZE) {
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 6374b21..07ae936 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -102,6 +102,9 @@ void free_initmem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
+   start = _ALIGN_DOWN(start, PAGE_SIZE);
+   end = _ALIGN_UP(end, PAGE_SIZE);
+
if (start  end)
printk (Freeing initrd memory: %ldk freed\n, (end - start)  
10);
for (; start  end; start += PAGE_SIZE) {
--
1.7.4
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH]powerpc: Force page alignment for early reserved memory

2011-05-20 Thread Dave Carroll

When using 64K pages with a separate cpio rootfs, U-Boot will align the rootfs 
on a 4K
page boundary. When the memory is reserved, and subsequent early memblock_alloc
is called, it will allocate memory between the 64K page alignment and reserved
memory. When the reserved memory is subsequently freed, it is done so by pages,
causing the early memblock_alloc requests to be re-used, which in my case, 
caused
the device-tree to be clobbered.

This patch forces all early reserved memory to be kernel page aligned, to match
the mechanism used to free reserved memory.

Signed-off-by: Dave Carroll dcarr...@astekcorp.com
---
 arch/powerpc/kernel/prom.c |   21 +
 1 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index e74fa12..2744792 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -534,6 +534,19 @@ void __init early_init_dt_setup_initrd_arch(unsigned long 
start,
 }
 #endif

+static void __init reserve_mem(u64 base, u64 size)
+{
+   u64 top = base + size;
+   if (size == 0)
+   return;
+
+   base = _ALIGN_DOWN(base, PAGE_SIZE);
+   top = _ALIGN_UP(top, PAGE_SIZE);
+   size = top - base;
+   memblock_reserve(base, size);
+
+}
+
 static void __init early_reserve_mem(void)
 {
u64 base, size;
@@ -547,12 +560,12 @@ static void __init early_reserve_mem(void)
/* before we do anything, lets reserve the dt blob */
self_base = __pa((unsigned long)initial_boot_params);
self_size = initial_boot_params-totalsize;
-   memblock_reserve(self_base, self_size);
+   reserve_mem(self_base, self_size);

 #ifdef CONFIG_BLK_DEV_INITRD
/* then reserve the initrd, if any */
if (initrd_start  (initrd_end  initrd_start))
-   memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
+   reserve_mem(__pa(initrd_start), initrd_end - initrd_start);
 #endif /* CONFIG_BLK_DEV_INITRD */

 #ifdef CONFIG_PPC32
@@ -573,7 +586,7 @@ static void __init early_reserve_mem(void)
if (base_32 == self_base  size_32 == self_size)
continue;
DBG(reserving: %x - %x\n, base_32, size_32);
-   memblock_reserve(base_32, size_32);
+   reserve_mem(base_32, size_32);
}
return;
}
@@ -584,7 +597,7 @@ static void __init early_reserve_mem(void)
if (size == 0)
break;
DBG(reserving: %llx - %llx\n, base, size);
-   memblock_reserve(base, size);
+   reserve_mem(base, size);
}
 }

--
1.7.4
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


RE: [PATCH v2]powerpc: Force page alignment for initrd

2011-05-20 Thread Dave Carroll

When using 64K pages with a separate cpio rootfs, U-Boot will align the rootfs
on a 4K page boundary. When the memory is reserved, and subsequent early
memblock_alloc is called, it will allocate memory between the 64K page alignment
and reserved memory. When the reserved memory is subsequently freed, it is done
so by pages, causing the early memblock_alloc requests to be re-used, which in
my case, caused the device-tree to be clobbered.

This patch forces initrd to be kernel page aligned, to match the mechanism used
to free reserved memory.

Signed-off-by: Dave Carroll dcarr...@astekcorp.com
---
 arch/powerpc/kernel/prom.c |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 48aeb55..7e58f6b 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -555,7 +555,8 @@ static void __init early_reserve_mem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
/* then reserve the initrd, if any */
if (initrd_start  (initrd_end  initrd_start))
-   memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
+   memblock_reserve(_ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE),
+   PAGE_ALIGN(initrd_end) - _ALIGN_DOWN(initrd_start, 
PAGE_SIZE));
 #endif /* CONFIG_BLK_DEV_INITRD */

 #ifdef CONFIG_PPC32
--
1.7.4
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev