ia64/linux-2.6.18-xen.hg

view arch/alpha/boot/main.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 /*
2 * arch/alpha/boot/main.c
3 *
4 * Copyright (C) 1994, 1995 Linus Torvalds
5 *
6 * This file is the bootloader for the Linux/AXP kernel
7 */
8 #include <linux/kernel.h>
9 #include <linux/string.h>
10 #include <linux/utsrelease.h>
11 #include <linux/mm.h>
13 #include <asm/system.h>
14 #include <asm/console.h>
15 #include <asm/hwrpb.h>
16 #include <asm/pgtable.h>
18 #include <stdarg.h>
20 #include "ksize.h"
22 extern int vsprintf(char *, const char *, va_list);
23 extern unsigned long switch_to_osf_pal(unsigned long nr,
24 struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
25 unsigned long *vptb);
26 struct hwrpb_struct *hwrpb = INIT_HWRPB;
27 static struct pcb_struct pcb_va[1];
29 /*
30 * Find a physical address of a virtual object..
31 *
32 * This is easy using the virtual page table address.
33 */
35 static inline void *
36 find_pa(unsigned long *vptb, void *ptr)
37 {
38 unsigned long address = (unsigned long) ptr;
39 unsigned long result;
41 result = vptb[address >> 13];
42 result >>= 32;
43 result <<= 13;
44 result |= address & 0x1fff;
45 return (void *) result;
46 }
48 /*
49 * This function moves into OSF/1 pal-code, and has a temporary
50 * PCB for that. The kernel proper should replace this PCB with
51 * the real one as soon as possible.
52 *
53 * The page table muckery in here depends on the fact that the boot
54 * code has the L1 page table identity-map itself in the second PTE
55 * in the L1 page table. Thus the L1-page is virtually addressable
56 * itself (through three levels) at virtual address 0x200802000.
57 */
59 #define VPTB ((unsigned long *) 0x200000000)
60 #define L1 ((unsigned long *) 0x200802000)
62 void
63 pal_init(void)
64 {
65 unsigned long i, rev;
66 struct percpu_struct * percpu;
67 struct pcb_struct * pcb_pa;
69 /* Create the dummy PCB. */
70 pcb_va->ksp = 0;
71 pcb_va->usp = 0;
72 pcb_va->ptbr = L1[1] >> 32;
73 pcb_va->asn = 0;
74 pcb_va->pcc = 0;
75 pcb_va->unique = 0;
76 pcb_va->flags = 1;
77 pcb_va->res1 = 0;
78 pcb_va->res2 = 0;
79 pcb_pa = find_pa(VPTB, pcb_va);
81 /*
82 * a0 = 2 (OSF)
83 * a1 = return address, but we give the asm the vaddr of the PCB
84 * a2 = physical addr of PCB
85 * a3 = new virtual page table pointer
86 * a4 = KSP (but the asm sets it)
87 */
88 srm_printk("Switching to OSF PAL-code .. ");
90 i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
91 if (i) {
92 srm_printk("failed, code %ld\n", i);
93 __halt();
94 }
96 percpu = (struct percpu_struct *)
97 (INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
98 rev = percpu->pal_revision = percpu->palcode_avail[2];
100 srm_printk("Ok (rev %lx)\n", rev);
102 tbia(); /* do it directly in case we are SMP */
103 }
105 static inline long openboot(void)
106 {
107 char bootdev[256];
108 long result;
110 result = callback_getenv(ENV_BOOTED_DEV, bootdev, 255);
111 if (result < 0)
112 return result;
113 return callback_open(bootdev, result & 255);
114 }
116 static inline long close(long dev)
117 {
118 return callback_close(dev);
119 }
121 static inline long load(long dev, unsigned long addr, unsigned long count)
122 {
123 char bootfile[256];
124 extern char _end;
125 long result, boot_size = &_end - (char *) BOOT_ADDR;
127 result = callback_getenv(ENV_BOOTED_FILE, bootfile, 255);
128 if (result < 0)
129 return result;
130 result &= 255;
131 bootfile[result] = '\0';
132 if (result)
133 srm_printk("Boot file specification (%s) not implemented\n",
134 bootfile);
135 return callback_read(dev, count, addr, boot_size/512 + 1);
136 }
138 /*
139 * Start the kernel.
140 */
141 static void runkernel(void)
142 {
143 __asm__ __volatile__(
144 "bis %1,%1,$30\n\t"
145 "bis %0,%0,$26\n\t"
146 "ret ($26)"
147 : /* no outputs: it doesn't even return */
148 : "r" (START_ADDR),
149 "r" (PAGE_SIZE + INIT_STACK));
150 }
152 void start_kernel(void)
153 {
154 long i;
155 long dev;
156 int nbytes;
157 char envval[256];
159 srm_printk("Linux/AXP bootloader for Linux " UTS_RELEASE "\n");
160 if (INIT_HWRPB->pagesize != 8192) {
161 srm_printk("Expected 8kB pages, got %ldkB\n", INIT_HWRPB->pagesize >> 10);
162 return;
163 }
164 pal_init();
165 dev = openboot();
166 if (dev < 0) {
167 srm_printk("Unable to open boot device: %016lx\n", dev);
168 return;
169 }
170 dev &= 0xffffffff;
171 srm_printk("Loading vmlinux ...");
172 i = load(dev, START_ADDR, KERNEL_SIZE);
173 close(dev);
174 if (i != KERNEL_SIZE) {
175 srm_printk("Failed (%lx)\n", i);
176 return;
177 }
179 nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
180 if (nbytes < 0) {
181 nbytes = 0;
182 }
183 envval[nbytes] = '\0';
184 strcpy((char*)ZERO_PGE, envval);
186 srm_printk(" Ok\nNow booting the kernel\n");
187 runkernel();
188 for (i = 0 ; i < 0x100000000 ; i++)
189 /* nothing */;
190 __halt();
191 }