debuggers.hg
changeset 996:b86d78981ae9
bitkeeper revision 1.613 (3fbbf72duBrrL77JwhqU9DkVTwQtFA)
Many files:
Rename new library to 'xc' (Xen Control).
xc.h:
Rename: tools/libxc/xi.h -> tools/libxc/xc.h
libxc_private.h:
Rename: tools/libxc/libxi_private.h -> tools/libxc/libxc_private.h
libxc_vif.c:
Rename: tools/libxc/libxi_vif.c -> tools/libxc/libxc_vif.c
libxc_vbd.c:
Rename: tools/libxc/libxi_vbd.c -> tools/libxc/libxc_vbd.c
libxc_private.c:
Rename: tools/libxc/libxi_private.c -> tools/libxc/libxc_private.c
libxc_misc.c:
Rename: tools/libxc/libxi_misc.c -> tools/libxc/libxc_misc.c
libxc_linux_restore.c:
Rename: tools/libxc/libxi_linux_restore.c -> tools/libxc/libxc_linux_restore.c
libxc_linux_save.c:
Rename: tools/libxc/libxi_linux_save.c -> tools/libxc/libxc_linux_save.c
libxc_linux_build.c:
Rename: tools/libxc/libxi_linux_build.c -> tools/libxc/libxc_linux_build.c
libxc_domain.c:
Rename: tools/libxc/libxi_domain.c -> tools/libxc/libxc_domain.c
libxc_bvtsched.c:
Rename: tools/libxc/libxi_bvtsched.c -> tools/libxc/libxc_bvtsched.c
Many files:
mvdir
Many files:
Rename new library to 'xc' (Xen Control).
xc.h:
Rename: tools/libxc/xi.h -> tools/libxc/xc.h
libxc_private.h:
Rename: tools/libxc/libxi_private.h -> tools/libxc/libxc_private.h
libxc_vif.c:
Rename: tools/libxc/libxi_vif.c -> tools/libxc/libxc_vif.c
libxc_vbd.c:
Rename: tools/libxc/libxi_vbd.c -> tools/libxc/libxc_vbd.c
libxc_private.c:
Rename: tools/libxc/libxi_private.c -> tools/libxc/libxc_private.c
libxc_misc.c:
Rename: tools/libxc/libxi_misc.c -> tools/libxc/libxc_misc.c
libxc_linux_restore.c:
Rename: tools/libxc/libxi_linux_restore.c -> tools/libxc/libxc_linux_restore.c
libxc_linux_save.c:
Rename: tools/libxc/libxi_linux_save.c -> tools/libxc/libxc_linux_save.c
libxc_linux_build.c:
Rename: tools/libxc/libxi_linux_build.c -> tools/libxc/libxc_linux_build.c
libxc_domain.c:
Rename: tools/libxc/libxi_domain.c -> tools/libxc/libxc_domain.c
libxc_bvtsched.c:
Rename: tools/libxc/libxi_bvtsched.c -> tools/libxc/libxc_bvtsched.c
Many files:
mvdir
author | kaf24@scramble.cl.cam.ac.uk |
---|---|
date | Wed Nov 19 23:05:17 2003 +0000 (2003-11-19) |
parents | 603ae09a1314 |
children | 461fc928a4bf |
files | .rootkeys tools/libxc/Makefile tools/libxc/libxc_bvtsched.c tools/libxc/libxc_domain.c tools/libxc/libxc_linux_build.c tools/libxc/libxc_linux_restore.c tools/libxc/libxc_linux_save.c tools/libxc/libxc_misc.c tools/libxc/libxc_private.c tools/libxc/libxc_private.h tools/libxc/libxc_vbd.c tools/libxc/libxc_vif.c tools/libxc/rpm.spec tools/libxc/xc.h tools/libxi/Makefile tools/libxi/libxi_bvtsched.c tools/libxi/libxi_domain.c tools/libxi/libxi_linux_build.c tools/libxi/libxi_linux_restore.c tools/libxi/libxi_linux_save.c tools/libxi/libxi_misc.c tools/libxi/libxi_private.c tools/libxi/libxi_private.h tools/libxi/libxi_vbd.c tools/libxi/libxi_vif.c tools/libxi/rpm.spec tools/libxi/xi.h |
line diff
1.1 --- a/.rootkeys Wed Nov 19 17:22:42 2003 +0000 1.2 +++ b/.rootkeys Wed Nov 19 23:05:17 2003 +0000 1.3 @@ -184,19 +184,19 @@ 3fb01fd54I4P44vZDb1CtDt1BytDtA tools/int 1.4 3fb01fd5B-UeibZkmSCOUZckNyNFYA tools/internal/xi_vbd_list.c 1.5 3f86be322bd0h9jG3krZFOUgCDoxZg tools/internal/xi_vif_params.c 1.6 3eb781fd7211MZsLxJSiuy7W4KnJXg tools/internal/xi_vifinit 1.7 -3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/libxi/Makefile 1.8 -3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/libxi/libxi_bvtsched.c 1.9 -3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/libxi/libxi_domain.c 1.10 -3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/libxi/libxi_linux_build.c 1.11 -3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/libxi/libxi_linux_restore.c 1.12 -3fbba6db7li3FJiABYtCmuGxOJxEGw tools/libxi/libxi_linux_save.c 1.13 -3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/libxi/libxi_misc.c 1.14 -3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/libxi/libxi_private.c 1.15 -3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/libxi/libxi_private.h 1.16 -3fbba6dcoGq9hQlksrBUfC2P5F6sGg tools/libxi/libxi_vbd.c 1.17 -3fbba6dc38q-ioRlwSR_quw4G3qUeQ tools/libxi/libxi_vif.c 1.18 -3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/libxi/rpm.spec 1.19 -3fbba6dcrNxtygEcgJYAJJ1gCQqfsA tools/libxi/xi.h 1.20 +3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/libxc/Makefile 1.21 +3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/libxc/libxc_bvtsched.c 1.22 +3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/libxc/libxc_domain.c 1.23 +3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/libxc/libxc_linux_build.c 1.24 +3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/libxc/libxc_linux_restore.c 1.25 +3fbba6db7li3FJiABYtCmuGxOJxEGw tools/libxc/libxc_linux_save.c 1.26 +3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/libxc/libxc_misc.c 1.27 +3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/libxc/libxc_private.c 1.28 +3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/libxc/libxc_private.h 1.29 +3fbba6dcoGq9hQlksrBUfC2P5F6sGg tools/libxc/libxc_vbd.c 1.30 +3fbba6dc38q-ioRlwSR_quw4G3qUeQ tools/libxc/libxc_vif.c 1.31 +3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/libxc/rpm.spec 1.32 +3fbba6dcrNxtygEcgJYAJJ1gCQqfsA tools/libxc/xc.h 1.33 3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile 1.34 3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile 1.35 3f6dc140C8tAeBfroAF24VrmCS4v_w tools/misc/miniterm/README
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/tools/libxc/Makefile Wed Nov 19 23:05:17 2003 +0000 2.3 @@ -0,0 +1,48 @@ 2.4 + 2.5 +CC = gcc 2.6 +CFLAGS = -c -Wall -O3 2.7 +CFLAGS += -I../../xen/include -I../../xenolinux-sparse/include 2.8 + 2.9 +HDRS = $(wildcard *.h) 2.10 +OBJS = $(patsubst %.c,%.o,$(wildcard libxc_*.c)) 2.11 + 2.12 +LIBS = libxc.a libxc.so 2.13 + 2.14 +all: check-for-zlib $(LIBS) 2.15 + ranlib libxc.a 2.16 + 2.17 +check-for-zlib: 2.18 + @if [ ! -e /usr/include/zlib.h ]; then \ 2.19 + echo "***********************************************************"; \ 2.20 + echo "ERROR: install zlib header files (http://www.gzip.org/zlib)"; \ 2.21 + echo "***********************************************************"; \ 2.22 + false; \ 2.23 + fi 2.24 + 2.25 +install: all 2.26 + mkdir -p ../../../install/lib 2.27 + mkdir -p ../../../install/include 2.28 + cp -a $(LIBS) ../../../install/lib 2.29 + for i in $(LIBS) do ; chmod 755 ../../../install/bin/$i ; done 2.30 + cp -a xc.h ../../../install/include 2.31 + chmod 644 ../../../install/include/xc.h 2.32 + 2.33 +clean: 2.34 + $(RM) *.a *.so *.o *.rpm $(LIBS) 2.35 + 2.36 +rpm: all 2.37 + rm -rf staging 2.38 + mkdir staging 2.39 + mkdir staging/i386 2.40 + rpmbuild --define "staging$$PWD/staging" --define '_builddir.' \ 2.41 + --define "_rpmdir$$PWD/staging" -bb rpm.spec 2.42 + mv staging/i386/*.rpm . 2.43 + rm -rf staging 2.44 + 2.45 +libxc.so: $(OBJS) 2.46 + $(LD) -shared -o $@ $^ -lz 2.47 + 2.48 +libxc.a: libxc.a($(OBJS)) 2.49 + 2.50 +%.o: %.c $(HDRS) Makefile 2.51 + $(CC) $(CFLAGS) -o $@ $<
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/tools/libxc/libxc_bvtsched.c Wed Nov 19 23:05:17 2003 +0000 3.3 @@ -0,0 +1,33 @@ 3.4 +/****************************************************************************** 3.5 + * libxc_bvtsched.c 3.6 + * 3.7 + * API for manipulating parameters of the Borrowed Virtual Time scheduler. 3.8 + * 3.9 + * Copyright (c) 2003, K A Fraser. 3.10 + */ 3.11 + 3.12 +#include "libxc_private.h" 3.13 + 3.14 +int xc_bvtsched_global_set(unsigned long ctx_allow) 3.15 +{ 3.16 + dom0_op_t op; 3.17 + op.cmd = DOM0_BVTCTL; 3.18 + op.u.bvtctl.ctx_allow = ctx_allow; 3.19 + return do_dom0_op(&op); 3.20 +} 3.21 + 3.22 +int xc_bvtsched_domain_set(unsigned int domid, 3.23 + unsigned long mcuadv, 3.24 + unsigned long warp, 3.25 + unsigned long warpl, 3.26 + unsigned long warpu) 3.27 +{ 3.28 + dom0_op_t op; 3.29 + op.cmd = DOM0_ADJUSTDOM; 3.30 + op.u.adjustdom.domain = domid; 3.31 + op.u.adjustdom.mcu_adv = mcuadv; 3.32 + op.u.adjustdom.warp = warp; 3.33 + op.u.adjustdom.warpl = warpl; 3.34 + op.u.adjustdom.warpu = warpu; 3.35 + return do_dom0_op(&op); 3.36 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/tools/libxc/libxc_domain.c Wed Nov 19 23:05:17 2003 +0000 4.3 @@ -0,0 +1,80 @@ 4.4 +/****************************************************************************** 4.5 + * libxc_domain.c 4.6 + * 4.7 + * API for manipulating and obtaining information on domains. 4.8 + * 4.9 + * Copyright (c) 2003, K A Fraser. 4.10 + */ 4.11 + 4.12 +#include "libxc_private.h" 4.13 + 4.14 +int xc_domain_create(unsigned int mem_kb, const char *name) 4.15 +{ 4.16 + int err; 4.17 + dom0_op_t op; 4.18 + 4.19 + op.cmd = DOM0_CREATEDOMAIN; 4.20 + op.u.createdomain.memory_kb = mem_kb; 4.21 + strncpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME); 4.22 + op.u.createdomain.name[MAX_DOMAIN_NAME-1] = '\0'; 4.23 + 4.24 + err = do_dom0_op(&op); 4.25 + 4.26 + return (err < 0) ? err : op.u.createdomain.domain; 4.27 +} 4.28 + 4.29 + 4.30 +int xc_domain_start(unsigned int domid) 4.31 +{ 4.32 + dom0_op_t op; 4.33 + op.cmd = DOM0_STARTDOMAIN; 4.34 + op.u.startdomain.domain = domid; 4.35 + return do_dom0_op(&op); 4.36 +} 4.37 + 4.38 + 4.39 +int xc_domain_stop(unsigned int domid) 4.40 +{ 4.41 + dom0_op_t op; 4.42 + op.cmd = DOM0_STOPDOMAIN; 4.43 + op.u.stopdomain.domain = domid; 4.44 + return do_dom0_op(&op); 4.45 +} 4.46 + 4.47 + 4.48 +int xc_domain_destroy(unsigned int domid, int force) 4.49 +{ 4.50 + dom0_op_t op; 4.51 + op.cmd = DOM0_DESTROYDOMAIN; 4.52 + op.u.destroydomain.domain = domid; 4.53 + op.u.destroydomain.force = !!force; 4.54 + return do_dom0_op(&op); 4.55 +} 4.56 + 4.57 +int xc_domain_getinfo(unsigned int first_domid, 4.58 + unsigned int max_doms, 4.59 + xc_dominfo_t *info) 4.60 +{ 4.61 + unsigned int nr_doms, next_domid = first_domid; 4.62 + dom0_op_t op; 4.63 + 4.64 + for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ ) 4.65 + { 4.66 + op.cmd = DOM0_GETDOMAININFO; 4.67 + op.u.getdomaininfo.domain = next_domid; 4.68 + if ( do_dom0_op(&op) < 0 ) 4.69 + break; 4.70 + info->domid = op.u.getdomaininfo.domain; 4.71 + info->cpu = op.u.getdomaininfo.processor; 4.72 + info->has_cpu = op.u.getdomaininfo.has_cpu; 4.73 + info->stopped = (op.u.getdomaininfo.state == DOMSTATE_STOPPED); 4.74 + info->nr_pages = op.u.getdomaininfo.tot_pages; 4.75 + info->cpu_time = op.u.getdomaininfo.cpu_time; 4.76 + strncpy(info->name, op.u.getdomaininfo.name, XC_DOMINFO_MAXNAME); 4.77 + info->name[XC_DOMINFO_MAXNAME-1] = '\0'; 4.78 + 4.79 + next_domid = op.u.getdomaininfo.domain + 1; 4.80 + } 4.81 + 4.82 + return nr_doms; 4.83 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/tools/libxc/libxc_linux_build.c Wed Nov 19 23:05:17 2003 +0000 5.3 @@ -0,0 +1,481 @@ 5.4 +/****************************************************************************** 5.5 + * libxc_linux_build.c 5.6 + */ 5.7 + 5.8 +#include "libxc_private.h" 5.9 +#include <zlib.h> 5.10 + 5.11 +/* This string is written to the head of every guest kernel image. */ 5.12 +#define GUEST_SIG "XenoGues" 5.13 +#define SIG_LEN 8 5.14 + 5.15 +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED) 5.16 +#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) 5.17 + 5.18 +static long get_tot_pages(int domid) 5.19 +{ 5.20 + dom0_op_t op; 5.21 + op.cmd = DOM0_GETDOMAININFO; 5.22 + op.u.getdomaininfo.domain = domid; 5.23 + return (do_dom0_op(&op) < 0) ? -1 : op.u.getdomaininfo.tot_pages; 5.24 +} 5.25 + 5.26 +static int get_pfn_list( 5.27 + int domid, unsigned long *pfn_buf, unsigned long max_pfns) 5.28 +{ 5.29 + dom0_op_t op; 5.30 + int ret; 5.31 + op.cmd = DOM0_GETMEMLIST; 5.32 + op.u.getmemlist.domain = domid; 5.33 + op.u.getmemlist.max_pfns = max_pfns; 5.34 + op.u.getmemlist.buffer = pfn_buf; 5.35 + 5.36 + if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 ) 5.37 + return -1; 5.38 + 5.39 + ret = do_dom0_op(&op); 5.40 + 5.41 + (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long)); 5.42 + 5.43 + return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; 5.44 +} 5.45 + 5.46 +static int send_pgupdates(mmu_update_t *updates, int nr_updates) 5.47 +{ 5.48 + int ret = -1; 5.49 + privcmd_hypercall_t hypercall; 5.50 + 5.51 + hypercall.op = __HYPERVISOR_mmu_update; 5.52 + hypercall.arg[0] = (unsigned long)updates; 5.53 + hypercall.arg[1] = (unsigned long)nr_updates; 5.54 + 5.55 + if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 ) 5.56 + goto out1; 5.57 + 5.58 + if ( do_xen_hypercall(&hypercall) < 0 ) 5.59 + goto out2; 5.60 + 5.61 + ret = 0; 5.62 + 5.63 + out2: (void)munlock(updates, nr_updates * sizeof(*updates)); 5.64 + out1: return ret; 5.65 +} 5.66 + 5.67 +/* Read the kernel header, extracting the image size and load address. */ 5.68 +static int read_kernel_header(gzFile gfd, long dom_size, 5.69 + unsigned long *load_addr, int verbose) 5.70 +{ 5.71 + char signature[SIG_LEN]; 5.72 + 5.73 + gzread(gfd, signature, SIG_LEN); 5.74 + if ( strncmp(signature, GUEST_SIG, SIG_LEN) ) 5.75 + { 5.76 + if ( verbose ) 5.77 + ERROR("Kernel image does not contain required signature"); 5.78 + return -1; 5.79 + } 5.80 + 5.81 + /* Read the load address which immediately follows the Xeno signature. */ 5.82 + gzread(gfd, load_addr, sizeof(unsigned long)); 5.83 + 5.84 + return 0; 5.85 +} 5.86 + 5.87 +static int copy_to_domain_page(unsigned long dst_pfn, void *src_page) 5.88 +{ 5.89 + void *vaddr = map_pfn(dst_pfn); 5.90 + if ( vaddr == NULL ) 5.91 + return -1; 5.92 + memcpy(vaddr, src_page, PAGE_SIZE); 5.93 + unmap_pfn(vaddr); 5.94 + return 0; 5.95 +} 5.96 + 5.97 +static int setup_guestos( 5.98 + int dom, gzFile kernel_gfd, int initrd_fd, unsigned long tot_pages, 5.99 + unsigned long *virt_startinfo_addr, unsigned long virt_load_addr, 5.100 + dom0_builddomain_t *builddomain, const char *cmdline, 5.101 + unsigned long shared_info_frame, int verbose) 5.102 +{ 5.103 + l1_pgentry_t *vl1tab = NULL, *vl1e = NULL; 5.104 + l2_pgentry_t *vl2tab = NULL, *vl2e = NULL; 5.105 + unsigned long *page_array = NULL; 5.106 + mmu_update_t *pgt_update_arr = NULL, *pgt_updates = NULL; 5.107 + int alloc_index, num_pt_pages; 5.108 + unsigned long l2tab; 5.109 + unsigned long l1tab = 0; 5.110 + unsigned long num_pgt_updates = 0; 5.111 + unsigned long count, pt_start, i, j; 5.112 + unsigned long initrd_addr = 0, initrd_len = 0; 5.113 + start_info_t *start_info; 5.114 + shared_info_t *shared_info; 5.115 + unsigned long ksize; 5.116 + 5.117 + memset(builddomain, 0, sizeof(*builddomain)); 5.118 + 5.119 + if ( init_pfn_mapper() < 0 ) 5.120 + goto error_out; 5.121 + 5.122 + pgt_updates = malloc((tot_pages + 1024) * 3 * sizeof(mmu_update_t)); 5.123 + page_array = malloc(tot_pages * sizeof(unsigned long)); 5.124 + pgt_update_arr = pgt_updates; 5.125 + if ( (pgt_update_arr == NULL) || (page_array == NULL) ) 5.126 + { 5.127 + if ( verbose ) 5.128 + PERROR("Could not allocate memory"); 5.129 + goto error_out; 5.130 + } 5.131 + 5.132 + if ( get_pfn_list(dom, page_array, tot_pages) != tot_pages ) 5.133 + { 5.134 + if ( verbose ) 5.135 + PERROR("Could not get the page frame list"); 5.136 + goto error_out; 5.137 + } 5.138 + 5.139 + /* Load the guest OS image. Let it take no more than 1/2 memory.*/ 5.140 + for ( i = 0; i < ((tot_pages/2)*PAGE_SIZE); i += PAGE_SIZE ) 5.141 + { 5.142 + char page[PAGE_SIZE]; 5.143 + int size; 5.144 + if ( (size = gzread(kernel_gfd, page, PAGE_SIZE)) == -1 ) 5.145 + { 5.146 + if ( verbose ) 5.147 + PERROR("Error reading kernel image, could not" 5.148 + " read the whole image."); 5.149 + goto error_out; 5.150 + } 5.151 + if ( size == 0 ) 5.152 + goto kernel_copied; 5.153 + copy_to_domain_page(page_array[i>>PAGE_SHIFT], page); 5.154 + } 5.155 + if ( verbose ) 5.156 + ERROR("Kernel too big to safely fit in domain memory"); 5.157 + goto error_out; 5.158 + 5.159 + kernel_copied: 5.160 + /* ksize is kernel-image size rounded up to a page boundary. */ 5.161 + ksize = i; 5.162 + 5.163 + /* Load the initial ramdisk image. */ 5.164 + if ( initrd_fd >= 0 ) 5.165 + { 5.166 + struct stat stat; 5.167 + unsigned long isize; 5.168 + 5.169 + if ( fstat(initrd_fd, &stat) < 0 ) 5.170 + { 5.171 + if ( verbose ) 5.172 + PERROR("Could not stat the initrd image"); 5.173 + goto error_out; 5.174 + } 5.175 + isize = stat.st_size; 5.176 + if ( (isize + ksize) > ((tot_pages/2) * PAGE_SIZE) ) 5.177 + { 5.178 + if ( verbose ) 5.179 + ERROR("Kernel/initrd too big to safely fit in domain memory"); 5.180 + goto error_out; 5.181 + } 5.182 + 5.183 + initrd_addr = virt_load_addr + ksize; 5.184 + initrd_len = isize; 5.185 + 5.186 + for ( j = 0, i = ksize; j < isize; j += PAGE_SIZE, i += PAGE_SIZE ) 5.187 + { 5.188 + char page[PAGE_SIZE]; 5.189 + int size = ((isize-j) < PAGE_SIZE) ? (isize-j) : PAGE_SIZE; 5.190 + if ( read(initrd_fd, page, size) != size ) 5.191 + { 5.192 + if ( verbose ) 5.193 + PERROR("Error reading initrd image, could not" 5.194 + " read the whole image."); 5.195 + goto error_out; 5.196 + } 5.197 + copy_to_domain_page(page_array[i>>PAGE_SHIFT], page); 5.198 + } 5.199 + } 5.200 + 5.201 + alloc_index = tot_pages - 1; 5.202 + 5.203 + /* Count bottom-level PTs, rounding up. */ 5.204 + num_pt_pages = (l1_table_offset(virt_load_addr) + tot_pages + 1023) / 1024; 5.205 + 5.206 + /* We must also count the page directory. */ 5.207 + num_pt_pages++; 5.208 + 5.209 + /* Index of first PT page. */ 5.210 + pt_start = tot_pages - num_pt_pages; 5.211 + 5.212 + /* 5.213 + * First allocate page for page dir. Allocation goes backwards from the end 5.214 + * of the allocated physical address space. 5.215 + */ 5.216 + l2tab = page_array[alloc_index] << PAGE_SHIFT; 5.217 + alloc_index--; 5.218 + builddomain->ctxt.pt_base = l2tab; 5.219 + 5.220 + /* 5.221 + * Pin down l2tab addr as page dir page - causes hypervisor to provide 5.222 + * correct protection for the page 5.223 + */ 5.224 + pgt_updates->ptr = l2tab | MMU_EXTENDED_COMMAND; 5.225 + pgt_updates->val = MMUEXT_PIN_L2_TABLE; 5.226 + pgt_updates++; 5.227 + num_pgt_updates++; 5.228 + 5.229 + /* Initialise the page tables. */ 5.230 + if ( (vl2tab = map_pfn(l2tab >> PAGE_SHIFT)) == NULL ) 5.231 + goto error_out; 5.232 + memset(vl2tab, 0, PAGE_SIZE); 5.233 + vl2e = vl2tab + l2_table_offset(virt_load_addr); 5.234 + for ( count = 0; count < tot_pages; count++ ) 5.235 + { 5.236 + if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) 5.237 + { 5.238 + l1tab = page_array[alloc_index] << PAGE_SHIFT; 5.239 + if ( (vl1tab = map_pfn(l1tab >> PAGE_SHIFT)) == NULL ) 5.240 + goto error_out; 5.241 + memset(vl1tab, 0, PAGE_SIZE); 5.242 + alloc_index--; 5.243 + 5.244 + vl1e = vl1tab + l1_table_offset(virt_load_addr + 5.245 + (count << PAGE_SHIFT)); 5.246 + 5.247 + /* make apropriate entry in the page directory */ 5.248 + pgt_updates->ptr = (unsigned long)vl2e; 5.249 + pgt_updates->val = l1tab | L2_PROT; 5.250 + pgt_updates++; 5.251 + num_pgt_updates++; 5.252 + vl2e++; 5.253 + } 5.254 + 5.255 + if ( count < pt_start ) 5.256 + { 5.257 + pgt_updates->ptr = (unsigned long)vl1e; 5.258 + pgt_updates->val = (page_array[count] << PAGE_SHIFT) | L1_PROT; 5.259 + pgt_updates++; 5.260 + num_pgt_updates++; 5.261 + vl1e++; 5.262 + } 5.263 + else 5.264 + { 5.265 + pgt_updates->ptr = (unsigned long)vl1e; 5.266 + pgt_updates->val = 5.267 + ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW; 5.268 + pgt_updates++; 5.269 + num_pgt_updates++; 5.270 + vl1e++; 5.271 + } 5.272 + 5.273 + pgt_updates->ptr = 5.274 + (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; 5.275 + pgt_updates->val = count; 5.276 + pgt_updates++; 5.277 + num_pgt_updates++; 5.278 + } 5.279 + 5.280 + *virt_startinfo_addr = 5.281 + virt_load_addr + ((alloc_index-1) << PAGE_SHIFT); 5.282 + 5.283 + start_info = map_pfn(page_array[alloc_index-1]); 5.284 + memset(start_info, 0, sizeof(*start_info)); 5.285 + start_info->pt_base = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT); 5.286 + start_info->mod_start = initrd_addr; 5.287 + start_info->mod_len = initrd_len; 5.288 + start_info->nr_pages = tot_pages; 5.289 + start_info->shared_info = shared_info_frame << PAGE_SHIFT; 5.290 + start_info->dom_id = dom; 5.291 + start_info->flags = 0; 5.292 + strncpy(start_info->cmd_line, cmdline, MAX_CMD_LEN); 5.293 + start_info->cmd_line[MAX_CMD_LEN-1] = '\0'; 5.294 + 5.295 + unmap_pfn(start_info); 5.296 + 5.297 + /* shared_info page starts its life empty. */ 5.298 + shared_info = map_pfn(shared_info_frame); 5.299 + memset(shared_info, 0, PAGE_SIZE); 5.300 + unmap_pfn(shared_info); 5.301 + 5.302 + /* Send the page update requests down to the hypervisor. */ 5.303 + if ( send_pgupdates(pgt_update_arr, num_pgt_updates) < 0 ) 5.304 + goto error_out; 5.305 + 5.306 + free(page_array); 5.307 + free(pgt_update_arr); 5.308 + return 0; 5.309 + 5.310 + error_out: 5.311 + if ( page_array == NULL ) 5.312 + free(page_array); 5.313 + if ( pgt_update_arr == NULL ) 5.314 + free(pgt_update_arr); 5.315 + return -1; 5.316 +} 5.317 + 5.318 +int xc_domain_build(unsigned int domid, 5.319 + const char *image_name, 5.320 + const char *ramdisk_name, 5.321 + const char *cmdline, 5.322 + int verbose) 5.323 +{ 5.324 + dom0_op_t launch_op, op; 5.325 + unsigned long load_addr; 5.326 + long tot_pages; 5.327 + int kernel_fd, initrd_fd = -1; 5.328 + gzFile kernel_gfd; 5.329 + int rc, i; 5.330 + full_execution_context_t *ctxt; 5.331 + unsigned long virt_startinfo_addr; 5.332 + 5.333 + if ( (tot_pages = get_tot_pages(domid)) < 0 ) 5.334 + { 5.335 + if ( verbose ) 5.336 + PERROR("Could not find total pages for domain"); 5.337 + return 1; 5.338 + } 5.339 + 5.340 + kernel_fd = open(image_name, O_RDONLY); 5.341 + if ( kernel_fd < 0 ) 5.342 + { 5.343 + if ( verbose ) 5.344 + PERROR("Could not open kernel image"); 5.345 + return 1; 5.346 + } 5.347 + 5.348 + if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL ) 5.349 + { 5.350 + if ( verbose ) 5.351 + PERROR("Could not allocate decompression state for state file"); 5.352 + close(kernel_fd); 5.353 + return 1; 5.354 + } 5.355 + 5.356 + rc = read_kernel_header(kernel_gfd, 5.357 + tot_pages << (PAGE_SHIFT - 10), 5.358 + &load_addr, verbose); 5.359 + if ( rc < 0 ) 5.360 + goto error_out; 5.361 + 5.362 + if ( (load_addr & (PAGE_SIZE-1)) != 0 ) 5.363 + { 5.364 + if ( verbose ) 5.365 + ERROR("We can only deal with page-aligned load addresses"); 5.366 + goto error_out; 5.367 + } 5.368 + 5.369 + if ( (load_addr + (tot_pages << PAGE_SHIFT)) > HYPERVISOR_VIRT_START ) 5.370 + { 5.371 + if ( verbose ) 5.372 + ERROR("Cannot map all domain memory without hitting Xen space"); 5.373 + goto error_out; 5.374 + } 5.375 + 5.376 + if ( ramdisk_name != NULL ) 5.377 + { 5.378 + initrd_fd = open(ramdisk_name, O_RDONLY); 5.379 + if ( initrd_fd < 0 ) 5.380 + { 5.381 + if ( verbose ) 5.382 + PERROR("Could not open the initial ramdisk image"); 5.383 + goto error_out; 5.384 + } 5.385 + } 5.386 + 5.387 + op.cmd = DOM0_GETDOMAININFO; 5.388 + op.u.getdomaininfo.domain = domid; 5.389 + if ( (do_dom0_op(&op) < 0) || (op.u.getdomaininfo.domain != domid) ) 5.390 + { 5.391 + if ( verbose ) 5.392 + PERROR("Could not get info on domain"); 5.393 + goto error_out; 5.394 + } 5.395 + if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) || 5.396 + (op.u.getdomaininfo.ctxt.pt_base != 0) ) 5.397 + { 5.398 + if ( verbose ) 5.399 + ERROR("Domain is already constructed"); 5.400 + goto error_out; 5.401 + } 5.402 + 5.403 + if ( setup_guestos(domid, kernel_gfd, initrd_fd, tot_pages, 5.404 + &virt_startinfo_addr, 5.405 + load_addr, &launch_op.u.builddomain, cmdline, 5.406 + op.u.getdomaininfo.shared_info_frame, verbose) < 0 ) 5.407 + { 5.408 + if ( verbose ) 5.409 + ERROR("Error constructing guest OS"); 5.410 + goto error_out; 5.411 + } 5.412 + 5.413 + if ( initrd_fd >= 0 ) 5.414 + close(initrd_fd); 5.415 + gzclose(kernel_gfd); 5.416 + 5.417 + ctxt = &launch_op.u.builddomain.ctxt; 5.418 + 5.419 + ctxt->flags = 0; 5.420 + 5.421 + /* 5.422 + * Initial register values: 5.423 + * DS,ES,FS,GS = FLAT_RING1_DS 5.424 + * CS:EIP = FLAT_RING1_CS:start_pc 5.425 + * SS:ESP = FLAT_RING1_DS:start_stack 5.426 + * ESI = start_info 5.427 + * [EAX,EBX,ECX,EDX,EDI,EBP are zero] 5.428 + * EFLAGS = IF | 2 (bit 1 is reserved and should always be 1) 5.429 + */ 5.430 + ctxt->i386_ctxt.ds = FLAT_RING1_DS; 5.431 + ctxt->i386_ctxt.es = FLAT_RING1_DS; 5.432 + ctxt->i386_ctxt.fs = FLAT_RING1_DS; 5.433 + ctxt->i386_ctxt.gs = FLAT_RING1_DS; 5.434 + ctxt->i386_ctxt.ss = FLAT_RING1_DS; 5.435 + ctxt->i386_ctxt.cs = FLAT_RING1_CS; 5.436 + ctxt->i386_ctxt.eip = load_addr; 5.437 + ctxt->i386_ctxt.esp = virt_startinfo_addr; 5.438 + ctxt->i386_ctxt.esi = virt_startinfo_addr; 5.439 + ctxt->i386_ctxt.eflags = (1<<9) | (1<<2); 5.440 + 5.441 + /* FPU is set up to default initial state. */ 5.442 + memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt)); 5.443 + 5.444 + /* Virtual IDT is empty at start-of-day. */ 5.445 + for ( i = 0; i < 256; i++ ) 5.446 + { 5.447 + ctxt->trap_ctxt[i].vector = i; 5.448 + ctxt->trap_ctxt[i].cs = FLAT_RING1_CS; 5.449 + } 5.450 + ctxt->fast_trap_idx = 0; 5.451 + 5.452 + /* No LDT. */ 5.453 + ctxt->ldt_ents = 0; 5.454 + 5.455 + /* Use the default Xen-provided GDT. */ 5.456 + ctxt->gdt_ents = 0; 5.457 + 5.458 + /* Ring 1 stack is the initial stack. */ 5.459 + ctxt->ring1_ss = FLAT_RING1_DS; 5.460 + ctxt->ring1_esp = virt_startinfo_addr; 5.461 + 5.462 + /* No debugging. */ 5.463 + memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg)); 5.464 + 5.465 + /* No callback handlers. */ 5.466 + ctxt->event_callback_cs = FLAT_RING1_CS; 5.467 + ctxt->event_callback_eip = 0; 5.468 + ctxt->failsafe_callback_cs = FLAT_RING1_CS; 5.469 + ctxt->failsafe_callback_eip = 0; 5.470 + 5.471 + launch_op.u.builddomain.domain = domid; 5.472 + launch_op.u.builddomain.num_vifs = 1; 5.473 + 5.474 + launch_op.cmd = DOM0_BUILDDOMAIN; 5.475 + rc = do_dom0_op(&launch_op); 5.476 + 5.477 + return rc; 5.478 + 5.479 + error_out: 5.480 + if ( initrd_fd >= 0 ) 5.481 + close(initrd_fd); 5.482 + gzclose(kernel_gfd); 5.483 + return -1; 5.484 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/tools/libxc/libxc_linux_restore.c Wed Nov 19 23:05:17 2003 +0000 6.3 @@ -0,0 +1,476 @@ 6.4 +/****************************************************************************** 6.5 + * libxc_linux_restore.c 6.6 + * 6.7 + * Restore the state of a Xenolinux session. 6.8 + * 6.9 + * Copyright (c) 2003, K A Fraser. 6.10 + */ 6.11 + 6.12 +#include "libxc_private.h" 6.13 +#include <asm-xeno/suspend.h> 6.14 +#include <zlib.h> 6.15 + 6.16 +/* This may allow us to create a 'quiet' command-line option, if necessary. */ 6.17 +#define verbose_printf(_f, _a...) \ 6.18 + do { \ 6.19 + if ( !verbose ) break; \ 6.20 + printf( _f , ## _a ); \ 6.21 + fflush(stdout); \ 6.22 + } while ( 0 ) 6.23 + 6.24 +static int get_pfn_list( 6.25 + int domain_id, unsigned long *pfn_buf, unsigned long max_pfns) 6.26 +{ 6.27 + dom0_op_t op; 6.28 + int ret; 6.29 + op.cmd = DOM0_GETMEMLIST; 6.30 + op.u.getmemlist.domain = domain_id; 6.31 + op.u.getmemlist.max_pfns = max_pfns; 6.32 + op.u.getmemlist.buffer = pfn_buf; 6.33 + 6.34 + if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 ) 6.35 + { 6.36 + PERROR("Could not lock pfn list buffer"); 6.37 + return -1; 6.38 + } 6.39 + 6.40 + ret = do_dom0_op(&op); 6.41 + 6.42 + (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long)); 6.43 + 6.44 + return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; 6.45 +} 6.46 + 6.47 +#define MAX_MMU_UPDATES 1024 6.48 + 6.49 +static int flush_mmu_updates(mmu_update_t *mmu_updates, 6.50 + int *mmu_update_idx) 6.51 +{ 6.52 + int err = 0; 6.53 + privcmd_hypercall_t hypercall; 6.54 + 6.55 + if ( *mmu_update_idx == 0 ) 6.56 + return 0; 6.57 + 6.58 + hypercall.op = __HYPERVISOR_mmu_update; 6.59 + hypercall.arg[0] = (unsigned long)mmu_updates; 6.60 + hypercall.arg[1] = (unsigned long)*mmu_update_idx; 6.61 + 6.62 + if ( mlock(mmu_updates, sizeof(mmu_updates)) != 0 ) 6.63 + { 6.64 + PERROR("Could not lock pagetable update array"); 6.65 + err = 1; 6.66 + goto out; 6.67 + } 6.68 + 6.69 + if ( do_xen_hypercall(&hypercall) < 0 ) 6.70 + { 6.71 + ERROR("Failure when submitting mmu updates"); 6.72 + err = 1; 6.73 + } 6.74 + 6.75 + *mmu_update_idx = 0; 6.76 + 6.77 + (void)munlock(mmu_updates, sizeof(mmu_updates)); 6.78 + 6.79 + out: 6.80 + return err; 6.81 +} 6.82 + 6.83 +static int add_mmu_update(mmu_update_t *mmu_updates, 6.84 + int *mmu_update_idx, 6.85 + unsigned long ptr, 6.86 + unsigned long val) 6.87 +{ 6.88 + mmu_updates[*mmu_update_idx].ptr = ptr; 6.89 + mmu_updates[*mmu_update_idx].val = val; 6.90 + if ( ++*mmu_update_idx == MAX_MMU_UPDATES ) 6.91 + return flush_mmu_updates(mmu_updates, mmu_update_idx); 6.92 + return 0; 6.93 +} 6.94 + 6.95 +static int checked_read(gzFile fd, void *buf, size_t count) 6.96 +{ 6.97 + int rc; 6.98 + while ( ((rc = gzread(fd, buf, count)) == -1) && (errno == EINTR) ) 6.99 + continue; 6.100 + return rc == count; 6.101 +} 6.102 + 6.103 +int xc_linux_restore(const char *state_file, int verbose) 6.104 +{ 6.105 + dom0_op_t op; 6.106 + int rc = 1, i, j; 6.107 + unsigned long mfn, pfn, dom = 0; 6.108 + unsigned int prev_pc, this_pc; 6.109 + 6.110 + /* Number of page frames in use by this XenoLinux session. */ 6.111 + unsigned long nr_pfns; 6.112 + 6.113 + /* The new domain's shared-info frame number. */ 6.114 + unsigned long shared_info_frame; 6.115 + unsigned char shared_info[PAGE_SIZE]; /* saved contents from file */ 6.116 + 6.117 + /* A copy of the CPU context of the guest. */ 6.118 + full_execution_context_t ctxt; 6.119 + 6.120 + /* First 16 bytes of the state file must contain 'XenoLinuxSuspend'. */ 6.121 + char signature[16]; 6.122 + 6.123 + /* A copy of the domain's name. */ 6.124 + char name[MAX_DOMAIN_NAME]; 6.125 + 6.126 + /* A table containg the type of each PFN (/not/ MFN!). */ 6.127 + unsigned long *pfn_type = NULL; 6.128 + 6.129 + /* A temporary mapping, and a copy, of one frame of guest memory. */ 6.130 + unsigned long *ppage, page[1024]; 6.131 + 6.132 + /* A copy of the pfn-to-mfn table frame list. */ 6.133 + unsigned long pfn_to_mfn_frame_list[1024]; 6.134 + 6.135 + /* A table mapping each PFN to its new MFN. */ 6.136 + unsigned long *pfn_to_mfn_table = NULL; 6.137 + 6.138 + /* A temporary mapping of the guest's suspend record. */ 6.139 + suspend_record_t *p_srec; 6.140 + 6.141 + /* The name and descriptor of the file that we are reading from. */ 6.142 + int fd; 6.143 + gzFile gfd; 6.144 + 6.145 + mmu_update_t mmu_updates[MAX_MMU_UPDATES]; 6.146 + int mmu_update_idx = 0; 6.147 + 6.148 + if ( (fd = open(state_file, O_RDONLY)) == -1 ) 6.149 + { 6.150 + PERROR("Could not open state file for reading"); 6.151 + return 1; 6.152 + } 6.153 + 6.154 + if ( (gfd = gzdopen(fd, "rb")) == NULL ) 6.155 + { 6.156 + ERROR("Could not allocate decompression state for state file"); 6.157 + close(fd); 6.158 + return 1; 6.159 + } 6.160 + 6.161 + /* Start writing out the saved-domain record. */ 6.162 + if ( !checked_read(gfd, signature, 16) || 6.163 + (memcmp(signature, "XenoLinuxSuspend", 16) != 0) ) 6.164 + { 6.165 + ERROR("Unrecognised state format -- no signature found"); 6.166 + goto out; 6.167 + } 6.168 + 6.169 + if ( !checked_read(gfd, name, sizeof(name)) || 6.170 + !checked_read(gfd, &nr_pfns, sizeof(unsigned long)) || 6.171 + !checked_read(gfd, &ctxt, sizeof(ctxt)) || 6.172 + !checked_read(gfd, shared_info, PAGE_SIZE) || 6.173 + !checked_read(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) ) 6.174 + { 6.175 + ERROR("Error when reading from state file"); 6.176 + goto out; 6.177 + } 6.178 + 6.179 + for ( i = 0; i < MAX_DOMAIN_NAME; i++ ) 6.180 + { 6.181 + if ( name[i] == '\0' ) break; 6.182 + if ( name[i] & 0x80 ) 6.183 + { 6.184 + ERROR("Random characters in domain name"); 6.185 + goto out; 6.186 + } 6.187 + } 6.188 + name[MAX_DOMAIN_NAME-1] = '\0'; 6.189 + 6.190 + if ( nr_pfns > 1024*1024 ) 6.191 + { 6.192 + ERROR("Invalid state file -- pfn count out of range"); 6.193 + goto out; 6.194 + } 6.195 + 6.196 + /* We want zeroed memory so use calloc rather than malloc. */ 6.197 + pfn_to_mfn_table = calloc(1, 4 * nr_pfns); 6.198 + pfn_type = calloc(1, 4 * nr_pfns); 6.199 + 6.200 + if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) ) 6.201 + { 6.202 + errno = ENOMEM; 6.203 + goto out; 6.204 + } 6.205 + 6.206 + if ( !checked_read(gfd, pfn_type, 4 * nr_pfns) ) 6.207 + { 6.208 + ERROR("Error when reading from state file"); 6.209 + goto out; 6.210 + } 6.211 + 6.212 + /* Create a new domain of the appropriate size, and find it's dom_id. */ 6.213 + op.cmd = DOM0_CREATEDOMAIN; 6.214 + op.u.createdomain.memory_kb = nr_pfns * (PAGE_SIZE / 1024); 6.215 + memcpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME); 6.216 + if ( do_dom0_op(&op) < 0 ) 6.217 + { 6.218 + ERROR("Could not create new domain"); 6.219 + goto out; 6.220 + } 6.221 + dom = op.u.createdomain.domain; 6.222 + 6.223 + /* Get the domain's shared-info frame. */ 6.224 + op.cmd = DOM0_GETDOMAININFO; 6.225 + op.u.getdomaininfo.domain = dom; 6.226 + if ( do_dom0_op(&op) < 0 ) 6.227 + { 6.228 + ERROR("Could not get information on new domain"); 6.229 + goto out; 6.230 + } 6.231 + shared_info_frame = op.u.getdomaininfo.shared_info_frame; 6.232 + 6.233 + if ( init_pfn_mapper() < 0 ) 6.234 + goto out; 6.235 + 6.236 + /* Copy saved contents of shared-info page. No checking needed. */ 6.237 + ppage = map_pfn(shared_info_frame); 6.238 + memcpy(ppage, shared_info, PAGE_SIZE); 6.239 + unmap_pfn(ppage); 6.240 + 6.241 + /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */ 6.242 + if ( get_pfn_list(dom, pfn_to_mfn_table, nr_pfns) != nr_pfns ) 6.243 + { 6.244 + ERROR("Did not read correct number of frame numbers for new dom"); 6.245 + goto out; 6.246 + } 6.247 + 6.248 + verbose_printf("Reloading memory pages: 0%%"); 6.249 + 6.250 + /* 6.251 + * Now simply read each saved frame into its new machine frame. 6.252 + * We uncanonicalise page tables as we go. 6.253 + */ 6.254 + prev_pc = 0; 6.255 + for ( i = 0; i < nr_pfns; i++ ) 6.256 + { 6.257 + this_pc = (i * 100) / nr_pfns; 6.258 + if ( (this_pc - prev_pc) >= 5 ) 6.259 + { 6.260 + verbose_printf("\b\b\b\b%3d%%", this_pc); 6.261 + prev_pc = this_pc; 6.262 + } 6.263 + 6.264 + mfn = pfn_to_mfn_table[i]; 6.265 + 6.266 + if ( !checked_read(gfd, page, PAGE_SIZE) ) 6.267 + { 6.268 + ERROR("Error when reading from state file"); 6.269 + goto out; 6.270 + } 6.271 + 6.272 + ppage = map_pfn(mfn); 6.273 + switch ( pfn_type[i] ) 6.274 + { 6.275 + case L1TAB: 6.276 + memset(ppage, 0, PAGE_SIZE); 6.277 + if ( add_mmu_update(mmu_updates, &mmu_update_idx, 6.278 + (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND, 6.279 + MMUEXT_PIN_L1_TABLE) ) 6.280 + goto out; 6.281 + for ( j = 0; j < 1024; j++ ) 6.282 + { 6.283 + if ( page[j] & _PAGE_PRESENT ) 6.284 + { 6.285 + if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns ) 6.286 + { 6.287 + ERROR("Frame number in page table is out of range"); 6.288 + goto out; 6.289 + } 6.290 + if ( (pfn_type[pfn] != NONE) && (page[j] & _PAGE_RW) ) 6.291 + { 6.292 + ERROR("Write access requested for a restricted frame"); 6.293 + goto out; 6.294 + } 6.295 + page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT); 6.296 + page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT; 6.297 + } 6.298 + if ( add_mmu_update(mmu_updates, &mmu_update_idx, 6.299 + (unsigned long)&ppage[j], page[j]) ) 6.300 + goto out; 6.301 + } 6.302 + break; 6.303 + case L2TAB: 6.304 + memset(ppage, 0, PAGE_SIZE); 6.305 + if ( add_mmu_update(mmu_updates, &mmu_update_idx, 6.306 + (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND, 6.307 + MMUEXT_PIN_L2_TABLE) ) 6.308 + goto out; 6.309 + for ( j = 0; j < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); j++ ) 6.310 + { 6.311 + if ( page[j] & _PAGE_PRESENT ) 6.312 + { 6.313 + if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns ) 6.314 + { 6.315 + ERROR("Frame number in page table is out of range"); 6.316 + goto out; 6.317 + } 6.318 + if ( pfn_type[pfn] != L1TAB ) 6.319 + { 6.320 + ERROR("Page table mistyping"); 6.321 + goto out; 6.322 + } 6.323 + /* Haven't reached the L1 table yet. Ensure it is safe! */ 6.324 + if ( pfn > i ) 6.325 + { 6.326 + unsigned long **l1 = map_pfn(pfn_to_mfn_table[pfn]); 6.327 + memset(l1, 0, PAGE_SIZE); 6.328 + unmap_pfn(l1); 6.329 + } 6.330 + page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE); 6.331 + page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT; 6.332 + } 6.333 + if ( add_mmu_update(mmu_updates, &mmu_update_idx, 6.334 + (unsigned long)&ppage[j], page[j]) ) 6.335 + goto out; 6.336 + } 6.337 + break; 6.338 + default: 6.339 + memcpy(ppage, page, PAGE_SIZE); 6.340 + break; 6.341 + } 6.342 + /* NB. Must flush before unmapping page, as pass VAs to Xen. */ 6.343 + if ( flush_mmu_updates(mmu_updates, &mmu_update_idx) ) 6.344 + goto out; 6.345 + unmap_pfn(ppage); 6.346 + 6.347 + if ( add_mmu_update(mmu_updates, &mmu_update_idx, 6.348 + (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, i) ) 6.349 + goto out; 6.350 + } 6.351 + 6.352 + if ( flush_mmu_updates(mmu_updates, &mmu_update_idx) ) 6.353 + goto out; 6.354 + 6.355 + verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n"); 6.356 + 6.357 + /* Uncanonicalise the suspend-record frame number and poke resume rec. */ 6.358 + pfn = ctxt.i386_ctxt.esi; 6.359 + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) ) 6.360 + { 6.361 + ERROR("Suspend record frame number is bad"); 6.362 + goto out; 6.363 + } 6.364 + ctxt.i386_ctxt.esi = mfn = pfn_to_mfn_table[pfn]; 6.365 + p_srec = map_pfn(mfn); 6.366 + p_srec->resume_info.nr_pages = nr_pfns; 6.367 + p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT; 6.368 + p_srec->resume_info.dom_id = dom; 6.369 + p_srec->resume_info.flags = 0; 6.370 + unmap_pfn(p_srec); 6.371 + 6.372 + /* Uncanonicalise each GDT frame number. */ 6.373 + if ( ctxt.gdt_ents > 8192 ) 6.374 + { 6.375 + ERROR("GDT entry count out of range"); 6.376 + goto out; 6.377 + } 6.378 + for ( i = 0; i < ctxt.gdt_ents; i += 512 ) 6.379 + { 6.380 + pfn = ctxt.gdt_frames[i]; 6.381 + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) ) 6.382 + { 6.383 + ERROR("GDT frame number is bad"); 6.384 + goto out; 6.385 + } 6.386 + ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn]; 6.387 + } 6.388 + 6.389 + /* Uncanonicalise the page table base pointer. */ 6.390 + pfn = ctxt.pt_base >> PAGE_SHIFT; 6.391 + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) ) 6.392 + { 6.393 + ERROR("PT base is bad"); 6.394 + goto out; 6.395 + } 6.396 + ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT; 6.397 + 6.398 + /* Uncanonicalise the pfn-to-mfn table frame-number list. */ 6.399 + for ( i = 0; i < nr_pfns; i += 1024 ) 6.400 + { 6.401 + unsigned long copy_size = (nr_pfns - i) * sizeof(unsigned long); 6.402 + if ( copy_size > PAGE_SIZE ) copy_size = PAGE_SIZE; 6.403 + pfn = pfn_to_mfn_frame_list[i/1024]; 6.404 + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) ) 6.405 + { 6.406 + ERROR("PFN-to-MFN frame number is bad"); 6.407 + goto out; 6.408 + } 6.409 + ppage = map_pfn(pfn_to_mfn_table[pfn]); 6.410 + memcpy(ppage, &pfn_to_mfn_table[i], copy_size); 6.411 + unmap_pfn(ppage); 6.412 + } 6.413 + 6.414 + /* 6.415 + * Safety checking of saved context: 6.416 + * 1. i386_ctxt is fine, as Xen checks that on context switch. 6.417 + * 2. i387_ctxt is fine, as it can't hurt Xen. 6.418 + * 3. trap_ctxt needs the code selectors checked. 6.419 + * 4. fast_trap_idx is checked by Xen. 6.420 + * 5. ldt base must be page-aligned, no more than 8192 ents, ... 6.421 + * 6. gdt already done, and further checking is done by Xen. 6.422 + * 7. check that ring1_ss is safe. 6.423 + * 8. pt_base is already done. 6.424 + * 9. debugregs are checked by Xen. 6.425 + * 10. callback code selectors need checking. 6.426 + */ 6.427 + for ( i = 0; i < 256; i++ ) 6.428 + { 6.429 + ctxt.trap_ctxt[i].vector = i; 6.430 + if ( (ctxt.trap_ctxt[i].cs & 3) == 0 ) 6.431 + ctxt.trap_ctxt[i].cs = FLAT_RING1_CS; 6.432 + } 6.433 + if ( (ctxt.ring1_ss & 3) == 0 ) 6.434 + ctxt.ring1_ss = FLAT_RING1_DS; 6.435 + if ( (ctxt.event_callback_cs & 3) == 0 ) 6.436 + ctxt.event_callback_cs = FLAT_RING1_CS; 6.437 + if ( (ctxt.failsafe_callback_cs & 3) == 0 ) 6.438 + ctxt.failsafe_callback_cs = FLAT_RING1_CS; 6.439 + if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) || 6.440 + (ctxt.ldt_ents > 8192) || 6.441 + (ctxt.ldt_base > HYPERVISOR_VIRT_START) || 6.442 + ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) ) 6.443 + { 6.444 + ERROR("Bad LDT base or size"); 6.445 + goto out; 6.446 + } 6.447 + 6.448 + op.cmd = DOM0_BUILDDOMAIN; 6.449 + op.u.builddomain.domain = dom; 6.450 + op.u.builddomain.num_vifs = 1; 6.451 + memcpy(&op.u.builddomain.ctxt, &ctxt, sizeof(ctxt)); 6.452 + rc = do_dom0_op(&op); 6.453 + 6.454 + out: 6.455 + if ( rc != 0 ) 6.456 + { 6.457 + if ( dom != 0 ) 6.458 + { 6.459 + op.cmd = DOM0_DESTROYDOMAIN; 6.460 + op.u.destroydomain.domain = dom; 6.461 + op.u.destroydomain.force = 1; 6.462 + (void)do_dom0_op(&op); 6.463 + } 6.464 + } 6.465 + else 6.466 + { 6.467 + /* Success: print the domain id. */ 6.468 + verbose_printf("DOM=%ld\n", dom); 6.469 + } 6.470 + 6.471 + if ( pfn_to_mfn_table != NULL ) 6.472 + free(pfn_to_mfn_table); 6.473 + if ( pfn_type != NULL ) 6.474 + free(pfn_type); 6.475 + 6.476 + gzclose(gfd); 6.477 + 6.478 + return (rc == 0) ? dom : rc; 6.479 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/tools/libxc/libxc_linux_save.c Wed Nov 19 23:05:17 2003 +0000 7.3 @@ -0,0 +1,380 @@ 7.4 +/****************************************************************************** 7.5 + * libxc_linux_save.c 7.6 + * 7.7 + * Save the state of a running Xenolinux session. 7.8 + * 7.9 + * Copyright (c) 2003, K A Fraser. 7.10 + */ 7.11 + 7.12 +#include "libxc_private.h" 7.13 +#include <asm-xeno/suspend.h> 7.14 +#include <zlib.h> 7.15 + 7.16 +/* This may allow us to create a 'quiet' command-line option, if necessary. */ 7.17 +#define verbose_printf(_f, _a...) \ 7.18 + do { \ 7.19 + if ( !verbose ) break; \ 7.20 + printf( _f , ## _a ); \ 7.21 + fflush(stdout); \ 7.22 + } while ( 0 ) 7.23 + 7.24 +/* 7.25 + * Returns TRUE if the given machine frame number has a unique mapping 7.26 + * in the guest's pseudophysical map. 7.27 + */ 7.28 +#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \ 7.29 + (((_mfn) < (1024*1024)) && \ 7.30 + (pfn_to_mfn_table[mfn_to_pfn_table[_mfn]] == (_mfn))) 7.31 + 7.32 +/* Returns TRUE if MFN is successfully converted to a PFN. */ 7.33 +#define translate_mfn_to_pfn(_pmfn) \ 7.34 +({ \ 7.35 + unsigned long mfn = *(_pmfn); \ 7.36 + int _res = 1; \ 7.37 + if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) \ 7.38 + _res = 0; \ 7.39 + else \ 7.40 + *(_pmfn) = mfn_to_pfn_table[mfn]; \ 7.41 + _res; \ 7.42 +}) 7.43 + 7.44 +static int check_pfn_ownership(unsigned long mfn, unsigned int dom) 7.45 +{ 7.46 + dom0_op_t op; 7.47 + op.cmd = DOM0_GETPAGEFRAMEINFO; 7.48 + op.u.getpageframeinfo.pfn = mfn; 7.49 + if ( (do_dom0_op(&op) < 0) || (op.u.getpageframeinfo.domain != dom) ) 7.50 + return 0; 7.51 + return 1; 7.52 +} 7.53 + 7.54 +#define GETPFN_ERR (~0U) 7.55 +static unsigned int get_pfn_type(unsigned long mfn) 7.56 +{ 7.57 + dom0_op_t op; 7.58 + op.cmd = DOM0_GETPAGEFRAMEINFO; 7.59 + op.u.getpageframeinfo.pfn = mfn; 7.60 + if ( do_dom0_op(&op) < 0 ) 7.61 + { 7.62 + PERROR("Unexpected failure when getting page frame info!"); 7.63 + return GETPFN_ERR; 7.64 + } 7.65 + return op.u.getpageframeinfo.type; 7.66 +} 7.67 + 7.68 +static int checked_write(gzFile fd, void *buf, size_t count) 7.69 +{ 7.70 + int rc; 7.71 + while ( ((rc = gzwrite(fd, buf, count)) == -1) && (errno = EINTR) ) 7.72 + continue; 7.73 + return rc == count; 7.74 +} 7.75 + 7.76 +int xc_linux_save(unsigned int domid, const char *state_file, int verbose) 7.77 +{ 7.78 + dom0_op_t op; 7.79 + int rc = 1, i, j; 7.80 + unsigned long mfn; 7.81 + unsigned int prev_pc, this_pc; 7.82 + 7.83 + /* Remember if we stopped the guest, so we can restart it on exit. */ 7.84 + int we_stopped_it = 0; 7.85 + 7.86 + /* The new domain's shared-info frame number. */ 7.87 + unsigned long shared_info_frame; 7.88 + 7.89 + /* A copy of the CPU context of the guest. */ 7.90 + full_execution_context_t ctxt; 7.91 + 7.92 + /* A copy of the domain's name. */ 7.93 + char name[MAX_DOMAIN_NAME]; 7.94 + 7.95 + /* A table containg the type of each PFN (/not/ MFN!). */ 7.96 + unsigned long *pfn_type = NULL; 7.97 + 7.98 + /* A temporary mapping, and a copy, of one frame of guest memory. */ 7.99 + unsigned long *ppage, page[1024]; 7.100 + 7.101 + /* A temporary mapping, and a copy, of the pfn-to-mfn table frame list. */ 7.102 + unsigned long *p_pfn_to_mfn_frame_list, pfn_to_mfn_frame_list[1024]; 7.103 + /* A temporary mapping of one frame in the above list. */ 7.104 + unsigned long *pfn_to_mfn_frame; 7.105 + 7.106 + /* A table mapping each PFN to its current MFN. */ 7.107 + unsigned long *pfn_to_mfn_table = NULL; 7.108 + /* A table mapping each current MFN to its canonical PFN. */ 7.109 + unsigned long *mfn_to_pfn_table = NULL; 7.110 + 7.111 + /* A temporary mapping, and a copy, of the guest's suspend record. */ 7.112 + suspend_record_t *p_srec, srec; 7.113 + 7.114 + /* The name and descriptor of the file that we are writing to. */ 7.115 + int fd; 7.116 + gzFile gfd; 7.117 + 7.118 + if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 ) 7.119 + { 7.120 + PERROR("Could not open file for writing"); 7.121 + return 1; 7.122 + } 7.123 + 7.124 + /* 7.125 + * Compression rate 1: we want speed over compression. We're mainly going 7.126 + * for those zero pages, after all. 7.127 + */ 7.128 + if ( (gfd = gzdopen(fd, "wb1")) == NULL ) 7.129 + { 7.130 + ERROR("Could not allocate compression state for state file"); 7.131 + close(fd); 7.132 + return 1; 7.133 + } 7.134 + 7.135 + /* Ensure that the domain exists, and that it is stopped. */ 7.136 + for ( ; ; ) 7.137 + { 7.138 + op.cmd = DOM0_GETDOMAININFO; 7.139 + op.u.getdomaininfo.domain = domid; 7.140 + if ( (do_dom0_op(&op) < 0) || (op.u.getdomaininfo.domain != domid) ) 7.141 + { 7.142 + PERROR("Could not get info on domain"); 7.143 + goto out; 7.144 + } 7.145 + 7.146 + memcpy(&ctxt, &op.u.getdomaininfo.ctxt, sizeof(ctxt)); 7.147 + memcpy(name, op.u.getdomaininfo.name, sizeof(name)); 7.148 + shared_info_frame = op.u.getdomaininfo.shared_info_frame; 7.149 + 7.150 + if ( op.u.getdomaininfo.state == DOMSTATE_STOPPED ) 7.151 + break; 7.152 + 7.153 + we_stopped_it = 1; 7.154 + 7.155 + op.cmd = DOM0_STOPDOMAIN; 7.156 + op.u.stopdomain.domain = domid; 7.157 + (void)do_dom0_op(&op); 7.158 + 7.159 + sleep(1); 7.160 + } 7.161 + 7.162 + /* A cheesy test to see whether the domain contains valid state. */ 7.163 + if ( ctxt.pt_base == 0 ) 7.164 + { 7.165 + ERROR("Domain is not in a valid Xenolinux state"); 7.166 + goto out; 7.167 + } 7.168 + 7.169 + if ( init_pfn_mapper() < 0 ) 7.170 + goto out; 7.171 + 7.172 + /* Is the suspend-record MFN actually valid for this domain? */ 7.173 + if ( !check_pfn_ownership(ctxt.i386_ctxt.esi, domid) ) 7.174 + { 7.175 + ERROR("Invalid state record pointer"); 7.176 + goto out; 7.177 + } 7.178 + 7.179 + /* If the suspend-record MFN is okay then grab a copy of it to @srec. */ 7.180 + p_srec = map_pfn(ctxt.i386_ctxt.esi); 7.181 + memcpy(&srec, p_srec, sizeof(srec)); 7.182 + unmap_pfn(p_srec); 7.183 + 7.184 + if ( srec.nr_pfns > 1024*1024 ) 7.185 + { 7.186 + ERROR("Invalid state record -- pfn count out of range"); 7.187 + goto out; 7.188 + } 7.189 + 7.190 + if ( !check_pfn_ownership(srec.pfn_to_mfn_frame_list, domid) ) 7.191 + { 7.192 + ERROR("Invalid pfn-to-mfn frame list pointer"); 7.193 + goto out; 7.194 + } 7.195 + 7.196 + /* Grab a copy of the pfn-to-mfn table frame list. */ 7.197 + p_pfn_to_mfn_frame_list = map_pfn(srec.pfn_to_mfn_frame_list); 7.198 + memcpy(pfn_to_mfn_frame_list, p_pfn_to_mfn_frame_list, PAGE_SIZE); 7.199 + unmap_pfn(p_pfn_to_mfn_frame_list); 7.200 + 7.201 + /* We want zeroed memory so use calloc rather than malloc. */ 7.202 + mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024); 7.203 + pfn_to_mfn_table = calloc(1, 4 * srec.nr_pfns); 7.204 + pfn_type = calloc(1, 4 * srec.nr_pfns); 7.205 + 7.206 + if ( (mfn_to_pfn_table == NULL) || 7.207 + (pfn_to_mfn_table == NULL) || 7.208 + (pfn_type == NULL) ) 7.209 + { 7.210 + errno = ENOMEM; 7.211 + goto out; 7.212 + } 7.213 + 7.214 + 7.215 + /* 7.216 + * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this 7.217 + * loop we have each MFN mapped at most once. Note that there may be MFNs 7.218 + * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP. 7.219 + */ 7.220 + pfn_to_mfn_frame = NULL; 7.221 + for ( i = 0; i < srec.nr_pfns; i++ ) 7.222 + { 7.223 + /* Each frameful of table frames must be checked & mapped on demand. */ 7.224 + if ( (i & 1023) == 0 ) 7.225 + { 7.226 + mfn = pfn_to_mfn_frame_list[i/1024]; 7.227 + if ( !check_pfn_ownership(mfn, domid) ) 7.228 + { 7.229 + ERROR("Invalid frame number if pfn-to-mfn frame list"); 7.230 + goto out; 7.231 + } 7.232 + if ( pfn_to_mfn_frame != NULL ) 7.233 + unmap_pfn(pfn_to_mfn_frame); 7.234 + pfn_to_mfn_frame = map_pfn(mfn); 7.235 + } 7.236 + 7.237 + mfn = pfn_to_mfn_frame[i & 1023]; 7.238 + 7.239 + if ( !check_pfn_ownership(mfn, domid) ) 7.240 + { 7.241 + ERROR("Invalid frame specified with pfn-to-mfn table"); 7.242 + goto out; 7.243 + } 7.244 + 7.245 + /* Did we map this MFN already? That would be invalid! */ 7.246 + if ( MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) 7.247 + { 7.248 + ERROR("A machine frame appears twice in pseudophys space"); 7.249 + goto out; 7.250 + } 7.251 + 7.252 + pfn_to_mfn_table[i] = mfn; 7.253 + mfn_to_pfn_table[mfn] = i; 7.254 + 7.255 + /* Query page type by MFN, but store it by PFN. */ 7.256 + if ( (pfn_type[i] = get_pfn_type(mfn)) == GETPFN_ERR ) 7.257 + goto out; 7.258 + } 7.259 + 7.260 + /* Canonicalise the suspend-record frame number. */ 7.261 + if ( !translate_mfn_to_pfn(&ctxt.i386_ctxt.esi) ) 7.262 + { 7.263 + ERROR("State record is not in range of pseudophys map"); 7.264 + goto out; 7.265 + } 7.266 + 7.267 + /* Canonicalise each GDT frame number. */ 7.268 + for ( i = 0; i < ctxt.gdt_ents; i += 512 ) 7.269 + { 7.270 + if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) ) 7.271 + { 7.272 + ERROR("GDT frame is not in range of pseudophys map"); 7.273 + goto out; 7.274 + } 7.275 + } 7.276 + 7.277 + /* Canonicalise the page table base pointer. */ 7.278 + if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) ) 7.279 + { 7.280 + ERROR("PT base is not in range of pseudophys map"); 7.281 + goto out; 7.282 + } 7.283 + ctxt.pt_base = mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT; 7.284 + 7.285 + /* Canonicalise the pfn-to-mfn table frame-number list. */ 7.286 + for ( i = 0; i < srec.nr_pfns; i += 1024 ) 7.287 + { 7.288 + if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) ) 7.289 + { 7.290 + ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys"); 7.291 + goto out; 7.292 + } 7.293 + } 7.294 + 7.295 + /* Start writing out the saved-domain record. */ 7.296 + ppage = map_pfn(shared_info_frame); 7.297 + if ( !checked_write(gfd, "XenoLinuxSuspend", 16) || 7.298 + !checked_write(gfd, name, sizeof(name)) || 7.299 + !checked_write(gfd, &srec.nr_pfns, sizeof(unsigned long)) || 7.300 + !checked_write(gfd, &ctxt, sizeof(ctxt)) || 7.301 + !checked_write(gfd, ppage, PAGE_SIZE) || 7.302 + !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) || 7.303 + !checked_write(gfd, pfn_type, 4 * srec.nr_pfns) ) 7.304 + { 7.305 + ERROR("Error when writing to state file"); 7.306 + goto out; 7.307 + } 7.308 + unmap_pfn(ppage); 7.309 + 7.310 + verbose_printf("Saving memory pages: 0%%"); 7.311 + 7.312 + /* Now write out each data page, canonicalising page tables as we go... */ 7.313 + prev_pc = 0; 7.314 + for ( i = 0; i < srec.nr_pfns; i++ ) 7.315 + { 7.316 + this_pc = (i * 100) / srec.nr_pfns; 7.317 + if ( (this_pc - prev_pc) >= 5 ) 7.318 + { 7.319 + verbose_printf("\b\b\b\b%3d%%", this_pc); 7.320 + prev_pc = this_pc; 7.321 + } 7.322 + 7.323 + mfn = pfn_to_mfn_table[i]; 7.324 + 7.325 + ppage = map_pfn(mfn); 7.326 + memcpy(page, ppage, PAGE_SIZE); 7.327 + unmap_pfn(ppage); 7.328 + 7.329 + if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) ) 7.330 + { 7.331 + for ( j = 0; 7.332 + j < ((pfn_type[i] == L2TAB) ? 7.333 + (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 7.334 + j++ ) 7.335 + { 7.336 + if ( !(page[j] & _PAGE_PRESENT) ) continue; 7.337 + mfn = page[j] >> PAGE_SHIFT; 7.338 + if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) 7.339 + { 7.340 + ERROR("Frame number in pagetable page is invalid"); 7.341 + goto out; 7.342 + } 7.343 + page[j] &= PAGE_SIZE - 1; 7.344 + page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT; 7.345 + } 7.346 + } 7.347 + 7.348 + if ( !checked_write(gfd, page, PAGE_SIZE) ) 7.349 + { 7.350 + ERROR("Error when writing to state file"); 7.351 + goto out; 7.352 + } 7.353 + } 7.354 + 7.355 + verbose_printf("\b\b\b\b100%%\nMemory saved.\n"); 7.356 + 7.357 + /* Success! */ 7.358 + rc = 0; 7.359 + 7.360 + out: 7.361 + /* Restart the domain if we had to stop it to save its state. */ 7.362 + if ( we_stopped_it ) 7.363 + { 7.364 + op.cmd = DOM0_STARTDOMAIN; 7.365 + op.u.startdomain.domain = domid; 7.366 + (void)do_dom0_op(&op); 7.367 + } 7.368 + 7.369 + gzclose(gfd); 7.370 + 7.371 + if ( pfn_to_mfn_table != NULL ) 7.372 + free(pfn_to_mfn_table); 7.373 + if ( mfn_to_pfn_table != NULL ) 7.374 + free(mfn_to_pfn_table); 7.375 + if ( pfn_type != NULL ) 7.376 + free(pfn_type); 7.377 + 7.378 + /* On error, make sure the file is deleted. */ 7.379 + if ( rc != 0 ) 7.380 + unlink(state_file); 7.381 + 7.382 + return !!rc; 7.383 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/tools/libxc/libxc_misc.c Wed Nov 19 23:05:17 2003 +0000 8.3 @@ -0,0 +1,50 @@ 8.4 +/****************************************************************************** 8.5 + * libxc_misc.c 8.6 + * 8.7 + * Miscellaneous control interface functions. 8.8 + */ 8.9 + 8.10 +#include "libxc_private.h" 8.11 + 8.12 +int privcmd_fd = -1; 8.13 + 8.14 +int xc_interface_open(void) 8.15 +{ 8.16 + if ( (privcmd_fd == -1) && 8.17 + ((privcmd_fd = open("/proc/xeno/privcmd", O_RDWR)) < 0) ) 8.18 + { 8.19 + privcmd_fd = -1; 8.20 + return -1; 8.21 + } 8.22 + return 0; 8.23 +} 8.24 + 8.25 +int xc_interface_close(void) 8.26 +{ 8.27 + if ( privcmd_fd != -1 ) 8.28 + { 8.29 + close(privcmd_fd); 8.30 + privcmd_fd = -1; 8.31 + } 8.32 + return 0; 8.33 +} 8.34 + 8.35 + 8.36 +#define CONSOLE_RING_CLEAR 1 8.37 + 8.38 +int xc_readconsolering(char *str, unsigned int max_chars, int clear) 8.39 +{ 8.40 + int ret; 8.41 + dom0_op_t op; 8.42 + 8.43 + op.cmd = DOM0_READCONSOLE; 8.44 + op.u.readconsole.str = (unsigned long)str; 8.45 + op.u.readconsole.count = max_chars; 8.46 + op.u.readconsole.cmd = clear ? CONSOLE_RING_CLEAR : 0; 8.47 + 8.48 + if ( (ret = do_dom0_op(&op)) > 0 ) 8.49 + str[ret] = '\0'; 8.50 + 8.51 + return ret; 8.52 +} 8.53 +
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/tools/libxc/libxc_private.c Wed Nov 19 23:05:17 2003 +0000 9.3 @@ -0,0 +1,34 @@ 9.4 +/****************************************************************************** 9.5 + * libxc_private.c 9.6 + * 9.7 + * Helper functions for the rest of the library. 9.8 + */ 9.9 + 9.10 +#include "libxc_private.h" 9.11 + 9.12 +static int devmem_fd = -1; 9.13 + 9.14 +int init_pfn_mapper(void) 9.15 +{ 9.16 + if ( (devmem_fd == -1) && 9.17 + ((devmem_fd = open("/dev/mem", O_RDWR)) < 0) ) 9.18 + { 9.19 + devmem_fd = -1; 9.20 + return -1; 9.21 + } 9.22 + return 0; 9.23 +} 9.24 + 9.25 +void *map_pfn(unsigned long pfn) 9.26 +{ 9.27 + void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, 9.28 + MAP_SHARED, devmem_fd, pfn << PAGE_SHIFT); 9.29 + if ( vaddr == MAP_FAILED ) 9.30 + return NULL; 9.31 + return vaddr; 9.32 +} 9.33 + 9.34 +void unmap_pfn(void *vaddr) 9.35 +{ 9.36 + (void)munmap(vaddr, PAGE_SIZE); 9.37 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/tools/libxc/libxc_private.h Wed Nov 19 23:05:17 2003 +0000 10.3 @@ -0,0 +1,155 @@ 10.4 + 10.5 +#ifndef __LIBXC_PRIVATE_H__ 10.6 +#define __LIBXC_PRIVATE_H__ 10.7 + 10.8 +typedef unsigned char u8; 10.9 +typedef unsigned short u16; 10.10 +typedef unsigned long u32; 10.11 +typedef unsigned long long u64; 10.12 +typedef signed char s8; 10.13 +typedef signed short s16; 10.14 +typedef signed long s32; 10.15 +typedef signed long long s64; 10.16 + 10.17 +#include <unistd.h> 10.18 +#include <stdio.h> 10.19 +#include <errno.h> 10.20 +#include <fcntl.h> 10.21 +#include <sys/mman.h> 10.22 +#include <sys/types.h> 10.23 +#include <sys/stat.h> 10.24 +#include <stdlib.h> 10.25 +#include <sys/ioctl.h> 10.26 +#include <errno.h> 10.27 +#include <string.h> 10.28 + 10.29 +#include "xc.h" 10.30 + 10.31 +#include <asm-xeno/proc_cmd.h> 10.32 +#include <hypervisor-ifs/hypervisor-if.h> 10.33 +#include <hypervisor-ifs/dom0_ops.h> 10.34 +#include <hypervisor-ifs/vbd.h> 10.35 + 10.36 +#define _PAGE_PRESENT 0x001 10.37 +#define _PAGE_RW 0x002 10.38 +#define _PAGE_USER 0x004 10.39 +#define _PAGE_PWT 0x008 10.40 +#define _PAGE_PCD 0x010 10.41 +#define _PAGE_ACCESSED 0x020 10.42 +#define _PAGE_DIRTY 0x040 10.43 +#define _PAGE_PAT 0x080 10.44 +#define _PAGE_PSE 0x080 10.45 +#define _PAGE_GLOBAL 0x100 10.46 + 10.47 + 10.48 +#define L1_PAGETABLE_SHIFT 12 10.49 +#define L2_PAGETABLE_SHIFT 22 10.50 + 10.51 +#define ENTRIES_PER_L1_PAGETABLE 1024 10.52 +#define ENTRIES_PER_L2_PAGETABLE 1024 10.53 + 10.54 +#define PAGE_SHIFT L1_PAGETABLE_SHIFT 10.55 +#define PAGE_SIZE (1UL << PAGE_SHIFT) 10.56 +#define PAGE_MASK (~(PAGE_SIZE-1)) 10.57 + 10.58 +typedef struct { unsigned long l1_lo; } l1_pgentry_t; 10.59 +typedef struct { unsigned long l2_lo; } l2_pgentry_t; 10.60 + 10.61 +#define l1_table_offset(_a) \ 10.62 + (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1)) 10.63 +#define l2_table_offset(_a) \ 10.64 + ((_a) >> L2_PAGETABLE_SHIFT) 10.65 + 10.66 +#define ERROR(_m) \ 10.67 + fprintf(stderr, "ERROR: %s\n", (_m)) 10.68 + 10.69 +#define PERROR(_m) \ 10.70 + fprintf(stderr, "ERROR: %s (%d = %s)\n", (_m), errno, strerror(errno)) 10.71 + 10.72 +extern int privcmd_fd; 10.73 +static inline int do_privcmd(unsigned int cmd, unsigned long data) 10.74 +{ 10.75 + return ioctl(privcmd_fd, cmd, data); 10.76 +} 10.77 + 10.78 +static inline int do_xen_hypercall(privcmd_hypercall_t *hypercall) 10.79 +{ 10.80 + return do_privcmd(IOCTL_PRIVCMD_HYPERCALL, (unsigned long)hypercall); 10.81 +} 10.82 + 10.83 +static inline int do_dom0_op(dom0_op_t *op) 10.84 +{ 10.85 + int ret = -1; 10.86 + privcmd_hypercall_t hypercall; 10.87 + 10.88 + op->interface_version = DOM0_INTERFACE_VERSION; 10.89 + 10.90 + hypercall.op = __HYPERVISOR_dom0_op; 10.91 + hypercall.arg[0] = (unsigned long)op; 10.92 + 10.93 + if ( mlock(op, sizeof(*op)) != 0 ) 10.94 + goto out1; 10.95 + 10.96 + if ( (ret = do_xen_hypercall(&hypercall)) < 0 ) 10.97 + { 10.98 + if ( errno == EACCES ) 10.99 + fprintf(stderr, "Dom0 operation failed -- need to" 10.100 + " rebuild the user-space tool set?\n"); 10.101 + goto out2; 10.102 + } 10.103 + 10.104 + ret = 0; 10.105 + 10.106 + out2: (void)munlock(op, sizeof(*op)); 10.107 + out1: return ret; 10.108 +} 10.109 + 10.110 +static inline int do_network_op(network_op_t *op) 10.111 +{ 10.112 + int ret = -1; 10.113 + privcmd_hypercall_t hypercall; 10.114 + 10.115 + hypercall.op = __HYPERVISOR_network_op; 10.116 + hypercall.arg[0] = (unsigned long)op; 10.117 + 10.118 + if ( mlock(op, sizeof(*op)) != 0 ) 10.119 + goto out1; 10.120 + 10.121 + if ( (ret = do_xen_hypercall(&hypercall)) < 0 ) 10.122 + goto out2; 10.123 + 10.124 + ret = 0; 10.125 + 10.126 + out2: (void)munlock(op, sizeof(*op)); 10.127 + out1: return ret; 10.128 +} 10.129 + 10.130 + 10.131 +static inline int do_block_io_op(block_io_op_t *op) 10.132 +{ 10.133 + int ret = -1; 10.134 + privcmd_hypercall_t hypercall; 10.135 + 10.136 + hypercall.op = __HYPERVISOR_block_io_op; 10.137 + hypercall.arg[0] = (unsigned long)op; 10.138 + 10.139 + if ( mlock(op, sizeof(*op)) != 0 ) 10.140 + goto out1; 10.141 + 10.142 + if ( do_xen_hypercall(&hypercall) < 0 ) 10.143 + goto out2; 10.144 + 10.145 + ret = 0; 10.146 + 10.147 + out2: (void)munlock(op, sizeof(*op)); 10.148 + out1: return ret; 10.149 +} 10.150 + 10.151 +/* 10.152 + * PFN mapping. 10.153 + */ 10.154 +int init_pfn_mapper(void); 10.155 +void *map_pfn(unsigned long pfn); 10.156 +void unmap_pfn(void *vaddr); 10.157 + 10.158 +#endif /* __LIBXC_PRIVATE_H__ */
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/tools/libxc/libxc_vbd.c Wed Nov 19 23:05:17 2003 +0000 11.3 @@ -0,0 +1,116 @@ 11.4 +/****************************************************************************** 11.5 + * libxc_vbd.c 11.6 + * 11.7 + * API for manipulating and accessing per-domain virtual block devices. 11.8 + * 11.9 + * Copyright (c) 2003, K A Fraser. 11.10 + */ 11.11 + 11.12 +#define _GNU_SOURCE 11.13 +#include "libxc_private.h" 11.14 + 11.15 +int xc_vbd_create(unsigned int domid, unsigned short vbdid, int writeable) 11.16 +{ 11.17 + block_io_op_t op; 11.18 + op.cmd = BLOCK_IO_OP_VBD_CREATE; 11.19 + op.u.create_params.domain = domid; 11.20 + op.u.create_params.vdevice = vbdid; 11.21 + op.u.create_params.mode = VBD_MODE_R | (writeable ? VBD_MODE_W : 0); 11.22 + return do_block_io_op(&op); 11.23 +} 11.24 + 11.25 + 11.26 +int xc_vbd_destroy(unsigned int domid, unsigned short vbdid) 11.27 +{ 11.28 + block_io_op_t op; 11.29 + op.cmd = BLOCK_IO_OP_VBD_DELETE; 11.30 + op.u.delete_params.domain = domid; 11.31 + op.u.delete_params.vdevice = vbdid; 11.32 + return do_block_io_op(&op); 11.33 +} 11.34 + 11.35 + 11.36 +int xc_vbd_add_extent(unsigned int domid, 11.37 + unsigned short vbdid, 11.38 + unsigned short real_device, 11.39 + unsigned long start_sector, 11.40 + unsigned long nr_sectors) 11.41 +{ 11.42 + block_io_op_t op; 11.43 + op.cmd = BLOCK_IO_OP_VBD_ADD; 11.44 + op.u.add_params.domain = domid; 11.45 + op.u.add_params.vdevice = vbdid; 11.46 + op.u.add_params.extent.device = real_device; 11.47 + op.u.add_params.extent.start_sector = start_sector; 11.48 + op.u.add_params.extent.nr_sectors = nr_sectors; 11.49 + return do_block_io_op(&op); 11.50 +} 11.51 + 11.52 + 11.53 +int xc_vbd_delete_extent(unsigned int domid, 11.54 + unsigned short vbdid, 11.55 + unsigned short real_device, 11.56 + unsigned long start_sector, 11.57 + unsigned long nr_sectors) 11.58 +{ 11.59 + block_io_op_t op; 11.60 + op.cmd = BLOCK_IO_OP_VBD_REMOVE; 11.61 + op.u.add_params.domain = domid; 11.62 + op.u.add_params.vdevice = vbdid; 11.63 + op.u.add_params.extent.device = real_device; 11.64 + op.u.add_params.extent.start_sector = start_sector; 11.65 + op.u.add_params.extent.nr_sectors = nr_sectors; 11.66 + return do_block_io_op(&op); 11.67 +} 11.68 + 11.69 + 11.70 +int xc_vbd_probe(unsigned int domid, 11.71 + unsigned short vbdid, 11.72 + unsigned int max_vbds, 11.73 + xc_vbd_t *vbds) 11.74 +{ 11.75 + block_io_op_t op; 11.76 + xen_disk_info_t *xdi = &op.u.probe_params.xdi; 11.77 + int i, j, ret, allocsz = max_vbds * sizeof(xen_disk_t); 11.78 + 11.79 + op.cmd = BLOCK_IO_OP_VBD_PROBE; 11.80 + op.u.probe_params.domain = domid; 11.81 + 11.82 + xdi->max = max_vbds; 11.83 + xdi->disks = malloc(allocsz); 11.84 + xdi->count = 0; 11.85 + 11.86 + if ( (xdi->disks == NULL) || (mlock(xdi->disks, allocsz) != 0) ) 11.87 + { 11.88 + if ( xdi->disks != NULL ) 11.89 + free(xdi->disks); 11.90 + return -ENOMEM; 11.91 + } 11.92 + 11.93 + ret = do_block_io_op(&op); 11.94 + 11.95 + (void)munlock(xdi->disks, allocsz); 11.96 + 11.97 + if ( ret >= 0 ) 11.98 + { 11.99 + for ( i = 0, j = 0; i < xdi->count; i++ ) 11.100 + { 11.101 + if ( !(xdi->disks[i].info & XD_FLAG_VIRT) ) 11.102 + continue; 11.103 + 11.104 + vbds[j].domid = xdi->disks[i].domain; 11.105 + vbds[j].vbdid = xdi->disks[i].device; 11.106 + vbds[j].flags = (xdi->disks[i].info & XD_FLAG_RO) ? 11.107 + 0 : XC_VBDF_WRITEABLE; 11.108 + vbds[j].nr_sectors = xdi->disks[i].capacity; 11.109 + 11.110 + j++; 11.111 + } 11.112 + 11.113 + ret = j; 11.114 + } 11.115 + 11.116 + free(xdi->disks); 11.117 + 11.118 + return ret; 11.119 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/tools/libxc/libxc_vif.c Wed Nov 19 23:05:17 2003 +0000 12.3 @@ -0,0 +1,66 @@ 12.4 +/****************************************************************************** 12.5 + * libxc_vif.c 12.6 + * 12.7 + * API for manipulating and accessing per-network-interface parameters. 12.8 + * 12.9 + * Copyright (c) 2003, K A Fraser. 12.10 + */ 12.11 + 12.12 +#include "libxc_private.h" 12.13 + 12.14 +int xc_vif_scheduler_set(unsigned int domid, 12.15 + unsigned int vifid, 12.16 + xc_vif_sched_params_t *params) 12.17 +{ 12.18 + network_op_t netop; 12.19 + netop.cmd = NETWORK_OP_VIFSETPARAMS; 12.20 + netop.u.vif_setparams.domain = domid; 12.21 + netop.u.vif_setparams.vif = vifid; 12.22 + netop.u.vif_setparams.credit_bytes = params->credit_bytes; 12.23 + netop.u.vif_setparams.credit_usec = params->credit_usec; 12.24 + return do_network_op(&netop); 12.25 +} 12.26 + 12.27 + 12.28 +int xc_vif_scheduler_get(unsigned int domid, 12.29 + unsigned int vifid, 12.30 + xc_vif_sched_params_t *params) 12.31 +{ 12.32 + network_op_t netop; 12.33 + int rc; 12.34 + 12.35 + netop.cmd = NETWORK_OP_VIFGETINFO; 12.36 + netop.u.vif_getinfo.domain = domid; 12.37 + netop.u.vif_getinfo.vif = vifid; 12.38 + 12.39 + if ( (rc = do_network_op(&netop)) >= 0 ) 12.40 + { 12.41 + params->credit_bytes = netop.u.vif_getinfo.credit_bytes; 12.42 + params->credit_usec = netop.u.vif_getinfo.credit_usec; 12.43 + } 12.44 + 12.45 + return rc; 12.46 +} 12.47 + 12.48 + 12.49 +int xc_vif_stats_get(unsigned int domid, 12.50 + unsigned int vifid, 12.51 + xc_vif_stats_t *stats) 12.52 +{ 12.53 + network_op_t netop; 12.54 + int rc; 12.55 + 12.56 + netop.cmd = NETWORK_OP_VIFGETINFO; 12.57 + netop.u.vif_getinfo.domain = domid; 12.58 + netop.u.vif_getinfo.vif = vifid; 12.59 + 12.60 + if ( (rc = do_network_op(&netop)) >= 0 ) 12.61 + { 12.62 + stats->tx_bytes = netop.u.vif_getinfo.total_bytes_sent; 12.63 + stats->tx_pkts = netop.u.vif_getinfo.total_packets_sent; 12.64 + stats->rx_bytes = netop.u.vif_getinfo.total_bytes_received; 12.65 + stats->rx_pkts = netop.u.vif_getinfo.total_packets_received; 12.66 + } 12.67 + 12.68 + return rc; 12.69 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/tools/libxc/rpm.spec Wed Nov 19 23:05:17 2003 +0000 13.3 @@ -0,0 +1,28 @@ 13.4 +Summary: Xen control interface library 13.5 +Name: xen-internal-library 13.6 +Version: 1.2 13.7 +Release: 1 13.8 +License: Xen 13.9 +Group: Xen 13.10 +BuildRoot: %{staging} 13.11 +%description 13.12 +Library to make it easier to access the Xen control interfaces. 13.13 + 13.14 +%pre 13.15 +%preun 13.16 +%install 13.17 +install -m 0755 -d $RPM_BUILD_ROOT/lib 13.18 +install -m 0755 libxc.a $RPM_BUILD_ROOT/lib/libxc.a 13.19 +install -m 0755 libxc.so $RPM_BUILD_ROOT/lib/libxc.so 13.20 +install -m 0755 -d $RPM_BUILD_ROOT/include 13.21 +install -m 0644 xc.h $RPM_BUILD_ROOT/include/xc.h 13.22 +%clean 13.23 +%post 13.24 +%postun 13.25 +%files 13.26 +%defattr(-,root,root) 13.27 +%dir /lib 13.28 +/lib/libxc.a 13.29 +/lib/libxc.so 13.30 +%dir /include 13.31 +/include/xc.h
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/tools/libxc/xc.h Wed Nov 19 23:05:17 2003 +0000 14.3 @@ -0,0 +1,99 @@ 14.4 +/****************************************************************************** 14.5 + * xc.h 14.6 + * 14.7 + * A library for low-level access to the Xen control interfaces. 14.8 + * 14.9 + * Copyright (c) 2003, K A Fraser. 14.10 + */ 14.11 + 14.12 +#ifndef __XC_H__ 14.13 +#define __XC_H__ 14.14 + 14.15 +int xc_interface_open(void); 14.16 +int xc_interface_close(void); 14.17 + 14.18 +typedef struct { 14.19 + unsigned int domid; 14.20 + unsigned int cpu; 14.21 + int has_cpu; 14.22 + int stopped; 14.23 + unsigned long nr_pages; 14.24 + unsigned long long cpu_time; 14.25 +#define XC_DOMINFO_MAXNAME 16 14.26 + char name[XC_DOMINFO_MAXNAME]; 14.27 +} xc_dominfo_t; 14.28 + 14.29 +int xc_domain_create(unsigned int mem_kb, const char *name); 14.30 +int xc_domain_start(unsigned int domid); 14.31 +int xc_domain_stop(unsigned int domid); 14.32 +int xc_domain_destroy(unsigned int domid, int force); 14.33 +int xc_domain_getinfo(unsigned int first_domid, 14.34 + unsigned int max_doms, 14.35 + xc_dominfo_t *info); 14.36 + 14.37 +int xc_linux_save(unsigned int domid, const char *state_file, int verbose); 14.38 +int xc_linux_restore(const char *state_file, int verbose); 14.39 +int xc_linux_build(unsigned int domid, 14.40 + const char *image_name, 14.41 + const char *ramdisk_name, 14.42 + const char *cmdline, 14.43 + int verbose); 14.44 + 14.45 +int xc_bvtsched_global_set(unsigned long ctx_allow); 14.46 +int xc_bvtsched_domain_set(unsigned int domid, 14.47 + unsigned long mcuadv, 14.48 + unsigned long warp, 14.49 + unsigned long warpl, 14.50 + unsigned long warpu); 14.51 + 14.52 +typedef struct { 14.53 + unsigned long credit_bytes; 14.54 + unsigned long credit_usec; 14.55 +} xc_vif_sched_params_t; 14.56 + 14.57 +typedef struct { 14.58 + unsigned long long tx_bytes, tx_pkts; 14.59 + unsigned long long rx_bytes, rx_pkts; 14.60 +} xc_vif_stats_t; 14.61 + 14.62 +int xc_vif_scheduler_set(unsigned int domid, 14.63 + unsigned int vifid, 14.64 + xc_vif_sched_params_t *params); 14.65 +int xc_vif_scheduler_get(unsigned int domid, 14.66 + unsigned int vifid, 14.67 + xc_vif_sched_params_t *params); 14.68 +int xc_vif_stats_get(unsigned int domid, 14.69 + unsigned int vifid, 14.70 + xc_vif_stats_t *stats); 14.71 + 14.72 +typedef struct { 14.73 +#define XC_VBDDOM_PROBE_ALL (~0U) 14.74 + unsigned int domid; 14.75 + unsigned short vbdid; 14.76 +#define XC_VBDF_WRITEABLE (1<<0) 14.77 + unsigned long flags; 14.78 + unsigned long nr_sectors; 14.79 +} xc_vbd_t; 14.80 + 14.81 + 14.82 +int xc_vbd_create(unsigned int domid, unsigned short vbdid, int writeable); 14.83 +int xc_vbd_destroy(unsigned int domid, unsigned short vbdid); 14.84 +int xc_vbd_add_extent(unsigned int domid, 14.85 + unsigned short vbdid, 14.86 + unsigned short real_device, 14.87 + unsigned long start_sector, 14.88 + unsigned long nr_sectors); 14.89 +int xc_vbd_delete_extent(unsigned int domid, 14.90 + unsigned short vbdid, 14.91 + unsigned short real_device, 14.92 + unsigned long start_sector, 14.93 + unsigned long nr_sectors); 14.94 +int xc_vbd_probe(unsigned int domid, 14.95 + unsigned short vbdid, 14.96 + unsigned int max_vbds, 14.97 + xc_vbd_t *vbds); 14.98 + 14.99 +int xc_readconsolering(char *str, unsigned int max_chars, int clear); 14.100 + 14.101 + 14.102 +#endif /* __XC_H__ */
15.1 --- a/tools/libxi/Makefile Wed Nov 19 17:22:42 2003 +0000 15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 15.3 @@ -1,48 +0,0 @@ 15.4 - 15.5 -CC = gcc 15.6 -CFLAGS = -c -Wall -O3 15.7 -CFLAGS += -I../../xen/include -I../../xenolinux-sparse/include 15.8 - 15.9 -HDRS = $(wildcard *.h) 15.10 -OBJS = $(patsubst %.c,%.o,$(wildcard libxi_*.c)) 15.11 - 15.12 -LIBS = libxi.a libxi.so 15.13 - 15.14 -all: check-for-zlib $(LIBS) 15.15 - ranlib libxi.a 15.16 - 15.17 -check-for-zlib: 15.18 - @if [ ! -e /usr/include/zlib.h ]; then \ 15.19 - echo "***********************************************************"; \ 15.20 - echo "ERROR: install zlib header files (http://www.gzip.org/zlib)"; \ 15.21 - echo "***********************************************************"; \ 15.22 - false; \ 15.23 - fi 15.24 - 15.25 -install: all 15.26 - mkdir -p ../../../install/lib 15.27 - mkdir -p ../../../install/include 15.28 - cp -a $(LIBS) ../../../install/lib 15.29 - for i in $(LIBS) do ; chmod 755 ../../../install/bin/$i ; done 15.30 - cp -a xi.h ../../../install/include 15.31 - chmod 644 ../../../install/include/xi.h 15.32 - 15.33 -clean: 15.34 - $(RM) *.a *.so *.o *.rpm $(LIBS) 15.35 - 15.36 -rpm: all 15.37 - rm -rf staging 15.38 - mkdir staging 15.39 - mkdir staging/i386 15.40 - rpmbuild --define "staging$$PWD/staging" --define '_builddir.' \ 15.41 - --define "_rpmdir$$PWD/staging" -bb rpm.spec 15.42 - mv staging/i386/*.rpm . 15.43 - rm -rf staging 15.44 - 15.45 -libxi.so: $(OBJS) 15.46 - $(LD) -shared -o $@ $^ -lz 15.47 - 15.48 -libxi.a: libxi.a($(OBJS)) 15.49 - 15.50 -%.o: %.c $(HDRS) Makefile 15.51 - $(CC) $(CFLAGS) -o $@ $<
16.1 --- a/tools/libxi/libxi_bvtsched.c Wed Nov 19 17:22:42 2003 +0000 16.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 16.3 @@ -1,33 +0,0 @@ 16.4 -/****************************************************************************** 16.5 - * libxi_bvtsched.c 16.6 - * 16.7 - * API for manipulating parameters of the Borrowed Virtual Time scheduler. 16.8 - * 16.9 - * Copyright (c) 2003, K A Fraser. 16.10 - */ 16.11 - 16.12 -#include "libxi_private.h" 16.13 - 16.14 -int xi_bvtsched_global_set(unsigned long ctx_allow) 16.15 -{ 16.16 - dom0_op_t op; 16.17 - op.cmd = DOM0_BVTCTL; 16.18 - op.u.bvtctl.ctx_allow = ctx_allow; 16.19 - return do_dom0_op(&op); 16.20 -} 16.21 - 16.22 -int xi_bvtsched_domain_set(unsigned int domid, 16.23 - unsigned long mcuadv, 16.24 - unsigned long warp, 16.25 - unsigned long warpl, 16.26 - unsigned long warpu) 16.27 -{ 16.28 - dom0_op_t op; 16.29 - op.cmd = DOM0_ADJUSTDOM; 16.30 - op.u.adjustdom.domain = domid; 16.31 - op.u.adjustdom.mcu_adv = mcuadv; 16.32 - op.u.adjustdom.warp = warp; 16.33 - op.u.adjustdom.warpl = warpl; 16.34 - op.u.adjustdom.warpu = warpu; 16.35 - return do_dom0_op(&op); 16.36 -}
17.1 --- a/tools/libxi/libxi_domain.c Wed Nov 19 17:22:42 2003 +0000 17.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 17.3 @@ -1,80 +0,0 @@ 17.4 -/****************************************************************************** 17.5 - * libxi_domain.c 17.6 - * 17.7 - * API for manipulating and obtaining information on domains. 17.8 - * 17.9 - * Copyright (c) 2003, K A Fraser. 17.10 - */ 17.11 - 17.12 -#include "libxi_private.h" 17.13 - 17.14 -int xi_domain_create(unsigned int mem_kb, const char *name) 17.15 -{ 17.16 - int err; 17.17 - dom0_op_t op; 17.18 - 17.19 - op.cmd = DOM0_CREATEDOMAIN; 17.20 - op.u.createdomain.memory_kb = mem_kb; 17.21 - strncpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME); 17.22 - op.u.createdomain.name[MAX_DOMAIN_NAME-1] = '\0'; 17.23 - 17.24 - err = do_dom0_op(&op); 17.25 - 17.26 - return (err < 0) ? err : op.u.createdomain.domain; 17.27 -} 17.28 - 17.29 - 17.30 -int xi_domain_start(unsigned int domid) 17.31 -{ 17.32 - dom0_op_t op; 17.33 - op.cmd = DOM0_STARTDOMAIN; 17.34 - op.u.startdomain.domain = domid; 17.35 - return do_dom0_op(&op); 17.36 -} 17.37 - 17.38 - 17.39 -int xi_domain_stop(unsigned int domid) 17.40 -{ 17.41 - dom0_op_t op; 17.42 - op.cmd = DOM0_STOPDOMAIN; 17.43 - op.u.stopdomain.domain = domid; 17.44 - return do_dom0_op(&op); 17.45 -} 17.46 - 17.47 - 17.48 -int xi_domain_destroy(unsigned int domid, int force) 17.49 -{ 17.50 - dom0_op_t op; 17.51 - op.cmd = DOM0_DESTROYDOMAIN; 17.52 - op.u.destroydomain.domain = domid; 17.53 - op.u.destroydomain.force = !!force; 17.54 - return do_dom0_op(&op); 17.55 -} 17.56 - 17.57 -int xi_domain_getinfo(unsigned int first_domid, 17.58 - unsigned int max_doms, 17.59 - xi_dominfo_t *info) 17.60 -{ 17.61 - unsigned int nr_doms, next_domid = first_domid; 17.62 - dom0_op_t op; 17.63 - 17.64 - for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ ) 17.65 - { 17.66 - op.cmd = DOM0_GETDOMAININFO; 17.67 - op.u.getdomaininfo.domain = next_domid; 17.68 - if ( do_dom0_op(&op) < 0 ) 17.69 - break; 17.70 - info->domid = op.u.getdomaininfo.domain; 17.71 - info->cpu = op.u.getdomaininfo.processor; 17.72 - info->has_cpu = op.u.getdomaininfo.has_cpu; 17.73 - info->stopped = (op.u.getdomaininfo.state == DOMSTATE_STOPPED); 17.74 - info->nr_pages = op.u.getdomaininfo.tot_pages; 17.75 - info->cpu_time = op.u.getdomaininfo.cpu_time; 17.76 - strncpy(info->name, op.u.getdomaininfo.name, XI_DOMINFO_MAXNAME); 17.77 - info->name[XI_DOMINFO_MAXNAME-1] = '\0'; 17.78 - 17.79 - next_domid = op.u.getdomaininfo.domain + 1; 17.80 - } 17.81 - 17.82 - return nr_doms; 17.83 -}
18.1 --- a/tools/libxi/libxi_linux_build.c Wed Nov 19 17:22:42 2003 +0000 18.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 18.3 @@ -1,481 +0,0 @@ 18.4 -/****************************************************************************** 18.5 - * libxi_linux_build.c 18.6 - */ 18.7 - 18.8 -#include "libxi_private.h" 18.9 -#include <zlib.h> 18.10 - 18.11 -/* This string is written to the head of every guest kernel image. */ 18.12 -#define GUEST_SIG "XenoGues" 18.13 -#define SIG_LEN 8 18.14 - 18.15 -#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED) 18.16 -#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) 18.17 - 18.18 -static long get_tot_pages(int domid) 18.19 -{ 18.20 - dom0_op_t op; 18.21 - op.cmd = DOM0_GETDOMAININFO; 18.22 - op.u.getdomaininfo.domain = domid; 18.23 - return (do_dom0_op(&op) < 0) ? -1 : op.u.getdomaininfo.tot_pages; 18.24 -} 18.25 - 18.26 -static int get_pfn_list( 18.27 - int domid, unsigned long *pfn_buf, unsigned long max_pfns) 18.28 -{ 18.29 - dom0_op_t op; 18.30 - int ret; 18.31 - op.cmd = DOM0_GETMEMLIST; 18.32 - op.u.getmemlist.domain = domid; 18.33 - op.u.getmemlist.max_pfns = max_pfns; 18.34 - op.u.getmemlist.buffer = pfn_buf; 18.35 - 18.36 - if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 ) 18.37 - return -1; 18.38 - 18.39 - ret = do_dom0_op(&op); 18.40 - 18.41 - (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long)); 18.42 - 18.43 - return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; 18.44 -} 18.45 - 18.46 -static int send_pgupdates(mmu_update_t *updates, int nr_updates) 18.47 -{ 18.48 - int ret = -1; 18.49 - privcmd_hypercall_t hypercall; 18.50 - 18.51 - hypercall.op = __HYPERVISOR_mmu_update; 18.52 - hypercall.arg[0] = (unsigned long)updates; 18.53 - hypercall.arg[1] = (unsigned long)nr_updates; 18.54 - 18.55 - if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 ) 18.56 - goto out1; 18.57 - 18.58 - if ( do_xen_hypercall(&hypercall) < 0 ) 18.59 - goto out2; 18.60 - 18.61 - ret = 0; 18.62 - 18.63 - out2: (void)munlock(updates, nr_updates * sizeof(*updates)); 18.64 - out1: return ret; 18.65 -} 18.66 - 18.67 -/* Read the kernel header, extracting the image size and load address. */ 18.68 -static int read_kernel_header(gzFile gfd, long dom_size, 18.69 - unsigned long *load_addr, int verbose) 18.70 -{ 18.71 - char signature[SIG_LEN]; 18.72 - 18.73 - gzread(gfd, signature, SIG_LEN); 18.74 - if ( strncmp(signature, GUEST_SIG, SIG_LEN) ) 18.75 - { 18.76 - if ( verbose ) 18.77 - ERROR("Kernel image does not contain required signature"); 18.78 - return -1; 18.79 - } 18.80 - 18.81 - /* Read the load address which immediately follows the Xeno signature. */ 18.82 - gzread(gfd, load_addr, sizeof(unsigned long)); 18.83 - 18.84 - return 0; 18.85 -} 18.86 - 18.87 -static int copy_to_domain_page(unsigned long dst_pfn, void *src_page) 18.88 -{ 18.89 - void *vaddr = map_pfn(dst_pfn); 18.90 - if ( vaddr == NULL ) 18.91 - return -1; 18.92 - memcpy(vaddr, src_page, PAGE_SIZE); 18.93 - unmap_pfn(vaddr); 18.94 - return 0; 18.95 -} 18.96 - 18.97 -static int setup_guestos( 18.98 - int dom, gzFile kernel_gfd, int initrd_fd, unsigned long tot_pages, 18.99 - unsigned long *virt_startinfo_addr, unsigned long virt_load_addr, 18.100 - dom0_builddomain_t *builddomain, const char *cmdline, 18.101 - unsigned long shared_info_frame, int verbose) 18.102 -{ 18.103 - l1_pgentry_t *vl1tab = NULL, *vl1e = NULL; 18.104 - l2_pgentry_t *vl2tab = NULL, *vl2e = NULL; 18.105 - unsigned long *page_array = NULL; 18.106 - mmu_update_t *pgt_update_arr = NULL, *pgt_updates = NULL; 18.107 - int alloc_index, num_pt_pages; 18.108 - unsigned long l2tab; 18.109 - unsigned long l1tab = 0; 18.110 - unsigned long num_pgt_updates = 0; 18.111 - unsigned long count, pt_start, i, j; 18.112 - unsigned long initrd_addr = 0, initrd_len = 0; 18.113 - start_info_t *start_info; 18.114 - shared_info_t *shared_info; 18.115 - unsigned long ksize; 18.116 - 18.117 - memset(builddomain, 0, sizeof(*builddomain)); 18.118 - 18.119 - if ( init_pfn_mapper() < 0 ) 18.120 - goto error_out; 18.121 - 18.122 - pgt_updates = malloc((tot_pages + 1024) * 3 * sizeof(mmu_update_t)); 18.123 - page_array = malloc(tot_pages * sizeof(unsigned long)); 18.124 - pgt_update_arr = pgt_updates; 18.125 - if ( (pgt_update_arr == NULL) || (page_array == NULL) ) 18.126 - { 18.127 - if ( verbose ) 18.128 - PERROR("Could not allocate memory"); 18.129 - goto error_out; 18.130 - } 18.131 - 18.132 - if ( get_pfn_list(dom, page_array, tot_pages) != tot_pages ) 18.133 - { 18.134 - if ( verbose ) 18.135 - PERROR("Could not get the page frame list"); 18.136 - goto error_out; 18.137 - } 18.138 - 18.139 - /* Load the guest OS image. Let it take no more than 1/2 memory.*/ 18.140 - for ( i = 0; i < ((tot_pages/2)*PAGE_SIZE); i += PAGE_SIZE ) 18.141 - { 18.142 - char page[PAGE_SIZE]; 18.143 - int size; 18.144 - if ( (size = gzread(kernel_gfd, page, PAGE_SIZE)) == -1 ) 18.145 - { 18.146 - if ( verbose ) 18.147 - PERROR("Error reading kernel image, could not" 18.148 - " read the whole image."); 18.149 - goto error_out; 18.150 - } 18.151 - if ( size == 0 ) 18.152 - goto kernel_copied; 18.153 - copy_to_domain_page(page_array[i>>PAGE_SHIFT], page); 18.154 - } 18.155 - if ( verbose ) 18.156 - ERROR("Kernel too big to safely fit in domain memory"); 18.157 - goto error_out; 18.158 - 18.159 - kernel_copied: 18.160 - /* ksize is kernel-image size rounded up to a page boundary. */ 18.161 - ksize = i; 18.162 - 18.163 - /* Load the initial ramdisk image. */ 18.164 - if ( initrd_fd >= 0 ) 18.165 - { 18.166 - struct stat stat; 18.167 - unsigned long isize; 18.168 - 18.169 - if ( fstat(initrd_fd, &stat) < 0 ) 18.170 - { 18.171 - if ( verbose ) 18.172 - PERROR("Could not stat the initrd image"); 18.173 - goto error_out; 18.174 - } 18.175 - isize = stat.st_size; 18.176 - if ( (isize + ksize) > ((tot_pages/2) * PAGE_SIZE) ) 18.177 - { 18.178 - if ( verbose ) 18.179 - ERROR("Kernel/initrd too big to safely fit in domain memory"); 18.180 - goto error_out; 18.181 - } 18.182 - 18.183 - initrd_addr = virt_load_addr + ksize; 18.184 - initrd_len = isize; 18.185 - 18.186 - for ( j = 0, i = ksize; j < isize; j += PAGE_SIZE, i += PAGE_SIZE ) 18.187 - { 18.188 - char page[PAGE_SIZE]; 18.189 - int size = ((isize-j) < PAGE_SIZE) ? (isize-j) : PAGE_SIZE; 18.190 - if ( read(initrd_fd, page, size) != size ) 18.191 - { 18.192 - if ( verbose ) 18.193 - PERROR("Error reading initrd image, could not" 18.194 - " read the whole image."); 18.195 - goto error_out; 18.196 - } 18.197 - copy_to_domain_page(page_array[i>>PAGE_SHIFT], page); 18.198 - } 18.199 - } 18.200 - 18.201 - alloc_index = tot_pages - 1; 18.202 - 18.203 - /* Count bottom-level PTs, rounding up. */ 18.204 - num_pt_pages = (l1_table_offset(virt_load_addr) + tot_pages + 1023) / 1024; 18.205 - 18.206 - /* We must also count the page directory. */ 18.207 - num_pt_pages++; 18.208 - 18.209 - /* Index of first PT page. */ 18.210 - pt_start = tot_pages - num_pt_pages; 18.211 - 18.212 - /* 18.213 - * First allocate page for page dir. Allocation goes backwards from the end 18.214 - * of the allocated physical address space. 18.215 - */ 18.216 - l2tab = page_array[alloc_index] << PAGE_SHIFT; 18.217 - alloc_index--; 18.218 - builddomain->ctxt.pt_base = l2tab; 18.219 - 18.220 - /* 18.221 - * Pin down l2tab addr as page dir page - causes hypervisor to provide 18.222 - * correct protection for the page 18.223 - */ 18.224 - pgt_updates->ptr = l2tab | MMU_EXTENDED_COMMAND; 18.225 - pgt_updates->val = MMUEXT_PIN_L2_TABLE; 18.226 - pgt_updates++; 18.227 - num_pgt_updates++; 18.228 - 18.229 - /* Initialise the page tables. */ 18.230 - if ( (vl2tab = map_pfn(l2tab >> PAGE_SHIFT)) == NULL ) 18.231 - goto error_out; 18.232 - memset(vl2tab, 0, PAGE_SIZE); 18.233 - vl2e = vl2tab + l2_table_offset(virt_load_addr); 18.234 - for ( count = 0; count < tot_pages; count++ ) 18.235 - { 18.236 - if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) 18.237 - { 18.238 - l1tab = page_array[alloc_index] << PAGE_SHIFT; 18.239 - if ( (vl1tab = map_pfn(l1tab >> PAGE_SHIFT)) == NULL ) 18.240 - goto error_out; 18.241 - memset(vl1tab, 0, PAGE_SIZE); 18.242 - alloc_index--; 18.243 - 18.244 - vl1e = vl1tab + l1_table_offset(virt_load_addr + 18.245 - (count << PAGE_SHIFT)); 18.246 - 18.247 - /* make apropriate entry in the page directory */ 18.248 - pgt_updates->ptr = (unsigned long)vl2e; 18.249 - pgt_updates->val = l1tab | L2_PROT; 18.250 - pgt_updates++; 18.251 - num_pgt_updates++; 18.252 - vl2e++; 18.253 - } 18.254 - 18.255 - if ( count < pt_start ) 18.256 - { 18.257 - pgt_updates->ptr = (unsigned long)vl1e; 18.258 - pgt_updates->val = (page_array[count] << PAGE_SHIFT) | L1_PROT; 18.259 - pgt_updates++; 18.260 - num_pgt_updates++; 18.261 - vl1e++; 18.262 - } 18.263 - else 18.264 - { 18.265 - pgt_updates->ptr = (unsigned long)vl1e; 18.266 - pgt_updates->val = 18.267 - ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW; 18.268 - pgt_updates++; 18.269 - num_pgt_updates++; 18.270 - vl1e++; 18.271 - } 18.272 - 18.273 - pgt_updates->ptr = 18.274 - (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; 18.275 - pgt_updates->val = count; 18.276 - pgt_updates++; 18.277 - num_pgt_updates++; 18.278 - } 18.279 - 18.280 - *virt_startinfo_addr = 18.281 - virt_load_addr + ((alloc_index-1) << PAGE_SHIFT); 18.282 - 18.283 - start_info = map_pfn(page_array[alloc_index-1]); 18.284 - memset(start_info, 0, sizeof(*start_info)); 18.285 - start_info->pt_base = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT); 18.286 - start_info->mod_start = initrd_addr; 18.287 - start_info->mod_len = initrd_len; 18.288 - start_info->nr_pages = tot_pages; 18.289 - start_info->shared_info = shared_info_frame << PAGE_SHIFT; 18.290 - start_info->dom_id = dom; 18.291 - start_info->flags = 0; 18.292 - strncpy(start_info->cmd_line, cmdline, MAX_CMD_LEN); 18.293 - start_info->cmd_line[MAX_CMD_LEN-1] = '\0'; 18.294 - 18.295 - unmap_pfn(start_info); 18.296 - 18.297 - /* shared_info page starts its life empty. */ 18.298 - shared_info = map_pfn(shared_info_frame); 18.299 - memset(shared_info, 0, PAGE_SIZE); 18.300 - unmap_pfn(shared_info); 18.301 - 18.302 - /* Send the page update requests down to the hypervisor. */ 18.303 - if ( send_pgupdates(pgt_update_arr, num_pgt_updates) < 0 ) 18.304 - goto error_out; 18.305 - 18.306 - free(page_array); 18.307 - free(pgt_update_arr); 18.308 - return 0; 18.309 - 18.310 - error_out: 18.311 - if ( page_array == NULL ) 18.312 - free(page_array); 18.313 - if ( pgt_update_arr == NULL ) 18.314 - free(pgt_update_arr); 18.315 - return -1; 18.316 -} 18.317 - 18.318 -int xi_domain_build(unsigned int domid, 18.319 - const char *image_name, 18.320 - const char *ramdisk_name, 18.321 - const char *cmdline, 18.322 - int verbose) 18.323 -{ 18.324 - dom0_op_t launch_op, op; 18.325 - unsigned long load_addr; 18.326 - long tot_pages; 18.327 - int kernel_fd, initrd_fd = -1; 18.328 - gzFile kernel_gfd; 18.329 - int rc, i; 18.330 - full_execution_context_t *ctxt; 18.331 - unsigned long virt_startinfo_addr; 18.332 - 18.333 - if ( (tot_pages = get_tot_pages(domid)) < 0 ) 18.334 - { 18.335 - if ( verbose ) 18.336 - PERROR("Could not find total pages for domain"); 18.337 - return 1; 18.338 - } 18.339 - 18.340 - kernel_fd = open(image_name, O_RDONLY); 18.341 - if ( kernel_fd < 0 ) 18.342 - { 18.343 - if ( verbose ) 18.344 - PERROR("Could not open kernel image"); 18.345 - return 1; 18.346 - } 18.347 - 18.348 - if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL ) 18.349 - { 18.350 - if ( verbose ) 18.351 - PERROR("Could not allocate decompression state for state file"); 18.352 - close(kernel_fd); 18.353 - return 1; 18.354 - } 18.355 - 18.356 - rc = read_kernel_header(kernel_gfd, 18.357 - tot_pages << (PAGE_SHIFT - 10), 18.358 - &load_addr, verbose); 18.359 - if ( rc < 0 ) 18.360 - goto error_out; 18.361 - 18.362 - if ( (load_addr & (PAGE_SIZE-1)) != 0 ) 18.363 - { 18.364 - if ( verbose ) 18.365 - ERROR("We can only deal with page-aligned load addresses"); 18.366 - goto error_out; 18.367 - } 18.368 - 18.369 - if ( (load_addr + (tot_pages << PAGE_SHIFT)) > HYPERVISOR_VIRT_START ) 18.370 - { 18.371 - if ( verbose ) 18.372 - ERROR("Cannot map all domain memory without hitting Xen space"); 18.373 - goto error_out; 18.374 - } 18.375 - 18.376 - if ( ramdisk_name != NULL ) 18.377 - { 18.378 - initrd_fd = open(ramdisk_name, O_RDONLY); 18.379 - if ( initrd_fd < 0 ) 18.380 - { 18.381 - if ( verbose ) 18.382 - PERROR("Could not open the initial ramdisk image"); 18.383 - goto error_out; 18.384 - } 18.385 - } 18.386 - 18.387 - op.cmd = DOM0_GETDOMAININFO; 18.388 - op.u.getdomaininfo.domain = domid; 18.389 - if ( (do_dom0_op(&op) < 0) || (op.u.getdomaininfo.domain != domid) ) 18.390 - { 18.391 - if ( verbose ) 18.392 - PERROR("Could not get info on domain"); 18.393 - goto error_out; 18.394 - } 18.395 - if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) || 18.396 - (op.u.getdomaininfo.ctxt.pt_base != 0) ) 18.397 - { 18.398 - if ( verbose ) 18.399 - ERROR("Domain is already constructed"); 18.400 - goto error_out; 18.401 - } 18.402 - 18.403 - if ( setup_guestos(domid, kernel_gfd, initrd_fd, tot_pages, 18.404 - &virt_startinfo_addr, 18.405 - load_addr, &launch_op.u.builddomain, cmdline, 18.406 - op.u.getdomaininfo.shared_info_frame, verbose) < 0 ) 18.407 - { 18.408 - if ( verbose ) 18.409 - ERROR("Error constructing guest OS"); 18.410 - goto error_out; 18.411 - } 18.412 - 18.413 - if ( initrd_fd >= 0 ) 18.414 - close(initrd_fd); 18.415 - gzclose(kernel_gfd); 18.416 - 18.417 - ctxt = &launch_op.u.builddomain.ctxt; 18.418 - 18.419 - ctxt->flags = 0; 18.420 - 18.421 - /* 18.422 - * Initial register values: 18.423 - * DS,ES,FS,GS = FLAT_RING1_DS 18.424 - * CS:EIP = FLAT_RING1_CS:start_pc 18.425 - * SS:ESP = FLAT_RING1_DS:start_stack 18.426 - * ESI = start_info 18.427 - * [EAX,EBX,ECX,EDX,EDI,EBP are zero] 18.428 - * EFLAGS = IF | 2 (bit 1 is reserved and should always be 1) 18.429 - */ 18.430 - ctxt->i386_ctxt.ds = FLAT_RING1_DS; 18.431 - ctxt->i386_ctxt.es = FLAT_RING1_DS; 18.432 - ctxt->i386_ctxt.fs = FLAT_RING1_DS; 18.433 - ctxt->i386_ctxt.gs = FLAT_RING1_DS; 18.434 - ctxt->i386_ctxt.ss = FLAT_RING1_DS; 18.435 - ctxt->i386_ctxt.cs = FLAT_RING1_CS; 18.436 - ctxt->i386_ctxt.eip = load_addr; 18.437 - ctxt->i386_ctxt.esp = virt_startinfo_addr; 18.438 - ctxt->i386_ctxt.esi = virt_startinfo_addr; 18.439 - ctxt->i386_ctxt.eflags = (1<<9) | (1<<2); 18.440 - 18.441 - /* FPU is set up to default initial state. */ 18.442 - memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt)); 18.443 - 18.444 - /* Virtual IDT is empty at start-of-day. */ 18.445 - for ( i = 0; i < 256; i++ ) 18.446 - { 18.447 - ctxt->trap_ctxt[i].vector = i; 18.448 - ctxt->trap_ctxt[i].cs = FLAT_RING1_CS; 18.449 - } 18.450 - ctxt->fast_trap_idx = 0; 18.451 - 18.452 - /* No LDT. */ 18.453 - ctxt->ldt_ents = 0; 18.454 - 18.455 - /* Use the default Xen-provided GDT. */ 18.456 - ctxt->gdt_ents = 0; 18.457 - 18.458 - /* Ring 1 stack is the initial stack. */ 18.459 - ctxt->ring1_ss = FLAT_RING1_DS; 18.460 - ctxt->ring1_esp = virt_startinfo_addr; 18.461 - 18.462 - /* No debugging. */ 18.463 - memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg)); 18.464 - 18.465 - /* No callback handlers. */ 18.466 - ctxt->event_callback_cs = FLAT_RING1_CS; 18.467 - ctxt->event_callback_eip = 0; 18.468 - ctxt->failsafe_callback_cs = FLAT_RING1_CS; 18.469 - ctxt->failsafe_callback_eip = 0; 18.470 - 18.471 - launch_op.u.builddomain.domain = domid; 18.472 - launch_op.u.builddomain.num_vifs = 1; 18.473 - 18.474 - launch_op.cmd = DOM0_BUILDDOMAIN; 18.475 - rc = do_dom0_op(&launch_op); 18.476 - 18.477 - return rc; 18.478 - 18.479 - error_out: 18.480 - if ( initrd_fd >= 0 ) 18.481 - close(initrd_fd); 18.482 - gzclose(kernel_gfd); 18.483 - return -1; 18.484 -}
19.1 --- a/tools/libxi/libxi_linux_restore.c Wed Nov 19 17:22:42 2003 +0000 19.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 19.3 @@ -1,476 +0,0 @@ 19.4 -/****************************************************************************** 19.5 - * libxi_linux_restore.c 19.6 - * 19.7 - * Restore the state of a Xenolinux session. 19.8 - * 19.9 - * Copyright (c) 2003, K A Fraser. 19.10 - */ 19.11 - 19.12 -#include "libxi_private.h" 19.13 -#include <asm-xeno/suspend.h> 19.14 -#include <zlib.h> 19.15 - 19.16 -/* This may allow us to create a 'quiet' command-line option, if necessary. */ 19.17 -#define verbose_printf(_f, _a...) \ 19.18 - do { \ 19.19 - if ( !verbose ) break; \ 19.20 - printf( _f , ## _a ); \ 19.21 - fflush(stdout); \ 19.22 - } while ( 0 ) 19.23 - 19.24 -static int get_pfn_list( 19.25 - int domain_id, unsigned long *pfn_buf, unsigned long max_pfns) 19.26 -{ 19.27 - dom0_op_t op; 19.28 - int ret; 19.29 - op.cmd = DOM0_GETMEMLIST; 19.30 - op.u.getmemlist.domain = domain_id; 19.31 - op.u.getmemlist.max_pfns = max_pfns; 19.32 - op.u.getmemlist.buffer = pfn_buf; 19.33 - 19.34 - if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 ) 19.35 - { 19.36 - PERROR("Could not lock pfn list buffer"); 19.37 - return -1; 19.38 - } 19.39 - 19.40 - ret = do_dom0_op(&op); 19.41 - 19.42 - (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long)); 19.43 - 19.44 - return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; 19.45 -} 19.46 - 19.47 -#define MAX_MMU_UPDATES 1024 19.48 - 19.49 -static int flush_mmu_updates(mmu_update_t *mmu_updates, 19.50 - int *mmu_update_idx) 19.51 -{ 19.52 - int err = 0; 19.53 - privcmd_hypercall_t hypercall; 19.54 - 19.55 - if ( *mmu_update_idx == 0 ) 19.56 - return 0; 19.57 - 19.58 - hypercall.op = __HYPERVISOR_mmu_update; 19.59 - hypercall.arg[0] = (unsigned long)mmu_updates; 19.60 - hypercall.arg[1] = (unsigned long)*mmu_update_idx; 19.61 - 19.62 - if ( mlock(mmu_updates, sizeof(mmu_updates)) != 0 ) 19.63 - { 19.64 - PERROR("Could not lock pagetable update array"); 19.65 - err = 1; 19.66 - goto out; 19.67 - } 19.68 - 19.69 - if ( do_xen_hypercall(&hypercall) < 0 ) 19.70 - { 19.71 - ERROR("Failure when submitting mmu updates"); 19.72 - err = 1; 19.73 - } 19.74 - 19.75 - *mmu_update_idx = 0; 19.76 - 19.77 - (void)munlock(mmu_updates, sizeof(mmu_updates)); 19.78 - 19.79 - out: 19.80 - return err; 19.81 -} 19.82 - 19.83 -static int add_mmu_update(mmu_update_t *mmu_updates, 19.84 - int *mmu_update_idx, 19.85 - unsigned long ptr, 19.86 - unsigned long val) 19.87 -{ 19.88 - mmu_updates[*mmu_update_idx].ptr = ptr; 19.89 - mmu_updates[*mmu_update_idx].val = val; 19.90 - if ( ++*mmu_update_idx == MAX_MMU_UPDATES ) 19.91 - return flush_mmu_updates(mmu_updates, mmu_update_idx); 19.92 - return 0; 19.93 -} 19.94 - 19.95 -static int checked_read(gzFile fd, void *buf, size_t count) 19.96 -{ 19.97 - int rc; 19.98 - while ( ((rc = gzread(fd, buf, count)) == -1) && (errno == EINTR) ) 19.99 - continue; 19.100 - return rc == count; 19.101 -} 19.102 - 19.103 -int xi_linux_restore(const char *state_file, int verbose) 19.104 -{ 19.105 - dom0_op_t op; 19.106 - int rc = 1, i, j; 19.107 - unsigned long mfn, pfn, dom = 0; 19.108 - unsigned int prev_pc, this_pc; 19.109 - 19.110 - /* Number of page frames in use by this XenoLinux session. */ 19.111 - unsigned long nr_pfns; 19.112 - 19.113 - /* The new domain's shared-info frame number. */ 19.114 - unsigned long shared_info_frame; 19.115 - unsigned char shared_info[PAGE_SIZE]; /* saved contents from file */ 19.116 - 19.117 - /* A copy of the CPU context of the guest. */ 19.118 - full_execution_context_t ctxt; 19.119 - 19.120 - /* First 16 bytes of the state file must contain 'XenoLinuxSuspend'. */ 19.121 - char signature[16]; 19.122 - 19.123 - /* A copy of the domain's name. */ 19.124 - char name[MAX_DOMAIN_NAME]; 19.125 - 19.126 - /* A table containg the type of each PFN (/not/ MFN!). */ 19.127 - unsigned long *pfn_type = NULL; 19.128 - 19.129 - /* A temporary mapping, and a copy, of one frame of guest memory. */ 19.130 - unsigned long *ppage, page[1024]; 19.131 - 19.132 - /* A copy of the pfn-to-mfn table frame list. */ 19.133 - unsigned long pfn_to_mfn_frame_list[1024]; 19.134 - 19.135 - /* A table mapping each PFN to its new MFN. */ 19.136 - unsigned long *pfn_to_mfn_table = NULL; 19.137 - 19.138 - /* A temporary mapping of the guest's suspend record. */ 19.139 - suspend_record_t *p_srec; 19.140 - 19.141 - /* The name and descriptor of the file that we are reading from. */ 19.142 - int fd; 19.143 - gzFile gfd; 19.144 - 19.145 - mmu_update_t mmu_updates[MAX_MMU_UPDATES]; 19.146 - int mmu_update_idx = 0; 19.147 - 19.148 - if ( (fd = open(state_file, O_RDONLY)) == -1 ) 19.149 - { 19.150 - PERROR("Could not open state file for reading"); 19.151 - return 1; 19.152 - } 19.153 - 19.154 - if ( (gfd = gzdopen(fd, "rb")) == NULL ) 19.155 - { 19.156 - ERROR("Could not allocate decompression state for state file"); 19.157 - close(fd); 19.158 - return 1; 19.159 - } 19.160 - 19.161 - /* Start writing out the saved-domain record. */ 19.162 - if ( !checked_read(gfd, signature, 16) || 19.163 - (memcmp(signature, "XenoLinuxSuspend", 16) != 0) ) 19.164 - { 19.165 - ERROR("Unrecognised state format -- no signature found"); 19.166 - goto out; 19.167 - } 19.168 - 19.169 - if ( !checked_read(gfd, name, sizeof(name)) || 19.170 - !checked_read(gfd, &nr_pfns, sizeof(unsigned long)) || 19.171 - !checked_read(gfd, &ctxt, sizeof(ctxt)) || 19.172 - !checked_read(gfd, shared_info, PAGE_SIZE) || 19.173 - !checked_read(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) ) 19.174 - { 19.175 - ERROR("Error when reading from state file"); 19.176 - goto out; 19.177 - } 19.178 - 19.179 - for ( i = 0; i < MAX_DOMAIN_NAME; i++ ) 19.180 - { 19.181 - if ( name[i] == '\0' ) break; 19.182 - if ( name[i] & 0x80 ) 19.183 - { 19.184 - ERROR("Random characters in domain name"); 19.185 - goto out; 19.186 - } 19.187 - } 19.188 - name[MAX_DOMAIN_NAME-1] = '\0'; 19.189 - 19.190 - if ( nr_pfns > 1024*1024 ) 19.191 - { 19.192 - ERROR("Invalid state file -- pfn count out of range"); 19.193 - goto out; 19.194 - } 19.195 - 19.196 - /* We want zeroed memory so use calloc rather than malloc. */ 19.197 - pfn_to_mfn_table = calloc(1, 4 * nr_pfns); 19.198 - pfn_type = calloc(1, 4 * nr_pfns); 19.199 - 19.200 - if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) ) 19.201 - { 19.202 - errno = ENOMEM; 19.203 - goto out; 19.204 - } 19.205 - 19.206 - if ( !checked_read(gfd, pfn_type, 4 * nr_pfns) ) 19.207 - { 19.208 - ERROR("Error when reading from state file"); 19.209 - goto out; 19.210 - } 19.211 - 19.212 - /* Create a new domain of the appropriate size, and find it's dom_id. */ 19.213 - op.cmd = DOM0_CREATEDOMAIN; 19.214 - op.u.createdomain.memory_kb = nr_pfns * (PAGE_SIZE / 1024); 19.215 - memcpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME); 19.216 - if ( do_dom0_op(&op) < 0 ) 19.217 - { 19.218 - ERROR("Could not create new domain"); 19.219 - goto out; 19.220 - } 19.221 - dom = op.u.createdomain.domain; 19.222 - 19.223 - /* Get the domain's shared-info frame. */ 19.224 - op.cmd = DOM0_GETDOMAININFO; 19.225 - op.u.getdomaininfo.domain = dom; 19.226 - if ( do_dom0_op(&op) < 0 ) 19.227 - { 19.228 - ERROR("Could not get information on new domain"); 19.229 - goto out; 19.230 - } 19.231 - shared_info_frame = op.u.getdomaininfo.shared_info_frame; 19.232 - 19.233 - if ( init_pfn_mapper() < 0 ) 19.234 - goto out; 19.235 - 19.236 - /* Copy saved contents of shared-info page. No checking needed. */ 19.237 - ppage = map_pfn(shared_info_frame); 19.238 - memcpy(ppage, shared_info, PAGE_SIZE); 19.239 - unmap_pfn(ppage); 19.240 - 19.241 - /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */ 19.242 - if ( get_pfn_list(dom, pfn_to_mfn_table, nr_pfns) != nr_pfns ) 19.243 - { 19.244 - ERROR("Did not read correct number of frame numbers for new dom"); 19.245 - goto out; 19.246 - } 19.247 - 19.248 - verbose_printf("Reloading memory pages: 0%%"); 19.249 - 19.250 - /* 19.251 - * Now simply read each saved frame into its new machine frame. 19.252 - * We uncanonicalise page tables as we go. 19.253 - */ 19.254 - prev_pc = 0; 19.255 - for ( i = 0; i < nr_pfns; i++ ) 19.256 - { 19.257 - this_pc = (i * 100) / nr_pfns; 19.258 - if ( (this_pc - prev_pc) >= 5 ) 19.259 - { 19.260 - verbose_printf("\b\b\b\b%3d%%", this_pc); 19.261 - prev_pc = this_pc; 19.262 - } 19.263 - 19.264 - mfn = pfn_to_mfn_table[i]; 19.265 - 19.266 - if ( !checked_read(gfd, page, PAGE_SIZE) ) 19.267 - { 19.268 - ERROR("Error when reading from state file"); 19.269 - goto out; 19.270 - } 19.271 - 19.272 - ppage = map_pfn(mfn); 19.273 - switch ( pfn_type[i] ) 19.274 - { 19.275 - case L1TAB: 19.276 - memset(ppage, 0, PAGE_SIZE); 19.277 - if ( add_mmu_update(mmu_updates, &mmu_update_idx, 19.278 - (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND, 19.279 - MMUEXT_PIN_L1_TABLE) ) 19.280 - goto out; 19.281 - for ( j = 0; j < 1024; j++ ) 19.282 - { 19.283 - if ( page[j] & _PAGE_PRESENT ) 19.284 - { 19.285 - if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns ) 19.286 - { 19.287 - ERROR("Frame number in page table is out of range"); 19.288 - goto out; 19.289 - } 19.290 - if ( (pfn_type[pfn] != NONE) && (page[j] & _PAGE_RW) ) 19.291 - { 19.292 - ERROR("Write access requested for a restricted frame"); 19.293 - goto out; 19.294 - } 19.295 - page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT); 19.296 - page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT; 19.297 - } 19.298 - if ( add_mmu_update(mmu_updates, &mmu_update_idx, 19.299 - (unsigned long)&ppage[j], page[j]) ) 19.300 - goto out; 19.301 - } 19.302 - break; 19.303 - case L2TAB: 19.304 - memset(ppage, 0, PAGE_SIZE); 19.305 - if ( add_mmu_update(mmu_updates, &mmu_update_idx, 19.306 - (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND, 19.307 - MMUEXT_PIN_L2_TABLE) ) 19.308 - goto out; 19.309 - for ( j = 0; j < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); j++ ) 19.310 - { 19.311 - if ( page[j] & _PAGE_PRESENT ) 19.312 - { 19.313 - if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns ) 19.314 - { 19.315 - ERROR("Frame number in page table is out of range"); 19.316 - goto out; 19.317 - } 19.318 - if ( pfn_type[pfn] != L1TAB ) 19.319 - { 19.320 - ERROR("Page table mistyping"); 19.321 - goto out; 19.322 - } 19.323 - /* Haven't reached the L1 table yet. Ensure it is safe! */ 19.324 - if ( pfn > i ) 19.325 - { 19.326 - unsigned long **l1 = map_pfn(pfn_to_mfn_table[pfn]); 19.327 - memset(l1, 0, PAGE_SIZE); 19.328 - unmap_pfn(l1); 19.329 - } 19.330 - page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE); 19.331 - page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT; 19.332 - } 19.333 - if ( add_mmu_update(mmu_updates, &mmu_update_idx, 19.334 - (unsigned long)&ppage[j], page[j]) ) 19.335 - goto out; 19.336 - } 19.337 - break; 19.338 - default: 19.339 - memcpy(ppage, page, PAGE_SIZE); 19.340 - break; 19.341 - } 19.342 - /* NB. Must flush before unmapping page, as pass VAs to Xen. */ 19.343 - if ( flush_mmu_updates(mmu_updates, &mmu_update_idx) ) 19.344 - goto out; 19.345 - unmap_pfn(ppage); 19.346 - 19.347 - if ( add_mmu_update(mmu_updates, &mmu_update_idx, 19.348 - (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, i) ) 19.349 - goto out; 19.350 - } 19.351 - 19.352 - if ( flush_mmu_updates(mmu_updates, &mmu_update_idx) ) 19.353 - goto out; 19.354 - 19.355 - verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n"); 19.356 - 19.357 - /* Uncanonicalise the suspend-record frame number and poke resume rec. */ 19.358 - pfn = ctxt.i386_ctxt.esi; 19.359 - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) ) 19.360 - { 19.361 - ERROR("Suspend record frame number is bad"); 19.362 - goto out; 19.363 - } 19.364 - ctxt.i386_ctxt.esi = mfn = pfn_to_mfn_table[pfn]; 19.365 - p_srec = map_pfn(mfn); 19.366 - p_srec->resume_info.nr_pages = nr_pfns; 19.367 - p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT; 19.368 - p_srec->resume_info.dom_id = dom; 19.369 - p_srec->resume_info.flags = 0; 19.370 - unmap_pfn(p_srec); 19.371 - 19.372 - /* Uncanonicalise each GDT frame number. */ 19.373 - if ( ctxt.gdt_ents > 8192 ) 19.374 - { 19.375 - ERROR("GDT entry count out of range"); 19.376 - goto out; 19.377 - } 19.378 - for ( i = 0; i < ctxt.gdt_ents; i += 512 ) 19.379 - { 19.380 - pfn = ctxt.gdt_frames[i]; 19.381 - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) ) 19.382 - { 19.383 - ERROR("GDT frame number is bad"); 19.384 - goto out; 19.385 - } 19.386 - ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn]; 19.387 - } 19.388 - 19.389 - /* Uncanonicalise the page table base pointer. */ 19.390 - pfn = ctxt.pt_base >> PAGE_SHIFT; 19.391 - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) ) 19.392 - { 19.393 - ERROR("PT base is bad"); 19.394 - goto out; 19.395 - } 19.396 - ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT; 19.397 - 19.398 - /* Uncanonicalise the pfn-to-mfn table frame-number list. */ 19.399 - for ( i = 0; i < nr_pfns; i += 1024 ) 19.400 - { 19.401 - unsigned long copy_size = (nr_pfns - i) * sizeof(unsigned long); 19.402 - if ( copy_size > PAGE_SIZE ) copy_size = PAGE_SIZE; 19.403 - pfn = pfn_to_mfn_frame_list[i/1024]; 19.404 - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) ) 19.405 - { 19.406 - ERROR("PFN-to-MFN frame number is bad"); 19.407 - goto out; 19.408 - } 19.409 - ppage = map_pfn(pfn_to_mfn_table[pfn]); 19.410 - memcpy(ppage, &pfn_to_mfn_table[i], copy_size); 19.411 - unmap_pfn(ppage); 19.412 - } 19.413 - 19.414 - /* 19.415 - * Safety checking of saved context: 19.416 - * 1. i386_ctxt is fine, as Xen checks that on context switch. 19.417 - * 2. i387_ctxt is fine, as it can't hurt Xen. 19.418 - * 3. trap_ctxt needs the code selectors checked. 19.419 - * 4. fast_trap_idx is checked by Xen. 19.420 - * 5. ldt base must be page-aligned, no more than 8192 ents, ... 19.421 - * 6. gdt already done, and further checking is done by Xen. 19.422 - * 7. check that ring1_ss is safe. 19.423 - * 8. pt_base is already done. 19.424 - * 9. debugregs are checked by Xen. 19.425 - * 10. callback code selectors need checking. 19.426 - */ 19.427 - for ( i = 0; i < 256; i++ ) 19.428 - { 19.429 - ctxt.trap_ctxt[i].vector = i; 19.430 - if ( (ctxt.trap_ctxt[i].cs & 3) == 0 ) 19.431 - ctxt.trap_ctxt[i].cs = FLAT_RING1_CS; 19.432 - } 19.433 - if ( (ctxt.ring1_ss & 3) == 0 ) 19.434 - ctxt.ring1_ss = FLAT_RING1_DS; 19.435 - if ( (ctxt.event_callback_cs & 3) == 0 ) 19.436 - ctxt.event_callback_cs = FLAT_RING1_CS; 19.437 - if ( (ctxt.failsafe_callback_cs & 3) == 0 ) 19.438 - ctxt.failsafe_callback_cs = FLAT_RING1_CS; 19.439 - if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) || 19.440 - (ctxt.ldt_ents > 8192) || 19.441 - (ctxt.ldt_base > HYPERVISOR_VIRT_START) || 19.442 - ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) ) 19.443 - { 19.444 - ERROR("Bad LDT base or size"); 19.445 - goto out; 19.446 - } 19.447 - 19.448 - op.cmd = DOM0_BUILDDOMAIN; 19.449 - op.u.builddomain.domain = dom; 19.450 - op.u.builddomain.num_vifs = 1; 19.451 - memcpy(&op.u.builddomain.ctxt, &ctxt, sizeof(ctxt)); 19.452 - rc = do_dom0_op(&op); 19.453 - 19.454 - out: 19.455 - if ( rc != 0 ) 19.456 - { 19.457 - if ( dom != 0 ) 19.458 - { 19.459 - op.cmd = DOM0_DESTROYDOMAIN; 19.460 - op.u.destroydomain.domain = dom; 19.461 - op.u.destroydomain.force = 1; 19.462 - (void)do_dom0_op(&op); 19.463 - } 19.464 - } 19.465 - else 19.466 - { 19.467 - /* Success: print the domain id. */ 19.468 - verbose_printf("DOM=%ld\n", dom); 19.469 - } 19.470 - 19.471 - if ( pfn_to_mfn_table != NULL ) 19.472 - free(pfn_to_mfn_table); 19.473 - if ( pfn_type != NULL ) 19.474 - free(pfn_type); 19.475 - 19.476 - gzclose(gfd); 19.477 - 19.478 - return (rc == 0) ? dom : rc; 19.479 -}
20.1 --- a/tools/libxi/libxi_linux_save.c Wed Nov 19 17:22:42 2003 +0000 20.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 20.3 @@ -1,380 +0,0 @@ 20.4 -/****************************************************************************** 20.5 - * libxi_linux_save.c 20.6 - * 20.7 - * Save the state of a running Xenolinux session. 20.8 - * 20.9 - * Copyright (c) 2003, K A Fraser. 20.10 - */ 20.11 - 20.12 -#include "libxi_private.h" 20.13 -#include <asm-xeno/suspend.h> 20.14 -#include <zlib.h> 20.15 - 20.16 -/* This may allow us to create a 'quiet' command-line option, if necessary. */ 20.17 -#define verbose_printf(_f, _a...) \ 20.18 - do { \ 20.19 - if ( !verbose ) break; \ 20.20 - printf( _f , ## _a ); \ 20.21 - fflush(stdout); \ 20.22 - } while ( 0 ) 20.23 - 20.24 -/* 20.25 - * Returns TRUE if the given machine frame number has a unique mapping 20.26 - * in the guest's pseudophysical map. 20.27 - */ 20.28 -#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \ 20.29 - (((_mfn) < (1024*1024)) && \ 20.30 - (pfn_to_mfn_table[mfn_to_pfn_table[_mfn]] == (_mfn))) 20.31 - 20.32 -/* Returns TRUE if MFN is successfully converted to a PFN. */ 20.33 -#define translate_mfn_to_pfn(_pmfn) \ 20.34 -({ \ 20.35 - unsigned long mfn = *(_pmfn); \ 20.36 - int _res = 1; \ 20.37 - if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) \ 20.38 - _res = 0; \ 20.39 - else \ 20.40 - *(_pmfn) = mfn_to_pfn_table[mfn]; \ 20.41 - _res; \ 20.42 -}) 20.43 - 20.44 -static int check_pfn_ownership(unsigned long mfn, unsigned int dom) 20.45 -{ 20.46 - dom0_op_t op; 20.47 - op.cmd = DOM0_GETPAGEFRAMEINFO; 20.48 - op.u.getpageframeinfo.pfn = mfn; 20.49 - if ( (do_dom0_op(&op) < 0) || (op.u.getpageframeinfo.domain != dom) ) 20.50 - return 0; 20.51 - return 1; 20.52 -} 20.53 - 20.54 -#define GETPFN_ERR (~0U) 20.55 -static unsigned int get_pfn_type(unsigned long mfn) 20.56 -{ 20.57 - dom0_op_t op; 20.58 - op.cmd = DOM0_GETPAGEFRAMEINFO; 20.59 - op.u.getpageframeinfo.pfn = mfn; 20.60 - if ( do_dom0_op(&op) < 0 ) 20.61 - { 20.62 - PERROR("Unexpected failure when getting page frame info!"); 20.63 - return GETPFN_ERR; 20.64 - } 20.65 - return op.u.getpageframeinfo.type; 20.66 -} 20.67 - 20.68 -static int checked_write(gzFile fd, void *buf, size_t count) 20.69 -{ 20.70 - int rc; 20.71 - while ( ((rc = gzwrite(fd, buf, count)) == -1) && (errno = EINTR) ) 20.72 - continue; 20.73 - return rc == count; 20.74 -} 20.75 - 20.76 -int xi_linux_save(unsigned int domid, const char *state_file, int verbose) 20.77 -{ 20.78 - dom0_op_t op; 20.79 - int rc = 1, i, j; 20.80 - unsigned long mfn; 20.81 - unsigned int prev_pc, this_pc; 20.82 - 20.83 - /* Remember if we stopped the guest, so we can restart it on exit. */ 20.84 - int we_stopped_it = 0; 20.85 - 20.86 - /* The new domain's shared-info frame number. */ 20.87 - unsigned long shared_info_frame; 20.88 - 20.89 - /* A copy of the CPU context of the guest. */ 20.90 - full_execution_context_t ctxt; 20.91 - 20.92 - /* A copy of the domain's name. */ 20.93 - char name[MAX_DOMAIN_NAME]; 20.94 - 20.95 - /* A table containg the type of each PFN (/not/ MFN!). */ 20.96 - unsigned long *pfn_type = NULL; 20.97 - 20.98 - /* A temporary mapping, and a copy, of one frame of guest memory. */ 20.99 - unsigned long *ppage, page[1024]; 20.100 - 20.101 - /* A temporary mapping, and a copy, of the pfn-to-mfn table frame list. */ 20.102 - unsigned long *p_pfn_to_mfn_frame_list, pfn_to_mfn_frame_list[1024]; 20.103 - /* A temporary mapping of one frame in the above list. */ 20.104 - unsigned long *pfn_to_mfn_frame; 20.105 - 20.106 - /* A table mapping each PFN to its current MFN. */ 20.107 - unsigned long *pfn_to_mfn_table = NULL; 20.108 - /* A table mapping each current MFN to its canonical PFN. */ 20.109 - unsigned long *mfn_to_pfn_table = NULL; 20.110 - 20.111 - /* A temporary mapping, and a copy, of the guest's suspend record. */ 20.112 - suspend_record_t *p_srec, srec; 20.113 - 20.114 - /* The name and descriptor of the file that we are writing to. */ 20.115 - int fd; 20.116 - gzFile gfd; 20.117 - 20.118 - if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 ) 20.119 - { 20.120 - PERROR("Could not open file for writing"); 20.121 - return 1; 20.122 - } 20.123 - 20.124 - /* 20.125 - * Compression rate 1: we want speed over compression. We're mainly going 20.126 - * for those zero pages, after all. 20.127 - */ 20.128 - if ( (gfd = gzdopen(fd, "wb1")) == NULL ) 20.129 - { 20.130 - ERROR("Could not allocate compression state for state file"); 20.131 - close(fd); 20.132 - return 1; 20.133 - } 20.134 - 20.135 - /* Ensure that the domain exists, and that it is stopped. */ 20.136 - for ( ; ; ) 20.137 - { 20.138 - op.cmd = DOM0_GETDOMAININFO; 20.139 - op.u.getdomaininfo.domain = domid; 20.140 - if ( (do_dom0_op(&op) < 0) || (op.u.getdomaininfo.domain != domid) ) 20.141 - { 20.142 - PERROR("Could not get info on domain"); 20.143 - goto out; 20.144 - } 20.145 - 20.146 - memcpy(&ctxt, &op.u.getdomaininfo.ctxt, sizeof(ctxt)); 20.147 - memcpy(name, op.u.getdomaininfo.name, sizeof(name)); 20.148 - shared_info_frame = op.u.getdomaininfo.shared_info_frame; 20.149 - 20.150 - if ( op.u.getdomaininfo.state == DOMSTATE_STOPPED ) 20.151 - break; 20.152 - 20.153 - we_stopped_it = 1; 20.154 - 20.155 - op.cmd = DOM0_STOPDOMAIN; 20.156 - op.u.stopdomain.domain = domid; 20.157 - (void)do_dom0_op(&op); 20.158 - 20.159 - sleep(1); 20.160 - } 20.161 - 20.162 - /* A cheesy test to see whether the domain contains valid state. */ 20.163 - if ( ctxt.pt_base == 0 ) 20.164 - { 20.165 - ERROR("Domain is not in a valid Xenolinux state"); 20.166 - goto out; 20.167 - } 20.168 - 20.169 - if ( init_pfn_mapper() < 0 ) 20.170 - goto out; 20.171 - 20.172 - /* Is the suspend-record MFN actually valid for this domain? */ 20.173 - if ( !check_pfn_ownership(ctxt.i386_ctxt.esi, domid) ) 20.174 - { 20.175 - ERROR("Invalid state record pointer"); 20.176 - goto out; 20.177 - } 20.178 - 20.179 - /* If the suspend-record MFN is okay then grab a copy of it to @srec. */ 20.180 - p_srec = map_pfn(ctxt.i386_ctxt.esi); 20.181 - memcpy(&srec, p_srec, sizeof(srec)); 20.182 - unmap_pfn(p_srec); 20.183 - 20.184 - if ( srec.nr_pfns > 1024*1024 ) 20.185 - { 20.186 - ERROR("Invalid state record -- pfn count out of range"); 20.187 - goto out; 20.188 - } 20.189 - 20.190 - if ( !check_pfn_ownership(srec.pfn_to_mfn_frame_list, domid) ) 20.191 - { 20.192 - ERROR("Invalid pfn-to-mfn frame list pointer"); 20.193 - goto out; 20.194 - } 20.195 - 20.196 - /* Grab a copy of the pfn-to-mfn table frame list. */ 20.197 - p_pfn_to_mfn_frame_list = map_pfn(srec.pfn_to_mfn_frame_list); 20.198 - memcpy(pfn_to_mfn_frame_list, p_pfn_to_mfn_frame_list, PAGE_SIZE); 20.199 - unmap_pfn(p_pfn_to_mfn_frame_list); 20.200 - 20.201 - /* We want zeroed memory so use calloc rather than malloc. */ 20.202 - mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024); 20.203 - pfn_to_mfn_table = calloc(1, 4 * srec.nr_pfns); 20.204 - pfn_type = calloc(1, 4 * srec.nr_pfns); 20.205 - 20.206 - if ( (mfn_to_pfn_table == NULL) || 20.207 - (pfn_to_mfn_table == NULL) || 20.208 - (pfn_type == NULL) ) 20.209 - { 20.210 - errno = ENOMEM; 20.211 - goto out; 20.212 - } 20.213 - 20.214 - 20.215 - /* 20.216 - * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this 20.217 - * loop we have each MFN mapped at most once. Note that there may be MFNs 20.218 - * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP. 20.219 - */ 20.220 - pfn_to_mfn_frame = NULL; 20.221 - for ( i = 0; i < srec.nr_pfns; i++ ) 20.222 - { 20.223 - /* Each frameful of table frames must be checked & mapped on demand. */ 20.224 - if ( (i & 1023) == 0 ) 20.225 - { 20.226 - mfn = pfn_to_mfn_frame_list[i/1024]; 20.227 - if ( !check_pfn_ownership(mfn, domid) ) 20.228 - { 20.229 - ERROR("Invalid frame number if pfn-to-mfn frame list"); 20.230 - goto out; 20.231 - } 20.232 - if ( pfn_to_mfn_frame != NULL ) 20.233 - unmap_pfn(pfn_to_mfn_frame); 20.234 - pfn_to_mfn_frame = map_pfn(mfn); 20.235 - } 20.236 - 20.237 - mfn = pfn_to_mfn_frame[i & 1023]; 20.238 - 20.239 - if ( !check_pfn_ownership(mfn, domid) ) 20.240 - { 20.241 - ERROR("Invalid frame specified with pfn-to-mfn table"); 20.242 - goto out; 20.243 - } 20.244 - 20.245 - /* Did we map this MFN already? That would be invalid! */ 20.246 - if ( MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) 20.247 - { 20.248 - ERROR("A machine frame appears twice in pseudophys space"); 20.249 - goto out; 20.250 - } 20.251 - 20.252 - pfn_to_mfn_table[i] = mfn; 20.253 - mfn_to_pfn_table[mfn] = i; 20.254 - 20.255 - /* Query page type by MFN, but store it by PFN. */ 20.256 - if ( (pfn_type[i] = get_pfn_type(mfn)) == GETPFN_ERR ) 20.257 - goto out; 20.258 - } 20.259 - 20.260 - /* Canonicalise the suspend-record frame number. */ 20.261 - if ( !translate_mfn_to_pfn(&ctxt.i386_ctxt.esi) ) 20.262 - { 20.263 - ERROR("State record is not in range of pseudophys map"); 20.264 - goto out; 20.265 - } 20.266 - 20.267 - /* Canonicalise each GDT frame number. */ 20.268 - for ( i = 0; i < ctxt.gdt_ents; i += 512 ) 20.269 - { 20.270 - if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) ) 20.271 - { 20.272 - ERROR("GDT frame is not in range of pseudophys map"); 20.273 - goto out; 20.274 - } 20.275 - } 20.276 - 20.277 - /* Canonicalise the page table base pointer. */ 20.278 - if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) ) 20.279 - { 20.280 - ERROR("PT base is not in range of pseudophys map"); 20.281 - goto out; 20.282 - } 20.283 - ctxt.pt_base = mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT; 20.284 - 20.285 - /* Canonicalise the pfn-to-mfn table frame-number list. */ 20.286 - for ( i = 0; i < srec.nr_pfns; i += 1024 ) 20.287 - { 20.288 - if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) ) 20.289 - { 20.290 - ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys"); 20.291 - goto out; 20.292 - } 20.293 - } 20.294 - 20.295 - /* Start writing out the saved-domain record. */ 20.296 - ppage = map_pfn(shared_info_frame); 20.297 - if ( !checked_write(gfd, "XenoLinuxSuspend", 16) || 20.298 - !checked_write(gfd, name, sizeof(name)) || 20.299 - !checked_write(gfd, &srec.nr_pfns, sizeof(unsigned long)) || 20.300 - !checked_write(gfd, &ctxt, sizeof(ctxt)) || 20.301 - !checked_write(gfd, ppage, PAGE_SIZE) || 20.302 - !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) || 20.303 - !checked_write(gfd, pfn_type, 4 * srec.nr_pfns) ) 20.304 - { 20.305 - ERROR("Error when writing to state file"); 20.306 - goto out; 20.307 - } 20.308 - unmap_pfn(ppage); 20.309 - 20.310 - verbose_printf("Saving memory pages: 0%%"); 20.311 - 20.312 - /* Now write out each data page, canonicalising page tables as we go... */ 20.313 - prev_pc = 0; 20.314 - for ( i = 0; i < srec.nr_pfns; i++ ) 20.315 - { 20.316 - this_pc = (i * 100) / srec.nr_pfns; 20.317 - if ( (this_pc - prev_pc) >= 5 ) 20.318 - { 20.319 - verbose_printf("\b\b\b\b%3d%%", this_pc); 20.320 - prev_pc = this_pc; 20.321 - } 20.322 - 20.323 - mfn = pfn_to_mfn_table[i]; 20.324 - 20.325 - ppage = map_pfn(mfn); 20.326 - memcpy(page, ppage, PAGE_SIZE); 20.327 - unmap_pfn(ppage); 20.328 - 20.329 - if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) ) 20.330 - { 20.331 - for ( j = 0; 20.332 - j < ((pfn_type[i] == L2TAB) ? 20.333 - (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 20.334 - j++ ) 20.335 - { 20.336 - if ( !(page[j] & _PAGE_PRESENT) ) continue; 20.337 - mfn = page[j] >> PAGE_SHIFT; 20.338 - if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) 20.339 - { 20.340 - ERROR("Frame number in pagetable page is invalid"); 20.341 - goto out; 20.342 - } 20.343 - page[j] &= PAGE_SIZE - 1; 20.344 - page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT; 20.345 - } 20.346 - } 20.347 - 20.348 - if ( !checked_write(gfd, page, PAGE_SIZE) ) 20.349 - { 20.350 - ERROR("Error when writing to state file"); 20.351 - goto out; 20.352 - } 20.353 - } 20.354 - 20.355 - verbose_printf("\b\b\b\b100%%\nMemory saved.\n"); 20.356 - 20.357 - /* Success! */ 20.358 - rc = 0; 20.359 - 20.360 - out: 20.361 - /* Restart the domain if we had to stop it to save its state. */ 20.362 - if ( we_stopped_it ) 20.363 - { 20.364 - op.cmd = DOM0_STARTDOMAIN; 20.365 - op.u.startdomain.domain = domid; 20.366 - (void)do_dom0_op(&op); 20.367 - } 20.368 - 20.369 - gzclose(gfd); 20.370 - 20.371 - if ( pfn_to_mfn_table != NULL ) 20.372 - free(pfn_to_mfn_table); 20.373 - if ( mfn_to_pfn_table != NULL ) 20.374 - free(mfn_to_pfn_table); 20.375 - if ( pfn_type != NULL ) 20.376 - free(pfn_type); 20.377 - 20.378 - /* On error, make sure the file is deleted. */ 20.379 - if ( rc != 0 ) 20.380 - unlink(state_file); 20.381 - 20.382 - return !!rc; 20.383 -}
21.1 --- a/tools/libxi/libxi_misc.c Wed Nov 19 17:22:42 2003 +0000 21.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 21.3 @@ -1,50 +0,0 @@ 21.4 -/****************************************************************************** 21.5 - * libxi_misc.c 21.6 - * 21.7 - * Miscellaneous control interface functions. 21.8 - */ 21.9 - 21.10 -#include "libxi_private.h" 21.11 - 21.12 -int privcmd_fd = -1; 21.13 - 21.14 -int xi_interface_open(void) 21.15 -{ 21.16 - if ( (privcmd_fd == -1) && 21.17 - ((privcmd_fd = open("/proc/xeno/privcmd", O_RDWR)) < 0) ) 21.18 - { 21.19 - privcmd_fd = -1; 21.20 - return -1; 21.21 - } 21.22 - return 0; 21.23 -} 21.24 - 21.25 -int xi_interface_close(void) 21.26 -{ 21.27 - if ( privcmd_fd != -1 ) 21.28 - { 21.29 - close(privcmd_fd); 21.30 - privcmd_fd = -1; 21.31 - } 21.32 - return 0; 21.33 -} 21.34 - 21.35 - 21.36 -#define CONSOLE_RING_CLEAR 1 21.37 - 21.38 -int xi_readconsolering(char *str, unsigned int max_chars, int clear) 21.39 -{ 21.40 - int ret; 21.41 - dom0_op_t op; 21.42 - 21.43 - op.cmd = DOM0_READCONSOLE; 21.44 - op.u.readconsole.str = (unsigned long)str; 21.45 - op.u.readconsole.count = max_chars; 21.46 - op.u.readconsole.cmd = clear ? CONSOLE_RING_CLEAR : 0; 21.47 - 21.48 - if ( (ret = do_dom0_op(&op)) > 0 ) 21.49 - str[ret] = '\0'; 21.50 - 21.51 - return ret; 21.52 -} 21.53 -
22.1 --- a/tools/libxi/libxi_private.c Wed Nov 19 17:22:42 2003 +0000 22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 22.3 @@ -1,34 +0,0 @@ 22.4 -/****************************************************************************** 22.5 - * libxi_private.c 22.6 - * 22.7 - * Helper functions for the rest of the library. 22.8 - */ 22.9 - 22.10 -#include "libxi_private.h" 22.11 - 22.12 -static int devmem_fd = -1; 22.13 - 22.14 -int init_pfn_mapper(void) 22.15 -{ 22.16 - if ( (devmem_fd == -1) && 22.17 - ((devmem_fd = open("/dev/mem", O_RDWR)) < 0) ) 22.18 - { 22.19 - devmem_fd = -1; 22.20 - return -1; 22.21 - } 22.22 - return 0; 22.23 -} 22.24 - 22.25 -void *map_pfn(unsigned long pfn) 22.26 -{ 22.27 - void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, 22.28 - MAP_SHARED, devmem_fd, pfn << PAGE_SHIFT); 22.29 - if ( vaddr == MAP_FAILED ) 22.30 - return NULL; 22.31 - return vaddr; 22.32 -} 22.33 - 22.34 -void unmap_pfn(void *vaddr) 22.35 -{ 22.36 - (void)munmap(vaddr, PAGE_SIZE); 22.37 -}
23.1 --- a/tools/libxi/libxi_private.h Wed Nov 19 17:22:42 2003 +0000 23.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 23.3 @@ -1,155 +0,0 @@ 23.4 - 23.5 -#ifndef __LIBXI_PRIVATE_H__ 23.6 -#define __LIBXI_PRIVATE_H__ 23.7 - 23.8 -typedef unsigned char u8; 23.9 -typedef unsigned short u16; 23.10 -typedef unsigned long u32; 23.11 -typedef unsigned long long u64; 23.12 -typedef signed char s8; 23.13 -typedef signed short s16; 23.14 -typedef signed long s32; 23.15 -typedef signed long long s64; 23.16 - 23.17 -#include <unistd.h> 23.18 -#include <stdio.h> 23.19 -#include <errno.h> 23.20 -#include <fcntl.h> 23.21 -#include <sys/mman.h> 23.22 -#include <sys/types.h> 23.23 -#include <sys/stat.h> 23.24 -#include <stdlib.h> 23.25 -#include <sys/ioctl.h> 23.26 -#include <errno.h> 23.27 -#include <string.h> 23.28 - 23.29 -#include "xi.h" 23.30 - 23.31 -#include <asm-xeno/proc_cmd.h> 23.32 -#include <hypervisor-ifs/hypervisor-if.h> 23.33 -#include <hypervisor-ifs/dom0_ops.h> 23.34 -#include <hypervisor-ifs/vbd.h> 23.35 - 23.36 -#define _PAGE_PRESENT 0x001 23.37 -#define _PAGE_RW 0x002 23.38 -#define _PAGE_USER 0x004 23.39 -#define _PAGE_PWT 0x008 23.40 -#define _PAGE_PCD 0x010 23.41 -#define _PAGE_ACCESSED 0x020 23.42 -#define _PAGE_DIRTY 0x040 23.43 -#define _PAGE_PAT 0x080 23.44 -#define _PAGE_PSE 0x080 23.45 -#define _PAGE_GLOBAL 0x100 23.46 - 23.47 - 23.48 -#define L1_PAGETABLE_SHIFT 12 23.49 -#define L2_PAGETABLE_SHIFT 22 23.50 - 23.51 -#define ENTRIES_PER_L1_PAGETABLE 1024 23.52 -#define ENTRIES_PER_L2_PAGETABLE 1024 23.53 - 23.54 -#define PAGE_SHIFT L1_PAGETABLE_SHIFT 23.55 -#define PAGE_SIZE (1UL << PAGE_SHIFT) 23.56 -#define PAGE_MASK (~(PAGE_SIZE-1)) 23.57 - 23.58 -typedef struct { unsigned long l1_lo; } l1_pgentry_t; 23.59 -typedef struct { unsigned long l2_lo; } l2_pgentry_t; 23.60 - 23.61 -#define l1_table_offset(_a) \ 23.62 - (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1)) 23.63 -#define l2_table_offset(_a) \ 23.64 - ((_a) >> L2_PAGETABLE_SHIFT) 23.65 - 23.66 -#define ERROR(_m) \ 23.67 - fprintf(stderr, "ERROR: %s\n", (_m)) 23.68 - 23.69 -#define PERROR(_m) \ 23.70 - fprintf(stderr, "ERROR: %s (%d = %s)\n", (_m), errno, strerror(errno)) 23.71 - 23.72 -extern int privcmd_fd; 23.73 -static inline int do_privcmd(unsigned int cmd, unsigned long data) 23.74 -{ 23.75 - return ioctl(privcmd_fd, cmd, data); 23.76 -} 23.77 - 23.78 -static inline int do_xen_hypercall(privcmd_hypercall_t *hypercall) 23.79 -{ 23.80 - return do_privcmd(IOCTL_PRIVCMD_HYPERCALL, (unsigned long)hypercall); 23.81 -} 23.82 - 23.83 -static inline int do_dom0_op(dom0_op_t *op) 23.84 -{ 23.85 - int ret = -1; 23.86 - privcmd_hypercall_t hypercall; 23.87 - 23.88 - op->interface_version = DOM0_INTERFACE_VERSION; 23.89 - 23.90 - hypercall.op = __HYPERVISOR_dom0_op; 23.91 - hypercall.arg[0] = (unsigned long)op; 23.92 - 23.93 - if ( mlock(op, sizeof(*op)) != 0 ) 23.94 - goto out1; 23.95 - 23.96 - if ( (ret = do_xen_hypercall(&hypercall)) < 0 ) 23.97 - { 23.98 - if ( errno == EACCES ) 23.99 - fprintf(stderr, "Dom0 operation failed -- need to" 23.100 - " rebuild the user-space tool set?\n"); 23.101 - goto out2; 23.102 - } 23.103 - 23.104 - ret = 0; 23.105 - 23.106 - out2: (void)munlock(op, sizeof(*op)); 23.107 - out1: return ret; 23.108 -} 23.109 - 23.110 -static inline int do_network_op(network_op_t *op) 23.111 -{ 23.112 - int ret = -1; 23.113 - privcmd_hypercall_t hypercall; 23.114 - 23.115 - hypercall.op = __HYPERVISOR_network_op; 23.116 - hypercall.arg[0] = (unsigned long)op; 23.117 - 23.118 - if ( mlock(op, sizeof(*op)) != 0 ) 23.119 - goto out1; 23.120 - 23.121 - if ( (ret = do_xen_hypercall(&hypercall)) < 0 ) 23.122 - goto out2; 23.123 - 23.124 - ret = 0; 23.125 - 23.126 - out2: (void)munlock(op, sizeof(*op)); 23.127 - out1: return ret; 23.128 -} 23.129 - 23.130 - 23.131 -static inline int do_block_io_op(block_io_op_t *op) 23.132 -{ 23.133 - int ret = -1; 23.134 - privcmd_hypercall_t hypercall; 23.135 - 23.136 - hypercall.op = __HYPERVISOR_block_io_op; 23.137 - hypercall.arg[0] = (unsigned long)op; 23.138 - 23.139 - if ( mlock(op, sizeof(*op)) != 0 ) 23.140 - goto out1; 23.141 - 23.142 - if ( do_xen_hypercall(&hypercall) < 0 ) 23.143 - goto out2; 23.144 - 23.145 - ret = 0; 23.146 - 23.147 - out2: (void)munlock(op, sizeof(*op)); 23.148 - out1: return ret; 23.149 -} 23.150 - 23.151 -/* 23.152 - * PFN mapping. 23.153 - */ 23.154 -int init_pfn_mapper(void); 23.155 -void *map_pfn(unsigned long pfn); 23.156 -void unmap_pfn(void *vaddr); 23.157 - 23.158 -#endif /* __LIBXI_PRIVATE_H__ */
24.1 --- a/tools/libxi/libxi_vbd.c Wed Nov 19 17:22:42 2003 +0000 24.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 24.3 @@ -1,116 +0,0 @@ 24.4 -/****************************************************************************** 24.5 - * libxi_vbd.c 24.6 - * 24.7 - * API for manipulating and accessing per-domain virtual block devices. 24.8 - * 24.9 - * Copyright (c) 2003, K A Fraser. 24.10 - */ 24.11 - 24.12 -#define _GNU_SOURCE 24.13 -#include "libxi_private.h" 24.14 - 24.15 -int xi_vbd_create(unsigned int domid, unsigned short vbdid, int writeable) 24.16 -{ 24.17 - block_io_op_t op; 24.18 - op.cmd = BLOCK_IO_OP_VBD_CREATE; 24.19 - op.u.create_params.domain = domid; 24.20 - op.u.create_params.vdevice = vbdid; 24.21 - op.u.create_params.mode = VBD_MODE_R | (writeable ? VBD_MODE_W : 0); 24.22 - return do_block_io_op(&op); 24.23 -} 24.24 - 24.25 - 24.26 -int xi_vbd_destroy(unsigned int domid, unsigned short vbdid) 24.27 -{ 24.28 - block_io_op_t op; 24.29 - op.cmd = BLOCK_IO_OP_VBD_DELETE; 24.30 - op.u.delete_params.domain = domid; 24.31 - op.u.delete_params.vdevice = vbdid; 24.32 - return do_block_io_op(&op); 24.33 -} 24.34 - 24.35 - 24.36 -int xi_vbd_add_extent(unsigned int domid, 24.37 - unsigned short vbdid, 24.38 - unsigned short real_device, 24.39 - unsigned long start_sector, 24.40 - unsigned long nr_sectors) 24.41 -{ 24.42 - block_io_op_t op; 24.43 - op.cmd = BLOCK_IO_OP_VBD_ADD; 24.44 - op.u.add_params.domain = domid; 24.45 - op.u.add_params.vdevice = vbdid; 24.46 - op.u.add_params.extent.device = real_device; 24.47 - op.u.add_params.extent.start_sector = start_sector; 24.48 - op.u.add_params.extent.nr_sectors = nr_sectors; 24.49 - return do_block_io_op(&op); 24.50 -} 24.51 - 24.52 - 24.53 -int xi_vbd_delete_extent(unsigned int domid, 24.54 - unsigned short vbdid, 24.55 - unsigned short real_device, 24.56 - unsigned long start_sector, 24.57 - unsigned long nr_sectors) 24.58 -{ 24.59 - block_io_op_t op; 24.60 - op.cmd = BLOCK_IO_OP_VBD_REMOVE; 24.61 - op.u.add_params.domain = domid; 24.62 - op.u.add_params.vdevice = vbdid; 24.63 - op.u.add_params.extent.device = real_device; 24.64 - op.u.add_params.extent.start_sector = start_sector; 24.65 - op.u.add_params.extent.nr_sectors = nr_sectors; 24.66 - return do_block_io_op(&op); 24.67 -} 24.68 - 24.69 - 24.70 -int xi_vbd_probe(unsigned int domid, 24.71 - unsigned short vbdid, 24.72 - unsigned int max_vbds, 24.73 - xi_vbd_t *vbds) 24.74 -{ 24.75 - block_io_op_t op; 24.76 - xen_disk_info_t *xdi = &op.u.probe_params.xdi; 24.77 - int i, j, ret, allocsz = max_vbds * sizeof(xen_disk_t); 24.78 - 24.79 - op.cmd = BLOCK_IO_OP_VBD_PROBE; 24.80 - op.u.probe_params.domain = domid; 24.81 - 24.82 - xdi->max = max_vbds; 24.83 - xdi->disks = malloc(allocsz); 24.84 - xdi->count = 0; 24.85 - 24.86 - if ( (xdi->disks == NULL) || (mlock(xdi->disks, allocsz) != 0) ) 24.87 - { 24.88 - if ( xdi->disks != NULL ) 24.89 - free(xdi->disks); 24.90 - return -ENOMEM; 24.91 - } 24.92 - 24.93 - ret = do_block_io_op(&op); 24.94 - 24.95 - (void)munlock(xdi->disks, allocsz); 24.96 - 24.97 - if ( ret >= 0 ) 24.98 - { 24.99 - for ( i = 0, j = 0; i < xdi->count; i++ ) 24.100 - { 24.101 - if ( !(xdi->disks[i].info & XD_FLAG_VIRT) ) 24.102 - continue; 24.103 - 24.104 - vbds[j].domid = xdi->disks[i].domain; 24.105 - vbds[j].vbdid = xdi->disks[i].device; 24.106 - vbds[j].flags = (xdi->disks[i].info & XD_FLAG_RO) ? 24.107 - 0 : XI_VBDF_WRITEABLE; 24.108 - vbds[j].nr_sectors = xdi->disks[i].capacity; 24.109 - 24.110 - j++; 24.111 - } 24.112 - 24.113 - ret = j; 24.114 - } 24.115 - 24.116 - free(xdi->disks); 24.117 - 24.118 - return ret; 24.119 -}
25.1 --- a/tools/libxi/libxi_vif.c Wed Nov 19 17:22:42 2003 +0000 25.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 25.3 @@ -1,66 +0,0 @@ 25.4 -/****************************************************************************** 25.5 - * libxi_vif.c 25.6 - * 25.7 - * API for manipulating and accessing per-network-interface parameters. 25.8 - * 25.9 - * Copyright (c) 2003, K A Fraser. 25.10 - */ 25.11 - 25.12 -#include "libxi_private.h" 25.13 - 25.14 -int xi_vif_scheduler_set(unsigned int domid, 25.15 - unsigned int vifid, 25.16 - xi_vif_sched_params_t *params) 25.17 -{ 25.18 - network_op_t netop; 25.19 - netop.cmd = NETWORK_OP_VIFSETPARAMS; 25.20 - netop.u.vif_setparams.domain = domid; 25.21 - netop.u.vif_setparams.vif = vifid; 25.22 - netop.u.vif_setparams.credit_bytes = params->credit_bytes; 25.23 - netop.u.vif_setparams.credit_usec = params->credit_usec; 25.24 - return do_network_op(&netop); 25.25 -} 25.26 - 25.27 - 25.28 -int xi_vif_scheduler_get(unsigned int domid, 25.29 - unsigned int vifid, 25.30 - xi_vif_sched_params_t *params) 25.31 -{ 25.32 - network_op_t netop; 25.33 - int rc; 25.34 - 25.35 - netop.cmd = NETWORK_OP_VIFGETINFO; 25.36 - netop.u.vif_getinfo.domain = domid; 25.37 - netop.u.vif_getinfo.vif = vifid; 25.38 - 25.39 - if ( (rc = do_network_op(&netop)) >= 0 ) 25.40 - { 25.41 - params->credit_bytes = netop.u.vif_getinfo.credit_bytes; 25.42 - params->credit_usec = netop.u.vif_getinfo.credit_usec; 25.43 - } 25.44 - 25.45 - return rc; 25.46 -} 25.47 - 25.48 - 25.49 -int xi_vif_stats_get(unsigned int domid, 25.50 - unsigned int vifid, 25.51 - xi_vif_stats_t *stats) 25.52 -{ 25.53 - network_op_t netop; 25.54 - int rc; 25.55 - 25.56 - netop.cmd = NETWORK_OP_VIFGETINFO; 25.57 - netop.u.vif_getinfo.domain = domid; 25.58 - netop.u.vif_getinfo.vif = vifid; 25.59 - 25.60 - if ( (rc = do_network_op(&netop)) >= 0 ) 25.61 - { 25.62 - stats->tx_bytes = netop.u.vif_getinfo.total_bytes_sent; 25.63 - stats->tx_pkts = netop.u.vif_getinfo.total_packets_sent; 25.64 - stats->rx_bytes = netop.u.vif_getinfo.total_bytes_received; 25.65 - stats->rx_pkts = netop.u.vif_getinfo.total_packets_received; 25.66 - } 25.67 - 25.68 - return rc; 25.69 -}
26.1 --- a/tools/libxi/rpm.spec Wed Nov 19 17:22:42 2003 +0000 26.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 26.3 @@ -1,28 +0,0 @@ 26.4 -Summary: Xen control interface library 26.5 -Name: xen-internal-library 26.6 -Version: 1.2 26.7 -Release: 1 26.8 -License: Xen 26.9 -Group: Xen 26.10 -BuildRoot: %{staging} 26.11 -%description 26.12 -Library to make it easier to access the Xen control interfaces. 26.13 - 26.14 -%pre 26.15 -%preun 26.16 -%install 26.17 -install -m 0755 -d $RPM_BUILD_ROOT/lib 26.18 -install -m 0755 libxi.a $RPM_BUILD_ROOT/lib/libxi.a 26.19 -install -m 0755 libxi.so $RPM_BUILD_ROOT/lib/libxi.so 26.20 -install -m 0755 -d $RPM_BUILD_ROOT/include 26.21 -install -m 0644 xi.h $RPM_BUILD_ROOT/include/xi.h 26.22 -%clean 26.23 -%post 26.24 -%postun 26.25 -%files 26.26 -%defattr(-,root,root) 26.27 -%dir /lib 26.28 -/lib/libxi.a 26.29 -/lib/libxi.so 26.30 -%dir /include 26.31 -/include/xi.h
27.1 --- a/tools/libxi/xi.h Wed Nov 19 17:22:42 2003 +0000 27.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 27.3 @@ -1,99 +0,0 @@ 27.4 -/****************************************************************************** 27.5 - * xi.h 27.6 - * 27.7 - * A library for low-level access to the Xen control interfaces. 27.8 - * 27.9 - * Copyright (c) 2003, K A Fraser. 27.10 - */ 27.11 - 27.12 -#ifndef __XI_H__ 27.13 -#define __XI_H__ 27.14 - 27.15 -int xi_interface_open(void); 27.16 -int xi_interface_close(void); 27.17 - 27.18 -typedef struct { 27.19 - unsigned int domid; 27.20 - unsigned int cpu; 27.21 - int has_cpu; 27.22 - int stopped; 27.23 - unsigned long nr_pages; 27.24 - unsigned long long cpu_time; 27.25 -#define XI_DOMINFO_MAXNAME 16 27.26 - char name[XI_DOMINFO_MAXNAME]; 27.27 -} xi_dominfo_t; 27.28 - 27.29 -int xi_domain_create(unsigned int mem_kb, const char *name); 27.30 -int xi_domain_start(unsigned int domid); 27.31 -int xi_domain_stop(unsigned int domid); 27.32 -int xi_domain_destroy(unsigned int domid, int force); 27.33 -int xi_domain_getinfo(unsigned int first_domid, 27.34 - unsigned int max_doms, 27.35 - xi_dominfo_t *info); 27.36 - 27.37 -int xi_linux_save(unsigned int domid, const char *state_file, int verbose); 27.38 -int xi_linux_restore(const char *state_file, int verbose); 27.39 -int xi_linux_build(unsigned int domid, 27.40 - const char *image_name, 27.41 - const char *ramdisk_name, 27.42 - const char *cmdline, 27.43 - int verbose); 27.44 - 27.45 -int xi_bvtsched_global_set(unsigned long ctx_allow); 27.46 -int xi_bvtsched_domain_set(unsigned int domid, 27.47 - unsigned long mcuadv, 27.48 - unsigned long warp, 27.49 - unsigned long warpl, 27.50 - unsigned long warpu); 27.51 - 27.52 -typedef struct { 27.53 - unsigned long credit_bytes; 27.54 - unsigned long credit_usec; 27.55 -} xi_vif_sched_params_t; 27.56 - 27.57 -typedef struct { 27.58 - unsigned long long tx_bytes, tx_pkts; 27.59 - unsigned long long rx_bytes, rx_pkts; 27.60 -} xi_vif_stats_t; 27.61 - 27.62 -int xi_vif_scheduler_set(unsigned int domid, 27.63 - unsigned int vifid, 27.64 - xi_vif_sched_params_t *params); 27.65 -int xi_vif_scheduler_get(unsigned int domid, 27.66 - unsigned int vifid, 27.67 - xi_vif_sched_params_t *params); 27.68 -int xi_vif_stats_get(unsigned int domid, 27.69 - unsigned int vifid, 27.70 - xi_vif_stats_t *stats); 27.71 - 27.72 -typedef struct { 27.73 -#define XI_VBDDOM_PROBE_ALL (~0U) 27.74 - unsigned int domid; 27.75 - unsigned short vbdid; 27.76 -#define XI_VBDF_WRITEABLE (1<<0) 27.77 - unsigned long flags; 27.78 - unsigned long nr_sectors; 27.79 -} xi_vbd_t; 27.80 - 27.81 - 27.82 -int xi_vbd_create(unsigned int domid, unsigned short vbdid, int writeable); 27.83 -int xi_vbd_destroy(unsigned int domid, unsigned short vbdid); 27.84 -int xi_vbd_add_extent(unsigned int domid, 27.85 - unsigned short vbdid, 27.86 - unsigned short real_device, 27.87 - unsigned long start_sector, 27.88 - unsigned long nr_sectors); 27.89 -int xi_vbd_delete_extent(unsigned int domid, 27.90 - unsigned short vbdid, 27.91 - unsigned short real_device, 27.92 - unsigned long start_sector, 27.93 - unsigned long nr_sectors); 27.94 -int xi_vbd_probe(unsigned int domid, 27.95 - unsigned short vbdid, 27.96 - unsigned int max_vbds, 27.97 - xi_vbd_t *vbds); 27.98 - 27.99 -int xi_readconsolering(char *str, unsigned int max_chars, int clear); 27.100 - 27.101 - 27.102 -#endif /* __XI_H__ */