diff options
Diffstat (limited to 'xenolinux-2.4.21-pre4-sparse/arch')
5 files changed, 316 insertions, 1 deletions
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/Makefile b/xenolinux-2.4.21-pre4-sparse/arch/xeno/Makefile index 544af84605..557fe98217 100644 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/Makefile +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/Makefile @@ -47,12 +47,14 @@ HEAD := arch/xeno/kernel/head.o arch/xeno/kernel/init_task.o SUBDIRS += arch/xeno/kernel arch/xeno/mm arch/xeno/lib SUBDIRS += arch/xeno/drivers/console arch/xeno/drivers/network SUBDIRS += arch/xeno/drivers/dom0 arch/xeno/drivers/block +SUBDIRS += arch/xeno/drivers/balloon CORE_FILES += arch/xeno/kernel/kernel.o arch/xeno/mm/mm.o CORE_FILES += arch/xeno/drivers/console/con.o CORE_FILES += arch/xeno/drivers/block/blk.o CORE_FILES += arch/xeno/drivers/network/net.o CORE_FILES += arch/xeno/drivers/dom0/dom0.o +CORE_FILES += arch/xeno/drivers/balloon/balloon_driver.o LIBS := $(TOPDIR)/arch/xeno/lib/lib.a $(LIBS) $(TOPDIR)/arch/xeno/lib/lib.a arch/xeno/kernel: dummy @@ -73,6 +75,9 @@ arch/xeno/drivers/block: dummy arch/xeno/drivers/dom0: dummy $(MAKE) linuxsubdirs SUBDIRS=arch/xeno/drivers/dom0 +arch/xeno/drivers/balloon: dummy + $(MAKE) linuxsubdirs SUBDIRS=arch/xeno/drivers/balloon + MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot vmlinux: arch/xeno/vmlinux.lds diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/Makefile b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/Makefile new file mode 100644 index 0000000000..f780a515e0 --- /dev/null +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/Makefile @@ -0,0 +1,3 @@ +O_TARGET := balloon_driver.o +obj-y := balloon.o +include $(TOPDIR)/Rules.make diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/balloon.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/balloon.c new file mode 100644 index 0000000000..abe5884800 --- /dev/null +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/balloon.c @@ -0,0 +1,275 @@ +/****************************************************************************** + * balloon.c + * + * Xeno balloon driver - enables returning/claiming memory to/from xen + * + * Copyright (c) 2003, B Dragovic + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/proc_fs.h> + +#include <linux/mm.h> +#include <linux/mman.h> +#include <linux/smp_lock.h> +#include <linux/pagemap.h> + +#include <asm/hypervisor.h> +#include <asm/pgalloc.h> +#include <asm/pgtable.h> +#include <asm/uaccess.h> +#include <asm/tlb.h> + +#include "dom_mem_ops.h" + +/* USER DEFINES -- THESE SHOULD BE COPIED TO USER-SPACE TOOLS */ +#define USER_INFLATE_BALLOON 1 /* return mem to hypervisor */ +#define USER_DEFLATE_BALLOON 2 /* claim mem from hypervisor */ +typedef struct user_balloon_op { + unsigned int op; + unsigned long size; +} user_balloon_op_t; +/* END OF USER DEFINE */ + +/* Dead entry written into ballon-owned entries in the PMT. */ +#define DEAD 0xdeadbeef + +#define BALLOON_ENTRY "balloon" +extern struct proc_dir_entry *xeno_base; + +static struct proc_dir_entry *balloon_pde; +unsigned long credit; + +static inline unsigned long get_ppte(unsigned long addr) +{ + unsigned long ppte; + pgd_t *pgd; pmd_t *pmd; pte_t *ptep; + pgd = pgd_offset_k(addr); + + if ( pgd_none(*pgd) || pgd_bad(*pgd) ) BUG(); + + pmd = pmd_offset(pgd, addr); + if ( pmd_none(*pmd) || pmd_bad(*pmd) ) BUG(); + + ptep = pte_offset(pmd, addr); + ppte = (unsigned long)__pa(ptep); + + return ppte; +} + +/* main function for relinquishing bit of memory */ +static unsigned long inflate_balloon(unsigned long num_pages) +{ + dom_mem_op_t dom_mem_op; + unsigned long *parray; + unsigned long *currp; + unsigned long ret = 0; + unsigned long vaddr; + unsigned long i, j; + + parray = (unsigned long *)kmalloc(num_pages * + sizeof(unsigned long), GFP_KERNEL); + currp = parray; + + for ( i = 0; i < num_pages; i++ ) + { + /* try to obtain a free page, has to be done with GFP_ATOMIC + * as we do not want to sleep indefinately. + */ + vaddr = __get_free_page(GFP_ATOMIC); + + /* if allocation fails, free all reserved pages */ + if(!vaddr){ + printk("Unable to inflate balloon by %ld, only %ld pages free.", + num_pages, i); + currp = parray; + for(j = 0; j < i; j++){ + free_page(*currp++); + } + goto cleanup; + } + + *currp++ = vaddr; + } + + + currp = parray; + for ( i = 0; i < num_pages; i++ ) + { + queue_l1_entry_update(get_ppte(*currp) | PGREQ_NORMAL, 0); + phys_to_machine_mapping[__pa(*currp) >> PAGE_SHIFT] = DEAD; + currp++; + } + + XENO_flush_page_update_queue(); + + dom_mem_op.op = BALLOON_INFLATE_OP; + dom_mem_op.u.balloon_inflate.size = num_pages; + dom_mem_op.u.balloon_inflate.pages = parray; + if ( (ret = HYPERVISOR_dom_mem_op(&dom_mem_op)) != num_pages ) + { + printk("Unable to deflate balloon, error %lx\n", ret); + goto cleanup; + } + + credit += num_pages; + ret = num_pages; + + cleanup: + kfree(parray); + + return ret; +} + +/* install new mem pages obtained by deflate_balloon. function walks + * phys->machine mapping table looking for DEAD entries and populates + * them. + */ +static unsigned long process_new_pages(unsigned long * parray, + unsigned long num) +{ + /* currently, this function is rather simplistic as + * it is assumed that domain reclaims only number of + * pages previously released. this is to change soon + * and the code to extend page tables etc. will be + * incorporated here. + */ + + unsigned long tot_pages = start_info.nr_pages; + unsigned long * curr = parray; + unsigned long num_installed; + unsigned long i; + + num_installed = 0; + for ( i = 0; i < tot_pages; i++ ) + { + if ( phys_to_machine_mapping[i] == DEAD ) + { + phys_to_machine_mapping[i] = *curr; + queue_l1_entry_update((i << PAGE_SHIFT) | PGREQ_MPT_UPDATE, i); + queue_l1_entry_update( + get_ppte((unsigned long)__va(i << PAGE_SHIFT)) | PGREQ_NORMAL, + ((*curr) << PAGE_SHIFT) | L1_PROT); + + *curr = (unsigned long)__va(i << PAGE_SHIFT); + curr++; + num_installed++; + } + } + + /* now, this is tricky (and will also change for machine addrs that + * are mapped to not previously released addresses). we free pages + * that were allocated by get_free_page (the mappings are different + * now, of course). + */ + curr = parray; + for ( i = 0; i < num_installed; i++ ) + { + free_page(*curr); + curr++; + } + + return num_installed; +} + +static unsigned long deflate_balloon(unsigned long num_pages) +{ + dom_mem_op_t dom_mem_op; + unsigned long ret; + unsigned long * parray; + + if ( num_pages > credit ) + { + printk("Can not allocate more pages than previously released.\n"); + return -EAGAIN; + } + + parray = (unsigned long *)kmalloc(num_pages * sizeof(unsigned long), + GFP_KERNEL); + + dom_mem_op.op = BALLOON_DEFLATE_OP; + dom_mem_op.u.balloon_deflate.size = num_pages; + dom_mem_op.u.balloon_deflate.pages = parray; + if((ret = HYPERVISOR_dom_mem_op(&dom_mem_op)) != num_pages){ + printk("Unable to deflate balloon, error %lx\n", ret); + goto cleanup; + } + + if((ret = process_new_pages(parray, num_pages)) < num_pages){ + printk("Unable to deflate balloon by specified %lx pages, only %lx.\n", + num_pages, ret); + goto cleanup; + } + + ret = num_pages; + + cleanup: + kfree(parray); + + return ret; +} + +static int balloon_write(struct file *file, const char *buffer, + u_long count, void *data) +{ + user_balloon_op_t bop; + + /* Only admin can play with the balloon :) */ + if ( !capable(CAP_SYS_ADMIN) ) + return -EPERM; + + if ( copy_from_user(&bop, buffer, sizeof(bop)) ) + return -EFAULT; + + switch ( bop.op ) + { + case USER_INFLATE_BALLOON: + if ( inflate_balloon(bop.size) < bop.size ) + return -EAGAIN; + break; + + case USER_DEFLATE_BALLOON: + deflate_balloon(bop.size); + break; + + default: + printk("Unknown command to balloon driver."); + return -EFAULT; + } + + return sizeof(bop); +} + +/* + * main balloon driver initialization function. + */ +static int __init init_module(void) +{ + printk(KERN_ALERT "Starting Xeno Balloon driver\n"); + + credit = 0; + + balloon_pde = create_proc_entry(BALLOON_ENTRY, 0600, xeno_base); + if ( balloon_pde == NULL ) + { + printk(KERN_ALERT "Unable to create balloon driver proc entry!"); + return -1; + } + + balloon_pde->write_proc = balloon_write; + + return 0; +} + +static void __exit cleanup_module(void) +{ +} + +module_init(init_module); +module_exit(cleanup_module); + + diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/dom_mem_ops.h b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/dom_mem_ops.h new file mode 100644 index 0000000000..c473f193e7 --- /dev/null +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/dom_mem_ops.h @@ -0,0 +1,32 @@ +/****************************************************************************** + * dom_mem_ops.h + * + * Header file supporting domain related memory operations. N.B. keep in sync + * with xen version. + * + * Copyright (c) 2003, B Dragovic + */ + +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED) +#define BALLOON_DEFLATE_OP 0 +#define BALLOON_INFLATE_OP 1 + +typedef struct balloon_deflate_op { + unsigned long size; + unsigned long * pages; +} balloon_def_op_t; + +typedef struct balloon_inflate_op { + unsigned long size; + unsigned long * pages; +} balloon_inf_op_t; + +typedef struct dom_mem_ops +{ + unsigned int op; + union + { + balloon_def_op_t balloon_deflate; + balloon_inf_op_t balloon_inflate; + }u; +} dom_mem_op_t; diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/dom0/dom0_core.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/dom0/dom0_core.c index f8af85358b..c36ab02e96 100644 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/dom0/dom0_core.c +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/dom0/dom0_core.c @@ -53,7 +53,7 @@ typedef struct proc_mem_data { #define MAP_DISCONT 1 -static struct proc_dir_entry *xeno_base; +struct proc_dir_entry *xeno_base; static struct proc_dir_entry *dom0_cmd_intf; static struct proc_dir_entry *proc_ft; |