mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
bitkeeper revision 1.33.1.1 (3e4d0046UBuDSsmiQzTssLuipi89Wg)
put domain builder tools and scripts under bk (these are for running under domain 0)
This commit is contained in:
1 parent
ce62d9e7f6
commit
238daefdd2
12 files changed
+808
No files matched your search
@@ -1,12 +1,23 @@
|
||||
3ddb6b0bKlMz_dz-M59a1mkUa1lASw BitKeeper/etc/config
|
||||
3ddb6b0buTaC5zg1_a8FoAR9FWi_mw BitKeeper/etc/ignore
|
||||
3ddb79c9_hgSp-gsQm8HqWM_9W3B_A BitKeeper/etc/logging_ok
|
||||
3e4d00468-FN2VDeEHo96zxrMHK_mA tools/domain_builder/Makefile
|
||||
3e4d0046SPau_y0sw2WLJz8QkqNoRA tools/domain_builder/README
|
||||
3e4d0046bbdH0GsI9J_1Eb4ZQHfIiQ tools/domain_builder/dom0_defs.h
|
||||
3e4d0046RgYCfGOw6qGz_7kYLMV2Vw tools/domain_builder/dom0_ops.h
|
||||
3e4d0046ouLij_CMN_j7-dUHZIBI_A tools/domain_builder/dom_builder.c
|
||||
3e4d0046EKs06fY0CWDEgZQcn7DYUg tools/domain_builder/dom_kill.c
|
||||
3e4d0046aPbGiRTtdWxqY5b3ytWurA tools/domain_builder/hypervisor_defs.h
|
||||
3e4d00468aE86IfyjfrJwYoxzM7pAw tools/domain_builder/mem_defs.h
|
||||
3e4d0046VHhXwFuG5FK34AVxqd5A_A tools/domain_builder/newdom
|
||||
3e4d0046IBzDIeaMbQB-e2QB2ahbig tools/domain_builder/vifinit
|
||||
3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen-2.4.16/Makefile
|
||||
3ddb79bcCa2VbsMp7mWKlhgwLQUQGA xen-2.4.16/README
|
||||
3ddb79bcWnTwYsQRWl_PaneJfa6p0w xen-2.4.16/Rules.mk
|
||||
3ddb79bcZbRBzT3elFWSX7u6NtMagQ xen-2.4.16/arch/i386/Makefile
|
||||
3ddb79bcBQF85CfLS4i1WGZ4oLLaCA xen-2.4.16/arch/i386/Rules.mk
|
||||
3ddb79bcsjinG9k1KcvbVBuas1R2dA xen-2.4.16/arch/i386/apic.c
|
||||
3e4d0046IHluXnd2lSLBCKqMg2QsZg xen-2.4.16/arch/i386/apic.o
|
||||
3ddb79bcSC_LvnmFlX-T5iTgaR0SKg xen-2.4.16/arch/i386/boot/boot.S
|
||||
3ddb79bcUrk2EIaM5VsT6wUudH1kkg xen-2.4.16/arch/i386/delay.c
|
||||
3ddb79bcecupHj56ZbTa3B0FxDowMg xen-2.4.16/arch/i386/entry.S
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
CC = gcc
|
||||
BUILDER = domain_builder
|
||||
KILL = kill_domain
|
||||
|
||||
all: dom_builder.o dom_kill.o
|
||||
$(CC) -o $(BUILDER) dom_builder.o
|
||||
$(CC) -o $(KILL) dom_kill.o
|
||||
|
||||
dom_builder.o: dom_builder.c dom0_defs.h dom0_ops.h hypervisor_defs.h mem_defs.h
|
||||
$(CC) -c dom_builder.c
|
||||
|
||||
dom_kill.o: dom_kill.c dom0_ops.h dom0_defs.h
|
||||
$(CC) -c dom_kill.c
|
||||
|
||||
clean:
|
||||
$(RM) *.o domain_builder kill_domain
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
A couple of simple steps to get you going:
|
||||
|
||||
1. do make (suitable Makefile is in the source dir)
|
||||
2. copy over andy's vifinit script to local dir
|
||||
3. copy over xenolinux guestos image (NB. image needs to be uncompressed, so
|
||||
if the only image you have is image.gz do gunzip image.gz before doing
|
||||
anything further)
|
||||
4. add executable permissions to newdom and vifint
|
||||
5. edit newdom script and change it as it suits you
|
||||
|
||||
newdom script takes guestos image file name as first parameter and newdom id
|
||||
as second parameter, eg.:
|
||||
|
||||
./newdom xenolinux 1
|
||||
|
||||
should initiate building of dom1 with the image contained in file named
|
||||
xenolinux in local dir.
|
||||
|
||||
in general, domain_builder application takes three parameters: requested
|
||||
memory in kb, guestos image file name and number of vifs to be created, eg.
|
||||
|
||||
./domain_builder 16000 xenolinux 1
|
||||
|
||||
would build domX reserving 16MB mem, creating 1 vif and using os image stored
|
||||
as xenolinux in local dir.
|
||||
|
||||
happy booting!
|
||||
|
||||
boris
|
||||
@@ -0,0 +1,8 @@
|
||||
#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 MAX_PATH 256
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/******************************************************************************
|
||||
* dom0_ops.h
|
||||
*
|
||||
* Process command requests from domain-0 guest OS.
|
||||
*
|
||||
* Copyright (c) 2002, K A Fraser, B Dragovic
|
||||
*/
|
||||
|
||||
#define DOM0_NEWDOMAIN 0
|
||||
#define DOM0_KILLDOMAIN 1
|
||||
#define DOM0_GETMEMLIST 2
|
||||
#define DOM0_STARTDOM 4
|
||||
#define MAP_DOM_MEM 6 /* Not passed down to Xen */
|
||||
#define DO_PGUPDATES 7 /* Not passed down to Xen */
|
||||
#define MAX_CMD 8
|
||||
|
||||
#define MAX_CMD_LEN 256
|
||||
|
||||
typedef struct dom0_newdomain_st
|
||||
{
|
||||
unsigned int domain;
|
||||
unsigned int memory_kb;
|
||||
unsigned int num_vifs; // temporary
|
||||
unsigned long pg_head; // return parameter
|
||||
} dom0_newdomain_t;
|
||||
|
||||
typedef struct dom0_killdomain_st
|
||||
{
|
||||
unsigned int domain;
|
||||
} dom0_killdomain_t;
|
||||
|
||||
typedef struct dom0_getmemlist_st
|
||||
{
|
||||
unsigned long start_pfn;
|
||||
unsigned long num_pfns;
|
||||
void *buffer;
|
||||
} dom0_getmemlist_t;
|
||||
|
||||
/* This is entirely processed by XenoLinux */
|
||||
typedef struct dom_mem
|
||||
{
|
||||
unsigned int domain;
|
||||
unsigned long vaddr;
|
||||
unsigned long start_pfn;
|
||||
int tot_pages;
|
||||
} dom_mem_t;
|
||||
|
||||
/* This is entirely processed by XenoLinux */
|
||||
typedef struct dom_pgupdate
|
||||
{
|
||||
unsigned long pgt_update_arr;
|
||||
unsigned long num_pgt_updates;
|
||||
} dom_pgupdate_t;
|
||||
|
||||
typedef struct domain_launch
|
||||
{
|
||||
unsigned int domain;
|
||||
unsigned long l2_pgt_addr;
|
||||
unsigned long virt_load_addr;
|
||||
unsigned long virt_shinfo_addr;
|
||||
unsigned long virt_startinfo_addr;
|
||||
unsigned int num_vifs;
|
||||
char cmd_line[MAX_CMD_LEN];
|
||||
} dom_meminfo_t;
|
||||
|
||||
typedef struct dom0_op_st
|
||||
{
|
||||
unsigned long cmd;
|
||||
union
|
||||
{
|
||||
dom0_newdomain_t newdomain;
|
||||
dom0_killdomain_t killdomain;
|
||||
dom0_getmemlist_t getmemlist;
|
||||
dom_mem_t dommem;
|
||||
dom_pgupdate_t pgupdate;
|
||||
dom_meminfo_t meminfo;
|
||||
}
|
||||
u;
|
||||
} dom0_op_t;
|
||||
|
||||
@@ -0,0 +1,485 @@
|
||||
/*
|
||||
* 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 "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
|
||||
|
||||
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED)
|
||||
#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED|_PAGE_DIRTY)
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* create new domain */
|
||||
static dom0_newdomain_t * create_new_domain(long req_mem)
|
||||
{
|
||||
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(PERR_STRING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dop.cmd = DOM0_NEWDOMAIN;
|
||||
dop.u.newdomain.memory_kb = req_mem;
|
||||
|
||||
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){}
|
||||
dom_data = (dom0_newdomain_t *)malloc(sizeof(dom0_newdomain_t));
|
||||
read(id_fd, dom_data, sizeof(dom0_newdomain_t));
|
||||
close(id_fd);
|
||||
|
||||
sprintf(cmd_path, "Reserved %ld kbytes memory and assigned id %d to the"
|
||||
"new domain.", req_mem, dom_data->domain);
|
||||
dbstatus(cmd_path);
|
||||
|
||||
return dom_data;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
*ksize = stat.st_size - SIG_LEN;
|
||||
|
||||
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));
|
||||
|
||||
sprintf(status, "Kernel image %s valid, kernel virtual load address %lx",
|
||||
image, *load_addr);
|
||||
dbstatus(status);
|
||||
|
||||
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...
|
||||
*/
|
||||
static dom_meminfo_t * setup_guestos(int dom, int kernel_fd,
|
||||
unsigned long virt_load_addr, size_t ksize, dom_mem_t *dom_mem)
|
||||
{
|
||||
dom_meminfo_t * meminfo = (dom_meminfo_t *)malloc(sizeof(dom_meminfo_t));
|
||||
unsigned long * page_array = (unsigned long *)(dom_mem->vaddr);
|
||||
page_update_request_t * pgt_updates = (page_update_request_t *)
|
||||
(dom_mem->vaddr + ((ksize + (PAGE_SIZE-1)) & PAGE_MASK));
|
||||
dom_mem_t mem_map;
|
||||
dom_meminfo_t * ret = NULL;
|
||||
int alloc_index = dom_mem->tot_pages - 1, num_pt_pages;
|
||||
unsigned long l2tab;
|
||||
unsigned long l1tab = 0;
|
||||
unsigned long num_pgt_updates = 0;
|
||||
unsigned long pgt_update_arr = (unsigned long)pgt_updates;
|
||||
unsigned long count, pt_start;
|
||||
|
||||
/* Count bottom-level PTs. Round up to a whole PT. */
|
||||
num_pt_pages =
|
||||
(l1_table_offset(virt_load_addr) + dom_mem->tot_pages + 1023) / 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;
|
||||
alloc_index--;
|
||||
meminfo->l2_pgt_addr = l2tab;
|
||||
meminfo->virt_shinfo_addr = virt_load_addr + nr_2_page(dom_mem->tot_pages);
|
||||
count = ((unsigned long)pgt_updates - (unsigned long)(dom_mem->vaddr))
|
||||
>> PAGE_SHIFT;
|
||||
|
||||
/* zero out l2 page */
|
||||
if(map_dom_mem(l2tab >> PAGE_SHIFT, 1, dom_mem->domain, &mem_map)){
|
||||
dberr("Unable to map l2 page into Domain Builder.");
|
||||
goto out;
|
||||
}
|
||||
memset((void *)mem_map.vaddr, 0, PAGE_SIZE);
|
||||
dom_mem_cleanup(&mem_map);
|
||||
|
||||
/* 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++;
|
||||
|
||||
/* this loop initializes page tables and does one extra entry
|
||||
* to be used by the shared info page. shared info is not in
|
||||
* the domains physical address space and is not owned by the
|
||||
* domain.
|
||||
*/
|
||||
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;
|
||||
alloc_index--;
|
||||
|
||||
/* zero out l1 page */
|
||||
if(map_dom_mem(l1tab >> PAGE_SHIFT, 1, dom_mem->domain, &mem_map)){
|
||||
dberr("Unable to map l1 page into Domain Builder.");
|
||||
goto out;
|
||||
}
|
||||
memset((void *)mem_map.vaddr, 0, PAGE_SIZE);
|
||||
dom_mem_cleanup(&mem_map);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* copy the guest os image */
|
||||
if(!(read(kernel_fd, (char *)dom_mem->vaddr, ksize) > 0)){
|
||||
dberr("Error reading kernel image, could not"
|
||||
" read the whole image. Terminating.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
{
|
||||
dom0_op_t pgupdate_req;
|
||||
char cmd_path[MAX_PATH];
|
||||
int cmd_fd;
|
||||
|
||||
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 = pgt_update_arr;
|
||||
pgupdate_req.u.pgupdate.num_pgt_updates = num_pgt_updates;
|
||||
|
||||
write(cmd_fd, &pgupdate_req, sizeof(dom0_op_t));
|
||||
close(cmd_fd);
|
||||
}
|
||||
|
||||
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_STARTDOM;
|
||||
memcpy(&dop.u.meminfo, meminfo, sizeof(dom_meminfo_t));
|
||||
write(cmd_fd, &dop, sizeof(dom0_op_t));
|
||||
|
||||
dbstatus("Launched the new domain!");
|
||||
|
||||
close(cmd_fd);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
dom0_newdomain_t * dom_data;
|
||||
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;
|
||||
int count;
|
||||
int cmd_len;
|
||||
int ret = 0;
|
||||
|
||||
unsigned long addr;
|
||||
|
||||
if(argc < 4){
|
||||
dberr("Usage: dom_builder <kbytes_mem> <image> <num_vifs> "
|
||||
"<boot_params>\n");
|
||||
ret = -1;
|
||||
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;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* request the creation of new domain */
|
||||
dom_data = create_new_domain(atol(argv[1]));
|
||||
if(dom_data == 0){
|
||||
ret = -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;
|
||||
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);
|
||||
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';
|
||||
cmd_len = 0;
|
||||
for(count = 4; 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 */
|
||||
if(launch_domain(meminfo) != 0)
|
||||
ret = -1;
|
||||
|
||||
free(meminfo);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#define PERR_STRING "Xen Domain Killer"
|
||||
|
||||
static int do_kill_domain(int dom_id)
|
||||
{
|
||||
char cmd_path[MAX_PATH];
|
||||
dom0_op_t dop;
|
||||
int cmd_fd;
|
||||
|
||||
dop.cmd = DOM0_KILLDOMAIN;
|
||||
dop.u.killdomain.domain = dom_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(PERR_STRING);
|
||||
return -1;
|
||||
}
|
||||
|
||||
write(cmd_fd, &dop, sizeof(dom0_op_t));
|
||||
close(cmd_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(argc < 2){
|
||||
printf("Usage: kill_domain <domain_id>\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = do_kill_domain(atoi(argv[1]));
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
VIFINIT=./vifinit
|
||||
DOM_BUILDER=./domain_builder
|
||||
|
||||
DOM=$2
|
||||
|
||||
ADDR=`/sbin/ifconfig eth0 | grep inet.addr | sed -e 's/.*inet addr:\([0-9.]*\) .*/\1/'`
|
||||
|
||||
LO=`echo $ADDR | sed -e 's/[0-9]\+\.[0-9]\+\.[0-9]\+\.\([0-9]\+\)/\1/'`
|
||||
HI=`echo $ADDR | sed -e 's/\([0-9]\+\.[0-9]\+\.[0-9]\+\)\.[0-9]\+/\1/'`
|
||||
|
||||
NEWADDR=$HI.$[LO+DOM]
|
||||
|
||||
$VIFINIT $DOM $NEWADDR
|
||||
|
||||
$DOM_BUILDER 16000 $1 1
|
||||
@@ -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 id] [dotted decimal ip address]
|
||||
#
|
||||
if [ $# -ne 2 ] ;
|
||||
then
|
||||
echo "usage: vifinit [vif id] [dotted decimal ip address]"
|
||||
exit
|
||||
fi
|
||||
|
||||
#outbound rule:
|
||||
echo "ADD ACCEPT srcaddr=$2 srcaddrmask=255.255.255.255 srcint=$1 dstint=-1 proto=any" > /proc/vfr
|
||||
|
||||
#inbound rule:
|
||||
echo "ADD ACCEPT dstaddr=$2 dstaddrmask=255.255.255.255 srcint=-4 dstint=$1 proto=any" > /proc/vfr
|
||||
|
||||
#----] done.
|
||||
|
||||
Binary file not shown.