WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-ppc-devel

[XenPPC][Patch] xc_ppc_linux_save.c xc_ppc_linux_restore.c

To: XenPPC-devel <xen-ppc-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [XenPPC][Patch] xc_ppc_linux_save.c xc_ppc_linux_restore.c
From: geyi <kudva@xxxxxxxxxxxxxx>
Date: Wed, 01 Nov 2006 17:07:58 -0500
Delivery-date: Thu, 02 Nov 2006 13:40:42 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-ppc-devel-request@lists.xensource.com?subject=help>
List-id: Xen PPC development <xen-ppc-devel.lists.xensource.com>
List-post: <mailto:xen-ppc-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ppc-devel>, <mailto:xen-ppc-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ppc-devel>, <mailto:xen-ppc-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-ppc-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 1.5.0.7 (Windows/20060909)
These two files need to be put under tools/libxc/powerpc64 .
/******************************************************************************
 * xc_ppc_linux_save.c
 *
 * Save the state of a running Linux session.
 *
 * Copyright (c) 2003, K A Fraser.
 *  Rewritten for ppc
 */

#include <inttypes.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include "htab.h"

#include "xg_private.h"

/*
** Default values for important tuning parameters. Can override by passing
** non-zero replacement values to xc_linux_save().
**
** XXX SMH: should consider if want to be able to override MAX_MBIT_RATE too.
**
*/
#define DEF_MAX_ITERS    (4 - 1)        /* limit us to 4 times round loop  */
#define DEF_MAX_FACTOR   3              /* never send more than 3x nr_pfns */

/*
** During (live) save/migrate, we maintain a number of bitmaps to track
** which pages we have to send, and to skip.
*/

#define DECOR 0x80000000                // indicates htab address
//#define DECOR 0x400000                // indicates htab address
#define LOG_PTE_SIZE            4

#define INVALID_MFN       (~0ULL)

#define BITS_PER_LONG (sizeof(unsigned long) * 8)

#define BITMAP_ENTRY(_nr,_bmap) \
   ((unsigned long *)(_bmap))[(_nr)/BITS_PER_LONG]

#define BITMAP_SHIFT(_nr) ((_nr) % BITS_PER_LONG)

static inline int test_bit (int nr, volatile void * addr)
{
    return (BITMAP_ENTRY(nr, addr) >> BITMAP_SHIFT(nr)) & 1;
}

static inline void clear_bit (int nr, volatile void * addr)
{
    BITMAP_ENTRY(nr, addr) &= ~(1UL << BITMAP_SHIFT(nr));
}

static inline void set_bit ( int nr, volatile void * addr)
{
    BITMAP_ENTRY(nr, addr) |= (1UL << BITMAP_SHIFT(nr));
}

/* total number of pages used by the current guest */
static unsigned long max_pfn;


static int
suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
                  int dom, xc_dominfo_t *info)
{
    int i = 0;

    DPRINTF("suspend_and_state()\n");
    if (!(*suspend)(dom)) {
        ERROR("Suspend request failed");
        return -1;
    }

retry:
    if (xc_domain_getinfo(xc_handle, dom, 1, info) != 1) {
        ERROR("Could not get domain info");
        return -1;
    }

    if (info->shutdown && info->shutdown_reason == SHUTDOWN_suspend)
        return 0; // success

    if (info->paused) {
        // try unpausing domain, wait, and retest
        xc_domain_unpause(xc_handle, dom);

        ERROR("Domain was paused. Wait and re-test.");
        usleep(10000);  // 10ms

        goto retry;
    }


    if(++i < 100) {
        ERROR("Retry suspend domain.");
        usleep(10000);  // 10ms
        goto retry;
    }

    ERROR("Unable to suspend domain.");

    return -1;
}

static inline ssize_t
write_exact(int fd, void *buf, size_t count)
{
    if (write(fd, buf, count) != count)
        return 0;
    return 1;
}

