1/* 2 * linux/arch/m32r/mm/discontig.c 3 * 4 * Discontig memory support 5 * 6 * Copyright (c) 2003 Hitoshi Yamamoto 7 */ 8 9#include <linux/mm.h> 10#include <linux/bootmem.h> 11#include <linux/mmzone.h> 12#include <linux/initrd.h> 13#include <linux/nodemask.h> 14#include <linux/module.h> 15#include <linux/pfn.h> 16 17#include <asm/setup.h> 18 19extern char _end[]; 20 21struct pglist_data *node_data[MAX_NUMNODES]; 22EXPORT_SYMBOL(node_data); 23 24pg_data_t m32r_node_data[MAX_NUMNODES]; 25 26/* Memory profile */ 27typedef struct { 28 unsigned long start_pfn; 29 unsigned long pages; 30 unsigned long holes; 31 unsigned long free_pfn; 32} mem_prof_t; 33static mem_prof_t mem_prof[MAX_NUMNODES]; 34 35extern unsigned long memory_start; 36extern unsigned long memory_end; 37 38static void __init mem_prof_init(void) 39{ 40 unsigned long start_pfn, holes, free_pfn; 41 const unsigned long zone_alignment = 1UL << (MAX_ORDER - 1); 42 unsigned long ul; 43 mem_prof_t *mp; 44 45 /* Node#0 SDRAM */ 46 mp = &mem_prof[0]; 47 mp->start_pfn = PFN_UP(CONFIG_MEMORY_START); 48 mp->pages = PFN_DOWN(memory_end - memory_start); 49 mp->holes = 0; 50 mp->free_pfn = PFN_UP(__pa(_end)); 51 52 /* Node#1 internal SRAM */ 53 mp = &mem_prof[1]; 54 start_pfn = free_pfn = PFN_UP(CONFIG_IRAM_START); 55 holes = 0; 56 if (start_pfn & (zone_alignment - 1)) { 57 ul = zone_alignment; 58 while (start_pfn >= ul) 59 ul += zone_alignment; 60 61 start_pfn = ul - zone_alignment; 62 holes = free_pfn - start_pfn; 63 } 64 65 mp->start_pfn = start_pfn; 66 mp->pages = PFN_DOWN(CONFIG_IRAM_SIZE) + holes; 67 mp->holes = holes; 68 mp->free_pfn = PFN_UP(CONFIG_IRAM_START); 69} 70 71unsigned long __init setup_memory(void) 72{ 73 unsigned long bootmap_size; 74 unsigned long min_pfn; 75 int nid; 76 mem_prof_t *mp; 77 78 max_low_pfn = 0; 79 min_low_pfn = -1; 80 81 mem_prof_init(); 82 83 for_each_online_node(nid) { 84 mp = &mem_prof[nid]; 85 NODE_DATA(nid)=(pg_data_t *)&m32r_node_data[nid]; 86 NODE_DATA(nid)->bdata = &bootmem_node_data[nid]; 87 min_pfn = mp->start_pfn; 88 max_pfn = mp->start_pfn + mp->pages; 89 bootmap_size = init_bootmem_node(NODE_DATA(nid), mp->free_pfn, 90 mp->start_pfn, max_pfn); 91 92 free_bootmem_node(NODE_DATA(nid), PFN_PHYS(mp->start_pfn), 93 PFN_PHYS(mp->pages)); 94 95 reserve_bootmem_node(NODE_DATA(nid), PFN_PHYS(mp->start_pfn), 96 PFN_PHYS(mp->free_pfn - mp->start_pfn) + bootmap_size, 97 BOOTMEM_DEFAULT); 98 99 if (max_low_pfn < max_pfn) 100 max_low_pfn = max_pfn; 101 102 if (min_low_pfn > min_pfn) 103 min_low_pfn = min_pfn; 104 } 105 106#ifdef CONFIG_BLK_DEV_INITRD 107 if (LOADER_TYPE && INITRD_START) { 108 if (INITRD_START + INITRD_SIZE <= PFN_PHYS(max_low_pfn)) { 109 reserve_bootmem_node(NODE_DATA(0), INITRD_START, 110 INITRD_SIZE, BOOTMEM_DEFAULT); 111 initrd_start = INITRD_START + PAGE_OFFSET; 112 initrd_end = initrd_start + INITRD_SIZE; 113 printk("initrd:start[%08lx],size[%08lx]\n", 114 initrd_start, INITRD_SIZE); 115 } else { 116 printk("initrd extends beyond end of memory " 117 "(0x%08lx > 0x%08llx)\ndisabling initrd\n", 118 INITRD_START + INITRD_SIZE, 119 (unsigned long long)PFN_PHYS(max_low_pfn)); 120 121 initrd_start = 0; 122 } 123 } 124#endif /* CONFIG_BLK_DEV_INITRD */ 125 126 return max_low_pfn; 127} 128 129#define START_PFN(nid) (NODE_DATA(nid)->bdata->node_min_pfn) 130#define MAX_LOW_PFN(nid) (NODE_DATA(nid)->bdata->node_low_pfn) 131 132void __init zone_sizes_init(void) 133{ 134 unsigned long zones_size[MAX_NR_ZONES], zholes_size[MAX_NR_ZONES]; 135 unsigned long low, start_pfn; 136 int nid, i; 137 mem_prof_t *mp; 138 139 for_each_online_node(nid) { 140 mp = &mem_prof[nid]; 141 for (i = 0 ; i < MAX_NR_ZONES ; i++) { 142 zones_size[i] = 0; 143 zholes_size[i] = 0; 144 } 145 start_pfn = START_PFN(nid); 146 low = MAX_LOW_PFN(nid); 147 zones_size[ZONE_DMA] = low - start_pfn; 148 zholes_size[ZONE_DMA] = mp->holes; 149 150 node_set_state(nid, N_NORMAL_MEMORY); 151 free_area_init_node(nid, zones_size, start_pfn, zholes_size); 152 } 153 154 /* 155 * For test 156 * Use all area of internal RAM. 157 * see __alloc_pages() 158 */ 159 NODE_DATA(1)->node_zones->watermark[WMARK_MIN] = 0; 160 NODE_DATA(1)->node_zones->watermark[WMARK_LOW] = 0; 161 NODE_DATA(1)->node_zones->watermark[WMARK_HIGH] = 0; 162} 163