[patch 34/50] SPARC64: Fix "mem=xxx" handling.

2007-01-05 Thread Chris Wright
-stable review patch.  If anyone has any objections, please let us know.
--

From: David Miller <[EMAIL PROTECTED]>

We were not being careful enough.  When we trim the physical
memory areas, we have to make sure we don't remove the kernel
image or initial ramdisk image ranges.

Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
Signed-off-by: Chris Wright <[EMAIL PROTECTED]>

---
 arch/sparc64/mm/init.c |  147 +
 1 file changed, 124 insertions(+), 23 deletions(-)

--- linux-2.6.19.1.orig/arch/sparc64/mm/init.c
+++ linux-2.6.19.1/arch/sparc64/mm/init.c
@@ -872,6 +872,115 @@ static unsigned long __init choose_bootm
prom_halt();
 }
 
+static void __init trim_pavail(unsigned long *cur_size_p,
+  unsigned long *end_of_phys_p)
+{
+   unsigned long to_trim = *cur_size_p - cmdline_memory_size;
+   unsigned long avoid_start, avoid_end;
+   int i;
+
+   to_trim = PAGE_ALIGN(to_trim);
+
+   avoid_start = avoid_end = 0;
+#ifdef CONFIG_BLK_DEV_INITRD
+   avoid_start = initrd_start;
+   avoid_end = PAGE_ALIGN(initrd_end);
+#endif
+
+   /* Trim some pavail[] entries in order to satisfy the
+* requested "mem=xxx" kernel command line specification.
+*
+* We must not trim off the kernel image area nor the
+* initial ramdisk range (if any).  Also, we must not trim
+* any pavail[] entry down to zero in order to preserve
+* the invariant that all pavail[] entries have a non-zero
+* size which is assumed by all of the code in here.
+*/
+   for (i = 0; i < pavail_ents; i++) {
+   unsigned long start, end, kern_end;
+   unsigned long trim_low, trim_high, n;
+
+   kern_end = PAGE_ALIGN(kern_base + kern_size);
+
+   trim_low = start = pavail[i].phys_addr;
+   trim_high = end = start + pavail[i].reg_size;
+
+   if (kern_base >= start &&
+   kern_base < end) {
+   trim_low = kern_base;
+   if (kern_end >= end)
+   continue;
+   }
+   if (kern_end >= start &&
+   kern_end < end) {
+   trim_high = kern_end;
+   }
+   if (avoid_start &&
+   avoid_start >= start &&
+   avoid_start < end) {
+   if (trim_low > avoid_start)
+   trim_low = avoid_start;
+   if (avoid_end >= end)
+   continue;
+   }
+   if (avoid_end &&
+   avoid_end >= start &&
+   avoid_end < end) {
+   if (trim_high < avoid_end)
+   trim_high = avoid_end;
+   }
+
+   if (trim_high <= trim_low)
+   continue;
+
+   if (trim_low == start && trim_high == end) {
+   /* Whole chunk is available for trimming.
+* Trim all except one page, in order to keep
+* entry non-empty.
+*/
+   n = (end - start) - PAGE_SIZE;
+   if (n > to_trim)
+   n = to_trim;
+
+   if (n) {
+   pavail[i].phys_addr += n;
+   pavail[i].reg_size -= n;
+   to_trim -= n;
+   }
+   } else {
+   n = (trim_low - start);
+   if (n > to_trim)
+   n = to_trim;
+
+   if (n) {
+   pavail[i].phys_addr += n;
+   pavail[i].reg_size -= n;
+   to_trim -= n;
+   }
+   if (to_trim) {
+   n = end - trim_high;
+   if (n > to_trim)
+   n = to_trim;
+   if (n) {
+   pavail[i].reg_size -= n;
+   to_trim -= n;
+   }
+   }
+   }
+
+   if (!to_trim)
+   break;
+   }
+
+   /* Recalculate.  */
+   *cur_size_p = 0UL;
+   for (i = 0; i < pavail_ents; i++) {
+   *end_of_phys_p = pavail[i].phys_addr +
+   pavail[i].reg_size;
+   *cur_size_p += pavail[i].reg_size;
+   }
+}
+
 static unsigned long __init bootmem_init(unsigned long *pages_avail,
 unsigned long phys_base)
 {
@@ -889,31 +998,13 @@ static unsigned long __init bootmem_init
  

[patch 34/50] SPARC64: Fix mem=xxx handling.

2007-01-05 Thread Chris Wright
-stable review patch.  If anyone has any objections, please let us know.
--

From: David Miller [EMAIL PROTECTED]

We were not being careful enough.  When we trim the physical
memory areas, we have to make sure we don't remove the kernel
image or initial ramdisk image ranges.

Signed-off-by: David S. Miller [EMAIL PROTECTED]
Signed-off-by: Chris Wright [EMAIL PROTECTED]

---
 arch/sparc64/mm/init.c |  147 +
 1 file changed, 124 insertions(+), 23 deletions(-)

--- linux-2.6.19.1.orig/arch/sparc64/mm/init.c
+++ linux-2.6.19.1/arch/sparc64/mm/init.c
@@ -872,6 +872,115 @@ static unsigned long __init choose_bootm
prom_halt();
 }
 