int
xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
              uint32_t max_factor, uint32_t flags, int (*suspend)(int))
{
    DECLARE_DOMCTL;
    xc_dominfo_t info;

    int rc = 1;
    int debug = 0;

    /* The new domain's shared-info frame number. */
    unsigned long shared_info_frame;

    /* A copy of the CPU context of the guest. */
    vcpu_guest_context_t ctxt;

    xen_pfn_t *page_array = NULL;

    /* Live mapping of shared info structure */
    shared_info_t *live_shinfo = NULL;


    DPRINTF("xc_linux_save (ppc): started dom=%d\n", dom);

    if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) {
        ERROR("Could not get domain info");
        return 1;
    }

    shared_info_frame = info.shared_info_frame;

    /* Map the shared info frame */
    live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
                                       PROT_READ, shared_info_frame);
    if (!live_shinfo) {
        ERROR("Couldn't map live_shinfo");
        goto out;
    }

    max_pfn = info.max_memkb >> (PAGE_SHIFT - 10);

    DPRINTF("max_pfn: 0x%08lx\n", max_pfn);

    page_array = malloc(max_pfn * sizeof(xen_pfn_t));
    if (page_array == NULL) {
        ERROR("Could not allocate memory");
        goto out;
    }

    /* This is expected by xm restore.  */
    if (!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) {
        ERROR("write: max_pfn");
        goto out;
    }

    /* xc_linux_restore starts to read here.  */
    /* Write a version number.  This can avoid searching for a stupid bug
       if the format change.
       The version is hard-coded, don't forget to change the restore code
       too!  */
    {
        unsigned long version = 1;

        if (!write_exact(io_fd, &version, sizeof(unsigned long))) {
            ERROR("write: version");
            goto out;
        }
    }

#if 0
    domctl.cmd = XEN_DOMCTL_arch_setup;
    domctl.domain = (domid_t)dom;
    domctl.u.arch_setup.flags = XEN_DOMAINSETUP_query;
    if (xc_domctl(xc_handle, &domctl) < 0) {
        ERROR("Could not get domain setup");
        goto out;
    }
    if (!write_exact(io_fd, &domctl.u.arch_setup,
                     sizeof(domctl.u.arch_setup))) {
        ERROR("write: domain setup");
        goto out;
    }
