ia64/linux-2.6.18-xen.hg

view arch/alpha/kernel/sys_ruffian.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_ruffian.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999, 2000 Richard Henderson
7 *
8 * Code supporting the RUFFIAN.
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/ioport.h>
17 #include <linux/init.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_cia.h>
27 #include <asm/tlbflush.h>
28 #include <asm/8253pit.h>
30 #include "proto.h"
31 #include "irq_impl.h"
32 #include "pci_impl.h"
33 #include "machvec_impl.h"
36 static void __init
37 ruffian_init_irq(void)
38 {
39 /* Invert 6&7 for i82371 */
40 *(vulp)PYXIS_INT_HILO = 0x000000c0UL; mb();
41 *(vulp)PYXIS_INT_CNFG = 0x00002064UL; mb(); /* all clear */
43 outb(0x11,0xA0);
44 outb(0x08,0xA1);
45 outb(0x02,0xA1);
46 outb(0x01,0xA1);
47 outb(0xFF,0xA1);
49 outb(0x11,0x20);
50 outb(0x00,0x21);
51 outb(0x04,0x21);
52 outb(0x01,0x21);
53 outb(0xFF,0x21);
55 /* Finish writing the 82C59A PIC Operation Control Words */
56 outb(0x20,0xA0);
57 outb(0x20,0x20);
59 init_i8259a_irqs();
61 /* Not interested in the bogus interrupts (0,3,6),
62 NMI (1), HALT (2), flash (5), or 21142 (8). */
63 init_pyxis_irqs(0x16f0000);
65 common_init_isa_dma();
66 }
68 #define RUFFIAN_LATCH ((PIT_TICK_RATE + HZ / 2) / HZ)
70 static void __init
71 ruffian_init_rtc(void)
72 {
73 /* Ruffian does not have the RTC connected to the CPU timer
74 interrupt. Instead, it uses the PIT connected to IRQ 0. */
76 /* Setup interval timer. */
77 outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */
78 outb(RUFFIAN_LATCH & 0xff, 0x40); /* LSB */
79 outb(RUFFIAN_LATCH >> 8, 0x40); /* MSB */
81 outb(0xb6, 0x43); /* pit counter 2: speaker */
82 outb(0x31, 0x42);
83 outb(0x13, 0x42);
85 setup_irq(0, &timer_irqaction);
86 }
88 static void
89 ruffian_kill_arch (int mode)
90 {
91 cia_kill_arch(mode);
92 #if 0
93 /* This only causes re-entry to ARCSBIOS */
94 /* Perhaps this works for other PYXIS as well? */
95 *(vuip) PYXIS_RESET = 0x0000dead;
96 mb();
97 #endif
98 }
100 /*
101 * Interrupt routing:
102 *
103 * Primary bus
104 * IdSel INTA INTB INTC INTD
105 * 21052 13 - - - -
106 * SIO 14 23 - - -
107 * 21143 15 44 - - -
108 * Slot 0 17 43 42 41 40
109 *
110 * Secondary bus
111 * IdSel INTA INTB INTC INTD
112 * Slot 0 8 (18) 19 18 17 16
113 * Slot 1 9 (19) 31 30 29 28
114 * Slot 2 10 (20) 27 26 25 24
115 * Slot 3 11 (21) 39 38 37 36
116 * Slot 4 12 (22) 35 34 33 32
117 * 53c875 13 (23) 20 - - -
118 *
119 */
121 static int __init
122 ruffian_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
123 {
124 static char irq_tab[11][5] __initdata = {
125 /*INT INTA INTB INTC INTD */
126 {-1, -1, -1, -1, -1}, /* IdSel 13, 21052 */
127 {-1, -1, -1, -1, -1}, /* IdSel 14, SIO */
128 {44, 44, 44, 44, 44}, /* IdSel 15, 21143 */
129 {-1, -1, -1, -1, -1}, /* IdSel 16, none */
130 {43, 43, 42, 41, 40}, /* IdSel 17, 64-bit slot */
131 /* the next 6 are actually on PCI bus 1, across the bridge */
132 {19, 19, 18, 17, 16}, /* IdSel 8, slot 0 */
133 {31, 31, 30, 29, 28}, /* IdSel 9, slot 1 */
134 {27, 27, 26, 25, 24}, /* IdSel 10, slot 2 */
135 {39, 39, 38, 37, 36}, /* IdSel 11, slot 3 */
136 {35, 35, 34, 33, 32}, /* IdSel 12, slot 4 */
137 {20, 20, 20, 20, 20}, /* IdSel 13, 53c875 */
138 };
139 const long min_idsel = 13, max_idsel = 23, irqs_per_slot = 5;
140 return COMMON_TABLE_LOOKUP;
141 }
143 static u8 __init
144 ruffian_swizzle(struct pci_dev *dev, u8 *pinp)
145 {
146 int slot, pin = *pinp;
148 if (dev->bus->number == 0) {
149 slot = PCI_SLOT(dev->devfn);
150 }
151 /* Check for the built-in bridge. */
152 else if (PCI_SLOT(dev->bus->self->devfn) == 13) {
153 slot = PCI_SLOT(dev->devfn) + 10;
154 }
155 else
156 {
157 /* Must be a card-based bridge. */
158 do {
159 if (PCI_SLOT(dev->bus->self->devfn) == 13) {
160 slot = PCI_SLOT(dev->devfn) + 10;
161 break;
162 }
163 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
165 /* Move up the chain of bridges. */
166 dev = dev->bus->self;
167 /* Slot of the next bridge. */
168 slot = PCI_SLOT(dev->devfn);
169 } while (dev->bus->self);
170 }
171 *pinp = pin;
172 return slot;
173 }
175 #ifdef BUILDING_FOR_MILO
176 /*
177 * The DeskStation Ruffian motherboard firmware does not place
178 * the memory size in the PALimpure area. Therefore, we use
179 * the Bank Configuration Registers in PYXIS to obtain the size.
180 */
181 static unsigned long __init
182 ruffian_get_bank_size(unsigned long offset)
183 {
184 unsigned long bank_addr, bank, ret = 0;
186 /* Valid offsets are: 0x800, 0x840 and 0x880
187 since Ruffian only uses three banks. */
188 bank_addr = (unsigned long)PYXIS_MCR + offset;
189 bank = *(vulp)bank_addr;
191 /* Check BANK_ENABLE */
192 if (bank & 0x01) {
193 static unsigned long size[] __initdata = {
194 0x40000000UL, /* 0x00, 1G */
195 0x20000000UL, /* 0x02, 512M */
196 0x10000000UL, /* 0x04, 256M */
197 0x08000000UL, /* 0x06, 128M */
198 0x04000000UL, /* 0x08, 64M */
199 0x02000000UL, /* 0x0a, 32M */
200 0x01000000UL, /* 0x0c, 16M */
201 0x00800000UL, /* 0x0e, 8M */
202 0x80000000UL, /* 0x10, 2G */
203 };
205 bank = (bank & 0x1e) >> 1;
206 if (bank < ARRAY_SIZE(size))
207 ret = size[bank];
208 }
210 return ret;
211 }
212 #endif /* BUILDING_FOR_MILO */
214 /*
215 * The System Vector
216 */
218 struct alpha_machine_vector ruffian_mv __initmv = {
219 .vector_name = "Ruffian",
220 DO_EV5_MMU,
221 DO_DEFAULT_RTC,
222 DO_PYXIS_IO,
223 .machine_check = cia_machine_check,
224 .max_isa_dma_address = ALPHA_RUFFIAN_MAX_ISA_DMA_ADDRESS,
225 .min_io_address = DEFAULT_IO_BASE,
226 .min_mem_address = DEFAULT_MEM_BASE,
227 .pci_dac_offset = PYXIS_DAC_OFFSET,
229 .nr_irqs = 48,
230 .device_interrupt = pyxis_device_interrupt,
232 .init_arch = pyxis_init_arch,
233 .init_irq = ruffian_init_irq,
234 .init_rtc = ruffian_init_rtc,
235 .init_pci = cia_init_pci,
236 .kill_arch = ruffian_kill_arch,
237 .pci_map_irq = ruffian_map_irq,
238 .pci_swizzle = ruffian_swizzle,
239 };
240 ALIAS_MV(ruffian)