MODULE_AUTHOR("Brian King ");
MODULE_DESCRIPTION("IBM System p Collaborative Memory Manager");
MODULE_LICENSE("GPL");
MODULE_VERSION(CMM_DRIVER_VERSION);
module_param_named(delay, delay, uint, 0644);
MODULE_PARM_DESC(delay, "Delay (in seconds) between polls to query hypervisor paging requests. " "[Default=" __stringify(CMM_DEFAULT_DELAY) "]");
module_param_named(hotplug_delay, hotplug_delay, uint, 0644);
MODULE_PARM_DESC(hotplug_delay, "Delay (in seconds) after memory hotplug remove " "before loaning resumes. " "[Default=" __stringify(CMM_HOTPLUG_DELAY) "]");
module_param_named(oom_kb, oom_kb, uint, 0644);
MODULE_PARM_DESC(oom_kb, "Amount of memory in kb to free on OOM. " "[Default=" __stringify(CMM_OOM_KB) "]");
module_param_named(min_mem_mb, min_mem_mb, ulong, 0644);
MODULE_PARM_DESC(min_mem_mb, "Minimum amount of memory (in MB) to not balloon. " "[Default=" __stringify(CMM_MIN_MEM_MB) "]");
module_param_named(debug, cmm_debug, uint, 0644);
MODULE_PARM_DESC(debug, "Enable module debugging logging. Set to 1 to enable. " "[Default=" __stringify(CMM_DEBUG) "]");
module_param_named(simulate, simulate, bool, 0444);
MODULE_PARM_DESC(simulate, "Enable simulation mode (no communication with hw).");
#define cmm_dbg(...) if (cmm_debug) { printk(KERN_INFO "cmm: "__VA_ARGS__); }
staticlong plpar_page_set_loaned(struct page *page)
{ constunsignedlong vpa = page_to_phys(page); unsignedlong cmo_page_sz = cmo_get_page_size(); long rc = 0; int i;
if (unlikely(simulate)) return 0;
for (i = 0; !rc && i < PAGE_SIZE; i += cmo_page_sz)
rc = plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED, vpa + i, 0);
for (i -= cmo_page_sz; rc && i != 0; i -= cmo_page_sz)
plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE,
vpa + i - cmo_page_sz, 0);
return rc;
}
staticlong plpar_page_set_active(struct page *page)
{ constunsignedlong vpa = page_to_phys(page); unsignedlong cmo_page_sz = cmo_get_page_size(); long rc = 0; int i;
if (unlikely(simulate)) return 0;
for (i = 0; !rc && i < PAGE_SIZE; i += cmo_page_sz)
rc = plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE, vpa + i, 0);
for (i -= cmo_page_sz; rc && i != 0; i -= cmo_page_sz)
plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED,
vpa + i - cmo_page_sz, 0);
return rc;
}
/** * cmm_alloc_pages - Allocate pages and mark them as loaned * @nr: number of pages to allocate * * Return value: * number of pages requested to be allocated which were not
**/ staticlong cmm_alloc_pages(long nr)
{ struct page *page; long rc;
cmm_dbg("Begin request for %ld pages\n", nr);
while (nr) { /* Exit if a hotplug operation is in progress or occurred */ if (mutex_trylock(&hotplug_mutex)) { if (hotplug_occurred) {
mutex_unlock(&hotplug_mutex); break;
}
mutex_unlock(&hotplug_mutex);
} else { break;
}
page = balloon_page_alloc(); if (!page) break;
rc = plpar_page_set_loaned(page); if (rc) {
pr_err("%s: Can not set page to loaned. rc=%ld\n", __func__, rc);
__free_page(page); break;
}
cmm_dbg("End request with %ld pages unfulfilled\n", nr); return nr;
}
/** * cmm_free_pages - Free pages and mark them as active * @nr: number of pages to free * * Return value: * number of pages requested to be freed which were not
**/ staticlong cmm_free_pages(long nr)
{ struct page *page;
cmm_dbg("Begin free of %ld pages.\n", nr); while (nr) {
page = balloon_page_dequeue(&b_dev_info); if (!page) break;
plpar_page_set_active(page);
adjust_managed_page_count(page, 1);
__free_page(page);
atomic_long_dec(&loaned_pages);
nr--;
}
cmm_dbg("End request with %ld pages unfulfilled\n", nr); return nr;
}
/** * cmm_oom_notify - OOM notifier * @self: notifier block struct * @dummy: not used * @parm: returned - number of pages freed * * Return value: * NOTIFY_OK
**/ staticint cmm_oom_notify(struct notifier_block *self, unsignedlong dummy, void *parm)
{ unsignedlong *freed = parm; long nr = KB2PAGES(oom_kb);
/** * cmm_sysfs_register - Register with sysfs * * Return value: * 0 on success / other on failure
**/ staticint cmm_sysfs_register(struct device *dev)
{ int i, rc;
if ((rc = subsys_system_register(&cmm_subsys, NULL))) return rc;
/* * loan/"inflate" the newpage first. * * We might race against the cmm_thread who might discover after our * loan request that another page is to be unloaned. However, once * the cmm_thread runs again later, this error will automatically * be corrected.
*/ if (plpar_page_set_loaned(newpage)) { /* Unlikely, but possible. Tell the caller not to retry now. */
pr_err_ratelimited("%s: Cannot set page to loaned.", __func__); return -EBUSY;
}
/* balloon page list reference */
get_page(newpage);
/* * When we migrate a page to a different zone, we have to fixup the * count of both involved zones as we adjusted the managed page count * when inflating.
*/ if (page_zone(page) != page_zone(newpage)) {
adjust_managed_page_count(page, 1);
adjust_managed_page_count(newpage, -1);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.