aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/phyp_dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/phyp_dump.c')
-rw-r--r--arch/powerpc/platforms/pseries/phyp_dump.c83
1 files changed, 77 insertions, 6 deletions
diff --git a/arch/powerpc/platforms/pseries/phyp_dump.c b/arch/powerpc/platforms/pseries/phyp_dump.c
index 5cdba6a6f70c..df4870ec90d8 100644
--- a/arch/powerpc/platforms/pseries/phyp_dump.c
+++ b/arch/powerpc/platforms/pseries/phyp_dump.c
@@ -70,6 +70,10 @@ static struct phyp_dump_header phdr;
70#define DUMP_SOURCE_CPU 0x0001 70#define DUMP_SOURCE_CPU 0x0001
71#define DUMP_SOURCE_HPTE 0x0002 71#define DUMP_SOURCE_HPTE 0x0002
72#define DUMP_SOURCE_RMO 0x0011 72#define DUMP_SOURCE_RMO 0x0011
73#define DUMP_ERROR_FLAG 0x2000
74#define DUMP_TRIGGERED 0x4000
75#define DUMP_PERFORMED 0x8000
76
73 77
74/** 78/**
75 * init_dump_header() - initialize the header declaring a dump 79 * init_dump_header() - initialize the header declaring a dump
@@ -181,9 +185,15 @@ static void print_dump_header(const struct phyp_dump_header *ph)
181static void register_dump_area(struct phyp_dump_header *ph, unsigned long addr) 185static void register_dump_area(struct phyp_dump_header *ph, unsigned long addr)
182{ 186{
183 int rc; 187 int rc;
184 ph->cpu_data.destination_address += addr; 188
185 ph->hpte_data.destination_address += addr; 189 /* Add addr value if not initialized before */
186 ph->kernel_data.destination_address += addr; 190 if (ph->cpu_data.destination_address == 0) {
191 ph->cpu_data.destination_address += addr;
192 ph->hpte_data.destination_address += addr;
193 ph->kernel_data.destination_address += addr;
194 }
195
196 /* ToDo Invalidate kdump and free memory range. */
187 197
188 do { 198 do {
189 rc = rtas_call(ibm_configure_kernel_dump, 3, 1, NULL, 199 rc = rtas_call(ibm_configure_kernel_dump, 3, 1, NULL,
@@ -197,6 +207,30 @@ static void register_dump_area(struct phyp_dump_header *ph, unsigned long addr)
197 } 207 }
198} 208}
199 209
210static
211void invalidate_last_dump(struct phyp_dump_header *ph, unsigned long addr)
212{
213 int rc;
214
215 /* Add addr value if not initialized before */
216 if (ph->cpu_data.destination_address == 0) {
217 ph->cpu_data.destination_address += addr;
218 ph->hpte_data.destination_address += addr;
219 ph->kernel_data.destination_address += addr;
220 }
221
222 do {
223 rc = rtas_call(ibm_configure_kernel_dump, 3, 1, NULL,
224 2, ph, sizeof(struct phyp_dump_header));
225 } while (rtas_busy_delay(rc));
226
227 if (rc) {
228 printk(KERN_ERR "phyp-dump: unexpected error (%d) "
229 "on invalidate\n", rc);
230 print_dump_header(ph);
231 }
232}
233
200/* ------------------------------------------------- */ 234/* ------------------------------------------------- */
201/** 235/**
202 * release_memory_range -- release memory previously lmb_reserved 236 * release_memory_range -- release memory previously lmb_reserved
@@ -207,8 +241,8 @@ static void register_dump_area(struct phyp_dump_header *ph, unsigned long addr)
207 * lmb_reserved in early boot. The released memory becomes 241 * lmb_reserved in early boot. The released memory becomes
208 * available for genreal use. 242 * available for genreal use.
209 */ 243 */
210static void 244static void release_memory_range(unsigned long start_pfn,
211release_memory_range(unsigned long start_pfn, unsigned long nr_pages) 245 unsigned long nr_pages)
212{ 246{
213 struct page *rpage; 247 struct page *rpage;
214 unsigned long end_pfn; 248 unsigned long end_pfn;
@@ -269,8 +303,29 @@ static ssize_t store_release_region(struct kobject *kobj,
269 return count; 303 return count;
270} 304}
271 305
306static ssize_t show_release_region(struct kobject *kobj,
307 struct kobj_attribute *attr, char *buf)
308{
309 u64 second_addr_range;
310
311 /* total reserved size - start of scratch area */
312 second_addr_range = phyp_dump_info->init_reserve_size -
313 phyp_dump_info->reserved_scratch_size;
314 return sprintf(buf, "CPU:0x%lx-0x%lx: HPTE:0x%lx-0x%lx:"
315 " DUMP:0x%lx-0x%lx, 0x%lx-0x%lx:\n",
316 phdr.cpu_data.destination_address,
317 phdr.cpu_data.length_copied,
318 phdr.hpte_data.destination_address,
319 phdr.hpte_data.length_copied,
320 phdr.kernel_data.destination_address,
321 phdr.kernel_data.length_copied,
322 phyp_dump_info->init_reserve_start,
323 second_addr_range);
324}
325
272static struct kobj_attribute rr = __ATTR(release_region, 0600, 326static struct kobj_attribute rr = __ATTR(release_region, 0600,
273 NULL, store_release_region); 327 show_release_region,
328 store_release_region);
274 329
275static int __init phyp_dump_setup(void) 330static int __init phyp_dump_setup(void)
276{ 331{
@@ -313,6 +368,22 @@ static int __init phyp_dump_setup(void)
313 return 0; 368 return 0;
314 } 369 }
315 370
371 /* re-register the dump area, if old dump was invalid */
372 if ((dump_header) && (dump_header->status & DUMP_ERROR_FLAG)) {
373 invalidate_last_dump(&phdr, dump_area_start);
374 register_dump_area(&phdr, dump_area_start);
375 return 0;
376 }
377
378 if (dump_header) {
379 phyp_dump_info->reserved_scratch_addr =
380 dump_header->cpu_data.destination_address;
381 phyp_dump_info->reserved_scratch_size =
382 dump_header->cpu_data.source_length +
383 dump_header->hpte_data.source_length +
384 dump_header->kernel_data.source_length;
385 }
386
316 /* Should we create a dump_subsys, analogous to s390/ipl.c ? */ 387 /* Should we create a dump_subsys, analogous to s390/ipl.c ? */
317 rc = sysfs_create_file(kernel_kobj, &rr.attr); 388 rc = sysfs_create_file(kernel_kobj, &rr.attr);
318 if (rc) 389 if (rc)