[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] merge with xen-unstable.hg



# HG changeset patch
# User awilliam@xxxxxxxxxxxx
# Date 1170870378 25200
# Node ID fbc233a1dc53dd0928fb8c0062d6582ef210950d
# Parent  d3f08d39e69530f749fdc7061a4f552bf8049804
# Parent  584ab4fd1ad5de524ea3767e4a9bc1ea6bf6a30f
merge with xen-unstable.hg
---
 .hgignore                                          |    1 
 extras/mini-os/gnttab.c                            |    5 
 extras/mini-os/netfront.c                          |    4 
 linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S  |   22 --
 linux-2.6-xen-sparse/drivers/xen/core/evtchn.c     |    6 
 patches/linux-2.6.18/series                        |    1 
 patches/linux-2.6.18/softlockup-no-idle-hz.patch   |   32 ++
 tools/firmware/rombios/32bit/tcgbios/tcgbios.c     |   14 -
 tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c |   52 +++-
 tools/firmware/rombios/32bit/util.h                |   15 +
 tools/firmware/rombios/rombios.c                   |   13 -
 tools/ioemu/hw/cirrus_vga.c                        |   31 +-
 tools/ioemu/hw/tpm_tis.c                           |   13 -
 tools/libxc/xc_domain.c                            |    8 
 tools/libxc/xc_hvm_save.c                          |   21 +
 tools/python/xen/xend/XendLogging.py               |    4 
 tools/python/xen/xm/main.py                        |    6 
 tools/python/xen/xm/opts.py                        |    4 
 tools/xentrace/xentrace_format                     |    3 
 xen/arch/x86/domctl.c                              |   25 +-
 xen/arch/x86/hvm/Makefile                          |    1 
 xen/arch/x86/hvm/hpet.c                            |    5 
 xen/arch/x86/hvm/hvm.c                             |   36 ++-
 xen/arch/x86/hvm/i8254.c                           |   28 +-
 xen/arch/x86/hvm/intercept.c                       |  176 ----------------
 xen/arch/x86/hvm/irq.c                             |  181 +++++++++++++++-
 xen/arch/x86/hvm/rtc.c                             |    2 
 xen/arch/x86/hvm/save.c                            |  229 +++++++++++++++++++++
 xen/arch/x86/hvm/svm/svm.c                         |    1 
 xen/arch/x86/hvm/svm/vmcb.c                        |    3 
 xen/arch/x86/hvm/vioapic.c                         |   60 -----
 xen/arch/x86/hvm/vlapic.c                          |   23 --
 xen/arch/x86/hvm/vmx/vmcs.c                        |   16 +
 xen/arch/x86/hvm/vmx/vmx.c                         |    7 
 xen/arch/x86/hvm/vpic.c                            |    2 
 xen/arch/x86/mm/shadow/multi.c                     |    8 
 xen/include/asm-x86/hvm/domain.h                   |    2 
 xen/include/asm-x86/hvm/hvm.h                      |    1 
 xen/include/asm-x86/hvm/irq.h                      |   63 +++++
 xen/include/asm-x86/hvm/support.h                  |   34 ++-
 xen/include/asm-x86/hvm/vlapic.h                   |    2 
 xen/include/asm-x86/hvm/vpt.h                      |    4 
 xen/include/public/domctl.h                        |    3 
 xen/include/public/hvm/save.h                      |  185 +++++++---------
 44 files changed, 843 insertions(+), 509 deletions(-)

diff -r d3f08d39e695 -r fbc233a1dc53 .hgignore
--- a/.hgignore Wed Feb 07 10:14:41 2007 -0700
+++ b/.hgignore Wed Feb 07 10:46:18 2007 -0700
@@ -107,6 +107,7 @@
 ^tools/firmware/rombios/BIOS-bochs-[^/]*$
 ^tools/firmware/rombios/_rombios[^/]*_\.c$
 ^tools/firmware/rombios/rombios[^/]*\.s$
+^tools/firmware/rombios/32bit/32bitbios_flat\.h$
 ^tools/firmware/vmxassist/gen$
 ^tools/firmware/vmxassist/offsets\.h$
 ^tools/firmware/vmxassist/vmxassist$
diff -r d3f08d39e695 -r fbc233a1dc53 extras/mini-os/gnttab.c
--- a/extras/mini-os/gnttab.c   Wed Feb 07 10:14:41 2007 -0700
+++ b/extras/mini-os/gnttab.c   Wed Feb 07 10:46:18 2007 -0700
@@ -21,7 +21,12 @@
 
 #define NR_RESERVED_ENTRIES 8
 
+/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
+#ifdef __ia64__
+#define NR_GRANT_FRAMES 1
+#else
 #define NR_GRANT_FRAMES 4
+#endif
 #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
 
 static grant_entry_t *gnttab_table;
diff -r d3f08d39e695 -r fbc233a1dc53 extras/mini-os/netfront.c
--- a/extras/mini-os/netfront.c Wed Feb 07 10:14:41 2007 -0700
+++ b/extras/mini-os/netfront.c Wed Feb 07 10:46:18 2007 -0700
@@ -349,7 +349,9 @@ done:
     init_rx_buffers();
 
     unsigned char rawmac[6];
