ia64/linux-2.6.18-xen.hg

view arch/alpha/kernel/sys_eb64p.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_eb64p.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 EB64+ and EB66.
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/bitops.h>
19 #include <asm/ptrace.h>
20 #include <asm/system.h>
21 #include <asm/dma.h>
22 #include <asm/irq.h>
23 #include <asm/mmu_context.h>
24 #include <asm/io.h>
25 #include <asm/pgtable.h>
26 #include <asm/core_apecs.h>
27 #include <asm/core_lca.h>
28 #include <asm/hwrpb.h>
29 #include <asm/tlbflush.h>
31 #include "proto.h"
32 #include "irq_impl.h"
33 #include "pci_impl.h"
34 #include "machvec_impl.h"
37 /* Note mask bit is true for DISABLED irqs. */
38 static unsigned int cached_irq_mask = -1;
40 static inline void
41 eb64p_update_irq_hw(unsigned int irq, unsigned long mask)
42 {
43 outb(mask >> (irq >= 24 ? 24 : 16), (irq >= 24 ? 0x27 : 0x26));
44 }
46 static inline void
47 eb64p_enable_irq(unsigned int irq)
48 {
49 eb64p_update_irq_hw(irq, cached_irq_mask &= ~(1 << irq));
50 }
52 static void
53 eb64p_disable_irq(unsigned int irq)
54 {
55 eb64p_update_irq_hw(irq, cached_irq_mask |= 1 << irq);
56 }
58 static unsigned int
59 eb64p_startup_irq(unsigned int irq)
60 {
61 eb64p_enable_irq(irq);
62 return 0; /* never anything pending */
63 }
65 static void
66 eb64p_end_irq(unsigned int irq)
67 {
68 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
69 eb64p_enable_irq(irq);
70 }
72 static struct hw_interrupt_type eb64p_irq_type = {
73 .typename = "EB64P",
74 .startup = eb64p_startup_irq,
75 .shutdown = eb64p_disable_irq,
76 .enable = eb64p_enable_irq,
77 .disable = eb64p_disable_irq,
78 .ack = eb64p_disable_irq,
79 .end = eb64p_end_irq,
80 };
82 static void
83 eb64p_device_interrupt(unsigned long vector, struct pt_regs *regs)
84 {
85 unsigned long pld;
86 unsigned int i;
88 /* Read the interrupt summary registers */
89 pld = inb(0x26) | (inb(0x27) << 8);
91 /*
92 * Now, for every possible bit set, work through
93 * them and call the appropriate interrupt handler.
94 */
95 while (pld) {
96 i = ffz(~pld);
97 pld &= pld - 1; /* clear least bit set */
99 if (i == 5) {
100 isa_device_interrupt(vector, regs);
101 } else {
102 handle_irq(16 + i, regs);
103 }
104 }
105 }
107 static void __init
108 eb64p_init_irq(void)
109 {
110 long i;
112 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_CABRIOLET)
113 /*
114 * CABRIO SRM may not set variation correctly, so here we test
115 * the high word of the interrupt summary register for the RAZ
116 * bits, and hope that a true EB64+ would read all ones...
117 */
118 if (inw(0x806) != 0xffff) {
119 extern struct alpha_machine_vector cabriolet_mv;
121 printk("Detected Cabriolet: correcting HWRPB.\n");
123 hwrpb->sys_variation |= 2L << 10;
124 hwrpb_update_checksum(hwrpb);
126 alpha_mv = cabriolet_mv;
127 alpha_mv.init_irq();
128 return;
129 }
130 #endif /* GENERIC */
132 outb(0xff, 0x26);
133 outb(0xff, 0x27);
135 init_i8259a_irqs();
137 for (i = 16; i < 32; ++i) {
138 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
139 irq_desc[i].chip = &eb64p_irq_type;
140 }
142 common_init_isa_dma();
143 setup_irq(16+5, &isa_cascade_irqaction);
144 }
146 /*
147 * PCI Fixup configuration.
148 *
149 * There are two 8 bit external summary registers as follows:
150 *
151 * Summary @ 0x26:
152 * Bit Meaning
153 * 0 Interrupt Line A from slot 0
154 * 1 Interrupt Line A from slot 1
155 * 2 Interrupt Line B from slot 0
156 * 3 Interrupt Line B from slot 1
157 * 4 Interrupt Line C from slot 0
158 * 5 Interrupt line from the two ISA PICs
159 * 6 Tulip
160 * 7 NCR SCSI
161 *
162 * Summary @ 0x27
163 * Bit Meaning
164 * 0 Interrupt Line C from slot 1
165 * 1 Interrupt Line D from slot 0
166 * 2 Interrupt Line D from slot 1
167 * 3 RAZ
168 * 4 RAZ
169 * 5 RAZ
170 * 6 RAZ
171 * 7 RAZ
172 *
173 * The device to slot mapping looks like:
174 *
175 * Slot Device
176 * 5 NCR SCSI controller
177 * 6 PCI on board slot 0
178 * 7 PCI on board slot 1
179 * 8 Intel SIO PCI-ISA bridge chip
180 * 9 Tulip - DECchip 21040 Ethernet controller
181 *
182 *
183 * This two layered interrupt approach means that we allocate IRQ 16 and
184 * above for PCI interrupts. The IRQ relates to which bit the interrupt
185 * comes in on. This makes interrupt processing much easier.
186 */
188 static int __init
189 eb64p_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
190 {
191 static char irq_tab[5][5] __initdata = {
192 /*INT INTA INTB INTC INTD */
193 {16+7, 16+7, 16+7, 16+7, 16+7}, /* IdSel 5, slot ?, ?? */
194 {16+0, 16+0, 16+2, 16+4, 16+9}, /* IdSel 6, slot ?, ?? */
195 {16+1, 16+1, 16+3, 16+8, 16+10}, /* IdSel 7, slot ?, ?? */
196 { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
197 {16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 9, TULIP */
198 };
199 const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
200 return COMMON_TABLE_LOOKUP;
201 }
204 /*
205 * The System Vector
206 */
208 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB64P)
209 struct alpha_machine_vector eb64p_mv __initmv = {
210 .vector_name = "EB64+",
211 DO_EV4_MMU,
212 DO_DEFAULT_RTC,
213 DO_APECS_IO,
214 .machine_check = apecs_machine_check,
215 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
216 .min_io_address = DEFAULT_IO_BASE,
217 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE,
219 .nr_irqs = 32,
220 .device_interrupt = eb64p_device_interrupt,
222 .init_arch = apecs_init_arch,
223 .init_irq = eb64p_init_irq,
224 .init_rtc = common_init_rtc,
225 .init_pci = common_init_pci,
226 .kill_arch = NULL,
227 .pci_map_irq = eb64p_map_irq,
228 .pci_swizzle = common_swizzle,
229 };
230 ALIAS_MV(eb64p)
231 #endif
233 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66)
234 struct alpha_machine_vector eb66_mv __initmv = {
235 .vector_name = "EB66",
236 DO_EV4_MMU,
237 DO_DEFAULT_RTC,
238 DO_LCA_IO,
239 .machine_check = lca_machine_check,
240 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
241 .min_io_address = DEFAULT_IO_BASE,
242 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE,
244 .nr_irqs = 32,
245 .device_interrupt = eb64p_device_interrupt,
247 .init_arch = lca_init_arch,
248 .init_irq = eb64p_init_irq,
249 .init_rtc = common_init_rtc,
250 .init_pci = common_init_pci,
251 .pci_map_irq = eb64p_map_irq,
252 .pci_swizzle = common_swizzle,
253 };
254 ALIAS_MV(eb66)
255 #endif