+static void __init trim_pavail(unsigned long *cur_size_p,
+  unsigned long *end_of_phys_p)
+{
+   unsigned long to_trim = *cur_size_p - cmdline_memory_size;
+   unsigned long avoid_start, avoid_end;
+   int i;
+
+   to_trim = PAGE_ALIGN(to_trim);
+
+   avoid_start = avoid_end = 0;
+#ifdef CONFIG_BLK_DEV_INITRD
+   avoid_start = initrd_start;
+   avoid_end = PAGE_ALIGN(initrd_end);
+#endif
+
+   /* Trim some pavail[] entries in order to satisfy the
+* requested mem=xxx kernel command line specification.
+*
+* We must not trim off the kernel image area nor the
+* initial ramdisk range (if any).  Also, we must not trim
+* any pavail[] entry down to zero in order to preserve
+* the invariant that all pavail[] entries have a non-zero
+* size which is assumed by all of the code in here.
+*/
+   for (i = 0; i  pavail_ents; i++) {
+   unsigned long start, end, kern_end;
+   unsigned long trim_low, trim_high, n;
+
+   kern_end = PAGE_ALIGN(kern_base + kern_size);
+
+   trim_low = start = pavail[i].phys_addr;
+   trim_high = end = start + pavail[i].reg_size;
+
+   if (kern_base = start 
+   kern_base  end) {
+   trim_low = kern_base;
+   if (kern_end = end)
+   continue;
+   }
+   if (kern_end = start 
+   kern_end  end) {
+   trim_high = kern_end;
+   }
+   if (avoid_start 
+   avoid_start = start 
+   avoid_start  end) {
+   if (trim_low  avoid_start)
+   trim_low = avoid_start;
+   if (avoid_end = end)
+   continue;
+   }
+   if (avoid_end 
+   avoid_end = start 
+   avoid_end  end) {
+   if (trim_high  avoid_end)
+   trim_high = avoid_end;
+   }
+
+   if (trim_high = trim_low)
+   continue;
+
+   if (trim_low == start  trim_high == end) {
+   /* Whole chunk is available for trimming.
+* Trim all except one page, in order to keep
+* entry non-empty.
+*/
+   n = (end - start) - PAGE_SIZE;
+   if (n  to_trim)
+   n = to_trim;
+
+   if (n) {
+   pavail[i].phys_addr += n;
+   pavail[i].reg_size -= n;
+   to_trim -= n;
+   }
+   } else {
+   n = (trim_low - start);
+   if (n  to_trim)
+   n = to_trim;
+
+   if (n) {
+   pavail[i].phys_addr += n;
+   pavail[i].reg_size -= n;
+   to_trim -= n;
+   }
+   if (to_trim) {
+   n = end - trim_high;
+   if (n  to_trim)
+   n = to_trim;
+   if (n) {
+   pavail[i].reg_size -= n;
+   to_trim -= n;
+   }
+   }
+   }
+
+   if (!to_trim)
+   break;
+   }
+
+   /* Recalculate.  */
+   *cur_size_p = 0UL;
+   for (i = 0; i  pavail_ents; i++) {
+   *end_of_phys_p = pavail[i].phys_addr +
+   pavail[i].reg_size;
+   *cur_size_p += pavail[i].reg_size;
+   }
+}
+
 static unsigned long __init bootmem_init(unsigned long *pages_avail,
 unsigned long phys_base)
 {
@@ -889,31 +998,13 @@ static unsigned long __init bootmem_init
end_of_phys_memory =