ia64/linux-2.6.18-xen.hg

view arch/alpha/kernel/module.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /* Kernel module help for Alpha.
2 Copyright (C) 2002 Richard Henderson.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 #include <linux/moduleloader.h>
19 #include <linux/elf.h>
20 #include <linux/vmalloc.h>
21 #include <linux/fs.h>
22 #include <linux/string.h>
23 #include <linux/kernel.h>
24 #include <linux/slab.h>
26 #if 0
27 #define DEBUGP printk
28 #else
29 #define DEBUGP(fmt...)
30 #endif
32 void *
33 module_alloc(unsigned long size)
34 {
35 if (size == 0)
36 return NULL;
37 return vmalloc(size);
38 }
40 void
41 module_free(struct module *mod, void *module_region)
42 {
43 vfree(module_region);
44 }
46 /* Allocate the GOT at the end of the core sections. */
48 struct got_entry {
49 struct got_entry *next;
50 Elf64_Sxword r_addend;
51 int got_offset;
52 };
54 static inline void
55 process_reloc_for_got(Elf64_Rela *rela,
56 struct got_entry *chains, Elf64_Xword *poffset)
57 {
58 unsigned long r_sym = ELF64_R_SYM (rela->r_info);
59 unsigned long r_type = ELF64_R_TYPE (rela->r_info);
60 Elf64_Sxword r_addend = rela->r_addend;
61 struct got_entry *g;
63 if (r_type != R_ALPHA_LITERAL)
64 return;
66 for (g = chains + r_sym; g ; g = g->next)
67 if (g->r_addend == r_addend) {
68 if (g->got_offset == 0) {
69 g->got_offset = *poffset;
70 *poffset += 8;
71 }
72 goto found_entry;
73 }
75 g = kmalloc (sizeof (*g), GFP_KERNEL);
76 g->next = chains[r_sym].next;
77 g->r_addend = r_addend;
78 g->got_offset = *poffset;
79 *poffset += 8;
80 chains[r_sym].next = g;
82 found_entry:
83 /* Trick: most of the ELF64_R_TYPE field is unused. There are
84 42 valid relocation types, and a 32-bit field. Co-opt the
85 bits above 256 to store the got offset for this reloc. */
86 rela->r_info |= g->got_offset << 8;
87 }
89 int
90 module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs,
91 char *secstrings, struct module *me)
92 {
93 struct got_entry *chains;
94 Elf64_Rela *rela;
95 Elf64_Shdr *esechdrs, *symtab, *s, *got;
96 unsigned long nsyms, nrela, i;
98 esechdrs = sechdrs + hdr->e_shnum;
99 symtab = got = NULL;
101 /* Find out how large the symbol table is. Allocate one got_entry
102 head per symbol. Normally this will be enough, but not always.
103 We'll chain different offsets for the symbol down each head. */
104 for (s = sechdrs; s < esechdrs; ++s)
105 if (s->sh_type == SHT_SYMTAB)
106 symtab = s;
107 else if (!strcmp(".got", secstrings + s->sh_name)) {
108 got = s;
109 me->arch.gotsecindex = s - sechdrs;
110 }
112 if (!symtab) {
113 printk(KERN_ERR "module %s: no symbol table\n", me->name);
114 return -ENOEXEC;
115 }
116 if (!got) {
117 printk(KERN_ERR "module %s: no got section\n", me->name);
118 return -ENOEXEC;
119 }
121 nsyms = symtab->sh_size / sizeof(Elf64_Sym);
122 chains = kmalloc(nsyms * sizeof(struct got_entry), GFP_KERNEL);
123 memset(chains, 0, nsyms * sizeof(struct got_entry));
125 got->sh_size = 0;
126 got->sh_addralign = 8;
127 got->sh_type = SHT_NOBITS;
129 /* Examine all LITERAL relocations to find out what GOT entries
130 are required. This sizes the GOT section as well. */
131 for (s = sechdrs; s < esechdrs; ++s)
132 if (s->sh_type == SHT_RELA) {
133 nrela = s->sh_size / sizeof(Elf64_Rela);
134 rela = (void *)hdr + s->sh_offset;
135 for (i = 0; i < nrela; ++i)
136 process_reloc_for_got(rela+i, chains,
137 &got->sh_size);
138 }
140 /* Free the memory we allocated. */
141 for (i = 0; i < nsyms; ++i) {
142 struct got_entry *g, *n;
143 for (g = chains[i].next; g ; g = n) {
144 n = g->next;
145 kfree(g);
146 }
147 }
148 kfree(chains);
150 return 0;
151 }
153 int
154 apply_relocate(Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex,
155 unsigned int relsec, struct module *me)
156 {
157 printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name);
158 return -ENOEXEC;
159 }
161 int
162 apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab,
163 unsigned int symindex, unsigned int relsec,
164 struct module *me)
165 {
166 Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr;
167 unsigned long i, n = sechdrs[relsec].sh_size / sizeof(*rela);
168 Elf64_Sym *symtab, *sym;
169 void *base, *location;
170 unsigned long got, gp;
172 DEBUGP("Applying relocate section %u to %u\n", relsec,
173 sechdrs[relsec].sh_info);
175 base = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr;
176 symtab = (Elf64_Sym *)sechdrs[symindex].sh_addr;
178 /* The small sections were sorted to the end of the segment.
179 The following should definitely cover them. */
180 gp = (u64)me->module_core + me->core_size - 0x8000;
181 got = sechdrs[me->arch.gotsecindex].sh_addr;
183 for (i = 0; i < n; i++) {
184 unsigned long r_sym = ELF64_R_SYM (rela[i].r_info);
185 unsigned long r_type = ELF64_R_TYPE (rela[i].r_info);
186 unsigned long r_got_offset = r_type >> 8;
187 unsigned long value, hi, lo;
188 r_type &= 0xff;
190 /* This is where to make the change. */
191 location = base + rela[i].r_offset;
193 /* This is the symbol it is referring to. Note that all
194 unresolved symbols have been resolved. */
195 sym = symtab + r_sym;
196 value = sym->st_value + rela[i].r_addend;
198 switch (r_type) {
199 case R_ALPHA_NONE:
200 break;
201 case R_ALPHA_REFQUAD:
202 /* BUG() can produce misaligned relocations. */
203 ((u32 *)location)[0] = value;
204 ((u32 *)location)[1] = value >> 32;
205 break;
206 case R_ALPHA_GPREL32:
207 value -= gp;
208 if ((int)value != value)
209 goto reloc_overflow;
210 *(u32 *)location = value;
211 break;
212 case R_ALPHA_LITERAL:
213 hi = got + r_got_offset;
214 lo = hi - gp;
215 if ((short)lo != lo)
216 goto reloc_overflow;
217 *(u16 *)location = lo;
218 *(u64 *)hi = value;
219 break;
220 case R_ALPHA_LITUSE:
221 break;
222 case R_ALPHA_GPDISP:
223 value = gp - (u64)location;
224 lo = (short)value;
225 hi = (int)(value - lo);
226 if (hi + lo != value)
227 goto reloc_overflow;
228 *(u16 *)location = hi >> 16;
229 *(u16 *)(location + rela[i].r_addend) = lo;
230 break;
231 case R_ALPHA_BRSGP:
232 /* BRSGP is only allowed to bind to local symbols.
233 If the section is undef, this means that the
234 value was resolved from somewhere else. */
235 if (sym->st_shndx == SHN_UNDEF)
236 goto reloc_overflow;
237 if ((sym->st_other & STO_ALPHA_STD_GPLOAD) ==
238 STO_ALPHA_STD_GPLOAD)
239 /* Omit the prologue. */
240 value += 8;
241 /* FALLTHRU */
242 case R_ALPHA_BRADDR:
243 value -= (u64)location + 4;
244 if (value & 3)
245 goto reloc_overflow;
246 value = (long)value >> 2;
247 if (value + (1<<21) >= 1<<22)
248 goto reloc_overflow;
249 value &= 0x1fffff;
250 value |= *(u32 *)location & ~0x1fffff;
251 *(u32 *)location = value;
252 break;
253 case R_ALPHA_HINT:
254 break;
255 case R_ALPHA_SREL32:
256 value -= (u64)location;
257 if ((int)value != value)
258 goto reloc_overflow;
259 *(u32 *)location = value;
260 break;
261 case R_ALPHA_SREL64:
262 value -= (u64)location;
263 *(u64 *)location = value;
264 break;
265 case R_ALPHA_GPRELHIGH:
266 value = (long)(value - gp + 0x8000) >> 16;
267 if ((short) value != value)
268 goto reloc_overflow;
269 *(u16 *)location = value;
270 break;
271 case R_ALPHA_GPRELLOW:
272 value -= gp;
273 *(u16 *)location = value;
274 break;
275 case R_ALPHA_GPREL16:
276 value -= gp;
277 if ((short) value != value)
278 goto reloc_overflow;
279 *(u16 *)location = value;
280 break;
281 default:
282 printk(KERN_ERR "module %s: Unknown relocation: %lu\n",
283 me->name, r_type);
284 return -ENOEXEC;
285 reloc_overflow:
286 if (ELF64_ST_TYPE (sym->st_info) == STT_SECTION)
287 printk(KERN_ERR
288 "module %s: Relocation overflow vs section %d\n",
289 me->name, sym->st_shndx);
290 else
291 printk(KERN_ERR
292 "module %s: Relocation overflow vs %s\n",
293 me->name, strtab + sym->st_name);
294 return -ENOEXEC;
295 }
296 }
298 return 0;
299 }
301 int
302 module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
303 struct module *me)
304 {
305 return 0;
306 }
308 void
309 module_arch_cleanup(struct module *mod)
310 {
311 }