ia64/xen-unstable

changeset 961:31e50e01f987

bitkeeper revision 1.616 (3fbca451cCh4CiAzcPFCijGwNS4Bjg)

Many files:
Mods to new xclib.
Makefile:
new file
Rename: tools/xc/Makefile -> tools/xc/lib/Makefile
rpm.spec:
Rename: tools/xc/rpm.spec -> tools/xc/lib/rpm.spec
xc.h:
Rename: tools/xc/xc.h -> tools/xc/lib/xc.h
libxc_private.h:
Rename: tools/xc/libxc_private.h -> tools/xc/lib/libxc_private.h
libxc_vif.c:
Rename: tools/xc/libxc_vif.c -> tools/xc/lib/libxc_vif.c
libxc_vbd.c:
Rename: tools/xc/libxc_vbd.c -> tools/xc/lib/libxc_vbd.c
libxc_private.c:
Rename: tools/xc/libxc_private.c -> tools/xc/lib/libxc_private.c
libxc_misc.c:
Rename: tools/xc/libxc_misc.c -> tools/xc/lib/libxc_misc.c
libxc_linux_save.c:
Rename: tools/xc/libxc_linux_save.c -> tools/xc/lib/libxc_linux_save.c
libxc_linux_restore.c:
Rename: tools/xc/libxc_linux_restore.c -> tools/xc/lib/libxc_linux_restore.c
libxc_linux_build.c:
Rename: tools/xc/libxc_linux_build.c -> tools/xc/lib/libxc_linux_build.c
libxc_domain.c:
Rename: tools/xc/libxc_domain.c -> tools/xc/lib/libxc_domain.c
libxc_bvtsched.c:
Rename: tools/xc/libxc_bvtsched.c -> tools/xc/lib/libxc_bvtsched.c
Many files:
mvdir
author kaf24@scramble.cl.cam.ac.uk
date Thu Nov 20 11:24:01 2003 +0000 (2003-11-20)
parents 835dc1d3ad23
children 57093982ce20 3f16bb4c82c9
files .rootkeys tools/Makefile 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/xc/Makefile tools/xc/lib/Makefile tools/xc/lib/libxc_bvtsched.c tools/xc/lib/libxc_domain.c tools/xc/lib/libxc_linux_build.c tools/xc/lib/libxc_linux_restore.c tools/xc/lib/libxc_linux_save.c tools/xc/lib/libxc_misc.c tools/xc/lib/libxc_private.c tools/xc/lib/libxc_private.h tools/xc/lib/libxc_vbd.c tools/xc/lib/libxc_vif.c tools/xc/lib/rpm.spec tools/xc/lib/xc.h
line diff
     1.1 --- a/.rootkeys	Thu Nov 20 10:03:52 2003 +0000
     1.2 +++ b/.rootkeys	Thu Nov 20 11:24:01 2003 +0000
     1.3 @@ -184,19 +184,6 @@ 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/libxc/Makefile
     1.8 -3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/libxc/libxc_bvtsched.c
     1.9 -3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/libxc/libxc_domain.c
    1.10 -3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/libxc/libxc_linux_build.c
    1.11 -3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/libxc/libxc_linux_restore.c
    1.12 -3fbba6db7li3FJiABYtCmuGxOJxEGw tools/libxc/libxc_linux_save.c
    1.13 -3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/libxc/libxc_misc.c
    1.14 -3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/libxc/libxc_private.c
    1.15 -3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/libxc/libxc_private.h
    1.16 -3fbba6dcoGq9hQlksrBUfC2P5F6sGg tools/libxc/libxc_vbd.c
    1.17 -3fbba6dc38q-ioRlwSR_quw4G3qUeQ tools/libxc/libxc_vif.c
    1.18 -3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/libxc/rpm.spec
    1.19 -3fbba6dcrNxtygEcgJYAJJ1gCQqfsA tools/libxc/xc.h
    1.20  3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
    1.21  3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
    1.22  3f6dc140C8tAeBfroAF24VrmCS4v_w tools/misc/miniterm/README
    1.23 @@ -211,6 +198,20 @@ 3f13d81eQ9Vz-h-6RDGFkNR9CRP95g tools/mis
    1.24  3f13d81e6Z6806ihYYUw8GVKNkYnuw tools/misc/xen_nat_enable.README
    1.25  3f1668d4F29Jsw0aC0bJEIkOBiagiQ tools/misc/xen_read_console.c
    1.26  3f87ba90EUVPQLVOlFG0sW89BCwouQ tools/misc/xen_refresh_dev.c
    1.27 +3fbca441SjQr8vJwTQIgH1laysaWog tools/xc/Makefile
    1.28 +3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/xc/lib/Makefile
    1.29 +3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/xc/lib/libxc_bvtsched.c
    1.30 +3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/xc/lib/libxc_domain.c
    1.31 +3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/xc/lib/libxc_linux_build.c
    1.32 +3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/xc/lib/libxc_linux_restore.c
    1.33 +3fbba6db7li3FJiABYtCmuGxOJxEGw tools/xc/lib/libxc_linux_save.c
    1.34 +3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/xc/lib/libxc_misc.c
    1.35 +3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/xc/lib/libxc_private.c
    1.36 +3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/xc/lib/libxc_private.h
    1.37 +3fbba6dcoGq9hQlksrBUfC2P5F6sGg tools/xc/lib/libxc_vbd.c
    1.38 +3fbba6dc38q-ioRlwSR_quw4G3qUeQ tools/xc/lib/libxc_vif.c
    1.39 +3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/xc/lib/rpm.spec
    1.40 +3fbba6dcrNxtygEcgJYAJJ1gCQqfsA tools/xc/lib/xc.h
    1.41  3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING
    1.42  3f841450eJvqAD1Dldc0_aOweGiglQ xen/GUEST_CHANGES
    1.43  3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile
     2.1 --- a/tools/Makefile	Thu Nov 20 10:03:52 2003 +0000
     2.2 +++ b/tools/Makefile	Thu Nov 20 11:24:01 2003 +0000
     2.3 @@ -21,20 +21,20 @@ all:
     2.4  	$(MAKE) -C balloon
     2.5  	$(MAKE) -C control
     2.6  	$(MAKE) -C internal
     2.7 -	$(MAKE) -C libxc
     2.8 +	$(MAKE) -C xc
     2.9  	$(MAKE) -C misc
    2.10  
    2.11  install: all
    2.12  	$(MAKE) -C balloon install
    2.13  	$(MAKE) -C control install
    2.14  	$(MAKE) -C internal install
    2.15 -	$(MAKE) -C libxc install
    2.16 +	$(MAKE) -C xc install
    2.17  	$(MAKE) -C misc install
    2.18  
    2.19  clean:
    2.20  	$(MAKE) -C balloon clean
    2.21  	$(MAKE) -C control clean
    2.22  	$(MAKE) -C internal clean
    2.23 -	$(MAKE) -C libxc clean
    2.24 +	$(MAKE) -C xc clean
    2.25  	$(MAKE) -C misc clean
    2.26  
     3.1 --- a/tools/libxc/Makefile	Thu Nov 20 10:03:52 2003 +0000
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,48 +0,0 @@
     3.4 -
     3.5 -CC       = gcc
     3.6 -CFLAGS   = -c -Wall -O3 
     3.7 -CFLAGS  += -I../../xen/include -I../../xenolinux-sparse/include
     3.8 -
     3.9 -HDRS     = $(wildcard *.h)
    3.10 -OBJS     = $(patsubst %.c,%.o,$(wildcard libxc_*.c))
    3.11 -
    3.12 -LIBS     = libxc.a libxc.so
    3.13 -
    3.14 -all: check-for-zlib $(LIBS)
    3.15 -	ranlib libxc.a
    3.16 -
    3.17 -check-for-zlib:
    3.18 -	@if [ ! -e /usr/include/zlib.h ]; then \
    3.19 -	echo "***********************************************************"; \
    3.20 -	echo "ERROR: install zlib header files (http://www.gzip.org/zlib)"; \
    3.21 -	echo "***********************************************************"; \
    3.22 -	false; \
    3.23 -	fi
    3.24 -
    3.25 -install: all
    3.26 -	mkdir -p ../../../install/lib
    3.27 -	mkdir -p ../../../install/include
    3.28 -	cp -a $(LIBS) ../../../install/lib
    3.29 -	for i in $(LIBS) do ; chmod 755 ../../../install/bin/$i ; done
    3.30 -	cp -a xc.h ../../../install/include
    3.31 -	chmod 644 ../../../install/include/xc.h
    3.32 -
    3.33 -clean:
    3.34 -	$(RM) *.a *.so *.o *.rpm $(LIBS)
    3.35 -
    3.36 -rpm: all
    3.37 -	rm -rf staging
    3.38 -	mkdir staging
    3.39 -	mkdir staging/i386
    3.40 -	rpmbuild --define "staging$$PWD/staging" --define '_builddir.' \
    3.41 -		--define "_rpmdir$$PWD/staging" -bb rpm.spec
    3.42 -	mv staging/i386/*.rpm .
    3.43 -	rm -rf staging
    3.44 -
    3.45 -libxc.so: $(OBJS)
    3.46 -	$(LD) -shared -o $@ $^ -lz
    3.47 -
    3.48 -libxc.a: libxc.a($(OBJS))
    3.49 -
    3.50 -%.o: %.c $(HDRS) Makefile
    3.51 -	$(CC) $(CFLAGS) -o $@ $<
     4.1 --- a/tools/libxc/libxc_bvtsched.c	Thu Nov 20 10:03:52 2003 +0000
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,33 +0,0 @@
     4.4 -/******************************************************************************
     4.5 - * libxc_bvtsched.c
     4.6 - * 
     4.7 - * API for manipulating parameters of the Borrowed Virtual Time scheduler.
     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_bvtsched_global_set(unsigned long ctx_allow)
    4.15 -{
    4.16 -    dom0_op_t op;
    4.17 -    op.cmd = DOM0_BVTCTL;
    4.18 -    op.u.bvtctl.ctx_allow = ctx_allow;
    4.19 -    return do_dom0_op(&op);
    4.20 -}
    4.21 -
    4.22 -int xc_bvtsched_domain_set(unsigned int domid,
    4.23 -                           unsigned long mcuadv,
    4.24 -                           unsigned long warp,
    4.25 -                           unsigned long warpl,
    4.26 -                           unsigned long warpu)
    4.27 -{
    4.28 -    dom0_op_t op;
    4.29 -    op.cmd = DOM0_ADJUSTDOM;
    4.30 -    op.u.adjustdom.domain  = domid;
    4.31 -    op.u.adjustdom.mcu_adv = mcuadv;
    4.32 -    op.u.adjustdom.warp    = warp;
    4.33 -    op.u.adjustdom.warpl   = warpl;
    4.34 -    op.u.adjustdom.warpu   = warpu;
    4.35 -    return do_dom0_op(&op);
    4.36 -}
     5.1 --- a/tools/libxc/libxc_domain.c	Thu Nov 20 10:03:52 2003 +0000
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,80 +0,0 @@
     5.4 -/******************************************************************************
     5.5 - * libxc_domain.c
     5.6 - * 
     5.7 - * API for manipulating and obtaining information on domains.
     5.8 - * 
     5.9 - * Copyright (c) 2003, K A Fraser.
    5.10 - */
    5.11 -
    5.12 -#include "libxc_private.h"
    5.13 -
    5.14 -int xc_domain_create(unsigned int mem_kb, const char *name)
    5.15 -{
    5.16 -    int err;
    5.17 -    dom0_op_t op;
    5.18 -
    5.19 -    op.cmd = DOM0_CREATEDOMAIN;
    5.20 -    op.u.createdomain.memory_kb = mem_kb;
    5.21 -    strncpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
    5.22 -    op.u.createdomain.name[MAX_DOMAIN_NAME-1] = '\0';
    5.23 -
    5.24 -    err = do_dom0_op(&op);
    5.25 -
    5.26 -    return (err < 0) ? err : op.u.createdomain.domain;
    5.27 -}    
    5.28 -
    5.29 -
    5.30 -int xc_domain_start(unsigned int domid)
    5.31 -{
    5.32 -    dom0_op_t op;
    5.33 -    op.cmd = DOM0_STARTDOMAIN;
    5.34 -    op.u.startdomain.domain = domid;
    5.35 -    return do_dom0_op(&op);
    5.36 -}    
    5.37 -
    5.38 -
    5.39 -int xc_domain_stop(unsigned int domid)
    5.40 -{
    5.41 -    dom0_op_t op;
    5.42 -    op.cmd = DOM0_STOPDOMAIN;
    5.43 -    op.u.stopdomain.domain = domid;
    5.44 -    return do_dom0_op(&op);
    5.45 -}    
    5.46 -
    5.47 -
    5.48 -int xc_domain_destroy(unsigned int domid, int force)
    5.49 -{
    5.50 -    dom0_op_t op;
    5.51 -    op.cmd = DOM0_DESTROYDOMAIN;
    5.52 -    op.u.destroydomain.domain = domid;
    5.53 -    op.u.destroydomain.force  = !!force;
    5.54 -    return do_dom0_op(&op);
    5.55 -}
    5.56 -
    5.57 -int xc_domain_getinfo(unsigned int first_domid,
    5.58 -                      unsigned int max_doms,
    5.59 -                      xc_dominfo_t *info)
    5.60 -{
    5.61 -    unsigned int nr_doms, next_domid = first_domid;
    5.62 -    dom0_op_t op;
    5.63 -
    5.64 -    for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
    5.65 -    {
    5.66 -        op.cmd = DOM0_GETDOMAININFO;
    5.67 -        op.u.getdomaininfo.domain = next_domid;
    5.68 -        if ( do_dom0_op(&op) < 0 )
    5.69 -            break;
    5.70 -        info->domid   = op.u.getdomaininfo.domain;
    5.71 -        info->cpu     = op.u.getdomaininfo.processor;
    5.72 -        info->has_cpu = op.u.getdomaininfo.has_cpu;
    5.73 -        info->stopped = (op.u.getdomaininfo.state == DOMSTATE_STOPPED);
    5.74 -        info->nr_pages = op.u.getdomaininfo.tot_pages;
    5.75 -        info->cpu_time = op.u.getdomaininfo.cpu_time;
    5.76 -        strncpy(info->name, op.u.getdomaininfo.name, XC_DOMINFO_MAXNAME);
    5.77 -        info->name[XC_DOMINFO_MAXNAME-1] = '\0';
    5.78 -
    5.79 -        next_domid = op.u.getdomaininfo.domain + 1;
    5.80 -    }
    5.81 -
    5.82 -    return nr_doms;
    5.83 -}
     6.1 --- a/tools/libxc/libxc_linux_build.c	Thu Nov 20 10:03:52 2003 +0000
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,481 +0,0 @@
     6.4 -/******************************************************************************
     6.5 - * libxc_linux_build.c
     6.6 - */
     6.7 -
     6.8 -#include "libxc_private.h"
     6.9 -#include <zlib.h>
    6.10 -
    6.11 -/* This string is written to the head of every guest kernel image. */
    6.12 -#define GUEST_SIG   "XenoGues"
    6.13 -#define SIG_LEN    8
    6.14 -
    6.15 -#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
    6.16 -#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
    6.17 -
    6.18 -static long get_tot_pages(int domid)
    6.19 -{
    6.20 -    dom0_op_t op;
    6.21 -    op.cmd = DOM0_GETDOMAININFO;
    6.22 -    op.u.getdomaininfo.domain = domid;
    6.23 -    return (do_dom0_op(&op) < 0) ? -1 : op.u.getdomaininfo.tot_pages;
    6.24 -}
    6.25 -
    6.26 -static int get_pfn_list(
    6.27 -    int domid, unsigned long *pfn_buf, unsigned long max_pfns)
    6.28 -{
    6.29 -    dom0_op_t op;
    6.30 -    int ret;
    6.31 -    op.cmd = DOM0_GETMEMLIST;
    6.32 -    op.u.getmemlist.domain   = domid;
    6.33 -    op.u.getmemlist.max_pfns = max_pfns;
    6.34 -    op.u.getmemlist.buffer   = pfn_buf;
    6.35 -
    6.36 -    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
    6.37 -        return -1;
    6.38 -
    6.39 -    ret = do_dom0_op(&op);
    6.40 -
    6.41 -    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
    6.42 -
    6.43 -    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
    6.44 -}
    6.45 -
    6.46 -static int send_pgupdates(mmu_update_t *updates, int nr_updates)
    6.47 -{
    6.48 -    int ret = -1;
    6.49 -    privcmd_hypercall_t hypercall;
    6.50 -
    6.51 -    hypercall.op     = __HYPERVISOR_mmu_update;
    6.52 -    hypercall.arg[0] = (unsigned long)updates;
    6.53 -    hypercall.arg[1] = (unsigned long)nr_updates;
    6.54 -
    6.55 -    if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 )
    6.56 -        goto out1;
    6.57 -
    6.58 -    if ( do_xen_hypercall(&hypercall) < 0 )
    6.59 -        goto out2;
    6.60 -
    6.61 -    ret = 0;
    6.62 -
    6.63 - out2: (void)munlock(updates, nr_updates * sizeof(*updates));
    6.64 - out1: return ret;
    6.65 -}
    6.66 -
    6.67 -/* Read the kernel header, extracting the image size and load address. */
    6.68 -static int read_kernel_header(gzFile gfd, long dom_size, 
    6.69 -                              unsigned long *load_addr, int verbose)
    6.70 -{
    6.71 -    char signature[SIG_LEN];
    6.72 -
    6.73 -    gzread(gfd, signature, SIG_LEN);
    6.74 -    if ( strncmp(signature, GUEST_SIG, SIG_LEN) )
    6.75 -    {
    6.76 -        if ( verbose )
    6.77 -            ERROR("Kernel image does not contain required signature");
    6.78 -        return -1;
    6.79 -    }
    6.80 -
    6.81 -    /* Read the load address which immediately follows the Xeno signature. */
    6.82 -    gzread(gfd, load_addr, sizeof(unsigned long));
    6.83 -
    6.84 -    return 0;
    6.85 -}
    6.86 -
    6.87 -static int copy_to_domain_page(unsigned long dst_pfn, void *src_page)
    6.88 -{
    6.89 -    void *vaddr = map_pfn(dst_pfn);
    6.90 -    if ( vaddr == NULL )
    6.91 -        return -1;
    6.92 -    memcpy(vaddr, src_page, PAGE_SIZE);
    6.93 -    unmap_pfn(vaddr);
    6.94 -    return 0;
    6.95 -}
    6.96 -
    6.97 -static int setup_guestos(
    6.98 -    int dom, gzFile kernel_gfd, int initrd_fd, unsigned long tot_pages,
    6.99 -    unsigned long *virt_startinfo_addr, unsigned long virt_load_addr, 
   6.100 -    dom0_builddomain_t *builddomain, const char *cmdline,
   6.101 -    unsigned long shared_info_frame, int verbose)
   6.102 -{
   6.103 -    l1_pgentry_t *vl1tab = NULL, *vl1e = NULL;
   6.104 -    l2_pgentry_t *vl2tab = NULL, *vl2e = NULL;
   6.105 -    unsigned long *page_array = NULL;
   6.106 -    mmu_update_t *pgt_update_arr = NULL, *pgt_updates = NULL;
   6.107 -    int alloc_index, num_pt_pages;
   6.108 -    unsigned long l2tab;
   6.109 -    unsigned long l1tab = 0;
   6.110 -    unsigned long num_pgt_updates = 0;
   6.111 -    unsigned long count, pt_start, i, j;
   6.112 -    unsigned long initrd_addr = 0, initrd_len = 0;
   6.113 -    start_info_t *start_info;
   6.114 -    shared_info_t *shared_info;
   6.115 -    unsigned long ksize;
   6.116 -
   6.117 -    memset(builddomain, 0, sizeof(*builddomain));
   6.118 -
   6.119 -    if ( init_pfn_mapper() < 0 )
   6.120 -        goto error_out;
   6.121 -
   6.122 -    pgt_updates = malloc((tot_pages + 1024) * 3 * sizeof(mmu_update_t));
   6.123 -    page_array = malloc(tot_pages * sizeof(unsigned long));
   6.124 -    pgt_update_arr = pgt_updates;
   6.125 -    if ( (pgt_update_arr == NULL) || (page_array == NULL) )
   6.126 -    {
   6.127 -        if ( verbose )
   6.128 -            PERROR("Could not allocate memory");
   6.129 -        goto error_out;
   6.130 -    }
   6.131 -
   6.132 -    if ( get_pfn_list(dom, page_array, tot_pages) != tot_pages )
   6.133 -    {
   6.134 -        if ( verbose )
   6.135 -            PERROR("Could not get the page frame list");
   6.136 -        goto error_out;
   6.137 -    }
   6.138 -
   6.139 -    /* Load the guest OS image. Let it take no more than 1/2 memory.*/
   6.140 -    for ( i = 0; i < ((tot_pages/2)*PAGE_SIZE); i += PAGE_SIZE )
   6.141 -    {
   6.142 -        char page[PAGE_SIZE];
   6.143 -        int size;
   6.144 -        if ( (size = gzread(kernel_gfd, page, PAGE_SIZE)) == -1 )
   6.145 -        {
   6.146 -            if ( verbose )
   6.147 -                PERROR("Error reading kernel image, could not"
   6.148 -                       " read the whole image.");
   6.149 -            goto error_out;
   6.150 -        }
   6.151 -        if ( size == 0 )
   6.152 -            goto kernel_copied;
   6.153 -        copy_to_domain_page(page_array[i>>PAGE_SHIFT], page);
   6.154 -    }
   6.155 -    if ( verbose )
   6.156 -        ERROR("Kernel too big to safely fit in domain memory");
   6.157 -    goto error_out;
   6.158 -
   6.159 - kernel_copied:
   6.160 -    /* ksize is kernel-image size rounded up to a page boundary. */
   6.161 -    ksize = i;
   6.162 -
   6.163 -    /* Load the initial ramdisk image. */
   6.164 -    if ( initrd_fd >= 0 )
   6.165 -    {
   6.166 -        struct stat stat;
   6.167 -        unsigned long isize;
   6.168 -
   6.169 -        if ( fstat(initrd_fd, &stat) < 0 )
   6.170 -        {
   6.171 -            if ( verbose )
   6.172 -                PERROR("Could not stat the initrd image");
   6.173 -            goto error_out;
   6.174 -        }
   6.175 -        isize = stat.st_size;
   6.176 -        if ( (isize + ksize) > ((tot_pages/2) * PAGE_SIZE) )
   6.177 -        {
   6.178 -            if ( verbose )
   6.179 -                ERROR("Kernel/initrd too big to safely fit in domain memory");
   6.180 -            goto error_out;
   6.181 -        }
   6.182 -
   6.183 -        initrd_addr = virt_load_addr + ksize;
   6.184 -        initrd_len  = isize;
   6.185 -
   6.186 -        for ( j = 0, i = ksize; j < isize; j += PAGE_SIZE, i += PAGE_SIZE )
   6.187 -        {
   6.188 -            char page[PAGE_SIZE];
   6.189 -            int size = ((isize-j) < PAGE_SIZE) ? (isize-j) : PAGE_SIZE;
   6.190 -            if ( read(initrd_fd, page, size) != size )
   6.191 -            {
   6.192 -                if ( verbose )
   6.193 -                    PERROR("Error reading initrd image, could not"
   6.194 -                           " read the whole image.");
   6.195 -                goto error_out;
   6.196 -            } 
   6.197 -            copy_to_domain_page(page_array[i>>PAGE_SHIFT], page);
   6.198 -        }
   6.199 -    }
   6.200 -
   6.201 -    alloc_index = tot_pages - 1;
   6.202 -
   6.203 -    /* Count bottom-level PTs, rounding up. */
   6.204 -    num_pt_pages = (l1_table_offset(virt_load_addr) + tot_pages + 1023) / 1024;
   6.205 -
   6.206 -    /* We must also count the page directory. */
   6.207 -    num_pt_pages++;
   6.208 -
   6.209 -    /* Index of first PT page. */
   6.210 -    pt_start = tot_pages - num_pt_pages;
   6.211 -
   6.212 -    /*
   6.213 -     * First allocate page for page dir. Allocation goes backwards from the end
   6.214 -     * of the allocated physical address space.
   6.215 -     */
   6.216 -    l2tab = page_array[alloc_index] << PAGE_SHIFT;
   6.217 -    alloc_index--;
   6.218 -    builddomain->ctxt.pt_base = l2tab;
   6.219 -
   6.220 -    /*
   6.221 -     * Pin down l2tab addr as page dir page - causes hypervisor to provide
   6.222 -     * correct protection for the page
   6.223 -     */ 
   6.224 -    pgt_updates->ptr = l2tab | MMU_EXTENDED_COMMAND;
   6.225 -    pgt_updates->val = MMUEXT_PIN_L2_TABLE;
   6.226 -    pgt_updates++;
   6.227 -    num_pgt_updates++;
   6.228 -
   6.229 -    /* Initialise the page tables. */
   6.230 -    if ( (vl2tab = map_pfn(l2tab >> PAGE_SHIFT)) == NULL )
   6.231 -        goto error_out;
   6.232 -    memset(vl2tab, 0, PAGE_SIZE);
   6.233 -    vl2e = vl2tab + l2_table_offset(virt_load_addr);
   6.234 -    for ( count = 0; count < tot_pages; count++ )
   6.235 -    {    
   6.236 -        if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) 
   6.237 -        {
   6.238 -            l1tab = page_array[alloc_index] << PAGE_SHIFT;
   6.239 -            if ( (vl1tab = map_pfn(l1tab >> PAGE_SHIFT)) == NULL )
   6.240 -                goto error_out;
   6.241 -            memset(vl1tab, 0, PAGE_SIZE);
   6.242 -            alloc_index--;
   6.243 -		
   6.244 -            vl1e = vl1tab + l1_table_offset(virt_load_addr + 
   6.245 -                                            (count << PAGE_SHIFT));
   6.246 -
   6.247 -            /* make apropriate entry in the page directory */
   6.248 -            pgt_updates->ptr = (unsigned long)vl2e;
   6.249 -            pgt_updates->val = l1tab | L2_PROT;
   6.250 -            pgt_updates++;
   6.251 -            num_pgt_updates++;
   6.252 -            vl2e++;
   6.253 -        }
   6.254 -
   6.255 -        if ( count < pt_start )
   6.256 -        {
   6.257 -            pgt_updates->ptr = (unsigned long)vl1e;
   6.258 -            pgt_updates->val = (page_array[count] << PAGE_SHIFT) | L1_PROT;
   6.259 -            pgt_updates++;
   6.260 -            num_pgt_updates++;
   6.261 -            vl1e++;
   6.262 -        }
   6.263 -        else
   6.264 -        {
   6.265 -            pgt_updates->ptr = (unsigned long)vl1e;
   6.266 -            pgt_updates->val = 
   6.267 -                ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
   6.268 -            pgt_updates++;
   6.269 -            num_pgt_updates++;
   6.270 -            vl1e++;
   6.271 -        }
   6.272 -
   6.273 -        pgt_updates->ptr = 
   6.274 -            (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
   6.275 -        pgt_updates->val = count;
   6.276 -        pgt_updates++;
   6.277 -        num_pgt_updates++;
   6.278 -    }
   6.279 -
   6.280 -    *virt_startinfo_addr =
   6.281 -        virt_load_addr + ((alloc_index-1) << PAGE_SHIFT);
   6.282 -
   6.283 -    start_info = map_pfn(page_array[alloc_index-1]);
   6.284 -    memset(start_info, 0, sizeof(*start_info));
   6.285 -    start_info->pt_base     = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
   6.286 -    start_info->mod_start   = initrd_addr;
   6.287 -    start_info->mod_len     = initrd_len;
   6.288 -    start_info->nr_pages    = tot_pages;
   6.289 -    start_info->shared_info = shared_info_frame << PAGE_SHIFT;
   6.290 -    start_info->dom_id      = dom;
   6.291 -    start_info->flags       = 0;
   6.292 -    strncpy(start_info->cmd_line, cmdline, MAX_CMD_LEN);
   6.293 -    start_info->cmd_line[MAX_CMD_LEN-1] = '\0';
   6.294 -
   6.295 -    unmap_pfn(start_info);
   6.296 -
   6.297 -    /* shared_info page starts its life empty. */
   6.298 -    shared_info = map_pfn(shared_info_frame);
   6.299 -    memset(shared_info, 0, PAGE_SIZE);
   6.300 -    unmap_pfn(shared_info);
   6.301 -
   6.302 -    /* Send the page update requests down to the hypervisor. */
   6.303 -    if ( send_pgupdates(pgt_update_arr, num_pgt_updates) < 0 )
   6.304 -        goto error_out;
   6.305 -
   6.306 -    free(page_array);
   6.307 -    free(pgt_update_arr);
   6.308 -    return 0;
   6.309 -
   6.310 - error_out:
   6.311 -    if ( page_array == NULL )
   6.312 -        free(page_array);
   6.313 -    if ( pgt_update_arr == NULL )
   6.314 -        free(pgt_update_arr);
   6.315 -    return -1;
   6.316 -}
   6.317 -
   6.318 -int xc_domain_build(unsigned int domid,
   6.319 -                    const char *image_name,
   6.320 -                    const char *ramdisk_name,
   6.321 -                    const char *cmdline,
   6.322 -                    int verbose)
   6.323 -{
   6.324 -    dom0_op_t launch_op, op;
   6.325 -    unsigned long load_addr;
   6.326 -    long tot_pages;
   6.327 -    int kernel_fd, initrd_fd = -1;
   6.328 -    gzFile kernel_gfd;
   6.329 -    int rc, i;
   6.330 -    full_execution_context_t *ctxt;
   6.331 -    unsigned long virt_startinfo_addr;
   6.332 -
   6.333 -    if ( (tot_pages = get_tot_pages(domid)) < 0 )
   6.334 -    {
   6.335 -        if ( verbose )
   6.336 -            PERROR("Could not find total pages for domain");
   6.337 -        return 1;
   6.338 -    }
   6.339 -
   6.340 -    kernel_fd = open(image_name, O_RDONLY);
   6.341 -    if ( kernel_fd < 0 )
   6.342 -    {
   6.343 -        if ( verbose )
   6.344 -            PERROR("Could not open kernel image");
   6.345 -        return 1;
   6.346 -    }
   6.347 -
   6.348 -    if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
   6.349 -    {
   6.350 -        if ( verbose )
   6.351 -            PERROR("Could not allocate decompression state for state file");
   6.352 -        close(kernel_fd);
   6.353 -        return 1;
   6.354 -    }
   6.355 -
   6.356 -    rc = read_kernel_header(kernel_gfd,
   6.357 -                            tot_pages << (PAGE_SHIFT - 10), 
   6.358 -                            &load_addr, verbose);
   6.359 -    if ( rc < 0 )
   6.360 -        goto error_out;
   6.361 -    
   6.362 -    if ( (load_addr & (PAGE_SIZE-1)) != 0 )
   6.363 -    {
   6.364 -        if ( verbose )
   6.365 -            ERROR("We can only deal with page-aligned load addresses");
   6.366 -        goto error_out;
   6.367 -    }
   6.368 -
   6.369 -    if ( (load_addr + (tot_pages << PAGE_SHIFT)) > HYPERVISOR_VIRT_START )
   6.370 -    {
   6.371 -        if ( verbose )
   6.372 -            ERROR("Cannot map all domain memory without hitting Xen space");
   6.373 -        goto error_out;
   6.374 -    }
   6.375 -
   6.376 -    if ( ramdisk_name != NULL )
   6.377 -    {
   6.378 -        initrd_fd = open(ramdisk_name, O_RDONLY);
   6.379 -        if ( initrd_fd < 0 )
   6.380 -        {
   6.381 -            if ( verbose )
   6.382 -                PERROR("Could not open the initial ramdisk image");
   6.383 -            goto error_out;
   6.384 -        }
   6.385 -    }
   6.386 -
   6.387 -    op.cmd = DOM0_GETDOMAININFO;
   6.388 -    op.u.getdomaininfo.domain = domid;
   6.389 -    if ( (do_dom0_op(&op) < 0) || (op.u.getdomaininfo.domain != domid) )
   6.390 -    {
   6.391 -        if ( verbose )
   6.392 -            PERROR("Could not get info on domain");
   6.393 -        goto error_out;
   6.394 -    }
   6.395 -    if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) ||
   6.396 -         (op.u.getdomaininfo.ctxt.pt_base != 0) )
   6.397 -    {
   6.398 -        if ( verbose )
   6.399 -            ERROR("Domain is already constructed");
   6.400 -        goto error_out;
   6.401 -    }
   6.402 -
   6.403 -    if ( setup_guestos(domid, kernel_gfd, initrd_fd, tot_pages,
   6.404 -                       &virt_startinfo_addr,
   6.405 -                       load_addr, &launch_op.u.builddomain, cmdline,
   6.406 -                       op.u.getdomaininfo.shared_info_frame, verbose) < 0 )
   6.407 -    {
   6.408 -        if ( verbose )
   6.409 -            ERROR("Error constructing guest OS");
   6.410 -        goto error_out;
   6.411 -    }
   6.412 -
   6.413 -    if ( initrd_fd >= 0 )
   6.414 -        close(initrd_fd);
   6.415 -    gzclose(kernel_gfd);
   6.416 -
   6.417 -    ctxt = &launch_op.u.builddomain.ctxt;
   6.418 -
   6.419 -    ctxt->flags = 0;
   6.420 -
   6.421 -    /*
   6.422 -     * Initial register values:
   6.423 -     *  DS,ES,FS,GS = FLAT_RING1_DS
   6.424 -     *       CS:EIP = FLAT_RING1_CS:start_pc
   6.425 -     *       SS:ESP = FLAT_RING1_DS:start_stack
   6.426 -     *          ESI = start_info
   6.427 -     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
   6.428 -     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
   6.429 -     */
   6.430 -    ctxt->i386_ctxt.ds = FLAT_RING1_DS;
   6.431 -    ctxt->i386_ctxt.es = FLAT_RING1_DS;
   6.432 -    ctxt->i386_ctxt.fs = FLAT_RING1_DS;
   6.433 -    ctxt->i386_ctxt.gs = FLAT_RING1_DS;
   6.434 -    ctxt->i386_ctxt.ss = FLAT_RING1_DS;
   6.435 -    ctxt->i386_ctxt.cs = FLAT_RING1_CS;
   6.436 -    ctxt->i386_ctxt.eip = load_addr;
   6.437 -    ctxt->i386_ctxt.esp = virt_startinfo_addr;
   6.438 -    ctxt->i386_ctxt.esi = virt_startinfo_addr;
   6.439 -    ctxt->i386_ctxt.eflags = (1<<9) | (1<<2);
   6.440 -
   6.441 -    /* FPU is set up to default initial state. */
   6.442 -    memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt));
   6.443 -
   6.444 -    /* Virtual IDT is empty at start-of-day. */
   6.445 -    for ( i = 0; i < 256; i++ )
   6.446 -    {
   6.447 -        ctxt->trap_ctxt[i].vector = i;
   6.448 -        ctxt->trap_ctxt[i].cs     = FLAT_RING1_CS;
   6.449 -    }
   6.450 -    ctxt->fast_trap_idx = 0;
   6.451 -
   6.452 -    /* No LDT. */
   6.453 -    ctxt->ldt_ents = 0;
   6.454 -    
   6.455 -    /* Use the default Xen-provided GDT. */
   6.456 -    ctxt->gdt_ents = 0;
   6.457 -
   6.458 -    /* Ring 1 stack is the initial stack. */
   6.459 -    ctxt->ring1_ss  = FLAT_RING1_DS;
   6.460 -    ctxt->ring1_esp = virt_startinfo_addr;
   6.461 -
   6.462 -    /* No debugging. */
   6.463 -    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
   6.464 -
   6.465 -    /* No callback handlers. */
   6.466 -    ctxt->event_callback_cs     = FLAT_RING1_CS;
   6.467 -    ctxt->event_callback_eip    = 0;
   6.468 -    ctxt->failsafe_callback_cs  = FLAT_RING1_CS;
   6.469 -    ctxt->failsafe_callback_eip = 0;
   6.470 -
   6.471 -    launch_op.u.builddomain.domain   = domid;
   6.472 -    launch_op.u.builddomain.num_vifs = 1;
   6.473 -
   6.474 -    launch_op.cmd = DOM0_BUILDDOMAIN;
   6.475 -    rc = do_dom0_op(&launch_op);
   6.476 -    
   6.477 -    return rc;
   6.478 -
   6.479 - error_out:
   6.480 -    if ( initrd_fd >= 0 )
   6.481 -        close(initrd_fd);
   6.482 -    gzclose(kernel_gfd);
   6.483 -    return -1;
   6.484 -}
     7.1 --- a/tools/libxc/libxc_linux_restore.c	Thu Nov 20 10:03:52 2003 +0000
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,476 +0,0 @@
     7.4 -/******************************************************************************
     7.5 - * libxc_linux_restore.c
     7.6 - * 
     7.7 - * Restore the state of a 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 -static int get_pfn_list(
    7.25 -    int domain_id, unsigned long *pfn_buf, unsigned long max_pfns)
    7.26 -{
    7.27 -    dom0_op_t op;
    7.28 -    int ret;
    7.29 -    op.cmd = DOM0_GETMEMLIST;
    7.30 -    op.u.getmemlist.domain   = domain_id;
    7.31 -    op.u.getmemlist.max_pfns = max_pfns;
    7.32 -    op.u.getmemlist.buffer   = pfn_buf;
    7.33 -
    7.34 -    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
    7.35 -    {
    7.36 -        PERROR("Could not lock pfn list buffer");
    7.37 -        return -1;
    7.38 -    }    
    7.39 -
    7.40 -    ret = do_dom0_op(&op);
    7.41 -
    7.42 -    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
    7.43 -
    7.44 -    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
    7.45 -}
    7.46 -
    7.47 -#define MAX_MMU_UPDATES 1024
    7.48 -
    7.49 -static int flush_mmu_updates(mmu_update_t *mmu_updates,
    7.50 -                             int *mmu_update_idx)
    7.51 -{
    7.52 -    int err = 0;
    7.53 -    privcmd_hypercall_t hypercall;
    7.54 -
    7.55 -    if ( *mmu_update_idx == 0 )
    7.56 -        return 0;
    7.57 -
    7.58 -    hypercall.op     = __HYPERVISOR_mmu_update;
    7.59 -    hypercall.arg[0] = (unsigned long)mmu_updates;
    7.60 -    hypercall.arg[1] = (unsigned long)*mmu_update_idx;
    7.61 -
    7.62 -    if ( mlock(mmu_updates, sizeof(mmu_updates)) != 0 )
    7.63 -    {
    7.64 -        PERROR("Could not lock pagetable update array");
    7.65 -        err = 1;
    7.66 -        goto out;
    7.67 -    }
    7.68 -
    7.69 -    if ( do_xen_hypercall(&hypercall) < 0 )
    7.70 -    {
    7.71 -        ERROR("Failure when submitting mmu updates");
    7.72 -        err = 1;
    7.73 -    }
    7.74 -
    7.75 -    *mmu_update_idx = 0;
    7.76 -    
    7.77 -    (void)munlock(mmu_updates, sizeof(mmu_updates));
    7.78 -
    7.79 - out:
    7.80 -    return err;
    7.81 -}
    7.82 -
    7.83 -static int add_mmu_update(mmu_update_t *mmu_updates,
    7.84 -                          int *mmu_update_idx,
    7.85 -                          unsigned long ptr, 
    7.86 -                          unsigned long val)
    7.87 -{
    7.88 -    mmu_updates[*mmu_update_idx].ptr = ptr;
    7.89 -    mmu_updates[*mmu_update_idx].val = val;
    7.90 -    if ( ++*mmu_update_idx == MAX_MMU_UPDATES )
    7.91 -        return flush_mmu_updates(mmu_updates, mmu_update_idx);
    7.92 -    return 0;
    7.93 -}
    7.94 -
    7.95 -static int checked_read(gzFile fd, void *buf, size_t count)
    7.96 -{
    7.97 -    int rc;
    7.98 -    while ( ((rc = gzread(fd, buf, count)) == -1) && (errno == EINTR) )
    7.99 -        continue;
   7.100 -    return rc == count;
   7.101 -}
   7.102 -
   7.103 -int xc_linux_restore(const char *state_file, int verbose)
   7.104 -{
   7.105 -    dom0_op_t op;
   7.106 -    int rc = 1, i, j;
   7.107 -    unsigned long mfn, pfn, dom = 0;
   7.108 -    unsigned int prev_pc, this_pc;
   7.109 -    
   7.110 -    /* Number of page frames in use by this XenoLinux session. */
   7.111 -    unsigned long nr_pfns;
   7.112 -
   7.113 -    /* The new domain's shared-info frame number. */
   7.114 -    unsigned long shared_info_frame;
   7.115 -    unsigned char shared_info[PAGE_SIZE]; /* saved contents from file */
   7.116 -    
   7.117 -    /* A copy of the CPU context of the guest. */
   7.118 -    full_execution_context_t ctxt;
   7.119 -
   7.120 -    /* First 16 bytes of the state file must contain 'XenoLinuxSuspend'. */
   7.121 -    char signature[16];
   7.122 -    
   7.123 -    /* A copy of the domain's name. */
   7.124 -    char name[MAX_DOMAIN_NAME];
   7.125 -
   7.126 -    /* A table containg the type of each PFN (/not/ MFN!). */
   7.127 -    unsigned long *pfn_type = NULL;
   7.128 -
   7.129 -    /* A temporary mapping, and a copy, of one frame of guest memory. */
   7.130 -    unsigned long *ppage, page[1024];
   7.131 -
   7.132 -    /* A copy of the pfn-to-mfn table frame list. */
   7.133 -    unsigned long pfn_to_mfn_frame_list[1024];
   7.134 -
   7.135 -    /* A table mapping each PFN to its new MFN. */
   7.136 -    unsigned long *pfn_to_mfn_table = NULL;
   7.137 -
   7.138 -    /* A temporary mapping of the guest's suspend record. */
   7.139 -    suspend_record_t *p_srec;
   7.140 -
   7.141 -    /* The name and descriptor of the file that we are reading from. */
   7.142 -    int    fd;
   7.143 -    gzFile gfd;
   7.144 -
   7.145 -    mmu_update_t mmu_updates[MAX_MMU_UPDATES];
   7.146 -    int mmu_update_idx = 0;
   7.147 -
   7.148 -    if ( (fd = open(state_file, O_RDONLY)) == -1 )
   7.149 -    {
   7.150 -        PERROR("Could not open state file for reading");
   7.151 -        return 1;
   7.152 -    }
   7.153 -
   7.154 -    if ( (gfd = gzdopen(fd, "rb")) == NULL )
   7.155 -    {
   7.156 -        ERROR("Could not allocate decompression state for state file");
   7.157 -        close(fd);
   7.158 -        return 1;
   7.159 -    }
   7.160 -
   7.161 -    /* Start writing out the saved-domain record. */
   7.162 -    if ( !checked_read(gfd, signature, 16) ||
   7.163 -         (memcmp(signature, "XenoLinuxSuspend", 16) != 0) )
   7.164 -    {
   7.165 -        ERROR("Unrecognised state format -- no signature found");
   7.166 -        goto out;
   7.167 -    }
   7.168 -
   7.169 -    if ( !checked_read(gfd, name,                  sizeof(name)) ||
   7.170 -         !checked_read(gfd, &nr_pfns,              sizeof(unsigned long)) ||
   7.171 -         !checked_read(gfd, &ctxt,                 sizeof(ctxt)) ||
   7.172 -         !checked_read(gfd, shared_info,           PAGE_SIZE) ||
   7.173 -         !checked_read(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) )
   7.174 -    {
   7.175 -        ERROR("Error when reading from state file");
   7.176 -        goto out;
   7.177 -    }
   7.178 -
   7.179 -    for ( i = 0; i < MAX_DOMAIN_NAME; i++ )
   7.180 -    {
   7.181 -        if ( name[i] == '\0' ) break;
   7.182 -        if ( name[i] & 0x80 )
   7.183 -        {
   7.184 -            ERROR("Random characters in domain name");
   7.185 -            goto out;
   7.186 -        }
   7.187 -    }
   7.188 -    name[MAX_DOMAIN_NAME-1] = '\0';
   7.189 -
   7.190 -    if ( nr_pfns > 1024*1024 )
   7.191 -    {
   7.192 -        ERROR("Invalid state file -- pfn count out of range");
   7.193 -        goto out;
   7.194 -    }
   7.195 -
   7.196 -    /* We want zeroed memory so use calloc rather than malloc. */
   7.197 -    pfn_to_mfn_table = calloc(1, 4 * nr_pfns);
   7.198 -    pfn_type         = calloc(1, 4 * nr_pfns);    
   7.199 -
   7.200 -    if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) )
   7.201 -    {
   7.202 -        errno = ENOMEM;
   7.203 -        goto out;
   7.204 -    }
   7.205 -
   7.206 -    if ( !checked_read(gfd, pfn_type, 4 * nr_pfns) )
   7.207 -    {
   7.208 -        ERROR("Error when reading from state file");
   7.209 -        goto out;
   7.210 -    }
   7.211 -
   7.212 -    /* Create a new domain of the appropriate size, and find it's dom_id. */
   7.213 -    op.cmd = DOM0_CREATEDOMAIN;
   7.214 -    op.u.createdomain.memory_kb = nr_pfns * (PAGE_SIZE / 1024);
   7.215 -    memcpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
   7.216 -    if ( do_dom0_op(&op) < 0 )
   7.217 -    {
   7.218 -        ERROR("Could not create new domain");
   7.219 -        goto out;
   7.220 -    }
   7.221 -    dom = op.u.createdomain.domain;
   7.222 -
   7.223 -    /* Get the domain's shared-info frame. */
   7.224 -    op.cmd = DOM0_GETDOMAININFO;
   7.225 -    op.u.getdomaininfo.domain = dom;
   7.226 -    if ( do_dom0_op(&op) < 0 )
   7.227 -    {
   7.228 -        ERROR("Could not get information on new domain");
   7.229 -        goto out;
   7.230 -    }
   7.231 -    shared_info_frame = op.u.getdomaininfo.shared_info_frame;
   7.232 -
   7.233 -    if ( init_pfn_mapper() < 0 )
   7.234 -        goto out;
   7.235 -
   7.236 -    /* Copy saved contents of shared-info page. No checking needed. */
   7.237 -    ppage = map_pfn(shared_info_frame);
   7.238 -    memcpy(ppage, shared_info, PAGE_SIZE);
   7.239 -    unmap_pfn(ppage);
   7.240 -
   7.241 -    /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
   7.242 -    if ( get_pfn_list(dom, pfn_to_mfn_table, nr_pfns) != nr_pfns )
   7.243 -    {
   7.244 -        ERROR("Did not read correct number of frame numbers for new dom");
   7.245 -        goto out;
   7.246 -    }
   7.247 -
   7.248 -    verbose_printf("Reloading memory pages:   0%%");
   7.249 -
   7.250 -    /*
   7.251 -     * Now simply read each saved frame into its new machine frame.
   7.252 -     * We uncanonicalise page tables as we go.
   7.253 -     */
   7.254 -    prev_pc = 0;
   7.255 -    for ( i = 0; i < nr_pfns; i++ )
   7.256 -    {
   7.257 -        this_pc = (i * 100) / nr_pfns;
   7.258 -        if ( (this_pc - prev_pc) >= 5 )
   7.259 -        {
   7.260 -            verbose_printf("\b\b\b\b%3d%%", this_pc);
   7.261 -            prev_pc = this_pc;
   7.262 -        }
   7.263 -
   7.264 -        mfn = pfn_to_mfn_table[i];
   7.265 -
   7.266 -        if ( !checked_read(gfd, page, PAGE_SIZE) )
   7.267 -        {
   7.268 -            ERROR("Error when reading from state file");
   7.269 -            goto out;
   7.270 -        }
   7.271 -
   7.272 -        ppage = map_pfn(mfn);
   7.273 -        switch ( pfn_type[i] )
   7.274 -        {
   7.275 -        case L1TAB:
   7.276 -            memset(ppage, 0, PAGE_SIZE);
   7.277 -            if ( add_mmu_update(mmu_updates, &mmu_update_idx,
   7.278 -                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
   7.279 -                                MMUEXT_PIN_L1_TABLE) )
   7.280 -                goto out;
   7.281 -            for ( j = 0; j < 1024; j++ )
   7.282 -            {
   7.283 -                if ( page[j] & _PAGE_PRESENT )
   7.284 -                {
   7.285 -                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
   7.286 -                    {
   7.287 -                        ERROR("Frame number in page table is out of range");
   7.288 -                        goto out;
   7.289 -                    }
   7.290 -                    if ( (pfn_type[pfn] != NONE) && (page[j] & _PAGE_RW) )
   7.291 -                    {
   7.292 -                        ERROR("Write access requested for a restricted frame");
   7.293 -                        goto out;
   7.294 -                    }
   7.295 -                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT);
   7.296 -                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
   7.297 -                }
   7.298 -                if ( add_mmu_update(mmu_updates, &mmu_update_idx,
   7.299 -                                    (unsigned long)&ppage[j], page[j]) )
   7.300 -                    goto out;
   7.301 -            }
   7.302 -            break;
   7.303 -        case L2TAB:
   7.304 -            memset(ppage, 0, PAGE_SIZE);
   7.305 -            if ( add_mmu_update(mmu_updates, &mmu_update_idx,
   7.306 -                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
   7.307 -                                MMUEXT_PIN_L2_TABLE) )
   7.308 -                goto out;
   7.309 -            for ( j = 0; j < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); j++ )
   7.310 -            {
   7.311 -                if ( page[j] & _PAGE_PRESENT )
   7.312 -                {
   7.313 -                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
   7.314 -                    {
   7.315 -                        ERROR("Frame number in page table is out of range");
   7.316 -                        goto out;
   7.317 -                    }
   7.318 -                    if ( pfn_type[pfn] != L1TAB )
   7.319 -                    {
   7.320 -                        ERROR("Page table mistyping");
   7.321 -                        goto out;
   7.322 -                    }
   7.323 -                    /* Haven't reached the L1 table yet. Ensure it is safe! */
   7.324 -                    if ( pfn > i )
   7.325 -                    {
   7.326 -                        unsigned long **l1 = map_pfn(pfn_to_mfn_table[pfn]);
   7.327 -                        memset(l1, 0, PAGE_SIZE);
   7.328 -                        unmap_pfn(l1);
   7.329 -                    }
   7.330 -                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE);
   7.331 -                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
   7.332 -                }
   7.333 -                if ( add_mmu_update(mmu_updates, &mmu_update_idx,
   7.334 -                                    (unsigned long)&ppage[j], page[j]) )
   7.335 -                    goto out;
   7.336 -            }
   7.337 -            break;
   7.338 -        default:
   7.339 -            memcpy(ppage, page, PAGE_SIZE);
   7.340 -            break;
   7.341 -        }
   7.342 -        /* NB. Must flush before unmapping page, as pass VAs to Xen. */
   7.343 -        if ( flush_mmu_updates(mmu_updates, &mmu_update_idx) )
   7.344 -            goto out;
   7.345 -        unmap_pfn(ppage);
   7.346 -
   7.347 -        if ( add_mmu_update(mmu_updates, &mmu_update_idx,
   7.348 -                            (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, i) )
   7.349 -            goto out;
   7.350 -    }
   7.351 -
   7.352 -    if ( flush_mmu_updates(mmu_updates, &mmu_update_idx) )
   7.353 -        goto out;
   7.354 -
   7.355 -    verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n");
   7.356 -
   7.357 -    /* Uncanonicalise the suspend-record frame number and poke resume rec. */
   7.358 -    pfn = ctxt.i386_ctxt.esi;
   7.359 -    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
   7.360 -    {
   7.361 -        ERROR("Suspend record frame number is bad");
   7.362 -        goto out;
   7.363 -    }
   7.364 -    ctxt.i386_ctxt.esi = mfn = pfn_to_mfn_table[pfn];
   7.365 -    p_srec = map_pfn(mfn);
   7.366 -    p_srec->resume_info.nr_pages    = nr_pfns;
   7.367 -    p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT;
   7.368 -    p_srec->resume_info.dom_id      = dom;
   7.369 -    p_srec->resume_info.flags       = 0;
   7.370 -    unmap_pfn(p_srec);
   7.371 -
   7.372 -    /* Uncanonicalise each GDT frame number. */
   7.373 -    if ( ctxt.gdt_ents > 8192 )
   7.374 -    {
   7.375 -        ERROR("GDT entry count out of range");
   7.376 -        goto out;
   7.377 -    }
   7.378 -    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
   7.379 -    {
   7.380 -        pfn = ctxt.gdt_frames[i];
   7.381 -        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
   7.382 -        {
   7.383 -            ERROR("GDT frame number is bad");
   7.384 -            goto out;
   7.385 -        }
   7.386 -        ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn];
   7.387 -    }
   7.388 -
   7.389 -    /* Uncanonicalise the page table base pointer. */
   7.390 -    pfn = ctxt.pt_base >> PAGE_SHIFT;
   7.391 -    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) )
   7.392 -    {
   7.393 -        ERROR("PT base is bad");
   7.394 -        goto out;
   7.395 -    }
   7.396 -    ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT;
   7.397 -
   7.398 -    /* Uncanonicalise the pfn-to-mfn table frame-number list. */
   7.399 -    for ( i = 0; i < nr_pfns; i += 1024 )
   7.400 -    {
   7.401 -        unsigned long copy_size = (nr_pfns - i) * sizeof(unsigned long);
   7.402 -        if ( copy_size > PAGE_SIZE ) copy_size = PAGE_SIZE;
   7.403 -        pfn = pfn_to_mfn_frame_list[i/1024];
   7.404 -        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
   7.405 -        {
   7.406 -            ERROR("PFN-to-MFN frame number is bad");
   7.407 -            goto out;
   7.408 -        }
   7.409 -        ppage = map_pfn(pfn_to_mfn_table[pfn]);
   7.410 -        memcpy(ppage, &pfn_to_mfn_table[i], copy_size);        
   7.411 -        unmap_pfn(ppage);
   7.412 -    }
   7.413 -
   7.414 -    /*
   7.415 -     * Safety checking of saved context:
   7.416 -     *  1. i386_ctxt is fine, as Xen checks that on context switch.
   7.417 -     *  2. i387_ctxt is fine, as it can't hurt Xen.
   7.418 -     *  3. trap_ctxt needs the code selectors checked.
   7.419 -     *  4. fast_trap_idx is checked by Xen.
   7.420 -     *  5. ldt base must be page-aligned, no more than 8192 ents, ...
   7.421 -     *  6. gdt already done, and further checking is done by Xen.
   7.422 -     *  7. check that ring1_ss is safe.
   7.423 -     *  8. pt_base is already done.
   7.424 -     *  9. debugregs are checked by Xen.
   7.425 -     *  10. callback code selectors need checking.
   7.426 -     */
   7.427 -    for ( i = 0; i < 256; i++ )
   7.428 -    {
   7.429 -        ctxt.trap_ctxt[i].vector = i;
   7.430 -        if ( (ctxt.trap_ctxt[i].cs & 3) == 0 )
   7.431 -            ctxt.trap_ctxt[i].cs = FLAT_RING1_CS;
   7.432 -    }
   7.433 -    if ( (ctxt.ring1_ss & 3) == 0 )
   7.434 -        ctxt.ring1_ss = FLAT_RING1_DS;
   7.435 -    if ( (ctxt.event_callback_cs & 3) == 0 )
   7.436 -        ctxt.event_callback_cs = FLAT_RING1_CS;
   7.437 -    if ( (ctxt.failsafe_callback_cs & 3) == 0 )
   7.438 -        ctxt.failsafe_callback_cs = FLAT_RING1_CS;
   7.439 -    if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) ||
   7.440 -         (ctxt.ldt_ents > 8192) ||
   7.441 -         (ctxt.ldt_base > HYPERVISOR_VIRT_START) ||
   7.442 -         ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) )
   7.443 -    {
   7.444 -        ERROR("Bad LDT base or size");
   7.445 -        goto out;
   7.446 -    }
   7.447 -
   7.448 -    op.cmd = DOM0_BUILDDOMAIN;
   7.449 -    op.u.builddomain.domain   = dom;
   7.450 -    op.u.builddomain.num_vifs = 1;
   7.451 -    memcpy(&op.u.builddomain.ctxt, &ctxt, sizeof(ctxt));
   7.452 -    rc = do_dom0_op(&op);
   7.453 -
   7.454 - out:
   7.455 -    if ( rc != 0 )
   7.456 -    {
   7.457 -        if ( dom != 0 )
   7.458 -        {
   7.459 -            op.cmd = DOM0_DESTROYDOMAIN;
   7.460 -            op.u.destroydomain.domain = dom;
   7.461 -            op.u.destroydomain.force  = 1;
   7.462 -            (void)do_dom0_op(&op);
   7.463 -        }
   7.464 -    }
   7.465 -    else
   7.466 -    {
   7.467 -        /* Success: print the domain id. */
   7.468 -        verbose_printf("DOM=%ld\n", dom);
   7.469 -    }
   7.470 -
   7.471 -    if ( pfn_to_mfn_table != NULL )
   7.472 -        free(pfn_to_mfn_table);
   7.473 -    if ( pfn_type != NULL )
   7.474 -        free(pfn_type);
   7.475 -
   7.476 -    gzclose(gfd);
   7.477 -
   7.478 -    return (rc == 0) ? dom : rc;
   7.479 -}
     8.1 --- a/tools/libxc/libxc_linux_save.c	Thu Nov 20 10:03:52 2003 +0000
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,380 +0,0 @@
     8.4 -/******************************************************************************
     8.5 - * libxc_linux_save.c
     8.6 - * 
     8.7 - * Save the state of a running Xenolinux session.
     8.8 - * 
     8.9 - * Copyright (c) 2003, K A Fraser.
    8.10 - */
    8.11 -
    8.12 -#include "libxc_private.h"
    8.13 -#include <asm-xeno/suspend.h>
    8.14 -#include <zlib.h>
    8.15 -
    8.16 -/* This may allow us to create a 'quiet' command-line option, if necessary. */
    8.17 -#define verbose_printf(_f, _a...) \
    8.18 -    do {                          \
    8.19 -        if ( !verbose ) break;    \
    8.20 -        printf( _f , ## _a );     \
    8.21 -        fflush(stdout);           \
    8.22 -    } while ( 0 )
    8.23 -
    8.24 -/*
    8.25 - * Returns TRUE if the given machine frame number has a unique mapping
    8.26 - * in the guest's pseudophysical map.
    8.27 - */
    8.28 -#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \
    8.29 -    (((_mfn) < (1024*1024)) &&          \
    8.30 -     (pfn_to_mfn_table[mfn_to_pfn_table[_mfn]] == (_mfn)))
    8.31 -
    8.32 -/* Returns TRUE if MFN is successfully converted to a PFN. */
    8.33 -#define translate_mfn_to_pfn(_pmfn)         \
    8.34 -({                                          \
    8.35 -    unsigned long mfn = *(_pmfn);           \
    8.36 -    int _res = 1;                           \
    8.37 -    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )   \
    8.38 -        _res = 0;                           \
    8.39 -    else                                    \
    8.40 -        *(_pmfn) = mfn_to_pfn_table[mfn];   \
    8.41 -    _res;                                   \
    8.42 -})
    8.43 -
    8.44 -static int check_pfn_ownership(unsigned long mfn, unsigned int dom)
    8.45 -{
    8.46 -    dom0_op_t op;
    8.47 -    op.cmd = DOM0_GETPAGEFRAMEINFO;
    8.48 -    op.u.getpageframeinfo.pfn = mfn;
    8.49 -    if ( (do_dom0_op(&op) < 0) || (op.u.getpageframeinfo.domain != dom) )
    8.50 -        return 0;
    8.51 -    return 1;
    8.52 -}
    8.53 -
    8.54 -#define GETPFN_ERR (~0U)
    8.55 -static unsigned int get_pfn_type(unsigned long mfn)
    8.56 -{
    8.57 -    dom0_op_t op;
    8.58 -    op.cmd = DOM0_GETPAGEFRAMEINFO;
    8.59 -    op.u.getpageframeinfo.pfn = mfn;
    8.60 -    if ( do_dom0_op(&op) < 0 )
    8.61 -    {
    8.62 -        PERROR("Unexpected failure when getting page frame info!");
    8.63 -        return GETPFN_ERR;
    8.64 -    }
    8.65 -    return op.u.getpageframeinfo.type;
    8.66 -}
    8.67 -
    8.68 -static int checked_write(gzFile fd, void *buf, size_t count)
    8.69 -{
    8.70 -    int rc;
    8.71 -    while ( ((rc = gzwrite(fd, buf, count)) == -1) && (errno = EINTR) )
    8.72 -        continue;
    8.73 -    return rc == count;
    8.74 -}
    8.75 -
    8.76 -int xc_linux_save(unsigned int domid, const char *state_file, int verbose)
    8.77 -{
    8.78 -    dom0_op_t op;
    8.79 -    int rc = 1, i, j;
    8.80 -    unsigned long mfn;
    8.81 -    unsigned int prev_pc, this_pc;
    8.82 -
    8.83 -    /* Remember if we stopped the guest, so we can restart it on exit. */
    8.84 -    int we_stopped_it = 0;
    8.85 -
    8.86 -    /* The new domain's shared-info frame number. */
    8.87 -    unsigned long shared_info_frame;
    8.88 -    
    8.89 -    /* A copy of the CPU context of the guest. */
    8.90 -    full_execution_context_t ctxt;
    8.91 -
    8.92 -    /* A copy of the domain's name. */
    8.93 -    char name[MAX_DOMAIN_NAME];
    8.94 -
    8.95 -    /* A table containg the type of each PFN (/not/ MFN!). */
    8.96 -    unsigned long *pfn_type = NULL;
    8.97 -
    8.98 -    /* A temporary mapping, and a copy, of one frame of guest memory. */
    8.99 -    unsigned long *ppage, page[1024];
   8.100 -
   8.101 -    /* A temporary mapping, and a copy, of the pfn-to-mfn table frame list. */
   8.102 -    unsigned long *p_pfn_to_mfn_frame_list, pfn_to_mfn_frame_list[1024];
   8.103 -    /* A temporary mapping of one frame in the above list. */
   8.104 -    unsigned long *pfn_to_mfn_frame;
   8.105 -
   8.106 -    /* A table mapping each PFN to its current MFN. */
   8.107 -    unsigned long *pfn_to_mfn_table = NULL;
   8.108 -    /* A table mapping each current MFN to its canonical PFN. */
   8.109 -    unsigned long *mfn_to_pfn_table = NULL;
   8.110 -    
   8.111 -    /* A temporary mapping, and a copy, of the guest's suspend record. */
   8.112 -    suspend_record_t *p_srec, srec;
   8.113 -
   8.114 -    /* The name and descriptor of the file that we are writing to. */
   8.115 -    int    fd;
   8.116 -    gzFile gfd;
   8.117 -
   8.118 -    if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 )
   8.119 -    {
   8.120 -        PERROR("Could not open file for writing");
   8.121 -        return 1;
   8.122 -    }
   8.123 -
   8.124 -    /*
   8.125 -     * Compression rate 1: we want speed over compression. We're mainly going
   8.126 -     * for those zero pages, after all.
   8.127 -     */
   8.128 -    if ( (gfd = gzdopen(fd, "wb1")) == NULL )
   8.129 -    {
   8.130 -        ERROR("Could not allocate compression state for state file");
   8.131 -        close(fd);
   8.132 -        return 1;
   8.133 -    }
   8.134 -
   8.135 -    /* Ensure that the domain exists, and that it is stopped. */
   8.136 -    for ( ; ; )
   8.137 -    {
   8.138 -        op.cmd = DOM0_GETDOMAININFO;
   8.139 -        op.u.getdomaininfo.domain = domid;
   8.140 -        if ( (do_dom0_op(&op) < 0) || (op.u.getdomaininfo.domain != domid) )
   8.141 -        {
   8.142 -            PERROR("Could not get info on domain");
   8.143 -            goto out;
   8.144 -        }
   8.145 -
   8.146 -        memcpy(&ctxt, &op.u.getdomaininfo.ctxt, sizeof(ctxt));
   8.147 -        memcpy(name, op.u.getdomaininfo.name, sizeof(name));
   8.148 -        shared_info_frame = op.u.getdomaininfo.shared_info_frame;
   8.149 -
   8.150 -        if ( op.u.getdomaininfo.state == DOMSTATE_STOPPED )
   8.151 -            break;
   8.152 -
   8.153 -        we_stopped_it = 1;
   8.154 -
   8.155 -        op.cmd = DOM0_STOPDOMAIN;
   8.156 -        op.u.stopdomain.domain = domid;
   8.157 -        (void)do_dom0_op(&op);
   8.158 -
   8.159 -        sleep(1);
   8.160 -    }
   8.161 -
   8.162 -    /* A cheesy test to see whether the domain contains valid state. */
   8.163 -    if ( ctxt.pt_base == 0 )
   8.164 -    {
   8.165 -        ERROR("Domain is not in a valid Xenolinux state");
   8.166 -        goto out;
   8.167 -    }
   8.168 -
   8.169 -    if ( init_pfn_mapper() < 0 )
   8.170 -        goto out;
   8.171 -
   8.172 -    /* Is the suspend-record MFN actually valid for this domain? */
   8.173 -    if ( !check_pfn_ownership(ctxt.i386_ctxt.esi, domid) )
   8.174 -    {
   8.175 -        ERROR("Invalid state record pointer");
   8.176 -        goto out;
   8.177 -    }
   8.178 -
   8.179 -    /* If the suspend-record MFN is okay then grab a copy of it to @srec. */
   8.180 -    p_srec = map_pfn(ctxt.i386_ctxt.esi);
   8.181 -    memcpy(&srec, p_srec, sizeof(srec));
   8.182 -    unmap_pfn(p_srec);
   8.183 -
   8.184 -    if ( srec.nr_pfns > 1024*1024 )
   8.185 -    {
   8.186 -        ERROR("Invalid state record -- pfn count out of range");
   8.187 -        goto out;
   8.188 -    }
   8.189 -
   8.190 -    if ( !check_pfn_ownership(srec.pfn_to_mfn_frame_list, domid) )
   8.191 -    {
   8.192 -        ERROR("Invalid pfn-to-mfn frame list pointer");
   8.193 -        goto out;
   8.194 -    }
   8.195 -
   8.196 -    /* Grab a copy of the pfn-to-mfn table frame list. */
   8.197 -    p_pfn_to_mfn_frame_list = map_pfn(srec.pfn_to_mfn_frame_list);
   8.198 -    memcpy(pfn_to_mfn_frame_list, p_pfn_to_mfn_frame_list, PAGE_SIZE);
   8.199 -    unmap_pfn(p_pfn_to_mfn_frame_list);
   8.200 -
   8.201 -    /* We want zeroed memory so use calloc rather than malloc. */
   8.202 -    mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024);
   8.203 -    pfn_to_mfn_table = calloc(1, 4 * srec.nr_pfns);
   8.204 -    pfn_type         = calloc(1, 4 * srec.nr_pfns);
   8.205 -
   8.206 -    if ( (mfn_to_pfn_table == NULL) ||
   8.207 -         (pfn_to_mfn_table == NULL) ||
   8.208 -         (pfn_type == NULL) )
   8.209 -    {
   8.210 -        errno = ENOMEM;
   8.211 -        goto out;
   8.212 -    }
   8.213 -
   8.214 -
   8.215 -    /*
   8.216 -     * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this
   8.217 -     * loop we have each MFN mapped at most once. Note that there may be MFNs
   8.218 -     * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP.
   8.219 -     */
   8.220 -    pfn_to_mfn_frame = NULL;
   8.221 -    for ( i = 0; i < srec.nr_pfns; i++ )
   8.222 -    {
   8.223 -        /* Each frameful of table frames must be checked & mapped on demand. */
   8.224 -        if ( (i & 1023) == 0 )
   8.225 -        {
   8.226 -            mfn = pfn_to_mfn_frame_list[i/1024];
   8.227 -            if ( !check_pfn_ownership(mfn, domid) )
   8.228 -            {
   8.229 -                ERROR("Invalid frame number if pfn-to-mfn frame list");
   8.230 -                goto out;
   8.231 -            }
   8.232 -            if ( pfn_to_mfn_frame != NULL )
   8.233 -                unmap_pfn(pfn_to_mfn_frame);
   8.234 -            pfn_to_mfn_frame = map_pfn(mfn);
   8.235 -        }
   8.236 -        
   8.237 -        mfn = pfn_to_mfn_frame[i & 1023];
   8.238 -
   8.239 -        if ( !check_pfn_ownership(mfn, domid) )
   8.240 -        {
   8.241 -            ERROR("Invalid frame specified with pfn-to-mfn table");
   8.242 -            goto out;
   8.243 -        }
   8.244 -
   8.245 -        /* Did we map this MFN already? That would be invalid! */
   8.246 -        if ( MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
   8.247 -        {
   8.248 -            ERROR("A machine frame appears twice in pseudophys space");
   8.249 -            goto out;
   8.250 -        }
   8.251 -
   8.252 -        pfn_to_mfn_table[i] = mfn;
   8.253 -        mfn_to_pfn_table[mfn] = i;
   8.254 -
   8.255 -        /* Query page type by MFN, but store it by PFN. */
   8.256 -        if ( (pfn_type[i] = get_pfn_type(mfn)) == GETPFN_ERR )
   8.257 -            goto out;
   8.258 -    }
   8.259 -
   8.260 -    /* Canonicalise the suspend-record frame number. */
   8.261 -    if ( !translate_mfn_to_pfn(&ctxt.i386_ctxt.esi) )
   8.262 -    {
   8.263 -        ERROR("State record is not in range of pseudophys map");
   8.264 -        goto out;
   8.265 -    }
   8.266 -
   8.267 -    /* Canonicalise each GDT frame number. */
   8.268 -    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
   8.269 -    {
   8.270 -        if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) )
   8.271 -        {
   8.272 -            ERROR("GDT frame is not in range of pseudophys map");
   8.273 -            goto out;
   8.274 -        }
   8.275 -    }
   8.276 -
   8.277 -    /* Canonicalise the page table base pointer. */
   8.278 -    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) )
   8.279 -    {
   8.280 -        ERROR("PT base is not in range of pseudophys map");
   8.281 -        goto out;
   8.282 -    }
   8.283 -    ctxt.pt_base = mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT;
   8.284 -
   8.285 -    /* Canonicalise the pfn-to-mfn table frame-number list. */
   8.286 -    for ( i = 0; i < srec.nr_pfns; i += 1024 )
   8.287 -    {
   8.288 -        if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
   8.289 -        {
   8.290 -            ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys");
   8.291 -            goto out;
   8.292 -        }
   8.293 -    }
   8.294 -
   8.295 -    /* Start writing out the saved-domain record. */
   8.296 -    ppage = map_pfn(shared_info_frame);
   8.297 -    if ( !checked_write(gfd, "XenoLinuxSuspend",    16) ||
   8.298 -         !checked_write(gfd, name,                  sizeof(name)) ||
   8.299 -         !checked_write(gfd, &srec.nr_pfns,         sizeof(unsigned long)) ||
   8.300 -         !checked_write(gfd, &ctxt,                 sizeof(ctxt)) ||
   8.301 -         !checked_write(gfd, ppage,                 PAGE_SIZE) ||
   8.302 -         !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) ||
   8.303 -         !checked_write(gfd, pfn_type,              4 * srec.nr_pfns) )
   8.304 -    {
   8.305 -        ERROR("Error when writing to state file");
   8.306 -        goto out;
   8.307 -    }
   8.308 -    unmap_pfn(ppage);
   8.309 -
   8.310 -    verbose_printf("Saving memory pages:   0%%");
   8.311 -
   8.312 -    /* Now write out each data page, canonicalising page tables as we go... */
   8.313 -    prev_pc = 0;
   8.314 -    for ( i = 0; i < srec.nr_pfns; i++ )
   8.315 -    {
   8.316 -        this_pc = (i * 100) / srec.nr_pfns;
   8.317 -        if ( (this_pc - prev_pc) >= 5 )
   8.318 -        {
   8.319 -            verbose_printf("\b\b\b\b%3d%%", this_pc);
   8.320 -            prev_pc = this_pc;
   8.321 -        }
   8.322 -
   8.323 -        mfn = pfn_to_mfn_table[i];
   8.324 -
   8.325 -        ppage = map_pfn(mfn);
   8.326 -        memcpy(page, ppage, PAGE_SIZE);
   8.327 -        unmap_pfn(ppage);
   8.328 -
   8.329 -        if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) )
   8.330 -        {
   8.331 -            for ( j = 0; 
   8.332 -                  j < ((pfn_type[i] == L2TAB) ? 
   8.333 -                       (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 
   8.334 -                  j++ )
   8.335 -            {
   8.336 -                if ( !(page[j] & _PAGE_PRESENT) ) continue;
   8.337 -                mfn = page[j] >> PAGE_SHIFT;
   8.338 -                if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
   8.339 -                {
   8.340 -                    ERROR("Frame number in pagetable page is invalid");
   8.341 -                    goto out;
   8.342 -                }
   8.343 -                page[j] &= PAGE_SIZE - 1;
   8.344 -                page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT;
   8.345 -            }
   8.346 -        }
   8.347 -
   8.348 -        if ( !checked_write(gfd, page, PAGE_SIZE) )
   8.349 -        {
   8.350 -            ERROR("Error when writing to state file");
   8.351 -            goto out;
   8.352 -        }
   8.353 -    }
   8.354 -
   8.355 -    verbose_printf("\b\b\b\b100%%\nMemory saved.\n");
   8.356 -
   8.357 -    /* Success! */
   8.358 -    rc = 0;
   8.359 -
   8.360 - out:
   8.361 -    /* Restart the domain if we had to stop it to save its state. */
   8.362 -    if ( we_stopped_it )
   8.363 -    {
   8.364 -        op.cmd = DOM0_STARTDOMAIN;
   8.365 -        op.u.startdomain.domain = domid;
   8.366 -        (void)do_dom0_op(&op);
   8.367 -    }
   8.368 -
   8.369 -    gzclose(gfd);
   8.370 -
   8.371 -    if ( pfn_to_mfn_table != NULL )
   8.372 -        free(pfn_to_mfn_table);
   8.373 -    if ( mfn_to_pfn_table != NULL )
   8.374 -        free(mfn_to_pfn_table);
   8.375 -    if ( pfn_type != NULL )
   8.376 -        free(pfn_type);
   8.377 -
   8.378 -    /* On error, make sure the file is deleted. */
   8.379 -    if ( rc != 0 )
   8.380 -        unlink(state_file);
   8.381 -    
   8.382 -    return !!rc;
   8.383 -}
     9.1 --- a/tools/libxc/libxc_misc.c	Thu Nov 20 10:03:52 2003 +0000
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,50 +0,0 @@
     9.4 -/******************************************************************************
     9.5 - * libxc_misc.c
     9.6 - * 
     9.7 - * Miscellaneous control interface functions.
     9.8 - */
     9.9 -
    9.10 -#include "libxc_private.h"
    9.11 -
    9.12 -int privcmd_fd = -1;
    9.13 -
    9.14 -int xc_interface_open(void)
    9.15 -{
    9.16 -    if ( (privcmd_fd == -1) &&
    9.17 -         ((privcmd_fd = open("/proc/xeno/privcmd", O_RDWR)) < 0) )
    9.18 -    {
    9.19 -        privcmd_fd = -1;
    9.20 -        return -1;
    9.21 -    }
    9.22 -    return 0;
    9.23 -}
    9.24 -
    9.25 -int xc_interface_close(void)
    9.26 -{
    9.27 -    if ( privcmd_fd != -1 )
    9.28 -    {
    9.29 -        close(privcmd_fd);
    9.30 -        privcmd_fd = -1;
    9.31 -    }
    9.32 -    return 0;
    9.33 -}
    9.34 -
    9.35 -
    9.36 -#define CONSOLE_RING_CLEAR	1
    9.37 -
    9.38 -int xc_readconsolering(char *str, unsigned int max_chars, int clear)
    9.39 -{
    9.40 -    int ret;
    9.41 -    dom0_op_t op;
    9.42 -
    9.43 -    op.cmd = DOM0_READCONSOLE;
    9.44 -    op.u.readconsole.str = (unsigned long)str;
    9.45 -    op.u.readconsole.count = max_chars;
    9.46 -    op.u.readconsole.cmd = clear ? CONSOLE_RING_CLEAR : 0;
    9.47 -
    9.48 -    if ( (ret = do_dom0_op(&op)) > 0 )
    9.49 -        str[ret] = '\0';
    9.50 -
    9.51 -    return ret;
    9.52 -}    
    9.53 -
    10.1 --- a/tools/libxc/libxc_private.c	Thu Nov 20 10:03:52 2003 +0000
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,34 +0,0 @@
    10.4 -/******************************************************************************
    10.5 - * libxc_private.c
    10.6 - * 
    10.7 - * Helper functions for the rest of the library.
    10.8 - */
    10.9 -
   10.10 -#include "libxc_private.h"
   10.11 -
   10.12 -static int devmem_fd = -1;
   10.13 -
   10.14 -int init_pfn_mapper(void)
   10.15 -{
   10.16 -    if ( (devmem_fd == -1) &&
   10.17 -         ((devmem_fd = open("/dev/mem", O_RDWR)) < 0) )
   10.18 -    {
   10.19 -        devmem_fd = -1;
   10.20 -        return -1;
   10.21 -    }
   10.22 -    return 0;
   10.23 -}
   10.24 -
   10.25 -void *map_pfn(unsigned long pfn)
   10.26 -{
   10.27 -    void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
   10.28 -                       MAP_SHARED, devmem_fd, pfn << PAGE_SHIFT);
   10.29 -    if ( vaddr == MAP_FAILED )
   10.30 -        return NULL;
   10.31 -    return vaddr;
   10.32 -}
   10.33 -
   10.34 -void unmap_pfn(void *vaddr)
   10.35 -{
   10.36 -    (void)munmap(vaddr, PAGE_SIZE);
   10.37 -}
    11.1 --- a/tools/libxc/libxc_private.h	Thu Nov 20 10:03:52 2003 +0000
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,155 +0,0 @@
    11.4 -
    11.5 -#ifndef __LIBXC_PRIVATE_H__
    11.6 -#define __LIBXC_PRIVATE_H__
    11.7 -
    11.8 -typedef unsigned char      u8;
    11.9 -typedef unsigned short     u16;
   11.10 -typedef unsigned long      u32;
   11.11 -typedef unsigned long long u64;
   11.12 -typedef signed char        s8;
   11.13 -typedef signed short       s16;
   11.14 -typedef signed long        s32;
   11.15 -typedef signed long long   s64;
   11.16 -
   11.17 -#include <unistd.h>
   11.18 -#include <stdio.h>
   11.19 -#include <errno.h>
   11.20 -#include <fcntl.h>
   11.21 -#include <sys/mman.h>
   11.22 -#include <sys/types.h>
   11.23 -#include <sys/stat.h>
   11.24 -#include <stdlib.h>
   11.25 -#include <sys/ioctl.h>
   11.26 -#include <errno.h>
   11.27 -#include <string.h>
   11.28 -
   11.29 -#include "xc.h"
   11.30 -
   11.31 -#include <asm-xeno/proc_cmd.h>
   11.32 -#include <hypervisor-ifs/hypervisor-if.h>
   11.33 -#include <hypervisor-ifs/dom0_ops.h>
   11.34 -#include <hypervisor-ifs/vbd.h>
   11.35 -
   11.36 -#define _PAGE_PRESENT   0x001
   11.37 -#define _PAGE_RW        0x002
   11.38 -#define _PAGE_USER      0x004
   11.39 -#define _PAGE_PWT       0x008
   11.40 -#define _PAGE_PCD       0x010
   11.41 -#define _PAGE_ACCESSED  0x020
   11.42 -#define _PAGE_DIRTY     0x040
   11.43 -#define _PAGE_PAT       0x080
   11.44 -#define _PAGE_PSE       0x080
   11.45 -#define _PAGE_GLOBAL    0x100
   11.46 -
   11.47 -
   11.48 -#define L1_PAGETABLE_SHIFT       12
   11.49 -#define L2_PAGETABLE_SHIFT       22
   11.50 - 
   11.51 -#define ENTRIES_PER_L1_PAGETABLE 1024
   11.52 -#define ENTRIES_PER_L2_PAGETABLE 1024
   11.53 - 
   11.54 -#define PAGE_SHIFT              L1_PAGETABLE_SHIFT
   11.55 -#define PAGE_SIZE               (1UL << PAGE_SHIFT)
   11.56 -#define PAGE_MASK               (~(PAGE_SIZE-1))
   11.57 -
   11.58 -typedef struct { unsigned long l1_lo; } l1_pgentry_t;
   11.59 -typedef struct { unsigned long l2_lo; } l2_pgentry_t;
   11.60 -
   11.61 -#define l1_table_offset(_a) \
   11.62 -          (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
   11.63 -#define l2_table_offset(_a) \
   11.64 -          ((_a) >> L2_PAGETABLE_SHIFT)
   11.65 -
   11.66 -#define ERROR(_m)  \
   11.67 -    fprintf(stderr, "ERROR: %s\n", (_m))
   11.68 -
   11.69 -#define PERROR(_m) \
   11.70 -    fprintf(stderr, "ERROR: %s (%d = %s)\n", (_m), errno, strerror(errno))
   11.71 -
   11.72 -extern int privcmd_fd;
   11.73 -static inline int do_privcmd(unsigned int cmd, unsigned long data)
   11.74 -{
   11.75 -    return ioctl(privcmd_fd, cmd, data);
   11.76 -}
   11.77 -
   11.78 -static inline int do_xen_hypercall(privcmd_hypercall_t *hypercall)
   11.79 -{
   11.80 -    return do_privcmd(IOCTL_PRIVCMD_HYPERCALL, (unsigned long)hypercall);
   11.81 -}
   11.82 -
   11.83 -static inline int do_dom0_op(dom0_op_t *op)
   11.84 -{
   11.85 -    int ret = -1;
   11.86 -    privcmd_hypercall_t hypercall;
   11.87 -
   11.88 -    op->interface_version = DOM0_INTERFACE_VERSION;
   11.89 -
   11.90 -    hypercall.op     = __HYPERVISOR_dom0_op;
   11.91 -    hypercall.arg[0] = (unsigned long)op;
   11.92 -
   11.93 -    if ( mlock(op, sizeof(*op)) != 0 )
   11.94 -        goto out1;
   11.95 -
   11.96 -    if ( (ret = do_xen_hypercall(&hypercall)) < 0 )
   11.97 -    {
   11.98 -        if ( errno == EACCES )
   11.99 -            fprintf(stderr, "Dom0 operation failed -- need to"
  11.100 -                    " rebuild the user-space tool set?\n");
  11.101 -        goto out2;
  11.102 -    }
  11.103 -
  11.104 -    ret = 0;
  11.105 -
  11.106 - out2: (void)munlock(op, sizeof(*op));
  11.107 - out1: return ret;
  11.108 -}
  11.109 -
  11.110 -static inline int do_network_op(network_op_t *op)
  11.111 -{
  11.112 -    int ret = -1;
  11.113 -    privcmd_hypercall_t hypercall;
  11.114 -
  11.115 -    hypercall.op     = __HYPERVISOR_network_op;
  11.116 -    hypercall.arg[0] = (unsigned long)op;
  11.117 -
  11.118 -    if ( mlock(op, sizeof(*op)) != 0 )
  11.119 -        goto out1;
  11.120 -
  11.121 -    if ( (ret = do_xen_hypercall(&hypercall)) < 0 )
  11.122 -        goto out2;
  11.123 -
  11.124 -    ret = 0;
  11.125 -
  11.126 - out2: (void)munlock(op, sizeof(*op));
  11.127 - out1: return ret;
  11.128 -}
  11.129 -
  11.130 -
  11.131 -static inline int do_block_io_op(block_io_op_t *op)
  11.132 -{
  11.133 -    int ret = -1;
  11.134 -    privcmd_hypercall_t hypercall;
  11.135 -
  11.136 -    hypercall.op     = __HYPERVISOR_block_io_op;
  11.137 -    hypercall.arg[0] = (unsigned long)op;
  11.138 -
  11.139 -    if ( mlock(op, sizeof(*op)) != 0 )
  11.140 -        goto out1;
  11.141 -
  11.142 -    if ( do_xen_hypercall(&hypercall) < 0 )
  11.143 -        goto out2;
  11.144 -
  11.145 -    ret = 0;
  11.146 -
  11.147 - out2: (void)munlock(op, sizeof(*op));
  11.148 - out1: return ret;
  11.149 -}
  11.150 -
  11.151 -/*
  11.152 - * PFN mapping.
  11.153 - */
  11.154 -int init_pfn_mapper(void);
  11.155 -void *map_pfn(unsigned long pfn);
  11.156 -void unmap_pfn(void *vaddr);
  11.157 -
  11.158 -#endif /* __LIBXC_PRIVATE_H__ */
    12.1 --- a/tools/libxc/libxc_vbd.c	Thu Nov 20 10:03:52 2003 +0000
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,116 +0,0 @@
    12.4 -/******************************************************************************
    12.5 - * libxc_vbd.c
    12.6 - * 
    12.7 - * API for manipulating and accessing per-domain virtual block devices.
    12.8 - * 
    12.9 - * Copyright (c) 2003, K A Fraser.
   12.10 - */
   12.11 -
   12.12 -#define _GNU_SOURCE
   12.13 -#include "libxc_private.h"
   12.14 -
   12.15 -int xc_vbd_create(unsigned int domid, unsigned short vbdid, int writeable)
   12.16 -{
   12.17 -    block_io_op_t op; 
   12.18 -    op.cmd = BLOCK_IO_OP_VBD_CREATE; 
   12.19 -    op.u.create_params.domain  = domid;
   12.20 -    op.u.create_params.vdevice = vbdid;
   12.21 -    op.u.create_params.mode    = VBD_MODE_R | (writeable ? VBD_MODE_W : 0);
   12.22 -    return do_block_io_op(&op);
   12.23 -}
   12.24 -
   12.25 -
   12.26 -int xc_vbd_destroy(unsigned int domid, unsigned short vbdid)
   12.27 -{
   12.28 -    block_io_op_t op; 
   12.29 -    op.cmd = BLOCK_IO_OP_VBD_DELETE; 
   12.30 -    op.u.delete_params.domain  = domid;
   12.31 -    op.u.delete_params.vdevice = vbdid;
   12.32 -    return do_block_io_op(&op);
   12.33 -}
   12.34 -
   12.35 -
   12.36 -int xc_vbd_add_extent(unsigned int domid, 
   12.37 -                      unsigned short vbdid,
   12.38 -                      unsigned short real_device,
   12.39 -                      unsigned long start_sector,
   12.40 -                      unsigned long nr_sectors)
   12.41 -{
   12.42 -    block_io_op_t op; 
   12.43 -    op.cmd = BLOCK_IO_OP_VBD_ADD; 
   12.44 -    op.u.add_params.domain  = domid; 
   12.45 -    op.u.add_params.vdevice = vbdid;
   12.46 -    op.u.add_params.extent.device       = real_device; 
   12.47 -    op.u.add_params.extent.start_sector = start_sector;
   12.48 -    op.u.add_params.extent.nr_sectors   = nr_sectors;
   12.49 -    return do_block_io_op(&op);
   12.50 -}
   12.51 -
   12.52 -
   12.53 -int xc_vbd_delete_extent(unsigned int domid, 
   12.54 -                         unsigned short vbdid,
   12.55 -                         unsigned short real_device,
   12.56 -                         unsigned long start_sector,
   12.57 -                         unsigned long nr_sectors)
   12.58 -{
   12.59 -    block_io_op_t op; 
   12.60 -    op.cmd = BLOCK_IO_OP_VBD_REMOVE; 
   12.61 -    op.u.add_params.domain  = domid; 
   12.62 -    op.u.add_params.vdevice = vbdid;
   12.63 -    op.u.add_params.extent.device       = real_device; 
   12.64 -    op.u.add_params.extent.start_sector = start_sector;
   12.65 -    op.u.add_params.extent.nr_sectors   = nr_sectors;
   12.66 -    return do_block_io_op(&op);
   12.67 -}
   12.68 -
   12.69 -
   12.70 -int xc_vbd_probe(unsigned int domid,
   12.71 -                 unsigned short vbdid,
   12.72 -                 unsigned int max_vbds,
   12.73 -                 xc_vbd_t *vbds)
   12.74 -{
   12.75 -    block_io_op_t op; 
   12.76 -    xen_disk_info_t *xdi = &op.u.probe_params.xdi; 
   12.77 -    int i, j, ret, allocsz = max_vbds * sizeof(xen_disk_t); 
   12.78 -
   12.79 -    op.cmd = BLOCK_IO_OP_VBD_PROBE; 
   12.80 -    op.u.probe_params.domain    = domid; 
   12.81 -    
   12.82 -    xdi->max   = max_vbds;
   12.83 -    xdi->disks = malloc(allocsz);
   12.84 -    xdi->count = 0;
   12.85 -
   12.86 -    if ( (xdi->disks == NULL) || (mlock(xdi->disks, allocsz) != 0) )
   12.87 -    {
   12.88 -        if ( xdi->disks != NULL )
   12.89 -            free(xdi->disks);
   12.90 -        return -ENOMEM;
   12.91 -    }
   12.92 -
   12.93 -    ret = do_block_io_op(&op);
   12.94 -
   12.95 -    (void)munlock(xdi->disks, allocsz);
   12.96 -
   12.97 -    if ( ret >= 0 )
   12.98 -    {
   12.99 -	for ( i = 0, j = 0; i < xdi->count; i++ )
  12.100 -        {
  12.101 -            if ( !(xdi->disks[i].info & XD_FLAG_VIRT) )
  12.102 -                continue;
  12.103 -            
  12.104 -            vbds[j].domid = xdi->disks[i].domain;
  12.105 -            vbds[j].vbdid = xdi->disks[i].device;
  12.106 -            vbds[j].flags = (xdi->disks[i].info & XD_FLAG_RO) ? 
  12.107 -                0 : XC_VBDF_WRITEABLE;
  12.108 -            vbds[j].nr_sectors = xdi->disks[i].capacity;
  12.109 -            
  12.110 -            j++;
  12.111 -        }
  12.112 -
  12.113 -        ret = j;
  12.114 -    }
  12.115 -    
  12.116 -    free(xdi->disks);
  12.117 -
  12.118 -    return ret;
  12.119 -}
    13.1 --- a/tools/libxc/libxc_vif.c	Thu Nov 20 10:03:52 2003 +0000
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,66 +0,0 @@
    13.4 -/******************************************************************************
    13.5 - * libxc_vif.c
    13.6 - * 
    13.7 - * API for manipulating and accessing per-network-interface parameters.
    13.8 - * 
    13.9 - * Copyright (c) 2003, K A Fraser.
   13.10 - */
   13.11 -
   13.12 -#include "libxc_private.h"
   13.13 -
   13.14 -int xc_vif_scheduler_set(unsigned int domid, 
   13.15 -                         unsigned int vifid, 
   13.16 -                         xc_vif_sched_params_t *params)
   13.17 -{
   13.18 -    network_op_t  netop;
   13.19 -    netop.cmd = NETWORK_OP_VIFSETPARAMS;
   13.20 -    netop.u.vif_setparams.domain       = domid;
   13.21 -    netop.u.vif_setparams.vif          = vifid;
   13.22 -    netop.u.vif_setparams.credit_bytes = params->credit_bytes;
   13.23 -    netop.u.vif_setparams.credit_usec  = params->credit_usec;
   13.24 -    return do_network_op(&netop);
   13.25 -}
   13.26 -
   13.27 -
   13.28 -int xc_vif_scheduler_get(unsigned int domid, 
   13.29 -                         unsigned int vifid, 
   13.30 -                         xc_vif_sched_params_t *params)
   13.31 -{
   13.32 -    network_op_t  netop;
   13.33 -    int rc;
   13.34 -
   13.35 -    netop.cmd = NETWORK_OP_VIFGETINFO;
   13.36 -    netop.u.vif_getinfo.domain = domid;
   13.37 -    netop.u.vif_getinfo.vif    = vifid;
   13.38 -
   13.39 -    if ( (rc = do_network_op(&netop)) >= 0 )
   13.40 -    {
   13.41 -        params->credit_bytes = netop.u.vif_getinfo.credit_bytes;
   13.42 -        params->credit_usec  = netop.u.vif_getinfo.credit_usec;
   13.43 -    }
   13.44 -
   13.45 -    return rc;
   13.46 -}
   13.47 -
   13.48 -
   13.49 -int xc_vif_stats_get(unsigned int domid, 
   13.50 -                     unsigned int vifid, 
   13.51 -                     xc_vif_stats_t *stats)
   13.52 -{
   13.53 -    network_op_t  netop;
   13.54 -    int rc;
   13.55 -
   13.56 -    netop.cmd = NETWORK_OP_VIFGETINFO;
   13.57 -    netop.u.vif_getinfo.domain = domid;
   13.58 -    netop.u.vif_getinfo.vif    = vifid;
   13.59 -
   13.60 -    if ( (rc = do_network_op(&netop)) >= 0 )
   13.61 -    {
   13.62 -        stats->tx_bytes = netop.u.vif_getinfo.total_bytes_sent;
   13.63 -        stats->tx_pkts  = netop.u.vif_getinfo.total_packets_sent;
   13.64 -        stats->rx_bytes = netop.u.vif_getinfo.total_bytes_received;
   13.65 -        stats->rx_pkts  = netop.u.vif_getinfo.total_packets_received;
   13.66 -    }
   13.67 -
   13.68 -    return rc;
   13.69 -}
    14.1 --- a/tools/libxc/rpm.spec	Thu Nov 20 10:03:52 2003 +0000
    14.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3 @@ -1,28 +0,0 @@
    14.4 -Summary: Xen control interface library
    14.5 -Name: xen-internal-library
    14.6 -Version: 1.2
    14.7 -Release: 1
    14.8 -License: Xen
    14.9 -Group: Xen
   14.10 -BuildRoot: %{staging}
   14.11 -%description
   14.12 -Library to make it easier to access the Xen control interfaces.
   14.13 -
   14.14 -%pre
   14.15 -%preun
   14.16 -%install
   14.17 -install -m 0755 -d $RPM_BUILD_ROOT/lib
   14.18 -install -m 0755 libxc.a $RPM_BUILD_ROOT/lib/libxc.a
   14.19 -install -m 0755 libxc.so $RPM_BUILD_ROOT/lib/libxc.so
   14.20 -install -m 0755 -d $RPM_BUILD_ROOT/include
   14.21 -install -m 0644 xc.h $RPM_BUILD_ROOT/include/xc.h
   14.22 -%clean
   14.23 -%post
   14.24 -%postun
   14.25 -%files
   14.26 -%defattr(-,root,root)
   14.27 -%dir /lib
   14.28 -/lib/libxc.a
   14.29 -/lib/libxc.so
   14.30 -%dir /include
   14.31 -/include/xc.h
    15.1 --- a/tools/libxc/xc.h	Thu Nov 20 10:03:52 2003 +0000
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,99 +0,0 @@
    15.4 -/******************************************************************************
    15.5 - * xc.h
    15.6 - * 
    15.7 - * A library for low-level access to the Xen control interfaces.
    15.8 - * 
    15.9 - * Copyright (c) 2003, K A Fraser.
   15.10 - */
   15.11 -
   15.12 -#ifndef __XC_H__
   15.13 -#define __XC_H__
   15.14 -
   15.15 -int xc_interface_open(void);
   15.16 -int xc_interface_close(void);
   15.17 -
   15.18 -typedef struct {
   15.19 -    unsigned int  domid;
   15.20 -    unsigned int  cpu;
   15.21 -    int           has_cpu;
   15.22 -    int           stopped;
   15.23 -    unsigned long nr_pages;
   15.24 -    unsigned long long cpu_time;
   15.25 -#define XC_DOMINFO_MAXNAME 16
   15.26 -    char          name[XC_DOMINFO_MAXNAME];
   15.27 -} xc_dominfo_t;
   15.28 -
   15.29 -int xc_domain_create(unsigned int mem_kb, const char *name);
   15.30 -int xc_domain_start(unsigned int domid);
   15.31 -int xc_domain_stop(unsigned int domid);
   15.32 -int xc_domain_destroy(unsigned int domid, int force);
   15.33 -int xc_domain_getinfo(unsigned int first_domid, 
   15.34 -                      unsigned int max_doms,
   15.35 -                      xc_dominfo_t *info);
   15.36 -
   15.37 -int xc_linux_save(unsigned int domid, const char *state_file, int verbose);
   15.38 -int xc_linux_restore(const char *state_file, int verbose);
   15.39 -int xc_linux_build(unsigned int domid,
   15.40 -                   const char *image_name,
   15.41 -                   const char *ramdisk_name,
   15.42 -                   const char *cmdline,
   15.43 -                   int verbose);
   15.44 -
   15.45 -int xc_bvtsched_global_set(unsigned long ctx_allow);
   15.46 -int xc_bvtsched_domain_set(unsigned int domid,
   15.47 -                           unsigned long mcuadv,
   15.48 -                           unsigned long warp,
   15.49 -                           unsigned long warpl,
   15.50 -                           unsigned long warpu);
   15.51 -
   15.52 -typedef struct {
   15.53 -    unsigned long credit_bytes;
   15.54 -    unsigned long credit_usec;
   15.55 -} xc_vif_sched_params_t;
   15.56 -
   15.57 -typedef struct {
   15.58 -    unsigned long long tx_bytes, tx_pkts;
   15.59 -    unsigned long long rx_bytes, rx_pkts;
   15.60 -} xc_vif_stats_t;
   15.61 -
   15.62 -int xc_vif_scheduler_set(unsigned int domid, 
   15.63 -                         unsigned int vifid,
   15.64 -                         xc_vif_sched_params_t *params);
   15.65 -int xc_vif_scheduler_get(unsigned int domid, 
   15.66 -                         unsigned int vifid,
   15.67 -                         xc_vif_sched_params_t *params);
   15.68 -int xc_vif_stats_get(unsigned int domid, 
   15.69 -                         unsigned int vifid,
   15.70 -                         xc_vif_stats_t *stats);
   15.71 -
   15.72 -typedef struct {
   15.73 -#define XC_VBDDOM_PROBE_ALL (~0U)
   15.74 -    unsigned int   domid;
   15.75 -    unsigned short vbdid;
   15.76 -#define XC_VBDF_WRITEABLE (1<<0)
   15.77 -    unsigned long  flags;
   15.78 -    unsigned long  nr_sectors;
   15.79 -} xc_vbd_t;
   15.80 -
   15.81 -
   15.82 -int xc_vbd_create(unsigned int domid, unsigned short vbdid, int writeable);
   15.83 -int xc_vbd_destroy(unsigned int domid, unsigned short vbdid);
   15.84 -int xc_vbd_add_extent(unsigned int domid, 
   15.85 -                      unsigned short vbdid,
   15.86 -                      unsigned short real_device,
   15.87 -                      unsigned long start_sector,
   15.88 -                      unsigned long nr_sectors);
   15.89 -int xc_vbd_delete_extent(unsigned int domid, 
   15.90 -                         unsigned short vbdid,
   15.91 -                         unsigned short real_device,
   15.92 -                         unsigned long start_sector,
   15.93 -                         unsigned long nr_sectors);
   15.94 -int xc_vbd_probe(unsigned int domid,
   15.95 -                 unsigned short vbdid,
   15.96 -                 unsigned int max_vbds,
   15.97 -                 xc_vbd_t *vbds);
   15.98 -
   15.99 -int xc_readconsolering(char *str, unsigned int max_chars, int clear);
  15.100 -
  15.101 -
  15.102 -#endif /* __XC_H__ */
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/tools/xc/Makefile	Thu Nov 20 11:24:01 2003 +0000
    16.3 @@ -0,0 +1,9 @@
    16.4 +
    16.5 +all:
    16.6 +	$(MAKE) -C lib
    16.7 +
    16.8 +install:
    16.9 +	$(MAKE) -C lib install
   16.10 +
   16.11 +clean:
   16.12 +	$(MAKE) -C lib xlean
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/tools/xc/lib/Makefile	Thu Nov 20 11:24:01 2003 +0000
    17.3 @@ -0,0 +1,48 @@
    17.4 +
    17.5 +CC       = gcc
    17.6 +CFLAGS   = -c -Wall -O3 
    17.7 +CFLAGS  += -I../../../xen/include -I../../../xenolinux-sparse/include
    17.8 +
    17.9 +HDRS     = $(wildcard *.h)
   17.10 +OBJS     = $(patsubst %.c,%.o,$(wildcard libxc_*.c))
   17.11 +
   17.12 +LIBS     = libxc.a libxc.so
   17.13 +
   17.14 +all: check-for-zlib $(LIBS)
   17.15 +	ranlib libxc.a
   17.16 +
   17.17 +check-for-zlib:
   17.18 +	@if [ ! -e /usr/include/zlib.h ]; then \
   17.19 +	echo "***********************************************************"; \
   17.20 +	echo "ERROR: install zlib header files (http://www.gzip.org/zlib)"; \
   17.21 +	echo "***********************************************************"; \
   17.22 +	false; \
   17.23 +	fi
   17.24 +
   17.25 +install: all
   17.26 +	mkdir -p ../../../../install/lib
   17.27 +	mkdir -p ../../../../install/include
   17.28 +	cp -a $(LIBS) ../../../../install/lib
   17.29 +	for i in $(LIBS) do ; chmod 755 ../../../../install/bin/$i ; done
   17.30 +	cp -a xc.h ../../../../install/include
   17.31 +	chmod 644 ../../../../install/include/xc.h
   17.32 +
   17.33 +clean:
   17.34 +	$(RM) *.a *.so *.o *.rpm $(LIBS)
   17.35 +
   17.36 +rpm: all
   17.37 +	rm -rf staging
   17.38 +	mkdir staging
   17.39 +	mkdir staging/i386
   17.40 +	rpmbuild --define "staging$$PWD/staging" --define '_builddir.' \
   17.41 +		--define "_rpmdir$$PWD/staging" -bb rpm.spec
   17.42 +	mv staging/i386/*.rpm .
   17.43 +	rm -rf staging
   17.44 +
   17.45 +libxc.so: $(OBJS)
   17.46 +	$(LD) -shared -o $@ $^ -lz
   17.47 +
   17.48 +libxc.a: libxc.a($(OBJS))
   17.49 +
   17.50 +%.o: %.c $(HDRS) Makefile
   17.51 +	$(CC) $(CFLAGS) -o $@ $<
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/tools/xc/lib/libxc_bvtsched.c	Thu Nov 20 11:24:01 2003 +0000
    18.3 @@ -0,0 +1,35 @@
    18.4 +/******************************************************************************
    18.5 + * libxc_bvtsched.c
    18.6 + * 
    18.7 + * API for manipulating parameters of the Borrowed Virtual Time scheduler.
    18.8 + * 
    18.9 + * Copyright (c) 2003, K A Fraser.
   18.10 + */
   18.11 +
   18.12 +#include "libxc_private.h"
   18.13 +
   18.14 +int xc_bvtsched_global_set(int xc_handle,
   18.15 +                           unsigned long ctx_allow)
   18.16 +{
   18.17 +    dom0_op_t op;
   18.18 +    op.cmd = DOM0_BVTCTL;
   18.19 +    op.u.bvtctl.ctx_allow = ctx_allow;
   18.20 +    return do_dom0_op(xc_handle, &op);
   18.21 +}
   18.22 +
   18.23 +int xc_bvtsched_domain_set(int xc_handle,
   18.24 +                           unsigned int domid,
   18.25 +                           unsigned long mcuadv,
   18.26 +                           unsigned long warp,
   18.27 +                           unsigned long warpl,
   18.28 +                           unsigned long warpu)
   18.29 +{
   18.30 +    dom0_op_t op;
   18.31 +    op.cmd = DOM0_ADJUSTDOM;
   18.32 +    op.u.adjustdom.domain  = domid;
   18.33 +    op.u.adjustdom.mcu_adv = mcuadv;
   18.34 +    op.u.adjustdom.warp    = warp;
   18.35 +    op.u.adjustdom.warpl   = warpl;
   18.36 +    op.u.adjustdom.warpu   = warpu;
   18.37 +    return do_dom0_op(xc_handle, &op);
   18.38 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/tools/xc/lib/libxc_domain.c	Thu Nov 20 11:24:01 2003 +0000
    19.3 @@ -0,0 +1,87 @@
    19.4 +/******************************************************************************
    19.5 + * libxc_domain.c
    19.6 + * 
    19.7 + * API for manipulating and obtaining information on domains.
    19.8 + * 
    19.9 + * Copyright (c) 2003, K A Fraser.
   19.10 + */
   19.11 +
   19.12 +#include "libxc_private.h"
   19.13 +
   19.14 +int xc_domain_create(int xc_handle,
   19.15 +                     unsigned int mem_kb, 
   19.16 +                     const char *name)
   19.17 +{
   19.18 +    int err;
   19.19 +    dom0_op_t op;
   19.20 +
   19.21 +    op.cmd = DOM0_CREATEDOMAIN;
   19.22 +    op.u.createdomain.memory_kb = mem_kb;
   19.23 +    strncpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
   19.24 +    op.u.createdomain.name[MAX_DOMAIN_NAME-1] = '\0';
   19.25 +
   19.26 +    err = do_dom0_op(xc_handle, &op);
   19.27 +
   19.28 +    return (err < 0) ? err : op.u.createdomain.domain;
   19.29 +}    
   19.30 +
   19.31 +
   19.32 +int xc_domain_start(int xc_handle,
   19.33 +                    unsigned int domid)
   19.34 +{
   19.35 +    dom0_op_t op;
   19.36 +    op.cmd = DOM0_STARTDOMAIN;
   19.37 +    op.u.startdomain.domain = domid;
   19.38 +    return do_dom0_op(xc_handle, &op);
   19.39 +}    
   19.40 +
   19.41 +
   19.42 +int xc_domain_stop(int xc_handle, 
   19.43 +                   unsigned int domid)
   19.44 +{
   19.45 +    dom0_op_t op;
   19.46 +    op.cmd = DOM0_STOPDOMAIN;
   19.47 +    op.u.stopdomain.domain = domid;
   19.48 +    return do_dom0_op(xc_handle, &op);
   19.49 +}    
   19.50 +
   19.51 +
   19.52 +int xc_domain_destroy(int xc_handle,
   19.53 +                      unsigned int domid, 
   19.54 +                      int force)
   19.55 +{
   19.56 +    dom0_op_t op;
   19.57 +    op.cmd = DOM0_DESTROYDOMAIN;
   19.58 +    op.u.destroydomain.domain = domid;
   19.59 +    op.u.destroydomain.force  = !!force;
   19.60 +    return do_dom0_op(xc_handle, &op);
   19.61 +}
   19.62 +
   19.63 +int xc_domain_getinfo(int xc_handle,
   19.64 +                      unsigned int first_domid,
   19.65 +                      unsigned int max_doms,
   19.66 +                      xc_dominfo_t *info)
   19.67 +{
   19.68 +    unsigned int nr_doms, next_domid = first_domid;
   19.69 +    dom0_op_t op;
   19.70 +
   19.71 +    for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
   19.72 +    {
   19.73 +        op.cmd = DOM0_GETDOMAININFO;
   19.74 +        op.u.getdomaininfo.domain = next_domid;
   19.75 +        if ( do_dom0_op(xc_handle, &op) < 0 )
   19.76 +            break;
   19.77 +        info->domid   = op.u.getdomaininfo.domain;
   19.78 +        info->cpu     = op.u.getdomaininfo.processor;
   19.79 +        info->has_cpu = op.u.getdomaininfo.has_cpu;
   19.80 +        info->stopped = (op.u.getdomaininfo.state == DOMSTATE_STOPPED);
   19.81 +        info->nr_pages = op.u.getdomaininfo.tot_pages;
   19.82 +        info->cpu_time = op.u.getdomaininfo.cpu_time;
   19.83 +        strncpy(info->name, op.u.getdomaininfo.name, XC_DOMINFO_MAXNAME);
   19.84 +        info->name[XC_DOMINFO_MAXNAME-1] = '\0';
   19.85 +
   19.86 +        next_domid = op.u.getdomaininfo.domain + 1;
   19.87 +    }
   19.88 +
   19.89 +    return nr_doms;
   19.90 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/tools/xc/lib/libxc_linux_build.c	Thu Nov 20 11:24:01 2003 +0000
    20.3 @@ -0,0 +1,478 @@
    20.4 +/******************************************************************************
    20.5 + * libxc_linux_build.c
    20.6 + */
    20.7 +
    20.8 +#include "libxc_private.h"
    20.9 +#include <zlib.h>
   20.10 +
   20.11 +/* This string is written to the head of every guest kernel image. */
   20.12 +#define GUEST_SIG   "XenoGues"
   20.13 +#define SIG_LEN    8
   20.14 +
   20.15 +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
   20.16 +#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   20.17 +
   20.18 +static long get_tot_pages(int xc_handle, int domid)
   20.19 +{
   20.20 +    dom0_op_t op;
   20.21 +    op.cmd = DOM0_GETDOMAININFO;
   20.22 +    op.u.getdomaininfo.domain = domid;
   20.23 +    return (do_dom0_op(xc_handle, &op) < 0) ? 
   20.24 +        -1 : op.u.getdomaininfo.tot_pages;
   20.25 +}
   20.26 +
   20.27 +static int get_pfn_list(int xc_handle,
   20.28 +                        int domid, 
   20.29 +                        unsigned long *pfn_buf, 
   20.30 +                        unsigned long max_pfns)
   20.31 +{
   20.32 +    dom0_op_t op;
   20.33 +    int ret;
   20.34 +    op.cmd = DOM0_GETMEMLIST;
   20.35 +    op.u.getmemlist.domain   = domid;
   20.36 +    op.u.getmemlist.max_pfns = max_pfns;
   20.37 +    op.u.getmemlist.buffer   = pfn_buf;
   20.38 +
   20.39 +    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
   20.40 +        return -1;
   20.41 +
   20.42 +    ret = do_dom0_op(xc_handle, &op);
   20.43 +
   20.44 +    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
   20.45 +
   20.46 +    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
   20.47 +}
   20.48 +
   20.49 +static int send_pgupdates(int xc_handle, mmu_update_t *updates, int nr_updates)
   20.50 +{
   20.51 +    int ret = -1;
   20.52 +    privcmd_hypercall_t hypercall;
   20.53 +
   20.54 +    hypercall.op     = __HYPERVISOR_mmu_update;
   20.55 +    hypercall.arg[0] = (unsigned long)updates;
   20.56 +    hypercall.arg[1] = (unsigned long)nr_updates;
   20.57 +
   20.58 +    if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 )
   20.59 +        goto out1;
   20.60 +
   20.61 +    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
   20.62 +        goto out2;
   20.63 +
   20.64 +    ret = 0;
   20.65 +
   20.66 + out2: (void)munlock(updates, nr_updates * sizeof(*updates));
   20.67 + out1: return ret;
   20.68 +}
   20.69 +
   20.70 +/* Read the kernel header, extracting the image size and load address. */
   20.71 +static int read_kernel_header(gzFile gfd, long dom_size, 
   20.72 +                              unsigned long *load_addr)
   20.73 +{
   20.74 +    char signature[SIG_LEN];
   20.75 +
   20.76 +    gzread(gfd, signature, SIG_LEN);
   20.77 +    if ( strncmp(signature, GUEST_SIG, SIG_LEN) )
   20.78 +    {
   20.79 +        ERROR("Kernel image does not contain required signature");
   20.80 +        return -1;
   20.81 +    }
   20.82 +
   20.83 +    /* Read the load address which immediately follows the Xeno signature. */
   20.84 +    gzread(gfd, load_addr, sizeof(unsigned long));
   20.85 +
   20.86 +    return 0;
   20.87 +}
   20.88 +
   20.89 +static int copy_to_domain_page(int pm_handle,
   20.90 +                               unsigned long dst_pfn, 
   20.91 +                               void *src_page)
   20.92 +{
   20.93 +    void *vaddr = map_pfn(pm_handle, dst_pfn);
   20.94 +    if ( vaddr == NULL )
   20.95 +        return -1;
   20.96 +    memcpy(vaddr, src_page, PAGE_SIZE);
   20.97 +    unmap_pfn(pm_handle, vaddr);
   20.98 +    return 0;
   20.99 +}
  20.100 +
  20.101 +static int setup_guestos(int xc_handle,
  20.102 +                         int dom, 
  20.103 +                         gzFile kernel_gfd, 
  20.104 +                         int initrd_fd, 
  20.105 +                         unsigned long tot_pages,
  20.106 +                         unsigned long *virt_startinfo_addr, 
  20.107 +                         unsigned long virt_load_addr, 
  20.108 +                         dom0_builddomain_t *builddomain, 
  20.109 +                         const char *cmdline,
  20.110 +                         unsigned long shared_info_frame)
  20.111 +{
  20.112 +    l1_pgentry_t *vl1tab = NULL, *vl1e = NULL;
  20.113 +    l2_pgentry_t *vl2tab = NULL, *vl2e = NULL;
  20.114 +    unsigned long *page_array = NULL;
  20.115 +    mmu_update_t *pgt_update_arr = NULL, *pgt_updates = NULL;
  20.116 +    int alloc_index, num_pt_pages;
  20.117 +    unsigned long l2tab;
  20.118 +    unsigned long l1tab = 0;
  20.119 +    unsigned long num_pgt_updates = 0;
  20.120 +    unsigned long count, pt_start, i, j;
  20.121 +    unsigned long initrd_addr = 0, initrd_len = 0;
  20.122 +    start_info_t *start_info;
  20.123 +    shared_info_t *shared_info;
  20.124 +    unsigned long ksize;
  20.125 +    int pm_handle;
  20.126 +
  20.127 +    memset(builddomain, 0, sizeof(*builddomain));
  20.128 +
  20.129 +    if ( (pm_handle = init_pfn_mapper()) < 0 )
  20.130 +        goto error_out;
  20.131 +
  20.132 +    pgt_updates = malloc((tot_pages + 1024) * 3 * sizeof(mmu_update_t));
  20.133 +    page_array = malloc(tot_pages * sizeof(unsigned long));
  20.134 +    pgt_update_arr = pgt_updates;
  20.135 +    if ( (pgt_update_arr == NULL) || (page_array == NULL) )
  20.136 +    {
  20.137 +        PERROR("Could not allocate memory");
  20.138 +        goto error_out;
  20.139 +    }
  20.140 +
  20.141 +    if ( get_pfn_list(xc_handle, dom, page_array, tot_pages) != tot_pages )
  20.142 +    {
  20.143 +        PERROR("Could not get the page frame list");
  20.144 +        goto error_out;
  20.145 +    }
  20.146 +
  20.147 +    /* Load the guest OS image. Let it take no more than 1/2 memory.*/
  20.148 +    for ( i = 0; i < ((tot_pages/2)*PAGE_SIZE); i += PAGE_SIZE )
  20.149 +    {
  20.150 +        char page[PAGE_SIZE];
  20.151 +        int size;
  20.152 +        if ( (size = gzread(kernel_gfd, page, PAGE_SIZE)) == -1 )
  20.153 +        {
  20.154 +            PERROR("Error reading kernel image, could not"
  20.155 +                   " read the whole image.");
  20.156 +            goto error_out;
  20.157 +        }
  20.158 +        if ( size == 0 )
  20.159 +            goto kernel_copied;
  20.160 +        copy_to_domain_page(pm_handle, page_array[i>>PAGE_SHIFT], page);
  20.161 +    }
  20.162 +    ERROR("Kernel too big to safely fit in domain memory");
  20.163 +    goto error_out;
  20.164 +
  20.165 + kernel_copied:
  20.166 +    /* ksize is kernel-image size rounded up to a page boundary. */
  20.167 +    ksize = i;
  20.168 +
  20.169 +    /* Load the initial ramdisk image. */
  20.170 +    if ( initrd_fd >= 0 )
  20.171 +    {
  20.172 +        struct stat stat;
  20.173 +        unsigned long isize;
  20.174 +
  20.175 +        if ( fstat(initrd_fd, &stat) < 0 )
  20.176 +        {
  20.177 +            PERROR("Could not stat the initrd image");
  20.178 +            goto error_out;
  20.179 +        }
  20.180 +        isize = stat.st_size;
  20.181 +        if ( (isize + ksize) > ((tot_pages/2) * PAGE_SIZE) )
  20.182 +        {
  20.183 +            ERROR("Kernel/initrd too big to safely fit in domain memory");
  20.184 +            goto error_out;
  20.185 +        }
  20.186 +
  20.187 +        initrd_addr = virt_load_addr + ksize;
  20.188 +        initrd_len  = isize;
  20.189 +
  20.190 +        for ( j = 0, i = ksize; j < isize; j += PAGE_SIZE, i += PAGE_SIZE )
  20.191 +        {
  20.192 +            char page[PAGE_SIZE];
  20.193 +            int size = ((isize-j) < PAGE_SIZE) ? (isize-j) : PAGE_SIZE;
  20.194 +            if ( read(initrd_fd, page, size) != size )
  20.195 +            {
  20.196 +                PERROR("Error reading initrd image, could not"
  20.197 +                       " read the whole image.");
  20.198 +                goto error_out;
  20.199 +            } 
  20.200 +            copy_to_domain_page(pm_handle, page_array[i>>PAGE_SHIFT], page);
  20.201 +        }
  20.202 +    }
  20.203 +
  20.204 +    alloc_index = tot_pages - 1;
  20.205 +
  20.206 +    /* Count bottom-level PTs, rounding up. */
  20.207 +    num_pt_pages = (l1_table_offset(virt_load_addr) + tot_pages + 1023) / 1024;
  20.208 +
  20.209 +    /* We must also count the page directory. */
  20.210 +    num_pt_pages++;
  20.211 +
  20.212 +    /* Index of first PT page. */
  20.213 +    pt_start = tot_pages - num_pt_pages;
  20.214 +
  20.215 +    /*
  20.216 +     * First allocate page for page dir. Allocation goes backwards from the end
  20.217 +     * of the allocated physical address space.
  20.218 +     */
  20.219 +    l2tab = page_array[alloc_index] << PAGE_SHIFT;
  20.220 +    alloc_index--;
  20.221 +    builddomain->ctxt.pt_base = l2tab;
  20.222 +
  20.223 +    /*
  20.224 +     * Pin down l2tab addr as page dir page - causes hypervisor to provide
  20.225 +     * correct protection for the page
  20.226 +     */ 
  20.227 +    pgt_updates->ptr = l2tab | MMU_EXTENDED_COMMAND;
  20.228 +    pgt_updates->val = MMUEXT_PIN_L2_TABLE;
  20.229 +    pgt_updates++;
  20.230 +    num_pgt_updates++;
  20.231 +
  20.232 +    /* Initialise the page tables. */
  20.233 +    if ( (vl2tab = map_pfn(pm_handle, l2tab >> PAGE_SHIFT)) == NULL )
  20.234 +        goto error_out;
  20.235 +    memset(vl2tab, 0, PAGE_SIZE);
  20.236 +    vl2e = vl2tab + l2_table_offset(virt_load_addr);
  20.237 +    for ( count = 0; count < tot_pages; count++ )
  20.238 +    {    
  20.239 +        if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) 
  20.240 +        {
  20.241 +            l1tab = page_array[alloc_index] << PAGE_SHIFT;
  20.242 +            if ( (vl1tab = map_pfn(pm_handle, l1tab >> PAGE_SHIFT)) == NULL )
  20.243 +                goto error_out;
  20.244 +            memset(vl1tab, 0, PAGE_SIZE);
  20.245 +            alloc_index--;
  20.246 +		
  20.247 +            vl1e = vl1tab + l1_table_offset(virt_load_addr + 
  20.248 +                                            (count << PAGE_SHIFT));
  20.249 +
  20.250 +            /* make apropriate entry in the page directory */
  20.251 +            pgt_updates->ptr = (unsigned long)vl2e;
  20.252 +            pgt_updates->val = l1tab | L2_PROT;
  20.253 +            pgt_updates++;
  20.254 +            num_pgt_updates++;
  20.255 +            vl2e++;
  20.256 +        }
  20.257 +
  20.258 +        if ( count < pt_start )
  20.259 +        {
  20.260 +            pgt_updates->ptr = (unsigned long)vl1e;
  20.261 +            pgt_updates->val = (page_array[count] << PAGE_SHIFT) | L1_PROT;
  20.262 +            pgt_updates++;
  20.263 +            num_pgt_updates++;
  20.264 +            vl1e++;
  20.265 +        }
  20.266 +        else
  20.267 +        {
  20.268 +            pgt_updates->ptr = (unsigned long)vl1e;
  20.269 +            pgt_updates->val = 
  20.270 +                ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
  20.271 +            pgt_updates++;
  20.272 +            num_pgt_updates++;
  20.273 +            vl1e++;
  20.274 +        }
  20.275 +
  20.276 +        pgt_updates->ptr = 
  20.277 +            (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
  20.278 +        pgt_updates->val = count;
  20.279 +        pgt_updates++;
  20.280 +        num_pgt_updates++;
  20.281 +    }
  20.282 +
  20.283 +    *virt_startinfo_addr =
  20.284 +        virt_load_addr + ((alloc_index-1) << PAGE_SHIFT);
  20.285 +
  20.286 +    start_info = map_pfn(pm_handle, page_array[alloc_index-1]);
  20.287 +    memset(start_info, 0, sizeof(*start_info));
  20.288 +    start_info->pt_base     = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
  20.289 +    start_info->mod_start   = initrd_addr;
  20.290 +    start_info->mod_len     = initrd_len;
  20.291 +    start_info->nr_pages    = tot_pages;
  20.292 +    start_info->shared_info = shared_info_frame << PAGE_SHIFT;
  20.293 +    start_info->dom_id      = dom;
  20.294 +    start_info->flags       = 0;
  20.295 +    strncpy(start_info->cmd_line, cmdline, MAX_CMD_LEN);
  20.296 +    start_info->cmd_line[MAX_CMD_LEN-1] = '\0';
  20.297 +
  20.298 +    unmap_pfn(pm_handle, start_info);
  20.299 +
  20.300 +    /* shared_info page starts its life empty. */
  20.301 +    shared_info = map_pfn(pm_handle, shared_info_frame);
  20.302 +    memset(shared_info, 0, PAGE_SIZE);
  20.303 +    unmap_pfn(pm_handle, shared_info);
  20.304 +
  20.305 +    /* Send the page update requests down to the hypervisor. */
  20.306 +    if ( send_pgupdates(xc_handle, pgt_update_arr, num_pgt_updates) < 0 )
  20.307 +        goto error_out;
  20.308 +
  20.309 +    free(page_array);
  20.310 +    free(pgt_update_arr);
  20.311 +    return 0;
  20.312 +
  20.313 + error_out:
  20.314 +    if ( pm_handle >= 0 )
  20.315 +        (void)close_pfn_mapper(pm_handle);
  20.316 +    if ( page_array == NULL )
  20.317 +        free(page_array);
  20.318 +    if ( pgt_update_arr == NULL )
  20.319 +        free(pgt_update_arr);
  20.320 +    return -1;
  20.321 +}
  20.322 +
  20.323 +int xc_domain_build(int xc_handle,
  20.324 +                    unsigned int domid,
  20.325 +                    const char *image_name,
  20.326 +                    const char *ramdisk_name,
  20.327 +                    const char *cmdline)
  20.328 +{
  20.329 +    dom0_op_t launch_op, op;
  20.330 +    unsigned long load_addr;
  20.331 +    long tot_pages;
  20.332 +    int kernel_fd, initrd_fd = -1;
  20.333 +    gzFile kernel_gfd;
  20.334 +    int rc, i;
  20.335 +    full_execution_context_t *ctxt;
  20.336 +    unsigned long virt_startinfo_addr;
  20.337 +
  20.338 +    if ( (tot_pages = get_tot_pages(xc_handle, domid)) < 0 )
  20.339 +    {
  20.340 +        PERROR("Could not find total pages for domain");
  20.341 +        return 1;
  20.342 +    }
  20.343 +
  20.344 +    kernel_fd = open(image_name, O_RDONLY);
  20.345 +    if ( kernel_fd < 0 )
  20.346 +    {
  20.347 +        PERROR("Could not open kernel image");
  20.348 +        return 1;
  20.349 +    }
  20.350 +
  20.351 +    if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
  20.352 +    {
  20.353 +        PERROR("Could not allocate decompression state for state file");
  20.354 +        close(kernel_fd);
  20.355 +        return 1;
  20.356 +    }
  20.357 +
  20.358 +    rc = read_kernel_header(kernel_gfd,
  20.359 +                            tot_pages << (PAGE_SHIFT - 10), 
  20.360 +                            &load_addr);
  20.361 +    if ( rc < 0 )
  20.362 +        goto error_out;
  20.363 +    
  20.364 +    if ( (load_addr & (PAGE_SIZE-1)) != 0 )
  20.365 +    {
  20.366 +        ERROR("We can only deal with page-aligned load addresses");
  20.367 +        goto error_out;
  20.368 +    }
  20.369 +
  20.370 +    if ( (load_addr + (tot_pages << PAGE_SHIFT)) > HYPERVISOR_VIRT_START )
  20.371 +    {
  20.372 +        ERROR("Cannot map all domain memory without hitting Xen space");
  20.373 +        goto error_out;
  20.374 +    }
  20.375 +
  20.376 +    if ( ramdisk_name != NULL )
  20.377 +    {
  20.378 +        initrd_fd = open(ramdisk_name, O_RDONLY);
  20.379 +        if ( initrd_fd < 0 )
  20.380 +        {
  20.381 +            PERROR("Could not open the initial ramdisk image");
  20.382 +            goto error_out;
  20.383 +        }
  20.384 +    }
  20.385 +
  20.386 +    op.cmd = DOM0_GETDOMAININFO;
  20.387 +    op.u.getdomaininfo.domain = domid;
  20.388 +    if ( (do_dom0_op(xc_handle, &op) < 0) || 
  20.389 +         (op.u.getdomaininfo.domain != domid) )
  20.390 +    {
  20.391 +        PERROR("Could not get info on domain");
  20.392 +        goto error_out;
  20.393 +    }
  20.394 +    if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) ||
  20.395 +         (op.u.getdomaininfo.ctxt.pt_base != 0) )
  20.396 +    {
  20.397 +        ERROR("Domain is already constructed");
  20.398 +        goto error_out;
  20.399 +    }
  20.400 +
  20.401 +    if ( setup_guestos(xc_handle, domid, kernel_gfd, initrd_fd, tot_pages,
  20.402 +                       &virt_startinfo_addr,
  20.403 +                       load_addr, &launch_op.u.builddomain, cmdline,
  20.404 +                       op.u.getdomaininfo.shared_info_frame) < 0 )
  20.405 +    {
  20.406 +        ERROR("Error constructing guest OS");
  20.407 +        goto error_out;
  20.408 +    }
  20.409 +
  20.410 +    if ( initrd_fd >= 0 )
  20.411 +        close(initrd_fd);
  20.412 +    gzclose(kernel_gfd);
  20.413 +
  20.414 +    ctxt = &launch_op.u.builddomain.ctxt;
  20.415 +
  20.416 +    ctxt->flags = 0;
  20.417 +
  20.418 +    /*
  20.419 +     * Initial register values:
  20.420 +     *  DS,ES,FS,GS = FLAT_RING1_DS
  20.421 +     *       CS:EIP = FLAT_RING1_CS:start_pc
  20.422 +     *       SS:ESP = FLAT_RING1_DS:start_stack
  20.423 +     *          ESI = start_info
  20.424 +     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
  20.425 +     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
  20.426 +     */
  20.427 +    ctxt->i386_ctxt.ds = FLAT_RING1_DS;
  20.428 +    ctxt->i386_ctxt.es = FLAT_RING1_DS;
  20.429 +    ctxt->i386_ctxt.fs = FLAT_RING1_DS;
  20.430 +    ctxt->i386_ctxt.gs = FLAT_RING1_DS;
  20.431 +    ctxt->i386_ctxt.ss = FLAT_RING1_DS;
  20.432 +    ctxt->i386_ctxt.cs = FLAT_RING1_CS;
  20.433 +    ctxt->i386_ctxt.eip = load_addr;
  20.434 +    ctxt->i386_ctxt.esp = virt_startinfo_addr;
  20.435 +    ctxt->i386_ctxt.esi = virt_startinfo_addr;
  20.436 +    ctxt->i386_ctxt.eflags = (1<<9) | (1<<2);
  20.437 +
  20.438 +    /* FPU is set up to default initial state. */
  20.439 +    memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt));
  20.440 +
  20.441 +    /* Virtual IDT is empty at start-of-day. */
  20.442 +    for ( i = 0; i < 256; i++ )
  20.443 +    {
  20.444 +        ctxt->trap_ctxt[i].vector = i;
  20.445 +        ctxt->trap_ctxt[i].cs     = FLAT_RING1_CS;
  20.446 +    }
  20.447 +    ctxt->fast_trap_idx = 0;
  20.448 +
  20.449 +    /* No LDT. */
  20.450 +    ctxt->ldt_ents = 0;
  20.451 +    
  20.452 +    /* Use the default Xen-provided GDT. */
  20.453 +    ctxt->gdt_ents = 0;
  20.454 +
  20.455 +    /* Ring 1 stack is the initial stack. */
  20.456 +    ctxt->ring1_ss  = FLAT_RING1_DS;
  20.457 +    ctxt->ring1_esp = virt_startinfo_addr;
  20.458 +
  20.459 +    /* No debugging. */
  20.460 +    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
  20.461 +
  20.462 +    /* No callback handlers. */
  20.463 +    ctxt->event_callback_cs     = FLAT_RING1_CS;
  20.464 +    ctxt->event_callback_eip    = 0;
  20.465 +    ctxt->failsafe_callback_cs  = FLAT_RING1_CS;
  20.466 +    ctxt->failsafe_callback_eip = 0;
  20.467 +
  20.468 +    launch_op.u.builddomain.domain   = domid;
  20.469 +    launch_op.u.builddomain.num_vifs = 1;
  20.470 +
  20.471 +    launch_op.cmd = DOM0_BUILDDOMAIN;
  20.472 +    rc = do_dom0_op(xc_handle, &launch_op);
  20.473 +    
  20.474 +    return rc;
  20.475 +
  20.476 + error_out:
  20.477 +    if ( initrd_fd >= 0 )
  20.478 +        close(initrd_fd);
  20.479 +    gzclose(kernel_gfd);
  20.480 +    return -1;
  20.481 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/tools/xc/lib/libxc_linux_restore.c	Thu Nov 20 11:24:01 2003 +0000
    21.3 @@ -0,0 +1,488 @@
    21.4 +/******************************************************************************
    21.5 + * libxc_linux_restore.c
    21.6 + * 
    21.7 + * Restore the state of a Xenolinux session.
    21.8 + * 
    21.9 + * Copyright (c) 2003, K A Fraser.
   21.10 + */
   21.11 +
   21.12 +#include "libxc_private.h"
   21.13 +#include <asm-xeno/suspend.h>
   21.14 +#include <zlib.h>
   21.15 +
   21.16 +/* This may allow us to create a 'quiet' command-line option, if necessary. */
   21.17 +#define verbose_printf(_f, _a...) \
   21.18 +    do {                          \
   21.19 +        if ( !verbose ) break;    \
   21.20 +        printf( _f , ## _a );     \
   21.21 +        fflush(stdout);           \
   21.22 +    } while ( 0 )
   21.23 +
   21.24 +static int get_pfn_list(int xc_handle,
   21.25 +                        int domain_id, 
   21.26 +                        unsigned long *pfn_buf, 
   21.27 +                        unsigned long max_pfns)
   21.28 +{
   21.29 +    dom0_op_t op;
   21.30 +    int ret;
   21.31 +    op.cmd = DOM0_GETMEMLIST;
   21.32 +    op.u.getmemlist.domain   = domain_id;
   21.33 +    op.u.getmemlist.max_pfns = max_pfns;
   21.34 +    op.u.getmemlist.buffer   = pfn_buf;
   21.35 +
   21.36 +    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
   21.37 +    {
   21.38 +        PERROR("Could not lock pfn list buffer");
   21.39 +        return -1;
   21.40 +    }    
   21.41 +
   21.42 +    ret = do_dom0_op(xc_handle, &op);
   21.43 +
   21.44 +    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
   21.45 +
   21.46 +    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
   21.47 +}
   21.48 +
   21.49 +#define MAX_MMU_UPDATES 1024
   21.50 +
   21.51 +static int flush_mmu_updates(int xc_handle,
   21.52 +                             mmu_update_t *mmu_updates,
   21.53 +                             int *mmu_update_idx)
   21.54 +{
   21.55 +    int err = 0;
   21.56 +    privcmd_hypercall_t hypercall;
   21.57 +
   21.58 +    if ( *mmu_update_idx == 0 )
   21.59 +        return 0;
   21.60 +
   21.61 +    hypercall.op     = __HYPERVISOR_mmu_update;
   21.62 +    hypercall.arg[0] = (unsigned long)mmu_updates;
   21.63 +    hypercall.arg[1] = (unsigned long)*mmu_update_idx;
   21.64 +
   21.65 +    if ( mlock(mmu_updates, sizeof(mmu_updates)) != 0 )
   21.66 +    {
   21.67 +        PERROR("Could not lock pagetable update array");
   21.68 +        err = 1;
   21.69 +        goto out;
   21.70 +    }
   21.71 +
   21.72 +    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
   21.73 +    {
   21.74 +        ERROR("Failure when submitting mmu updates");
   21.75 +        err = 1;
   21.76 +    }
   21.77 +
   21.78 +    *mmu_update_idx = 0;
   21.79 +    
   21.80 +    (void)munlock(mmu_updates, sizeof(mmu_updates));
   21.81 +
   21.82 + out:
   21.83 +    return err;
   21.84 +}
   21.85 +
   21.86 +static int add_mmu_update(int xc_handle,
   21.87 +                          mmu_update_t *mmu_updates,
   21.88 +                          int *mmu_update_idx,
   21.89 +                          unsigned long ptr, 
   21.90 +                          unsigned long val)
   21.91 +{
   21.92 +    mmu_updates[*mmu_update_idx].ptr = ptr;
   21.93 +    mmu_updates[*mmu_update_idx].val = val;
   21.94 +    if ( ++*mmu_update_idx == MAX_MMU_UPDATES )
   21.95 +        return flush_mmu_updates(xc_handle, mmu_updates, mmu_update_idx);
   21.96 +    return 0;
   21.97 +}
   21.98 +
   21.99 +static int checked_read(gzFile fd, void *buf, size_t count)
  21.100 +{
  21.101 +    int rc;
  21.102 +    while ( ((rc = gzread(fd, buf, count)) == -1) && (errno == EINTR) )
  21.103 +        continue;
  21.104 +    return rc == count;
  21.105 +}
  21.106 +
  21.107 +int xc_linux_restore(int xc_handle,
  21.108 +                     const char *state_file,
  21.109 +                     int verbose)
  21.110 +{
  21.111 +    dom0_op_t op;
  21.112 +    int rc = 1, i, j;
  21.113 +    unsigned long mfn, pfn, dom = 0;
  21.114 +    unsigned int prev_pc, this_pc;
  21.115 +    
  21.116 +    /* Number of page frames in use by this XenoLinux session. */
  21.117 +    unsigned long nr_pfns;
  21.118 +
  21.119 +    /* The new domain's shared-info frame number. */
  21.120 +    unsigned long shared_info_frame;
  21.121 +    unsigned char shared_info[PAGE_SIZE]; /* saved contents from file */
  21.122 +    
  21.123 +    /* A copy of the CPU context of the guest. */
  21.124 +    full_execution_context_t ctxt;
  21.125 +
  21.126 +    /* First 16 bytes of the state file must contain 'XenoLinuxSuspend'. */
  21.127 +    char signature[16];
  21.128 +    
  21.129 +    /* A copy of the domain's name. */
  21.130 +    char name[MAX_DOMAIN_NAME];
  21.131 +
  21.132 +    /* A table containg the type of each PFN (/not/ MFN!). */
  21.133 +    unsigned long *pfn_type = NULL;
  21.134 +
  21.135 +    /* A temporary mapping, and a copy, of one frame of guest memory. */
  21.136 +    unsigned long *ppage, page[1024];
  21.137 +
  21.138 +    /* A copy of the pfn-to-mfn table frame list. */
  21.139 +    unsigned long pfn_to_mfn_frame_list[1024];
  21.140 +
  21.141 +    /* A table mapping each PFN to its new MFN. */
  21.142 +    unsigned long *pfn_to_mfn_table = NULL;
  21.143 +
  21.144 +    /* A temporary mapping of the guest's suspend record. */
  21.145 +    suspend_record_t *p_srec;
  21.146 +
  21.147 +    /* The name and descriptor of the file that we are reading from. */
  21.148 +    int    fd;
  21.149 +    gzFile gfd;
  21.150 +
  21.151 +    mmu_update_t mmu_updates[MAX_MMU_UPDATES];
  21.152 +    int mmu_update_idx = 0;
  21.153 +
  21.154 +    int pm_handle = -1;
  21.155 +
  21.156 +    if ( (fd = open(state_file, O_RDONLY)) == -1 )
  21.157 +    {
  21.158 +        PERROR("Could not open state file for reading");
  21.159 +        return 1;
  21.160 +    }
  21.161 +
  21.162 +    if ( (gfd = gzdopen(fd, "rb")) == NULL )
  21.163 +    {
  21.164 +        ERROR("Could not allocate decompression state for state file");
  21.165 +        close(fd);
  21.166 +        return 1;
  21.167 +    }
  21.168 +
  21.169 +    /* Start writing out the saved-domain record. */
  21.170 +    if ( !checked_read(gfd, signature, 16) ||
  21.171 +         (memcmp(signature, "XenoLinuxSuspend", 16) != 0) )
  21.172 +    {
  21.173 +        ERROR("Unrecognised state format -- no signature found");
  21.174 +        goto out;
  21.175 +    }
  21.176 +
  21.177 +    if ( !checked_read(gfd, name,                  sizeof(name)) ||
  21.178 +         !checked_read(gfd, &nr_pfns,              sizeof(unsigned long)) ||
  21.179 +         !checked_read(gfd, &ctxt,                 sizeof(ctxt)) ||
  21.180 +         !checked_read(gfd, shared_info,           PAGE_SIZE) ||
  21.181 +         !checked_read(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) )
  21.182 +    {
  21.183 +        ERROR("Error when reading from state file");
  21.184 +        goto out;
  21.185 +    }
  21.186 +
  21.187 +    for ( i = 0; i < MAX_DOMAIN_NAME; i++ )
  21.188 +    {
  21.189 +        if ( name[i] == '\0' ) break;
  21.190 +        if ( name[i] & 0x80 )
  21.191 +        {
  21.192 +            ERROR("Random characters in domain name");
  21.193 +            goto out;
  21.194 +        }
  21.195 +    }
  21.196 +    name[MAX_DOMAIN_NAME-1] = '\0';
  21.197 +
  21.198 +    if ( nr_pfns > 1024*1024 )
  21.199 +    {
  21.200 +        ERROR("Invalid state file -- pfn count out of range");
  21.201 +        goto out;
  21.202 +    }
  21.203 +
  21.204 +    /* We want zeroed memory so use calloc rather than malloc. */
  21.205 +    pfn_to_mfn_table = calloc(1, 4 * nr_pfns);
  21.206 +    pfn_type         = calloc(1, 4 * nr_pfns);    
  21.207 +
  21.208 +    if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) )
  21.209 +    {
  21.210 +        errno = ENOMEM;
  21.211 +        goto out;
  21.212 +    }
  21.213 +
  21.214 +    if ( !checked_read(gfd, pfn_type, 4 * nr_pfns) )
  21.215 +    {
  21.216 +        ERROR("Error when reading from state file");
  21.217 +        goto out;
  21.218 +    }
  21.219 +
  21.220 +    /* Create a new domain of the appropriate size, and find it's dom_id. */
  21.221 +    op.cmd = DOM0_CREATEDOMAIN;
  21.222 +    op.u.createdomain.memory_kb = nr_pfns * (PAGE_SIZE / 1024);
  21.223 +    memcpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
  21.224 +    if ( do_dom0_op(xc_handle, &op) < 0 )
  21.225 +    {
  21.226 +        ERROR("Could not create new domain");
  21.227 +        goto out;
  21.228 +    }
  21.229 +    dom = op.u.createdomain.domain;
  21.230 +
  21.231 +    /* Get the domain's shared-info frame. */
  21.232 +    op.cmd = DOM0_GETDOMAININFO;
  21.233 +    op.u.getdomaininfo.domain = dom;
  21.234 +    if ( do_dom0_op(xc_handle, &op) < 0 )
  21.235 +    {
  21.236 +        ERROR("Could not get information on new domain");
  21.237 +        goto out;
  21.238 +    }
  21.239 +    shared_info_frame = op.u.getdomaininfo.shared_info_frame;
  21.240 +
  21.241 +    if ( (pm_handle = init_pfn_mapper()) < 0 )
  21.242 +        goto out;
  21.243 +
  21.244 +    /* Copy saved contents of shared-info page. No checking needed. */
  21.245 +    ppage = map_pfn(pm_handle, shared_info_frame);
  21.246 +    memcpy(ppage, shared_info, PAGE_SIZE);
  21.247 +    unmap_pfn(pm_handle, ppage);
  21.248 +
  21.249 +    /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
  21.250 +    if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns )
  21.251 +    {
  21.252 +        ERROR("Did not read correct number of frame numbers for new dom");
  21.253 +        goto out;
  21.254 +    }
  21.255 +
  21.256 +    verbose_printf("Reloading memory pages:   0%%");
  21.257 +
  21.258 +    /*
  21.259 +     * Now simply read each saved frame into its new machine frame.
  21.260 +     * We uncanonicalise page tables as we go.
  21.261 +     */
  21.262 +    prev_pc = 0;
  21.263 +    for ( i = 0; i < nr_pfns; i++ )
  21.264 +    {
  21.265 +        this_pc = (i * 100) / nr_pfns;
  21.266 +        if ( (this_pc - prev_pc) >= 5 )
  21.267 +        {
  21.268 +            verbose_printf("\b\b\b\b%3d%%", this_pc);
  21.269 +            prev_pc = this_pc;
  21.270 +        }
  21.271 +
  21.272 +        mfn = pfn_to_mfn_table[i];
  21.273 +
  21.274 +        if ( !checked_read(gfd, page, PAGE_SIZE) )
  21.275 +        {
  21.276 +            ERROR("Error when reading from state file");
  21.277 +            goto out;
  21.278 +        }
  21.279 +
  21.280 +        ppage = map_pfn(pm_handle, mfn);
  21.281 +        switch ( pfn_type[i] )
  21.282 +        {
  21.283 +        case L1TAB:
  21.284 +            memset(ppage, 0, PAGE_SIZE);
  21.285 +            if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
  21.286 +                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
  21.287 +                                MMUEXT_PIN_L1_TABLE) )
  21.288 +                goto out;
  21.289 +            for ( j = 0; j < 1024; j++ )
  21.290 +            {
  21.291 +                if ( page[j] & _PAGE_PRESENT )
  21.292 +                {
  21.293 +                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
  21.294 +                    {
  21.295 +                        ERROR("Frame number in page table is out of range");
  21.296 +                        goto out;
  21.297 +                    }
  21.298 +                    if ( (pfn_type[pfn] != NONE) && (page[j] & _PAGE_RW) )
  21.299 +                    {
  21.300 +                        ERROR("Write access requested for a restricted frame");
  21.301 +                        goto out;
  21.302 +                    }
  21.303 +                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT);
  21.304 +                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
  21.305 +                }
  21.306 +                if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
  21.307 +                                    (unsigned long)&ppage[j], page[j]) )
  21.308 +                    goto out;
  21.309 +            }
  21.310 +            break;
  21.311 +        case L2TAB:
  21.312 +            memset(ppage, 0, PAGE_SIZE);
  21.313 +            if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
  21.314 +                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
  21.315 +                                MMUEXT_PIN_L2_TABLE) )
  21.316 +                goto out;
  21.317 +            for ( j = 0; j < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); j++ )
  21.318 +            {
  21.319 +                if ( page[j] & _PAGE_PRESENT )
  21.320 +                {
  21.321 +                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
  21.322 +                    {
  21.323 +                        ERROR("Frame number in page table is out of range");
  21.324 +                        goto out;
  21.325 +                    }
  21.326 +                    if ( pfn_type[pfn] != L1TAB )
  21.327 +                    {
  21.328 +                        ERROR("Page table mistyping");
  21.329 +                        goto out;
  21.330 +                    }
  21.331 +                    /* Haven't reached the L1 table yet. Ensure it is safe! */
  21.332 +                    if ( pfn > i )
  21.333 +                    {
  21.334 +                        unsigned long **l1 = map_pfn(pm_handle, 
  21.335 +                                                     pfn_to_mfn_table[pfn]);
  21.336 +                        memset(l1, 0, PAGE_SIZE);
  21.337 +                        unmap_pfn(pm_handle, l1);
  21.338 +                    }
  21.339 +                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE);
  21.340 +                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
  21.341 +                }
  21.342 +                if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
  21.343 +                                    (unsigned long)&ppage[j], page[j]) )
  21.344 +                    goto out;
  21.345 +            }
  21.346 +            break;
  21.347 +        default:
  21.348 +            memcpy(ppage, page, PAGE_SIZE);
  21.349 +            break;
  21.350 +        }
  21.351 +        /* NB. Must flush before unmapping page, as pass VAs to Xen. */
  21.352 +        if ( flush_mmu_updates(xc_handle, mmu_updates, &mmu_update_idx) )
  21.353 +            goto out;
  21.354 +        unmap_pfn(pm_handle, ppage);
  21.355 +
  21.356 +        if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
  21.357 +                            (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, i) )
  21.358 +            goto out;
  21.359 +    }
  21.360 +
  21.361 +    if ( flush_mmu_updates(xc_handle, mmu_updates, &mmu_update_idx) )
  21.362 +        goto out;
  21.363 +
  21.364 +    verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n");
  21.365 +
  21.366 +    /* Uncanonicalise the suspend-record frame number and poke resume rec. */
  21.367 +    pfn = ctxt.i386_ctxt.esi;
  21.368 +    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
  21.369 +    {
  21.370 +        ERROR("Suspend record frame number is bad");
  21.371 +        goto out;
  21.372 +    }
  21.373 +    ctxt.i386_ctxt.esi = mfn = pfn_to_mfn_table[pfn];
  21.374 +    p_srec = map_pfn(pm_handle, mfn);
  21.375 +    p_srec->resume_info.nr_pages    = nr_pfns;
  21.376 +    p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT;
  21.377 +    p_srec->resume_info.dom_id      = dom;
  21.378 +    p_srec->resume_info.flags       = 0;
  21.379 +    unmap_pfn(pm_handle, p_srec);
  21.380 +
  21.381 +    /* Uncanonicalise each GDT frame number. */
  21.382 +    if ( ctxt.gdt_ents > 8192 )
  21.383 +    {
  21.384 +        ERROR("GDT entry count out of range");
  21.385 +        goto out;
  21.386 +    }
  21.387 +    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
  21.388 +    {
  21.389 +        pfn = ctxt.gdt_frames[i];
  21.390 +        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
  21.391 +        {
  21.392 +            ERROR("GDT frame number is bad");
  21.393 +            goto out;
  21.394 +        }
  21.395 +        ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn];
  21.396 +    }
  21.397 +
  21.398 +    /* Uncanonicalise the page table base pointer. */
  21.399 +    pfn = ctxt.pt_base >> PAGE_SHIFT;
  21.400 +    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) )
  21.401 +    {
  21.402 +        ERROR("PT base is bad");
  21.403 +        goto out;
  21.404 +    }
  21.405 +    ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT;
  21.406 +
  21.407 +    /* Uncanonicalise the pfn-to-mfn table frame-number list. */
  21.408 +    for ( i = 0; i < nr_pfns; i += 1024 )
  21.409 +    {
  21.410 +        unsigned long copy_size = (nr_pfns - i) * sizeof(unsigned long);
  21.411 +        if ( copy_size > PAGE_SIZE ) copy_size = PAGE_SIZE;
  21.412 +        pfn = pfn_to_mfn_frame_list[i/1024];
  21.413 +        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
  21.414 +        {
  21.415 +            ERROR("PFN-to-MFN frame number is bad");
  21.416 +            goto out;
  21.417 +        }
  21.418 +        ppage = map_pfn(pm_handle, pfn_to_mfn_table[pfn]);
  21.419 +        memcpy(ppage, &pfn_to_mfn_table[i], copy_size);        
  21.420 +        unmap_pfn(pm_handle, ppage);
  21.421 +    }
  21.422 +
  21.423 +    /*
  21.424 +     * Safety checking of saved context:
  21.425 +     *  1. i386_ctxt is fine, as Xen checks that on context switch.
  21.426 +     *  2. i387_ctxt is fine, as it can't hurt Xen.
  21.427 +     *  3. trap_ctxt needs the code selectors checked.
  21.428 +     *  4. fast_trap_idx is checked by Xen.
  21.429 +     *  5. ldt base must be page-aligned, no more than 8192 ents, ...
  21.430 +     *  6. gdt already done, and further checking is done by Xen.
  21.431 +     *  7. check that ring1_ss is safe.
  21.432 +     *  8. pt_base is already done.
  21.433 +     *  9. debugregs are checked by Xen.
  21.434 +     *  10. callback code selectors need checking.
  21.435 +     */
  21.436 +    for ( i = 0; i < 256; i++ )
  21.437 +    {
  21.438 +        ctxt.trap_ctxt[i].vector = i;
  21.439 +        if ( (ctxt.trap_ctxt[i].cs & 3) == 0 )
  21.440 +            ctxt.trap_ctxt[i].cs = FLAT_RING1_CS;
  21.441 +    }
  21.442 +    if ( (ctxt.ring1_ss & 3) == 0 )
  21.443 +        ctxt.ring1_ss = FLAT_RING1_DS;
  21.444 +    if ( (ctxt.event_callback_cs & 3) == 0 )
  21.445 +        ctxt.event_callback_cs = FLAT_RING1_CS;
  21.446 +    if ( (ctxt.failsafe_callback_cs & 3) == 0 )
  21.447 +        ctxt.failsafe_callback_cs = FLAT_RING1_CS;
  21.448 +    if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) ||
  21.449 +         (ctxt.ldt_ents > 8192) ||
  21.450 +         (ctxt.ldt_base > HYPERVISOR_VIRT_START) ||
  21.451 +         ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) )
  21.452 +    {
  21.453 +        ERROR("Bad LDT base or size");
  21.454 +        goto out;
  21.455 +    }
  21.456 +
  21.457 +    op.cmd = DOM0_BUILDDOMAIN;
  21.458 +    op.u.builddomain.domain   = dom;
  21.459 +    op.u.builddomain.num_vifs = 1;
  21.460 +    memcpy(&op.u.builddomain.ctxt, &ctxt, sizeof(ctxt));
  21.461 +    rc = do_dom0_op(xc_handle, &op);
  21.462 +
  21.463 + out:
  21.464 +    if ( rc != 0 )
  21.465 +    {
  21.466 +        if ( dom != 0 )
  21.467 +        {
  21.468 +            op.cmd = DOM0_DESTROYDOMAIN;
  21.469 +            op.u.destroydomain.domain = dom;
  21.470 +            op.u.destroydomain.force  = 1;
  21.471 +            (void)do_dom0_op(xc_handle, &op);
  21.472 +        }
  21.473 +    }
  21.474 +    else
  21.475 +    {
  21.476 +        /* Success: print the domain id. */
  21.477 +        verbose_printf("DOM=%ld\n", dom);
  21.478 +    }
  21.479 +
  21.480 +    if ( pm_handle >= 0 )
  21.481 +        (void)close_pfn_mapper(pm_handle);
  21.482 +
  21.483 +    if ( pfn_to_mfn_table != NULL )
  21.484 +        free(pfn_to_mfn_table);
  21.485 +    if ( pfn_type != NULL )
  21.486 +        free(pfn_type);
  21.487 +
  21.488 +    gzclose(gfd);
  21.489 +
  21.490 +    return (rc == 0) ? dom : rc;
  21.491 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/tools/xc/lib/libxc_linux_save.c	Thu Nov 20 11:24:01 2003 +0000
    22.3 @@ -0,0 +1,392 @@
    22.4 +/******************************************************************************
    22.5 + * libxc_linux_save.c
    22.6 + * 
    22.7 + * Save the state of a running Xenolinux session.
    22.8 + * 
    22.9 + * Copyright (c) 2003, K A Fraser.
   22.10 + */
   22.11 +
   22.12 +#include "libxc_private.h"
   22.13 +#include <asm-xeno/suspend.h>
   22.14 +#include <zlib.h>
   22.15 +
   22.16 +/* This may allow us to create a 'quiet' command-line option, if necessary. */
   22.17 +#define verbose_printf(_f, _a...) \
   22.18 +    do {                          \
   22.19 +        if ( !verbose ) break;    \
   22.20 +        printf( _f , ## _a );     \
   22.21 +        fflush(stdout);           \
   22.22 +    } while ( 0 )
   22.23 +
   22.24 +/*
   22.25 + * Returns TRUE if the given machine frame number has a unique mapping
   22.26 + * in the guest's pseudophysical map.
   22.27 + */
   22.28 +#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \
   22.29 +    (((_mfn) < (1024*1024)) &&          \
   22.30 +     (pfn_to_mfn_table[mfn_to_pfn_table[_mfn]] == (_mfn)))
   22.31 +
   22.32 +/* Returns TRUE if MFN is successfully converted to a PFN. */
   22.33 +#define translate_mfn_to_pfn(_pmfn)         \
   22.34 +({                                          \
   22.35 +    unsigned long mfn = *(_pmfn);           \
   22.36 +    int _res = 1;                           \
   22.37 +    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )   \
   22.38 +        _res = 0;                           \
   22.39 +    else                                    \
   22.40 +        *(_pmfn) = mfn_to_pfn_table[mfn];   \
   22.41 +    _res;                                   \
   22.42 +})
   22.43 +
   22.44 +static int check_pfn_ownership(int xc_handle, 
   22.45 +                               unsigned long mfn, 
   22.46 +                               unsigned int dom)
   22.47 +{
   22.48 +    dom0_op_t op;
   22.49 +    op.cmd = DOM0_GETPAGEFRAMEINFO;
   22.50 +    op.u.getpageframeinfo.pfn = mfn;
   22.51 +    if ( (do_dom0_op(xc_handle, &op) < 0) || 
   22.52 +         (op.u.getpageframeinfo.domain != dom) )
   22.53 +        return 0;
   22.54 +    return 1;
   22.55 +}
   22.56 +
   22.57 +#define GETPFN_ERR (~0U)
   22.58 +static unsigned int get_pfn_type(int xc_handle, unsigned long mfn)
   22.59 +{
   22.60 +    dom0_op_t op;
   22.61 +    op.cmd = DOM0_GETPAGEFRAMEINFO;
   22.62 +    op.u.getpageframeinfo.pfn = mfn;
   22.63 +    if ( do_dom0_op(xc_handle, &op) < 0 )
   22.64 +    {
   22.65 +        PERROR("Unexpected failure when getting page frame info!");
   22.66 +        return GETPFN_ERR;
   22.67 +    }
   22.68 +    return op.u.getpageframeinfo.type;
   22.69 +}
   22.70 +
   22.71 +static int checked_write(gzFile fd, void *buf, size_t count)
   22.72 +{
   22.73 +    int rc;
   22.74 +    while ( ((rc = gzwrite(fd, buf, count)) == -1) && (errno = EINTR) )
   22.75 +        continue;
   22.76 +    return rc == count;
   22.77 +}
   22.78 +
   22.79 +int xc_linux_save(int xc_handle,
   22.80 +                  unsigned int domid, 
   22.81 +                  const char *state_file, 
   22.82 +                  int verbose)
   22.83 +{
   22.84 +    dom0_op_t op;
   22.85 +    int rc = 1, i, j;
   22.86 +    unsigned long mfn;
   22.87 +    unsigned int prev_pc, this_pc;
   22.88 +
   22.89 +    /* Remember if we stopped the guest, so we can restart it on exit. */
   22.90 +    int we_stopped_it = 0;
   22.91 +
   22.92 +    /* The new domain's shared-info frame number. */
   22.93 +    unsigned long shared_info_frame;
   22.94 +    
   22.95 +    /* A copy of the CPU context of the guest. */
   22.96 +    full_execution_context_t ctxt;
   22.97 +
   22.98 +    /* A copy of the domain's name. */
   22.99 +    char name[MAX_DOMAIN_NAME];
  22.100 +
  22.101 +    /* A table containg the type of each PFN (/not/ MFN!). */
  22.102 +    unsigned long *pfn_type = NULL;
  22.103 +
  22.104 +    /* A temporary mapping, and a copy, of one frame of guest memory. */
  22.105 +    unsigned long *ppage, page[1024];
  22.106 +
  22.107 +    /* A temporary mapping, and a copy, of the pfn-to-mfn table frame list. */
  22.108 +    unsigned long *p_pfn_to_mfn_frame_list, pfn_to_mfn_frame_list[1024];
  22.109 +    /* A temporary mapping of one frame in the above list. */
  22.110 +    unsigned long *pfn_to_mfn_frame;
  22.111 +
  22.112 +    /* A table mapping each PFN to its current MFN. */
  22.113 +    unsigned long *pfn_to_mfn_table = NULL;
  22.114 +    /* A table mapping each current MFN to its canonical PFN. */
  22.115 +    unsigned long *mfn_to_pfn_table = NULL;
  22.116 +    
  22.117 +    /* A temporary mapping, and a copy, of the guest's suspend record. */
  22.118 +    suspend_record_t *p_srec, srec;
  22.119 +
  22.120 +    /* The name and descriptor of the file that we are writing to. */
  22.121 +    int    fd;
  22.122 +    gzFile gfd;
  22.123 +
  22.124 +    int pm_handle = -1;
  22.125 +
  22.126 +    if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 )
  22.127 +    {
  22.128 +        PERROR("Could not open file for writing");
  22.129 +        return 1;
  22.130 +    }
  22.131 +
  22.132 +    /*
  22.133 +     * Compression rate 1: we want speed over compression. We're mainly going
  22.134 +     * for those zero pages, after all.
  22.135 +     */
  22.136 +    if ( (gfd = gzdopen(fd, "wb1")) == NULL )
  22.137 +    {
  22.138 +        ERROR("Could not allocate compression state for state file");
  22.139 +        close(fd);
  22.140 +        return 1;
  22.141 +    }
  22.142 +
  22.143 +    /* Ensure that the domain exists, and that it is stopped. */
  22.144 +    for ( ; ; )
  22.145 +    {
  22.146 +        op.cmd = DOM0_GETDOMAININFO;
  22.147 +        op.u.getdomaininfo.domain = domid;
  22.148 +        if ( (do_dom0_op(xc_handle, &op) < 0) || 
  22.149 +             (op.u.getdomaininfo.domain != domid) )
  22.150 +        {
  22.151 +            PERROR("Could not get info on domain");
  22.152 +            goto out;
  22.153 +        }
  22.154 +
  22.155 +        memcpy(&ctxt, &op.u.getdomaininfo.ctxt, sizeof(ctxt));
  22.156 +        memcpy(name, op.u.getdomaininfo.name, sizeof(name));
  22.157 +        shared_info_frame = op.u.getdomaininfo.shared_info_frame;
  22.158 +
  22.159 +        if ( op.u.getdomaininfo.state == DOMSTATE_STOPPED )
  22.160 +            break;
  22.161 +
  22.162 +        we_stopped_it = 1;
  22.163 +
  22.164 +        op.cmd = DOM0_STOPDOMAIN;
  22.165 +        op.u.stopdomain.domain = domid;
  22.166 +        (void)do_dom0_op(xc_handle, &op);
  22.167 +
  22.168 +        sleep(1);
  22.169 +    }
  22.170 +
  22.171 +    /* A cheesy test to see whether the domain contains valid state. */
  22.172 +    if ( ctxt.pt_base == 0 )
  22.173 +    {
  22.174 +        ERROR("Domain is not in a valid Xenolinux state");
  22.175 +        goto out;
  22.176 +    }
  22.177 +
  22.178 +    if ( (pm_handle = init_pfn_mapper()) < 0 )
  22.179 +        goto out;
  22.180 +
  22.181 +    /* Is the suspend-record MFN actually valid for this domain? */
  22.182 +    if ( !check_pfn_ownership(xc_handle, ctxt.i386_ctxt.esi, domid) )
  22.183 +    {
  22.184 +        ERROR("Invalid state record pointer");
  22.185 +        goto out;
  22.186 +    }
  22.187 +
  22.188 +    /* If the suspend-record MFN is okay then grab a copy of it to @srec. */
  22.189 +    p_srec = map_pfn(pm_handle, ctxt.i386_ctxt.esi);
  22.190 +    memcpy(&srec, p_srec, sizeof(srec));
  22.191 +    unmap_pfn(pm_handle, p_srec);
  22.192 +
  22.193 +    if ( srec.nr_pfns > 1024*1024 )
  22.194 +    {
  22.195 +        ERROR("Invalid state record -- pfn count out of range");
  22.196 +        goto out;
  22.197 +    }
  22.198 +
  22.199 +    if ( !check_pfn_ownership(xc_handle, srec.pfn_to_mfn_frame_list, domid) )
  22.200 +    {
  22.201 +        ERROR("Invalid pfn-to-mfn frame list pointer");
  22.202 +        goto out;
  22.203 +    }
  22.204 +
  22.205 +    /* Grab a copy of the pfn-to-mfn table frame list. */
  22.206 +    p_pfn_to_mfn_frame_list = map_pfn(pm_handle, srec.pfn_to_mfn_frame_list);
  22.207 +    memcpy(pfn_to_mfn_frame_list, p_pfn_to_mfn_frame_list, PAGE_SIZE);
  22.208 +    unmap_pfn(pm_handle, p_pfn_to_mfn_frame_list);
  22.209 +
  22.210 +    /* We want zeroed memory so use calloc rather than malloc. */
  22.211 +    mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024);
  22.212 +    pfn_to_mfn_table = calloc(1, 4 * srec.nr_pfns);
  22.213 +    pfn_type         = calloc(1, 4 * srec.nr_pfns);
  22.214 +
  22.215 +    if ( (mfn_to_pfn_table == NULL) ||
  22.216 +         (pfn_to_mfn_table == NULL) ||
  22.217 +         (pfn_type == NULL) )
  22.218 +    {
  22.219 +        errno = ENOMEM;
  22.220 +        goto out;
  22.221 +    }
  22.222 +
  22.223 +
  22.224 +    /*
  22.225 +     * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this
  22.226 +     * loop we have each MFN mapped at most once. Note that there may be MFNs
  22.227 +     * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP.
  22.228 +     */
  22.229 +    pfn_to_mfn_frame = NULL;
  22.230 +    for ( i = 0; i < srec.nr_pfns; i++ )
  22.231 +    {
  22.232 +        /* Each frameful of table frames must be checked & mapped on demand. */
  22.233 +        if ( (i & 1023) == 0 )
  22.234 +        {
  22.235 +            mfn = pfn_to_mfn_frame_list[i/1024];
  22.236 +            if ( !check_pfn_ownership(xc_handle, mfn, domid) )
  22.237 +            {
  22.238 +                ERROR("Invalid frame number if pfn-to-mfn frame list");
  22.239 +                goto out;
  22.240 +            }
  22.241 +            if ( pfn_to_mfn_frame != NULL )
  22.242 +                unmap_pfn(pm_handle, pfn_to_mfn_frame);
  22.243 +            pfn_to_mfn_frame = map_pfn(pm_handle, mfn);
  22.244 +        }
  22.245 +        
  22.246 +        mfn = pfn_to_mfn_frame[i & 1023];
  22.247 +
  22.248 +        if ( !check_pfn_ownership(xc_handle, mfn, domid) )
  22.249 +        {
  22.250 +            ERROR("Invalid frame specified with pfn-to-mfn table");
  22.251 +            goto out;
  22.252 +        }
  22.253 +
  22.254 +        /* Did we map this MFN already? That would be invalid! */
  22.255 +        if ( MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
  22.256 +        {
  22.257 +            ERROR("A machine frame appears twice in pseudophys space");
  22.258 +            goto out;
  22.259 +        }
  22.260 +
  22.261 +        pfn_to_mfn_table[i] = mfn;
  22.262 +        mfn_to_pfn_table[mfn] = i;
  22.263 +
  22.264 +        /* Query page type by MFN, but store it by PFN. */
  22.265 +        if ( (pfn_type[i] = get_pfn_type(xc_handle, mfn)) == GETPFN_ERR )
  22.266 +            goto out;
  22.267 +    }
  22.268 +
  22.269 +    /* Canonicalise the suspend-record frame number. */
  22.270 +    if ( !translate_mfn_to_pfn(&ctxt.i386_ctxt.esi) )
  22.271 +    {
  22.272 +        ERROR("State record is not in range of pseudophys map");
  22.273 +        goto out;
  22.274 +    }
  22.275 +
  22.276 +    /* Canonicalise each GDT frame number. */
  22.277 +    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
  22.278 +    {
  22.279 +        if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) )
  22.280 +        {
  22.281 +            ERROR("GDT frame is not in range of pseudophys map");
  22.282 +            goto out;
  22.283 +        }
  22.284 +    }
  22.285 +
  22.286 +    /* Canonicalise the page table base pointer. */
  22.287 +    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) )
  22.288 +    {
  22.289 +        ERROR("PT base is not in range of pseudophys map");
  22.290 +        goto out;
  22.291 +    }
  22.292 +    ctxt.pt_base = mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT;
  22.293 +
  22.294 +    /* Canonicalise the pfn-to-mfn table frame-number list. */
  22.295 +    for ( i = 0; i < srec.nr_pfns; i += 1024 )
  22.296 +    {
  22.297 +        if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
  22.298 +        {
  22.299 +            ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys");
  22.300 +            goto out;
  22.301 +        }
  22.302 +    }
  22.303 +
  22.304 +    /* Start writing out the saved-domain record. */
  22.305 +    ppage = map_pfn(pm_handle, shared_info_frame);
  22.306 +    if ( !checked_write(gfd, "XenoLinuxSuspend",    16) ||
  22.307 +         !checked_write(gfd, name,                  sizeof(name)) ||
  22.308 +         !checked_write(gfd, &srec.nr_pfns,         sizeof(unsigned long)) ||
  22.309 +         !checked_write(gfd, &ctxt,                 sizeof(ctxt)) ||
  22.310 +         !checked_write(gfd, ppage,                 PAGE_SIZE) ||
  22.311 +         !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) ||
  22.312 +         !checked_write(gfd, pfn_type,              4 * srec.nr_pfns) )
  22.313 +    {
  22.314 +        ERROR("Error when writing to state file");
  22.315 +        goto out;
  22.316 +    }
  22.317 +    unmap_pfn(pm_handle, ppage);
  22.318 +
  22.319 +    verbose_printf("Saving memory pages:   0%%");
  22.320 +
  22.321 +    /* Now write out each data page, canonicalising page tables as we go... */
  22.322 +    prev_pc = 0;
  22.323 +    for ( i = 0; i < srec.nr_pfns; i++ )
  22.324 +    {
  22.325 +        this_pc = (i * 100) / srec.nr_pfns;
  22.326 +        if ( (this_pc - prev_pc) >= 5 )
  22.327 +        {
  22.328 +            verbose_printf("\b\b\b\b%3d%%", this_pc);
  22.329 +            prev_pc = this_pc;
  22.330 +        }
  22.331 +
  22.332 +        mfn = pfn_to_mfn_table[i];
  22.333 +
  22.334 +        ppage = map_pfn(pm_handle, mfn);
  22.335 +        memcpy(page, ppage, PAGE_SIZE);
  22.336 +        unmap_pfn(pm_handle, ppage);
  22.337 +
  22.338 +        if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) )
  22.339 +        {
  22.340 +            for ( j = 0; 
  22.341 +                  j < ((pfn_type[i] == L2TAB) ? 
  22.342 +                       (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 
  22.343 +                  j++ )
  22.344 +            {
  22.345 +                if ( !(page[j] & _PAGE_PRESENT) ) continue;
  22.346 +                mfn = page[j] >> PAGE_SHIFT;
  22.347 +                if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
  22.348 +                {
  22.349 +                    ERROR("Frame number in pagetable page is invalid");
  22.350 +                    goto out;
  22.351 +                }
  22.352 +                page[j] &= PAGE_SIZE - 1;
  22.353 +                page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT;
  22.354 +            }
  22.355 +        }
  22.356 +
  22.357 +        if ( !checked_write(gfd, page, PAGE_SIZE) )
  22.358 +        {
  22.359 +            ERROR("Error when writing to state file");
  22.360 +            goto out;
  22.361 +        }
  22.362 +    }
  22.363 +
  22.364 +    verbose_printf("\b\b\b\b100%%\nMemory saved.\n");
  22.365 +
  22.366 +    /* Success! */
  22.367 +    rc = 0;
  22.368 +
  22.369 + out:
  22.370 +    /* Restart the domain if we had to stop it to save its state. */
  22.371 +    if ( we_stopped_it )
  22.372 +    {
  22.373 +        op.cmd = DOM0_STARTDOMAIN;
  22.374 +        op.u.startdomain.domain = domid;
  22.375 +        (void)do_dom0_op(xc_handle, &op);
  22.376 +    }
  22.377 +
  22.378 +    gzclose(gfd);
  22.379 +
  22.380 +    if ( pm_handle >= 0 )
  22.381 +        (void)close_pfn_mapper(pm_handle);
  22.382 +
  22.383 +    if ( pfn_to_mfn_table != NULL )
  22.384 +        free(pfn_to_mfn_table);
  22.385 +    if ( mfn_to_pfn_table != NULL )
  22.386 +        free(mfn_to_pfn_table);
  22.387 +    if ( pfn_type != NULL )
  22.388 +        free(pfn_type);
  22.389 +
  22.390 +    /* On error, make sure the file is deleted. */
  22.391 +    if ( rc != 0 )
  22.392 +        unlink(state_file);
  22.393 +    
  22.394 +    return !!rc;
  22.395 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/tools/xc/lib/libxc_misc.c	Thu Nov 20 11:24:01 2003 +0000
    23.3 @@ -0,0 +1,40 @@
    23.4 +/******************************************************************************
    23.5 + * libxc_misc.c
    23.6 + * 
    23.7 + * Miscellaneous control interface functions.
    23.8 + */
    23.9 +
   23.10 +#include "libxc_private.h"
   23.11 +
   23.12 +int xc_interface_open(void)
   23.13 +{
   23.14 +    return open("/proc/xeno/privcmd", O_RDWR);
   23.15 +}
   23.16 +
   23.17 +int xc_interface_close(int xc_handle)
   23.18 +{
   23.19 +    return close(xc_handle);
   23.20 +}
   23.21 +
   23.22 +
   23.23 +#define CONSOLE_RING_CLEAR	1
   23.24 +
   23.25 +int xc_readconsolering(int xc_handle,
   23.26 +                       char *str, 
   23.27 +                       unsigned int max_chars, 
   23.28 +                       int clear)
   23.29 +{
   23.30 +    int ret;
   23.31 +    dom0_op_t op;
   23.32 +
   23.33 +    op.cmd = DOM0_READCONSOLE;
   23.34 +    op.u.readconsole.str = (unsigned long)str;
   23.35 +    op.u.readconsole.count = max_chars;
   23.36 +    op.u.readconsole.cmd = clear ? CONSOLE_RING_CLEAR : 0;
   23.37 +
   23.38 +    if ( (ret = do_dom0_op(xc_handle, &op)) > 0 )
   23.39 +        str[ret] = '\0';
   23.40 +
   23.41 +    return ret;
   23.42 +}    
   23.43 +
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/tools/xc/lib/libxc_private.c	Thu Nov 20 11:24:01 2003 +0000
    24.3 @@ -0,0 +1,31 @@
    24.4 +/******************************************************************************
    24.5 + * libxc_private.c
    24.6 + * 
    24.7 + * Helper functions for the rest of the library.
    24.8 + */
    24.9 +
   24.10 +#include "libxc_private.h"
   24.11 +
   24.12 +int init_pfn_mapper(void)
   24.13 +{
   24.14 +    return open("/dev/mem", O_RDWR);
   24.15 +}
   24.16 +
   24.17 +int close_pfn_mapper(int pm_handle)
   24.18 +{
   24.19 +    return close(pm_handle);
   24.20 +}
   24.21 +
   24.22 +void *map_pfn(int pm_handle, unsigned long pfn)
   24.23 +{
   24.24 +    void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
   24.25 +                       MAP_SHARED, pm_handle, pfn << PAGE_SHIFT);
   24.26 +    if ( vaddr == MAP_FAILED )
   24.27 +        return NULL;
   24.28 +    return vaddr;
   24.29 +}
   24.30 +
   24.31 +void unmap_pfn(int pm_handle, void *vaddr)
   24.32 +{
   24.33 +    (void)munmap(vaddr, PAGE_SIZE);
   24.34 +}
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/tools/xc/lib/libxc_private.h	Thu Nov 20 11:24:01 2003 +0000
    25.3 @@ -0,0 +1,169 @@
    25.4 +
    25.5 +#ifndef __LIBXC_PRIVATE_H__
    25.6 +#define __LIBXC_PRIVATE_H__
    25.7 +
    25.8 +typedef unsigned char      u8;
    25.9 +typedef unsigned short     u16;
   25.10 +typedef unsigned long      u32;
   25.11 +typedef unsigned long long u64;
   25.12 +typedef signed char        s8;
   25.13 +typedef signed short       s16;
   25.14 +typedef signed long        s32;
   25.15 +typedef signed long long   s64;
   25.16 +
   25.17 +#include <unistd.h>
   25.18 +#include <stdio.h>
   25.19 +#include <errno.h>
   25.20 +#include <fcntl.h>
   25.21 +#include <sys/mman.h>
   25.22 +#include <sys/types.h>
   25.23 +#include <sys/stat.h>
   25.24 +#include <stdlib.h>
   25.25 +#include <sys/ioctl.h>
   25.26 +#include <errno.h>
   25.27 +#include <string.h>
   25.28 +
   25.29 +#include "xc.h"
   25.30 +
   25.31 +#include <asm-xeno/proc_cmd.h>
   25.32 +#include <hypervisor-ifs/hypervisor-if.h>
   25.33 +#include <hypervisor-ifs/dom0_ops.h>
   25.34 +#include <hypervisor-ifs/vbd.h>
   25.35 +
   25.36 +#define _PAGE_PRESENT   0x001
   25.37 +#define _PAGE_RW        0x002
   25.38 +#define _PAGE_USER      0x004
   25.39 +#define _PAGE_PWT       0x008
   25.40 +#define _PAGE_PCD       0x010
   25.41 +#define _PAGE_ACCESSED  0x020
   25.42 +#define _PAGE_DIRTY     0x040
   25.43 +#define _PAGE_PAT       0x080
   25.44 +#define _PAGE_PSE       0x080
   25.45 +#define _PAGE_GLOBAL    0x100
   25.46 +
   25.47 +
   25.48 +#define L1_PAGETABLE_SHIFT       12
   25.49 +#define L2_PAGETABLE_SHIFT       22
   25.50 + 
   25.51 +#define ENTRIES_PER_L1_PAGETABLE 1024
   25.52 +#define ENTRIES_PER_L2_PAGETABLE 1024
   25.53 + 
   25.54 +#define PAGE_SHIFT              L1_PAGETABLE_SHIFT
   25.55 +#define PAGE_SIZE               (1UL << PAGE_SHIFT)
   25.56 +#define PAGE_MASK               (~(PAGE_SIZE-1))
   25.57 +
   25.58 +typedef struct { unsigned long l1_lo; } l1_pgentry_t;
   25.59 +typedef struct { unsigned long l2_lo; } l2_pgentry_t;
   25.60 +
   25.61 +#define l1_table_offset(_a) \
   25.62 +          (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
   25.63 +#define l2_table_offset(_a) \
   25.64 +          ((_a) >> L2_PAGETABLE_SHIFT)
   25.65 +
   25.66 +#define ERROR(_m)  \
   25.67 +    fprintf(stderr, "ERROR: %s\n", (_m))
   25.68 +
   25.69 +#define PERROR(_m) \
   25.70 +    fprintf(stderr, "ERROR: %s (%d = %s)\n", (_m), errno, strerror(errno))
   25.71 +
   25.72 +static inline int do_privcmd(int xc_handle,
   25.73 +                             unsigned int cmd, 
   25.74 +                             unsigned long data)
   25.75 +{
   25.76 +    return ioctl(xc_handle, cmd, data);
   25.77 +}
   25.78 +
   25.79 +static inline int do_xen_hypercall(int xc_handle,
   25.80 +                                   privcmd_hypercall_t *hypercall)
   25.81 +{
   25.82 +    return do_privcmd(xc_handle,
   25.83 +                      IOCTL_PRIVCMD_HYPERCALL, 
   25.84 +                      (unsigned long)hypercall);
   25.85 +}
   25.86 +
   25.87 +static inline int do_dom0_op(int xc_handle, dom0_op_t *op)
   25.88 +{
   25.89 +    int ret = -1;
   25.90 +    privcmd_hypercall_t hypercall;
   25.91 +
   25.92 +    op->interface_version = DOM0_INTERFACE_VERSION;
   25.93 +
   25.94 +    hypercall.op     = __HYPERVISOR_dom0_op;
   25.95 +    hypercall.arg[0] = (unsigned long)op;
   25.96 +
   25.97 +    if ( mlock(op, sizeof(*op)) != 0 )
   25.98 +    {
   25.99 +        PERROR("Could not lock memory for Xen hypercall");
  25.100 +        goto out1;
  25.101 +    }
  25.102 +
  25.103 +    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
  25.104 +    {
  25.105 +        if ( errno == EACCES )
  25.106 +            fprintf(stderr, "Dom0 operation failed -- need to"
  25.107 +                    " rebuild the user-space tool set?\n");
  25.108 +        goto out2;
  25.109 +    }
  25.110 +
  25.111 +    ret = 0;
  25.112 +
  25.113 + out2: (void)munlock(op, sizeof(*op));
  25.114 + out1: return ret;
  25.115 +}
  25.116 +
  25.117 +static inline int do_network_op(int xc_handle, network_op_t *op)
  25.118 +{
  25.119 +    int ret = -1;
  25.120 +    privcmd_hypercall_t hypercall;
  25.121 +
  25.122 +    hypercall.op     = __HYPERVISOR_network_op;
  25.123 +    hypercall.arg[0] = (unsigned long)op;
  25.124 +
  25.125 +    if ( mlock(op, sizeof(*op)) != 0 )
  25.126 +    {
  25.127 +        PERROR("Could not lock memory for Xen hypercall");
  25.128 +        goto out1;
  25.129 +    }
  25.130 +
  25.131 +    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
  25.132 +        goto out2;
  25.133 +
  25.134 +    ret = 0;
  25.135 +
  25.136 + out2: (void)munlock(op, sizeof(*op));
  25.137 + out1: return ret;
  25.138 +}
  25.139 +
  25.140 +
  25.141 +static inline int do_block_io_op(int xc_handle, block_io_op_t *op)
  25.142 +{
  25.143 +    int ret = -1;
  25.144 +    privcmd_hypercall_t hypercall;
  25.145 +
  25.146 +    hypercall.op     = __HYPERVISOR_block_io_op;
  25.147 +    hypercall.arg[0] = (unsigned long)op;
  25.148 +
  25.149 +    if ( mlock(op, sizeof(*op)) != 0 )
  25.150 +    {
  25.151 +        PERROR("Could not lock memory for Xen hypercall");
  25.152 +        goto out1;
  25.153 +    }
  25.154 +
  25.155 +    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
  25.156 +        goto out2;
  25.157 +
  25.158 +    ret = 0;
  25.159 +
  25.160 + out2: (void)munlock(op, sizeof(*op));
  25.161 + out1: return ret;
  25.162 +}
  25.163 +
  25.164 +/*
  25.165 + * PFN mapping.
  25.166 + */
  25.167 +int init_pfn_mapper(void);
  25.168 +int close_pfn_mapper(int pm_handle);
  25.169 +void *map_pfn(int pm_handle, unsigned long pfn);
  25.170 +void unmap_pfn(int pm_handle, void *vaddr);
  25.171 +
  25.172 +#endif /* __LIBXC_PRIVATE_H__ */
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/tools/xc/lib/libxc_vbd.c	Thu Nov 20 11:24:01 2003 +0000
    26.3 @@ -0,0 +1,124 @@
    26.4 +/******************************************************************************
    26.5 + * libxc_vbd.c
    26.6 + * 
    26.7 + * API for manipulating and accessing per-domain virtual block devices.
    26.8 + * 
    26.9 + * Copyright (c) 2003, K A Fraser.
   26.10 + */
   26.11 +
   26.12 +#define _GNU_SOURCE
   26.13 +#include "libxc_private.h"
   26.14 +
   26.15 +int xc_vbd_create(int xc_handle,
   26.16 +                  unsigned int domid, 
   26.17 +                  unsigned short vbdid, 
   26.18 +                  int writeable)
   26.19 +{
   26.20 +    block_io_op_t op; 
   26.21 +    op.cmd = BLOCK_IO_OP_VBD_CREATE; 
   26.22 +    op.u.create_params.domain  = domid;
   26.23 +    op.u.create_params.vdevice = vbdid;
   26.24 +    op.u.create_params.mode    = VBD_MODE_R | (writeable ? VBD_MODE_W : 0);
   26.25 +    return do_block_io_op(xc_handle, &op);
   26.26 +}
   26.27 +
   26.28 +
   26.29 +int xc_vbd_destroy(int xc_handle,
   26.30 +                   unsigned int domid, 
   26.31 +                   unsigned short vbdid)
   26.32 +{
   26.33 +    block_io_op_t op; 
   26.34 +    op.cmd = BLOCK_IO_OP_VBD_DELETE; 
   26.35 +    op.u.delete_params.domain  = domid;
   26.36 +    op.u.delete_params.vdevice = vbdid;
   26.37 +    return do_block_io_op(xc_handle, &op);
   26.38 +}
   26.39 +
   26.40 +
   26.41 +int xc_vbd_add_extent(int xc_handle,
   26.42 +                      unsigned int domid, 
   26.43 +                      unsigned short vbdid,
   26.44 +                      unsigned short real_device,
   26.45 +                      unsigned long start_sector,
   26.46 +                      unsigned long nr_sectors)
   26.47 +{
   26.48 +    block_io_op_t op; 
   26.49 +    op.cmd = BLOCK_IO_OP_VBD_ADD; 
   26.50 +    op.u.add_params.domain  = domid; 
   26.51 +    op.u.add_params.vdevice = vbdid;
   26.52 +    op.u.add_params.extent.device       = real_device; 
   26.53 +    op.u.add_params.extent.start_sector = start_sector;
   26.54 +    op.u.add_params.extent.nr_sectors   = nr_sectors;
   26.55 +    return do_block_io_op(xc_handle, &op);
   26.56 +}
   26.57 +
   26.58 +
   26.59 +int xc_vbd_delete_extent(int xc_handle,
   26.60 +                         unsigned int domid, 
   26.61 +                         unsigned short vbdid,
   26.62 +                         unsigned short real_device,
   26.63 +                         unsigned long start_sector,
   26.64 +                         unsigned long nr_sectors)
   26.65 +{
   26.66 +    block_io_op_t op; 
   26.67 +    op.cmd = BLOCK_IO_OP_VBD_REMOVE; 
   26.68 +    op.u.add_params.domain  = domid; 
   26.69 +    op.u.add_params.vdevice = vbdid;
   26.70 +    op.u.add_params.extent.device       = real_device; 
   26.71 +    op.u.add_params.extent.start_sector = start_sector;
   26.72 +    op.u.add_params.extent.nr_sectors   = nr_sectors;
   26.73 +    return do_block_io_op(xc_handle, &op);
   26.74 +}
   26.75 +
   26.76 +
   26.77 +int xc_vbd_probe(int xc_handle,
   26.78 +                 unsigned int domid,
   26.79 +                 unsigned short vbdid,
   26.80 +                 unsigned int max_vbds,
   26.81 +                 xc_vbd_t *vbds)
   26.82 +{
   26.83 +    block_io_op_t op; 
   26.84 +    xen_disk_info_t *xdi = &op.u.probe_params.xdi; 
   26.85 +    int i, j, ret, allocsz = max_vbds * sizeof(xen_disk_t); 
   26.86 +
   26.87 +    op.cmd = BLOCK_IO_OP_VBD_PROBE; 
   26.88 +    op.u.probe_params.domain    = domid; 
   26.89 +    
   26.90 +    xdi->max   = max_vbds;
   26.91 +    xdi->disks = malloc(allocsz);
   26.92 +    xdi->count = 0;
   26.93 +
   26.94 +    if ( (xdi->disks == NULL) || (mlock(xdi->disks, allocsz) != 0) )
   26.95 +    {
   26.96 +        if ( xdi->disks != NULL )
   26.97 +            free(xdi->disks);
   26.98 +        return -ENOMEM;
   26.99 +    }
  26.100 +
  26.101 +    ret = do_block_io_op(xc_handle, &op);
  26.102 +
  26.103 +    (void)munlock(xdi->disks, allocsz);
  26.104 +
  26.105 +    if ( ret >= 0 )
  26.106 +    {
  26.107 +	for ( i = 0, j = 0; i < xdi->count; i++ )
  26.108 +        {
  26.109 +            if ( !(xdi->disks[i].info & XD_FLAG_VIRT) )
  26.110 +                continue;
  26.111 +            
  26.112 +            vbds[j].domid = xdi->disks[i].domain;
  26.113 +            vbds[j].vbdid = xdi->disks[i].device;
  26.114 +            vbds[j].flags = (xdi->disks[i].info & XD_FLAG_RO) ? 
  26.115 +                0 : XC_VBDF_WRITEABLE;
  26.116 +            vbds[j].nr_sectors = xdi->disks[i].capacity;
  26.117 +            
  26.118 +            j++;
  26.119 +        }
  26.120 +
  26.121 +        ret = j;
  26.122 +    }
  26.123 +    
  26.124 +    free(xdi->disks);
  26.125 +
  26.126 +    return ret;
  26.127 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/tools/xc/lib/libxc_vif.c	Thu Nov 20 11:24:01 2003 +0000
    27.3 @@ -0,0 +1,69 @@
    27.4 +/******************************************************************************
    27.5 + * libxc_vif.c
    27.6 + * 
    27.7 + * API for manipulating and accessing per-network-interface parameters.
    27.8 + * 
    27.9 + * Copyright (c) 2003, K A Fraser.
   27.10 + */
   27.11 +
   27.12 +#include "libxc_private.h"
   27.13 +
   27.14 +int xc_vif_scheduler_set(int xc_handle,
   27.15 +                         unsigned int domid, 
   27.16 +                         unsigned int vifid, 
   27.17 +                         xc_vif_sched_params_t *params)
   27.18 +{
   27.19 +    network_op_t  netop;
   27.20 +    netop.cmd = NETWORK_OP_VIFSETPARAMS;
   27.21 +    netop.u.vif_setparams.domain       = domid;
   27.22 +    netop.u.vif_setparams.vif          = vifid;
   27.23 +    netop.u.vif_setparams.credit_bytes = params->credit_bytes;
   27.24 +    netop.u.vif_setparams.credit_usec  = params->credit_usec;
   27.25 +    return do_network_op(xc_handle, &netop);
   27.26 +}
   27.27 +
   27.28 +
   27.29 +int xc_vif_scheduler_get(int xc_handle,
   27.30 +                         unsigned int domid, 
   27.31 +                         unsigned int vifid, 
   27.32 +                         xc_vif_sched_params_t *params)
   27.33 +{
   27.34 +    network_op_t  netop;
   27.35 +    int rc;
   27.36 +
   27.37 +    netop.cmd = NETWORK_OP_VIFGETINFO;
   27.38 +    netop.u.vif_getinfo.domain = domid;
   27.39 +    netop.u.vif_getinfo.vif    = vifid;
   27.40 +
   27.41 +    if ( (rc = do_network_op(xc_handle, &netop)) >= 0 )
   27.42 +    {
   27.43 +        params->credit_bytes = netop.u.vif_getinfo.credit_bytes;
   27.44 +        params->credit_usec  = netop.u.vif_getinfo.credit_usec;
   27.45 +    }
   27.46 +
   27.47 +    return rc;
   27.48 +}
   27.49 +
   27.50 +
   27.51 +int xc_vif_stats_get(int xc_handle,
   27.52 +                     unsigned int domid, 
   27.53 +                     unsigned int vifid, 
   27.54 +                     xc_vif_stats_t *stats)
   27.55 +{
   27.56 +    network_op_t  netop;
   27.57 +    int rc;
   27.58 +
   27.59 +    netop.cmd = NETWORK_OP_VIFGETINFO;
   27.60 +    netop.u.vif_getinfo.domain = domid;
   27.61 +    netop.u.vif_getinfo.vif    = vifid;
   27.62 +
   27.63 +    if ( (rc = do_network_op(xc_handle, &netop)) >= 0 )
   27.64 +    {
   27.65 +        stats->tx_bytes = netop.u.vif_getinfo.total_bytes_sent;
   27.66 +        stats->tx_pkts  = netop.u.vif_getinfo.total_packets_sent;
   27.67 +        stats->rx_bytes = netop.u.vif_getinfo.total_bytes_received;
   27.68 +        stats->rx_pkts  = netop.u.vif_getinfo.total_packets_received;
   27.69 +    }
   27.70 +
   27.71 +    return rc;
   27.72 +}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/tools/xc/lib/rpm.spec	Thu Nov 20 11:24:01 2003 +0000
    28.3 @@ -0,0 +1,28 @@
    28.4 +Summary: Xen control interface library
    28.5 +Name: xen-internal-library
    28.6 +Version: 1.2
    28.7 +Release: 1
    28.8 +License: Xen
    28.9 +Group: Xen
   28.10 +BuildRoot: %{staging}
   28.11 +%description
   28.12 +Library to make it easier to access the Xen control interfaces.
   28.13 +
   28.14 +%pre
   28.15 +%preun
   28.16 +%install
   28.17 +install -m 0755 -d $RPM_BUILD_ROOT/lib
   28.18 +install -m 0755 libxc.a $RPM_BUILD_ROOT/lib/libxc.a
   28.19 +install -m 0755 libxc.so $RPM_BUILD_ROOT/lib/libxc.so
   28.20 +install -m 0755 -d $RPM_BUILD_ROOT/include
   28.21 +install -m 0644 xc.h $RPM_BUILD_ROOT/include/xc.h
   28.22 +%clean
   28.23 +%post
   28.24 +%postun
   28.25 +%files
   28.26 +%defattr(-,root,root)
   28.27 +%dir /lib
   28.28 +/lib/libxc.a
   28.29 +/lib/libxc.so
   28.30 +%dir /include
   28.31 +/include/xc.h
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/tools/xc/lib/xc.h	Thu Nov 20 11:24:01 2003 +0000
    29.3 @@ -0,0 +1,127 @@
    29.4 +/******************************************************************************
    29.5 + * xc.h
    29.6 + * 
    29.7 + * A library for low-level access to the Xen control interfaces.
    29.8 + * 
    29.9 + * Copyright (c) 2003, K A Fraser.
   29.10 + */
   29.11 +
   29.12 +#ifndef __XC_H__
   29.13 +#define __XC_H__
   29.14 +
   29.15 +/* Obtain or relinquish a handle on the 'xc' library. */
   29.16 +int xc_interface_open(void);
   29.17 +int xc_interface_close(int xc_handle);
   29.18 +
   29.19 +typedef struct {
   29.20 +    unsigned int  domid;
   29.21 +    unsigned int  cpu;
   29.22 +    int           has_cpu;
   29.23 +    int           stopped;
   29.24 +    unsigned long nr_pages;
   29.25 +    unsigned long long cpu_time;
   29.26 +#define XC_DOMINFO_MAXNAME 16
   29.27 +    char          name[XC_DOMINFO_MAXNAME];
   29.28 +} xc_dominfo_t;
   29.29 +
   29.30 +int xc_domain_create(int xc_handle, 
   29.31 +                     unsigned int mem_kb, 
   29.32 +                     const char *name);
   29.33 +int xc_domain_start(int xc_handle, 
   29.34 +                    unsigned int domid);
   29.35 +int xc_domain_stop(int xc_handle, 
   29.36 +                   unsigned int domid);
   29.37 +int xc_domain_destroy(int xc_handle, 
   29.38 +                      unsigned int domid, 
   29.39 +                      int force);
   29.40 +int xc_domain_getinfo(int xc_handle,
   29.41 +                      unsigned int first_domid, 
   29.42 +                      unsigned int max_doms,
   29.43 +                      xc_dominfo_t *info);
   29.44 +
   29.45 +int xc_linux_save(int xc_handle,
   29.46 +                  unsigned int domid, 
   29.47 +                  const char *state_file, 
   29.48 +                  int verbose);
   29.49 +int xc_linux_restore(int xc_handle,
   29.50 +                     const char *state_file, int verbose);
   29.51 +int xc_linux_build(int xc_handle,
   29.52 +                   unsigned int domid,
   29.53 +                   const char *image_name,
   29.54 +                   const char *ramdisk_name,
   29.55 +                   const char *cmdline);
   29.56 +
   29.57 +int xc_bvtsched_global_set(int xc_handle,
   29.58 +                           unsigned long ctx_allow);
   29.59 +int xc_bvtsched_domain_set(int xc_handle,
   29.60 +                           unsigned int domid,
   29.61 +                           unsigned long mcuadv,
   29.62 +                           unsigned long warp,
   29.63 +                           unsigned long warpl,
   29.64 +                           unsigned long warpu);
   29.65 +
   29.66 +typedef struct {
   29.67 +    unsigned long credit_bytes;
   29.68 +    unsigned long credit_usec;
   29.69 +} xc_vif_sched_params_t;
   29.70 +
   29.71 +typedef struct {
   29.72 +    unsigned long long tx_bytes, tx_pkts;
   29.73 +    unsigned long long rx_bytes, rx_pkts;
   29.74 +} xc_vif_stats_t;
   29.75 +
   29.76 +int xc_vif_scheduler_set(int xc_handle,
   29.77 +                         unsigned int domid, 
   29.78 +                         unsigned int vifid,
   29.79 +                         xc_vif_sched_params_t *params);
   29.80 +int xc_vif_scheduler_get(int xc_handle,
   29.81 +                         unsigned int domid, 
   29.82 +                         unsigned int vifid,
   29.83 +                         xc_vif_sched_params_t *params);
   29.84 +int xc_vif_stats_get(int xc_handle,
   29.85 +                     unsigned int domid, 
   29.86 +                     unsigned int vifid,
   29.87 +                     xc_vif_stats_t *stats);
   29.88 +
   29.89 +typedef struct {
   29.90 +#define XC_VBDDOM_PROBE_ALL (~0U)
   29.91 +    unsigned int   domid;
   29.92 +    unsigned short vbdid;
   29.93 +#define XC_VBDF_WRITEABLE (1<<0)
   29.94 +    unsigned long  flags;
   29.95 +    unsigned long  nr_sectors;
   29.96 +} xc_vbd_t;
   29.97 +
   29.98 +
   29.99 +int xc_vbd_create(int xc_handle,
  29.100 +                  unsigned int domid, 
  29.101 +                  unsigned short vbdid, 
  29.102 +                  int writeable);
  29.103 +int xc_vbd_destroy(int xc_handle,
  29.104 +                   unsigned int domid, 
  29.105 +                   unsigned short vbdid);
  29.106 +int xc_vbd_add_extent(int xc_handle,
  29.107 +                      unsigned int domid, 
  29.108 +                      unsigned short vbdid,
  29.109 +                      unsigned short real_device,
  29.110 +                      unsigned long start_sector,
  29.111 +                      unsigned long nr_sectors);
  29.112 +int xc_vbd_delete_extent(int xc_handle,
  29.113 +                         unsigned int domid, 
  29.114 +                         unsigned short vbdid,
  29.115 +                         unsigned short real_device,
  29.116 +                         unsigned long start_sector,
  29.117 +                         unsigned long nr_sectors);
  29.118 +int xc_vbd_probe(int xc_handle,
  29.119 +                 unsigned int domid,
  29.120 +                 unsigned short vbdid,
  29.121 +                 unsigned int max_vbds,
  29.122 +                 xc_vbd_t *vbds);
  29.123 +
  29.124 +int xc_readconsolering(int xc_handle,
  29.125 +                       char *str, 
  29.126 +                       unsigned int max_chars, 
  29.127 +                       int clear);
  29.128 +
  29.129 +
  29.130 +#endif /* __XC_H__ */