Skip to content

Commit

Permalink
[POWERPC] pseries: phyp dump: Reserve and release memory
Browse files Browse the repository at this point in the history
Initial patch for reserving memory in early boot, and freeing it
later.  If the previous boot had ended with a crash, the reserved
memory would contain a copy of the crashed kernel data.

Signed-off-by: Manish Ahuja <mahuja@us.ibm.com>
Signed-off-by: Linas Vepstas <linasvepstas@gmail.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
  • Loading branch information
Manish Ahuja authored and Paul Mackerras committed Mar 25, 2008
1 parent d28a793 commit 6ac26c8
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 0 deletions.
52 changes: 52 additions & 0 deletions arch/powerpc/kernel/prom.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include <asm/machdep.h>
#include <asm/pSeries_reconfig.h>
#include <asm/pci-bridge.h>
#include <asm/phyp_dump.h>
#include <asm/kexec.h>

#ifdef DEBUG
Expand Down Expand Up @@ -1040,6 +1041,51 @@ static void __init early_reserve_mem(void)
#endif
}

#ifdef CONFIG_PHYP_DUMP
/**
* phyp_dump_reserve_mem() - reserve all not-yet-dumped mmemory
*
* This routine may reserve memory regions in the kernel only
* if the system is supported and a dump was taken in last
* boot instance or if the hardware is supported and the
* scratch area needs to be setup. In other instances it returns
* without reserving anything. The memory in case of dump being
* active is freed when the dump is collected (by userland tools).
*/
static void __init phyp_dump_reserve_mem(void)
{
unsigned long base, size;
if (!phyp_dump_info->phyp_dump_configured) {
printk(KERN_ERR "Phyp-dump not supported on this hardware\n");
return;
}

if (phyp_dump_info->phyp_dump_is_active) {
/* Reserve *everything* above RMR.Area freed by userland tools*/
base = PHYP_DUMP_RMR_END;
size = lmb_end_of_DRAM() - base;

/* XXX crashed_ram_end is wrong, since it may be beyond
* the memory_limit, it will need to be adjusted. */
lmb_reserve(base, size);

phyp_dump_info->init_reserve_start = base;
phyp_dump_info->init_reserve_size = size;
} else {
size = phyp_dump_info->cpu_state_size +
phyp_dump_info->hpte_region_size +
PHYP_DUMP_RMR_END;
base = lmb_end_of_DRAM() - size;
lmb_reserve(base, size);
phyp_dump_info->init_reserve_start = base;
phyp_dump_info->init_reserve_size = size;
}
}
#else
static inline void __init phyp_dump_reserve_mem(void) {}
#endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */


