/* * \brief Balloon driver to use Genode's dynamic memory balancing * \author Stefan Kalkowski * \date 2013-09-19 */ /* * Copyright (C) 2013 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ /* Linux includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define GFP_BALLOON \ (__GFP_IO | __GFP_FS | __GFP_HARDWALL | __GFP_HIGHMEM | __GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC) enum { CHUNK_CACHE_SIZE = 16384 }; static void* chunk_cache[CHUNK_CACHE_SIZE]; static void free_avail_pages(unsigned long data) { void *pages; unsigned i = 0; LOG_printf("free_avail_pages\n"); for (; i < CHUNK_CACHE_SIZE; i++) { pages = alloc_pages_exact(SZ_1M, GFP_BALLOON); if (!pages) break; chunk_cache[i] = pages; } BUG_ON(i == CHUNK_CACHE_SIZE); /* Ensure that ballooned highmem pages don't have kmaps. */ kmap_flush_unused(); flush_tlb_all(); for (; i > 0;) { genode_balloon_free_chunk((unsigned long)chunk_cache[--i]); free_pages_exact(chunk_cache[i], SZ_1M); } LOG_printf("free_avail_pages done\n"); genode_balloon_free_done(); } DECLARE_TASKLET(free_avail, free_avail_pages, 0); static irqreturn_t event_interrupt(int irq, void *data) { tasklet_schedule(&free_avail); return IRQ_HANDLED; } static struct platform_device genode_balloon_device = { .name = "balloon-genode", }; static int __init balloon_init(void) { int ret = 0; unsigned irq; l4_cap_idx_t irq_cap; /* * touch the memory eager otherwise we run into trouble * when memory is empty and we balloon */ memset(&chunk_cache, 0, sizeof(chunk_cache)); /** * Obtain an IRQ for the device. */ irq_cap = genode_balloon_irq_cap(); if ((irq = l4x_register_irq(irq_cap)) < 0) return -ENOMEM; if ((ret = request_irq(irq, event_interrupt, 0, "Genode balloon", &genode_balloon_device))) { printk(KERN_WARNING "%s: request_irq failed: %d\n", __func__, ret); return ret; } ret = platform_device_register(&genode_balloon_device); return ret; } subsys_initcall(balloon_init); MODULE_LICENSE("GPL");