ia64/linux-2.6.18-xen.hg

view arch/alpha/kernel/sys_nautilus.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_nautilus.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1998 Richard Henderson
6 * Copyright (C) 1999 Alpha Processor, Inc.,
7 * (David Daniel, Stig Telfer, Soohoon Lee)
8 *
9 * Code supporting NAUTILUS systems.
10 *
11 *
12 * NAUTILUS has the following I/O features:
13 *
14 * a) Driven by AMD 751 aka IRONGATE (northbridge):
15 * 4 PCI slots
16 * 1 AGP slot
17 *
18 * b) Driven by ALI M1543C (southbridge)
19 * 2 ISA slots
20 * 2 IDE connectors
21 * 1 dual drive capable FDD controller
22 * 2 serial ports
23 * 1 ECP/EPP/SP parallel port
24 * 2 USB ports
25 */
27 #include <linux/kernel.h>
28 #include <linux/types.h>
29 #include <linux/mm.h>
30 #include <linux/sched.h>
31 #include <linux/pci.h>
32 #include <linux/init.h>
33 #include <linux/reboot.h>
34 #include <linux/bootmem.h>
35 #include <linux/bitops.h>
37 #include <asm/ptrace.h>
38 #include <asm/system.h>
39 #include <asm/dma.h>
40 #include <asm/irq.h>
41 #include <asm/mmu_context.h>
42 #include <asm/io.h>
43 #include <asm/pci.h>
44 #include <asm/pgtable.h>
45 #include <asm/core_irongate.h>
46 #include <asm/hwrpb.h>
47 #include <asm/tlbflush.h>
49 #include "proto.h"
50 #include "err_impl.h"
51 #include "irq_impl.h"
52 #include "pci_impl.h"
53 #include "machvec_impl.h"
56 static void __init
57 nautilus_init_irq(void)
58 {
59 if (alpha_using_srm) {
60 alpha_mv.device_interrupt = srm_device_interrupt;
61 }
63 init_i8259a_irqs();
64 common_init_isa_dma();
65 }
67 static int __init
68 nautilus_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
69 {
70 /* Preserve the IRQ set up by the console. */
72 u8 irq;
73 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
74 return irq;
75 }
77 void
78 nautilus_kill_arch(int mode)
79 {
80 struct pci_bus *bus = pci_isa_hose->bus;
81 u32 pmuport;
82 int off;
84 switch (mode) {
85 case LINUX_REBOOT_CMD_RESTART:
86 if (! alpha_using_srm) {
87 u8 t8;
88 pci_bus_read_config_byte(bus, 0x38, 0x43, &t8);
89 pci_bus_write_config_byte(bus, 0x38, 0x43, t8 | 0x80);
90 outb(1, 0x92);
91 outb(0, 0x92);
92 /* NOTREACHED */
93 }
94 break;
96 case LINUX_REBOOT_CMD_POWER_OFF:
97 /* Assume M1543C */
98 off = 0x2000; /* SLP_TYPE = 0, SLP_EN = 1 */
99 pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport);
100 if (!pmuport) {
101 /* M1535D/D+ */
102 off = 0x3400; /* SLP_TYPE = 5, SLP_EN = 1 */
103 pci_bus_read_config_dword(bus, 0x88, 0xe0, &pmuport);
104 }
105 pmuport &= 0xfffe;
106 outw(0xffff, pmuport); /* Clear pending events. */
107 outw(off, pmuport + 4);
108 /* NOTREACHED */
109 break;
110 }
111 }
113 /* Perform analysis of a machine check that arrived from the system (NMI) */
115 static void
116 naut_sys_machine_check(unsigned long vector, unsigned long la_ptr,
117 struct pt_regs *regs)
118 {
119 printk("PC %lx RA %lx\n", regs->pc, regs->r26);
120 irongate_pci_clr_err();
121 }
123 /* Machine checks can come from two sources - those on the CPU and those
124 in the system. They are analysed separately but all starts here. */
126 void
127 nautilus_machine_check(unsigned long vector, unsigned long la_ptr,
128 struct pt_regs *regs)
129 {
130 char *mchk_class;
132 /* Now for some analysis. Machine checks fall into two classes --
133 those picked up by the system, and those picked up by the CPU.
134 Add to that the two levels of severity - correctable or not. */
136 if (vector == SCB_Q_SYSMCHK
137 && ((IRONGATE0->dramms & 0x300) == 0x300)) {
138 unsigned long nmi_ctl;
140 /* Clear ALI NMI */
141 nmi_ctl = inb(0x61);
142 nmi_ctl |= 0x0c;
143 outb(nmi_ctl, 0x61);
144 nmi_ctl &= ~0x0c;
145 outb(nmi_ctl, 0x61);
147 /* Write again clears error bits. */
148 IRONGATE0->stat_cmd = IRONGATE0->stat_cmd & ~0x100;
149 mb();
150 IRONGATE0->stat_cmd;
152 /* Write again clears error bits. */
153 IRONGATE0->dramms = IRONGATE0->dramms;
154 mb();
155 IRONGATE0->dramms;
157 draina();
158 wrmces(0x7);
159 mb();
160 return;
161 }
163 if (vector == SCB_Q_SYSERR)
164 mchk_class = "Correctable";
165 else if (vector == SCB_Q_SYSMCHK)
166 mchk_class = "Fatal";
167 else {
168 ev6_machine_check(vector, la_ptr, regs);
169 return;
170 }
172 printk(KERN_CRIT "NAUTILUS Machine check 0x%lx "
173 "[%s System Machine Check (NMI)]\n",
174 vector, mchk_class);
176 naut_sys_machine_check(vector, la_ptr, regs);
178 /* Tell the PALcode to clear the machine check */
179 draina();
180 wrmces(0x7);
181 mb();
182 }
184 extern void free_reserved_mem(void *, void *);
186 static struct resource irongate_mem = {
187 .name = "Irongate PCI MEM",
188 .flags = IORESOURCE_MEM,
189 };
191 void __init
192 nautilus_init_pci(void)
193 {
194 struct pci_controller *hose = hose_head;
195 struct pci_bus *bus;
196 struct pci_dev *irongate;
197 unsigned long bus_align, bus_size, pci_mem;
198 unsigned long memtop = max_low_pfn << PAGE_SHIFT;
200 /* Scan our single hose. */
201 bus = pci_scan_bus(0, alpha_mv.pci_ops, hose);
202 hose->bus = bus;
204 irongate = pci_find_slot(0, 0);
205 bus->self = irongate;
206 bus->resource[1] = &irongate_mem;
208 pci_bus_size_bridges(bus);
210 /* IO port range. */
211 bus->resource[0]->start = 0;
212 bus->resource[0]->end = 0xffff;
214 /* Set up PCI memory range - limit is hardwired to 0xffffffff,
215 base must be at aligned to 16Mb. */
216 bus_align = bus->resource[1]->start;
217 bus_size = bus->resource[1]->end + 1 - bus_align;
218 if (bus_align < 0x1000000UL)
219 bus_align = 0x1000000UL;
221 pci_mem = (0x100000000UL - bus_size) & -bus_align;
223 bus->resource[1]->start = pci_mem;
224 bus->resource[1]->end = 0xffffffffUL;
225 if (request_resource(&iomem_resource, bus->resource[1]) < 0)
226 printk(KERN_ERR "Failed to request MEM on hose 0\n");
228 if (pci_mem < memtop)
229 memtop = pci_mem;
230 if (memtop > alpha_mv.min_mem_address) {
231 free_reserved_mem(__va(alpha_mv.min_mem_address),
232 __va(memtop));
233 printk("nautilus_init_pci: %ldk freed\n",
234 (memtop - alpha_mv.min_mem_address) >> 10);
235 }
237 if ((IRONGATE0->dev_vendor >> 16) > 0x7006) /* Albacore? */
238 IRONGATE0->pci_mem = pci_mem;
240 pci_bus_assign_resources(bus);
241 pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
242 }
244 /*
245 * The System Vectors
246 */
248 struct alpha_machine_vector nautilus_mv __initmv = {
249 .vector_name = "Nautilus",
250 DO_EV6_MMU,
251 DO_DEFAULT_RTC,
252 DO_IRONGATE_IO,
253 .machine_check = nautilus_machine_check,
254 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
255 .min_io_address = DEFAULT_IO_BASE,
256 .min_mem_address = IRONGATE_DEFAULT_MEM_BASE,
258 .nr_irqs = 16,
259 .device_interrupt = isa_device_interrupt,
261 .init_arch = irongate_init_arch,
262 .init_irq = nautilus_init_irq,
263 .init_rtc = common_init_rtc,
264 .init_pci = nautilus_init_pci,
265 .kill_arch = nautilus_kill_arch,
266 .pci_map_irq = nautilus_map_irq,
267 .pci_swizzle = common_swizzle,
268 };
269 ALIAS_MV(nautilus)