Back to home page

OSCL-LXR

 
 

    


0001 /******************************************************************************
0002  * Xen balloon driver - enables returning/claiming memory to/from Xen.
0003  *
0004  * Copyright (c) 2003, B Dragovic
0005  * Copyright (c) 2003-2004, M Williamson, K Fraser
0006  * Copyright (c) 2005 Dan M. Smith, IBM Corporation
0007  *
0008  * This program is free software; you can redistribute it and/or
0009  * modify it under the terms of the GNU General Public License version 2
0010  * as published by the Free Software Foundation; or, when distributed
0011  * separately from the Linux kernel or incorporated into other
0012  * software packages, subject to the following license:
0013  *
0014  * Permission is hereby granted, free of charge, to any person obtaining a copy
0015  * of this source file (the "Software"), to deal in the Software without
0016  * restriction, including without limitation the rights to use, copy, modify,
0017  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
0018  * and to permit persons to whom the Software is furnished to do so, subject to
0019  * the following conditions:
0020  *
0021  * The above copyright notice and this permission notice shall be included in
0022  * all copies or substantial portions of the Software.
0023  *
0024  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0025  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0026  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0027  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0028  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
0029  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
0030  * IN THE SOFTWARE.
0031  */
0032 
0033 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0034 
0035 #include <linux/kernel.h>
0036 #include <linux/errno.h>
0037 #include <linux/mm_types.h>
0038 #include <linux/init.h>
0039 #include <linux/capability.h>
0040 #include <linux/memory_hotplug.h>
0041 
0042 #include <xen/xen.h>
0043 #include <xen/interface/xen.h>
0044 #include <xen/balloon.h>
0045 #include <xen/xenbus.h>
0046 #include <xen/features.h>
0047 #include <xen/page.h>
0048 #include <xen/mem-reservation.h>
0049 
0050 #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
0051 
0052 #define BALLOON_CLASS_NAME "xen_memory"
0053 
0054 #ifdef CONFIG_MEMORY_HOTPLUG
0055 u64 xen_saved_max_mem_size = 0;
0056 #endif
0057 
0058 static struct device balloon_dev;
0059 
0060 static int register_balloon(struct device *dev);
0061 
0062 /* React to a change in the target key */
0063 static void watch_target(struct xenbus_watch *watch,
0064              const char *path, const char *token)
0065 {
0066     unsigned long long new_target, static_max;
0067     int err;
0068     static bool watch_fired;
0069     static long target_diff;
0070 
0071 #ifdef CONFIG_MEMORY_HOTPLUG
0072     /* The balloon driver will take care of adding memory now. */
0073     if (xen_saved_max_mem_size)
0074         max_mem_size = xen_saved_max_mem_size;
0075 #endif
0076 
0077     err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target);
0078     if (err != 1) {
0079         /* This is ok (for domain0 at least) - so just return */
0080         return;
0081     }
0082 
0083     /* The given memory/target value is in KiB, so it needs converting to
0084      * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10.
0085      */
0086     new_target >>= PAGE_SHIFT - 10;
0087 
0088     if (!watch_fired) {
0089         watch_fired = true;
0090 
0091         if ((xenbus_scanf(XBT_NIL, "memory", "static-max",
0092                   "%llu", &static_max) == 1) ||
0093             (xenbus_scanf(XBT_NIL, "memory", "memory_static_max",
0094                   "%llu", &static_max) == 1))
0095             static_max >>= PAGE_SHIFT - 10;
0096         else
0097             static_max = balloon_stats.current_pages;
0098 
0099         target_diff = (xen_pv_domain() || xen_initial_domain()) ? 0
0100                 : static_max - balloon_stats.target_pages;
0101     }
0102 
0103     balloon_set_new_target(new_target - target_diff);
0104 }
0105 static struct xenbus_watch target_watch = {
0106     .node = "memory/target",
0107     .callback = watch_target,
0108 };
0109 
0110 
0111 static int balloon_init_watcher(struct notifier_block *notifier,
0112                 unsigned long event,
0113                 void *data)
0114 {
0115     int err;
0116 
0117     err = register_xenbus_watch(&target_watch);
0118     if (err)
0119         pr_err("Failed to set balloon watcher\n");
0120 
0121     return NOTIFY_DONE;
0122 }
0123 
0124 static struct notifier_block xenstore_notifier = {
0125     .notifier_call = balloon_init_watcher,
0126 };
0127 
0128 void xen_balloon_init(void)
0129 {
0130     register_balloon(&balloon_dev);
0131 
0132     register_xenstore_notifier(&xenstore_notifier);
0133 }
0134 EXPORT_SYMBOL_GPL(xen_balloon_init);
0135 
0136 #define BALLOON_SHOW(name, format, args...)             \
0137     static ssize_t name##_show(struct device *dev,          \
0138                    struct device_attribute *attr,   \
0139                    char *buf)               \
0140     {                               \
0141         return sprintf(buf, format, ##args);            \
0142     }                               \
0143     static DEVICE_ATTR_RO(name)
0144 
0145 BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
0146 BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low));
0147 BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high));
0148 
0149 static DEVICE_ULONG_ATTR(schedule_delay, 0444, balloon_stats.schedule_delay);
0150 static DEVICE_ULONG_ATTR(max_schedule_delay, 0644, balloon_stats.max_schedule_delay);
0151 static DEVICE_ULONG_ATTR(retry_count, 0444, balloon_stats.retry_count);
0152 static DEVICE_ULONG_ATTR(max_retry_count, 0644, balloon_stats.max_retry_count);
0153 static DEVICE_BOOL_ATTR(scrub_pages, 0644, xen_scrub_pages);
0154 
0155 static ssize_t target_kb_show(struct device *dev, struct device_attribute *attr,
0156                   char *buf)
0157 {
0158     return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages));
0159 }
0160 
0161 static ssize_t target_kb_store(struct device *dev,
0162                    struct device_attribute *attr,
0163                    const char *buf, size_t count)
0164 {
0165     char *endchar;
0166     unsigned long long target_bytes;
0167 
0168     if (!capable(CAP_SYS_ADMIN))
0169         return -EPERM;
0170 
0171     target_bytes = simple_strtoull(buf, &endchar, 0) * 1024;
0172 
0173     balloon_set_new_target(target_bytes >> PAGE_SHIFT);
0174 
0175     return count;
0176 }
0177 
0178 static DEVICE_ATTR_RW(target_kb);
0179 
0180 static ssize_t target_show(struct device *dev, struct device_attribute *attr,
0181                char *buf)
0182 {
0183     return sprintf(buf, "%llu\n",
0184                (unsigned long long)balloon_stats.target_pages
0185                << PAGE_SHIFT);
0186 }
0187 
0188 static ssize_t target_store(struct device *dev,
0189                 struct device_attribute *attr,
0190                 const char *buf, size_t count)
0191 {
0192     char *endchar;
0193     unsigned long long target_bytes;
0194 
0195     if (!capable(CAP_SYS_ADMIN))
0196         return -EPERM;
0197 
0198     target_bytes = memparse(buf, &endchar);
0199 
0200     balloon_set_new_target(target_bytes >> PAGE_SHIFT);
0201 
0202     return count;
0203 }
0204 
0205 static DEVICE_ATTR_RW(target);
0206 
0207 static struct attribute *balloon_attrs[] = {
0208     &dev_attr_target_kb.attr,
0209     &dev_attr_target.attr,
0210     &dev_attr_schedule_delay.attr.attr,
0211     &dev_attr_max_schedule_delay.attr.attr,
0212     &dev_attr_retry_count.attr.attr,
0213     &dev_attr_max_retry_count.attr.attr,
0214     &dev_attr_scrub_pages.attr.attr,
0215     NULL
0216 };
0217 
0218 static const struct attribute_group balloon_group = {
0219     .attrs = balloon_attrs
0220 };
0221 
0222 static struct attribute *balloon_info_attrs[] = {
0223     &dev_attr_current_kb.attr,
0224     &dev_attr_low_kb.attr,
0225     &dev_attr_high_kb.attr,
0226     NULL
0227 };
0228 
0229 static const struct attribute_group balloon_info_group = {
0230     .name = "info",
0231     .attrs = balloon_info_attrs
0232 };
0233 
0234 static const struct attribute_group *balloon_groups[] = {
0235     &balloon_group,
0236     &balloon_info_group,
0237     NULL
0238 };
0239 
0240 static struct bus_type balloon_subsys = {
0241     .name = BALLOON_CLASS_NAME,
0242     .dev_name = BALLOON_CLASS_NAME,
0243 };
0244 
0245 static int register_balloon(struct device *dev)
0246 {
0247     int error;
0248 
0249     error = subsys_system_register(&balloon_subsys, NULL);
0250     if (error)
0251         return error;
0252 
0253     dev->id = 0;
0254     dev->bus = &balloon_subsys;
0255     dev->groups = balloon_groups;
0256 
0257     error = device_register(dev);
0258     if (error) {
0259         bus_unregister(&balloon_subsys);
0260         return error;
0261     }
0262 
0263     return 0;
0264 }