ia64/linux-2.6.18-xen.hg

view arch/alpha/boot/bootp.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/bootp.c
3 *
4 * Copyright (C) 1997 Jay Estabrook
5 *
6 * This file is used for creating a bootp file for the Linux/AXP kernel
7 *
8 * based significantly on the arch/alpha/boot/main.c of Linus Torvalds
9 */
10 #include <linux/kernel.h>
11 #include <linux/string.h>
12 #include <linux/utsrelease.h>
13 #include <linux/mm.h>
15 #include <asm/system.h>
16 #include <asm/console.h>
17 #include <asm/hwrpb.h>
18 #include <asm/pgtable.h>
19 #include <asm/io.h>
21 #include <stdarg.h>
23 #include "ksize.h"
25 extern unsigned long switch_to_osf_pal(unsigned long nr,
26 struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
27 unsigned long *vptb);
29 extern void move_stack(unsigned long new_stack);
31 struct hwrpb_struct *hwrpb = INIT_HWRPB;
32 static struct pcb_struct pcb_va[1];
34 /*
35 * Find a physical address of a virtual object..
36 *
37 * This is easy using the virtual page table address.
38 */
40 static inline void *
41 find_pa(unsigned long *vptb, void *ptr)
42 {
43 unsigned long address = (unsigned long) ptr;
44 unsigned long result;
46 result = vptb[address >> 13];
47 result >>= 32;
48 result <<= 13;
49 result |= address & 0x1fff;
50 return (void *) result;
51 }
53 /*
54 * This function moves into OSF/1 pal-code, and has a temporary
55 * PCB for that. The kernel proper should replace this PCB with
56 * the real one as soon as possible.
57 *
58 * The page table muckery in here depends on the fact that the boot
59 * code has the L1 page table identity-map itself in the second PTE
60 * in the L1 page table. Thus the L1-page is virtually addressable
61 * itself (through three levels) at virtual address 0x200802000.
62 */
64 #define VPTB ((unsigned long *) 0x200000000)
65 #define L1 ((unsigned long *) 0x200802000)
67 void
68 pal_init(void)
69 {
70 unsigned long i, rev;
71 struct percpu_struct * percpu;
72 struct pcb_struct * pcb_pa;
74 /* Create the dummy PCB. */
75 pcb_va->ksp = 0;
76 pcb_va->usp = 0;
77 pcb_va->ptbr = L1[1] >> 32;
78 pcb_va->asn = 0;
79 pcb_va->pcc = 0;
80 pcb_va->unique = 0;
81 pcb_va->flags = 1;
82 pcb_va->res1 = 0;
83 pcb_va->res2 = 0;
84 pcb_pa = find_pa(VPTB, pcb_va);
86 /*
87 * a0 = 2 (OSF)
88 * a1 = return address, but we give the asm the vaddr of the PCB
89 * a2 = physical addr of PCB
90 * a3 = new virtual page table pointer
91 * a4 = KSP (but the asm sets it)
92 */
93 srm_printk("Switching to OSF PAL-code .. ");
95 i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
96 if (i) {
97 srm_printk("failed, code %ld\n", i);
98 __halt();
99 }
101 percpu = (struct percpu_struct *)
102 (INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
103 rev = percpu->pal_revision = percpu->palcode_avail[2];
105 srm_printk("Ok (rev %lx)\n", rev);
107 tbia(); /* do it directly in case we are SMP */
108 }
110 static inline void
111 load(unsigned long dst, unsigned long src, unsigned long count)
112 {
113 memcpy((void *)dst, (void *)src, count);
114 }
116 /*
117 * Start the kernel.
118 */
119 static inline void
120 runkernel(void)
121 {
122 __asm__ __volatile__(
123 "bis %0,%0,$27\n\t"
124 "jmp ($27)"
125 : /* no outputs: it doesn't even return */
126 : "r" (START_ADDR));
127 }
129 extern char _end;
130 #define KERNEL_ORIGIN \
131 ((((unsigned long)&_end) + 511) & ~511)
133 void
134 start_kernel(void)
135 {
136 /*
137 * Note that this crufty stuff with static and envval
138 * and envbuf is because:
139 *
140 * 1. Frequently, the stack is short, and we don't want to overrun;
141 * 2. Frequently the stack is where we are going to copy the kernel to;
142 * 3. A certain SRM console required the GET_ENV output to stack.
143 * ??? A comment in the aboot sources indicates that the GET_ENV
144 * destination must be quadword aligned. Might this explain the
145 * behaviour, rather than requiring output to the stack, which
146 * seems rather far-fetched.
147 */
148 static long nbytes;
149 static char envval[256] __attribute__((aligned(8)));
150 static unsigned long initrd_start;
152 srm_printk("Linux/AXP bootp loader for Linux " UTS_RELEASE "\n");
153 if (INIT_HWRPB->pagesize != 8192) {
154 srm_printk("Expected 8kB pages, got %ldkB\n",
155 INIT_HWRPB->pagesize >> 10);
156 return;
157 }
158 if (INIT_HWRPB->vptb != (unsigned long) VPTB) {
159 srm_printk("Expected vptb at %p, got %p\n",
160 VPTB, (void *)INIT_HWRPB->vptb);
161 return;
162 }
163 pal_init();
165 /* The initrd must be page-aligned. See below for the
166 cause of the magic number 5. */
167 initrd_start = ((START_ADDR + 5*KERNEL_SIZE + PAGE_SIZE) |
168 (PAGE_SIZE-1)) + 1;
169 #ifdef INITRD_IMAGE_SIZE
170 srm_printk("Initrd positioned at %#lx\n", initrd_start);
171 #endif
173 /*
174 * Move the stack to a safe place to ensure it won't be
175 * overwritten by kernel image.
176 */
177 move_stack(initrd_start - PAGE_SIZE);
179 nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
180 if (nbytes < 0 || nbytes >= sizeof(envval)) {
181 nbytes = 0;
182 }
183 envval[nbytes] = '\0';
184 srm_printk("Loading the kernel...'%s'\n", envval);
186 /* NOTE: *no* callbacks or printouts from here on out!!! */
188 /* This is a hack, as some consoles seem to get virtual 20000000 (ie
189 * where the SRM console puts the kernel bootp image) memory
190 * overlapping physical memory where the kernel wants to be put,
191 * which causes real problems when attempting to copy the former to
192 * the latter... :-(
193 *
194 * So, we first move the kernel virtual-to-physical way above where
195 * we physically want the kernel to end up, then copy it from there
196 * to its final resting place... ;-}
197 *
198 * Sigh... */
200 #ifdef INITRD_IMAGE_SIZE
201 load(initrd_start, KERNEL_ORIGIN+KERNEL_SIZE, INITRD_IMAGE_SIZE);
202 #endif
203 load(START_ADDR+(4*KERNEL_SIZE), KERNEL_ORIGIN, KERNEL_SIZE);
204 load(START_ADDR, START_ADDR+(4*KERNEL_SIZE), KERNEL_SIZE);
206 memset((char*)ZERO_PGE, 0, PAGE_SIZE);
207 strcpy((char*)ZERO_PGE, envval);
208 #ifdef INITRD_IMAGE_SIZE
209 ((long *)(ZERO_PGE+256))[0] = initrd_start;
210 ((long *)(ZERO_PGE+256))[1] = INITRD_IMAGE_SIZE;
211 #endif
213 runkernel();
214 }