ia64/linux-2.6.18-xen.hg

view arch/sparc64/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 sparc64.
2 *
3 * Copyright (C) 2001 Rusty Russell.
4 * Copyright (C) 2002 David S. Miller.
5 */
7 #include <linux/moduleloader.h>
8 #include <linux/kernel.h>
9 #include <linux/elf.h>
10 #include <linux/vmalloc.h>
11 #include <linux/fs.h>
12 #include <linux/string.h>
13 #include <linux/slab.h>
14 #include <linux/vmalloc.h>
15 #include <linux/mm.h>
17 #include <asm/processor.h>
18 #include <asm/spitfire.h>
20 static void *module_map(unsigned long size)
21 {
22 struct vm_struct *area;
24 size = PAGE_ALIGN(size);
25 if (!size || size > MODULES_LEN)
26 return NULL;
28 area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
29 if (!area)
30 return NULL;
32 return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
33 }
35 void *module_alloc(unsigned long size)
36 {
37 void *ret;
39 /* We handle the zero case fine, unlike vmalloc */
40 if (size == 0)
41 return NULL;
43 ret = module_map(size);
44 if (!ret)
45 ret = ERR_PTR(-ENOMEM);
46 else
47 memset(ret, 0, size);
49 return ret;
50 }
52 /* Free memory returned from module_core_alloc/module_init_alloc */
53 void module_free(struct module *mod, void *module_region)
54 {
55 vfree(module_region);
56 /* FIXME: If module_region == mod->init_region, trim exception
57 table entries. */
58 }
60 /* Make generic code ignore STT_REGISTER dummy undefined symbols. */
61 int module_frob_arch_sections(Elf_Ehdr *hdr,
62 Elf_Shdr *sechdrs,
63 char *secstrings,
64 struct module *mod)
65 {
66 unsigned int symidx;
67 Elf64_Sym *sym;
68 const char *strtab;
69 int i;
71 for (symidx = 0; sechdrs[symidx].sh_type != SHT_SYMTAB; symidx++) {
72 if (symidx == hdr->e_shnum-1) {
73 printk("%s: no symtab found.\n", mod->name);
74 return -ENOEXEC;
75 }
76 }
77 sym = (Elf64_Sym *)sechdrs[symidx].sh_addr;
78 strtab = (char *)sechdrs[sechdrs[symidx].sh_link].sh_addr;
80 for (i = 1; i < sechdrs[symidx].sh_size / sizeof(Elf_Sym); i++) {
81 if (sym[i].st_shndx == SHN_UNDEF &&
82 ELF64_ST_TYPE(sym[i].st_info) == STT_REGISTER)
83 sym[i].st_shndx = SHN_ABS;
84 }
85 return 0;
86 }
88 int apply_relocate(Elf64_Shdr *sechdrs,
89 const char *strtab,
90 unsigned int symindex,
91 unsigned int relsec,
92 struct module *me)
93 {
94 printk(KERN_ERR "module %s: non-ADD RELOCATION unsupported\n",
95 me->name);
96 return -ENOEXEC;
97 }
99 int apply_relocate_add(Elf64_Shdr *sechdrs,
100 const char *strtab,
101 unsigned int symindex,
102 unsigned int relsec,
103 struct module *me)
104 {
105 unsigned int i;
106 Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
107 Elf64_Sym *sym;
108 u8 *location;
109 u32 *loc32;
111 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
112 Elf64_Addr v;
114 /* This is where to make the change */
115 location = (u8 *)sechdrs[sechdrs[relsec].sh_info].sh_addr
116 + rel[i].r_offset;
117 loc32 = (u32 *) location;
119 BUG_ON(((u64)location >> (u64)32) != (u64)0);
121 /* This is the symbol it is referring to. Note that all
122 undefined symbols have been resolved. */
123 sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
124 + ELF64_R_SYM(rel[i].r_info);
125 v = sym->st_value + rel[i].r_addend;
127 switch (ELF64_R_TYPE(rel[i].r_info) & 0xff) {
128 case R_SPARC_64:
129 location[0] = v >> 56;
130 location[1] = v >> 48;
131 location[2] = v >> 40;
132 location[3] = v >> 32;
133 location[4] = v >> 24;
134 location[5] = v >> 16;
135 location[6] = v >> 8;
136 location[7] = v >> 0;
137 break;
139 case R_SPARC_32:
140 location[0] = v >> 24;
141 location[1] = v >> 16;
142 location[2] = v >> 8;
143 location[3] = v >> 0;
144 break;
146 case R_SPARC_DISP32:
147 v -= (Elf64_Addr) location;
148 *loc32 = v;
149 break;
151 case R_SPARC_WDISP30:
152 v -= (Elf64_Addr) location;
153 *loc32 = (*loc32 & ~0x3fffffff) |
154 ((v >> 2) & 0x3fffffff);
155 break;
157 case R_SPARC_WDISP22:
158 v -= (Elf64_Addr) location;
159 *loc32 = (*loc32 & ~0x3fffff) |
160 ((v >> 2) & 0x3fffff);
161 break;
163 case R_SPARC_WDISP19:
164 v -= (Elf64_Addr) location;
165 *loc32 = (*loc32 & ~0x7ffff) |
166 ((v >> 2) & 0x7ffff);
167 break;
169 case R_SPARC_LO10:
170 *loc32 = (*loc32 & ~0x3ff) | (v & 0x3ff);
171 break;
173 case R_SPARC_HI22:
174 *loc32 = (*loc32 & ~0x3fffff) |
175 ((v >> 10) & 0x3fffff);
176 break;
178 case R_SPARC_OLO10:
179 *loc32 = (*loc32 & ~0x1fff) |
180 (((v & 0x3ff) +
181 (ELF64_R_TYPE(rel[i].r_info) >> 8))
182 & 0x1fff);
183 break;
185 default:
186 printk(KERN_ERR "module %s: Unknown relocation: %x\n",
187 me->name,
188 (int) (ELF64_R_TYPE(rel[i].r_info) & 0xff));
189 return -ENOEXEC;
190 };
191 }
192 return 0;
193 }
195 int module_finalize(const Elf_Ehdr *hdr,
196 const Elf_Shdr *sechdrs,
197 struct module *me)
198 {
199 /* Cheetah's I-cache is fully coherent. */
200 if (tlb_type == spitfire) {
201 unsigned long va;
203 flushw_all();
204 for (va = 0; va < (PAGE_SIZE << 1); va += 32)
205 spitfire_put_icache_tag(va, 0x0);
206 __asm__ __volatile__("flush %g6");
207 }
209 return 0;
210 }
212 void module_arch_cleanup(struct module *mod)
213 {
214 }