ia64/linux-2.6.18-xen.hg

view arch/alpha/kernel/sys_takara.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_takara.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 TAKARA.
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>
18 #include <asm/ptrace.h>
19 #include <asm/system.h>
20 #include <asm/dma.h>
21 #include <asm/irq.h>
22 #include <asm/mmu_context.h>
23 #include <asm/io.h>
24 #include <asm/pgtable.h>
25 #include <asm/core_cia.h>
26 #include <asm/tlbflush.h>
28 #include "proto.h"
29 #include "irq_impl.h"
30 #include "pci_impl.h"
31 #include "machvec_impl.h"
34 /* Note mask bit is true for DISABLED irqs. */
35 static unsigned long cached_irq_mask[2] = { -1, -1 };
37 static inline void
38 takara_update_irq_hw(unsigned long irq, unsigned long mask)
39 {
40 int regaddr;
42 mask = (irq >= 64 ? mask << 16 : mask >> ((irq - 16) & 0x30));
43 regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);
44 outl(mask & 0xffff0000UL, regaddr);
45 }
47 static inline void
48 takara_enable_irq(unsigned int irq)
49 {
50 unsigned long mask;
51 mask = (cached_irq_mask[irq >= 64] &= ~(1UL << (irq & 63)));
52 takara_update_irq_hw(irq, mask);
53 }
55 static void
56 takara_disable_irq(unsigned int irq)
57 {
58 unsigned long mask;
59 mask = (cached_irq_mask[irq >= 64] |= 1UL << (irq & 63));
60 takara_update_irq_hw(irq, mask);
61 }
63 static unsigned int
64 takara_startup_irq(unsigned int irq)
65 {
66 takara_enable_irq(irq);
67 return 0; /* never anything pending */
68 }
70 static void
71 takara_end_irq(unsigned int irq)
72 {
73 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
74 takara_enable_irq(irq);
75 }
77 static struct hw_interrupt_type takara_irq_type = {
78 .typename = "TAKARA",
79 .startup = takara_startup_irq,
80 .shutdown = takara_disable_irq,
81 .enable = takara_enable_irq,
82 .disable = takara_disable_irq,
83 .ack = takara_disable_irq,
84 .end = takara_end_irq,
85 };
87 static void
88 takara_device_interrupt(unsigned long vector, struct pt_regs *regs)
89 {
90 unsigned intstatus;
92 /*
93 * The PALcode will have passed us vectors 0x800 or 0x810,
94 * which are fairly arbitrary values and serve only to tell
95 * us whether an interrupt has come in on IRQ0 or IRQ1. If
96 * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's
97 * probably ISA, but PCI interrupts can come through IRQ0
98 * as well if the interrupt controller isn't in accelerated
99 * mode.
100 *
101 * OTOH, the accelerator thing doesn't seem to be working
102 * overly well, so what we'll do instead is try directly
103 * examining the Master Interrupt Register to see if it's a
104 * PCI interrupt, and if _not_ then we'll pass it on to the
105 * ISA handler.
106 */
108 intstatus = inw(0x500) & 15;
109 if (intstatus) {
110 /*
111 * This is a PCI interrupt. Check each bit and
112 * despatch an interrupt if it's set.
113 */
115 if (intstatus & 8) handle_irq(16+3, regs);
116 if (intstatus & 4) handle_irq(16+2, regs);
117 if (intstatus & 2) handle_irq(16+1, regs);
118 if (intstatus & 1) handle_irq(16+0, regs);
119 } else {
120 isa_device_interrupt (vector, regs);
121 }
122 }
124 static void
125 takara_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
126 {
127 int irq = (vector - 0x800) >> 4;
128 handle_irq(irq, regs);
129 }
131 static void __init
132 takara_init_irq(void)
133 {
134 long i;
136 init_i8259a_irqs();
138 if (alpha_using_srm) {
139 alpha_mv.device_interrupt = takara_srm_device_interrupt;
140 } else {
141 unsigned int ctlreg = inl(0x500);
143 /* Return to non-accelerated mode. */
144 ctlreg &= ~0x8000;
145 outl(ctlreg, 0x500);
147 /* Enable the PCI interrupt register. */
148 ctlreg = 0x05107c00;
149 outl(ctlreg, 0x500);
150 }
152 for (i = 16; i < 128; i += 16)
153 takara_update_irq_hw(i, -1);
155 for (i = 16; i < 128; ++i) {
156 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
157 irq_desc[i].chip = &takara_irq_type;
158 }
160 common_init_isa_dma();
161 }
164 /*
165 * The Takara has PCI devices 1, 2, and 3 configured to slots 20,
166 * 19, and 18 respectively, in the default configuration. They can
167 * also be jumpered to slots 8, 7, and 6 respectively, which is fun
168 * because the SIO ISA bridge can also be slot 7. However, the SIO
169 * doesn't explicitly generate PCI-type interrupts, so we can
170 * assign it whatever the hell IRQ we like and it doesn't matter.
171 */
173 static int __init
174 takara_map_irq_srm(struct pci_dev *dev, u8 slot, u8 pin)
175 {
176 static char irq_tab[15][5] __initdata = {
177 { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */
178 { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 7 == device 2 */
179 { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 8 == device 1 */
180 { -1, -1, -1, -1, -1}, /* slot 9 == nothing */
181 { -1, -1, -1, -1, -1}, /* slot 10 == nothing */
182 { -1, -1, -1, -1, -1}, /* slot 11 == nothing */
183 /* These are behind the bridges. */
184 { 12, 12, 13, 14, 15}, /* slot 12 == nothing */
185 { 8, 8, 9, 19, 11}, /* slot 13 == nothing */
186 { 4, 4, 5, 6, 7}, /* slot 14 == nothing */
187 { 0, 0, 1, 2, 3}, /* slot 15 == nothing */
188 { -1, -1, -1, -1, -1}, /* slot 16 == nothing */
189 {64+ 0, 64+0, 64+1, 64+2, 64+3}, /* slot 17= device 4 */
190 {48+ 0, 48+0, 48+1, 48+2, 48+3}, /* slot 18= device 3 */
191 {32+ 0, 32+0, 32+1, 32+2, 32+3}, /* slot 19= device 2 */
192 {16+ 0, 16+0, 16+1, 16+2, 16+3}, /* slot 20= device 1 */
193 };
194 const long min_idsel = 6, max_idsel = 20, irqs_per_slot = 5;
195 int irq = COMMON_TABLE_LOOKUP;
196 if (irq >= 0 && irq < 16) {
197 /* Guess that we are behind a bridge. */
198 unsigned int busslot = PCI_SLOT(dev->bus->self->devfn);
199 irq += irq_tab[busslot-min_idsel][0];
200 }
201 return irq;
202 }
204 static int __init
205 takara_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
206 {
207 static char irq_tab[15][5] __initdata = {
208 { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */
209 { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 7 == device 2 */
210 { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 8 == device 1 */
211 { -1, -1, -1, -1, -1}, /* slot 9 == nothing */
212 { -1, -1, -1, -1, -1}, /* slot 10 == nothing */
213 { -1, -1, -1, -1, -1}, /* slot 11 == nothing */
214 { -1, -1, -1, -1, -1}, /* slot 12 == nothing */
215 { -1, -1, -1, -1, -1}, /* slot 13 == nothing */
216 { -1, -1, -1, -1, -1}, /* slot 14 == nothing */
217 { -1, -1, -1, -1, -1}, /* slot 15 == nothing */
218 { -1, -1, -1, -1, -1}, /* slot 16 == nothing */
219 { -1, -1, -1, -1, -1}, /* slot 17 == nothing */
220 { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 18 == device 3 */
221 { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 19 == device 2 */
222 { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 20 == device 1 */
223 };
224 const long min_idsel = 6, max_idsel = 20, irqs_per_slot = 5;
225 return COMMON_TABLE_LOOKUP;
226 }
228 static u8 __init
229 takara_swizzle(struct pci_dev *dev, u8 *pinp)
230 {
231 int slot = PCI_SLOT(dev->devfn);
232 int pin = *pinp;
233 unsigned int ctlreg = inl(0x500);
234 unsigned int busslot;
236 if (!dev->bus->self)
237 return slot;
239 busslot = PCI_SLOT(dev->bus->self->devfn);
240 /* Check for built-in bridges. */
241 if (dev->bus->number != 0
242 && busslot > 16
243 && ((1<<(36-busslot)) & ctlreg)) {
244 if (pin == 1)
245 pin += (20 - busslot);
246 else {
247 printk(KERN_WARNING "takara_swizzle: can only "
248 "handle cards with INTA IRQ pin.\n");
249 }
250 } else {
251 /* Must be a card-based bridge. */
252 printk(KERN_WARNING "takara_swizzle: cannot handle "
253 "card-bridge behind builtin bridge yet.\n");
254 }
256 *pinp = pin;
257 return slot;
258 }
260 static void __init
261 takara_init_pci(void)
262 {
263 if (alpha_using_srm)
264 alpha_mv.pci_map_irq = takara_map_irq_srm;
266 cia_init_pci();
267 ns87312_enable_ide(0x26e);
268 }
271 /*
272 * The System Vector
273 */
275 struct alpha_machine_vector takara_mv __initmv = {
276 .vector_name = "Takara",
277 DO_EV5_MMU,
278 DO_DEFAULT_RTC,
279 DO_CIA_IO,
280 .machine_check = cia_machine_check,
281 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
282 .min_io_address = DEFAULT_IO_BASE,
283 .min_mem_address = CIA_DEFAULT_MEM_BASE,
285 .nr_irqs = 128,
286 .device_interrupt = takara_device_interrupt,
288 .init_arch = cia_init_arch,
289 .init_irq = takara_init_irq,
290 .init_rtc = common_init_rtc,
291 .init_pci = takara_init_pci,
292 .kill_arch = cia_kill_arch,
293 .pci_map_irq = takara_map_irq,
294 .pci_swizzle = takara_swizzle,
295 };
296 ALIAS_MV(takara)