Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 28705
b: refs/heads/master
c: 2babf5c
h: refs/heads/master
i:
  28703: d1b3c34
v: v3
  • Loading branch information
Michael Ellerman authored and Paul Mackerras committed May 19, 2006
1 parent beb765c commit 4d7e26b
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 131 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 846f77b08c8301682ded5ce127c56397327a60d0
refs/heads/master: 2babf5c2ec2f2d5de3e38d20f7df7fd815fd10c9
5 changes: 5 additions & 0 deletions trunk/arch/powerpc/kernel/machine_kexec_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,3 +339,8 @@ void __init kexec_setup(void)
{
export_htab_values();
}

int overlaps_crashkernel(unsigned long start, unsigned long size)
{
return (start + size) > crashk_res.start && start <= crashk_res.end;
}
89 changes: 47 additions & 42 deletions trunk/arch/powerpc/kernel/prom.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include <asm/machdep.h>
#include <asm/pSeries_reconfig.h>
#include <asm/pci-bridge.h>
#include <asm/kexec.h>

#ifdef DEBUG
#define DBG(fmt...) printk(KERN_ERR fmt)
Expand Down Expand Up @@ -836,6 +837,42 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
return mem;
}

static int __init early_parse_mem(char *p)
{
if (!p)
return 1;

memory_limit = PAGE_ALIGN(memparse(p, &p));
DBG("memory limit = 0x%lx\n", memory_limit);

return 0;
}
early_param("mem", early_parse_mem);

/*
* The device tree may be allocated below our memory limit, or inside the
* crash kernel region for kdump. If so, move it out now.
*/
static void move_device_tree(void)
{
unsigned long start, size;
void *p;

DBG("-> move_device_tree\n");

start = __pa(initial_boot_params);
size = initial_boot_params->totalsize;

if ((memory_limit && (start + size) > memory_limit) ||
overlaps_crashkernel(start, size)) {
p = __va(lmb_alloc_base(size, PAGE_SIZE, lmb.rmo_size));
memcpy(p, initial_boot_params, size);
initial_boot_params = (struct boot_param_header *)p;
DBG("Moved device tree to 0x%p\n", p);
}

DBG("<- move_device_tree\n");
}

/**
* unflattens the device-tree passed by the firmware, creating the
Expand Down Expand Up @@ -1070,6 +1107,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
iommu_force_on = 1;
#endif

/* mem=x on the command line is the preferred mechanism */
lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
if (lprop)
memory_limit = *lprop;
Expand Down Expand Up @@ -1123,17 +1161,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,

DBG("Command line is: %s\n", cmd_line);

if (strstr(cmd_line, "mem=")) {
char *p, *q;

for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
q = p + 4;
if (p > cmd_line && p[-1] != ' ')
continue;
memory_limit = memparse(q, &q);
}
}

/* break now */
return 1;
}
Expand Down Expand Up @@ -1297,18 +1324,22 @@ void __init early_init_devtree(void *params)
strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
parse_early_param();

lmb_enforce_memory_limit(memory_limit);
lmb_analyze();

DBG("Phys. mem: %lx\n", lmb_phys_mem_size());

/* Reserve LMB regions used by kernel, initrd, dt, etc... */
lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
#ifdef CONFIG_CRASH_DUMP
lmb_reserve(0, KDUMP_RESERVE_LIMIT);
#endif
early_reserve_mem();

lmb_enforce_memory_limit(memory_limit);
lmb_analyze();

DBG("Phys. mem: %lx\n", lmb_phys_mem_size());

/* We may need to relocate the flat tree, do it now.
* FIXME .. and the initrd too? */
move_device_tree();

DBG("Scanning CPUs ...\n");

/* Retreive CPU related informations from the flat tree
Expand Down Expand Up @@ -2058,29 +2089,3 @@ int prom_update_property(struct device_node *np,
return 0;
}

#ifdef CONFIG_KEXEC
/* We may have allocated the flat device tree inside the crash kernel region
* in prom_init. If so we need to move it out into regular memory. */
void kdump_move_device_tree(void)
{
unsigned long start, end;
struct boot_param_header *new;

start = __pa((unsigned long)initial_boot_params);
end = start + initial_boot_params->totalsize;

if (end < crashk_res.start || start > crashk_res.end)
return;

new = (struct boot_param_header*)
__va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE));

