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#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 34 35#include <linux/kernel.h> 36#include <linux/module.h> 37#include <linux/capability.h> 38 39#include <xen/xen.h> 40#include <xen/interface/xen.h> 41#include <xen/balloon.h> 42#include <xen/xenbus.h> 43#include <xen/features.h> 44#include <xen/page.h> 45 46#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) 47 48#define BALLOON_CLASS_NAME "xen_memory" 49 50static struct device balloon_dev; 51 52static int register_balloon(struct device *dev); 53 54/* React to a change in the target key */ 55static void watch_target(struct xenbus_watch *watch, 56 const char **vec, unsigned int len) 57{ 58 unsigned long long new_target; 59 int err; 60 61 err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target); 62 if (err != 1) { 63 /* This is ok (for domain0 at least) - so just return */ 64 return; 65 } 66 67 /* The given memory/target value is in KiB, so it needs converting to 68 * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10. 69 */ 70 balloon_set_new_target(new_target >> (PAGE_SHIFT - 10)); 71} 72static struct xenbus_watch target_watch = { 73 .node = "memory/target", 74 .callback = watch_target, 75}; 76 77 78static int balloon_init_watcher(struct notifier_block *notifier, 79 unsigned long event, 80 void *data) 81{ 82 int err; 83 84 err = register_xenbus_watch(&target_watch); 85 if (err) 86 pr_err("Failed to set balloon watcher\n"); 87 88 return NOTIFY_DONE; 89} 90 91static struct notifier_block xenstore_notifier = { 92 .notifier_call = balloon_init_watcher, 93}; 94 95static int __init balloon_init(void) 96{ 97 if (!xen_domain()) 98 return -ENODEV; 99 100 pr_info("Initialising balloon driver\n"); 101 102 register_balloon(&balloon_dev); 103 104 register_xen_selfballooning(&balloon_dev); 105 106 register_xenstore_notifier(&xenstore_notifier); 107 108 return 0; 109} 110subsys_initcall(balloon_init); 111 112static void balloon_exit(void) 113{ 114 /* XXX - release balloon here */ 115 return; 116} 117 118module_exit(balloon_exit); 119 120#define BALLOON_SHOW(name, format, args...) \ 121 static ssize_t show_##name(struct device *dev, \ 122 struct device_attribute *attr, \ 123 char *buf) \ 124 { \ 125 return sprintf(buf, format, ##args); \ 126 } \ 127 static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) 128 129BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages)); 130BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low)); 131BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high)); 132 133static DEVICE_ULONG_ATTR(schedule_delay, 0444, balloon_stats.schedule_delay); 134static DEVICE_ULONG_ATTR(max_schedule_delay, 0644, balloon_stats.max_schedule_delay); 135static DEVICE_ULONG_ATTR(retry_count, 0444, balloon_stats.retry_count); 136static DEVICE_ULONG_ATTR(max_retry_count, 0644, balloon_stats.max_retry_count); 137 138static ssize_t show_target_kb(struct device *dev, struct device_attribute *attr, 139 char *buf) 140{ 141 return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages)); 142} 143 144static ssize_t store_target_kb(struct device *dev, 145 struct device_attribute *attr, 146 const char *buf, 147 size_t count) 148{ 149 char *endchar; 150 unsigned long long target_bytes; 151 152 if (!capable(CAP_SYS_ADMIN)) 153 return -EPERM; 154 155 target_bytes = simple_strtoull(buf, &endchar, 0) * 1024; 156 157 balloon_set_new_target(target_bytes >> PAGE_SHIFT); 158 159 return count; 160} 161 162static DEVICE_ATTR(target_kb, S_IRUGO | S_IWUSR, 163 show_target_kb, store_target_kb); 164 165 166static ssize_t show_target(struct device *dev, struct device_attribute *attr, 167 char *buf) 168{ 169 return sprintf(buf, "%llu\n", 170 (unsigned long long)balloon_stats.target_pages 171 << PAGE_SHIFT); 172} 173 174static ssize_t store_target(struct device *dev, 175 struct device_attribute *attr, 176 const char *buf, 177 size_t count) 178{ 179 char *endchar; 180 unsigned long long target_bytes; 181 182 if (!capable(CAP_SYS_ADMIN)) 183 return -EPERM; 184 185 target_bytes = memparse(buf, &endchar); 186 187 balloon_set_new_target(target_bytes >> PAGE_SHIFT); 188 189 return count; 190} 191 192static DEVICE_ATTR(target, S_IRUGO | S_IWUSR, 193 show_target, store_target); 194 195 196static struct attribute *balloon_attrs[] = { 197 &dev_attr_target_kb.attr, 198 &dev_attr_target.attr, 199 &dev_attr_schedule_delay.attr.attr, 200 &dev_attr_max_schedule_delay.attr.attr, 201 &dev_attr_retry_count.attr.attr, 202 &dev_attr_max_retry_count.attr.attr, 203 NULL 204}; 205 206static const struct attribute_group balloon_group = { 207 .attrs = balloon_attrs 208}; 209 210static struct attribute *balloon_info_attrs[] = { 211 &dev_attr_current_kb.attr, 212 &dev_attr_low_kb.attr, 213 &dev_attr_high_kb.attr, 214 NULL 215}; 216 217static const struct attribute_group balloon_info_group = { 218 .name = "info", 219 .attrs = balloon_info_attrs 220}; 221 222static const struct attribute_group *balloon_groups[] = { 223 &balloon_group, 224 &balloon_info_group, 225 NULL 226}; 227 228static struct bus_type balloon_subsys = { 229 .name = BALLOON_CLASS_NAME, 230 .dev_name = BALLOON_CLASS_NAME, 231}; 232 233static int register_balloon(struct device *dev) 234{ 235 int error; 236 237 error = subsys_system_register(&balloon_subsys, NULL); 238 if (error) 239 return error; 240 241 dev->id = 0; 242 dev->bus = &balloon_subsys; 243 dev->groups = balloon_groups; 244 245 error = device_register(dev); 246 if (error) { 247 bus_unregister(&balloon_subsys); 248 return error; 249 } 250 251 return 0; 252} 253 254MODULE_LICENSE("GPL"); 255