ia64/linux-2.6.18-xen.hg

view arch/alpha/kernel/sys_titan.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_titan.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996, 1999 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 * Copyright (C) 1999, 2000 Jeff Wiedemeier
8 *
9 * Code supporting TITAN systems (EV6+TITAN), currently:
10 * Privateer
11 * Falcon
12 * Granite
13 */
15 #include <linux/kernel.h>
16 #include <linux/types.h>
17 #include <linux/mm.h>
18 #include <linux/sched.h>
19 #include <linux/pci.h>
20 #include <linux/init.h>
21 #include <linux/bitops.h>
23 #include <asm/ptrace.h>
24 #include <asm/system.h>
25 #include <asm/dma.h>
26 #include <asm/irq.h>
27 #include <asm/mmu_context.h>
28 #include <asm/io.h>
29 #include <asm/pgtable.h>
30 #include <asm/core_titan.h>
31 #include <asm/hwrpb.h>
32 #include <asm/tlbflush.h>
34 #include "proto.h"
35 #include "irq_impl.h"
36 #include "pci_impl.h"
37 #include "machvec_impl.h"
38 #include "err_impl.h"
41 /*
42 * Titan generic
43 */
45 /*
46 * Titan supports up to 4 CPUs
47 */
48 static unsigned long titan_cpu_irq_affinity[4] = { ~0UL, ~0UL, ~0UL, ~0UL };
50 /*
51 * Mask is set (1) if enabled
52 */
53 static unsigned long titan_cached_irq_mask;
55 /*
56 * Need SMP-safe access to interrupt CSRs
57 */
58 DEFINE_SPINLOCK(titan_irq_lock);
60 static void
61 titan_update_irq_hw(unsigned long mask)
62 {
63 register titan_cchip *cchip = TITAN_cchip;
64 unsigned long isa_enable = 1UL << 55;
65 register int bcpu = boot_cpuid;
67 #ifdef CONFIG_SMP
68 cpumask_t cpm = cpu_present_map;
69 volatile unsigned long *dim0, *dim1, *dim2, *dim3;
70 unsigned long mask0, mask1, mask2, mask3, dummy;
72 mask &= ~isa_enable;
73 mask0 = mask & titan_cpu_irq_affinity[0];
74 mask1 = mask & titan_cpu_irq_affinity[1];
75 mask2 = mask & titan_cpu_irq_affinity[2];
76 mask3 = mask & titan_cpu_irq_affinity[3];
78 if (bcpu == 0) mask0 |= isa_enable;
79 else if (bcpu == 1) mask1 |= isa_enable;
80 else if (bcpu == 2) mask2 |= isa_enable;
81 else mask3 |= isa_enable;
83 dim0 = &cchip->dim0.csr;
84 dim1 = &cchip->dim1.csr;
85 dim2 = &cchip->dim2.csr;
86 dim3 = &cchip->dim3.csr;
87 if (!cpu_isset(0, cpm)) dim0 = &dummy;
88 if (!cpu_isset(1, cpm)) dim1 = &dummy;
89 if (!cpu_isset(2, cpm)) dim2 = &dummy;
90 if (!cpu_isset(3, cpm)) dim3 = &dummy;
92 *dim0 = mask0;
93 *dim1 = mask1;
94 *dim2 = mask2;
95 *dim3 = mask3;
96 mb();
97 *dim0;
98 *dim1;
99 *dim2;
100 *dim3;
101 #else
102 volatile unsigned long *dimB;
103 dimB = &cchip->dim0.csr;
104 if (bcpu == 1) dimB = &cchip->dim1.csr;
105 else if (bcpu == 2) dimB = &cchip->dim2.csr;
106 else if (bcpu == 3) dimB = &cchip->dim3.csr;
108 *dimB = mask | isa_enable;
109 mb();
110 *dimB;
111 #endif
112 }
114 static inline void
115 titan_enable_irq(unsigned int irq)
116 {
117 spin_lock(&titan_irq_lock);
118 titan_cached_irq_mask |= 1UL << (irq - 16);
119 titan_update_irq_hw(titan_cached_irq_mask);
120 spin_unlock(&titan_irq_lock);
121 }
123 static inline void
124 titan_disable_irq(unsigned int irq)
125 {
126 spin_lock(&titan_irq_lock);
127 titan_cached_irq_mask &= ~(1UL << (irq - 16));
128 titan_update_irq_hw(titan_cached_irq_mask);
129 spin_unlock(&titan_irq_lock);
130 }
132 static unsigned int
133 titan_startup_irq(unsigned int irq)
134 {
135 titan_enable_irq(irq);
136 return 0; /* never anything pending */
137 }
139 static void
140 titan_end_irq(unsigned int irq)
141 {
142 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
143 titan_enable_irq(irq);
144 }
146 static void
147 titan_cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
148 {
149 int cpu;
151 for (cpu = 0; cpu < 4; cpu++) {
152 if (cpu_isset(cpu, affinity))
153 titan_cpu_irq_affinity[cpu] |= 1UL << irq;
154 else
155 titan_cpu_irq_affinity[cpu] &= ~(1UL << irq);
156 }
158 }
160 static void
161 titan_set_irq_affinity(unsigned int irq, cpumask_t affinity)
162 {
163 spin_lock(&titan_irq_lock);
164 titan_cpu_set_irq_affinity(irq - 16, affinity);
165 titan_update_irq_hw(titan_cached_irq_mask);
166 spin_unlock(&titan_irq_lock);
167 }
169 static void
170 titan_device_interrupt(unsigned long vector, struct pt_regs * regs)
171 {
172 printk("titan_device_interrupt: NOT IMPLEMENTED YET!! \n");
173 }
175 static void
176 titan_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
177 {
178 int irq;
180 irq = (vector - 0x800) >> 4;
181 handle_irq(irq, regs);
182 }
185 static void __init
186 init_titan_irqs(struct hw_interrupt_type * ops, int imin, int imax)
187 {
188 long i;
189 for (i = imin; i <= imax; ++i) {
190 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
191 irq_desc[i].chip = ops;
192 }
193 }
195 static struct hw_interrupt_type titan_irq_type = {
196 .typename = "TITAN",
197 .startup = titan_startup_irq,
198 .shutdown = titan_disable_irq,
199 .enable = titan_enable_irq,
200 .disable = titan_disable_irq,
201 .ack = titan_disable_irq,
202 .end = titan_end_irq,
203 .set_affinity = titan_set_irq_affinity,
204 };
206 static irqreturn_t
207 titan_intr_nop(int irq, void *dev_id, struct pt_regs *regs)
208 {
209 /*
210 * This is a NOP interrupt handler for the purposes of
211 * event counting -- just return.
212 */
213 return IRQ_HANDLED;
214 }
216 static void __init
217 titan_init_irq(void)
218 {
219 if (alpha_using_srm && !alpha_mv.device_interrupt)
220 alpha_mv.device_interrupt = titan_srm_device_interrupt;
221 if (!alpha_mv.device_interrupt)
222 alpha_mv.device_interrupt = titan_device_interrupt;
224 titan_update_irq_hw(0);
226 init_titan_irqs(&titan_irq_type, 16, 63 + 16);
227 }
229 static void __init
230 titan_legacy_init_irq(void)
231 {
232 /* init the legacy dma controller */
233 outb(0, DMA1_RESET_REG);
234 outb(0, DMA2_RESET_REG);
235 outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
236 outb(0, DMA2_MASK_REG);
238 /* init the legacy irq controller */
239 init_i8259a_irqs();
241 /* init the titan irqs */
242 titan_init_irq();
243 }
245 void
246 titan_dispatch_irqs(u64 mask, struct pt_regs *regs)
247 {
248 unsigned long vector;
250 /*
251 * Mask down to those interrupts which are enable on this processor
252 */
253 mask &= titan_cpu_irq_affinity[smp_processor_id()];
255 /*
256 * Dispatch all requested interrupts
257 */
258 while (mask) {
259 /* convert to SRM vector... priority is <63> -> <0> */
260 __asm__("ctlz %1, %0" : "=r"(vector) : "r"(mask));
261 vector = 63 - vector;
262 mask &= ~(1UL << vector); /* clear it out */
263 vector = 0x900 + (vector << 4); /* convert to SRM vector */
265 /* dispatch it */
266 alpha_mv.device_interrupt(vector, regs);
267 }
268 }
271 /*
272 * Titan Family
273 */
274 static void __init
275 titan_late_init(void)
276 {
277 /*
278 * Enable the system error interrupts. These interrupts are
279 * all reported to the kernel as machine checks, so the handler
280 * is a nop so it can be called to count the individual events.
281 */
282 request_irq(63+16, titan_intr_nop, IRQF_DISABLED,
283 "CChip Error", NULL);
284 request_irq(62+16, titan_intr_nop, IRQF_DISABLED,
285 "PChip 0 H_Error", NULL);
286 request_irq(61+16, titan_intr_nop, IRQF_DISABLED,
287 "PChip 1 H_Error", NULL);
288 request_irq(60+16, titan_intr_nop, IRQF_DISABLED,
289 "PChip 0 C_Error", NULL);
290 request_irq(59+16, titan_intr_nop, IRQF_DISABLED,
291 "PChip 1 C_Error", NULL);
293 /*
294 * Register our error handlers.
295 */
296 titan_register_error_handlers();
298 /*
299 * Check if the console left us any error logs.
300 */
301 cdl_check_console_data_log();
303 }
305 static int __devinit
306 titan_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
307 {
308 u8 intline;
309 int irq;
311 /* Get the current intline. */
312 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
313 irq = intline;
315 /* Is it explicitly routed through ISA? */
316 if ((irq & 0xF0) == 0xE0)
317 return irq;
319 /* Offset by 16 to make room for ISA interrupts 0 - 15. */
320 return irq + 16;
321 }
323 static void __init
324 titan_init_pci(void)
325 {
326 /*
327 * This isn't really the right place, but there's some init
328 * that needs to be done after everything is basically up.
329 */
330 titan_late_init();
332 pci_probe_only = 1;
333 common_init_pci();
334 SMC669_Init(0);
335 #ifdef CONFIG_VGA_HOSE
336 locate_and_init_vga(NULL);
337 #endif
338 }
341 /*
342 * Privateer
343 */
344 static void __init
345 privateer_init_pci(void)
346 {
347 /*
348 * Hook a couple of extra err interrupts that the
349 * common titan code won't.
350 */
351 request_irq(53+16, titan_intr_nop, IRQF_DISABLED,
352 "NMI", NULL);
353 request_irq(50+16, titan_intr_nop, IRQF_DISABLED,
354 "Temperature Warning", NULL);
356 /*
357 * Finish with the common version.
358 */
359 return titan_init_pci();
360 }
363 /*
364 * The System Vectors.
365 */
366 struct alpha_machine_vector titan_mv __initmv = {
367 .vector_name = "TITAN",
368 DO_EV6_MMU,
369 DO_DEFAULT_RTC,
370 DO_TITAN_IO,
371 .machine_check = titan_machine_check,
372 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
373 .min_io_address = DEFAULT_IO_BASE,
374 .min_mem_address = DEFAULT_MEM_BASE,
375 .pci_dac_offset = TITAN_DAC_OFFSET,
377 .nr_irqs = 80, /* 64 + 16 */
378 /* device_interrupt will be filled in by titan_init_irq */
380 .agp_info = titan_agp_info,
382 .init_arch = titan_init_arch,
383 .init_irq = titan_legacy_init_irq,
384 .init_rtc = common_init_rtc,
385 .init_pci = titan_init_pci,
387 .kill_arch = titan_kill_arch,
388 .pci_map_irq = titan_map_irq,
389 .pci_swizzle = common_swizzle,
390 };
391 ALIAS_MV(titan)
393 struct alpha_machine_vector privateer_mv __initmv = {
394 .vector_name = "PRIVATEER",
395 DO_EV6_MMU,
396 DO_DEFAULT_RTC,
397 DO_TITAN_IO,
398 .machine_check = privateer_machine_check,
399 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
400 .min_io_address = DEFAULT_IO_BASE,
401 .min_mem_address = DEFAULT_MEM_BASE,
402 .pci_dac_offset = TITAN_DAC_OFFSET,
404 .nr_irqs = 80, /* 64 + 16 */
405 /* device_interrupt will be filled in by titan_init_irq */
407 .agp_info = titan_agp_info,
409 .init_arch = titan_init_arch,
410 .init_irq = titan_legacy_init_irq,
411 .init_rtc = common_init_rtc,
412 .init_pci = privateer_init_pci,
414 .kill_arch = titan_kill_arch,
415 .pci_map_irq = titan_map_irq,
416 .pci_swizzle = common_swizzle,
417 };
418 /* No alpha_mv alias for privateer since we compile it
419 in unconditionally with titan; setup_arch knows how to cope. */