#endif
    
    /* This is a non-live suspend. Issue the call back to get the
       domain suspended */
    
    if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info)) {
        ERROR("Domain appears not to have suspended");
        goto out;
    }
    

    {
        char *mem;
        xen_pfn_t pfn;
        unsigned int total_sent = 0;

        if (xc_get_pfn_list(xc_handle, dom, 
                            page_array, max_pfn) != max_pfn) {
            ERROR("Could not get the page frame list");
            goto out;
        }

        /* Start writing out the saved-domain record. */
        for (pfn = 0; pfn < max_pfn; pfn++){
     //   for (pfn = 0; pfn < 16; pfn++){
            if (page_array[pfn] == INVALID_MFN)
                continue;

            if (debug)
                fprintf(stderr, "xc_linux_save: page %llx (%llu/%lu)\n",
                        page_array[pfn], pfn, max_pfn);

      //          DPRINTF( "xc_linux_save: page %llx (%llu/%lu)\n",
       //                 page_array[pfn], pfn, max_pfn);
            mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
                                       PROT_READ|PROT_WRITE, page_array[pfn]);
            if (mem == NULL) {
                /* The page may have move.
                   It will be remarked dirty.
                   FIXME: to be tracked.  */
                fprintf(stderr, "cannot map page %llx: %s\n",
                        page_array[pfn], strerror (errno));
                continue;
            }
            else 
            {
                if (pfn <8)
                        DPRINTF("memory addres %lx \n", (ulong)mem);
            }

            if (!write_exact(io_fd, &pfn, sizeof(pfn))) {
                ERROR("Error when writing to state file (4)");
                goto out;
            }

            if (write(io_fd, mem, PAGE_SIZE) != PAGE_SIZE) {
                ERROR("Error when writing to state file (5)");
                goto out;
            }
            munmap(mem, PAGE_SIZE);
            total_sent++;
        }

        DPRINTF("total_sent: %d\n", total_sent);
    }

    fprintf (stderr, "All memory is saved\n");

    /* terminate memory dump */
    {
        xen_pfn_t pfn = INVALID_MFN;
        if (!write_exact(io_fd, &pfn, sizeof(pfn))) {
            ERROR("Error when writing to state file (6)");
            goto out;
        }
    }
    
    {
        int i, k, num_ptes;
        char *mem, *temp, *copy;
        unsigned long N;
        unsigned int total_sent = 0;
        uint64_t htab_raddr;
        ulong htab_mfn, htab_pages;
        xen_pfn_t htab_rpn;
        union pte *ppte;

        num_ptes = xc_get_shadow_list(xc_handle, dom, &htab_raddr);
        if (num_ptes == -1){ 
            ERROR("Could not get the shadow list");
            goto out;
        }

        temp = malloc(PAGE_SIZE * 2);
        if (temp == NULL){
            ERROR("Could not allocate temp memory");
            goto out;
        }

        copy = (char *)(((ulong)temp + (PAGE_SIZE - 1)) & (~(PAGE_SIZE-1)));

        htab_mfn = htab_raddr >> PAGE_SHIFT;
        htab_pages = num_ptes / (PAGE_SIZE / (1UL << LOG_PTE_SIZE));
   //     DPRINTF("htab_pages: 0x%08lx htab_addr: %llx  htab_mfn %lx\n", 
htab_pages,htab_raddr, htab_mfn);

        if (!write_exact(io_fd, &num_ptes, sizeof(num_ptes))) {
            ERROR("Error when writing to state file (4)");
            goto out;
        }
        /* Replace rpn with guest pfn, then write out htab, by page */
        for (N = 0; N < htab_pages;  N++, htab_mfn++) {
            mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
                                       PROT_READ|PROT_WRITE, htab_mfn | DECOR);
            if (mem == NULL){
                ERROR("Cannot map htab_mfn 0x%08lx: %s\n", 
                    htab_mfn, strerror (errno));
                goto out;
            }
            //else DPRINTF("success map htab to guest: %lx \n", (unsigned 
long)mem);

             memcpy(copy, mem, PAGE_SIZE);
            /*** TBD - improve search of page_array[] for htab_rpn ***/
            ppte = (union pte *)copy;
            for (i = 0; i < (PAGE_SIZE / (1UL << LOG_PTE_SIZE)); i++, ppte++){
//      DPRINTF(" htab : i %d, ppte->vsid  %llx, rpn %llx \n", i , (unsigned 
long long)ppte->words.vsid, (unsigned long long)ppte->words.rpn);
                if (ppte->bits.v == 1){         // valid htab entry
                    htab_rpn = ppte->bits.rpn;
                    for (k = 0; k < max_pfn; k++){
                        if (htab_rpn == page_array[k])
                            break;
                    }

                    if (k >= max_pfn){
                        ERROR("htab_rpn: 0x%016llx not found in page_array[] 
%d",
                            htab_rpn, i);
                        ppte->bits.v = 0;
                         goto out;
                    }

                    ppte->bits.rpn = k;
                } else {                                                        
// invalid htab entry
                    ppte->words.rpn = 0;
                }
            }

            if (write(io_fd, copy, PAGE_SIZE) != PAGE_SIZE) {
                ERROR("Error when writing to state file (7)");
                goto out;
            }
            munmap(mem, PAGE_SIZE);
            total_sent++;
        }

        free(temp);

        DPRINTF("htab_sent: %d\n", total_sent);
    }
