ia64/linux-2.6.18-xen.hg

view arch/sparc64/kernel/devices.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 /* devices.c: Initial scan of the prom device tree for important
2 * Sparc device nodes which we need to find.
3 *
4 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
5 */
7 #include <linux/kernel.h>
8 #include <linux/threads.h>
9 #include <linux/init.h>
10 #include <linux/ioport.h>
11 #include <linux/string.h>
12 #include <linux/spinlock.h>
13 #include <linux/errno.h>
14 #include <linux/bootmem.h>
16 #include <asm/page.h>
17 #include <asm/oplib.h>
18 #include <asm/system.h>
19 #include <asm/smp.h>
20 #include <asm/spitfire.h>
21 #include <asm/timer.h>
22 #include <asm/cpudata.h>
24 /* Used to synchronize acceses to NatSemi SUPER I/O chip configure
25 * operations in asm/ns87303.h
26 */
27 DEFINE_SPINLOCK(ns87303_lock);
29 extern void cpu_probe(void);
30 extern void central_probe(void);
32 static const char *cpu_mid_prop(void)
33 {
34 if (tlb_type == spitfire)
35 return "upa-portid";
36 return "portid";
37 }
39 static int get_cpu_mid(struct device_node *dp)
40 {
41 struct property *prop;
43 if (tlb_type == hypervisor) {
44 struct linux_prom64_registers *reg;
45 int len;
47 prop = of_find_property(dp, "cpuid", &len);
48 if (prop && len == 4)
49 return *(int *) prop->value;
51 prop = of_find_property(dp, "reg", NULL);
52 reg = prop->value;
53 return (reg[0].phys_addr >> 32) & 0x0fffffffUL;
54 } else {
55 const char *prop_name = cpu_mid_prop();
57 prop = of_find_property(dp, prop_name, NULL);
58 if (prop)
59 return *(int *) prop->value;
60 return 0;
61 }
62 }
64 static int check_cpu_node(struct device_node *dp, int *cur_inst,
65 int (*compare)(struct device_node *, int, void *),
66 void *compare_arg,
67 struct device_node **dev_node, int *mid)
68 {
69 if (!compare(dp, *cur_inst, compare_arg)) {
70 if (dev_node)
71 *dev_node = dp;
72 if (mid)
73 *mid = get_cpu_mid(dp);
74 return 0;
75 }
77 (*cur_inst)++;
79 return -ENODEV;
80 }
82 static int __cpu_find_by(int (*compare)(struct device_node *, int, void *),
83 void *compare_arg,
84 struct device_node **dev_node, int *mid)
85 {
86 struct device_node *dp;
87 int cur_inst;
89 cur_inst = 0;
90 for_each_node_by_type(dp, "cpu") {
91 int err = check_cpu_node(dp, &cur_inst,
92 compare, compare_arg,
93 dev_node, mid);
94 if (err == 0)
95 return 0;
96 }
98 return -ENODEV;
99 }
101 static int cpu_instance_compare(struct device_node *dp, int instance, void *_arg)
102 {
103 int desired_instance = (int) (long) _arg;
105 if (instance == desired_instance)
106 return 0;
107 return -ENODEV;
108 }
110 int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid)
111 {
112 return __cpu_find_by(cpu_instance_compare, (void *)(long)instance,
113 dev_node, mid);
114 }
116 static int cpu_mid_compare(struct device_node *dp, int instance, void *_arg)
117 {
118 int desired_mid = (int) (long) _arg;
119 int this_mid;
121 this_mid = get_cpu_mid(dp);
122 if (this_mid == desired_mid)
123 return 0;
124 return -ENODEV;
125 }
127 int cpu_find_by_mid(int mid, struct device_node **dev_node)
128 {
129 return __cpu_find_by(cpu_mid_compare, (void *)(long)mid,
130 dev_node, NULL);
131 }
133 void __init device_scan(void)
134 {
135 /* FIX ME FAST... -DaveM */
136 ioport_resource.end = 0xffffffffffffffffUL;
138 prom_printf("Booting Linux...\n");
140 #ifndef CONFIG_SMP
141 {
142 struct device_node *dp;
143 int err, def;
145 err = cpu_find_by_instance(0, &dp, NULL);
146 if (err) {
147 prom_printf("No cpu nodes, cannot continue\n");
148 prom_halt();
149 }
150 cpu_data(0).clock_tick =
151 of_getintprop_default(dp, "clock-frequency", 0);
153 def = ((tlb_type == hypervisor) ?
154 (8 * 1024) :
155 (16 * 1024));
156 cpu_data(0).dcache_size = of_getintprop_default(dp,
157 "dcache-size",
158 def);
160 def = 32;
161 cpu_data(0).dcache_line_size =
162 of_getintprop_default(dp, "dcache-line-size", def);
164 def = 16 * 1024;
165 cpu_data(0).icache_size = of_getintprop_default(dp,
166 "icache-size",
167 def);
169 def = 32;
170 cpu_data(0).icache_line_size =
171 of_getintprop_default(dp, "icache-line-size", def);
173 def = ((tlb_type == hypervisor) ?
174 (3 * 1024 * 1024) :
175 (4 * 1024 * 1024));
176 cpu_data(0).ecache_size = of_getintprop_default(dp,
177 "ecache-size",
178 def);
180 def = 64;
181 cpu_data(0).ecache_line_size =
182 of_getintprop_default(dp, "ecache-line-size", def);
183 printk("CPU[0]: Caches "
184 "D[sz(%d):line_sz(%d)] "
185 "I[sz(%d):line_sz(%d)] "
186 "E[sz(%d):line_sz(%d)]\n",
187 cpu_data(0).dcache_size, cpu_data(0).dcache_line_size,
188 cpu_data(0).icache_size, cpu_data(0).icache_line_size,
189 cpu_data(0).ecache_size, cpu_data(0).ecache_line_size);
190 }
191 #endif
193 central_probe();
195 cpu_probe();
196 }