diff options
Diffstat (limited to 'tools/internal')
-rw-r--r-- | tools/internal/Makefile | 32 | ||||
-rw-r--r-- | tools/internal/dom0_defs.h | 9 | ||||
-rw-r--r-- | tools/internal/hypervisor_defs.h | 36 | ||||
-rw-r--r-- | tools/internal/mem_defs.h | 45 | ||||
-rw-r--r-- | tools/internal/xi_build.c | 524 | ||||
-rw-r--r-- | tools/internal/xi_create.c | 98 | ||||
-rw-r--r-- | tools/internal/xi_destroy.c | 81 | ||||
-rw-r--r-- | tools/internal/xi_start.c | 80 | ||||
-rw-r--r-- | tools/internal/xi_stop.c | 80 | ||||
-rwxr-xr-x | tools/internal/xi_vifinit | 25 |
10 files changed, 1010 insertions, 0 deletions
diff --git a/tools/internal/Makefile b/tools/internal/Makefile new file mode 100644 index 0000000000..d2e19221d1 --- /dev/null +++ b/tools/internal/Makefile @@ -0,0 +1,32 @@ +CC = gcc +XI_CREATE = xi_create +XI_START = xi_start +XI_STOP = xi_stop +XI_DESTROY = xi_destroy +XI_BUILD = xi_build + +all: $(XI_CREATE).o $(XI_START).o $(XI_STOP).o $(XI_DESTROY).o $(XI_BUILD).o + $(CC) -o $(XI_CREATE) $(XI_CREATE).o + $(CC) -o $(XI_BUILD) $(XI_BUILD).o + $(CC) -o $(XI_START) $(XI_START).o + $(CC) -o $(XI_STOP) $(XI_STOP).o + $(CC) -o $(XI_DESTROY) $(XI_DESTROY).o + +$(XI_CREATE).o: $(XI_CREATE).c dom0_defs.h dom0_ops.h hypervisor_defs.h mem_defs.h + $(CC) -c $(XI_CREATE).c + +internal_domain_build.o: internal_domain_build.c dom0_defs.h dom0_ops.h hypervisor_defs.h mem_defs.h + $(CC) -c internal_domain_build.c + +$(XI_START).o: $(XI_START).c dom0_defs.h dom0_ops.h hypervisor_defs.h mem_defs.h + $(CC) -c $(XI_START).c + +$(XI_STOP).o: $(XI_STOP).c dom0_defs.h dom0_ops.h hypervisor_defs.h mem_defs.h + $(CC) -c $(XI_STOP).c + +$(XI_DESTROY).o: $(XI_DESTROY).c dom0_ops.h dom0_defs.h + $(CC) -c $(XI_DESTROY).c + +clean: + $(RM) *.o $(XI_CREATE) $(XI_START) $(XI_STOP) $(XI_DESTROY) $(XI_BUILD) + diff --git a/tools/internal/dom0_defs.h b/tools/internal/dom0_defs.h new file mode 100644 index 0000000000..e79d85d417 --- /dev/null +++ b/tools/internal/dom0_defs.h @@ -0,0 +1,9 @@ +#define PROC_XENO_ROOT "xeno" +#define PROC_CMD "dom0_cmd" +#define PROC_DOM_PREFIX "dom" +#define PROC_DOM_MEM "mem" +#define PROC_DOM_DATA "new_dom_data" +#define PROC_DOMAINS "domains" + +#define MAX_PATH 256 + diff --git a/tools/internal/hypervisor_defs.h b/tools/internal/hypervisor_defs.h new file mode 100644 index 0000000000..7d0aba03d7 --- /dev/null +++ b/tools/internal/hypervisor_defs.h @@ -0,0 +1,36 @@ +/****************************************************************************** + * hypervisor_defs.h + * + * This needs to be kept in sync with Xen's pagetable update interface! + * + * Copyright (c) 2002-2003, Keir Fraser & Boris Dragovic + */ + +/* taken from include/hypervisor-ifs/hypervisor-if.h */ +typedef struct +{ +/* + * PGREQ_XXX: specified in least-significant bits of 'ptr' field. All requests + * specify relevent PTE or PT address in 'ptr'. Normal requests specify update + * value in 'value'. Extended requests specify command in least 8 bits of + * 'value'. + */ + unsigned long ptr, val; /* *ptr = val */ +} page_update_request_t; + +/* A normal page-table update request. */ +#define PGREQ_NORMAL 0 +#define PGREQ_MPT_UPDATE 1 +/* An extended command. */ +#define PGREQ_EXTENDED_COMMAND 2 +/* Announce a new top-level page table. */ +#define PGEXT_PIN_L1_TABLE 0 +#define PGEXT_PIN_L2_TABLE 1 +#define PGEXT_PIN_L3_TABLE 2 +#define PGEXT_PIN_L4_TABLE 3 +#define PGEXT_UNPIN_TABLE 4 +#define PGEXT_NEW_BASEPTR 5 +#define PGEXT_TLB_FLUSH 6 +#define PGEXT_INVLPG 7 +#define PGEXT_CMD_MASK 255 +#define PGEXT_CMD_SHIFT 8 diff --git a/tools/internal/mem_defs.h b/tools/internal/mem_defs.h new file mode 100644 index 0000000000..a9a1441d61 --- /dev/null +++ b/tools/internal/mem_defs.h @@ -0,0 +1,45 @@ +/* + * memory related definitions needed for userspace domain builder dom0 application. these _need_ to + * be kept in sync with the kernel .h files they were copied over from or something horrible will + * happen. remmember: god kills a kitten every time you forget to keep these in sync. + * + * KAF: Boris, these constants are all fixed by x86 hardware. So the kittens are safe for now :-) + * + * Copyright 2002 by B Dragovic + */ + +/* copied over from hypervisor: include/asm-i386/page.h */ + +#define _PAGE_PRESENT 0x001 +#define _PAGE_RW 0x002 +#define _PAGE_USER 0x004 +#define _PAGE_PWT 0x008 +#define _PAGE_PCD 0x010 +#define _PAGE_ACCESSED 0x020 +#define _PAGE_DIRTY 0x040 +#define _PAGE_PAT 0x080 +#define _PAGE_PSE 0x080 +#define _PAGE_GLOBAL 0x100 + + +#define L1_PAGETABLE_SHIFT 12 +#define L2_PAGETABLE_SHIFT 22 + +#define ENTRIES_PER_L1_PAGETABLE 1024 +#define ENTRIES_PER_L2_PAGETABLE 1024 + +#define PAGE_SHIFT L1_PAGETABLE_SHIFT +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +typedef struct { unsigned long l1_lo; } l1_pgentry_t; +typedef struct { unsigned long l2_lo; } l2_pgentry_t; + +#define l1_table_offset(_a) \ + (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1)) +#define l2_table_offset(_a) \ + ((_a) >> L2_PAGETABLE_SHIFT) + +/* local definitions */ + +#define nr_2_page(x) (x << PAGE_SHIFT) diff --git a/tools/internal/xi_build.c b/tools/internal/xi_build.c new file mode 100644 index 0000000000..2df44f6532 --- /dev/null +++ b/tools/internal/xi_build.c @@ -0,0 +1,524 @@ +/* + * XenoDomainBuilder, copyright (c) Boris Dragovic, bd240@cl.cam.ac.uk + * This code is released under terms and conditions of GNU GPL :). + * Usage: <executable> <mem_kb> <os image> <num_vifs> + */ + +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdlib.h> + +#include "hypervisor_defs.h" +#include "dom0_ops.h" +#include "dom0_defs.h" +#include "mem_defs.h" + +#define PERR_STRING "Xeno Domain Builder" + +#define GUEST_SIG "XenoGues" +#define SIG_LEN 8 + +/* + * NB. No ring-3 access in initial guestOS pagetables. Note that we allow + * ring-3 privileges in the page directories, so that the guestOS may later + * decide to share a 4MB region with applications. + */ +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED) +#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) + +/* standardized error reporting function */ +static void dberr(char *msg) +{ + printf("%s: %s\n", PERR_STRING, msg); +} + +/* status reporting function */ +static void dbstatus(char * msg) +{ + printf("Domain Builder: %s\n", msg); +} + + +/* clean up domain's memory allocations */ +static void dom_mem_cleanup(dom_mem_t * dom_mem) +{ + char mem_path[MAX_PATH]; + int mem_fd; + + /* open the domain's /proc mem interface */ + sprintf(mem_path, "%s%s%s%s%d%s%s", "/proc/", PROC_XENO_ROOT, "/", + PROC_DOM_PREFIX, dom_mem->domain, "/", PROC_DOM_MEM); + + mem_fd = open(mem_path, O_WRONLY); + 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"); + } + + close(mem_fd); +} + +/* ask dom0 to export domains memory through /proc */ +static int setup_dom_memmap(unsigned long pfn, int pages, int dom) +{ + char cmd_path[MAX_PATH]; + dom0_op_t dop; + int cmd_fd; + + dop.cmd = MAP_DOM_MEM; + dop.u.dommem.start_pfn = pfn; + dop.u.dommem.tot_pages = pages; + dop.u.dommem.domain = dom; + + /* open the /proc command interface */ + sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD); + cmd_fd = open(cmd_path, O_WRONLY); + if(cmd_fd < 0){ + perror(PERR_STRING); + return -1; + } + + write(cmd_fd, &dop, sizeof(dom0_op_t)); + close(cmd_fd); + + return 0; +} + +/* request the actual mapping from dom0 */ +static unsigned long get_vaddr(unsigned int dom) +{ + char mem_path[MAX_PATH]; + unsigned long addr; + int mem_fd; + + /* open the domain's /proc mem interface */ + sprintf(mem_path, "%s%s%s%s%d%s%s", "/proc/", PROC_XENO_ROOT, "/", + PROC_DOM_PREFIX, dom, "/", PROC_DOM_MEM); + + mem_fd = open(mem_path, O_RDONLY); + if(mem_fd < 0){ + perror(PERR_STRING); + return 0; + } + + /* get virtual address of mapped region */ + read(mem_fd, &addr, sizeof(addr)); + + close(mem_fd); + + return addr; +} + +static int map_dom_mem(unsigned long pfn, int pages, int dom, + dom_mem_t * dom_mem) +{ + + if(setup_dom_memmap(pfn, pages, dom)){ + perror(PERR_STRING); + return -1; + } + + dom_mem->domain = dom; + dom_mem->start_pfn = pfn; + dom_mem->tot_pages = pages; + if((dom_mem->vaddr = get_vaddr(dom)) == 0){ + dberr("Error mapping dom memory."); + return -1; + } + + return 0; +} + +/* open kernel image and do some sanity checks */ +static int do_kernel_chcks(char *image, long dom_size, + unsigned long * load_addr, size_t * ksize) +{ + char signature[8]; + char status[MAX_PATH]; + struct stat stat; + int fd; + int ret; + + fd = open(image, O_RDONLY); + if(fd < 0){ + perror(PERR_STRING); + ret = -1; + goto out; + } + + if(fstat(fd, &stat) < 0){ + perror(PERR_STRING); + ret = -1; + close(fd); + goto out; + } + + if(stat.st_size > (dom_size << 10)){ + sprintf(status, "Kernel image size %ld larger than requested " + "domain size %ld\n Terminated.\n", stat.st_size, dom_size); + dberr(status); + ret = -1; + close(fd); + goto out; + } + + read(fd, signature, SIG_LEN); + if(strncmp(signature, GUEST_SIG, SIG_LEN)){ + dberr("Kernel image does not contain required signature. " + "Terminating.\n"); + ret = -1; + close(fd); + goto out; + } + + read(fd, load_addr, sizeof(unsigned long)); + + *ksize = stat.st_size - SIG_LEN - sizeof(unsigned long); + + ret = fd; + +out: + return ret; +} + +/* this is the main guestos setup function, + * returnes domain descriptor structure to be used when launching + * the domain by hypervisor to do some last minute initialization. + * page table initialization is done by making a list of page table + * requests that are handeled by the hypervisor in the ordinary + * manner. this way, many potentially messy things are avoided... + */ +#define PAGE_TO_VADDR(_pfn) ((void *)(dom_mem->vaddr + ((_pfn) * PAGE_SIZE))) +static dom_meminfo_t *setup_guestos(int dom, int kernel_fd, int initrd_fd, + unsigned long virt_load_addr, size_t ksize, dom_mem_t *dom_mem) +{ + dom_meminfo_t *meminfo; + unsigned long *page_array; + page_update_request_t *pgt_updates; + dom_mem_t mem_map; + dom_meminfo_t *ret = NULL; + int alloc_index, num_pt_pages; + unsigned long l2tab; + unsigned long l1tab = 0; + unsigned long num_pgt_updates = 0; + unsigned long count, pt_start; + dom0_op_t pgupdate_req; + char cmd_path[MAX_PATH]; + int cmd_fd; + + meminfo = (dom_meminfo_t *)malloc(sizeof(dom_meminfo_t)); + page_array = malloc(dom_mem->tot_pages * 4); + pgt_updates = (page_update_request_t *)dom_mem->vaddr; + alloc_index = dom_mem->tot_pages - 1; + + memset(meminfo, 0, sizeof(meminfo)); + + memcpy(page_array, (void *)dom_mem->vaddr, dom_mem->tot_pages * 4); + + /* Count bottom-level PTs, rounding up. Include one PTE for shared info. */ + num_pt_pages = + (l1_table_offset(virt_load_addr) + dom_mem->tot_pages + 1024) / 1024; + + /* We must also count the page directory. */ + num_pt_pages++; + + /* Index of first PT page. */ + pt_start = dom_mem->tot_pages - num_pt_pages; + + /* first allocate page for page dir. allocation goes backwards from the + * end of the allocated physical address space. + */ + l2tab = *(page_array + alloc_index) << PAGE_SHIFT; + memset(PAGE_TO_VADDR(alloc_index), 0, PAGE_SIZE); + alloc_index--; + meminfo->l2_pgt_addr = l2tab; + meminfo->virt_shinfo_addr = virt_load_addr + nr_2_page(dom_mem->tot_pages); + + /* pin down l2tab addr as page dir page - causes hypervisor to provide + * correct protection for the page + */ + pgt_updates->ptr = l2tab | PGREQ_EXTENDED_COMMAND; + pgt_updates->val = PGEXT_PIN_L2_TABLE; + pgt_updates++; + num_pgt_updates++; + + /* + * Initialise the page tables. The final iteration is for the shared_info + * PTE -- we break out before filling in the entry, as that is done by + * Xen during final setup. + */ + l2tab += l2_table_offset(virt_load_addr) * sizeof(l2_pgentry_t); + for ( count = 0; count < (dom_mem->tot_pages + 1); count++ ) + { + if ( !((unsigned long)l1tab & (PAGE_SIZE-1)) ) + { + l1tab = *(page_array + alloc_index) << PAGE_SHIFT; + memset(PAGE_TO_VADDR(alloc_index), 0, PAGE_SIZE); + alloc_index--; + + l1tab += l1_table_offset(virt_load_addr + nr_2_page(count)) + * sizeof(l1_pgentry_t); + + /* make apropriate entry in the page directory */ + pgt_updates->ptr = l2tab; + pgt_updates->val = l1tab | L2_PROT; + pgt_updates++; + num_pgt_updates++; + l2tab += sizeof(l2_pgentry_t); + } + + /* The last PTE we consider is filled in later by Xen. */ + if ( count == dom_mem->tot_pages ) break; + + if ( count < pt_start ) + { + pgt_updates->ptr = l1tab; + pgt_updates->val = (*(page_array + count) << PAGE_SHIFT) | L1_PROT; + pgt_updates++; + num_pgt_updates++; + l1tab += sizeof(l1_pgentry_t); + } + else + { + pgt_updates->ptr = l1tab; + pgt_updates->val = + ((*(page_array + count) << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW; + pgt_updates++; + num_pgt_updates++; + l1tab += sizeof(l1_pgentry_t); + } + + pgt_updates->ptr = + (*(page_array + count) << PAGE_SHIFT) | PGREQ_MPT_UPDATE; + pgt_updates->val = count; + pgt_updates++; + num_pgt_updates++; + } + + meminfo->virt_startinfo_addr = virt_load_addr + nr_2_page(alloc_index - 1); + meminfo->domain = dom; + + /* + * Send the page update requests down to the hypervisor. + * NB. We must do this before loading the guest OS image! + */ + sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD); + if ( (cmd_fd = open(cmd_path, O_WRONLY)) < 0 ) goto out; + pgupdate_req.cmd = DO_PGUPDATES; + pgupdate_req.u.pgupdate.pgt_update_arr = (unsigned long)dom_mem->vaddr; + pgupdate_req.u.pgupdate.num_pgt_updates = num_pgt_updates; + write(cmd_fd, &pgupdate_req, sizeof(dom0_op_t)); + close(cmd_fd); + + /* Load the guest OS image. */ + if( read(kernel_fd, (char *)dom_mem->vaddr, ksize) != ksize ) + { + dberr("Error reading kernel image, could not" + " read the whole image. Terminating.\n"); + goto out; + } + + if( initrd_fd ) + { + struct stat stat; + unsigned long isize; + + if(fstat(initrd_fd, &stat) < 0){ + perror(PERR_STRING); + close(initrd_fd); + goto out; + } + isize = stat.st_size; + + if( read(initrd_fd, ((char *)dom_mem->vaddr)+ksize, isize) != isize ) + { + dberr("Error reading initrd image, could not" + " read the whole image. Terminating.\n"); + goto out; + } + + meminfo->virt_mod_addr = virt_load_addr + ksize; + meminfo->virt_mod_len = isize; + + } + + + ret = meminfo; +out: + + return ret; +} + +static int launch_domain(dom_meminfo_t * meminfo) +{ + char cmd_path[MAX_PATH]; + dom0_op_t dop; + int cmd_fd; + + sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD); + cmd_fd = open(cmd_path, O_WRONLY); + if(cmd_fd < 0){ + perror(PERR_STRING); + return -1; + } + + dop.cmd = DOM0_BUILDDOMAIN; + memcpy(&dop.u.meminfo, meminfo, sizeof(dom_meminfo_t)); + write(cmd_fd, &dop, sizeof(dom0_op_t)); + close(cmd_fd); + + return 0; +} + +static int get_domain_info (int domain_id, + int *pg_head, + int *tot_pages) +{ + FILE *f; + char domains_path[MAX_PATH]; + char domains_line[256]; + int rc = -1; + int read_id; + + sprintf (domains_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_DOMAINS +); + + f = fopen (domains_path, "r"); + if (f == NULL) goto out; + + read_id = -1; + while (fgets (domains_line, 256, f) != 0) + { + int trans; + trans = sscanf (domains_line, "%d %*d %*d %*d %*d %*d %x %d %*s", &read_id +, pg_head, tot_pages); + if (trans == 3) { + if (read_id == domain_id) { + rc = 0; + break; + } + } + } + + if (read_id == -1) { + errno = ESRCH; + } + + fclose (f); + + out: + return rc; +} + + +int main(int argc, char **argv) +{ + + dom_mem_t dom_os_image; + dom_mem_t dom_pgt; + dom_meminfo_t * meminfo; + size_t ksize; + unsigned long load_addr; + char status[1024]; + int kernel_fd, initrd_fd = 0; + int count; + int cmd_len; + int rc = -1; + int args_start = 4; + char initrd_name[1024]; + int domain_id; + int pg_head; + int tot_pages; + + unsigned long addr; + + /**** this argument parsing code is really _gross_. rewrite me! ****/ + + if(argc < 4) { + dberr("Usage: dom_builder <domain_id> <image> <num_vifs> " + "[<initrd=initrd_name>] <boot_params>\n"); + return -1; + } + + /* Look up information about the domain */ + domain_id = atol(argv[1]); + if (get_domain_info (domain_id, &pg_head, &tot_pages) != 0) { + perror ("Could not find domain information"); + rc = -1; + goto out; + } + + kernel_fd = do_kernel_chcks(argv[2], tot_pages << (PAGE_SHIFT - 10), &load_addr, &ksize); + if(kernel_fd < 0) + return -1; + + + /* map domain's memory */ + if(map_dom_mem(pg_head, tot_pages, + domain_id, &dom_os_image)) + goto out; + + if( strncmp("initrd=", argv[args_start], 7) == 0 ) + { + strncpy( initrd_name, argv[args_start]+7, sizeof(initrd_name) ); + initrd_name[sizeof(initrd_name)-1] = 0; + printf("initrd present, name = %s\n", initrd_name ); + args_start++; + + initrd_fd = open(initrd_name, O_RDONLY); + if(initrd_fd < 0){ + perror(PERR_STRING); + goto out; + } + } + + /* the following code does the actual domain building */ + meminfo = setup_guestos(domain_id, kernel_fd, initrd_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; + } + + meminfo->virt_load_addr = load_addr; + meminfo->num_vifs = atoi(argv[3]); + meminfo->cmd_line[0] = '\0'; + cmd_len = 0; + for(count = args_start; count < argc; count++){ + if(cmd_len + strlen(argv[count]) > MAX_CMD_LEN - 1){ + dberr("Size of image boot params too big!\n"); + break; + } + strcat(meminfo->cmd_line, argv[count]); + strcat(meminfo->cmd_line, " "); + cmd_len += strlen(argv[count] + 1); + } + + /* sprintf(status, + "About to launch new domain %d with folowing parameters:\n" + " * page table base: %lx \n * load address: %lx \n" + " * shared info address: %lx \n * start info address: %lx \n" + " * number of vifs: %d \n * cmd line: %s \n", meminfo->domain, + meminfo->l2_pgt_addr, meminfo->virt_load_addr, + meminfo->virt_shinfo_addr, meminfo->virt_startinfo_addr, + meminfo->num_vifs, meminfo->cmd_line); + dbstatus(status);*/ + + /* and launch the domain */ + rc = launch_domain(meminfo); + +out: + return rc; +} diff --git a/tools/internal/xi_create.c b/tools/internal/xi_create.c new file mode 100644 index 0000000000..5162e27bba --- /dev/null +++ b/tools/internal/xi_create.c @@ -0,0 +1,98 @@ +/* + * XenoDomainBuilder, copyright (c) Boris Dragovic, bd240@cl.cam.ac.uk + * This code is released under terms and conditions of GNU GPL :). + * Usage: <executable> <mem_kb> <os image> <num_vifs> + */ + +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdlib.h> + +#include "hypervisor_defs.h" +#include "dom0_ops.h" +#include "dom0_defs.h" +#include "mem_defs.h" + +/***********************************************************************/ + +static char *argv0 = "internal_domain_create"; + +static void ERROR (char *message) +{ + fprintf (stderr, "%s: %s\n", argv0, message); + exit (-1); +} + +static void PERROR (char *message) +{ + fprintf (stderr, "%s: %s (%s)\n", argv0, message, sys_errlist[errno]); + exit (-1); +} + +/***********************************************************************/ + +static dom0_newdomain_t * create_new_domain(long req_mem, char *name) +{ + dom0_newdomain_t * dom_data; + char cmd_path[MAX_PATH]; + char dom_id_path[MAX_PATH]; + dom0_op_t dop; + int cmd_fd; + int id_fd; + + /* open the /proc command interface */ + sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD); + cmd_fd = open(cmd_path, O_WRONLY); + if(cmd_fd < 0){ + PERROR ("Could not open PROC_CMD interface"); + return 0; + } + + dop.cmd = DOM0_CREATEDOMAIN; + dop.u.newdomain.memory_kb = req_mem; + strncpy (dop.u.newdomain.name, name, MAX_DOMAIN_NAME - 1); + dop.u.newdomain.name[MAX_DOMAIN_NAME - 1] = 0; + + write(cmd_fd, &dop, sizeof(dom0_op_t)); + close(cmd_fd); + + sprintf(dom_id_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", + PROC_DOM_DATA); + while((id_fd = open(dom_id_path, O_RDONLY)) < 0) continue; + dom_data = (dom0_newdomain_t *)malloc(sizeof(dom0_newdomain_t)); + read(id_fd, dom_data, sizeof(dom0_newdomain_t)); + close(id_fd); + + return dom_data; +} + +/***********************************************************************/ + +int main(int argc, char **argv) +{ + dom0_newdomain_t * dom_data; + + if (argv[0] != NULL) + { + argv0 = argv[0]; + } + + if(argc != 3) + { + fprintf (stderr, "Usage: %s <kbytes-mem> <domain-name>\n", argv0); + return -1; + } + + if(!(dom_data = create_new_domain(atol(argv[1]), argv[2]))) + { + return -1; + } + + fprintf (stdout, "%d\n", dom_data -> domain); + return 0; +} diff --git a/tools/internal/xi_destroy.c b/tools/internal/xi_destroy.c new file mode 100644 index 0000000000..b262609165 --- /dev/null +++ b/tools/internal/xi_destroy.c @@ -0,0 +1,81 @@ +/* + * A very(!) simple program to kill a domain. (c) Boris Dragovic + * Usage: <executable> <mem_kb> <os image> <num_vifs> + */ + +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "dom0_ops.h" +#include "dom0_defs.h" + +/***********************************************************************/ + +static char *argv0 = "internal_domain_stop"; + +static void ERROR (char *message) +{ + fprintf (stderr, "%s: %s\n", argv0, message); + exit (-1); +} + +static void PERROR (char *message) +{ + fprintf (stderr, "%s: %s (%s)\n", argv0, message, sys_errlist[errno]); + exit (-1); +} + +/***********************************************************************/ + +static int do_kill_domain(int dom_id, int force) +{ + char cmd_path[MAX_PATH]; + dom0_op_t dop; + int cmd_fd; + + dop.cmd = DOM0_DESTROYDOMAIN; + dop.u.killdomain.domain = dom_id; + dop.u.killdomain.force = force; + + /* open the /proc command interface */ + sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD); + cmd_fd = open(cmd_path, O_WRONLY); + if(cmd_fd < 0){ + PERROR ("Count not open PROC_CMD interface"); + } + + write(cmd_fd, &dop, sizeof(dom0_op_t)); + close(cmd_fd); + + return 0; +} + +int main(int argc, char **argv) +{ + int ret; + + if (argv[0] != NULL) + { + argv0 = argv[0]; + } + + if ( (argc < 2) || (argc > 3) ) + { + usage: + fprintf(stderr, "Usage: %s [-f] <domain_id>\n", argv0); + fprintf(stderr, " -f: Forces immediate destruction of specified domain\n"); + ret = -1; + goto out; + } + + if ( (argc == 3) && strcmp("-f", argv[1]) ) goto usage; + + ret = do_kill_domain(atoi(argv[argc-1]), argc == 3); + +out: + return ret; +} diff --git a/tools/internal/xi_start.c b/tools/internal/xi_start.c new file mode 100644 index 0000000000..7c03180dcc --- /dev/null +++ b/tools/internal/xi_start.c @@ -0,0 +1,80 @@ +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdlib.h> + +#include "hypervisor_defs.h" +#include "dom0_ops.h" +#include "dom0_defs.h" +#include "mem_defs.h" + +/***********************************************************************/ + +static char *argv0 = "internal_domain_start"; + +static void ERROR (char *message) +{ + fprintf (stderr, "%s: %s\n", argv0, message); + exit (-1); +} + +static void PERROR (char *message) +{ + fprintf (stderr, "%s: %s (%s)\n", argv0, message, sys_errlist[errno]); + exit (-1); +} + +/***********************************************************************/ + +static int start_domain(int id) +{ + dom0_newdomain_t * dom_data; + char cmd_path[MAX_PATH]; + char dom_id_path[MAX_PATH]; + dom0_op_t dop; + int cmd_fd; + int id_fd; + + /* Set up the DOM0_STARTDOMAIN command */ + dop.cmd = DOM0_STARTDOMAIN; + dop.u.meminfo.domain = id; + + /* open the /proc command interface */ + sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD); + cmd_fd = open(cmd_path, O_WRONLY); + if(cmd_fd < 0){ + PERROR ("Count not open PROC_CMD interface"); + } + + /* Issue the command */ + write(cmd_fd, &dop, sizeof(dom0_op_t)); + close(cmd_fd); + + return 0; +} + +/***********************************************************************/ + +int main(int argc, char **argv) +{ + int rc; + + if (argv[0] != NULL) + { + argv0 = argv[0]; + } + + if(argc != 2) + { + fprintf (stderr, "Usage: %s <domain-id>\n", argv0); + return -1; + } + + rc = start_domain(atol(argv[1])); + + return rc; +} diff --git a/tools/internal/xi_stop.c b/tools/internal/xi_stop.c new file mode 100644 index 0000000000..cbed24d867 --- /dev/null +++ b/tools/internal/xi_stop.c @@ -0,0 +1,80 @@ +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdlib.h> + +#include "hypervisor_defs.h" +#include "dom0_ops.h" +#include "dom0_defs.h" +#include "mem_defs.h" + +/***********************************************************************/ + +static char *argv0 = "internal_domain_stop"; + +static void ERROR (char *message) +{ + fprintf (stderr, "%s: %s\n", argv0, message); + exit (-1); +} + +static void PERROR (char *message) +{ + fprintf (stderr, "%s: %s (%s)\n", argv0, message, sys_errlist[errno]); + exit (-1); +} + +/***********************************************************************/ + +static int stop_domain(int id) +{ + dom0_newdomain_t * dom_data; + char cmd_path[MAX_PATH]; + char dom_id_path[MAX_PATH]; + dom0_op_t dop; + int cmd_fd; + int id_fd; + + /* Set up the DOM0_STOPDOMAIN command */ + dop.cmd = DOM0_STOPDOMAIN; + dop.u.meminfo.domain = id; + + /* open the /proc command interface */ + sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD); + cmd_fd = open(cmd_path, O_WRONLY); + if(cmd_fd < 0){ + PERROR ("Count not open PROC_CMD interface"); + } + + /* Issue the command */ + write(cmd_fd, &dop, sizeof(dom0_op_t)); + close(cmd_fd); + + return 0; +} + +/***********************************************************************/ + +int main(int argc, char **argv) +{ + int rc; + + if (argv[0] != NULL) + { + argv0 = argv[0]; + } + + if(argc != 2) + { + fprintf (stderr, "Usage: %s <domain-id>\n", argv0); + return -1; + } + + rc = stop_domain(atol(argv[1])); + + return rc; +} diff --git a/tools/internal/xi_vifinit b/tools/internal/xi_vifinit new file mode 100755 index 0000000000..feac666bb6 --- /dev/null +++ b/tools/internal/xi_vifinit @@ -0,0 +1,25 @@ +#!/bin/bash +# +# vifinit +# +# This is a silly little script to dump a couple of simple rules down to +# the hypervisor to assign a full static IP to a given virtual interface. +# +# Usage is: +# +# vifinit [vif dom] [vif idx] [dotted decimal ip address] +# +if [ $# -ne 3 ] ; +then + echo "usage: $0 <domain_id> <vid_ifx> <dotted_decimal_ip_address>" + exit +fi + +#outbound rule: +echo "ADD ACCEPT srcaddr=$3 srcaddrmask=255.255.255.255 srcdom=$1 srcidx=$2 dst=PHYS proto=any" > /proc/vfr + +#inbound rule: +echo "ADD ACCEPT dstaddr=$3 dstaddrmask=255.255.255.255 src=ANY dstdom=$1 dstidx=$2 proto=any" > /proc/vfr + +#----] done. + |