aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2009-03-12 19:09:49 -0400
committerH. Peter Anvin <hpa@zytor.com>2009-03-14 20:23:47 -0400
commit796216a57fe45c04adc35bda1f0782efec78a713 (patch)
tree7f94407dfa2ccc2ab7a8e2b3e09cee04290f0ca1
parent7543c1de84ed93c6769c9f20dced08a522af8912 (diff)
x86: allow extend_brk users to reserve brk space
Impact: new interface; remove hard-coded limit Add RESERVE_BRK(name, size) macro to reserve space in the brk area. This should be a conservative (ie, larger) estimate of how much space might possibly be required from the brk area. Any unused space will be freed, so there's no real downside on making the reservation too large (within limits). The name should be unique within a given file, and somewhat descriptive. The C definition of RESERVE_BRK() ends up being more complex than one would expect to work around a cluster of gcc infelicities: The first attempt was to simply try putting __section(.brk_reservation) on a variable. This doesn't work because it ends up making it a @progbits section, which gets actual space allocated in the vmlinux executable. The second attempt was to emit the space into a section using asm, but gcc doesn't allow arguments to be passed to file-level asm() statements, making it hard to pass in the size. The final attempt is to wrap the asm() in a function to allow it to have arguments, and put the function itself into the .discard section, which vmlinux*.lds drops entirely from the emitted vmlinux. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--arch/x86/include/asm/setup.h30
-rw-r--r--arch/x86/kernel/head_32.S2
-rw-r--r--arch/x86/kernel/setup.c2
-rw-r--r--arch/x86/kernel/vmlinux_32.lds.S4
-rw-r--r--arch/x86/kernel/vmlinux_64.lds.S4
5 files changed, 40 insertions, 2 deletions
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index 366d36639940..61b126b97885 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -104,6 +104,29 @@ extern struct boot_params boot_params;
104extern unsigned long _brk_end; 104extern unsigned long _brk_end;
105void *extend_brk(size_t size, size_t align); 105void *extend_brk(size_t size, size_t align);
106 106
107/*
108 * Reserve space in the brk section. The name must be unique within
109 * the file, and somewhat descriptive. The size is in bytes. Must be
110 * used at file scope.
111 *
112 * (This uses a temp function to wrap the asm so we can pass it the
113 * size parameter; otherwise we wouldn't be able to. We can't use a
114 * "section" attribute on a normal variable because it always ends up
115 * being @progbits, which ends up allocating space in the vmlinux
116 * executable.)
117 */
118#define RESERVE_BRK(name,sz) \
119 static void __section(.discard) __used \
120 __brk_reservation_fn_##name##__(void) { \
121 asm volatile ( \
122 ".pushsection .brk_reservation,\"aw\",@nobits;" \
123 "__brk_reservation_" #name "__:" \
124 " 1:.skip %c0;" \
125 " .size __brk_reservation_" #name "__, . - 1b;" \
126 " .popsection" \
127 : : "i" (sz)); \
128 }
129
107#ifdef __i386__ 130#ifdef __i386__
108 131
109void __init i386_start_kernel(void); 132void __init i386_start_kernel(void);
@@ -115,6 +138,13 @@ void __init x86_64_start_reservations(char *real_mode_data);
115 138
116#endif /* __i386__ */ 139#endif /* __i386__ */
117#endif /* _SETUP */ 140#endif /* _SETUP */
141#else
142#define RESERVE_BRK(name,sz) \
143 .pushsection .brk_reservation,"aw",@nobits; \
144__brk_reservation_##name##__: \
1451: .skip sz; \
146 .size __brk_reservation_##name##__,.-1b; \
147 .popsection
118#endif /* __ASSEMBLY__ */ 148#endif /* __ASSEMBLY__ */
119#endif /* __KERNEL__ */ 149#endif /* __KERNEL__ */
120 150
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 3ce5456dfbe6..9e89f2a14b90 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -75,6 +75,8 @@ ALLOCATOR_SLOP = 4
75 75
76INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_SIZE_asm 76INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_SIZE_asm
77 77
78RESERVE_BRK(pagetables, PAGE_TABLE_SIZE * PAGE_SIZE)
79
78/* 80/*
79 * 32-bit kernel entrypoint; only used by the boot CPU. On entry, 81 * 32-bit kernel entrypoint; only used by the boot CPU. On entry,
80 * %esi points to the real-mode code as a 32-bit pointer. 82 * %esi points to the real-mode code as a 32-bit pointer.
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index e894f36335f2..a0d26237d7cf 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -112,6 +112,8 @@
112#define ARCH_SETUP 112#define ARCH_SETUP
113#endif 113#endif
114 114
115RESERVE_BRK(dmi_alloc, 65536);
116
115unsigned int boot_cpu_id __read_mostly; 117unsigned int boot_cpu_id __read_mostly;
116 118
117static __initdata unsigned long _brk_start = (unsigned long)__brk_base; 119static __initdata unsigned long _brk_start = (unsigned long)__brk_base;
diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S
index 1063fbe93c73..a1f28b85fb34 100644
--- a/arch/x86/kernel/vmlinux_32.lds.S
+++ b/arch/x86/kernel/vmlinux_32.lds.S
@@ -192,7 +192,8 @@ SECTIONS
192 192
193 . = ALIGN(PAGE_SIZE); 193 . = ALIGN(PAGE_SIZE);
194 __brk_base = . ; 194 __brk_base = . ;
195 . += 1024 * 1024 ; 195 . += 64 * 1024 ; /* 64k slop space */
196 *(.brk_reservation) /* areas brk users have reserved */
196 __brk_limit = . ; 197 __brk_limit = . ;
197 198
198 _end = . ; 199 _end = . ;
@@ -201,6 +202,7 @@ SECTIONS
201 /* Sections to be discarded */ 202 /* Sections to be discarded */
202 /DISCARD/ : { 203 /DISCARD/ : {
203 *(.exitcall.exit) 204 *(.exitcall.exit)
205 *(.discard)
204 } 206 }
205 207
206 STABS_DEBUG 208 STABS_DEBUG
diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S
index ff373423138c..7996687663a2 100644
--- a/arch/x86/kernel/vmlinux_64.lds.S
+++ b/arch/x86/kernel/vmlinux_64.lds.S
@@ -250,7 +250,8 @@ SECTIONS
250 250
251 . = ALIGN(PAGE_SIZE); 251 . = ALIGN(PAGE_SIZE);
252 __brk_base = . ; 252 __brk_base = . ;
253 . += 1024 * 1024 ; 253 . += 64 * 1024; /* 64k slop space */
254 *(.brk_reservation) /* areas brk users have reserved */
254 __brk_limit = . ; 255 __brk_limit = . ;
255 } 256 }
256 257
@@ -260,6 +261,7 @@ SECTIONS
260 /DISCARD/ : { 261 /DISCARD/ : {
261 *(.exitcall.exit) 262 *(.exitcall.exit)
262 *(.eh_frame) 263 *(.eh_frame)
264 *(.discard)
263 } 265 }
264 266
265 STABS_DEBUG 267 STABS_DEBUG