memcpy(new, initial_boot_params, initial_boot_params->totalsize);

initial_boot_params = new;

DBG("Flat device tree blob moved to %p\n", initial_boot_params);

/* XXX should we unreserve the old DT? */
}
#endif /* CONFIG_KEXEC */
55 changes: 5 additions & 50 deletions trunk/arch/powerpc/kernel/prom_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,6 @@ static int __initdata of_platform;

static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];

static unsigned long __initdata prom_memory_limit;

static unsigned long __initdata alloc_top;
static unsigned long __initdata alloc_top_high;
static unsigned long __initdata alloc_bottom;
Expand Down Expand Up @@ -594,16 +592,6 @@ static void __init early_cmdline_parse(void)
}
#endif

opt = strstr(RELOC(prom_cmd_line), RELOC("mem="));
if (opt) {
opt += 4;
RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt);
#ifdef CONFIG_PPC64
/* Align to 16 MB == size of ppc64 large page */
RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
#endif
}

#ifdef CONFIG_KEXEC
/*
* crashkernel=size@addr specifies the location to reserve for
Expand Down Expand Up @@ -1114,29 +1102,6 @@ static void __init prom_init_mem(void)
RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(prom_initrd_end));
}

/*
* If prom_memory_limit is set we reduce the upper limits *except* for
* alloc_top_high. This must be the real top of RAM so we can put
* TCE's up there.
*/

RELOC(alloc_top_high) = RELOC(ram_top);

if (RELOC(prom_memory_limit)) {
if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) {
prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
RELOC(prom_memory_limit));
RELOC(prom_memory_limit) = 0;
} else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) {
prom_printf("Ignoring mem=%x >= ram_top.\n",
RELOC(prom_memory_limit));
RELOC(prom_memory_limit) = 0;
} else {
RELOC(ram_top) = RELOC(prom_memory_limit);
RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit));
}
}

/*
* Setup our top alloc point, that is top of RMO or top of
* segment 0 when running non-LPAR.
Expand All @@ -1149,9 +1114,9 @@ static void __init prom_init_mem(void)
RELOC(rmo_top) = RELOC(ram_top);
RELOC(rmo_top) = min(0x30000000ul, RELOC(rmo_top));
RELOC(alloc_top) = RELOC(rmo_top);
RELOC(alloc_top_high) = RELOC(ram_top);

prom_printf("memory layout at init:\n");
prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom));
prom_printf(" alloc_top : %x\n", RELOC(alloc_top));
prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
Expand Down Expand Up @@ -1348,16 +1313,10 @@ static void __init prom_initialize_tce_table(void)

reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);

if (RELOC(prom_memory_limit)) {
/*
* We align the start to a 16MB boundary so we can map
* the TCE area using large pages if possible.
* The end should be the top of RAM so no need to align it.
*/
RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom,
0x1000000);
RELOC(prom_tce_alloc_end) = local_alloc_top;
}
/* These are only really needed if there is a memory limit in
* effect, but we don't know so export them always. */
RELOC(prom_tce_alloc_start) = local_alloc_bottom;
RELOC(prom_tce_alloc_end) = local_alloc_top;

