Merge master.kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6
[linux-2.6.git] / arch / parisc / mm / init.c
index 852eda3..75ea9f2 100644 (file)
@@ -6,10 +6,10 @@
  *    changed by Philipp Rumpf
  *  Copyright 1999 Philipp Rumpf (prumpf@tux.org)
  *  Copyright 2004 Randolph Chung (tausq@debian.org)
+ *  Copyright 2006-2007 Helge Deller (deller@gmx.de)
  *
  */
 
-#include <linux/config.h>
 
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>     /* for release_pages and page_cache_release */
 
 #include <asm/pgalloc.h>
+#include <asm/pgtable.h>
 #include <asm/tlb.h>
 #include <asm/pdc_chassis.h>
 #include <asm/mmzone.h>
+#include <asm/sections.h>
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
-extern char _text;     /* start of kernel code, defined by linker */
 extern int  data_start;
-extern char _end;      /* end of BSS, defined by linker */
-extern char __init_begin, __init_end;
 
 #ifdef CONFIG_DISCONTIGMEM
 struct node_map_data node_data[MAX_NUMNODES] __read_mostly;
@@ -67,11 +66,11 @@ static struct resource sysram_resources[MAX_PHYSMEM_RANGES] __read_mostly;
 physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES] __read_mostly;
 int npmem_ranges __read_mostly;
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define MAX_MEM         (~0UL)
-#else /* !__LP64__ */
+#else /* !CONFIG_64BIT */
 #define MAX_MEM         (3584U*1024U*1024U)
-#endif /* !__LP64__ */
+#endif /* !CONFIG_64BIT */
 
 static unsigned long mem_limit __read_mostly = MAX_MEM;
 