#if 0
    /* terminate htab dump*/
    {
        xen_pfn_t pfn = INVALID_MFN;
        if (!write_exact(io_fd, &pfn, sizeof(pfn))) {
            ERROR("Error when writing to state file (8)");
            goto out;
        }
    }
#endif
    /*** TBD - save vcpu context for all vcpus ***/
    if (xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt)) {
        ERROR("Could not get vcpu context");
        goto out;
    }

    if (!write_exact(io_fd, &ctxt, sizeof(ctxt))) {
        ERROR("Error when writing to state file (1)");
        goto out;
    }

#if 0
    mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
                               PROT_READ|PROT_WRITE, ctxt.privregs_pfn);
    if (mem == NULL) {
        ERROR("cannot map privreg page");
        goto out;
    }
    if (write(io_fd, mem, PAGE_SIZE) != PAGE_SIZE) {
        ERROR("Error when writing privreg to state file (5)");
        goto out;
    }
    munmap(mem, PAGE_SIZE);    
#endif

    if (!write_exact(io_fd, live_shinfo, PAGE_SIZE)) {
        ERROR("Error when writing to state file (1)");
        goto out;
    }

    /* Success! */
    rc = 0;


    DPRINTF("Domain ready to be built.\n");

    domctl.cmd = XEN_DOMCTL_setvcpucontext;
    domctl.domain = (domid_t)dom;
    domctl.u.vcpucontext.vcpu   = 0;
    set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt);
    rc = xc_domctl(xc_handle, &domctl);

    if (rc != 0) {
        ERROR("Couldn't build the domain");
        goto out;
    }

 out:

    free(page_array);
    if (live_shinfo)
        munmap(live_shinfo, PAGE_SIZE);

    DPRINTF("Save exit rc=%d\n",rc);

    return !!rc;
}

/*
 * Local variables:
 * mode: C
 * c-set-style: "BSD"
 * c-basic-offset: 4
 * tab-width: 4
 * indent-tabs-mode: nil
 * End:
 */
/******************************************************************************
 * xc_ppc_linux_restore.c
 *
 * Restore the state of a Linux session.
 *
 * Copyright (c) 2003, K A Fraser.
 *  Rewritten for ppc
 */

#include <inttypes.h>
#include <stdlib.h>
#include <unistd.h>
#include "htab.h"

#include "xg_private.h"

#define DECOR 0x80000000                // indicates htab address
#define LOG_PTE_SIZE            4

#define INVALID_MFN       (~0ULL)

#define PFN_TO_KB(_pfn) ((_pfn) << (PAGE_SHIFT - 10))

//*** static unsigned char pg_buf[PAGE_SIZE];

/* total number of pages used by the current guest */
static unsigned long max_pfn;

static ssize_t
read_exact(int fd, void *buf, size_t count)
{
    int r = 0, s;
    unsigned char *b = buf;

    while (r < count) {
        s = read(fd, &b[r], count - r);
        if ((s == -1) && (errno == EINTR))
            continue;
        if (s <= 0) {
            break;
        }
        r += s;
    }

    return (r == count) ? 1 : 0;
}

static int
read_page(int xc_handle, int io_fd, uint32_t dom, xen_pfn_t mfn)
{
    void *mem;

    mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
                               PROT_READ|PROT_WRITE, mfn);
    if (mem == NULL) {
            ERROR("cannot map page");
            return -1;
    }
    if (!read_exact(io_fd, mem, PAGE_SIZE)) {
            ERROR("Error when reading from state file (5)");
            return -1;
    }
    munmap(mem, PAGE_SIZE);
    return 0;
}

