aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries
diff options
context:
space:
mode:
authorManish Ahuja <ahuja@austin.ibm.com>2008-03-21 19:43:15 -0400
committerPaul Mackerras <paulus@samba.org>2008-03-25 17:44:06 -0400
commit2c4f41139cc4ffc3ad12d7fdb8dd71dc36824a6e (patch)
tree4a6dc1b277692e9f8dd644b987a5cd801c288a2d /arch/powerpc/platforms/pseries
parentd5a29c7a36958ddec1ae7ab685ce09a002356548 (diff)
[POWERPC] pseries: phyp dump: Register dump area
Set up the actual dump header, register it with the hypervisor. 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>
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r--arch/powerpc/platforms/pseries/phyp_dump.c137
1 files changed, 131 insertions, 6 deletions
diff --git a/arch/powerpc/platforms/pseries/phyp_dump.c b/arch/powerpc/platforms/pseries/phyp_dump.c
index f355f052a56..d93f1b1585a 100644
--- a/arch/powerpc/platforms/pseries/phyp_dump.c
+++ b/arch/powerpc/platforms/pseries/phyp_dump.c
@@ -29,6 +29,117 @@
29static struct phyp_dump phyp_dump_vars; 29static struct phyp_dump phyp_dump_vars;
30struct phyp_dump *phyp_dump_info = &phyp_dump_vars; 30struct phyp_dump *phyp_dump_info = &phyp_dump_vars;
31 31
32static int ibm_configure_kernel_dump;
33/* ------------------------------------------------- */
34/* RTAS interfaces to declare the dump regions */
35
36struct dump_section {
37 u32 dump_flags;
38 u16 source_type;
39 u16 error_flags;
40 u64 source_address;
41 u64 source_length;
42 u64 length_copied;
43 u64 destination_address;
44};
45
46struct phyp_dump_header {
47 u32 version;
48 u16 num_of_sections;
49 u16 status;
50
51 u32 first_offset_section;
52 u32 dump_disk_section;
53 u64 block_num_dd;
54 u64 num_of_blocks_dd;
55 u32 offset_dd;
56 u32 maxtime_to_auto;
57 /* No dump disk path string used */
58
59 struct dump_section cpu_data;
60 struct dump_section hpte_data;
61 struct dump_section kernel_data;
62};
63
64/* The dump header *must be* in low memory, so .bss it */
65static struct phyp_dump_header phdr;
66
67#define NUM_DUMP_SECTIONS 3
68#define DUMP_HEADER_VERSION 0x1
69#define DUMP_REQUEST_FLAG 0x1
70#define DUMP_SOURCE_CPU 0x0001
71#define DUMP_SOURCE_HPTE 0x0002
72#define DUMP_SOURCE_RMO 0x0011
73
74/**
75 * init_dump_header() - initialize the header declaring a dump
76 * Returns: length of dump save area.
77 *
78 * When the hypervisor saves crashed state, it needs to put
79 * it somewhere. The dump header tells the hypervisor where
80 * the data can be saved.
81 */
82static unsigned long init_dump_header(struct phyp_dump_header *ph)
83{
84 unsigned long addr_offset = 0;
85
86 /* Set up the dump header */
87 ph->version = DUMP_HEADER_VERSION;
88 ph->num_of_sections = NUM_DUMP_SECTIONS;
89 ph->status = 0;
90
91 ph->first_offset_section =
92 (u32)offsetof(struct phyp_dump_header, cpu_data);
93 ph->dump_disk_section = 0;
94 ph->block_num_dd = 0;
95 ph->num_of_blocks_dd = 0;
96 ph->offset_dd = 0;
97
98 ph->maxtime_to_auto = 0; /* disabled */
99
100 /* The first two sections are mandatory */
101 ph->cpu_data.dump_flags = DUMP_REQUEST_FLAG;
102 ph->cpu_data.source_type = DUMP_SOURCE_CPU;
103 ph->cpu_data.source_address = 0;
104 ph->cpu_data.source_length = phyp_dump_info->cpu_state_size;
105 ph->cpu_data.destination_address = addr_offset;
106 addr_offset += phyp_dump_info->cpu_state_size;
107
108 ph->hpte_data.dump_flags = DUMP_REQUEST_FLAG;
109 ph->hpte_data.source_type = DUMP_SOURCE_HPTE;
110 ph->hpte_data.source_address = 0;
111 ph->hpte_data.source_length = phyp_dump_info->hpte_region_size;
112 ph->hpte_data.destination_address = addr_offset;
113 addr_offset += phyp_dump_info->hpte_region_size;
114
115 /* This section describes the low kernel region */
116 ph->kernel_data.dump_flags = DUMP_REQUEST_FLAG;
117 ph->kernel_data.source_type = DUMP_SOURCE_RMO;
118 ph->kernel_data.source_address = PHYP_DUMP_RMR_START;
119 ph->kernel_data.source_length = PHYP_DUMP_RMR_END;
120 ph->kernel_data.destination_address = addr_offset;
121 addr_offset += ph->kernel_data.source_length;
122
123 return addr_offset;
124}
125
126static void register_dump_area(struct phyp_dump_header *ph, unsigned long addr)
127{
128 int rc;
129 ph->cpu_data.destination_address += addr;
130 ph->hpte_data.destination_address += addr;
131 ph->kernel_data.destination_address += addr;
132
133 do {
134 rc = rtas_call(ibm_configure_kernel_dump, 3, 1, NULL,
135 1, ph, sizeof(struct phyp_dump_header));
136 } while (rtas_busy_delay(rc));
137
138 if (rc)
139 printk(KERN_ERR "phyp-dump: unexpected error (%d) on "
140 "register\n", rc);
141}
142
32/* ------------------------------------------------- */ 143/* ------------------------------------------------- */
33/** 144/**
34 * release_memory_range -- release memory previously lmb_reserved 145 * release_memory_range -- release memory previously lmb_reserved
@@ -107,7 +218,9 @@ static struct kobj_attribute rr = __ATTR(release_region, 0600,
107static int __init phyp_dump_setup(void) 218static int __init phyp_dump_setup(void)
108{ 219{
109 struct device_node *rtas; 220 struct device_node *rtas;
110 const int *dump_header = NULL; 221 const struct phyp_dump_header *dump_header = NULL;
222 unsigned long dump_area_start;
223 unsigned long dump_area_length;
111 int header_len = 0; 224 int header_len = 0;
112 int rc; 225 int rc;
113 226
@@ -119,7 +232,13 @@ static int __init phyp_dump_setup(void)
119 if (!phyp_dump_info->phyp_dump_configured) 232 if (!phyp_dump_info->phyp_dump_configured)
120 return -ENOSYS; 233 return -ENOSYS;
121 234
122 /* Is there dump data waiting for us? */ 235 /* Is there dump data waiting for us? If there isn't,
236 * then register a new dump area, and release all of
237 * the rest of the reserved ram.
238 *
239 * The /rtas/ibm,kernel-dump rtas node is present only
240 * if there is dump data waiting for us.
241 */
123 rtas = of_find_node_by_path("/rtas"); 242 rtas = of_find_node_by_path("/rtas");
124 if (rtas) { 243 if (rtas) {
125 dump_header = of_get_property(rtas, "ibm,kernel-dump", 244 dump_header = of_get_property(rtas, "ibm,kernel-dump",
@@ -127,17 +246,23 @@ static int __init phyp_dump_setup(void)
127 of_node_put(rtas); 246 of_node_put(rtas);
128 } 247 }
129 248
130 if (dump_header == NULL) 249 dump_area_length = init_dump_header(&phdr);
250
251 /* align down */
252 dump_area_start = phyp_dump_info->init_reserve_start & PAGE_MASK;
253
254 if (dump_header == NULL) {
255 register_dump_area(&phdr, dump_area_start);
131 return 0; 256 return 0;
257 }
132 258
133 /* Should we create a dump_subsys, analogous to s390/ipl.c ? */ 259 /* Should we create a dump_subsys, analogous to s390/ipl.c ? */
134 rc = sysfs_create_file(kernel_kobj, &rr.attr); 260 rc = sysfs_create_file(kernel_kobj, &rr.attr);
135 if (rc) { 261 if (rc)
136 printk(KERN_ERR "phyp-dump: unable to create sysfs file (%d)\n", 262 printk(KERN_ERR "phyp-dump: unable to create sysfs file (%d)\n",
137 rc); 263 rc);
138 return 0;
139 }
140 264
265 /* ToDo: re-register the dump area, for next time. */
141 return 0; 266 return 0;
142} 267}
143machine_subsys_initcall(pseries, phyp_dump_setup); 268machine_subsys_initcall(pseries, phyp_dump_setup);