diff options
author | Manish Ahuja <ahuja@austin.ibm.com> | 2008-03-21 19:39:17 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-03-25 17:44:06 -0400 |
commit | d5a29c7a36958ddec1ae7ab685ce09a002356548 (patch) | |
tree | 658282c0e2154e000e46c3fc4fbfd97ccae97fd8 /arch/powerpc/platforms | |
parent | 6ac26c8a7eb149dbd669cc6cd9b77ffc9cd0d2fb (diff) |
[POWERPC] pseries: phyp dump: Use sysfs to release reserved mem
Check to see if there actually is data from a previously
crashed kernel waiting. If so, allow user-space tools to
grab the data (by reading /proc/kcore). When user-space
finishes dumping a section, it must release that memory
by writing to sysfs. For example,
echo "0x40000000 0x10000000" > /sys/kernel/release_region
will release 256MB starting at the 1GB. The released memory
becomes free for general use.
Signed-off-by: Linas Vepstas <linasvepstas@gmail.com>
Signed-off-by: Manish Ahuja <mahuja@us.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/pseries/phyp_dump.c | 81 |
1 files changed, 76 insertions, 5 deletions
diff --git a/arch/powerpc/platforms/pseries/phyp_dump.c b/arch/powerpc/platforms/pseries/phyp_dump.c index 230286cafffe..f355f052a56c 100644 --- a/arch/powerpc/platforms/pseries/phyp_dump.c +++ b/arch/powerpc/platforms/pseries/phyp_dump.c | |||
@@ -12,19 +12,24 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/kobject.h> | ||
15 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/of.h> | ||
16 | #include <linux/pfn.h> | 18 | #include <linux/pfn.h> |
17 | #include <linux/swap.h> | 19 | #include <linux/swap.h> |
20 | #include <linux/sysfs.h> | ||
18 | 21 | ||
19 | #include <asm/page.h> | 22 | #include <asm/page.h> |
20 | #include <asm/phyp_dump.h> | 23 | #include <asm/phyp_dump.h> |
21 | #include <asm/machdep.h> | 24 | #include <asm/machdep.h> |
22 | #include <asm/prom.h> | 25 | #include <asm/prom.h> |
26 | #include <asm/rtas.h> | ||
23 | 27 | ||
24 | /* Variables, used to communicate data between early boot and late boot */ | 28 | /* Variables, used to communicate data between early boot and late boot */ |
25 | static struct phyp_dump phyp_dump_vars; | 29 | static struct phyp_dump phyp_dump_vars; |
26 | struct phyp_dump *phyp_dump_info = &phyp_dump_vars; | 30 | struct phyp_dump *phyp_dump_info = &phyp_dump_vars; |
27 | 31 | ||
32 | /* ------------------------------------------------- */ | ||
28 | /** | 33 | /** |
29 | * release_memory_range -- release memory previously lmb_reserved | 34 | * release_memory_range -- release memory previously lmb_reserved |
30 | * @start_pfn: starting physical frame number | 35 | * @start_pfn: starting physical frame number |
@@ -54,18 +59,84 @@ release_memory_range(unsigned long start_pfn, unsigned long nr_pages) | |||
54 | } | 59 | } |
55 | } | 60 | } |
56 | 61 | ||
57 | static int __init phyp_dump_setup(void) | 62 | /* ------------------------------------------------- */ |
63 | /** | ||
64 | * sysfs_release_region -- sysfs interface to release memory range. | ||
65 | * | ||
66 | * Usage: | ||
67 | * "echo <start addr> <length> > /sys/kernel/release_region" | ||
68 | * | ||
69 | * Example: | ||
70 | * "echo 0x40000000 0x10000000 > /sys/kernel/release_region" | ||
71 | * | ||
72 | * will release 256MB starting at 1GB. | ||
73 | */ | ||
74 | static ssize_t store_release_region(struct kobject *kobj, | ||
75 | struct kobj_attribute *attr, | ||
76 | const char *buf, size_t count) | ||
58 | { | 77 | { |
78 | unsigned long start_addr, length, end_addr; | ||
59 | unsigned long start_pfn, nr_pages; | 79 | unsigned long start_pfn, nr_pages; |
80 | ssize_t ret; | ||
81 | |||
82 | ret = sscanf(buf, "%lx %lx", &start_addr, &length); | ||
83 | if (ret != 2) | ||
84 | return -EINVAL; | ||
85 | |||
86 | /* Range-check - don't free any reserved memory that | ||
87 | * wasn't reserved for phyp-dump */ | ||
88 | if (start_addr < phyp_dump_info->init_reserve_start) | ||
89 | start_addr = phyp_dump_info->init_reserve_start; | ||
90 | |||
91 | end_addr = phyp_dump_info->init_reserve_start + | ||
92 | phyp_dump_info->init_reserve_size; | ||
93 | if (start_addr+length > end_addr) | ||
94 | length = end_addr - start_addr; | ||
95 | |||
96 | /* Release the region of memory assed in by user */ | ||
97 | start_pfn = PFN_DOWN(start_addr); | ||
98 | nr_pages = PFN_DOWN(length); | ||
99 | release_memory_range(start_pfn, nr_pages); | ||
100 | |||
101 | return count; | ||
102 | } | ||
103 | |||
104 | static struct kobj_attribute rr = __ATTR(release_region, 0600, | ||
105 | NULL, store_release_region); | ||
106 | |||
107 | static int __init phyp_dump_setup(void) | ||
108 | { | ||
109 | struct device_node *rtas; | ||
110 | const int *dump_header = NULL; | ||
111 | int header_len = 0; | ||
112 | int rc; | ||
60 | 113 | ||
61 | /* If no memory was reserved in early boot, there is nothing to do */ | 114 | /* If no memory was reserved in early boot, there is nothing to do */ |
62 | if (phyp_dump_info->init_reserve_size == 0) | 115 | if (phyp_dump_info->init_reserve_size == 0) |
63 | return 0; | 116 | return 0; |
64 | 117 | ||
65 | /* Release memory that was reserved in early boot */ | 118 | /* Return if phyp dump not supported */ |
66 | start_pfn = PFN_DOWN(phyp_dump_info->init_reserve_start); | 119 | if (!phyp_dump_info->phyp_dump_configured) |
67 | nr_pages = PFN_DOWN(phyp_dump_info->init_reserve_size); | 120 | return -ENOSYS; |
68 | release_memory_range(start_pfn, nr_pages); | 121 | |
122 | /* Is there dump data waiting for us? */ | ||
123 | rtas = of_find_node_by_path("/rtas"); | ||
124 | if (rtas) { | ||
125 | dump_header = of_get_property(rtas, "ibm,kernel-dump", | ||
126 | &header_len); | ||
127 | of_node_put(rtas); | ||
128 | } | ||
129 | |||
130 | if (dump_header == NULL) | ||
131 | return 0; | ||
132 | |||
133 | /* Should we create a dump_subsys, analogous to s390/ipl.c ? */ | ||
134 | rc = sysfs_create_file(kernel_kobj, &rr.attr); | ||
135 | if (rc) { | ||
136 | printk(KERN_ERR "phyp-dump: unable to create sysfs file (%d)\n", | ||
137 | rc); | ||
138 | return 0; | ||
139 | } | ||
69 | 140 | ||
70 | return 0; | 141 | return 0; |
71 | } | 142 | } |