int
xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
                 unsigned long nr_pfns, unsigned int store_evtchn,
                 unsigned long *store_mfn, unsigned int console_evtchn,
                 unsigned long *console_mfn)
{
    DECLARE_DOMCTL;
    int rc = 1, i;
    xen_pfn_t mfn = INVALID_MFN, pfn;
    unsigned long ver;
    int prntctr = 0;
    
    /* The new domain's shared-info frame number. */
    unsigned long shared_info_frame;
    unsigned char shared_info_page[PAGE_SIZE]; /* saved contents from file */
    shared_info_t *shared_info = (shared_info_t *)shared_info_page;

    /* A copy of the CPU context of the guest. */
    vcpu_guest_context_t ctxt;

    xen_pfn_t shared_info_pfn, *page_array = NULL;

    /* A temporary mapping of the guest's start_info page. */
    start_info_t *start_info;

    max_pfn = nr_pfns;

    DPRINTF("xc_linux_restore start: max_pfn = %ld\n", max_pfn);

    if (!read_exact(io_fd, &ver, sizeof(unsigned long))) {
        ERROR("Error when reading version");
        goto out;
    }
    if (ver != 1) {
        ERROR("version of save doesn't match");
        goto out;
    }

    if (mlock(&ctxt, sizeof(ctxt))) {
        /* needed for build domctl, but might as well do early */
        ERROR("Unable to mlock ctxt");
        return 1;
    }

    /* Get the domain's shared-info frame. */
    domctl.cmd = XEN_DOMCTL_getdomaininfo;
    domctl.domain = (domid_t)dom;
    if (xc_domctl(xc_handle, &domctl) < 0) {
        ERROR("Could not get information on new domain");
        goto out;
    }
    shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;

    if (xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(max_pfn)) != 0) {
        errno = ENOMEM;
        goto out;
    }

#if 0
    if (xc_domain_memory_increase_reservation(xc_handle, dom, max_pfn,
                                              0, 0, NULL) != 0) {
        ERROR("Failed to increase reservation by %ld KB", PFN_TO_KB(max_pfn));
        errno = ENOMEM;
        goto out;
    }

    DPRINTF("Increased domain reservation by %ld KB\n", PFN_TO_KB(max_pfn));
#endif

#if 0
    if (!read_exact(io_fd, &domctl.u.arch_setup, sizeof(domctl.u.arch_setup))) {
        ERROR("read: domain setup");
        goto out;
    }

    /* Build firmware (will be overwritten).  */
    domctl.domain = (domid_t)dom;
    domctl.u.arch_setup.flags &= ~XEN_DOMAINSETUP_query;
    domctl.u.arch_setup.bp = ((nr_pfns - 3) << PAGE_SHIFT)
                           + sizeof (start_info_t);
    domctl.u.arch_setup.maxmem = (nr_pfns - 3) << PAGE_SHIFT;
    
    domctl.cmd = XEN_DOMCTL_arch_setup;
    if (xc_domctl(xc_handle, &domctl))
        goto out;
