ia64/linux-2.6.18-xen.hg

view arch/alpha/kernel/sys_rx164.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_rx164.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 RX164 (PCA56+POLARIS).
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_polaris.h>
27 #include <asm/tlbflush.h>
29 #include "proto.h"
30 #include "irq_impl.h"
31 #include "pci_impl.h"
32 #include "machvec_impl.h"
35 /* Note mask bit is true for ENABLED irqs. */
36 static unsigned long cached_irq_mask;
38 static inline void
39 rx164_update_irq_hw(unsigned long mask)
40 {
41 volatile unsigned int *irq_mask;
43 irq_mask = (void *)(POLARIS_DENSE_CONFIG_BASE + 0x74);
44 *irq_mask = mask;
45 mb();
46 *irq_mask;
47 }
49 static inline void
50 rx164_enable_irq(unsigned int irq)
51 {
52 rx164_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
53 }
55 static void
56 rx164_disable_irq(unsigned int irq)
57 {
58 rx164_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
59 }
61 static unsigned int
62 rx164_startup_irq(unsigned int irq)
63 {
64 rx164_enable_irq(irq);
65 return 0;
66 }
68 static void
69 rx164_end_irq(unsigned int irq)
70 {
71 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
72 rx164_enable_irq(irq);
73 }
75 static struct hw_interrupt_type rx164_irq_type = {
76 .typename = "RX164",
77 .startup = rx164_startup_irq,
78 .shutdown = rx164_disable_irq,
79 .enable = rx164_enable_irq,
80 .disable = rx164_disable_irq,
81 .ack = rx164_disable_irq,
82 .end = rx164_end_irq,
83 };
85 static void
86 rx164_device_interrupt(unsigned long vector, struct pt_regs *regs)
87 {
88 unsigned long pld;
89 volatile unsigned int *dirr;
90 long i;
92 /* Read the interrupt summary register. On Polaris, this is
93 the DIRR register in PCI config space (offset 0x84). */
94 dirr = (void *)(POLARIS_DENSE_CONFIG_BASE + 0x84);
95 pld = *dirr;
97 /*
98 * Now for every possible bit set, work through them and call
99 * the appropriate interrupt handler.
100 */
101 while (pld) {
102 i = ffz(~pld);
103 pld &= pld - 1; /* clear least bit set */
104 if (i == 20) {
105 isa_no_iack_sc_device_interrupt(vector, regs);
106 } else {
107 handle_irq(16+i, regs);
108 }
109 }
110 }
112 static void __init
113 rx164_init_irq(void)
114 {
115 long i;
117 rx164_update_irq_hw(0);
118 for (i = 16; i < 40; ++i) {
119 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
120 irq_desc[i].chip = &rx164_irq_type;
121 }
123 init_i8259a_irqs();
124 common_init_isa_dma();
126 setup_irq(16+20, &isa_cascade_irqaction);
127 }
130 /*
131 * The RX164 changed its interrupt routing between pass1 and pass2...
132 *
133 * PASS1:
134 *
135 * Slot IDSEL INTA INTB INTC INTD
136 * 0 6 5 10 15 20
137 * 1 7 4 9 14 19
138 * 2 5 3 8 13 18
139 * 3 9 2 7 12 17
140 * 4 10 1 6 11 16
141 *
142 * PASS2:
143 * Slot IDSEL INTA INTB INTC INTD
144 * 0 5 1 7 12 17
145 * 1 6 2 8 13 18
146 * 2 8 3 9 14 19
147 * 3 9 4 10 15 20
148 * 4 10 5 11 16 6
149 *
150 */
152 /*
153 * IdSel
154 * 5 32 bit PCI option slot 0
155 * 6 64 bit PCI option slot 1
156 * 7 PCI-ISA bridge
157 * 7 64 bit PCI option slot 2
158 * 9 32 bit PCI option slot 3
159 * 10 PCI-PCI bridge
160 *
161 */
163 static int __init
164 rx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
165 {
166 #if 0
167 static char irq_tab_pass1[6][5] __initdata = {
168 /*INT INTA INTB INTC INTD */
169 { 16+3, 16+3, 16+8, 16+13, 16+18}, /* IdSel 5, slot 2 */
170 { 16+5, 16+5, 16+10, 16+15, 16+20}, /* IdSel 6, slot 0 */
171 { 16+4, 16+4, 16+9, 16+14, 16+19}, /* IdSel 7, slot 1 */
172 { -1, -1, -1, -1, -1}, /* IdSel 8, PCI/ISA bridge */
173 { 16+2, 16+2, 16+7, 16+12, 16+17}, /* IdSel 9, slot 3 */
174 { 16+1, 16+1, 16+6, 16+11, 16+16}, /* IdSel 10, slot 4 */
175 };
176 #else
177 static char irq_tab[6][5] __initdata = {
178 /*INT INTA INTB INTC INTD */
179 { 16+0, 16+0, 16+6, 16+11, 16+16}, /* IdSel 5, slot 0 */
180 { 16+1, 16+1, 16+7, 16+12, 16+17}, /* IdSel 6, slot 1 */
181 { -1, -1, -1, -1, -1}, /* IdSel 7, PCI/ISA bridge */
182 { 16+2, 16+2, 16+8, 16+13, 16+18}, /* IdSel 8, slot 2 */
183 { 16+3, 16+3, 16+9, 16+14, 16+19}, /* IdSel 9, slot 3 */
184 { 16+4, 16+4, 16+10, 16+15, 16+5}, /* IdSel 10, PCI-PCI */
185 };
186 #endif
187 const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5;
189 /* JRP - Need to figure out how to distinguish pass1 from pass2,
190 and use the correct table. */
191 return COMMON_TABLE_LOOKUP;
192 }
195 /*
196 * The System Vector
197 */
199 struct alpha_machine_vector rx164_mv __initmv = {
200 .vector_name = "RX164",
201 DO_EV5_MMU,
202 DO_DEFAULT_RTC,
203 DO_POLARIS_IO,
204 .machine_check = polaris_machine_check,
205 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
206 .min_io_address = DEFAULT_IO_BASE,
207 .min_mem_address = DEFAULT_MEM_BASE,
209 .nr_irqs = 40,
210 .device_interrupt = rx164_device_interrupt,
212 .init_arch = polaris_init_arch,
213 .init_irq = rx164_init_irq,
214 .init_rtc = common_init_rtc,
215 .init_pci = common_init_pci,
216 .kill_arch = NULL,
217 .pci_map_irq = rx164_map_irq,
218 .pci_swizzle = common_swizzle,
219 };
220 ALIAS_MV(rx164)