mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 20:53:53 +08:00
[POWERPC] pseries: phyp dump: Reserve and release memory
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>
This commit is contained in:
parent
d28a79326a
commit
6ac26c8a7e
@ -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
|
||||
@ -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);
|
||||
@ -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 ...
|
||||
@ -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();
|
||||
|
@ -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
arch/powerpc/platforms/pseries/phyp_dump.c
Normal file
103
arch/powerpc/platforms/pseries/phyp_dump.c
Normal file
@ -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
include/asm-powerpc/phyp_dump.h
Normal file
41
include/asm-powerpc/phyp_dump.h
Normal file
@ -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 */
|
Loading…
Reference in New Issue
Block a user