ia64/linux-2.6.18-xen.hg

view arch/mips/sgi-ip32/ip32-reset.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 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2001 Keith M Wesolowski
7 * Copyright (C) 2001 Paul Mundt
8 * Copyright (C) 2003 Guido Guenther <agx@sigxcpu.org>
9 */
11 #include <linux/init.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/notifier.h>
15 #include <linux/delay.h>
16 #include <linux/ds17287rtc.h>
17 #include <linux/interrupt.h>
18 #include <linux/pm.h>
20 #include <asm/addrspace.h>
21 #include <asm/irq.h>
22 #include <asm/reboot.h>
23 #include <asm/system.h>
24 #include <asm/wbflush.h>
25 #include <asm/ip32/mace.h>
26 #include <asm/ip32/crime.h>
27 #include <asm/ip32/ip32_ints.h>
29 #define POWERDOWN_TIMEOUT 120
30 /*
31 * Blink frequency during reboot grace period and when panicked.
32 */
33 #define POWERDOWN_FREQ (HZ / 4)
34 #define PANIC_FREQ (HZ / 8)
36 static struct timer_list power_timer, blink_timer, debounce_timer;
37 static int has_panicked, shuting_down;
39 static void ip32_machine_restart(char *command) __attribute__((noreturn));
40 static void ip32_machine_halt(void) __attribute__((noreturn));
41 static void ip32_machine_power_off(void) __attribute__((noreturn));
43 static void ip32_machine_restart(char *cmd)
44 {
45 crime->control = CRIME_CONTROL_HARD_RESET;
46 while (1);
47 }
49 static inline void ip32_machine_halt(void)
50 {
51 ip32_machine_power_off();
52 }
54 static void ip32_machine_power_off(void)
55 {
56 volatile unsigned char reg_a, xctrl_a, xctrl_b;
58 disable_irq(MACEISA_RTC_IRQ);
59 reg_a = CMOS_READ(RTC_REG_A);
61 /* setup for kickstart & wake-up (DS12287 Ref. Man. p. 19) */
62 reg_a &= ~DS_REGA_DV2;
63 reg_a |= DS_REGA_DV1;
65 CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A);
66 wbflush();
67 xctrl_b = CMOS_READ(DS_B1_XCTRL4B)
68 | DS_XCTRL4B_ABE | DS_XCTRL4B_KFE;
69 CMOS_WRITE(xctrl_b, DS_B1_XCTRL4B);
70 xctrl_a = CMOS_READ(DS_B1_XCTRL4A) & ~DS_XCTRL4A_IFS;
71 CMOS_WRITE(xctrl_a, DS_B1_XCTRL4A);
72 wbflush();
73 /* adios amigos... */
74 CMOS_WRITE(xctrl_a | DS_XCTRL4A_PAB, DS_B1_XCTRL4A);
75 CMOS_WRITE(reg_a, RTC_REG_A);
76 wbflush();
77 while (1);
78 }
80 static void power_timeout(unsigned long data)
81 {
82 ip32_machine_power_off();
83 }
85 static void blink_timeout(unsigned long data)
86 {
87 unsigned long led = mace->perif.ctrl.misc ^ MACEISA_LED_RED;
88 mace->perif.ctrl.misc = led;
89 mod_timer(&blink_timer, jiffies + data);
90 }
92 static void debounce(unsigned long data)
93 {
94 volatile unsigned char reg_a, reg_c, xctrl_a;
96 reg_c = CMOS_READ(RTC_INTR_FLAGS);
97 CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A);
98 wbflush();
99 xctrl_a = CMOS_READ(DS_B1_XCTRL4A);
100 if ((xctrl_a & DS_XCTRL4A_IFS) || (reg_c & RTC_IRQF )) {
101 /* Interrupt still being sent. */
102 debounce_timer.expires = jiffies + 50;
103 add_timer(&debounce_timer);
105 /* clear interrupt source */
106 CMOS_WRITE(xctrl_a & ~DS_XCTRL4A_IFS, DS_B1_XCTRL4A);
107 CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A);
108 return;
109 }
110 CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A);
112 if (has_panicked)
113 ip32_machine_restart(NULL);
115 enable_irq(MACEISA_RTC_IRQ);
116 }
118 static inline void ip32_power_button(void)
119 {
120 if (has_panicked)
121 return;
123 if (shuting_down || kill_proc(1, SIGINT, 1)) {
124 /* No init process or button pressed twice. */
125 ip32_machine_power_off();
126 }
128 shuting_down = 1;
129 blink_timer.data = POWERDOWN_FREQ;
130 blink_timeout(POWERDOWN_FREQ);
132 init_timer(&power_timer);
133 power_timer.function = power_timeout;
134 power_timer.expires = jiffies + POWERDOWN_TIMEOUT * HZ;
135 add_timer(&power_timer);
136 }
138 static irqreturn_t ip32_rtc_int(int irq, void *dev_id, struct pt_regs *regs)
139 {
140 volatile unsigned char reg_c;
142 reg_c = CMOS_READ(RTC_INTR_FLAGS);
143 if (!(reg_c & RTC_IRQF)) {
144 printk(KERN_WARNING
145 "%s: RTC IRQ without RTC_IRQF\n", __FUNCTION__);
146 }
147 /* Wait until interrupt goes away */
148 disable_irq(MACEISA_RTC_IRQ);
149 init_timer(&debounce_timer);
150 debounce_timer.function = debounce;
151 debounce_timer.expires = jiffies + 50;
152 add_timer(&debounce_timer);
154 printk(KERN_DEBUG "Power button pressed\n");
155 ip32_power_button();
156 return IRQ_HANDLED;
157 }
159 static int panic_event(struct notifier_block *this, unsigned long event,
160 void *ptr)
161 {
162 unsigned long led;
164 if (has_panicked)
165 return NOTIFY_DONE;
166 has_panicked = 1;
168 /* turn off the green LED */
169 led = mace->perif.ctrl.misc | MACEISA_LED_GREEN;
170 mace->perif.ctrl.misc = led;
172 blink_timer.data = PANIC_FREQ;
173 blink_timeout(PANIC_FREQ);
175 return NOTIFY_DONE;
176 }
178 static struct notifier_block panic_block = {
179 .notifier_call = panic_event,
180 };
182 static __init int ip32_reboot_setup(void)
183 {
184 /* turn on the green led only */
185 unsigned long led = mace->perif.ctrl.misc;
186 led |= MACEISA_LED_RED;
187 led &= ~MACEISA_LED_GREEN;
188 mace->perif.ctrl.misc = led;
190 _machine_restart = ip32_machine_restart;
191 _machine_halt = ip32_machine_halt;
192 pm_power_off = ip32_machine_power_off;
194 init_timer(&blink_timer);
195 blink_timer.function = blink_timeout;
196 atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
198 request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL);
200 return 0;
201 }
203 subsys_initcall(ip32_reboot_setup);