/* Flag the first invalid entry */
prom_debug("ending prom_initialize_tce_table\n");
Expand Down Expand Up @@ -2265,10 +2224,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
/*
* Fill in some infos for use by the kernel later on
*/
if (RELOC(prom_memory_limit))
prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit",
&RELOC(prom_memory_limit),
sizeof(prom_memory_limit));
#ifdef CONFIG_PPC64
if (RELOC(ppc64_iommu_off))
prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off",
Expand Down
3 changes: 0 additions & 3 deletions trunk/arch/powerpc/kernel/setup_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,9 +347,6 @@ void __init setup_system(void)
{
DBG(" -> setup_system()\n");

#ifdef CONFIG_KEXEC
kdump_move_device_tree();
#endif
/*
* Unflatten the device-tree passed by prom_init or kexec
*/
Expand Down
43 changes: 32 additions & 11 deletions trunk/arch/powerpc/mm/lmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,25 @@ static long __init lmb_regions_adjacent(struct lmb_region *rgn,
return lmb_addrs_adjacent(base1, size1, base2, size2);
}

/* Assumption: base addr of region 1 < base addr of region 2 */
static void __init lmb_coalesce_regions(struct lmb_region *rgn,
unsigned long r1, unsigned long r2)
static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r)
{
unsigned long i;

rgn->region[r1].size += rgn->region[r2].size;
for (i=r2; i < rgn->cnt-1; i++) {
rgn->region[i].base = rgn->region[i+1].base;
rgn->region[i].size = rgn->region[i+1].size;
for (i = r; i < rgn->cnt - 1; i++) {
rgn->region[i].base = rgn->region[i + 1].base;
rgn->region[i].size = rgn->region[i + 1].size;
}
rgn->cnt--;
}

/* Assumption: base addr of region 1 < base addr of region 2 */
static void __init lmb_coalesce_regions(struct lmb_region *rgn,
unsigned long r1, unsigned long r2)
{
rgn->region[r1].size += rgn->region[r2].size;
lmb_remove_region(rgn, r2);
}

/* This routine called with relocation disabled. */
void __init lmb_init(void)
{
Expand Down Expand Up @@ -294,17 +299,16 @@ unsigned long __init lmb_end_of_DRAM(void)
return (lmb.memory.region[idx].base + lmb.memory.region[idx].size);
}

/*
* Truncate the lmb list to memory_limit if it's set
* You must call lmb_analyze() after this.
*/
/* You must call lmb_analyze() after this. */
void __init lmb_enforce_memory_limit(unsigned long memory_limit)
{
unsigned long i, limit;
struct lmb_property *p;

if (! memory_limit)
return;

/* Truncate the lmb regions to satisfy the memory limit. */
limit = memory_limit;
for (i = 0; i < lmb.memory.cnt; i++) {
if (limit > lmb.memory.region[i].size) {
Expand All @@ -316,4 +320,21 @@ void __init lmb_enforce_memory_limit(unsigned long memory_limit)
lmb.memory.cnt = i + 1;
break;
}

lmb.rmo_size = lmb.memory.region[0].size;

/* And truncate any reserves above the limit also. */
for (i = 0; i < lmb.reserved.cnt; i++) {
p = &lmb.reserved.region[i];

if (p->base > memory_limit)
p->size = 0;
else if ((p->base + p->size) > memory_limit)
p->size = memory_limit - p->base;

if (p->size == 0) {
lmb_remove_region(&lmb.reserved, i);
i--;
}
}
}
22 changes: 0 additions & 22 deletions trunk/arch/powerpc/platforms/iseries/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,6 @@ extern unsigned long embedded_sysmap_end;
extern unsigned long iSeries_recal_tb;
extern unsigned long iSeries_recal_titan;

static unsigned long cmd_mem_limit;

struct MemoryBlock {
unsigned long absStart;
unsigned long absEnd;
Expand Down Expand Up @@ -1026,8 +1024,6 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
/* /chosen */
dt_start_node(dt, "chosen");
dt_prop_str(dt, "bootargs", cmd_line);
if (cmd_mem_limit)
dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit);
dt_end_node(dt);

dt_cpus(dt);
Expand All @@ -1053,29 +1049,11 @@ void * __init iSeries_early_setup(void)

iSeries_get_cmdline();

/* Save unparsed command line copy for /proc/cmdline */
strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);

/* Parse early parameters, in particular mem=x */
parse_early_param();

build_flat_dt(&iseries_dt, phys_mem_size);

return (void *) __pa(&iseries_dt);
}

/*
* On iSeries we just parse the mem=X option from the command line.
* On pSeries it's a bit more complicated, see prom_init_mem()
*/
static int __init early_parsemem(char *p)
{
if (p)
cmd_mem_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
return 0;
}
early_param("mem", early_parsemem);

static void hvputc(char c)
{
if (c == '\n')
Expand Down
Loading

0 comments on commit 4d7e26b

Please sign in to comment.