WARNING - OLD ARCHIVES

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

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 09 Feb 2007 09:40:57 -0800
Delivery-date: Fri, 09 Feb 2007 10:36:45 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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