aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/kexec.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-04-26 12:12:12 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-04-26 12:12:12 +0100
commitc1cfb1a358c12bdf1284f6bcf55407366efaf485 (patch)
tree6dedec1891e2f79822663ae6c8b881e938665b04 /xen/common/kexec.c
parentefaca454ab76878603ed9c2ce61b94e9bba0fe35 (diff)
downloadxen-c1cfb1a358c12bdf1284f6bcf55407366efaf485.tar.gz
xen-c1cfb1a358c12bdf1284f6bcf55407366efaf485.tar.bz2
xen-c1cfb1a358c12bdf1284f6bcf55407366efaf485.zip
Support Linux's advanced crashkernel= syntax
Quoting the original Linux patch's description: "This patch adds a extended crashkernel syntax that makes the value of reserved system RAM dependent on the system RAM itself: crashkernel=3D<range1>:<size1>[,<range2>:<size2>,...][@offset] range=3Dstart-[end] For example: crashkernel=3D512M-2G:64M,2G-:128M The motivation comes from distributors that configure their crashkernel command line automatically with some configuration tool (YaST, you know ;)). Of course that tool knows the value of System RAM, but if the user removes RAM, then the system becomes unbootable or at least unusable and error handling is very difficult." For x86, other than Linux we pass the actual amount of RAM rather than the highest page's address (to cope with sparse physical address maps). This still needs to be hooked up for ia64. Signed-off-by: Jan Beulich <jbeulich@novell.com>
Diffstat (limited to 'xen/common/kexec.c')
-rw-r--r--xen/common/kexec.c100
1 files changed, 97 insertions, 3 deletions
diff --git a/xen/common/kexec.c b/xen/common/kexec.c
index 56196167b8..e4dc1f0390 100644
--- a/xen/common/kexec.c
+++ b/xen/common/kexec.c
@@ -47,15 +47,109 @@ static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
static size_t vmcoreinfo_size = 0;
xen_kexec_reserve_t kexec_crash_area;
+static struct {
+ u64 start, end;
+ unsigned long size;
+} ranges[16] __initdata;
+/*
+ * Parse command lines in the format
+ *
+ * crashkernel=<ramsize-range>:<size>[,...][@<offset>]
+ *
+ * with <ramsize-range> being of form
+ *
+ * <start>-[<end>]
+ *
+ * as well as the legacy ones in the format
+ *
+ * crashkernel=<size>[@<offset>]
+ */
static void __init parse_crashkernel(const char *str)
{
- kexec_crash_area.size = parse_size_and_unit(str, &str);
- if ( *str == '@' )
- kexec_crash_area.start = parse_size_and_unit(str+1, NULL);
+ const char *cur;
+
+ if ( strchr(str, ':' ) )
+ {
+ unsigned int idx = 0;
+
+ do {
+ if ( idx >= ARRAY_SIZE(ranges) )
+ {
+ printk(XENLOG_WARNING "crashkernel: too many ranges\n");
+ cur = NULL;
+ str = strchr(str, '@');
+ break;
+ }
+
+ ranges[idx].start = parse_size_and_unit(cur = str + !!idx, &str);
+ if ( cur == str )
+ break;
+
+ if ( *str != '-' )
+ {
+ printk(XENLOG_WARNING "crashkernel: '-' expected\n");
+ break;
+ }
+
+ if ( *++str != ':' )
+ {
+ ranges[idx].end = parse_size_and_unit(cur = str, &str);
+ if ( cur == str )
+ break;
+ if ( ranges[idx].end <= ranges[idx].start )
+ {
+ printk(XENLOG_WARNING "crashkernel: end <= start\n");
+ break;
+ }
+ }
+ else
+ ranges[idx].end = -1;
+
+ if ( *str != ':' )
+ {
+ printk(XENLOG_WARNING "crashkernel: ':' expected\n");
+ break;
+ }
+
+ ranges[idx].size = parse_size_and_unit(cur = str + 1, &str);
+ if ( cur == str )
+ break;
+
+ ++idx;
+ } while ( *str == ',' );
+ if ( idx < ARRAY_SIZE(ranges) )
+ ranges[idx].size = 0;
+ }
+ else
+ kexec_crash_area.size = parse_size_and_unit(cur = str, &str);
+ if ( cur != str && *str == '@' )
+ kexec_crash_area.start = parse_size_and_unit(cur = str + 1, &str);
+ if ( cur == str )
+ printk(XENLOG_WARNING "crashkernel: memory value expected\n");
}
custom_param("crashkernel", parse_crashkernel);
+void __init set_kexec_crash_area_size(u64 system_ram)
+{
+ unsigned int idx;
+
+ for ( idx = 0; idx < ARRAY_SIZE(ranges) && !kexec_crash_area.size; ++idx )
+ {
+ if ( !ranges[idx].size )
+ break;
+
+ if ( ranges[idx].size >= system_ram )
+ {
+ printk(XENLOG_WARNING "crashkernel: invalid size\n");
+ continue;
+ }
+
+ if ( ranges[idx].start <= system_ram && ranges[idx].end > system_ram )
+ kexec_crash_area.size = ranges[idx].size;
+ }
+}
+
static void one_cpu_only(void)
{
/* Only allow the first cpu to continue - force other cpus to spin */