ia64/linux-2.6.18-xen.hg

view arch/alpha/kernel/sys_alcor.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 * linux/arch/alpha/kernel/sys_alcor.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 *
8 * Code supporting the ALCOR and XLT (XL-300/366/433).
9 */
11 #include <linux/kernel.h>
12 #include <linux/types.h>
13 #include <linux/mm.h>
14 #include <linux/sched.h>
15 #include <linux/pci.h>
16 #include <linux/init.h>
17 #include <linux/reboot.h>
18 #include <linux/bitops.h>
20 #include <asm/ptrace.h>
21 #include <asm/system.h>
22 #include <asm/io.h>
23 #include <asm/dma.h>
24 #include <asm/mmu_context.h>
25 #include <asm/irq.h>
26 #include <asm/pgtable.h>
27 #include <asm/core_cia.h>
28 #include <asm/tlbflush.h>
30 #include "proto.h"
31 #include "irq_impl.h"
32 #include "pci_impl.h"
33 #include "machvec_impl.h"
36 /* Note mask bit is true for ENABLED irqs. */
37 static unsigned long cached_irq_mask;
39 static inline void
40 alcor_update_irq_hw(unsigned long mask)
41 {
42 *(vuip)GRU_INT_MASK = mask;
43 mb();
44 }
46 static inline void
47 alcor_enable_irq(unsigned int irq)
48 {
49 alcor_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
50 }
52 static void
53 alcor_disable_irq(unsigned int irq)
54 {
55 alcor_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
56 }
58 static void
59 alcor_mask_and_ack_irq(unsigned int irq)
60 {
61 alcor_disable_irq(irq);
63 /* On ALCOR/XLT, need to dismiss interrupt via GRU. */
64 *(vuip)GRU_INT_CLEAR = 1 << (irq - 16); mb();
65 *(vuip)GRU_INT_CLEAR = 0; mb();
66 }
68 static unsigned int
69 alcor_startup_irq(unsigned int irq)
70 {
71 alcor_enable_irq(irq);
72 return 0;
73 }
75 static void
76 alcor_isa_mask_and_ack_irq(unsigned int irq)
77 {
78 i8259a_mask_and_ack_irq(irq);
80 /* On ALCOR/XLT, need to dismiss interrupt via GRU. */
81 *(vuip)GRU_INT_CLEAR = 0x80000000; mb();
82 *(vuip)GRU_INT_CLEAR = 0; mb();
83 }
85 static void
86 alcor_end_irq(unsigned int irq)
87 {
88 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
89 alcor_enable_irq(irq);
90 }
92 static struct hw_interrupt_type alcor_irq_type = {
93 .typename = "ALCOR",
94 .startup = alcor_startup_irq,
95 .shutdown = alcor_disable_irq,
96 .enable = alcor_enable_irq,
97 .disable = alcor_disable_irq,
98 .ack = alcor_mask_and_ack_irq,
99 .end = alcor_end_irq,
100 };
102 static void
103 alcor_device_interrupt(unsigned long vector, struct pt_regs *regs)
104 {
105 unsigned long pld;
106 unsigned int i;
108 /* Read the interrupt summary register of the GRU */
109 pld = (*(vuip)GRU_INT_REQ) & GRU_INT_REQ_BITS;
111 /*
112 * Now for every possible bit set, work through them and call
113 * the appropriate interrupt handler.
114 */
115 while (pld) {
116 i = ffz(~pld);
117 pld &= pld - 1; /* clear least bit set */
118 if (i == 31) {
119 isa_device_interrupt(vector, regs);
120 } else {
121 handle_irq(16 + i, regs);
122 }
123 }
124 }
126 static void __init
127 alcor_init_irq(void)
128 {
129 long i;
131 if (alpha_using_srm)
132 alpha_mv.device_interrupt = srm_device_interrupt;
134 *(vuip)GRU_INT_MASK = 0; mb(); /* all disabled */
135 *(vuip)GRU_INT_EDGE = 0; mb(); /* all are level */
136 *(vuip)GRU_INT_HILO = 0x80000000U; mb(); /* ISA only HI */
137 *(vuip)GRU_INT_CLEAR = 0; mb(); /* all clear */
139 for (i = 16; i < 48; ++i) {
140 /* On Alcor, at least, lines 20..30 are not connected
141 and can generate spurrious interrupts if we turn them
142 on while IRQ probing. */
143 if (i >= 16+20 && i <= 16+30)
144 continue;
145 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
146 irq_desc[i].chip = &alcor_irq_type;
147 }
148 i8259a_irq_type.ack = alcor_isa_mask_and_ack_irq;
150 init_i8259a_irqs();
151 common_init_isa_dma();
153 setup_irq(16+31, &isa_cascade_irqaction);
154 }
157 /*
158 * PCI Fixup configuration.
159 *
160 * Summary @ GRU_INT_REQ:
161 * Bit Meaning
162 * 0 Interrupt Line A from slot 2
163 * 1 Interrupt Line B from slot 2
164 * 2 Interrupt Line C from slot 2
165 * 3 Interrupt Line D from slot 2
166 * 4 Interrupt Line A from slot 1
167 * 5 Interrupt line B from slot 1
168 * 6 Interrupt Line C from slot 1
169 * 7 Interrupt Line D from slot 1
170 * 8 Interrupt Line A from slot 0
171 * 9 Interrupt Line B from slot 0
172 *10 Interrupt Line C from slot 0
173 *11 Interrupt Line D from slot 0
174 *12 Interrupt Line A from slot 4
175 *13 Interrupt Line B from slot 4
176 *14 Interrupt Line C from slot 4
177 *15 Interrupt Line D from slot 4
178 *16 Interrupt Line D from slot 3
179 *17 Interrupt Line D from slot 3
180 *18 Interrupt Line D from slot 3
181 *19 Interrupt Line D from slot 3
182 *20-30 Reserved
183 *31 EISA interrupt
184 *
185 * The device to slot mapping looks like:
186 *
187 * Slot Device
188 * 6 built-in TULIP (XLT only)
189 * 7 PCI on board slot 0
190 * 8 PCI on board slot 3
191 * 9 PCI on board slot 4
192 * 10 PCEB (PCI-EISA bridge)
193 * 11 PCI on board slot 2
194 * 12 PCI on board slot 1
195 *
196 *
197 * This two layered interrupt approach means that we allocate IRQ 16 and
198 * above for PCI interrupts. The IRQ relates to which bit the interrupt
199 * comes in on. This makes interrupt processing much easier.
200 */
202 static int __init
203 alcor_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
204 {
205 static char irq_tab[7][5] __initdata = {
206 /*INT INTA INTB INTC INTD */
207 /* note: IDSEL 17 is XLT only */
208 {16+13, 16+13, 16+13, 16+13, 16+13}, /* IdSel 17, TULIP */
209 { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 18, slot 0 */
210 {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 19, slot 3 */
211 {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 20, slot 4 */
212 { -1, -1, -1, -1, -1}, /* IdSel 21, PCEB */
213 { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 2 */
214 { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */
215 };
216 const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5;
217 return COMMON_TABLE_LOOKUP;
218 }
220 static void
221 alcor_kill_arch(int mode)
222 {
223 cia_kill_arch(mode);
225 #ifndef ALPHA_RESTORE_SRM_SETUP
226 switch(mode) {
227 case LINUX_REBOOT_CMD_RESTART:
228 /* Who said DEC engineer's have no sense of humor? ;-) */
229 if (alpha_using_srm) {
230 *(vuip) GRU_RESET = 0x0000dead;
231 mb();
232 }
233 break;
234 case LINUX_REBOOT_CMD_HALT:
235 break;
236 case LINUX_REBOOT_CMD_POWER_OFF:
237 break;
238 }
240 halt();
241 #endif
242 }
244 static void __init
245 alcor_init_pci(void)
246 {
247 struct pci_dev *dev;
249 cia_init_pci();
251 /*
252 * Now we can look to see if we are really running on an XLT-type
253 * motherboard, by looking for a 21040 TULIP in slot 6, which is
254 * built into XLT and BRET/MAVERICK, but not available on ALCOR.
255 */
256 dev = pci_get_device(PCI_VENDOR_ID_DEC,
257 PCI_DEVICE_ID_DEC_TULIP,
258 NULL);
259 if (dev && dev->devfn == PCI_DEVFN(6,0)) {
260 alpha_mv.sys.cia.gru_int_req_bits = XLT_GRU_INT_REQ_BITS;
261 printk(KERN_INFO "%s: Detected AS500 or XLT motherboard.\n",
262 __FUNCTION__);
263 }
264 pci_dev_put(dev);
265 }
268 /*
269 * The System Vectors
270 */
272 struct alpha_machine_vector alcor_mv __initmv = {
273 .vector_name = "Alcor",
274 DO_EV5_MMU,
275 DO_DEFAULT_RTC,
276 DO_CIA_IO,
277 .machine_check = cia_machine_check,
278 .max_isa_dma_address = ALPHA_ALCOR_MAX_ISA_DMA_ADDRESS,
279 .min_io_address = EISA_DEFAULT_IO_BASE,
280 .min_mem_address = CIA_DEFAULT_MEM_BASE,
282 .nr_irqs = 48,
283 .device_interrupt = alcor_device_interrupt,
285 .init_arch = cia_init_arch,
286 .init_irq = alcor_init_irq,
287 .init_rtc = common_init_rtc,
288 .init_pci = alcor_init_pci,
289 .kill_arch = alcor_kill_arch,
290 .pci_map_irq = alcor_map_irq,
291 .pci_swizzle = common_swizzle,
293 .sys = { .cia = {
294 .gru_int_req_bits = ALCOR_GRU_INT_REQ_BITS
295 }}
296 };
297 ALIAS_MV(alcor)
299 struct alpha_machine_vector xlt_mv __initmv = {
300 .vector_name = "XLT",
301 DO_EV5_MMU,
302 DO_DEFAULT_RTC,
303 DO_CIA_IO,
304 .machine_check = cia_machine_check,
305 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
306 .min_io_address = EISA_DEFAULT_IO_BASE,
307 .min_mem_address = CIA_DEFAULT_MEM_BASE,
309 .nr_irqs = 48,
310 .device_interrupt = alcor_device_interrupt,
312 .init_arch = cia_init_arch,
313 .init_irq = alcor_init_irq,
314 .init_rtc = common_init_rtc,
315 .init_pci = alcor_init_pci,
316 .kill_arch = alcor_kill_arch,
317 .pci_map_irq = alcor_map_irq,
318 .pci_swizzle = common_swizzle,
320 .sys = { .cia = {
321 .gru_int_req_bits = XLT_GRU_INT_REQ_BITS
322 }}
323 };
325 /* No alpha_mv alias for XLT, since we compile it in unconditionally
326 with ALCOR; setup_arch knows how to cope. */