ia64/linux-2.6.18-xen.hg

view scripts/mod/file2alias.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 /* Simple code to turn various tables in an ELF file into alias definitions.
2 * This deals with kernel datastructures where they should be
3 * dealt with: in the kernel source.
4 *
5 * Copyright 2002-2003 Rusty Russell, IBM Corporation
6 * 2003 Kai Germaschewski
7 *
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 */
13 #include "modpost.h"
15 /* We use the ELF typedefs for kernel_ulong_t but bite the bullet and
16 * use either stdint.h or inttypes.h for the rest. */
17 #if KERNEL_ELFCLASS == ELFCLASS32
18 typedef Elf32_Addr kernel_ulong_t;
19 #define BITS_PER_LONG 32
20 #else
21 typedef Elf64_Addr kernel_ulong_t;
22 #define BITS_PER_LONG 64
23 #endif
24 #ifdef __sun__
25 #include <inttypes.h>
26 #else
27 #include <stdint.h>
28 #endif
30 #include <ctype.h>
32 typedef uint32_t __u32;
33 typedef uint16_t __u16;
34 typedef unsigned char __u8;
36 /* Big exception to the "don't include kernel headers into userspace, which
37 * even potentially has different endianness and word sizes, since
38 * we handle those differences explicitly below */
39 #include "../../include/linux/mod_devicetable.h"
40 #include "../../include/linux/input.h"
42 #define ADD(str, sep, cond, field) \
43 do { \
44 strcat(str, sep); \
45 if (cond) \
46 sprintf(str + strlen(str), \
47 sizeof(field) == 1 ? "%02X" : \
48 sizeof(field) == 2 ? "%04X" : \
49 sizeof(field) == 4 ? "%08X" : "", \
50 field); \
51 else \
52 sprintf(str + strlen(str), "*"); \
53 } while(0)
55 /**
56 * Check that sizeof(device_id type) are consistent with size of section
57 * in .o file. If in-consistent then userspace and kernel does not agree
58 * on actual size which is a bug.
59 **/
60 static void device_id_size_check(const char *modname, const char *device_id,
61 unsigned long size, unsigned long id_size)
62 {
63 if (size % id_size || size < id_size) {
64 fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
65 "of the size of section __mod_%s_device_table=%lu.\n"
66 "Fix definition of struct %s_device_id "
67 "in mod_devicetable.h\n",
68 modname, device_id, id_size, device_id, size, device_id);
69 }
70 }
72 /* USB is special because the bcdDevice can be matched against a numeric range */
73 /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */
74 static void do_usb_entry(struct usb_device_id *id,
75 unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
76 unsigned char range_lo, unsigned char range_hi,
77 struct module *mod)
78 {
79 char alias[500];
80 strcpy(alias, "usb:");
81 ADD(alias, "v", id->match_flags&USB_DEVICE_ID_MATCH_VENDOR,
82 id->idVendor);
83 ADD(alias, "p", id->match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
84 id->idProduct);
86 strcat(alias, "d");
87 if (bcdDevice_initial_digits)
88 sprintf(alias + strlen(alias), "%0*X",
89 bcdDevice_initial_digits, bcdDevice_initial);
90 if (range_lo == range_hi)
91 sprintf(alias + strlen(alias), "%u", range_lo);
92 else if (range_lo > 0 || range_hi < 9)
93 sprintf(alias + strlen(alias), "[%u-%u]", range_lo, range_hi);
94 if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1))
95 strcat(alias, "*");
97 ADD(alias, "dc", id->match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
98 id->bDeviceClass);
99 ADD(alias, "dsc",
100 id->match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
101 id->bDeviceSubClass);
102 ADD(alias, "dp",
103 id->match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
104 id->bDeviceProtocol);
105 ADD(alias, "ic",
106 id->match_flags&USB_DEVICE_ID_MATCH_INT_CLASS,
107 id->bInterfaceClass);
108 ADD(alias, "isc",
109 id->match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS,
110 id->bInterfaceSubClass);
111 ADD(alias, "ip",
112 id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
113 id->bInterfaceProtocol);
115 /* Always end in a wildcard, for future extension */
116 if (alias[strlen(alias)-1] != '*')
117 strcat(alias, "*");
118 buf_printf(&mod->dev_table_buf,
119 "MODULE_ALIAS(\"%s\");\n", alias);
120 }
122 static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
123 {
124 unsigned int devlo, devhi;
125 unsigned char chi, clo;
126 int ndigits;
128 id->match_flags = TO_NATIVE(id->match_flags);
129 id->idVendor = TO_NATIVE(id->idVendor);
130 id->idProduct = TO_NATIVE(id->idProduct);
132 devlo = id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
133 TO_NATIVE(id->bcdDevice_lo) : 0x0U;
134 devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
135 TO_NATIVE(id->bcdDevice_hi) : ~0x0U;
137 /*
138 * Some modules (visor) have empty slots as placeholder for
139 * run-time specification that results in catch-all alias
140 */
141 if (!(id->idVendor | id->bDeviceClass | id->bInterfaceClass))
142 return;
144 /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
145 for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
146 clo = devlo & 0xf;
147 chi = devhi & 0xf;
148 if (chi > 9) /* it's bcd not hex */
149 chi = 9;
150 devlo >>= 4;
151 devhi >>= 4;
153 if (devlo == devhi || !ndigits) {
154 do_usb_entry(id, devlo, ndigits, clo, chi, mod);
155 break;
156 }
158 if (clo > 0)
159 do_usb_entry(id, devlo++, ndigits, clo, 9, mod);
161 if (chi < 9)
162 do_usb_entry(id, devhi--, ndigits, 0, chi, mod);
163 }
164 }
166 static void do_usb_table(void *symval, unsigned long size,
167 struct module *mod)
168 {
169 unsigned int i;
170 const unsigned long id_size = sizeof(struct usb_device_id);
172 device_id_size_check(mod->name, "usb", size, id_size);
174 /* Leave last one: it's the terminator. */
175 size -= id_size;
177 for (i = 0; i < size; i += id_size)
178 do_usb_entry_multi(symval + i, mod);
179 }
181 /* Looks like: ieee1394:venNmoNspNverN */
182 static int do_ieee1394_entry(const char *filename,
183 struct ieee1394_device_id *id, char *alias)
184 {
185 id->match_flags = TO_NATIVE(id->match_flags);
186 id->vendor_id = TO_NATIVE(id->vendor_id);
187 id->model_id = TO_NATIVE(id->model_id);
188 id->specifier_id = TO_NATIVE(id->specifier_id);
189 id->version = TO_NATIVE(id->version);
191 strcpy(alias, "ieee1394:");
192 ADD(alias, "ven", id->match_flags & IEEE1394_MATCH_VENDOR_ID,
193 id->vendor_id);
194 ADD(alias, "mo", id->match_flags & IEEE1394_MATCH_MODEL_ID,
195 id->model_id);
196 ADD(alias, "sp", id->match_flags & IEEE1394_MATCH_SPECIFIER_ID,
197 id->specifier_id);
198 ADD(alias, "ver", id->match_flags & IEEE1394_MATCH_VERSION,
199 id->version);
201 return 1;
202 }
204 /* Looks like: pci:vNdNsvNsdNbcNscNiN. */
205 static int do_pci_entry(const char *filename,
206 struct pci_device_id *id, char *alias)
207 {
208 /* Class field can be divided into these three. */
209 unsigned char baseclass, subclass, interface,
210 baseclass_mask, subclass_mask, interface_mask;
212 id->vendor = TO_NATIVE(id->vendor);
213 id->device = TO_NATIVE(id->device);
214 id->subvendor = TO_NATIVE(id->subvendor);
215 id->subdevice = TO_NATIVE(id->subdevice);
216 id->class = TO_NATIVE(id->class);
217 id->class_mask = TO_NATIVE(id->class_mask);
219 strcpy(alias, "pci:");
220 ADD(alias, "v", id->vendor != PCI_ANY_ID, id->vendor);
221 ADD(alias, "d", id->device != PCI_ANY_ID, id->device);
222 ADD(alias, "sv", id->subvendor != PCI_ANY_ID, id->subvendor);
223 ADD(alias, "sd", id->subdevice != PCI_ANY_ID, id->subdevice);
225 baseclass = (id->class) >> 16;
226 baseclass_mask = (id->class_mask) >> 16;
227 subclass = (id->class) >> 8;
228 subclass_mask = (id->class_mask) >> 8;
229 interface = id->class;
230 interface_mask = id->class_mask;
232 if ((baseclass_mask != 0 && baseclass_mask != 0xFF)
233 || (subclass_mask != 0 && subclass_mask != 0xFF)
234 || (interface_mask != 0 && interface_mask != 0xFF)) {
235 warn("Can't handle masks in %s:%04X\n",
236 filename, id->class_mask);
237 return 0;
238 }
240 ADD(alias, "bc", baseclass_mask == 0xFF, baseclass);
241 ADD(alias, "sc", subclass_mask == 0xFF, subclass);
242 ADD(alias, "i", interface_mask == 0xFF, interface);
243 return 1;
244 }
246 /* looks like: "ccw:tNmNdtNdmN" */
247 static int do_ccw_entry(const char *filename,
248 struct ccw_device_id *id, char *alias)
249 {
250 id->match_flags = TO_NATIVE(id->match_flags);
251 id->cu_type = TO_NATIVE(id->cu_type);
252 id->cu_model = TO_NATIVE(id->cu_model);
253 id->dev_type = TO_NATIVE(id->dev_type);
254 id->dev_model = TO_NATIVE(id->dev_model);
256 strcpy(alias, "ccw:");
257 ADD(alias, "t", id->match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE,
258 id->cu_type);
259 ADD(alias, "m", id->match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL,
260 id->cu_model);
261 ADD(alias, "dt", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE,
262 id->dev_type);
263 ADD(alias, "dm", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
264 id->dev_model);
265 return 1;
266 }
268 /* Looks like: "serio:tyNprNidNexN" */
269 static int do_serio_entry(const char *filename,
270 struct serio_device_id *id, char *alias)
271 {
272 id->type = TO_NATIVE(id->type);
273 id->proto = TO_NATIVE(id->proto);
274 id->id = TO_NATIVE(id->id);
275 id->extra = TO_NATIVE(id->extra);
277 strcpy(alias, "serio:");
278 ADD(alias, "ty", id->type != SERIO_ANY, id->type);
279 ADD(alias, "pr", id->proto != SERIO_ANY, id->proto);
280 ADD(alias, "id", id->id != SERIO_ANY, id->id);
281 ADD(alias, "ex", id->extra != SERIO_ANY, id->extra);
283 return 1;
284 }
286 /* looks like: "pnp:dD" */
287 static int do_pnp_entry(const char *filename,
288 struct pnp_device_id *id, char *alias)
289 {
290 sprintf(alias, "pnp:d%s", id->id);
291 return 1;
292 }
294 /* looks like: "pnp:cCdD..." */
295 static int do_pnp_card_entry(const char *filename,
296 struct pnp_card_device_id *id, char *alias)
297 {
298 int i;
300 sprintf(alias, "pnp:c%s", id->id);
301 for (i = 0; i < PNP_MAX_DEVICES; i++) {
302 if (! *id->devs[i].id)
303 break;
304 sprintf(alias + strlen(alias), "d%s", id->devs[i].id);
305 }
306 return 1;
307 }
309 /* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
310 static int do_pcmcia_entry(const char *filename,
311 struct pcmcia_device_id *id, char *alias)
312 {
313 unsigned int i;
315 id->match_flags = TO_NATIVE(id->match_flags);
316 id->manf_id = TO_NATIVE(id->manf_id);
317 id->card_id = TO_NATIVE(id->card_id);
318 id->func_id = TO_NATIVE(id->func_id);
319 id->function = TO_NATIVE(id->function);
320 id->device_no = TO_NATIVE(id->device_no);
322 for (i=0; i<4; i++) {
323 id->prod_id_hash[i] = TO_NATIVE(id->prod_id_hash[i]);
324 }
326 strcpy(alias, "pcmcia:");
327 ADD(alias, "m", id->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID,
328 id->manf_id);
329 ADD(alias, "c", id->match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID,
330 id->card_id);
331 ADD(alias, "f", id->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID,
332 id->func_id);
333 ADD(alias, "fn", id->match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION,
334 id->function);
335 ADD(alias, "pfn", id->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO,
336 id->device_no);
337 ADD(alias, "pa", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, id->prod_id_hash[0]);
338 ADD(alias, "pb", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, id->prod_id_hash[1]);
339 ADD(alias, "pc", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, id->prod_id_hash[2]);
340 ADD(alias, "pd", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, id->prod_id_hash[3]);
342 return 1;
343 }
347 static int do_of_entry (const char *filename, struct of_device_id *of, char *alias)
348 {
349 char *tmp;
350 sprintf (alias, "of:N%sT%sC%s",
351 of->name[0] ? of->name : "*",
352 of->type[0] ? of->type : "*",
353 of->compatible[0] ? of->compatible : "*");
355 /* Replace all whitespace with underscores */
356 for (tmp = alias; tmp && *tmp; tmp++)
357 if (isspace (*tmp))
358 *tmp = '_';
360 return 1;
361 }
363 static int do_vio_entry(const char *filename, struct vio_device_id *vio,
364 char *alias)
365 {
366 char *tmp;
368 sprintf(alias, "vio:T%sS%s", vio->type[0] ? vio->type : "*",
369 vio->compat[0] ? vio->compat : "*");
371 /* Replace all whitespace with underscores */
372 for (tmp = alias; tmp && *tmp; tmp++)
373 if (isspace (*tmp))
374 *tmp = '_';
376 return 1;
377 }
379 static int do_i2c_entry(const char *filename, struct i2c_device_id *i2c, char *alias)
380 {
381 strcpy(alias, "i2c:");
382 ADD(alias, "id", 1, i2c->id);
383 return 1;
384 }
386 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
388 static void do_input(char *alias,
389 kernel_ulong_t *arr, unsigned int min, unsigned int max)
390 {
391 unsigned int i;
393 for (i = min; i < max; i++)
394 if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG)))
395 sprintf(alias + strlen(alias), "%X,*", i);
396 }
398 /* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
399 static int do_input_entry(const char *filename, struct input_device_id *id,
400 char *alias)
401 {
402 sprintf(alias, "input:");
404 ADD(alias, "b", id->flags & INPUT_DEVICE_ID_MATCH_BUS, id->bustype);
405 ADD(alias, "v", id->flags & INPUT_DEVICE_ID_MATCH_VENDOR, id->vendor);
406 ADD(alias, "p", id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT, id->product);
407 ADD(alias, "e", id->flags & INPUT_DEVICE_ID_MATCH_VERSION, id->version);
409 sprintf(alias + strlen(alias), "-e*");
410 if (id->flags & INPUT_DEVICE_ID_MATCH_EVBIT)
411 do_input(alias, id->evbit, 0, EV_MAX);
412 sprintf(alias + strlen(alias), "k*");
413 if (id->flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
414 do_input(alias, id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
415 sprintf(alias + strlen(alias), "r*");
416 if (id->flags & INPUT_DEVICE_ID_MATCH_RELBIT)
417 do_input(alias, id->relbit, 0, REL_MAX);
418 sprintf(alias + strlen(alias), "a*");
419 if (id->flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
420 do_input(alias, id->absbit, 0, ABS_MAX);
421 sprintf(alias + strlen(alias), "m*");
422 if (id->flags & INPUT_DEVICE_ID_MATCH_MSCIT)
423 do_input(alias, id->mscbit, 0, MSC_MAX);
424 sprintf(alias + strlen(alias), "l*");
425 if (id->flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
426 do_input(alias, id->ledbit, 0, LED_MAX);
427 sprintf(alias + strlen(alias), "s*");
428 if (id->flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
429 do_input(alias, id->sndbit, 0, SND_MAX);
430 sprintf(alias + strlen(alias), "f*");
431 if (id->flags & INPUT_DEVICE_ID_MATCH_FFBIT)
432 do_input(alias, id->ffbit, 0, FF_MAX);
433 sprintf(alias + strlen(alias), "w*");
434 if (id->flags & INPUT_DEVICE_ID_MATCH_SWBIT)
435 do_input(alias, id->swbit, 0, SW_MAX);
436 return 1;
437 }
439 /* Ignore any prefix, eg. v850 prepends _ */
440 static inline int sym_is(const char *symbol, const char *name)
441 {
442 const char *match;
444 match = strstr(symbol, name);
445 if (!match)
446 return 0;
447 return match[strlen(symbol)] == '\0';
448 }
450 static void do_table(void *symval, unsigned long size,
451 unsigned long id_size,
452 const char *device_id,
453 void *function,
454 struct module *mod)
455 {
456 unsigned int i;
457 char alias[500];
458 int (*do_entry)(const char *, void *entry, char *alias) = function;
460 device_id_size_check(mod->name, device_id, size, id_size);
461 /* Leave last one: it's the terminator. */
462 size -= id_size;
464 for (i = 0; i < size; i += id_size) {
465 if (do_entry(mod->name, symval+i, alias)) {
466 /* Always end in a wildcard, for future extension */
467 if (alias[strlen(alias)-1] != '*')
468 strcat(alias, "*");
469 buf_printf(&mod->dev_table_buf,
470 "MODULE_ALIAS(\"%s\");\n", alias);
471 }
472 }
473 }
475 /* Create MODULE_ALIAS() statements.
476 * At this time, we cannot write the actual output C source yet,
477 * so we write into the mod->dev_table_buf buffer. */
478 void handle_moddevtable(struct module *mod, struct elf_info *info,
479 Elf_Sym *sym, const char *symname)
480 {
481 void *symval;
483 /* We're looking for a section relative symbol */
484 if (!sym->st_shndx || sym->st_shndx >= info->hdr->e_shnum)
485 return;
487 symval = (void *)info->hdr
488 + info->sechdrs[sym->st_shndx].sh_offset
489 + sym->st_value;
491 if (sym_is(symname, "__mod_pci_device_table"))
492 do_table(symval, sym->st_size,
493 sizeof(struct pci_device_id), "pci",
494 do_pci_entry, mod);
495 else if (sym_is(symname, "__mod_usb_device_table"))
496 /* special case to handle bcdDevice ranges */
497 do_usb_table(symval, sym->st_size, mod);
498 else if (sym_is(symname, "__mod_ieee1394_device_table"))
499 do_table(symval, sym->st_size,
500 sizeof(struct ieee1394_device_id), "ieee1394",
501 do_ieee1394_entry, mod);
502 else if (sym_is(symname, "__mod_ccw_device_table"))
503 do_table(symval, sym->st_size,
504 sizeof(struct ccw_device_id), "ccw",
505 do_ccw_entry, mod);
506 else if (sym_is(symname, "__mod_serio_device_table"))
507 do_table(symval, sym->st_size,
508 sizeof(struct serio_device_id), "serio",
509 do_serio_entry, mod);
510 else if (sym_is(symname, "__mod_pnp_device_table"))
511 do_table(symval, sym->st_size,
512 sizeof(struct pnp_device_id), "pnp",
513 do_pnp_entry, mod);
514 else if (sym_is(symname, "__mod_pnp_card_device_table"))
515 do_table(symval, sym->st_size,
516 sizeof(struct pnp_card_device_id), "pnp_card",
517 do_pnp_card_entry, mod);
518 else if (sym_is(symname, "__mod_pcmcia_device_table"))
519 do_table(symval, sym->st_size,
520 sizeof(struct pcmcia_device_id), "pcmcia",
521 do_pcmcia_entry, mod);
522 else if (sym_is(symname, "__mod_of_device_table"))
523 do_table(symval, sym->st_size,
524 sizeof(struct of_device_id), "of",
525 do_of_entry, mod);
526 else if (sym_is(symname, "__mod_vio_device_table"))
527 do_table(symval, sym->st_size,
528 sizeof(struct vio_device_id), "vio",
529 do_vio_entry, mod);
530 else if (sym_is(symname, "__mod_i2c_device_table"))
531 do_table(symval, sym->st_size,
532 sizeof(struct i2c_device_id), "i2c",
533 do_i2c_entry, mod);
534 else if (sym_is(symname, "__mod_input_device_table"))
535 do_table(symval, sym->st_size,
536 sizeof(struct input_device_id), "input",
537 do_input_entry, mod);
538 }
540 /* Now add out buffered information to the generated C source */
541 void add_moddevtable(struct buffer *buf, struct module *mod)
542 {
543 buf_printf(buf, "\n");
544 buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos);
545 free(mod->dev_table_buf.p);
546 }