void __init early_init_devtree(void *params)
{
DBG(" -> early_init_devtree(%p)\n", params);
Expand All @@ -1052,6 +1098,11 @@ void __init early_init_devtree(void *params)
of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
#endif

#ifdef CONFIG_PHYP_DUMP
/* scan tree to see if dump occured during last boot */
of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
#endif

/* Retrieve various informations from the /chosen node of the
* device-tree, including the platform type, initrd location and
* size, TCE reserve, and more ...
Expand All @@ -1072,6 +1123,7 @@ void __init early_init_devtree(void *params)
reserve_kdump_trampoline();
reserve_crashkernel();
early_reserve_mem();
phyp_dump_reserve_mem();

lmb_enforce_memory_limit(memory_limit);
lmb_analyze();
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/platforms/pseries/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o
obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_HVCS) += hvcserver.o
obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o
103 changes: 103 additions & 0 deletions arch/powerpc/platforms/pseries/phyp_dump.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Hypervisor-assisted dump
*
* Linas Vepstas, Manish Ahuja 2008
* Copyright 2008 IBM Corp.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/

#include <linux/init.h>
#include <linux/mm.h>
#include <linux/pfn.h>
#include <linux/swap.h>

#include <asm/page.h>
#include <asm/phyp_dump.h>
#include <asm/machdep.h>
#include <asm/prom.h>

/* Variables, used to communicate data between early boot and late boot */
static struct phyp_dump phyp_dump_vars;
struct phyp_dump *phyp_dump_info = &phyp_dump_vars;

/**
* release_memory_range -- release memory previously lmb_reserved
* @start_pfn: starting physical frame number
* @nr_pages: number of pages to free.
*
* This routine will release memory that had been previously
* lmb_reserved in early boot. The released memory becomes
* available for genreal use.
*/
static void
release_memory_range(unsigned long start_pfn, unsigned long nr_pages)
{
struct page *rpage;
unsigned long end_pfn;
long i;

end_pfn = start_pfn + nr_pages;

for (i = start_pfn; i <= end_pfn; i++) {
rpage = pfn_to_page(i);
if (PageReserved(rpage)) {
ClearPageReserved(rpage);
init_page_count(rpage);
__free_page(rpage);
totalram_pages++;
}
}
}

static int __init phyp_dump_setup(void)
{
unsigned long start_pfn, nr_pages;

/* If no memory was reserved in early boot, there is nothing to do */
if (phyp_dump_info->init_reserve_size == 0)
return 0;

/* Release memory that was reserved in early boot */
start_pfn = PFN_DOWN(phyp_dump_info->init_reserve_start);
nr_pages = PFN_DOWN(phyp_dump_info->init_reserve_size);
release_memory_range(start_pfn, nr_pages);

return 0;
}
machine_subsys_initcall(pseries, phyp_dump_setup);

int __init early_init_dt_scan_phyp_dump(unsigned long node,
const char *uname, int depth, void *data)
{
const unsigned int *sizes;

phyp_dump_info->phyp_dump_configured = 0;
phyp_dump_info->phyp_dump_is_active = 0;

if (depth != 1 || strcmp(uname, "rtas") != 0)
return 0;

if (of_get_flat_dt_prop(node, "ibm,configure-kernel-dump", NULL))
phyp_dump_info->phyp_dump_configured++;

if (of_get_flat_dt_prop(node, "ibm,dump-kernel", NULL))
phyp_dump_info->phyp_dump_is_active++;

sizes = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump-sizes",
NULL);
if (!sizes)
return 0;

if (sizes[0] == 1)
phyp_dump_info->cpu_state_size = *((unsigned long *)&sizes[1]);

if (sizes[3] == 2)
phyp_dump_info->hpte_region_size =
*((unsigned long *)&sizes[4]);
return 1;
}
41 changes: 41 additions & 0 deletions include/asm-powerpc/phyp_dump.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Hypervisor-assisted dump
*
* Linas Vepstas, Manish Ahuja 2008
* Copyright 2008 IBM Corp.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/

#ifndef _PPC64_PHYP_DUMP_H
#define _PPC64_PHYP_DUMP_H

#ifdef CONFIG_PHYP_DUMP

/* The RMR region will be saved for later dumping
* whenever the kernel crashes. Set this to 256MB. */
#define PHYP_DUMP_RMR_START 0x0
#define PHYP_DUMP_RMR_END (1UL<<28)

struct phyp_dump {
/* Memory that is reserved during very early boot. */
unsigned long init_reserve_start;
unsigned long init_reserve_size;
/* Check status during boot if dump supported, active & present*/
unsigned long phyp_dump_configured;
unsigned long phyp_dump_is_active;
/* store cpu & hpte size */
unsigned long cpu_state_size;
unsigned long hpte_region_size;
};

extern struct phyp_dump *phyp_dump_info;

int early_init_dt_scan_phyp_dump(unsigned long node,
const char *uname, int depth, void *data);

#endif /* CONFIG_PHYP_DUMP */
#endif /* _PPC64_PHYP_DUMP_H */

0 comments on commit 6ac26c8

Please sign in to comment.