diff options
Diffstat (limited to 'arch/mips/kernel/setup.c')
| -rw-r--r-- | arch/mips/kernel/setup.c | 439 |
1 files changed, 187 insertions, 252 deletions
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 8c2b596a136f..fdbb508661c5 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c | |||
| @@ -10,29 +10,15 @@ | |||
| 10 | * Copyright (C) 1999 Silicon Graphics, Inc. | 10 | * Copyright (C) 1999 Silicon Graphics, Inc. |
| 11 | * Copyright (C) 2000 2001, 2002 Maciej W. Rozycki | 11 | * Copyright (C) 2000 2001, 2002 Maciej W. Rozycki |
| 12 | */ | 12 | */ |
| 13 | #include <linux/errno.h> | ||
| 14 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 15 | #include <linux/ioport.h> | 14 | #include <linux/ioport.h> |
| 16 | #include <linux/sched.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/mm.h> | ||
| 19 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 20 | #include <linux/stddef.h> | ||
| 21 | #include <linux/string.h> | ||
| 22 | #include <linux/unistd.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/user.h> | ||
| 25 | #include <linux/utsname.h> | ||
| 26 | #include <linux/a.out.h> | ||
| 27 | #include <linux/screen_info.h> | 16 | #include <linux/screen_info.h> |
| 28 | #include <linux/bootmem.h> | 17 | #include <linux/bootmem.h> |
| 29 | #include <linux/initrd.h> | 18 | #include <linux/initrd.h> |
| 30 | #include <linux/major.h> | ||
| 31 | #include <linux/kdev_t.h> | ||
| 32 | #include <linux/root_dev.h> | 19 | #include <linux/root_dev.h> |
| 33 | #include <linux/highmem.h> | 20 | #include <linux/highmem.h> |
| 34 | #include <linux/console.h> | 21 | #include <linux/console.h> |
| 35 | #include <linux/mmzone.h> | ||
| 36 | #include <linux/pfn.h> | 22 | #include <linux/pfn.h> |
| 37 | 23 | ||
| 38 | #include <asm/addrspace.h> | 24 | #include <asm/addrspace.h> |
| @@ -96,6 +82,12 @@ void __init add_memory_region(phys_t start, phys_t size, long type) | |||
| 96 | int x = boot_mem_map.nr_map; | 82 | int x = boot_mem_map.nr_map; |
| 97 | struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1; | 83 | struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1; |
| 98 | 84 | ||
| 85 | /* Sanity check */ | ||
| 86 | if (start + size < start) { | ||
| 87 | printk("Trying to add an invalid memory region, skipped\n"); | ||
| 88 | return; | ||
| 89 | } | ||
| 90 | |||
| 99 | /* | 91 | /* |
| 100 | * Try to merge with previous entry if any. This is far less than | 92 | * Try to merge with previous entry if any. This is far less than |
| 101 | * perfect but is sufficient for most real world cases. | 93 | * perfect but is sufficient for most real world cases. |
| @@ -143,167 +135,132 @@ static void __init print_memory_map(void) | |||
| 143 | } | 135 | } |
| 144 | } | 136 | } |
| 145 | 137 | ||
| 146 | static inline void parse_cmdline_early(void) | 138 | /* |
| 139 | * Manage initrd | ||
| 140 | */ | ||
| 141 | #ifdef CONFIG_BLK_DEV_INITRD | ||
| 142 | |||
| 143 | static int __init rd_start_early(char *p) | ||
| 147 | { | 144 | { |
| 148 | char c = ' ', *to = command_line, *from = saved_command_line; | 145 | unsigned long start = memparse(p, &p); |
| 149 | unsigned long start_at, mem_size; | ||
| 150 | int len = 0; | ||
| 151 | int usermem = 0; | ||
| 152 | 146 | ||
| 153 | printk("Determined physical RAM map:\n"); | 147 | #ifdef CONFIG_64BIT |
| 154 | print_memory_map(); | 148 | /* HACK: Guess if the sign extension was forgotten */ |
| 149 | if (start > 0x0000000080000000 && start < 0x00000000ffffffff) | ||
| 150 | start |= 0xffffffff00000000UL; | ||
| 151 | #endif | ||
| 152 | initrd_start = start; | ||
| 153 | initrd_end += start; | ||
| 155 | 154 | ||
| 156 | for (;;) { | 155 | return 0; |
| 157 | /* | 156 | } |
| 158 | * "mem=XXX[kKmM]" defines a memory region from | 157 | early_param("rd_start", rd_start_early); |
| 159 | * 0 to <XXX>, overriding the determined size. | ||
| 160 | * "mem=XXX[KkmM]@YYY[KkmM]" defines a memory region from | ||
| 161 | * <YYY> to <YYY>+<XXX>, overriding the determined size. | ||
| 162 | */ | ||
| 163 | if (c == ' ' && !memcmp(from, "mem=", 4)) { | ||
| 164 | if (to != command_line) | ||
| 165 | to--; | ||
| 166 | /* | ||
| 167 | * If a user specifies memory size, we | ||
| 168 | * blow away any automatically generated | ||
| 169 | * size. | ||
| 170 | */ | ||
| 171 | if (usermem == 0) { | ||
| 172 | boot_mem_map.nr_map = 0; | ||
| 173 | usermem = 1; | ||
| 174 | } | ||
| 175 | mem_size = memparse(from + 4, &from); | ||
| 176 | if (*from == '@') | ||
| 177 | start_at = memparse(from + 1, &from); | ||
| 178 | else | ||
| 179 | start_at = 0; | ||
| 180 | add_memory_region(start_at, mem_size, BOOT_MEM_RAM); | ||
| 181 | } | ||
| 182 | c = *(from++); | ||
| 183 | if (!c) | ||
| 184 | break; | ||
| 185 | if (CL_SIZE <= ++len) | ||
| 186 | break; | ||
| 187 | *(to++) = c; | ||
| 188 | } | ||
| 189 | *to = '\0'; | ||
| 190 | 158 | ||
| 191 | if (usermem) { | 159 | static int __init rd_size_early(char *p) |
| 192 | printk("User-defined physical RAM map:\n"); | 160 | { |
| 193 | print_memory_map(); | 161 | initrd_end += memparse(p, &p); |
| 194 | } | 162 | |
| 163 | return 0; | ||
| 195 | } | 164 | } |
| 165 | early_param("rd_size", rd_size_early); | ||
| 196 | 166 | ||
| 197 | static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end) | 167 | static unsigned long __init init_initrd(void) |
| 198 | { | 168 | { |
| 169 | unsigned long tmp, end, size; | ||
| 170 | u32 *initrd_header; | ||
| 171 | |||
| 172 | ROOT_DEV = Root_RAM0; | ||
| 173 | |||
| 199 | /* | 174 | /* |
| 200 | * "rd_start=0xNNNNNNNN" defines the memory address of an initrd | 175 | * Board specific code or command line parser should have |
| 201 | * "rd_size=0xNN" it's size | 176 | * already set up initrd_start and initrd_end. In these cases |
| 177 | * perfom sanity checks and use them if all looks good. | ||
| 202 | */ | 178 | */ |
| 203 | unsigned long start = 0; | 179 | size = initrd_end - initrd_start; |
| 204 | unsigned long size = 0; | 180 | if (initrd_end == 0 || size == 0) { |
| 205 | unsigned long end; | 181 | initrd_start = 0; |
| 206 | char cmd_line[CL_SIZE]; | 182 | initrd_end = 0; |
| 207 | char *start_str; | 183 | } else |
| 208 | char *size_str; | 184 | return initrd_end; |
| 209 | char *tmp; | 185 | |
| 210 | 186 | end = (unsigned long)&_end; | |
| 211 | strcpy(cmd_line, command_line); | 187 | tmp = PAGE_ALIGN(end) - sizeof(u32) * 2; |
| 212 | *command_line = 0; | 188 | if (tmp < end) |
| 213 | tmp = cmd_line; | 189 | tmp += PAGE_SIZE; |
| 214 | /* Ignore "rd_start=" strings in other parameters. */ | 190 | |
| 215 | start_str = strstr(cmd_line, "rd_start="); | 191 | initrd_header = (u32 *)tmp; |
| 216 | if (start_str && start_str != cmd_line && *(start_str - 1) != ' ') | 192 | if (initrd_header[0] == 0x494E5244) { |
| 217 | start_str = strstr(start_str, " rd_start="); | 193 | initrd_start = (unsigned long)&initrd_header[2]; |
| 218 | while (start_str) { | 194 | initrd_end = initrd_start + initrd_header[1]; |
| 219 | if (start_str != cmd_line) | ||
| 220 | strncat(command_line, tmp, start_str - tmp); | ||
| 221 | start = memparse(start_str + 9, &start_str); | ||
| 222 | tmp = start_str + 1; | ||
| 223 | start_str = strstr(start_str, " rd_start="); | ||
| 224 | } | 195 | } |
| 225 | if (*tmp) | 196 | return initrd_end; |
| 226 | strcat(command_line, tmp); | 197 | } |
| 227 | 198 | ||
| 228 | strcpy(cmd_line, command_line); | 199 | static void __init finalize_initrd(void) |
| 229 | *command_line = 0; | 200 | { |
| 230 | tmp = cmd_line; | 201 | unsigned long size = initrd_end - initrd_start; |
| 231 | /* Ignore "rd_size" strings in other parameters. */ | 202 | |
| 232 | size_str = strstr(cmd_line, "rd_size="); | 203 | if (size == 0) { |
| 233 | if (size_str && size_str != cmd_line && *(size_str - 1) != ' ') | 204 | printk(KERN_INFO "Initrd not found or empty"); |
| 234 | size_str = strstr(size_str, " rd_size="); | 205 | goto disable; |
| 235 | while (size_str) { | 206 | } |
| 236 | if (size_str != cmd_line) | 207 | if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) { |
| 237 | strncat(command_line, tmp, size_str - tmp); | 208 | printk("Initrd extends beyond end of memory"); |
| 238 | size = memparse(size_str + 8, &size_str); | 209 | goto disable; |
| 239 | tmp = size_str + 1; | ||
| 240 | size_str = strstr(size_str, " rd_size="); | ||
| 241 | } | 210 | } |
| 242 | if (*tmp) | ||
| 243 | strcat(command_line, tmp); | ||
| 244 | 211 | ||
| 245 | #ifdef CONFIG_64BIT | 212 | reserve_bootmem(CPHYSADDR(initrd_start), size); |
| 246 | /* HACK: Guess if the sign extension was forgotten */ | 213 | initrd_below_start_ok = 1; |
| 247 | if (start > 0x0000000080000000 && start < 0x00000000ffffffff) | 214 | |
| 248 | start |= 0xffffffff00000000UL; | 215 | printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n", |
| 216 | initrd_start, size); | ||
| 217 | return; | ||
| 218 | disable: | ||
| 219 | printk(" - disabling initrd\n"); | ||
| 220 | initrd_start = 0; | ||
| 221 | initrd_end = 0; | ||
| 222 | } | ||
| 223 | |||
| 224 | #else /* !CONFIG_BLK_DEV_INITRD */ | ||
| 225 | |||
| 226 | #define init_initrd() 0 | ||
| 227 | #define finalize_initrd() do {} while (0) | ||
| 228 | |||
| 249 | #endif | 229 | #endif |
| 250 | 230 | ||
| 251 | end = start + size; | 231 | /* |
| 252 | if (start && end) { | 232 | * Initialize the bootmem allocator. It also setup initrd related data |
| 253 | *rd_start = start; | 233 | * if needed. |
| 254 | *rd_end = end; | 234 | */ |
| 255 | return 1; | 235 | #ifdef CONFIG_SGI_IP27 |
| 256 | } | 236 | |
| 257 | return 0; | 237 | static void __init bootmem_init(void) |
| 238 | { | ||
| 239 | init_initrd(); | ||
| 240 | finalize_initrd(); | ||
| 258 | } | 241 | } |
| 259 | 242 | ||
| 260 | #define MAXMEM HIGHMEM_START | 243 | #else /* !CONFIG_SGI_IP27 */ |
| 261 | #define MAXMEM_PFN PFN_DOWN(MAXMEM) | ||
| 262 | 244 | ||
| 263 | static inline void bootmem_init(void) | 245 | static void __init bootmem_init(void) |
| 264 | { | 246 | { |
| 265 | unsigned long start_pfn; | 247 | unsigned long reserved_end; |
| 266 | unsigned long reserved_end = (unsigned long)&_end; | 248 | unsigned long highest = 0; |
| 267 | #ifndef CONFIG_SGI_IP27 | 249 | unsigned long mapstart = -1UL; |
| 268 | unsigned long first_usable_pfn; | ||
| 269 | unsigned long bootmap_size; | 250 | unsigned long bootmap_size; |
| 270 | int i; | 251 | int i; |
| 271 | #endif | ||
| 272 | #ifdef CONFIG_BLK_DEV_INITRD | ||
| 273 | int initrd_reserve_bootmem = 0; | ||
| 274 | |||
| 275 | /* Board specific code should have set up initrd_start and initrd_end */ | ||
| 276 | ROOT_DEV = Root_RAM0; | ||
| 277 | if (parse_rd_cmdline(&initrd_start, &initrd_end)) { | ||
| 278 | reserved_end = max(reserved_end, initrd_end); | ||
| 279 | initrd_reserve_bootmem = 1; | ||
| 280 | } else { | ||
| 281 | unsigned long tmp; | ||
| 282 | u32 *initrd_header; | ||
| 283 | |||
| 284 | tmp = ((reserved_end + PAGE_SIZE-1) & PAGE_MASK) - sizeof(u32) * 2; | ||
| 285 | if (tmp < reserved_end) | ||
| 286 | tmp += PAGE_SIZE; | ||
| 287 | initrd_header = (u32 *)tmp; | ||
| 288 | if (initrd_header[0] == 0x494E5244) { | ||
| 289 | initrd_start = (unsigned long)&initrd_header[2]; | ||
| 290 | initrd_end = initrd_start + initrd_header[1]; | ||
| 291 | reserved_end = max(reserved_end, initrd_end); | ||
| 292 | initrd_reserve_bootmem = 1; | ||
| 293 | } | ||
| 294 | } | ||
| 295 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
| 296 | 252 | ||
| 297 | /* | 253 | /* |
| 298 | * Partially used pages are not usable - thus | 254 | * Init any data related to initrd. It's a nop if INITRD is |
| 299 | * we are rounding upwards. | 255 | * not selected. Once that done we can determine the low bound |
| 256 | * of usable memory. | ||
| 300 | */ | 257 | */ |
| 301 | start_pfn = PFN_UP(CPHYSADDR(reserved_end)); | 258 | reserved_end = init_initrd(); |
| 259 | reserved_end = PFN_UP(CPHYSADDR(max(reserved_end, (unsigned long)&_end))); | ||
| 302 | 260 | ||
| 303 | #ifndef CONFIG_SGI_IP27 | 261 | /* |
| 304 | /* Find the highest page frame number we have available. */ | 262 | * Find the highest page frame number we have available. |
| 305 | max_pfn = 0; | 263 | */ |
| 306 | first_usable_pfn = -1UL; | ||
| 307 | for (i = 0; i < boot_mem_map.nr_map; i++) { | 264 | for (i = 0; i < boot_mem_map.nr_map; i++) { |
| 308 | unsigned long start, end; | 265 | unsigned long start, end; |
| 309 | 266 | ||
| @@ -312,56 +269,38 @@ static inline void bootmem_init(void) | |||
| 312 | 269 | ||
| 313 | start = PFN_UP(boot_mem_map.map[i].addr); | 270 | start = PFN_UP(boot_mem_map.map[i].addr); |
| 314 | end = PFN_DOWN(boot_mem_map.map[i].addr | 271 | end = PFN_DOWN(boot_mem_map.map[i].addr |
| 315 | + boot_mem_map.map[i].size); | 272 | + boot_mem_map.map[i].size); |
| 316 | 273 | ||
| 317 | if (start >= end) | 274 | if (end > highest) |
| 275 | highest = end; | ||
| 276 | if (end <= reserved_end) | ||
| 318 | continue; | 277 | continue; |
| 319 | if (end > max_pfn) | 278 | if (start >= mapstart) |
| 320 | max_pfn = end; | 279 | continue; |
| 321 | if (start < first_usable_pfn) { | 280 | mapstart = max(reserved_end, start); |
| 322 | if (start > start_pfn) { | ||
| 323 | first_usable_pfn = start; | ||
| 324 | } else if (end > start_pfn) { | ||
| 325 | first_usable_pfn = start_pfn; | ||
| 326 | } | ||
| 327 | } | ||
| 328 | } | 281 | } |
| 329 | 282 | ||
| 330 | /* | 283 | /* |
| 331 | * Determine low and high memory ranges | 284 | * Determine low and high memory ranges |
| 332 | */ | 285 | */ |
| 333 | max_low_pfn = max_pfn; | 286 | if (highest > PFN_DOWN(HIGHMEM_START)) { |
| 334 | if (max_low_pfn > MAXMEM_PFN) { | 287 | #ifdef CONFIG_HIGHMEM |
| 335 | max_low_pfn = MAXMEM_PFN; | 288 | highstart_pfn = PFN_DOWN(HIGHMEM_START); |
| 336 | #ifndef CONFIG_HIGHMEM | 289 | highend_pfn = highest; |
| 337 | /* Maximum memory usable is what is directly addressable */ | ||
| 338 | printk(KERN_WARNING "Warning only %ldMB will be used.\n", | ||
| 339 | MAXMEM >> 20); | ||
| 340 | printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); | ||
| 341 | #endif | 290 | #endif |
| 291 | highest = PFN_DOWN(HIGHMEM_START); | ||
| 342 | } | 292 | } |
| 343 | 293 | ||
| 344 | #ifdef CONFIG_HIGHMEM | ||
| 345 | /* | 294 | /* |
| 346 | * Crude, we really should make a better attempt at detecting | 295 | * Initialize the boot-time allocator with low memory only. |
| 347 | * highstart_pfn | ||
| 348 | */ | 296 | */ |
| 349 | highstart_pfn = highend_pfn = max_pfn; | 297 | bootmap_size = init_bootmem(mapstart, highest); |
| 350 | if (max_pfn > MAXMEM_PFN) { | ||
| 351 | highstart_pfn = MAXMEM_PFN; | ||
| 352 | printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", | ||
| 353 | (highend_pfn - highstart_pfn) >> (20 - PAGE_SHIFT)); | ||
| 354 | } | ||
| 355 | #endif | ||
| 356 | |||
| 357 | /* Initialize the boot-time allocator with low memory only. */ | ||
| 358 | bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn); | ||
| 359 | 298 | ||
| 360 | /* | 299 | /* |
| 361 | * Register fully available low RAM pages with the bootmem allocator. | 300 | * Register fully available low RAM pages with the bootmem allocator. |
| 362 | */ | 301 | */ |
| 363 | for (i = 0; i < boot_mem_map.nr_map; i++) { | 302 | for (i = 0; i < boot_mem_map.nr_map; i++) { |
| 364 | unsigned long curr_pfn, last_pfn, size; | 303 | unsigned long start, end, size; |
| 365 | 304 | ||
| 366 | /* | 305 | /* |
| 367 | * Reserve usable memory. | 306 | * Reserve usable memory. |
| @@ -369,85 +308,50 @@ static inline void bootmem_init(void) | |||
| 369 | if (boot_mem_map.map[i].type != BOOT_MEM_RAM) | 308 | if (boot_mem_map.map[i].type != BOOT_MEM_RAM) |
| 370 | continue; | 309 | continue; |
| 371 | 310 | ||
| 372 | /* | 311 | start = PFN_UP(boot_mem_map.map[i].addr); |
| 373 | * We are rounding up the start address of usable memory: | 312 | end = PFN_DOWN(boot_mem_map.map[i].addr |
| 374 | */ | ||
| 375 | curr_pfn = PFN_UP(boot_mem_map.map[i].addr); | ||
| 376 | if (curr_pfn >= max_low_pfn) | ||
| 377 | continue; | ||
| 378 | if (curr_pfn < start_pfn) | ||
| 379 | curr_pfn = start_pfn; | ||
| 380 | |||
| 381 | /* | ||
| 382 | * ... and at the end of the usable range downwards: | ||
| 383 | */ | ||
| 384 | last_pfn = PFN_DOWN(boot_mem_map.map[i].addr | ||
| 385 | + boot_mem_map.map[i].size); | 313 | + boot_mem_map.map[i].size); |
| 386 | |||
| 387 | if (last_pfn > max_low_pfn) | ||
| 388 | last_pfn = max_low_pfn; | ||
| 389 | |||
| 390 | /* | 314 | /* |
| 391 | * Only register lowmem part of lowmem segment with bootmem. | 315 | * We are rounding up the start address of usable memory |
| 316 | * and at the end of the usable range downwards. | ||
| 392 | */ | 317 | */ |
| 393 | size = last_pfn - curr_pfn; | 318 | if (start >= max_low_pfn) |
| 394 | if (curr_pfn > PFN_DOWN(HIGHMEM_START)) | ||
| 395 | continue; | ||
| 396 | if (curr_pfn + size - 1 > PFN_DOWN(HIGHMEM_START)) | ||
| 397 | size = PFN_DOWN(HIGHMEM_START) - curr_pfn; | ||
| 398 | if (!size) | ||
| 399 | continue; | 319 | continue; |
| 320 | if (start < reserved_end) | ||
| 321 | start = reserved_end; | ||
| 322 | if (end > max_low_pfn) | ||
| 323 | end = max_low_pfn; | ||
| 400 | 324 | ||
| 401 | /* | 325 | /* |
| 402 | * ... finally, did all the rounding and playing | 326 | * ... finally, is the area going away? |
| 403 | * around just make the area go away? | ||
| 404 | */ | 327 | */ |
| 405 | if (last_pfn <= curr_pfn) | 328 | if (end <= start) |
| 406 | continue; | 329 | continue; |
| 330 | size = end - start; | ||
| 407 | 331 | ||
| 408 | /* Register lowmem ranges */ | 332 | /* Register lowmem ranges */ |
| 409 | free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size)); | 333 | free_bootmem(PFN_PHYS(start), size << PAGE_SHIFT); |
| 410 | memory_present(0, curr_pfn, curr_pfn + size - 1); | 334 | memory_present(0, start, end); |
| 411 | } | 335 | } |
| 412 | 336 | ||
| 413 | /* Reserve the bootmap memory. */ | 337 | /* |
| 414 | reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size); | 338 | * Reserve the bootmap memory. |
| 415 | #endif /* CONFIG_SGI_IP27 */ | 339 | */ |
| 416 | 340 | reserve_bootmem(PFN_PHYS(mapstart), bootmap_size); | |
| 417 | #ifdef CONFIG_BLK_DEV_INITRD | ||
| 418 | initrd_below_start_ok = 1; | ||
| 419 | if (initrd_start) { | ||
| 420 | unsigned long initrd_size = ((unsigned char *)initrd_end) - | ||
| 421 | ((unsigned char *)initrd_start); | ||
| 422 | const int width = sizeof(long) * 2; | ||
| 423 | |||
| 424 | printk("Initial ramdisk at: 0x%p (%lu bytes)\n", | ||
| 425 | (void *)initrd_start, initrd_size); | ||
| 426 | |||
| 427 | if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) { | ||
| 428 | printk("initrd extends beyond end of memory " | ||
| 429 | "(0x%0*Lx > 0x%0*Lx)\ndisabling initrd\n", | ||
| 430 | width, | ||
| 431 | (unsigned long long) CPHYSADDR(initrd_end), | ||
| 432 | width, | ||
| 433 | (unsigned long long) PFN_PHYS(max_low_pfn)); | ||
| 434 | initrd_start = initrd_end = 0; | ||
| 435 | initrd_reserve_bootmem = 0; | ||
| 436 | } | ||
| 437 | 341 | ||
| 438 | if (initrd_reserve_bootmem) | 342 | /* |
| 439 | reserve_bootmem(CPHYSADDR(initrd_start), initrd_size); | 343 | * Reserve initrd memory if needed. |
| 440 | } | 344 | */ |
| 441 | #endif /* CONFIG_BLK_DEV_INITRD */ | 345 | finalize_initrd(); |
| 442 | } | 346 | } |
| 443 | 347 | ||
| 348 | #endif /* CONFIG_SGI_IP27 */ | ||
| 349 | |||
| 444 | /* | 350 | /* |
| 445 | * arch_mem_init - initialize memory managment subsystem | 351 | * arch_mem_init - initialize memory managment subsystem |
| 446 | * | 352 | * |
| 447 | * o plat_mem_setup() detects the memory configuration and will record detected | 353 | * o plat_mem_setup() detects the memory configuration and will record detected |
| 448 | * memory areas using add_memory_region. | 354 | * memory areas using add_memory_region. |
| 449 | * o parse_cmdline_early() parses the command line for mem= options which, | ||
| 450 | * iff detected, will override the results of the automatic detection. | ||
| 451 | * | 355 | * |
| 452 | * At this stage the memory configuration of the system is known to the | 356 | * At this stage the memory configuration of the system is known to the |
| 453 | * kernel but generic memory managment system is still entirely uninitialized. | 357 | * kernel but generic memory managment system is still entirely uninitialized. |
| @@ -465,25 +369,59 @@ static inline void bootmem_init(void) | |||
| 465 | * initialization hook for anything else was introduced. | 369 | * initialization hook for anything else was introduced. |
| 466 | */ | 370 | */ |
| 467 | 371 | ||
| 468 | extern void plat_mem_setup(void); | 372 | static int usermem __initdata = 0; |
| 373 | |||
| 374 | static int __init early_parse_mem(char *p) | ||
| 375 | { | ||
| 376 | unsigned long start, size; | ||
| 377 | |||
| 378 | /* | ||
| 379 | * If a user specifies memory size, we | ||
| 380 | * blow away any automatically generated | ||
| 381 | * size. | ||
| 382 | */ | ||
| 383 | if (usermem == 0) { | ||
| 384 | boot_mem_map.nr_map = 0; | ||
| 385 | usermem = 1; | ||
| 386 | } | ||
| 387 | start = 0; | ||
| 388 | size = memparse(p, &p); | ||
| 389 | if (*p == '@') | ||
| 390 | start = memparse(p + 1, &p); | ||
| 391 | |||
| 392 | add_memory_region(start, size, BOOT_MEM_RAM); | ||
| 393 | return 0; | ||
| 394 | } | ||
| 395 | early_param("mem", early_parse_mem); | ||
| 469 | 396 | ||
| 470 | static void __init arch_mem_init(char **cmdline_p) | 397 | static void __init arch_mem_init(char **cmdline_p) |
| 471 | { | 398 | { |
| 399 | extern void plat_mem_setup(void); | ||
| 400 | |||
| 472 | /* call board setup routine */ | 401 | /* call board setup routine */ |
| 473 | plat_mem_setup(); | 402 | plat_mem_setup(); |
| 474 | 403 | ||
| 404 | printk("Determined physical RAM map:\n"); | ||
| 405 | print_memory_map(); | ||
| 406 | |||
| 475 | strlcpy(command_line, arcs_cmdline, sizeof(command_line)); | 407 | strlcpy(command_line, arcs_cmdline, sizeof(command_line)); |
| 476 | strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); | 408 | strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); |
| 477 | 409 | ||
| 478 | *cmdline_p = command_line; | 410 | *cmdline_p = command_line; |
| 479 | 411 | ||
| 480 | parse_cmdline_early(); | 412 | parse_early_param(); |
| 413 | |||
| 414 | if (usermem) { | ||
| 415 | printk("User-defined physical RAM map:\n"); | ||
| 416 | print_memory_map(); | ||
| 417 | } | ||
| 418 | |||
| 481 | bootmem_init(); | 419 | bootmem_init(); |
| 482 | sparse_init(); | 420 | sparse_init(); |
| 483 | paging_init(); | 421 | paging_init(); |
| 484 | } | 422 | } |
| 485 | 423 | ||
| 486 | static inline void resource_init(void) | 424 | static void __init resource_init(void) |
| 487 | { | 425 | { |
| 488 | int i; | 426 | int i; |
| 489 | 427 | ||
| @@ -504,10 +442,10 @@ static inline void resource_init(void) | |||
| 504 | 442 | ||
| 505 | start = boot_mem_map.map[i].addr; | 443 | start = boot_mem_map.map[i].addr; |
| 506 | end = boot_mem_map.map[i].addr + boot_mem_map.map[i].size - 1; | 444 | end = boot_mem_map.map[i].addr + boot_mem_map.map[i].size - 1; |
| 507 | if (start >= MAXMEM) | 445 | if (start >= HIGHMEM_START) |
| 508 | continue; | 446 | continue; |
| 509 | if (end >= MAXMEM) | 447 | if (end >= HIGHMEM_START) |
| 510 | end = MAXMEM - 1; | 448 | end = HIGHMEM_START - 1; |
| 511 | 449 | ||
| 512 | res = alloc_bootmem(sizeof(struct resource)); | 450 | res = alloc_bootmem(sizeof(struct resource)); |
| 513 | switch (boot_mem_map.map[i].type) { | 451 | switch (boot_mem_map.map[i].type) { |
| @@ -536,9 +474,6 @@ static inline void resource_init(void) | |||
| 536 | } | 474 | } |
| 537 | } | 475 | } |
| 538 | 476 | ||
| 539 | #undef MAXMEM | ||
| 540 | #undef MAXMEM_PFN | ||
| 541 | |||
| 542 | void __init setup_arch(char **cmdline_p) | 477 | void __init setup_arch(char **cmdline_p) |
| 543 | { | 478 | { |
| 544 | cpu_probe(); | 479 | cpu_probe(); |