@@ -79,12 +78,11 @@ static void __init mem_limit_func(void)
 {
        char *cp, *end;
        unsigned long limit;
-       extern char saved_command_line[];
 
        /* We need this before __setup() functions are called */
 
        limit = MAX_MEM;
-       for (cp = saved_command_line; *cp; ) {
+       for (cp = boot_command_line; *cp; ) {
                if (memcmp(cp, "mem=", 4) == 0) {
                        cp += 4;
                        limit = memparse(cp, &end);
@@ -318,8 +316,8 @@ static void __init setup_bootmem(void)
 
        reserve_bootmem_node(NODE_DATA(0), 0UL,
                        (unsigned long)(PAGE0->mem_free + PDC_CONSOLE_IO_IODC_SIZE));
-       reserve_bootmem_node(NODE_DATA(0),__pa((unsigned long)&_text),
-                       (unsigned long)(&_end - &_text));
+       reserve_bootmem_node(NODE_DATA(0), __pa((unsigned long)_text),
+                       (unsigned long)(_end - _text));
        reserve_bootmem_node(NODE_DATA(0), (bootmap_start_pfn << PAGE_SHIFT),
                        ((bootmap_pfn - bootmap_start_pfn) << PAGE_SHIFT));
 
@@ -354,8 +352,8 @@ static void __init setup_bootmem(void)
 #endif
 
        data_resource.start =  virt_to_phys(&data_start);
-       data_resource.end = virt_to_phys(&_end)-1;
-       code_resource.start = virt_to_phys(&_text);
+       data_resource.end = virt_to_phys(_end) - 1;
+       code_resource.start = virt_to_phys(_text);
        code_resource.end = virt_to_phys(&data_start)-1;
 
        /* We don't know which region the kernel will be in, so try
@@ -371,8 +369,8 @@ static void __init setup_bootmem(void)
 
 void free_initmem(void)
 {
-       unsigned long addr;
-       
+       unsigned long addr, init_begin, init_end;
+
        printk(KERN_INFO "Freeing unused kernel memory: ");
 
 #ifdef CONFIG_DEBUG_KERNEL
@@ -384,19 +382,22 @@ void free_initmem(void)
         */
        local_irq_disable();
 
-       memset(&__init_begin, 0x00, 
-               (unsigned long)&__init_end - (unsigned long)&__init_begin);
+       memset(__init_begin, 0x00,
+               (unsigned long)__init_end - (unsigned long)__init_begin);
 
        flush_data_cache();
        asm volatile("sync" : : );
-       flush_icache_range((unsigned long)&__init_begin, (unsigned long)&__init_end);
+       flush_icache_range((unsigned long)__init_begin, (unsigned long)__init_end);
        asm volatile("sync" : : );
 
        local_irq_enable();
 #endif
        
-       addr = (unsigned long)(&__init_begin);
-       for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+       /* align __init_begin and __init_end to page size,
+          ignoring linker script where we might have tried to save RAM */
+       init_begin = PAGE_ALIGN((unsigned long)(__init_begin));
+       init_end   = PAGE_ALIGN((unsigned long)(__init_end));
+       for (addr = init_begin; addr < init_end; addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
                init_page_count(virt_to_page(addr));
                free_page(addr);
@@ -407,18 +408,17 @@ void free_initmem(void)
        /* set up a new led state on systems shipped LED State panel */
        pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE);
        
-       printk("%luk freed\n", (unsigned long)(&__init_end - &__init_begin) >> 10);
+       printk("%luk freed\n", (init_end - init_begin) >> 10);
 }
 
 
 #ifdef CONFIG_DEBUG_RODATA
 void mark_rodata_ro(void)
 {
-       extern char __start_rodata, __end_rodata;
        /* rodata memory was already mapped with KERNEL_RO access rights by
            pagetable_init() and map_pages(). No need to do additional stuff here */
        printk (KERN_INFO "Write protecting the kernel read-only data: %luk\n",
-               (unsigned long)(&__end_rodata - &__start_rodata) >> 10);
+               (unsigned long)(__end_rodata - __start_rodata) >> 10);
 }
 #endif
 
@@ -453,6 +453,8 @@ unsigned long pcxl_dma_start __read_mostly;
 
 void __init mem_init(void)
 {
+       int codesize, reservedpages, datasize, initsize;
+
        high_memory = __va((max_pfn << PAGE_SHIFT));
 
 #ifndef CONFIG_DISCONTIGMEM
@@ -467,7 +469,32 @@ void __init mem_init(void)
        }
 #endif
 
-       printk(KERN_INFO "Memory: %luk available\n", num_physpages << (PAGE_SHIFT-10));
+       codesize = (unsigned long)_etext - (unsigned long)_text;
+       datasize = (unsigned long)_edata - (unsigned long)_etext;
+       initsize = (unsigned long)__init_end - (unsigned long)__init_begin;
+
+       reservedpages = 0;
+{
+       unsigned long pfn;
+#ifdef CONFIG_DISCONTIGMEM
+       int i;
+
+       for (i = 0; i < npmem_ranges; i++) {
+               for (pfn = node_start_pfn(i); pfn < node_end_pfn(i); pfn++) {
+                       if (PageReserved(pfn_to_page(pfn)))
+                               reservedpages++;
+               }
+       }
+#else /* !CONFIG_DISCONTIGMEM */
+       for (pfn = 0; pfn < max_pfn; pfn++) {
+               /*
+                * Only count reserved RAM pages
+                */
+               if (PageReserved(pfn_to_page(pfn)))
+                       reservedpages++;
+       }
+#endif
+}
 
 #ifdef CONFIG_PA11
        if (hppa_dma_ops == &pcxl_dma_ops) {
@@ -481,6 +508,38 @@ void __init mem_init(void)
        vmalloc_start = SET_MAP_OFFSET(MAP_START);
 #endif
 
+       printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+               (unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
+               num_physpages << (PAGE_SHIFT-10),
+               codesize >> 10,
+               reservedpages << (PAGE_SHIFT-10),
+               datasize >> 10,
+               initsize >> 10
+       );
+
+#ifdef CONFIG_DEBUG_KERNEL /* double-sanity-check paranoia */
+       printk("virtual kernel memory layout:\n"
+              "    vmalloc : 0x%p - 0x%p   (%4ld MB)\n"
+              "    memory  : 0x%p - 0x%p   (%4ld MB)\n"
+              "      .init : 0x%p - 0x%p   (%4ld kB)\n"
+              "      .data : 0x%p - 0x%p   (%4ld kB)\n"
+              "      .text : 0x%p - 0x%p   (%4ld kB)\n",
+
+              (void*)VMALLOC_START, (void*)VMALLOC_END,
+              (VMALLOC_END - VMALLOC_START) >> 20,
+
+              __va(0), high_memory,
+              ((unsigned long)high_memory - (unsigned long)__va(0)) >> 20,
+
+              __init_begin, __init_end,
+              ((unsigned long)__init_end - (unsigned long)__init_begin) >> 10,
+
+              _etext, _edata,
+              ((unsigned long)_edata - (unsigned long)_etext) >> 10,
+
+              _text, _etext,
+              ((unsigned long)_etext - (unsigned long)_text) >> 10);
+#endif
 }
 
 unsigned long *empty_zero_page __read_mostly;
@@ -548,7 +607,7 @@ void show_mem(void)
 
                                printk("Zone list for zone %d on node %d: ", j, i);
                                for (k = 0; zl->zones[k] != NULL; k++) 
-                                       printk("[%d/%s] ", zl->zones[k]->zone_pgdat->node_id, zl->zones[k]->name);
+                                       printk("[%ld/%s] ", zone_to_nid(zl->zones[k]), zl->zones[k]->name);
                                printk("\n");
                        }
                }
