diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2014-03-21 13:04:40 -0400 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2014-04-01 17:35:54 -0400 |
commit | 06bd2824f7dcbfb8dcd13519239a53d13298d238 (patch) | |
tree | 249b0b2ae6c1b088c358b8b150dabe2b839c16db | |
parent | 6232791833785ae591b211609f6f7c4faa7c6e55 (diff) |
xtensa: handle memmap kernel option
This option is useful for reserving memory regions for secondary cores
in AMP configurations.
Implement the following memmap variants:
- memmap=nn[KMG]@ss[KMG]: force usage of a specific region of memory;
- memmap=nn[KMG]$ss[KMG]: mark specified memory as reserved;
- memmap=nn[KMG]: set end of memory.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
-rw-r--r-- | arch/xtensa/kernel/setup.c | 1 | ||||
-rw-r--r-- | arch/xtensa/mm/init.c | 50 |
2 files changed, 51 insertions, 0 deletions
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 017c06aba9b2..9757bb74e532 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c | |||
@@ -507,6 +507,7 @@ void __init setup_arch(char **cmdline_p) | |||
507 | __pa(&_Level6InterruptVector_text_end), 0); | 507 | __pa(&_Level6InterruptVector_text_end), 0); |
508 | #endif | 508 | #endif |
509 | 509 | ||
510 | parse_early_param(); | ||
510 | bootmem_init(); | 511 | bootmem_init(); |
511 | 512 | ||
512 | unflatten_and_copy_device_tree(); | 513 | unflatten_and_copy_device_tree(); |
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index 5d23697957bf..d70ba9333f44 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c | |||
@@ -332,3 +332,53 @@ void free_initmem(void) | |||
332 | { | 332 | { |
333 | free_initmem_default(-1); | 333 | free_initmem_default(-1); |
334 | } | 334 | } |
335 | |||
336 | static void __init parse_memmap_one(char *p) | ||
337 | { | ||
338 | char *oldp; | ||
339 | unsigned long start_at, mem_size; | ||
340 | |||
341 | if (!p) | ||
342 | return; | ||
343 | |||
344 | oldp = p; | ||
345 | mem_size = memparse(p, &p); | ||
346 | if (p == oldp) | ||
347 | return; | ||
348 | |||
349 | switch (*p) { | ||
350 | case '@': | ||
351 | start_at = memparse(p + 1, &p); | ||
352 | add_sysmem_bank(start_at, start_at + mem_size); | ||
353 | break; | ||
354 | |||
355 | case '$': | ||
356 | start_at = memparse(p + 1, &p); | ||
357 | mem_reserve(start_at, start_at + mem_size, 0); | ||
358 | break; | ||
359 | |||
360 | case 0: | ||
361 | mem_reserve(mem_size, 0, 0); | ||
362 | break; | ||
363 | |||
364 | default: | ||
365 | pr_warn("Unrecognized memmap syntax: %s\n", p); | ||
366 | break; | ||
367 | } | ||
368 | } | ||
369 | |||
370 | static int __init parse_memmap_opt(char *str) | ||
371 | { | ||
372 | while (str) { | ||
373 | char *k = strchr(str, ','); | ||
374 | |||
375 | if (k) | ||
376 | *k++ = 0; | ||
377 | |||
378 | parse_memmap_one(str); | ||
379 | str = k; | ||
380 | } | ||
381 | |||
382 | return 0; | ||
383 | } | ||
384 | early_param("memmap", parse_memmap_opt); | ||