aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/machine_kexec_32.c
diff options
context:
space:
mode:
authorHuang Ying <ying.huang@intel.com>2008-10-30 21:48:08 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-31 05:01:56 -0400
commit92be3d6bdf2cb34972ab50e12ad4da1076e690da (patch)
tree6ed10cb8a14615ca0bda48f64520c82480397d00 /arch/x86/kernel/machine_kexec_32.c
parent31498a01496ffca3b542bae72b8ec499cd9302db (diff)
kexec/i386: allocate page table pages dynamically
Impact: save .text size when kexec is built in but not loaded This patch adds an architecture specific struct kimage_arch into struct kimage. The pointers to page table pages used by kexec are added to struct kimage_arch. The page tables pages are dynamically allocated in machine_kexec_prepare instead of statically from BSS segment. This will save up to 20k memory when kexec image is not loaded. Signed-off-by: Huang Ying <ying.huang@intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/machine_kexec_32.c')
-rw-r--r--arch/x86/kernel/machine_kexec_32.c67
1 files changed, 46 insertions, 21 deletions
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
index 7a385746509a..1100312847a5 100644
--- a/arch/x86/kernel/machine_kexec_32.c
+++ b/arch/x86/kernel/machine_kexec_32.c
@@ -13,6 +13,7 @@
13#include <linux/numa.h> 13#include <linux/numa.h>
14#include <linux/ftrace.h> 14#include <linux/ftrace.h>
15#include <linux/suspend.h> 15#include <linux/suspend.h>
16#include <linux/gfp.h>
16 17
17#include <asm/pgtable.h> 18#include <asm/pgtable.h>
18#include <asm/pgalloc.h> 19#include <asm/pgalloc.h>
@@ -25,15 +26,6 @@
25#include <asm/system.h> 26#include <asm/system.h>
26#include <asm/cacheflush.h> 27#include <asm/cacheflush.h>
27 28
28#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
29static u32 kexec_pgd[1024] PAGE_ALIGNED;
30#ifdef CONFIG_X86_PAE
31static u32 kexec_pmd0[1024] PAGE_ALIGNED;
32static u32 kexec_pmd1[1024] PAGE_ALIGNED;
33#endif
34static u32 kexec_pte0[1024] PAGE_ALIGNED;
35static u32 kexec_pte1[1024] PAGE_ALIGNED;
36
37static void set_idt(void *newidt, __u16 limit) 29static void set_idt(void *newidt, __u16 limit)
38{ 30{
39 struct desc_ptr curidt; 31 struct desc_ptr curidt;
@@ -76,6 +68,37 @@ static void load_segments(void)
76#undef __STR 68#undef __STR
77} 69}
78 70
71static void machine_kexec_free_page_tables(struct kimage *image)
72{
73 free_page((unsigned long)image->arch.pgd);
74#ifdef CONFIG_X86_PAE
75 free_page((unsigned long)image->arch.pmd0);
76 free_page((unsigned long)image->arch.pmd1);
77#endif
78 free_page((unsigned long)image->arch.pte0);
79 free_page((unsigned long)image->arch.pte1);
80}
81
82static int machine_kexec_alloc_page_tables(struct kimage *image)
83{
84 image->arch.pgd = (pgd_t *)get_zeroed_page(GFP_KERNEL);
85#ifdef CONFIG_X86_PAE
86 image->arch.pmd0 = (pmd_t *)get_zeroed_page(GFP_KERNEL);
87 image->arch.pmd1 = (pmd_t *)get_zeroed_page(GFP_KERNEL);
88#endif
89 image->arch.pte0 = (pte_t *)get_zeroed_page(GFP_KERNEL);
90 image->arch.pte1 = (pte_t *)get_zeroed_page(GFP_KERNEL);
91 if (!image->arch.pgd ||
92#ifdef CONFIG_X86_PAE
93 !image->arch.pmd0 || !image->arch.pmd1 ||
94#endif
95 !image->arch.pte0 || !image->arch.pte1) {
96 machine_kexec_free_page_tables(image);
97 return -ENOMEM;
98 }
99 return 0;
100}
101
79/* 102/*
80 * A architecture hook called to validate the 103 * A architecture hook called to validate the
81 * proposed image and prepare the control pages 104 * proposed image and prepare the control pages
@@ -87,13 +110,14 @@ static void load_segments(void)
87 * reboot code buffer to allow us to avoid allocations 110 * reboot code buffer to allow us to avoid allocations
88 * later. 111 * later.
89 * 112 *
90 * Make control page executable. 113 * - Make control page executable.
114 * - Allocate page tables
91 */ 115 */
92int machine_kexec_prepare(struct kimage *image) 116int machine_kexec_prepare(struct kimage *image)
93{ 117{
94 if (nx_enabled) 118 if (nx_enabled)
95 set_pages_x(image->control_code_page, 1); 119 set_pages_x(image->control_code_page, 1);
96 return 0; 120 return machine_kexec_alloc_page_tables(image);
97} 121}
98 122
99/* 123/*
@@ -104,6 +128,7 @@ void machine_kexec_cleanup(struct kimage *image)
104{ 128{
105 if (nx_enabled) 129 if (nx_enabled)
106 set_pages_nx(image->control_code_page, 1); 130 set_pages_nx(image->control_code_page, 1);
131 machine_kexec_free_page_tables(image);
107} 132}
108 133
109/* 134/*
@@ -150,18 +175,18 @@ void machine_kexec(struct kimage *image)
150 relocate_kernel_ptr = control_page; 175 relocate_kernel_ptr = control_page;
151 page_list[PA_CONTROL_PAGE] = __pa(control_page); 176 page_list[PA_CONTROL_PAGE] = __pa(control_page);
152 page_list[VA_CONTROL_PAGE] = (unsigned long)control_page; 177 page_list[VA_CONTROL_PAGE] = (unsigned long)control_page;
153 page_list[PA_PGD] = __pa(kexec_pgd); 178 page_list[PA_PGD] = __pa(image->arch.pgd);
154 page_list[VA_PGD] = (unsigned long)kexec_pgd; 179 page_list[VA_PGD] = (unsigned long)image->arch.pgd;
155#ifdef CONFIG_X86_PAE 180#ifdef CONFIG_X86_PAE
156 page_list[PA_PMD_0] = __pa(kexec_pmd0); 181 page_list[PA_PMD_0] = __pa(image->arch.pmd0);
157 page_list[VA_PMD_0] = (unsigned long)kexec_pmd0; 182 page_list[VA_PMD_0] = (unsigned long)image->arch.pmd0;
158 page_list[PA_PMD_1] = __pa(kexec_pmd1); 183 page_list[PA_PMD_1] = __pa(image->arch.pmd1);
159 page_list[VA_PMD_1] = (unsigned long)kexec_pmd1; 184 page_list[VA_PMD_1] = (unsigned long)image->arch.pmd1;
160#endif 185#endif
161 page_list[PA_PTE_0] = __pa(kexec_pte0); 186 page_list[PA_PTE_0] = __pa(image->arch.pte0);
162 page_list[VA_PTE_0] = (unsigned long)kexec_pte0; 187 page_list[VA_PTE_0] = (unsigned long)image->arch.pte0;
163 page_list[PA_PTE_1] = __pa(kexec_pte1); 188 page_list[PA_PTE_1] = __pa(image->arch.pte1);
164 page_list[VA_PTE_1] = (unsigned long)kexec_pte1; 189 page_list[VA_PTE_1] = (unsigned long)image->arch.pte1;
165 190
166 if (image->type == KEXEC_TYPE_DEFAULT) 191 if (image->type == KEXEC_TYPE_DEFAULT)
167 page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page) 192 page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page)