-    sscanf(mac,"%x:%x:%x:%x:%x:%x",
+        /* Special conversion specifier 'hh' needed for __ia64__. Without
+           this mini-os panics with 'Unaligned reference'. */
+    sscanf(mac,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
             &rawmac[0],
             &rawmac[1],
             &rawmac[2],
diff -r d3f08d39e695 -r fbc233a1dc53 
linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S
--- a/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S Wed Feb 07 10:14:41 
2007 -0700
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S Wed Feb 07 10:46:18 
2007 -0700
@@ -747,7 +747,7 @@ ENTRY(hypervisor_callback)
        jb   11f
        cmpl $sysexit_ecrit,%eax
        ja   11f
-       addl $0x34,%esp                 # Remove cs...ebx from stack frame.
+       addl $OLDESP,%esp               # Remove eflags...ebx from stack frame.
 11:    push %esp
        call evtchn_do_upcall
        add  $4,%esp
@@ -777,18 +777,13 @@ ecrit:  /**** END OF CRITICAL REGION ***
 # provides the number of bytes which have already been popped from the
 # interrupted stack frame.
 critical_region_fixup:
-       addl $critical_fixup_table-scrit,%eax
-       movzbl (%eax),%eax              # %eax contains num bytes popped
-       cmpb $0xff,%al                  # 0xff => vcpu_info critical region
+       movzbl critical_fixup_table-scrit(%eax),%ecx # %eax contains num bytes 
popped
+       cmpb $0xff,%cl                  # 0xff => vcpu_info critical region
        jne  15f
-       GET_THREAD_INFO(%ebp)
-        xorl %eax,%eax
-15:    mov  %esp,%esi
-       add  %eax,%esi                  # %esi points at end of src region
-       mov  %esp,%edi
-       add  $0x34,%edi                 # %edi points at end of dst region
-       mov  %eax,%ecx
-       shr  $2,%ecx                    # convert words to bytes
+       xorl %ecx,%ecx
+15:    leal (%esp,%ecx),%esi           # %esi points at end of src region
+       leal OLDESP(%esp),%edi          # %edi points at end of dst region
+       shrl $2,%ecx                    # convert words to bytes
        je   17f                        # skip loop if nothing to copy
 16:    subl $4,%esi                    # pre-decrementing copy loop
        subl $4,%edi
@@ -798,6 +793,7 @@ 17: movl %edi,%esp                  # final %edi is top
 17:    movl %edi,%esp                  # final %edi is top of merged stack
        jmp  11b
 
+.section .rodata,"a"
 critical_fixup_table:
        .byte 0xff,0xff,0xff            # testb $0xff,(%esi) = __TEST_PENDING
        .byte 0xff,0xff                 # jnz  14f
@@ -814,6 +810,7 @@ critical_fixup_table:
        .byte 0x28                      # iret
        .byte 0xff,0xff,0xff,0xff       # movb $1,1(%esi)
        .byte 0x00,0x00                 # jmp  11b
+.previous
 
 # Hypervisor uses this for application faults while it executes.
 # We get here for two reasons:
@@ -1194,6 +1191,7 @@ ENTRY(fixup_4gb_segment)
        jmp error_code
 
 .section .rodata,"a"
+.align 4
 #include "syscall_table.S"
 
 syscall_table_size=(.-sys_call_table)
diff -r d3f08d39e695 -r fbc233a1dc53 
linux-2.6-xen-sparse/drivers/xen/core/evtchn.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c    Wed Feb 07 10:14:41 
2007 -0700
+++ b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c    Wed Feb 07 10:46:18 
2007 -0700
@@ -424,7 +424,7 @@ static void unbind_from_irq(unsigned int
 static void unbind_from_irq(unsigned int irq)
 {
        struct evtchn_close close;
-       int evtchn = evtchn_from_irq(irq);
+       int cpu, evtchn = evtchn_from_irq(irq);
 
        spin_lock(&irq_mapping_update_lock);
 
@@ -452,6 +452,10 @@ static void unbind_from_irq(unsigned int
 
                evtchn_to_irq[evtchn] = -1;
                irq_info[irq] = IRQ_UNBOUND;
+
+               /* Zap stats across IRQ changes of use. */
+               for_each_possible_cpu(cpu)
+                       kstat_cpu(cpu).irqs[irq] = 0;
        }
 
        spin_unlock(&irq_mapping_update_lock);
diff -r d3f08d39e695 -r fbc233a1dc53 patches/linux-2.6.18/series
--- a/patches/linux-2.6.18/series       Wed Feb 07 10:14:41 2007 -0700
+++ b/patches/linux-2.6.18/series       Wed Feb 07 10:46:18 2007 -0700
@@ -18,3 +18,4 @@ x86-elfnote-as-preprocessor-macro.patch
 x86-elfnote-as-preprocessor-macro.patch
 fixaddr-top.patch
 git-c06cb8b1c4d25e5b4d7a2d7c2462619de1e0dbc4.patch
+softlockup-no-idle-hz.patch
diff -r d3f08d39e695 -r fbc233a1dc53 
patches/linux-2.6.18/softlockup-no-idle-hz.patch
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.18/softlockup-no-idle-hz.patch  Wed Feb 07 10:46:18 
2007 -0700
@@ -0,0 +1,56 @@
+diff -pruN ../orig-linux-2.6.18/include/linux/sched.h ./include/linux/sched.h
+--- ../orig-linux-2.6.18/include/linux/sched.h 2006-09-20 04:42:06.000000000 
+0100
++++ ./include/linux/sched.h    2007-02-07 01:10:24.000000000 +0000
+@@ -211,10 +211,15 @@ extern void update_process_times(int use
+ extern void scheduler_tick(void);
+ 
+ #ifdef CONFIG_DETECT_SOFTLOCKUP
++extern unsigned long softlockup_get_next_event(void);
+ extern void softlockup_tick(void);
+ extern void spawn_softlockup_task(void);
+ extern void touch_softlockup_watchdog(void);
+ #else
++static inline unsigned long softlockup_get_next_event(void)
++{
++      return MAX_JIFFY_OFFSET;
++}
+ static inline void softlockup_tick(void)
+ {
+ }
+diff -pruN ../orig-linux-2.6.18/kernel/softlockup.c ./kernel/softlockup.c
+--- ../orig-linux-2.6.18/kernel/softlockup.c   2006-09-20 04:42:06.000000000 
+0100
++++ ./kernel/softlockup.c      2007-02-07 01:53:22.000000000 +0000
+@@ -40,6 +40,19 @@ void touch_softlockup_watchdog(void)
+ }
+ EXPORT_SYMBOL(touch_softlockup_watchdog);
+ 
++unsigned long softlockup_get_next_event(void)
++{
++      int this_cpu = smp_processor_id();
++      unsigned long touch_timestamp = per_cpu(touch_timestamp, this_cpu);
++
++      if (per_cpu(print_timestamp, this_cpu) == touch_timestamp ||
++              did_panic ||
++                      !per_cpu(watchdog_task, this_cpu))
++              return MAX_JIFFY_OFFSET;
++
++      return min_t(long, 0, touch_timestamp + HZ - jiffies);
++}
++
+ /*
+  * This callback runs from the timer interrupt, and checks
+  * whether the watchdog thread has hung or not:
+diff -pruN ../orig-linux-2.6.18/kernel/timer.c ./kernel/timer.c
+--- ../orig-linux-2.6.18/kernel/timer.c        2006-09-20 04:42:06.000000000 
+0100
++++ ./kernel/timer.c   2007-02-07 01:29:34.000000000 +0000
+@@ -485,7 +485,9 @@ unsigned long next_timer_interrupt(void)
+               if (hr_expires < 3)
+                       return hr_expires + jiffies;
+       }
+-      hr_expires += jiffies;
++      hr_expires = min_t(unsigned long,
++                         softlockup_get_next_event(),
++                         hr_expires) + jiffies;
+ 
+       base = __get_cpu_var(tvec_bases);
+       spin_lock(&base->lock);
diff -r d3f08d39e695 -r fbc233a1dc53 
tools/firmware/rombios/32bit/tcgbios/tcgbios.c
--- a/tools/firmware/rombios/32bit/tcgbios/tcgbios.c    Wed Feb 07 10:14:41 
2007 -0700
+++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c    Wed Feb 07 10:46:18 
2007 -0700
@@ -146,7 +146,7 @@ static int tpm_driver_to_use = TPM_INVAL
 static int tpm_driver_to_use = TPM_INVALID_DRIVER;
 
 static
-uint32_t MA_IsTPMPresent()
+uint32_t MA_IsTPMPresent(void)
 {
        uint32_t rc = 0;
        unsigned int i;
@@ -263,11 +263,11 @@ void tcpa_acpi_init(void)
 {
        struct acpi_20_rsdt *rsdt;
        uint32_t length;
-       struct acpi_20_tcpa *tcpa;
+       struct acpi_20_tcpa *tcpa = (void *)0;
        uint16_t found = 0;
        uint16_t rsdp_off;
        uint16_t off;
-       struct acpi_20_rsdp *rsdp;
+       struct acpi_20_rsdp *rsdp = (void *)0;
 
        if (MA_IsTPMPresent() == 0) {
                return;
@@ -732,8 +732,8 @@ void tcpa_measure_post(Bit32u from, Bit3
 void tcpa_measure_post(Bit32u from, Bit32u to)
 {
        struct pcpes pcpes; /* PCClientPCREventStruc */
+       int len = to - from;
        memset(&pcpes, 0x0, sizeof(pcpes));
-       int len = to - from;
 
        if (len > 0) {
                sha1((unsigned char *)from,
@@ -986,7 +986,7 @@ uint32_t PassThroughToTPM32(struct pttti
 {
        uint32_t rc = 0;
        uint8_t *cmd32;
-       uint32_t resbuflen;
+       uint32_t resbuflen = 0;
 
        if (TCG_IsShutdownPreBootInterface() != 0) {
                rc = (TCG_PC_TPMERROR |
@@ -1277,9 +1277,7 @@ typedef struct _sha1_ctx {
 } sha1_ctx;
 
 
-static inline uint32_t rol(val, rol)
-  uint32_t val;
-  uint16_t rol;
+static inline uint32_t rol(uint32_t val, uint16_t rol)
 {
        return (val << rol) | (val >> (32 - rol));
 }
diff -r d3f08d39e695 -r fbc233a1dc53 
tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c
--- a/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c        Wed Feb 07 
10:14:41 2007 -0700
+++ b/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c        Wed Feb 07 
10:46:18 2007 -0700
@@ -27,12 +27,27 @@
 #include "tpm_drivers.h"
 #include "tcgbios.h"
 
+#define STS_VALID                    (1 << 7) /* 0x80 */
+#define STS_COMMAND_READY            (1 << 6) /* 0x40 */
+#define STS_TPM_GO                   (1 << 5) /* 0x20 */
+#define STS_DATA_AVAILABLE           (1 << 4) /* 0x10 */
+#define STS_EXPECT                   (1 << 3) /* 0x08 */
+#define STS_RESPONSE_RETRY           (1 << 1) /* 0x02 */
+
+#define ACCESS_TPM_REG_VALID_STS     (1 << 7) /* 0x80 */
+#define ACCESS_ACTIVE_LOCALITY       (1 << 5) /* 0x20 */
+#define ACCESS_BEEN_SEIZED           (1 << 4) /* 0x10 */
+#define ACCESS_SEIZE                 (1 << 3) /* 0x08 */
+#define ACCESS_PENDING_REQUEST       (1 << 2) /* 0x04 */
+#define ACCESS_REQUEST_USE           (1 << 1) /* 0x02 */
+#define ACCESS_TPM_ESTABLISHMENT     (1 << 0) /* 0x01 */
+
 static uint32_t tis_wait_sts(uint8_t *addr, uint32_t time,
                              uint8_t mask, uint8_t expect)
 {
        uint32_t rc = 0;
        while (time > 0) {
-               uint8_t sts = addr[TPM_STS];
+               uint8_t sts = mmio_readb(&addr[TPM_STS]);
                if ((sts & mask) == expect) {
                        rc = 1;
                        break;
@@ -45,16 +60,17 @@ static uint32_t tis_wait_sts(uint8_t *ad
 
 static uint32_t tis_activate(uint32_t baseaddr)
 {
-       uint32_t rc = 0;
+       uint32_t rc = 1;
        uint8_t *tis_addr = (uint8_t*)baseaddr;
        uint8_t acc;
        /* request access to locality */
-       tis_addr[TPM_ACCESS] = 0x2;
+       tis_addr[TPM_ACCESS] = ACCESS_REQUEST_USE;
 
-       acc = tis_addr[TPM_ACCESS];
-       if ((acc & 0x20) != 0) {
-               tis_addr[TPM_STS] = 0x40;
-               rc = tis_wait_sts(tis_addr, 100, 0x40, 0x40);
+       acc = mmio_readb(&tis_addr[TPM_ACCESS]);
+       if ((acc & ACCESS_ACTIVE_LOCALITY) != 0) {
+               tis_addr[TPM_STS] = STS_COMMAND_READY;
+               rc = tis_wait_sts(tis_addr, 100,
+                                 STS_COMMAND_READY, STS_COMMAND_READY);
        }
        return rc;
 }
@@ -64,8 +80,8 @@ uint32_t tis_ready(uint32_t baseaddr)
        uint32_t rc = 0;
        uint8_t *tis_addr = (uint8_t*)baseaddr;
 
-       tis_addr[TPM_STS] = 0x40;
-       rc = tis_wait_sts(tis_addr, 100, 0x40, 0x40);
+       tis_addr[TPM_STS] = STS_COMMAND_READY;
+       rc = tis_wait_sts(tis_addr, 100, STS_COMMAND_READY, STS_COMMAND_READY);
 
        return rc;
 }
@@ -81,8 +97,7 @@ uint32_t tis_senddata(uint32_t baseaddr,
                uint16_t burst = 0;
                uint32_t ctr = 0;
                while (burst == 0 && ctr < 2000) {
-                       burst = (((uint16_t)tis_addr[TPM_STS+1])     ) +
-                               (((uint16_t)tis_addr[TPM_STS+2]) << 8);
+                       burst = mmio_readw((uint16_t *)&tis_addr[TPM_STS+1]);
                        if (burst == 0) {
                                mssleep(1);
                                ctr++;
@@ -120,11 +135,11 @@ uint32_t tis_readresp(uint32_t baseaddr,
        uint32_t sts;
 
        while (offset < len) {
-               buffer[offset] = tis_addr[TPM_DATA_FIFO];
+               buffer[offset] = mmio_readb(&tis_addr[TPM_DATA_FIFO]);
                offset++;
-               sts = tis_addr[TPM_STS];
+               sts = mmio_readb(&tis_addr[TPM_STS]);
                /* data left ? */
-               if ((sts & 0x10) == 0) {
+               if ((sts & STS_DATA_AVAILABLE) == 0) {
                        break;
                }
        }
@@ -136,7 +151,7 @@ uint32_t tis_waitdatavalid(uint32_t base
 {
        uint8_t *tis_addr = (uint8_t*)baseaddr;
        uint32_t rc = 0;
-       if (tis_wait_sts(tis_addr, 1000, 0x80, 0x80) == 0) {
+       if (tis_wait_sts(tis_addr, 1000, STS_VALID, STS_VALID) == 0) {
                rc = TCG_NO_RESPONSE;
        }
        return rc;
@@ -146,8 +161,9 @@ uint32_t tis_waitrespready(uint32_t base
 {
        uint32_t rc = 0;
        uint8_t *tis_addr = (uint8_t*)baseaddr;
-       tis_addr[TPM_STS] = 0x20;
-       if (tis_wait_sts(tis_addr, timeout, 0x10, 0x10) == 0) {
+       tis_addr[TPM_STS] = STS_TPM_GO;
+       if (tis_wait_sts(tis_addr, timeout,
+                        STS_DATA_AVAILABLE, STS_DATA_AVAILABLE) == 0) {
                rc = TCG_NO_RESPONSE;
        }
        return rc;
@@ -158,7 +174,7 @@ uint32_t tis_probe(uint32_t baseaddr)
 {
        uint32_t rc = 0;
        uint8_t *tis_addr = (uint8_t*)baseaddr;
-       uint32_t didvid = *(uint32_t*)&tis_addr[TPM_DID_VID];
+       uint32_t didvid = mmio_readl((uint32_t *)&tis_addr[TPM_DID_VID]);
        if ((didvid != 0) && (didvid != 0xffffffff)) {
                rc = 1;
        }
diff -r d3f08d39e695 -r fbc233a1dc53 tools/firmware/rombios/32bit/util.h
--- a/tools/firmware/rombios/32bit/util.h       Wed Feb 07 10:14:41 2007 -0700
+++ b/tools/firmware/rombios/32bit/util.h       Wed Feb 07 10:46:18 2007 -0700
@@ -24,5 +24,20 @@ void uuid_to_string(char *dest, uint8_t 
 void uuid_to_string(char *dest, uint8_t *uuid);
 int printf(const char *fmt, ...);
 
+static inline uint8_t mmio_readb(uint8_t *addr)
+{
+       return *(volatile uint8_t *)addr;
+}
+
+static inline uint16_t mmio_readw(uint16_t *addr)
+{
+       return *(volatile uint16_t *)addr;
+}
+
+static inline uint32_t mmio_readl(uint32_t *addr)
+{
+       return *(volatile uint32_t *)addr;
+}
+
 
 #endif
diff -r d3f08d39e695 -r fbc233a1dc53 tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c  Wed Feb 07 10:14:41 2007 -0700
+++ b/tools/firmware/rombios/rombios.c  Wed Feb 07 10:46:18 2007 -0700
@@ -5722,9 +5722,6 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, 
     goto int13_fail;
     }
 
-#if BX_TCGBIOS
-  tcpa_ipl((Bit32u)bootseg);               /* specs: 8.2.3 steps 4 and 5 */
-#endif
   
   switch (GET_AH()) {
 
@@ -7741,6 +7738,10 @@ ASM_END
       }
     }
 
+#if BX_TCGBIOS
+    tcpa_add_bootdevice((Bit32u)0L, (Bit32u)bootdrv);
+#endif
+
     /* Canonicalize bootseg:bootip */
     bootip = (bootseg & 0x0fff) << 4;
     bootseg &= 0xf000;
@@ -7760,6 +7761,9 @@ ASM_END
     bootdrv = (Bit8u)(status>>8);
     bootseg = read_word(ebda_seg,&EbdaData->cdemu.load_segment);
     /* Canonicalize bootseg:bootip */
+#if BX_TCGBIOS
+    tcpa_add_bootdevice((Bit32u)1L, (Bit32u)0L);
+#endif
     bootip = (bootseg & 0x0fff) << 4;
     bootseg &= 0xf000;
     break;
@@ -7773,6 +7777,9 @@ ASM_END
   default: return;
   }
 
+#if BX_TCGBIOS
+  tcpa_ipl((Bit32u)bootseg);               /* specs: 8.2.3 steps 4 and 5 */
+#endif
   /* Debugging info */
   printf("Booting from %x:%x\n", bootseg, bootip);
   
diff -r d3f08d39e695 -r fbc233a1dc53 tools/ioemu/hw/cirrus_vga.c
--- a/tools/ioemu/hw/cirrus_vga.c       Wed Feb 07 10:14:41 2007 -0700
+++ b/tools/ioemu/hw/cirrus_vga.c       Wed Feb 07 10:46:18 2007 -0700
@@ -2571,7 +2571,8 @@ static void *set_vram_mapping(unsigned l
     return vram_pointer;
 }
 
-static int unset_vram_mapping(unsigned long begin, unsigned long end)
+static int unset_vram_mapping(unsigned long begin, unsigned long end, 
+                              void *mapping)
 {
     xen_pfn_t *extent_start = NULL;
     unsigned long nr_extents;
@@ -2591,11 +2592,13 @@ static int unset_vram_mapping(unsigned l
         return -1;
     }
 
+    /* Drop our own references to the vram pages */
+    munmap(mapping, nr_extents * TARGET_PAGE_SIZE);
+
+    /* Now drop the guest's mappings */
     memset(extent_start, 0, sizeof(xen_pfn_t) * nr_extents);
-
     for (i = 0; i < nr_extents; i++)
         extent_start[i] = (begin + (i * TARGET_PAGE_SIZE)) >> TARGET_PAGE_BITS;
-
     unset_mm_mapping(xc_handle, domid, nr_extents, 0, extent_start);
 
     free(extent_start);
@@ -2642,16 +2645,14 @@ static void cirrus_update_memory_access(
         } else {
         generic_io:
             if (s->cirrus_lfb_addr && s->cirrus_lfb_end && s->map_addr) {
-               int error;
-                void *old_vram = NULL;
-
-               error = unset_vram_mapping(s->cirrus_lfb_addr,
-                                          s->cirrus_lfb_end);
-               if (!error)
-                   old_vram = vga_update_vram((VGAState *)s, NULL,
-                                               VGA_RAM_SIZE);
-                if (old_vram)
-                    munmap(old_vram, s->map_addr - s->map_end);
+                void *old_vram;
+
+                old_vram = vga_update_vram((VGAState *)s, NULL, VGA_RAM_SIZE);
+
+                unset_vram_mapping(s->cirrus_lfb_addr,
+                                   s->cirrus_lfb_end, 
+                                   old_vram);
+
                 s->map_addr = s->map_end = 0;
             }
             s->cirrus_linear_write[0] = cirrus_linear_writeb;
@@ -3016,10 +3017,8 @@ void cirrus_stop_acc(CirrusVGAState *s)
         int error;
         s->map_addr = 0;
         error = unset_vram_mapping(s->cirrus_lfb_addr,
-                s->cirrus_lfb_end);
+                s->cirrus_lfb_end, s->vram_ptr);
         fprintf(stderr, "cirrus_stop_acc:unset_vram_mapping.\n");
-
-        munmap(s->vram_ptr, VGA_RAM_SIZE);
     }
 }
 
diff -r d3f08d39e695 -r fbc233a1dc53 tools/ioemu/hw/tpm_tis.c
--- a/tools/ioemu/hw/tpm_tis.c  Wed Feb 07 10:14:41 2007 -0700
+++ b/tools/ioemu/hw/tpm_tis.c  Wed Feb 07 10:46:18 2007 -0700
@@ -517,7 +517,7 @@ static uint32_t tis_mem_readl(void *opaq
 
 #ifdef DEBUG_TPM
     fprintf(logfile," read(%08x) = %08x\n",
-            addr,
+            (int)addr,
             val);
 #endif
 
@@ -538,7 +538,7 @@ static void tis_mem_writel(void *opaque,
 
 #ifdef DEBUG_TPM
     fprintf(logfile,"write(%08x) = %08x\n",
-            addr,
+            (int)addr,
             val);
 #endif
 
@@ -757,10 +757,11 @@ static void tpm_save(QEMUFile* f,void* o
 static void tpm_save(QEMUFile* f,void* opaque)
 {
     tpmState* s=(tpmState*)opaque;
+    uint8_t locty = s->active_loc;
     int c;
 
     /* need to wait for outstanding requests to complete */
-    if (IS_COMM_WITH_VTPM(s)) {
+    if (s->loc[locty].state == STATE_EXECUTION) {
         int repeats = 30; /* 30 seconds; really should be infty */
         while (repeats > 0 &&
                !(s->loc[s->active_loc].sts & STS_DATA_AVAILABLE)) {
@@ -777,6 +778,10 @@ static void tpm_save(QEMUFile* f,void* o
         }
     }
 
+    if (IS_COMM_WITH_VTPM(s)) {
+        close_vtpm_channel(s, 1);
+    }
+
     qemu_put_be32s(f,&s->offset);
     qemu_put_buffer(f, s->buffer.buf, TPM_MAX_PKT);
     qemu_put_8s(f, &s->active_loc);
@@ -993,7 +998,7 @@ static int TPM_Receive(tpmState *s, tpmB
         uint32_t size = tpm_get_size_from_buffer(buffer->buf);
         if (size + sizeof(buffer->instance) != off) {
             fprintf(logfile,"TPM: Packet size is bad! %d != %d\n",
-                    size + sizeof(buffer->instance),
+                    (int)(size + sizeof(buffer->instance)),
                     off);
         } else {
             uint32_t ret;
diff -r d3f08d39e695 -r fbc233a1dc53 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c   Wed Feb 07 10:14:41 2007 -0700
+++ b/tools/libxc/xc_domain.c   Wed Feb 07 10:46:18 2007 -0700
@@ -252,12 +252,14 @@ int xc_domain_hvm_getcontext(int xc_hand
     domctl.u.hvmcontext.size = size;
     set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
 
-    if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
-        return ret;
+    if ( ctxt_buf ) 
+        if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
+            return ret;
 
     ret = do_domctl(xc_handle, &domctl);
 
-    unlock_pages(ctxt_buf, size);
+    if ( ctxt_buf ) 
+        unlock_pages(ctxt_buf, size);
 
     return (ret < 0 ? -1 : domctl.u.hvmcontext.size);
 }
diff -r d3f08d39e695 -r fbc233a1dc53 tools/libxc/xc_hvm_save.c
--- a/tools/libxc/xc_hvm_save.c Wed Feb 07 10:14:41 2007 -0700
+++ b/tools/libxc/xc_hvm_save.c Wed Feb 07 10:46:18 2007 -0700
@@ -33,12 +33,6 @@
 #include "xg_save_restore.h"
 
 /*
- * Size of a buffer big enough to take the HVM state of a domain.
- * Ought to calculate this a bit more carefully, or maybe ask Xen.
- */
-#define HVM_CTXT_SIZE 8192
-
-/*
 ** Default values for important tuning parameters. Can override by passing
 ** non-zero replacement values to xc_hvm_save().
 **
@@ -286,6 +280,7 @@ int xc_hvm_save(int xc_handle, int io_fd
     unsigned long *pfn_batch = NULL;
 
     /* A copy of hvm domain context buffer*/
+    uint32_t hvm_buf_size;
     uint8_t *hvm_buf = NULL;
 
     /* Live mapping of shared info structure */
@@ -431,9 +426,15 @@ int xc_hvm_save(int xc_handle, int io_fd
 
     page_array = (unsigned long *) malloc( sizeof(unsigned long) * max_pfn);
 
-    hvm_buf = malloc(HVM_CTXT_SIZE);
-
-    if (!to_send ||!to_skip ||!page_array ||!hvm_buf ) {
+    hvm_buf_size = xc_domain_hvm_getcontext(xc_handle, dom, 0, 0);
+    if ( hvm_buf_size == -1 )
+    {
+        ERROR("Couldn't get HVM context size from Xen");
+        goto out;
+    }
+    hvm_buf = malloc(hvm_buf_size);
+
+    if (!to_send ||!to_skip ||!page_array ||!hvm_buf) {
         ERROR("Couldn't allocate memory");
         goto out;
     }
@@ -661,7 +662,7 @@ int xc_hvm_save(int xc_handle, int io_fd
     }
 
     if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, 
-                                              HVM_CTXT_SIZE)) == -1) {
+                                              hvm_buf_size)) == -1) {
         ERROR("HVM:Could not get hvm buffer");
         goto out;
     }
diff -r d3f08d39e695 -r fbc233a1dc53 tools/python/xen/xend/XendLogging.py
--- a/tools/python/xen/xend/XendLogging.py      Wed Feb 07 10:14:41 2007 -0700
+++ b/tools/python/xen/xend/XendLogging.py      Wed Feb 07 10:46:18 2007 -0700
@@ -52,8 +52,8 @@ if 'TRACE' not in logging.__dict__:
         for frame in frames:
             filename = os.path.normcase(frame[1])
             if filename != thisfile and filename != logging._srcfile:
-                major, minor, _, _, _ = sys.version_info
-                if major == 2 and minor >= 4:
+                major, minor, micro, _, _ = sys.version_info
+                if (major, minor, micro) >= (2, 4, 2):
                     return filename, frame[2], frame[3]
                 else:
                     return filename, frame[2]
diff -r d3f08d39e695 -r fbc233a1dc53 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Wed Feb 07 10:14:41 2007 -0700
+++ b/tools/python/xen/xm/main.py       Wed Feb 07 10:46:18 2007 -0700
@@ -1144,6 +1144,9 @@ def xm_sched_sedf(args):
     doms = filter(lambda x : domid_match(domid, x),
                         [parse_doms_info(dom)
                          for dom in getDomains(None, 'running')])
+    if domid is not None and doms == []: 
+        err("Domain '%s' does not exist." % domid)
+        usage('sched-sedf')
 
     # print header if we aren't setting any parameters
     if len(opts.keys()) == 0:
@@ -1207,6 +1210,9 @@ def xm_sched_credit(args):
                   for dom in getDomains(None, 'running')])
 
     if weight is None and cap is None:
+        if domid is not None and doms == []: 
+            err("Domain '%s' does not exist." % domid)
+            usage('sched-credit')
         # print header if we aren't setting any parameters
         print '%-33s %-2s %-6s %-4s' % ('Name','ID','Weight','Cap')
         
diff -r d3f08d39e695 -r fbc233a1dc53 tools/python/xen/xm/opts.py
--- a/tools/python/xen/xm/opts.py       Wed Feb 07 10:14:41 2007 -0700
+++ b/tools/python/xen/xm/opts.py       Wed Feb 07 10:46:18 2007 -0700
@@ -250,7 +250,8 @@ class OptVals:
 class OptVals:
     """Class to hold option values.
     """
-    pass
+    def __init__(self):
+        self.quiet = False
 
 class Opts:
     """Container for options.
@@ -276,7 +277,6 @@ class Opts:
         self.argv = []
         # Option values.
         self.vals = OptVals()
-        self.vals.quiet = 0
         # Variables for default scripts.
         self.vars = {}
         # Option to use for bare words.
diff -r d3f08d39e695 -r fbc233a1dc53 tools/xentrace/xentrace_format
--- a/tools/xentrace/xentrace_format    Wed Feb 07 10:14:41 2007 -0700
+++ b/tools/xentrace/xentrace_format    Wed Feb 07 10:46:18 2007 -0700
@@ -107,6 +107,9 @@ while not interrupted:
 
         (tsc, event, d1, d2, d3, d4, d5) = struct.unpack(TRCREC, line)
 
+        # Event field is 'uint32_t', not 'long'.
+        event &= 0xffffffff
+
        #tsc = (tscH<<32) | tscL
 
        #print i, tsc
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c     Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/domctl.c     Wed Feb 07 10:46:18 2007 -0700
@@ -326,10 +326,6 @@ long arch_do_domctl(
         struct hvm_domain_context c;
         struct domain             *d;
 
-        c.cur = 0;
-        c.size = domctl->u.hvmcontext.size;
-        c.data = NULL;
-
         ret = -ESRCH;
         if ( (d = get_domain_by_id(domctl->domain)) == NULL )
             break;
@@ -338,19 +334,38 @@ long arch_do_domctl(
         if ( !is_hvm_domain(d) ) 
             goto gethvmcontext_out;
 
+        c.cur = 0;
+        c.size = hvm_save_size(d);
+        c.data = NULL;
+
+        if ( guest_handle_is_null(domctl->u.hvmcontext.buffer) )
+        {
+            /* Client is querying for the correct buffer size */
+            domctl->u.hvmcontext.size = c.size;
+            ret = 0;
+            goto gethvmcontext_out;            
+        }
+
+        /* Check that the client has a big enough buffer */
+        ret = -ENOSPC;
+        if ( domctl->u.hvmcontext.size < c.size ) 
+            goto gethvmcontext_out;
+
+        /* Allocate our own marshalling buffer */
         ret = -ENOMEM;
         if ( (c.data = xmalloc_bytes(c.size)) == NULL )
             goto gethvmcontext_out;
 
         ret = hvm_save(d, &c);
 
+        domctl->u.hvmcontext.size = c.cur;
         if ( copy_to_guest(domctl->u.hvmcontext.buffer, c.data, c.size) != 0 )
             ret = -EFAULT;
 
+    gethvmcontext_out:
         if ( copy_to_guest(u_domctl, domctl, 1) )
             ret = -EFAULT;
 
-    gethvmcontext_out:
         if ( c.data != NULL )
             xfree(c.data);
 
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/Makefile
--- a/xen/arch/x86/hvm/Makefile Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/hvm/Makefile Wed Feb 07 10:46:18 2007 -0700
@@ -15,3 +15,4 @@ obj-y += vioapic.o
 obj-y += vioapic.o
 obj-y += vlapic.o
 obj-y += vpic.o
+obj-y += save.o
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/hpet.c
--- a/xen/arch/x86/hvm/hpet.c   Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/hvm/hpet.c   Wed Feb 07 10:46:18 2007 -0700
@@ -383,6 +383,9 @@ static int hpet_save(struct domain *d, h
 {
     HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet;
 
+    /* Write the proper value into the main counter */
+    hp->hpet.mc64 = hp->mc_offset + hvm_get_guest_time(hp->vcpu);
+
     /* Save the HPET registers */
     return hvm_save_entry(HPET, 0, h, &hp->hpet);
 }
@@ -406,7 +409,7 @@ static int hpet_load(struct domain *d, h
     return 0;
 }
 
-HVM_REGISTER_SAVE_RESTORE(HPET, hpet_save, hpet_load);
+HVM_REGISTER_SAVE_RESTORE(HPET, hpet_save, hpet_load, 1, HVMSR_PER_DOM);
 
 void hpet_init(struct vcpu *v)
 {
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/hvm/hvm.c    Wed Feb 07 10:46:18 2007 -0700
@@ -227,7 +227,8 @@ static int hvm_load_cpu_ctxt(struct doma
     return 0;
 }
 
-HVM_REGISTER_SAVE_RESTORE(CPU, hvm_save_cpu_ctxt, hvm_load_cpu_ctxt);
+HVM_REGISTER_SAVE_RESTORE(CPU, hvm_save_cpu_ctxt, hvm_load_cpu_ctxt,
+                          1, HVMSR_PER_VCPU);
 
 int hvm_vcpu_initialise(struct vcpu *v)
 {
@@ -271,6 +272,24 @@ void hvm_vcpu_destroy(struct vcpu *v)
 
     /* Event channel is already freed by evtchn_destroy(). */
     /*free_xen_event_channel(v, v->arch.hvm_vcpu.xen_port);*/
+}
+
+
+void hvm_vcpu_reset(struct vcpu *v)
+{
+    vcpu_pause(v);
+
+    vlapic_reset(vcpu_vlapic(v));
+
+    hvm_funcs.vcpu_initialise(v);
+
+    set_bit(_VCPUF_down, &v->vcpu_flags);
+    clear_bit(_VCPUF_initialised, &v->vcpu_flags);
+    clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags);
+    clear_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags);
+    clear_bit(_VCPUF_blocked, &v->vcpu_flags);
+
+    vcpu_unpause(v);
 }
 
 static void hvm_vcpu_down(void)
@@ -624,19 +643,12 @@ void hvm_hypercall_page_initialise(struc
  */
 int hvm_bringup_ap(int vcpuid, int trampoline_vector)
 {
-    struct vcpu *bsp = current, *v;
-    struct domain *d = bsp->domain;
+    struct vcpu *v;
+    struct domain *d = current->domain;
     struct vcpu_guest_context *ctxt;
     int rc = 0;
 
     BUG_ON(!is_hvm_domain(d));
-
-    if ( bsp->vcpu_id != 0 )
-    {
-        gdprintk(XENLOG_ERR, "Not calling hvm_bringup_ap from BSP context.\n");
-        domain_crash(bsp->domain);
-        return -EINVAL;
-    }
 
     if ( (v = d->vcpu[vcpuid]) == NULL )
         return -ENOENT;
@@ -668,8 +680,8 @@ int hvm_bringup_ap(int vcpuid, int tramp
         goto out;
     }
 
-    if ( test_and_clear_bit(_VCPUF_down, &d->vcpu[vcpuid]->vcpu_flags) )
-        vcpu_wake(d->vcpu[vcpuid]);
+    if ( test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) )
+        vcpu_wake(v);
     gdprintk(XENLOG_INFO, "AP %d bringup suceeded.\n", vcpuid);
 
  out:
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/i8254.c
--- a/xen/arch/x86/hvm/i8254.c  Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/hvm/i8254.c  Wed Feb 07 10:46:18 2007 -0700
@@ -83,8 +83,8 @@ static int pit_get_count(PITState *s, in
     struct hvm_hw_pit_channel *c = &s->hw.channels[channel];
     struct periodic_time *pt = &s->pt[channel];
 
-    d = muldiv64(hvm_get_guest_time(pt->vcpu) 
-                 - c->count_load_time, PIT_FREQ, ticks_per_sec(pt->vcpu));
+    d = muldiv64(hvm_get_guest_time(pt->vcpu) - s->count_load_time[channel],
+                 PIT_FREQ, ticks_per_sec(pt->vcpu));
     switch(c->mode) {
     case 0:
     case 1:
@@ -110,7 +110,7 @@ int pit_get_out(PITState *pit, int chann
     uint64_t d;
     int out;
 
-    d = muldiv64(current_time - s->count_load_time, 
+    d = muldiv64(current_time - pit->count_load_time[channel], 
                  PIT_FREQ, ticks_per_sec(pit->pt[channel].vcpu));
     switch(s->mode) {
     default:
@@ -153,7 +153,7 @@ void pit_set_gate(PITState *pit, int cha
     case 5:
         if (s->gate < val) {
             /* restart counting on rising edge */
-            s->count_load_time = hvm_get_guest_time(pt->vcpu);
+            pit->count_load_time[channel] = hvm_get_guest_time(pt->vcpu);
 //            pit_irq_timer_update(s, s->count_load_time);
         }
         break;
@@ -161,7 +161,7 @@ void pit_set_gate(PITState *pit, int cha
     case 3:
         if (s->gate < val) {
             /* restart counting on rising edge */
-            s->count_load_time = hvm_get_guest_time(pt->vcpu);
+            pit->count_load_time[channel] = hvm_get_guest_time(pt->vcpu);
 //            pit_irq_timer_update(s, s->count_load_time);
         }
         /* XXX: disable/enable counting */
@@ -177,8 +177,8 @@ int pit_get_gate(PITState *pit, int chan
 
 void pit_time_fired(struct vcpu *v, void *priv)
 {
-    struct hvm_hw_pit_channel *s = priv;
-    s->count_load_time = hvm_get_guest_time(v);
+    uint64_t *count_load_time = priv;
+    *count_load_time = hvm_get_guest_time(v);
 }
 
 static inline void pit_load_count(PITState *pit, int channel, int val)
@@ -190,7 +190,7 @@ static inline void pit_load_count(PITSta
 
     if (val == 0)
         val = 0x10000;
-    s->count_load_time = hvm_get_guest_time(pt->vcpu);
+    pit->count_load_time[channel] = hvm_get_guest_time(pt->vcpu);
     s->count = val;
     period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ);
 
@@ -203,7 +203,7 @@ static inline void pit_load_count(PITSta
             val,
             period,
             s->mode,
-            (long long)s->count_load_time);
+            (long long)pit->count_load_time[channel]);
 #endif
 
     /* Choose a vcpu to set the timer on: current if appropriate else vcpu 0 */
@@ -216,11 +216,13 @@ static inline void pit_load_count(PITSta
     switch (s->mode) {
         case 2:
             /* create periodic time */
-            create_periodic_time(v, pt, period, 0, 0, pit_time_fired, s);
+            create_periodic_time(v, pt, period, 0, 0, pit_time_fired, 
+                                 &pit->count_load_time[channel]);
             break;
         case 1:
             /* create one shot time */
-            create_periodic_time(v, pt, period, 0, 1, pit_time_fired, s);
+            create_periodic_time(v, pt, period, 0, 1, pit_time_fired,
+                                 &pit->count_load_time[channel]);
 #ifdef DEBUG_PIT
             printk("HVM_PIT: create one shot time.\n");
 #endif
@@ -387,7 +389,7 @@ static void pit_info(PITState *pit)
         printk("pit 0x%x.\n", s->mode);
         printk("pit 0x%x.\n", s->bcd);
         printk("pit 0x%x.\n", s->gate);
-        printk("pit %"PRId64"\n", s->count_load_time);
+        printk("pit %"PRId64"\n", pit->count_load_time[i]);
 
         pt = &pit->pt[i];
         if (pt) {
@@ -443,7 +445,7 @@ static int pit_load(struct domain *d, hv
     return 0;
 }
 
-HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load);
+HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load, 1, HVMSR_PER_DOM);
 
 static void pit_reset(void *opaque)
 {
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/intercept.c
--- a/xen/arch/x86/hvm/intercept.c      Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/hvm/intercept.c      Wed Feb 07 10:46:18 2007 -0700
@@ -29,8 +29,6 @@
 #include <asm/current.h>
 #include <io_ports.h>
 #include <xen/event.h>
-#include <xen/compile.h>
-#include <public/version.h>
 
 
 extern struct hvm_mmio_handler hpet_mmio_handler;
@@ -157,180 +155,6 @@ static inline void hvm_mmio_access(struc
     }
 }
 
-/* List of handlers for various HVM save and restore types */
-static struct { 
-    hvm_save_handler save;
-    hvm_load_handler load; 
-    const char *name;
-} hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL, "<?>"},};
-
-/* Init-time function to add entries to that list */
-void hvm_register_savevm(uint16_t typecode, 
-                         const char *name,
-                         hvm_save_handler save_state,
-                         hvm_load_handler load_state)
-{
-    ASSERT(typecode <= HVM_SAVE_CODE_MAX);
-    ASSERT(hvm_sr_handlers[typecode].save == NULL);
-    ASSERT(hvm_sr_handlers[typecode].load == NULL);
-    hvm_sr_handlers[typecode].save = save_state;
-    hvm_sr_handlers[typecode].load = load_state;
-    hvm_sr_handlers[typecode].name = name;
-}
-
-
-int hvm_save(struct domain *d, hvm_domain_context_t *h)
-{
-    uint32_t eax, ebx, ecx, edx;
-    char *c;
-    struct hvm_save_header hdr;
-    struct hvm_save_end end;
-    hvm_save_handler handler;
-    uint16_t i;
-
-    hdr.magic = HVM_FILE_MAGIC;
-    hdr.version = HVM_FILE_VERSION;
-
-    /* Save some CPUID bits */
-    cpuid(1, &eax, &ebx, &ecx, &edx);
-    hdr.cpuid = eax;
-
-    /* Save xen changeset */
-    c = strrchr(XEN_CHANGESET, ':');
-    if ( c )
-        hdr.changeset = simple_strtoll(c, NULL, 16);
-    else 
-        hdr.changeset = -1ULL; /* Unknown */
-
-    if ( hvm_save_entry(HEADER, 0, h, &hdr) != 0 )
-    {
-        gdprintk(XENLOG_ERR, "HVM save: failed to write header\n");
-        return -EFAULT;
-    } 
-
-    /* Save all available kinds of state */
-    for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ ) 
-    {
-        handler = hvm_sr_handlers[i].save;
-        if ( handler != NULL ) 
-        {
-            gdprintk(XENLOG_INFO, "HVM save: %s\n",  hvm_sr_handlers[i].name);
-            if ( handler(d, h) != 0 ) 
-            {
-                gdprintk(XENLOG_ERR, 
-                         "HVM save: failed to save type %"PRIu16"\n", i);
-                return -EFAULT;
-            } 
-        }
-    }
-
-    /* Save an end-of-file marker */
-    if ( hvm_save_entry(END, 0, h, &end) != 0 )
-    {
-        /* Run out of data */
-        gdprintk(XENLOG_ERR, "HVM save: no room for end marker.\n");
-        return -EFAULT;
-    }
-
-    /* Save macros should not have let us overrun */
-    ASSERT(h->cur <= h->size);
-    return 0;
-}
-
-int hvm_load(struct domain *d, hvm_domain_context_t *h)
-{
-    uint32_t eax, ebx, ecx, edx;
-    char *c;
-    uint64_t cset;
-    struct hvm_save_header hdr;
-    struct hvm_save_descriptor *desc;
-    hvm_load_handler handler;
-    struct vcpu *v;
-    
-    /* Read the save header, which must be first */
-    if ( hvm_load_entry(HEADER, h, &hdr) != 0 ) 
-        return -1;
-
-    if (hdr.magic != HVM_FILE_MAGIC) {
-        gdprintk(XENLOG_ERR, 
-                 "HVM restore: bad magic number %#"PRIx32"\n", hdr.magic);
-        return -1;
-    }
-
-    if (hdr.version != HVM_FILE_VERSION) {
-        gdprintk(XENLOG_ERR, 
-                 "HVM restore: unsupported version %u\n", hdr.version);
-        return -1;
-    }
-
-    cpuid(1, &eax, &ebx, &ecx, &edx);
-    /*TODO: need to define how big a difference is acceptable */
-    if (hdr.cpuid != eax)
-        gdprintk(XENLOG_WARNING, "HVM restore: saved CPUID (%#"PRIx32") "
-               "does not match host (%#"PRIx32").\n", hdr.cpuid, eax);
-
-
-    c = strrchr(XEN_CHANGESET, ':');
-    if ( hdr.changeset == -1ULL )
-        gdprintk(XENLOG_WARNING, 
-                 "HVM restore: Xen changeset was not saved.\n");
-    else if ( c == NULL )
-        gdprintk(XENLOG_WARNING, 
-                 "HVM restore: Xen changeset is not available.\n");
-    else
-    {
-        cset = simple_strtoll(c, NULL, 16);
-        if ( hdr.changeset != cset )
-        gdprintk(XENLOG_WARNING, "HVM restore: saved Xen changeset (%#"PRIx64
-                 ") does not match host (%#"PRIx64").\n", hdr.changeset, cset);
-    }
-
-    /* Down all the vcpus: we only re-enable the ones that had state saved. */
-    for_each_vcpu(d, v) 
-        if ( test_and_set_bit(_VCPUF_down, &v->vcpu_flags) )
-            vcpu_sleep_nosync(v);
-
-    while(1) {
-
-        if ( h->size - h->cur < sizeof(struct hvm_save_descriptor) )
-        {
-            /* Run out of data */
-            gdprintk(XENLOG_ERR, 
-                     "HVM restore: save did not end with a null entry\n");
-            return -1;
-        }
-        
-        /* Read the typecode of the next entry  and check for the end-marker */
-        desc = (struct hvm_save_descriptor *)(&h->data[h->cur]);
-        if ( desc->typecode == 0 )
-            return 0; 
-        
-        /* Find the handler for this entry */
-        if ( desc->typecode > HVM_SAVE_CODE_MAX 
-             || (handler = hvm_sr_handlers[desc->typecode].load) == NULL ) 
-        {
-            gdprintk(XENLOG_ERR, 
-                     "HVM restore: unknown entry typecode %u\n", 
-                     desc->typecode);
-            return -1;
-        }
-
-        /* Load the entry */
-        gdprintk(XENLOG_INFO, "HVM restore: %s %"PRIu16"\n",  
-                 hvm_sr_handlers[desc->typecode].name, desc->instance);
-        if ( handler(d, h) != 0 ) 
-        {
-            gdprintk(XENLOG_ERR, 
-                     "HVM restore: failed to load entry %u/%u\n", 
-                     desc->typecode, desc->instance);
-            return -1;
-        }
-    }
-
-    /* Not reached */
-}
-
-
 int hvm_buffered_io_intercept(ioreq_t *p)
 {
     struct vcpu *v = current;
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c    Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/hvm/irq.c    Wed Feb 07 10:46:18 2007 -0700
@@ -24,16 +24,17 @@
 #include <xen/event.h>
 #include <xen/sched.h>
 #include <asm/hvm/domain.h>
+#include <asm/hvm/support.h>
 
 static void __hvm_pci_intx_assert(
     struct domain *d, unsigned int device, unsigned int intx)
 {
-    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
     unsigned int gsi, link, isa_irq;
 
     ASSERT((device <= 31) && (intx <= 3));
 
-    if ( __test_and_set_bit(device*4 + intx, &hvm_irq->pci_intx) )
+    if ( __test_and_set_bit(device*4 + intx, &hvm_irq->pci_intx.i) )
         return;
 
     gsi = hvm_pci_intx_gsi(device, intx);
@@ -41,7 +42,7 @@ static void __hvm_pci_intx_assert(
         vioapic_irq_positive_edge(d, gsi);
 
     link    = hvm_pci_intx_link(device, intx);
-    isa_irq = hvm_irq->pci_link_route[link];
+    isa_irq = hvm_irq->pci_link.route[link];
     if ( (hvm_irq->pci_link_assert_count[link]++ == 0) && isa_irq &&
          (hvm_irq->gsi_assert_count[isa_irq]++ == 0) )
     {
@@ -61,19 +62,19 @@ static void __hvm_pci_intx_deassert(
 static void __hvm_pci_intx_deassert(
     struct domain *d, unsigned int device, unsigned int intx)
 {
-    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
     unsigned int gsi, link, isa_irq;
 
     ASSERT((device <= 31) && (intx <= 3));
 
-    if ( !__test_and_clear_bit(device*4 + intx, &hvm_irq->pci_intx) )
+    if ( !__test_and_clear_bit(device*4 + intx, &hvm_irq->pci_intx.i) )
         return;
 
     gsi = hvm_pci_intx_gsi(device, intx);
     --hvm_irq->gsi_assert_count[gsi];
 
     link    = hvm_pci_intx_link(device, intx);
-    isa_irq = hvm_irq->pci_link_route[link];
+    isa_irq = hvm_irq->pci_link.route[link];
     if ( (--hvm_irq->pci_link_assert_count[link] == 0) && isa_irq &&
          (--hvm_irq->gsi_assert_count[isa_irq] == 0) )
         vpic_irq_negative_edge(d, isa_irq);
@@ -90,14 +91,14 @@ void hvm_isa_irq_assert(
 void hvm_isa_irq_assert(
     struct domain *d, unsigned int isa_irq)
 {
-    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
     unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
 
     ASSERT(isa_irq <= 15);
 
     spin_lock(&d->arch.hvm_domain.irq_lock);
 
-    if ( !__test_and_set_bit(isa_irq, &hvm_irq->isa_irq) &&
+    if ( !__test_and_set_bit(isa_irq, &hvm_irq->isa_irq.i) &&
          (hvm_irq->gsi_assert_count[gsi]++ == 0) )
     {
         vioapic_irq_positive_edge(d, gsi);
@@ -110,14 +111,14 @@ void hvm_isa_irq_deassert(
 void hvm_isa_irq_deassert(
     struct domain *d, unsigned int isa_irq)
 {
-    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
     unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
 
     ASSERT(isa_irq <= 15);
 
     spin_lock(&d->arch.hvm_domain.irq_lock);
 
-    if ( __test_and_clear_bit(isa_irq, &hvm_irq->isa_irq) &&
+    if ( __test_and_clear_bit(isa_irq, &hvm_irq->isa_irq.i) &&
          (--hvm_irq->gsi_assert_count[gsi] == 0) )
         vpic_irq_negative_edge(d, isa_irq);
 
@@ -128,7 +129,7 @@ void hvm_set_callback_irq_level(void)
 {
     struct vcpu *v = current;
     struct domain *d = v->domain;
-    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
     unsigned int gsi, pdev, pintx, asserted;
 
     /* Fast lock-free tests. */
@@ -178,17 +179,17 @@ void hvm_set_callback_irq_level(void)
 
 void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq)
 {
-    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
     u8 old_isa_irq;
 
     ASSERT((link <= 3) && (isa_irq <= 15));
 
     spin_lock(&d->arch.hvm_domain.irq_lock);
 
-    old_isa_irq = hvm_irq->pci_link_route[link];
+    old_isa_irq = hvm_irq->pci_link.route[link];
     if ( old_isa_irq == isa_irq )
         goto out;
-    hvm_irq->pci_link_route[link] = isa_irq;
+    hvm_irq->pci_link.route[link] = isa_irq;
 
     if ( hvm_irq->pci_link_assert_count[link] == 0 )
         goto out;
@@ -211,7 +212,7 @@ void hvm_set_pci_link_route(struct domai
 
 void hvm_set_callback_via(struct domain *d, uint64_t via)
 {
-    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
     unsigned int gsi=0, pdev=0, pintx=0;
     uint8_t via_type;
 
@@ -335,3 +336,153 @@ int is_isa_irq_masked(struct vcpu *v, in
              (1 << (isa_irq & 7))) &&
             domain_vioapic(v->domain)->redirtbl[gsi].fields.mask);
 }
+
+#if 0 /* Keep for debugging */
+static void irq_dump(struct domain *d)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    int i; 
+    printk("PCI 0x%16.16"PRIx64"%16.16"PRIx64
+           " ISA 0x%8.8"PRIx32" ROUTE %u %u %u %u\n",
+           hvm_irq->pci_intx.pad[0],  hvm_irq->pci_intx.pad[1],
+           (uint32_t) hvm_irq->isa_irq.pad[0], 
+           hvm_irq->pci_link.route[0], hvm_irq->pci_link.route[1],
+           hvm_irq->pci_link.route[2], hvm_irq->pci_link.route[3]);
+    for ( i = 0 ; i < VIOAPIC_NUM_PINS; i += 8 )
+        printk("GSI  %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8
+               " %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8"\n",
+               hvm_irq->gsi_assert_count[i+0],
+               hvm_irq->gsi_assert_count[i+1],
+               hvm_irq->gsi_assert_count[i+2],
+               hvm_irq->gsi_assert_count[i+3],
+               hvm_irq->gsi_assert_count[i+4],
+               hvm_irq->gsi_assert_count[i+5],
+               hvm_irq->gsi_assert_count[i+6],
+               hvm_irq->gsi_assert_count[i+7]);
+    printk("Link %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8"\n",
+           hvm_irq->pci_link_assert_count[0],
+           hvm_irq->pci_link_assert_count[1],
+           hvm_irq->pci_link_assert_count[2],
+           hvm_irq->pci_link_assert_count[3]);
+    printk("Callback via %i:0x%"PRIx32",%s asserted\n", 
+           hvm_irq->callback_via_type, hvm_irq->callback_via.gsi, 
+           hvm_irq->callback_via_asserted ? "" : " not");
+}
+#endif
+
+static int irq_save_pci(struct domain *d, hvm_domain_context_t *h)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+
+    /* Save PCI IRQ lines */
+    return ( hvm_save_entry(PCI_IRQ, 0, h, &hvm_irq->pci_intx) );
+}
+
+static int irq_save_isa(struct domain *d, hvm_domain_context_t *h)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+
+    /* Save ISA IRQ lines */
+    return ( hvm_save_entry(ISA_IRQ, 0, h, &hvm_irq->isa_irq) );
+}
+
+static int irq_save_link(struct domain *d, hvm_domain_context_t *h)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+
+    /* Save PCI-ISA link state */
+    return ( hvm_save_entry(PCI_LINK, 0, h, &hvm_irq->pci_link) );
+}
+
+static int irq_load_pci(struct domain *d, hvm_domain_context_t *h)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    int link, dev, intx, gsi;
+
+    /* Load the PCI IRQ lines */
+    if ( hvm_load_entry(PCI_IRQ, h, &hvm_irq->pci_intx) != 0 )
+        return -EINVAL;
+
+    /* Clear the PCI link assert counts */
+    for ( link = 0; link < 4; link++ )
+        hvm_irq->pci_link_assert_count[link] = 0;
+    
+    /* Clear the GSI link assert counts */
+    for ( gsi = 0; gsi < VIOAPIC_NUM_PINS; gsi++ )
+        hvm_irq->gsi_assert_count[gsi] = 0;
+
+    /* Recalculate the counts from the IRQ line state */
+    for ( dev = 0; dev < 32; dev++ )
+        for ( intx = 0; intx < 4; intx++ )
+            if ( test_bit(dev*4 + intx, &hvm_irq->pci_intx.i) )
+            {
+                /* Direct GSI assert */
+                gsi = hvm_pci_intx_gsi(dev, intx);
+                hvm_irq->gsi_assert_count[gsi]++;
+                /* PCI-ISA bridge assert */
+                link = hvm_pci_intx_link(dev, intx);
+                hvm_irq->pci_link_assert_count[link]++;
+            }
+
+    return 0;
+}
+
+static int irq_load_isa(struct domain *d, hvm_domain_context_t *h)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    int irq;
+
+    /* Load the ISA IRQ lines */
+    if ( hvm_load_entry(ISA_IRQ, h, &hvm_irq->isa_irq) != 0 )
+        return -EINVAL;
+
+    /* Adjust the GSI assert counts for the ISA IRQ line state.
+     * This relies on the PCI IRQ state being loaded first. */
+    for ( irq = 0; irq < 16; irq++ )
+        if ( test_bit(irq, &hvm_irq->isa_irq.i) )
+            hvm_irq->gsi_assert_count[hvm_isa_irq_to_gsi(irq)]++;
+
+    return 0;
+}
+
+
+static int irq_load_link(struct domain *d, hvm_domain_context_t *h)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    int link, gsi;
+
+    /* Load the PCI-ISA IRQ link routing table */
+    if ( hvm_load_entry(PCI_LINK, h, &hvm_irq->pci_link) != 0 )
+        return -EINVAL;
+
+    /* Sanity check */
+    for ( link = 0; link < 4; link++ )
+        if ( hvm_irq->pci_link.route[link] > 15 )
+        {
+            gdprintk(XENLOG_ERR, 
+                     "HVM restore: PCI-ISA link %u out of range (%u)\n",
+                     link, hvm_irq->pci_link.route[link]);
+            return -EINVAL;
+        }
+
+    /* Adjust the GSI assert counts for the link outputs.
+     * This relies on the PCI and ISA IRQ state being loaded first */
+    for ( link = 0; link < 4; link++ )
+    {
+        if ( hvm_irq->pci_link_assert_count[link] != 0 )
+        {
+            gsi = hvm_irq->pci_link.route[link];
+            if ( gsi != 0 )
+                hvm_irq->gsi_assert_count[gsi]++;
+        }
+    }
+
+    return 0;
+}
+
+HVM_REGISTER_SAVE_RESTORE(PCI_IRQ, irq_save_pci, irq_load_pci,
+                          1, HVMSR_PER_DOM);
+HVM_REGISTER_SAVE_RESTORE(ISA_IRQ, irq_save_isa, irq_load_isa, 
+                          1, HVMSR_PER_DOM);
+HVM_REGISTER_SAVE_RESTORE(PCI_LINK, irq_save_link, irq_load_link,
+                          1, HVMSR_PER_DOM);
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/rtc.c
--- a/xen/arch/x86/hvm/rtc.c    Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/hvm/rtc.c    Wed Feb 07 10:46:18 2007 -0700
@@ -417,7 +417,7 @@ static int rtc_load(struct domain *d, hv
     return 0;
 }
 
-HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save, rtc_load);
+HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save, rtc_load, 1, HVMSR_PER_DOM);
 
 
 void rtc_init(struct vcpu *v, int base)
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/save.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/hvm/save.c   Wed Feb 07 10:46:18 2007 -0700
@@ -0,0 +1,229 @@
+/*
+ * hvm/save.c: Save and restore HVM guest's emulated hardware state.
+ *
+ * Copyright (c) 2004, Intel Corporation.
+ * Copyright (c) 2007, XenSource Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <xen/config.h>
+#include <xen/compile.h>
+#include <xen/lib.h>
+#include <public/version.h>
+#include <xen/sched.h>
+
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/domain.h>
+#include <asm/current.h>
+
+
+/* List of handlers for various HVM save and restore types */
+static struct { 
+    hvm_save_handler save;
+    hvm_load_handler load; 
+    const char *name;
+    size_t size;
+    int kind;
+} hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL, "<?>"},};
+
+/* Init-time function to add entries to that list */
+void hvm_register_savevm(uint16_t typecode, 
+                         const char *name,
+                         hvm_save_handler save_state,
+                         hvm_load_handler load_state,
+                         size_t size, int kind)
+{
+    ASSERT(typecode <= HVM_SAVE_CODE_MAX);
+    ASSERT(hvm_sr_handlers[typecode].save == NULL);
+    ASSERT(hvm_sr_handlers[typecode].load == NULL);
+    hvm_sr_handlers[typecode].save = save_state;
+    hvm_sr_handlers[typecode].load = load_state;
+    hvm_sr_handlers[typecode].name = name;
+    hvm_sr_handlers[typecode].size = size;
+    hvm_sr_handlers[typecode].kind = kind;
+}
+
+size_t hvm_save_size(struct domain *d) 
+{
+    struct vcpu *v;
+    size_t sz;
+    int i;
+    
+    /* Basic overhead for header and footer */
+    sz = (2 * sizeof (struct hvm_save_descriptor)) + HVM_SAVE_LENGTH(HEADER);
+
+    /* Plus space for each thing we will be saving */
+    for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ ) 
+        if ( hvm_sr_handlers[i].kind == HVMSR_PER_VCPU )
+            for_each_vcpu(d, v)
+                sz += hvm_sr_handlers[i].size;
+        else 
+            sz += hvm_sr_handlers[i].size;
+
+    return sz;
+}
+
+
+int hvm_save(struct domain *d, hvm_domain_context_t *h)
+{
+    uint32_t eax, ebx, ecx, edx;
+    char *c;
+    struct hvm_save_header hdr;
+    struct hvm_save_end end;
+    hvm_save_handler handler;
+    uint16_t i;
+
+    hdr.magic = HVM_FILE_MAGIC;
+    hdr.version = HVM_FILE_VERSION;
+
+    /* Save some CPUID bits */
+    cpuid(1, &eax, &ebx, &ecx, &edx);
+    hdr.cpuid = eax;
+
+    /* Save xen changeset */
+    c = strrchr(XEN_CHANGESET, ':');
+    if ( c )
+        hdr.changeset = simple_strtoll(c, NULL, 16);
+    else 
+        hdr.changeset = -1ULL; /* Unknown */
+
+    if ( hvm_save_entry(HEADER, 0, h, &hdr) != 0 )
+    {
+        gdprintk(XENLOG_ERR, "HVM save: failed to write header\n");
+        return -EFAULT;
+    } 
+
+    /* Save all available kinds of state */
+    for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ ) 
+    {
+        handler = hvm_sr_handlers[i].save;
+        if ( handler != NULL ) 
+        {
+            gdprintk(XENLOG_INFO, "HVM save: %s\n",  hvm_sr_handlers[i].name);
+            if ( handler(d, h) != 0 ) 
+            {
+                gdprintk(XENLOG_ERR, 
+                         "HVM save: failed to save type %"PRIu16"\n", i);
+                return -EFAULT;
+            } 
+        }
+    }
+
+    /* Save an end-of-file marker */
+    if ( hvm_save_entry(END, 0, h, &end) != 0 )
+    {
+        /* Run out of data */
+        gdprintk(XENLOG_ERR, "HVM save: no room for end marker.\n");
+        return -EFAULT;
+    }
+
+    /* Save macros should not have let us overrun */
+    ASSERT(h->cur <= h->size);
+    return 0;
+}
+
+int hvm_load(struct domain *d, hvm_domain_context_t *h)
+{
+    uint32_t eax, ebx, ecx, edx;
+    char *c;
+    uint64_t cset;
+    struct hvm_save_header hdr;
+    struct hvm_save_descriptor *desc;
+    hvm_load_handler handler;
+    struct vcpu *v;
+    
+    /* Read the save header, which must be first */
+    if ( hvm_load_entry(HEADER, h, &hdr) != 0 ) 
+        return -1;
+
+    if (hdr.magic != HVM_FILE_MAGIC) {
+        gdprintk(XENLOG_ERR, 
+                 "HVM restore: bad magic number %#"PRIx32"\n", hdr.magic);
+        return -1;
+    }
+
+    if (hdr.version != HVM_FILE_VERSION) {
+        gdprintk(XENLOG_ERR, 
+                 "HVM restore: unsupported version %u\n", hdr.version);
+        return -1;
+    }
+
+    cpuid(1, &eax, &ebx, &ecx, &edx);
+    /*TODO: need to define how big a difference is acceptable */
+    if (hdr.cpuid != eax)
+        gdprintk(XENLOG_WARNING, "HVM restore: saved CPUID (%#"PRIx32") "
+               "does not match host (%#"PRIx32").\n", hdr.cpuid, eax);
+
+
+    c = strrchr(XEN_CHANGESET, ':');
+    if ( hdr.changeset == -1ULL )
+        gdprintk(XENLOG_WARNING, 
+                 "HVM restore: Xen changeset was not saved.\n");
+    else if ( c == NULL )
+        gdprintk(XENLOG_WARNING, 
+                 "HVM restore: Xen changeset is not available.\n");
+    else
+    {
+        cset = simple_strtoll(c, NULL, 16);
+        if ( hdr.changeset != cset )
+        gdprintk(XENLOG_WARNING, "HVM restore: saved Xen changeset (%#"PRIx64
+                 ") does not match host (%#"PRIx64").\n", hdr.changeset, cset);
+    }
+
+    /* Down all the vcpus: we only re-enable the ones that had state saved. */
+    for_each_vcpu(d, v) 
+        if ( test_and_set_bit(_VCPUF_down, &v->vcpu_flags) )
+            vcpu_sleep_nosync(v);
+
+    while(1) {
+
+        if ( h->size - h->cur < sizeof(struct hvm_save_descriptor) )
+        {
+            /* Run out of data */
+            gdprintk(XENLOG_ERR, 
+                     "HVM restore: save did not end with a null entry\n");
+            return -1;
+        }
+        
+        /* Read the typecode of the next entry  and check for the end-marker */
+        desc = (struct hvm_save_descriptor *)(&h->data[h->cur]);
+        if ( desc->typecode == 0 )
+            return 0; 
+        
+        /* Find the handler for this entry */
+        if ( desc->typecode > HVM_SAVE_CODE_MAX 
+             || (handler = hvm_sr_handlers[desc->typecode].load) == NULL ) 
+        {
+            gdprintk(XENLOG_ERR, 
+                     "HVM restore: unknown entry typecode %u\n", 
+                     desc->typecode);
+            return -1;
+        }
+
+        /* Load the entry */
+        gdprintk(XENLOG_INFO, "HVM restore: %s %"PRIu16"\n",  
+                 hvm_sr_handlers[desc->typecode].name, desc->instance);
+        if ( handler(d, h) != 0 ) 
+        {
+            gdprintk(XENLOG_ERR, 
+                     "HVM restore: failed to load entry %u/%u\n", 
+                     desc->typecode, desc->instance);
+            return -1;
+        }
+    }
+
+    /* Not reached */
+}
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/hvm/svm/svm.c        Wed Feb 07 10:46:18 2007 -0700
@@ -591,6 +591,7 @@ void svm_load_cpu_state(struct vcpu *v, 
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
 
+    vmcb->kerngsbase = data->shadow_gs;
     /* MSR_LSTAR, MSR_STAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_EFER */
     vmcb->lstar  = data->msr_items[0];
     vmcb->star   = data->msr_items[1];
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Wed Feb 07 10:46:18 2007 -0700
@@ -209,7 +209,8 @@ int svm_create_vmcb(struct vcpu *v)
     struct arch_svm_struct *arch_svm = &v->arch.hvm_svm;
     int rc;
 
-    if ( (arch_svm->vmcb = alloc_vmcb()) == NULL )
+    if ( (arch_svm->vmcb == NULL) &&
+         (arch_svm->vmcb = alloc_vmcb()) == NULL )
     {
         printk("Failed to create a new VMCB\n");
         return -ENOMEM;
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/vioapic.c
--- a/xen/arch/x86/hvm/vioapic.c        Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/hvm/vioapic.c        Wed Feb 07 10:46:18 2007 -0700
@@ -125,7 +125,7 @@ static void vioapic_write_redirent(
     struct hvm_hw_vioapic *vioapic, unsigned int idx, int top_word, uint32_t 
val)
 {
     struct domain *d = vioapic_domain(vioapic);
-    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
     union vioapic_redir_entry *pent, ent;
 
     spin_lock(&d->arch.hvm_domain.irq_lock);
@@ -446,7 +446,7 @@ void vioapic_update_EOI(struct domain *d
 void vioapic_update_EOI(struct domain *d, int vector)
 {
     struct hvm_hw_vioapic *vioapic = domain_vioapic(d);
-    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
     union vioapic_redir_entry *ent;
     int gsi;
 
@@ -486,41 +486,10 @@ static void ioapic_info(struct hvm_hw_vi
     }
 
 }
-static void hvmirq_info(struct hvm_hw_irq *hvm_irq)
-{
-    int i;
-    printk("*****hvmirq state:*****\n");
-    for (i = 0; i < BITS_TO_LONGS(32*4); i++)
-        printk("hvmirq pci_intx[%d]:0x%lx.\n", i, hvm_irq->pci_intx[i]);
-
-    for (i = 0; i < BITS_TO_LONGS(16); i++)
-        printk("hvmirq isa_irq[%d]:0x%lx.\n", i, hvm_irq->isa_irq[i]);
-
-    for (i = 0; i < BITS_TO_LONGS(1); i++)
-        printk("hvmirq callback_irq_wire[%d]:0x%lx.\n", i, 
hvm_irq->callback_irq_wire[i]);
-
-    printk("hvmirq callback_via_type:0x%x.\n", hvm_irq->callback_via_type);
-    printk("hvmirq callback_via:0x%x.\n", hvm_irq->callback_via.gsi);
-    
-
-    for (i = 0; i < 4; i++)
-        printk("hvmirq pci_link_route[%d]:0x%"PRIx8".\n", i, 
hvm_irq->pci_link_route[i]);
-
-    for (i = 0; i < 4; i++)
-        printk("hvmirq pci_link_assert_count[%d]:0x%"PRIx8".\n", i, 
hvm_irq->pci_link_assert_count[i]);
-
-    for (i = 0; i < VIOAPIC_NUM_PINS; i++)
-        printk("hvmirq gsi_assert_count[%d]:0x%"PRIx8".\n", i, 
hvm_irq->gsi_assert_count[i]);
-
-    printk("hvmirq round_robin_prev_vcpu:0x%"PRIx8".\n", 
hvm_irq->round_robin_prev_vcpu);
-}
 #else
 static void ioapic_info(struct hvm_hw_vioapic *s)
 {
 }
-static void hvmirq_info(struct hvm_hw_irq *hvm_irq)
-{
-}
 #endif
 
 
@@ -532,16 +501,6 @@ static int ioapic_save(struct domain *d,
     /* save io-apic state*/
     return ( hvm_save_entry(IOAPIC, 0, h, s) );
 }
-
-static int ioapic_save_irqs(struct domain *d, hvm_domain_context_t *h)
-{
-    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
-    hvmirq_info(hvm_irq);
-
-    /* save IRQ state*/
-    return ( hvm_save_entry(IRQ, 0, h, hvm_irq) );    
-}
-
 
 static int ioapic_load(struct domain *d, hvm_domain_context_t *h)
 {
@@ -555,20 +514,7 @@ static int ioapic_load(struct domain *d,
     return 0;
 }
 
-static int ioapic_load_irqs(struct domain *d, hvm_domain_context_t *h)
-{
-    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
-
-    /* restore irq state */
-    if ( hvm_load_entry(IRQ, h, hvm_irq) != 0 )
-        return -EINVAL;
-
-    hvmirq_info(hvm_irq);
-    return 0;
-}
-
-HVM_REGISTER_SAVE_RESTORE(IOAPIC, ioapic_save, ioapic_load);
-HVM_REGISTER_SAVE_RESTORE(IRQ, ioapic_save_irqs, ioapic_load_irqs);
+HVM_REGISTER_SAVE_RESTORE(IOAPIC, ioapic_save, ioapic_load, 1, HVMSR_PER_DOM);
 
 void vioapic_init(struct domain *d)
 {
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/hvm/vlapic.c Wed Feb 07 10:46:18 2007 -0700
@@ -83,8 +83,6 @@ static unsigned int vlapic_lvt_mask[VLAP
 #define vlapic_base_address(vlapic)                             \
     (vlapic->hw.apic_base_msr & MSR_IA32_APICBASE_BASE)
 
-static int vlapic_reset(struct vlapic *vlapic);
-
 /*
  * Generic APIC bitmap vector update & search routines.
  */
@@ -293,8 +291,11 @@ static int vlapic_accept_irq(struct vcpu
         break;
 
     case APIC_DM_SMI:
+        gdprintk(XENLOG_WARNING, "Ignoring guest SMI\n");
+        break;
+
     case APIC_DM_NMI:
-        gdprintk(XENLOG_WARNING, "Ignoring guest SMI/NMI\n");
+        gdprintk(XENLOG_WARNING, "Ignoring guest NMI\n");
         break;
 
     case APIC_DM_INIT:
@@ -303,10 +304,7 @@ static int vlapic_accept_irq(struct vcpu
             break;
         /* FIXME How to check the situation after vcpu reset? */
         if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
-        {
-            gdprintk(XENLOG_ERR, "Reset hvm vcpu not supported yet\n");
-            goto exit_and_crash;
-        }
+            hvm_vcpu_reset(v);
         v->arch.hvm_vcpu.init_sipi_sipi_state =
             HVM_VCPU_INIT_SIPI_SIPI_STATE_WAIT_SIPI;
         result = 1;
@@ -764,7 +762,7 @@ int cpu_get_apic_interrupt(struct vcpu *
 }
 
 /* Reset the VLPAIC back to its power-on/reset state. */
-static int vlapic_reset(struct vlapic *vlapic)
+void vlapic_reset(struct vlapic *vlapic)
 {
     struct vcpu *v = vlapic_vcpu(vlapic);
     int i;
@@ -793,8 +791,6 @@ static int vlapic_reset(struct vlapic *v
 
     vlapic_set_reg(vlapic, APIC_SPIV, 0xff);
     vlapic->hw.disabled |= VLAPIC_SW_DISABLED;
-
-    return 1;
 }
 
 #ifdef HVM_DEBUG_SUSPEND
@@ -908,8 +904,10 @@ static int lapic_load_regs(struct domain
     return 0;
 }
 
-HVM_REGISTER_SAVE_RESTORE(LAPIC, lapic_save_hidden, lapic_load_hidden);
-HVM_REGISTER_SAVE_RESTORE(LAPIC_REGS, lapic_save_regs, lapic_load_regs);
+HVM_REGISTER_SAVE_RESTORE(LAPIC, lapic_save_hidden, lapic_load_hidden,
+                          1, HVMSR_PER_VCPU);
+HVM_REGISTER_SAVE_RESTORE(LAPIC_REGS, lapic_save_regs, lapic_load_regs,
+                          1, HVMSR_PER_VCPU);
 
 int vlapic_init(struct vcpu *v)
 {
@@ -922,7 +920,6 @@ int vlapic_init(struct vcpu *v)
     {
         dprintk(XENLOG_ERR, "malloc vlapic regs error for vcpu %x\n",
                 v->vcpu_id);
-        xfree(vlapic);
         return -ENOMEM;
     }
 
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Wed Feb 07 10:46:18 2007 -0700
@@ -295,6 +295,11 @@ static void construct_vmcs(struct vcpu *
 
     vmx_vmcs_enter(v);
 
+    v->arch.hvm_vmx.cpu_cr2 = 0;
+    v->arch.hvm_vmx.cpu_cr3 = 0;
+    memset(&v->arch.hvm_vmx.msr_state, 0, sizeof(v->arch.hvm_vmx.msr_state));
+    v->arch.hvm_vmx.vmxassist_enabled = 0;
+
     /* VMCS controls. */
     __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control);
     __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control);
@@ -448,10 +453,13 @@ static void construct_vmcs(struct vcpu *
 
 int vmx_create_vmcs(struct vcpu *v)
 {
-    if ( (v->arch.hvm_vmx.vmcs = vmx_alloc_vmcs()) == NULL )
-        return -ENOMEM;
- 
-    __vmx_clear_vmcs(v);
+    if ( v->arch.hvm_vmx.vmcs == NULL )
+    {
+        if ( (v->arch.hvm_vmx.vmcs = vmx_alloc_vmcs()) == NULL )
+            return -ENOMEM;
+
+        __vmx_clear_vmcs(v);
+    }
 
     construct_vmcs(v);
 
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Wed Feb 07 10:46:18 2007 -0700
@@ -588,7 +588,7 @@ void vmx_save_cpu_state(struct vcpu *v, 
     int i = 0;
 
     data->shadow_gs = guest_state->shadow_gs;
-    data->vmxassist_enabled = v->arch.hvm_vmx.vmxassist_enabled;
+
     /* save msrs */
     data->flags = guest_flags;
     for (i = 0; i < VMX_MSR_COUNT; i++)
@@ -611,10 +611,7 @@ void vmx_load_cpu_state(struct vcpu *v, 
 
     guest_state->shadow_gs = data->shadow_gs;
 
-    /*XXX:no need to restore msrs, current!=vcpu as not called by 
arch_vmx_do_launch */
-/*    vmx_restore_guest_msrs(v);*/
-
-    v->arch.hvm_vmx.vmxassist_enabled = data->vmxassist_enabled;
+    v->arch.hvm_vmx.vmxassist_enabled = !(data->cr0 & X86_CR0_PE);
 
     hvm_set_guest_time(v, data->tsc);
 
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/hvm/vpic.c
--- a/xen/arch/x86/hvm/vpic.c   Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/hvm/vpic.c   Wed Feb 07 10:46:18 2007 -0700
@@ -440,7 +440,7 @@ static int vpic_load(struct domain *d, h
     return 0;
 }
 
-HVM_REGISTER_SAVE_RESTORE(PIC, vpic_save, vpic_load);
+HVM_REGISTER_SAVE_RESTORE(PIC, vpic_save, vpic_load, 2, HVMSR_PER_DOM);
 
 void vpic_init(struct domain *d)
 {
diff -r d3f08d39e695 -r fbc233a1dc53 xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/arch/x86/mm/shadow/multi.c    Wed Feb 07 10:46:18 2007 -0700
@@ -3875,11 +3875,9 @@ static inline void * emulate_map_dest(st
         goto page_fault;
     }
 
-    /* Attempted a write to a bad gfn? This should never happen:
-     * after all, we're here because this write is to a page table. */
-    BUG_ON(!mfn_valid(mfn));
-
-    ASSERT(sh_mfn_is_a_page_table(mfn));
+    if ( !mfn_valid(mfn) )
+        return NULL;
+
     *mfnp = mfn;
     return sh_map_domain_page(mfn) + (vaddr & ~PAGE_MASK);
 
diff -r d3f08d39e695 -r fbc233a1dc53 xen/include/asm-x86/hvm/domain.h
--- a/xen/include/asm-x86/hvm/domain.h  Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/include/asm-x86/hvm/domain.h  Wed Feb 07 10:46:18 2007 -0700
@@ -39,7 +39,7 @@ struct hvm_domain {
 
     /* Lock protects access to irq, vpic and vioapic. */
     spinlock_t             irq_lock;
-    struct hvm_hw_irq      irq;
+    struct hvm_irq         irq;
     struct hvm_hw_vpic     vpic[2]; /* 0=master; 1=slave */
     struct hvm_hw_vioapic  vioapic;
 
diff -r d3f08d39e695 -r fbc233a1dc53 xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/include/asm-x86/hvm/hvm.h     Wed Feb 07 10:46:18 2007 -0700
@@ -153,6 +153,7 @@ void hvm_domain_destroy(struct domain *d
 
 int hvm_vcpu_initialise(struct vcpu *v);
 void hvm_vcpu_destroy(struct vcpu *v);
+void hvm_vcpu_reset(struct vcpu *vcpu);
 
 void hvm_send_assist_req(struct vcpu *v);
 
diff -r d3f08d39e695 -r fbc233a1dc53 xen/include/asm-x86/hvm/irq.h
--- a/xen/include/asm-x86/hvm/irq.h     Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/include/asm-x86/hvm/irq.h     Wed Feb 07 10:46:18 2007 -0700
@@ -27,6 +27,69 @@
 #include <asm/hvm/vpic.h>
 #include <asm/hvm/vioapic.h>
 #include <public/hvm/save.h>
+
+
+struct hvm_irq {
+    /*
+     * Virtual interrupt wires for a single PCI bus.
+     * Indexed by: device*4 + INTx#.
+     */
+    struct hvm_hw_pci_irqs pci_intx;
+
+    /*
+     * Virtual interrupt wires for ISA devices.
+     * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
+     */
+    struct hvm_hw_isa_irqs isa_irq;
+
+    /*
+     * PCI-ISA interrupt router.
+     * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
+     * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
+     * The router provides a programmable mapping from each link to a GSI.
+     */
+    struct hvm_hw_pci_link pci_link;
+
+    /* Virtual interrupt and via-link for paravirtual platform driver. */
+    uint32_t callback_via_asserted;
+    union {
+        enum {
+            HVMIRQ_callback_none,
+            HVMIRQ_callback_gsi,
+            HVMIRQ_callback_pci_intx
+        } callback_via_type;
+        uint32_t pad; /* So the next field will be aligned */
+    };
+    union {
+        uint32_t gsi;
+        struct { uint8_t dev, intx; } pci;
+    } callback_via;
+
+    /* Number of INTx wires asserting each PCI-ISA link. */
+    u8 pci_link_assert_count[4];
+
+    /*
+     * Number of wires asserting each GSI.
+     * 
+     * GSIs 0-15 are the ISA IRQs. ISA devices map directly into this space
+     * except ISA IRQ 0, which is connected to GSI 2.
+     * PCI links map into this space via the PCI-ISA bridge.
+     * 
+     * GSIs 16+ are used only be PCI devices. The mapping from PCI device to
+     * GSI is as follows: ((device*4 + device/8 + INTx#) & 31) + 16
+     */
+    u8 gsi_assert_count[VIOAPIC_NUM_PINS];
+
+    /*
+     * GSIs map onto PIC/IO-APIC in the usual way:
+     *  0-7:  Master 8259 PIC, IO-APIC pins 0-7
+     *  8-15: Slave  8259 PIC, IO-APIC pins 8-15
+     *  16+ : IO-APIC pins 16+
+     */
+
+    /* Last VCPU that was delivered a LowestPrio interrupt. */
+    u8 round_robin_prev_vcpu;
+};
 
 #define hvm_pci_intx_gsi(dev, intx)  \
     (((((dev)<<2) + ((dev)>>3) + (intx)) & 31) + 16)
diff -r d3f08d39e695 -r fbc233a1dc53 xen/include/asm-x86/hvm/support.h
--- a/xen/include/asm-x86/hvm/support.h Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/include/asm-x86/hvm/support.h Wed Feb 07 10:46:18 2007 -0700
@@ -221,23 +221,37 @@ typedef int (*hvm_load_handler) (struct 
 typedef int (*hvm_load_handler) (struct domain *d,
                                  hvm_domain_context_t *h);
 
-/* Init-time function to declare a pair of handlers for a type */
+/* Init-time function to declare a pair of handlers for a type,
+ * and the maximum buffer space needed to save this type of state */
 void hvm_register_savevm(uint16_t typecode,
                          const char *name, 
                          hvm_save_handler save_state,
-                         hvm_load_handler load_state);
-
-/* Syntactic sugar around that function */
-#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load)                     \
-static int __hvm_register_##_x##_save_and_restore(void)                 \
-{                                                                       \
-    hvm_register_savevm(HVM_SAVE_CODE(_x), #_x, &_save, &_load);        \
-    return 0;                                                           \
-}                                                                       \
+                         hvm_load_handler load_state,
+                         size_t size, int kind);
+
+/* The space needed for saving can be per-domain or per-vcpu: */
+#define HVMSR_PER_DOM  0
+#define HVMSR_PER_VCPU 1
+
+/* Syntactic sugar around that function: specify the max number of
+ * saves, and this calculates the size of buffer needed */
+#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load, _num, _k)             \
+static int __hvm_register_##_x##_save_and_restore(void)                   \
+{                                                                         \
+    hvm_register_savevm(HVM_SAVE_CODE(_x),                                \
+                        #_x,                                              \
+                        &_save,                                           \
+                        &_load,                                           \
+                        (_num) * (HVM_SAVE_LENGTH(_x)                     \
+                                  + sizeof (struct hvm_save_descriptor)), \
+                        _k);                                              \
+    return 0;                                                             \
+}                                                                         \
 __initcall(__hvm_register_##_x##_save_and_restore);
 
 
 /* Entry points for saving and restoring HVM domain state */
+size_t hvm_save_size(struct domain *d);
 int hvm_save(struct domain *d, hvm_domain_context_t *h);
 int hvm_load(struct domain *d, hvm_domain_context_t *h);
 
diff -r d3f08d39e695 -r fbc233a1dc53 xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h  Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/include/asm-x86/hvm/vlapic.h  Wed Feb 07 10:46:18 2007 -0700
@@ -78,6 +78,8 @@ int  vlapic_init(struct vcpu *v);
 int  vlapic_init(struct vcpu *v);
 void vlapic_destroy(struct vcpu *v);
 
+void vlapic_reset(struct vlapic *vlapic);
+
 void vlapic_msr_set(struct vlapic *vlapic, uint64_t value);
 
 int vlapic_accept_pic_intr(struct vcpu *v);
diff -r d3f08d39e695 -r fbc233a1dc53 xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h     Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/include/asm-x86/hvm/vpt.h     Wed Feb 07 10:46:18 2007 -0700
@@ -66,7 +66,7 @@ struct periodic_time {
     u64 last_plt_gtime;         /* platform time when last IRQ is injected */
     struct timer timer;         /* ac_timer */
     time_cb *cb;
-    void *priv;                 /* ponit back to platform time source */
+    void *priv;                 /* point back to platform time source */
 };
 
 
@@ -76,6 +76,8 @@ typedef struct PITState {
 typedef struct PITState {
     /* Hardware state */
     struct hvm_hw_pit hw;
+    /* Last time the counters read zero, for calcuating counter reads */
+    int64_t count_load_time[3];
     /* irq handling */
     struct periodic_time pt[3];
 } PITState;
diff -r d3f08d39e695 -r fbc233a1dc53 xen/include/public/domctl.h
--- a/xen/include/public/domctl.h       Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/include/public/domctl.h       Wed Feb 07 10:46:18 2007 -0700
@@ -390,7 +390,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_setti
 #define XEN_DOMCTL_sethvmcontext   34
 typedef struct xen_domctl_hvmcontext {
     uint32_t size; /* IN/OUT: size of buffer / bytes filled */
-    XEN_GUEST_HANDLE(uint8_t) buffer; /* IN/OUT */
+    XEN_GUEST_HANDLE(uint8_t) buffer; /* IN/OUT: data, or call gethvmcontext 
+                                       * with NULL buffer to get size req'd */
 } xen_domctl_hvmcontext_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t);
 
diff -r d3f08d39e695 -r fbc233a1dc53 xen/include/public/hvm/save.h
--- a/xen/include/public/hvm/save.h     Wed Feb 07 10:14:41 2007 -0700
+++ b/xen/include/public/hvm/save.h     Wed Feb 07 10:46:18 2007 -0700
@@ -140,45 +140,16 @@ struct hvm_hw_cpu {
     uint64_t sysenter_esp;
     uint64_t sysenter_eip;
 
-    /* msr for em64t */
+    /* MSRs */
     uint64_t shadow_gs;
     uint64_t flags;
-
-    /* same size as VMX_MSR_COUNT */
     uint64_t msr_items[6];
-    uint64_t vmxassist_enabled;
 
     /* guest's idea of what rdtsc() would return */
     uint64_t tsc;
 };
 
 DECLARE_HVM_SAVE_TYPE(CPU, 2, struct hvm_hw_cpu);
-
-
-/* 
- *  PIT
- */
-
-struct hvm_hw_pit {
-    struct hvm_hw_pit_channel {
-        int64_t count_load_time;
-        uint32_t count; /* can be 65536 */
-        uint16_t latched_count;
-        uint8_t count_latched;
-        uint8_t status_latched;
-        uint8_t status;
-        uint8_t read_state;
-        uint8_t write_state;
-        uint8_t write_latch;
-        uint8_t rw_mode;
-        uint8_t mode;
-        uint8_t bcd; /* not supported */
-        uint8_t gate; /* timer start */
-    } channels[3];  /* 3 x 24 bytes */
-    uint32_t speaker_data_on;
-};
-
-DECLARE_HVM_SAVE_TYPE(PIT, 3, struct hvm_hw_pit);
 
 
 /*
@@ -233,7 +204,7 @@ struct hvm_hw_vpic {
     uint8_t int_output;
 };
 
-DECLARE_HVM_SAVE_TYPE(PIC, 4, struct hvm_hw_vpic);
+DECLARE_HVM_SAVE_TYPE(PIC, 3, struct hvm_hw_vpic);
 
 
 /*
@@ -275,95 +246,95 @@ struct hvm_hw_vioapic {
     } redirtbl[VIOAPIC_NUM_PINS];
 };
 
-DECLARE_HVM_SAVE_TYPE(IOAPIC, 5, struct hvm_hw_vioapic);
-
-
-/*
- * IRQ
- */
-
-struct hvm_hw_irq {
+DECLARE_HVM_SAVE_TYPE(IOAPIC, 4, struct hvm_hw_vioapic);
+
+
+/*
+ * LAPIC
+ */
+
+struct hvm_hw_lapic {
+    uint64_t             apic_base_msr;
+    uint32_t             disabled; /* VLAPIC_xx_DISABLED */
+    uint32_t             timer_divisor;
+};
+
+DECLARE_HVM_SAVE_TYPE(LAPIC, 5, struct hvm_hw_lapic);
+
+struct hvm_hw_lapic_regs {
+    /* A 4k page of register state */
+    uint8_t  data[0x400];
+};
+
+DECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 6, struct hvm_hw_lapic_regs);
+
+
+/*
+ * IRQs
+ */
+
+struct hvm_hw_pci_irqs {
     /*
      * Virtual interrupt wires for a single PCI bus.
      * Indexed by: device*4 + INTx#.
      */
-    DECLARE_BITMAP(pci_intx, 32*4);
-
+    union {
+        DECLARE_BITMAP(i, 32*4);
+        uint64_t pad[2];
+    };
+};
+
+DECLARE_HVM_SAVE_TYPE(PCI_IRQ, 7, struct hvm_hw_pci_irqs);
+
+struct hvm_hw_isa_irqs {
     /*
      * Virtual interrupt wires for ISA devices.
      * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
      */
-    DECLARE_BITMAP(isa_irq, 16);
-
-    /* Virtual interrupt and via-link for paravirtual platform driver. */
-    uint32_t callback_via_asserted;
     union {
-        enum {
-            HVMIRQ_callback_none,
-            HVMIRQ_callback_gsi,
-            HVMIRQ_callback_pci_intx
-        } callback_via_type;
-        uint32_t pad; /* So the next field will be aligned */
+        DECLARE_BITMAP(i, 16);
+        uint64_t pad[1];
     };
-    union {
-        uint32_t gsi;
-        struct { uint8_t dev, intx; } pci;
-    } callback_via;
-
+};
+
+DECLARE_HVM_SAVE_TYPE(ISA_IRQ, 8, struct hvm_hw_isa_irqs);
+
+struct hvm_hw_pci_link {
     /*
      * PCI-ISA interrupt router.
      * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
      * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
      * The router provides a programmable mapping from each link to a GSI.
      */
-    u8 pci_link_route[4];
-
-    /* Number of INTx wires asserting each PCI-ISA link. */
-    u8 pci_link_assert_count[4];
-
-    /*
-     * Number of wires asserting each GSI.
-     * 
-     * GSIs 0-15 are the ISA IRQs. ISA devices map directly into this space
-     * except ISA IRQ 0, which is connected to GSI 2.
-     * PCI links map into this space via the PCI-ISA bridge.
-     * 
-     * GSIs 16+ are used only be PCI devices. The mapping from PCI device to
-     * GSI is as follows: ((device*4 + device/8 + INTx#) & 31) + 16
-     */
-    u8 gsi_assert_count[VIOAPIC_NUM_PINS];
-
-    /*
-     * GSIs map onto PIC/IO-APIC in the usual way:
-     *  0-7:  Master 8259 PIC, IO-APIC pins 0-7
-     *  8-15: Slave  8259 PIC, IO-APIC pins 8-15
-     *  16+ : IO-APIC pins 16+
-     */
-
-    /* Last VCPU that was delivered a LowestPrio interrupt. */
-    u8 round_robin_prev_vcpu;
-};
-
-DECLARE_HVM_SAVE_TYPE(IRQ, 6, struct hvm_hw_irq);
-
-/*
- * LAPIC
- */
-
-struct hvm_hw_lapic {
-    uint64_t             apic_base_msr;
-    uint32_t             disabled; /* VLAPIC_xx_DISABLED */
-    uint32_t             timer_divisor;
-};
-
-DECLARE_HVM_SAVE_TYPE(LAPIC, 7, struct hvm_hw_lapic);
-
-struct hvm_hw_lapic_regs {
-    /* A 4k page of register state */
-    uint8_t  data[0x400];
-};
-
-DECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 8, struct hvm_hw_lapic_regs);
+    u8 route[4];
+};
+
+DECLARE_HVM_SAVE_TYPE(PCI_LINK, 9, struct hvm_hw_pci_link);
+
+
+/* 
+ *  PIT
+ */
+
+struct hvm_hw_pit {
+    struct hvm_hw_pit_channel {
+        uint32_t count; /* can be 65536 */
+        uint16_t latched_count;
+        uint8_t count_latched;
+        uint8_t status_latched;
+        uint8_t status;
+        uint8_t read_state;
+        uint8_t write_state;
+        uint8_t write_latch;
+        uint8_t rw_mode;
+        uint8_t mode;
+        uint8_t bcd; /* not supported */
+        uint8_t gate; /* timer start */
+    } channels[3];  /* 3 x 16 bytes */
+    uint32_t speaker_data_on;
+};
+
+DECLARE_HVM_SAVE_TYPE(PIT, 10, struct hvm_hw_pit);
 
 
 /* 
@@ -378,7 +349,7 @@ struct hvm_hw_rtc {
     uint8_t cmos_index;
 };
 
-DECLARE_HVM_SAVE_TYPE(RTC, 9, struct hvm_hw_rtc);
+DECLARE_HVM_SAVE_TYPE(RTC, 11, struct hvm_hw_rtc);
 
 
 /*
@@ -408,13 +379,13 @@ struct hvm_hw_hpet {
     uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */
 };
 
-DECLARE_HVM_SAVE_TYPE(HPET, 10, struct hvm_hw_hpet);
+DECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet);
 
 
 /* 
  * Largest type-code in use
  */
-#define HVM_SAVE_CODE_MAX 10
+#define HVM_SAVE_CODE_MAX 12
 
 
 /* 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.