diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/kexec.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c index fbffdb457cce..aa74a1ef2da8 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
| @@ -1146,6 +1146,172 @@ static int __init crash_notes_memory_init(void) | |||
| 1146 | } | 1146 | } |
| 1147 | module_init(crash_notes_memory_init) | 1147 | module_init(crash_notes_memory_init) |
| 1148 | 1148 | ||
| 1149 | |||
| 1150 | /* | ||
| 1151 | * parsing the "crashkernel" commandline | ||
| 1152 | * | ||
| 1153 | * this code is intended to be called from architecture specific code | ||
| 1154 | */ | ||
| 1155 | |||
| 1156 | |||
| 1157 | /* | ||
| 1158 | * This function parses command lines in the format | ||
| 1159 | * | ||
| 1160 | * crashkernel=ramsize-range:size[,...][@offset] | ||
| 1161 | * | ||
| 1162 | * The function returns 0 on success and -EINVAL on failure. | ||
| 1163 | */ | ||
| 1164 | static int __init parse_crashkernel_mem(char *cmdline, | ||
| 1165 | unsigned long long system_ram, | ||
| 1166 | unsigned long long *crash_size, | ||
| 1167 | unsigned long long *crash_base) | ||
| 1168 | { | ||
| 1169 | char *cur = cmdline, *tmp; | ||
| 1170 | |||
| 1171 | /* for each entry of the comma-separated list */ | ||
| 1172 | do { | ||
| 1173 | unsigned long long start, end = ULLONG_MAX, size; | ||
| 1174 | |||
| 1175 | /* get the start of the range */ | ||
| 1176 | start = memparse(cur, &tmp); | ||
| 1177 | if (cur == tmp) { | ||
| 1178 | pr_warning("crashkernel: Memory value expected\n"); | ||
| 1179 | return -EINVAL; | ||
| 1180 | } | ||
| 1181 | cur = tmp; | ||
| 1182 | if (*cur != '-') { | ||
| 1183 | pr_warning("crashkernel: '-' expected\n"); | ||
| 1184 | return -EINVAL; | ||
| 1185 | } | ||
| 1186 | cur++; | ||
| 1187 | |||
| 1188 | /* if no ':' is here, than we read the end */ | ||
| 1189 | if (*cur != ':') { | ||
| 1190 | end = memparse(cur, &tmp); | ||
| 1191 | if (cur == tmp) { | ||
| 1192 | pr_warning("crashkernel: Memory " | ||
| 1193 | "value expected\n"); | ||
| 1194 | return -EINVAL; | ||
| 1195 | } | ||
| 1196 | cur = tmp; | ||
| 1197 | if (end <= start) { | ||
| 1198 | pr_warning("crashkernel: end <= start\n"); | ||
| 1199 | return -EINVAL; | ||
| 1200 | } | ||
| 1201 | } | ||
| 1202 | |||
| 1203 | if (*cur != ':') { | ||
| 1204 | pr_warning("crashkernel: ':' expected\n"); | ||
| 1205 | return -EINVAL; | ||
| 1206 | } | ||
| 1207 | cur++; | ||
| 1208 | |||
| 1209 | size = memparse(cur, &tmp); | ||
| 1210 | if (cur == tmp) { | ||
| 1211 | pr_warning("Memory value expected\n"); | ||
| 1212 | return -EINVAL; | ||
| 1213 | } | ||
| 1214 | cur = tmp; | ||
| 1215 | if (size >= system_ram) { | ||
| 1216 | pr_warning("crashkernel: invalid size\n"); | ||
| 1217 | return -EINVAL; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | /* match ? */ | ||
| 1221 | if (system_ram >= start && system_ram <= end) { | ||
| 1222 | *crash_size = size; | ||
| 1223 | break; | ||
| 1224 | } | ||
| 1225 | } while (*cur++ == ','); | ||
| 1226 | |||
| 1227 | if (*crash_size > 0) { | ||
| 1228 | while (*cur != ' ' && *cur != '@') | ||
| 1229 | cur++; | ||
| 1230 | if (*cur == '@') { | ||
| 1231 | cur++; | ||
| 1232 | *crash_base = memparse(cur, &tmp); | ||
| 1233 | if (cur == tmp) { | ||
| 1234 | pr_warning("Memory value expected " | ||
| 1235 | "after '@'\n"); | ||
| 1236 | return -EINVAL; | ||
| 1237 | } | ||
| 1238 | } | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | return 0; | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | /* | ||
| 1245 | * That function parses "simple" (old) crashkernel command lines like | ||
| 1246 | * | ||
| 1247 | * crashkernel=size[@offset] | ||
| 1248 | * | ||
| 1249 | * It returns 0 on success and -EINVAL on failure. | ||
| 1250 | */ | ||
| 1251 | static int __init parse_crashkernel_simple(char *cmdline, | ||
| 1252 | unsigned long long *crash_size, | ||
| 1253 | unsigned long long *crash_base) | ||
| 1254 | { | ||
| 1255 | char *cur = cmdline; | ||
| 1256 | |||
| 1257 | *crash_size = memparse(cmdline, &cur); | ||
| 1258 | if (cmdline == cur) { | ||
| 1259 | pr_warning("crashkernel: memory value expected\n"); | ||
| 1260 | return -EINVAL; | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | if (*cur == '@') | ||
| 1264 | *crash_base = memparse(cur+1, &cur); | ||
| 1265 | |||
| 1266 | return 0; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | /* | ||
| 1270 | * That function is the entry point for command line parsing and should be | ||
| 1271 | * called from the arch-specific code. | ||
| 1272 | */ | ||
| 1273 | int __init parse_crashkernel(char *cmdline, | ||
| 1274 | unsigned long long system_ram, | ||
| 1275 | unsigned long long *crash_size, | ||
| 1276 | unsigned long long *crash_base) | ||
| 1277 | { | ||
| 1278 | char *p = cmdline, *ck_cmdline = NULL; | ||
| 1279 | char *first_colon, *first_space; | ||
| 1280 | |||
| 1281 | BUG_ON(!crash_size || !crash_base); | ||
| 1282 | *crash_size = 0; | ||
| 1283 | *crash_base = 0; | ||
| 1284 | |||
| 1285 | /* find crashkernel and use the last one if there are more */ | ||
| 1286 | p = strstr(p, "crashkernel="); | ||
| 1287 | while (p) { | ||
| 1288 | ck_cmdline = p; | ||
| 1289 | p = strstr(p+1, "crashkernel="); | ||
| 1290 | } | ||
| 1291 | |||
| 1292 | if (!ck_cmdline) | ||
| 1293 | return -EINVAL; | ||
| 1294 | |||
| 1295 | ck_cmdline += 12; /* strlen("crashkernel=") */ | ||
| 1296 | |||
| 1297 | /* | ||
| 1298 | * if the commandline contains a ':', then that's the extended | ||
| 1299 | * syntax -- if not, it must be the classic syntax | ||
| 1300 | */ | ||
| 1301 | first_colon = strchr(ck_cmdline, ':'); | ||
| 1302 | first_space = strchr(ck_cmdline, ' '); | ||
| 1303 | if (first_colon && (!first_space || first_colon < first_space)) | ||
| 1304 | return parse_crashkernel_mem(ck_cmdline, system_ram, | ||
| 1305 | crash_size, crash_base); | ||
| 1306 | else | ||
| 1307 | return parse_crashkernel_simple(ck_cmdline, crash_size, | ||
| 1308 | crash_base); | ||
| 1309 | |||
| 1310 | return 0; | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | |||
| 1314 | |||
| 1149 | void crash_save_vmcoreinfo(void) | 1315 | void crash_save_vmcoreinfo(void) |
| 1150 | { | 1316 | { |
| 1151 | u32 *buf; | 1317 | u32 *buf; |