@@ -575,7 +634,7 @@ static void __init map_pages(unsigned long start_vaddr, unsigned long start_padd
        extern const unsigned long fault_vector_20;
        extern void * const linux_gateway_page;
 
-       ro_start = __pa((unsigned long)&_text);
+       ro_start = __pa((unsigned long)_text);
        ro_end   = __pa((unsigned long)&data_start);
        fv_addr  = __pa((unsigned long)&fault_vector_20) & PAGE_MASK;
        gw_addr  = __pa((unsigned long)&linux_gateway_page) & PAGE_MASK;
@@ -639,11 +698,13 @@ static void __init map_pages(unsigned long start_vaddr, unsigned long start_padd
                                 * Map the fault vector writable so we can
                                 * write the HPMC checksum.
                                 */
+#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
                                if (address >= ro_start && address < ro_end
                                                        && address != fv_addr
                                                        && address != gw_addr)
                                    pte = __mk_pte(address, PAGE_KERNEL_RO);
                                else
+#endif
                                    pte = __mk_pte(address, pgprot);
 
                                if (address >= end_paddr)
@@ -804,11 +865,9 @@ void __init paging_init(void)
        flush_tlb_all_local(NULL);
 
        for (i = 0; i < npmem_ranges; i++) {
-               unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0 };
+               unsigned long zones_size[MAX_NR_ZONES] = { 0, };
 
-               /* We have an IOMMU, so all memory can go into a single
-                  ZONE_DMA zone. */
-               zones_size[ZONE_DMA] = pmem_ranges[i].pages;
+               zones_size[ZONE_NORMAL] = pmem_ranges[i].pages;
 
 #ifdef CONFIG_DISCONTIGMEM
                /* Need to initialize the pfnnid_map before we can initialize
@@ -874,8 +933,7 @@ unsigned long alloc_sid(void)
                        flush_tlb_all(); /* flush_tlb_all() calls recycle_sids() */
                        spin_lock(&sid_lock);
                }
-               if (free_space_ids == 0)
-                       BUG();
+               BUG_ON(free_space_ids == 0);
        }
 
        free_space_ids--;
@@ -899,8 +957,7 @@ void free_sid(unsigned long spaceid)
 
        spin_lock(&sid_lock);
 
-       if (*dirty_space_offset & (1L << index))
-           BUG(); /* attempt to free space id twice */
+       BUG_ON(*dirty_space_offset & (1L << index)); /* attempt to free space id twice */
 
        *dirty_space_offset |= (1L << index);
        dirty_space_ids++;
@@ -975,7 +1032,7 @@ static void recycle_sids(void)
 
 static unsigned long recycle_ndirty;
 static unsigned long recycle_dirty_array[SID_ARRAY_SIZE];
-static unsigned int recycle_inuse = 0;
+static unsigned int recycle_inuse;
 
 void flush_tlb_all(void)
 {
@@ -984,9 +1041,7 @@ void flush_tlb_all(void)
        do_recycle = 0;
        spin_lock(&sid_lock);
        if (dirty_space_ids > RECYCLE_THRESHOLD) {
-           if (recycle_inuse) {
-               BUG();  /* FIXME: Use a semaphore/wait queue here */
-           }
+           BUG_ON(recycle_inuse);  /* FIXME: Use a semaphore/wait queue here */
            get_dirty_sids(&recycle_ndirty,recycle_dirty_array);
            recycle_inuse++;
            do_recycle++;
@@ -1013,9 +1068,9 @@ void flush_tlb_all(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-#if 0
-       if (start < end)
-               printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+       if (start >= end)
+               return;
+       printk(KERN_INFO "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));
@@ -1023,6 +1078,5 @@ void free_initrd_mem(unsigned long start, unsigned long end)
                num_physpages++;
                totalram_pages++;
        }
-#endif
 }
 #endif