Blame view

drivers/xen/xen-balloon.c 6.69 KB
803eb047a   Daniel De Graaf   xen-balloon: Move...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  /******************************************************************************
   * Xen balloon driver - enables returning/claiming memory to/from Xen.
   *
   * Copyright (c) 2003, B Dragovic
   * Copyright (c) 2003-2004, M Williamson, K Fraser
   * Copyright (c) 2005 Dan M. Smith, IBM Corporation
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License version 2
   * as published by the Free Software Foundation; or, when distributed
   * separately from the Linux kernel or incorporated into other
   * software packages, subject to the following license:
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this source file (the "Software"), to deal in the Software without
   * restriction, including without limitation the rights to use, copy, modify,
   * merge, publish, distribute, sublicense, and/or sell copies of the Software,
   * and to permit persons to whom the Software is furnished to do so, subject to
   * the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   * IN THE SOFTWARE.
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
803eb047a   Daniel De Graaf   xen-balloon: Move...
35
36
37
38
39
40
41
42
43
44
45
46
  #include <linux/capability.h>
  
  #include <xen/xen.h>
  #include <xen/interface/xen.h>
  #include <xen/balloon.h>
  #include <xen/xenbus.h>
  #include <xen/features.h>
  #include <xen/page.h>
  
  #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
  
  #define BALLOON_CLASS_NAME "xen_memory"
070680218   Kay Sievers   xen-balloon: conv...
47
  static struct device balloon_dev;
803eb047a   Daniel De Graaf   xen-balloon: Move...
48

070680218   Kay Sievers   xen-balloon: conv...
49
  static int register_balloon(struct device *dev);
803eb047a   Daniel De Graaf   xen-balloon: Move...
50

803eb047a   Daniel De Graaf   xen-balloon: Move...
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  /* React to a change in the target key */
  static void watch_target(struct xenbus_watch *watch,
  			 const char **vec, unsigned int len)
  {
  	unsigned long long new_target;
  	int err;
  
  	err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target);
  	if (err != 1) {
  		/* This is ok (for domain0 at least) - so just return */
  		return;
  	}
  
  	/* The given memory/target value is in KiB, so it needs converting to
  	 * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10.
  	 */
  	balloon_set_new_target(new_target >> (PAGE_SHIFT - 10));
  }
6b71c52e7   Olaf Hering   xen: use static i...
69
70
71
72
  static struct xenbus_watch target_watch = {
  	.node = "memory/target",
  	.callback = watch_target,
  };
