[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <tip-084d1283986a530828b8898f206adf44d5d3146d@git.kernel.org>
Date: Tue, 29 Jan 2013 17:42:09 -0800
From: tip-bot for Yinghai Lu <yinghai@...nel.org>
To: linux-tip-commits@...r.kernel.org
Cc: linux-kernel@...r.kernel.org, hpa@...or.com, mingo@...nel.org,
yinghai@...nel.org, tglx@...utronix.de, hpa@...ux.intel.com
Subject: [tip:x86/mm2] x86, kexec:
Set ident mapping for kernel that is above max_pfn
Commit-ID: 084d1283986a530828b8898f206adf44d5d3146d
Gitweb: http://git.kernel.org/tip/084d1283986a530828b8898f206adf44d5d3146d
Author: Yinghai Lu <yinghai@...nel.org>
AuthorDate: Thu, 24 Jan 2013 12:20:03 -0800
Committer: H. Peter Anvin <hpa@...ux.intel.com>
CommitDate: Tue, 29 Jan 2013 15:26:26 -0800
x86, kexec: Set ident mapping for kernel that is above max_pfn
When first kernel is booted with memmap= or mem= to limit max_pfn.
kexec can load second kernel above that max_pfn.
We need to set ident mapping for whole image in this case instead of just
for first 2M.
Signed-off-by: Yinghai Lu <yinghai@...nel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-23-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@...ux.intel.com>
---
arch/x86/kernel/machine_kexec_64.c | 43 ++++++++++++++++++++++++++++++++------
1 file changed, 37 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index b3ea9db..be14ee1 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -56,6 +56,25 @@ out:
return result;
}
+static int ident_mapping_init(struct kimage *image, pgd_t *level4p,
+ unsigned long mstart, unsigned long mend)
+{
+ int result;
+
+ mstart = round_down(mstart, PMD_SIZE);
+ mend = round_up(mend - 1, PMD_SIZE);
+
+ while (mstart < mend) {
+ result = init_one_level2_page(image, level4p, mstart);
+ if (result)
+ return result;
+
+ mstart += PMD_SIZE;
+ }
+
+ return 0;
+}
+
static void init_level2_page(pmd_t *level2p, unsigned long addr)
{
unsigned long end_addr;
@@ -184,22 +203,34 @@ err:
return result;
}
-
static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
{
+ unsigned long mstart, mend;
pgd_t *level4p;
int result;
+ int i;
+
level4p = (pgd_t *)__va(start_pgtable);
result = init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT);
if (result)
return result;
+
/*
- * image->start may be outside 0 ~ max_pfn, for example when
- * jump back to original kernel from kexeced kernel
+ * segments's mem ranges could be outside 0 ~ max_pfn,
+ * for example when jump back to original kernel from kexeced kernel.
+ * or first kernel is booted with user mem map, and second kernel
+ * could be loaded out of that range.
*/
- result = init_one_level2_page(image, level4p, image->start);
- if (result)
- return result;
+ for (i = 0; i < image->nr_segments; i++) {
+ mstart = image->segment[i].mem;
+ mend = mstart + image->segment[i].memsz;
+
+ result = ident_mapping_init(image, level4p, mstart, mend);
+
+ if (result)
+ return result;
+ }
+
return init_transition_pgtable(image, level4p);
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists