ia64/linux-2.6.18-xen.hg

view arch/sparc64/kernel/setup.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 /* $Id: setup.c,v 1.72 2002/02/09 19:49:30 davem Exp $
2 * linux/arch/sparc64/kernel/setup.c
3 *
4 * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
6 */
8 #include <linux/errno.h>
9 #include <linux/sched.h>
10 #include <linux/kernel.h>
11 #include <linux/mm.h>
12 #include <linux/stddef.h>
13 #include <linux/unistd.h>
14 #include <linux/ptrace.h>
15 #include <linux/slab.h>
16 #include <asm/smp.h>
17 #include <linux/user.h>
18 #include <linux/a.out.h>
19 #include <linux/screen_info.h>
20 #include <linux/delay.h>
21 #include <linux/fs.h>
22 #include <linux/seq_file.h>
23 #include <linux/syscalls.h>
24 #include <linux/kdev_t.h>
25 #include <linux/major.h>
26 #include <linux/string.h>
27 #include <linux/init.h>
28 #include <linux/inet.h>
29 #include <linux/console.h>
30 #include <linux/root_dev.h>
31 #include <linux/interrupt.h>
32 #include <linux/cpu.h>
33 #include <linux/initrd.h>
35 #include <asm/system.h>
36 #include <asm/io.h>
37 #include <asm/processor.h>
38 #include <asm/oplib.h>
39 #include <asm/page.h>
40 #include <asm/pgtable.h>
41 #include <asm/idprom.h>
42 #include <asm/head.h>
43 #include <asm/starfire.h>
44 #include <asm/mmu_context.h>
45 #include <asm/timer.h>
46 #include <asm/sections.h>
47 #include <asm/setup.h>
48 #include <asm/mmu.h>
50 #ifdef CONFIG_IP_PNP
51 #include <net/ipconfig.h>
52 #endif
54 struct screen_info screen_info = {
55 0, 0, /* orig-x, orig-y */
56 0, /* unused */
57 0, /* orig-video-page */
58 0, /* orig-video-mode */
59 128, /* orig-video-cols */
60 0, 0, 0, /* unused, ega_bx, unused */
61 54, /* orig-video-lines */
62 0, /* orig-video-isVGA */
63 16 /* orig-video-points */
64 };
66 void (*prom_palette)(int);
67 void (*prom_keyboard)(void);
69 static void
70 prom_console_write(struct console *con, const char *s, unsigned n)
71 {
72 prom_write(s, n);
73 }
75 unsigned int boot_flags = 0;
76 #define BOOTME_DEBUG 0x1
77 #define BOOTME_SINGLE 0x2
79 /* Exported for mm/init.c:paging_init. */
80 unsigned long cmdline_memory_size = 0;
82 static struct console prom_debug_console = {
83 .name = "debug",
84 .write = prom_console_write,
85 .flags = CON_PRINTBUFFER,
86 .index = -1,
87 };
89 /* XXX Implement this at some point... */
90 void kernel_enter_debugger(void)
91 {
92 }
94 int obp_system_intr(void)
95 {
96 if (boot_flags & BOOTME_DEBUG) {
97 printk("OBP: system interrupted\n");
98 prom_halt();
99 return 1;
100 }
101 return 0;
102 }
104 /*
105 * Process kernel command line switches that are specific to the
106 * SPARC or that require special low-level processing.
107 */
108 static void __init process_switch(char c)
109 {
110 switch (c) {
111 case 'd':
112 boot_flags |= BOOTME_DEBUG;
113 break;
114 case 's':
115 boot_flags |= BOOTME_SINGLE;
116 break;
117 case 'h':
118 prom_printf("boot_flags_init: Halt!\n");
119 prom_halt();
120 break;
121 case 'p':
122 /* Use PROM debug console. */
123 register_console(&prom_debug_console);
124 break;
125 case 'P':
126 /* Force UltraSPARC-III P-Cache on. */
127 if (tlb_type != cheetah) {
128 printk("BOOT: Ignoring P-Cache force option.\n");
129 break;
130 }
131 cheetah_pcache_forced_on = 1;
132 add_taint(TAINT_MACHINE_CHECK);
133 cheetah_enable_pcache();
134 break;
136 default:
137 printk("Unknown boot switch (-%c)\n", c);
138 break;
139 }
140 }
142 static void __init process_console(char *commands)
143 {
144 serial_console = 0;
145 commands += 8;
146 /* Linux-style serial */
147 if (!strncmp(commands, "ttyS", 4))
148 serial_console = simple_strtoul(commands + 4, NULL, 10) + 1;
149 else if (!strncmp(commands, "tty", 3)) {
150 char c = *(commands + 3);
151 /* Solaris-style serial */
152 if (c == 'a' || c == 'b') {
153 serial_console = c - 'a' + 1;
154 prom_printf ("Using /dev/tty%c as console.\n", c);
155 }
156 /* else Linux-style fbcon, not serial */
157 }
158 #if defined(CONFIG_PROM_CONSOLE)
159 if (!strncmp(commands, "prom", 4)) {
160 char *p;
162 for (p = commands - 8; *p && *p != ' '; p++)
163 *p = ' ';
164 conswitchp = &prom_con;
165 }
166 #endif
167 }
169 static void __init boot_flags_init(char *commands)
170 {
171 while (*commands) {
172 /* Move to the start of the next "argument". */
173 while (*commands && *commands == ' ')
174 commands++;
176 /* Process any command switches, otherwise skip it. */
177 if (*commands == '\0')
178 break;
179 if (*commands == '-') {
180 commands++;
181 while (*commands && *commands != ' ')
182 process_switch(*commands++);
183 continue;
184 }
185 if (!strncmp(commands, "console=", 8)) {
186 process_console(commands);
187 } else if (!strncmp(commands, "mem=", 4)) {
188 /*
189 * "mem=XXX[kKmM]" overrides the PROM-reported
190 * memory size.
191 */
192 cmdline_memory_size = simple_strtoul(commands + 4,
193 &commands, 0);
194 if (*commands == 'K' || *commands == 'k') {
195 cmdline_memory_size <<= 10;
196 commands++;
197 } else if (*commands=='M' || *commands=='m') {
198 cmdline_memory_size <<= 20;
199 commands++;
200 }
201 }
202 while (*commands && *commands != ' ')
203 commands++;
204 }
205 }
207 extern void panic_setup(char *, int *);
209 extern unsigned short root_flags;
210 extern unsigned short root_dev;
211 extern unsigned short ram_flags;
212 #define RAMDISK_IMAGE_START_MASK 0x07FF
213 #define RAMDISK_PROMPT_FLAG 0x8000
214 #define RAMDISK_LOAD_FLAG 0x4000
216 extern int root_mountflags;
218 char reboot_command[COMMAND_LINE_SIZE];
220 static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 };
222 void __init per_cpu_patch(void)
223 {
224 struct cpuid_patch_entry *p;
225 unsigned long ver;
226 int is_jbus;
228 if (tlb_type == spitfire && !this_is_starfire)
229 return;
231 is_jbus = 0;
232 if (tlb_type != hypervisor) {
233 __asm__ ("rdpr %%ver, %0" : "=r" (ver));
234 is_jbus = ((ver >> 32UL) == __JALAPENO_ID ||
235 (ver >> 32UL) == __SERRANO_ID);
236 }
238 p = &__cpuid_patch;
239 while (p < &__cpuid_patch_end) {
240 unsigned long addr = p->addr;
241 unsigned int *insns;
243 switch (tlb_type) {
244 case spitfire:
245 insns = &p->starfire[0];
246 break;
247 case cheetah:
248 case cheetah_plus:
249 if (is_jbus)
250 insns = &p->cheetah_jbus[0];
251 else
252 insns = &p->cheetah_safari[0];
253 break;
254 case hypervisor:
255 insns = &p->sun4v[0];
256 break;
257 default:
258 prom_printf("Unknown cpu type, halting.\n");
259 prom_halt();
260 };
262 *(unsigned int *) (addr + 0) = insns[0];
263 wmb();
264 __asm__ __volatile__("flush %0" : : "r" (addr + 0));
266 *(unsigned int *) (addr + 4) = insns[1];
267 wmb();
268 __asm__ __volatile__("flush %0" : : "r" (addr + 4));
270 *(unsigned int *) (addr + 8) = insns[2];
271 wmb();
272 __asm__ __volatile__("flush %0" : : "r" (addr + 8));
274 *(unsigned int *) (addr + 12) = insns[3];
275 wmb();
276 __asm__ __volatile__("flush %0" : : "r" (addr + 12));
278 p++;
279 }
280 }
282 void __init sun4v_patch(void)
283 {
284 struct sun4v_1insn_patch_entry *p1;
285 struct sun4v_2insn_patch_entry *p2;
287 if (tlb_type != hypervisor)
288 return;
290 p1 = &__sun4v_1insn_patch;
291 while (p1 < &__sun4v_1insn_patch_end) {
292 unsigned long addr = p1->addr;
294 *(unsigned int *) (addr + 0) = p1->insn;
295 wmb();
296 __asm__ __volatile__("flush %0" : : "r" (addr + 0));
298 p1++;
299 }
301 p2 = &__sun4v_2insn_patch;
302 while (p2 < &__sun4v_2insn_patch_end) {
303 unsigned long addr = p2->addr;
305 *(unsigned int *) (addr + 0) = p2->insns[0];
306 wmb();
307 __asm__ __volatile__("flush %0" : : "r" (addr + 0));
309 *(unsigned int *) (addr + 4) = p2->insns[1];
310 wmb();
311 __asm__ __volatile__("flush %0" : : "r" (addr + 4));
313 p2++;
314 }
315 }
317 #ifdef CONFIG_SMP
318 void __init boot_cpu_id_too_large(int cpu)
319 {
320 prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n",
321 cpu, NR_CPUS);
322 prom_halt();
323 }
324 #endif
326 void __init setup_arch(char **cmdline_p)
327 {
328 /* Initialize PROM console and command line. */
329 *cmdline_p = prom_getbootargs();
330 strcpy(saved_command_line, *cmdline_p);
332 if (tlb_type == hypervisor)
333 printk("ARCH: SUN4V\n");
334 else
335 printk("ARCH: SUN4U\n");
337 #ifdef CONFIG_DUMMY_CONSOLE
338 conswitchp = &dummy_con;
339 #elif defined(CONFIG_PROM_CONSOLE)
340 conswitchp = &prom_con;
341 #endif
343 boot_flags_init(*cmdline_p);
345 idprom_init();
347 if (!root_flags)
348 root_mountflags &= ~MS_RDONLY;
349 ROOT_DEV = old_decode_dev(root_dev);
350 #ifdef CONFIG_BLK_DEV_RAM
351 rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
352 rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
353 rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);
354 #endif
356 task_thread_info(&init_task)->kregs = &fake_swapper_regs;
358 #ifdef CONFIG_IP_PNP
359 if (!ic_set_manually) {
360 int chosen = prom_finddevice ("/chosen");
361 u32 cl, sv, gw;
363 cl = prom_getintdefault (chosen, "client-ip", 0);
364 sv = prom_getintdefault (chosen, "server-ip", 0);
365 gw = prom_getintdefault (chosen, "gateway-ip", 0);
366 if (cl && sv) {
367 ic_myaddr = cl;
368 ic_servaddr = sv;
369 if (gw)
370 ic_gateway = gw;
371 #if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP)
372 ic_proto_enabled = 0;
373 #endif
374 }
375 }
376 #endif
378 /* Get boot processor trap_block[] setup. */
379 init_cur_cpu_trap(current_thread_info());
381 paging_init();
383 smp_setup_cpu_possible_map();
384 }
386 static int __init set_preferred_console(void)
387 {
388 int idev, odev;
390 /* The user has requested a console so this is already set up. */
391 if (serial_console >= 0)
392 return -EBUSY;
394 idev = prom_query_input_device();
395 odev = prom_query_output_device();
396 if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
397 serial_console = 0;
398 } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
399 serial_console = 1;
400 } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
401 serial_console = 2;
402 } else if (idev == PROMDEV_IRSC && odev == PROMDEV_ORSC) {
403 serial_console = 3;
404 } else if (idev == PROMDEV_IVCONS && odev == PROMDEV_OVCONS) {
405 /* sunhv_console_init() doesn't check the serial_console
406 * value anyways...
407 */
408 serial_console = 4;
409 return add_preferred_console("ttyHV", 0, NULL);
410 } else {
411 prom_printf("Inconsistent console: "
412 "input %d, output %d\n",
413 idev, odev);
414 prom_halt();
415 }
417 if (serial_console)
418 return add_preferred_console("ttyS", serial_console - 1, NULL);
420 return -ENODEV;
421 }
422 console_initcall(set_preferred_console);
424 /* BUFFER is PAGE_SIZE bytes long. */
426 extern char *sparc_cpu_type;
427 extern char *sparc_fpu_type;
429 extern void smp_info(struct seq_file *);
430 extern void smp_bogo(struct seq_file *);
431 extern void mmu_info(struct seq_file *);
433 unsigned int dcache_parity_tl1_occurred;
434 unsigned int icache_parity_tl1_occurred;
436 static int ncpus_probed;
438 static int show_cpuinfo(struct seq_file *m, void *__unused)
439 {
440 seq_printf(m,
441 "cpu\t\t: %s\n"
442 "fpu\t\t: %s\n"
443 "prom\t\t: %s\n"
444 "type\t\t: %s\n"
445 "ncpus probed\t: %d\n"
446 "ncpus active\t: %d\n"
447 "D$ parity tl1\t: %u\n"
448 "I$ parity tl1\t: %u\n"
449 #ifndef CONFIG_SMP
450 "Cpu0Bogo\t: %lu.%02lu\n"
451 "Cpu0ClkTck\t: %016lx\n"
452 #endif
453 ,
454 sparc_cpu_type,
455 sparc_fpu_type,
456 prom_version,
457 ((tlb_type == hypervisor) ?
458 "sun4v" :
459 "sun4u"),
460 ncpus_probed,
461 num_online_cpus(),
462 dcache_parity_tl1_occurred,
463 icache_parity_tl1_occurred
464 #ifndef CONFIG_SMP
465 , cpu_data(0).udelay_val/(500000/HZ),
466 (cpu_data(0).udelay_val/(5000/HZ)) % 100,
467 cpu_data(0).clock_tick
468 #endif
469 );
470 #ifdef CONFIG_SMP
471 smp_bogo(m);
472 #endif
473 mmu_info(m);
474 #ifdef CONFIG_SMP
475 smp_info(m);
476 #endif
477 return 0;
478 }
480 static void *c_start(struct seq_file *m, loff_t *pos)
481 {
482 /* The pointer we are returning is arbitrary,
483 * it just has to be non-NULL and not IS_ERR
484 * in the success case.
485 */
486 return *pos == 0 ? &c_start : NULL;
487 }
489 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
490 {
491 ++*pos;
492 return c_start(m, pos);
493 }
495 static void c_stop(struct seq_file *m, void *v)
496 {
497 }
499 struct seq_operations cpuinfo_op = {
500 .start =c_start,
501 .next = c_next,
502 .stop = c_stop,
503 .show = show_cpuinfo,
504 };
506 extern int stop_a_enabled;
508 void sun_do_break(void)
509 {
510 if (!stop_a_enabled)
511 return;
513 prom_printf("\n");
514 flush_user_windows();
516 prom_cmdline();
517 }
519 int serial_console = -1;
520 int stop_a_enabled = 1;
522 static int __init topology_init(void)
523 {
524 int i, err;
526 err = -ENOMEM;
528 /* Count the number of physically present processors in
529 * the machine, even on uniprocessor, so that /proc/cpuinfo
530 * output is consistent with 2.4.x
531 */
532 ncpus_probed = 0;
533 while (!cpu_find_by_instance(ncpus_probed, NULL, NULL))
534 ncpus_probed++;
536 for_each_possible_cpu(i) {
537 struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
538 if (p) {
539 register_cpu(p, i);
540 err = 0;
541 }
542 }
544 return err;
545 }
547 subsys_initcall(topology_init);