803eb047a   Daniel De Graaf   xen-balloon: Move...
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  
  static int balloon_init_watcher(struct notifier_block *notifier,
  				unsigned long event,
  				void *data)
  {
  	int err;
  
  	err = register_xenbus_watch(&target_watch);
  	if (err)
  		printk(KERN_ERR "Failed to set balloon watcher
  ");
  
  	return NOTIFY_DONE;
  }
6b71c52e7   Olaf Hering   xen: use static i...
87
88
89
  static struct notifier_block xenstore_notifier = {
  	.notifier_call = balloon_init_watcher,
  };
803eb047a   Daniel De Graaf   xen-balloon: Move...
90
91
92
93
94
95
96
97
  
  static int __init balloon_init(void)
  {
  	if (!xen_domain())
  		return -ENODEV;
  
  	pr_info("xen-balloon: Initialising balloon driver.
  ");
070680218   Kay Sievers   xen-balloon: conv...
98
  	register_balloon(&balloon_dev);
803eb047a   Daniel De Graaf   xen-balloon: Move...
99

070680218   Kay Sievers   xen-balloon: conv...
100
  	register_xen_selfballooning(&balloon_dev);
a50777c79   Dan Magenheimer   xen: tmem: self-b...
101

803eb047a   Daniel De Graaf   xen-balloon: Move...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  	register_xenstore_notifier(&xenstore_notifier);
  
  	return 0;
  }
  subsys_initcall(balloon_init);
  
  static void balloon_exit(void)
  {
      /* XXX - release balloon here */
      return;
  }
  
  module_exit(balloon_exit);
  
  #define BALLOON_SHOW(name, format, args...)				\
070680218   Kay Sievers   xen-balloon: conv...
117
118
  	static ssize_t show_##name(struct device *dev,			\
  				   struct device_attribute *attr,	\
803eb047a   Daniel De Graaf   xen-balloon: Move...
119
120
121
122
  				   char *buf)				\
  	{								\
  		return sprintf(buf, format, ##args);			\
  	}								\
070680218   Kay Sievers   xen-balloon: conv...
123
  	static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
803eb047a   Daniel De Graaf   xen-balloon: Move...
124
125
126
127
128
129
130
  
  BALLOON_SHOW(current_kb, "%lu
  ", PAGES2KB(balloon_stats.current_pages));
  BALLOON_SHOW(low_kb, "%lu
  ", PAGES2KB(balloon_stats.balloon_low));
  BALLOON_SHOW(high_kb, "%lu
  ", PAGES2KB(balloon_stats.balloon_high));
070680218   Kay Sievers   xen-balloon: conv...
131
132
133
134
  static DEVICE_ULONG_ATTR(schedule_delay, 0444, balloon_stats.schedule_delay);
  static DEVICE_ULONG_ATTR(max_schedule_delay, 0644, balloon_stats.max_schedule_delay);
  static DEVICE_ULONG_ATTR(retry_count, 0444, balloon_stats.retry_count);
  static DEVICE_ULONG_ATTR(max_retry_count, 0644, balloon_stats.max_retry_count);
803eb047a   Daniel De Graaf   xen-balloon: Move...
135

070680218   Kay Sievers   xen-balloon: conv...
136
  static ssize_t show_target_kb(struct device *dev, struct device_attribute *attr,
803eb047a   Daniel De Graaf   xen-balloon: Move...
137
138
139
140
141
  			      char *buf)
  {
  	return sprintf(buf, "%lu
  ", PAGES2KB(balloon_stats.target_pages));
  }
070680218   Kay Sievers   xen-balloon: conv...
142
143
  static ssize_t store_target_kb(struct device *dev,
  			       struct device_attribute *attr,
803eb047a   Daniel De Graaf   xen-balloon: Move...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  			       const char *buf,
  			       size_t count)
  {
  	char *endchar;
  	unsigned long long target_bytes;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	target_bytes = simple_strtoull(buf, &endchar, 0) * 1024;
  
  	balloon_set_new_target(target_bytes >> PAGE_SHIFT);
  
  	return count;
  }
070680218   Kay Sievers   xen-balloon: conv...
159
  static DEVICE_ATTR(target_kb, S_IRUGO | S_IWUSR,
803eb047a   Daniel De Graaf   xen-balloon: Move...
160
  		   show_target_kb, store_target_kb);
070680218   Kay Sievers   xen-balloon: conv...
161
  static ssize_t show_target(struct device *dev, struct device_attribute *attr,
803eb047a   Daniel De Graaf   xen-balloon: Move...
162
163
164
165
166
167
168
  			      char *buf)
  {
  	return sprintf(buf, "%llu
  ",
  		       (unsigned long long)balloon_stats.target_pages
  		       << PAGE_SHIFT);
  }
070680218   Kay Sievers   xen-balloon: conv...
169
170
  static ssize_t store_target(struct device *dev,
  			    struct device_attribute *attr,
803eb047a   Daniel De Graaf   xen-balloon: Move...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  			    const char *buf,
  			    size_t count)
  {
  	char *endchar;
  	unsigned long long target_bytes;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	target_bytes = memparse(buf, &endchar);
  
  	balloon_set_new_target(target_bytes >> PAGE_SHIFT);
  
  	return count;
  }
070680218   Kay Sievers   xen-balloon: conv...
186
  static DEVICE_ATTR(target, S_IRUGO | S_IWUSR,
803eb047a   Daniel De Graaf   xen-balloon: Move...
187
  		   show_target, store_target);
070680218   Kay Sievers   xen-balloon: conv...
188
189
190
191
192
193
194
  static struct device_attribute *balloon_attrs[] = {
  	&dev_attr_target_kb,
  	&dev_attr_target,
  	&dev_attr_schedule_delay.attr,
  	&dev_attr_max_schedule_delay.attr,
  	&dev_attr_retry_count.attr,
  	&dev_attr_max_retry_count.attr
803eb047a   Daniel De Graaf   xen-balloon: Move...
195
196
197
  };
  
  static struct attribute *balloon_info_attrs[] = {
070680218   Kay Sievers   xen-balloon: conv...
198
199
200
  	&dev_attr_current_kb.attr,
  	&dev_attr_low_kb.attr,
  	&dev_attr_high_kb.attr,
803eb047a   Daniel De Graaf   xen-balloon: Move...
201
202
203
204
205
206
207
  	NULL
  };
  
  static struct attribute_group balloon_info_group = {
  	.name = "info",
  	.attrs = balloon_info_attrs
  };
070680218   Kay Sievers   xen-balloon: conv...
208
209
210
  static struct bus_type balloon_subsys = {
  	.name = BALLOON_CLASS_NAME,
  	.dev_name = BALLOON_CLASS_NAME,
803eb047a   Daniel De Graaf   xen-balloon: Move...
211
  };
070680218   Kay Sievers   xen-balloon: conv...
212
  static int register_balloon(struct device *dev)
803eb047a   Daniel De Graaf   xen-balloon: Move...
213
214
  {
  	int i, error;
070680218   Kay Sievers   xen-balloon: conv...
215
  	error = bus_register(&balloon_subsys);
803eb047a   Daniel De Graaf   xen-balloon: Move...
216
217
  	if (error)
  		return error;
070680218   Kay Sievers   xen-balloon: conv...
218
219
  	dev->id = 0;
  	dev->bus = &balloon_subsys;
803eb047a   Daniel De Graaf   xen-balloon: Move...
220

070680218   Kay Sievers   xen-balloon: conv...
221
  	error = device_register(dev);
803eb047a   Daniel De Graaf   xen-balloon: Move...
222
  	if (error) {
070680218   Kay Sievers   xen-balloon: conv...
223
  		bus_unregister(&balloon_subsys);
803eb047a   Daniel De Graaf   xen-balloon: Move...
224
225
226
227
  		return error;
  	}
  
  	for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) {
070680218   Kay Sievers   xen-balloon: conv...
228
  		error = device_create_file(dev, balloon_attrs[i]);
803eb047a   Daniel De Graaf   xen-balloon: Move...
229
230
231
  		if (error)
  			goto fail;
  	}
070680218   Kay Sievers   xen-balloon: conv...
232
  	error = sysfs_create_group(&dev->kobj, &balloon_info_group);
803eb047a   Daniel De Graaf   xen-balloon: Move...
233
234
235
236
237
238
239
  	if (error)
  		goto fail;
  
  	return 0;
  
   fail:
  	while (--i >= 0)
070680218   Kay Sievers   xen-balloon: conv...
240
241
242
  		device_remove_file(dev, balloon_attrs[i]);
  	device_unregister(dev);
  	bus_unregister(&balloon_subsys);
803eb047a   Daniel De Graaf   xen-balloon: Move...
243
244
245
246
  	return error;
  }
  
  MODULE_LICENSE("GPL");