#endif

    /* Get pages.  */
    page_array = malloc(max_pfn * sizeof(xen_pfn_t));
    if (page_array == NULL ) {
        ERROR("Could not allocate memory");
        goto out;
    }

    if (xc_get_pfn_list(xc_handle, dom, 
                            page_array, max_pfn) != max_pfn) {
        ERROR("Could not get the page frame list");
        goto out;
    }

    DPRINTF("Reloading memory pages:   0%%\n");

    while (1) {
        if (!read_exact(io_fd, &pfn, sizeof(xen_pfn_t))) {
            ERROR("Error when reading batch size");
            goto out;
        }
        if (pfn == INVALID_MFN)
                break;

        if (pfn > max_pfn){
            DPRINTF("pfn: 0x%016llx\n", pfn);
            continue;
        }

        mfn = page_array[pfn];

        if (prntctr++ < 8)
            DPRINTF("xc_linux_restore: page %llu/%lu at %llx\n", pfn, max_pfn, 
mfn);

#if 0
        if (!read_exact(io_fd, pg_buf, PAGE_SIZE)) {    //***
            ERROR("Error when reading batch size");
            goto out;
        }
#endif

        if (read_page(xc_handle, io_fd, dom, mfn) < 0)
                goto out;
    }

    DPRINTF("Received all pages\n");

    {
        int i, num_ptes, htab_ptes;
        uint64_t htab_raddr;
        ulong htab_mfn, htab_pages;
        unsigned long N;
        char *mem, *temp, *copy;
        unsigned int total_sent = 0;
        xen_pfn_t htab_rpn;
        union pte *ppte;

        htab_ptes = xc_get_shadow_list(xc_handle, dom, &htab_raddr);
        if (htab_ptes == -1){ 
            ERROR("Could not get the shadow list");
            goto out;
        }
        
        if (!read_exact(io_fd, &num_ptes, sizeof(num_ptes))) {
            ERROR("Error when reading num_ptes");
            goto out;
        }

        if (num_ptes != htab_ptes){
            ERROR("num_ptes != htab_ptes:  %d  %d   htab_raddr: 0x%016llx",
                num_ptes, htab_ptes, htab_raddr);
            goto out;
        }

        temp = malloc(PAGE_SIZE * 2);
        if (temp == NULL){
            ERROR("Could not allocate temp memory");
            goto out;
        }

        copy = (char *)(((ulong)temp + (PAGE_SIZE - 1)) & (~(PAGE_SIZE-1)));

        htab_mfn = htab_raddr >> PAGE_SHIFT;
        htab_pages = htab_ptes / (PAGE_SIZE / (1UL << LOG_PTE_SIZE));
        //DPRINTF("htab_pages: 0x%08lx\n", htab_pages);
        //DPRINTF("htab_mfn: 0x%08lx\n", htab_mfn);

        /* Replace guest pfn with rfn, then copy to htab, by page */
        for (N = 0; N < htab_pages;  N++, htab_mfn++) {
            mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
                                       PROT_READ|PROT_WRITE, htab_mfn | DECOR);
            if (mem == NULL){
                ERROR("Cannot map htab_mfn 0x%08lx: %s\n", 
                    htab_mfn, strerror (errno));
                goto out;
            }

            if (!read_exact(io_fd, copy, PAGE_SIZE)) {
                ERROR("Error when reading htab page");
                goto out;
            }

            ppte = (union pte *)copy;
            for (i = 0; i < (PAGE_SIZE / (1UL << LOG_PTE_SIZE)); i++, ppte++){
                if (ppte->bits.v == 1){                 // valid htab entry
                    htab_rpn = ppte->bits.rpn;          // guest's pfn

                    if (htab_rpn >= max_pfn){
                        ERROR("htab_rpn: 0x%016llx not found in page_array[]",
                            htab_rpn);
                        goto out;
                    }

                    ppte->bits.rpn = page_array[htab_rpn]; // guest's rpn

                } else {                                // invalid htab entry
                    ppte->words.rpn = 0;
                }
            }

            memcpy(mem, copy, PAGE_SIZE);

            munmap(mem, PAGE_SIZE);
            total_sent++;
        }

        free(temp);

        DPRINTF("htab_get: %d\n", total_sent);
    }


    if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) {
        ERROR("Error when reading ctxt");
        goto out;
    }


    /* First to initialize.  */
    domctl.cmd = XEN_DOMCTL_setvcpucontext;
    domctl.domain = (domid_t)dom;
    domctl.u.vcpucontext.vcpu   = 0;
    set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt);
    if (xc_domctl(xc_handle, &domctl) != 0) {
            ERROR("Couldn't set vcpu context");
            goto out;
    }
    
//    DPRINTF("MSR saved %llx \n",(unsigned long long)ctxt.user_regs.msr);
#if 0
    /* Second to set registers...  */
//***    ctxt.flags = VGCF_EXTRA_REGS;
    domctl.cmd = XEN_DOMCTL_setvcpucontext;
    domctl.domain = (domid_t)dom;
    domctl.u.vcpucontext.vcpu   = 0;
    set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt);
    if (xc_domctl(xc_handle, &domctl) != 0) {
            ERROR("Couldn't set vcpu context");
            goto out;
    }
