summaryrefslogtreecommitdiff
path: root/kexec/arch/i386
diff options
context:
space:
mode:
authorChris Leech <christopher.leech@linux.intel.com>2011-03-28 14:50:11 -0700
committerSimon Horman <horms@verge.net.au>2011-03-29 06:55:50 +0900
commit42409b35bef90eed023f783ecffb9004f78b69fa (patch)
tree09b77fe68979fbb5949f369a7d9524f6ef10b869 /kexec/arch/i386
parent0e5e00632f5f6f164d1d6fbdaaff5ea3973917e5 (diff)
kexec, x86: fix kexec when boot_params.hardware_subarch != 0
kexec needs to keep the subarch setting the same as the running kernel in the boot parameters, or the kernel will die in early setup. I ran into this with X86_SUBARCH_MRST, but it should apply to CE4100 and any future subarch that uses non-default early setup code. This patch requires debugfs mounted at /sys/kernel/debug, as that's the only way I know of to get at the running kernels boot_params. Without debugfs mounted it falls back to the current behavior of assuming subarch 0. Signed-off-by: Chris Leech <christopher.leech@linux.intel.com> Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'kexec/arch/i386')
-rw-r--r--kexec/arch/i386/x86-linux-setup.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c
index f843ca4..50b32be 100644
--- a/kexec/arch/i386/x86-linux-setup.c
+++ b/kexec/arch/i386/x86-linux-setup.c
@@ -20,6 +20,7 @@
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
+#include <stddef.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
@@ -396,12 +397,32 @@ out:
real_mode->eddbuf_entries);
}
+#define BOOT_PARAMS_DBGFS "/sys/kernel/debug/boot_params/data"
+
+void setup_subarch(struct x86_linux_param_header *real_mode)
+{
+ int data_file;
+ const off_t offset = offsetof(typeof(*real_mode), hardware_subarch);
+
+ data_file = open(BOOT_PARAMS_DBGFS, O_RDONLY);
+ if (data_file < 0)
+ return;
+ if (lseek(data_file, offset, SEEK_SET) < 0)
+ goto close;
+ read(data_file, &real_mode->hardware_subarch, sizeof(uint32_t));
+close:
+ close(data_file);
+}
+
void setup_linux_system_parameters(struct x86_linux_param_header *real_mode,
unsigned long kexec_flags)
{
/* Fill in information the BIOS would usually provide */
struct memory_range *range;
int i, ranges;
+
+ /* get subarch from running kernel */
+ setup_subarch(real_mode);
/* Default screen size */
real_mode->orig_x = 0;