direct-io.hg

changeset 13492:e2ca6bd16046

Merge with xen-ia64-unstable.hg
author kfraser@localhost.localdomain
date Thu Jan 18 18:25:04 2007 +0000 (2007-01-18)
parents 58637a0a7c7e 7c653e58cbe4
children 4f0a68df2585
files tools/ioemu/vl.c tools/python/xen/xend/XendRoot.py tools/python/xen/xend/image.py
line diff
     1.1 --- a/buildconfigs/linux-defconfig_xen0_x86_32	Wed Jan 17 21:45:34 2007 -0700
     1.2 +++ b/buildconfigs/linux-defconfig_xen0_x86_32	Thu Jan 18 18:25:04 2007 +0000
     1.3 @@ -548,7 +548,7 @@ CONFIG_MEGARAID_NEWGEN=y
     1.4  # CONFIG_MEGARAID_LEGACY is not set
     1.5  # CONFIG_MEGARAID_SAS is not set
     1.6  CONFIG_SCSI_SATA=y
     1.7 -# CONFIG_SCSI_SATA_AHCI is not set
     1.8 +CONFIG_SCSI_SATA_AHCI=y
     1.9  # CONFIG_SCSI_SATA_SVW is not set
    1.10  CONFIG_SCSI_ATA_PIIX=y
    1.11  # CONFIG_SCSI_SATA_MV is not set
    1.12 @@ -713,7 +713,7 @@ CONFIG_E1000=y
    1.13  CONFIG_SK98LIN=y
    1.14  # CONFIG_VIA_VELOCITY is not set
    1.15  CONFIG_TIGON3=y
    1.16 -# CONFIG_BNX2 is not set
    1.17 +CONFIG_BNX2=y
    1.18  
    1.19  #
    1.20  # Ethernet (10000 Mbit)
     2.1 --- a/buildconfigs/linux-defconfig_xen0_x86_64	Wed Jan 17 21:45:34 2007 -0700
     2.2 +++ b/buildconfigs/linux-defconfig_xen0_x86_64	Thu Jan 18 18:25:04 2007 +0000
     2.3 @@ -498,7 +498,7 @@ CONFIG_MEGARAID_NEWGEN=y
     2.4  # CONFIG_MEGARAID_LEGACY is not set
     2.5  # CONFIG_MEGARAID_SAS is not set
     2.6  CONFIG_SCSI_SATA=y
     2.7 -# CONFIG_SCSI_SATA_AHCI is not set
     2.8 +CONFIG_SCSI_SATA_AHCI=y
     2.9  # CONFIG_SCSI_SATA_SVW is not set
    2.10  CONFIG_SCSI_ATA_PIIX=y
    2.11  # CONFIG_SCSI_SATA_MV is not set
    2.12 @@ -663,7 +663,7 @@ CONFIG_E1000=y
    2.13  CONFIG_SK98LIN=y
    2.14  # CONFIG_VIA_VELOCITY is not set
    2.15  CONFIG_TIGON3=y
    2.16 -# CONFIG_BNX2 is not set
    2.17 +CONFIG_BNX2=y
    2.18  
    2.19  #
    2.20  # Ethernet (10000 Mbit)
     3.1 --- a/buildconfigs/mk.linux-2.6-xen	Wed Jan 17 21:45:34 2007 -0700
     3.2 +++ b/buildconfigs/mk.linux-2.6-xen	Thu Jan 18 18:25:04 2007 +0000
     3.3 @@ -9,6 +9,10 @@ LINUX_DIR    = build-linux-$(LINUX_VER)-
     3.4  IMAGE_TARGET ?= vmlinuz
     3.5  INSTALL_BOOT_PATH ?= $(DESTDIR)
     3.6  
     3.7 +ifeq ($(XEN_TARGET_ARCH),ia64)
     3.8 +INSTALL_BOOT_PATH := $(DESTDIR)/boot
     3.9 +endif
    3.10 +
    3.11  LINUX_VER3  := $(LINUX_SERIES).$(word 3, $(subst ., ,$(LINUX_VER)))
    3.12  
    3.13  include buildconfigs/Rules.mk
     4.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c	Wed Jan 17 21:45:34 2007 -0700
     4.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c	Thu Jan 18 18:25:04 2007 +0000
     4.3 @@ -56,7 +56,9 @@ static void *syscall_page;
     4.4  
     4.5  int __init sysenter_setup(void)
     4.6  {
     4.7 -	syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
     4.8 +	void *page = (void *)get_zeroed_page(GFP_ATOMIC);
     4.9 +
    4.10 +	syscall_page = page;
    4.11  
    4.12  #ifdef CONFIG_XEN
    4.13  	if (boot_cpu_has(X86_FEATURE_SEP)) {
    4.14 @@ -70,16 +72,16 @@ int __init sysenter_setup(void)
    4.15  	}
    4.16  #endif
    4.17  
    4.18 -	if (boot_cpu_has(X86_FEATURE_SEP)) {
    4.19 -		memcpy(syscall_page,
    4.20 -		       &vsyscall_sysenter_start,
    4.21 -		       &vsyscall_sysenter_end - &vsyscall_sysenter_start);
    4.22 +	if (!boot_cpu_has(X86_FEATURE_SEP)) {
    4.23 +		memcpy(page,
    4.24 +		       &vsyscall_int80_start,
    4.25 +		       &vsyscall_int80_end - &vsyscall_int80_start);
    4.26  		return 0;
    4.27  	}
    4.28  
    4.29 -	memcpy(syscall_page,
    4.30 -	       &vsyscall_int80_start,
    4.31 -	       &vsyscall_int80_end - &vsyscall_int80_start);
    4.32 +	memcpy(page,
    4.33 +	       &vsyscall_sysenter_start,
    4.34 +	       &vsyscall_sysenter_end - &vsyscall_sysenter_start);
    4.35  
    4.36  	return 0;
    4.37  }
     5.1 --- a/tools/ioemu/hw/cirrus_vga.c	Wed Jan 17 21:45:34 2007 -0700
     5.2 +++ b/tools/ioemu/hw/cirrus_vga.c	Thu Jan 18 18:25:04 2007 +0000
     5.3 @@ -3010,11 +3010,44 @@ static CPUWriteMemoryFunc *cirrus_mmio_w
     5.4      cirrus_mmio_writel,
     5.5  };
     5.6  
     5.7 +void cirrus_stop_acc(CirrusVGAState *s)
     5.8 +{
     5.9 +    if (s->map_addr){
    5.10 +        int error;
    5.11 +        s->map_addr = 0;
    5.12 +        error = unset_vram_mapping(s->cirrus_lfb_addr,
    5.13 +                s->cirrus_lfb_end);
    5.14 +        fprintf(stderr, "cirrus_stop_acc:unset_vram_mapping.\n");
    5.15 +
    5.16 +        munmap(s->vram_ptr, VGA_RAM_SIZE);
    5.17 +    }
    5.18 +}
    5.19 +
    5.20 +void cirrus_restart_acc(CirrusVGAState *s)
    5.21 +{
    5.22 +    if (s->cirrus_lfb_addr && s->cirrus_lfb_end) {
    5.23 +        void *vram_pointer, *old_vram;
    5.24 +        fprintf(stderr, "cirrus_vga_load:re-enable vga acc.lfb_addr=0x%lx, lfb_end=0x%lx.\n",
    5.25 +                s->cirrus_lfb_addr, s->cirrus_lfb_end);
    5.26 +        vram_pointer = set_vram_mapping(s->cirrus_lfb_addr ,s->cirrus_lfb_end);
    5.27 +        if (!vram_pointer){
    5.28 +            fprintf(stderr, "cirrus_vga_load:NULL vram_pointer\n");
    5.29 +        } else {
    5.30 +            old_vram = vga_update_vram((VGAState *)s, vram_pointer,
    5.31 +                    VGA_RAM_SIZE);
    5.32 +            qemu_free(old_vram);
    5.33 +            s->map_addr = s->cirrus_lfb_addr;
    5.34 +            s->map_end = s->cirrus_lfb_end;
    5.35 +        }
    5.36 +    }
    5.37 +}
    5.38 +
    5.39  /* load/save state */
    5.40  
    5.41  static void cirrus_vga_save(QEMUFile *f, void *opaque)
    5.42  {
    5.43      CirrusVGAState *s = opaque;
    5.44 +    uint8_t vga_acc;
    5.45  
    5.46      qemu_put_be32s(f, &s->latch);
    5.47      qemu_put_8s(f, &s->sr_index);
    5.48 @@ -3049,11 +3082,20 @@ static void cirrus_vga_save(QEMUFile *f,
    5.49      qemu_put_be32s(f, &s->hw_cursor_y);
    5.50      /* XXX: we do not save the bitblt state - we assume we do not save
    5.51         the state when the blitter is active */
    5.52 +
    5.53 +    vga_acc = (!!s->map_addr);
    5.54 +    qemu_put_8s(f, &vga_acc);
    5.55 +    qemu_put_be64s(f, (uint64_t*)&s->cirrus_lfb_addr);
    5.56 +    qemu_put_be64s(f, (uint64_t*)&s->cirrus_lfb_end);
    5.57 +    qemu_put_buffer(f, s->vram_ptr, VGA_RAM_SIZE); 
    5.58 +    if (vga_acc)
    5.59 +        cirrus_stop_acc(s);
    5.60  }
    5.61  
    5.62  static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
    5.63  {
    5.64      CirrusVGAState *s = opaque;
    5.65 +    uint8_t vga_acc = 0;
    5.66  
    5.67      if (version_id != 1)
    5.68          return -EINVAL;
    5.69 @@ -3092,6 +3134,14 @@ static int cirrus_vga_load(QEMUFile *f, 
    5.70      qemu_get_be32s(f, &s->hw_cursor_x);
    5.71      qemu_get_be32s(f, &s->hw_cursor_y);
    5.72  
    5.73 +    qemu_get_8s(f, &vga_acc);
    5.74 +    qemu_get_be64s(f, (uint64_t*)&s->cirrus_lfb_addr);
    5.75 +    qemu_get_be64s(f, (uint64_t*)&s->cirrus_lfb_end);
    5.76 +    qemu_get_buffer(f, s->vram_ptr, VGA_RAM_SIZE); 
    5.77 +    if (vga_acc){
    5.78 +        cirrus_restart_acc(s);
    5.79 +    }
    5.80 +
    5.81      /* force refresh */
    5.82      s->graphic_mode = -1;
    5.83      cirrus_update_bank_ptr(s, 0);
    5.84 @@ -3297,6 +3347,8 @@ void pci_cirrus_vga_init(PCIBus *bus, Di
    5.85                      ds, vga_ram_base, vga_ram_offset, vga_ram_size);
    5.86      cirrus_init_common(s, device_id, 1);
    5.87  
    5.88 +    register_savevm("cirrus_vga_pci", 0, 1, generic_pci_save, generic_pci_load, d);
    5.89 +
    5.90      /* setup memory space */
    5.91      /* memory #0 LFB */
    5.92      /* memory #1 memory-mapped I/O */
     6.1 --- a/tools/ioemu/hw/ide.c	Wed Jan 17 21:45:34 2007 -0700
     6.2 +++ b/tools/ioemu/hw/ide.c	Thu Jan 18 18:25:04 2007 +0000
     6.3 @@ -2512,6 +2512,9 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
     6.4                pic_set_irq_new, isa_pic, 15);
     6.5      ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
     6.6      ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
     6.7 +
     6.8 +    register_savevm("ide_pci", 0, 1, generic_pci_save, generic_pci_load, d);
     6.9 +
    6.10  #ifdef DMA_MULTI_THREAD    
    6.11      dma_create_thread();
    6.12  #endif //DMA_MULTI_THREAD    
     7.1 --- a/tools/ioemu/hw/pci.c	Wed Jan 17 21:45:34 2007 -0700
     7.2 +++ b/tools/ioemu/hw/pci.c	Thu Jan 18 18:25:04 2007 +0000
     7.3 @@ -40,6 +40,8 @@ target_phys_addr_t pci_mem_base;
     7.4  static int pci_irq_index;
     7.5  static PCIBus *first_bus;
     7.6  
     7.7 +static void pci_update_mappings(PCIDevice *d);
     7.8 +
     7.9  PCIBus *pci_register_bus(pci_set_irq_fn set_irq, void *pic, int devfn_min)
    7.10  {
    7.11      PCIBus *bus;
    7.12 @@ -71,6 +73,7 @@ int generic_pci_load(QEMUFile* f, void *
    7.13          return -EINVAL;
    7.14  
    7.15      qemu_get_buffer(f, s->config, 256);
    7.16 +    pci_update_mappings(s);
    7.17      return 0;
    7.18  }
    7.19  
     8.1 --- a/tools/ioemu/target-i386-dm/helper2.c	Wed Jan 17 21:45:34 2007 -0700
     8.2 +++ b/tools/ioemu/target-i386-dm/helper2.c	Thu Jan 18 18:25:04 2007 +0000
     8.3 @@ -546,6 +546,7 @@ int main_loop(void)
     8.4  {
     8.5      extern int vm_running;
     8.6      extern int shutdown_requested;
     8.7 +    extern int suspend_requested;
     8.8      CPUState *env = cpu_single_env;
     8.9      int evtchn_fd = xc_evtchn_fd(xce_handle);
    8.10  
    8.11 @@ -563,12 +564,24 @@ int main_loop(void)
    8.12                  qemu_system_reset();
    8.13                  reset_requested = 0;
    8.14              }
    8.15 +            if (suspend_requested) {
    8.16 +                fprintf(logfile, "device model received suspend signal!\n");
    8.17 +                break;
    8.18 +            }
    8.19          }
    8.20  
    8.21          /* Wait up to 10 msec. */
    8.22          main_loop_wait(10);
    8.23      }
    8.24 -    destroy_hvm_domain();
    8.25 +    if (!suspend_requested)
    8.26 +        destroy_hvm_domain();
    8.27 +    else {
    8.28 +        char qemu_file[20];
    8.29 +        sprintf(qemu_file, "/tmp/xen.qemu-dm.%d", domid);
    8.30 +        if (qemu_savevm(qemu_file) < 0)
    8.31 +            fprintf(stderr, "qemu save fail.\n");
    8.32 +    }
    8.33 +
    8.34      return 0;
    8.35  }
    8.36  
     9.1 --- a/tools/ioemu/vl.c	Wed Jan 17 21:45:34 2007 -0700
     9.2 +++ b/tools/ioemu/vl.c	Thu Jan 18 18:25:04 2007 +0000
     9.3 @@ -4441,6 +4441,11 @@ int qemu_loadvm(const char *filename)
     9.4          qemu_fseek(f, cur_pos + record_len, SEEK_SET);
     9.5      }
     9.6      fclose(f);
     9.7 +
     9.8 +    /* del tmp file */
     9.9 +    if (unlink(filename) == -1)
    9.10 +        fprintf(stderr, "delete tmp qemu state file failed.\n");
    9.11 +
    9.12      ret = 0;
    9.13   the_end:
    9.14      if (saved_vm_running)
    9.15 @@ -5027,6 +5032,7 @@ typedef struct QEMUResetEntry {
    9.16  static QEMUResetEntry *first_reset_entry;
    9.17  int reset_requested;
    9.18  int shutdown_requested;
    9.19 +int suspend_requested;
    9.20  static int powerdown_requested;
    9.21  
    9.22  void qemu_register_reset(QEMUResetHandler *func, void *opaque)
    9.23 @@ -5808,6 +5814,14 @@ int set_mm_mapping(int xc_handle, uint32
    9.24      return 0;
    9.25  }
    9.26  
    9.27 +void suspend(int sig)
    9.28 +{
    9.29 +   fprintf(logfile, "suspend sig handler called with requested=%d!\n", suspend_requested);
    9.30 +    if (sig != SIGUSR1)
    9.31 +        fprintf(logfile, "suspend signal dismatch, get sig=%d!\n", sig);
    9.32 +    suspend_requested = 1;
    9.33 +}
    9.34 +
    9.35  #if defined(__i386__) || defined(__x86_64__)
    9.36  static struct map_cache *mapcache_entry;
    9.37  static unsigned long nr_buckets;
    9.38 @@ -6714,6 +6728,26 @@ int main(int argc, char **argv)
    9.39              vm_start();
    9.40          }
    9.41      }
    9.42 +
    9.43 +    /* register signal for the suspend request when save */
    9.44 +    {
    9.45 +        struct sigaction act;
    9.46 +        sigset_t set;
    9.47 +        act.sa_handler = suspend;
    9.48 +        act.sa_flags = SA_RESTART;
    9.49 +        sigemptyset(&act.sa_mask);
    9.50 +
    9.51 +        sigaction(SIGUSR1, &act, NULL);
    9.52 +
    9.53 +        /* control panel mask some signals when spawn qemu, need unmask here*/
    9.54 +        sigemptyset(&set);
    9.55 +        sigaddset(&set, SIGUSR1);
    9.56 +        sigaddset(&set, SIGTERM);
    9.57 +        if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1)
    9.58 +            fprintf(stderr, "unblock signal fail, possible issue for HVM save!\n");
    9.59 +
    9.60 +    }
    9.61 +
    9.62      main_loop();
    9.63      quit_timers();
    9.64      return 0;
    10.1 --- a/tools/libfsimage/common/Makefile	Wed Jan 17 21:45:34 2007 -0700
    10.2 +++ b/tools/libfsimage/common/Makefile	Thu Jan 18 18:25:04 2007 +0000
    10.3 @@ -1,7 +1,7 @@
    10.4  XEN_ROOT = ../../..
    10.5  include $(XEN_ROOT)/tools/Rules.mk
    10.6  
    10.7 -MAJOR = 1.1
    10.8 +MAJOR = 1.0
    10.9  MINOR = 0
   10.10  
   10.11  CFLAGS += -Werror -Wp,-MD,.$(@F).d
    11.1 --- a/tools/libxc/Makefile	Wed Jan 17 21:45:34 2007 -0700
    11.2 +++ b/tools/libxc/Makefile	Thu Jan 18 18:25:04 2007 +0000
    11.3 @@ -27,7 +27,7 @@ GUEST_SRCS-y += xg_private.c
    11.4  GUEST_SRCS-$(CONFIG_X86) += xc_linux_build.c
    11.5  GUEST_SRCS-$(CONFIG_IA64) += xc_linux_build.c
    11.6  GUEST_SRCS-$(CONFIG_MIGRATE) += xc_linux_restore.c xc_linux_save.c
    11.7 -GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c
    11.8 +GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c xc_hvm_restore.c xc_hvm_save.c
    11.9  
   11.10  -include $(XEN_TARGET_ARCH)/Makefile
   11.11  
    12.1 --- a/tools/libxc/xc_domain.c	Wed Jan 17 21:45:34 2007 -0700
    12.2 +++ b/tools/libxc/xc_domain.c	Thu Jan 18 18:25:04 2007 +0000
    12.3 @@ -235,6 +235,50 @@ int xc_domain_getinfolist(int xc_handle,
    12.4      return ret;
    12.5  }
    12.6  
    12.7 +/* get info from hvm guest for save */
    12.8 +int xc_domain_hvm_getcontext(int xc_handle,
    12.9 +                             uint32_t domid,
   12.10 +                             hvm_domain_context_t *hvm_ctxt)
   12.11 +{
   12.12 +    int rc;
   12.13 +    DECLARE_DOMCTL;
   12.14 +
   12.15 +    domctl.cmd = XEN_DOMCTL_gethvmcontext;
   12.16 +    domctl.domain = (domid_t)domid;
   12.17 +    set_xen_guest_handle(domctl.u.hvmcontext.ctxt, hvm_ctxt);
   12.18 +
   12.19 +    if ( (rc = mlock(hvm_ctxt, sizeof(*hvm_ctxt))) != 0 )
   12.20 +        return rc;
   12.21 +
   12.22 +    rc = do_domctl(xc_handle, &domctl);
   12.23 +
   12.24 +    safe_munlock(hvm_ctxt, sizeof(*hvm_ctxt));
   12.25 +
   12.26 +    return rc;
   12.27 +}
   12.28 +
   12.29 +/* set info to hvm guest for restore */
   12.30 +int xc_domain_hvm_setcontext(int xc_handle,
   12.31 +                             uint32_t domid,
   12.32 +                             hvm_domain_context_t *hvm_ctxt)
   12.33 +{
   12.34 +    int rc;
   12.35 +    DECLARE_DOMCTL;
   12.36 +
   12.37 +    domctl.cmd = XEN_DOMCTL_sethvmcontext;
   12.38 +    domctl.domain = domid;
   12.39 +    set_xen_guest_handle(domctl.u.hvmcontext.ctxt, hvm_ctxt);
   12.40 +
   12.41 +    if ( (rc = mlock(hvm_ctxt, sizeof(*hvm_ctxt))) != 0 )
   12.42 +        return rc;
   12.43 +
   12.44 +    rc = do_domctl(xc_handle, &domctl);
   12.45 +
   12.46 +    safe_munlock(hvm_ctxt, sizeof(*hvm_ctxt));
   12.47 +
   12.48 +    return rc;
   12.49 +}
   12.50 +
   12.51  int xc_vcpu_getcontext(int xc_handle,
   12.52                                 uint32_t domid,
   12.53                                 uint32_t vcpu,
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/tools/libxc/xc_hvm_restore.c	Thu Jan 18 18:25:04 2007 +0000
    13.3 @@ -0,0 +1,360 @@
    13.4 +/******************************************************************************
    13.5 + * xc_hvm_restore.c
    13.6 + *
    13.7 + * Restore the state of a HVM guest.
    13.8 + *
    13.9 + * Copyright (c) 2003, K A Fraser.
   13.10 + * Copyright (c) 2006 Intel Corperation
   13.11 + * rewriten for hvm guest by Zhai Edwin <edwin.zhai@intel.com>
   13.12 + *
   13.13 + * This program is free software; you can redistribute it and/or modify it
   13.14 + * under the terms and conditions of the GNU General Public License,
   13.15 + * version 2, as published by the Free Software Foundation.
   13.16 + *
   13.17 + * This program is distributed in the hope it will be useful, but WITHOUT
   13.18 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.19 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   13.20 + * more details.
   13.21 + *
   13.22 + * You should have received a copy of the GNU General Public License along with
   13.23 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
   13.24 + * Place - Suite 330, Boston, MA 02111-1307 USA.
   13.25 + *
   13.26 + */
   13.27 +
   13.28 +#include <stdlib.h>
   13.29 +#include <unistd.h>
   13.30 +
   13.31 +#include "xg_private.h"
   13.32 +#include "xg_save_restore.h"
   13.33 +
   13.34 +#include <xen/hvm/ioreq.h>
   13.35 +#include <xen/hvm/params.h>
   13.36 +#include <xen/hvm/e820.h>
   13.37 +
   13.38 +/* max mfn of the whole machine */
   13.39 +static unsigned long max_mfn;
   13.40 +
   13.41 +/* virtual starting address of the hypervisor */
   13.42 +static unsigned long hvirt_start;
   13.43 +
   13.44 +/* #levels of page tables used by the currrent guest */
   13.45 +static unsigned int pt_levels;
   13.46 +
   13.47 +/* total number of pages used by the current guest */
   13.48 +static unsigned long max_pfn;
   13.49 +
   13.50 +/* A table mapping each PFN to its new MFN. */
   13.51 +static xen_pfn_t *p2m = NULL;
   13.52 +
   13.53 +static ssize_t
   13.54 +read_exact(int fd, void *buf, size_t count)
   13.55 +{
   13.56 +    int r = 0, s;
   13.57 +    unsigned char *b = buf;
   13.58 +
   13.59 +    while (r < count) {
   13.60 +        s = read(fd, &b[r], count - r);
   13.61 +        if ((s == -1) && (errno == EINTR))
   13.62 +            continue;
   13.63 +        if (s <= 0) {
   13.64 +            break;
   13.65 +        }
   13.66 +        r += s;
   13.67 +    }
   13.68 +
   13.69 +    return (r == count) ? 1 : 0;
   13.70 +}
   13.71 +
   13.72 +int xc_hvm_restore(int xc_handle, int io_fd,
   13.73 +                     uint32_t dom, unsigned long nr_pfns,
   13.74 +                     unsigned int store_evtchn, unsigned long *store_mfn,
   13.75 +                     unsigned int console_evtchn, unsigned long *console_mfn,
   13.76 +                     unsigned int pae, unsigned int apic)
   13.77 +{
   13.78 +    DECLARE_DOMCTL;
   13.79 +
   13.80 +    /* The new domain's shared-info frame number. */
   13.81 +    unsigned long shared_info_frame;
   13.82 +
   13.83 +    /* A copy of the CPU context of the guest. */
   13.84 +    vcpu_guest_context_t ctxt;
   13.85 +
   13.86 +    char *region_base;
   13.87 +
   13.88 +    unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
   13.89 +
   13.90 +    xc_dominfo_t info;
   13.91 +    unsigned int rc = 1, n, i;
   13.92 +    uint32_t rec_len, nr_vcpus;
   13.93 +    hvm_domain_context_t hvm_ctxt;
   13.94 +    unsigned long long v_end, memsize;
   13.95 +    unsigned long shared_page_nr;
   13.96 +
   13.97 +    unsigned long mfn, pfn;
   13.98 +    unsigned int prev_pc, this_pc;
   13.99 +    int verify = 0;
  13.100 +
  13.101 +    /* Types of the pfns in the current region */
  13.102 +    unsigned long region_pfn_type[MAX_BATCH_SIZE];
  13.103 +
  13.104 +    /* hvm guest mem size (Mb) */
  13.105 +    memsize = (unsigned long long)*store_mfn;
  13.106 +    v_end = memsize << 20;
  13.107 +
  13.108 +    DPRINTF("xc_hvm_restore:dom=%d, nr_pfns=0x%lx, store_evtchn=%d, *store_mfn=%ld, console_evtchn=%d, *console_mfn=%ld, pae=%u, apic=%u.\n", 
  13.109 +            dom, nr_pfns, store_evtchn, *store_mfn, console_evtchn, *console_mfn, pae, apic);
  13.110 +
  13.111 +    max_pfn = nr_pfns;
  13.112 +
  13.113 +    if(!get_platform_info(xc_handle, dom,
  13.114 +                          &max_mfn, &hvirt_start, &pt_levels)) {
  13.115 +        ERROR("Unable to get platform info.");
  13.116 +        return 1;
  13.117 +    }
  13.118 +
  13.119 +    DPRINTF("xc_hvm_restore start: max_pfn = %lx, max_mfn = %lx, hvirt_start=%lx, pt_levels=%d\n",
  13.120 +            max_pfn,
  13.121 +            max_mfn,
  13.122 +            hvirt_start,
  13.123 +            pt_levels);
  13.124 +
  13.125 +    if (mlock(&ctxt, sizeof(ctxt))) {
  13.126 +        /* needed for build dom0 op, but might as well do early */
  13.127 +        ERROR("Unable to mlock ctxt");
  13.128 +        return 1;
  13.129 +    }
  13.130 +
  13.131 +
  13.132 +    p2m        = malloc(max_pfn * sizeof(xen_pfn_t));
  13.133 +
  13.134 +    if (p2m == NULL) {
  13.135 +        ERROR("memory alloc failed");
  13.136 +        errno = ENOMEM;
  13.137 +        goto out;
  13.138 +    }
  13.139 +
  13.140 +    /* Get the domain's shared-info frame. */
  13.141 +    domctl.cmd = XEN_DOMCTL_getdomaininfo;
  13.142 +    domctl.domain = (domid_t)dom;
  13.143 +    if (xc_domctl(xc_handle, &domctl) < 0) {
  13.144 +        ERROR("Could not get information on new domain");
  13.145 +        goto out;
  13.146 +    }
  13.147 +    shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
  13.148 +
  13.149 +    if(xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(max_pfn)) != 0) {
  13.150 +        errno = ENOMEM;
  13.151 +        goto out;
  13.152 +    }
  13.153 +
  13.154 +    for ( i = 0; i < max_pfn; i++ )
  13.155 +        p2m[i] = i;
  13.156 +    for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < max_pfn; i++ )
  13.157 +        p2m[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
  13.158 +
  13.159 +    /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */
  13.160 +    rc = xc_domain_memory_populate_physmap(
  13.161 +        xc_handle, dom, (max_pfn > 0xa0) ? 0xa0 : max_pfn,
  13.162 +        0, 0, &p2m[0x00]);
  13.163 +    if ( (rc == 0) && (max_pfn > 0xc0) )
  13.164 +        rc = xc_domain_memory_populate_physmap(
  13.165 +            xc_handle, dom, max_pfn - 0xc0, 0, 0, &p2m[0xc0]);
  13.166 +    if ( rc != 0 )
  13.167 +    {
  13.168 +        PERROR("Could not allocate memory for HVM guest.\n");
  13.169 +        goto out;
  13.170 +    }
  13.171 +
  13.172 +
  13.173 +    /**********XXXXXXXXXXXXXXXX******************/
  13.174 +    if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) {
  13.175 +        ERROR("Could not get domain info");
  13.176 +        return 1;
  13.177 +    }
  13.178 +
  13.179 +    domctl.cmd = XEN_DOMCTL_getdomaininfo;
  13.180 +    domctl.domain = (domid_t)dom;
  13.181 +    if (xc_domctl(xc_handle, &domctl) < 0) {
  13.182 +        ERROR("Could not get information on new domain");
  13.183 +        goto out;
  13.184 +    }
  13.185 +
  13.186 +    for ( i = 0; i < max_pfn; i++)
  13.187 +        p2m[i] = i;
  13.188 +
  13.189 +    prev_pc = 0;
  13.190 +
  13.191 +    n = 0;
  13.192 +    while (1) {
  13.193 +
  13.194 +        int j;
  13.195 +
  13.196 +        this_pc = (n * 100) / max_pfn;
  13.197 +        if ( (this_pc - prev_pc) >= 5 )
  13.198 +        {
  13.199 +            PPRINTF("\b\b\b\b%3d%%", this_pc);
  13.200 +            prev_pc = this_pc;
  13.201 +        }
  13.202 +
  13.203 +        if (!read_exact(io_fd, &j, sizeof(int))) {
  13.204 +            ERROR("HVM restore Error when reading batch size");
  13.205 +            goto out;
  13.206 +        }
  13.207 +
  13.208 +        PPRINTF("batch %d\n",j);
  13.209 +
  13.210 +        if (j == -1) {
  13.211 +            verify = 1;
  13.212 +            DPRINTF("Entering page verify mode\n");
  13.213 +            continue;
  13.214 +        }
  13.215 +
  13.216 +        if (j == 0)
  13.217 +            break;  /* our work here is done */
  13.218 +
  13.219 +        if (j > MAX_BATCH_SIZE) {
  13.220 +            ERROR("Max batch size exceeded. Giving up.");
  13.221 +            goto out;
  13.222 +        }
  13.223 +
  13.224 +        if (!read_exact(io_fd, region_pfn_type, j*sizeof(unsigned long))) {
  13.225 +            ERROR("Error when reading region pfn types");
  13.226 +            goto out;
  13.227 +        }
  13.228 +
  13.229 +        region_base = xc_map_foreign_batch(
  13.230 +            xc_handle, dom, PROT_WRITE, region_pfn_type, j);
  13.231 +
  13.232 +        for ( i = 0; i < j; i++ )
  13.233 +        {
  13.234 +            void *page;
  13.235 +
  13.236 +            pfn = region_pfn_type[i];
  13.237 +            if ( pfn > max_pfn )
  13.238 +            {
  13.239 +                ERROR("pfn out of range");
  13.240 +                goto out;
  13.241 +            }
  13.242 +
  13.243 +            if ( pfn >= 0xa0 && pfn < 0xc0) {
  13.244 +                ERROR("hvm restore:pfn in vga hole");
  13.245 +                goto out;
  13.246 +            }
  13.247 +
  13.248 +
  13.249 +            mfn = p2m[pfn];
  13.250 +
  13.251 +            /* In verify mode, we use a copy; otherwise we work in place */
  13.252 +            page = verify ? (void *)buf : (region_base + i*PAGE_SIZE);
  13.253 +
  13.254 +            if (!read_exact(io_fd, page, PAGE_SIZE)) {
  13.255 +                ERROR("Error when reading page (%x)", i);
  13.256 +                goto out;
  13.257 +            }
  13.258 +
  13.259 +            if (verify) {
  13.260 +
  13.261 +                int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE);
  13.262 +
  13.263 +                if (res) {
  13.264 +
  13.265 +                    int v;
  13.266 +
  13.267 +                    DPRINTF("************** pfn=%lx mfn=%lx gotcs=%08lx "
  13.268 +                            "actualcs=%08lx\n", pfn, p2m[pfn],
  13.269 +                            csum_page(region_base + i*PAGE_SIZE),
  13.270 +                            csum_page(buf));
  13.271 +
  13.272 +                    for (v = 0; v < 4; v++) {
  13.273 +
  13.274 +                        unsigned long *p = (unsigned long *)
  13.275 +                            (region_base + i*PAGE_SIZE);
  13.276 +                        if (buf[v] != p[v])
  13.277 +                            DPRINTF("    %d: %08lx %08lx\n", v, buf[v], p[v]);
  13.278 +                    }
  13.279 +                }
  13.280 +            }
  13.281 +
  13.282 +        } /* end of 'batch' for loop */
  13.283 +        munmap(region_base, j*PAGE_SIZE);
  13.284 +        n+= j; /* crude stats */
  13.285 +
  13.286 +    }/*while 1*/
  13.287 +    
  13.288 +/*    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_APIC_ENABLED, apic);*/
  13.289 +    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae);
  13.290 +    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn);
  13.291 +
  13.292 +    if ( v_end > HVM_BELOW_4G_RAM_END )
  13.293 +        shared_page_nr = (HVM_BELOW_4G_RAM_END >> PAGE_SHIFT) - 1;
  13.294 +    else
  13.295 +        shared_page_nr = (v_end >> PAGE_SHIFT) - 1;
  13.296 +
  13.297 +    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, shared_page_nr-1);
  13.298 +    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, shared_page_nr-2);
  13.299 +    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, shared_page_nr);
  13.300 +
  13.301 +    /* caculate the store_mfn , wrong val cause hang when introduceDomain */
  13.302 +    *store_mfn = (v_end >> PAGE_SHIFT) - 2;
  13.303 +    DPRINTF("hvm restore:calculate new store_mfn=0x%lx,v_end=0x%llx..\n", *store_mfn, v_end);
  13.304 +
  13.305 +    /* restore hvm context including pic/pit/shpage */
  13.306 +    if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
  13.307 +        ERROR("error read hvm context size!\n");
  13.308 +        goto out;
  13.309 +    }
  13.310 +    if (rec_len != sizeof(hvm_ctxt)) {
  13.311 +        ERROR("hvm context size dismatch!\n");
  13.312 +        goto out;
  13.313 +    }
  13.314 +
  13.315 +    if (!read_exact(io_fd, &hvm_ctxt, sizeof(hvm_ctxt))) {
  13.316 +        ERROR("error read hvm context!\n");
  13.317 +        goto out;
  13.318 +    }
  13.319 +
  13.320 +    if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, &hvm_ctxt))) {
  13.321 +        ERROR("error set hvm context!\n");
  13.322 +        goto out;
  13.323 +    }
  13.324 +
  13.325 +    if (!read_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
  13.326 +        ERROR("error read nr vcpu !\n");
  13.327 +        goto out;
  13.328 +    }
  13.329 +    DPRINTF("hvm restore:get nr_vcpus=%d.\n", nr_vcpus);
  13.330 +
  13.331 +    for (i =0; i < nr_vcpus; i++) {
  13.332 +        if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
  13.333 +            ERROR("error read vcpu context size!\n");
  13.334 +            goto out;
  13.335 +        }
  13.336 +        if (rec_len != sizeof(ctxt)) {
  13.337 +            ERROR("vcpu context size dismatch!\n");
  13.338 +            goto out;
  13.339 +        }
  13.340 +
  13.341 +        if (!read_exact(io_fd, &(ctxt), sizeof(ctxt))) {
  13.342 +            ERROR("error read vcpu context.\n");
  13.343 +            goto out;
  13.344 +        }
  13.345 +
  13.346 +        if ( (rc = xc_vcpu_setcontext(xc_handle, dom, i, &ctxt)) ) {
  13.347 +            ERROR("Could not set vcpu context, rc=%d", rc);
  13.348 +            goto out;
  13.349 +        }
  13.350 +    }
  13.351 +
  13.352 +    rc = 0;
  13.353 +    goto out;
  13.354 +
  13.355 + out:
  13.356 +    if ( (rc != 0) && (dom != 0) )
  13.357 +        xc_domain_destroy(xc_handle, dom);
  13.358 +    free(p2m);
  13.359 +
  13.360 +    DPRINTF("Restore exit with rc=%d\n", rc);
  13.361 +
  13.362 +    return rc;
  13.363 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/libxc/xc_hvm_save.c	Thu Jan 18 18:25:04 2007 +0000
    14.3 @@ -0,0 +1,727 @@
    14.4 +/******************************************************************************
    14.5 + * xc_hvm_save.c
    14.6 + *
    14.7 + * Save the state of a running HVM guest.
    14.8 + *
    14.9 + * Copyright (c) 2003, K A Fraser.
   14.10 + * Copyright (c) 2006 Intel Corperation
   14.11 + * rewriten for hvm guest by Zhai Edwin <edwin.zhai@intel.com>
   14.12 + *
   14.13 + * This program is free software; you can redistribute it and/or modify it
   14.14 + * under the terms and conditions of the GNU General Public License,
   14.15 + * version 2, as published by the Free Software Foundation.
   14.16 + *
   14.17 + * This program is distributed in the hope it will be useful, but WITHOUT
   14.18 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.19 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   14.20 + * more details.
   14.21 + *
   14.22 + * You should have received a copy of the GNU General Public License along with
   14.23 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
   14.24 + * Place - Suite 330, Boston, MA 02111-1307 USA.
   14.25 + *
   14.26 + */
   14.27 +
   14.28 +#include <inttypes.h>
   14.29 +#include <time.h>
   14.30 +#include <stdlib.h>
   14.31 +#include <unistd.h>
   14.32 +#include <sys/time.h>
   14.33 +
   14.34 +#include "xc_private.h"
   14.35 +#include "xg_private.h"
   14.36 +#include "xg_save_restore.h"
   14.37 +
   14.38 +/*
   14.39 +** Default values for important tuning parameters. Can override by passing
   14.40 +** non-zero replacement values to xc_hvm_save().
   14.41 +**
   14.42 +** XXX SMH: should consider if want to be able to override MAX_MBIT_RATE too.
   14.43 +**
   14.44 +*/
   14.45 +#define DEF_MAX_ITERS   29   /* limit us to 30 times round loop   */
   14.46 +#define DEF_MAX_FACTOR   3   /* never send more than 3x nr_pfns   */
   14.47 +
   14.48 +/* max mfn of the whole machine */
   14.49 +static unsigned long max_mfn;
   14.50 +
   14.51 +/* virtual starting address of the hypervisor */
   14.52 +static unsigned long hvirt_start;
   14.53 +
   14.54 +/* #levels of page tables used by the currrent guest */
   14.55 +static unsigned int pt_levels;
   14.56 +
   14.57 +/* total number of pages used by the current guest */
   14.58 +static unsigned long max_pfn;
   14.59 +
   14.60 +/*
   14.61 +** During (live) save/migrate, we maintain a number of bitmaps to track
   14.62 +** which pages we have to send, to fixup, and to skip.
   14.63 +*/
   14.64 +
   14.65 +#define BITS_PER_LONG (sizeof(unsigned long) * 8)
   14.66 +#define BITMAP_SIZE   ((max_pfn + BITS_PER_LONG - 1) / 8)
   14.67 +
   14.68 +#define BITMAP_ENTRY(_nr,_bmap) \
   14.69 +   ((unsigned long *)(_bmap))[(_nr)/BITS_PER_LONG]
   14.70 +
   14.71 +#define BITMAP_SHIFT(_nr) ((_nr) % BITS_PER_LONG)
   14.72 +
   14.73 +static inline int test_bit (int nr, volatile void * addr)
   14.74 +{
   14.75 +    return (BITMAP_ENTRY(nr, addr) >> BITMAP_SHIFT(nr)) & 1;
   14.76 +}
   14.77 +
   14.78 +static inline void clear_bit (int nr, volatile void * addr)
   14.79 +{
   14.80 +    BITMAP_ENTRY(nr, addr) &= ~(1UL << BITMAP_SHIFT(nr));
   14.81 +}
   14.82 +
   14.83 +static inline int permute( int i, int nr, int order_nr  )
   14.84 +{
   14.85 +    /* Need a simple permutation function so that we scan pages in a
   14.86 +       pseudo random order, enabling us to get a better estimate of
   14.87 +       the domain's page dirtying rate as we go (there are often
   14.88 +       contiguous ranges of pfns that have similar behaviour, and we
   14.89 +       want to mix them up. */
   14.90 +
   14.91 +    /* e.g. nr->oder 15->4 16->4 17->5 */
   14.92 +    /* 512MB domain, 128k pages, order 17 */
   14.93 +
   14.94 +    /*
   14.95 +      QPONMLKJIHGFEDCBA
   14.96 +             QPONMLKJIH
   14.97 +      GFEDCBA
   14.98 +     */
   14.99 +
  14.100 +    /*
  14.101 +      QPONMLKJIHGFEDCBA
  14.102 +                  EDCBA
  14.103 +             QPONM
  14.104 +      LKJIHGF
  14.105 +      */
  14.106 +
  14.107 +    do { i = ((i>>(order_nr-10)) | ( i<<10 ) ) & ((1<<order_nr)-1); }
  14.108 +    while ( i >= nr ); /* this won't ever loop if nr is a power of 2 */
  14.109 +
  14.110 +    return i;
  14.111 +}
  14.112 +
  14.113 +static uint64_t tv_to_us(struct timeval *new)
  14.114 +{
  14.115 +    return (new->tv_sec * 1000000) + new->tv_usec;
  14.116 +}
  14.117 +
  14.118 +static uint64_t llgettimeofday(void)
  14.119 +{
  14.120 +    struct timeval now;
  14.121 +    gettimeofday(&now, NULL);
  14.122 +    return tv_to_us(&now);
  14.123 +}
  14.124 +
  14.125 +static uint64_t tv_delta(struct timeval *new, struct timeval *old)
  14.126 +{
  14.127 +    return ((new->tv_sec - old->tv_sec)*1000000 ) +
  14.128 +        (new->tv_usec - old->tv_usec);
  14.129 +}
  14.130 +
  14.131 +
  14.132 +#define RATE_IS_MAX() (0)
  14.133 +#define ratewrite(_io_fd, _buf, _n) write((_io_fd), (_buf), (_n))
  14.134 +#define initialize_mbit_rate()
  14.135 +
  14.136 +static inline ssize_t write_exact(int fd, void *buf, size_t count)
  14.137 +{
  14.138 +    if(write(fd, buf, count) != count)
  14.139 +        return 0;
  14.140 +    return 1;
  14.141 +}
  14.142 +
  14.143 +static int print_stats(int xc_handle, uint32_t domid, int pages_sent,
  14.144 +                       xc_shadow_op_stats_t *stats, int print)
  14.145 +{
  14.146 +    static struct timeval wall_last;
  14.147 +    static long long      d0_cpu_last;
  14.148 +    static long long      d1_cpu_last;
  14.149 +
  14.150 +    struct timeval        wall_now;
  14.151 +    long long             wall_delta;
  14.152 +    long long             d0_cpu_now, d0_cpu_delta;
  14.153 +    long long             d1_cpu_now, d1_cpu_delta;
  14.154 +
  14.155 +    gettimeofday(&wall_now, NULL);
  14.156 +
  14.157 +    d0_cpu_now = xc_domain_get_cpu_usage(xc_handle, 0, /* FIXME */ 0)/1000;
  14.158 +    d1_cpu_now = xc_domain_get_cpu_usage(xc_handle, domid, /* FIXME */ 0)/1000;
  14.159 +
  14.160 +    if ( (d0_cpu_now == -1) || (d1_cpu_now == -1) )
  14.161 +        DPRINTF("ARRHHH!!\n");
  14.162 +
  14.163 +    wall_delta = tv_delta(&wall_now,&wall_last)/1000;
  14.164 +
  14.165 +    if (wall_delta == 0) wall_delta = 1;
  14.166 +
  14.167 +    d0_cpu_delta = (d0_cpu_now - d0_cpu_last)/1000;
  14.168 +    d1_cpu_delta = (d1_cpu_now - d1_cpu_last)/1000;
  14.169 +
  14.170 +    if (print)
  14.171 +        DPRINTF(
  14.172 +                "delta %lldms, dom0 %d%%, target %d%%, sent %dMb/s, "
  14.173 +                "dirtied %dMb/s %" PRId32 " pages\n",
  14.174 +                wall_delta,
  14.175 +                (int)((d0_cpu_delta*100)/wall_delta),
  14.176 +                (int)((d1_cpu_delta*100)/wall_delta),
  14.177 +                (int)((pages_sent*PAGE_SIZE)/(wall_delta*(1000/8))),
  14.178 +                (int)((stats->dirty_count*PAGE_SIZE)/(wall_delta*(1000/8))),
  14.179 +                stats->dirty_count);
  14.180 +
  14.181 +    d0_cpu_last = d0_cpu_now;
  14.182 +    d1_cpu_last = d1_cpu_now;
  14.183 +    wall_last   = wall_now;
  14.184 +
  14.185 +    return 0;
  14.186 +}
  14.187 +
  14.188 +static int analysis_phase(int xc_handle, uint32_t domid, int max_pfn,
  14.189 +                          unsigned long *arr, int runs)
  14.190 +{
  14.191 +    long long start, now;
  14.192 +    xc_shadow_op_stats_t stats;
  14.193 +    int j;
  14.194 +
  14.195 +    start = llgettimeofday();
  14.196 +
  14.197 +    for (j = 0; j < runs; j++) {
  14.198 +        int i;
  14.199 +
  14.200 +        xc_shadow_control(xc_handle, domid, XEN_DOMCTL_SHADOW_OP_CLEAN,
  14.201 +                          arr, max_pfn, NULL, 0, NULL);
  14.202 +        DPRINTF("#Flush\n");
  14.203 +        for ( i = 0; i < 40; i++ ) {
  14.204 +            usleep(50000);
  14.205 +            now = llgettimeofday();
  14.206 +            xc_shadow_control(xc_handle, domid, XEN_DOMCTL_SHADOW_OP_PEEK,
  14.207 +                              NULL, 0, NULL, 0, &stats);
  14.208 +
  14.209 +            DPRINTF("now= %lld faults= %"PRId32" dirty= %"PRId32"\n",
  14.210 +                    ((now-start)+500)/1000,
  14.211 +                    stats.fault_count, stats.dirty_count);
  14.212 +        }
  14.213 +    }
  14.214 +
  14.215 +    return -1;
  14.216 +}
  14.217 +
  14.218 +static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
  14.219 +                             int dom, xc_dominfo_t *info,
  14.220 +                             vcpu_guest_context_t *ctxt)
  14.221 +{
  14.222 +    int i = 0;
  14.223 +
  14.224 +    if (!(*suspend)(dom)) {
  14.225 +        ERROR("Suspend request failed");
  14.226 +        return -1;
  14.227 +    }
  14.228 +
  14.229 + retry:
  14.230 +
  14.231 +    if (xc_domain_getinfo(xc_handle, dom, 1, info) != 1) {
  14.232 +        ERROR("Could not get domain info");
  14.233 +        return -1;
  14.234 +    }
  14.235 +
  14.236 +    if ( xc_vcpu_getcontext(xc_handle, dom, 0 /* XXX */, ctxt))
  14.237 +        ERROR("Could not get vcpu context");
  14.238 +
  14.239 +
  14.240 +    if (info->shutdown && info->shutdown_reason == SHUTDOWN_suspend)
  14.241 +        return 0; // success
  14.242 +
  14.243 +    if (info->paused) {
  14.244 +        // try unpausing domain, wait, and retest
  14.245 +        xc_domain_unpause( xc_handle, dom );
  14.246 +
  14.247 +        ERROR("Domain was paused. Wait and re-test.");
  14.248 +        usleep(10000);  // 10ms
  14.249 +
  14.250 +        goto retry;
  14.251 +    }
  14.252 +
  14.253 +
  14.254 +    if( ++i < 100 ) {
  14.255 +        ERROR("Retry suspend domain.");
  14.256 +        usleep(10000);  // 10ms
  14.257 +        goto retry;
  14.258 +    }
  14.259 +
  14.260 +    ERROR("Unable to suspend domain.");
  14.261 +
  14.262 +    return -1;
  14.263 +}
  14.264 +
  14.265 +int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
  14.266 +                  uint32_t max_factor, uint32_t flags, int (*suspend)(int))
  14.267 +{
  14.268 +    xc_dominfo_t info;
  14.269 +
  14.270 +    int rc = 1, i, last_iter, iter = 0;
  14.271 +    int live  = (flags & XCFLAGS_LIVE);
  14.272 +    int debug = (flags & XCFLAGS_DEBUG);
  14.273 +    int sent_last_iter, skip_this_iter;
  14.274 +
  14.275 +    /* The new domain's shared-info frame number. */
  14.276 +    unsigned long shared_info_frame;
  14.277 +
  14.278 +    /* A copy of the CPU context of the guest. */
  14.279 +    vcpu_guest_context_t ctxt;
  14.280 +
  14.281 +    /* A table containg the type of each PFN (/not/ MFN!). */
  14.282 +    unsigned long *pfn_type = NULL;
  14.283 +    unsigned long *pfn_batch = NULL;
  14.284 +
  14.285 +    /* A copy of hvm domain context */
  14.286 +    hvm_domain_context_t hvm_ctxt;
  14.287 +
  14.288 +    /* Live mapping of shared info structure */
  14.289 +    shared_info_t *live_shinfo = NULL;
  14.290 +
  14.291 +    /* base of the region in which domain memory is mapped */
  14.292 +    unsigned char *region_base = NULL;
  14.293 +
  14.294 +    uint32_t nr_pfns, rec_size, nr_vcpus;
  14.295 +    unsigned long *page_array = NULL;
  14.296 +
  14.297 +    /* power of 2 order of max_pfn */
  14.298 +    int order_nr;
  14.299 +
  14.300 +    /* bitmap of pages:
  14.301 +       - that should be sent this iteration (unless later marked as skip);
  14.302 +       - to skip this iteration because already dirty; */
  14.303 +    unsigned long *to_send = NULL, *to_skip = NULL;
  14.304 +
  14.305 +    xc_shadow_op_stats_t stats;
  14.306 +
  14.307 +    unsigned long total_sent    = 0;
  14.308 +
  14.309 +    DPRINTF("xc_hvm_save:dom=%d, max_iters=%d, max_factor=%d, flags=0x%x, live=%d, debug=%d.\n",
  14.310 +            dom, max_iters, max_factor, flags,
  14.311 +            live, debug);
  14.312 +
  14.313 +    /* If no explicit control parameters given, use defaults */
  14.314 +    if(!max_iters)
  14.315 +        max_iters = DEF_MAX_ITERS;
  14.316 +    if(!max_factor)
  14.317 +        max_factor = DEF_MAX_FACTOR;
  14.318 +
  14.319 +    initialize_mbit_rate();
  14.320 +
  14.321 +    if(!get_platform_info(xc_handle, dom,
  14.322 +                          &max_mfn, &hvirt_start, &pt_levels)) {
  14.323 +        ERROR("HVM:Unable to get platform info.");
  14.324 +        return 1;
  14.325 +    }
  14.326 +
  14.327 +    if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) {
  14.328 +        ERROR("HVM:Could not get domain info");
  14.329 +        return 1;
  14.330 +    }
  14.331 +    nr_vcpus = info.nr_online_vcpus;
  14.332 +
  14.333 +    if (mlock(&ctxt, sizeof(ctxt))) {
  14.334 +        ERROR("HVM:Unable to mlock ctxt");
  14.335 +        return 1;
  14.336 +    }
  14.337 +
  14.338 +    /* Only have to worry about vcpu 0 even for SMP */
  14.339 +    if (xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt)) {
  14.340 +        ERROR("HVM:Could not get vcpu context");
  14.341 +        goto out;
  14.342 +    }
  14.343 +    shared_info_frame = info.shared_info_frame;
  14.344 +
  14.345 +    /* A cheesy test to see whether the domain contains valid state. */
  14.346 +    if (ctxt.ctrlreg[3] == 0)
  14.347 +    {
  14.348 +        ERROR("Domain is not in a valid HVM guest state");
  14.349 +        goto out;
  14.350 +    }
  14.351 +
  14.352 +   /* cheesy sanity check */
  14.353 +    if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) {
  14.354 +        ERROR("Invalid HVM state record -- pfn count out of range: %lu",
  14.355 +            (info.max_memkb >> (PAGE_SHIFT - 10)));
  14.356 +        goto out;
  14.357 +    }
  14.358 +
  14.359 +    /* Map the shared info frame */
  14.360 +    if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
  14.361 +                                            PROT_READ, shared_info_frame))) {
  14.362 +        ERROR("HVM:Couldn't map live_shinfo");
  14.363 +        goto out;
  14.364 +    }
  14.365 +
  14.366 +    max_pfn = live_shinfo->arch.max_pfn;
  14.367 +
  14.368 +    DPRINTF("saved hvm domain info:max_memkb=0x%lx, max_mfn=0x%lx, nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages); 
  14.369 +
  14.370 +    /* nr_pfns: total pages excluding vga acc mem
  14.371 +     * max_pfn: nr_pfns + 0x20 vga hole(0xa0~0xc0)
  14.372 +     * getdomaininfo.tot_pages: all the allocated pages for this domain
  14.373 +     */
  14.374 +    if (live) {
  14.375 +        ERROR("hvm domain doesn't support live migration now.\n");
  14.376 +        goto out;
  14.377 +
  14.378 +        if (xc_shadow_control(xc_handle, dom,
  14.379 +                              XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
  14.380 +                              NULL, 0, NULL, 0, NULL) < 0) {
  14.381 +            ERROR("Couldn't enable shadow mode");
  14.382 +            goto out;
  14.383 +        }
  14.384 +
  14.385 +        /* excludes vga acc mem */
  14.386 +        nr_pfns = info.nr_pages - 0x800;
  14.387 +
  14.388 +        last_iter = 0;
  14.389 +        DPRINTF("hvm domain live migration debug start: logdirty enable.\n");
  14.390 +    } else {
  14.391 +        /* This is a non-live suspend. Issue the call back to get the
  14.392 +           domain suspended */
  14.393 +
  14.394 +        last_iter = 1;
  14.395 +
  14.396 +        /* suspend hvm domain */
  14.397 +        if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info, &ctxt)) {
  14.398 +            ERROR("HVM Domain appears not to have suspended");
  14.399 +            goto out;
  14.400 +        }
  14.401 +        nr_pfns = info.nr_pages;
  14.402 +        DPRINTF("after suspend hvm domain nr_pages=0x%x.\n", nr_pfns);
  14.403 +    }
  14.404 +
  14.405 +    DPRINTF("after 1st handle hvm domain nr_pfns=0x%x, nr_pages=0x%lx, max_memkb=0x%lx, live=%d.\n",
  14.406 +            nr_pfns,
  14.407 +            info.nr_pages,
  14.408 +            info.max_memkb,
  14.409 +            live);
  14.410 +
  14.411 +    nr_pfns = info.nr_pages;
  14.412 +
  14.413 +    /*XXX: caculate the VGA hole*/
  14.414 +    max_pfn = nr_pfns + 0x20;
  14.415 +
  14.416 +    skip_this_iter = 0;/*XXX*/
  14.417 +    /* pretend we sent all the pages last iteration */
  14.418 +    sent_last_iter = max_pfn;
  14.419 +
  14.420 +    /* calculate the power of 2 order of max_pfn, e.g.
  14.421 +       15->4 16->4 17->5 */
  14.422 +    for (i = max_pfn-1, order_nr = 0; i ; i >>= 1, order_nr++)
  14.423 +        continue;
  14.424 +
  14.425 +    /* Setup to_send / to_fix and to_skip bitmaps */
  14.426 +    to_send = malloc(BITMAP_SIZE);
  14.427 +    to_skip = malloc(BITMAP_SIZE);
  14.428 +
  14.429 +    if (!to_send ||!to_skip) {
  14.430 +        ERROR("Couldn't allocate to_send array");
  14.431 +        goto out;
  14.432 +    }
  14.433 +
  14.434 +    memset(to_send, 0xff, BITMAP_SIZE);
  14.435 +
  14.436 +    if (lock_pages(to_send, BITMAP_SIZE)) {
  14.437 +        ERROR("Unable to lock to_send");
  14.438 +        return 1;
  14.439 +    }
  14.440 +
  14.441 +    /* (to fix is local only) */
  14.442 +    if (lock_pages(to_skip, BITMAP_SIZE)) {
  14.443 +        ERROR("Unable to lock to_skip");
  14.444 +        return 1;
  14.445 +    }
  14.446 +
  14.447 +    analysis_phase(xc_handle, dom, max_pfn, to_skip, 0);
  14.448 +
  14.449 +    /* get all the HVM domain pfns */
  14.450 +    if ( (page_array = (unsigned long *) malloc (sizeof(unsigned long) * max_pfn)) == NULL) {
  14.451 +        ERROR("HVM:malloc fail!\n");
  14.452 +        goto out;
  14.453 +    }
  14.454 +
  14.455 +    for ( i = 0; i < max_pfn; i++)
  14.456 +        page_array[i] = i;
  14.457 +
  14.458 +
  14.459 +    /* We want zeroed memory so use calloc rather than malloc. */
  14.460 +    pfn_type  = calloc(MAX_BATCH_SIZE, sizeof(*pfn_type));
  14.461 +    pfn_batch = calloc(MAX_BATCH_SIZE, sizeof(*pfn_batch));
  14.462 +
  14.463 +    if ((pfn_type == NULL) || (pfn_batch == NULL)) {
  14.464 +        ERROR("failed to alloc memory for pfn_type and/or pfn_batch arrays");
  14.465 +        errno = ENOMEM;
  14.466 +        goto out;
  14.467 +    }
  14.468 +
  14.469 +    if (lock_pages(pfn_type, MAX_BATCH_SIZE * sizeof(*pfn_type))) {
  14.470 +        ERROR("Unable to lock");
  14.471 +        goto out;
  14.472 +    }
  14.473 +
  14.474 +    /* Start writing out the saved-domain record. */
  14.475 +    if (!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) {
  14.476 +        ERROR("write: max_pfn");
  14.477 +        goto out;
  14.478 +    }
  14.479 +
  14.480 +    while(1) {
  14.481 +
  14.482 +        unsigned int prev_pc, sent_this_iter, N, batch;
  14.483 +
  14.484 +        iter++;
  14.485 +        sent_this_iter = 0;
  14.486 +        skip_this_iter = 0;
  14.487 +        prev_pc = 0;
  14.488 +        N=0;
  14.489 +
  14.490 +        DPRINTF("Saving HVM domain memory pages: iter %d   0%%", iter);
  14.491 +
  14.492 +        while( N < max_pfn ){
  14.493 +
  14.494 +            unsigned int this_pc = (N * 100) / max_pfn;
  14.495 +
  14.496 +            if ((this_pc - prev_pc) >= 5) {
  14.497 +                DPRINTF("\b\b\b\b%3d%%", this_pc);
  14.498 +                prev_pc = this_pc;
  14.499 +            }
  14.500 +
  14.501 +            /* slightly wasteful to peek the whole array evey time,
  14.502 +               but this is fast enough for the moment. */
  14.503 +            if (!last_iter && xc_shadow_control(
  14.504 +                    xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK,
  14.505 +                    to_skip, max_pfn, NULL, 0, NULL) != max_pfn) {
  14.506 +                ERROR("Error peeking HVM shadow bitmap");
  14.507 +                goto out;
  14.508 +            }
  14.509 +
  14.510 +
  14.511 +            /* load pfn_type[] with the mfn of all the pages we're doing in
  14.512 +               this batch. */
  14.513 +            for (batch = 0; batch < MAX_BATCH_SIZE && N < max_pfn ; N++) {
  14.514 +
  14.515 +                int n = permute(N, max_pfn, order_nr);
  14.516 +
  14.517 +                if (debug) {
  14.518 +                    DPRINTF("%d pfn= %08lx mfn= %08lx %d \n",
  14.519 +                            iter, (unsigned long)n, page_array[n],
  14.520 +                            test_bit(n, to_send));
  14.521 +                }
  14.522 +
  14.523 +                if (!last_iter && test_bit(n, to_send)&& test_bit(n, to_skip))
  14.524 +                    skip_this_iter++; /* stats keeping */
  14.525 +
  14.526 +                if (!((test_bit(n, to_send) && !test_bit(n, to_skip)) ||
  14.527 +                      (test_bit(n, to_send) && last_iter)))
  14.528 +                    continue;
  14.529 +
  14.530 +                if (n >= 0xa0 && n < 0xc0) {
  14.531 +/*                    DPRINTF("get a vga hole pfn= %x.\n", n);*/
  14.532 +                    continue;
  14.533 +                }
  14.534 +                /*
  14.535 +                ** we get here if:
  14.536 +                **  1. page is marked to_send & hasn't already been re-dirtied
  14.537 +                **  2. (ignore to_skip in last iteration)
  14.538 +                */
  14.539 +
  14.540 +                pfn_batch[batch] = n;
  14.541 +                pfn_type[batch]  = page_array[n];
  14.542 +
  14.543 +                batch++;
  14.544 +            }
  14.545 +
  14.546 +            if (batch == 0)
  14.547 +                goto skip; /* vanishingly unlikely... */
  14.548 +
  14.549 +            /* map_foreign use pfns now !*/
  14.550 +            if ((region_base = xc_map_foreign_batch(
  14.551 +                     xc_handle, dom, PROT_READ, pfn_batch, batch)) == 0) {
  14.552 +                ERROR("map batch failed");
  14.553 +                goto out;
  14.554 +            }
  14.555 +
  14.556 +            /* write num of pfns */
  14.557 +            if(!write_exact(io_fd, &batch, sizeof(unsigned int))) {
  14.558 +                ERROR("Error when writing to state file (2)");
  14.559 +                goto out;
  14.560 +            }
  14.561 +
  14.562 +            /* write all the pfns */
  14.563 +            if(!write_exact(io_fd, pfn_batch, sizeof(unsigned long)*batch)) {
  14.564 +                ERROR("Error when writing to state file (3)");
  14.565 +                goto out;
  14.566 +            }
  14.567 +
  14.568 +            if (ratewrite(io_fd, region_base, PAGE_SIZE * batch) != PAGE_SIZE * batch) {
  14.569 +                ERROR("ERROR when writting to state file (4)");
  14.570 +                goto out;
  14.571 +            }
  14.572 +
  14.573 +
  14.574 +            sent_this_iter += batch;
  14.575 +
  14.576 +            munmap(region_base, batch*PAGE_SIZE);
  14.577 +
  14.578 +        } /* end of this while loop for this iteration */
  14.579 +
  14.580 +      skip:
  14.581 +
  14.582 +        total_sent += sent_this_iter;
  14.583 +
  14.584 +        DPRINTF("\r %d: sent %d, skipped %d, ",
  14.585 +                iter, sent_this_iter, skip_this_iter );
  14.586 +
  14.587 +        if (last_iter) {
  14.588 +            print_stats( xc_handle, dom, sent_this_iter, &stats, 1);
  14.589 +
  14.590 +            DPRINTF("Total pages sent= %ld (%.2fx)\n",
  14.591 +                    total_sent, ((float)total_sent)/max_pfn );
  14.592 +        }
  14.593 +
  14.594 +        if (last_iter && debug){
  14.595 +            int minusone = -1;
  14.596 +            memset(to_send, 0xff, BITMAP_SIZE);
  14.597 +            debug = 0;
  14.598 +            DPRINTF("Entering debug resend-all mode\n");
  14.599 +
  14.600 +            /* send "-1" to put receiver into debug mode */
  14.601 +            if(!write_exact(io_fd, &minusone, sizeof(int))) {
  14.602 +                ERROR("Error when writing to state file (6)");
  14.603 +                goto out;
  14.604 +            }
  14.605 +
  14.606 +            continue;
  14.607 +        }
  14.608 +
  14.609 +        if (last_iter) break;
  14.610 +
  14.611 +        if (live) {
  14.612 +
  14.613 +
  14.614 +            if(
  14.615 +                ((sent_this_iter > sent_last_iter) && RATE_IS_MAX()) ||
  14.616 +                (iter >= max_iters) ||
  14.617 +                (sent_this_iter+skip_this_iter < 50) ||
  14.618 +                (total_sent > max_pfn*max_factor) ) {
  14.619 +
  14.620 +                DPRINTF("Start last iteration for HVM domain\n");
  14.621 +                last_iter = 1;
  14.622 +
  14.623 +                if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info,
  14.624 +                                      &ctxt)) {
  14.625 +                    ERROR("Domain appears not to have suspended");
  14.626 +                    goto out;
  14.627 +                }
  14.628 +
  14.629 +                DPRINTF("SUSPEND shinfo %08lx eip %08lx edx %08lx\n",
  14.630 +                        info.shared_info_frame,
  14.631 +                        (unsigned long)ctxt.user_regs.eip,
  14.632 +                        (unsigned long)ctxt.user_regs.edx);
  14.633 +            }
  14.634 +
  14.635 +            if (xc_shadow_control(xc_handle, dom, 
  14.636 +                                  XEN_DOMCTL_SHADOW_OP_CLEAN, to_send, 
  14.637 +                                  max_pfn, NULL, 0, &stats) != max_pfn) {
  14.638 +                ERROR("Error flushing shadow PT");
  14.639 +                goto out;
  14.640 +            }
  14.641 +
  14.642 +            sent_last_iter = sent_this_iter;
  14.643 +
  14.644 +            print_stats(xc_handle, dom, sent_this_iter, &stats, 1);
  14.645 +
  14.646 +        }
  14.647 +
  14.648 +
  14.649 +    } /* end of while 1 */
  14.650 +
  14.651 +
  14.652 +    DPRINTF("All HVM memory is saved\n");
  14.653 +
  14.654 +    /* Zero terminate */
  14.655 +    i = 0;
  14.656 +    if (!write_exact(io_fd, &i, sizeof(int))) {
  14.657 +        ERROR("Error when writing to state file (6)");
  14.658 +        goto out;
  14.659 +    }
  14.660 +
  14.661 +    /* save hvm hypervisor state including pic/pit/shpage */
  14.662 +    if (mlock(&hvm_ctxt, sizeof(hvm_ctxt))) {
  14.663 +        ERROR("Unable to mlock ctxt");
  14.664 +        return 1;
  14.665 +    }
  14.666 +
  14.667 +    if (xc_domain_hvm_getcontext(xc_handle, dom, &hvm_ctxt)){
  14.668 +        ERROR("HVM:Could not get hvm context");
  14.669 +        goto out;
  14.670 +    }
  14.671 +
  14.672 +    rec_size = sizeof(hvm_ctxt);
  14.673 +    if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
  14.674 +        ERROR("error write hvm ctxt size");
  14.675 +        goto out;
  14.676 +    }
  14.677 +
  14.678 +    if ( !write_exact(io_fd, &hvm_ctxt, sizeof(hvm_ctxt)) ) {
  14.679 +        ERROR("write HVM info failed!\n");
  14.680 +    }
  14.681 +
  14.682 +    /* save vcpu/vmcs context */
  14.683 +    if (!write_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
  14.684 +        ERROR("error write nr vcpus");
  14.685 +        goto out;
  14.686 +    }
  14.687 +
  14.688 +    /*XXX: need a online map to exclude down cpu */
  14.689 +    for (i = 0; i < nr_vcpus; i++) {
  14.690 +
  14.691 +        if (xc_vcpu_getcontext(xc_handle, dom, i, &ctxt)) {
  14.692 +            ERROR("HVM:Could not get vcpu context");
  14.693 +            goto out;
  14.694 +        }
  14.695 +
  14.696 +        rec_size = sizeof(ctxt);
  14.697 +        DPRINTF("write %d vcpucontext of total %d.\n", i, nr_vcpus); 
  14.698 +        if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
  14.699 +            ERROR("error write vcpu ctxt size");
  14.700 +            goto out;
  14.701 +        }
  14.702 +
  14.703 +        if (!write_exact(io_fd, &(ctxt), sizeof(ctxt)) ) {
  14.704 +            ERROR("write vmcs failed!\n");
  14.705 +            goto out;
  14.706 +        }
  14.707 +    }
  14.708 + 
  14.709 +    /* Success! */
  14.710 +    rc = 0;
  14.711 +
  14.712 + out:
  14.713 +
  14.714 +    if (live) {
  14.715 +        if(xc_shadow_control(xc_handle, dom, 
  14.716 +                             XEN_DOMCTL_SHADOW_OP_OFF,
  14.717 +                             NULL, 0, NULL, 0, NULL) < 0) {
  14.718 +            DPRINTF("Warning - couldn't disable shadow mode");
  14.719 +        }
  14.720 +    }
  14.721 +
  14.722 +    free(page_array);
  14.723 +
  14.724 +    free(pfn_type);
  14.725 +    free(pfn_batch);
  14.726 +    free(to_send);
  14.727 +    free(to_skip);
  14.728 +
  14.729 +    return !!rc;
  14.730 +}
    15.1 --- a/tools/libxc/xenctrl.h	Wed Jan 17 21:45:34 2007 -0700
    15.2 +++ b/tools/libxc/xenctrl.h	Thu Jan 18 18:25:04 2007 +0000
    15.3 @@ -313,6 +313,30 @@ int xc_domain_getinfolist(int xc_handle,
    15.4                            xc_domaininfo_t *info);
    15.5  
    15.6  /**
    15.7 + * This function returns information about the context of a hvm domain
    15.8 + * @parm xc_handle a handle to an open hypervisor interface
    15.9 + * @parm domid the domain to get information from
   15.10 + * @parm hvm_ctxt a pointer to a structure to store the execution context of the
   15.11 + *            hvm domain
   15.12 + * @return 0 on success, -1 on failure
   15.13 + */
   15.14 +int xc_domain_hvm_getcontext(int xc_handle,
   15.15 +                             uint32_t domid,
   15.16 +                             hvm_domain_context_t *hvm_ctxt);
   15.17 +
   15.18 +/**
   15.19 + * This function will set the context for hvm domain
   15.20 + *
   15.21 + * @parm xc_handle a handle to an open hypervisor interface
   15.22 + * @parm domid the domain to set the hvm domain context for
   15.23 + * @parm hvm_ctxt pointer to the the hvm context with the values to set
   15.24 + * @return 0 on success, -1 on failure
   15.25 + */
   15.26 +int xc_domain_hvm_setcontext(int xc_handle,
   15.27 +                             uint32_t domid,
   15.28 +                             hvm_domain_context_t *hvm_ctxt);
   15.29 +
   15.30 +/**
   15.31   * This function returns information about the execution context of a
   15.32   * particular vcpu of a domain.
   15.33   *
    16.1 --- a/tools/libxc/xenguest.h	Wed Jan 17 21:45:34 2007 -0700
    16.2 +++ b/tools/libxc/xenguest.h	Thu Jan 18 18:25:04 2007 +0000
    16.3 @@ -11,6 +11,7 @@
    16.4  
    16.5  #define XCFLAGS_LIVE      1
    16.6  #define XCFLAGS_DEBUG     2
    16.7 +#define XCFLAGS_HVM       4
    16.8  
    16.9  
   16.10  /**
   16.11 @@ -25,6 +26,13 @@ int xc_linux_save(int xc_handle, int io_
   16.12                    uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
   16.13                    int (*suspend)(int domid));
   16.14  
   16.15 +/**
   16.16 + * This function will save a hvm domain running unmodified guest.
   16.17 + * @return 0 on success, -1 on failure
   16.18 + */
   16.19 +int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
   16.20 +                  uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
   16.21 +                  int (*suspend)(int domid));
   16.22  
   16.23  /**
   16.24   * This function will restore a saved domain running Linux.
   16.25 @@ -43,6 +51,18 @@ int xc_linux_restore(int xc_handle, int 
   16.26                       unsigned long *console_mfn);
   16.27  
   16.28  /**
   16.29 + * This function will restore a saved hvm domain running unmodified guest.
   16.30 + *
   16.31 + * @parm store_mfn pass mem size & returned with the mfn of the store page
   16.32 + * @return 0 on success, -1 on failure
   16.33 + */
   16.34 +int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom,
   16.35 +                      unsigned long nr_pfns, unsigned int store_evtchn,
   16.36 +                      unsigned long *store_mfn, unsigned int console_evtchn,
   16.37 +                      unsigned long *console_mfn,
   16.38 +                      unsigned int pae, unsigned int apic);
   16.39 +
   16.40 +/**
   16.41   * This function will create a domain for a paravirtualized Linux
   16.42   * using file names pointing to kernel and ramdisk
   16.43   *
    17.1 --- a/tools/python/setup.py	Wed Jan 17 21:45:34 2007 -0700
    17.2 +++ b/tools/python/setup.py	Thu Jan 18 18:25:04 2007 +0000
    17.3 @@ -30,6 +30,13 @@ xs = Extension("xs",
    17.4                 libraries          = libraries,
    17.5                 sources            = [ "xen/lowlevel/xs/xs.c" ])
    17.6  
    17.7 +scf = Extension("scf",
    17.8 +               extra_compile_args = extra_compile_args,
    17.9 +               include_dirs       = include_dirs + [ "xen/lowlevel/scf" ],
   17.10 +               library_dirs       = library_dirs,
   17.11 +               libraries          = libraries,
   17.12 +               sources            = [ "xen/lowlevel/scf/scf.c" ])
   17.13 +             
   17.14  acm = Extension("acm",
   17.15                 extra_compile_args = extra_compile_args,
   17.16                 include_dirs       = include_dirs + [ "xen/lowlevel/acm" ],
   17.17 @@ -37,6 +44,10 @@ acm = Extension("acm",
   17.18                 libraries          = libraries,
   17.19                 sources            = [ "xen/lowlevel/acm/acm.c" ])
   17.20  
   17.21 +modules = [ xc, xs, acm ]
   17.22 +if os.uname()[0] == 'SunOS':
   17.23 +    modules.append(scf)
   17.24 +
   17.25  setup(name            = 'xen',
   17.26        version         = '3.0',
   17.27        description     = 'Xen',
   17.28 @@ -56,7 +67,7 @@ setup(name            = 'xen',
   17.29                           'xen.xm.tests'
   17.30                           ],
   17.31        ext_package = "xen.lowlevel",
   17.32 -      ext_modules = [ xc, xs, acm ]
   17.33 +      ext_modules = modules
   17.34        )
   17.35  
   17.36  os.chdir('logging')
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/tools/python/xen/lowlevel/scf/scf.c	Thu Jan 18 18:25:04 2007 +0000
    18.3 @@ -0,0 +1,156 @@
    18.4 +/*
    18.5 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    18.6 + * of this software and associated documentation files (the "Software"), to
    18.7 + * deal in the Software without restriction, including without limitation the
    18.8 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    18.9 + * sell copies of the Software, and to permit persons to whom the Software is
   18.10 + * furnished to do so, subject to the following conditions:
   18.11 + *
   18.12 + * The above copyright notice and this permission notice shall be included in
   18.13 + * all copies or substantial portions of the Software.
   18.14 + *
   18.15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   18.16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18.17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   18.18 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   18.19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   18.20 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   18.21 + * DEALINGS IN THE SOFTWARE.
   18.22 + *
   18.23 + * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
   18.24 + * Use is subject to license terms.
   18.25 + */
   18.26 +
   18.27 +#include <Python.h>
   18.28 +
   18.29 +#include <libscf.h>
   18.30 +#include <stdio.h>
   18.31 +
   18.32 +#define	XEND_FMRI "svc:/system/xen/xend:default"
   18.33 +#define	XEND_PG "config"
   18.34 +
   18.35 +static PyObject *scf_exc;
   18.36 +
   18.37 +static void *
   18.38 +scf_exception(const char *err, const char *value)
   18.39 +{
   18.40 +	int scferr = scf_error();
   18.41 +	const char *scfstrerr = scf_strerror(scferr);
   18.42 +	PyObject *obj = Py_BuildValue("(isss)", scferr, err, scfstrerr, value);
   18.43 +	PyErr_SetObject(scf_exc, obj);
   18.44 +	return (NULL);
   18.45 +}
   18.46 +
   18.47 +static PyObject *
   18.48 +pyscf_get_bool(PyObject *o, PyObject *args, PyObject *kwargs)
   18.49 +{
   18.50 +	static char *kwlist[] = { "name", NULL };
   18.51 +	scf_simple_prop_t *prop;
   18.52 +	uint8_t *val;
   18.53 +	char *name;
   18.54 +
   18.55 +	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
   18.56 +		return (NULL);
   18.57 +
   18.58 +	prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
   18.59 +
   18.60 +	if (prop == NULL)
   18.61 +		return (scf_exception("scf_simple_prop_get() failed", name));
   18.62 +
   18.63 +	if ((val = scf_simple_prop_next_boolean(prop)) == NULL)
   18.64 +		return (scf_exception("scf_simple_prop_next_boolean() failed",
   18.65 +		    name));
   18.66 +
   18.67 +	if (*val) {
   18.68 +		scf_simple_prop_free(prop);
   18.69 +		Py_INCREF(Py_True);
   18.70 +		return (Py_True);
   18.71 +	}
   18.72 +
   18.73 +	scf_simple_prop_free(prop);
   18.74 +	Py_INCREF(Py_False);
   18.75 +	return (Py_False);
   18.76 +}
   18.77 +
   18.78 +static PyObject *
   18.79 +pyscf_get_int(PyObject *o, PyObject *args, PyObject *kwargs)
   18.80 +{
   18.81 +	static char *kwlist[] = { "name", NULL };
   18.82 +	scf_simple_prop_t *prop;
   18.83 +	PyObject *obj;
   18.84 +	int64_t *val;
   18.85 +	char *name;
   18.86 +
   18.87 +	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
   18.88 +		return (NULL);
   18.89 +
   18.90 +	prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
   18.91 +
   18.92 +	if (prop == NULL)
   18.93 +		return (scf_exception("scf_simple_prop_get() failed", name));
   18.94 +
   18.95 +	if ((val = scf_simple_prop_next_integer(prop)) == NULL)
   18.96 +		return (scf_exception("scf_simple_prop_next_integer() failed",
   18.97 +		    name));
   18.98 +
   18.99 +	obj = PyInt_FromLong((long)*val);
  18.100 +	scf_simple_prop_free(prop);
  18.101 +	return (obj);
  18.102 +}
  18.103 +
  18.104 +static PyObject *
  18.105 +pyscf_get_string(PyObject *o, PyObject *args, PyObject *kwargs)
  18.106 +{
  18.107 +	static char *kwlist[] = { "name", NULL };
  18.108 +	scf_simple_prop_t *prop;
  18.109 +	PyObject *obj;
  18.110 +	char *name;
  18.111 +	char *str;
  18.112 +
  18.113 +	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
  18.114 +		return (NULL);
  18.115 +
  18.116 +	prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
  18.117 +
  18.118 +	if (prop == NULL)
  18.119 +		return (scf_exception("scf_simple_prop_get() failed", name));
  18.120 +
  18.121 +	if ((str = scf_simple_prop_next_astring(prop)) == NULL) {
  18.122 +		scf_simple_prop_free(prop);
  18.123 +		return (scf_exception("scf_simple_prop_next_astring() failed",
  18.124 +		    name));
  18.125 +	}
  18.126 +
  18.127 +	obj = PyString_FromString(str);
  18.128 +	scf_simple_prop_free(prop);
  18.129 +	return (obj);
  18.130 +}
  18.131 +
  18.132 +PyDoc_STRVAR(pyscf_get_bool__doc__,
  18.133 +   "get_bool(name) - get the value of the named boolean property");
  18.134 +PyDoc_STRVAR(pyscf_get_int__doc__,
  18.135 +   "get_int(name) - get the value of the named integer property");
  18.136 +PyDoc_STRVAR(pyscf_get_string__doc__,
  18.137 +   "get_string(name) - get the value of the named string property");
  18.138 +
  18.139 +static struct PyMethodDef pyscf_module_methods[] = {
  18.140 +	{ "get_bool", (PyCFunction) pyscf_get_bool,
  18.141 +	  METH_VARARGS|METH_KEYWORDS, pyscf_get_bool__doc__ },
  18.142 +	{ "get_int", (PyCFunction) pyscf_get_int,
  18.143 +	  METH_VARARGS|METH_KEYWORDS, pyscf_get_int__doc__ },
  18.144 +	{ "get_string", (PyCFunction) pyscf_get_string,
  18.145 +	  METH_VARARGS|METH_KEYWORDS, pyscf_get_string__doc__ },
  18.146 +	{ NULL, NULL, 0, NULL }	
  18.147 +};
  18.148 +
  18.149 +PyMODINIT_FUNC
  18.150 +initscf(void)
  18.151 +{
  18.152 +	PyObject *m;
  18.153 +	m = Py_InitModule("scf", pyscf_module_methods);
  18.154 +
  18.155 +	scf_exc = PyErr_NewException("scf.error", NULL, NULL);
  18.156 +	Py_INCREF(scf_exc);
  18.157 +	PyModule_AddObject(m, "error", scf_exc);
  18.158 +	PyModule_AddIntConstant(m, "SCF_ERROR_NOT_FOUND", SCF_ERROR_NOT_FOUND);
  18.159 +}
    19.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Wed Jan 17 21:45:34 2007 -0700
    19.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Thu Jan 18 18:25:04 2007 +0000
    19.3 @@ -160,6 +160,20 @@ static PyObject *pyxc_domain_destroy(XcO
    19.4      return dom_op(self, args, xc_domain_destroy);
    19.5  }
    19.6  
    19.7 +static PyObject *pyxc_domain_shutdown(XcObject *self, PyObject *args)
    19.8 +{
    19.9 +    uint32_t dom, reason;
   19.10 +
   19.11 +    if (!PyArg_ParseTuple(args, "ii", &dom, &reason))
   19.12 +      return NULL;
   19.13 +
   19.14 +    if (xc_domain_shutdown(self->xc_handle, dom, reason) != 0)
   19.15 +        return pyxc_error_to_exception();
   19.16 +    
   19.17 +    Py_INCREF(zero);
   19.18 +    return zero;
   19.19 +}
   19.20 +
   19.21  
   19.22  static PyObject *pyxc_vcpu_setaffinity(XcObject *self,
   19.23                                         PyObject *args,
   19.24 @@ -1029,6 +1043,14 @@ static PyMethodDef pyxc_methods[] = {
   19.25        " dom [int]:    Identifier of domain to be destroyed.\n\n"
   19.26        "Returns: [int] 0 on success; -1 on error.\n" },
   19.27  
   19.28 +    { "domain_shutdown", 
   19.29 +      (PyCFunction)pyxc_domain_shutdown,
   19.30 +      METH_VARARGS, "\n"
   19.31 +      "Shutdown a domain.\n"
   19.32 +      " dom       [int, 0]:      Domain identifier to use.\n"
   19.33 +      " reason     [int, 0]:      Reason for shutdown.\n"
   19.34 +      "Returns: [int] 0 on success; -1 on error.\n" },
   19.35 +
   19.36      { "vcpu_setaffinity", 
   19.37        (PyCFunction)pyxc_vcpu_setaffinity, 
   19.38        METH_VARARGS | METH_KEYWORDS, "\n"
    20.1 --- a/tools/python/xen/util/xmlrpclib2.py	Wed Jan 17 21:45:34 2007 -0700
    20.2 +++ b/tools/python/xen/util/xmlrpclib2.py	Thu Jan 18 18:25:04 2007 +0000
    20.3 @@ -256,6 +256,7 @@ class UnixXMLRPCRequestHandler(XMLRPCReq
    20.4  
    20.5  class UnixXMLRPCServer(TCPXMLRPCServer):
    20.6      address_family = socket.AF_UNIX
    20.7 +    allow_address_reuse = True
    20.8  
    20.9      def __init__(self, addr, allowed, xenapi, logRequests = 1):
   20.10          mkdir.parents(os.path.dirname(addr), stat.S_IRWXU, True)
    21.1 --- a/tools/python/xen/web/httpserver.py	Wed Jan 17 21:45:34 2007 -0700
    21.2 +++ b/tools/python/xen/web/httpserver.py	Thu Jan 18 18:25:04 2007 +0000
    21.3 @@ -294,8 +294,6 @@ class HttpServer:
    21.4  
    21.5      backlog = 5
    21.6  
    21.7 -    closed = False
    21.8 -
    21.9      def __init__(self, root, interface, port=8080):
   21.10          self.root = root
   21.11          self.interface = interface
   21.12 @@ -303,6 +301,7 @@ class HttpServer:
   21.13          # ready indicates when we are ready to begin accept connections
   21.14          # it should be set after a successful bind
   21.15          self.ready = False
   21.16 +        self.closed = False
   21.17  
   21.18      def run(self):
   21.19          self.bind()
   21.20 @@ -317,7 +316,6 @@ class HttpServer:
   21.21      def stop(self):
   21.22          self.close()
   21.23  
   21.24 -
   21.25      def bind(self):
   21.26          self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   21.27          flags = fcntl.fcntl(self.socket.fileno(), fcntl.F_GETFD)
   21.28 @@ -334,7 +332,10 @@ class HttpServer:
   21.29  
   21.30      def close(self):
   21.31          self.closed = True
   21.32 +        self.ready = False
   21.33          try:
   21.34 +            # shutdown socket explicitly to allow reuse
   21.35 +            self.socket.shutdown(socket.SHUT_RDWR)
   21.36              self.socket.close()
   21.37          except:
   21.38              pass
   21.39 @@ -345,6 +346,9 @@ class HttpServer:
   21.40      def getResource(self, req):
   21.41          return self.root.getRequestResource(req)
   21.42  
   21.43 +    def shutdown(self):
   21.44 +        self.close()
   21.45 +
   21.46  
   21.47  class UnixHttpServer(HttpServer):
   21.48  
    22.1 --- a/tools/python/xen/xend/Vifctl.py	Wed Jan 17 21:45:34 2007 -0700
    22.2 +++ b/tools/python/xen/xend/Vifctl.py	Thu Jan 18 18:25:04 2007 +0000
    22.3 @@ -20,7 +20,7 @@
    22.4  """
    22.5  import os
    22.6  
    22.7 -import XendRoot
    22.8 +import XendOptions
    22.9  
   22.10  
   22.11  def network(op):
   22.12 @@ -30,7 +30,7 @@ def network(op):
   22.13      """
   22.14      if op not in ['start', 'stop']:
   22.15          raise ValueError('Invalid operation: ' + op)
   22.16 -    script = XendRoot.instance().get_network_script()
   22.17 +    script = XendOptions.instance().get_network_script()
   22.18      if script:
   22.19          script.insert(1, op)
   22.20          os.spawnv(os.P_WAIT, script[0], script)
    23.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Wed Jan 17 21:45:34 2007 -0700
    23.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Thu Jan 18 18:25:04 2007 +0000
    23.3 @@ -22,11 +22,14 @@ from xen.xend.XendConfig import XendConf
    23.4  from xen.xend.XendConstants import *
    23.5  
    23.6  SIGNATURE = "LinuxGuestRecord"
    23.7 +QEMU_SIGNATURE = "QemuDeviceModelRecord"
    23.8 +dm_batch = 512
    23.9  XC_SAVE = "xc_save"
   23.10  XC_RESTORE = "xc_restore"
   23.11  
   23.12  
   23.13  sizeof_int = calcsize("i")
   23.14 +sizeof_unsigned_int = calcsize("I")
   23.15  sizeof_unsigned_long = calcsize("L")
   23.16  
   23.17  
   23.18 @@ -69,6 +72,11 @@ def save(fd, dominfo, network, live, dst
   23.19                      "could not write guest state file: config len")
   23.20          write_exact(fd, config, "could not write guest state file: config")
   23.21  
   23.22 +        image_cfg = dominfo.info.get('image', {})
   23.23 +        hvm = image_cfg.has_key('hvm')
   23.24 +
   23.25 +        if hvm:
   23.26 +            log.info("save hvm domain")
   23.27          # xc_save takes three customization parameters: maxit, max_f, and
   23.28          # flags the last controls whether or not save is 'live', while the
   23.29          # first two further customize behaviour when 'live' save is
   23.30 @@ -76,7 +84,7 @@ def save(fd, dominfo, network, live, dst
   23.31          # libxenguest; see the comments and/or code in xc_linux_save() for
   23.32          # more information.
   23.33          cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
   23.34 -               str(dominfo.getDomid()), "0", "0", str(int(live)) ]
   23.35 +               str(dominfo.getDomid()), "0", "0", str(int(live) | (int(hvm) << 2)) ]
   23.36          log.debug("[xc_save]: %s", string.join(cmd))
   23.37  
   23.38          def saveInputHandler(line, tochild):
   23.39 @@ -90,12 +98,29 @@ def save(fd, dominfo, network, live, dst
   23.40                  log.info("Domain %d suspended.", dominfo.getDomid())
   23.41                  dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP3,
   23.42                                         domain_name)
   23.43 +                #send signal to device model for save
   23.44 +                if hvm:
   23.45 +                    log.info("release_devices for hvm domain")
   23.46 +                    dominfo._releaseDevices(True)
   23.47                  tochild.write("done\n")
   23.48                  tochild.flush()
   23.49                  log.debug('Written done')
   23.50  
   23.51          forkHelper(cmd, fd, saveInputHandler, False)
   23.52  
   23.53 +        # put qemu device model state
   23.54 +        if hvm:
   23.55 +            write_exact(fd, QEMU_SIGNATURE, "could not write qemu signature")
   23.56 +            qemu_fd = os.open("/tmp/xen.qemu-dm.%d" % dominfo.getDomid(), os.O_RDONLY)
   23.57 +            while True:
   23.58 +                buf = os.read(qemu_fd, dm_batch)
   23.59 +                if len(buf):
   23.60 +                    write_exact(fd, buf, "could not write device model state")
   23.61 +                else:
   23.62 +                    break
   23.63 +            os.close(qemu_fd)
   23.64 +            os.remove("/tmp/xen.qemu-dm.%d" % dominfo.getDomid())
   23.65 +
   23.66          dominfo.destroyDomain()
   23.67          try:
   23.68              dominfo.setName(domain_name)
   23.69 @@ -149,19 +174,49 @@ def restore(xd, fd, dominfo = None, paus
   23.70  
   23.71      nr_pfns = (dominfo.getMemoryTarget() + 3) / 4 
   23.72  
   23.73 +    # if hvm, pass mem size to calculate the store_mfn
   23.74 +    hvm  = 0
   23.75 +    apic = 0
   23.76 +    pae  = 0
   23.77 +    image_cfg = dominfo.info.get('image', {})
   23.78 +    hvm  = image_cfg.has_key('hvm')
   23.79 +    if hvm:
   23.80 +        # the 'memory' in config has been removed
   23.81 +        hvm  = dominfo.info['memory_static_min']
   23.82 +        apic = dominfo.info['image']['hvm'].get('apic', 0)
   23.83 +        pae  = dominfo.info['image']['hvm'].get('pae',  0)
   23.84 +        log.info("restore hvm domain %d, mem=%d, apic=%d, pae=%d",
   23.85 +                 dominfo.domid, hvm, apic, pae)
   23.86 +
   23.87      try:
   23.88 -        l = read_exact(fd, sizeof_unsigned_long,
   23.89 -                       "not a valid guest state file: pfn count read")
   23.90 +        if hvm:
   23.91 +            l = read_exact(fd, sizeof_unsigned_int,
   23.92 +                           "not a valid hvm guest state file: pfn count read")
   23.93 +            nr_pfns = unpack("I", l)[0]    # native sizeof int
   23.94 +        else: 
   23.95 +            l = read_exact(fd, sizeof_unsigned_long,
   23.96 +                           "not a valid guest state file: pfn count read")
   23.97 +
   23.98          max_pfn = unpack("L", l)[0]    # native sizeof long
   23.99          if max_pfn > 16*1024*1024:     # XXX 
  23.100              raise XendError(
  23.101                  "not a valid guest state file: pfn count out of range")
  23.102  
  23.103 -        balloon.free(xc.pages_to_kib(nr_pfns))
  23.104 +        shadow = dominfo.info['shadow_memory']
  23.105 +        log.debug("restore:shadow=0x%x, _static_max=0x%x, _static_min=0x%x, "
  23.106 +                  "nr_pfns=0x%x.", dominfo.info['shadow_memory'],
  23.107 +                  dominfo.info['memory_static_max'],
  23.108 +                  dominfo.info['memory_static_min'], nr_pfns)
  23.109 +
  23.110 +
  23.111 +        balloon.free(xc.pages_to_kib(nr_pfns) + shadow * 1024)
  23.112 +
  23.113 +        shadow_cur = xc.shadow_mem_control(dominfo.getDomid(), shadow)
  23.114 +        dominfo.info['shadow_memory'] = shadow_cur
  23.115  
  23.116          cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE),
  23.117                          fd, dominfo.getDomid(), max_pfn,
  23.118 -                        store_port, console_port])
  23.119 +                        store_port, console_port, hvm, pae, apic])
  23.120          log.debug("[xc_restore]: %s", string.join(cmd))
  23.121  
  23.122          handler = RestoreInputHandler()
  23.123 @@ -171,10 +226,30 @@ def restore(xd, fd, dominfo = None, paus
  23.124          if handler.store_mfn is None or handler.console_mfn is None:
  23.125              raise XendError('Could not read store/console MFN')
  23.126  
  23.127 -        os.read(fd, 1)           # Wait for source to close connection
  23.128          dominfo.waitForDevices() # Wait for backends to set up
  23.129          if not paused:
  23.130              dominfo.unpause()
  23.131 +
  23.132 +         # get qemu state and create a tmp file for dm restore
  23.133 +        if hvm:
  23.134 +            qemu_signature = read_exact(fd, len(QEMU_SIGNATURE),
  23.135 +                                        "invalid device model signature read")
  23.136 +            if qemu_signature != QEMU_SIGNATURE:
  23.137 +                raise XendError("not a valid device model state: found '%s'" %
  23.138 +                                qemu_signature)
  23.139 +            qemu_fd = os.open("/tmp/xen.qemu-dm.%d" % dominfo.getDomid(),
  23.140 +                              os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
  23.141 +            while True:
  23.142 +                buf = os.read(fd, dm_batch)
  23.143 +                if len(buf):
  23.144 +                    write_exact(qemu_fd, buf,
  23.145 +                                "could not write dm state to tmp file")
  23.146 +                else:
  23.147 +                    break
  23.148 +            os.close(qemu_fd)
  23.149 +
  23.150 +
  23.151 +        os.read(fd, 1)           # Wait for source to close connection
  23.152          
  23.153          dominfo.completeRestore(handler.store_mfn, handler.console_mfn)
  23.154          
    24.1 --- a/tools/python/xen/xend/XendConfig.py	Wed Jan 17 21:45:34 2007 -0700
    24.2 +++ b/tools/python/xen/xend/XendConfig.py	Thu Jan 18 18:25:04 2007 +0000
    24.3 @@ -78,6 +78,25 @@ def scrub_password(data):
    24.4      else:
    24.5          return data
    24.6  
    24.7 +#
    24.8 +# CPU fields:
    24.9 +#
   24.10 +# vcpus_number -- the maximum number of vcpus that this domain may ever have.
   24.11 +#                 aka XendDomainInfo.getVCpuCount().
   24.12 +# vcpus        -- the legacy configuration name for above.
   24.13 +# max_vcpu_id  -- vcpus_number - 1.  This is given to us by Xen.
   24.14 +#
   24.15 +# cpus         -- the list of pCPUs available to each vCPU.
   24.16 +#
   24.17 +#   vcpu_avail:  a bitmap telling the guest domain whether it may use each of
   24.18 +#                its VCPUs.  This is translated to
   24.19 +#                <dompath>/cpu/<id>/availability = {online,offline} for use
   24.20 +#                by the guest domain.
   24.21 +# online_vpcus -- the number of VCPUs currently up, as reported by Xen.  This
   24.22 +#                 is changed by changing vcpu_avail, and waiting for the
   24.23 +#                 domain to respond.
   24.24 +#
   24.25 +
   24.26  
   24.27  # Mapping from XendConfig configuration keys to the old
   24.28  # legacy configuration keys that map directly.
   24.29 @@ -185,7 +204,7 @@ LEGACY_CFG_TYPES = {
   24.30      'uuid':          str,
   24.31      'name':          str,
   24.32      'vcpus':         int,
   24.33 -    'vcpu_avail':    int,
   24.34 +    'vcpu_avail':    long,
   24.35      'memory':        int,
   24.36      'shadow_memory': int,
   24.37      'maxmem':        int,
   24.38 @@ -355,9 +374,6 @@ class XendConfig(dict):
   24.39              'cpu_weight': 256,
   24.40              'cpu_cap': 0,
   24.41              'vcpus_number': 1,
   24.42 -            'online_vcpus': 1,
   24.43 -            'max_vcpu_id': 0,
   24.44 -            'vcpu_avail': 1,
   24.45              'console_refs': [],
   24.46              'vif_refs': [],
   24.47              'vbd_refs': [],
   24.48 @@ -389,7 +405,7 @@ class XendConfig(dict):
   24.49                                        event)
   24.50  
   24.51      def _vcpus_sanity_check(self):
   24.52 -        if self.get('vcpus_number') != None:
   24.53 +        if 'vcpus_number' in self and 'vcpu_avail' not in self:
   24.54              self['vcpu_avail'] = (1 << self['vcpus_number']) - 1
   24.55  
   24.56      def _uuid_sanity_check(self):
   24.57 @@ -405,7 +421,7 @@ class XendConfig(dict):
   24.58      def _dominfo_to_xapi(self, dominfo):
   24.59          self['domid'] = dominfo['domid']
   24.60          self['online_vcpus'] = dominfo['online_vcpus']
   24.61 -        self['max_vcpu_id'] = dominfo['max_vcpu_id']
   24.62 +        self['vcpus_number'] = dominfo['max_vcpu_id'] + 1
   24.63          self['memory_dynamic_min'] = (dominfo['mem_kb'] + 1023)/1024
   24.64          self['memory_dynamic_max'] = (dominfo['maxmem_kb'] + 1023)/1024
   24.65          self['cpu_time'] = dominfo['cpu_time']/1e9
   24.66 @@ -636,9 +652,6 @@ class XendConfig(dict):
   24.67          self['memory_dynamic_max'] = self['memory_static_max']
   24.68          self['memory_dynamic_min'] = self['memory_static_min']
   24.69  
   24.70 -        # make sure max_vcpu_id is set correctly
   24.71 -        self['max_vcpu_id'] = self['vcpus_number'] - 1
   24.72 -
   24.73          # set device references in the configuration
   24.74          self['devices'] = cfg.get('devices', {})
   24.75          
   24.76 @@ -720,13 +733,11 @@ class XendConfig(dict):
   24.77          _set_cfg_if_exists('on_xend_stop')
   24.78          _set_cfg_if_exists('on_xend_start')
   24.79          _set_cfg_if_exists('vcpu_avail')
   24.80 -        _set_cfg_if_exists('max_vcpu_id') # needed for vcpuDomDetails
   24.81          _set_cfg_if_exists('cpu_weight')
   24.82          _set_cfg_if_exists('cpu_cap')
   24.83          
   24.84          # Parse and store runtime configuration 
   24.85          _set_cfg_if_exists('start_time')
   24.86 -        _set_cfg_if_exists('online_vcpus')
   24.87          _set_cfg_if_exists('cpu_time')
   24.88          _set_cfg_if_exists('shutdown_reason')
   24.89          _set_cfg_if_exists('up_time')
   24.90 @@ -1115,19 +1126,17 @@ class XendConfig(dict):
   24.91          # configuration
   24.92          log.debug("update_with_image_sxp(%s)" % scrub_password(image_sxp))
   24.93  
   24.94 -        kernel_args = ""
   24.95 +        # user-specified args must come last: previous releases did this and
   24.96 +        # some domU kernels rely upon the ordering.
   24.97 +        kernel_args = sxp.child_value(image_sxp, 'args', '')
   24.98  
   24.99          # attempt to extract extra arguments from SXP config
  24.100          arg_ip = sxp.child_value(image_sxp, 'ip')
  24.101          if arg_ip and not re.search(r'ip=[^ ]+', kernel_args):
  24.102 -            kernel_args += 'ip=%s ' % arg_ip
  24.103 +            kernel_args = 'ip=%s ' % arg_ip + kernel_args
  24.104          arg_root = sxp.child_value(image_sxp, 'root')
  24.105          if arg_root and not re.search(r'root=', kernel_args):
  24.106 -            kernel_args += 'root=%s ' % arg_root
  24.107 -
  24.108 -        # user-specified args must come last: previous releases did this and
  24.109 -        # some domU kernels rely upon the ordering.
  24.110 -        kernel_args += sxp.child_value(image_sxp, 'args', '')
  24.111 +            kernel_args = 'root=%s ' % arg_root + kernel_args
  24.112  
  24.113          if bootloader:
  24.114              self['_temp_using_bootloader'] = '1'
    25.1 --- a/tools/python/xen/xend/XendDomain.py	Wed Jan 17 21:45:34 2007 -0700
    25.2 +++ b/tools/python/xen/xend/XendDomain.py	Thu Jan 18 18:25:04 2007 +0000
    25.3 @@ -32,7 +32,7 @@ import threading
    25.4  import xen.lowlevel.xc
    25.5  
    25.6  
    25.7 -from xen.xend import XendRoot, XendCheckpoint, XendDomainInfo
    25.8 +from xen.xend import XendOptions, XendCheckpoint, XendDomainInfo
    25.9  from xen.xend.PrettyPrint import prettyprint
   25.10  from xen.xend.XendConfig import XendConfig
   25.11  from xen.xend.XendError import XendError, XendInvalidDomain, VmError
   25.12 @@ -51,7 +51,7 @@ from xen.util import mkdir, security
   25.13  from xen.xend import uuid
   25.14  
   25.15  xc = xen.lowlevel.xc.xc()
   25.16 -xroot = XendRoot.instance() 
   25.17 +xoptions = XendOptions.instance() 
   25.18  
   25.19  __all__ = [ "XendDomain" ]
   25.20  
   25.21 @@ -214,7 +214,7 @@ class XendDomain:
   25.22          @rtype: String
   25.23          @return: Path.
   25.24          """
   25.25 -        dom_path = xroot.get_xend_domains_path()
   25.26 +        dom_path = xoptions.get_xend_domains_path()
   25.27          if domuuid:
   25.28              dom_path = os.path.join(dom_path, domuuid)
   25.29          return dom_path
   25.30 @@ -361,7 +361,7 @@ class XendDomain:
   25.31  
   25.32      def _setDom0CPUCount(self):
   25.33          """Sets the number of VCPUs dom0 has. Retreived from the
   25.34 -        Xend configuration, L{XendRoot}.
   25.35 +        Xend configuration, L{XendOptions}.
   25.36  
   25.37          @requires: Expects to be protected by domains_lock.
   25.38          @rtype: None
   25.39 @@ -369,7 +369,7 @@ class XendDomain:
   25.40          dom0 = self.privilegedDomain()
   25.41  
   25.42          # get max number of vcpus to use for dom0 from config
   25.43 -        target = int(xroot.get_dom0_vcpus())
   25.44 +        target = int(xoptions.get_dom0_vcpus())
   25.45          log.debug("number of vcpus to use is %d", target)
   25.46     
   25.47          # target == 0 means use all processors
   25.48 @@ -1164,7 +1164,7 @@ class XendDomain:
   25.49              dominfo.checkLiveMigrateMemory()
   25.50  
   25.51          if port == 0:
   25.52 -            port = xroot.get_xend_relocation_port()
   25.53 +            port = xoptions.get_xend_relocation_port()
   25.54          try:
   25.55              sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   25.56              sock.connect((dst, port))
    26.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Wed Jan 17 21:45:34 2007 -0700
    26.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Thu Jan 18 18:25:04 2007 +0000
    26.3 @@ -38,7 +38,7 @@ from xen.util.blkif import blkdev_uname_
    26.4  from xen.util import security
    26.5  
    26.6  from xen.xend import balloon, sxp, uuid, image, arch, osdep
    26.7 -from xen.xend import XendRoot, XendNode, XendConfig
    26.8 +from xen.xend import XendOptions, XendNode, XendConfig
    26.9  
   26.10  from xen.xend.XendConfig import scrub_password
   26.11  from xen.xend.XendBootloader import bootloader
   26.12 @@ -54,31 +54,12 @@ MIGRATE_TIMEOUT = 30.0
   26.13  BOOTLOADER_LOOPBACK_DEVICE = '/dev/xvdp'
   26.14  
   26.15  xc = xen.lowlevel.xc.xc()
   26.16 -xroot = XendRoot.instance()
   26.17 +xoptions = XendOptions.instance()
   26.18  
   26.19  log = logging.getLogger("xend.XendDomainInfo")
   26.20  #log.setLevel(logging.TRACE)
   26.21  
   26.22  
   26.23 -#
   26.24 -# There are a number of CPU-related fields:
   26.25 -#
   26.26 -#   vcpus:       the number of virtual CPUs this domain is configured to use.
   26.27 -#   vcpu_avail:  a bitmap telling the guest domain whether it may use each of
   26.28 -#                its VCPUs.  This is translated to
   26.29 -#                <dompath>/cpu/<id>/availability = {online,offline} for use
   26.30 -#                by the guest domain.
   26.31 -#   cpumap:      a list of bitmaps, one for each VCPU, giving the physical
   26.32 -#                CPUs that that VCPU may use.
   26.33 -#   cpu:         a configuration setting requesting that VCPU 0 is pinned to
   26.34 -#                the specified physical CPU.
   26.35 -#
   26.36 -# vcpus and vcpu_avail settings persist with the VM (i.e. they are persistent
   26.37 -# across save, restore, migrate, and restart).  The other settings are only
   26.38 -# specific to the domain, so are lost when the VM moves.
   26.39 -#
   26.40 -
   26.41 -
   26.42  def create(config):
   26.43      """Creates and start a VM using the supplied configuration. 
   26.44  
   26.45 @@ -451,6 +432,16 @@ class XendDomainInfo:
   26.46          self._removeVm('xend/previous_restart_time')
   26.47          self.storeDom("control/shutdown", reason)
   26.48  
   26.49 +        ## shutdown hypercall for hvm domain desides xenstore write
   26.50 +        image_cfg = self.info.get('image', {})
   26.51 +        hvm = image_cfg.has_key('hvm')
   26.52 +        if hvm:
   26.53 +            for code in DOMAIN_SHUTDOWN_REASONS.keys():
   26.54 +                if DOMAIN_SHUTDOWN_REASONS[code] == reason:
   26.55 +                    break
   26.56 +            xc.domain_shutdown(self.domid, code)
   26.57 +
   26.58 +
   26.59      def pause(self):
   26.60          """Pause domain
   26.61          
   26.62 @@ -614,7 +605,7 @@ class XendDomainInfo:
   26.63                      ['name',       self.info['name_label']],
   26.64                      ['vcpu_count', self.info['vcpus_number']]]
   26.65  
   26.66 -            for i in range(0, self.info['max_vcpu_id']+1):
   26.67 +            for i in range(0, self.info['vcpus_number']):
   26.68                  info = xc.vcpu_getinfo(self.domid, i)
   26.69  
   26.70                  sxpr.append(['vcpu',
   26.71 @@ -739,7 +730,7 @@ class XendDomainInfo:
   26.72              'domid':              str(self.domid),
   26.73              'vm':                 self.vmpath,
   26.74              'name':               self.info['name_label'],
   26.75 -            'console/limit':      str(xroot.get_console_limit() * 1024),
   26.76 +            'console/limit':      str(xoptions.get_console_limit() * 1024),
   26.77              'memory/target':      str(self.info['memory_static_min'] * 1024)
   26.78              }
   26.79  
   26.80 @@ -898,8 +889,9 @@ class XendDomainInfo:
   26.81                  self._writeDom(self._vcpuDomDetails())
   26.82          else:
   26.83              self.info['vcpus_number'] = vcpus
   26.84 -            self.info['online_vcpus'] = vcpus
   26.85              xen.xend.XendDomain.instance().managed_config_save(self)
   26.86 +        log.info("Set VCPU count on domain %s to %d", self.info['name_label'],
   26.87 +                 vcpus)
   26.88  
   26.89      def getLabel(self):
   26.90          return security.get_security_info(self.info, 'label')
   26.91 @@ -976,7 +968,7 @@ class XendDomainInfo:
   26.92                           self.info['name_label'], self.domid)
   26.93                  self._writeVm(LAST_SHUTDOWN_REASON, 'crash')
   26.94  
   26.95 -                if xroot.get_enable_dump():
   26.96 +                if xoptions.get_enable_dump():
   26.97                      try:
   26.98                          self.dumpCore()
   26.99                      except XendError:
  26.100 @@ -1228,8 +1220,11 @@ class XendDomainInfo:
  26.101          if self.image:
  26.102              self.image.createDeviceModel()
  26.103  
  26.104 -    def _releaseDevices(self):
  26.105 +    def _releaseDevices(self, suspend = False):
  26.106          """Release all domain's devices.  Nothrow guarantee."""
  26.107 +        if suspend and self.image:
  26.108 +            self.image.destroy(suspend)
  26.109 +            return
  26.110  
  26.111          while True:
  26.112              t = xstransact("%s/device" % self.dompath)
  26.113 @@ -1381,7 +1376,7 @@ class XendDomainInfo:
  26.114              # this is done prior to memory allocation to aide in memory
  26.115              # distribution for NUMA systems.
  26.116              if self.info['cpus'] is not None and len(self.info['cpus']) > 0:
  26.117 -                for v in range(0, self.info['max_vcpu_id']+1):
  26.118 +                for v in range(0, self.info['vcpus_number']):
  26.119                      xc.vcpu_setaffinity(self.domid, v, self.info['cpus'])
  26.120  
  26.121              # Use architecture- and image-specific calculations to determine
  26.122 @@ -1395,6 +1390,7 @@ class XendDomainInfo:
  26.123                  self.info['shadow_memory'] * 1024,
  26.124                  self.info['memory_static_max'] * 1024)
  26.125  
  26.126 +            log.debug("_initDomain:shadow_memory=0x%x, memory_static_max=0x%x, memory_static_min=0x%x.", self.info['shadow_memory'], self.info['memory_static_max'], self.info['memory_static_min'],)
  26.127              # Round shadow up to a multiple of a MiB, as shadow_mem_control
  26.128              # takes MiB and we must not round down and end up under-providing.
  26.129              shadow = ((shadow + 1023) / 1024) * 1024
  26.130 @@ -1494,6 +1490,16 @@ class XendDomainInfo:
  26.131          self.console_mfn = console_mfn
  26.132  
  26.133          self._introduceDomain()
  26.134 +        image_cfg = self.info.get('image', {})
  26.135 +        hvm = image_cfg.has_key('hvm')
  26.136 +        if hvm:
  26.137 +            self.image = image.create(self,
  26.138 +                    self.info,
  26.139 +                    self.info['image'],
  26.140 +                    self.info['devices'])
  26.141 +            if self.image:
  26.142 +                self.image.createDeviceModel(True)
  26.143 +                self.image.register_shutdown_watch()
  26.144          self._storeDomDetails()
  26.145          self._registerWatches()
  26.146          self.refreshShutdown()
  26.147 @@ -2028,8 +2034,8 @@ class XendDomainInfo:
  26.148          # TODO: spec says that key is int, however, python does not allow
  26.149          #       non-string keys to dictionaries.
  26.150          vcpu_util = {}
  26.151 -        if 'max_vcpu_id' in self.info and self.domid != None:
  26.152 -            for i in range(0, self.info['max_vcpu_id']+1):
  26.153 +        if 'vcpus_number' in self.info and self.domid != None:
  26.154 +            for i in range(0, self.info['vcpus_number']):
  26.155                  info = xc.vcpu_getinfo(self.domid, i)
  26.156                  vcpu_util[str(i)] = info['cpu_time']/1000000000.0
  26.157                  
    27.1 --- a/tools/python/xen/xend/XendNode.py	Wed Jan 17 21:45:34 2007 -0700
    27.2 +++ b/tools/python/xen/xend/XendNode.py	Thu Jan 18 18:25:04 2007 +0000
    27.3 @@ -24,7 +24,7 @@ from xen.util import Brctl
    27.4  
    27.5  from xen.xend import uuid
    27.6  from xen.xend.XendError import XendError, NetworkAlreadyConnected
    27.7 -from xen.xend.XendRoot import instance as xendroot
    27.8 +from xen.xend.XendOptions import instance as xendoptions
    27.9  from xen.xend.XendStorageRepository import XendStorageRepository
   27.10  from xen.xend.XendLogging import log
   27.11  from xen.xend.XendPIF import *
   27.12 @@ -45,7 +45,7 @@ class XendNode:
   27.13          """
   27.14          
   27.15          self.xc = xen.lowlevel.xc.xc()
   27.16 -        self.state_store = XendStateStore(xendroot().get_xend_state_path())
   27.17 +        self.state_store = XendStateStore(xendoptions().get_xend_state_path())
   27.18  
   27.19          # load host state from XML file
   27.20          saved_host = self.state_store.load_state('host')
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/tools/python/xen/xend/XendOptions.py	Thu Jan 18 18:25:04 2007 +0000
    28.3 @@ -0,0 +1,373 @@
    28.4 +#============================================================================
    28.5 +# This library is free software; you can redistribute it and/or
    28.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
    28.7 +# License as published by the Free Software Foundation.
    28.8 +#
    28.9 +# This library is distributed in the hope that it will be useful,
   28.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   28.12 +# Lesser General Public License for more details.
   28.13 +#
   28.14 +# You should have received a copy of the GNU Lesser General Public
   28.15 +# License along with this library; if not, write to the Free Software
   28.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   28.17 +#============================================================================
   28.18 +# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
   28.19 +# Copyright (C) 2005 XenSource Ltd
   28.20 +#============================================================================
   28.21 +
   28.22 +"""Xend root class.
   28.23 +Creates the servers and handles configuration.
   28.24 +
   28.25 +Other classes get config variables by importing this module,
   28.26 +using instance() to get a XendOptions instance, and then
   28.27 +the config functions (e.g. get_xend_port()) to get
   28.28 +configured values.
   28.29 +"""
   28.30 +
   28.31 +import os
   28.32 +import os.path
   28.33 +import string
   28.34 +import sys
   28.35 +
   28.36 +from xen.xend import sxp, osdep, XendLogging
   28.37 +from xen.xend.XendError import XendError
   28.38 +
   28.39 +if os.uname()[0] == 'SunOS':
   28.40 +    from xen.lowlevel import scf
   28.41 +
   28.42 +class XendOptions:
   28.43 +    """Configuration options."""
   28.44 +
   28.45 +    """Where network control scripts live."""
   28.46 +    network_script_dir = osdep.scripts_dir
   28.47 +
   28.48 +    """Where block control scripts live."""
   28.49 +    block_script_dir = osdep.scripts_dir
   28.50 +
   28.51 +    """Default path to the log file. """
   28.52 +    logfile_default = "/var/log/xen/xend.log"
   28.53 +
   28.54 +    """Default level of information to be logged."""
   28.55 +    loglevel_default = 'DEBUG'
   28.56 +
   28.57 +    """Default Xen-API server configuration. """
   28.58 +    xen_api_server_default = [['unix']]
   28.59 +
   28.60 +    """Default for the flag indicating whether xend should run an http server
   28.61 +    (deprecated)."""
   28.62 +    xend_http_server_default = 'no'
   28.63 +
   28.64 +    xend_tcp_xmlrpc_server_default = 'no'
   28.65 +
   28.66 +    xend_unix_xmlrpc_server_default = 'yes'
   28.67 +
   28.68 +    """Default interface address xend listens at. """
   28.69 +    xend_address_default      = ''
   28.70 +
   28.71 +    """Default for the flag indicating whether xend should run a relocation server."""
   28.72 +    xend_relocation_server_default = 'no'
   28.73 +
   28.74 +    """Default interface address the xend relocation server listens at. """
   28.75 +    xend_relocation_address_default = ''
   28.76 +
   28.77 +    """Default port xend serves HTTP at. """
   28.78 +    xend_port_default         = 8000
   28.79 +
   28.80 +    """Default port xend serves relocation at. """
   28.81 +    xend_relocation_port_default = 8002
   28.82 +
   28.83 +    xend_relocation_hosts_allow_default = ''
   28.84 +
   28.85 +    """Default for the flag indicating whether xend should run a unix-domain
   28.86 +    server (deprecated)."""
   28.87 +    xend_unix_server_default = 'no'
   28.88 +
   28.89 +    """Default external migration tool """
   28.90 +    external_migration_tool_default = ''
   28.91 +
   28.92 +    """Default path the unix-domain server listens at."""
   28.93 +    xend_unix_path_default = '/var/lib/xend/xend-socket'
   28.94 +
   28.95 +    dom0_min_mem_default = 0
   28.96 +
   28.97 +    dom0_vcpus_default = 0
   28.98 +
   28.99 +    vncpasswd_default = None
  28.100 +
  28.101 +    """Default interface to listen for VNC connections on"""
  28.102 +    xend_vnc_listen_default = '127.0.0.1'
  28.103 +
  28.104 +    """Default session storage path."""
  28.105 +    xend_domains_path_default = '/var/lib/xend/domains'
  28.106 +
  28.107 +    """Default xend management state storage."""
  28.108 +    xend_state_path_default = '/var/lib/xend/state'
  28.109 +
  28.110 +    """Default type of backend network interfaces"""
  28.111 +    netback_type = osdep.netback_type
  28.112 +
  28.113 +    """Default script to configure a backend network interface"""
  28.114 +    vif_script = osdep.vif_script
  28.115 +
  28.116 +    def __init__(self):
  28.117 +        self.configure()
  28.118 +
  28.119 +    def _logError(self, fmt, *args):
  28.120 +        """Logging function to log to stderr. We use this for XendOptions log
  28.121 +        messages because they may be logged before the logger has been
  28.122 +        configured.  Other components can safely use the logger.
  28.123 +        """
  28.124 +        print >>sys.stderr, "xend [ERROR]", fmt % args
  28.125 +
  28.126 +
  28.127 +    def configure(self):
  28.128 +        self.set_config()
  28.129 +        XendLogging.init(self.get_config_string("logfile",
  28.130 +                                               self.logfile_default),
  28.131 +                         self.get_config_string("loglevel",
  28.132 +                                               self.loglevel_default))
  28.133 +
  28.134 +    def set_config(self):
  28.135 +        raise NotImplementedError()
  28.136 +
  28.137 +    def get_config_bool(self, name, val=None):
  28.138 +        raise NotImplementedError()
  28.139 +         
  28.140 +    def get_config_int(self, name, val=None):
  28.141 +        raise NotImplementedError()
  28.142 +
  28.143 +    def get_config_string(self, name, val=None):
  28.144 +        raise NotImplementedError()
  28.145 +
  28.146 +    def get_xen_api_server(self):
  28.147 +        raise NotImplementedError()
  28.148 +
  28.149 +    def get_xend_http_server(self):
  28.150 +        """Get the flag indicating whether xend should run an http server.
  28.151 +        """
  28.152 +        return self.get_config_bool("xend-http-server", self.xend_http_server_default)
  28.153 +
  28.154 +    def get_xend_tcp_xmlrpc_server(self):
  28.155 +        return self.get_config_bool("xend-tcp-xmlrpc-server",
  28.156 +                                    self.xend_tcp_xmlrpc_server_default)
  28.157 +
  28.158 +    def get_xend_unix_xmlrpc_server(self):
  28.159 +        return self.get_config_bool("xend-unix-xmlrpc-server",
  28.160 +                                    self.xend_unix_xmlrpc_server_default)
  28.161 +
  28.162 +    def get_xend_relocation_server(self):
  28.163 +        """Get the flag indicating whether xend should run a relocation server.
  28.164 +        """
  28.165 +        return self.get_config_bool("xend-relocation-server",
  28.166 +                                    self.xend_relocation_server_default)
  28.167 +
  28.168 +    def get_xend_port(self):
  28.169 +        """Get the port xend listens at for its HTTP interface.
  28.170 +        """
  28.171 +        return self.get_config_int('xend-port', self.xend_port_default)
  28.172 +
  28.173 +    def get_xend_relocation_port(self):
  28.174 +        """Get the port xend listens at for connection to its relocation server.
  28.175 +        """
  28.176 +        return self.get_config_int('xend-relocation-port',
  28.177 +                                   self.xend_relocation_port_default)
  28.178 +
  28.179 +    def get_xend_relocation_hosts_allow(self):
  28.180 +        return self.get_config_string("xend-relocation-hosts-allow",
  28.181 +                                     self.xend_relocation_hosts_allow_default)
  28.182 +
  28.183 +    def get_xend_address(self):
  28.184 +        """Get the address xend listens at for its HTTP port.
  28.185 +        This defaults to the empty string which allows all hosts to connect.
  28.186 +        If this is set to 'localhost' only the localhost will be able to connect
  28.187 +        to the HTTP port.
  28.188 +        """
  28.189 +        return self.get_config_string('xend-address', self.xend_address_default)
  28.190 +
  28.191 +    def get_xend_relocation_address(self):
  28.192 +        """Get the address xend listens at for its relocation server port.
  28.193 +        This defaults to the empty string which allows all hosts to connect.
  28.194 +        If this is set to 'localhost' only the localhost will be able to connect
  28.195 +        to the relocation port.
  28.196 +        """
  28.197 +        return self.get_config_string('xend-relocation-address', self.xend_relocation_address_default)
  28.198 +
  28.199 +    def get_xend_unix_server(self):
  28.200 +        """Get the flag indicating whether xend should run a unix-domain server.
  28.201 +        """
  28.202 +        return self.get_config_bool("xend-unix-server", self.xend_unix_server_default)
  28.203 +
  28.204 +    def get_xend_unix_path(self):
  28.205 +        """Get the path the xend unix-domain server listens at.
  28.206 +        """
  28.207 +        return self.get_config_string("xend-unix-path", self.xend_unix_path_default)
  28.208 +
  28.209 +    def get_xend_domains_path(self):
  28.210 +        """ Get the path for persistent domain configuration storage
  28.211 +        """
  28.212 +        return self.get_config_string("xend-domains-path", self.xend_domains_path_default)
  28.213 +
  28.214 +    def get_xend_state_path(self):
  28.215 +        """ Get the path for persistent domain configuration storage
  28.216 +        """
  28.217 +        return self.get_config_string("xend-state-path", self.xend_state_path_default)    
  28.218 +
  28.219 +    def get_network_script(self):
  28.220 +        """@return the script used to alter the network configuration when
  28.221 +        Xend starts and stops, or None if no such script is specified."""
  28.222 +        
  28.223 +        s = self.get_config_string('network-script')
  28.224 +
  28.225 +        if s:
  28.226 +            result = s.split(" ")
  28.227 +            result[0] = os.path.join(self.network_script_dir, result[0])
  28.228 +            return result
  28.229 +        else:
  28.230 +            return None
  28.231 +
  28.232 +    def get_external_migration_tool(self):
  28.233 +        """@return the name of the tool to handle virtual TPM migration."""
  28.234 +        return self.get_config_string('external-migration-tool', self.external_migration_tool_default)
  28.235 +
  28.236 +    def get_enable_dump(self):
  28.237 +        return self.get_config_bool('enable-dump', 'no')
  28.238 +
  28.239 +    def get_vif_script(self):
  28.240 +        return self.get_config_string('vif-script', self.vif_script)
  28.241 +
  28.242 +    def get_dom0_min_mem(self):
  28.243 +        return self.get_config_int('dom0-min-mem', self.dom0_min_mem_default)
  28.244 +
  28.245 +    def get_dom0_vcpus(self):
  28.246 +        return self.get_config_int('dom0-cpus', self.dom0_vcpus_default)
  28.247 +
  28.248 +    def get_console_limit(self):
  28.249 +        return self.get_config_int('console-limit', 1024)
  28.250 +
  28.251 +    def get_vnclisten_address(self):
  28.252 +        return self.get_config_string('vnc-listen', self.xend_vnc_listen_default)
  28.253 +
  28.254 +    def get_vncpasswd_default(self):
  28.255 +        return self.get_config_string('vncpasswd',
  28.256 +                                     self.vncpasswd_default)
  28.257 +
  28.258 +class XendOptionsFile(XendOptions):
  28.259 +
  28.260 +    """Default path to the config file."""
  28.261 +    config_default = "/etc/xen/xend-config.sxp"
  28.262 +
  28.263 +    """Environment variable used to override config_default."""
  28.264 +    config_var     = "XEND_CONFIG"
  28.265 +
  28.266 +    def set_config(self):
  28.267 +        """If the config file exists, read it. If not, ignore it.
  28.268 +
  28.269 +        The config file is a sequence of sxp forms.
  28.270 +        """
  28.271 +        self.config_path = os.getenv(self.config_var, self.config_default)
  28.272 +        if os.path.exists(self.config_path):
  28.273 +            try:
  28.274 +                fin = file(self.config_path, 'rb')
  28.275 +                try:
  28.276 +                    config = sxp.parse(fin)
  28.277 +                finally:
  28.278 +                    fin.close()
  28.279 +                if config is None:
  28.280 +                    config = ['xend-config']
  28.281 +                else:
  28.282 +                    config.insert(0, 'xend-config')
  28.283 +                self.config = config
  28.284 +            except Exception, ex:
  28.285 +                self._logError('Reading config file %s: %s',
  28.286 +                               self.config_path, str(ex))
  28.287 +                raise
  28.288 +        else:
  28.289 +            self._logError('Config file does not exist: %s',
  28.290 +                           self.config_path)
  28.291 +            self.config = ['xend-config']
  28.292 +
  28.293 +    def get_config_value(self, name, val=None):
  28.294 +        """Get the value of an atomic configuration element.
  28.295 +
  28.296 +        @param name: element name
  28.297 +        @param val:  default value (optional, defaults to None)
  28.298 +        @return: value
  28.299 +        """
  28.300 +        return sxp.child_value(self.config, name, val=val)
  28.301 +
  28.302 +    def get_config_bool(self, name, val=None):
  28.303 +        v = string.lower(str(self.get_config_value(name, val)))
  28.304 +        if v in ['yes', 'y', '1', 'on',  'true',  't']:
  28.305 +            return True
  28.306 +        if v in ['no',  'n', '0', 'off', 'false', 'f']:
  28.307 +            return False
  28.308 +        raise XendError("invalid xend config %s: expected bool: %s" % (name, v))
  28.309 +
  28.310 +    def get_config_int(self, name, val=None):
  28.311 +        v = self.get_config_value(name, val)
  28.312 +        try:
  28.313 +            return int(v)
  28.314 +        except Exception:
  28.315 +            raise XendError("invalid xend config %s: expected int: %s" % (name, v))
  28.316 +
  28.317 +    def get_config_string(self, name, val=None):
  28.318 +        return self.get_config_value(name, val)
  28.319 +
  28.320 +    def get_xen_api_server(self):
  28.321 +        """Get the Xen-API server configuration.
  28.322 +        """
  28.323 +        return self.get_config_value('xen-api-server',
  28.324 +                                     self.xen_api_server_default)
  28.325 +
  28.326 +if os.uname()[0] == 'SunOS':
  28.327 +    class XendOptionsSMF(XendOptions):
  28.328 +
  28.329 +        def set_config(self):
  28.330 +            pass
  28.331 +
  28.332 +        def get_config_bool(self, name, val=None):
  28.333 +            try:
  28.334 +                return scf.get_bool(name)
  28.335 +            except scf.error, e:
  28.336 +                if e[0] == scf.SCF_ERROR_NOT_FOUND:
  28.337 +                    return val
  28.338 +                else:
  28.339 +                    raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
  28.340 +
  28.341 +        def get_config_int(self, name, val=None):
  28.342 +            try:
  28.343 +                return scf.get_int(name)
  28.344 +            except scf.error, e:
  28.345 +                if e[0] == scf.SCF_ERROR_NOT_FOUND:
  28.346 +                    return val
  28.347 +                else:
  28.348 +                    raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
  28.349 +
  28.350 +        def get_config_string(self, name, val=None):
  28.351 +            try:
  28.352 +                return scf.get_string(name)
  28.353 +            except scf.error, e:
  28.354 +                if e[0] == scf.SCF_ERROR_NOT_FOUND:
  28.355 +                    return val
  28.356 +                else:
  28.357 +                    raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
  28.358 +
  28.359 +        def get_xen_api_server(self):
  28.360 +            # When the new server is a supported configuration, we should
  28.361 +            # expand this.
  28.362 +            return [["unix"]]
  28.363 +
  28.364 +def instance():
  28.365 +    """Get an instance of XendOptions.
  28.366 +    Use this instead of the constructor.
  28.367 +    """
  28.368 +    global inst
  28.369 +    try:
  28.370 +        inst
  28.371 +    except:
  28.372 +        if os.uname()[0] == 'SunOS':
  28.373 +            inst = XendOptionsSMF()
  28.374 +        else:
  28.375 +            inst = XendOptionsFile()
  28.376 +    return inst
    29.1 --- a/tools/python/xen/xend/XendProtocol.py	Wed Jan 17 21:45:34 2007 -0700
    29.2 +++ b/tools/python/xen/xend/XendProtocol.py	Thu Jan 18 18:25:04 2007 +0000
    29.3 @@ -24,7 +24,7 @@ import types
    29.4  from encode import *
    29.5  from xen.xend import sxp
    29.6  
    29.7 -from xen.xend import XendRoot
    29.8 +from xen.xend import XendOptions
    29.9  
   29.10  DEBUG = 0
   29.11  
   29.12 @@ -34,7 +34,7 @@ HTTP_ACCEPTED                        = 2
   29.13  HTTP_NO_CONTENT                      = 204
   29.14  
   29.15  
   29.16 -xroot = XendRoot.instance()
   29.17 +xoptions = XendOptions.instance()
   29.18  
   29.19  
   29.20  class XendError(RuntimeError):
   29.21 @@ -218,7 +218,7 @@ class UnixXendClientProtocol(HttpXendCli
   29.22  
   29.23      def __init__(self, path=None):
   29.24          if path is None:
   29.25 -            path = xroot.get_xend_unix_path()
   29.26 +            path = xoptions.get_xend_unix_path()
   29.27          self.path = path
   29.28  
   29.29      def makeConnection(self, _):
    30.1 --- a/tools/python/xen/xend/XendRoot.py	Wed Jan 17 21:45:34 2007 -0700
    30.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.3 @@ -1,322 +0,0 @@
    30.4 -#============================================================================
    30.5 -# This library is free software; you can redistribute it and/or
    30.6 -# modify it under the terms of version 2.1 of the GNU Lesser General Public
    30.7 -# License as published by the Free Software Foundation.
    30.8 -#
    30.9 -# This library is distributed in the hope that it will be useful,
   30.10 -# but WITHOUT ANY WARRANTY; without even the implied warranty of
   30.11 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   30.12 -# Lesser General Public License for more details.
   30.13 -#
   30.14 -# You should have received a copy of the GNU Lesser General Public
   30.15 -# License along with this library; if not, write to the Free Software
   30.16 -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   30.17 -#============================================================================
   30.18 -# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
   30.19 -# Copyright (C) 2005 XenSource Ltd
   30.20 -#============================================================================
   30.21 -
   30.22 -"""Xend root class.
   30.23 -Creates the servers and handles configuration.
   30.24 -
   30.25 -Other classes get config variables by importing this module,
   30.26 -using instance() to get a XendRoot instance, and then
   30.27 -the config functions (e.g. get_xend_port()) to get
   30.28 -configured values.
   30.29 -"""
   30.30 -
   30.31 -import os
   30.32 -import os.path
   30.33 -import string
   30.34 -import sys
   30.35 -
   30.36 -from xen.xend import sxp, osdep, XendLogging
   30.37 -from xen.xend.XendError import XendError
   30.38 -
   30.39 -class XendRoot:
   30.40 -    """Root of the management classes."""
   30.41 -
   30.42 -    """Default path to the config file."""
   30.43 -    config_default = "/etc/xen/xend-config.sxp"
   30.44 -
   30.45 -    """Environment variable used to override config_default."""
   30.46 -    config_var     = "XEND_CONFIG"
   30.47 -
   30.48 -    """Where network control scripts live."""
   30.49 -    network_script_dir = osdep.scripts_dir
   30.50 -
   30.51 -    """Where block control scripts live."""
   30.52 -    block_script_dir = osdep.scripts_dir
   30.53 -
   30.54 -    """Default path to the log file. """
   30.55 -    logfile_default = "/var/log/xen/xend.log"
   30.56 -
   30.57 -    """Default level of information to be logged."""
   30.58 -    loglevel_default = 'DEBUG'
   30.59 -
   30.60 -    """Default Xen-API server configuration. """
   30.61 -    xen_api_server_default = [['unix']]
   30.62 -
   30.63 -    """Default for the flag indicating whether xend should run an http server
   30.64 -    (deprecated)."""
   30.65 -    xend_http_server_default = 'no'
   30.66 -
   30.67 -    xend_tcp_xmlrpc_server_default = 'no'
   30.68 -
   30.69 -    xend_unix_xmlrpc_server_default = 'yes'
   30.70 -
   30.71 -    """Default interface address xend listens at. """
   30.72 -    xend_address_default      = ''
   30.73 -
   30.74 -    """Default for the flag indicating whether xend should run a relocation server."""
   30.75 -    xend_relocation_server_default = 'no'
   30.76 -
   30.77 -    """Default interface address the xend relocation server listens at. """
   30.78 -    xend_relocation_address_default = ''
   30.79 -
   30.80 -    """Default port xend serves HTTP at. """
   30.81 -    xend_port_default         = '8000'
   30.82 -
   30.83 -    """Default port xend serves relocation at. """
   30.84 -    xend_relocation_port_default = '8002'
   30.85 -
   30.86 -    xend_relocation_hosts_allow_default = ''
   30.87 -
   30.88 -    """Default for the flag indicating whether xend should run a unix-domain
   30.89 -    server (deprecated)."""
   30.90 -    xend_unix_server_default = 'no'
   30.91 -
   30.92 -    """Default external migration tool """
   30.93 -    external_migration_tool_default = ''
   30.94 -
   30.95 -    """Default path the unix-domain server listens at."""
   30.96 -    xend_unix_path_default = '/var/lib/xend/xend-socket'
   30.97 -
   30.98 -    dom0_min_mem_default = '0'
   30.99 -
  30.100 -    dom0_vcpus_default = '0'
  30.101 -
  30.102 -    vncpasswd_default = None
  30.103 -
  30.104 -    """Default interface to listen for VNC connections on"""
  30.105 -    xend_vnc_listen_default = '127.0.0.1'
  30.106 -
  30.107 -    """Default session storage path."""
  30.108 -    xend_domains_path_default = '/var/lib/xend/domains'
  30.109 -
  30.110 -    """Default xend management state storage."""
  30.111 -    xend_state_path_default = '/var/lib/xend/state'
  30.112 -
  30.113 -    components = {}
  30.114 -
  30.115 -    def __init__(self):
  30.116 -        self.config_path = None
  30.117 -        self.config = None
  30.118 -        self.configure()
  30.119 -
  30.120 -
  30.121 -    def _logError(self, fmt, *args):
  30.122 -        """Logging function to log to stderr. We use this for XendRoot log
  30.123 -        messages because they may be logged before the logger has been
  30.124 -        configured.  Other components can safely use the logger.
  30.125 -        """
  30.126 -        print >>sys.stderr, "xend [ERROR]", fmt % args
  30.127 -
  30.128 -
  30.129 -    def configure(self):
  30.130 -        self.set_config()
  30.131 -        XendLogging.init(self.get_config_value("logfile",
  30.132 -                                               self.logfile_default),
  30.133 -                         self.get_config_value("loglevel",
  30.134 -                                               self.loglevel_default))
  30.135 -
  30.136 -
  30.137 -    def set_config(self):
  30.138 -        """If the config file exists, read it. If not, ignore it.
  30.139 -
  30.140 -        The config file is a sequence of sxp forms.
  30.141 -        """
  30.142 -        self.config_path = os.getenv(self.config_var, self.config_default)
  30.143 -        if os.path.exists(self.config_path):
  30.144 -            try:
  30.145 -                fin = file(self.config_path, 'rb')
  30.146 -                try:
  30.147 -                    config = sxp.parse(fin)
  30.148 -                finally:
  30.149 -                    fin.close()
  30.150 -                if config is None:
  30.151 -                    config = ['xend-config']
  30.152 -                else:
  30.153 -                    config.insert(0, 'xend-config')
  30.154 -                self.config = config
  30.155 -            except Exception, ex:
  30.156 -                self._logError('Reading config file %s: %s',
  30.157 -                               self.config_path, str(ex))
  30.158 -                raise
  30.159 -        else:
  30.160 -            self._logError('Config file does not exist: %s',
  30.161 -                           self.config_path)
  30.162 -            self.config = ['xend-config']
  30.163 -
  30.164 -    def get_config(self, name=None):
  30.165 -        """Get the configuration element with the given name, or
  30.166 -        the whole configuration if no name is given.
  30.167 -
  30.168 -        @param name: element name (optional)
  30.169 -        @return: config or none
  30.170 -        """
  30.171 -        if name is None:
  30.172 -            val = self.config
  30.173 -        else:
  30.174 -            val = sxp.child(self.config, name)
  30.175 -        return val
  30.176 -
  30.177 -    def get_config_value(self, name, val=None):
  30.178 -        """Get the value of an atomic configuration element.
  30.179 -
  30.180 -        @param name: element name
  30.181 -        @param val:  default value (optional, defaults to None)
  30.182 -        @return: value
  30.183 -        """
  30.184 -        return sxp.child_value(self.config, name, val=val)
  30.185 -
  30.186 -    def get_config_bool(self, name, val=None):
  30.187 -        v = string.lower(str(self.get_config_value(name, val)))
  30.188 -        if v in ['yes', 'y', '1', 'on',  'true',  't']:
  30.189 -            return True
  30.190 -        if v in ['no',  'n', '0', 'off', 'false', 'f']:
  30.191 -            return False
  30.192 -        raise XendError("invalid xend config %s: expected bool: %s" % (name, v))
  30.193 -
  30.194 -    def get_config_int(self, name, val=None):
  30.195 -        v = self.get_config_value(name, val)
  30.196 -        try:
  30.197 -            return int(v)
  30.198 -        except Exception:
  30.199 -            raise XendError("invalid xend config %s: expected int: %s" % (name, v))
  30.200 -
  30.201 -    def get_xen_api_server(self):
  30.202 -        """Get the Xen-API server configuration.
  30.203 -        """
  30.204 -        return self.get_config_value('xen-api-server',
  30.205 -                                     self.xen_api_server_default)
  30.206 -
  30.207 -    def get_xend_http_server(self):
  30.208 -        """Get the flag indicating whether xend should run an http server.
  30.209 -        """
  30.210 -        return self.get_config_bool("xend-http-server", self.xend_http_server_default)
  30.211 -
  30.212 -    def get_xend_tcp_xmlrpc_server(self):
  30.213 -        return self.get_config_bool("xend-tcp-xmlrpc-server",
  30.214 -                                    self.xend_tcp_xmlrpc_server_default)
  30.215 -
  30.216 -    def get_xend_unix_xmlrpc_server(self):
  30.217 -        return self.get_config_bool("xend-unix-xmlrpc-server",
  30.218 -                                    self.xend_unix_xmlrpc_server_default)
  30.219 -
  30.220 -    def get_xend_relocation_server(self):
  30.221 -        """Get the flag indicating whether xend should run a relocation server.
  30.222 -        """
  30.223 -        return self.get_config_bool("xend-relocation-server",
  30.224 -                                    self.xend_relocation_server_default)
  30.225 -
  30.226 -    def get_xend_port(self):
  30.227 -        """Get the port xend listens at for its HTTP interface.
  30.228 -        """
  30.229 -        return self.get_config_int('xend-port', self.xend_port_default)
  30.230 -
  30.231 -    def get_xend_relocation_port(self):
  30.232 -        """Get the port xend listens at for connection to its relocation server.
  30.233 -        """
  30.234 -        return self.get_config_int('xend-relocation-port',
  30.235 -                                   self.xend_relocation_port_default)
  30.236 -
  30.237 -    def get_xend_relocation_hosts_allow(self):
  30.238 -        return self.get_config_value("xend-relocation-hosts-allow",
  30.239 -                                     self.xend_relocation_hosts_allow_default)
  30.240 -
  30.241 -    def get_xend_address(self):
  30.242 -        """Get the address xend listens at for its HTTP port.
  30.243 -        This defaults to the empty string which allows all hosts to connect.
  30.244 -        If this is set to 'localhost' only the localhost will be able to connect
  30.245 -        to the HTTP port.
  30.246 -        """
  30.247 -        return self.get_config_value('xend-address', self.xend_address_default)
  30.248 -
  30.249 -    def get_xend_relocation_address(self):
  30.250 -        """Get the address xend listens at for its relocation server port.
  30.251 -        This defaults to the empty string which allows all hosts to connect.
  30.252 -        If this is set to 'localhost' only the localhost will be able to connect
  30.253 -        to the relocation port.
  30.254 -        """
  30.255 -        return self.get_config_value('xend-relocation-address', self.xend_relocation_address_default)
  30.256 -
  30.257 -    def get_xend_unix_server(self):
  30.258 -        """Get the flag indicating whether xend should run a unix-domain server.
  30.259 -        """
  30.260 -        return self.get_config_bool("xend-unix-server", self.xend_unix_server_default)
  30.261 -
  30.262 -    def get_xend_unix_path(self):
  30.263 -        """Get the path the xend unix-domain server listens at.
  30.264 -        """
  30.265 -        return self.get_config_value("xend-unix-path", self.xend_unix_path_default)
  30.266 -
  30.267 -    def get_xend_domains_path(self):
  30.268 -        """ Get the path for persistent domain configuration storage
  30.269 -        """
  30.270 -        return self.get_config_value("xend-domains-path", self.xend_domains_path_default)
  30.271 -
  30.272 -    def get_xend_state_path(self):
  30.273 -        """ Get the path for persistent domain configuration storage
  30.274 -        """
  30.275 -        return self.get_config_value("xend-state-path", self.xend_state_path_default)    
  30.276 -
  30.277 -    def get_network_script(self):
  30.278 -        """@return the script used to alter the network configuration when
  30.279 -        Xend starts and stops, or None if no such script is specified."""
  30.280 -        
  30.281 -        s = self.get_config_value('network-script')
  30.282 -
  30.283 -        if s:
  30.284 -            result = s.split(" ")
  30.285 -            result[0] = os.path.join(self.network_script_dir, result[0])
  30.286 -            return result
  30.287 -        else:
  30.288 -            return None
  30.289 -
  30.290 -    def get_external_migration_tool(self):
  30.291 -        """@return the name of the tool to handle virtual TPM migration."""
  30.292 -        return self.get_config_value('external-migration-tool', self.external_migration_tool_default)
  30.293 -
  30.294 -    def get_enable_dump(self):
  30.295 -        return self.get_config_bool('enable-dump', 'no')
  30.296 -
  30.297 -    def get_vif_script(self):
  30.298 -        return self.get_config_value('vif-script', 'vif-bridge')
  30.299 -
  30.300 -    def get_dom0_min_mem(self):
  30.301 -        return self.get_config_int('dom0-min-mem', self.dom0_min_mem_default)
  30.302 -
  30.303 -    def get_dom0_vcpus(self):
  30.304 -        return self.get_config_int('dom0-cpus', self.dom0_vcpus_default)
  30.305 -
  30.306 -    def get_console_limit(self):
  30.307 -        return self.get_config_int('console-limit', 1024)
  30.308 -
  30.309 -    def get_vnclisten_address(self):
  30.310 -        return self.get_config_value('vnc-listen', self.xend_vnc_listen_default)
  30.311 -
  30.312 -    def get_vncpasswd_default(self):
  30.313 -        return self.get_config_value('vncpasswd',
  30.314 -                                     self.vncpasswd_default)
  30.315 -
  30.316 -def instance():
  30.317 -    """Get an instance of XendRoot.
  30.318 -    Use this instead of the constructor.
  30.319 -    """
  30.320 -    global inst
  30.321 -    try:
  30.322 -        inst
  30.323 -    except:
  30.324 -        inst = XendRoot()
  30.325 -    return inst
    31.1 --- a/tools/python/xen/xend/balloon.py	Wed Jan 17 21:45:34 2007 -0700
    31.2 +++ b/tools/python/xen/xend/balloon.py	Thu Jan 18 18:25:04 2007 +0000
    31.3 @@ -22,7 +22,7 @@ import time
    31.4  import xen.lowlevel.xc
    31.5  
    31.6  import XendDomain
    31.7 -import XendRoot
    31.8 +import XendOptions
    31.9  from XendLogging import log
   31.10  from XendError import VmError
   31.11  
   31.12 @@ -107,11 +107,11 @@ def free(need_mem):
   31.13      # usage, so we recheck the required alloc each time around the loop, but
   31.14      # track the last used value so that we don't trigger too many watches.
   31.15  
   31.16 -    xroot = XendRoot.instance()
   31.17 +    xoptions = XendOptions.instance()
   31.18      xc = xen.lowlevel.xc.xc()
   31.19  
   31.20      try:
   31.21 -        dom0_min_mem = xroot.get_dom0_min_mem() * 1024
   31.22 +        dom0_min_mem = xoptions.get_dom0_min_mem() * 1024
   31.23  
   31.24          retries = 0
   31.25          sleep_time = SLEEP_TIME_GROWTH
    32.1 --- a/tools/python/xen/xend/image.py	Wed Jan 17 21:45:34 2007 -0700
    32.2 +++ b/tools/python/xen/xend/image.py	Thu Jan 18 18:25:04 2007 +0000
    32.3 @@ -173,7 +173,7 @@ class ImageHandler:
    32.4          """Build the domain. Define in subclass."""
    32.5          raise NotImplementedError()
    32.6  
    32.7 -    def createDeviceModel(self):
    32.8 +    def createDeviceModel(self, restore = False):
    32.9          """Create device model for the domain (define in subclass if needed)."""
   32.10          pass
   32.11      
   32.12 @@ -377,11 +377,12 @@ class HVMImageHandler(ImageHandler):
   32.13      # xm config file
   32.14      def parseDeviceModelArgs(self, imageConfig, deviceConfig):
   32.15          dmargs = [ 'boot', 'fda', 'fdb', 'soundhw',
   32.16 -                   'localtime', 'serial', 'stdvga', 'isa', 'vcpus',
   32.17 +                   'localtime', 'serial', 'stdvga', 'isa',
   32.18                     'acpi', 'usb', 'usbdevice', 'keymap' ]
   32.19 -        ret = []
   32.20          hvmDeviceConfig = imageConfig['hvm']['devices']
   32.21 -        
   32.22 +
   32.23 +        ret = ['-vcpus', str(self.vm.getVCpuCount())]
   32.24 +
   32.25          for a in dmargs:
   32.26              v = hvmDeviceConfig.get(a)
   32.27  
   32.28 @@ -461,14 +462,14 @@ class HVMImageHandler(ImageHandler):
   32.29              vnclisten = imageConfig.get('vnclisten')
   32.30  
   32.31              if not(vnclisten):
   32.32 -                vnclisten = (xen.xend.XendRoot.instance().
   32.33 +                vnclisten = (xen.xend.XendOptions.instance().
   32.34                               get_vnclisten_address())
   32.35              if vnclisten:
   32.36                  ret += ['-vnclisten', vnclisten]
   32.37  
   32.38              vncpasswd = vncpasswd_vmconfig
   32.39              if vncpasswd is None:
   32.40 -                vncpasswd = (xen.xend.XendRoot.instance().
   32.41 +                vncpasswd = (xen.xend.XendOptions.instance().
   32.42                               get_vncpasswd_default())
   32.43                  if vncpasswd is None:
   32.44                      raise VmError('vncpasswd is not set up in ' +
   32.45 @@ -478,7 +479,7 @@ class HVMImageHandler(ImageHandler):
   32.46  
   32.47          return ret
   32.48  
   32.49 -    def createDeviceModel(self):
   32.50 +    def createDeviceModel(self, restore = False):
   32.51          if self.pid:
   32.52              return
   32.53          # Execute device model.
   32.54 @@ -487,6 +488,8 @@ class HVMImageHandler(ImageHandler):
   32.55          args = args + ([ "-d",  "%d" % self.vm.getDomid(),
   32.56                    "-m", "%s" % (self.getRequiredInitialReservation() / 1024)])
   32.57          args = args + self.dmargs
   32.58 +        if restore:
   32.59 +            args = args + ([ "-loadvm", "/tmp/xen.qemu-dm.%d" % self.vm.getDomid() ])
   32.60          env = dict(os.environ)
   32.61          if self.display:
   32.62              env['DISPLAY'] = self.display
   32.63 @@ -505,12 +508,16 @@ class HVMImageHandler(ImageHandler):
   32.64          self.register_reboot_feature_watch()
   32.65          self.pid = self.vm.gatherDom(('image/device-model-pid', int))
   32.66  
   32.67 -    def destroy(self):
   32.68 +    def destroy(self, suspend = False):
   32.69          self.unregister_shutdown_watch()
   32.70          self.unregister_reboot_feature_watch();
   32.71          if self.pid:
   32.72              try:
   32.73 -                os.kill(self.pid, signal.SIGKILL)
   32.74 +                sig = signal.SIGKILL
   32.75 +                if suspend:
   32.76 +                    log.info("use sigusr1 to signal qemu %d", self.pid)
   32.77 +                    sig = signal.SIGUSR1
   32.78 +                os.kill(self.pid, sig)
   32.79              except OSError, exn:
   32.80                  log.exception(exn)
   32.81              try:
    33.1 --- a/tools/python/xen/xend/osdep.py	Wed Jan 17 21:45:34 2007 -0700
    33.2 +++ b/tools/python/xen/xend/osdep.py	Thu Jan 18 18:25:04 2007 +0000
    33.3 @@ -33,9 +33,19 @@ import os
    33.4      "SunOS": "/usr/lib/xen/bin/pygrub"
    33.5  }
    33.6  
    33.7 +_netback_type = {
    33.8 +    "SunOS": "SUNW_mac"
    33.9 +}
   33.10 +
   33.11 +_vif_script = {
   33.12 +    "SunOS": "vif-vnic"
   33.13 +}
   33.14 +
   33.15  def _get(var, default=None):
   33.16      return var.get(os.uname()[0], default)
   33.17  
   33.18  scripts_dir = _get(_scripts_dir, "/etc/xen/scripts")
   33.19  xend_autorestart = _get(_xend_autorestart)
   33.20  pygrub_path = _get(_pygrub_path, "/usr/bin/pygrub")
   33.21 +netback_type = _get(_netback_type, "netfront")
   33.22 +vif_script = _get(_vif_script, "vif-bridge")
    34.1 --- a/tools/python/xen/xend/server/DevController.py	Wed Jan 17 21:45:34 2007 -0700
    34.2 +++ b/tools/python/xen/xend/server/DevController.py	Thu Jan 18 18:25:04 2007 +0000
    34.3 @@ -19,7 +19,7 @@
    34.4  from threading import Event
    34.5  import types
    34.6  
    34.7 -from xen.xend import sxp, XendRoot
    34.8 +from xen.xend import sxp, XendOptions
    34.9  from xen.xend.XendError import VmError
   34.10  from xen.xend.XendLogging import log
   34.11  
   34.12 @@ -50,7 +50,7 @@ xenbusState = {
   34.13      'Closed'       : 6,
   34.14      }
   34.15  
   34.16 -xroot = XendRoot.instance()
   34.17 +xoptions = XendOptions.instance()
   34.18  
   34.19  xenbusState.update(dict(zip(xenbusState.values(), xenbusState.keys())))
   34.20  
   34.21 @@ -324,7 +324,7 @@ class DevController:
   34.22                        Make sure that the migration has finished and only
   34.23                        then return from the call.
   34.24          """
   34.25 -        tool = xroot.get_external_migration_tool()
   34.26 +        tool = xoptions.get_external_migration_tool()
   34.27          if tool:
   34.28              log.info("Calling external migration tool for step %d" % step)
   34.29              fd = os.popen("%s -type %s -step %d -host %s -domname %s" %
   34.30 @@ -341,7 +341,7 @@ class DevController:
   34.31          """ Recover from device migration. The given step was the
   34.32              last one that was successfully executed.
   34.33          """
   34.34 -        tool = xroot.get_external_migration_tool()
   34.35 +        tool = xoptions.get_external_migration_tool()
   34.36          if tool:
   34.37              log.info("Calling external migration tool")
   34.38              fd = os.popen("%s -type %s -step %d -host %s -domname %s -recover" %
    35.1 --- a/tools/python/xen/xend/server/SrvRoot.py	Wed Jan 17 21:45:34 2007 -0700
    35.2 +++ b/tools/python/xen/xend/server/SrvRoot.py	Thu Jan 18 18:25:04 2007 +0000
    35.3 @@ -25,7 +25,7 @@ class SrvRoot(SrvDir):
    35.4      """Server sub-components. Each entry is (name, class), where
    35.5      'name' is the entry name and  'class' is the name of its class.
    35.6      """
    35.7 -    #todo Get this list from the XendRoot config.
    35.8 +    #todo Get this list from the XendOptions config.
    35.9      subdirs = [
   35.10          ('node',    'SrvNode'       ),
   35.11          ('domain',  'SrvDomainDir'  ),
    36.1 --- a/tools/python/xen/xend/server/SrvServer.py	Wed Jan 17 21:45:34 2007 -0700
    36.2 +++ b/tools/python/xen/xend/server/SrvServer.py	Thu Jan 18 18:25:04 2007 +0000
    36.3 @@ -48,7 +48,7 @@ from threading import Thread
    36.4  
    36.5  from xen.web.httpserver import HttpServer, UnixHttpServer
    36.6  
    36.7 -from xen.xend import XendNode, XendRoot, XendAPI
    36.8 +from xen.xend import XendNode, XendOptions, XendAPI
    36.9  from xen.xend import Vifctl
   36.10  from xen.xend.XendLogging import log
   36.11  from xen.xend.XendClient import XEN_API_SOCKET
   36.12 @@ -57,7 +57,7 @@ from xen.web.SrvDir import SrvDir
   36.13  from SrvRoot import SrvRoot
   36.14  from XMLRPCServer import XMLRPCServer
   36.15  
   36.16 -xroot = XendRoot.instance()
   36.17 +xoptions = XendOptions.instance()
   36.18  
   36.19  
   36.20  class XendServers:
   36.21 @@ -65,6 +65,7 @@ class XendServers:
   36.22      def __init__(self, root):
   36.23          self.servers = []
   36.24          self.root = root
   36.25 +        self.running = False
   36.26          self.cleaningUp = False
   36.27          self.reloadingConfig = False
   36.28  
   36.29 @@ -79,6 +80,7 @@ class XendServers:
   36.30                  server.shutdown()
   36.31              except:
   36.32                  pass
   36.33 +        self.running = False
   36.34  
   36.35      def reloadConfig(self, signum = 0, frame = None):
   36.36          log.debug("SrvServer.reloadConfig()")
   36.37 @@ -107,13 +109,12 @@ class XendServers:
   36.38                  if server.ready:
   36.39                      continue
   36.40  
   36.41 -                thread = Thread(target=server.run, name=server.__class__.__name__)
   36.42 -                if isinstance(server, HttpServer):
   36.43 -                    thread.setDaemon(True)
   36.44 +                thread = Thread(target=server.run,
   36.45 +                                name=server.__class__.__name__)
   36.46 +                thread.setDaemon(True)
   36.47                  thread.start()
   36.48                  threads.append(thread)
   36.49  
   36.50 -
   36.51              # check for when all threads have initialized themselves and then
   36.52              # close the status pipe
   36.53  
   36.54 @@ -143,47 +144,32 @@ class XendServers:
   36.55                  status.close()
   36.56                  status = None
   36.57  
   36.58 -            # Interruptible Thread.join - Python Bug #1167930
   36.59 -            #   Replaces: for t in threads: t.join()
   36.60 -            #   Reason:   The above will cause python signal handlers to be
   36.61 -            #             blocked so we're not able to catch SIGTERM in any
   36.62 -            #             way for cleanup
   36.63 -            runningThreads = threads
   36.64 -            while len(runningThreads) > 0:
   36.65 -                try:
   36.66 -                    for t in threads:
   36.67 -                        t.join(1.0)
   36.68 -                    runningThreads = [t for t in threads
   36.69 -                                      if t.isAlive() and not t.isDaemon()]
   36.70 -                    if self.cleaningUp and len(runningThreads) > 0:
   36.71 -                        log.debug("Waiting for %s." %
   36.72 -                                  [x.getName() for x in runningThreads])
   36.73 -                except:
   36.74 -                    pass
   36.75 -
   36.76 +            # loop to keep main thread alive until it receives a SIGTERM
   36.77 +            self.running = True
   36.78 +            while self.running:
   36.79 +                time.sleep(100000000)
   36.80 +                
   36.81              if self.reloadingConfig:
   36.82                  log.info("Restarting all XML-RPC and Xen-API servers...")
   36.83                  self.cleaningUp = False
   36.84                  self.reloadingConfig = False
   36.85 -                xroot.set_config()
   36.86 -                new_servers = [x for x in self.servers
   36.87 -                               if isinstance(x, HttpServer)]
   36.88 -                self.servers = new_servers
   36.89 +                xoptions.set_config()
   36.90 +                self.servers = []
   36.91                  _loadConfig(self, self.root, True)
   36.92              else:
   36.93                  break
   36.94  
   36.95  def _loadConfig(servers, root, reload):
   36.96 -    if not reload and xroot.get_xend_http_server():
   36.97 +    if xoptions.get_xend_http_server():
   36.98          servers.add(HttpServer(root,
   36.99 -                               xroot.get_xend_address(),
  36.100 -                               xroot.get_xend_port()))
  36.101 -    if not reload and xroot.get_xend_unix_server():
  36.102 -        path = xroot.get_xend_unix_path()
  36.103 +                               xoptions.get_xend_address(),
  36.104 +                               xoptions.get_xend_port()))
  36.105 +    if  xoptions.get_xend_unix_server():
  36.106 +        path = xoptions.get_xend_unix_path()
  36.107          log.info('unix path=' + path)
  36.108          servers.add(UnixHttpServer(root, path))
  36.109  
  36.110 -    api_cfg = xroot.get_xen_api_server()
  36.111 +    api_cfg = xoptions.get_xen_api_server()
  36.112      if api_cfg:
  36.113          try:
  36.114              addrs = [(str(x[0]).split(':'),
  36.115 @@ -218,10 +204,10 @@ def _loadConfig(servers, root, reload):
  36.116          except TypeError, exn:
  36.117              log.error('Xen-API server configuration %s is invalid.', api_cfg)
  36.118  
  36.119 -    if xroot.get_xend_tcp_xmlrpc_server():
  36.120 +    if xoptions.get_xend_tcp_xmlrpc_server():
  36.121          servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, True))
  36.122  
  36.123 -    if xroot.get_xend_unix_xmlrpc_server():
  36.124 +    if xoptions.get_xend_unix_xmlrpc_server():
  36.125          servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False))
  36.126  
  36.127  
    37.1 --- a/tools/python/xen/xend/server/XMLRPCServer.py	Wed Jan 17 21:45:34 2007 -0700
    37.2 +++ b/tools/python/xen/xend/server/XMLRPCServer.py	Thu Jan 18 18:25:04 2007 +0000
    37.3 @@ -179,21 +179,24 @@ class XMLRPCServer:
    37.4          # Custom runloop so we can cleanup when exiting.
    37.5          # -----------------------------------------------------------------
    37.6          try:
    37.7 -            self.server.socket.settimeout(1.0)
    37.8              while self.running:
    37.9                  self.server.handle_request()
   37.10          finally:
   37.11 -            self.cleanup()
   37.12 +            self.shutdown()
   37.13  
   37.14      def cleanup(self):
   37.15 -        log.debug("XMLRPCServer.cleanup()")
   37.16 +        log.debug('XMLRPCServer.cleanup()')
   37.17          try:
   37.18 -            self.server.socket.close()
   37.19 +            if hasattr(self, 'server'):
   37.20 +                # shutdown socket explicitly to allow reuse
   37.21 +                self.server.socket.shutdown(socket.SHUT_RDWR)
   37.22 +                self.server.socket.close()
   37.23          except Exception, exn:
   37.24              log.exception(exn)
   37.25              pass
   37.26  
   37.27      def shutdown(self):
   37.28          self.running = False
   37.29 -        self.ready = False
   37.30 -
   37.31 +        if self.ready:
   37.32 +            self.ready = False
   37.33 +            self.cleanup()
    38.1 --- a/tools/python/xen/xend/server/netif.py	Wed Jan 17 21:45:34 2007 -0700
    38.2 +++ b/tools/python/xen/xend/server/netif.py	Thu Jan 18 18:25:04 2007 +0000
    38.3 @@ -24,10 +24,10 @@ import os
    38.4  import random
    38.5  import re
    38.6  
    38.7 -from xen.xend import XendRoot
    38.8 +from xen.xend import XendOptions
    38.9  from xen.xend.server.DevController import DevController
   38.10  
   38.11 -xroot = XendRoot.instance()
   38.12 +xoptions = XendOptions.instance()
   38.13  
   38.14  def randomMAC():
   38.15      """Generate a random MAC address.
   38.16 @@ -138,8 +138,8 @@ class NetifController(DevController):
   38.17      def getDeviceDetails(self, config):
   38.18          """@see DevController.getDeviceDetails"""
   38.19  
   38.20 -        script = os.path.join(xroot.network_script_dir,
   38.21 -                              config.get('script', xroot.get_vif_script()))
   38.22 +        script = os.path.join(xoptions.network_script_dir,
   38.23 +                              config.get('script', xoptions.get_vif_script()))
   38.24          typ     = config.get('type')
   38.25          bridge  = config.get('bridge')
   38.26          mac     = config.get('mac')
   38.27 @@ -150,9 +150,8 @@ class NetifController(DevController):
   38.28  
   38.29          devid = self.allocateDeviceID()
   38.30  
   38.31 -        # The default type is 'netfront'.
   38.32          if not typ:
   38.33 -            typ = 'netfront'
   38.34 +            typ = xoptions.netback_type
   38.35              
   38.36          if not mac:
   38.37              mac = randomMAC()
   38.38 @@ -190,7 +189,7 @@ class NetifController(DevController):
   38.39          (script, ip, bridge, mac, typ, vifname, rate, uuid) = devinfo
   38.40  
   38.41          if script:
   38.42 -            network_script_dir = xroot.network_script_dir + os.sep
   38.43 +            network_script_dir = xoptions.network_script_dir + os.sep
   38.44              result['script'] = script.replace(network_script_dir, "")
   38.45          if ip:
   38.46              result['ip'] = ip
    39.1 --- a/tools/python/xen/xend/server/relocate.py	Wed Jan 17 21:45:34 2007 -0700
    39.2 +++ b/tools/python/xen/xend/server/relocate.py	Thu Jan 18 18:25:04 2007 +0000
    39.3 @@ -24,7 +24,7 @@ from xen.web import protocol, tcp, unix
    39.4  
    39.5  from xen.xend import sxp
    39.6  from xen.xend import XendDomain
    39.7 -from xen.xend import XendRoot
    39.8 +from xen.xend import XendOptions
    39.9  from xen.xend.XendError import XendError
   39.10  from xen.xend.XendLogging import log
   39.11  
   39.12 @@ -114,15 +114,15 @@ class RelocationProtocol(protocol.Protoc
   39.13  
   39.14  
   39.15  def listenRelocation():
   39.16 -    xroot = XendRoot.instance()
   39.17 -    if xroot.get_xend_unix_server():
   39.18 +    xoptions = XendOptions.instance()
   39.19 +    if xoptions.get_xend_unix_server():
   39.20          path = '/var/lib/xend/relocation-socket'
   39.21          unix.UnixListener(path, RelocationProtocol)
   39.22 -    if xroot.get_xend_relocation_server():
   39.23 -        port = xroot.get_xend_relocation_port()
   39.24 -        interface = xroot.get_xend_relocation_address()
   39.25 +    if xoptions.get_xend_relocation_server():
   39.26 +        port = xoptions.get_xend_relocation_port()
   39.27 +        interface = xoptions.get_xend_relocation_address()
   39.28  
   39.29 -        hosts_allow = xroot.get_xend_relocation_hosts_allow()
   39.30 +        hosts_allow = xoptions.get_xend_relocation_hosts_allow()
   39.31          if hosts_allow == '':
   39.32              hosts_allow = None
   39.33          else:
    40.1 --- a/tools/python/xen/xend/server/tests/test_controllers.py	Wed Jan 17 21:45:34 2007 -0700
    40.2 +++ b/tools/python/xen/xend/server/tests/test_controllers.py	Thu Jan 18 18:25:04 2007 +0000
    40.3 @@ -2,9 +2,9 @@ import os
    40.4  import re
    40.5  import unittest
    40.6  
    40.7 -import xen.xend.XendRoot
    40.8 +import xen.xend.XendOptions
    40.9  
   40.10 -xen.xend.XendRoot.XendRoot.config_default = '/dev/null'
   40.11 +xen.xend.XendOptions.XendOptions.config_default = '/dev/null'
   40.12  
   40.13  from xen.xend.server import netif
   40.14  
   40.15 @@ -13,7 +13,7 @@ FAKE_DOMID = 42
   40.16  FAKE_DEVID = 63
   40.17  
   40.18  
   40.19 -xroot = xen.xend.XendRoot.instance()
   40.20 +xoptions = xen.xend.XendOptions.instance()
   40.21  
   40.22  
   40.23  class test_controllers(unittest.TestCase):
   40.24 @@ -36,8 +36,8 @@ class test_controllers(unittest.TestCase
   40.25  
   40.26          self.assertEqual(backdets['handle'], str(FAKE_DEVID))
   40.27          self.assertEqual(backdets['script'],
   40.28 -                         os.path.join(xroot.network_script_dir,
   40.29 -                                      xroot.get_vif_script()))
   40.30 +                         os.path.join(xoptions.network_script_dir,
   40.31 +                                      xoptions.get_vif_script()))
   40.32          self.assertValidMac(backdets['mac'], expectedMac)
   40.33  
   40.34          self.assertEqual(frontdets['handle'], str(FAKE_DEVID))
    41.1 --- a/tools/python/xen/xend/server/tpmif.py	Wed Jan 17 21:45:34 2007 -0700
    41.2 +++ b/tools/python/xen/xend/server/tpmif.py	Thu Jan 18 18:25:04 2007 +0000
    41.3 @@ -20,7 +20,7 @@
    41.4  
    41.5  """Support for virtual TPM interfaces."""
    41.6  
    41.7 -from xen.xend import XendRoot
    41.8 +from xen.xend import XendOptions
    41.9  from xen.xend.XendLogging import log
   41.10  from xen.xend.XendError import XendError
   41.11  from xen.xend.XendConstants import DEV_MIGRATE_TEST, VTPM_DELETE_SCRIPT
   41.12 @@ -29,7 +29,7 @@ from xen.xend.server.DevController impor
   41.13  import os
   41.14  import re
   41.15  
   41.16 -xroot = XendRoot.instance()
   41.17 +xoptions = XendOptions.instance()
   41.18  
   41.19  def destroy_vtpmstate(name):
   41.20      if os.path.exists(VTPM_DELETE_SCRIPT):
   41.21 @@ -88,7 +88,7 @@ class TPMifController(DevController):
   41.22      def migrate(self, deviceConfig, network, dst, step, domName):
   41.23          """@see DevContoller.migrate"""
   41.24          if network:
   41.25 -            tool = xroot.get_external_migration_tool()
   41.26 +            tool = xoptions.get_external_migration_tool()
   41.27              if tool != '':
   41.28                  log.info("Request to network-migrate device to %s. step=%d.",
   41.29                           dst, step)
   41.30 @@ -116,7 +116,7 @@ class TPMifController(DevController):
   41.31      def recover_migrate(self, deviceConfig, network, dst, step, domName):
   41.32          """@see DevContoller.recover_migrate"""
   41.33          if network:
   41.34 -            tool = xroot.get_external_migration_tool()
   41.35 +            tool = xoptions.get_external_migration_tool()
   41.36              if tool != '':
   41.37                  log.info("Request to recover network-migrated device. last good step=%d.",
   41.38                           step)
    42.1 --- a/tools/python/xen/xend/server/vfbif.py	Wed Jan 17 21:45:34 2007 -0700
    42.2 +++ b/tools/python/xen/xend/server/vfbif.py	Thu Jan 18 18:25:04 2007 +0000
    42.3 @@ -52,7 +52,7 @@ class VfbifController(DevController):
    42.4              if config.has_key("vncpasswd"):
    42.5                  passwd = config["vncpasswd"]
    42.6              else:
    42.7 -                passwd = xen.xend.XendRoot.instance().get_vncpasswd_default()
    42.8 +                passwd = xen.xend.XendOptions.instance().get_vncpasswd_default()
    42.9              if passwd:
   42.10                  self.vm.storeVm("vncpasswd", passwd)
   42.11                  log.debug("Stored a VNC password for vfb access")
   42.12 @@ -66,7 +66,7 @@ class VfbifController(DevController):
   42.13              elif config.has_key("vncdisplay"):
   42.14                  args += ["--vncport", "%d" % (5900 + int(config["vncdisplay"]))]
   42.15              vnclisten = config.get("vnclisten",
   42.16 -                                   xen.xend.XendRoot.instance().get_vnclisten_address())
   42.17 +                                   xen.xend.XendOptions.instance().get_vnclisten_address())
   42.18              args += [ "--listen", vnclisten ]
   42.19              spawn_detached(args[0], args + std_args, os.environ)
   42.20          elif t == "sdl":
    43.1 --- a/tools/python/xen/xm/create.py	Wed Jan 17 21:45:34 2007 -0700
    43.2 +++ b/tools/python/xen/xm/create.py	Thu Jan 18 18:25:04 2007 +0000
    43.3 @@ -190,6 +190,10 @@ gopts.var('vcpus', val='VCPUS',
    43.4            fn=set_int, default=1,
    43.5            use="# of Virtual CPUS in domain.")
    43.6  
    43.7 +gopts.var('vcpu_avail', val='VCPUS',
    43.8 +          fn=set_long, default=None,
    43.9 +          use="Bitmask for virtual CPUs to make available immediately.")
   43.10 +
   43.11  gopts.var('cpu_cap', val='CAP',
   43.12            fn=set_int, default=None,
   43.13            use="""Set the maximum amount of cpu.
   43.14 @@ -740,7 +744,7 @@ def make_config(vals):
   43.15  
   43.16      map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory',
   43.17                     'restart', 'on_poweroff',
   43.18 -                   'on_reboot', 'on_crash', 'vcpus', 'features',
   43.19 +                   'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features',
   43.20                     'on_xend_start', 'on_xend_stop'])
   43.21  
   43.22      if vals.uuid is not None:
    44.1 --- a/tools/python/xen/xm/main.py	Wed Jan 17 21:45:34 2007 -0700
    44.2 +++ b/tools/python/xen/xm/main.py	Thu Jan 18 18:25:04 2007 +0000
    44.3 @@ -693,12 +693,15 @@ def parse_doms_info(info):
    44.4          up_time = time.time() - start_time
    44.5  
    44.6      return {
    44.7 -        'domid'    : get_info('domid',        str,   ''),
    44.8 -        'name'     : get_info('name',         str,   '??'),
    44.9 +        'domid'    : get_info('domid',              str,   ''),
   44.10 +        'name'     : get_info('name',               str,   '??'),
   44.11          'mem'      : get_info('memory_dynamic_min', int,   0),
   44.12 -        'vcpus'    : get_info('online_vcpus',        int,   0),
   44.13 -        'state'    : get_info('state',        str,    ''),
   44.14 -        'cpu_time' : get_info('cpu_time',     float, 0),
   44.15 +        'state'    : get_info('state',              str,   ''),
   44.16 +        'cpu_time' : get_info('cpu_time',           float, 0.0),
   44.17 +        # VCPUs is the number online when the VM is up, or the number
   44.18 +        # configured otherwise.
   44.19 +        'vcpus'    : get_info('online_vcpus', int,
   44.20 +                              get_info('vcpus', int, 0)),
   44.21          'up_time'  : up_time,
   44.22          'seclabel' : security.get_security_printlabel(info),
   44.23          }
    45.1 --- a/tools/python/xen/xm/opts.py	Wed Jan 17 21:45:34 2007 -0700
    45.2 +++ b/tools/python/xen/xm/opts.py	Thu Jan 18 18:25:04 2007 +0000
    45.3 @@ -571,6 +571,14 @@ def set_int(opt, k, v):
    45.4          opt.opts.err('Invalid value: ' + str(v))
    45.5      opt.set(v)
    45.6  
    45.7 +def set_long(opt, k, v):
    45.8 +    """Set an option to a long integer value."""
    45.9 +    try:
   45.10 +        v = long(v)
   45.11 +    except:
   45.12 +        opt.opts.err('Invalid value: ' + str(v))
   45.13 +    opt.set(v)
   45.14 +
   45.15  def set_float(opt, k, v):
   45.16      """Set an option to a float value."""
   45.17      try:
    46.1 --- a/tools/python/xen/xm/tests/test_create.py	Wed Jan 17 21:45:34 2007 -0700
    46.2 +++ b/tools/python/xen/xm/tests/test_create.py	Thu Jan 18 18:25:04 2007 +0000
    46.3 @@ -3,9 +3,9 @@ import os.path
    46.4  import tempfile
    46.5  import unittest
    46.6  
    46.7 -import xen.xend.XendRoot
    46.8 +import xen.xend.XendOptions
    46.9  
   46.10 -xen.xend.XendRoot.XendRoot.config_default = '/dev/null'
   46.11 +xen.xend.XendOptions.XendOptions.config_default = '/dev/null'
   46.12  
   46.13  import xen.xm.create
   46.14  
    47.1 --- a/tools/xcutils/xc_restore.c	Wed Jan 17 21:45:34 2007 -0700
    47.2 +++ b/tools/xcutils/xc_restore.c	Thu Jan 18 18:25:04 2007 +0000
    47.3 @@ -19,12 +19,13 @@ int
    47.4  main(int argc, char **argv)
    47.5  {
    47.6      unsigned int xc_fd, io_fd, domid, nr_pfns, store_evtchn, console_evtchn;
    47.7 +    unsigned int hvm, pae, apic;
    47.8      int ret;
    47.9      unsigned long store_mfn, console_mfn;
   47.10  
   47.11 -    if (argc != 6)
   47.12 +    if (argc != 9)
   47.13  	errx(1,
   47.14 -	     "usage: %s iofd domid nr_pfns store_evtchn console_evtchn",
   47.15 +	     "usage: %s iofd domid nr_pfns store_evtchn console_evtchn hvm pae apic",
   47.16  	     argv[0]);
   47.17  
   47.18      xc_fd = xc_interface_open();
   47.19 @@ -36,9 +37,19 @@ main(int argc, char **argv)
   47.20      nr_pfns = atoi(argv[3]);
   47.21      store_evtchn = atoi(argv[4]);
   47.22      console_evtchn = atoi(argv[5]);
   47.23 +    hvm  = atoi(argv[6]);
   47.24 +    pae  = atoi(argv[7]);
   47.25 +    apic = atoi(argv[8]);
   47.26  
   47.27 -    ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
   47.28 -			   &store_mfn, console_evtchn, &console_mfn);
   47.29 +    if (hvm) {
   47.30 +         /* pass the memsize to xc_hvm_restore to find the store_mfn */
   47.31 +        store_mfn = hvm;
   47.32 +        ret = xc_hvm_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
   47.33 +                &store_mfn, console_evtchn, &console_mfn, pae, apic);
   47.34 +    } else 
   47.35 +        ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
   47.36 +                &store_mfn, console_evtchn, &console_mfn);
   47.37 +
   47.38      if (ret == 0) {
   47.39  	printf("store-mfn %li\n", store_mfn);
   47.40  	printf("console-mfn %li\n", console_mfn);
    48.1 --- a/tools/xcutils/xc_save.c	Wed Jan 17 21:45:34 2007 -0700
    48.2 +++ b/tools/xcutils/xc_save.c	Thu Jan 18 18:25:04 2007 +0000
    48.3 @@ -51,7 +51,10 @@ main(int argc, char **argv)
    48.4      max_f = atoi(argv[4]);
    48.5      flags = atoi(argv[5]);
    48.6  
    48.7 -    ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
    48.8 +    if (flags & XCFLAGS_HVM)
    48.9 +        ret = xc_hvm_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
   48.10 +    else 
   48.11 +        ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
   48.12  
   48.13      xc_interface_close(xc_fd);
   48.14  
    49.1 --- a/xen/arch/x86/domain.c	Wed Jan 17 21:45:34 2007 -0700
    49.2 +++ b/xen/arch/x86/domain.c	Thu Jan 18 18:25:04 2007 +0000
    49.3 @@ -573,6 +573,7 @@ int arch_set_info_guest(
    49.4      else
    49.5      {
    49.6          hvm_load_cpu_guest_regs(v, &v->arch.guest_context.user_regs);
    49.7 +        hvm_load_cpu_context(v, &v->arch.guest_context.hvmcpu_ctxt);
    49.8      }
    49.9  
   49.10      if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
    50.1 --- a/xen/arch/x86/domctl.c	Wed Jan 17 21:45:34 2007 -0700
    50.2 +++ b/xen/arch/x86/domctl.c	Thu Jan 18 18:25:04 2007 +0000
    50.3 @@ -322,8 +322,10 @@ void arch_get_info_guest(struct vcpu *v,
    50.4  
    50.5      if ( is_hvm_vcpu(v) )
    50.6      {
    50.7 -        if ( !IS_COMPAT(v->domain) )
    50.8 +        if ( !IS_COMPAT(v->domain) ) {
    50.9              hvm_store_cpu_guest_regs(v, &c.nat->user_regs, c.nat->ctrlreg);
   50.10 +            hvm_save_cpu_context(v, &c.nat->hvmcpu_ctxt);
   50.11 +        }
   50.12  #ifdef CONFIG_COMPAT
   50.13          else
   50.14          {
    51.1 --- a/xen/arch/x86/hvm/hvm.c	Wed Jan 17 21:45:34 2007 -0700
    51.2 +++ b/xen/arch/x86/hvm/hvm.c	Thu Jan 18 18:25:04 2007 +0000
    51.3 @@ -149,11 +149,19 @@ int hvm_domain_initialise(struct domain 
    51.4  
    51.5  void hvm_domain_destroy(struct domain *d)
    51.6  {
    51.7 +    HVMStateEntry *se, *dse;
    51.8      pit_deinit(d);
    51.9      rtc_deinit(d);
   51.10      pmtimer_deinit(d);
   51.11      hpet_deinit(d);
   51.12  
   51.13 +    se = d->arch.hvm_domain.first_se;
   51.14 +    while (se) {
   51.15 +        dse = se;
   51.16 +        se = se->next;
   51.17 +        xfree(dse);
   51.18 +    }
   51.19 + 
   51.20      if ( d->arch.hvm_domain.shared_page_va )
   51.21          unmap_domain_page_global(
   51.22              (void *)d->arch.hvm_domain.shared_page_va);
   51.23 @@ -189,6 +197,9 @@ int hvm_vcpu_initialise(struct vcpu *v)
   51.24      rtc_init(v, RTC_PORT(0), RTC_IRQ);
   51.25      pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS);
   51.26      hpet_init(v);
   51.27 + 
   51.28 +    /* init hvm sharepage */
   51.29 +    shpage_init(v->domain, get_sp(v->domain));
   51.30  
   51.31      /* Init guest TSC to start from zero. */
   51.32      hvm_set_guest_time(v, 0);
    52.1 --- a/xen/arch/x86/hvm/i8254.c	Wed Jan 17 21:45:34 2007 -0700
    52.2 +++ b/xen/arch/x86/hvm/i8254.c	Thu Jan 18 18:25:04 2007 +0000
    52.3 @@ -207,11 +207,11 @@ static inline void pit_load_count(PITCha
    52.4      switch (s->mode) {
    52.5          case 2:
    52.6              /* create periodic time */
    52.7 -            create_periodic_time(&s->pt, period, 0, 0, pit_time_fired, s);
    52.8 +            create_periodic_time(current, &s->pt, period, 0, 0, pit_time_fired, s);
    52.9              break;
   52.10          case 1:
   52.11              /* create one shot time */
   52.12 -            create_periodic_time(&s->pt, period, 0, 1, pit_time_fired, s);
   52.13 +            create_periodic_time(current, &s->pt, period, 0, 1, pit_time_fired, s);
   52.14  #ifdef DEBUG_PIT
   52.15              printk("HVM_PIT: create one shot time.\n");
   52.16  #endif
   52.17 @@ -356,6 +356,154 @@ void pit_stop_channel0_irq(PITState * pi
   52.18      destroy_periodic_time(&s->pt);
   52.19  }
   52.20  
   52.21 +#ifdef HVM_DEBUG_SUSPEND
   52.22 +static void pit_info(PITState *pit)
   52.23 +{
   52.24 +    PITChannelState *s;
   52.25 +    int i;
   52.26 +
   52.27 +    for(i = 0; i < 3; i++) {
   52.28 +        printk("*****pit channel %d's state:*****\n", i);
   52.29 +        s = &pit->channels[i];
   52.30 +        printk("pit 0x%x.\n", s->count);
   52.31 +        printk("pit 0x%x.\n", s->latched_count);
   52.32 +        printk("pit 0x%x.\n", s->count_latched);
   52.33 +        printk("pit 0x%x.\n", s->status_latched);
   52.34 +        printk("pit 0x%x.\n", s->status);
   52.35 +        printk("pit 0x%x.\n", s->read_state);
   52.36 +        printk("pit 0x%x.\n", s->write_state);
   52.37 +        printk("pit 0x%x.\n", s->write_latch);
   52.38 +        printk("pit 0x%x.\n", s->rw_mode);
   52.39 +        printk("pit 0x%x.\n", s->mode);
   52.40 +        printk("pit 0x%x.\n", s->bcd);
   52.41 +        printk("pit 0x%x.\n", s->gate);
   52.42 +        printk("pit %"PRId64"\n", s->count_load_time);
   52.43 +
   52.44 +        if (s->pt) {
   52.45 +            struct periodic_time *pt = s->pt;
   52.46 +            printk("pit channel %d has a periodic timer:\n", i);
   52.47 +            printk("pt %d.\n", pt->enabled);
   52.48 +            printk("pt %d.\n", pt->one_shot);
   52.49 +            printk("pt %d.\n", pt->irq);
   52.50 +            printk("pt %d.\n", pt->first_injected);
   52.51 +
   52.52 +            printk("pt %d.\n", pt->pending_intr_nr);
   52.53 +            printk("pt %d.\n", pt->period);
   52.54 +            printk("pt %"PRId64"\n", pt->period_cycles);
   52.55 +            printk("pt %"PRId64"\n", pt->last_plt_gtime);
   52.56 +        }
   52.57 +    }
   52.58 +
   52.59 +}
   52.60 +#else
   52.61 +static void pit_info(PITState *pit)
   52.62 +{
   52.63 +}
   52.64 +#endif
   52.65 +
   52.66 +static void pit_save(hvm_domain_context_t *h, void *opaque)
   52.67 +{
   52.68 +    struct domain *d = opaque;
   52.69 +    PITState *pit = &d->arch.hvm_domain.pl_time.vpit;
   52.70 +    PITChannelState *s;
   52.71 +    struct periodic_time *pt;
   52.72 +    int i, pti = -1;
   52.73 +    
   52.74 +    pit_info(pit);
   52.75 +
   52.76 +    for(i = 0; i < 3; i++) {
   52.77 +        s = &pit->channels[i];
   52.78 +        hvm_put_32u(h, s->count);
   52.79 +        hvm_put_16u(h, s->latched_count);
   52.80 +        hvm_put_8u(h, s->count_latched);
   52.81 +        hvm_put_8u(h, s->status_latched);
   52.82 +        hvm_put_8u(h, s->status);
   52.83 +        hvm_put_8u(h, s->read_state);
   52.84 +        hvm_put_8u(h, s->write_state);
   52.85 +        hvm_put_8u(h, s->write_latch);
   52.86 +        hvm_put_8u(h, s->rw_mode);
   52.87 +        hvm_put_8u(h, s->mode);
   52.88 +        hvm_put_8u(h, s->bcd);
   52.89 +        hvm_put_8u(h, s->gate);
   52.90 +        hvm_put_64u(h, s->count_load_time);
   52.91 +
   52.92 +        if (s->pt.enabled && pti == -1)
   52.93 +            pti = i;
   52.94 +    }
   52.95 +
   52.96 +    pt = &pit->channels[pti].pt;
   52.97 +
   52.98 +    /* save the vcpu for pt */
   52.99 +    hvm_put_32u(h, pt->vcpu->vcpu_id);
  52.100 +
  52.101 +    /* save guest time */
  52.102 +    hvm_put_8u(h, pti);
  52.103 +    hvm_put_32u(h, pt->pending_intr_nr);
  52.104 +    hvm_put_64u(h, pt->last_plt_gtime);
  52.105 +
  52.106 +}
  52.107 +
  52.108 +static int pit_load(hvm_domain_context_t *h, void *opaque, int version_id)
  52.109 +{
  52.110 +    struct domain *d = opaque;
  52.111 +    PITState *pit = &d->arch.hvm_domain.pl_time.vpit;
  52.112 +    PITChannelState *s;
  52.113 +    int i, pti, vcpu_id;
  52.114 +    u32 period;
  52.115 +
  52.116 +    if (version_id != 1)
  52.117 +        return -EINVAL;
  52.118 +
  52.119 +    for(i = 0; i < 3; i++) {
  52.120 +        s = &pit->channels[i];
  52.121 +        s->count = hvm_get_32u(h);
  52.122 +        s->latched_count = hvm_get_16u(h);
  52.123 +        s->count_latched = hvm_get_8u(h);
  52.124 +        s->status_latched = hvm_get_8u(h);
  52.125 +        s->status = hvm_get_8u(h);
  52.126 +        s->read_state = hvm_get_8u(h);
  52.127 +        s->write_state = hvm_get_8u(h);
  52.128 +        s->write_latch = hvm_get_8u(h);
  52.129 +        s->rw_mode = hvm_get_8u(h);
  52.130 +        s->mode = hvm_get_8u(h);
  52.131 +        s->bcd = hvm_get_8u(h);
  52.132 +        s->gate = hvm_get_8u(h);
  52.133 +        s->count_load_time = hvm_get_64u(h);
  52.134 +    }
  52.135 +
  52.136 +    vcpu_id = hvm_get_32u(h);
  52.137 +
  52.138 +    pti = hvm_get_8u(h);
  52.139 +    if ( pti < 0 || pti > 2) {
  52.140 +        printk("pit load get a wrong channel %d when HVM resume.\n", pti);
  52.141 +        return -EINVAL;
  52.142 +    }
  52.143 +
  52.144 +    s = &pit->channels[pti];
  52.145 +    period = DIV_ROUND((s->count * 1000000000ULL), PIT_FREQ);
  52.146 +
  52.147 +    printk("recreate periodic timer %d in mode %d, freq=%d.\n", pti, s->mode, period);
  52.148 +    switch (s->mode) {
  52.149 +        case 2:
  52.150 +            /* create periodic time */
  52.151 +            create_periodic_time(d->vcpu[vcpu_id], &s->pt, period, 0, 0, pit_time_fired, s);
  52.152 +            break;
  52.153 +        case 1:
  52.154 +            /* create one shot time */
  52.155 +            create_periodic_time(d->vcpu[vcpu_id], &s->pt, period, 0, 1, pit_time_fired, s);
  52.156 +            break;
  52.157 +        default:
  52.158 +            printk("pit mode %"PRId8" should not use periodic timer!\n", s->mode);
  52.159 +            return -EINVAL;
  52.160 +    }
  52.161 +    s->pt.pending_intr_nr = hvm_get_32u(h);
  52.162 +    s->pt.last_plt_gtime = hvm_get_64u(h);
  52.163 +
  52.164 +    pit_info(pit);
  52.165 +
  52.166 +    return 0;
  52.167 +}
  52.168 +
  52.169  static void pit_reset(void *opaque)
  52.170  {
  52.171      PITState *pit = opaque;
  52.172 @@ -383,6 +531,7 @@ void pit_init(struct vcpu *v, unsigned l
  52.173      s++; s->pt.vcpu = v;
  52.174      s++; s->pt.vcpu = v;
  52.175  
  52.176 +    hvm_register_savevm(v->domain, "xen_hvm_i8254", PIT_BASE, 1, pit_save, pit_load, v->domain);
  52.177      register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io);
  52.178      /* register the speaker port */
  52.179      register_portio_handler(v->domain, 0x61, 1, handle_speaker_io);
    53.1 --- a/xen/arch/x86/hvm/intercept.c	Wed Jan 17 21:45:34 2007 -0700
    53.2 +++ b/xen/arch/x86/hvm/intercept.c	Thu Jan 18 18:25:04 2007 +0000
    53.3 @@ -29,6 +29,8 @@
    53.4  #include <asm/current.h>
    53.5  #include <io_ports.h>
    53.6  #include <xen/event.h>
    53.7 +#include <xen/compile.h>
    53.8 +#include <public/version.h>
    53.9  
   53.10  
   53.11  extern struct hvm_mmio_handler hpet_mmio_handler;
   53.12 @@ -155,6 +157,307 @@ static inline void hvm_mmio_access(struc
   53.13      }
   53.14  }
   53.15  
   53.16 +/* save/restore support */
   53.17 +#define HVM_FILE_MAGIC   0x54381286
   53.18 +#define HVM_FILE_VERSION 0x00000001
   53.19 +
   53.20 +int hvm_register_savevm(struct domain *d,
   53.21 +                    const char *idstr,
   53.22 +                    int instance_id,
   53.23 +                    int version_id,
   53.24 +                    SaveStateHandler *save_state,
   53.25 +                    LoadStateHandler *load_state,
   53.26 +                    void *opaque)
   53.27 +{
   53.28 +    HVMStateEntry *se, **pse;
   53.29 +
   53.30 +    if ( (se = xmalloc(struct HVMStateEntry)) == NULL ){
   53.31 +        printk("allocat hvmstate entry fail.\n");
   53.32 +        return -1;
   53.33 +    }
   53.34 +
   53.35 +    strncpy(se->idstr, idstr, HVM_SE_IDSTR_LEN);
   53.36 +
   53.37 +    se->instance_id = instance_id;
   53.38 +    se->version_id = version_id;
   53.39 +    se->save_state = save_state;
   53.40 +    se->load_state = load_state;
   53.41 +    se->opaque = opaque;
   53.42 +    se->next = NULL;
   53.43 +
   53.44 +    /* add at the end of list */
   53.45 +    pse = &d->arch.hvm_domain.first_se;
   53.46 +    while (*pse != NULL)
   53.47 +        pse = &(*pse)->next;
   53.48 +    *pse = se;
   53.49 +    return 0;
   53.50 +}
   53.51 +
   53.52 +int hvm_save(struct vcpu *v, hvm_domain_context_t *h)
   53.53 +{
   53.54 +    uint32_t len, len_pos, cur_pos;
   53.55 +    uint32_t eax, ebx, ecx, edx;
   53.56 +    HVMStateEntry *se;
   53.57 +    char *chgset;
   53.58 +
   53.59 +    if (!is_hvm_vcpu(v)) {
   53.60 +        printk("hvm_save only for hvm guest!\n");
   53.61 +        return -1;
   53.62 +    }
   53.63 +
   53.64 +    memset(h, 0, sizeof(hvm_domain_context_t));
   53.65 +    hvm_put_32u(h, HVM_FILE_MAGIC);
   53.66 +    hvm_put_32u(h, HVM_FILE_VERSION);
   53.67 +
   53.68 +    /* save xen changeset */
   53.69 +    chgset = strrchr(XEN_CHANGESET, ' ');
   53.70 +    if ( chgset )
   53.71 +        chgset++;
   53.72 +    else
   53.73 +        chgset = XEN_CHANGESET;
   53.74 +
   53.75 +    len = strlen(chgset);
   53.76 +    hvm_put_8u(h, len);
   53.77 +    hvm_put_buffer(h, chgset, len);
   53.78 +
   53.79 +    /* save cpuid */
   53.80 +    cpuid(1, &eax, &ebx, &ecx, &edx);
   53.81 +    hvm_put_32u(h, eax);
   53.82 +
   53.83 +    for(se = v->domain->arch.hvm_domain.first_se; se != NULL; se = se->next) {
   53.84 +        /* ID string */
   53.85 +        len = strnlen(se->idstr, HVM_SE_IDSTR_LEN);
   53.86 +        hvm_put_8u(h, len);
   53.87 +        hvm_put_buffer(h, se->idstr, len);
   53.88 +
   53.89 +        hvm_put_32u(h, se->instance_id);
   53.90 +        hvm_put_32u(h, se->version_id);
   53.91 +
   53.92 +        /* record size */
   53.93 +        len_pos = hvm_ctxt_tell(h);
   53.94 +        hvm_put_32u(h, 0);
   53.95 +
   53.96 +        se->save_state(h, se->opaque);
   53.97 +
   53.98 +        cur_pos = hvm_ctxt_tell(h);
   53.99 +        len = cur_pos - len_pos - 4;
  53.100 +        hvm_ctxt_seek(h, len_pos);
  53.101 +        hvm_put_32u(h, len);
  53.102 +        hvm_ctxt_seek(h, cur_pos);
  53.103 +
  53.104 +    }
  53.105 +
  53.106 +    h->size = hvm_ctxt_tell(h);
  53.107 +    hvm_ctxt_seek(h, 0);
  53.108 +
  53.109 +    if (h->size >= HVM_CTXT_SIZE) {
  53.110 +        printk("hvm_domain_context overflow when hvm_save! need %"PRId32" bytes for use.\n", h->size);
  53.111 +        return -1;
  53.112 +    }
  53.113 +
  53.114 +    return 0;
  53.115 +
  53.116 +}
  53.117 +
  53.118 +static HVMStateEntry *find_se(struct domain *d, const char *idstr, int instance_id)
  53.119 +{
  53.120 +    HVMStateEntry *se;
  53.121 +
  53.122 +    for(se = d->arch.hvm_domain.first_se; se != NULL; se = se->next) {
  53.123 +        if (!strncmp(se->idstr, idstr, HVM_SE_IDSTR_LEN) &&
  53.124 +            instance_id == se->instance_id){
  53.125 +            return se;
  53.126 +        }
  53.127 +    }
  53.128 +    return NULL;
  53.129 +}
  53.130 +
  53.131 +int hvm_load(struct vcpu *v, hvm_domain_context_t *h)
  53.132 +{
  53.133 +    uint32_t len, rec_len, rec_pos, magic, instance_id, version_id;
  53.134 +    uint32_t eax, ebx, ecx, edx;
  53.135 +    HVMStateEntry *se;
  53.136 +    char idstr[HVM_SE_IDSTR_LEN];
  53.137 +    xen_changeset_info_t chgset;
  53.138 +    char *cur_chgset;
  53.139 +    int ret;
  53.140 +
  53.141 +    if (!is_hvm_vcpu(v)) {
  53.142 +        printk("hvm_load only for hvm guest!\n");
  53.143 +        return -1;
  53.144 +    }
  53.145 +
  53.146 +    if (h->size >= HVM_CTXT_SIZE) {
  53.147 +        printk("hvm_load fail! seems hvm_domain_context overflow when hvm_save! need %"PRId32" bytes.\n", h->size);
  53.148 +        return -1;
  53.149 +    }
  53.150 +
  53.151 +    hvm_ctxt_seek(h, 0);
  53.152 +
  53.153 +    magic = hvm_get_32u(h);
  53.154 +    if (magic != HVM_FILE_MAGIC) {
  53.155 +        printk("HVM restore magic dismatch!\n");
  53.156 +        return -1;
  53.157 +    }
  53.158 +
  53.159 +    magic = hvm_get_32u(h);
  53.160 +    if (magic != HVM_FILE_VERSION) {
  53.161 +        printk("HVM restore version dismatch!\n");
  53.162 +        return -1;
  53.163 +    }
  53.164 +
  53.165 +    /* check xen change set */
  53.166 +    cur_chgset = strrchr(XEN_CHANGESET, ' ');
  53.167 +    if ( cur_chgset )
  53.168 +        cur_chgset++;
  53.169 +    else
  53.170 +        cur_chgset = XEN_CHANGESET;
  53.171 +
  53.172 +    len = hvm_get_8u(h);
  53.173 +    if (len > 20) { /*typical length is 18 -- "revision number:changeset id" */
  53.174 +        printk("wrong change set length %d when hvm restore!\n", len);
  53.175 +        return -1;
  53.176 +    }
  53.177 +
  53.178 +    hvm_get_buffer(h, chgset, len);
  53.179 +    chgset[len] = '\0';
  53.180 +    if (strncmp(cur_chgset, chgset, len + 1))
  53.181 +        printk("warnings: try to restore hvm guest(%s) on a different changeset %s.\n",
  53.182 +                chgset, cur_chgset);
  53.183 +
  53.184 +
  53.185 +    if ( !strcmp(cur_chgset, "unavailable") )
  53.186 +        printk("warnings: try to restore hvm guest when changeset is unavailable.\n");
  53.187 +
  53.188 +
  53.189 +    /* check cpuid */
  53.190 +    cpuid(1, &eax, &ebx, &ecx, &edx);
  53.191 +    ebx = hvm_get_32u(h);
  53.192 +    /*TODO: need difine how big difference is acceptable */
  53.193 +    if (ebx != eax)
  53.194 +        printk("warnings: try to restore hvm guest(0x%"PRIx32") "
  53.195 +               "on a different type processor(0x%"PRIx32").\n",
  53.196 +                ebx,
  53.197 +                eax);
  53.198 +
  53.199 +    while(1) {
  53.200 +        if (hvm_ctxt_end(h)) {
  53.201 +            break;
  53.202 +        }
  53.203 +
  53.204 +        /* ID string */
  53.205 +        len = hvm_get_8u(h);
  53.206 +        if (len > HVM_SE_IDSTR_LEN) {
  53.207 +            printk("wrong HVM save entry idstr len %d!", len);
  53.208 +            return -1;
  53.209 +        }
  53.210 +
  53.211 +        hvm_get_buffer(h, idstr, len);
  53.212 +        idstr[len] = '\0';
  53.213 +
  53.214 +        instance_id = hvm_get_32u(h);
  53.215 +        version_id = hvm_get_32u(h);
  53.216 +
  53.217 +        rec_len = hvm_get_32u(h);
  53.218 +        rec_pos = hvm_ctxt_tell(h);
  53.219 +
  53.220 +        se = find_se(v->domain, idstr, instance_id);
  53.221 +        if (se == NULL) {
  53.222 +            printk("warnings: hvm load can't find device %s's instance %d!\n",
  53.223 +                    idstr, instance_id);
  53.224 +        } else {
  53.225 +            ret = se->load_state(h, se->opaque, version_id);
  53.226 +            if (ret < 0)
  53.227 +                printk("warnings: loading state fail for device %s instance %d!\n",
  53.228 +                        idstr, instance_id);
  53.229 +        }
  53.230 +                    
  53.231 +
  53.232 +        /* make sure to jump end of record */
  53.233 +        if ( hvm_ctxt_tell(h) - rec_pos != rec_len) {
  53.234 +            printk("wrong hvm record size, maybe some dismatch between save&restore handler!\n");
  53.235 +        }
  53.236 +        hvm_ctxt_seek(h, rec_pos + rec_len);
  53.237 +    }
  53.238 +
  53.239 +    return 0;
  53.240 +}
  53.241 +
  53.242 +int arch_gethvm_ctxt(
  53.243 +    struct vcpu *v, struct hvm_domain_context *c)
  53.244 +{
  53.245 +    if ( !is_hvm_vcpu(v) )
  53.246 +        return -1;
  53.247 +
  53.248 +    return hvm_save(v, c);
  53.249 +
  53.250 +}
  53.251 +
  53.252 +int arch_sethvm_ctxt(
  53.253 +        struct vcpu *v, struct hvm_domain_context *c)
  53.254 +{
  53.255 +    return hvm_load(v, c);
  53.256 +}
  53.257 +
  53.258 +#ifdef HVM_DEBUG_SUSPEND
  53.259 +static void shpage_info(shared_iopage_t *sh)
  53.260 +{
  53.261 +
  53.262 +    vcpu_iodata_t *p = &sh->vcpu_iodata[0];
  53.263 +    ioreq_t *req = &p->vp_ioreq;
  53.264 +    printk("*****sharepage_info******!\n");
  53.265 +    printk("vp_eport=%d\n", p->vp_eport);
  53.266 +    printk("io packet: "
  53.267 +                     "state:%x, pvalid: %x, dir:%x, port: %"PRIx64", "
  53.268 +                     "data: %"PRIx64", count: %"PRIx64", size: %"PRIx64"\n",
  53.269 +                     req->state, req->data_is_ptr, req->dir, req->addr,
  53.270 +                     req->data, req->count, req->size);
  53.271 +}
  53.272 +#else
  53.273 +static void shpage_info(shared_iopage_t *sh)
  53.274 +{
  53.275 +}
  53.276 +#endif
  53.277 +
  53.278 +static void shpage_save(hvm_domain_context_t *h, void *opaque)
  53.279 +{
  53.280 +    /* XXX:no action required for shpage save/restore, since it's in guest memory
  53.281 +     * keep it for debug purpose only */
  53.282 +
  53.283 +#if 0
  53.284 +    struct shared_iopage *s = opaque;
  53.285 +    /* XXX:smp */
  53.286 +    struct ioreq *req = &s->vcpu_iodata[0].vp_ioreq;
  53.287 +    
  53.288 +    shpage_info(s);
  53.289 +
  53.290 +    hvm_put_buffer(h, (char*)req, sizeof(struct ioreq));
  53.291 +#endif
  53.292 +}
  53.293 +
  53.294 +static int shpage_load(hvm_domain_context_t *h, void *opaque, int version_id)
  53.295 +{
  53.296 +    struct shared_iopage *s = opaque;
  53.297 +#if 0
  53.298 +    /* XXX:smp */
  53.299 +    struct ioreq *req = &s->vcpu_iodata[0].vp_ioreq;
  53.300 +
  53.301 +    if (version_id != 1)
  53.302 +        return -EINVAL;
  53.303 +
  53.304 +    hvm_get_buffer(h, (char*)req, sizeof(struct ioreq));
  53.305 +
  53.306 +
  53.307 +#endif
  53.308 +    shpage_info(s);
  53.309 +    return 0;
  53.310 +}
  53.311 +
  53.312 +void shpage_init(struct domain *d, shared_iopage_t *sp)
  53.313 +{
  53.314 +    hvm_register_savevm(d, "xen_hvm_shpage", 0x10, 1, shpage_save, shpage_load, sp);
  53.315 +}
  53.316 +
  53.317  int hvm_buffered_io_intercept(ioreq_t *p)
  53.318  {
  53.319      struct vcpu *v = current;
    54.1 --- a/xen/arch/x86/hvm/rtc.c	Wed Jan 17 21:45:34 2007 -0700
    54.2 +++ b/xen/arch/x86/hvm/rtc.c	Thu Jan 18 18:25:04 2007 +0000
    54.3 @@ -62,7 +62,7 @@ static void rtc_timer_update(RTCState *s
    54.4  #ifdef DEBUG_RTC
    54.5          printk("HVM_RTC: period = %uns\n", period);
    54.6  #endif
    54.7 -        create_periodic_time(&s->pt, period, RTC_IRQ, 0, rtc_periodic_cb, s);
    54.8 +        create_periodic_time(current, &s->pt, period, RTC_IRQ, 0, rtc_periodic_cb, s);
    54.9      } 
   54.10      else
   54.11          destroy_periodic_time(&s->pt);
    55.1 --- a/xen/arch/x86/hvm/vioapic.c	Wed Jan 17 21:45:34 2007 -0700
    55.2 +++ b/xen/arch/x86/hvm/vioapic.c	Thu Jan 18 18:25:04 2007 +0000
    55.3 @@ -473,11 +473,143 @@ void vioapic_update_EOI(struct domain *d
    55.4      spin_unlock(&hvm_irq->lock);
    55.5  }
    55.6  
    55.7 +#ifdef HVM_DEBUG_SUSPEND
    55.8 +static void ioapic_info(struct vioapic *s)
    55.9 +{
   55.10 +    int i;
   55.11 +    printk("*****ioapic state:*****\n");
   55.12 +    printk("ioapic 0x%x.\n", s->ioregsel);
   55.13 +    printk("ioapic 0x%x.\n", s->id);
   55.14 +    printk("ioapic 0x%lx.\n", s->base_address);
   55.15 +    for (i = 0; i < VIOAPIC_NUM_PINS; i++) {
   55.16 +        printk("ioapic redirtbl[%d]:0x%"PRIx64"\n", i, s->redirtbl[i].bits);
   55.17 +    }
   55.18 +
   55.19 +}
   55.20 +static void hvmirq_info(struct hvm_irq *hvm_irq)
   55.21 +{
   55.22 +    int i;
   55.23 +    printk("*****hvmirq state:*****\n");
   55.24 +    for (i = 0; i < BITS_TO_LONGS(32*4); i++)
   55.25 +        printk("hvmirq pci_intx[%d]:0x%lx.\n", i, hvm_irq->pci_intx[i]);
   55.26 +
   55.27 +    for (i = 0; i < BITS_TO_LONGS(16); i++)
   55.28 +        printk("hvmirq isa_irq[%d]:0x%lx.\n", i, hvm_irq->isa_irq[i]);
   55.29 +
   55.30 +    for (i = 0; i < BITS_TO_LONGS(1); i++)
   55.31 +        printk("hvmirq callback_irq_wire[%d]:0x%lx.\n", i, hvm_irq->callback_irq_wire[i]);
   55.32 +
   55.33 +    printk("hvmirq callback_via_type:0x%x.\n", hvm_irq->callback_via_type);
   55.34 +    printk("hvmirq callback_via:0x%x.\n", hvm_irq->callback_via.gsi);
   55.35 +    
   55.36 +
   55.37 +    for (i = 0; i < 4; i++)
   55.38 +        printk("hvmirq pci_link_route[%d]:0x%"PRIx8".\n", i, hvm_irq->pci_link_route[i]);
   55.39 +
   55.40 +    for (i = 0; i < 4; i++)
   55.41 +        printk("hvmirq pci_link_assert_count[%d]:0x%"PRIx8".\n", i, hvm_irq->pci_link_assert_count[i]);
   55.42 +
   55.43 +    for (i = 0; i < VIOAPIC_NUM_PINS; i++)
   55.44 +        printk("hvmirq gsi_assert_count[%d]:0x%"PRIx8".\n", i, hvm_irq->gsi_assert_count[i]);
   55.45 +
   55.46 +    printk("hvmirq round_robin_prev_vcpu:0x%"PRIx8".\n", hvm_irq->round_robin_prev_vcpu);
   55.47 +}
   55.48 +#else
   55.49 +static void ioapic_info(struct vioapic *s)
   55.50 +{
   55.51 +}
   55.52 +static void hvmirq_info(struct hvm_irq *hvm_irq)
   55.53 +{
   55.54 +}
   55.55 +#endif
   55.56 +
   55.57 +static void ioapic_save(hvm_domain_context_t *h, void *opaque)
   55.58 +{
   55.59 +    int i;
   55.60 +    struct domain *d = opaque;
   55.61 +    struct vioapic *s = domain_vioapic(d);
   55.62 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
   55.63 +
   55.64 +    ioapic_info(s);
   55.65 +    hvmirq_info(hvm_irq);
   55.66 +
   55.67 +    /* save iopaic state*/
   55.68 +    hvm_put_32u(h, s->ioregsel);
   55.69 +    hvm_put_32u(h, s->id);
   55.70 +    hvm_put_64u(h, s->base_address);
   55.71 +    for (i = 0; i < VIOAPIC_NUM_PINS; i++) {
   55.72 +        hvm_put_64u(h, s->redirtbl[i].bits);
   55.73 +    }
   55.74 +
   55.75 +    /* save hvm irq state */
   55.76 +    hvm_put_buffer(h, (char*)hvm_irq->pci_intx, 16);
   55.77 +    hvm_put_buffer(h, (char*)hvm_irq->isa_irq, 2);
   55.78 +    hvm_put_32u(h, hvm_irq->callback_via_asserted);
   55.79 +    hvm_put_32u(h, hvm_irq->callback_via_type);
   55.80 +    hvm_put_32u(h, hvm_irq->callback_via.gsi);
   55.81 +
   55.82 +    for (i = 0; i < 4; i++)
   55.83 +        hvm_put_8u(h, hvm_irq->pci_link_route[i]);
   55.84 +
   55.85 +    for (i = 0; i < 4; i++)
   55.86 +        hvm_put_8u(h, hvm_irq->pci_link_assert_count[i]);
   55.87 +
   55.88 +    for (i = 0; i < VIOAPIC_NUM_PINS; i++)
   55.89 +        hvm_put_8u(h, hvm_irq->gsi_assert_count[i]);
   55.90 +
   55.91 +    hvm_put_8u(h, hvm_irq->round_robin_prev_vcpu);
   55.92 +
   55.93 +}
   55.94 +
   55.95 +static int ioapic_load(hvm_domain_context_t *h, void *opaque, int version_id)
   55.96 +{
   55.97 +    int i;
   55.98 +    struct domain *d = opaque;
   55.99 +    struct vioapic *s = domain_vioapic(d);
  55.100 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
  55.101 +    
  55.102 +    if (version_id != 1)
  55.103 +        return -EINVAL;
  55.104 +
  55.105 +    /* restore ioapic state */
  55.106 +    s->ioregsel = hvm_get_32u(h);
  55.107 +    s->id = hvm_get_32u(h);
  55.108 +    s->base_address = hvm_get_64u(h);
  55.109 +    for (i = 0; i < VIOAPIC_NUM_PINS; i++) {
  55.110 +        s->redirtbl[i].bits = hvm_get_64u(h);
  55.111 +    }
  55.112 +
  55.113 +    /* restore irq state */
  55.114 +    hvm_get_buffer(h, (char*)hvm_irq->pci_intx, 16);
  55.115 +    hvm_get_buffer(h, (char*)hvm_irq->isa_irq, 2);
  55.116 +    hvm_irq->callback_via_asserted = hvm_get_32u(h);
  55.117 +    hvm_irq->callback_via_type = hvm_get_32u(h);
  55.118 +    hvm_irq->callback_via.gsi = hvm_get_32u(h);
  55.119 +
  55.120 +    for (i = 0; i < 4; i++)
  55.121 +        hvm_irq->pci_link_route[i] = hvm_get_8u(h);
  55.122 +
  55.123 +    for (i = 0; i < 4; i++)
  55.124 +        hvm_irq->pci_link_assert_count[i] = hvm_get_8u(h);
  55.125 +
  55.126 +    for (i = 0; i < VIOAPIC_NUM_PINS; i++)
  55.127 +        hvm_irq->gsi_assert_count[i] = hvm_get_8u(h);
  55.128 +
  55.129 +    hvm_irq->round_robin_prev_vcpu = hvm_get_8u(h);
  55.130 +
  55.131 +    ioapic_info(s);
  55.132 +    hvmirq_info(hvm_irq);
  55.133 +
  55.134 +    return 0;
  55.135 +}
  55.136 +
  55.137  void vioapic_init(struct domain *d)
  55.138  {
  55.139      struct vioapic *vioapic = domain_vioapic(d);
  55.140      int i;
  55.141  
  55.142 +    hvm_register_savevm(d, "xen_hvm_ioapic", 0, 1, ioapic_save, ioapic_load, d);
  55.143 +
  55.144      memset(vioapic, 0, sizeof(*vioapic));
  55.145      for ( i = 0; i < VIOAPIC_NUM_PINS; i++ )
  55.146          vioapic->redirtbl[i].fields.mask = 1;
    56.1 --- a/xen/arch/x86/hvm/vlapic.c	Wed Jan 17 21:45:34 2007 -0700
    56.2 +++ b/xen/arch/x86/hvm/vlapic.c	Thu Jan 18 18:25:04 2007 +0000
    56.3 @@ -659,7 +659,7 @@ static void vlapic_write(struct vcpu *v,
    56.4          uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)val * vlapic->timer_divisor;
    56.5  
    56.6          vlapic_set_reg(vlapic, APIC_TMICT, val);
    56.7 -        create_periodic_time(&vlapic->pt, period, vlapic->pt.irq,
    56.8 +        create_periodic_time(current, &vlapic->pt, period, vlapic->pt.irq,
    56.9                               vlapic_lvtt_period(vlapic), NULL, vlapic);
   56.10  
   56.11          HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
   56.12 @@ -795,6 +795,77 @@ static int vlapic_reset(struct vlapic *v
   56.13      return 1;
   56.14  }
   56.15  
   56.16 +#ifdef HVM_DEBUG_SUSPEND
   56.17 +static void lapic_info(struct vlapic *s)
   56.18 +{
   56.19 +    printk("*****lapic state:*****\n");
   56.20 +    printk("lapic 0x%"PRIx64".\n", s->apic_base_msr);
   56.21 +    printk("lapic 0x%x.\n", s->disabled);
   56.22 +    printk("lapic 0x%x.\n", s->timer_divisor);
   56.23 +    printk("lapic 0x%x.\n", s->timer_pending_count);
   56.24 +}
   56.25 +#else
   56.26 +static void lapic_info(struct vlapic *s)
   56.27 +{
   56.28 +}
   56.29 +#endif
   56.30 +
   56.31 +static void lapic_save(hvm_domain_context_t *h, void *opaque)
   56.32 +{
   56.33 +    struct vlapic *s = opaque;
   56.34 +
   56.35 +    lapic_info(s);
   56.36 +
   56.37 +    hvm_put_64u(h, s->apic_base_msr);
   56.38 +    hvm_put_32u(h, s->disabled);
   56.39 +    hvm_put_32u(h, s->timer_divisor);
   56.40 +
   56.41 +    /*XXX: need this?*/
   56.42 +    hvm_put_32u(h, s->timer_pending_count);
   56.43 +
   56.44 +    hvm_put_buffer(h, (char*)s->regs, 0x3f0);
   56.45 +
   56.46 +}
   56.47 +
   56.48 +static int lapic_load(hvm_domain_context_t *h, void *opaque, int version_id)
   56.49 +{
   56.50 +    struct vlapic *s = opaque;
   56.51 +    struct vcpu *v = vlapic_vcpu(s);
   56.52 +    unsigned long tmict;
   56.53 +
   56.54 +    if (version_id != 1)
   56.55 +        return -EINVAL;
   56.56 +
   56.57 +    s->apic_base_msr = hvm_get_64u(h);
   56.58 +    s->disabled = hvm_get_32u(h);
   56.59 +    s->timer_divisor = hvm_get_32u(h);
   56.60 +
   56.61 +    /*XXX: need this?*/
   56.62 +    s->timer_pending_count = hvm_get_32u(h);
   56.63 +
   56.64 +    hvm_get_buffer(h, (char*)s->regs, 0x3f0);
   56.65 +
   56.66 +    /* rearm the actiemr if needed */
   56.67 +    tmict = vlapic_get_reg(s, APIC_TMICT);
   56.68 +    if (tmict > 0) {
   56.69 +        uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)tmict * s->timer_divisor;
   56.70 +
   56.71 +        create_periodic_time(v, &s->pt, period, s->pt.irq,
   56.72 +                             vlapic_lvtt_period(s), NULL, s);
   56.73 +
   56.74 +        printk("lapic_load to rearm the actimer:"
   56.75 +                    "bus cycle is %uns, "
   56.76 +                    "saved tmict count %lu, period %"PRIu64"ns\n",
   56.77 +                    APIC_BUS_CYCLE_NS, tmict, period);
   56.78 +
   56.79 +    }
   56.80 +
   56.81 +
   56.82 +    lapic_info(s);
   56.83 +
   56.84 +    return 0;
   56.85 +}
   56.86 +
   56.87  int vlapic_init(struct vcpu *v)
   56.88  {
   56.89      struct vlapic *vlapic = vcpu_vlapic(v);
   56.90 @@ -813,6 +884,7 @@ int vlapic_init(struct vcpu *v)
   56.91      vlapic->regs = map_domain_page_global(page_to_mfn(vlapic->regs_page));
   56.92      memset(vlapic->regs, 0, PAGE_SIZE);
   56.93  
   56.94 +    hvm_register_savevm(v->domain, "xen_hvm_lapic", v->vcpu_id, 1, lapic_save, lapic_load, vlapic);
   56.95      vlapic_reset(vlapic);
   56.96  
   56.97      vlapic->apic_base_msr = MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
    57.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Wed Jan 17 21:45:34 2007 -0700
    57.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Thu Jan 18 18:25:04 2007 +0000
    57.3 @@ -363,6 +363,299 @@ static inline void __restore_debug_regis
    57.4      /* DR7 is loaded from the VMCS. */
    57.5  }
    57.6  
    57.7 +static int __get_instruction_length(void);
    57.8 +int vmx_vmcs_save(struct vcpu *v, struct vmcs_data *c)
    57.9 +{
   57.10 +    unsigned long inst_len;
   57.11 +
   57.12 +    inst_len = __get_instruction_length();
   57.13 +    c->eip = __vmread(GUEST_RIP);
   57.14 +
   57.15 +#ifdef HVM_DEBUG_SUSPEND
   57.16 +    printk("vmx_vmcs_save: inst_len=0x%lx, eip=0x%"PRIx64".\n", 
   57.17 +            inst_len, c->eip);
   57.18 +#endif
   57.19 +
   57.20 +    c->esp = __vmread(GUEST_RSP);
   57.21 +    c->eflags = __vmread(GUEST_RFLAGS);
   57.22 +
   57.23 +    c->cr0 = v->arch.hvm_vmx.cpu_shadow_cr0;
   57.24 +    c->cr3 = v->arch.hvm_vmx.cpu_cr3;
   57.25 +    c->cr4 = v->arch.hvm_vmx.cpu_shadow_cr4;
   57.26 +
   57.27 +#ifdef HVM_DEBUG_SUSPEND
   57.28 +    printk("vmx_vmcs_save: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n",
   57.29 +            c->cr3,
   57.30 +            c->cr0,
   57.31 +            c->cr4);
   57.32 +#endif
   57.33 +
   57.34 +    c->idtr_limit = __vmread(GUEST_IDTR_LIMIT);
   57.35 +    c->idtr_base = __vmread(GUEST_IDTR_BASE);
   57.36 +
   57.37 +    c->gdtr_limit = __vmread(GUEST_GDTR_LIMIT);
   57.38 +    c->gdtr_base = __vmread(GUEST_GDTR_BASE);
   57.39 +
   57.40 +    c->cs_sel = __vmread(GUEST_CS_SELECTOR);
   57.41 +    c->cs_limit = __vmread(GUEST_CS_LIMIT);
   57.42 +    c->cs_base = __vmread(GUEST_CS_BASE);
   57.43 +    c->cs_arbytes = __vmread(GUEST_CS_AR_BYTES);
   57.44 +
   57.45 +    c->ds_sel = __vmread(GUEST_DS_SELECTOR);
   57.46 +    c->ds_limit = __vmread(GUEST_DS_LIMIT);
   57.47 +    c->ds_base = __vmread(GUEST_DS_BASE);
   57.48 +    c->ds_arbytes = __vmread(GUEST_DS_AR_BYTES);
   57.49 +
   57.50 +    c->es_sel = __vmread(GUEST_ES_SELECTOR);
   57.51 +    c->es_limit = __vmread(GUEST_ES_LIMIT);
   57.52 +    c->es_base = __vmread(GUEST_ES_BASE);
   57.53 +    c->es_arbytes = __vmread(GUEST_ES_AR_BYTES);
   57.54 +
   57.55 +    c->ss_sel = __vmread(GUEST_SS_SELECTOR);
   57.56 +    c->ss_limit = __vmread(GUEST_SS_LIMIT);
   57.57 +    c->ss_base = __vmread(GUEST_SS_BASE);
   57.58 +    c->ss_arbytes = __vmread(GUEST_SS_AR_BYTES);
   57.59 +
   57.60 +    c->fs_sel = __vmread(GUEST_FS_SELECTOR);
   57.61 +    c->fs_limit = __vmread(GUEST_FS_LIMIT);
   57.62 +    c->fs_base = __vmread(GUEST_FS_BASE);
   57.63 +    c->fs_arbytes = __vmread(GUEST_FS_AR_BYTES);
   57.64 +
   57.65 +    c->gs_sel = __vmread(GUEST_GS_SELECTOR);
   57.66 +    c->gs_limit = __vmread(GUEST_GS_LIMIT);
   57.67 +    c->gs_base = __vmread(GUEST_GS_BASE);
   57.68 +    c->gs_arbytes = __vmread(GUEST_GS_AR_BYTES);
   57.69 +
   57.70 +    c->tr_sel = __vmread(GUEST_TR_SELECTOR);
   57.71 +    c->tr_limit = __vmread(GUEST_TR_LIMIT);
   57.72 +    c->tr_base = __vmread(GUEST_TR_BASE);
   57.73 +    c->tr_arbytes = __vmread(GUEST_TR_AR_BYTES);
   57.74 +
   57.75 +    c->ldtr_sel = __vmread(GUEST_LDTR_SELECTOR);
   57.76 +    c->ldtr_limit = __vmread(GUEST_LDTR_LIMIT);
   57.77 +    c->ldtr_base = __vmread(GUEST_LDTR_BASE);
   57.78 +    c->ldtr_arbytes = __vmread(GUEST_LDTR_AR_BYTES);
   57.79 +
   57.80 +    c->sysenter_cs = __vmread(GUEST_SYSENTER_CS);
   57.81 +    c->sysenter_esp = __vmread(GUEST_SYSENTER_ESP);
   57.82 +    c->sysenter_eip = __vmread(GUEST_SYSENTER_EIP);
   57.83 +
   57.84 +    return 1;
   57.85 +}
   57.86 +
   57.87 +int vmx_vmcs_restore(struct vcpu *v, struct vmcs_data *c)
   57.88 +{
   57.89 +    unsigned long mfn, old_base_mfn;
   57.90 +
   57.91 +    vmx_vmcs_enter(v);
   57.92 +
   57.93 +    __vmwrite(GUEST_RIP, c->eip);
   57.94 +    __vmwrite(GUEST_RSP, c->esp);
   57.95 +    __vmwrite(GUEST_RFLAGS, c->eflags);
   57.96 +
   57.97 +    v->arch.hvm_vmx.cpu_shadow_cr0 = c->cr0;
   57.98 +    __vmwrite(CR0_READ_SHADOW, v->arch.hvm_vmx.cpu_shadow_cr0);
   57.99 +
  57.100 +#ifdef HVM_DEBUG_SUSPEND
  57.101 +    printk("vmx_vmcs_restore: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n",
  57.102 +            c->cr3,
  57.103 +            c->cr0,
  57.104 +            c->cr4);
  57.105 +#endif
  57.106 +
  57.107 +    if (!vmx_paging_enabled(v)) {
  57.108 +        printk("vmx_vmcs_restore: paging not enabled.");
  57.109 +        goto skip_cr3;
  57.110 +    }
  57.111 +
  57.112 +    if (c->cr3 == v->arch.hvm_vmx.cpu_cr3) {
  57.113 +        /*
  57.114 +         * This is simple TLB flush, implying the guest has
  57.115 +         * removed some translation or changed page attributes.
  57.116 +         * We simply invalidate the shadow.
  57.117 +         */
  57.118 +        mfn = gmfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT);
  57.119 +        if (mfn != pagetable_get_pfn(v->arch.guest_table)) {
  57.120 +            goto bad_cr3;
  57.121 +        }
  57.122 +    } else {
  57.123 +        /*
  57.124 +         * If different, make a shadow. Check if the PDBR is valid
  57.125 +         * first.
  57.126 +         */
  57.127 +        HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %"PRIx64"", c->cr3);
  57.128 +        /* current!=vcpu as not called by arch_vmx_do_launch */
  57.129 +        mfn = gmfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT);
  57.130 +        if( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain)) {
  57.131 +            goto bad_cr3;
  57.132 +        }
  57.133 +        old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
  57.134 +        v->arch.guest_table = pagetable_from_pfn(mfn);
  57.135 +        if (old_base_mfn)
  57.136 +             put_page(mfn_to_page(old_base_mfn));
  57.137 +        /*
  57.138 +         * arch.shadow_table should now hold the next CR3 for shadow
  57.139 +         */
  57.140 +        v->arch.hvm_vmx.cpu_cr3 = c->cr3;
  57.141 +    }
  57.142 +
  57.143 + skip_cr3:
  57.144 +#if defined(__x86_64__)
  57.145 +    if (vmx_long_mode_enabled(v)) {
  57.146 +        unsigned long vm_entry_value;
  57.147 +        vm_entry_value = __vmread(VM_ENTRY_CONTROLS);
  57.148 +        vm_entry_value |= VM_ENTRY_IA32E_MODE;
  57.149 +        __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value);
  57.150 +    }
  57.151 +#endif
  57.152 +
  57.153 +    __vmwrite(GUEST_CR4, (c->cr4 | VMX_CR4_HOST_MASK));
  57.154 +    v->arch.hvm_vmx.cpu_shadow_cr4 = c->cr4;
  57.155 +    __vmwrite(CR4_READ_SHADOW, v->arch.hvm_vmx.cpu_shadow_cr4);
  57.156 +
  57.157 +    __vmwrite(GUEST_IDTR_LIMIT, c->idtr_limit);
  57.158 +    __vmwrite(GUEST_IDTR_BASE, c->idtr_base);
  57.159 +
  57.160 +    __vmwrite(GUEST_GDTR_LIMIT, c->gdtr_limit);
  57.161 +    __vmwrite(GUEST_GDTR_BASE, c->gdtr_base);
  57.162 +
  57.163 +    __vmwrite(GUEST_CS_SELECTOR, c->cs_sel);
  57.164 +    __vmwrite(GUEST_CS_LIMIT, c->cs_limit);
  57.165 +    __vmwrite(GUEST_CS_BASE, c->cs_base);
  57.166 +    __vmwrite(GUEST_CS_AR_BYTES, c->cs_arbytes);
  57.167 +
  57.168 +    __vmwrite(GUEST_DS_SELECTOR, c->ds_sel);
  57.169 +    __vmwrite(GUEST_DS_LIMIT, c->ds_limit);
  57.170 +    __vmwrite(GUEST_DS_BASE, c->ds_base);
  57.171 +    __vmwrite(GUEST_DS_AR_BYTES, c->ds_arbytes);
  57.172 +
  57.173 +    __vmwrite(GUEST_ES_SELECTOR, c->es_sel);
  57.174 +    __vmwrite(GUEST_ES_LIMIT, c->es_limit);
  57.175 +    __vmwrite(GUEST_ES_BASE, c->es_base);
  57.176 +    __vmwrite(GUEST_ES_AR_BYTES, c->es_arbytes);
  57.177 +
  57.178 +    __vmwrite(GUEST_SS_SELECTOR, c->ss_sel);
  57.179 +    __vmwrite(GUEST_SS_LIMIT, c->ss_limit);
  57.180 +    __vmwrite(GUEST_SS_BASE, c->ss_base);
  57.181 +    __vmwrite(GUEST_SS_AR_BYTES, c->ss_arbytes);
  57.182 +
  57.183 +    __vmwrite(GUEST_FS_SELECTOR, c->fs_sel);
  57.184 +    __vmwrite(GUEST_FS_LIMIT, c->fs_limit);
  57.185 +    __vmwrite(GUEST_FS_BASE, c->fs_base);
  57.186 +    __vmwrite(GUEST_FS_AR_BYTES, c->fs_arbytes);
  57.187 +
  57.188 +    __vmwrite(GUEST_GS_SELECTOR, c->gs_sel);
  57.189 +    __vmwrite(GUEST_GS_LIMIT, c->gs_limit);
  57.190 +    __vmwrite(GUEST_GS_BASE, c->gs_base);
  57.191 +    __vmwrite(GUEST_GS_AR_BYTES, c->gs_arbytes);
  57.192 +
  57.193 +    __vmwrite(GUEST_TR_SELECTOR, c->tr_sel);
  57.194 +    __vmwrite(GUEST_TR_LIMIT, c->tr_limit);
  57.195 +    __vmwrite(GUEST_TR_BASE, c->tr_base);
  57.196 +    __vmwrite(GUEST_TR_AR_BYTES, c->tr_arbytes);
  57.197 +
  57.198 +    __vmwrite(GUEST_LDTR_SELECTOR, c->ldtr_sel);
  57.199 +    __vmwrite(GUEST_LDTR_LIMIT, c->ldtr_limit);
  57.200 +    __vmwrite(GUEST_LDTR_BASE, c->ldtr_base);
  57.201 +    __vmwrite(GUEST_LDTR_AR_BYTES, c->ldtr_arbytes);
  57.202 +
  57.203 +    __vmwrite(GUEST_SYSENTER_CS, c->sysenter_cs);
  57.204 +    __vmwrite(GUEST_SYSENTER_ESP, c->sysenter_esp);
  57.205 +    __vmwrite(GUEST_SYSENTER_EIP, c->sysenter_eip);
  57.206 +
  57.207 +    vmx_vmcs_exit(v);
  57.208 +
  57.209 +    shadow_update_paging_modes(v);
  57.210 +    return 0;
  57.211 +
  57.212 + bad_cr3:
  57.213 +    gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%"PRIx64"", c->cr3);
  57.214 +    vmx_vmcs_exit(v);
  57.215 +    return -EINVAL;
  57.216 +}
  57.217 +
  57.218 +#ifdef HVM_DEBUG_SUSPEND
  57.219 +static void dump_msr_state(struct vmx_msr_state *m)
  57.220 +{
  57.221 +    int i = 0;
  57.222 +    printk("**** msr state ****\n");
  57.223 +    printk("shadow_gs=0x%lx, flags=0x%lx, msr_items:", m->shadow_gs, m->flags);
  57.224 +    for (i = 0; i < VMX_MSR_COUNT; i++)
  57.225 +        printk("0x%lx,", m->msrs[i]);
  57.226 +    printk("\n");
  57.227 +}
  57.228 +#else
  57.229 +static void dump_msr_state(struct vmx_msr_state *m)
  57.230 +{
  57.231 +}
  57.232 +#endif
  57.233 +        
  57.234 +void vmx_save_cpu_state(struct vcpu *v, struct hvmcpu_context *ctxt)
  57.235 +{
  57.236 +    struct vmcs_data *data = &ctxt->data;
  57.237 +    struct vmx_msr_state *guest_state = &v->arch.hvm_vmx.msr_state;
  57.238 +    unsigned long guest_flags = guest_state->flags;
  57.239 +    int i = 0;
  57.240 +
  57.241 +    data->shadow_gs = guest_state->shadow_gs;
  57.242 +    data->vmxassist_enabled = v->arch.hvm_vmx.vmxassist_enabled;
  57.243 +    /* save msrs */
  57.244 +    data->flags = guest_flags;
  57.245 +    for (i = 0; i < VMX_MSR_COUNT; i++)
  57.246 +        data->msr_items[i] = guest_state->msrs[i];
  57.247 +
  57.248 +    dump_msr_state(guest_state);
  57.249 +}
  57.250 +
  57.251 +void vmx_load_cpu_state(struct vcpu *v, struct hvmcpu_context *ctxt)
  57.252 +{
  57.253 +    int i = 0;
  57.254 +    struct vmcs_data *data = &ctxt->data;
  57.255 +    struct vmx_msr_state *guest_state = &v->arch.hvm_vmx.msr_state;
  57.256 +
  57.257 +    /* restore msrs */
  57.258 +    guest_state->flags = data->flags;
  57.259 +    for (i = 0; i < VMX_MSR_COUNT; i++)
  57.260 +        guest_state->msrs[i] = data->msr_items[i];
  57.261 +
  57.262 +    guest_state->shadow_gs = data->shadow_gs;
  57.263 +
  57.264 +    /*XXX:no need to restore msrs, current!=vcpu as not called by arch_vmx_do_launch */
  57.265 +/*    vmx_restore_guest_msrs(v);*/
  57.266 +
  57.267 +    v->arch.hvm_vmx.vmxassist_enabled = data->vmxassist_enabled;
  57.268 +
  57.269 +    dump_msr_state(guest_state);
  57.270 +}
  57.271 +
  57.272 +void vmx_save_vmcs_ctxt(struct vcpu *v, struct hvmcpu_context *ctxt)
  57.273 +{
  57.274 +    struct vmcs_data *data = &ctxt->data;
  57.275 +
  57.276 +    vmx_save_cpu_state(v, ctxt);
  57.277 +
  57.278 +    vmx_vmcs_enter(v);
  57.279 +
  57.280 +    vmx_vmcs_save(v, data);
  57.281 +
  57.282 +    vmx_vmcs_exit(v);
  57.283 +
  57.284 +}
  57.285 +
  57.286 +void vmx_load_vmcs_ctxt(struct vcpu *v, struct hvmcpu_context *ctxt)
  57.287 +{
  57.288 +    vmx_load_cpu_state(v, ctxt);
  57.289 +
  57.290 +    if (vmx_vmcs_restore(v, &ctxt->data)) {
  57.291 +        printk("vmx_vmcs restore failed!\n");
  57.292 +        domain_crash(v->domain);
  57.293 +    }
  57.294 +
  57.295 +    /* only load vmcs once */
  57.296 +    ctxt->valid = 0;
  57.297 +
  57.298 +}
  57.299 +
  57.300  /*
  57.301   * DR7 is saved and restored on every vmexit.  Other debug registers only
  57.302   * need to be restored if their value is going to affect execution -- i.e.,
  57.303 @@ -721,6 +1014,9 @@ static void vmx_setup_hvm_funcs(void)
  57.304      hvm_funcs.store_cpu_guest_regs = vmx_store_cpu_guest_regs;
  57.305      hvm_funcs.load_cpu_guest_regs = vmx_load_cpu_guest_regs;
  57.306  
  57.307 +    hvm_funcs.save_cpu_ctxt = vmx_save_vmcs_ctxt;
  57.308 +    hvm_funcs.load_cpu_ctxt = vmx_load_vmcs_ctxt;
  57.309 +
  57.310      hvm_funcs.paging_enabled = vmx_paging_enabled;
  57.311      hvm_funcs.long_mode_enabled = vmx_long_mode_enabled;
  57.312      hvm_funcs.pae_enabled = vmx_pae_enabled;
    58.1 --- a/xen/arch/x86/hvm/vpic.c	Wed Jan 17 21:45:34 2007 -0700
    58.2 +++ b/xen/arch/x86/hvm/vpic.c	Thu Jan 18 18:25:04 2007 +0000
    58.3 @@ -378,6 +378,87 @@ static int vpic_intercept_elcr_io(ioreq_
    58.4      return 1;
    58.5  }
    58.6  
    58.7 +#ifdef HVM_DEBUG_SUSPEND
    58.8 +static void vpic_info(struct vpic *s)
    58.9 +{
   58.10 +    printk("*****pic state:*****\n");
   58.11 +    printk("pic 0x%x.\n", s->irr);
   58.12 +    printk("pic 0x%x.\n", s->imr);
   58.13 +    printk("pic 0x%x.\n", s->isr);
   58.14 +    printk("pic 0x%x.\n", s->irq_base);
   58.15 +    printk("pic 0x%x.\n", s->init_state);
   58.16 +    printk("pic 0x%x.\n", s->priority_add);
   58.17 +    printk("pic 0x%x.\n", s->readsel_isr);
   58.18 +    printk("pic 0x%x.\n", s->poll);
   58.19 +    printk("pic 0x%x.\n", s->auto_eoi);
   58.20 +    printk("pic 0x%x.\n", s->rotate_on_auto_eoi);
   58.21 +    printk("pic 0x%x.\n", s->special_fully_nested_mode);
   58.22 +    printk("pic 0x%x.\n", s->special_mask_mode);
   58.23 +    printk("pic 0x%x.\n", s->elcr);
   58.24 +    printk("pic 0x%x.\n", s->int_output);
   58.25 +    printk("pic 0x%x.\n", s->is_master);
   58.26 +}
   58.27 +#else
   58.28 +static void vpic_info(struct vpic *s)
   58.29 +{
   58.30 +}
   58.31 +#endif
   58.32 +
   58.33 +static void vpic_save(hvm_domain_context_t *h, void *opaque)
   58.34 +{
   58.35 +    struct vpic *s = opaque;
   58.36 +    
   58.37 +    vpic_info(s);
   58.38 +
   58.39 +    hvm_put_8u(h, s->irr);
   58.40 +    hvm_put_8u(h, s->imr);
   58.41 +    hvm_put_8u(h, s->isr);
   58.42 +    hvm_put_8u(h, s->irq_base);
   58.43 +    hvm_put_8u(h, s->init_state);
   58.44 +    hvm_put_8u(h, s->priority_add);
   58.45 +    hvm_put_8u(h, s->readsel_isr);
   58.46 +
   58.47 +    hvm_put_8u(h, s->poll);
   58.48 +    hvm_put_8u(h, s->auto_eoi);
   58.49 +
   58.50 +    hvm_put_8u(h, s->rotate_on_auto_eoi);
   58.51 +    hvm_put_8u(h, s->special_fully_nested_mode);
   58.52 +    hvm_put_8u(h, s->special_mask_mode);
   58.53 +
   58.54 +    hvm_put_8u(h, s->elcr);
   58.55 +    hvm_put_8u(h, s->int_output);
   58.56 +}
   58.57 +
   58.58 +static int vpic_load(hvm_domain_context_t *h, void *opaque, int version_id)
   58.59 +{
   58.60 +    struct vpic *s = opaque;
   58.61 +    
   58.62 +    if (version_id != 1)
   58.63 +        return -EINVAL;
   58.64 +
   58.65 +    s->irr = hvm_get_8u(h);
   58.66 +    s->imr = hvm_get_8u(h);
   58.67 +    s->isr = hvm_get_8u(h);
   58.68 +    s->irq_base = hvm_get_8u(h);
   58.69 +    s->init_state = hvm_get_8u(h);
   58.70 +    s->priority_add = hvm_get_8u(h);
   58.71 +    s->readsel_isr = hvm_get_8u(h);
   58.72 +
   58.73 +    s->poll = hvm_get_8u(h);
   58.74 +    s->auto_eoi = hvm_get_8u(h);
   58.75 +
   58.76 +    s->rotate_on_auto_eoi = hvm_get_8u(h);
   58.77 +    s->special_fully_nested_mode = hvm_get_8u(h);
   58.78 +    s->special_mask_mode = hvm_get_8u(h);
   58.79 +
   58.80 +    s->elcr = hvm_get_8u(h);
   58.81 +    s->int_output = hvm_get_8u(h);
   58.82 +
   58.83 +    vpic_info(s);
   58.84 +
   58.85 +    return 0;
   58.86 +}
   58.87 +
   58.88  void vpic_init(struct domain *d)
   58.89  {
   58.90      struct vpic *vpic;
   58.91 @@ -387,12 +468,14 @@ void vpic_init(struct domain *d)
   58.92      memset(vpic, 0, sizeof(*vpic));
   58.93      vpic->is_master = 1;
   58.94      vpic->elcr      = 1 << 2;
   58.95 +    hvm_register_savevm(d, "xen_hvm_i8259", 0x20, 1, vpic_save, vpic_load, vpic);
   58.96      register_portio_handler(d, 0x20, 2, vpic_intercept_pic_io);
   58.97      register_portio_handler(d, 0x4d0, 1, vpic_intercept_elcr_io);
   58.98  
   58.99      /* Slave PIC. */
  58.100      vpic++;
  58.101      memset(vpic, 0, sizeof(*vpic));
  58.102 +    hvm_register_savevm(d, "xen_hvm_i8259", 0xa0, 1, vpic_save, vpic_load, vpic);
  58.103      register_portio_handler(d, 0xa0, 2, vpic_intercept_pic_io);
  58.104      register_portio_handler(d, 0x4d1, 1, vpic_intercept_elcr_io);
  58.105  }
    59.1 --- a/xen/arch/x86/hvm/vpt.c	Wed Jan 17 21:45:34 2007 -0700
    59.2 +++ b/xen/arch/x86/hvm/vpt.c	Thu Jan 18 18:25:04 2007 +0000
    59.3 @@ -195,7 +195,7 @@ void pt_reset(struct vcpu *v)
    59.4      }
    59.5  }
    59.6  
    59.7 -void create_periodic_time(struct periodic_time *pt, uint64_t period,
    59.8 +void create_periodic_time(struct vcpu *v, struct periodic_time *pt, uint64_t period,
    59.9                            uint8_t irq, char one_shot, time_cb *cb, void *data)
   59.10  {
   59.11      destroy_periodic_time(pt);
   59.12 @@ -209,7 +209,7 @@ void create_periodic_time(struct periodi
   59.13          period = 900000; /* force to 0.9ms */
   59.14      }
   59.15      pt->period = period;
   59.16 -    pt->vcpu = current;
   59.17 +    pt->vcpu = v;
   59.18      pt->last_plt_gtime = hvm_get_guest_time(pt->vcpu);
   59.19      pt->irq = irq;
   59.20      pt->period_cycles = (u64)period * cpu_khz / 1000000L;
   59.21 @@ -218,7 +218,7 @@ void create_periodic_time(struct periodi
   59.22      pt->cb = cb;
   59.23      pt->priv = data;
   59.24  
   59.25 -    list_add(&pt->list, &current->arch.hvm_vcpu.tm_list);
   59.26 +    list_add(&pt->list, &v->arch.hvm_vcpu.tm_list);
   59.27      set_timer(&pt->timer, pt->scheduled);
   59.28  }
   59.29  
    60.1 --- a/xen/arch/x86/mm.c	Wed Jan 17 21:45:34 2007 -0700
    60.2 +++ b/xen/arch/x86/mm.c	Thu Jan 18 18:25:04 2007 +0000
    60.3 @@ -154,6 +154,15 @@ l2_pgentry_t *compat_idle_pg_table_l2 = 
    60.4  #define l3_disallow_mask(d) L3_DISALLOW_MASK
    60.5  #endif
    60.6  
    60.7 +static void queue_deferred_ops(struct domain *d, unsigned int ops)
    60.8 +{
    60.9 +    if ( d == current->domain )
   60.10 +        this_cpu(percpu_mm_info).deferred_ops |= ops;
   60.11 +    else
   60.12 +        BUG_ON(!test_bit(_DOMF_paused, &d->domain_flags) ||
   60.13 +               !cpus_empty(d->domain_dirty_cpumask));
   60.14 +}
   60.15 +
   60.16  void __init init_frametable(void)
   60.17  {
   60.18      unsigned long nr_pages, page_step, i, mfn;
   60.19 @@ -416,8 +425,7 @@ void invalidate_shadow_ldt(struct vcpu *
   60.20      }
   60.21  
   60.22      /* Dispose of the (now possibly invalid) mappings from the TLB.  */
   60.23 -    ASSERT(v->processor == smp_processor_id());
   60.24 -    this_cpu(percpu_mm_info).deferred_ops |= DOP_FLUSH_TLB | DOP_RELOAD_LDT;
   60.25 +    queue_deferred_ops(v->domain, DOP_FLUSH_TLB | DOP_RELOAD_LDT);
   60.26  }
   60.27  
   60.28  
   60.29 @@ -945,7 +953,8 @@ static int create_pae_xen_mappings(struc
   60.30      }
   60.31  #else
   60.32      memcpy(&pl2e[COMPAT_L2_PAGETABLE_FIRST_XEN_SLOT(d)],
   60.33 -           &compat_idle_pg_table_l2[l2_table_offset(HIRO_COMPAT_MPT_VIRT_START)],
   60.34 +           &compat_idle_pg_table_l2[
   60.35 +               l2_table_offset(HIRO_COMPAT_MPT_VIRT_START)],
   60.36             COMPAT_L2_PAGETABLE_XEN_SLOTS(d) * sizeof(*pl2e));
   60.37  #endif
   60.38      unmap_domain_page(pl2e);
   60.39 @@ -1561,7 +1570,7 @@ void free_page_type(struct page_info *pa
   60.40           * (e.g., update_va_mapping()) or we could end up modifying a page
   60.41           * that is no longer a page table (and hence screw up ref counts).
   60.42           */
   60.43 -        this_cpu(percpu_mm_info).deferred_ops |= DOP_FLUSH_ALL_TLBS;
   60.44 +        queue_deferred_ops(owner, DOP_FLUSH_ALL_TLBS);
   60.45  
   60.46          if ( unlikely(shadow_mode_enabled(owner)) )
   60.47          {
   60.48 @@ -1759,24 +1768,14 @@ int new_guest_cr3(unsigned long mfn)
   60.49      int okay;
   60.50      unsigned long old_base_mfn;
   60.51  
   60.52 -    if ( is_hvm_domain(d) && !hvm_paging_enabled(v) )
   60.53 -        return 0;
   60.54 -
   60.55  #ifdef CONFIG_COMPAT
   60.56      if ( IS_COMPAT(d) )
   60.57      {
   60.58 -        l4_pgentry_t l4e = l4e_from_pfn(mfn, _PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED);
   60.59 -
   60.60 -        if ( shadow_mode_refcounts(d) )
   60.61 -        {
   60.62 -            okay = get_page_from_pagenr(mfn, d);
   60.63 -            old_base_mfn = l4e_get_pfn(l4e);
   60.64 -            if ( okay && old_base_mfn )
   60.65 -                put_page(mfn_to_page(old_base_mfn));
   60.66 -        }
   60.67 -        else
   60.68 -            okay = mod_l4_entry(__va(pagetable_get_paddr(v->arch.guest_table)),
   60.69 -                                l4e, 0);
   60.70 +        okay = shadow_mode_refcounts(d)
   60.71 +            ? 0 /* Old code was broken, but what should it be? */
   60.72 +            : mod_l4_entry(__va(pagetable_get_paddr(v->arch.guest_table)),
   60.73 +                           l4e_from_pfn(mfn, (_PAGE_PRESENT|_PAGE_RW|
   60.74 +                                              _PAGE_USER|_PAGE_ACCESSED)), 0);
   60.75          if ( unlikely(!okay) )
   60.76          {
   60.77              MEM_LOG("Error while installing new compat baseptr %lx", mfn);
   60.78 @@ -1789,41 +1788,13 @@ int new_guest_cr3(unsigned long mfn)
   60.79          return 1;
   60.80      }
   60.81  #endif
   60.82 -    if ( shadow_mode_refcounts(d) )
   60.83 -    {
   60.84 -        okay = get_page_from_pagenr(mfn, d);
   60.85 -        if ( unlikely(!okay) )
   60.86 -        {
   60.87 -            MEM_LOG("Error while installing new baseptr %lx", mfn);
   60.88 -            return 0;
   60.89 -        }
   60.90 -    }
   60.91 -    else
   60.92 +    okay = shadow_mode_refcounts(d)
   60.93 +        ? get_page_from_pagenr(mfn, d)
   60.94 +        : get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d);
   60.95 +    if ( unlikely(!okay) )
   60.96      {
   60.97 -        okay = get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d);
   60.98 -        if ( unlikely(!okay) )
   60.99 -        {
  60.100 -            /* Switch to idle pagetable: this VCPU has no active p.t. now. */
  60.101 -            MEM_LOG("New baseptr %lx: slow path via idle pagetables", mfn);
  60.102 -            old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
  60.103 -            v->arch.guest_table = pagetable_null();
  60.104 -            update_cr3(v);
  60.105 -            write_cr3(__pa(idle_pg_table));
  60.106 -            if ( old_base_mfn != 0 )
  60.107 -                put_page_and_type(mfn_to_page(old_base_mfn));
  60.108 -
  60.109 -            /* Retry the validation with no active p.t. for this VCPU. */
  60.110 -            okay = get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d);
  60.111 -            if ( !okay )
  60.112 -            {
  60.113 -                /* Failure here is unrecoverable: the VCPU has no pagetable! */
  60.114 -                MEM_LOG("Fatal error while installing new baseptr %lx", mfn);
  60.115 -                domain_crash(d);
  60.116 -                ASSERT(v->processor == smp_processor_id());
  60.117 -                this_cpu(percpu_mm_info).deferred_ops = 0;
  60.118 -                return 0;
  60.119 -            }
  60.120 -        }
  60.121 +        MEM_LOG("Error while installing new baseptr %lx", mfn);
  60.122 +        return 0;
  60.123      }
  60.124  
  60.125      invalidate_shadow_ldt(v);
  60.126 @@ -1831,7 +1802,7 @@ int new_guest_cr3(unsigned long mfn)
  60.127      old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
  60.128  
  60.129      v->arch.guest_table = pagetable_from_pfn(mfn);
  60.130 -    update_cr3(v); /* update shadow_table and cr3 fields of vcpu struct */
  60.131 +    update_cr3(v);
  60.132  
  60.133      write_ptbase(v);
  60.134  
    61.1 --- a/xen/arch/x86/mm/shadow/common.c	Wed Jan 17 21:45:34 2007 -0700
    61.2 +++ b/xen/arch/x86/mm/shadow/common.c	Thu Jan 18 18:25:04 2007 +0000
    61.3 @@ -2184,10 +2184,11 @@ int sh_remove_all_mappings(struct vcpu *
    61.4      expected_count = (page->count_info & PGC_allocated) ? 1 : 0;
    61.5      if ( (page->count_info & PGC_count_mask) != expected_count )
    61.6      {
    61.7 -        /* Don't complain if we're in HVM and there's one extra mapping: 
    61.8 -         * The qemu helper process has an untyped mapping of this dom's RAM */
    61.9 +        /* Don't complain if we're in HVM and there are some extra mappings: 
   61.10 +         * The qemu helper process has an untyped mapping of this dom's RAM 
   61.11 +         * and the HVM restore program takes another. */
   61.12          if ( !(shadow_mode_external(v->domain)
   61.13 -               && (page->count_info & PGC_count_mask) <= 2
   61.14 +               && (page->count_info & PGC_count_mask) <= 3
   61.15                 && (page->u.inuse.type_info & PGT_count_mask) == 0) )
   61.16          {
   61.17              SHADOW_ERROR("can't find all mappings of mfn %lx: "
    62.1 --- a/xen/arch/x86/mm/shadow/multi.c	Wed Jan 17 21:45:34 2007 -0700
    62.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Thu Jan 18 18:25:04 2007 +0000
    62.3 @@ -1627,7 +1627,7 @@ sh_make_shadow(struct vcpu *v, mfn_t gmf
    62.4          default: /* Do nothing */ break;
    62.5          }
    62.6      }
    62.7 -    
    62.8 +
    62.9      shadow_promote(v, gmfn, shadow_type);
   62.10      set_shadow_status(v, gmfn, shadow_type, smfn);
   62.11  
    63.1 --- a/xen/common/domain.c	Wed Jan 17 21:45:34 2007 -0700
    63.2 +++ b/xen/common/domain.c	Thu Jan 18 18:25:04 2007 +0000
    63.3 @@ -24,6 +24,7 @@
    63.4  #include <xen/percpu.h>
    63.5  #include <xen/multicall.h>
    63.6  #include <asm/debugger.h>
    63.7 +#include <asm/hvm/support.h>
    63.8  #include <public/sched.h>
    63.9  #include <public/vcpu.h>
   63.10  #ifdef CONFIG_COMPAT
   63.11 @@ -505,6 +506,14 @@ int set_info_guest(struct domain *d,
   63.12      if ( rc == 0 )
   63.13          rc = arch_set_info_guest(v, c);
   63.14  
   63.15 +    /*XXX: hvm smp guest restore support */
   63.16 +    if ( rc == 0 &&
   63.17 +            v->vcpu_id != 0 &&
   63.18 +            is_hvm_vcpu(v) &&
   63.19 +            test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) ) {
   63.20 +        vcpu_wake(v);
   63.21 +    }
   63.22 +
   63.23      domain_unpause(d);
   63.24  
   63.25      xfree(c.nat);
    64.1 --- a/xen/common/domctl.c	Wed Jan 17 21:45:34 2007 -0700
    64.2 +++ b/xen/common/domctl.c	Thu Jan 18 18:25:04 2007 +0000
    64.3 @@ -215,6 +215,39 @@ ret_t do_domctl(XEN_GUEST_HANDLE(xen_dom
    64.4      }
    64.5      break;
    64.6  
    64.7 +    case XEN_DOMCTL_sethvmcontext:
    64.8 +    { 
    64.9 +        struct hvm_domain_context *c;
   64.10 +        struct domain             *d;
   64.11 +        struct vcpu               *v;
   64.12 +
   64.13 +        ret = -ESRCH;
   64.14 +        if ( (d = find_domain_by_id(op->domain)) == NULL )
   64.15 +            break;
   64.16 +
   64.17 +        ret = -ENOMEM;
   64.18 +        if ( (c = xmalloc(struct hvm_domain_context)) == NULL )
   64.19 +            goto sethvmcontext_out;
   64.20 +
   64.21 +        v = d->vcpu[0];
   64.22 +        
   64.23 +        ret = -EFAULT;
   64.24 +
   64.25 +#ifndef CONFIG_COMPAT
   64.26 +        if ( copy_from_guest(c, op->u.hvmcontext.ctxt, 1) != 0 )
   64.27 +            goto sethvmcontext_out;
   64.28 +
   64.29 +        ret = arch_sethvm_ctxt(v, c);
   64.30 +#endif
   64.31 +
   64.32 +        xfree(c);
   64.33 +
   64.34 +    sethvmcontext_out:
   64.35 +        put_domain(d);
   64.36 +
   64.37 +    }
   64.38 +    break;
   64.39 +
   64.40      case XEN_DOMCTL_pausedomain:
   64.41      {
   64.42          struct domain *d = find_domain_by_id(op->domain);
   64.43 @@ -552,6 +585,46 @@ ret_t do_domctl(XEN_GUEST_HANDLE(xen_dom
   64.44      }
   64.45      break;
   64.46  
   64.47 +    case XEN_DOMCTL_gethvmcontext:
   64.48 +    { 
   64.49 +        struct hvm_domain_context *c;
   64.50 +        struct domain             *d;
   64.51 +        struct vcpu               *v;
   64.52 +
   64.53 +        ret = -ESRCH;
   64.54 +        if ( (d = find_domain_by_id(op->domain)) == NULL )
   64.55 +            break;
   64.56 +
   64.57 +        ret = -ENOMEM;
   64.58 +        if ( (c = xmalloc(struct hvm_domain_context)) == NULL )
   64.59 +            goto gethvmcontext_out;
   64.60 +
   64.61 +        v = d->vcpu[0];
   64.62 +
   64.63 +        ret = -ENODATA;
   64.64 +        if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
   64.65 +            goto gethvmcontext_out;
   64.66 +        
   64.67 +        ret = 0;
   64.68 +        if (arch_gethvm_ctxt(v, c) == -1)
   64.69 +            ret = -EFAULT;
   64.70 +
   64.71 +#ifndef CONFIG_COMPAT
   64.72 +        if ( copy_to_guest(op->u.hvmcontext.ctxt, c, 1) )
   64.73 +            ret = -EFAULT;
   64.74 +
   64.75 +        xfree(c);
   64.76 +#endif
   64.77 +
   64.78 +        if ( copy_to_guest(u_domctl, op, 1) )
   64.79 +            ret = -EFAULT;
   64.80 +
   64.81 +    gethvmcontext_out:
   64.82 +        put_domain(d);
   64.83 +
   64.84 +    }
   64.85 +    break;
   64.86 +
   64.87      case XEN_DOMCTL_getvcpuinfo:
   64.88      { 
   64.89          struct domain *d;
    65.1 --- a/xen/include/asm-x86/hvm/domain.h	Wed Jan 17 21:45:34 2007 -0700
    65.2 +++ b/xen/include/asm-x86/hvm/domain.h	Thu Jan 18 18:25:04 2007 +0000
    65.3 @@ -27,6 +27,20 @@
    65.4  #include <asm/hvm/io.h>
    65.5  #include <public/hvm/params.h>
    65.6  
    65.7 +typedef void SaveStateHandler(hvm_domain_context_t *h, void *opaque);
    65.8 +typedef int LoadStateHandler(hvm_domain_context_t *h, void *opaque, int version_id);
    65.9 +
   65.10 +#define HVM_SE_IDSTR_LEN 32
   65.11 +typedef struct HVMStateEntry {
   65.12 +    char idstr[HVM_SE_IDSTR_LEN];
   65.13 +    int instance_id;
   65.14 +    int version_id;
   65.15 +    SaveStateHandler *save_state;
   65.16 +    LoadStateHandler *load_state;
   65.17 +    void *opaque;
   65.18 +    struct HVMStateEntry *next;
   65.19 +} HVMStateEntry;
   65.20 +
   65.21  struct hvm_domain {
   65.22      unsigned long          shared_page_va;
   65.23      unsigned long          buffered_io_va;
   65.24 @@ -44,6 +58,9 @@ struct hvm_domain {
   65.25      spinlock_t             pbuf_lock;
   65.26  
   65.27      uint64_t               params[HVM_NR_PARAMS];
   65.28 +
   65.29 +    struct hvm_domain_context *hvm_ctxt;
   65.30 +    HVMStateEntry *first_se;
   65.31  };
   65.32  
   65.33  #endif /* __ASM_X86_HVM_DOMAIN_H__ */
    66.1 --- a/xen/include/asm-x86/hvm/hvm.h	Wed Jan 17 21:45:34 2007 -0700
    66.2 +++ b/xen/include/asm-x86/hvm/hvm.h	Thu Jan 18 18:25:04 2007 +0000
    66.3 @@ -79,6 +79,13 @@ struct hvm_function_table {
    66.4          struct vcpu *v, struct cpu_user_regs *r, unsigned long *crs);
    66.5      void (*load_cpu_guest_regs)(
    66.6          struct vcpu *v, struct cpu_user_regs *r);
    66.7 +
    66.8 +    /* save and load hvm guest cpu context for save/restore */
    66.9 +    void (*save_cpu_ctxt)(
   66.10 +        struct vcpu *v, struct hvmcpu_context *ctxt);
   66.11 +    void (*load_cpu_ctxt)(
   66.12 +        struct vcpu *v, struct hvmcpu_context *ctxt);
   66.13 +
   66.14      /*
   66.15       * Examine specifics of the guest state:
   66.16       * 1) determine whether paging is enabled,
   66.17 @@ -157,6 +164,35 @@ hvm_load_cpu_guest_regs(struct vcpu *v, 
   66.18      hvm_funcs.load_cpu_guest_regs(v, r);
   66.19  }
   66.20  
   66.21 +void hvm_set_guest_time(struct vcpu *v, u64 gtime);
   66.22 +u64 hvm_get_guest_time(struct vcpu *v);
   66.23 +
   66.24 +static inline void
   66.25 +hvm_save_cpu_context(
   66.26 +        struct vcpu *v, struct hvmcpu_context *ctxt)
   66.27 +{
   66.28 +    hvm_funcs.save_cpu_ctxt(v, ctxt);
   66.29 +
   66.30 +    /* save guest time */
   66.31 +    ctxt->gtime = hvm_get_guest_time(v);
   66.32 +
   66.33 +    /* set valid flag to recover whole vmcs when restore */
   66.34 +    ctxt->valid = 0x55885588;
   66.35 +}
   66.36 +
   66.37 +static inline void
   66.38 +hvm_load_cpu_context(
   66.39 +        struct vcpu *v, struct hvmcpu_context *ctxt)
   66.40 +{
   66.41 +    if ( ctxt->valid != 0x55885588)
   66.42 +        return;
   66.43 +
   66.44 +    hvm_funcs.load_cpu_ctxt(v, ctxt);
   66.45 +
   66.46 +    /* restore guest time*/
   66.47 +    hvm_set_guest_time(v, ctxt->gtime);
   66.48 +}
   66.49 +
   66.50  static inline int
   66.51  hvm_paging_enabled(struct vcpu *v)
   66.52  {
   66.53 @@ -222,8 +258,6 @@ hvm_get_segment_register(struct vcpu *v,
   66.54  void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
   66.55                                     unsigned int *ecx, unsigned int *edx);
   66.56  void hvm_stts(struct vcpu *v);
   66.57 -void hvm_set_guest_time(struct vcpu *v, u64 gtime);
   66.58 -u64 hvm_get_guest_time(struct vcpu *v);
   66.59  void hvm_migrate_timers(struct vcpu *v);
   66.60  void hvm_do_resume(struct vcpu *v);
   66.61  
    67.1 --- a/xen/include/asm-x86/hvm/support.h	Wed Jan 17 21:45:34 2007 -0700
    67.2 +++ b/xen/include/asm-x86/hvm/support.h	Thu Jan 18 18:25:04 2007 +0000
    67.3 @@ -121,6 +121,133 @@ extern unsigned int opt_hvm_debug_level;
    67.4  #define TRACE_VMEXIT(index, value)                              \
    67.5      current->arch.hvm_vcpu.hvm_trace_values[index] = (value)
    67.6  
    67.7 +/* save/restore support */
    67.8 +
    67.9 +//#define HVM_DEBUG_SUSPEND
   67.10 +
   67.11 +extern int hvm_register_savevm(struct domain *d,
   67.12 +                    const char *idstr,
   67.13 +                    int instance_id,
   67.14 +                    int version_id,
   67.15 +                    SaveStateHandler *save_state,
   67.16 +                    LoadStateHandler *load_state,
   67.17 +                    void *opaque);
   67.18 +
   67.19 +static inline void hvm_ctxt_seek(hvm_domain_context_t *h, unsigned int pos)
   67.20 +{
   67.21 +    h->cur = pos;
   67.22 +}
   67.23 +
   67.24 +static inline uint32_t hvm_ctxt_tell(hvm_domain_context_t *h)
   67.25 +{
   67.26 +    return h->cur;
   67.27 +}
   67.28 +
   67.29 +static inline int hvm_ctxt_end(hvm_domain_context_t *h)
   67.30 +{
   67.31 +    return (h->cur >= h->size || h->cur >= HVM_CTXT_SIZE);
   67.32 +}
   67.33 +
   67.34 +static inline void hvm_put_byte(hvm_domain_context_t *h, unsigned int i)
   67.35 +{
   67.36 +    if (h->cur >= HVM_CTXT_SIZE) {
   67.37 +        h->cur++;
   67.38 +        return;
   67.39 +    }
   67.40 +    h->data[h->cur++] = (char)i;
   67.41 +}
   67.42 +
   67.43 +static inline void hvm_put_8u(hvm_domain_context_t *h, uint8_t b)
   67.44 +{
   67.45 +    hvm_put_byte(h, b);
   67.46 +}
   67.47 +
   67.48 +static inline void hvm_put_16u(hvm_domain_context_t *h, uint16_t b)
   67.49 +{
   67.50 +    hvm_put_8u(h, b >> 8);
   67.51 +    hvm_put_8u(h, b);
   67.52 +}
   67.53 +
   67.54 +static inline void hvm_put_32u(hvm_domain_context_t *h, uint32_t b)
   67.55 +{
   67.56 +    hvm_put_16u(h, b >> 16);
   67.57 +    hvm_put_16u(h, b);
   67.58 +}
   67.59 +
   67.60 +static inline void hvm_put_64u(hvm_domain_context_t *h, uint64_t b)
   67.61 +{
   67.62 +    hvm_put_32u(h, b >> 32);
   67.63 +    hvm_put_32u(h, b);
   67.64 +}
   67.65 +
   67.66 +static inline void hvm_put_buffer(hvm_domain_context_t *h, const char *buf, int len)
   67.67 +{
   67.68 +    memcpy(&h->data[h->cur], buf, len);
   67.69 +    h->cur += len;
   67.70 +}
   67.71 +
   67.72 +
   67.73 +static inline char hvm_get_byte(hvm_domain_context_t *h)
   67.74 +{
   67.75 +    if (h->cur >= HVM_CTXT_SIZE) {
   67.76 +        printk("hvm_get_byte overflow.\n");
   67.77 +        return -1;
   67.78 +    }
   67.79 +
   67.80 +    if (h->cur >= h->size) {
   67.81 +        printk("hvm_get_byte exceed data area.\n");
   67.82 +        return -1;
   67.83 +    }
   67.84 +
   67.85 +    return h->data[h->cur++];
   67.86 +}
   67.87 +
   67.88 +static inline uint8_t hvm_get_8u(hvm_domain_context_t *h)
   67.89 +{
   67.90 +    return hvm_get_byte(h);
   67.91 +}
   67.92 +
   67.93 +static inline uint16_t hvm_get_16u(hvm_domain_context_t *h)
   67.94 +{
   67.95 +    uint16_t v;
   67.96 +    v =  hvm_get_8u(h) << 8;
   67.97 +    v |= hvm_get_8u(h);
   67.98 +
   67.99 +    return v;
  67.100 +}
  67.101 +
  67.102 +static inline uint32_t hvm_get_32u(hvm_domain_context_t *h)
  67.103 +{
  67.104 +    uint32_t v;
  67.105 +    v =  hvm_get_16u(h) << 16;
  67.106 +    v |= hvm_get_16u(h);
  67.107 +
  67.108 +    return v;
  67.109 +}
  67.110 +
  67.111 +static inline uint64_t hvm_get_64u(hvm_domain_context_t *h)
  67.112 +{
  67.113 +    uint64_t v;
  67.114 +    v =  (uint64_t)hvm_get_32u(h) << 32;
  67.115 +    v |= hvm_get_32u(h);
  67.116 +
  67.117 +    return v;
  67.118 +}
  67.119 +
  67.120 +static inline void hvm_get_buffer(hvm_domain_context_t *h, char *buf, int len)
  67.121 +{
  67.122 +    memcpy(buf, &h->data[h->cur], len);
  67.123 +    h->cur += len;
  67.124 +}
  67.125 +
  67.126 +extern int hvm_save(struct vcpu*, hvm_domain_context_t *h);
  67.127 +extern int hvm_load(struct vcpu*, hvm_domain_context_t *h);
  67.128 +
  67.129 +extern int arch_sethvm_ctxt(struct vcpu *v, struct hvm_domain_context *c);
  67.130 +extern int arch_gethvm_ctxt(struct vcpu *v, struct hvm_domain_context *c);
  67.131 +
  67.132 +extern void shpage_init(struct domain *d, shared_iopage_t *sp);
  67.133 +
  67.134  extern int hvm_enabled;
  67.135  
  67.136  int hvm_copy_to_guest_phys(paddr_t paddr, void *buf, int size);
    68.1 --- a/xen/include/asm-x86/hvm/vpt.h	Wed Jan 17 21:45:34 2007 -0700
    68.2 +++ b/xen/include/asm-x86/hvm/vpt.h	Thu Jan 18 18:25:04 2007 +0000
    68.3 @@ -152,7 +152,7 @@ void pt_update_irq(struct vcpu *v);
    68.4  struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type);
    68.5  void pt_intr_post(struct vcpu *v, int vector, int type);
    68.6  void pt_reset(struct vcpu *v);
    68.7 -void create_periodic_time(struct periodic_time *pt, uint64_t period,
    68.8 +void create_periodic_time(struct vcpu *v, struct periodic_time *pt, uint64_t period,
    68.9                            uint8_t irq, char one_shot, time_cb *cb, void *data);
   68.10  void destroy_periodic_time(struct periodic_time *pt);
   68.11  
    69.1 --- a/xen/include/public/arch-x86/xen.h	Wed Jan 17 21:45:34 2007 -0700
    69.2 +++ b/xen/include/public/arch-x86/xen.h	Thu Jan 18 18:25:04 2007 +0000
    69.3 @@ -109,6 +109,70 @@ DEFINE_XEN_GUEST_HANDLE(trap_info_t);
    69.4  typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
    69.5  
    69.6  /*
    69.7 + * World vmcs state
    69.8 + */
    69.9 +struct vmcs_data {
   69.10 +    uint64_t  eip;        /* execution pointer */
   69.11 +    uint64_t  esp;        /* stack pointer */
   69.12 +    uint64_t  eflags;     /* flags register */
   69.13 +    uint64_t  cr0;
   69.14 +    uint64_t  cr3;        /* page table directory */
   69.15 +    uint64_t  cr4;
   69.16 +    uint32_t  idtr_limit; /* idt */
   69.17 +    uint64_t  idtr_base;
   69.18 +    uint32_t  gdtr_limit; /* gdt */
   69.19 +    uint64_t  gdtr_base;
   69.20 +    uint32_t  cs_sel;     /* cs selector */
   69.21 +    uint32_t  cs_limit;
   69.22 +    uint64_t  cs_base;
   69.23 +    uint32_t  cs_arbytes;
   69.24 +    uint32_t  ds_sel;     /* ds selector */
   69.25 +    uint32_t  ds_limit;
   69.26 +    uint64_t  ds_base;
   69.27 +    uint32_t  ds_arbytes;
   69.28 +    uint32_t  es_sel;     /* es selector */
   69.29 +    uint32_t  es_limit;
   69.30 +    uint64_t  es_base;
   69.31 +    uint32_t  es_arbytes;
   69.32 +    uint32_t  ss_sel;     /* ss selector */
   69.33 +    uint32_t  ss_limit;
   69.34 +    uint64_t  ss_base;
   69.35 +    uint32_t  ss_arbytes;
   69.36 +    uint32_t  fs_sel;     /* fs selector */
   69.37 +    uint32_t  fs_limit;
   69.38 +    uint64_t  fs_base;
   69.39 +    uint32_t  fs_arbytes;
   69.40 +    uint32_t  gs_sel;     /* gs selector */
   69.41 +    uint32_t  gs_limit;
   69.42 +    uint64_t  gs_base;
   69.43 +    uint32_t  gs_arbytes;
   69.44 +    uint32_t  tr_sel;     /* task selector */
   69.45 +    uint32_t  tr_limit;
   69.46 +    uint64_t  tr_base;
   69.47 +    uint32_t  tr_arbytes;
   69.48 +    uint32_t  ldtr_sel;   /* ldtr selector */
   69.49 +    uint32_t  ldtr_limit;
   69.50 +    uint64_t  ldtr_base;
   69.51 +    uint32_t  ldtr_arbytes;
   69.52 +    uint32_t  sysenter_cs;
   69.53 +    uint64_t  sysenter_esp;
   69.54 +    uint64_t  sysenter_eip;
   69.55 +    /* msr for em64t */
   69.56 +    uint64_t shadow_gs;
   69.57 +    uint64_t flags;
   69.58 +    /* same size as VMX_MSR_COUNT */
   69.59 +    uint64_t msr_items[6];
   69.60 +    uint64_t vmxassist_enabled;
   69.61 +};
   69.62 +typedef struct vmcs_data vmcs_data_t;
   69.63 +
   69.64 +struct hvmcpu_context {
   69.65 +    uint32_t valid;
   69.66 +    struct vmcs_data data;
   69.67 +    uint64_t gtime;
   69.68 +};
   69.69 +
   69.70 +/*
   69.71   * The following is all CPU context. Note that the fpu_ctxt block is filled 
   69.72   * in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
   69.73   */
   69.74 @@ -154,6 +218,7 @@ struct vcpu_guest_context {
   69.75  #endif
   69.76  #endif
   69.77      unsigned long vm_assist;                /* VMASST_TYPE_* bitmap */
   69.78 +    struct hvmcpu_context hvmcpu_ctxt;      /* whole vmcs region */
   69.79  #ifdef __x86_64__
   69.80      /* Segment base addresses. */
   69.81      uint64_t      fs_base;
    70.1 --- a/xen/include/public/domctl.h	Wed Jan 17 21:45:34 2007 -0700
    70.2 +++ b/xen/include/public/domctl.h	Thu Jan 18 18:25:04 2007 +0000
    70.3 @@ -386,6 +386,21 @@ struct xen_domctl_settimeoffset {
    70.4  };
    70.5  typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t;
    70.6  DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t);
    70.7 + 
    70.8 +#define HVM_CTXT_SIZE        6144
    70.9 +typedef struct hvm_domain_context {
   70.10 +    uint32_t cur;
   70.11 +    uint32_t size;
   70.12 +    uint8_t data[HVM_CTXT_SIZE];
   70.13 +} hvm_domain_context_t;
   70.14 +DEFINE_XEN_GUEST_HANDLE(hvm_domain_context_t);
   70.15 +
   70.16 +#define XEN_DOMCTL_gethvmcontext   33
   70.17 +#define XEN_DOMCTL_sethvmcontext   34
   70.18 +typedef struct xen_domctl_hvmcontext {
   70.19 +    XEN_GUEST_HANDLE(hvm_domain_context_t) ctxt;  /* IN/OUT */
   70.20 +} xen_domctl_hvmcontext_t;
   70.21 +DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t);
   70.22  
   70.23  #define XEN_DOMCTL_real_mode_area     26
   70.24  struct xen_domctl_real_mode_area {
   70.25 @@ -423,6 +438,7 @@ struct xen_domctl {
   70.26          struct xen_domctl_arch_setup        arch_setup;
   70.27          struct xen_domctl_settimeoffset     settimeoffset;
   70.28          struct xen_domctl_real_mode_area    real_mode_area;
   70.29 +        struct xen_domctl_hvmcontext        hvmcontext;
   70.30          uint8_t                             pad[128];
   70.31      } u;
   70.32  };
    71.1 --- a/xen/include/xlat.lst	Wed Jan 17 21:45:34 2007 -0700
    71.2 +++ b/xen/include/xlat.lst	Thu Jan 18 18:25:04 2007 +0000
    71.3 @@ -8,6 +8,8 @@
    71.4  ?	vcpu_time_info			xen.h
    71.5  !	cpu_user_regs			arch-x86/xen-@arch@.h
    71.6  !	trap_info			arch-x86/xen.h
    71.7 +!	hvmcpu_context			arch-x86/xen.h
    71.8 +!	vmcs_data			arch-x86/xen.h
    71.9  !	vcpu_guest_context		arch-x86/xen.h
   71.10  ?	acm_getdecision			acm_ops.h
   71.11  !	ctl_cpumap			domctl.h