#endif

    /* Just a check.  */
    if (xc_vcpu_getcontext(xc_handle, dom, 0 /* XXX */, &ctxt)) {
        ERROR("Could not get vcpu context");
        goto out;
    }

#if 0
    /* Then get privreg page.  */
    if (read_page(xc_handle, io_fd, dom, ctxt.privregs_pfn) < 0) {
            ERROR("Could not read vcpu privregs");
            goto out;
    }
#endif

    /* Read shared info.  */
    shared_info = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
                                       PROT_READ|PROT_WRITE, shared_info_frame);
    if (shared_info == NULL) {
            ERROR("cannot map page");
            goto out;
    }
    if (!read_exact(io_fd, shared_info, PAGE_SIZE)) {
            ERROR("Error when reading shared_info page");
            goto out;
    }

    /* clear any pending events and the selector */
    memset(&(shared_info->evtchn_pending[0]), 0,
           sizeof (shared_info->evtchn_pending));
    for (i = 0; i < MAX_VIRT_CPUS; i++)
        shared_info->vcpu_info[i].evtchn_pending_sel = 0;


#if 1
    mfn = shared_info_frame - 3 ;       
//    mfn = page_array[shared_info->arch.start_info_pfn];
    DPRINTF("start_info mfn %llx \n", (unsigned long long)  mfn);
#endif

    munmap (shared_info, PAGE_SIZE);

    for (i=0;i<max_pfn;i++) 
        if (page_array[i] == shared_info_frame) break;
    if ( i >= max_pfn)  
    {
        ERROR();
        goto out;
    }
    shared_info_pfn = (unsigned long) i;

 //    rc = 0; goto out;        //***

    /* Uncanonicalise the suspend-record frame number and poke resume rec. */
    start_info = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
                                      PROT_READ | PROT_WRITE, mfn);
    start_info->nr_pages = max_pfn;
 //   DPRINTF("shared_info_mfn %llx \n", (unsigned long long)(shared_info_pfn 
<< PAGE_SHIFT));
   // DPRINTF("start_info->shared_info%llx \n", (unsigned long 
long)start_info->shared_info);
    start_info->shared_info =  shared_info_pfn << PAGE_SHIFT;
    start_info->flags = 0;
    *store_mfn = page_array[start_info->store_mfn];
    start_info->store_evtchn = store_evtchn;
    *console_mfn = page_array[start_info->console.domU.mfn];
    start_info->console.domU.evtchn = console_evtchn;
    munmap(start_info, PAGE_SIZE);


    /*
     * Safety checking of saved context:
     *  1. user_regs is fine, as Xen checks that on context switch.
     *  2. fpu_ctxt is fine, as it can't hurt Xen.
     *  3. trap_ctxt needs the code selectors checked.
     *  4. ldt base must be page-aligned, no more than 8192 ents, ...
     *  5. gdt already done, and further checking is done by Xen.
     *  6. check that kernel_ss is safe.
     *  7. pt_base is already done.
     *  8. debugregs are checked by Xen.
     *  9. callback code selectors need checking.
     */
    DPRINTF("Domain ready to be built.\n");

    rc = 0;

 out:
    if ((rc != 0) && (dom != 0))
        xc_domain_destroy(xc_handle, dom);
#if 0
    else
    {
        DPRINTF("Domain puased: ");
        xc_domain_pause(xc_handle,dom);
        DPRINTF("Domain unpuased: ");
        xc_domain_unpause(xc_handle,dom);
    }

#endif
    free (page_array);

    DPRINTF("Restore exit with rc=%d\n", rc);

    return rc;
}
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel
<Prev in Thread] Current Thread [Next in Thread>
  • [XenPPC][Patch] xc_ppc_linux_save.c xc_ppc_linux_restore.c, geyi <=