mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
bitkeeper revision 1.107 (3e665ab0XNZynD-498WHLN1g1IPRrw)
Merge labyrinth.cl.cam.ac.uk:/usr/groups/xeno/BK/xeno.bk into labyrinth.cl.cam.ac.uk:/anfs/scratch/boulderdash/ach61/xeno/xeno.bk
This commit is contained in:
commit
f3c8dfc627
24 files changed
+890
-71
No files matched your search
@@ -176,6 +176,9 @@
|
||||
3e15d52e0_j129JPvo7xfYGndVFpwQ old/xenolinux-2.4.16-sparse/mm/memory.c
|
||||
3e15d535DLvpzTrLRUIerB69LpJD1g old/xenolinux-2.4.16-sparse/mm/mremap.c
|
||||
3e15d531m1Y1_W8ki64AFOU_ua4C4w old/xenolinux-2.4.16-sparse/mm/swapfile.c
|
||||
3e6377b24eQqYMsDi9XrFkIgTzZ47A tools/balloon/Makefile
|
||||
3e6377d6eiFjF1hHIS6JEIOFk62xSA tools/balloon/README
|
||||
3e6377dbGcgnisKw16DPCaND7oGO3Q tools/balloon/balloon.c
|
||||
3e4d00468-FN2VDeEHo96zxrMHK_mA tools/domain_builder/Makefile
|
||||
3e4d0046SPau_y0sw2WLJz8QkqNoRA tools/domain_builder/README
|
||||
3e4d0046bbdH0GsI9J_1Eb4ZQHfIiQ tools/domain_builder/dom0_defs.h
|
||||
@@ -226,6 +229,7 @@
|
||||
3ddb79bddEYJbcURvqqcx99Yl2iAhQ xen/common/block.c
|
||||
3ddb79bdrqnW93GR9gZk1OJe1qK-iQ xen/common/brlock.c
|
||||
3ddb79bdLX_P6iB7ILiblRLWvebapg xen/common/dom0_ops.c
|
||||
3e6377e4i0c9GtKN65e99OtRbw3AZw xen/common/dom_mem_ops.c
|
||||
3ddb79bdYO5D8Av12NHqPeSviav7cg xen/common/domain.c
|
||||
3e32af9aRnYGl4GMOaDKp7JdfhOGhg xen/common/domain_page.c
|
||||
3ddb79bdeyutmaXEfpQvvxj7eQ0fCw xen/common/event.c
|
||||
@@ -400,6 +404,7 @@
|
||||
3ddb79c1V44RD26YqCUm-kqIupM37A xen/include/xeno/ctype.h
|
||||
3ddb79c05DdHQ0UxX_jKsXdR4QlMCA xen/include/xeno/delay.h
|
||||
3ddb79c2PMeWTK86y4C3F4MzHw4A1g xen/include/xeno/dom0_ops.h
|
||||
3e6377eaioRoNm0m_HSDEAd4Vqrq_w xen/include/xeno/dom_mem_ops.h
|
||||
3ddb79c1uaWQZj551j1O0B5z8AnHOg xen/include/xeno/elevator.h
|
||||
3ddb79c0HIghfBF8zFUdmXhOU8i6hA xen/include/xeno/errno.h
|
||||
3ddb79c0rMjudDKkJku_mkm0J-BZgw xen/include/xeno/etherdevice.h
|
||||
@@ -465,6 +470,9 @@
|
||||
3e5a4e65n-KhsEAs-A4ULiStBp-r6w xenolinux-2.4.21-pre4-sparse/arch/xeno/boot/Makefile
|
||||
3e5a4e65OV_j_DBtjzt5vej771AJsA xenolinux-2.4.21-pre4-sparse/arch/xeno/config.in
|
||||
3e5a4e65TNEycLeXqPSXQJQm_xGecA xenolinux-2.4.21-pre4-sparse/arch/xeno/defconfig
|
||||
3e6377f5xwPfYZkPHPrDbEq1PRN7uQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/Makefile
|
||||
3e6377f8Me8IqtvEhb70XFgOvqQH7A xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/balloon.c
|
||||
3e6377fbMjXWAQd0XN0FWv4fDEo6fg xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/dom_mem_ops.h
|
||||
3e5a4e65iHEuC5sjFhj42XALYbLVRw xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile
|
||||
3e5a4e65pP5spJErBW69pJxSSdK9RA xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c
|
||||
3e5a4e65GtI9JZRAjuRdXaxt_4ohyQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c
|
||||
|
||||
@@ -22,3 +22,134 @@ xenolinux-2.4.16-sparse/scripts/kconfig.tk
|
||||
xen-2.4.16/foo
|
||||
xen-2.4.16/common/domain.c.smh
|
||||
URK
|
||||
tools/domain_builder/dom_builder.o
|
||||
tools/domain_builder/dom_kill.o
|
||||
tools/domain_builder/domain_builder
|
||||
tools/domain_builder/kill_domain
|
||||
xen/arch/i386/acpitable.o
|
||||
xen/arch/i386/apic.o
|
||||
xen/arch/i386/arch.o
|
||||
xen/arch/i386/boot/boot.o
|
||||
xen/arch/i386/delay.o
|
||||
xen/arch/i386/entry.o
|
||||
xen/arch/i386/extable.o
|
||||
xen/arch/i386/i387.o
|
||||
xen/arch/i386/i8259.o
|
||||
xen/arch/i386/idle0_task.o
|
||||
xen/arch/i386/io_apic.o
|
||||
xen/arch/i386/ioremap.o
|
||||
xen/arch/i386/irq.o
|
||||
xen/arch/i386/mm.o
|
||||
xen/arch/i386/mpparse.o
|
||||
xen/arch/i386/pci-dma.o
|
||||
xen/arch/i386/pci-i386.o
|
||||
xen/arch/i386/pci-irq.o
|
||||
xen/arch/i386/pci-pc.o
|
||||
xen/arch/i386/process.o
|
||||
xen/arch/i386/rwlock.o
|
||||
xen/arch/i386/setup.o
|
||||
xen/arch/i386/smp.o
|
||||
xen/arch/i386/smpboot.o
|
||||
xen/arch/i386/time.o
|
||||
xen/arch/i386/trampoline.o
|
||||
xen/arch/i386/traps.o
|
||||
xen/arch/i386/usercopy.o
|
||||
xen/common/ac_timer.o
|
||||
xen/common/block.o
|
||||
xen/common/brlock.o
|
||||
xen/common/common.o
|
||||
xen/common/dom0_ops.o
|
||||
xen/common/domain.o
|
||||
xen/common/domain_page.o
|
||||
xen/common/event.o
|
||||
xen/common/kernel.o
|
||||
xen/common/keyhandler.o
|
||||
xen/common/lib.o
|
||||
xen/common/memory.o
|
||||
xen/common/network.o
|
||||
xen/common/page_alloc.o
|
||||
xen/common/perfc.o
|
||||
xen/common/resource.o
|
||||
xen/common/schedule.o
|
||||
xen/common/slab.o
|
||||
xen/common/softirq.o
|
||||
xen/common/timer.o
|
||||
xen/common/vsprintf.o
|
||||
xen/drivers/block/blkpg.o
|
||||
xen/drivers/block/driver.o
|
||||
xen/drivers/block/elevator.o
|
||||
xen/drivers/block/genhd.o
|
||||
xen/drivers/block/ll_rw_blk.o
|
||||
xen/drivers/block/xen_block.o
|
||||
xen/drivers/char/driver.o
|
||||
xen/drivers/char/xen_kbd.o
|
||||
xen/drivers/char/xen_serial.o
|
||||
xen/drivers/ide/driver.o
|
||||
xen/drivers/ide/ide-disk.o
|
||||
xen/drivers/ide/ide-dma.o
|
||||
xen/drivers/ide/ide-features.o
|
||||
xen/drivers/ide/ide-geometry.o
|
||||
xen/drivers/ide/ide-pci.o
|
||||
xen/drivers/ide/ide-probe.o
|
||||
xen/drivers/ide/ide-taskfile.o
|
||||
xen/drivers/ide/ide-xeno.o
|
||||
xen/drivers/ide/ide.o
|
||||
xen/drivers/ide/piix.o
|
||||
xen/drivers/net/3c59x.o
|
||||
xen/drivers/net/Space.o
|
||||
xen/drivers/net/driver.o
|
||||
xen/drivers/net/e1000/e1000.o
|
||||
xen/drivers/net/e1000/e1000_ethtool.o
|
||||
xen/drivers/net/e1000/e1000_hw.o
|
||||
xen/drivers/net/e1000/e1000_main.o
|
||||
xen/drivers/net/e1000/e1000_param.o
|
||||
xen/drivers/net/ne/8390.o
|
||||
xen/drivers/net/ne/ne.o
|
||||
xen/drivers/net/ne/ne_drv.o
|
||||
xen/drivers/net/net_init.o
|
||||
xen/drivers/net/setup.o
|
||||
xen/drivers/net/tg3.o
|
||||
xen/drivers/pci/classlist.h
|
||||
xen/drivers/pci/compat.o
|
||||
xen/drivers/pci/devlist.h
|
||||
xen/drivers/pci/driver.o
|
||||
xen/drivers/pci/gen-devlist
|
||||
xen/drivers/pci/names.o
|
||||
xen/drivers/pci/pci.o
|
||||
xen/drivers/pci/quirks.o
|
||||
xen/drivers/pci/setup-res.o
|
||||
xen/drivers/scsi/aacraid/aachba.o
|
||||
xen/drivers/scsi/aacraid/aacraid.o
|
||||
xen/drivers/scsi/aacraid/commctrl.o
|
||||
xen/drivers/scsi/aacraid/comminit.o
|
||||
xen/drivers/scsi/aacraid/commsup.o
|
||||
xen/drivers/scsi/aacraid/dpcsup.o
|
||||
xen/drivers/scsi/aacraid/linit.o
|
||||
xen/drivers/scsi/aacraid/rx.o
|
||||
xen/drivers/scsi/aacraid/sa.o
|
||||
xen/drivers/scsi/constants.o
|
||||
xen/drivers/scsi/driver.o
|
||||
xen/drivers/scsi/hosts.o
|
||||
xen/drivers/scsi/scsi.o
|
||||
xen/drivers/scsi/scsi_dma.o
|
||||
xen/drivers/scsi/scsi_error.o
|
||||
xen/drivers/scsi/scsi_ioctl.o
|
||||
xen/drivers/scsi/scsi_lib.o
|
||||
xen/drivers/scsi/scsi_merge.o
|
||||
xen/drivers/scsi/scsi_proc.o
|
||||
xen/drivers/scsi/scsi_queue.o
|
||||
xen/drivers/scsi/scsi_scan.o
|
||||
xen/drivers/scsi/scsi_syms.o
|
||||
xen/drivers/scsi/scsicam.o
|
||||
xen/drivers/scsi/sd.o
|
||||
xen/image
|
||||
xen/image.gz
|
||||
xen/include/asm
|
||||
xen/include/linux
|
||||
xen/net/dev.o
|
||||
xen/net/dev_mcast.o
|
||||
xen/net/devinit.o
|
||||
xen/net/eth.o
|
||||
xen/net/network.o
|
||||
xen/net/skbuff.o
|
||||
xen/tools/elf-reloc
|
||||
@@ -0,0 +1,9 @@
|
||||
CC = gcc
|
||||
TARGET=balloon
|
||||
|
||||
TARGET: balloon.c
|
||||
$(CC) -O2 -Wall -o $(TARGET) balloon.c
|
||||
|
||||
clean:
|
||||
$(RM) *.o $(TARGET) *~
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
Xeno Balloon driver supports two operations:
|
||||
|
||||
1. Inflating - which means domain giving up pages of mem to xen.
|
||||
2. Deflating - which means reclaiming memory pages from xen.
|
||||
|
||||
Currently, domain can only claim pages from xen up to the number of
|
||||
previously released ones. This is to change.
|
||||
|
||||
Example:
|
||||
|
||||
# balloon inflate 1000
|
||||
|
||||
Give up 1000 pages to xen.
|
||||
|
||||
# balloon deflate 1000
|
||||
|
||||
Claim 1000 pages from xen.
|
||||
@@ -0,0 +1,114 @@
|
||||
/******************************************************************************
|
||||
* balloon.c
|
||||
*
|
||||
* Xeno balloon driver userspace control tool. Used to shrink/grow domain's
|
||||
* memory.
|
||||
*
|
||||
* Copyright (c) 2003, B Dragovic
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define INFLATE_BALLOON "inflate" /* return mem to hypervisor */
|
||||
#define DEFLATE_BALLOON "deflate" /* claim mem from hypervisor */
|
||||
|
||||
/* THIS IS TAKEN FROM XENOLINUX BALLOON DRIVER */
|
||||
#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 CODE TAKEN FROM XENOLINUX BALLOON DRIVER */
|
||||
|
||||
|
||||
static int open_balloon_proc()
|
||||
{
|
||||
return open("/proc/xeno/balloon", O_RDWR);
|
||||
}
|
||||
|
||||
/* inflate balloon function signals to kernel it should relinquish memory */
|
||||
static int inflate_balloon(unsigned long num_pages)
|
||||
{
|
||||
user_balloon_op_t bop;
|
||||
int proc_fd;
|
||||
|
||||
if((proc_fd = open_balloon_proc()) <= 0){
|
||||
printf("Error opening balloon proc file.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bop.op = USER_INFLATE_BALLOON;
|
||||
bop.size = num_pages;
|
||||
if ( write(proc_fd, &bop, sizeof(bop)) <= 0 )
|
||||
{
|
||||
printf("Error writing to balloon proc file.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
close(proc_fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* deflate balloon function signals to kernel it should claim memory */
|
||||
static int deflate_balloon(unsigned long num_pages)
|
||||
{
|
||||
user_balloon_op_t bop;
|
||||
int proc_fd;
|
||||
|
||||
if((proc_fd = open_balloon_proc()) <= 0){
|
||||
printf("Error opening balloon proc file.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bop.op = USER_DEFLATE_BALLOON;
|
||||
bop.size = num_pages;
|
||||
if(write(proc_fd, &bop, sizeof(bop)) <= 0){
|
||||
printf("Error writing to balloon proc file.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
close(proc_fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned long num_pages;
|
||||
|
||||
if(argc < 2){
|
||||
printf("Usage: balloon <inflate|deflate> <num_pages>\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
num_pages = atol(argv[2]);
|
||||
|
||||
if(!strcmp(argv[1], INFLATE_BALLOON)){
|
||||
if(!inflate_balloon(num_pages)){
|
||||
perror("Inflating balloon failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else if (!strcmp(argv[1], DEFLATE_BALLOON)){
|
||||
if(!deflate_balloon(num_pages)){
|
||||
perror("Deflating balloon failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
printf("Unrecognized command line argument.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -52,10 +52,10 @@ static void dom_mem_cleanup(dom_mem_t * dom_mem)
|
||||
if(mem_fd < 0){
|
||||
perror(PERR_STRING);
|
||||
}
|
||||
|
||||
if(write(mem_fd, (dom_mem_t *)dom_mem, sizeof(dom_mem_t)) < 0){
|
||||
dbstatus("Error unmapping domain's memory.\n");
|
||||
}
|
||||
|
||||
if(write(mem_fd, (dom_mem_t *)dom_mem, sizeof(dom_mem_t)) < 0){
|
||||
dbstatus("Error unmapping domain's memory.\n");
|
||||
}
|
||||
|
||||
close(mem_fd);
|
||||
}
|
||||
@@ -163,7 +163,7 @@ static dom0_newdomain_t * create_new_domain(long req_mem)
|
||||
close(id_fd);
|
||||
|
||||
sprintf(cmd_path, "Reserved %ld kbytes memory and assigned id %d to the"
|
||||
"new domain.", req_mem, dom_data->domain);
|
||||
" new domain.", req_mem, dom_data->domain);
|
||||
dbstatus(cmd_path);
|
||||
|
||||
return dom_data;
|
||||
@@ -386,6 +386,7 @@ static int launch_domain(dom_meminfo_t * meminfo)
|
||||
dbstatus("Launched the new domain!");
|
||||
|
||||
close(cmd_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
@@ -401,51 +402,45 @@ int main(int argc, char **argv)
|
||||
int kernel_fd;
|
||||
int count;
|
||||
int cmd_len;
|
||||
int ret = 0;
|
||||
int rc = -1;
|
||||
|
||||
unsigned long addr;
|
||||
unsigned long addr;
|
||||
|
||||
if(argc < 4){
|
||||
if(argc < 4) {
|
||||
dberr("Usage: dom_builder <kbytes_mem> <image> <num_vifs> "
|
||||
"<boot_params>\n");
|
||||
ret = -1;
|
||||
"<boot_params>\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* create new domain and set up all the neccessary mappings */
|
||||
|
||||
kernel_fd = do_kernel_chcks(argv[2], atol(argv[1]), &load_addr, &ksize);
|
||||
if(kernel_fd < 0){
|
||||
ret = -1;
|
||||
if(kernel_fd < 0) {
|
||||
rc = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
/* request the creation of new domain */
|
||||
dom_data = create_new_domain(atol(argv[1]));
|
||||
if(dom_data == 0){
|
||||
ret = -1;
|
||||
if(!(dom_data = create_new_domain(atol(argv[1]))))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* map domain's memory */
|
||||
if(map_dom_mem(dom_data->pg_head, dom_data->memory_kb >> (PAGE_SHIFT - 10),
|
||||
dom_data->domain, &dom_os_image)){
|
||||
ret = -1;
|
||||
if(map_dom_mem(dom_data->pg_head, dom_data->memory_kb >> (PAGE_SHIFT-10),
|
||||
dom_data->domain, &dom_os_image))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* the following code does the actual domain building */
|
||||
meminfo = setup_guestos(dom_data->domain, kernel_fd, load_addr, ksize,
|
||||
&dom_os_image);
|
||||
if(meminfo == NULL){
|
||||
printf("Domain Builder: debug: meminfo NULL\n");
|
||||
ret = -1;
|
||||
dom_mem_cleanup(&dom_os_image);
|
||||
meminfo = setup_guestos(dom_data->domain, kernel_fd, load_addr,
|
||||
ksize, &dom_os_image);
|
||||
|
||||
/* and unmap the new domain's memory image since we no longer need it */
|
||||
dom_mem_cleanup(&dom_os_image);
|
||||
|
||||
if(!meminfo) {
|
||||
printf("Domain Builder: debug: meminfo NULL\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
dom_mem_cleanup(&dom_os_image);
|
||||
|
||||
meminfo->virt_load_addr = load_addr;
|
||||
meminfo->num_vifs = atoi(argv[3]);
|
||||
meminfo->cmd_line[0] = '\0';
|
||||
@@ -471,13 +466,11 @@ int main(int argc, char **argv)
|
||||
dbstatus(status);
|
||||
|
||||
/* and launch the domain */
|
||||
if(launch_domain(meminfo) != 0)
|
||||
ret = -1;
|
||||
|
||||
rc = launch_domain(meminfo);
|
||||
|
||||
out:
|
||||
if( ret >= 0 )
|
||||
if( rc >= 0 )
|
||||
return meminfo->domain;
|
||||
else
|
||||
return ret;
|
||||
return rc;
|
||||
}
|
||||
@@ -529,6 +529,7 @@ ENTRY(hypervisor_call_table)
|
||||
.long SYMBOL_NAME(do_get_debugreg)
|
||||
.long SYMBOL_NAME(do_update_descriptor)
|
||||
.long SYMBOL_NAME(do_set_fast_trap)
|
||||
.long SYMBOL_NAME(do_dom_mem_op)
|
||||
.rept NR_syscalls-(.-hypervisor_call_table)/4
|
||||
.long SYMBOL_NAME(sys_ni_syscall)
|
||||
.endr
|
||||
@@ -0,0 +1,144 @@
|
||||
/******************************************************************************
|
||||
* dom_mem_ops.c
|
||||
*
|
||||
* Code to handle memory related requests from domains eg. balloon driver.
|
||||
*
|
||||
* Copyright (c) 2003, B Dragovic
|
||||
*/
|
||||
|
||||
#include <xeno/config.h>
|
||||
#include <xeno/types.h>
|
||||
#include <xeno/lib.h>
|
||||
#include <xeno/dom_mem_ops.h>
|
||||
#include <xeno/sched.h>
|
||||
#include <xeno/event.h>
|
||||
#include <asm/domain_page.h>
|
||||
|
||||
#if 1
|
||||
#define DPRINTK(_f, _a...) printk( _f , ## _a )
|
||||
#else
|
||||
#define DPRINTK(_f, _a...) ((void)0)
|
||||
#endif
|
||||
|
||||
static long alloc_dom_mem(struct task_struct *p, balloon_def_op_t bop)
|
||||
{
|
||||
struct list_head *temp;
|
||||
struct pfn_info *pf; /* pfn_info of current page */
|
||||
unsigned long mpfn; /* machine frame number of current page */
|
||||
void *va; /* Xen-usable mapping of current page */
|
||||
unsigned long i;
|
||||
unsigned long flags;
|
||||
|
||||
/* POLICY DECISION: Each domain has a page limit. */
|
||||
if( (p->tot_pages + bop.size) > p->max_pages )
|
||||
return -ENOMEM;
|
||||
|
||||
if ( free_pfns < bop.size )
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_irqsave(&free_list_lock, flags);
|
||||
|
||||
temp = free_list.next;
|
||||
for ( i = 0; i < bop.size; i++ )
|
||||
{
|
||||
/* Get a free page and add it to the domain's page list. */
|
||||
pf = list_entry(temp, struct pfn_info, list);
|
||||
pf->flags |= p->domain;
|
||||
pf->type_count = pf->tot_count = 0;
|
||||
temp = temp->next;
|
||||
list_del(&pf->list);
|
||||
list_add_tail(&pf->list, &p->pg_head);
|
||||
free_pfns--;
|
||||
|
||||
p->tot_pages++;
|
||||
|
||||
/* Inform the domain of the new page's machine address. */
|
||||
mpfn = (unsigned long)(pf - frame_table);
|
||||
copy_to_user(bop.pages, &mpfn, sizeof(mpfn));
|
||||
bop.pages++;
|
||||
|
||||
/* Zero out the page to prevent information leakage. */
|
||||
va = map_domain_mem(mpfn << PAGE_SHIFT);
|
||||
memset(va, 0, PAGE_SIZE);
|
||||
unmap_domain_mem(va);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&free_list_lock, flags);
|
||||
|
||||
return bop.size;
|
||||
}
|
||||
|
||||
static long free_dom_mem(struct task_struct *p, balloon_inf_op_t bop)
|
||||
{
|
||||
struct list_head *temp;
|
||||
struct pfn_info *pf; /* pfn_info of current page */
|
||||
unsigned long mpfn; /* machine frame number of current page */
|
||||
unsigned long i;
|
||||
unsigned long flags;
|
||||
long rc = 0;
|
||||
|
||||
spin_lock_irqsave(&free_list_lock, flags);
|
||||
|
||||
temp = free_list.next;
|
||||
for ( i = 0; i < bop.size; i++ )
|
||||
{
|
||||
copy_from_user(&mpfn, bop.pages, sizeof(mpfn));
|
||||
bop.pages++;
|
||||
if ( mpfn >= max_page )
|
||||
{
|
||||
DPRINTK("Domain %d page number out of range (%08lx>=%08lx)\n",
|
||||
p->domain, mpfn, max_page);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pf = &frame_table[mpfn];
|
||||
if ( (pf->type_count != 0) ||
|
||||
(pf->type_count != 0) ||
|
||||
(pf->flags != p->domain) )
|
||||
{
|
||||
DPRINTK("Bad page free for domain %d (%ld, %ld, %08lx)\n",
|
||||
p->domain, pf->type_count, pf->tot_count, pf->flags);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pf->flags = 0;
|
||||
|
||||
list_del(&pf->list);
|
||||
list_add(&pf->list, &free_list);
|
||||
free_pfns++;
|
||||
|
||||
p->tot_pages--;
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&free_list_lock, flags);
|
||||
|
||||
return rc ? rc : bop.size;
|
||||
}
|
||||
|
||||
long do_dom_mem_op(dom_mem_op_t *mem_op)
|
||||
{
|
||||
dom_mem_op_t dmop;
|
||||
unsigned long ret = 0;
|
||||
|
||||
if ( copy_from_user(&dmop, mem_op, sizeof(dom_mem_op_t)) )
|
||||
return -EFAULT;
|
||||
|
||||
switch ( dmop.op )
|
||||
{
|
||||
case BALLOON_DEFLATE_OP:
|
||||
ret = alloc_dom_mem(current, dmop.u.balloon_deflate);
|
||||
break;
|
||||
|
||||
case BALLOON_INFLATE_OP:
|
||||
ret = free_dom_mem(current, dmop.u.balloon_inflate);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("Bad memory operation request %08x.\n", dmop.op);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
+10
-1
@@ -63,7 +63,7 @@ struct task_struct *do_newdomain(unsigned int dom_id, unsigned int cpu)
|
||||
|
||||
p->net_ring_base = (net_ring_t *)(p->shared_info + 1);
|
||||
INIT_LIST_HEAD(&p->pg_head);
|
||||
p->tot_pages = 0;
|
||||
p->max_pages = p->tot_pages = 0;
|
||||
write_lock_irqsave(&tasklist_lock, flags);
|
||||
SET_LINKS(p);
|
||||
write_unlock_irqrestore(&tasklist_lock, flags);
|
||||
@@ -177,6 +177,9 @@ unsigned int alloc_new_dom_mem(struct task_struct *p, unsigned int kbytes)
|
||||
|
||||
p->tot_pages = req_pages;
|
||||
|
||||
// temporary, max_pages should be explicitly specified
|
||||
p->max_pages = p->tot_pages;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -206,6 +209,9 @@ void release_task(struct task_struct *p)
|
||||
REMOVE_LINKS(p);
|
||||
write_unlock_irq(&tasklist_lock);
|
||||
|
||||
/* XXX SMH: so below is screwed currently; need ref counting on vifs,
|
||||
vhds, etc and proper clean up. Until then just blow the memory :-( */
|
||||
#if 0
|
||||
/*
|
||||
* Safe! Only queue skbuffs with tasklist_lock held.
|
||||
* Only access shared_info with tasklist_lock held.
|
||||
@@ -225,6 +231,9 @@ void release_task(struct task_struct *p)
|
||||
free_all_dom_mem(p);
|
||||
|
||||
free_task_struct(p);
|
||||
#else
|
||||
printk("XEN::release_task: not freeing memory etc yet XXX FIXME.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ void halt_machine(u_char key, void *dev_id, struct pt_regs *regs)
|
||||
/* XXX SMH: this is keir's fault */
|
||||
static char *task_states[] =
|
||||
{
|
||||
"Running",
|
||||
"Runnable",
|
||||
"Interruptible Sleep",
|
||||
"Uninterruptible Sleep",
|
||||
NULL, "Stopped",
|
||||
@@ -104,9 +104,8 @@ void do_task_queues(u_char key, void *dev_id, struct pt_regs *regs)
|
||||
printk("Notifying guest...\n");
|
||||
set_bit(_EVENT_DEBUG, &s->events);
|
||||
}
|
||||
}
|
||||
} while ( (p = p->next_task) != &idle0_task );
|
||||
|
||||
while ( (p = p->next_task) != &idle0_task );
|
||||
read_unlock_irqrestore(&tasklist_lock, flags);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -768,7 +768,7 @@ int do_process_page_updates(page_update_request_t *ureqs, int count)
|
||||
{
|
||||
MEM_LOG("Bad domain MPT update (dom %d, pfn %ld)",
|
||||
current->domain, pfn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
|
||||
@@ -38,13 +38,13 @@ typedef struct
|
||||
* Extended requests specify command in least 8 bits of 'value'.
|
||||
*/
|
||||
/* A normal page-table update request. */
|
||||
#define PGREQ_NORMAL 0
|
||||
#define PGREQ_NORMAL 0
|
||||
/* Update an entry in the machine->physical mapping table. */
|
||||
#define PGREQ_MPT_UPDATE 1
|
||||
#define PGREQ_MPT_UPDATE 1
|
||||
/* An extended command. */
|
||||
#define PGREQ_EXTENDED_COMMAND 2
|
||||
#define PGREQ_EXTENDED_COMMAND 2
|
||||
/* DOM0 can make entirely unchecked updates which do not affect refcnts. */
|
||||
#define PGREQ_UNCHECKED_UPDATE 3
|
||||
#define PGREQ_UNCHECKED_UPDATE 3
|
||||
unsigned long ptr, val; /* *ptr = val */
|
||||
/* Announce a new top-level page table. */
|
||||
#define PGEXT_PIN_L1_TABLE 0
|
||||
@@ -90,6 +90,7 @@ typedef struct
|
||||
#define __HYPERVISOR_get_debugreg 13
|
||||
#define __HYPERVISOR_update_descriptor 14
|
||||
#define __HYPERVISOR_set_fast_trap 15
|
||||
#define __HYPERVISOR_dom_mem_op 16
|
||||
|
||||
#define TRAP_INSTR "int $0x82"
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/******************************************************************************
|
||||
* 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 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;
|
||||
@@ -68,7 +68,8 @@ struct task_struct {
|
||||
shared_info_t *shared_info;
|
||||
|
||||
struct list_head pg_head;
|
||||
unsigned int tot_pages;
|
||||
unsigned int tot_pages; /* number of pages currently possesed */
|
||||
unsigned int max_pages; /* max number of pages that can be possesed */
|
||||
|
||||
/* Network I/O */
|
||||
net_ring_t *net_ring_base;
|
||||
|
||||
+13
-8
@@ -657,10 +657,11 @@ static void add_to_net_schedule_list_tail(net_vif_t *vif)
|
||||
/* Destructor function for tx skbs. */
|
||||
static void tx_skb_release(struct sk_buff *skb)
|
||||
{
|
||||
int i;
|
||||
int i, send = 0;
|
||||
net_vif_t *vif = sys_vif_list[skb->src_vif];
|
||||
unsigned int idx;
|
||||
tx_shadow_entry_t *tx;
|
||||
unsigned long cpu_mask;
|
||||
|
||||
for ( i = 0; i < skb_shinfo(skb)->nr_frags; i++ )
|
||||
put_page_tot(skb_shinfo(skb)->frags[i].page);
|
||||
@@ -691,9 +692,7 @@ static void tx_skb_release(struct sk_buff *skb)
|
||||
if ( idx == vif->shadow_ring->tx_idx ) BUG();
|
||||
tx = &vif->shadow_ring->tx_ring[idx];
|
||||
vif->shadow_ring->tx_cons = TX_RING_INC(idx);
|
||||
if ( vif->shadow_ring->tx_cons == vif->net_ring->tx_event )
|
||||
set_bit(_EVENT_NET_TX,
|
||||
&sys_vif_list[skb->src_vif]->domain->shared_info->events);
|
||||
if ( vif->shadow_ring->tx_cons == vif->net_ring->tx_event ) send = 1;
|
||||
} while ( tx->status != RING_STATUS_OK );
|
||||
|
||||
/* Now skip over any more bad descriptors, up to the next good one. */
|
||||
@@ -705,13 +704,19 @@ static void tx_skb_release(struct sk_buff *skb)
|
||||
(tx->status == RING_STATUS_OK) )
|
||||
break;
|
||||
vif->shadow_ring->tx_cons = TX_RING_INC(idx);
|
||||
if ( vif->shadow_ring->tx_cons == vif->net_ring->tx_event )
|
||||
set_bit(_EVENT_NET_TX,
|
||||
&sys_vif_list[skb->src_vif]->domain->shared_info->events);
|
||||
if ( vif->shadow_ring->tx_cons == vif->net_ring->tx_event ) send = 1;
|
||||
} while ( 1 );
|
||||
|
||||
/* Finally, update shared consumer index to the new private value. */
|
||||
/* Update shared consumer index to the new private value. */
|
||||
vif->net_ring->tx_cons = vif->shadow_ring->tx_cons;
|
||||
|
||||
/* Send a transmit event if requested. */
|
||||
if ( send )
|
||||
{
|
||||
cpu_mask = mark_guest_event(
|
||||
sys_vif_list[skb->src_vif]->domain, _EVENT_NET_TX);
|
||||
guest_event_notify(cpu_mask);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
|
||||
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
|
||||
|
||||
# Xeno hack XXX
|
||||
ARCH=xeno
|
||||
ARCH := xeno
|
||||
SUBARCH := i386
|
||||
|
||||
KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g")
|
||||
|
||||
@@ -361,7 +362,7 @@ include/linux/version.h: ./Makefile
|
||||
comma := ,
|
||||
|
||||
init/version.o: init/version.c include/linux/compile.h include/config/MARKER
|
||||
$(CC) $(CFLAGS) $(CFLAGS_KERNEL) -DUTS_MACHINE='"$(ARCH)"' -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -c -o init/version.o init/version.c
|
||||
$(CC) $(CFLAGS) $(CFLAGS_KERNEL) -DUTS_MACHINE='"$(SUBARCH)"' -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -c -o init/version.o init/version.c
|
||||
|
||||
init/main.o: init/main.c include/config/MARKER
|
||||
$(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -c -o $@ $<
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
O_TARGET := balloon_driver.o
|
||||
obj-y := balloon.o
|
||||
include $(TOPDIR)/Rules.make
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/pkt_sched.h>
|
||||
|
||||
#define NET_TX_IRQ _EVENT_NET_TX
|
||||
#define NET_RX_IRQ _EVENT_NET_RX
|
||||
@@ -65,7 +66,20 @@ struct net_private
|
||||
spinlock_t tx_lock;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void dbg_network_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *)dev_id;
|
||||
struct net_private *np = dev->priv;
|
||||
printk(KERN_ALERT "tx_full = %d, tx_entries = %d, tx_idx = %d,"
|
||||
" tx_cons = %d, tx_prod = %d, tx_event = %d, state=%d\n",
|
||||
np->tx_full, atomic_read(&np->tx_entries), np->tx_idx,
|
||||
np->net_ring->tx_cons, np->net_ring->tx_prod,
|
||||
np->net_ring->tx_event,
|
||||
test_bit(__LINK_STATE_XOFF, &dev->state));
|
||||
}
|
||||
|
||||
|
||||
static int network_open(struct net_device *dev)
|
||||
{
|
||||
struct net_private *np = dev->priv;
|
||||
@@ -123,6 +137,14 @@ static int network_open(struct net_device *dev)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
error = request_irq(_EVENT_DEBUG, dbg_network_int, SA_SHIRQ,
|
||||
"debug", dev);
|
||||
if ( error )
|
||||
{
|
||||
printk(KERN_WARNING "%s: Non-fatal error -- no debug interrupt\n",
|
||||
dev->name);
|
||||
}
|
||||
|
||||
printk("XenoLinux Virtual Network Driver installed as %s\n", dev->name);
|
||||
|
||||
netif_start_queue(dev);
|
||||
@@ -147,17 +169,28 @@ static void network_tx_buf_gc(struct net_device *dev)
|
||||
struct net_private *np = dev->priv;
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
unsigned int cons;
|
||||
|
||||
spin_lock_irqsave(&np->tx_lock, flags);
|
||||
|
||||
for ( i = np->tx_idx; i != np->net_ring->tx_cons; i = TX_RING_INC(i) )
|
||||
{
|
||||
skb = np->tx_skb_ring[i];
|
||||
dev_kfree_skb_any(skb);
|
||||
atomic_dec(&np->tx_entries);
|
||||
}
|
||||
do {
|
||||
cons = np->net_ring->tx_cons;
|
||||
|
||||
np->tx_idx = i;
|
||||
for ( i = np->tx_idx; i != cons; i = TX_RING_INC(i) )
|
||||
{
|
||||
skb = np->tx_skb_ring[i];
|
||||
dev_kfree_skb_any(skb);
|
||||
atomic_dec(&np->tx_entries);
|
||||
}
|
||||
|
||||
np->tx_idx = i;
|
||||
|
||||
/* Set a new event, then check for race with update of tx_cons. */
|
||||
np->net_ring->tx_event =
|
||||
TX_RING_ADD(cons, (atomic_read(&np->tx_entries)>>1) + 1);
|
||||
smp_mb();
|
||||
}
|
||||
while ( cons != np->net_ring->tx_cons );
|
||||
|
||||
if ( np->tx_full && (atomic_read(&np->tx_entries) < TX_MAX_ENTRIES) )
|
||||
{
|
||||
@@ -262,17 +295,9 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
np->tx_full = 1;
|
||||
netif_stop_queue(dev);
|
||||
np->net_ring->tx_event =
|
||||
TX_RING_ADD(np->tx_idx, atomic_read(&np->tx_entries) >> 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Avoid unnecessary tx interrupts. */
|
||||
np->net_ring->tx_event = TX_RING_INC(np->net_ring->tx_prod);
|
||||
}
|
||||
spin_unlock_irq(&np->tx_lock);
|
||||
|
||||
/* Must do this after setting tx_event: race with updates of tx_cons. */
|
||||
network_tx_buf_gc(dev);
|
||||
|
||||
HYPERVISOR_net_update();
|
||||
|
||||
@@ -313,4 +313,15 @@ static inline int HYPERVISOR_set_fast_trap(int idx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_dom_mem_op(void *dom_mem_op)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_dom_mem_op),
|
||||
"b" (dom_mem_op) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __HYPERVISOR_H__ */
|
||||
@@ -173,6 +173,10 @@ static __inline__ int get_order(unsigned long size)
|
||||
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
|
||||
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
|
||||
|
||||
/* VIRT <-> MACHINE conversion */
|
||||
#define virt_to_machine(_a) (phys_to_machine(__pa(_a)))
|
||||
#define machine_to_virt(_m) (__va(machine_to_phys(_m)))
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _I386_PAGE_H */
|
||||