ia64/linux-2.6.18-xen.hg

view arch/alpha/kernel/sys_wildfire.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_wildfire.c
3 *
4 * Wildfire support.
5 *
6 * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
7 */
9 #include <linux/kernel.h>
10 #include <linux/types.h>
11 #include <linux/mm.h>
12 #include <linux/sched.h>
13 #include <linux/pci.h>
14 #include <linux/init.h>
15 #include <linux/bitops.h>
17 #include <asm/ptrace.h>
18 #include <asm/system.h>
19 #include <asm/dma.h>
20 #include <asm/irq.h>
21 #include <asm/mmu_context.h>
22 #include <asm/io.h>
23 #include <asm/pgtable.h>
24 #include <asm/core_wildfire.h>
25 #include <asm/hwrpb.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"
33 static unsigned long cached_irq_mask[WILDFIRE_NR_IRQS/(sizeof(long)*8)];
35 DEFINE_SPINLOCK(wildfire_irq_lock);
37 static int doing_init_irq_hw = 0;
39 static void
40 wildfire_update_irq_hw(unsigned int irq)
41 {
42 int qbbno = (irq >> 8) & (WILDFIRE_MAX_QBB - 1);
43 int pcano = (irq >> 6) & (WILDFIRE_PCA_PER_QBB - 1);
44 wildfire_pca *pca;
45 volatile unsigned long * enable0;
47 if (!WILDFIRE_PCA_EXISTS(qbbno, pcano)) {
48 if (!doing_init_irq_hw) {
49 printk(KERN_ERR "wildfire_update_irq_hw:"
50 " got irq %d for non-existent PCA %d"
51 " on QBB %d.\n",
52 irq, pcano, qbbno);
53 }
54 return;
55 }
57 pca = WILDFIRE_pca(qbbno, pcano);
58 enable0 = (unsigned long *) &pca->pca_int[0].enable; /* ??? */
60 *enable0 = cached_irq_mask[qbbno * WILDFIRE_PCA_PER_QBB + pcano];
61 mb();
62 *enable0;
63 }
65 static void __init
66 wildfire_init_irq_hw(void)
67 {
68 #if 0
69 register wildfire_pca * pca = WILDFIRE_pca(0, 0);
70 volatile unsigned long * enable0, * enable1, * enable2, *enable3;
71 volatile unsigned long * target0, * target1, * target2, *target3;
73 enable0 = (unsigned long *) &pca->pca_int[0].enable;
74 enable1 = (unsigned long *) &pca->pca_int[1].enable;
75 enable2 = (unsigned long *) &pca->pca_int[2].enable;
76 enable3 = (unsigned long *) &pca->pca_int[3].enable;
78 target0 = (unsigned long *) &pca->pca_int[0].target;
79 target1 = (unsigned long *) &pca->pca_int[1].target;
80 target2 = (unsigned long *) &pca->pca_int[2].target;
81 target3 = (unsigned long *) &pca->pca_int[3].target;
83 *enable0 = *enable1 = *enable2 = *enable3 = 0;
85 *target0 = (1UL<<8) | WILDFIRE_QBB(0);
86 *target1 = *target2 = *target3 = 0;
88 mb();
90 *enable0; *enable1; *enable2; *enable3;
91 *target0; *target1; *target2; *target3;
93 #else
94 int i;
96 doing_init_irq_hw = 1;
98 /* Need to update only once for every possible PCA. */
99 for (i = 0; i < WILDFIRE_NR_IRQS; i+=WILDFIRE_IRQ_PER_PCA)
100 wildfire_update_irq_hw(i);
102 doing_init_irq_hw = 0;
103 #endif
104 }
106 static void
107 wildfire_enable_irq(unsigned int irq)
108 {
109 if (irq < 16)
110 i8259a_enable_irq(irq);
112 spin_lock(&wildfire_irq_lock);
113 set_bit(irq, &cached_irq_mask);
114 wildfire_update_irq_hw(irq);
115 spin_unlock(&wildfire_irq_lock);
116 }
118 static void
119 wildfire_disable_irq(unsigned int irq)
120 {
121 if (irq < 16)
122 i8259a_disable_irq(irq);
124 spin_lock(&wildfire_irq_lock);
125 clear_bit(irq, &cached_irq_mask);
126 wildfire_update_irq_hw(irq);
127 spin_unlock(&wildfire_irq_lock);
128 }
130 static void
131 wildfire_mask_and_ack_irq(unsigned int irq)
132 {
133 if (irq < 16)
134 i8259a_mask_and_ack_irq(irq);
136 spin_lock(&wildfire_irq_lock);
137 clear_bit(irq, &cached_irq_mask);
138 wildfire_update_irq_hw(irq);
139 spin_unlock(&wildfire_irq_lock);
140 }
142 static unsigned int
143 wildfire_startup_irq(unsigned int irq)
144 {
145 wildfire_enable_irq(irq);
146 return 0; /* never anything pending */
147 }
149 static void
150 wildfire_end_irq(unsigned int irq)
151 {
152 #if 0
153 if (!irq_desc[irq].action)
154 printk("got irq %d\n", irq);
155 #endif
156 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
157 wildfire_enable_irq(irq);
158 }
160 static struct hw_interrupt_type wildfire_irq_type = {
161 .typename = "WILDFIRE",
162 .startup = wildfire_startup_irq,
163 .shutdown = wildfire_disable_irq,
164 .enable = wildfire_enable_irq,
165 .disable = wildfire_disable_irq,
166 .ack = wildfire_mask_and_ack_irq,
167 .end = wildfire_end_irq,
168 };
170 static void __init
171 wildfire_init_irq_per_pca(int qbbno, int pcano)
172 {
173 int i, irq_bias;
174 unsigned long io_bias;
175 static struct irqaction isa_enable = {
176 .handler = no_action,
177 .name = "isa_enable",
178 };
180 irq_bias = qbbno * (WILDFIRE_PCA_PER_QBB * WILDFIRE_IRQ_PER_PCA)
181 + pcano * WILDFIRE_IRQ_PER_PCA;
183 /* Only need the following for first PCI bus per PCA. */
184 io_bias = WILDFIRE_IO(qbbno, pcano<<1) - WILDFIRE_IO_BIAS;
186 #if 0
187 outb(0, DMA1_RESET_REG + io_bias);
188 outb(0, DMA2_RESET_REG + io_bias);
189 outb(DMA_MODE_CASCADE, DMA2_MODE_REG + io_bias);
190 outb(0, DMA2_MASK_REG + io_bias);
191 #endif
193 #if 0
194 /* ??? Not sure how to do this, yet... */
195 init_i8259a_irqs(); /* ??? */
196 #endif
198 for (i = 0; i < 16; ++i) {
199 if (i == 2)
200 continue;
201 irq_desc[i+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
202 irq_desc[i+irq_bias].chip = &wildfire_irq_type;
203 }
205 irq_desc[36+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
206 irq_desc[36+irq_bias].chip = &wildfire_irq_type;
207 for (i = 40; i < 64; ++i) {
208 irq_desc[i+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
209 irq_desc[i+irq_bias].chip = &wildfire_irq_type;
210 }
212 setup_irq(32+irq_bias, &isa_enable);
213 }
215 static void __init
216 wildfire_init_irq(void)
217 {
218 int qbbno, pcano;
220 #if 1
221 wildfire_init_irq_hw();
222 init_i8259a_irqs();
223 #endif
225 for (qbbno = 0; qbbno < WILDFIRE_MAX_QBB; qbbno++) {
226 if (WILDFIRE_QBB_EXISTS(qbbno)) {
227 for (pcano = 0; pcano < WILDFIRE_PCA_PER_QBB; pcano++) {
228 if (WILDFIRE_PCA_EXISTS(qbbno, pcano)) {
229 wildfire_init_irq_per_pca(qbbno, pcano);
230 }
231 }
232 }
233 }
234 }
236 static void
237 wildfire_device_interrupt(unsigned long vector, struct pt_regs * regs)
238 {
239 int irq;
241 irq = (vector - 0x800) >> 4;
243 /*
244 * bits 10-8: source QBB ID
245 * bits 7-6: PCA
246 * bits 5-0: irq in PCA
247 */
249 handle_irq(irq, regs);
250 return;
251 }
253 /*
254 * PCI Fixup configuration.
255 *
256 * Summary per PCA (2 PCI or HIPPI buses):
257 *
258 * Bit Meaning
259 * 0-15 ISA
260 *
261 *32 ISA summary
262 *33 SMI
263 *34 NMI
264 *36 builtin QLogic SCSI (or slot 0 if no IO module)
265 *40 Interrupt Line A from slot 2 PCI0
266 *41 Interrupt Line B from slot 2 PCI0
267 *42 Interrupt Line C from slot 2 PCI0
268 *43 Interrupt Line D from slot 2 PCI0
269 *44 Interrupt Line A from slot 3 PCI0
270 *45 Interrupt Line B from slot 3 PCI0
271 *46 Interrupt Line C from slot 3 PCI0
272 *47 Interrupt Line D from slot 3 PCI0
273 *
274 *48 Interrupt Line A from slot 4 PCI1
275 *49 Interrupt Line B from slot 4 PCI1
276 *50 Interrupt Line C from slot 4 PCI1
277 *51 Interrupt Line D from slot 4 PCI1
278 *52 Interrupt Line A from slot 5 PCI1
279 *53 Interrupt Line B from slot 5 PCI1
280 *54 Interrupt Line C from slot 5 PCI1
281 *55 Interrupt Line D from slot 5 PCI1
282 *56 Interrupt Line A from slot 6 PCI1
283 *57 Interrupt Line B from slot 6 PCI1
284 *58 Interrupt Line C from slot 6 PCI1
285 *50 Interrupt Line D from slot 6 PCI1
286 *60 Interrupt Line A from slot 7 PCI1
287 *61 Interrupt Line B from slot 7 PCI1
288 *62 Interrupt Line C from slot 7 PCI1
289 *63 Interrupt Line D from slot 7 PCI1
290 *
291 *
292 * IdSel
293 * 0 Cypress Bridge I/O (ISA summary interrupt)
294 * 1 64 bit PCI 0 option slot 1 (SCSI QLogic builtin)
295 * 2 64 bit PCI 0 option slot 2
296 * 3 64 bit PCI 0 option slot 3
297 * 4 64 bit PCI 1 option slot 4
298 * 5 64 bit PCI 1 option slot 5
299 * 6 64 bit PCI 1 option slot 6
300 * 7 64 bit PCI 1 option slot 7
301 */
303 static int __init
304 wildfire_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
305 {
306 static char irq_tab[8][5] __initdata = {
307 /*INT INTA INTB INTC INTD */
308 { -1, -1, -1, -1, -1}, /* IdSel 0 ISA Bridge */
309 { 36, 36, 36+1, 36+2, 36+3}, /* IdSel 1 SCSI builtin */
310 { 40, 40, 40+1, 40+2, 40+3}, /* IdSel 2 PCI 0 slot 2 */
311 { 44, 44, 44+1, 44+2, 44+3}, /* IdSel 3 PCI 0 slot 3 */
312 { 48, 48, 48+1, 48+2, 48+3}, /* IdSel 4 PCI 1 slot 4 */
313 { 52, 52, 52+1, 52+2, 52+3}, /* IdSel 5 PCI 1 slot 5 */
314 { 56, 56, 56+1, 56+2, 56+3}, /* IdSel 6 PCI 1 slot 6 */
315 { 60, 60, 60+1, 60+2, 60+3}, /* IdSel 7 PCI 1 slot 7 */
316 };
317 long min_idsel = 0, max_idsel = 7, irqs_per_slot = 5;
319 struct pci_controller *hose = dev->sysdata;
320 int irq = COMMON_TABLE_LOOKUP;
322 if (irq > 0) {
323 int qbbno = hose->index >> 3;
324 int pcano = (hose->index >> 1) & 3;
325 irq += (qbbno << 8) + (pcano << 6);
326 }
327 return irq;
328 }
331 /*
332 * The System Vectors
333 */
335 struct alpha_machine_vector wildfire_mv __initmv = {
336 .vector_name = "WILDFIRE",
337 DO_EV6_MMU,
338 DO_DEFAULT_RTC,
339 DO_WILDFIRE_IO,
340 .machine_check = wildfire_machine_check,
341 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
342 .min_io_address = DEFAULT_IO_BASE,
343 .min_mem_address = DEFAULT_MEM_BASE,
345 .nr_irqs = WILDFIRE_NR_IRQS,
346 .device_interrupt = wildfire_device_interrupt,
348 .init_arch = wildfire_init_arch,
349 .init_irq = wildfire_init_irq,
350 .init_rtc = common_init_rtc,
351 .init_pci = common_init_pci,
352 .kill_arch = wildfire_kill_arch,
353 .pci_map_irq = wildfire_map_irq,
354 .pci_swizzle = common_swizzle,
356 .pa_to_nid = wildfire_pa_to_nid,
357 .cpuid_to_nid = wildfire_cpuid_to_nid,
358 .node_mem_start = wildfire_node_mem_start,
359 .node_mem_size = wildfire_node_mem_size,
360 };
361 ALIAS_MV(wildfire)