Root/
1 | /****************************************************************************** |
2 | * Xen balloon driver - enables returning/claiming memory to/from Xen. |
3 | * |
4 | * Copyright (c) 2003, B Dragovic |
5 | * Copyright (c) 2003-2004, M Williamson, K Fraser |
6 | * Copyright (c) 2005 Dan M. Smith, IBM Corporation |
7 | * |
8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License version 2 |
10 | * as published by the Free Software Foundation; or, when distributed |
11 | * separately from the Linux kernel or incorporated into other |
12 | * software packages, subject to the following license: |
13 | * |
14 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
15 | * of this source file (the "Software"), to deal in the Software without |
16 | * restriction, including without limitation the rights to use, copy, modify, |
17 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, |
18 | * and to permit persons to whom the Software is furnished to do so, subject to |
19 | * the following conditions: |
20 | * |
21 | * The above copyright notice and this permission notice shall be included in |
22 | * all copies or substantial portions of the Software. |
23 | * |
24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
28 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
29 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
30 | * IN THE SOFTWARE. |
31 | */ |
32 | |
33 | #include <linux/kernel.h> |
34 | #include <linux/module.h> |
35 | #include <linux/capability.h> |
36 | |
37 | #include <xen/xen.h> |
38 | #include <xen/interface/xen.h> |
39 | #include <xen/balloon.h> |
40 | #include <xen/xenbus.h> |
41 | #include <xen/features.h> |
42 | #include <xen/page.h> |
43 | |
44 | #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) |
45 | |
46 | #define BALLOON_CLASS_NAME "xen_memory" |
47 | |
48 | static struct device balloon_dev; |
49 | |
50 | static int register_balloon(struct device *dev); |
51 | |
52 | /* React to a change in the target key */ |
53 | static void watch_target(struct xenbus_watch *watch, |
54 | const char **vec, unsigned int len) |
55 | { |
56 | unsigned long long new_target; |
57 | int err; |
58 | |
59 | err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target); |
60 | if (err != 1) { |
61 | /* This is ok (for domain0 at least) - so just return */ |
62 | return; |
63 | } |
64 | |
65 | /* The given memory/target value is in KiB, so it needs converting to |
66 | * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10. |
67 | */ |
68 | balloon_set_new_target(new_target >> (PAGE_SHIFT - 10)); |
69 | } |
70 | static struct xenbus_watch target_watch = { |
71 | .node = "memory/target", |
72 | .callback = watch_target, |
73 | }; |
74 | |
75 | |
76 | static int balloon_init_watcher(struct notifier_block *notifier, |
77 | unsigned long event, |
78 | void *data) |
79 | { |
80 | int err; |
81 | |
82 | err = register_xenbus_watch(&target_watch); |
83 | if (err) |
84 | printk(KERN_ERR "Failed to set balloon watcher\n"); |
85 | |
86 | return NOTIFY_DONE; |
87 | } |
88 | |
89 | static struct notifier_block xenstore_notifier = { |
90 | .notifier_call = balloon_init_watcher, |
91 | }; |
92 | |
93 | static int __init balloon_init(void) |
94 | { |
95 | if (!xen_domain()) |
96 | return -ENODEV; |
97 | |
98 | pr_info("xen-balloon: Initialising balloon driver.\n"); |
99 | |
100 | register_balloon(&balloon_dev); |
101 | |
102 | register_xen_selfballooning(&balloon_dev); |
103 | |
104 | register_xenstore_notifier(&xenstore_notifier); |
105 | |
106 | return 0; |
107 | } |
108 | subsys_initcall(balloon_init); |
109 | |
110 | static void balloon_exit(void) |
111 | { |
112 | /* XXX - release balloon here */ |
113 | return; |
114 | } |
115 | |
116 | module_exit(balloon_exit); |
117 | |
118 | #define BALLOON_SHOW(name, format, args...) \ |
119 | static ssize_t show_##name(struct device *dev, \ |
120 | struct device_attribute *attr, \ |
121 | char *buf) \ |
122 | { \ |
123 | return sprintf(buf, format, ##args); \ |
124 | } \ |
125 | static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) |
126 | |
127 | BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages)); |
128 | BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low)); |
129 | BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high)); |
130 | |
131 | static DEVICE_ULONG_ATTR(schedule_delay, 0444, balloon_stats.schedule_delay); |
132 | static DEVICE_ULONG_ATTR(max_schedule_delay, 0644, balloon_stats.max_schedule_delay); |
133 | static DEVICE_ULONG_ATTR(retry_count, 0444, balloon_stats.retry_count); |
134 | static DEVICE_ULONG_ATTR(max_retry_count, 0644, balloon_stats.max_retry_count); |
135 | |
136 | static ssize_t show_target_kb(struct device *dev, struct device_attribute *attr, |
137 | char *buf) |
138 | { |
139 | return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages)); |
140 | } |
141 | |
142 | static ssize_t store_target_kb(struct device *dev, |
143 | struct device_attribute *attr, |
144 | const char *buf, |
145 | size_t count) |
146 | { |
147 | char *endchar; |
148 | unsigned long long target_bytes; |
149 | |
150 | if (!capable(CAP_SYS_ADMIN)) |
151 | return -EPERM; |
152 | |
153 | target_bytes = simple_strtoull(buf, &endchar, 0) * 1024; |
154 | |
155 | balloon_set_new_target(target_bytes >> PAGE_SHIFT); |
156 | |
157 | return count; |
158 | } |
159 | |
160 | static DEVICE_ATTR(target_kb, S_IRUGO | S_IWUSR, |
161 | show_target_kb, store_target_kb); |
162 | |
163 | |
164 | static ssize_t show_target(struct device *dev, struct device_attribute *attr, |
165 | char *buf) |
166 | { |
167 | return sprintf(buf, "%llu\n", |
168 | (unsigned long long)balloon_stats.target_pages |
169 | << PAGE_SHIFT); |
170 | } |
171 | |
172 | static ssize_t store_target(struct device *dev, |
173 | struct device_attribute *attr, |
174 | const char *buf, |
175 | size_t count) |
176 | { |
177 | char *endchar; |
178 | unsigned long long target_bytes; |
179 | |
180 | if (!capable(CAP_SYS_ADMIN)) |
181 | return -EPERM; |
182 | |
183 | target_bytes = memparse(buf, &endchar); |
184 | |
185 | balloon_set_new_target(target_bytes >> PAGE_SHIFT); |
186 | |
187 | return count; |
188 | } |
189 | |
190 | static DEVICE_ATTR(target, S_IRUGO | S_IWUSR, |
191 | show_target, store_target); |
192 | |
193 | |
194 | static struct device_attribute *balloon_attrs[] = { |
195 | &dev_attr_target_kb, |
196 | &dev_attr_target, |
197 | &dev_attr_schedule_delay.attr, |
198 | &dev_attr_max_schedule_delay.attr, |
199 | &dev_attr_retry_count.attr, |
200 | &dev_attr_max_retry_count.attr |
201 | }; |
202 | |
203 | static struct attribute *balloon_info_attrs[] = { |
204 | &dev_attr_current_kb.attr, |
205 | &dev_attr_low_kb.attr, |
206 | &dev_attr_high_kb.attr, |
207 | NULL |
208 | }; |
209 | |
210 | static const struct attribute_group balloon_info_group = { |
211 | .name = "info", |
212 | .attrs = balloon_info_attrs |
213 | }; |
214 | |
215 | static struct bus_type balloon_subsys = { |
216 | .name = BALLOON_CLASS_NAME, |
217 | .dev_name = BALLOON_CLASS_NAME, |
218 | }; |
219 | |
220 | static int register_balloon(struct device *dev) |
221 | { |
222 | int i, error; |
223 | |
224 | error = subsys_system_register(&balloon_subsys, NULL); |
225 | if (error) |
226 | return error; |
227 | |
228 | dev->id = 0; |
229 | dev->bus = &balloon_subsys; |
230 | |
231 | error = device_register(dev); |
232 | if (error) { |
233 | bus_unregister(&balloon_subsys); |
234 | return error; |
235 | } |
236 | |
237 | for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) { |
238 | error = device_create_file(dev, balloon_attrs[i]); |
239 | if (error) |
240 | goto fail; |
241 | } |
242 | |
243 | error = sysfs_create_group(&dev->kobj, &balloon_info_group); |
244 | if (error) |
245 | goto fail; |
246 | |
247 | return 0; |
248 | |
249 | fail: |
250 | while (--i >= 0) |
251 | device_remove_file(dev, balloon_attrs[i]); |
252 | device_unregister(dev); |
253 | bus_unregister(&balloon_subsys); |
254 | return error; |
255 | } |
256 | |
257 | MODULE_LICENSE("GPL"); |
258 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9