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] Merge (only) xen-ia64-unstable with latest xen-unstable

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Merge (only) xen-ia64-unstable with latest xen-unstable
From: Xen patchbot -unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 15 Sep 2005 07:48:27 +0000
Delivery-date: Thu, 15 Sep 2005 07:56:13 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
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 djm@xxxxxxxxxxxxxxx
# Node ID b2f4823b6ff09017e21c0d44f73c58118f50ea46
# Parent  10b1d30d3f66beac5a8275d108461da558c38d1d
# Parent  ec4a3f2d060e1dcc137cca136309ca67d46fbb85
Merge (only) xen-ia64-unstable with latest xen-unstable

diff -r 10b1d30d3f66 -r b2f4823b6ff0 .hgignore
--- a/.hgignore Thu Sep  8 15:18:40 2005
+++ b/.hgignore Fri Sep  9 16:30:54 2005
@@ -82,6 +82,7 @@
 ^tools/blktap/parallax/vdi_validate$
 ^tools/blktap/parallax/parallax$
 ^tools/blktap/parallax/blockstored$
+^tools/blktap/ublkback/ublkback$
 ^tools/blktap/xen/.*$
 ^tools/check/\..*$
 ^tools/cmdline/.*$
@@ -141,24 +142,28 @@
 ^tools/vnet/vnet-module/\.tmp_versions/.*$
 ^tools/vnet/vnet-module/vnet_module\.mod\..*$
 ^tools/vnetd/vnetd$
+^tools/vtpm/vtpm*
+^tools/vtpm/tpm_emulator-*
+^tools/vtpm_manager/manager/vtpm_managerd
 ^tools/web-shutdown\.tap$
 ^tools/x2d2/minixend$
-^tools/xcs/xcs$
-^tools/xcs/xcsdump$
 ^tools/xcutils/xc_restore$
 ^tools/xcutils/xc_save$
 ^tools/xenstat/xentop/xentop$
 ^tools/xenstore/testsuite/tmp/.*$
 ^tools/xenstore/xen$
+^tools/xenstore/xenbus_dev.h$
 ^tools/xenstore/xenstored$
 ^tools/xenstore/xenstored_test$
+^tools/xenstore/xenstore-read$
+^tools/xenstore/xenstore-rm$
+^tools/xenstore/xenstore-write$
 ^tools/xenstore/xs_dom0_test$
 ^tools/xenstore/xs_random$
 ^tools/xenstore/xs_stress$
 ^tools/xenstore/xs_test$
 ^tools/xenstore/xs_watch_stress$
 ^tools/xentrace/xentrace$
-^tools/xfrd/xfrd$
 ^xen/BLOG$
 ^xen/TAGS$
 ^xen/arch/x86/asm-offsets\.s$
diff -r 10b1d30d3f66 -r b2f4823b6ff0 Config.mk
--- a/Config.mk Thu Sep  8 15:18:40 2005
+++ b/Config.mk Fri Sep  9 16:30:54 2005
@@ -48,3 +48,4 @@
 # Optional components
 XENSTAT_XENTOP ?= y
 
+VTPM_TOOLS ?= n
diff -r 10b1d30d3f66 -r b2f4823b6ff0 Makefile
--- a/Makefile  Thu Sep  8 15:18:40 2005
+++ b/Makefile  Fri Sep  9 16:30:54 2005
@@ -35,11 +35,11 @@
 export pae=y
 endif
 
-.PHONY:        all dist install xen tools kernels docs world clean mkpatches 
mrproper
+.PHONY:        all dist install xen kernels tools docs world clean mkpatches 
mrproper
 .PHONY:        kbuild kdelete kclean
 
 # build and install everything into the standard system directories
-install: install-xen install-tools install-kernels install-docs
+install: install-xen install-kernels install-tools install-docs
 
 build: kernels
        $(MAKE) -C xen build
@@ -47,7 +47,7 @@
        $(MAKE) -C docs build
 
 # build and install everything into local dist directory
-dist: xen tools kernels docs
+dist: xen kernels tools docs
        $(INSTALL_DIR) $(DISTDIR)/check
        $(INSTALL_DATA) ./COPYING $(DISTDIR)
        $(INSTALL_DATA) ./README $(DISTDIR)
@@ -178,6 +178,8 @@
        rm -rf $(D)/usr/share/man/man1/xen*
        rm -rf $(D)/usr/share/man/man8/xen*
        rm -rf $(D)/usr/lib/xen
+       rm -rf $(D)/etc/hotplug.d/xen-backend
+       rm -rf $(D)/etc/hotplug/xen-backend.agent
 
 # Legacy targets for compatibility
 linux24:
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/Makefile
--- a/extras/mini-os/Makefile   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/Makefile   Fri Sep  9 16:30:54 2005
@@ -31,16 +31,18 @@
 OBJS := $(TARGET_ARCH).o
 OBJS += $(patsubst %.c,%.o,$(wildcard *.c))
 OBJS += $(patsubst %.c,%.o,$(wildcard lib/*.c))
-
+OBJS += $(patsubst %.c,%.o,$(wildcard xenbus/*.c))
+                                                                               
   
 HDRS := $(wildcard include/*.h)
 HDRS += $(wildcard include/xen/*.h)
 
 default: $(TARGET)
 
-xen-public:
+links:
        [ -e include/xen ] || ln -sf ../../../xen/include/public include/xen
-
-$(TARGET): xen-public $(OBJS)
+       [ -e xenbus/xenstored.h ] || ln -sf ../../../tools/xenstore/xenstored.h 
xenbus/xenstored.h
+       
+$(TARGET): links $(OBJS)
        $(LD) -N -T minios-$(TARGET_ARCH).lds $(OBJS) -o $@.elf
        gzip -f -9 -c $@.elf >$@.gz
 
@@ -55,3 +57,4 @@
 %.o: %.S $(HDRS) Makefile
        $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $@
 
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/README
--- a/extras/mini-os/README     Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/README     Fri Sep  9 16:30:54 2005
@@ -23,13 +23,8 @@
 
 - to build it just type make.
 
-- copy image.final somewhere where dom0 can access it
+- to start it do the following in domain0 (assuming xend is running)
+  # xm create domain_config
 
-- in dom0
-  # xi_create 16000 test
-    <domid>
-  # xi_build <domid> image.final 0
-  # xi_start <domid>
-
-this prints out a bunch of stuff and then every 1000 timer interrupts the
-system time.
+this starts the kernel and prints out a bunch of stuff and then every
+1000 timer interrupts the system time.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/events.c
--- a/extras/mini-os/events.c   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/events.c   Fri Sep  9 16:30:54 2005
@@ -17,13 +17,13 @@
  */
 
 #include <os.h>
+#include <mm.h>
 #include <hypervisor.h>
 #include <events.h>
 #include <lib.h>
 
-#include <xen/event_channel.h>
 static ev_action_t ev_actions[NR_EVS];
-void default_handler(u32 port, struct pt_regs *regs);
+void default_handler(int port, struct pt_regs *regs);
 
 
 /*
@@ -32,7 +32,6 @@
 int do_event(u32 port, struct pt_regs *regs)
 {
     ev_action_t  *action;
-
     if (port >= NR_EVS) {
         printk("Port number too large: %d\n", port);
         return 0;
@@ -57,11 +56,23 @@
 
 }
 
+void bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *) )
+{
+       if(ev_actions[port].handler)
+        printk("WARN: Handler for port %d already registered, replacing\n",
+                               port);
+
+       ev_actions[port].handler = handler;
+       ev_actions[port].status &= ~EVS_DISABLED;         
+ 
+       /* Finally unmask the port */
+       unmask_evtchn(port);
+}
+
 int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) )
 {
        evtchn_op_t op;
        int ret = 0;
-       u32 port;
 
        /* Try to bind the virq to a port */
        op.cmd = EVTCHNOP_bind_virq;
@@ -73,21 +84,12 @@
                printk("Failed to bind virtual IRQ %d\n", virq);
                goto out;
     }
-
-    port = op.u.bind_virq.port;
-       
-       if(ev_actions[port].handler)
-        printk("WARN: Handler for port %d already registered, replacing\n",
-                               port);
-
-       ev_actions[port].handler = handler;
-       ev_actions[port].status &= ~EVS_DISABLED;
-       
-       /* Finally unmask the port */
-       unmask_evtchn(port);
+    bind_evtchn(op.u.bind_virq.port, handler); 
 out:
        return ret;
 }
+
+
 
 /*
  * Initially all events are without a handler and disabled
@@ -100,10 +102,10 @@
     for ( i = 0; i < NR_EVS; i++ )
     {
         ev_actions[i].status  = EVS_DISABLED;
-        ev_actions[i].handler = NULL;
+        ev_actions[i].handler = default_handler;
     }
 }
 
-void default_handler(u32 port, struct pt_regs *regs) {
+void default_handler(int port, struct pt_regs *regs) {
     printk("[Port %d] - event received\n", port);
 }
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/events.h
--- a/extras/mini-os/include/events.h   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/events.h   Fri Sep  9 16:30:54 2005
@@ -20,6 +20,7 @@
 #define _EVENTS_H_
 
 #include<traps.h>
+#include <xen/event_channel.h>
 
 #define NR_EVS 1024
 
@@ -39,6 +40,16 @@
 /* prototypes */
 int do_event(u32 port, struct pt_regs *regs);
 int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) );
+void bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *) );
 void init_events(void);
 
+static inline int notify_via_evtchn(int port)
+{
+    evtchn_op_t op;
+    op.cmd = EVTCHNOP_send;
+    op.u.send.local_port = port;
+    return HYPERVISOR_event_channel_op(&op);
+}
+
+
 #endif /* _EVENTS_H_ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/hypervisor.h
--- a/extras/mini-os/include/hypervisor.h       Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/hypervisor.h       Fri Sep  9 16:30:54 2005
@@ -13,7 +13,6 @@
 #define _HYPERVISOR_H_
 
 #include <types.h>
-
 #include <xen/xen.h>
 #include <xen/io/domain_controller.h>
 
@@ -40,48 +39,26 @@
 /*
  * Assembler stubs for hyper-calls.
  */
-
-#ifdef __i386__
-#define _a1 "b"
-#define _a2 "c"
-#define _a3 "d"
-#define _a4 "S"
-#else
-#define _a1 "D"
-#define _a2 "S"
-#define _a3 "d"
-#define _a4 "b"
-#endif
-
-static __inline__ int HYPERVISOR_event_channel_op(
-    void *op)
+#if defined(__i386__)
+static inline int
+HYPERVISOR_set_trap_table(
+    trap_info_t *table)
 {
     int ret;
     unsigned long ignore;
+
     __asm__ __volatile__ (
         TRAP_INSTR
         : "=a" (ret), "=b" (ignore)
-       : "0" (__HYPERVISOR_event_channel_op), "1" (op)
-       : "memory" );
-
-    return ret;
-}
-
-static __inline__ int HYPERVISOR_set_trap_table(trap_info_t *table)
-{
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret) : "0" (__HYPERVISOR_set_trap_table),
-        _a1 (table) : "memory" );
-
-    return ret;
-}
-
-static __inline__ int HYPERVISOR_mmu_update(mmu_update_t *req, 
-                                            int count, 
-                                            int *success_count, 
-                                            domid_t domid)
+       : "0" (__HYPERVISOR_set_trap_table), "1" (table)
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_mmu_update(
+    mmu_update_t *req, int count, int *success_count, domid_t domid)
 {
     int ret;
     unsigned long ign1, ign2, ign3, ign4;
@@ -89,18 +66,16 @@
     __asm__ __volatile__ (
         TRAP_INSTR
         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
-        : "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
-          "3" (success_count), "4" (domid)
-        : "memory" );
-
-    return ret;
-}
-
-
-static __inline__ int HYPERVISOR_mmuext_op(struct mmuext_op *op, 
-                                           int count, 
-                                           int *success_count, 
-                                           domid_t domid)
+       : "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
+        "3" (success_count), "4" (domid)
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_mmuext_op(
+    struct mmuext_op *op, int count, int *success_count, domid_t domid)
 {
     int ret;
     unsigned long ign1, ign2, ign3, ign4;
@@ -108,70 +83,65 @@
     __asm__ __volatile__ (
         TRAP_INSTR
         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
-        : "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count),
-          "3" (success_count), "4" (domid)
-        : "memory" );
-
-    return ret;
-}
-
-
-
-static __inline__ int HYPERVISOR_set_gdt(unsigned long *frame_list, int 
entries)
-{
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret) : "0" (__HYPERVISOR_set_gdt), 
-        _a1 (frame_list), _a2 (entries) : "memory" );
-
-
-    return ret;
-}
-
-static __inline__ int HYPERVISOR_stack_switch(unsigned long ss, unsigned long 
esp)
-{
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret) : "0" (__HYPERVISOR_stack_switch),
-        _a1 (ss), _a2 (esp) : "memory" );
-
-    return ret;
-}
-
-#ifdef __i386__
-static __inline__ int HYPERVISOR_set_callbacks(
+       : "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count),
+        "3" (success_count), "4" (domid)
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_set_gdt(
+    unsigned long *frame_list, int entries)
+{
+    int ret;
+    unsigned long ign1, ign2;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1), "=c" (ign2)
+       : "0" (__HYPERVISOR_set_gdt), "1" (frame_list), "2" (entries)
+       : "memory" );
+
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_stack_switch(
+    unsigned long ss, unsigned long esp)
+{
+    int ret;
+    unsigned long ign1, ign2;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1), "=c" (ign2)
+       : "0" (__HYPERVISOR_stack_switch), "1" (ss), "2" (esp)
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_set_callbacks(
     unsigned long event_selector, unsigned long event_address,
     unsigned long failsafe_selector, unsigned long failsafe_address)
 {
     int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret) : "0" (__HYPERVISOR_set_callbacks),
-        _a1 (event_selector), _a2 (event_address), 
-        _a3 (failsafe_selector), _a4 (failsafe_address) : "memory" );
-
-    return ret;
-}
-#else
-static __inline__ int HYPERVISOR_set_callbacks(
-    unsigned long event_address,
-    unsigned long failsafe_address,
-    unsigned long syscall_address)
-{
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret) : "0" (__HYPERVISOR_set_callbacks),
-        _a1 (event_address), _a2 (failsafe_address), 
-        _a3 (syscall_address) : "memory" );
-
-    return ret;
-}
-#endif
-
-static __inline__ int
+    unsigned long ign1, ign2, ign3, ign4;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+       : "0" (__HYPERVISOR_set_callbacks), "1" (event_selector),
+         "2" (event_address), "3" (failsafe_selector), "4" (failsafe_address)
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
 HYPERVISOR_fpu_taskswitch(
     int set)
 {
@@ -187,67 +157,106 @@
     return ret;
 }
 
-static __inline__ int HYPERVISOR_yield(void)
-{
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret) : "0" (__HYPERVISOR_sched_op),
-        _a1 (SCHEDOP_yield) : "memory" );
-
-    return ret;
-}
-
-static __inline__ int HYPERVISOR_block(void)
-{
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret) : "0" (__HYPERVISOR_sched_op),
-        _a1 (SCHEDOP_block) : "memory" );
-
-    return ret;
-}
-
-static __inline__ int HYPERVISOR_shutdown(void)
-{
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret) : "0" (__HYPERVISOR_sched_op),
-        _a1 (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
-        : "memory" );
-
-    return ret;
-}
-
-static __inline__ int HYPERVISOR_reboot(void)
-{
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret) : "0" (__HYPERVISOR_sched_op),
-        _a1 (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
-        : "memory" );
-
-    return ret;
-}
-
-static __inline__ int HYPERVISOR_suspend(unsigned long srec)
-{
-    int ret;
+static inline int
+HYPERVISOR_yield(
+    void)
+{
+    int ret;
+    unsigned long ign;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign)
+       : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield)
+       : "memory", "ecx" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_block(
+    void)
+{
+    int ret;
+    unsigned long ign1;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1)
+       : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block)
+       : "memory", "ecx" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_shutdown(
+    void)
+{
+    int ret;
+    unsigned long ign1;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1)
+       : "0" (__HYPERVISOR_sched_op),
+         "1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
+        : "memory", "ecx" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_reboot(
+    void)
+{
+    int ret;
+    unsigned long ign1;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1)
+       : "0" (__HYPERVISOR_sched_op),
+         "1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
+        : "memory", "ecx" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_suspend(
+    unsigned long srec)
+{
+    int ret;
+    unsigned long ign1, ign2;
+
     /* NB. On suspend, control software expects a suspend record in %esi. */
     __asm__ __volatile__ (
         TRAP_INSTR
-        : "=a" (ret) : "0" (__HYPERVISOR_sched_op),
-        _a1 (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)), 
-        "S" (srec) : "memory" );
-
-    return ret;
-}
-
-#ifdef __i386__
-static __inline__ long HYPERVISOR_set_timer_op( u64 timeout )
+        : "=a" (ret), "=b" (ign1), "=S" (ign2)
+       : "0" (__HYPERVISOR_sched_op),
+        "b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)), 
+        "S" (srec) : "memory", "ecx");
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_crash(
+    void)
+{
+    int ret;
+    unsigned long ign1;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1)
+       : "0" (__HYPERVISOR_sched_op),
+         "1" (SCHEDOP_shutdown | (SHUTDOWN_crash << SCHEDOP_reasonshift))
+        : "memory", "ecx" );
+
+    return ret;
+}
+
+static inline long
+HYPERVISOR_set_timer_op(
+    u64 timeout)
 {
     int ret;
     unsigned long timeout_hi = (unsigned long)(timeout>>32);
@@ -262,8 +271,516 @@
 
     return ret;
 }
+
+#if 0
+static inline int
+HYPERVISOR_dom0_op(
+    dom0_op_t *dom0_op)
+{
+    int ret;
+    unsigned long ign1;
+
+    dom0_op->interface_version = DOM0_INTERFACE_VERSION;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1)
+       : "0" (__HYPERVISOR_dom0_op), "1" (dom0_op)
+       : "memory");
+
+    return ret;
+}
+#endif
+
+static inline int
+HYPERVISOR_set_debugreg(
+    int reg, unsigned long value)
+{
+    int ret;
+    unsigned long ign1, ign2;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1), "=c" (ign2)
+       : "0" (__HYPERVISOR_set_debugreg), "1" (reg), "2" (value)
+       : "memory" );
+
+    return ret;
+}
+
+static inline unsigned long
+HYPERVISOR_get_debugreg(
+    int reg)
+{
+    unsigned long ret;
+    unsigned long ign;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign)
+       : "0" (__HYPERVISOR_get_debugreg), "1" (reg)
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_update_descriptor(
+    u64 ma, u64 desc)
+{
+    int ret;
+    unsigned long ign1, ign2, ign3, ign4;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+       : "0" (__HYPERVISOR_update_descriptor),
+         "1" ((unsigned long)ma), "2" ((unsigned long)(ma>>32)),
+         "3" ((unsigned long)desc), "4" ((unsigned long)(desc>>32))
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_dom_mem_op(
+    unsigned int op, unsigned long *extent_list,
+    unsigned long nr_extents, unsigned int extent_order)
+{
+    int ret;
+    unsigned long ign1, ign2, ign3, ign4, ign5;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
+         "=D" (ign5)
+       : "0" (__HYPERVISOR_dom_mem_op), "1" (op), "2" (extent_list),
+         "3" (nr_extents), "4" (extent_order), "5" (DOMID_SELF)
+        : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_multicall(
+    void *call_list, int nr_calls)
+{
+    int ret;
+    unsigned long ign1, ign2;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1), "=c" (ign2)
+       : "0" (__HYPERVISOR_multicall), "1" (call_list), "2" (nr_calls)
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_update_va_mapping(
+    unsigned long va, pte_t new_val, unsigned long flags)
+{
+    int ret;
+    unsigned long ign1, ign2, ign3, ign4;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+       : "0" (__HYPERVISOR_update_va_mapping), 
+          "1" (va), "2" ((new_val).pte_low),
+#ifdef CONFIG_X86_PAE
+         "3" ((new_val).pte_high),
 #else
-static __inline__ long HYPERVISOR_set_timer_op( u64 timeout )
+         "3" (0),
+#endif
+         "4" (flags)
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_event_channel_op(
+    void *op)
+{
+    int ret;
+    unsigned long ignore;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ignore)
+       : "0" (__HYPERVISOR_event_channel_op), "1" (op)
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_xen_version(
+    int cmd)
+{
+    int ret;
+    unsigned long ignore;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ignore)
+       : "0" (__HYPERVISOR_xen_version), "1" (cmd)
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_console_io(
+    int cmd, int count, char *str)
+{
+    int ret;
+    unsigned long ign1, ign2, ign3;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
+       : "0" (__HYPERVISOR_console_io), "1" (cmd), "2" (count), "3" (str)
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_physdev_op(
+    void *physdev_op)
+{
+    int ret;
+    unsigned long ign;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign)
+       : "0" (__HYPERVISOR_physdev_op), "1" (physdev_op)
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_grant_table_op(
+    unsigned int cmd, void *uop, unsigned int count)
+{
+    int ret;
+    unsigned long ign1, ign2, ign3;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
+       : "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (uop), "3" (count)
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_update_va_mapping_otherdomain(
+    unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+{
+    int ret;
+    unsigned long ign1, ign2, ign3, ign4, ign5;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3),
+         "=S" (ign4), "=D" (ign5)
+       : "0" (__HYPERVISOR_update_va_mapping_otherdomain),
+          "1" (va), "2" ((new_val).pte_low),
+#ifdef CONFIG_X86_PAE
+         "3" ((new_val).pte_high),
+#else
+         "3" (0),
+#endif
+         "4" (flags), "5" (domid) :
+        "memory" );
+    
+    return ret;
+}
+
+static inline int
+HYPERVISOR_vm_assist(
+    unsigned int cmd, unsigned int type)
+{
+    int ret;
+    unsigned long ign1, ign2;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1), "=c" (ign2)
+       : "0" (__HYPERVISOR_vm_assist), "1" (cmd), "2" (type)
+       : "memory" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_boot_vcpu(
+    unsigned long vcpu, vcpu_guest_context_t *ctxt)
+{
+    int ret;
+    unsigned long ign1, ign2;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1), "=c" (ign2)
+       : "0" (__HYPERVISOR_boot_vcpu), "1" (vcpu), "2" (ctxt)
+       : "memory");
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_vcpu_down(
+    int vcpu)
+{
+    int ret;
+    unsigned long ign1;
+    /* Yes, I really do want to clobber edx here: when we resume a
+       vcpu after unpickling a multi-processor domain, it returns
+       here, but clobbers all of the call clobbered registers. */
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1)
+       : "0" (__HYPERVISOR_sched_op),
+         "1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift))
+        : "memory", "ecx", "edx" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_vcpu_up(
+    int vcpu)
+{
+    int ret;
+    unsigned long ign1;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1)
+       : "0" (__HYPERVISOR_sched_op),
+         "1" (SCHEDOP_vcpu_up | (vcpu << SCHEDOP_vcpushift))
+        : "memory", "ecx" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_vcpu_pickle(
+    int vcpu, vcpu_guest_context_t *ctxt)
+{
+    int ret;
+    unsigned long ign1, ign2;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret), "=b" (ign1), "=c" (ign2)
+       : "0" (__HYPERVISOR_sched_op),
+         "1" (SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)),
+         "2" (ctxt)
+        : "memory" );
+
+    return ret;
+}
+#elif defined(__x86_64__)
+
+#define __syscall_clobber "r11","rcx","memory"
+
+/*
+ * Assembler stubs for hyper-calls.
+ */
+static inline int
+HYPERVISOR_set_trap_table(
+    trap_info_t *table)
+{
+    int ret;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret)
+       : "0" ((unsigned long)__HYPERVISOR_set_trap_table), "D" (table)
+       : __syscall_clobber );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_mmu_update(
+    mmu_update_t *req, int count, int *success_count, domid_t domid)
+{
+    int ret;
+
+    __asm__ __volatile__ (
+        "movq %5, %%r10;" TRAP_INSTR
+        : "=a" (ret)
+       : "0" ((unsigned long)__HYPERVISOR_mmu_update), "D" (req), "S" 
((long)count),
+         "d" (success_count), "g" ((unsigned long)domid)
+       : __syscall_clobber, "r10" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_mmuext_op(
+    struct mmuext_op *op, int count, int *success_count, domid_t domid)
+{
+    int ret;
+
+    __asm__ __volatile__ (
+        "movq %5, %%r10;" TRAP_INSTR
+        : "=a" (ret)
+        : "0" (__HYPERVISOR_mmuext_op), "D" (op), "S" ((long)count), 
+          "d" (success_count), "g" ((unsigned long)domid)
+        : __syscall_clobber, "r10" );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_set_gdt(
+    unsigned long *frame_list, int entries)
+{
+    int ret;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret)
+       : "0" ((unsigned long)__HYPERVISOR_set_gdt), "D" (frame_list), "S" 
((long)entries)
+       : __syscall_clobber );
+
+
+    return ret;
+}
+static inline int
+HYPERVISOR_stack_switch(
+    unsigned long ss, unsigned long esp)
+{
+    int ret;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret)
+       : "0" ((unsigned long)__HYPERVISOR_stack_switch), "D" (ss), "S" (esp)
+       : __syscall_clobber );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_set_callbacks(
+    unsigned long event_address, unsigned long failsafe_address, 
+    unsigned long syscall_address)
+{
+    int ret;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret)
+       : "0" ((unsigned long)__HYPERVISOR_set_callbacks), "D" (event_address),
+         "S" (failsafe_address), "d" (syscall_address)
+       : __syscall_clobber );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_fpu_taskswitch(
+    int set)
+{
+    int ret;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret) : "0" ((unsigned long)__HYPERVISOR_fpu_taskswitch),
+          "D" ((unsigned long) set) : __syscall_clobber );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_yield(
+    void)
+{
+    int ret;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret)
+       : "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned 
long)SCHEDOP_yield)
+       : __syscall_clobber );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_block(
+    void)
+{
+    int ret;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret)
+       : "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned 
long)SCHEDOP_block)
+       : __syscall_clobber );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_shutdown(
+    void)
+{
+    int ret;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret)
+       : "0" ((unsigned long)__HYPERVISOR_sched_op),
+         "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_poweroff << 
SCHEDOP_reasonshift)))
+       : __syscall_clobber );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_reboot(
+    void)
+{
+    int ret;
+
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret)
+       : "0" ((unsigned long)__HYPERVISOR_sched_op),
+         "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_reboot << 
SCHEDOP_reasonshift)))
+       : __syscall_clobber );
+
+    return ret;
+}
+
+static inline int
+HYPERVISOR_suspend(
+    unsigned long srec)
+{
+    int ret;
+
+    /* NB. On suspend, control software expects a suspend record in %esi. */
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret)
+       : "0" ((unsigned long)__HYPERVISOR_sched_op),
+        "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_suspend << 
SCHEDOP_reasonshift))), 
+        "S" (srec)
+       : __syscall_clobber );
+
+    return ret;
+}
+
+/*
+ * We can have the timeout value in a single argument for the hypercall, but
+ * that will break the common code. 
+ */
+static inline long
+HYPERVISOR_set_timer_op(
+    u64 timeout)
 {
     int ret;
 
@@ -329,7 +846,7 @@
     int ret;
     __asm__ __volatile__ (
         TRAP_INSTR
-        : "=a" (ret) : "0" (__HYPERVISOR_dom_mem_op),
+        : "=a" (ret) : "0" (__HYPERVISOR_memory_op),
         _a1 (dom_mem_op) : "memory" );
 
     return ret;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/lib.h
--- a/extras/mini-os/include/lib.h      Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/lib.h      Fri Sep  9 16:30:54 2005
@@ -60,10 +60,22 @@
 /* printing */
 #define printk  printf
 #define kprintf printf
-int printf(const char *fmt, ...);
-int vprintf(const char *fmt, va_list ap);
-int sprintf(char *buf, const char *cfmt, ...);
-int vsprintf(char *buf, const char *cfmt, va_list ap);
+#define _p(_x) ((void *)(unsigned long)(_x))
+void printf(const char *fmt, ...);
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
+int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
+int snprintf(char * buf, size_t size, const char *fmt, ...);
+int scnprintf(char * buf, size_t size, const char *fmt, ...);
+int vsprintf(char *buf, const char *fmt, va_list args);
+int sprintf(char * buf, const char *fmt, ...);
+int vsscanf(const char * buf, const char * fmt, va_list args);
+int sscanf(const char * buf, const char * fmt, ...);
+
+long simple_strtol(const char *cp,char **endp,unsigned int base);
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base);
+long long simple_strtoll(const char *cp,char **endp,unsigned int base);
+unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int 
base);
+
 
 /* string and memory manipulation */
 int    memcmp(const void *cs, const void *ct, size_t count);
@@ -77,6 +89,16 @@
 size_t strlen(const char *s);
 char  *strchr(const char *s, int c);
 char  *strstr(const char *s1, const char *s2);
+char * strcat(char * dest, const char * src);
+
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+struct kvec {
+    void *iov_base;
+    size_t iov_len;
+};
+
 
 
 #endif /* _LIB_H_ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/mm.h
--- a/extras/mini-os/include/mm.h       Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/mm.h       Fri Sep  9 16:30:54 2005
@@ -24,6 +24,15 @@
 
 #ifndef _MM_H_
 #define _MM_H_
+
+#ifdef __i386__
+#include <xen/arch-x86_32.h>
+#endif
+
+#ifdef __x86_64__
+#include <xen/arch-x86_64.h>
+#endif
+
 
 #ifdef __x86_64__
 
@@ -56,6 +65,8 @@
 
 #define L1_PAGETABLE_ENTRIES    1024
 #define L2_PAGETABLE_ENTRIES    1024
+
+#elif defined(__x86_64__)
 #endif
 
 /* Given a virtual address, get an entry offset into a page table. */
@@ -97,13 +108,15 @@
 
 extern unsigned long *phys_to_machine_mapping;
 #define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
-#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
 static __inline__ unsigned long phys_to_machine(unsigned long phys)
 {
     unsigned long machine = pfn_to_mfn(phys >> L1_PAGETABLE_SHIFT);
     machine = (machine << L1_PAGETABLE_SHIFT) | (phys & ~PAGE_MASK);
     return machine;
 }
+
+
+#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
 static __inline__ unsigned long machine_to_phys(unsigned long machine)
 {
     unsigned long phys = mfn_to_pfn(machine >> L1_PAGETABLE_SHIFT);
@@ -119,16 +132,15 @@
 
 #define to_phys(x)                 ((unsigned long)(x)-VIRT_START)
 #define to_virt(x)                 ((void *)((unsigned long)(x)+VIRT_START))
-#define __va to_virt
-#define __pa to_phys
 
 #define virt_to_pfn(_virt)         (PFN_DOWN(to_phys(_virt)))
+#define mach_to_virt(_mach)        (to_virt(machine_to_phys(_mach)))
+#define mfn_to_virt(_mfn)          (mach_to_virt(_mfn << PAGE_SHIFT))
 
 void init_mm(void);
 unsigned long alloc_pages(int order);
 #define alloc_page()    alloc_pages(0);
 void free_pages(void *pointer, int order);
-//int is_mfn_mapped(unsigned long mfn);
 
 static __inline__ int get_order(unsigned long size)
 {
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/os.h
--- a/extras/mini-os/include/os.h       Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/os.h       Fri Sep  9 16:30:54 2005
@@ -15,15 +15,16 @@
 #define unlikely(x)  __builtin_expect((x),0)
 
 #define smp_processor_id() 0
-#define preempt_disable() ((void)0)
-#define preempt_enable() ((void)0)
-
-#define force_evtchn_callback() ((void)HYPERVISOR_xen_version(0))
+
 
 #ifndef __ASSEMBLY__
 #include <types.h>
+#include <hypervisor.h>
 #endif
 #include <xen/xen.h>
+
+
+#define force_evtchn_callback() ((void)HYPERVISOR_xen_version(0))
 
 #define __KERNEL_CS  FLAT_KERNEL_CS
 #define __KERNEL_DS  FLAT_KERNEL_DS
@@ -54,8 +55,6 @@
 /* Everything below this point is not included by assembler (.S) files. */
 #ifndef __ASSEMBLY__
 
-#define pt_regs xen_regs
-
 void trap_init(void);
 
 /* 
@@ -69,10 +68,8 @@
 #define __cli()                                                                
\
 do {                                                                   \
        vcpu_info_t *_vcpu;                                             \
-       preempt_disable();                                              \
        _vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
        _vcpu->evtchn_upcall_mask = 1;                                  \
-       preempt_enable_no_resched();                                    \
        barrier();                                                      \
 } while (0)
 
@@ -80,13 +77,11 @@
 do {                                                                   \
        vcpu_info_t *_vcpu;                                             \
        barrier();                                                      \
-       preempt_disable();                                              \
        _vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
        _vcpu->evtchn_upcall_mask = 0;                                  \
        barrier(); /* unmask then check (avoid races) */                \
        if ( unlikely(_vcpu->evtchn_upcall_pending) )                   \
                force_evtchn_callback();                                \
-       preempt_enable();                                               \
 } while (0)
 
 #define __save_flags(x)                                                        
\
@@ -100,15 +95,12 @@
 do {                                                                   \
        vcpu_info_t *_vcpu;                                             \
        barrier();                                                      \
-       preempt_disable();                                              \
        _vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
        if ((_vcpu->evtchn_upcall_mask = (x)) == 0) {                   \
                barrier(); /* unmask then check (avoid races) */        \
                if ( unlikely(_vcpu->evtchn_upcall_pending) )           \
                        force_evtchn_callback();                        \
-               preempt_enable();                                       \
-       } else                                                          \
-               preempt_enable_no_resched();                            \
+       }\
 } while (0)
 
 #define safe_halt()            ((void)0)
@@ -116,11 +108,9 @@
 #define __save_and_cli(x)                                              \
 do {                                                                   \
        vcpu_info_t *_vcpu;                                             \
-       preempt_disable();                                              \
        _vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
        (x) = _vcpu->evtchn_upcall_mask;                                \
        _vcpu->evtchn_upcall_mask = 1;                                  \
-       preempt_enable_no_resched();                                    \
        barrier();                                                      \
 } while (0)
 
@@ -135,6 +125,15 @@
 
 /* This is a barrier for the compiler only, NOT the processor! */
 #define barrier() __asm__ __volatile__("": : :"memory")
+
+#if defined(__i386__)
+#define mb()    __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
+#define rmb()   __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
+#elif defined(__x86_64__)
+#define mb()    __asm__ __volatile__ ("mfence":::"memory")
+#define rmb()   __asm__ __volatile__ ("lfence":::"memory")
+#endif
+
 
 #define LOCK_PREFIX ""
 #define LOCK ""
@@ -147,69 +146,71 @@
 typedef struct { volatile int counter; } atomic_t;
 
 
-#define xchg(ptr,v) \
-        ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
+/************************** i386 *******************************/
+#if defined (__i386__)
+
+#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned 
long)(v),(ptr),sizeof(*(ptr))))
 struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
-                                   int size)
-{
-    switch (size) {
-    case 1:
-        __asm__ __volatile__("xchgb %b0,%1"
-                             :"=q" (x)
-                             :"m" (*__xg(ptr)), "0" (x)
-                             :"memory");
-        break;
-    case 2:
-        __asm__ __volatile__("xchgw %w0,%1"
-                             :"=r" (x)
-                             :"m" (*__xg(ptr)), "0" (x)
-                             :"memory");
-        break;
-    case 4:
-        __asm__ __volatile__("xchgl %0,%1"
-                             :"=r" (x)
-                             :"m" (*__xg(ptr)), "0" (x)
-                             :"memory");
-        break;
-    }
-    return x;
+#define __xg(x) ((struct __xchg_dummy *)(x))
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int 
size)
+{
+       switch (size) {
+               case 1:
+                       __asm__ __volatile__("xchgb %b0,%1"
+                               :"=q" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+               case 2:
+                       __asm__ __volatile__("xchgw %w0,%1"
+                               :"=r" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+               case 4:
+                       __asm__ __volatile__("xchgl %0,%1"
+                               :"=r" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+       }
+       return x;
 }
 
 /**
  * test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to set
+ * @nr: Bit to clear
  * @addr: Address to count from
  *
- * This operation is atomic and cannot be reordered.  
+ * This operation is atomic and cannot be reordered.
+ * It can be reorderdered on other architectures other than x86.
  * It also implies a memory barrier.
  */
-static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
-{
-        int oldbit;
-
-        __asm__ __volatile__( LOCK_PREFIX
-                "btrl %2,%1\n\tsbbl %0,%0"
-                :"=r" (oldbit),"=m" (ADDR)
-                :"Ir" (nr) : "memory");
-        return oldbit;
-}
-
-static __inline__ int constant_test_bit(int nr, const volatile void * addr)
-{
-    return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 
5])) != 0;
-}
-
-static __inline__ int variable_test_bit(int nr, volatile void * addr)
-{
-    int oldbit;
-    
-    __asm__ __volatile__(
-        "btl %2,%1\n\tsbbl %0,%0"
-        :"=r" (oldbit)
-        :"m" (ADDR),"Ir" (nr));
-    return oldbit;
+static inline int test_and_clear_bit(int nr, volatile unsigned long * addr)
+{
+       int oldbit;
+
+       __asm__ __volatile__( LOCK
+               "btrl %2,%1\n\tsbbl %0,%0"
+               :"=r" (oldbit),"=m" (ADDR)
+               :"Ir" (nr) : "memory");
+       return oldbit;
+}
+
+static inline int constant_test_bit(int nr, const volatile unsigned long *addr)
+{
+       return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0;
+}
+
+static inline int variable_test_bit(int nr, const volatile unsigned long * 
addr)
+{
+       int oldbit;
+
+       __asm__ __volatile__(
+               "btl %2,%1\n\tsbbl %0,%0"
+               :"=r" (oldbit)
+               :"m" (ADDR),"Ir" (nr));
+       return oldbit;
 }
 
 #define test_bit(nr,addr) \
@@ -217,6 +218,152 @@
  constant_test_bit((nr),(addr)) : \
  variable_test_bit((nr),(addr)))
 
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered.  See __set_bit()
+ * if you do not require the atomic guarantees.
+ *
+ * Note: there are no guarantees that this function will not be reordered
+ * on non x86 architectures, so if you are writting portable code,
+ * make sure not to rely on its reordering guarantees.
+ *
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static inline void set_bit(int nr, volatile unsigned long * addr)
+{
+       __asm__ __volatile__( LOCK
+               "btsl %1,%0"
+               :"=m" (ADDR)
+               :"Ir" (nr));
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered.  However, it does
+ * not contain a memory barrier, so if it is used for locking purposes,
+ * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * in order to ensure changes are visible on other processors.
+ */
+static inline void clear_bit(int nr, volatile unsigned long * addr)
+{
+       __asm__ __volatile__( LOCK
+               "btrl %1,%0"
+               :"=m" (ADDR)
+               :"Ir" (nr));
+}
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+       __asm__("bsfl %1,%0"
+               :"=r" (word)
+               :"rm" (word));
+       return word;
+}
+
+
+/*
+ * These have to be done with inline assembly: that way the bit-setting
+ * is guaranteed to be atomic. All bit operations return 0 if the bit
+ * was cleared before the operation and != 0 if it was not.
+ *
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ */
+#define ADDR (*(volatile long *) addr)
+
+#define rdtscll(val) \
+     __asm__ __volatile__("rdtsc" : "=A" (val))
+
+
+
+#elif defined(__x86_64__)/* ifdef __i386__ */
+/************************** x86_84 *******************************/
+
+#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned 
long)(v),(ptr),sizeof(*(ptr))))
+#define __xg(x) ((volatile long *)(x))
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int 
size)
+{
+       switch (size) {
+               case 1:
+                       __asm__ __volatile__("xchgb %b0,%1"
+                               :"=q" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+               case 2:
+                       __asm__ __volatile__("xchgw %w0,%1"
+                               :"=r" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+               case 4:
+                       __asm__ __volatile__("xchgl %k0,%1"
+                               :"=r" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+               case 8:
+                       __asm__ __volatile__("xchgq %0,%1"
+                               :"=r" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+       }
+       return x;
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.  
+ * It also implies a memory barrier.
+ */
+static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+{
+       int oldbit;
+
+       __asm__ __volatile__( LOCK_PREFIX
+               "btrl %2,%1\n\tsbbl %0,%0"
+               :"=r" (oldbit),"=m" (ADDR)
+               :"dIr" (nr) : "memory");
+       return oldbit;
+}
+
+static __inline__ int constant_test_bit(int nr, const volatile void * addr)
+{
+       return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr 
>> 5])) != 0;
+}
+
+static __inline__ int variable_test_bit(int nr, volatile const void * addr)
+{
+       int oldbit;
+
+       __asm__ __volatile__(
+               "btl %2,%1\n\tsbbl %0,%0"
+               :"=r" (oldbit)
+               :"m" (ADDR),"dIr" (nr));
+       return oldbit;
+}
+
+#define test_bit(nr,addr) \
+(__builtin_constant_p(nr) ? \
+ constant_test_bit((nr),(addr)) : \
+ variable_test_bit((nr),(addr)))
+
 
 /**
  * set_bit - Atomically set a bit in memory
@@ -230,10 +377,10 @@
  */
 static __inline__ void set_bit(int nr, volatile void * addr)
 {
-        __asm__ __volatile__( LOCK_PREFIX
-                "btsl %1,%0"
-                :"=m" (ADDR)
-                :"Ir" (nr));
+       __asm__ __volatile__( LOCK_PREFIX
+               "btsl %1,%0"
+               :"=m" (ADDR)
+               :"dIr" (nr) : "memory");
 }
 
 /**
@@ -248,40 +395,43 @@
  */
 static __inline__ void clear_bit(int nr, volatile void * addr)
 {
-        __asm__ __volatile__( LOCK_PREFIX
-                "btrl %1,%0"
-                :"=m" (ADDR)
-                :"Ir" (nr));
-}
-
-/**
- * atomic_inc - increment atomic variable
- * @v: pointer of type atomic_t
- * 
- * Atomically increments @v by 1.  Note that the guaranteed
- * useful range of an atomic_t is only 24 bits.
- */ 
-static __inline__ void atomic_inc(atomic_t *v)
-{
-        __asm__ __volatile__(
-                LOCK "incl %0"
-                :"=m" (v->counter)
-                :"m" (v->counter));
-}
-
-
-#define rdtscll(val) \
-     __asm__ __volatile__("rdtsc" : "=A" (val))
-
+       __asm__ __volatile__( LOCK_PREFIX
+               "btrl %1,%0"
+               :"=m" (ADDR)
+               :"dIr" (nr));
+}
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
 static __inline__ unsigned long __ffs(unsigned long word)
 {
-        __asm__("bsfl %1,%0"
-                :"=r" (word)
-                :"rm" (word));
-        return word;
+       __asm__("bsfq %1,%0"
+               :"=r" (word)
+               :"rm" (word));
+       return word;
 }
 
 #define ADDR (*(volatile long *) addr)
+
+#define rdtscll(val) do { \
+     unsigned int __a,__d; \
+     asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
+     (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
+} while(0)
+
+
+#else /* ifdef __x86_64__ */
+#error "Unsupported architecture"
+#endif
+
+
+/********************* common i386 and x86_64  ****************************/
+
+
 
 static __inline__ void synch_set_bit(int nr, volatile void * addr)
 {
@@ -306,6 +456,14 @@
     return oldbit;
 }
 
+static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr)
+{
+    int oldbit;
+    __asm__ __volatile__ (
+        "lock btrl %2,%1\n\tsbbl %0,%0"
+        : "=r" (oldbit), "=m" (ADDR) : "Ir" (nr) : "memory");
+    return oldbit;
+}
 
 static __inline__ int synch_const_test_bit(int nr, const volatile void * addr)
 {
@@ -326,9 +484,8 @@
 (__builtin_constant_p(nr) ? \
  synch_const_test_bit((nr),(addr)) : \
  synch_var_test_bit((nr),(addr)))
-#endif /* !__ASSEMBLY__ */
-
-#define rdtsc(low,high) \
-     __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
-
+
+
+
+#endif /* not assembly */
 #endif /* _OS_H_ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/time.h
--- a/extras/mini-os/include/time.h     Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/time.h     Fri Sep  9 16:30:54 2005
@@ -58,6 +58,6 @@
 s_time_t get_s_time(void);
 s_time_t get_v_time(void);
 void     gettimeofday(struct timeval *tv);
-void     block(u32 millisecs);
+void     block_domain(u32 millisecs);
 
 #endif /* _TIME_H_ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/traps.h
--- a/extras/mini-os/include/traps.h    Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/traps.h    Fri Sep  9 16:30:54 2005
@@ -17,6 +17,7 @@
 #ifndef _TRAPS_H_
 #define _TRAPS_H_
 
+#ifdef __i386__
 struct pt_regs {
        long ebx;
        long ecx;
@@ -34,7 +35,38 @@
        long esp;
        int  xss;
 };
+#elif __x86_64__
 
+struct pt_regs {
+       unsigned long r15;
+       unsigned long r14;
+       unsigned long r13;
+       unsigned long r12;
+       unsigned long rbp;
+       unsigned long rbx;
+/* arguments: non interrupts/non tracing syscalls only save upto here*/
+       unsigned long r11;
+       unsigned long r10;      
+       unsigned long r9;
+       unsigned long r8;
+       unsigned long rax;
+       unsigned long rcx;
+       unsigned long rdx;
+       unsigned long rsi;
+       unsigned long rdi;
+       unsigned long orig_rax;
+/* end of arguments */         
+/* cpu exception frame or undefined */
+       unsigned long rip;
+       unsigned long cs;
+       unsigned long eflags; 
+       unsigned long rsp; 
+       unsigned long ss;
+/* top of stack page */ 
+};
+
+
+#endif
 
 void dump_regs(struct pt_regs *regs);
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/types.h
--- a/extras/mini-os/include/types.h    Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/types.h    Fri Sep  9 16:30:54 2005
@@ -44,11 +44,19 @@
 typedef long long           quad_t;
 typedef unsigned long long  u_quad_t;
 typedef unsigned int        uintptr_t;
+
+typedef struct { unsigned long pte_low; } pte_t;
 #elif defined(__x86_64__)
 typedef long                quad_t;
 typedef unsigned long       u_quad_t;
 typedef unsigned long       uintptr_t;
+
+typedef struct { unsigned long pte; } pte_t;
 #endif
 
+
+
+
+#define INT_MAX         ((int)(~0U>>1))
 #define UINT_MAX            (~0U)
 #endif /* _TYPES_H_ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/kernel.c
--- a/extras/mini-os/kernel.c   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/kernel.c   Fri Sep  9 16:30:54 2005
@@ -33,6 +33,8 @@
 #include <time.h>
 #include <types.h>
 #include <lib.h>
+#include <sched.h>
+#include <xenbus.h>
 
 /*
  * Shared page for communicating with the hypervisor.
@@ -59,10 +61,12 @@
 
 extern char shared_info[PAGE_SIZE];
 
+#define __pte(x) ((pte_t) { (0) } )
+
 static shared_info_t *map_shared_info(unsigned long pa)
 {
     if ( HYPERVISOR_update_va_mapping(
-        (unsigned long)shared_info, pa | 7, UVMF_INVLPG) )
+        (unsigned long)shared_info, __pte(pa | 7), UVMF_INVLPG) )
     {
         printk("Failed to map shared_info!!\n");
         *(int*)0=0;
@@ -77,7 +81,6 @@
 void start_kernel(start_info_t *si)
 {
     static char hello[] = "Bootstrapping...\n";
-    int i;
     (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
 
     /* Copy the start_info struct to a globally-accessible area. */
@@ -96,7 +99,6 @@
         (unsigned long)hypervisor_callback,
         (unsigned long)failsafe_callback, 0);
 #endif
-
     trap_init();
 
     /* ENABLE EVENT DELIVERY. This is disabled at start of day. */
@@ -119,7 +121,6 @@
      * If used for porting another OS, start here to figure out your
      * guest os entry point. Otherwise continue below...
      */
-
     /* init memory management */
     init_mm();
 
@@ -127,15 +128,15 @@
     init_events();
     /* init time and timers */
     init_time();
+    
+    /* init scheduler */
+    init_sched();
 
-    /* do nothing */
-    i = 0;
-    for ( ; ; ) 
-    {      
-//        HYPERVISOR_yield();
-        block(100);
-        i++;
-    }
+    /* init xenbus */
+    xs_init();
+    
+    /* Everything initialised, start idle thread */
+    run_idle_thread();
 }
 
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/lib/printf.c
--- a/extras/mini-os/lib/printf.c       Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/lib/printf.c       Fri Sep  9 16:30:54 2005
@@ -1,20 +1,18 @@
-/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
+/* 
  ****************************************************************************
  * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
  ****************************************************************************
  *
  *        File: printf.c
  *      Author: Rolf Neugebauer (neugebar@xxxxxxxxxxxxx)
- *     Changes: 
+ *     Changes: Grzegorz Milos (gm281@xxxxxxxxx) 
  *              
- *        Date: Aug 2003
+ *        Date: Aug 2003, Aug 2005
  * 
  * Environment: Xen Minimal OS
  * Description: Library functions for printing
  *              (freebsd port, mainly sys/subr_prf.c)
  *
- ****************************************************************************
- * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
  ****************************************************************************
  *
  *-
@@ -60,409 +58,748 @@
 #include <types.h>
 #include <hypervisor.h>
 #include <lib.h>
-
-/****************************************************************************
- * RN: printf family of routines
- * taken mainly from sys/subr_prf.c
- ****************************************************************************/
-char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-#define hex2ascii(hex)  (hex2ascii_data[hex])
-#define NBBY    8               /* number of bits in a byte */
-#define MAXNBUF    (sizeof(quad_t) * NBBY + 1)
-
-static int kvprintf(char const *fmt, void *arg, int radix, va_list ap);
-
-
-int
-printf(const char *fmt, ...)
-{
-       va_list ap;
-       int retval;
-    static char printk_buf[1024];
-
-       va_start(ap, fmt);
-       retval = kvprintf(fmt, printk_buf, 10, ap);
-    printk_buf[retval] = '\0';
-       va_end(ap);
-    (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(printk_buf), 
-                                printk_buf);
-       return retval;
-}
-
-int
-vprintf(const char *fmt, va_list ap)
-{
-       int retval;
-    static char printk_buf[1024];
-       retval = kvprintf(fmt, printk_buf, 10, ap);
-    printk_buf[retval] = '\0';
-    (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(printk_buf),
-                                printk_buf);
-       return retval;
-}
-
-int
-sprintf(char *buf, const char *cfmt, ...)
-{
-       int retval;
-       va_list ap;
-
-       va_start(ap, cfmt);
-       retval = kvprintf(cfmt, (void *)buf, 10, ap);
-       buf[retval] = '\0';
-       va_end(ap);
-       return retval;
-}
-
-int
-vsprintf(char *buf, const char *cfmt, va_list ap)
-{
-       int retval;
-
-       retval = kvprintf(cfmt, (void *)buf, 10, ap);
-       buf[retval] = '\0';
-       return retval;
-}
-
-
-/*
- * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
- * order; return an optional length and a pointer to the last character
- * written in the buffer (i.e., the first character of the string).
- * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
- */
-static char *
-ksprintn(char *nbuf, u_long ul, int base, int *lenp)
-{
-       char *p;
-
-       p = nbuf;
-       *p = '\0';
-       do {
-               *++p = hex2ascii(ul % base);
-       } while (ul /= base);
-       if (lenp)
-               *lenp = p - nbuf;
-       return (p);
-}
-/* ksprintn, but for a quad_t. */
-static char *
-ksprintqn(char *nbuf, u_quad_t uq, int base, int *lenp)
-{
-       char *p;
-
-       p = nbuf;
-       *p = '\0';
-       do {
-               *++p = hex2ascii(uq % base);
-       } while (uq /= base);
-       if (lenp)
-               *lenp = p - nbuf;
-       return (p);
-}
-
-/*
- * Scaled down version of printf(3).
+#include <mm.h>
+#include <ctype.h>
+
+/**
+ * simple_strtoul - convert a string to an unsigned long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
+{
+    unsigned long result = 0,value;
+
+    if (!base) {
+        base = 10;
+        if (*cp == '0') {
+            base = 8;
+            cp++;
+            if ((*cp == 'x') && isxdigit(cp[1])) {
+                cp++;
+                base = 16;
+            }
+        }
+    }
+    while (isxdigit(*cp) &&
+           (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
+        result = result*base + value;
+        cp++;
+    }
+    if (endp)
+        *endp = (char *)cp;
+    return result;
+}
+
+/**
+ * simple_strtol - convert a string to a signed long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long simple_strtol(const char *cp,char **endp,unsigned int base)
+{
+    if(*cp=='-')
+        return -simple_strtoul(cp+1,endp,base);
+    return simple_strtoul(cp,endp,base);
+}
+
+/**
+ * simple_strtoull - convert a string to an unsigned long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int 
base)
+{
+    unsigned long long result = 0,value;
+
+    if (!base) {
+        base = 10;
+        if (*cp == '0') {
+            base = 8;
+            cp++;
+            if ((*cp == 'x') && isxdigit(cp[1])) {
+                cp++;
+                base = 16;
+            }
+        }
+    }
+    while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+                                                               ? toupper(*cp) 
: *cp)-'A'+10) < base) {
+        result = result*base + value;
+        cp++;
+    }
+    if (endp)
+        *endp = (char *)cp;
+    return result;
+}
+
+/**
+ * simple_strtoll - convert a string to a signed long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long long simple_strtoll(const char *cp,char **endp,unsigned int base)
+{
+    if(*cp=='-')
+        return -simple_strtoull(cp+1,endp,base);
+    return simple_strtoull(cp,endp,base);
+}
+
+static int skip_atoi(const char **s)
+{
+    int i=0;
+
+    while (isdigit(**s))
+        i = i*10 + *((*s)++) - '0';
+    return i;
+}
+
+#define ZEROPAD 1               /* pad with zero */
+#define SIGN    2               /* unsigned/signed long */
+#define PLUS    4               /* show plus */
+#define SPACE   8               /* space if plus */
+#define LEFT    16              /* left justified */
+#define SPECIAL 32              /* 0x */
+#define LARGE   64              /* use 'ABCDEF' instead of 'abcdef' */
+
+static char * number(char * buf, char * end, long long num, int base, int 
size, int precision, int type)
+{
+    char c,sign,tmp[66];
+    const char *digits;
+    const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+    const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    int i;
+
+    digits = (type & LARGE) ? large_digits : small_digits;
+    if (type & LEFT)
+        type &= ~ZEROPAD;
+    if (base < 2 || base > 36)
+        return buf;
+    c = (type & ZEROPAD) ? '0' : ' ';
+    sign = 0;
+    if (type & SIGN) {
+        if (num < 0) {
+            sign = '-';
+            num = -num;
+            size--;
+        } else if (type & PLUS) {
+            sign = '+';
+            size--;
+        } else if (type & SPACE) {
+            sign = ' ';
+            size--;
+        }
+    }
+    if (type & SPECIAL) {
+        if (base == 16)
+            size -= 2;
+        else if (base == 8)
+            size--;
+    }
+    i = 0;
+    if (num == 0)
+        tmp[i++]='0';
+    else 
+    {
+        /* XXX KAF: force unsigned mod and div. */
+        unsigned long long num2=(unsigned long long)num;
+        unsigned int base2=(unsigned int)base;
+        while (num2 != 0) { tmp[i++] = digits[num2%base2]; num2 /= base2; }
+    }
+    if (i > precision)
+        precision = i;
+    size -= precision;
+    if (!(type&(ZEROPAD+LEFT))) {
+        while(size-->0) {
+            if (buf <= end)
+                *buf = ' ';
+            ++buf;
+        }
+    }
+    if (sign) {
+        if (buf <= end)
+            *buf = sign;
+        ++buf;
+    }
+    if (type & SPECIAL) {
+        if (base==8) {
+            if (buf <= end)
+                *buf = '0';
+            ++buf;
+        } else if (base==16) {
+            if (buf <= end)
+                *buf = '0';
+            ++buf;
+            if (buf <= end)
+                *buf = digits[33];
+            ++buf;
+        }
+    }
+    if (!(type & LEFT)) {
+        while (size-- > 0) {
+            if (buf <= end)
+                *buf = c;
+            ++buf;
+        }
+    }
+    while (i < precision--) {
+        if (buf <= end)
+            *buf = '0';
+        ++buf;
+    }
+    while (i-- > 0) {
+        if (buf <= end)
+            *buf = tmp[i];
+        ++buf;
+    }
+    while (size-- > 0) {
+        if (buf <= end)
+            *buf = ' ';
+        ++buf;
+    }
+    return buf;
+}
+
+/**
+* vsnprintf - Format a string and place it in a buffer
+* @buf: The buffer to place the result into
+* @size: The size of the buffer, including the trailing null space
+* @fmt: The format string to use
+* @args: Arguments for the format string
+*
+* Call this function if you are already dealing with a va_list.
+* You probably want snprintf instead.
+ */
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+    int len;
+    unsigned long long num;
+    int i, base;
+    char *str, *end, c;
+    const char *s;
+
+    int flags;          /* flags to number() */
+
+    int field_width;    /* width of output field */
+    int precision;              /* min. # of digits for integers; max
+                                   number of chars for from string */
+    int qualifier;              /* 'h', 'l', or 'L' for integer fields */
+                                /* 'z' support added 23/7/1999 S.H.    */
+                                /* 'z' changed to 'Z' --davidm 1/25/99 */
+
+    str = buf;
+    end = buf + size - 1;
+
+    if (end < buf - 1) {
+        end = ((void *) -1);
+        size = end - buf + 1;
+    }
+
+    for (; *fmt ; ++fmt) {
+        if (*fmt != '%') {
+            if (str <= end)
+                *str = *fmt;
+            ++str;
+            continue;
+        }
+
+        /* process flags */
+        flags = 0;
+    repeat:
+        ++fmt;          /* this also skips first '%' */
+        switch (*fmt) {
+        case '-': flags |= LEFT; goto repeat;
+        case '+': flags |= PLUS; goto repeat;
+        case ' ': flags |= SPACE; goto repeat;
+        case '#': flags |= SPECIAL; goto repeat;
+        case '0': flags |= ZEROPAD; goto repeat;
+        }
+
+        /* get field width */
+        field_width = -1;
+        if (isdigit(*fmt))
+            field_width = skip_atoi(&fmt);
+        else if (*fmt == '*') {
+            ++fmt;
+            /* it's the next argument */
+            field_width = va_arg(args, int);
+            if (field_width < 0) {
+                field_width = -field_width;
+                flags |= LEFT;
+            }
+        }
+
+        /* get the precision */
+        precision = -1;
+        if (*fmt == '.') {
+            ++fmt;
+            if (isdigit(*fmt))
+                precision = skip_atoi(&fmt);
+            else if (*fmt == '*') {
+                ++fmt;
+                          /* it's the next argument */
+                precision = va_arg(args, int);
+            }
+            if (precision < 0)
+                precision = 0;
+        }
+
+        /* get the conversion qualifier */
+        qualifier = -1;
+        if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
+            qualifier = *fmt;
+            ++fmt;
+            if (qualifier == 'l' && *fmt == 'l') {
+                qualifier = 'L';
+                ++fmt;
+            }
+        }
+        if (*fmt == 'q') {
+            qualifier = 'L';
+            ++fmt;
+        }
+
+        /* default base */
+        base = 10;
+
+        switch (*fmt) {
+        case 'c':
+            if (!(flags & LEFT)) {
+                while (--field_width > 0) {
+                    if (str <= end)
+                        *str = ' ';
+                    ++str;
+                }
+            }
+            c = (unsigned char) va_arg(args, int);
+            if (str <= end)
+                *str = c;
+            ++str;
+            while (--field_width > 0) {
+                if (str <= end)
+                    *str = ' ';
+                ++str;
+            }
+            continue;
+
+        case 's':
+            s = va_arg(args, char *);
+            if (!s)
+                s = "<NULL>";
+
+            len = strnlen(s, precision);
+
+            if (!(flags & LEFT)) {
+                while (len < field_width--) {
+                    if (str <= end)
+                        *str = ' ';
+                    ++str;
+                }
+            }
+            for (i = 0; i < len; ++i) {
+                if (str <= end)
+                    *str = *s;
+                ++str; ++s;
+            }
+            while (len < field_width--) {
+                if (str <= end)
+                    *str = ' ';
+                ++str;
+            }
+            continue;
+
+        case 'p':
+            if (field_width == -1) {
+                field_width = 2*sizeof(void *);
+                flags |= ZEROPAD;
+            }
+            str = number(str, end,
+                         (unsigned long) va_arg(args, void *),
+                         16, field_width, precision, flags);
+            continue;
+
+
+        case 'n':
+            /* FIXME:
+             * What does C99 say about the overflow case here? */
+            if (qualifier == 'l') {
+                long * ip = va_arg(args, long *);
+                *ip = (str - buf);
+            } else if (qualifier == 'Z') {
+                size_t * ip = va_arg(args, size_t *);
+                *ip = (str - buf);
+            } else {
+                int * ip = va_arg(args, int *);
+                *ip = (str - buf);
+            }
+            continue;
+
+        case '%':
+            if (str <= end)
+                *str = '%';
+            ++str;
+            continue;
+
+                        /* integer number formats - set up the flags and 
"break" */
+        case 'o':
+            base = 8;
+            break;
+
+        case 'X':
+            flags |= LARGE;
+        case 'x':
+            base = 16;
+            break;
+
+        case 'd':
+        case 'i':
+            flags |= SIGN;
+        case 'u':
+            break;
+
+        default:
+            if (str <= end)
+                *str = '%';
+            ++str;
+            if (*fmt) {
+                if (str <= end)
+                    *str = *fmt;
+                ++str;
+            } else {
+                --fmt;
+            }
+            continue;
+        }
+        if (qualifier == 'L')
+            num = va_arg(args, long long);
+        else if (qualifier == 'l') {
+            num = va_arg(args, unsigned long);
+            if (flags & SIGN)
+                num = (signed long) num;
+        } else if (qualifier == 'Z') {
+            num = va_arg(args, size_t);
+        } else if (qualifier == 'h') {
+            num = (unsigned short) va_arg(args, int);
+            if (flags & SIGN)
+                num = (signed short) num;
+        } else {
+            num = va_arg(args, unsigned int);
+            if (flags & SIGN)
+                num = (signed int) num;
+        }
+
+        str = number(str, end, num, base,
+                     field_width, precision, flags);
+    }
+    if (str <= end)
+        *str = '\0';
+    else if (size > 0)
+        /* don't write out a null byte if the buf size is zero */
+        *end = '\0';
+    /* the trailing null byte doesn't count towards the total
+     * ++str;
+     */
+    return str-buf;
+}
+
+/**
+ * snprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ */
+int snprintf(char * buf, size_t size, const char *fmt, ...)
+{
+    va_list args;
+    int i;
+
+    va_start(args, fmt);
+    i=vsnprintf(buf,size,fmt,args);
+    va_end(args);
+    return i;
+}
+
+/**
+ * vsprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
  *
- * Two additional formats:
- *
- * The format %b is supported to decode error registers.
- * Its usage is:
- *
- *     printf("reg=%b\n", regval, "<base><arg>*");
- *
- * where <base> is the output base expressed as a control character, e.g.
- * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
- * the first of which gives the bit number to be inspected (origin 1), and
- * the next characters (up to a control character, i.e. a character <= 32),
- * give the name of the register.  Thus:
- *
- *     kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
- *
- * would produce output:
- *
- *     reg=3<BITTWO,BITONE>
- *
- * XXX:  %D  -- Hexdump, takes pointer and separator string:
- *             ("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
- *             ("%*D", len, ptr, " " -> XX XX XX XX ...
- */
-
-/* RN: This normally takes a function for output. 
- * we always print to a string and the use HYPERCALL for write to console */
-static int
-kvprintf(char const *fmt, void *arg, int radix, va_list ap)
-{
-
-#define PCHAR(c) {int cc=(c); *d++ = cc; retval++; }
-
-       char nbuf[MAXNBUF];
-       char *p, *q, *d;
-       u_char *up;
-       int ch, n;
-       u_long ul;
-       u_quad_t uq;
-       int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
-       int dwidth;
-       char padc;
-       int retval = 0;
-
-       ul = 0;
-       uq = 0;
-    d = (char *) arg;
-
-       if (fmt == NULL)
-               fmt = "(fmt null)\n";
-
-       if (radix < 2 || radix > 36)
-               radix = 10;
-
-       for (;;) {
-               padc = ' ';
-               width = 0;
-               while ((ch = (u_char)*fmt++) != '%') {
-                       if (ch == '\0') 
-                               return retval;
-                       PCHAR(ch);
-               }
-               qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
-               sign = 0; dot = 0; dwidth = 0;
-reswitch:      switch (ch = (u_char)*fmt++) {
-               case '.':
-                       dot = 1;
-                       goto reswitch;
-               case '#':
-                       sharpflag = 1;
-                       goto reswitch;
-               case '+':
-                       sign = 1;
-                       goto reswitch;
-               case '-':
-                       ladjust = 1;
-                       goto reswitch;
-               case '%':
-                       PCHAR(ch);
-                       break;
-               case '*':
-                       if (!dot) {
-                               width = va_arg(ap, int);
-                               if (width < 0) {
-                                       ladjust = !ladjust;
-                                       width = -width;
+ * Call this function if you are already dealing with a va_list.
+ * You probably want sprintf instead.
+ */
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+    return vsnprintf(buf, 0xFFFFFFFFUL, fmt, args);
+}
+
+
+/**
+ * sprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ */
+int sprintf(char * buf, const char *fmt, ...)
+{
+    va_list args;
+    int i;
+
+    va_start(args, fmt);
+    i=vsprintf(buf,fmt,args);
+    va_end(args);
+    return i;
+}
+
+
+void printf(const char *fmt, ...)
+{
+    static char   buf[1024];
+    va_list       args;
+    
+    va_start(args, fmt);
+    (void)vsnprintf(buf, sizeof(buf), fmt, args);
+    va_end(args);        
+   
+    (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
+}
+
+/**
+ * vsscanf - Unformat a buffer into a list of arguments
+ * @buf:       input buffer
+ * @fmt:       format of buffer
+ * @args:      arguments
+ */
+int vsscanf(const char * buf, const char * fmt, va_list args)
+{
+       const char *str = buf;
+       char *next;
+       char digit;
+       int num = 0;
+       int qualifier;
+       int base;
+       int field_width;
+       int is_sign = 0;
+
+       while(*fmt && *str) {
+               /* skip any white space in format */
+               /* white space in format matchs any amount of
+                * white space, including none, in the input.
+                */
+               if (isspace(*fmt)) {
+                       while (isspace(*fmt))
+                               ++fmt;
+                       while (isspace(*str))
+                               ++str;
+               }
+
+               /* anything that is not a conversion must match exactly */
+               if (*fmt != '%' && *fmt) {
+                       if (*fmt++ != *str++)
+                               break;
+                       continue;
+               }
+
+               if (!*fmt)
+                       break;
+               ++fmt;
+               
+               /* skip this conversion.
+                * advance both strings to next white space
+                */
+               if (*fmt == '*') {
+                       while (!isspace(*fmt) && *fmt)
+                               fmt++;
+                       while (!isspace(*str) && *str)
+                               str++;
+                       continue;
+               }
+
+               /* get field width */
+               field_width = -1;
+               if (isdigit(*fmt))
+                       field_width = skip_atoi(&fmt);
+
+               /* get conversion qualifier */
+               qualifier = -1;
+               if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
+                   *fmt == 'Z' || *fmt == 'z') {
+                       qualifier = *fmt++;
+                       if (unlikely(qualifier == *fmt)) {
+                               if (qualifier == 'h') {
+                                       qualifier = 'H';
+                                       fmt++;
+                               } else if (qualifier == 'l') {
+                                       qualifier = 'L';
+                                       fmt++;
                                }
-                       } else {
-                               dwidth = va_arg(ap, int);
                        }
-                       goto reswitch;
-               case '0':
-                       if (!dot) {
-                               padc = '0';
-                               goto reswitch;
+               }
+               base = 10;
+               is_sign = 0;
+
+               if (!*fmt || !*str)
+                       break;
+
+               switch(*fmt++) {
+               case 'c':
+               {
+                       char *s = (char *) va_arg(args,char*);
+                       if (field_width == -1)
+                               field_width = 1;
+                       do {
+                               *s++ = *str++;
+                       } while (--field_width > 0 && *str);
+                       num++;
+               }
+               continue;
+               case 's':
+               {
+                       char *s = (char *) va_arg(args, char *);
+                       if(field_width == -1)
+                               field_width = INT_MAX;
+                       /* first, skip leading white space in buffer */
+                       while (isspace(*str))
+                               str++;
+
+                       /* now copy until next white space */
+                       while (*str && !isspace(*str) && field_width--) {
+                               *s++ = *str++;
                        }
-               case '1': case '2': case '3': case '4':
-               case '5': case '6': case '7': case '8': case '9':
-                               for (n = 0;; ++fmt) {
-                                       n = n * 10 + ch - '0';
-                                       ch = *fmt;
-                                       if (ch < '0' || ch > '9')
-                                               break;
-                               }
-                       if (dot)
-                               dwidth = n;
-                       else
-                               width = n;
-                       goto reswitch;
-               case 'b':
-                       ul = va_arg(ap, int);
-                       p = va_arg(ap, char *);
-                       for (q = ksprintn(nbuf, ul, *p++, NULL); *q;)
-                               PCHAR(*q--);
-
-                       if (!ul)
-                               break;
-
-                       for (tmp = 0; *p;) {
-                               n = *p++;
-                               if (ul & (1 << (n - 1))) {
-                                       PCHAR(tmp ? ',' : '<');
-                                       for (; (n = *p) > ' '; ++p)
-                                               PCHAR(n);
-                                       tmp = 1;
-                               } else
-                                       for (; *p > ' '; ++p)
-                                               continue;
-                       }
-                       if (tmp)
-                               PCHAR('>');
-                       break;
-               case 'c':
-                       PCHAR(va_arg(ap, int));
-                       break;
-               case 'D':
-                       up = va_arg(ap, u_char *);
-                       p = va_arg(ap, char *);
-                       if (!width)
-                               width = 16;
-                       while(width--) {
-                               PCHAR(hex2ascii(*up >> 4));
-                               PCHAR(hex2ascii(*up & 0x0f));
-                               up++;
-                               if (width)
-                                       for (q=p;*q;q++)
-                                               PCHAR(*q);
-                       }
-                       break;
-               case 'd':
-                       if (qflag)
-                               uq = va_arg(ap, quad_t);
-                       else if (lflag)
-                               ul = va_arg(ap, long);
-                       else
-                               ul = va_arg(ap, int);
-                       sign = 1;
-                       base = 10;
-                       goto number;
-               case 'l':
-                       if (lflag) {
-                               lflag = 0;
-                               qflag = 1;
-                       } else
-                               lflag = 1;
-                       goto reswitch;
+                       *s = '\0';
+                       num++;
+               }
+               continue;
+               case 'n':
+                       /* return number of characters read so far */
+               {
+                       int *i = (int *)va_arg(args,int*);
+                       *i = str - buf;
+               }
+               continue;
                case 'o':
-                       if (qflag)
-                               uq = va_arg(ap, u_quad_t);
-                       else if (lflag)
-                               ul = va_arg(ap, u_long);
-                       else
-                               ul = va_arg(ap, u_int);
                        base = 8;
-                       goto nosign;
-               case 'p':
-                       ul = (uintptr_t)va_arg(ap, void *);
-                       base = 16;
-                       sharpflag = 0;
-            padc  = '0';
-            width = sizeof(uintptr_t)*2;
-                       goto nosign;
-               case 'q':
-                       qflag = 1;
-                       goto reswitch;
-               case 'n':
-               case 'r':
-                       if (qflag)
-                               uq = va_arg(ap, u_quad_t);
-                       else if (lflag)
-                               ul = va_arg(ap, u_long);
-                       else
-                               ul = sign ?
-                                   (u_long)va_arg(ap, int) : va_arg(ap, u_int);
-                       base = radix;
-                       goto number;
-               case 's':
-                       p = va_arg(ap, char *);
-                       if (p == NULL)
-                               p = "(null)";
-                       if (!dot)
-                               n = strlen (p);
-                       else
-                               for (n = 0; n < dwidth && p[n]; n++)
-                                       continue;
-
-                       width -= n;
-
-                       if (!ladjust && width > 0)
-                               while (width--)
-                                       PCHAR(padc);
-                       while (n--)
-                               PCHAR(*p++);
-                       if (ladjust && width > 0)
-                               while (width--)
-                                       PCHAR(padc);
-                       break;
-               case 'u':
-                       if (qflag)
-                               uq = va_arg(ap, u_quad_t);
-                       else if (lflag)
-                               ul = va_arg(ap, u_long);
-                       else
-                               ul = va_arg(ap, u_int);
-                       base = 10;
-                       goto nosign;
+                       break;
                case 'x':
                case 'X':
-                       if (qflag)
-                               uq = va_arg(ap, u_quad_t);
-                       else if (lflag)
-                               ul = va_arg(ap, u_long);
-                       else
-                               ul = va_arg(ap, u_int);
                        base = 16;
-                       goto nosign;
+                       break;
+               case 'i':
+                        base = 0;
+               case 'd':
+                       is_sign = 1;
+               case 'u':
+                       break;
+               case '%':
+                       /* looking for '%' in str */
+                       if (*str++ != '%') 
+                               return num;
+                       continue;
+               default:
+                       /* invalid format; stop here */
+                       return num;
+               }
+
+               /* have some sort of integer conversion.
+                * first, skip white space in buffer.
+                */
+               while (isspace(*str))
+                       str++;
+
+               digit = *str;
+               if (is_sign && digit == '-')
+                       digit = *(str + 1);
+
+               if (!digit
+                    || (base == 16 && !isxdigit(digit))
+                    || (base == 10 && !isdigit(digit))
+                    || (base == 8 && (!isdigit(digit) || digit > '7'))
+                    || (base == 0 && !isdigit(digit)))
+                               break;
+
+               switch(qualifier) {
+               case 'H':       /* that's 'hh' in format */
+                       if (is_sign) {
+                               signed char *s = (signed char *) 
va_arg(args,signed char *);
+                               *s = (signed char) 
simple_strtol(str,&next,base);
+                       } else {
+                               unsigned char *s = (unsigned char *) 
va_arg(args, unsigned char *);
+                               *s = (unsigned char) simple_strtoul(str, &next, 
base);
+                       }
+                       break;
+               case 'h':
+                       if (is_sign) {
+                               short *s = (short *) va_arg(args,short *);
+                               *s = (short) simple_strtol(str,&next,base);
+                       } else {
+                               unsigned short *s = (unsigned short *) 
va_arg(args, unsigned short *);
+                               *s = (unsigned short) simple_strtoul(str, 
&next, base);
+                       }
+                       break;
+               case 'l':
+                       if (is_sign) {
+                               long *l = (long *) va_arg(args,long *);
+                               *l = simple_strtol(str,&next,base);
+                       } else {
+                               unsigned long *l = (unsigned long*) 
va_arg(args,unsigned long*);
+                               *l = simple_strtoul(str,&next,base);
+                       }
+                       break;
+               case 'L':
+                       if (is_sign) {
+                               long long *l = (long long*) va_arg(args,long 
long *);
+                               *l = simple_strtoll(str,&next,base);
+                       } else {
+                               unsigned long long *l = (unsigned long long*) 
va_arg(args,unsigned long long*);
+                               *l = simple_strtoull(str,&next,base);
+                       }
+                       break;
+               case 'Z':
                case 'z':
-                       if (qflag)
-                               uq = va_arg(ap, u_quad_t);
-                       else if (lflag)
-                               ul = va_arg(ap, u_long);
-                       else
-                               ul = sign ?
-                                   (u_long)va_arg(ap, int) : va_arg(ap, u_int);
-                       base = 16;
-                       goto number;
-nosign:                        sign = 0;
-number:                        
-                       if (qflag) {
-                               if (sign && (quad_t)uq < 0) {
-                                       neg = 1;
-                                       uq = -(quad_t)uq;
-                               }
-                               p = ksprintqn(nbuf, uq, base, &tmp);
+               {
+                       size_t *s = (size_t*) va_arg(args,size_t*);
+                       *s = (size_t) simple_strtoul(str,&next,base);
+               }
+               break;
+               default:
+                       if (is_sign) {
+                               int *i = (int *) va_arg(args, int*);
+                               *i = (int) simple_strtol(str,&next,base);
                        } else {
-                               if (sign && (long)ul < 0) {
-                                       neg = 1;
-                                       ul = -(long)ul;
-                               }
-                               p = ksprintn(nbuf, ul, base, &tmp);
+                               unsigned int *i = (unsigned int*) va_arg(args, 
unsigned int*);
+                               *i = (unsigned int) 
simple_strtoul(str,&next,base);
                        }
-                       if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
-                               if (base == 8)
-                                       tmp++;
-                               else if (base == 16)
-                                       tmp += 2;
-                       }
-                       if (neg)
-                               tmp++;
-
-                       if (!ladjust && width && (width -= tmp) > 0)
-                               while (width--)
-                                       PCHAR(padc);
-                       if (neg)
-                               PCHAR('-');
-                       if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
-                               if (base == 8) {
-                                       PCHAR('0');
-                               } else if (base == 16) {
-                                       PCHAR('0');
-                                       PCHAR('x');
-                               }
-                       }
-
-                       while (*p)
-                               PCHAR(*p--);
-
-                       if (ladjust && width && (width -= tmp) > 0)
-                               while (width--)
-                                       PCHAR(padc);
-
-                       break;
-               default:
-                       PCHAR('%');
-                       if (lflag)
-                               PCHAR('l');
-                       PCHAR(ch);
-                       break;
-               }
+                       break;
+               }
+               num++;
+
+               if (!next)
+                       break;
+               str = next;
        }
-#undef PCHAR
-}
-
+       return num;
+}
+
+/**
+ * sscanf - Unformat a buffer into a list of arguments
+ * @buf:       input buffer
+ * @fmt:       formatting of buffer
+ * @...:       resulting arguments
+ */
+int sscanf(const char * buf, const char * fmt, ...)
+{
+       va_list args;
+       int i;
+
+       va_start(args,fmt);
+       i = vsscanf(buf,fmt,args);
+       va_end(args);
+       return i;
+}
+
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/lib/string.c
--- a/extras/mini-os/lib/string.c       Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/lib/string.c       Fri Sep  9 16:30:54 2005
@@ -107,6 +107,19 @@
         return sc - s;
 }
 
+
+char * strcat(char * dest, const char * src)
+{
+    char *tmp = dest;
+    
+    while (*dest)
+        dest++;
+    
+    while ((*dest++ = *src++) != '\0');
+    
+    return tmp;
+}
+
 size_t strlen(const char * s)
 {
        const char *sc;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/mm.c
--- a/extras/mini-os/mm.c       Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/mm.c       Fri Sep  9 16:30:54 2005
@@ -198,7 +198,6 @@
 #endif
 
 
-
 /*
  * Initialise allocator, placing addresses [@min,@max] in free pool.
  * @min and @max are PHYSICAL addresses.
@@ -486,16 +485,17 @@
     phys_to_machine_mapping = (unsigned long *)start_info.mfn_list;
    
     /* First page follows page table pages and 3 more pages (store page etc) */
-    start_pfn = PFN_UP(__pa(start_info.pt_base)) + start_info.nr_pt_frames + 3;
+    start_pfn = PFN_UP(to_phys(start_info.pt_base)) + start_info.nr_pt_frames 
+ 3;
     max_pfn = start_info.nr_pages;
 
     printk("  start_pfn:    %lx\n", start_pfn);
     printk("  max_pfn:      %lx\n", max_pfn);
 
 
+#ifdef __i386__
     build_pagetable(&start_pfn, &max_pfn);
-    
-#ifdef __i386__
+#endif
+
     /*
      * now we can initialise the page allocator
      */
@@ -503,7 +503,5 @@
            (u_long)to_virt(PFN_PHYS(start_pfn)), PFN_PHYS(start_pfn), 
            (u_long)to_virt(PFN_PHYS(max_pfn)), PFN_PHYS(max_pfn));
     init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn));   
-#endif
-    
     printk("MM: done\n");
 }
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/time.c
--- a/extras/mini-os/time.c     Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/time.c     Fri Sep  9 16:30:54 2005
@@ -203,7 +203,7 @@
 }
 
 
-void block(u32 millisecs)
+void block_domain(u32 millisecs)
 {
     struct timeval tv;
     gettimeofday(&tv);
@@ -232,5 +232,6 @@
 
 void init_time(void)
 {
+    printk("Initialising timer interface\n");
     bind_virq(VIRQ_TIMER, &timer_handler);
 }
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/traps.c
--- a/extras/mini-os/traps.c    Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/traps.c    Fri Sep  9 16:30:54 2005
@@ -33,36 +33,7 @@
 
 void dump_regs(struct pt_regs *regs)
 {
-    unsigned long esp;
-    unsigned short ss;
-
-#ifdef __x86_64__
-    esp = regs->rsp;
-    ss  = regs->xss;
-#else
-    esp = (unsigned long) (&regs->esp);
-    ss = __KERNEL_DS;
-    if (regs->xcs & 2) {
-printk("CS is true, esp is %x\n", regs->esp);
-        esp = regs->esp;
-        ss = regs->xss & 0xffff;
-    }
-#endif
-    printf("EIP:    %04x:[<%p>]\n",
-           0xffff & regs->xcs , regs->eip);
-    printf("EFLAGS: %p\n",regs->eflags);
-    printf("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
-           regs->eax, regs->ebx, regs->ecx, regs->edx);
-    printf("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
-           regs->esi, regs->edi, regs->ebp, esp);
-#ifdef __x86_64__
-    printf("r8 : %p   r9 : %p   r10: %p   r11: %p\n",
-           regs->r8,  regs->r9,  regs->r10, regs->r11);
-    printf("r12: %p   r13: %p   r14: %p   r15: %p\n",
-           regs->r12, regs->r13, regs->r14, regs->r15);
-#endif
-    printf("ds: %04x   es: %04x   ss: %04x\n",
-           regs->xds & 0xffff, regs->xes & 0xffff, ss);
+    printk("FIXME: proper register dump (with the stack dump)\n");
 }      
 
 
@@ -105,6 +76,7 @@
     printk("Page fault at linear address %p\n", addr);
     dump_regs(regs);
 #ifdef __x86_64__
+    /* FIXME: _PAGE_PSE */
     {
         unsigned long *tab = (unsigned long *)start_info.pt_base;
         unsigned long page;
@@ -112,23 +84,16 @@
         printk("Pagetable walk from %p:\n", tab);
         
         page = tab[l4_table_offset(addr)];
-        tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
+        tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
         printk(" L4 = %p (%p)\n", page, tab);
-        if ( !(page & AGERESENT) )
-            goto out;
 
         page = tab[l3_table_offset(addr)];
-        tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
+        tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
         printk("  L3 = %p (%p)\n", page, tab);
-        if ( !(page & AGERESENT) )
-            goto out;
         
         page = tab[l2_table_offset(addr)];
-        tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
-        printk("   L2 = %p (%p) %s\n", page, tab,
-               (page & AGESE) ? "(2MB)" : "");
-        if ( !(page & AGERESENT) || (page & AGESE) )
-            goto out;
+        tab =  to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
+        printk("   L2 = %p (%p)\n", page, tab);
         
         page = tab[l1_table_offset(addr)];
         printk("    L1 = %p\n", page);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.4-xen-sparse/mkbuildtree
--- a/linux-2.4-xen-sparse/mkbuildtree  Thu Sep  8 15:18:40 2005
+++ b/linux-2.4-xen-sparse/mkbuildtree  Fri Sep  9 16:30:54 2005
@@ -102,9 +102,9 @@
 relative_lndir ${RS}
 rm -f mkbuildtree
 
-set ${RS}/../linux-2.6-xen-sparse
-[ "$1" == "${RS}/../linux-2.6-xen-sparse" ] && { echo "no Linux 2.6 sparse 
tree at ${RS}/../linux-2.6-xen-sparse"; exit 1; }
-LINUX_26="$1"
+LINUX_26=${RS}/../linux-2.6-xen-sparse
+[ -d $LINUX_26 ] || { echo "no Linux 2.6 sparse tree at 
${RS}/../linux-2.6-xen-sparse"; exit 1; }
+
 
 # Create links to the shared definitions of the Xen interfaces.
 rm -rf ${AD}/include/asm-xen/xen-public
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/arch/xen/Kconfig
--- a/linux-2.6-xen-sparse/arch/xen/Kconfig     Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/Kconfig     Fri Sep  9 16:30:54 2005
@@ -70,6 +70,27 @@
          network devices to other guests via a high-performance shared-memory
          interface.
 
+config XEN_TPMDEV_FRONTEND
+        bool "TPM-device frontend driver"
+        default n
+        help
+          The TPM-device frontend driver.
+
+config XEN_TPMDEV_BACKEND
+        bool "TPM-device backend driver"
+        default n
+        help
+          The TPM-device backend driver
+
+config XEN_TPMDEV_CLOSE_IF_VTPM_FAILS
+        bool "TPM backend closes upon vTPM failure"
+        depends on XEN_TPMDEV_BACKEND
+        default n
+        help
+          The TPM backend closes the channel if the vTPM in userspace indicates
+          a failure. The corresponding domain's channel will be closed.
+          Say Y if you want this feature.
+
 config XEN_BLKDEV_FRONTEND
        bool "Block-device frontend driver"
        default y
@@ -88,15 +109,8 @@
          dedicated device-driver domain, or your master control domain
          (domain 0), then you almost certainly want to say Y here.
 
-config XEN_NETDEV_GRANT_TX
-        bool "Grant table substrate for net drivers tx path (DANGEROUS)"
-        default n
-        help
-          This introduces the use of grant tables as a data exhange mechanism
-          between the frontend and backend network drivers.
-
-config XEN_NETDEV_GRANT_RX
-        bool "Grant table substrate for net drivers rx path (DANGEROUS)"
+config XEN_NETDEV_GRANT
+        bool "Grant table substrate for network drivers (DANGEROUS)"
         default n
         help
           This introduces the use of grant tables as a data exhange mechanism
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/Kconfig.drivers
--- a/linux-2.6-xen-sparse/arch/xen/Kconfig.drivers     Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/Kconfig.drivers     Fri Sep  9 16:30:54 2005
@@ -49,6 +49,10 @@
 endif
 
 if !XEN_PHYSDEV_ACCESS
+source "drivers/char/tpm/Kconfig.domU"
+endif
+
+if !XEN_PHYSDEV_ACCESS
 
 menu "Character devices"
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/arch/xen/Makefile
--- a/linux-2.6-xen-sparse/arch/xen/Makefile    Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/Makefile    Fri Sep  9 16:30:54 2005
@@ -65,6 +65,7 @@
 
 XINSTALL_NAME ?= $(KERNELRELEASE)
 install: vmlinuz
+install kernel_install:
        mkdir -p $(INSTALL_PATH)/boot
        ln -f -s vmlinuz-$(XINSTALL_NAME)$(INSTALL_SUFFIX) 
$(INSTALL_PATH)/boot/vmlinuz-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(XENGUEST)$(INSTALL_SUFFIX)
        rm -f $(INSTALL_PATH)/boot/vmlinuz-$(XINSTALL_NAME)$(INSTALL_SUFFIX)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32       Thu Sep 
 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32       Fri Sep 
 9 16:30:54 2005
@@ -15,10 +15,11 @@
 CONFIG_XEN_BLKDEV_BACKEND=y
 # CONFIG_XEN_BLKDEV_TAP_BE is not set
 CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT_TX=y
-CONFIG_XEN_NETDEV_GRANT_RX=y
+CONFIG_XEN_NETDEV_GRANT=y
 # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
 # CONFIG_XEN_BLKDEV_TAP is not set
 # CONFIG_XEN_SHADOW_MODE is not set
@@ -1122,7 +1123,7 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=y
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64       Thu Sep 
 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64       Fri Sep 
 9 16:30:54 2005
@@ -15,10 +15,11 @@
 CONFIG_XEN_BLKDEV_BACKEND=y
 # CONFIG_XEN_BLKDEV_TAP_BE is not set
 CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT_TX=y
-CONFIG_XEN_NETDEV_GRANT_RX=y
+CONFIG_XEN_NETDEV_GRANT=y
 # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
 # CONFIG_XEN_BLKDEV_TAP is not set
 # CONFIG_XEN_SHADOW_MODE is not set
@@ -195,6 +196,7 @@
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=16384
@@ -1030,7 +1032,7 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=y
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32       Thu Sep 
 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32       Fri Sep 
 9 16:30:54 2005
@@ -12,10 +12,11 @@
 #
 # CONFIG_XEN_PRIVILEGED_GUEST is not set
 # CONFIG_XEN_PHYSDEV_ACCESS is not set
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT_TX=y
-CONFIG_XEN_NETDEV_GRANT_RX=y
+CONFIG_XEN_NETDEV_GRANT=y
 # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
 # CONFIG_XEN_BLKDEV_TAP is not set
 # CONFIG_XEN_SHADOW_MODE is not set
@@ -336,6 +337,7 @@
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_TCG_TPM is not set
 
 #
 # Character devices
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64       Thu Sep 
 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64       Fri Sep 
 9 16:30:54 2005
@@ -12,10 +12,11 @@
 #
 # CONFIG_XEN_PRIVILEGED_GUEST is not set
 # CONFIG_XEN_PHYSDEV_ACCESS is not set
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT_TX=y
-CONFIG_XEN_NETDEV_GRANT_RX=y
+CONFIG_XEN_NETDEV_GRANT=y
 # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
 # CONFIG_XEN_BLKDEV_TAP is not set
 # CONFIG_XEN_SHADOW_MODE is not set
@@ -662,6 +663,7 @@
 CONFIG_INPUT=m
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
+# CONFIG_TCG_TPM is not set
 
 #
 # Character devices
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32        Thu Sep 
 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32        Fri Sep 
 9 16:30:54 2005
@@ -15,10 +15,11 @@
 CONFIG_XEN_BLKDEV_BACKEND=y
 # CONFIG_XEN_BLKDEV_TAP_BE is not set
 CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT_TX=y
-CONFIG_XEN_NETDEV_GRANT_RX=y
+CONFIG_XEN_NETDEV_GRANT=y
 # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
 # CONFIG_XEN_BLKDEV_TAP is not set
 # CONFIG_XEN_SHADOW_MODE is not set
@@ -1855,9 +1856,7 @@
 #
 # TPM devices
 #
-CONFIG_TCG_TPM=m
-CONFIG_TCG_NSC=m
-CONFIG_TCG_ATMEL=m
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64        Thu Sep 
 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64        Fri Sep 
 9 16:30:54 2005
@@ -15,10 +15,11 @@
 CONFIG_XEN_BLKDEV_BACKEND=y
 # CONFIG_XEN_BLKDEV_TAP_BE is not set
 CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT_TX=y
-CONFIG_XEN_NETDEV_GRANT_RX=y
+CONFIG_XEN_NETDEV_GRANT=y
 # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
 # CONFIG_XEN_BLKDEV_TAP is not set
 # CONFIG_XEN_SHADOW_MODE is not set
@@ -2201,7 +2202,7 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
+CONFIG_DEVFS_FS=y
 CONFIG_DEVPTS_FS_XATTR=y
 CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
@@ -2231,7 +2232,7 @@
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
-CONFIG_CRAMFS=m
+CONFIG_CRAMFS=y
 CONFIG_VXFS_FS=m
 # CONFIG_HPFS_FS is not set
 CONFIG_QNX4FS_FS=m
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/arch/xen/i386/Kconfig
--- a/linux-2.6-xen-sparse/arch/xen/i386/Kconfig        Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/Kconfig        Fri Sep  9 16:30:54 2005
@@ -379,18 +379,18 @@
          If you don't know what to do here, say N.
 
 config SMP_ALTERNATIVES
-        bool "SMP alternatives support (EXPERIMENTAL)"
-        depends on SMP && EXPERIMENTAL
-        help
-          Try to reduce the overhead of running an SMP kernel on a uniprocessor
-          host slightly by replacing certain key instruction sequences
-          according to whether we currently have more than one CPU available.
-          This should provide a noticeable boost to performance when
-          running SMP kernels on UP machines, and have negligible impact
-          when running on an true SMP host.
+       bool "SMP alternatives support (EXPERIMENTAL)"
+       depends on SMP && EXPERIMENTAL
+       help
+         Try to reduce the overhead of running an SMP kernel on a uniprocessor
+         host slightly by replacing certain key instruction sequences
+         according to whether we currently have more than one CPU available.
+         This should provide a noticeable boost to performance when
+         running SMP kernels on UP machines, and have negligible impact
+         when running on an true SMP host.
 
           If unsure, say N.
-
+         
 config NR_CPUS
        int "Maximum number of CPUs (2-255)"
        range 2 255
@@ -807,8 +807,8 @@
          direct access method and falls back to the BIOS if that doesn't
          work. If unsure, go with the default, which is "Any".
 
-config PCI_GOBIOS
-       bool "BIOS"
+#config PCI_GOBIOS
+#      bool "BIOS"
 
 config PCI_GOMMCONFIG
        bool "MMConfig"
@@ -821,10 +821,10 @@
 
 endchoice
 
-config PCI_BIOS
-       bool
-       depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
-       default y
+#config PCI_BIOS
+#      bool
+#      depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
+#      default y
 
 config PCI_DIRECT
        bool
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/kernel/Makefile
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/Makefile        Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/Makefile        Fri Sep  9 
16:30:54 2005
@@ -5,6 +5,7 @@
 XENARCH        := $(subst ",,$(CONFIG_XENARCH))
 
 CFLAGS += -Iarch/$(XENARCH)/kernel
+AFLAGS += -Iarch/$(XENARCH)/kernel
 
 extra-y := head.o init_task.o
 
@@ -32,7 +33,7 @@
 obj-$(CONFIG_X86_LOCAL_APIC)   += apic.o
 c-obj-$(CONFIG_X86_LOCAL_APIC) += nmi.o
 obj-$(CONFIG_X86_IO_APIC)      += io_apic.o
-c-obj-$(CONFIG_X86_REBOOTFIXUPS)+= reboot_fixups.o
+c-obj-$(CONFIG_X86_REBOOTFIXUPS)       += reboot_fixups.o
 c-obj-$(CONFIG_X86_NUMAQ)      += numaq.o
 c-obj-$(CONFIG_X86_SUMMIT_NUMA)        += summit.o
 c-obj-$(CONFIG_MODULES)                += module.o
@@ -69,7 +70,7 @@
 
 $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so: \
 $(obj)/vsyscall-%.so: $(src)/vsyscall.lds \
-                     $(obj)/vsyscall-%.o FORCE
+                     $(obj)/vsyscall-%.o $(obj)/vsyscall-note.o FORCE
        $(call if_changed,syscall)
 
 # We also create a special relocatable object that should mirror the symbol
@@ -81,20 +82,17 @@
 
 SYSCFLAGS_vsyscall-syms.o = -r
 $(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \
-                       $(obj)/vsyscall-sysenter.o FORCE
+                       $(obj)/vsyscall-sysenter.o $(obj)/vsyscall-note.o FORCE
        $(call if_changed,syscall)
 
 c-link :=
-s-link := vsyscall-int80.o vsyscall-sysenter.o vsyscall-sigreturn.o 
vsyscall.lds.o syscall_table.o
+s-link := vsyscall-int80.o vsyscall-sysenter.o vsyscall-sigreturn.o 
vsyscall.lds.o vsyscall-note.o
 
 $(patsubst %.o,$(obj)/%.c,$(c-obj-y) $(c-obj-m) $(c-link)) $(patsubst 
%.o,$(obj)/%.S,$(s-obj-y) $(s-link)):
        @ln -fsn $(srctree)/arch/i386/kernel/$(notdir $@) $@
 
 $(obj)/vsyscall-int80.S: $(obj)/vsyscall-sigreturn.S
 
-EXTRA_AFLAGS   += -I$(obj)
-$(obj)/entry.o: $(src)/entry.S $(src)/syscall_table.S
-
 obj-y  += $(c-obj-y) $(s-obj-y)
 obj-m  += $(c-obj-m)
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c     Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c     Fri Sep  9 
16:30:54 2005
@@ -469,6 +469,18 @@
        unsigned int irq;
        unsigned int plat_gsi = gsi;
 
+#ifdef CONFIG_PCI
+       /*
+        * Make sure all (legacy) PCI IRQs are set as level-triggered.
+        */
+       if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
+               extern void eisa_set_level_irq(unsigned int irq);
+
+               if (edge_level == ACPI_LEVEL_SENSITIVE)
+                               eisa_set_level_irq(gsi);
+       }
+#endif
+
 #ifdef CONFIG_X86_IO_APIC
        if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
                plat_gsi = mp_register_gsi(gsi, edge_level, active_high_low);
@@ -610,7 +622,7 @@
        acpi_fadt.force_apic_physical_destination_mode = 
fadt->force_apic_physical_destination_mode;
 #endif
 
-#ifdef CONFIG_X86_PM_TIMER
+#if defined(CONFIG_X86_PM_TIMER) && !defined(CONFIG_XEN)
        /* detect the location of the ACPI PM Timer */
        if (fadt->revision >= FADT2_REVISION_ID) {
                /* FADT rev. 2 */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c Fri Sep  9 
16:30:54 2005
@@ -147,7 +147,7 @@
 {
        struct cpuinfo_x86 *c = &boot_cpu_data;
 
-       if (!(xen_start_info.flags & SIF_PRIVILEGED))
+       if (!(xen_start_info->flags & SIF_PRIVILEGED))
                return -ENODEV;
 
        if ((!cpu_has(c, X86_FEATURE_MTRR)) &&
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S Fri Sep  9 16:30:54 2005
@@ -47,6 +47,7 @@
 #include <asm/segment.h>
 #include <asm/smp.h>
 #include <asm/page.h>
+#include <asm/desc.h>
 #include "irq_vectors.h"
 #include <asm-xen/xen-public/xen.h>
 
@@ -112,7 +113,7 @@
                                XEN_BLOCK_EVENTS(%esi)
 #else
 #define preempt_stop
-#define resume_kernel          restore_all
+#define resume_kernel          restore_nocheck
 #endif
 
 #define SAVE_ALL \
@@ -161,11 +162,9 @@
        addl $4, %esp;  \
 1:     iret;           \
 .section .fixup,"ax";   \
-2:     movl $(__USER_DS), %edx; \
-       movl %edx, %ds; \
-       movl %edx, %es; \
-       movl $11,%eax;  \
-       call do_exit;   \
+2:     pushl $0;       \
+       pushl $do_iret_error;   \
+       jmp error_code; \
 .previous;             \
 .section __ex_table,"a";\
        .align 4;       \
@@ -196,7 +195,7 @@
        movl EFLAGS(%esp), %eax         # mix EFLAGS and CS
        movb CS(%esp), %al
        testl $(VM_MASK | 2), %eax
-       jz resume_kernel                # returning to kernel or vm86-space
+       jz resume_kernel
 ENTRY(resume_userspace)
        XEN_BLOCK_EVENTS(%esi)          # make sure we don't miss an interrupt
                                        # setting need_resched or sigpending
@@ -211,7 +210,7 @@
 ENTRY(resume_kernel)
        XEN_BLOCK_EVENTS(%esi)
        cmpl $0,TI_preempt_count(%ebp)  # non-zero preempt_count ?
-       jnz restore_all
+       jnz restore_nocheck
 need_resched:
        movl TI_flags(%ebp), %ecx       # need_resched set ?
        testb $_TIF_NEED_RESCHED, %cl
@@ -252,7 +251,8 @@
        SAVE_ALL
        GET_THREAD_INFO(%ebp)
 
-       testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+       /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not 
testb */
+       testw 
$(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),TI_flags(%ebp)
        jnz syscall_trace_entry
        cmpl $(nr_syscalls), %eax
        jae syscall_badsys
@@ -276,7 +276,8 @@
        SAVE_ALL
        GET_THREAD_INFO(%ebp)
                                        # system call tracing in operation
-       testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+       /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not 
testb */
+       testw 
$(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),TI_flags(%ebp)
        jnz syscall_trace_entry
        cmpl $(nr_syscalls), %eax
        jae syscall_badsys
@@ -290,7 +291,20 @@
        movl TI_flags(%ebp), %ecx
        testw $_TIF_ALLWORK_MASK, %cx   # current->work
        jne syscall_exit_work
+
 restore_all:
+#if 0 /* XEN */
+       movl EFLAGS(%esp), %eax         # mix EFLAGS, SS and CS
+       # Warning: OLDSS(%esp) contains the wrong/random values if we
+       # are returning to the kernel.
+       # See comments in process.c:copy_thread() for details.
+       movb OLDSS(%esp), %ah
+       movb CS(%esp), %al
+       andl $(VM_MASK | (4 << 8) | 3), %eax
+       cmpl $((4 << 8) | 3), %eax
+       je ldt_ss                       # returning to user-space with LDT SS
+#endif /* XEN */
+restore_nocheck:
        testl $VM_MASK, EFLAGS(%esp)
        jnz resume_vm86
        movb EVENT_MASK(%esp), %al
@@ -300,7 +314,19 @@
        andb $1,%al                     # %al == mask & ~saved_mask
        jnz restore_all_enable_events   #     != 0 => reenable event delivery
        XEN_PUT_VCPU_INFO(%esi)
-       RESTORE_ALL
+       RESTORE_REGS
+       addl $4, %esp
+1:     iret
+.section .fixup,"ax"
+iret_exc:
+       pushl $0                        # no error code
+       pushl $do_iret_error
+       jmp error_code
+.previous
+.section __ex_table,"a"
+       .align 4
+       .long 1b,iret_exc
+.previous
 
 resume_vm86:
        XEN_UNBLOCK_EVENTS(%esi)
@@ -309,6 +335,33 @@
        movl $__HYPERVISOR_switch_vm86,%eax
        int $0x82
        ud2
+
+#if 0 /* XEN */
+ldt_ss:
+       larl OLDSS(%esp), %eax
+       jnz restore_nocheck
+       testl $0x00400000, %eax         # returning to 32bit stack?
+       jnz restore_nocheck             # allright, normal return
+       /* If returning to userspace with 16bit stack,
+        * try to fix the higher word of ESP, as the CPU
+        * won't restore it.
+        * This is an "official" bug of all the x86-compatible
+        * CPUs, which we can try to work around to make
+        * dosemu and wine happy. */
+       subl $8, %esp           # reserve space for switch16 pointer
+       cli
+       movl %esp, %eax
+       /* Set up the 16bit stack frame with switch32 pointer on top,
+        * and a switch16 pointer on top of the current frame. */
+       call setup_x86_bogus_stack
+       RESTORE_REGS
+       lss 20+4(%esp), %esp    # switch to 16bit stack
+1:     iret
+.section __ex_table,"a"
+       .align 4
+       .long 1b,iret_exc
+.previous
+#endif /* XEN */
 
        # perform work that needs to be done immediately before resumption
        ALIGN
@@ -385,6 +438,27 @@
        jmp resume_userspace
 
 #if 0 /* XEN */
+#define FIXUP_ESPFIX_STACK \
+       movl %esp, %eax; \
+       /* switch to 32bit stack using the pointer on top of 16bit stack */ \
+       lss %ss:CPU_16BIT_STACK_SIZE-8, %esp; \
+       /* copy data from 16bit stack to 32bit stack */ \
+       call fixup_x86_bogus_stack; \
+       /* put ESP to the proper location */ \
+       movl %eax, %esp;
+#define UNWIND_ESPFIX_STACK \
+       pushl %eax; \
+       movl %ss, %eax; \
+       /* see if on 16bit stack */ \
+       cmpw $__ESPFIX_SS, %ax; \
+       jne 28f; \
+       movl $__KERNEL_DS, %edx; \
+       movl %edx, %ds; \
+       movl %edx, %es; \
+       /* switch to 32bit stack */ \
+       FIXUP_ESPFIX_STACK \
+28:    popl %eax;
+
 /*
  * Build the entry stubs and pointer table with
  * some assembler magic.
@@ -440,7 +514,9 @@
        pushl %ecx
        pushl %ebx
        cld
-       movl %es, %ecx
+       pushl %es
+#      UNWIND_ESPFIX_STACK
+       popl %ecx
        movl ES(%esp), %edi             # get the function address
        movl ORIG_EAX(%esp), %edx       # get the error code
        movl %eax, ORIG_EAX(%esp)
@@ -625,6 +701,11 @@
  * fault happened on the sysenter path.
  */
 ENTRY(nmi)
+       pushl %eax
+       movl %ss, %eax
+       cmpw $__ESPFIX_SS, %ax
+       popl %eax
+       je nmi_16bit_stack
        cmpl $sysenter_entry,(%esp)
        je nmi_stack_fixup
        pushl %eax
@@ -644,7 +725,7 @@
        xorl %edx,%edx          # zero error code
        movl %esp,%eax          # pt_regs pointer
        call do_nmi
-       RESTORE_ALL
+       jmp restore_all
 
 nmi_stack_fixup:
        FIX_STACK(12,nmi_stack_correct, 1)
@@ -659,6 +740,29 @@
 nmi_debug_stack_fixup:
        FIX_STACK(24,nmi_stack_correct, 1)
        jmp nmi_stack_correct
+
+nmi_16bit_stack:
+       /* create the pointer to lss back */
+       pushl %ss
+       pushl %esp
+       movzwl %sp, %esp
+       addw $4, (%esp)
+       /* copy the iret frame of 12 bytes */
+       .rept 3
+       pushl 16(%esp)
+       .endr
+       pushl %eax
+       SAVE_ALL
+       FIXUP_ESPFIX_STACK              # %eax == %esp
+       xorl %edx,%edx                  # zero error code
+       call do_nmi
+       RESTORE_REGS
+       lss 12+4(%esp), %esp            # back to 16bit stack
+1:     iret
+.section __ex_table,"a"
+       .align 4
+       .long 1b,iret_exc
+.previous
 #endif /* XEN */
 
 ENTRY(int3)
@@ -725,7 +829,9 @@
        pushl %ecx
        pushl %ebx
        cld
-       movl %es,%edi
+       pushl %es
+#      UNWIND_ESPFIX_STACK
+       popl %edi
        movl ES(%esp), %ecx             /* get the faulting address */
        movl ORIG_EAX(%esp), %edx       /* get the error code */
        movl %eax, ORIG_EAX(%esp)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S  Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S  Fri Sep  9 16:30:54 2005
@@ -38,17 +38,13 @@
 #define X86_VENDOR_ID  new_cpu_data+CPUINFO_x86_vendor_id
 
 ENTRY(startup_32)
-       cld
-
-       /* Copy the necessary stuff from xen_start_info structure. */
-       mov  $xen_start_info_union,%edi
-       mov  $512,%ecx
-       rep movsl
+       movl %esi,xen_start_info
 
 #ifdef CONFIG_SMP
 ENTRY(startup_32_smp)
+#endif /* CONFIG_SMP */
+
        cld
-#endif /* CONFIG_SMP */
 
        /* Set up the stack pointer */
        lss stack_start,%esp
@@ -179,7 +175,7 @@
        .quad 0x0000000000000000        /* 0xc0 APM CS 16 code (16 bit) */
        .quad 0x0000000000000000        /* 0xc8 APM DS    data */
 
-       .quad 0x0000000000000000        /* 0xd0 - unused */
+       .quad 0x0000000000000000        /* 0xd0 - ESPFIX 16-bit SS */
        .quad 0x0000000000000000        /* 0xd8 - unused */
        .quad 0x0000000000000000        /* 0xe0 - unused */
        .quad 0x0000000000000000        /* 0xe8 - unused */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/kernel/irq.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/irq.c   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/irq.c   Fri Sep  9 16:30:54 2005
@@ -242,12 +242,12 @@
        } else if (i == NR_IRQS) {
                seq_printf(p, "NMI: ");
                for_each_cpu(j)
-                       seq_printf(p, "%10u ", nmi_count(j));
+                       seq_printf(p, "%10u ", nmi_count(j));
                seq_putc(p, '\n');
 #ifdef CONFIG_X86_LOCAL_APIC
                seq_printf(p, "LOC: ");
                for_each_cpu(j)
-                       seq_printf(p, "%10u ", per_cpu(irq_stat, 
j).apic_timer_irqs);
+                       seq_printf(p, "%10u ", 
per_cpu(irq_stat,j).apic_timer_irqs);
                seq_putc(p, '\n');
 #endif
                seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
@@ -263,6 +263,7 @@
 void fixup_irqs(cpumask_t map)
 {
        unsigned int irq;
+       static int warned;
 
        for (irq = 0; irq < NR_IRQS; irq++) {
                cpumask_t mask;
@@ -276,7 +277,7 @@
                }
                if (irq_desc[irq].handler->set_affinity)
                        irq_desc[irq].handler->set_affinity(irq, mask);
-               else if (irq_desc[irq].action)
+               else if (irq_desc[irq].action && !(warned++))
                        printk("Cannot set affinity for irq %i\n", irq);
        }
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/kernel/pci-dma.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/pci-dma.c       Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/pci-dma.c       Fri Sep  9 
16:30:54 2005
@@ -115,9 +115,9 @@
        if (swiotlb)
                return swiotlb_dma_supported(dev, mask);
        /*
-         * By default we'll BUG when an infeasible DMA is requested, and
-         * request swiotlb=force (see IOMMU_BUG_ON).
-         */
+        * By default we'll BUG when an infeasible DMA is requested, and
+        * request swiotlb=force (see IOMMU_BUG_ON).
+        */
        return 1;
 }
 EXPORT_SYMBOL(dma_supported);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c       Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c       Fri Sep  9 
16:30:54 2005
@@ -135,6 +135,10 @@
  * low exit latency (ie sit in a loop waiting for
  * somebody to say that they'd like to reschedule)
  */
+#ifdef CONFIG_SMP
+extern void smp_suspend(void);
+extern void smp_resume(void);
+#endif
 void cpu_idle (void)
 {
        int cpu = _smp_processor_id();
@@ -149,6 +153,9 @@
 
                        if (cpu_is_offline(cpu)) {
                                local_irq_disable();
+#ifdef CONFIG_SMP
+                               smp_suspend();
+#endif
 #if defined(CONFIG_XEN) && defined(CONFIG_HOTPLUG_CPU)
                                /* Ack it.  From this point on until
                                   we get woken up, we're not allowed
@@ -159,6 +166,9 @@
                                HYPERVISOR_vcpu_down(cpu);
 #endif
                                play_dead();
+#ifdef CONFIG_SMP
+                               smp_resume();
+#endif
                                local_irq_enable();
                        }
 
@@ -456,7 +466,6 @@
        boot_option_idle_override = 1;
        return 1;
 }
-
 
 /*
  *     switch_to(x,yn) should switch tasks from x to y.
@@ -789,10 +798,3 @@
                sp -= get_random_int() % 8192;
        return sp & ~0xf;
 }
-
-
-#ifndef CONFIG_X86_SMP
-void _restore_vcpu(void)
-{
-}
-#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c Fri Sep  9 16:30:54 2005
@@ -55,6 +55,7 @@
 #include <asm/io.h>
 #include <asm-xen/hypervisor.h>
 #include <asm-xen/xen-public/physdev.h>
+#include <asm-xen/xen-public/memory.h>
 #include "setup_arch_pre.h"
 #include <bios_ebda.h>
 
@@ -288,7 +289,7 @@
        int           i;
 
        /* Nothing to do if not running in dom0. */
-       if (!(xen_start_info.flags & SIF_INITDOMAIN))
+       if (!(xen_start_info->flags & SIF_INITDOMAIN))
                return;
 
        /* video rom */
@@ -358,11 +359,12 @@
 shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
 EXPORT_SYMBOL(HYPERVISOR_shared_info);
 
-unsigned int *phys_to_machine_mapping, *pfn_to_mfn_frame_list;
+unsigned long *phys_to_machine_mapping;
+unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[16];
 EXPORT_SYMBOL(phys_to_machine_mapping);
 
 /* Raw start-of-day parameters from the hypervisor. */
-union xen_start_info_union xen_start_info_union;
+start_info_t *xen_start_info;
 
 static void __init limit_regions(unsigned long long size)
 {
@@ -702,7 +704,7 @@
 
        if ((max_cmdline = MAX_GUEST_CMDLINE) > COMMAND_LINE_SIZE)
                max_cmdline = COMMAND_LINE_SIZE;
-       memcpy(saved_command_line, xen_start_info.cmd_line, max_cmdline);
+       memcpy(saved_command_line, xen_start_info->cmd_line, max_cmdline);
        /* Save unparsed command line copy for /proc/cmdline */
        saved_command_line[max_cmdline-1] = '\0';
 
@@ -933,8 +935,8 @@
 /* We don't use the fake e820 because we need to respond to user override. */
 void __init find_max_pfn(void)
 {
-       if ( xen_override_max_pfn < xen_start_info.nr_pages )
-               xen_override_max_pfn = xen_start_info.nr_pages;
+       if ( xen_override_max_pfn < xen_start_info->nr_pages )
+               xen_override_max_pfn = xen_start_info->nr_pages;
        max_pfn = xen_override_max_pfn;
 }
 #endif /* XEN */
@@ -1077,12 +1079,12 @@
 void __init setup_bootmem_allocator(void);
 static unsigned long __init setup_memory(void)
 {
-
        /*
         * partially used pages are not usable - thus
         * we are rounding upwards:
         */
-       min_low_pfn = PFN_UP(__pa(xen_start_info.pt_base)) + 
xen_start_info.nr_pt_frames;
+       min_low_pfn = PFN_UP(__pa(xen_start_info->pt_base)) +
+               xen_start_info->nr_pt_frames;
 
        find_max_pfn();
 
@@ -1188,7 +1190,7 @@
 #endif /* !CONFIG_XEN */
 
 #ifdef CONFIG_BLK_DEV_INITRD
-       if (xen_start_info.mod_start) {
+       if (xen_start_info->mod_start) {
                if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
                        /*reserve_bootmem(INITRD_START, INITRD_SIZE);*/
                        initrd_start = INITRD_START + PAGE_OFFSET;
@@ -1205,7 +1207,7 @@
        }
 #endif
 
-       phys_to_machine_mapping = (unsigned int *)xen_start_info.mfn_list;
+       phys_to_machine_mapping = (unsigned long *)xen_start_info->mfn_list;
 }
 
 /*
@@ -1234,10 +1236,64 @@
 legacy_init_iomem_resources(struct resource *code_resource, struct resource 
*data_resource)
 {
        int i;
+#ifdef CONFIG_XEN
+       dom0_op_t op;
+       struct dom0_memory_map_entry *map;
+       unsigned long gapstart, gapsize;
+       unsigned long long last;
+#endif
 
 #ifdef CONFIG_XEN_PRIVILEGED_GUEST
        probe_roms();
 #endif
+
+#ifdef CONFIG_XEN
+       map = alloc_bootmem_low_pages(PAGE_SIZE);
+       op.cmd = DOM0_PHYSICAL_MEMORY_MAP;
+       op.u.physical_memory_map.memory_map = map;
+       op.u.physical_memory_map.max_map_entries =
+               PAGE_SIZE / sizeof(struct dom0_memory_map_entry);
+       BUG_ON(HYPERVISOR_dom0_op(&op));
+
+       last = 0x100000000ULL;
+       gapstart = 0x10000000;
+       gapsize = 0x400000;
+
+       for (i = op.u.physical_memory_map.nr_map_entries - 1; i >= 0; i--) {
+               struct resource *res;
+
+               if ((last > map[i].end) && ((last - map[i].end) > gapsize)) {
+                       gapsize = last - map[i].end;
+                       gapstart = map[i].end;
+               }
+               if (map[i].start < last)
+                       last = map[i].start;
+
+               if (map[i].end > 0x100000000ULL)
+                       continue;
+               res = alloc_bootmem_low(sizeof(struct resource));
+               res->name = map[i].is_ram ? "System RAM" : "reserved";
+               res->start = map[i].start;
+               res->end = map[i].end - 1;
+               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+               request_resource(&iomem_resource, res);
+       }
+
+       free_bootmem(__pa(map), PAGE_SIZE);
+
+       /*
+        * Start allocating dynamic PCI memory a bit into the gap,
+        * aligned up to the nearest megabyte.
+        *
+        * Question: should we try to pad it up a bit (do something
+        * like " + (gapsize >> 3)" in there too?). We now have the
+        * technology.
+        */
+       pci_mem_start = (gapstart + 0xfffff) & ~0xfffff;
+
+       printk("Allocating PCI resources starting at %08lx (gap: 
%08lx:%08lx)\n",
+               pci_mem_start, gapstart, gapsize);
+#else
        for (i = 0; i < e820.nr_map; i++) {
                struct resource *res;
                if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
@@ -1263,6 +1319,7 @@
                        request_resource(res, data_resource);
                }
        }
+#endif
 }
 
 /*
@@ -1270,23 +1327,29 @@
  */
 static void __init register_memory(void)
 {
+#ifndef CONFIG_XEN
        unsigned long gapstart, gapsize;
        unsigned long long last;
+#endif
        int           i;
+
+       /* Nothing to do if not running in dom0. */
+       if (!(xen_start_info->flags & SIF_INITDOMAIN))
+               return;
 
        if (efi_enabled)
                efi_initialize_iomem_resources(&code_resource, &data_resource);
        else
                legacy_init_iomem_resources(&code_resource, &data_resource);
 
-       if (xen_start_info.flags & SIF_INITDOMAIN)
-               /* EFI systems may still have VGA */
-               request_resource(&iomem_resource, &video_ram_resource);
+       /* EFI systems may still have VGA */
+       request_resource(&iomem_resource, &video_ram_resource);
 
        /* request I/O space for devices used on all i[345]86 PCs */
        for (i = 0; i < STANDARD_IO_RESOURCES; i++)
                request_resource(&ioport_resource, &standard_io_resources[i]);
 
+#ifndef CONFIG_XEN
        /*
         * Search for the bigest gap in the low 32 bits of the e820
         * memory space.
@@ -1327,6 +1390,7 @@
 
        printk("Allocating PCI resources starting at %08lx (gap: 
%08lx:%08lx)\n",
                pci_mem_start, gapstart, gapsize);
+#endif
 }
 
 /* Use inline assembly to define this because the nops are defined 
@@ -1456,7 +1520,7 @@
  */
 void __init setup_arch(char **cmdline_p)
 {
-       int i, j;
+       int i, j, k, fpp;
        physdev_op_t op;
        unsigned long max_low_pfn;
 
@@ -1535,8 +1599,8 @@
        init_mm.start_code = (unsigned long) _text;
        init_mm.end_code = (unsigned long) _etext;
        init_mm.end_data = (unsigned long) _edata;
-       init_mm.brk = (PFN_UP(__pa(xen_start_info.pt_base)) +
-                      xen_start_info.nr_pt_frames) << PAGE_SHIFT;
+       init_mm.brk = (PFN_UP(__pa(xen_start_info->pt_base)) +
+                      xen_start_info->nr_pt_frames) << PAGE_SHIFT;
 
        /* XEN: This is nonsense: kernel may not even be contiguous in RAM. */
        /*code_resource.start = virt_to_phys(_text);*/
@@ -1573,42 +1637,64 @@
 #endif
 
        /* Make sure we have a correctly sized P->M table. */
-       if (max_pfn != xen_start_info.nr_pages) {
+       if (max_pfn != xen_start_info->nr_pages) {
                phys_to_machine_mapping = alloc_bootmem_low_pages(
-                       max_pfn * sizeof(unsigned int));
-
-               if (max_pfn > xen_start_info.nr_pages) {
+                       max_pfn * sizeof(unsigned long));
+
+               if (max_pfn > xen_start_info->nr_pages) {
                        /* set to INVALID_P2M_ENTRY */
                        memset(phys_to_machine_mapping, ~0,
-                               max_pfn * sizeof(unsigned int));
+                               max_pfn * sizeof(unsigned long));
                        memcpy(phys_to_machine_mapping,
-                               (unsigned int *)xen_start_info.mfn_list,
-                               xen_start_info.nr_pages * sizeof(unsigned int));
+                               (unsigned long *)xen_start_info->mfn_list,
+                               xen_start_info->nr_pages * sizeof(unsigned 
long));
                } else {
+                       struct xen_memory_reservation reservation = {
+                               .extent_start = (unsigned long 
*)xen_start_info->mfn_list + max_pfn,
+                               .nr_extents   = xen_start_info->nr_pages - 
max_pfn,
+                               .extent_order = 0,
+                               .domid        = DOMID_SELF
+                       };
+
                        memcpy(phys_to_machine_mapping,
-                               (unsigned int *)xen_start_info.mfn_list,
-                               max_pfn * sizeof(unsigned int));
-                       /* N.B. below relies on sizeof(int) == sizeof(long). */
-                       if (HYPERVISOR_dom_mem_op(
-                               MEMOP_decrease_reservation,
-                               (unsigned long *)xen_start_info.mfn_list + 
max_pfn,
-                               xen_start_info.nr_pages - max_pfn, 0) !=
-                           (xen_start_info.nr_pages - max_pfn)) BUG();
+                               (unsigned long *)xen_start_info->mfn_list,
+                               max_pfn * sizeof(unsigned long));
+                       BUG_ON(HYPERVISOR_memory_op(
+                               XENMEM_decrease_reservation,
+                               &reservation) !=
+                           (xen_start_info->nr_pages - max_pfn));
                }
                free_bootmem(
-                       __pa(xen_start_info.mfn_list), 
-                       PFN_PHYS(PFN_UP(xen_start_info.nr_pages *
-                       sizeof(unsigned int))));
-       }
-
-       pfn_to_mfn_frame_list = alloc_bootmem_low_pages(PAGE_SIZE);
-       for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned int)), j++ )
-       {       
-            pfn_to_mfn_frame_list[j] = 
-                 virt_to_mfn(&phys_to_machine_mapping[i]);
-       }
-       HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
-            virt_to_mfn(pfn_to_mfn_frame_list);
+                       __pa(xen_start_info->mfn_list), 
+                       PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
+                       sizeof(unsigned long))));
+       }
+
+
+       /* 
+        * Initialise the list of the frames that specify the list of 
+        * frames that make up the p2m table. Used by save/restore
+        */
+       pfn_to_mfn_frame_list_list = alloc_bootmem_low_pages(PAGE_SIZE);
+       HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+         virt_to_mfn(pfn_to_mfn_frame_list_list);
+              
+       fpp = PAGE_SIZE/sizeof(unsigned long);
+       for ( i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++ )
+       {
+           if ( (j % fpp) == 0 )
+           {
+               k++;
+               BUG_ON(k>=16);
+               pfn_to_mfn_frame_list[k] = alloc_bootmem_low_pages(PAGE_SIZE);
+               pfn_to_mfn_frame_list_list[k] = 
+                   virt_to_mfn(pfn_to_mfn_frame_list[k]);
+               j=0;
+           }
+           pfn_to_mfn_frame_list[k][j] = 
+               virt_to_mfn(&phys_to_machine_mapping[i]);
+       }
+       HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
 
        /*
         * NOTE: at this point the bootmem allocator is fully available.
@@ -1626,8 +1712,8 @@
        }
 #endif
 
-
-       dmi_scan_machine();
+       if (xen_start_info->flags & SIF_INITDOMAIN)
+               dmi_scan_machine();
 
 #ifdef CONFIG_X86_GENERICARCH
        generic_apic_probe(*cmdline_p);
@@ -1640,7 +1726,7 @@
        HYPERVISOR_physdev_op(&op);
 
 #ifdef CONFIG_ACPI_BOOT
-       if (!(xen_start_info.flags & SIF_INITDOMAIN)) {
+       if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
                printk(KERN_INFO "ACPI in unprivileged domain disabled\n");
                acpi_disabled = 1;
                acpi_ht = 0;
@@ -1666,8 +1752,8 @@
 
        register_memory();
 
-       if (xen_start_info.flags & SIF_INITDOMAIN) {
-               if (!(xen_start_info.flags & SIF_PRIVILEGED))
+       if (xen_start_info->flags & SIF_INITDOMAIN) {
+               if (!(xen_start_info->flags & SIF_PRIVILEGED))
                        panic("Xen granted us console access "
                              "but not privileged status");
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c       Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c       Fri Sep  9 
16:30:54 2005
@@ -856,9 +856,6 @@
        cpu_gdt_descr[cpu].address = __get_free_page(GFP_KERNEL|__GFP_ZERO);
        BUG_ON(cpu_gdt_descr[0].size > PAGE_SIZE);
        cpu_gdt_descr[cpu].size = cpu_gdt_descr[0].size;
-       printk("GDT: copying %d bytes from %lx to %lx\n",
-               cpu_gdt_descr[0].size, cpu_gdt_descr[0].address,
-               cpu_gdt_descr[cpu].address); 
        memcpy((void *)cpu_gdt_descr[cpu].address,
               (void *)cpu_gdt_descr[0].address, cpu_gdt_descr[0].size);
 
@@ -1274,6 +1271,7 @@
                        printk(KERN_WARNING "WARNING: %d siblings found for 
CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
                        smp_num_siblings = siblings;
                }
+
                if (c->x86_num_cores > 1) {
                        for (i = 0; i < NR_CPUS; i++) {
                                if (!cpu_isset(i, cpu_callout_map))
@@ -1601,32 +1599,71 @@
 
 void smp_suspend(void)
 {
-       /* XXX todo: take down time and ipi's on all cpus */
        local_teardown_timer_irq();
        smp_intr_exit();
 }
 
 void smp_resume(void)
 {
-       /* XXX todo: restore time and ipi's on all cpus */
        smp_intr_init();
        local_setup_timer_irq();
 }
 
-DECLARE_PER_CPU(int, timer_irq);
-
-void _restore_vcpu(void)
-{
-       int cpu = smp_processor_id();
-       extern atomic_t vcpus_rebooting;
-
-       /* We are the first thing the vcpu runs when it comes back,
-          and we are supposed to restore the IPIs and timer
-          interrupts etc.  When we return, the vcpu's idle loop will
-          start up again. */
-       _bind_virq_to_irq(VIRQ_TIMER, cpu, per_cpu(timer_irq, cpu));
-       _bind_virq_to_irq(VIRQ_DEBUG, cpu, per_cpu(ldebug_irq, cpu));
-       _bind_ipi_to_irq(RESCHEDULE_VECTOR, cpu, per_cpu(resched_irq, cpu) );
-       _bind_ipi_to_irq(CALL_FUNCTION_VECTOR, cpu, per_cpu(callfunc_irq, cpu) 
);
+static atomic_t vcpus_rebooting;
+
+static void restore_vcpu_ready(void)
+{
+
        atomic_dec(&vcpus_rebooting);
 }
+
+void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
+{
+       int r;
+       int gdt_pages;
+       r = HYPERVISOR_vcpu_pickle(vcpu, ctxt);
+       if (r != 0)
+               panic("pickling vcpu %d -> %d!\n", vcpu, r);
+
+       /* Translate from machine to physical addresses where necessary,
+          so that they can be translated to our new machine address space
+          after resume.  libxc is responsible for doing this to vcpu0,
+          but we do it to the others. */
+       gdt_pages = (ctxt->gdt_ents + 511) / 512;
+       ctxt->ctrlreg[3] = machine_to_phys(ctxt->ctrlreg[3]);
+       for (r = 0; r < gdt_pages; r++)
+               ctxt->gdt_frames[r] = mfn_to_pfn(ctxt->gdt_frames[r]);
+}
+
+int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
+{
+       int r;
+       int gdt_pages = (ctxt->gdt_ents + 511) / 512;
+
+       /* This is kind of a hack, and implicitly relies on the fact that
+          the vcpu stops in a place where all of the call clobbered
+          registers are already dead. */
+       ctxt->user_regs.esp -= 4;
+       ((unsigned long *)ctxt->user_regs.esp)[0] = ctxt->user_regs.eip;
+       ctxt->user_regs.eip = (unsigned long)restore_vcpu_ready;
+
+       /* De-canonicalise.  libxc handles this for vcpu 0, but we need
+          to do it for the other vcpus. */
+       ctxt->ctrlreg[3] = phys_to_machine(ctxt->ctrlreg[3]);
+       for (r = 0; r < gdt_pages; r++)
+               ctxt->gdt_frames[r] = pfn_to_mfn(ctxt->gdt_frames[r]);
+
+       atomic_set(&vcpus_rebooting, 1);
+       r = HYPERVISOR_boot_vcpu(vcpu, ctxt);
+       if (r != 0) {
+               printk(KERN_EMERG "Failed to reboot vcpu %d (%d)\n", vcpu, r);
+               return -1;
+       }
+
+       /* Make sure we wait for the new vcpu to come up before trying to do
+          anything with it or starting the next one. */
+       while (atomic_read(&vcpus_rebooting))
+               barrier();
+
+       return 0;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c       Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c       Fri Sep  9 
16:30:54 2005
@@ -51,7 +51,7 @@
  * swiotlb_sync_single_*, to see if the memory was in fact allocated by this
  * API.
  */
-static dma_addr_t iotlb_bus_start, iotlb_bus_mask;
+static dma_addr_t iotlb_bus_start, iotlb_bus_end, iotlb_bus_mask;
 
 /* Does the given dma address reside within the swiotlb aperture? */
 #define in_swiotlb_aperture(a) (!(((a) ^ iotlb_bus_start) & iotlb_bus_mask))
@@ -157,6 +157,7 @@
        io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
 
        iotlb_bus_start = virt_to_bus(iotlb_virt_start);
+       iotlb_bus_end   = iotlb_bus_start + bytes;
        iotlb_bus_mask  = ~(dma_addr_t)(bytes - 1);
 
        printk(KERN_INFO "Software IO TLB enabled: \n"
@@ -165,7 +166,7 @@
               " Kernel range: 0x%016lx - 0x%016lx\n",
               bytes >> 20,
               (unsigned long)iotlb_bus_start,
-              (unsigned long)iotlb_bus_start + bytes,
+              (unsigned long)iotlb_bus_end,
               (unsigned long)iotlb_virt_start,
               (unsigned long)iotlb_virt_start + bytes);
 }
@@ -181,7 +182,7 @@
          * Otherwise, enable for domain 0 if the machine has 'lots of memory',
          * which we take to mean more than 2GB.
          */
-       if (xen_start_info.flags & SIF_INITDOMAIN) {
+       if (xen_start_info->flags & SIF_INITDOMAIN) {
                dom0_op_t op;
                op.cmd = DOM0_PHYSINFO;
                if ((HYPERVISOR_dom0_op(&op) == 0) &&
@@ -191,6 +192,8 @@
 
        if (swiotlb)
                swiotlb_init_with_default_size(64 * (1<<20));
+       else
+               printk(KERN_INFO "Software IO TLB disabled\n");
 }
 
 static void
@@ -424,13 +427,6 @@
        }
 
        dev_addr = virt_to_bus(map);
-
-       /*
-        * Ensure that the address returned is DMA'ble
-        */
-       if (address_needs_mapping(hwdev, dev_addr))
-               panic("map_single: bounce buffer is not DMA'ble");
-
        return dev_addr;
 }
 
@@ -632,7 +628,7 @@
 int
 swiotlb_dma_supported (struct device *hwdev, u64 mask)
 {
-       return (mask >= 0xffffffffUL);
+       return (mask >= (iotlb_bus_end - 1));
 }
 
 EXPORT_SYMBOL(swiotlb_init);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Fri Sep  9 16:30:54 2005
@@ -445,7 +445,7 @@
        sec = tv->tv_sec;
        __normalize_time(&sec, &nsec);
 
-       if ((xen_start_info.flags & SIF_INITDOMAIN) &&
+       if ((xen_start_info->flags & SIF_INITDOMAIN) &&
            !independent_wallclock) {
                op.cmd = DOM0_SETTIME;
                op.u.settime.secs        = sec;
@@ -476,7 +476,7 @@
 
        WARN_ON(irqs_disabled());
 
-       if (!(xen_start_info.flags & SIF_INITDOMAIN))
+       if (!(xen_start_info->flags & SIF_INITDOMAIN))
                return 0;
 
        /* gets recalled with irq locally disabled */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Fri Sep  9 16:30:54 2005
@@ -449,10 +449,10 @@
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
 DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
-DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
 #ifdef CONFIG_X86_MCE
 DO_ERROR(18, SIGBUS, "machine check", machine_check)
 #endif
+DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
 
 fastcall void do_general_protection(struct pt_regs * regs, long error_code)
 {
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c     Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c     Fri Sep  9 16:30:54 2005
@@ -588,7 +588,15 @@
                pmd_k = pmd_offset(pud_k, address);
                if (!pmd_present(*pmd_k))
                        goto no_context;
+#ifndef CONFIG_XEN
                set_pmd(pmd, *pmd_k);
+#else
+               /*
+                * When running on Xen we must launder *pmd_k through
+                * pmd_val() to ensure that _PAGE_PRESENT is correctly set.
+                */
+               set_pmd(pmd, __pmd(pmd_val(*pmd_k)));
+#endif
 
                pte_k = pte_offset_kernel(pmd_k, address);
                if (!pte_present(*pte_k))
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c        Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c        Fri Sep  9 
16:30:54 2005
@@ -35,6 +35,7 @@
 #include <asm/pgtable.h>
 #include <asm-xen/hypervisor.h>
 #include <asm-xen/balloon.h>
+#include <asm-xen/xen-public/memory.h>
 #include <linux/module.h>
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 #include <linux/percpu.h>
@@ -105,7 +106,7 @@
 void xen_machphys_update(unsigned long mfn, unsigned long pfn)
 {
        mmu_update_t u;
-       u.ptr = (mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
+       u.ptr = ((unsigned long long)mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
        u.val = pfn;
        BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0);
 }
@@ -320,6 +321,12 @@
        pmd_t         *pmd;
        pte_t         *pte;
        unsigned long  mfn, i, flags;
+       struct xen_memory_reservation reservation = {
+               .extent_start = &mfn,
+               .nr_extents   = 1,
+               .extent_order = 0,
+               .domid        = DOMID_SELF
+       };
 
        scrub_pages(vstart, 1 << order);
 
@@ -336,13 +343,15 @@
                        vstart + (i*PAGE_SIZE), __pte_ma(0), 0));
                phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] =
                        INVALID_P2M_ENTRY;
-               BUG_ON(HYPERVISOR_dom_mem_op(
-                       MEMOP_decrease_reservation, &mfn, 1, 0) != 1);
+               BUG_ON(HYPERVISOR_memory_op(
+                       XENMEM_decrease_reservation, &reservation) != 1);
        }
 
        /* 2. Get a new contiguous memory extent. */
-       BUG_ON(HYPERVISOR_dom_mem_op(
-               MEMOP_increase_reservation, &mfn, 1, order | (32<<8)) != 1);
+       reservation.extent_order = order;
+       reservation.address_bits = 31; /* aacraid limitation */
+       BUG_ON(HYPERVISOR_memory_op(
+               XENMEM_increase_reservation, &reservation) != 1);
 
        /* 3. Map the new extent in place of old pages. */
        for (i = 0; i < (1<<order); i++) {
@@ -367,6 +376,12 @@
        pmd_t         *pmd;
        pte_t         *pte;
        unsigned long  mfn, i, flags;
+       struct xen_memory_reservation reservation = {
+               .extent_start = &mfn,
+               .nr_extents   = 1,
+               .extent_order = 0,
+               .domid        = DOMID_SELF
+       };
 
        scrub_pages(vstart, 1 << order);
 
@@ -385,14 +400,14 @@
                        vstart + (i*PAGE_SIZE), __pte_ma(0), 0));
                phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] =
                        INVALID_P2M_ENTRY;
-               BUG_ON(HYPERVISOR_dom_mem_op(
-                       MEMOP_decrease_reservation, &mfn, 1, 0) != 1);
+               BUG_ON(HYPERVISOR_memory_op(
+                       XENMEM_decrease_reservation, &reservation) != 1);
        }
 
        /* 2. Map new pages in place of old pages. */
        for (i = 0; i < (1<<order); i++) {
-               BUG_ON(HYPERVISOR_dom_mem_op(
-                       MEMOP_increase_reservation, &mfn, 1, 0) != 1);
+               BUG_ON(HYPERVISOR_memory_op(
+                       XENMEM_increase_reservation, &reservation) != 1);
                BUG_ON(HYPERVISOR_update_va_mapping(
                        vstart + (i*PAGE_SIZE),
                        pfn_pte_ma(mfn, PAGE_KERNEL), 0));
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/mm/init.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c      Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c      Fri Sep  9 16:30:54 2005
@@ -159,7 +159,7 @@
        pte_t *pte;
        int pgd_idx, pmd_idx, pte_ofs;
 
-       unsigned long max_ram_pfn = xen_start_info.nr_pages;
+       unsigned long max_ram_pfn = xen_start_info->nr_pages;
        if (max_ram_pfn > max_low_pfn)
                max_ram_pfn = max_low_pfn;
 
@@ -219,6 +219,8 @@
        }
 }
 
+#ifndef CONFIG_XEN
+
 static inline int page_kills_ppro(unsigned long pagenr)
 {
        if (pagenr >= 0x70000 && pagenr <= 0x7003F)
@@ -266,6 +268,13 @@
        return 0;
 }
 
+#else /* CONFIG_XEN */
+
+#define page_kills_ppro(p)     0
+#define page_is_ram(p)         1
+
+#endif
+
 #ifdef CONFIG_HIGHMEM
 pte_t *kmap_pte;
 pgprot_t kmap_prot;
@@ -308,7 +317,7 @@
                ClearPageReserved(page);
                set_bit(PG_highmem, &page->flags);
                set_page_count(page, 1);
-               if (pfn < xen_start_info.nr_pages)
+               if (pfn < xen_start_info->nr_pages)
                        __free_page(page);
                totalhigh_pages++;
        } else
@@ -347,7 +356,7 @@
 static void __init pagetable_init (void)
 {
        unsigned long vaddr;
-       pgd_t *pgd_base = (pgd_t *)xen_start_info.pt_base;
+       pgd_t *pgd_base = (pgd_t *)xen_start_info->pt_base;
        int i;
 
        swapper_pg_dir = pgd_base;
@@ -526,14 +535,14 @@
        kmap_init();
 
        /* Switch to the real shared_info page, and clear the dummy page. */
-       set_fixmap(FIX_SHARED_INFO, xen_start_info.shared_info);
+       set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
        HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
        memset(empty_zero_page, 0, sizeof(empty_zero_page));
 
 #ifdef CONFIG_XEN_PHYSDEV_ACCESS
        /* Setup mapping of lower 1st MB */
        for (i = 0; i < NR_FIX_ISAMAPS; i++)
-               if (xen_start_info.flags & SIF_PRIVILEGED)
+               if (xen_start_info->flags & SIF_PRIVILEGED)
                        set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE);
                else
                        __set_fixmap(FIX_ISAMAP_BEGIN - i,
@@ -630,7 +639,7 @@
        /* this will put all low memory onto the freelists */
        totalram_pages += free_all_bootmem();
        /* XEN: init and count low-mem pages outside initial allocation. */
-       for (pfn = xen_start_info.nr_pages; pfn < max_low_pfn; pfn++) {
+       for (pfn = xen_start_info->nr_pages; pfn < max_low_pfn; pfn++) {
                ClearPageReserved(&mem_map[pfn]);
                set_page_count(&mem_map[pfn], 1);
                totalram_pages++;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c   Fri Sep  9 16:30:54 2005
@@ -19,295 +19,17 @@
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 
-#ifndef CONFIG_XEN_PHYSDEV_ACCESS
-
-void * __ioremap(unsigned long phys_addr, unsigned long size,
-                unsigned long flags)
-{
-       return NULL;
-}
-
-void *ioremap_nocache (unsigned long phys_addr, unsigned long size)
-{
-       return NULL;
-}
-
-void iounmap(volatile void __iomem *addr)
-{
-}
-
-#ifdef __i386__
-
-void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
-{
-       return NULL;
-}
-
-void __init bt_iounmap(void *addr, unsigned long size)
-{
-}
-
-#endif /* __i386__ */
-
-#else
-
-/*
- * Does @address reside within a non-highmem page that is local to this virtual
- * machine (i.e., not an I/O page, nor a memory page belonging to another VM).
- * See the comment that accompanies pte_pfn() in pgtable-2level.h to understand
- * why this works.
- */
-static inline int is_local_lowmem(unsigned long address)
-{
-       extern unsigned long max_low_pfn;
-       unsigned long mfn = address >> PAGE_SHIFT;
-       unsigned long pfn = mfn_to_pfn(mfn);
-       return ((pfn < max_low_pfn) && (phys_to_machine_mapping[pfn] == mfn));
-}
-
-/*
- * Generic mapping function (not visible outside):
- */
-
-/*
- * Remap an arbitrary physical address space into the kernel virtual
- * address space. Needed when the kernel wants to access high addresses
- * directly.
- *
- * NOTE! We need to allow non-page-aligned mappings too: we will obviously
- * have to convert them into an offset in a page-aligned mapping, but the
- * caller shouldn't need to know that small detail.
- */
-void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned 
long flags)
-{
-       void __iomem * addr;
-       struct vm_struct * area;
-       unsigned long offset, last_addr;
-       domid_t domid = DOMID_IO;
-
-       /* Don't allow wraparound or zero size */
-       last_addr = phys_addr + size - 1;
-       if (!size || last_addr < phys_addr)
-               return NULL;
-
-#ifdef CONFIG_XEN_PRIVILEGED_GUEST
-       /*
-        * Don't remap the low PCI/ISA area, it's always mapped..
-        */
-       if (phys_addr >= 0x0 && last_addr < 0x100000)
-               return isa_bus_to_virt(phys_addr);
-#endif
-
-       /*
-        * Don't allow anybody to remap normal RAM that we're using..
-        */
-       if (is_local_lowmem(phys_addr)) {
-               char *t_addr, *t_end;
-               struct page *page;
-
-               t_addr = bus_to_virt(phys_addr);
-               t_end = t_addr + (size - 1);
-          
-               for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); 
page++)
-                       if(!PageReserved(page))
-                               return NULL;
-
-               domid = DOMID_SELF;
-       }
-
-       /*
-        * Mappings have to be page-aligned
-        */
-       offset = phys_addr & ~PAGE_MASK;
-       phys_addr &= PAGE_MASK;
-       size = PAGE_ALIGN(last_addr+1) - phys_addr;
-
-       /*
-        * Ok, go for it..
-        */
-       area = get_vm_area(size, VM_IOREMAP | (flags << 20));
-       if (!area)
-               return NULL;
-       area->phys_addr = phys_addr;
-       addr = (void __iomem *) area->addr;
-       flags |= _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED;
-#ifdef __x86_64__
-       flags |= _PAGE_USER;
-#endif
-       if (direct_remap_area_pages(&init_mm, (unsigned long) addr, phys_addr,
-                                   size, __pgprot(flags), domid)) {
-               vunmap((void __force *) addr);
-               return NULL;
-       }
-       return (void __iomem *) (offset + (char __iomem *)addr);
-}
-
-
-/**
- * ioremap_nocache     -   map bus memory into CPU space
- * @offset:    bus address of the memory
- * @size:      size of the resource to map
- *
- * ioremap_nocache performs a platform specific sequence of operations to
- * make bus memory CPU accessible via the readb/readw/readl/writeb/
- * writew/writel functions and the other mmio helpers. The returned
- * address is not guaranteed to be usable directly as a virtual
- * address. 
- *
- * This version of ioremap ensures that the memory is marked uncachable
- * on the CPU as well as honouring existing caching rules from things like
- * the PCI bus. Note that there are other caches and buffers on many 
- * busses. In particular driver authors should read up on PCI writes
- *
- * It's useful if some control registers are in such an area and
- * write combining or read caching is not desirable:
- * 
- * Must be freed with iounmap.
- */
-
-void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
-{
-       unsigned long last_addr;
-       void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD);
-       if (!p) 
-               return p; 
-
-       /* Guaranteed to be > phys_addr, as per __ioremap() */
-       last_addr = phys_addr + size - 1;
-
-       if (is_local_lowmem(last_addr)) { 
-               struct page *ppage = virt_to_page(bus_to_virt(phys_addr));
-               unsigned long npages;
-
-               phys_addr &= PAGE_MASK;
-
-               /* This might overflow and become zero.. */
-               last_addr = PAGE_ALIGN(last_addr);
-
-               /* .. but that's ok, because modulo-2**n arithmetic will make
-               * the page-aligned "last - first" come out right.
-               */
-               npages = (last_addr - phys_addr) >> PAGE_SHIFT;
-
-               if (change_page_attr(ppage, npages, PAGE_KERNEL_NOCACHE) < 0) { 
-                       iounmap(p); 
-                       p = NULL;
-               }
-               global_flush_tlb();
-       }
-
-       return p;                                       
-}
-
-void iounmap(volatile void __iomem *addr)
-{
-       struct vm_struct *p;
-       if ((void __force *) addr <= high_memory) 
-               return; 
-#ifdef CONFIG_XEN_PRIVILEGED_GUEST
-       if ((unsigned long) addr >= fix_to_virt(FIX_ISAMAP_BEGIN))
-               return;
-#endif
-       p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
-       if (!p) { 
-               printk("__iounmap: bad address %p\n", addr);
-               return;
-       }
-
-       if ((p->flags >> 20) && is_local_lowmem(p->phys_addr)) {
-               /* p->size includes the guard page, but cpa doesn't like that */
-               change_page_attr(virt_to_page(bus_to_virt(p->phys_addr)),
-                                (p->size - PAGE_SIZE) >> PAGE_SHIFT,
-                                PAGE_KERNEL);                           
-               global_flush_tlb();
-       } 
-       kfree(p); 
-}
-
-#ifdef __i386__
-
-void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
-{
-       unsigned long offset, last_addr;
-       unsigned int nrpages;
-       enum fixed_addresses idx;
-
-       /* Don't allow wraparound or zero size */
-       last_addr = phys_addr + size - 1;
-       if (!size || last_addr < phys_addr)
-               return NULL;
-
-#ifdef CONFIG_XEN_PRIVILEGED_GUEST
-       /*
-        * Don't remap the low PCI/ISA area, it's always mapped..
-        */
-       if (phys_addr >= 0x0 && last_addr < 0x100000)
-               return isa_bus_to_virt(phys_addr);
-#endif
-
-       /*
-        * Mappings have to be page-aligned
-        */
-       offset = phys_addr & ~PAGE_MASK;
-       phys_addr &= PAGE_MASK;
-       size = PAGE_ALIGN(last_addr) - phys_addr;
-
-       /*
-        * Mappings have to fit in the FIX_BTMAP area.
-        */
-       nrpages = size >> PAGE_SHIFT;
-       if (nrpages > NR_FIX_BTMAPS)
-               return NULL;
-
-       /*
-        * Ok, go for it..
-        */
-       idx = FIX_BTMAP_BEGIN;
-       while (nrpages > 0) {
-               set_fixmap(idx, phys_addr);
-               phys_addr += PAGE_SIZE;
-               --idx;
-               --nrpages;
-       }
-       return (void*) (offset + fix_to_virt(FIX_BTMAP_BEGIN));
-}
-
-void __init bt_iounmap(void *addr, unsigned long size)
-{
-       unsigned long virt_addr;
-       unsigned long offset;
-       unsigned int nrpages;
-       enum fixed_addresses idx;
-
-       virt_addr = (unsigned long)addr;
-       if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN))
-               return;
-#ifdef CONFIG_XEN_PRIVILEGED_GUEST
-       if (virt_addr >= fix_to_virt(FIX_ISAMAP_BEGIN))
-               return;
-#endif
-       offset = virt_addr & ~PAGE_MASK;
-       nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT;
-
-       idx = FIX_BTMAP_BEGIN;
-       while (nrpages > 0) {
-               clear_fixmap(idx);
-               --idx;
-               --nrpages;
-       }
-}
-
-#endif /* __i386__ */
-
-#endif /* CONFIG_XEN_PHYSDEV_ACCESS */
-
+#define ISA_START_ADDRESS      0x0
+#define ISA_END_ADDRESS                0x100000
+
+#if 0 /* not PAE safe */
 /* These hacky macros avoid phys->machine translations. */
 #define __direct_pte(x) ((pte_t) { (x) } )
 #define __direct_mk_pte(page_nr,pgprot) \
   __direct_pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot))
 #define direct_mk_pte_phys(physpage, pgprot) \
   __direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot)
-
+#endif
 
 static int direct_remap_area_pte_fn(pte_t *pte, 
                                    struct page *pte_page,
@@ -316,16 +38,16 @@
 {
        mmu_update_t **v = (mmu_update_t **)data;
 
-       (*v)->ptr = ((maddr_t)pfn_to_mfn(page_to_pfn(pte_page)) <<
+       (*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pte_page)) <<
                     PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
        (*v)++;
 
        return 0;
 }
 
-int direct_remap_area_pages(struct mm_struct *mm,
+int direct_remap_pfn_range(struct mm_struct *mm,
                            unsigned long address, 
-                           unsigned long machine_addr,
+                           unsigned long mfn,
                            unsigned long size, 
                            pgprot_t prot,
                            domid_t  domid)
@@ -356,9 +78,9 @@
                 * Fill in the machine address: PTE ptr is done later by
                 * __direct_remap_area_pages(). 
                 */
-               v->val = pte_val_ma(pfn_pte_ma(machine_addr >> PAGE_SHIFT, 
prot));
-
-               machine_addr += PAGE_SIZE;
+               v->val = pte_val_ma(pfn_pte_ma(mfn, prot));
+
+               mfn++;
                address += PAGE_SIZE; 
                v++;
        }
@@ -376,8 +98,10 @@
        return 0;
 }
 
-EXPORT_SYMBOL(direct_remap_area_pages);
-
+EXPORT_SYMBOL(direct_remap_pfn_range);
+
+
+/* FIXME: This is horribly broken on PAE */ 
 static int lookup_pte_fn(
        pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
 {
@@ -412,6 +136,292 @@
 } 
 
 EXPORT_SYMBOL(touch_pte_range);
+
+#ifdef CONFIG_XEN_PHYSDEV_ACCESS
+
+/*
+ * Does @address reside within a non-highmem page that is local to this virtual
+ * machine (i.e., not an I/O page, nor a memory page belonging to another VM).
+ * See the comment that accompanies pte_pfn() in pgtable-2level.h to understand
+ * why this works.
+ */
+static inline int is_local_lowmem(unsigned long address)
+{
+       extern unsigned long max_low_pfn;
+       unsigned long mfn = address >> PAGE_SHIFT;
+       unsigned long pfn = mfn_to_pfn(mfn);
+       return ((pfn < max_low_pfn) && (phys_to_machine_mapping[pfn] == mfn));
+}
+
+/*
+ * Generic mapping function (not visible outside):
+ */
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned 
long flags)
+{
+       void __iomem * addr;
+       struct vm_struct * area;
+       unsigned long offset, last_addr;
+       domid_t domid = DOMID_IO;
+
+       /* Don't allow wraparound or zero size */
+       last_addr = phys_addr + size - 1;
+       if (!size || last_addr < phys_addr)
+               return NULL;
+
+       /*
+        * Don't remap the low PCI/ISA area, it's always mapped..
+        */
+       if (xen_start_info->flags & SIF_PRIVILEGED &&
+           phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
+               return (void __iomem *) isa_bus_to_virt(phys_addr);
+
+       /*
+        * Don't allow anybody to remap normal RAM that we're using..
+        */
+       if (is_local_lowmem(phys_addr)) {
+               char *t_addr, *t_end;
+               struct page *page;
+
+               t_addr = bus_to_virt(phys_addr);
+               t_end = t_addr + (size - 1);
+          
+               for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); 
page++)
+                       if(!PageReserved(page))
+                               return NULL;
+
+               domid = DOMID_SELF;
+       }
+
+       /*
+        * Mappings have to be page-aligned
+        */
+       offset = phys_addr & ~PAGE_MASK;
+       phys_addr &= PAGE_MASK;
+       size = PAGE_ALIGN(last_addr+1) - phys_addr;
+
+       /*
+        * Ok, go for it..
+        */
+       area = get_vm_area(size, VM_IOREMAP | (flags << 20));
+       if (!area)
+               return NULL;
+       area->phys_addr = phys_addr;
+       addr = (void __iomem *) area->addr;
+       flags |= _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED;
+#ifdef __x86_64__
+       flags |= _PAGE_USER;
+#endif
+       if (direct_remap_pfn_range(&init_mm, (unsigned long) addr, 
phys_addr>>PAGE_SHIFT,
+                                   size, __pgprot(flags), domid)) {
+               vunmap((void __force *) addr);
+               return NULL;
+       }
+       return (void __iomem *) (offset + (char __iomem *)addr);
+}
+
+
+/**
+ * ioremap_nocache     -   map bus memory into CPU space
+ * @offset:    bus address of the memory
+ * @size:      size of the resource to map
+ *
+ * ioremap_nocache performs a platform specific sequence of operations to
+ * make bus memory CPU accessible via the readb/readw/readl/writeb/
+ * writew/writel functions and the other mmio helpers. The returned
+ * address is not guaranteed to be usable directly as a virtual
+ * address. 
+ *
+ * This version of ioremap ensures that the memory is marked uncachable
+ * on the CPU as well as honouring existing caching rules from things like
+ * the PCI bus. Note that there are other caches and buffers on many 
+ * busses. In particular driver authors should read up on PCI writes
+ *
+ * It's useful if some control registers are in such an area and
+ * write combining or read caching is not desirable:
+ * 
+ * Must be freed with iounmap.
+ */
+
+void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
+{
+       unsigned long last_addr;
+       void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD);
+       if (!p) 
+               return p; 
+
+       /* Guaranteed to be > phys_addr, as per __ioremap() */
+       last_addr = phys_addr + size - 1;
+
+       if (is_local_lowmem(last_addr)) { 
+               struct page *ppage = virt_to_page(bus_to_virt(phys_addr));
+               unsigned long npages;
+
+               phys_addr &= PAGE_MASK;
+
+               /* This might overflow and become zero.. */
+               last_addr = PAGE_ALIGN(last_addr);
+
+               /* .. but that's ok, because modulo-2**n arithmetic will make
+               * the page-aligned "last - first" come out right.
+               */
+               npages = (last_addr - phys_addr) >> PAGE_SHIFT;
+
+               if (change_page_attr(ppage, npages, PAGE_KERNEL_NOCACHE) < 0) { 
+                       iounmap(p); 
+                       p = NULL;
+               }
+               global_flush_tlb();
+       }
+
+       return p;                                       
+}
+
+void iounmap(volatile void __iomem *addr)
+{
+       struct vm_struct *p;
+       if ((void __force *) addr <= high_memory) 
+               return;
+
+       /*
+        * __ioremap special-cases the PCI/ISA range by not instantiating a
+        * vm_area and by simply returning an address into the kernel mapping
+        * of ISA space.   So handle that here.
+        */
+       if ((unsigned long) addr >= fix_to_virt(FIX_ISAMAP_BEGIN))
+               return;
+
+       write_lock(&vmlist_lock);
+       p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) 
addr));
+       if (!p) { 
+               printk("iounmap: bad address %p\n", addr);
+               goto out_unlock;
+       }
+
+       if ((p->flags >> 20) && is_local_lowmem(p->phys_addr)) {
+               /* p->size includes the guard page, but cpa doesn't like that */
+               change_page_attr(virt_to_page(bus_to_virt(p->phys_addr)),
+                                (p->size - PAGE_SIZE) >> PAGE_SHIFT,
+                                PAGE_KERNEL);
+               global_flush_tlb();
+       } 
+out_unlock:
+       write_unlock(&vmlist_lock);
+       kfree(p); 
+}
+
+#ifdef __i386__
+
+void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
+{
+       unsigned long offset, last_addr;
+       unsigned int nrpages;
+       enum fixed_addresses idx;
+
+       /* Don't allow wraparound or zero size */
+       last_addr = phys_addr + size - 1;
+       if (!size || last_addr < phys_addr)
+               return NULL;
+
+       /*
+        * Don't remap the low PCI/ISA area, it's always mapped..
+        */
+       if (xen_start_info->flags & SIF_PRIVILEGED &&
+           phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
+               return isa_bus_to_virt(phys_addr);
+
+       /*
+        * Mappings have to be page-aligned
+        */
+       offset = phys_addr & ~PAGE_MASK;
+       phys_addr &= PAGE_MASK;
+       size = PAGE_ALIGN(last_addr) - phys_addr;
+
+       /*
+        * Mappings have to fit in the FIX_BTMAP area.
+        */
+       nrpages = size >> PAGE_SHIFT;
+       if (nrpages > NR_FIX_BTMAPS)
+               return NULL;
+
+       /*
+        * Ok, go for it..
+        */
+       idx = FIX_BTMAP_BEGIN;
+       while (nrpages > 0) {
+               set_fixmap(idx, phys_addr);
+               phys_addr += PAGE_SIZE;
+               --idx;
+               --nrpages;
+       }
+       return (void*) (offset + fix_to_virt(FIX_BTMAP_BEGIN));
+}
+
+void __init bt_iounmap(void *addr, unsigned long size)
+{
+       unsigned long virt_addr;
+       unsigned long offset;
+       unsigned int nrpages;
+       enum fixed_addresses idx;
+
+       virt_addr = (unsigned long)addr;
+       if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN))
+               return;
+       if (virt_addr >= fix_to_virt(FIX_ISAMAP_BEGIN))
+               return;
+       offset = virt_addr & ~PAGE_MASK;
+       nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT;
+
+       idx = FIX_BTMAP_BEGIN;
+       while (nrpages > 0) {
+               clear_fixmap(idx);
+               --idx;
+               --nrpages;
+       }
+}
+
+#endif /* __i386__ */
+
+#else /* CONFIG_XEN_PHYSDEV_ACCESS */
+
+void __iomem * __ioremap(unsigned long phys_addr, unsigned long size,
+                        unsigned long flags)
+{
+       return NULL;
+}
+
+void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
+{
+       return NULL;
+}
+
+void iounmap(volatile void __iomem *addr)
+{
+}
+
+#ifdef __i386__
+
+void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
+{
+       return NULL;
+}
+
+void __init bt_iounmap(void *addr, unsigned long size)
+{
+}
+
+#endif /* __i386__ */
+
+#endif /* CONFIG_XEN_PHYSDEV_ACCESS */
 
 /*
  * Local variables:
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/i386/pci/Makefile
--- a/linux-2.6-xen-sparse/arch/xen/i386/pci/Makefile   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/pci/Makefile   Fri Sep  9 16:30:54 2005
@@ -4,7 +4,7 @@
 
 c-obj-y                                := i386.o
 
-c-obj-$(CONFIG_PCI_BIOS)               += pcbios.o
+#c-obj-$(CONFIG_PCI_BIOS)              += pcbios.o
 c-obj-$(CONFIG_PCI_MMCONFIG)   += mmconfig.o
 c-obj-$(CONFIG_PCI_DIRECT)     += direct.o
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/kernel/Makefile
--- a/linux-2.6-xen-sparse/arch/xen/kernel/Makefile     Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/Makefile     Fri Sep  9 16:30:54 2005
@@ -11,7 +11,7 @@
 
 extra-y += vmlinux.lds
 
-obj-y   := ctrl_if.o evtchn.o fixup.o reboot.o gnttab.o devmem.o
+obj-y   := evtchn.o fixup.o reboot.o gnttab.o devmem.o
 
 obj-$(CONFIG_PROC_FS) += xen_proc.o
 obj-$(CONFIG_NET)     += skbuff.o
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c     Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c     Fri Sep  9 16:30:54 2005
@@ -40,16 +40,8 @@
 #include <asm-xen/synch_bitops.h>
 #include <asm-xen/xen-public/event_channel.h>
 #include <asm-xen/xen-public/physdev.h>
-#include <asm-xen/ctrl_if.h>
 #include <asm-xen/hypervisor.h>
 #include <asm-xen/evtchn.h>
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-EXPORT_SYMBOL(force_evtchn_callback);
-EXPORT_SYMBOL(evtchn_do_upcall);
-EXPORT_SYMBOL(bind_evtchn_to_irq);
-EXPORT_SYMBOL(unbind_evtchn_from_irq);
-#endif
 
 /*
  * This lock protects updates to the following mapping and reference-count
@@ -133,6 +125,7 @@
 {
     (void)HYPERVISOR_xen_version(0);
 }
+EXPORT_SYMBOL(force_evtchn_callback);
 
 /* NB. Interrupts are disabled on entry. */
 asmlinkage void evtchn_do_upcall(struct pt_regs *regs)
@@ -165,6 +158,7 @@
         }
     }
 }
+EXPORT_SYMBOL(evtchn_do_upcall);
 
 static int find_unbound_irq(void)
 {
@@ -211,6 +205,7 @@
     
     return irq;
 }
+EXPORT_SYMBOL(bind_virq_to_irq);
 
 void unbind_virq_from_irq(int virq)
 {
@@ -244,74 +239,7 @@
 
     spin_unlock(&irq_mapping_update_lock);
 }
-
-/* This is only used when a vcpu from an xm save.  The ipi is expected
-   to have been bound before we suspended, and so all of the xenolinux
-   state is set up; we only need to restore the Xen side of things.
-   The irq number has to be the same, but the evtchn number can
-   change. */
-void _bind_ipi_to_irq(int ipi, int vcpu, int irq)
-{
-    evtchn_op_t op;
-    int evtchn;
-
-    spin_lock(&irq_mapping_update_lock);
-
-    op.cmd = EVTCHNOP_bind_ipi;
-    if ( HYPERVISOR_event_channel_op(&op) != 0 )
-       panic("Failed to bind virtual IPI %d on cpu %d\n", ipi, vcpu);
-    evtchn = op.u.bind_ipi.port;
-
-    printk("<0>IPI %d, old evtchn %d, evtchn %d.\n",
-          ipi, per_cpu(ipi_to_evtchn, vcpu)[ipi],
-          evtchn);
-
-    evtchn_to_irq[irq_to_evtchn[irq]] = -1;
-    irq_to_evtchn[irq] = -1;
-
-    evtchn_to_irq[evtchn] = irq;
-    irq_to_evtchn[irq]    = evtchn;
-
-    printk("<0>evtchn_to_irq[%d] = %d.\n", evtchn,
-          evtchn_to_irq[evtchn]);
-    per_cpu(ipi_to_evtchn, vcpu)[ipi] = evtchn;
-
-    bind_evtchn_to_cpu(evtchn, vcpu);
-
-    spin_unlock(&irq_mapping_update_lock);
-
-    clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_mask);
-    clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_pending);
-}
-
-void _bind_virq_to_irq(int virq, int cpu, int irq)
-{
-    evtchn_op_t op;
-    int evtchn;
-
-    spin_lock(&irq_mapping_update_lock);
-
-    op.cmd              = EVTCHNOP_bind_virq;
-    op.u.bind_virq.virq = virq;
-    if ( HYPERVISOR_event_channel_op(&op) != 0 )
-            panic("Failed to bind virtual IRQ %d\n", virq);
-    evtchn = op.u.bind_virq.port;
-
-    evtchn_to_irq[irq_to_evtchn[irq]] = -1;
-    irq_to_evtchn[irq] = -1;
-
-    evtchn_to_irq[evtchn] = irq;
-    irq_to_evtchn[irq]    = evtchn;
-
-    per_cpu(virq_to_irq, cpu)[virq] = irq;
-
-    bind_evtchn_to_cpu(evtchn, cpu);
-
-    spin_unlock(&irq_mapping_update_lock);
-
-    clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_mask);
-    clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_pending);
-}
+EXPORT_SYMBOL(unbind_virq_from_irq);
 
 int bind_ipi_to_irq(int ipi)
 {
@@ -347,6 +275,7 @@
 
     return irq;
 }
+EXPORT_SYMBOL(bind_ipi_to_irq);
 
 void unbind_ipi_from_irq(int ipi)
 {
@@ -374,6 +303,7 @@
 
     spin_unlock(&irq_mapping_update_lock);
 }
+EXPORT_SYMBOL(unbind_ipi_from_irq);
 
 int bind_evtchn_to_irq(unsigned int evtchn)
 {
@@ -394,6 +324,7 @@
     
     return irq;
 }
+EXPORT_SYMBOL(bind_evtchn_to_irq);
 
 void unbind_evtchn_from_irq(unsigned int evtchn)
 {
@@ -409,6 +340,7 @@
 
     spin_unlock(&irq_mapping_update_lock);
 }
+EXPORT_SYMBOL(unbind_evtchn_from_irq);
 
 int bind_evtchn_to_irqhandler(
     unsigned int evtchn,
@@ -427,6 +359,7 @@
 
     return retval;
 }
+EXPORT_SYMBOL(bind_evtchn_to_irqhandler);
 
 void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id)
 {
@@ -434,6 +367,7 @@
     free_irq(irq, dev_id);
     unbind_evtchn_from_irq(evtchn);
 }
+EXPORT_SYMBOL(unbind_evtchn_from_irqhandler);
 
 #ifdef CONFIG_SMP
 static void do_nothing_function(void *ign)
@@ -797,7 +731,4 @@
         irq_desc[pirq_to_irq(i)].depth   = 1;
         irq_desc[pirq_to_irq(i)].handler = &pirq_type;
     }
-
-    /* This needs to be done early, but after the IRQ subsystem is alive. */
-    ctrl_if_init();
-}
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/kernel/reboot.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c     Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c     Fri Sep  9 16:30:54 2005
@@ -12,10 +12,8 @@
 #include <asm-xen/evtchn.h>
 #include <asm-xen/hypervisor.h>
 #include <asm-xen/xen-public/dom0_ops.h>
-#include <asm-xen/linux-public/suspend.h>
 #include <asm-xen/queues.h>
 #include <asm-xen/xenbus.h>
-#include <asm-xen/ctrl_if.h>
 #include <linux/cpu.h>
 #include <linux/kthread.h>
 
@@ -65,69 +63,10 @@
 #define cpu_up(x) (-EOPNOTSUPP)
 #endif
 
-static void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
-{
-    int r;
-    int gdt_pages;
-    r = HYPERVISOR_vcpu_pickle(vcpu, ctxt);
-    if (r != 0)
-       panic("pickling vcpu %d -> %d!\n", vcpu, r);
-
-    /* Translate from machine to physical addresses where necessary,
-       so that they can be translated to our new machine address space
-       after resume.  libxc is responsible for doing this to vcpu0,
-       but we do it to the others. */
-    gdt_pages = (ctxt->gdt_ents + 511) / 512;
-    ctxt->ctrlreg[3] = machine_to_phys(ctxt->ctrlreg[3]);
-    for (r = 0; r < gdt_pages; r++)
-       ctxt->gdt_frames[r] = mfn_to_pfn(ctxt->gdt_frames[r]);
-}
-
-void _restore_vcpu(int cpu);
-
-atomic_t vcpus_rebooting;
-
-static int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
-{
-    int r;
-    int gdt_pages = (ctxt->gdt_ents + 511) / 512;
-
-    /* This is kind of a hack, and implicitly relies on the fact that
-       the vcpu stops in a place where all of the call clobbered
-       registers are already dead. */
-    ctxt->user_regs.esp -= 4;
-    ((unsigned long *)ctxt->user_regs.esp)[0] = ctxt->user_regs.eip;
-    ctxt->user_regs.eip = (unsigned long)_restore_vcpu;
-
-    /* De-canonicalise.  libxc handles this for vcpu 0, but we need
-       to do it for the other vcpus. */
-    ctxt->ctrlreg[3] = phys_to_machine(ctxt->ctrlreg[3]);
-    for (r = 0; r < gdt_pages; r++)
-       ctxt->gdt_frames[r] = pfn_to_mfn(ctxt->gdt_frames[r]);
-
-    atomic_set(&vcpus_rebooting, 1);
-    r = HYPERVISOR_boot_vcpu(vcpu, ctxt);
-    if (r != 0) {
-       printk(KERN_EMERG "Failed to reboot vcpu %d (%d)\n", vcpu, r);
-       return -1;
-    }
-
-    /* Make sure we wait for the new vcpu to come up before trying to do
-       anything with it or starting the next one. */
-    while (atomic_read(&vcpus_rebooting))
-       barrier();
-
-    return 0;
-}
 
 static int __do_suspend(void *ignore)
 {
-    int i, j;
-    suspend_record_t *suspend_record;
-    static vcpu_guest_context_t suspended_cpu_records[NR_CPUS];
-
-    /* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */
-       /* XXX SMH: yes it would :-( */ 
+    int i, j, k, fpp;
 
 #ifdef CONFIG_XEN_USB_FRONTEND
     extern void usbif_resume();
@@ -138,16 +77,25 @@
     extern int gnttab_suspend(void);
     extern int gnttab_resume(void);
 
-#ifdef CONFIG_SMP
-    extern void smp_suspend(void);
-    extern void smp_resume(void);
-#endif
     extern void time_suspend(void);
     extern void time_resume(void);
     extern unsigned long max_pfn;
-    extern unsigned int *pfn_to_mfn_frame_list;
-
+    extern unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[];
+
+#ifdef CONFIG_SMP
+    extern void smp_suspend(void);
+    extern void smp_resume(void);
+
+    static vcpu_guest_context_t suspended_cpu_records[NR_CPUS];
     cpumask_t prev_online_cpus, prev_present_cpus;
+
+    void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt);
+    int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt);
+#endif
+
+    extern void xencons_suspend(void);
+    extern void xencons_resume(void);
+
     int err = 0;
 
     BUG_ON(smp_processor_id() != 0);
@@ -155,15 +103,14 @@
 
 #if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU)
     if (num_online_cpus() > 1) {
-       printk(KERN_WARNING "Can't suspend SMP guests without 
CONFIG_HOTPLUG_CPU\n");
+       printk(KERN_WARNING 
+               "Can't suspend SMP guests without CONFIG_HOTPLUG_CPU\n");
        return -EOPNOTSUPP;
     }
 #endif
 
-    suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL);
-    if ( suspend_record == NULL )
-        goto out;
-
+    preempt_disable();
+#ifdef CONFIG_SMP
     /* Take all of the other cpus offline.  We need to be careful not
        to get preempted between the final test for num_online_cpus()
        == 1 and disabling interrupts, since otherwise userspace could
@@ -175,7 +122,6 @@
        since by the time num_online_cpus() == 1, there aren't any
        other cpus) */
     cpus_clear(prev_online_cpus);
-    preempt_disable();
     while (num_online_cpus() > 1) {
        preempt_enable();
        for_each_online_cpu(i) {
@@ -190,13 +136,13 @@
        }
        preempt_disable();
     }
-
-    suspend_record->nr_pfns = max_pfn; /* final number of pfns */
+#endif
 
     __cli();
 
     preempt_enable();
 
+#ifdef CONFIG_SMP
     cpus_clear(prev_present_cpus);
     for_each_present_cpu(i) {
        if (i == 0)
@@ -204,6 +150,7 @@
        save_vcpu_context(i, &suspended_cpu_records[i]);
        cpu_set(i, prev_present_cpus);
     }
+#endif
 
 #ifdef __i386__
     mm_pin_all();
@@ -218,7 +165,7 @@
 
     xenbus_suspend();
 
-    ctrl_if_suspend();
+    xencons_suspend();
 
     irq_suspend();
 
@@ -227,37 +174,44 @@
     HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
     clear_fixmap(FIX_SHARED_INFO);
 
-    memcpy(&suspend_record->resume_info, &xen_start_info,
-           sizeof(xen_start_info));
+    xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
+    xen_start_info->console_mfn = mfn_to_pfn(xen_start_info->console_mfn);
 
     /* We'll stop somewhere inside this hypercall.  When it returns,
        we'll start resuming after the restore. */
-    HYPERVISOR_suspend(virt_to_mfn(suspend_record));
+    HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
 
     shutting_down = SHUTDOWN_INVALID; 
 
-    memcpy(&xen_start_info, &suspend_record->resume_info,
-           sizeof(xen_start_info));
-
-    set_fixmap(FIX_SHARED_INFO, xen_start_info.shared_info);
+    set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
 
     HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
 
     memset(empty_zero_page, 0, PAGE_SIZE);
-
-    for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ )
+            
+    HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+               virt_to_mfn(pfn_to_mfn_frame_list_list);
+  
+    fpp = PAGE_SIZE/sizeof(unsigned long);
+    for ( i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++ )
     {
-        pfn_to_mfn_frame_list[j] = 
-            virt_to_mfn(&phys_to_machine_mapping[i]);
-    }
-    HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
-        virt_to_mfn(pfn_to_mfn_frame_list);
+       if ( (j % fpp) == 0 )
+       {
+           k++;
+           pfn_to_mfn_frame_list_list[k] = 
+                   virt_to_mfn(pfn_to_mfn_frame_list[k]);
+           j=0;
+       }
+       pfn_to_mfn_frame_list[k][j] = 
+               virt_to_mfn(&phys_to_machine_mapping[i]);
+    }
+    HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
 
     gnttab_resume();
 
     irq_resume();
 
-    ctrl_if_resume();
+    xencons_resume();
 
     xenbus_resume();
 
@@ -269,12 +223,14 @@
 
     usbif_resume();
 
-    for_each_cpu_mask(i, prev_present_cpus) {
+#ifdef CONFIG_SMP
+    for_each_cpu_mask(i, prev_present_cpus)
        restore_vcpu_context(i, &suspended_cpu_records[i]);
-    }
+#endif
 
     __sti();
 
+#ifdef CONFIG_SMP
  out_reenable_cpus:
     for_each_cpu_mask(i, prev_online_cpus) {
        j = cpu_up(i);
@@ -284,10 +240,8 @@
            err = j;
        }
     }
-
- out:
-    if ( suspend_record != NULL )
-        free_page((unsigned long)suspend_record);
+#endif
+
     return err;
 }
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/x86_64/Kconfig
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/Kconfig      Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/Kconfig      Fri Sep  9 16:30:54 2005
@@ -21,12 +21,12 @@
          classical 32-bit x86 architecture. For details see
          <http://www.x86-64.org/>.
 
-config X86
-       bool
-       default y
-
 config 64BIT
        def_bool y
+
+config X86
+       bool
+       default y
 
 config MMU
        bool
@@ -89,10 +89,11 @@
 #        Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs.
 
 config MPSC
-       bool "Intel x86-64"
+       bool "Intel EM64T"
        help
-         Optimize for Intel IA32 with 64bit extension CPUs
-         (Prescott/Nocona/Potomac)
+         Optimize for Intel Pentium 4 and Xeon CPUs with Intel
+         Extended Memory 64 Technology(EM64T). For details see
+         <http://www.intel.com/technology/64bitextensions/>.
 
 config GENERIC_CPU
        bool "Generic-x86-64"
@@ -367,7 +368,6 @@
 
          If unsure, say Y. Only embedded should say N here.
 
-
 endmenu
 
 #
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile      Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile      Fri Sep  9 
16:30:54 2005
@@ -40,7 +40,7 @@
 i386-obj-$(CONFIG_DUMMY_IOMMU) += pci-dma.o
 i386-obj-$(CONFIG_SWIOTLB)     += swiotlb.o
 obj-$(CONFIG_KPROBES)          += kprobes.o
-obj-$(CONFIG_X86_PM_TIMER)     += pmtimer.o
+#obj-$(CONFIG_X86_PM_TIMER)    += pmtimer.o
 
 c-obj-$(CONFIG_MODULES)                += module.o
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c        Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c        Fri Sep  9 
16:30:54 2005
@@ -20,6 +20,9 @@
 #include <asm/e820.h>
 #include <asm/proto.h>
 #include <asm/bootsetup.h>
+#include <asm-xen/xen-public/memory.h>
+
+unsigned long pci_mem_start = 0xaeedbabe;
 
 /* 
  * PFN of last memory page.
@@ -517,14 +520,13 @@
 }
 
 #else  /* CONFIX_XEN */
+
 extern unsigned long xen_override_max_pfn;
 extern union xen_start_info_union xen_start_info_union;
-/*
- * Guest physical starts from 0.
- */
+
 unsigned long __init e820_end_of_ram(void)
 {
-        unsigned long max_end_pfn = xen_start_info.nr_pages;
+        unsigned long max_end_pfn = xen_start_info->nr_pages;
 
        if ( xen_override_max_pfn <  max_end_pfn)
                xen_override_max_pfn = max_end_pfn;
@@ -532,64 +534,53 @@
         return xen_override_max_pfn;
 }
 
-
-
 void __init e820_reserve_resources(void) 
 {
-       return;                 /* Xen won't have reserved entries */
-}
-
-#endif
-
-void __init parse_memopt(char *p, char **from) 
-{ 
-       end_user_pfn = memparse(p, from);
-       end_user_pfn >>= PAGE_SHIFT;    
-        xen_override_max_pfn = (unsigned long) end_user_pfn;
-} 
-
-unsigned long pci_mem_start = 0xaeedbabe;
-
-/*
- * Search for the biggest gap in the low 32 bits of the e820
- * memory space.  We pass this space to PCI to assign MMIO resources
- * for hotplug or unconfigured devices in.
- * Hopefully the BIOS let enough space left.
- */
-__init void e820_setup_gap(void)
-{
-       unsigned long gapstart, gapsize;
-       unsigned long last;
-       int i;
-       int found = 0;
-
-       last = 0x100000000ull;
+       dom0_op_t op;
+       struct dom0_memory_map_entry *map;
+       unsigned long gapstart, gapsize, last;
+       int i, found = 0;
+
+       if (!(xen_start_info->flags & SIF_INITDOMAIN))
+               return;
+
+       map = alloc_bootmem_low_pages(PAGE_SIZE);
+       op.cmd = DOM0_PHYSICAL_MEMORY_MAP;
+       op.u.physical_memory_map.memory_map = map;
+       op.u.physical_memory_map.max_map_entries =
+               PAGE_SIZE / sizeof(struct dom0_memory_map_entry);
+       BUG_ON(HYPERVISOR_dom0_op(&op));
+
+       last = 0x100000000ULL;
        gapstart = 0x10000000;
        gapsize = 0x400000;
-       i = e820.nr_map;
-       while (--i >= 0) {
-               unsigned long long start = e820.map[i].addr;
-               unsigned long long end = start + e820.map[i].size;
-
-               /*
-                * Since "last" is at most 4GB, we know we'll
-                * fit in 32 bits if this condition is true
-                */
-               if (last > end) {
-                       unsigned long gap = last - end;
-
-                       if (gap > gapsize) {
-                               gapsize = gap;
-                               gapstart = end;
-                               found = 1;
-                       }
-               }
-               if (start < last)
-                       last = start;
-       }
+
+       for (i = op.u.physical_memory_map.nr_map_entries - 1; i >= 0; i--) {
+               struct resource *res;
+
+               if ((last > map[i].end) && ((last - map[i].end) > gapsize)) {
+                       gapsize = last - map[i].end;
+                       gapstart = map[i].end;
+                       found = 1;
+               }
+               if (map[i].start < last)
+                       last = map[i].start;
+
+               if (map[i].end > 0x100000000ULL)
+                       continue;
+               res = alloc_bootmem_low(sizeof(struct resource));
+               res->name = map[i].is_ram ? "System RAM" : "reserved";
+               res->start = map[i].start;
+               res->end = map[i].end - 1;
+               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+               request_resource(&iomem_resource, res);
+       }
+
+       free_bootmem(__pa(map), PAGE_SIZE);
 
        if (!found) {
-               gapstart = (end_pfn << PAGE_SHIFT) + 1024*1024;
+               HYPERVISOR_memory_op(XENMEM_maximum_ram_page, &gapstart);
+               gapstart = (gapstart << PAGE_SHIFT) + 1024*1024;
                printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit 
address range\n"
                       KERN_ERR "PCI: Unassigned devices with 32bit resource 
registers may break!\n");
        }
@@ -607,3 +598,72 @@
        printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: 
%lx:%lx)\n",
                pci_mem_start, gapstart, gapsize);
 }
+
+#endif
+
+void __init parse_memopt(char *p, char **from) 
+{ 
+       end_user_pfn = memparse(p, from);
+       end_user_pfn >>= PAGE_SHIFT;    
+        xen_override_max_pfn = (unsigned long) end_user_pfn;
+} 
+
+/*
+ * Search for the biggest gap in the low 32 bits of the e820
+ * memory space.  We pass this space to PCI to assign MMIO resources
+ * for hotplug or unconfigured devices in.
+ * Hopefully the BIOS let enough space left.
+ */
+__init void e820_setup_gap(void)
+{
+#ifndef CONFIG_XEN
+       unsigned long gapstart, gapsize;
+       unsigned long last;
+       int i;
+       int found = 0;
+
+       last = 0x100000000ull;
+       gapstart = 0x10000000;
+       gapsize = 0x400000;
+       i = e820.nr_map;
+       while (--i >= 0) {
+               unsigned long long start = e820.map[i].addr;
+               unsigned long long end = start + e820.map[i].size;
+
+               /*
+                * Since "last" is at most 4GB, we know we'll
+                * fit in 32 bits if this condition is true
+                */
+               if (last > end) {
+                       unsigned long gap = last - end;
+
+                       if (gap > gapsize) {
+                               gapsize = gap;
+                               gapstart = end;
+                               found = 1;
+                       }
+               }
+               if (start < last)
+                       last = start;
+       }
+
+       if (!found) {
+               gapstart = (end_pfn << PAGE_SHIFT) + 1024*1024;
+               printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit 
address range\n"
+                      KERN_ERR "PCI: Unassigned devices with 32bit resource 
registers may break!\n");
+       }
+
+       /*
+        * Start allocating dynamic PCI memory a bit into the gap,
+        * aligned up to the nearest megabyte.
+        *
+        * Question: should we try to pad it up a bit (do something
+        * like " + (gapsize >> 3)" in there too?). We now have the
+        * technology.
+        */
+       pci_mem_start = (gapstart + 0xfffff) & ~0xfffff;
+
+       printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: 
%lx:%lx)\n",
+               pci_mem_start, gapstart, gapsize);
+#endif
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S        Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S        Fri Sep  9 
16:30:54 2005
@@ -40,16 +40,13 @@
        .globl startup_64
 startup_64:
 ENTRY(_start)
-        cld                
-       /* Copy the necessary stuff from xen_start_info structure. */
-       movq  $xen_start_info_union,%rdi
-       movq  $256,%rcx
-       rep movsq
+       movq %rsi,xen_start_info(%rip)
 
 #ifdef CONFIG_SMP
-        ENTRY(startup_64_smp)
+ENTRY(startup_64_smp)
+#endif /* CONFIG_SMP */
+
        cld
-#endif /* CONFIG_SMP */
 
        movq init_rsp(%rip),%rsp
        /* zero EFLAGS after setting rsp */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head64.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head64.c      Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head64.c      Fri Sep  9 
16:30:54 2005
@@ -90,8 +90,9 @@
 {
        int i;
 
-        phys_to_machine_mapping = (u32 *)xen_start_info.mfn_list;
-        start_pfn = (__pa(xen_start_info.pt_base) >> PAGE_SHIFT) +  
xen_start_info.nr_pt_frames;
+        phys_to_machine_mapping = (unsigned long *)xen_start_info->mfn_list;
+        start_pfn = (__pa(xen_start_info->pt_base) >> PAGE_SHIFT) + 
+               xen_start_info->nr_pt_frames;
 
        for (i = 0; i < 256; i++)
                set_intr_gate(i, early_idt_handler);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c       Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c       Fri Sep  9 
16:30:54 2005
@@ -76,7 +76,8 @@
 /* Allows setting of maximum possible memory size  */
 unsigned long xen_override_max_pfn;
 
-u32 *phys_to_machine_mapping, *pfn_to_mfn_frame_list;
+unsigned long *phys_to_machine_mapping;
+unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[512];
 
 EXPORT_SYMBOL(phys_to_machine_mapping);
 
@@ -84,7 +85,7 @@
 DEFINE_PER_CPU(int, nr_multicall_ents);
 
 /* Raw start-of-day parameters from the hypervisor. */
-union xen_start_info_union xen_start_info_union;
+start_info_t *xen_start_info;
 #endif
 
 /*
@@ -314,7 +315,7 @@
        
        if ((max_cmdline = MAX_GUEST_CMDLINE) > COMMAND_LINE_SIZE)
                max_cmdline = COMMAND_LINE_SIZE;
-       memcpy(saved_command_line, xen_start_info.cmd_line, max_cmdline);
+       memcpy(saved_command_line, xen_start_info->cmd_line, max_cmdline);
        saved_command_line[max_cmdline-1] = '\0';
 #else
        memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
@@ -687,7 +688,7 @@
 #endif
 #ifdef CONFIG_XEN
 #ifdef CONFIG_BLK_DEV_INITRD
-       if (xen_start_info.mod_start) {
+       if (xen_start_info->mod_start) {
                if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
                        /*reserve_bootmem_generic(INITRD_START, INITRD_SIZE);*/
                        initrd_start = INITRD_START + PAGE_OFFSET;
@@ -730,29 +731,50 @@
 #endif
 #ifdef CONFIG_XEN
        {
-               int i, j;
+               int i, j, k, fpp;
                /* Make sure we have a large enough P->M table. */
-               if (end_pfn > xen_start_info.nr_pages) {
+               if (end_pfn > xen_start_info->nr_pages) {
                        phys_to_machine_mapping = alloc_bootmem(
-                               max_pfn * sizeof(u32));
+                               end_pfn * sizeof(unsigned long));
                        memset(phys_to_machine_mapping, ~0,
-                              max_pfn * sizeof(u32));
+                              end_pfn * sizeof(unsigned long));
                        memcpy(phys_to_machine_mapping,
-                              (u32 *)xen_start_info.mfn_list,
-                              xen_start_info.nr_pages * sizeof(u32));
+                              (unsigned long *)xen_start_info->mfn_list,
+                              xen_start_info->nr_pages * sizeof(unsigned 
long));
                        free_bootmem(
-                               __pa(xen_start_info.mfn_list), 
-                               PFN_PHYS(PFN_UP(xen_start_info.nr_pages *
-                                               sizeof(u32))));
-               }
-
-               pfn_to_mfn_frame_list = alloc_bootmem(PAGE_SIZE);
-
-               for ( i=0, j=0; i < end_pfn; i+=(PAGE_SIZE/sizeof(u32)), j++ )
-               {       
-                       pfn_to_mfn_frame_list[j] = 
+                               __pa(xen_start_info->mfn_list), 
+                               PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
+                                               sizeof(unsigned long))));
+               }
+
+               /* 
+                * Initialise the list of the frames that specify the list of 
+                * frames that make up the p2m table. Used by save/restore
+                */
+               pfn_to_mfn_frame_list_list = alloc_bootmem(PAGE_SIZE);
+               HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+                 virt_to_mfn(pfn_to_mfn_frame_list_list);
+              
+               fpp = PAGE_SIZE/sizeof(unsigned long);
+               for ( i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++ )
+               {
+                       if ( (j % fpp) == 0 )
+                       {
+                               k++;
+                               BUG_ON(k>=fpp);
+                               pfn_to_mfn_frame_list[k] = 
alloc_bootmem(PAGE_SIZE);
+                               pfn_to_mfn_frame_list_list[k] = 
+                                       virt_to_mfn(pfn_to_mfn_frame_list[k]);
+                               j=0;
+                       }
+                       pfn_to_mfn_frame_list[k][j] = 
                                virt_to_mfn(&phys_to_machine_mapping[i]);
                }
+               HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
+               
+               
+
+
 
        }
 #endif
@@ -817,8 +839,8 @@
               op.u.set_iopl.iopl = 1;
               HYPERVISOR_physdev_op(&op);
 
-              if (xen_start_info.flags & SIF_INITDOMAIN) {
-                      if (!(xen_start_info.flags & SIF_PRIVILEGED))
+              if (xen_start_info->flags & SIF_INITDOMAIN) {
+                      if (!(xen_start_info->flags & SIF_PRIVILEGED))
                               panic("Xen granted us console access "
                                     "but not privileged status");
                       
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c     Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c     Fri Sep  9 
16:30:54 2005
@@ -1277,21 +1277,23 @@
 
 void smp_suspend(void)
 {
-       /* XXX todo: take down time and ipi's on all cpus */
        local_teardown_timer_irq();
        smp_intr_exit();
 }
 
 void smp_resume(void)
 {
-       /* XXX todo: restore time and ipi's on all cpus */
        smp_intr_init();
        local_setup_timer_irq();
 }
 
-void _restore_vcpu(void)
-{
-       /* XXX need to write this */
-}
-
-#endif
+void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
+{
+}
+
+int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
+{
+       return 0;
+}
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c   Fri Sep  9 16:30:54 2005
@@ -149,7 +149,7 @@
        pmd_t *pmd;
        pte_t *pte;
 
-        pgd = (pgd_t *)per_cpu(cur_pgd, smp_processor_id());
+       pgd = (pgd_t *)per_cpu(cur_pgd, smp_processor_id());
        pgd += pgd_index(address);
 
        printk("PGD %lx ", pgd_val(*pgd));
@@ -296,9 +296,9 @@
 #define MEM_VERBOSE 1
 
 #ifdef MEM_VERBOSE
-#define MEM_LOG(_f, _a...)                           \
-  printk("fault.c:[%d]-> " _f "\n", \
-          __LINE__ , ## _a )
+#define MEM_LOG(_f, _a...)                     \
+       printk("fault.c:[%d]-> " _f "\n",       \
+       __LINE__ , ## _a )
 #else
 #define MEM_LOG(_f, _a...) ((void)0)
 #endif
@@ -325,7 +325,7 @@
        siginfo_t info;
 
        if (!user_mode(regs))
-                error_code &= ~4; /* means kernel */
+               error_code &= ~4; /* means kernel */
 
 #ifdef CONFIG_CHECKING
        { 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c    Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c    Fri Sep  9 16:30:54 2005
@@ -62,14 +62,16 @@
  * avaialble in init_memory_mapping().
  */
 
-#define addr_to_page(addr, page)                                             \
-        (addr) &= PHYSICAL_PAGE_MASK;                                   \
-        (page) = ((unsigned long *) ((unsigned long)(((mfn_to_pfn((addr) >> 
PAGE_SHIFT)) << PAGE_SHIFT) + __START_KERNEL_map)))
+#define addr_to_page(addr, page)                               \
+       (addr) &= PHYSICAL_PAGE_MASK;                           \
+       (page) = ((unsigned long *) ((unsigned long)            \
+       (((mfn_to_pfn((addr) >> PAGE_SHIFT)) << PAGE_SHIFT) +   \
+       __START_KERNEL_map)))
 
 static void __make_page_readonly(unsigned long va)
 {
-        unsigned long addr;
-        pte_t pte, *ptep;
+       unsigned long addr;
+       pte_t pte, *ptep;
        unsigned long *page = (unsigned long *) init_level4_pgt;
 
        addr = (unsigned long) page[pgd_index(va)];
@@ -89,22 +91,22 @@
 
 static void __make_page_writable(unsigned long va)
 {
-        unsigned long addr;
-        pte_t pte, *ptep;
-        unsigned long *page = (unsigned long *) init_level4_pgt;
-
-        addr = (unsigned long) page[pgd_index(va)];
-        addr_to_page(addr, page);
-
-        addr = page[pud_index(va)];
-        addr_to_page(addr, page);
-        
-        addr = page[pmd_index(va)];
-        addr_to_page(addr, page);
-
-        ptep = (pte_t *) &page[pte_index(va)];
+       unsigned long addr;
+       pte_t pte, *ptep;
+       unsigned long *page = (unsigned long *) init_level4_pgt;
+
+       addr = (unsigned long) page[pgd_index(va)];
+       addr_to_page(addr, page);
+
+       addr = page[pud_index(va)];
+       addr_to_page(addr, page);
+ 
+       addr = page[pmd_index(va)];
+       addr_to_page(addr, page);
+
+       ptep = (pte_t *) &page[pte_index(va)];
        pte.pte = (ptep->pte | _PAGE_RW);
-        xen_l1_entry_update(ptep, pte);
+       xen_l1_entry_update(ptep, pte);
        __flush_tlb_one(addr);
 }
 
@@ -115,55 +117,55 @@
 void make_page_readonly(void *va)
 {
        pgd_t* pgd; pud_t *pud; pmd_t* pmd; pte_t pte, *ptep;
-        unsigned long addr = (unsigned long) va;
-
-        if (!init_mapping_done) {
-                __make_page_readonly(addr);
-                return;
-        }
-                
-        pgd = pgd_offset_k(addr);
-        pud = pud_offset(pgd, addr);
-        pmd = pmd_offset(pud, addr);
-        ptep = pte_offset_kernel(pmd, addr);
+       unsigned long addr = (unsigned long) va;
+
+       if (!init_mapping_done) {
+               __make_page_readonly(addr);
+               return;
+       }
+  
+       pgd = pgd_offset_k(addr);
+       pud = pud_offset(pgd, addr);
+       pmd = pmd_offset(pud, addr);
+       ptep = pte_offset_kernel(pmd, addr);
        pte.pte = (ptep->pte & ~_PAGE_RW);
-        xen_l1_entry_update(ptep, pte);
+       xen_l1_entry_update(ptep, pte);
        __flush_tlb_one(addr);
 }
 
 void make_page_writable(void *va)
 {
-        pgd_t* pgd; pud_t *pud; pmd_t* pmd; pte_t pte, *ptep;
-        unsigned long addr = (unsigned long) va;
-
-        if (!init_mapping_done) {
-                __make_page_writable(addr);
-                return;
-        }
-
-        pgd = pgd_offset_k(addr);
-        pud = pud_offset(pgd, addr);
-        pmd = pmd_offset(pud, addr);
-        ptep = pte_offset_kernel(pmd, addr);
+       pgd_t* pgd; pud_t *pud; pmd_t* pmd; pte_t pte, *ptep;
+       unsigned long addr = (unsigned long) va;
+
+       if (!init_mapping_done) {
+               __make_page_writable(addr);
+               return;
+       }
+
+       pgd = pgd_offset_k(addr);
+       pud = pud_offset(pgd, addr);
+       pmd = pmd_offset(pud, addr);
+       ptep = pte_offset_kernel(pmd, addr);
        pte.pte = (ptep->pte | _PAGE_RW);
-        xen_l1_entry_update(ptep, pte);
+       xen_l1_entry_update(ptep, pte);
        __flush_tlb_one(addr);
 }
 
 void make_pages_readonly(void* va, unsigned nr)
 {
-        while ( nr-- != 0 ) {
-                make_page_readonly(va);
-                va = (void*)((unsigned long)va + PAGE_SIZE);
-        }
+       while (nr-- != 0) {
+               make_page_readonly(va);
+               va = (void*)((unsigned long)va + PAGE_SIZE);
+       }
 }
 
 void make_pages_writable(void* va, unsigned nr)
 {
-        while ( nr-- != 0 ) {
-                make_page_writable(va);
-                va = (void*)((unsigned long)va + PAGE_SIZE);
-        }
+       while (nr-- != 0) {
+               make_page_writable(va);
+               va = (void*)((unsigned long)va + PAGE_SIZE);
+       }
 }
 
 /*
@@ -389,7 +391,7 @@
         set_pte_phys(address, phys, prot, SET_FIXMAP_USER); 
 }
 
-unsigned long __initdata table_start, table_end, tables_space; 
+unsigned long __initdata table_start, tables_space; 
 
 unsigned long get_machine_pfn(unsigned long addr)
 {
@@ -400,40 +402,15 @@
         return pte_mfn(*pte);
 } 
 
-#define ALIGN_TO_4K __attribute__((section(".data.page_aligned")))
-#define MAX_LOW_PAGES  0x20
-static unsigned long __init_pgt[MAX_LOW_PAGES][512]  ALIGN_TO_4K;
-static int __init_pgt_index;
-
-/*
- * We start using from start_pfn
- */
 static __init void *alloc_static_page(unsigned long *phys)
 {
-       int i = __init_pgt_index++;
-
-       if (__init_pgt_index >= MAX_LOW_PAGES) {
-               printk("Need to increase MAX_LOW_PAGES");
-               BUG();
-       }
-               
-       *phys = __pa(__init_pgt[i]);
-
-       return (void *) __init_pgt[i];
+       unsigned long va = (start_pfn << PAGE_SHIFT) + __START_KERNEL_map;
+       *phys = start_pfn << PAGE_SHIFT;
+       start_pfn++;
+       memset((void *)va, 0, PAGE_SIZE);
+       return (void *)va;
 } 
 
-/*
- * Get RO page
- */
-static void __init *alloc_low_page(unsigned long *phys)
-{ 
-        unsigned long pfn = table_end++;
-    
-        *phys = (pfn << PAGE_SHIFT);
-        memset((void *) ((pfn << PAGE_SHIFT) + __START_KERNEL_map), 0, 
PAGE_SIZE);
-        return (void *)((pfn << PAGE_SHIFT) + __START_KERNEL_map);
-} 
-
 #define PTE_SIZE PAGE_SIZE
 
 static inline void __set_pte(pte_t *dst, pte_t val)
@@ -443,30 +420,24 @@
 
 static inline int make_readonly(unsigned long paddr)
 {
-    int readonly = 0;
-
-    /* Make new page tables read-only. */
-    if ((paddr < ((table_start << PAGE_SHIFT) + tables_space)) &&
-        (paddr >= (table_start << PAGE_SHIFT)))
-        readonly = 1;
-
-    /* Make old page tables read-only. */
-    if ((paddr < ((xen_start_info.pt_base - __START_KERNEL_map) +
-                  (xen_start_info.nr_pt_frames << PAGE_SHIFT))) &&
-        (paddr >= (xen_start_info.pt_base - __START_KERNEL_map)))
-        readonly = 1;
-
-    /*
-     * No need for writable mapping of kernel image. This also ensures that
-     * page and descriptor tables embedded inside don't have writable mappings.
-     */
-    if ((paddr >= __pa_symbol(&_text)) && (paddr < __pa_symbol(&_end)))
-        readonly = 1;
-
-    return readonly;
-}
-
-void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
+       int readonly = 0;
+
+       /* Make old and new page tables read-only. */
+       if ((paddr >= (xen_start_info->pt_base - __START_KERNEL_map))
+           && (paddr < ((table_start << PAGE_SHIFT) + tables_space)))
+               readonly = 1;
+       /*
+        * No need for writable mapping of kernel image. This also ensures that
+        * page and descriptor tables embedded inside don't have writable
+        * mappings. 
+        */
+       if ((paddr >= __pa_symbol(&_text)) && (paddr < __pa_symbol(&_end)))
+               readonly = 1;
+
+       return readonly;
+}
+
+static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned 
long end)
 { 
         long i, j, k; 
         unsigned long paddr;
@@ -485,7 +456,7 @@
                        break;
                } 
 
-               pmd = alloc_low_page(&pmd_phys);
+               pmd = alloc_static_page(&pmd_phys);
                 make_page_readonly(pmd);
                 xen_pmd_pin(pmd_phys);
                set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE));
@@ -499,18 +470,19 @@
                                        set_pmd(pmd,  __pmd(0)); 
                                break;
                        }
-                        pte = alloc_low_page(&pte_phys);
+                        pte = alloc_static_page(&pte_phys);
                         pte_save = pte;
                         for (k = 0; k < PTRS_PER_PTE; pte++, k++, paddr += 
PTE_SIZE) {
+                                if ((paddr >= end) ||
+                                    ((paddr >> PAGE_SHIFT) >=
+                                     xen_start_info->nr_pages)) { 
+                                        __set_pte(pte, __pte(0)); 
+                                        continue;
+                                }
                                 if (make_readonly(paddr)) {
                                         __set_pte(pte, 
                                                 __pte(paddr | (_KERNPG_TABLE & 
~_PAGE_RW)));
                                         continue;
-                                }
-                                if (paddr >= end) { 
-                                        for (; k < PTRS_PER_PTE; k++, pte++)
-                                                __set_pte(pte, __pte(0)); 
-                                        break;
                                 }
                                 __set_pte(pte, __pte(paddr | _KERNPG_TABLE));
                         }
@@ -525,15 +497,16 @@
 
 static void __init find_early_table_space(unsigned long end)
 {
-        unsigned long puds, pmds, ptes; 
+       unsigned long puds, pmds, ptes; 
 
        puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
        pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
-        ptes = (end + PTE_SIZE - 1) >> PAGE_SHIFT;
-
-        tables_space = round_up(puds * 8, PAGE_SIZE) + 
-                         round_up(pmds * 8, PAGE_SIZE) + 
-                         round_up(ptes * 8, PAGE_SIZE); 
+       ptes = (end + PTE_SIZE - 1) >> PAGE_SHIFT;
+
+       tables_space =
+               round_up(puds * 8, PAGE_SIZE) + 
+               round_up(pmds * 8, PAGE_SIZE) + 
+               round_up(ptes * 8, PAGE_SIZE); 
 }
 
 void __init xen_init_pt(void)
@@ -549,7 +522,7 @@
        memset((void *)level2_kernel_pgt, 0, PAGE_SIZE);
 
        /* Find the initial pte page that was built for us. */
-       page = (unsigned long *)xen_start_info.pt_base;
+       page = (unsigned long *)xen_start_info->pt_base;
        addr = page[pgd_index(__START_KERNEL_map)];
        addr_to_page(addr, page);
        addr = page[pud_index(__START_KERNEL_map)];
@@ -579,65 +552,58 @@
                mk_kernel_pgd(__pa_symbol(level3_user_pgt)));
 }
 
-/*
- * Extend kernel mapping to access pages for page tables.  The initial
- * mapping done by Xen is minimal (e.g. 8MB) and we need to extend the
- * mapping for early initialization.
- */
-static unsigned long current_size, extended_size;
-
 void __init extend_init_mapping(void) 
 {
        unsigned long va = __START_KERNEL_map;
        unsigned long phys, addr, *pte_page;
-        pmd_t *pmd;
+       pmd_t *pmd;
        pte_t *pte, new_pte;
-       unsigned long *page = (unsigned long *) init_level4_pgt;
-       int i;
+       unsigned long *page = (unsigned long *)init_level4_pgt;
 
        addr = page[pgd_index(va)];
        addr_to_page(addr, page);
        addr = page[pud_index(va)];
        addr_to_page(addr, page);
 
-       for (;;) {
+       /* Kill mapping of low 1MB. */
+       while (va < (unsigned long)&_text) {
+               HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0);
+               va += PAGE_SIZE;
+       }
+
+       /* Ensure init mappings cover kernel text/data and initial tables. */
+       while (va < (__START_KERNEL_map
+                    + (start_pfn << PAGE_SHIFT)
+                    + tables_space)) {
                pmd = (pmd_t *)&page[pmd_index(va)];
-               if (!pmd_present(*pmd))
-                       break;
-               addr = page[pmd_index(va)];
-               addr_to_page(addr, pte_page);
-               for (i = 0; i < PTRS_PER_PTE; i++) {
-                       pte = (pte_t *) &pte_page[pte_index(va)];
-                       if (!pte_present(*pte))
-                               break;
-                       va += PAGE_SIZE;
-                       current_size += PAGE_SIZE;
+               if (pmd_none(*pmd)) {
+                       pte_page = alloc_static_page(&phys);
+                       make_page_readonly(pte_page);
+                       xen_pte_pin(phys);
+                       set_pmd(pmd, __pmd(phys | _KERNPG_TABLE | _PAGE_USER));
+               } else {
+                       addr = page[pmd_index(va)];
+                       addr_to_page(addr, pte_page);
                }
-       }
-
-       while (va < __START_KERNEL_map + current_size + tables_space) {
-               pmd = (pmd_t *) &page[pmd_index(va)];
-               if (!pmd_none(*pmd))
-                       continue;
-               pte_page = (unsigned long *) alloc_static_page(&phys);
-               make_page_readonly(pte_page);
-               xen_pte_pin(phys);
-               set_pmd(pmd, __pmd(phys | _KERNPG_TABLE | _PAGE_USER));
-               for (i = 0; i < PTRS_PER_PTE; i++, va += PAGE_SIZE) {
+               pte = (pte_t *)&pte_page[pte_index(va)];
+               if (pte_none(*pte)) {
                        new_pte = pfn_pte(
                                (va - __START_KERNEL_map) >> PAGE_SHIFT, 
                                __pgprot(_KERNPG_TABLE | _PAGE_USER));
-                       pte = (pte_t *)&pte_page[pte_index(va)];
                        xen_l1_entry_update(pte, new_pte);
-                       extended_size += PAGE_SIZE;
                }
-       }
-
-       /* Kill mapping of low 1MB. */
-       for (va = __START_KERNEL_map; va < (unsigned long)&_text; va += 
PAGE_SIZE)
+               va += PAGE_SIZE;
+       }
+
+       /* Finally, blow away any spurious initial mappings. */
+       while (1) {
+               pmd = (pmd_t *)&page[pmd_index(va)];
+               if (pmd_none(*pmd))
+                       break;
                HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0);
-}
-
+               va += PAGE_SIZE;
+       }
+}
 
 /* Setup the direct mapping of the physical memory at PAGE_OFFSET.
    This runs before bootmem is initialized and gets pages directly from the 
@@ -650,34 +616,31 @@
 
        find_early_table_space(end);
        extend_init_mapping();
-       start_pfn = current_size >> PAGE_SHIFT;
 
        table_start = start_pfn;
-       table_end = table_start;
 
        start = (unsigned long)__va(start);
        end = (unsigned long)__va(end);
 
        for (; start < end; start = next) {
                unsigned long pud_phys; 
-                pud_t *pud = alloc_low_page(&pud_phys);
-                make_page_readonly(pud);
-                xen_pud_pin(pud_phys);
+               pud_t *pud = alloc_static_page(&pud_phys);
+               make_page_readonly(pud);
+               xen_pud_pin(pud_phys);
                next = start + PGDIR_SIZE;
                if (next > end) 
                        next = end; 
                phys_pud_init(pud, __pa(start), __pa(next));
                set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
-       } 
-
-       printk("kernel direct mapping tables upto %lx @ %lx-%lx\n", end, 
-              table_start<<PAGE_SHIFT, 
-              table_end<<PAGE_SHIFT);
-
-        start_pfn = ((current_size + extended_size) >> PAGE_SHIFT);
+       }
+
+       printk("kernel direct mapping tables upto %lx @ %lx-%lx\n",
+              __pa(end), table_start<<PAGE_SHIFT, start_pfn<<PAGE_SHIFT);
+
+       BUG_ON(start_pfn != (table_start + (tables_space >> PAGE_SHIFT)));
 
        __flush_tlb_all();
-        init_mapping_done = 1;
+       init_mapping_done = 1;
 }
 
 extern struct x8664_pda cpu_pda[NR_CPUS];
@@ -708,7 +671,7 @@
                free_area_init(zones_size);
        }
 
-        set_fixmap(FIX_SHARED_INFO, xen_start_info.shared_info);
+        set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
         HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
 
         memset(empty_zero_page, 0, sizeof(empty_zero_page));
@@ -719,7 +682,7 @@
                int i;
         /* Setup mapping of lower 1st MB */
                for (i = 0; i < NR_FIX_ISAMAPS; i++)
-                       if (xen_start_info.flags & SIF_PRIVILEGED)
+                       if (xen_start_info->flags & SIF_PRIVILEGED)
                                set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE);
                        else
                                __set_fixmap(FIX_ISAMAP_BEGIN - i,
@@ -767,9 +730,6 @@
 
 static inline int page_is_ram (unsigned long pagenr)
 {
-        if (pagenr < start_pfn || pagenr >= end_pfn)
-                return 0;
-
         return 1;
 }
 
@@ -1005,3 +965,13 @@
 {
        return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
 }
+
+/*
+ * Local variables:
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/drivers/char/mem.c
--- a/linux-2.6-xen-sparse/drivers/char/mem.c   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/mem.c   Fri Sep  9 16:30:54 2005
@@ -231,7 +231,7 @@
 }
 #endif
 
-static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
+static int mmap_mem(struct file * file, struct vm_area_struct * vma)
 {
 #if defined(__HAVE_PHYS_MEM_ACCESS_PROT)
        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
@@ -258,7 +258,6 @@
        return 0;
 }
 
-#if 0
 static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
 {
         unsigned long long val;
@@ -275,7 +274,6 @@
        vma->vm_pgoff = __pa(val) >> PAGE_SHIFT;
        return mmap_mem(file, vma);
 }
-#endif
 
 extern long vread(char *buf, char *addr, unsigned long count);
 extern long vwrite(char *buf, char *addr, unsigned long count);
@@ -731,7 +729,7 @@
        .llseek         = memory_lseek,
        .read           = read_mem,
        .write          = write_mem,
-       .mmap           = mmap_kmem,
+       .mmap           = mmap_mem,
        .open           = open_mem,
 };
 #else
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/drivers/xen/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/Makefile Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/Makefile Fri Sep  9 16:30:54 2005
@@ -8,7 +8,9 @@
 
 obj-$(CONFIG_XEN_BLKDEV_BACKEND)       += blkback/
 obj-$(CONFIG_XEN_NETDEV_BACKEND)       += netback/
+obj-$(CONFIG_XEN_TPMDEV_BACKEND)       += tpmback/
 obj-$(CONFIG_XEN_BLKDEV_FRONTEND)      += blkfront/
 obj-$(CONFIG_XEN_NETDEV_FRONTEND)      += netfront/
 obj-$(CONFIG_XEN_BLKDEV_TAP)           += blktap/
+obj-$(CONFIG_XEN_TPMDEV_FRONTEND)      += tpmfront/
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c
--- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c        Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c        Fri Sep  9 
16:30:54 2005
@@ -44,6 +44,7 @@
 #include <asm-xen/xen_proc.h>
 #include <asm-xen/hypervisor.h>
 #include <asm-xen/balloon.h>
+#include <asm-xen/xen-public/memory.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -57,6 +58,12 @@
 static struct proc_dir_entry *balloon_pde;
 
 static DECLARE_MUTEX(balloon_mutex);
+
+/*
+ * Protects atomic reservation decrease/increase against concurrent increases.
+ * Also protects non-atomic updates of current_pages and driver_pages, and
+ * balloon lists.
+ */
 spinlock_t balloon_lock = SPIN_LOCK_UNLOCKED;
 
 /* We aim for 'current allocation' == 'target allocation'. */
@@ -156,6 +163,146 @@
        return target;
 }
 
+static int increase_reservation(unsigned long nr_pages)
+{
+       unsigned long *mfn_list, pfn, i, flags;
+       struct page   *page;
+       long           rc;
+       struct xen_memory_reservation reservation = {
+               .address_bits = 0,
+               .extent_order = 0,
+               .domid        = DOMID_SELF
+       };
+
+       if (nr_pages > (PAGE_SIZE / sizeof(unsigned long)))
+               nr_pages = PAGE_SIZE / sizeof(unsigned long);
+
+       mfn_list = (unsigned long *)__get_free_page(GFP_KERNEL);
+       if (mfn_list == NULL)
+               return -ENOMEM;
+
+       balloon_lock(flags);
+
+       reservation.extent_start = mfn_list;
+       reservation.nr_extents   = nr_pages;
+       rc = HYPERVISOR_memory_op(
+               XENMEM_increase_reservation, &reservation);
+       if (rc < nr_pages) {
+               /* We hit the Xen hard limit: reprobe. */
+               reservation.extent_start = mfn_list;
+               reservation.nr_extents   = rc;
+               BUG_ON(HYPERVISOR_memory_op(
+                       XENMEM_decrease_reservation,
+                       &reservation) != rc);
+               hard_limit = current_pages + rc - driver_pages;
+               goto out;
+       }
+
+       for (i = 0; i < nr_pages; i++) {
+               page = balloon_retrieve();
+               BUG_ON(page == NULL);
+
+               pfn = page - mem_map;
+               BUG_ON(phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
+
+               /* Update P->M and M->P tables. */
+               phys_to_machine_mapping[pfn] = mfn_list[i];
+               xen_machphys_update(mfn_list[i], pfn);
+            
+               /* Link back into the page tables if not highmem. */
+               if (pfn < max_low_pfn)
+                       BUG_ON(HYPERVISOR_update_va_mapping(
+                               (unsigned long)__va(pfn << PAGE_SHIFT),
+                               pfn_pte_ma(mfn_list[i], PAGE_KERNEL),
+                               0));
+
+               /* Relinquish the page back to the allocator. */
+               ClearPageReserved(page);
+               set_page_count(page, 1);
+               __free_page(page);
+       }
+
+       current_pages += nr_pages;
+
+ out:
+       balloon_unlock(flags);
+
+       free_page((unsigned long)mfn_list);
+
+       return 0;
+}
+
+static int decrease_reservation(unsigned long nr_pages)
+{
+       unsigned long *mfn_list, pfn, i, flags;
+       struct page   *page;
+       void          *v;
+       int            need_sleep = 0;
+       struct xen_memory_reservation reservation = {
+               .address_bits = 0,
+               .extent_order = 0,
+               .domid        = DOMID_SELF
+       };
+
+       if (nr_pages > (PAGE_SIZE / sizeof(unsigned long)))
+               nr_pages = PAGE_SIZE / sizeof(unsigned long);
+
+       mfn_list = (unsigned long *)__get_free_page(GFP_KERNEL);
+       if (mfn_list == NULL)
+               return -ENOMEM;
+
+       for (i = 0; i < nr_pages; i++) {
+               if ((page = alloc_page(GFP_HIGHUSER)) == NULL) {
+                       nr_pages = i;
+                       need_sleep = 1;
+                       break;
+               }
+
+               pfn = page - mem_map;
+               mfn_list[i] = phys_to_machine_mapping[pfn];
+
+               if (!PageHighMem(page)) {
+                       v = phys_to_virt(pfn << PAGE_SHIFT);
+                       scrub_pages(v, 1);
+                       BUG_ON(HYPERVISOR_update_va_mapping(
+                               (unsigned long)v, __pte_ma(0), 0));
+               }
+#ifdef CONFIG_XEN_SCRUB_PAGES
+               else {
+                       v = kmap(page);
+                       scrub_pages(v, 1);
+                       kunmap(page);
+               }
+#endif
+       }
+
+       /* Ensure that ballooned highmem pages don't have kmaps. */
+       kmap_flush_unused();
+       flush_tlb_all();
+
+       balloon_lock(flags);
+
+       /* No more mappings: invalidate P2M and add to balloon. */
+       for (i = 0; i < nr_pages; i++) {
+               pfn = mfn_to_pfn(mfn_list[i]);
+               phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY;
+               balloon_append(pfn_to_page(pfn));
+       }
+
+       reservation.extent_start = mfn_list;
+       reservation.nr_extents   = nr_pages;
+       BUG_ON(HYPERVISOR_memory_op(
+               XENMEM_decrease_reservation, &reservation) != nr_pages);
+
+       current_pages -= nr_pages;
+
+       balloon_unlock(flags);
+
+       free_page((unsigned long)mfn_list);
+
+       return need_sleep;
+}
+
 /*
  * We avoid multiple worker processes conflicting via the balloon mutex.
  * We may of course race updates of the target counts (which are protected
@@ -164,112 +311,23 @@
  */
 static void balloon_process(void *unused)
 {
-       unsigned long *mfn_list, pfn, i, flags;
-       struct page   *page;
-       long           credit, debt, rc;
-       void          *v;
+       int need_sleep = 0;
+       long credit;
 
        down(&balloon_mutex);
 
- retry:
-       mfn_list = NULL;
-
-       if ((credit = current_target() - current_pages) > 0) {
-               mfn_list = vmalloc(credit * sizeof(*mfn_list));
-               if (mfn_list == NULL)
-                       goto out;
-
-               balloon_lock(flags);
-               rc = HYPERVISOR_dom_mem_op(
-                       MEMOP_increase_reservation, mfn_list, credit, 0);
-               balloon_unlock(flags);
-               if (rc < credit) {
-                       /* We hit the Xen hard limit: reprobe. */
-                       BUG_ON(HYPERVISOR_dom_mem_op(
-                               MEMOP_decrease_reservation,
-                               mfn_list, rc, 0) != rc);
-                       hard_limit = current_pages + rc - driver_pages;
-                       vfree(mfn_list);
-                       goto retry;
-               }
-
-               for (i = 0; i < credit; i++) {
-                       page = balloon_retrieve();
-                       BUG_ON(page == NULL);
-
-                       pfn = page - mem_map;
-                       if (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY)
-                               BUG();
-
-                       /* Update P->M and M->P tables. */
-                       phys_to_machine_mapping[pfn] = mfn_list[i];
-                       xen_machphys_update(mfn_list[i], pfn);
-            
-                       /* Link back into the page tables if not highmem. */
-                       if (pfn < max_low_pfn)
-                               BUG_ON(HYPERVISOR_update_va_mapping(
-                                       (unsigned long)__va(pfn << PAGE_SHIFT),
-                                       pfn_pte_ma(mfn_list[i], PAGE_KERNEL),
-                                       0));
-
-                       /* Relinquish the page back to the allocator. */
-                       ClearPageReserved(page);
-                       set_page_count(page, 1);
-                       __free_page(page);
-               }
-
-               current_pages += credit;
-       } else if (credit < 0) {
-               debt = -credit;
-
-               mfn_list = vmalloc(debt * sizeof(*mfn_list));
-               if (mfn_list == NULL)
-                       goto out;
-
-               for (i = 0; i < debt; i++) {
-                       if ((page = alloc_page(GFP_HIGHUSER)) == NULL) {
-                               debt = i;
-                               break;
-                       }
-
-                       pfn = page - mem_map;
-                       mfn_list[i] = phys_to_machine_mapping[pfn];
-
-                       if (!PageHighMem(page)) {
-                               v = phys_to_virt(pfn << PAGE_SHIFT);
-                               scrub_pages(v, 1);
-                               BUG_ON(HYPERVISOR_update_va_mapping(
-                                       (unsigned long)v, __pte_ma(0), 0));
-                       }
-#ifdef CONFIG_XEN_SCRUB_PAGES
-                       else {
-                               v = kmap(page);
-                               scrub_pages(v, 1);
-                               kunmap(page);
-                       }
+       do {
+               credit = current_target() - current_pages;
+               if (credit > 0)
+                       need_sleep = (increase_reservation(credit) != 0);
+               if (credit < 0)
+                       need_sleep = (decrease_reservation(-credit) != 0);
+
+#ifndef CONFIG_PREEMPT
+               if (need_resched())
+                       schedule();
 #endif
-               }
-
-               /* Ensure that ballooned highmem pages don't have kmaps. */
-               kmap_flush_unused();
-               flush_tlb_all();
-
-               /* No more mappings: invalidate P2M and add to balloon. */
-               for (i = 0; i < debt; i++) {
-                       pfn = mfn_to_pfn(mfn_list[i]);
-                       phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY;
-                       balloon_append(pfn_to_page(pfn));
-               }
-
-               BUG_ON(HYPERVISOR_dom_mem_op(
-                       MEMOP_decrease_reservation,mfn_list, debt, 0) != debt);
-
-               current_pages -= debt;
-       }
-
- out:
-       if (mfn_list != NULL)
-               vfree(mfn_list);
+       } while ((credit != 0) && !need_sleep);
 
        /* Schedule more work if there is some still to be done. */
        if (current_target() != current_pages)
@@ -295,10 +353,10 @@
 /* React to a change in the target key */
 static void watch_target(struct xenbus_watch *watch, const char *node)
 {
-       unsigned long new_target;
+       unsigned long long new_target;
        int err;
 
-       err = xenbus_scanf("memory", "target", "%lu", &new_target);
+       err = xenbus_scanf("memory", "target", "%llu", &new_target);
        if (err != 1) {
                printk(KERN_ERR "Unable to read memory/target\n");
                return;
@@ -390,7 +448,7 @@
 
        IPRINTK("Initialising balloon driver.\n");
 
-       current_pages = min(xen_start_info.nr_pages, max_pfn);
+       current_pages = min(xen_start_info->nr_pages, max_pfn);
        target_pages  = current_pages;
        balloon_low   = 0;
        balloon_high  = 0;
@@ -410,7 +468,7 @@
        balloon_pde->write_proc = balloon_write;
     
        /* Initialise the balloon with excess memory space. */
-       for (pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++) {
+       for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
                page = &mem_map[pfn];
                if (!PageReserved(page))
                        balloon_append(page);
@@ -429,8 +487,9 @@
 void balloon_update_driver_allowance(long delta)
 {
        unsigned long flags;
+
        balloon_lock(flags);
-       driver_pages += delta; /* non-atomic update */
+       driver_pages += delta;
        balloon_unlock(flags);
 }
 
@@ -438,11 +497,17 @@
        pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
 {
        unsigned long mfn = pte_mfn(*pte);
+       struct xen_memory_reservation reservation = {
+               .extent_start = &mfn,
+               .nr_extents   = 1,
+               .extent_order = 0,
+               .domid        = DOMID_SELF
+       };
        set_pte(pte, __pte_ma(0));
        phys_to_machine_mapping[__pa(addr) >> PAGE_SHIFT] =
                INVALID_P2M_ENTRY;
-       BUG_ON(HYPERVISOR_dom_mem_op(
-               MEMOP_decrease_reservation, &mfn, 1, 0) != 1);
+       BUG_ON(HYPERVISOR_memory_op(
+               XENMEM_decrease_reservation, &reservation) != 1);
        return 0;
 }
 
@@ -457,9 +522,10 @@
 
        scrub_pages(vstart, 1 << order);
 
-       balloon_lock(flags);
        BUG_ON(generic_page_range(
                &init_mm, vstart, PAGE_SIZE << order, dealloc_pte_fn, NULL));
+
+       balloon_lock(flags);
        current_pages -= 1UL << order;
        balloon_unlock(flags);
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c        Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c        Fri Sep  9 
16:30:54 2005
@@ -504,8 +504,8 @@
     int i;
     struct page *page;
 
-    if ( !(xen_start_info.flags & SIF_INITDOMAIN) &&
-         !(xen_start_info.flags & SIF_BLK_BE_DOMAIN) )
+    if ( !(xen_start_info->flags & SIF_INITDOMAIN) &&
+         !(xen_start_info->flags & SIF_BLK_BE_DOMAIN) )
         return 0;
 
     blkif_interface_init();
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c      Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c      Fri Sep  9 
16:30:54 2005
@@ -32,23 +32,15 @@
  */
 
 #if 1
-#define ASSERT(_p) \
-    if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
-    __LINE__, __FILE__); *(int*)0=0; }
+#define ASSERT(p)                                                         \
+       if (!(p)) { printk("Assertion '%s' failed, line %d, file %s", #p , \
+       __LINE__, __FILE__); *(int*)0=0; }
 #else
 #define ASSERT(_p)
 #endif
 
 #include <linux/version.h>
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 #include "block.h"
-#else
-#include "common.h"
-#include <linux/blk.h>
-#include <linux/tqueue.h>
-#endif
-
 #include <linux/cdrom.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
@@ -58,90 +50,57 @@
 #include <asm-xen/xen-public/grant_table.h>
 #include <asm-xen/gnttab.h>
 
-typedef unsigned char byte; /* from linux/ide.h */
-
-/* Control whether runtime update of vbds is enabled. */
-#define ENABLE_VBD_UPDATE 1
-
 #define BLKIF_STATE_DISCONNECTED 0
 #define BLKIF_STATE_CONNECTED    1
 
 static unsigned int blkif_state = BLKIF_STATE_DISCONNECTED;
-
-#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
 
 #define MAXIMUM_OUTSTANDING_BLOCK_REQS \
     (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE)
 #define GRANTREF_INVALID (1<<15)
-
-static struct blk_shadow {
-    blkif_request_t req;
-    unsigned long request;
-    unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-} blk_shadow[BLK_RING_SIZE];
-unsigned long blk_shadow_free;
+#define GRANT_INVALID_REF      (0xFFFF)
 
 static int recovery = 0; /* Recovery in progress: protected by blkif_io_lock */
 
 static void kick_pending_request_queues(struct blkfront_info *info);
 
-static int __init xlblk_init(void);
-
 static void blkif_completion(struct blk_shadow *s);
 
-static inline int GET_ID_FROM_FREELIST(void)
-{
-    unsigned long free = blk_shadow_free;
-    BUG_ON(free > BLK_RING_SIZE);
-    blk_shadow_free = blk_shadow[free].req.id;
-    blk_shadow[free].req.id = 0x0fffffee; /* debug */
-    return free;
-}
-
-static inline void ADD_ID_TO_FREELIST(unsigned long id)
-{
-    blk_shadow[id].req.id  = blk_shadow_free;
-    blk_shadow[id].request = 0;
-    blk_shadow_free = id;
-}
-
-
-/************************  COMMON CODE  (inlined)  ************************/
-
-/* Kernel-specific definitions used in the common code */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-#define DISABLE_SCATTERGATHER()
-#else
-static int sg_operation = -1;
-#define DISABLE_SCATTERGATHER() (sg_operation = -1)
-#endif
+static inline int GET_ID_FROM_FREELIST(
+       struct blkfront_info *info)
+{
+       unsigned long free = info->shadow_free;
+       BUG_ON(free > BLK_RING_SIZE);
+       info->shadow_free = info->shadow[free].req.id;
+       info->shadow[free].req.id = 0x0fffffee; /* debug */
+       return free;
+}
+
+static inline void ADD_ID_TO_FREELIST(
+       struct blkfront_info *info, unsigned long id)
+{
+       info->shadow[id].req.id  = info->shadow_free;
+       info->shadow[id].request = 0;
+       info->shadow_free = id;
+}
 
 static inline void pickle_request(struct blk_shadow *s, blkif_request_t *r)
 {
 
-    s->req = *r;
+       s->req = *r;
 }
 
 static inline void unpickle_request(blkif_request_t *r, struct blk_shadow *s)
 {
 
-    *r = s->req;
-}
-
+       *r = s->req;
+}
 
 static inline void flush_requests(struct blkfront_info *info)
 {
-    DISABLE_SCATTERGATHER();
-    RING_PUSH_REQUESTS(&info->ring);
-    notify_via_evtchn(info->evtchn);
-}
-
-
-/**************************  KERNEL VERSION 2.6  **************************/
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-
-module_init(xlblk_init);
+       RING_PUSH_REQUESTS(&info->ring);
+       notify_via_evtchn(info->evtchn);
+}
 
 static void kick_pending_request_queues(struct blkfront_info *info)
 {
@@ -169,50 +128,44 @@
 
 int blkif_open(struct inode *inode, struct file *filep)
 {
-       // struct gendisk *gd = inode->i_bdev->bd_disk;
-       // struct xlbd_disk_info *di = (struct xlbd_disk_info 
*)gd->private_data;
-
-       /* Update of usage count is protected by per-device semaphore. */
-       // di->mi->usage++;
-
        return 0;
 }
 
 
 int blkif_release(struct inode *inode, struct file *filep)
 {
-    /* FIXME: This is where we can actually free up majors, etc. --RR */
-    return 0;
+       return 0;
 }
 
 
 int blkif_ioctl(struct inode *inode, struct file *filep,
                 unsigned command, unsigned long argument)
 {
-    int i;
-
-    DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
-                  command, (long)argument, inode->i_rdev);
-
-    switch ( command )
-    {
-    case HDIO_GETGEO:
-        /* return ENOSYS to use defaults */
-        return -ENOSYS;
-
-    case CDROMMULTISESSION:
-        DPRINTK("FIXME: support multisession CDs later\n");
-        for ( i = 0; i < sizeof(struct cdrom_multisession); i++ )
-            if ( put_user(0, (byte *)(argument + i)) ) return -EFAULT;
-        return 0;
-
-    default:
-        /*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n",
-          command);*/
-        return -EINVAL; /* same return as native Linux */
-    }
-
-    return 0;
+       int i;
+
+       DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
+                     command, (long)argument, inode->i_rdev);
+
+       switch ( command )
+       {
+       case HDIO_GETGEO:
+               /* return ENOSYS to use defaults */
+               return -ENOSYS;
+
+       case CDROMMULTISESSION:
+               DPRINTK("FIXME: support multisession CDs later\n");
+               for (i = 0; i < sizeof(struct cdrom_multisession); i++)
+                       if (put_user(0, (char *)(argument + i)))
+                               return -EFAULT;
+               return 0;
+
+       default:
+               /*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n",
+                 command);*/
+               return -EINVAL; /* same return as native Linux */
+       }
+
+       return 0;
 }
 
 
@@ -228,76 +181,77 @@
  */
 static int blkif_queue_request(struct request *req)
 {
-    struct blkfront_info *info = req->rq_disk->private_data;
-    unsigned long buffer_ma;
-    blkif_request_t *ring_req;
-    struct bio *bio;
-    struct bio_vec *bvec;
-    int idx;
-    unsigned long id;
-    unsigned int fsect, lsect;
-    int ref;
-    grant_ref_t gref_head;
-
-    if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
-        return 1;
-
-    if (gnttab_alloc_grant_references(BLKIF_MAX_SEGMENTS_PER_REQUEST,
-                                     &gref_head) < 0) {
-           gnttab_request_free_callback(&info->callback,
-                                        blkif_restart_queue_callback, info,
-                                        BLKIF_MAX_SEGMENTS_PER_REQUEST);
-           return 1;
-    }
-
-    /* Fill out a communications ring structure. */
-    ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
-    id = GET_ID_FROM_FREELIST();
-    blk_shadow[id].request = (unsigned long)req;
-
-    ring_req->id = id;
-    ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE : BLKIF_OP_READ;
-    ring_req->sector_number = (blkif_sector_t)req->sector;
-    ring_req->handle = info->handle;
-
-    ring_req->nr_segments = 0;
-    rq_for_each_bio(bio, req)
-    {
-        bio_for_each_segment(bvec, bio, idx)
-        {
-            if ( ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST )
-                BUG();
-            buffer_ma = page_to_phys(bvec->bv_page);
-            fsect = bvec->bv_offset >> 9;
-            lsect = fsect + (bvec->bv_len >> 9) - 1;
-            /* install a grant reference. */
-            ref = gnttab_claim_grant_reference(&gref_head);
-            ASSERT( ref != -ENOSPC );
-
-            gnttab_grant_foreign_access_ref(
-                        ref,
-                        info->backend_id,
-                        buffer_ma >> PAGE_SHIFT,
-                        rq_data_dir(req) );
-
-            blk_shadow[id].frame[ring_req->nr_segments] =
-                buffer_ma >> PAGE_SHIFT;
-
-            ring_req->frame_and_sects[ring_req->nr_segments] =
-                blkif_fas_from_gref(ref, fsect, lsect);
-
-           ring_req->nr_segments++;
-        }
-    }
-
-    info->ring.req_prod_pvt++;
-
-    /* Keep a private copy so we can reissue requests when recovering. */
-    pickle_request(&blk_shadow[id], ring_req);
-
-    gnttab_free_grant_references(gref_head);
-
-    return 0;
+       struct blkfront_info *info = req->rq_disk->private_data;
+       unsigned long buffer_mfn;
+       blkif_request_t *ring_req;
+       struct bio *bio;
+       struct bio_vec *bvec;
+       int idx;
+       unsigned long id;
+       unsigned int fsect, lsect;
+       int ref;
+       grant_ref_t gref_head;
+
+       if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
+               return 1;
+
+       if (gnttab_alloc_grant_references(
+               BLKIF_MAX_SEGMENTS_PER_REQUEST, &gref_head) < 0) {
+               gnttab_request_free_callback(
+                       &info->callback,
+                       blkif_restart_queue_callback,
+                       info,
+                       BLKIF_MAX_SEGMENTS_PER_REQUEST);
+               return 1;
+       }
+
+       /* Fill out a communications ring structure. */
+       ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
+       id = GET_ID_FROM_FREELIST(info);
+       info->shadow[id].request = (unsigned long)req;
+
+       ring_req->id = id;
+       ring_req->operation = rq_data_dir(req) ?
+               BLKIF_OP_WRITE : BLKIF_OP_READ;
+       ring_req->sector_number = (blkif_sector_t)req->sector;
+       ring_req->handle = info->handle;
+
+       ring_req->nr_segments = 0;
+       rq_for_each_bio (bio, req) {
+               bio_for_each_segment (bvec, bio, idx) {
+                       BUG_ON(ring_req->nr_segments
+                              == BLKIF_MAX_SEGMENTS_PER_REQUEST);
+                       buffer_mfn = page_to_phys(bvec->bv_page) >> PAGE_SHIFT;
+                       fsect = bvec->bv_offset >> 9;
+                       lsect = fsect + (bvec->bv_len >> 9) - 1;
+                       /* install a grant reference. */
+                       ref = gnttab_claim_grant_reference(&gref_head);
+                       ASSERT(ref != -ENOSPC);
+
+                       gnttab_grant_foreign_access_ref(
+                               ref,
+                               info->backend_id,
+                               buffer_mfn,
+                               rq_data_dir(req) );
+
+                       info->shadow[id].frame[ring_req->nr_segments] =
+                               buffer_mfn;
+
+                       ring_req->frame_and_sects[ring_req->nr_segments] =
+                               blkif_fas_from_gref(ref, fsect, lsect);
+
+                       ring_req->nr_segments++;
+               }
+       }
+
+       info->ring.req_prod_pvt++;
+
+       /* Keep a private copy so we can reissue requests when recovering. */
+       pickle_request(&info->shadow[id], ring_req);
+
+       gnttab_free_grant_references(gref_head);
+
+       return 0;
 }
 
 /*
@@ -306,756 +260,200 @@
  */
 void do_blkif_request(request_queue_t *rq)
 {
-    struct blkfront_info *info = NULL;
-    struct request *req;
-    int queued;
-
-    DPRINTK("Entered do_blkif_request\n");
-
-    queued = 0;
-
-    while ( (req = elv_next_request(rq)) != NULL )
-    {
-       info = req->rq_disk->private_data;
-
-        if ( !blk_fs_request(req) )
-        {
-            end_request(req, 0);
-            continue;
-        }
-
-       if (RING_FULL(&info->ring))
-               goto wait;
-
-        DPRINTK("do_blk_req %p: cmd %p, sec %lx, (%u/%li) buffer:%p [%s]\n",
-                req, req->cmd, req->sector, req->current_nr_sectors,
-                req->nr_sectors, req->buffer,
-                rq_data_dir(req) ? "write" : "read");
-
-        blkdev_dequeue_request(req);
-        if (blkif_queue_request(req)) {
-               blk_requeue_request(rq, req);
-        wait:
-               /* Avoid pointless unplugs. */
-               blk_stop_queue(rq);
-               break;
-        }
-
-        queued++;
-    }
-
-    if ( queued != 0 )
-        flush_requests(info);
+       struct blkfront_info *info = NULL;
+       struct request *req;
+       int queued;
+
+       DPRINTK("Entered do_blkif_request\n");
+
+       queued = 0;
+
+       while ((req = elv_next_request(rq)) != NULL) {
+               info = req->rq_disk->private_data;
+
+               if (!blk_fs_request(req)) {
+                       end_request(req, 0);
+                       continue;
+               }
+
+               if (RING_FULL(&info->ring))
+                       goto wait;
+
+               DPRINTK("do_blk_req %p: cmd %p, sec %lx, "
+                       "(%u/%li) buffer:%p [%s]\n",
+                       req, req->cmd, req->sector, req->current_nr_sectors,
+                       req->nr_sectors, req->buffer,
+                       rq_data_dir(req) ? "write" : "read");
+
+               blkdev_dequeue_request(req);
+               if (blkif_queue_request(req)) {
+                       blk_requeue_request(rq, req);
+               wait:
+                       /* Avoid pointless unplugs. */
+                       blk_stop_queue(rq);
+                       break;
+               }
+
+               queued++;
+       }
+
+       if (queued != 0)
+               flush_requests(info);
 }
 
 
 static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
 {
-    struct request *req;
-    blkif_response_t *bret;
-    RING_IDX i, rp;
-    unsigned long flags;
-    struct blkfront_info *info = (struct blkfront_info *)dev_id;
-
-    spin_lock_irqsave(&blkif_io_lock, flags);
-
-    if (unlikely(info->connected != BLKIF_STATE_CONNECTED || recovery)) {
-        spin_unlock_irqrestore(&blkif_io_lock, flags);
-        return IRQ_HANDLED;
-    }
-
-    rp = info->ring.sring->rsp_prod;
-    rmb(); /* Ensure we see queued responses up to 'rp'. */
-
-    for ( i = info->ring.rsp_cons; i != rp; i++ )
-    {
-        unsigned long id;
-
-        bret = RING_GET_RESPONSE(&info->ring, i);
-        id   = bret->id;
-        req  = (struct request *)blk_shadow[id].request;
-
-        blkif_completion(&blk_shadow[id]);
-
-        ADD_ID_TO_FREELIST(id);
-
-        switch ( bret->operation )
-        {
-        case BLKIF_OP_READ:
-        case BLKIF_OP_WRITE:
-            if ( unlikely(bret->status != BLKIF_RSP_OKAY) )
-                DPRINTK("Bad return from blkdev data request: %x\n",
-                        bret->status);
-
-            if ( unlikely(end_that_request_first
-                          (req,
-                           (bret->status == BLKIF_RSP_OKAY),
-                           req->hard_nr_sectors)) )
-                BUG();
-            end_that_request_last(req);
-
-            break;
-        default:
-            BUG();
-        }
-    }
-
-    info->ring.rsp_cons = i;
-
-    kick_pending_request_queues(info);
-
-    spin_unlock_irqrestore(&blkif_io_lock, flags);
-
-    return IRQ_HANDLED;
-}
-
-#else
-/**************************  KERNEL VERSION 2.4  **************************/
-
-static kdev_t        sg_dev;
-static unsigned long sg_next_sect;
-
-/*
- * Request queues with outstanding work, but ring is currently full.
- * We need no special lock here, as we always access this with the
- * blkif_io_lock held. We only need a small maximum list.
- */
-#define MAX_PENDING 8
-static request_queue_t *pending_queues[MAX_PENDING];
-static int nr_pending;
-
-
-#define blkif_io_lock io_request_lock
-
-/*============================================================================*/
-static void kick_pending_request_queues(void)
-{
-    /* We kick pending request queues if the ring is reasonably empty. */
-    if ( (nr_pending != 0) &&
-         (RING_PENDING_REQUESTS(&info->ring) < (BLK_RING_SIZE >> 1)) )
-    {
-        /* Attempt to drain the queue, but bail if the ring becomes full. */
-        while ( (nr_pending != 0) && !RING_FULL(&info->ring) )
-            do_blkif_request(pending_queues[--nr_pending]);
-    }
-}
-
-int blkif_open(struct inode *inode, struct file *filep)
-{
-    short xldev = inode->i_rdev;
-    struct gendisk *gd = get_gendisk(xldev);
-    xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev);
-    short minor = MINOR(xldev);
-
-    if ( gd->part[minor].nr_sects == 0 )
-    {
-        /*
-         * Device either doesn't exist, or has zero capacity; we use a few
-         * cheesy heuristics to return the relevant error code
-         */
-        if ( (gd->sizes[minor >> gd->minor_shift] != 0) ||
-             ((minor & (gd->max_p - 1)) != 0) )
-        {
-            /*
-             * We have a real device, but no such partition, or we just have a
-             * partition number so guess this is the problem.
-             */
-            return -ENXIO;     /* no such device or address */
-        }
-        else if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE )
-        {
-            /* This is a removable device => assume that media is missing. */
-            return -ENOMEDIUM; /* media not present (this is a guess) */
-        }
-        else
-        {
-            /* Just go for the general 'no such device' error. */
-            return -ENODEV;    /* no such device */
-        }
-    }
-
-    /* Update of usage count is protected by per-device semaphore. */
-    disk->usage++;
-
-    return 0;
-}
-
-
-int blkif_release(struct inode *inode, struct file *filep)
-{
-    xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev);
-
-    /*
-     * When usage drops to zero it may allow more VBD updates to occur.
-     * Update of usage count is protected by a per-device semaphore.
-     */
-    if ( --disk->usage == 0 ) {
-        vbd_update();
-    }
-
-    return 0;
-}
-
-
-int blkif_ioctl(struct inode *inode, struct file *filep,
-                unsigned command, unsigned long argument)
-{
-    kdev_t dev = inode->i_rdev;
-    struct hd_geometry *geo = (struct hd_geometry *)argument;
-    struct gendisk *gd;
-    struct hd_struct *part;
-    int i;
-    unsigned short cylinders;
-    byte heads, sectors;
-
-    /* NB. No need to check permissions. That is done for us. */
-
-    DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
-                  command, (long) argument, dev);
-
-    gd = get_gendisk(dev);
-    part = &gd->part[MINOR(dev)];
-
-    switch ( command )
-    {
-    case BLKGETSIZE:
-        DPRINTK_IOCTL("   BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects);
-        return put_user(part->nr_sects, (unsigned long *) argument);
-
-    case BLKGETSIZE64:
-        DPRINTK_IOCTL("   BLKGETSIZE64: %x %llx\n", BLKGETSIZE64,
-                      (u64)part->nr_sects * 512);
-        return put_user((u64)part->nr_sects * 512, (u64 *) argument);
-
-    case BLKRRPART:                               /* re-read partition table */
-        DPRINTK_IOCTL("   BLKRRPART: %x\n", BLKRRPART);
-        return blkif_revalidate(dev);
-
-    case BLKSSZGET:
-        return hardsect_size[MAJOR(dev)][MINOR(dev)];
-
-    case BLKBSZGET:                                        /* get block size */
-        DPRINTK_IOCTL("   BLKBSZGET: %x\n", BLKBSZGET);
-        break;
-
-    case BLKBSZSET:                                        /* set block size */
-        DPRINTK_IOCTL("   BLKBSZSET: %x\n", BLKBSZSET);
-        break;
-
-    case BLKRASET:                                         /* set read-ahead */
-        DPRINTK_IOCTL("   BLKRASET: %x\n", BLKRASET);
-        break;
-
-    case BLKRAGET:                                         /* get read-ahead */
-        DPRINTK_IOCTL("   BLKRAFET: %x\n", BLKRAGET);
-        break;
-
-    case HDIO_GETGEO:
-        DPRINTK_IOCTL("   HDIO_GETGEO: %x\n", HDIO_GETGEO);
-        if (!argument) return -EINVAL;
-
-        /* We don't have real geometry info, but let's at least return
-           values consistent with the size of the device */
-
-        heads = 0xff;
-        sectors = 0x3f;
-        cylinders = part->nr_sects / (heads * sectors);
-
-        if (put_user(0x00,  (unsigned long *) &geo->start)) return -EFAULT;
-        if (put_user(heads,  (byte *)&geo->heads)) return -EFAULT;
-        if (put_user(sectors,  (byte *)&geo->sectors)) return -EFAULT;
-        if (put_user(cylinders, (unsigned short *)&geo->cylinders)) return 
-EFAULT;
-
-        return 0;
-
-    case HDIO_GETGEO_BIG:
-        DPRINTK_IOCTL("   HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG);
-        if (!argument) return -EINVAL;
-
-        /* We don't have real geometry info, but let's at least return
-           values consistent with the size of the device */
-
-        heads = 0xff;
-        sectors = 0x3f;
-        cylinders = part->nr_sects / (heads * sectors);
-
-        if (put_user(0x00,  (unsigned long *) &geo->start))  return -EFAULT;
-        if (put_user(heads,  (byte *)&geo->heads))   return -EFAULT;
-        if (put_user(sectors,  (byte *)&geo->sectors)) return -EFAULT;
-        if (put_user(cylinders, (unsigned int *) &geo->cylinders)) return 
-EFAULT;
-
-        return 0;
-
-    case CDROMMULTISESSION:
-        DPRINTK("FIXME: support multisession CDs later\n");
-        for ( i = 0; i < sizeof(struct cdrom_multisession); i++ )
-            if ( put_user(0, (byte *)(argument + i)) ) return -EFAULT;
-        return 0;
-
-    case SCSI_IOCTL_GET_BUS_NUMBER:
-        DPRINTK("FIXME: SCSI_IOCTL_GET_BUS_NUMBER ioctl in XL blkif");
-        return -ENOSYS;
-
-    default:
-        WPRINTK("ioctl %08x not supported by XL blkif\n", command);
-        return -ENOSYS;
-    }
-
-    return 0;
-}
-
-
-
-/* check media change: should probably do something here in some cases :-) */
-int blkif_check(kdev_t dev)
-{
-    DPRINTK("blkif_check\n");
-    return 0;
-}
-
-int blkif_revalidate(kdev_t dev)
-{
-    struct block_device *bd;
-    struct gendisk *gd;
-    xl_disk_t *disk;
-    unsigned long capacity;
-    int i, rc = 0;
-
-    if ( (bd = bdget(dev)) == NULL )
-        return -EINVAL;
-
-    /*
-     * Update of partition info, and check of usage count, is protected
-     * by the per-block-device semaphore.
-     */
-    down(&bd->bd_sem);
-
-    if ( ((gd = get_gendisk(dev)) == NULL) ||
-         ((disk = xldev_to_xldisk(dev)) == NULL) ||
-         ((capacity = gd->part[MINOR(dev)].nr_sects) == 0) )
-    {
-        rc = -EINVAL;
-        goto out;
-    }
-
-    if ( disk->usage > 1 )
-    {
-        rc = -EBUSY;
-        goto out;
-    }
-
-    /* Only reread partition table if VBDs aren't mapped to partitions. */
-    if ( !(gd->flags[MINOR(dev) >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) )
-    {
-        for ( i = gd->max_p - 1; i >= 0; i-- )
-        {
-            invalidate_device(dev+i, 1);
-            gd->part[MINOR(dev+i)].start_sect = 0;
-            gd->part[MINOR(dev+i)].nr_sects   = 0;
-            gd->sizes[MINOR(dev+i)]           = 0;
-        }
-
-        grok_partitions(gd, MINOR(dev)>>gd->minor_shift, gd->max_p, capacity);
-    }
-
- out:
-    up(&bd->bd_sem);
-    bdput(bd);
-    return rc;
-}
-
-
-/*
- * blkif_queue_request
- *
- * request block io
- * 
- * id: for guest use only.
- * operation: BLKIF_OP_{READ,WRITE,PROBE}
- * buffer: buffer to read/write into. this should be a
- *   virtual address in the guest os.
- */
-static int blkif_queue_request(unsigned long   id,
-                               int             operation,
-                               char *          buffer,
-                               unsigned long   sector_number,
-                               unsigned short  nr_sectors,
-                               kdev_t          device,
-                              blkif_vdev_t    handle)
-{
-    unsigned long       buffer_ma = virt_to_bus(buffer);
-    unsigned long       xid;
-    struct gendisk     *gd;
-    blkif_request_t    *req;
-    struct buffer_head *bh;
-    unsigned int        fsect, lsect;
-    int ref;
-
-    fsect = (buffer_ma & ~PAGE_MASK) >> 9;
-    lsect = fsect + nr_sectors - 1;
-
-    /* Buffer must be sector-aligned. Extent mustn't cross a page boundary. */
-    if ( unlikely((buffer_ma & ((1<<9)-1)) != 0) )
-        BUG();
-    if ( lsect > ((PAGE_SIZE/512)-1) )
-        BUG();
-
-    buffer_ma &= PAGE_MASK;
-
-    if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
-        return 1;
-
-    switch ( operation )
-    {
-
-    case BLKIF_OP_READ:
-    case BLKIF_OP_WRITE:
-        gd = get_gendisk(device);
-
-        /*
-         * Update the sector_number we'll pass down as appropriate; note that
-         * we could sanity check that resulting sector will be in this
-         * partition, but this will happen in driver backend anyhow.
-         */
-        sector_number += gd->part[MINOR(device)].start_sect;
-
-        /*
-         * If this unit doesn't consist of virtual partitions then we clear
-         * the partn bits from the device number.
-         */
-        if ( !(gd->flags[MINOR(device)>>gd->minor_shift] &
-               GENHD_FL_VIRT_PARTNS) )
-            device &= ~(gd->max_p - 1);
-
-        if ( (sg_operation == operation) &&
-             (sg_dev == device) &&
-             (sg_next_sect == sector_number) )
-        {
-            req = RING_GET_REQUEST(&info->ring,
-                                   info->ring.req_prod_pvt - 1);
-            bh = (struct buffer_head *)id;
-
-            bh->b_reqnext = (struct buffer_head *)blk_shadow[req->id].request;
-            blk_shadow[req->id].request = (unsigned long)id;
-
-            /* install a grant reference. */
-            ref = gnttab_claim_grant_reference(&gref_head);
-            ASSERT( ref != -ENOSPC );
-
-            gnttab_grant_foreign_access_ref(
-                        ref,
-                        info->backend_id,
-                        buffer_ma >> PAGE_SHIFT,
-                        ( operation == BLKIF_OP_WRITE ? 1 : 0 ) );
-
-            blk_shadow[req->id].frame[req->nr_segments] =
-                buffer_ma >> PAGE_SHIFT;
-
-            req->frame_and_sects[req->nr_segments] =
-                blkif_fas_from_gref(ref, fsect, lsect);
-            if ( ++req->nr_segments < BLKIF_MAX_SEGMENTS_PER_REQUEST )
-                sg_next_sect += nr_sectors;
-            else
-                DISABLE_SCATTERGATHER();
-
-            /* Update the copy of the request in the recovery ring. */
-            pickle_request(&blk_shadow[req->id], req );
-
-            return 0;
-        }
-        else if ( RING_FULL(&info->ring) )
-        {
-            return 1;
-        }
-        else
-        {
-            sg_operation = operation;
-            sg_dev       = device;
-            sg_next_sect = sector_number + nr_sectors;
-        }
-        break;
-
-    default:
-        panic("unknown op %d\n", operation);
-    }
-
-    /* Fill out a communications ring structure. */
-    req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
-
-    xid = GET_ID_FROM_FREELIST();
-    blk_shadow[xid].request = (unsigned long)id;
-
-    req->id            = xid;
-    req->operation     = operation;
-    req->sector_number = (blkif_sector_t)sector_number;
-    req->handle        = handle;
-    req->nr_segments   = 1;
-    /* install a grant reference. */
-    ref = gnttab_claim_grant_reference(&gref_head);
-    ASSERT( ref != -ENOSPC );
-
-    gnttab_grant_foreign_access_ref(
-                ref,
-                info->backend_id,
-                buffer_ma >> PAGE_SHIFT,
-                ( operation == BLKIF_OP_WRITE ? 1 : 0 ) );
-
-    blk_shadow[xid].frame[0] = buffer_ma >> PAGE_SHIFT;
-
-    req->frame_and_sects[0] = blkif_fas_from_gref(ref, fsect, lsect);
-
-    /* Keep a private copy so we can reissue requests when recovering. */
-    pickle_request(&blk_shadow[xid], req);
-
-    info->ring.req_prod_pvt++;
-
-    return 0;
-}
-
-
-/*
- * do_blkif_request
- *  read a block; request is in a request queue
- */
-void do_blkif_request(request_queue_t *rq)
-{
-    struct request *req;
-    struct buffer_head *bh, *next_bh;
-    int rw, nsect, full, queued = 0;
-
-    DPRINTK("Entered do_blkif_request\n");
-
-    while ( !rq->plugged && !list_empty(&rq->queue_head))
-    {
-        if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL )
-            goto out;
-
-        DPRINTK("do_blkif_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n",
-                req, req->cmd, req->sector,
-                req->current_nr_sectors, req->nr_sectors, req->bh);
-
-        rw = req->cmd;
-        if ( rw == READA )
-            rw = READ;
-        if ( unlikely((rw != READ) && (rw != WRITE)) )
-            panic("XenoLinux Virtual Block Device: bad cmd: %d\n", rw);
-
-        req->errors = 0;
-
-        bh = req->bh;
-        while ( bh != NULL )
-        {
-            next_bh = bh->b_reqnext;
-            bh->b_reqnext = NULL;
-
-            full = blkif_queue_request(
-                (unsigned long)bh,
-                (rw == READ) ? BLKIF_OP_READ : BLKIF_OP_WRITE,
-                bh->b_data, bh->b_rsector, bh->b_size>>9, bh->b_rdev);
-
-            if ( full )
-            {
-                bh->b_reqnext = next_bh;
-                pending_queues[nr_pending++] = rq;
-                if ( unlikely(nr_pending >= MAX_PENDING) )
-                    BUG();
-                goto out;
-            }
-
-            queued++;
-
-            /* Dequeue the buffer head from the request. */
-            nsect = bh->b_size >> 9;
-            bh = req->bh = next_bh;
-
-            if ( bh != NULL )
-            {
-                /* There's another buffer head to do. Update the request. */
-                req->hard_sector += nsect;
-                req->hard_nr_sectors -= nsect;
-                req->sector = req->hard_sector;
-                req->nr_sectors = req->hard_nr_sectors;
-                req->current_nr_sectors = bh->b_size >> 9;
-                req->buffer = bh->b_data;
-            }
-            else
-            {
-                /* That was the last buffer head. Finalise the request. */
-                if ( unlikely(end_that_request_first(req, 1, "XenBlk")) )
-                    BUG();
-                blkdev_dequeue_request(req);
-                end_that_request_last(req);
-            }
-        }
-    }
-
- out:
-    if ( queued != 0 )
-        flush_requests();
-}
-
-
-static void blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
-{
-    RING_IDX i, rp;
-    unsigned long flags;
-    struct buffer_head *bh, *next_bh;
-
-    spin_lock_irqsave(&io_request_lock, flags);
-
-    if ( unlikely(info->connected != BLKIF_STATE_CONNECTED || recovery) )
-    {
-        spin_unlock_irqrestore(&io_request_lock, flags);
-        return;
-    }
-
-    rp = info->ring.sring->rsp_prod;
-    rmb(); /* Ensure we see queued responses up to 'rp'. */
-
-    for ( i = info->ring.rsp_cons; i != rp; i++ )
-    {
-        unsigned long id;
-        blkif_response_t *bret;
-
-        bret = RING_GET_RESPONSE(&info->ring, i);
-        id = bret->id;
-        bh = (struct buffer_head *)blk_shadow[id].request;
-
-        blkif_completion(&blk_shadow[id]);
-
-        ADD_ID_TO_FREELIST(id);
-
-        switch ( bret->operation )
-        {
-        case BLKIF_OP_READ:
-        case BLKIF_OP_WRITE:
-            if ( unlikely(bret->status != BLKIF_RSP_OKAY) )
-                DPRINTK("Bad return from blkdev data request: %lx\n",
-                        bret->status);
-            for ( ; bh != NULL; bh = next_bh )
-            {
-                next_bh = bh->b_reqnext;
-                bh->b_reqnext = NULL;
-                bh->b_end_io(bh, bret->status == BLKIF_RSP_OKAY);
-            }
-
-            break;
-        case BLKIF_OP_PROBE:
-            memcpy(&blkif_control_rsp, bret, sizeof(*bret));
-            blkif_control_rsp_valid = 1;
-            break;
-        default:
-            BUG();
-        }
-
-    }
-    info->ring.rsp_cons = i;
-
-    kick_pending_request_queues();
-
-    spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
-#endif
-
-/*****************************  COMMON CODE  *******************************/
+       struct request *req;
+       blkif_response_t *bret;
+       RING_IDX i, rp;
+       unsigned long flags;
+       struct blkfront_info *info = (struct blkfront_info *)dev_id;
+
+       spin_lock_irqsave(&blkif_io_lock, flags);
+
+       if (unlikely(info->connected != BLKIF_STATE_CONNECTED || recovery)) {
+               spin_unlock_irqrestore(&blkif_io_lock, flags);
+               return IRQ_HANDLED;
+       }
+
+       rp = info->ring.sring->rsp_prod;
+       rmb(); /* Ensure we see queued responses up to 'rp'. */
+
+       for (i = info->ring.rsp_cons; i != rp; i++) {
+               unsigned long id;
+
+               bret = RING_GET_RESPONSE(&info->ring, i);
+               id   = bret->id;
+               req  = (struct request *)info->shadow[id].request;
+
+               blkif_completion(&info->shadow[id]);
+
+               ADD_ID_TO_FREELIST(info, id);
+
+               switch (bret->operation) {
+               case BLKIF_OP_READ:
+               case BLKIF_OP_WRITE:
+                       if (unlikely(bret->status != BLKIF_RSP_OKAY))
+                               DPRINTK("Bad return from blkdev data "
+                                       "request: %x\n", bret->status);
+
+                       BUG_ON(end_that_request_first(
+                               req, (bret->status == BLKIF_RSP_OKAY),
+                               req->hard_nr_sectors));
+                       end_that_request_last(req);
+                       break;
+               default:
+                       BUG();
+               }
+       }
+
+       info->ring.rsp_cons = i;
+
+       kick_pending_request_queues(info);
+
+       spin_unlock_irqrestore(&blkif_io_lock, flags);
+
+       return IRQ_HANDLED;
+}
 
 static void blkif_free(struct blkfront_info *info)
 {
-    /* Prevent new requests being issued until we fix things up. */
-    spin_lock_irq(&blkif_io_lock);
-    info->connected = BLKIF_STATE_DISCONNECTED;
-    spin_unlock_irq(&blkif_io_lock);
-
-    /* Free resources associated with old device channel. */
-    if ( info->ring.sring != NULL )
-    {
-        free_page((unsigned long)info->ring.sring);
-        info->ring.sring = NULL;
-    }
-    unbind_evtchn_from_irqhandler(info->evtchn, NULL);
-    info->evtchn = 0;
+       /* Prevent new requests being issued until we fix things up. */
+       spin_lock_irq(&blkif_io_lock);
+       info->connected = BLKIF_STATE_DISCONNECTED;
+       spin_unlock_irq(&blkif_io_lock);
+
+       /* Free resources associated with old device channel. */
+       if (info->ring.sring != NULL) {
+               free_page((unsigned long)info->ring.sring);
+               info->ring.sring = NULL;
+       }
+       if (info->ring_ref != GRANT_INVALID_REF)
+               gnttab_end_foreign_access(info->ring_ref, 0);
+       info->ring_ref = GRANT_INVALID_REF;
+       unbind_evtchn_from_irqhandler(info->evtchn, info); 
+       info->evtchn = 0;
 }
 
 static void blkif_recover(struct blkfront_info *info)
 {
-    int i;
-    blkif_request_t *req;
-    struct blk_shadow *copy;
-    int j;
-
-    /* Stage 1: Make a safe copy of the shadow state. */
-    copy = (struct blk_shadow *)kmalloc(sizeof(blk_shadow), GFP_KERNEL);
-    BUG_ON(copy == NULL);
-    memcpy(copy, blk_shadow, sizeof(blk_shadow));
-
-    /* Stage 2: Set up free list. */
-    memset(&blk_shadow, 0, sizeof(blk_shadow));
-    for ( i = 0; i < BLK_RING_SIZE; i++ )
-        blk_shadow[i].req.id = i+1;
-    blk_shadow_free = info->ring.req_prod_pvt;
-    blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
-
-    /* Stage 3: Find pending requests and requeue them. */
-    for ( i = 0; i < BLK_RING_SIZE; i++ )
-    {
-        /* Not in use? */
-        if ( copy[i].request == 0 )
-            continue;
-
-        /* Grab a request slot and unpickle shadow state into it. */
-        req = RING_GET_REQUEST(
-            &info->ring, info->ring.req_prod_pvt);
-        unpickle_request(req, &copy[i]);
-
-        /* We get a new request id, and must reset the shadow state. */
-        req->id = GET_ID_FROM_FREELIST();
-        memcpy(&blk_shadow[req->id], &copy[i], sizeof(copy[i]));
-
-        /* Rewrite any grant references invalidated by suspend/resume. */
-        for ( j = 0; j < req->nr_segments; j++ )
-        {
-            if ( req->frame_and_sects[j] & GRANTREF_INVALID )
-                gnttab_grant_foreign_access_ref(
-                    blkif_gref_from_fas(req->frame_and_sects[j]),
-                    info->backend_id,
-                    blk_shadow[req->id].frame[j],
-                    rq_data_dir((struct request *)
-                                blk_shadow[req->id].request));
-            req->frame_and_sects[j] &= ~GRANTREF_INVALID;
-        }
-        blk_shadow[req->id].req = *req;
-
-        info->ring.req_prod_pvt++;
-    }
-
-    kfree(copy);
-
-    recovery = 0;
-
-    /* info->ring->req_prod will be set when we flush_requests().*/
-    wmb();
-
-    /* Kicks things back into life. */
-    flush_requests(info);
-
-    /* Now safe to left other people use the interface. */
-    info->connected = BLKIF_STATE_CONNECTED;
+       int i;
+       blkif_request_t *req;
+       struct blk_shadow *copy;
+       int j;
+
+       /* Stage 1: Make a safe copy of the shadow state. */
+       copy = (struct blk_shadow *)kmalloc(sizeof(info->shadow), GFP_KERNEL);
+       BUG_ON(copy == NULL);
+       memcpy(copy, info->shadow, sizeof(info->shadow));
+
+       /* Stage 2: Set up free list. */
+       memset(&info->shadow, 0, sizeof(info->shadow));
+       for (i = 0; i < BLK_RING_SIZE; i++)
+               info->shadow[i].req.id = i+1;
+       info->shadow_free = info->ring.req_prod_pvt;
+       info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
+
+       /* Stage 3: Find pending requests and requeue them. */
+       for (i = 0; i < BLK_RING_SIZE; i++) {
+               /* Not in use? */
+               if (copy[i].request == 0)
+                       continue;
+
+               /* Grab a request slot and unpickle shadow state into it. */
+               req = RING_GET_REQUEST(
+                       &info->ring, info->ring.req_prod_pvt);
+               unpickle_request(req, &copy[i]);
+
+               /* We get a new request id, and must reset the shadow state. */
+               req->id = GET_ID_FROM_FREELIST(info);
+               memcpy(&info->shadow[req->id], &copy[i], sizeof(copy[i]));
+
+               /* Rewrite any grant references invalidated by susp/resume. */
+               for (j = 0; j < req->nr_segments; j++) {
+                       if ( req->frame_and_sects[j] & GRANTREF_INVALID )
+                               gnttab_grant_foreign_access_ref(
+                                       blkif_gref_from_fas(
+                                               req->frame_and_sects[j]),
+                                       info->backend_id,
+                                       info->shadow[req->id].frame[j],
+                                       rq_data_dir(
+                                               (struct request *)
+                                               info->shadow[req->id].request));
+                       req->frame_and_sects[j] &= ~GRANTREF_INVALID;
+               }
+               info->shadow[req->id].req = *req;
+
+               info->ring.req_prod_pvt++;
+       }
+
+       kfree(copy);
+
+       recovery = 0;
+
+       /* info->ring->req_prod will be set when we flush_requests().*/
+       wmb();
+
+       /* Kicks things back into life. */
+       flush_requests(info);
+
+       /* Now safe to left other people use the interface. */
+       info->connected = BLKIF_STATE_CONNECTED;
 }
 
 static void blkif_connect(struct blkfront_info *info, u16 evtchn)
 {
-    int err = 0;
-
-    info->evtchn = evtchn;
-
-    err = bind_evtchn_to_irqhandler(
-        info->evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", info);
-    if ( err != 0 )
-    {
-        WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err);
-        return;
-    }
+       int err = 0;
+
+       info->evtchn = evtchn;
+
+       err = bind_evtchn_to_irqhandler(
+               info->evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", info);
+       if (err != 0) {
+               WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err);
+               return;
+       }
 }
 
 
@@ -1107,6 +505,8 @@
        blkif_sring_t *sring;
        evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
        int err;
+
+       info->ring_ref = GRANT_INVALID_REF;
 
        sring = (void *)__get_free_page(GFP_KERNEL);
        if (!sring) {
@@ -1130,6 +530,7 @@
        err = HYPERVISOR_event_channel_op(&op);
        if (err) {
                gnttab_end_foreign_access(info->ring_ref, 0);
+               info->ring_ref = GRANT_INVALID_REF;
                free_page((unsigned long)info->ring.sring);
                info->ring.sring = 0;
                xenbus_dev_error(dev, err, "allocating event channel");
@@ -1227,9 +628,8 @@
 static int blkfront_probe(struct xenbus_device *dev,
                          const struct xenbus_device_id *id)
 {
-       int err;
+       int err, vdevice, i;
        struct blkfront_info *info;
-       int vdevice;
 
        /* FIXME: Use dynamic device id if this is not set. */
        err = xenbus_scanf(dev->nodename, "virtual-device", "%i", &vdevice);
@@ -1250,6 +650,12 @@
        info->connected = BLKIF_STATE_DISCONNECTED;
        info->mi = NULL;
        INIT_WORK(&info->work, blkif_restart_queue, (void *)info);
+
+       info->shadow_free = 0;
+       memset(info->shadow, 0, sizeof(info->shadow));
+       for (i = 0; i < BLK_RING_SIZE; i++)
+               info->shadow[i].req.id = i+1;
+       info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
 
        /* Front end dir is a number, which is used as the id. */
        info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0);
@@ -1329,55 +735,57 @@
 
 static int wait_for_blkif(void)
 {
-    int err = 0;
-    int i;
-
-    /*
-     * We should figure out how many and which devices we need to
-     * proceed and only wait for those.  For now, continue once the
-     * first device is around.
-     */
-    for ( i=0; blkif_state != BLKIF_STATE_CONNECTED && (i < 10*HZ); i++ )
-    {
-        set_current_state(TASK_INTERRUPTIBLE);
-        schedule_timeout(1);
-    }
-
-    if ( blkif_state != BLKIF_STATE_CONNECTED )
-    {
-        WPRINTK("Timeout connecting to device!\n");
-        err = -ENOSYS;
-    }
-    return err;
+       int err = 0;
+       int i;
+
+       /*
+        * We should figure out how many and which devices we need to
+        * proceed and only wait for those.  For now, continue once the
+        * first device is around.
+        */
+       for (i = 0; blkif_state != BLKIF_STATE_CONNECTED && (i < 10*HZ); i++) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(1);
+       }
+
+       if (blkif_state != BLKIF_STATE_CONNECTED) {
+               WPRINTK("Timeout connecting to device!\n");
+               err = -ENOSYS;
+       }
+       return err;
 }
 
 static int __init xlblk_init(void)
 {
-    int i;
-
-    if ( (xen_start_info.flags & SIF_INITDOMAIN) ||
-         (xen_start_info.flags & SIF_BLK_BE_DOMAIN) )
-        return 0;
-
-    IPRINTK("Initialising virtual block device driver\n");
-
-    blk_shadow_free = 0;
-    memset(blk_shadow, 0, sizeof(blk_shadow));
-    for ( i = 0; i < BLK_RING_SIZE; i++ )
-        blk_shadow[i].req.id = i+1;
-    blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
-
-    init_blk_xenbus();
-
-    wait_for_blkif();
-
-    return 0;
-}
+       if ((xen_start_info->flags & SIF_INITDOMAIN) ||
+           (xen_start_info->flags & SIF_BLK_BE_DOMAIN) )
+               return 0;
+
+       IPRINTK("Initialising virtual block device driver\n");
+
+       init_blk_xenbus();
+
+       wait_for_blkif();
+
+       return 0;
+}
+
+module_init(xlblk_init);
 
 static void blkif_completion(struct blk_shadow *s)
 {
-    int i;
-    for ( i = 0; i < s->req.nr_segments; i++ )
-        gnttab_free_grant_reference(
-               blkif_gref_from_fas(s->req.frame_and_sects[i]));
-}
+       int i;
+       for (i = 0; i < s->req.nr_segments; i++)
+               gnttab_end_foreign_access(
+                       blkif_gref_from_fas(s->req.frame_and_sects[i]), 0);
+}
+
+/*
+ * Local variables:
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/blkfront/block.h
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Fri Sep  9 16:30:54 2005
@@ -96,6 +96,14 @@
        struct xlbd_type_info *type;
 };
 
+struct blk_shadow {
+       blkif_request_t req;
+       unsigned long request;
+       unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+
+#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
+
 /*
  * We have one of these per vbd, whether ide, scsi or 'other'.  They
  * hang in private_data off the gendisk structure. We may end up
@@ -116,11 +124,11 @@
        blkif_front_ring_t ring;
        unsigned int evtchn;
        struct xlbd_major_info *mi;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
        request_queue_t *rq;
-#endif
        struct work_struct work;
        struct gnttab_free_callback callback;
+       struct blk_shadow shadow[BLK_RING_SIZE];
+       unsigned long shadow_free;
 };
 
 extern spinlock_t blkif_io_lock;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/blktap/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/Makefile  Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/Makefile  Fri Sep  9 16:30:54 2005
@@ -1,3 +1,3 @@
 
-obj-y  := blktap_userdev.o blktap_datapath.o blktap_controlmsg.o blktap.o 
+obj-y  := xenbus.o interface.o blktap.o 
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c  Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c  Fri Sep  9 16:30:54 2005
@@ -1,90 +1,916 @@
 /******************************************************************************
- * blktap.c
+ * arch/xen/drivers/blkif/blktap/blktap.c
  * 
- * XenLinux virtual block-device tap.
+ * This is a modified version of the block backend driver that remaps requests
+ * to a user-space memory region.  It is intended to be used to write 
+ * application-level servers that provide block interfaces to client VMs.
  * 
- * Copyright (c) 2004, Andrew Warfield
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <asm-xen/balloon.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/gfp.h>
+#include <linux/poll.h>
+#include <asm/tlbflush.h>
+#include "common.h"
+
+/* Only one process may open /dev/xen/blktap at any time. */
+static unsigned long blktap_dev_inuse;
+unsigned long blktap_ring_ok; /* make this ring->state */
+
+/* Rings up to user space. */
+static blkif_front_ring_t blktap_ufe_ring;
+
+/* for poll: */
+static wait_queue_head_t blktap_wait;
+
+/* current switching mode */
+static unsigned long blktap_mode;
+
+/* local prototypes */
+static int blktap_read_ufe_ring(void);
+
+
+/* /dev/xen/blktap resides at device number major=10, minor=200        */ 
+#define BLKTAP_MINOR 202
+
+/* blktap IOCTLs:                                                      */
+#define BLKTAP_IOCTL_KICK_FE         1
+#define BLKTAP_IOCTL_KICK_BE         2 /* currently unused */
+#define BLKTAP_IOCTL_SETMODE         3
+#define BLKTAP_IOCTL_PRINT_IDXS      100  
+
+/* blktap switching modes: (Set with BLKTAP_IOCTL_SETMODE)             */
+#define BLKTAP_MODE_PASSTHROUGH      0x00000000  /* default            */
+#define BLKTAP_MODE_INTERCEPT_FE     0x00000001
+#define BLKTAP_MODE_INTERCEPT_BE     0x00000002  /* unimp. */
+#define BLKTAP_MODE_COPY_FE          0x00000004  /* unimp. */
+#define BLKTAP_MODE_COPY_BE          0x00000008  /* unimp. */
+#define BLKTAP_MODE_COPY_FE_PAGES    0x00000010  /* unimp. */
+#define BLKTAP_MODE_COPY_BE_PAGES    0x00000020  /* unimp. */
+
+#define BLKTAP_MODE_INTERPOSE \
+           (BLKTAP_MODE_INTERCEPT_FE | BLKTAP_MODE_INTERCEPT_BE)
+
+#define BLKTAP_MODE_COPY_BOTH \
+           (BLKTAP_MODE_COPY_FE | BLKTAP_MODE_COPY_BE)
+
+#define BLKTAP_MODE_COPY_BOTH_PAGES \
+           (BLKTAP_MODE_COPY_FE_PAGES | BLKTAP_MODE_COPY_BE_PAGES)
+
+static inline int BLKTAP_MODE_VALID(unsigned long arg)
+{
+    return (
+        ( arg == BLKTAP_MODE_PASSTHROUGH  ) ||
+        ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
+        ( arg == BLKTAP_MODE_INTERPOSE    ) );
+/*
+    return (
+        ( arg == BLKTAP_MODE_PASSTHROUGH  ) ||
+        ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
+        ( arg == BLKTAP_MODE_INTERCEPT_BE ) ||
+        ( arg == BLKTAP_MODE_INTERPOSE    ) ||
+        ( (arg & ~BLKTAP_MODE_COPY_FE_PAGES) == BLKTAP_MODE_COPY_FE ) ||
+        ( (arg & ~BLKTAP_MODE_COPY_BE_PAGES) == BLKTAP_MODE_COPY_BE ) ||
+        ( (arg & ~BLKTAP_MODE_COPY_BOTH_PAGES) == BLKTAP_MODE_COPY_BOTH )
+        );
+*/
+}
+
+
+/******************************************************************
+ * MMAP REGION
+ */
+
+/*
+ * We use a big chunk of address space to map in-flight requests into,
+ * and export this region up to user-space.  See the comments in blkback
+ * about this -- the two must be kept in sync if the tap is used as a 
+ * passthrough.
+ */
+
+#define MAX_PENDING_REQS 64
+#define BATCH_PER_DOMAIN 16
+
+/* immediately before the mmap area, we have a bunch of pages reserved
+ * for shared memory rings.
+ */
+#define RING_PAGES 1 /* Front */ 
+
+/* Where things are inside the device mapping. */
+struct vm_area_struct *blktap_vma = NULL;
+unsigned long mmap_vstart;  /* Kernel pages for mapping in data. */
+unsigned long rings_vstart; /* start of mmaped vma               */
+unsigned long user_vstart;  /* start of user mappings            */
+
+#define MMAP_PAGES                                              \
+    (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
+#define MMAP_VADDR(_start, _req,_seg)                           \
+    (_start +                                                   \
+     ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) +    \
+     ((_seg) * PAGE_SIZE))
+
+
+
+/*
+ * Each outstanding request that we've passed to the lower device layers has a 
+ * 'pending_req' allocated to it. Each buffer_head that completes decrements 
+ * the pendcnt towards zero. When it hits zero, the specified domain has a 
+ * response queued for it, with the saved 'id' passed back.
+ */
+typedef struct {
+    blkif_t       *blkif;
+    unsigned long  id;
+    int            nr_pages;
+    atomic_t       pendcnt;
+    unsigned short operation;
+    int            status;
+} pending_req_t;
+
+/*
+ * We can't allocate pending_req's in order, since they may complete out of 
+ * order. We therefore maintain an allocation ring. This ring also indicates 
+ * when enough work has been passed down -- at that point the allocation ring 
+ * will be empty.
+ */
+static pending_req_t pending_reqs[MAX_PENDING_REQS];
+static unsigned char pending_ring[MAX_PENDING_REQS];
+static spinlock_t pend_prod_lock = SPIN_LOCK_UNLOCKED;
+/* NB. We use a different index type to differentiate from shared blk rings. */
+typedef unsigned int PEND_RING_IDX;
+#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
+static PEND_RING_IDX pending_prod, pending_cons;
+#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
+
+/* Requests passing through the tap to the backend hijack the id field
+ * in the request message.  In it we put the AR index _AND_ the fe domid.
+ * the domid is used by the backend to map the pages properly.
+ */
+
+static inline unsigned long MAKE_ID(domid_t fe_dom, PEND_RING_IDX idx)
+{
+    return ( (fe_dom << 16) | MASK_PEND_IDX(idx) );
+}
+
+extern inline PEND_RING_IDX ID_TO_IDX(unsigned long id) 
+{ 
+    return (PEND_RING_IDX)( id & 0x0000ffff );
+}
+
+extern inline domid_t ID_TO_DOM(unsigned long id) 
+{ 
+    return (domid_t)(id >> 16); 
+}
+
+
+
+/******************************************************************
+ * GRANT HANDLES
+ */
+
+/* When using grant tables to map a frame for device access then the
+ * handle returned must be used to unmap the frame. This is needed to
+ * drop the ref count on the frame.
+ */
+struct grant_handle_pair
+{
+    u16  kernel;
+    u16  user;
+};
+static struct grant_handle_pair pending_grant_handles[MMAP_PAGES];
+#define pending_handle(_idx, _i) \
+    (pending_grant_handles[((_idx) * BLKIF_MAX_SEGMENTS_PER_REQUEST) + (_i)])
+#define BLKTAP_INVALID_HANDLE(_g) \
+    (((_g->kernel) == 0xFFFF) && ((_g->user) == 0xFFFF))
+#define BLKTAP_INVALIDATE_HANDLE(_g) do {       \
+    (_g)->kernel = 0xFFFF; (_g)->user = 0xFFFF; \
+    } while(0)
+
+
+/******************************************************************
+ * BLKTAP VM OPS
+ */
+
+static struct page *blktap_nopage(struct vm_area_struct *vma,
+                                             unsigned long address,
+                                             int *type)
+{
+    /*
+     * if the page has not been mapped in by the driver then generate
+     * a SIGBUS to the domain.
+     */
+
+    force_sig(SIGBUS, current);
+
+    return 0;
+}
+
+struct vm_operations_struct blktap_vm_ops = {
+    nopage:   blktap_nopage,
+};
+
+/******************************************************************
+ * BLKTAP FILE OPS
+ */
+
+static int blktap_open(struct inode *inode, struct file *filp)
+{
+    blkif_sring_t *sring;
+    
+    if ( test_and_set_bit(0, &blktap_dev_inuse) )
+        return -EBUSY;
+    
+    /* Allocate the fe ring. */
+    sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
+    if (sring == NULL)
+        goto fail_nomem;
+
+    SetPageReserved(virt_to_page(sring));
+    
+    SHARED_RING_INIT(sring);
+    FRONT_RING_INIT(&blktap_ufe_ring, sring, PAGE_SIZE);
+
+    return 0;
+
+ fail_nomem:
+    return -ENOMEM;
+}
+
+static int blktap_release(struct inode *inode, struct file *filp)
+{
+    blktap_dev_inuse = 0;
+    blktap_ring_ok = 0;
+
+    /* Free the ring page. */
+    ClearPageReserved(virt_to_page(blktap_ufe_ring.sring));
+    free_page((unsigned long) blktap_ufe_ring.sring);
+
+    /* Clear any active mappings and free foreign map table */
+    if (blktap_vma != NULL) {
+        zap_page_range(blktap_vma, blktap_vma->vm_start, 
+                       blktap_vma->vm_end - blktap_vma->vm_start, NULL);
+        blktap_vma = NULL;
+    }
+
+    return 0;
+}
+
+
+/* Note on mmap:
+ * We need to map pages to user space in a way that will allow the block
+ * subsystem set up direct IO to them.  This couldn't be done before, because
+ * there isn't really a sane way to translate a user virtual address down to a 
+ * physical address when the page belongs to another domain.
  *
- * Based on the original split block driver:
- * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
- * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
- * Copyright (c) 2004, Christian Limpach
- * 
- * Note that unlike the split block driver code, this driver has been developed
- * strictly for Linux 2.6
- */
-
-#include "blktap.h"
-
-int __init xlblktap_init(void)
-{
-    ctrl_msg_t               cmsg;
-    blkif_fe_driver_status_t fe_st;
-    blkif_be_driver_status_t be_st;
-
-    printk(KERN_INFO "Initialising Xen block tap device\n");
-#ifdef CONFIG_XEN_BLKDEV_GRANT
-    printk(KERN_INFO "Block tap is using grant tables.\n");
-#endif
-
-    DPRINTK("   tap - Backend connection init:\n");
-
-
-    (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, blkif_ctrlif_rx,
-                                    CALLBACK_IN_BLOCKING_CONTEXT);
-
-    /* Send a driver-UP notification to the domain controller. */
-    cmsg.type      = CMSG_BLKIF_FE;
-    cmsg.subtype   = CMSG_BLKIF_FE_DRIVER_STATUS;
-    cmsg.length    = sizeof(blkif_fe_driver_status_t);
-    fe_st.status   = BLKIF_DRIVER_STATUS_UP;
-    memcpy(cmsg.msg, &fe_st, sizeof(fe_st));
-    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-
-    DPRINTK("   tap - Frontend connection init:\n");
+ * My first approach was to map the page in to kernel memory, add an entry
+ * for it in the physical frame list (using alloc_lomem_region as in blkback)
+ * and then attempt to map that page up to user space.  This is disallowed
+ * by xen though, which realizes that we don't really own the machine frame
+ * underlying the physical page.
+ *
+ * The new approach is to provide explicit support for this in xen linux.
+ * The VMA now has a flag, VM_FOREIGN, to indicate that it contains pages
+ * mapped from other vms.  vma->vm_private_data is set up as a mapping 
+ * from pages to actual page structs.  There is a new clause in get_user_pages
+ * that does the right thing for this sort of mapping.
+ */
+static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+    int size;
+    struct page **map;
+    int i;
+
+    DPRINTK(KERN_ALERT "blktap mmap (%lx, %lx)\n",
+           vma->vm_start, vma->vm_end);
+
+    vma->vm_flags |= VM_RESERVED;
+    vma->vm_ops = &blktap_vm_ops;
+
+    size = vma->vm_end - vma->vm_start;
+    if ( size != ( (MMAP_PAGES + RING_PAGES) << PAGE_SHIFT ) ) {
+        printk(KERN_INFO 
+               "blktap: you _must_ map exactly %d pages!\n",
+               MMAP_PAGES + RING_PAGES);
+        return -EAGAIN;
+    }
+
+    size >>= PAGE_SHIFT;
+    DPRINTK(KERN_INFO "blktap: 2 rings + %d pages.\n", size-1);
     
-    active_reqs_init();
+    rings_vstart = vma->vm_start;
+    user_vstart  = rings_vstart + (RING_PAGES << PAGE_SHIFT);
+    
+    /* Map the ring pages to the start of the region and reserve it. */
+
+    /* not sure if I really need to do this... */
+    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+    if (remap_pfn_range(vma, vma->vm_start, 
+                         __pa(blktap_ufe_ring.sring) >> PAGE_SHIFT, 
+                         PAGE_SIZE, vma->vm_page_prot)) 
+    {
+        WPRINTK("Mapping user ring failed!\n");
+        goto fail;
+    }
+
+    /* Mark this VM as containing foreign pages, and set up mappings. */
+    map = kmalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT)
+                  * sizeof(struct page_struct*),
+                  GFP_KERNEL);
+    if (map == NULL) 
+    {
+        WPRINTK("Couldn't alloc VM_FOREIGH map.\n");
+        goto fail;
+    }
+
+    for (i=0; i<((vma->vm_end - vma->vm_start) >> PAGE_SHIFT); i++)
+        map[i] = NULL;
+    
+    vma->vm_private_data = map;
+    vma->vm_flags |= VM_FOREIGN;
+
+    blktap_vma = vma;
+    blktap_ring_ok = 1;
+
+    return 0;
+ fail:
+    /* Clear any active mappings. */
+    zap_page_range(vma, vma->vm_start, 
+                   vma->vm_end - vma->vm_start, NULL);
+
+    return -ENOMEM;
+}
+
+static int blktap_ioctl(struct inode *inode, struct file *filp,
+                        unsigned int cmd, unsigned long arg)
+{
+    switch(cmd) {
+    case BLKTAP_IOCTL_KICK_FE: /* There are fe messages to process. */
+        return blktap_read_ufe_ring();
+
+    case BLKTAP_IOCTL_SETMODE:
+        if (BLKTAP_MODE_VALID(arg)) {
+            blktap_mode = arg;
+            /* XXX: may need to flush rings here. */
+            printk(KERN_INFO "blktap: set mode to %lx\n", arg);
+            return 0;
+        }
+    case BLKTAP_IOCTL_PRINT_IDXS:
+        {
+            //print_fe_ring_idxs();
+            WPRINTK("User Rings: \n-----------\n");
+            WPRINTK("UF: rsp_cons: %2d, req_prod_prv: %2d "
+                            "| req_prod: %2d, rsp_prod: %2d\n",
+                            blktap_ufe_ring.rsp_cons,
+                            blktap_ufe_ring.req_prod_pvt,
+                            blktap_ufe_ring.sring->req_prod,
+                            blktap_ufe_ring.sring->rsp_prod);
+            
+        }
+    }
+    return -ENOIOCTLCMD;
+}
+
+static unsigned int blktap_poll(struct file *file, poll_table *wait)
+{
+        poll_wait(file, &blktap_wait, wait);
+        if ( RING_HAS_UNPUSHED_REQUESTS(&blktap_ufe_ring) ) 
+        {
+            flush_tlb_all();
+
+            RING_PUSH_REQUESTS(&blktap_ufe_ring);
+            return POLLIN | POLLRDNORM;
+        }
+
+        return 0;
+}
+
+void blktap_kick_user(void)
+{
+    /* blktap_ring->req_prod = blktap_req_prod; */
+    wake_up_interruptible(&blktap_wait);
+}
+
+static struct file_operations blktap_fops = {
+    owner:    THIS_MODULE,
+    poll:     blktap_poll,
+    ioctl:    blktap_ioctl,
+    open:     blktap_open,
+    release:  blktap_release,
+    mmap:     blktap_mmap,
+};
+
+
+
+static int do_block_io_op(blkif_t *blkif, int max_to_do);
+static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req);
+static void make_response(blkif_t *blkif, unsigned long id, 
+                          unsigned short op, int st);
+
+
+static void fast_flush_area(int idx, int nr_pages)
+{
+    struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
+    unsigned int i, op = 0;
+    struct grant_handle_pair *handle;
+    unsigned long ptep;
+
+    for (i=0; i<nr_pages; i++)
+    {
+        handle = &pending_handle(idx, i);
+        if (!BLKTAP_INVALID_HANDLE(handle))
+        {
+
+            unmap[op].host_addr = MMAP_VADDR(mmap_vstart, idx, i);
+            unmap[op].dev_bus_addr = 0;
+            unmap[op].handle = handle->kernel;
+            op++;
+
+            if (create_lookup_pte_addr(blktap_vma->vm_mm,
+                                       MMAP_VADDR(user_vstart, idx, i), 
+                                       &ptep) !=0) {
+                DPRINTK("Couldn't get a pte addr!\n");
+                return;
+            }
+            unmap[op].host_addr    = ptep;
+            unmap[op].dev_bus_addr = 0;
+            unmap[op].handle       = handle->user;
+            op++;
+            
+           BLKTAP_INVALIDATE_HANDLE(handle);
+        }
+    }
+    if ( unlikely(HYPERVISOR_grant_table_op(
+        GNTTABOP_unmap_grant_ref, unmap, op)))
+        BUG();
+
+    if (blktap_vma != NULL)
+        zap_page_range(blktap_vma, 
+                       MMAP_VADDR(user_vstart, idx, 0), 
+                       nr_pages << PAGE_SHIFT, NULL);
+}
+
+/******************************************************************
+ * BLOCK-DEVICE SCHEDULER LIST MAINTENANCE
+ */
+
+static struct list_head blkio_schedule_list;
+static spinlock_t blkio_schedule_list_lock;
+
+static int __on_blkdev_list(blkif_t *blkif)
+{
+    return blkif->blkdev_list.next != NULL;
+}
+
+static void remove_from_blkdev_list(blkif_t *blkif)
+{
+    unsigned long flags;
+    if ( !__on_blkdev_list(blkif) ) return;
+    spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+    if ( __on_blkdev_list(blkif) )
+    {
+        list_del(&blkif->blkdev_list);
+        blkif->blkdev_list.next = NULL;
+        blkif_put(blkif);
+    }
+    spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+}
+
+static void add_to_blkdev_list_tail(blkif_t *blkif)
+{
+    unsigned long flags;
+    if ( __on_blkdev_list(blkif) ) return;
+    spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+    if ( !__on_blkdev_list(blkif) && (blkif->status == CONNECTED) )
+    {
+        list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
+        blkif_get(blkif);
+    }
+    spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+}
+
+
+/******************************************************************
+ * SCHEDULER FUNCTIONS
+ */
+
+static DECLARE_WAIT_QUEUE_HEAD(blkio_schedule_wait);
+
+static int blkio_schedule(void *arg)
+{
+    DECLARE_WAITQUEUE(wq, current);
+
+    blkif_t          *blkif;
+    struct list_head *ent;
+
+    daemonize("xenblkd");
+
+    for ( ; ; )
+    {
+        /* Wait for work to do. */
+        add_wait_queue(&blkio_schedule_wait, &wq);
+        set_current_state(TASK_INTERRUPTIBLE);
+        if ( (NR_PENDING_REQS == MAX_PENDING_REQS) || 
+             list_empty(&blkio_schedule_list) )
+            schedule();
+        __set_current_state(TASK_RUNNING);
+        remove_wait_queue(&blkio_schedule_wait, &wq);
+
+        /* Queue up a batch of requests. */
+        while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
+                !list_empty(&blkio_schedule_list) )
+        {
+            ent = blkio_schedule_list.next;
+            blkif = list_entry(ent, blkif_t, blkdev_list);
+            blkif_get(blkif);
+            remove_from_blkdev_list(blkif);
+            if ( do_block_io_op(blkif, BATCH_PER_DOMAIN) )
+                add_to_blkdev_list_tail(blkif);
+            blkif_put(blkif);
+        }
+    }
+}
+
+static void maybe_trigger_blkio_schedule(void)
+{
+    /*
+     * Needed so that two processes, who together make the following predicate
+     * true, don't both read stale values and evaluate the predicate
+     * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
+     */
+    smp_mb();
+
+    if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
+         !list_empty(&blkio_schedule_list) )
+        wake_up(&blkio_schedule_wait);
+}
+
+
+
+/******************************************************************
+ * COMPLETION CALLBACK -- Called as bh->b_end_io()
+ */
+
+
+static int blktap_read_ufe_ring(void)
+{
+    /* This is called to read responses from the UFE ring. */
+
+    RING_IDX i, j, rp;
+    blkif_response_t *resp;
+    blkif_t *blkif;
+    int pending_idx;
+    pending_req_t *pending_req;
+    unsigned long     flags;
+
+    /* if we are forwarding from UFERring to FERing */
+    if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) {
+
+        /* for each outstanding message on the UFEring  */
+        rp = blktap_ufe_ring.sring->rsp_prod;
+        rmb();
+        
+        for ( i = blktap_ufe_ring.rsp_cons; i != rp; i++ )
+        {
+            resp = RING_GET_RESPONSE(&blktap_ufe_ring, i);
+            pending_idx = MASK_PEND_IDX(ID_TO_IDX(resp->id));
+            pending_req = &pending_reqs[pending_idx];
+            
+            blkif = pending_req->blkif;
+            for (j = 0; j < pending_req->nr_pages; j++) {
+                unsigned long vaddr;
+                struct page **map = blktap_vma->vm_private_data;
+                int offset; 
+
+                vaddr  = MMAP_VADDR(user_vstart, pending_idx, j);
+                offset = (vaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
+
+                //ClearPageReserved(virt_to_page(vaddr));
+                ClearPageReserved((struct page *)map[offset]);
+                map[offset] = NULL;
+            }
+
+            fast_flush_area(pending_idx, pending_req->nr_pages);
+            make_response(blkif, pending_req->id, resp->operation, 
+                          resp->status);
+            blkif_put(pending_req->blkif);
+            spin_lock_irqsave(&pend_prod_lock, flags);
+            pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+            spin_unlock_irqrestore(&pend_prod_lock, flags);
+        }
+        blktap_ufe_ring.rsp_cons = i;
+        maybe_trigger_blkio_schedule();
+    }
+    return 0;
+}
+
+
+/******************************************************************************
+ * NOTIFICATION FROM GUEST OS.
+ */
+
+irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+    blkif_t *blkif = dev_id;
+    add_to_blkdev_list_tail(blkif);
+    maybe_trigger_blkio_schedule();
+    return IRQ_HANDLED;
+}
+
+
+
+/******************************************************************
+ * DOWNWARD CALLS -- These interface with the block-device layer proper.
+ */
+
+static int do_block_io_op(blkif_t *blkif, int max_to_do)
+{
+    blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+    blkif_request_t *req;
+    RING_IDX i, rp;
+    int more_to_do = 0;
+    
+    rp = blk_ring->sring->req_prod;
+    rmb(); /* Ensure we see queued requests up to 'rp'. */
+
+    for ( i = blk_ring->req_cons; 
+         (i != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, i);
+          i++ )
+    {
+        if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) )
+        {
+            more_to_do = 1;
+            break;
+        }
+        
+        req = RING_GET_REQUEST(blk_ring, i);
+        switch ( req->operation )
+        {
+        case BLKIF_OP_READ:
+        case BLKIF_OP_WRITE:
+            dispatch_rw_block_io(blkif, req);
+            break;
+
+        default:
+            DPRINTK("error: unknown block io operation [%d]\n",
+                    req->operation);
+            make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+            break;
+        }
+    }
+
+    blk_ring->req_cons = i;
+    blktap_kick_user();
+
+    return more_to_do;
+}
+
+static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
+{
+    blkif_request_t *target;
+    int i, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
+    pending_req_t *pending_req;
+    struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
+    int op, ret;
+    unsigned int nseg;
+
+    /* Check that number of segments is sane. */
+    nseg = req->nr_segments;
+    if ( unlikely(nseg == 0) || 
+         unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) )
+    {
+        DPRINTK("Bad number of segments in request (%d)\n", nseg);
+        goto bad_descriptor;
+    }
+
+    /* Make sure userspace is ready. */
+    if (!blktap_ring_ok) {
+        DPRINTK("blktap: ring not ready for requests!\n");
+        goto bad_descriptor;
+    }
+    
+
+    if ( RING_FULL(&blktap_ufe_ring) ) {
+        WPRINTK("blktap: fe_ring is full, can't add (very broken!).\n");
+        goto bad_descriptor;
+    }
+
+    flush_cache_all(); /* a noop on intel... */
+
+    /* Map the foreign pages directly in to the application */    
+    op = 0;
+    for (i=0; i<req->nr_segments; i++) {
+
+        unsigned long uvaddr;
+        unsigned long kvaddr;
+        unsigned long ptep;
+
+        uvaddr = MMAP_VADDR(user_vstart, pending_idx, i);
+        kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i);
+
+        /* Map the remote page to kernel. */
+        map[op].host_addr = kvaddr;
+        map[op].dom   = blkif->domid;
+        map[op].ref   = blkif_gref_from_fas(req->frame_and_sects[i]);
+        map[op].flags = GNTMAP_host_map;
+        /* This needs a bit more thought in terms of interposition: 
+         * If we want to be able to modify pages during write using 
+         * grant table mappings, the guest will either need to allow 
+         * it, or we'll need to incur a copy. Bit of an fbufs moment. ;) */
+        if (req->operation == BLKIF_OP_WRITE)
+            map[op].flags |= GNTMAP_readonly;
+        op++;
+
+        /* Now map it to user. */
+        ret = create_lookup_pte_addr(blktap_vma->vm_mm, uvaddr, &ptep);
+        if (ret)
+        {
+            DPRINTK("Couldn't get a pte addr!\n");
+            fast_flush_area(pending_idx, req->nr_segments);
+            goto bad_descriptor;
+        }
+
+        map[op].host_addr = ptep;
+        map[op].dom       = blkif->domid;
+        map[op].ref       = blkif_gref_from_fas(req->frame_and_sects[i]);
+        map[op].flags     = GNTMAP_host_map | GNTMAP_application_map
+                            | GNTMAP_contains_pte;
+        /* Above interposition comment applies here as well. */
+        if (req->operation == BLKIF_OP_WRITE)
+            map[op].flags |= GNTMAP_readonly;
+        op++;
+    }
+
+    if ( unlikely(HYPERVISOR_grant_table_op(
+            GNTTABOP_map_grant_ref, map, op)))
+        BUG();
+
+    op = 0;
+    for (i=0; i<(req->nr_segments*2); i+=2) {
+        unsigned long uvaddr;
+        unsigned long kvaddr;
+        unsigned long offset;
+        int cancel = 0;
+
+        uvaddr = MMAP_VADDR(user_vstart, pending_idx, i/2);
+        kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i/2);
+
+        if ( unlikely(map[i].handle < 0) ) 
+        {
+            DPRINTK("Error on kernel grant mapping (%d)\n", map[i].handle);
+            ret = map[i].handle;
+            cancel = 1;
+        }
+
+        if ( unlikely(map[i+1].handle < 0) ) 
+        {
+            DPRINTK("Error on user grant mapping (%d)\n", map[i+1].handle);
+            ret = map[i+1].handle;
+            cancel = 1;
+        }
+
+        if (cancel) 
+        {
+            fast_flush_area(pending_idx, req->nr_segments);
+            goto bad_descriptor;
+        }
+
+        /* Set the necessary mappings in p2m and in the VM_FOREIGN 
+         * vm_area_struct to allow user vaddr -> struct page lookups
+         * to work.  This is needed for direct IO to foreign pages. */
+        phys_to_machine_mapping[__pa(kvaddr) >> PAGE_SHIFT] =
+            FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT);
+
+        offset = (uvaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
+        ((struct page **)blktap_vma->vm_private_data)[offset] =
+            pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+
+        /* Save handles for unmapping later. */
+        pending_handle(pending_idx, i/2).kernel = map[i].handle;
+        pending_handle(pending_idx, i/2).user   = map[i+1].handle;
+    }
+
+    /* Mark mapped pages as reserved: */
+    for ( i = 0; i < req->nr_segments; i++ )
+    {
+        unsigned long kvaddr;
+
+        kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i);
+        SetPageReserved(pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT));
+    }
+
+    pending_req = &pending_reqs[pending_idx];
+    pending_req->blkif     = blkif;
+    pending_req->id        = req->id;
+    pending_req->operation = req->operation;
+    pending_req->status    = BLKIF_RSP_OKAY;
+    pending_req->nr_pages  = nseg;
+    req->id = MAKE_ID(blkif->domid, pending_idx);
+    //atomic_set(&pending_req->pendcnt, nbio);
+    pending_cons++;
+    blkif_get(blkif);
+
+    /* Finally, write the request message to the user ring. */
+    target = RING_GET_REQUEST(&blktap_ufe_ring, blktap_ufe_ring.req_prod_pvt);
+    memcpy(target, req, sizeof(*req));
+    blktap_ufe_ring.req_prod_pvt++;
+    return;
+
+ bad_descriptor:
+    make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+} 
+
+
+
+/******************************************************************
+ * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
+ */
+
+
+static void make_response(blkif_t *blkif, unsigned long id, 
+                          unsigned short op, int st)
+{
+    blkif_response_t *resp;
+    unsigned long     flags;
+    blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+
+    /* Place on the response ring for the relevant domain. */ 
+    spin_lock_irqsave(&blkif->blk_ring_lock, flags);
+    resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
+    resp->id        = id;
+    resp->operation = op;
+    resp->status    = st;
+    wmb(); /* Ensure other side can see the response fields. */
+    blk_ring->rsp_prod_pvt++;
+    RING_PUSH_RESPONSES(blk_ring);
+    spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
+
+    /* Kick the relevant domain. */
+    notify_via_evtchn(blkif->evtchn);
+}
+
+static struct miscdevice blktap_miscdev = {
+    .minor        = BLKTAP_MINOR,
+    .name         = "blktap",
+    .fops         = &blktap_fops,
+    .devfs_name   = "misc/blktap",
+};
+
+void blkif_deschedule(blkif_t *blkif)
+{
+    remove_from_blkdev_list(blkif);
+}
+
+static int __init blkif_init(void)
+{
+    int i, j, err;
+    struct page *page;
+/*
+    if ( !(xen_start_info->flags & SIF_INITDOMAIN) &&
+         !(xen_start_info->flags & SIF_BLK_BE_DOMAIN) )
+        return 0;
+*/
     blkif_interface_init();
-    blkdev_schedule_init();
+
+    page = balloon_alloc_empty_page_range(MMAP_PAGES);
+    BUG_ON(page == NULL);
+    mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+
+    pending_cons = 0;
+    pending_prod = MAX_PENDING_REQS;
+    memset(pending_reqs, 0, sizeof(pending_reqs));
+    for ( i = 0; i < MAX_PENDING_REQS; i++ )
+        pending_ring[i] = i;
     
-    (void)ctrl_if_register_receiver(CMSG_BLKIF_BE, blkif_ctrlif_rx, 
-                                    CALLBACK_IN_BLOCKING_CONTEXT);
-
-    /* Send a driver-UP notification to the domain controller. */
-    cmsg.type      = CMSG_BLKIF_BE;
-    cmsg.subtype   = CMSG_BLKIF_BE_DRIVER_STATUS;
-    cmsg.length    = sizeof(blkif_be_driver_status_t);
-    be_st.status   = BLKIF_DRIVER_STATUS_UP;
-    memcpy(cmsg.msg, &be_st, sizeof(be_st));
-    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-
-    DPRINTK("   tap - Userland channel init:\n");
-
-    blktap_init();
-
-    DPRINTK("Blkif tap device initialized.\n");
+    spin_lock_init(&blkio_schedule_list_lock);
+    INIT_LIST_HEAD(&blkio_schedule_list);
+
+    if ( kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
+        BUG();
+
+    blkif_xenbus_init();
+
+    for (i=0; i<MAX_PENDING_REQS ; i++)
+        for (j=0; j<BLKIF_MAX_SEGMENTS_PER_REQUEST; j++)
+            BLKTAP_INVALIDATE_HANDLE(&pending_handle(i, j));
+
+    err = misc_register(&blktap_miscdev);
+    if ( err != 0 )
+    {
+        printk(KERN_ALERT "Couldn't register /dev/misc/blktap (%d)\n", err);
+        return err;
+    }
+
+    init_waitqueue_head(&blktap_wait);
 
     return 0;
 }
 
-#if 0 /* tap doesn't handle suspend/resume */
-void blkdev_suspend(void)
-{
-}
-
-void blkdev_resume(void)
-{
-    ctrl_msg_t               cmsg;
-    blkif_fe_driver_status_t st;    
-
-    /* Send a driver-UP notification to the domain controller. */
-    cmsg.type      = CMSG_BLKIF_FE;
-    cmsg.subtype   = CMSG_BLKIF_FE_DRIVER_STATUS;
-    cmsg.length    = sizeof(blkif_fe_driver_status_t);
-    st.status      = BLKIF_DRIVER_STATUS_UP;
-    memcpy(cmsg.msg, &st, sizeof(st));
-    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
-#endif
-
-__initcall(xlblktap_init);
+__initcall(blkif_init);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/blktap/blktap.h
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.h  Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.h  Fri Sep  9 16:30:54 2005
@@ -15,7 +15,6 @@
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
-#include <asm-xen/ctrl_if.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
 #include <asm/io.h>
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/console/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/console/Makefile Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/Makefile Fri Sep  9 16:30:54 2005
@@ -1,2 +1,2 @@
 
-obj-y  := console.o
+obj-y  := console.o xencons_ring.o
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/console/console.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/console.c        Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c        Fri Sep  9 
16:30:54 2005
@@ -45,14 +45,15 @@
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/bootmem.h>
+#include <linux/sysrq.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm-xen/xen-public/event_channel.h>
 #include <asm-xen/hypervisor.h>
 #include <asm-xen/evtchn.h>
-#include <asm-xen/ctrl_if.h>
-
+
+#include "xencons_ring.h"
 /*
  * Modes:
  *  'xencons=off'  [XC_OFF]:     Console is disabled.
@@ -66,6 +67,11 @@
 static enum { XC_OFF, XC_DEFAULT, XC_TTY, XC_SERIAL } xc_mode = XC_DEFAULT;
 static int xc_num = -1;
 
+#ifdef CONFIG_MAGIC_SYSRQ
+static unsigned long sysrq_requested;
+extern int sysrq_enabled;
+#endif
+
 static int __init xencons_setup(char *str)
 {
     char *q;
@@ -118,13 +124,6 @@
 /* Common transmit-kick routine. */
 static void __xencons_tx_flush(void);
 
-/* This task is used to defer sending console data until there is space. */
-static void xencons_tx_flush_task_routine(void *data);
-
-static DECLARE_TQUEUE(xencons_tx_flush_task, 
-                      xencons_tx_flush_task_routine,
-                      NULL);
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 static struct tty_driver *xencons_driver;
 #else
@@ -196,7 +195,7 @@
 void xen_console_init(void)
 #endif
 {
-    if ( xen_start_info.flags & SIF_INITDOMAIN )
+    if ( xen_start_info->flags & SIF_INITDOMAIN )
     {
         if ( xc_mode == XC_DEFAULT )
             xc_mode = XC_SERIAL;
@@ -264,39 +263,22 @@
 /*** Forcibly flush console data before dying. ***/
 void xencons_force_flush(void)
 {
-    ctrl_msg_t msg;
     int        sz;
 
     /* Emergency console is synchronous, so there's nothing to flush. */
-    if ( xen_start_info.flags & SIF_INITDOMAIN )
-        return;
-
-    /*
-     * We use dangerous control-interface functions that require a quiescent
-     * system and no interrupts. Try to ensure this with a global cli().
-     */
-    local_irq_disable(); /* XXXsmp */
+    if ( xen_start_info->flags & SIF_INITDOMAIN )
+        return;
+
 
     /* Spin until console data is flushed through to the domain controller. */
-    while ( (wc != wp) && !ctrl_if_transmitter_empty() )
-    {
-        /* Interrupts are disabled -- we must manually reap responses. */
-        ctrl_if_discard_responses();
-
+    while ( (wc != wp) )
+    {
+       int sent = 0;
         if ( (sz = wp - wc) == 0 )
             continue;
-        if ( sz > sizeof(msg.msg) )
-            sz = sizeof(msg.msg);
-        if ( sz > (wbuf_size - WBUF_MASK(wc)) )
-            sz = wbuf_size - WBUF_MASK(wc);
-
-        msg.type    = CMSG_CONSOLE;
-        msg.subtype = CMSG_CONSOLE_DATA;
-        msg.length  = sz;
-        memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
-            
-        if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
-            wc += sz;
+       sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
+       if (sent > 0)
+           wc += sent;
     }
 }
 
@@ -320,7 +302,7 @@
 static char x_char;
 
 /* Non-privileged receive callback. */
-static void xencons_rx(ctrl_msg_t *msg, unsigned long id)
+static void xencons_rx(char *buf, unsigned len, struct pt_regs *regs)
 {
     int           i;
     unsigned long flags;
@@ -328,23 +310,39 @@
     spin_lock_irqsave(&xencons_lock, flags);
     if ( xencons_tty != NULL )
     {
-        for ( i = 0; i < msg->length; i++ )
-            tty_insert_flip_char(xencons_tty, msg->msg[i], 0);
+        for ( i = 0; i < len; i++ ) {
+#ifdef CONFIG_MAGIC_SYSRQ
+            if (sysrq_enabled) {
+                if (buf[i] == '\x0f') { /* ^O */
+                    sysrq_requested = jiffies;
+                    continue; /* don't print the sysrq key */
+                } else if (sysrq_requested) {
+                    unsigned long sysrq_timeout = sysrq_requested + HZ*2;
+                    sysrq_requested = 0;
+                    /* if it's been less than a timeout, do the sysrq */
+                    if (time_before(jiffies, sysrq_timeout)) {
+                        spin_unlock_irqrestore(&xencons_lock, flags);
+                        handle_sysrq(buf[i], regs, xencons_tty);
+                        spin_lock_irqsave(&xencons_lock, flags);
+                        continue;
+                    }
+                }
+            }
+#endif
+            tty_insert_flip_char(xencons_tty, buf[i], 0);
+        }
         tty_flip_buffer_push(xencons_tty);
     }
     spin_unlock_irqrestore(&xencons_lock, flags);
 
-    msg->length = 0;
-    ctrl_if_send_response(msg);
 }
 
 /* Privileged and non-privileged transmit worker. */
 static void __xencons_tx_flush(void)
 {
     int        sz, work_done = 0;
-    ctrl_msg_t msg;
-
-    if ( xen_start_info.flags & SIF_INITDOMAIN )
+
+    if ( xen_start_info->flags & SIF_INITDOMAIN )
     {
         if ( x_char )
         {
@@ -367,38 +365,23 @@
     {
         while ( x_char )
         {
-            msg.type    = CMSG_CONSOLE;
-            msg.subtype = CMSG_CONSOLE_DATA;
-            msg.length  = 1;
-            msg.msg[0]  = x_char;
-
-            if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
-                x_char = 0;
-            else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
-                break;
-
-            work_done = 1;
+           if (xencons_ring_send(&x_char, 1) == 1) {
+               x_char = 0;
+               work_done = 1;
+           }
         }
 
         while ( wc != wp )
         {
+           int sent;
             sz = wp - wc;
-            if ( sz > sizeof(msg.msg) )
-                sz = sizeof(msg.msg);
-            if ( sz > (wbuf_size - WBUF_MASK(wc)) )
-                sz = wbuf_size - WBUF_MASK(wc);
-
-            msg.type    = CMSG_CONSOLE;
-            msg.subtype = CMSG_CONSOLE_DATA;
-            msg.length  = sz;
-            memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
-            
-            if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
-                wc += sz;
-            else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
-                break;
-
-            work_done = 1;
+           if ( sz > (wbuf_size - WBUF_MASK(wc)) )
+               sz = wbuf_size - WBUF_MASK(wc);
+           sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
+           if ( sent > 0 ) {
+               wc += sent;
+               work_done = 1;
+           }
         }
     }
 
@@ -409,15 +392,6 @@
              (xencons_tty->ldisc.write_wakeup != NULL) )
             (xencons_tty->ldisc.write_wakeup)(xencons_tty);
     }
-}
-
-/* Non-privileged transmit kicker. */
-static void xencons_tx_flush_task_routine(void *data)
-{
-    unsigned long flags;
-    spin_lock_irqsave(&xencons_lock, flags);
-    __xencons_tx_flush();
-    spin_unlock_irqrestore(&xencons_lock, flags);
 }
 
 /* Privileged receive callback and transmit kicker. */
@@ -726,6 +700,8 @@
     if ( xc_mode == XC_OFF )
         return 0;
 
+    xencons_ring_init();
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
     xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ? 
                                       1 : MAX_NR_CONSOLES);
@@ -794,7 +770,7 @@
     tty_register_device(xencons_driver, 0, NULL);
 #endif
 
-    if ( xen_start_info.flags & SIF_INITDOMAIN )
+    if ( xen_start_info->flags & SIF_INITDOMAIN )
     {
         xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE);
         (void)request_irq(xencons_priv_irq,
@@ -802,7 +778,8 @@
     }
     else
     {
-        (void)ctrl_if_register_receiver(CMSG_CONSOLE, xencons_rx, 0);
+       
+       xencons_ring_register_receiver(xencons_rx);
     }
 
     printk("Xen virtual console successfully installed as %s%d\n",
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c
--- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c  Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c  Fri Sep  9 16:30:54 2005
@@ -350,6 +350,8 @@
 
     spin_unlock_irq(&port_user_lock);
 
+    kfree(u);
+
     return 0;
 }
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/netback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Fri Sep  9 16:30:54 2005
@@ -14,15 +14,17 @@
 #include <linux/in.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-#include <asm-xen/ctrl_if.h>
 #include <asm-xen/evtchn.h>
 #include <asm-xen/xen-public/io/netif.h>
 #include <asm/io.h>
 #include <asm/pgalloc.h>
 
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
+#ifdef CONFIG_XEN_NETDEV_GRANT
 #include <asm-xen/xen-public/grant_table.h>
 #include <asm-xen/gnttab.h>
+
+#define GRANT_INVALID_REF (0xFFFF)
+
 #endif
 
 
@@ -37,6 +39,11 @@
 #define ASSERT(_p) ((void)0)
 #define DPRINTK(_f, _a...) ((void)0)
 #endif
+#define IPRINTK(fmt, args...) \
+    printk(KERN_INFO "xen_net: " fmt, ##args)
+#define WPRINTK(fmt, args...) \
+    printk(KERN_WARNING "xen_net: " fmt, ##args)
+
 
 typedef struct netif_st {
     /* Unique identifier for this interface. */
@@ -47,13 +54,13 @@
 
     /* Physical parameters of the comms window. */
     unsigned long    tx_shmem_frame;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     u16              tx_shmem_handle;
     unsigned long    tx_shmem_vaddr; 
     grant_ref_t      tx_shmem_ref; 
 #endif
     unsigned long    rx_shmem_frame;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     u16              rx_shmem_handle;
     unsigned long    rx_shmem_vaddr; 
     grant_ref_t      rx_shmem_ref; 
@@ -68,7 +75,7 @@
     /* Private indexes into shared ring. */
     NETIF_RING_IDX rx_req_cons;
     NETIF_RING_IDX rx_resp_prod; /* private version of shared variable */
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     NETIF_RING_IDX rx_resp_prod_copy; /* private version of shared variable */
 #endif
     NETIF_RING_IDX tx_req_cons;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/netback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c      Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c      Fri Sep  9 
16:30:54 2005
@@ -111,91 +111,81 @@
     return netif;
 }
 
-static int map_frontend_page(netif_t *netif, unsigned long localaddr,
-                            unsigned long tx_ring_ref, unsigned long 
rx_ring_ref)
-{
-#if !defined(CONFIG_XEN_NETDEV_GRANT_TX)||!defined(CONFIG_XEN_NETDEV_GRANT_RX)
+static int map_frontend_pages(netif_t *netif, unsigned long localaddr,
+                              unsigned long tx_ring_ref, 
+                              unsigned long rx_ring_ref)
+{
+#ifdef CONFIG_XEN_NETDEV_GRANT
+    struct gnttab_map_grant_ref op;
+
+    /* Map: Use the Grant table reference */
+    op.host_addr = localaddr;
+    op.flags     = GNTMAP_host_map;
+    op.ref       = tx_ring_ref;
+    op.dom       = netif->domid;
+    
+    BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
+    if (op.handle < 0) { 
+        DPRINTK(" Grant table operation failure mapping tx_ring_ref!\n");
+        return op.handle;
+    }
+
+    netif->tx_shmem_ref    = tx_ring_ref;
+    netif->tx_shmem_handle = op.handle;
+    netif->tx_shmem_vaddr  = localaddr;
+
+    /* Map: Use the Grant table reference */
+    op.host_addr = localaddr + PAGE_SIZE;
+    op.flags     = GNTMAP_host_map;
+    op.ref       = rx_ring_ref;
+    op.dom       = netif->domid;
+
+    BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
+    if (op.handle < 0) { 
+        DPRINTK(" Grant table operation failure mapping rx_ring_ref!\n");
+        return op.handle;
+    }
+
+    netif->rx_shmem_ref    = rx_ring_ref;
+    netif->rx_shmem_handle = op.handle;
+    netif->rx_shmem_vaddr  = localaddr + PAGE_SIZE;
+
+#else
     pgprot_t      prot = __pgprot(_KERNPG_TABLE);
     int           err;
-#endif
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX)
-    {
-        struct gnttab_map_grant_ref op;
-
-        /* Map: Use the Grant table reference */
-        op.host_addr = localaddr;
-        op.flags     = GNTMAP_host_map;
-        op.ref       = tx_ring_ref;
-        op.dom       = netif->domid;
-       
-       BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
-        if (op.handle < 0) { 
-            DPRINTK(" Grant table operation failure !\n");
-            return op.handle;
-        }
-
-        netif->tx_shmem_ref    = tx_ring_ref;
-        netif->tx_shmem_handle = op.handle;
-        netif->tx_shmem_vaddr  = localaddr;
-    }
-#else 
-    err = direct_remap_area_pages(&init_mm, localaddr,
-                                 tx_ring_ref<<PAGE_SHIFT, PAGE_SIZE,
+
+    err = direct_remap_pfn_range(&init_mm, localaddr,
+                                 tx_ring_ref, PAGE_SIZE,
                                  prot, netif->domid); 
+    
+    err |= direct_remap_pfn_range(&init_mm, localaddr + PAGE_SIZE,
+                                 rx_ring_ref, PAGE_SIZE,
+                                 prot, netif->domid);
+
     if (err)
        return err;
 #endif
 
-#if defined(CONFIG_XEN_NETDEV_GRANT_RX)
-    {
-        struct gnttab_map_grant_ref op;
-
-        /* Map: Use the Grant table reference */
-        op.host_addr = localaddr + PAGE_SIZE;
-        op.flags     = GNTMAP_host_map;
-        op.ref       = rx_ring_ref;
-        op.dom       = netif->domid;
-
-       BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
-        if (op.handle < 0) { 
-            DPRINTK(" Grant table operation failure !\n");
-            return op.handle;
-        }
-
-        netif->rx_shmem_ref    = rx_ring_ref;
-        netif->rx_shmem_handle = op.handle;
-        netif->rx_shmem_vaddr  = localaddr + PAGE_SIZE;
-    }
-#else 
-    err = direct_remap_area_pages(&init_mm, localaddr + PAGE_SIZE,
-                                 rx_ring_ref<<PAGE_SHIFT, PAGE_SIZE,
-                                 prot, netif->domid);
-    if (err)
-       return err;
-#endif
-
     return 0;
 }
 
-static void unmap_frontend_page(netif_t *netif)
-{
-#if defined(CONFIG_XEN_NETDEV_GRANT_RX) || defined(CONFIG_XEN_NETDEV_GRANT_TX)
+static void unmap_frontend_pages(netif_t *netif)
+{
+#ifdef CONFIG_XEN_NETDEV_GRANT
     struct gnttab_unmap_grant_ref op;
-#endif
-
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+
     op.host_addr    = netif->tx_shmem_vaddr;
     op.handle       = netif->tx_shmem_handle;
     op.dev_bus_addr = 0;
     BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
-#endif
-
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+
     op.host_addr    = netif->rx_shmem_vaddr;
     op.handle       = netif->rx_shmem_handle;
     op.dev_bus_addr = 0;
     BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
 #endif
+
+    return; 
 }
 
 int netif_map(netif_t *netif, unsigned long tx_ring_ref,
@@ -209,8 +199,8 @@
     if (vma == NULL)
         return -ENOMEM;
 
-    err = map_frontend_page(netif, (unsigned long)vma->addr, tx_ring_ref,
-                           rx_ring_ref);
+    err = map_frontend_pages(netif, (unsigned long)vma->addr, tx_ring_ref,
+                             rx_ring_ref);
     if (err) {
         vfree(vma->addr);
        return err;
@@ -222,7 +212,7 @@
     op.u.bind_interdomain.port2 = evtchn;
     err = HYPERVISOR_event_channel_op(&op);
     if (err) {
-       unmap_frontend_page(netif);
+       unmap_frontend_pages(netif);
        vfree(vma->addr);
        return err;
     }
@@ -267,7 +257,7 @@
     unregister_netdev(netif->dev);
 
     if (netif->tx) {
-       unmap_frontend_page(netif);
+       unmap_frontend_pages(netif);
        vfree(netif->tx); /* Frees netif->rx as well. */
     }
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/netback/loopback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c       Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c       Fri Sep  9 
16:30:54 2005
@@ -29,136 +29,163 @@
 #include <linux/skbuff.h>
 #include <net/dst.h>
 
+static int nloopbacks = 1;
+module_param(nloopbacks, int, 0);
+MODULE_PARM_DESC(nloopbacks, "Number of netback-loopback devices to create");
+
 struct net_private {
-    struct net_device *loopback_dev;
-    struct net_device_stats stats;
+       struct net_device *loopback_dev;
+       struct net_device_stats stats;
 };
 
 static int loopback_open(struct net_device *dev)
 {
-    struct net_private *np = netdev_priv(dev);
-    memset(&np->stats, 0, sizeof(np->stats));
-    netif_start_queue(dev);
-    return 0;
+       struct net_private *np = netdev_priv(dev);
+       memset(&np->stats, 0, sizeof(np->stats));
+       netif_start_queue(dev);
+       return 0;
 }
 
 static int loopback_close(struct net_device *dev)
 {
-    netif_stop_queue(dev);
-    return 0;
+       netif_stop_queue(dev);
+       return 0;
 }
 
 static int loopback_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-    struct net_private *np = netdev_priv(dev);
+       struct net_private *np = netdev_priv(dev);
 
-    dst_release(skb->dst);
-    skb->dst = NULL;
+       dst_release(skb->dst);
+       skb->dst = NULL;
 
-    skb_orphan(skb);
+       skb_orphan(skb);
 
-    np->stats.tx_bytes += skb->len;
-    np->stats.tx_packets++;
+       np->stats.tx_bytes += skb->len;
+       np->stats.tx_packets++;
 
-    /* Switch to loopback context. */
-    dev = np->loopback_dev;
-    np  = netdev_priv(dev);
+       /* Switch to loopback context. */
+       dev = np->loopback_dev;
+       np  = netdev_priv(dev);
 
-    np->stats.rx_bytes += skb->len;
-    np->stats.rx_packets++;
+       np->stats.rx_bytes += skb->len;
+       np->stats.rx_packets++;
 
-    if ( skb->ip_summed == CHECKSUM_HW )
-    {
-        /* Defer checksum calculation. */
-        skb->proto_csum_blank = 1;
-        /* Must be a local packet: assert its integrity. */
-        skb->proto_csum_valid = 1;
-    }
+       if (skb->ip_summed == CHECKSUM_HW) {
+               /* Defer checksum calculation. */
+               skb->proto_csum_blank = 1;
+               /* Must be a local packet: assert its integrity. */
+               skb->proto_csum_valid = 1;
+       }
 
-    skb->ip_summed = skb->proto_csum_valid ?
-        CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
+       skb->ip_summed = skb->proto_csum_valid ?
+               CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
 
-    skb->pkt_type = PACKET_HOST; /* overridden by eth_type_trans() */
-    skb->protocol = eth_type_trans(skb, dev);
-    skb->dev      = dev;
-    dev->last_rx  = jiffies;
-    netif_rx(skb);
+       skb->pkt_type = PACKET_HOST; /* overridden by eth_type_trans() */
+       skb->protocol = eth_type_trans(skb, dev);
+       skb->dev      = dev;
+       dev->last_rx  = jiffies;
+       netif_rx(skb);
 
-    return 0;
+       return 0;
 }
 
 static struct net_device_stats *loopback_get_stats(struct net_device *dev)
 {
-    struct net_private *np = netdev_priv(dev);
-    return &np->stats;
+       struct net_private *np = netdev_priv(dev);
+       return &np->stats;
 }
 
 static void loopback_construct(struct net_device *dev, struct net_device *lo)
 {
-    struct net_private *np = netdev_priv(dev);
+       struct net_private *np = netdev_priv(dev);
 
-    np->loopback_dev     = lo;
+       np->loopback_dev     = lo;
 
-    dev->open            = loopback_open;
-    dev->stop            = loopback_close;
-    dev->hard_start_xmit = loopback_start_xmit;
-    dev->get_stats       = loopback_get_stats;
+       dev->open            = loopback_open;
+       dev->stop            = loopback_close;
+       dev->hard_start_xmit = loopback_start_xmit;
+       dev->get_stats       = loopback_get_stats;
 
-    dev->tx_queue_len    = 0;
+       dev->tx_queue_len    = 0;
 
-    dev->features        = NETIF_F_HIGHDMA | NETIF_F_LLTX;
+       dev->features        = NETIF_F_HIGHDMA | NETIF_F_LLTX;
 
-    /*
-     * We do not set a jumbo MTU on the interface. Otherwise the network
-     * stack will try to send large packets that will get dropped by the
-     * Ethernet bridge (unless the physical Ethernet interface is configured
-     * to transfer jumbo packets). If a larger MTU is desired then the system
-     * administrator can specify it using the 'ifconfig' command.
-     */
-    /*dev->mtu             = 16*1024;*/
+       /*
+        * We do not set a jumbo MTU on the interface. Otherwise the network
+        * stack will try to send large packets that will get dropped by the
+        * Ethernet bridge (unless the physical Ethernet interface is
+        * configured to transfer jumbo packets). If a larger MTU is desired
+        * then the system administrator can specify it using the 'ifconfig'
+        * command.
+        */
+       /*dev->mtu             = 16*1024;*/
+}
+
+static int __init make_loopback(int i)
+{
+       struct net_device *dev1, *dev2;
+       char dev_name[IFNAMSIZ];
+       int err = -ENOMEM;
+
+       sprintf(dev_name, "vif0.%d", i);
+       dev1 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
+       sprintf(dev_name, "veth%d", i);
+       dev2 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
+       if ((dev1 == NULL) || (dev2 == NULL))
+               goto fail;
+
+       loopback_construct(dev1, dev2);
+       loopback_construct(dev2, dev1);
+
+       dev1->features |= NETIF_F_NO_CSUM;
+       dev2->features |= NETIF_F_IP_CSUM;
+
+       /*
+        * Initialise a dummy MAC address for the 'dummy backend' interface. We
+        * choose the numerically largest non-broadcast address to prevent the
+        * address getting stolen by an Ethernet bridge for STP purposes.
+        */
+       memset(dev1->dev_addr, 0xFF, ETH_ALEN);
+       dev1->dev_addr[0] &= ~0x01;
+
+       if ((err = register_netdev(dev1)) != 0)
+               goto fail;
+
+       if ((err = register_netdev(dev2)) != 0) {
+               unregister_netdev(dev1);
+               goto fail;
+       }
+
+       return 0;
+
+ fail:
+       if (dev1 != NULL)
+               kfree(dev1);
+       if (dev2 != NULL)
+               kfree(dev2);
+       return err;
 }
 
 static int __init loopback_init(void)
 {
-    struct net_device *dev1, *dev2;
-    int err = -ENOMEM;
+       int i, err = 0;
 
-    dev1 = alloc_netdev(sizeof(struct net_private), "vif0.0", ether_setup);
-    dev2 = alloc_netdev(sizeof(struct net_private), "veth0", ether_setup);
-    if ( (dev1 == NULL) || (dev2 == NULL) )
-        goto fail;
+       for (i = 0; i < nloopbacks; i++)
+               if ((err = make_loopback(i)) != 0)
+                       break;
 
-    loopback_construct(dev1, dev2);
-    loopback_construct(dev2, dev1);
-
-    dev1->features |= NETIF_F_NO_CSUM;
-    dev2->features |= NETIF_F_IP_CSUM;
-
-    /*
-     * Initialise a dummy MAC address for the 'dummy backend' interface. We
-     * choose the numerically largest non-broadcast address to prevent the
-     * address getting stolen by an Ethernet bridge for STP purposes.
-     */
-    memset(dev1->dev_addr, 0xFF, ETH_ALEN);
-    dev1->dev_addr[0] &= ~0x01;
-
-    if ( (err = register_netdev(dev1)) != 0 )
-        goto fail;
-
-    if ( (err = register_netdev(dev2)) != 0 )
-    {
-        unregister_netdev(dev1);
-        goto fail;
-    }
-
-    return 0;
-
- fail:
-    if ( dev1 != NULL )
-        kfree(dev1);
-    if ( dev2 != NULL )
-        kfree(dev2);
-    return err;
+       return err;
 }
 
 module_init(loopback_init);
+
+/*
+ * Local variables:
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Fri Sep  9 
16:30:54 2005
@@ -12,24 +12,8 @@
 
 #include "common.h"
 #include <asm-xen/balloon.h>
-
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
-#include <asm-xen/xen-public/grant_table.h>
-#include <asm-xen/gnttab.h>
-#ifdef GRANT_DEBUG
-static void
-dump_packet(int tag, u32 addr, unsigned char *p)
-{
-       int i;
-
-       printk(KERN_ALERT "#### rx_action %c %08x ", tag & 0xff, addr);
-       for (i = 0; i < 20; i++) {
-               printk("%02x", p[i]);
-       }
-       printk("\n");
-}
-#endif
-#endif
+#include <asm-xen/xen-public/memory.h>
+
 
 static void netif_idx_release(u16 pending_idx);
 static void netif_page_release(struct page *page);
@@ -56,7 +40,8 @@
 static struct sk_buff_head rx_queue;
 static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2+1];
 static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE];
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+
+#ifdef CONFIG_XEN_NETDEV_GRANT
 static gnttab_donate_t grant_rx_op[MAX_PENDING_REQS];
 #else
 static struct mmuext_op rx_mmuext[NETIF_RX_RING_SIZE];
@@ -87,16 +72,13 @@
 
 static struct sk_buff_head tx_queue;
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
 static u16 grant_tx_ref[MAX_PENDING_REQS];
 static gnttab_unmap_grant_ref_t tx_unmap_ops[MAX_PENDING_REQS];
 static gnttab_map_grant_ref_t tx_map_ops[MAX_PENDING_REQS];
+
 #else
 static multicall_entry_t tx_mcl[MAX_PENDING_REQS];
-#endif
-
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
-#define GRANT_INVALID_REF (0xFFFF)
 #endif
 
 static struct list_head net_schedule_list;
@@ -110,25 +92,37 @@
 static unsigned long alloc_mfn(void)
 {
     unsigned long mfn = 0, flags;
+    struct xen_memory_reservation reservation = {
+        .extent_start = mfn_list,
+        .nr_extents   = MAX_MFN_ALLOC,
+        .extent_order = 0,
+        .domid        = DOMID_SELF
+    };
     spin_lock_irqsave(&mfn_lock, flags);
     if ( unlikely(alloc_index == 0) )
-        alloc_index = HYPERVISOR_dom_mem_op(
-            MEMOP_increase_reservation, mfn_list, MAX_MFN_ALLOC, 0);
+        alloc_index = HYPERVISOR_memory_op(
+            XENMEM_increase_reservation, &reservation);
     if ( alloc_index != 0 )
         mfn = mfn_list[--alloc_index];
     spin_unlock_irqrestore(&mfn_lock, flags);
     return mfn;
 }
 
-#ifndef CONFIG_XEN_NETDEV_GRANT_RX
+#ifndef CONFIG_XEN_NETDEV_GRANT
 static void free_mfn(unsigned long mfn)
 {
     unsigned long flags;
+    struct xen_memory_reservation reservation = {
+        .extent_start = &mfn,
+        .nr_extents   = 1,
+        .extent_order = 0,
+        .domid        = DOMID_SELF
+    };
     spin_lock_irqsave(&mfn_lock, flags);
     if ( alloc_index != MAX_MFN_ALLOC )
         mfn_list[alloc_index++] = mfn;
-    else if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation,
-                                    &mfn, 1, 0) != 1 )
+    else if ( HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation)
+              != 1 )
         BUG();
     spin_unlock_irqrestore(&mfn_lock, flags);
 }
@@ -187,7 +181,7 @@
         dev_kfree_skb(skb);
         skb = nskb;
     }
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
 #ifdef DEBUG_GRANT
     printk(KERN_ALERT "#### be_xmit: req_prod=%d req_cons=%d id=%04x 
gr=%04x\n",
            netif->rx->req_prod,
@@ -233,12 +227,12 @@
 
 static void net_rx_action(unsigned long unused)
 {
-    netif_t *netif;
+    netif_t *netif = NULL; 
     s8 status;
     u16 size, id, evtchn;
     multicall_entry_t *mcl;
     mmu_update_t *mmu;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     gnttab_donate_t *gop;
 #else
     struct mmuext_op *mmuext;
@@ -253,7 +247,7 @@
 
     mcl = rx_mcl;
     mmu = rx_mmu;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     gop = grant_rx_op;
 #else
     mmuext = rx_mmuext;
@@ -269,7 +263,7 @@
         if ( (new_mfn = alloc_mfn()) == 0 )
         {
             if ( net_ratelimit() )
-                printk(KERN_WARNING "Memory squeeze in netback driver.\n");
+                WPRINTK("Memory squeeze in netback driver.\n");
             mod_timer(&net_timer, jiffies + HZ);
             skb_queue_head(&rx_queue, skb);
             break;
@@ -284,7 +278,7 @@
                                pfn_pte_ma(new_mfn, PAGE_KERNEL), 0);
         mcl++;
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
         gop->mfn = old_mfn;
         gop->domid = netif->domid;
         gop->handle = netif->rx->ring[
@@ -303,7 +297,7 @@
         mmuext->mfn = old_mfn;
         mmuext++;
 #endif
-        mmu->ptr = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
+        mmu->ptr = ((unsigned long long)new_mfn << PAGE_SHIFT) | 
MMU_MACHPHYS_UPDATE;
         mmu->val = __pa(vdata) >> PAGE_SHIFT;  
         mmu++;
 
@@ -327,7 +321,7 @@
     mcl->args[3] = DOMID_SELF;
     mcl++;
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     mcl[-2].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
 #else
     mcl[-3].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
@@ -336,9 +330,17 @@
         BUG();
 
     mcl = rx_mcl;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
-    BUG_ON(HYPERVISOR_grant_table_op(
-        GNTTABOP_donate, grant_rx_op, gop - grant_rx_op));
+#ifdef CONFIG_XEN_NETDEV_GRANT
+    if(HYPERVISOR_grant_table_op(GNTTABOP_donate, grant_rx_op, 
+                                 gop - grant_rx_op)) { 
+        /* 
+        ** The other side has given us a bad grant ref, or has no headroom, 
+        ** or has gone away. Unfortunately the current grant table code 
+        ** doesn't inform us which is the case, so not much we can do. 
+        */
+        DPRINTK("net_rx: donate to DOM%u failed; dropping (up to) %d "
+                "packets.\n", grant_rx_op[0].domid, gop - grant_rx_op); 
+    }
     gop = grant_rx_op;
 #else
     mmuext = rx_mmuext;
@@ -350,7 +352,7 @@
 
         /* Rederive the machine addresses. */
         new_mfn = mcl[0].args[1] >> PAGE_SHIFT;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
         old_mfn = 0; /* XXX Fix this so we can free_mfn() on error! */
 #else
         old_mfn = mmuext[0].mfn;
@@ -367,8 +369,13 @@
 
         /* Check the reassignment error code. */
         status = NETIF_RSP_OKAY;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
-        BUG_ON(gop->status != 0); /* XXX */
+#ifdef CONFIG_XEN_NETDEV_GRANT
+        if(gop->status != 0) { 
+            DPRINTK("Bad status %d from grant donate to DOM%u\n", 
+                    gop->status, netif->domid);
+            /* XXX SMH: should free 'old_mfn' here */
+            status = NETIF_RSP_ERROR; 
+        } 
 #else
         if ( unlikely(mcl[1].result != 0) )
         {
@@ -391,7 +398,7 @@
 
         netif_put(netif);
         dev_kfree_skb(skb);
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
         mcl++;
         gop++;
 #else
@@ -407,6 +414,7 @@
         notify_via_evtchn(evtchn);
     }
 
+  out: 
     /* More work to do? */
     if ( !skb_queue_empty(&rx_queue) && !timer_pending(&net_timer) )
         tasklet_schedule(&net_rx_tasklet);
@@ -483,7 +491,7 @@
 
 inline static void net_tx_action_dealloc(void)
 {
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     gnttab_unmap_grant_ref_t *gop;
 #else
     multicall_entry_t *mcl;
@@ -495,7 +503,7 @@
     dc = dealloc_cons;
     dp = dealloc_prod;
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     /*
      * Free up any grants we have finished using
      */
@@ -529,7 +537,7 @@
 #endif
     while ( dealloc_cons != dp )
     {
-#ifndef CONFIG_XEN_NETDEV_GRANT_TX
+#ifndef CONFIG_XEN_NETDEV_GRANT
         /* The update_va_mapping() must not fail. */
         BUG_ON(mcl[0].result != 0);
 #endif
@@ -556,7 +564,7 @@
         
         netif_put(netif);
 
-#ifndef CONFIG_XEN_NETDEV_GRANT_TX
+#ifndef CONFIG_XEN_NETDEV_GRANT
         mcl++;
 #endif
     }
@@ -572,7 +580,7 @@
     netif_tx_request_t txreq;
     u16 pending_idx;
     NETIF_RING_IDX i;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     gnttab_map_grant_ref_t *mop;
 #else
     multicall_entry_t *mcl;
@@ -582,7 +590,7 @@
     if ( dealloc_cons != dealloc_prod )
         net_tx_action_dealloc();
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     mop = tx_map_ops;
 #else
     mcl = tx_mcl;
@@ -683,7 +691,7 @@
 
         /* Packets passed to netif_rx() must have some headroom. */
         skb_reserve(skb, 16);
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
         mop->host_addr = MMAP_VADDR(pending_idx);
         mop->dom       = netif->domid;
         mop->ref       = txreq.addr >> PAGE_SHIFT;
@@ -706,7 +714,7 @@
 
         pending_cons++;
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
         if ( (mop - tx_map_ops) >= ARRAY_SIZE(tx_map_ops) )
             break;
 #else
@@ -716,7 +724,7 @@
 #endif
     }
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     if ( mop == tx_map_ops )
         return;
 
@@ -739,7 +747,7 @@
         memcpy(&txreq, &pending_tx_info[pending_idx].req, sizeof(txreq));
 
         /* Check the remap error code. */
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
         /* 
            XXX SMH: error returns from grant operations are pretty poorly
            specified/thought out, but the below at least conforms with 
@@ -813,7 +821,7 @@
         netif_rx(skb);
         netif->dev->last_rx = jiffies;
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
         mop++;
 #else
         mcl++;
@@ -932,16 +940,13 @@
     int i;
     struct page *page;
 
-    if ( !(xen_start_info.flags & SIF_NET_BE_DOMAIN) &&
-         !(xen_start_info.flags & SIF_INITDOMAIN) )
+    if ( !(xen_start_info->flags & SIF_NET_BE_DOMAIN) &&
+         !(xen_start_info->flags & SIF_INITDOMAIN) )
         return 0;
 
-    printk("Initialising Xen netif backend\n");
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
-    printk("#### netback tx using grant tables\n");
-#endif
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
-    printk("#### netback rx using grant tables\n");
+    IPRINTK("Initialising Xen netif backend.\n");
+#ifdef CONFIG_XEN_NETDEV_GRANT
+    IPRINTK("Using grant tables.\n");
 #endif
 
     /* We can increase reservation by this much in net_rx_action(). */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Sep  9 16:30:54 2005
@@ -160,9 +160,47 @@
                }
 #endif
 
+               kobject_hotplug(&dev->dev.kobj, KOBJ_ONLINE);
+
                /* Pass in NULL node to skip exist test. */
                frontend_changed(&be->watch, NULL);
        }
+}
+
+static int netback_hotplug(struct xenbus_device *xdev, char **envp,
+                          int num_envp, char *buffer, int buffer_size)
+{
+       struct backend_info *be;
+       netif_t *netif;
+       char **key, *val;
+       int i = 0, length = 0;
+       static char *env_vars[] = { "script", "domain", "mac", "bridge", "ip",
+                                   NULL };
+
+       be = xdev->data;
+       netif = be->netif;
+
+       add_hotplug_env_var(envp, num_envp, &i,
+                           buffer, buffer_size, &length,
+                           "vif=%s", netif->dev->name);
+
+       key = env_vars;
+       while (*key != NULL) {
+               val = xenbus_read(xdev->nodename, *key, NULL);
+               if (!IS_ERR(val)) {
+                       char buf[strlen(*key) + 4];
+                       sprintf(buf, "%s=%%s", *key);
+                       add_hotplug_env_var(envp, num_envp, &i,
+                                           buffer, buffer_size, &length,
+                                           buf, val);
+                       kfree(val);
+               }
+               key++;
+       }
+
+       envp[i] = NULL;
+
+       return 0;
 }
 
 static int netback_probe(struct xenbus_device *dev,
@@ -249,6 +287,7 @@
        .ids = netback_ids,
        .probe = netback_probe,
        .remove = netback_remove,
+       .hotplug = netback_hotplug,
 };
 
 void netif_xenbus_init(void)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Fri Sep  9 
16:30:54 2005
@@ -50,13 +50,23 @@
 #include <asm-xen/evtchn.h>
 #include <asm-xen/xenbus.h>
 #include <asm-xen/xen-public/io/netif.h>
+#include <asm-xen/xen-public/memory.h>
 #include <asm-xen/balloon.h>
 #include <asm/page.h>
 #include <asm/uaccess.h>
 
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
+#ifdef CONFIG_XEN_NETDEV_GRANT
 #include <asm-xen/xen-public/grant_table.h>
 #include <asm-xen/gnttab.h>
+
+static grant_ref_t gref_tx_head;
+static grant_ref_t grant_tx_ref[NETIF_TX_RING_SIZE + 1]; 
+
+static grant_ref_t gref_rx_head;
+static grant_ref_t grant_rx_ref[NETIF_RX_RING_SIZE + 1];
+
+#define GRANT_INVALID_REF      (0xFFFF)
+
 #ifdef GRANT_DEBUG
 static void
 dump_packet(int tag, void *addr, u32 ap)
@@ -70,8 +80,17 @@
     }
     printk("\n");
 }
-#endif
-#endif
+
+#define GDPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
+                           __FILE__ , __LINE__ , ## _a )
+#else 
+#define dump_packet(x,y,z)  ((void)0)  
+#define GDPRINTK(_f, _a...) ((void)0)
+#endif
+
+#endif
+
+
 
 #ifndef __GFP_NOWARN
 #define __GFP_NOWARN 0
@@ -101,22 +120,10 @@
 #define TX_TEST_IDX req_cons  /* conservative: not seen all our requests? */
 #endif
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
-static grant_ref_t gref_tx_head;
-static grant_ref_t grant_tx_ref[NETIF_TX_RING_SIZE + 1];
-#endif
-
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
-static grant_ref_t gref_rx_head;
-static grant_ref_t grant_rx_ref[NETIF_RX_RING_SIZE + 1];
-#endif
-
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
-#define GRANT_INVALID_REF      (0xFFFF)
-#endif
 
 #define NETIF_STATE_DISCONNECTED 0
 #define NETIF_STATE_CONNECTED    1
+
 
 static unsigned int netif_state = NETIF_STATE_DISCONNECTED;
 
@@ -278,7 +285,7 @@
         for (i = np->tx_resp_cons; i != prod; i++) {
             id  = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id;
             skb = np->tx_skbs[id];
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
             if (unlikely(gnttab_query_foreign_access(grant_tx_ref[id]) != 0)) {
                 /* other domain is still using this grant - shouldn't happen
                    but if it does, we'll try to reclaim the grant later */
@@ -309,7 +316,7 @@
         mb();
     } while (prod != np->tx->resp_prod);
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
   out: 
 #endif
 
@@ -328,8 +335,9 @@
     struct sk_buff *skb;
     int i, batch_target;
     NETIF_RING_IDX req_prod = np->rx->req_prod;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
-    int ref;
+    struct xen_memory_reservation reservation;
+#ifdef CONFIG_XEN_NETDEV_GRANT
+    grant_ref_t ref;
 #endif
 
     if (unlikely(np->backend_state != BEST_CONNECTED))
@@ -363,9 +371,9 @@
         np->rx_skbs[id] = skb;
         
         np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.id = id;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
        ref = gnttab_claim_grant_reference(&gref_rx_head);
-        if (unlikely(ref < 0)) {
+        if (unlikely((signed short)ref < 0)) {
             printk(KERN_ALERT "#### netfront can't claim rx reference\n");
             BUG();
         }
@@ -388,12 +396,15 @@
     rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
 
     /* Give away a batch of pages. */
-    rx_mcl[i].op = __HYPERVISOR_dom_mem_op;
-    rx_mcl[i].args[0] = MEMOP_decrease_reservation;
-    rx_mcl[i].args[1] = (unsigned long)rx_pfn_array;
-    rx_mcl[i].args[2] = (unsigned long)i;
-    rx_mcl[i].args[3] = 0;
-    rx_mcl[i].args[4] = DOMID_SELF;
+    rx_mcl[i].op = __HYPERVISOR_memory_op;
+    rx_mcl[i].args[0] = XENMEM_decrease_reservation;
+    rx_mcl[i].args[1] = (unsigned long)&reservation;
+
+    reservation.extent_start = rx_pfn_array;
+    reservation.nr_extents   = i;
+    reservation.extent_order = 0;
+    reservation.address_bits = 0;
+    reservation.domid        = DOMID_SELF;
 
     /* Tell the ballon driver what is going on. */
     balloon_update_driver_allowance(i);
@@ -401,7 +412,7 @@
     /* Zap PTEs and give away pages in one big multicall. */
     (void)HYPERVISOR_multicall(rx_mcl, i+1);
 
-    /* Check return status of HYPERVISOR_dom_mem_op(). */
+    /* Check return status of HYPERVISOR_memory_op(). */
     if (unlikely(rx_mcl[i].result != i))
         panic("Unable to reduce memory reservation\n");
 
@@ -421,8 +432,8 @@
     struct net_private *np = netdev_priv(dev);
     netif_tx_request_t *tx;
     NETIF_RING_IDX i;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
-    unsigned int ref;
+#ifdef CONFIG_XEN_NETDEV_GRANT
+    grant_ref_t ref;
     unsigned long mfn;
 #endif
 
@@ -459,9 +470,9 @@
     tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req;
 
     tx->id   = id;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     ref = gnttab_claim_grant_reference(&gref_tx_head);
-    if (unlikely(ref < 0)) {
+    if (unlikely((signed short)ref < 0)) {
         printk(KERN_ALERT "#### netfront can't claim tx grant reference\n");
         BUG();
     }
@@ -514,7 +525,7 @@
     network_tx_buf_gc(dev);
     spin_unlock_irqrestore(&np->tx_lock, flags);
 
-    if ((np->rx_resp_cons != np->rx->resp_prod) && (np->user_state == 
UST_OPEN))
+    if((np->rx_resp_cons != np->rx->resp_prod) && (np->user_state == UST_OPEN))
         netif_rx_schedule(dev);
 
     return IRQ_HANDLED;
@@ -532,7 +543,7 @@
     int work_done, budget, more_to_do = 1;
     struct sk_buff_head rxq;
     unsigned long flags;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     unsigned long mfn;
     grant_ref_t ref;
 #endif
@@ -569,8 +580,19 @@
             continue;
         }
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
-        ref = grant_rx_ref[rx->id];
+#ifdef CONFIG_XEN_NETDEV_GRANT
+        ref = grant_rx_ref[rx->id]; 
+
+        if(ref == GRANT_INVALID_REF) { 
+            printk(KERN_WARNING "Bad rx grant reference %d from dom %d.\n",
+                   ref, np->backend_id);
+            np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].req.id = rx->id;
+            wmb();
+            np->rx->req_prod++;
+            work_done--;
+            continue;
+        }
+
         grant_rx_ref[rx->id] = GRANT_INVALID_REF;
         mfn = gnttab_end_foreign_transfer_ref(ref);
         gnttab_release_grant_reference(&gref_rx_head, ref);
@@ -580,7 +602,7 @@
         ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
 
         /* NB. We handle skb overflow later. */
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
         skb->data = skb->head + rx->addr;
 #else
         skb->data = skb->head + (rx->addr & ~PAGE_MASK);
@@ -595,14 +617,14 @@
         np->stats.rx_bytes += rx->status;
 
         /* Remap the page. */
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
-        mmu->ptr = mfn << PAGE_SHIFT | MMU_MACHPHYS_UPDATE;
+#ifdef CONFIG_XEN_NETDEV_GRANT
+        mmu->ptr = ((unsigned long long)mfn << PAGE_SHIFT) | 
MMU_MACHPHYS_UPDATE;
 #else
         mmu->ptr  = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE;
 #endif
         mmu->val  = __pa(skb->head) >> PAGE_SHIFT;
         mmu++;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
        MULTI_update_va_mapping(mcl, (unsigned long)skb->head,
                                pfn_pte_ma(mfn, PAGE_KERNEL), 0);
 #else
@@ -612,19 +634,19 @@
 #endif
         mcl++;
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
         phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = mfn;
+        GDPRINTK("#### rx_poll     enqueue vdata=%p mfn=%lu ref=%x\n",
+                skb->data, mfn, ref);
 #else
         phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = 
             rx->addr >> PAGE_SHIFT;
-#endif
-
-#ifdef GRANT_DEBUG
-        printk(KERN_ALERT "#### rx_poll     enqueue vdata=%p mfn=%lu ref=%x\n",
-               skb->data, mfn, ref);
-#endif
+#endif 
+
+
         __skb_queue_tail(&rxq, skb);
     }
+
 
     /* Some pages are no longer absent... */
     balloon_update_driver_allowance(-work_done);
@@ -641,9 +663,9 @@
     }
 
     while ((skb = __skb_dequeue(&rxq)) != NULL) {
-#ifdef GRANT_DEBUG
-        printk(KERN_ALERT "#### rx_poll     dequeue vdata=%p mfn=%lu\n",
-               skb->data, virt_to_mfn(skb->data));
+#ifdef CONFIG_XEN_NETDEV_GRANT
+        GDPRINTK("#### rx_poll     dequeue vdata=%p mfn=%lu\n",
+                skb->data, virt_to_mfn(skb->data));
         dump_packet('d', skb->data, (unsigned long)skb->data);
 #endif
         /*
@@ -742,7 +764,6 @@
     return &np->stats;
 }
 
-
 static void network_connect(struct net_device *dev)
 {
     struct net_private *np;
@@ -782,8 +803,11 @@
             tx = &np->tx->ring[requeue_idx++].req;
 
             tx->id   = i;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
-            tx->addr = 0; /*(ref << PAGE_SHIFT) |*/
+#ifdef CONFIG_XEN_NETDEV_GRANT
+            gnttab_grant_foreign_access_ref(grant_tx_ref[i], np->backend_id, 
+                                            virt_to_mfn(np->tx_skbs[i]->data),
+                                            GNTMAP_readonly); 
+            tx->addr = grant_tx_ref[i] << PAGE_SHIFT; 
 #else
             tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT;
 #endif
@@ -798,9 +822,20 @@
     np->tx->req_prod = requeue_idx;
 
     /* Rebuild the RX buffer freelist and the RX ring itself. */
-    for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++)
-        if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET)
-            np->rx->ring[requeue_idx++].req.id = i;
+    for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++) { 
+        if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET) {
+#ifdef CONFIG_XEN_NETDEV_GRANT 
+            /* Reinstate the grant ref so backend can 'donate' mfn to us. */
+            gnttab_grant_foreign_transfer_ref(grant_rx_ref[i], np->backend_id,
+                                              virt_to_mfn(np->rx_skbs[i]->head)
+                );
+            np->rx->ring[requeue_idx].req.gref = grant_rx_ref[i];
+#endif
+            np->rx->ring[requeue_idx].req.id   = i;
+            requeue_idx++; 
+        }
+    }
+
     wmb();                
     np->rx->req_prod = requeue_idx;
 
@@ -896,13 +931,14 @@
     /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */
     for (i = 0; i <= NETIF_TX_RING_SIZE; i++) {
         np->tx_skbs[i] = (void *)((unsigned long) i+1);
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
         grant_tx_ref[i] = GRANT_INVALID_REF;
 #endif
     }
+
     for (i = 0; i <= NETIF_RX_RING_SIZE; i++) {
         np->rx_skbs[i] = (void *)((unsigned long) i+1);
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
         grant_rx_ref[i] = GRANT_INVALID_REF;
 #endif
     }
@@ -986,10 +1022,8 @@
        evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
        int err;
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
        info->tx_ring_ref = GRANT_INVALID_REF;
-#endif
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
        info->rx_ring_ref = GRANT_INVALID_REF;
 #endif
 
@@ -1009,7 +1043,7 @@
        memset(info->rx, 0, PAGE_SIZE);
        info->backend_state = BEST_DISCONNECTED;
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
        err = gnttab_grant_foreign_access(info->backend_id,
                                          virt_to_mfn(info->tx), 0);
        if (err < 0) {
@@ -1017,11 +1051,7 @@
                goto out;
        }
        info->tx_ring_ref = err;
-#else
-       info->tx_ring_ref = virt_to_mfn(info->tx);
-#endif
-
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+
        err = gnttab_grant_foreign_access(info->backend_id,
                                          virt_to_mfn(info->rx), 0);
        if (err < 0) {
@@ -1029,7 +1059,9 @@
                goto out;
        }
        info->rx_ring_ref = err;
+
 #else
+       info->tx_ring_ref = virt_to_mfn(info->tx);
        info->rx_ring_ref = virt_to_mfn(info->rx);
 #endif
 
@@ -1049,16 +1081,17 @@
        if (info->rx)
                free_page((unsigned long)info->rx);
        info->rx = 0;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+
+#ifdef CONFIG_XEN_NETDEV_GRANT
        if (info->tx_ring_ref != GRANT_INVALID_REF)
                gnttab_end_foreign_access(info->tx_ring_ref, 0);
        info->tx_ring_ref = GRANT_INVALID_REF;
-#endif
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+
        if (info->rx_ring_ref != GRANT_INVALID_REF)
                gnttab_end_foreign_access(info->rx_ring_ref, 0);
        info->rx_ring_ref = GRANT_INVALID_REF;
 #endif
+
        return err;
 }
 
@@ -1070,16 +1103,17 @@
        if (info->rx)
                free_page((unsigned long)info->rx);
        info->rx = 0;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+
+#ifdef CONFIG_XEN_NETDEV_GRANT
        if (info->tx_ring_ref != GRANT_INVALID_REF)
                gnttab_end_foreign_access(info->tx_ring_ref, 0);
        info->tx_ring_ref = GRANT_INVALID_REF;
-#endif
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+
        if (info->rx_ring_ref != GRANT_INVALID_REF)
                gnttab_end_foreign_access(info->rx_ring_ref, 0);
        info->rx_ring_ref = GRANT_INVALID_REF;
 #endif
+
        unbind_evtchn_from_irqhandler(info->evtchn, info->netdev);
        info->evtchn = 0;
 }
@@ -1272,25 +1306,25 @@
 
 static int netfront_suspend(struct xenbus_device *dev)
 {
-    struct net_private *np = dev->data;
-    /* Avoid having tx/rx stuff happen until we're ready. */
-    unbind_evtchn_from_irqhandler(np->evtchn, np->netdev);
-    return 0;
+       struct netfront_info *info = dev->data;
+
+       unregister_xenbus_watch(&info->watch);
+       kfree(info->backend);
+       info->backend = NULL;
+
+       netif_free(info);
+
+       return 0;
 }
 
 static int netfront_resume(struct xenbus_device *dev)
 {
-    struct net_private *np = dev->data;
-    /*
-     * Connect regardless of whether IFF_UP flag set.
-     * Stop bad things from happening until we're back up.
-     */
-    np->backend_state = BEST_DISCONNECTED;
-    memset(np->tx, 0, PAGE_SIZE);
-    memset(np->rx, 0, PAGE_SIZE);
-    
-    // send_interface_connect(np);
-    return 0;
+       struct net_private *np = dev->data;
+       int err;
+
+       err = talk_to_backend(dev, np);
+
+       return err;
 }
 
 static struct xenbus_driver netfront = {
@@ -1335,32 +1369,31 @@
 {
     int err = 0;
 
-    if (xen_start_info.flags & SIF_INITDOMAIN)
+    if (xen_start_info->flags & SIF_INITDOMAIN)
         return 0;
 
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
-    /* A grant for every ring slot */
+    if ((err = xennet_proc_init()) != 0)
+        return err;
+
+    IPRINTK("Initialising virtual ethernet driver.\n");
+
+#ifdef CONFIG_XEN_NETDEV_GRANT
+    IPRINTK("Using grant tables.\n"); 
+
+    /* A grant for every tx ring slot */
     if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE,
                                       &gref_tx_head) < 0) {
         printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
         return 1;
     }
-    printk(KERN_ALERT "Netdev frontend (TX) is using grant tables.\n"); 
-#endif
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
-    /* A grant for every ring slot */
+    /* A grant for every rx ring slot */
     if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE,
                                       &gref_rx_head) < 0) {
         printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n");
         return 1;
     }
-    printk(KERN_ALERT "Netdev frontend (RX) is using grant tables.\n"); 
-#endif
-
-    if ((err = xennet_proc_init()) != 0)
-        return err;
-
-    IPRINTK("Initialising virtual ethernet driver.\n");
+#endif
+
 
     (void)register_inetaddr_notifier(&notifier_inetdev);
 
@@ -1373,10 +1406,8 @@
 
 static void netif_exit(void)
 {
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     gnttab_free_grant_references(gref_tx_head);
-#endif
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
     gnttab_free_grant_references(gref_rx_head);
 #endif
 }
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
--- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c        Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c        Fri Sep  9 
16:30:54 2005
@@ -63,27 +63,23 @@
             "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
             : "=a" (ret) : "0" (&hypercall) : "memory" );
 #elif defined (__x86_64__)
-       __asm__ __volatile__ (
-           "movq   %5,%%r10; movq %6,%%r8;" TRAP_INSTR
-           : "=a" (ret)
-           : "a" ((unsigned long)hypercall.op), 
-             "D" ((unsigned long)hypercall.arg[0]), 
-             "S" ((unsigned long)hypercall.arg[1]),
-             "d" ((unsigned long)hypercall.arg[2]), 
-             "g" ((unsigned long)hypercall.arg[3]),
-             "g" ((unsigned long)hypercall.arg[4])
-           : "r11","rcx","r8","r10","memory");
+        {
+            long ign1, ign2, ign3;
+            __asm__ __volatile__ (
+                "movq %8,%%r10; movq %9,%%r8;" TRAP_INSTR
+                : "=a" (ret), "=D" (ign1), "=S" (ign2), "=d" (ign3)
+                : "0" ((unsigned long)hypercall.op), 
+                "1" ((unsigned long)hypercall.arg[0]), 
+                "2" ((unsigned long)hypercall.arg[1]),
+                "3" ((unsigned long)hypercall.arg[2]), 
+                "g" ((unsigned long)hypercall.arg[3]),
+                "g" ((unsigned long)hypercall.arg[4])
+                : "r11","rcx","r8","r10","memory");
+        }
 #endif
     }
     break;
 
-    case IOCTL_PRIVCMD_INITDOMAIN_EVTCHN:
-    {
-        extern int initdom_ctrlif_domcontroller_port;
-        ret = initdom_ctrlif_domcontroller_port;
-    }
-    break;
-    
 #if defined(CONFIG_XEN_PRIVILEGED_GUEST)
     case IOCTL_PRIVCMD_MMAP:
     {
@@ -120,9 +116,9 @@
                 if ( (msg[j].va + (msg[j].npages<<PAGE_SHIFT)) > vma->vm_end )
                     return -EINVAL;
 
-                if ( (rc = direct_remap_area_pages(vma->vm_mm, 
+                if ( (rc = direct_remap_pfn_range(vma->vm_mm, 
                                                    msg[j].va&PAGE_MASK, 
-                                                   msg[j].mfn<<PAGE_SHIFT, 
+                                                   msg[j].mfn, 
                                                    msg[j].npages<<PAGE_SHIFT, 
                                                    vma->vm_page_prot,
                                                    mmapcmd.dom)) < 0 )
@@ -202,8 +198,8 @@
         extern int do_xenbus_probe(void*);
         unsigned long page;
 
-        if (xen_start_info.store_evtchn != 0) {
-            ret = xen_start_info.store_mfn;
+        if (xen_start_info->store_evtchn != 0) {
+            ret = xen_start_info->store_mfn;
             break;
         }
 
@@ -219,10 +215,10 @@
         SetPageReserved(virt_to_page(page));
 
         /* Initial connect. Setup channel and page. */
-        xen_start_info.store_evtchn = data;
-        xen_start_info.store_mfn = pfn_to_mfn(virt_to_phys((void *)page) >>
+        xen_start_info->store_evtchn = data;
+        xen_start_info->store_mfn = pfn_to_mfn(virt_to_phys((void *)page) >>
                                               PAGE_SHIFT);
-        ret = xen_start_info.store_mfn;
+        ret = xen_start_info->store_mfn;
 
         /* We'll return then this will wait for daemon to answer */
         kthread_run(do_xenbus_probe, NULL, "xenbus_probe");
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/usbback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/usbback/common.h Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/usbback/common.h Fri Sep  9 16:30:54 2005
@@ -12,7 +12,6 @@
 #include <asm/io.h>
 #include <asm/setup.h>
 #include <asm/pgalloc.h>
-#include <asm-xen/ctrl_if.h>
 #include <asm-xen/hypervisor.h>
 
 #include <asm-xen/xen-public/io/usbif.h>
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/usbback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/usbback/interface.c      Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/usbback/interface.c      Fri Sep  9 
16:30:54 2005
@@ -161,8 +161,8 @@
     }
 
     prot = __pgprot(_KERNPG_TABLE);
-    error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr),
-                                    shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
+    error = direct_remap_pfn_range(&init_mm, VMALLOC_VMADDR(vma->addr),
+                                    shmem_frame, PAGE_SIZE,
                                     prot, domid);
     if ( error != 0 )
     {
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c
--- a/linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c        Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c        Fri Sep  9 
16:30:54 2005
@@ -1029,8 +1029,8 @@
     int i;
     struct page *page;
 
-    if ( !(xen_start_info.flags & SIF_INITDOMAIN) &&
-         !(xen_start_info.flags & SIF_USB_BE_DOMAIN) )
+    if ( !(xen_start_info->flags & SIF_INITDOMAIN) &&
+         !(xen_start_info->flags & SIF_USB_BE_DOMAIN) )
         return 0;
 
     page = balloon_alloc_empty_page_range(MMAP_PAGES);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/usbfront/usbfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/usbfront/usbfront.c      Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/usbfront/usbfront.c      Fri Sep  9 
16:30:54 2005
@@ -70,7 +70,6 @@
 #include "../../../../../drivers/usb/hcd.h"
 
 #include <asm-xen/xen-public/io/usbif.h>
-#include <asm/ctrl_if.h>
 #include <asm/xen-public/io/domain_controller.h>
 
 /*
@@ -1675,8 +1674,8 @@
 {
        int retval = -ENOMEM, i;
 
-       if ( (xen_start_info.flags & SIF_INITDOMAIN)
-            || (xen_start_info.flags & SIF_USB_BE_DOMAIN) )
+       if ( (xen_start_info->flags & SIF_INITDOMAIN) ||
+            (xen_start_info->flags & SIF_USB_BE_DOMAIN) )
                 return 0;
 
        info(DRIVER_DESC " " DRIVER_VERSION);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile  Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile  Fri Sep  9 16:30:54 2005
@@ -4,3 +4,4 @@
 xenbus-objs += xenbus_comms.o
 xenbus-objs += xenbus_xs.o
 xenbus-objs += xenbus_probe.o 
+xenbus-objs += xenbus_dev.o 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c    Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c    Fri Sep  9 
16:30:54 2005
@@ -48,12 +48,12 @@
 
 static inline struct ringbuf_head *outbuf(void)
 {
-       return mfn_to_virt(xen_start_info.store_mfn);
+       return mfn_to_virt(xen_start_info->store_mfn);
 }
 
 static inline struct ringbuf_head *inbuf(void)
 {
-       return mfn_to_virt(xen_start_info.store_mfn) + PAGE_SIZE/2;
+       return mfn_to_virt(xen_start_info->store_mfn) + PAGE_SIZE/2;
 }
 
 static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs)
@@ -145,7 +145,7 @@
                data += avail;
                len -= avail;
                update_output_chunk(out, avail);
-               notify_via_evtchn(xen_start_info.store_evtchn);
+               notify_via_evtchn(xen_start_info->store_evtchn);
        } while (len != 0);
 
        return 0;
@@ -190,7 +190,7 @@
                pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
                /* If it was full, tell them we've taken some. */
                if (was_full)
-                       notify_via_evtchn(xen_start_info.store_evtchn);
+                       notify_via_evtchn(xen_start_info->store_evtchn);
        }
 
        /* If we left something, wake watch thread to deal with it. */
@@ -205,20 +205,20 @@
 {
        int err;
 
-       if (!xen_start_info.store_evtchn)
+       if (!xen_start_info->store_evtchn)
                return 0;
 
        err = bind_evtchn_to_irqhandler(
-               xen_start_info.store_evtchn, wake_waiting,
+               xen_start_info->store_evtchn, wake_waiting,
                0, "xenbus", &xb_waitq);
        if (err) {
                printk(KERN_ERR "XENBUS request irq failed %i\n", err);
-               unbind_evtchn_from_irq(xen_start_info.store_evtchn);
+               unbind_evtchn_from_irq(xen_start_info->store_evtchn);
                return err;
        }
 
        /* FIXME zero out page -- domain builder should probably do this*/
-       memset(mfn_to_virt(xen_start_info.store_mfn), 0, PAGE_SIZE);
+       memset(mfn_to_virt(xen_start_info->store_mfn), 0, PAGE_SIZE);
 
        return 0;
 }
@@ -226,8 +226,8 @@
 void xb_suspend_comms(void)
 {
 
-       if (!xen_start_info.store_evtchn)
+       if (!xen_start_info->store_evtchn)
                return;
 
-       unbind_evtchn_from_irqhandler(xen_start_info.store_evtchn, &xb_waitq);
-}
+       unbind_evtchn_from_irqhandler(xen_start_info->store_evtchn, &xb_waitq);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c    Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c    Fri Sep  9 
16:30:54 2005
@@ -147,6 +147,39 @@
        return 0;
 }
 
+static int xenbus_hotplug_backend(struct device *dev, char **envp,
+                                 int num_envp, char *buffer, int buffer_size)
+{
+       struct xenbus_device *xdev;
+       int i = 0;
+       int length = 0;
+
+       if (dev == NULL)
+               return -ENODEV;
+
+       xdev = to_xenbus_device(dev);
+       if (xdev == NULL)
+               return -ENODEV;
+
+       /* stuff we want to pass to /sbin/hotplug */
+       add_hotplug_env_var(envp, num_envp, &i,
+                           buffer, buffer_size, &length,
+                           "XENBUS_TYPE=%s", xdev->devicetype);
+
+       /* terminate, set to next free slot, shrink available space */
+       envp[i] = NULL;
+       envp = &envp[i];
+       num_envp -= i;
+       buffer = &buffer[length];
+       buffer_size -= length;
+
+       if (dev->driver && to_xenbus_driver(dev->driver)->hotplug)
+               return to_xenbus_driver(dev->driver)->hotplug
+                       (xdev, envp, num_envp, buffer, buffer_size);
+
+       return 0;
+}
+
 static int xenbus_probe_backend(const char *type, const char *uuid);
 static struct xen_bus_type xenbus_backend = {
        .root = "backend",
@@ -156,6 +189,7 @@
        .bus = {
                .name  = "xen-backend",
                .match = xenbus_match,
+               .hotplug = xenbus_hotplug_backend,
        },
        .dev = {
                .bus_id = "xen-backend",
@@ -209,6 +243,7 @@
 {
        return xenbus_register_driver(drv, &xenbus_frontend);
 }
+EXPORT_SYMBOL(xenbus_register_device);
 
 int xenbus_register_backend(struct xenbus_driver *drv)
 {
@@ -586,7 +621,7 @@
 
        down(&xenbus_lock);
 
-       if (xen_start_info.store_evtchn) {
+       if (xen_start_info->store_evtchn) {
                ret = nb->notifier_call(nb, 0, NULL);
        } else {
                notifier_chain_register(&xenstore_chain, nb);
@@ -612,7 +647,7 @@
        int err = 0;
 
        /* Initialize xenstore comms unless already done. */
-       printk("store_evtchn = %i\n", xen_start_info.store_evtchn);
+       printk("store_evtchn = %i\n", xen_start_info->store_evtchn);
        err = xs_init();
        if (err) {
                printk("XENBUS: Error initializing xenstore comms:"
@@ -640,7 +675,7 @@
        device_register(&xenbus_frontend.dev);
        device_register(&xenbus_backend.dev);
 
-       if (!xen_start_info.store_evtchn)
+       if (!xen_start_info->store_evtchn)
                return 0;
 
        do_xenbus_probe(NULL);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c       Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c       Fri Sep  9 
16:30:54 2005
@@ -45,7 +45,9 @@
 
 static char printf_buffer[4096];
 static LIST_HEAD(watches);
+
 DECLARE_MUTEX(xenbus_lock);
+EXPORT_SYMBOL(xenbus_lock);
 
 static int get_error(const char *errorstring)
 {
@@ -104,10 +106,10 @@
 }
 
 /* Send message to xs, get kmalloc'ed reply.  ERR_PTR() on error. */
-static void *xs_talkv(enum xsd_sockmsg_type type,
-                     const struct kvec *iovec,
-                     unsigned int num_vecs,
-                     unsigned int *len)
+void *xs_talkv(enum xsd_sockmsg_type type,
+              const struct kvec *iovec,
+              unsigned int num_vecs,
+              unsigned int *len)
 {
        struct xsd_sockmsg msg;
        void *ret = NULL;
@@ -224,6 +226,7 @@
                ret[(*num)++] = p;
        return ret;
 }
+EXPORT_SYMBOL(xenbus_directory);
 
 /* Check if a path exists. Return 1 if it does. */
 int xenbus_exists(const char *dir, const char *node)
@@ -237,6 +240,7 @@
        kfree(d);
        return 1;
 }
+EXPORT_SYMBOL(xenbus_exists);
 
 /* Get the value of a single file.
  * Returns a kmalloced value: call free() on it after use.
@@ -246,6 +250,7 @@
 {
        return xs_single(XS_READ, join(dir, node), len);
 }
+EXPORT_SYMBOL(xenbus_read);
 
 /* Write the value of a single file.
  * Returns -err on failure.  createflags can be 0, O_CREAT, or O_CREAT|O_EXCL.
@@ -276,18 +281,21 @@
 
        return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
 }
+EXPORT_SYMBOL(xenbus_write);
 
 /* Create a new directory. */
 int xenbus_mkdir(const char *dir, const char *node)
 {
        return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL));
 }
+EXPORT_SYMBOL(xenbus_mkdir);
 
 /* Destroy a file or directory (directories must be empty). */
 int xenbus_rm(const char *dir, const char *node)
 {
        return xs_error(xs_single(XS_RM, join(dir, node), NULL));
 }
+EXPORT_SYMBOL(xenbus_rm);
 
 /* Start a transaction: changes by others will not be seen during this
  * transaction, and changes will not be visible to others until end.
@@ -298,6 +306,7 @@
 {
        return xs_error(xs_single(XS_TRANSACTION_START, subtree, NULL));
 }
+EXPORT_SYMBOL(xenbus_transaction_start);
 
 /* End a transaction.
  * If abandon is true, transaction is discarded instead of committed.
@@ -312,6 +321,7 @@
                strcpy(abortstr, "T");
        return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
 }
+EXPORT_SYMBOL(xenbus_transaction_end);
 
 /* Single read and scanf: returns -errno or num scanned. */
 int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
@@ -333,6 +343,7 @@
                return -ERANGE;
        return ret;
 }
+EXPORT_SYMBOL(xenbus_scanf);
 
 /* Single printf and write: returns -errno or 0. */
 int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
@@ -348,6 +359,7 @@
        BUG_ON(ret > sizeof(printf_buffer)-1);
        return xenbus_write(dir, node, printf_buffer, O_CREAT);
 }
+EXPORT_SYMBOL(xenbus_printf);
 
 /* Report a (negative) errno into the store, with explanation. */
 void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...)
@@ -369,6 +381,7 @@
                printk("xenbus: failed to write error node for %s (%s)\n",
                       dev->nodename, printf_buffer);
 }
+EXPORT_SYMBOL(xenbus_dev_error);
 
 /* Clear any error. */
 void xenbus_dev_ok(struct xenbus_device *dev)
@@ -381,6 +394,7 @@
                        dev->has_error = 0;
        }
 }
+EXPORT_SYMBOL(xenbus_dev_ok);
        
 /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
 int xenbus_gather(const char *dir, ...)
@@ -410,6 +424,7 @@
        va_end(ap);
        return ret;
 }
+EXPORT_SYMBOL(xenbus_gather);
 
 static int xs_watch(const char *path, const char *token)
 {
@@ -482,6 +497,7 @@
                list_add(&watch->list, &watches);
        return err;
 }
+EXPORT_SYMBOL(register_xenbus_watch);
 
 void unregister_xenbus_watch(struct xenbus_watch *watch)
 {
@@ -499,6 +515,7 @@
                       "XENBUS Failed to release watch %s: %i\n",
                       watch->node, err);
 }
+EXPORT_SYMBOL(unregister_xenbus_watch);
 
 /* Re-register callbacks to all watches. */
 void reregister_xenbus_watches(void)
@@ -540,7 +557,7 @@
                        BUG_ON(!w);
                        w->callback(w, node);
                        kfree(node);
-               } else
+               } else if (node)
                        printk(KERN_WARNING "XENBUS xs_read_watch: %li\n",
                               PTR_ERR(node));
                up(&xenbus_lock);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Fri Sep  9 
16:30:54 2005
@@ -29,551 +29,360 @@
 
 #ifndef __HYPERCALL_H__
 #define __HYPERCALL_H__
+
 #include <asm-xen/xen-public/xen.h>
 
-/*
- * Assembler stubs for hyper-calls.
- */
+#define _hypercall0(type, name)                        \
+({                                             \
+       long __res;                             \
+       asm volatile (                          \
+               TRAP_INSTR                      \
+               : "=a" (__res)                  \
+               : "0" (__HYPERVISOR_##name)     \
+               : "memory" );                   \
+       (type)__res;                            \
+})
+
+#define _hypercall1(type, name, a1)                            \
+({                                                             \
+       long __res, __ign1;                                     \
+       asm volatile (                                          \
+               TRAP_INSTR                                      \
+               : "=a" (__res), "=b" (__ign1)                   \
+               : "0" (__HYPERVISOR_##name), "1" ((long)(a1))   \
+               : "memory" );                                   \
+       (type)__res;                                            \
+})
+
+#define _hypercall2(type, name, a1, a2)                                \
+({                                                             \
+       long __res, __ign1, __ign2;                             \
+       asm volatile (                                          \
+               TRAP_INSTR                                      \
+               : "=a" (__res), "=b" (__ign1), "=c" (__ign2)    \
+               : "0" (__HYPERVISOR_##name), "1" ((long)(a1)),  \
+               "2" ((long)(a2))                                \
+               : "memory" );                                   \
+       (type)__res;                                            \
+})
+
+#define _hypercall3(type, name, a1, a2, a3)                    \
+({                                                             \
+       long __res, __ign1, __ign2, __ign3;                     \
+       asm volatile (                                          \
+               TRAP_INSTR                                      \
+               : "=a" (__res), "=b" (__ign1), "=c" (__ign2),   \
+               "=d" (__ign3)                                   \
+               : "0" (__HYPERVISOR_##name), "1" ((long)(a1)),  \
+               "2" ((long)(a2)), "3" ((long)(a3))              \
+               : "memory" );                                   \
+       (type)__res;                                            \
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4)                        \
+({                                                             \
+       long __res, __ign1, __ign2, __ign3, __ign4;             \
+       asm volatile (                                          \
+               TRAP_INSTR                                      \
+               : "=a" (__res), "=b" (__ign1), "=c" (__ign2),   \
+               "=d" (__ign3), "=S" (__ign4)                    \
+               : "0" (__HYPERVISOR_##name), "1" ((long)(a1)),  \
+               "2" ((long)(a2)), "3" ((long)(a3)),             \
+               "4" ((long)(a4))                                \
+               : "memory" );                                   \
+       (type)__res;                                            \
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5)            \
+({                                                             \
+       long __res, __ign1, __ign2, __ign3, __ign4, __ign5;     \
+       asm volatile (                                          \
+               TRAP_INSTR                                      \
+               : "=a" (__res), "=b" (__ign1), "=c" (__ign2),   \
+               "=d" (__ign3), "=S" (__ign4), "=D" (__ign5)     \
+               : "0" (__HYPERVISOR_##name), "1" ((long)(a1)),  \
+               "2" ((long)(a2)), "3" ((long)(a3)),             \
+               "4" ((long)(a4)), "5" ((long)(a5))              \
+               : "memory" );                                   \
+       (type)__res;                                            \
+})
 
 static inline int
 HYPERVISOR_set_trap_table(
-    trap_info_t *table)
-{
-    int ret;
-    unsigned long ignore;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ignore)
-       : "0" (__HYPERVISOR_set_trap_table), "1" (table)
-       : "memory" );
-
-    return ret;
+       trap_info_t *table)
+{
+       return _hypercall1(int, set_trap_table, table);
 }
 
 static inline int
 HYPERVISOR_mmu_update(
-    mmu_update_t *req, int count, int *success_count, domid_t domid)
-{
-    int ret;
-    unsigned long ign1, ign2, ign3, ign4;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
-       : "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
-        "3" (success_count), "4" (domid)
-       : "memory" );
-
-    return ret;
+       mmu_update_t *req, int count, int *success_count, domid_t domid)
+{
+       return _hypercall4(int, mmu_update, req, count, success_count, domid);
 }
 
 static inline int
 HYPERVISOR_mmuext_op(
-    struct mmuext_op *op, int count, int *success_count, domid_t domid)
-{
-    int ret;
-    unsigned long ign1, ign2, ign3, ign4;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
-       : "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count),
-        "3" (success_count), "4" (domid)
-       : "memory" );
-
-    return ret;
+       struct mmuext_op *op, int count, int *success_count, domid_t domid)
+{
+       return _hypercall4(int, mmuext_op, op, count, success_count, domid);
 }
 
 static inline int
 HYPERVISOR_set_gdt(
-    unsigned long *frame_list, int entries)
-{
-    int ret;
-    unsigned long ign1, ign2;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2)
-       : "0" (__HYPERVISOR_set_gdt), "1" (frame_list), "2" (entries)
-       : "memory" );
-
-
-    return ret;
+       unsigned long *frame_list, int entries)
+{
+       return _hypercall2(int, set_gdt, frame_list, entries);
 }
 
 static inline int
 HYPERVISOR_stack_switch(
-    unsigned long ss, unsigned long esp)
-{
-    int ret;
-    unsigned long ign1, ign2;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2)
-       : "0" (__HYPERVISOR_stack_switch), "1" (ss), "2" (esp)
-       : "memory" );
-
-    return ret;
+       unsigned long ss, unsigned long esp)
+{
+       return _hypercall2(int, stack_switch, ss, esp);
 }
 
 static inline int
 HYPERVISOR_set_callbacks(
-    unsigned long event_selector, unsigned long event_address,
-    unsigned long failsafe_selector, unsigned long failsafe_address)
-{
-    int ret;
-    unsigned long ign1, ign2, ign3, ign4;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
-       : "0" (__HYPERVISOR_set_callbacks), "1" (event_selector),
-         "2" (event_address), "3" (failsafe_selector), "4" (failsafe_address)
-       : "memory" );
-
-    return ret;
+       unsigned long event_selector, unsigned long event_address,
+       unsigned long failsafe_selector, unsigned long failsafe_address)
+{
+       return _hypercall4(int, set_callbacks,
+                          event_selector, event_address,
+                          failsafe_selector, failsafe_address);
 }
 
 static inline int
 HYPERVISOR_fpu_taskswitch(
-    int set)
-{
-    int ret;
-    unsigned long ign;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign)
-        : "0" (__HYPERVISOR_fpu_taskswitch), "1" (set)
-        : "memory" );
-
-    return ret;
+       int set)
+{
+       return _hypercall1(int, fpu_taskswitch, set);
 }
 
 static inline int
 HYPERVISOR_yield(
-    void)
-{
-    int ret;
-    unsigned long ign;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign)
-       : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield)
-       : "memory", "ecx" );
-
-    return ret;
+       void)
+{
+       return _hypercall2(int, sched_op, SCHEDOP_yield, 0);
 }
 
 static inline int
 HYPERVISOR_block(
-    void)
-{
-    int ret;
-    unsigned long ign1;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1)
-       : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block)
-       : "memory", "ecx" );
-
-    return ret;
+       void)
+{
+       return _hypercall2(int, sched_op, SCHEDOP_block, 0);
 }
 
 static inline int
 HYPERVISOR_shutdown(
-    void)
-{
-    int ret;
-    unsigned long ign1;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1)
-       : "0" (__HYPERVISOR_sched_op),
-         "1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
-        : "memory", "ecx" );
-
-    return ret;
+       void)
+{
+       return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+                          (SHUTDOWN_poweroff << SCHEDOP_reasonshift), 0);
 }
 
 static inline int
 HYPERVISOR_reboot(
-    void)
-{
-    int ret;
-    unsigned long ign1;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1)
-       : "0" (__HYPERVISOR_sched_op),
-         "1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
-        : "memory", "ecx" );
-
-    return ret;
-}
-
-static inline int
-HYPERVISOR_suspend(
-    unsigned long srec)
-{
-    int ret;
-    unsigned long ign1, ign2;
-
-    /* NB. On suspend, control software expects a suspend record in %esi. */
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=S" (ign2)
-       : "0" (__HYPERVISOR_sched_op),
-        "b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)), 
-        "S" (srec) : "memory", "ecx");
-
-    return ret;
+       void)
+{
+       return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+                          (SHUTDOWN_reboot << SCHEDOP_reasonshift), 0);
 }
 
 static inline int
 HYPERVISOR_crash(
-    void)
-{
-    int ret;
-    unsigned long ign1;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1)
-       : "0" (__HYPERVISOR_sched_op),
-         "1" (SCHEDOP_shutdown | (SHUTDOWN_crash << SCHEDOP_reasonshift))
-        : "memory", "ecx" );
-
-    return ret;
+       void)
+{
+       return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+                          (SHUTDOWN_crash << SCHEDOP_reasonshift), 0);
 }
 
 static inline long
 HYPERVISOR_set_timer_op(
-    u64 timeout)
-{
-    int ret;
-    unsigned long timeout_hi = (unsigned long)(timeout>>32);
-    unsigned long timeout_lo = (unsigned long)timeout;
-    unsigned long ign1, ign2;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2)
-       : "0" (__HYPERVISOR_set_timer_op), "b" (timeout_lo), "c" (timeout_hi)
-       : "memory");
-
-    return ret;
+       u64 timeout)
+{
+       unsigned long timeout_hi = (unsigned long)(timeout>>32);
+       unsigned long timeout_lo = (unsigned long)timeout;
+       return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
 }
 
 static inline int
 HYPERVISOR_dom0_op(
-    dom0_op_t *dom0_op)
-{
-    int ret;
-    unsigned long ign1;
-
-    dom0_op->interface_version = DOM0_INTERFACE_VERSION;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1)
-       : "0" (__HYPERVISOR_dom0_op), "1" (dom0_op)
-       : "memory");
-
-    return ret;
+       dom0_op_t *dom0_op)
+{
+       dom0_op->interface_version = DOM0_INTERFACE_VERSION;
+       return _hypercall1(int, dom0_op, dom0_op);
 }
 
 static inline int
 HYPERVISOR_set_debugreg(
-    int reg, unsigned long value)
-{
-    int ret;
-    unsigned long ign1, ign2;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2)
-       : "0" (__HYPERVISOR_set_debugreg), "1" (reg), "2" (value)
-       : "memory" );
-
-    return ret;
+       int reg, unsigned long value)
+{
+       return _hypercall2(int, set_debugreg, reg, value);
 }
 
 static inline unsigned long
 HYPERVISOR_get_debugreg(
-    int reg)
-{
-    unsigned long ret;
-    unsigned long ign;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign)
-       : "0" (__HYPERVISOR_get_debugreg), "1" (reg)
-       : "memory" );
-
-    return ret;
+       int reg)
+{
+       return _hypercall1(unsigned long, get_debugreg, reg);
 }
 
 static inline int
 HYPERVISOR_update_descriptor(
-    u64 ma, u64 desc)
-{
-    int ret;
-    unsigned long ign1, ign2, ign3, ign4;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
-       : "0" (__HYPERVISOR_update_descriptor),
-         "1" ((unsigned long)ma), "2" ((unsigned long)(ma>>32)),
-         "3" ((unsigned long)desc), "4" ((unsigned long)(desc>>32))
-       : "memory" );
-
-    return ret;
-}
-
-static inline int
-HYPERVISOR_dom_mem_op(
-    unsigned int op, unsigned long *extent_list,
-    unsigned long nr_extents, unsigned int extent_order)
-{
-    int ret;
-    unsigned long ign1, ign2, ign3, ign4, ign5;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
-         "=D" (ign5)
-       : "0" (__HYPERVISOR_dom_mem_op), "1" (op), "2" (extent_list),
-         "3" (nr_extents), "4" (extent_order), "5" (DOMID_SELF)
-        : "memory" );
-
-    return ret;
+       u64 ma, u64 desc)
+{
+       return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
+}
+
+static inline int
+HYPERVISOR_memory_op(
+       unsigned int cmd, void *arg)
+{
+       return _hypercall2(int, memory_op, cmd, arg);
 }
 
 static inline int
 HYPERVISOR_multicall(
-    void *call_list, int nr_calls)
-{
-    int ret;
-    unsigned long ign1, ign2;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2)
-       : "0" (__HYPERVISOR_multicall), "1" (call_list), "2" (nr_calls)
-       : "memory" );
-
-    return ret;
+       void *call_list, int nr_calls)
+{
+       return _hypercall2(int, multicall, call_list, nr_calls);
 }
 
 static inline int
 HYPERVISOR_update_va_mapping(
-    unsigned long va, pte_t new_val, unsigned long flags)
-{
-    int ret;
-    unsigned long ign1, ign2, ign3, ign4;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
-       : "0" (__HYPERVISOR_update_va_mapping), 
-          "1" (va), "2" ((new_val).pte_low),
+       unsigned long va, pte_t new_val, unsigned long flags)
+{
+       unsigned long pte_hi = 0;
 #ifdef CONFIG_X86_PAE
-         "3" ((new_val).pte_high),
-#else
-         "3" (0),
+       pte_hi = new_val.pte_high;
 #endif
-         "4" (flags)
-       : "memory" );
-
-    return ret;
+       return _hypercall4(int, update_va_mapping, va,
+                          new_val.pte_low, pte_hi, flags);
 }
 
 static inline int
 HYPERVISOR_event_channel_op(
-    void *op)
-{
-    int ret;
-    unsigned long ignore;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ignore)
-       : "0" (__HYPERVISOR_event_channel_op), "1" (op)
-       : "memory" );
-
-    return ret;
+       void *op)
+{
+       return _hypercall1(int, event_channel_op, op);
 }
 
 static inline int
 HYPERVISOR_xen_version(
-    int cmd)
-{
-    int ret;
-    unsigned long ignore;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ignore)
-       : "0" (__HYPERVISOR_xen_version), "1" (cmd)
-       : "memory" );
-
-    return ret;
+       int cmd)
+{
+       return _hypercall1(int, xen_version, cmd);
 }
 
 static inline int
 HYPERVISOR_console_io(
-    int cmd, int count, char *str)
-{
-    int ret;
-    unsigned long ign1, ign2, ign3;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
-       : "0" (__HYPERVISOR_console_io), "1" (cmd), "2" (count), "3" (str)
-       : "memory" );
-
-    return ret;
+       int cmd, int count, char *str)
+{
+       return _hypercall3(int, console_io, cmd, count, str);
 }
 
 static inline int
 HYPERVISOR_physdev_op(
-    void *physdev_op)
-{
-    int ret;
-    unsigned long ign;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign)
-       : "0" (__HYPERVISOR_physdev_op), "1" (physdev_op)
-       : "memory" );
-
-    return ret;
+       void *physdev_op)
+{
+       return _hypercall1(int, physdev_op, physdev_op);
 }
 
 static inline int
 HYPERVISOR_grant_table_op(
-    unsigned int cmd, void *uop, unsigned int count)
-{
-    int ret;
-    unsigned long ign1, ign2, ign3;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
-       : "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (uop), "3" (count)
-       : "memory" );
-
-    return ret;
+       unsigned int cmd, void *uop, unsigned int count)
+{
+       return _hypercall3(int, grant_table_op, cmd, uop, count);
 }
 
 static inline int
 HYPERVISOR_update_va_mapping_otherdomain(
-    unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
-{
-    int ret;
-    unsigned long ign1, ign2, ign3, ign4, ign5;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3),
-         "=S" (ign4), "=D" (ign5)
-       : "0" (__HYPERVISOR_update_va_mapping_otherdomain),
-          "1" (va), "2" ((new_val).pte_low),
+       unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+{
+       unsigned long pte_hi = 0;
 #ifdef CONFIG_X86_PAE
-         "3" ((new_val).pte_high),
-#else
-         "3" (0),
+       pte_hi = new_val.pte_high;
 #endif
-         "4" (flags), "5" (domid) :
-        "memory" );
-    
-    return ret;
+       return _hypercall5(int, update_va_mapping_otherdomain, va,
+                          new_val.pte_low, pte_hi, flags, domid);
 }
 
 static inline int
 HYPERVISOR_vm_assist(
-    unsigned int cmd, unsigned int type)
-{
-    int ret;
-    unsigned long ign1, ign2;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2)
-       : "0" (__HYPERVISOR_vm_assist), "1" (cmd), "2" (type)
-       : "memory" );
-
-    return ret;
+       unsigned int cmd, unsigned int type)
+{
+       return _hypercall2(int, vm_assist, cmd, type);
 }
 
 static inline int
 HYPERVISOR_boot_vcpu(
-    unsigned long vcpu, vcpu_guest_context_t *ctxt)
-{
-    int ret;
-    unsigned long ign1, ign2;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2)
-       : "0" (__HYPERVISOR_boot_vcpu), "1" (vcpu), "2" (ctxt)
-       : "memory");
-
-    return ret;
+       unsigned long vcpu, vcpu_guest_context_t *ctxt)
+{
+       return _hypercall2(int, boot_vcpu, vcpu, ctxt);
+}
+
+static inline int
+HYPERVISOR_vcpu_up(
+       int vcpu)
+{
+       return _hypercall2(int, sched_op, SCHEDOP_vcpu_up |
+                          (vcpu << SCHEDOP_vcpushift), 0);
+}
+
+static inline int
+HYPERVISOR_vcpu_pickle(
+       int vcpu, vcpu_guest_context_t *ctxt)
+{
+       return _hypercall2(int, sched_op, SCHEDOP_vcpu_pickle |
+                          (vcpu << SCHEDOP_vcpushift), ctxt);
+}
+
+static inline int
+HYPERVISOR_suspend(
+       unsigned long srec)
+{
+       int ret;
+       unsigned long ign1, ign2;
+
+       /* On suspend, control software expects a suspend record in %esi. */
+       __asm__ __volatile__ (
+               TRAP_INSTR
+               : "=a" (ret), "=b" (ign1), "=S" (ign2)
+               : "0" (__HYPERVISOR_sched_op),
+               "1" (SCHEDOP_shutdown | (SHUTDOWN_suspend <<
+                                        SCHEDOP_reasonshift)), 
+               "2" (srec) : "memory", "ecx");
+
+       return ret;
 }
 
 static inline int
 HYPERVISOR_vcpu_down(
-    int vcpu)
-{
-    int ret;
-    unsigned long ign1;
-    /* Yes, I really do want to clobber edx here: when we resume a
-       vcpu after unpickling a multi-processor domain, it returns
-       here, but clobbers all of the call clobbered registers. */
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1)
-       : "0" (__HYPERVISOR_sched_op),
-         "1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift))
-        : "memory", "ecx", "edx" );
-
-    return ret;
-}
-
-static inline int
-HYPERVISOR_vcpu_up(
-    int vcpu)
-{
-    int ret;
-    unsigned long ign1;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1)
-       : "0" (__HYPERVISOR_sched_op),
-         "1" (SCHEDOP_vcpu_up | (vcpu << SCHEDOP_vcpushift))
-        : "memory", "ecx" );
-
-    return ret;
-}
-
-static inline int
-HYPERVISOR_vcpu_pickle(
-    int vcpu, vcpu_guest_context_t *ctxt)
-{
-    int ret;
-    unsigned long ign1, ign2;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret), "=b" (ign1), "=c" (ign2)
-       : "0" (__HYPERVISOR_sched_op),
-         "1" (SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)),
-         "2" (ctxt)
-        : "memory" );
-
-    return ret;
+       int vcpu)
+{
+       int ret;
+       unsigned long ign1;
+       /* Yes, I really do want to clobber edx here: when we resume a
+          vcpu after unpickling a multi-processor domain, it returns
+          here, but clobbers all of the call clobbered registers. */
+       __asm__ __volatile__ (
+               TRAP_INSTR
+               : "=a" (ret), "=b" (ign1)
+               : "0" (__HYPERVISOR_sched_op),
+               "1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift))
+               : "memory", "ecx", "edx" );
+       return ret;
 }
 
 #endif /* __HYPERCALL_H__ */
+
+/*
+ * Local variables:
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h  
Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h  
Fri Sep  9 16:30:54 2005
@@ -8,7 +8,7 @@
 
 static char * __init machine_specific_memory_setup(void)
 {
-       unsigned long max_pfn = xen_start_info.nr_pages;
+       unsigned long max_pfn = xen_start_info->nr_pages;
 
        e820.nr_map = 0;
        add_memory_region(0, PFN_PHYS(max_pfn), E820_RAM);
@@ -23,7 +23,7 @@
        clear_bit(X86_FEATURE_PSE, c->x86_capability);
        clear_bit(X86_FEATURE_PGE, c->x86_capability);
        clear_bit(X86_FEATURE_SEP, c->x86_capability);
-       if (!(xen_start_info.flags & SIF_PRIVILEGED))
+       if (!(xen_start_info->flags & SIF_PRIVILEGED))
                clear_bit(X86_FEATURE_MTRR, c->x86_capability);
 }
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/mmu_context.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mmu_context.h       Thu Sep 
 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mmu_context.h       Fri Sep 
 9 16:30:54 2005
@@ -35,9 +35,9 @@
         * happen before reload of cr3/ldt (i.e., not in __switch_to).
         */
        asm volatile ( "mov %%fs,%0 ; mov %%gs,%1"
-               : "=m" (*(int *)&current->thread.fs),
-                 "=m" (*(int *)&current->thread.gs));
-       asm volatile ( "mov %0,%%fs ; mov %0,%%gs"
+               : "=m" (current->thread.fs),
+                 "=m" (current->thread.gs));
+       asm volatile ( "movl %0,%%fs ; movl %0,%%gs"
                : : "r" (0) );
 }
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h      Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h      Fri Sep  9 
16:30:54 2005
@@ -60,14 +60,14 @@
 #define copy_user_page(to, from, vaddr, pg)    copy_page(to, from)
 
 /**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
-#define INVALID_P2M_ENTRY      (~0U)
-#define FOREIGN_FRAME(m)       ((m) | 0x80000000U)
-extern unsigned int *phys_to_machine_mapping;
+#define INVALID_P2M_ENTRY      (~0UL)
+#define FOREIGN_FRAME(m)       ((m) | (1UL<<31))
+extern unsigned long *phys_to_machine_mapping;
 #define pfn_to_mfn(pfn)        \
-((unsigned long)phys_to_machine_mapping[(unsigned int)(pfn)] & 0x7FFFFFFFUL)
+(phys_to_machine_mapping[(unsigned int)(pfn)] & ~(1UL<<31))
 static inline unsigned long mfn_to_pfn(unsigned long mfn)
 {
-       unsigned int pfn;
+       unsigned long pfn;
 
        /*
         * The array access can fail (e.g., device space beyond end of RAM).
@@ -83,7 +83,7 @@
                ".previous"
                : "=r" (pfn) : "m" (machine_to_phys_mapping[mfn]) );
 
-       return (unsigned long)pfn;
+       return pfn;
 }
 
 /* Definitions for machine and pseudophysical addresses. */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/pci.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pci.h       Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pci.h       Fri Sep  9 
16:30:54 2005
@@ -43,8 +43,32 @@
 
 struct pci_dev;
 
+#ifdef CONFIG_SWIOTLB
+
+
 /* On Xen we use SWIOTLB instead of blk-specific bounce buffers. */
 #define PCI_DMA_BUS_IS_PHYS    (0)
+
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)      \
+       dma_addr_t ADDR_NAME;
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)                \
+       __u32 LEN_NAME;
+#define pci_unmap_addr(PTR, ADDR_NAME)                 \
+       ((PTR)->ADDR_NAME)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)                \
+       (((PTR)->ADDR_NAME) = (VAL))
+#define pci_unmap_len(PTR, LEN_NAME)                   \
+       ((PTR)->LEN_NAME)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)          \
+       (((PTR)->LEN_NAME) = (VAL))
+
+#else
+
+/* The PCI address space does equal the physical memory
+ * address space.  The networking and block device layers use
+ * this boolean for bounce buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS    (1)
 
 /* pci_unmap_{page,single} is a nop so... */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
@@ -53,6 +77,8 @@
 #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)        do { } while (0)
 #define pci_unmap_len(PTR, LEN_NAME)           (0)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)  do { } while (0)
+
+#endif
 
 /* This is always fine. */
 #define pci_dac_dma_supported(pci_dev, mask)   (1)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h   Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h   Fri Sep  9 
16:30:54 2005
@@ -460,9 +460,9 @@
 #define kern_addr_valid(addr)  (1)
 #endif /* !CONFIG_DISCONTIGMEM */
 
-int direct_remap_area_pages(struct mm_struct *mm,
+int direct_remap_pfn_range(struct mm_struct *mm,
                             unsigned long address, 
-                            unsigned long machine_addr,
+                            unsigned long mfn,
                             unsigned long size, 
                             pgprot_t prot,
                             domid_t  domid);
@@ -474,10 +474,10 @@
                     unsigned long size);
 
 #define io_remap_page_range(vma,from,phys,size,prot) \
-direct_remap_area_pages(vma->vm_mm,from,phys,size,prot,DOMID_IO)
+direct_remap_pfn_range(vma->vm_mm,from,phys>>PAGE_SHIFT,size,prot,DOMID_IO)
 
 #define io_remap_pfn_range(vma,from,pfn,size,prot) \
-direct_remap_area_pages(vma->vm_mm,from,pfn<<PAGE_SHIFT,size,prot,DOMID_IO)
+direct_remap_pfn_range(vma->vm_mm,from,pfn,size,prot,DOMID_IO)
 
 #define MK_IOSPACE_PFN(space, pfn)     (pfn)
 #define GET_IOSPACE(pfn)               0
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/processor.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/processor.h Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/processor.h Fri Sep  9 
16:30:54 2005
@@ -517,8 +517,8 @@
  * This special macro can be used to load a debugging register
  */
 #define loaddebug(thread,register) \
-       HYPERVISOR_set_debugreg((register),     \
-                       ((thread)->debugreg[register]))
+               HYPERVISOR_set_debugreg((register), \
+                                       ((thread)->debugreg[register]))
 
 /* Forward declaration, a strange C thing */
 struct task_struct;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/setup.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/setup.h     Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/setup.h     Fri Sep  9 
16:30:54 2005
@@ -53,8 +53,8 @@
 #define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
 #define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
 #define KERNEL_START (*(unsigned long *) (PARAM+0x214))
-#define INITRD_START (__pa(xen_start_info.mod_start))
-#define INITRD_SIZE (xen_start_info.mod_len)
+#define INITRD_START (__pa(xen_start_info->mod_start))
+#define INITRD_SIZE (xen_start_info->mod_len)
 #define EDID_INFO   (*(struct edid_info *) (PARAM+0x440))
 #define EDD_NR     (*(unsigned char *) (PARAM+EDDNR))
 #define EDD_MBR_SIG_NR (*(unsigned char *) (PARAM+EDD_MBR_SIG_NR_BUF))
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h    Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h    Fri Sep  9 
16:30:54 2005
@@ -561,8 +561,14 @@
 #define local_irq_disable()    __cli()
 #define local_irq_enable()     __sti()
 
+/* Don't use smp_processor_id: this is called in debug versions of that fn. */
+#ifdef CONFIG_SMP
 #define irqs_disabled()                        \
-    HYPERVISOR_shared_info->vcpu_data[smp_processor_id()].evtchn_upcall_mask
+    HYPERVISOR_shared_info->vcpu_data[__smp_processor_id()].evtchn_upcall_mask
+#else
+#define irqs_disabled()                        \
+    HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask
+#endif
 
 /*
  * disable hlt during certain critical i/o operations
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/bootsetup.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/bootsetup.h       Thu Sep 
 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/bootsetup.h       Fri Sep 
 9 16:30:54 2005
@@ -25,8 +25,8 @@
 #define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
 #define KERNEL_START (*(unsigned int *) (PARAM+0x214))
 
-#define INITRD_START (__pa(xen_start_info.mod_start))
-#define INITRD_SIZE (xen_start_info.mod_len)
+#define INITRD_START (__pa(xen_start_info->mod_start))
+#define INITRD_SIZE (xen_start_info->mod_len)
 #define EDID_INFO   (*(struct edid_info *) (PARAM+0x440))
 
 #define EDD_NR     (*(unsigned char *) (PARAM+EDDNR))
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h       Thu Sep 
 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h       Fri Sep 
 9 16:30:54 2005
@@ -4,6 +4,10 @@
  * Linux-specific hypervisor handling.
  * 
  * Copyright (c) 2002-2004, K A Fraser
+ * 
+ * 64-bit updates:
+ *   Benjamin Liu <benjamin.liu@xxxxxxxxx>
+ *   Jun Nakajima <jun.nakajima@xxxxxxxxx>
  * 
  * This file may be distributed separately from the Linux kernel, or
  * incorporated into other software packages, subject to the following license:
@@ -26,497 +30,329 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  * IN THE SOFTWARE.
  */
-/*
- * Benjamin Liu <benjamin.liu@xxxxxxxxx>
- * Jun Nakajima <jun.nakajima@xxxxxxxxx>
- *   Ported to x86-64.
- * 
- */
 
 #ifndef __HYPERCALL_H__
 #define __HYPERCALL_H__
+
 #include <asm-xen/xen-public/xen.h>
 
 #define __syscall_clobber "r11","rcx","memory"
 
-/*
- * Assembler stubs for hyper-calls.
- */
+#define _hypercall0(type, name)                        \
+({                                             \
+       long __res;                             \
+       asm volatile (                          \
+               TRAP_INSTR                      \
+               : "=a" (__res)                  \
+               : "0" (__HYPERVISOR_##name)     \
+               : __syscall_clobber );          \
+       (type)__res;                            \
+})
+
+#define _hypercall1(type, name, a1)                            \
+({                                                             \
+       long __res, __ign1;                                     \
+       asm volatile (                                          \
+               TRAP_INSTR                                      \
+               : "=a" (__res), "=D" (__ign1)                   \
+               : "0" (__HYPERVISOR_##name), "1" ((long)(a1))   \
+               : __syscall_clobber );                          \
+       (type)__res;                                            \
+})
+
+#define _hypercall2(type, name, a1, a2)                                \
+({                                                             \
+       long __res, __ign1, __ign2;                             \
+       asm volatile (                                          \
+               TRAP_INSTR                                      \
+               : "=a" (__res), "=D" (__ign1), "=S" (__ign2)    \
+               : "0" (__HYPERVISOR_##name), "1" ((long)(a1)),  \
+               "2" ((long)(a2))                                \
+               : __syscall_clobber );                          \
+       (type)__res;                                            \
+})
+
+#define _hypercall3(type, name, a1, a2, a3)                    \
+({                                                             \
+       long __res, __ign1, __ign2, __ign3;                     \
+       asm volatile (                                          \
+               TRAP_INSTR                                      \
+               : "=a" (__res), "=D" (__ign1), "=S" (__ign2),   \
+               "=d" (__ign3)                                   \
+               : "0" (__HYPERVISOR_##name), "1" ((long)(a1)),  \
+               "2" ((long)(a2)), "3" ((long)(a3))              \
+               : __syscall_clobber );                          \
+       (type)__res;                                            \
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4)                        \
+({                                                             \
+       long __res, __ign1, __ign2, __ign3;                     \
+       asm volatile (                                          \
+               "movq %8,%%r10; " TRAP_INSTR                    \
+               : "=a" (__res), "=D" (__ign1), "=S" (__ign2),   \
+               "=d" (__ign3)                                   \
+               : "0" (__HYPERVISOR_##name), "1" ((long)(a1)),  \
+               "2" ((long)(a2)), "3" ((long)(a3)),             \
+               "g" ((long)(a4))                                \
+               : __syscall_clobber, "r10" );                   \
+       (type)__res;                                            \
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5)            \
+({                                                             \
+       long __res, __ign1, __ign2, __ign3;                     \
+       asm volatile (                                          \
+               "movq %8,%%r10; movq %9,%%r8; " TRAP_INSTR      \
+               : "=a" (__res), "=D" (__ign1), "=S" (__ign2),   \
+               "=d" (__ign3)                                   \
+               : "0" (__HYPERVISOR_##name), "1" ((long)(a1)),  \
+               "2" ((long)(a2)), "3" ((long)(a3)),             \
+               "g" ((long)(a4)), "g" ((long)(a5))              \
+               : __syscall_clobber, "r10", "r8" );             \
+       (type)__res;                                            \
+})
+
 static inline int
 HYPERVISOR_set_trap_table(
-    trap_info_t *table)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_set_trap_table), "D" (table)
-       : __syscall_clobber );
-
-    return ret;
+       trap_info_t *table)
+{
+       return _hypercall1(int, set_trap_table, table);
 }
 
 static inline int
 HYPERVISOR_mmu_update(
-    mmu_update_t *req, int count, int *success_count, domid_t domid)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        "movq %5, %%r10;" TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_mmu_update), "D" (req), "S" 
((long)count),
-         "d" (success_count), "g" ((unsigned long)domid)
-       : __syscall_clobber, "r10" );
-
-    return ret;
+       mmu_update_t *req, int count, int *success_count, domid_t domid)
+{
+       return _hypercall4(int, mmu_update, req, count, success_count, domid);
 }
 
 static inline int
 HYPERVISOR_mmuext_op(
-    struct mmuext_op *op, int count, int *success_count, domid_t domid)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        "movq %5, %%r10;" TRAP_INSTR
-        : "=a" (ret)
-        : "0" (__HYPERVISOR_mmuext_op), "D" (op), "S" ((long)count), 
-          "d" (success_count), "g" ((unsigned long)domid)
-        : __syscall_clobber, "r10" );
-
-    return ret;
+       struct mmuext_op *op, int count, int *success_count, domid_t domid)
+{
+       return _hypercall4(int, mmuext_op, op, count, success_count, domid);
 }
 
 static inline int
 HYPERVISOR_set_gdt(
-    unsigned long *frame_list, int entries)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_set_gdt), "D" (frame_list), "S" 
((long)entries)
-       : __syscall_clobber );
-
-
-    return ret;
-}
+       unsigned long *frame_list, int entries)
+{
+       return _hypercall2(int, set_gdt, frame_list, entries);
+}
+
 static inline int
 HYPERVISOR_stack_switch(
-    unsigned long ss, unsigned long esp)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_stack_switch), "D" (ss), "S" (esp)
-       : __syscall_clobber );
-
-    return ret;
+       unsigned long ss, unsigned long esp)
+{
+       return _hypercall2(int, stack_switch, ss, esp);
 }
 
 static inline int
 HYPERVISOR_set_callbacks(
-    unsigned long event_address, unsigned long failsafe_address, 
-    unsigned long syscall_address)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_set_callbacks), "D" (event_address),
-         "S" (failsafe_address), "d" (syscall_address)
-       : __syscall_clobber );
-
-    return ret;
+       unsigned long event_address, unsigned long failsafe_address, 
+       unsigned long syscall_address)
+{
+       return _hypercall3(int, set_callbacks,
+                          event_address, failsafe_address, syscall_address);
 }
 
 static inline int
 HYPERVISOR_fpu_taskswitch(
-    int set)
-{
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret) : "0" ((unsigned long)__HYPERVISOR_fpu_taskswitch),
-          "D" ((unsigned long) set) : __syscall_clobber );
-
-    return ret;
+       int set)
+{
+       return _hypercall1(int, fpu_taskswitch, set);
 }
 
 static inline int
 HYPERVISOR_yield(
-    void)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned 
long)SCHEDOP_yield)
-       : __syscall_clobber );
-
-    return ret;
+       void)
+{
+       return _hypercall2(int, sched_op, SCHEDOP_yield, 0);
 }
 
 static inline int
 HYPERVISOR_block(
-    void)
-{
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned 
long)SCHEDOP_block)
-       : __syscall_clobber );
-
-    return ret;
+       void)
+{
+       return _hypercall2(int, sched_op, SCHEDOP_block, 0);
 }
 
 static inline int
 HYPERVISOR_shutdown(
-    void)
-{
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_sched_op),
-         "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_poweroff << 
SCHEDOP_reasonshift)))
-       : __syscall_clobber );
-
-    return ret;
+       void)
+{
+       return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+                          (SHUTDOWN_poweroff << SCHEDOP_reasonshift), 0);
 }
 
 static inline int
 HYPERVISOR_reboot(
-    void)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_sched_op),
-         "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_reboot << 
SCHEDOP_reasonshift)))
-       : __syscall_clobber );
-
-    return ret;
-}
-
-static inline int
-HYPERVISOR_suspend(
-    unsigned long srec)
-{
-    int ret;
-
-    /* NB. On suspend, control software expects a suspend record in %esi. */
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_sched_op),
-        "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_suspend << 
SCHEDOP_reasonshift))), 
-        "S" (srec)
-       : __syscall_clobber );
-
-    return ret;
-}
-
-/*
- * We can have the timeout value in a single argument for the hypercall, but
- * that will break the common code. 
- */
+       void)
+{
+       return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+                          (SHUTDOWN_reboot << SCHEDOP_reasonshift), 0);
+}
+
 static inline long
 HYPERVISOR_set_timer_op(
-    u64 timeout)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_set_timer_op),
-         "D" (timeout)
-       : __syscall_clobber );
-
-    return ret;
+       u64 timeout)
+{
+       return _hypercall1(long, set_timer_op, timeout);
 }
 
 static inline int
 HYPERVISOR_dom0_op(
-    dom0_op_t *dom0_op)
-{
-    int ret;
-
-    dom0_op->interface_version = DOM0_INTERFACE_VERSION;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_dom0_op), "D" (dom0_op)
-       : __syscall_clobber );
-
-    return ret;
+       dom0_op_t *dom0_op)
+{
+       dom0_op->interface_version = DOM0_INTERFACE_VERSION;
+       return _hypercall1(int, dom0_op, dom0_op);
 }
 
 static inline int
 HYPERVISOR_set_debugreg(
-    int reg, unsigned long value)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_set_debugreg), "D" ((unsigned 
long)reg), "S" (value)
-       : __syscall_clobber );
-
-    return ret;
+       int reg, unsigned long value)
+{
+       return _hypercall2(int, set_debugreg, reg, value);
 }
 
 static inline unsigned long
 HYPERVISOR_get_debugreg(
-    int reg)
-{
-    unsigned long ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_get_debugreg), "D" ((unsigned 
long)reg)
-       : __syscall_clobber );
-
-    return ret;
+       int reg)
+{
+       return _hypercall1(unsigned long, get_debugreg, reg);
 }
 
 static inline int
 HYPERVISOR_update_descriptor(
-    unsigned long ma, unsigned long word)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_update_descriptor), "D" (ma),
-         "S" (word)
-       : __syscall_clobber );
-
-    return ret;
-}
-
-static inline int
-HYPERVISOR_dom_mem_op(
-    unsigned int op, unsigned long *extent_list,
-    unsigned long nr_extents, unsigned int extent_order)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        "movq %5,%%r10; movq %6,%%r8;" TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_dom_mem_op), "D" ((unsigned 
long)op), "S" (extent_list),
-         "d" (nr_extents), "g" ((unsigned long) extent_order), "g" ((unsigned 
long) DOMID_SELF)
-       : __syscall_clobber,"r8","r10");
-
-    return ret;
+       unsigned long ma, unsigned long word)
+{
+       return _hypercall2(int, update_descriptor, ma, word);
+}
+
+static inline int
+HYPERVISOR_memory_op(
+       unsigned int cmd, void *arg)
+{
+       return _hypercall2(int, memory_op, cmd, arg);
 }
 
 static inline int
 HYPERVISOR_multicall(
-    void *call_list, int nr_calls)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_multicall), "D" (call_list), "S" 
((unsigned long)nr_calls)
-       : __syscall_clobber);
-
-    return ret;
+       void *call_list, int nr_calls)
+{
+       return _hypercall2(int, multicall, call_list, nr_calls);
 }
 
 static inline int
 HYPERVISOR_update_va_mapping(
-    unsigned long page_nr, pte_t new_val, unsigned long flags)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_update_va_mapping), 
-          "D" (page_nr), "S" (new_val.pte), "d" (flags)
-       : __syscall_clobber);
-
-    return ret;
+       unsigned long va, pte_t new_val, unsigned long flags)
+{
+       return _hypercall3(int, update_va_mapping, va, new_val.pte, flags);
 }
 
 static inline int
 HYPERVISOR_event_channel_op(
-    void *op)
-{
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_event_channel_op), "D" (op)
-       : __syscall_clobber);
-
-    return ret;
+       void *op)
+{
+       return _hypercall1(int, event_channel_op, op);
 }
 
 static inline int
 HYPERVISOR_xen_version(
-    int cmd)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_xen_version), "D" ((unsigned 
long)cmd)
-       : __syscall_clobber);
-
-    return ret;
+       int cmd)
+{
+       return _hypercall1(int, xen_version, cmd);
 }
 
 static inline int
 HYPERVISOR_console_io(
-    int cmd, int count, char *str)
-{
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_console_io), "D" ((unsigned 
long)cmd), "S" ((unsigned long)count), "d" (str)
-       : __syscall_clobber);
-
-    return ret;
+       int cmd, int count, char *str)
+{
+       return _hypercall3(int, console_io, cmd, count, str);
 }
 
 static inline int
 HYPERVISOR_physdev_op(
-    void *physdev_op)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_physdev_op), "D" (physdev_op)
-       : __syscall_clobber);
-
-    return ret;
+       void *physdev_op)
+{
+       return _hypercall1(int, physdev_op, physdev_op);
 }
 
 static inline int
 HYPERVISOR_grant_table_op(
-    unsigned int cmd, void *uop, unsigned int count)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_grant_table_op), "D" ((unsigned 
long)cmd), "S" ((unsigned long)uop), "d" (count)
-       : __syscall_clobber);
-
-    return ret;
+       unsigned int cmd, void *uop, unsigned int count)
+{
+       return _hypercall3(int, grant_table_op, cmd, uop, count);
 }
 
 static inline int
 HYPERVISOR_update_va_mapping_otherdomain(
-    unsigned long page_nr, pte_t new_val, unsigned long flags, domid_t domid)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        "movq %5, %%r10;" TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_update_va_mapping_otherdomain),
-          "D" (page_nr), "S" (new_val.pte), "d" (flags), "g" ((unsigned 
long)domid)
-       : __syscall_clobber,"r10");
-    
-    return ret;
+       unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+{
+       return _hypercall4(int, update_va_mapping_otherdomain, va,
+                          new_val.pte, flags, domid);
 }
 
 static inline int
 HYPERVISOR_vm_assist(
-    unsigned int cmd, unsigned int type)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_vm_assist), "D" ((unsigned 
long)cmd), "S" ((unsigned long)type)
-       : __syscall_clobber);
-
-    return ret;
+       unsigned int cmd, unsigned int type)
+{
+       return _hypercall2(int, vm_assist, cmd, type);
+}
+
+static inline int
+HYPERVISOR_boot_vcpu(
+       unsigned long vcpu, vcpu_guest_context_t *ctxt)
+{
+       return _hypercall2(int, boot_vcpu, vcpu, ctxt);
+}
+
+static inline int
+HYPERVISOR_vcpu_up(
+       int vcpu)
+{
+       return _hypercall2(int, sched_op, SCHEDOP_vcpu_up |
+                          (vcpu << SCHEDOP_vcpushift), 0);
+}
+
+static inline int
+HYPERVISOR_vcpu_pickle(
+       int vcpu, vcpu_guest_context_t *ctxt)
+{
+       return _hypercall2(int, sched_op, SCHEDOP_vcpu_pickle |
+                          (vcpu << SCHEDOP_vcpushift), ctxt);
 }
 
 static inline int
 HYPERVISOR_switch_to_user(void)
 {
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret) : "0" ((unsigned long)__HYPERVISOR_switch_to_user) : 
__syscall_clobber );
-
-    return ret;
-}
-
-static inline int
-HYPERVISOR_boot_vcpu(
-    unsigned long vcpu, vcpu_guest_context_t *ctxt)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" (__HYPERVISOR_boot_vcpu), "D" (vcpu), "S" (ctxt)
-       : __syscall_clobber);
-
-    return ret;
+       return _hypercall0(int, switch_to_user);
 }
 
 static inline int
 HYPERVISOR_set_segment_base(
-    int reg, unsigned long value)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_set_segment_base), "D" ((unsigned 
long)reg), "S" (value)
-       : __syscall_clobber );
-
-    return ret;
-}
-
-static inline int
-HYPERVISOR_vcpu_pickle(
-    int vcpu, vcpu_guest_context_t *ctxt)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret)
-       : "0" ((unsigned long)__HYPERVISOR_sched_op),
-       "D" ((unsigned long)SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)),
-       "S" ((unsigned long)ctxt)
-       : __syscall_clobber );
-
-    return ret;
+       int reg, unsigned long value)
+{
+       return _hypercall2(int, set_segment_base, reg, value);
+}
+
+static inline int
+HYPERVISOR_suspend(
+       unsigned long srec)
+{
+       return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+                          (SHUTDOWN_suspend << SCHEDOP_reasonshift), srec);
 }
 
 #endif /* __HYPERCALL_H__ */
+
+/*
+ * Local variables:
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h
--- 
a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h    
    Thu Sep  8 15:18:40 2005
+++ 
b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h    
    Fri Sep  9 16:30:54 2005
@@ -14,7 +14,7 @@
        who = "Xen";
 
        start_pfn = 0;
-       max_pfn = xen_start_info.nr_pages;
+       max_pfn = xen_start_info->nr_pages;
 
        e820.nr_map = 0;
        add_memory_region(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn) - 
PFN_PHYS(start_pfn), E820_RAM);
@@ -29,7 +29,7 @@
        clear_bit(X86_FEATURE_PSE, c->x86_capability);
        clear_bit(X86_FEATURE_PGE, c->x86_capability);
        clear_bit(X86_FEATURE_SEP, c->x86_capability);
-       if (!(xen_start_info.flags & SIF_PRIVILEGED))
+       if (!(xen_start_info->flags & SIF_PRIVILEGED))
                clear_bit(X86_FEATURE_MTRR, c->x86_capability);
 }
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h    Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h    Fri Sep  9 
16:30:54 2005
@@ -62,14 +62,14 @@
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 /**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
-#define INVALID_P2M_ENTRY      (~0U)
-#define FOREIGN_FRAME(m)       ((m) | 0x80000000U)
-extern u32 *phys_to_machine_mapping;
+#define INVALID_P2M_ENTRY      (~0UL)
+#define FOREIGN_FRAME(m)       ((m) | (1UL<<63))
+extern unsigned long *phys_to_machine_mapping;
 #define pfn_to_mfn(pfn)        \
-((unsigned long)phys_to_machine_mapping[(unsigned int)(pfn)] & 0x7FFFFFFFUL)
+(phys_to_machine_mapping[(unsigned int)(pfn)] & ~(1UL << 63))
 static inline unsigned long mfn_to_pfn(unsigned long mfn)
 {
-       unsigned int pfn;
+       unsigned long pfn;
 
        /*
         * The array access can fail (e.g., device space beyond end of RAM).
@@ -77,7 +77,7 @@
         * but we must handle the fault without crashing!
         */
        asm (
-               "1:     movl %1,%k0\n"
+               "1:     movq %1,%0\n"
                "2:\n"
                ".section __ex_table,\"a\"\n"
                "       .align 8\n"
@@ -85,7 +85,7 @@
                ".previous"
                : "=r" (pfn) : "m" (machine_to_phys_mapping[mfn]) );
 
-       return (unsigned long)pfn;
+       return pfn;
 }
 
 /* Definitions for machine and pseudophysical addresses. */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pci.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pci.h     Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pci.h     Fri Sep  9 
16:30:54 2005
@@ -76,12 +76,29 @@
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)          \
        (((PTR)->LEN_NAME) = (VAL))
 
+#elif defined(CONFIG_SWIOTLB)
+
+#define PCI_DMA_BUS_IS_PHYS    0
+
+#define pci_dac_dma_supported(pci_dev, mask)    1
+
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)      \
+       dma_addr_t ADDR_NAME;
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)                \
+       __u32 LEN_NAME;
+#define pci_unmap_addr(PTR, ADDR_NAME)                 \
+       ((PTR)->ADDR_NAME)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)                \
+       (((PTR)->ADDR_NAME) = (VAL))
+#define pci_unmap_len(PTR, LEN_NAME)                   \
+       ((PTR)->LEN_NAME)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)          \
+       (((PTR)->LEN_NAME) = (VAL))
+
 #else
 /* No IOMMU */
 
-/* On Xen we use SWIOTLB instead of blk-specific bounce buffers. */
-#define PCI_DMA_BUS_IS_PHYS    (0)
-
+#define PCI_DMA_BUS_IS_PHYS    1
 #define pci_dac_dma_supported(pci_dev, mask)    1
 
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h Fri Sep  9 
16:30:54 2005
@@ -307,7 +307,7 @@
 #define pte_pfn(_pte)                                                  \
 ({                                                                     \
        unsigned long mfn = pte_mfn(_pte);                              \
-       unsigned pfn = mfn_to_pfn(mfn);                                 \
+       unsigned long pfn = mfn_to_pfn(mfn);                            \
        if ((pfn >= max_mapnr) || (phys_to_machine_mapping[pfn] != mfn))\
                pfn = max_mapnr; /* special: force !pfn_valid() */      \
        pfn;                                                            \
@@ -526,28 +526,26 @@
 
 #define DOMID_LOCAL (0xFFFFU)
 
-int direct_remap_area_pages(struct mm_struct *mm,
+int direct_remap_pfn_range(struct mm_struct *mm,
                             unsigned long address,
-                            unsigned long machine_addr,
+                            unsigned long mfn,
                             unsigned long size,
                             pgprot_t prot,
                             domid_t  domid);
-int __direct_remap_area_pages(struct mm_struct *mm,
-                              unsigned long address,
-                              unsigned long size,
-                              mmu_update_t *v);
+
 int create_lookup_pte_addr(struct mm_struct *mm,
                            unsigned long address,
                            unsigned long *ptep);
+
 int touch_pte_range(struct mm_struct *mm,
                     unsigned long address,
                     unsigned long size);
 
 #define io_remap_page_range(vma, vaddr, paddr, size, prot)             \
-               
direct_remap_area_pages((vma)->vm_mm,vaddr,paddr,size,prot,DOMID_IO)
+               
direct_remap_pfn_range((vma)->vm_mm,vaddr,paddr>>PAGE_SHIFT,size,prot,DOMID_IO)
 
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
-               
direct_remap_area_pages((vma)->vm_mm,vaddr,(pfn)<<PAGE_SHIFT,size,prot,DOMID_IO)
+               
direct_remap_pfn_range((vma)->vm_mm,vaddr,pfn,size,prot,DOMID_IO)
 
 #define MK_IOSPACE_PFN(space, pfn)     (pfn)
 #define GET_IOSPACE(pfn)               0
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h  Thu Sep  8 
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h  Fri Sep  9 
16:30:54 2005
@@ -387,8 +387,14 @@
 #define local_irq_disable()    __cli()
 #define local_irq_enable()     __sti()
 
+/* Don't use smp_processor_id: this is called in debug versions of that fn. */
+#ifdef CONFIG_SMP
 #define irqs_disabled()                        \
-    HYPERVISOR_shared_info->vcpu_data[smp_processor_id()].evtchn_upcall_mask
+    HYPERVISOR_shared_info->vcpu_data[__smp_processor_id()].evtchn_upcall_mask
+#else
+#define irqs_disabled()                        \
+    HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask
+#endif
 
 /*
  * disable hlt during certain critical i/o operations
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/hypervisor.h
--- a/linux-2.6-xen-sparse/include/asm-xen/hypervisor.h Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/hypervisor.h Fri Sep  9 16:30:54 2005
@@ -52,13 +52,7 @@
 #endif
 
 /* arch/xen/i386/kernel/setup.c */
-union xen_start_info_union
-{
-    start_info_t xen_start_info;
-    char padding[2048];
-};
-extern union xen_start_info_union xen_start_info_union;
-#define xen_start_info (xen_start_info_union.xen_start_info)
+extern start_info_t *xen_start_info;
 
 /* arch/xen/kernel/evtchn.c */
 /* Force a proper event-channel callback from Xen. */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h
--- a/linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h       Thu Sep 
 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h       Fri Sep 
 9 16:30:54 2005
@@ -70,14 +70,6 @@
 #define IOCTL_PRIVCMD_HYPERCALL         \
     _IOC(_IOC_NONE, 'P', 0, sizeof(privcmd_hypercall_t))
 
-/*
- * @cmd: IOCTL_PRIVCMD_INITDOMAIN_EVTCHN
- * @arg: n/a
- * Return: Port associated with domain-controller end of control event channel
- *         for the initial domain.
- */
-#define IOCTL_PRIVCMD_INITDOMAIN_EVTCHN \
-    _IOC(_IOC_NONE, 'P', 1, 0)
 #define IOCTL_PRIVCMD_MMAP             \
     _IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t))
 #define IOCTL_PRIVCMD_MMAPBATCH             \
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/xenbus.h
--- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h     Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h     Fri Sep  9 16:30:54 2005
@@ -64,6 +64,7 @@
        int (*remove)(struct xenbus_device *dev);
        int (*suspend)(struct xenbus_device *dev);
        int (*resume)(struct xenbus_device *dev);
+       int (*hotplug)(struct xenbus_device *, char **, int, char *, int);
        struct device_driver driver;
 };
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/mm/memory.c
--- a/linux-2.6-xen-sparse/mm/memory.c  Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/mm/memory.c  Fri Sep  9 16:30:54 2005
@@ -954,10 +954,8 @@
                         i++;
                         start += PAGE_SIZE;
                         len--;
-printk(KERN_ALERT "HIT  0x%lx\n", start);
                         continue;
                     } 
-else printk(KERN_ALERT "MISS 0x%lx\n", start);
                 }
 
                if (!vma || (vma->vm_flags & VM_IO)
@@ -1367,20 +1365,15 @@
        struct page *old_page, *new_page;
        unsigned long pfn = pte_pfn(pte);
        pte_t entry;
+       struct page invalid_page;
 
        if (unlikely(!pfn_valid(pfn))) {
-               /*
-                * This should really halt the system so it can be debugged or
-                * at least the kernel stops what it's doing before it corrupts
-                * data, but for the moment just pretend this is OOM.
-                */
-               pte_unmap(page_table);
-               printk(KERN_ERR "do_wp_page: bogus page at address %08lx\n",
-                               address);
-               spin_unlock(&mm->page_table_lock);
-               return VM_FAULT_OOM;
-       }
-       old_page = pfn_to_page(pfn);
+               /* This can happen with /dev/mem (PROT_WRITE, MAP_PRIVATE). */
+               invalid_page.flags = (1<<PG_reserved) | (1<<PG_locked);
+               old_page = &invalid_page;
+       } else {
+               old_page = pfn_to_page(pfn);
+       }
 
        if (!TestSetPageLocked(old_page)) {
                int reuse = can_share_swap_page(old_page);
@@ -1416,7 +1409,13 @@
                new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
                if (!new_page)
                        goto no_new_page;
-               copy_user_highpage(new_page, old_page, address);
+               if (old_page == &invalid_page) {
+                       char *vto = kmap_atomic(new_page, KM_USER1);
+                       copy_page(vto, (void *)(address & PAGE_MASK));
+                       kunmap_atomic(vto, KM_USER1);
+               } else {
+                       copy_user_highpage(new_page, old_page, address);
+               }
        }
        /*
         * Re-check the pte - we dropped the lock
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/Makefile
--- a/tools/Makefile    Thu Sep  8 15:18:40 2005
+++ b/tools/Makefile    Fri Sep  9 16:30:54 2005
@@ -7,14 +7,23 @@
 SUBDIRS += misc
 SUBDIRS += examples
 SUBDIRS += xentrace
-SUBDIRS += python
-SUBDIRS += xcs
 SUBDIRS += xcutils
-#SUBDIRS += pygrub
 SUBDIRS += firmware
 SUBDIRS += security
 SUBDIRS += console
+ifeq ($(VTPM_TOOLS),y)
+SUBDIRS += vtpm_manager
+SUBDIRS += vtpm
+endif
 SUBDIRS += xenstat
+
+.PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
+
+# These don't cross-compile
+ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
+SUBDIRS += python
+#SUBDIRS += pygrub
+endif
 
 .PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/Rules.mk
--- a/tools/Rules.mk    Thu Sep  8 15:18:40 2005
+++ b/tools/Rules.mk    Fri Sep  9 16:30:54 2005
@@ -4,7 +4,6 @@
 
 XEN_XC             = $(XEN_ROOT)/tools/python/xen/lowlevel/xc
 XEN_LIBXC          = $(XEN_ROOT)/tools/libxc
-XEN_XCS            = $(XEN_ROOT)/tools/xcs
 XEN_XENSTORE       = $(XEN_ROOT)/tools/xenstore
 XEN_LIBXENSTAT     = $(XEN_ROOT)/tools/xenstat/libxenstat/src
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/Makefile
--- a/tools/blktap/Makefile     Thu Sep  8 15:18:40 2005
+++ b/tools/blktap/Makefile     Fri Sep  9 16:30:54 2005
@@ -6,7 +6,8 @@
 include $(XEN_ROOT)/tools/Rules.mk
 
 SUBDIRS :=
-SUBDIRS += parallax
+SUBDIRS += ublkback
+#SUBDIRS += parallax
 
 BLKTAP_INSTALL_DIR = /usr/sbin
 
@@ -14,12 +15,12 @@
 INSTALL_PROG       = $(INSTALL) -m0755
 INSTALL_DIR        = $(INSTALL) -d -m0755
 
-INCLUDES += -I. -I $(XEN_LIBXC)
+INCLUDES += -I. -I $(XEN_LIBXC) -I $(XEN_XENSTORE)
 
 LIBS     := -lpthread -lz
 
 SRCS     :=
-SRCS     += blktaplib.c
+SRCS     += blktaplib.c xenbus.c blkif.c
 
 CFLAGS   += -Wall
 CFLAGS   += -Werror
@@ -28,17 +29,20 @@
 CFLAGS   += -g3
 CFLAGS   += -fno-strict-aliasing
 CFLAGS   += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
+# get asprintf():
+CFLAGS   += -D _GNU_SOURCE
 # Get gcc to generate the dependencies for us.
 CFLAGS   += -Wp,-MD,.$(@F).d
 CFLAGS   += $(INCLUDES) 
 DEPS     = .*.d
 
 OBJS     = $(patsubst %.c,%.o,$(SRCS))
-IBINS    = blkdump
+IBINS   :=
+#IBINS   += blkdump
 
 LIB      = libblktap.so libblktap.so.$(MAJOR) libblktap.so.$(MAJOR).$(MINOR)
 
-all: mk-symlinks libblktap.so blkdump
+all: mk-symlinks libblktap.so #blkdump
        @set -e; for subdir in $(SUBDIRS); do \
                $(MAKE) -C $$subdir $@;       \
        done
@@ -59,7 +63,7 @@
        $(INSTALL_DIR) -p $(DESTDIR)/usr/include
        $(INSTALL_PROG) $(LIB) $(DESTDIR)/usr/$(LIBDIR)
        $(INSTALL_PROG) blktaplib.h $(DESTDIR)/usr/include
-       $(INSTALL_PROG) $(IBINS) $(DESTDIR)$(BLKTAP_INSTALL_DIR)
+       #$(INSTALL_PROG) $(IBINS) $(DESTDIR)$(BLKTAP_INSTALL_DIR)
        @set -e; for subdir in $(SUBDIRS); do \
                $(MAKE) -C $$subdir $@;       \
        done
@@ -79,14 +83,16 @@
        mv staging/i386/*.rpm .
        rm -rf staging
 
-libblktap.so: $(OBJS)
-       $(CC) $(CFLAGS) -Wl,-soname -Wl,$(SONAME) -shared -o      \
-             libblktap.so.$(MAJOR).$(MINOR) $^ $(LIBS)
+libblktap.so: $(OBJS) 
+       $(CC) $(CFLAGS) -Wl,-soname -Wl,$(SONAME) -shared         \
+             -L$(XEN_XENSTORE) -l xenstore                       \
+             -o libblktap.so.$(MAJOR).$(MINOR) $^ $(LIBS)
        ln -sf libblktap.so.$(MAJOR).$(MINOR) libblktap.so.$(MAJOR)
        ln -sf libblktap.so.$(MAJOR) $@
 
 blkdump: libblktap.so
-       $(CC) $(CFLAGS) -o blkdump -L$(XEN_LIBXC) -L. -l blktap blkdump.c
+       $(CC) $(CFLAGS) -o blkdump -L$(XEN_LIBXC) -L. \
+             -l blktap blkdump.c
 
 .PHONY: TAGS clean install mk-symlinks rpm
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/blkdump.c
--- a/tools/blktap/blkdump.c    Thu Sep  8 15:18:40 2005
+++ b/tools/blktap/blkdump.c    Fri Sep  9 16:30:54 2005
@@ -8,85 +8,18 @@
 #include <stdio.h>
 #include "blktaplib.h"
  
-int control_print(control_msg_t *msg)
-{
-    if (msg->type != CMSG_BLKIF_BE) 
-    {
-        printf("***\nUNEXPECTED CTRL MSG MAJOR TYPE(%d)\n***\n", msg->type);
-        return 0;
-    }
-    
-    switch(msg->subtype)
-    {
-    case CMSG_BLKIF_BE_CREATE:
-        if ( msg->length != sizeof(blkif_be_create_t) )
-            goto parse_error;
-        printf("[CONTROL_MSG] CMSG_BLKIF_BE_CREATE(d:%d,h:%d)\n",
-                ((blkif_be_create_t *)msg->msg)->domid,
-                ((blkif_be_create_t *)msg->msg)->blkif_handle);
-        break; 
-    case CMSG_BLKIF_BE_DESTROY:
-        if ( msg->length != sizeof(blkif_be_destroy_t) )
-            goto parse_error;
-        printf("[CONTROL_MSG] CMSG_BLKIF_BE_DESTROY(d:%d,h:%d)\n",
-                ((blkif_be_destroy_t *)msg->msg)->domid,
-                ((blkif_be_destroy_t *)msg->msg)->blkif_handle);
-        break;   
-    case CMSG_BLKIF_BE_CONNECT:
-        if ( msg->length != sizeof(blkif_be_connect_t) )
-            goto parse_error;
-        printf("[CONTROL_MSG] CMSG_BLKIF_BE_CONNECT(d:%d,h:%d)\n",
-                ((blkif_be_connect_t *)msg->msg)->domid,
-                ((blkif_be_connect_t *)msg->msg)->blkif_handle);
-        break;        
-    case CMSG_BLKIF_BE_DISCONNECT:
-        if ( msg->length != sizeof(blkif_be_disconnect_t) )
-            goto parse_error;
-        printf("[CONTROL_MSG] CMSG_BLKIF_BE_DISCONNECT(d:%d,h:%d)\n",
-                ((blkif_be_disconnect_t *)msg->msg)->domid,
-                ((blkif_be_disconnect_t *)msg->msg)->blkif_handle);
-        break;     
-    case CMSG_BLKIF_BE_VBD_CREATE:
-        if ( msg->length != sizeof(blkif_be_vbd_create_t) )
-            goto parse_error;
-        printf("[CONTROL_MSG] CMSG_BLKIF_BE_VBD_CREATE(d:%d,h:%d,v:%d)\n",
-                ((blkif_be_vbd_create_t *)msg->msg)->domid,
-                ((blkif_be_vbd_create_t *)msg->msg)->blkif_handle,
-                ((blkif_be_vbd_create_t *)msg->msg)->vdevice);
-        break;
-    case CMSG_BLKIF_BE_VBD_DESTROY:
-        if ( msg->length != sizeof(blkif_be_vbd_destroy_t) )
-            goto parse_error;
-        printf("[CONTROL_MSG] CMSG_BLKIF_BE_VBD_DESTROY(d:%d,h:%d,v:%d)\n",
-                ((blkif_be_vbd_destroy_t *)msg->msg)->domid,
-                ((blkif_be_vbd_destroy_t *)msg->msg)->blkif_handle,
-                ((blkif_be_vbd_destroy_t *)msg->msg)->vdevice);
-        break;
-    default:
-        goto parse_error;
-    }
-   
-    return 0; 
-      
-parse_error:
-    printf("[CONTROL_MSG] Bad message type or length!\n");
-    return 0;
-}
- 
 int request_print(blkif_request_t *req)
 {
     int i;
     unsigned long fas;
     
-    if ( req->operation == BLKIF_OP_PROBE ) {
-        printf("[%2u:%2u<%s]\n", ID_TO_DOM(req->id), ID_TO_IDX(req->id),
-                blkif_op_name[req->operation]);
-        return BLKTAP_PASS;
-    } else {
+    if ( (req->operation == BLKIF_OP_READ) ||
+         (req->operation == BLKIF_OP_WRITE) )
+    {
         printf("[%2u:%2u<%5s] (nr_segs: %03u, dev: %03u, %010llu)\n", 
                 ID_TO_DOM(req->id), ID_TO_IDX(req->id), 
                 blkif_op_name[req->operation], 
-                req->nr_segments, req->device, 
+                req->nr_segments, req->handle, 
                 req->sector_number);
         
         
@@ -99,6 +32,8 @@
                     );
         }
             
+    } else {
+        printf("Unknown request message type.\n");
     }
     
     return BLKTAP_PASS;
@@ -106,23 +41,22 @@
 
 int response_print(blkif_response_t *rsp)
 {   
-    if ( rsp->operation == BLKIF_OP_PROBE ) {
-        printf("[%2u:%2u>%s]\n", ID_TO_DOM(rsp->id), ID_TO_IDX(rsp->id),
-                blkif_op_name[rsp->operation]);
-        return BLKTAP_PASS;
-    } else {
+    if ( (rsp->operation == BLKIF_OP_READ) ||
+         (rsp->operation == BLKIF_OP_WRITE) )
+    {
         printf("[%2u:%2u>%5s] (status: %d)\n", 
                 ID_TO_DOM(rsp->id), ID_TO_IDX(rsp->id), 
                 blkif_op_name[rsp->operation], 
                 rsp->status);
             
+    } else {
+        printf("Unknown request message type.\n");
     }
     return BLKTAP_PASS;
 }
 
 int main(int argc, char *argv[])
 {
-    blktap_register_ctrl_hook("control_print", control_print);
     blktap_register_request_hook("request_print", request_print);
     blktap_register_response_hook("response_print", response_print);
     blktap_listen();
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/blktaplib.c
--- a/tools/blktap/blktaplib.c  Thu Sep  8 15:18:40 2005
+++ b/tools/blktap/blktaplib.c  Fri Sep  9 16:30:54 2005
@@ -24,7 +24,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <pthread.h>
-
+#include <xs.h>
                                                                      
 #define __COMPILING_BLKTAP_LIB
 #include "blktaplib.h"
@@ -34,11 +34,12 @@
 #else
 #define DPRINTF(_f, _a...) ((void)0)
 #endif
-#define DEBUG_RING_IDXS 1
+#define DEBUG_RING_IDXS 0
 
 #define POLLRDNORM     0x040 
 
 #define BLKTAP_IOCTL_KICK 1
+
 
 void got_sig_bus();
 void got_sig_int();
@@ -46,17 +47,13 @@
 /* in kernel these are opposite, but we are a consumer now. */
 blkif_back_ring_t  fe_ring; /* slightly counterintuitive ;) */
 blkif_front_ring_t be_ring; 
-ctrl_back_ring_t   ctrl_ring;
 
 unsigned long mmap_vstart = 0;
 char *blktap_mem;
 int fd = 0;
 
-#define BLKTAP_RING_PAGES       3 /* Ctrl, Back, Front */
-/*#define BLKTAP_MMAP_PAGES       ((11 + 1) * 64)*/
-#define BLKTAP_MMAP_PAGES \
-    ((BLKIF_MAX_SEGMENTS_PER_REQUEST + 1) * BLKIF_RING_SIZE)
-#define BLKTAP_MMAP_REGION_SIZE (BLKTAP_RING_PAGES + BLKTAP_MMAP_PAGES)
+#define BLKTAP_RING_PAGES       1 /* Front */
+#define BLKTAP_MMAP_REGION_SIZE (BLKTAP_RING_PAGES + MMAP_PAGES)
     
 int bad_count = 0;
 void bad(void)
@@ -79,126 +76,13 @@
 }
 
 inline domid_t ID_TO_DOM(unsigned long id) { return (id >> 16); }
-/*
+
 static int (*request_hook)(blkif_request_t *req) = NULL;
 static int (*response_hook)(blkif_response_t *req) = NULL;
-*/
-
-/*-----[ Request/Response hook chains.]----------------------------------*/
-
-#define HOOK_NAME_MAX 50
-        
-typedef struct ctrl_hook_st {
-    char name[HOOK_NAME_MAX];
-    int (*func)(control_msg_t *);
-    struct ctrl_hook_st *next;
-} ctrl_hook_t;
-        
-typedef struct request_hook_st {
-    char name[HOOK_NAME_MAX];
-    int (*func)(blkif_request_t *);
-    struct request_hook_st *next;
-} request_hook_t;
-
-typedef struct response_hook_st {
-    char name[HOOK_NAME_MAX];
-    int (*func)(blkif_response_t *);
-    struct response_hook_st *next;
-} response_hook_t;
-
-static ctrl_hook_t *ctrl_hook_chain = NULL;
-static request_hook_t *request_hook_chain = NULL;
-static response_hook_t *response_hook_chain = NULL;
-
-void blktap_register_ctrl_hook(char *name, int (*ch)(control_msg_t *)) 
-{
-    ctrl_hook_t *ch_ent, **c;
-    
-    ch_ent = (ctrl_hook_t *)malloc(sizeof(ctrl_hook_t));
-    if (!ch_ent) { printf("couldn't allocate a new hook\n"); exit(-1); }
-    
-    ch_ent->func  = ch;
-    ch_ent->next = NULL;
-    strncpy(ch_ent->name, name, HOOK_NAME_MAX);
-    ch_ent->name[HOOK_NAME_MAX-1] = '\0';
-    
-    c = &ctrl_hook_chain;
-    while (*c != NULL) {
-        c = &(*c)->next;
-    }
-    *c = ch_ent;
-}
-
-void blktap_register_request_hook(char *name, int (*rh)(blkif_request_t *)) 
-{
-    request_hook_t *rh_ent, **c;
-    
-    rh_ent = (request_hook_t *)malloc(sizeof(request_hook_t));
-    if (!rh_ent) { printf("couldn't allocate a new hook\n"); exit(-1); }
-    
-    rh_ent->func  = rh;
-    rh_ent->next = NULL;
-    strncpy(rh_ent->name, name, HOOK_NAME_MAX);
-    
-    c = &request_hook_chain;
-    while (*c != NULL) {
-        c = &(*c)->next;
-    }
-    *c = rh_ent;
-}
-
-void blktap_register_response_hook(char *name, int (*rh)(blkif_response_t *)) 
-{
-    response_hook_t *rh_ent, **c;
-    
-    rh_ent = (response_hook_t *)malloc(sizeof(response_hook_t));
-    if (!rh_ent) { printf("couldn't allocate a new hook\n"); exit(-1); }
-    
-    rh_ent->func  = rh;
-    rh_ent->next = NULL;
-    strncpy(rh_ent->name, name, HOOK_NAME_MAX);
-    
-    c = &response_hook_chain;
-    while (*c != NULL) {
-        c = &(*c)->next;
-    }
-    *c = rh_ent;
-}
-
-void print_hooks(void)
-{
-    request_hook_t  *req_hook;
-    response_hook_t *rsp_hook;
-    ctrl_hook_t     *ctrl_hook;
-    
-    DPRINTF("Control Hooks:\n");
-    ctrl_hook = ctrl_hook_chain;
-    while (ctrl_hook != NULL)
-    {
-        DPRINTF("  [0x%p] %s\n", ctrl_hook->func, ctrl_hook->name);
-        ctrl_hook = ctrl_hook->next;
-    }
-    
-    DPRINTF("Request Hooks:\n");
-    req_hook = request_hook_chain;
-    while (req_hook != NULL)
-    {
-        DPRINTF("  [0x%p] %s\n", req_hook->func, req_hook->name);
-        req_hook = req_hook->next;
-    }
-    
-    DPRINTF("Response Hooks:\n");
-    rsp_hook = response_hook_chain;
-    while (rsp_hook != NULL)
-    {
-        DPRINTF("  [0x%p] %s\n", rsp_hook->func, rsp_hook->name);
-        rsp_hook = rsp_hook->next;
-    }
-}
         
 /*-----[ Data to/from Backend (server) VM ]------------------------------*/
 
-
+/*
 
 inline int write_req_to_be_ring(blkif_request_t *req)
 {
@@ -214,6 +98,7 @@
     
     return 0;
 }
+*/
 
 inline int write_rsp_to_fe_ring(blkif_response_t *rsp)
 {
@@ -230,14 +115,14 @@
     return 0;
 }
 
-static void apply_rsp_hooks(blkif_response_t *rsp)
+static void apply_rsp_hooks(blkif_t *blkif, blkif_response_t *rsp)
 {
     response_hook_t  *rsp_hook;
     
-    rsp_hook = response_hook_chain;
+    rsp_hook = blkif->response_hook_chain;
     while (rsp_hook != NULL)
     {
-        switch(rsp_hook->func(rsp))
+        switch(rsp_hook->func(blkif, rsp, 1))
         {
         case BLKTAP_PASS:
             break;
@@ -248,15 +133,19 @@
     }
 }
 
+
 static pthread_mutex_t push_mutex = PTHREAD_MUTEX_INITIALIZER;
 
-void blktap_inject_response(blkif_response_t *rsp)
-{
-    
-    apply_rsp_hooks(rsp);
-    
+void blkif_inject_response(blkif_t *blkif, blkif_response_t *rsp)
+{
+    
+    apply_rsp_hooks(blkif, rsp);
+  
     write_rsp_to_fe_ring(rsp);
-    
+}
+
+void blktap_kick_responses(void)
+{
     pthread_mutex_lock(&push_mutex);
     
     RING_PUSH_RESPONSES(&fe_ring);
@@ -277,7 +166,7 @@
     int active;
 } pollhook_t;
 
-static struct pollfd  pfd[MAX_POLLFDS+1];
+static struct pollfd  pfd[MAX_POLLFDS+2]; /* tap and store are extra */
 static pollhook_t     pollhooks[MAX_POLLFDS];
 static unsigned int   ph_freelist[MAX_POLLFDS];
 static unsigned int   ph_cons, ph_prod;
@@ -344,65 +233,65 @@
 
 int blktap_listen(void)
 {
-    int               notify_be, notify_fe, tap_pfd;
-    
+    int notify_be, notify_fe, tap_pfd, store_pfd, xs_fd, ret;
+    struct xs_handle *h;
+    blkif_t *blkif;
+
     /* comms rings: */
     blkif_request_t  *req;
     blkif_response_t *rsp;
-    control_msg_t    *msg;
     blkif_sring_t    *sring;
-    ctrl_sring_t     *csring;
     RING_IDX          rp, i, pfd_count; 
     
     /* pending rings */
     blkif_request_t req_pending[BLKIF_RING_SIZE];
-    blkif_response_t rsp_pending[BLKIF_RING_SIZE];
+    /* blkif_response_t rsp_pending[BLKIF_RING_SIZE] */;
     
     /* handler hooks: */
     request_hook_t   *req_hook;
     response_hook_t  *rsp_hook;
-    ctrl_hook_t      *ctrl_hook;
     
     signal (SIGBUS, got_sig_bus);
     signal (SIGINT, got_sig_int);
     
-    print_hooks();
-    
+    __init_blkif();
+
     fd = open("/dev/blktap", O_RDWR);
-    if (fd == -1) {
-        printf("open failed! (%d)\n", errno);
-        goto open_failed;
-    }
+    if (fd == -1)
+        err(-1, "open failed!");
 
     blktap_mem = mmap(0, PAGE_SIZE * BLKTAP_MMAP_REGION_SIZE, 
              PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 
-    if ((int)blktap_mem == -1) {
-        printf("mmap failed! (%d)\n", errno);
-        goto mmap_failed;
-    }
+    if ((int)blktap_mem == -1) 
+        err(-1, "mmap failed!");
 
     /* assign the rings to the mapped memory */
-    csring = (ctrl_sring_t *)blktap_mem;
-    BACK_RING_INIT(&ctrl_ring, csring, PAGE_SIZE);
-    
+/*
     sring = (blkif_sring_t *)((unsigned long)blktap_mem + PAGE_SIZE);
     FRONT_RING_INIT(&be_ring, sring, PAGE_SIZE);
-    
-    sring = (blkif_sring_t *)((unsigned long)blktap_mem + (2 *PAGE_SIZE));
+*/  
+    sring = (blkif_sring_t *)((unsigned long)blktap_mem);
     BACK_RING_INIT(&fe_ring, sring, PAGE_SIZE);
 
     mmap_vstart = (unsigned long)blktap_mem +(BLKTAP_RING_PAGES << PAGE_SHIFT);
 
+
+    /* Set up store connection and watch. */
+    h = xs_daemon_open();
+    if (h == NULL) 
+        err(-1, "xs_daemon_open");
+    
+    ret = add_blockdevice_probe_watch(h, "Domain-0");
+    if (ret != 0)
+        err(0, "adding device probewatch");
+    
     ioctl(fd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE );
 
     while(1) {
         int ret;
         
         /* build the poll list */
-        
-        DPRINTF("Building poll list.\n");
-        
         pfd_count = 0;
         for ( i=0; i < MAX_POLLFDS; i++ ) {
             pollhook_t *ph = &pollhooks[i];
@@ -415,49 +304,31 @@
             }
         }
 
-        tap_pfd = pfd_count;
+        tap_pfd = pfd_count++;
         pfd[tap_pfd].fd = fd;
         pfd[tap_pfd].events = POLLIN;
 
-        DPRINTF("poll() %d fds.\n", pfd_count);
+        store_pfd = pfd_count++;
+        pfd[store_pfd].fd = xs_fileno(h);
+        pfd[store_pfd].events = POLLIN;
         
-        if ( (ret = (poll(pfd, pfd_count+1, 10000)) == 0) ) {
+        if ( (ret = (poll(pfd, pfd_count, 10000)) == 0) ) {
             if (DEBUG_RING_IDXS)
                 ioctl(fd, BLKTAP_IOCTL_PRINT_IDXS);
             continue;
         }
 
-        DPRINTF("poll returned %d\n", ret);
-
         for (i=0; i < MAX_POLLFDS; i++) {
             if ( (pollhooks[i].active ) && (pollhooks[i].pfd->revents ) )
                 pollhooks[i].func(pollhooks[i].pfd->fd);
         }
         
-        if (pfd[tap_pfd].revents) {
-            
-            /* empty the control ring */
-            rp = ctrl_ring.sring->req_prod;
-            rmb();
-            for (i = ctrl_ring.req_cons; i < rp; i++)
-            {
-                msg = RING_GET_REQUEST(&ctrl_ring, i);
-
-                ctrl_hook = ctrl_hook_chain;
-                while (ctrl_hook != NULL)
-                {
-                    DPRINTF("CTRL_HOOK: %s\n", ctrl_hook->name);
-                    /* We currently don't respond to ctrl messages. */
-                    ctrl_hook->func(msg);
-                    ctrl_hook = ctrl_hook->next;
-                }
-            }
-            /* Using this as a unidirectional ring. */
-            ctrl_ring.req_cons = ctrl_ring.rsp_prod_pvt = i;
-pthread_mutex_lock(&push_mutex);
-            RING_PUSH_RESPONSES(&ctrl_ring);
-pthread_mutex_unlock(&push_mutex);
-            
+        if (pfd[store_pfd].revents) {
+            ret = xs_fire_next_watch(h);
+        }
+
+        if (pfd[tap_pfd].revents) 
+        {    
             /* empty the fe_ring */
             notify_fe = 0;
             notify_be = RING_HAS_UNCONSUMED_REQUESTS(&fe_ring);
@@ -465,44 +336,62 @@
             rmb();
             for (i = fe_ring.req_cons; i != rp; i++)
             {
-                int done = 0; /* stop forwarding this request */
+                int done = 0; 
 
                 req = RING_GET_REQUEST(&fe_ring, i);
                 memcpy(&req_pending[ID_TO_IDX(req->id)], req, sizeof(*req));
                 req = &req_pending[ID_TO_IDX(req->id)];
 
-                DPRINTF("copying an fe request\n");
-
-                req_hook = request_hook_chain;
-                while (req_hook != NULL)
+                blkif = blkif_find_by_handle(ID_TO_DOM(req->id), req->handle);
+
+                if (blkif != NULL)
                 {
-                    DPRINTF("REQ_HOOK: %s\n", req_hook->name);
-                    switch(req_hook->func(req))
+                    req_hook = blkif->request_hook_chain;
+                    while (req_hook != NULL)
                     {
-                    case BLKTAP_RESPOND:
-                        apply_rsp_hooks((blkif_response_t *)req);
-                        write_rsp_to_fe_ring((blkif_response_t *)req);
-                        notify_fe = 1;
-                        done = 1;
-                        break;
-                    case BLKTAP_STOLEN:
-                        done = 1;
-                        break;
-                    case BLKTAP_PASS:
-                        break;
-                    default:
-                        printf("Unknown request hook return value!\n");
+                        switch(req_hook->func(blkif, req, ((i+1) == rp)))
+                        {
+                        case BLKTAP_RESPOND:
+                            apply_rsp_hooks(blkif, (blkif_response_t *)req);
+                            write_rsp_to_fe_ring((blkif_response_t *)req);
+                            notify_fe = 1;
+                            done = 1;
+                            break;
+                        case BLKTAP_STOLEN:
+                            done = 1;
+                            break;
+                        case BLKTAP_PASS:
+                            break;
+                        default:
+                            printf("Unknown request hook return value!\n");
+                        }
+                        if (done) break;
+                        req_hook = req_hook->next;
                     }
-                    if (done) break;
-                    req_hook = req_hook->next;
                 }
 
-                if (done == 0) write_req_to_be_ring(req);
+                if (done == 0) 
+                {
+                    /* this was:  */
+                    /* write_req_to_be_ring(req); */
+
+                    unsigned long id = req->id;
+                    unsigned short operation = req->operation;
+                    printf("Unterminated request!\n");
+                    rsp = (blkif_response_t *)req;
+                    rsp->id = id;
+                    rsp->operation = operation;
+                    rsp->status = BLKIF_RSP_ERROR;
+                    write_rsp_to_fe_ring(rsp);
+                    notify_fe = 1;
+                    done = 1;
+                }
 
             }
             fe_ring.req_cons = i;
 
             /* empty the be_ring */
+/*
             notify_fe |= RING_HAS_UNCONSUMED_RESPONSES(&be_ring);
             rp = be_ring.sring->rsp_prod;
             rmb();
@@ -519,9 +408,9 @@
                 write_rsp_to_fe_ring(rsp);
             }
             be_ring.rsp_cons = i;
-
+*/
             /* notify the domains */
-
+/*
             if (notify_be) {
                 DPRINTF("notifying be\n");
 pthread_mutex_lock(&push_mutex);
@@ -529,13 +418,13 @@
                 ioctl(fd, BLKTAP_IOCTL_KICK_BE);
 pthread_mutex_unlock(&push_mutex);
             }
-
+*/
             if (notify_fe) {
                 DPRINTF("notifying fe\n");
-pthread_mutex_lock(&push_mutex);
+                pthread_mutex_lock(&push_mutex);
                 RING_PUSH_RESPONSES(&fe_ring);
                 ioctl(fd, BLKTAP_IOCTL_KICK_FE);
-pthread_mutex_unlock(&push_mutex);
+                pthread_mutex_unlock(&push_mutex);
             }
         }        
     }
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/blktaplib.h
--- a/tools/blktap/blktaplib.h  Thu Sep  8 15:18:40 2005
+++ b/tools/blktap/blktaplib.h  Fri Sep  9 16:30:54 2005
@@ -2,6 +2,9 @@
  *
  * userland accessors to the block tap.
  *
+ * Sept 2/05 -- I'm scaling this back to only support block remappings
+ * to user in a backend domain.  Passthrough and interposition can be readded
+ * once transitive grants are available.
  */
  
 #ifndef __BLKTAPLIB_H__
@@ -13,6 +16,7 @@
 #include <xen/io/blkif.h>
 #include <xen/io/ring.h>
 #include <xen/io/domain_controller.h>
+#include <xs.h>
 
 /* /dev/xen/blktap resides at device number major=10, minor=202        */ 
 #define BLKTAP_MINOR 202
@@ -49,12 +53,18 @@
     return (
         ( arg == BLKTAP_MODE_PASSTHROUGH  ) ||
         ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
+        ( arg == BLKTAP_MODE_INTERPOSE    ) );
+/*
+    return (
+        ( arg == BLKTAP_MODE_PASSTHROUGH  ) ||
+        ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
         ( arg == BLKTAP_MODE_INTERCEPT_BE ) ||
         ( arg == BLKTAP_MODE_INTERPOSE    ) ||
         ( (arg & ~BLKTAP_MODE_COPY_FE_PAGES) == BLKTAP_MODE_COPY_FE ) ||
         ( (arg & ~BLKTAP_MODE_COPY_BE_PAGES) == BLKTAP_MODE_COPY_BE ) ||
         ( (arg & ~BLKTAP_MODE_COPY_BOTH_PAGES) == BLKTAP_MODE_COPY_BOTH )
         );
+*/
 }
 
 /* Return values for handling messages in hooks. */
@@ -62,29 +72,88 @@
 #define BLKTAP_RESPOND  1 /* Request is now a reply.  Return it.  */
 #define BLKTAP_STOLEN   2 /* Hook has stolen request.             */
 
-#define domid_t unsigned short
+//#define domid_t unsigned short
 
 inline unsigned int ID_TO_IDX(unsigned long id);
 inline domid_t ID_TO_DOM(unsigned long id);
 
-void blktap_register_ctrl_hook(char *name, int (*ch)(control_msg_t *));
-void blktap_register_request_hook(char *name, int (*rh)(blkif_request_t *));
-void blktap_register_response_hook(char *name, int (*rh)(blkif_response_t *));
-void blktap_inject_response(blkif_response_t *);
 int  blktap_attach_poll(int fd, short events, int (*func)(int));
 void blktap_detach_poll(int fd);
 int  blktap_listen(void);
 
+struct blkif;
+
+typedef struct request_hook_st {
+    char *name;
+    int (*func)(struct blkif *, blkif_request_t *, int);
+    struct request_hook_st *next;
+} request_hook_t;
+
+typedef struct response_hook_st {
+    char *name;
+    int (*func)(struct blkif *, blkif_response_t *, int);
+    struct response_hook_st *next;
+} response_hook_t;
+
+struct blkif_ops {
+    long int (*get_size)(struct blkif *blkif);
+    long int (*get_secsize)(struct blkif *blkif);
+    unsigned (*get_info)(struct blkif *blkif);
+};
+
+typedef struct blkif {
+    domid_t domid;
+    long int handle;
+
+    long int pdev;
+    long int readonly;
+
+    enum { DISCONNECTED, CONNECTED } state;
+
+    struct blkif_ops *ops;
+    request_hook_t *request_hook_chain;
+    response_hook_t *response_hook_chain;
+
+    struct blkif *hash_next;
+
+    void *prv;  /* device-specific data */
+} blkif_t;
+
+void register_new_blkif_hook(int (*fn)(blkif_t *blkif));
+blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle);
+blkif_t *alloc_blkif(domid_t domid);
+int blkif_init(blkif_t *blkif, long int handle, long int pdev, 
+               long int readonly);
+void free_blkif(blkif_t *blkif);
+void __init_blkif(void);
+
+
+/* xenstore/xenbus: */
+extern int add_blockdevice_probe_watch(struct xs_handle *h, 
+                                       const char *domname);
+int xs_fire_next_watch(struct xs_handle *h);
+
+
+void blkif_print_hooks(blkif_t *blkif);
+void blkif_register_request_hook(blkif_t *blkif, char *name, 
+                             int (*rh)(blkif_t *, blkif_request_t *, int));
+void blkif_register_response_hook(blkif_t *blkif, char *name, 
+                             int (*rh)(blkif_t *, blkif_response_t *, int));
+void blkif_inject_response(blkif_t *blkif, blkif_response_t *);
+void blktap_kick_responses(void);
+
+/* this must match the underlying driver... */
+#define MAX_PENDING_REQS 64
+
 /* Accessing attached data page mappings */
-#define MMAP_PAGES_PER_REQUEST \
-    (BLKIF_MAX_SEGMENTS_PER_REQUEST + 1)
-#define MMAP_VADDR(_req,_seg)                        \
-    (mmap_vstart +                                   \
-     ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \
+#define MMAP_PAGES                                              \
+    (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
+#define MMAP_VADDR(_req,_seg)                                   \
+    (mmap_vstart +                                              \
+     ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) +    \
      ((_seg) * PAGE_SIZE))
 
 extern unsigned long mmap_vstart;
-
 
 /* Defines that are only used by library clients */
 
@@ -93,7 +162,6 @@
 static char *blkif_op_name[] = {
     [BLKIF_OP_READ]       = "READ",
     [BLKIF_OP_WRITE]      = "WRITE",
-    [BLKIF_OP_PROBE]      = "PROBE",
 };
 
 #endif /* __COMPILING_BLKTAP_LIB */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_brctl
--- a/tools/check/check_brctl   Thu Sep  8 15:18:40 2005
+++ b/tools/check/check_brctl   Fri Sep  9 16:30:54 2005
@@ -2,8 +2,9 @@
 # CHECK-INSTALL
 
 function error {
-   echo 'Check for the bridge control utils (brctl) failed.'
+   echo
+   echo '  *** Check for the bridge control utils (brctl) FAILED'
    exit 1
 }
 
-brctl show || error
\ No newline at end of file
+which brctl 1>/dev/null 2>&1 || error
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_iproute
--- a/tools/check/check_iproute Thu Sep  8 15:18:40 2005
+++ b/tools/check/check_iproute Fri Sep  9 16:30:54 2005
@@ -2,9 +2,10 @@
 # CHECK-INSTALL
 
 function error {
-   echo 'Check for iproute (ip addr) failed.'
+   echo
+   echo '  *** Check for iproute (ip addr) FAILED'
    exit 1
 }
 
-ip addr list || error
+ip addr list 1>/dev/null 2>&1 || error
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_logging
--- a/tools/check/check_logging Thu Sep  8 15:18:40 2005
+++ b/tools/check/check_logging Fri Sep  9 16:30:54 2005
@@ -18,11 +18,12 @@
         import logging
     except ImportError:
         hline()
-        msg("Python logging is not installed.")
-        msg("Use 'make install-logging' at the xen root to install.")
         msg("")
-        msg("Alternatively download and install from")
-        msg("http://www.red-dove.com/python_logging.html";)
+        msg("  *** Python logging is not installed.")
+        msg("  *** Use 'make install-logging' at the xen root to install.")
+        msg("  *** ")
+        msg("  *** Alternatively download and install from")
+        msg("  *** http://www.red-dove.com/python_logging.html";)
         hline()
         sys.exit(1)
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_python
--- a/tools/check/check_python  Thu Sep  8 15:18:40 2005
+++ b/tools/check/check_python  Fri Sep  9 16:30:54 2005
@@ -2,9 +2,9 @@
 # CHECK-BUILD CHECK-INSTALL
 
 function error {
-    echo "Check for Python version 2.2 or higher failed."
+    echo
+    echo "  *** Check for Python version >= 2.2 FAILED"
     exit 1
 }
 
-python -V
 python -V 2>&1 | cut -d ' ' -f 2 | grep -q -E '^2.2|^2.3|^2.4' || error
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_zlib_devel
--- a/tools/check/check_zlib_devel      Thu Sep  8 15:18:40 2005
+++ b/tools/check/check_zlib_devel      Fri Sep  9 16:30:54 2005
@@ -2,9 +2,10 @@
 # CHECK-BUILD
 
 function error {
-    echo 'Check for zlib includes failed.'
+    echo
+    echo "  *** Check for zlib headers FAILED"
     exit 1
 }
 
 set -e
-[ -e /usr/include/zlib.h ] || error
\ No newline at end of file
+[ -e /usr/include/zlib.h ] || error
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_zlib_lib
--- a/tools/check/check_zlib_lib        Thu Sep  8 15:18:40 2005
+++ b/tools/check/check_zlib_lib        Fri Sep  9 16:30:54 2005
@@ -2,9 +2,10 @@
 # CHECK-BUILD CHECK-INSTALL
 
 function error {
-    echo 'Check for zlib library failed.'
+    echo
+    echo "  *** Check for zlib library FAILED"
     exit 1
 }
 
 set -e
-ldconfig -p | grep libz.so || error
\ No newline at end of file
+ldconfig -p | grep -q libz.so || error
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/chk
--- a/tools/check/chk   Thu Sep  8 15:18:40 2005
+++ b/tools/check/chk   Fri Sep  9 16:30:54 2005
@@ -17,14 +17,11 @@
 case $1 in
     build)
         check="CHECK-BUILD"
-        info=".chkbuild"
         ;;
     install)
         check="CHECK-INSTALL"
-        info=".chkinstall"
         ;;
     clean)
-        rm -f .chkbuild .chkinstall
         exit 0
         ;;
     *)
@@ -34,7 +31,7 @@
 
 failed=0
 
-echo "Xen ${check} " $(date) > ${info}
+echo "Xen ${check} " $(date)
 for f in check_* ; do
     case $f in
         *~)
@@ -49,24 +46,12 @@
     if ! grep -q ${check} $f ; then
         continue
     fi
-    echo ' ' >> ${info}
-    echo "Checking $f" >> ${info}
-    if ./$f 1>>${info} 2>&1 ; then
-        echo OK >> ${info}
+    echo -n "Checking $f: "
+    if ./$f 2>&1 ; then
+        echo OK
     else
         failed=1
-        echo "FAILED $f"
-        echo FAILED >> ${info}
     fi
 done
 
-echo >> ${info}
-
-if [ "$failed" == "1" ] ; then
-    echo "Checks failed. See `pwd`/${info} for details."
-    echo "FAILED" >> ${info}
-    exit 1
-else
-    echo "OK" >> ${info}
-    exit 0
-fi
+exit $failed
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/console/Makefile
--- a/tools/console/Makefile    Thu Sep  8 15:18:40 2005
+++ b/tools/console/Makefile    Fri Sep  9 16:30:54 2005
@@ -9,10 +9,8 @@
 INSTALL_PROG    = $(INSTALL) -m0755
 INSTALL_DIR     = $(INSTALL) -d -m0755
 
-CC       = gcc
-CFLAGS   = -Wall -Werror -g3
+CFLAGS  += -Wall -Werror -g3
 
-CFLAGS  += -I $(XEN_XCS)
 CFLAGS  += -I $(XEN_LIBXC)
 CFLAGS  += -I $(XEN_XENSTORE)
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/console/client/main.c
--- a/tools/console/client/main.c       Thu Sep  8 15:18:40 2005
+++ b/tools/console/client/main.c       Fri Sep  9 16:30:54 2005
@@ -170,12 +170,12 @@
                { 0 },
 
        };
-       char *str_pty;
-       char path[1024];
+       char *str_pty, *path;
        int spty;
        unsigned int len = 0;
        struct xs_handle *xs;
        char *end;
+       time_t now;
 
        while((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
                switch(ch) {
@@ -213,20 +213,51 @@
        
        signal(SIGTERM, sighandler);
 
-       snprintf(path, sizeof(path), "/console/%d/tty", domid);
+       path = xs_get_domain_path(xs, domid);
+       if (path == NULL)
+               err(errno, "xs_get_domain_path()");
+       path = realloc(path, strlen(path) + strlen("/console/tty") + 1);
+       if (path == NULL)
+               err(ENOMEM, "realloc");
+       strcat(path, "/console/tty");
        str_pty = xs_read(xs, path, &len);
+
        /* FIXME consoled currently does not assume domain-0 doesn't have a
           console which is good when we break domain-0 up.  To keep us
           user friendly, we'll bail out here since no data will ever show
           up on domain-0. */
-       if (domid == 0 || str_pty == NULL) {
+       if (domid == 0) {
                err(errno, "Could not read tty from store");
        }
+
+       /* Wait a little bit for tty to appear.  There is a race
+          condition that occurs after xend creates a domain.  This
+          code might be running before consoled has noticed the new
+          domain and setup a pty for it.
+
+          A xenstore watch would slightly improve responsiveness but
+          a timeout would still be needed since we don't want to
+          block forever if given an invalid domain or worse yet, a
+          domain that someone else has connected to. */
+
+       now = time(0);
+       while (str_pty == NULL && (now + 5) > time(0)) {
+               struct timeval tv = { 0, 500 };
+               select(0, NULL, NULL, NULL, &tv); /* pause briefly */
+
+               str_pty = xs_read(xs, path, &len);
+       }
+
+       if (str_pty == NULL) {
+               err(errno, "Could not read tty from store");
+       }
+
        spty = open(str_pty, O_RDWR | O_NOCTTY);
        if (spty == -1) {
                err(errno, "Could not open tty `%s'", str_pty);
        }
        free(str_pty);
+       free(path);
 
        init_term(STDIN_FILENO, &attr);
        console_loop(xc_handle, domid, spty);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/console/daemon/io.c
--- a/tools/console/daemon/io.c Thu Sep  8 15:18:40 2005
+++ b/tools/console/daemon/io.c Fri Sep  9 16:30:54 2005
@@ -26,7 +26,6 @@
 #include "xenctrl.h"
 #include "xs.h"
 #include "xen/io/domain_controller.h"
-#include "xcs_proto.h"
 
 #include <malloc.h>
 #include <stdlib.h>
@@ -36,9 +35,15 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <termios.h>
+#include <stdarg.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
 
 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+/* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
+#define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
 
 struct buffer
 {
@@ -48,41 +53,6 @@
        size_t max_capacity;
 };
 
-static void buffer_append(struct buffer *buffer, const void *data, size_t size)
-{
-       if ((buffer->capacity - buffer->size) < size) {
-               buffer->capacity += (size + 1024);
-               buffer->data = realloc(buffer->data, buffer->capacity);
-               if (buffer->data == NULL) {
-                       dolog(LOG_ERR, "Memory allocation failed");
-                       exit(ENOMEM);
-               }
-       }
-
-       memcpy(buffer->data + buffer->size, data, size);
-       buffer->size += size;
-
-       if (buffer->max_capacity &&
-           buffer->size > buffer->max_capacity) {
-               memmove(buffer->data + (buffer->size - buffer->max_capacity),
-                       buffer->data, buffer->max_capacity);
-               buffer->data = realloc(buffer->data, buffer->max_capacity);
-               buffer->capacity = buffer->max_capacity;
-       }
-}
-
-static bool buffer_empty(struct buffer *buffer)
-{
-       return buffer->size == 0;
-}
-
-static void buffer_advance(struct buffer *buffer, size_t size)
-{
-       size = MIN(size, buffer->size);
-       memmove(buffer->data, buffer + size, buffer->size - size);
-       buffer->size -= size;
-}
-
 struct domain
 {
        int domid;
@@ -90,9 +60,74 @@
        bool is_dead;
        struct buffer buffer;
        struct domain *next;
+       char *conspath;
+       int ring_ref;
+       int local_port;
+       char *page;
+       int evtchn_fd;
 };
 
 static struct domain *dom_head;
+
+struct ring_head
+{
+       u32 cons;
+       u32 prod;
+       char buf[0];
+} __attribute__((packed));
+
+#define PAGE_SIZE (getpagesize())
+#define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head))
+#define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE)
+#define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE)
+#define XENCONS_SPACE(ring) (XENCONS_RING_SIZE - ((ring)->prod - (ring)->cons))
+
+static void buffer_append(struct domain *dom)
+{
+       struct buffer *buffer = &dom->buffer;
+       struct ring_head *ring = (struct ring_head *)dom->page;
+       size_t size;
+
+       while ((size = ring->prod - ring->cons) != 0) {
+               if ((buffer->capacity - buffer->size) < size) {
+                       buffer->capacity += (size + 1024);
+                       buffer->data = realloc(buffer->data, buffer->capacity);
+                       if (buffer->data == NULL) {
+                               dolog(LOG_ERR, "Memory allocation failed");
+                               exit(ENOMEM);
+                       }
+               }
+
+               while (ring->cons < ring->prod) {
+                       buffer->data[buffer->size] =
+                               ring->buf[XENCONS_IDX(ring->cons)];
+                       buffer->size++;
+                       ring->cons++;
+               }
+
+               if (buffer->max_capacity &&
+                   buffer->size > buffer->max_capacity) {
+                       memmove(buffer->data + (buffer->size -
+                                               buffer->max_capacity),
+                               buffer->data, buffer->max_capacity);
+                       buffer->data = realloc(buffer->data,
+                                              buffer->max_capacity);
+                       buffer->capacity = buffer->max_capacity;
+               }
+       }
+}
+
+static bool buffer_empty(struct buffer *buffer)
+{
+       return buffer->size == 0;
+}
+
+static void buffer_advance(struct buffer *buffer, size_t size)
+{
+       size = MIN(size, buffer->size);
+       memmove(buffer->data, buffer + size, buffer->size - size);
+       buffer->size -= size;
+}
 
 static bool domain_is_valid(int domid)
 {
@@ -107,8 +142,9 @@
 
 static int domain_create_tty(struct domain *dom)
 {
-       char path[1024];
+       char *path;
        int master;
+       bool success;
 
        if ((master = getpt()) == -1 ||
            grantpt(master) == -1 || unlockpt(master) == -1) {
@@ -126,27 +162,134 @@
                        tcsetattr(master, TCSAFLUSH, &term);
                }
 
-               xs_mkdir(xs, "/console");
-               snprintf(path, sizeof(path), "/console/%d", dom->domid);
-               xs_mkdir(xs, path);
-               strcat(path, "/tty");
-
-               xs_write(xs, path, slave, strlen(slave), O_CREAT);
-
-               snprintf(path, sizeof(path), "/console/%d/limit", dom->domid);
+               success = asprintf(&path, "%s/tty", dom->conspath) != -1;
+               if (!success)
+                       goto out;
+               success = xs_write(xs, path, slave, strlen(slave), O_CREAT);
+               free(path);
+               if (!success)
+                       goto out;
+
+               success = asprintf(&path, "%s/limit", dom->conspath) != -1;
+               if (!success)
+                       goto out;
                data = xs_read(xs, path, &len);
                if (data) {
                        dom->buffer.max_capacity = strtoul(data, 0, 0);
                        free(data);
                }
+               free(path);
        }
 
        return master;
+ out:
+       close(master);
+       return -1;
+}
+
+/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
+int xs_gather(struct xs_handle *xs, const char *dir, ...)
+{
+       va_list ap;
+       const char *name;
+       char *path;
+       int ret = 0;
+
+       va_start(ap, dir);
+       while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
+               const char *fmt = va_arg(ap, char *);
+               void *result = va_arg(ap, void *);
+               char *p;
+
+               asprintf(&path, "%s/%s", dir, name);
+               p = xs_read(xs, path, NULL);
+               free(path);
+               if (p == NULL) {
+                       ret = ENOENT;
+                       break;
+               }
+               if (fmt) {
+                       if (sscanf(p, fmt, result) == 0)
+                               ret = EINVAL;
+                       free(p);
+               } else
+                       *(char **)result = p;
+       }
+       va_end(ap);
+       return ret;
+}
+
+#define EVENTCHN_BIND          _IO('E', 2)
+#define EVENTCHN_UNBIND        _IO('E', 3)
+
+static int domain_create_ring(struct domain *dom)
+{
+       int err, local_port, ring_ref;
+
+       err = xs_gather(xs, dom->conspath,
+                       "ring-ref", "%u", &ring_ref,
+                       "port", "%i", &local_port,
+                       NULL);
+       if (err)
+               goto out;
+
+       if (ring_ref != dom->ring_ref) {
+               if (dom->page)
+                       munmap(dom->page, getpagesize());
+               dom->page = xc_map_foreign_range(xc, dom->domid, getpagesize(),
+                                                PROT_READ|PROT_WRITE,
+                                                (unsigned long)ring_ref);
+               if (dom->page == NULL) {
+                       err = EINVAL;
+                       goto out;
+               }
+               dom->ring_ref = ring_ref;
+       }
+
+       if (local_port != dom->local_port) {
+               dom->local_port = -1;
+               if (dom->evtchn_fd != -1)
+                       close(dom->evtchn_fd);
+               /* Opening evtchn independently for each console is a bit
+                * wastefule, but that's how the code is structured... */
+               dom->evtchn_fd = open("/dev/xen/evtchn", O_RDWR);
+               if (dom->evtchn_fd == -1) {
+                       err = errno;
+                       goto out;
+               }
+ 
+               if (ioctl(dom->evtchn_fd, EVENTCHN_BIND, local_port) == -1) {
+                       err = errno;
+                       close(dom->evtchn_fd);
+                       dom->evtchn_fd = -1;
+                       goto out;
+               }
+               dom->local_port = local_port;
+       }
+
+ out:
+       return err;
+}
+
+static bool watch_domain(struct domain *dom, bool watch)
+{
+       char domid_str[3 + MAX_STRLEN(dom->domid)];
+       bool success;
+
+       sprintf(domid_str, "dom%u", dom->domid);
+       if (watch)
+               success = xs_watch(xs, dom->conspath, domid_str);
+       else
+               success = xs_unwatch(xs, dom->conspath, domid_str);
+       if (success)
+               domain_create_ring(dom);
+       return success;
 }
 
 static struct domain *create_domain(int domid)
 {
        struct domain *dom;
+       char *s;
 
        dom = (struct domain *)malloc(sizeof(struct domain));
        if (dom == NULL) {
@@ -156,99 +299,145 @@
        }
 
        dom->domid = domid;
+
+       dom->conspath = xs_get_domain_path(xs, dom->domid);
+       if (dom->conspath == NULL)
+               goto out;
+       s = realloc(dom->conspath, strlen(dom->conspath) +
+                   strlen("/console") + 1);
+       if (s == NULL)
+               goto out;
+       dom->conspath = s;
+       strcat(dom->conspath, "/console");
+
        dom->tty_fd = domain_create_tty(dom);
        dom->is_dead = false;
        dom->buffer.data = 0;
        dom->buffer.size = 0;
        dom->buffer.capacity = 0;
        dom->buffer.max_capacity = 0;
-       dom->next = 0;
+       dom->next = NULL;
+
+       dom->ring_ref = -1;
+       dom->local_port = -1;
+       dom->page = NULL;
+       dom->evtchn_fd = -1;
+
+       if (!watch_domain(dom, true))
+               goto out;
+
+       dom->next = dom_head;
+       dom_head = dom;
 
        dolog(LOG_DEBUG, "New domain %d", domid);
 
        return dom;
+ out:
+       if (dom->conspath)
+               free(dom->conspath);
+       free(dom);
+       return NULL;
 }
 
 static struct domain *lookup_domain(int domid)
 {
+       struct domain *dom;
+
+       for (dom = dom_head; dom; dom = dom->next)
+               if (dom->domid == domid)
+                       return dom;
+       return NULL;
+}
+
+static void remove_domain(struct domain *dom)
+{
        struct domain **pp;
 
+       dolog(LOG_DEBUG, "Removing domain-%d", dom->domid);
+
        for (pp = &dom_head; *pp; pp = &(*pp)->next) {
-               struct domain *dom = *pp;
-
-               if (dom->domid == domid) {
-                       return dom;
-               } else if (dom->domid > domid) {
-                       *pp = create_domain(domid);
-                       (*pp)->next = dom;
-                       return *pp;
-               }
-       }
-
-       *pp = create_domain(domid);
-       return *pp;
-}
-
-static void remove_domain(struct domain *dom)
-{
-       struct domain **pp;
-
-       dolog(LOG_DEBUG, "Removing domain-%d", dom->domid);
-
-       for (pp = &dom_head; *pp; pp = &(*pp)->next) {
-               struct domain *d = *pp;
-
-               if (dom->domid == d->domid) {
-                       *pp = d->next;
-                       if (d->buffer.data) {
-                               free(d->buffer.data);
-                       }
-                       free(d);
+               if (dom == *pp) {
+                       *pp = dom->next;
+                       free(dom);
                        break;
                }
        }
 }
 
-static void remove_dead_domains(struct domain *dom)
-{
-       if (dom == NULL) return;
-       remove_dead_domains(dom->next);
-
-       if (dom->is_dead) {
-               remove_domain(dom);
+static void cleanup_domain(struct domain *d)
+{
+       if (!buffer_empty(&d->buffer))
+               return;
+
+       if (d->buffer.data)
+               free(d->buffer.data);
+       d->buffer.data = NULL;
+       if (d->tty_fd != -1)
+               close(d->tty_fd);
+       d->tty_fd = -1;
+       remove_domain(d);
+}
+
+static void shutdown_domain(struct domain *d)
+{
+       d->is_dead = true;
+       watch_domain(d, false);
+       if (d->page)
+               munmap(d->page, getpagesize());
+       d->page = NULL;
+       if (d->evtchn_fd != -1)
+               close(d->evtchn_fd);
+       d->evtchn_fd = -1;
+       cleanup_domain(d);
+}
+
+void enum_domains(void)
+{
+       int domid = 1;
+       xc_dominfo_t dominfo;
+       struct domain *dom;
+
+       while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
+               dom = lookup_domain(dominfo.domid);
+               if (dominfo.dying || dominfo.crashed || dominfo.shutdown) {
+                       if (dom)
+                               shutdown_domain(dom);
+               } else {
+                       if (dom == NULL)
+                               create_domain(dominfo.domid);
+               }
+               domid = dominfo.domid + 1;
        }
 }
 
 static void handle_tty_read(struct domain *dom)
 {
        ssize_t len;
-       xcs_msg_t msg;
-
-       msg.type = XCS_REQUEST;
-       msg.u.control.remote_dom = dom->domid;
-       msg.u.control.msg.type = CMSG_CONSOLE;
-       msg.u.control.msg.subtype = CMSG_CONSOLE_DATA;
-       msg.u.control.msg.id = 1;
-
-       len = read(dom->tty_fd, msg.u.control.msg.msg, 60);
+       char msg[80];
+       struct ring_head *inring =
+               (struct ring_head *)(dom->page + PAGE_SIZE/2);
+       int i;
+
+       len = read(dom->tty_fd, msg, MIN(XENCONS_SPACE(inring), sizeof(msg)));
        if (len < 1) {
                close(dom->tty_fd);
+               dom->tty_fd = -1;
 
                if (domain_is_valid(dom->domid)) {
                        dom->tty_fd = domain_create_tty(dom);
                } else {
-                       dom->is_dead = true;
+                       shutdown_domain(dom);
                }
        } else if (domain_is_valid(dom->domid)) {
-               msg.u.control.msg.length = len;
-
-               if (!write_sync(xcs_data_fd, &msg, sizeof(msg))) {
-                       dolog(LOG_ERR, "Write to xcs failed: %m");
-                       exit(1);
-               }
+               for (i = 0; i < len; i++) {
+                       inring->buf[XENCONS_IDX(inring->prod)] = msg[i];
+                       inring->prod++;
+               }
+               xc_evtchn_send(xc, dom->local_port);
        } else {
                close(dom->tty_fd);
-               dom->is_dead = true;
+               dom->tty_fd = -1;
+               shutdown_domain(dom);
        }
 }
 
@@ -259,104 +448,105 @@
        len = write(dom->tty_fd, dom->buffer.data, dom->buffer.size);
        if (len < 1) {
                close(dom->tty_fd);
+               dom->tty_fd = -1;
 
                if (domain_is_valid(dom->domid)) {
                        dom->tty_fd = domain_create_tty(dom);
                } else {
-                       dom->is_dead = true;
+                       shutdown_domain(dom);
                }
        } else {
                buffer_advance(&dom->buffer, len);
        }
 }
 
-static void handle_xcs_msg(int fd)
-{
-       xcs_msg_t msg;
-
-       if (!read_sync(fd, &msg, sizeof(msg))) {
-               dolog(LOG_ERR, "read from xcs failed! %m");
-               exit(1);
-       } else if (msg.type == XCS_REQUEST) {
-               struct domain *dom;
-
-               dom = lookup_domain(msg.u.control.remote_dom);
-               buffer_append(&dom->buffer,
-                             msg.u.control.msg.msg,
-                             msg.u.control.msg.length);
-       }
-}
-
-static void enum_domains(void)
-{
-       int domid = 0;
-       xc_dominfo_t dominfo;
-
-       while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
-               lookup_domain(dominfo.domid);
-               domid = dominfo.domid + 1;
-       }
+static void handle_ring_read(struct domain *dom)
+{
+       u16 v;
+
+       if (!read_sync(dom->evtchn_fd, &v, sizeof(v)))
+               return;
+
+       buffer_append(dom);
+
+       (void)write_sync(dom->evtchn_fd, &v, sizeof(v));
+}
+
+static void handle_xs(int fd)
+{
+       char **vec;
+       int domid;
+       struct domain *dom;
+
+       vec = xs_read_watch(xs);
+       if (!vec)
+               return;
+
+       if (!strcmp(vec[1], "domlist"))
+               enum_domains();
+       else if (sscanf(vec[1], "dom%u", &domid) == 1) {
+               dom = lookup_domain(domid);
+               if (dom->is_dead == false)
+                       domain_create_ring(dom);
+       }
+
+       xs_acknowledge_watch(xs, vec[1]);
+       free(vec);
 }
 
 void handle_io(void)
 {
        fd_set readfds, writefds;
        int ret;
-       int max_fd = -1;
-       int num_of_writes = 0;
 
        do {
-               struct domain *d;
-               struct timeval tv = { 1, 0 };
+               struct domain *d, *n;
+               struct timeval tv = { 100, 0 };
+               int max_fd = -1;
 
                FD_ZERO(&readfds);
                FD_ZERO(&writefds);
 
-               FD_SET(xcs_data_fd, &readfds);
-               max_fd = MAX(xcs_data_fd, max_fd);
+               FD_SET(xs_fileno(xs), &readfds);
+               max_fd = MAX(xs_fileno(xs), max_fd);
 
                for (d = dom_head; d; d = d->next) {
+                       if (d->evtchn_fd != -1) {
+                               FD_SET(d->evtchn_fd, &readfds);
+                               max_fd = MAX(d->evtchn_fd, max_fd);
+                       }
+
                        if (d->tty_fd != -1) {
-                               FD_SET(d->tty_fd, &readfds);
+                               if (!d->is_dead)
+                                       FD_SET(d->tty_fd, &readfds);
+
+                               if (!buffer_empty(&d->buffer))
+                                       FD_SET(d->tty_fd, &writefds);
+                               max_fd = MAX(d->tty_fd, max_fd);
                        }
-
-                       if (d->tty_fd != -1 && !buffer_empty(&d->buffer)) {
-                               FD_SET(d->tty_fd, &writefds);
+               }
+
+               ret = select(max_fd + 1, &readfds, &writefds, 0, &tv);
+
+               if (FD_ISSET(xs_fileno(xs), &readfds))
+                       handle_xs(xs_fileno(xs));
+
+               for (d = dom_head; d; d = n) {
+                       n = d->next;
+                       if (d->evtchn_fd != -1 &&
+                           FD_ISSET(d->evtchn_fd, &readfds))
+                               handle_ring_read(d);
+
+                       if (d->tty_fd != -1) {
+                               if (FD_ISSET(d->tty_fd, &readfds))
+                                       handle_tty_read(d);
+
+                               if (FD_ISSET(d->tty_fd, &writefds))
+                                       handle_tty_write(d);
+
+                               if (d->is_dead)
+                                       cleanup_domain(d);
                        }
-
-                       max_fd = MAX(d->tty_fd, max_fd);
-               }
-
-               ret = select(max_fd + 1, &readfds, &writefds, 0, &tv);
-               if (tv.tv_sec == 1 && (++num_of_writes % 100) == 0) {
-#if 0
-                       /* FIXME */
-                       /* This is a nasty hack.  xcs does not handle the
-                          control channels filling up well at all.  We'll
-                          throttle ourselves here since we do proper
-                          queueing to give the domains a shot at pulling out
-                          the data.  Fixing xcs is not worth it as it's
-                          going away */
-                       tv.tv_usec = 1000;
-                       select(0, 0, 0, 0, &tv);
-#endif
-               }
-               enum_domains();
-
-               if (FD_ISSET(xcs_data_fd, &readfds)) {
-                       handle_xcs_msg(xcs_data_fd);
-               }
-
-               for (d = dom_head; d; d = d->next) {
-                       if (!d->is_dead && FD_ISSET(d->tty_fd, &readfds)) {
-                               handle_tty_read(d);
-                       }
-
-                       if (!d->is_dead && FD_ISSET(d->tty_fd, &writefds)) {
-                               handle_tty_write(d);
-                       }
-               }
-
-               remove_dead_domains(dom_head);
+               }
        } while (ret > -1);
 }
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/console/daemon/io.h
--- a/tools/console/daemon/io.h Thu Sep  8 15:18:40 2005
+++ b/tools/console/daemon/io.h Fri Sep  9 16:30:54 2005
@@ -21,6 +21,7 @@
 #ifndef CONSOLED_IO_H
 #define CONSOLED_IO_H
 
+void enum_domains(void);
 void handle_io(void);
 
 #endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/console/daemon/main.c
--- a/tools/console/daemon/main.c       Thu Sep  8 15:18:40 2005
+++ b/tools/console/daemon/main.c       Fri Sep  9 16:30:54 2005
@@ -26,8 +26,6 @@
 #include <sys/types.h>
 
 #include "xenctrl.h"
-#include "xen/io/domain_controller.h"
-#include "xcs_proto.h"
 
 #include "utils.h"
 #include "io.h"
@@ -83,7 +81,10 @@
                daemonize("/var/run/xenconsoled.pid");
        }
 
-       xen_setup();
+       if (!xen_setup())
+               exit(1);
+
+       enum_domains();
 
        handle_io();
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/console/daemon/utils.c
--- a/tools/console/daemon/utils.c      Thu Sep  8 15:18:40 2005
+++ b/tools/console/daemon/utils.c      Fri Sep  9 16:30:54 2005
@@ -35,15 +35,11 @@
 
 #include "xenctrl.h"
 #include "xen/io/domain_controller.h"
-#include "xcs_proto.h"
 
 #include "utils.h"
 
 struct xs_handle *xs;
 int xc;
-
-int xcs_ctrl_fd = -1;
-int xcs_data_fd = -1;
 
 bool _read_write_sync(int fd, void *data, size_t size, bool do_read)
 {
@@ -69,32 +65,6 @@
        }
 
        return true;
-}
-
-static int open_domain_socket(const char *path)
-{
-       struct sockaddr_un addr;
-       int sock;
-       size_t addr_len;
-
-       if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
-               goto out;
-       }
-
-       addr.sun_family = AF_UNIX;
-       strcpy(addr.sun_path, path);
-       addr_len = sizeof(addr.sun_family) + strlen(XCS_SUN_PATH) + 1;
-
-       if (connect(sock, (struct sockaddr *)&addr, addr_len) == -1) {
-               goto out_close_sock;
-       }
-
-       return sock;
-
- out_close_sock:
-       close(sock);
- out:
-       return -1;
 }
 
 static void child_exit(int sig)
@@ -155,34 +125,8 @@
        signal(SIGTTIN, SIG_IGN);
 }
 
-/* synchronized send/recv strictly for setting up xcs */
-/* always use asychronize callbacks any other time */
-static bool xcs_send_recv(int fd, xcs_msg_t *msg)
-{
-       bool ret = false;
-
-       if (!write_sync(fd, msg, sizeof(*msg))) {
-               dolog(LOG_ERR, "Write failed at %s:%s():L%d?  Possible bug.",
-                      __FILE__, __FUNCTION__, __LINE__);
-               goto out;
-       }
-
-       if (!read_sync(fd, msg, sizeof(*msg))) {
-               dolog(LOG_ERR, "Read failed at %s:%s():L%d?  Possible bug.",
-                      __FILE__, __FUNCTION__, __LINE__);
-               goto out;
-       }
-
-       ret = true;
-
- out:
-       return ret;
-}
-
 bool xen_setup(void)
 {
-       int sock;
-       xcs_msg_t msg;
        
        xs = xs_daemon_open();
        if (xs == NULL) {
@@ -197,57 +141,23 @@
                goto out;
        }
 
-       sock = open_domain_socket(XCS_SUN_PATH);
-       if (sock == -1) {
-               dolog(LOG_ERR, "Failed to contact xcs (%m).  Is it running?");
-               goto out_close_store;
+       if (!xs_watch(xs, "@introduceDomain", "domlist")) {
+               dolog(LOG_ERR, "xenstore watch on @introduceDomain fails.");
+               goto out;
        }
 
-       xcs_ctrl_fd = sock;
-
-       sock = open_domain_socket(XCS_SUN_PATH);
-       if (sock == -1) {
-               dolog(LOG_ERR, "Failed to contact xcs (%m).  Is it running?");
-               goto out_close_ctrl;
-       }
-       
-       xcs_data_fd = sock;
-
-       memset(&msg, 0, sizeof(msg));
-       msg.type = XCS_CONNECT_CTRL;
-       if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
-               dolog(LOG_ERR, "xcs control connect failed.  Possible bug.");
-               goto out_close_data;
+       if (!xs_watch(xs, "@releaseDomain", "domlist")) {
+               dolog(LOG_ERR, "xenstore watch on @releaseDomain fails.");
+               goto out;
        }
 
-       msg.type = XCS_CONNECT_DATA;
-       if (!xcs_send_recv(xcs_data_fd, &msg) || msg.result != XCS_RSLT_OK) {
-               dolog(LOG_ERR, "xcs data connect failed.  Possible bug.");
-               goto out_close_data;
-       }
-
-       /* Since the vast majority of control messages are console messages
-          it's just easier to ignore other messages that try to bind to 
-          a specific type. */
-       msg.type = XCS_MSG_BIND;
-       msg.u.bind.port = PORT_WILDCARD;
-       msg.u.bind.type = TYPE_WILDCARD;
-       if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
-               dolog(LOG_ERR, "xcs vind failed.  Possible bug.");
-               goto out_close_data;
-       }
-       
        return true;
 
- out_close_data:
-       close(xcs_ctrl_fd);
-       xcs_data_fd = -1;
- out_close_ctrl:
-       close(xcs_ctrl_fd);
-       xcs_ctrl_fd = -1;
- out_close_store:
-       xs_daemon_close(xs);
  out:
+       if (xs)
+               xs_daemon_close(xs);
+       if (xc != -1)
+               xc_interface_close(xc);
        return false;
 }
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/console/daemon/utils.h
--- a/tools/console/daemon/utils.h      Thu Sep  8 15:18:40 2005
+++ b/tools/console/daemon/utils.h      Fri Sep  9 16:30:54 2005
@@ -33,13 +33,15 @@
 #define write_sync(fd, buffer, size) _read_write_sync(fd, buffer, size, false)
 bool _read_write_sync(int fd, void *data, size_t size, bool do_read);
 
-extern int xcs_ctrl_fd;
-extern int xcs_data_fd;
 extern struct xs_handle *xs;
 extern int xc;
 
 #if 1
-#define dolog(val, fmt, ...) syslog(val, fmt, ## __VA_ARGS__)
+#define dolog(val, fmt, ...) do {                              \
+       if ((val) == LOG_ERR)                                   \
+               fprintf(stderr, fmt "\n", ## __VA_ARGS__);      \
+       syslog(val, fmt, ## __VA_ARGS__);                       \
+} while (/* CONSTCOND */0)
 #else
 #define dolog(val, fmt, ...) fprintf(stderr, fmt "\n", ## __VA_ARGS__)
 #endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/Makefile
--- a/tools/examples/Makefile   Thu Sep  8 15:18:40 2005
+++ b/tools/examples/Makefile   Fri Sep  9 16:30:54 2005
@@ -1,3 +1,6 @@
+XEN_ROOT = ../../
+include $(XEN_ROOT)/tools/Rules.mk
+
 INSTALL                = install
 INSTALL_DIR    = $(INSTALL) -d -m0755
 INSTALL_PROG   = $(INSTALL) -m0755
@@ -24,8 +27,8 @@
 XEN_BOOT_DIR = /usr/lib/xen/boot
 XEN_BOOT = mem-map.sxp
 
-XEN_HOTPLUG_DIR = /etc/hotplug.d/xen-backend
-XEN_HOTPLUG_SCRIPTS = backend.hotplug
+XEN_HOTPLUG_DIR = /etc/hotplug
+XEN_HOTPLUG_SCRIPTS = xen-backend.agent
 
 all: 
 build:
@@ -68,7 +71,7 @@
        [ -d $(DESTDIR)$(XEN_HOTPLUG_DIR) ] || \
                $(INSTALL_DIR) $(DESTDIR)$(XEN_HOTPLUG_DIR)
        for i in $(XEN_HOTPLUG_SCRIPTS); \
-           do [ -a $(DESTDIR)$(XEN_HOTPLUG_DIR)/$$i ] || \
+           do \
            $(INSTALL_PROG) $$i $(DESTDIR)$(XEN_HOTPLUG_DIR); \
        done
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/init.d/xend
--- a/tools/examples/init.d/xend        Thu Sep  8 15:18:40 2005
+++ b/tools/examples/init.d/xend        Fri Sep  9 16:30:54 2005
@@ -11,7 +11,7 @@
        exit 0
 fi
 
-# Wait for Xend and xcs to be up
+# Wait for Xend to be up
 function await_daemons_up
 {
        i=1
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/vif-bridge
--- a/tools/examples/vif-bridge Thu Sep  8 15:18:40 2005
+++ b/tools/examples/vif-bridge Fri Sep  9 16:30:54 2005
@@ -80,7 +80,7 @@
 fi
 ifconfig ${vif} $OP
 
-if [ ${ip} ] ; then
+if [ "${ip}" ] ; then
 
     # If we've been given a list of IP networks, allow pkts with these src 
addrs.
     for addr in ${ip} ; do
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/vif-route
--- a/tools/examples/vif-route  Thu Sep  8 15:18:40 2005
+++ b/tools/examples/vif-route  Fri Sep  9 16:30:54 2005
@@ -63,7 +63,7 @@
         ;;
 esac
 
-if [ ${ip} ] ; then
+if [ "${ip}" ] ; then
 
     # If we've been given a list of IP networks, allow pkts with these src 
addrs.
     for addr in ${ip} ; do
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/xmexample.vmx
--- a/tools/examples/xmexample.vmx      Thu Sep  8 15:18:40 2005
+++ b/tools/examples/xmexample.vmx      Fri Sep  9 16:30:54 2005
@@ -73,6 +73,10 @@
 vnc=1
 
 #----------------------------------------------------------------------------
+# enable spawning vncviewer(only valid when vnc=1), default = 1
+vncviewer=1
+
+#----------------------------------------------------------------------------
 # no graphics, use serial port
 #nographic=0
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/xmexample1
--- a/tools/examples/xmexample1 Thu Sep  8 15:18:40 2005
+++ b/tools/examples/xmexample1 Fri Sep  9 16:30:54 2005
@@ -48,6 +48,20 @@
 disk = [ 'phy:hda1,hda1,w' ]
 
 #----------------------------------------------------------------------------
+# Define to which TPM instance the user domain should communicate.
+# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM'
+# where INSTANCE indicates the instance number of the TPM the VM
+# should be talking to and DOM provides the domain where the backend
+# is located.
+# Note that no two virtual machines should try to connect to the same
+# TPM instance. The handling of all TPM instances does require
+# some management effort in so far that VM configration files (and thus
+# a VM) should be associated with a TPM instance throughout the lifetime
+# of the VM / VM configuration file. The instance number must be
+# greater or equal to 1.
+#vtpm = [ 'instance=1,backend=0' ]
+
+#----------------------------------------------------------------------------
 # Set the kernel command line for the new domain.
 # You only need to define the IP parameters and hostname if the domain's
 # IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/xmexample2
--- a/tools/examples/xmexample2 Thu Sep  8 15:18:40 2005
+++ b/tools/examples/xmexample2 Fri Sep  9 16:30:54 2005
@@ -84,6 +84,20 @@
          'phy:sda6,sda6,r' ]
 
 #----------------------------------------------------------------------------
+# Define to which TPM instance the user domain should communicate.
+# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM'
+# where INSTANCE indicates the instance number of the TPM the VM
+# should be talking to and DOM provides the domain where the backend
+# is located.
+# Note that no two virtual machines should try to connect to the same
+# TPM instance. The handling of all TPM instances does require
+# some management effort in so far that VM configration files (and thus
+# a VM) should be associated with a TPM instance throughout the lifetime
+# of the VM / VM configuration file. The instance number must be
+# greater or equal to 1.
+#vtpm = ['instance=%d,backend=0' % (vmid) ]
+
+#----------------------------------------------------------------------------
 # Set the kernel command line for the new domain.
 # You only need to define the IP parameters and hostname if the domain's
 # IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/xmexample3
--- a/tools/examples/xmexample3 Thu Sep  8 15:18:40 2005
+++ b/tools/examples/xmexample3 Fri Sep  9 16:30:54 2005
@@ -80,6 +80,20 @@
 disk = [ 'phy:hda%d,hda1,w' % (vmid)]
 
 #----------------------------------------------------------------------------
+# Define to which TPM instance the user domain should communicate.
+# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM'
+# where INSTANCE indicates the instance number of the TPM the VM
+# should be talking to and DOM provides the domain where the backend
+# is located.
+# Note that no two virtual machines should try to connect to the same
+# TPM instance. The handling of all TPM instances does require
+# some management effort in so far that VM configration files (and thus
+# a VM) should be associated with a TPM instance throughout the lifetime
+# of the VM / VM configuration file. The instance number must be
+# greater or equal to 1.
+#vtpm = ['instance=%d,backend=0' % (vmid) ]
+
+#----------------------------------------------------------------------------
 # Set the kernel command line for the new domain.
 # You only need to define the IP parameters and hostname if the domain's
 # IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c  Thu Sep  8 15:18:40 2005
+++ b/tools/firmware/rombios/rombios.c  Fri Sep  9 16:30:54 2005
@@ -31,7 +31,7 @@
 
 // Xen full virtualization does not handle unaligned IO with page crossing.
 // Disable 32-bit PIO as a workaround.
-#define NO_PIO32
+#undef NO_PIO32
 
 
 // ROM BIOS compatability entry points:
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/firmware/vmxassist/Makefile
--- a/tools/firmware/vmxassist/Makefile Thu Sep  8 15:18:40 2005
+++ b/tools/firmware/vmxassist/Makefile Fri Sep  9 16:30:54 2005
@@ -24,7 +24,7 @@
 # The emulator code lives in ROM space
 TEXTADDR=0x000D0000
 
-DEFINES=-DDEBUG -DENABLE_VME -DTEXTADDR=${TEXTADDR}
+DEFINES=-DDEBUG -DTEXTADDR=${TEXTADDR}
 XENINC=-I$(XEN_ROOT)/xen/include -I$(XEN_ROOT)/tools/libxc
 #DEFINES=-DDEBUG -DTEST -DTEXTADDR=${TEXTADDR}
 #XENINC=-I/home/leendert/xen/xeno-unstable.bk/xen/include
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/firmware/vmxassist/setup.c
--- a/tools/firmware/vmxassist/setup.c  Thu Sep  8 15:18:40 2005
+++ b/tools/firmware/vmxassist/setup.c  Fri Sep  9 16:30:54 2005
@@ -353,7 +353,7 @@
 #endif
        setup_gdt();
        setup_idt();
-#ifdef ENABLE_VME
+#ifndef        TEST
        set_cr4(get_cr4() | CR4_VME); 
 #endif
        setup_ctx();
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/firmware/vmxassist/vm86.c
--- a/tools/firmware/vmxassist/vm86.c   Thu Sep  8 15:18:40 2005
+++ b/tools/firmware/vmxassist/vm86.c   Fri Sep  9 16:30:54 2005
@@ -465,8 +465,7 @@
  * Emulate a segment load in protected mode
  */
 int
-load_seg(unsigned long sel, unsigned long *base, unsigned long *limit,
-                                               union vmcs_arbytes *arbytes)
+load_seg(unsigned long sel, u32 *base, u32 *limit, union vmcs_arbytes *arbytes)
 {
        unsigned long long entry;
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/firmware/vmxassist/vmxloader.c
--- a/tools/firmware/vmxassist/vmxloader.c      Thu Sep  8 15:18:40 2005
+++ b/tools/firmware/vmxassist/vmxloader.c      Fri Sep  9 16:30:54 2005
@@ -110,8 +110,8 @@
        }
 #ifdef _ACPI_
        puts("Loading ACPI ...\n");
-    if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000 ){
-        /* make sure acpi table does not overlap rombios
+       if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000 ){
+               /* make sure acpi table does not overlap rombios
                 * currently acpi less than 8K will be OK.
                 */
                 memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi));
@@ -122,5 +122,6 @@
        memcpy((void *)TEXTADDR, vmxassist, sizeof(vmxassist));
        puts("Go ...\n");
        ((void (*)())TEXTADDR)();
+       return 0;
 }
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/cpu-all.h
--- a/tools/ioemu/cpu-all.h     Thu Sep  8 15:18:40 2005
+++ b/tools/ioemu/cpu-all.h     Fri Sep  9 16:30:54 2005
@@ -672,6 +672,8 @@
 int cpu_memory_rw_debug(CPUState *env, target_ulong addr, 
                         uint8_t *buf, int len, int is_write);
 
+#define VGA_DIRTY_FLAG 0x01
+
 /* read dirty bit (return 0 or 1) */
 static inline int cpu_physical_memory_is_dirty(target_ulong addr)
 {
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/exec.c
--- a/tools/ioemu/exec.c        Thu Sep  8 15:18:40 2005
+++ b/tools/ioemu/exec.c        Fri Sep  9 16:30:54 2005
@@ -142,6 +142,10 @@
 #else
         setvbuf(logfile, NULL, _IOLBF, 0);
 #endif
+/*
+       stdout = logfile;
+       stderr = logfile;
+*/
     }
 }
 
@@ -386,9 +390,6 @@
                     io_mem_write[io_index][1](io_mem_opaque[io_index], addr, 
val);
                     l = 2;
                 } else {
-                    if (l!=1){
-                        fprintf(logfile, "ERROR 8 bit mmio\n");
-                    }
                     /* 8 bit access */
                     val = ldub_raw(buf);
                     io_mem_write[io_index][0](io_mem_opaque[io_index], addr, 
val);
@@ -461,4 +462,14 @@
 
 void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end)
 {
-}
+       uint8_t *p;
+       int len;
+
+       if ((len = (end - start)) <= 0)
+               return;
+       p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
+       len = len >> TARGET_PAGE_BITS;
+       while (len > 0)
+               p[--len] &= ~VGA_DIRTY_FLAG;
+       return;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c       Thu Sep  8 15:18:40 2005
+++ b/tools/ioemu/hw/pc.c       Fri Sep  9 16:30:54 2005
@@ -540,7 +540,10 @@
 
     if (pci_enabled) {
         for(i = 0; i < nb_nics; i++) {
-            pci_ne2000_init(pci_bus, &nd_table[i]);
+            if (nic_pcnet)
+                pci_pcnet_init(pci_bus, &nd_table[i]);
+            else
+                pci_ne2000_init(pci_bus, &nd_table[i]); 
         }
         pci_piix3_ide_init(pci_bus, bs_table);
 #ifdef APIC_SUPPORT
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/hw/vga.c
--- a/tools/ioemu/hw/vga.c      Thu Sep  8 15:18:40 2005
+++ b/tools/ioemu/hw/vga.c      Fri Sep  9 16:30:54 2005
@@ -1620,7 +1620,6 @@
 static void vga_save(QEMUFile *f, void *opaque)
 {
     VGAState *s = opaque;
-    int i;
 
     qemu_put_be32s(f, &s->latch);
     qemu_put_8s(f, &s->sr_index);
@@ -1661,7 +1660,7 @@
 static int vga_load(QEMUFile *f, void *opaque, int version_id)
 {
     VGAState *s = opaque;
-    int is_vbe, i;
+    int is_vbe;
 
     if (version_id != 1)
         return -EINVAL;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/target-i386-dm/Makefile
--- a/tools/ioemu/target-i386-dm/Makefile       Thu Sep  8 15:18:40 2005
+++ b/tools/ioemu/target-i386-dm/Makefile       Fri Sep  9 16:30:54 2005
@@ -272,7 +272,7 @@
 # Hardware support
 VL_OBJS+= ide.o ne2000.o pckbd.o vga.o dma.o
 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o port-e9.o
-VL_OBJS+= cirrus_vga.o
+VL_OBJS+= cirrus_vga.o pcnet.o
 
 ifeq ($(TARGET_ARCH), ppc)
 VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c      Thu Sep  8 15:18:40 2005
+++ b/tools/ioemu/target-i386-dm/helper2.c      Fri Sep  9 16:30:54 2005
@@ -169,133 +169,217 @@
 unsigned long
 do_inp(CPUState *env, unsigned long addr, unsigned long size)
 {
-  switch(size) {
-      case 1:
-        return cpu_inb(env, addr);
-      case 2:
-        return cpu_inw(env, addr);
-      case 4:
-        return cpu_inl(env, addr);
-      default:
-       fprintf(logfile, "inp: bad size: %lx %lx\n", addr, size);
-        exit(-1);
-  }
+       switch(size) {
+       case 1:
+               return cpu_inb(env, addr);
+       case 2:
+               return cpu_inw(env, addr);
+       case 4:
+               return cpu_inl(env, addr);
+       default:
+               fprintf(logfile, "inp: bad size: %lx %lx\n", addr, size);
+               exit(-1);
+       }
 }
 
 void
 do_outp(CPUState *env, unsigned long addr, unsigned long size, 
         unsigned long val)
 {
-  switch(size) {
-      case 1:
-        return cpu_outb(env, addr, val);
-      case 2:
-        return cpu_outw(env, addr, val);
-      case 4:
-        return cpu_outl(env, addr, val);
-      default:
-       fprintf(logfile, "outp: bad size: %lx %lx\n", addr, size);
-        exit(-1);
-  }
+       switch(size) {
+       case 1:
+               return cpu_outb(env, addr, val);
+       case 2:
+               return cpu_outw(env, addr, val);
+       case 4:
+               return cpu_outl(env, addr, val);
+       default:
+               fprintf(logfile, "outp: bad size: %lx %lx\n", addr, size);
+               exit(-1);
+       }
 }
 
 extern void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 
                                    int len, int is_write);
 
 static inline void
-read_physical(target_phys_addr_t addr, unsigned long size, void *val)
-{
-        return cpu_physical_memory_rw(addr, val, size, 0);
+read_physical(u64 addr, unsigned long size, void *val)
+{
+        return cpu_physical_memory_rw((target_phys_addr_t)addr, val, size, 0);
 }
 
 static inline void
-write_physical(target_phys_addr_t addr, unsigned long size, void *val)
-{
-        return cpu_physical_memory_rw(addr, val, size, 1);
-}
-
-//send the ioreq to device model
-void cpu_dispatch_ioreq(CPUState *env, ioreq_t *req)
-{
-       int i;
-       int sign;
-
-       sign = (req->df) ? -1 : 1;
-
-       if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) {
-               if (req->size != 4) {
-                       // Bochs expects higher bits to be 0
-                       req->u.data &= (1UL << (8 * req->size))-1;
-               }
-       }
-
-       if (req->port_mm == 0){//port io
-               if(req->dir == IOREQ_READ){//read
-                       if (!req->pdata_valid) {
-                               req->u.data = do_inp(env, req->addr, req->size);
-                       } else {
-                               unsigned long tmp; 
-
-                               for (i = 0; i < req->count; i++) {
-                                       tmp = do_inp(env, req->addr, req->size);
-                                       
write_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), 
-                                                      req->size, &tmp);
-                               }
-                       }
-               } else if(req->dir == IOREQ_WRITE) {
-                       if (!req->pdata_valid) {
-                               do_outp(env, req->addr, req->size, req->u.data);
-                       } else {
-                               for (i = 0; i < req->count; i++) {
-                                       unsigned long tmp;
-
-                                       
read_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), 
req->size, 
-                                                     &tmp);
-                                       do_outp(env, req->addr, req->size, tmp);
-                               }
-                       }
-                       
-               }
-       } else if (req->port_mm == 1){//memory map io
+write_physical(u64 addr, unsigned long size, void *val)
+{
+        return cpu_physical_memory_rw((target_phys_addr_t)addr, val, size, 1);
+}
+
+void
+cpu_ioreq_pio(CPUState *env, ioreq_t *req)
+{
+       int i, sign;
+
+       sign = req->df ? -1 : 1;
+
+       if (req->dir == IOREQ_READ) {
                if (!req->pdata_valid) {
-                       //handle stos
-                       if(req->dir == IOREQ_READ) { //read
-                               for (i = 0; i < req->count; i++) {
-                                       
read_physical((target_phys_addr_t)req->addr + (sign * i * req->size), 
req->size, &req->u.data);
-                               }
-                       } else if(req->dir == IOREQ_WRITE) { //write
-                               for (i = 0; i < req->count; i++) {
-                                       
write_physical((target_phys_addr_t)req->addr + (sign * i * req->size), 
req->size, &req->u.data);
-                               }
-                       }
+                       req->u.data = do_inp(env, req->addr, req->size);
                } else {
-                       //handle movs
-                       unsigned long tmp;
-                       if (req->dir == IOREQ_READ) {
-                               for (i = 0; i < req->count; i++) {
-                                       
read_physical((target_phys_addr_t)req->addr + (sign * i * req->size), 
req->size, &tmp);
-                                       
write_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), 
req->size, &tmp);
-                               }
-                       } else if (req->dir == IOREQ_WRITE) {
-                               for (i = 0; i < req->count; i++) {
-                                       
read_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), 
req->size, &tmp);
-                                       
write_physical((target_phys_addr_t)req->addr + (sign * i * req->size), 
req->size, &tmp);
-                               }
-                       }
-               }
-       }
-        /* No state change if state = STATE_IORESP_HOOK */
-        if (req->state == STATE_IOREQ_INPROCESS)
-                req->state = STATE_IORESP_READY;
-       env->send_event = 1;
+                       unsigned long tmp; 
+
+                       for (i = 0; i < req->count; i++) {
+                               tmp = do_inp(env, req->addr, req->size);
+                               write_physical((target_phys_addr_t) req->u.pdata
+                                               + (sign * i * req->size), 
+                                       req->size, &tmp);
+                       }
+               }
+       } else if (req->dir == IOREQ_WRITE) {
+               if (!req->pdata_valid) {
+                       do_outp(env, req->addr, req->size, req->u.data);
+               } else {
+                       for (i = 0; i < req->count; i++) {
+                               unsigned long tmp;
+
+                               read_physical((target_phys_addr_t) req->u.pdata
+                                               + (sign * i * req->size),
+                                       req->size, &tmp);
+                               do_outp(env, req->addr, req->size, tmp);
+                       }
+               }
+       }
+}
+
+void
+cpu_ioreq_move(CPUState *env, ioreq_t *req)
+{
+       int i, sign;
+
+       sign = req->df ? -1 : 1;
+
+       if (!req->pdata_valid) {
+               if (req->dir == IOREQ_READ) {
+                       for (i = 0; i < req->count; i++) {
+                               read_physical(req->addr
+                                               + (sign * i * req->size),
+                                       req->size, &req->u.data);
+                       }
+               } else if (req->dir == IOREQ_WRITE) {
+                       for (i = 0; i < req->count; i++) {
+                               write_physical(req->addr
+                                               + (sign * i * req->size),
+                                       req->size, &req->u.data);
+                       }
+               }
+       } else {
+               unsigned long tmp;
+
+               if (req->dir == IOREQ_READ) {
+                       for (i = 0; i < req->count; i++) {
+                               read_physical(req->addr
+                                               + (sign * i * req->size),
+                                       req->size, &tmp);
+                               write_physical((target_phys_addr_t )req->u.pdata
+                                               + (sign * i * req->size),
+                                       req->size, &tmp);
+                       }
+               } else if (req->dir == IOREQ_WRITE) {
+                       for (i = 0; i < req->count; i++) {
+                               read_physical((target_phys_addr_t) req->u.pdata
+                                               + (sign * i * req->size),
+                                       req->size, &tmp);
+                               write_physical(req->addr
+                                               + (sign * i * req->size),
+                                       req->size, &tmp);
+                       }
+               }
+       }
+}
+
+void
+cpu_ioreq_and(CPUState *env, ioreq_t *req)
+{
+       unsigned long tmp1, tmp2;
+
+       if (req->pdata_valid != 0)
+               hw_error("expected scalar value");
+
+       read_physical(req->addr, req->size, &tmp1);
+       if (req->dir == IOREQ_WRITE) {
+               tmp2 = tmp1 & (unsigned long) req->u.data;
+               write_physical(req->addr, req->size, &tmp2);
+       }
+       req->u.data = tmp1;
+}
+
+void
+cpu_ioreq_or(CPUState *env, ioreq_t *req)
+{
+       unsigned long tmp1, tmp2;
+
+       if (req->pdata_valid != 0)
+               hw_error("expected scalar value");
+
+       read_physical(req->addr, req->size, &tmp1);
+       if (req->dir == IOREQ_WRITE) {
+               tmp2 = tmp1 | (unsigned long) req->u.data;
+               write_physical(req->addr, req->size, &tmp2);
+       }
+       req->u.data = tmp1;
+}
+
+void
+cpu_ioreq_xor(CPUState *env, ioreq_t *req)
+{
+       unsigned long tmp1, tmp2;
+
+       if (req->pdata_valid != 0)
+               hw_error("expected scalar value");
+
+       read_physical(req->addr, req->size, &tmp1);
+       if (req->dir == IOREQ_WRITE) {
+               tmp2 = tmp1 ^ (unsigned long) req->u.data;
+               write_physical(req->addr, req->size, &tmp2);
+       }
+       req->u.data = tmp1;
 }
 
 void
 cpu_handle_ioreq(CPUState *env)
 {
        ioreq_t *req = cpu_get_ioreq();
-       if (req)
-               cpu_dispatch_ioreq(env, req);
+
+       if (req) {
+               if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) {
+                       if (req->size != 4)
+                               req->u.data &= (1UL << (8 * req->size))-1;
+               }
+
+               switch (req->type) {
+               case IOREQ_TYPE_PIO:
+                       cpu_ioreq_pio(env, req);
+                       break;
+               case IOREQ_TYPE_COPY:
+                       cpu_ioreq_move(env, req);
+                       break;
+               case IOREQ_TYPE_AND:
+                       cpu_ioreq_and(env, req);
+                       break;
+               case IOREQ_TYPE_OR:
+                       cpu_ioreq_or(env, req);
+                       break;
+               case IOREQ_TYPE_XOR:
+                       cpu_ioreq_xor(env, req);
+                       break;
+               default:
+                       hw_error("Invalid ioreq type 0x%x", req->type);
+               }
+
+               /* No state change if state = STATE_IORESP_HOOK */
+               if (req->state == STATE_IOREQ_INPROCESS)
+                       req->state = STATE_IORESP_READY;
+               env->send_event = 1;
+       }
 }
 
 void
@@ -321,7 +405,7 @@
 
        // Send a message on the event channel. Add the vector to the shared mem
        // page.
-       intr = &(shared_page->sp_global.pic_intr[0]);
+       intr = (unsigned long *) &(shared_page->sp_global.pic_intr[0]);
        atomic_set_bit(vector, intr);
         if (loglevel & CPU_LOG_INT)
                 fprintf(logfile, "injecting vector: %x\n", vector);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Thu Sep  8 15:18:40 2005
+++ b/tools/ioemu/vl.c  Fri Sep  9 16:30:54 2005
@@ -125,6 +125,7 @@
 QEMUTimer *polling_timer;
 int vm_running;
 int audio_enabled = 0;
+int nic_pcnet = 1;
 int sb16_enabled = 1;
 int adlib_enabled = 1;
 int gus_enabled = 1;
@@ -412,6 +413,11 @@
     fprintf(stderr, "qemu: hardware error: ");
     vfprintf(stderr, fmt, ap);
     fprintf(stderr, "\n");
+    if (logfile) {
+       fprintf(logfile, "qemu: hardware error: ");
+       vfprintf(logfile, fmt, ap);
+       fprintf(logfile, "\n");
+    }
     va_end(ap);
     abort();
 }
@@ -2115,6 +2121,7 @@
            "-prep           Simulate a PREP system (default is PowerMAC)\n"
            "-g WxH[xDEPTH]  Set the initial VGA graphic mode\n"
 #endif
+           "-nic-pcnet     simulate an AMD PC-Net PCI ethernet adaptor\n"
            "\n"
            "Network options:\n"
            "-nics n         simulate 'n' network cards [default=1]\n"
@@ -2229,6 +2236,7 @@
     QEMU_OPTION_L,
     QEMU_OPTION_no_code_copy,
     QEMU_OPTION_pci,
+    QEMU_OPTION_nic_pcnet,
     QEMU_OPTION_isa,
     QEMU_OPTION_prep,
     QEMU_OPTION_k,
@@ -2313,6 +2321,7 @@
     
     /* temporary options */
     { "pci", 0, QEMU_OPTION_pci },
+    { "nic-pcnet", 0, QEMU_OPTION_nic_pcnet },
     { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
     { NULL },
 };
@@ -2639,6 +2648,9 @@
                 break;
             case QEMU_OPTION_pci:
                 pci_enabled = 1;
+                break;
+            case QEMU_OPTION_nic_pcnet:
+                nic_pcnet = 1;
                 break;
             case QEMU_OPTION_isa:
                 pci_enabled = 0;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Thu Sep  8 15:18:40 2005
+++ b/tools/ioemu/vl.h  Fri Sep  9 16:30:54 2005
@@ -600,6 +600,12 @@
 void isa_ne2000_init(int base, int irq, NetDriverState *nd);
 void pci_ne2000_init(PCIBus *bus, NetDriverState *nd);
 
+/* pcnet.c */
+
+extern int nic_pcnet;
+
+void pci_pcnet_init(PCIBus *bus, NetDriverState *nd);
+
 /* pckbd.c */
 
 void kbd_init(void);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/Makefile
--- a/tools/libxc/Makefile      Thu Sep  8 15:18:40 2005
+++ b/tools/libxc/Makefile      Fri Sep  9 16:30:54 2005
@@ -139,7 +139,7 @@
 libxenguest.so.$(MAJOR): libxenguest.so.$(MAJOR).$(MINOR)
        ln -sf $< $@
 
-libxenguest.so.$(MAJOR).$(MINOR): $(PIC_BUILD_OBJS)
+libxenguest.so.$(MAJOR).$(MINOR): $(PIC_BUILD_OBJS) libxenctrl.so
        $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-soname -Wl,libxenguest.so.$(MAJOR) 
-shared -o $@ $^ -lz -lxenctrl
 
 -include $(DEPS)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_core.c
--- a/tools/libxc/xc_core.c     Thu Sep  8 15:18:40 2005
+++ b/tools/libxc/xc_core.c     Fri Sep  9 16:30:54 2005
@@ -2,6 +2,7 @@
 #define ELFSIZE 32
 #include "xc_elf.h"
 #include <stdlib.h>
+#include <unistd.h>
 #include <zlib.h>
 
 /* number of pages to write at a time */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c   Thu Sep  8 15:18:40 2005
+++ b/tools/libxc/xc_domain.c   Fri Sep  9 16:30:54 2005
@@ -7,6 +7,7 @@
  */
 
 #include "xc_private.h"
+#include <xen/memory.h>
 
 int xc_domain_create(int xc_handle,
                      u32 ssidref,
@@ -261,19 +262,66 @@
 
 int xc_domain_memory_increase_reservation(int xc_handle,
                                           u32 domid, 
-                                          unsigned int mem_kb)
+                                          unsigned long nr_extents,
+                                          unsigned int extent_order,
+                                          unsigned int address_bits,
+                                         unsigned long *extent_start)
 {
     int err;
-    unsigned int npages = mem_kb / (PAGE_SIZE/1024);
-
-    err = xc_dom_mem_op(xc_handle, MEMOP_increase_reservation, NULL,
-                        npages, 0, domid);
-    if (err == npages)
+    struct xen_memory_reservation reservation = {
+        .extent_start = extent_start, /* may be NULL */
+        .nr_extents   = nr_extents,
+        .extent_order = extent_order,  
+        .address_bits = address_bits,
+        .domid        = domid
+    };
+
+    err = xc_memory_op(xc_handle, XENMEM_increase_reservation, &reservation);
+    if (err == nr_extents)
         return 0;
 
     if (err > 0) {
+        fprintf(stderr,"Failed alocation for dom %d : %ld pages order %d 
addr_bits %d\n",
+                                 domid, nr_extents, extent_order, 
address_bits);
         errno = ENOMEM;
         err = -1;
     }
     return err;
 }
+
+int xc_domain_memory_decrease_reservation(int xc_handle,
+                                          u32 domid, 
+                                          unsigned long nr_extents,
+                                          unsigned int extent_order,
+                                         unsigned long *extent_start)
+{
+    int err;
+    struct xen_memory_reservation reservation = {
+        .extent_start = extent_start, 
+        .nr_extents   = nr_extents,
+        .extent_order = extent_order,  
+        .address_bits = 0,
+        .domid        = domid
+    };
+
+    if (extent_start == NULL)
+    {
+        fprintf(stderr,"decrease_reservation extent_start is NULL!\n");
+        errno = EINVAL;
+        err = -1;
+       goto out;
+    }
+
+    err = xc_memory_op(xc_handle, XENMEM_increase_reservation, &reservation);
+    if (err == nr_extents)
+        return 0;
+
+    if (err > 0) {
+        fprintf(stderr,"Failed de-alocation for dom %d : %ld pages order %d\n",
+                                 domid, nr_extents, extent_order);
+        errno = EBUSY;
+        err = -1;
+    }
+out:
+    return err;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_linux_build.c
--- a/tools/libxc/xc_linux_build.c      Thu Sep  8 15:18:40 2005
+++ b/tools/libxc/xc_linux_build.c      Fri Sep  9 16:30:54 2005
@@ -17,6 +17,7 @@
 #include "xc_elf.h"
 #include "xc_aout9.h"
 #include <stdlib.h>
+#include <unistd.h>
 #include <zlib.h>
 
 #if defined(__i386__)
@@ -56,7 +57,7 @@
 }
 
 #define alloc_pt(ltab, vltab) \
-        ltab = page_array[ppt_alloc++] << PAGE_SHIFT; \
+        ltab = (unsigned long long)(page_array[ppt_alloc++]) << PAGE_SHIFT; \
         if (vltab != NULL) { \
             munmap(vltab, PAGE_SIZE); \
         } \
@@ -127,18 +128,37 @@
     l1_pgentry_64_t *vl1tab=NULL, *vl1e=NULL;
     l2_pgentry_64_t *vl2tab=NULL, *vl2e=NULL;
     l3_pgentry_64_t *vl3tab=NULL, *vl3e=NULL;
-    unsigned long l1tab = 0;
-    unsigned long l2tab = 0;
-    unsigned long l3tab = 0;
+    unsigned long long l1tab = 0;
+    unsigned long long l2tab = 0;
+    unsigned long long l3tab = 0;
     unsigned long ppt_alloc;
     unsigned long count;
 
     /* First allocate page for page dir. */
     ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
+
+    if ( page_array[ppt_alloc] > 0xfffff )
+    {
+       unsigned long nmfn;
+       nmfn = xc_make_page_below_4G( xc_handle, dom, page_array[ppt_alloc] );
+       if ( nmfn == 0 )
+       {
+           fprintf(stderr, "Couldn't get a page below 4GB :-(\n");
+           goto error_out;
+       }
+       page_array[ppt_alloc] = nmfn;
+    }
+
     alloc_pt(l3tab, vl3tab);
     vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)];
     ctxt->ctrlreg[3] = l3tab;
-    
+
+    if(l3tab>0xfffff000ULL)
+    {
+        fprintf(stderr,"L3TAB = %llx above 4GB!\n",l3tab);
+        goto error_out;
+    }
+ 
     for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++)
     {
         if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
@@ -274,7 +294,6 @@
                          unsigned long *pvss, vcpu_guest_context_t *ctxt,
                          const char *cmdline,
                          unsigned long shared_info_frame,
-                         unsigned int control_evtchn,
                          unsigned long flags,
                          unsigned int vcpus,
                          unsigned int store_evtchn, unsigned long *store_mfn)
@@ -332,10 +351,10 @@
                        unsigned long *pvss, vcpu_guest_context_t *ctxt,
                        const char *cmdline,
                        unsigned long shared_info_frame,
-                       unsigned int control_evtchn,
                        unsigned long flags,
                        unsigned int vcpus,
-                      unsigned int store_evtchn, unsigned long *store_mfn)
+                      unsigned int store_evtchn, unsigned long *store_mfn,
+                      unsigned int console_evtchn, unsigned long *console_mfn)
 {
     unsigned long *page_array = NULL;
     unsigned long count, i;
@@ -346,7 +365,7 @@
 
     unsigned long nr_pt_pages;
     unsigned long physmap_pfn;
-    u32 *physmap, *physmap_e;
+    unsigned long *physmap, *physmap_e;
 
     struct load_funcs load_funcs;
     struct domain_setup_info dsi;
@@ -358,6 +377,8 @@
     unsigned long vstartinfo_end;
     unsigned long vstoreinfo_start;
     unsigned long vstoreinfo_end;
+    unsigned long vconsole_start;
+    unsigned long vconsole_end;
     unsigned long vstack_start;
     unsigned long vstack_end;
     unsigned long vpt_start;
@@ -391,16 +412,18 @@
     vinitrd_end      = vinitrd_start + initrd_len;
     vphysmap_start   = round_pgup(vinitrd_end);
     vphysmap_end     = vphysmap_start + (nr_pages * sizeof(unsigned long));
-    vstoreinfo_start = round_pgup(vphysmap_end);
+    vstartinfo_start = round_pgup(vphysmap_end);
+    vstartinfo_end   = vstartinfo_start + PAGE_SIZE;
+    vstoreinfo_start = vstartinfo_end;
     vstoreinfo_end   = vstoreinfo_start + PAGE_SIZE;
-    vpt_start        = vstoreinfo_end; 
+    vconsole_start   = vstoreinfo_end;
+    vconsole_end     = vconsole_start + PAGE_SIZE;
+    vpt_start        = vconsole_end; 
 
     for ( nr_pt_pages = 2; ; nr_pt_pages++ )
     {
         vpt_end          = vpt_start + (nr_pt_pages * PAGE_SIZE);
-        vstartinfo_start = vpt_end;
-        vstartinfo_end   = vstartinfo_start + PAGE_SIZE;
-        vstack_start     = vstartinfo_end;
+        vstack_start     = vpt_end;
         vstack_end       = vstack_start + PAGE_SIZE;
         v_end            = (vstack_end + (1UL<<22)-1) & ~((1UL<<22)-1);
         if ( (v_end - vstack_end) < (512UL << 10) )
@@ -436,17 +459,19 @@
            " Loaded kernel: %p->%p\n"
            " Init. ramdisk: %p->%p\n"
            " Phys-Mach map: %p->%p\n"
+           " Start info:    %p->%p\n"
            " Store page:    %p->%p\n"
+           " Console page:  %p->%p\n"
            " Page tables:   %p->%p\n"
-           " Start info:    %p->%p\n"
            " Boot stack:    %p->%p\n"
            " TOTAL:         %p->%p\n",
            _p(dsi.v_kernstart), _p(dsi.v_kernend), 
            _p(vinitrd_start), _p(vinitrd_end),
            _p(vphysmap_start), _p(vphysmap_end),
+           _p(vstartinfo_start), _p(vstartinfo_end),
            _p(vstoreinfo_start), _p(vstoreinfo_end),
+           _p(vconsole_start), _p(vconsole_end),
            _p(vpt_start), _p(vpt_end),
-           _p(vstartinfo_start), _p(vstartinfo_end),
            _p(vstack_start), _p(vstack_end),
            _p(dsi.v_start), _p(v_end));
     printf(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
@@ -519,12 +544,14 @@
     physmap = physmap_e = xc_map_foreign_range(
         xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
         page_array[physmap_pfn++]);
+
     for ( count = 0; count < nr_pages; count++ )
     {
         if ( xc_add_mmu_update(xc_handle, mmu,
-                              (page_array[count] << PAGE_SHIFT) | 
+                              ((unsigned long long)page_array[count] << 
PAGE_SHIFT) | 
                               MMU_MACHPHYS_UPDATE, count) )
         {
+            fprintf(stderr,"m2p update failure p=%lx 
m=%lx\n",count,page_array[count] ); 
             munmap(physmap, PAGE_SIZE);
             goto error_out;
         }
@@ -566,6 +593,8 @@
 #endif
 
     *store_mfn = page_array[(vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT];
+    *console_mfn = page_array[(vconsole_start-dsi.v_start) >> PAGE_SHIFT];
+
 
     start_info = xc_map_foreign_range(
         xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
@@ -577,9 +606,10 @@
     start_info->pt_base      = vpt_start;
     start_info->nr_pt_frames = nr_pt_pages;
     start_info->mfn_list     = vphysmap_start;
-    start_info->domain_controller_evtchn = control_evtchn;
     start_info->store_mfn    = *store_mfn;
     start_info->store_evtchn = store_evtchn;
+    start_info->console_mfn   = *console_mfn;
+    start_info->console_evtchn = console_evtchn;
     if ( initrd_len != 0 )
     {
         start_info->mod_start    = vinitrd_start;
@@ -627,11 +657,12 @@
                    const char *image_name,
                    const char *ramdisk_name,
                    const char *cmdline,
-                   unsigned int control_evtchn,
                    unsigned long flags,
                    unsigned int vcpus,
                    unsigned int store_evtchn,
-                   unsigned long *store_mfn)
+                   unsigned long *store_mfn,
+                   unsigned int console_evtchn,
+                   unsigned long *console_mfn)
 {
     dom0_op_t launch_op, op;
     int initrd_fd = -1;
@@ -706,8 +737,9 @@
                      &vstartinfo_start, &vkern_entry,
                      &vstack_start, ctxt, cmdline,
                      op.u.getdomaininfo.shared_info_frame,
-                     control_evtchn, flags, vcpus,
-                     store_evtchn, store_mfn) < 0 )
+                     flags, vcpus,
+                     store_evtchn, store_mfn,
+                    console_evtchn, console_mfn) < 0 )
     {
         ERROR("Error constructing guest OS");
         goto error_out;
@@ -727,7 +759,6 @@
     ctxt->regs.ar_fpsr = FPSR_DEFAULT;
     /* ctxt->regs.r28 = dom_fw_setup(); currently done by hypervisor, should 
move here */
     ctxt->vcpu.privregs = 0;
-    ctxt->shared.domain_controller_evtchn = control_evtchn;
     ctxt->shared.flags = flags;
     i = 0; /* silence unused variable warning */
 #else /* x86 */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_linux_restore.c
--- a/tools/libxc/xc_linux_restore.c    Thu Sep  8 15:18:40 2005
+++ b/tools/libxc/xc_linux_restore.c    Fri Sep  9 16:30:54 2005
@@ -8,24 +8,22 @@
 
 #include <stdlib.h>
 #include <unistd.h>
-
 #include "xg_private.h"
 #include <xenctrl.h>
-
-#include <xen/linux/suspend.h>
+#include <xen/memory.h>
 
 #define MAX_BATCH_SIZE 1024
 
 #define DEBUG 0
 
 #if 1
-#define ERR(_f, _a...) fprintf ( stderr, _f , ## _a ); fflush(stderr)
+#define ERR(_f, _a...) do { fprintf ( stderr, _f , ## _a ); fflush(stderr); } 
while(0)
 #else
 #define ERR(_f, _a...) ((void)0)
 #endif
 
 #if DEBUG
-#define DPRINTF(_f, _a...) fprintf ( stdout, _f , ## _a ); fflush(stdout)
+#define DPRINTF(_f, _a...) do { fprintf ( stdout, _f , ## _a ); 
fflush(stdout); } while (0)
 #else
 #define DPRINTF(_f, _a...) ((void)0)
 #endif
@@ -54,7 +52,8 @@
 }
 
 int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
-                    unsigned int store_evtchn, unsigned long *store_mfn)
+                    unsigned int store_evtchn, unsigned long *store_mfn,
+                    unsigned int console_evtchn, unsigned long *console_mfn)
 {
     dom0_op_t op;
     int rc = 1, i, n, k;
@@ -89,8 +88,8 @@
     /* used by mapper for updating the domain's copy of the table */
     unsigned long *live_pfn_to_mfn_table = NULL;
 
-    /* A temporary mapping of the guest's suspend record. */
-    suspend_record_t *p_srec;
+    /* A temporary mapping of the guest's start_info page. */
+    start_info_t *start_info;
 
     char *region_base;
 
@@ -103,7 +102,7 @@
     struct mmuext_op pin[MAX_PIN_BATCH];
     unsigned int nr_pins = 0;
 
-    DPRINTF("xc_linux_restore start\n");
+    DPRINTF("xc_linux_restore start: nr_pfns = %lx\n", nr_pfns);
 
     if (mlock(&ctxt, sizeof(ctxt))) {
         /* needed for when we do the build dom0 op, 
@@ -150,8 +149,10 @@
     }
 
     err = xc_domain_memory_increase_reservation(xc_handle, dom,
-                                                nr_pfns * PAGE_SIZE / 1024);
+                                                nr_pfns, 0, 0, NULL);
     if (err != 0) {
+        ERR("Failed to increase reservation by %lx\n", 
+            nr_pfns * PAGE_SIZE / 1024); 
         errno = ENOMEM;
         goto out;
     }
@@ -409,7 +410,8 @@
 
     /* Get the list of PFNs that are not in the psuedo-phys map */
     {
-       unsigned int count, *pfntab;
+       unsigned int count;
+        unsigned long *pfntab;
        int rc;
 
        if ( read_exact(io_fd, &count, sizeof(count)) != sizeof(count) )
@@ -441,9 +443,15 @@
 
        if ( count > 0 )
        {
-           if ( (rc = xc_dom_mem_op( xc_handle,
-                                      MEMOP_decrease_reservation,
-                                      pfntab, count, 0, dom )) <0 )
+            struct xen_memory_reservation reservation = {
+                .extent_start = pfntab,
+                .nr_extents   = count,
+                .extent_order = 0,
+                .domid        = dom
+            };
+           if ( (rc = xc_memory_op(xc_handle,
+                                    XENMEM_decrease_reservation,
+                                    &reservation)) != count )
            {
                ERR("Could not decrease reservation : %d",rc);
                goto out;
@@ -470,15 +478,18 @@
         goto out;
     }
     ctxt.user_regs.esi = mfn = pfn_to_mfn_table[pfn];
-    p_srec = xc_map_foreign_range(
+    start_info = xc_map_foreign_range(
         xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
-    p_srec->resume_info.nr_pages    = nr_pfns;
-    p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT;
-    p_srec->resume_info.flags       = 0;
-    *store_mfn = p_srec->resume_info.store_mfn   =
-       pfn_to_mfn_table[p_srec->resume_info.store_mfn];
-    p_srec->resume_info.store_evtchn = store_evtchn;
-    munmap(p_srec, PAGE_SIZE);
+    start_info->nr_pages    = nr_pfns;
+    start_info->shared_info = shared_info_frame << PAGE_SHIFT;
+    start_info->flags       = 0;
+    *store_mfn = start_info->store_mfn   =
+       pfn_to_mfn_table[start_info->store_mfn];
+    start_info->store_evtchn = store_evtchn;
+    *console_mfn = start_info->console_mfn   =
+       pfn_to_mfn_table[start_info->console_mfn];
+    start_info->console_evtchn = console_evtchn;
+    munmap(start_info, PAGE_SIZE);
 
     /* Uncanonicalise each GDT frame number. */
     if ( ctxt.gdt_ents > 8192 )
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_linux_save.c
--- a/tools/libxc/xc_linux_save.c       Thu Sep  8 15:18:40 2005
+++ b/tools/libxc/xc_linux_save.c       Fri Sep  9 16:30:54 2005
@@ -14,12 +14,29 @@
 
 #include "xg_private.h"
 
-#include <xen/linux/suspend.h>
 #include <xen/io/domain_controller.h>
 
 #define BATCH_SIZE 1024   /* 1024 pages (4MB) at a time */
 
 #define MAX_MBIT_RATE 500
+
+
+/*
+** Default values for important tuning parameters. Can override by passing
+** non-zero replacement values to xc_linux_save().  
+**
+** XXX SMH: should consider if want to be able to override MAX_MBIT_RATE too. 
+** 
+*/
+#define DEF_MAX_ITERS   29   /* limit us to 30 times round loop */ 
+#define DEF_MAX_FACTOR   3   /* never send more than 3x nr_pfns */
+
+
+
+/* Flags to control behaviour of xc_linux_save */
+#define XCFLAGS_LIVE      1
+#define XCFLAGS_DEBUG     2
+
 
 #define DEBUG 0
 
@@ -320,18 +337,18 @@
                              xc_dominfo_t *info,
                              vcpu_guest_context_t *ctxt)
 {
-    int i=0;
+    int i = 0;
     char ans[30];
 
     printf("suspend\n");
     fflush(stdout);
     if (fgets(ans, sizeof(ans), stdin) == NULL) {
-       ERR("failed reading suspend reply");
-       return -1;
+        ERR("failed reading suspend reply");
+        return -1;
     }
     if (strncmp(ans, "done\n", 5)) {
-       ERR("suspend reply incorrect: %s", ans);
-       return -1;
+        ERR("suspend reply incorrect: %s", ans);
+        return -1;
     }
 
 retry:
@@ -377,19 +394,16 @@
     return -1;
 }
 
-int xc_linux_save(int xc_handle, int io_fd, u32 dom)
+int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters, 
+                  u32 max_factor, u32 flags)
 {
     xc_dominfo_t info;
 
     int rc = 1, i, j, k, last_iter, iter = 0;
     unsigned long mfn;
-    int live =  0; // (ioctxt->flags & XCFLAGS_LIVE);
-    int debug = 0; // (ioctxt->flags & XCFLAGS_DEBUG);
+    int live  = (flags & XCFLAGS_LIVE); 
+    int debug = (flags & XCFLAGS_DEBUG); 
     int sent_last_iter, skip_this_iter;
-
-    /* Important tuning parameters */
-    int max_iters  = 29; /* limit us to 30 times round loop */
-    int max_factor = 3;  /* never send more than 3x nr_pfns */
 
     /* The new domain's shared-info frame number. */
     unsigned long shared_info_frame;
@@ -405,6 +419,7 @@
     unsigned long page[1024];
 
     /* A copy of the pfn-to-mfn table frame list. */
+    unsigned long *live_pfn_to_mfn_frame_list_list = NULL;
     unsigned long *live_pfn_to_mfn_frame_list = NULL;
     unsigned long pfn_to_mfn_frame_list[1024];
 
@@ -420,9 +435,6 @@
     /* base of the region in which domain memory is mapped */
     unsigned char *region_base = NULL;
 
-    /* A temporary mapping, and a copy, of the guest's suspend record. */
-    suspend_record_t *p_srec = NULL;
-
     /* number of pages we're dealing with */
     unsigned long nr_pfns;
 
@@ -442,8 +454,16 @@
 
     MBIT_RATE = START_MBIT_RATE;
 
-    DPRINTF("xc_linux_save start %d\n", dom);
-    
+
+    /* If no explicit control parameters given, use defaults */
+    if(!max_iters) 
+        max_iters = DEF_MAX_ITERS; 
+    if(!max_factor) 
+        max_factor = DEF_MAX_FACTOR; 
+
+
+    DPRINTF("xc_linux_save start DOM%u live=%s\n", dom, live?"true":"false"); 
+
     if (mlock(&ctxt, sizeof(ctxt))) {
         ERR("Unable to mlock ctxt");
         return 1;
@@ -487,11 +507,20 @@
         goto out;
     }
 
-    /* the pfn_to_mfn_frame_list fits in a single page */
+    live_pfn_to_mfn_frame_list_list = xc_map_foreign_range(xc_handle, dom,
+                                        PAGE_SIZE, PROT_READ,
+                                        
live_shinfo->arch.pfn_to_mfn_frame_list_list);
+
+    if (!live_pfn_to_mfn_frame_list_list){
+        ERR("Couldn't map pfn_to_mfn_frame_list_list");
+        goto out;
+    }
+
     live_pfn_to_mfn_frame_list = 
-        xc_map_foreign_range(xc_handle, dom, 
-                              PAGE_SIZE, PROT_READ, 
-                              live_shinfo->arch.pfn_to_mfn_frame_list );
+       xc_map_foreign_batch(xc_handle, dom, 
+                            PROT_READ,
+                            live_pfn_to_mfn_frame_list_list,
+                            (nr_pfns+(1024*1024)-1)/(1024*1024) );
 
     if (!live_pfn_to_mfn_frame_list){
         ERR("Couldn't map pfn_to_mfn_frame_list");
@@ -647,22 +676,6 @@
         goto out;
     }
 
-    /* Map the suspend-record MFN to pin it. The page must be owned by 
-       dom for this to succeed. */
-    p_srec = xc_map_foreign_range(xc_handle, dom,
-                                   sizeof(*p_srec), PROT_READ | PROT_WRITE, 
-                                   ctxt.user_regs.esi);
-    if (!p_srec){
-        ERR("Couldn't map suspend record");
-        goto out;
-    }
-
-    /* Canonicalize store mfn. */
-    if ( !translate_mfn_to_pfn(&p_srec->resume_info.store_mfn) ) {
-       ERR("Store frame is not in range of pseudophys map");
-       goto out;
-    }
-
     print_stats( xc_handle, dom, 0, &stats, 0 );
 
     /* Now write out each data page, canonicalising page tables as we go... */
@@ -763,8 +776,6 @@
                 batch++;
             }
      
-//            DPRINTF("batch %d:%d (n=%d)\n", iter, batch, n);
-
             if ( batch == 0 )
                 goto skip; /* vanishingly unlikely... */
       
@@ -915,7 +926,7 @@
             continue;
         }
 
-        if ( last_iter ) break;
+        if ( last_iter ) break; 
 
         if ( live )
         {
@@ -1003,13 +1014,6 @@
        }
     }
 
-    if (nr_pfns != p_srec->nr_pfns )
-    {
-       ERR("Suspend record nr_pfns unexpected (%ld != %ld)",
-                  p_srec->nr_pfns, nr_pfns);
-        goto out;
-    }
-
     /* Canonicalise the suspend-record frame number. */
     if ( !translate_mfn_to_pfn(&ctxt.user_regs.esi) ){
         ERR("Suspend record is not in range of pseudophys map");
@@ -1043,9 +1047,6 @@
     if(live_shinfo)
         munmap(live_shinfo, PAGE_SIZE);
 
-    if(p_srec) 
-        munmap(p_srec, sizeof(*p_srec));
-
     if(live_pfn_to_mfn_frame_list) 
         munmap(live_pfn_to_mfn_frame_list, PAGE_SIZE);
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_load_aout9.c
--- a/tools/libxc/xc_load_aout9.c       Thu Sep  8 15:18:40 2005
+++ b/tools/libxc/xc_load_aout9.c       Fri Sep  9 16:30:54 2005
@@ -14,7 +14,8 @@
 
 
 #define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
-#define round_pgdown(_p)  ((_p)&PAGE_MASK)
+#define KZERO             0x80000000
+#define KOFFSET(_p)       ((_p)&~KZERO)
 
 static int parseaout9image(char *, unsigned long, struct domain_setup_info *);
 static int loadaout9image(char *, unsigned long, int, u32, unsigned long *, 
struct domain_setup_info *);
@@ -47,7 +48,7 @@
     struct domain_setup_info *dsi)
 {
     struct Exec ehdr;
-    unsigned long start, txtsz, end;
+    unsigned long start, dstart, end;
 
     if (!get_header(image, image_size, &ehdr)) {
         ERROR("Kernel image does not have a a.out9 header.");
@@ -59,11 +60,11 @@
         return -EINVAL;
     }
 
-    start = round_pgdown(ehdr.entry);
-    txtsz = round_pgup(ehdr.text);
-    end = start + txtsz + ehdr.data + ehdr.bss;
+    start = ehdr.entry;
+    dstart = round_pgup(start + ehdr.text);
+    end = dstart + ehdr.data + ehdr.bss;
 
-    dsi->v_start       = start;
+    dsi->v_start       = KZERO;
     dsi->v_kernstart   = start;
     dsi->v_kernend     = end;
     dsi->v_kernentry   = ehdr.entry;
@@ -83,19 +84,18 @@
     struct domain_setup_info *dsi)
 {
     struct Exec ehdr;
-    unsigned long txtsz;
+    unsigned long start, dstart;
 
     if (!get_header(image, image_size, &ehdr)) {
         ERROR("Kernel image does not have a a.out9 header.");
         return -EINVAL;
     }
 
-    txtsz = round_pgup(ehdr.text);
-    copyout(xch, dom, parray, 
-            0, image, sizeof ehdr + ehdr.text);
-    copyout(xch, dom, parray, 
-            txtsz, image + sizeof ehdr + ehdr.text, ehdr.data);
-    /* XXX zeroing of BSS needed? */
+    start = ehdr.entry;
+    dstart = round_pgup(start + ehdr.text);
+    copyout(xch, dom, parray, start, image + sizeof ehdr, ehdr.text);
+    copyout(xch, dom, parray, dstart,
+            image + sizeof ehdr + ehdr.text, ehdr.data);
 
     /* XXX load symbols */
 
@@ -110,13 +110,14 @@
 copyout(
     int xch, u32 dom,
     unsigned long *parray,
-    unsigned long off,
+    unsigned long addr,
     void *buf,
     int sz)
 {
-    unsigned long pgoff, chunksz;
+    unsigned long pgoff, chunksz, off;
     void *pg;
 
+    off = KOFFSET(addr);
     while (sz > 0) {
         pgoff = off & (PAGE_SIZE-1);
         chunksz = sz;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_private.c
--- a/tools/libxc/xc_private.c  Thu Sep  8 15:18:40 2005
+++ b/tools/libxc/xc_private.c  Fri Sep  9 16:30:54 2005
@@ -6,6 +6,7 @@
 
 #include <zlib.h>
 #include "xc_private.h"
+#include <xen/memory.h>
 
 void *xc_map_foreign_batch(int xc_handle, u32 dom, int prot,
                            unsigned long *arr, int num )
@@ -115,7 +116,7 @@
 
     if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
     {
-       fprintf(stderr, "Dom_mem operation failed (rc=%ld errno=%d)-- need to"
+       fprintf(stderr, "Dom_mmuext operation failed (rc=%ld errno=%d)-- need 
to"
                     " rebuild the user-space tool set?\n",ret,errno);
     }
 
@@ -171,7 +172,7 @@
 }
 
 int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu, 
-                     unsigned long ptr, unsigned long val)
+                     unsigned long long ptr, unsigned long long val)
 {
     mmu->updates[mmu->idx].ptr = ptr;
     mmu->updates[mmu->idx].val = val;
@@ -187,38 +188,64 @@
     return flush_mmu_updates(xc_handle, mmu);
 }
 
-int xc_dom_mem_op(int xc_handle,
-                 unsigned int memop, 
-                 unsigned int *extent_list, 
-                 unsigned int nr_extents,
-                 unsigned int extent_order,
-                 domid_t domid)
+int xc_memory_op(int xc_handle,
+                 int cmd,
+                 void *arg)
 {
     privcmd_hypercall_t hypercall;
+    struct xen_memory_reservation *reservation = arg;
     long ret = -EINVAL;
 
-    hypercall.op     = __HYPERVISOR_dom_mem_op;
-    hypercall.arg[0] = (unsigned long)memop;
-    hypercall.arg[1] = (unsigned long)extent_list;
-    hypercall.arg[2] = (unsigned long)nr_extents;
-    hypercall.arg[3] = (unsigned long)extent_order;
-    hypercall.arg[4] = (unsigned long)domid;
-
-    if ( (extent_list != NULL) && 
-         (mlock(extent_list, nr_extents*sizeof(unsigned long)) != 0) )
-    {
-        PERROR("Could not lock memory for Xen hypercall");
-        goto out1;
+    hypercall.op     = __HYPERVISOR_memory_op;
+    hypercall.arg[0] = (unsigned long)cmd;
+    hypercall.arg[1] = (unsigned long)arg;
+
+    switch ( cmd )
+    {
+    case XENMEM_increase_reservation:
+    case XENMEM_decrease_reservation:
+        if ( mlock(reservation, sizeof(*reservation)) != 0 )
+        {
+            PERROR("Could not mlock");
+            goto out1;
+        }
+        if ( (reservation->extent_start != NULL) &&
+             (mlock(reservation->extent_start,
+                    reservation->nr_extents * sizeof(unsigned long)) != 0) )
+        {
+            PERROR("Could not mlock");
+            safe_munlock(reservation, sizeof(*reservation));
+            goto out1;
+        }
+        break;
+    case XENMEM_maximum_ram_page:
+        if ( mlock(arg, sizeof(unsigned long)) != 0 )
+        {
+            PERROR("Could not mlock");
+            goto out1;
+        }
+        break;
     }
 
     if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
     {
-       fprintf(stderr, "Dom_mem operation failed (rc=%ld errno=%d)-- need to"
+       fprintf(stderr, "hypercall failed (rc=%ld errno=%d)-- need to"
                 " rebuild the user-space tool set?\n",ret,errno);
     }
 
-    if ( extent_list != NULL )
-        safe_munlock(extent_list, nr_extents*sizeof(unsigned long));
+    switch ( cmd )
+    {
+    case XENMEM_increase_reservation:
+    case XENMEM_decrease_reservation:
+        safe_munlock(reservation, sizeof(*reservation));
+        if ( reservation->extent_start != NULL )
+            safe_munlock(reservation->extent_start,
+                         reservation->nr_extents * sizeof(unsigned long));
+        break;
+    case XENMEM_maximum_ram_page:
+        safe_munlock(arg, sizeof(unsigned long));
+        break;
+    }
 
  out1:
     return ret;
@@ -395,3 +422,26 @@
 {
     return do_dom0_op(xc_handle, op);
 }
+
+int xc_version(int xc_handle, int cmd, void *arg)
+{
+    return do_xen_version(xc_handle, cmd, arg);
+}
+
+unsigned long xc_make_page_below_4G(int xc_handle, u32 domid, 
+                                   unsigned long mfn)
+{
+    unsigned long new_mfn;
+    if ( xc_domain_memory_decrease_reservation( 
+       xc_handle, domid, 1, 0, &mfn ) != 1 )
+    {
+       fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn);
+       return 0;
+    }
+    if ( xc_domain_memory_increase_reservation( xc_handle, domid, 1, 0, 32, 
&new_mfn ) != 1 )
+    {
+       fprintf(stderr,"xc_make_page_below_4G increase failed. mfn=%lx\n",mfn);
+       return 0;
+    }
+    return new_mfn;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_private.h
--- a/tools/libxc/xc_private.h  Thu Sep  8 15:18:40 2005
+++ b/tools/libxc/xc_private.h  Fri Sep  9 16:30:54 2005
@@ -59,6 +59,17 @@
                       (unsigned long)hypercall);
 }
 
+static inline int do_xen_version(int xc_handle, int cmd, void *dest)
+{
+    privcmd_hypercall_t hypercall;
+
+    hypercall.op     = __HYPERVISOR_xen_version;
+    hypercall.arg[0] = (unsigned long) cmd;
+    hypercall.arg[1] = (unsigned long) dest;
+    
+    return do_xen_hypercall(xc_handle, &hypercall);
+}
+
 static inline int do_dom0_op(int xc_handle, dom0_op_t *op)
 {
     int ret = -1;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_vmx_build.c
--- a/tools/libxc/xc_vmx_build.c        Thu Sep  8 15:18:40 2005
+++ b/tools/libxc/xc_vmx_build.c        Fri Sep  9 16:30:54 2005
@@ -7,6 +7,7 @@
 #define ELFSIZE 32
 #include "xc_elf.h"
 #include <stdlib.h>
+#include <unistd.h>
 #include <zlib.h>
 #include <xen/io/ioreq.h>
 #include "linux_boot_params.h"
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Thu Sep  8 15:18:40 2005
+++ b/tools/libxc/xenctrl.h     Fri Sep  9 16:30:54 2005
@@ -23,6 +23,7 @@
 #include <sys/ptrace.h>
 #include <xen/xen.h>
 #include <xen/dom0_ops.h>
+#include <xen/version.h>
 #include <xen/event_channel.h>
 #include <xen/sched_ctl.h>
 #include <xen/acm.h>
@@ -386,7 +387,19 @@
 
 int xc_domain_memory_increase_reservation(int xc_handle,
                                           u32 domid, 
-                                          unsigned int mem_kb);
+                                          unsigned long nr_extents,
+                                          unsigned int extent_order,
+                                          unsigned int address_bits,
+                                         unsigned long *extent_start);
+
+int xc_domain_memory_decrease_reservation(int xc_handle,
+                                          u32 domid, 
+                                          unsigned long nr_extents,
+                                          unsigned int extent_order,
+                                         unsigned long *extent_start);
+
+unsigned long xc_make_page_below_4G(int xc_handle, u32 domid, 
+                                   unsigned long mfn);
 
 typedef dom0_perfc_desc_t xc_perfc_desc_t;
 /* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */
@@ -430,9 +443,7 @@
 int xc_mmuext_op(int xc_handle, struct mmuext_op *op, unsigned int nr_ops,
                 domid_t dom);
 
-int xc_dom_mem_op(int xc_handle, unsigned int memop, unsigned int *extent_list,
-                 unsigned int nr_extents, unsigned int extent_order,
-                 domid_t domid);
+int xc_memory_op(int xc_handle, int cmd, void *arg);
 
 int xc_get_pfn_type_batch(int xc_handle, u32 dom, int num, unsigned long *arr);
 
@@ -498,6 +509,8 @@
 
 /* Execute a privileged dom0 operation. */
 int xc_dom0_op(int xc_handle, dom0_op_t *op);
+
+int xc_version(int xc_handle, int cmd, void *arg);
 
 /* Initializes the store (for dom0)
    remote_port should be the remote end of a bound interdomain channel between
@@ -520,7 +533,7 @@
 typedef struct xc_mmu xc_mmu_t;
 xc_mmu_t *xc_init_mmu_updates(int xc_handle, domid_t dom);
 int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu, 
-                   unsigned long ptr, unsigned long val);
+                   unsigned long long ptr, unsigned long long val);
 int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu);
 
 #endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h    Thu Sep  8 15:18:40 2005
+++ b/tools/libxc/xenguest.h    Fri Sep  9 16:30:54 2005
@@ -6,13 +6,12 @@
  * Copyright (c) 2003-2004, K A Fraser.
  */
 
-#ifndef XENBUILD_H
-#define XENBUILD_H
+#ifndef XENGUEST_H
+#define XENGUEST_H
 
-#define XCFLAGS_VERBOSE   1
-#define XCFLAGS_LIVE      2
-#define XCFLAGS_DEBUG     4
-#define XCFLAGS_CONFIGURE 8
+#define XCFLAGS_LIVE      1
+#define XCFLAGS_DEBUG     2
+
 
 /**
  * This function will save a domain running Linux.
@@ -22,7 +21,8 @@
  * @parm dom the id of the domain
  * @return 0 on success, -1 on failure
  */
-int xc_linux_save(int xc_handle, int fd, uint32_t dom);
+int xc_linux_save(int xc_handle, int fd, uint32_t dom, uint32_t max_iters, 
+                  uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */);
 
 /**
  * This function will restore a saved domain running Linux.
@@ -35,19 +35,22 @@
  * @parm store_mfn returned with the mfn of the store page
  * @return 0 on success, -1 on failure
  */
-int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom, unsigned long 
nr_pfns,
-                    unsigned int store_evtchn, unsigned long *store_mfn);
+int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom, 
+                     unsigned long nr_pfns, unsigned int store_evtchn, 
+                     unsigned long *store_mfn, unsigned int console_evtchn,
+                    unsigned long *console_mfn);
 
 int xc_linux_build(int xc_handle,
                    uint32_t domid,
                    const char *image_name,
                    const char *ramdisk_name,
                    const char *cmdline,
-                   unsigned int control_evtchn,
                    unsigned long flags,
                    unsigned int vcpus,
                    unsigned int store_evtchn,
-                   unsigned long *store_mfn);
+                   unsigned long *store_mfn,
+                   unsigned int console_evtchn,
+                   unsigned long *console_mfn);
 
 struct mem_map;
 int xc_vmx_build(int xc_handle,
@@ -63,4 +66,4 @@
                  unsigned int store_evtchn,
                  unsigned long *store_mfn);
 
-#endif
+#endif // XENGUEST_H
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c  Thu Sep  8 15:18:40 2005
+++ b/tools/libxc/xg_private.c  Fri Sep  9 16:30:54 2005
@@ -5,6 +5,7 @@
  */
 
 #include <stdlib.h>
+#include <unistd.h>
 #include <zlib.h>
 
 #include "xg_private.h"
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/misc/cpuperf/cpuperf.c
--- a/tools/misc/cpuperf/cpuperf.c      Thu Sep  8 15:18:40 2005
+++ b/tools/misc/cpuperf/cpuperf.c      Fri Sep  9 16:30:54 2005
@@ -243,16 +243,12 @@
     }
 
     if (read) {
-        while((cpu_mask&1)) {
-            int i;
-            for (i=0x300;i<0x312;i++) {
-                printf("%010llu ",cpus_rdmsr( cpu_mask, i ) );
-            }
-            printf("\n");
-            cpu_mask>>=1;
-        }
+        int i;
+        for (i=0x300;i<0x312;i++)
+            printf("%010llu ",cpus_rdmsr( cpu_mask, i ) );
+        printf("\n");
         exit(1);
-    } 
+    }
     
     if (!escr) {
         fprintf(stderr, "Need an ESCR.\n");
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/misc/mbootpack/Makefile
--- a/tools/misc/mbootpack/Makefile     Thu Sep  8 15:18:40 2005
+++ b/tools/misc/mbootpack/Makefile     Fri Sep  9 16:30:54 2005
@@ -20,8 +20,7 @@
 INCS   := -I. -I-
 DEFS   := 
 LDFLAGS        := 
-CC     := gcc
-CFLAGS         := -Wall -Wpointer-arith -Wcast-qual -Wno-unused -Wno-format
+CFLAGS := -Wall -Wpointer-arith -Wcast-qual -Wno-unused -Wno-format
 CFLAGS += -Wmissing-prototypes
 #CFLAGS        += -pipe -g -O0 -Wcast-align
 CFLAGS += -pipe -O3 
@@ -34,7 +33,7 @@
 DEPS     = .*.d
 
 mbootpack: $(OBJS)
-       $(CC) -o $@ $(filter-out %.a, $^) $(LDFLAGS)
+       $(HOSTCC) -o $@ $(filter-out %.a, $^) $(LDFLAGS)
 
 clean:
        $(RM) mbootpack *.o $(DEPS) bootsect setup bzimage_header.c bin2c
@@ -48,7 +47,7 @@
        $(LD) -m elf_i386 -Ttext 0x0 -s --oformat binary setup.o -o $@
 
 bin2c: bin2c.o 
-       $(CC) -o $@ $^ 
+       $(HOSTCC) -o $@ $^ 
 
 bzimage_header.c: bootsect setup bin2c
        ./bin2c -n 8 -b1 -a bzimage_bootsect bootsect > bzimage_header.c
@@ -58,10 +57,10 @@
        @
 
 %.o: %.S
-       $(CC) $(DEPFLAGS) $(CFLAGS) $(INCS) $(DEFS) -c $< -o $@
+       $(HOSTCC) $(DEPFLAGS) $(CFLAGS) $(INCS) $(DEFS) -c $< -o $@
 
 %.o: %.c
-       $(CC) $(DEPFLAGS) $(CFLAGS) $(INCS) $(DEFS) -c $< -o $@
+       $(HOSTCC) $(DEPFLAGS) $(CFLAGS) $(INCS) $(DEFS) -c $< -o $@
 
 .PHONY: all clean gdb
 .PRECIOUS: $(OBJS) $(OBJS:.o=.c) $(DEPS)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/misc/mbootpack/buildimage.c
--- a/tools/misc/mbootpack/buildimage.c Thu Sep  8 15:18:40 2005
+++ b/tools/misc/mbootpack/buildimage.c Fri Sep  9 16:30:54 2005
@@ -42,6 +42,7 @@
 
 #include "mbootpack.h"
 #include "mb_header.h"
+
 
 /*  We will build an image that a bzImage-capable bootloader will load like 
  *  this:
@@ -105,8 +106,8 @@
     section_t *s;
 
     /* Patch the kernel and mbi addresses into the setup code */
-    *(address_t *)(bzimage_setup + BZ_ENTRY_OFFSET) = entry;
-    *(address_t *)(bzimage_setup + BZ_MBI_OFFSET) = mbi;
+    *(address_t *)(bzimage_setup + BZ_ENTRY_OFFSET) = eswap(entry);
+    *(address_t *)(bzimage_setup + BZ_MBI_OFFSET) = eswap(mbi);
     if (!quiet) printf("Kernel entry is %p, MBI is %p.\n", entry, mbi);
 
     /* Write out header and trampoline */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/misc/mbootpack/mbootpack.c
--- a/tools/misc/mbootpack/mbootpack.c  Thu Sep  8 15:18:40 2005
+++ b/tools/misc/mbootpack/mbootpack.c  Fri Sep  9 16:30:54 2005
@@ -252,20 +252,21 @@
     for (i = 0; i <= MIN(len - 12, MULTIBOOT_SEARCH - 12); i += 4)
     {
         mbh = (struct multiboot_header *)(headerbuf + i);
-        if (mbh->magic != MULTIBOOT_MAGIC 
-            || ((mbh->magic+mbh->flags+mbh->checksum) & 0xffffffff))
+        if (eswap(mbh->magic) != MULTIBOOT_MAGIC 
+            || ((eswap(mbh->magic)+eswap(mbh->flags)+eswap(mbh->checksum)) 
+                               & 0xffffffff))
         {
             /* Not a multiboot header */
             continue;
         }
-        if (mbh->flags & MULTIBOOT_UNSUPPORTED) {
+        if (eswap(mbh->flags) & MULTIBOOT_UNSUPPORTED) {
             /* Requires options we don't support */
             printf("Fatal: found a multiboot header, but it "
                     "requires multiboot options that I\n"
                     "don't understand.  Sorry.\n");
             exit(1);
         } 
-        if (mbh->flags & MULTIBOOT_VIDEO_MODE) { 
+        if (eswap(mbh->flags) & MULTIBOOT_VIDEO_MODE) { 
             /* Asked for screen mode information */
             /* XXX carry on regardless */
             printf("Warning: found a multiboot header which asks "
@@ -275,22 +276,22 @@
         }
         /* This kernel will do: place and load it */
 
-        if (mbh->flags & MULTIBOOT_AOUT_KLUDGE) {
+        if (eswap(mbh->flags) & MULTIBOOT_AOUT_KLUDGE) {
 
             /* Load using the offsets in the multiboot header */
             if(!quiet) 
                 printf("Loading %s using multiboot header.\n", filename);
 
             /* How much is there? */
-            start = mbh->load_addr;            
-            if (mbh->load_end_addr != 0) 
-                loadsize = mbh->load_end_addr - mbh->load_addr;
+            start = eswap(mbh->load_addr);            
+            if (eswap(mbh->load_end_addr) != 0) 
+                loadsize = eswap(mbh->load_end_addr) - eswap(mbh->load_addr);
             else 
                 loadsize = sb.st_size;
             
             /* How much memory will it take up? */ 
-            if (mbh->bss_end_addr != 0)
-                size = mbh->bss_end_addr - mbh->load_addr;
+            if (eswap(mbh->bss_end_addr) != 0)
+                size = eswap(mbh->bss_end_addr) - eswap(mbh->load_addr);
             else
                 size = loadsize;
             
@@ -335,32 +336,34 @@
             
             /* Done. */
             if (!quiet) printf("Loaded kernel from %s\n", filename);
-            return mbh->entry_addr;
+            return eswap(mbh->entry_addr);
             
         } else {
 
             /* Now look for an ELF32 header */    
             ehdr = (Elf32_Ehdr *)headerbuf;
-            if (*(unsigned long *)ehdr != 0x464c457f 
+            if (*(unsigned long *)ehdr != eswap(0x464c457f)
                 || ehdr->e_ident[EI_DATA] != ELFDATA2LSB
                 || ehdr->e_ident[EI_CLASS] != ELFCLASS32
-                || ehdr->e_machine != EM_386)
+                || eswap(ehdr->e_machine) != EM_386)
             {
                 printf("Fatal: kernel has neither ELF32/x86 nor multiboot load"
                        " headers.\n");
                 exit(1);
             }
-            if (ehdr->e_phoff + ehdr->e_phnum*sizeof(*phdr) > HEADERBUF_SIZE) {
+            if (eswap(ehdr->e_phoff) + eswap(ehdr->e_phnum)*sizeof(*phdr) 
+                               > HEADERBUF_SIZE) {
                 /* Don't expect this will happen with sane kernels */
                 printf("Fatal: too much ELF for me.  Try increasing "
                        "HEADERBUF_SIZE in mbootpack.\n");
                 exit(1);
             }
-            if (ehdr->e_phoff + ehdr->e_phnum*sizeof (*phdr) > len) {
+            if (eswap(ehdr->e_phoff) + eswap(ehdr->e_phnum)*sizeof (*phdr) 
+                               > len) {
                 printf("Fatal: malformed ELF header overruns EOF.\n");
                 exit(1);
             }
-            if (ehdr->e_phnum <= 0) {
+            if (eswap(ehdr->e_phnum) <= 0) {
                 printf("Fatal: ELF kernel has no program headers.\n");
                 exit(1);
             }
@@ -368,22 +371,22 @@
             if(!quiet) 
                 printf("Loading %s using ELF header.\n", filename);
 
-            if (ehdr->e_type != ET_EXEC 
-                || ehdr->e_version != EV_CURRENT
-                || ehdr->e_phentsize != sizeof (Elf32_Phdr)) {
+            if (eswap(ehdr->e_type) != ET_EXEC 
+                || eswap(ehdr->e_version) != EV_CURRENT
+                || eswap(ehdr->e_phentsize) != sizeof (Elf32_Phdr)) {
                 printf("Warning: funny-looking ELF header.\n");
             }
-            phdr = (Elf32_Phdr *)(headerbuf + ehdr->e_phoff);
+            phdr = (Elf32_Phdr *)(headerbuf + eswap(ehdr->e_phoff));
 
             /* Obey the program headers to load the kernel */
-            for(i = 0; i < ehdr->e_phnum; i++) {
-
-                start = phdr[i].p_paddr;
-                size = phdr[i].p_memsz;
-                if (phdr[i].p_type != PT_LOAD) 
+            for(i = 0; i < eswap(ehdr->e_phnum); i++) {
+
+                start = eswap(phdr[i].p_paddr);
+                size = eswap(phdr[i].p_memsz);
+                if (eswap(phdr[i].p_type) != PT_LOAD) 
                     loadsize = 0;
                 else 
-                    loadsize = MIN((long int)phdr[i].p_filesz, size);
+                    loadsize = MIN((long int)eswap(phdr[i].p_filesz), size);
 
                 if ((buffer = malloc(size)) == NULL) {
                     printf("Fatal: malloc() for kernel load failed: %s\n",
@@ -396,7 +399,7 @@
 
                 /* Load section from file */ 
                 if (loadsize > 0) {
-                    if (fseek(fp, phdr[i].p_offset, SEEK_SET) != 0) {
+                    if (fseek(fp, eswap(phdr[i].p_offset), SEEK_SET) != 0) {
                         printf("Fatal: seek failed in %s\n",
                                 strerror(errno));
                         exit(1);
@@ -452,7 +455,7 @@
          
             /* Done! */
             if (!quiet) printf("Loaded kernel from %s\n", filename);
-            return ehdr->e_entry;
+            return eswap(ehdr->e_entry);
         }
 
     }
@@ -568,12 +571,12 @@
     /* Command line */
     p = (char *)(mbi + 1);
     sprintf(p, "%s %s", imagename, command_line);
-    mbi->cmdline = ((address_t)p) + mbi_reloc_offset;
+    mbi->cmdline = eswap(((address_t)p) + mbi_reloc_offset);
     p += command_line_len;
 
     /* Bootloader ID */
     sprintf(p, version_string);
-    mbi->boot_loader_name = ((address_t)p) + mbi_reloc_offset;
+    mbi->boot_loader_name = eswap(((address_t)p) + mbi_reloc_offset);
     p += strlen(version_string) + 1;
 
     /* Next is space for the module command lines */
@@ -582,17 +585,17 @@
     /* Last come the module info structs */
     modp = (struct mod_list *)
         ((((address_t)p + mod_command_line_space) + 3) & ~3);
-    mbi->mods_count = modules;
-    mbi->mods_addr = ((address_t)modp) + mbi_reloc_offset;
+    mbi->mods_count = eswap(modules);
+    mbi->mods_addr = eswap(((address_t)modp) + mbi_reloc_offset);
 
     /* Memory information will be added at boot time, by setup.S 
      * or trampoline.S. */
-    mbi->flags = MB_INFO_CMDLINE | MB_INFO_BOOT_LOADER_NAME;
+    mbi->flags = eswap(MB_INFO_CMDLINE | MB_INFO_BOOT_LOADER_NAME);
 
 
     /* Load the modules */
     if (modules) {
-        mbi->flags |= MB_INFO_MODS;
+        mbi->flags = eswap(eswap(mbi->flags) | MB_INFO_MODS);
                 
         /* Go back and parse the module command lines */
         optind = opterr = 1;
@@ -652,10 +655,10 @@
             if (p != NULL) *p = ' ';
 
             /* Fill in the module info struct */
-            modp->mod_start = start;
-            modp->mod_end = start + size;
-            modp->cmdline = (address_t)mod_clp + mbi_reloc_offset;
-            modp->pad = 0;
+            modp->mod_start = eswap(start);
+            modp->mod_end = eswap(start + size);
+            modp->cmdline = eswap((address_t)mod_clp + mbi_reloc_offset);
+            modp->pad = eswap(0);
             modp++;
 
             /* Store the module command line */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/misc/mbootpack/mbootpack.h
--- a/tools/misc/mbootpack/mbootpack.h  Thu Sep  8 15:18:40 2005
+++ b/tools/misc/mbootpack/mbootpack.h  Fri Sep  9 16:30:54 2005
@@ -31,6 +31,24 @@
 
 #undef NDEBUG
 #include <stdio.h>
+
+#include <endian.h>
+#include <byteswap.h>
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define eswap(x) (x)
+#else 
+#define eswap(x)                                               \
+        ({                                                      \
+               typeof(x) y = (x);                              \
+               switch(sizeof(y))                               \
+               {                                               \
+               case 2: y = __bswap_16(y); break;               \
+               case 4: y = __bswap_32(y); break;               \
+               case 8: y = __bswap_64(y); break;               \
+               }                                               \
+               y;                                              \
+        })     
+#endif                 
 
 /* Flags */
 extern int quiet;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/misc/xend
--- a/tools/misc/xend   Thu Sep  8 15:18:40 2005
+++ b/tools/misc/xend   Fri Sep  9 16:30:54 2005
@@ -25,11 +25,6 @@
 import signal
 import time
 import commands
-
-XCS_PATH    = "/var/lib/xen/xcs_socket"
-XCS_EXEC    = "/usr/sbin/xcs"
-XCS_PIDFILE = "/var/run/xcs.pid"
-XCS_ARGS    = (XCS_EXEC, "-p", XCS_PIDFILE)
 
 # add fallback path for non-native python path installs if needed
 sys.path.append('/usr/lib/python')
@@ -70,52 +65,6 @@
         hline()
         raise CheckError("invalid user")
 
-def xcs_running():
-    """ See if the control switch is running.
-    """        
-    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-    try:
-        s.connect( (XCS_PATH) )
-        s.close()
-    except:
-        try:
-            os.remove(XCS_PIDFILE)
-        except:
-            pass
-       return 0
-    return 1
-    
-def start_xcs():
-    if (not xcs_running()):
-        if os.fork() == 0 :
-            if not os.path.isdir(os.path.dirname(XCS_PATH)):
-                os.makedirs(os.path.dirname(XCS_PATH))
-            try:
-                os.execvp(XCS_EXEC, XCS_ARGS)
-            except:
-                hline()
-                msg("Tried to start xcs, but failed. Is it installed?")
-                hline()
-                raise CheckError("couldn't start xcs")
-        for n in range(10) :
-            if (xcs_running()):
-                break
-            time.sleep(0.1)
-        else :
-                hline()
-                msg("Failed to start the control interface switch.")
-                hline()
-                raise CheckError("xcs not running")
-            
-def stop_xcs():
-    try:
-       xcs_pidfile = open(XCS_PIDFILE)
-        xcs_pid = int(xcs_pidfile.read().strip())
-        os.kill(xcs_pid, signal.SIGTERM)
-        xcs_pidfile.close()
-    except:
-       return    
-
 def start_xenstored():
     XENSTORED_TRACE = os.getenv("XENSTORED_TRACE")
     cmd = "/usr/sbin/xenstored --pid-file=/var/run/xenstore.pid"
@@ -141,21 +90,16 @@
         pid, status = os.wait()
         return status >> 8
     elif sys.argv[1] == 'start':
-        start_xcs()
         start_xenstored()
         start_consoled()
         return daemon.start()
     elif sys.argv[1] == 'trace_start':
-        start_xcs()
         start_xenstored()
         start_consoled()
         return daemon.start(trace=1)
     elif sys.argv[1] == 'stop':
-        stop_xcs()
         return daemon.stop()
     elif sys.argv[1] == 'restart':
-        stop_xcs()
-        start_xcs()
         start_xenstored()
         start_consoled()
         return daemon.stop() or daemon.start()
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/setup.py
--- a/tools/python/setup.py     Thu Sep  8 15:18:40 2005
+++ b/tools/python/setup.py     Fri Sep  9 16:30:54 2005
@@ -7,10 +7,8 @@
 extra_compile_args  = [ "-fno-strict-aliasing", "-Wall", "-Werror" ]
 
 
-include_dirs = [ XEN_ROOT + "/tools/python/xen/lowlevel/xu",
-                 XEN_ROOT + "/tools/libxc",
+include_dirs = [ XEN_ROOT + "/tools/libxc",
                  XEN_ROOT + "/tools/xenstore",
-                 XEN_ROOT + "/tools/xcs",
                  ]
 
 library_dirs = [ XEN_ROOT + "/tools/libxc",
@@ -25,13 +23,6 @@
                library_dirs       = library_dirs,
                libraries          = libraries,
                sources            = [ "xen/lowlevel/xc/xc.c" ])
-
-xu = Extension("xu",
-               extra_compile_args = extra_compile_args,
-               include_dirs       = include_dirs + [ "xen/lowlevel/xu" ],
-               library_dirs       = library_dirs,
-               libraries          = libraries,
-               sources            = [ "xen/lowlevel/xu/xu.c" ])
 
 xs = Extension("xs",
                extra_compile_args = extra_compile_args,
@@ -51,10 +42,10 @@
                          'xen.xend.xenstore',
                          'xen.xm',
                          'xen.web',
-                                                'xen.sv'
+                         'xen.sv'
                          ],
       ext_package = "xen.lowlevel",
-      ext_modules = [ xc, xu, xs ]
+      ext_modules = [ xc, xs ]
       )
 
 os.chdir('logging')
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/lowlevel/xc/xc.c Fri Sep  9 16:30:54 2005
@@ -268,25 +268,33 @@
     u32 dom;
     char *image, *ramdisk = NULL, *cmdline = "";
     int flags = 0, vcpus = 1;
-    int control_evtchn, store_evtchn;
+    int store_evtchn, console_evtchn;
     unsigned long store_mfn = 0;
-
-    static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn", 
-                                "image", "ramdisk", "cmdline", "flags",
+    unsigned long console_mfn = 0;
+
+    static char *kwd_list[] = { "dom", "store_evtchn", 
+                                "console_evtchn", "image", 
+                               /* optional */
+                               "ramdisk", "cmdline", "flags",
                                "vcpus", NULL };
 
     if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiis|ssii", kwd_list,
-                                      &dom, &control_evtchn, &store_evtchn,
-                                      &image, &ramdisk, &cmdline, &flags,
+                                      &dom, &store_evtchn,
+                                     &console_evtchn, &image, 
+                                     /* optional */
+                                     &ramdisk, &cmdline, &flags,
                                       &vcpus) )
         return NULL;
 
     if ( xc_linux_build(xc->xc_handle, dom, image,
-                        ramdisk, cmdline, control_evtchn, flags, vcpus,
-                        store_evtchn, &store_mfn) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
+                        ramdisk, cmdline, flags, vcpus,
+                        store_evtchn, &store_mfn, 
+                       console_evtchn, &console_mfn) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    return Py_BuildValue("{s:i,s:i}", 
+                        "store_mfn", store_mfn,
+                        "console_mfn", console_mfn);
 }
 
 static PyObject *pyxc_vmx_build(PyObject *self,
@@ -682,6 +690,8 @@
 {
     XcObject *xc = (XcObject *)self;
     xc_physinfo_t info;
+    char cpu_cap[128], *p=cpu_cap, *q=cpu_cap;
+    int i;
     
     if ( !PyArg_ParseTuple(args, "") )
         return NULL;
@@ -689,15 +699,72 @@
     if ( xc_physinfo(xc->xc_handle, &info) != 0 )
         return PyErr_SetFromErrno(xc_error);
 
-    return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:i}",
+    *q=0;
+    for(i=0;i<sizeof(info.hw_cap)/4;i++)
+    {
+        p+=sprintf(p,"%08x:",info.hw_cap[i]);
+        if(info.hw_cap[i])
+           q=p;
+    }
+    if(q>cpu_cap)
+        *(q-1)=0;
+
+    return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:i,s:s}",
                          "threads_per_core", info.threads_per_core,
                          "cores_per_socket", info.cores_per_socket,
                          "sockets_per_node", info.sockets_per_node,
                          "nr_nodes",         info.nr_nodes,
                          "total_pages",      info.total_pages,
                          "free_pages",       info.free_pages,
-                         "cpu_khz",          info.cpu_khz);
-}
+                         "cpu_khz",          info.cpu_khz,
+                         "hw_caps",          cpu_cap);
+}
+
+static PyObject *pyxc_xeninfo(PyObject *self,
+                              PyObject *args,
+                              PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    xen_extraversion_t xen_extra;
+    xen_compile_info_t xen_cc;
+    xen_changeset_info_t xen_chgset;
+    xen_capabilities_info_t xen_caps;
+    xen_parameters_info_t xen_parms;
+    long xen_version;
+    char str[128];
+
+    xen_version = xc_version(xc->xc_handle, XENVER_version, NULL);
+
+    if ( xc_version(xc->xc_handle, XENVER_extraversion, &xen_extra) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    if ( xc_version(xc->xc_handle, XENVER_compile_info, &xen_cc) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    if ( xc_version(xc->xc_handle, XENVER_changeset, &xen_chgset) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    if ( xc_version(xc->xc_handle, XENVER_capabilities, &xen_caps) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    if ( xc_version(xc->xc_handle, XENVER_parameters, &xen_parms) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    sprintf(str,"virt_start=0x%lx",xen_parms.virt_start);
+
+    return Py_BuildValue("{s:i,s:i,s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s}",
+                         "xen_major", xen_version >> 16,
+                         "xen_minor", (xen_version & 0xffff),
+                         "xen_extra", xen_extra,
+                         "xen_caps",  xen_caps.caps,
+                         "xen_params", str,
+                         "xen_changeset", xen_chgset,
+                         "cc_compiler", xen_cc.compiler,
+                         "cc_compile_by", xen_cc.compile_by,
+                         "cc_compile_domain", xen_cc.compile_domain,
+                         "cc_compile_date", xen_cc.compile_date);
+}
+
 
 static PyObject *pyxc_sedf_domain_set(PyObject *self,
                                          PyObject *args,
@@ -800,14 +867,21 @@
 
     u32 dom;
     unsigned long mem_kb;
-
-    static char *kwd_list[] = { "dom", "mem_kb", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, 
-                                      &dom, &mem_kb) )
-        return NULL;
-
-    if ( xc_domain_memory_increase_reservation(xc->xc_handle, dom, mem_kb) )
+    unsigned int extent_order = 0 , address_bits = 0;
+    unsigned long nr_extents;
+
+    static char *kwd_list[] = { "dom", "mem_kb", "extent_order", 
"address_bits", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "il|ii", kwd_list, 
+                                      &dom, &mem_kb, &extent_order, 
&address_bits) )
+        return NULL;
+
+    /* round down to nearest power of 2. Assume callers using extent_order>0
+       know what they are doing */
+    nr_extents = (mem_kb / (XC_PAGE_SIZE/1024)) >> extent_order;
+    if ( xc_domain_memory_increase_reservation(xc->xc_handle, dom, 
+                                              nr_extents, extent_order, 
+                                              address_bits, NULL) )
         return PyErr_SetFromErrno(xc_error);
     
     Py_INCREF(zero);
@@ -1081,6 +1155,13 @@
       "Returns [dict]: information about the hardware"
       "        [None]: on failure.\n" },
 
+    { "xeninfo",
+      (PyCFunction)pyxc_xeninfo,
+      METH_VARARGS, "\n"
+      "Get information about the Xen host\n"
+      "Returns [dict]: information about Xen"
+      "        [None]: on failure.\n" },
+
     { "shadow_control", 
       (PyCFunction)pyxc_shadow_control, 
       METH_VARARGS | METH_KEYWORDS, "\n"
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/lowlevel/xs/xs.c
--- a/tools/python/xen/lowlevel/xs/xs.c Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/lowlevel/xs/xs.c Fri Sep  9 16:30:54 2005
@@ -15,6 +15,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * Copyright (C) 2005 Mike Wray Hewlett-Packard
+ * Copyright (C) 2005 Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
  *
  */
 
@@ -45,6 +46,7 @@
 typedef struct XsHandle {
     PyObject_HEAD;
     struct xs_handle *xh;
+    PyObject *watches;
 } XsHandle;
 
 static inline struct xs_handle *xshandle(PyObject *self)
@@ -87,19 +89,21 @@
     PyObject *val = NULL;
 
     if (!xh)
-       goto exit;
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
                                      &path))
         goto exit;
+    Py_BEGIN_ALLOW_THREADS
     xsval = xs_read(xh, path, &xsval_n);
-    if (!xsval) {
-        val = pyvalue_int(0);
+    Py_END_ALLOW_THREADS
+    if (!xsval) {
+        PyErr_SetFromErrno(PyExc_RuntimeError);
         goto exit;
     }
     val = PyString_FromStringAndSize(xsval, xsval_n);
  exit:
     if (xsval)
-       free(xsval);
+        free(xsval);
     return val;
 }
 
@@ -110,7 +114,7 @@
        " create [int]    : create flag, default 0.\n"          \
        " excl   [int]    : exclusive flag, default 0.\n"       \
        "\n"                                                    \
-       "Returns: [int] 0 on success.\n"                        \
+       "Returns None on success.\n"                            \
        "Raises RuntimeError on error.\n"                       \
        "\n"
 
@@ -130,16 +134,23 @@
     int xsval = 0;
 
     if (!xh)
-       goto exit;
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
                                      &path, &data, &data_n, &create, &excl))
         goto exit;
     if (create)
-       flags |= O_CREAT;
+        flags |= O_CREAT;
     if (excl)
-       flags |= O_EXCL;
+        flags |= O_EXCL;
+    Py_BEGIN_ALLOW_THREADS
     xsval = xs_write(xh, path, data, data_n, flags);
-    val = pyvalue_int(xsval);
+    Py_END_ALLOW_THREADS
+    if (!xsval) {
+        PyErr_SetFromErrno(PyExc_RuntimeError);
+        goto exit;
+    }
+    Py_INCREF(Py_None);
+    val = Py_None;
  exit:
     return val;
 }
@@ -165,12 +176,14 @@
     int i;
 
     if (!xh)
-       goto exit;
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
         goto exit;
+    Py_BEGIN_ALLOW_THREADS
     xsval = xs_directory(xh, path, &xsval_n);
-    if (!xsval) {
-        val = pyvalue_int(0);
+    Py_END_ALLOW_THREADS
+    if (!xsval) {
+        PyErr_SetFromErrno(PyExc_RuntimeError);
         goto exit;
     }
     val = PyList_New(xsval_n);
@@ -184,7 +197,7 @@
        "Make a directory.\n"                                   \
        " path [string]: path to directory to create.\n"        \
        "\n"                                                    \
-       "Returns: [int] 0 on success.\n"                        \
+       "Returns None on success.\n"                            \
        "Raises RuntimeError on error.\n"                       \
        "\n"
 
@@ -199,11 +212,18 @@
     int xsval = 0;
 
     if (!xh)
-       goto exit;
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
         goto exit;
+    Py_BEGIN_ALLOW_THREADS
     xsval = xs_mkdir(xh, path);
-    val = pyvalue_int(xsval);
+    Py_END_ALLOW_THREADS
+    if (!xsval) {
+        PyErr_SetFromErrno(PyExc_RuntimeError);
+        goto exit;
+    }
+    Py_INCREF(Py_None);
+    val = Py_None;
  exit:
     return val;
 }
@@ -212,7 +232,7 @@
        "Remove a path.\n"                      \
        " path [string] : path to remove\n"     \
        "\n"                                    \
-       "Returns: [int] 0 on success.\n"        \
+       "Returns None on success.\n"            \
        "Raises RuntimeError on error.\n"       \
        "\n"
 
@@ -227,11 +247,18 @@
     int xsval = 0;
 
     if (!xh)
-       goto exit;
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
         goto exit;
+    Py_BEGIN_ALLOW_THREADS
     xsval = xs_rm(xh, path);
-    val = pyvalue_int(xsval);
+    Py_END_ALLOW_THREADS
+    if (!xsval) {
+        PyErr_SetFromErrno(PyExc_RuntimeError);
+        goto exit;
+    }
+    Py_INCREF(Py_None);
+    val = Py_None;
  exit:
     return val;
 }
@@ -245,7 +272,7 @@
        "\n"
 
 static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
-                                     PyObject *kwds)
+                                      PyObject *kwds)
 {
     static char *kwd_spec[] = { "path", NULL };
     static char *arg_spec = "s|";
@@ -258,10 +285,12 @@
     int i;
 
     if (!xh)
-       goto exit;
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
         goto exit;
+    Py_BEGIN_ALLOW_THREADS
     perms = xs_get_permissions(xh, path, &perms_n);
+    Py_END_ALLOW_THREADS
     if (!perms) {
         PyErr_SetFromErrno(PyExc_RuntimeError);
         goto exit;
@@ -283,12 +312,12 @@
        " path  [string] : xenstore path.\n"    \
        " perms          : permissions.\n"      \
        "\n"                                    \
-       "Returns: [int] 0 on success.\n"        \
+       "Returns None on success.\n"            \
        "Raises RuntimeError on error.\n"       \
        "\n"
 
 static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
-                                     PyObject *kwds)
+                                      PyObject *kwds)
 {
     static char *kwd_spec[] = { "path", "perms", NULL };
     static char *arg_spec = "sO";
@@ -321,7 +350,7 @@
     }
     tuple0 = PyTuple_New(0);
     if (!tuple0)
-       goto exit;
+        goto exit;
     for (i = 0; i < xsperms_n; i++) {
         /* Domain the permissions apply to. */
         int dom = 0;
@@ -329,20 +358,27 @@
         int p_read = 0, p_write = 0;
         PyObject *p = PyList_GetItem(perms, i);
         if (!PyArg_ParseTupleAndKeywords(tuple0, p, perm_spec, perm_names,
-                                        &dom, &p_read, &p_write))
+                                         &dom, &p_read, &p_write))
             goto exit;
         xsperms[i].id = dom;
         if (p_read)
-           xsperms[i].perms |= XS_PERM_READ;
+            xsperms[i].perms |= XS_PERM_READ;
         if (p_write)
-           xsperms[i].perms |= XS_PERM_WRITE;
-    }
+            xsperms[i].perms |= XS_PERM_WRITE;
+    }
+    Py_BEGIN_ALLOW_THREADS
     xsval = xs_set_permissions(xh, path, xsperms, xsperms_n);
-    val = pyvalue_int(xsval);
+    Py_END_ALLOW_THREADS
+    if (!xsval) {
+        PyErr_SetFromErrno(PyExc_RuntimeError);
+        goto exit;
+    }
+    Py_INCREF(Py_None);
+    val = Py_None;
  exit:
     Py_XDECREF(tuple0);
     if (xsperms)
-       free(xsperms);
+        free(xsperms);
     return val;
 }
 
@@ -351,28 +387,53 @@
        " path     [string] : xenstore path.\n"                         \
        " token    [string] : returned in watch notification.\n"        \
        "\n"                                                            \
-       "Returns: [int] 0 on success.\n"                                \
+       "Returns None on success.\n"                                    \
        "Raises RuntimeError on error.\n"                               \
        "\n"
 
+/* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
+#define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
+
 static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
 {
     static char *kwd_spec[] = { "path", "token", NULL };
-    static char *arg_spec = "s|is";
-    char *path = NULL;
-    char *token = "";
-
-    struct xs_handle *xh = xshandle(self);
-    PyObject *val = NULL;
-    int xsval = 0;
-
-    if (!xh)
-       goto exit;
+    static char *arg_spec = "sO";
+    char *path = NULL;
+    PyObject *token;
+    char token_str[MAX_STRLEN(unsigned long) + 1];
+    int i;
+
+    XsHandle *xsh = (XsHandle *)self;
+    struct xs_handle *xh = xshandle(self);
+    PyObject *val = NULL;
+    int xsval = 0;
+
+    if (!xh)
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, 
                                      &path, &token))
         goto exit;
-    xsval = xs_watch(xh, path, token);
-    val = pyvalue_int(xsval);
+    Py_INCREF(token);
+    sprintf(token_str, "%li", (unsigned long)token);
+    Py_BEGIN_ALLOW_THREADS
+    xsval = xs_watch(xh, path, token_str);
+    Py_END_ALLOW_THREADS
+    if (!xsval) {
+        PyErr_SetFromErrno(PyExc_RuntimeError);
+        Py_DECREF(token);
+        goto exit;
+    }
+
+    for (i = 0; i < PyList_Size(xsh->watches); i++) {
+        if (PyList_GetItem(xsh->watches, i) == Py_None) {
+            PyList_SetItem(xsh->watches, i, token);
+            break;
+        }
+    }
+    if (i == PyList_Size(xsh->watches))
+        PyList_Append(xsh->watches, token);
+    Py_INCREF(Py_None);
+    val = Py_None;
  exit:
     return val;
 }
@@ -388,29 +449,46 @@
        "\n"
 
 static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
-                                PyObject *kwds)
+                                 PyObject *kwds)
 {
     static char *kwd_spec[] = { NULL };
     static char *arg_spec = "";
 
+    XsHandle *xsh = (XsHandle *)self;
     struct xs_handle *xh = xshandle(self);
     PyObject *val = NULL;
     char **xsval = NULL;
-
-    if (!xh)
-       goto exit;
+    PyObject *token;
+    int i;
+
+    if (!xh)
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
         goto exit;
+    Py_BEGIN_ALLOW_THREADS
     xsval = xs_read_watch(xh);
-    if (!xsval) {
-            val = PyErr_SetFromErrno(PyExc_RuntimeError);
-            goto exit;
+    Py_END_ALLOW_THREADS
+    if (!xsval) {
+        PyErr_SetFromErrno(PyExc_RuntimeError);
+        goto exit;
+    }
+    if (sscanf(xsval[1], "%li", (unsigned long *)&token) != 1) {
+        PyErr_SetString(PyExc_RuntimeError, "invalid token");
+        goto exit;
+    }
+    for (i = 0; i < PyList_Size(xsh->watches); i++) {
+        if (token == PyList_GetItem(xsh->watches, i))
+            break;
+    }
+    if (i == PyList_Size(xsh->watches)) {
+        PyErr_SetString(PyExc_RuntimeError, "invalid token");
+        goto exit;
     }
     /* Create tuple (path, token). */
-    val = Py_BuildValue("(ss)", xsval[0], xsval[1]);
+    val = Py_BuildValue("(sO)", xsval[0], token);
  exit:
     if (xsval)
-       free(xsval);
+        free(xsval);
     return val;
 }
 
@@ -418,27 +496,36 @@
        "Acknowledge a watch notification that has been read.\n"        \
        " token [string] : from the watch notification\n"               \
        "\n"                                                            \
-       "Returns: [int] 0 on success.\n"                                \
+       "Returns None on success.\n"                                    \
        "Raises RuntimeError on error.\n"                               \
        "\n"
 
 static PyObject *xspy_acknowledge_watch(PyObject *self, PyObject *args,
-                                       PyObject *kwds)
+                                        PyObject *kwds)
 {
     static char *kwd_spec[] = { "token", NULL };
-    static char *arg_spec = "s";
-    char *token;
-
-    struct xs_handle *xh = xshandle(self);
-    PyObject *val = NULL;
-    int xsval = 0;
-
-    if (!xh)
-       goto exit;
+    static char *arg_spec = "O";
+    PyObject *token;
+    char token_str[MAX_STRLEN(unsigned long) + 1];
+
+    struct xs_handle *xh = xshandle(self);
+    PyObject *val = NULL;
+    int xsval = 0;
+
+    if (!xh)
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &token))
         goto exit;
-    xsval = xs_acknowledge_watch(xh, token);
-    val = pyvalue_int(xsval);
+    sprintf(token_str, "%li", (unsigned long)token);
+    Py_BEGIN_ALLOW_THREADS
+    xsval = xs_acknowledge_watch(xh, token_str);
+    Py_END_ALLOW_THREADS
+    if (!xsval) {
+        PyErr_SetFromErrno(PyExc_RuntimeError);
+        goto exit;
+    }
+    Py_INCREF(Py_None);
+    val = Py_None;
  exit:
     return val;
 }
@@ -448,28 +535,46 @@
        " path  [string] : xenstore path.\n"            \
        " token [string] : token from the watch.\n"     \
        "\n"                                            \
-       "Returns: [int] 0 on success.\n"                \
+       "Returns None on success.\n"                    \
        "Raises RuntimeError on error.\n"               \
        "\n"
 
 static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
 {
     static char *kwd_spec[] = { "path", "token", NULL };
-    static char *arg_spec = "s|s";
-    char *path = NULL;
-    char *token = "";
-
-    struct xs_handle *xh = xshandle(self);
-    PyObject *val = NULL;
-    int xsval = 0;
-
-    if (!xh)
-       goto exit;
+    static char *arg_spec = "sO";
+    char *path = NULL;
+    PyObject *token;
+    char token_str[MAX_STRLEN(unsigned long) + 1];
+    int i;
+
+    XsHandle *xsh = (XsHandle *)self;
+    struct xs_handle *xh = xshandle(self);
+    PyObject *val = NULL;
+    int xsval = 0;
+
+    if (!xh)
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path,
-                                    &token))
-        goto exit;
-    xsval = xs_unwatch(xh, path, token);
-    val = pyvalue_int(xsval);
+                                     &token))
+        goto exit;
+    sprintf(token_str, "%li", (unsigned long)token);
+    Py_BEGIN_ALLOW_THREADS
+    xsval = xs_unwatch(xh, path, token_str);
+    Py_END_ALLOW_THREADS
+    if (!xsval)
+        PyErr_SetFromErrno(PyExc_RuntimeError);
+    else {
+        Py_INCREF(Py_None);
+        val = Py_None;
+    }
+    for (i = 0; i < PyList_Size(xsh->watches); i++) {
+        if (token == PyList_GetItem(xsh->watches, i)) {
+            Py_INCREF(Py_None);
+            PyList_SetItem(xsh->watches, i, Py_None);
+            break;
+        }
+    }
  exit:
     return val;
 }
@@ -479,12 +584,12 @@
        "Only one transaction can be active at a time.\n"       \
        " path [string]: xenstore path.\n"                      \
        "\n"                                                    \
-       "Returns: [int] 0 on success.\n"                        \
+       "Returns None on success.\n"                            \
        "Raises RuntimeError on error.\n"                       \
        "\n"
 
 static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
-                                       PyObject *kwds)
+                                        PyObject *kwds)
 {
     static char *kwd_spec[] = { "path", NULL };
     static char *arg_spec = "s|";
@@ -495,11 +600,18 @@
     int xsval = 0;
 
     if (!xh)
-       goto exit;
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
         goto exit;
+    Py_BEGIN_ALLOW_THREADS
     xsval = xs_transaction_start(xh, path);
-    val = pyvalue_int(xsval);
+    Py_END_ALLOW_THREADS
+    if (!xsval) {
+        PyErr_SetFromErrno(PyExc_RuntimeError);
+        goto exit;
+    }
+    Py_INCREF(Py_None);
+    val = Py_None;
  exit:
     return val;
 }
@@ -509,12 +621,12 @@
        "Attempts to commit the transaction unless abort is true.\n"    \
        " abort [int]: abort flag (default 0).\n"                       \
        "\n"                                                            \
-       "Returns: [int] 0 on success.\n"                                \
+       "Returns None on success.\n"                                    \
        "Raises RuntimeError on error.\n"                               \
        "\n"
 
 static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
-                                     PyObject *kwds)
+                                      PyObject *kwds)
 {
     static char *kwd_spec[] = { "abort", NULL };
     static char *arg_spec = "|i";
@@ -525,11 +637,18 @@
     int xsval = 0;
 
     if (!xh)
-       goto exit;
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &abort))
         goto exit;
+    Py_BEGIN_ALLOW_THREADS
     xsval = xs_transaction_end(xh, abort);
-    val = pyvalue_int(xsval);
+    Py_END_ALLOW_THREADS
+    if (!xsval) {
+        PyErr_SetFromErrno(PyExc_RuntimeError);
+        goto exit;
+    }
+    Py_INCREF(Py_None);
+    val = Py_None;
  exit:
     return val;
 }
@@ -541,12 +660,12 @@
        " port [int]   : port the domain is using for xenstore\n"       \
        " path [string]: path to the domain's data in xenstore\n"       \
        "\n"                                                            \
-       "Returns: [int] 0 on success.\n"                                \
+       "Returns None on success.\n"                                    \
        "Raises RuntimeError on error.\n"                               \
        "\n"
 
 static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
-                                      PyObject *kwds)
+                                       PyObject *kwds)
 {
     static char *kwd_spec[] = { "dom", "page", "port", "path", NULL };
     static char *arg_spec = "iiis|";
@@ -560,12 +679,19 @@
     int xsval = 0;
 
     if (!xh)
-       goto exit;
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
                                      &dom, &page, &port, &path))
         goto exit;
+    Py_BEGIN_ALLOW_THREADS
     xsval = xs_introduce_domain(xh, dom, page, port, path);
-    val = pyvalue_int(xsval);
+    Py_END_ALLOW_THREADS
+    if (!xsval) {
+        PyErr_SetFromErrno(PyExc_RuntimeError);
+        goto exit;
+    }
+    Py_INCREF(Py_None);
+    val = Py_None;
  exit:
     return val;
 }
@@ -575,12 +701,12 @@
        "Unless this is done the domain will not be released.\n"        \
        " dom [int]: domain id\n"                                       \
        "\n"                                                            \
-       "Returns: [int] 0 on success.\n"                                \
+       "Returns None on success.\n"                                    \
        "Raises RuntimeError on error.\n"                               \
        "\n"
 
 static PyObject *xspy_release_domain(PyObject *self, PyObject *args,
-                                    PyObject *kwds)
+                                     PyObject *kwds)
 {
     static char *kwd_spec[] = { "dom", NULL };
     static char *arg_spec = "i|";
@@ -591,12 +717,19 @@
     int xsval = 0;
 
     if (!xh)
-       goto exit;
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
                                      &dom))
         goto exit;
+    Py_BEGIN_ALLOW_THREADS
     xsval = xs_release_domain(xh, dom);
-    val = pyvalue_int(xsval);
+    Py_END_ALLOW_THREADS
+    if (!xsval) {
+        PyErr_SetFromErrno(PyExc_RuntimeError);
+        goto exit;
+    }
+    Py_INCREF(Py_None);
+    val = Py_None;
  exit:
     return val;
 }
@@ -604,7 +737,7 @@
 #define xspy_close_doc "\n"                    \
        "Close the connection to xenstore.\n"   \
        "\n"                                    \
-       "Returns: [int] 0 on success.\n"        \
+       "Returns None on success.\n"            \
        "Raises RuntimeError on error.\n"       \
        "\n"
 
@@ -612,18 +745,25 @@
 {
     static char *kwd_spec[] = { NULL };
     static char *arg_spec = "";
-
-    struct xs_handle *xh = xshandle(self);
-    PyObject *val = NULL;
-    int xsval = 1;
-
-    if (!xh)
-       goto exit;
+    int i;
+
+    XsHandle *xsh = (XsHandle *)self;
+    struct xs_handle *xh = xshandle(self);
+    PyObject *val = NULL;
+
+    if (!xh)
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
         goto exit;
+    for (i = 0; i < PyList_Size(xsh->watches); i++) {
+        /* TODO: xs_unwatch watches */
+        Py_INCREF(Py_None);
+        PyList_SetItem(xsh->watches, i, Py_None);
+    }
     xs_daemon_close(xh);
-    ((XsHandle*)self)->xh = NULL;
-    val = pyvalue_int(xsval);
+    xsh->xh = NULL;
+    Py_INCREF(Py_None);
+    val = Py_None;
  exit:
     return val;
 }
@@ -631,7 +771,7 @@
 #define xspy_shutdown_doc "\n"                 \
        "Shutdown the xenstore daemon.\n"       \
        "\n"                                    \
-       "Returns: [int] 0 on success.\n"        \
+       "Returns None on success.\n"            \
        "Raises RuntimeError on error.\n"       \
        "\n"
 
@@ -645,11 +785,18 @@
     int xsval = 0;
 
     if (!xh)
-       goto exit;
+        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
         goto exit;
+    Py_BEGIN_ALLOW_THREADS
     xsval = xs_shutdown(xh);
-    val = pyvalue_int(xsval);
+    Py_END_ALLOW_THREADS
+    if (!xsval) {
+        PyErr_SetFromErrno(PyExc_RuntimeError);
+        goto exit;
+    }
+    Py_INCREF(Py_None);
+    val = Py_None;
  exit:
     return val;
 }
@@ -750,20 +897,25 @@
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
                                      &readonly))
-        goto exit;
+        return NULL;
 
     xsh = PyObject_New(XsHandle, &xshandle_type);
     if (!xsh)
-       goto exit;
+        return NULL;
+    xsh->watches = PyList_New(0);
+    if (!xsh->watches)
+        goto exit;
     xsh->xh = (readonly ? xs_daemon_open_readonly() : xs_daemon_open());
     if (!xsh->xh) {
-        PyObject_Del(xsh);
-        val = pyvalue_int(0);
+        Py_DECREF(xsh->watches);
+        PyErr_SetFromErrno(PyExc_RuntimeError);
         goto exit;
     }
     val = (PyObject *)xsh;
- exit:
-    return val;
+    return val;
+ exit:
+    PyObject_Del(xsh);
+    return NULL;
 }
 
 static PyMethodDef xs_methods[] = {
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py   Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/XendCheckpoint.py   Fri Sep  9 16:30:54 2005
@@ -34,7 +34,7 @@
         raise XendError(errmsg)
     return buf
 
-def save(xd, fd, dominfo):
+def save(xd, fd, dominfo, live):
     write_exact(fd, SIGNATURE, "could not write guest state file: signature")
 
     config = sxp.to_string(dominfo.sxpr())
@@ -42,8 +42,13 @@
                 "could not write guest state file: config len")
     write_exact(fd, config, "could not write guest state file: config")
 
+    # xc_save takes three customization parameters: maxit, max_f, and flags
+    # the last controls whether or not save is 'live', while the first two
+    # further customize behaviour when 'live' save is enabled. Passing "0"
+    # simply uses the defaults compiled into libxenguest; see the comments 
+    # and/or code in xc_linux_save() for more information. 
     cmd = [PATH_XC_SAVE, str(xc.handle()), str(fd),
-           str(dominfo.id)]
+           str(dominfo.id), "0", "0", str(int(live)) ]
     log.info("[xc_save] " + join(cmd))
     child = xPopen3(cmd, True, -1, [fd, xc.handle()])
     
@@ -51,7 +56,7 @@
     p = select.poll()
     p.register(child.fromchild.fileno())
     p.register(child.childerr.fileno())
-    while True:
+    while True: 
         r = p.poll()
         for (fd, event) in r:
             if not event & select.POLLIN:
@@ -65,15 +70,16 @@
                 if l.rstrip() == "suspend":
                     log.info("suspending %d" % dominfo.id)
                     xd.domain_shutdown(dominfo.id, reason='suspend')
+                    dominfo.state_wait("suspended")
+                    log.info("suspend %d done" % dominfo.id)
                     if dominfo.store_channel:
                         try:
                             dominfo.db.releaseDomain(dominfo.id)
                         except Exception, ex:
-                            log.warning("error in domain release on xenstore: 
%s",
-                                        ex)
+                            log.warning(
+                                "error in domain release on xenstore: %s",
+                                ex)
                             pass
-                    dominfo.state_wait("suspended")
-                    log.info("suspend %d done" % dominfo.id)
                     child.tochild.write("done\n")
                     child.tochild.flush()
         if filter(lambda (fd, event): event & select.POLLHUP, r):
@@ -121,12 +127,18 @@
             "not a valid guest state file: pfn count out of range")
 
     if dominfo.store_channel:
-        evtchn = dominfo.store_channel.port2
+        store_evtchn = dominfo.store_channel.port2
     else:
-        evtchn = 0
+        store_evtchn = 0
+
+    if dominfo.console_channel:
+        console_evtchn = dominfo.console_channel.port2
+    else:
+        console_evtchn = 0
 
     cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd),
-           str(dominfo.id), str(nr_pfns), str(evtchn)]
+           str(dominfo.id), str(nr_pfns),
+           str(store_evtchn), str(console_evtchn)]
     log.info("[xc_restore] " + join(cmd))
     child = xPopen3(cmd, True, -1, [fd, xc.handle()])
     child.tochild.close()
@@ -147,6 +159,7 @@
             if fd == child.fromchild.fileno():
                 l = child.fromchild.readline()
                 while l:
+                    log.info(l.rstrip())
                     m = re.match(r"^(store-mfn) (\d+)\n$", l)
                     if m:
                         if dominfo.store_channel:
@@ -156,7 +169,10 @@
                                                            dominfo.store_mfn,
                                                            
dominfo.store_channel)
                             dominfo.exportToDB(save=True, sync=True)
-                    log.info(l.rstrip())
+                    m = re.match(r"^(console-mfn) (\d+)\n$", l)
+                    if m:
+                        dominfo.console_mfn = int(m.group(2))
+                        dominfo.exportToDB(save=True, sync=True)
                     try:
                         l = child.fromchild.readline()
                     except:
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py       Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/XendDomain.py       Fri Sep  9 16:30:54 2005
@@ -36,7 +36,6 @@
 from xen.xend.XendError import XendError
 from xen.xend.XendLogging import log
 from xen.xend import scheduler
-from xen.xend.server import channel
 from xen.xend.server import relocate
 from xen.xend.uuid import getUuid
 from xen.xend.xenstore import XenNode, DBMap
@@ -67,7 +66,7 @@
         xroot.add_component("xen.xend.XendDomain", self)
         self.domains = XendDomainDict()
         self.dbmap = DBMap(db=XenNode("/domain"))
-        eserver.subscribe('xend.virq', self.onVirq)
+        self.watchReleaseDomain()
         self.initial_refresh()
 
     def list(self):
@@ -75,12 +74,32 @@
 
         @return: domain objects
         """
+        self.refresh()
         return self.domains.values()
-    
-    def onVirq(self, event, val):
-        """Event handler for virq.
-        """
+
+    def list_sorted(self):
+        """Get list of domain objects, sorted by name.
+
+        @return: domain objects
+        """
+        doms = self.list()
+        doms.sort(lambda x, y: cmp(x.name, y.name))
+        return doms
+
+    def list_names(self):
+        """Get list of domain names.
+
+        @return: domain names
+        """
+        doms = self.list_sorted()
+        return map(lambda x: x.name, doms)
+
+    def onReleaseDomain(self):
         self.refresh(cleanup=True)
+
+    def watchReleaseDomain(self):
+        from xen.xend.xenstore.xswatch import xswatch
+        self.releaseDomain = xswatch("@releaseDomain", self.onReleaseDomain)
 
     def xen_domains(self):
         """Get table of domains indexed by id from xc.
@@ -265,24 +284,6 @@
         else:
             self._delete_domain(id)
 
-    def domain_ls(self):
-        """Get list of domain names.
-
-        @return: domain names
-        """
-        self.refresh()
-        doms = self.domains.values()
-        doms.sort(lambda x, y: cmp(x.name, y.name))
-        return map(lambda x: x.name, doms)
-
-    def domain_ls_ids(self):
-        """Get list of domain ids.
-
-        @return: domain names
-        """
-        self.refresh()
-        return self.domains.keys()
-
     def domain_create(self, config):
         """Create a domain from a configuration.
 
@@ -542,7 +543,7 @@
             dominfo.name = "tmp-" + dominfo.name
 
         try:
-            XendCheckpoint.save(self, sock.fileno(), dominfo)
+            XendCheckpoint.save(self, sock.fileno(), dominfo, live)
         except:
             if dst == "localhost":
                 dominfo.name = string.replace(dominfo.name, "tmp-", "", 1)
@@ -563,7 +564,8 @@
 
             fd = os.open(dst, os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
 
-            return XendCheckpoint.save(self, fd, dominfo)
+            # For now we don't support 'live checkpoint' 
+            return XendCheckpoint.save(self, fd, dominfo, False)
 
         except OSError, ex:
             raise XendError("can't write guest state file %s: %s" %
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py   Fri Sep  9 16:30:54 2005
@@ -34,8 +34,7 @@
 
 from xen.xend.server import controller
 from xen.xend.server import SrvDaemon; xend = SrvDaemon.instance()
-from xen.xend.server import messages
-from xen.xend.server.channel import EventChannel, channelFactory
+from xen.xend.server.channel import EventChannel
 from xen.util.blkif import blkdev_name_to_number, expand_dev_name
 
 from xen.xend import sxp
@@ -47,7 +46,7 @@
 from xen.xend.XendRoot import get_component
 
 from xen.xend.uuid import getUuid
-from xen.xend.xenstore import DBVar
+from xen.xend.xenstore import DBVar, XenNode, DBMap
 
 """Shutdown code for poweroff."""
 DOMAIN_POWEROFF = 0
@@ -231,6 +230,7 @@
         DBVar('start_time',    ty='float'),
         DBVar('state',         ty='str'),
         DBVar('store_mfn',     ty='long'),
+        DBVar('console_mfn',   ty='long', path="console/ring-ref"),
         DBVar('restart_mode',  ty='str'),
         DBVar('restart_state', ty='str'),
         DBVar('restart_time',  ty='float'),
@@ -257,15 +257,17 @@
 
         self.target = None
 
-        self.channel = None
         self.store_channel = None
         self.store_mfn = None
+        self.console_channel = None
+        self.console_mfn = None
         self.controllers = {}
         
         self.info = None
         self.blkif_backend = False
         self.netif_backend = False
         self.netif_idx = 0
+        self.tpmif_backend = False
         
         #todo: state: running, suspended
         self.state = STATE_VM_OK
@@ -292,18 +294,18 @@
         self.db.saveDB(save=save, sync=sync)
 
     def exportToDB(self, save=False, sync=False):
-        if self.channel:
-            self.channel.saveToDB(self.db.addChild("channel"), save=save)
         if self.store_channel:
             self.store_channel.saveToDB(self.db.addChild("store_channel"),
                                         save=save)
+        if self.console_channel:
+            self.db['console/port'] = "%i" % self.console_channel.port1
         if self.image:
             self.image.exportToDB(save=save, sync=sync)
         self.db.exportToDB(self, fields=self.__exports__, save=save, sync=sync)
 
     def importFromDB(self):
         self.db.importFromDB(self, fields=self.__exports__)
-        self.store_channel = self.eventChannel("store_channel")
+        self.store_channel = self.eventChannelOld("store_channel")
 
     def setdom(self, dom):
         """Set the domain id.
@@ -323,16 +325,16 @@
     def getName(self):
         return self.name
 
-    def getChannel(self):
-        return self.channel
-
     def getStoreChannel(self):
         return self.store_channel
 
-    def update(self, info):
+    def getConsoleChannel(self):
+        return self.console_channel
+
+    def update(self, info=None):
         """Update with  info from xc.domain_getinfo().
         """
-        self.info = info
+        self.info = info or dom_get(self.id)
         self.memory = self.info['mem_kb'] / 1024
         self.ssidref = self.info['ssidref']
         self.target = self.info['mem_kb'] * 1024
@@ -384,6 +386,8 @@
         return ctrl
 
     def createDevice(self, type, devconfig, change=False):
+        if self.recreate:
+            return
         if type == 'vbd':
             typedev = sxp.child_value(devconfig, 'dev')
             if re.match('^ioemu:', typedev):
@@ -420,6 +424,15 @@
             return
 
         if type == 'vif':
+            from xen.xend import XendRoot
+            xroot = XendRoot.instance()
+
+            def _get_config_ipaddr(config):
+                val = []
+                for ipaddr in sxp.children(config, elt='ip'):
+                    val.append(sxp.child0(ipaddr))
+                return val
+
             backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0'))
 
             log.error(devconfig)
@@ -427,6 +440,14 @@
             devnum = self.netif_idx
             self.netif_idx += 1
 
+            script = sxp.child_value(devconfig, 'script',
+                                     xroot.get_vif_script())
+            script = os.path.join(xroot.network_script_dir, script)
+            bridge = sxp.child_value(devconfig, 'bridge',
+                                     xroot.get_vif_bridge())
+            mac = sxp.child_value(devconfig, 'mac')
+            ipaddr = _get_config_ipaddr(devconfig)
+
             # create backend db
             backdb = backdom.db.addChild("/backend/%s/%s/%d" %
                                          (type, self.uuid, devnum))
@@ -434,6 +455,12 @@
             # create frontend db
             db = self.db.addChild("/device/%s/%d" % (type, devnum))
             
+            backdb['script'] = script
+            backdb['domain'] = self.name
+            backdb['mac'] = mac
+            backdb['bridge'] = bridge
+            if ipaddr:
+                backdb['ip'] = ' '.join(ipaddr)
             backdb['frontend'] = db.getPath()
             backdb['frontend-id'] = "%i" % self.id
             backdb['handle'] = "%i" % devnum
@@ -442,13 +469,37 @@
             db['backend'] = backdb.getPath()
             db['backend-id'] = "%i" % backdom.id
             db['handle'] = "%i" % devnum
-            log.error(sxp.child_value(devconfig, 'mac'))
-            db['mac'] = sxp.child_value(devconfig, 'mac')
+            db['mac'] = mac
 
             db.saveDB(save=True)
 
             return
         
+        if type == 'vtpm':
+            backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0'))
+
+            devnum = int(sxp.child_value(devconfig, 'instance', '0'))
+            log.error("The domain has a TPM with instance %d." % devnum)
+
+            # create backend db
+            backdb = backdom.db.addChild("/backend/%s/%s/%d" %
+                                         (type, self.uuid, devnum))
+            # create frontend db
+            db = self.db.addChild("/device/%s/%d" % (type, devnum))
+
+            backdb['frontend'] = db.getPath()
+            backdb['frontend-id'] = "%i" % self.id
+            backdb['instance'] = sxp.child_value(devconfig, 'instance', '0')
+            backdb.saveDB(save=True)
+
+            db['handle'] = "%i" % devnum
+            db['backend'] = backdb.getPath()
+            db['backend-id'] = "%i" % int(sxp.child_value(devconfig,
+                                                          'backend', '0'))
+            db.saveDB(save=True)
+
+            return
+
         ctrl = self.findDeviceController(type)
         return ctrl.createDevice(devconfig, recreate=self.recreate,
                                  change=change)
@@ -512,12 +563,18 @@
             sxpr.append(['up_time', str(up_time) ])
             sxpr.append(['start_time', str(self.start_time) ])
 
-        if self.channel:
-            sxpr.append(self.channel.sxpr())
         if self.store_channel:
             sxpr.append(self.store_channel.sxpr())
         if self.store_mfn:
             sxpr.append(['store_mfn', self.store_mfn])
+        if self.console_channel:
+            sxpr.append(['console_channel', self.console_channel.sxpr()])
+        if self.console_mfn:
+            sxpr.append(['console_mfn', self.console_mfn])
+# already in (devices)
+#        console = self.getConsole()
+#        if console:
+#            sxpr.append(console.sxpr())
 
         if self.restart_count:
             sxpr.append(['restart_count', self.restart_count])
@@ -695,12 +752,6 @@
         """
         self.state = STATE_VM_TERMINATED
         self.release_devices()
-        if self.channel:
-            try:
-                self.channel.close()
-                self.channel = None
-            except:
-                pass
         if self.store_channel:
             try:
                 self.store_channel.close()
@@ -712,6 +763,13 @@
             except Exception, ex:
                 log.warning("error in domain release on xenstore: %s", ex)
                 pass
+        if self.console_channel:
+            # notify processes using this cosole?
+            try:
+                self.console_channel.close()
+                self.console_channel = None
+            except:
+                pass
         if self.image:
             try:
                 self.device_model_pid = 0
@@ -723,8 +781,8 @@
     def destroy(self):
         """Clenup vm and destroy domain.
         """
+        self.destroy_domain()
         self.cleanup()
-        self.destroy_domain()
         self.saveToDB()
         return 0
 
@@ -755,6 +813,11 @@
                 for dev in typedb.keys():
                     typedb[dev].delete()
                 typedb.saveDB(save=True)
+            if type == 'vtpm':
+                typedb = ddb.addChild(type)
+                for dev in typedb.keys():
+                    typedb[dev].delete()
+                typedb.saveDB(save=True)
 
     def show(self):
         """Print virtual machine info.
@@ -780,21 +843,7 @@
                   id, self.name, self.memory)
         self.setdom(id)
 
-    def openChannel(self, key, local, remote):
-        """Create a control channel to the domain.
-        If saved info is available recreate the channel.
-        
-        @param key db key for the saved data (if any)
-        @param local default local port
-        @param remote default remote port
-        """
-        db = self.db.addChild(key)
-        chan = channelFactory().restoreFromDB(db, self.id, local, remote)
-        #todo: save here?
-        #chan.saveToDB(db)
-        return chan
-
-    def eventChannel(self, key):
+    def eventChannelOld(self, key):
         """Create an event channel to the domain.
         If saved info is available recreate the channel.
         
@@ -803,11 +852,27 @@
         db = self.db.addChild(key)
         return EventChannel.restoreFromDB(db, 0, self.id)
         
+    def eventChannel(self, path=None, key=None):
+        """Create an event channel to the domain.
+        
+        @param path under which port is stored in db
+        """
+        port = 0
+        try:
+            if path and key:
+                if path:
+                    db = self.db.addChild(path)
+                else:
+                    db = self.db
+                port = int(db[key].getData())
+        except: pass
+        return EventChannel.interdomain(0, self.id, port1=port, port2=0)
+        
     def create_channel(self):
         """Create the channels to the domain.
         """
-        self.channel = self.openChannel("channel", 0, 1)
-        self.store_channel = self.eventChannel("store_channel")
+        self.store_channel = self.eventChannelOld("store_channel")
+        self.console_channel = self.eventChannel("console", "port")
 
     def create_configured_devices(self):
         devices = sxp.children(self.config, 'device')
@@ -950,6 +1015,7 @@
 
         """
         try:
+            self.clear_shutdown()
             self.state = STATE_VM_OK
             self.shutdown_pending = None
             self.restart_check()
@@ -993,6 +1059,8 @@
                 self.netif_backend = True
             elif name == 'usbif':
                 self.usbif_backend = True
+            elif name == 'tpmif':
+                self.tpmif_backend = True
             else:
                 raise VmError('invalid backend type:' + str(name))
 
@@ -1084,7 +1152,7 @@
 
     def dom0_init_store(self):
         if not self.store_channel:
-            self.store_channel = self.eventChannel("store_channel")
+            self.store_channel = self.eventChannelOld("store_channel")
         self.store_mfn = xc.init_store(self.store_channel.port2)
         if self.store_mfn >= 0:
             self.db.introduceDomain(self.id, self.store_mfn,
@@ -1158,6 +1226,10 @@
 controller.addDevControllerClass("vif", netif.NetifController)
 add_device_handler("vif", "vif")
 
+from server import tpmif
+controller.addDevControllerClass("vtpm", tpmif.TPMifController)
+add_device_handler("vtpm", "vtpm")
+
 from server import pciif
 controller.addDevControllerClass("pci", pciif.PciController)
 add_device_handler("pci", "pci")
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/XendNode.py Fri Sep  9 16:30:54 2005
@@ -46,7 +46,7 @@
         return self.xc.bvtsched_global_get()
     
     def info(self):
-        return self.nodeinfo() + self.physinfo()
+        return self.nodeinfo() + self.physinfo() + self.xeninfo()
 
     def nodeinfo(self):
         (sys, host, rel, ver, mch) = os.uname()
@@ -58,14 +58,29 @@
 
     def physinfo(self):
         pinfo = self.xc.physinfo()
-        info = [['cores_per_socket', pinfo['cores_per_socket']],
+        info = [['nr_cpus',          
pinfo['nr_nodes']*pinfo['sockets_per_node']*pinfo['cores_per_socket']*pinfo['threads_per_core']],
+                ['nr_nodes',         pinfo['nr_nodes']],
+                ['sockets_per_node', pinfo['sockets_per_node']],
+                ['cores_per_socket', pinfo['cores_per_socket']],
                 ['threads_per_core', pinfo['threads_per_core']],
-                ['cpu_mhz', pinfo['cpu_khz']/1000],
-                ['memory', pinfo['total_pages']/256],
-                ['free_memory', pinfo['free_pages']/256]]
+                ['cpu_mhz',          pinfo['cpu_khz']/1000],
+                ['hw_caps',          pinfo['hw_caps']],
+                ['memory',           pinfo['total_pages']/256],
+                ['free_memory',      pinfo['free_pages']/256]]
         return info
         
-        
+    def xeninfo(self):
+        xinfo = self.xc.xeninfo()
+        return [['xen_major', xinfo['xen_major']],
+                ['xen_minor', xinfo['xen_minor']],
+                ['xen_extra', xinfo['xen_extra']],
+                ['xen_caps',  xinfo['xen_caps']],
+                ['xen_params',xinfo['xen_params']],
+                ['xen_changeset', xinfo['xen_changeset']],
+                ['cc_compiler', xinfo['cc_compiler']],
+                ['cc_compile_by', xinfo['cc_compile_by']],
+                ['cc_compile_domain', xinfo['cc_compile_domain']],
+                ['cc_compile_date', xinfo['cc_compile_date']]]
 
 def instance():
     global inst
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/image.py    Fri Sep  9 16:30:54 2005
@@ -32,6 +32,9 @@
 """Flag for a net device backend domain."""
 SIF_NET_BE_DOMAIN = (1<<5)
 
+"""Flag for a TPM device backend domain."""
+SIF_TPM_BE_DOMAIN = (1<<7)
+
 class ImageHandler:
     """Abstract base class for image handlers.
 
@@ -156,7 +159,12 @@
         xc.domain_setmaxmem(dom, mem_kb)
 
         try:
-            xc.domain_memory_increase_reservation(dom, mem_kb)
+            # Give the domain some memory below 4GB
+            lmem_kb = 0
+            if lmem_kb > 0:
+                xc.domain_memory_increase_reservation(dom, 
min(lmem_kb,mem_kb), 0, 32)
+            if mem_kb > lmem_kb:
+                xc.domain_memory_increase_reservation(dom, mem_kb-lmem_kb, 0, 
0)
         except:
             xc.domain_destroy(dom)
             raise
@@ -194,6 +202,7 @@
         self.flags = 0
         if self.vm.netif_backend: self.flags |= SIF_NET_BE_DOMAIN
         if self.vm.blkif_backend: self.flags |= SIF_BLK_BE_DOMAIN
+        if self.vm.tpmif_backend: self.flags |= SIF_TPM_BE_DOMAIN
 
         if self.vm.recreate or self.vm.restore:
             return
@@ -238,16 +247,31 @@
             store_evtchn = self.vm.store_channel.port2
         else:
             store_evtchn = 0
+        if self.vm.console_channel:
+            console_evtchn = self.vm.console_channel.port2
+        else:
+            console_evtchn = 0
+
+        log.debug("dom            = %d", self.vm.getDomain())
+        log.debug("image          = %s", self.kernel)
+        log.debug("store_evtchn   = %d", store_evtchn)
+        log.debug("console_evtchn = %d", console_evtchn)
+        log.debug("cmdline        = %s", self.cmdline)
+        log.debug("ramdisk        = %s", self.ramdisk)
+        log.debug("flags          = %d", self.flags)
+        log.debug("vcpus          = %d", self.vm.vcpus)
+
         ret = xc.linux_build(dom            = self.vm.getDomain(),
                              image          = self.kernel,
-                             control_evtchn = self.vm.channel.getRemotePort(),
                              store_evtchn   = store_evtchn,
+                             console_evtchn = console_evtchn,
                              cmdline        = self.cmdline,
                              ramdisk        = self.ramdisk,
                              flags          = self.flags,
                              vcpus          = self.vm.vcpus)
         if isinstance(ret, dict):
             self.vm.store_mfn = ret.get('store_mfn')
+            self.vm.console_mfn = ret.get('console_mfn')
             return 0
         return ret
 
@@ -349,6 +373,11 @@
                mac = sxp.child_value(vifinfo, 'mac')
                ret.append("-macaddr")
                ret.append("%s" % mac)
+            if name == 'vtpm':
+               vtpminfo = sxp.child(device, 'vtpm')
+               instance = sxp.child_value(vtpminfo, 'instance')
+               ret.append("-instance")
+               ret.append("%s" % instance)
 
        # Handle graphics library related options
        vnc = sxp.child_value(self.vm.config, 'vnc')
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/SrvDaemon.py
--- a/tools/python/xen/xend/server/SrvDaemon.py Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/server/SrvDaemon.py Fri Sep  9 16:30:54 2005
@@ -17,8 +17,6 @@
 import time
 import glob
 
-from xen.lowlevel import xu
-
 from xen.xend import sxp
 from xen.xend import PrettyPrint
 from xen.xend import EventServer; eserver = EventServer.instance()
@@ -27,7 +25,6 @@
 from xen.xend.XendLogging import log
 from xen.xend import XendRoot; xroot = XendRoot.instance()
 
-import channel
 import controller
 import event
 import relocate
@@ -37,12 +34,12 @@
     """The xend daemon.
     """
     def __init__(self):
-        self.channelF = None
         self.shutdown = 0
         self.traceon = 0
         self.tracefile = None
         self.traceindent = 0
-
+        self.child = 0 
+        
     def daemon_pids(self):
         pids = []
         pidex = '(?P<pid>\d+)'
@@ -140,15 +137,12 @@
         else:
             return 0
 
-    def install_child_reaper(self):
-        #signal.signal(signal.SIGCHLD, self.onSIGCHLD)
-        # Ensure that zombie children are automatically reaped.
-        xu.autoreap()
-
     def onSIGCHLD(self, signum, frame):
-        code = 1
-        while code > 0:
-            code = os.waitpid(-1, os.WNOHANG)
+        if self.child > 0: 
+            try: 
+                pid, sts = os.waitpid(self.child, os.WNOHANG)
+            except os.error, ex:
+                pass
 
     def fork_pid(self, pidfile):
         """Fork and write the pid of the child to 'pidfile'.
@@ -156,13 +150,16 @@
         @param pidfile: pid file
         @return: pid of child in parent, 0 in child
         """
-        pid = os.fork()
-        if pid:
+
+        self.child = os.fork()
+
+        if self.child:
             # Parent
             pidfile = open(pidfile, 'w')
-            pidfile.write(str(pid))
+            pidfile.write(str(self.child))
             pidfile.close()
-        return pid
+
+        return self.child
 
     def daemonize(self):
         if not XEND_DAEMONIZE: return
@@ -203,8 +200,7 @@
             # Trying to run an already-running service is a success.
             return 0
 
-        self.install_child_reaper()
-
+        signal.signal(signal.SIGCHLD, self.onSIGCHLD)
         if self.fork_pid(XEND_PID_FILE):
             #Parent. Sleep to give child time to start.
             time.sleep(1)
@@ -298,10 +294,8 @@
         _enforce_dom0_cpus()
         try:
             log.info("Xend Daemon started")
-            self.createFactories()
             event.listenEvent(self)
             relocate.listenRelocation()
-            self.listenChannels()
             servers = SrvServer.create()
             self.daemonize()
             servers.start()
@@ -309,22 +303,10 @@
             print >>sys.stderr, 'Exception starting xend:', ex
             if XEND_DEBUG:
                 traceback.print_exc()
-            log.exception("Exception starting xend")
+            log.exception("Exception starting xend (%s)" % ex)
             self.exit(1)
             
-    def createFactories(self):
-        self.channelF = channel.channelFactory()
-
-    def listenChannels(self):
-        def virqReceived(virq):
-            eserver.inject('xend.virq', virq)
-
-        self.channelF.setVirqHandler(virqReceived)
-        self.channelF.start()
-
     def exit(self, rc=0):
-        if self.channelF:
-            self.channelF.stop()
         # Calling sys.exit() raises a SystemExit exception, which only
         # kills the current thread. Calling os._exit() makes the whole
         # Python process exit immediately. There doesn't seem to be another
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/SrvDomain.py
--- a/tools/python/xen/xend/server/SrvDomain.py Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/server/SrvDomain.py Fri Sep  9 16:30:54 2005
@@ -221,6 +221,7 @@
         #
         # if op and op[0] in ['vifs', 'vif', 'vbds', 'vbd', 'mem_target_set']:
         #    return self.perform(req)
+        self.dom.update()
         if self.use_sxp(req):
             req.setHeader("Content-Type", sxp.mime_type)
             sxp.show(self.dom.sxpr(), out=req)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
tools/python/xen/xend/server/SrvDomainDir.py
--- a/tools/python/xen/xend/server/SrvDomainDir.py      Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/server/SrvDomainDir.py      Fri Sep  9 16:30:54 2005
@@ -146,11 +146,10 @@
         if not url.endswith('/'):
             url += '/'
         if use_sxp:
-            domains = self.xd.domain_ls()
+            domains = self.xd.list_names()
             sxp.show(domains, out=req)
         else:
-            domains = self.xd.list()
-            domains.sort(lambda x, y: cmp(x.name, y.name))
+            domains = self.xd.list_sorted()
             req.write('<ul>')
             for d in domains:
                req.write('<li><a href="%s%s"> Domain %s</a>'
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/SrvServer.py
--- a/tools/python/xen/xend/server/SrvServer.py Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/server/SrvServer.py Fri Sep  9 16:30:54 2005
@@ -61,9 +61,14 @@
 
     def start(self):
         Vifctl.network('start')
+        threads = []
         for server in self.servers:
             thread = Thread(target=server.run)
             thread.start()
+            threads.append(thread)
+
+        for t in threads:
+            t.join()
 
 def create():
     root = SrvDir()
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/blkif.py
--- a/tools/python/xen/xend/server/blkif.py     Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/server/blkif.py     Fri Sep  9 16:30:54 2005
@@ -27,9 +27,7 @@
 from xen.xend import Blkctl
 from xen.xend.xenstore import DBVar
 
-from xen.xend.server import channel
-from xen.xend.server.controller import CtrlMsgRcvr, Dev, DevController
-from xen.xend.server.messages import *
+from xen.xend.server.controller import Dev, DevController
 
 class BlkifBackend:
     """ Handler for the 'back-end' channel to a block device driver domain
@@ -41,21 +39,15 @@
         self.controller = controller
         self.id = id
         self.frontendDomain = self.controller.getDomain()
-        self.frontendChannel = None
         self.backendDomain = dom
-        self.backendChannel = None
         self.destroyed = False
         self.connected = False
-        self.evtchn = None
         self.status = None
 
     def init(self, recreate=False, reboot=False):
         self.destroyed = False
         self.status = BLKIF_INTERFACE_STATUS_DISCONNECTED
         self.frontendDomain = self.controller.getDomain()
-        self.frontendChannel = self.controller.getChannel()
-        cf = channel.channelFactory()
-        self.backendChannel = cf.openChannel(self.backendDomain)
 
     def __str__(self):
         return ('<BlkifBackend frontend=%d backend=%d id=%d>'
@@ -66,29 +58,6 @@
     def getId(self):
         return self.id
 
-    def getEvtchn(self):
-        return self.evtchn
-
-    def closeEvtchn(self):
-        if self.evtchn:
-            channel.eventChannelClose(self.evtchn)
-            self.evtchn = None
-
-    def openEvtchn(self):
-        self.evtchn = channel.eventChannel(self.backendDomain, 
self.frontendDomain)
-
-    def getEventChannelBackend(self):
-        val = 0
-        if self.evtchn:
-            val = self.evtchn['port1']
-        return val
-
-    def getEventChannelFrontend(self):
-        val = 0
-        if self.evtchn:
-            val = self.evtchn['port2']
-        return val
-
     def connect(self, recreate=False):
         """Connect to the blkif control interface.
 
@@ -98,83 +67,19 @@
         if recreate or self.connected:
             self.connected = True
             pass
-        else:
-            self.send_be_create()
-        
-    def send_be_create(self):
-        log.debug("send_be_create %s", str(self))
-        msg = packMsg('blkif_be_create_t',
-                      { 'domid'        : self.frontendDomain,
-                        'blkif_handle' : self.id })
-        msg = self.backendChannel.requestResponse(msg)
-        #todo: check return status
-        self.connected = True
-
+        
     def destroy(self, change=False, reboot=False):
         """Disconnect from the blkif control interface and destroy it.
         """
-        self.send_be_disconnect()
-        self.send_be_destroy()
-        self.closeEvtchn()
         self.destroyed = True
         # For change true need to notify front-end, or back-end will do it?
 
-    def send_be_disconnect(self):
-        msg = packMsg('blkif_be_disconnect_t',
-                      { 'domid'        : self.frontendDomain,
-                        'blkif_handle' : self.id })
-        self.backendChannel.requestResponse(msg)
-        #todo: check return status
-        self.connected = False
-
-    def send_be_destroy(self):
-        msg = packMsg('blkif_be_destroy_t',
-                      { 'domid'        : self.frontendDomain,
-                        'blkif_handle' : self.id })
-        self.backendChannel.requestResponse(msg)
-        #todo: check return status
-
     def connectInterface(self, val):
-        self.openEvtchn()
-        log.debug("Connecting blkif to event channel %s ports=%d:%d",
-                  str(self), self.evtchn['port1'], self.evtchn['port2'])
-        msg = packMsg('blkif_be_connect_t',
-                      { 'domid'        : self.frontendDomain,
-                        'blkif_handle' : self.id,
-                        'evtchn'       : self.getEventChannelBackend(),
-                        'shmem_frame'  : val['shmem_frame'],
-                        'shmem_ref'    : val['shmem_ref'] })
-        msg = self.backendChannel.requestResponse(msg)
-        #todo: check return status
-        val = unpackMsg('blkif_be_connect_t', msg)
         self.status = BLKIF_INTERFACE_STATUS_CONNECTED
-        self.send_fe_interface_status()
             
-    def send_fe_interface_status(self):
-        msg = packMsg('blkif_fe_interface_status_t',
-                      { 'handle' : self.id,
-                        'status' : self.status,
-                        'domid'  : self.backendDomain,
-                        'evtchn' : self.getEventChannelFrontend() })
-        self.frontendChannel.writeRequest(msg)
-
     def interfaceDisconnected(self):
         self.status = BLKIF_INTERFACE_STATUS_DISCONNECTED
-        #todo?: Close evtchn:
-        #self.closeEvtchn()
-        self.send_fe_interface_status()
-        
-    def interfaceChanged(self):
-        """Notify the front-end that devices have been added or removed.
-        The front-end should then probe for devices.
-        """
-        msg = packMsg('blkif_fe_interface_status_t',
-                      { 'handle' : self.id,
-                        'status' : BLKIF_INTERFACE_STATUS_CHANGED,
-                        'domid'  : self.backendDomain,
-                        'evtchn' : 0 })
-        self.frontendChannel.writeRequest(msg)
-
+        
 class BlkDev(Dev):
     """Info record for a block device.
     """
@@ -207,24 +112,17 @@
         self.nr_sectors = None
         
         self.frontendDomain = self.getDomain()
-        self.frontendChannel = None
         self.backendDomain = None
-        self.backendChannel = None
         self.backendId = 0
         self.configure(self.config, recreate=recreate)
 
     def exportToDB(self, save=False):
         Dev.exportToDB(self, save=save)
         backend = self.getBackend()
-        if backend and backend.evtchn:
-            db = self.db.addChild("evtchn")
-            backend.evtchn.saveToDB(db, save=save)
 
     def init(self, recreate=False, reboot=False):
         self.frontendDomain = self.getDomain()
-        self.frontendChannel = self.getChannel()
         backend = self.getBackend()
-        self.backendChannel = backend.backendChannel
         self.backendId = backend.id
 
     def configure(self, config, change=False, recreate=False):
@@ -351,7 +249,6 @@
         self.destroyed = True
         log.debug("Destroying vbd domain=%d id=%s", self.frontendDomain,
                   self.id)
-        self.send_be_vbd_destroy()
         if change:
             self.interfaceChanged()
         self.unbind()
@@ -367,30 +264,6 @@
 
         """
         self.getBackend().connect()
-        self.send_be_vbd_create()
-        
-    def send_be_vbd_create(self):
-        msg = packMsg('blkif_be_vbd_create_t',
-                      { 'domid'        : self.frontendDomain,
-                        'blkif_handle' : self.backendId,
-                        'pdevice'      : self.device,
-                        'dev_handle'   : self.dev_handle,
-                        'vdevice'      : self.vdev,
-                        'readonly'     : self.readonly() })
-        msg = self.backendChannel.requestResponse(msg)
-        
-        val = unpackMsg('blkif_be_vbd_create_t', msg)
-        status = val['status']
-        if status != BLKIF_BE_STATUS_OKAY:
-            raise XendError("Creating vbd failed: device %s, error %d"
-                            % (sxp.to_string(self.config), status))
-
-    def send_be_vbd_destroy(self):
-        msg = packMsg('blkif_be_vbd_destroy_t',
-                      { 'domid'                : self.frontendDomain,
-                        'blkif_handle'         : self.backendId,
-                        'vdevice'              : self.vdev })
-        return self.backendChannel.writeRequest(msg)
         
 class BlkifController(DevController):
     """Block device interface controller. Handles all block devices
@@ -403,19 +276,9 @@
         DevController.__init__(self, vm, recreate=recreate)
         self.backends = {}
         self.backendId = 0
-        self.rcvr = None
 
     def initController(self, recreate=False, reboot=False):
         self.destroyed = False
-        # Add our handlers for incoming requests.
-        self.rcvr = CtrlMsgRcvr(self.getChannel())
-        self.rcvr.addHandler(CMSG_BLKIF_FE,
-                             CMSG_BLKIF_FE_DRIVER_STATUS,
-                             self.recv_fe_driver_status)
-        self.rcvr.addHandler(CMSG_BLKIF_FE,
-                             CMSG_BLKIF_FE_INTERFACE_CONNECT,
-                             self.recv_fe_interface_connect)
-        self.rcvr.registerChannel()
         if reboot:
             self.rebootBackends()
             self.rebootDevices()
@@ -465,26 +328,7 @@
         log.debug("Destroying blkif domain=%d", self.getDomain())
         self.destroyDevices(reboot=reboot)
         self.destroyBackends(reboot=reboot)
-        self.rcvr.deregisterChannel()
 
     def destroyBackends(self, reboot=False):
         for backend in self.backends.values():
             backend.destroy(reboot=reboot)
-
-    def recv_fe_driver_status(self, msg):
-        val = unpackMsg('blkif_fe_driver_status_t', msg)
-        for backend in self.backends.values():
-            backend.interfaceDisconnected()
-
-    def recv_fe_interface_connect(self, msg):
-        val = unpackMsg('blkif_fe_interface_connect_t', msg)
-        id = val['handle']
-        backend = self.getBackendById(id)
-        if backend:
-            try:
-                backend.connectInterface(val)
-            except IOError, ex:
-                log.error("Exception connecting backend: %s", ex)
-        else:
-            log.error('interface connect on unknown interface: id=%d', id)
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/channel.py
--- a/tools/python/xen/xend/server/channel.py   Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/server/channel.py   Fri Sep  9 16:30:54 2005
@@ -19,11 +19,8 @@
 import select
 
 import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
-from xen.lowlevel import xu
 
 from xen.xend.XendLogging import log
-
-from messages import *
 
 DEBUG = 0
 
@@ -132,501 +129,3 @@
     """
     if not evtchn: return
     evtchn.close()
-
-class ChannelFactory:
-    """Factory for creating control channels.
-    Maintains a table of channels.
-    """
-
-    """ Channels indexed by index. """
-    channels = None
-
-    thread = None
-
-    notifier = None
-
-    """Map of ports to the virq they signal."""
-    virqPorts = None
-
-    def __init__(self):
-        """Constructor - do not use. Use the channelFactory function."""
-        self.channels = {}
-        self.virqPorts = {}
-        self.notifier = xu.notifier()
-        # Register interest in virqs.
-        self.bind_virq(xen.lowlevel.xc.VIRQ_DOM_EXC)
-        self.virqHandler = None
-
-    def bind_virq(self, virq):
-        port = self.notifier.bind_virq(virq)
-        self.virqPorts[port] = virq
-        log.info("Virq %s on port %s", virq, port)
-
-    def start(self):
-        """Fork a thread to read messages.
-        """
-        if self.thread: return
-        self.thread = threading.Thread(name="ChannelFactory",
-                                       target=self.main)
-        self.thread.setDaemon(True)
-        self.thread.start()
-
-    def stop(self):
-        """Signal the thread to stop.
-        """
-        self.thread = None
-
-    def main(self):
-        """Main routine for the thread.
-        Reads the notifier and dispatches to channels.
-        """
-        while True:
-            if self.thread == None: return
-            port = self.notifier.read()
-            if port:
-                virq = self.virqPorts.get(port)
-                if virq is not None:
-                    self.virqReceived(virq)
-                else:
-                    self.msgReceived(port)
-            else:
-                select.select([self.notifier], [], [], 1.0)
-
-    def msgReceived(self, port):
-        # We run the message handlers in their own threads.
-        # Note we use keyword args to lambda to save the values -
-        # otherwise lambda will use the variables, which will get
-        # assigned by the loop and the lambda will get the changed values.
-        received = 0
-        for chan in self.channels.values():
-            if self.thread == None: return
-            msg = chan.readResponse()
-            if msg:
-                received += 1
-                chan.responseReceived(msg)
-        for chan in self.channels.values():
-            if self.thread == None: return
-            msg = chan.readRequest()
-            if msg:
-                received += 1
-                self.runInThread(lambda chan=chan, msg=msg: 
chan.requestReceived(msg))
-        if port and received == 0:
-            log.warning("Port %s notified, but no messages found", port)
-
-    def runInThread(self, thunk):
-        thread = threading.Thread(target = thunk)
-        thread.setDaemon(True)
-        thread.start()
-
-    def setVirqHandler(self, virqHandler):
-        self.virqHandler = virqHandler
-
-    def virqReceived(self, virq):
-        if DEBUG:
-            print 'virqReceived>', virq
-        if not self.virqHandler: return
-        self.runInThread(lambda virq=virq: self.virqHandler(virq))
-
-    def newChannel(self, dom, local_port, remote_port):
-        """Create a new channel.
-        """
-        return self.addChannel(Channel(self, dom, local_port, remote_port))
-    
-    def addChannel(self, channel):
-        """Add a channel.
-        """
-        self.channels[channel.getKey()] = channel
-        return channel
-
-    def delChannel(self, channel):
-        """Remove the channel.
-        """
-        key = channel.getKey()
-        if key in self.channels:
-            del self.channels[key]
-
-    def getChannel(self, dom, local_port, remote_port):
-        """Get the channel with the given domain and ports (if any).
-        """
-        key = (dom, local_port, remote_port)
-        return self.channels.get(key)
-
-    def findChannel(self, dom, local_port=0, remote_port=0):
-        """Find a channel. Ports given as zero are wildcards.
-
-        dom domain
-
-        returns channel
-        """
-        chan = self.getChannel(dom, local_port, remote_port)
-        if chan: return chan
-        if local_port and remote_port:
-            return None
-        for c in self.channels.values():
-            if c.dom != dom: continue
-            if local_port and local_port != c.getLocalPort(): continue
-            if remote_port and remote_port != c.getRemotePort(): continue
-            return c
-        return None
-
-    def openChannel(self, dom, local_port=0, remote_port=0):
-        chan = self.findChannel(dom, local_port=local_port,
-                                remote_port=remote_port)
-        if chan:
-            return chan
-        chan = self.newChannel(dom, local_port, remote_port)
-        return chan
-        
-
-    def createPort(self, dom, local_port=0, remote_port=0):
-        """Create a port for a channel to the given domain.
-        If only the domain is specified, a new channel with new port ids is
-        created.  If one port id is specified and the given port id is in use,
-        the other port id is filled.  If one port id is specified and the
-        given port id is not in use, a new channel is created with one port
-        id equal to the given id and a new id for the other end.  If both
-        port ids are specified, a port is reconnected using the given port
-        ids.
-
-        @param dom: domain
-        @param local: local port id to use
-        @type  local: int
-        @param remote: remote port id to use
-        @type  remote: int
-        @return: port object
-        """
-        return xu.port(dom, local_port=local_port, remote_port=remote_port)
-
-    def restoreFromDB(self, db, dom, local, remote):
-        """Create a channel using ports restored from the db (if available).
-        Otherwise use the given ports. This is the inverse operation to
-        saveToDB() on a channel.
-
-        @param db db
-        @param dom  domain the channel connects to
-        @param local default local port
-        @param remote default remote port
-        """
-        try:
-            local_port  = int(db['local_port'])
-        except:
-            local_port = local
-        try:
-            remote_port = int(db['remote_port'])
-        except:
-            remote_port = remote
-        try:
-            chan = self.openChannel(dom, local_port, remote_port)
-        except:
-            return None
-        return chan
-
-def channelFactory():
-    """Singleton constructor for the channel factory.
-    Use this instead of the class constructor.
-    """
-    global inst
-    try:
-        inst
-    except:
-        inst = ChannelFactory()
-    return inst
-
-class Channel:
-    """Control channel to a domain.
-    Maintains a list of device handlers to dispatch requests to, based
-    on the request type.
-    """
-
-    def __init__(self, factory, dom, local_port, remote_port):
-        self.factory = factory
-        self.dom = int(dom)
-        # Registered device handlers.
-        self.devs = []
-        # Handlers indexed by the message types they handle.
-        self.devs_by_type = {}
-        self.port = self.factory.createPort(self.dom,
-                                            local_port=local_port,
-                                            remote_port=remote_port)
-        self.closed = False
-        # Queue of waiters for responses to requests.
-        self.queue = ResponseQueue(self)
-        # Make sure the port will deliver all the messages.
-        self.port.register(TYPE_WILDCARD)
-
-    def saveToDB(self, db, save=False):
-        """Save the channel ports to the db so the channel can be restored 
later,
-        using restoreFromDB() on the factory.
-
-        @param db db
-        """
-        if self.closed: return
-        db['local_port'] = str(self.getLocalPort())
-        db['remote_port'] = str(self.getRemotePort())
-        db.saveDB(save=save)
-
-    def getKey(self):
-        """Get the channel key.
-        """
-        return (self.dom, self.getLocalPort(), self.getRemotePort())
-
-    def sxpr(self):
-        val = ['channel']
-        val.append(['domain', self.dom])
-        if self.port:
-            val.append(['local_port', self.port.local_port])
-            val.append(['remote_port', self.port.remote_port])
-        return val
-
-    def close(self):
-        """Close the channel.
-        """
-        if DEBUG:
-            print 'Channel>close>', self
-        if self.closed: return
-        self.closed = True
-        self.factory.delChannel(self)
-        for d in self.devs[:]:
-            d.lostChannel(self)
-        self.devs = []
-        self.devs_by_type = {}
-        if self.port:
-            self.port.close()
-            #self.port = None
-
-    def getDomain(self):
-        return self.dom
-
-    def getLocalPort(self):
-        """Get the local port.
-
-        @return: local port
-        @rtype:  int
-        """
-        if self.closed: return -1
-        return self.port.local_port
-
-    def getRemotePort(self):
-        """Get the remote port.
-
-        @return: remote port
-        @rtype:  int
-        """
-        if self.closed: return -1
-        return self.port.remote_port
-
-    def __repr__(self):
-        return ('<Channel dom=%d ports=%d:%d>'
-                % (self.dom,
-                   self.getLocalPort(),
-                   self.getRemotePort()))
-
-
-    def registerDevice(self, types, dev):
-        """Register a device message handler.
-
-        @param types: message types handled
-        @type  types: array of ints
-        @param dev:   device handler
-        """
-        if self.closed: return
-        self.devs.append(dev)
-        for ty in types:
-            self.devs_by_type[ty] = dev
-
-    def deregisterDevice(self, dev):
-        """Remove the registration for a device handler.
-
-        @param dev: device handler
-        """
-        if dev in self.devs:
-            self.devs.remove(dev)
-        types = [ ty for (ty, d) in self.devs_by_type.items() if d == dev ]
-        for ty in types:
-            del self.devs_by_type[ty]
-
-    def getDevice(self, type):
-        """Get the handler for a message type.
-
-        @param type: message type
-        @type  type: int
-        @return: controller or None
-        @rtype:  device handler
-        """
-        return self.devs_by_type.get(type)
-
-    def requestReceived(self, msg):
-        """A request has been received on the channel.
-        Disptach it to the device handlers.
-        Called from the channel factory thread.
-        """
-        if DEBUG:
-            print 'Channel>requestReceived>', self,
-            printMsg(msg)
-        (ty, subty) = getMessageType(msg)
-        responded = False
-        dev = self.getDevice(ty)
-        if dev:
-            responded = dev.requestReceived(msg, ty, subty)
-        elif DEBUG:
-            print "Channel>requestReceived> No device handler", self,
-            printMsg(msg)
-        else:
-            pass
-        if not responded:
-            self.writeResponse(msg)
-
-    def writeRequest(self, msg):
-        """Write a request to the channel.
-        """
-        if DEBUG:
-            print 'Channel>writeRequest>', self,
-            printMsg(msg, all=True)
-        if self.closed: return -1
-        self.port.write_request(msg)
-        return 1
-
-    def writeResponse(self, msg):
-        """Write a response to the channel.
-        """
-        if DEBUG:
-            print 'Channel>writeResponse>', self,
-            printMsg(msg, all=True)
-        if self.port:
-            self.port.write_response(msg)
-        return 1
-
-    def readRequest(self):
-        """Read a request from the channel.
-        Called internally.
-        """
-        if self.closed:
-            val =  None
-        else:
-            val = self.port.read_request()
-        return val
-        
-    def readResponse(self):
-        """Read a response from the channel.
-        Called internally.
-        """
-        if self.closed:
-            val = None
-        else:
-            val = self.port.read_response()
-        if DEBUG and val:
-            print 'Channel>readResponse>', self,
-            printMsg(val, all=True)
-        return val
-
-    def requestResponse(self, msg, timeout=None):
-        """Write a request and wait for a response.
-        Raises IOError on timeout.
-
-        @param msg request message
-        @param timeout timeout (0 is forever)
-        @return response message
-        """
-        if self.closed:
-            raise IOError("closed")
-        if self.closed:
-            return None
-        if timeout is None:
-            timeout = RESPONSE_TIMEOUT
-        elif timeout <= 0:
-            timeout = None
-        return self.queue.call(msg, timeout)
-
-    def responseReceived(self, msg):
-        """A response has been received, look for a waiter to
-        give it to.
-        Called internally.
-        """
-        if DEBUG:
-            print 'Channel>responseReceived>', self,
-            printMsg(msg)
-        self.queue.response(getMessageId(msg), msg)
-
-    def virq(self):
-        self.factory.virq()
-
-class Response:
-    """Entry in the response queue.
-    Used to signal a response to a message.
-    """
-
-    def __init__(self, mid):
-        self.mid = mid
-        self.msg = None
-        self.ready = threading.Event()
-
-    def response(self, msg):
-        """Signal arrival of a response to a waiting thread.
-        Passing msg None cancels the wait with an IOError.
-        """
-        if msg:
-            self.msg = msg
-        else:
-            self.mid = -1
-        self.ready.set()
-
-    def wait(self, timeout):
-        """Wait up to 'timeout' seconds for a response.
-        Returns the response or raises an IOError.
-        """
-        self.ready.wait(timeout)
-        if self.mid < 0:
-            raise IOError("wait canceled")
-        if self.msg is None:
-            raise IOError("response timeout")
-        return self.msg
-
-class ResponseQueue:
-    """Response queue. Manages waiters for responses to messages.
-    """
-
-    def __init__(self, channel):
-        self.channel = channel
-        self.lock = threading.Lock()
-        self.responses = {}
-
-    def add(self, mid):
-        r = Response(mid)
-        self.responses[mid] = r
-        return r
-
-    def get(self, mid):
-        return self.responses.get(mid)
-
-    def remove(self, mid):
-        r = self.responses.get(mid)
-        if r:
-            del self.responses[mid]
-        return r
-
-    def response(self, mid, msg):
-        """Process a response - signals any waiter that a response
-        has arrived.
-        """
-        try:
-            self.lock.acquire()
-            r = self.remove(mid)
-        finally:
-            self.lock.release()
-        if r:
-            r.response(msg)
-
-    def call(self, msg, timeout):
-        """Send the message and wait for 'timeout' seconds for a response.
-        Returns the response.
-        Raises IOError on timeout.
-        """
-        mid = getMessageId(msg)
-        try:
-            self.lock.acquire()
-            r = self.add(mid)
-        finally:
-            self.lock.release()
-        self.channel.writeRequest(msg)
-        return r.wait(timeout)
-                
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/controller.py
--- a/tools/python/xen/xend/server/controller.py        Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/server/controller.py        Fri Sep  9 16:30:54 2005
@@ -21,106 +21,8 @@
 
 from xen.xend.XendError import XendError
 from xen.xend.xenstore import DBVar
-from xen.xend.server.messages import msgTypeName, printMsg, getMessageType
 
 DEBUG = 0
-
-class CtrlMsgRcvr:
-    """Utility class to dispatch messages on a control channel.
-    Once I{registerChannel} has been called, our message types are registered
-    with the channel. The channel will call I{requestReceived}
-    when a request arrives if it has one of our message types.
-
-    @ivar channel: channel to a domain
-    @type channel: Channel
-    @ivar majorTypes: major message types we are interested in
-    @type majorTypes: {int:{int:method}}
-    
-    """
-
-    def __init__(self, channel):
-        self.majorTypes = {}
-        self.channel = channel
-
-    def getHandler(self, type, subtype):
-        """Get the method for a type and subtype.
-
-        @param type: major message type
-        @param subtype: minor message type
-        @return: method or None
-        """
-        method = None
-        subtypes = self.majorTypes.get(type)
-        if subtypes:
-            method = subtypes.get(subtype)
-        return method
-
-    def addHandler(self, type, subtype, method):
-        """Add a method to handle a message type and subtype.
-        
-        @param type: major message type
-        @param subtype: minor message type
-        @param method: method
-        """
-        subtypes = self.majorTypes.get(type)
-        if not subtypes:
-            subtypes = {}
-            self.majorTypes[type] = subtypes
-        subtypes[subtype] = method
-
-    def getMajorTypes(self):
-        """Get the list of major message types handled.
-        """
-        return self.majorTypes.keys()
-
-    def requestReceived(self, msg, type, subtype):
-        """Dispatch a request message to handlers.
-        Called by the channel for requests with one of our types.
-
-        @param msg:     message
-        @type  msg:     xu message
-        @param type:    major message type
-        @type  type:    int
-        @param subtype: minor message type
-        @type  subtype: int
-        """
-        if DEBUG:
-            print 'requestReceived>',
-            printMsg(msg, all=True)
-        responded = 0
-        method = self.getHandler(type, subtype)
-        if method:
-            responded = method(msg)
-        elif DEBUG:
-            print ('requestReceived> No handler: Message type %s %d:%d'
-                   % (msgTypeName(type, subtype), type, subtype)), self
-        return responded
-        
-
-    def lostChannel(self):
-        """Called when the channel to the domain is lost.
-        """
-        if DEBUG:
-            print 'CtrlMsgRcvr>lostChannel>',
-        self.channel = None
-    
-    def registerChannel(self):
-        """Register interest in our major message types with the
-        channel to our domain. Once we have registered, the channel
-        will call requestReceived for our messages.
-        """
-        if DEBUG:
-            print 'CtrlMsgRcvr>registerChannel>', self.channel, 
self.getMajorTypes()
-        if self.channel:
-            self.channel.registerDevice(self.getMajorTypes(), self)
-        
-    def deregisterChannel(self):
-        """Deregister interest in our major message types with the
-        channel to our domain. After this the channel won't call
-        us any more.
-        """
-        if self.channel:
-            self.channel.deregisterDevice(self)
 
 class DevControllerTable:
     """Table of device controller classes, indexed by type name.
@@ -232,10 +134,6 @@
     def getDomainName(self):
         return self.vm.getName()
 
-    def getChannel(self):
-        chan = self.vm.getChannel()
-        return chan
-    
     def getDomainInfo(self):
         return self.vm
 
@@ -433,9 +331,6 @@
     def getDomainName(self):
         return self.controller.getDomainName()
 
-    def getChannel(self):
-        return self.controller.getChannel()
-    
     def getDomainInfo(self):
         return self.controller.getDomainInfo()
     
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/event.py
--- a/tools/python/xen/xend/server/event.py     Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/server/event.py     Fri Sep  9 16:30:54 2005
@@ -174,11 +174,6 @@
         else:
             logging.removeLogStderr()
 
-    def op_debug_msg(self, name, v):
-        mode = v[1]
-        import messages
-        messages.DEBUG = (mode == 'on')
-
     def op_debug_controller(self, name, v):
         mode = v[1]
         import controller
@@ -186,7 +181,7 @@
 
     def op_domain_ls(self, name, v):
         xd = xroot.get_component("xen.xend.XendDomain")
-        return xd.domain_ls()
+        return xd.list_names()
 
     def op_domain_configure(self, name, v):
         domid = sxp.child_value(v, "dom")
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/netif.py
--- a/tools/python/xen/xend/server/netif.py     Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/server/netif.py     Fri Sep  9 16:30:54 2005
@@ -30,9 +30,7 @@
 from xen.xend.XendRoot import get_component
 from xen.xend.xenstore import DBVar
 
-from xen.xend.server import channel
-from xen.xend.server.controller import CtrlMsgRcvr, Dev, DevController
-from xen.xend.server.messages import *
+from xen.xend.server.controller import Dev, DevController
 
 class NetDev(Dev):
     """A network device.
@@ -90,12 +88,9 @@
     def __init__(self, controller, id, config, recreate=False):
         Dev.__init__(self, controller, id, config, recreate=recreate)
         self.vif = int(self.id)
-        self.evtchn = None
         self.status = None
         self.frontendDomain = self.getDomain()
-        self.frontendChannel = None
         self.backendDomain = None
-        self.backendChannel = None
         self.credit = None
         self.period = None
         self.mac = None
@@ -109,17 +104,11 @@
 
     def exportToDB(self, save=False):
         Dev.exportToDB(self, save=save)
-        if self.evtchn:
-            db = self.db.addChild("evtchn")
-            self.evtchn.saveToDB(db, save=save)
 
     def init(self, recreate=False, reboot=False):
         self.destroyed = False
         self.status = NETIF_INTERFACE_STATUS_DISCONNECTED
         self.frontendDomain = self.getDomain()
-        self.frontendChannel = self.getChannel()
-        cf = channel.channelFactory()
-        self.backendChannel = cf.openChannel(self.backendDomain)
 
     def _get_config_mac(self, config):
         vmac = sxp.child_value(config, 'mac')
@@ -287,10 +276,6 @@
             val.append(['credit', self.credit])
         if self.period:
             val.append(['period', self.period])
-        if self.evtchn:
-            val.append(['evtchn',
-                        self.evtchn['port1'],
-                        self.evtchn['port2']])
         return val
 
     def get_vifname(self):
@@ -348,42 +333,11 @@
         if recreate:
             pass
         else:
-            self.send_be_create()
             if self.credit and self.period:
-                self.send_be_creditlimit(self.credit, self.period)
+                #self.send_be_creditlimit(self.credit, self.period)
+                pass
             self.vifctl('up', vmname=self.getDomainName())
         
-    def closeEvtchn(self):
-        if self.evtchn:
-            channel.eventChannelClose(self.evtchn)
-            self.evtchn = None
-
-    def openEvtchn(self):
-        self.evtchn = channel.eventChannel(self.backendDomain, 
self.frontendDomain)
-        
-    def getEventChannelBackend(self):
-        val = 0
-        if self.evtchn:
-            val = self.evtchn['port1']
-        return val
-
-    def getEventChannelFrontend(self):
-        val = 0
-        if self.evtchn:
-            val = self.evtchn['port2']
-        return val
-
-    def send_be_create(self):
-        msg = packMsg('netif_be_create_t',
-                      { 'domid'        : self.frontendDomain,
-                        'netif_handle' : self.vif,
-                        'be_mac'       : self.be_mac or [0, 0, 0, 0, 0, 0],
-                        'mac'          : self.mac,
-                        #'vifname'      : self.vifname
-                        })
-        msg = self.backendChannel.requestResponse(msg)
-        # todo: check return status
-
     def destroy(self, change=False, reboot=False):
         """Destroy the device's resources and disconnect from the back-end
         device controller. If 'change' is true notify the front-end interface.
@@ -393,47 +347,14 @@
         self.destroyed = True
         self.status = NETIF_INTERFACE_STATUS_CLOSED
         log.debug("Destroying vif domain=%d vif=%d", self.frontendDomain, 
self.vif)
-        self.closeEvtchn()
         self.vifctl('down')
-        self.send_be_disconnect()
-        self.send_be_destroy()
         if change:
             self.reportStatus()
-
-    def send_be_disconnect(self):
-        msg = packMsg('netif_be_disconnect_t',
-                      { 'domid'        : self.frontendDomain,
-                        'netif_handle' : self.vif })
-        self.backendChannel.requestResponse(msg)
-        #todo: check return status
-
-    def send_be_destroy(self, response=None):
-        msg = packMsg('netif_be_destroy_t',
-                      { 'domid'        : self.frontendDomain,
-                        'netif_handle' : self.vif })
-        self.backendChannel.requestResponse(msg)
-        #todo: check return status
-    
-    def recv_fe_interface_connect(self, val):
-        self.openEvtchn()
-        msg = packMsg('netif_be_connect_t',
-                      { 'domid'          : self.frontendDomain,
-                        'netif_handle'   : self.vif,
-                        'evtchn'         : self.getEventChannelBackend(),
-                        'tx_shmem_frame' : val['tx_shmem_frame'],
-                        'tx_shmem_ref'   : val['tx_shmem_ref'],
-                        'rx_shmem_frame' : val['rx_shmem_frame'],
-                        'rx_shmem_ref'   : val['rx_shmem_ref'] })
-        msg = self.backendChannel.requestResponse(msg)
-        #todo: check return status
-        self.status = NETIF_INTERFACE_STATUS_CONNECTED
-        self.reportStatus()
 
     def setCreditLimit(self, credit, period):
         #todo: these params should be in sxpr and vif config.
         self.credit = credit
         self.period = period
-        self.send_be_creditlimit(credit, period)
 
     def getCredit(self):
         return self.credit
@@ -441,31 +362,10 @@
     def getPeriod(self):
         return self.period
         
-    def send_be_creditlimit(self, credit, period):
-        msg = packMsg('netif_be_creditlimit_t',
-                      { 'domid'          : self.frontendDomain,
-                        'netif_handle'   : self.vif,
-                        'credit_bytes'   : credit,
-                        'period_usec'    : period })
-        msg = self.backendChannel.requestResponse(msg)
-        # todo: check return status
-        
-    def reportStatus(self, resp=False):
-        msg = packMsg('netif_fe_interface_status_t',
-                      { 'handle' : self.vif,
-                        'status' : self.status,
-                        'evtchn' : self.getEventChannelFrontend(),
-                        'domid'  : self.backendDomain,
-                        'mac'    : self.mac })
-        if resp:
-            self.frontendChannel.writeResponse(msg)
-        else:
-            self.frontendChannel.writeRequest(msg)
-
     def interfaceChanged(self):
         """Notify the front-end that a device has been added or removed.
         """
-        self.reportStatus()
+        pass
         
 class NetifController(DevController):
     """Network interface controller. Handles all network devices for a domain.
@@ -473,25 +373,9 @@
     
     def __init__(self, vm, recreate=False):
         DevController.__init__(self, vm, recreate=recreate)
-        self.channel = None
-        self.rcvr = None
-        self.channel = None
 
     def initController(self, recreate=False, reboot=False):
         self.destroyed = False
-        self.channel = self.getChannel()
-        # Register our handlers for incoming requests.
-        self.rcvr = CtrlMsgRcvr(self.channel)
-        self.rcvr.addHandler(CMSG_NETIF_FE,
-                             CMSG_NETIF_FE_DRIVER_STATUS,
-                             self.recv_fe_driver_status)
-        self.rcvr.addHandler(CMSG_NETIF_FE,
-                             CMSG_NETIF_FE_INTERFACE_STATUS,
-                             self.recv_fe_interface_status)
-        self.rcvr.addHandler(CMSG_NETIF_FE,
-                             CMSG_NETIF_FE_INTERFACE_CONNECT,
-                             self.recv_fe_interface_connect)
-        self.rcvr.registerChannel()
         if reboot:
             self.rebootDevices()
 
@@ -501,8 +385,6 @@
         self.destroyed = True
         log.debug("Destroying netif domain=%d", self.getDomain())
         self.destroyDevices(reboot=reboot)
-        if self.rcvr:
-            self.rcvr.deregisterChannel()
 
     def sxpr(self):
         val = ['netif', ['dom', self.getDomain()]]
@@ -524,57 +406,3 @@
         
         dev = self.devices[vif]
         return dev.setCreditLimit(credit, period)
-    
-    def recv_fe_driver_status(self, msg):
-        msg = packMsg('netif_fe_driver_status_t',
-                      { 'status'     : NETIF_DRIVER_STATUS_UP,
-                        ## FIXME: max_handle should be max active interface id
-                        'max_handle' : self.getDeviceCount()
-                        #'max_handle' : self.getMaxDeviceId()
-                        })
-        # Two ways of doing it:
-        # 1) front-end requests driver status, we reply with the interface 
count,
-        #    front-end polls the interfaces,
-        #    front-end checks they are all up
-        # 2) front-end requests driver status, we reply (with anything),
-        #    we notify the interfaces,
-        #    we notify driver status up with the count
-        #    front-end checks they are all up
-        #
-        # We really want to use 1), but at the moment the xenU kernel panics
-        # in that mode, so we're sticking to 2) for now.
-        resp = False
-        if resp:
-            self.channel.writeResponse(msg)
-        else:
-            for dev in self.devices.values():
-                dev.reportStatus()
-            self.channel.writeRequest(msg)
-        return resp
-
-    def recv_fe_interface_status(self, msg):
-        val = unpackMsg('netif_fe_interface_status_t', msg)
-        vif = val['handle']
-        dev = self.findDevice(vif)
-        if dev:
-            dev.reportStatus(resp=True)
-        else:
-            log.error('Received netif_fe_interface_status for unknown vif: 
dom=%d vif=%d',
-                      self.getDomain(), vif)
-            msg = packMsg('netif_fe_interface_status_t',
-                          { 'handle' : -1,
-                            'status' : NETIF_INTERFACE_STATUS_CLOSED,
-                            });
-            self.channel.writeResponse(msg)
-        return True
-            
-    def recv_fe_interface_connect(self, msg):
-        val = unpackMsg('netif_fe_interface_connect_t', msg)
-        vif = val['handle']
-        dev = self.getDevice(vif)
-        if dev:
-            dev.recv_fe_interface_connect(val)
-        else:
-            log.error('Received netif_fe_interface_connect for unknown vif: 
dom=%d vif=%d',
-                      self.getDomain(), vif)
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/usbif.py
--- a/tools/python/xen/xend/server/usbif.py     Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/server/usbif.py     Fri Sep  9 16:30:54 2005
@@ -9,9 +9,7 @@
 from xen.xend.XendError import XendError
 from xen.xend.xenstore import DBVar
 
-from xen.xend.server import channel
 from xen.xend.server.controller import Dev, DevController
-from xen.xend.server.messages import *
 
 class UsbBackend:
     """Handler for the 'back-end' channel to a USB device driver domain
@@ -25,39 +23,15 @@
         self.connecting = False
         self.frontendDomain = self.controller.getDomain()
         self.backendDomain = dom
-        self.frontendChannel = None
-        self.backendChannel = None
 
     def init(self, recreate=False, reboot=False):
-        self.frontendChannel = self.controller.getChannel()
-        cf = channel.channelFactory()
-        self.backendChannel = cf.openChannel(self.backendDomain)
-
+        pass
+    
     def __str__(self):
         return ('<UsbifBackend frontend=%d backend=%d id=%d>'
                 % (self.frontendDomain,
                    self.backendDomain,
                    self.id))
-
-    def closeEvtchn(self):
-        if self.evtchn:
-            channel.eventChannelClose(self.evtchn)
-            self.evtchn = None
-
-    def openEvtchn(self):
-        self.evtchn = channel.eventChannel(self.backendDomain, 
self.frontendDomain)
-        
-    def getEventChannelBackend(self):
-        val = 0
-        if self.evtchn:
-            val = self.evtchn['port1']
-        return val
-
-    def getEventChannelFrontend(self):
-        val = 0
-        if self.evtchn:
-            val = self.evtchn['port2']
-        return val
 
     def connect(self, recreate=False):
         """Connect the controller to the usbif control interface.
@@ -67,78 +41,14 @@
         log.debug("Connecting usbif %s", str(self))
         if recreate or self.connected or self.connecting:
             pass
-        else:
-            self.send_be_create()
         
-    def send_be_create(self):
-        msg = packMsg('usbif_be_create_t',
-                      { 'domid'        : self.frontendDomain })
-        msg = self.backendChannel.requestResponse(msg)
-        val = unpackMsg('usbif_be_create_t', msg)
-        log.debug('>UsbifBackendController>respond_be_create> %s', str(val))
-        self.connected = True
-    
     def destroy(self, reboot=False):
         """Disconnect from the usbif control interface and destroy it.
         """
         self.destroyed = True
-        self.send_be_disconnect()
-        self.send_be_destroy()
-        self.closeEvtchn()
         
-    def send_be_disconnect(self):
-        log.debug('>UsbifBackendController>send_be_disconnect> %s', str(self))
-        msg = packMsg('usbif_be_disconnect_t',
-                      { 'domid'        : self.frontendDomain })
-        self.backendChannel.requestResponse(msg)
-
-    def send_be_destroy(self, response=None):
-        log.debug('>UsbifBackendController>send_be_destroy> %s', str(self))
-        msg = packMsg('usbif_be_destroy_t',
-                      { 'domid'        : self.frontendDomain })
-        self.backendChannel.requestResponse(msg)
-        #todo: check return status
-
-    
-    def connectInterface(self, val):
-        self.openEvtchn()
-        log.debug(">UsbifBackendController>connectInterface> connecting usbif 
to event channel %s ports=%d:%d",
-                  str(self),
-                  self.getEventChannelBackend(),
-                  self.getEventChannelFrontend())
-        msg = packMsg('usbif_be_connect_t',
-                      { 'domid'        : self.frontendDomain,
-                        'evtchn'       : self.getEventChannelBackend(),
-                        'shmem_frame'  : val['shmem_frame'],
-                        'bandwidth'    : 500 # XXX fix bandwidth!
-                        })
-        msg = self.backendChannel.requestResponse(msg)
-        self.respond_be_connect(msg)
-
-    def respond_be_connect(self, msg):
-        """Response handler for a be_connect message.
-
-        @param msg: message
-        @type  msg: xu message
-        """
-        val = unpackMsg('usbif_be_connect_t', msg)
-        log.debug('>UsbifBackendController>respond_be_connect> %s, %s', 
str(self), str(val))
-        self.send_fe_interface_status_changed()
-        log.debug(">UsbifBackendController> Successfully connected USB 
interface for domain %d" % self.frontendDomain)
-        self.controller.claim_ports()
-            
-    def send_fe_interface_status_changed(self):
-        msg = packMsg('usbif_fe_interface_status_changed_t',
-                      { 'status'    : USBIF_INTERFACE_STATUS_CONNECTED,
-                        'domid'     : self.backendDomain,
-                        'evtchn'    : self.getEventChannelFrontend(),
-                        'bandwidth' : 500,
-                        'num_ports' : len(self.controller.devices)
-                        })
-        self.frontendChannel.writeRequest(msg)
-
     def interfaceChanged(self):
-        self.send_fe_interface_status_changed()
+        pass
 
 
 class UsbDev(Dev):
@@ -153,17 +63,12 @@
         self.port = id
         self.path = None
         self.frontendDomain = self.getDomain()
-        self.frontendChannel = None
         self.backendDomain = 0
-        self.backendChannel = None
         self.configure(self.config, recreate=recreate)
 
     def init(self, recreate=False, reboot=False):
         self.destroyed = False
         self.frontendDomain = self.getDomain()
-        self.frontendChannel = self.getChannel()
-        backend = self.getBackend()
-        self.backendChannel = backend.backendChannel
         
     def configure(self, config, change=False, recreate=False):
         if change:
@@ -204,7 +109,6 @@
         """
         self.destroyed = True
         log.debug("Destroying usb domain=%d id=%s", self.frontendDomain, 
self.id)
-        self.send_be_release_port()
         if change:
             self.interfaceChanged()
 
@@ -220,27 +124,6 @@
         """
         self.getBackend().connect()
 
-    def send_be_claim_port(self):
-        log.debug(">UsbifBackendController>send_be_claim_port> about to claim 
port %s" % self.path)
-        msg = packMsg('usbif_be_claim_port_t',
-                      { 'domid'        : self.frontendDomain,
-                        'path'         : self.path,
-                        'usbif_port'   : self.port,
-                        'status'       : 0})
-        self.backendChannel.writeRequest(msg)
-        log.debug(">UsbifBackendController> Claim port completed")
-        # No need to add any callbacks, since the guest polls its virtual ports
-        # anyhow, somewhat like a UHCI controller ;-)
-
-    def send_be_release_port(self):
-        msg = packMsg('usbif_be_release_port_t',
-                      { 'domid'        : self.frontendDomain,
-                        'path'         : self.path })
-        self.backendChannel.writeRequest(msg)        
-        log.debug(">UsbifBackendController> Release port completed")
-        # No need to add any callbacks, since the guest polls its virtual ports
-        # anyhow, somewhat like a UHCI controller ;-)
-
 class UsbifController(DevController):
     """USB device interface controller. Handles all USB devices
     for a domain.
@@ -252,18 +135,9 @@
         DevController.__init__(self, vm, recreate=recreate)
         self.backends = {}
         self.backendId = 0
-        self.rcvr = None
 
     def init(self, recreate=False, reboot=False):
         self.destroyed = False
-        self.rcvr = CtrlMsgRcvr(self.getChannel())
-        self.rcvr.addHandler(CMSG_USBIF_FE,
-                             CMSG_USBIF_FE_DRIVER_STATUS_CHANGED,
-                             self.recv_fe_driver_status_changed)
-        self.rcvr.addHandler(CMSG_USBIF_FE,
-                             CMSG_USBIF_FE_INTERFACE_CONNECT,
-                             self.recv_fe_interface_connect)
-        self.rcvr.registerChannel()
         if reboot:
             self.rebootBackends()
             self.rebootDevices()
@@ -283,8 +157,6 @@
         log.debug("Destroying blkif domain=%d", self.getDomain())
         self.destroyDevices(reboot=reboot)
         self.destroyBackends(reboot=reboot)
-        if self.rcvr:
-            self.rcvr.deregisterChannel()
 
     def rebootBackends(self):
         for backend in self.backends.values():
@@ -311,40 +183,3 @@
     def destroyBackends(self, reboot=False):
         for backend in self.backends.values():
             backend.destroy(reboot=reboot)
-
-    def recv_fe_driver_status_changed(self, msg):
-        val = unpackMsg('usbif_fe_driver_status_changed_t', msg)
-        log.debug('>UsbifController>recv_fe_driver_status_changed> %s', 
str(val))
-        #todo: FIXME: For each backend?
-        msg = packMsg('usbif_fe_interface_status_changed_t',
-                      { 'status' : USBIF_INTERFACE_STATUS_DISCONNECTED,
-                        'domid'  : 0, #todo: FIXME: should be domid of backend
-                        'evtchn' : 0 })
-        msg = self.getChannel().requestResponse(msg)
-        self.disconnected_resp(msg)
-
-    def disconnected_resp(self, msg):
-        val = unpackMsg('usbif_fe_interface_status_changed_t', msg)
-        if val['status'] != USBIF_INTERFACE_STATUS_DISCONNECTED:
-            log.error(">UsbifController>disconnected_resp> unexpected status 
change")
-        else:
-            log.debug(">UsbifController>disconnected_resp> interface 
disconnected OK")
-
-    def recv_fe_interface_connect(self, msg):
-        val = unpackMsg('usbif_fe_interface_status_changed_t', msg)
-        log.debug(">UsbifController>recv_fe_interface_connect> notifying 
backend")
-        #todo: FIXME: generalise to more than one backend.
-        id = 0
-        backend = self.getBackendById(id)
-        if backend:
-            try:
-                backend.connectInterface(val)
-            except IOError, ex:
-                log.error("Exception connecting backend: %s", ex)
-        else:
-            log.error('interface connect on unknown interface: id=%d', id)
-
-    def claim_ports(self):
-        for dev in self.devices.values():
-            dev.send_be_claim_port()
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/xenstore/xsobj.py
--- a/tools/python/xen/xend/xenstore/xsobj.py   Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/xenstore/xsobj.py   Fri Sep  9 16:30:54 2005
@@ -543,10 +543,10 @@
             if not isinstance(node, DBMap): continue
             node.saveDB(sync=sync, save=save)
         # Remove db nodes not in children.
-        if sync:
-            for name in self.__db__.ls():
-                if name not in self:
-                    self.__db__.delete(name)
+        ###if sync:
+        ###    for name in self.__db__.ls():
+        ###        if name not in self:
+        ###            self.__db__.delete(name)
 
     def importFromDB(self, obj, fields):
         """Set fields in obj from db fields.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xm/create.py     Fri Sep  9 16:30:54 2005
@@ -103,12 +103,13 @@
           fn=set_true, default=0,
           use="Connect to the console after the domain is created.")
 
-gopts.var('vnc', val='no|yes',
+gopts.var('vncviewer', val='no|yes',
           fn=set_bool, default=None,
           use="""Spawn a vncviewer listening for a vnc server in the domain.
           The address of the vncviewer is passed to the domain on the kernel 
command
           line using 'VNC_SERVER=<host>:<port>'. The port used by vnc is 5500 
+ DISPLAY.
           A display value with a free port is chosen if possible.
+         Only valid when vnc=1.
           """)
 
 gopts.var('name', val='NAME',
@@ -174,6 +175,12 @@
 gopts.var('netif', val='no|yes',
           fn=set_bool, default=0,
           use="Make the domain a network interface backend.")
+
+gopts.var('tpmif', val='frontend=DOM',
+          fn=append_value, default=[],
+          use="""Make the domain a TPM interface backend. If frontend is given,
+          the frontend in that domain is connected to this backend (not
+          completely implemented, yet)""")
 
 gopts.var('disk', val='phy:DEV,VDEV,MODE[,DOM]',
           fn=append_value, default=[],
@@ -213,6 +220,12 @@
           This option may be repeated to add more than one vif.
           Specifying vifs will increase the number of interfaces as needed.""")
 
+gopts.var('vtpm', val="instance=INSTANCE,backend=DOM",
+          fn=append_value, default=[],
+          use="""Add a tpm interface. On the backend side us the the given
+          instance as virtual TPM instance. Use the backend in the given
+          domain.""")
+
 gopts.var('nics', val="NUM",
           fn=set_int, default=1,
           use="""Set the number of network interfaces.
@@ -308,6 +321,10 @@
 gopts.var('nographic', val='no|yes',
           fn=set_bool, default=0,
           use="Should device models use graphics?")
+
+gopts.var('vnc', val='',
+          fn=set_value, default=None,
+          use="""Should the device model use VNC?""")
 
 gopts.var('sdl', val='',
           fn=set_value, default=None,
@@ -368,6 +385,46 @@
     for path in vals.usb:
         config_usb = ['usb', ['path', path]]
         config_devs.append(['device', config_usb])
+
+def configure_vtpm(opts, config_devs, vals):
+    """Create the config for virtual TPM interfaces.
+    """
+    vtpm = vals.vtpm
+    vtpm_n = 1
+    for idx in range(0, vtpm_n):
+        if idx < len(vtpm):
+            d = vtpm[idx]
+            instance = d.get('instance')
+            if instance == "VTPMD":
+                instance = "0"
+            else:
+                try:
+                    if int(instance) == 0:
+                        opts.err('VM config error: vTPM instance must not be 
0.')
+                except ValueError:
+                    opts.err('Vm config error: could not parse instance 
number.')
+            backend = d.get('backend')
+            config_vtpm = ['vtpm']
+            if instance:
+                config_vtpm.append(['instance', instance])
+            if backend:
+                config_vtpm.append(['backend', backend])
+            config_devs.append(['device', config_vtpm])
+
+def configure_tpmif(opts, config_devs, vals):
+    """Create the config for virtual TPM interfaces.
+    """
+    tpmif = vals.tpmif
+    tpmif_n = 1
+    for idx in range(0, tpmif_n):
+        if idx < len(tpmif):
+            d = tpmif[idx]
+            frontend = d.get('frontend')
+            config_tpmif = ['tpmif']
+            if frontend:
+                config_tpmif.append(['frontend', frontend])
+            config_devs.append(['device', config_tpmif])
+
 
 def randomMAC():
     """Generate a random MAC address.
@@ -442,7 +499,7 @@
     """
     args = [ 'memmap', 'device_model', 'cdrom',
             'boot', 'fda', 'fdb', 'localtime', 'serial', 'macaddr', 'stdvga', 
-             'isa', 'nographic', 'vnc', 'sdl', 'display']        
+             'isa', 'nographic', 'vnc', 'vncviewer', 'sdl', 'display']   
     for a in args:
        if (vals.__dict__[a]):
            config_devs.append([a, vals.__dict__[a]])
@@ -479,6 +536,8 @@
         config.append(['backend', ['blkif']])
     if vals.netif:
         config.append(['backend', ['netif']])
+    if vals.tpmif:
+        config.append(['backend', ['tpmif']])
     if vals.restart:
         config.append(['restart', vals.restart])
 
@@ -491,6 +550,7 @@
     configure_pci(opts, config_devs, vals)
     configure_vifs(opts, config_devs, vals)
     configure_usb(opts, config_devs, vals)
+    configure_vtpm(opts, config_devs, vals)
     configure_vmx(opts, config_devs, vals)
     config += config_devs
 
@@ -539,6 +599,38 @@
         vifs.append(d)
     vals.vif = vifs
 
+def preprocess_vtpm(opts, vals):
+    if not vals.vtpm: return
+    vtpms = []
+    for vtpm in vals.vtpm:
+        d = {}
+        a = vtpm.split(',')
+        for b in a:
+            (k, v) = b.strip().split('=', 1)
+            k = k.strip()
+            v = v.strip()
+            if k not in ['backend', 'instance']:
+                opts.err('Invalid vtpm specifier: ' + vtpm)
+            d[k] = v
+        vtpms.append(d)
+    vals.vtpm = vtpms
+
+def preprocess_tpmif(opts, vals):
+    if not vals.tpmif: return
+    tpmifs = []
+    for tpmif in vals.tpmif:
+        d = {}
+        a = tpmif.split(',')
+        for b in a:
+            (k, v) = b.strip().split('=', 1)
+            k = k.strip()
+            v = v.strip()
+            if k not in ['frontend']:
+                opts.err('Invalid tpmif specifier: ' + vtpm)
+            d[k] = v
+        tpmifs.append(d)
+    vals.tpmif = tpmifs
+
 def preprocess_ip(opts, vals):
     if vals.ip or vals.dhcp != 'off':
         dummy_nfs_server = '1.2.3.4'
@@ -606,7 +698,7 @@
     """If vnc was specified, spawn a vncviewer in listen mode
     and pass its address to the domain on the kernel command line.
     """
-    if not vals.vnc or vals.dryrun: return
+    if not (vals.vnc and vals.vncviewer) or vals.dryrun: return
     vnc_display = choose_vnc_display()
     if not vnc_display:
         opts.warn("No free vnc display")
@@ -627,6 +719,8 @@
     preprocess_ip(opts, vals)
     preprocess_nfs(opts, vals)
     preprocess_vnc(opts, vals)
+    preprocess_vtpm(opts, vals)
+    preprocess_tpmif(opts, vals)
          
 def make_domain(opts, config):
     """Create, build and start a domain.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xm/main.py       Fri Sep  9 16:30:54 2005
@@ -715,9 +715,9 @@
             err("Most commands need root access.  Please try again as root")
             sys.exit(1)
         except XendError, ex:
-            if args[0] == "bogus":
-                args.remove("bogus")
             if len(args) > 0:
+                if args[0] == "bogus":
+                    args.remove("bogus")
                 handle_xend_error(argv[1], args[0], ex)
             else:
                 print "Unexpected error:", sys.exc_info()[0]
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/security/Makefile
--- a/tools/security/Makefile   Thu Sep  8 15:18:40 2005
+++ b/tools/security/Makefile   Fri Sep  9 16:30:54 2005
@@ -45,6 +45,7 @@
        $(MAKE) secpol_xml2bin
        chmod 700 ./setlabel.sh
        chmod 700 ./updategrub.sh
+       chmod 700 ./getlabel.sh
 
 secpol_tool : secpol_tool.c secpol_compat.h
        $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $<
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/security/secpol_tool.c
--- a/tools/security/secpol_tool.c      Thu Sep  8 15:18:40 2005
+++ b/tools/security/secpol_tool.c      Fri Sep  9 16:30:54 2005
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <getopt.h>
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -40,6 +41,17 @@
 #define PERROR(_m, _a...) \
 fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a ,  \
                 errno, strerror(errno))
+
+void usage(char *progname)
+{
+    printf("Use: %s \n"
+           "\t getpolicy\n"
+           "\t dumpstats\n"
+           "\t loadpolicy <binary policy file>\n"
+           "\t getssid -d <domainid> [-f]\n"
+                  "\t getssid -s <ssidref> [-f]\n", progname);
+    exit(-1);
+}
 
 static inline int do_policycmd(int xc_handle, unsigned int cmd,
                                unsigned long data)
@@ -320,7 +332,7 @@
 
         if (ret)
             printf
-                ("ERROR setting policy. Use 'xm dmesg' to see details.\n");
+                ("ERROR setting policy. Try 'xm dmesg' to see details.\n");
         else
             printf("Successfully changed policy.\n");
 
@@ -370,7 +382,7 @@
 
     if (ret < 0)
     {
-        printf("ERROR dumping policy stats. Use 'xm dmesg' to see details.\n");
+        printf("ERROR dumping policy stats. Try 'xm dmesg' to see details.\n");
         return ret;
     }
     stats = (struct acm_stats_buffer *) stats_buffer;
@@ -421,17 +433,121 @@
     }
     return ret;
 }
+/************************ get ssidref & types ******************************/
+/*
+ * the ssid (types) can be looked up either by domain id or by ssidref
+ */
+int acm_domain_getssid(int xc_handle, int argc, char * const argv[])
+{
+    /* this includes header and a set of types */
+    #define MAX_SSIDBUFFER  2000
+    int ret, i;
+    acm_op_t op;
+    struct acm_ssid_buffer *hdr;
+    unsigned char *buf;
+       int nice_print = 1;
+
+    op.cmd = ACM_GETSSID;
+    op.interface_version = ACM_INTERFACE_VERSION;
+       op.u.getssid.get_ssid_by = UNSET;
+       /* arguments
+          -d ... domain id to look up
+          -s ... ssidref number to look up
+          -f ... formatted print (scripts depend on this format)
+       */
+       while (1)
+    {
+               int c = getopt(argc, argv, "d:s:f");
+               if (c == -1)
+                       break;
+               if (c == 'd')
+        {
+                       if (op.u.getssid.get_ssid_by != UNSET)
+                               usage(argv[0]);
+                       op.u.getssid.get_ssid_by = DOMAINID;
+                       op.u.getssid.id.domainid = strtoul(optarg, NULL, 0);
+               }
+               else if (c== 's')
+        {
+                       if (op.u.getssid.get_ssid_by != UNSET)
+                               usage(argv[0]);
+                       op.u.getssid.get_ssid_by = SSIDREF;
+                       op.u.getssid.id.ssidref = strtoul(optarg, NULL, 0);
+               }
+               else if (c== 'f')
+               {
+                       nice_print = 0;
+               }
+               else
+                       usage(argv[0]);
+       }
+       if (op.u.getssid.get_ssid_by == UNSET)
+               usage(argv[0]);
+
+       buf = malloc(MAX_SSIDBUFFER);
+    if (!buf)
+        return -ENOMEM;
+
+    /* dump it and then push it down into xen/acm */
+    op.u.getssid.ssidbuf = buf;   /* out */
+    op.u.getssid.ssidbuf_size = MAX_SSIDBUFFER;
+    ret = do_acm_op(xc_handle, &op);
+
+    if (ret)
+    {
+        printf("ERROR getting ssidref. Try 'xm dmesg' to see details.\n");
+        goto out;
+    }
+    hdr = (struct acm_ssid_buffer *)buf;
+    if (hdr->len > MAX_SSIDBUFFER)
+    {
+        printf("ERROR: Buffer length inconsistent (ret=%d, hdr->len=%d)!\n",
+               ret, hdr->len);
+            return -EIO;
+    }
+       if (nice_print)
+    {
+               printf("SSID: ssidref = 0x%08x \n", hdr->ssidref);
+               printf("      P: %s, max_types = %d\n",
+                          ACM_POLICY_NAME(hdr->primary_policy_code), 
hdr->primary_max_types);
+               printf("          Types: ");
+               for (i=0; i< hdr->primary_max_types; i++)
+                       if (buf[hdr->primary_types_offset + i])
+                               printf("%02x ", i);
+                       else
+                               printf("-- ");
+               printf("\n");
+
+               printf("      S: %s, max_types = %d\n",
+                          ACM_POLICY_NAME(hdr->secondary_policy_code), 
hdr->secondary_max_types);
+               printf("          Types: ");
+               for (i=0; i< hdr->secondary_max_types; i++)
+                       if (buf[hdr->secondary_types_offset + i])
+                               printf("%02x ", i);
+                       else
+                               printf("-- ");
+               printf("\n");
+       }
+       else
+    {
+               /* formatted print for use with scripts (.sh)
+                *  update scripts when updating here (usually
+                *  used in combination with -d to determine a
+                *  running domain's label
+                */
+               printf("SSID: ssidref = 0x%08x \n", hdr->ssidref);
+       }
+
+    /* return ste ssidref */
+    if (hdr->primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
+        ret = (hdr->ssidref) & 0xffff;
+    else if (hdr->secondary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
+        ret = (hdr->ssidref) >> 16;
+ out:
+    return ret;
+}
 
 /***************************** main **************************************/
-
-void usage(char *progname)
-{
-    printf("Use: %s \n"
-           "\t getpolicy\n"
-           "\t dumpstats\n"
-           "\t loadpolicy <binary policy file>\n", progname);
-    exit(-1);
-}
 
 int main(int argc, char **argv)
 {
@@ -459,6 +575,8 @@
         if (argc != 2)
             usage(argv[0]);
         ret = acm_domain_dumpstats(acm_cmd_fd);
+    } else if (!strcmp(argv[1], "getssid")) {
+        ret = acm_domain_getssid(acm_cmd_fd, argc, argv);
     } else
         usage(argv[0]);
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/security/setlabel.sh
--- a/tools/security/setlabel.sh        Thu Sep  8 15:18:40 2005
+++ b/tools/security/setlabel.sh        Fri Sep  9 16:30:54 2005
@@ -34,275 +34,27 @@
        exec sh -c "bash $0 $*"
 fi
 
+export PATH=$PATH:.
+source labelfuncs.sh
 
 usage ()
 {
-       echo "Usage: $0 [Option] <vmfile> <label> <policy name> "
-       echo "    or $0 -l <policy name>"
+       echo "Usage: $0 [Option] <vmfile> <label> [<policy name>]"
+       echo "    or $0 -l [<policy name>]"
        echo ""
-       echo "Valid Options are:"
+       echo "Valid options are:"
        echo "-r          : to relabel a file without being prompted"
        echo ""
        echo "vmfile      : XEN vm configuration file"
-       echo "label       : the label to map"
+       echo "label       : the label to map to an ssidref"
        echo "policy name : the name of the policy, i.e. 'chwall'"
+       echo "              If the policy name is omitted, it is attempted"
+       echo "              to find the current policy's name in grub.conf."
        echo ""
-       echo "-l <policy name> is used to show valid labels in the map file"
+       echo "-l [<policy name>] is used to show valid labels in the map file 
of"
+       echo "                   the given or current policy."
        echo ""
 }
-
-
-findMapFile ()
-{
-       mapfile="./$1.map"
-       if [ -r "$mapfile" ]; then
-               return 1
-       fi
-
-       mapfile="./policies/$1/$1.map"
-       if [ -r "$mapfile" ]; then
-               return 1
-       fi
-
-       return 0
-}
-
-showLabels ()
-{
-       mapfile=$1
-       if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
-               echo "Cannot read from vm configuration file $vmfile."
-               return -1
-       fi
-
-       getPrimaryPolicy $mapfile
-       getSecondaryPolicy $mapfile
-
-       echo "The following labels are available:"
-       let line=1
-       while [ 1 ]; do
-               ITEM=`cat $mapfile |         \
-                     awk -vline=$line       \
-                         -vprimary=$primary \
-                     '{                     \
-                        if ($1 == "LABEL->SSID" &&  \
-                            $2 == "VM" &&           \
-                            $3 == primary ) {       \
-                          ctr++;                    \
-                          if (ctr == line) {        \
-                            print $4;               \
-                          }                         \
-                        }                           \
-                      } END {                       \
-                      }'`
-
-               if [ "$ITEM" == "" ]; then
-                       break
-               fi
-               if [ "$secondary" != "NULL" ]; then
-                       LABEL=`cat $mapfile |     \
-                              awk -vitem=$ITEM   \
-                              '{
-                                 if ($1 == "LABEL->SSID" && \
-                                     $2 == "VM" &&          \
-                                     $3 == "CHWALL" &&      \
-                                     $4 == item ) {         \
-                                   result = item;           \
-                                 }                          \
-                               } END {                      \
-                                   print result             \
-                               }'`
-               else
-                       LABEL=$ITEM
-               fi
-
-               if [ "$LABEL" != "" ]; then
-                       echo "$LABEL"
-                       found=1
-               fi
-               let line=line+1
-       done
-       if [ "$found" != "1" ]; then
-               echo "No labels found."
-       fi
-}
-
-getPrimaryPolicy ()
-{
-       mapfile=$1
-       primary=`cat $mapfile  |   \
-                awk '             \
-                 {                \
-                   if ( $1 == "PRIMARY" ) { \
-                     res=$2;                \
-                   }                        \
-                 } END {                    \
-                   print res;               \
-                 } '`
-}
-
-getSecondaryPolicy ()
-{
-       mapfile=$1
-       secondary=`cat $mapfile  |   \
-                awk '             \
-                 {                \
-                   if ( $1 == "SECONDARY" ) { \
-                     res=$2;                \
-                   }                        \
-                 } END {                    \
-                   print res;               \
-                 } '`
-}
-
-
-getDefaultSsid ()
-{
-       mapfile=$1
-       pol=$2
-       RES=`cat $mapfile    \
-            awk -vpol=$pol  \
-             {              \
-               if ($1 == "LABEL->SSID" && \
-                   $2 == "ANY"         && \
-                   $3 == pol           && \
-                   $4 == "DEFAULT"       ) {\
-                     res=$5;                \
-               }                            \
-             } END {                        \
-               printf "%04x", strtonum(res) \
-            }'`
-       echo "default NULL mapping is $RES"
-       defaultssid=$RES
-}
-
-relabel ()
-{
-       vmfile=$1
-       label=$2
-       mapfile=$3
-       mode=$4
-
-       if [ ! -r "$vmfile" ]; then
-               echo "Cannot read from vm configuration file $vmfile."
-               return -1
-       fi
-
-       if [ ! -w "$vmfile" ]; then
-               echo "Cannot write to vm configuration file $vmfile."
-               return -1
-       fi
-
-       if [ ! -r "$mapfile" ] ; then
-               echo "Cannot read mapping file $mapfile."
-               return -1
-       fi
-
-       # Determine which policy is primary, which sec.
-       getPrimaryPolicy $mapfile
-       getSecondaryPolicy $mapfile
-
-       # Calculate the primary policy's SSIDREF
-       if [ "$primary" == "NULL" ]; then
-               SSIDLO="0000"
-       else
-               SSIDLO=`cat $mapfile |                    \
-                       awk -vlabel=$label                \
-                           -vprimary=$primary            \
-                          '{                             \
-                             if ( $1 == "LABEL->SSID" && \
-                                  $2 == "VM" &&          \
-                                  $3 == primary  &&      \
-                                  $4 == label ) {        \
-                               result=$5                 \
-                             }                           \
-                          } END {                        \
-                            if (result != "" )           \
-                              {printf "%04x", strtonum(result)}\
-                          }'`
-       fi
-
-       # Calculate the secondary policy's SSIDREF
-       if [ "$secondary" == "NULL" ]; then
-               SSIDHI="0000"
-       else
-               SSIDHI=`cat $mapfile |                    \
-                       awk -vlabel=$label                \
-                           -vsecondary=$secondary        \
-                          '{                             \
-                             if ( $1 == "LABEL->SSID" && \
-                                  $2 == "VM"          && \
-                                  $3 == secondary     && \
-                                  $4 == label ) {        \
-                               result=$5                 \
-                             }                           \
-                           }  END {                      \
-                             if (result != "" )          \
-                               {printf "%04x", strtonum(result)}\
-                           }'`
-       fi
-
-       if [ "$SSIDLO" == "" -o \
-            "$SSIDHI" == "" ]; then
-               echo "Could not map the given label '$label'."
-               return -1
-       fi
-
-       ACM_POLICY=`cat $mapfile |             \
-           awk ' { if ( $1 == "POLICY" ) {    \
-                     result=$2                \
-                   }                          \
-                 }                            \
-                 END {                        \
-                   if (result != "") {        \
-                     printf result            \
-                   }                          \
-                 }'`
-
-       if [ "$ACM_POLICY" == "" ]; then
-               echo "Could not find 'POLICY' entry in map file."
-               return -1
-       fi
-
-       SSIDREF="0x$SSIDHI$SSIDLO"
-
-       if [ "$mode" != "relabel" ]; then
-               RES=`cat $vmfile |  \
-                    awk '{         \
-                      if ( substr($1,0,7) == "ssidref" ) {\
-                        print $0;             \
-                      }                       \
-                    }'`
-               if [ "$RES" != "" ]; then
-                       echo "Do you want to overwrite the existing mapping 
($RES)? (y/N)"
-                       read user
-                       if [ "$user" != "y" -a "$user" != "Y" ]; then
-                               echo "Aborted."
-                               return 0
-                       fi
-               fi
-       fi
-
-       #Write the output
-       vmtmp1="/tmp/__setlabel.tmp1"
-       vmtmp2="/tmp/__setlabel.tmp2"
-       touch $vmtmp1
-       touch $vmtmp2
-       if [ ! -w "$vmtmp1" -o ! -w "$vmtmp2" ]; then
-               echo "Cannot create temporary files. Aborting."
-               return -1
-       fi
-       RES=`sed -e '/^#ACM_POLICY/d' $vmfile > $vmtmp1`
-       RES=`sed -e '/^#ACM_LABEL/d' $vmtmp1 > $vmtmp2`
-       RES=`sed -e '/^ssidref/d' $vmtmp2 > $vmtmp1`
-       echo "#ACM_POLICY=$ACM_POLICY" >> $vmtmp1
-       echo "#ACM_LABEL=$label" >> $vmtmp1
-       echo "ssidref = $SSIDREF" >> $vmtmp1
-       mv -f $vmtmp1 $vmfile
-       rm -rf $vmtmp1 $vmtmp2
-       echo "Mapped label '$label' to ssidref '$SSIDREF'."
-}
-
 
 
 if [ "$1" == "-r" ]; then
@@ -317,10 +69,25 @@
 
 if [ "$mode" == "show" ]; then
        if [ "$1" == "" ]; then
-               usage
-               exit -1;
+               findGrubConf
+               ret=$?
+               if [ $ret -eq 0 ]; then
+                       echo "Could not find grub.conf"
+                       exit -1;
+               fi
+               findPolicyInGrub $grubconf
+               if [ "$policy" != "" ]; then
+                       echo "Assuming policy to be '$policy'.";
+               else
+                       echo "Could not find policy."
+                       exit -1;
+               fi
+       else
+               policy=$3;
        fi
-       findMapFile $1
+
+
+       findMapFile $policy
        res=$?
        if [ "$res" != "0" ]; then
                showLabels $mapfile
@@ -330,11 +97,29 @@
 elif [ "$mode" == "usage" ]; then
        usage
 else
+       if [ "$2" == "" ]; then
+               usage
+               exit -1
+       fi
        if [ "$3" == "" ]; then
-               usage
-               exit -1;
+               findGrubConf
+               ret=$?
+               if [ $ret -eq 0 ]; then
+                       echo "Could not find grub.conf"
+                       exit -1;
+               fi
+               findPolicyInGrub $grubconf
+               if [ "$policy" != "" ]; then
+                       echo "Assuming policy to be '$policy'.";
+               else
+                       echo "Could not find policy."
+                       exit -1;
+               fi
+
+       else
+               policy=$3;
        fi
-       findMapFile $3
+       findMapFile $policy
        res=$?
        if [ "$res" != "0" ]; then
                relabel $1 $2 $mapfile $mode
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcutils/Makefile
--- a/tools/xcutils/Makefile    Thu Sep  8 15:18:40 2005
+++ b/tools/xcutils/Makefile    Fri Sep  9 16:30:54 2005
@@ -18,8 +18,6 @@
 PROGRAMS_INSTALL_DIR   = /usr/libexec/xen
 
 INCLUDES += -I $(XEN_LIBXC)
-
-CC := gcc
 
 CFLAGS += -Wall -Werror -O3 -fno-strict-aliasing
 CFLAGS += $(INCLUDES)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcutils/xc_restore.c
--- a/tools/xcutils/xc_restore.c        Thu Sep  8 15:18:40 2005
+++ b/tools/xcutils/xc_restore.c        Fri Sep  9 16:30:54 2005
@@ -17,22 +17,27 @@
 int
 main(int argc, char **argv)
 {
-    unsigned int xc_fd, io_fd, domid, nr_pfns, evtchn;
+    unsigned int xc_fd, io_fd, domid, nr_pfns, store_evtchn, console_evtchn;
     int ret;
-    unsigned long mfn;
+    unsigned long store_mfn, console_mfn;
 
-    if (argc != 6)
-       errx(1, "usage: %s xcfd iofd domid nr_pfns evtchn", argv[0]);
+    if (argc != 7)
+       errx(1,
+            "usage: %s xcfd iofd domid nr_pfns store_evtchn console_evtchn",
+            argv[0]);
 
     xc_fd = atoi(argv[1]);
     io_fd = atoi(argv[2]);
     domid = atoi(argv[3]);
     nr_pfns = atoi(argv[4]);
-    evtchn = atoi(argv[5]);
+    store_evtchn = atoi(argv[5]);
+    console_evtchn = atoi(argv[6]);
 
-    ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, evtchn, &mfn);
+    ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
+                          &store_mfn, console_evtchn, &console_mfn);
     if (ret == 0) {
-       printf("store-mfn %li\n", mfn);
+       printf("store-mfn %li\n", store_mfn);
+       printf("console-mfn %li\n", console_mfn);
        fflush(stdout);
     }
     return ret;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcutils/xc_save.c
--- a/tools/xcutils/xc_save.c   Thu Sep  8 15:18:40 2005
+++ b/tools/xcutils/xc_save.c   Fri Sep  9 16:30:54 2005
@@ -17,14 +17,17 @@
 int
 main(int argc, char **argv)
 {
-    unsigned int xc_fd, io_fd, domid;
+    unsigned int xc_fd, io_fd, domid, maxit, max_f, flags; 
 
-    if (argc != 4)
-       errx(1, "usage: %s xcfd iofd domid", argv[0]);
+    if (argc != 7)
+       errx(1, "usage: %s xcfd iofd domid maxit maxf flags", argv[0]);
 
     xc_fd = atoi(argv[1]);
     io_fd = atoi(argv[2]);
     domid = atoi(argv[3]);
+    maxit = atoi(argv[4]);
+    max_f = atoi(argv[5]);
+    flags = atoi(argv[6]);
 
-    return xc_linux_save(xc_fd, io_fd, domid);
+    return xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags);
 }
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstat/Makefile
--- a/tools/xenstat/Makefile    Thu Sep  8 15:18:40 2005
+++ b/tools/xenstat/Makefile    Fri Sep  9 16:30:54 2005
@@ -3,7 +3,11 @@
 
 SUBDIRS :=
 SUBDIRS += libxenstat
+
+# This doesn't cross-compile (cross-compile environments rarely have curses)
+ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
 SUBDIRS += xentop
+endif
 
 .PHONY: all install clean
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/Makefile
--- a/tools/xenstore/Makefile   Thu Sep  8 15:18:40 2005
+++ b/tools/xenstore/Makefile   Fri Sep  9 16:30:54 2005
@@ -8,15 +8,16 @@
 INSTALL_DIR     = $(INSTALL) -d -m0755
 
 PROFILE=#-pg
-BASECFLAGS=-Wall -W -g 
+BASECFLAGS=-Wall -W -g -Werror
 # Make gcc generate dependencies.
 BASECFLAGS += -Wp,-MD,.$(@F).d
 PROG_DEP = .*.d
-#BASECFLAGS+= -O3 $(PROFILE)
+BASECFLAGS+= -O3 $(PROFILE)
 #BASECFLAGS+= -I$(XEN_ROOT)/tools
 BASECFLAGS+= -I$(XEN_ROOT)/tools/libxc
 BASECFLAGS+= -I$(XEN_ROOT)/xen/include/public
 BASECFLAGS+= -I.
+BASECFLAGS+= -I$(XEN_ROOT)/linux-2.6-xen-sparse/include/asm-xen/linux-public
 
 CFLAGS  += $(BASECFLAGS)
 LDFLAGS += $(PROFILE) -L$(XEN_LIBXC)
@@ -24,15 +25,22 @@
 TESTFLAGS= -DTESTING
 TESTENV  = XENSTORED_ROOTDIR=$(TESTDIR) XENSTORED_RUNDIR=$(TESTDIR)
 
-all: xen xenstored libxenstore.so
+CLIENTS := xenstore-read xenstore-rm xenstore-write
+CLIENTS_OBJS := $(patsubst xenstore-%,xenstore_%.o,$(CLIENTS))
 
-testcode: xen xs_test xenstored_test xs_random xs_dom0_test
+all: libxenstore.so xenstored $(CLIENTS)
 
-xen:
-       ln -sf $(XEN_ROOT)/xen/include/public $@
+testcode: xs_test xenstored_test xs_random xs_dom0_test
 
 xenstored: xenstored_core.o xenstored_watch.o xenstored_domain.o 
xenstored_transaction.o xs_lib.o talloc.o utils.o
        $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -o $@
+
+$(CLIENTS): libxenstore.so
+$(CLIENTS): xenstore-%: xenstore_%.o
+       $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -L. -lxenstore -o $@
+
+$(CLIENTS_OBJS): xenstore_%.o: xenstore_client.c
+       $(COMPILE.c) -DCLIENT_$(*F) -o $@ $<
 
 xenstored_test: xenstored_core_test.o xenstored_watch_test.o 
xenstored_domain_test.o xenstored_transaction_test.o xs_lib.o talloc_test.o 
fake_libxc.o utils.o
        $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
@@ -58,7 +66,7 @@
 
 clean: testsuite-clean
        rm -f *.o *.opic *.so
-       rm -f xen xenstored xs_random xs_stress xs_crashme
+       rm -f xenstored xs_random xs_stress xs_crashme
        rm -f xs_test xenstored_test xs_dom0_test
        $(RM) $(PROG_DEP)
 
@@ -72,10 +80,10 @@
 
 fullcheck: testsuite-run randomcheck stresstest
 
-testsuite-run: xen xenstored_test xs_test
+testsuite-run: xenstored_test xs_test
        $(TESTENV) testsuite/test.sh && echo
 
-testsuite-fast: xen xenstored_test xs_test
+testsuite-fast: xenstored_test xs_test
        @$(TESTENV) testsuite/test.sh --fast
 
 testsuite-clean:
@@ -111,12 +119,14 @@
 tarball: clean
        cd .. && tar -c -j -v -h -f xenstore.tar.bz2 xenstore/
 
-install: xenstored libxenstore.so
+install: libxenstore.so xenstored $(CLIENTS)
        $(INSTALL_DIR) -p $(DESTDIR)/var/run/xenstored
        $(INSTALL_DIR) -p $(DESTDIR)/var/lib/xenstored
+       $(INSTALL_DIR) -p $(DESTDIR)/usr/bin
        $(INSTALL_DIR) -p $(DESTDIR)/usr/sbin
        $(INSTALL_DIR) -p $(DESTDIR)/usr/include
        $(INSTALL_PROG) xenstored $(DESTDIR)/usr/sbin
+       $(INSTALL_PROG) $(CLIENTS) $(DESTDIR)/usr/bin
        $(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR)
        $(INSTALL_DATA) libxenstore.so $(DESTDIR)/usr/$(LIBDIR)
        $(INSTALL_DATA) xs.h $(DESTDIR)/usr/include
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xenstored.h
--- a/tools/xenstore/xenstored.h        Thu Sep  8 15:18:40 2005
+++ b/tools/xenstore/xenstored.h        Fri Sep  9 16:30:54 2005
@@ -42,7 +42,7 @@
        XS_OP_READ_ONLY = XS_TRANSACTION_END,
        XS_INTRODUCE,
        XS_RELEASE,
-       XS_GETDOMAINPATH,
+       XS_GET_DOMAIN_PATH,
        XS_WRITE,
        XS_MKDIR,
        XS_RM,
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xenstored_core.c
--- a/tools/xenstore/xenstored_core.c   Thu Sep  8 15:18:40 2005
+++ b/tools/xenstore/xenstored_core.c   Fri Sep  9 16:30:54 2005
@@ -49,6 +49,8 @@
 #include "xenstored_watch.h"
 #include "xenstored_transaction.h"
 #include "xenstored_domain.h"
+#include "xenctrl.h"
+#include "xen/io/domain_controller.h"
 
 static bool verbose;
 LIST_HEAD(connections);
@@ -140,7 +142,7 @@
        case XS_TRANSACTION_END: return "TRANSACTION_END";
        case XS_INTRODUCE: return "INTRODUCE";
        case XS_RELEASE: return "RELEASE";
-       case XS_GETDOMAINPATH: return "GETDOMAINPATH";
+       case XS_GET_DOMAIN_PATH: return "GET_DOMAIN_PATH";
        case XS_WRITE: return "WRITE";
        case XS_MKDIR: return "MKDIR";
        case XS_RM: return "RM";
@@ -719,7 +721,7 @@
        char *slash = strrchr(node + 1, '/');
        if (!slash)
                return talloc_strdup(node, "/");
-       return talloc_asprintf(node, "%.*s", slash - node, node);
+       return talloc_asprintf(node, "%.*s", (int)(slash - node), node);
 }
 
 static enum xs_perm_type perm_for_id(domid_t id,
@@ -828,6 +830,15 @@
        return false;
 }
 
+bool check_event_node(const char *node)
+{
+       if (!node || !strstarts(node, "@")) {
+               errno = EINVAL;
+               return false;
+       }
+       return true;
+}
+
 static void send_directory(struct connection *conn, const char *node)
 {
        char *path, *reply;
@@ -901,7 +912,7 @@
        if (slash)
                *slash = '\0';
 
-       dest = talloc_asprintf(dir, "%.*s", dot - dir, dir);
+       dest = talloc_asprintf(dir, "%.*s", (int)(dot - dir), dir);
        return rename(dir, dest) == 0;
 }
 
@@ -1277,7 +1288,7 @@
                do_release(conn, onearg(in));
                break;
 
-       case XS_GETDOMAINPATH:
+       case XS_GET_DOMAIN_PATH:
                do_get_domain_path(conn, onearg(in));
                break;
 
@@ -1295,8 +1306,12 @@
 
 static void consider_message(struct connection *conn)
 {
-       struct buffered_data *in = NULL;
-       enum xsd_sockmsg_type type = conn->in->hdr.msg.type;
+       /*
+        * 'volatile' qualifier prevents register allocation which fixes:
+        *   warning: variable 'xxx' might be clobbered by 'longjmp' or 'vfork'
+        */
+       struct buffered_data *volatile in = NULL;
+       enum xsd_sockmsg_type volatile type = conn->in->hdr.msg.type;
        jmp_buf talloc_fail;
 
        assert(conn->state == OK);
@@ -1434,7 +1449,11 @@
 
 struct connection *new_connection(connwritefn_t *write, connreadfn_t *read)
 {
-       struct connection *new;
+       /*
+        * 'volatile' qualifier prevents register allocation which fixes:
+        *   warning: variable 'xxx' might be clobbered by 'longjmp' or 'vfork'
+        */
+       struct connection *volatile new;
        jmp_buf talloc_fail;
 
        new = talloc(talloc_autofree_context(), struct connection);
@@ -1628,12 +1647,13 @@
 }
 
 
-static struct option options[] = { { "no-fork", 0, NULL, 'N' },
-                                  { "verbose", 0, NULL, 'V' },
-                                  { "output-pid", 0, NULL, 'P' },
-                                  { "trace-file", 1, NULL, 'T' },
-                                  { "pid-file", 1, NULL, 'F' },
-                                  { NULL, 0, NULL, 0 } };
+static struct option options[] = {
+       { "pid-file", 1, NULL, 'F' },
+       { "no-fork", 0, NULL, 'N' },
+       { "output-pid", 0, NULL, 'P' },
+       { "trace-file", 1, NULL, 'T' },
+       { "verbose", 0, NULL, 'V' },
+       { NULL, 0, NULL, 0 } };
 
 int main(int argc, char *argv[])
 {
@@ -1644,13 +1664,14 @@
        bool outputpid = false;
        const char *pidfile = NULL;
 
-       while ((opt = getopt_long(argc, argv, "DVT:", options, NULL)) != -1) {
+       while ((opt = getopt_long(argc, argv, "F:NPT:V", options,
+                                 NULL)) != -1) {
                switch (opt) {
+               case 'F':
+                       pidfile = optarg;
+                       break;
                case 'N':
                        dofork = false;
-                       break;
-               case 'V':
-                       verbose = true;
                        break;
                case 'P':
                        outputpid = true;
@@ -1662,8 +1683,9 @@
                                            optarg);
                         write(tracefd, "\n***\n", strlen("\n***\n"));
                        break;
-               case 'F':
-                       pidfile = optarg;
+               case 'V':
+                       verbose = true;
+                       break;
                }
        }
        if (optind != argc)
@@ -1812,6 +1834,7 @@
                /* If transactions ended, we might be able to do more work. */
                unblock_connections();
 
-               max = initialize_set(&inset, &outset, *sock,*ro_sock,event_fd);
-       }
-}
+               max = initialize_set(&inset, &outset, *sock, *ro_sock,
+                                    event_fd);
+       }
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xenstored_core.h
--- a/tools/xenstore/xenstored_core.h   Thu Sep  8 15:18:40 2005
+++ b/tools/xenstore/xenstored_core.h   Fri Sep  9 16:30:54 2005
@@ -133,6 +133,9 @@
 bool check_node_perms(struct connection *conn, const char *node,
                      enum xs_perm_type perm);
 
+/* Check if node is an event node. */
+bool check_event_node(const char *node);
+
 /* Path to this node outside transaction. */
 char *node_dir_outside_transaction(const char *node);
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xenstored_domain.c
--- a/tools/xenstore/xenstored_domain.c Thu Sep  8 15:18:40 2005
+++ b/tools/xenstore/xenstored_domain.c Fri Sep  9 16:30:54 2005
@@ -1,4 +1,4 @@
-/* 
+/*
     Domain communications for Xen Store Daemon.
     Copyright (C) 2005 Rusty Russell IBM Corporation
 
@@ -33,10 +33,12 @@
 #include "talloc.h"
 #include "xenstored_core.h"
 #include "xenstored_domain.h"
+#include "xenstored_watch.h"
 #include "xenstored_test.h"
 
 static int *xc_handle;
 static int eventchn_fd;
+static int virq_port;
 static unsigned int ringbuf_datasize;
 
 struct domain
@@ -216,17 +218,6 @@
        return 0;
 }
 
-static struct domain *find_domain(u16 port)
-{
-       struct domain *i;
-
-       list_for_each_entry(i, &domains, list) {
-               if (i->port == port)
-                       return i;
-       }
-       return NULL;
-}
-
 /* We scan all domains rather than use the information given here. */
 void handle_event(int event_fd)
 {
@@ -234,6 +225,10 @@
 
        if (read(event_fd, &port, sizeof(port)) != sizeof(port))
                barf_perror("Failed to read from event fd");
+
+       if (port == virq_port)
+               domain_cleanup();
+
 #ifndef TESTING
        if (write(event_fd, &port, sizeof(port)) != sizeof(port))
                barf_perror("Failed to write to event fd");
@@ -319,6 +314,9 @@
 
        /* Now domain belongs to its connection. */
        talloc_steal(domain->conn, domain);
+
+       fire_watches(conn, "@introduceDomain", false);
+
        send_ack(conn, XS_INTRODUCE);
 }
 
@@ -367,7 +365,30 @@
        }
 
        talloc_free(domain->conn);
+
+       fire_watches(NULL, "@releaseDomain", false);
+
        send_ack(conn, XS_RELEASE);
+}
+
+void domain_cleanup(void)
+{
+       xc_dominfo_t dominfo;
+       struct domain *domain, *tmp;
+       int released = 0;
+
+       list_for_each_entry_safe(domain, tmp, &domains, list) {
+               if (xc_domain_getinfo(*xc_handle, domain->domid, 1,
+                                     &dominfo) == 1 &&
+                   dominfo.domid == domain->domid &&
+                   !dominfo.dying && !dominfo.crashed && !dominfo.shutdown)
+                       continue;
+               talloc_free(domain->conn);
+               released++;
+       }
+
+       if (released)
+               fire_watches(NULL, "@releaseDomain", false);
 }
 
 void do_get_domain_path(struct connection *conn, const char *domid_str)
@@ -386,10 +407,10 @@
        else
                domain = find_domain_by_domid(domid);
 
-       if (!domain) 
+       if (!domain)
                send_error(conn, ENOENT);
        else
-               send_reply(conn, XS_GETDOMAINPATH, domain->path,
+               send_reply(conn, XS_GET_DOMAIN_PATH, domain->path,
                           strlen(domain->path) + 1);
 }
 
@@ -412,26 +433,55 @@
 {
 }
 
+#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
+#define EVTCHN_DEV_MAJOR 10
+#define EVTCHN_DEV_MINOR 201
+
 /* Returns the event channel handle. */
 int domain_init(void)
 {
+       struct stat st;
+
        /* The size of the ringbuffer: half a page minus head structure. */
        ringbuf_datasize = getpagesize() / 2 - sizeof(struct ringbuf_head);
 
        xc_handle = talloc(talloc_autofree_context(), int);
        if (!xc_handle)
                barf_perror("Failed to allocate domain handle");
+
        *xc_handle = xc_interface_open();
        if (*xc_handle < 0)
                barf_perror("Failed to open connection to hypervisor");
+
        talloc_set_destructor(xc_handle, close_xc_handle);
 
 #ifdef TESTING
        eventchn_fd = fake_open_eventchn();
 #else
-       eventchn_fd = open("/dev/xen/evtchn", O_RDWR);
+       /* Make sure any existing device file links to correct device. */
+       if ((lstat(EVTCHN_DEV_NAME, &st) != 0) || !S_ISCHR(st.st_mode) ||
+           (st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)))
+               (void)unlink(EVTCHN_DEV_NAME);
+
+ reopen:
+       eventchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
+       if (eventchn_fd == -1) {
+               if ((errno == ENOENT) &&
+                   ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
+                   (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600,
+                          makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) == 0))
+                       goto reopen;
+               return -errno;
+       }
 #endif
        if (eventchn_fd < 0)
-               barf_perror("Failed to open connection to hypervisor");
+               barf_perror("Failed to open evtchn device");
+
+       if (xc_evtchn_bind_virq(*xc_handle, VIRQ_DOM_EXC, &virq_port))
+               barf_perror("Failed to bind to domain exception virq");
+
+       if (ioctl(eventchn_fd, EVENTCHN_BIND, virq_port) != 0)
+               barf_perror("Failed to bind to domain exception virq port");
+
        return eventchn_fd;
 }
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xenstored_domain.h
--- a/tools/xenstore/xenstored_domain.h Thu Sep  8 15:18:40 2005
+++ b/tools/xenstore/xenstored_domain.h Fri Sep  9 16:30:54 2005
@@ -28,6 +28,10 @@
 /* domid */
 void do_release(struct connection *conn, const char *domid_str);
 
+/* Enumerate domains and release connections for non-existant or dying
+ * domains. */
+void domain_cleanup(void);
+
 /* domid */
 void do_get_domain_path(struct connection *conn, const char *domid_str);
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xenstored_watch.c
--- a/tools/xenstore/xenstored_watch.c  Thu Sep  8 15:18:40 2005
+++ b/tools/xenstore/xenstored_watch.c  Fri Sep  9 16:30:54 2005
@@ -103,7 +103,8 @@
        /* Check read permission: no permission, no watch event.
         * If it doesn't exist, we need permission to read parent.
         */
-       if (!check_node_perms(conn, node, XS_PERM_READ|XS_PERM_ENOENT_OK)) {
+       if (!check_node_perms(conn, node, XS_PERM_READ|XS_PERM_ENOENT_OK) &&
+           !check_event_node(node)) {
                fprintf(stderr, "No permission for %s\n", node);
                return;
        }
@@ -131,7 +132,7 @@
        struct watch *watch;
 
        /* During transactions, don't fire watches. */
-       if (conn->transaction)
+       if (conn && conn->transaction)
                return;
 
        /* Create an event for each watch.  Don't send to self. */
@@ -213,11 +214,16 @@
                return;
        }
 
-       relative = !strstarts(vec[0], "/");
-       vec[0] = canonicalize(conn, vec[0]);
-       if (!is_valid_nodename(vec[0])) {
-               send_error(conn, errno);
-               return;
+       if (strstarts(vec[0], "@")) {
+               relative = false;
+               /* check if valid event */
+       } else {
+               relative = !strstarts(vec[0], "/");
+               vec[0] = canonicalize(conn, vec[0]);
+               if (!is_valid_nodename(vec[0])) {
+                       send_error(conn, errno);
+                       return;
+               }
        }
 
        watch = talloc(conn, struct watch);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xs.c
--- a/tools/xenstore/xs.c       Thu Sep  8 15:18:40 2005
+++ b/tools/xenstore/xs.c       Fri Sep  9 16:30:54 2005
@@ -31,14 +31,17 @@
 #include <signal.h>
 #include <stdint.h>
 #include <errno.h>
+#include <sys/ioctl.h>
 #include "xs.h"
 #include "xenstored.h"
 #include "xs_lib.h"
 #include "utils.h"
+#include "xenbus_dev.h"
 
 struct xs_handle
 {
        int fd;
+       enum { SOCK, DEV } type;
 };
 
 /* Get the socket from the store daemon handle.
@@ -65,17 +68,39 @@
                h = malloc(sizeof(*h));
                if (h) {
                        h->fd = sock;
+                       h->type = SOCK;
                        return h;
                }
        }
 
        saved_errno = errno;
        close(sock);
-       free(h);
        errno = saved_errno;
        return NULL;
 }
 
+static struct xs_handle *get_dev(const char *connect_to)
+{
+       int fd, saved_errno;
+       struct xs_handle *h = NULL;
+
+       fd = open(connect_to, O_RDONLY);
+       if (fd < 0)
+               return NULL;
+
+       h = malloc(sizeof(*h));
+       if (h) {
+               h->fd = fd;
+               h->type = DEV;
+               return h;
+       }
+
+       saved_errno = errno;
+       close(fd);
+       errno = saved_errno;
+       return NULL;
+}
+
 struct xs_handle *xs_daemon_open(void)
 {
        return get_socket(xs_daemon_socket());
@@ -84,6 +109,11 @@
 struct xs_handle *xs_daemon_open_readonly(void)
 {
        return get_socket(xs_daemon_socket_ro());
+}
+
+struct xs_handle *xs_domain_open(void)
+{
+       return get_dev(xs_domain_dev());
 }
 
 void xs_daemon_close(struct xs_handle *h)
@@ -160,9 +190,9 @@
 }
 
 /* Send message to xs, get malloc'ed reply.  NULL and set errno on error. */
-static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
-                     const struct iovec *iovec, unsigned int num_vecs,
-                     unsigned int *len)
+static void *xs_talkv_sock(struct xs_handle *h, enum xsd_sockmsg_type type,
+                          const struct iovec *iovec, unsigned int num_vecs,
+                          unsigned int *len)
 {
        struct xsd_sockmsg msg;
        void *ret = NULL;
@@ -220,6 +250,54 @@
        close(h->fd);
        h->fd = -1;
        errno = saved_errno;
+       return NULL;
+}
+
+/* Send message to xs, get malloc'ed reply.  NULL and set errno on error. */
+static void *xs_talkv_dev(struct xs_handle *h, enum xsd_sockmsg_type type,
+                         const struct iovec *iovec, unsigned int num_vecs,
+                         unsigned int *len)
+{
+       struct xenbus_dev_talkv dt;
+       char *buf;
+       int err, buflen = 1024;
+
+ again:
+       buf = malloc(buflen);
+       if (buf == NULL) {
+               errno = ENOMEM;
+               return NULL;
+       }
+       dt.type = type;
+       dt.iovec = (struct kvec *)iovec;
+       dt.num_vecs = num_vecs;
+       dt.buf = buf;
+       dt.len = buflen;
+       err = ioctl(h->fd, IOCTL_XENBUS_DEV_TALKV, &dt);
+       if (err < 0) {
+               free(buf);
+               errno = err;
+               return NULL;
+       }
+       if (err > buflen) {
+               free(buf);
+               buflen = err;
+               goto again;
+       }
+       if (len)
+               *len = err;
+       return buf;
+}
+
+/* Send message to xs, get malloc'ed reply.  NULL and set errno on error. */
+static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
+                     const struct iovec *iovec, unsigned int num_vecs,
+                     unsigned int *len)
+{
+       if (h->type == SOCK)
+               return xs_talkv_sock(h, type, iovec, num_vecs, len);
+       if (h->type == DEV)
+               return xs_talkv_dev(h, type, iovec, num_vecs, len);
        return NULL;
 }
 
@@ -535,13 +613,23 @@
        return xs_bool(xs_single(h, XS_RELEASE, domid_str, NULL));
 }
 
+char *xs_get_domain_path(struct xs_handle *h, domid_t domid)
+{
+       char domid_str[MAX_STRLEN(domid)];
+
+       sprintf(domid_str, "%u", domid);
+
+       return xs_single(h, XS_GET_DOMAIN_PATH, domid_str, NULL);
+}
+
 bool xs_shutdown(struct xs_handle *h)
 {
        bool ret = xs_bool(xs_single(h, XS_SHUTDOWN, "", NULL));
        if (ret) {
                char c;
                /* Wait for it to actually shutdown. */
-               read(h->fd, &c, 1);
+               while ((read(h->fd, &c, 1) < 0) && (errno == EINTR))
+                       continue;
        }
        return ret;
 }
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xs.h
--- a/tools/xenstore/xs.h       Thu Sep  8 15:18:40 2005
+++ b/tools/xenstore/xs.h       Fri Sep  9 16:30:54 2005
@@ -30,6 +30,7 @@
  * Returns a handle or NULL.
  */
 struct xs_handle *xs_daemon_open(void);
+struct xs_handle *xs_domain_open(void);
 
 /* Connect to the xs daemon (readonly for non-root clients).
  * Returns a handle or NULL.
@@ -133,6 +134,10 @@
  */
 bool xs_release_domain(struct xs_handle *h, domid_t domid);
 
+/* Query the home path of a domain.
+ */
+char *xs_get_domain_path(struct xs_handle *h, domid_t domid);
+
 /* Only useful for DEBUG versions */
 char *xs_debug_command(struct xs_handle *h, const char *cmd,
                       void *data, unsigned int len);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xs_lib.c
--- a/tools/xenstore/xs_lib.c   Thu Sep  8 15:18:40 2005
+++ b/tools/xenstore/xs_lib.c   Fri Sep  9 16:30:54 2005
@@ -64,6 +64,12 @@
        static char buf[PATH_MAX];
        sprintf(buf, "%s/transactions", xs_daemon_rootdir());
        return buf;
+}
+
+const char *xs_domain_dev(void)
+{
+       char *s = getenv("XENSTORED_DOMAIN_DEV");
+       return (s ? s : "/proc/xen/xenbus");
 }
 
 /* Simple routines for writing to sockets, etc. */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xs_lib.h
--- a/tools/xenstore/xs_lib.h   Thu Sep  8 15:18:40 2005
+++ b/tools/xenstore/xs_lib.h   Fri Sep  9 16:30:54 2005
@@ -48,6 +48,7 @@
 const char *xs_daemon_socket_ro(void);
 const char *xs_daemon_store(void);
 const char *xs_daemon_transactions(void);
+const char *xs_domain_dev(void);
 
 /* Simple write function: loops for you. */
 bool xs_write_all(int fd, const void *data, unsigned int len);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xentrace/formats
--- a/tools/xentrace/formats    Thu Sep  8 15:18:40 2005
+++ b/tools/xentrace/formats    Fri Sep  9 16:30:54 2005
@@ -15,3 +15,7 @@
 0x00080001     CPU%(cpu)d      %(tsc)d         VMX_VMEXIT              [ domid 
= 0x%(1)08x, eip = 0x%(2)08x, reason = 0x%(3)08x ]
 0x00080002     CPU%(cpu)d      %(tsc)d         VMX_VECTOR              [ domid 
= 0x%(1)08x, eip = 0x%(2)08x, vector = 0x%(3)08x ]
 0x00080003     CPU%(cpu)d      %(tsc)d         VMX_INT                 [ domid 
= 0x%(1)08x, trap = 0x%(2)08x, va = 0x%(3)08x ]
+
+0x00090001      CPU%(cpu)d      %(tsc)d         VMENTRY                 
0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x
+0x00090002      CPU%(cpu)d      %(tsc)d         VMEXIT                  
0x%(1)08x 0x%(2)08x 0x%(3)08x 
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xentrace/xentrace.c
--- a/tools/xentrace/xentrace.c Thu Sep  8 15:18:40 2005
+++ b/tools/xentrace/xentrace.c Fri Sep  9 16:30:54 2005
@@ -525,7 +525,7 @@
     }
 
     if (opts.cpu_mask != 0) {
-        set_mask(opts.evt_mask, 1);
+        set_mask(opts.cpu_mask, 1);
     }
 
     if ( opts.outfile )
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/Rules.mk
--- a/xen/Rules.mk      Thu Sep  8 15:18:40 2005
+++ b/xen/Rules.mk      Fri Sep  9 16:30:54 2005
@@ -7,7 +7,6 @@
 perfc       ?= n
 perfc_arrays?= n
 trace       ?= n
-optimize    ?= y
 domu_debug  ?= n
 crash_debug ?= n
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/acm/acm_chinesewall_hooks.c
--- a/xen/acm/acm_chinesewall_hooks.c   Thu Sep  8 15:18:40 2005
+++ b/xen/acm/acm_chinesewall_hooks.c   Fri Sep  9 16:30:54 2005
@@ -310,6 +310,28 @@
        return 0;
 }
 
+static int
+chwall_dump_ssid_types(ssidref_t ssidref, u8 *buf, u16 len)
+{
+    int i;
+
+    /* fill in buffer */
+    if (chwall_bin_pol.max_types > len)
+        return -EFAULT;
+
+       if (ssidref >= chwall_bin_pol.max_ssidrefs)
+               return -EFAULT;
+
+    /* read types for chwall ssidref */
+    for(i=0; i< chwall_bin_pol.max_types; i++) {
+        if (chwall_bin_pol.ssidrefs[ssidref * chwall_bin_pol.max_types + i])
+            buf[i] = 1;
+        else
+            buf[i] = 0;
+    }
+    return chwall_bin_pol.max_types;
+}
+
 /***************************
  * Authorization functions
  ***************************/
@@ -492,6 +514,7 @@
        .dump_binary_policy             = chwall_dump_policy,
        .set_binary_policy              = chwall_set_policy,
        .dump_statistics                = chwall_dump_stats,
+    .dump_ssid_types        = chwall_dump_ssid_types,
        /* domain management control hooks */
        .pre_domain_create              = chwall_pre_domain_create,
        .post_domain_create             = chwall_post_domain_create,
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/acm/acm_core.c
--- a/xen/acm/acm_core.c        Thu Sep  8 15:18:40 2005
+++ b/xen/acm/acm_core.c        Fri Sep  9 16:30:54 2005
@@ -64,16 +64,17 @@
 void acm_set_endian(void)
 {
     u32 test = 1;
-    if (*((u8 *)&test) == 1) {
+    if (*((u8 *)&test) == 1)
+    {
        printk("ACM module running in LITTLE ENDIAN.\n");
-       little_endian = 1;
-    } else {
-       printk("ACM module running in BIG ENDIAN.\n");
-       little_endian = 0;
-    }
-}
-
-#if (ACM_USE_SECURITY_POLICY != ACM_NULL_POLICY)
+        little_endian = 1;
+    }
+    else
+    {
+        printk("ACM module running in BIG ENDIAN.\n");
+        little_endian = 0;
+    }
+}
 
 /* initialize global security policy for Xen; policy write-locked already */
 static void
@@ -101,7 +102,8 @@
      * Try all modules and see whichever could be the binary policy.
      * Adjust the initrdidx if module[1] is the binary policy.
      */
-    for (i = mbi->mods_count-1; i >= 1; i--) {
+    for (i = mbi->mods_count-1; i >= 1; i--)
+    {
         struct acm_policy_buffer *pol;
         char *_policy_start; 
         unsigned long _policy_len;
@@ -117,23 +119,32 @@
                continue; /* not a policy */
 
         pol = (struct acm_policy_buffer *)_policy_start;
-        if (ntohl(pol->magic) == ACM_MAGIC) {
+        if (ntohl(pol->magic) == ACM_MAGIC)
+        {
             rc = acm_set_policy((void *)_policy_start,
                                 (u16)_policy_len,
                                 0);
-            if (rc == ACM_OK) {
+            if (rc == ACM_OK)
+            {
                 printf("Policy len  0x%lx, start at 
%p.\n",_policy_len,_policy_start);
-                if (i == 1) {
-                    if (mbi->mods_count > 2) {
+                if (i == 1)
+                {
+                    if (mbi->mods_count > 2)
+                    {
                         *initrdidx = 2;
-                    } else {
+                    }
+                    else {
                         *initrdidx = 0;
                     }
-                } else {
+                }
+                else
+                {
                     *initrdidx = 1;
                 }
                 break;
-            } else {
+            }
+            else
+            {
                printk("Invalid policy. %d.th module line.\n", i+1);
             }
         } /* end if a binary policy definition, i.e., (ntohl(pol->magic) == 
ACM_MAGIC ) */
@@ -147,56 +158,84 @@
          const multiboot_info_t *mbi,
          unsigned long initial_images_start)
 {
-       int ret = -EINVAL;
-
-       acm_set_endian();
+       int ret = ACM_OK;
+
+    acm_set_endian();
        write_lock(&acm_bin_pol_rwlock);
-
-       if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_POLICY) {
-               acm_init_binary_policy(NULL, NULL);
-               acm_init_chwall_policy();
+    acm_init_binary_policy(NULL, NULL);
+
+    /* set primary policy component */
+    switch ((ACM_USE_SECURITY_POLICY) & 0x0f)
+    {
+
+    case ACM_CHINESE_WALL_POLICY:
+        acm_init_chwall_policy();
                acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
                acm_primary_ops = &acm_chinesewall_ops;
+        break;
+
+    case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
+        acm_init_ste_policy();
+               acm_bin_pol.primary_policy_code = 
ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
+               acm_primary_ops = &acm_simple_type_enforcement_ops;
+        break;
+
+    default:
+        /* NULL or Unknown policy not allowed primary;
+         * NULL/NULL will not compile this code */
+        ret = -EINVAL;
+        goto out;
+    }
+
+    /* secondary policy component part */
+    switch ((ACM_USE_SECURITY_POLICY) >> 4) {
+    case ACM_NULL_POLICY:
                acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
                acm_secondary_ops = &acm_null_ops;
-               ret = ACM_OK;
-       } else if (ACM_USE_SECURITY_POLICY == 
ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
-               acm_init_binary_policy(NULL, NULL);
+               break;
+
+    case ACM_CHINESE_WALL_POLICY:
+        if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY)
+        {   /* not a valid combination */
+            ret = -EINVAL;
+            goto out;
+        }
+               acm_init_chwall_policy();
+        acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY;
+               acm_secondary_ops = &acm_chinesewall_ops;
+        break;
+
+    case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
+        if (acm_bin_pol.primary_policy_code == 
ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
+        {   /* not a valid combination */
+            ret = -EINVAL;
+            goto out;
+        }
                acm_init_ste_policy();
-               acm_bin_pol.primary_policy_code = 
ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
-               acm_primary_ops = &acm_simple_type_enforcement_ops;
-               acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
-               acm_secondary_ops = &acm_null_ops;
-               ret = ACM_OK;
-       } else if (ACM_USE_SECURITY_POLICY == 
ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
-               acm_init_binary_policy(NULL, NULL);
-               acm_init_chwall_policy();
-               acm_init_ste_policy();
-               acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
-               acm_primary_ops = &acm_chinesewall_ops;
                acm_bin_pol.secondary_policy_code = 
ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
                acm_secondary_ops = &acm_simple_type_enforcement_ops;
-               ret = ACM_OK;
-       } else if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) {
-               acm_init_binary_policy(NULL, NULL);
-               acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
-               acm_primary_ops = &acm_null_ops;
-               acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
-               acm_secondary_ops = &acm_null_ops;
-               ret = ACM_OK;
+        break;
+
+    default:
+        ret = -EINVAL;
+        goto out;
+    }
+
+ out:
+       write_unlock(&acm_bin_pol_rwlock);
+
+       if (ret != ACM_OK)
+    {
+        printk("%s: Error setting policies.\n", __func__);
+        /* here one could imagine a clean panic */
+               return -EINVAL;
        }
-       write_unlock(&acm_bin_pol_rwlock);
-
-       if (ret != ACM_OK)
-               return -EINVAL;         
        acm_setup(initrdidx, mbi, initial_images_start);
        printk("%s: Enforcing Primary %s, Secondary %s.\n", __func__, 
-              ACM_POLICY_NAME(acm_bin_pol.primary_policy_code), 
ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code));
+              ACM_POLICY_NAME(acm_bin_pol.primary_policy_code),
+           ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code));
        return ret;
 }
-
-
-#endif
 
 int
 acm_init_domain_ssid(domid_t id, ssidref_t ssidref)
@@ -205,7 +244,8 @@
        struct domain *subj = find_domain_by_id(id);
        int ret1, ret2;
        
-       if (subj == NULL) {
+       if (subj == NULL)
+    {
                printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id);
                return ACM_NULL_POINTER_ERROR;
        }
@@ -235,14 +275,16 @@
        else
                ret2 = ACM_OK;
 
-       if ((ret1 != ACM_OK) || (ret2 != ACM_OK)) {
+       if ((ret1 != ACM_OK) || (ret2 != ACM_OK))
+    {
                printk("%s: ERROR instantiating individual ssids for domain 
0x%02x.\n",
                       __func__, subj->domain_id);
                acm_free_domain_ssid(ssid);     
                put_domain(subj);
                return ACM_INIT_SSID_ERROR;
        }
-       printk("%s: assigned domain %x the ssidref=%x.\n", __func__, id, 
ssid->ssidref);
+       printk("%s: assigned domain %x the ssidref=%x.\n",
+           __func__, id, ssid->ssidref);
        put_domain(subj);
        return ACM_OK;
 }
@@ -254,11 +296,12 @@
        domid_t id;
 
        /* domain is already gone, just ssid is left */
-       if (ssid == NULL) {
+       if (ssid == NULL)
+    {
                printk("%s: ACM_NULL_POINTER ERROR.\n", __func__);
                return ACM_NULL_POINTER_ERROR;
        }
-               id = ssid->domainid;
+    id = ssid->domainid;
        ssid->subject        = NULL;
 
        if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
@@ -268,6 +311,7 @@
                acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
        ssid->secondary_ssid = NULL;
        xfree(ssid);
-       printkd("%s: Freed individual domain ssid (domain=%02x).\n",__func__, 
id);
+       printkd("%s: Freed individual domain ssid (domain=%02x).\n",
+            __func__, id);
        return ACM_OK;
 }
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/acm/acm_null_hooks.c
--- a/xen/acm/acm_null_hooks.c  Thu Sep  8 15:18:40 2005
+++ b/xen/acm/acm_null_hooks.c  Fri Sep  9 16:30:54 2005
@@ -14,13 +14,13 @@
 #include <acm/acm_hooks.h>
 
 static int
-null_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref)
+null_init_domain_ssid(void **ssid, ssidref_t ssidref)
 {
        return ACM_OK;
 }
 
 static void
-null_free_domain_ssid(void *chwall_ssid)
+null_free_domain_ssid(void *ssid)
 {
        return;
 }
@@ -44,6 +44,14 @@
        return 0;
 }
 
+static int
+null_dump_ssid_types(ssidref_t ssidref, u8 *buffer, u16 buf_size)
+{
+    /* no types */
+    return 0;
+}
+
+
 /* now define the hook structure similarly to LSM */
 struct acm_operations acm_null_ops = {
        .init_domain_ssid               = null_init_domain_ssid,
@@ -51,6 +59,7 @@
        .dump_binary_policy             = null_dump_binary_policy,
        .set_binary_policy              = null_set_binary_policy,
        .dump_statistics                = null_dump_stats,
+    .dump_ssid_types        = null_dump_ssid_types,
        /* domain management control hooks */
        .pre_domain_create              = NULL,
        .post_domain_create             = NULL,
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/acm/acm_policy.c
--- a/xen/acm/acm_policy.c      Thu Sep  8 15:18:40 2005
+++ b/xen/acm/acm_policy.c      Fri Sep  9 16:30:54 2005
@@ -26,8 +26,8 @@
 #include <xen/lib.h>
 #include <xen/delay.h>
 #include <xen/sched.h>
+#include <acm/acm_core.h>
 #include <public/acm_ops.h>
-#include <acm/acm_core.h>
 #include <acm/acm_hooks.h>
 #include <acm/acm_endian.h>
 
@@ -37,14 +37,16 @@
        u8 *policy_buffer = NULL;
        struct acm_policy_buffer *pol;
        
-       if (buf_size < sizeof(struct acm_policy_buffer))
+    if (buf_size < sizeof(struct acm_policy_buffer))
                return -EFAULT;
 
        /* 1. copy buffer from domain */
        if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
-           goto error_free;
+           return -ENOMEM;
+
        if (isuserbuffer) {
-               if (copy_from_user(policy_buffer, buf, buf_size)) {
+               if (copy_from_user(policy_buffer, buf, buf_size))
+        {
                        printk("%s: Error copying!\n",__func__);
                        goto error_free;
                }
@@ -57,11 +59,13 @@
        if ((ntohl(pol->magic) != ACM_MAGIC) || 
            (ntohl(pol->policy_version) != ACM_POLICY_VERSION) ||
            (ntohl(pol->primary_policy_code) != 
acm_bin_pol.primary_policy_code) ||
-           (ntohl(pol->secondary_policy_code) != 
acm_bin_pol.secondary_policy_code)) {
+           (ntohl(pol->secondary_policy_code) != 
acm_bin_pol.secondary_policy_code))
+    {
                printkd("%s: Wrong policy magics or versions!\n", __func__);
                goto error_free;
        }
-       if (buf_size != ntohl(pol->len)) {
+       if (buf_size != ntohl(pol->len))
+    {
                printk("%s: ERROR in buf size.\n", __func__);
                goto error_free;
        }
@@ -72,27 +76,25 @@
        /* 3. set primary policy data */
        if (acm_primary_ops->set_binary_policy(buf + 
ntohl(pol->primary_buffer_offset),
                                                
ntohl(pol->secondary_buffer_offset) -
-                                              
ntohl(pol->primary_buffer_offset))) {
+                                              
ntohl(pol->primary_buffer_offset)))
                goto error_lock_free;
-       }
+
        /* 4. set secondary policy data */
        if (acm_secondary_ops->set_binary_policy(buf + 
ntohl(pol->secondary_buffer_offset),
                                                 ntohl(pol->len) - 
-                                                
ntohl(pol->secondary_buffer_offset))) {
+                                                
ntohl(pol->secondary_buffer_offset)))
                goto error_lock_free;
-       }
+
        write_unlock(&acm_bin_pol_rwlock);
-       if (policy_buffer != NULL)
-               xfree(policy_buffer);
+       xfree(policy_buffer);
        return ACM_OK;
 
  error_lock_free:
        write_unlock(&acm_bin_pol_rwlock);
  error_free:
        printk("%s: Error setting policy.\n", __func__);
-       if (policy_buffer != NULL)
-               xfree(policy_buffer);
-       return -ENOMEM;
+    xfree(policy_buffer);
+       return -EFAULT;
 }
 
 int
@@ -102,11 +104,14 @@
      int ret;
      struct acm_policy_buffer *bin_pol;
        
+    if (buf_size < sizeof(struct acm_policy_buffer))
+               return -EFAULT;
+
      if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
            return -ENOMEM;
 
      read_lock(&acm_bin_pol_rwlock);
-     /* future: read policy from file and set it */
+
      bin_pol = (struct acm_policy_buffer *)policy_buffer;
      bin_pol->magic = htonl(ACM_MAGIC);
      bin_pol->primary_policy_code = htonl(acm_bin_pol.primary_policy_code);
@@ -118,27 +123,30 @@
      
      ret = acm_primary_ops->dump_binary_policy (policy_buffer + 
ntohl(bin_pol->primary_buffer_offset),
                                       buf_size - 
ntohl(bin_pol->primary_buffer_offset));
-     if (ret < 0) {
-            printk("%s: ERROR creating chwallpolicy buffer.\n", __func__);
-            read_unlock(&acm_bin_pol_rwlock);
-            return -1;
-     }
+     if (ret < 0)
+         goto error_free_unlock;
+
      bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
      bin_pol->secondary_buffer_offset = htonl(ntohl(bin_pol->len));
 
      ret = acm_secondary_ops->dump_binary_policy(policy_buffer + 
ntohl(bin_pol->secondary_buffer_offset),
                                    buf_size - 
ntohl(bin_pol->secondary_buffer_offset));
-     if (ret < 0) {
-            printk("%s: ERROR creating chwallpolicy buffer.\n", __func__);
-            read_unlock(&acm_bin_pol_rwlock);
-            return -1;
-     }
+     if (ret < 0)
+         goto error_free_unlock;
+
      bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
-     read_unlock(&acm_bin_pol_rwlock);
      if (copy_to_user(buf, policy_buffer, ntohl(bin_pol->len)))
-            return -EFAULT;
+            goto error_free_unlock;
+
+     read_unlock(&acm_bin_pol_rwlock);
      xfree(policy_buffer);
      return ACM_OK;
+
+ error_free_unlock:
+     read_unlock(&acm_bin_pol_rwlock);
+     printk("%s: Error getting policy.\n", __func__);
+     xfree(policy_buffer);
+     return -EFAULT;
 }
 
 int
@@ -185,4 +193,62 @@
      return -EFAULT;
 }
 
+
+int
+acm_get_ssid(ssidref_t ssidref, u8 *buf, u16 buf_size)
+{
+    /* send stats to user space */
+     u8 *ssid_buffer;
+     int ret;
+     struct acm_ssid_buffer *acm_ssid;
+     if (buf_size < sizeof(struct acm_ssid_buffer))
+               return -EFAULT;
+
+     if ((ssid_buffer = xmalloc_array(u8, buf_size)) == NULL)
+           return -ENOMEM;
+
+     read_lock(&acm_bin_pol_rwlock);
+
+     acm_ssid = (struct acm_ssid_buffer *)ssid_buffer;
+     acm_ssid->len = sizeof(struct acm_ssid_buffer);
+     acm_ssid->ssidref = ssidref;
+     acm_ssid->primary_policy_code = acm_bin_pol.primary_policy_code;
+     acm_ssid->secondary_policy_code = acm_bin_pol.secondary_policy_code;
+     acm_ssid->primary_types_offset = acm_ssid->len;
+
+     /* ret >= 0 --> ret == max_types */
+     ret = acm_primary_ops->dump_ssid_types(ACM_PRIMARY(ssidref),
+                                            ssid_buffer + 
acm_ssid->primary_types_offset,
+                                            buf_size - 
acm_ssid->primary_types_offset);
+     if (ret < 0)
+         goto error_free_unlock;
+
+     acm_ssid->len += ret;
+     acm_ssid->primary_max_types = ret;
+
+     acm_ssid->secondary_types_offset = acm_ssid->len;
+
+     ret = acm_secondary_ops->dump_ssid_types(ACM_SECONDARY(ssidref),
+                                              ssid_buffer + 
acm_ssid->secondary_types_offset,
+                                              buf_size - 
acm_ssid->secondary_types_offset);
+     if (ret < 0)
+         goto error_free_unlock;
+
+     acm_ssid->len += ret;
+     acm_ssid->secondary_max_types = ret;
+
+     if (copy_to_user(buf, ssid_buffer, acm_ssid->len))
+            goto error_free_unlock;
+
+     read_unlock(&acm_bin_pol_rwlock);
+     xfree(ssid_buffer);
+     return ACM_OK;
+
+ error_free_unlock:
+     read_unlock(&acm_bin_pol_rwlock);
+     printk("%s: Error getting ssid.\n", __func__);
+     xfree(ssid_buffer);
+     return -ENOMEM;
+}
+
 /*eof*/
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/acm/acm_simple_type_enforcement_hooks.c
--- a/xen/acm/acm_simple_type_enforcement_hooks.c       Thu Sep  8 15:18:40 2005
+++ b/xen/acm/acm_simple_type_enforcement_hooks.c       Fri Sep  9 16:30:54 2005
@@ -383,6 +383,27 @@
     return sizeof(struct acm_ste_stats_buffer);
 }
 
+static int
+ste_dump_ssid_types(ssidref_t ssidref, u8 *buf, u16 len)
+{
+    int i;
+
+    /* fill in buffer */
+    if (ste_bin_pol.max_types > len)
+        return -EFAULT;
+
+       if (ssidref >= ste_bin_pol.max_ssidrefs)
+               return -EFAULT;
+
+    /* read types for chwall ssidref */
+    for(i=0; i< ste_bin_pol.max_types; i++) {
+               if (ste_bin_pol.ssidrefs[ssidref * ste_bin_pol.max_types + i])
+            buf[i] = 1;
+        else
+            buf[i] = 0;
+    }
+    return ste_bin_pol.max_types;
+}
 
 /* we need to go through this before calling the hooks,
  * returns 1 == cache hit */
@@ -625,22 +646,23 @@
        /* policy management services */
        .init_domain_ssid               = ste_init_domain_ssid,
        .free_domain_ssid               = ste_free_domain_ssid,
-       .dump_binary_policy             = ste_dump_policy,
-       .set_binary_policy              = ste_set_policy,
+       .dump_binary_policy     = ste_dump_policy,
+       .set_binary_policy      = ste_set_policy,
        .dump_statistics                = ste_dump_stats,
+    .dump_ssid_types        = ste_dump_ssid_types,
        /* domain management control hooks */
        .pre_domain_create              = ste_pre_domain_create,
-       .post_domain_create             = NULL,
-       .fail_domain_create             = NULL,
-       .post_domain_destroy            = ste_post_domain_destroy,
+       .post_domain_create         = NULL,
+       .fail_domain_create     = NULL,
+       .post_domain_destroy    = ste_post_domain_destroy,
        /* event channel control hooks */
-       .pre_eventchannel_unbound       = ste_pre_eventchannel_unbound,
+       .pre_eventchannel_unbound   = ste_pre_eventchannel_unbound,
        .fail_eventchannel_unbound      = NULL,
        .pre_eventchannel_interdomain   = ste_pre_eventchannel_interdomain,
        .fail_eventchannel_interdomain  = NULL,
        /* grant table control hooks */
-       .pre_grant_map_ref              = ste_pre_grant_map_ref,
-       .fail_grant_map_ref             = NULL,
-       .pre_grant_setup                = ste_pre_grant_setup,
-       .fail_grant_setup               = NULL,
+       .pre_grant_map_ref      = ste_pre_grant_map_ref,
+       .fail_grant_map_ref     = NULL,
+       .pre_grant_setup        = ste_pre_grant_setup,
+       .fail_grant_setup       = NULL,
 };
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/Makefile
--- a/xen/arch/x86/Makefile     Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/Makefile     Fri Sep  9 16:30:54 2005
@@ -17,7 +17,7 @@
 
 OBJS := $(patsubst shadow%.o,,$(OBJS)) # drop all
 ifeq ($(TARGET_SUBARCH),x86_64) 
- OBJS += shadow.o shadow_public.o      # x86_64: new code
+ OBJS += shadow.o shadow_public.o shadow_guest32.o     # x86_64: new code
 endif
 ifeq ($(TARGET_SUBARCH),x86_32) 
  ifneq ($(pae),n)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/Rules.mk
--- a/xen/arch/x86/Rules.mk     Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/Rules.mk     Fri Sep  9 16:30:54 2005
@@ -13,10 +13,8 @@
 CFLAGS  += -I$(BASEDIR)/include/asm-x86/mach-generic
 CFLAGS  += -I$(BASEDIR)/include/asm-x86/mach-default
 
-ifeq ($(optimize),y)
+ifneq ($(debug),y)
 CFLAGS  += -O3 -fomit-frame-pointer
-else
-x86_32/usercopy.o: CFLAGS += -O1
 endif
 
 # Prevent floating-point variables from creeping into Xen.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/boot/x86_32.S
--- a/xen/arch/x86/boot/x86_32.S        Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/boot/x86_32.S        Fri Sep  9 16:30:54 2005
@@ -9,6 +9,8 @@
                .text
 
 ENTRY(start)
+ENTRY(stext)
+ENTRY(_stext)
         jmp __start
 
         .align 4
@@ -260,6 +262,3 @@
         .org 0x2000 + STACK_SIZE + PAGE_SIZE
 
 #endif /* CONFIG_X86_PAE */
-
-ENTRY(stext)
-ENTRY(_stext)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/boot/x86_64.S
--- a/xen/arch/x86/boot/x86_64.S        Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/boot/x86_64.S        Fri Sep  9 16:30:54 2005
@@ -10,6 +10,8 @@
         .code32
 
 ENTRY(start)
+ENTRY(stext)
+ENTRY(_stext)
         jmp __start
 
         .org    0x004
@@ -267,5 +269,3 @@
 
         .org 0x4000 + STACK_SIZE + PAGE_SIZE
         .code64
-ENTRY(stext)
-ENTRY(_stext)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/cdb.c
--- a/xen/arch/x86/cdb.c        Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/cdb.c        Fri Sep  9 16:30:54 2005
@@ -21,7 +21,7 @@
    debugger. so avoid it. */
 #define dbg_printk(...)
 
-static unsigned char opt_cdb[30] = "none";
+static char opt_cdb[30] = "none";
 string_param("cdb", opt_cdb);
 
 struct xendbg_context {
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/dom0_ops.c
--- a/xen/arch/x86/dom0_ops.c   Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/dom0_ops.c   Fri Sep  9 16:30:54 2005
@@ -19,6 +19,7 @@
 #include <xen/console.h>
 #include <asm/shadow.h>
 #include <asm/irq.h>
+#include <asm/processor.h>
 #include <public/sched_ctl.h>
 
 #include <asm/mtrr.h>
@@ -188,9 +189,11 @@
         pi->total_pages      = max_page;
         pi->free_pages       = avail_domheap_pages();
         pi->cpu_khz          = cpu_khz;
-
-        copy_to_user(u_dom0_op, op, sizeof(*op));
+        memset( pi->hw_cap, 0, sizeof(pi->hw_cap) );
+        memcpy( pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4 );
         ret = 0;
+        if( copy_to_user(u_dom0_op, op, sizeof(*op)) )
+           ret = -EINVAL;
     }
     break;
     
@@ -389,9 +392,31 @@
     }
     break;
 
+    case DOM0_PHYSICAL_MEMORY_MAP:
+    {
+        struct dom0_memory_map_entry entry;
+        int i;
+
+        for ( i = 0; i < e820.nr_map; i++ )
+        {
+            if ( i >= op->u.physical_memory_map.max_map_entries )
+                break;
+            entry.start  = e820.map[i].addr;
+            entry.end    = e820.map[i].addr + e820.map[i].size;
+            entry.is_ram = (e820.map[i].type == E820_RAM);
+            (void)copy_to_user(
+                &op->u.physical_memory_map.memory_map[i],
+                &entry, sizeof(entry));
+        }
+
+        op->u.physical_memory_map.nr_map_entries = i;
+        (void)copy_to_user(u_dom0_op, op, sizeof(*op));
+    }
+    break;
+
     default:
         ret = -ENOSYS;
-
+        break;
     }
 
     return ret;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/domain.c     Fri Sep  9 16:30:54 2005
@@ -255,13 +255,13 @@
     v->vcpu_info = &d->shared_info->vcpu_data[v->vcpu_id];
     v->cpumap = CPUMAP_RUNANYWHERE;
     SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d);
-    machine_to_phys_mapping[virt_to_phys(d->shared_info) >> 
-                           PAGE_SHIFT] = INVALID_M2P_ENTRY;
+    set_pfn_from_mfn(virt_to_phys(d->shared_info) >> PAGE_SHIFT,
+            INVALID_M2P_ENTRY);
     
     d->arch.mm_perdomain_pt = alloc_xenheap_page();
     memset(d->arch.mm_perdomain_pt, 0, PAGE_SIZE);
-    machine_to_phys_mapping[virt_to_phys(d->arch.mm_perdomain_pt) >> 
-                           PAGE_SHIFT] = INVALID_M2P_ENTRY;
+    set_pfn_from_mfn(virt_to_phys(d->arch.mm_perdomain_pt) >> PAGE_SHIFT,
+            INVALID_M2P_ENTRY);
     v->arch.perdomain_ptes = d->arch.mm_perdomain_pt;
     v->arch.perdomain_ptes[FIRST_RESERVED_GDT_PAGE] =
         l1e_from_page(virt_to_page(gdt_table), PAGE_HYPERVISOR);
@@ -381,11 +381,13 @@
 out:
     free_vmcs(vmcs);
     if(v->arch.arch_vmx.io_bitmap_a != 0) {
-        free_xenheap_pages(v->arch.arch_vmx.io_bitmap_a, get_order(0x1000));
+        free_xenheap_pages(
+            v->arch.arch_vmx.io_bitmap_a, get_order_from_bytes(0x1000));
         v->arch.arch_vmx.io_bitmap_a = 0;
     }
     if(v->arch.arch_vmx.io_bitmap_b != 0) {
-        free_xenheap_pages(v->arch.arch_vmx.io_bitmap_b, get_order(0x1000));
+        free_xenheap_pages(
+            v->arch.arch_vmx.io_bitmap_b, get_order_from_bytes(0x1000));
         v->arch.arch_vmx.io_bitmap_b = 0;
     }
     v->arch.arch_vmx.vmcs = 0;
@@ -885,8 +887,13 @@
     return switch_required;
 }
 
-void sync_lazy_execstate_cpu(unsigned int cpu)
-{
+void sync_vcpu_execstate(struct vcpu *v)
+{
+    unsigned int cpu = v->processor;
+
+    if ( !cpu_isset(cpu, v->domain->cpumask) )
+        return;
+
     if ( cpu == smp_processor_id() )
     {
         (void)__sync_lazy_execstate();
@@ -967,11 +974,13 @@
     BUG_ON(v->arch.arch_vmx.vmcs == NULL);
     free_vmcs(v->arch.arch_vmx.vmcs);
     if(v->arch.arch_vmx.io_bitmap_a != 0) {
-        free_xenheap_pages(v->arch.arch_vmx.io_bitmap_a, get_order(0x1000));
+        free_xenheap_pages(
+            v->arch.arch_vmx.io_bitmap_a, get_order_from_bytes(0x1000));
         v->arch.arch_vmx.io_bitmap_a = 0;
     }
     if(v->arch.arch_vmx.io_bitmap_b != 0) {
-        free_xenheap_pages(v->arch.arch_vmx.io_bitmap_b, get_order(0x1000));
+        free_xenheap_pages(
+            v->arch.arch_vmx.io_bitmap_b, get_order_from_bytes(0x1000));
         v->arch.arch_vmx.io_bitmap_b = 0;
     }
     v->arch.arch_vmx.vmcs = 0;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c       Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/domain_build.c       Fri Sep  9 16:30:54 2005
@@ -20,6 +20,7 @@
 #include <asm/processor.h>
 #include <asm/desc.h>
 #include <asm/i387.h>
+#include <asm/physdev.h>
 #include <asm/shadow.h>
 
 static long dom0_nrpages;
@@ -74,15 +75,12 @@
     struct pfn_info *page;
     unsigned int order;
     /*
-     * Allocate up to 2MB at a time:
-     *  1. This prevents overflow of get_order() when allocating more than
-     *     4GB to domain 0 on a PAE machine.
-     *  2. It prevents allocating very large chunks from DMA pools before
-     *     the >4GB pool is fully depleted.
+     * Allocate up to 2MB at a time: It prevents allocating very large chunks
+     * from DMA pools before the >4GB pool is fully depleted.
      */
     if ( max_pages > (2UL << (20 - PAGE_SHIFT)) )
         max_pages = 2UL << (20 - PAGE_SHIFT);
-    order = get_order(max_pages << PAGE_SHIFT);
+    order = get_order_from_pages(max_pages);
     if ( (max_pages & (max_pages-1)) != 0 )
         order--;
     while ( (page = alloc_domheap_pages(d, order, 0)) == NULL )
@@ -217,14 +215,14 @@
     vinitrd_start    = round_pgup(dsi.v_end);
     vinitrd_end      = vinitrd_start + initrd_len;
     vphysmap_start   = round_pgup(vinitrd_end);
-    vphysmap_end     = vphysmap_start + (nr_pages * sizeof(u32));
-    vpt_start        = round_pgup(vphysmap_end);
+    vphysmap_end     = vphysmap_start + (nr_pages * sizeof(unsigned long));
+    vstartinfo_start = round_pgup(vphysmap_end);
+    vstartinfo_end   = vstartinfo_start + PAGE_SIZE;
+    vpt_start        = vstartinfo_end;
     for ( nr_pt_pages = 2; ; nr_pt_pages++ )
     {
         vpt_end          = vpt_start + (nr_pt_pages * PAGE_SIZE);
-        vstartinfo_start = vpt_end;
-        vstartinfo_end   = vstartinfo_start + PAGE_SIZE;
-        vstack_start     = vstartinfo_end;
+        vstack_start     = vpt_end;
         vstack_end       = vstack_start + PAGE_SIZE;
         v_end            = (vstack_end + (1UL<<22)-1) & ~((1UL<<22)-1);
         if ( (v_end - vstack_end) < (512UL << 10) )
@@ -251,7 +249,7 @@
 #endif
     }
 
-    order = get_order(v_end - dsi.v_start);
+    order = get_order_from_bytes(v_end - dsi.v_start);
     if ( (1UL << order) > nr_pages )
         panic("Domain 0 allocation is too small for kernel image.\n");
 
@@ -271,15 +269,15 @@
            " Loaded kernel: %p->%p\n"
            " Init. ramdisk: %p->%p\n"
            " Phys-Mach map: %p->%p\n"
+           " Start info:    %p->%p\n"
            " Page tables:   %p->%p\n"
-           " Start info:    %p->%p\n"
            " Boot stack:    %p->%p\n"
            " TOTAL:         %p->%p\n",
            _p(dsi.v_kernstart), _p(dsi.v_kernend), 
            _p(vinitrd_start), _p(vinitrd_end),
            _p(vphysmap_start), _p(vphysmap_end),
+           _p(vstartinfo_start), _p(vstartinfo_end),
            _p(vpt_start), _p(vpt_end),
-           _p(vstartinfo_start), _p(vstartinfo_end),
            _p(vstack_start), _p(vstack_end),
            _p(dsi.v_start), _p(v_end));
     printk(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
@@ -592,8 +590,7 @@
     if ( opt_dom0_translate )
     {
         si->shared_info  = d->next_io_page << PAGE_SHIFT;
-        set_machinetophys(virt_to_phys(d->shared_info) >> PAGE_SHIFT,
-                          d->next_io_page);
+        set_pfn_from_mfn(virt_to_phys(d->shared_info) >> PAGE_SHIFT, 
d->next_io_page);
         d->next_io_page++;
     }
     else
@@ -613,8 +610,8 @@
         if ( !opt_dom0_translate && (pfn > REVERSE_START) )
             mfn = alloc_epfn - (pfn - REVERSE_START);
 #endif
-        ((u32 *)vphysmap_start)[pfn] = mfn;
-        machine_to_phys_mapping[mfn] = pfn;
+        ((unsigned long *)vphysmap_start)[pfn] = mfn;
+        set_pfn_from_mfn(mfn, pfn);
     }
     while ( pfn < nr_pages )
     {
@@ -626,8 +623,8 @@
 #ifndef NDEBUG
 #define pfn (nr_pages - 1 - (pfn - (alloc_epfn - alloc_spfn)))
 #endif
-            ((u32 *)vphysmap_start)[pfn] = mfn;
-            machine_to_phys_mapping[mfn] = pfn;
+            ((unsigned long *)vphysmap_start)[pfn] = mfn;
+            set_pfn_from_mfn(mfn, pfn);
 #undef pfn
             page++; pfn++;
         }
@@ -708,6 +705,18 @@
         printk("dom0: shadow setup done\n");
     }
 
+    /*
+     * Modify I/O port access permissions.
+     */
+    /* Master Interrupt Controller (PIC). */
+    physdev_modify_ioport_access_range(dom0, 0, 0x20, 2);
+    /* Slave Interrupt Controller (PIC). */
+    physdev_modify_ioport_access_range(dom0, 0, 0xA0, 2);
+    /* Interval Timer (PIT). */
+    physdev_modify_ioport_access_range(dom0, 0, 0x40, 4);
+    /* PIT Channel 2 / PC Speaker Control. */
+    physdev_modify_ioport_access_range(dom0, 0, 0x61, 1);
+
     return 0;
 }
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/mm.c Fri Sep  9 16:30:54 2005
@@ -1450,9 +1450,9 @@
                          ((type & PGT_type_mask) != PGT_l1_page_table) )
                         MEM_LOG("Bad type (saw %" PRtype_info
                                 "!= exp %" PRtype_info ") "
-                                "for mfn %lx (pfn %x)",
+                                "for mfn %lx (pfn %lx)",
                                 x, type, page_to_pfn(page),
-                                machine_to_phys_mapping[page_to_pfn(page)]);
+                                get_pfn_from_mfn(page_to_pfn(page)));
                     return 0;
                 }
                 else if ( (x & PGT_va_mask) == PGT_va_mutable )
@@ -2206,7 +2206,7 @@
                 printk("privileged guest dom%d requests pfn=%lx to "
                        "map mfn=%lx for dom%d\n",
                        d->domain_id, gpfn, mfn, FOREIGNDOM->domain_id);
-                set_machinetophys(mfn, gpfn);
+                set_pfn_from_mfn(mfn, gpfn);
                 set_p2m_entry(FOREIGNDOM, gpfn, mfn, &sh_mapcache, &mapcache);
                 okay = 1;
                 shadow_unlock(FOREIGNDOM);
@@ -2225,7 +2225,7 @@
                 break;
             }
 
-            set_machinetophys(mfn, gpfn);
+            set_pfn_from_mfn(mfn, gpfn);
             okay = 1;
 
             /*
@@ -3185,7 +3185,7 @@
     struct pfn_info *page;
     l1_pgentry_t     pte;
     l2_pgentry_t    *pl2e, l2e;
-    int              which;
+    int              which, flags;
     unsigned long    l2_idx;
 
     if ( unlikely(shadow_mode_enabled(d)) )
@@ -3206,8 +3206,24 @@
     pfn  = l1e_get_pfn(pte);
     page = &frame_table[pfn];
 
+#ifdef CONFIG_X86_64
+#define WRPT_PTE_FLAGS (_PAGE_RW | _PAGE_PRESENT | _PAGE_USER)
+#else
+#define WRPT_PTE_FLAGS (_PAGE_RW | _PAGE_PRESENT)
+#endif
+
+    /*
+     * Check the required flags for a valid wrpt mapping. If the page is
+     * already writable then we can return straight to the guest (SMP race).
+     * We decide whether or not to propagate the fault by testing for write
+     * permissions in page directories by writing back to the linear mapping.
+     */
+    if ( (flags = l1e_get_flags(pte) & WRPT_PTE_FLAGS) == WRPT_PTE_FLAGS )
+        return !__put_user(
+            pte.l1, &linear_pg_table[l1_linear_offset(addr)].l1);
+
     /* We are looking only for read-only mappings of p.t. pages. */
-    if ( ((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) != _PAGE_PRESENT) ||
+    if ( ((flags | _PAGE_RW) != WRPT_PTE_FLAGS) ||
          ((page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table) ||
          ((page->u.inuse.type_info & PGT_count_mask) == 0) ||
          (page_get_owner(page) != d) )
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/setup.c      Fri Sep  9 16:30:54 2005
@@ -12,6 +12,8 @@
 #include <xen/trace.h>
 #include <xen/multiboot.h>
 #include <xen/domain_page.h>
+#include <xen/compile.h>
+#include <public/version.h>
 #include <asm/bitops.h>
 #include <asm/smp.h>
 #include <asm/processor.h>
@@ -90,6 +92,8 @@
 unsigned long mmu_cr4_features = X86_CR4_PSE;
 #endif
 EXPORT_SYMBOL(mmu_cr4_features);
+
+int hvm_enabled = 0; /* can we run unmodified guests */
 
 struct vcpu *idle_task[NR_CPUS] = { &idle0_vcpu };
 
@@ -529,6 +533,45 @@
     startup_cpu_idle_loop();
 }
 
+void arch_get_xen_caps(xen_capabilities_info_t *info)
+{
+    char *p=info->caps;
+
+    *p=0;
+
+#ifdef CONFIG_X86_32
+
+#ifndef CONFIG_X86_PAE       
+    p+=sprintf(p,"xen_%d.%d_x86_32 ",XEN_VERSION,XEN_SUBVERSION);    
+    if(hvm_enabled)
+    {
+        p+=sprintf(p,"hvm_%d.%d_x86_32 ",XEN_VERSION,XEN_SUBVERSION);    
+    }
+#else
+    p+=sprintf(p,"xen_%d.%d_x86_32p ",XEN_VERSION,XEN_SUBVERSION);
+    if(hvm_enabled)
+    {
+        //p+=sprintf(p,"hvm_%d.%d_x86_32 ",XEN_VERSION,XEN_SUBVERSION);    
+        //p+=sprintf(p,"hvm_%d.%d_x86_32p ",XEN_VERSION,XEN_SUBVERSION);    
+    }
+
+#endif        
+
+#else /* !CONFIG_X86_32 */
+    p+=sprintf(p,"xen_%d.%d_x86_64 ",XEN_VERSION,XEN_SUBVERSION);
+    if(hvm_enabled)
+    {
+        //p+=sprintf(p,"hvm_%d.%d_x86_32 ",XEN_VERSION,XEN_SUBVERSION);    
+        //p+=sprintf(p,"hvm_%d.%d_x86_32p ",XEN_VERSION,XEN_SUBVERSION);    
+        p+=sprintf(p,"hvm_%d.%d_x86_64 ",XEN_VERSION,XEN_SUBVERSION);    
+    }
+#endif
+    
+    BUG_ON((p-info->caps)>sizeof(*info));
+
+    if(p>info->caps) *(p-1) = 0;
+}
+
 /*
  * Local variables:
  * mode: C
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/shadow.c
--- a/xen/arch/x86/shadow.c     Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/shadow.c     Fri Sep  9 16:30:54 2005
@@ -53,6 +53,9 @@
     struct domain *d, unsigned long gpfn, unsigned long gmfn);
 static void shadow_map_into_current(struct vcpu *v,
     unsigned long va, unsigned int from, unsigned int to);
+static inline void validate_bl2e_change( struct domain *d,
+       guest_root_pgentry_t *new_gle_p, pgentry_64_t *shadow_l3, int index);
+
 #endif
 
 /********
@@ -217,10 +220,38 @@
         }
         else
         {
-            page = alloc_domheap_page(NULL);
-            void *l1 = map_domain_page(page_to_pfn(page));
-            memset(l1, 0, PAGE_SIZE);
-            unmap_domain_page(l1);
+            if (d->arch.ops->guest_paging_levels == PAGING_L2)
+            {
+#if CONFIG_PAGING_LEVELS >= 4
+                /* For 32-bit VMX guest, 2 shadow L1s to simulate 1 guest L1
+                 * So need allocate 2 continues shadow L1 each time.
+                 */
+                page = alloc_domheap_pages(NULL, SL1_ORDER, 0);
+                if (!page)
+                    domain_crash_synchronous();
+
+                void *l1_0 = map_domain_page(page_to_pfn(page));
+                memset(l1_0,0,PAGE_SIZE);
+                unmap_domain_page(l1_0);
+                void *l1_1 = map_domain_page(page_to_pfn(page+1));
+                memset(l1_1,0,PAGE_SIZE);
+                unmap_domain_page(l1_1);
+#else
+                page = alloc_domheap_page(NULL);
+                if (!page)
+                    domain_crash_synchronous();
+                void *l1 = map_domain_page(page_to_pfn(page));
+                memset(l1, 0, PAGE_SIZE);
+                unmap_domain_page(l1);
+#endif
+            }
+            else
+            {
+                page = alloc_domheap_page(NULL);
+                void *l1 = map_domain_page(page_to_pfn(page));
+                memset(l1, 0, PAGE_SIZE);
+                unmap_domain_page(l1);
+            }
         }
     }
     else {
@@ -331,7 +362,21 @@
   fail:
     FSH_LOG("promotion of pfn=%lx mfn=%lx failed!  external gnttab refs?",
             gpfn, gmfn);
-    free_domheap_page(page);
+    if (psh_type == PGT_l1_shadow)
+    {
+        if (d->arch.ops->guest_paging_levels == PAGING_L2)
+        {
+#if CONFIG_PAGING_LEVELS >=4
+            free_domheap_pages(page, SL1_ORDER);
+#else
+            free_domheap_page(page);
+#endif
+        }
+        else
+            free_domheap_page(page);
+    }
+    else
+        free_domheap_page(page);
     return 0;
 }
 
@@ -478,13 +523,15 @@
 { 
     struct vcpu *v = current;
     struct domain *d = v->domain;
-    l1_pgentry_t *gpl1e, *spl1e;
-    l2_pgentry_t gl2e, sl2e;
+    l1_pgentry_t *spl1e;
+    l2_pgentry_t sl2e;
+    guest_l1_pgentry_t *gpl1e;
+    guest_l2_pgentry_t gl2e;
     unsigned long gl1pfn, gl1mfn, sl1mfn;
     int i, init_table = 0;
 
     __guest_get_l2e(v, va, &gl2e);
-    ASSERT(l2e_get_flags(gl2e) & _PAGE_PRESENT);
+    ASSERT(guest_l2e_get_flags(gl2e) & _PAGE_PRESENT);
     gl1pfn = l2e_get_pfn(gl2e);
 
     if ( !(sl1mfn = __shadow_status(d, gl1pfn, PGT_l1_shadow)) )
@@ -523,28 +570,49 @@
     ASSERT( !(l2e_get_flags(old_sl2e) & _PAGE_PRESENT) );
 #endif
 
-    if ( !get_shadow_ref(sl1mfn) )
-        BUG();
-    l2pde_general(d, &gl2e, &sl2e, sl1mfn);
-    __guest_set_l2e(v, va, &gl2e);
-    __shadow_set_l2e(v, va, &sl2e);
+#if CONFIG_PAGING_LEVELS >=4
+    if (d->arch.ops->guest_paging_levels == PAGING_L2)
+    {
+        /* for 32-bit VMX guest on 64-bit host, 
+         * need update two L2 entries each time
+         */
+        if ( !get_shadow_ref(sl1mfn))
+                BUG();
+        l2pde_general(d, &gl2e, &sl2e, sl1mfn);
+        __guest_set_l2e(v, va, &gl2e);
+        __shadow_set_l2e(v, va & ~((1<<L2_PAGETABLE_SHIFT_32) - 1), &sl2e);
+        if ( !get_shadow_ref(sl1mfn+1))
+            BUG();
+        sl2e = l2e_empty();
+        l2pde_general(d, &gl2e, &sl2e, sl1mfn+1);
+        __shadow_set_l2e(v,((va & ~((1<<L2_PAGETABLE_SHIFT_32) - 1)) + (1 << 
L2_PAGETABLE_SHIFT)) , &sl2e);
+    } else
+#endif
+    {
+        if ( !get_shadow_ref(sl1mfn) )
+            BUG();
+        l2pde_general(d, &gl2e, &sl2e, sl1mfn);
+        __guest_set_l2e(v, va, &gl2e);
+        __shadow_set_l2e(v, va , &sl2e);
+    }
 
     if ( init_table )
     {
         l1_pgentry_t sl1e;
-        int index = l1_table_offset(va);
+        int index = guest_l1_table_offset(va);
         int min = 1, max = 0;
         
         unsigned long entries, pt_va;
         l1_pgentry_t tmp_sl1e;
-        l1_pgentry_t tmp_gl1e;//Prepare for double compile
-
-
-        entries = PAGE_SIZE / sizeof(l1_pgentry_t);
+        guest_l1_pgentry_t tmp_gl1e;//Prepare for double compile
+
+
+        entries = PAGE_SIZE / sizeof(guest_l1_pgentry_t);
         pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(entries - 1)) << 
L1_PAGETABLE_SHIFT;
-        gpl1e = (l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gl1e);
-
-        entries = PAGE_SIZE / sizeof(l1_pgentry_t);
+        gpl1e = (guest_l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gl1e);
+
+        /* If the PGT_l1_shadow has two continual pages */
+        entries = PAGE_SIZE / sizeof(guest_l1_pgentry_t); //1024 entry!!!
         pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(entries - 1)) << 
L1_PAGETABLE_SHIFT;
         spl1e = (l1_pgentry_t *) __shadow_get_l1e(v, pt_va, &tmp_sl1e);
 
@@ -555,7 +623,7 @@
         spl1e = &(shadow_linear_pg_table[l1_linear_offset(va) &
                                      ~(L1_PAGETABLE_ENTRIES-1)]);*/
 
-        for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
+        for ( i = 0; i < GUEST_L1_PAGETABLE_ENTRIES; i++ )
         {
             l1pte_propagate_from_guest(d, gpl1e[i], &sl1e);
             if ( (l1e_get_flags(sl1e) & _PAGE_PRESENT) &&
@@ -584,7 +652,7 @@
     }
 }
 
-static void 
+static void
 shadow_set_l1e(unsigned long va, l1_pgentry_t new_spte, int create_l1_shadow)
 {
     struct vcpu *v = current;
@@ -616,7 +684,7 @@
                 perfc_incrc(shadow_set_l1e_unlinked);
                 if ( !get_shadow_ref(sl1mfn) )
                     BUG();
-                l2pde_general(d, &gpde, &sl2e, sl1mfn);
+                l2pde_general(d, (guest_l2_pgentry_t *)&gpde, &sl2e, sl1mfn);
                 __guest_set_l2e(v, va, &gpde);
                 __shadow_set_l2e(v, va, &sl2e);
             }
@@ -651,6 +719,7 @@
     shadow_update_min_max(l2e_get_pfn(sl2e), l1_table_offset(va));
 }
 
+#if CONFIG_PAGING_LEVELS <= 3
 static void shadow_invlpg_32(struct vcpu *v, unsigned long va)
 {
     struct domain *d = v->domain;
@@ -671,6 +740,7 @@
                          sizeof(gpte))) {*/
     if (unlikely(!__guest_get_l1e(v, va, &gpte))) {
         perfc_incrc(shadow_invlpg_faults);
+        shadow_unlock(d);
         return;
     }
     l1pte_propagate_from_guest(d, gpte, &spte);
@@ -678,6 +748,7 @@
 
     shadow_unlock(d);
 }
+#endif
 
 static struct out_of_sync_entry *
 shadow_alloc_oos_entry(struct domain *d)
@@ -758,8 +829,8 @@
     length = max - min + 1;
     perfc_incr_histo(snapshot_copies, length, PT_UPDATES);
 
-    min *= sizeof(l1_pgentry_t);
-    length *= sizeof(l1_pgentry_t);
+    min *= sizeof(guest_l1_pgentry_t);
+    length *= sizeof(guest_l1_pgentry_t);
 
     original = map_domain_page(gmfn);
     snapshot = map_domain_page(smfn);
@@ -840,7 +911,7 @@
 
         __shadow_get_l4e(v, va, &sl4e);
         if ( !(l4e_get_flags(sl4e) & _PAGE_PRESENT)) {
-            shadow_map_into_current(v, va, L3, L4);
+            shadow_map_into_current(v, va, PAGING_L3, PAGING_L4);
         }
 
         if (!__shadow_get_l3e(v, va, &sl3e)) {
@@ -848,7 +919,7 @@
         }
 
         if ( !(l3e_get_flags(sl3e) & _PAGE_PRESENT)) {
-            shadow_map_into_current(v, va, L2, L3);
+            shadow_map_into_current(v, va, PAGING_L2, PAGING_L3);
         }
     }
 #endif
@@ -886,11 +957,11 @@
  * Returns 0 otherwise.
  */
 static int snapshot_entry_matches(
-    struct domain *d, l1_pgentry_t *guest_pt,
+    struct domain *d, guest_l1_pgentry_t *guest_pt,
     unsigned long gpfn, unsigned index)
 {
     unsigned long smfn = __shadow_status(d, gpfn, PGT_snapshot);
-    l1_pgentry_t *snapshot, gpte; // could be L1s or L2s or ...
+    guest_l1_pgentry_t *snapshot, gpte; // could be L1s or L2s or ...
     int entries_match;
 
     perfc_incrc(snapshot_entry_matches_calls);
@@ -907,7 +978,7 @@
     // This could probably be smarter, but this is sufficent for
     // our current needs.
     //
-    entries_match = !l1e_has_changed(gpte, snapshot[index],
+    entries_match = !guest_l1e_has_changed(gpte, snapshot[index],
                                      PAGE_FLAG_MASK);
 
     unmap_domain_page(snapshot);
@@ -935,10 +1006,10 @@
     unsigned long l2mfn = pagetable_get_pfn(v->arch.guest_table);
 #endif
     unsigned long l2pfn = __mfn_to_gpfn(d, l2mfn);
-    l2_pgentry_t l2e;
+    guest_l2_pgentry_t l2e;
     unsigned long l1pfn, l1mfn;
-    l1_pgentry_t *guest_pt;
-    l1_pgentry_t tmp_gle;
+    guest_l1_pgentry_t *guest_pt;
+    guest_l1_pgentry_t tmp_gle;
     unsigned long pt_va;
 
     ASSERT(shadow_lock_is_acquired(d));
@@ -947,7 +1018,7 @@
     perfc_incrc(shadow_out_of_sync_calls);
 
 #if CONFIG_PAGING_LEVELS >= 4
-    if (d->arch.ops->guest_paging_levels == L4) { /* Mode F */
+    if (d->arch.ops->guest_paging_levels == PAGING_L4) { /* Mode F */
         pgentry_64_t le;
         unsigned long gmfn;
         unsigned long gpfn;
@@ -955,9 +1026,9 @@
 
         gmfn = l2mfn;
         gpfn = l2pfn;
-        guest_pt = (l1_pgentry_t *)v->arch.guest_vtable;
-
-        for (i = L4; i >= L3; i--) {
+        guest_pt = (guest_l1_pgentry_t *)v->arch.guest_vtable;
+
+        for (i = PAGING_L4; i >= PAGING_L3; i--) {
             if ( page_out_of_sync(&frame_table[gmfn]) &&
               !snapshot_entry_matches(
                   d, guest_pt, gpfn, table_offset_64(va, i)) )
@@ -971,7 +1042,7 @@
             if ( !VALID_MFN(gmfn) )
                 return 0;
             /* Todo: check!*/
-            guest_pt = (l1_pgentry_t *)map_domain_page(gmfn);
+            guest_pt = (guest_l1_pgentry_t *)map_domain_page(gmfn);
 
         }
 
@@ -985,13 +1056,13 @@
 #endif
 
     if ( page_out_of_sync(&frame_table[l2mfn]) &&
-         !snapshot_entry_matches(d, (l1_pgentry_t *)v->arch.guest_vtable,
-                                 l2pfn, l2_table_offset(va)) )
+         !snapshot_entry_matches(d, (guest_l1_pgentry_t *)v->arch.guest_vtable,
+                                 l2pfn, guest_l2_table_offset(va)) )
         return 1;
 
     __guest_get_l2e(v, va, &l2e);
-    if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) || 
-         (l2e_get_flags(l2e) & _PAGE_PSE))
+    if ( !(guest_l2e_get_flags(l2e) & _PAGE_PRESENT) || 
+         (guest_l2e_get_flags(l2e) & _PAGE_PSE))
         return 0;
 
     l1pfn = l2e_get_pfn(l2e);
@@ -1000,20 +1071,20 @@
     // If the l1 pfn is invalid, it can't be out of sync...
     if ( !VALID_MFN(l1mfn) )
         return 0;
-    
-    pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(L1_PAGETABLE_ENTRIES - 1))
+
+    pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(GUEST_L1_PAGETABLE_ENTRIES - 1))
       << L1_PAGETABLE_SHIFT;
-    guest_pt = (l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gle);
+    guest_pt = (guest_l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gle);
 
     if ( page_out_of_sync(&frame_table[l1mfn]) &&
          !snapshot_entry_matches(
-             d, guest_pt, l1pfn, l1_table_offset(va)) )
+             d, guest_pt, l1pfn, guest_l1_table_offset(va)) )
         return 1;
 
     return 0;
 }
 
-#define GPFN_TO_GPTEPAGE(_gpfn) ((_gpfn) / (PAGE_SIZE / sizeof(l1_pgentry_t)))
+#define GPFN_TO_GPTEPAGE(_gpfn) ((_gpfn) / (PAGE_SIZE / 
sizeof(guest_l1_pgentry_t)))
 static inline unsigned long
 predict_writable_pte_page(struct domain *d, unsigned long gpfn)
 {
@@ -1107,7 +1178,7 @@
         return (found == max_refs_to_find);
     }
 
-    i = readonly_gpfn & (L1_PAGETABLE_ENTRIES - 1);
+    i = readonly_gpfn & (GUEST_L1_PAGETABLE_ENTRIES - 1);
     if ( !l1e_has_changed(pt[i], match, flags) && fix_entry(i) )
     {
         perfc_incrc(remove_write_fast_exit);
@@ -1116,7 +1187,7 @@
         return found;
     }
  
-    for (i = 0; i < L1_PAGETABLE_ENTRIES; i++)
+    for (i = 0; i < GUEST_L1_PAGETABLE_ENTRIES; i++)
     {
         if ( unlikely(!l1e_has_changed(pt[i], match, flags)) && fix_entry(i) )
             break;
@@ -1281,15 +1352,15 @@
         switch ( stype ) {
         case PGT_l1_shadow:
         {
-            l1_pgentry_t *guest1 = guest;
+            guest_l1_pgentry_t *guest1 = guest;
             l1_pgentry_t *shadow1 = shadow;
-            l1_pgentry_t *snapshot1 = snapshot;
+            guest_l1_pgentry_t *snapshot1 = snapshot;
 
             ASSERT(VM_ASSIST(d, VMASST_TYPE_writable_pagetables) ||
                    shadow_mode_write_all(d));
 
             if ( !shadow_mode_refcounts(d) )
-                revalidate_l1(d, guest1, snapshot1);
+                revalidate_l1(d, (l1_pgentry_t *)guest1, (l1_pgentry_t 
*)snapshot1);
 
             if ( !smfn )
                 break;
@@ -1300,7 +1371,7 @@
             for ( i = min_shadow; i <= max_shadow; i++ )
             {
                 if ( (i < min_snapshot) || (i > max_snapshot) ||
-                     l1e_has_changed(guest1[i], snapshot1[i], PAGE_FLAG_MASK) )
+                     guest_l1e_has_changed(guest1[i], snapshot1[i], 
PAGE_FLAG_MASK) )
                 {
                     need_flush |= validate_pte_change(d, guest1[i], 
&shadow1[i]);
 
@@ -1430,32 +1501,36 @@
         {
             int max = -1;
 
-            l4_pgentry_t *guest4 = guest;
+            guest_root_pgentry_t *guest_root = guest;
             l4_pgentry_t *shadow4 = shadow;
-            l4_pgentry_t *snapshot4 = snapshot;
+            guest_root_pgentry_t *snapshot_root = snapshot;
 
             changed = 0;
-            for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ )
+            for ( i = 0; i < GUEST_ROOT_PAGETABLE_ENTRIES; i++ )
             {
                 if ( !is_guest_l4_slot(i) && !external )
                     continue;
-                l4_pgentry_t new_l4e = guest4[i];
-                if ( l4e_has_changed(new_l4e, snapshot4[i], PAGE_FLAG_MASK))
+                guest_root_pgentry_t new_root_e = guest_root[i];
+                if ( root_entry_has_changed(
+                        new_root_e, snapshot_root[i], PAGE_FLAG_MASK))
                 {
-                    need_flush |= validate_entry_change(
-                      d, (pgentry_64_t *)&new_l4e,
-                      (pgentry_64_t *)&shadow4[i], 
shadow_type_to_level(stype));
-
+                    if (d->arch.ops->guest_paging_levels == PAGING_L4) {
+                        need_flush |= validate_entry_change(
+                          d, (pgentry_64_t *)&new_root_e,
+                          (pgentry_64_t *)&shadow4[i], 
shadow_type_to_level(stype));
+                    } else {
+                        validate_bl2e_change(d, &new_root_e, shadow, i);
+                    }
                     changed++;
                     ESH_LOG("%d: shadow4 mfn: %lx, shadow root: %lx\n", i,
                       smfn, pagetable_get_paddr(current->arch.shadow_table));
                 }
-                if ( l4e_get_intpte(new_l4e) != 0 ) /* FIXME: check flags? */
+                if ( guest_root_get_intpte(new_root_e) != 0 ) /* FIXME: check 
flags? */
                     max = i;
 
                 //  Need a better solution in the long term.
-                if ( !(l4e_get_flags(new_l4e) & _PAGE_PRESENT) &&
-                  unlikely(l4e_get_intpte(new_l4e) != 0) &&
+                if ( !(guest_root_get_flags(new_root_e) & _PAGE_PRESENT) &&
+                  unlikely(guest_root_get_intpte(new_root_e) != 0) &&
                   !unshadow &&
                   (frame_table[smfn].u.inuse.type_info & PGT_pinned) )
                     unshadow = 1;
@@ -1554,8 +1629,14 @@
     if ( shadow_mode_translate(d) )
         need_flush |= resync_all(d, PGT_hl2_shadow);
 #endif
-    need_flush |= resync_all(d, PGT_l2_shadow);
-    need_flush |= resync_all(d, PGT_l3_shadow);
+
+    /*
+     * Fixme: for i386 host
+     */
+    if (d->arch.ops->guest_paging_levels == PAGING_L4) {
+        need_flush |= resync_all(d, PGT_l2_shadow);
+        need_flush |= resync_all(d, PGT_l3_shadow);
+    }
     need_flush |= resync_all(d, PGT_l4_shadow);
 
     if ( need_flush && !unlikely(shadow_mode_external(d)) )
@@ -1565,11 +1646,11 @@
 }
 
 static inline int l1pte_write_fault(
-    struct vcpu *v, l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p,
+    struct vcpu *v, guest_l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p,
     unsigned long va)
 {
     struct domain *d = v->domain;
-    l1_pgentry_t gpte = *gpte_p;
+    guest_l1_pgentry_t gpte = *gpte_p;
     l1_pgentry_t spte;
     unsigned long gpfn = l1e_get_pfn(gpte);
     unsigned long gmfn = __gpfn_to_mfn(d, gpfn);
@@ -1583,9 +1664,9 @@
         return 0;
     }
 
-    ASSERT(l1e_get_flags(gpte) & _PAGE_RW);
-    l1e_add_flags(gpte, _PAGE_DIRTY | _PAGE_ACCESSED);
-    spte = l1e_from_pfn(gmfn, l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
+    ASSERT(guest_l1e_get_flags(gpte) & _PAGE_RW);
+    guest_l1e_add_flags(gpte, _PAGE_DIRTY | _PAGE_ACCESSED);
+    spte = l1e_from_pfn(gmfn, guest_l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
 
     SH_VVLOG("l1pte_write_fault: updating spte=0x%" PRIpte " gpte=0x%" PRIpte,
              l1e_get_intpte(spte), l1e_get_intpte(gpte));
@@ -1603,9 +1684,9 @@
 }
 
 static inline int l1pte_read_fault(
-    struct domain *d, l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p)
+    struct domain *d, guest_l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p)
 { 
-    l1_pgentry_t gpte = *gpte_p;
+    guest_l1_pgentry_t gpte = *gpte_p;
     l1_pgentry_t spte = *spte_p;
     unsigned long pfn = l1e_get_pfn(gpte);
     unsigned long mfn = __gpfn_to_mfn(d, pfn);
@@ -1617,10 +1698,10 @@
         return 0;
     }
 
-    l1e_add_flags(gpte, _PAGE_ACCESSED);
-    spte = l1e_from_pfn(mfn, l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
-
-    if ( shadow_mode_log_dirty(d) || !(l1e_get_flags(gpte) & _PAGE_DIRTY) ||
+    guest_l1e_add_flags(gpte, _PAGE_ACCESSED);
+    spte = l1e_from_pfn(mfn, guest_l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
+
+    if ( shadow_mode_log_dirty(d) || !(guest_l1e_get_flags(gpte) & 
_PAGE_DIRTY) ||
          mfn_is_page_table(mfn) )
     {
         l1e_remove_flags(spte, _PAGE_RW);
@@ -1633,7 +1714,7 @@
 
     return 1;
 }
-
+#if CONFIG_PAGING_LEVELS <= 3
 static int shadow_fault_32(unsigned long va, struct cpu_user_regs *regs)
 {
     l1_pgentry_t gpte, spte, orig_gpte;
@@ -1767,6 +1848,7 @@
     shadow_unlock(d);
     return 0;
 }
+#endif
 
 static int do_update_va_mapping(unsigned long va,
                                 l1_pgentry_t val,
@@ -1786,7 +1868,7 @@
     //
     __shadow_sync_va(v, va);
 
-    l1pte_propagate_from_guest(d, val, &spte);
+    l1pte_propagate_from_guest(d, *(guest_l1_pgentry_t *)&val, &spte);
     shadow_set_l1e(va, spte, 0);
 
     /*
@@ -1847,7 +1929,7 @@
 #if CONFIG_PAGING_LEVELS == 2
     unsigned long hl2mfn;
 #endif
-  
+
     int max_mode = ( shadow_mode_external(d) ? SHM_external
                      : shadow_mode_translate(d) ? SHM_translate
                      : shadow_mode_enabled(d) ? SHM_enable
@@ -1953,17 +2035,6 @@
 #endif
 }
 
-struct shadow_ops MODE_A_HANDLER = {
-    .guest_paging_levels        = 2,
-    .invlpg                     = shadow_invlpg_32,
-    .fault                      = shadow_fault_32,
-    .update_pagetables          = shadow_update_pagetables,
-    .sync_all                   = sync_all,
-    .remove_all_write_access    = remove_all_write_access,
-    .do_update_va_mapping       = do_update_va_mapping,
-    .mark_mfn_out_of_sync       = mark_mfn_out_of_sync,
-    .is_out_of_sync             = is_out_of_sync,
-};
 
 /************************************************************************/
 /************************************************************************/
@@ -2444,12 +2515,90 @@
     BUG();                      /* not implemenated yet */
     return 42;
 }
+static unsigned long gva_to_gpa_pae(unsigned long gva)
+{
+    BUG();
+    return 43;
+}
 #endif
 
 #if CONFIG_PAGING_LEVELS >= 4
 /****************************************************************************/
 /* 64-bit shadow-mode code testing */
 /****************************************************************************/
+/*
+ * validate_bl2e_change()
+ * The code is for 32-bit VMX gues on 64-bit host.
+ * To sync guest L2.
+ */
+
+static inline void
+validate_bl2e_change(
+  struct domain *d,
+  guest_root_pgentry_t *new_gle_p,
+  pgentry_64_t *shadow_l3,
+  int index)
+{
+    int sl3_idx, sl2_idx;
+    unsigned long sl2mfn, sl1mfn;
+    pgentry_64_t *sl2_p;
+
+    /* Using guest l2 pte index to get shadow l3&l2 index
+     * index: 0 ~ 1023, PAGETABLE_ENTRIES: 512
+     */
+    sl3_idx = index / (PAGETABLE_ENTRIES / 2);
+    sl2_idx = (index % (PAGETABLE_ENTRIES / 2)) * 2;
+
+    sl2mfn = entry_get_pfn(shadow_l3[sl3_idx]);
+    sl2_p = (pgentry_64_t *)map_domain_page(sl2mfn);
+
+    validate_pde_change(
+        d, *(guest_l2_pgentry_t *)new_gle_p, (l2_pgentry_t *)&sl2_p[sl2_idx]);
+
+    /* Mapping the second l1 shadow page */
+    if (entry_get_flags(sl2_p[sl2_idx]) & _PAGE_PRESENT) {
+       sl1mfn = entry_get_pfn(sl2_p[sl2_idx]);
+       sl2_p[sl2_idx + 1] =
+            entry_from_pfn(sl1mfn + 1, entry_get_flags(sl2_p[sl2_idx]));
+    }
+    unmap_domain_page(sl2_p);
+
+}
+
+/*
+ * init_bl2() is for 32-bit VMX guest on 64-bit host
+ * Using 1 shadow L4(l3) and 4 shadow L2s to simulate guest L2
+ */
+static inline unsigned long init_bl2(l4_pgentry_t *spl4e, unsigned long smfn)
+{
+    unsigned int count;
+    unsigned long sl2mfn;
+    struct pfn_info *page;
+
+    memset(spl4e, 0, PAGE_SIZE);
+
+    /* Map the self entry, L4&L3 share the same page */
+    spl4e[PAE_SHADOW_SELF_ENTRY] = l4e_from_pfn(smfn, __PAGE_HYPERVISOR);
+
+    /* Allocate 4 shadow L2s */
+    page = alloc_domheap_pages(NULL, SL2_ORDER, 0);
+    if (!page)
+        domain_crash_synchronous();
+
+    for (count = 0; count < PDP_ENTRIES; count++)
+    {
+        sl2mfn = page_to_pfn(page+count);
+        void *l2 = map_domain_page(sl2mfn);
+        memset(l2, 0, PAGE_SIZE);
+        unmap_domain_page(l2);
+        spl4e[count] = l4e_from_pfn(sl2mfn, _PAGE_PRESENT);
+    }
+
+    unmap_domain_page(spl4e);
+    return smfn;
+
+
+}
 
 static unsigned long shadow_l4_table(
   struct domain *d, unsigned long gpfn, unsigned long gmfn)
@@ -2463,11 +2612,16 @@
 
     if ( unlikely(!(smfn = alloc_shadow_page(d, gpfn, gmfn, PGT_l4_shadow))) )
     {
-        printk("Couldn't alloc an L2 shadow for pfn=%lx mfn=%lx\n", gpfn, 
gmfn);
+        printk("Couldn't alloc an L4 shadow for pfn=%lx mfn=%lx\n", gpfn, 
gmfn);
         BUG(); /* XXX Deal gracefully with failure. */
     }
 
     spl4e = (l4_pgentry_t *)map_domain_page(smfn);
+
+    if (d->arch.ops->guest_paging_levels == PAGING_L2) {
+        return init_bl2(spl4e, smfn);
+    }
+
     /* Install hypervisor and 4x linear p.t. mapings. */
     if ( (PGT_base_page_table == PGT_l4_page_table) &&
       !shadow_mode_external(d) )
@@ -2575,7 +2729,7 @@
     pgentry_64_t gle, sle;
     unsigned long gpfn, smfn;
 
-    if (from == L1 && to == L2) {
+    if (from == PAGING_L1 && to == PAGING_L2) {
         shadow_map_l1_into_current_l2(va);
         return;
     }
@@ -2607,7 +2761,7 @@
     if (!(l4e_get_flags(sl4e) & _PAGE_PRESENT)) {
         if (create_l2_shadow) {
             perfc_incrc(shadow_set_l3e_force_map);
-            shadow_map_into_current(v, va, L3, L4);
+            shadow_map_into_current(v, va, PAGING_L3, PAGING_L4);
             __shadow_get_l4e(v, va, &sl4e);
         } else {
             printk("For non VMX shadow, create_l1_shadow:%d\n", 
create_l2_shadow);
@@ -2618,7 +2772,7 @@
     if (!(l3e_get_flags(sl3e) & _PAGE_PRESENT)) {
          if (create_l2_shadow) {
             perfc_incrc(shadow_set_l2e_force_map);
-            shadow_map_into_current(v, va, L2, L3);
+            shadow_map_into_current(v, va, PAGING_L2, PAGING_L3);
             __shadow_get_l3e(v, va, &sl3e);
         } else {
             printk("For non VMX shadow, create_l1_shadow:%d\n", 
create_l2_shadow);
@@ -2654,8 +2808,15 @@
     l1_pgentry_t old_spte;
     l1_pgentry_t sl1e = *(l1_pgentry_t *)sl1e_p;
     int i;
-
-    for (i = L4; i >= L2; i--) {
+    unsigned long orig_va = 0;
+
+    if (d->arch.ops->guest_paging_levels == PAGING_L2) {
+        /* This is for 32-bit VMX guest on 64-bit host */
+        orig_va = va;
+        va = va & (~((1<<L2_PAGETABLE_SHIFT_32)-1));
+    }
+
+    for (i = PAGING_L4; i >= PAGING_L2; i--) {
         if (!__rw_entry(v, va, &sle, SHADOW_ENTRY | GET_ENTRY | i)) {
             printk("<%s> i = %d\n", __func__, i);
             BUG();
@@ -2671,9 +2832,13 @@
 #endif
             }
         }
-        if(i < L4)
+        if(i < PAGING_L4)
             shadow_update_min_max(entry_get_pfn(sle_up), table_offset_64(va, 
i));
         sle_up = sle;
+    }
+
+    if (d->arch.ops->guest_paging_levels == PAGING_L2) {
+        va = orig_va;
     }
 
     if ( shadow_mode_refcounts(d) )
@@ -2691,9 +2856,13 @@
     }
 
     __shadow_set_l1e(v, va, &sl1e);
-    shadow_update_min_max(entry_get_pfn(sle_up), table_offset_64(va, L1));
-}
-
+
+    shadow_update_min_max(entry_get_pfn(sle_up), guest_l1_table_offset(va));
+}
+
+/* As 32-bit guest don't support 4M page yet,
+ * we don't concern double compile for this function
+ */
 static inline int l2e_rw_fault(
     struct vcpu *v, l2_pgentry_t *gl2e_p, unsigned long va, int rw)
 {
@@ -2824,12 +2993,120 @@
 
 }
 
+/*
+ * Check P, R/W, U/S bits in the guest page table.
+ * If the fault belongs to guest return 1,
+ * else return 0.
+ */
+#if defined( GUEST_PGENTRY_32 )
+static inline int guest_page_fault(struct vcpu *v,
+  unsigned long va, unsigned int error_code, 
+  guest_l2_pgentry_t *gpl2e, guest_l1_pgentry_t *gpl1e)
+{
+    /* The following check for 32-bit guest on 64-bit host */
+
+    __guest_get_l2e(v, va, gpl2e);
+
+    /* Check the guest L2 page-table entry first*/
+    if (unlikely(!(guest_l2e_get_flags(*gpl2e) & _PAGE_PRESENT)))
+        return 1;
+
+    if (error_code & ERROR_W) {
+        if (unlikely(!(guest_l2e_get_flags(*gpl2e) & _PAGE_RW)))
+            return 1;
+    }
+    if (error_code & ERROR_U) {
+        if (unlikely(!(guest_l2e_get_flags(*gpl2e) & _PAGE_USER)))
+            return 1;
+    }
+
+    if (guest_l2e_get_flags(*gpl2e) & _PAGE_PSE)
+        return 0;
+
+    __guest_get_l1e(v, va, gpl1e);
+
+    /* Then check the guest L1 page-table entry */
+    if (unlikely(!(guest_l1e_get_flags(*gpl1e) & _PAGE_PRESENT)))
+        return 1;
+
+    if (error_code & ERROR_W) {
+        if (unlikely(!(guest_l1e_get_flags(*gpl1e) & _PAGE_RW)))
+            return 1;
+    }
+    if (error_code & ERROR_U) {
+        if (unlikely(!(guest_l1e_get_flags(*gpl1e) & _PAGE_USER)))
+            return 1;
+    }
+
+    return 0;
+}
+#else
+static inline int guest_page_fault(struct vcpu *v,
+  unsigned long va, unsigned int error_code, 
+  guest_l2_pgentry_t *gpl2e, guest_l1_pgentry_t *gpl1e)
+{
+    struct domain *d = v->domain;
+    pgentry_64_t gle, *lva;
+    unsigned long mfn;
+    int i;
+
+    __rw_entry(v, va, &gle, GUEST_ENTRY | GET_ENTRY | PAGING_L4);
+    if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT)))
+        return 1;
+
+    if (error_code & ERROR_W) {
+        if (unlikely(!(entry_get_flags(gle) & _PAGE_RW)))
+            return 1;
+    }
+    if (error_code & ERROR_U) {
+        if (unlikely(!(entry_get_flags(gle) & _PAGE_USER)))
+            return 1;
+    }
+    for (i = PAGING_L3; i >= PAGING_L1; i--) {
+        /*
+         * If it's not external mode, then mfn should be machine physical.
+         */
+        mfn = __gpfn_to_mfn(d, (entry_get_value(gle) >> PAGE_SHIFT));
+
+        lva = (pgentry_64_t *) phys_to_virt(
+          mfn << PAGE_SHIFT);
+        gle = lva[table_offset_64(va, i)];
+
+        if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT)))
+            return 1;
+
+        if (error_code & ERROR_W) {
+            if (unlikely(!(entry_get_flags(gle) & _PAGE_RW)))
+                return 1;
+        }
+        if (error_code & ERROR_U) {
+            if (unlikely(!(entry_get_flags(gle) & _PAGE_USER)))
+                return 1;
+        }
+
+        if (i == PAGING_L2) {
+            if (gpl2e)
+                gpl2e->l2 = gle.lo;
+
+            if (likely(entry_get_flags(gle) & _PAGE_PSE))
+                return 0;
+
+        }
+
+        if (i == PAGING_L1)
+            if (gpl1e)
+                gpl1e->l1 = gle.lo;
+    }
+    return 0;
+}
+#endif
 static int shadow_fault_64(unsigned long va, struct cpu_user_regs *regs)
 {
     struct vcpu *v = current;
     struct domain *d = v->domain;
-    l2_pgentry_t gl2e;
-    l1_pgentry_t sl1e, gl1e;
+    guest_l2_pgentry_t gl2e;
+    guest_l1_pgentry_t gl1e;
+    l1_pgentry_t sl1e;
 
     perfc_incrc(shadow_fault_calls);
 
@@ -2852,12 +3129,11 @@
      * STEP 2. Check if the fault belongs to guest
      */
     if ( guest_page_fault(
-            v, va, regs->error_code, 
-            (pgentry_64_t *)&gl2e, (pgentry_64_t *)&gl1e) ) {
+            v, va, regs->error_code, &gl2e, &gl1e) ) {
         goto fail;
     }
     
-    if ( unlikely(!(l2e_get_flags(gl2e) & _PAGE_PSE)) ) {
+    if ( unlikely(!(guest_l2e_get_flags(gl2e) & _PAGE_PSE)) ) {
         /*
          * Handle 4K pages here
          */
@@ -2891,11 +3167,11 @@
          */
         /* Write fault? */
         if ( regs->error_code & 2 ) {
-            if ( !l2e_rw_fault(v, &gl2e, va, WRITE_FAULT) ) {
+            if ( !l2e_rw_fault(v, (l2_pgentry_t *)&gl2e, va, WRITE_FAULT) ) {
                 goto fail;
             }
         } else {
-            l2e_rw_fault(v, &gl2e, va, READ_FAULT);
+            l2e_rw_fault(v, (l2_pgentry_t *)&gl2e, va, READ_FAULT);
         }
 
         /*
@@ -2943,7 +3219,27 @@
     shadow_unlock(d);
 }
 
-#ifndef PGENTRY_32
+static unsigned long gva_to_gpa_64(unsigned long gva)
+{
+    struct vcpu *v = current;
+    guest_l1_pgentry_t gl1e = {0};
+    guest_l2_pgentry_t gl2e = {0};
+    unsigned long gpa;
+
+    if (guest_page_fault(v, gva, 0, &gl2e, &gl1e))
+        return 0;
+    
+    if (guest_l2e_get_flags(gl2e) & _PAGE_PSE)
+        gpa = guest_l2e_get_paddr(gl2e) + (gva & ((1 << 
GUEST_L2_PAGETABLE_SHIFT) - 1));
+    else
+        gpa = guest_l1e_get_paddr(gl1e) + (gva & ~PAGE_MASK);
+
+    return gpa;
+
+}
+
+#ifndef GUEST_PGENTRY_32
+
 struct shadow_ops MODE_F_HANDLER = {
     .guest_paging_levels              = 4,
     .invlpg                     = shadow_invlpg_64,
@@ -2954,10 +3250,42 @@
     .do_update_va_mapping       = do_update_va_mapping,
     .mark_mfn_out_of_sync       = mark_mfn_out_of_sync,
     .is_out_of_sync             = is_out_of_sync,
+    .gva_to_gpa                 = gva_to_gpa_64,
 };
 #endif
 
 #endif
+
+#if CONFIG_PAGING_LEVELS == 2
+struct shadow_ops MODE_A_HANDLER = {
+    .guest_paging_levels        = 2,
+    .invlpg                     = shadow_invlpg_32,
+    .fault                      = shadow_fault_32,
+    .update_pagetables          = shadow_update_pagetables,
+    .sync_all                   = sync_all,
+    .remove_all_write_access    = remove_all_write_access,
+    .do_update_va_mapping       = do_update_va_mapping,
+    .mark_mfn_out_of_sync       = mark_mfn_out_of_sync,
+    .is_out_of_sync             = is_out_of_sync,
+    .gva_to_gpa                 = gva_to_gpa_64,
+};
+
+#elif CONFIG_PAGING_LEVELS == 3
+struct shadow_ops MODE_B_HANDLER = {
+    .guest_paging_levels              = 3,
+    .invlpg                     = shadow_invlpg_32,
+    .fault                      = shadow_fault_32,
+    .update_pagetables          = shadow_update_pagetables,
+    .sync_all                   = sync_all,
+    .remove_all_write_access    = remove_all_write_access,
+    .do_update_va_mapping       = do_update_va_mapping,
+    .mark_mfn_out_of_sync       = mark_mfn_out_of_sync,
+    .is_out_of_sync             = is_out_of_sync,
+    .gva_to_gpa                 = gva_to_gpa_pae,
+};
+
+#endif
+
 
 /*
  * Local variables:
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/shadow32.c
--- a/xen/arch/x86/shadow32.c   Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/shadow32.c   Fri Sep  9 16:30:54 2005
@@ -827,7 +827,7 @@
     {
         page = list_entry(list_ent, struct pfn_info, list);
         mfn = page_to_pfn(page);
-        pfn = machine_to_phys_mapping[mfn];
+        pfn = get_pfn_from_mfn(mfn);
         ASSERT(pfn != INVALID_M2P_ENTRY);
         ASSERT(pfn < (1u<<20));
 
@@ -841,7 +841,7 @@
     {
         page = list_entry(list_ent, struct pfn_info, list);
         mfn = page_to_pfn(page);
-        pfn = machine_to_phys_mapping[mfn];
+        pfn = get_pfn_from_mfn(mfn);
         if ( (pfn != INVALID_M2P_ENTRY) &&
              (pfn < (1u<<20)) )
         {
@@ -1685,6 +1685,7 @@
     if (__copy_from_user(&gpte, &linear_pg_table[va >> PAGE_SHIFT],
                          sizeof(gpte))) {
         perfc_incrc(shadow_invlpg_faults);
+        shadow_unlock(d);
         return;
     }
     l1pte_propagate_from_guest(d, gpte, &spte);
@@ -1917,8 +1918,10 @@
     snapshot = map_domain_page(smfn);
 
     if (__copy_from_user(&gpte, &guest_pt[index],
-                         sizeof(gpte)))
+                         sizeof(gpte))) {
+        unmap_domain_page(snapshot);
         return 0;
+    }
 
     // This could probably be smarter, but this is sufficent for
     // our current needs.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/shadow_public.c
--- a/xen/arch/x86/shadow_public.c      Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/shadow_public.c      Fri Sep  9 16:30:54 2005
@@ -33,11 +33,15 @@
 #if CONFIG_PAGING_LEVELS >= 3
 #include <asm/shadow_64.h>
 
+#endif
+#if CONFIG_PAGING_LEVELS == 4
 extern struct shadow_ops MODE_F_HANDLER;
+extern struct shadow_ops MODE_D_HANDLER;
 #endif
 
 extern struct shadow_ops MODE_A_HANDLER;
 
+#define SHADOW_MAX_GUEST32(_encoded) ((L1_PAGETABLE_ENTRIES_32 - 1) - 
((_encoded) >> 16))
 /****************************************************************************/
 /************* export interface functions ***********************************/
 /****************************************************************************/
@@ -48,7 +52,7 @@
     shadow_lock(d);
 
     switch(levels) {
-#if CONFIG_PAGING_LEVELS >= 4 
+#if CONFIG_PAGING_LEVELS >= 4
     case 4:
        if ( d->arch.ops != &MODE_F_HANDLER )
            d->arch.ops = &MODE_F_HANDLER;
@@ -56,9 +60,14 @@
         return 1;
 #endif
     case 3:
-    case 2:                     
+    case 2:
+#if CONFIG_PAGING_LEVELS == 2
        if ( d->arch.ops != &MODE_A_HANDLER )
            d->arch.ops = &MODE_A_HANDLER;
+#elif CONFIG_PAGING_LEVELS == 4
+       if ( d->arch.ops != &MODE_D_HANDLER )
+           d->arch.ops = &MODE_D_HANDLER;
+#endif
        shadow_unlock(d);
         return 1;
    default:
@@ -122,13 +131,17 @@
     return d->arch.ops->is_out_of_sync(v, va);
 }
 
+unsigned long gva_to_gpa(unsigned long gva)
+{
+    struct domain *d = current->domain;
+    return d->arch.ops->gva_to_gpa(gva);
+}
 /****************************************************************************/
 /****************************************************************************/
 #if CONFIG_PAGING_LEVELS >= 4
 /*
  * Convert PAE 3-level page-table to 4-level page-table
  */
-#define PDP_ENTRIES   4
 static pagetable_t page_table_convert(struct domain *d)
 {
     struct pfn_info *l4page, *l3page;
@@ -203,19 +216,41 @@
 /*
  * Free l2, l3, l4 shadow tables
  */
+
+void free_fake_shadow_l2(struct domain *d,unsigned long smfn);
+
 static void inline
 free_shadow_tables(struct domain *d, unsigned long smfn, u32 level)
 {
     pgentry_64_t *ple = map_domain_page(smfn);
     int i, external = shadow_mode_external(d);
-
-    for ( i = 0; i < PAGETABLE_ENTRIES; i++ )
-        if ( external || is_guest_l4_slot(i) )
-            if ( entry_get_flags(ple[i]) & _PAGE_PRESENT )
-                put_shadow_ref(entry_get_pfn(ple[i]));
-
-    unmap_domain_page(ple);
-}
+    struct pfn_info *page = &frame_table[smfn];
+
+    if (d->arch.ops->guest_paging_levels == PAGING_L2)
+    {
+#if CONFIG_PAGING_LEVELS >=4
+        for ( i = 0; i < PDP_ENTRIES; i++ )
+        {
+            if (entry_get_flags(ple[i]) & _PAGE_PRESENT )
+                free_fake_shadow_l2(d,entry_get_pfn(ple[i]));
+        }
+   
+        page = &frame_table[entry_get_pfn(ple[0])];
+        free_domheap_pages(page, SL2_ORDER);
+        unmap_domain_page(ple);
+#endif
+    }
+    else
+    {
+        for ( i = 0; i < PAGETABLE_ENTRIES; i++ )
+            if ( external || is_guest_l4_slot(i) )
+                if ( entry_get_flags(ple[i]) & _PAGE_PRESENT )
+                        put_shadow_ref(entry_get_pfn(ple[i]));
+
+        unmap_domain_page(ple);
+    }
+}
+
 
 void free_monitor_pagetable(struct vcpu *v)
 {
@@ -453,7 +488,12 @@
     struct pfn_info *spage = pfn_to_page(smfn);
     u32 min_max = spage->tlbflush_timestamp;
     int min = SHADOW_MIN(min_max);
-    int max = SHADOW_MAX(min_max);
+    int max;
+    
+    if (d->arch.ops->guest_paging_levels == PAGING_L2)
+        max = SHADOW_MAX_GUEST32(min_max);
+    else
+        max = SHADOW_MAX(min_max);
 
     for ( i = min; i <= max; i++ )
     {
@@ -512,9 +552,24 @@
     unmap_domain_page(pl2e);
 }
 
+void free_fake_shadow_l2(struct domain *d, unsigned long smfn)
+{
+    pgentry_64_t *ple = map_domain_page(smfn);
+    int i;
+
+    for ( i = 0; i < PAGETABLE_ENTRIES; i = i + 2 )
+    {
+        if ( entry_get_flags(ple[i]) & _PAGE_PRESENT )
+            put_shadow_ref(entry_get_pfn(ple[i]));
+    }
+
+    unmap_domain_page(ple);
+}
+
 void free_shadow_page(unsigned long smfn)
 {
     struct pfn_info *page = &frame_table[smfn];
+
     unsigned long gmfn = page->u.inuse.type_info & PGT_mfn_mask;
     struct domain *d = page_get_owner(pfn_to_page(gmfn));
     unsigned long gpfn = __mfn_to_gpfn(d, gmfn);
@@ -531,6 +586,7 @@
             gpfn |= (1UL << 63);
     }
 #endif
+
     delete_shadow_status(d, gpfn, gmfn, type);
 
     switch ( type )
@@ -687,7 +743,7 @@
     int                   i;
     struct shadow_status *x;
     struct vcpu          *v;
- 
+
     /*
      * WARNING! The shadow page table must not currently be in use!
      * e.g., You are expected to have paused the domain and synchronized CR3.
@@ -794,7 +850,16 @@
         perfc_decr(free_l1_pages);
 
         struct pfn_info *page = list_entry(list_ent, struct pfn_info, list);
-        free_domheap_page(page);
+       if (d->arch.ops->guest_paging_levels == PAGING_L2)
+       {
+#if CONFIG_PAGING_LEVELS >=4
+        free_domheap_pages(page, SL1_ORDER);
+#else
+       free_domheap_page(page);
+#endif
+       }
+       else
+       free_domheap_page(page);
     }
 
     shadow_audit(d, 0);
@@ -1191,7 +1256,7 @@
     {
         DPRINTK("Don't try to do a shadow op on yourself!\n");
         return -EINVAL;
-    }   
+    }
 
     domain_pause(d);
 
@@ -1311,7 +1376,7 @@
     {
         page = list_entry(list_ent, struct pfn_info, list);
         mfn = page_to_pfn(page);
-        pfn = machine_to_phys_mapping[mfn];
+        pfn = get_pfn_from_mfn(mfn);
         ASSERT(pfn != INVALID_M2P_ENTRY);
         ASSERT(pfn < (1u<<20));
 
@@ -1325,7 +1390,7 @@
     {
         page = list_entry(list_ent, struct pfn_info, list);
         mfn = page_to_pfn(page);
-        pfn = machine_to_phys_mapping[mfn];
+        pfn = get_pfn_from_mfn(mfn);
         if ( (pfn != INVALID_M2P_ENTRY) &&
              (pfn < (1u<<20)) )
         {
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/time.c       Fri Sep  9 16:30:54 2005
@@ -792,6 +792,13 @@
     tsc_elapsed64   = curr_tsc - prev_tsc;
 
     /*
+     * Weirdness can happen if we lose sync with the platform timer.
+     * We could be smarter here: resync platform timer with local timer?
+     */
+    if ( ((s64)stime_elapsed64 < (EPOCH / 2)) )
+        goto out;
+
+    /*
      * Calculate error-correction factor. This only slows down a fast local
      * clock (slow clocks are warped forwards). The scale factor is clamped
      * to >= 0.5.
@@ -854,6 +861,7 @@
     cpu_time[cpu].stime_local_stamp  = curr_local_stime;
     cpu_time[cpu].stime_master_stamp = curr_master_stime;
 
+ out:
     set_ac_timer(&cpu_time[cpu].calibration_timer, NOW() + EPOCH);
 
     if ( cpu == 0 )
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/traps.c      Fri Sep  9 16:30:54 2005
@@ -101,6 +101,14 @@
 static int debug_stack_lines = 20;
 integer_param("debug_stack_lines", debug_stack_lines);
 
+#ifdef CONFIG_X86_32
+#define stack_words_per_line 8
+#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)&regs->esp)
+#else
+#define stack_words_per_line 4
+#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)regs->esp)
+#endif
+
 int is_kernel_text(unsigned long addr)
 {
     extern char _stext, _etext;
@@ -117,17 +125,16 @@
     return (unsigned long) &_etext;
 }
 
-void show_guest_stack(void)
+static void show_guest_stack(struct cpu_user_regs *regs)
 {
     int i;
-    struct cpu_user_regs *regs = guest_cpu_user_regs();
     unsigned long *stack = (unsigned long *)regs->esp, addr;
 
     printk("Guest stack trace from "__OP"sp=%p:\n   ", stack);
 
-    for ( i = 0; i < (debug_stack_lines*8); i++ )
-    {
-        if ( ((long)stack & (STACK_SIZE-1)) == 0 )
+    for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )
+    {
+        if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )
             break;
         if ( get_user(addr, stack) )
         {
@@ -137,7 +144,7 @@
             i = 1;
             break;
         }
-        if ( (i != 0) && ((i % 8) == 0) )
+        if ( (i != 0) && ((i % stack_words_per_line) == 0) )
             printk("\n   ");
         printk("%p ", _p(addr));
         stack++;
@@ -147,40 +154,100 @@
     printk("\n");
 }
 
-void show_trace(unsigned long *esp)
-{
-    unsigned long *stack = esp, addr;
-    int i = 0;
-
-    printk("Xen call trace from "__OP"sp=%p:\n   ", stack);
-
-    while ( ((long) stack & (STACK_SIZE-1)) != 0 )
+#ifdef NDEBUG
+
+static void show_trace(struct cpu_user_regs *regs)
+{
+    unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;
+
+    printk("Xen call trace:\n   ");
+
+    printk("[<%p>]", _p(regs->eip));
+    print_symbol(" %s\n   ", regs->eip);
+
+    while ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) != 0 )
     {
         addr = *stack++;
         if ( is_kernel_text(addr) )
         {
             printk("[<%p>]", _p(addr));
             print_symbol(" %s\n   ", addr);
-            i++;
-        }
-    }
-    if ( i == 0 )
-        printk("Trace empty.");
+        }
+    }
+
     printk("\n");
 }
 
-void show_stack(unsigned long *esp)
-{
-    unsigned long *stack = esp, addr;
+#else
+
+static void show_trace(struct cpu_user_regs *regs)
+{
+    unsigned long *frame, next, addr, low, high;
+
+    printk("Xen call trace:\n   ");
+
+    printk("[<%p>]", _p(regs->eip));
+    print_symbol(" %s\n   ", regs->eip);
+
+    /* Bounds for range of valid frame pointer. */
+    low  = (unsigned long)(ESP_BEFORE_EXCEPTION(regs) - 2);
+    high = (low & ~(STACK_SIZE - 1)) + (STACK_SIZE - sizeof(struct cpu_info));
+
+    /* The initial frame pointer. */
+    next = regs->ebp;
+
+    for ( ; ; )
+    {
+        /* Valid frame pointer? */
+        if ( (next < low) || (next > high) )
+        {
+            /*
+             * Exception stack frames have a different layout, denoted by an
+             * inverted frame pointer.
+             */
+            next = ~next;
+            if ( (next < low) || (next > high) )
+                break;
+            frame = (unsigned long *)next;
+            next  = frame[0];
+            addr  = frame[(offsetof(struct cpu_user_regs, eip) -
+                           offsetof(struct cpu_user_regs, ebp))
+                         / BYTES_PER_LONG];
+        }
+        else
+        {
+            /* Ordinary stack frame. */
+            frame = (unsigned long *)next;
+            next  = frame[0];
+            addr  = frame[1];
+        }
+
+        printk("[<%p>]", _p(addr));
+        print_symbol(" %s\n   ", addr);
+
+        low = (unsigned long)&frame[2];
+    }
+
+    printk("\n");
+}
+
+#endif
+
+void show_stack(struct cpu_user_regs *regs)
+{
+    unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;
     int i;
 
+    if ( GUEST_MODE(regs) )
+        return show_guest_stack(regs);
+
     printk("Xen stack trace from "__OP"sp=%p:\n   ", stack);
 
-    for ( i = 0; i < (debug_stack_lines*8); i++ )
-    {
-        if ( ((long)stack & (STACK_SIZE-1)) == 0 )
-            break;
-        if ( (i != 0) && ((i % 8) == 0) )
+    for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )
+    {
+        if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )
+            break;
+        if ( (i != 0) && ((i % stack_words_per_line) == 0) )
             printk("\n   ");
         addr = *stack++;
         printk("%p ", _p(addr));
@@ -189,7 +256,7 @@
         printk("Stack empty.");
     printk("\n");
 
-    show_trace(esp);
+    show_trace(regs);
 }
 
 /*
@@ -403,20 +470,32 @@
     return EXCRET_fault_fixed;
 }
 
-asmlinkage int do_page_fault(struct cpu_user_regs *regs)
-{
-    unsigned long addr, fixup;
-    struct vcpu *v = current;
+#ifdef HYPERVISOR_VIRT_END
+#define IN_HYPERVISOR_RANGE(va) \
+    (((va) >= HYPERVISOR_VIRT_START) && ((va) < HYPERVISOR_VIRT_END))
+#else
+#define IN_HYPERVISOR_RANGE(va) \
+    (((va) >= HYPERVISOR_VIRT_START))
+#endif
+
+static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs)
+{
+    struct vcpu   *v = current;
     struct domain *d = v->domain;
 
-    __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : );
-
-    DEBUGGER_trap_entry(TRAP_page_fault, regs);
-
-    perfc_incrc(page_faults);
-
-    if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables) &&
-                !shadow_mode_enabled(d)) )
+    if ( unlikely(IN_HYPERVISOR_RANGE(addr)) )
+    {
+        if ( shadow_mode_external(d) && GUEST_CONTEXT(v, regs) )
+            return shadow_fault(addr, regs);
+        if ( (addr >= PERDOMAIN_VIRT_START) && (addr < PERDOMAIN_VIRT_END) )
+            return handle_perdomain_mapping_fault(
+                addr - PERDOMAIN_VIRT_START, regs);
+    }
+    else if ( unlikely(shadow_mode_enabled(d)) )
+    {
+        return shadow_fault(addr, regs);
+    }
+    else if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
     {
         LOCK_BIGLOCK(d);
         if ( unlikely(d->arch.ptwr[PTWR_PT_ACTIVE].l1va) &&
@@ -428,14 +507,9 @@
             return EXCRET_fault_fixed;
         }
 
-        if ( ((addr < HYPERVISOR_VIRT_START) 
-#if defined(__x86_64__)
-              || (addr >= HYPERVISOR_VIRT_END)
-#endif        
-            )     
-             &&
-             KERNEL_MODE(v, regs) &&
-             ((regs->error_code & 3) == 3) && /* write-protection fault */
+        if ( KERNEL_MODE(v, regs) &&
+             /* Protection violation on write? No reserved-bit violation? */
+             ((regs->error_code & 0xb) == 0x3) &&
              ptwr_do_page_fault(d, addr, regs) )
         {
             UNLOCK_BIGLOCK(d);
@@ -444,43 +518,51 @@
         UNLOCK_BIGLOCK(d);
     }
 
-    if ( unlikely(shadow_mode_enabled(d)) &&
-         ((addr < HYPERVISOR_VIRT_START) ||
-#if defined(__x86_64__)
-          (addr >= HYPERVISOR_VIRT_END) ||
-#endif
-          (shadow_mode_external(d) && GUEST_CONTEXT(v, regs))) &&
-         shadow_fault(addr, regs) )
-        return EXCRET_fault_fixed;
-
-    if ( unlikely(addr >= PERDOMAIN_VIRT_START) &&
-         unlikely(addr < PERDOMAIN_VIRT_END) &&
-         handle_perdomain_mapping_fault(addr - PERDOMAIN_VIRT_START, regs) )
-        return EXCRET_fault_fixed;
-
-    if ( !GUEST_MODE(regs) )
-        goto xen_fault;
+    return 0;
+}
+
+/*
+ * #PF error code:
+ *  Bit 0: Protection violation (=1) ; Page not present (=0)
+ *  Bit 1: Write access
+ *  Bit 2: Supervisor mode
+ *  Bit 3: Reserved bit violation
+ *  Bit 4: Instruction fetch
+ */
+asmlinkage int do_page_fault(struct cpu_user_regs *regs)
+{
+    unsigned long addr, fixup;
+    int rc;
+
+    __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : );
+
+    DEBUGGER_trap_entry(TRAP_page_fault, regs);
+
+    perfc_incrc(page_faults);
+
+    if ( unlikely((rc = fixup_page_fault(addr, regs)) != 0) )
+        return rc;
+
+    if ( unlikely(!GUEST_MODE(regs)) )
+    {
+        if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
+        {
+            perfc_incrc(copy_user_faults);
+            regs->eip = fixup;
+            return 0;
+        }
+
+        DEBUGGER_trap_fatal(TRAP_page_fault, regs);
+
+        show_registers(regs);
+        show_page_walk(addr);
+        panic("CPU%d FATAL PAGE FAULT\n"
+              "[error_code=%04x]\n"
+              "Faulting linear address: %p\n",
+              smp_processor_id(), regs->error_code, addr);
+    }
 
     propagate_page_fault(addr, regs->error_code);
-    return 0;
-
- xen_fault:
-
-    if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
-    {
-        perfc_incrc(copy_user_faults);
-        regs->eip = fixup;
-        return 0;
-    }
-
-    DEBUGGER_trap_fatal(TRAP_page_fault, regs);
-
-    show_registers(regs);
-    show_page_walk(addr);
-    panic("CPU%d FATAL PAGE FAULT\n"
-          "[error_code=%04x]\n"
-          "Faulting linear address: %p\n",
-          smp_processor_id(), regs->error_code, addr);
     return 0;
 }
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/vmx.c
--- a/xen/arch/x86/vmx.c        Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/vmx.c        Fri Sep  9 16:30:54 2005
@@ -49,6 +49,15 @@
 int vmcs_size;
 unsigned int opt_vmx_debug_level = 0;
 integer_param("vmx_debug", opt_vmx_debug_level);
+
+extern int hvm_enabled;
+
+#ifdef TRACE_BUFFER
+static unsigned long trace_values[NR_CPUS][4];
+#define TRACE_VMEXIT(index,value) trace_values[current->processor][index]=value
+#else
+#define TRACE_VMEXIT(index,value) ((void)0)
+#endif
 
 #ifdef __x86_64__
 static struct msr_state percpu_msr[NR_CPUS];
@@ -338,6 +347,8 @@
 
     vmx_save_init_msrs();
 
+    hvm_enabled = 1;
+
     return 1;
 }
 
@@ -351,7 +362,7 @@
  * Not all cases receive valid value in the VM-exit instruction length field.
  */
 #define __get_instruction_length(len) \
-    __vmread(INSTRUCTION_LEN, &(len)); \
+    __vmread(VM_EXIT_INSTRUCTION_LEN, &(len)); \
      if ((len) < 1 || (len) > 15) \
         __vmx_bug(&regs);
 
@@ -381,6 +392,7 @@
 
     if (!vmx_paging_enabled(current)){
         handle_mmio(va, va);
+        TRACE_VMEXIT (2,2);
         return 1;
     }
     gpa = gva_to_gpa(va);
@@ -389,21 +401,22 @@
     if ( mmio_space(gpa) ){
         if (gpa >= 0xFEE00000) { /* workaround for local APIC */
             u32 inst_len;
-            __vmread(INSTRUCTION_LEN, &(inst_len));
+            __vmread(VM_EXIT_INSTRUCTION_LEN, &(inst_len));
             __update_guest_eip(inst_len);
             return 1;
         }
+        TRACE_VMEXIT (2,2);
         handle_mmio(va, gpa);
         return 1;
     }
 
     result = shadow_fault(va, regs);
-
+    TRACE_VMEXIT (2,result);
 #if 0
     if ( !result )
     {
         __vmread(GUEST_RIP, &eip);
-        printk("vmx pgfault to guest va=%p eip=%p\n", va, eip);
+        printk("vmx pgfault to guest va=%lx eip=%lx\n", va, eip);
     }
 #endif
 
@@ -447,7 +460,16 @@
         clear_bit(X86_FEATURE_PSE, &edx);
         clear_bit(X86_FEATURE_PAE, &edx);
         clear_bit(X86_FEATURE_PSE36, &edx);
+#else
+        struct vcpu *d = current;
+        if (d->domain->arch.ops->guest_paging_levels == PAGING_L2)
+        {
+            clear_bit(X86_FEATURE_PSE, &edx);
+            clear_bit(X86_FEATURE_PAE, &edx);
+            clear_bit(X86_FEATURE_PSE36, &edx);
+        }
 #endif
+
     }
 
     regs->eax = (unsigned long) eax;
@@ -542,7 +564,7 @@
     int i, inst_len;
     int inst_copy_from_guest(unsigned char *, unsigned long, int);
 
-    __vmread(INSTRUCTION_LEN, &inst_len);
+    __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
     memset(inst, 0, MAX_INST_LEN);
     if (inst_copy_from_guest(inst, eip, inst_len) != inst_len) {
         printf("check_for_null_selector: get guest instruction failed\n");
@@ -584,15 +606,66 @@
     return 0;
 }
 
+void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
+       unsigned long count, int size, long value, int dir, int pvalid)
+{
+    struct vcpu *v = current;
+    vcpu_iodata_t *vio;
+    ioreq_t *p;
+
+    vio = get_vio(v->domain, v->vcpu_id);
+    if (vio == NULL) {
+        printk("bad shared page: %lx\n", (unsigned long) vio);
+        domain_crash_synchronous();
+    }
+
+    if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
+       printf("VMX I/O has not yet completed\n");
+       domain_crash_synchronous();
+    }
+    set_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
+
+    p = &vio->vp_ioreq;
+    p->dir = dir;
+    p->pdata_valid = pvalid;
+
+    p->type = IOREQ_TYPE_PIO;
+    p->size = size;
+    p->addr = port;
+    p->count = count;
+    p->df = regs->eflags & EF_DF ? 1 : 0;
+
+    if (pvalid) {
+        if (vmx_paging_enabled(current))
+            p->u.pdata = (void *) gva_to_gpa(value);
+        else
+            p->u.pdata = (void *) value; /* guest VA == guest PA */
+    } else
+        p->u.data = value;
+
+    p->state = STATE_IOREQ_READY;
+
+    if (vmx_portio_intercept(p)) {
+        /* no blocking & no evtchn notification */
+        clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
+        return;
+    }
+
+    evtchn_send(iopacket_port(v->domain));
+    vmx_wait_io();
+}
+
 static void vmx_io_instruction(struct cpu_user_regs *regs, 
                    unsigned long exit_qualification, unsigned long inst_len) 
 {
-    struct vcpu *d = current;
-    vcpu_iodata_t *vio;
-    ioreq_t *p;
-    unsigned long addr;
+    struct mi_per_cpu_info *mpcip;
     unsigned long eip, cs, eflags;
+    unsigned long port, size, dir;
     int vm86;
+
+    mpcip = &current->domain->arch.vmx_platform.mpci;
+    mpcip->instr = INSTR_PIO;
+    mpcip->flags = 0;
 
     __vmread(GUEST_RIP, &eip);
     __vmread(GUEST_CS_SELECTOR, &cs);
@@ -605,104 +678,93 @@
                 vm86, cs, eip, exit_qualification);
 
     if (test_bit(6, &exit_qualification))
-        addr = (exit_qualification >> 16) & (0xffff);
+        port = (exit_qualification >> 16) & 0xFFFF;
     else
-        addr = regs->edx & 0xffff;
-
-    vio = get_vio(d->domain, d->vcpu_id);
-    if (vio == 0) {
-        printk("bad shared page: %lx", (unsigned long) vio);
-        domain_crash_synchronous(); 
-    }
-    p = &vio->vp_ioreq;
-    p->dir = test_bit(3, &exit_qualification); /* direction */
-
-    p->pdata_valid = 0;
-    p->count = 1;
-    p->size = (exit_qualification & 7) + 1;
+        port = regs->edx & 0xffff;
+    TRACE_VMEXIT(2, port);
+    size = (exit_qualification & 7) + 1;
+    dir = test_bit(3, &exit_qualification); /* direction */
 
     if (test_bit(4, &exit_qualification)) { /* string instruction */
-       unsigned long laddr;
-
-       __vmread(GUEST_LINEAR_ADDRESS, &laddr);
+       unsigned long addr, count = 1;
+       int sign = regs->eflags & EF_DF ? -1 : 1;
+
+       __vmread(GUEST_LINEAR_ADDRESS, &addr);
+
         /*
          * In protected mode, guest linear address is invalid if the
          * selector is null.
          */
-        if (!vm86 && check_for_null_selector(eip)) {
-            laddr = (p->dir == IOREQ_WRITE) ? regs->esi : regs->edi;
-        }
-        p->pdata_valid = 1;
-
-        p->u.data = laddr;
-        if (vmx_paging_enabled(d))
-                p->u.pdata = (void *) gva_to_gpa(p->u.data);
-        p->df = (eflags & X86_EFLAGS_DF) ? 1 : 0;
-
-        if (test_bit(5, &exit_qualification)) /* "rep" prefix */
-           p->count = vm86 ? regs->ecx & 0xFFFF : regs->ecx;
-
-        /*
-         * Split up string I/O operations that cross page boundaries. Don't
-         * advance %eip so that "rep insb" will restart at the next page.
-         */
-        if ((p->u.data & PAGE_MASK) != 
-               ((p->u.data + p->count * p->size - 1) & PAGE_MASK)) {
-           VMX_DBG_LOG(DBG_LEVEL_2,
-               "String I/O crosses page boundary (cs:eip=0x%lx:0x%lx)\n",
-               cs, eip);
-            if (p->u.data & (p->size - 1)) {
-               printf("Unaligned string I/O operation (cs:eip=0x%lx:0x%lx)\n",
-                       cs, eip);
-                domain_crash_synchronous();     
-            }
-            p->count = (PAGE_SIZE - (p->u.data & ~PAGE_MASK)) / p->size;
-        } else {
-            __update_guest_eip(inst_len);
-        }
-    } else if (p->dir == IOREQ_WRITE) {
-        p->u.data = regs->eax;
+        if (!vm86 && check_for_null_selector(eip))
+            addr = dir == IOREQ_WRITE ? regs->esi : regs->edi;
+
+        if (test_bit(5, &exit_qualification)) { /* "rep" prefix */
+           mpcip->flags |= REPZ;
+           count = vm86 ? regs->ecx & 0xFFFF : regs->ecx;
+       }
+
+       /*
+        * Handle string pio instructions that cross pages or that
+        * are unaligned. See the comments in vmx_platform.c/handle_mmio()
+        */
+       if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) {
+           unsigned long value = 0;
+
+           mpcip->flags |= OVERLAP;
+           if (dir == IOREQ_WRITE)
+               vmx_copy(&value, addr, size, VMX_COPY_IN);
+           send_pio_req(regs, port, 1, size, value, dir, 0);
+       } else {
+           if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) {
+                if (sign > 0)
+                    count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
+                else
+                    count = (addr & ~PAGE_MASK) / size;
+           } else
+               __update_guest_eip(inst_len);
+
+           send_pio_req(regs, port, count, size, addr, dir, 1);
+       }
+    } else {
         __update_guest_eip(inst_len);
-    } else
-        __update_guest_eip(inst_len);
-
-    p->addr = addr;
-    p->port_mm = 0;
-
-    /* Check if the packet needs to be intercepted */
-    if (vmx_portio_intercept(p))
-       /* no blocking & no evtchn notification */
-        return;
-
-    set_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags);
-    p->state = STATE_IOREQ_READY;
-    evtchn_send(iopacket_port(d->domain));
-    vmx_wait_io();
-}
-
-enum { COPY_IN = 0, COPY_OUT };
-
-static inline int
+       send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
+    }
+}
+
+int
 vmx_copy(void *buf, unsigned long laddr, int size, int dir)
 {
+    unsigned long gpa, mfn;
     char *addr;
-    unsigned long mfn;
-
-    if ( (size + (laddr & (PAGE_SIZE - 1))) >= PAGE_SIZE )
-    {
-       printf("vmx_copy exceeds page boundary\n");
-        return 0;
-    }
-
-    mfn = phys_to_machine_mapping(laddr >> PAGE_SHIFT);
-    addr = (char *)map_domain_page(mfn) + (laddr & ~PAGE_MASK);
-
-    if (dir == COPY_IN)
-           memcpy(buf, addr, size);
-    else
-           memcpy(addr, buf, size);
-
-    unmap_domain_page(addr);
+    int count;
+
+    while (size > 0) {
+       count = PAGE_SIZE - (laddr & ~PAGE_MASK);
+       if (count > size)
+           count = size;
+
+       if (vmx_paging_enabled(current)) {
+               gpa = gva_to_gpa(laddr);
+               mfn = get_mfn_from_pfn(gpa >> PAGE_SHIFT);
+       } else
+               mfn = get_mfn_from_pfn(laddr >> PAGE_SHIFT);
+       if (mfn == INVALID_MFN)
+               return 0;
+
+       addr = (char *)map_domain_page(mfn) + (laddr & ~PAGE_MASK);
+
+       if (dir == VMX_COPY_IN)
+           memcpy(buf, addr, count);
+       else
+           memcpy(addr, buf, count);
+
+       unmap_domain_page(addr);
+
+       laddr += count;
+       buf += count;
+       size -= count;
+    }
+
     return 1;
 }
 
@@ -712,7 +774,7 @@
     unsigned long inst_len;
     int error = 0;
 
-    error |= __vmread(INSTRUCTION_LEN, &inst_len);
+    error |= __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
     error |= __vmread(GUEST_RIP, &c->eip);
     c->eip += inst_len; /* skip transition instruction */
     error |= __vmread(GUEST_RSP, &c->esp);
@@ -795,7 +857,7 @@
         * removed some translation or changed page attributes.
         * We simply invalidate the shadow.
         */
-       mfn = phys_to_machine_mapping(c->cr3 >> PAGE_SHIFT);
+       mfn = get_mfn_from_pfn(c->cr3 >> PAGE_SHIFT);
        if (mfn != pagetable_get_pfn(d->arch.guest_table)) {
            printk("Invalid CR3 value=%x", c->cr3);
            domain_crash_synchronous();
@@ -813,7 +875,7 @@
            domain_crash_synchronous(); 
            return 0;
        }
-       mfn = phys_to_machine_mapping(c->cr3 >> PAGE_SHIFT);
+       mfn = get_mfn_from_pfn(c->cr3 >> PAGE_SHIFT);
        d->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
        update_pagetables(d);
        /* 
@@ -889,7 +951,7 @@
     u32 cp;
 
     /* make sure vmxassist exists (this is not an error) */
-    if (!vmx_copy(&magic, VMXASSIST_MAGIC_OFFSET, sizeof(magic), COPY_IN))
+    if (!vmx_copy(&magic, VMXASSIST_MAGIC_OFFSET, sizeof(magic), VMX_COPY_IN))
        return 0;
     if (magic != VMXASSIST_MAGIC)
        return 0;
@@ -903,20 +965,20 @@
      */
     case VMX_ASSIST_INVOKE:
        /* save the old context */
-       if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), COPY_IN))
+       if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), VMX_COPY_IN))
            goto error;
        if (cp != 0) {
            if (!vmx_world_save(d, &c))
                goto error;
-           if (!vmx_copy(&c, cp, sizeof(c), COPY_OUT))
+           if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_OUT))
                goto error;
        }
 
        /* restore the new context, this should activate vmxassist */
-       if (!vmx_copy(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp), COPY_IN))
+       if (!vmx_copy(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp), VMX_COPY_IN))
            goto error;
        if (cp != 0) {
-            if (!vmx_copy(&c, cp, sizeof(c), COPY_IN))
+            if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_IN))
                goto error;
            if (!vmx_world_restore(d, &c))
                goto error;
@@ -930,10 +992,10 @@
      */
     case VMX_ASSIST_RESTORE:
        /* save the old context */
-       if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), COPY_IN))
+       if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), VMX_COPY_IN))
            goto error;
        if (cp != 0) {
-            if (!vmx_copy(&c, cp, sizeof(c), COPY_IN))
+            if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_IN))
                goto error;
            if (!vmx_world_restore(d, &c))
                goto error;
@@ -968,7 +1030,7 @@
         /*
          * The guest CR3 must be pointing to the guest physical.
          */
-        if ( !VALID_MFN(mfn = phys_to_machine_mapping(
+        if ( !VALID_MFN(mfn = get_mfn_from_pfn(
                             d->arch.arch_vmx.cpu_cr3 >> PAGE_SHIFT)) ||
              !get_page(pfn_to_page(mfn), d->domain) )
         {
@@ -996,6 +1058,15 @@
 
 #if CONFIG_PAGING_LEVELS >= 4 
             if(!shadow_set_guest_paging_levels(d->domain, 4)) {
+                printk("Unsupported guest paging levels\n");
+                domain_crash_synchronous(); /* need to take a clean path */
+            }
+#endif
+        }
+        else
+        {
+#if CONFIG_PAGING_LEVELS >= 4
+            if(!shadow_set_guest_paging_levels(d->domain, 2)) {
                 printk("Unsupported guest paging levels\n");
                 domain_crash_synchronous(); /* need to take a clean path */
             }
@@ -1164,7 +1235,7 @@
              * removed some translation or changed page attributes.
              * We simply invalidate the shadow.
              */
-            mfn = phys_to_machine_mapping(value >> PAGE_SHIFT);
+            mfn = get_mfn_from_pfn(value >> PAGE_SHIFT);
             if (mfn != pagetable_get_pfn(d->arch.guest_table))
                 __vmx_bug(regs);
             shadow_sync_all(d->domain);
@@ -1175,7 +1246,7 @@
              */
             VMX_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
             if ( ((value >> PAGE_SHIFT) > d->domain->max_pages ) ||
-                 !VALID_MFN(mfn = phys_to_machine_mapping(value >> 
PAGE_SHIFT)) ||
+                 !VALID_MFN(mfn = get_mfn_from_pfn(value >> PAGE_SHIFT)) ||
                  !get_page(pfn_to_page(mfn), d->domain) )
             {
                 printk("Invalid CR3 value=%lx", value);
@@ -1282,13 +1353,20 @@
     case TYPE_MOV_TO_CR:
         gp = exit_qualification & CONTROL_REG_ACCESS_REG;
         cr = exit_qualification & CONTROL_REG_ACCESS_NUM;
+        TRACE_VMEXIT(1,TYPE_MOV_TO_CR);
+        TRACE_VMEXIT(2,cr);
+        TRACE_VMEXIT(3,gp);
         return mov_to_cr(gp, cr, regs);
     case TYPE_MOV_FROM_CR:
         gp = exit_qualification & CONTROL_REG_ACCESS_REG;
         cr = exit_qualification & CONTROL_REG_ACCESS_NUM;
+        TRACE_VMEXIT(1,TYPE_MOV_FROM_CR);
+        TRACE_VMEXIT(2,cr);
+        TRACE_VMEXIT(3,gp);
         mov_from_cr(cr, gp, regs);
         break;
     case TYPE_CLTS:
+        TRACE_VMEXIT(1,TYPE_CLTS);
         clts();
         setup_fpu(current);
 
@@ -1301,6 +1379,7 @@
         __vmwrite(CR0_READ_SHADOW, value);
         break;
     case TYPE_LMSW:
+        TRACE_VMEXIT(1,TYPE_LMSW);
         __vmread(CR0_READ_SHADOW, &value);
        value = (value & ~0xF) |
                (((exit_qualification & LMSW_SOURCE_DATA) >> 16) & 0xF);
@@ -1518,15 +1597,18 @@
 
     __vmread(IDT_VECTORING_INFO_FIELD, &idtv_info_field);
     if (idtv_info_field & INTR_INFO_VALID_MASK) {
-       if ((idtv_info_field & 0x0700) != 0x400) { /* exclude soft ints */
-            __vmwrite(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field);
-
-           if (idtv_info_field & 0x800) { /* valid error code */
-               unsigned long error_code;
-               __vmread(VM_EXIT_INTR_ERROR_CODE, &error_code);
-               __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
-           } 
-       }
+       __vmwrite(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field);
+
+       __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
+       if (inst_len >= 1 && inst_len <= 15) 
+           __vmwrite(VM_ENTRY_INSTRUCTION_LEN, inst_len);
+
+       if (idtv_info_field & 0x800) { /* valid error code */
+           unsigned long error_code;
+           __vmread(IDT_VECTORING_ERROR_CODE, &error_code);
+           __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
+       } 
+
         VMX_DBG_LOG(DBG_LEVEL_1, "idtv_info_field=%x", idtv_info_field);
     }
 
@@ -1544,6 +1626,7 @@
 
     __vmread(GUEST_RIP, &eip);
     TRACE_3D(TRC_VMX_VMEXIT, v->domain->domain_id, eip, exit_reason);
+    TRACE_VMEXIT(0,exit_reason);
 
     switch (exit_reason) {
     case EXIT_REASON_EXCEPTION_NMI:
@@ -1562,6 +1645,7 @@
             __vmx_bug(&regs);
         vector &= 0xff;
 
+        TRACE_VMEXIT(1,vector);
         perfc_incra(cause_vector, vector);
 
         TRACE_3D(TRC_VMX_VECTOR, v->domain->domain_id, eip, vector);
@@ -1606,6 +1690,10 @@
         {
             __vmread(EXIT_QUALIFICATION, &va);
             __vmread(VM_EXIT_INTR_ERROR_CODE, &regs.error_code);
+            
+           TRACE_VMEXIT(3,regs.error_code);
+           TRACE_VMEXIT(4,va);
+
             VMX_DBG_LOG(DBG_LEVEL_VMMU, 
                         "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
                         (unsigned long)regs.eax, (unsigned long)regs.ebx,
@@ -1680,6 +1768,8 @@
                 eip, inst_len, exit_qualification);
         if (vmx_cr_access(exit_qualification, &regs))
            __update_guest_eip(inst_len);
+        TRACE_VMEXIT(3,regs.error_code);
+        TRACE_VMEXIT(4,exit_qualification);
         break;
     }
     case EXIT_REASON_DR_ACCESS:
@@ -1692,6 +1782,7 @@
         __vmread(EXIT_QUALIFICATION, &exit_qualification);
         __get_instruction_length(inst_len);
         vmx_io_instruction(&regs, exit_qualification, inst_len);
+        TRACE_VMEXIT(4,exit_qualification);
         break;
     case EXIT_REASON_MSR_READ:
         __get_instruction_length(inst_len);
@@ -1726,6 +1817,25 @@
 #endif
 }
 
+#ifdef TRACE_BUFFER
+asmlinkage void trace_vmentry (void)
+{
+    TRACE_5D(TRC_VMENTRY,trace_values[current->processor][0],
+          
trace_values[current->processor][1],trace_values[current->processor][2],
+          
trace_values[current->processor][3],trace_values[current->processor][4]);
+    TRACE_VMEXIT(0,9);
+    TRACE_VMEXIT(1,9);
+    TRACE_VMEXIT(2,9);
+    TRACE_VMEXIT(3,9);
+    TRACE_VMEXIT(4,9);
+    return;
+}
+asmlinkage void trace_vmexit (void)
+{
+    TRACE_3D(TRC_VMEXIT,0,0,0);
+    return;
+}
+#endif 
 #endif /* CONFIG_VMX */
 
 /*
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/vmx_intercept.c
--- a/xen/arch/x86/vmx_intercept.c      Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/vmx_intercept.c      Fri Sep  9 16:30:54 2005
@@ -172,7 +172,7 @@
 
     if (p->size != 1 ||
         p->pdata_valid ||
-        p->port_mm)
+       p->type != IOREQ_TYPE_PIO)
         return 0;
     
     if (p->addr == PIT_MODE &&
@@ -284,7 +284,5 @@
         if (!reinit)
            register_portio_handler(0x40, 4, intercept_pit_io); 
     }
-
-}
-
+}
 #endif /* CONFIG_VMX */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/vmx_io.c
--- a/xen/arch/x86/vmx_io.c     Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/vmx_io.c     Fri Sep  9 16:30:54 2005
@@ -33,6 +33,7 @@
 #include <asm/vmx_platform.h>
 #include <asm/vmx_virpit.h>
 #include <asm/apic.h>
+#include <asm/shadow.h>
 
 #include <public/io/ioreq.h>
 #include <public/io/vmx_vlapic.h>
@@ -123,7 +124,6 @@
             regs->esp &= 0xFFFF0000;
             regs->esp |= (value & 0xFFFF);
             break;
-
         case 5:
             regs->ebp &= 0xFFFF0000;
             regs->ebp |= (value & 0xFFFF);
@@ -207,7 +207,6 @@
             *reg &= ~0xFFFF;
             *reg |= (value & 0xFFFF);
             break;
-
         case LONG:
             *reg &= ~0xFFFFFFFF;
             *reg |= (value & 0xFFFFFFFF);
@@ -322,13 +321,319 @@
 }
 #endif
 
+extern long get_reg_value(int size, int index, int seg, struct cpu_user_regs 
*regs);
+
+static inline void set_eflags_CF(int size, unsigned long v1,
+       unsigned long v2, struct cpu_user_regs *regs)
+{
+    unsigned long mask = (1 << (8 * size)) - 1;
+
+    if ((v1 & mask) > (v2 & mask))
+       regs->eflags |= X86_EFLAGS_CF;
+    else
+       regs->eflags &= ~X86_EFLAGS_CF;
+}
+
+static inline void set_eflags_OF(int size, unsigned long v1,
+       unsigned long v2, unsigned long v3, struct cpu_user_regs *regs)
+{
+    if ((v3 ^ v2) & (v3 ^ v1) & (1 << ((8 * size) - 1)))
+       regs->eflags |= X86_EFLAGS_OF;
+}
+
+static inline void set_eflags_AF(int size, unsigned long v1,
+       unsigned long v2, unsigned long v3, struct cpu_user_regs *regs)
+{
+    if ((v1 ^ v2 ^ v3) & 0x10)
+       regs->eflags |= X86_EFLAGS_AF;
+}
+
+static inline void set_eflags_ZF(int size, unsigned long v1,
+       struct cpu_user_regs *regs)
+{
+    unsigned long mask = (1 << (8 * size)) - 1;
+
+    if ((v1 & mask) == 0)
+       regs->eflags |= X86_EFLAGS_ZF;
+}
+
+static inline void set_eflags_SF(int size, unsigned long v1,
+       struct cpu_user_regs *regs)
+{
+    if (v1 & (1 << ((8 * size) - 1)))
+       regs->eflags |= X86_EFLAGS_SF;
+}
+
+static char parity_table[256] = {
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
+};
+
+static inline void set_eflags_PF(int size, unsigned long v1,
+       struct cpu_user_regs *regs)
+{
+    if (parity_table[v1 & 0xFF])
+       regs->eflags |= X86_EFLAGS_PF;
+}
+
+static void vmx_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
+                                       struct mi_per_cpu_info *mpcip)
+{
+    unsigned long old_eax;
+    int sign = p->df ? -1 : 1;
+
+    if (p->dir == IOREQ_WRITE) {
+        if (p->pdata_valid) {
+            regs->esi += sign * p->count * p->size;
+           if (mpcip->flags & REPZ)
+               regs->ecx -= p->count;
+        }
+    } else {
+       if (mpcip->flags & OVERLAP) {
+           unsigned long addr;
+
+            regs->edi += sign * p->count * p->size;
+           if (mpcip->flags & REPZ)
+               regs->ecx -= p->count;
+
+           addr = regs->edi;
+           if (sign > 0)
+               addr -= p->size;
+           vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT);
+       } else if (p->pdata_valid) {
+            regs->edi += sign * p->count * p->size;
+           if (mpcip->flags & REPZ)
+               regs->ecx -= p->count;
+        } else {
+           old_eax = regs->eax;
+           switch (p->size) {
+            case 1:
+                regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
+                break;
+            case 2:
+                regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
+                break;
+            case 4:
+                regs->eax = (p->u.data & 0xffffffff);
+                break;
+            default:
+               printk("Error: %s unknown port size\n", __FUNCTION__);
+               domain_crash_synchronous();
+           }
+       }
+    }
+}
+
+static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
+                                       struct mi_per_cpu_info *mpcip)
+{
+    int sign = p->df ? -1 : 1;
+    int size = -1, index = -1;
+    unsigned long value = 0, diff = 0;
+    unsigned long src, dst;
+
+    src = mpcip->operand[0];
+    dst = mpcip->operand[1];
+    size = operand_size(src);
+
+    switch (mpcip->instr) {
+    case INSTR_MOV:
+       if (dst & REGISTER) {
+           index = operand_index(dst);
+           set_reg_value(size, index, 0, regs, p->u.data);
+       }
+       break;
+
+    case INSTR_MOVZ:
+       if (dst & REGISTER) {
+           index = operand_index(dst);
+           switch (size) {
+           case BYTE: p->u.data = p->u.data & 0xFFULL; break;
+           case WORD: p->u.data = p->u.data & 0xFFFFULL; break;
+           case LONG: p->u.data = p->u.data & 0xFFFFFFFFULL; break;
+           }
+           set_reg_value(operand_size(dst), index, 0, regs, p->u.data);
+       }
+       break;
+
+    case INSTR_MOVS:
+       sign = p->df ? -1 : 1;
+       regs->esi += sign * p->count * p->size;
+       regs->edi += sign * p->count * p->size;
+
+       if ((mpcip->flags & OVERLAP) && p->dir == IOREQ_READ) {
+           unsigned long addr = regs->edi;
+
+           if (sign > 0)
+               addr -= p->size;
+           vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT);
+       }
+
+       if (mpcip->flags & REPZ)
+           regs->ecx -= p->count;
+       break;
+
+    case INSTR_STOS:
+       sign = p->df ? -1 : 1;
+       regs->edi += sign * p->count * p->size;
+       if (mpcip->flags & REPZ)
+           regs->ecx -= p->count;
+       break;
+
+    case INSTR_AND:
+       if (src & REGISTER) {
+           index = operand_index(src);
+           value = get_reg_value(size, index, 0, regs);
+           diff = (unsigned long) p->u.data & value;
+       } else if (src & IMMEDIATE) {
+           value = mpcip->immediate;
+           diff = (unsigned long) p->u.data & value;
+       } else if (src & MEMORY) {
+           index = operand_index(dst);
+           value = get_reg_value(size, index, 0, regs);
+           diff = (unsigned long) p->u.data & value;
+           set_reg_value(size, index, 0, regs, diff);
+       }
+
+       /*
+        * The OF and CF flags are cleared; the SF, ZF, and PF
+        * flags are set according to the result. The state of
+        * the AF flag is undefined.
+        */
+       regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
+                         X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
+       set_eflags_ZF(size, diff, regs);
+       set_eflags_SF(size, diff, regs);
+       set_eflags_PF(size, diff, regs);
+       break;
+
+    case INSTR_OR:
+       if (src & REGISTER) {
+           index = operand_index(src);
+           value = get_reg_value(size, index, 0, regs);
+           diff = (unsigned long) p->u.data | value;
+       } else if (src & IMMEDIATE) {
+           value = mpcip->immediate;
+           diff = (unsigned long) p->u.data | value;
+       } else if (src & MEMORY) {
+           index = operand_index(dst);
+           value = get_reg_value(size, index, 0, regs);
+           diff = (unsigned long) p->u.data | value;
+           set_reg_value(size, index, 0, regs, diff);
+       }
+
+       /*
+        * The OF and CF flags are cleared; the SF, ZF, and PF
+        * flags are set according to the result. The state of
+        * the AF flag is undefined.
+        */
+       regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
+                         X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
+       set_eflags_ZF(size, diff, regs);
+       set_eflags_SF(size, diff, regs);
+       set_eflags_PF(size, diff, regs);
+       break;
+
+    case INSTR_XOR:
+       if (src & REGISTER) {
+           index = operand_index(src);
+           value = get_reg_value(size, index, 0, regs);
+           diff = (unsigned long) p->u.data ^ value;
+       } else if (src & IMMEDIATE) {
+           value = mpcip->immediate;
+           diff = (unsigned long) p->u.data ^ value;
+       } else if (src & MEMORY) {
+           index = operand_index(dst);
+           value = get_reg_value(size, index, 0, regs);
+           diff = (unsigned long) p->u.data ^ value;
+           set_reg_value(size, index, 0, regs, diff);
+       }
+
+       /*
+        * The OF and CF flags are cleared; the SF, ZF, and PF
+        * flags are set according to the result. The state of
+        * the AF flag is undefined.
+        */
+       regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
+                         X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
+       set_eflags_ZF(size, diff, regs);
+       set_eflags_SF(size, diff, regs);
+       set_eflags_PF(size, diff, regs);
+       break;
+
+    case INSTR_CMP:
+       if (src & REGISTER) {
+           index = operand_index(src);
+           value = get_reg_value(size, index, 0, regs);
+           diff = (unsigned long) p->u.data - value;
+       } else if (src & IMMEDIATE) {
+           value = mpcip->immediate;
+           diff = (unsigned long) p->u.data - value;
+       } else if (src & MEMORY) {
+           index = operand_index(dst);
+           value = get_reg_value(size, index, 0, regs);
+           diff = value - (unsigned long) p->u.data;
+       }
+
+       /*
+        * The CF, OF, SF, ZF, AF, and PF flags are set according
+        * to the result
+        */
+       regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
+                         X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
+       set_eflags_CF(size, value, (unsigned long) p->u.data, regs);
+       set_eflags_OF(size, diff, value, (unsigned long) p->u.data, regs);
+       set_eflags_AF(size, diff, value, (unsigned long) p->u.data, regs);
+       set_eflags_ZF(size, diff, regs);
+       set_eflags_SF(size, diff, regs);
+       set_eflags_PF(size, diff, regs);
+       break;
+
+    case INSTR_TEST:
+       if (src & REGISTER) {
+           index = operand_index(src);
+           value = get_reg_value(size, index, 0, regs);
+       } else if (src & IMMEDIATE) {
+           value = mpcip->immediate;
+       } else if (src & MEMORY) {
+           index = operand_index(dst);
+           value = get_reg_value(size, index, 0, regs);
+       }
+       diff = (unsigned long) p->u.data & value;
+
+       /*
+        * Sets the SF, ZF, and PF status flags. CF and OF are set to 0
+        */
+       regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
+                         X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
+       set_eflags_ZF(size, diff, regs);
+       set_eflags_SF(size, diff, regs);
+       set_eflags_PF(size, diff, regs);
+       break;
+    }
+
+    load_cpu_user_regs(regs);
+}
+
 void vmx_io_assist(struct vcpu *v) 
 {
     vcpu_iodata_t *vio;
     ioreq_t *p;
     struct cpu_user_regs *regs = guest_cpu_user_regs();
-    unsigned long old_eax;
-    int sign;
     struct mi_per_cpu_info *mpci_p;
     struct cpu_user_regs *inst_decoder_regs;
 
@@ -340,80 +645,26 @@
     if (vio == 0) {
         VMX_DBG_LOG(DBG_LEVEL_1, 
                     "bad shared page: %lx", (unsigned long) vio);
+       printf("bad shared page: %lx\n", (unsigned long) vio);
         domain_crash_synchronous();
     }
+
     p = &vio->vp_ioreq;
-
-    if (p->state == STATE_IORESP_HOOK){
+    if (p->state == STATE_IORESP_HOOK)
         vmx_hooks_assist(v);
-    }
 
     /* clear IO wait VMX flag */
     if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
-        if (p->state != STATE_IORESP_READY) {
-                /* An interrupt send event raced us */
-                return;
-        } else {
-            p->state = STATE_INVALID;
-        }
-        clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
-    } else {
-        return;
-    }
-
-    sign = (p->df) ? -1 : 1;
-    if (p->port_mm) {
-        if (p->pdata_valid) {
-            regs->esi += sign * p->count * p->size;
-            regs->edi += sign * p->count * p->size;
-        } else {
-            if (p->dir == IOREQ_WRITE) {
-                return;
-            }
-            int size = -1, index = -1;
-
-            size = operand_size(v->domain->arch.vmx_platform.mpci.mmio_target);
-            index = 
operand_index(v->domain->arch.vmx_platform.mpci.mmio_target);
-
-            if (v->domain->arch.vmx_platform.mpci.mmio_target & WZEROEXTEND) {
-                p->u.data = p->u.data & 0xffff;
-            }        
-            set_reg_value(size, index, 0, regs, p->u.data);
-
-        }
-        load_cpu_user_regs(regs);
-        return;
-    }
-
-    if (p->dir == IOREQ_WRITE) {
-        if (p->pdata_valid) {
-            regs->esi += sign * p->count * p->size;
-            regs->ecx -= p->count;
-        }
-        return;
-    } else {
-        if (p->pdata_valid) {
-            regs->edi += sign * p->count * p->size;
-            regs->ecx -= p->count;
-            return;
-        }
-    }
-
-    old_eax = regs->eax;
-
-    switch(p->size) {
-    case 1:
-        regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
-        break;
-    case 2:
-        regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
-        break;
-    case 4:
-        regs->eax = (p->u.data & 0xffffffff);
-        break;
-    default:
-        printk("Error: %s unknwon port size\n", __FUNCTION__);
-        domain_crash_synchronous();
+        if (p->state == STATE_IORESP_READY) {
+           p->state = STATE_INVALID;
+            clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
+
+           if (p->type == IOREQ_TYPE_PIO)
+               vmx_pio_assist(regs, p, mpci_p);
+           else
+               vmx_mmio_assist(regs, p, mpci_p);
+       }
+       /* else an interrupt send event raced us */
     }
 }
 
@@ -456,8 +707,9 @@
     int port = iopacket_port(current->domain);
 
     do {
-        if(!test_bit(port, &current->domain->shared_info->evtchn_pending[0]))
+        if (!test_bit(port, &current->domain->shared_info->evtchn_pending[0]))
             do_block();
+
         vmx_check_events(current);
         if (!test_bit(ARCH_VMX_IO_WAIT, &current->arch.arch_vmx.flags))
             break;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/vmx_platform.c
--- a/xen/arch/x86/vmx_platform.c       Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/vmx_platform.c       Fri Sep  9 16:30:54 2005
@@ -64,37 +64,37 @@
         case QUAD:
             return (long)(reg);
         default:
-            printk("Error: <__get_reg_value>Invalid reg size\n");
+       printf("Error: (__get_reg_value) Invalid reg size\n");
             domain_crash_synchronous();
     }
 }
 
-static long get_reg_value(int size, int index, int seg, struct cpu_user_regs 
*regs) 
+long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs) 
 {
     if (size == BYTE) {
         switch (index) { 
-            case 0: //%al
+       case 0: /* %al */
                 return (char)(regs->rax & 0xFF);
-            case 1: //%cl  
+       case 1: /* %cl */
                 return (char)(regs->rcx & 0xFF);
-            case 2: //%dl
+       case 2: /* %dl */
                 return (char)(regs->rdx & 0xFF); 
-            case 3: //%bl
+       case 3: /* %bl */
                 return (char)(regs->rbx & 0xFF);
-            case 4: //%ah
+       case 4: /* %ah */
                 return (char)((regs->rax & 0xFF00) >> 8);
-            case 5: //%ch 
+       case 5: /* %ch */
                 return (char)((regs->rcx & 0xFF00) >> 8);
-            case 6: //%dh
+       case 6: /* %dh */
                 return (char)((regs->rdx & 0xFF00) >> 8);
-            case 7: //%bh
+       case 7: /* %bh */
                 return (char)((regs->rbx & 0xFF00) >> 8);
             default:
-                printk("Error: (get_reg_value)Invalid index value\n"); 
+           printf("Error: (get_reg_value) Invalid index value\n"); 
                 domain_crash_synchronous();
         }
-
-    }
+    }
+
     switch (index) {
         case 0: return __get_reg_value(regs->rax, size);
         case 1: return __get_reg_value(regs->rcx, size);
@@ -113,7 +113,7 @@
         case 14: return __get_reg_value(regs->r14, size);
         case 15: return __get_reg_value(regs->r15, size);
         default:
-            printk("Error: (get_reg_value)Invalid index value\n"); 
+       printf("Error: (get_reg_value) Invalid index value\n"); 
             domain_crash_synchronous();
     }
 }
@@ -129,117 +129,91 @@
     __vmread(GUEST_RIP, &regs->eip);
 }
 
-static long get_reg_value(int size, int index, int seg, struct cpu_user_regs 
*regs)
+static inline long __get_reg_value(unsigned long reg, int size)
 {                    
-    /*               
-     * Reference the db_reg[] table
-     */              
-    switch (size) {  
-    case BYTE: 
+    switch(size) {
+    case WORD:
+       return (short)(reg & 0xFFFF);
+    case LONG:
+       return (int)(reg & 0xFFFFFFFF);
+    default:
+       printf("Error: (__get_reg_value) Invalid reg size\n");
+       domain_crash_synchronous();
+    }
+}
+
+long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
+{                    
+    if (size == BYTE) {
         switch (index) { 
-        case 0: //%al
+       case 0: /* %al */
             return (char)(regs->eax & 0xFF);
-        case 1: //%cl  
+       case 1: /* %cl */
             return (char)(regs->ecx & 0xFF);
-        case 2: //%dl
+       case 2: /* %dl */
             return (char)(regs->edx & 0xFF); 
-        case 3: //%bl
+       case 3: /* %bl */
             return (char)(regs->ebx & 0xFF);
-        case 4: //%ah
+       case 4: /* %ah */
             return (char)((regs->eax & 0xFF00) >> 8);
-        case 5: //%ch 
+       case 5: /* %ch */
             return (char)((regs->ecx & 0xFF00) >> 8);
-        case 6: //%dh
+       case 6: /* %dh */
             return (char)((regs->edx & 0xFF00) >> 8);
-        case 7: //%bh
+       case 7: /* %bh */
             return (char)((regs->ebx & 0xFF00) >> 8);
         default:
-            printk("Error: (get_reg_value)size case 0 error\n"); 
+           printf("Error: (get_reg_value) Invalid index value\n"); 
             domain_crash_synchronous();
         }
-    case WORD:
+        }
+
         switch (index) {
-        case 0: //%ax
-            return (short)(regs->eax & 0xFFFF);
-        case 1: //%cx
-            return (short)(regs->ecx & 0xFFFF);
-        case 2: //%dx
-            return (short)(regs->edx & 0xFFFF);
-        case 3: //%bx
-            return (short)(regs->ebx & 0xFFFF);
-        case 4: //%sp
-            return (short)(regs->esp & 0xFFFF);
-            break;
-        case 5: //%bp
-            return (short)(regs->ebp & 0xFFFF);
-        case 6: //%si
-            return (short)(regs->esi & 0xFFFF);
-        case 7: //%di
-            return (short)(regs->edi & 0xFFFF);
-        default:
-            printk("Error: (get_reg_value)size case 1 error\n");
-            domain_crash_synchronous();
-        }
-    case LONG:
-        switch (index) {
-        case 0: //%eax
-            return regs->eax;
-        case 1: //%ecx
-            return regs->ecx;
-        case 2: //%edx
-            return regs->edx;
-
-        case 3: //%ebx
-            return regs->ebx;
-        case 4: //%esp
-            return regs->esp;
-        case 5: //%ebp
-            return regs->ebp;
-        case 6: //%esi
-            return regs->esi;
-        case 7: //%edi
-            return regs->edi;
-        default:
-            printk("Error: (get_reg_value)size case 2 error\n");
-            domain_crash_synchronous();
-        }
+    case 0: return __get_reg_value(regs->eax, size);
+    case 1: return __get_reg_value(regs->ecx, size);
+    case 2: return __get_reg_value(regs->edx, size);
+    case 3: return __get_reg_value(regs->ebx, size);
+    case 4: return __get_reg_value(regs->esp, size);
+    case 5: return __get_reg_value(regs->ebp, size);
+    case 6: return __get_reg_value(regs->esi, size);
+    case 7: return __get_reg_value(regs->edi, size);
     default:
-        printk("Error: (get_reg_value)size case error\n");
+       printf("Error: (get_reg_value) Invalid index value\n"); 
         domain_crash_synchronous();
     }
 }
 #endif
 
-static inline const unsigned char *check_prefix(const unsigned char *inst, 
struct instruction *thread_inst, unsigned char *rex_p)
+static inline unsigned char *check_prefix(unsigned char *inst,
+               struct instruction *thread_inst, unsigned char *rex_p)
 {
     while (1) {
         switch (*inst) {
-            /* rex prefix for em64t instructions*/
+        /* rex prefix for em64t instructions */
             case 0x40 ... 0x4e:
                 *rex_p = *inst;
                 break;
-
-            case 0xf3: //REPZ
+        case 0xf3: /* REPZ */
                thread_inst->flags = REPZ;
-                       break;
-            case 0xf2: //REPNZ
+               break;
+        case 0xf2: /* REPNZ */
                thread_inst->flags = REPNZ;
-                       break;
-            case 0xf0: //LOCK
+               break;
+        case 0xf0: /* LOCK */
                break;
-            case 0x2e: //CS
-            case 0x36: //SS
-            case 0x3e: //DS
-            case 0x26: //ES
-            case 0x64: //FS
-            case 0x65: //GS
-                       thread_inst->seg_sel = *inst;
+        case 0x2e: /* CS */
+        case 0x36: /* SS */
+        case 0x3e: /* DS */
+        case 0x26: /* ES */
+        case 0x64: /* FS */
+        case 0x65: /* GS */
+               thread_inst->seg_sel = *inst;
                 break;
-            case 0x66: //32bit->16bit
+        case 0x66: /* 32bit->16bit */
                 thread_inst->op_size = WORD;
                 break;
             case 0x67:
-                       printf("Error: Not handling 0x67 (yet)\n");
+               printf("Error: Not handling 0x67 (yet)\n");
                 domain_crash_synchronous();
                 break;
             default:
@@ -249,7 +223,7 @@
     }
 }
 
-static inline unsigned long get_immediate(int op16, const unsigned char *inst, 
int op_size)
+static inline unsigned long get_immediate(int op16,const unsigned char *inst, 
int op_size)
 {
     int mod, reg, rm;
     unsigned long val = 0;
@@ -317,275 +291,328 @@
 
 static void init_instruction(struct instruction *mmio_inst)
 {
-    memset(mmio_inst->i_name, '0', I_NAME_LEN);
-    mmio_inst->op_size =  0;
-    mmio_inst->offset = 0;
+    mmio_inst->instr = 0;
+    mmio_inst->op_size = 0;
     mmio_inst->immediate = 0;
     mmio_inst->seg_sel = 0;
-    mmio_inst->op_num = 0;
 
     mmio_inst->operand[0] = 0;
     mmio_inst->operand[1] = 0;
-    mmio_inst->operand[2] = 0;
         
     mmio_inst->flags = 0;
 }
 
 #define GET_OP_SIZE_FOR_BYTE(op_size)   \
-    do {if (rex) op_size = BYTE_64;else op_size = BYTE;} while(0)
+    do {                               \
+       if (rex)                        \
+           op_size = BYTE_64;          \
+       else                            \
+           op_size = BYTE;             \
+    } while(0)
 
 #define GET_OP_SIZE_FOR_NONEBYTE(op_size)   \
-    do {if (rex & 0x8) op_size = QUAD; else if (op_size != WORD) op_size = 
LONG;} while(0)
-
-static int vmx_decode(const unsigned char *inst, struct instruction 
*thread_inst)
+    do {                               \
+       if (rex & 0x8)                  \
+           op_size = QUAD;             \
+       else if (op_size != WORD)       \
+           op_size = LONG;             \
+    } while(0)
+
+
+/*
+ * Decode mem,accumulator operands (as in <opcode> m8/m16/m32, al,ax,eax)
+ */
+static int mem_acc(unsigned char size, struct instruction *instr)
+{
+    instr->operand[0] = mk_operand(size, 0, 0, MEMORY);
+    instr->operand[1] = mk_operand(size, 0, 0, REGISTER);
+    return DECODE_success;
+}
+
+/*
+ * Decode accumulator,mem operands (as in <opcode> al,ax,eax, m8/m16/m32)
+ */
+static int acc_mem(unsigned char size, struct instruction *instr)
+{
+    instr->operand[0] = mk_operand(size, 0, 0, REGISTER);
+    instr->operand[1] = mk_operand(size, 0, 0, MEMORY);
+    return DECODE_success;
+}
+
+/*
+ * Decode mem,reg operands (as in <opcode> r32/16, m32/16)
+ */
+static int mem_reg(unsigned char size, unsigned char *opcode,
+                       struct instruction *instr, unsigned char rex)
+{
+    int index = get_index(opcode + 1, rex);
+
+    instr->operand[0] = mk_operand(size, 0, 0, MEMORY);
+    instr->operand[1] = mk_operand(size, index, 0, REGISTER);
+    return DECODE_success;
+}
+
+/*
+ * Decode reg,mem operands (as in <opcode> m32/16, r32/16)
+ */
+static int reg_mem(unsigned char size, unsigned char *opcode,
+                       struct instruction *instr, unsigned char rex)
+{
+    int index = get_index(opcode + 1, rex);
+
+    instr->operand[0] = mk_operand(size, index, 0, REGISTER);
+    instr->operand[1] = mk_operand(size, 0, 0, MEMORY);
+    return DECODE_success;
+}
+
+static int vmx_decode(unsigned char *opcode, struct instruction *instr)
 {
     unsigned long eflags;
     int index, vm86 = 0;
     unsigned char rex = 0;
     unsigned char tmp_size = 0;
 
-
-    init_instruction(thread_inst);
-
-    inst = check_prefix(inst, thread_inst, &rex);
+    init_instruction(instr);
+
+    opcode = check_prefix(opcode, instr, &rex);
 
     __vmread(GUEST_RFLAGS, &eflags);
     if (eflags & X86_EFLAGS_VM)
         vm86 = 1;
 
     if (vm86) { /* meaning is reversed */
-       if (thread_inst->op_size == WORD)
-           thread_inst->op_size = LONG;
-       else if (thread_inst->op_size == LONG)
-           thread_inst->op_size = WORD;
-       else if (thread_inst->op_size == 0)
-           thread_inst->op_size = WORD;
-    }
-
-    switch(*inst) {
-        case 0x81:
-            /* This is only a workaround for cmpl instruction*/
-            strcpy((char *)thread_inst->i_name, "cmp");
+       if (instr->op_size == WORD)
+           instr->op_size = LONG;
+       else if (instr->op_size == LONG)
+           instr->op_size = WORD;
+       else if (instr->op_size == 0)
+           instr->op_size = WORD;
+    }
+
+    switch (*opcode) {
+    case 0x0B: /* or m32/16, r32/16 */
+       instr->instr = INSTR_OR;
+       GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+       return mem_reg(instr->op_size, opcode, instr, rex);
+
+    case 0x20: /* and r8, m8 */
+       instr->instr = INSTR_AND;
+       GET_OP_SIZE_FOR_BYTE(instr->op_size);
+       return reg_mem(instr->op_size, opcode, instr, rex);
+
+    case 0x21: /* and r32/16, m32/16 */
+       instr->instr = INSTR_AND;
+       GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+       return reg_mem(instr->op_size, opcode, instr, rex);
+
+    case 0x23: /* and m32/16, r32/16 */
+       instr->instr = INSTR_AND;
+       GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+       return mem_reg(instr->op_size, opcode, instr, rex);
+
+    case 0x30: /* xor r8, m8 */
+       instr->instr = INSTR_XOR;
+       GET_OP_SIZE_FOR_BYTE(instr->op_size);
+       return reg_mem(instr->op_size, opcode, instr, rex);
+
+    case 0x31: /* xor r32/16, m32/16 */
+       instr->instr = INSTR_XOR;
+       GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+       return reg_mem(instr->op_size, opcode, instr, rex);
+
+    case 0x39: /* cmp r32/16, m32/16 */
+       instr->instr = INSTR_CMP;
+       GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+       return reg_mem(instr->op_size, opcode, instr, rex);
+
+    case 0x81:
+       if (((opcode[1] >> 3) & 7) == 7) { /* cmp $imm, m32/16 */
+           instr->instr = INSTR_CMP;
+           GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+
+           instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
+           instr->immediate = get_immediate(vm86, opcode+1, BYTE);
+           instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
+
             return DECODE_success;
-
-        case 0x88:
-            /* mov r8 to m8 */
-            thread_inst->op_size = BYTE;
-            index = get_index((inst + 1), rex);
-            GET_OP_SIZE_FOR_BYTE(tmp_size);
-            thread_inst->operand[0] = mk_operand(tmp_size, index, 0, REGISTER);
-
-            break;
-        case 0x89:
-            /* mov r32/16 to m32/16 */
-            index = get_index((inst + 1), rex);
-            GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
-            thread_inst->operand[0] = mk_operand(thread_inst->op_size, index, 
0, REGISTER);
-
-            break;
-        case 0x8a:
-            /* mov m8 to r8 */
-            thread_inst->op_size = BYTE;
-            index = get_index((inst + 1), rex);
-            GET_OP_SIZE_FOR_BYTE(tmp_size);
-            thread_inst->operand[1] = mk_operand(tmp_size, index, 0, REGISTER);
-            break;
-        case 0x8b:
-            /* mov r32/16 to m32/16 */
-            index = get_index((inst + 1), rex);
-            GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
-            thread_inst->operand[1] = mk_operand(thread_inst->op_size, index, 
0, REGISTER);
-            break;
-        case 0x8c:
-        case 0x8e:
-            printk("%x, This opcode hasn't been handled yet!", *inst);
-            return DECODE_failure;
-            /* Not handle it yet. */
-        case 0xa0:
-            /* mov byte to al */
-            thread_inst->op_size = BYTE;
-            GET_OP_SIZE_FOR_BYTE(tmp_size);
-            thread_inst->operand[1] = mk_operand(tmp_size, 0, 0, REGISTER);
-            break;
-        case 0xa1:
-            /* mov word/doubleword to ax/eax */
-           GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
-           thread_inst->operand[1] = mk_operand(thread_inst->op_size, 0, 0, 
REGISTER);
-
-            break;
-        case 0xa2:
-            /* mov al to (seg:offset) */
-            thread_inst->op_size = BYTE;
-            GET_OP_SIZE_FOR_BYTE(tmp_size);
-            thread_inst->operand[0] = mk_operand(tmp_size, 0, 0, REGISTER);
-            break;
-        case 0xa3:
-            /* mov ax/eax to (seg:offset) */
-            GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
-            thread_inst->operand[0] = mk_operand(thread_inst->op_size, 0, 0, 
REGISTER);
-            break;
-        case 0xa4:
-            /* movsb */
-            thread_inst->op_size = BYTE;
-            strcpy((char *)thread_inst->i_name, "movs");
-            return DECODE_success;
-        case 0xa5:
-            /* movsw/movsl */
-            GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
-           strcpy((char *)thread_inst->i_name, "movs");
-            return DECODE_success;
-        case 0xaa:
-            /* stosb */
-            thread_inst->op_size = BYTE;
-            strcpy((char *)thread_inst->i_name, "stosb");
-            return DECODE_success;
-       case 0xab:
-            /* stosw/stosl */
-            if (thread_inst->op_size == WORD) {
-                strcpy((char *)thread_inst->i_name, "stosw");
-            } else {
-                thread_inst->op_size = LONG;
-                strcpy((char *)thread_inst->i_name, "stosl");
-            }
-            return DECODE_success;
-        case 0xc6:
-            /* mov imm8 to m8 */
-            thread_inst->op_size = BYTE;
-            thread_inst->operand[0] = mk_operand(BYTE, 0, 0, IMMEDIATE);
-            thread_inst->immediate = get_immediate(vm86,
-                                       (inst+1), thread_inst->op_size);
-            break;
-        case 0xc7:
-            /* mov imm16/32 to m16/32 */
-            GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
-            thread_inst->operand[0] = mk_operand(thread_inst->op_size, 0, 0, 
IMMEDIATE);
-            thread_inst->immediate = get_immediate(vm86, (inst+1), 
thread_inst->op_size);
+       } else
+           return DECODE_failure;
+
+    case 0x84:  /* test m8, r8 */
+       instr->instr = INSTR_TEST;
+       instr->op_size = BYTE;
+       GET_OP_SIZE_FOR_BYTE(tmp_size);
+       return mem_reg(tmp_size, opcode, instr, rex);
+
+    case 0x88: /* mov r8, m8 */
+       instr->instr = INSTR_MOV;
+       instr->op_size = BYTE;
+        GET_OP_SIZE_FOR_BYTE(tmp_size);
+       return reg_mem(tmp_size, opcode, instr, rex);
+
+    case 0x89: /* mov r32/16, m32/16 */
+       instr->instr = INSTR_MOV;
+       GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+       return reg_mem(instr->op_size, opcode, instr, rex);
+
+    case 0x8A: /* mov m8, r8 */
+       instr->instr = INSTR_MOV;
+       instr->op_size = BYTE;
+        GET_OP_SIZE_FOR_BYTE(tmp_size);
+       return mem_reg(tmp_size, opcode, instr, rex);
+
+    case 0x8B: /* mov m32/16, r32/16 */
+       instr->instr = INSTR_MOV;
+       GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+       return mem_reg(instr->op_size, opcode, instr, rex);
+
+    case 0xA0: /* mov <addr>, al */
+       instr->instr = INSTR_MOV;
+       instr->op_size = BYTE;
+        GET_OP_SIZE_FOR_BYTE(tmp_size);
+       return mem_acc(tmp_size, instr);
+
+    case 0xA1: /* mov <addr>, ax/eax */
+       instr->instr = INSTR_MOV;
+       GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+       return mem_acc(instr->op_size, instr);
+
+    case 0xA2: /* mov al, <addr> */
+       instr->instr = INSTR_MOV;
+       instr->op_size = BYTE;
+        GET_OP_SIZE_FOR_BYTE(tmp_size);
+       return acc_mem(tmp_size, instr);
+
+    case 0xA3: /* mov ax/eax, <addr> */
+       instr->instr = INSTR_MOV;
+       GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+       return acc_mem(instr->op_size, instr);
+
+    case 0xA4: /* movsb */
+       instr->instr = INSTR_MOVS;
+       instr->op_size = BYTE;
+        return DECODE_success;
             
-            break;
-        case 0x0f:
-            break;
-        default:
-            printk("%x, This opcode hasn't been handled yet!", *inst);
-            return DECODE_failure;
-    }
+    case 0xA5: /* movsw/movsl */
+       instr->instr = INSTR_MOVS;
+       GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+       return DECODE_success;
     
-    strcpy((char *)thread_inst->i_name, "mov");
-    if (*inst != 0x0f) {
+    case 0xAA: /* stosb */
+       instr->instr = INSTR_STOS;
+       instr->op_size = BYTE;
         return DECODE_success;
-    }
-
-    inst++;
-    switch (*inst) {
+
+    case 0xAB: /* stosw/stosl */
+       instr->instr = INSTR_STOS;
+       GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+       return DECODE_success;
                     
-        /* movz */
-        case 0xb6:
-            index = get_index((inst + 1), rex);
-            GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
-            thread_inst->operand[1] = mk_operand(thread_inst->op_size, index, 
0, REGISTER);
-            thread_inst->op_size = BYTE;
-            strcpy((char *)thread_inst->i_name, "movzb");
+    case 0xC6:
+       if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm8, m8 */
+           instr->instr = INSTR_MOV;
+           instr->op_size = BYTE;
+
+           instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
+           instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
+           instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
             
             return DECODE_success;
-        case 0xb7:
-           index = get_index((inst + 1), rex);
-           if (rex & 0x8) {
-                   thread_inst->op_size = LONG;
-                   thread_inst->operand[1] = mk_operand(QUAD, index, 0, 
REGISTER);
-           } else {
-                   thread_inst->op_size = WORD;
-                   thread_inst->operand[1] = mk_operand(LONG, index, 0, 
REGISTER);
-           }
+       } else
+           return DECODE_failure;
             
-            strcpy((char *)thread_inst->i_name, "movzw");
+    case 0xC7:
+       if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm16/32, m16/32 */
+           instr->instr = INSTR_MOV;
+           GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+
+           instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
+           instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
+           instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
             
             return DECODE_success;
-        default:
-            printk("0f %x, This opcode hasn't been handled yet!", *inst);
-            return DECODE_failure;
-    }
-
-    /* will never reach here */
-    return DECODE_failure;
+       } else
+           return DECODE_failure;
+
+    case 0xF6:
+       if (((opcode[1] >> 3) & 7) == 0) { /* testb $imm8, m8 */
+           instr->instr = INSTR_TEST;
+           instr->op_size = BYTE;
+
+           instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
+           instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
+           instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
+
+           return DECODE_success;
+       } else
+           return DECODE_failure;
+
+    case 0x0F:
+       break;
+
+    default:
+       printf("%x, This opcode isn't handled yet!\n", *opcode);
+        return DECODE_failure;
+    }
+
+    switch (*++opcode) {
+    case 0xB6: /* movz m8, r16/r32 */
+       instr->instr = INSTR_MOVZ;
+       GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+       index = get_index(opcode + 1, rex);
+       instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
+       instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
+       return DECODE_success;
+
+    case 0xB7: /* movz m16, r32 */
+       instr->instr = INSTR_MOVZ;
+       index = get_index(opcode + 1, rex);
+       if (rex & 0x8) {
+          instr->op_size = LONG;
+          instr->operand[1] = mk_operand(QUAD, index, 0, REGISTER);
+       } else {
+          instr->op_size = WORD;
+          instr->operand[1] = mk_operand(LONG, index, 0, REGISTER);
+       }
+       instr->operand[0] = mk_operand(instr->op_size, 0, 0, MEMORY);
+       return DECODE_success;
+
+    default:
+       printf("0f %x, This opcode isn't handled yet\n", *opcode);
+       return DECODE_failure;
+    }
 }
 
 int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, int 
inst_len)
 {
-    unsigned long gpa;
-    unsigned long mfn;
-    unsigned char *inst_start;
-    int remaining = 0;
-        
-    if ( (inst_len > MAX_INST_LEN) || (inst_len <= 0) )
+    if (inst_len > MAX_INST_LEN || inst_len <= 0)
         return 0;
-
-    if ( vmx_paging_enabled(current) )
-    {
-        gpa = gva_to_gpa(guest_eip);
-        mfn = phys_to_machine_mapping(gpa >> PAGE_SHIFT);
-
-        /* Does this cross a page boundary ? */
-        if ( (guest_eip & PAGE_MASK) != ((guest_eip + inst_len) & PAGE_MASK) )
-        {
-            remaining = (guest_eip + inst_len) & ~PAGE_MASK;
-            inst_len -= remaining;
-        }
-    }
-    else
-    {
-        mfn = phys_to_machine_mapping(guest_eip >> PAGE_SHIFT);
-    }
-
-    inst_start = map_domain_page(mfn);
-    memcpy((char *)buf, inst_start + (guest_eip & ~PAGE_MASK), inst_len);
-    unmap_domain_page(inst_start);
-
-    if ( remaining )
-    {
-        gpa = gva_to_gpa(guest_eip+inst_len+remaining);
-        mfn = phys_to_machine_mapping(gpa >> PAGE_SHIFT);
-
-        inst_start = map_domain_page(mfn);
-        memcpy((char *)buf+inst_len, inst_start, remaining);
-        unmap_domain_page(inst_start);
-    }
-
-    return inst_len+remaining;
-}
-
-static int read_from_mmio(struct instruction *inst_p)
-{
-    // Only for mov instruction now!!!
-    if (inst_p->operand[1] & REGISTER)
-        return 1;
-
-    return 0;
-}
-
-// dir:  1 read from mmio
-//       0 write to mmio
-static void send_mmio_req(unsigned long gpa, 
-                   struct instruction *inst_p, long value, int dir, int pvalid)
+    if (!vmx_copy(buf, guest_eip, inst_len, VMX_COPY_IN))
+        return 0;
+    return inst_len;
+}
+
+void send_mmio_req(unsigned char type, unsigned long gpa, 
+          unsigned long count, int size, long value, int dir, int pvalid)
 {
     struct vcpu *d = current;
     vcpu_iodata_t *vio;
     ioreq_t *p;
     int vm86;
-    struct mi_per_cpu_info *mpci_p;
-    struct cpu_user_regs *inst_decoder_regs;
+    struct cpu_user_regs *regs;
     extern long evtchn_send(int lport);
 
-    mpci_p = &current->domain->arch.vmx_platform.mpci;
-    inst_decoder_regs = mpci_p->inst_decoder_regs;
+    regs = current->domain->arch.vmx_platform.mpci.inst_decoder_regs;
 
     vio = get_vio(d->domain, d->vcpu_id);
-
     if (vio == NULL) {
-        printk("bad shared page\n");
+        printf("bad shared page\n");
         domain_crash_synchronous(); 
     }
+
     p = &vio->vp_ioreq;
 
-    vm86 = inst_decoder_regs->eflags & X86_EFLAGS_VM;
+    vm86 = regs->eflags & X86_EFLAGS_VM;
 
     if (test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags)) {
         printf("VMX I/O has not yet completed\n");
@@ -596,24 +623,21 @@
     p->dir = dir;
     p->pdata_valid = pvalid;
 
-    p->port_mm = 1;
-    p->size = inst_p->op_size;
+    p->type = type;
+    p->size = size;
     p->addr = gpa;
-    p->u.data = value;
+    p->count = count;
+    p->df = regs->eflags & EF_DF ? 1 : 0;
+
+    if (pvalid) {
+       if (vmx_paging_enabled(current))
+           p->u.pdata = (void *) gva_to_gpa(value);
+        else
+           p->u.pdata = (void *) value; /* guest VA == guest PA */
+    } else
+       p->u.data = value;
 
     p->state = STATE_IOREQ_READY;
-
-    if (inst_p->flags & REPZ) {
-        if (vm86)
-            p->count = inst_decoder_regs->ecx & 0xFFFF;
-        else
-            p->count = inst_decoder_regs->ecx;
-        p->df = (inst_decoder_regs->eflags & EF_DF) ? 1 : 0;
-    } else
-        p->count = 1;
-
-    if ((pvalid) && vmx_paging_enabled(current))
-        p->u.pdata = (void *) gva_to_gpa(p->u.data);
 
     if (vmx_mmio_intercept(p)){
         p->state = STATE_IORESP_READY;
@@ -625,21 +649,53 @@
     vmx_wait_io();
 }
 
+static void mmio_operands(int type, unsigned long gpa, struct instruction 
*inst,
+               struct mi_per_cpu_info *mpcip, struct cpu_user_regs *regs)
+{
+    unsigned long value = 0;
+    int index, size;
+    
+    size = operand_size(inst->operand[0]);
+
+    mpcip->flags = inst->flags;
+    mpcip->instr = inst->instr;
+    mpcip->operand[0] = inst->operand[0]; /* source */
+    mpcip->operand[1] = inst->operand[1]; /* destination */
+
+    if (inst->operand[0] & REGISTER) { /* dest is memory */
+       index = operand_index(inst->operand[0]);
+       value = get_reg_value(size, index, 0, regs);
+       send_mmio_req(type, gpa, 1, size, value, IOREQ_WRITE, 0);
+    } else if (inst->operand[0] & IMMEDIATE) { /* dest is memory */
+       value = inst->immediate;
+       send_mmio_req(type, gpa, 1, size, value, IOREQ_WRITE, 0);
+    } else if (inst->operand[0] & MEMORY) { /* dest is register */
+       /* send the request and wait for the value */
+       send_mmio_req(type, gpa, 1, size, 0, IOREQ_READ, 0);
+    } else {
+       printf("mmio_operands: invalid operand\n");
+       domain_crash_synchronous();
+    }
+}
+
+#define GET_REPEAT_COUNT() \
+     (mmio_inst.flags & REPZ ? (vm86 ? regs->ecx & 0xFFFF : regs->ecx) : 1)
+       
 void handle_mmio(unsigned long va, unsigned long gpa)
 {
     unsigned long eip, eflags, cs;
     unsigned long inst_len, inst_addr;
-    struct mi_per_cpu_info *mpci_p;
-    struct cpu_user_regs *inst_decoder_regs;
+    struct mi_per_cpu_info *mpcip;
+    struct cpu_user_regs *regs;
     struct instruction mmio_inst;
     unsigned char inst[MAX_INST_LEN];
-    int vm86, ret;
+    int i, vm86, ret;
      
-    mpci_p = &current->domain->arch.vmx_platform.mpci;
-    inst_decoder_regs = mpci_p->inst_decoder_regs;
+    mpcip = &current->domain->arch.vmx_platform.mpci;
+    regs = mpcip->inst_decoder_regs;
 
     __vmread(GUEST_RIP, &eip);
-    __vmread(INSTRUCTION_LEN, &inst_len);
+    __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
     __vmread(GUEST_RFLAGS, &eflags);
     vm86 = eflags & X86_EFLAGS_VM;
 
@@ -647,108 +703,142 @@
         __vmread(GUEST_CS_SELECTOR, &cs);
         inst_addr = (cs << 4) + eip;
     } else
-        inst_addr = eip; /* XXX should really look at GDT[cs].base too */
-
-    memset(inst, '0', MAX_INST_LEN);
+        inst_addr = eip;
+
+    memset(inst, 0, MAX_INST_LEN);
     ret = inst_copy_from_guest(inst, inst_addr, inst_len);
     if (ret != inst_len) {
-        printk("handle_mmio - EXIT: get guest instruction fault\n");
+        printf("handle_mmio - EXIT: get guest instruction fault\n");
         domain_crash_synchronous();
     }
-
 
     init_instruction(&mmio_inst);
     
     if (vmx_decode(inst, &mmio_inst) == DECODE_failure) {
-        printk("vmx decode failure: eip=%lx, va=%lx\n %x %x %x %x\n", eip, va, 
-               inst[0], inst[1], inst[2], inst[3]);
+       printf("mmio opcode: va 0x%lx, gpa 0x%lx, len %ld:",
+               va, gpa, inst_len);
+       for (i = 0; i < inst_len; i++)
+           printf(" %02x", inst[i] & 0xFF);
+       printf("\n");
         domain_crash_synchronous();
     }
 
-    __vmwrite(GUEST_RIP, eip + inst_len);
-    store_cpu_user_regs(inst_decoder_regs);
-
-    // Only handle "mov" and "movs" instructions!
-    if (!strncmp((char *)mmio_inst.i_name, "movz", 4)) {
-        if (read_from_mmio(&mmio_inst)) {
-            // Send the request and waiting for return value.
-            mpci_p->mmio_target = mmio_inst.operand[1] | WZEROEXTEND;
-            send_mmio_req(gpa, &mmio_inst, 0, IOREQ_READ, 0);
-            return ;
-        } else {
-            printk("handle_mmio - EXIT: movz error!\n");
-            domain_crash_synchronous();
-        }
-    }
-
-    if (!strncmp((char *)mmio_inst.i_name, "movs", 4)) {
+    store_cpu_user_regs(regs);
+    regs->eip += inst_len; /* advance %eip */
+
+    switch (mmio_inst.instr) {
+    case INSTR_MOV:
+       mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
+       break;
+
+    case INSTR_MOVS:
+    {
+       unsigned long count = GET_REPEAT_COUNT();
+       unsigned long size = mmio_inst.op_size;
+       int sign = regs->eflags & EF_DF ? -1 : 1;
        unsigned long addr = 0;
        int dir;
 
+       /* determine non-MMIO address */
        if (vm86) {
            unsigned long seg;
 
            __vmread(GUEST_ES_SELECTOR, &seg);
-           if (((seg << 4) + (inst_decoder_regs->edi & 0xFFFF)) == va) {
+           if (((seg << 4) + (regs->edi & 0xFFFF)) == va) {
                dir = IOREQ_WRITE;
                __vmread(GUEST_DS_SELECTOR, &seg);
-               addr = (seg << 4) + (inst_decoder_regs->esi & 0xFFFF);
+               addr = (seg << 4) + (regs->esi & 0xFFFF);
            } else {
                dir = IOREQ_READ;
-               addr = (seg << 4) + (inst_decoder_regs->edi & 0xFFFF);
+               addr = (seg << 4) + (regs->edi & 0xFFFF);
            }
-       } else { /* XXX should really look at GDT[ds/es].base too */
-           if (va == inst_decoder_regs->edi) {
+       } else {
+           if (va == regs->edi) {
                dir = IOREQ_WRITE;
-               addr = inst_decoder_regs->esi;
+               addr = regs->esi;
            } else {
                dir = IOREQ_READ;
-               addr = inst_decoder_regs->edi;
+               addr = regs->edi;
            }
        }
 
-       send_mmio_req(gpa, &mmio_inst, addr, dir, 1);
-        return;
-    }
-
-    if (!strncmp((char *)mmio_inst.i_name, "mov", 3)) {
-        long value = 0;
-        int size, index;
-
-        if (read_from_mmio(&mmio_inst)) {
-            // Send the request and waiting for return value.
-            mpci_p->mmio_target = mmio_inst.operand[1];
-            send_mmio_req(gpa, &mmio_inst, value, IOREQ_READ, 0);
-            return;
-        } else {
-            // Write to MMIO
-            if (mmio_inst.operand[0] & IMMEDIATE) {
-                value = mmio_inst.immediate;
-            } else if (mmio_inst.operand[0] & REGISTER) {
-                size = operand_size(mmio_inst.operand[0]);
-                index = operand_index(mmio_inst.operand[0]);
-                value = get_reg_value(size, index, 0, inst_decoder_regs);
-            } else {
-                domain_crash_synchronous();
-            }
-            send_mmio_req(gpa, &mmio_inst, value, IOREQ_WRITE, 0);
-            return;
-        }
-    }
-
-    if (!strncmp((char *)mmio_inst.i_name, "stos", 4)) {
-        send_mmio_req(gpa, &mmio_inst,
-            inst_decoder_regs->eax, IOREQ_WRITE, 0);
-        return;
-    }
-    /* Workaround for cmp instruction */
-    if (!strncmp((char *)mmio_inst.i_name, "cmp", 3)) {
-        inst_decoder_regs->eflags &= ~X86_EFLAGS_ZF;
-        __vmwrite(GUEST_RFLAGS, inst_decoder_regs->eflags);
-        return;
-    }
-
-    domain_crash_synchronous();
+       mpcip->flags = mmio_inst.flags;
+       mpcip->instr = mmio_inst.instr;
+
+       /*
+        * In case of a movs spanning multiple pages, we break the accesses
+        * up into multiple pages (the device model works with non-continguous
+        * physical guest pages). To copy just one page, we adjust %ecx and
+        * do not advance %eip so that the next "rep movs" copies the next page.
+        * Unaligned accesses, for example movsl starting at PGSZ-2, are
+        * turned into a single copy where we handle the overlapping memory
+        * copy ourself. After this copy succeeds, "rep movs" is executed
+        * again.
+        */
+       if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) {
+           unsigned long value = 0;
+
+           mpcip->flags |= OVERLAP;
+
+           regs->eip -= inst_len; /* do not advance %eip */
+
+           if (dir == IOREQ_WRITE)
+               vmx_copy(&value, addr, size, VMX_COPY_IN);
+           send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, size, value, dir, 0);
+       } else {
+           if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) {
+               regs->eip -= inst_len; /* do not advance %eip */
+
+               if (sign > 0)
+                   count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
+               else
+                   count = (addr & ~PAGE_MASK) / size;
+           }
+
+           send_mmio_req(IOREQ_TYPE_COPY, gpa, count, size, addr, dir, 1);
+       }
+        break;
+    }
+
+    case INSTR_MOVZ:
+       mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
+       break;
+
+    case INSTR_STOS:
+       /*
+        * Since the destination is always in (contiguous) mmio space we don't
+        * need to break it up into pages.
+        */
+       mpcip->flags = mmio_inst.flags;
+       mpcip->instr = mmio_inst.instr;
+        send_mmio_req(IOREQ_TYPE_COPY, gpa,
+           GET_REPEAT_COUNT(), mmio_inst.op_size, regs->eax, IOREQ_WRITE, 0);
+       break;
+
+    case INSTR_OR:
+       mmio_operands(IOREQ_TYPE_OR, gpa, &mmio_inst, mpcip, regs);
+       break;
+
+    case INSTR_AND:
+       mmio_operands(IOREQ_TYPE_AND, gpa, &mmio_inst, mpcip, regs);
+       break;
+
+    case INSTR_XOR:
+       mmio_operands(IOREQ_TYPE_XOR, gpa, &mmio_inst, mpcip, regs);
+       break;
+
+    case INSTR_CMP:
+       mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
+       break;
+
+    case INSTR_TEST:
+       mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
+       break;
+
+    default:
+       printf("Unhandled MMIO instruction\n");
+       domain_crash_synchronous();
+    }
 }
 
 #endif /* CONFIG_VMX */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/vmx_vmcs.c
--- a/xen/arch/x86/vmx_vmcs.c   Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/vmx_vmcs.c   Fri Sep  9 16:30:54 2005
@@ -44,7 +44,7 @@
 
     rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high);
     vmcs_size = vmx_msr_high & 0x1fff;
-    vmcs = alloc_xenheap_pages(get_order(vmcs_size)); 
+    vmcs = alloc_xenheap_pages(get_order_from_bytes(vmcs_size)); 
     memset((char *)vmcs, 0, vmcs_size); /* don't remove this */
 
     vmcs->vmcs_revision_id = vmx_msr_low;
@@ -55,7 +55,7 @@
 {
     int order;
 
-    order = get_order(vmcs_size);
+    order = get_order_from_bytes(vmcs_size);
     free_xenheap_pages(vmcs, order);
 }
 
@@ -76,8 +76,8 @@
     error |= __vmwrite(VM_ENTRY_CONTROLS, MONITOR_VM_ENTRY_CONTROLS);
 
     /* need to use 0x1000 instead of PAGE_SIZE */
-    io_bitmap_a = (void*) alloc_xenheap_pages(get_order(0x1000)); 
-    io_bitmap_b = (void*) alloc_xenheap_pages(get_order(0x1000)); 
+    io_bitmap_a = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000)); 
+    io_bitmap_b = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000)); 
     memset(io_bitmap_a, 0xff, 0x1000);
     /* don't bother debug port access */
     clear_bit(PC_DEBUG_PORT, io_bitmap_a);
@@ -148,7 +148,7 @@
     offset = (addr & ~PAGE_MASK);
     addr = round_pgdown(addr);
 
-    mpfn = phys_to_machine_mapping(addr >> PAGE_SHIFT);
+    mpfn = get_mfn_from_pfn(addr >> PAGE_SHIFT);
     p = map_domain_page(mpfn);
 
     e820p = (struct e820entry *) ((unsigned long) p + offset); 
@@ -175,7 +175,7 @@
     unmap_domain_page(p);        
 
     /* Initialise shared page */
-    mpfn = phys_to_machine_mapping(gpfn);
+    mpfn = get_mfn_from_pfn(gpfn);
     p = map_domain_page(mpfn);
     d->domain->arch.vmx_platform.shared_page_va = (unsigned long)p;
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_32/asm-offsets.c
--- a/xen/arch/x86/x86_32/asm-offsets.c Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/x86_32/asm-offsets.c Fri Sep  9 16:30:54 2005
@@ -71,6 +71,9 @@
     OFFSET(VCPUINFO_upcall_mask, vcpu_info_t, evtchn_upcall_mask);
     BLANK();
 
+    DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
+    BLANK();
+
     OFFSET(TRAPBOUNCE_error_code, struct trap_bounce, error_code);
     OFFSET(TRAPBOUNCE_cr2, struct trap_bounce, cr2);
     OFFSET(TRAPBOUNCE_flags, struct trap_bounce, flags);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S       Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/x86_32/entry.S       Fri Sep  9 16:30:54 2005
@@ -61,6 +61,11 @@
 #include <asm/page.h>
 #include <public/xen.h>
 
+#define GET_GUEST_REGS(reg)                     \
+        movl $~(STACK_SIZE-1),reg;              \
+        andl %esp,reg;                          \
+        orl  $(STACK_SIZE-CPUINFO_sizeof),reg;
+
 #define GET_CURRENT(reg)         \
         movl $STACK_SIZE-4, reg; \
         orl  %esp, reg;          \
@@ -121,6 +126,9 @@
 ENTRY(vmx_asm_vmexit_handler)
         /* selectors are restored/saved by VMX */
         VMX_SAVE_ALL_NOSEGREGS
+#ifdef TRACE_BUFFER
+        call trace_vmexit
+#endif
         call vmx_vmexit_handler
         jmp vmx_asm_do_resume
 
@@ -142,6 +150,9 @@
 /* vmx_restore_all_guest */
         call vmx_intr_assist
         call load_cr2
+#ifdef TRACE_BUFFER
+        call trace_vmentry
+#endif
         .endif
         VMX_RESTORE_ALL_NOSEGREGS
         /* 
@@ -273,7 +284,41 @@
         GET_CURRENT(%ebx)
         andl $(NR_hypercalls-1),%eax
         PERFC_INCR(PERFC_hypercalls, %eax)
+#ifndef NDEBUG
+        /* Deliberately corrupt parameter regs not used by this hypercall. */
+        pushl %eax
+        pushl UREGS_eip+4(%esp)
+        pushl 28(%esp) # EBP
+        pushl 28(%esp) # EDI
+        pushl 28(%esp) # ESI
+        pushl 28(%esp) # EDX
+        pushl 28(%esp) # ECX
+        pushl 28(%esp) # EBX
+        movzb hypercall_args_table(,%eax,1),%ecx
+        leal  (%esp,%ecx,4),%edi
+        subl  $6,%ecx
+        negl  %ecx
+        movl  %eax,%esi
+        movl  $0xDEADBEEF,%eax
+        rep   stosl
+        movl  %esi,%eax
+#endif
         call *hypercall_table(,%eax,4)
+#ifndef NDEBUG
+        /* Deliberately corrupt parameter regs used by this hypercall. */
+        addl  $24,%esp     # Shadow parameters
+        popl  %ecx         # Shadow EIP
+        cmpl  %ecx,UREGS_eip(%esp)
+        popl  %ecx         # Shadow hypercall index
+        jne   skip_clobber # If EIP has changed then don't clobber
+        movzb hypercall_args_table(,%ecx,1),%ecx
+        movl  %esp,%edi
+        movl  %eax,%esi
+        movl  $0xDEADBEEF,%eax
+        rep   stosl
+        movl  %esi,%eax
+skip_clobber:
+#endif
         movl %eax,UREGS_eax(%esp)       # save the return value
 
 test_all_events:
@@ -674,12 +719,14 @@
 do_arch_sched_op:
         # Ensure we return success even if we return via schedule_tail()
         xorl %eax,%eax
-        movl %eax,UREGS_eax+4(%esp)
+        GET_GUEST_REGS(%ecx)
+        movl %eax,UREGS_eax(%ecx)
         jmp  do_sched_op
 
 do_switch_vm86:
-        # Discard the return address
-        addl $4,%esp
+        # Reset the stack pointer
+        GET_GUEST_REGS(%ecx)
+        movl %ecx,%esp
 
         # GS:ESI == Ring-1 stack activation
         movl UREGS_esp(%esp),%esi
@@ -749,7 +796,7 @@
         .long do_get_debugreg
         .long do_update_descriptor  /* 10 */
         .long do_ni_hypercall
-        .long do_dom_mem_op
+        .long do_memory_op
         .long do_multicall
         .long do_update_va_mapping
         .long do_set_timer_op       /* 15 */
@@ -768,3 +815,36 @@
         .rept NR_hypercalls-((.-hypercall_table)/4)
         .long do_ni_hypercall
         .endr
+
+ENTRY(hypercall_args_table)
+        .byte 1 /* do_set_trap_table    */  /*  0 */
+        .byte 4 /* do_mmu_update        */
+        .byte 2 /* do_set_gdt           */
+        .byte 2 /* do_stack_switch      */
+        .byte 4 /* do_set_callbacks     */
+        .byte 1 /* do_fpu_taskswitch    */  /*  5 */
+        .byte 2 /* do_arch_sched_op     */
+        .byte 1 /* do_dom0_op           */
+        .byte 2 /* do_set_debugreg      */
+        .byte 1 /* do_get_debugreg      */
+        .byte 4 /* do_update_descriptor */  /* 10 */
+        .byte 0 /* do_ni_hypercall      */
+        .byte 2 /* do_memory_op         */
+        .byte 2 /* do_multicall         */
+        .byte 4 /* do_update_va_mapping */
+        .byte 2 /* do_set_timer_op      */  /* 15 */
+        .byte 1 /* do_event_channel_op  */
+        .byte 1 /* do_xen_version       */
+        .byte 3 /* do_console_io        */
+        .byte 1 /* do_physdev_op        */
+        .byte 3 /* do_grant_table_op    */  /* 20 */
+        .byte 2 /* do_vm_assist         */
+        .byte 5 /* do_update_va_mapping_otherdomain */
+        .byte 0 /* do_switch_vm86       */
+        .byte 2 /* do_boot_vcpu         */
+        .byte 0 /* do_ni_hypercall      */  /* 25 */
+        .byte 4 /* do_mmuext_op         */
+        .byte 1 /* do_acm_op            */
+        .rept NR_hypercalls-(.-hypercall_args_table)
+        .byte 0 /* do_ni_hypercall      */
+        .endr
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_32/mm.c
--- a/xen/arch/x86/x86_32/mm.c  Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/x86_32/mm.c  Fri Sep  9 16:30:54 2005
@@ -95,7 +95,7 @@
      * Allocate and map the machine-to-phys table and create read-only mapping 
      * of MPT for guest-OS use.
      */
-    mpt_size  = (max_page * 4) + (1UL << L2_PAGETABLE_SHIFT) - 1UL;
+    mpt_size  = (max_page * BYTES_PER_LONG) + (1UL << L2_PAGETABLE_SHIFT) - 1;
     mpt_size &= ~((1UL << L2_PAGETABLE_SHIFT) - 1UL);
     for ( i = 0; i < (mpt_size >> L2_PAGETABLE_SHIFT); i++ )
     {
@@ -118,7 +118,8 @@
     }
 
     /* Set up mapping cache for domain pages. */
-    mapcache_order = get_order(MAPCACHE_MBYTES << (20 - PAGETABLE_ORDER));
+    mapcache_order = get_order_from_bytes(
+        MAPCACHE_MBYTES << (20 - PAGETABLE_ORDER));
     mapcache = alloc_xenheap_pages(mapcache_order);
     memset(mapcache, 0, PAGE_SIZE << mapcache_order);
     for ( i = 0; i < (MAPCACHE_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ )
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_32/traps.c
--- a/xen/arch/x86/x86_32/traps.c       Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/x86_32/traps.c       Fri Sep  9 16:30:54 2005
@@ -79,11 +79,8 @@
            "ss: %04lx   cs: %04lx\n",
            ds, es, fs, gs, ss, cs);
 
-    if ( GUEST_MODE(regs) )
-        show_guest_stack();
-    else
-        show_stack((unsigned long *)&regs->esp);
-} 
+    show_stack(regs);
+}
 
 void show_page_walk(unsigned long addr)
 {
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_64/asm-offsets.c
--- a/xen/arch/x86/x86_64/asm-offsets.c Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/x86_64/asm-offsets.c Fri Sep  9 16:30:54 2005
@@ -71,6 +71,9 @@
     OFFSET(VCPUINFO_upcall_mask, vcpu_info_t, evtchn_upcall_mask);
     BLANK();
 
+    DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
+    BLANK();
+
     OFFSET(TRAPBOUNCE_error_code, struct trap_bounce, error_code);
     OFFSET(TRAPBOUNCE_cr2, struct trap_bounce, cr2);
     OFFSET(TRAPBOUNCE_flags, struct trap_bounce, flags);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S       Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/x86_64/entry.S       Fri Sep  9 16:30:54 2005
@@ -11,6 +11,11 @@
 #include <asm/apicdef.h>
 #include <asm/page.h>
 #include <public/xen.h>
+
+#define GET_GUEST_REGS(reg)                     \
+        movq $~(STACK_SIZE-1),reg;              \
+        andq %rsp,reg;                          \
+        orq  $(STACK_SIZE-CPUINFO_sizeof),reg;
 
 #define GET_CURRENT(reg)         \
         movq $STACK_SIZE-8, reg; \
@@ -120,10 +125,42 @@
 /*hypercall:*/
         movq  %r10,%rcx
         andq  $(NR_hypercalls-1),%rax
+#ifndef NDEBUG
+        /* Deliberately corrupt parameter regs not used by this hypercall. */
+        pushq %rdi; pushq %rsi; pushq %rdx; pushq %rcx; pushq %r8 ; pushq %r9 
+        leaq  hypercall_args_table(%rip),%r10
+        movq  $6,%rcx
+        sub   (%r10,%rax,1),%cl
+        movq  %rsp,%rdi
+        movl  $0xDEADBEEF,%eax
+        rep   stosq
+        popq  %r9 ; popq  %r8 ; popq  %rcx; popq  %rdx; popq  %rsi; popq  %rdi
+        movq  UREGS_rax(%rsp),%rax
+        andq  $(NR_hypercalls-1),%rax
+        pushq %rax
+        pushq UREGS_rip+8(%rsp)
+#endif
         leaq  hypercall_table(%rip),%r10
         PERFC_INCR(PERFC_hypercalls, %rax)
         callq *(%r10,%rax,8)
-        movq %rax,UREGS_rax(%rsp)       # save the return value
+#ifndef NDEBUG
+        /* Deliberately corrupt parameter regs used by this hypercall. */
+        popq  %r10         # Shadow RIP
+        cmpq  %r10,UREGS_rip(%rsp)
+        popq  %rcx         # Shadow hypercall index
+        jne   skip_clobber /* If RIP has changed then don't clobber. */
+        leaq  hypercall_args_table(%rip),%r10
+        movb  (%r10,%rcx,1),%cl
+        movl  $0xDEADBEEF,%r10d
+        cmpb  $1,%cl; jb skip_clobber; movq %r10,UREGS_rdi(%rsp)
+        cmpb  $2,%cl; jb skip_clobber; movq %r10,UREGS_rsi(%rsp)
+        cmpb  $3,%cl; jb skip_clobber; movq %r10,UREGS_rdx(%rsp)
+        cmpb  $4,%cl; jb skip_clobber; movq %r10,UREGS_r10(%rsp)
+        cmpb  $5,%cl; jb skip_clobber; movq %r10,UREGS_r8(%rsp)
+        cmpb  $6,%cl; jb skip_clobber; movq %r10,UREGS_r9(%rsp)
+skip_clobber:
+#endif
+        movq  %rax,UREGS_rax(%rsp)       # save the return value
 
 /* %rbx: struct vcpu */
 test_all_events:
@@ -302,7 +339,8 @@
 1:      /* In kernel context already: push new frame at existing %rsp. */
         movq  UREGS_rsp+8(%rsp),%rsi
         andb  $0xfc,UREGS_cs+8(%rsp)    # Indicate kernel context to guest.
-2:      movq  $HYPERVISOR_VIRT_START,%rax
+2:      andq  $~0xf,%rsi                # Stack frames are 16-byte aligned.
+        movq  $HYPERVISOR_VIRT_START,%rax
         cmpq  %rax,%rsi
         jb    1f                        # In +ve address space? Then okay.
         movq  $HYPERVISOR_VIRT_END+60,%rax
@@ -538,7 +576,8 @@
 do_arch_sched_op:
         # Ensure we return success even if we return via schedule_tail()
         xorl  %eax,%eax
-        movq  %rax,UREGS_rax+8(%rsp)
+        GET_GUEST_REGS(%r10)
+        movq  %rax,UREGS_rax(%r10)
         jmp   do_sched_op
 
 .data
@@ -578,7 +617,7 @@
         .quad do_get_debugreg
         .quad do_update_descriptor  /* 10 */
         .quad do_ni_hypercall
-        .quad do_dom_mem_op
+        .quad do_memory_op
         .quad do_multicall
         .quad do_update_va_mapping
         .quad do_set_timer_op       /* 15 */
@@ -597,3 +636,36 @@
         .rept NR_hypercalls-((.-hypercall_table)/4)
         .quad do_ni_hypercall
         .endr
+
+ENTRY(hypercall_args_table)
+        .byte 1 /* do_set_trap_table    */  /*  0 */
+        .byte 4 /* do_mmu_update        */
+        .byte 2 /* do_set_gdt           */
+        .byte 2 /* do_stack_switch      */
+        .byte 3 /* do_set_callbacks     */
+        .byte 1 /* do_fpu_taskswitch    */  /*  5 */
+        .byte 2 /* do_arch_sched_op     */
+        .byte 1 /* do_dom0_op           */
+        .byte 2 /* do_set_debugreg      */
+        .byte 1 /* do_get_debugreg      */
+        .byte 2 /* do_update_descriptor */  /* 10 */
+        .byte 0 /* do_ni_hypercall      */
+        .byte 2 /* do_memory_op         */
+        .byte 2 /* do_multicall         */
+        .byte 3 /* do_update_va_mapping */
+        .byte 1 /* do_set_timer_op      */  /* 15 */
+        .byte 1 /* do_event_channel_op  */
+        .byte 1 /* do_xen_version       */
+        .byte 3 /* do_console_io        */
+        .byte 1 /* do_physdev_op        */
+        .byte 3 /* do_grant_table_op    */  /* 20 */
+        .byte 2 /* do_vm_assist         */
+        .byte 4 /* do_update_va_mapping_otherdomain */
+        .byte 0 /* do_switch_to_user    */
+        .byte 2 /* do_boot_vcpu         */
+        .byte 2 /* do_set_segment_base  */  /* 25 */
+        .byte 4 /* do_mmuext_op         */
+        .byte 1 /* do_acm_op            */
+        .rept NR_hypercalls-(.-hypercall_args_table)
+        .byte 0 /* do_ni_hypercall      */
+        .endr
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c  Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/x86_64/mm.c  Fri Sep  9 16:30:54 2005
@@ -98,7 +98,7 @@
      * Allocate and map the machine-to-phys table.
      * This also ensures L3 is present for fixmaps.
      */
-    mpt_size  = (max_page * 4) + (1UL << L2_PAGETABLE_SHIFT) - 1UL;
+    mpt_size  = (max_page * BYTES_PER_LONG) + (1UL << L2_PAGETABLE_SHIFT) - 1;
     mpt_size &= ~((1UL << L2_PAGETABLE_SHIFT) - 1UL);
     for ( i = 0; i < (mpt_size >> L2_PAGETABLE_SHIFT); i++ )
     {
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_64/traps.c
--- a/xen/arch/x86/x86_64/traps.c       Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/x86_64/traps.c       Fri Sep  9 16:30:54 2005
@@ -15,24 +15,24 @@
 
 void show_registers(struct cpu_user_regs *regs)
 {
-    printk("CPU:    %d\nEIP:    %04x:[<%016lx>]",
+    printk("CPU:    %d\nRIP:    %04x:[<%016lx>]",
            smp_processor_id(), 0xffff & regs->cs, regs->rip);
     if ( !GUEST_MODE(regs) )
         print_symbol(" %s", regs->rip);
-    printk("\nEFLAGS: %016lx\n", regs->eflags);
-    printk("rax: %016lx   rbx: %016lx   rcx: %016lx   rdx: %016lx\n",
-           regs->rax, regs->rbx, regs->rcx, regs->rdx);
-    printk("rsi: %016lx   rdi: %016lx   rbp: %016lx   rsp: %016lx\n",
-           regs->rsi, regs->rdi, regs->rbp, regs->rsp);
-    printk("r8:  %016lx   r9:  %016lx   r10: %016lx   r11: %016lx\n",
-           regs->r8,  regs->r9,  regs->r10, regs->r11);
-    printk("r12: %016lx   r13: %016lx   r14: %016lx   r15: %016lx\n",
-           regs->r12, regs->r13, regs->r14, regs->r15);
+    printk("\nRFLAGS: %016lx\n", regs->eflags);
+    printk("rax: %016lx   rbx: %016lx   rcx: %016lx\n",
+           regs->rax, regs->rbx, regs->rcx);
+    printk("rdx: %016lx   rsi: %016lx   rdi: %016lx\n",
+           regs->rdx, regs->rsi, regs->rdi);
+    printk("rbp: %016lx   rsp: %016lx   r8:  %016lx\n",
+           regs->rbp, regs->rsp, regs->r8);
+    printk("r9:  %016lx   r10: %016lx   r11: %016lx\n",
+           regs->r9,  regs->r10, regs->r11);
+    printk("r12: %016lx   r13: %016lx   r14: %016lx\n",
+           regs->r12, regs->r13, regs->r14);
+    printk("r15: %016lx\n", regs->r15);
 
-    if ( GUEST_MODE(regs) )
-        show_guest_stack();
-    else
-        show_stack((unsigned long *)regs->rsp);
+    show_stack(regs);
 }
 
 void show_page_walk(unsigned long addr)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/Makefile
--- a/xen/common/Makefile       Thu Sep  8 15:18:40 2005
+++ b/xen/common/Makefile       Fri Sep  9 16:30:54 2005
@@ -2,7 +2,6 @@
 include $(BASEDIR)/Rules.mk
 
 ifeq ($(TARGET_ARCH),ia64)
-#OBJS := $(subst dom_mem_ops.o,,$(OBJS))
 OBJS := $(subst grant_table.o,,$(OBJS))
 endif
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/acm_ops.c
--- a/xen/common/acm_ops.c      Thu Sep  8 15:18:40 2005
+++ b/xen/common/acm_ops.c      Fri Sep  9 16:30:54 2005
@@ -19,6 +19,7 @@
 #include <xen/types.h>
 #include <xen/lib.h>
 #include <xen/mm.h>
+#include <public/acm.h>
 #include <public/acm_ops.h>
 #include <xen/sched.h>
 #include <xen/event.h>
@@ -41,7 +42,8 @@
     POLICY,                     /* access to policy interface (early drop) */
     GETPOLICY,                  /* dump policy cache */
     SETPOLICY,                  /* set policy cache (controls security) */
-    DUMPSTATS                   /* dump policy statistics */
+    DUMPSTATS,                  /* dump policy statistics */
+    GETSSID                     /* retrieve ssidref for domain id */
 } acm_operation_t;
 
 int acm_authorize_acm_ops(struct domain *d, acm_operation_t pops)
@@ -117,6 +119,35 @@
         }
         break;
 
+    case ACM_GETSSID:
+        {
+                       ssidref_t ssidref;
+
+            if (acm_authorize_acm_ops(current->domain, GETSSID))
+                return -EACCES;
+
+                       if (op->u.getssid.get_ssid_by == SSIDREF)
+                               ssidref = op->u.getssid.id.ssidref;
+                       else if (op->u.getssid.get_ssid_by == DOMAINID) {
+                               struct domain *subj = 
find_domain_by_id(op->u.getssid.id.domainid);
+                               if (!subj)
+                                       return -ESRCH; /* domain not found */
+
+                               ssidref = ((struct acm_ssid_domain 
*)(subj->ssid))->ssidref;
+                               put_domain(subj);
+                       } else
+                               return -ESRCH;
+
+            ret = acm_get_ssid(ssidref,
+                               op->u.getssid.ssidbuf,
+                               op->u.getssid.ssidbuf_size);
+            if (ret == ACM_OK)
+                ret = 0;
+            else
+                ret = -ESRCH;
+        }
+        break;
+
     default:
         ret = -ESRCH;
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/domain.c
--- a/xen/common/domain.c       Thu Sep  8 15:18:40 2005
+++ b/xen/common/domain.c       Fri Sep  9 16:30:54 2005
@@ -114,6 +114,8 @@
             sched_rem_domain(v);
         domain_relinquish_resources(d);
         put_domain(d);
+
+        send_guest_virq(dom0->vcpu[0], VIRQ_DOM_EXC);
     }
 }
 
@@ -174,7 +176,7 @@
 void domain_shutdown(u8 reason)
 {
     struct domain *d = current->domain;
-    struct vcpu *v;
+    struct vcpu   *v;
 
     if ( d->domain_id == 0 )
     {
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/event_channel.c
--- a/xen/common/event_channel.c        Thu Sep  8 15:18:40 2005
+++ b/xen/common/event_channel.c        Fri Sep  9 16:30:54 2005
@@ -250,6 +250,9 @@
 
     if ( virq >= ARRAY_SIZE(v->virq_to_evtchn) )
         return -EINVAL;
+
+    if ( d->domain_id == 0 && virq >= VIRQ_CONSOLE )
+        v = d->vcpu[0];
 
     spin_lock(&d->evtchn_lock);
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/grant_table.c
--- a/xen/common/grant_table.c  Thu Sep  8 15:18:40 2005
+++ b/xen/common/grant_table.c  Fri Sep  9 16:30:54 2005
@@ -399,7 +399,7 @@
     {
         int              i;
         grant_mapping_t *new_mt;
-        grant_table_t   *lgt      = ld->grant_table;
+        grant_table_t   *lgt = ld->grant_table;
 
         if ( (lgt->maptrack_limit << 1) > MAPTRACK_MAX_ENTRIES )
         {
@@ -437,9 +437,8 @@
             ref, dom, dev_hst_ro_flags);
 #endif
 
-    if ( 0 <= ( rc = __gnttab_activate_grant_ref( ld, led, rd, ref,
-                                                  dev_hst_ro_flags,
-                                                  addr, &frame)))
+    if ( (rc = __gnttab_activate_grant_ref(ld, led, rd, ref, dev_hst_ro_flags,
+                                           addr, &frame)) >= 0 )
     {
         /*
          * Only make the maptrack live _after_ writing the pte, in case we 
@@ -807,7 +806,8 @@
     int i;
     int result = GNTST_okay;
 
-    for (i = 0; i < count; i++) {
+    for ( i = 0; i < count; i++ )
+    {
         gnttab_donate_t *gop = &uop[i];
 #if GRANT_DEBUG
         printk("gnttab_donate: i=%d mfn=%lx domid=%d gref=%08x\n",
@@ -815,19 +815,24 @@
 #endif
         page = &frame_table[gop->mfn];
         
-        if (unlikely(IS_XEN_HEAP_FRAME(page))) { 
+        if ( unlikely(IS_XEN_HEAP_FRAME(page)))
+        { 
             printk("gnttab_donate: xen heap frame mfn=%lx\n", 
                    (unsigned long) gop->mfn);
             gop->status = GNTST_bad_virt_addr;
             continue;
         }
-        if (unlikely(!pfn_valid(page_to_pfn(page)))) {
+        
+        if ( unlikely(!pfn_valid(page_to_pfn(page))) )
+        {
             printk("gnttab_donate: invalid pfn for mfn=%lx\n", 
                    (unsigned long) gop->mfn);
             gop->status = GNTST_bad_virt_addr;
             continue;
         }
-        if (unlikely((e = find_domain_by_id(gop->domid)) == NULL)) {
+
+        if ( unlikely((e = find_domain_by_id(gop->domid)) == NULL) )
+        {
             printk("gnttab_donate: can't find domain %d\n", gop->domid);
             gop->status = GNTST_bad_domain;
             continue;
@@ -881,47 +886,23 @@
          * headroom.  Also, a domain mustn't have PGC_allocated
          * pages when it is dying.
          */
-#ifdef GRANT_DEBUG
-        if (unlikely(e->tot_pages >= e->max_pages)) {
-            printk("gnttab_dontate: no headroom tot_pages=%d max_pages=%d\n",
-                   e->tot_pages, e->max_pages);
+        if ( unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags)) ||
+             unlikely(e->tot_pages >= e->max_pages) ||
+             unlikely(!gnttab_prepare_for_transfer(e, d, gop->handle)) )
+        {
+            DPRINTK("gnttab_donate: Transferee has no reservation headroom "
+                    "(%d,%d) or provided a bad grant ref (%08x) or "
+                    "is dying (%lx)\n",
+                    e->tot_pages, e->max_pages, gop->handle, e->domain_flags);
             spin_unlock(&e->page_alloc_lock);
             put_domain(e);
-            result = GNTST_general_error;
+            gop->status = result = GNTST_general_error;
             break;
         }
-        if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags))) {
-            printk("gnttab_donate: target domain is dying\n");
-            spin_unlock(&e->page_alloc_lock);
-            put_domain(e);
-            result = GNTST_general_error;
-            break;
-        }
-        if (unlikely(!gnttab_prepare_for_transfer(e, d, gop->handle))) {
-            printk("gnttab_donate: gnttab_prepare_for_transfer fails\n");
-            spin_unlock(&e->page_alloc_lock);
-            put_domain(e);
-            result = GNTST_general_error;
-            break;
-        }
-#else
-        ASSERT(e->tot_pages <= e->max_pages);
-        if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags)) ||
-            unlikely(e->tot_pages == e->max_pages) ||
-            unlikely(!gnttab_prepare_for_transfer(e, d, gop->handle))) {
-            printk("gnttab_donate: Transferee has no reservation headroom (%d,"
-                   "%d) or provided a bad grant ref (%08x) or is dying (%p)\n",
-                   e->tot_pages, e->max_pages, gop->handle, e->d_flags);
-            spin_unlock(&e->page_alloc_lock);
-            put_domain(e);
-            result = GNTST_general_error;
-            break;
-        }
-#endif
+
         /* Okay, add the page to 'e'. */
-        if (unlikely(e->tot_pages++ == 0)) {
+        if ( unlikely(e->tot_pages++ == 0) )
             get_knownalive_domain(e);
-        }
         list_add_tail(&page->list, &e->page_list);
         page_set_owner(page, e);
         
@@ -937,6 +918,7 @@
         
         gop->status = GNTST_okay;
     }
+
     return result;
 }
 
@@ -956,38 +938,38 @@
     
     rc = -EFAULT;
     switch ( cmd )
-        {
-        case GNTTABOP_map_grant_ref:
-            if ( unlikely(!array_access_ok(
-                              uop, count, sizeof(gnttab_map_grant_ref_t))) )
-                goto out;
-            rc = gnttab_map_grant_ref((gnttab_map_grant_ref_t *)uop, count);
-            break;
-        case GNTTABOP_unmap_grant_ref:
-            if ( unlikely(!array_access_ok(
-                              uop, count, sizeof(gnttab_unmap_grant_ref_t))) )
-                goto out;
-            rc = gnttab_unmap_grant_ref((gnttab_unmap_grant_ref_t *)uop, 
-                                        count);
-            break;
-        case GNTTABOP_setup_table:
-            rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count);
-            break;
+    {
+    case GNTTABOP_map_grant_ref:
+        if ( unlikely(!array_access_ok(
+            uop, count, sizeof(gnttab_map_grant_ref_t))) )
+            goto out;
+        rc = gnttab_map_grant_ref((gnttab_map_grant_ref_t *)uop, count);
+        break;
+    case GNTTABOP_unmap_grant_ref:
+        if ( unlikely(!array_access_ok(
+            uop, count, sizeof(gnttab_unmap_grant_ref_t))) )
+            goto out;
+        rc = gnttab_unmap_grant_ref(
+            (gnttab_unmap_grant_ref_t *)uop, count);
+        break;
+    case GNTTABOP_setup_table:
+        rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count);
+        break;
 #if GRANT_DEBUG
-        case GNTTABOP_dump_table:
-            rc = gnttab_dump_table((gnttab_dump_table_t *)uop);
-            break;
+    case GNTTABOP_dump_table:
+        rc = gnttab_dump_table((gnttab_dump_table_t *)uop);
+        break;
 #endif
-        case GNTTABOP_donate:
-            if (unlikely(!array_access_ok(uop, count, 
-                                          sizeof(gnttab_donate_t))))
-                goto out;
-            rc = gnttab_donate(uop, count);
-            break;
-        default:
-            rc = -ENOSYS;
-            break;
-        }
+    case GNTTABOP_donate:
+        if (unlikely(!array_access_ok(
+            uop, count, sizeof(gnttab_donate_t))))
+            goto out;
+        rc = gnttab_donate(uop, count);
+        break;
+    default:
+        rc = -ENOSYS;
+        break;
+    }
     
   out:
     UNLOCK_BIGLOCK(d);
@@ -1020,17 +1002,17 @@
     lgt = ld->grant_table;
     
 #if GRANT_DEBUG_VERBOSE
-    if ( ld->domain_ id != 0 ) {
-            DPRINTK("Foreign unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n",
-                    rd->domain_id, ld->domain_id, frame, readonly);
-      }
+    if ( ld->domain_id != 0 )
+        DPRINTK("Foreign unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n",
+                rd->domain_id, ld->domain_id, frame, readonly);
 #endif
     
     /* Fast exit if we're not mapping anything using grant tables */
     if ( lgt->map_count == 0 )
         return 0;
     
-    if ( get_domain(rd) == 0 ) {
+    if ( get_domain(rd) == 0 )
+    {
         DPRINTK("gnttab_check_unmap: couldn't get_domain rd(%d)\n",
                 rd->domain_id);
         return 0;
@@ -1211,13 +1193,13 @@
         DPRINTK("Bad pfn (%lx)\n", pfn);
     else
     {
-        machine_to_phys_mapping[frame] = pfn;
+        set_pfn_from_mfn(frame, pfn);
 
         if ( unlikely(shadow_mode_log_dirty(ld)))
              mark_dirty(ld, frame);
 
         if (shadow_mode_translate(ld))
-            __phys_to_machine_mapping[pfn] = frame;
+            set_mfn_from_pfn(pfn, frame);
     }
     sha->frame = __mfn_to_gpfn(rd, frame);
     sha->domid = rd->domain_id;
@@ -1267,9 +1249,11 @@
     for ( i = 0; i < NR_GRANT_FRAMES; i++ )
     {
         SHARE_PFN_WITH_DOMAIN(
-            virt_to_page((char *)(t->shared)+(i*PAGE_SIZE)), d);
-        machine_to_phys_mapping[(virt_to_phys(t->shared) >> PAGE_SHIFT) + i] =
-            INVALID_M2P_ENTRY;
+            virt_to_page((char *)t->shared + (i * PAGE_SIZE)),
+            d);
+        set_pfn_from_mfn(
+            (virt_to_phys(t->shared) >> PAGE_SHIFT) + i,
+            INVALID_M2P_ENTRY);
     }
 
     /* Okay, install the structure. */
@@ -1306,57 +1290,53 @@
     {
         map = &gt->maptrack[handle];
 
-        if ( map->ref_and_flags & GNTMAP_device_map )
-        {
-            dom = map->domid;
-            ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT;
-
-            DPRINTK("Grant release (%hu) ref:(%hu) flags:(%x) dom:(%hu)\n",
-                    handle, ref,
-                    map->ref_and_flags & MAPTRACK_GNTMAP_MASK, dom);
-
-            if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
-                 unlikely(ld == rd) )
+        if ( !(map->ref_and_flags & GNTMAP_device_map) )
+            continue;
+
+        dom = map->domid;
+        ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT;
+
+        DPRINTK("Grant release (%hu) ref:(%hu) flags:(%x) dom:(%hu)\n",
+                handle, ref, map->ref_and_flags & MAPTRACK_GNTMAP_MASK, dom);
+
+        if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
+             unlikely(ld == rd) )
+        {
+            if ( rd != NULL )
+                put_domain(rd);
+            printk(KERN_WARNING "Grant release: No dom%d\n", dom);
+            continue;
+        }
+
+        act = &rd->grant_table->active[ref];
+        sha = &rd->grant_table->shared[ref];
+
+        spin_lock(&rd->grant_table->lock);
+
+        if ( act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask) )
+        {
+            frame = act->frame;
+
+            if ( ( (act->pin & GNTPIN_hstw_mask) == 0 ) &&
+                 ( (act->pin & GNTPIN_devw_mask) >  0 ) )
             {
-                if ( rd != NULL )
-                    put_domain(rd);
-
-                printk(KERN_WARNING "Grant release: No dom%d\n", dom);
-                continue;
+                clear_bit(_GTF_writing, &sha->flags);
+                put_page_type(&frame_table[frame]);
             }
 
-            act = &rd->grant_table->active[ref];
-            sha = &rd->grant_table->shared[ref];
-
-            spin_lock(&rd->grant_table->lock);
-
-            if ( act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask) )
+            map->ref_and_flags &= ~GNTMAP_device_map;
+            act->pin &= ~(GNTPIN_devw_mask | GNTPIN_devr_mask);
+            if ( act->pin == 0 )
             {
-                frame = act->frame;
-
-                if ( ( (act->pin & GNTPIN_hstw_mask) == 0 ) &&
-                     ( (act->pin & GNTPIN_devw_mask) >  0 ) )
-                {
-                    clear_bit(_GTF_writing, &sha->flags);
-                    put_page_type(&frame_table[frame]);
-                }
-
-                act->pin &= ~(GNTPIN_devw_mask | GNTPIN_devr_mask);
-
-                if ( act->pin == 0 )
-                {
-                    clear_bit(_GTF_reading, &sha->flags);
-                    map->ref_and_flags = 0;
-                    put_page(&frame_table[frame]);
-                }
-                else
-                    map->ref_and_flags &= ~GNTMAP_device_map;
+                clear_bit(_GTF_reading, &sha->flags);
+                map->ref_and_flags = 0;
+                put_page(&frame_table[frame]);
             }
-
-            spin_unlock(&rd->grant_table->lock);
-
-            put_domain(rd);
-        }
+        }
+
+        spin_unlock(&rd->grant_table->lock);
+
+        put_domain(rd);
     }
 }
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/kernel.c
--- a/xen/common/kernel.c       Thu Sep  8 15:18:40 2005
+++ b/xen/common/kernel.c       Fri Sep  9 16:30:54 2005
@@ -46,7 +46,7 @@
         if ( optval != NULL )
             *optval++ = '\0';
 
-        for ( param = &__setup_start; param != &__setup_end; param++ )
+        for ( param = &__setup_start; param <= &__setup_end; param++ )
         {
             if ( strcmp(param->name, opt ) != 0 )
                 continue;
@@ -110,6 +110,38 @@
             return -EFAULT;
         return 0;
     }
+
+    case XENVER_capabilities:
+    {
+        xen_capabilities_info_t info;
+        extern void arch_get_xen_caps(xen_capabilities_info_t * info);
+        
+        memset(&info, 0, sizeof(info));
+        arch_get_xen_caps(&info);
+
+        if ( copy_to_user(arg, &info, sizeof(info)) )
+            return -EFAULT;
+        return 0;
+    }
+    
+    case XENVER_parameters:
+    {
+        xen_parameters_info_t info = { .virt_start = HYPERVISOR_VIRT_START };
+
+        if ( copy_to_user(arg, &info, sizeof(info)) )
+            return -EFAULT;
+        return 0;
+        
+    }
+    
+    case XENVER_changeset:
+    {
+        xen_changeset_info_t chgset;
+        safe_strcpy(chgset, XEN_CHANGESET);
+        if ( copy_to_user(arg, chgset, sizeof(chgset)) )
+            return -EFAULT;
+        return 0;
+    }
     }
 
     return -ENOSYS;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/multicall.c
--- a/xen/common/multicall.c    Thu Sep  8 15:18:40 2005
+++ b/xen/common/multicall.c    Fri Sep  9 16:30:54 2005
@@ -45,6 +45,18 @@
 
         do_multicall_call(&mcs->call);
 
+#ifndef NDEBUG
+        {
+            /*
+             * Deliberately corrupt the contents of the multicall structure.
+             * The caller must depend only on the 'result' field on return.
+             */
+            multicall_entry_t corrupt;
+            memset(&corrupt, 0xAA, sizeof(corrupt));
+            (void)__copy_to_user(&call_list[i], &corrupt, sizeof(corrupt));
+        }
+#endif
+
         if ( unlikely(__put_user(mcs->call.result, &call_list[i].result)) )
         {
             DPRINTK("Error writing result back to multicall block.\n");
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/page_alloc.c
--- a/xen/common/page_alloc.c   Thu Sep  8 15:18:40 2005
+++ b/xen/common/page_alloc.c   Fri Sep  9 16:30:54 2005
@@ -216,7 +216,7 @@
 #define NR_ZONES    3
 
 
-#define MAX_DMADOM_PFN 0xFFFFF
+#define MAX_DMADOM_PFN 0x7FFFFUL /* 31 addressable bits */
 #define pfn_dom_zone_type(_pfn)                                 \
     (((_pfn) <= MAX_DMADOM_PFN) ? MEMZONE_DMADOM : MEMZONE_DOM)
 
@@ -485,43 +485,40 @@
 
 void init_domheap_pages(physaddr_t ps, physaddr_t pe)
 {
+    unsigned long s_tot, e_tot, s_dma, e_dma, s_nrm, e_nrm;
+
     ASSERT(!in_irq());
 
-    ps = round_pgup(ps) >> PAGE_SHIFT;
-    pe = round_pgdown(pe) >> PAGE_SHIFT;
-    if ( pe <= ps )
-        return;
-
-    if ( (ps < MAX_DMADOM_PFN) && (pe > MAX_DMADOM_PFN) )
-    {
-        init_heap_pages(
-            MEMZONE_DMADOM, pfn_to_page(ps), MAX_DMADOM_PFN - ps);
-        init_heap_pages(
-            MEMZONE_DOM, pfn_to_page(MAX_DMADOM_PFN), pe - MAX_DMADOM_PFN);
-    }
-    else
-    {
-        init_heap_pages(pfn_dom_zone_type(ps), pfn_to_page(ps), pe - ps);
-    }
+    s_tot = round_pgup(ps) >> PAGE_SHIFT;
+    e_tot = round_pgdown(pe) >> PAGE_SHIFT;
+
+    s_dma = min(s_tot, MAX_DMADOM_PFN + 1);
+    e_dma = min(e_tot, MAX_DMADOM_PFN + 1);
+    if ( s_dma < e_dma )
+        init_heap_pages(MEMZONE_DMADOM, pfn_to_page(s_dma), e_dma - s_dma);
+
+    s_nrm = max(s_tot, MAX_DMADOM_PFN + 1);
+    e_nrm = max(e_tot, MAX_DMADOM_PFN + 1);
+    if ( s_nrm < e_nrm )
+        init_heap_pages(MEMZONE_DOM, pfn_to_page(s_nrm), e_nrm - s_nrm);
 }
 
 
 struct pfn_info *alloc_domheap_pages(
     struct domain *d, unsigned int order, unsigned int flags)
 {
-    struct pfn_info *pg;
+    struct pfn_info *pg = NULL;
     cpumask_t mask;
     int i;
 
     ASSERT(!in_irq());
 
-    pg = NULL;
-    if (! (flags & ALLOC_DOM_DMA))
+    if ( !(flags & ALLOC_DOM_DMA) )
         pg = alloc_heap_pages(MEMZONE_DOM, order);
-    if (pg == NULL) {
-        if ( unlikely((pg = alloc_heap_pages(MEMZONE_DMADOM, order)) == NULL) )
+
+    if ( pg == NULL )
+        if ( (pg = alloc_heap_pages(MEMZONE_DMADOM, order)) == NULL )
             return NULL;
-    }
 
     mask = pg->u.free.cpumask;
     tlbflush_filter(mask, pg->tlbflush_timestamp);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/schedule.c
--- a/xen/common/schedule.c     Thu Sep  8 15:18:40 2005
+++ b/xen/common/schedule.c     Fri Sep  9 16:30:54 2005
@@ -218,9 +218,7 @@
             && spin_is_locked(&schedule_data[v->processor].schedule_lock) )
         cpu_relax();
 
-    /* Counteract lazy context switching. */
-    if ( cpu_isset(v->processor, v->domain->cpumask) )
-        sync_lazy_execstate_cpu(v->processor);
+    sync_vcpu_execstate(v);
 }
 
 void vcpu_wake(struct vcpu *v)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/trace.c
--- a/xen/common/trace.c        Thu Sep  8 15:18:40 2005
+++ b/xen/common/trace.c        Fri Sep  9 16:30:54 2005
@@ -66,7 +66,7 @@
     }
 
     nr_pages = num_online_cpus() * opt_tbuf_size;
-    order    = get_order(nr_pages * PAGE_SIZE);
+    order    = get_order_from_pages(nr_pages);
     
     if ( (rawbuf = alloc_xenheap_pages(order)) == NULL )
     {
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/xmalloc.c
--- a/xen/common/xmalloc.c      Thu Sep  8 15:18:40 2005
+++ b/xen/common/xmalloc.c      Fri Sep  9 16:30:54 2005
@@ -86,7 +86,7 @@
 static void *xmalloc_whole_pages(size_t size)
 {
     struct xmalloc_hdr *hdr;
-    unsigned int pageorder = get_order(size);
+    unsigned int pageorder = get_order_from_bytes(size);
 
     hdr = alloc_xenheap_pages(pageorder);
     if ( hdr == NULL )
@@ -159,7 +159,7 @@
     /* Big allocs free directly. */
     if ( hdr->size >= PAGE_SIZE )
     {
-        free_xenheap_pages(hdr, get_order(hdr->size));
+        free_xenheap_pages(hdr, get_order_from_bytes(hdr->size));
         return;
     }
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/drivers/char/console.c
--- a/xen/drivers/char/console.c        Thu Sep  8 15:18:40 2005
+++ b/xen/drivers/char/console.c        Fri Sep  9 16:30:54 2005
@@ -627,7 +627,7 @@
     if ( bytes == 0 )
         return 0;
 
-    order = get_order(bytes);
+    order = get_order_from_bytes(bytes);
     debugtrace_buf = alloc_xenheap_pages(order);
     ASSERT(debugtrace_buf != NULL);
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/drivers/char/serial.c
--- a/xen/drivers/char/serial.c Thu Sep  8 15:18:40 2005
+++ b/xen/drivers/char/serial.c Fri Sep  9 16:30:54 2005
@@ -366,8 +366,9 @@
 void serial_async_transmit(struct serial_port *port)
 {
     BUG_ON(!port->driver->tx_empty);
-    if ( !port->txbuf )
-        port->txbuf = alloc_xenheap_pages(get_order(SERIAL_TXBUFSZ));
+    if ( port->txbuf == NULL )
+        port->txbuf = alloc_xenheap_pages(
+            get_order_from_bytes(SERIAL_TXBUFSZ));
 }
 
 /*
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/acm/acm_core.h
--- a/xen/include/acm/acm_core.h        Thu Sep  8 15:18:40 2005
+++ b/xen/include/acm/acm_core.h        Fri Sep  9 16:30:54 2005
@@ -101,9 +101,15 @@
  *     primary ssidref   = lower 16 bit
  *      secondary ssidref = higher 16 bit
  */
+#define ACM_PRIMARY(ssidref) \
+       ((ssidref) & 0xffff)
+
+#define ACM_SECONDARY(ssidref) \
+       ((ssidref) >> 16)
+
 #define GET_SSIDREF(POLICY, ssidref) \
        ((POLICY) == acm_bin_pol.primary_policy_code) ? \
-       ((ssidref) & 0xffff) : ((ssidref) >> 16)
+       ACM_PRIMARY(ssidref) : ACM_SECONDARY(ssidref)
 
 /* macros to access ssid pointer for primary / secondary policy */
 #define GET_SSIDP(POLICY, ssid) \
@@ -116,6 +122,7 @@
 int acm_set_policy(void *buf, u16 buf_size, int isuserbuffer);
 int acm_get_policy(void *buf, u16 buf_size);
 int acm_dump_statistics(void *buf, u16 buf_size);
+int acm_get_ssid(ssidref_t ssidref, u8 *buf, u16 buf_size);
 
 #endif
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/acm/acm_hooks.h
--- a/xen/include/acm/acm_hooks.h       Thu Sep  8 15:18:40 2005
+++ b/xen/include/acm/acm_hooks.h       Fri Sep  9 16:30:54 2005
@@ -92,6 +92,7 @@
     int  (*dump_binary_policy)         (u8 *buffer, u16 buf_size);
     int  (*set_binary_policy)          (u8 *buffer, u16 buf_size);
     int  (*dump_statistics)            (u8 *buffer, u16 buf_size);
+    int  (*dump_ssid_types)            (ssidref_t ssidref, u8 *buffer, u16 
buf_size);
     /* domain management control hooks (can be NULL) */
     int  (*pre_domain_create)          (void *subject_ssid, ssidref_t ssidref);
     void (*post_domain_create)         (domid_t domid, ssidref_t ssidref);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/asm_defns.h
--- a/xen/include/asm-x86/asm_defns.h   Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/asm_defns.h   Fri Sep  9 16:30:54 2005
@@ -6,11 +6,6 @@
 #include <asm/asm-offsets.h>
 #include <asm/processor.h>
 
-#ifndef STR
-#define __STR(x) #x
-#define STR(x) __STR(x)
-#endif
-
 #ifdef __x86_64__
 #include <asm/x86_64/asm_defns.h>
 #else
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/bitops.h
--- a/xen/include/asm-x86/bitops.h      Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/bitops.h      Fri Sep  9 16:30:54 2005
@@ -6,11 +6,6 @@
  */
 
 #include <xen/config.h>
-
-#ifndef STR
-#define __STR(x) #x
-#define STR(x) __STR(x)
-#endif
 
 /*
  * These have to be done with inline assembly: that way the bit-setting
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h  Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/mm.h  Fri Sep  9 16:30:54 2005
@@ -255,10 +255,13 @@
  * contiguous (or near contiguous) physical memory.
  */
 #undef  machine_to_phys_mapping
-#define machine_to_phys_mapping ((u32 *)RDWR_MPT_VIRT_START)
-#define INVALID_M2P_ENTRY        (~0U)
-#define VALID_M2P(_e)            (!((_e) & (1U<<31)))
+#define machine_to_phys_mapping  ((unsigned long *)RDWR_MPT_VIRT_START)
+#define INVALID_M2P_ENTRY        (~0UL)
+#define VALID_M2P(_e)            (!((_e) & (1UL<<(BITS_PER_LONG-1))))
 #define IS_INVALID_M2P_ENTRY(_e) (!VALID_M2P(_e))
+
+#define set_pfn_from_mfn(mfn, pfn) (machine_to_phys_mapping[(mfn)] = (pfn))
+#define get_pfn_from_mfn(mfn)      (machine_to_phys_mapping[(mfn)])
 
 /*
  * The phys_to_machine_mapping is the reversed mapping of MPT for full
@@ -266,17 +269,17 @@
  * guests, so we steal the address space that would have normally
  * been used by the read-only MPT map.
  */
-#define __phys_to_machine_mapping ((unsigned long *)RO_MPT_VIRT_START)
-#define INVALID_MFN               (~0UL)
-#define VALID_MFN(_mfn)           (!((_mfn) & (1U<<31)))
-
-/* Returns the machine physical */
-static inline unsigned long phys_to_machine_mapping(unsigned long pfn) 
+#define phys_to_machine_mapping ((unsigned long *)RO_MPT_VIRT_START)
+#define INVALID_MFN             (~0UL)
+#define VALID_MFN(_mfn)         (!((_mfn) & (1U<<31)))
+
+#define set_mfn_from_pfn(pfn, mfn) (phys_to_machine_mapping[(pfn)] = (mfn))
+static inline unsigned long get_mfn_from_pfn(unsigned long pfn) 
 {
     unsigned long mfn;
     l1_pgentry_t pte;
 
-    if ( (__copy_from_user(&pte, &__phys_to_machine_mapping[pfn],
+    if ( (__copy_from_user(&pte, &phys_to_machine_mapping[pfn],
                            sizeof(pte)) == 0) &&
          (l1e_get_flags(pte) & _PAGE_PRESENT) )
        mfn = l1e_get_pfn(pte);
@@ -285,7 +288,6 @@
     
     return mfn; 
 }
-#define set_machinetophys(_mfn, _pfn) machine_to_phys_mapping[(_mfn)] = (_pfn)
 
 #ifdef MEMORY_GUARD
 void memguard_init(void);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/page-guest32.h
--- a/xen/include/asm-x86/page-guest32.h        Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/page-guest32.h        Fri Sep  9 16:30:54 2005
@@ -32,6 +32,11 @@
 /* Get pte access flags (unsigned int). */
 #define l1e_get_flags_32(x)           (get_pte_flags_32((x).l1))
 #define l2e_get_flags_32(x)           (get_pte_flags_32((x).l2))
+
+#define l1e_get_paddr_32(x)           \
+    ((physaddr_t)(((x).l1 & (PADDR_MASK&PAGE_MASK))))
+#define l2e_get_paddr_32(x)           \
+    ((physaddr_t)(((x).l2 & (PADDR_MASK&PAGE_MASK))))
 
 /* Construct an empty pte. */
 #define l1e_empty_32()                ((l1_pgentry_32_t) { 0 })
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/page.h
--- a/xen/include/asm-x86/page.h        Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/page.h        Fri Sep  9 16:30:54 2005
@@ -280,12 +280,21 @@
 
 #ifndef __ASSEMBLY__
 
-static __inline__ int get_order(unsigned long size)
+static inline int get_order_from_bytes(physaddr_t size)
 {
     int order;
     size = (size-1) >> PAGE_SHIFT;
     for ( order = 0; size; order++ )
         size >>= 1;
+    return order;
+}
+
+static inline int get_order_from_pages(unsigned long nr_pages)
+{
+    int order;
+    nr_pages--;
+    for ( order = 0; nr_pages; order++ )
+        nr_pages >>= 1;
     return order;
 }
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/processor.h
--- a/xen/include/asm-x86/processor.h   Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/processor.h   Fri Sep  9 16:30:54 2005
@@ -496,9 +496,7 @@
 
 #endif
 
-void show_guest_stack();
-void show_trace(unsigned long *esp);
-void show_stack(unsigned long *esp);
+void show_stack(struct cpu_user_regs *regs);
 void show_registers(struct cpu_user_regs *regs);
 void show_page_walk(unsigned long addr);
 asmlinkage void fatal_trap(int trapnr, struct cpu_user_regs *regs);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/shadow.h
--- a/xen/include/asm-x86/shadow.h      Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/shadow.h      Fri Sep  9 16:30:54 2005
@@ -34,6 +34,8 @@
 #include <asm/vmx.h>
 #include <public/dom0_ops.h>
 #include <asm/shadow_public.h>
+#include <asm/page-guest32.h>
+#include <asm/shadow_ops.h>
 
 /* Shadow PT operation mode : shadow-mode variable in arch_domain. */
 
@@ -104,9 +106,9 @@
 } while (0)
 #endif
 
-#define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((L1_PAGETABLE_ENTRIES - 1) - 
(_max)) << 16) | (_min))
+#define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((GUEST_L1_PAGETABLE_ENTRIES - 1) 
- (_max)) << 16) | (_min))
 #define SHADOW_MIN(_encoded) ((_encoded) & ((1u<<16) - 1))
-#define SHADOW_MAX(_encoded) ((L1_PAGETABLE_ENTRIES - 1) - ((_encoded) >> 16))
+#define SHADOW_MAX(_encoded) ((GUEST_L1_PAGETABLE_ENTRIES - 1) - ((_encoded) 
>> 16))
 
 extern void shadow_mode_init(void);
 extern int shadow_mode_control(struct domain *p, dom0_shadow_control_t *sc);
@@ -132,6 +134,7 @@
                                        struct domain_mmap_cache *cache);
 #if CONFIG_PAGING_LEVELS >= 3
 #include <asm/page-guest32.h>
+extern unsigned long gva_to_gpa(unsigned long gva);
 extern void shadow_l3_normal_pt_update(struct domain *d,
                                        unsigned long pa, l3_pgentry_t l3e,
                                        struct domain_mmap_cache *cache);
@@ -269,14 +272,14 @@
 
 #define __mfn_to_gpfn(_d, mfn)                         \
     ( (shadow_mode_translate(_d))                      \
-      ? machine_to_phys_mapping[(mfn)]                 \
+      ? get_pfn_from_mfn(mfn)                                   \
       : (mfn) )
 
 #define __gpfn_to_mfn(_d, gpfn)                        \
     ({                                                 \
         ASSERT(current->domain == (_d));               \
         (shadow_mode_translate(_d))                    \
-        ? phys_to_machine_mapping(gpfn)                \
+        ? get_mfn_from_pfn(gpfn)                \
         : (gpfn);                                      \
     })
 
@@ -461,7 +464,7 @@
     // This wants the nice compact set of PFNs from 0..domain's max,
     // which __mfn_to_gpfn() only returns for translated domains.
     //
-    pfn = machine_to_phys_mapping[mfn];
+    pfn = get_pfn_from_mfn(mfn);
 
     /*
      * Values with the MSB set denote MFNs that aren't really part of the 
@@ -562,7 +565,7 @@
     old_hl2e = v->arch.hl2_vtable[index];
 
     if ( (l2e_get_flags(gl2e) & _PAGE_PRESENT) &&
-         VALID_MFN(mfn = phys_to_machine_mapping(l2e_get_pfn(gl2e))) )
+         VALID_MFN(mfn = get_mfn_from_pfn(l2e_get_pfn(gl2e))) )
         new_hl2e = l1e_from_pfn(mfn, __PAGE_HYPERVISOR);
     else
         new_hl2e = l1e_empty();
@@ -794,22 +797,22 @@
 #endif
 
 static inline void l1pte_propagate_from_guest(
-    struct domain *d, l1_pgentry_t gpte, l1_pgentry_t *spte_p)
+    struct domain *d, guest_l1_pgentry_t gpte, l1_pgentry_t *spte_p)
 { 
     unsigned long mfn;
     l1_pgentry_t spte;
 
     spte = l1e_empty();
 
-    if ( ((l1e_get_flags(gpte) & (_PAGE_PRESENT|_PAGE_ACCESSED) ) ==
+    if ( ((guest_l1e_get_flags(gpte) & (_PAGE_PRESENT|_PAGE_ACCESSED) ) ==
           (_PAGE_PRESENT|_PAGE_ACCESSED)) &&
          VALID_MFN(mfn = __gpfn_to_mfn(d, l1e_get_pfn(gpte))) )
     {
         spte = l1e_from_pfn(
-            mfn, l1e_get_flags(gpte) & ~(_PAGE_GLOBAL | _PAGE_AVAIL));
+            mfn, guest_l1e_get_flags(gpte) & ~(_PAGE_GLOBAL | _PAGE_AVAIL));
 
         if ( shadow_mode_log_dirty(d) ||
-             !(l1e_get_flags(gpte) & _PAGE_DIRTY) ||
+             !(guest_l1e_get_flags(gpte) & _PAGE_DIRTY) ||
              mfn_is_page_table(mfn) )
         {
             l1e_remove_flags(spte, _PAGE_RW);
@@ -859,22 +862,22 @@
 
 static inline void l2pde_general(
     struct domain *d,
-    l2_pgentry_t *gpde_p,
+    guest_l2_pgentry_t *gpde_p,
     l2_pgentry_t *spde_p,
     unsigned long sl1mfn)
 {
-    l2_pgentry_t gpde = *gpde_p;
+    guest_l2_pgentry_t gpde = *gpde_p;
     l2_pgentry_t spde;
 
     spde = l2e_empty();
-    if ( (l2e_get_flags(gpde) & _PAGE_PRESENT) && (sl1mfn != 0) )
+    if ( (guest_l2e_get_flags(gpde) & _PAGE_PRESENT) && (sl1mfn != 0) )
     {
         spde = l2e_from_pfn(
-            sl1mfn, 
-            (l2e_get_flags(gpde) | _PAGE_RW | _PAGE_ACCESSED) & ~_PAGE_AVAIL);
+            sl1mfn,
+            (guest_l2e_get_flags(gpde) | _PAGE_RW | _PAGE_ACCESSED) & 
~_PAGE_AVAIL);
 
         /* N.B. PDEs do not have a dirty bit. */
-        l2e_add_flags(gpde, _PAGE_ACCESSED);
+        guest_l2e_add_flags(gpde, _PAGE_ACCESSED);
 
         *gpde_p = gpde;
     }
@@ -887,12 +890,12 @@
 }
 
 static inline void l2pde_propagate_from_guest(
-    struct domain *d, l2_pgentry_t *gpde_p, l2_pgentry_t *spde_p)
-{
-    l2_pgentry_t gpde = *gpde_p;
+    struct domain *d, guest_l2_pgentry_t *gpde_p, l2_pgentry_t *spde_p)
+{
+    guest_l2_pgentry_t gpde = *gpde_p;
     unsigned long sl1mfn = 0;
 
-    if ( l2e_get_flags(gpde) & _PAGE_PRESENT )
+    if ( guest_l2e_get_flags(gpde) & _PAGE_PRESENT )
         sl1mfn =  __shadow_status(d, l2e_get_pfn(gpde), PGT_l1_shadow);
     l2pde_general(d, gpde_p, spde_p, sl1mfn);
 }
@@ -904,7 +907,7 @@
 static int inline
 validate_pte_change(
     struct domain *d,
-    l1_pgentry_t new_pte,
+    guest_l1_pgentry_t new_pte,
     l1_pgentry_t *shadow_pte_p)
 {
     l1_pgentry_t old_spte, new_spte;
@@ -1004,7 +1007,7 @@
 static int inline
 validate_pde_change(
     struct domain *d,
-    l2_pgentry_t new_gpde,
+    guest_l2_pgentry_t new_gpde,
     l2_pgentry_t *shadow_pde_p)
 {
     l2_pgentry_t old_spde, new_spde;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/shadow_64.h
--- a/xen/include/asm-x86/shadow_64.h   Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/shadow_64.h   Fri Sep  9 16:30:54 2005
@@ -27,6 +27,7 @@
 #ifndef _XEN_SHADOW_64_H
 #define _XEN_SHADOW_64_H
 #include <asm/shadow.h>
+#include <asm/shadow_ops.h>
 
 #define READ_FAULT  0
 #define WRITE_FAULT 1
@@ -42,14 +43,14 @@
 #define ESH_LOG(_f, _a...) ((void)0)
 #endif
 
-#define L4      4UL
-#define L3      3UL
-#define L2      2UL
-#define L1      1UL
+#define PAGING_L4      4UL
+#define PAGING_L3      3UL
+#define PAGING_L2      2UL
+#define PAGING_L1      1UL
 #define L_MASK  0xff
 
-#define ROOT_LEVEL_64   L4
-#define ROOT_LEVEL_32   L2
+#define ROOT_LEVEL_64   PAGING_L4
+#define ROOT_LEVEL_32   PAGING_L2
 
 #define SHADOW_ENTRY    (2UL << 16)
 #define GUEST_ENTRY     (1UL << 16)
@@ -58,6 +59,10 @@
 #define SET_ENTRY   (1UL << 8)
 
 #define PAGETABLE_ENTRIES    (1<<PAGETABLE_ORDER)
+
+/* For 32-bit VMX guest to allocate shadow L1 & L2*/
+#define SL1_ORDER   1
+#define SL2_ORDER   2
 
 typedef struct { intpte_t lo; } pgentry_64_t;
 #define shadow_level_to_type(l)    (l << 29)
@@ -76,6 +81,10 @@
 #define entry_remove_flags(x, flags) ((x).lo &= ~put_pte_flags(flags))
 #define entry_has_changed(x,y,flags) \
         ( !!(((x).lo ^ (y).lo) & 
((PADDR_MASK&PAGE_MASK)|put_pte_flags(flags))) )
+
+#define PAE_SHADOW_SELF_ENTRY   259
+#define PDP_ENTRIES   4
+
 static inline int  table_offset_64(unsigned long va, int level)
 {
     switch(level) {
@@ -86,8 +95,13 @@
         case 3:
             return  (((va) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 
1));
 #if CONFIG_PAGING_LEVELS >= 4
+#ifndef GUEST_PGENTRY_32
         case 4:
             return  (((va) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 
1));
+#else
+        case 4:
+            return PAE_SHADOW_SELF_ENTRY; 
+#endif
 #endif
         default:
             //printk("<table_offset_64> level %d is too big\n", level);
@@ -138,7 +152,7 @@
             return NULL;
         mfn = entry_get_value(*le_e) >> PAGE_SHIFT;
         if ((flag & GUEST_ENTRY) && shadow_mode_translate(d))
-            mfn = phys_to_machine_mapping(mfn);
+            mfn = get_mfn_from_pfn(mfn);
         le_p = (pgentry_64_t *)phys_to_virt(mfn << PAGE_SHIFT);
         index = table_offset_64(va, (level + i - 1));
         le_e = &le_p[index];
@@ -165,30 +179,30 @@
     return le_e;
 }
 #define __shadow_set_l4e(v, va, value) \
-  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L4)
+  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L4)
 #define __shadow_get_l4e(v, va, sl4e) \
-  __rw_entry(v, va, sl4e, SHADOW_ENTRY | GET_ENTRY | L4)
+  __rw_entry(v, va, sl4e, SHADOW_ENTRY | GET_ENTRY | PAGING_L4)
 #define __shadow_set_l3e(v, va, value) \
-  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L3)
+  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L3)
 #define __shadow_get_l3e(v, va, sl3e) \
-  __rw_entry(v, va, sl3e, SHADOW_ENTRY | GET_ENTRY | L3)
+  __rw_entry(v, va, sl3e, SHADOW_ENTRY | GET_ENTRY | PAGING_L3)
 #define __shadow_set_l2e(v, va, value) \
-  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L2)
+  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L2)
 #define __shadow_get_l2e(v, va, sl2e) \
-  __rw_entry(v, va, sl2e, SHADOW_ENTRY | GET_ENTRY | L2)
+  __rw_entry(v, va, sl2e, SHADOW_ENTRY | GET_ENTRY | PAGING_L2)
 #define __shadow_set_l1e(v, va, value) \
-  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L1)
+  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L1)
 #define __shadow_get_l1e(v, va, sl1e) \
-  __rw_entry(v, va, sl1e, SHADOW_ENTRY | GET_ENTRY | L1)
+  __rw_entry(v, va, sl1e, SHADOW_ENTRY | GET_ENTRY | PAGING_L1)
 
 #define __guest_set_l4e(v, va, value) \
-  __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L4)
+  __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | PAGING_L4)
 #define __guest_get_l4e(v, va, gl4e) \
-  __rw_entry(v, va, gl4e, GUEST_ENTRY | GET_ENTRY | L4)
+  __rw_entry(v, va, gl4e, GUEST_ENTRY | GET_ENTRY | PAGING_L4)
 #define __guest_set_l3e(v, va, value) \
-  __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L3)
+  __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | PAGING_L3)
 #define __guest_get_l3e(v, va, sl3e) \
-  __rw_entry(v, va, gl3e, GUEST_ENTRY | GET_ENTRY | L3)
+  __rw_entry(v, va, gl3e, GUEST_ENTRY | GET_ENTRY | PAGING_L3)
 
 static inline void *  __guest_set_l2e(
     struct vcpu *v, u64 va, void *value, int size)
@@ -205,7 +219,7 @@
                 return &l2va[l2_table_offset_32(va)];
             }
         case 8:
-            return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L2);
+            return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | 
PAGING_L2);
         default:
             BUG();
             return NULL;
@@ -230,7 +244,7 @@
                 return &l2va[l2_table_offset_32(va)];
             }
         case 8:
-            return __rw_entry(v, va, gl2e, GUEST_ENTRY | GET_ENTRY | L2);
+            return __rw_entry(v, va, gl2e, GUEST_ENTRY | GET_ENTRY | 
PAGING_L2);
         default:
             BUG();
             return NULL;
@@ -257,7 +271,7 @@
                 if (unlikely(!(l2e_get_flags_32(gl2e) & _PAGE_PRESENT)))
                     return NULL;
 
-                l1mfn = phys_to_machine_mapping(
+                l1mfn = get_mfn_from_pfn(
                   l2e_get_pfn(gl2e));
 
                 l1va = (l1_pgentry_32_t *)
@@ -269,7 +283,7 @@
             }
 
         case 8:
-            return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L1);
+            return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | 
PAGING_L1);
         default:
             BUG();
             return NULL;
@@ -299,7 +313,7 @@
                     return NULL;
 
 
-                l1mfn = phys_to_machine_mapping(
+                l1mfn = get_mfn_from_pfn(
                   l2e_get_pfn(gl2e));
                 l1va = (l1_pgentry_32_t *) phys_to_virt(
                   l1mfn << L1_PAGETABLE_SHIFT);
@@ -310,7 +324,7 @@
             }
         case 8:
             // 64-bit guest
-            return __rw_entry(v, va, gl1e, GUEST_ENTRY | GET_ENTRY | L1);
+            return __rw_entry(v, va, gl1e, GUEST_ENTRY | GET_ENTRY | 
PAGING_L1);
         default:
             BUG();
             return NULL;
@@ -334,7 +348,7 @@
     sle = entry_empty();
     if ( (entry_get_flags(gle) & _PAGE_PRESENT) && (smfn != 0) )
     {
-        if ((entry_get_flags(gle) & _PAGE_PSE) && level == L2) {
+        if ((entry_get_flags(gle) & _PAGE_PSE) && level == PAGING_L2) {
             sle = entry_from_pfn(smfn, entry_get_flags(gle));
             entry_remove_flags(sle, _PAGE_PSE);
 
@@ -376,7 +390,7 @@
     unsigned long smfn = 0;
 
     if ( entry_get_flags(gle) & _PAGE_PRESENT ) {
-        if ((entry_get_flags(gle) & _PAGE_PSE) && level == L2) {
+        if ((entry_get_flags(gle) & _PAGE_PSE) && level == PAGING_L2) {
             smfn =  __shadow_status(d, entry_get_value(gle) >> PAGE_SHIFT, 
PGT_fl1_shadow);
         } else {
             smfn =  __shadow_status(d, entry_get_pfn(gle), 
@@ -421,86 +435,6 @@
     return 1;
 }
 
-/*
- * Check P, R/W, U/S bits in the guest page table.
- * If the fault belongs to guest return 1,
- * else return 0.
- */
-static inline int guest_page_fault(struct vcpu *v,
-  unsigned long va, unsigned int error_code, pgentry_64_t *gpl2e, pgentry_64_t 
*gpl1e)
-{
-    struct domain *d = v->domain;
-    pgentry_64_t gle, *lva;
-    unsigned long mfn;
-    int i;
-
-    __rw_entry(v, va, &gle, GUEST_ENTRY | GET_ENTRY | L4);
-    if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT)))
-        return 1;
-
-    if (error_code & ERROR_W) {
-        if (unlikely(!(entry_get_flags(gle) & _PAGE_RW)))
-            return 1;
-    }
-    if (error_code & ERROR_U) {
-        if (unlikely(!(entry_get_flags(gle) & _PAGE_USER)))
-            return 1;
-    }
-    for (i = L3; i >= L1; i--) {
-       /*
-        * If it's not external mode, then mfn should be machine physical.
-        */
-       mfn = __gpfn_to_mfn(d, (entry_get_value(gle) >> PAGE_SHIFT));
-
-        lva = (pgentry_64_t *) phys_to_virt(
-           mfn << PAGE_SHIFT);
-        gle = lva[table_offset_64(va, i)];
-
-        if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT)))
-            return 1;
-
-        if (error_code & ERROR_W) {
-            if (unlikely(!(entry_get_flags(gle) & _PAGE_RW)))
-                return 1;
-        }
-        if (error_code & ERROR_U) {
-            if (unlikely(!(entry_get_flags(gle) & _PAGE_USER)))
-                return 1;
-        }
-
-        if (i == L2) {
-            if (gpl2e)
-                *gpl2e = gle;
-
-            if (likely(entry_get_flags(gle) & _PAGE_PSE))
-                return 0;
-
-        }
-
-        if (i == L1)
-            if (gpl1e)
-                *gpl1e = gle;
-    }
-    return 0;
-}
-
-static inline unsigned long gva_to_gpa(unsigned long gva)
-{
-    struct vcpu *v = current;
-    pgentry_64_t gl1e = {0};
-    pgentry_64_t gl2e = {0};
-    unsigned long gpa;
-
-    if (guest_page_fault(v, gva, 0, &gl2e, &gl1e))
-        return 0;
-    if (entry_get_flags(gl2e) & _PAGE_PSE)
-        gpa = entry_get_paddr(gl2e) + (gva & ((1 << L2_PAGETABLE_SHIFT) - 1));
-    else
-        gpa = entry_get_paddr(gl1e) + (gva & ~PAGE_MASK);
-
-    return gpa;
-
-}
 #endif
 
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/shadow_public.h
--- a/xen/include/asm-x86/shadow_public.h       Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/shadow_public.h       Fri Sep  9 16:30:54 2005
@@ -49,6 +49,7 @@
          (*mark_mfn_out_of_sync)(struct vcpu *v, unsigned long gpfn,
                               unsigned long mfn);
     int  (*is_out_of_sync)(struct vcpu *v, unsigned long va);
+    unsigned long (*gva_to_gpa)(unsigned long gva);
 };
 #endif
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/vmx.h
--- a/xen/include/asm-x86/vmx.h Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/vmx.h Fri Sep  9 16:30:54 2005
@@ -275,7 +275,9 @@
     return 0;
 }
 
-static inline int __vmread (unsigned long field, void *value)
+#define __vmread(x, ptr) ___vmread((x), (ptr), sizeof(*(ptr)))
+
+static always_inline int ___vmread (const unsigned long field,  void *ptr, 
const int size)
 {
     unsigned long eflags;
     unsigned long ecx = 0;
@@ -286,7 +288,23 @@
                            : "a" (field)
                            : "memory");
 
-    *((long *) value) = ecx;
+    switch (size) {
+    case 1:
+        *((u8 *) (ptr)) = ecx;
+        break;
+    case 2:
+        *((u16 *) (ptr)) = ecx;
+        break;
+    case 4:
+        *((u32 *) (ptr)) = ecx;
+        break;
+    case 8:
+        *((u64 *) (ptr)) = ecx;
+        break;
+    default:
+        domain_crash_synchronous();
+        break;
+    }
 
     __save_flags(eflags);
     if (eflags & X86_EFLAGS_ZF || eflags & X86_EFLAGS_CF)
@@ -453,4 +471,7 @@
 void load_cpu_user_regs(struct cpu_user_regs *regs);
 void store_cpu_user_regs(struct cpu_user_regs *regs);
 
+enum { VMX_COPY_IN = 0, VMX_COPY_OUT };
+int vmx_copy(void *buf, unsigned long laddr, int size, int dir);
+
 #endif /* __ASM_X86_VMX_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/vmx_platform.h
--- a/xen/include/asm-x86/vmx_platform.h        Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/vmx_platform.h        Fri Sep  9 16:30:54 2005
@@ -24,8 +24,7 @@
 #include <asm/vmx_virpit.h>
 #include <asm/vmx_intercept.h>
 
-#define MAX_OPERAND_NUM 3
-#define I_NAME_LEN  16
+#define MAX_OPERAND_NUM 2
 
 #define mk_operand(size, index, seg, flag) \
     (((size) << 24) | ((index) << 16) | ((seg) << 8) | (flag))
@@ -35,54 +34,60 @@
 
 #define operand_index(operand)  \
       ((operand >> 16) & 0xFF)
-      //For instruction.operand[].size
+
+/* for instruction.operand[].size */
 #define BYTE    1
 #define WORD    2
 #define LONG    4
 #define QUAD    8
 #define BYTE_64 16
 
-      //For instruction.operand[].flag
+/* for instruction.operand[].flag */
 #define REGISTER    0x1
 #define MEMORY      0x2
 #define IMMEDIATE   0x4
-#define WZEROEXTEND 0x8
 
-      //For instruction.flags
+/* for instruction.flags */
 #define REPZ    0x1
 #define REPNZ   0x2
+#define OVERLAP 0x4
+
+#define        INSTR_PIO       1
+#define INSTR_OR       2
+#define INSTR_AND      3
+#define INSTR_XOR      4
+#define INSTR_CMP      5
+#define INSTR_MOV      6
+#define INSTR_MOVS     7
+#define INSTR_MOVZ     8
+#define INSTR_STOS     9
+#define INSTR_TEST     10
 
 struct instruction {
-    __s8    i_name[I_NAME_LEN];  //Instruction's name
-    __s16   op_size;    //The operand's bit size, e.g. 16-bit or 32-bit.
-
-    __u64   offset;     //The effective address
-          //offset = Base + (Index * Scale) + Displacement
-
+    __s8    instr;     /* instruction type */
+    __s16   op_size;    /* the operand's bit size, e.g. 16-bit or 32-bit */
     __u64   immediate;
-
-    __u16   seg_sel;    //Segmentation selector
-
-    __u32   operand[MAX_OPERAND_NUM];   //The order of operand is from AT&T 
Assembly
-    __s16   op_num; //The operand numbers
-
-    __u32   flags; //
+    __u16   seg_sel;    /* segmentation selector */
+    __u32   operand[MAX_OPERAND_NUM];   /* order is AT&T assembly */
+    __u32   flags;
 };
 
 #define MAX_INST_LEN      32
 
-struct mi_per_cpu_info
-{
-    unsigned long          mmio_target;
-    struct cpu_user_regs        *inst_decoder_regs;
+struct mi_per_cpu_info {
+    int                    flags;
+    int                           instr;               /* instruction */
+    unsigned long          operand[2];         /* operands */
+    unsigned long          immediate;          /* immediate portion */
+    struct cpu_user_regs   *inst_decoder_regs; /* current context */
 };
 
 struct virtual_platform_def {
-    unsigned long          *real_mode_data; /* E820, etc. */
+    unsigned long          *real_mode_data;    /* E820, etc. */
     unsigned long          shared_page_va;
     struct vmx_virpit_t    vmx_pit;
     struct vmx_handler_t   vmx_handler;
-    struct mi_per_cpu_info mpci;            /* MMIO */
+    struct mi_per_cpu_info mpci;               /* MMIO */
 };
 
 extern void handle_mmio(unsigned long, unsigned long);
@@ -91,6 +96,6 @@
 extern void vmx_io_assist(struct vcpu *v);
 
 // XXX - think about this -- maybe use bit 30 of the mfn to signify an MMIO 
frame.
-#define mmio_space(gpa) (!VALID_MFN(phys_to_machine_mapping((gpa) >> 
PAGE_SHIFT)))
+#define mmio_space(gpa) (!VALID_MFN(get_mfn_from_pfn((gpa) >> PAGE_SHIFT)))
 
 #endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/vmx_vmcs.h
--- a/xen/include/asm-x86/vmx_vmcs.h    Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/vmx_vmcs.h    Fri Sep  9 16:30:54 2005
@@ -183,7 +183,7 @@
     VM_ENTRY_MSR_LOAD_COUNT         = 0x00004014,
     VM_ENTRY_INTR_INFO_FIELD        = 0x00004016,
     VM_ENTRY_EXCEPTION_ERROR_CODE   = 0x00004018,
-    VM_ENTRY_INSTRUCTION_LENGTH     = 0x0000401a,
+    VM_ENTRY_INSTRUCTION_LEN        = 0x0000401a,
     TPR_THRESHOLD                   = 0x0000401c,
     SECONDARY_VM_EXEC_CONTROL       = 0x0000401e,
     VM_INSTRUCTION_ERROR            = 0x00004400,
@@ -192,7 +192,7 @@
     VM_EXIT_INTR_ERROR_CODE         = 0x00004406,
     IDT_VECTORING_INFO_FIELD        = 0x00004408,
     IDT_VECTORING_ERROR_CODE        = 0x0000440a,
-    INSTRUCTION_LEN                 = 0x0000440c,
+    VM_EXIT_INSTRUCTION_LEN         = 0x0000440c,
     VMX_INSTRUCTION_INFO            = 0x0000440e,
     GUEST_ES_LIMIT                  = 0x00004800,
     GUEST_CS_LIMIT                  = 0x00004802,
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/x86_32/asm_defns.h
--- a/xen/include/asm-x86/x86_32/asm_defns.h    Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/x86_32/asm_defns.h    Fri Sep  9 16:30:54 2005
@@ -1,56 +1,26 @@
 #ifndef __X86_32_ASM_DEFNS_H__
 #define __X86_32_ASM_DEFNS_H__
 
-/* Maybe auto-generate the following two cases (quoted vs. unquoted). */
-#ifndef __ASSEMBLY__
-
-#define __SAVE_ALL_PRE                                                  \
-        "cld;"                                                          \
-        "pushl %eax;"                                                   \
-        "pushl %ebp;"                                                   \
-        "pushl %edi;"                                                   \
-        "pushl %esi;"                                                   \
-        "pushl %edx;"                                                   \
-        "pushl %ecx;"                                                   \
-        "pushl %ebx;"                                                   \
-        "testl $"STR(X86_EFLAGS_VM)","STR(UREGS_eflags)"(%esp);"        \
-        "jz 2f;"                                                        \
-        "call setup_vm86_frame;"                                        \
-        "jmp 3f;"                                                       \
-        "2:testb $3,"STR(UREGS_cs)"(%esp);"                             \
-        "jz 1f;"                                                        \
-        "mov %ds,"STR(UREGS_ds)"(%esp);"                                \
-        "mov %es,"STR(UREGS_es)"(%esp);"                                \
-        "mov %fs,"STR(UREGS_fs)"(%esp);"                                \
-        "mov %gs,"STR(UREGS_gs)"(%esp);"                                \
-        "3:"
-
-#define SAVE_ALL_NOSEGREGS(_reg)                \
-        __SAVE_ALL_PRE                          \
-        "1:"
-
-#define SET_XEN_SEGMENTS(_reg)                                  \
-        "movl $("STR(__HYPERVISOR_DS)"),%e"STR(_reg)"x;"        \
-        "mov %e"STR(_reg)"x,%ds;"                              \
-        "mov %e"STR(_reg)"x,%es;"
-
-#define SAVE_ALL(_reg)                          \
-        __SAVE_ALL_PRE                          \
-        SET_XEN_SEGMENTS(_reg)                  \
-        "1:"
-
+#ifndef NDEBUG
+/* Indicate special exception stack frame by inverting the frame pointer. */
+#define SETUP_EXCEPTION_FRAME_POINTER           \
+        movl  %esp,%ebp;                        \
+        notl  %ebp
 #else
+#define SETUP_EXCEPTION_FRAME_POINTER
+#endif
 
 #define __SAVE_ALL_PRE                                  \
         cld;                                            \
         pushl %eax;                                     \
         pushl %ebp;                                     \
+        SETUP_EXCEPTION_FRAME_POINTER;                  \
         pushl %edi;                                     \
         pushl %esi;                                     \
         pushl %edx;                                     \
         pushl %ecx;                                     \
         pushl %ebx;                                     \
-        testl $X86_EFLAGS_VM,UREGS_eflags(%esp);        \
+        testl $(X86_EFLAGS_VM),UREGS_eflags(%esp);      \
         jz 2f;                                          \
         call setup_vm86_frame;                          \
         jmp 3f;                                         \
@@ -83,8 +53,6 @@
 #define PERFC_INCR(_name,_idx)
 #endif
 
-#endif
-
 #define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v)
 #define XBUILD_SMP_INTERRUPT(x,v)               \
 asmlinkage void x(void);                        \
@@ -92,7 +60,7 @@
     "\n"__ALIGN_STR"\n"                         \
     STR(x) ":\n\t"                              \
     "pushl $"#v"<<16\n\t"                       \
-    SAVE_ALL(a)                                 \
+    STR(SAVE_ALL(a))                            \
     "call "STR(smp_##x)"\n\t"                   \
     "jmp ret_from_intr\n");
 
@@ -103,7 +71,7 @@
 "\n"__ALIGN_STR"\n"                             \
 STR(x) ":\n\t"                                  \
     "pushl $"#v"<<16\n\t"                       \
-    SAVE_ALL(a)                                 \
+    STR(SAVE_ALL(a))                            \
     "movl %esp,%eax\n\t"                        \
     "pushl %eax\n\t"                            \
     "call "STR(smp_##x)"\n\t"                   \
@@ -114,7 +82,7 @@
 __asm__(                                        \
     "\n" __ALIGN_STR"\n"                        \
     "common_interrupt:\n\t"                     \
-    SAVE_ALL(a)                                 \
+    STR(SAVE_ALL(a))                            \
     "movl %esp,%eax\n\t"                        \
     "pushl %eax\n\t"                            \
     "call " STR(do_IRQ) "\n\t"                  \
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/x86_64/asm_defns.h
--- a/xen/include/asm-x86/x86_64/asm_defns.h    Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/x86_64/asm_defns.h    Fri Sep  9 16:30:54 2005
@@ -1,49 +1,14 @@
 #ifndef __X86_64_ASM_DEFNS_H__
 #define __X86_64_ASM_DEFNS_H__
 
-/* Maybe auto-generate the following two cases (quoted vs. unquoted). */
-#ifndef __ASSEMBLY__
-
-#define SAVE_ALL                                \
-        "cld;"                                  \
-        "pushq %rdi;"                           \
-        "pushq %rsi;"                           \
-        "pushq %rdx;"                           \
-        "pushq %rcx;"                           \
-        "pushq %rax;"                           \
-        "pushq %r8;"                            \
-        "pushq %r9;"                            \
-        "pushq %r10;"                           \
-        "pushq %r11;"                           \
-        "pushq %rbx;"                           \
-        "pushq %rbp;"                           \
-        "pushq %r12;"                           \
-        "pushq %r13;"                           \
-        "pushq %r14;"                           \
-        "pushq %r15;"
-
-#define RESTORE_ALL                             \
-        "popq  %r15;"                           \
-        "popq  %r14;"                           \
-        "popq  %r13;"                           \
-        "popq  %r12;"                           \
-        "popq  %rbp;"                           \
-        "popq  %rbx;"                           \
-        "popq  %r11;"                           \
-        "popq  %r10;"                           \
-        "popq  %r9;"                            \
-        "popq  %r8;"                            \
-        "popq  %rax;"                           \
-        "popq  %rcx;"                           \
-        "popq  %rdx;"                           \
-        "popq  %rsi;"                           \
-        "popq  %rdi;"
-
-/* Work around AMD erratum #88 */
-#define safe_swapgs                             \
-        "mfence; swapgs;"
-
+#ifndef NDEBUG
+/* Indicate special exception stack frame by inverting the frame pointer. */
+#define SETUP_EXCEPTION_FRAME_POINTER           \
+        movq  %rsp,%rbp;                        \
+        notq  %rbp
 #else
+#define SETUP_EXCEPTION_FRAME_POINTER
+#endif
 
 #define SAVE_ALL                                \
         cld;                                    \
@@ -58,6 +23,7 @@
         pushq %r11;                             \
         pushq %rbx;                             \
         pushq %rbp;                             \
+        SETUP_EXCEPTION_FRAME_POINTER;          \
         pushq %r12;                             \
         pushq %r13;                             \
         pushq %r14;                             \
@@ -90,7 +56,9 @@
 #define PERFC_INCR(_name,_idx)
 #endif
 
-#endif
+/* Work around AMD erratum #88 */
+#define safe_swapgs                             \
+        "mfence; swapgs;"
 
 #define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v)
 #define XBUILD_SMP_INTERRUPT(x,v)               \
@@ -100,7 +68,7 @@
     STR(x) ":\n\t"                              \
     "pushq $0\n\t"                              \
     "movl $"#v",4(%rsp)\n\t"                    \
-    SAVE_ALL                                    \
+    STR(SAVE_ALL)                               \
     "callq "STR(smp_##x)"\n\t"                  \
     "jmp ret_from_intr\n");
 
@@ -112,7 +80,7 @@
 STR(x) ":\n\t"                                  \
     "pushq $0\n\t"                              \
     "movl $"#v",4(%rsp)\n\t"                    \
-    SAVE_ALL                                    \
+    STR(SAVE_ALL)                               \
     "movq %rsp,%rdi\n\t"                        \
     "callq "STR(smp_##x)"\n\t"                  \
     "jmp ret_from_intr\n");
@@ -121,7 +89,7 @@
 __asm__(                                        \
     "\n" __ALIGN_STR"\n"                        \
     "common_interrupt:\n\t"                     \
-    SAVE_ALL                                    \
+    STR(SAVE_ALL)                               \
     "movq %rsp,%rdi\n\t"                        \
     "callq " STR(do_IRQ) "\n\t"                 \
     "jmp ret_from_intr\n");
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/acm.h
--- a/xen/include/public/acm.h  Thu Sep  8 15:18:40 2005
+++ b/xen/include/public/acm.h  Fri Sep  9 16:30:54 2005
@@ -56,20 +56,22 @@
 #define ACM_ACCESS_DENIED              -111
 #define ACM_NULL_POINTER_ERROR         -200
 
-#define ACM_MAX_POLICY  3
-
+/* primary policy in lower 4 bits */
 #define ACM_NULL_POLICY        0
 #define ACM_CHINESE_WALL_POLICY        1
 #define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2
-#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY 3
+
+/* combinations have secondary policy component in higher 4bit */
+#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY \
+    ((ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY << 4) | ACM_CHINESE_WALL_POLICY)
 
 /* policy: */
 #define ACM_POLICY_NAME(X) \
-       (X == ACM_NULL_POLICY) ? "NULL policy" : \
-       (X == ACM_CHINESE_WALL_POLICY) ? "CHINESE WALL policy" : \
-       (X == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "SIMPLE TYPE ENFORCEMENT 
policy" : \
-       (X == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "CHINESE 
WALL AND SIMPLE TYPE ENFORCEMENT policy" : \
-       "UNDEFINED policy"
+       ((X) == (ACM_NULL_POLICY)) ? "NULL policy" :                        \
+    ((X) == (ACM_CHINESE_WALL_POLICY)) ? "CHINESE WALL policy" :        \
+    ((X) == (ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "SIMPLE TYPE ENFORCEMENT 
policy" : \
+    ((X) == (ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "CHINESE 
WALL AND SIMPLE TYPE ENFORCEMENT policy" : \
+     "UNDEFINED policy"
 
 /* the following policy versions must be increased
  * whenever the interpretation of the related
@@ -122,7 +124,7 @@
  */
 struct acm_policy_buffer {
        u32 policy_version; /* ACM_POLICY_VERSION */
-        u32 magic;
+    u32 magic;
        u32 len;
        u32 primary_policy_code;
        u32 primary_buffer_offset;
@@ -151,7 +153,7 @@
 };
 
 struct acm_stats_buffer {
-        u32 magic;
+    u32 magic;
        u32 len;
        u32 primary_policy_code;
        u32 primary_stats_offset;
@@ -168,5 +170,15 @@
        u32 gt_cachehit_count;
 };
 
+struct acm_ssid_buffer {
+       u32 len;
+    ssidref_t ssidref;
+       u32 primary_policy_code;
+       u32 primary_max_types;
+    u32 primary_types_offset;
+       u32 secondary_policy_code;
+    u32 secondary_max_types;
+       u32 secondary_types_offset;
+};
 
 #endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/acm_ops.h
--- a/xen/include/public/acm_ops.h      Thu Sep  8 15:18:40 2005
+++ b/xen/include/public/acm_ops.h      Fri Sep  9 16:30:54 2005
@@ -1,3 +1,4 @@
+
 /******************************************************************************
  * acm_ops.h
  *
@@ -27,7 +28,7 @@
  * This makes sure that old versions of acm tools will stop working in a
  * well-defined way (rather than crashing the machine, for instance).
  */
-#define ACM_INTERFACE_VERSION   0xAAAA0003
+#define ACM_INTERFACE_VERSION   0xAAAA0004
 
 /************************************************************************/
 
@@ -46,12 +47,25 @@
     u16 pullcache_size;
 } acm_getpolicy_t;
 
+
 #define ACM_DUMPSTATS          6
 typedef struct acm_dumpstats {
     void *pullcache;
     u16 pullcache_size;
 } acm_dumpstats_t;
 
+
+#define ACM_GETSSID            7
+enum get_type {UNSET, SSIDREF, DOMAINID};
+typedef struct acm_getssid {
+       enum get_type get_ssid_by;
+       union {
+               domaintype_t domainid;
+               ssidref_t    ssidref;
+       } id;
+    void *ssidbuf;
+    u16 ssidbuf_size;
+} acm_getssid_t;
 
 typedef struct acm_op {
     u32 cmd;
@@ -60,6 +74,7 @@
         acm_setpolicy_t setpolicy;
         acm_getpolicy_t getpolicy;
         acm_dumpstats_t dumpstats;
+        acm_getssid_t getssid;
     } u;
 } acm_op_t;
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/arch-x86_32.h
--- a/xen/include/public/arch-x86_32.h  Thu Sep  8 15:18:40 2005
+++ b/xen/include/public/arch-x86_32.h  Fri Sep  9 16:30:54 2005
@@ -55,7 +55,7 @@
 # define HYPERVISOR_VIRT_START (0xFC000000UL)
 #endif
 #ifndef machine_to_phys_mapping
-#define machine_to_phys_mapping ((u32 *)HYPERVISOR_VIRT_START)
+#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
 #endif
 
 /* Maximum number of virtual CPUs in multi-processor guests. */
@@ -128,8 +128,11 @@
 } vcpu_guest_context_t;
 
 typedef struct arch_shared_info {
-    /* MFN of a table of MFNs that make up p2m table */
-    u64 pfn_to_mfn_frame_list;
+    unsigned long max_pfn;                  /* max pfn that appears in table */
+    unsigned long pfn_to_mfn_frame_list_list; 
+                                            /* frame containing list of mfns
+                                              containing list of mfns 
+                                              containing the p2m table. */
 } arch_shared_info_t;
 
 #endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/arch-x86_64.h
--- a/xen/include/public/arch-x86_64.h  Thu Sep  8 15:18:40 2005
+++ b/xen/include/public/arch-x86_64.h  Fri Sep  9 16:30:54 2005
@@ -71,7 +71,7 @@
 
 /* The machine->physical mapping table starts at this address, read-only. */
 #ifndef machine_to_phys_mapping
-#define machine_to_phys_mapping ((u32 *)HYPERVISOR_VIRT_START)
+#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
 #endif
 
 /*
@@ -186,8 +186,11 @@
 } vcpu_guest_context_t;
 
 typedef struct arch_shared_info {
-    /* MFN of a table of MFNs that make up p2m table */
-    u64 pfn_to_mfn_frame_list;
+    unsigned long max_pfn;                  /* max pfn that appears in table */
+    unsigned long pfn_to_mfn_frame_list_list; 
+                                            /* frame containing list of mfns
+                                              containing list of mfns 
+                                              containing the p2m table. */
 } arch_shared_info_t;
 
 #endif /* !__ASSEMBLY__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h     Thu Sep  8 15:18:40 2005
+++ b/xen/include/public/dom0_ops.h     Fri Sep  9 16:30:54 2005
@@ -213,6 +213,7 @@
     u32      cpu_khz;
     unsigned long total_pages;
     unsigned long free_pages;
+    u32      hw_cap[8];
 } dom0_physinfo_t;
 
 /*
@@ -373,6 +374,18 @@
     /* IN variables. */
     int quirk_id;
 } dom0_platform_quirk_t;
+
+#define DOM0_PHYSICAL_MEMORY_MAP 40
+typedef struct {
+    /* IN variables. */
+    int max_map_entries;
+    /* OUT variables. */
+    int nr_map_entries;
+    struct dom0_memory_map_entry {
+        u64 start, end;
+        int is_ram;
+    } *memory_map;
+} dom0_physical_memory_map_t;
 
 typedef struct {
     u32 cmd;
@@ -408,6 +421,7 @@
         dom0_getvcpucontext_t    getvcpucontext;
         dom0_getdomaininfolist_t getdomaininfolist;
         dom0_platform_quirk_t    platform_quirk;
+        dom0_physical_memory_map_t physical_memory_map;
     } u;
 } dom0_op_t;
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/io/ioreq.h
--- a/xen/include/public/io/ioreq.h     Thu Sep  8 15:18:40 2005
+++ b/xen/include/public/io/ioreq.h     Fri Sep  9 16:30:54 2005
@@ -29,9 +29,17 @@
 #define STATE_IORESP_READY      3
 #define STATE_IORESP_HOOK       4
 
-/* VMExit dispatcher should cooperate with instruction decoder to
-   prepare this structure and notify service OS and DM by sending
-   virq */
+#define IOREQ_TYPE_PIO         0       /* pio */
+#define IOREQ_TYPE_COPY                1       /* mmio ops */
+#define IOREQ_TYPE_AND         2
+#define IOREQ_TYPE_OR          3
+#define IOREQ_TYPE_XOR         4
+
+/*
+ * VMExit dispatcher should cooperate with instruction decoder to
+ * prepare this structure and notify service OS and DM by sending
+ * virq 
+ */
 typedef struct {
     u64     addr;               /*  physical address            */
     u64     size;               /*  size in bytes               */
@@ -43,8 +51,8 @@
     u8      state:4;
     u8      pdata_valid:1;     /* if 1, use pdata above        */
     u8      dir:1;             /*  1=read, 0=write             */
-    u8      port_mm:1;         /*  0=portio, 1=mmio            */
     u8      df:1;
+    u8      type;              /* I/O type                     */
 } ioreq_t;
 
 #define MAX_VECTOR    256
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/io/netif.h
--- a/xen/include/public/io/netif.h     Thu Sep  8 15:18:40 2005
+++ b/xen/include/public/io/netif.h     Fri Sep  9 16:30:54 2005
@@ -23,13 +23,13 @@
 
 typedef struct {
     u16       id;    /* Echoed in response message.        */
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     grant_ref_t gref;  /* 2: Reference to incoming granted frame */
 #endif
 } netif_rx_request_t;
 
 typedef struct {
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
     u32      addr;   /*  0: Offset in page of start of received packet  */
 #else
     unsigned long addr; /* Machine address of packet.              */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/trace.h
--- a/xen/include/public/trace.h        Thu Sep  8 15:18:40 2005
+++ b/xen/include/public/trace.h        Fri Sep  9 16:30:54 2005
@@ -23,7 +23,7 @@
 #define TRC_VMXTIMER 0x00082000   /* VMX timer trace           */
 #define TRC_VMXINT   0x00084000   /* VMX interrupt trace       */
 #define TRC_VMXIO    0x00088000   /* VMX io emulation trace  */
-
+#define TRC_VMEXIT_HANDLER    0x00090000   /* VMX handler trace  */
 
 /* Trace events per class */
 
@@ -49,6 +49,10 @@
 
 #define TRC_VMX_INT             (TRC_VMXINT + 1)
 
+#define TRC_VMEXIT              (TRC_VMEXIT_HANDLER + 1)
+#define TRC_VMENTRY             (TRC_VMEXIT_HANDLER + 2)
+
+
 /* This structure represents a single trace buffer record. */
 struct t_rec {
     u64 cycles;               /* cycle counter timestamp */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/version.h
--- a/xen/include/public/version.h      Thu Sep  8 15:18:40 2005
+++ b/xen/include/public/version.h      Fri Sep  9 16:30:54 2005
@@ -28,4 +28,17 @@
     char compile_date[32];
 } xen_compile_info_t;
 
+#define XENVER_capabilities 3
+typedef struct xen_capabilities_info {
+    char caps[1024];
+} xen_capabilities_info_t;
+
+#define XENVER_changeset 4
+typedef char xen_changeset_info_t[64];
+
+#define XENVER_parameters 5
+typedef struct xen_paramaters_info {
+unsigned long virt_start;
+} xen_parameters_info_t;
+
 #endif /* __XEN_PUBLIC_VERSION_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/xen.h
--- a/xen/include/public/xen.h  Thu Sep  8 15:18:40 2005
+++ b/xen/include/public/xen.h  Fri Sep  9 16:30:54 2005
@@ -42,7 +42,7 @@
 #define __HYPERVISOR_set_debugreg          8
 #define __HYPERVISOR_get_debugreg          9
 #define __HYPERVISOR_update_descriptor    10
-#define __HYPERVISOR_dom_mem_op           12
+#define __HYPERVISOR_memory_op            12
 #define __HYPERVISOR_multicall            13
 #define __HYPERVISOR_update_va_mapping    14
 #define __HYPERVISOR_set_timer_op         15
@@ -223,12 +223,6 @@
  */
 #define CONSOLEIO_write         0
 #define CONSOLEIO_read          1
-
-/*
- * Commands to HYPERVISOR_dom_mem_op().
- */
-#define MEMOP_increase_reservation 0
-#define MEMOP_decrease_reservation 1
 
 /*
  * Commands to HYPERVISOR_vm_assist().
@@ -438,19 +432,20 @@
 #define MAX_GUEST_CMDLINE 1024
 typedef struct start_info {
     /* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME.    */
-    unsigned long nr_pages;   /* Total pages allocated to this domain.    */
-    unsigned long shared_info;/* MACHINE address of shared info struct.   */
-    u32      flags;           /* SIF_xxx flags.                           */
-    u16      domain_controller_evtchn;
+    unsigned long nr_pages;     /* Total pages allocated to this domain.  */
+    unsigned long shared_info;  /* MACHINE address of shared info struct. */
+    u32      flags;             /* SIF_xxx flags.                         */
+    unsigned long store_mfn;    /* MACHINE page number of shared page.    */
+    u16      store_evtchn;      /* Event channel for store communication. */
+    unsigned long console_mfn;  /* MACHINE address of console page.       */
+    u16      console_evtchn;    /* Event channel for console messages.    */
     /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME).     */
-    unsigned long pt_base;    /* VIRTUAL address of page directory.       */
-    unsigned long nr_pt_frames;/* Number of bootstrap p.t. frames.        */
-    unsigned long mfn_list;   /* VIRTUAL address of page-frame list.      */
-    unsigned long mod_start;  /* VIRTUAL address of pre-loaded module.    */
-    unsigned long mod_len;    /* Size (bytes) of pre-loaded module.       */
+    unsigned long pt_base;      /* VIRTUAL address of page directory.     */
+    unsigned long nr_pt_frames; /* Number of bootstrap p.t. frames.       */
+    unsigned long mfn_list;     /* VIRTUAL address of page-frame list.    */
+    unsigned long mod_start;    /* VIRTUAL address of pre-loaded module.  */
+    unsigned long mod_len;      /* Size (bytes) of pre-loaded module.     */
     s8 cmd_line[MAX_GUEST_CMDLINE];
-    unsigned long store_mfn;  /* MACHINE page number of shared page.      */
-    u16      store_evtchn;    /* Event channel for store communication.   */
 } start_info_t;
 
 /* These flags are passed in the 'flags' field of start_info_t. */
@@ -459,6 +454,7 @@
 #define SIF_BLK_BE_DOMAIN (1<<4)  /* Is this a block backend domain? */
 #define SIF_NET_BE_DOMAIN (1<<5)  /* Is this a net backend domain? */
 #define SIF_USB_BE_DOMAIN (1<<6)  /* Is this a usb backend domain? */
+#define SIF_TPM_BE_DOMAIN (1<<7)  /* Is this a TPM backend domain? */
 /* For use in guest OSes. */
 extern shared_info_t *HYPERVISOR_shared_info;
 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/xen/config.h
--- a/xen/include/xen/config.h  Thu Sep  8 15:18:40 2005
+++ b/xen/include/xen/config.h  Fri Sep  9 16:30:54 2005
@@ -40,4 +40,7 @@
 #include <xen/compiler.h>
 #endif
 
+#define __STR(...) #__VA_ARGS__
+#define STR(...) __STR(__VA_ARGS__)
+
 #endif /* __XEN_CONFIG_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/xen/perfc.h
--- a/xen/include/xen/perfc.h   Thu Sep  8 15:18:40 2005
+++ b/xen/include/xen/perfc.h   Fri Sep  9 16:30:54 2005
@@ -4,6 +4,7 @@
 
 #ifdef PERF_COUNTERS
 
+#include <xen/lib.h>
 #include <asm/atomic.h>
 
 /* 
@@ -87,7 +88,7 @@
  * Histogram: special treatment for 0 and 1 count. After that equally spaced 
  * with last bucket taking the rest.
  */
-#ifdef PERFC_ARRAYS
+#ifdef PERF_ARRAYS
 #define perfc_incr_histo(_x,_v,_n)                                          \
     do {                                                                    \
         if ( (_v) == 0 )                                                    \
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Thu Sep  8 15:18:40 2005
+++ b/xen/include/xen/sched.h   Fri Sep  9 16:30:54 2005
@@ -250,10 +250,11 @@
 void vcpu_sleep_sync(struct vcpu *d);
 
 /*
- * Force loading of currently-executing domain state on the specified CPU.
- * This is used to counteract lazy state switching where required.
- */
-extern void sync_lazy_execstate_cpu(unsigned int cpu);
+ * Force synchronisation of given VCPU's state. If it is currently descheduled,
+ * this call will ensure that all its state is committed to memory and that
+ * no CPU is using critical state (e.g., page tables) belonging to the VCPU.
+ */
+extern void sync_vcpu_execstate(struct vcpu *v);
 
 /*
  * Called by the scheduler to switch to another VCPU. On entry, although
@@ -265,7 +266,7 @@
  * The callee must ensure that the local CPU is no longer running in @prev's
  * context, and that the context is saved to memory, before returning.
  * Alternatively, if implementing lazy context switching, it suffices to ensure
- * that invoking sync_lazy_execstate() will switch and commit @prev's state.
+ * that invoking sync_vcpu_execstate() will switch and commit @prev's state.
  */
 extern void context_switch(
     struct vcpu *prev, 
diff -r 10b1d30d3f66 -r b2f4823b6ff0 docs/misc/vtpm.txt
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/docs/misc/vtpm.txt        Fri Sep  9 16:30:54 2005
@@ -0,0 +1,122 @@
+Copyright: IBM Corporation (C), Intel Corporation
+17 August 2005
+Authors: Stefan Berger <stefanb@xxxxxxxxxx> (IBM), 
+         Employees of Intel Corp
+
+This document gives a short introduction to the virtual TPM support
+in XEN and goes as far as connecting a user domain to a virtual TPM
+instance and doing a short test to verify success. It is assumed
+that the user is fairly familiar with compiling and installing XEN
+and Linux on a machine. 
+ 
+Production Prerequisites: An x86-based machine machine with an ATMEL or
+National Semiconductor (NSC) TPM on the motherboard.
+Development Prerequisites: An emulator for TESTING ONLY is provided
+
+
+Compiling XEN tree:
+-------------------
+
+Compile the XEN tree as usual.
+
+make uninstall; make mrproper; make install 
+
+After compiling the tree, verify that in the linux-2.6.XX-xen0/.config 
+file at least the following entries are set as below (they should be set
+by default):
+
+CONFIG_XEN_TPMDEV_BACKEND=y
+CONFIG_XEN_TPMDEV_GRANT=y
+
+CONFIG_TCG_TPM=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+
+
+Verify that in the linux-2.6.XX-xenU/.config file at least the 
+Following entries are set as below (they should be set by default):
+
+CONFIG_XEN_TPMDEV_FRONTEND=y
+CONFIG_XEN_TPMDEV_GRANT=y
+
+CONFIG_TCG_TPM=y
+CONFIG_TCG_XEN=y
+
+
+Reboot the machine with the created XEN-0 kernel.
+
+Note: If you do not want any TPM-related code compiled into your
+kernel or built as module then comment all the above lines like
+this example:
+# CONFIG_TCG_TPM is not set
+
+
+Modifying VM Configuration files:
+---------------------------------
+
+VM configuration files need to be adapted to make a TPM instance
+available to a user domain. The following VM configuration file is
+an example of how a user domain can be configured to have a TPM
+available. It works similar to making a network interface
+available to a domain.
+
+kernel = "/boot/vmlinuz-2.6.12-xenU"
+ramdisk = "/xen/initrd_domU/U1_ramdisk.img"
+memory = 32
+name = "TPMUserDomain0"
+vtpm = ['instance=1,backend=0']
+root = "/dev/ram0 cosole=tty ro"
+vif = ['backend=0']
+
+In the above configuration file the line 'vtpm = ...' provides
+information about the domain where the virtual TPM is running and
+where the TPM backend has been compiled into - this has to be 
+domain 0  at the moment - and which TPM instance the user domain
+is supposed to talk to. Note that each running VM must use a 
+different instance and that using instance 0 is NOT allowed.
+
+Note: If you do not want TPM functionality for your user domain simply
+leave out the 'vtpm' line in the configuration file.
+
+
+Running the TPM:
+----------------
+
+To run the vTPM, dev device /dev/vtpm must be available.
+Verify that 'ls -l /dev/vtpm' shows the following output:
+
+crw-------  1 root root 10, 225 Aug 11 06:58 /dev/vtpm
+
+If it is not available, run the following command as 'root'.
+mknod /dev/vtpm c 10 225
+
+Make sure that the vTPM is running in domain 0. To do this run the
+following
+
+/usr/bin/vtpm_managerd
+
+Start a user domain using the 'xm create' command. Once you are in the
+shell of the user domain, you should be able to do the following:
+
+> cd /sys/devices/vtpm
+> ls
+cancel  caps   pcrs    pubek
+> cat pcrs
+PCR-00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-01: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-02: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-03: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-04: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-05: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-06: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-07: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-08: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[...]
+
+At this point the user domain has been sucessfully connected to its
+virtual TPM instance.
+
+For further information please read the documentation in 
+tools/vtpm_manager/README and tools/vtpm/README
+
+Stefan Berger and Employees of the Intel Corp
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/domain_config
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/domain_config      Fri Sep  9 16:30:54 2005
@@ -0,0 +1,17 @@
+#  -*- mode: python; -*-
+#============================================================================
+# Python configuration setup for 'xm create'.
+# This script sets the parameters used when a domain is created using 'xm 
create'.
+# You use a separate script for each domain you want to create, or 
+# you can set the parameters for the domain on the xm command line.
+#============================================================================
+
+#----------------------------------------------------------------------------
+# Kernel image file.
+kernel = "mini-os.elf"
+
+# Initial memory allocation (in megabytes) for the new domain.
+memory = 32
+
+# A name for your domain. All domains must have different names.
+name = "Mini-OS"
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/ctype.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/ctype.h    Fri Sep  9 16:30:54 2005
@@ -0,0 +1,79 @@
+#ifndef _CTYPE_H
+#define _CTYPE_H
+
+/*
+ * NOTE! This ctype does not handle EOF like the standard C
+ * library is required to.
+ */
+
+#define _U     0x01    /* upper */
+#define _L     0x02    /* lower */
+#define _D     0x04    /* digit */
+#define _C     0x08    /* cntrl */
+#define _P     0x10    /* punct */
+#define _S     0x20    /* white space (space/lf/tab) */
+#define _X     0x40    /* hex digit */
+#define _SP    0x80    /* hard space (0x20) */
+
+
+unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C,                        /* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,         /* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C,                        /* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C,                        /* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,                    /* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P,                        /* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D,                        /* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P,                        /* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,      /* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U,                        /* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U,                        /* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P,                        /* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,      /* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L,                        /* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L,                        /* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C,                        /* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
+
+#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
+
+#define isalnum(c)     ((__ismask(c)&(_U|_L|_D)) != 0)
+#define isalpha(c)     ((__ismask(c)&(_U|_L)) != 0)
+#define iscntrl(c)     ((__ismask(c)&(_C)) != 0)
+#define isdigit(c)     ((__ismask(c)&(_D)) != 0)
+#define isgraph(c)     ((__ismask(c)&(_P|_U|_L|_D)) != 0)
+#define islower(c)     ((__ismask(c)&(_L)) != 0)
+#define isprint(c)     ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
+#define ispunct(c)     ((__ismask(c)&(_P)) != 0)
+#define isspace(c)     ((__ismask(c)&(_S)) != 0)
+#define isupper(c)     ((__ismask(c)&(_U)) != 0)
+#define isxdigit(c)    ((__ismask(c)&(_D|_X)) != 0)
+
+#define isascii(c) (((unsigned char)(c))<=0x7f)
+#define toascii(c) (((unsigned char)(c))&0x7f)
+
+static inline unsigned char __tolower(unsigned char c)
+{
+       if (isupper(c))
+               c -= 'A'-'a';
+       return c;
+}
+
+static inline unsigned char __toupper(unsigned char c)
+{
+       if (islower(c))
+               c -= 'a'-'A';
+       return c;
+}
+
+#define tolower(c) __tolower(c)
+#define toupper(c) __toupper(c)
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/err.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/err.h      Fri Sep  9 16:30:54 2005
@@ -0,0 +1,31 @@
+#ifndef _ERR_H
+#define _ERR_H
+
+#include <errno.h>
+
+/*
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a dentry
+ * pointer with the same return value.
+ *
+ * This should be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ */
+#define IS_ERR_VALUE(x) ((x) > (unsigned long)-1000L)
+
+static inline void *ERR_PTR(long error)
+{
+       return (void *) error;
+}
+
+static inline long PTR_ERR(const void *ptr)
+{
+       return (long) ptr;
+}
+
+static inline long IS_ERR(const void *ptr)
+{
+       return IS_ERR_VALUE((unsigned long)ptr);
+}
+
+#endif /* _LINUX_ERR_H */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/errno-base.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/errno-base.h       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,39 @@
+#ifndef _ERRNO_BASE_H
+#define _ERRNO_BASE_H
+
+#define        EPERM            1      /* Operation not permitted */
+#define        ENOENT           2      /* No such file or directory */
+#define        ESRCH            3      /* No such process */
+#define        EINTR            4      /* Interrupted system call */
+#define        EIO              5      /* I/O error */
+#define        ENXIO            6      /* No such device or address */
+#define        E2BIG            7      /* Argument list too long */
+#define        ENOEXEC          8      /* Exec format error */
+#define        EBADF            9      /* Bad file number */
+#define        ECHILD          10      /* No child processes */
+#define        EAGAIN          11      /* Try again */
+#define        ENOMEM          12      /* Out of memory */
+#define        EACCES          13      /* Permission denied */
+#define        EFAULT          14      /* Bad address */
+#define        ENOTBLK         15      /* Block device required */
+#define        EBUSY           16      /* Device or resource busy */
+#define        EEXIST          17      /* File exists */
+#define        EXDEV           18      /* Cross-device link */
+#define        ENODEV          19      /* No such device */
+#define        ENOTDIR         20      /* Not a directory */
+#define        EISDIR          21      /* Is a directory */
+#define        EINVAL          22      /* Invalid argument */
+#define        ENFILE          23      /* File table overflow */
+#define        EMFILE          24      /* Too many open files */
+#define        ENOTTY          25      /* Not a typewriter */
+#define        ETXTBSY         26      /* Text file busy */
+#define        EFBIG           27      /* File too large */
+#define        ENOSPC          28      /* No space left on device */
+#define        ESPIPE          29      /* Illegal seek */
+#define        EROFS           30      /* Read-only file system */
+#define        EMLINK          31      /* Too many links */
+#define        EPIPE           32      /* Broken pipe */
+#define        EDOM            33      /* Math argument out of domain of func 
*/
+#define        ERANGE          34      /* Math result not representable */
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/errno.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/errno.h    Fri Sep  9 16:30:54 2005
@@ -0,0 +1,109 @@
+#ifndef _ERRNO_H
+#define _ERRNO_H
+
+#include <errno-base.h>
+
+#define        EDEADLK         35      /* Resource deadlock would occur */
+#define        ENAMETOOLONG    36      /* File name too long */
+#define        ENOLCK          37      /* No record locks available */
+#define        ENOSYS          38      /* Function not implemented */
+#define        ENOTEMPTY       39      /* Directory not empty */
+#define        ELOOP           40      /* Too many symbolic links encountered 
*/
+#define        EWOULDBLOCK     EAGAIN  /* Operation would block */
+#define        ENOMSG          42      /* No message of desired type */
+#define        EIDRM           43      /* Identifier removed */
+#define        ECHRNG          44      /* Channel number out of range */
+#define        EL2NSYNC        45      /* Level 2 not synchronized */
+#define        EL3HLT          46      /* Level 3 halted */
+#define        EL3RST          47      /* Level 3 reset */
+#define        ELNRNG          48      /* Link number out of range */
+#define        EUNATCH         49      /* Protocol driver not attached */
+#define        ENOCSI          50      /* No CSI structure available */
+#define        EL2HLT          51      /* Level 2 halted */
+#define        EBADE           52      /* Invalid exchange */
+#define        EBADR           53      /* Invalid request descriptor */
+#define        EXFULL          54      /* Exchange full */
+#define        ENOANO          55      /* No anode */
+#define        EBADRQC         56      /* Invalid request code */
+#define        EBADSLT         57      /* Invalid slot */
+
+#define        EDEADLOCK       EDEADLK
+
+#define        EBFONT          59      /* Bad font file format */
+#define        ENOSTR          60      /* Device not a stream */
+#define        ENODATA         61      /* No data available */
+#define        ETIME           62      /* Timer expired */
+#define        ENOSR           63      /* Out of streams resources */
+#define        ENONET          64      /* Machine is not on the network */
+#define        ENOPKG          65      /* Package not installed */
+#define        EREMOTE         66      /* Object is remote */
+#define        ENOLINK         67      /* Link has been severed */
+#define        EADV            68      /* Advertise error */
+#define        ESRMNT          69      /* Srmount error */
+#define        ECOMM           70      /* Communication error on send */
+#define        EPROTO          71      /* Protocol error */
+#define        EMULTIHOP       72      /* Multihop attempted */
+#define        EDOTDOT         73      /* RFS specific error */
+#define        EBADMSG         74      /* Not a data message */
+#define        EOVERFLOW       75      /* Value too large for defined data 
type */
+#define        ENOTUNIQ        76      /* Name not unique on network */
+#define        EBADFD          77      /* File descriptor in bad state */
+#define        EREMCHG         78      /* Remote address changed */
+#define        ELIBACC         79      /* Can not access a needed shared 
library */
+#define        ELIBBAD         80      /* Accessing a corrupted shared library 
*/
+#define        ELIBSCN         81      /* .lib section in a.out corrupted */
+#define        ELIBMAX         82      /* Attempting to link in too many 
shared libraries */
+#define        ELIBEXEC        83      /* Cannot exec a shared library 
directly */
+#define        EILSEQ          84      /* Illegal byte sequence */
+#define        ERESTART        85      /* Interrupted system call should be 
restarted */
+#define        ESTRPIPE        86      /* Streams pipe error */
+#define        EUSERS          87      /* Too many users */
+#define        ENOTSOCK        88      /* Socket operation on non-socket */
+#define        EDESTADDRREQ    89      /* Destination address required */
+#define        EMSGSIZE        90      /* Message too long */
+#define        EPROTOTYPE      91      /* Protocol wrong type for socket */
+#define        ENOPROTOOPT     92      /* Protocol not available */
+#define        EPROTONOSUPPORT 93      /* Protocol not supported */
+#define        ESOCKTNOSUPPORT 94      /* Socket type not supported */
+#define        EOPNOTSUPP      95      /* Operation not supported on transport 
endpoint */
+#define        EPFNOSUPPORT    96      /* Protocol family not supported */
+#define        EAFNOSUPPORT    97      /* Address family not supported by 
protocol */
+#define        EADDRINUSE      98      /* Address already in use */
+#define        EADDRNOTAVAIL   99      /* Cannot assign requested address */
+#define        ENETDOWN        100     /* Network is down */
+#define        ENETUNREACH     101     /* Network is unreachable */
+#define        ENETRESET       102     /* Network dropped connection because 
of reset */
+#define        ECONNABORTED    103     /* Software caused connection abort */
+#define        ECONNRESET      104     /* Connection reset by peer */
+#define        ENOBUFS         105     /* No buffer space available */
+#define        EISCONN         106     /* Transport endpoint is already 
connected */
+#define        ENOTCONN        107     /* Transport endpoint is not connected 
*/
+#define        ESHUTDOWN       108     /* Cannot send after transport endpoint 
shutdown */
+#define        ETOOMANYREFS    109     /* Too many references: cannot splice */
+#define        ETIMEDOUT       110     /* Connection timed out */
+#define        ECONNREFUSED    111     /* Connection refused */
+#define        EHOSTDOWN       112     /* Host is down */
+#define        EHOSTUNREACH    113     /* No route to host */
+#define        EALREADY        114     /* Operation already in progress */
+#define        EINPROGRESS     115     /* Operation now in progress */
+#define        ESTALE          116     /* Stale NFS file handle */
+#define        EUCLEAN         117     /* Structure needs cleaning */
+#define        ENOTNAM         118     /* Not a XENIX named type file */
+#define        ENAVAIL         119     /* No XENIX semaphores available */
+#define        EISNAM          120     /* Is a named type file */
+#define        EREMOTEIO       121     /* Remote I/O error */
+#define        EDQUOT          122     /* Quota exceeded */
+
+#define        ENOMEDIUM       123     /* No medium found */
+#define        EMEDIUMTYPE     124     /* Wrong medium type */
+#define        ECANCELED       125     /* Operation Canceled */
+#define        ENOKEY          126     /* Required key not available */
+#define        EKEYEXPIRED     127     /* Key has expired */
+#define        EKEYREVOKED     128     /* Key has been revoked */
+#define        EKEYREJECTED    129     /* Key was rejected by service */
+
+/* for robust mutexes */
+#define        EOWNERDEAD      130     /* Owner died */
+#define        ENOTRECOVERABLE 131     /* State not recoverable */
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/fcntl.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/fcntl.h    Fri Sep  9 16:30:54 2005
@@ -0,0 +1,89 @@
+#ifndef _I386_FCNTL_H
+#define _I386_FCNTL_H
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_ACCMODE         0003
+#define O_RDONLY            00
+#define O_WRONLY            01
+#define O_RDWR              02
+#define O_CREAT                   0100 /* not fcntl */
+#define O_EXCL            0200 /* not fcntl */
+#define O_NOCTTY          0400 /* not fcntl */
+#define O_TRUNC                  01000 /* not fcntl */
+#define O_APPEND         02000
+#define O_NONBLOCK       04000
+#define O_NDELAY       O_NONBLOCK
+#define O_SYNC          010000
+#define FASYNC          020000 /* fcntl, for BSD compatibility */
+#define O_DIRECT        040000 /* direct disk access hint */
+#define O_LARGEFILE    0100000
+#define O_DIRECTORY    0200000 /* must be a directory */
+#define O_NOFOLLOW     0400000 /* don't follow links */
+#define O_NOATIME      01000000
+
+#define F_DUPFD                0       /* dup */
+#define F_GETFD                1       /* get close_on_exec */
+#define F_SETFD                2       /* set/clear close_on_exec */
+#define F_GETFL                3       /* get file->f_flags */
+#define F_SETFL                4       /* set file->f_flags */
+#define F_GETLK                5
+#define F_SETLK                6
+#define F_SETLKW       7
+
+#define F_SETOWN       8       /*  for sockets. */
+#define F_GETOWN       9       /*  for sockets. */
+#define F_SETSIG       10      /*  for sockets. */
+#define F_GETSIG       11      /*  for sockets. */
+
+#define F_GETLK64      12      /*  using 'struct flock64' */
+#define F_SETLK64      13
+#define F_SETLKW64     14
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK                0
+#define F_WRLCK                1
+#define F_UNLCK                2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK                4       /* or 3 */
+#define F_SHLCK                8       /* or 4 */
+
+/* for leases */
+#define F_INPROGRESS   16
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH                1       /* shared lock */
+#define LOCK_EX                2       /* exclusive lock */
+#define LOCK_NB                4       /* or'd with one of the above to prevent
+                                  blocking */
+#define LOCK_UN                8       /* remove lock */
+
+#define LOCK_MAND      32      /* This is a mandatory flock */
+#define LOCK_READ      64      /* ... Which allows concurrent read operations 
*/
+#define LOCK_WRITE     128     /* ... Which allows concurrent write operations 
*/
+#define LOCK_RW                192     /* ... Which allows concurrent read & 
write ops */
+
+/*
+struct flock {
+       short l_type;
+       short l_whence;
+       off_t l_start;
+       off_t l_len;
+       pid_t l_pid;
+};
+
+struct flock64 {
+       short  l_type;
+       short  l_whence;
+       loff_t l_start;
+       loff_t l_len;
+       pid_t  l_pid;
+};
+
+#define F_LINUX_SPECIFIC_BASE  1024
+*/
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/list.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/list.h     Fri Sep  9 16:30:54 2005
@@ -0,0 +1,184 @@
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+       struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+       (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries. 
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_add(struct list_head * new,
+       struct list_head * prev,
+       struct list_head * next)
+{
+       next->prev = new;
+       new->next = next;
+       new->prev = prev;
+       prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static __inline__ void list_add(struct list_head *new, struct list_head *head)
+{
+       __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static __inline__ void list_add_tail(struct list_head *new, struct list_head 
*head)
+{
+       __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_del(struct list_head * prev,
+                                 struct list_head * next)
+{
+       next->prev = prev;
+       prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is in 
an undefined state.
+ */
+static __inline__ void list_del(struct list_head *entry)
+{
+       __list_del(entry->prev, entry->next);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static __inline__ void list_del_init(struct list_head *entry)
+{
+       __list_del(entry->prev, entry->next);
+       INIT_LIST_HEAD(entry); 
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static __inline__ int list_empty(struct list_head *head)
+{
+       return head->next == head;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static __inline__ void list_splice(struct list_head *list, struct list_head 
*head)
+{
+       struct list_head *first = list->next;
+
+       if (first != list) {
+               struct list_head *last = list->prev;
+               struct list_head *at = head->next;
+
+               first->prev = head;
+               head->next = first;
+
+               last->next = at;
+               at->prev = last;
+       }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:       the &struct list_head pointer.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+       ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+/**
+ * list_for_each       -       iterate over a list
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @head:      the head for your list.
+ */
+#define list_for_each(pos, head) \
+       for (pos = (head)->next; pos != (head); pos = pos->next)
+               
+/**
+ * list_for_each_safe  -       iterate over a list safe against removal of 
list entry
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @n:         another &struct list_head to use as temporary storage
+ * @head:      the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+       for (pos = (head)->next, n = pos->next; pos != (head); \
+               pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry -       iterate over list of given type
+ * @pos:       the type * to use as a loop counter.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)                         \
+       for (pos = list_entry((head)->next, typeof(*pos), member);      \
+            &pos->member != (head);                                    \
+            pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against 
removal of list entry
+ * @pos:       the type * to use as a loop counter.
+ * @n:         another type * to use as temporary storage
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member)                 \
+       for (pos = list_entry((head)->next, typeof(*pos), member),      \
+               n = list_entry(pos->member.next, typeof(*pos), member); \
+            &pos->member != (head);                                    \
+            pos = n, n = list_entry(n->member.next, typeof(*n), member))
+#endif /* _LINUX_LIST_H */
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/sched.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/sched.h    Fri Sep  9 16:30:54 2005
@@ -0,0 +1,38 @@
+#ifndef __SCHED_H__
+#define __SCHED_H__
+
+#include <list.h>
+
+struct thread
+{
+    char *name;
+    char *stack;
+    unsigned long eps;
+    unsigned long eip;
+    struct list_head thread_list;
+    u32 flags;
+};
+
+
+
+void init_sched(void);
+void run_idle_thread(void);
+struct thread* create_thread(char *name, void (*function)(void *), void *data);
+void schedule(void);
+
+static inline struct thread* get_current(void)
+{
+    struct thread **current;
+#ifdef __i386__    
+    __asm__("andl %%esp,%0; ":"=r" (current) : "r" (~8191UL));
+#endif    
+    return *current;
+}
+          
+#define current get_current()
+
+
+void wake(struct thread *thread);
+void block(struct thread *thread);
+
+#endif /* __SCHED_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/semaphore.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/semaphore.h        Fri Sep  9 16:30:54 2005
@@ -0,0 +1,46 @@
+#ifndef _SEMAPHORE_H_
+#define _SEMAPHORE_H_
+
+#include <wait.h>
+
+/*
+ * Implementation of semaphore in Mini-os is simple, because 
+ * there are no preemptive threads, the atomicity is guaranteed.
+ */
+
+struct semaphore
+{
+       int count;
+       struct wait_queue_head wait;
+};
+
+
+#define __SEMAPHORE_INITIALIZER(name, n)                            \
+{                                                                   \
+    .count    = n,                                                  \
+    .wait           = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+}
+
+#define __MUTEX_INITIALIZER(name) \
+    __SEMAPHORE_INITIALIZER(name,1)
+                           
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+    struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+    
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+static void inline down(struct semaphore *sem)
+{
+    wait_event(sem->wait, sem->count > 0);
+    sem->count--;
+}
+
+static void inline up(struct semaphore *sem)
+{
+    sem->count++;
+    wake_up(&sem->wait);
+}
+
+#endif /* _SEMAPHORE_H */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/wait.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/wait.h     Fri Sep  9 16:30:54 2005
@@ -0,0 +1,91 @@
+#ifndef __WAIT_H__
+#define __WAIT_H__
+
+#include <sched.h>
+#include <list.h>
+#include <lib.h>
+#include <os.h>
+
+struct wait_queue
+{
+    struct thread *thread;
+    struct list_head thread_list;
+};
+
+struct wait_queue_head
+{
+    /* TODO - lock required? */
+    struct list_head thread_list;
+};
+
+#define DECLARE_WAIT_QUEUE_HEAD(name) \
+   struct wait_queue_head name =     \
+        { .thread_list = { &(name).thread_list, &(name).thread_list} }
+
+#define __WAIT_QUEUE_HEAD_INITIALIZER(name) {                           \
+    .thread_list      = { &(name).thread_list, &(name).thread_list } }
+
+
+#define DEFINE_WAIT(name)                               \
+struct wait_queue name = {                              \
+    .thread       = current,                            \
+    .thread_list  = LIST_HEAD_INIT((name).thread_list), \
+}
+
+
+
+static inline void init_waitqueue_entry(struct wait_queue *q, struct thread 
*thread)
+{
+    q->thread = thread;
+}
+
+
+static inline void add_wait_queue(struct wait_queue_head *h, struct wait_queue 
*q)
+{
+    if (list_empty(&q->thread_list))
+        list_add(&q->thread_list, &h->thread_list);   
+}
+
+static inline void remove_wait_queue(struct wait_queue *q)
+{
+    list_del(&q->thread_list);
+}
+
+static inline void wake_up(struct wait_queue_head *head)
+{
+    struct list_head *tmp, *next;
+    list_for_each_safe(tmp, next, &head->thread_list)
+    {
+         struct wait_queue *curr;
+         curr = list_entry(tmp, struct wait_queue, thread_list);
+         wake(curr->thread);
+    }
+}
+
+#define wait_event(wq, condition) do{             \
+    unsigned long flags;                          \
+    if(condition)                                 \
+        break;                                    \
+    DEFINE_WAIT(__wait);                          \
+    for(;;)                                       \
+    {                                             \
+        /* protect the list */                    \
+        local_irq_save(flags);                    \
+        add_wait_queue(&wq, &__wait);             \
+        block(current);                           \
+        local_irq_restore(flags);                 \
+        if(condition)                             \
+            break;                                \
+        schedule();                               \
+    }                                             \
+    local_irq_save(flags);                        \
+    /* need to wake up */                         \
+    wake(current);                                \
+    remove_wait_queue(&__wait);                   \
+    local_irq_restore(flags);                     \
+} while(0) 
+
+
+
+
+#endif /* __WAIT_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/xenbus.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/include/xenbus.h   Fri Sep  9 16:30:54 2005
@@ -0,0 +1,89 @@
+/******************************************************************************
+ * xenbus.h
+ *
+ * Talks to Xen Store to figure out what devices we have.
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef _ASM_XEN_XENBUS_H
+#define _ASM_XEN_XENBUS_H
+
+
+/* Caller must hold this lock to call these functions: it's also held
+ * across watch callbacks. */
+// TODO
+//extern struct semaphore xenbus_lock;
+
+char **xenbus_directory(const char *dir, const char *node, unsigned int *num);
+void *xenbus_read(const char *dir, const char *node, unsigned int *len);
+int xenbus_write(const char *dir, const char *node,
+                const char *string, int createflags);
+int xenbus_mkdir(const char *dir, const char *node);
+int xenbus_exists(const char *dir, const char *node);
+int xenbus_rm(const char *dir, const char *node);
+int xenbus_transaction_start(const char *subtree);
+int xenbus_transaction_end(int abort);
+
+/* Single read and scanf: returns -errno or num scanned if > 0. */
+int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
+       __attribute__((format(scanf, 3, 4)));
+
+/* Single printf and write: returns -errno or 0. */
+int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
+       __attribute__((format(printf, 3, 4)));
+
+/* Generic read function: NULL-terminated triples of name,
+ * sprintf-style type string, and pointer. Returns 0 or errno.*/
+int xenbus_gather(const char *dir, ...);
+
+/* Register callback to watch this node. */
+struct xenbus_watch
+{
+       struct list_head list;
+       char *node;
+       void (*callback)(struct xenbus_watch *, const char *node);
+};
+
+int register_xenbus_watch(struct xenbus_watch *watch);
+void unregister_xenbus_watch(struct xenbus_watch *watch);
+void reregister_xenbus_watches(void);
+
+/* Called from xen core code. */
+void xenbus_suspend(void);
+void xenbus_resume(void);
+
+#define XENBUS_IS_ERR_READ(str) ({                     \
+       if (!IS_ERR(str) && strlen(str) == 0) {         \
+               kfree(str);                             \
+               str = ERR_PTR(-ERANGE);                 \
+       }                                               \
+       IS_ERR(str);                                    \
+})
+
+#define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE)
+
+int xs_init(void);
+
+#endif /* _ASM_XEN_XENBUS_H */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/sched.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/sched.c    Fri Sep  9 16:30:54 2005
@@ -0,0 +1,300 @@
+/* 
+ ****************************************************************************
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ *        File: sched.c
+ *      Author: Grzegorz Milos
+ *     Changes: 
+ *              
+ *        Date: Aug 2005
+ * 
+ * Environment: Xen Minimal OS
+ * Description: simple scheduler for Mini-Os
+ *
+ * The scheduler is non-preemptive (cooperative), and schedules according 
+ * to Round Robin algorithm.
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <os.h>
+#include <hypervisor.h>
+#include <time.h>
+#include <mm.h>
+#include <types.h>
+#include <lib.h>
+#include <xmalloc.h>
+#include <list.h>
+#include <sched.h>
+#include <semaphore.h>
+
+#ifdef SCHED_DEBUG
+#define DEBUG(_f, _a...) \
+    printk("MINI_OS(file=sched.c, line=%d) " _f "\n", __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...)    ((void)0)
+#endif
+
+
+#define RUNNABLE_FLAG   0x00000001
+
+#define is_runnable(_thread)    (_thread->flags & RUNNABLE_FLAG)
+#define set_runnable(_thread)   (_thread->flags |= RUNNABLE_FLAG)
+#define clear_runnable(_thread) (_thread->flags &= ~RUNNABLE_FLAG)
+
+
+struct thread *idle_thread;
+LIST_HEAD(exited_threads);
+
+void dump_stack(struct thread *thread)
+{
+    unsigned long *bottom = (unsigned long *)thread->stack + 2048; 
+    unsigned long *pointer = (unsigned long *)thread->eps;
+    int count;
+    printk("The stack for \"%s\"\n", thread->name);
+    for(count = 0; count < 15 && pointer < bottom; count ++)
+    {
+        printk("[0x%lx] 0x%lx\n", pointer, *pointer);
+        pointer++;
+    }
+    
+    if(pointer < bottom) printk("Not the whole stack printed\n");
+}
+
+#ifdef __i386__
+#define switch_threads(prev, next) do {                                 \
+    unsigned long esi,edi;                                              \
+    __asm__ __volatile__("pushfl\n\t"                                   \
+                         "pushl %%ebp\n\t"                              \
+                         "movl %%esp,%0\n\t"         /* save ESP */     \
+                         "movl %4,%%esp\n\t"        /* restore ESP */   \
+                         "movl $1f,%1\n\t"          /* save EIP */      \
+                         "pushl %5\n\t"             /* restore EIP */   \
+                         "ret\n\t"                                      \
+                         "1:\t"                                         \
+                         "popl %%ebp\n\t"                               \
+                         "popfl"                                        \
+                         :"=m" (prev->eps),"=m" (prev->eip),            \
+                          "=S" (esi),"=D" (edi)             \
+                         :"m" (next->eps),"m" (next->eip),              \
+                          "2" (prev), "d" (next));                      \
+} while (0)
+#elif __x86_64__
+/* FIXME */
+#endif
+
+void inline print_runqueue(void)
+{
+    struct list_head *it;
+    struct thread *th;
+    list_for_each(it, &idle_thread->thread_list)
+    {
+        th = list_entry(it, struct thread, thread_list);
+        printk("   Thread \"%s\", runnable=%d\n", th->name, is_runnable(th));
+    }
+    printk("\n");
+}
+
+
+void schedule(void)
+{
+    struct thread *prev, *next, *thread;
+    struct list_head *iterator;
+    unsigned long flags;
+    prev = current;
+    local_irq_save(flags); 
+    list_for_each(iterator, &exited_threads)
+    {
+        thread = list_entry(iterator, struct thread, thread_list);
+        if(thread != prev)
+        {
+            list_del(&thread->thread_list);
+            free_pages(thread->stack, 1);
+            xfree(thread);
+        }
+    }
+    next = idle_thread;    
+    /* Thread list needs to be protected */
+    list_for_each(iterator, &idle_thread->thread_list)
+    {
+        thread = list_entry(iterator, struct thread, thread_list);
+        if(is_runnable(thread)) 
+        {
+            next = thread;
+            /* Put this thread on the end of the list */
+            list_del(&thread->thread_list);
+            list_add_tail(&thread->thread_list, &idle_thread->thread_list);
+            break;
+        }
+    }
+    local_irq_restore(flags);
+    /* Interrupting the switch is equivalent to having the next thread
+       inturrupted at the return instruction. And therefore at safe point. */
+/* The thread switching only works for i386 at the moment */    
+#ifdef __i386__    
+    if(prev != next) switch_threads(prev, next);
+#endif    
+}
+
+
+
+void exit_thread(struct thread *thread)
+{
+    unsigned long flags;
+    printk("Thread \"%s\" exited.\n", thread->name);
+    local_irq_save(flags);
+    /* Remove from the thread list */
+    list_del(&thread->thread_list);
+    clear_runnable(thread);
+    /* Put onto exited list */
+    list_add(&thread->thread_list, &exited_threads);
+    local_irq_restore(flags);
+    /* Schedule will free the resources */
+    schedule();
+}
+
+
+struct thread* create_thread(char *name, void (*function)(void *), void *data)
+{
+    struct thread *thread;
+    unsigned long flags;
+    
+    thread = xmalloc(struct thread);
+    /* Allocate 2 pages for stack, stack will be 2pages aligned */
+    thread->stack = (char *)alloc_pages(1);
+    thread->name = name;
+    printk("Thread \"%s\": pointer: 0x%lx, stack: 0x%lx\n", name, thread, 
+            thread->stack);
+    
+    thread->eps = (unsigned long)thread->stack + 4096 * 2 - 4;
+    /* Save pointer to the thread on the stack, used by current macro */
+    *((unsigned long *)thread->stack) = (unsigned long)thread;
+    *((unsigned long *)thread->eps) = (unsigned long)thread;
+    thread->eps -= 4; 
+    *((unsigned long *)thread->eps) = (unsigned long)data;
+    
+    /* No return address */
+    thread->eps -= 4;
+    *((unsigned long *)thread->eps) = (unsigned long)exit_thread;
+    
+    thread->eip = (unsigned long)function;
+     
+    /* Not runable, not exited */ 
+    thread->flags = 0;
+    set_runnable(thread);
+    
+    local_irq_save(flags);
+    if(idle_thread != NULL)
+        list_add_tail(&thread->thread_list, &idle_thread->thread_list); 
+    local_irq_restore(flags);
+
+    return thread;
+}
+
+
+void block(struct thread *thread)
+{
+    clear_runnable(thread);
+}
+
+void wake(struct thread *thread)
+{
+    set_runnable(thread);
+}
+
+void idle_thread_fn(void *unused)
+{
+    for(;;)
+    {
+        schedule();
+        printk("Blocking the domain\n"); 
+        block_domain(10000);
+    }
+}
+
+void run_idle_thread(void)
+{
+    /* Switch stacks and run the thread */ 
+    __asm__ __volatile__("mov %0,%%esp\n\t"
+                         "push %1\n\t" 
+                         "ret"                                            
+                         :"=m" (idle_thread->eps)
+                         :"m" (idle_thread->eip));                          
+}
+
+
+
+DECLARE_MUTEX(mutex);
+
+void th_f1(void *data)
+{
+    struct timeval tv1, tv2;
+
+    for(;;)
+    {
+        down(&mutex);
+        printk("Thread \"%s\" got semaphore, runnable %d\n", current->name, 
is_runnable(current));
+        schedule();
+        printk("Thread \"%s\" releases the semaphore\n", current->name);
+        up(&mutex);
+        
+        
+        gettimeofday(&tv1);
+        for(;;)
+        {
+            gettimeofday(&tv2);
+            if(tv2.tv_sec - tv1.tv_sec > 2) break;
+        }
+                
+        
+        schedule(); 
+    }
+}
+
+void th_f2(void *data)
+{
+    for(;;)
+    {
+        printk("Thread OTHER executing, data 0x%lx\n", data);
+        schedule();
+    }
+}
+
+
+
+void init_sched(void)
+{
+    printk("Initialising scheduler\n");
+       
+    idle_thread = create_thread("Idle", idle_thread_fn, NULL);
+    INIT_LIST_HEAD(&idle_thread->thread_list);
+
+    
+/*    create_thread("1", th_f1, (void *)0x1234);    
+    create_thread("2", th_f1, (void *)0x1234);    
+    create_thread("3", th_f1, (void *)0x1234);    
+    create_thread("4", th_f1, (void *)0x1234);    
+    create_thread("5", th_f1, (void *)0x1234);    
+    create_thread("6", th_f1, (void *)0x1234);    
+    create_thread("second", th_f2, NULL);
+*/   
+}
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/xenbus/Makefile
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/xenbus/Makefile    Fri Sep  9 16:30:54 2005
@@ -0,0 +1,9 @@
+all: xenstore.h xenbus_comms.o xenbus_xs.o xenbus_probe.o
+
+xenstore.h:
+       [ -e xenstored.h ] || ln -sf ../../../tools/xenstore/xenstored.h 
xenstored.h
+
+clean:
+       #Taken care of by main Makefile
+       #rm xenstored.h
+       #rm *.o
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/xenbus/xenbus_comms.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/xenbus/xenbus_comms.c      Fri Sep  9 16:30:54 2005
@@ -0,0 +1,231 @@
+/******************************************************************************
+ * xenbus_comms.c
+ *
+ * Low level code to talks to Xen Store: ringbuffer and event channel.
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <types.h>
+#include <wait.h>
+#include <mm.h>
+#include <hypervisor.h>
+#include <events.h>
+#include <os.h>
+#include <lib.h>
+
+
+#ifdef XENBUS_COMMS_DEBUG
+#define DEBUG(_f, _a...) \
+    printk("MINI_OS(file=xenbus_comms.c, line=%d) " _f "\n", __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...)    ((void)0)
+#endif
+
+
+#define RINGBUF_DATASIZE ((PAGE_SIZE / 2) - sizeof(struct ringbuf_head))
+struct ringbuf_head
+{
+       u32 write; /* Next place to write to */
+       u32 read; /* Next place to read from */
+       u8 flags;
+       char buf[0];
+} __attribute__((packed));
+
+DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
+
+static inline struct ringbuf_head *outbuf(void)
+{
+       return mfn_to_virt(start_info.store_mfn);
+}
+
+static inline struct ringbuf_head *inbuf(void)
+{
+       return (struct ringbuf_head *)((char 
*)mfn_to_virt(start_info.store_mfn) + PAGE_SIZE/2);
+}
+
+static void wake_waiting(int port, struct pt_regs *regs)
+{
+       wake_up(&xb_waitq);
+}
+
+static int check_buffer(const struct ringbuf_head *h)
+{
+       return (h->write < RINGBUF_DATASIZE && h->read < RINGBUF_DATASIZE);
+}
+
+/* We can't fill last byte: would look like empty buffer. */
+static void *get_output_chunk(const struct ringbuf_head *h,
+                             void *buf, u32 *len)
+{
+       u32 read_mark;
+
+       if (h->read == 0)
+               read_mark = RINGBUF_DATASIZE - 1;
+       else
+               read_mark = h->read - 1;
+
+       /* Here to the end of buffer, unless they haven't read some out. */
+       *len = RINGBUF_DATASIZE - h->write;
+       if (read_mark >= h->write)
+               *len = read_mark - h->write;
+       return (void *)((char *)buf + h->write);
+}
+
+static const void *get_input_chunk(const struct ringbuf_head *h,
+                                  const void *buf, u32 *len)
+{
+       /* Here to the end of buffer, unless they haven't written some. */
+       *len = RINGBUF_DATASIZE - h->read;
+       if (h->write >= h->read)
+               *len = h->write - h->read;
+       return (void *)((char *)buf + h->read);
+}
+
+static void update_output_chunk(struct ringbuf_head *h, u32 len)
+{
+       h->write += len;
+       if (h->write == RINGBUF_DATASIZE)
+               h->write = 0;
+}
+
+static void update_input_chunk(struct ringbuf_head *h, u32 len)
+{
+       h->read += len;
+       if (h->read == RINGBUF_DATASIZE)
+               h->read = 0;
+}
+
+static int output_avail(struct ringbuf_head *out)
+{
+       unsigned int avail;
+
+       get_output_chunk(out, out->buf, &avail);
+       return avail != 0;
+}
+
+int xb_write(const void *data, unsigned len)
+{
+       struct ringbuf_head h;
+       struct ringbuf_head *out = outbuf();
+
+       do {
+               void *dst;
+               unsigned int avail;
+
+               wait_event(xb_waitq, output_avail(out));
+
+               /* Read, then check: not that we don't trust store.
+                * Hell, some of my best friends are daemons.  But,
+                * in this post-911 world... */
+               h = *out;
+               mb();
+               if (!check_buffer(&h)) {
+                       return -1; /* ETERRORIST! */
+               }
+
+               dst = get_output_chunk(&h, out->buf, &avail);
+               if (avail > len)
+                       avail = len;
+               memcpy(dst, data, avail);
+               data = (void *)((char *)data + avail);
+               len -= avail;
+               update_output_chunk(out, avail);
+               notify_via_evtchn(start_info.store_evtchn);
+       } while (len != 0);
+
+       return 0;
+}
+
+int xs_input_avail(void)
+{
+       unsigned int avail;
+       struct ringbuf_head *in = inbuf();
+
+       get_input_chunk(in, in->buf, &avail);
+       return avail != 0;
+}
+
+int xb_read(void *data, unsigned len)
+{
+       struct ringbuf_head h;
+       struct ringbuf_head *in = inbuf();
+       int was_full;
+
+       while (len != 0) {
+               unsigned int avail;
+               const char *src;
+
+               wait_event(xb_waitq, xs_input_avail());
+               h = *in;
+               mb();
+               if (!check_buffer(&h)) {
+                       return -1;
+               }
+
+               src = get_input_chunk(&h, in->buf, &avail);
+               if (avail > len)
+                       avail = len;
+               was_full = !output_avail(&h);
+
+               memcpy(data, src, avail);
+               data = (void *)((char *)data + avail);
+               len -= avail;
+               update_input_chunk(in, avail);
+               DEBUG("Finished read of %i bytes (%i to go)\n", avail, len);
+               /* If it was full, tell them we've taken some. */
+               if (was_full)
+                       notify_via_evtchn(start_info.store_evtchn);
+       }
+
+       /* If we left something, wake watch thread to deal with it. */
+       if (xs_input_avail())
+               wake_up(&xb_waitq);
+
+       return 0;
+}
+
+/* Set up interrupt handler off store event channel. */
+int xb_init_comms(void)
+{
+    printk("Init xenbus comms, store event channel %d\n", 
start_info.store_evtchn);
+       if (!start_info.store_evtchn)
+               return 0;
+    printk("Binding virq\n");
+       bind_evtchn(start_info.store_evtchn, &wake_waiting);
+
+       /* FIXME zero out page -- domain builder should probably do this*/
+       memset(mfn_to_virt(start_info.store_mfn), 0, PAGE_SIZE);
+    notify_via_evtchn(start_info.store_evtchn);
+       return 0;
+}
+
+void xb_suspend_comms(void)
+{
+
+       if (!start_info.store_evtchn)
+               return;
+
+    // TODO
+       //unbind_evtchn_from_irqhandler(xen_start_info.store_evtchn, &xb_waitq);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/xenbus/xenbus_comms.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/xenbus/xenbus_comms.h      Fri Sep  9 16:30:54 2005
@@ -0,0 +1,40 @@
+/*
+ * Private include for xenbus communications.
+ * 
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef _XENBUS_COMMS_H
+#define _XENBUS_COMMS_H
+
+int xb_init_comms(void);
+void xb_suspend_comms(void);
+
+/* Low level routines. */
+int xb_write(const void *data, unsigned len);
+int xb_read(void *data, unsigned len);
+int xs_input_avail(void);
+extern struct wait_queue_head xb_waitq;
+
+#endif /* _XENBUS_COMMS_H */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/xenbus/xenbus_xs.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/extras/mini-os/xenbus/xenbus_xs.c Fri Sep  9 16:30:54 2005
@@ -0,0 +1,554 @@
+/******************************************************************************
+ * xenbus_xs.c
+ *
+ * This is the kernel equivalent of the "xs" library.  We don't need everything
+ * and we use xenbus_comms for communication.
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <errno.h>
+#include <types.h>
+#include <list.h>
+#include <lib.h>
+#include <err.h>
+#include <os.h>
+#include <xmalloc.h>
+#include <fcntl.h>
+#include <xenbus.h>
+#include <wait.h>
+#include <sched.h>
+#include <semaphore.h>
+#include "xenstored.h"
+#include "xenbus_comms.h"
+
+#define streq(a, b) (strcmp((a), (b)) == 0)
+
+static char printf_buffer[4096];
+static LIST_HEAD(watches);
+//TODO
+DECLARE_MUTEX(xenbus_lock);
+
+static int get_error(const char *errorstring)
+{
+       unsigned int i;
+
+       for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) {
+               if (i == ARRAY_SIZE(xsd_errors) - 1) {
+                       printk("XENBUS xen store gave: unknown error %s",
+                              errorstring);
+                       return EINVAL;
+               }
+       }
+       return xsd_errors[i].errnum;
+}
+
+static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
+{
+       struct xsd_sockmsg msg;
+       void *ret;
+       int err;
+
+       err = xb_read(&msg, sizeof(msg));
+       if (err)
+               return ERR_PTR(err);
+
+       ret = xmalloc_array(char, msg.len + 1);
+       if (!ret)
+               return ERR_PTR(-ENOMEM);
+
+       err = xb_read(ret, msg.len);
+       if (err) {
+               xfree(ret);
+               return ERR_PTR(err);
+       }
+       ((char*)ret)[msg.len] = '\0';
+
+       *type = msg.type;
+       if (len)
+               *len = msg.len;
+       return ret;
+}
+
+/* Emergency write. */
+void xenbus_debug_write(const char *str, unsigned int count)
+{
+       struct xsd_sockmsg msg;
+
+       msg.type = XS_DEBUG;
+       msg.len = sizeof("print") + count + 1;
+
+       xb_write(&msg, sizeof(msg));
+       xb_write("print", sizeof("print"));
+       xb_write(str, count);
+       xb_write("", 1);
+}
+
+/* Send message to xs, get kmalloc'ed reply.  ERR_PTR() on error. */
+static void *xs_talkv(enum xsd_sockmsg_type type,
+                     const struct kvec *iovec,
+                     unsigned int num_vecs,
+                     unsigned int *len)
+{
+       struct xsd_sockmsg msg;
+       void *ret = NULL;
+       unsigned int i;
+       int err;
+
+       //WARN_ON(down_trylock(&xenbus_lock) == 0);
+
+       msg.type = type;
+       msg.len = 0;
+       for (i = 0; i < num_vecs; i++)
+               msg.len += iovec[i].iov_len;
+
+       err = xb_write(&msg, sizeof(msg));
+       if (err)
+               return ERR_PTR(err);
+
+       for (i = 0; i < num_vecs; i++) {
+               err = xb_write(iovec[i].iov_base, iovec[i].iov_len);;
+               if (err)
+                       return ERR_PTR(err);
+       }
+
+       /* Watches can have fired before reply comes: daemon detects
+        * and re-transmits, so we can ignore this. */
+       do {
+               xfree(ret);
+               ret = read_reply(&msg.type, len);
+               if (IS_ERR(ret))
+                       return ret;
+       } while (msg.type == XS_WATCH_EVENT);
+
+       if (msg.type == XS_ERROR) {
+               err = get_error(ret);
+               xfree(ret);
+               return ERR_PTR(-err);
+       }
+
+       //BUG_ON(msg.type != type);
+       return ret;
+}
+
+/* Simplified version of xs_talkv: single message. */
+static void *xs_single(enum xsd_sockmsg_type type,
+                      const char *string, unsigned int *len)
+{
+       struct kvec iovec;
+
+       iovec.iov_base = (void *)string;
+       iovec.iov_len = strlen(string) + 1;
+       return xs_talkv(type, &iovec, 1, len);
+}
+
+/* Many commands only need an ack, don't care what it says. */
+static int xs_error(char *reply)
+{
+       if (IS_ERR(reply))
+               return PTR_ERR(reply);
+       xfree(reply);
+       return 0;
+}
+
+static unsigned int count_strings(const char *strings, unsigned int len)
+{
+       unsigned int num;
+       const char *p;
+
+       for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1)
+               num++;
+
+       return num;
+}
+
+/* Return the path to dir with /name appended. */ 
+static char *join(const char *dir, const char *name)
+{
+       static char buffer[4096];
+
+       //BUG_ON(down_trylock(&xenbus_lock) == 0);
+       /* XXX FIXME: might not be correct if name == "" */
+       //BUG_ON(strlen(dir) + strlen("/") + strlen(name) + 1 > sizeof(buffer));
+
+       strcpy(buffer, dir);
+       if (!streq(name, "")) {
+               strcat(buffer, "/");
+               strcat(buffer, name);
+       }
+       return buffer;
+}
+
+char **xenbus_directory(const char *dir, const char *node, unsigned int *num)
+{
+       char *strings, *p, **ret;
+       unsigned int len;
+
+       strings = xs_single(XS_DIRECTORY, join(dir, node), &len);
+       if (IS_ERR(strings))
+               return (char **)strings;
+
+       /* Count the strings. */
+       *num = count_strings(strings, len);
+
+       /* Transfer to one big alloc for easy freeing. */
+       ret = (char **)xmalloc_array(char, *num * sizeof(char *) + len);
+       if (!ret) {
+               xfree(strings);
+               return ERR_PTR(-ENOMEM);
+       }
+       memcpy(&ret[*num], strings, len);
+       xfree(strings);
+
+       strings = (char *)&ret[*num];
+       for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
+               ret[(*num)++] = p;
+       return ret;
+}
+
+/* Check if a path exists. Return 1 if it does. */
+int xenbus_exists(const char *dir, const char *node)
+{
+       char **d;
+       int dir_n;
+
+       d = xenbus_directory(dir, node, &dir_n);
+       if (IS_ERR(d))
+               return 0;
+       xfree(d);
+       return 1;
+}
+
+/* Get the value of a single file.
+ * Returns a kmalloced value: call free() on it after use.
+ * len indicates length in bytes.
+ */
+void *xenbus_read(const char *dir, const char *node, unsigned int *len)
+{
+       return xs_single(XS_READ, join(dir, node), len);
+}
+
+/* Write the value of a single file.
+ * Returns -err on failure.  createflags can be 0, O_CREAT, or O_CREAT|O_EXCL.
+ */
+int xenbus_write(const char *dir, const char *node,
+                const char *string, int createflags)
+{
+       const char *flags, *path;
+       struct kvec iovec[3];
+
+       path = join(dir, node);
+       /* Format: Flags (as string), path, data. */
+       if (createflags == 0)
+               flags = XS_WRITE_NONE;
+       else if (createflags == O_CREAT)
+               flags = XS_WRITE_CREATE;
+       else if (createflags == (O_CREAT|O_EXCL))
+               flags = XS_WRITE_CREATE_EXCL;
+       else
+               return -EINVAL;
+
+       iovec[0].iov_base = (void *)path;
+       iovec[0].iov_len = strlen(path) + 1;
+       iovec[1].iov_base = (void *)flags;
+       iovec[1].iov_len = strlen(flags) + 1;
+       iovec[2].iov_base = (void *)string;
+       iovec[2].iov_len = strlen(string);
+
+       return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
+}
+
+/* Create a new directory. */
+int xenbus_mkdir(const char *dir, const char *node)
+{
+       return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL));
+}
+
+/* Destroy a file or directory (directories must be empty). */
+int xenbus_rm(const char *dir, const char *node)
+{
+       return xs_error(xs_single(XS_RM, join(dir, node), NULL));
+}
+
+/* Start a transaction: changes by others will not be seen during this
+ * transaction, and changes will not be visible to others until end.
+ * Transaction only applies to the given subtree.
+ * You can only have one transaction at any time.
+ */
+int xenbus_transaction_start(const char *subtree)
+{
+       return xs_error(xs_single(XS_TRANSACTION_START, subtree, NULL));
+}
+
+/* End a transaction.
+ * If abandon is true, transaction is discarded instead of committed.
+ */
+int xenbus_transaction_end(int abort)
+{
+       char abortstr[2];
+
+       if (abort)
+               strcpy(abortstr, "F");
+       else
+               strcpy(abortstr, "T");
+       return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
+}
+
+/* Single read and scanf: returns -errno or num scanned. */
+int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
+{
+       va_list ap;
+       int ret;
+       char *val;
+
+       val = xenbus_read(dir, node, NULL);
+       if (IS_ERR(val))
+               return PTR_ERR(val);
+
+       va_start(ap, fmt);
+       ret = vsscanf(val, fmt, ap);
+       va_end(ap);
+       xfree(val);
+       /* Distinctive errno. */
+       if (ret == 0)
+               return -ERANGE;
+       return ret;
+}
+
+/* Single printf and write: returns -errno or 0. */
+int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
+{
+       va_list ap;
+       int ret;
+
+       //BUG_ON(down_trylock(&xenbus_lock) == 0);
+       va_start(ap, fmt);
+       ret = vsnprintf(printf_buffer, sizeof(printf_buffer), fmt, ap);
+       va_end(ap);
+
+       //BUG_ON(ret > sizeof(printf_buffer)-1);
+       return xenbus_write(dir, node, printf_buffer, O_CREAT);
+}
+
+       
+/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
+int xenbus_gather(const char *dir, ...)
+{
+       va_list ap;
+       const char *name;
+       int ret = 0;
+
+       va_start(ap, dir);
+       while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
+               const char *fmt = va_arg(ap, char *);
+               void *result = va_arg(ap, void *);
+               char *p;
+
+               p = xenbus_read(dir, name, NULL);
+               if (IS_ERR(p)) {
+                       ret = PTR_ERR(p);
+                       break;
+               }
+               if (fmt) {
+                       if (sscanf(p, fmt, result) == 0)
+                               ret = -EINVAL;
+                       xfree(p);
+               } else
+                       *(char **)result = p;
+       }
+       va_end(ap);
+       return ret;
+}
+
+static int xs_watch(const char *path, const char *token)
+{
+       struct kvec iov[2];
+
+       iov[0].iov_base = (void *)path;
+       iov[0].iov_len = strlen(path) + 1;
+       iov[1].iov_base = (void *)token;
+       iov[1].iov_len = strlen(token) + 1;
+
+       return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
+}
+
+static char *xs_read_watch(char **token)
+{
+       enum xsd_sockmsg_type type;
+       char *ret;
+
+       ret = read_reply(&type, NULL);
+       if (IS_ERR(ret))
+               return ret;
+
+       //BUG_ON(type != XS_WATCH_EVENT);
+       *token = ret + strlen(ret) + 1;
+       return ret;
+}
+
+static int xs_acknowledge_watch(const char *token)
+{
+       return xs_error(xs_single(XS_WATCH_ACK, token, NULL));
+}
+
+static int xs_unwatch(const char *path, const char *token)
+{
+       struct kvec iov[2];
+
+       iov[0].iov_base = (char *)path;
+       iov[0].iov_len = strlen(path) + 1;
+       iov[1].iov_base = (char *)token;
+       iov[1].iov_len = strlen(token) + 1;
+
+       return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
+}
+
+/* A little paranoia: we don't just trust token. */
+static struct xenbus_watch *find_watch(const char *token)
+{
+       struct xenbus_watch *i, *cmp;
+
+       cmp = (void *)simple_strtoul(token, NULL, 16);
+
+       list_for_each_entry(i, &watches, list)
+               if (i == cmp)
+                       return i;
+       return NULL;
+}
+
+/* Register callback to watch this node. */
+int register_xenbus_watch(struct xenbus_watch *watch)
+{
+       /* Pointer in ascii is the token. */
+       char token[sizeof(watch) * 2 + 1];
+       int err;
+
+       sprintf(token, "%lX", (long)watch);
+       //BUG_ON(find_watch(token));
+printk("Registered watch for: %s\n", token);
+       err = xs_watch(watch->node, token);
+       if (!err)
+               list_add(&watch->list, &watches);
+       return err;
+}
+
+void unregister_xenbus_watch(struct xenbus_watch *watch)
+{
+       char token[sizeof(watch) * 2 + 1];
+       int err;
+
+       sprintf(token, "%lX", (long)watch);
+       //BUG_ON(!find_watch(token));
+
+       err = xs_unwatch(watch->node, token);
+       list_del(&watch->list);
+
+       if (err)
+               printk("XENBUS Failed to release watch %s: %i\n",
+                      watch->node, err);
+}
+
+/* Re-register callbacks to all watches. */
+void reregister_xenbus_watches(void)
+{
+       struct xenbus_watch *watch;
+       char token[sizeof(watch) * 2 + 1];
+
+       list_for_each_entry(watch, &watches, list) {
+               sprintf(token, "%lX", (long)watch);
+               xs_watch(watch->node, token);
+       }
+}
+
+void watch_thread(void *unused)
+{
+       for (;;) {
+               char *token;
+               char *node = NULL;
+
+               wait_event(xb_waitq, xs_input_avail());
+
+               /* If this is a spurious wakeup caused by someone
+                * doing an op, they'll hold the lock and the buffer
+                * will be empty by the time we get there.               
+                */
+               down(&xenbus_lock);
+               if (xs_input_avail())
+                       node = xs_read_watch(&token);
+
+               if (node && !IS_ERR(node)) {
+                       struct xenbus_watch *w;
+                       int err;
+
+                       err = xs_acknowledge_watch(token);
+                       if (err)
+                               printk("XENBUS ack %s fail %i\n", node, err);
+                       w = find_watch(token);
+                       //BUG_ON(!w);
+                       w->callback(w, node);
+                       xfree(node);
+               } else
+                       printk("XENBUS xs_read_watch: %li\n", PTR_ERR(node));
+               up(&xenbus_lock);
+       }
+}
+
+
+static void ballon_changed(struct xenbus_watch *watch, const char *node)
+{
+    unsigned long new_target;
+    int err;
+    err = xenbus_scanf("memory", "target", "%lu", &new_target);
+
+    if(err != 1)
+    {
+        printk("Unable to read memory/target\n");
+        return;
+    }
+
+    printk("Memory target changed to: %ld bytes, ignoring.\n", new_target);
+}
+
+
+static struct xenbus_watch ballon_watch = {
+    .node = "memory/target",
+    .callback = ballon_changed,
+};
+
+
+
+int xs_init(void)
+{
+       int err;
+       struct thread *watcher;
+    printk("xb_init_comms\n");
+       err = xb_init_comms();
+       if (err)
+               return err;
+       
+       watcher = create_thread("kxwatch", watch_thread, NULL);
+    down(&xenbus_lock);
+    register_xenbus_watch(&ballon_watch);
+    up(&xenbus_lock);
+       return 0;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/char/tpm/Kconfig.domU
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig.domU        Fri Sep  9 
16:30:54 2005
@@ -0,0 +1,30 @@
+#
+# TPM device configuration
+#
+
+menu "TPM devices"
+
+config TCG_TPM
+       tristate "TPM Support for XEN"
+       depends on ARCH_XEN && !XEN_PHYSDEV_ACCESS
+       ---help---
+         If you want to make TPM security available in your system,
+         say Yes and it will be accessible from within a user domain.  For
+         more information see <http://www.trustedcomputinggroup.org>.
+         An implementation of the Trusted Software Stack (TSS), the
+         userspace enablement piece of the specification, can be
+         obtained at: <http://sourceforge.net/projects/trousers>.  To
+         compile this driver as a module, choose M here; the module
+         will be called tpm. If unsure, say N.
+
+config TCG_XEN
+       tristate "XEN TPM Interface"
+       depends on TCG_TPM && ARCH_XEN && XEN_TPMDEV_FRONTEND
+       ---help---
+         If you want to make TPM support available to a Xen
+         user domain, say Yes and it will
+          be accessible from within Linux. To compile this driver
+          as a module, choose M here; the module will be called
+          tpm_xen.
+
+endmenu
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/char/tpm/Makefile
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/Makefile    Fri Sep  9 16:30:54 2005
@@ -0,0 +1,12 @@
+#
+# Makefile for the kernel tpm device drivers.
+#
+ifeq ($(CONFIG_XEN_PHYSDEV_ACCESS),y)
+obj-$(CONFIG_TCG_TPM) += tpm.o
+obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
+obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
+obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
+else
+obj-$(CONFIG_TCG_TPM) += tpm_nopci.o
+obj-$(CONFIG_TCG_XEN) += tpm_xen.o
+endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/drivers/char/tpm/tpm.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.c       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,627 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * Note, the TPM chip is not interrupt driven (only polling)
+ * and can have very long timeouts (minutes!). Hence the unusual
+ * calls to schedule_timeout.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/spinlock.h>
+#include "tpm.h"
+
+#define        TPM_MINOR                       224     /* officially assigned 
*/
+
+#define        TPM_BUFSIZE                     2048
+
+static LIST_HEAD(tpm_chip_list);
+static DEFINE_SPINLOCK(driver_lock);
+static int dev_mask[32];
+
+static void user_reader_timeout(unsigned long ptr)
+{
+       struct tpm_chip *chip = (struct tpm_chip *) ptr;
+
+       down(&chip->buffer_mutex);
+       atomic_set(&chip->data_pending, 0);
+       memset(chip->data_buffer, 0, TPM_BUFSIZE);
+       up(&chip->buffer_mutex);
+}
+
+void tpm_time_expired(unsigned long ptr)
+{
+       int *exp = (int *) ptr;
+       *exp = 1;
+}
+
+EXPORT_SYMBOL_GPL(tpm_time_expired);
+
+/*
+ * Internal kernel interface to transmit TPM commands
+ */
+static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
+                           size_t bufsiz)
+{
+       ssize_t len;
+       u32 count;
+       __be32 *native_size;
+
+       native_size = (__force __be32 *) (buf + 2);
+       count = be32_to_cpu(*native_size);
+
+       if (count == 0)
+               return -ENODATA;
+       if (count > bufsiz) {
+               dev_err(&chip->pci_dev->dev,
+                       "invalid count value %x %zx \n", count, bufsiz);
+               return -E2BIG;
+       }
+
+       down(&chip->tpm_mutex);
+
+       if ((len = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+               dev_err(&chip->pci_dev->dev,
+                       "tpm_transmit: tpm_send: error %zd\n", len);
+               return len;
+       }
+
+       down(&chip->timer_manipulation_mutex);
+       chip->time_expired = 0;
+       init_timer(&chip->device_timer);
+       chip->device_timer.function = tpm_time_expired;
+       chip->device_timer.expires = jiffies + 2 * 60 * HZ;
+       chip->device_timer.data = (unsigned long) &chip->time_expired;
+       add_timer(&chip->device_timer);
+       up(&chip->timer_manipulation_mutex);
+
+       do {
+               u8 status = inb(chip->vendor->base + 1);
+               if ((status & chip->vendor->req_complete_mask) ==
+                   chip->vendor->req_complete_val) {
+                       down(&chip->timer_manipulation_mutex);
+                       del_singleshot_timer_sync(&chip->device_timer);
+                       up(&chip->timer_manipulation_mutex);
+                       goto out_recv;
+               }
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(TPM_TIMEOUT);
+               rmb();
+       } while (!chip->time_expired);
+
+
+       chip->vendor->cancel(chip);
+       dev_err(&chip->pci_dev->dev, "Time expired\n");
+       up(&chip->tpm_mutex);
+       return -EIO;
+
+out_recv:
+       len = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+       if (len < 0)
+               dev_err(&chip->pci_dev->dev,
+                       "tpm_transmit: tpm_recv: error %zd\n", len);
+       up(&chip->tpm_mutex);
+       return len;
+}
+
+#define TPM_DIGEST_SIZE 20
+#define CAP_PCR_RESULT_SIZE 18
+static u8 cap_pcr[] = {
+       0, 193,                 /* TPM_TAG_RQU_COMMAND */
+       0, 0, 0, 22,            /* length */
+       0, 0, 0, 101,           /* TPM_ORD_GetCapability */
+       0, 0, 0, 5,
+       0, 0, 0, 4,
+       0, 0, 1, 1
+};
+
+#define READ_PCR_RESULT_SIZE 30
+static u8 pcrread[] = {
+       0, 193,                 /* TPM_TAG_RQU_COMMAND */
+       0, 0, 0, 14,            /* length */
+       0, 0, 0, 21,            /* TPM_ORD_PcrRead */
+       0, 0, 0, 0              /* PCR index */
+};
+
+static ssize_t show_pcrs(struct device *dev, char *buf)
+{
+       u8 data[READ_PCR_RESULT_SIZE];
+       ssize_t len;
+       int i, j, index, num_pcrs;
+       char *str = buf;
+
+       struct tpm_chip *chip =
+           pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+       if (chip == NULL)
+               return -ENODEV;
+
+       memcpy(data, cap_pcr, sizeof(cap_pcr));
+       if ((len = tpm_transmit(chip, data, sizeof(data)))
+           < CAP_PCR_RESULT_SIZE)
+               return len;
+
+       num_pcrs = be32_to_cpu(*((__force __be32 *) (data + 14)));
+
+       for (i = 0; i < num_pcrs; i++) {
+               memcpy(data, pcrread, sizeof(pcrread));
+               index = cpu_to_be32(i);
+               memcpy(data + 10, &index, 4);
+               if ((len = tpm_transmit(chip, data, sizeof(data)))
+                   < READ_PCR_RESULT_SIZE)
+                       return len;
+               str += sprintf(str, "PCR-%02d: ", i);
+               for (j = 0; j < TPM_DIGEST_SIZE; j++)
+                       str += sprintf(str, "%02X ", *(data + 10 + j));
+               str += sprintf(str, "\n");
+       }
+       return str - buf;
+}
+
+static DEVICE_ATTR(pcrs, S_IRUGO, show_pcrs, NULL);
+
+#define  READ_PUBEK_RESULT_SIZE 314
+static u8 readpubek[] = {
+       0, 193,                 /* TPM_TAG_RQU_COMMAND */
+       0, 0, 0, 30,            /* length */
+       0, 0, 0, 124,           /* TPM_ORD_ReadPubek */
+};
+
+static ssize_t show_pubek(struct device *dev, char *buf)
+{
+       u8 data[READ_PUBEK_RESULT_SIZE];
+       ssize_t len;
+       __be32 *native_val;
+       int i;
+       char *str = buf;
+
+       struct tpm_chip *chip =
+           pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+       if (chip == NULL)
+               return -ENODEV;
+
+       memcpy(data, readpubek, sizeof(readpubek));
+       memset(data + sizeof(readpubek), 0, 20);        /* zero nonce */
+
+       if ((len = tpm_transmit(chip, data, sizeof(data))) <
+           READ_PUBEK_RESULT_SIZE)
+               return len;
+
+       /*
+          ignore header 10 bytes
+          algorithm 32 bits (1 == RSA )
+          encscheme 16 bits
+          sigscheme 16 bits
+          parameters (RSA 12->bytes: keybit, #primes, expbit)
+          keylenbytes 32 bits
+          256 byte modulus
+          ignore checksum 20 bytes
+        */
+
+       native_val = (__force __be32 *) (data + 34);
+
+       str +=
+           sprintf(str,
+                   "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
+                   "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X"
+                   " %02X %02X %02X %02X %02X %02X %02X %02X\n"
+                   "Modulus length: %d\nModulus: \n",
+                   data[10], data[11], data[12], data[13], data[14],
+                   data[15], data[16], data[17], data[22], data[23],
+                   data[24], data[25], data[26], data[27], data[28],
+                   data[29], data[30], data[31], data[32], data[33],
+                   be32_to_cpu(*native_val)
+           );
+
+       for (i = 0; i < 256; i++) {
+               str += sprintf(str, "%02X ", data[i + 39]);
+               if ((i + 1) % 16 == 0)
+                       str += sprintf(str, "\n");
+       }
+       return str - buf;
+}
+
+static DEVICE_ATTR(pubek, S_IRUGO, show_pubek, NULL);
+
+#define CAP_VER_RESULT_SIZE 18
+static u8 cap_version[] = {
+       0, 193,                 /* TPM_TAG_RQU_COMMAND */
+       0, 0, 0, 18,            /* length */
+       0, 0, 0, 101,           /* TPM_ORD_GetCapability */
+       0, 0, 0, 6,
+       0, 0, 0, 0
+};
+
+#define CAP_MANUFACTURER_RESULT_SIZE 18
+static u8 cap_manufacturer[] = {
+       0, 193,                 /* TPM_TAG_RQU_COMMAND */
+       0, 0, 0, 22,            /* length */
+       0, 0, 0, 101,           /* TPM_ORD_GetCapability */
+       0, 0, 0, 5,
+       0, 0, 0, 4,
+       0, 0, 1, 3
+};
+
+static ssize_t show_caps(struct device *dev, char *buf)
+{
+       u8 data[READ_PUBEK_RESULT_SIZE];
+       ssize_t len;
+       char *str = buf;
+
+       struct tpm_chip *chip =
+           pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+       if (chip == NULL)
+               return -ENODEV;
+
+       memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
+
+       if ((len = tpm_transmit(chip, data, sizeof(data))) <
+           CAP_MANUFACTURER_RESULT_SIZE)
+               return len;
+
+       str += sprintf(str, "Manufacturer: 0x%x\n",
+                      be32_to_cpu(*(data + 14)));
+
+       memcpy(data, cap_version, sizeof(cap_version));
+
+       if ((len = tpm_transmit(chip, data, sizeof(data))) <
+           CAP_VER_RESULT_SIZE)
+               return len;
+
+       str +=
+           sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
+                   (int) data[14], (int) data[15], (int) data[16],
+                   (int) data[17]);
+
+       return str - buf;
+}
+
+static DEVICE_ATTR(caps, S_IRUGO, show_caps, NULL);
+
+/*
+ * Device file system interface to the TPM
+ */
+int tpm_open(struct inode *inode, struct file *file)
+{
+       int rc = 0, minor = iminor(inode);
+       struct tpm_chip *chip = NULL, *pos;
+
+       spin_lock(&driver_lock);
+
+       list_for_each_entry(pos, &tpm_chip_list, list) {
+               if (pos->vendor->miscdev.minor == minor) {
+                       chip = pos;
+                       break;
+               }
+       }
+
+       if (chip == NULL) {
+               rc = -ENODEV;
+               goto err_out;
+       }
+
+       if (chip->num_opens) {
+               dev_dbg(&chip->pci_dev->dev,
+                       "Another process owns this TPM\n");
+               rc = -EBUSY;
+               goto err_out;
+       }
+
+       chip->num_opens++;
+       pci_dev_get(chip->pci_dev);
+
+       spin_unlock(&driver_lock);
+
+       chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+       if (chip->data_buffer == NULL) {
+               chip->num_opens--;
+               pci_dev_put(chip->pci_dev);
+               return -ENOMEM;
+       }
+
+       atomic_set(&chip->data_pending, 0);
+
+       file->private_data = chip;
+       return 0;
+
+err_out:
+       spin_unlock(&driver_lock);
+       return rc;
+}
+
+EXPORT_SYMBOL_GPL(tpm_open);
+
+int tpm_release(struct inode *inode, struct file *file)
+{
+       struct tpm_chip *chip = file->private_data;
+
+       file->private_data = NULL;
+
+       spin_lock(&driver_lock);
+       chip->num_opens--;
+       spin_unlock(&driver_lock);
+
+       down(&chip->timer_manipulation_mutex);
+       if (timer_pending(&chip->user_read_timer))
+               del_singleshot_timer_sync(&chip->user_read_timer);
+       else if (timer_pending(&chip->device_timer))
+               del_singleshot_timer_sync(&chip->device_timer);
+       up(&chip->timer_manipulation_mutex);
+
+       kfree(chip->data_buffer);
+       atomic_set(&chip->data_pending, 0);
+
+       pci_dev_put(chip->pci_dev);
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_release);
+
+ssize_t tpm_write(struct file * file, const char __user * buf,
+                 size_t size, loff_t * off)
+{
+       struct tpm_chip *chip = file->private_data;
+       int in_size = size, out_size;
+
+       /* cannot perform a write until the read has cleared
+          either via tpm_read or a user_read_timer timeout */
+       while (atomic_read(&chip->data_pending) != 0) {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(TPM_TIMEOUT);
+       }
+
+       down(&chip->buffer_mutex);
+
+       if (in_size > TPM_BUFSIZE)
+               in_size = TPM_BUFSIZE;
+
+       if (copy_from_user
+           (chip->data_buffer, (void __user *) buf, in_size)) {
+               up(&chip->buffer_mutex);
+               return -EFAULT;
+       }
+
+       /* atomic tpm command send and result receive */
+       out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
+
+       atomic_set(&chip->data_pending, out_size);
+       atomic_set(&chip->data_position, 0);
+       up(&chip->buffer_mutex);
+
+       /* Set a timeout by which the reader must come claim the result */
+       down(&chip->timer_manipulation_mutex);
+       init_timer(&chip->user_read_timer);
+       chip->user_read_timer.function = user_reader_timeout;
+       chip->user_read_timer.data = (unsigned long) chip;
+       chip->user_read_timer.expires = jiffies + (60 * HZ);
+       add_timer(&chip->user_read_timer);
+       up(&chip->timer_manipulation_mutex);
+
+       return in_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_write);
+
+ssize_t tpm_read(struct file * file, char __user * buf,
+                size_t size, loff_t * off)
+{
+       struct tpm_chip *chip = file->private_data;
+       int ret_size = -ENODATA;
+       int pos, pending = 0;
+
+       down(&chip->buffer_mutex);
+       ret_size = atomic_read(&chip->data_pending);
+       if ( ret_size > 0 ) {   /* Result available */
+               if (size < ret_size)
+                       ret_size = size;
+
+               pos = atomic_read(&chip->data_position);
+
+               if (copy_to_user((void __user *) buf,
+                                &chip->data_buffer[pos], ret_size)) {
+                       ret_size = -EFAULT;
+               } else {
+                       pending = atomic_read(&chip->data_pending) - ret_size;
+                       if ( pending ) {
+                               atomic_set( &chip->data_pending, pending );
+                               atomic_set( &chip->data_position, pos+ret_size 
);
+                       }
+               }
+       }
+       up(&chip->buffer_mutex);
+
+       if ( ret_size <= 0 || pending == 0 ) {
+               atomic_set( &chip->data_pending, 0 );
+               down(&chip->timer_manipulation_mutex);
+               del_singleshot_timer_sync(&chip->user_read_timer);
+               up(&chip->timer_manipulation_mutex);
+       }
+
+       return ret_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_read);
+
+void __devexit tpm_remove(struct pci_dev *pci_dev)
+{
+       struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+
+       if (chip == NULL) {
+               dev_err(&pci_dev->dev, "No device data found\n");
+               return;
+       }
+
+       spin_lock(&driver_lock);
+
+       list_del(&chip->list);
+
+       spin_unlock(&driver_lock);
+
+       pci_set_drvdata(pci_dev, NULL);
+       misc_deregister(&chip->vendor->miscdev);
+
+       device_remove_file(&pci_dev->dev, &dev_attr_pubek);
+       device_remove_file(&pci_dev->dev, &dev_attr_pcrs);
+       device_remove_file(&pci_dev->dev, &dev_attr_caps);
+
+       pci_disable_device(pci_dev);
+
+       dev_mask[chip->dev_num / 32] &= !(1 << (chip->dev_num % 32));
+
+       kfree(chip);
+
+       pci_dev_put(pci_dev);
+}
+
+EXPORT_SYMBOL_GPL(tpm_remove);
+
+static u8 savestate[] = {
+       0, 193,                 /* TPM_TAG_RQU_COMMAND */
+       0, 0, 0, 10,            /* blob length (in bytes) */
+       0, 0, 0, 152            /* TPM_ORD_SaveState */
+};
+
+/*
+ * We are about to suspend. Save the TPM state
+ * so that it can be restored.
+ */
+int tpm_pm_suspend(struct pci_dev *pci_dev, pm_message_t pm_state)
+{
+       struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+       if (chip == NULL)
+               return -ENODEV;
+
+       tpm_transmit(chip, savestate, sizeof(savestate));
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_suspend);
+
+/*
+ * Resume from a power safe. The BIOS already restored
+ * the TPM state.
+ */
+int tpm_pm_resume(struct pci_dev *pci_dev)
+{
+       struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+
+       if (chip == NULL)
+               return -ENODEV;
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_resume);
+
+/*
+ * Called from tpm_<specific>.c probe function only for devices
+ * the driver has determined it should claim.  Prior to calling
+ * this function the specific probe function has called pci_enable_device
+ * upon errant exit from this function specific probe function should call
+ * pci_disable_device
+ */
+int tpm_register_hardware(struct pci_dev *pci_dev,
+                         struct tpm_vendor_specific *entry)
+{
+       char devname[7];
+       struct tpm_chip *chip;
+       int i, j;
+
+       /* Driver specific per-device data */
+       chip = kmalloc(sizeof(*chip), GFP_KERNEL);
+       if (chip == NULL)
+               return -ENOMEM;
+
+       memset(chip, 0, sizeof(struct tpm_chip));
+
+       init_MUTEX(&chip->buffer_mutex);
+       init_MUTEX(&chip->tpm_mutex);
+       init_MUTEX(&chip->timer_manipulation_mutex);
+       INIT_LIST_HEAD(&chip->list);
+
+       chip->vendor = entry;
+
+       chip->dev_num = -1;
+
+       for (i = 0; i < 32; i++)
+               for (j = 0; j < 8; j++)
+                       if ((dev_mask[i] & (1 << j)) == 0) {
+                               chip->dev_num = i * 32 + j;
+                               dev_mask[i] |= 1 << j;
+                               goto dev_num_search_complete;
+                       }
+
+dev_num_search_complete:
+       if (chip->dev_num < 0) {
+               dev_err(&pci_dev->dev,
+                       "No available tpm device numbers\n");
+               kfree(chip);
+               return -ENODEV;
+       } else if (chip->dev_num == 0)
+               chip->vendor->miscdev.minor = TPM_MINOR;
+       else
+               chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
+
+       snprintf(devname, sizeof(devname), "%s%d", "tpm", chip->dev_num);
+       chip->vendor->miscdev.name = devname;
+
+       chip->vendor->miscdev.dev = &(pci_dev->dev);
+       chip->pci_dev = pci_dev_get(pci_dev);
+
+       if (misc_register(&chip->vendor->miscdev)) {
+               dev_err(&chip->pci_dev->dev,
+                       "unable to misc_register %s, minor %d\n",
+                       chip->vendor->miscdev.name,
+                       chip->vendor->miscdev.minor);
+               pci_dev_put(pci_dev);
+               kfree(chip);
+               dev_mask[i] &= !(1 << j);
+               return -ENODEV;
+       }
+
+       pci_set_drvdata(pci_dev, chip);
+
+       list_add(&chip->list, &tpm_chip_list);
+
+       device_create_file(&pci_dev->dev, &dev_attr_pubek);
+       device_create_file(&pci_dev->dev, &dev_attr_pcrs);
+       device_create_file(&pci_dev->dev, &dev_attr_caps);
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_register_hardware);
+
+static int __init init_tpm(void)
+{
+       return 0;
+}
+
+static void __exit cleanup_tpm(void)
+{
+
+}
+
+module_init(init_tpm);
+module_exit(cleanup_tpm);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/drivers/char/tpm/tpm.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.h       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+
+#define TPM_TIMEOUT msecs_to_jiffies(5)
+
+/* TPM addresses */
+#define        TPM_ADDR                        0x4E
+#define        TPM_DATA                        0x4F
+
+struct tpm_chip;
+
+struct tpm_vendor_specific {
+       u8 req_complete_mask;
+       u8 req_complete_val;
+       u16 base;               /* TPM base address */
+
+       int (*recv) (struct tpm_chip *, u8 *, size_t);
+       int (*send) (struct tpm_chip *, u8 *, size_t);
+       void (*cancel) (struct tpm_chip *);
+       struct miscdevice miscdev;
+};
+
+struct tpm_chip {
+       struct pci_dev *pci_dev;        /* PCI device stuff */
+
+       int dev_num;            /* /dev/tpm# */
+       int num_opens;          /* only one allowed */
+       int time_expired;
+
+       /* Data passed to and from the tpm via the read/write calls */
+       u8 *data_buffer;
+       atomic_t data_pending;
+       atomic_t data_position;
+       struct semaphore buffer_mutex;
+
+       struct timer_list user_read_timer;      /* user needs to claim result */
+       struct semaphore tpm_mutex;     /* tpm is processing */
+       struct timer_list device_timer; /* tpm is processing */
+       struct semaphore timer_manipulation_mutex;
+
+       struct tpm_vendor_specific *vendor;
+
+       struct list_head list;
+};
+
+static inline int tpm_read_index(int index)
+{
+       outb(index, TPM_ADDR);
+       return inb(TPM_DATA) & 0xFF;
+}
+
+static inline void tpm_write_index(int index, int value)
+{
+       outb(index, TPM_ADDR);
+       outb(value & 0xFF, TPM_DATA);
+}
+
+extern void tpm_time_expired(unsigned long);
+extern int tpm_register_hardware(struct pci_dev *,
+                                struct tpm_vendor_specific *);
+extern int tpm_open(struct inode *, struct file *);
+extern int tpm_release(struct inode *, struct file *);
+extern ssize_t tpm_write(struct file *, const char __user *, size_t,
+                        loff_t *);
+extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
+extern void __devexit tpm_remove(struct pci_dev *);
+extern int tpm_pm_suspend(struct pci_dev *, pm_message_t);
+extern int tpm_pm_resume(struct pci_dev *);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/char/tpm/tpm_atmel.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_atmel.c Fri Sep  9 16:30:54 2005
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include "tpm.h"
+
+/* Atmel definitions */
+enum tpm_atmel_addr {
+       TPM_ATMEL_BASE_ADDR_LO = 0x08,
+       TPM_ATMEL_BASE_ADDR_HI = 0x09
+};
+
+/* write status bits */
+#define        ATML_STATUS_ABORT               0x01
+#define        ATML_STATUS_LASTBYTE            0x04
+
+/* read status bits */
+#define        ATML_STATUS_BUSY                0x01
+#define        ATML_STATUS_DATA_AVAIL          0x02
+#define        ATML_STATUS_REWRITE             0x04
+
+
+static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+       u8 status, *hdr = buf;
+       u32 size;
+       int i;
+       __be32 *native_size;
+
+       /* start reading header */
+       if (count < 6)
+               return -EIO;
+
+       for (i = 0; i < 6; i++) {
+               status = inb(chip->vendor->base + 1);
+               if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+                       dev_err(&chip->pci_dev->dev,
+                               "error reading header\n");
+                       return -EIO;
+               }
+               *buf++ = inb(chip->vendor->base);
+       }
+
+       /* size of the data received */
+       native_size = (__force __be32 *) (hdr + 2);
+       size = be32_to_cpu(*native_size);
+
+       if (count < size) {
+               dev_err(&chip->pci_dev->dev,
+                       "Recv size(%d) less than available space\n", size);
+               for (; i < size; i++) { /* clear the waiting data anyway */
+                       status = inb(chip->vendor->base + 1);
+                       if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+                               dev_err(&chip->pci_dev->dev,
+                                       "error reading data\n");
+                               return -EIO;
+                       }
+               }
+               return -EIO;
+       }
+
+       /* read all the data available */
+       for (; i < size; i++) {
+               status = inb(chip->vendor->base + 1);
+               if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+                       dev_err(&chip->pci_dev->dev,
+                               "error reading data\n");
+                       return -EIO;
+               }
+               *buf++ = inb(chip->vendor->base);
+       }
+
+       /* make sure data available is gone */
+       status = inb(chip->vendor->base + 1);
+       if (status & ATML_STATUS_DATA_AVAIL) {
+               dev_err(&chip->pci_dev->dev, "data available is stuck\n");
+               return -EIO;
+       }
+
+       return size;
+}
+
+static int tpm_atml_send(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+       int i;
+
+       dev_dbg(&chip->pci_dev->dev, "tpm_atml_send: ");
+       for (i = 0; i < count; i++) {
+               dev_dbg(&chip->pci_dev->dev, "0x%x(%d) ", buf[i], buf[i]);
+               outb(buf[i], chip->vendor->base);
+       }
+
+       return count;
+}
+
+static void tpm_atml_cancel(struct tpm_chip *chip)
+{
+       outb(ATML_STATUS_ABORT, chip->vendor->base + 1);
+}
+
+static struct file_operations atmel_ops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .open = tpm_open,
+       .read = tpm_read,
+       .write = tpm_write,
+       .release = tpm_release,
+};
+
+static struct tpm_vendor_specific tpm_atmel = {
+       .recv = tpm_atml_recv,
+       .send = tpm_atml_send,
+       .cancel = tpm_atml_cancel,
+       .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
+       .req_complete_val = ATML_STATUS_DATA_AVAIL,
+       .miscdev = { .fops = &atmel_ops, },
+};
+
+static int __devinit tpm_atml_init(struct pci_dev *pci_dev,
+                                  const struct pci_device_id *pci_id)
+{
+       u8 version[4];
+       int rc = 0;
+       int lo, hi;
+
+       if (pci_enable_device(pci_dev))
+               return -EIO;
+
+       lo = tpm_read_index( TPM_ATMEL_BASE_ADDR_LO );
+       hi = tpm_read_index( TPM_ATMEL_BASE_ADDR_HI );
+
+       tpm_atmel.base = (hi<<8)|lo;
+       dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base);
+
+       /* verify that it is an Atmel part */
+       if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T'
+           || tpm_read_index(6) != 'M' || tpm_read_index(7) != 'L') {
+               rc = -ENODEV;
+               goto out_err;
+       }
+
+       /* query chip for its version number */
+       if ((version[0] = tpm_read_index(0x00)) != 0xFF) {
+               version[1] = tpm_read_index(0x01);
+               version[2] = tpm_read_index(0x02);
+               version[3] = tpm_read_index(0x03);
+       } else {
+               dev_info(&pci_dev->dev, "version query failed\n");
+               rc = -ENODEV;
+               goto out_err;
+       }
+
+       if ((rc = tpm_register_hardware(pci_dev, &tpm_atmel)) < 0)
+               goto out_err;
+
+       dev_info(&pci_dev->dev,
+                "Atmel TPM version %d.%d.%d.%d\n", version[0], version[1],
+                version[2], version[3]);
+
+       return 0;
+out_err:
+       pci_disable_device(pci_dev);
+       return rc;
+}
+
+static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+       {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
+
+static struct pci_driver atmel_pci_driver = {
+       .name = "tpm_atmel",
+       .id_table = tpm_pci_tbl,
+       .probe = tpm_atml_init,
+       .remove = __devexit_p(tpm_remove),
+       .suspend = tpm_pm_suspend,
+       .resume = tpm_pm_resume,
+};
+
+static int __init init_atmel(void)
+{
+       return pci_register_driver(&atmel_pci_driver);
+}
+
+static void __exit cleanup_atmel(void)
+{
+       pci_unregister_driver(&atmel_pci_driver);
+}
+
+module_init(init_atmel);
+module_exit(cleanup_atmel);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.c Fri Sep  9 16:30:54 2005
@@ -0,0 +1,741 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * Note, the TPM chip is not interrupt driven (only polling)
+ * and can have very long timeouts (minutes!). Hence the unusual
+ * calls to schedule_timeout.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/spinlock.h>
+#include "tpm_nopci.h"
+
+enum {
+       TPM_MINOR = 224,        /* officially assigned */
+       TPM_BUFSIZE = 2048,
+       TPM_NUM_DEVICES = 256,
+       TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
+};
+
+  /* PCI configuration addresses */
+enum {
+       PCI_GEN_PMCON_1 = 0xA0,
+       PCI_GEN1_DEC = 0xE4,
+       PCI_LPC_EN = 0xE6,
+       PCI_GEN2_DEC = 0xEC
+};
+
+enum {
+       TPM_LOCK_REG = 0x0D,
+       TPM_INTERUPT_REG = 0x0A,
+       TPM_BASE_ADDR_LO = 0x08,
+       TPM_BASE_ADDR_HI = 0x09,
+       TPM_UNLOCK_VALUE = 0x55,
+       TPM_LOCK_VALUE = 0xAA,
+       TPM_DISABLE_INTERUPT_VALUE = 0x00
+};
+
+static LIST_HEAD(tpm_chip_list);
+static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
+static int dev_mask[32];
+
+static void user_reader_timeout(unsigned long ptr)
+{
+       struct tpm_chip *chip = (struct tpm_chip *) ptr;
+
+       down(&chip->buffer_mutex);
+       atomic_set(&chip->data_pending, 0);
+       memset(chip->data_buffer, 0, TPM_BUFSIZE);
+       up(&chip->buffer_mutex);
+}
+
+void tpm_time_expired(unsigned long ptr)
+{
+       int *exp = (int *) ptr;
+       *exp = 1;
+}
+
+EXPORT_SYMBOL_GPL(tpm_time_expired);
+
+
+/*
+ * This function should be used by other kernel subsystems attempting to use 
the tpm through the tpm_transmit interface.
+ * A call to this function will return the chip structure corresponding to the 
TPM you are looking for that can then be sent with your command to tpm_transmit.
+ * Passing 0 as the argument corresponds to /dev/tpm0 and thus the first and 
probably primary TPM on the system.  Passing 1 corresponds to /dev/tpm1 and the 
next TPM discovered.  If a TPM with the given chip_num does not exist NULL will 
be returned.
+ */
+struct tpm_chip* tpm_chip_lookup(int chip_num)
+{
+
+       struct tpm_chip *pos;
+       list_for_each_entry(pos, &tpm_chip_list, list)
+               if (pos->dev_num == chip_num ||
+                   chip_num == TPM_ANY_NUM)
+                       return pos;
+
+       return NULL;
+
+}
+
+/*
+ * Internal kernel interface to transmit TPM commands
+ */
+ssize_t tpm_transmit(struct tpm_chip * chip, const char *buf,
+                    size_t bufsiz)
+{
+       ssize_t rc;
+       u32 count;
+       unsigned long stop;
+
+       count = be32_to_cpu(*((__be32 *) (buf + 2)));
+
+       if (count == 0)
+               return -ENODATA;
+       if (count > bufsiz) {
+               dev_err(chip->dev,
+                       "invalid count value %x %x \n", count, bufsiz);
+               return -E2BIG;
+       }
+
+       dev_dbg(chip->dev, "TPM Ordinal: %d\n",
+               be32_to_cpu(*((__be32 *) (buf + 6))));
+       dev_dbg(chip->dev, "Chip Status: %x\n",
+               inb(chip->vendor->base + 1));
+
+       down(&chip->tpm_mutex);
+
+       if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+               dev_err(chip->dev,
+                       "tpm_transmit: tpm_send: error %d\n", rc);
+               goto out;
+       }
+
+       stop = jiffies + 2 * 60 * HZ;
+       do {
+               u8 status = chip->vendor->status(chip);
+               if ((status & chip->vendor->req_complete_mask) ==
+                   chip->vendor->req_complete_val) {
+                       goto out_recv;
+               }
+
+               if ((status == chip->vendor->req_canceled)) {
+                       dev_err(chip->dev, "Operation Canceled\n");
+                       rc = -ECANCELED;
+                       goto out;
+               }
+
+               msleep(TPM_TIMEOUT);    /* CHECK */
+               rmb();
+       }
+       while (time_before(jiffies, stop));
+
+
+       chip->vendor->cancel(chip);
+       dev_err(chip->dev, "Operation Timed out\n");
+       rc = -ETIME;
+       goto out;
+
+out_recv:
+       rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+       if (rc < 0)
+               dev_err(chip->dev,
+                       "tpm_transmit: tpm_recv: error %d\n", rc);
+       atomic_set(&chip->data_position, 0);
+
+out:
+       up(&chip->tpm_mutex);
+       return rc;
+}
+
+EXPORT_SYMBOL_GPL(tpm_transmit);
+
+#define TPM_DIGEST_SIZE 20
+#define CAP_PCR_RESULT_SIZE 18
+static const u8 cap_pcr[] = {
+       0, 193,                 /* TPM_TAG_RQU_COMMAND */
+       0, 0, 0, 22,            /* length */
+       0, 0, 0, 101,           /* TPM_ORD_GetCapability */
+       0, 0, 0, 5,
+       0, 0, 0, 4,
+       0, 0, 1, 1
+};
+
+#define READ_PCR_RESULT_SIZE 30
+static const u8 pcrread[] = {
+       0, 193,                 /* TPM_TAG_RQU_COMMAND */
+       0, 0, 0, 14,            /* length */
+       0, 0, 0, 21,            /* TPM_ORD_PcrRead */
+       0, 0, 0, 0              /* PCR index */
+};
+
+ssize_t tpm_show_pcrs(struct device *dev, char *buf)
+{
+       u8 data[READ_PCR_RESULT_SIZE];
+       ssize_t len;
+       int i, j, num_pcrs;
+       __be32 index;
+       char *str = buf;
+
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+       if (chip == NULL)
+               return -ENODEV;
+
+       memcpy(data, cap_pcr, sizeof(cap_pcr));
+       if ((len = tpm_transmit(chip, data, sizeof(data)))
+           < CAP_PCR_RESULT_SIZE)
+               return len;
+
+       num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
+
+       for (i = 0; i < num_pcrs; i++) {
+               memcpy(data, pcrread, sizeof(pcrread));
+               index = cpu_to_be32(i);
+               memcpy(data + 10, &index, 4);
+               if ((len = tpm_transmit(chip, data, sizeof(data)))
+                   < READ_PCR_RESULT_SIZE)
+                       return len;
+               str += sprintf(str, "PCR-%02d: ", i);
+               for (j = 0; j < TPM_DIGEST_SIZE; j++)
+                       str += sprintf(str, "%02X ", *(data + 10 + j));
+               str += sprintf(str, "\n");
+       }
+       return str - buf;
+}
+
+EXPORT_SYMBOL_GPL(tpm_show_pcrs);
+
+/*
+ * Return 0 on success.  On error pass along error code.
+ * chip_id Upper 2 bytes equal ANY, HW_ONLY or SW_ONLY
+ * Lower 2 bytes equal tpm idx # or AN&
+ * res_buf must fit a TPM_PCR (20 bytes) or NULL if you don't care
+ */
+int tpm_pcr_read( u32 chip_id, int pcr_idx, u8* res_buf, int res_buf_size )
+{
+       u8 data[READ_PCR_RESULT_SIZE];
+       int rc;
+       __be32 index;
+       int chip_num = chip_id & TPM_CHIP_NUM_MASK;
+       struct tpm_chip* chip;
+
+       if ( res_buf && res_buf_size < TPM_DIGEST_SIZE )
+               return -ENOSPC;
+       if ( (chip = tpm_chip_lookup( chip_num /*,
+                                      chip_id >> TPM_CHIP_TYPE_SHIFT*/ ) ) == 
NULL ) {
+               printk("chip %d not found.\n",chip_num);
+               return -ENODEV;
+       }
+       memcpy(data, pcrread, sizeof(pcrread));
+       index = cpu_to_be32(pcr_idx);
+       memcpy(data + 10, &index, 4);
+       if ((rc = tpm_transmit(chip, data, sizeof(data))) > 0 )
+               rc = be32_to_cpu(*((u32*)(data+6)));
+
+       if ( rc == 0 && res_buf )
+               memcpy(res_buf, data+10, TPM_DIGEST_SIZE);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_pcr_read);
+
+#define EXTEND_PCR_SIZE 34
+static const u8 pcrextend[] = {
+       0, 193,                                          /* TPM_TAG_RQU_COMMAND 
*/
+       0, 0, 0, 34,                             /* length */
+       0, 0, 0, 20,                             /* TPM_ORD_Extend */
+       0, 0, 0, 0                               /* PCR index */
+};
+
+/*
+ * Return 0 on success.  On error pass along error code.
+ * chip_id Upper 2 bytes equal ANY, HW_ONLY or SW_ONLY
+ * Lower 2 bytes equal tpm idx # or ANY
+ */
+int tpm_pcr_extend(u32 chip_id, int pcr_idx, const u8* hash)
+{
+       u8 data[EXTEND_PCR_SIZE];
+       int rc;
+       __be32 index;
+       int chip_num = chip_id & TPM_CHIP_NUM_MASK;
+       struct tpm_chip* chip;
+
+       if ( (chip = tpm_chip_lookup( chip_num /*,
+                                     chip_id >> TPM_CHIP_TYPE_SHIFT */)) == 
NULL )
+               return -ENODEV;
+
+       memcpy(data, pcrextend, sizeof(pcrextend));
+       index = cpu_to_be32(pcr_idx);
+       memcpy(data + 10, &index, 4);
+       memcpy( data + 14, hash, TPM_DIGEST_SIZE );
+       if ((rc = tpm_transmit(chip, data, sizeof(data))) > 0 )
+               rc = be32_to_cpu(*((u32*)(data+6)));
+       return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_pcr_extend);
+
+
+
+#define  READ_PUBEK_RESULT_SIZE 314
+static const u8 readpubek[] = {
+       0, 193,                 /* TPM_TAG_RQU_COMMAND */
+       0, 0, 0, 30,            /* length */
+       0, 0, 0, 124,           /* TPM_ORD_ReadPubek */
+};
+
+ssize_t tpm_show_pubek(struct device *dev, char *buf)
+{
+       u8 *data;
+       ssize_t len;
+       int i, rc;
+       char *str = buf;
+
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+       if (chip == NULL)
+               return -ENODEV;
+
+       data = kmalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       memcpy(data, readpubek, sizeof(readpubek));
+       memset(data + sizeof(readpubek), 0, 20);        /* zero nonce */
+
+       if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
+           READ_PUBEK_RESULT_SIZE) {
+               rc = len;
+               goto out;
+       }
+
+       /*
+          ignore header 10 bytes
+          algorithm 32 bits (1 == RSA )
+          encscheme 16 bits
+          sigscheme 16 bits
+          parameters (RSA 12->bytes: keybit, #primes, expbit)
+          keylenbytes 32 bits
+          256 byte modulus
+          ignore checksum 20 bytes
+        */
+
+       str +=
+           sprintf(str,
+                   "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
+                   "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X"
+                   " %02X %02X %02X %02X %02X %02X %02X %02X\n"
+                   "Modulus length: %d\nModulus: \n",
+                   data[10], data[11], data[12], data[13], data[14],
+                   data[15], data[16], data[17], data[22], data[23],
+                   data[24], data[25], data[26], data[27], data[28],
+                   data[29], data[30], data[31], data[32], data[33],
+                   be32_to_cpu(*((__be32 *) (data + 32))));
+
+       for (i = 0; i < 256; i++) {
+               str += sprintf(str, "%02X ", data[i + 39]);
+               if ((i + 1) % 16 == 0)
+                       str += sprintf(str, "\n");
+       }
+       rc = str - buf;
+out:
+       kfree(data);
+       return rc;
+}
+
+EXPORT_SYMBOL_GPL(tpm_show_pubek);
+
+#define CAP_VER_RESULT_SIZE 18
+static const u8 cap_version[] = {
+       0, 193,                 /* TPM_TAG_RQU_COMMAND */
+       0, 0, 0, 18,            /* length */
+       0, 0, 0, 101,           /* TPM_ORD_GetCapability */
+       0, 0, 0, 6,
+       0, 0, 0, 0
+};
+
+#define CAP_MANUFACTURER_RESULT_SIZE 18
+static const u8 cap_manufacturer[] = {
+       0, 193,                 /* TPM_TAG_RQU_COMMAND */
+       0, 0, 0, 22,            /* length */
+       0, 0, 0, 101,           /* TPM_ORD_GetCapability */
+       0, 0, 0, 5,
+       0, 0, 0, 4,
+       0, 0, 1, 3
+};
+
+ssize_t tpm_show_caps(struct device *dev, char *buf)
+{
+       u8 data[sizeof(cap_manufacturer)];
+       ssize_t len;
+       char *str = buf;
+
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+       if (chip == NULL)
+               return -ENODEV;
+
+       memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
+
+       if ((len = tpm_transmit(chip, data, sizeof(data))) <
+           CAP_MANUFACTURER_RESULT_SIZE)
+               return len;
+
+       str += sprintf(str, "Manufacturer: 0x%x\n",
+                      be32_to_cpu(*((__be32 *)(data + 14))));
+
+       memcpy(data, cap_version, sizeof(cap_version));
+
+       if ((len = tpm_transmit(chip, data, sizeof(data))) <
+           CAP_VER_RESULT_SIZE)
+               return len;
+
+       str +=
+           sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
+                   (int) data[14], (int) data[15], (int) data[16],
+                   (int) data[17]);
+
+       return str - buf;
+}
+
+EXPORT_SYMBOL_GPL(tpm_show_caps);
+
+ssize_t tpm_store_cancel(struct device * dev, const char *buf,
+                        size_t count)
+{
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+       if (chip == NULL)
+               return 0;
+
+       chip->vendor->cancel(chip);
+       return count;
+}
+
+EXPORT_SYMBOL_GPL(tpm_store_cancel);
+
+/*
+ * Device file system interface to the TPM
+ */
+int tpm_open(struct inode *inode, struct file *file)
+{
+       int rc = 0, minor = iminor(inode);
+       struct tpm_chip *chip = NULL, *pos;
+
+       spin_lock(&driver_lock);
+
+       list_for_each_entry(pos, &tpm_chip_list, list) {
+               if (pos->vendor->miscdev.minor == minor) {
+                       chip = pos;
+                       break;
+               }
+       }
+
+       if (chip == NULL) {
+               rc = -ENODEV;
+               goto err_out;
+       }
+
+       if (chip->num_opens) {
+               dev_dbg(chip->dev, "Another process owns this TPM\n");
+               rc = -EBUSY;
+               goto err_out;
+       }
+
+       chip->num_opens++;
+       get_device(chip->dev);
+
+       spin_unlock(&driver_lock);
+
+       chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+       if (chip->data_buffer == NULL) {
+               chip->num_opens--;
+               put_device(chip->dev);
+               return -ENOMEM;
+       }
+
+       atomic_set(&chip->data_pending, 0);
+
+       file->private_data = chip;
+       return 0;
+
+err_out:
+       spin_unlock(&driver_lock);
+       return rc;
+}
+
+EXPORT_SYMBOL_GPL(tpm_open);
+
+int tpm_release(struct inode *inode, struct file *file)
+{
+       struct tpm_chip *chip = file->private_data;
+
+       spin_lock(&driver_lock);
+       file->private_data = NULL;
+       chip->num_opens--;
+       del_singleshot_timer_sync(&chip->user_read_timer);
+       atomic_set(&chip->data_pending, 0);
+       put_device(chip->dev);
+       kfree(chip->data_buffer);
+       spin_unlock(&driver_lock);
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_release);
+
+ssize_t tpm_write(struct file * file, const char __user * buf,
+                 size_t size, loff_t * off)
+{
+       struct tpm_chip *chip = file->private_data;
+       int in_size = size, out_size;
+
+       /* cannot perform a write until the read has cleared
+          either via tpm_read or a user_read_timer timeout */
+       while (atomic_read(&chip->data_pending) != 0)
+               msleep(TPM_TIMEOUT);
+
+       down(&chip->buffer_mutex);
+
+       if (in_size > TPM_BUFSIZE)
+               in_size = TPM_BUFSIZE;
+
+       if (copy_from_user
+           (chip->data_buffer, (void __user *) buf, in_size)) {
+               up(&chip->buffer_mutex);
+               return -EFAULT;
+       }
+
+       /* atomic tpm command send and result receive */
+       out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
+
+       atomic_set(&chip->data_pending, out_size);
+       up(&chip->buffer_mutex);
+
+       /* Set a timeout by which the reader must come claim the result */
+       mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
+
+       return in_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_write);
+
+ssize_t tpm_read(struct file * file, char __user * buf,
+                size_t size, loff_t * off)
+{
+       struct tpm_chip *chip = file->private_data;
+       int ret_size;
+
+       del_singleshot_timer_sync(&chip->user_read_timer);
+       ret_size = atomic_read(&chip->data_pending);
+
+       if (ret_size > 0) {     /* relay data */
+               int position = atomic_read(&chip->data_position);
+
+               if (size < ret_size)
+                       ret_size = size;
+
+               down(&chip->buffer_mutex);
+
+               if (copy_to_user((void __user *) buf,
+                                &chip->data_buffer[position],
+                                ret_size)) {
+                       ret_size = -EFAULT;
+               } else {
+                       int pending = atomic_read(&chip->data_pending) - 
ret_size;
+                       atomic_set(&chip->data_pending,
+                                  pending);
+                       atomic_set(&chip->data_position,
+                                  position + ret_size);
+               }
+               up(&chip->buffer_mutex);
+       }
+
+       return ret_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_read);
+
+void tpm_remove_hardware(struct device *dev)
+{
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+       int i;
+
+       if (chip == NULL) {
+               dev_err(dev, "No device data found\n");
+               return;
+       }
+
+       spin_lock(&driver_lock);
+
+       list_del(&chip->list);
+
+       spin_unlock(&driver_lock);
+
+       dev_set_drvdata(dev, NULL);
+       misc_deregister(&chip->vendor->miscdev);
+
+       for (i = 0; i < TPM_NUM_ATTR; i++)
+               device_remove_file(dev, &chip->vendor->attr[i]);
+
+       dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES] &=
+           !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
+
+       kfree(chip);
+
+       put_device(dev);
+}
+
+EXPORT_SYMBOL_GPL(tpm_remove_hardware);
+
+static const u8 savestate[] = {
+       0, 193,                 /* TPM_TAG_RQU_COMMAND */
+       0, 0, 0, 10,            /* blob length (in bytes) */
+       0, 0, 0, 152            /* TPM_ORD_SaveState */
+};
+
+/*
+ * We are about to suspend. Save the TPM state
+ * so that it can be restored.
+ */
+int tpm_pm_suspend(struct pci_dev *pci_dev, u32 pm_state)
+{
+       struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+       if (chip == NULL)
+               return -ENODEV;
+
+       tpm_transmit(chip, savestate, sizeof(savestate));
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_suspend);
+
+/*
+ * Resume from a power safe. The BIOS already restored
+ * the TPM state.
+ */
+int tpm_pm_resume(struct pci_dev *pci_dev)
+{
+       struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+
+       if (chip == NULL)
+               return -ENODEV;
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_resume);
+
+/*
+ * Called from tpm_<specific>.c probe function only for devices
+ * the driver has determined it should claim.  Prior to calling
+ * this function the specific probe function has called pci_enable_device
+ * upon errant exit from this function specific probe function should call
+ * pci_disable_device
+ */
+int tpm_register_hardware_nopci(struct device *dev,
+                               struct tpm_vendor_specific *entry)
+{
+       char devname[7];
+       struct tpm_chip *chip;
+       int i, j;
+
+       /* Driver specific per-device data */
+       chip = kmalloc(sizeof(*chip), GFP_KERNEL);
+       if (chip == NULL)
+               return -ENOMEM;
+
+       memset(chip, 0, sizeof(struct tpm_chip));
+
+       init_MUTEX(&chip->buffer_mutex);
+       init_MUTEX(&chip->tpm_mutex);
+       INIT_LIST_HEAD(&chip->list);
+
+       init_timer(&chip->user_read_timer);
+       chip->user_read_timer.function = user_reader_timeout;
+       chip->user_read_timer.data = (unsigned long) chip;
+
+       chip->vendor = entry;
+
+       chip->dev_num = -1;
+
+       for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
+               for (j = 0; j < 8 * sizeof(int); j++)
+                       if ((dev_mask[i] & (1 << j)) == 0) {
+                               chip->dev_num =
+                                   i * TPM_NUM_MASK_ENTRIES + j;
+                               dev_mask[i] |= 1 << j;
+                               goto dev_num_search_complete;
+                       }
+
+dev_num_search_complete:
+       if (chip->dev_num < 0) {
+               dev_err(dev, "No available tpm device numbers\n");
+               kfree(chip);
+               return -ENODEV;
+       } else if (chip->dev_num == 0)
+               chip->vendor->miscdev.minor = TPM_MINOR;
+       else
+               chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
+
+       snprintf(devname, sizeof(devname), "%s%d", "tpm", chip->dev_num);
+       chip->vendor->miscdev.name = devname;
+
+       chip->vendor->miscdev.dev = dev;
+       chip->dev = get_device(dev);
+
+
+       if (misc_register(&chip->vendor->miscdev)) {
+               dev_err(chip->dev,
+                       "unable to misc_register %s, minor %d\n",
+                       chip->vendor->miscdev.name,
+                       chip->vendor->miscdev.minor);
+               put_device(dev);
+               kfree(chip);
+               dev_mask[i] &= !(1 << j);
+               return -ENODEV;
+       }
+
+       spin_lock(&driver_lock);
+
+       dev_set_drvdata(dev, chip);
+
+       list_add(&chip->list, &tpm_chip_list);
+
+       spin_unlock(&driver_lock);
+
+       for (i = 0; i < TPM_NUM_ATTR; i++)
+               device_create_file(dev, &chip->vendor->attr[i]);
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_register_hardware_nopci);
+
+static int __init init_tpm(void)
+{
+       return 0;
+}
+
+static void __exit cleanup_tpm(void)
+{
+
+}
+
+module_init(init_tpm);
+module_exit(cleanup_tpm);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.h Fri Sep  9 16:30:54 2005
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/miscdevice.h>
+
+enum {
+       TPM_TIMEOUT = 5,        /* msecs */
+       TPM_NUM_ATTR = 4
+};
+
+/* TPM addresses */
+enum {
+       TPM_ADDR = 0x4E,
+       TPM_DATA = 0x4F
+};
+
+/*
+ * Chip num is this value or a valid tpm idx in lower two bytes of chip_id
+ */
+enum tpm_chip_num {
+       TPM_ANY_NUM = 0xFFFF,
+};
+
+#define TPM_CHIP_NUM_MASK      0x0000ffff
+
+extern ssize_t tpm_show_pubek(struct device *, char *);
+extern ssize_t tpm_show_pcrs(struct device *, char *);
+extern ssize_t tpm_show_caps(struct device *, char *);
+extern ssize_t tpm_store_cancel(struct device *, const char *, size_t);
+
+#define TPM_DEVICE_ATTRS { \
+       __ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL), \
+       __ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL), \
+       __ATTR(caps, S_IRUGO, tpm_show_caps, NULL), \
+       __ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel) }
+
+struct tpm_chip;
+
+struct tpm_vendor_specific {
+       u8 req_complete_mask;
+       u8 req_complete_val;
+       u8 req_canceled;
+       u16 base;               /* TPM base address */
+
+       int (*recv) (struct tpm_chip *, u8 *, size_t);
+       int (*send) (struct tpm_chip *, u8 *, size_t);
+       void (*cancel) (struct tpm_chip *);
+        u8(*status) (struct tpm_chip *);
+       struct miscdevice miscdev;
+       struct device_attribute attr[TPM_NUM_ATTR];
+};
+
+struct tpm_chip {
+       struct device *dev;     /* PCI device stuff */
+
+       int dev_num;            /* /dev/tpm# */
+       int num_opens;          /* only one allowed */
+       int time_expired;
+
+       /* Data passed to and from the tpm via the read/write calls */
+       u8 *data_buffer;
+       atomic_t data_pending;
+       atomic_t data_position;
+       struct semaphore buffer_mutex;
+
+       struct timer_list user_read_timer;      /* user needs to claim result */
+       struct semaphore tpm_mutex;     /* tpm is processing */
+
+       struct tpm_vendor_specific *vendor;
+
+       struct list_head list;
+};
+
+static inline int tpm_read_index(int index)
+{
+       outb(index, TPM_ADDR);
+       return inb(TPM_DATA) & 0xFF;
+}
+
+static inline void tpm_write_index(int index, int value)
+{
+       outb(index, TPM_ADDR);
+       outb(value & 0xFF, TPM_DATA);
+}
+
+extern void tpm_time_expired(unsigned long);
+extern int tpm_lpc_bus_init(struct pci_dev *, u16);
+
+extern int tpm_register_hardware_nopci(struct device *,
+                                      struct tpm_vendor_specific *);
+extern void tpm_remove_hardware(struct device *);
+extern int tpm_open(struct inode *, struct file *);
+extern int tpm_release(struct inode *, struct file *);
+extern ssize_t tpm_write(struct file *, const char __user *, size_t,
+                        loff_t *);
+extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
+extern int tpm_pcr_extend(u32 chip_id, int pcr_idx, const u8* hash);
+extern int tpm_pcr_read( u32 chip_id, int pcr_idx, u8* res_buf, int 
res_buf_size );
+
+extern int tpm_pm_suspend(struct pci_dev *, u32);
+extern int tpm_pm_resume(struct pci_dev *);
+
+/* internal kernel interface */
+extern ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
+                           size_t bufsiz);
+extern struct tpm_chip *tpm_chip_lookup(int chip_num);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/char/tpm/tpm_nsc.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nsc.c   Fri Sep  9 16:30:54 2005
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include "tpm.h"
+
+/* National definitions */
+#define        TPM_NSC_BASE                    0x360
+#define        TPM_NSC_IRQ                     0x07
+#define        TPM_NSC_BASE0_HI                0x60
+#define        TPM_NSC_BASE0_LO                0x61
+#define        TPM_NSC_BASE1_HI                0x62
+#define        TPM_NSC_BASE1_LO                0x63
+
+#define        NSC_LDN_INDEX                   0x07
+#define        NSC_SID_INDEX                   0x20
+#define        NSC_LDC_INDEX                   0x30
+#define        NSC_DIO_INDEX                   0x60
+#define        NSC_CIO_INDEX                   0x62
+#define        NSC_IRQ_INDEX                   0x70
+#define        NSC_ITS_INDEX                   0x71
+
+#define        NSC_STATUS                      0x01
+#define        NSC_COMMAND                     0x01
+#define        NSC_DATA                        0x00
+
+/* status bits */
+#define        NSC_STATUS_OBF                  0x01    /* output buffer full */
+#define        NSC_STATUS_IBF                  0x02    /* input buffer full */
+#define        NSC_STATUS_F0                   0x04    /* F0 */
+#define        NSC_STATUS_A2                   0x08    /* A2 */
+#define        NSC_STATUS_RDY                  0x10    /* ready to receive 
command */
+#define        NSC_STATUS_IBR                  0x20    /* ready to receive 
data */
+
+/* command bits */
+#define        NSC_COMMAND_NORMAL              0x01    /* normal mode */
+#define        NSC_COMMAND_EOC                 0x03
+#define        NSC_COMMAND_CANCEL              0x22
+
+/*
+ * Wait for a certain status to appear
+ */
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
+{
+       int expired = 0;
+       struct timer_list status_timer =
+           TIMER_INITIALIZER(tpm_time_expired, jiffies + 10 * HZ,
+                             (unsigned long) &expired);
+
+       /* status immediately available check */
+       *data = inb(chip->vendor->base + NSC_STATUS);
+       if ((*data & mask) == val)
+               return 0;
+
+       /* wait for status */
+       add_timer(&status_timer);
+       do {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(TPM_TIMEOUT);
+               *data = inb(chip->vendor->base + 1);
+               if ((*data & mask) == val) {
+                       del_singleshot_timer_sync(&status_timer);
+                       return 0;
+               }
+       }
+       while (!expired);
+
+       return -EBUSY;
+}
+
+static int nsc_wait_for_ready(struct tpm_chip *chip)
+{
+       int status;
+       int expired = 0;
+       struct timer_list status_timer =
+           TIMER_INITIALIZER(tpm_time_expired, jiffies + 100,
+                             (unsigned long) &expired);
+
+       /* status immediately available check */
+       status = inb(chip->vendor->base + NSC_STATUS);
+       if (status & NSC_STATUS_OBF)
+               status = inb(chip->vendor->base + NSC_DATA);
+       if (status & NSC_STATUS_RDY)
+               return 0;
+
+       /* wait for status */
+       add_timer(&status_timer);
+       do {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(TPM_TIMEOUT);
+               status = inb(chip->vendor->base + NSC_STATUS);
+               if (status & NSC_STATUS_OBF)
+                       status = inb(chip->vendor->base + NSC_DATA);
+               if (status & NSC_STATUS_RDY) {
+                       del_singleshot_timer_sync(&status_timer);
+                       return 0;
+               }
+       }
+       while (!expired);
+
+       dev_info(&chip->pci_dev->dev, "wait for ready failed\n");
+       return -EBUSY;
+}
+
+
+static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+       u8 *buffer = buf;
+       u8 data, *p;
+       u32 size;
+       __be32 *native_size;
+
+       if (count < 6)
+               return -EIO;
+
+       if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) {
+               dev_err(&chip->pci_dev->dev, "F0 timeout\n");
+               return -EIO;
+       }
+       if ((data =
+            inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
+               dev_err(&chip->pci_dev->dev, "not in normal mode (0x%x)\n",
+                       data);
+               return -EIO;
+       }
+
+       /* read the whole packet */
+       for (p = buffer; p < &buffer[count]; p++) {
+               if (wait_for_stat
+                   (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) {
+                       dev_err(&chip->pci_dev->dev,
+                               "OBF timeout (while reading data)\n");
+                       return -EIO;
+               }
+               if (data & NSC_STATUS_F0)
+                       break;
+               *p = inb(chip->vendor->base + NSC_DATA);
+       }
+
+       if ((data & NSC_STATUS_F0) == 0) {
+               dev_err(&chip->pci_dev->dev, "F0 not set\n");
+               return -EIO;
+       }
+       if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
+               dev_err(&chip->pci_dev->dev,
+                       "expected end of command(0x%x)\n", data);
+               return -EIO;
+       }
+
+       native_size = (__force __be32 *) (buf + 2);
+       size = be32_to_cpu(*native_size);
+
+       if (count < size)
+               return -EIO;
+
+       return size;
+}
+
+static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+       u8 data;
+       int i;
+
+       /*
+        * If we hit the chip with back to back commands it locks up
+        * and never set IBF. Hitting it with this "hammer" seems to
+        * fix it. Not sure why this is needed, we followed the flow
+        * chart in the manual to the letter.
+        */
+       outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+
+       if (nsc_wait_for_ready(chip) != 0)
+               return -EIO;
+
+       if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+               dev_err(&chip->pci_dev->dev, "IBF timeout\n");
+               return -EIO;
+       }
+
+       outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
+       if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
+               dev_err(&chip->pci_dev->dev, "IBR timeout\n");
+               return -EIO;
+       }
+
+       for (i = 0; i < count; i++) {
+               if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+                       dev_err(&chip->pci_dev->dev,
+                               "IBF timeout (while writing data)\n");
+                       return -EIO;
+               }
+               outb(buf[i], chip->vendor->base + NSC_DATA);
+       }
+
+       if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+               dev_err(&chip->pci_dev->dev, "IBF timeout\n");
+               return -EIO;
+       }
+       outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
+
+       return count;
+}
+
+static void tpm_nsc_cancel(struct tpm_chip *chip)
+{
+       outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+}
+
+static struct file_operations nsc_ops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .open = tpm_open,
+       .read = tpm_read,
+       .write = tpm_write,
+       .release = tpm_release,
+};
+
+static struct tpm_vendor_specific tpm_nsc = {
+       .recv = tpm_nsc_recv,
+       .send = tpm_nsc_send,
+       .cancel = tpm_nsc_cancel,
+       .req_complete_mask = NSC_STATUS_OBF,
+       .req_complete_val = NSC_STATUS_OBF,
+       .miscdev = { .fops = &nsc_ops, },
+
+};
+
+static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
+                                 const struct pci_device_id *pci_id)
+{
+       int rc = 0;
+       int lo, hi;
+
+       hi = tpm_read_index(TPM_NSC_BASE0_HI);
+       lo = tpm_read_index(TPM_NSC_BASE0_LO);
+
+       tpm_nsc.base = (hi<<8) | lo;
+
+       if (pci_enable_device(pci_dev))
+               return -EIO;
+
+       /* verify that it is a National part (SID) */
+       if (tpm_read_index(NSC_SID_INDEX) != 0xEF) {
+               rc = -ENODEV;
+               goto out_err;
+       }
+
+       dev_dbg(&pci_dev->dev, "NSC TPM detected\n");
+       dev_dbg(&pci_dev->dev,
+               "NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
+               tpm_read_index(0x07), tpm_read_index(0x20),
+               tpm_read_index(0x27));
+       dev_dbg(&pci_dev->dev,
+               "NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n",
+               tpm_read_index(0x21), tpm_read_index(0x25),
+               tpm_read_index(0x26), tpm_read_index(0x28));
+       dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n",
+               (tpm_read_index(0x60) << 8) | tpm_read_index(0x61));
+       dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n",
+               (tpm_read_index(0x62) << 8) | tpm_read_index(0x63));
+       dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n",
+               tpm_read_index(0x70));
+       dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n",
+               tpm_read_index(0x71));
+       dev_dbg(&pci_dev->dev,
+               "NSC DMA channel select0 0x%x, select1 0x%x\n",
+               tpm_read_index(0x74), tpm_read_index(0x75));
+       dev_dbg(&pci_dev->dev,
+               "NSC Config "
+               "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+               tpm_read_index(0xF0), tpm_read_index(0xF1),
+               tpm_read_index(0xF2), tpm_read_index(0xF3),
+               tpm_read_index(0xF4), tpm_read_index(0xF5),
+               tpm_read_index(0xF6), tpm_read_index(0xF7),
+               tpm_read_index(0xF8), tpm_read_index(0xF9));
+
+       dev_info(&pci_dev->dev,
+                "NSC PC21100 TPM revision %d\n",
+                tpm_read_index(0x27) & 0x1F);
+
+       if (tpm_read_index(NSC_LDC_INDEX) == 0)
+               dev_info(&pci_dev->dev, ": NSC TPM not active\n");
+
+       /* select PM channel 1 */
+       tpm_write_index(NSC_LDN_INDEX, 0x12);
+       tpm_read_index(NSC_LDN_INDEX);
+
+       /* disable the DPM module */
+       tpm_write_index(NSC_LDC_INDEX, 0);
+       tpm_read_index(NSC_LDC_INDEX);
+
+       /* set the data register base addresses */
+       tpm_write_index(NSC_DIO_INDEX, TPM_NSC_BASE >> 8);
+       tpm_write_index(NSC_DIO_INDEX + 1, TPM_NSC_BASE);
+       tpm_read_index(NSC_DIO_INDEX);
+       tpm_read_index(NSC_DIO_INDEX + 1);
+
+       /* set the command register base addresses */
+       tpm_write_index(NSC_CIO_INDEX, (TPM_NSC_BASE + 1) >> 8);
+       tpm_write_index(NSC_CIO_INDEX + 1, (TPM_NSC_BASE + 1));
+       tpm_read_index(NSC_DIO_INDEX);
+       tpm_read_index(NSC_DIO_INDEX + 1);
+
+       /* set the interrupt number to be used for the host interface */
+       tpm_write_index(NSC_IRQ_INDEX, TPM_NSC_IRQ);
+       tpm_write_index(NSC_ITS_INDEX, 0x00);
+       tpm_read_index(NSC_IRQ_INDEX);
+
+       /* enable the DPM module */
+       tpm_write_index(NSC_LDC_INDEX, 0x01);
+       tpm_read_index(NSC_LDC_INDEX);
+
+       if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0)
+               goto out_err;
+
+       return 0;
+
+out_err:
+       pci_disable_device(pci_dev);
+       return rc;
+}
+
+static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+       {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
+
+static struct pci_driver nsc_pci_driver = {
+       .name = "tpm_nsc",
+       .id_table = tpm_pci_tbl,
+       .probe = tpm_nsc_init,
+       .remove = __devexit_p(tpm_remove),
+       .suspend = tpm_pm_suspend,
+       .resume = tpm_pm_resume,
+};
+
+static int __init init_nsc(void)
+{
+       return pci_register_driver(&nsc_pci_driver);
+}
+
+static void __exit cleanup_nsc(void)
+{
+       pci_unregister_driver(&nsc_pci_driver);
+}
+
+module_init(init_nsc);
+module_exit(cleanup_nsc);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c   Fri Sep  9 16:30:54 2005
@@ -0,0 +1,513 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ * Stefan Berger <stefanb@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module) for XEN.
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include <asm/uaccess.h>
+#include <linux/list.h>
+#include <linux/tpmfe.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include "tpm_nopci.h"
+
+/* read status bits */
+enum {
+       STATUS_BUSY = 0x01,
+       STATUS_DATA_AVAIL = 0x02,
+       STATUS_READY = 0x04
+};
+
+#define MIN(x,y)  ((x) < (y)) ? (x) : (y)
+
+struct transmission {
+       struct list_head next;
+       unsigned char *request;
+       unsigned int request_len;
+       unsigned char *rcv_buffer;
+       unsigned int  buffersize;
+       struct tpm_chip     *chip;
+       unsigned int flags;
+};
+
+enum {
+       TRANSMISSION_FLAG_WAS_QUEUED = 0x1
+};
+
+struct data_exchange {
+       struct transmission *current_request;
+       spinlock_t           req_list_lock;
+       wait_queue_head_t    req_wait_queue;
+
+       struct list_head     queued_requests;
+
+       struct transmission *current_response;
+       spinlock_t           resp_list_lock;
+       wait_queue_head_t    resp_wait_queue;     // processes waiting for 
responses
+
+       struct transmission *req_cancelled;       // if a cancellation was 
encounterd
+
+       unsigned int         fe_status;
+       unsigned int         flags;
+};
+
+enum {
+       DATAEX_FLAG_QUEUED_ONLY = 0x1
+};
+
+static struct data_exchange dataex;
+
+static unsigned long disconnect_time;
+
+/* local function prototypes */
+static void __exit cleanup_xen(void);
+
+
+/* =============================================================
+ * Some utility functions
+ * =============================================================
+ */
+static inline struct transmission *
+transmission_alloc(void)
+{
+       struct transmission *t = kmalloc(sizeof(*t), GFP_KERNEL);
+       if (t) {
+               memset(t, 0x0, sizeof(*t));
+       }
+       return t;
+}
+
+static inline unsigned char *
+transmission_set_buffer(struct transmission *t,
+                        unsigned char *buffer, unsigned int len)
+{
+       if (NULL != t->request) {
+               kfree(t->request);
+       }
+       t->request = kmalloc(len, GFP_KERNEL);
+       if (t->request) {
+               memcpy(t->request,
+                      buffer,
+                      len);
+               t->request_len = len;
+       }
+       return t->request;
+}
+
+static inline void
+transmission_free(struct transmission *t)
+{
+       if (t->request) {
+               kfree(t->request);
+       }
+       if (t->rcv_buffer) {
+               kfree(t->rcv_buffer);
+       }
+       kfree(t);
+}
+
+/* =============================================================
+ * Interface with the TPM shared memory driver for XEN
+ * =============================================================
+ */
+static int tpm_recv(const u8 *buffer, size_t count, const void *ptr)
+{
+       int ret_size = 0;
+       struct transmission *t, *temp;
+
+       /*
+        * The list with requests must contain one request
+        * only and the element there must be the one that
+        * was passed to me from the front-end.
+        */
+       if (dataex.current_request != ptr) {
+               printk("WARNING: The request pointer is different than the 
pointer "
+                      "the shared memory driver returned to me. %p != %p\n",
+                      dataex.current_request, ptr);
+       }
+
+       /*
+        * If the request has been cancelled, just quit here
+        */
+       if (dataex.req_cancelled == (struct transmission *)ptr) {
+               if (dataex.current_request == dataex.req_cancelled) {
+                       dataex.current_request = NULL;
+               }
+               transmission_free(dataex.req_cancelled);
+               dataex.req_cancelled = NULL;
+               return 0;
+       }
+
+       if (NULL != (temp = dataex.current_request)) {
+               transmission_free(temp);
+               dataex.current_request = NULL;
+       }
+
+       t = transmission_alloc();
+       if (NULL != t) {
+               unsigned long flags;
+               t->rcv_buffer = kmalloc(count, GFP_KERNEL);
+               if (NULL == t->rcv_buffer) {
+                       transmission_free(t);
+                       return -ENOMEM;
+               }
+               t->buffersize = count;
+               memcpy(t->rcv_buffer, buffer, count);
+               ret_size = count;
+
+               spin_lock_irqsave(&dataex.resp_list_lock ,flags);
+               dataex.current_response = t;
+               spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+               wake_up_interruptible(&dataex.resp_wait_queue);
+       }
+       return ret_size;
+}
+
+
+static void tpm_fe_status(unsigned int flags)
+{
+       dataex.fe_status = flags;
+       if ((dataex.fe_status & TPMFE_STATUS_CONNECTED) == 0) {
+               disconnect_time = jiffies;
+       }
+}
+
+/* =============================================================
+ * Interface with the generic TPM driver
+ * =============================================================
+ */
+static int tpm_xen_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+       unsigned long flags;
+       int rc = 0;
+
+       spin_lock_irqsave(&dataex.resp_list_lock, flags);
+       /*
+        * Check if the previous operation only queued the command
+        * In this case there won't be a response, so I just
+        * return from here and reset that flag. In any other
+        * case I should receive a response from the back-end.
+        */
+       if ((dataex.flags & DATAEX_FLAG_QUEUED_ONLY) != 0) {
+               dataex.flags &= ~DATAEX_FLAG_QUEUED_ONLY;
+               spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+               /*
+                * a little hack here. The first few measurements
+                * are queued since there's no way to talk to the
+                * TPM yet (due to slowness of the control channel)
+                * So we just make IMA happy by giving it 30 NULL
+                * bytes back where the most important part is
+                * that the result code is '0'.
+                */
+
+               count = MIN(count, 30);
+               memset(buf, 0x0, count);
+               return count;
+       }
+       /*
+        * Check whether something is in the responselist and if
+        * there's nothing in the list wait for something to appear.
+        */
+
+       if (NULL == dataex.current_response) {
+               spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+               interruptible_sleep_on_timeout(&dataex.resp_wait_queue,
+                                              1000);
+               spin_lock_irqsave(&dataex.resp_list_lock ,flags);
+       }
+
+       if (NULL != dataex.current_response) {
+               struct transmission *t = dataex.current_response;
+               dataex.current_response = NULL;
+               rc = MIN(count, t->buffersize);
+               memcpy(buf, t->rcv_buffer, rc);
+               transmission_free(t);
+       }
+
+       spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+       return rc;
+}
+
+static int tpm_xen_send(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+       /*
+        * We simply pass the packet onto the XEN shared
+        * memory driver.
+        */
+       unsigned long flags;
+       int rc;
+       struct transmission *t = transmission_alloc();
+
+       spin_lock_irqsave(&dataex.req_list_lock, flags);
+       /*
+        * If there's a current request, it must be the
+        * previous request that has timed out.
+        */
+       if (dataex.current_request != NULL) {
+               printk("WARNING: Sending although there is a request 
outstanding.\n"
+                      "         Previous request must have timed out.\n");
+               transmission_free(dataex.current_request);
+               dataex.current_request = NULL;
+       }
+
+       if (t != NULL) {
+               unsigned int error = 0;
+               t->rcv_buffer = NULL;
+               t->buffersize = 0;
+               t->chip = chip;
+
+               /*
+                * Queue the packet if the driver below is not
+                * ready, yet, or there is any packet already
+                * in the queue.
+                * If the driver below is ready, unqueue all
+                * packets first before sending our current
+                * packet.
+                * For each unqueued packet, except for the
+                * last (=current) packet, call the function
+                * tpm_xen_recv to wait for the response to come
+                * back.
+                */
+               if ((dataex.fe_status & TPMFE_STATUS_CONNECTED) == 0) {
+                       if (time_after(jiffies, disconnect_time + HZ * 10)) {
+                               rc = -ENOENT;
+                       } else {
+                               /*
+                                * copy the request into the buffer
+                                */
+                               if (transmission_set_buffer(t, buf, count)
+                                   == NULL) {
+                                       transmission_free(t);
+                                       rc = -ENOMEM;
+                                       goto exit;
+                               }
+                               dataex.flags |= DATAEX_FLAG_QUEUED_ONLY;
+                               list_add_tail(&t->next, 
&dataex.queued_requests);
+                               rc = 0;
+                       }
+               } else {
+                       /*
+                        * Check whether there are any packets in the queue
+                        */
+                       while (!list_empty(&dataex.queued_requests)) {
+                               /*
+                                * Need to dequeue them.
+                                * Read the result into a dummy buffer.
+                                */
+                               unsigned char buffer[1];
+                               struct transmission *qt = (struct transmission 
*) dataex.queued_requests.next;
+                               list_del(&qt->next);
+                               dataex.current_request = qt;
+                               spin_unlock_irqrestore(&dataex.req_list_lock, 
flags);
+
+                               rc = tpm_fe_send(qt->request,
+                                                qt->request_len,
+                                                qt);
+
+                               if (rc < 0) {
+                                       
spin_lock_irqsave(&dataex.req_list_lock, flags);
+                                       if ((qt = dataex.current_request) != 
NULL) {
+                                               /*
+                                                * requeue it at the beginning
+                                                * of the list
+                                                */
+                                               list_add(&qt->next,
+                                                        
&dataex.queued_requests);
+                                       }
+                                       dataex.current_request = NULL;
+                                       error = 1;
+                                       break;
+                               }
+                               /*
+                                * After this point qt is not valid anymore!
+                                * It is freed when the front-end is delivering 
the data
+                                * by calling tpm_recv
+                                */
+
+                               /*
+                                * Try to receive the response now into the 
provided dummy
+                                * buffer (I don't really care about this 
response since
+                                * there is no receiver anymore for this 
response)
+                                */
+                               rc = tpm_xen_recv(chip, buffer, sizeof(buffer));
+
+                               spin_lock_irqsave(&dataex.req_list_lock, flags);
+                       }
+
+                       if (error == 0) {
+                               /*
+                                * Finally, send the current request.
+                                */
+                               dataex.current_request = t;
+                               /*
+                                * Call the shared memory driver
+                                * Pass to it the buffer with the request, the
+                                * amount of bytes in the request and
+                                * a void * pointer (here: transmission 
structure)
+                                */
+                               rc = tpm_fe_send(buf, count, t);
+                               /*
+                                * The generic TPM driver will call
+                                * the function to receive the response.
+                                */
+                               if (rc < 0) {
+                                       dataex.current_request = NULL;
+                                       goto queue_it;
+                               }
+                       } else {
+queue_it:
+                               if (transmission_set_buffer(t, buf, count) == 
NULL) {
+                                       transmission_free(t);
+                                       rc = -ENOMEM;
+                                       goto exit;
+                               }
+                               /*
+                                * An error occurred. Don't event try
+                                * to send the current request. Just
+                                * queue it.
+                                */
+                               dataex.flags |= DATAEX_FLAG_QUEUED_ONLY;
+                               list_add_tail(&t->next, 
&dataex.queued_requests);
+                               rc = 0;
+                       }
+               }
+       } else {
+               rc = -ENOMEM;
+       }
+
+exit:
+       spin_unlock_irqrestore(&dataex.req_list_lock, flags);
+       return rc;
+}
+
+static void tpm_xen_cancel(struct tpm_chip *chip)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&dataex.resp_list_lock,flags);
+
+       dataex.req_cancelled = dataex.current_request;
+
+       spin_unlock_irqrestore(&dataex.resp_list_lock,flags);
+}
+
+static u8 tpm_xen_status(struct tpm_chip *chip)
+{
+       unsigned long flags;
+       u8 rc = 0;
+       spin_lock_irqsave(&dataex.resp_list_lock, flags);
+       /*
+        * Data are available if:
+        *  - there's a current response
+        *  - the last packet was queued only (this is fake, but necessary to
+        *      get the generic TPM layer to call the receive function.)
+        */
+       if (NULL != dataex.current_response ||
+           0 != (dataex.flags & DATAEX_FLAG_QUEUED_ONLY)) {
+               rc = STATUS_DATA_AVAIL;
+       }
+       spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+       return rc;
+}
+
+static struct file_operations tpm_xen_ops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .open = tpm_open,
+       .read = tpm_read,
+       .write = tpm_write,
+       .release = tpm_release,
+};
+
+static struct tpm_vendor_specific tpm_xen = {
+       .recv = tpm_xen_recv,
+       .send = tpm_xen_send,
+       .cancel = tpm_xen_cancel,
+       .status = tpm_xen_status,
+       .req_complete_mask = STATUS_BUSY | STATUS_DATA_AVAIL,
+       .req_complete_val  = STATUS_DATA_AVAIL,
+       .req_canceled = STATUS_READY,
+       .base = 0,
+       .attr = TPM_DEVICE_ATTRS,
+       .miscdev.fops = &tpm_xen_ops,
+};
+
+static struct device tpm_device = {
+       .bus_id = "vtpm",
+};
+
+static struct tpmfe_device tpmfe = {
+       .receive = tpm_recv,
+       .status  = tpm_fe_status,
+};
+
+
+static int __init init_xen(void)
+{
+       int rc;
+
+       /*
+        * Register device with the low lever front-end
+        * driver
+        */
+       if ((rc = tpm_fe_register_receiver(&tpmfe)) < 0) {
+               return rc;
+       }
+
+       /*
+        * Register our device with the system.
+        */
+       if ((rc = device_register(&tpm_device)) < 0) {
+               tpm_fe_unregister_receiver();
+               return rc;
+       }
+
+       if ((rc = tpm_register_hardware_nopci(&tpm_device, &tpm_xen)) < 0) {
+               device_unregister(&tpm_device);
+               tpm_fe_unregister_receiver();
+               return rc;
+       }
+
+       dataex.current_request = NULL;
+       spin_lock_init(&dataex.req_list_lock);
+       init_waitqueue_head(&dataex.req_wait_queue);
+       INIT_LIST_HEAD(&dataex.queued_requests);
+
+       dataex.current_response = NULL;
+       spin_lock_init(&dataex.resp_list_lock);
+       init_waitqueue_head(&dataex.resp_wait_queue);
+
+       disconnect_time = jiffies;
+
+       return 0;
+}
+
+static void __exit cleanup_xen(void)
+{
+       tpm_remove_hardware(&tpm_device);
+       device_unregister(&tpm_device);
+       tpm_fe_unregister_receiver();
+}
+
+fs_initcall(init_xen);
+module_exit(cleanup_xen);
+
+MODULE_AUTHOR("Stefan Berger (stefanb@xxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver for XEN (shared memory)");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/blktap/common.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h  Fri Sep  9 16:30:54 2005
@@ -0,0 +1,112 @@
+
+#ifndef __BLKIF__BACKEND__COMMON_H__
+#define __BLKIF__BACKEND__COMMON_H__
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/pgalloc.h>
+#include <asm-xen/evtchn.h>
+#include <asm-xen/hypervisor.h>
+#include <asm-xen/xen-public/io/blkif.h>
+#include <asm-xen/xen-public/io/ring.h>
+#include <asm-xen/gnttab.h>
+
+#if 0
+#define ASSERT(_p) \
+    if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
+    __LINE__, __FILE__); *(int*)0=0; }
+#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
+                           __FILE__ , __LINE__ , ## _a )
+#else
+#define ASSERT(_p) ((void)0)
+#define DPRINTK(_f, _a...) ((void)0)
+#endif
+
+#define WPRINTK(fmt, args...) printk(KERN_WARNING "blk_tap: " fmt, ##args)
+
+struct vbd {
+    blkif_vdev_t   handle;      /* what the domain refers to this vbd as */
+    unsigned char  readonly;    /* Non-zero -> read-only */
+    unsigned char  type;        /* VDISK_xxx */
+    blkif_pdev_t   pdevice;     /* phys device that this vbd maps to */
+    struct block_device *bdev;
+}; 
+
+typedef struct blkif_st {
+    /* Unique identifier for this interface. */
+    domid_t           domid;
+    unsigned int      handle;
+    /* Physical parameters of the comms window. */
+    unsigned long     shmem_frame;
+    unsigned int      evtchn;
+    unsigned int      remote_evtchn;
+    /* Comms information. */
+    blkif_back_ring_t blk_ring;
+    /* VBDs attached to this interface. */
+    struct vbd        vbd;
+    /* Private fields. */
+    enum { DISCONNECTED, CONNECTED } status;
+#ifdef CONFIG_XEN_BLKDEV_TAP_BE
+    /* Is this a blktap frontend */
+    unsigned int     is_blktap;
+#endif
+    struct list_head blkdev_list;
+    spinlock_t       blk_ring_lock;
+    atomic_t         refcnt;
+
+    struct work_struct free_work;
+    u16 shmem_handle;
+    unsigned long shmem_vaddr;
+    grant_ref_t shmem_ref;
+} blkif_t;
+
+void blkif_create(blkif_be_create_t *create);
+void blkif_destroy(blkif_be_destroy_t *destroy);
+void blkif_connect(blkif_be_connect_t *connect);
+int  blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id);
+void blkif_disconnect_complete(blkif_t *blkif);
+blkif_t *alloc_blkif(domid_t domid);
+void free_blkif_callback(blkif_t *blkif);
+int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn);
+
+#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
+#define blkif_put(_b)                             \
+    do {                                          \
+        if ( atomic_dec_and_test(&(_b)->refcnt) ) \
+            free_blkif_callback(_b);             \
+    } while (0)
+
+/* Create a vbd. */
+int vbd_create(blkif_t *blkif, blkif_vdev_t vdevice, blkif_pdev_t pdevice,
+              int readonly);
+void vbd_free(struct vbd *vbd);
+
+unsigned long vbd_size(struct vbd *vbd);
+unsigned int vbd_info(struct vbd *vbd);
+unsigned long vbd_secsize(struct vbd *vbd);
+
+struct phys_req {
+    unsigned short       dev;
+    unsigned short       nr_sects;
+    struct block_device *bdev;
+    blkif_sector_t       sector_number;
+};
+
+int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation); 
+
+void blkif_interface_init(void);
+
+void blkif_deschedule(blkif_t *blkif);
+
+void blkif_xenbus_init(void);
+
+irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
+
+#endif /* __BLKIF__BACKEND__COMMON_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/blktap/interface.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c       Fri Sep  9 
16:30:54 2005
@@ -0,0 +1,141 @@
+/******************************************************************************
+ * arch/xen/drivers/blkif/backend/interface.c
+ * 
+ * Block-device interface management.
+ * 
+ * Copyright (c) 2004, Keir Fraser
+ */
+
+#include "common.h"
+#include <asm-xen/evtchn.h>
+
+static kmem_cache_t *blkif_cachep;
+
+blkif_t *alloc_blkif(domid_t domid)
+{
+    blkif_t *blkif;
+
+    blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL);
+    if (!blkif)
+           return ERR_PTR(-ENOMEM);
+
+    memset(blkif, 0, sizeof(*blkif));
+    blkif->domid = domid;
+    blkif->status = DISCONNECTED;
+    spin_lock_init(&blkif->blk_ring_lock);
+    atomic_set(&blkif->refcnt, 1);
+
+    return blkif;
+}
+
+static int map_frontend_page(blkif_t *blkif, unsigned long localaddr,
+                            unsigned long shared_page)
+{
+    struct gnttab_map_grant_ref op;
+    op.host_addr = localaddr;
+    op.flags = GNTMAP_host_map;
+    op.ref = shared_page;
+    op.dom = blkif->domid;
+
+    BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
+
+    if (op.handle < 0) {
+       DPRINTK(" Grant table operation failure !\n");
+       return op.handle;
+    }
+
+    blkif->shmem_ref = shared_page;
+    blkif->shmem_handle = op.handle;
+    blkif->shmem_vaddr = localaddr;
+    return 0;
+}
+
+static void unmap_frontend_page(blkif_t *blkif)
+{
+    struct gnttab_unmap_grant_ref op;
+
+    op.host_addr = blkif->shmem_vaddr;
+    op.handle = blkif->shmem_handle;
+    op.dev_bus_addr = 0;
+    BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
+}
+
+int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
+{
+    struct vm_struct *vma;
+    blkif_sring_t *sring;
+    evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
+    int err;
+
+    BUG_ON(blkif->remote_evtchn);
+
+    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
+       return -ENOMEM;
+
+    err = map_frontend_page(blkif, (unsigned long)vma->addr, shared_page);
+    if (err) {
+        vfree(vma->addr);
+       return err;
+    }
+
+    op.u.bind_interdomain.dom1 = DOMID_SELF;
+    op.u.bind_interdomain.dom2 = blkif->domid;
+    op.u.bind_interdomain.port1 = 0;
+    op.u.bind_interdomain.port2 = evtchn;
+    err = HYPERVISOR_event_channel_op(&op);
+    if (err) {
+       unmap_frontend_page(blkif);
+       vfree(vma->addr);
+       return err;
+    }
+
+    blkif->evtchn = op.u.bind_interdomain.port1;
+    blkif->remote_evtchn = evtchn;
+
+    sring = (blkif_sring_t *)vma->addr;
+    SHARED_RING_INIT(sring);
+    BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
+
+    bind_evtchn_to_irqhandler(blkif->evtchn, blkif_be_int, 0, "blkif-backend",
+                             blkif);
+    blkif->status        = CONNECTED;
+    blkif->shmem_frame   = shared_page;
+
+    return 0;
+}
+
+static void free_blkif(void *arg)
+{
+    evtchn_op_t op = { .cmd = EVTCHNOP_close };
+    blkif_t *blkif = (blkif_t *)arg;
+
+    op.u.close.port = blkif->evtchn;
+    op.u.close.dom = DOMID_SELF;
+    HYPERVISOR_event_channel_op(&op);
+    op.u.close.port = blkif->remote_evtchn;
+    op.u.close.dom = blkif->domid;
+    HYPERVISOR_event_channel_op(&op);
+
+    if (blkif->evtchn)
+        unbind_evtchn_from_irqhandler(blkif->evtchn, blkif);
+
+    if (blkif->blk_ring.sring) {
+       unmap_frontend_page(blkif);
+       vfree(blkif->blk_ring.sring);
+       blkif->blk_ring.sring = NULL;
+    }
+
+    kmem_cache_free(blkif_cachep, blkif);
+}
+
+void free_blkif_callback(blkif_t *blkif)
+{
+    INIT_WORK(&blkif->free_work, free_blkif, (void *)blkif);
+    schedule_work(&blkif->free_work);
+}
+
+void __init blkif_interface_init(void)
+{
+    blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t), 
+                                     0, 0, NULL, NULL);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c  Fri Sep  9 16:30:54 2005
@@ -0,0 +1,225 @@
+/*  Xenbus code for blkif tap
+
+    A Warfield.
+
+    Hastily modified from the oroginal backend code:
+
+    Copyright (C) 2005 Rusty Russell <rusty@xxxxxxxxxxxxxxx>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that 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 <stdarg.h>
+#include <linux/module.h>
+#include <asm-xen/xenbus.h>
+#include "common.h"
+
+struct backend_info
+{
+       struct xenbus_device *dev;
+
+       /* our communications channel */
+       blkif_t *blkif;
+
+       long int frontend_id;
+
+       /* watch back end for changes */
+       struct xenbus_watch backend_watch;
+
+       /* watch front end for changes */
+       struct xenbus_watch watch;
+       char *frontpath;
+};
+
+static int blkback_remove(struct xenbus_device *dev)
+{
+       struct backend_info *be = dev->data;
+
+       if (be->watch.node)
+               unregister_xenbus_watch(&be->watch);
+       unregister_xenbus_watch(&be->backend_watch);
+       if (be->blkif)
+               blkif_put(be->blkif);
+       if (be->frontpath)
+               kfree(be->frontpath);
+       kfree(be);
+       return 0;
+}
+
+/* Front end tells us frame. */
+static void frontend_changed(struct xenbus_watch *watch, const char *node)
+{
+       unsigned long ring_ref;
+       unsigned int evtchn;
+       int err;
+       struct backend_info *be
+               = container_of(watch, struct backend_info, watch);
+
+       /* If other end is gone, delete ourself. */
+       if (node && !xenbus_exists(be->frontpath, "")) {
+               xenbus_rm(be->dev->nodename, "");
+               device_unregister(&be->dev->dev);
+               return;
+       }
+       if (be->blkif == NULL || be->blkif->status == CONNECTED)
+               return;
+
+       err = xenbus_gather(be->frontpath, "ring-ref", "%lu", &ring_ref,
+                           "event-channel", "%u", &evtchn, NULL);
+       if (err) {
+               xenbus_dev_error(be->dev, err,
+                                "reading %s/ring-ref and event-channel",
+                                be->frontpath);
+               return;
+       }
+
+       /* Map the shared frame, irq etc. */
+       err = blkif_map(be->blkif, ring_ref, evtchn);
+       if (err) {
+               xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u",
+                                ring_ref, evtchn);
+               goto abort;
+       }
+
+       xenbus_dev_ok(be->dev);
+
+       return;
+
+abort:
+       xenbus_transaction_end(1);
+}
+
+/* 
+   Setup supplies physical device.  
+   We provide event channel and device details to front end.
+   Frontend supplies shared frame and event channel.
+ */
+static void backend_changed(struct xenbus_watch *watch, const char *node)
+{
+       int err;
+       char *p;
+       long int handle;
+       struct backend_info *be
+               = container_of(watch, struct backend_info, backend_watch);
+       struct xenbus_device *dev = be->dev;
+
+       if (be->blkif == NULL) {
+               /* Front end dir is a number, which is used as the handle. */
+               p = strrchr(be->frontpath, '/') + 1;
+               handle = simple_strtoul(p, NULL, 0);
+
+               be->blkif = alloc_blkif(be->frontend_id);
+               if (IS_ERR(be->blkif)) {
+                       err = PTR_ERR(be->blkif);
+                       be->blkif = NULL;
+                       xenbus_dev_error(dev, err, "creating block interface");
+                       return;
+               }
+
+               /* Pass in NULL node to skip exist test. */
+               frontend_changed(&be->watch, NULL);
+       }
+}
+
+static int blkback_probe(struct xenbus_device *dev,
+                        const struct xenbus_device_id *id)
+{
+       struct backend_info *be;
+       char *frontend;
+       int err;
+
+       be = kmalloc(sizeof(*be), GFP_KERNEL);
+       if (!be) {
+               xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
+               return -ENOMEM;
+       }
+       memset(be, 0, sizeof(*be));
+
+       frontend = NULL;
+       err = xenbus_gather(dev->nodename,
+                           "frontend-id", "%li", &be->frontend_id,
+                           "frontend", NULL, &frontend,
+                           NULL);
+       if (XENBUS_EXIST_ERR(err))
+               goto free_be;
+       if (err < 0) {
+               xenbus_dev_error(dev, err,
+                                "reading %s/frontend or frontend-id",
+                                dev->nodename);
+               goto free_be;
+       }
+       if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
+               /* If we can't get a frontend path and a frontend-id,
+                * then our bus-id is no longer valid and we need to
+                * destroy the backend device.
+                */
+               err = -ENOENT;
+               goto free_be;
+       }
+
+       be->dev = dev;
+       be->backend_watch.node = dev->nodename;
+       be->backend_watch.callback = backend_changed;
+       err = register_xenbus_watch(&be->backend_watch);
+       if (err) {
+               be->backend_watch.node = NULL;
+               xenbus_dev_error(dev, err, "adding backend watch on %s",
+                                dev->nodename);
+               goto free_be;
+       }
+
+       be->frontpath = frontend;
+       be->watch.node = be->frontpath;
+       be->watch.callback = frontend_changed;
+       err = register_xenbus_watch(&be->watch);
+       if (err) {
+               be->watch.node = NULL;
+               xenbus_dev_error(dev, err,
+                                "adding frontend watch on %s",
+                                be->frontpath);
+               goto free_be;
+       }
+
+       dev->data = be;
+
+       backend_changed(&be->backend_watch, dev->nodename);
+       return 0;
+
+ free_be:
+       if (be->backend_watch.node)
+               unregister_xenbus_watch(&be->backend_watch);
+       if (frontend)
+               kfree(frontend);
+       kfree(be);
+       return err;
+}
+
+static struct xenbus_device_id blkback_ids[] = {
+       { "vbd" },
+       { "" }
+};
+
+static struct xenbus_driver blkback = {
+       .name = "vbd",
+       .owner = THIS_MODULE,
+       .ids = blkback_ids,
+       .probe = blkback_probe,
+       .remove = blkback_remove,
+};
+
+void blkif_xenbus_init(void)
+{
+       xenbus_register_backend(&blkback);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c   Fri Sep  9 
16:30:54 2005
@@ -0,0 +1,128 @@
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <asm-xen/hypervisor.h>
+#include <asm-xen/evtchn.h>
+#include <linux/wait.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include "xencons_ring.h"
+
+
+struct ring_head
+{
+       u32 cons;
+       u32 prod;
+       char buf[0];
+} __attribute__((packed));
+
+
+#define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head))
+#define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE)
+#define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE)
+
+static inline struct ring_head *outring(void)
+{
+       return machine_to_virt(xen_start_info->console_mfn << PAGE_SHIFT);
+}
+
+static inline struct ring_head *inring(void)
+{
+       return machine_to_virt(xen_start_info->console_mfn << PAGE_SHIFT)
+               + PAGE_SIZE/2;
+}
+
+
+/* don't block -  write as much as possible and return */
+static int __xencons_ring_send(struct ring_head *ring, const char *data, 
unsigned len)
+{
+       int copied = 0;
+
+       mb();
+       while (copied < len && !XENCONS_FULL(ring)) {
+               ring->buf[XENCONS_IDX(ring->prod)] = data[copied];
+               ring->prod++;
+               copied++;
+       }
+       mb();
+
+       return copied;
+}
+
+int xencons_ring_send(const char *data, unsigned len)
+{
+       struct ring_head *out = outring();
+       int sent = 0;
+       
+       sent = __xencons_ring_send(out, data, len);
+       notify_via_evtchn(xen_start_info->console_evtchn);
+       return sent;
+
+}      
+
+
+static xencons_receiver_func *xencons_receiver;
+
+static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs)
+{
+       struct ring_head *ring = inring();
+       while (ring->cons < ring->prod) {
+               if (xencons_receiver != NULL) {
+                       xencons_receiver(ring->buf + XENCONS_IDX(ring->cons),
+                                        1, regs);
+               }
+               ring->cons++;
+       }
+       return IRQ_HANDLED;
+}
+
+void xencons_ring_register_receiver(xencons_receiver_func *f)
+{
+       xencons_receiver = f;
+}
+
+int xencons_ring_init(void)
+{
+       int err;
+
+       if (!xen_start_info->console_evtchn)
+               return 0;
+
+       err = bind_evtchn_to_irqhandler(xen_start_info->console_evtchn,
+                                       handle_input, 0, "xencons", inring());
+       if (err) {
+               xprintk("XEN console request irq failed %i\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+void xencons_suspend(void)
+{
+
+       if (!xen_start_info->console_evtchn)
+               return;
+
+       unbind_evtchn_from_irqhandler(xen_start_info->console_evtchn,
+                                     inring());
+}
+
+void xencons_resume(void)
+{
+
+       (void)xencons_ring_init();
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.h   Fri Sep  9 
16:30:54 2005
@@ -0,0 +1,14 @@
+#ifndef _XENCONS_RING_H
+#define _XENCONS_RING_H
+
+asmlinkage int xprintk(const char *fmt, ...);
+
+
+int xencons_ring_init(void);
+int xencons_ring_send(const char *data, unsigned len);
+
+typedef void (xencons_receiver_func)(char *buf, unsigned len, 
+                                     struct pt_regs *regs);
+void xencons_ring_register_receiver(xencons_receiver_func *f);
+
+#endif /* _XENCONS_RING_H */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/tpmback/Makefile
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/Makefile Fri Sep  9 16:30:54 2005
@@ -0,0 +1,4 @@
+
+obj-$(CONFIG_XEN_TPMDEV_BACKEND)       += tpmbk.o
+
+tpmbk-y += tpmback.o interface.o xenbus.o
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/tpmback/common.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Fri Sep  9 16:30:54 2005
@@ -0,0 +1,88 @@
+/******************************************************************************
+ * drivers/xen/tpmback/common.h
+ */
+
+#ifndef __NETIF__BACKEND__COMMON_H__
+#define __NETIF__BACKEND__COMMON_H__
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <asm-xen/evtchn.h>
+#include <asm-xen/xen-public/io/tpmif.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+#include <asm-xen/xen-public/io/domain_controller.h>
+
+#if 0
+#define ASSERT(_p) \
+    if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
+    __LINE__, __FILE__); *(int*)0=0; }
+#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
+                           __FILE__ , __LINE__ , ## _a )
+#else
+#define ASSERT(_p) ((void)0)
+#define DPRINTK(_f, _a...) ((void)0)
+#endif
+
+typedef struct tpmif_st {
+        struct list_head tpmif_list;
+       /* Unique identifier for this interface. */
+       domid_t domid;
+       unsigned int handle;
+
+       /* Physical parameters of the comms window. */
+       unsigned long tx_shmem_frame;
+       unsigned int evtchn;
+       unsigned int remote_evtchn;
+
+       /* The shared rings and indexes. */
+       tpmif_tx_interface_t *tx;
+
+       /* Miscellaneous private stuff. */
+       enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
+       int active;
+
+       struct tpmif_st *hash_next;
+       struct list_head list;  /* scheduling list */
+       atomic_t refcnt;
+
+       long int tpm_instance;
+       unsigned long mmap_vstart;
+
+       struct work_struct work;
+
+       u16 shmem_handle;
+       unsigned long shmem_vaddr;
+       grant_ref_t shmem_ref;
+
+} tpmif_t;
+
+void tpmif_disconnect_complete(tpmif_t * tpmif);
+tpmif_t *tpmif_find(domid_t domid, long int instance);
+void tpmif_interface_init(void);
+void tpmif_schedule_work(tpmif_t * tpmif);
+void tpmif_deschedule_work(tpmif_t * tpmif);
+void tpmif_xenbus_init(void);
+int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn);
+irqreturn_t tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs);
+int tpmif_vtpm_open(tpmif_t *tpmif, domid_t domain, u32 instance);
+int tpmif_vtpm_close(u32 instance);
+
+int vtpm_release_packets(tpmif_t * tpmif, int send_msgs);
+
+#define tpmif_get(_b) (atomic_inc(&(_b)->refcnt))
+#define tpmif_put(_b)                             \
+    do {                                          \
+        if ( atomic_dec_and_test(&(_b)->refcnt) ) \
+            tpmif_disconnect_complete(_b);        \
+    } while (0)
+
+
+extern int num_frontends;
+
+#define MMAP_VADDR(t,_req) ((t)->mmap_vstart + ((_req) * PAGE_SIZE))
+
+#endif /* __TPMIF__BACKEND__COMMON_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c      Fri Sep  9 
16:30:54 2005
@@ -0,0 +1,200 @@
+/******************************************************************************
+ * drivers/xen/tpmback/interface.c
+ *
+ * Vritual TPM interface management.
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@xxxxxxxxxx
+ *
+ * This code has been derived from drivers/xen/netback/interface.c
+ * Copyright (c) 2004, Keir Fraser
+ */
+
+#include "common.h"
+#include <asm-xen/balloon.h>
+
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+#define TPMIF_HASHSZ (2 << 5)
+#define TPMIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(TPMIF_HASHSZ-1))
+
+static kmem_cache_t *tpmif_cachep;
+int num_frontends = 0;
+LIST_HEAD(tpmif_list);
+
+
+tpmif_t *alloc_tpmif(domid_t domid, long int instance)
+{
+    struct page *page;
+    tpmif_t *tpmif;
+
+    tpmif = kmem_cache_alloc(tpmif_cachep, GFP_KERNEL);
+    if (!tpmif)
+        return ERR_PTR(-ENOMEM);
+
+    memset(tpmif, 0, sizeof(*tpmif));
+    tpmif->domid        = domid;
+    tpmif->status       = DISCONNECTED;
+    tpmif->tpm_instance = instance;
+    atomic_set(&tpmif->refcnt, 1);
+
+    page = balloon_alloc_empty_page_range(TPMIF_TX_RING_SIZE);
+    BUG_ON(page == NULL);
+    tpmif->mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+
+    list_add(&tpmif->tpmif_list, &tpmif_list);
+    num_frontends++;
+
+    return tpmif;
+}
+
+
+void free_tpmif(tpmif_t *tpmif)
+{
+    num_frontends--;
+    list_del(&tpmif->tpmif_list);
+    kmem_cache_free(tpmif_cachep, tpmif);
+}
+
+
+tpmif_t *tpmif_find(domid_t domid, long int instance)
+{
+    tpmif_t *tpmif;
+
+    list_for_each_entry(tpmif, &tpmif_list, tpmif_list) {
+        if (tpmif->tpm_instance == instance) {
+            if (tpmif->domid == domid) {
+                tpmif_get(tpmif);
+                return tpmif;
+           } else {
+               return NULL;
+           }
+        }
+    }
+
+    return alloc_tpmif(domid, instance);
+}
+
+
+static int map_frontend_page(tpmif_t *tpmif, unsigned long localaddr,
+                            unsigned long shared_page)
+{
+    struct gnttab_map_grant_ref op = {
+        .host_addr = localaddr,
+        .flags     = GNTMAP_host_map,
+        .ref       = shared_page,
+        .dom       = tpmif->domid,
+    };
+
+    BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
+
+    if (op.handle < 0) {
+       DPRINTK(" Grant table operation failure !\n");
+       return op.handle;
+    }
+
+    tpmif->shmem_ref    = shared_page;
+    tpmif->shmem_handle = op.handle;
+    tpmif->shmem_vaddr  = localaddr;
+    return 0;
+}
+
+
+static void unmap_frontend_page(tpmif_t *tpmif)
+{
+    struct gnttab_unmap_grant_ref op;
+
+    op.host_addr = tpmif->shmem_vaddr;
+    op.handle = tpmif->shmem_handle;
+    op.dev_bus_addr = 0;
+
+    BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
+}
+
+
+int tpmif_map(tpmif_t *tpmif,
+              unsigned long shared_page, unsigned int evtchn)
+{
+    struct vm_struct *vma;
+    evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
+    int err;
+
+    BUG_ON(tpmif->remote_evtchn);
+
+    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
+       return -ENOMEM;
+
+    err = map_frontend_page(tpmif,
+                            VMALLOC_VMADDR(vma->addr),
+                            shared_page);
+    if (err) {
+        vfree(vma->addr);
+       return err;
+    }
+
+    op.u.bind_interdomain.dom1 = DOMID_SELF;
+    op.u.bind_interdomain.dom2 = tpmif->domid;
+    op.u.bind_interdomain.port1 = 0;
+    op.u.bind_interdomain.port2 = evtchn;
+    err = HYPERVISOR_event_channel_op(&op);
+    if (err) {
+       unmap_frontend_page(tpmif);
+       vfree(vma->addr);
+       return err;
+    }
+
+    tpmif->evtchn = op.u.bind_interdomain.port1;
+    tpmif->remote_evtchn = evtchn;
+
+    tpmif->tx = (tpmif_tx_interface_t *) vma->addr;
+
+    bind_evtchn_to_irqhandler(tpmif->evtchn,
+                              tpmif_be_int,
+                              0,
+                              "tpmif-backend",
+                             tpmif);
+    tpmif->status        = CONNECTED;
+    tpmif->shmem_ref     = shared_page;
+    tpmif->active        = 1;
+
+    return 0;
+}
+
+
+static void __tpmif_disconnect_complete(void *arg)
+{
+    evtchn_op_t op = { .cmd = EVTCHNOP_close };
+    tpmif_t *tpmif = (tpmif_t *) arg;
+
+    op.u.close.port = tpmif->evtchn;
+    op.u.close.dom  = DOMID_SELF;
+    HYPERVISOR_event_channel_op(&op);
+    op.u.close.port = tpmif->remote_evtchn;
+    op.u.close.dom  = tpmif->domid;
+    HYPERVISOR_event_channel_op(&op);
+
+    if (tpmif->evtchn)
+         unbind_evtchn_from_irqhandler(tpmif->evtchn, tpmif);
+
+    if (tpmif->tx) {
+        unmap_frontend_page(tpmif);
+        vfree(tpmif->tx);
+    }
+
+    free_tpmif(tpmif);
+}
+
+
+void tpmif_disconnect_complete(tpmif_t * tpmif)
+{
+    INIT_WORK(&tpmif->work, __tpmif_disconnect_complete, (void *)tpmif);
+    schedule_work(&tpmif->work);
+}
+
+
+void __init tpmif_interface_init(void)
+{
+    tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof(tpmif_t),
+                                     0, 0, NULL, NULL);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c        Fri Sep  9 
16:30:54 2005
@@ -0,0 +1,1077 @@
+/******************************************************************************
+ * drivers/xen/tpmback/tpmback.c
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@xxxxxxxxxx
+ * Grant table support: Mahadevan Gomathisankaran
+ *
+ * This code has been derived from drivers/xen/netback/netback.c
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ */
+
+#include "common.h"
+#include <asm-xen/evtchn.h>
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <asm-xen/xenbus.h>
+#include <asm-xen/xen-public/grant_table.h>
+
+
+struct data_exchange {
+       struct list_head pending_pak;
+       struct list_head current_pak;
+       unsigned int copied_so_far;
+       u8 has_opener;
+       rwlock_t pak_lock;  // protects all of the previous fields
+       wait_queue_head_t wait_queue;
+};
+
+struct packet {
+       struct list_head next;
+       unsigned int data_len;
+       u8 *data_buffer;
+       tpmif_t *tpmif;
+       u32 tpm_instance;
+       u8 req_tag;
+       u32 last_read;
+       u8 flags;
+       struct timer_list processing_timer;
+};
+
+enum {
+       PACKET_FLAG_DISCARD_RESPONSE = 1,
+       PACKET_FLAG_SEND_CONTROLMESSAGE = 2,
+};
+
+static struct data_exchange dataex;
+
+/* local function prototypes */
+static int vtpm_queue_packet(struct packet *pak);
+static int _packet_write(struct packet *pak,
+                         const char *data, size_t size,
+                         int userbuffer);
+static void processing_timeout(unsigned long ptr);
+static int  packet_read_shmem(struct packet *pak,
+                              tpmif_t *tpmif,
+                              u32 offset,
+                              char *buffer,
+                              int isuserbuffer,
+                              u32 left);
+
+
+#define MAX_PENDING_REQS TPMIF_TX_RING_SIZE
+
+static multicall_entry_t tx_mcl[MAX_PENDING_REQS];
+
+#define MIN(x,y)  (x) < (y) ? (x) : (y)
+
+/***************************************************************
+ Packet-related functions
+***************************************************************/
+
+static struct packet *
+packet_find_instance(struct list_head *head, u32 tpm_instance)
+{
+       struct packet *pak;
+       struct list_head *p;
+       /*
+        * traverse the list of packets and return the first
+        * one with the given instance number
+        */
+       list_for_each(p, head) {
+               pak = list_entry(p, struct packet, next);
+               if (pak->tpm_instance == tpm_instance) {
+                       return pak;
+               }
+       }
+       return NULL;
+}
+
+static struct packet *
+packet_find_packet(struct list_head *head, void *packet)
+{
+       struct packet *pak;
+       struct list_head *p;
+       /*
+        * traverse the list of packets and return the first
+        * one with the given instance number
+        */
+       list_for_each(p, head) {
+               pak = list_entry(p, struct packet, next);
+               if (pak == packet) {
+                       return pak;
+               }
+       }
+       return NULL;
+}
+
+static struct packet *
+packet_alloc(tpmif_t *tpmif, u32 size, u8 req_tag, u8 flags)
+{
+       struct packet *pak = NULL;
+       pak = kmalloc(sizeof(struct packet),
+                      GFP_KERNEL);
+       if (NULL != pak) {
+               memset(pak, 0x0, sizeof(*pak));
+               if (tpmif) {
+                       pak->tpmif = tpmif;
+                       pak->tpm_instance = tpmif->tpm_instance;
+               }
+               pak->data_len  = size;
+               pak->req_tag   = req_tag;
+               pak->last_read = 0;
+               pak->flags     = flags;
+
+               /*
+                * cannot do tpmif_get(tpmif); bad things happen
+                * on the last tpmif_put()
+                */
+               init_timer(&pak->processing_timer);
+               pak->processing_timer.function = processing_timeout;
+               pak->processing_timer.data = (unsigned long)pak;
+       }
+       return pak;
+}
+
+static void inline
+packet_reset(struct packet *pak)
+{
+       pak->last_read = 0;
+}
+
+static void inline
+packet_free(struct packet *pak)
+{
+       del_singleshot_timer_sync(&pak->processing_timer);
+       if (pak->data_buffer) {
+               kfree(pak->data_buffer);
+       }
+       /*
+        * cannot do tpmif_put(pak->tpmif); bad things happen
+        * on the last tpmif_put()
+        */
+       kfree(pak);
+}
+
+static int
+packet_set(struct packet *pak,
+           const unsigned char *buffer, u32 size)
+{
+       int rc = 0;
+       unsigned char *buf = kmalloc(size, GFP_KERNEL);
+       if (NULL != buf) {
+               pak->data_buffer = buf;
+               memcpy(buf, buffer, size);
+               pak->data_len = size;
+       } else {
+               rc = -ENOMEM;
+       }
+       return rc;
+}
+
+
+/*
+ * Write data to the shared memory and send it to the FE.
+ */
+static int
+packet_write(struct packet *pak,
+             const char *data, size_t size,
+             int userbuffer)
+{
+       int rc = 0;
+
+       DPRINTK("Supposed to send %d bytes to front-end!\n",
+               size);
+
+       if (0 != (pak->flags & PACKET_FLAG_SEND_CONTROLMESSAGE)) {
+#ifdef CONFIG_XEN_TPMDEV_CLOSE_IF_VTPM_FAILS
+               u32 res;
+               memcpy(&res, &data[2+4], sizeof(res));
+               if (res != 0) {
+                       /*
+                        * Will close down this device and have the
+                        * FE notified about closure.
+                        */
+               }
+#endif
+       }
+
+       if (0 != (pak->flags & PACKET_FLAG_DISCARD_RESPONSE)) {
+               /* Don't send a respone to this packet. Just acknowledge it. */
+               rc = size;
+       } else {
+               rc = _packet_write(pak, data, size, userbuffer);
+       }
+
+       return rc;
+}
+
+
+static int
+_packet_write(struct packet *pak,
+              const char *data, size_t size,
+              int userbuffer)
+{
+       /*
+        * Write into the shared memory pages directly
+        * and send it to the front end.
+        */
+       tpmif_t *tpmif = pak->tpmif;
+       u16 handle;
+       int rc = 0;
+       unsigned int i = 0;
+       unsigned int offset = 0;
+       multicall_entry_t *mcl;
+
+       if (tpmif == NULL)
+               return -EFAULT;
+
+       if (tpmif->status != CONNECTED) {
+               return size;
+       }
+
+       mcl = tx_mcl;
+       while (offset < size && i < TPMIF_TX_RING_SIZE) {
+               unsigned int tocopy;
+               struct gnttab_map_grant_ref map_op;
+               struct gnttab_unmap_grant_ref unmap_op;
+               tpmif_tx_request_t *tx;
+
+               tx = &tpmif->tx->ring[i].req;
+
+               if (0 == tx->addr) {
+                       DPRINTK("ERROR: Buffer for outgoing packet NULL?! 
i=%d\n", i);
+                       return 0;
+               }
+
+               map_op.host_addr  = MMAP_VADDR(tpmif, i);
+               map_op.flags      = GNTMAP_host_map;
+               map_op.ref        = tx->ref;
+               map_op.dom        = tpmif->domid;
+
+               if(unlikely(
+                   HYPERVISOR_grant_table_op(
+                       GNTTABOP_map_grant_ref,
+                       &map_op,
+                       1))) {
+                       BUG();
+               }
+
+               handle = map_op.handle;
+
+               if (map_op.handle < 0) {
+                       DPRINTK(" Grant table operation failure !\n");
+                       return 0;
+               }
+               phys_to_machine_mapping[__pa(MMAP_VADDR(tpmif,i)) >>
+                                       PAGE_SHIFT] =
+                       FOREIGN_FRAME(map_op.dev_bus_addr >> PAGE_SHIFT);
+
+               tocopy = size - offset;
+               if (tocopy > PAGE_SIZE) {
+                       tocopy = PAGE_SIZE;
+               }
+               if (userbuffer) {
+                       if (copy_from_user((void *)(MMAP_VADDR(tpmif,i) |
+                                                  (tx->addr & ~PAGE_MASK)),
+                                          (void __user *)&data[offset],
+                                          tocopy)) {
+                               tpmif_put(tpmif);
+                               return -EFAULT;
+                       }
+               } else {
+                       memcpy((void *)(MMAP_VADDR(tpmif,i) |
+                                       (tx->addr & ~PAGE_MASK)),
+                              &data[offset], tocopy);
+               }
+               tx->size = tocopy;
+
+               unmap_op.host_addr    = MMAP_VADDR(tpmif, i);
+               unmap_op.handle       = handle;
+               unmap_op.dev_bus_addr = 0;
+
+               if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+                                                     &unmap_op,
+                                                     1))) {
+                       BUG();
+               }
+
+               offset += tocopy;
+               i++;
+       }
+
+       rc = offset;
+       DPRINTK("Notifying frontend via event channel %d\n",
+               tpmif->evtchn);
+       notify_via_evtchn(tpmif->evtchn);
+
+       return rc;
+}
+
+/*
+ * Read data from the shared memory and copy it directly into the
+ * provided buffer. Advance the read_last indicator which tells
+ * how many bytes have already been read.
+ */
+static int
+packet_read(struct packet *pak, size_t numbytes,
+            char *buffer, size_t buffersize,
+            int userbuffer)
+{
+       tpmif_t *tpmif = pak->tpmif;
+       /*
+        * I am supposed to read 'numbytes' of data from the
+        * buffer.
+        * The first 4 bytes that are read are the instance number in
+        * network byte order, after that comes the data from the
+        * shared memory buffer.
+        */
+       u32 to_copy;
+       u32 offset = 0;
+       u32 room_left = buffersize;
+       /*
+        * Ensure that we see the request when we copy it.
+        */
+       mb();
+
+       if (pak->last_read < 4) {
+               /*
+                * copy the instance number into the buffer
+                */
+               u32 instance_no = htonl(pak->tpm_instance);
+               u32 last_read = pak->last_read;
+               to_copy = MIN(4 - last_read, numbytes);
+
+               if (userbuffer) {
+                       if (copy_to_user(&buffer[0],
+                                        &(((u8 *)&instance_no)[last_read]),
+                                        to_copy)) {
+                               return -EFAULT;
+                       }
+               } else {
+                       memcpy(&buffer[0],
+                              &(((u8 *)&instance_no)[last_read]),
+                              to_copy);
+               }
+
+               pak->last_read += to_copy;
+               offset += to_copy;
+               room_left -= to_copy;
+       }
+
+       /*
+        * If the packet has a data buffer appended, read from it...
+        */
+
+       if (room_left > 0) {
+               if (pak->data_buffer) {
+                       u32 to_copy = MIN(pak->data_len - offset, room_left);
+                       u32 last_read = pak->last_read - 4;
+                       if (userbuffer) {
+                               if (copy_to_user(&buffer[offset],
+                                                &pak->data_buffer[last_read],
+                                                to_copy)) {
+                                       return -EFAULT;
+                               }
+                       } else {
+                               memcpy(&buffer[offset],
+                                      &pak->data_buffer[last_read],
+                                      to_copy);
+                       }
+                       pak->last_read += to_copy;
+                       offset += to_copy;
+               } else {
+                       offset = packet_read_shmem(pak,
+                                                  tpmif,
+                                                  offset,
+                                                  buffer,
+                                                  userbuffer,
+                                                  room_left);
+               }
+       }
+       return offset;
+}
+
+
+static int
+packet_read_shmem(struct packet *pak,
+                  tpmif_t *tpmif,
+                  u32 offset,
+                  char *buffer,
+                  int isuserbuffer,
+                  u32 room_left) {
+       u32 last_read = pak->last_read - 4;
+       u32 i = (last_read / PAGE_SIZE);
+       u32 pg_offset = last_read & (PAGE_SIZE - 1);
+       u32 to_copy;
+       u16 handle;
+
+       tpmif_tx_request_t *tx;
+       tx = &tpmif->tx->ring[0].req;
+       /*
+        * Start copying data at the page with index 'index'
+        * and within that page at offset 'offset'.
+        * Copy a maximum of 'room_left' bytes.
+        */
+       to_copy = MIN(PAGE_SIZE - pg_offset, room_left);
+       while (to_copy > 0) {
+               void *src;
+               struct gnttab_map_grant_ref map_op;
+               struct gnttab_unmap_grant_ref unmap_op;
+
+               tx = &tpmif->tx->ring[i].req;
+
+               map_op.host_addr = MMAP_VADDR(tpmif, i);
+               map_op.flags     = GNTMAP_host_map;
+               map_op.ref       = tx->ref;
+               map_op.dom       = tpmif->domid;
+
+               if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
+                                                     &map_op,
+                                                     1))) {
+                       BUG();
+               }
+
+               if (map_op.handle < 0) {
+                       DPRINTK(" Grant table operation failure !\n");
+                       return -EFAULT;
+               }
+
+               handle = map_op.handle;
+
+               if (to_copy > tx->size) {
+                       /*
+                        * This is the case when the user wants to read more
+                        * than what we have. So we just give him what we
+                        * have.
+                        */
+                       to_copy = MIN(tx->size, to_copy);
+               }
+
+               DPRINTK("Copying from mapped memory at %08lx\n",
+                       (unsigned long)(MMAP_VADDR(tpmif,i) |
+                       (tx->addr & ~PAGE_MASK)));
+
+               src = (void *)(MMAP_VADDR(tpmif,i) | ((tx->addr & ~PAGE_MASK) + 
pg_offset));
+               if (isuserbuffer) {
+                       if (copy_to_user(&buffer[offset],
+                                        src,
+                                        to_copy)) {
+                               return -EFAULT;
+                       }
+               } else {
+                       memcpy(&buffer[offset],
+                              src,
+                              to_copy);
+               }
+
+
+               DPRINTK("Data from TPM-FE of domain %d are %d %d %d %d\n",
+                       tpmif->domid, buffer[offset], 
buffer[offset+1],buffer[offset+2],buffer[offset+3]);
+
+               unmap_op.host_addr    = MMAP_VADDR(tpmif, i);
+               unmap_op.handle       = handle;
+               unmap_op.dev_bus_addr = 0;
+
+               if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+                                                     &unmap_op,
+                                                     1))) {
+                       BUG();
+               }
+
+               offset += to_copy;
+               pg_offset = 0;
+               last_read += to_copy;
+               room_left -= to_copy;
+
+               to_copy = MIN(PAGE_SIZE, room_left);
+               i++;
+       } /* while (to_copy > 0) */
+       /*
+        * Adjust the last_read pointer
+        */
+       pak->last_read = last_read + 4;
+       return offset;
+}
+
+
+/* ============================================================
+ * The file layer for reading data from this device
+ * ============================================================
+ */
+static int
+vtpm_op_open(struct inode *inode, struct file *f)
+{
+       int rc = 0;
+       unsigned long flags;
+
+       write_lock_irqsave(&dataex.pak_lock, flags);
+       if (dataex.has_opener == 0) {
+               dataex.has_opener = 1;
+       } else {
+               rc = -EPERM;
+       }
+       write_unlock_irqrestore(&dataex.pak_lock, flags);
+       return rc;
+}
+
+static ssize_t
+vtpm_op_read(struct file *file,
+            char __user * data, size_t size, loff_t * offset)
+{
+       int ret_size = -ENODATA;
+       struct packet *pak = NULL;
+       unsigned long flags;
+
+       write_lock_irqsave(&dataex.pak_lock, flags);
+
+       if (list_empty(&dataex.pending_pak)) {
+               write_unlock_irqrestore(&dataex.pak_lock, flags);
+               wait_event_interruptible(dataex.wait_queue,
+                                        !list_empty(&dataex.pending_pak));
+               write_lock_irqsave(&dataex.pak_lock, flags);
+       }
+
+       if (!list_empty(&dataex.pending_pak)) {
+               unsigned int left;
+               pak = list_entry(dataex.pending_pak.next, struct packet, next);
+
+               left = pak->data_len - dataex.copied_so_far;
+
+               DPRINTK("size given by app: %d, available: %d\n", size, left);
+
+               ret_size = MIN(size,left);
+
+               ret_size = packet_read(pak, ret_size, data, size, 1);
+               if (ret_size < 0) {
+                       ret_size = -EFAULT;
+               } else {
+                       DPRINTK("Copied %d bytes to user buffer\n", ret_size);
+
+                       dataex.copied_so_far += ret_size;
+                       if (dataex.copied_so_far >= pak->data_len + 4) {
+                               DPRINTK("All data from this packet given to 
app.\n");
+                               /* All data given to app */
+
+                               
del_singleshot_timer_sync(&pak->processing_timer);
+                               list_del(&pak->next);
+                               list_add_tail(&pak->next, &dataex.current_pak);
+                               /*
+                                * The more fontends that are handled at the 
same time,
+                                * the more time we give the TPM to process the 
request.
+                                */
+                               mod_timer(&pak->processing_timer,
+                                         jiffies + (num_frontends * 10 * HZ));
+                               dataex.copied_so_far = 0;
+                       }
+               }
+       }
+       write_unlock_irqrestore(&dataex.pak_lock, flags);
+
+       DPRINTK("Returning result from read to app: %d\n", ret_size);
+
+       return ret_size;
+}
+
+/*
+ * Write operation - only works after a previous read operation!
+ */
+static ssize_t
+vtpm_op_write(struct file *file, const char __user * data, size_t size,
+             loff_t * offset)
+{
+       struct packet *pak;
+       int rc = 0;
+       unsigned int off = 4;
+       unsigned long flags;
+       u32 instance_no = 0;
+       u32 len_no = 0;
+
+       /*
+        * Minimum required packet size is:
+        * 4 bytes for instance number
+        * 2 bytes for tag
+        * 4 bytes for paramSize
+        * 4 bytes for the ordinal
+        * sum: 14 bytes
+        */
+       if ( size < off + 10 ) {
+               return -EFAULT;
+       }
+
+       if (copy_from_user(&instance_no,
+                          (void __user *)&data[0],
+                          4)) {
+               return -EFAULT;
+       }
+
+       if (copy_from_user(&len_no,
+                          (void __user *)&data[off+2],
+                          4) ||
+           (off + ntohl(len_no) != size)) {
+               return -EFAULT;
+       }
+
+       write_lock_irqsave(&dataex.pak_lock, flags);
+       pak = packet_find_instance(&dataex.current_pak, ntohl(instance_no));
+
+       if (pak == NULL) {
+               write_unlock_irqrestore(&dataex.pak_lock, flags);
+               printk(KERN_ALERT "No associated packet!\n");
+               return -EFAULT;
+       } else {
+               del_singleshot_timer_sync(&pak->processing_timer);
+               list_del(&pak->next);
+       }
+
+       write_unlock_irqrestore(&dataex.pak_lock, flags);
+
+       /*
+        * The first 'offset' bytes must be the instance number.
+        * I will just pull that from the packet.
+        */
+       size -= off;
+       data = &data[off];
+
+       rc = packet_write(pak, data, size, 1);
+
+       if (rc > 0) {
+               /* I neglected the first 4 bytes */
+               rc += off;
+       }
+       packet_free(pak);
+       return rc;
+}
+
+static int
+vtpm_op_release(struct inode *inode, struct file *file)
+{
+       unsigned long flags;
+       vtpm_release_packets(NULL, 1);
+       write_lock_irqsave(&dataex.pak_lock, flags);
+       dataex.has_opener = 0;
+       write_unlock_irqrestore(&dataex.pak_lock, flags);
+       return 0;
+}
+
+static unsigned int
+vtpm_op_poll(struct file *file, struct poll_table_struct *pst)
+{
+       return 0;
+}
+
+static struct file_operations vtpm_ops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .open = vtpm_op_open,
+       .read = vtpm_op_read,
+       .write = vtpm_op_write,
+       .release = vtpm_op_release,
+       .poll = vtpm_op_poll,
+};
+
+static struct miscdevice ibmvtpms_miscdevice = {
+       .minor = 225,
+       .name = "vtpm",
+       .fops = &vtpm_ops,
+};
+
+
+/***************************************************************
+ Virtual TPM functions and data stuctures
+***************************************************************/
+
+static u8 create_cmd[] = {
+        1,193,         /* 0: TPM_TAG_RQU_COMMAMD */
+        0,0,0,19,      /* 2: length */
+        0,0,0,0x1,     /* 6: VTPM_ORD_OPEN */
+        0,             /* 10: VTPM type */
+        0,0,0,0,       /* 11: domain id */
+        0,0,0,0                /* 15: instance id */
+};
+
+static u8 destroy_cmd[] = {
+        1,193,         /* 0: TPM_TAG_RQU_COMMAMD */
+        0,0,0,14,      /* 2: length */
+        0,0,0,0x2,     /* 6: VTPM_ORD_CLOSE */
+        0,0,0,0                /* 10: instance id */
+};
+
+int tpmif_vtpm_open(tpmif_t *tpmif, domid_t domid, u32 instance)
+{
+       int rc = 0;
+       struct packet *pak = packet_alloc(tpmif, sizeof(create_cmd), 
create_cmd[0],
+           PACKET_FLAG_DISCARD_RESPONSE|
+           PACKET_FLAG_SEND_CONTROLMESSAGE);
+       if (pak) {
+               u8 buf[sizeof(create_cmd)];
+               u32 domid_no = htonl((u32)domid);
+               u32 instance_no = htonl(instance);
+               memcpy(buf, create_cmd, sizeof(create_cmd));
+
+               memcpy(&buf[11], &domid_no, sizeof(u32));
+               memcpy(&buf[15], &instance_no, sizeof(u32));
+
+               /* copy the buffer into the packet */
+               rc = packet_set(pak, buf, sizeof(buf));
+
+               if (rc == 0) {
+                       pak->tpm_instance = 0;
+                       rc = vtpm_queue_packet(pak);
+               }
+               if (rc < 0) {
+                       /* could not be queued or built */
+                       packet_free(pak);
+               }
+       } else {
+               rc = -ENOMEM;
+       }
+       return rc;
+}
+
+int tpmif_vtpm_close(u32 instid)
+{
+       int rc = 0;
+       struct packet *pak;
+
+       pak = packet_alloc(NULL,
+                          sizeof(create_cmd),
+                          create_cmd[0],
+                          PACKET_FLAG_DISCARD_RESPONSE|
+                          PACKET_FLAG_SEND_CONTROLMESSAGE);
+       if (pak) {
+               u8 buf[sizeof(destroy_cmd)];
+               u32 instid_no = htonl(instid);
+               memcpy(buf, destroy_cmd, sizeof(destroy_cmd));
+               memcpy(&buf[10], &instid_no, sizeof(u32));
+
+               /* copy the buffer into the packet */
+               rc = packet_set(pak, buf, sizeof(buf));
+
+               if (rc == 0) {
+                       pak->tpm_instance = 0;
+                       rc = vtpm_queue_packet(pak);
+               }
+               if (rc < 0) {
+                       /* could not be queued or built */
+                       packet_free(pak);
+               }
+       } else {
+               rc = -ENOMEM;
+       }
+       return rc;
+}
+
+
+/***************************************************************
+ Utility functions
+***************************************************************/
+
+static int
+tpm_send_fail_message(struct packet *pak, u8 req_tag)
+{
+       int rc;
+       static const unsigned char tpm_error_message_fail[] = {
+               0x00, 0x00,
+               0x00, 0x00, 0x00, 0x0a,
+               0x00, 0x00, 0x00, 0x09 /* TPM_FAIL */
+       };
+       unsigned char buffer[sizeof(tpm_error_message_fail)];
+
+       memcpy(buffer, tpm_error_message_fail, sizeof(tpm_error_message_fail));
+       /*
+        * Insert the right response tag depending on the given tag
+        * All response tags are '+3' to the request tag.
+        */
+       buffer[1] = req_tag + 3;
+
+       /*
+        * Write the data to shared memory and notify the front-end
+        */
+       rc = packet_write(pak, buffer, sizeof(buffer), 0);
+
+       return rc;
+}
+
+
+static void
+_vtpm_release_packets(struct list_head *head, tpmif_t *tpmif,
+                      int send_msgs)
+{
+       struct packet *pak;
+       struct list_head *pos, *tmp;
+
+       list_for_each_safe(pos, tmp, head) {
+               pak = list_entry(pos, struct packet, next);
+               if (tpmif == NULL || pak->tpmif == tpmif) {
+                       int can_send = 0;
+                       del_singleshot_timer_sync(&pak->processing_timer);
+                       list_del(&pak->next);
+
+                       if (pak->tpmif && pak->tpmif->status == CONNECTED) {
+                               can_send = 1;
+                       }
+
+                       if (send_msgs && can_send) {
+                               tpm_send_fail_message(pak, pak->req_tag);
+                       }
+                       packet_free(pak);
+               }
+       }
+}
+
+
+int
+vtpm_release_packets(tpmif_t *tpmif, int send_msgs)
+{
+       unsigned long flags;
+
+       write_lock_irqsave(&dataex.pak_lock, flags);
+
+       _vtpm_release_packets(&dataex.pending_pak, tpmif, send_msgs);
+       _vtpm_release_packets(&dataex.current_pak, tpmif, send_msgs);
+
+       write_unlock_irqrestore(&dataex.pak_lock,
+                               flags);
+       return 0;
+}
+
+
+static int vtpm_queue_packet(struct packet *pak)
+{
+       int rc = 0;
+       if (dataex.has_opener) {
+               unsigned long flags;
+               write_lock_irqsave(&dataex.pak_lock, flags);
+               list_add_tail(&pak->next, &dataex.pending_pak);
+               /* give the TPM some time to pick up the request */
+               mod_timer(&pak->processing_timer, jiffies + (10 * HZ));
+               write_unlock_irqrestore(&dataex.pak_lock,
+                                       flags);
+
+               wake_up_interruptible(&dataex.wait_queue);
+       } else {
+               rc = -EFAULT;
+       }
+       return rc;
+}
+
+
+static int vtpm_receive(tpmif_t *tpmif, u32 size)
+{
+       int rc = 0;
+       unsigned char buffer[10];
+       __be32 *native_size;
+
+       struct packet *pak = packet_alloc(tpmif, size, buffer[4], 0);
+       if (NULL == pak) {
+               return -ENOMEM;
+       }
+       /*
+        * Read 10 bytes from the received buffer to test its
+        * content for validity.
+        */
+       if (sizeof(buffer) != packet_read(pak,
+                                         sizeof(buffer), buffer,
+                                         sizeof(buffer), 0)) {
+               goto failexit;
+       }
+       /*
+        * Reset the packet read pointer so we can read all its
+        * contents again.
+        */
+       packet_reset(pak);
+
+       native_size = (__force __be32 *)(&buffer[4+2]);
+       /*
+        * Verify that the size of the packet is correct
+        * as indicated and that there's actually someone reading packets.
+        * The minimum size of the packet is '10' for tag, size indicator
+        * and ordinal.
+        */
+       if (size < 10 ||
+           be32_to_cpu(*native_size) != size ||
+           0 == dataex.has_opener) {
+               rc = -EINVAL;
+               goto failexit;
+       } else {
+               if ((rc = vtpm_queue_packet(pak)) < 0) {
+                       goto failexit;
+               }
+       }
+       return 0;
+
+failexit:
+       if (pak) {
+               tpm_send_fail_message(pak, buffer[4+1]);
+               packet_free(pak);
+       }
+       return rc;
+}
+
+
+/*
+ * Timeout function that gets invoked when a packet has not been processed
+ * during the timeout period.
+ * The packet must be on a list when this function is invoked. This
+ * also means that once its taken off a list, the timer must be
+ * destroyed as well.
+ */
+static void processing_timeout(unsigned long ptr)
+{
+       struct packet *pak = (struct packet *)ptr;
+       unsigned long flags;
+       write_lock_irqsave(&dataex.pak_lock, flags);
+       /*
+        * The packet needs to be searched whether it
+        * is still on the list.
+        */
+       if (pak == packet_find_packet(&dataex.pending_pak, pak) ||
+           pak == packet_find_packet(&dataex.current_pak, pak) ) {
+               list_del(&pak->next);
+               tpm_send_fail_message(pak, pak->req_tag);
+               packet_free(pak);
+       }
+
+       write_unlock_irqrestore(&dataex.pak_lock, flags);
+}
+
+
+
+static void tpm_tx_action(unsigned long unused);
+static DECLARE_TASKLET(tpm_tx_tasklet, tpm_tx_action, 0);
+
+#define MAX_PENDING_REQS TPMIF_TX_RING_SIZE
+
+static struct list_head tpm_schedule_list;
+static spinlock_t tpm_schedule_list_lock;
+
+static inline void
+maybe_schedule_tx_action(void)
+{
+       smp_mb();
+       tasklet_schedule(&tpm_tx_tasklet);
+}
+
+static inline int
+__on_tpm_schedule_list(tpmif_t * tpmif)
+{
+       return tpmif->list.next != NULL;
+}
+
+static void
+remove_from_tpm_schedule_list(tpmif_t * tpmif)
+{
+       spin_lock_irq(&tpm_schedule_list_lock);
+       if (likely(__on_tpm_schedule_list(tpmif))) {
+               list_del(&tpmif->list);
+               tpmif->list.next = NULL;
+               tpmif_put(tpmif);
+       }
+       spin_unlock_irq(&tpm_schedule_list_lock);
+}
+
+static void
+add_to_tpm_schedule_list_tail(tpmif_t * tpmif)
+{
+       if (__on_tpm_schedule_list(tpmif))
+               return;
+
+       spin_lock_irq(&tpm_schedule_list_lock);
+       if (!__on_tpm_schedule_list(tpmif) && tpmif->active) {
+               list_add_tail(&tpmif->list, &tpm_schedule_list);
+               tpmif_get(tpmif);
+       }
+       spin_unlock_irq(&tpm_schedule_list_lock);
+}
+
+void
+tpmif_schedule_work(tpmif_t * tpmif)
+{
+       add_to_tpm_schedule_list_tail(tpmif);
+       maybe_schedule_tx_action();
+}
+
+void
+tpmif_deschedule_work(tpmif_t * tpmif)
+{
+       remove_from_tpm_schedule_list(tpmif);
+}
+
+
+static void
+tpm_tx_action(unsigned long unused)
+{
+       struct list_head *ent;
+       tpmif_t *tpmif;
+       tpmif_tx_request_t *tx;
+
+       DPRINTK("%s: Getting data from front-end(s)!\n", __FUNCTION__);
+
+       while (!list_empty(&tpm_schedule_list)) {
+               /* Get a tpmif from the list with work to do. */
+               ent = tpm_schedule_list.next;
+               tpmif = list_entry(ent, tpmif_t, list);
+               tpmif_get(tpmif);
+               remove_from_tpm_schedule_list(tpmif);
+               /*
+                * Ensure that we see the request when we read from it.
+                */
+               mb();
+
+               tx = &tpmif->tx->ring[0].req;
+
+               /* pass it up */
+               vtpm_receive(tpmif, tx->size);
+
+               tpmif_put(tpmif);
+       }
+}
+
+irqreturn_t
+tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+       tpmif_t *tpmif = dev_id;
+       add_to_tpm_schedule_list_tail(tpmif);
+       maybe_schedule_tx_action();
+       return IRQ_HANDLED;
+}
+
+static int __init
+tpmback_init(void)
+{
+       int rc;
+       if (!(xen_start_info->flags & SIF_TPM_BE_DOMAIN) &&
+           !(xen_start_info->flags & SIF_INITDOMAIN)) {
+               printk(KERN_ALERT "Neither TPM-BE Domain nor INIT domain!\n");
+               return 0;
+       }
+
+       if ((rc = misc_register(&ibmvtpms_miscdevice)) != 0) {
+               printk(KERN_ALERT "Could not register misc device for TPM 
BE.\n");
+               return rc;
+       }
+
+       INIT_LIST_HEAD(&dataex.pending_pak);
+       INIT_LIST_HEAD(&dataex.current_pak);
+       dataex.has_opener = 0;
+       rwlock_init(&dataex.pak_lock);
+       init_waitqueue_head(&dataex.wait_queue);
+
+       spin_lock_init(&tpm_schedule_list_lock);
+       INIT_LIST_HEAD(&tpm_schedule_list);
+
+       tpmif_interface_init();
+       tpmif_xenbus_init();
+
+       printk(KERN_ALERT "Successfully initialized TPM backend driver.\n");
+
+       return 0;
+}
+
+__initcall(tpmback_init);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Fri Sep  9 16:30:54 2005
@@ -0,0 +1,271 @@
+/*  Xenbus code for tpmif backend
+    Copyright (C) 2005 Rusty Russell <rusty@xxxxxxxxxxxxxxx>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that 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 <stdarg.h>
+#include <linux/module.h>
+#include <asm-xen/xenbus.h>
+#include "common.h"
+
+struct backend_info
+{
+       struct xenbus_device *dev;
+
+       /* our communications channel */
+       tpmif_t *tpmif;
+
+       long int frontend_id;
+       long int instance; // instance of TPM
+
+       /* watch front end for changes */
+       struct xenbus_watch backend_watch;
+
+       struct xenbus_watch watch;
+       char * frontpath;
+};
+
+static int tpmback_remove(struct xenbus_device *dev)
+{
+       struct backend_info *be = dev->data;
+
+       if (be->watch.node) {
+               unregister_xenbus_watch(&be->watch);
+       }
+       unregister_xenbus_watch(&be->backend_watch);
+
+       tpmif_vtpm_close(be->instance);
+
+       if (be->tpmif) {
+               tpmif_put(be->tpmif);
+       }
+
+       if (be->frontpath)
+               kfree(be->frontpath);
+       kfree(be);
+       return 0;
+}
+
+
+static void frontend_changed(struct xenbus_watch *watch, const char *node)
+{
+       unsigned long ringref;
+       unsigned int evtchn;
+       unsigned long ready = 1;
+       int err;
+       struct backend_info *be
+               = container_of(watch, struct backend_info, watch);
+
+       /* If other end is gone, delete ourself. */
+       if (node && !xenbus_exists(be->frontpath, "")) {
+               xenbus_rm(be->dev->nodename, "");
+               device_unregister(&be->dev->dev);
+               return;
+       }
+
+       if (be->tpmif == NULL || be->tpmif->status == CONNECTED)
+               return;
+
+       err = xenbus_gather(be->frontpath,
+                           "ring-ref", "%lu", &ringref,
+                           "event-channel", "%u", &evtchn, NULL);
+       if (err) {
+               xenbus_dev_error(be->dev, err,
+                                "reading %s/ring-ref and event-channel",
+                                be->frontpath);
+               return;
+       }
+
+
+       /*
+        * Tell the front-end that we are ready to go -
+        * unless something bad happens
+        */
+       err = xenbus_transaction_start(be->dev->nodename);
+       if (err) {
+               xenbus_dev_error(be->dev, err, "starting transaction");
+               return;
+       }
+
+       err = xenbus_printf(be->dev->nodename,
+                           "ready", "%lu", ready);
+       if (err) {
+               xenbus_dev_error(be->dev, err, "writing 'ready'");
+               goto abort;
+       }
+
+       err = tpmif_map(be->tpmif, ringref, evtchn);
+       if (err) {
+               xenbus_dev_error(be->dev, err,
+                                "mapping shared-frame %lu port %u",
+                                ringref, evtchn);
+               goto abort;
+       }
+
+       err = tpmif_vtpm_open(be->tpmif,
+                             be->frontend_id,
+                             be->instance);
+       if (err) {
+               xenbus_dev_error(be->dev, err,
+                                "queueing vtpm open packet");
+               /*
+                * Should close down this device and notify FE
+                * about closure.
+                */
+               goto abort;
+       }
+
+       xenbus_transaction_end(0);
+       xenbus_dev_ok(be->dev);
+       return;
+abort:
+       xenbus_transaction_end(1);
+}
+
+
+static void backend_changed(struct xenbus_watch *watch, const char *node)
+{
+       int err;
+       long int instance;
+       struct backend_info *be
+               = container_of(watch, struct backend_info, backend_watch);
+       struct xenbus_device *dev = be->dev;
+
+       err = xenbus_scanf(dev->nodename, "instance", "%li", &instance);
+       if (XENBUS_EXIST_ERR(err))
+               return;
+       if (err < 0) {
+               xenbus_dev_error(dev, err, "reading 'instance' variable");
+               return;
+       }
+
+       if (be->instance != -1 && be->instance != instance) {
+               printk(KERN_WARNING
+                      "cannot change the instance\n");
+               return;
+       }
+       be->instance = instance;
+
+       if (be->tpmif == NULL) {
+               be->tpmif = tpmif_find(be->frontend_id,
+                                      instance);
+               if (IS_ERR(be->tpmif)) {
+                       err = PTR_ERR(be->tpmif);
+                       be->tpmif = NULL;
+                       xenbus_dev_error(dev, err, "creating interface");
+                       return;
+               }
+
+               /* Pass in NULL node to skip exist test. */
+               frontend_changed(&be->watch, be->frontpath);
+       }
+}
+
+
+static int tpmback_probe(struct xenbus_device *dev,
+                        const struct xenbus_device_id *id)
+{
+       struct backend_info *be;
+       char *frontend;
+       int err;
+
+       be = kmalloc(sizeof(*be), GFP_KERNEL);
+       if (!be) {
+               xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
+               err = -ENOMEM;
+       }
+
+       memset(be, 0, sizeof(*be));
+
+       frontend = NULL;
+       err = xenbus_gather(dev->nodename,
+                           "frontend-id", "%li", &be->frontend_id,
+                           "frontend", NULL, &frontend,
+                           NULL);
+       if (XENBUS_EXIST_ERR(err))
+               goto free_be;
+       if (err < 0) {
+               xenbus_dev_error(dev, err,
+                                "reading %s/frontend or frontend-id",
+                                dev->nodename);
+               goto free_be;
+       }
+       if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
+               /* If we can't get a frontend path and a frontend-id,
+                * then our bus-id is no longer valid and we need to
+                * destroy the backend device.
+                */
+               err = -ENOENT;
+               goto free_be;
+       }
+
+       be->dev = dev;
+       be->backend_watch.node     = dev->nodename;
+       be->backend_watch.callback = backend_changed;
+       be->instance = -1;
+       err = register_xenbus_watch(&be->backend_watch);
+       if (err) {
+               be->backend_watch.node = NULL;
+               xenbus_dev_error(dev, err, "adding backend watch on %s",
+                                dev->nodename);
+               goto free_be;
+       }
+
+       be->frontpath = frontend;
+       be->watch.node = be->frontpath;
+       be->watch.callback = frontend_changed;
+       err = register_xenbus_watch(&be->watch);
+       if (err) {
+               be->watch.node = NULL;
+               xenbus_dev_error(dev, err,
+                                "adding frontend watch on %s",
+                                be->frontpath);
+               goto free_be;
+       }
+
+       dev->data = be;
+
+       backend_changed(&be->backend_watch, dev->nodename);
+       return err;
+
+free_be:
+       if (be->backend_watch.node)
+               unregister_xenbus_watch(&be->backend_watch);
+       if (frontend)
+               kfree(frontend);
+       kfree(be);
+       return err;
+}
+
+
+static struct xenbus_device_id tpmback_ids[] = {
+       { "vtpm" },
+       { "" }
+};
+
+
+static struct xenbus_driver tpmback = {
+       .name = "vtpm",
+       .owner = THIS_MODULE,
+       .ids = tpmback_ids,
+       .probe = tpmback_probe,
+       .remove = tpmback_remove,
+};
+
+
+void tpmif_xenbus_init(void)
+{
+       xenbus_register_backend(&tpmback);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/tpmfront/Makefile
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/Makefile        Fri Sep  9 
16:30:54 2005
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_XEN_TPMDEV_FRONTEND)      += tpmfront.o
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c      Fri Sep  9 
16:30:54 2005
@@ -0,0 +1,738 @@
+/*
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@xxxxxxxxxx
+ * Grant table support: Mahadevan Gomathisankaran
+ *
+ * This code has been derived from drivers/xen/netfront/netfront.c
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/tpmfe.h>
+
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <asm-xen/evtchn.h>
+#include <asm-xen/xen-public/io/tpmif.h>
+#include <asm/uaccess.h>
+#include <asm-xen/xenbus.h>
+#include <asm-xen/xen-public/io/domain_controller.h>
+#include <asm-xen/xen-public/grant_table.h>
+
+#include "tpmfront.h"
+
+#undef DEBUG
+
+#if 1
+#define ASSERT(_p) \
+    if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
+        __LINE__, __FILE__); *(int*)0=0; }
+#else
+#define ASSERT(_p)
+#endif
+
+/* locally visible variables */
+static grant_ref_t gref_head;
+static struct tpm_private my_private;
+
+/* local function prototypes */
+static irqreturn_t tpmif_int(int irq,
+                             void *tpm_priv,
+                             struct pt_regs *ptregs);
+static void tpmif_rx_action(unsigned long unused);
+static void tpmif_connect(u16 evtchn, domid_t domid);
+static DECLARE_TASKLET(tpmif_rx_tasklet, tpmif_rx_action, 0);
+static int tpm_allocate_buffers(struct tpm_private *tp);
+static void tpmif_set_connected_state(struct tpm_private *tp, int newstate);
+static int tpm_xmit(struct tpm_private *tp,
+                    const u8 * buf, size_t count, int userbuffer,
+                    void *remember);
+
+#if DEBUG
+#define DPRINTK(fmt, args...) \
+    printk(KERN_ALERT "xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__, 
##args)
+#else
+#define DPRINTK(fmt, args...) ((void)0)
+#endif
+#define IPRINTK(fmt, args...) \
+    printk(KERN_INFO "xen_tpm_fr: " fmt, ##args)
+#define WPRINTK(fmt, args...) \
+    printk(KERN_WARNING "xen_tpm_fr: " fmt, ##args)
+
+
+static inline int
+tx_buffer_copy(struct tx_buffer *txb, const u8 * src, int len,
+               int isuserbuffer)
+{
+       int copied = len;
+
+       if (len > txb->size) {
+               copied = txb->size;
+       }
+       if (isuserbuffer) {
+               if (copy_from_user(txb->data,
+                                  src,
+                                  copied)) {
+                       return -EFAULT;
+               }
+       } else {
+               memcpy(txb->data, src, copied);
+       }
+       txb->len = len;
+       return copied;
+}
+
+static inline struct tx_buffer *tx_buffer_alloc(void)
+{
+       struct tx_buffer *txb = kmalloc(sizeof (struct tx_buffer),
+                                       GFP_KERNEL);
+
+       if (txb) {
+               txb->len = 0;
+               txb->size = PAGE_SIZE;
+               txb->data = (unsigned char *)__get_free_page(GFP_KERNEL);
+               if (txb->data == NULL) {
+                       kfree(txb);
+                       txb = NULL;
+               }
+       }
+       return txb;
+}
+
+
+/**************************************************************
+
+ The interface to let the tpm plugin register its callback
+ function and send data to another partition using this module
+
+**************************************************************/
+
+static DECLARE_MUTEX(upperlayer_lock);
+static DECLARE_MUTEX(suspend_lock);
+static struct tpmfe_device *upperlayer_tpmfe;
+
+/*
+ * Send data via this module by calling this function
+ */
+int tpm_fe_send(const u8 * buf, size_t count, void *ptr)
+{
+       int sent = 0;
+       struct tpm_private *tp = &my_private;
+
+       down(&suspend_lock);
+       sent = tpm_xmit(tp, buf, count, 0, ptr);
+       up(&suspend_lock);
+
+       return sent;
+}
+EXPORT_SYMBOL(tpm_fe_send);
+
+/*
+ * Register a callback for receiving data from this module
+ */
+int tpm_fe_register_receiver(struct tpmfe_device *tpmfe_dev)
+{
+       int rc = 0;
+
+       down(&upperlayer_lock);
+       if (NULL == upperlayer_tpmfe) {
+               upperlayer_tpmfe = tpmfe_dev;
+               tpmfe_dev->max_tx_size = TPMIF_TX_RING_SIZE * PAGE_SIZE;
+       } else {
+               rc = -EBUSY;
+       }
+       up(&upperlayer_lock);
+       return rc;
+}
+EXPORT_SYMBOL(tpm_fe_register_receiver);
+
+/*
+ * Unregister the callback for receiving data from this module
+ */
+void tpm_fe_unregister_receiver(void)
+{
+       down(&upperlayer_lock);
+       upperlayer_tpmfe = NULL;
+       up(&upperlayer_lock);
+}
+EXPORT_SYMBOL(tpm_fe_unregister_receiver);
+
+/*
+ * Call this function to send data to the upper layer's
+ * registered receiver function.
+ */
+static int tpm_fe_send_upperlayer(const u8 * buf, size_t count,
+                                  const void *ptr)
+{
+       int rc;
+
+       down(&upperlayer_lock);
+
+       if (upperlayer_tpmfe && upperlayer_tpmfe->receive) {
+               rc = upperlayer_tpmfe->receive(buf, count, ptr);
+       } else {
+               rc = 0;
+       }
+
+       up(&upperlayer_lock);
+       return rc;
+}
+
+/**************************************************************
+ XENBUS support code
+**************************************************************/
+
+static void watch_for_status(struct xenbus_watch *watch, const char *node)
+{
+       struct tpmfront_info *info;
+       int err;
+       unsigned long ready;
+       struct tpm_private *tp = &my_private;
+
+       info = container_of(watch, struct tpmfront_info, watch);
+       node += strlen(watch->node);
+
+       if (tp->connected)
+               return;
+
+       err = xenbus_gather(watch->node,
+                           "ready", "%lu", &ready,
+                           NULL);
+       if (err) {
+               xenbus_dev_error(info->dev, err, "reading 'ready' field");
+               return;
+       }
+
+       tpmif_set_connected_state(tp, 1);
+
+       xenbus_dev_ok(info->dev);
+}
+
+
+static int setup_tpmring(struct xenbus_device *dev,
+                         struct tpmfront_info * info,
+                         domid_t backend_id)
+{
+       tpmif_tx_interface_t *sring;
+       struct tpm_private *tp = &my_private;
+
+       evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
+       int err;
+
+       sring = (void *)__get_free_page(GFP_KERNEL);
+       if (!sring) {
+               xenbus_dev_error(dev, -ENOMEM, "allocating shared ring");
+               return -ENOMEM;
+       }
+       tp->tx = sring;
+
+       tpm_allocate_buffers(tp);
+
+       info->ring_ref = gnttab_claim_grant_reference(&gref_head);
+       ASSERT(info->ring_ref != -ENOSPC);
+       gnttab_grant_foreign_access_ref(info->ring_ref,
+                                       backend_id,
+                                       (virt_to_machine(tp->tx) >> PAGE_SHIFT),
+                                       0);
+
+       op.u.alloc_unbound.dom = backend_id;
+       err = HYPERVISOR_event_channel_op(&op);
+       if (err) {
+               free_page((unsigned long)sring);
+               tp->tx = 0;
+               xenbus_dev_error(dev, err, "allocating event channel");
+               return err;
+       }
+       tpmif_connect(op.u.alloc_unbound.port, backend_id);
+       return 0;
+}
+
+
+static void destroy_tpmring(struct tpmfront_info *info, struct tpm_private *tp)
+{
+       tpmif_set_connected_state(tp,0);
+
+       if ( tp->tx != NULL ) {
+               free_page((unsigned long)tp->tx);
+               tp->tx = NULL;
+       }
+       unbind_evtchn_from_irqhandler(tp->evtchn, NULL);
+       tp->evtchn = 0;
+}
+
+
+static int talk_to_backend(struct xenbus_device *dev,
+                           struct tpmfront_info *info)
+{
+       char *backend;
+       const char *message;
+       int err;
+       int backend_id;
+
+       backend = NULL;
+       err = xenbus_gather(dev->nodename,
+                           "backend-id", "%i", &backend_id,
+                           "backend", NULL, &backend,
+                           NULL);
+       if (XENBUS_EXIST_ERR(err))
+               goto out;
+       if (backend && strlen(backend) == 0) {
+               err = -ENOENT;
+               goto out;
+       }
+       if (err < 0) {
+               xenbus_dev_error(dev, err, "reading %s/backend or backend-id",
+                                dev->nodename);
+               goto out;
+       }
+
+       info->backend_id      = backend_id;
+       my_private.backend_id = backend_id;
+
+       err = setup_tpmring(dev, info, backend_id);
+       if (err) {
+               xenbus_dev_error(dev, err, "setting up ring");
+               goto out;
+       }
+
+       err = xenbus_transaction_start(dev->nodename);
+       if (err) {
+               xenbus_dev_error(dev, err, "starting transaction");
+               goto destroy_tpmring;
+       }
+
+       err = xenbus_printf(dev->nodename,
+                           "ring-ref","%u", info->ring_ref);
+       if (err) {
+               message = "writing ring-ref";
+               goto abort_transaction;
+       }
+
+       err = xenbus_printf(dev->nodename,
+                           "event-channel", "%u", my_private.evtchn);
+       if (err) {
+               message = "writing event-channel";
+               goto abort_transaction;
+       }
+
+       info->backend = backend;
+       backend = NULL;
+
+       info->watch.node = info->backend;
+       info->watch.callback = watch_for_status;
+       err = register_xenbus_watch(&info->watch);
+       if (err) {
+               message = "registering watch on backend";
+               goto abort_transaction;
+       }
+
+       err = xenbus_transaction_end(0);
+       if (err) {
+               xenbus_dev_error(dev, err, "completing transaction");
+               goto destroy_tpmring;
+       }
+
+out:
+       if (backend)
+               kfree(backend);
+       return err;
+
+abort_transaction:
+       xenbus_transaction_end(1);
+       /* Have to do this *outside* transaction.  */
+       xenbus_dev_error(dev, err, "%s", message);
+destroy_tpmring:
+       destroy_tpmring(info, &my_private);
+       goto out;
+}
+
+
+static int tpmfront_probe(struct xenbus_device *dev,
+                          const struct xenbus_device_id *id)
+{
+       int err;
+       struct tpmfront_info *info;
+       int handle;
+
+       err = xenbus_scanf(dev->nodename,
+                          "handle", "%i", &handle);
+       if (XENBUS_EXIST_ERR(err))
+               return err;
+
+       if (err < 0) {
+               xenbus_dev_error(dev,err,"reading virtual-device");
+               return err;
+       }
+
+       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       if (!info) {
+               xenbus_dev_error(dev,err,"allocating info structure");
+               return err;
+       }
+       memset(info, 0x0, sizeof(*info));
+
+       info->dev = dev;
+       info->handle = handle;
+       dev->data = info;
+
+       err = talk_to_backend(dev, info);
+       if (err) {
+               kfree(info);
+               dev->data = NULL;
+               return err;
+       }
+
+       watch_for_status(&info->watch, info->watch.node);
+       return 0;
+}
+
+static int tpmfront_remove(struct xenbus_device *dev)
+{
+       struct tpmfront_info *info = dev->data;
+       if (info->backend)
+               unregister_xenbus_watch(&info->watch);
+
+       destroy_tpmring(info, &my_private);
+
+       kfree(info->backend);
+       kfree(info);
+
+       return 0;
+}
+
+static int tpmfront_suspend(struct xenbus_device *dev)
+{
+       struct tpmfront_info *info = dev->data;
+       struct tpm_private *tp = &my_private;
+
+       /* lock so no app can send */
+       down(&suspend_lock);
+
+       while (atomic_read(&tp->tx_busy)) {
+               printk("---- TPMIF: Outstanding request.\n");
+#if 0
+               /*
+                * Would like to wait until the outstanding request
+                * has come back, but this does not work properly, yet.
+                */
+               interruptible_sleep_on_timeout(&tp->wait_q,
+                                              100);
+#else
+               break;
+#endif
+       }
+
+       unregister_xenbus_watch(&info->watch);
+
+       kfree(info->backend);
+       info->backend = NULL;
+
+       destroy_tpmring(info, tp);
+
+       return 0;
+}
+
+static int tpmif_recover(void)
+{
+       return 0;
+}
+
+static int tpmfront_resume(struct xenbus_device *dev)
+{
+       struct tpmfront_info *info = dev->data;
+       int err;
+
+       err = talk_to_backend(dev, info);
+       if (!err) {
+               tpmif_recover();
+       }
+
+       /* unlock so apps can resume */
+       up(&suspend_lock);
+
+       return err;
+}
+
+static void tpmif_connect(u16 evtchn, domid_t domid)
+{
+       int err = 0;
+       struct tpm_private *tp = &my_private;
+
+       tp->evtchn = evtchn;
+       tp->backend_id  = domid;
+
+       err = bind_evtchn_to_irqhandler(
+               tp->evtchn,
+               tpmif_int, SA_SAMPLE_RANDOM, "tpmif", tp);
+       if ( err != 0 ) {
+               WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err);
+               return;
+       }
+}
+
+static struct xenbus_device_id tpmfront_ids[] = {
+       { "vtpm" },
+       { "" }
+};
+
+static struct xenbus_driver tpmfront = {
+       .name = "vtpm",
+       .owner = THIS_MODULE,
+       .ids = tpmfront_ids,
+       .probe = tpmfront_probe,
+       .remove =  tpmfront_remove,
+       .resume = tpmfront_resume,
+       .suspend = tpmfront_suspend,
+};
+
+static void __init init_tpm_xenbus(void)
+{
+       xenbus_register_device(&tpmfront);
+}
+
+
+static int
+tpm_allocate_buffers(struct tpm_private *tp)
+{
+       unsigned int i;
+
+       i = 0;
+       while (i < TPMIF_TX_RING_SIZE) {
+               tp->tx_buffers[i] = tx_buffer_alloc();
+               i++;
+       }
+
+       return 1;
+}
+
+static void
+tpmif_rx_action(unsigned long unused)
+{
+       struct tpm_private *tp = &my_private;
+
+       int i = 0;
+       unsigned int received;
+       unsigned int offset = 0;
+       u8 *buffer;
+       tpmif_tx_request_t *tx;
+       tx = &tp->tx->ring[i].req;
+
+       received = tx->size;
+
+       buffer = kmalloc(received, GFP_KERNEL);
+       if (NULL == buffer) {
+               goto exit;
+       }
+
+       i = 0;
+       while (i < TPMIF_TX_RING_SIZE &&
+              offset < received) {
+               struct tx_buffer *txb = tp->tx_buffers[i];
+               tpmif_tx_request_t *tx;
+               unsigned int tocopy;
+
+               tx = &tp->tx->ring[i].req;
+               tocopy = tx->size;
+               if (tocopy > PAGE_SIZE) {
+                       tocopy = PAGE_SIZE;
+               }
+
+               memcpy(&buffer[offset], txb->data, tocopy);
+
+               gnttab_release_grant_reference(&gref_head, tx->ref);
+
+               offset += tocopy;
+               i++;
+       }
+
+       tpm_fe_send_upperlayer(buffer, received, tp->tx_remember);
+       kfree(buffer);
+
+exit:
+       atomic_set(&tp->tx_busy, 0);
+       wake_up_interruptible(&tp->wait_q);
+}
+
+
+static irqreturn_t
+tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs)
+{
+       struct tpm_private *tp = tpm_priv;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tp->tx_lock, flags);
+       tasklet_schedule(&tpmif_rx_tasklet);
+       spin_unlock_irqrestore(&tp->tx_lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+
+static int
+tpm_xmit(struct tpm_private *tp,
+         const u8 * buf, size_t count, int isuserbuffer,
+         void *remember)
+{
+       tpmif_tx_request_t *tx;
+       TPMIF_RING_IDX i;
+       unsigned int offset = 0;
+
+       spin_lock_irq(&tp->tx_lock);
+
+       if (unlikely(atomic_read(&tp->tx_busy))) {
+               printk("There's an outstanding request/response on the way!\n");
+               spin_unlock_irq(&tp->tx_lock);
+               return -EBUSY;
+       }
+
+       if (tp->connected != 1) {
+               spin_unlock_irq(&tp->tx_lock);
+               return -EIO;
+       }
+
+       i = 0;
+       while (count > 0 && i < TPMIF_TX_RING_SIZE) {
+               struct tx_buffer *txb = tp->tx_buffers[i];
+               int copied;
+
+               if (NULL == txb) {
+                       DPRINTK("txb (i=%d) is NULL. buffers initilized?\n", i);
+                       DPRINTK("Not transmittin anything!\n");
+                       spin_unlock_irq(&tp->tx_lock);
+                       return -EFAULT;
+               }
+               copied = tx_buffer_copy(txb, &buf[offset], count,
+                                       isuserbuffer);
+               if (copied < 0) {
+                       /* An error occurred */
+                       return copied;
+               }
+               count -= copied;
+               offset += copied;
+
+               tx = &tp->tx->ring[i].req;
+
+               tx->id = i;
+               tx->addr = virt_to_machine(txb->data);
+               tx->size = txb->len;
+
+               DPRINTK("First 4 characters sent by TPM-FE are 0x%02x 0x%02x 
0x%02x 0x%02x\n",
+                       txb->data[0],txb->data[1],txb->data[2],txb->data[3]);
+
+               /* get the granttable reference for this page */
+               tx->ref = gnttab_claim_grant_reference( &gref_head );
+
+               if(-ENOSPC == tx->ref ) {
+                       DPRINTK(" Grant table claim reference failed in func:%s 
line:%d file:%s\n", __FUNCTION__, __LINE__, __FILE__);
+                       return -ENOSPC;
+               }
+               gnttab_grant_foreign_access_ref( tx->ref,
+                                                tp->backend_id,
+                                                (tx->addr >> PAGE_SHIFT),
+                                                0 /*RW*/);
+               i++;
+               wmb();
+       }
+
+       atomic_set(&tp->tx_busy, 1);
+       tp->tx_remember = remember;
+       mb();
+
+       DPRINTK("Notifying backend via event channel %d\n",
+               tp->evtchn);
+
+       notify_via_evtchn(tp->evtchn);
+
+       spin_unlock_irq(&tp->tx_lock);
+       return offset;
+}
+
+
+static void tpmif_notify_upperlayer(struct tpm_private *tp)
+{
+       /*
+        * Notify upper layer about the state of the connection
+        * to the BE.
+        */
+       down(&upperlayer_lock);
+
+       if (upperlayer_tpmfe != NULL) {
+               switch (tp->connected) {
+                       case 1:
+                               
upperlayer_tpmfe->status(TPMFE_STATUS_CONNECTED);
+                       break;
+
+                       default:
+                               upperlayer_tpmfe->status(0);
+                       break;
+               }
+       }
+       up(&upperlayer_lock);
+}
+
+
+static void tpmif_set_connected_state(struct tpm_private *tp, int newstate)
+{
+       if (newstate != tp->connected) {
+               tp->connected = newstate;
+               tpmif_notify_upperlayer(tp);
+       }
+}
+
+
+/* =================================================================
+ * Initialization function.
+ * =================================================================
+ */
+
+static int __init
+tpmif_init(void)
+{
+       IPRINTK("Initialising the vTPM driver.\n");
+       if ( gnttab_alloc_grant_references ( TPMIF_TX_RING_SIZE,
+                                            &gref_head ) < 0) {
+               return -EFAULT;
+       }
+       /*
+        * Only don't send the driver status when we are in the
+        * INIT domain.
+        */
+       spin_lock_init(&my_private.tx_lock);
+       init_waitqueue_head(&my_private.wait_q);
+
+       init_tpm_xenbus();
+
+       return 0;
+}
+
+__initcall(tpmif_init);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h      Fri Sep  9 
16:30:54 2005
@@ -0,0 +1,38 @@
+#ifndef TPM_FRONT_H
+#define TPM_FRONT_H
+
+
+struct tpm_private {
+       tpmif_tx_interface_t *tx;
+       unsigned int evtchn;
+       int connected;
+
+       spinlock_t tx_lock;
+
+       struct tx_buffer *tx_buffers[TPMIF_TX_RING_SIZE];
+
+       atomic_t tx_busy;
+       void *tx_remember;
+       domid_t backend_id;
+       wait_queue_head_t wait_q;
+};
+
+
+struct tpmfront_info
+{
+       struct xenbus_watch watch;
+       int handle;
+       struct xenbus_device *dev;
+       char *backend;
+       int ring_ref;
+       domid_t backend_id;
+};
+
+
+struct tx_buffer {
+       unsigned int size;      // available space in data
+       unsigned int len;       // used space in data
+       unsigned char *data;    // pointer to a page
+};
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c      Fri Sep  9 
16:30:54 2005
@@ -0,0 +1,186 @@
+/*
+ * xenbus_dev.c
+ * 
+ * Driver giving user-space access to the kernel's xenbus connection
+ * to xenstore.
+ * 
+ * Copyright (c) 2005, Christian Limpach
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/uio.h>
+#include <linux/notifier.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+
+#include "xenstored.h"
+#include "xenbus_comms.h"
+
+#include <asm/uaccess.h>
+#include <asm-xen/xenbus.h>
+#include <asm-xen/linux-public/xenbus_dev.h>
+#include <asm-xen/xen_proc.h>
+
+struct xenbus_dev_data {
+       int in_transaction;
+};
+
+static struct proc_dir_entry *xenbus_dev_intf;
+
+void *xs_talkv(enum xsd_sockmsg_type type, const struct kvec *iovec,
+              unsigned int num_vecs, unsigned int *len);
+
+static int xenbus_dev_talkv(struct xenbus_dev_data *u, unsigned long data)
+{
+       struct xenbus_dev_talkv xt;
+       unsigned int len;
+       void *resp, *base;
+       struct kvec *iovec;
+       int ret = -EFAULT, v = 0;
+
+       if (copy_from_user(&xt, (void *)data, sizeof(xt)))
+               return -EFAULT;
+
+       iovec = kmalloc(xt.num_vecs * sizeof(struct kvec), GFP_KERNEL);
+       if (iovec == NULL)
+               return -ENOMEM;
+
+       if (copy_from_user(iovec, xt.iovec,
+                          xt.num_vecs * sizeof(struct kvec)))
+               goto out;
+
+       for (v = 0; v < xt.num_vecs; v++) {
+               base = iovec[v].iov_base;
+               iovec[v].iov_base = kmalloc(iovec[v].iov_len, GFP_KERNEL);
+               if (iovec[v].iov_base == NULL ||
+                   copy_from_user(iovec[v].iov_base, base, iovec[v].iov_len))
+               {
+                       if (iovec[v].iov_base)
+                               kfree(iovec[v].iov_base);
+                       else
+                               ret = -ENOMEM;
+                       v--;
+                       goto out;
+               }
+       }
+
+       resp = xs_talkv(xt.type, iovec, xt.num_vecs, &len);
+       if (IS_ERR(resp)) {
+               ret = PTR_ERR(resp);
+               goto out;
+       }
+
+       switch (xt.type) {
+       case XS_TRANSACTION_START:
+               u->in_transaction = 1;
+               break;
+       case XS_TRANSACTION_END:
+               u->in_transaction = 0;
+               break;
+       default:
+               break;
+       }
+
+       ret = len;
+       if (len > xt.len)
+               len = xt.len;
+
+       if (copy_to_user(xt.buf, resp, len))
+               ret = -EFAULT;
+
+       kfree(resp);
+ out:
+       while (v-- > 0)
+               kfree(iovec[v].iov_base);
+       kfree(iovec);
+       return ret;
+}
+
+static int xenbus_dev_ioctl(struct inode *inode, struct file *filp,
+                           unsigned int cmd, unsigned long data)
+{
+       struct xenbus_dev_data *u = filp->private_data;
+       int ret = -ENOSYS;
+
+       switch (cmd) {
+       case IOCTL_XENBUS_DEV_TALKV:
+               ret = xenbus_dev_talkv(u, data);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+static int xenbus_dev_open(struct inode *inode, struct file *filp)
+{
+       struct xenbus_dev_data *u;
+
+       u = kmalloc(sizeof(*u), GFP_KERNEL);
+       if (u == NULL)
+               return -ENOMEM;
+
+       memset(u, 0, sizeof(*u));
+
+       filp->private_data = u;
+
+       down(&xenbus_lock);
+
+       return 0;
+}
+
+static int xenbus_dev_release(struct inode *inode, struct file *filp)
+{
+       struct xenbus_dev_data *u = filp->private_data;
+
+       if (u->in_transaction)
+               xenbus_transaction_end(1);
+
+       up(&xenbus_lock);
+
+       kfree(u);
+
+       return 0;
+}
+
+static struct file_operations xenbus_dev_file_ops = {
+       ioctl: xenbus_dev_ioctl,
+       open: xenbus_dev_open,
+       release: xenbus_dev_release
+};
+
+static int __init
+xenbus_dev_init(void)
+{
+       xenbus_dev_intf = create_xen_proc_entry("xenbus", 0400);
+       if (xenbus_dev_intf)
+               xenbus_dev_intf->proc_fops = &xenbus_dev_file_ops;
+
+       return 0;
+}
+
+__initcall(xenbus_dev_init);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/linux-public/xenbus_dev.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/linux-public/xenbus_dev.h    Fri Sep 
 9 16:30:54 2005
@@ -0,0 +1,47 @@
+/*
+ * xenbus_dev.h
+ * 
+ * Copyright (c) 2005, Christian Limpach
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef _XENBUS_DEV_H_
+#define _XENBUS_DEV_H_
+
+struct xenbus_dev_talkv {
+       enum xsd_sockmsg_type type;
+       const struct kvec *iovec;
+       unsigned int num_vecs;
+       char *buf;
+       unsigned int len;
+};
+
+/*
+ * @cmd: IOCTL_XENBUS_DEV_TALKV
+ * @arg: struct xenbus_dev_talkv
+ * Return: 0 on success, error code on failure.
+ */
+#define        IOCTL_XENBUS_DEV_TALKV \
+       _IOC(_IOC_NONE, 'X', 0, sizeof(struct xenbus_dev_talkv))
+
+#endif /* _XENBUS_DEV_H_ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/include/linux/tpmfe.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/linux/tpmfe.h        Fri Sep  9 16:30:54 2005
@@ -0,0 +1,33 @@
+#ifndef TPM_FE_H
+#define TPM_FE_H
+
+struct tpmfe_device {
+       /*
+        * Let upper layer receive data from front-end
+        */
+       int (*receive)(const u8 *buffer, size_t count, const void *ptr);
+       /*
+        * Indicate the status of the front-end to the upper
+        * layer.
+        */
+       void (*status)(unsigned int flags);
+
+       /*
+        * This field indicates the maximum size the driver can
+        * transfer in one chunk. It is filled out by the front-end
+        * driver and should be propagated to the generic tpm driver
+        * for allocation of buffers.
+        */
+       unsigned int max_tx_size;
+};
+
+enum {
+       TPMFE_STATUS_DISCONNECTED = 0x0,
+       TPMFE_STATUS_CONNECTED = 0x1
+};
+
+int tpm_fe_send(const u8 * buf, size_t count, void *ptr);
+int tpm_fe_register_receiver(struct tpmfe_device *);
+void tpm_fe_unregister_receiver(void);
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/README.sept05
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/blktap/README.sept05        Fri Sep  9 16:30:54 2005
@@ -0,0 +1,33 @@
+The blktap has been rewritten substantially based on the current
+blkback driver.  I've removed passthrough support, as this is broken
+by the move to grant tables and the lack of transitive grants.  A
+blktap VM is now only capable of terminating block requests in
+userspace.
+
+ublkback/ contains a _very_ initial cut at a user-level version of the block
+backend driver.  It gives a working example of how the current tap
+interfaces are used, in particular w.r.t. the vbd directories in
+xenstore.
+
+parallax/ contains fairly recent parallax code.  This does not run on
+the changed blktap interface, but should only be a couple of hours
+work to get going again.
+
+All of the tricky bits are done, but there is plenty of cleaning to
+do, and the top-level functionality is not here yet.  At the moment,
+the daemon ignores the pdev requested by the tools and opens the file 
+or device specified by TMP_IMAGE_FILE_NAME in ublkback.c.
+
+TODO:
+1. Fix to allow pdev in the store to specify the device to open.
+2. Add support (to tools as well) to mount arbitrary files...
+   just write the filename to mount into the store, instead of pdev.
+3. Reeximine blkif refcounting, it is almost certainly broken at the moment.
+   - creating a blkif should take a reference.
+   - each inflight request should take a reference on dequeue in blktaplib
+   - sending responses should drop refs.
+   - blkif should be implicitly freed when refcounts fall to 0.
+4. Modify the parallax req/rsp code as per ublkback to use the new tap 
+   interfaces. 
+5. Write a front end that allows parallax and normal mounts to coexist
+6. Allow blkback and blktap to run at the same time.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/blkif.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/blktap/blkif.c      Fri Sep  9 16:30:54 2005
@@ -0,0 +1,213 @@
+/*
+ * blkif.c
+ * 
+ * The blkif interface for blktap.  A blkif describes an in-use virtual disk.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <err.h>
+
+#include "blktaplib.h"
+
+#if 1
+#define DPRINTF(_f, _a...) printf ( _f , ## _a )
+#else
+#define DPRINTF(_f, _a...) ((void)0)
+#endif
+
+#define BLKIF_HASHSZ 1024
+#define BLKIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(BLKIF_HASHSZ-1))
+
+static blkif_t      *blkif_hash[BLKIF_HASHSZ];
+
+blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle)
+{
+    blkif_t *blkif = blkif_hash[BLKIF_HASH(domid, handle)];
+    while ( (blkif != NULL) && 
+            ((blkif->domid != domid) || (blkif->handle != handle)) )
+        blkif = blkif->hash_next;
+    return blkif;
+}
+
+blkif_t *alloc_blkif(domid_t domid)
+{
+    blkif_t *blkif;
+
+    blkif = (blkif_t *)malloc(sizeof(blkif_t));
+    if (!blkif)
+        return NULL;
+
+    memset(blkif, 0, sizeof(*blkif));
+    blkif->domid = domid;
+
+    return blkif;
+}
+
+static int (*new_blkif_hook)(blkif_t *blkif) = NULL;
+void register_new_blkif_hook(int (*fn)(blkif_t *blkif))
+{
+    new_blkif_hook = fn;
+}
+
+int blkif_init(blkif_t *blkif, long int handle, long int pdev, 
+               long int readonly)
+{
+    domid_t domid;
+    blkif_t **pblkif;
+    
+    if (blkif == NULL)
+        return -EINVAL;
+
+    domid = blkif->domid;
+    blkif->handle   = handle;
+    blkif->pdev     = pdev;
+    blkif->readonly = readonly;
+
+    /*
+     * Call out to the new_blkif_hook. The tap application should define this,
+     * and it should return having set blkif->ops
+     * 
+     */
+    if (new_blkif_hook == NULL)
+    {
+        warn("Probe detected a new blkif, but no new_blkif_hook!");
+        return -1;
+    }
+    new_blkif_hook(blkif);
+
+    /* Now wire it in. */
+    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
+    while ( *pblkif != NULL )
+    {
+        if ( ((*pblkif)->domid == domid) && ((*pblkif)->handle == handle) )
+        {
+            DPRINTF("Could not create blkif: already exists\n");
+            return -1;
+        }
+        pblkif = &(*pblkif)->hash_next;
+    }
+    blkif->hash_next = NULL;
+    *pblkif = blkif;
+
+    return 0;
+}
+
+void free_blkif(blkif_t *blkif)
+{
+    blkif_t **pblkif, *curs;
+    
+    pblkif = &blkif_hash[BLKIF_HASH(blkif->domid, blkif->handle)];
+    while ( (curs = *pblkif) != NULL )
+    {
+        if ( blkif == curs )
+        {
+            *pblkif = curs->hash_next;
+        }
+        pblkif = &curs->hash_next;
+    }
+    if (blkif != NULL)
+        free(blkif);
+}
+
+void blkif_register_request_hook(blkif_t *blkif, char *name, 
+                                 int (*rh)(blkif_t *, blkif_request_t *, int)) 
+{
+    request_hook_t *rh_ent, **c;
+    
+    rh_ent = (request_hook_t *)malloc(sizeof(request_hook_t));
+    if (!rh_ent) 
+    {
+        warn("couldn't allocate a new hook");
+        return;
+    }
+    
+    rh_ent->func  = rh;
+    rh_ent->next = NULL;
+    if (asprintf(&rh_ent->name, "%s", name) == -1)
+    {
+        free(rh_ent);
+        warn("couldn't allocate a new hook name");
+        return;
+    }
+    
+    c = &blkif->request_hook_chain;
+    while (*c != NULL) {
+        c = &(*c)->next;
+    }
+    *c = rh_ent;
+}
+
+void blkif_register_response_hook(blkif_t *blkif, char *name, 
+                                  int (*rh)(blkif_t *, blkif_response_t *, 
int)) 
+{
+    response_hook_t *rh_ent, **c;
+    
+    rh_ent = (response_hook_t *)malloc(sizeof(response_hook_t));
+    if (!rh_ent) 
+    { 
+        warn("couldn't allocate a new hook");
+        return;
+    }
+    
+    rh_ent->func  = rh;
+    rh_ent->next = NULL;
+    if (asprintf(&rh_ent->name, "%s", name) == -1)
+    {
+        free(rh_ent);
+        warn("couldn't allocate a new hook name");
+        return;
+    }
+    
+    c = &blkif->response_hook_chain;
+    while (*c != NULL) {
+        c = &(*c)->next;
+    }
+    *c = rh_ent;
+}
+
+void blkif_print_hooks(blkif_t *blkif)
+{
+    request_hook_t  *req_hook;
+    response_hook_t *rsp_hook;
+    
+    DPRINTF("Request Hooks:\n");
+    req_hook = blkif->request_hook_chain;
+    while (req_hook != NULL)
+    {
+        DPRINTF("  [0x%p] %s\n", req_hook->func, req_hook->name);
+        req_hook = req_hook->next;
+    }
+    
+    DPRINTF("Response Hooks:\n");
+    rsp_hook = blkif->response_hook_chain;
+    while (rsp_hook != NULL)
+    {
+        DPRINTF("  [0x%p] %s\n", rsp_hook->func, rsp_hook->name);
+        rsp_hook = rsp_hook->next;
+    }
+}
+
+
+long int vbd_size(blkif_t *blkif)
+{
+    return 1000000000;
+}
+
+long int vbd_secsize(blkif_t *blkif)
+{
+    return 512;
+}
+
+unsigned vbd_info(blkif_t *blkif)
+{
+    return 0;
+}
+
+
+void __init_blkif(void)
+{    
+    memset(blkif_hash, 0, sizeof(blkif_hash));
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/list.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/blktap/list.h       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,55 @@
+/*
+ * list.h
+ * 
+ * This is a subset of linux's list.h intended to be used in user-space.
+ * 
+ */
+
+#ifndef __LIST_H__
+#define __LIST_H__
+
+#define LIST_POISON1  ((void *) 0x00100100)
+#define LIST_POISON2  ((void *) 0x00200200)
+
+struct list_head {
+        struct list_head *next, *prev;
+};
+ 
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+ 
+#define LIST_HEAD(name) \
+        struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void __list_add(struct list_head *new,
+                              struct list_head *prev,
+                              struct list_head *next)
+{
+        next->prev = new;
+        new->next = next;
+        new->prev = prev;
+        prev->next = new;
+}
+
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+        __list_add(new, head, head->next);
+}
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+        next->prev = prev;
+        prev->next = next;
+}
+static inline void list_del(struct list_head *entry)
+{
+        __list_del(entry->prev, entry->next);
+        entry->next = LIST_POISON1;
+        entry->prev = LIST_POISON2;
+}
+#define list_entry(ptr, type, member)                                   \
+        ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+#define list_for_each_entry(pos, head, member)                          \
+        for (pos = list_entry((head)->next, typeof(*pos), member);      \
+             &pos->member != (head);                                    \
+             pos = list_entry(pos->member.next, typeof(*pos), member))
+
+#endif /* __LIST_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/ublkback/Makefile
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/blktap/ublkback/Makefile    Fri Sep  9 16:30:54 2005
@@ -0,0 +1,42 @@
+
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+INCLUDES += -I..
+
+INSTALL            = install
+INSTALL_PROG = $(INSTALL) -m0755
+IBIN         = ublkback
+INSTALL_DIR  = /usr/sbin
+
+CFLAGS   += -Wall
+CFLAGS   += -Werror
+CFLAGS   += -Wno-unused
+#CFLAGS   += -O3
+CFLAGS   += -g3
+CFLAGS   += -fno-strict-aliasing
+CFLAGS   += -I $(XEN_LIBXC)
+CFLAGS   += $(INCLUDES) -I.
+CFLAGS   += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
+# Get gcc to generate the dependencies for us.
+CFLAGS   += -Wp,-MD,.$(@F).d
+DEPS     = .*.d
+
+OBJS     = $(patsubst %.c,%.o,$(SRCS))
+
+all: $(IBIN)
+
+LINUX_ROOT := $(wildcard $(XEN_ROOT)/linux-2.6.*-xen-sparse)
+
+install:
+       $(INSTALL_PROG) $(IBIN) $(DESTDIR)$(INSTALL_DIR)
+clean:
+       rm -rf *.o*~ $(DEPS) xen TAGS $(IBIN)
+
+ublkback: 
+       $(CC) $(CFLAGS) -o ublkback -L$(XEN_LIBXC) -L. -L..  \
+             -lblktap -laio ublkback.c ublkbacklib.c -pg
+
+.PHONY: clean install
+
+-include $(DEPS)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/ublkback/ublkback.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/blktap/ublkback/ublkback.c  Fri Sep  9 16:30:54 2005
@@ -0,0 +1,18 @@
+/* ublkback.c
+ *
+ * libaio-based userlevel backend.
+ */
+
+#include "blktaplib.h"
+#include "ublkbacklib.h"
+
+
+int main(int argc, char *argv[])
+{
+    ublkback_init();
+    
+    register_new_blkif_hook(ublkback_new_blkif);
+    blktap_listen();
+    
+    return 0;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/ublkback/ublkbacklib.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/blktap/ublkback/ublkbacklib.c       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,477 @@
+/* ublkbacklib.c
+ *
+ * file/device image-backed block device -- using linux libaio.
+ * 
+ * (c) 2004 Andrew Warfield.
+ *
+ * Xend has been modified to use an amorfs:[fsid] disk tag.
+ * This will show up as device type (maj:240,min:0) = 61440.
+ *
+ * The fsid is placed in the sec_start field of the disk extent.
+ *
+ * NOTE: This doesn't work.  Grrr.
+ */
+
+#define _GNU_SOURCE
+#define __USE_LARGEFILE64
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <db.h>       
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <unistd.h>
+#include <errno.h>
+#include <libaio.h>
+#include <pthread.h>
+#include <time.h>
+#include <err.h>
+#include "blktaplib.h"
+
+/* XXXX:  */
+/* Current code just mounts this file/device to any requests that come in. */
+//#define TMP_IMAGE_FILE_NAME "/dev/sda1"
+#define TMP_IMAGE_FILE_NAME "fc3.image"
+
+#define MAX_REQUESTS            64 /* must be synced with the blkif drivers. */
+#define MAX_SEGMENTS_PER_REQ    11
+#define SECTOR_SHIFT             9
+#define MAX_AIO_REQS   (MAX_REQUESTS * MAX_SEGMENTS_PER_REQ)
+
+#if 0
+#define DPRINTF(_f, _a...) printf ( _f , ## _a )
+#else
+#define DPRINTF(_f, _a...) ((void)0)
+#endif
+           
+#if 1                                                                        
+#define ASSERT(_p) \
+    if ( !(_p) ) { printf("Assertion '%s' failed, line %d, file %s", #_p , \
+    __LINE__, __FILE__); *(int*)0=0; }
+#else
+#define ASSERT(_p) ((void)0)
+#endif                                                                     
+
+/* Note on pending_reqs: I assume all reqs are queued before they start to 
+ * get filled.  so count of 0 is an unused record.
+ */
+typedef struct {
+    blkif_request_t  req;
+    blkif_t         *blkif;
+    int              count;
+} pending_req_t;
+
+static pending_req_t    pending_list[MAX_REQUESTS];
+static io_context_t  ctx;
+static struct iocb  *iocb_free[MAX_AIO_REQS];
+static int           iocb_free_count;
+
+/* ---[ Notification mecahnism ]--------------------------------------- */
+
+enum { 
+    READ   = 0,
+    WRITE  = 1
+};
+
+static int aio_notify[2];
+static volatile int aio_listening = 0;
+static pthread_mutex_t notifier_sem = PTHREAD_MUTEX_INITIALIZER;
+
+static struct io_event aio_events[MAX_AIO_REQS];
+static int             aio_event_count = 0;
+
+/* this is commented out in libaio.h for some reason. */
+extern int io_queue_wait(io_context_t ctx, struct timespec *timeout);
+
+static void *notifier_thread(void *arg)
+{
+    int ret; 
+    int msg = 0x00feeb00;
+    
+    DPRINTF("Notifier thread started.\n");
+    for (;;) {
+        pthread_mutex_lock(&notifier_sem);
+        if ((ret = io_getevents(ctx, 1, MAX_AIO_REQS, aio_events, 0)) > 0) {
+            aio_event_count = ret;
+            write(aio_notify[WRITE], &msg, sizeof(msg));
+        } else {
+                printf("[io_queue_wait error! %d]\n", errno);
+                pthread_mutex_unlock(&notifier_sem);
+        }
+    }
+}
+
+/* --- Talking to xenstore: ------------------------------------------- */
+
+int ublkback_request(blkif_t *blkif, blkif_request_t *req, int batch_done);
+int ublkback_response(blkif_t *blkif, blkif_response_t *rsp, int batch_done);
+
+typedef struct image {
+    /* These need to turn into an array/rbtree for multi-disk support. */
+    int  fd;
+    u64  fsid;
+    blkif_vdev_t   vdevice;
+    long int size;
+    long int secsize;
+    long int info;
+} image_t;
+
+long int ublkback_get_size(blkif_t *blkif)
+{
+    image_t *img = (image_t *)blkif->prv;
+    return img->size;
+}
+
+long int ublkback_get_secsize(blkif_t *blkif)
+{
+    image_t *img = (image_t *)blkif->prv;
+    return img->secsize;
+}
+
+unsigned ublkback_get_info(blkif_t *blkif)
+{
+    image_t *img = (image_t *)blkif->prv;
+    return img->info;
+}
+
+static struct blkif_ops ublkback_ops = {
+    get_size:    ublkback_get_size,
+    get_secsize: ublkback_get_secsize,
+    get_info:    ublkback_get_info,
+};
+
+int ublkback_new_blkif(blkif_t *blkif)
+{
+    image_t *image;
+    struct stat stat;
+    int ret;
+
+    image = (image_t *)malloc(sizeof(image_t));
+    if (image == NULL) {
+        printf("error allocating image record.\n");
+        return -ENOMEM;
+    }
+
+    /* Open it. */
+    image->fd = open(TMP_IMAGE_FILE_NAME, 
+                     O_RDWR | O_DIRECT | O_LARGEFILE);
+
+    if ((image->fd < 0) && (errno == EINVAL)) {
+        /* Maybe O_DIRECT isn't supported. */
+        warn("open() failed on '%s', trying again without O_DIRECT",
+               TMP_IMAGE_FILE_NAME);
+        image->fd = open(TMP_IMAGE_FILE_NAME, O_RDWR | O_LARGEFILE);
+    }
+
+    if (image->fd < 0) {
+        warn("Couldn't open image file!");
+        free(image);
+        return -EINVAL;
+    }
+
+    /* Size it. */
+    ret = fstat(image->fd, &stat);
+    if (ret != 0) {
+        printf("Couldn't stat image in PROBE!");
+        return -EINVAL;
+    }
+    
+    image->size = (stat.st_size >> SECTOR_SHIFT);
+
+    /* TODO: IOCTL to get size of raw device. */
+/*
+  ret = ioctl(img->fd, BLKGETSIZE, &blksize);
+  if (ret != 0) {
+  printf("Couldn't ioctl image in PROBE!\n");
+  goto err;
+  }
+*/
+    if (image->size == 0)
+        image->size =((u64) 16836057);
+    image->secsize = 512;
+    image->info = 0;
+
+    /* Register the hooks */
+    blkif_register_request_hook(blkif, "Ublkback req.", ublkback_request);
+    blkif_register_response_hook(blkif, "Ublkback resp.", ublkback_response);
+
+
+    printf(">X<Created a new blkif! pdev was %ld, but you got %s\n", 
+           blkif->pdev, TMP_IMAGE_FILE_NAME);
+
+    blkif->ops = &ublkback_ops;
+    blkif->prv = (void *)image;
+
+    return 0;
+}
+
+
+/* --- Moving the bits: ----------------------------------------------- */
+
+static int batch_count = 0;
+int ublkback_request(blkif_t *blkif, blkif_request_t *req, int batch_done)
+{
+    int fd;
+    u64 sector;
+    char *spage, *dpage;
+    int ret, i, idx;
+    blkif_response_t *rsp;
+    domid_t dom = ID_TO_DOM(req->id);
+    static struct iocb *ioq[MAX_SEGMENTS_PER_REQ*MAX_REQUESTS]; 
+    static int io_idx = 0;
+    struct iocb *io;
+    image_t *img;
+
+    img = (image_t *)blkif->prv;
+    fd = img->fd;
+
+    switch (req->operation) 
+    {
+    case BLKIF_OP_WRITE:
+    {
+        unsigned long size;
+        
+        
+        batch_count++;
+
+        idx = ID_TO_IDX(req->id);
+        ASSERT(pending_list[idx].count == 0);
+        memcpy(&pending_list[idx].req, req, sizeof(*req));
+        pending_list[idx].count = req->nr_segments;
+        pending_list[idx].blkif = blkif;
+        
+        for (i = 0; i < req->nr_segments; i++) {
+            
+            sector = req->sector_number + (8*i);
+            
+            size = blkif_last_sect (req->frame_and_sects[i]) -
+                   blkif_first_sect(req->frame_and_sects[i]) + 1;
+            
+            if (blkif_first_sect(req->frame_and_sects[i]) != 0)
+            DPRINTF("iWR: sec_nr: %10llu sec: %10llu (%1lu,%1lu) pos: %15lu\n",
+                    req->sector_number, sector, 
+                    blkif_first_sect(req->frame_and_sects[i]),
+                    blkif_last_sect (req->frame_and_sects[i]),
+                    (long)(sector << SECTOR_SHIFT));
+                        
+            spage  = (char *)MMAP_VADDR(ID_TO_IDX(req->id), i);
+            spage += blkif_first_sect(req->frame_and_sects[i]) << SECTOR_SHIFT;
+            
+            /*convert size and sector to byte offsets */
+            size   <<= SECTOR_SHIFT;
+            sector <<= SECTOR_SHIFT;
+            
+            io = iocb_free[--iocb_free_count];
+            io_prep_pwrite(io, fd, spage, size, sector);
+            io->data = (void *)idx;
+            //ioq[i] = io;
+            ioq[io_idx++] = io;
+        }
+
+        if (batch_done) {
+            ret = io_submit(ctx, io_idx, ioq);
+            batch_count = 0;
+            if (ret < 0)
+                printf("BADNESS: io_submit error! (%d)\n", errno);
+            io_idx = 0;
+        }
+        
+        return BLKTAP_STOLEN;
+        
+    }
+    case BLKIF_OP_READ:
+    {
+        unsigned long size;
+        
+        batch_count++;
+        idx = ID_TO_IDX(req->id);
+        ASSERT(pending_list[idx].count == 0);
+        memcpy(&pending_list[idx].req, req, sizeof(*req));
+        pending_list[idx].count = req->nr_segments;
+        pending_list[idx].blkif = blkif;
+        
+        for (i = 0; i < req->nr_segments; i++) {
+            
+            sector  = req->sector_number + (8*i);
+            
+            size = blkif_last_sect (req->frame_and_sects[i]) -
+                   blkif_first_sect(req->frame_and_sects[i]) + 1;
+            
+            dpage  = (char *)MMAP_VADDR(ID_TO_IDX(req->id), i);
+            dpage += blkif_first_sect(req->frame_and_sects[i]) << SECTOR_SHIFT;
+            
+            if (blkif_first_sect(req->frame_and_sects[i]) != 0)
+            DPRINTF("iRD : sec_nr: %10llu sec: %10llu (%1lu,%1lu) "
+                    "pos: %15lu dpage: %p\n", 
+                    req->sector_number, sector, 
+                    blkif_first_sect(req->frame_and_sects[i]),
+                    blkif_last_sect (req->frame_and_sects[i]),
+                    (long)(sector << SECTOR_SHIFT), dpage);
+            
+            /*convert size and sector to byte offsets */
+            size   <<= SECTOR_SHIFT;
+            sector <<= SECTOR_SHIFT;
+            
+
+            /*
+             * NB: Looks like AIO now has non-page aligned support, this path 
+             * can probably be removed...  Only really used for hunting
+             * superblocks anyway... ;)
+             */
+            if ( ((unsigned long)dpage % PAGE_SIZE) != 0 ) {
+                /* AIO to raw devices must be page aligned, so do this read
+                 * synchronously.  The OS is probably just looking for 
+                 * a superblock or something, so this won't hurt performance. 
+                 */
+                int ret;
+
+                printf("Slow path block read.\n");
+                /* Question: do in-progress aio ops modify the file cursor? */
+                ret = lseek(fd, sector, SEEK_SET);
+                if (ret == (off_t)-1)
+                    printf("lseek failed!\n");
+                ret = read(fd, dpage, size);
+                if (ret < 0)
+                    printf("read problem (%d)\n", ret);
+                printf("|\n|\n| read: %lld, %lu, %d\n|\n|\n", sector, size, 
ret);
+
+                /* not an async request any more... */
+                pending_list[idx].count--;
+
+                rsp = (blkif_response_t *)req;
+                rsp->id = req->id;
+                rsp->operation = BLKIF_OP_READ;
+                rsp->status = BLKIF_RSP_OKAY;
+                return BLKTAP_RESPOND;  
+                /* Doh -- need to flush aio if this is end-of-batch */
+            }
+
+            io = iocb_free[--iocb_free_count];
+            
+            io_prep_pread(io, fd, dpage, size, sector);
+            io->data = (void *)idx;
+            
+            ioq[io_idx++] = io;
+            //ioq[i] = io;
+        }
+        
+        if (batch_done) {
+            ret = io_submit(ctx, io_idx, ioq);
+            batch_count = 0;
+            if (ret < 0)
+                printf("BADNESS: io_submit error! (%d)\n", errno);
+            io_idx = 0;
+        }
+        
+        return BLKTAP_STOLEN;
+        
+    }
+    }
+    
+    printf("Unknown block operation!\n");
+err:
+    rsp = (blkif_response_t *)req;
+    rsp->id = req->id;
+    rsp->operation = req->operation;
+    rsp->status = BLKIF_RSP_ERROR;
+    return BLKTAP_RESPOND;  
+}
+
+
+int ublkback_pollhook(int fd)
+{
+    struct io_event *ep;
+    int n, ret, idx;
+    blkif_request_t *req;
+    blkif_response_t *rsp;
+    int responses_queued = 0;
+    int pages=0;
+    
+    for (ep = aio_events; aio_event_count-- > 0; ep++) {
+        struct iocb *io = ep->obj;
+        idx = (int) ep->data;
+        
+        if ((idx > MAX_REQUESTS-1) || (pending_list[idx].count == 0)){
+            printf("invalid index returned(%u)!\n", idx);
+            break;
+        }
+        
+        if ((int)ep->res < 0) 
+            printf("***\n***aio request error! (%d,%d)\n***\n", 
+                   (int)ep->res, (int)ep->res2);
+        
+        pending_list[idx].count--;
+        iocb_free[iocb_free_count++] = io;
+        pages++;
+
+        if (pending_list[idx].count == 0) {
+            blkif_request_t tmp = pending_list[idx].req;
+            rsp = (blkif_response_t *)&pending_list[idx].req;
+            rsp->id = tmp.id;
+            rsp->operation = tmp.operation;
+            rsp->status = BLKIF_RSP_OKAY;
+            blkif_inject_response(pending_list[idx].blkif, rsp);
+            responses_queued++;
+        }
+    }
+
+    if (responses_queued) {
+        blktap_kick_responses();
+    }
+    
+    read(aio_notify[READ], &idx, sizeof(idx));
+    aio_listening = 1;
+    pthread_mutex_unlock(&notifier_sem);
+    
+    return 0;
+}
+
+/* the image library terminates the request stream. _resp is a noop. */
+int ublkback_response(blkif_t *blkif, blkif_response_t *rsp, int batch_done)
+{   
+    return BLKTAP_PASS;
+}
+
+void ublkback_init(void)
+{
+    int i, rc;
+    pthread_t p;
+    
+    for (i = 0; i < MAX_REQUESTS; i++)
+        pending_list[i].count = 0; 
+    
+    memset(&ctx, 0, sizeof(ctx));
+    rc = io_queue_init(MAX_AIO_REQS, &ctx);
+    if (rc != 0) {
+        printf("queue_init failed! (%d)\n", rc);
+        exit(0);
+    }
+    
+    for (i=0; i<MAX_AIO_REQS; i++) {
+        if (!(iocb_free[i] = (struct iocb *)malloc(sizeof(struct iocb)))) {
+            printf("error allocating iocb array\n");
+            exit(0);
+        }
+        iocb_free_count = i;
+    }
+    
+    rc = pipe(aio_notify);
+    if (rc != 0) {
+        printf("pipe failed! (%d)\n", errno);
+        exit(0);
+    }
+    
+    rc = pthread_create(&p, NULL, notifier_thread, NULL);
+    if (rc != 0) {
+        printf("pthread_create failed! (%d)\n", errno);
+        exit(0);
+    }
+    
+    aio_listening = 1;
+    
+    blktap_attach_poll(aio_notify[READ], POLLIN, ublkback_pollhook);
+}
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/ublkback/ublkbacklib.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/blktap/ublkback/ublkbacklib.h       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,16 @@
+/* blkaiolib.h
+ *
+ * aio image-backed block device.
+ * 
+ * (c) 2004 Andrew Warfield.
+ *
+ * Xend has been modified to use an amorfs:[fsid] disk tag.
+ * This will show up as device type (maj:240,min:0) = 61440.
+ *
+ * The fsid is placed in the sec_start field of the disk extent.
+ */
+
+int  ublkback_request(blkif_request_t *req, int batch_done);
+int  ublkback_response(blkif_response_t *rsp); /* noop */
+int  ublkback_new_blkif(blkif_t *blkif);
+void ublkback_init(void);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/xenbus.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/blktap/xenbus.c     Fri Sep  9 16:30:54 2005
@@ -0,0 +1,578 @@
+/*
+ * xenbus.c
+ * 
+ * xenbus interface to the blocktap.
+ * 
+ * this handles the top-half of integration with block devices through the
+ * store -- the tap driver negotiates the device channel etc, while the
+ * userland tap clinet needs to sort out the disk parameters etc.
+ * 
+ * A. Warfield 2005 Based primarily on the blkback and xenbus driver code.  
+ * Comments there apply here...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <xs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include "blktaplib.h"
+#include "list.h"
+
+#if 0
+#define DPRINTF(_f, _a...) printf ( _f , ## _a )
+#else
+#define DPRINTF(_f, _a...) ((void)0)
+#endif
+
+/* --- Xenstore / Xenbus helpers ---------------------------------------- */
+/*
+ * These should all be pulled out into the xenstore API.  I'm faulting commands
+ * in from the xenbus interface as i need them.
+ */
+
+
+/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
+int xs_gather(struct xs_handle *xs, const char *dir, ...)
+{
+    va_list ap;
+    const char *name;
+    char *path;
+    int ret = 0;
+    
+    va_start(ap, dir);
+    while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
+        const char *fmt = va_arg(ap, char *);
+        void *result = va_arg(ap, void *);
+        char *p;
+        
+        if (asprintf(&path, "%s/%s", dir, name) == -1)
+        {
+            warn("allocation error in xs_gather!\n");
+            ret = ENOMEM;
+            break;
+        }
+        p = xs_read(xs, path, NULL);
+        free(path);
+        if (p == NULL) {
+            ret = ENOENT;
+            break;
+        }
+        if (fmt) {
+            if (sscanf(p, fmt, result) == 0)
+                ret = EINVAL;
+            free(p);
+        } else
+            *(char **)result = p;
+    }
+    va_end(ap);
+    return ret;
+}
+
+/* Single printf and write: returns -errno or 0. */
+int xs_printf(struct xs_handle *h, const char *dir, const char *node, 
+                  const char *fmt, ...)
+{
+        char *buf, *path;
+        va_list ap;
+        int ret;
+ 
+        va_start(ap, fmt);
+        ret = vasprintf(&buf, fmt, ap);
+        va_end(ap);
+ 
+        asprintf(&path, "%s/%s", dir, node);
+
+        if ((path == NULL) || (buf == NULL))
+            return 0;
+
+        ret = xs_write(h, path, buf, strlen(buf)+1, O_CREAT);
+
+        free(buf);
+        free(path);
+
+        return ret;
+}
+
+
+int xs_exists(struct xs_handle *h, const char *path)
+{
+    char **d;
+    int num;
+
+    d = xs_directory(h, path, &num);
+    if (d == NULL)
+        return 0;
+    free(d);
+    return 1;
+}
+
+
+
+/* This assumes that the domain name we are looking for is unique! */
+char *get_dom_uuid(struct xs_handle *h, const char *name)
+{
+    char **e, *val, *uuid = NULL;
+    int num, i, len;
+    char *path;
+
+    e = xs_directory(h, "/domain", &num);
+
+    i=0;
+    while (i < num) {
+        asprintf(&path, "/domain/%s/name", e[i]);
+        val = xs_read(h, path, &len);
+        free(path);
+        if (val == NULL)
+            continue;
+        if (strcmp(val, name) == 0) {
+            /* match! */
+            asprintf(&path, "/domain/%s/uuid", e[i]);
+            uuid = xs_read(h, path, &len);
+            free(val);
+            free(path);
+            break;
+        }
+        free(val);
+        i++;
+    }
+
+    free(e);
+    return uuid;
+}
+
+static int strsep_len(const char *str, char c, unsigned int len)
+{
+    unsigned int i;
+    
+    for (i = 0; str[i]; i++)
+        if (str[i] == c) {
+            if (len == 0)
+                return i;
+            len--;
+        }
+    return (len == 0) ? i : -ERANGE;
+}
+
+
+/* xenbus watches: */     
+/* Register callback to watch this node. */
+struct xenbus_watch
+{
+        struct list_head list;
+        char *node;
+        void (*callback)(struct xs_handle *h, 
+                         struct xenbus_watch *, 
+                         const  char *node);
+};
+
+static LIST_HEAD(watches);
+
+/* A little paranoia: we don't just trust token. */
+static struct xenbus_watch *find_watch(const char *token)
+{
+    struct xenbus_watch *i, *cmp;
+    
+    cmp = (void *)strtoul(token, NULL, 16);
+    
+    list_for_each_entry(i, &watches, list)
+        if (i == cmp)
+            return i;
+    return NULL;
+}
+
+/* Register callback to watch this node. like xs_watch, return 0 on failure */
+int register_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch)
+{
+    /* Pointer in ascii is the token. */
+    char token[sizeof(watch) * 2 + 1];
+    int er;
+    
+    sprintf(token, "%lX", (long)watch);
+    if (find_watch(token)) 
+    {
+        warn("watch collision!");
+        return -EINVAL;
+    }
+    
+    er = xs_watch(h, watch->node, token);
+    if (er != 0) {
+        list_add(&watch->list, &watches);
+    } 
+        
+    return er;
+}
+
+int unregister_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch)
+{
+    char token[sizeof(watch) * 2 + 1];
+    int er;
+    
+    sprintf(token, "%lX", (long)watch);
+    if (!find_watch(token))
+    {
+        warn("no such watch!");
+        return -EINVAL;
+    }
+    
+    
+    er = xs_unwatch(h, watch->node, token);
+    list_del(&watch->list);
+    
+    if (er == 0)
+        warn("XENBUS Failed to release watch %s: %i",
+             watch->node, er);
+    return 0;
+}
+
+/* Re-register callbacks to all watches. */
+void reregister_xenbus_watches(struct xs_handle *h)
+{
+    struct xenbus_watch *watch;
+    char token[sizeof(watch) * 2 + 1];
+    
+    list_for_each_entry(watch, &watches, list) {
+        sprintf(token, "%lX", (long)watch);
+        xs_watch(h, watch->node, token);
+    }
+}
+
+/* based on watch_thread() */
+int xs_fire_next_watch(struct xs_handle *h)
+{
+    char **res;
+    char *token;
+    char *node = NULL;
+    struct xenbus_watch *w;
+    int er;
+
+    res = xs_read_watch(h);
+    if (res == NULL) 
+        return -EAGAIN; /* in O_NONBLOCK, read_watch returns 0... */
+
+    node  = res[0];
+    token = res[1];
+
+    er = xs_acknowledge_watch(h, token);
+    if (er == 0)
+        warn("Couldn't acknowledge watch (%s)", token);
+
+    w = find_watch(token);
+    if (!w)
+    {
+        warn("unregistered watch fired");
+        goto done;
+    }
+    w->callback(h, w, node);
+
+ done:
+    free(res);
+    return 1;
+}
+
+
+
+
+/* ---------------------------------------------------------------------- */
+
+struct backend_info
+{
+    /* our communications channel */
+    blkif_t *blkif;
+    
+    long int frontend_id;
+    long int pdev;
+    long int readonly;
+    
+    /* watch back end for changes */
+    struct xenbus_watch backend_watch;
+    char *backpath;
+
+    /* watch front end for changes */
+    struct xenbus_watch watch;
+    char *frontpath;
+
+    struct list_head list;
+};
+
+static LIST_HEAD(belist);
+
+static struct backend_info *be_lookup_be(const char *bepath)
+{
+    struct backend_info *be;
+
+    list_for_each_entry(be, &belist, list)
+        if (strcmp(bepath, be->backpath) == 0)
+            return be;
+    return (struct backend_info *)NULL;
+}
+
+static int be_exists_be(const char *bepath)
+{
+    return ( be_lookup_be(bepath) != NULL );
+}
+
+static struct backend_info *be_lookup_fe(const char *fepath)
+{
+    struct backend_info *be;
+
+    list_for_each_entry(be, &belist, list)
+        if (strcmp(fepath, be->frontpath) == 0)
+            return be;
+    return (struct backend_info *)NULL;
+}
+
+static int backend_remove(struct xs_handle *h, struct backend_info *be)
+{
+    /* Turn off watches. */
+    if (be->watch.node)
+        unregister_xenbus_watch(h, &be->watch);
+    if (be->backend_watch.node)
+        unregister_xenbus_watch(h, &be->backend_watch);
+
+    /* Unhook from be list. */
+    list_del(&be->list);
+
+    /* Free everything else. */
+    if (be->blkif)
+        free_blkif(be->blkif);
+    if (be->frontpath)
+        free(be->frontpath);
+    if (be->backpath)
+        free(be->backpath);
+    free(be);
+    return 0;
+}
+
+static void frontend_changed(struct xs_handle *h, struct xenbus_watch *w, 
+                     const char *fepath_im)
+{
+    struct backend_info *be;
+    char *fepath = NULL;
+    int er;
+
+    be = be_lookup_fe(w->node);
+    if (be == NULL)
+    {
+        warn("frontend changed called for nonexistent backend! (%s)", fepath);
+        goto fail;
+    }
+    
+    /* If other end is gone, delete ourself. */
+    if (w->node && !xs_exists(h, be->frontpath)) {
+        DPRINTF("DELETING BE: %s\n", be->backpath);
+        backend_remove(h, be);
+        return;
+    }
+
+    if (be->blkif == NULL || (be->blkif->state == CONNECTED))
+        return;
+
+    /* Supply the information about the device the frontend needs */
+    er = xs_transaction_start(h, be->backpath);
+    if (er == 0) {
+        warn("starting transaction");
+        goto fail;
+    }
+    
+    er = xs_printf(h, be->backpath, "sectors", "%lu",
+                           be->blkif->ops->get_size(be->blkif));
+    if (er == 0) {
+        warn("writing sectors");
+        goto fail;
+    }
+    
+    er = xs_printf(h, be->backpath, "info", "%u",
+                           be->blkif->ops->get_info(be->blkif));
+    if (er == 0) {
+        warn("writing info");
+        goto fail;
+    }
+    
+    er = xs_printf(h, be->backpath, "sector-size", "%lu",
+                           be->blkif->ops->get_secsize(be->blkif));
+    if (er == 0) {
+        warn("writing sector-size");
+        goto fail;
+    }
+
+    be->blkif->state = CONNECTED;
+
+    xs_transaction_end(h, 0);
+
+    return;
+
+ fail:
+    if (fepath)
+        free(fepath);
+}
+
+
+static void backend_changed(struct xs_handle *h, struct xenbus_watch *w, 
+                     const char *bepath_im)
+{
+    struct backend_info *be;
+    char *path = NULL, *p;
+    int len, er;
+    long int pdev = 0, handle;
+
+    be = be_lookup_be(w->node);
+    if (be == NULL)
+    {
+        warn("backend changed called for nonexistent backend! (%s)", w->node);
+        goto fail;
+    }
+    
+    er = xs_gather(h, be->backpath, "physical-device", "%li", &pdev, NULL);
+    if (er != 0) 
+        goto fail;
+
+    if (be->pdev && be->pdev != pdev) {
+        warn("changing physical-device not supported");
+        goto fail;
+    }
+    be->pdev = pdev;
+
+    asprintf(&path, "%s/%s", w->node, "read-only");
+    if (xs_exists(h, path))
+        be->readonly = 1;
+
+    if (be->blkif == NULL) {
+        /* Front end dir is a number, which is used as the handle. */
+        p = strrchr(be->frontpath, '/') + 1;
+        handle = strtoul(p, NULL, 0);
+
+        be->blkif = alloc_blkif(be->frontend_id);
+        if (be->blkif == NULL) 
+            goto fail;
+
+        er = blkif_init(be->blkif, handle, be->pdev, be->readonly);
+        if (er) 
+            goto fail;
+
+        DPRINTF("[BECHG]: ADDED A NEW BLKIF (%s)\n", w->node);
+
+        /* Pass in NULL node to skip exist test. */
+        frontend_changed(h, &be->watch, NULL);
+    }
+
+ fail:
+    if (path)
+        free(path);
+
+}
+
+static void blkback_probe(struct xs_handle *h, struct xenbus_watch *w, 
+                         const char *bepath_im)
+{
+       struct backend_info *be = NULL;
+       char *frontend = NULL, *bepath = NULL;
+       int er, len;
+
+        bepath = strdup(bepath_im);
+        if (!bepath)
+            return;
+        len = strsep_len(bepath, '/', 6);
+        if (len < 0) 
+            goto free_be;
+        
+        bepath[len] = '\0'; /*truncate the passed-in string with predjudice. */
+
+       be = malloc(sizeof(*be));
+       if (!be) {
+               warn("allocating backend structure");
+               goto free_be;
+       }
+       memset(be, 0, sizeof(*be));
+
+       frontend = NULL;
+       er = xs_gather(h, bepath,
+                        "frontend-id", "%li", &be->frontend_id,
+                        "frontend", NULL, &frontend,
+                        NULL);
+       if (er)
+               goto free_be;
+
+       if (strlen(frontend) == 0 || !xs_exists(h, frontend)) {
+            /* If we can't get a frontend path and a frontend-id,
+             * then our bus-id is no longer valid and we need to
+             * destroy the backend device.
+             */
+            DPRINTF("No frontend (%s)\n", frontend);
+            goto free_be;
+       }
+
+        /* Are we already tracking this device? */
+        if (be_exists_be(bepath))
+            goto free_be;
+
+        be->backpath = bepath;
+       be->backend_watch.node = be->backpath;
+       be->backend_watch.callback = backend_changed;
+       er = register_xenbus_watch(h, &be->backend_watch);
+       if (er == 0) {
+               be->backend_watch.node = NULL;
+               warn("error adding backend watch on %s", bepath);
+               goto free_be;
+       }
+
+       be->frontpath = frontend;
+       be->watch.node = be->frontpath;
+       be->watch.callback = frontend_changed;
+       er = register_xenbus_watch(h, &be->watch);
+       if (er == 0) {
+               be->watch.node = NULL;
+               warn("adding frontend watch on %s", be->frontpath);
+               goto free_be;
+       }
+
+        list_add(&be->list, &belist);
+
+        DPRINTF("[PROBE]: ADDED NEW DEVICE (%s)\n", bepath_im);
+
+       backend_changed(h, &be->backend_watch, bepath);
+       return;
+
+ free_be:
+       if ((be) && (be->backend_watch.node))
+            unregister_xenbus_watch(h, &be->backend_watch);
+       if (frontend)
+            free(frontend);
+        if (bepath)
+            free(bepath);
+       free(be);
+       return;
+}
+
+
+int add_blockdevice_probe_watch(struct xs_handle *h, const char *domname)
+{
+    char *uuid, *path;
+    struct xenbus_watch *vbd_watch;
+    int er;
+
+    uuid = get_dom_uuid(h, domname);
+
+    DPRINTF("%s: %s\n", domname, (uuid != NULL) ? uuid : "[ not found! ]");
+
+    asprintf(&path, "/domain/%s/backend/vbd", uuid);
+    if (path == NULL) 
+        return -ENOMEM;
+
+    vbd_watch = (struct xenbus_watch *)malloc(sizeof(struct xenbus_watch));
+    vbd_watch->node     = path;
+    vbd_watch->callback = blkback_probe;
+    er = register_xenbus_watch(h, vbd_watch);
+    if (er == 0) {
+        warn("Error adding vbd probe watch %s", path);
+        return -EINVAL;
+    }
+
+    return 0;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/xen-backend.agent
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/examples/xen-backend.agent  Fri Sep  9 16:30:54 2005
@@ -0,0 +1,25 @@
+#! /bin/sh
+
+#ACTION=add
+#DEVPATH=/devices/xen-backend/vif-1-0
+#PHYSDEVDRIVER=vif
+#XENBUS_TYPE=vif
+
+PATH=/etc/xen/scripts:$PATH
+
+case "$ACTION" in
+  add)
+    ;;
+  remove)
+    ;;
+  online)
+    case "$PHYSDEVDRIVER" in
+      vif)
+        [ -n "$script" ] && $script up
+        ;;
+    esac
+    ;;
+  offline)
+    ;;
+esac
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/hw/pcnet.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/ioemu/hw/pcnet.c    Fri Sep  9 16:30:54 2005
@@ -0,0 +1,1209 @@
+/*
+ * QEMU AMD PC-Net II (Am79C970A) emulation
+ * 
+ * Copyright (c) 2004 Antony T Curtis
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+ 
+/* This software was written to be compatible with the specification:
+ * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet
+ * AMD Publication# 19436  Rev:E  Amendment/0  Issue Date: June 2000
+ */
+ 
+#include "vl.h"
+#include <sys/times.h>
+#include <arpa/inet.h>
+#include <net/ethernet.h>
+
+//#define PCNET_DEBUG
+//#define PCNET_DEBUG_IO
+//#define PCNET_DEBUG_BCR
+//#define PCNET_DEBUG_CSR
+//#define PCNET_DEBUG_RMD
+//#define PCNET_DEBUG_TMD
+//#define PCNET_DEBUG_MATCH
+
+
+#define PCNET_IOPORT_SIZE       0x20
+#define PCNET_PNPMMIO_SIZE      0x20
+
+
+typedef struct PCNetState_st PCNetState;
+
+struct PCNetState_st {
+    PCIDevice dev;
+    NetDriverState *nd;
+    QEMUTimer *poll_timer;
+    int mmio_io_addr, rap, isr, lnkst;
+    target_phys_addr_t rdra, tdra;
+    uint8_t prom[16];
+    uint16_t csr[128];
+    uint16_t bcr[32];
+    uint64_t timer;
+    int xmit_pos, recv_pos;
+    uint8_t buffer[4096];
+};
+
+#include "pcnet.h"
+
+static void pcnet_poll(PCNetState *s);
+static void pcnet_poll_timer(void *opaque);
+
+static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
+static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
+static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
+static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
+
+static void pcnet_s_reset(PCNetState *s)
+{
+#ifdef PCNET_DEBUG
+    printf("pcnet_s_reset\n");
+#endif
+
+    s->lnkst = 0x40;
+    s->rdra = 0;
+    s->tdra = 0;
+    s->rap = 0;
+    
+    s->bcr[BCR_BSBC] &= ~0x0080;
+
+    s->csr[0]   = 0x0004;
+    s->csr[3]   = 0x0000;
+    s->csr[4]   = 0x0115;
+    s->csr[5]   = 0x0000;
+    s->csr[6]   = 0x0000;
+    s->csr[8]   = 0;
+    s->csr[9]   = 0;
+    s->csr[10]  = 0;
+    s->csr[11]  = 0;
+    s->csr[12]  = le16_to_cpu(((uint16_t *)&s->prom[0])[0]);
+    s->csr[13]  = le16_to_cpu(((uint16_t *)&s->prom[0])[1]);
+    s->csr[14]  = le16_to_cpu(((uint16_t *)&s->prom[0])[2]);
+    s->csr[15] &= 0x21c4;
+    s->csr[72]  = 1;
+    s->csr[74]  = 1;
+    s->csr[76]  = 1;
+    s->csr[78]  = 1;
+    s->csr[80]  = 0x1410;
+    s->csr[88]  = 0x1003;
+    s->csr[89]  = 0x0262;
+    s->csr[94]  = 0x0000;
+    s->csr[100] = 0x0200;
+    s->csr[103] = 0x0105;
+    s->csr[103] = 0x0105;
+    s->csr[112] = 0x0000;
+    s->csr[114] = 0x0000;
+    s->csr[122] = 0x0000;
+    s->csr[124] = 0x0000;
+}
+
+static void pcnet_update_irq(PCNetState *s)
+{
+    int isr = 0;
+    s->csr[0] &= ~0x0080;
+    
+#if 1
+    if (((s->csr[0] & ~s->csr[3]) & 0x5f00) ||
+        (((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) ||
+        (((s->csr[5]>>1) & s->csr[5]) & 0x0048))
+#else
+    if ((!(s->csr[3] & 0x4000) && !!(s->csr[0] & 0x4000)) /* BABL */ ||
+        (!(s->csr[3] & 0x1000) && !!(s->csr[0] & 0x1000)) /* MISS */ ||
+        (!(s->csr[3] & 0x0100) && !!(s->csr[0] & 0x0100)) /* IDON */ ||
+        (!(s->csr[3] & 0x0200) && !!(s->csr[0] & 0x0200)) /* TINT */ ||
+        (!(s->csr[3] & 0x0400) && !!(s->csr[0] & 0x0400)) /* RINT */ ||
+        (!(s->csr[3] & 0x0800) && !!(s->csr[0] & 0x0800)) /* MERR */ ||
+        (!(s->csr[4] & 0x0001) && !!(s->csr[4] & 0x0002)) /* JAB */ ||
+        (!(s->csr[4] & 0x0004) && !!(s->csr[4] & 0x0008)) /* TXSTRT */ ||
+        (!(s->csr[4] & 0x0010) && !!(s->csr[4] & 0x0020)) /* RCVO */ ||
+        (!(s->csr[4] & 0x0100) && !!(s->csr[4] & 0x0200)) /* MFCO */ ||
+        (!!(s->csr[5] & 0x0040) && !!(s->csr[5] & 0x0080)) /* EXDINT */ ||
+        (!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */)
+#endif
+    {
+       
+        isr = CSR_INEA(s);
+        s->csr[0] |= 0x0080;
+    }
+    
+    if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */
+        s->csr[4] &= ~0x0080;
+        s->csr[4] |= 0x0040;
+        s->csr[0] |= 0x0080;
+        isr = 1;
+#ifdef PCNET_DEBUG
+        printf("pcnet user int\n");
+#endif
+    }
+
+#if 1
+    if (((s->csr[5]>>1) & s->csr[5]) & 0x0500) 
+#else
+    if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ ||
+        (!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ )
+#endif
+    {
+        isr = 1;
+        s->csr[0] |= 0x0080;
+    }
+
+    if (isr != s->isr) {
+#ifdef PCNET_DEBUG
+        printf("pcnet: INTA=%d\n", isr);
+#endif
+    }
+        pci_set_irq(&s->dev, 0, isr);
+        s->isr = isr;
+}
+
+static void pcnet_init(PCNetState *s)
+{
+#ifdef PCNET_DEBUG
+    printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
+#endif
+    
+#define PCNET_INIT() do { \
+        cpu_physical_memory_read(PHYSADDR(s,CSR_IADR(s)),       \
+                (uint8_t *)&initblk, sizeof(initblk));          \
+        s->csr[15] = le16_to_cpu(initblk.mode);                 \
+        CSR_RCVRL(s) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512;  \
+        CSR_XMTRL(s) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512;  \
+        s->csr[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8);        \
+        s->csr[ 8] = le16_to_cpu(initblk.ladrf1);                       \
+        s->csr[ 9] = le16_to_cpu(initblk.ladrf2);                       \
+        s->csr[10] = le16_to_cpu(initblk.ladrf3);                       \
+        s->csr[11] = le16_to_cpu(initblk.ladrf4);                       \
+        s->csr[12] = le16_to_cpu(initblk.padr1);                        \
+        s->csr[13] = le16_to_cpu(initblk.padr2);                        \
+        s->csr[14] = le16_to_cpu(initblk.padr3);                        \
+        s->rdra = PHYSADDR(s,initblk.rdra);                             \
+        s->tdra = PHYSADDR(s,initblk.tdra);                             \
+} while (0)
+    
+    if (BCR_SSIZE32(s)) {
+        struct pcnet_initblk32 initblk;
+        PCNET_INIT();
+#ifdef PCNET_DEBUG
+        printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
+                initblk.rlen, initblk.tlen);
+#endif
+    } else {
+        struct pcnet_initblk16 initblk;
+        PCNET_INIT();
+#ifdef PCNET_DEBUG
+        printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
+                initblk.rlen, initblk.tlen);
+#endif
+    }
+
+#undef PCNET_INIT
+
+    CSR_RCVRC(s) = CSR_RCVRL(s);
+    CSR_XMTRC(s) = CSR_XMTRL(s);
+
+#ifdef PCNET_DEBUG
+    printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n", 
+        BCR_SSIZE32(s),
+        s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
+#endif
+
+    s->csr[0] |= 0x0101;    
+    s->csr[0] &= ~0x0004;       /* clear STOP bit */
+}
+
+static void pcnet_start(PCNetState *s)
+{
+#ifdef PCNET_DEBUG
+    printf("pcnet_start\n");
+#endif
+
+    if (!CSR_DTX(s))
+        s->csr[0] |= 0x0010;    /* set TXON */
+        
+    if (!CSR_DRX(s))
+        s->csr[0] |= 0x0020;    /* set RXON */
+
+    s->csr[0] &= ~0x0004;       /* clear STOP bit */
+    s->csr[0] |= 0x0002;
+}
+
+static void pcnet_stop(PCNetState *s)
+{
+#ifdef PCNET_DEBUG
+    printf("pcnet_stop\n");
+#endif
+    s->csr[0] &= ~0x7feb;
+    s->csr[0] |= 0x0014;
+    s->csr[4] &= ~0x02c2;
+    s->csr[5] &= ~0x0011;
+    pcnet_poll_timer(s);
+}
+
+static void pcnet_rdte_poll(PCNetState *s)
+{
+    s->csr[28] = s->csr[29] = 0;
+    if (s->rdra) {
+        int bad = 0;
+#if 1
+        target_phys_addr_t crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
+        target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
+        target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
+#else
+        target_phys_addr_t crda = s->rdra + 
+            (CSR_RCVRL(s) - CSR_RCVRC(s)) *
+            (BCR_SWSTYLE(s) ? 16 : 8 );
+        int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;
+        target_phys_addr_t nrda = s->rdra + 
+            (CSR_RCVRL(s) - nrdc) *
+            (BCR_SWSTYLE(s) ? 16 : 8 );
+        int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;
+        target_phys_addr_t nnrd = s->rdra + 
+            (CSR_RCVRL(s) - nnrc) *
+            (BCR_SWSTYLE(s) ? 16 : 8 );
+#endif
+
+        CHECK_RMD(PHYSADDR(s,crda), bad);
+        if (!bad) {
+            CHECK_RMD(PHYSADDR(s,nrda), bad);
+            if (bad || (nrda == crda)) nrda = 0;
+            CHECK_RMD(PHYSADDR(s,nnrd), bad);
+            if (bad || (nnrd == crda)) nnrd = 0;
+
+            s->csr[28] = crda & 0xffff;
+            s->csr[29] = crda >> 16;
+            s->csr[26] = nrda & 0xffff;
+            s->csr[27] = nrda >> 16;
+            s->csr[36] = nnrd & 0xffff;
+            s->csr[37] = nnrd >> 16;
+#ifdef PCNET_DEBUG
+            if (bad) {
+                printf("pcnet: BAD RMD RECORDS AFTER 0x%08x\n",
+                       PHYSADDR(s,crda));
+            }
+        } else {
+            printf("pcnet: BAD RMD RDA=0x%08x\n", PHYSADDR(s,crda));
+#endif
+        }
+    }
+    
+    if (CSR_CRDA(s)) {
+        struct pcnet_RMD rmd;
+        RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
+        CSR_CRBC(s) = rmd.rmd1.bcnt;
+        CSR_CRST(s) = ((uint32_t *)&rmd)[1] >> 16;
+#ifdef PCNET_DEBUG_RMD_X
+        printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMD1=0x%08x RMD2=0x%08x\n",
+                PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
+                ((uint32_t *)&rmd)[1], ((uint32_t *)&rmd)[2]);
+        PRINT_RMD(&rmd);
+#endif
+    } else {
+        CSR_CRBC(s) = CSR_CRST(s) = 0;
+    }
+    
+    if (CSR_NRDA(s)) {
+        struct pcnet_RMD rmd;
+        RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
+        CSR_NRBC(s) = rmd.rmd1.bcnt;
+        CSR_NRST(s) = ((uint32_t *)&rmd)[1] >> 16;
+    } else {
+        CSR_NRBC(s) = CSR_NRST(s) = 0;
+    }
+
+}
+
+static int pcnet_tdte_poll(PCNetState *s)
+{
+    s->csr[34] = s->csr[35] = 0;
+    if (s->tdra) {
+        target_phys_addr_t cxda = s->tdra + 
+            (CSR_XMTRL(s) - CSR_XMTRC(s)) *
+            (BCR_SWSTYLE(s) ? 16 : 8 );
+        int bad = 0;
+        CHECK_TMD(PHYSADDR(s, cxda),bad);
+        if (!bad) {
+            if (CSR_CXDA(s) != cxda) {
+                s->csr[60] = s->csr[34];
+                s->csr[61] = s->csr[35];
+                s->csr[62] = CSR_CXBC(s);
+                s->csr[63] = CSR_CXST(s);
+            }
+            s->csr[34] = cxda & 0xffff;
+            s->csr[35] = cxda >> 16;
+#ifdef PCNET_DEBUG
+        } else {
+            printf("pcnet: BAD TMD XDA=0x%08x\n", PHYSADDR(s,cxda));
+#endif
+        }
+    }
+
+    if (CSR_CXDA(s)) {
+        struct pcnet_TMD tmd;
+
+        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));                
+
+        CSR_CXBC(s) = tmd.tmd1.bcnt;
+        CSR_CXST(s) = ((uint32_t *)&tmd)[1] >> 16;
+    } else {
+        CSR_CXBC(s) = CSR_CXST(s) = 0;
+    }
+    
+    return !!(CSR_CXST(s) & 0x8000);
+}
+
+static int pcnet_can_receive(void *opaque)
+{
+    PCNetState *s = opaque;
+    if (CSR_STOP(s) || CSR_SPND(s))
+        return 0;
+        
+    if (s->recv_pos > 0)
+        return 0;
+
+    return sizeof(s->buffer)-16;
+}
+
+static void pcnet_receive(void *opaque, const uint8_t *buf, int size)
+{
+    PCNetState *s = opaque;
+    int is_padr = 0, is_bcast = 0, is_ladr = 0;
+
+    if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size)
+        return;
+
+#ifdef PCNET_DEBUG
+    printf("pcnet_receive size=%d\n", size);
+#endif
+
+    if (CSR_PROM(s) 
+        || (is_padr=padr_match(s, buf, size)) 
+        || (is_bcast=padr_bcast(s, buf, size))
+        || (is_ladr=ladr_match(s, buf, size))) {
+
+        pcnet_rdte_poll(s);
+
+        if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
+            struct pcnet_RMD rmd;
+            int rcvrc = CSR_RCVRC(s)-1,i;
+            target_phys_addr_t nrda;
+            for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
+                if (rcvrc <= 1)
+                    rcvrc = CSR_RCVRL(s);
+                nrda = s->rdra +
+                    (CSR_RCVRL(s) - rcvrc) *
+                    (BCR_SWSTYLE(s) ? 16 : 8 );
+                RMDLOAD(&rmd, PHYSADDR(s,nrda));                  
+                if (rmd.rmd1.own) {                
+#ifdef PCNET_DEBUG_RMD
+                    printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n", 
+                                rcvrc, CSR_RCVRC(s));
+#endif
+                    CSR_RCVRC(s) = rcvrc;
+                    pcnet_rdte_poll(s);
+                    break;
+                }
+            }
+        }
+
+        if (!(CSR_CRST(s) & 0x8000)) {
+#ifdef PCNET_DEBUG_RMD
+            printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
+#endif
+            s->csr[0] |= 0x1000; /* Set MISS flag */
+            CSR_MISSC(s)++;
+        } else {
+            uint8_t *src = &s->buffer[8];
+            target_phys_addr_t crda = CSR_CRDA(s);
+            struct pcnet_RMD rmd;
+            int pktcount = 0;
+
+            memcpy(src, buf, size);
+            
+            if (!CSR_ASTRP_RCV(s)) {
+                uint32_t fcs = ~0;
+#if 0            
+                uint8_t *p = s->buffer;
+                
+                ((uint32_t *)p)[0] = ((uint32_t *)p)[1] = 0xaaaaaaaa;
+                p[7] = 0xab;
+#else
+                uint8_t *p = src;
+#endif
+
+                while (size < 46) {
+                    src[size++] = 0;
+                }
+                
+                while (p != &src[size]) {
+                    CRC(fcs, *p++);
+                }
+                ((uint32_t *)&src[size])[0] = htonl(fcs);
+                size += 4; /* FCS at end of packet */
+            } else size += 4;
+
+#ifdef PCNET_DEBUG_MATCH
+            PRINT_PKTHDR(buf);
+#endif
+
+            RMDLOAD(&rmd, PHYSADDR(s,crda));
+            /*if (!CSR_LAPPEN(s))*/
+                rmd.rmd1.stp = 1;
+
+#define PCNET_RECV_STORE() do {                                 \
+    int count = MIN(4096 - rmd.rmd1.bcnt,size);                 \
+    target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr);     \
+    cpu_physical_memory_write(rbadr, src, count);               \
+    cpu_physical_memory_set_dirty(rbadr);                       \
+    cpu_physical_memory_set_dirty(rbadr+count);                 \
+    src += count; size -= count;                                \
+    rmd.rmd2.mcnt = count; rmd.rmd1.own = 0;                    \
+    RMDSTORE(&rmd, PHYSADDR(s,crda));                           \
+    pktcount++;                                                 \
+} while (0)
+
+            PCNET_RECV_STORE();
+            if ((size > 0) && CSR_NRDA(s)) {
+                target_phys_addr_t nrda = CSR_NRDA(s);
+                RMDLOAD(&rmd, PHYSADDR(s,nrda));
+                if (rmd.rmd1.own) {
+                    crda = nrda;
+                    PCNET_RECV_STORE();
+                    if ((size > 0) && (nrda=CSR_NNRD(s))) {
+                        RMDLOAD(&rmd, PHYSADDR(s,nrda));
+                        if (rmd.rmd1.own) {
+                            crda = nrda;
+                            PCNET_RECV_STORE();
+                        }
+                    }
+                }                
+            }
+
+#undef PCNET_RECV_STORE
+
+            RMDLOAD(&rmd, PHYSADDR(s,crda));
+            if (size == 0) {
+                rmd.rmd1.enp = 1;
+                rmd.rmd1.pam = !CSR_PROM(s) && is_padr;
+                rmd.rmd1.lafm = !CSR_PROM(s) && is_ladr;
+                rmd.rmd1.bam = !CSR_PROM(s) && is_bcast;
+            } else {
+                rmd.rmd1.oflo = 1;
+                rmd.rmd1.buff = 1;
+                rmd.rmd1.err = 1;
+            }
+            RMDSTORE(&rmd, PHYSADDR(s,crda));
+            s->csr[0] |= 0x0400;
+
+#ifdef PCNET_DEBUG
+            printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n", 
+                CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
+#endif
+#ifdef PCNET_DEBUG_RMD
+            PRINT_RMD(&rmd);
+#endif        
+
+            while (pktcount--) {
+                if (CSR_RCVRC(s) <= 1)
+                    CSR_RCVRC(s) = CSR_RCVRL(s);
+                else
+                    CSR_RCVRC(s)--;            
+            }
+            
+            pcnet_rdte_poll(s);
+
+        }        
+    }
+
+    pcnet_poll(s);
+    pcnet_update_irq(s);    
+}
+
+static void pcnet_transmit(PCNetState *s)
+{
+    target_phys_addr_t xmit_cxda = 0;
+    int count = CSR_XMTRL(s)-1;
+    s->xmit_pos = -1;
+    
+    if (!CSR_TXON(s)) {
+        s->csr[0] &= ~0x0008;
+        return;
+    }
+    
+    txagain:
+    if (pcnet_tdte_poll(s)) {
+        struct pcnet_TMD tmd;
+
+        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));                
+
+#ifdef PCNET_DEBUG_TMD
+        printf("  TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
+        PRINT_TMD(&tmd);
+#endif
+        if (tmd.tmd1.stp) {
+            s->xmit_pos = 0;                
+            if (!tmd.tmd1.enp) {
+                cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
+                        s->buffer, 4096 - tmd.tmd1.bcnt);
+                s->xmit_pos += 4096 - tmd.tmd1.bcnt;
+            } 
+            xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
+        }
+        if (tmd.tmd1.enp && (s->xmit_pos >= 0)) {
+            cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
+                    s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt);
+            s->xmit_pos += 4096 - tmd.tmd1.bcnt;
+
+           tmd.tmd1.own = 0;
+           TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
+
+#ifdef PCNET_DEBUG
+            printf("pcnet_transmit size=%d\n", s->xmit_pos);
+#endif            
+            if (CSR_LOOP(s))
+                pcnet_receive(s, s->buffer, s->xmit_pos);
+            else
+                qemu_send_packet(s->nd, s->buffer, s->xmit_pos);
+
+            s->csr[0] &= ~0x0008;   /* clear TDMD */
+            s->csr[4] |= 0x0004;    /* set TXSTRT */
+            s->xmit_pos = -1;
+        } else {
+           tmd.tmd1.own = 0;
+           TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
+       }
+        if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && tmd.tmd1.ltint))
+            s->csr[0] |= 0x0200;    /* set TINT */
+
+        if (CSR_XMTRC(s)<=1)
+            CSR_XMTRC(s) = CSR_XMTRL(s);
+        else
+            CSR_XMTRC(s)--;
+        if (count--)
+            goto txagain;
+
+    } else 
+    if (s->xmit_pos >= 0) {
+        struct pcnet_TMD tmd;
+        TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda));                
+        tmd.tmd2.buff = tmd.tmd2.uflo = tmd.tmd1.err = 1;
+        tmd.tmd1.own = 0;
+        TMDSTORE(&tmd, PHYSADDR(s,xmit_cxda));
+        s->csr[0] |= 0x0200;    /* set TINT */
+        if (!CSR_DXSUFLO(s)) {
+            s->csr[0] &= ~0x0010;
+        } else
+        if (count--)
+          goto txagain;
+    }
+}
+
+static void pcnet_poll(PCNetState *s)
+{
+    if (CSR_RXON(s)) {
+        pcnet_rdte_poll(s);
+    }
+
+    if (CSR_TDMD(s) || 
+        (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s)))
+        pcnet_transmit(s);
+}
+
+static void pcnet_poll_timer(void *opaque)
+{
+    PCNetState *s = opaque;
+
+    qemu_del_timer(s->poll_timer);
+
+    if (CSR_TDMD(s)) {
+        pcnet_transmit(s);
+    }
+
+    pcnet_update_irq(s);    
+
+    if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
+        uint64_t now = qemu_get_clock(vm_clock) * 33;
+        if (!s->timer || !now)
+            s->timer = now;
+        else {
+            uint64_t t = now - s->timer + CSR_POLL(s);
+            if (t > 0xffffLL) {
+                pcnet_poll(s);
+                CSR_POLL(s) = CSR_PINT(s);
+            } else
+                CSR_POLL(s) = t;
+        }
+        qemu_mod_timer(s->poll_timer, 
+            pcnet_get_next_poll_time(s,qemu_get_clock(vm_clock)));
+    }
+}
+
+
+static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
+{
+    uint16_t val = new_value;
+#ifdef PCNET_DEBUG_CSR
+    printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
+#endif
+    switch (rap) {
+    case 0:
+        s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
+
+        s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048);
+
+        val = (val & 0x007f) | (s->csr[0] & 0x7f00);
+
+        /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
+        if ((val&7) == 7)
+          val &= ~3;
+
+        if (!CSR_STOP(s) && (val & 4))
+            pcnet_stop(s);
+
+        if (!CSR_INIT(s) && (val & 1))
+            pcnet_init(s);
+
+        if (!CSR_STRT(s) && (val & 2))
+            pcnet_start(s);
+
+        if (CSR_TDMD(s)) 
+            pcnet_transmit(s);
+
+        return;
+    case 1:
+    case 2:
+    case 8:
+    case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 18: /* CRBAL */
+    case 19: /* CRBAU */
+    case 20: /* CXBAL */
+    case 21: /* CXBAU */
+    case 22: /* NRBAU */
+    case 23: /* NRBAU */
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 39:
+    case 40: /* CRBC */
+    case 41:
+    case 42: /* CXBC */
+    case 43:
+    case 44:
+    case 45:
+    case 46: /* POLL */
+    case 47: /* POLLINT */
+    case 72:
+    case 74:
+    case 76: /* RCVRL */
+    case 78: /* XMTRL */
+    case 112:
+       if (CSR_STOP(s) || CSR_SPND(s))
+           break;
+       return;
+    case 3:
+        break;
+    case 4:
+        s->csr[4] &= ~(val & 0x026a); 
+        val &= ~0x026a; val |= s->csr[4] & 0x026a;
+        break;
+    case 5:
+        s->csr[5] &= ~(val & 0x0a90); 
+        val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
+        break;
+    case 16:
+        pcnet_csr_writew(s,1,val);
+        return;
+    case 17:
+        pcnet_csr_writew(s,2,val);
+        return;
+    case 58:
+        pcnet_bcr_writew(s,BCR_SWS,val);
+        break;
+    default:
+        return;
+    }
+    s->csr[rap] = val;
+}
+
+static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
+{
+    uint32_t val;
+    switch (rap) {
+    case 0:
+        pcnet_update_irq(s);
+        val = s->csr[0];
+        val |= (val & 0x7800) ? 0x8000 : 0;
+        break;
+    case 16:
+        return pcnet_csr_readw(s,1);
+    case 17:
+        return pcnet_csr_readw(s,2);
+    case 58:
+        return pcnet_bcr_readw(s,BCR_SWS);
+    case 88:
+        val = s->csr[89];
+        val <<= 16;
+        val |= s->csr[88];
+        break;
+    default:
+        val = s->csr[rap];
+    }
+#ifdef PCNET_DEBUG_CSR
+    printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
+#endif
+    return val;
+}
+
+static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
+{
+    rap &= 127;
+#ifdef PCNET_DEBUG_BCR
+    printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
+#endif
+    switch (rap) {
+    case BCR_SWS:
+        if (!(CSR_STOP(s) || CSR_SPND(s)))
+            return;
+        val &= ~0x0300;
+        switch (val & 0x00ff) {
+        case 0:
+            val |= 0x0200;
+            break;
+        case 1:
+            val |= 0x0100;
+            break;
+        case 2:
+        case 3:
+            val |= 0x0300;
+            break;
+        default:
+            printf("Bad SWSTYLE=0x%02x\n", val & 0xff);
+            val = 0x0200;
+            break;
+        }
+#ifdef PCNET_DEBUG
+       printf("BCR_SWS=0x%04x\n", val);
+#endif
+    case BCR_LNKST:
+    case BCR_LED1:
+    case BCR_LED2:
+    case BCR_LED3:
+    case BCR_MC:
+    case BCR_FDC:
+    case BCR_BSBC:
+    case BCR_EECAS:
+    case BCR_PLAT:
+        s->bcr[rap] = val;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
+{
+    uint32_t val;
+    rap &= 127;
+    switch (rap) {
+    case BCR_LNKST:
+    case BCR_LED1:
+    case BCR_LED2:
+    case BCR_LED3:
+        val = s->bcr[rap] & ~0x8000;
+        val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
+        break;
+    default:
+        val = rap < 32 ? s->bcr[rap] : 0;
+        break;
+    }
+#ifdef PCNET_DEBUG_BCR
+    printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
+#endif
+    return val;
+}
+
+static void pcnet_h_reset(PCNetState *s)
+{
+    int i;
+    uint16_t checksum;
+
+    /* Initialize the PROM */
+
+    memcpy(s->prom, s->nd->macaddr, 6);
+    s->prom[12] = s->prom[13] = 0x00;
+    s->prom[14] = s->prom[15] = 0x57;
+
+    for (i = 0,checksum = 0; i < 16; i++)
+        checksum += s->prom[i];
+    *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
+
+
+    s->bcr[BCR_MSRDA] = 0x0005;
+    s->bcr[BCR_MSWRA] = 0x0005;
+    s->bcr[BCR_MC   ] = 0x0002;
+    s->bcr[BCR_LNKST] = 0x00c0;
+    s->bcr[BCR_LED1 ] = 0x0084;
+    s->bcr[BCR_LED2 ] = 0x0088;
+    s->bcr[BCR_LED3 ] = 0x0090;
+    s->bcr[BCR_FDC  ] = 0x0000;
+    s->bcr[BCR_BSBC ] = 0x9001;
+    s->bcr[BCR_EECAS] = 0x0002;
+    s->bcr[BCR_SWS  ] = 0x0200;
+    s->bcr[BCR_PLAT ] = 0xff06;
+
+    pcnet_s_reset(s);
+}
+
+static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    PCNetState *s = opaque;
+#ifdef PCNET_DEBUG
+    printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
+#endif    
+    /* Check APROMWE bit to enable write access */
+    if (pcnet_bcr_readw(s,2) & 0x80)
+        s->prom[addr & 15] = val;
+}       
+
+static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
+{
+    PCNetState *s = opaque;
+    uint32_t val = s->prom[addr &= 15];
+#ifdef PCNET_DEBUG
+    printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
+#endif
+    return val;
+}
+
+static void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+    PCNetState *s = opaque;
+    pcnet_poll_timer(s);
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
+#endif
+    if (!BCR_DWIO(s)) {
+        switch (addr & 0x0f) {
+        case 0x00: /* RDP */
+            pcnet_csr_writew(s, s->rap, val);
+            break;
+        case 0x02:
+            s->rap = val & 0x7f;
+            break;
+        case 0x06:
+            pcnet_bcr_writew(s, s->rap, val);
+            break;
+        }
+    }
+    pcnet_update_irq(s);
+}
+
+static uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
+{
+    PCNetState *s = opaque;
+    uint32_t val = -1;
+    pcnet_poll_timer(s);
+    if (!BCR_DWIO(s)) {
+        switch (addr & 0x0f) {
+        case 0x00: /* RDP */
+            val = pcnet_csr_readw(s, s->rap);
+            break;
+        case 0x02:
+            val = s->rap;
+            break;
+        case 0x04:
+            pcnet_s_reset(s);
+            val = 0;
+            break;
+        case 0x06:
+            val = pcnet_bcr_readw(s, s->rap);
+            break;
+        }
+    }
+    pcnet_update_irq(s);
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
+#endif
+    return val;
+}
+
+static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+    PCNetState *s = opaque;
+    pcnet_poll_timer(s);
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
+#endif
+    if (BCR_DWIO(s)) {
+        switch (addr & 0x0f) {
+        case 0x00: /* RDP */
+            pcnet_csr_writew(s, s->rap, val & 0xffff);
+            break;
+        case 0x04:
+            s->rap = val & 0x7f;
+            break;
+        case 0x0c:
+            pcnet_bcr_writew(s, s->rap, val & 0xffff);
+            break;
+        }
+    } else
+    if ((addr & 0x0f) == 0) {
+        /* switch device to dword i/o mode */
+        pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
+#ifdef PCNET_DEBUG_IO
+        printf("device switched into dword i/o mode\n");
+#endif        
+    }
+    pcnet_update_irq(s);
+}
+
+static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
+{
+    PCNetState *s = opaque;
+    uint32_t val = -1;
+    pcnet_poll_timer(s);
+    if (BCR_DWIO(s)) {  
+        switch (addr & 0x0f) {
+        case 0x00: /* RDP */
+            val = pcnet_csr_readw(s, s->rap);
+            break;
+        case 0x04:
+            val = s->rap;
+            break;
+        case 0x08:
+            pcnet_s_reset(s);
+            val = 0;
+            break;
+        case 0x0c:
+            val = pcnet_bcr_readw(s, s->rap);
+            break;
+        }
+    }
+    pcnet_update_irq(s);
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
+#endif
+    return val;
+}
+
+static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num, 
+                             uint32_t addr, uint32_t size, int type)
+{
+    PCNetState *d = (PCNetState *)pci_dev;
+
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size);
+#endif
+
+    register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
+    register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
+    
+    register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
+    register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
+    register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
+    register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
+}
+
+static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t 
val)
+{
+    PCNetState *d = opaque;
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_mmio_writeb addr=0x%08x val=0x%02x\n", addr, val);
+#endif
+    if (!(addr & 0x10))
+        pcnet_aprom_writeb(d, addr & 0x0f, val);
+}
+
+static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr) 
+{
+    PCNetState *d = opaque;
+    uint32_t val = -1;
+    if (!(addr & 0x10))
+        val = pcnet_aprom_readb(d, addr & 0x0f);
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_mmio_readb addr=0x%08x val=0x%02x\n", addr, val & 0xff);
+#endif
+    return val;
+}
+
+static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t 
val)
+{
+    PCNetState *d = opaque;
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_mmio_writew addr=0x%08x val=0x%04x\n", addr, val);
+#endif
+    if (addr & 0x10)
+        pcnet_ioport_writew(d, addr & 0x0f, val);
+    else {
+        addr &= 0x0f;
+        pcnet_aprom_writeb(d, addr, val & 0xff);
+        pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
+    }
+}
+
+static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr) 
+{
+    PCNetState *d = opaque;
+    uint32_t val = -1;
+    if (addr & 0x10)
+        val = pcnet_ioport_readw(d, addr & 0x0f);
+    else {
+        addr &= 0x0f;
+        val = pcnet_aprom_readb(d, addr+1);
+        val <<= 8;
+        val |= pcnet_aprom_readb(d, addr);
+    }
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_mmio_readw addr=0x%08x val = 0x%04x\n", addr, val & 0xffff);
+#endif
+    return val;
+}
+
+static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t 
val)
+{
+    PCNetState *d = opaque;
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_mmio_writel addr=0x%08x val=0x%08x\n", addr, val);
+#endif
+    if (addr & 0x10)
+        pcnet_ioport_writel(d, addr & 0x0f, val);
+    else {
+        addr &= 0x0f;
+        pcnet_aprom_writeb(d, addr, val & 0xff);
+        pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
+        pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
+        pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
+    }
+}
+
+static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr) 
+{
+    PCNetState *d = opaque;
+    uint32_t val;
+    if (addr & 0x10)
+        val = pcnet_ioport_readl(d, addr & 0x0f);
+    else {
+        addr &= 0x0f;
+        val = pcnet_aprom_readb(d, addr+3);
+        val <<= 8;
+        val |= pcnet_aprom_readb(d, addr+2);
+        val <<= 8;
+        val |= pcnet_aprom_readb(d, addr+1);
+        val <<= 8;
+        val |= pcnet_aprom_readb(d, addr);
+    }
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_mmio_readl addr=0x%08x val=0x%08x\n", addr, val);
+#endif
+    return val;
+}
+
+
+static CPUWriteMemoryFunc *pcnet_mmio_write[] = {
+    (CPUWriteMemoryFunc *)&pcnet_mmio_writeb,
+    (CPUWriteMemoryFunc *)&pcnet_mmio_writew,
+    (CPUWriteMemoryFunc *)&pcnet_mmio_writel
+};
+
+static CPUReadMemoryFunc *pcnet_mmio_read[] = {
+    (CPUReadMemoryFunc *)&pcnet_mmio_readb,
+    (CPUReadMemoryFunc *)&pcnet_mmio_readw,
+    (CPUReadMemoryFunc *)&pcnet_mmio_readl
+};
+
+static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num, 
+                            uint32_t addr, uint32_t size, int type)
+{
+    PCNetState *d = (PCNetState *)pci_dev;
+
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size);
+#endif
+
+    cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_io_addr);
+}
+
+void pci_pcnet_init(PCIBus *bus, NetDriverState *nd)
+{
+    PCNetState *d;
+    uint8_t *pci_conf;
+
+#if 0
+    printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n", 
+        sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));
+#endif
+
+    d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState),
+                                          -1, NULL, NULL);
+                                          
+    pci_conf = d->dev.config;
+    
+    *(uint16_t *)&pci_conf[0x00] = cpu_to_le16(0x1022);
+    *(uint16_t *)&pci_conf[0x02] = cpu_to_le16(0x2000);    
+    *(uint16_t *)&pci_conf[0x04] = cpu_to_le16(0x0007); 
+    *(uint16_t *)&pci_conf[0x06] = cpu_to_le16(0x0280);
+    pci_conf[0x08] = 0x10;
+    pci_conf[0x09] = 0x00;
+    pci_conf[0x0a] = 0x00; // ethernet network controller 
+    pci_conf[0x0b] = 0x02;
+    pci_conf[0x0e] = 0x00; // header_type
+    
+    *(uint32_t *)&pci_conf[0x10] = cpu_to_le32(0x00000001);
+    *(uint32_t *)&pci_conf[0x14] = cpu_to_le32(0x00000000);
+    
+    pci_conf[0x3d] = 1; // interrupt pin 0
+    pci_conf[0x3e] = 0x06;
+    pci_conf[0x3f] = 0xff;
+
+    /* Handler for memory-mapped I/O */
+    d->mmio_io_addr =
+      cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d);
+
+    pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE, 
+                           PCI_ADDRESS_SPACE_IO, pcnet_ioport_map);
+                           
+    pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE, 
+                           PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
+                           
+    d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
+
+    d->nd = nd;
+
+    pcnet_h_reset(d);
+
+    qemu_add_read_packet(nd, pcnet_can_receive, pcnet_receive, d);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/hw/pcnet.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/ioemu/hw/pcnet.h    Fri Sep  9 16:30:54 2005
@@ -0,0 +1,583 @@
+/*
+ * QEMU AMD PC-Net II (Am79C970A) emulation
+ * 
+ * Copyright (c) 2004 Antony T Curtis
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* This software was written to be compatible with the specification:
+ * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet
+ * AMD Publication# 19436  Rev:E  Amendment/0  Issue Date: June 2000
+ */
+
+#ifdef __GNUC__
+#define PACKED(A) A __attribute__ ((packed))
+#else
+#error FixMe
+#endif
+
+/* BUS CONFIGURATION REGISTERS */
+#define BCR_MSRDA    0
+#define BCR_MSWRA    1
+#define BCR_MC       2
+#define BCR_LNKST    4
+#define BCR_LED1     5
+#define BCR_LED2     6
+#define BCR_LED3     7
+#define BCR_FDC      9
+#define BCR_BSBC     18
+#define BCR_EECAS    19
+#define BCR_SWS      20
+#define BCR_PLAT     22
+
+#define BCR_DWIO(S)      !!((S)->bcr[BCR_BSBC] & 0x0080)
+#define BCR_SSIZE32(S)   !!((S)->bcr[BCR_SWS ] & 0x0100)
+#define BCR_SWSTYLE(S)     ((S)->bcr[BCR_SWS ] & 0x00FF)
+
+#define CSR_INIT(S)      !!(((S)->csr[0])&0x0001)
+#define CSR_STRT(S)      !!(((S)->csr[0])&0x0002)
+#define CSR_STOP(S)      !!(((S)->csr[0])&0x0004)
+#define CSR_TDMD(S)      !!(((S)->csr[0])&0x0008)
+#define CSR_TXON(S)      !!(((S)->csr[0])&0x0010)
+#define CSR_RXON(S)      !!(((S)->csr[0])&0x0020)
+#define CSR_INEA(S)      !!(((S)->csr[0])&0x0040)
+#define CSR_LAPPEN(S)    !!(((S)->csr[3])&0x0020)
+#define CSR_DXSUFLO(S)   !!(((S)->csr[3])&0x0040)
+#define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
+#define CSR_DPOLL(S)     !!(((S)->csr[4])&0x1000)
+#define CSR_SPND(S)      !!(((S)->csr[5])&0x0001)
+#define CSR_LTINTEN(S)   !!(((S)->csr[5])&0x4000)
+#define CSR_TOKINTD(S)   !!(((S)->csr[5])&0x8000)
+#define CSR_DRX(S)       !!(((S)->csr[15])&0x0001)
+#define CSR_DTX(S)       !!(((S)->csr[15])&0x0002)
+#define CSR_LOOP(S)      !!(((S)->csr[15])&0x0004)
+#define CSR_DRCVPA(S)    !!(((S)->csr[15])&0x2000)
+#define CSR_DRCVBC(S)    !!(((S)->csr[15])&0x4000)
+#define CSR_PROM(S)      !!(((S)->csr[15])&0x8000)
+
+#define CSR_CRBC(S)      ((S)->csr[40])
+#define CSR_CRST(S)      ((S)->csr[41])
+#define CSR_CXBC(S)      ((S)->csr[42])
+#define CSR_CXST(S)      ((S)->csr[43])
+#define CSR_NRBC(S)      ((S)->csr[44])
+#define CSR_NRST(S)      ((S)->csr[45])
+#define CSR_POLL(S)      ((S)->csr[46])
+#define CSR_PINT(S)      ((S)->csr[47])
+#define CSR_RCVRC(S)     ((S)->csr[72])
+#define CSR_XMTRC(S)     ((S)->csr[74])
+#define CSR_RCVRL(S)     ((S)->csr[76])
+#define CSR_XMTRL(S)     ((S)->csr[78])
+#define CSR_MISSC(S)     ((S)->csr[112])
+
+#define CSR_IADR(S)      ((S)->csr[ 1] | ((S)->csr[ 2] << 16))
+#define CSR_CRBA(S)      ((S)->csr[18] | ((S)->csr[19] << 16))
+#define CSR_CXBA(S)      ((S)->csr[20] | ((S)->csr[21] << 16))
+#define CSR_NRBA(S)      ((S)->csr[22] | ((S)->csr[23] << 16))
+#define CSR_BADR(S)      ((S)->csr[24] | ((S)->csr[25] << 16))
+#define CSR_NRDA(S)      ((S)->csr[26] | ((S)->csr[27] << 16))
+#define CSR_CRDA(S)      ((S)->csr[28] | ((S)->csr[29] << 16))
+#define CSR_BADX(S)      ((S)->csr[30] | ((S)->csr[31] << 16))
+#define CSR_NXDA(S)      ((S)->csr[32] | ((S)->csr[33] << 16))
+#define CSR_CXDA(S)      ((S)->csr[34] | ((S)->csr[35] << 16))
+#define CSR_NNRD(S)      ((S)->csr[36] | ((S)->csr[37] << 16))
+#define CSR_NNXD(S)      ((S)->csr[38] | ((S)->csr[39] << 16))
+#define CSR_PXDA(S)      ((S)->csr[60] | ((S)->csr[61] << 16))
+#define CSR_NXBA(S)      ((S)->csr[64] | ((S)->csr[65] << 16))
+
+#define PHYSADDR(S,A) \
+  (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(s)->csr[2])<<16))
+
+struct pcnet_initblk16 {
+    uint16_t mode;
+    uint16_t padr1;
+    uint16_t padr2;
+    uint16_t padr3;
+    uint16_t ladrf1;
+    uint16_t ladrf2;
+    uint16_t ladrf3;
+    uint16_t ladrf4;
+    unsigned PACKED(rdra:24);
+    unsigned PACKED(res1:5);
+    unsigned PACKED(rlen:3);
+    unsigned PACKED(tdra:24);
+    unsigned PACKED(res2:5);
+    unsigned PACKED(tlen:3);
+};
+
+struct pcnet_initblk32 {
+    uint16_t mode;
+    unsigned PACKED(res1:4);
+    unsigned PACKED(rlen:4);
+    unsigned PACKED(res2:4);
+    unsigned PACKED(tlen:4);
+    uint16_t padr1;
+    uint16_t padr2;
+    uint16_t padr3;
+    uint16_t _res;
+    uint16_t ladrf1;
+    uint16_t ladrf2;
+    uint16_t ladrf3;
+    uint16_t ladrf4;
+    uint32_t rdra;
+    uint32_t tdra;
+};
+
+struct pcnet_TMD {
+    struct {
+        unsigned tbadr:32;
+    } tmd0;
+    struct {
+        unsigned PACKED(bcnt:12), PACKED(ones:4), PACKED(res:7), PACKED(bpe:1);
+        unsigned PACKED(enp:1), PACKED(stp:1), PACKED(def:1), PACKED(one:1);
+        unsigned PACKED(ltint:1), PACKED(nofcs:1), PACKED(err:1), 
PACKED(own:1);
+    } tmd1;
+    struct {
+        unsigned PACKED(trc:4), PACKED(res:12);
+        unsigned PACKED(tdr:10), PACKED(rtry:1), PACKED(lcar:1);
+        unsigned PACKED(lcol:1), PACKED(exdef:1), PACKED(uflo:1), 
PACKED(buff:1);
+    } tmd2;
+    struct {
+        unsigned res:32;
+    } tmd3;    
+};
+
+struct pcnet_RMD {
+    struct {
+        unsigned rbadr:32;
+    } rmd0;
+    struct {
+        unsigned PACKED(bcnt:12), PACKED(ones:4), PACKED(res:4);
+        unsigned PACKED(bam:1), PACKED(lafm:1), PACKED(pam:1), PACKED(bpe:1);
+        unsigned PACKED(enp:1), PACKED(stp:1), PACKED(buff:1), PACKED(crc:1);
+        unsigned PACKED(oflo:1), PACKED(fram:1), PACKED(err:1), PACKED(own:1);
+    } rmd1;
+    struct {
+        unsigned PACKED(mcnt:12), PACKED(zeros:4);
+        unsigned PACKED(rpc:8), PACKED(rcc:8);
+    } rmd2;    
+    struct {
+        unsigned res:32;
+    } rmd3;    
+};
+
+
+#define PRINT_TMD(T) printf(    \
+        "TMD0 : TBADR=0x%08x\n" \
+        "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, "       \
+        "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n"             \
+        "       BPE=%d, BCNT=%d\n"                      \
+        "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, "       \
+        "LCA=%d, RTR=%d,\n"                             \
+        "       TDR=%d, TRC=%d\n",                      \
+        (T)->tmd0.tbadr,                                \
+        (T)->tmd1.own, (T)->tmd1.err, (T)->tmd1.nofcs,  \
+        (T)->tmd1.ltint, (T)->tmd1.one, (T)->tmd1.def,  \
+        (T)->tmd1.stp, (T)->tmd1.enp, (T)->tmd1.bpe,    \
+        4096-(T)->tmd1.bcnt,                            \
+        (T)->tmd2.buff, (T)->tmd2.uflo, (T)->tmd2.exdef,\
+        (T)->tmd2.lcol, (T)->tmd2.lcar, (T)->tmd2.rtry, \
+        (T)->tmd2.tdr, (T)->tmd2.trc)
+
+#define PRINT_RMD(R) printf(    \
+        "RMD0 : RBADR=0x%08x\n" \
+        "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, "     \
+        "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n       "     \
+        "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n"    \
+        "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n",   \
+        (R)->rmd0.rbadr,                                \
+        (R)->rmd1.own, (R)->rmd1.err, (R)->rmd1.fram,   \
+        (R)->rmd1.oflo, (R)->rmd1.crc, (R)->rmd1.buff,  \
+        (R)->rmd1.stp, (R)->rmd1.enp, (R)->rmd1.bpe,    \
+        (R)->rmd1.pam, (R)->rmd1.lafm, (R)->rmd1.bam,   \
+        (R)->rmd1.ones, 4096-(R)->rmd1.bcnt,            \
+        (R)->rmd2.rcc, (R)->rmd2.rpc, (R)->rmd2.mcnt,   \
+        (R)->rmd2.zeros)
+
+static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd, 
target_phys_addr_t addr)
+{
+    if (!BCR_SWSTYLE(s)) {
+        uint16_t xda[4];
+        cpu_physical_memory_read(addr,
+                (void *)&xda[0], sizeof(xda));
+        ((uint32_t *)tmd)[0] = (xda[0]&0xffff) |
+                ((xda[1]&0x00ff) << 16);
+        ((uint32_t *)tmd)[1] = (xda[2]&0xffff)|
+                ((xda[1] & 0xff00) << 16);
+        ((uint32_t *)tmd)[2] =
+                (xda[3] & 0xffff) << 16;
+        ((uint32_t *)tmd)[3] = 0;
+    }
+    else
+    if (BCR_SWSTYLE(s) != 3)
+        cpu_physical_memory_read(addr, (void *)tmd, 16);
+    else {
+        uint32_t xda[4];
+        cpu_physical_memory_read(addr,
+                (void *)&xda[0], sizeof(xda));
+        ((uint32_t *)tmd)[0] = xda[2];
+        ((uint32_t *)tmd)[1] = xda[1];
+        ((uint32_t *)tmd)[2] = xda[0];
+        ((uint32_t *)tmd)[3] = xda[3];
+    }
+}
+
+static inline void pcnet_tmd_store(PCNetState *s, struct pcnet_TMD *tmd, 
target_phys_addr_t addr)
+{
+    cpu_physical_memory_set_dirty(addr);
+    if (!BCR_SWSTYLE(s)) {
+        uint16_t xda[4];
+        xda[0] = ((uint32_t *)tmd)[0] & 0xffff;
+        xda[1] = ((((uint32_t *)tmd)[0]>>16)&0x00ff) |
+            ((((uint32_t *)tmd)[1]>>16)&0xff00);
+        xda[2] = ((uint32_t *)tmd)[1] & 0xffff;
+        xda[3] = ((uint32_t *)tmd)[2] >> 16;
+        cpu_physical_memory_write(addr,
+                (void *)&xda[0], sizeof(xda));
+        cpu_physical_memory_set_dirty(addr+7);
+    }
+    else {
+        if (BCR_SWSTYLE(s) != 3)
+            cpu_physical_memory_write(addr, (void *)tmd, 16);
+        else {
+            uint32_t xda[4];
+            xda[0] = ((uint32_t *)tmd)[2];
+            xda[1] = ((uint32_t *)tmd)[1];
+            xda[2] = ((uint32_t *)tmd)[0];
+            xda[3] = ((uint32_t *)tmd)[3];
+            cpu_physical_memory_write(addr,
+                    (void *)&xda[0], sizeof(xda));
+        }
+        cpu_physical_memory_set_dirty(addr+15);
+    }
+}
+
+static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, 
target_phys_addr_t addr)
+{
+    if (!BCR_SWSTYLE(s)) {
+        uint16_t rda[4];
+        cpu_physical_memory_read(addr,
+                (void *)&rda[0], sizeof(rda));
+        ((uint32_t *)rmd)[0] = (rda[0]&0xffff)|
+                ((rda[1] & 0x00ff) << 16);
+        ((uint32_t *)rmd)[1] = (rda[2]&0xffff)|
+                ((rda[1] & 0xff00) << 16);
+        ((uint32_t *)rmd)[2] = rda[3] & 0xffff;
+        ((uint32_t *)rmd)[3] = 0;
+    }
+    else
+    if (BCR_SWSTYLE(s) != 3)
+        cpu_physical_memory_read(addr, (void *)rmd, 16);
+    else {
+        uint32_t rda[4];
+        cpu_physical_memory_read(addr,
+                (void *)&rda[0], sizeof(rda));
+        ((uint32_t *)rmd)[0] = rda[2];
+        ((uint32_t *)rmd)[1] = rda[1];
+        ((uint32_t *)rmd)[2] = rda[0];
+        ((uint32_t *)rmd)[3] = rda[3];
+    }
+}
+
+static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, 
target_phys_addr_t addr)
+{
+    cpu_physical_memory_set_dirty(addr);
+    if (!BCR_SWSTYLE(s)) {
+        uint16_t rda[4];                        \
+        rda[0] = ((uint32_t *)rmd)[0] & 0xffff; \
+        rda[1] = ((((uint32_t *)rmd)[0]>>16)&0xff)|\
+            ((((uint32_t *)rmd)[1]>>16)&0xff00);\
+        rda[2] = ((uint32_t *)rmd)[1] & 0xffff; \
+        rda[3] = ((uint32_t *)rmd)[2] & 0xffff; \
+        cpu_physical_memory_write(addr,         \
+                (void *)&rda[0], sizeof(rda));  \
+        cpu_physical_memory_set_dirty(addr+7);
+    }
+    else {
+        if (BCR_SWSTYLE(s) != 3)
+            cpu_physical_memory_write(addr, (void *)rmd, 16);
+        else {
+            uint32_t rda[4];
+            rda[0] = ((uint32_t *)rmd)[2];
+            rda[1] = ((uint32_t *)rmd)[1];
+            rda[2] = ((uint32_t *)rmd)[0];
+            rda[3] = ((uint32_t *)rmd)[3];
+            cpu_physical_memory_write(addr,
+                    (void *)&rda[0], sizeof(rda));
+        }
+        cpu_physical_memory_set_dirty(addr+15);
+    }
+}
+
+
+#define TMDLOAD(TMD,ADDR) pcnet_tmd_load(s,TMD,ADDR)
+
+#define TMDSTORE(TMD,ADDR) pcnet_tmd_store(s,TMD,ADDR)
+
+#define RMDLOAD(RMD,ADDR) pcnet_rmd_load(s,RMD,ADDR)
+
+#define RMDSTORE(RMD,ADDR) pcnet_rmd_store(s,RMD,ADDR)
+
+#if 1
+
+#define CHECK_RMD(ADDR,RES) do {                \
+    struct pcnet_RMD rmd;                       \
+    RMDLOAD(&rmd,(ADDR));                       \
+    (RES) |= (rmd.rmd1.ones != 15)              \
+          || (rmd.rmd2.zeros != 0);             \
+} while (0)
+
+#define CHECK_TMD(ADDR,RES) do {                \
+    struct pcnet_TMD tmd;                       \
+    TMDLOAD(&tmd,(ADDR));                       \
+    (RES) |= (tmd.tmd1.ones != 15);             \
+} while (0)
+
+#else
+
+#define CHECK_RMD(ADDR,RES) do {                \
+    switch (BCR_SWSTYLE(s)) {                   \
+    case 0x00:                                  \
+        do {                                    \
+            uint16_t rda[4];                    \
+            cpu_physical_memory_read((ADDR),    \
+                (void *)&rda[0], sizeof(rda));  \
+            (RES) |= (rda[2] & 0xf000)!=0xf000; \
+            (RES) |= (rda[3] & 0xf000)!=0x0000; \
+        } while (0);                            \
+        break;                                  \
+    case 0x01:                                  \
+    case 0x02:                                  \
+        do {                                    \
+            uint32_t rda[4];                    \
+            cpu_physical_memory_read((ADDR),    \
+                (void *)&rda[0], sizeof(rda)); \
+            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
+            (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
+        } while (0);                            \
+        break;                                  \
+    case 0x03:                                  \
+        do {                                    \
+            uint32_t rda[4];                    \
+            cpu_physical_memory_read((ADDR),    \
+                (void *)&rda[0], sizeof(rda)); \
+            (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
+            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
+        } while (0);                            \
+        break;                                  \
+    }                                           \
+} while (0)
+
+#define CHECK_TMD(ADDR,RES) do {                \
+    switch (BCR_SWSTYLE(s)) {                   \
+    case 0x00:                                  \
+        do {                                    \
+            uint16_t xda[4];                    \
+            cpu_physical_memory_read((ADDR),    \
+                (void *)&xda[0], sizeof(xda));  \
+            (RES) |= (xda[2] & 0xf000)!=0xf000;\
+        } while (0);                            \
+        break;                                  \
+    case 0x01:                                  \
+    case 0x02:                                  \
+    case 0x03:                                  \
+        do {                                    \
+            uint32_t xda[4];                    \
+            cpu_physical_memory_read((ADDR),    \
+                (void *)&xda[0], sizeof(xda));  \
+            (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
+        } while (0);                            \
+        break;                                  \
+    }                                           \
+} while (0)
+
+#endif
+
+#define PRINT_PKTHDR(BUF) do {                  \
+    struct ether_header *hdr = (void *)(BUF);   \
+    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "       \
+           "shost=%02x:%02x:%02x:%02x:%02x:%02x, "              \
+           "type=0x%04x (bcast=%d)\n",                          \
+           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
+           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
+           hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
+           hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
+           htons(hdr->ether_type),                                      \
+           !!ETHER_IS_MULTICAST(hdr->ether_dhost));                     \
+} while (0)
+
+#define MULTICAST_FILTER_LEN 8
+
+static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
+{
+#define LNC_POLYNOMIAL          0xEDB88320UL
+    uint32_t crc = 0xFFFFFFFF;
+    int idx, bit;
+    uint8_t data;
+
+    for (idx = 0; idx < ETHER_ADDR_LEN; idx++) {
+        for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) 
{
+            crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
+            data >>= 1;
+        }
+    }
+    return crc;
+#undef LNC_POLYNOMIAL
+}
+
+#define MIN(X,Y) ((X>Y) ? (Y) : (X))
+
+#define CRC(crc, ch)    (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
+
+/* generated using the AUTODIN II polynomial
+ *     x^32 + x^26 + x^23 + x^22 + x^16 +
+ *     x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
+ */
+static const uint32_t crctab[256] = {
+       0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+       0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+       0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+       0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+       0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+       0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+       0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+       0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+       0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+       0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+       0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+       0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+       0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+       0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+       0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+       0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+       0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+       0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+       0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+       0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+       0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+       0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+       0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+       0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+       0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+       0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+       0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+       0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+       0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+       0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+       0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+       0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+       0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+       0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+       0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+       0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+       0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+       0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+       0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+       0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+       0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+       0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+       0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+       0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+       0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+       0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+       0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+       0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+       0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+       0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+       0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+       0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+       0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+       0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+       0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+       0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+       0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+       0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+       0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+       0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+       0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+       0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+       0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+       0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
+{
+    struct ether_header *hdr = (void *)buf;
+    uint8_t padr[6] = { 
+        s->csr[12] & 0xff, s->csr[12] >> 8,
+        s->csr[13] & 0xff, s->csr[13] >> 8,
+        s->csr[14] & 0xff, s->csr[14] >> 8 
+    };
+    int result = (!CSR_DRCVPA(s)) && !bcmp(hdr->ether_dhost, padr, 6);
+#ifdef PCNET_DEBUG_MATCH
+    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "
+           "padr=%02x:%02x:%02x:%02x:%02x:%02x\n",
+           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2],
+           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5],
+           padr[0],padr[1],padr[2],padr[3],padr[4],padr[5]);
+    printf("padr_match result=%d\n", result);
+#endif
+    return result;
+}
+
+static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
+{
+    static uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+    struct ether_header *hdr = (void *)buf;
+    int result = !CSR_DRCVBC(s) && !bcmp(hdr->ether_dhost, BCAST, 6);
+#ifdef PCNET_DEBUG_MATCH
+    printf("padr_bcast result=%d\n", result);
+#endif
+    return result;
+}
+
+static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
+{
+    struct ether_header *hdr = (void *)buf;
+    if ((*(hdr->ether_dhost)&0x01) && 
+        ((uint64_t *)&s->csr[8])[0] != 0LL) {
+        uint8_t ladr[8] = { 
+            s->csr[8] & 0xff, s->csr[8] >> 8,
+            s->csr[9] & 0xff, s->csr[9] >> 8,
+            s->csr[10] & 0xff, s->csr[10] >> 8, 
+            s->csr[11] & 0xff, s->csr[11] >> 8 
+        };
+        int index = lnc_mchash(hdr->ether_dhost) >> 26;
+        return !!(ladr[index >> 3] & (1 << (index & 7)));
+    }
+    return 0;
+}
+
+static inline target_phys_addr_t pcnet_rdra_addr(PCNetState *s, int idx) 
+{
+    while (idx < 1) idx += CSR_RCVRL(s);
+    return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8));
+}
+
+static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t 
current_time)
+{
+    int64_t next_time = current_time + 
+        muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)), 
+                 ticks_per_sec, 33000000L);
+    if (next_time <= current_time)
+        next_time = current_time + 1;
+    return next_time;
+}
+
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/tpmif.py
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/server/tpmif.py     Fri Sep  9 16:30:54 2005
@@ -0,0 +1,45 @@
+# Copyright (C) 2005 IBM Corporation
+#   Authort: Stefan Berger, stefanb@xxxxxxxxxx
+# Derived from netif.py:
+# Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx>
+"""Support for virtual TPM interfaces.
+"""
+
+import random
+
+from xen.xend import sxp
+from xen.xend.XendError import XendError, VmError
+from xen.xend.XendLogging import log
+from xen.xend.XendRoot import get_component
+from xen.xend.xenstore import DBVar
+
+from xen.xend.server.controller import Dev, DevController
+
+class TPMifController(DevController):
+    """TPM interface controller. Handles all TPM devices for a domain.
+    """
+
+    def __init__(self, vm, recreate=False):
+        DevController.__init__(self, vm, recreate=recreate)
+
+    def initController(self, recreate=False, reboot=False):
+        self.destroyed = False
+
+    def destroyController(self, reboot=False):
+        """Destroy the controller and all devices.
+        """
+        self.destroyed = True
+        self.destroyDevices(reboot=reboot)
+
+    def sxpr(self):
+        val = ['tpmif', ['dom', self.getDomain()]]
+        return val
+
+    def newDevice(self, id, config, recreate=False):
+        """Create a TPM device.
+
+        @param id: interface id
+        @param config: device configuration
+        @param recreate: recreate flag (true after xend restart)
+        """
+        return None
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
tools/python/xen/xend/xenstore/xstransact.py
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/xenstore/xstransact.py      Fri Sep  9 16:30:54 2005
@@ -0,0 +1,113 @@
+# Copyright (C) 2005 Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
+
+# This file is subject to the terms and conditions of the GNU General
+# Public License.  See the file "COPYING" in the main directory of
+# this archive for more details.
+
+import threading
+from xen.lowlevel import xs
+
+handles = {}
+
+# XXX need to g/c handles from dead threads
+def xshandle():
+    if not handles.has_key(threading.currentThread()):
+        handles[threading.currentThread()] = xs.open()
+    return handles[threading.currentThread()]
+
+class xstransact:
+
+    def __init__(self, path):
+        self.path = path.rstrip("/")
+        xshandle().transaction_start(path)
+        self.in_transaction = True
+
+    def __del__(self):
+        if self.in_transaction:
+            xshandle().transaction_end(True)
+
+    def commit(self):
+        if not self.in_transaction:
+            raise RuntimeError
+        self.in_transaction = False
+        return xshandle().transaction_end(False)
+
+    def abort(self):
+        if not self.in_transaction:
+            raise RuntimeError
+        self.in_transaction = False
+        return xshandle().transaction_end(True)
+
+    def _read(self, key):
+        path = "%s/%s" % (self.path, key)
+        return xshandle().read(path)
+
+    def read(self, *args):
+        if len(args) == 0:
+            raise TypeError
+        if len(args) == 1:
+            return self._read(args[0])
+        ret = []
+        for key in args:
+            ret.append(self._read(key))
+        return ret
+
+    def _write(self, key, data, create=True, excl=False):
+        path = "%s/%s" % (self.path, key)
+        xshandle().write(path, data, create=create, excl=excl)
+
+    def write(self, *args, **opts):
+        create = opts.get('create') or True
+        excl = opts.get('excl') or False
+        if len(args) == 0:
+            raise TypeError
+        if isinstance(args[0], dict):
+            for d in args:
+                if not isinstance(d, dict):
+                    raise TypeError
+                for key in d.keys():
+                    self._write(key, d[key], create, excl)
+        elif isinstance(args[0], list):
+            for l in args:
+                if not len(l) == 2:
+                    raise TypeError
+                self._write(l[0], l[1], create, excl)
+        elif len(args) % 2 == 0:
+            for i in range(len(args) / 2):
+                self._write(args[i * 2], args[i * 2 + 1], create, excl)
+        else:
+            raise TypeError
+
+    def Read(cls, path, *args):
+        t = cls(path)
+        v = t.read(*args)
+        t.commit()
+        return v
+
+    Read = classmethod(Read)
+
+    def Write(cls, path, *args, **opts):
+        t = cls(path)
+        t.write(*args, **opts)
+        t.commit()
+
+    Write = classmethod(Write)
+
+    def SafeRead(cls, path, *args):
+        while True:
+            try:
+                return cls.Read(path, *args)
+            except RuntimeError, ex:
+                pass
+
+    SafeRead = classmethod(SafeRead)
+
+    def SafeWrite(cls, path, *args, **opts):
+        while True:
+            try:
+                cls.Write(path, *args, **opts)
+                return
+            except RuntimeError, ex:
+                pass
+
+    SafeWrite = classmethod(SafeWrite)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/xenstore/xswatch.py
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/python/xen/xend/xenstore/xswatch.py Fri Sep  9 16:30:54 2005
@@ -0,0 +1,65 @@
+# Copyright (C) 2005 Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
+
+# This file is subject to the terms and conditions of the GNU General
+# Public License.  See the file "COPYING" in the main directory of
+# this archive for more details.
+
+import select
+import threading
+from xen.lowlevel import xs
+
+class xswatch:
+
+    watchThread = None
+    threadcond = threading.Condition()
+    xs = None
+    xslock = threading.Lock()
+    
+    def __init__(self, path, fn, args=(), kwargs={}):
+        self.fn = fn
+        self.args = args
+        self.kwargs = kwargs
+        xswatch.watchStart()
+        xswatch.xslock.acquire()
+        xswatch.xs.watch(path, self)
+        xswatch.xslock.release()
+
+    def watchStart(cls):
+        cls.threadcond.acquire()
+        if cls.watchThread:
+            cls.threadcond.release()
+            return
+        cls.watchThread = threading.Thread(name="Watcher",
+                                           target=cls.watchMain)
+        cls.watchThread.setDaemon(True)
+        cls.watchThread.start()
+        while cls.xs == None:
+            cls.threadcond.wait()
+        cls.threadcond.release()
+
+    watchStart = classmethod(watchStart)
+
+    def watchMain(cls):
+        cls.threadcond.acquire()
+        cls.xs = xs.open()
+        cls.threadcond.notifyAll()
+        cls.threadcond.release()
+        while True:
+            try:
+                (ord, owr, oer) = select.select([ cls.xs ], [], [])
+                cls.xslock.acquire()
+                # reconfirm ready to read with lock
+                (ord, owr, oer) = select.select([ cls.xs ], [], [], 0.001)
+                if not cls.xs in ord:
+                    cls.xslock.release()
+                    continue
+                we = cls.xs.read_watch()
+                watch = we[1]
+                cls.xs.acknowledge_watch(watch)
+                cls.xslock.release()
+            except RuntimeError, ex:
+                print ex
+                raise
+            watch.fn(*watch.args, **watch.kwargs)
+
+    watchMain = classmethod(watchMain)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/security/getlabel.sh
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/security/getlabel.sh        Fri Sep  9 16:30:54 2005
@@ -0,0 +1,130 @@
+#!/bin/sh
+# *
+# * getlabel
+# *
+# * Copyright (C) 2005 IBM Corporation
+# *
+# * Authors:
+# * Stefan Berger <stefanb@xxxxxxxxxx>
+# *
+# * This program is free software; you can redistribute it and/or
+# * modify it under the terms of the GNU General Public License as
+# * published by the Free Software Foundation, version 2 of the
+# * License.
+# *
+# * 'getlabel' tries to find the labels corresponding to the ssidref
+# *
+# * 'getlabel -?' shows the usage of the program
+# *
+# * 'getlabel -sid <ssidref> [<policy name>]' lists the label corresponding
+# *                              to the given ssidref.
+# *
+# * 'getlabel -dom <domain id> [<policy name>]' lists the label of the
+# *                              domain with given id
+# *
+#
+
+if [ -z "$runbash" ]; then
+       runbash="1"
+       export runbash
+       exec sh -c "bash $0 $*"
+fi
+
+
+export PATH=$PATH:.
+source labelfuncs.sh
+
+usage ()
+{
+       echo "Usage: $0 -sid <ssidref> [<policy name>] or"
+       echo "       $0 -dom <domid>   [<policy name>]  "
+       echo ""
+       echo "policy name : the name of the policy, i.e. 'chwall'"
+       echo "              If the policy name is omitted, the grub.conf"
+       echo "              entry of the running system is tried to be read"
+       echo "              and the policy name determined from there."
+       echo "ssidref     : an ssidref in hex or decimal format, i.e., 
'0x00010002'"
+       echo "              or '65538'"
+       echo "domid       : id of the domain, i.e., '1'; Use numbers from the 
2nd"
+       echo "              column shown when invoking 'xm list'"
+       echo ""
+}
+
+
+
+if [ "$1" == "-?" ]; then
+       mode="usage"
+elif [ "$1" == "-dom" ]; then
+       mode="domid"
+       shift
+elif [ "$1" == "-sid" ]; then
+       mode="sid"
+       shift
+elif [ "$1" == "" ]; then
+       usage
+       exit -1
+fi
+
+
+if [ "$mode" == "usage" ]; then
+       usage
+elif [ "$mode" == "domid" ]; then
+       if [ "$2" == "" ]; then
+               findGrubConf
+               ret=$?
+               if [ $ret -eq 0 ]; then
+                       echo "Could not find grub.conf"
+                       exit -1;
+               fi
+               findPolicyInGrub $grubconf
+               if [ "$policy" != "" ]; then
+                       echo "Assuming policy to be '$policy'.";
+               else
+                       echo "Could not find policy."
+                       exit -1;
+               fi
+       else
+               policy=$2
+       fi
+       findMapFile $policy
+       res=$?
+       if [ "$res" != "0" ]; then
+               getSSIDUsingSecpolTool $1
+               res=$?
+               if [ "$res" != "0" ]; then
+                       translateSSIDREF $ssid $mapfile
+               else
+                       echo "Could not determine the SSID of the domain."
+               fi
+       else
+               echo "Could not find map file for policy '$policy'."
+       fi
+elif [ "$mode" == "sid" ]; then
+       if [ "$2" == "" ]; then
+               findGrubConf
+               ret=$?
+               if [ $ret -eq 0 ]; then
+                       echo "Could not find grub.conf"
+                       exit -1;
+               fi
+               findPolicyInGrub $grubconf
+               if [ "$policy" != "" ]; then
+                       echo "Assuming policy to be '$policy'.";
+               else
+                       echo "Could not find policy."
+                       exit -1;
+               fi
+       else
+               policy=$2
+       fi
+       findMapFile $policy
+       res=$?
+       if [ "$res" != "0" ]; then
+               translateSSIDREF $1 $mapfile
+       else
+               echo "Could not find map file for policy '$policy'."
+       fi
+
+else
+    usage
+fi
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/security/labelfuncs.sh
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/security/labelfuncs.sh      Fri Sep  9 16:30:54 2005
@@ -0,0 +1,675 @@
+# *
+# * labelfuncs.sh
+# *
+# * Copyright (C) 2005 IBM Corporation
+# *
+# * Authors:
+# * Stefan Berger <stefanb@xxxxxxxxxx>
+# *
+# * This program is free software; you can redistribute it and/or
+# * modify it under the terms of the GNU General Public License as
+# * published by the Free Software Foundation, version 2 of the
+# * License.
+# *
+# *
+# * A collection of functions to handle polcies, mapfiles,
+# * and ssidrefs.
+#
+
+
+# Find the mapfile given a policy nmame
+# Parameters:
+# 1st : the name of the policy whose map file is to be found, i.e.,
+#       chwall
+# Results:
+# The variable mapfile will hold the realtive path to the mapfile
+# for the given policy.
+# In case the mapfile could be found, the functions returns a '1',
+# a '0' otherwise.
+findMapFile ()
+{
+       mapfile="./$1.map"
+       if [ -r "$mapfile" ]; then
+               return 1
+       fi
+
+       mapfile="./policies/$1/$1.map"
+       if [ -r "$mapfile" ]; then
+               return 1
+       fi
+
+       return 0
+}
+
+
+# Determine the name of the primary policy
+# Parameters
+# 1st : the path to the mapfile; the path may be relative
+#       to the current directory
+# Results
+# The variable primary will hold the name of the primary policy
+getPrimaryPolicy ()
+{
+       mapfile=$1
+       primary=`cat $mapfile  |   \
+                awk '             \
+                 {                \
+                   if ( $1 == "PRIMARY" ) { \
+                     res=$2;                \
+                   }                        \
+                 } END {                    \
+                   print res;               \
+                 } '`
+}
+
+
+# Determine the name of the secondary policy
+# Parameters
+# 1st : the path to the mapfile; the path may be relative
+#       to the current directory
+# Results
+# The variable secondary will hold the name of the secondary policy
+getSecondaryPolicy ()
+{
+       mapfile=$1
+       secondary=`cat $mapfile  |   \
+                awk '             \
+                 {                \
+                   if ( $1 == "SECONDARY" ) { \
+                     res=$2;                \
+                   }                        \
+                 } END {                    \
+                   print res;               \
+                 } '`
+}
+
+
+#Return where the grub.conf file is.
+#I only know of one place it can be.
+findGrubConf()
+{
+       grubconf="/boot/grub/grub.conf"
+       if [ -w $grubconf ]; then
+               return 1
+       fi
+       if [ -r $grubconf ]; then
+               return 2
+       fi
+       return 0
+}
+
+
+# This function sets the global variable 'linux'
+# to the name and version of the Linux kernel that was compiled
+# for domain 0.
+# If this variable could not be found, the variable 'linux'
+# will hold a pattern
+# Parameters:
+# 1st: the path to reach the root directory of the XEN build tree
+#      where linux-*-xen0 is located at
+# Results:
+# The variable linux holds then name and version of the compiled
+# kernel, i.e., 'vmlinuz-2.6.12-xen0'
+getLinuxVersion ()
+{
+       path=$1
+       linux=""
+       for f in $path/linux-*-xen0 ; do
+               versionfile=$f/include/linux/version.h
+               if [ -r $versionfile ]; then
+                       lnx=`cat $versionfile | \
+                            grep UTS_RELEASE | \
+                            awk '{             \
+                              len=length($3);  \
+                              print substr($3,2,len-2) }'`
+               fi
+               if [ "$lnx" != "" ]; then
+                       linux="[./0-9a-zA-z]*$lnx"
+                       return;
+               fi
+       done
+
+       #Last resort.
+       linux="vmlinuz-2.[45678].[0-9]*[.0-9]*-xen0$"
+}
+
+
+# Find out with which policy the hypervisor was booted with.
+# Parameters
+# 1st : The complete path to grub.conf, i.e., /boot/grub/grub.conf
+#
+findPolicyInGrub ()
+{
+       grubconf=$1
+       linux=`uname -r`
+       policy=`cat $grubconf |                        \
+                awk -vlinux=$linux '{                 \
+                  if ( $1 == "title" ) {              \
+                    kernelfound = 0;                  \
+                    policymaycome = 0;                \
+                  }                                   \
+                  else if ( $1 == "kernel" ) {        \
+                    if ( match($2,"xen.gz$") ) {      \
+                      pathlen=RSTART;                 \
+                      kernelfound = 1;                \
+                    }                                 \
+                  }                                   \
+                  else if ( $1 == "module" &&         \
+                            kernelfound == 1 &&       \
+                            match($2,linux) ) {       \
+                     policymaycome = 1;               \
+                  }                                   \
+                  else if ( $1 == "module" &&         \
+                            kernelfound == 1 &&       \
+                            policymaycome == 1 &&     \
+                            match($2,"[0-9a-zA-Z_]*.bin$") ) { \
+                     policymaycome = 0;               \
+                     kernelfound = 0;                 \
+                     polname = substr($2,pathlen);    \
+                     len=length(polname);             \
+                     polname = substr(polname,0,len-4); \
+                  }                                   \
+                } END {                               \
+                  print polname                       \
+                }'`
+}
+
+
+# Get the SSID of a domain
+# Parameters:
+# 1st : domain ID, i.e. '1'
+# Results
+# If the ssid could be found, the variable 'ssid' will hold
+# the currently used ssid in the hex format, i.e., '0x00010001'.
+# The funtion returns '1' on success, '0' on failure
+getSSIDUsingSecpolTool ()
+{
+       domid=$1
+       export PATH=$PATH:.
+       ssid=`secpol_tool getssid -d $domid -f | \
+               grep -E "SSID:" |          \
+               awk '{ print $4 }'`
+
+       if [ "$ssid" != "" ]; then
+               return 1
+       fi
+       return 0
+}
+
+
+# Break the ssid identifier into its high and low values,
+# which are equal to the secondary and primary policy references.
+# Parameters:
+# 1st: ssid to break into high and low value, i.e., '0x00010002'
+# Results:
+# The variable ssidlo_int and ssidhi_int will hold the low and
+# high ssid values as integers.
+getSSIDLOHI ()
+{
+       ssid=$1
+       ssidlo_int=`echo $ssid | awk          \
+                   '{                        \
+                      len=length($0);        \
+                      beg=substr($0,1,2);    \
+                      if ( beg == "0x" ) {   \
+                          dig = len - 2;     \
+                          if (dig <= 0) {    \
+                            exit;            \
+                          }                  \
+                          if (dig > 4) {     \
+                            dig=4;           \
+                          }                  \
+                          lo=sprintf("0x%s",substr($0,len-dig+1,dig)); \
+                          print strtonum(lo);\
+                      } else {               \
+                          lo=strtonum($0);   \
+                          if (lo < 65536) {  \
+                            print lo;        \
+                          } else {           \
+                            hi=lo;           \
+                            hi2= (hi / 65536);\
+                            hi2_str=sprintf("%d",hi2); \
+                            hi2=strtonum(hi2_str);\
+                            lo=hi-(hi2*65536); \
+                            printf("%d",lo); \
+                          }                  \
+                       }                     \
+                   }'`
+       ssidhi_int=`echo $ssid | awk          \
+                   '{                        \
+                      len=length($0);        \
+                      beg=substr($0,1,2);    \
+                      if ( beg == "0x" ) {   \
+                          dig = len - 2;     \
+                          if (dig <= 0 ||    \
+                            dig >  8) {      \
+                            exit;            \
+                          }                  \
+                          if (dig < 4) {     \
+                            print 0;         \
+                            exit;            \
+                          }                  \
+                          dig -= 4;          \
+                          hi=sprintf("0x%s",substr($0,len-4-dig+1,dig)); \
+                          print strtonum(hi);\
+                      } else {               \
+                          hi=strtonum($0);   \
+                          if (hi >= 65536) { \
+                            hi = hi / 65536; \
+                            printf ("%d",hi);\
+                          } else {           \
+                            printf ("0");    \
+                          }                  \
+                      }                      \
+                   }'`
+       if [ "$ssidhi_int" == "" -o \
+            "$ssidlo_int" == "" ]; then
+               return 0;
+       fi
+       return 1
+}
+
+
+#Update the grub configuration file.
+#Search for existing entries and replace the current
+#policy entry with the policy passed to this script
+#
+#Arguments passed to this function
+# 1st : the grub configuration file with full path
+# 2nd : the binary policy file name, i.e. chwall.bin
+# 3rd : the name or pattern of the linux kernel name to match
+#       (this determines where the module entry will be made)
+#
+# The algorithm here is based on pattern matching
+# and is working correctly if
+# - under a title a line beginning with 'kernel' is found
+#   whose following item ends with "xen.gz"
+#   Example:  kernel /xen.gz dom0_mem=....
+# - a module line matching the 3rd parameter is found
+#
+updateGrub ()
+{
+       grubconf=$1
+       policyfile=$2
+       linux=$3
+
+       tmpfile="/tmp/new_grub.conf"
+
+       cat $grubconf |                                \
+                awk -vpolicy=$policyfile              \
+                    -vlinux=$linux '{                 \
+                  if ( $1 == "title" ) {              \
+                    kernelfound = 0;                  \
+                    if ( policymaycome == 1 ){        \
+                      printf ("\tmodule %s%s\n", path, policy);      \
+                    }                                 \
+                    policymaycome = 0;                \
+                  }                                   \
+                  else if ( $1 == "kernel" ) {        \
+                    if ( match($2,"xen.gz$") ) {      \
+                      path=substr($2,1,RSTART-1);     \
+                      kernelfound = 1;                \
+                    }                                 \
+                  }                                   \
+                  else if ( $1 == "module" &&         \
+                            kernelfound == 1 &&       \
+                            match($2,linux) ) {       \
+                     policymaycome = 1;               \
+                  }                                   \
+                  else if ( $1 == "module" &&         \
+                            kernelfound == 1 &&       \
+                            policymaycome == 1 &&     \
+                            match($2,"[0-9a-zA-Z]*.bin$") ) { \
+                     printf ("\tmodule %s%s\n", path, policy); \
+                     policymaycome = 0;               \
+                     kernelfound = 0;                 \
+                     dontprint = 1;                   \
+                  }                                   \
+                  else if ( $1 == "" &&               \
+                            kernelfound == 1 &&       \
+                            policymaycome == 1) {     \
+                     dontprint = 1;                   \
+                  }                                   \
+                  if (dontprint == 0) {               \
+                    printf ("%s\n", $0);              \
+                  }                                   \
+                  dontprint = 0;                      \
+                } END {                               \
+                  if ( policymaycome == 1 ) {         \
+                    printf ("\tmodule %s%s\n", path, policy);  \
+                  }                                   \
+                }' > $tmpfile
+       if [ ! -r $tmpfile ]; then
+               echo "Could not create temporary file! Aborting."
+               exit -1
+       fi
+       mv -f $tmpfile $grubconf
+}
+
+
+# Display all the labels in a given mapfile
+# Parameters
+# 1st: Full or relative path to the policy's mapfile
+showLabels ()
+{
+       mapfile=$1
+       if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
+               echo "Cannot read from vm configuration file $vmfile."
+               return -1
+       fi
+
+       getPrimaryPolicy $mapfile
+       getSecondaryPolicy $mapfile
+
+       echo "The following labels are available:"
+       let line=1
+       while [ 1 ]; do
+               ITEM=`cat $mapfile |         \
+                     awk -vline=$line       \
+                         -vprimary=$primary \
+                     '{                     \
+                        if ($1 == "LABEL->SSID" &&  \
+                            $2 == "VM" &&           \
+                            $3 == primary ) {       \
+                          ctr++;                    \
+                          if (ctr == line) {        \
+                            print $4;               \
+                          }                         \
+                        }                           \
+                      } END {                       \
+                      }'`
+
+               if [ "$ITEM" == "" ]; then
+                       break
+               fi
+               if [ "$secondary" != "NULL" ]; then
+                       LABEL=`cat $mapfile |     \
+                              awk -vitem=$ITEM   \
+                              '{
+                                 if ($1 == "LABEL->SSID" && \
+                                     $2 == "VM" &&          \
+                                     $3 == "CHWALL" &&      \
+                                     $4 == item ) {         \
+                                   result = item;           \
+                                 }                          \
+                               } END {                      \
+                                   print result             \
+                               }'`
+               else
+                       LABEL=$ITEM
+               fi
+
+               if [ "$LABEL" != "" ]; then
+                       echo "$LABEL"
+                       found=1
+               fi
+               let line=line+1
+       done
+       if [ "$found" != "1" ]; then
+               echo "No labels found."
+       fi
+}
+
+
+# Get the default SSID given a mapfile and the policy name
+# Parameters
+# 1st: Full or relative path to the policy's mapfile
+# 2nd: the name of the policy
+getDefaultSsid ()
+{
+       mapfile=$1
+       pol=$2
+       RES=`cat $mapfile    \
+            awk -vpol=$pol  \
+             {              \
+               if ($1 == "LABEL->SSID" && \
+                   $2 == "ANY"         && \
+                   $3 == pol           && \
+                   $4 == "DEFAULT"       ) {\
+                     res=$5;                \
+               }                            \
+             } END {                        \
+               printf "%04x", strtonum(res) \
+            }'`
+       echo "default NULL mapping is $RES"
+       defaultssid=$RES
+}
+
+
+#Relabel a VM configuration file
+# Parameters
+# 1st: Full or relative path to the VM configuration file
+# 2nd: The label to translate into an ssidref
+# 3rd: Full or relative path to the policy's map file
+# 4th: The mode this function is supposed to operate in:
+#      'relabel' : Relabels the file without querying the user
+#      other     : Prompts the user whether to proceed
+relabel ()
+{
+       vmfile=$1
+       label=$2
+       mapfile=$3
+       mode=$4
+
+       if [ ! -r "$vmfile" ]; then
+               echo "Cannot read from vm configuration file $vmfile."
+               return -1
+       fi
+
+       if [ ! -w "$vmfile" ]; then
+               echo "Cannot write to vm configuration file $vmfile."
+               return -1
+       fi
+
+       if [ ! -r "$mapfile" ] ; then
+               echo "Cannot read mapping file $mapfile."
+               return -1
+       fi
+
+       # Determine which policy is primary, which sec.
+       getPrimaryPolicy $mapfile
+       getSecondaryPolicy $mapfile
+
+       # Calculate the primary policy's SSIDREF
+       if [ "$primary" == "NULL" ]; then
+               SSIDLO="0001"
+       else
+               SSIDLO=`cat $mapfile |                    \
+                       awk -vlabel=$label                \
+                           -vprimary=$primary            \
+                          '{                             \
+                             if ( $1 == "LABEL->SSID" && \
+                                  $2 == "VM" &&          \
+                                  $3 == primary  &&      \
+                                  $4 == label ) {        \
+                               result=$5                 \
+                             }                           \
+                          } END {                        \
+                            if (result != "" )           \
+                              {printf "%04x", strtonum(result)}\
+                          }'`
+       fi
+
+       # Calculate the secondary policy's SSIDREF
+       if [ "$secondary" == "NULL" ]; then
+               if [ "$primary" == "NULL" ]; then
+                       SSIDHI="0001"
+               else
+                       SSIDHI="0000"
+               fi
+       else
+               SSIDHI=`cat $mapfile |                    \
+                       awk -vlabel=$label                \
+                           -vsecondary=$secondary        \
+                          '{                             \
+                             if ( $1 == "LABEL->SSID" && \
+                                  $2 == "VM"          && \
+                                  $3 == secondary     && \
+                                  $4 == label ) {        \
+                               result=$5                 \
+                             }                           \
+                           }  END {                      \
+                             if (result != "" )          \
+                               {printf "%04x", strtonum(result)}\
+                           }'`
+       fi
+
+       if [ "$SSIDLO" == "" -o \
+            "$SSIDHI" == "" ]; then
+               echo "Could not map the given label '$label'."
+               return -1
+       fi
+
+       ACM_POLICY=`cat $mapfile |             \
+           awk ' { if ( $1 == "POLICY" ) {    \
+                     result=$2                \
+                   }                          \
+                 }                            \
+                 END {                        \
+                   if (result != "") {        \
+                     printf result            \
+                   }                          \
+                 }'`
+
+       if [ "$ACM_POLICY" == "" ]; then
+               echo "Could not find 'POLICY' entry in map file."
+               return -1
+       fi
+
+       SSIDREF="0x$SSIDHI$SSIDLO"
+
+       if [ "$mode" != "relabel" ]; then
+               RES=`cat $vmfile |  \
+                    awk '{         \
+                      if ( substr($1,0,7) == "ssidref" ) {\
+                        print $0;             \
+                      }                       \
+                    }'`
+               if [ "$RES" != "" ]; then
+                       echo "Do you want to overwrite the existing mapping 
($RES)? (y/N)"
+                       read user
+                       if [ "$user" != "y" -a "$user" != "Y" ]; then
+                               echo "Aborted."
+                               return 0
+                       fi
+               fi
+       fi
+
+       #Write the output
+       vmtmp1="/tmp/__setlabel.tmp1"
+       vmtmp2="/tmp/__setlabel.tmp2"
+       touch $vmtmp1
+       touch $vmtmp2
+       if [ ! -w "$vmtmp1" -o ! -w "$vmtmp2" ]; then
+               echo "Cannot create temporary files. Aborting."
+               return -1
+       fi
+       RES=`sed -e '/^#ACM_POLICY/d' $vmfile > $vmtmp1`
+       RES=`sed -e '/^#ACM_LABEL/d' $vmtmp1 > $vmtmp2`
+       RES=`sed -e '/^ssidref/d' $vmtmp2 > $vmtmp1`
+       echo "#ACM_POLICY=$ACM_POLICY" >> $vmtmp1
+       echo "#ACM_LABEL=$label" >> $vmtmp1
+       echo "ssidref = $SSIDREF" >> $vmtmp1
+       mv -f $vmtmp1 $vmfile
+       rm -rf $vmtmp1 $vmtmp2
+       echo "Mapped label '$label' to ssidref '$SSIDREF'."
+}
+
+
+# Translate an ssidref into its label. This does the reverse lookup
+# to the relabel function above.
+# This function displays the results.
+# Parameters:
+# 1st: The ssidref to translate; must be in the form '0x00010002'
+# 2nd: Full or relative path to the policy's mapfile
+translateSSIDREF ()
+{
+       ssidref=$1
+       mapfile=$2
+
+       if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
+               echo "Cannot read from vm configuration file $vmfile."
+               return -1
+       fi
+
+       getPrimaryPolicy $mapfile
+       getSecondaryPolicy $mapfile
+
+       if [ "$primary" == "NULL" -a "$secondary" == "NULL" ]; then
+               echo "There are no labels for the NULL policy."
+               return
+       fi
+
+       getSSIDLOHI $ssidref
+       ret=$?
+       if [ $ret -ne 1 ]; then
+               echo "Error while parsing the ssid ref number '$ssidref'."
+       fi;
+
+       let line1=0
+       let line2=0
+       while [ 1 ]; do
+               ITEM1=`cat $mapfile |                       \
+                     awk -vprimary=$primary                \
+                         -vssidlo=$ssidlo_int              \
+                         -vline=$line1                     \
+                     '{                                    \
+                        if ( $1 == "LABEL->SSID" &&        \
+                             $3 == primary &&              \
+                             int($5) == ssidlo     ) {     \
+                            if (l == line) {               \
+                                print $4;                  \
+                                exit;                      \
+                            }                              \
+                            l++;                           \
+                        }                                  \
+                      }'`
+
+               ITEM2=`cat $mapfile |                       \
+                     awk -vsecondary=$secondary            \
+                         -vssidhi=$ssidhi_int              \
+                         -vline=$line2                     \
+                     '{                                    \
+                        if ( $1 == "LABEL->SSID" &&        \
+                             $3 == secondary &&            \
+                             int($5) == ssidhi     ) {     \
+                            if (l == line) {               \
+                                print $4;                  \
+                                exit;                      \
+                            }                              \
+                            l++;                           \
+                        }                                  \
+                      }'`
+
+               if [ "$secondary" != "NULL" ]; then
+                       if [ "$ITEM1" == "" ]; then
+                               let line1=0
+                               let line2=line2+1
+                       else
+                               let line1=line1+1
+                       fi
+
+                       if [ "$ITEM1" == "" -a \
+                            "$ITEM2" == "" ]; then
+                               echo "Could not determine the referenced label."
+                               break
+                       fi
+
+                       if [ "$ITEM1" == "$ITEM2" ]; then
+                               echo "Label: $ITEM1"
+                               break
+                       fi
+               else
+                       if [ "$ITEM1" != "" ]; then
+                               echo "Label: $ITEM1"
+                       else
+                               if [ "$found" == "0" ]; then
+                                       found=1
+                               else
+                                       break
+                               fi
+                       fi
+                       let line1=line1+1
+               fi
+       done
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm/Makefile
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm/Makefile       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,63 @@
+XEN_ROOT = ../..
+
+# Base definitions and rules
+include $(XEN_ROOT)/tools/vtpm/Rules.mk
+
+# Dir name for emulator (as dom0 tpm driver)
+TPM_EMULATOR_DIR = tpm_emulator-0.2
+# Dir name for vtpm instance
+VTPM_DIR = vtpm
+
+# Emulator tarball name
+TPM_EMULATOR_TARFILE = tpm_emulator-0.2b.tar.gz
+
+all: build
+
+build: $(TPM_EMULATOR_TARFILE) extract patch build_sub
+
+install: build
+       $(MAKE) -C $(TPM_EMULATOR_DIR) $@
+       $(MAKE) -C $(VTPM_DIR) $@
+
+clean:
+       if [ -d $(TPM_EMULATOR_DIR) ]; \
+               then $(MAKE) -C $(TPM_EMULATOR_DIR) clean; \
+       fi
+       if [ -d $(VTPM_DIR) ]; \
+               then $(MAKE) -C $(VTPM_DIR) clean; \
+       fi
+       rm -rf $(TPM_EMULATOR_DIR)
+       rm -rf $(VTPM_DIR)
+
+mrproper: clean
+       rm -f $(TPM_EMULATOR_TARFILE)
+
+# Download Swiss emulator
+$(TPM_EMULATOR_TARFILE):
+       wget http://download.berlios.de/tpm-emulator/$(TPM_EMULATOR_TARFILE)
+
+# Create vtpm and TPM emulator dirs
+extract: $(TPM_EMULATOR_DIR)/README $(VTPM_DIR)/README
+
+$(TPM_EMULATOR_DIR)/README:
+       -rm -rf $(TPM_EMULATOR_DIR)
+       tar -xzf $(TPM_EMULATOR_TARFILE)
+
+$(VTPM_DIR)/README:
+       -rm -rf $(VTPM_DIR)
+       cp -r --preserve $(TPM_EMULATOR_DIR) $(VTPM_DIR)
+
+# apply patches for 1) used as dom0 tpm driver 2) used as vtpm device instance
+patch: $(TPM_EMULATOR_DIR)/Makefile $(VTPM_DIR)/Makefile
+
+$(TPM_EMULATOR_DIR)/Makefile: tpm_emulator.patch
+       -cd $(TPM_EMULATOR_DIR); \
+       patch -p1 <../tpm_emulator.patch
+
+$(VTPM_DIR)/Makefile: vtpm.patch
+       -cd $(VTPM_DIR); \
+       patch -p1 <../vtpm.patch
+
+build_sub:
+       $(MAKE) -C $(TPM_EMULATOR_DIR)
+       $(MAKE) -C $(VTPM_DIR)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm/README
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm/README Fri Sep  9 16:30:54 2005
@@ -0,0 +1,44 @@
+
+Directory Structure
+===================
+tools/vtpm/tpm_emulator-0.2b.tar.gz    -> TPM Emulator downloaded at build 
time that will
+                                          be patched and used for our vtpms
+tools/vtpm/vtpm.patch                  -> patch applied to tpm_emulator to 
make vtpm
+tools/vtpm/vtpm/                       -> (created on build) tpm_emulator 
moved to ring 3,
+                                          listens on a pair of fifos for TPM 
commands,
+                                          persistent state is sent via named 
fifo to vtpm
+                                            manager, which encrypts it and 
protects it.
+tools/vtpm/tpm_emulator.patch          -> To allow for debugging and testing 
on non-TPM
+                                          platforms, this patches the emulator 
to allow
+                                          it to be inserted into the dom0 
kernel
+tools/vtpm/tpm_emulator-0.2            -> (created on build) directory 
containing patched emulator
+
+Compile Flags
+===================
+VTPM_MULTI_VM                -> Defined (not finished): VTPMs run in their own 
VMs
+                                Not Defined (default): VTPMs are processes
+
+Requirements
+============
+- xen-unstable 
+- IBM frontend/backend vtpm driver patch
+- vtpm_managerd
+
+vtpmd Flow (for vtpm_manager. vtpmd never run by default)
+============================
+- Launch the VTPM manager (vtpm_managerd) which which begins listening to the 
BE with one thread
+  and listens to a named fifo that is shared by the vtpms to commuincate with 
the manager.
+- VTPM Manager listens to TPM BE.
+- When xend launches a tpm frontend equipped VM it contacts the manager over 
the vtpm backend. 
+- When the manager receives the open message from the BE, it launches a vtpm
+- Xend allows the VM to continue booting. 
+- When a TPM request is issued to the front end, the front end transmits the 
TPM request to the backend.
+- The manager receives the TPM requests and uses a named fifo to forward the 
request to the vtpm.
+- The fifo listener begins listening for the reply from vtpm for the request.
+- Vtpm processes request and replies to manager over shared named fifo.
+- If needed, the vtpm may send a request to the vtpm_manager at any time to 
save it's secrets to disk.
+- Manager receives response from vtpm and passes it back to backend for 
forwarding to guest.
+
+tpm_emulator flow
+==================
+Read documentation in tpm_emulator-0.2 directory
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm/Rules.mk
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm/Rules.mk       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,37 @@
+# Base definitions and rules (XEN_ROOT must be defined in including Makefile)
+include $(XEN_ROOT)/tools/Rules.mk
+
+#
+# Tool definitions
+#
+
+# Installation program and options
+INSTALL         = install
+INSTALL_PROG    = $(INSTALL) -m0755
+INSTALL_DIR     = $(INSTALL) -d -m0755
+
+# Xen tools installation directory
+TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin
+
+# General compiler flags
+CFLAGS   = -Wall -Werror -g3 -I.
+
+# For generating dependencies
+CFLAGS += -Wp,-MD,.$(@F).d
+
+DEP_FILES      = .*.d
+
+# Generic project files
+HDRS   = $(wildcard *.h)
+SRCS   = $(wildcard *.c)
+OBJS   = $(patsubst %.c,%.o,$(SRCS))
+
+# Generic (non-header) dependencies
+$(SRCS): Makefile $(XEN_ROOT)/tools/Rules.mk $(XEN_ROOT)/tools/vtpm/Rules.mk
+
+$(OBJS): $(SRCS)
+
+-include $(DEP_FILES)
+
+# Make sure these are just rules
+.PHONY : all build install clean
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm/tpm_emulator.patch
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm/tpm_emulator.patch     Fri Sep  9 16:30:54 2005
@@ -0,0 +1,151 @@
+diff -uprN orig/tpm_emulator-0.2/AUTHORS tpm_emulator-0.2/AUTHORS
+--- orig/tpm_emulator-0.2/AUTHORS      2005-08-17 10:58:36.000000000 -0700
++++ tpm_emulator-0.2/AUTHORS   2005-08-17 10:55:52.000000000 -0700
+@@ -1 +1,2 @@
+ Mario Strasser <mast@xxxxxxx>
++INTEL Corp <>
+diff -uprN orig/tpm_emulator-0.2/ChangeLog tpm_emulator-0.2/ChangeLog
+--- orig/tpm_emulator-0.2/ChangeLog    2005-08-17 10:58:36.000000000 -0700
++++ tpm_emulator-0.2/ChangeLog 2005-08-17 10:55:52.000000000 -0700
+@@ -1,3 +1,7 @@
++2005-08-16: INTEL Corp
++      * Set default permissions to PCRs
++      * Changed device to /dev/tpm0
++
+ 2005-08-15  Mario Strasser <mast@xxxxxxx>
+       * all: some typos corrected
+       * tpm_integrity.c: bug in TPM_Extend fixed
+diff -uprN orig/tpm_emulator-0.2/Makefile tpm_emulator-0.2/Makefile
+--- orig/tpm_emulator-0.2/Makefile     2005-08-17 10:58:36.000000000 -0700
++++ tpm_emulator-0.2/Makefile  2005-08-17 10:55:52.000000000 -0700
+@@ -1,15 +1,19 @@
+ # Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ # Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>
++# Copyright (C) 2005 INTEL Corp.
+ #
+ # $Id: Makefile 10 2005-04-26 20:59:50Z mast $
+ 
++XEN_ROOT       := ../../..
++EUID           := $(shell id -u)
++
+ # kernel settings
+ KERNEL_RELEASE := $(shell uname -r)
+-KERNEL_BUILD   := /lib/modules/$(KERNEL_RELEASE)/build
++KERNEL_BUILD   := $(XEN_ROOT)/linux-2.6.12-xen0
+ MOD_SUBDIR     := misc
+ 
+ # module settings
+-MODULE_NAME    := tpm_emulator
++BIN            := tpm_emulator
+ VERSION_MAJOR  := 0
+ VERSION_MINOR  := 2
+ VERSION_BUILD  := $(shell date +"%s")
+@@ -27,11 +30,9 @@ DIRS           := . crypto tpm 
+ SRCS           := $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.c))
+ OBJS           := $(patsubst %.c, %.o, $(SRCS))
+ SRCS           += $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.h))
+-DISTSRC        := ./README ./AUTHORS ./ChangeLog ./Makefile $(SRCS)
+-DISTDIR        := tpm_emulator-$(VERSION_MAJOR).$(VERSION_MINOR)
+ 
+-obj-m               := $(MODULE_NAME).o
+-$(MODULE_NAME)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a
++obj-m               := $(BIN).o
++$(BIN)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a
+ 
+ EXTRA_CFLAGS   += -I$(src) -I$(src)/crypto -I$(src)/tpm 
+ 
+@@ -42,23 +43,17 @@ all:       $(src)/crypto/gmp.h $(src)/crypto/l
+       @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules
+ 
+ install:
+-      @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules_install
+-      test -d /var/tpm || mkdir /var/tpm
+-      test -c /dev/tpm || mknod /dev/tpm c 10 224
+-      chmod 666 /dev/tpm
+-      depmod -a
++      @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) INSTALL_MOD_PATH=$(DESTDIR) 
modules_install
++      test -d $(DESTDIR)/var/tpm || mkdir $(DESTDIR)/var/tpm
++      test -d $(DESTDIR)/dev || mkdir $(DESTDIR)/dev
++      test -c $(DESTDIR)/dev/tpm0 || [ $(EUID) -ne 0 ] || mknod 
$(DESTDIR)/dev/tpm0 c 10 224
++      [ $(EUID) -ne 0 ] || chmod 666 $(DESTDIR)/dev/tpm0
+ 
+ clean:
+       @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) clean
+       rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a
+ 
+-dist: $(DISTSRC)
+-      rm -rf $(DISTDIR)
+-      mkdir $(DISTDIR)
+-      cp --parents $(DISTSRC) $(DISTDIR)/
+-      rm -f $(DISTDIR)/crypto/gmp.h 
+-      tar -chzf $(DISTDIR).tar.gz $(DISTDIR)
+-      rm -rf $(DISTDIR)
++mrproper: clean
+ 
+ $(src)/crypto/libgmp.a:
+       test -f $(src)/crypto/libgmp.a || ln -s $(GMP_LIB) 
$(src)/crypto/libgmp.a
+diff -uprN orig/tpm_emulator-0.2/README tpm_emulator-0.2/README
+--- orig/tpm_emulator-0.2/README       2005-08-17 10:58:36.000000000 -0700
++++ tpm_emulator-0.2/README    2005-08-17 10:55:52.000000000 -0700
+@@ -13,7 +13,8 @@ $Id: README 8 2005-01-25 21:11:45Z jmoli
+ Copyright
+ --------------------------------------------------------------------------
+ Copyright (C) 2004 Mario Strasser <mast@xxxxxxx> and Swiss Federal 
+-Institute of Technology (ETH) Zurich.
++                   Institute of Technology (ETH) Zurich.
++Copyright (C) 2005 
+               
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+diff -uprN orig/tpm_emulator-0.2/linux_module.h tpm_emulator-0.2/linux_module.h
+--- orig/tpm_emulator-0.2/linux_module.h       2005-08-17 10:58:36.000000000 
-0700
++++ tpm_emulator-0.2/linux_module.h    2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp.
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -33,7 +34,7 @@
+ #include "tpm_version.h"
+ 
+ #define TPM_DEVICE_MINOR      224
+-#define TPM_DEVICE_NAME         "tpm"
++#define TPM_DEVICE_NAME         "tpm0"
+ #define TPM_MODULE_NAME       "tpm_emulator"
+ 
+ /* debug and log output functions */
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_data.c tpm_emulator-0.2/tpm/tpm_data.c
+--- orig/tpm_emulator-0.2/tpm/tpm_data.c       2005-08-17 10:58:36.000000000 
-0700
++++ tpm_emulator-0.2/tpm/tpm_data.c    2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+  *                    Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -85,6 +86,11 @@ void tpm_init_data(void)
+   tpmData.permanent.data.version.revMinor = VERSION_MINOR;
+   /* setup PCR attributes */
+   for (i = 0; i < TPM_NUM_PCR; i++) {
++    int j;
++    for (j=0; j < TPM_NUM_LOCALITY; j++) {
++      tpmData.permanent.data.pcrAttrib[i].pcrExtendLocal[j] = TRUE;
++    }
++
+     tpmData.permanent.data.pcrAttrib[i].pcrReset = TRUE;
+   }
+   /* set tick type */
+diff -uprN orig/tpm_emulator-0.2/tpm_version.h tpm_emulator-0.2/tpm_version.h
+--- orig/tpm_emulator-0.2/tpm_version.h        2005-08-17 10:58:36.000000000 
-0700
++++ tpm_emulator-0.2/tpm_version.h     2005-08-17 10:55:53.000000000 -0700
+@@ -2,5 +2,5 @@
+ #define _TPM_VERSION_H_
+ #define VERSION_MAJOR 0
+ #define VERSION_MINOR 2
+-#define VERSION_BUILD 1123950310
++#define VERSION_BUILD 1124301353
+ #endif /* _TPM_VERSION_H_ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm/vtpm.patch
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm/vtpm.patch     Fri Sep  9 16:30:54 2005
@@ -0,0 +1,1645 @@
+diff -uprN orig/tpm_emulator-0.2/AUTHORS vtpm/AUTHORS
+--- orig/tpm_emulator-0.2/AUTHORS      2005-08-17 10:58:36.000000000 -0700
++++ vtpm/AUTHORS       2005-08-17 10:55:52.000000000 -0700
+@@ -1 +1,2 @@
+ Mario Strasser <mast@xxxxxxx>
++INTEL Corp <>
+diff -uprN orig/tpm_emulator-0.2/ChangeLog vtpm/ChangeLog
+--- orig/tpm_emulator-0.2/ChangeLog    2005-08-17 10:58:36.000000000 -0700
++++ vtpm/ChangeLog     2005-08-17 10:55:52.000000000 -0700
+@@ -1,3 +1,7 @@
++2005-08-16 Intel Corp
++      Moved module out of kernel to run as a ring 3 app
++      Modified save_to_file and load_from_file to call a xen backend driver 
to call a VTPM manager
++
+ 2005-08-15  Mario Strasser <mast@xxxxxxx>
+       * all: some typos corrected
+       * tpm_integrity.c: bug in TPM_Extend fixed
+diff -uprN orig/tpm_emulator-0.2/Makefile vtpm/Makefile
+--- orig/tpm_emulator-0.2/Makefile     2005-08-17 10:58:36.000000000 -0700
++++ vtpm/Makefile      2005-08-17 10:55:52.000000000 -0700
+@@ -1,21 +1,29 @@
+ # Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ # Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>
++# Copyright (C) 2005 INTEL Corp.
+ #
+ # $Id: Makefile 10 2005-04-26 20:59:50Z mast $
+ 
+-# kernel settings
+-KERNEL_RELEASE := $(shell uname -r)
+-KERNEL_BUILD   := /lib/modules/$(KERNEL_RELEASE)/build
+-MOD_SUBDIR     := misc
+-
+ # module settings
+-MODULE_NAME    := tpm_emulator
++BIN            := vtpmd
+ VERSION_MAJOR  := 0
+ VERSION_MINOR  := 2
+ VERSION_BUILD  := $(shell date +"%s")
+ 
+-# enable/disable DEBUG messages
+-EXTRA_CFLAGS   += -DDEBUG -g  
++# Installation program and options
++INSTALL         = install
++INSTALL_PROG    = $(INSTALL) -m0755
++INSTALL_DIR     = $(INSTALL) -d -m0755
++
++# Xen tools installation directory
++TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin
++
++CC      := gcc
++CFLAGS  += -g -Wall $(INCLUDE) -DDEBUG
++CFLAGS  += -I. -Itpm
++
++# Is the simulator running in it's own vm?
++#CFLAGS += -DVTPM_MULTI_VM
+ 
+ # GNU MP configuration
+ GMP_LIB        := /usr/lib/libgmp.a
+@@ -27,38 +35,31 @@ DIRS           := . crypto tpm 
+ SRCS           := $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.c))
+ OBJS           := $(patsubst %.c, %.o, $(SRCS))
+ SRCS           += $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.h))
+-DISTSRC        := ./README ./AUTHORS ./ChangeLog ./Makefile $(SRCS)
+-DISTDIR        := tpm_emulator-$(VERSION_MAJOR).$(VERSION_MINOR)
+ 
+-obj-m               := $(MODULE_NAME).o
+-$(MODULE_NAME)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a
++obj-m               := $(BIN)
++$(BIN)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a
+ 
+ EXTRA_CFLAGS   += -I$(src) -I$(src)/crypto -I$(src)/tpm 
+ 
+ # do not print "Entering directory ..."
+ MAKEFLAGS      += --no-print-directory
+ 
+-all:  $(src)/crypto/gmp.h $(src)/crypto/libgmp.a version
+-      @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules
++all: $(BIN)
++
++$(BIN):       $(src)/crypto/gmp.h $(src)/crypto/libgmp.a version $(SRCS) 
$(OBJS)
++      $(CC) $(CFLAGS) $(OBJS) $(src)/crypto/libgmp.a -o $(BIN)
++
++%.o: %.c
++      $(CC) $(CFLAGS) -c $< -o $@
+ 
+ install:
+-      @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules_install
+-      test -d /var/tpm || mkdir /var/tpm
+-      test -c /dev/tpm || mknod /dev/tpm c 10 224
+-      chmod 666 /dev/tpm
+-      depmod -a
++      $(INSTALL_PROG) $(BIN) $(TOOLS_INSTALL_DIR)
+ 
+ clean:
+-      @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) clean
+-      rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a
++      rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a $(OBJS)
+ 
+-dist: $(DISTSRC)
+-      rm -rf $(DISTDIR)
+-      mkdir $(DISTDIR)
+-      cp --parents $(DISTSRC) $(DISTDIR)/
+-      rm -f $(DISTDIR)/crypto/gmp.h 
+-      tar -chzf $(DISTDIR).tar.gz $(DISTDIR)
+-      rm -rf $(DISTDIR)
++mrproper: clean
++      rm -f $(BIN)
+ 
+ $(src)/crypto/libgmp.a:
+       test -f $(src)/crypto/libgmp.a || ln -s $(GMP_LIB) 
$(src)/crypto/libgmp.a
+diff -uprN orig/tpm_emulator-0.2/README vtpm/README
+--- orig/tpm_emulator-0.2/README       2005-08-17 10:58:36.000000000 -0700
++++ vtpm/README        2005-08-17 10:55:52.000000000 -0700
+@@ -13,7 +13,8 @@ $Id: README 8 2005-01-25 21:11:45Z jmoli
+ Copyright
+ --------------------------------------------------------------------------
+ Copyright (C) 2004 Mario Strasser <mast@xxxxxxx> and Swiss Federal 
+-Institute of Technology (ETH) Zurich.
++                   Institute of Technology (ETH) Zurich.
++Copyright (C) 2005 INTEL Corp 
+               
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+diff -uprN orig/tpm_emulator-0.2/crypto/gmp_kernel_wrapper.c 
vtpm/crypto/gmp_kernel_wrapper.c
+--- orig/tpm_emulator-0.2/crypto/gmp_kernel_wrapper.c  2005-08-17 
10:58:36.000000000 -0700
++++ vtpm/crypto/gmp_kernel_wrapper.c   2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -24,15 +25,10 @@ int __gmp_junk;
+ void __attribute__ ((regparm(0))) __gmp_assert_fail(const char *filename, 
+   int linenum, const char *expr) 
+ {
+-  panic(KERN_CRIT TPM_MODULE_NAME "%s:%d: GNU MP assertion failed: %s\n", 
++  error("%s:%d: GNU MP assertion failed: %s\n", 
+     filename, linenum, expr);
+ }
+ 
+-void __attribute__ ((regparm(0))) abort(void)
+-{
+-  panic(KERN_CRIT TPM_MODULE_NAME "GNU MP abort() was called\n");
+-}
+-
+ /* overwrite GNU MP random functions (used by mpz/millerrabin.c) */ 
+ 
+ void __attribute__ ((regparm(0))) gmp_randinit(gmp_randstate_t rstate, 
+@@ -77,20 +73,19 @@ void __attribute__ ((regparm(0))) mpz_ur
+ 
+ void __attribute__ ((regparm(0))) *kernel_allocate(size_t size)
+ {
+-  void *ret  = (void*)kmalloc(size, GFP_KERNEL);
+-  if (!ret) panic(KERN_CRIT TPM_MODULE_NAME 
+-    "GMP: cannot allocate memory (size=%u)\n", size);
++  void *ret  = (void*)malloc(size);
++  if (!ret) error("GMP: cannot allocate memory (size=%u)\n", size);
+   return ret;
+ }
+ 
+ void __attribute__ ((regparm(0))) *kernel_reallocate(void *oldptr, 
+   size_t old_size, size_t new_size)
+ {
+-  void *ret = (void*)kmalloc(new_size, GFP_KERNEL);
+-  if (!ret) panic(KERN_CRIT TPM_MODULE_NAME "GMP: Cannot reallocate memory "
++  void *ret = (void*)malloc(new_size);
++  if (!ret) error("GMP: Cannot reallocate memory "
+     "(old_size=%u new_size=%u)\n", old_size, new_size);
+   memcpy(ret, oldptr, old_size);
+-  kfree(oldptr);
++  free(oldptr);
+   return ret;
+ }
+ 
+@@ -99,7 +94,7 @@ void __attribute__ ((regparm(0))) kernel
+   /* overwrite used memory */
+   if (blk_ptr != NULL) { 
+     memset(blk_ptr, 0, blk_size);
+-    kfree(blk_ptr);
++    free(blk_ptr);
+   }
+ }
+ 
+diff -uprN orig/tpm_emulator-0.2/crypto/rsa.c vtpm/crypto/rsa.c
+--- orig/tpm_emulator-0.2/crypto/rsa.c 2005-08-17 10:58:36.000000000 -0700
++++ vtpm/crypto/rsa.c  2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -363,7 +364,7 @@ static int encode_message(int type, uint
+       msg[0] = 0x00;
+       get_random_bytes(&msg[1], SHA1_DIGEST_LENGTH);
+       sha1_init(&ctx);
+-      sha1_update(&ctx, "TCPA", 4);
++      sha1_update(&ctx, (uint8_t *) "TCPA", 4);
+       sha1_final(&ctx, &msg[1 + SHA1_DIGEST_LENGTH]);
+       memset(&msg[1 + 2 * SHA1_DIGEST_LENGTH], 0x00, 
+         msg_len - data_len - 2 * SHA1_DIGEST_LENGTH - 2);
+@@ -411,7 +412,7 @@ static int decode_message(int type, uint
+       mask_generation(&msg[1], SHA1_DIGEST_LENGTH,
+         &msg[1 + SHA1_DIGEST_LENGTH], msg_len - SHA1_DIGEST_LENGTH - 1);
+       sha1_init(&ctx);
+-      sha1_update(&ctx, "TCPA", 4);
++      sha1_update(&ctx, (uint8_t *) "TCPA", 4);
+       sha1_final(&ctx, &msg[1]);
+       if (memcmp(&msg[1], &msg[1 + SHA1_DIGEST_LENGTH], 
+           SHA1_DIGEST_LENGTH) != 0) return -1;
+diff -uprN orig/tpm_emulator-0.2/linux_module.c vtpm/linux_module.c
+--- orig/tpm_emulator-0.2/linux_module.c       2005-08-17 10:58:36.000000000 
-0700
++++ vtpm/linux_module.c        1969-12-31 16:00:00.000000000 -0800
+@@ -1,163 +0,0 @@
+-/* Software-Based Trusted Platform Module (TPM) Emulator for Linux 
+- * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+- *
+- * This module is free software; you can redistribute it and/or modify 
+- * it under the terms of the GNU General Public License as published 
+- * by the Free Software Foundation; either version 2 of the License, 
+- * or (at your option) any later version.  
+- *
+- * This module is distributed in the hope that 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.
+- *
+- * $Id: linux_module.c 19 2005-05-18 08:29:37Z mast $
+- */
+-
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/miscdevice.h>
+-#include <linux/poll.h>
+-#include "linux_module.h"
+-#include "tpm/tpm_emulator.h"
+-
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Mario Strasser <mast@xxxxxxx>");
+-MODULE_DESCRIPTION("Trusted Platform Module (TPM) Emulator");
+-MODULE_SUPPORTED_DEVICE(TPM_DEVICE_NAME);
+-
+-/* module startup parameters */
+-char *startup = "save";
+-MODULE_PARM(startup, "s");
+-MODULE_PARM_DESC(startup, " Sets the startup mode of the TPM. "
+-  "Possible values are 'clear', 'save' (default) and 'deactivated.");
+-char *storage_file = "/var/tpm/tpm_emulator-1.2.0.1";
+-MODULE_PARM(storage_file, "s");
+-MODULE_PARM_DESC(storage_file, " Sets the persistent-data storage " 
+-  "file of the TPM.");
+-
+-/* TPM lock */
+-static struct semaphore tpm_mutex;
+-
+-/* TPM command response */
+-static struct {
+-  uint8_t *data;
+-  uint32_t size;
+-} tpm_response;
+-
+-/* module state */
+-#define STATE_IS_OPEN 0
+-static uint32_t module_state;
+-
+-static int tpm_open(struct inode *inode, struct file *file)
+-{
+-  debug("%s()", __FUNCTION__);
+-  if (test_and_set_bit(STATE_IS_OPEN, (void*)&module_state)) return -EBUSY;
+-  return 0;
+-}
+-
+-static int tpm_release(struct inode *inode, struct file *file)
+-{
+-  debug("%s()", __FUNCTION__);
+-  clear_bit(STATE_IS_OPEN, (void*)&module_state);
+-  return 0;
+-}
+-
+-static ssize_t tpm_read(struct file *file, char *buf, size_t count, loff_t 
*ppos)
+-{
+-  debug("%s(%d)", __FUNCTION__, count);
+-  down(&tpm_mutex);
+-  if (tpm_response.data != NULL) {
+-    count = min(count, (size_t)tpm_response.size - (size_t)*ppos);
+-    count -= copy_to_user(buf, &tpm_response.data[*ppos], count);
+-    *ppos += count;
+-  } else {
+-    count = 0;
+-  }
+-  up(&tpm_mutex);
+-  return count;
+-}
+-
+-static ssize_t tpm_write(struct file *file, const char *buf, size_t count, 
loff_t *ppos)
+-{
+-  debug("%s(%d)", __FUNCTION__, count);
+-  down(&tpm_mutex);
+-  *ppos = 0;
+-  if (tpm_response.data != NULL) kfree(tpm_response.data);
+-  if (tpm_handle_command(buf, count, &tpm_response.data, 
+-                         &tpm_response.size) != 0) { 
+-    count = -EILSEQ;
+-    tpm_response.data = NULL;
+-  }
+-  up(&tpm_mutex);
+-  return count;
+-}
+-
+-static int tpm_ioctl(struct inode *inode, struct file *file, unsigned int 
cmd, unsigned long arg)
+-{
+-  debug("%s(%d, %ld)", __FUNCTION__, cmd, arg);
+-  return -1;
+-}
+-
+-struct file_operations fops = {
+-  .owner   = THIS_MODULE,
+-  .open    = tpm_open,
+-  .release = tpm_release,
+-  .read    = tpm_read,
+-  .write   = tpm_write,
+-  .ioctl   = tpm_ioctl,
+-};
+-
+-static struct miscdevice tpm_dev = {
+-  .minor      = TPM_DEVICE_MINOR, 
+-  .name       = TPM_DEVICE_NAME, 
+-  .fops       = &fops,
+-};
+-
+-int __init init_tpm_module(void)
+-{
+-  int res = misc_register(&tpm_dev);
+-  if (res != 0) {
+-    error("misc_register() failed for minor %d\n", TPM_DEVICE_MINOR);
+-    return res;
+-  }
+-  /* initialize variables */
+-  sema_init(&tpm_mutex, 1);
+-  module_state = 0;
+-  tpm_response.data = NULL;    
+-  /* initialize TPM emulator */
+-  if (!strcmp(startup, "clear")) {
+-    tpm_emulator_init(1);
+-  } else if (!strcmp(startup, "save")) { 
+-    tpm_emulator_init(2);
+-  } else if (!strcmp(startup, "deactivated")) {
+-    tpm_emulator_init(3);
+-  } else {
+-    error("invalid startup mode '%s'; must be 'clear', "
+-      "'save' (default) or 'deactivated", startup);
+-    misc_deregister(&tpm_dev);
+-    return -EINVAL;
+-  }
+-  return 0;
+-}
+-
+-void __exit cleanup_tpm_module(void)
+-{
+-  tpm_emulator_shutdown();
+-  misc_deregister(&tpm_dev);
+-}
+-
+-module_init(init_tpm_module);
+-module_exit(cleanup_tpm_module);
+-
+-uint64_t tpm_get_ticks(void)
+-{
+-  static struct timespec old_time = {0, 0}; 
+-  struct timespec new_time = current_kernel_time();
+-  uint64_t ticks = (uint64_t)(old_time.tv_sec - new_time.tv_sec) * 1000000
+-                   + (old_time.tv_nsec - new_time.tv_nsec) / 1000;
+-  old_time = new_time;
+-  return (ticks > 0) ? ticks : 1;
+-}
+-
+diff -uprN orig/tpm_emulator-0.2/linux_module.h vtpm/linux_module.h
+--- orig/tpm_emulator-0.2/linux_module.h       2005-08-17 10:58:36.000000000 
-0700
++++ vtpm/linux_module.h        2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -17,17 +18,22 @@
+ #ifndef _LINUX_MODULE_H_
+ #define _LINUX_MODULE_H_
+ 
+-#include <linux/version.h>
+-#include <linux/kernel.h>
+-#include <linux/slab.h>
++#include <malloc.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <string.h>
+ #include <linux/types.h>
+-#include <linux/string.h>
+-#include <linux/random.h>
+-#include <linux/time.h>
+-#include <asm/byteorder.h>
+ 
+-/* module settings */
++#include <endian.h>
++#define __BYTEORDER_HAS_U64__
++#ifdef LITTLE_ENDIAN
++ #include <linux/byteorder/little_endian.h>
++#else
++ #include <linux/byteorder/big_endian.h>
++#endif
+ 
++/* module settings */
++#define min(A,B) ((A)<(B)?(A):(B))
+ #define STR(s) __STR__(s)
+ #define __STR__(s) #s
+ #include "tpm_version.h"
+@@ -39,32 +45,35 @@
+ /* debug and log output functions */
+ 
+ #ifdef DEBUG
+-#define debug(fmt, ...) printk(KERN_DEBUG "%s %s:%d: Debug: " fmt "\n", \
+-                        TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)
++#define debug(fmt, ...) printf("%s:%d: Debug: " fmt "\n", \
++                        __FILE__, __LINE__, ## __VA_ARGS__)
+ #else
+ #define debug(fmt, ...) 
+ #endif
+-#define info(fmt, ...)  printk(KERN_INFO "%s %s:%d: Info: " fmt "\n", \
+-                        TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)
+-#define error(fmt, ...) printk(KERN_ERR "%s %s:%d: Error: " fmt "\n", \
+-                        TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)
+-#define alert(fmt, ...) printk(KERN_ALERT "%s %s:%d: Alert: " fmt "\n", \
+-                        TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)
++#define info(fmt, ...)  printf("%s:%d: Info: " fmt "\n", \
++                        __FILE__, __LINE__, ## __VA_ARGS__)
++#define error(fmt, ...) printf("%s:%d: Error: " fmt "\n", \
++                        __FILE__, __LINE__, ## __VA_ARGS__)
++#define alert(fmt, ...) printf("%s:%d: Alert: " fmt "\n", \
++                        __FILE__, __LINE__, ## __VA_ARGS__)
+ 
+ /* memory allocation */
+ 
+ static inline void *tpm_malloc(size_t size) 
+ {
+-  return kmalloc(size, GFP_KERNEL);  
++  return malloc(size);  
+ }
+ 
+ static inline void tpm_free(const void *ptr)
+ {
+-  if (ptr != NULL) kfree(ptr);
++  if (ptr != NULL) free( (void *) ptr);
+ }
+ 
+ /* random numbers */
+ 
++//FIXME;
++void get_random_bytes(void *buf, int nbytes);
++
+ static inline void tpm_get_random_bytes(void *buf, int nbytes)
+ {
+   get_random_bytes(buf, nbytes);
+@@ -84,9 +93,9 @@ uint64_t tpm_get_ticks(void);
+ #define CPU_TO_LE16(x) __cpu_to_le16(x)
+ 
+ #define BE64_TO_CPU(x) __be64_to_cpu(x)
+-#define LE64_TO_CPU(x) __be64_to_cpu(x)
++#define LE64_TO_CPU(x) __le64_to_cpu(x)
+ #define BE32_TO_CPU(x) __be32_to_cpu(x)
+-#define LE32_TO_CPU(x) __be32_to_cpu(x)
++#define LE32_TO_CPU(x) __le32_to_cpu(x)
+ #define BE16_TO_CPU(x) __be16_to_cpu(x)
+ #define LE16_TO_CPU(x) __le16_to_cpu(x)
+ 
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_audit.c vtpm/tpm/tpm_audit.c
+--- orig/tpm_emulator-0.2/tpm/tpm_audit.c      2005-08-17 10:58:36.000000000 
-0700
++++ vtpm/tpm/tpm_audit.c       2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+  *                    Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -45,14 +46,14 @@ void tpm_audit_request(TPM_COMMAND_CODE 
+       tpmData.permanent.data.auditMonotonicCounter++;
+     }
+     /* update audit digest */
+-    *((UINT16*)&buf[0])  = cpu_to_be16(TPM_TAG_AUDIT_EVENT_IN);
+-    *((UINT32*)&buf[2]) = cpu_to_be32(ordinal);
++    *((UINT16*)&buf[0])  = CPU_TO_BE16(TPM_TAG_AUDIT_EVENT_IN);
++    *((UINT32*)&buf[2]) = CPU_TO_BE32(ordinal);
+     sha1_init(&sha1_ctx);
+     sha1_update(&sha1_ctx, req->param, req->paramSize);
+     sha1_final(&sha1_ctx, &buf[6]);
+-    *((UINT16*)&buf[26])  = cpu_to_be16(TPM_TAG_COUNTER_VALUE);
++    *((UINT16*)&buf[26])  = CPU_TO_BE16(TPM_TAG_COUNTER_VALUE);
+     memset(&buf[30], 0, 4);
+-    *((UINT32*)&buf[34]) = 
cpu_to_be32(tpmData.permanent.data.auditMonotonicCounter);
++    *((UINT32*)&buf[34]) = 
CPU_TO_BE32(tpmData.permanent.data.auditMonotonicCounter);
+     sha1_init(&sha1_ctx);
+     sha1_update(&sha1_ctx, tpmData.stany.data.auditDigest.digest, 
+       sizeof(TPM_DIGEST));
+@@ -70,15 +71,15 @@ void tpm_audit_response(TPM_COMMAND_CODE
+       && (AUDIT_STATUS[ord / 8] & (1 << (ord & 0x07)))) {
+     info("tpm_audit_response()");
+     /* update audit digest */
+-    *((UINT16*)&buf[0])  = cpu_to_be16(TPM_TAG_AUDIT_EVENT_OUT);
+-    *((UINT32*)&buf[2]) = cpu_to_be32(ordinal);
++    *((UINT16*)&buf[0])  = CPU_TO_BE16(TPM_TAG_AUDIT_EVENT_OUT);
++    *((UINT32*)&buf[2]) = CPU_TO_BE32(ordinal);
+     sha1_init(&sha1_ctx);
+     sha1_update(&sha1_ctx, rsp->param, rsp->paramSize);
+     sha1_final(&sha1_ctx, &buf[6]);
+-    *((UINT16*)&buf[26])  = cpu_to_be16(TPM_TAG_COUNTER_VALUE);
++    *((UINT16*)&buf[26])  = CPU_TO_BE16(TPM_TAG_COUNTER_VALUE);
+     memset(&buf[30], 0, 4);
+-    *((UINT32*)&buf[34]) = 
cpu_to_be32(tpmData.permanent.data.auditMonotonicCounter);
+-    *((UINT32*)&buf[34]) = cpu_to_be32(rsp->result);
++    *((UINT32*)&buf[34]) = 
CPU_TO_BE32(tpmData.permanent.data.auditMonotonicCounter);
++    *((UINT32*)&buf[34]) = CPU_TO_BE32(rsp->result);
+     sha1_init(&sha1_ctx);
+     sha1_update(&sha1_ctx, tpmData.stany.data.auditDigest.digest, 
+       sizeof(TPM_DIGEST));
+@@ -158,7 +159,7 @@ TPM_RESULT TPM_GetAuditDigestSigned(TPM_
+   }
+   memcpy(&buf[0], "\x05\x00ADIG", 6);
+   memcpy(&buf[6], antiReplay->nonce, 20);
+-  *(UINT32*)&buf[26] = cpu_to_be32(buf_size - 30);
++  *(UINT32*)&buf[26] = CPU_TO_BE32(buf_size - 30);
+   memcpy(&buf[30], auditDigest->digest, 20);
+   ptr = &buf[50];
+   len = buf_size - 50;
+@@ -198,4 +199,3 @@ TPM_RESULT TPM_SetOrdinalAuditStatus(TPM
+   }
+   return TPM_SUCCESS;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_authorization.c 
vtpm/tpm/tpm_authorization.c
+--- orig/tpm_emulator-0.2/tpm/tpm_authorization.c      2005-08-17 
10:58:36.000000000 -0700
++++ vtpm/tpm/tpm_authorization.c       2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+  *                    Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -268,7 +269,7 @@ TPM_RESULT tpm_verify_auth(TPM_AUTH *aut
+ {
+   hmac_ctx_t ctx;
+   TPM_SESSION_DATA *session;
+-  UINT32 auth_handle = cpu_to_be32(auth->authHandle);
++  UINT32 auth_handle = CPU_TO_BE32(auth->authHandle);
+   
+   info("tpm_verify_auth(%08x)", auth->authHandle);
+   /* get dedicated authorization session */
+@@ -316,5 +317,3 @@ void tpm_decrypt_auth_secret(TPM_ENCAUTH
+   for (i = 0; i < sizeof(TPM_SECRET); i++)
+     plainAuth[i] ^= encAuth[i];
+ }
+-
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_capability.c vtpm/tpm/tpm_capability.c
+--- orig/tpm_emulator-0.2/tpm/tpm_capability.c 2005-08-17 10:58:36.000000000 
-0700
++++ vtpm/tpm/tpm_capability.c  2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+  *                    Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -398,7 +399,7 @@ TPM_RESULT TPM_GetCapability(TPM_CAPABIL
+ 
+     case TPM_CAP_KEY_HANDLE:
+       debug("[TPM_CAP_KEY_HANDLE]");
+-      subCapSize = cpu_to_be32(TPM_RT_KEY);
++      subCapSize = CPU_TO_BE32(TPM_RT_KEY);
+       return cap_handle(4, (BYTE*)&subCapSize, respSize, resp);
+ 
+     case TPM_CAP_CHECK_LOADED:
+@@ -472,4 +473,3 @@ TPM_RESULT TPM_GetCapability(TPM_CAPABIL
+       return TPM_BAD_MODE;
+   }
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_cmd_handler.c 
vtpm/tpm/tpm_cmd_handler.c
+--- orig/tpm_emulator-0.2/tpm/tpm_cmd_handler.c        2005-08-17 
10:58:36.000000000 -0700
++++ vtpm/tpm/tpm_cmd_handler.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+  *                    Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -26,7 +27,7 @@ static void tpm_compute_in_param_digest(
+ {
+   sha1_ctx_t sha1;
+   UINT32 offset;
+-  UINT32 ord = cpu_to_be32(req->ordinal);
++  UINT32 ord = CPU_TO_BE32(req->ordinal);
+ 
+   /* skip all key-handles at the beginning */
+   switch (req->ordinal) {
+@@ -82,8 +83,8 @@ static void tpm_compute_in_param_digest(
+ static void tpm_compute_out_param_digest(TPM_COMMAND_CODE ordinal, 
TPM_RESPONSE *rsp)
+ {
+   sha1_ctx_t sha1;
+-  UINT32 res = cpu_to_be32(rsp->result);
+-  UINT32 ord = cpu_to_be32(ordinal);
++  UINT32 res = CPU_TO_BE32(rsp->result);
++  UINT32 ord = CPU_TO_BE32(ordinal);
+ 
+   /* compute SHA1 hash */
+   sha1_init(&sha1);
+@@ -3081,7 +3082,7 @@ static void tpm_setup_rsp_auth(TPM_COMMA
+       hmac_update(&hmac, rsp->auth2->digest, sizeof(rsp->auth2->digest));
+ #if 0
+       if (tpm_get_auth(rsp->auth2->authHandle)->type == TPM_ST_OIAP) {
+-        UINT32 handle = cpu_to_be32(rsp->auth2->authHandle);
++        UINT32 handle = CPU_TO_BE32(rsp->auth2->authHandle);
+         hmac_update(&hmac, (BYTE*)&handle, 4);
+       }
+ #endif
+@@ -3096,7 +3097,7 @@ static void tpm_setup_rsp_auth(TPM_COMMA
+       hmac_update(&hmac, rsp->auth1->digest, sizeof(rsp->auth1->digest));
+ #if 0
+       if (tpm_get_auth(rsp->auth1->authHandle)->type == TPM_ST_OIAP) {
+-        UINT32 handle = cpu_to_be32(rsp->auth1->authHandle);
++        UINT32 handle = CPU_TO_BE32(rsp->auth1->authHandle);
+         hmac_update(&hmac, (BYTE*)&handle, 4);
+       }
+ #endif
+@@ -3179,7 +3180,9 @@ extern const char *tpm_error_to_string(T
+ static void tpm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp)
+ {
+   TPM_RESULT res;
+-  
++
++  req->tag = (BYTE) req->tag;  // VIN HACK!!! 
++
+   /* setup authorisation as well as response tag and size */
+   memset(rsp, 0, sizeof(*rsp));
+   switch (req->tag) {
+@@ -3878,4 +3881,3 @@ int tpm_handle_command(const uint8_t *in
+   tpm_free(rsp.param);
+   return 0;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_crypto.c vtpm/tpm/tpm_crypto.c
+--- orig/tpm_emulator-0.2/tpm/tpm_crypto.c     2005-08-17 10:58:36.000000000 
-0700
++++ vtpm/tpm/tpm_crypto.c      2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+  *                    Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -106,7 +107,7 @@ TPM_RESULT tpm_sign(TPM_KEY_DATA *key, T
+     /* setup TPM_SIGN_INFO structure */
+     memcpy(&buf[0], "\x05\x00SIGN", 6);
+     memcpy(&buf[6], auth->nonceOdd.nonce, 20);
+-    *(UINT32*)&buf[26] = cpu_to_be32(areaToSignSize);
++    *(UINT32*)&buf[26] = CPU_TO_BE32(areaToSignSize);
+     memcpy(&buf[30], areaToSign, areaToSignSize);
+     if (rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1, 
+         buf, areaToSignSize + 30, *sig)) {
+@@ -379,4 +380,3 @@ TPM_RESULT TPM_CertifyKey2(TPM_KEY_HANDL
+   }  
+   return TPM_SUCCESS;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_data.c vtpm/tpm/tpm_data.c
+--- orig/tpm_emulator-0.2/tpm/tpm_data.c       2005-08-17 10:58:36.000000000 
-0700
++++ vtpm/tpm/tpm_data.c        2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+  *                    Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -15,9 +16,15 @@
+  * $Id: tpm_data.c 9 2005-04-26 18:15:31Z mast $
+  */
+ 
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <unistd.h>
++
+ #include "tpm_emulator.h"
+ #include "tpm_structures.h"
+ #include "tpm_marshalling.h"
++#include "vtpm_manager.h"
+ 
+ TPM_DATA tpmData;
+ 
+@@ -28,6 +35,7 @@ BOOL tpm_get_physical_presence(void)
+ 
+ void tpm_init_data(void)
+ {
++#ifndef TPM_GENERATE_EK
+   /* endorsement key */
+   uint8_t ek_n[] =  "\xa8\xdb\xa9\x42\xa8\xf3\xb8\x06\x85\x90\x76\x93\xad\xf7"
+     "\x74\xec\x3f\xd3\x3d\x9d\xe8\x2e\xff\x15\xed\x0e\xce\x5f\x93"
+@@ -66,6 +74,8 @@ void tpm_init_data(void)
+     "\xd1\xc0\x8b\x5b\xa2\x2e\xa7\x15\xca\x50\x75\x10\x48\x9c\x2b"
+     "\x18\xb9\x67\x8f\x5d\x64\xc3\x28\x9f\x2f\x16\x2f\x08\xda\x47"
+     "\xec\x86\x43\x0c\x80\x99\x07\x34\x0f";
++#endif
++
+   int i;
+   /* reset all data to NULL, FALSE or 0 */
+   memset(&tpmData, 0, sizeof(tpmData));
+@@ -85,6 +95,10 @@ void tpm_init_data(void)
+   tpmData.permanent.data.version.revMinor = VERSION_MINOR;
+   /* setup PCR attributes */
+   for (i = 0; i < TPM_NUM_PCR; i++) {
++    int j;
++    for (j=0; j < TPM_NUM_LOCALITY; j++) {
++      tpmData.permanent.data.pcrAttrib[i].pcrExtendLocal[j] = TRUE;
++    }
+     tpmData.permanent.data.pcrAttrib[i].pcrReset = TRUE;
+   }
+   /* set tick type */
+@@ -115,49 +129,235 @@ void tpm_release_data(void)
+ 
+ #ifdef TPM_STORE_TO_FILE
+ 
+-#include <linux/fs.h>
+-#include <linux/unistd.h>
+-#include <asm/uaccess.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++
++ static int vtpm_tx_fh=-1, vtpm_rx_fh=-1;
+ 
+-#define TPM_STORAGE_FILE "/var/tpm/tpm_emulator-1.2." STR(VERSION_MAJOR) "." 
STR(VERSION_MINOR) 
++#ifdef VTPM_MUTLI_VM
++ #define DEV_FE "/dev/tpm"
++#else
++ #define VTPM_RX_FIFO_D  "/var/vtpm/fifos/vtpm-to-%d.fifo"
++ #define VTPM_TX_FIFO  "/var/vtpm/fifos/vtpm-from-all.fifo"
++
++ extern int dmi_id;
++ static char *vtpm_rx_name=NULL; 
++#endif
+ 
+ static int write_to_file(uint8_t *data, size_t data_length)
+ {
+-  int res;
+-  struct file *fp;
+-  mm_segment_t old_fs = get_fs();
+-  fp = filp_open(TPM_STORAGE_FILE, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | 
S_IWUSR);
+-  if (IS_ERR(fp)) return -1;
+-  set_fs(get_ds());
+-  res = fp->f_op->write(fp, data, data_length, &fp->f_pos);
+-  set_fs(old_fs);
+-  filp_close(fp, NULL);
+-  return (res == data_length) ? 0 : -1;
++  int res, out_data_size, in_header_size;
++  BYTE *ptr, *out_data, *in_header;
++  UINT32 result, len, in_rsp_size;
++  UINT16 tag = VTPM_TAG_REQ;
++      
++  printf("Saving NVM\n");
++  if (vtpm_tx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++    vtpm_tx_fh = open(DEV_FE, O_RDWR);
++#else
++      vtpm_tx_fh = open(VTPM_TX_FIFO, O_WRONLY);
++#endif
++  }
++
++  if (vtpm_tx_fh < 0) {
++              return -1;
++  }
++ 
++  // Send request to VTPM Manager to encrypt data
++#ifdef VTPM_MUTLI_VM
++  out_data_size = len = VTPM_COMMAND_HEADER_SIZE_CLT + data_length;
++#else
++  out_data_size = len = VTPM_COMMAND_HEADER_SIZE_SRV + data_length;
++#endif
++  
++  out_data = ptr = (BYTE *) malloc(len);
++
++  if (ptr == NULL
++#ifndef VTPM_MUTLI_VM
++      || tpm_marshal_UINT32(&ptr, &len, dmi_id)
++#endif
++        || tpm_marshal_UINT16(&ptr, &len, tag)
++#ifdef VTPM_MUTLI_VM
++        || tpm_marshal_UINT32(&ptr, &len, out_data_size)
++#else
++        || tpm_marshal_UINT32(&ptr, &len, out_data_size - sizeof(uint32_t))
++#endif  
++        || tpm_marshal_UINT32(&ptr, &len, VTPM_ORD_SAVENVM)
++        || tpm_marshal_BYTE_ARRAY(&ptr, &len, data, data_length)) {
++      free(out_data);
++      return -1;
++  }
++  
++  printf("\tSending SaveNVM Command.\n");
++  res = write(vtpm_tx_fh, out_data, out_data_size);
++  free(out_data);
++  if (res != out_data_size) return -1;
++
++  if (vtpm_rx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++    vtpm_rx_fh = vtpm_tx_fh
++#else
++    if (vtpm_rx_name == NULL) {
++      vtpm_rx_name = malloc(10 + strlen(VTPM_RX_FIFO_D));
++      sprintf(vtpm_rx_name, VTPM_RX_FIFO_D, (uint32_t) dmi_id);
++    }
++      vtpm_rx_fh = open(vtpm_rx_name, O_RDONLY);
++#endif
++  }
++
++  if (vtpm_rx_fh < 0) {
++              return -1;
++  }
++  
++  // Read Header of response so we can get the size & status
++#ifdef VTPM_MUTLI_VM
++  in_header_size = len = VTPM_COMMAND_HEADER_SIZE_CLT;
++#else
++  in_header_size = len = VTPM_COMMAND_HEADER_SIZE_SRV;
++#endif
++  in_header = ptr = malloc(in_header_size);
++  
++  printf("\tReading SaveNVM header.\n");
++  res = read(vtpm_rx_fh, in_header, in_header_size);
++
++  if ( (res != in_header_size)
++#ifndef VTPM_MUTLI_VM
++       || tpm_unmarshal_UINT32(&ptr, &len, (UINT32*)&dmi_id)
++#endif
++         || tpm_unmarshal_UINT16(&ptr, &len, &tag)
++         || tpm_unmarshal_UINT32(&ptr, &len, &in_rsp_size)
++         || tpm_unmarshal_UINT32(&ptr, &len, &result) ) {
++        free(in_header);
++        return -1;
++  }
++  free(in_header);
++  
++  if (result != VTPM_SUCCESS) {
++      return -1;  
++  }
++
++#ifdef VTPM_MUTLI_VM
++  close(vtpm_tx_fh); close(vtpm_rx_fh);
++#endif
++        
++  printf("\tFinishing up SaveNVM\n");
++  return (0);
+ }
+ 
+ static int read_from_file(uint8_t **data, size_t *data_length)
+ {
+-  int res;
+-  struct file *fp;
+-  mm_segment_t old_fs = get_fs();
+-  fp = filp_open(TPM_STORAGE_FILE, O_RDONLY, 0);
+-  if (IS_ERR(fp)) return -1;
+-  *data_length = (size_t)fp->f_dentry->d_inode->i_size;
+-  /* *data_length = i_size_read(fp->f_dentry->d_inode); */
+-  *data = tpm_malloc(*data_length);
+-  if (*data == NULL) {
+-    filp_close(fp, NULL);
++  int res, out_data_size, in_header_size;
++  uint8_t *ptr, *out_data, *in_header;
++  UINT16 tag = VTPM_TAG_REQ;
++  UINT32 len, in_rsp_size, result;
++#ifdef VTPM_MUTLI_VM
++      int vtpm_rx_fh, vtpm_tx_fh;
++#endif
++      
++  printf("Loading NVM.\n");
++  if (vtpm_tx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++    vtpm_tx_fh = open(DEV_FE, O_RDWR);
++#else
++      vtpm_tx_fh = open(VTPM_TX_FIFO, O_WRONLY);
++#endif
++  }
++
++  if (vtpm_tx_fh < 0) {
++              return -1;
++  }
++ 
++  // Send request to VTPM Manager to encrypt data
++#ifdef VTPM_MUTLI_VM
++  out_data_size = len = VTPM_COMMAND_HEADER_SIZE_CLT;
++#else
++  out_data_size = len = VTPM_COMMAND_HEADER_SIZE_SRV;
++#endif
++  out_data = ptr = (BYTE *) malloc(len);
++
++  if (ptr == NULL
++#ifndef VTPM_MUTLI_VM
++      || tpm_marshal_UINT32(&ptr, &len, dmi_id)
++#endif  
++      || tpm_marshal_UINT16(&ptr, &len, tag)
++#ifdef VTPM_MUTLI_VM
++      || tpm_marshal_UINT32(&ptr, &len, out_data_size)
++#else
++      || tpm_marshal_UINT32(&ptr, &len, out_data_size - sizeof(uint32_t))
++#endif
++      || tpm_marshal_UINT32(&ptr, &len, VTPM_ORD_LOADNVM)) {
++    free(out_data);
+     return -1;
+   }
+-  set_fs(get_ds());
+-  res = fp->f_op->read(fp, *data, *data_length, &fp->f_pos);
+-  set_fs(old_fs);
+-  filp_close(fp, NULL);
++
++  printf("\tSending LoadNVM command\n");
++  res = write(vtpm_tx_fh, out_data, out_data_size);
++  free(out_data);
++  if (res != out_data_size) return -1;
++
++    if (vtpm_rx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++    vtpm_rx_fh = vtpm_tx_fh;
++#else
++    if (vtpm_rx_name == NULL) {
++      vtpm_rx_name = malloc(10 + strlen(VTPM_RX_FIFO_D));
++      sprintf(vtpm_rx_name, VTPM_RX_FIFO_D, (uint32_t) dmi_id);
++    }
++      vtpm_rx_fh = open(vtpm_rx_name, O_RDONLY);
++#endif
++  }
++
++  if (vtpm_rx_fh < 0) {
++              return -1;
++  }
++  
++  // Read Header of response so we can get the size & status
++#ifdef VTPM_MUTLI_VM
++  in_header_size = len = VTPM_COMMAND_HEADER_SIZE_CLT;
++#else
++  in_header_size = len = VTPM_COMMAND_HEADER_SIZE_SRV;
++#endif
++  in_header = ptr = malloc(in_header_size);
++  
++  printf("\tReading LoadNVM header\n");
++  res = read(vtpm_rx_fh, in_header, in_header_size);
++
++  if ( (res != in_header_size)
++#ifndef VTPM_MUTLI_VM
++       || tpm_unmarshal_UINT32(&ptr, &len, (UINT32*)&dmi_id)
++#endif
++       || tpm_unmarshal_UINT16(&ptr, &len, &tag)
++       || tpm_unmarshal_UINT32(&ptr, &len, &in_rsp_size)
++       || tpm_unmarshal_UINT32(&ptr, &len, &result) ) {
++      free(in_header);
++      return -1;
++  }
++  free(in_header);
++  
++  if (result != VTPM_SUCCESS) {
++      return -1;  
++  }
++
++  // Read Encrypted data from VTPM Manager
++  *data_length = in_rsp_size - VTPM_COMMAND_HEADER_SIZE_CLT;
++  *data = (uint8_t *) malloc(*data_length);
++
++  printf("\tReading clear data from LoadNVM.\n");
++  res = read(vtpm_rx_fh, *data, *data_length);
++#ifdef VTPM_MUTLI_VM
++  close(vtpm_rx_fh);close(vtpm_tx_fh);
++#endif 
++      
++  printf("\tReturing from loading NVM\n");
+   if (res != *data_length) {
+-    tpm_free(*data);
+-    return -1;
++      free(*data);
++      return -1;
++  } else {
++      return 0;
+   }
+-  return 0;
++
+ }
+ 
+ #else
+@@ -231,7 +431,6 @@ int tpm_restore_permanent_data(void)
+ 
+ int tpm_erase_permanent_data(void)
+ {
+-  int res = write_to_file("", 0);
++  int res = write_to_file((uint8_t*)"", 0);
+   return res;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_deprecated.c vtpm/tpm/tpm_deprecated.c
+--- orig/tpm_emulator-0.2/tpm/tpm_deprecated.c 2005-08-17 10:58:36.000000000 
-0700
++++ vtpm/tpm/tpm_deprecated.c  2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+  *                    Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -50,7 +51,7 @@ TPM_RESULT TPM_SaveKeyContext(TPM_KEY_HA
+   BYTE *ptr;
+   UINT32 len;
+   info("TPM_SaveKeyContext()");
+-  res = TPM_SaveContext(keyHandle, TPM_RT_KEY, "SaveKeyContext..", 
++  res = TPM_SaveContext(keyHandle, TPM_RT_KEY, (BYTE*)"SaveKeyContext..", 
+                         keyContextSize, &contextBlob);
+   if (res != TPM_SUCCESS) return res;
+   len = *keyContextSize;
+@@ -82,7 +83,7 @@ TPM_RESULT TPM_SaveAuthContext(TPM_AUTHH
+   BYTE *ptr;
+   UINT32 len;
+   info("TPM_SaveAuthContext()");
+-  res = TPM_SaveContext(authHandle, TPM_RT_KEY, "SaveAuthContext.", 
++  res = TPM_SaveContext(authHandle, TPM_RT_KEY, (BYTE*)"SaveAuthContext.", 
+                         authContextSize, &contextBlob);
+   if (res != TPM_SUCCESS) return res;
+   len = *authContextSize;
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_emulator.h vtpm/tpm/tpm_emulator.h
+--- orig/tpm_emulator-0.2/tpm/tpm_emulator.h   2005-08-17 10:58:36.000000000 
-0700
++++ vtpm/tpm/tpm_emulator.h    2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -22,7 +23,8 @@
+ /* TPM configuration */
+ #define TPM_STORE_TO_FILE       1
+ #undef  TPM_STRONG_PERSISTENCE
+-#undef  TPM_GENERATE_EK
++//#undef  TPM_GENERATE_EK
++#define  TPM_GENERATE_EK
+ 
+ /**
+  * tpm_emulator_init - initialises and starts the TPM emulator
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_integrity.c vtpm/tpm/tpm_integrity.c
+--- orig/tpm_emulator-0.2/tpm/tpm_integrity.c  2005-08-17 10:58:36.000000000 
-0700
++++ vtpm/tpm/tpm_integrity.c   2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+  *                    Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -194,4 +195,3 @@ TPM_RESULT tpm_verify_pcr(TPM_KEY_DATA *
+   }
+   return TPM_SUCCESS;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_structures.h vtpm/tpm/tpm_structures.h
+--- orig/tpm_emulator-0.2/tpm/tpm_structures.h 2005-08-17 10:58:36.000000000 
-0700
++++ vtpm/tpm/tpm_structures.h  2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+  *                    Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -18,7 +19,7 @@
+ #ifndef _TPM_STRUCTURES_H_
+ #define _TPM_STRUCTURES_H_
+ 
+-#include <linux/types.h>
++//#include <linux/types.h>
+ #include "crypto/rsa.h"
+ 
+ /*
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_testing.c vtpm/tpm/tpm_testing.c
+--- orig/tpm_emulator-0.2/tpm/tpm_testing.c    2005-08-17 10:58:36.000000000 
-0700
++++ vtpm/tpm/tpm_testing.c     2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+  *                    Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -95,24 +96,24 @@ static int tpm_test_sha1(void)
+   struct {
+     uint8_t *data; uint32_t repetitions; uint8_t *digest;
+   } test_cases[] =  {{
+-    "abc", 1,
+-    
"\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D"
++      (uint8_t*)"abc", 1,
++    
(uint8_t*)"\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D"
+   }, {
+-    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
+-    
"\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1"
++    (uint8_t*)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
++    
(uint8_t*)"\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1"
+   }, {
+-    "a", 1000000,
+-    
"\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F"
++    (uint8_t*)"a", 1000000,
++    
(uint8_t*)"\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F"
+   }, {
+-    "0123456701234567012345670123456701234567012345670123456701234567", 10,
+-    
"\xDE\xA3\x56\xA2\xCD\xDD\x90\xC7\xA7\xEC\xED\xC5\xEB\xB5\x63\x93\x4F\x46\x04\x52"
++    
(uint8_t*)"0123456701234567012345670123456701234567012345670123456701234567", 
10,
++    
(uint8_t*)"\xDE\xA3\x56\xA2\xCD\xDD\x90\xC7\xA7\xEC\xED\xC5\xEB\xB5\x63\x93\x4F\x46\x04\x52"
+   }};
+ 
+   debug("tpm_test_sha1()");
+   for (i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {
+     sha1_init(&ctx);
+     for (j = 0; j < test_cases[i].repetitions; j++)
+-      sha1_update(&ctx, test_cases[i].data, strlen(test_cases[i].data));
++      sha1_update(&ctx, test_cases[i].data, 
strlen((char*)test_cases[i].data));
+     sha1_final(&ctx, digest);
+     if (memcmp(digest, test_cases[i].digest, SHA1_DIGEST_LENGTH) != 0) return 
-1;
+   }
+@@ -128,41 +129,41 @@ static int tpm_test_hmac(void)
+   struct {
+     uint8_t *key, key_len, *data, data_len, *digest;
+   } test_cases[] = {{
+-    "\x0b", 20, "Hi There", 8,
+-    
"\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00"
++    (uint8_t*)"\x0b", 20, (uint8_t*)"Hi There", 8,
++    
(uint8_t*)"\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00"
+   }, {
+-    "Jefe", 4, "what do ya want for nothing?", 28,
+-    
"\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79"
++    (uint8_t*)"Jefe", 4, (uint8_t*)"what do ya want for nothing?", 28,
++    
(uint8_t*)"\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79"
+   }, {
+-    "\xaa", 20, "\xdd", 50,
+-    
"\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3"
++    (uint8_t*)"\xaa", 20, (uint8_t*)"\xdd", 50,
++    
(uint8_t*)"\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3"
+   }, {
+-    
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
+-    "\x15\x16\x17\x18\x19", 25, "\xcd", 50,
+-    
"\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda"
++    
(uint8_t*)"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
++    "\x15\x16\x17\x18\x19", 25, (uint8_t*)"\xcd", 50,
++    
(uint8_t*)"\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda"
+   }, {
+-    "\x0c", 20, "Test With Truncation", 20,
+-    
"\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04"
++    (uint8_t*)"\x0c", 20, (uint8_t*)"Test With Truncation", 20,
++    
(uint8_t*)"\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04"
+   }, {
+-    "\xaa", 80, "Test Using Larger Than Block-Size Key - Hash Key First", 54,
+-    
"\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12"
++    (uint8_t*)"\xaa", 80, (uint8_t*)"Test Using Larger Than Block-Size Key - 
Hash Key First", 54,
++    
(uint8_t*)"\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12"
+   }, {
+-    "\xaa", 80,
+-    "Test Using Larger Than Block-Size Key and Larger Than One Block-Size 
Data", 73,
+-    
"\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91"
++    (uint8_t*)"\xaa", 80,
++    (uint8_t*)"Test Using Larger Than Block-Size Key and Larger Than One 
Block-Size Data", 73,
++    
(uint8_t*)"\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91"
+   }};
+ 
+   debug("tpm_test_hmac()");
+   for (i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {
+-    if (strlen(test_cases[i].key) < test_cases[i].key_len) {
++    if (strlen((char*)test_cases[i].key) < test_cases[i].key_len) {
+       uint8_t key[test_cases[i].key_len];
+       memset(key, test_cases[i].key[0], test_cases[i].key_len);
+       hmac_init(&ctx, key, test_cases[i].key_len);
+     } else {
+       hmac_init(&ctx, test_cases[i].key, test_cases[i].key_len);
+     }
+-    for (j = 0; j < test_cases[i].data_len; j += strlen(test_cases[i].data)) {
+-      hmac_update(&ctx, test_cases[i].data, strlen(test_cases[i].data));
++    for (j = 0; j < test_cases[i].data_len; j += 
strlen((char*)test_cases[i].data)) {
++      hmac_update(&ctx, test_cases[i].data, 
strlen((char*)test_cases[i].data));
+     }
+     hmac_final(&ctx, digest);
+     if (memcmp(digest, test_cases[i].digest, SHA1_DIGEST_LENGTH) != 0) return 
-1;
+@@ -173,9 +174,9 @@ static int tpm_test_hmac(void)
+ static int tpm_test_rsa_EK(void)
+ {
+   int res = 0;
+-  char *data = "RSA PKCS #1 v1.5 Test-String";
++  uint8_t *data = (uint8_t*)"RSA PKCS #1 v1.5 Test-String";
+   uint8_t buf[256];
+-  size_t buf_len, data_len = strlen(data);
++  size_t buf_len, data_len = strlen((char*)data);
+   rsa_private_key_t priv_key;
+   rsa_public_key_t pub_key;
+ 
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_ticks.c vtpm/tpm/tpm_ticks.c
+--- orig/tpm_emulator-0.2/tpm/tpm_ticks.c      2005-08-17 10:58:36.000000000 
-0700
++++ vtpm/tpm/tpm_ticks.c       2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+  * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+  *                    Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+  *
+  * This module is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published
+@@ -37,9 +38,7 @@ TPM_RESULT TPM_SetTickType(TPM_TICKTYPE 
+ TPM_RESULT TPM_GetTicks(TPM_CURRENT_TICKS *currentTime)
+ {
+   info("TPM_GetTicks()");
+-  memcpy(currentTime, &tpmData.stany.data.currentTicks, 
+-    sizeof(TPM_CURRENT_TICKS));
+-  return TPM_SUCCESS;
++  return TPM_DISABLED_CMD;
+ }
+ 
+ TPM_RESULT TPM_TickStampBlob(TPM_KEY_HANDLE keyHandle, TPM_NONCE *antiReplay,
+@@ -47,61 +46,12 @@ TPM_RESULT TPM_TickStampBlob(TPM_KEY_HAN
+                              TPM_CURRENT_TICKS *currentTicks, 
+                              UINT32 *sigSize, BYTE **sig)
+ {
+-  TPM_RESULT res;
+-  TPM_KEY_DATA *key;
+-  BYTE *info, *p;
+-  UINT32 info_length, length;
+   info("TPM_TickStampBlob()");
+-  /* get key */
+-  key = tpm_get_key(keyHandle);
+-  if (key == NULL) return TPM_INVALID_KEYHANDLE;
+-  /* verify authorization */ 
+-  res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);
+-  if (res != TPM_SUCCESS) return res;
+-  if (key->keyUsage != TPM_KEY_SIGNING && key->keyUsage != TPM_KEY_LEGACY
+-      && key->keyUsage != TPM_KEY_IDENTITY) return TPM_INVALID_KEYUSAGE;
+-  /* get current ticks */
+-  TPM_GetTicks(currentTicks);
+-  /* sign data using signature scheme PKCS1_SHA1 and TPM_SIGN_INFO container 
*/
+-  *sigSize = key->key.size >> 3;
+-  *sig = tpm_malloc(*sigSize);
+-  if (*sig == NULL) return TPM_FAIL; 
+-  /* setup TPM_SIGN_INFO structure */
+-  info_length = 30 + sizeof(TPM_DIGEST) + 
sizeof_TPM_CURRENT_TICKS(currentTicks);
+-  info = tpm_malloc(info_length);
+-  if (info == NULL) {
+-    tpm_free(*sig);
+-    return TPM_FAIL;
+-  }
+-  memcpy(&info[0], "\x05\x00TSTP", 6);
+-  memcpy(&info[6], antiReplay->nonce, 20);
+-  *(UINT32*)&info[26] = cpu_to_be32(20
+-                        + sizeof_TPM_CURRENT_TICKS(currentTicks));
+-  memcpy(&info[30], digestToStamp->digest, sizeof(TPM_DIGEST));
+-  p = &info[30 + sizeof(TPM_DIGEST)]; 
+-  length = sizeof_TPM_CURRENT_TICKS(currentTicks);
+-  if (tpm_marshal_TPM_CURRENT_TICKS(&p, &length, currentTicks)
+-      || rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1, info, info_length, *sig)) {  
 
+-    tpm_free(*sig);
+-    tpm_free(info);
+-    return TPM_FAIL;
+-  } 
+-  return TPM_SUCCESS;
++  return TPM_DISABLED_CMD;
+ }
+ 
+ void tpm_update_ticks(void)
+ {
+-  if (tpmData.stany.data.currentTicks.tag == 0) {
+-    tpmData.stany.data.currentTicks.tag = TPM_TAG_CURRENT_TICKS;
+-    tpmData.stany.data.currentTicks.currentTicks += tpm_get_ticks();
+-    tpmData.stany.data.currentTicks.tickType = 
tpmData.permanent.data.tickType;
+-    tpm_get_random_bytes(tpmData.stany.data.currentTicks.tickNonce.nonce, 
+-      sizeof(TPM_NONCE));
+-    tpmData.stany.data.currentTicks.tickRate = 1;
+-    tpmData.stany.data.currentTicks.tickSecurity = TICK_SEC_NO_CHECK;
+-  } else {
+-    tpmData.stany.data.currentTicks.currentTicks += tpm_get_ticks();   
+-  }
+ }
+   
+ 
+diff -uprN orig/tpm_emulator-0.2/tpm/vtpm_manager.h vtpm/tpm/vtpm_manager.h
+--- orig/tpm_emulator-0.2/tpm/vtpm_manager.h   1969-12-31 16:00:00.000000000 
-0800
++++ vtpm/tpm/vtpm_manager.h    2005-08-17 10:55:52.000000000 -0700
+@@ -0,0 +1,126 @@
++// ===================================================================
++// 
++// Copyright (c) 2005, Intel Corp.
++// All rights reserved.
++//
++// Redistribution and use in source and binary forms, with or without 
++// modification, are permitted provided that the following conditions 
++// are met:
++//
++//   * Redistributions of source code must retain the above copyright 
++//     notice, this list of conditions and the following disclaimer.
++//   * Redistributions in binary form must reproduce the above 
++//     copyright notice, this list of conditions and the following 
++//     disclaimer in the documentation and/or other materials provided 
++//     with the distribution.
++//   * Neither the name of Intel Corporation nor the names of its 
++//     contributors may be used to endorse or promote products derived
++//     from this software without specific prior written permission.
++//
++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
++// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
++// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
++// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
++// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
++// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
++// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++// OF THE POSSIBILITY OF SUCH DAMAGE.
++// ===================================================================
++// 
++// vtpm_manager.h
++// 
++//  Public Interface header for VTPM Manager
++//
++// ==================================================================
++
++#ifndef __VTPM_MANAGER_H__
++#define __VTPM_MANAGER_H__
++
++#define VTPM_TAG_REQ 0x01c1
++#define VTPM_TAG_RSP 0x01c4
++#define COMMAND_BUFFER_SIZE 4096
++
++// Header sizes. Note Header MAY include the DMI
++#define VTPM_COMMAND_HEADER_SIZE_SRV ( sizeof(UINT32) + sizeof(TPM_TAG) + 
sizeof(UINT32) + sizeof(TPM_COMMAND_CODE))
++#define VTPM_COMMAND_HEADER_SIZE_CLT (                  sizeof(TPM_TAG) + 
sizeof(UINT32) + sizeof(TPM_COMMAND_CODE))
++
++//************************ Command Codes ****************************
++#define VTPM_ORD_OPEN              1   // ULM Creates New DMI
++#define VTPM_ORD_CLOSE             2   // ULM Closes a DMI
++#define VTPM_ORD_DELETE            3   // ULM Permemently Deletes DMI
++#define VTPM_ORD_SAVENVM          4   // DMI requests Secrets Unseal
++#define VTPM_ORD_LOADNVM          5   // DMI requests Secrets Saved
++#define VTPM_ORD_TPMCOMMAND       6   // DMI issues HW TPM Command
++
++//************************ Return Codes ****************************
++#define VTPM_SUCCESS               0
++#define VTPM_FAIL                  1
++#define VTPM_UNSUPPORTED           2
++#define VTPM_FORBIDDEN             3
++#define VTPM_RESTORE_CONTEXT_FAILED    4
++#define VTPM_INVALID_REQUEST       5
++
++/******************* Command Parameter API *************************
++
++VTPM Command Format
++  dmi: 4 bytes                  // Source of message. 
++                                // WARNING: This is prepended by the channel. 
++                                // Thus it is received by VTPM Manager, 
++                                // but not sent by DMI
++  tpm tag: 2 bytes
++  command size: 4 bytes         // Size of command including header but not 
DMI
++  ord: 4 bytes                  // Command ordinal above
++  parameters: size - 10 bytes   // Command Parameter
++
++VTPM Response Format
++  tpm tag: 2 bytes
++  response_size: 4 bytes
++  status: 4 bytes         
++  parameters: size - 10 bytes
++
++
++VTPM_Open:
++  Input Parameters:
++    Domain_type: 1 byte
++    domain_id: 4 bytes
++    instance_id: 4 bytes
++  Output Parameters:
++    None
++    
++VTPM_Close
++  Input Parameters:
++    instance_id: 4 bytes
++  Output Parameters:
++    None
++
++VTPM_Delete
++  Input Parameters:
++    instance_id: 4 bytes
++  Output Parameters:
++    None
++
++VTPM_SaveNVM
++  Input Parameters:
++    data: n bytes (Header indicates size of data)
++  Output Parameters:
++    None
++
++VTPM_LoadNVM
++  Input Parameters:
++    None
++  Output Parameters:
++    data: n bytes (Header indicates size of data)
++
++VTPM_TPMCommand
++  Input Parameters:
++    TPM Command Byte Stream: n bytes 
++  Output Parameters:
++    TPM Reponse Byte Stream: n bytes 
++
++*********************************************************************/
++
++#endif //_VTPM_MANAGER_H_
+diff -uprN orig/tpm_emulator-0.2/tpmd.c vtpm/tpmd.c
+--- orig/tpm_emulator-0.2/tpmd.c       1969-12-31 16:00:00.000000000 -0800
++++ vtpm/tpmd.c        2005-08-17 10:55:52.000000000 -0700
+@@ -0,0 +1,207 @@
++/* Software-Based Trusted Platform Module (TPM) Emulator for Linux
++ * Copyright (C) 2005 INTEL Corp
++ *
++ * This module is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published
++ * by the Free Software Foundation; either version 2 of the License,
++ * or (at your option) any later version.
++ *
++ * This module is distributed in the hope that 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.
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <sys/time.h>
++
++#include "tpm_emulator.h"
++#include "vtpm_manager.h"
++
++#ifdef VTPM_MULTI_VM
++ #define DEV_BE "/dev/vtpm"
++#else
++ #define GUEST_RX_FIFO_D "/var/vtpm/fifos/guest-to-%d.fifo"
++ #define GUEST_TX_FIFO "/var/vtpm/fifos/guest-from-all.fifo"
++
++ int dmi_id;
++#endif
++                                              
++#define BUFFER_SIZE 2048
++
++static uint8_t ctrl_msg[] = { 0, 0, 0, 0,   // destination
++                              1, 193,       // VTPM_TAG
++                              0, 0, 0, 10,  // Size
++                              0, 0, 0, 0};  // TPM_SUCCESS
++                            
++
++static int devurandom=0;
++
++        
++void get_random_bytes(void *buf, int nbytes) {
++  
++  if (devurandom == 0) {
++    devurandom = open("/dev/urandom", O_RDONLY);
++  }
++
++  if (read(devurandom, buf, nbytes) != nbytes) {
++      printf("Can't get random number.\n");
++      exit(-1);
++  }
++}
++
++uint64_t tpm_get_ticks(void)
++{
++  //struct timeval tv;
++  //int gettimeofday(&tv, struct timezone *tz);
++  return 0;
++}
++
++int main(int argc, char **argv)
++{
++  uint8_t in[BUFFER_SIZE], *out, *addressed_out;
++  uint32_t out_size;
++  int in_size, written ;
++  int i, guest_id=-1;
++ 
++  int vtpm_tx_fh=-1, vtpm_rx_fh=-1;
++#ifdef VTPM_MULTI_VM
++  if (argc < 2) {
++    printf("Usage: tpmd clear|save|deactivated\n" );
++#else
++  if (argc < 3) {
++    printf("Usage: tpmd clear|save|deactivated vtpmid\n" );
++#endif
++        return -1;
++  }
++
++#ifndef VTPM_MULTI_VM
++  dmi_id = atoi(argv[2]);
++#endif
++
++  /* initialize TPM emulator */
++  if (!strcmp(argv[1], "clear")) {
++    printf("Initializing tpm: %s\n", argv[1]);
++    tpm_emulator_init(1);
++  } else if (!strcmp(argv[1], "save")) { 
++    printf("Initializing tpm: %s\n", argv[1]);
++    tpm_emulator_init(2);
++  } else if (!strcmp(argv[1], "deactivated")) {
++    printf("Initializing tpm: %s\n", argv[1]);
++    tpm_emulator_init(3);
++  } else {
++    printf("invalid startup mode '%s'; must be 'clear', "
++      "'save' (default) or 'deactivated", argv[1]);
++    return -1;
++  }
++
++  char *guest_rx_file = malloc(10 + strlen(GUEST_RX_FIFO_D));
++  sprintf(guest_rx_file, GUEST_RX_FIFO_D, (uint32_t) dmi_id);
++  
++  while (1) {
++abort_command:
++    if (vtpm_rx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++        vtpm_rx_fh = open(DEV_BE, O_RDWR);
++#else
++      vtpm_rx_fh = open(guest_rx_file, O_RDONLY);
++#endif
++    }
++    
++    if (vtpm_rx_fh < 0) {
++      printf("ERROR: failed to open devices to listen to guest.\n");
++      return -1;
++    }
++    
++    in_size = read(vtpm_rx_fh, in, BUFFER_SIZE);
++    if (in_size < 6) { // Magic size of minium TPM command
++      printf("Recv[%d] to small: 0x", in_size);
++      if (in_size <= 0) {
++          close(vtpm_rx_fh);
++          vtpm_rx_fh = -1;
++          goto abort_command;
++      }
++    } else { 
++      printf("Recv[%d]: 0x", in_size);
++      for (i=0; i< in_size; i++) 
++        printf("%x ", in[i]);
++      printf("\n");
++    }
++
++    if (guest_id == -1) {
++        guest_id = *((uint32_t *) in);
++        *((uint32_t *) ctrl_msg) = *((uint32_t *) in);
++    } else {
++        if (guest_id != *((uint32_t *) in) ) {
++            printf("WARNING: More than one guest attached\n");
++        }
++    }
++
++    if (vtpm_tx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++        vtpm_tx_fh = open(DEV_BE, O_RDWR);
++        vtpm_rx_fh = vtpm_tx_fh;
++#else
++      vtpm_tx_fh = open(GUEST_TX_FIFO, O_WRONLY);
++#endif
++    }
++
++    if (vtpm_tx_fh < 0) {
++      printf("ERROR: failed to open devices to respond to guest.\n");
++      return -1;
++    }
++    
++    // Handle command, but we need to skip the identifier
++    if (  BE16_TO_CPU( ((uint16_t *) in)[2] ) == VTPM_TAG_REQ ) { // Control 
message from xend
++      // This DM doesn't really care about ctrl messages. Just ACK the message
++      written = write(vtpm_tx_fh, ctrl_msg, sizeof(ctrl_msg));
++
++      if (written != sizeof(ctrl_msg)) {
++        printf("ERROR: Part of response not written %d/%d.\n", written, 
sizeof(ctrl_msg));
++      } else {
++        printf("Send Ctrl Message confermation\n");
++      }
++    } else { // Message from Guest
++      if (tpm_handle_command(in + sizeof(uint32_t), in_size - 
sizeof(uint32_t), &out, &out_size) != 0) { 
++        printf("ERROR: Handler Failed.\n");
++      }
++
++      addressed_out = (uint8_t *) tpm_malloc(sizeof(uint32_t) + out_size);
++      *(uint32_t *) addressed_out = *(uint32_t *) in;
++      memcpy(addressed_out + sizeof(uint32_t), out, out_size);
++
++      written = write(vtpm_tx_fh, addressed_out, out_size + sizeof(uint32_t));
++
++      if (written != out_size + sizeof(uint32_t)) {
++        printf("ERROR: Part of response not written %d/%d.\n", written, 
out_size);
++        for (i=0; i< out_size+ sizeof(uint32_t); i++)
++          printf("%x ", addressed_out[i]);
++        printf("\n");
++      } else {
++        printf("Sent[%d]: ", out_size + sizeof(uint32_t));
++        for (i=0; i< out_size+ sizeof(uint32_t); i++)
++          printf("%x ", addressed_out[i]);
++        printf("\n");
++      }
++      tpm_free(out);
++      tpm_free(addressed_out);
++    }
++
++  } // loop
++
++  tpm_emulator_shutdown();
++
++  close(vtpm_tx_fh);
++#ifndef VTPM_MUTLI_VM
++  close(vtpm_rx_fh);
++  free (guest_rx_file);
++#endif
++
++}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/COPYING
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/COPYING        Fri Sep  9 16:30:54 2005
@@ -0,0 +1,32 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/Makefile
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/Makefile       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,31 @@
+XEN_ROOT = ../..
+
+# Base definitions and rules
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+SUBDIRS                = crypto tcs util manager
+
+all: build
+
+build:
+       @set -e; for subdir in $(SUBDIRS); do \
+               $(MAKE) -C $$subdir $@; \
+       done
+
+install: build
+       @set -e; for subdir in $(SUBDIRS); do \
+               $(MAKE) -C $$subdir $@; \
+       done
+
+clean:
+       @set -e; for subdir in $(SUBDIRS); do \
+               $(MAKE) -C $$subdir $@; \
+       done
+
+
+mrproper:
+       @set -e; for subdir in $(SUBDIRS); do \
+               $(MAKE) -C $$subdir $@; \
+       done
+
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/README
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/README Fri Sep  9 16:30:54 2005
@@ -0,0 +1,89 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above
+//     copyright notice, this list of conditions and the following
+//     disclaimer in the documentation and/or other materials provided
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+Directory Structure
+===================
+tools/vtpm_manager/crypto    -> crypto files
+tools/vtpm_manager/TCS       -> TCS implementation
+tools/vtpm_manager/util      -> Utility Library. Include disk-io and buffers.
+tools/vtpm_manager/manager   -> VTPM Manager
+
+Compile Flags
+===================
+LOGGING_MODULES              -> How extensive logging happens
+                                see util/log.h for more info
+
+VTPM_MULTI_VM                -> Defined: VTPMs run in their own VMs
+                                Not Defined (default): VTPMs are processes
+
+# Debugging flags that may disappear without notice in the future
+
+DUMMY_BACKEND                -> vtpm_manager listens on /tmp/in.fifo and 
+                                /tmp/out.fifo rather than backend
+
+MANUAL_DM_LAUNCH             -> User must manually launch & kill VTPMs
+
+USE_FIXED_SRK_AUTH           -> Do not randomly generate a random SRK & Owner 
auth
+
+Requirements
+============
+- xen-unstable 
+- IBM frontend/backend vtpm driver patch
+
+Single-VM Flow
+============================
+- Launch the VTPM manager (vtpm_managerd) which which begins listening to the 
BE with one thread
+  and listens to a named fifo that is shared by the vtpms to commuincate with 
the manager.
+- VTPM Manager listens to TPM BE.
+- When xend launches a tpm frontend equipped VM it contacts the manager over 
the vtpm backend. 
+- When the manager receives the open message from the BE, it launches a vtpm
+- Xend allows the VM to continue booting. 
+- When a TPM request is issued to the front end, the front end transmits the 
TPM request to the backend.
+- The manager receives the TPM requests and uses a named fifo to forward the 
request to the vtpm.
+- The fifo listener begins listening for the reply from vtpm for the request.
+- Vtpm processes request and replies to manager over shared named fifo.
+- If needed, the vtpm may send a request to the vtpm_manager at any time to 
save it's secrets to disk.
+- Manager receives response from vtpm and passes it back to backend for 
forwarding to guest.
+
+NOTES:
+* SaveService SHOULD seal it's table before saving it to disk. However,
+  the current Xen infrastructure does not provide a mechanism for this to be
+  unsealed later. Specifically, the auth and wrapped key must be available ONLY
+  to the service, or it's not even worth encrypting
+
+  In the future the vtpm manager will be protected by an early boot mechanism
+  that will allow for better protection of it's data.
+
+TODO:
+- Timeout on crashed vtpms
+- create lock for shared fifo for talking to vtpms.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/Rules.mk
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/Rules.mk       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,68 @@
+# Base definitions and rules (XEN_ROOT must be defined in including Makefile)
+include $(XEN_ROOT)/tools/Rules.mk
+
+#
+# Tool definitions
+#
+
+# Installation program and options
+INSTALL         = install
+INSTALL_PROG    = $(INSTALL) -m0755
+INSTALL_DIR     = $(INSTALL) -d -m0755
+
+# Xen tools installation directory
+TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin
+
+# General compiler flags
+CFLAGS = -Wall -Werror -g3 -I.
+
+# For generating dependencies
+CFLAGS += -Wp,-MD,.$(@F).d
+
+DEP_FILES      = .*.d
+
+# Generic project files
+HDRS   = $(wildcard *.h)
+SRCS   = $(wildcard *.c)
+OBJS   = $(patsubst %.c,%.o,$(SRCS))
+
+# Generic (non-header) dependencies
+$(SRCS): Makefile $(XEN_ROOT)/tools/Rules.mk 
$(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+$(OBJS): $(SRCS)
+
+-include $(DEP_FILES)
+
+# Make sure these are just rules
+.PHONY : all build install clean
+
+#
+# Project-specific definitions
+#
+
+# Logging Level. See utils/tools.h for usage
+CFLAGS += 
-DLOGGING_MODULES="(BITMASK(VTPM_LOG_TCS)|BITMASK(VTPM_LOG_VTSP)|BITMASK(VTPM_LOG_VTPM)|BITMASK(VTPM_LOG_VTPM_DEEP))"
+
+# Silent Mode
+#CFLAGS += -DLOGGING_MODULES=0x0
+#CFLAGS += -DLOGGING_MODULES=0xff
+
+# Use frontend/backend pairs between manager & DMs?
+#CFLAGS += -DVTPM_MULTI_VM
+
+# vtpm_manager listens on /tmp/in.fifo and /tmp/out.fifo rather than backend
+#CFLAGS += -DDUMMY_BACKEND
+
+# Do not have manager launch DMs.
+#CFLAGS += -DMANUAL_DM_LAUNCH
+
+# Fixed SRK
+CFLAGS += -DUSE_FIXED_SRK_AUTH
+
+# TPM Hardware Device or TPM Simulator
+#CFLAGS += -DTPM_HWDEV
+
+# Include
+CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/crypto
+CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/util
+CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/tcs
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/crypto/Makefile
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/crypto/Makefile        Fri Sep  9 16:30:54 2005
@@ -0,0 +1,18 @@
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+BIN            = libtcpaCrypto.a
+
+all: build
+
+build: $(BIN)
+
+install: build
+
+clean:
+       rm -f *.a *.so *.o *.rpm $(DEP_FILES)
+
+mrproper: clean
+
+$(BIN): $(OBJS)
+       $(AR) rcs $(BIN) $(OBJS)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/crypto/crypto.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/crypto/crypto.c        Fri Sep  9 16:30:54 2005
@@ -0,0 +1,88 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// crypto.c
+// 
+//  This file will handle all the TPM Crypto functionality
+// 
+// ==================================================================
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include "crypto.h"
+#include "log.h"
+
+/**
+ * Initialize cryptography library
+ * @rand: random seed
+ * @size: size of @rand
+ */
+void Crypto_Init(const BYTE* rand, int size) {
+       ERR_load_crypto_strings();
+  CRYPTO_malloc_init();
+  OpenSSL_add_all_algorithms();
+  SYM_CIPHER = EVP_aes_128_cbc();
+  RAND_poll();
+  if (rand == NULL)
+    return;
+
+  RAND_add(rand, size, size);
+}
+
+/**
+ * Shutdown cryptography library
+ */
+void Crypto_Exit() {
+  ERR_free_strings();
+  ERR_remove_state(0);
+  EVP_cleanup();
+}
+
+
+/**
+ * Get random data
+ * @data: (OUT) Random data
+ * @size: Size of @data
+ */
+void Crypto_GetRandom(void* data, int size) {
+  int result;
+  
+  result = RAND_pseudo_bytes((BYTE*) data, size);
+  
+  if (result <= 0) 
+    vtpmlogerror (VTPM_LOG_CRYPTO, "RAND_pseudo_bytes failed: %s\n",
+            ERR_error_string (ERR_get_error(), NULL));
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/crypto/crypto.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/crypto/crypto.h        Fri Sep  9 16:30:54 2005
@@ -0,0 +1,175 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// crypto.h
+// 
+//  This file defines the TPM Crypto API
+//
+// ==================================================================
+
+#ifndef __CRYPTO_H__
+#define __CRYPTO_H__
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "tcg.h"
+#include "sym_crypto.h"
+
+#define CRYPTO_MAX_SIG_SIZE (2048 / 8)
+#define CRYPTO_MAX_RSA_KEY_SIZE (4096 / 8) //in bytes
+
+#define OAEP_P "TCPA"
+#define OAEP_P_SIZE 4
+
+// Algorithms supported by crypto. Stored in CRYPTO_INFO.algorithmID
+#define CRYPTO_ALGORITH_RSA 0x01
+
+// Supported Encryption Schemes CRYPTO_INFO.encScheme
+#define CRYPTO_ES_NONE 0x0001
+#define CRYPTO_ES_RSAESPKCSv15 0x0002
+#define CRYPTO_ES_RSAESOAEP_SHA1_MGF1 0x0003
+
+// Supported Signature schemes CRYPTO_INFO.sigScheme
+#define CRYPTO_SS_NONE 0x0001
+#define CRYPTO_SS_RSASSAPKCS1v15_SHA1 0x0002
+#define CRYPTO_SS_RSASSAPKCS1v15_DER 0x0003
+
+typedef struct CRYPTO_INFO {
+  void *keyInfo;
+  UINT32 algorithmID;
+  UINT32 encScheme;
+  UINT32 sigScheme;
+} CRYPTO_INFO;
+
+
+void Crypto_Init(const BYTE* rand, int size);
+
+void Crypto_Exit();
+
+void Crypto_GetRandom(void* data, int size);
+
+void Crypto_HMAC(   const BYTE* text, 
+                    int text_len, 
+                    const BYTE* key, 
+                    int key_len,
+                    BYTE* digest);
+
+TPM_RESULT Crypto_HMAC_buf (const buffer_t * text,
+                            const buffer_t * key,
+                            BYTE * o_digest); /* presumably of 20 bytes */
+    
+void Crypto_SHA1Full(   const BYTE* text, 
+                        UINT32 size,
+                        BYTE* hash); //Complete 3part SHA1
+
+// o_hash needs to be large enough to hold the digest, ie 20 bytes
+TPM_RESULT Crypto_SHA1Full_buf (const buffer_t * buf,
+                                BYTE * o_hash);
+    
+void Crypto_SHA1Start(UINT32* maxNumBytes);
+void Crypto_SHA1Update(int numBytes, const BYTE* hashData);
+void Crypto_SHA1Complete(   int hashDataSize, 
+                            const BYTE* hashData, 
+                            BYTE* hashValue);
+
+void Crypto_RSACreateKey(   /*in*/ UINT32 keySize,
+                            /*in*/ UINT32 pubExpSize, 
+                            /*in*/ BYTE *pubExp,
+                            /*out*/ UINT32 *privExpSize, 
+                            /*out*/ BYTE *privExp,
+                            /*out*/ UINT32 *modulusSize,
+                            /*out*/ BYTE *modulus,
+                            /*out*/ CRYPTO_INFO *keys);
+                            
+void Crypto_RSABuildCryptoInfo( /*[IN]*/ UINT32 pubExpSize, 
+                                /*[IN]*/ BYTE *pubExp,
+                                /*[IN]*/ UINT32 privExpSize, 
+                                /*[IN]*/ BYTE *privExp,
+                                /*[IN]*/ UINT32 modulusSize, 
+                                /*[IN]*/ BYTE *modulus, 
+                                /*[OUT]*/ CRYPTO_INFO* cryptoInfo);
+                                
+void Crypto_RSABuildCryptoInfoPublic(   /*[IN]*/ UINT32 pubExpSize, 
+                                        /*[IN]*/ BYTE *pubExp,
+                                        /*[IN]*/ UINT32 modulusSize, 
+                                        /*[IN]*/ BYTE *modulus, 
+                                        CRYPTO_INFO* cryptoInfo);
+
+//
+// symmetric pack and unpack operations
+//
+TPM_RESULT Crypto_RSAPackCryptoInfo (const CRYPTO_INFO* cryptoInfo,
+                                     BYTE ** io_buf, UINT32 * io_buflen);
+
+TPM_RESULT Crypto_RSAUnpackCryptoInfo (CRYPTO_INFO * ci,
+                                       BYTE * in, UINT32 len,
+                                       UINT32 * o_lenread);
+
+                             
+// return 0 on success, -1 on error
+int Crypto_RSAEnc(  CRYPTO_INFO *keys,
+                    UINT32 inDataSize,
+                    BYTE *inData,
+                    /*out*/ UINT32 *outDataSize,
+                    /*out*/ BYTE *outData);
+
+// return 0 on success, -1 on error
+int Crypto_RSADec(  CRYPTO_INFO *keys,
+                    UINT32 inDataSize,
+                    BYTE *inData,
+                    /*out*/ UINT32 *outDataSize,
+                    /*out*/ BYTE *outData);
+
+// return 0 on success, -1 on error
+int Crypto_RSASign( CRYPTO_INFO *keys,
+                    UINT32 inDataSize,
+                    BYTE *inData,
+                    /*out*/ UINT32 *sigSize,
+                    /*out*/ BYTE *sig);
+
+bool Crypto_RSAVerify(  CRYPTO_INFO *keys,
+                        UINT32 inDataSize,
+                        BYTE *inData,
+                        UINT32 sigSize,
+                        BYTE *sig);
+
+//private:
+int RSA_verify_DER(int dtype, unsigned char *m, unsigned int m_len,
+                   unsigned char *sigbuf, unsigned int siglen, CRYPTO_INFO 
*key);
+
+int RSA_sign_DER(int type, unsigned char *m, unsigned int m_len,
+              unsigned char *sigret, unsigned int *siglen, CRYPTO_INFO *key);
+
+#endif // __CRYPTO_H__
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/crypto/hash.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/crypto/hash.c  Fri Sep  9 16:30:54 2005
@@ -0,0 +1,153 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// hash.c
+// 
+//  This file will handle all the TPM Hash functionality
+//
+// ==================================================================
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+
+#include "tcg.h"         // for TPM_SUCCESS
+#include "crypto.h"
+
+static SHA_CTX g_shaContext;
+
+void Crypto_HMAC(   const BYTE* text, 
+                    int text_len, 
+                    const BYTE* key, 
+                    int key_len, 
+                    BYTE* digest) {
+  if (text == NULL || key == NULL || text_len == 0 || key_len == 0) 
+    return;
+  
+  HMAC(EVP_sha1(), key, key_len, text, text_len, digest, NULL);
+}
+
+TPM_RESULT Crypto_HMAC_buf (const buffer_t * text,
+                           const buffer_t * key,
+                           BYTE * o_digest) { /* presumably of 20 bytes */
+  
+  Crypto_HMAC (text->bytes, text->size, 
+              key->bytes, key->size,
+              o_digest);
+  
+  return TPM_SUCCESS;
+}
+
+
+/*
+ * SHA1
+ * (OUT) Create a SHA1 hash of text. Calls all three SHA1 steps internally
+ */
+void Crypto_SHA1Full( const BYTE* text, 
+      uint32_t size, 
+      BYTE* hash) {
+
+  if (text == NULL || size == 0) 
+    return;
+  
+  // Run SHA1Start + SHAUpdate (if necessary) + SHAComplete
+  uint32_t maxBytes; // Not used for anything
+  Crypto_SHA1Start(&maxBytes);
+  
+  while (size > 64){
+    Crypto_SHA1Update(64, text); 
+    size -= 64;
+    text += 64;
+  }
+  
+  Crypto_SHA1Complete(size, text, hash);
+}
+
+// same thing using buffer_t
+TPM_RESULT Crypto_SHA1Full_buf (const buffer_t * buf,
+                                 BYTE * o_digest) {
+
+  if (buf->bytes == NULL || buf->size == 0) 
+    return TPM_BAD_PARAMETER;
+  
+  Crypto_SHA1Full (buf->bytes, buf->size, o_digest);
+  
+  return TPM_SUCCESS;
+}
+
+
+/*
+ * Initialize SHA1
+ * (OUT) Maximum number of bytes that can be sent to SHA1Update. 
+ *   Must be a multiple of 64 bytes.
+ */
+void Crypto_SHA1Start(uint32_t* maxNumBytes) {
+  int max = SHA_CBLOCK;
+  // Initialize the crypto library
+  SHA1_Init(&g_shaContext);
+  *maxNumBytes = max;
+}
+
+/*
+ * Process SHA1
+ * @numBytes: (IN) The number of bytes in hashData. 
+ *       Must be a multiple of 64 bytes.
+ * @hashData: (IN) Bytes to be hashed.
+ */
+void Crypto_SHA1Update(int numBytes, const BYTE* hashData) {
+
+  if (hashData == NULL || numBytes == 0 || numBytes%64 != 0) 
+    return;
+  
+  SHA1_Update(&g_shaContext, hashData, numBytes); 
+}
+
+/*
+ * Complete the SHA1 process
+ * @hashDataSize: (IN) Number of bytes in hashData.
+ *       Must be a multiple of 64 bytes.
+ * @hashData: (IN) Final bytes to be hashed.
+ * @hashValue: (OUT) The output of the SHA-1 hash.
+ */
+void Crypto_SHA1Complete(int hashDataSize, 
+                        const BYTE* hashData, 
+                        BYTE* hashValue) {
+  SHA1_Update(&g_shaContext, hashData, hashDataSize);
+  SHA1_Final(hashValue, &g_shaContext);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/crypto/rsa.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/crypto/rsa.c   Fri Sep  9 16:30:54 2005
@@ -0,0 +1,434 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// rsa.c
+// 
+//  This file will handle all the TPM RSA crypto functionality
+// 
+// ==================================================================
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+#include <openssl/err.h>
+#include <stdio.h>
+
+#include "tcg.h"
+#include "buffer.h"
+#include "crypto.h"
+#include "log.h"
+
+void Crypto_RSACreateKey(   /*in*/ UINT32 keySize,
+                            /*in*/ UINT32 pubExpSize, 
+                            /*in*/ BYTE *pubExp,
+                            /*out*/ UINT32 *privExpSize, 
+                            /*out*/ BYTE *privExp,
+                            /*out*/ UINT32 *modulusSize,        
+                            /*out*/ BYTE *modulus,
+                            /*out*/ CRYPTO_INFO *keys) {
+  unsigned long e_value;
+  
+  if (pubExpSize == 0) // Default e = 2^16+1
+    e_value = (0x01 << 16) + 1;
+  else {
+    // This is not supported, but the following line MIGHT work
+    // under then assumption that the format is BigNum compatable
+    // Though it's not in the spec, so who knows what it is.
+    // Forcing the default.
+    //BN_bin2bn(pubExp, pubExpSize, NULL);
+    e_value = (0x01 << 16) + 1;
+  }
+
+  RSA *rsa = RSA_generate_key(keySize, e_value, NULL, NULL);
+  
+  if (keys) {
+    keys->keyInfo = rsa;
+    keys->algorithmID = CRYPTO_ALGORITH_RSA;
+  }
+  
+  if (modulus)   *modulusSize   = BN_bn2bin(rsa->n, modulus);
+  if (privExp)   *privExpSize   = BN_bn2bin(rsa->d, privExp);
+}
+
+// Create a CRYPTO_INFO struct from the BYTE * key parts. 
+// If pubExp info is NULL, use TCG default.
+// If there is a remainder while calculating the privExp, return FALSE.
+
+void Crypto_RSABuildCryptoInfo( /*[IN]*/ UINT32 pubExpSize, 
+                                /*[IN]*/ BYTE *pubExp,
+                                /*[IN]*/ UINT32 privExpSize, 
+                                /*[IN]*/ BYTE *privExp,
+                                /*[IN]*/ UINT32 modulusSize, 
+                                /*[IN]*/ BYTE *modulus, 
+                                CRYPTO_INFO* cryptoInfo) {
+  cryptoInfo->keyInfo = RSA_new();
+  RSA *rsa = (RSA *) cryptoInfo->keyInfo;
+  
+  rsa->e = BN_new();
+  
+  if (pubExpSize == 0) { // Default e = 2^16+1
+    BN_set_bit(rsa->e, 16);
+    BN_set_bit(rsa->e, 0);
+  } else {
+    // This is not supported, but the following line MIGHT work
+    // under then assumption that the format is BigNum compatable
+    // Though it's not in the spec, so who knows what it is.
+    // Forcing the default.
+    //BN_bin2bn(pubExp, pubExpSize, NULL);
+    BN_set_bit(rsa->e, 16);
+    BN_set_bit(rsa->e, 0);
+  }
+  
+  rsa->n = BN_bin2bn(modulus, modulusSize, NULL);
+  rsa->d = BN_bin2bn(privExp, privExpSize, NULL);
+}
+
+// Create a CRYPTO_INFO struct from the BYTE * key parts. 
+// If pubExp info is NULL, use TCG default.
+// If there is a remainder while calculating the privExp, return FALSE.
+
+void Crypto_RSABuildCryptoInfoPublic(   /*[IN]*/ UINT32 pubExpSize, 
+                                        /*[IN]*/ BYTE *pubExp,
+                                        /*[IN]*/ UINT32 modulusSize, 
+                                        /*[IN]*/ BYTE *modulus, 
+                                        CRYPTO_INFO* cryptoInfo) {
+  cryptoInfo->keyInfo = RSA_new();
+  RSA *rsa = (RSA *) cryptoInfo->keyInfo;
+  
+  rsa->e = BN_new();
+  
+  if (pubExpSize == 0) { // Default e = 2^16+1
+    BN_set_bit(rsa->e, 16);
+    BN_set_bit(rsa->e, 0);
+  } else {
+    // This is not supported, but the following line MIGHT work
+    // under then assumption that the format is BigNum compatable
+    // Though it's not in the spec, so who knows what it is.
+    // Forcing the default.
+    //BN_bin2bn(pubExp, pubExpSize, NULL);
+    BN_set_bit(rsa->e, 16);
+    BN_set_bit(rsa->e, 0);
+  }
+  
+  rsa->n = BN_bin2bn(modulus, modulusSize, NULL);
+  
+}
+
+int Crypto_RSAEnc(  CRYPTO_INFO *key,
+                   UINT32 inDataSize,
+                   BYTE *inData,
+                   /*out*/ UINT32 *outDataSize,
+                   /*out*/ BYTE *outData) {
+  RSA *rsa = (RSA *) key->keyInfo;
+  UINT32 paddedDataSize = RSA_size (rsa);
+  BYTE *paddedData = (BYTE *)malloc(sizeof(BYTE) * paddedDataSize);
+  int rc;
+    
+  if (paddedData == NULL) 
+    return -1;
+
+  *outDataSize = 0;
+  
+  switch (key->encScheme) {
+  case CRYPTO_ES_RSAESPKCSv15:
+    if (RSA_padding_add_PKCS1_type_2(paddedData, paddedDataSize, inData, 
inDataSize) <= 0) {
+      rc = -1; 
+      goto abort_egress;
+    }
+    break;
+  case CRYPTO_ES_RSAESOAEP_SHA1_MGF1:
+    if 
(RSA_padding_add_PKCS1_OAEP(paddedData,paddedDataSize,inData,inDataSize, (BYTE 
*) OAEP_P,OAEP_P_SIZE) <= 0 ) {
+      rc = -1; 
+      goto abort_egress;
+    }
+    break;
+  default:
+    rc = -1; 
+    goto abort_egress;
+  }
+  
+  rc = RSA_public_encrypt(paddedDataSize, paddedData, outData, rsa, 
RSA_NO_PADDING);
+  if (rc == -1)
+    goto abort_egress; 
+   
+  *outDataSize = rc;
+  
+  if (rc > 0) rc = 0;
+  
+  goto egress;
+  
+ abort_egress:
+ egress:
+  
+  if (paddedData) 
+    free (paddedData);
+  return rc;
+  
+}
+
+int Crypto_RSADec(  CRYPTO_INFO *key,
+                    UINT32 inDataSize,
+                    BYTE *inData,
+                    /*out*/ UINT32 *outDataSize,
+                    /*out*/ BYTE *outData) {
+  
+  RSA *rsa = (RSA *) key->keyInfo;
+  UINT32 paddedDataSize = RSA_size (rsa);
+  BYTE *paddedData = (BYTE *)malloc(sizeof(BYTE) * paddedDataSize);
+  int rc;
+  
+  if (paddedData == NULL)
+    goto abort_egress;
+  
+  rc = RSA_private_decrypt(inDataSize, inData, paddedData, rsa, 
RSA_NO_PADDING);
+  if (rc == -1) {
+    vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_private_decrypt: %s\n", 
ERR_error_string(ERR_get_error(), NULL));
+    goto abort_egress;
+  }
+  
+  paddedDataSize = rc;
+  
+  switch (key->encScheme) {
+  case CRYPTO_ES_RSAESPKCSv15:
+    rc = RSA_padding_check_PKCS1_type_2 (outData, paddedDataSize,
+                                        paddedData + 1, paddedDataSize - 1,
+                                        RSA_size(rsa));
+    if (rc == -1) {
+      vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_padding_check_PKCS1_type_2: %s\n", 
+             ERR_error_string(ERR_get_error(), NULL));
+      goto abort_egress;
+    }
+    *outDataSize = rc;
+    break;
+  case CRYPTO_ES_RSAESOAEP_SHA1_MGF1:
+    rc = RSA_padding_check_PKCS1_OAEP(outData, paddedDataSize,
+                                     paddedData + 1, paddedDataSize - 1,
+                                     RSA_size(rsa),
+                                     (BYTE *) OAEP_P, OAEP_P_SIZE);
+    if (rc == -1) {
+      vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_padding_check_PKCS1_OAEP: %s\n",
+             ERR_error_string(ERR_get_error(), NULL));
+      goto abort_egress;
+    }
+    *outDataSize = rc;
+    break;
+  default:
+    *outDataSize = 0;
+  }
+  
+  free(paddedData); paddedData = NULL;
+  goto egress;
+  
+ abort_egress:
+  
+  if (paddedData) 
+    free (paddedData);
+  return -1;
+  
+ egress:
+  return 0;
+}
+
+// Signs either a SHA1 digest of a message or a DER encoding of a message
+// Textual messages MUST be encoded or Hashed before sending into this function
+// It will NOT SHA the message.
+int Crypto_RSASign( CRYPTO_INFO *key,
+                    UINT32 inDataSize,
+                    BYTE *inData,
+                    /*out*/ UINT32 *sigSize,
+                    /*out*/ BYTE *sig) {
+  int status;
+  unsigned int intSigSize;
+  
+  switch(key->sigScheme) {
+  case CRYPTO_SS_RSASSAPKCS1v15_SHA1: 
+    status = RSA_sign(NID_sha1, inData, inDataSize, sig, &intSigSize, (RSA *) 
key->keyInfo);
+    break;
+  case CRYPTO_SS_RSASSAPKCS1v15_DER:
+    //        status = Crypto_RSA_sign_DER(NID_md5_sha1, inData, inDataSize, 
sig, &intSigSize, key);
+    vtpmlogerror(VTPM_LOG_CRYPTO, "Crypto: Unimplemented sign type (%d)\n", 
key->sigScheme);
+    status = 0;
+    break;
+  default:
+    status = 0;
+  }
+  
+  if (status == 0) {
+    *sigSize = 0;
+    vtpmlogerror(VTPM_LOG_CRYPTO, "%s\n", ERR_error_string(ERR_get_error(), 
NULL));
+    return -1;
+  }
+  
+  *sigSize = (UINT32) intSigSize;
+  return 0;
+}
+
+bool Crypto_RSAVerify(  CRYPTO_INFO *key,
+                        UINT32 inDataSize,
+                        BYTE *inData,
+                        UINT32 sigSize,
+                        BYTE *sig) {
+  int status;
+  
+  switch(key->sigScheme){
+  case CRYPTO_SS_RSASSAPKCS1v15_SHA1: 
+    status = RSA_verify(NID_sha1, inData, inDataSize, sig, sigSize, (RSA *) 
key->keyInfo);
+    break;
+  case CRYPTO_SS_RSASSAPKCS1v15_DER:
+    //status = Crypto_RSA_verify_DER(NID_md5_sha1, inData, inDataSize, sig, 
sigSize, key);
+    vtpmlogerror(VTPM_LOG_CRYPTO, "Crypto: Unimplemented sign type (%d)\n", 
key->sigScheme);
+    status = 0;
+    break;
+  default:
+    status = 0;
+  }
+  
+  if (status) 
+    return(1);
+  else {
+    vtpmlogerror(VTPM_LOG_CRYPTO, "RSA verify: %s\n", 
ERR_error_string(ERR_get_error(), NULL));
+    return(0);
+  }
+  
+}
+
+// helper which packs everything into a BIO!
+
+// packs the parameters first, then the private key, then the public key
+// if *io_buf is NULL, allocate it here as needed. otherwise its size is in
+// *io_buflen
+TPM_RESULT Crypto_RSAPackCryptoInfo (const CRYPTO_INFO* cryptoInfo,
+                                      BYTE ** io_buf, UINT32 * io_buflen) {
+  TPM_RESULT status = TPM_SUCCESS;
+  BYTE * buf;
+  long len, outlen = *io_buflen;
+  
+  const long PARAMSLEN = 3*sizeof(UINT32);
+  
+  RSA *rsa = (RSA *) cryptoInfo->keyInfo;
+  
+  BIO *mem = BIO_new(BIO_s_mem());
+  
+  
+  // write the openssl keys to the BIO
+  if ( i2d_RSAPrivateKey_bio (mem, rsa) == 0 ) {
+    ERR_print_errors_fp (stderr);
+    ERRORDIE (TPM_SIZE);
+  }
+  if ( i2d_RSAPublicKey_bio (mem, rsa) == 0 ) {
+    ERR_print_errors_fp (stderr);
+    ERRORDIE (TPM_SIZE);
+  }
+  
+  // get the buffer out
+  len = BIO_get_mem_data (mem, &buf);
+  
+  // see if we need to allocate a return buffer
+  if (*io_buf == NULL) {
+    *io_buf = (BYTE*) malloc (PARAMSLEN + len);
+    if (*io_buf == NULL) 
+      ERRORDIE (TPM_SIZE);
+  } else {                      // *io_buf is already allocated
+    if (outlen < len + PARAMSLEN) 
+      ERRORDIE (TPM_SIZE); // but not large enough!  
+  }
+  
+  // copy over the parameters (three UINT32's starting at algorithmID)
+  memcpy (*io_buf, &cryptoInfo->algorithmID, PARAMSLEN);
+  
+  // copy over the DER keys
+  memcpy (*io_buf + PARAMSLEN, buf, len);
+  
+  *io_buflen = len + PARAMSLEN;
+  
+  goto egress;
+  
+  
+ abort_egress:
+ egress:
+  
+  BIO_free (mem);
+  
+  return status;
+}
+
+
+
+// sets up ci, and returns the number of bytes read in o_lenread
+TPM_RESULT Crypto_RSAUnpackCryptoInfo (CRYPTO_INFO * ci,
+                                        BYTE * in, UINT32 len,
+                                        UINT32 * o_lenread) {
+  
+  TPM_RESULT status = TPM_SUCCESS;
+  long l;
+  BIO *mem;
+  RSA *rsa;
+  
+  // first load up the params
+  l = 3 * sizeof(UINT32);
+  memcpy (&ci->algorithmID, in, l);
+  len -= l;
+  in += l;
+  
+  // and now the openssl keys, private first
+  mem = BIO_new_mem_buf (in, len);
+  
+  if ( (rsa = d2i_RSAPrivateKey_bio (mem, NULL)) == NULL ) {
+    ERR_print_errors_fp (stderr);
+    ERRORDIE (TPM_BAD_PARAMETER);
+  }
+  // now use the same RSA object and fill in the private key
+  if ( d2i_RSAPublicKey_bio (mem, &rsa) == NULL ) {
+    ERR_print_errors_fp (stderr);
+    ERRORDIE (TPM_BAD_PARAMETER);
+  }
+  
+  ci->keyInfo = rsa;          // needs to be freed somehow later
+  
+  // FIXME: havent figured out yet how to tell how many bytes were read in the
+  // above oprations! so o_lenread is not set
+  
+  goto egress;
+  
+ abort_egress:
+ egress:
+  
+  BIO_free (mem);
+ 
+  return status;  
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/crypto/sym_crypto.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/crypto/sym_crypto.c    Fri Sep  9 16:30:54 2005
@@ -0,0 +1,242 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// sym_crypto.c
+// 
+//     Symmetric crypto portion of crypto 
+// 
+// ==================================================================
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+#include "tcg.h"
+#include "sym_crypto.h"
+
+typedef enum crypt_op_type_t {
+  CRYPT_ENCRYPT,
+  CRYPT_DECRYPT
+} crypt_op_type_t;
+
+TPM_RESULT ossl_symcrypto_op (symkey_t* key,
+                              const buffer_t* in,
+                              const buffer_t* iv,
+                              buffer_t * out,
+                              crypt_op_type_t optype);
+
+
+// this is initialized in Crypto_Init()
+const EVP_CIPHER * SYM_CIPHER = NULL;
+
+const BYTE ZERO_IV[EVP_MAX_IV_LENGTH] = {0};
+
+
+TPM_RESULT Crypto_symcrypto_initkey (symkey_t * key, const buffer_t* keybits) {
+  TPM_RESULT status = TPM_SUCCESS;
+  
+  EVP_CIPHER_CTX_init (&key->context);
+  
+  key->cipher = SYM_CIPHER;
+  
+  status = buffer_init_copy (&key->key, keybits);
+  STATUSCHECK(status);
+    
+  goto egress;
+  
+ abort_egress:
+  EVP_CIPHER_CTX_cleanup (&key->context);
+  
+ egress:
+  
+  return status;
+}
+
+
+
+TPM_RESULT Crypto_symcrypto_genkey (symkey_t * key) {
+  int res;
+  TPM_RESULT status = TPM_SUCCESS;
+  
+  // hmm, EVP_CIPHER_CTX_init does not return a value
+  EVP_CIPHER_CTX_init (&key->context);
+  
+  key->cipher = SYM_CIPHER;
+  
+  status = buffer_init (&key->key, EVP_CIPHER_key_length(key->cipher), NULL);
+  STATUSCHECK (status);
+  
+  // and generate the key material
+  res = RAND_pseudo_bytes (key->key.bytes, key->key.size);
+  if (res < 0) 
+    ERRORDIE (TPM_SHORTRANDOM);
+  
+  
+  goto egress;
+  
+ abort_egress:
+  EVP_CIPHER_CTX_cleanup (&key->context);
+  buffer_free (&key->key);
+  
+ egress:
+  return status;  
+}
+
+
+TPM_RESULT Crypto_symcrypto_encrypt (symkey_t* key,
+                              const buffer_t* clear,
+                              buffer_t* o_cipher) {
+  TPM_RESULT status = TPM_SUCCESS;
+  
+  buffer_t iv, cipher_alias;
+  
+  buffer_init_const (&iv, EVP_MAX_IV_LENGTH, ZERO_IV);
+  
+  buffer_init (o_cipher,
+              clear->size +
+              EVP_CIPHER_iv_length(key->cipher) +
+              EVP_CIPHER_block_size (key->cipher),
+                                0);
+  
+  // copy the IV into the front
+  buffer_copy (o_cipher, &iv);
+  
+  // make an alias into which we'll put the ciphertext
+  buffer_init_alias (&cipher_alias, o_cipher, 
EVP_CIPHER_iv_length(key->cipher), 0);
+  
+  status = ossl_symcrypto_op (key, clear, &iv, &cipher_alias, CRYPT_ENCRYPT);
+  STATUSCHECK (status);
+
+  // set the output size correctly
+  o_cipher->size += cipher_alias.size;
+  
+  goto egress;
+  
+ abort_egress:
+  
+ egress:
+  
+  return status;
+  
+}
+
+
+
+TPM_RESULT Crypto_symcrypto_decrypt (symkey_t* key,
+                              const buffer_t* cipher,
+                              buffer_t* o_clear) {
+  TPM_RESULT status = TPM_SUCCESS;
+  
+  buffer_t iv, cipher_alias;
+  
+  // alias for the IV
+  buffer_init_alias (&iv, cipher, 0, EVP_CIPHER_iv_length(key->cipher));
+  
+  // make an alias to where the ciphertext is, after the IV
+  buffer_init_alias (&cipher_alias, cipher, EVP_CIPHER_iv_length(key->cipher), 
0);
+  
+  // prepare the output buffer
+  status = buffer_init (o_clear,
+                       cipher->size
+                       - EVP_CIPHER_iv_length(key->cipher)
+                       + EVP_CIPHER_block_size(key->cipher), 
+                       0);
+  STATUSCHECK(status);
+  
+  // and decrypt
+  status = ossl_symcrypto_op (key, &cipher_alias, &iv, o_clear, CRYPT_DECRYPT);
+  STATUSCHECK (status);
+  
+  goto egress;
+  
+ abort_egress:
+  buffer_free (o_clear);
+  
+ egress:
+  
+  return status;
+}
+
+
+
+TPM_RESULT Crypto_symcrypto_freekey (symkey_t * key) {
+  buffer_memset (&key->key, 0);
+  buffer_free (&key->key);
+  
+  EVP_CIPHER_CTX_cleanup (&key->context);
+  
+  return TPM_SUCCESS;
+}
+
+
+TPM_RESULT ossl_symcrypto_op (symkey_t* key,
+                              const buffer_t* in,
+                              const buffer_t* iv,
+                              buffer_t * out,
+                              crypt_op_type_t optype) {
+  TPM_RESULT status = TPM_SUCCESS;
+  
+  int inlen, outlen;
+  tpm_size_t running;
+  
+  if ( ! EVP_CipherInit_ex (&key->context,
+                           key->cipher, NULL, key->key.bytes, iv->bytes,
+                           optype == CRYPT_ENCRYPT ? 1 : 0) ) 
+    ERRORDIE (TPM_FAIL);
+  
+  
+  
+  inlen = in->size;
+  
+  outlen  = 0;
+  running = 0;
+  
+  
+  if ( ! EVP_CipherUpdate (&key->context, out->bytes, &outlen, in->bytes, 
inlen) )
+    ERRORDIE (TPM_FAIL);
+
+  running += outlen;
+  
+  if ( ! EVP_CipherFinal_ex (&key->context, out->bytes + running, &outlen) )
+    ERRORDIE (TPM_FAIL);
+  
+  running += outlen;
+  
+  out->size = running;
+  
+  goto egress;
+  
+ abort_egress:
+ egress:
+  
+  return status;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/crypto/sym_crypto.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/crypto/sym_crypto.h    Fri Sep  9 16:30:54 2005
@@ -0,0 +1,72 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// sym_crypto.h
+// 
+//     Symmetric Crypto 
+// 
+// ==================================================================
+
+#ifndef _SYM_CRYPTO_H
+#define _SYM_CRYPTO_H
+
+#include <openssl/evp.h>
+#include "buffer.h"
+
+typedef struct symkey_t {
+  buffer_t key;
+  
+  EVP_CIPHER_CTX context;
+  const EVP_CIPHER * cipher;
+} symkey_t;
+
+extern const EVP_CIPHER * SYM_CIPHER;
+
+TPM_RESULT Crypto_symcrypto_genkey (symkey_t * key);
+
+TPM_RESULT Crypto_symcrypto_initkey (symkey_t * key, const buffer_t* keybits);
+
+
+// these functions will allocate their output buffers
+TPM_RESULT Crypto_symcrypto_encrypt (symkey_t* key,
+                              const buffer_t* clear,
+                              buffer_t* o_cipher);
+
+TPM_RESULT Crypto_symcrypto_decrypt (symkey_t* key,
+                              const buffer_t* cipher,
+                              buffer_t* o_clear);
+
+// only free the internal parts, not the 'key' ptr
+TPM_RESULT Crypto_symcrypto_freekey (symkey_t * key);
+
+#endif /* _SYM_CRYPTO_H */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/Makefile
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/Makefile       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,27 @@
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+BIN            = vtpm_managerd
+
+all: build
+
+build: $(BIN)
+
+install: build
+       if [ ! -d "$(DESTDIR)/var/vtpm/fifos" ]; \
+               then mkdir -p $(DESTDIR)/var/vtpm/fifos; \
+       fi
+       $(INSTALL_PROG) $(BIN) $(TOOLS_INSTALL_DIR)
+
+clean:
+       rm -f *.a *.so *.o *.rpm $(DEP_FILES)
+
+mrproper: clean
+       rm -f $(BIN)
+
+$(BIN): $(OBJS)
+       $(CC) $(LDFLAGS) $^ $(LIBS) -o $@
+
+# libraries
+LIBS += ../tcs/libTCS.a ../util/libTCGUtils.a ../crypto/libtcpaCrypto.a
+LIBS += -lcrypto -lpthread -lrt -lm
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/dmictl.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/dmictl.c       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,339 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+//   dmictl.c
+// 
+//     Functions for creating and destroying DMIs
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifndef VTPM_MUTLI_VM
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <signal.h>
+ #include <wait.h>
+#endif
+
+#include "vtpmpriv.h"
+#include "bsg.h"
+#include "buffer.h"
+#include "log.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+
+#define TPM_EMULATOR_PATH "/usr/bin/vtpmd"
+
+TPM_RESULT close_dmi( VTPM_DMI_RESOURCE *dmi_res) {
+       TPM_RESULT status = TPM_FAIL;
+       
+       if (dmi_res == NULL) 
+               return TPM_SUCCESS;
+       
+       status = TCS_CloseContext(dmi_res->TCSContext);
+       free ( dmi_res->NVMLocation );
+       dmi_res->connected = FALSE;
+
+#ifndef VTPM_MULTI_VM  
+       free(dmi_res->guest_tx_fname);
+       free(dmi_res->vtpm_tx_fname);
+               
+       close(dmi_res->guest_tx_fh); dmi_res->guest_tx_fh = -1;
+       close(dmi_res->vtpm_tx_fh);  dmi_res->vtpm_tx_fh = -1; 
+       
+               
+ #ifndef MANUAL_DM_LAUNCH
+  if (dmi_res->dmi_id != VTPM_CTL_DM) {
+    if (dmi_res->dmi_pid != 0) {
+      vtpmloginfo(VTPM_LOG_VTPM, "Killing dmi on pid %d.\n", dmi_res->dmi_pid);
+      if ((kill(dmi_res->dmi_pid, SIGKILL) !=0) ||
+         (waitpid(dmi_res->dmi_pid, NULL, 0) != dmi_res->dmi_pid)){
+        vtpmlogerror(VTPM_LOG_VTPM, "Could not kill dmi on pid %d.\n", 
dmi_res->dmi_pid);
+        status = TPM_FAIL;
+      }
+    } else 
+      vtpmlogerror(VTPM_LOG_VTPM, "Could not kill dmi because it's pid was 
0.\n");
+  }
+ #endif
+#endif
+
+       return status;
+}
+       
+TPM_RESULT VTPM_Handle_New_DMI( const buffer_t *param_buf) {
+  
+  VTPM_DMI_RESOURCE *new_dmi=NULL;
+  TPM_RESULT status=TPM_FAIL;
+  BYTE type;
+  UINT32 dmi_id, domain_id, *dmi_id_key; 
+  int fh;
+
+#ifndef VTPM_MUTLI_VM
+  char dmi_id_str[11]; // UINT32s are up to 10 digits + NULL
+  struct stat file_info;
+#endif
+  
+  if (param_buf == NULL) { // Assume creation of Dom 0 control
+    type = 0;
+    domain_id = VTPM_CTL_DM;
+    dmi_id = VTPM_CTL_DM;
+  } else if (buffer_len(param_buf) != sizeof(BYTE) + sizeof(UINT32) *2) {
+    vtpmloginfo(VTPM_LOG_VTPM, "New DMI command wrong length: %d.\n", 
buffer_len(param_buf));
+    status = TPM_BAD_PARAMETER;
+    goto abort_egress;
+  } else {
+    BSG_UnpackList( param_buf->bytes, 3,
+                   BSG_TYPE_BYTE, &type,
+                   BSG_TYPE_UINT32, &domain_id,
+                   BSG_TYPE_UINT32,  &dmi_id);
+  }
+  
+  new_dmi = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map, 
&dmi_id);
+  if (new_dmi == NULL) { 
+    vtpmloginfo(VTPM_LOG_VTPM, "Creating new DMI instance %d attached on 
domain %d.\n", dmi_id, domain_id);
+    // Brand New DMI. Initialize the persistent pieces
+    if ((new_dmi = (VTPM_DMI_RESOURCE *) malloc (sizeof(VTPM_DMI_RESOURCE))) 
== NULL) {
+      status = TPM_RESOURCES;
+      goto abort_egress;
+    }
+    memset(new_dmi, 0, sizeof(VTPM_DMI_RESOURCE));
+    new_dmi->dmi_id = dmi_id;
+    new_dmi->connected = FALSE;
+    
+    if ((dmi_id_key = (UINT32 *) malloc (sizeof(UINT32))) == NULL) {
+      status = TPM_RESOURCES;
+      goto abort_egress;
+    }      
+    *dmi_id_key = new_dmi->dmi_id;
+    
+    // install into map
+    if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, new_dmi)){
+      free(new_dmi);
+      free(dmi_id_key);
+      status = TPM_FAIL;
+      goto egress;
+    }
+    
+  } else 
+    vtpmloginfo(VTPM_LOG_VTPM, "Re-attaching DMI instance %d on domain %d 
.\n", dmi_id, domain_id);
+  
+  if (new_dmi->connected) {
+    vtpmlogerror(VTPM_LOG_VTPM, "Attempt to re-attach, currently attached 
instance %d. Ignoring\n", dmi_id);
+    status = TPM_BAD_PARAMETER;
+    goto egress;
+  }
+  
+  // Initialize the Non-persistent pieces
+  new_dmi->dmi_domain_id = domain_id;
+  new_dmi->NVMLocation = NULL;
+  
+  new_dmi->TCSContext = 0;
+  TPMTRYRETURN( TCS_OpenContext(&new_dmi->TCSContext) );
+  
+  new_dmi->NVMLocation = (char *) malloc(11 + strlen(DMI_NVM_FILE));
+  sprintf(new_dmi->NVMLocation, DMI_NVM_FILE, (uint32_t) new_dmi->dmi_id);
+  
+  // Measure DMI
+  // FIXME: This will measure DMI. Until then use a fixed DMI_Measurement value
+  /*
+  fh = open(TPM_EMULATOR_PATH, O_RDONLY);
+  stat_ret = fstat(fh, &file_stat);
+  if (stat_ret == 0) 
+    dmi_size = file_stat.st_size;
+  else {
+       vtpmlogerror(VTPM_LOG_VTPM, "Could not open tpm_emulator!!\n");
+    status = TPM_IOERROR;
+    goto abort_egress;
+  }
+  dmi_buffer
+  */
+  memset(&new_dmi->DMI_measurement, 0xcc, sizeof(TPM_DIGEST));
+  
+#ifndef VTPM_MULTI_VM
+  if (dmi_id != VTPM_CTL_DM) {
+    // Create a pair of fifo pipes
+               if( (new_dmi->guest_tx_fname = (char *) malloc(11 + 
strlen(GUEST_TX_FIFO))) == NULL){ 
+                       status = TPM_RESOURCES;
+                       goto abort_egress;
+               }
+               sprintf(new_dmi->guest_tx_fname, GUEST_TX_FIFO, (uint32_t) 
dmi_id);
+    
+               if ((new_dmi->vtpm_tx_fname = (char *) malloc(11 + 
strlen(VTPM_TX_FIFO))) == NULL) {
+                       status = TPM_RESOURCES;
+                       goto abort_egress;
+               }
+               sprintf(new_dmi->vtpm_tx_fname, VTPM_TX_FIFO, (uint32_t) 
dmi_id);
+    
+    new_dmi->guest_tx_fh = -1;
+    new_dmi->vtpm_tx_fh= -1;
+    
+    if ( stat(new_dmi->guest_tx_fname, &file_info) == -1) {
+      if ( mkfifo(new_dmi->guest_tx_fname, S_IWUSR | S_IRUSR ) ){
+                               status = TPM_FAIL;
+                               goto abort_egress;
+      }
+    }
+            
+    if ( (fh = open(new_dmi->vtpm_tx_fname, O_RDWR)) == -1) {
+      if ( mkfifo(new_dmi->vtpm_tx_fname, S_IWUSR | S_IRUSR ) ) {
+       status = TPM_FAIL;
+       goto abort_egress;
+      }
+    }
+                
+    // Launch DMI
+    sprintf(dmi_id_str, "%d", (int) dmi_id);
+#ifdef MANUAL_DM_LAUNCH
+    vtpmlogerror(VTPM_LOG_VTPM, "FAKING starting vtpm with dmi=%s\n", 
dmi_id_str);
+    new_dmi->dmi_pid = 0;
+#else
+    pid_t pid = fork();
+    
+    if (pid == -1) {
+                       vtpmlogerror(VTPM_LOG_VTPM, "Could not fork to launch 
vtpm\n");
+                 status = TPM_RESOURCES;
+      goto abort_egress;
+               } else if (pid == 0) {
+                 if ( stat(new_dmi->NVMLocation, &file_info) == -1)
+                               execl (TPM_EMULATOR_PATH, "vtmpd", "clear", 
dmi_id_str, NULL);
+                       else 
+                               execl (TPM_EMULATOR_PATH, "vtpmd", "save", 
dmi_id_str, NULL);
+                       
+                       // Returning from these at all is an error.
+                       vtpmlogerror(VTPM_LOG_VTPM, "Could not exec to launch 
vtpm\n");
+    } else {
+      new_dmi->dmi_pid = pid;
+      vtpmloginfo(VTPM_LOG_VTPM, "Launching DMI on PID = %d\n", pid);
+    }
+#endif // MANUAL_DM_LAUNCH
+  }
+#else // VTPM_MUTLI_VM
+  // FIXME: Measure DMI through call to Measurement agent in platform.
+#endif 
+       
+  vtpm_globals->DMI_table_dirty = TRUE;
+  new_dmi->connected = TRUE;  
+  status=TPM_SUCCESS;
+  goto egress;
+  
+ abort_egress:
+       close_dmi( new_dmi );
+       
+ egress:
+  return status;
+}
+
+TPM_RESULT VTPM_Handle_Close_DMI( const buffer_t *param_buf) {
+  
+  TPM_RESULT status=TPM_FAIL;
+  VTPM_DMI_RESOURCE *dmi_res=NULL;
+  UINT32 dmi_id;
+  
+  if ((param_buf == NULL) || (buffer_len(param_buf) != sizeof(UINT32)) ) {
+    vtpmlogerror(VTPM_LOG_VTPM, "Closing DMI has bad size.");
+    status = TPM_BAD_PARAMETER;
+    goto abort_egress;
+  }
+  
+  BSG_UnpackList( param_buf->bytes, 1,
+                 BSG_TYPE_UINT32, &dmi_id);
+  
+  vtpmloginfo(VTPM_LOG_VTPM, "Closing DMI %d.\n", dmi_id);
+  
+  dmi_res = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map, 
&dmi_id);
+  if (dmi_res == NULL ) {
+    vtpmlogerror(VTPM_LOG_VTPM, "Trying to close nonexistent DMI.\n");
+    status = TPM_BAD_PARAMETER;
+    goto abort_egress;
+  }
+       
+       if (!dmi_res->connected) {
+    vtpmlogerror(VTPM_LOG_VTPM, "Closing non-connected DMI.\n");
+    status = TPM_BAD_PARAMETER;
+    goto abort_egress;
+  }
+  
+  // Close Dmi
+       TPMTRYRETURN(close_dmi( dmi_res ));
+  
+  status=TPM_SUCCESS;    
+  goto egress;
+  
+ abort_egress:
+ egress:
+  
+  return status;
+}
+
+TPM_RESULT VTPM_Handle_Delete_DMI( const buffer_t *param_buf) {
+  
+  TPM_RESULT status=TPM_FAIL;
+  VTPM_DMI_RESOURCE *dmi_res=NULL;
+  UINT32 dmi_id;
+    
+  if ((param_buf == NULL) || (buffer_len(param_buf) != sizeof(UINT32)) ) {
+    vtpmlogerror(VTPM_LOG_VTPM, "Closing DMI has bad size.\n");
+    status = TPM_BAD_PARAMETER;
+    goto abort_egress;
+  }
+  
+  BSG_UnpackList( param_buf->bytes, 1,
+                 BSG_TYPE_UINT32, &dmi_id);
+  
+  vtpmloginfo(VTPM_LOG_VTPM, "Deleting DMI %d.\n", dmi_id);    
+  
+  dmi_res = (VTPM_DMI_RESOURCE *) hashtable_remove(vtpm_globals->dmi_map, 
&dmi_id);
+  if (dmi_res == NULL) {
+    vtpmlogerror(VTPM_LOG_VTPM, "Closing non-existent DMI.\n");
+    status = TPM_BAD_PARAMETER;
+    goto abort_egress;
+  }
+  
+       //TODO: Automatically delete file dmi_res->NVMLocation
+  
+  // Close DMI first
+  TPMTRYRETURN(close_dmi( dmi_res ));
+       free ( dmi_res );
+       
+  status=TPM_SUCCESS;    
+  goto egress;
+  
+ abort_egress:
+ egress:
+  
+  return status;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/securestorage.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/securestorage.c        Fri Sep  9 16:30:54 2005
@@ -0,0 +1,401 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// securestorage.c
+// 
+//  Functions regarding securely storing DMI secrets.
+//
+// ==================================================================
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "tcg.h"
+#include "vtpm_manager.h"
+#include "vtpmpriv.h"
+#include "vtsp.h"
+#include "bsg.h"
+#include "crypto.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+#include "buffer.h"
+#include "log.h"
+
+TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI, 
+                               const buffer_t *inbuf, 
+                               buffer_t *outbuf) {
+  
+  TPM_RESULT status = TPM_SUCCESS;
+  symkey_t    symkey;
+  buffer_t    state_cipher = NULL_BUF,
+              symkey_cipher = NULL_BUF;
+  int fh;
+  long bytes_written;
+  BYTE *sealed_NVM=NULL;
+  UINT32 sealed_NVM_size, i;
+  struct pack_constbuf_t symkey_cipher32, state_cipher32;
+  
+  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Save_NVMing[%d]: 0x", buffer_len(inbuf));
+  for (i=0; i< buffer_len(inbuf); i++)
+    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", inbuf->bytes[i]);
+  vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+  
+  // Generate a sym key and encrypt state with it
+  TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_genkey (&symkey) );
+  TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_encrypt (&symkey, inbuf, 
&state_cipher) );
+  
+  // Encrypt symmetric key
+  TPMTRYRETURN( VTSP_Bind(    &vtpm_globals->storageKey, 
+                             &symkey.key, 
+                             &symkey_cipher) );
+  
+  // Create output blob: symkey_size + symkey_cipher + state_cipher_size + 
state_cipher
+  
+  symkey_cipher32.size = buffer_len(&symkey_cipher);
+  symkey_cipher32.data = symkey_cipher.bytes;
+  
+  state_cipher32.size = buffer_len(&state_cipher);
+  state_cipher32.data = state_cipher.bytes;
+  
+  sealed_NVM = (BYTE *) malloc( 2 * sizeof(UINT32) + symkey_cipher32.size + 
state_cipher32.size);
+  
+  sealed_NVM_size = BSG_PackList(sealed_NVM, 2,
+                                BSG_TPM_SIZE32_DATA, &symkey_cipher32,
+                                BSG_TPM_SIZE32_DATA, &state_cipher32);
+  
+  // Mark DMI Table so new save state info will get pushed to disk on return.
+  vtpm_globals->DMI_table_dirty = TRUE;
+  
+  // Write sealed blob off disk from NVMLocation
+  // TODO: How to properly return from these. Do we care if we return failure
+  //       after writing the file? We can't get the old one back.
+  // TODO: Backup old file and try and recover that way.
+  fh = open(myDMI->NVMLocation, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
+  if ( (bytes_written = write(fh, sealed_NVM, sealed_NVM_size) ) != (long) 
sealed_NVM_size) {
+    vtpmlogerror(VTPM_LOG_VTPM, "We just overwrote a DMI_NVM and failed to 
finish. %ld/%ld bytes.\n", bytes_written, (long)sealed_NVM_size);
+    status = TPM_IOERROR;
+    goto abort_egress;
+  }
+  close(fh);
+  
+  Crypto_SHA1Full (sealed_NVM, sealed_NVM_size, (BYTE *) 
&myDMI->NVM_measurement);   
+  
+  vtpmloginfo(VTPM_LOG_VTPM, "Saved %d bytes of E(symkey) + %d bytes of 
E(NVM)\n", buffer_len(&symkey_cipher), buffer_len(&state_cipher));
+  goto egress;
+  
+ abort_egress:
+  vtpmlogerror(VTPM_LOG_VTPM, "Failed to load NVM\n.");
+  
+ egress:
+  
+  buffer_free ( &state_cipher);
+  buffer_free ( &symkey_cipher);
+  free(sealed_NVM);
+  Crypto_symcrypto_freekey (&symkey);
+  
+  return status;
+}
+
+
+/* inbuf = null outbuf = sealed blob size, sealed blob.*/
+TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE *myDMI, 
+                               const buffer_t *inbuf, 
+                               buffer_t *outbuf) {
+  
+  TPM_RESULT status = TPM_SUCCESS;
+  symkey_t    symkey;
+  buffer_t    state_cipher = NULL_BUF, 
+              symkey_clear = NULL_BUF, 
+              symkey_cipher = NULL_BUF;
+  struct pack_buf_t symkey_cipher32, state_cipher32;
+  
+  UINT32 sealed_NVM_size;
+  BYTE *sealed_NVM = NULL;
+  long fh_size;
+  int fh, stat_ret, i;
+  struct stat file_stat;
+  TPM_DIGEST sealedNVMHash;
+  
+  memset(&symkey, 0, sizeof(symkey_t));
+  
+  if (myDMI->NVMLocation == NULL) {
+    vtpmlogerror(VTPM_LOG_VTPM, "Unable to load NVM because the file name 
NULL.\n");
+    status = TPM_AUTHFAIL;
+    goto abort_egress;
+  }
+  
+  //Read sealed blob off disk from NVMLocation
+  fh = open(myDMI->NVMLocation, O_RDONLY);
+  stat_ret = fstat(fh, &file_stat);
+  if (stat_ret == 0) 
+    fh_size = file_stat.st_size;
+  else {
+    status = TPM_IOERROR;
+    goto abort_egress;
+  }
+  
+  sealed_NVM = (BYTE *) malloc(fh_size);
+  if (read(fh, sealed_NVM, fh_size) != fh_size) {
+    status = TPM_IOERROR;
+    goto abort_egress;
+  }
+  close(fh);
+  
+  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Load_NVMing[%ld]: 0x", fh_size);
+  for (i=0; i< fh_size; i++)
+    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", sealed_NVM[i]);
+  vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+  
+  sealed_NVM_size = BSG_UnpackList(sealed_NVM, 2,
+                                  BSG_TPM_SIZE32_DATA, &symkey_cipher32,
+                                  BSG_TPM_SIZE32_DATA, &state_cipher32);
+  
+  TPMTRYRETURN( buffer_init_convert (&symkey_cipher, 
+                                    symkey_cipher32.size, 
+                                    symkey_cipher32.data) );
+  
+  TPMTRYRETURN( buffer_init_convert (&state_cipher, 
+                                    state_cipher32.size, 
+                                    state_cipher32.data) );
+  
+  Crypto_SHA1Full(sealed_NVM, sealed_NVM_size, (BYTE *) &sealedNVMHash);    
+  
+  // Verify measurement of sealed blob.
+  if (memcmp(&sealedNVMHash, &myDMI->NVM_measurement, sizeof(TPM_DIGEST)) ) {
+    vtpmlogerror(VTPM_LOG_VTPM, "VTPM LoadNVM NVM measurement check 
failed.\n");
+    vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Correct hash: ");
+    for (i=0; i< sizeof(TPM_DIGEST); i++)
+      vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", 
((BYTE*)&myDMI->NVM_measurement)[i]);
+    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+    vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Measured hash: ");
+    for (i=0; i< sizeof(TPM_DIGEST); i++)
+      vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", ((BYTE*)&sealedNVMHash)[i]);
+    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+    
+    status = TPM_AUTHFAIL;
+    goto abort_egress;
+  }
+  
+  // Decrypt Symmetric Key
+  TPMTRYRETURN( VTSP_Unbind(  myDMI->TCSContext,
+                             vtpm_globals->storageKeyHandle,
+                             &symkey_cipher,
+                             (const 
TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth,
+                             &symkey_clear,
+                             &(vtpm_globals->keyAuth) ) );
+  
+  // create symmetric key using saved bits
+  Crypto_symcrypto_initkey (&symkey, &symkey_clear);
+  
+  // Decrypt State
+  TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey, &state_cipher, 
outbuf) );
+  
+  goto egress;
+  
+ abort_egress:
+  vtpmlogerror(VTPM_LOG_VTPM, "Failed to load NVM\n.");
+  
+ egress:
+  
+  buffer_free ( &state_cipher);
+  buffer_free ( &symkey_clear);
+  buffer_free ( &symkey_cipher);
+  free( sealed_NVM );
+  Crypto_symcrypto_freekey (&symkey);
+  
+  return status;
+}
+
+TPM_RESULT VTPM_SaveService(void) {
+  TPM_RESULT status=TPM_SUCCESS;
+  int fh, dmis=-1;
+  
+  BYTE *flat_global;
+  int flat_global_size, bytes_written;
+  UINT32 storageKeySize = buffer_len(&vtpm_globals->storageKeyWrap);
+  struct pack_buf_t storage_key_pack = {storageKeySize, 
vtpm_globals->storageKeyWrap.bytes};
+  
+  struct hashtable_itr *dmi_itr;
+  VTPM_DMI_RESOURCE *dmi_res;
+  
+  UINT32 flat_global_full_size;
+  
+  // Global Values needing to be saved
+  flat_global_full_size = 3*sizeof(TPM_DIGEST) + // Auths
+    sizeof(UINT32) +       // storagekeysize
+    storageKeySize +       // storage key
+    hashtable_count(vtpm_globals->dmi_map) * // num DMIS
+    (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info
+  
+  
+  flat_global = (BYTE *) malloc( flat_global_full_size);
+  
+  flat_global_size = BSG_PackList(flat_global, 4,
+                                 BSG_TPM_AUTHDATA, 
&vtpm_globals->owner_usage_auth,
+                                 BSG_TPM_AUTHDATA, 
&vtpm_globals->srk_usage_auth,
+                                 BSG_TPM_SECRET,   
&vtpm_globals->storage_key_usage_auth,
+                                 BSG_TPM_SIZE32_DATA, &storage_key_pack);
+  
+  // Per DMI values to be saved
+  if (hashtable_count(vtpm_globals->dmi_map) > 0) {
+    
+    dmi_itr = hashtable_iterator(vtpm_globals->dmi_map);
+    do {
+      dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr);
+      dmis++;
+
+      // No need to save dmi0.
+      if (dmi_res->dmi_id == 0)        
+       continue;
+      
+      
+      flat_global_size += BSG_PackList( flat_global + flat_global_size, 3,
+                                       BSG_TYPE_UINT32, &dmi_res->dmi_id,
+                                       BSG_TPM_DIGEST, 
&dmi_res->NVM_measurement,
+                                       BSG_TPM_DIGEST, 
&dmi_res->DMI_measurement);
+      
+    } while (hashtable_iterator_advance(dmi_itr));
+  }
+  
+  //FIXME: Once we have a way to protect a TPM key, we should use it to 
+  //       encrypt this blob. BUT, unless there is a way to ensure the key is
+  //       not used by other apps, this encryption is useless.
+  fh = open(STATE_FILE, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
+  if (fh == -1) {
+    vtpmlogerror(VTPM_LOG_VTPM, "Unable to open %s file for write.\n", 
STATE_FILE);
+    status = TPM_IOERROR;
+    goto abort_egress;
+  }
+  
+  if ( (bytes_written = write(fh, flat_global, flat_global_size)) != 
flat_global_size ) {
+    vtpmlogerror(VTPM_LOG_VTPM, "Failed to save service data. %d/%d bytes 
written.\n", bytes_written, flat_global_size);
+    status = TPM_IOERROR;
+    goto abort_egress;
+  }
+  vtpm_globals->DMI_table_dirty = FALSE; 
+  
+  goto egress;
+  
+ abort_egress:
+ egress:
+  
+  free(flat_global);
+  close(fh);
+  
+  vtpmloginfo(VTPM_LOG_VTPM, "Saved VTPM Service state (status = %d, dmis = 
%d)\n", (int) status, dmis);
+  return status;
+}
+
+TPM_RESULT VTPM_LoadService(void) {
+  
+  TPM_RESULT status=TPM_SUCCESS;
+  int fh, stat_ret, dmis=0;
+  long fh_size = 0, step_size;
+  BYTE *flat_global=NULL;
+  struct pack_buf_t storage_key_pack;
+  UINT32 *dmi_id_key;
+  
+  VTPM_DMI_RESOURCE *dmi_res;
+  struct stat file_stat;
+  
+  fh = open(STATE_FILE, O_RDONLY );
+  stat_ret = fstat(fh, &file_stat);
+  if (stat_ret == 0) 
+    fh_size = file_stat.st_size;
+  else {
+    status = TPM_IOERROR;
+    goto abort_egress;
+  }
+  
+  flat_global = (BYTE *) malloc(fh_size);
+  
+  if ((long) read(fh, flat_global, fh_size) != fh_size ) {
+    status = TPM_IOERROR;
+    goto abort_egress;
+  }
+  
+  // Global Values needing to be saved
+  step_size = BSG_UnpackList( flat_global, 4,
+                             BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,
+                             BSG_TPM_AUTHDATA, &vtpm_globals->srk_usage_auth,
+                             BSG_TPM_SECRET,   
&vtpm_globals->storage_key_usage_auth,
+                             BSG_TPM_SIZE32_DATA, &storage_key_pack);
+  
+  TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap, 0, 0) );
+  TPMTRYRETURN(buffer_append_raw(&vtpm_globals->storageKeyWrap, 
storage_key_pack.size, storage_key_pack.data) );
+  
+  // Per DMI values to be saved
+  while ( step_size < fh_size ){
+    if (fh_size - step_size < (long) (sizeof(UINT32) + 2*sizeof(TPM_DIGEST))) {
+      vtpmlogerror(VTPM_LOG_VTPM, "Encountered %ld extra bytes at end of 
manager state.\n", fh_size-step_size);
+      step_size = fh_size;
+    } else {
+      dmi_res = (VTPM_DMI_RESOURCE *) malloc(sizeof(VTPM_DMI_RESOURCE));
+      dmis++;
+      
+      dmi_res->connected = FALSE;
+      
+      step_size += BSG_UnpackList(flat_global + step_size, 3,
+                                 BSG_TYPE_UINT32, &dmi_res->dmi_id, 
+                                 BSG_TPM_DIGEST, &dmi_res->NVM_measurement,
+                                 BSG_TPM_DIGEST, &dmi_res->DMI_measurement);
+      
+      // install into map
+      dmi_id_key = (UINT32 *) malloc (sizeof(UINT32));
+      *dmi_id_key = dmi_res->dmi_id;
+      if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, dmi_res)) {
+       status = TPM_FAIL;
+       goto abort_egress;
+      }
+      
+    }
+    
+  }
+  
+  goto egress;
+  
+ abort_egress:
+  vtpmlogerror(VTPM_LOG_VTPM, "Failed to save service data\n");
+ egress:
+  
+  if (flat_global)
+    free(flat_global);
+  close(fh);
+  
+  vtpmloginfo(VTPM_LOG_VTPM, "Previously saved state reloaded (status = %d, 
dmis = %d).\n", (int) status, dmis);
+  return status;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/tpmpassthrough.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/tpmpassthrough.c       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,110 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// tpmpassthrough.c
+// 
+//  Functions regarding passing DMI requests to HWTPM
+//
+// ==================================================================
+
+#include "tcg.h"
+#include "vtpm_manager.h"
+#include "vtpmpriv.h"
+#include "vtsp.h"
+#include "log.h"
+
+TPM_RESULT VTPM_Handle_TPM_Command( VTPM_DMI_RESOURCE *dmi,
+                                   buffer_t *inbuf,  
+                                   buffer_t *outbuf) {
+  
+  TPM_RESULT status = TPM_SUCCESS;
+  TPM_COMMAND_CODE *ord;               
+  
+  ord = (TPM_COMMAND_CODE *) (inbuf->bytes + sizeof(TPM_TAG) + sizeof(UINT32));
+  
+  switch (*ord) {
+    
+    // Forbidden for DMI use
+  case TPM_ORD_TakeOwnership:
+  case TPM_ORD_ChangeAuthOwner:
+  case TPM_ORD_DirWriteAuth:
+  case TPM_ORD_DirRead:
+  case TPM_ORD_AuthorizeMigrationKey:
+  case TPM_ORD_CreateMaintenanceArchive:
+  case TPM_ORD_LoadMaintenanceArchive:
+  case TPM_ORD_KillMaintenanceFeature:
+  case TPM_ORD_LoadManuMaintPub:
+  case TPM_ORD_ReadManuMaintPub:
+  case TPM_ORD_SelfTestFull:
+  case TPM_ORD_SelfTestStartup:
+  case TPM_ORD_CertifySelfTest:
+  case TPM_ORD_ContinueSelfTest:
+  case TPM_ORD_GetTestResult:
+  case TPM_ORD_Reset:
+  case TPM_ORD_OwnerClear:
+  case TPM_ORD_DisableOwnerClear:
+  case TPM_ORD_ForceClear:
+  case TPM_ORD_DisableForceClear:
+  case TPM_ORD_GetCapabilityOwner:
+  case TPM_ORD_OwnerSetDisable:
+  case TPM_ORD_PhysicalEnable:
+  case TPM_ORD_PhysicalDisable:
+  case TPM_ORD_SetOwnerInstall:
+  case TPM_ORD_PhysicalSetDeactivated:
+  case TPM_ORD_SetTempDeactivated:
+  case TPM_ORD_CreateEndorsementKeyPair:
+  case TPM_ORD_GetAuditEvent:
+  case TPM_ORD_GetAuditEventSigned:
+  case TPM_ORD_GetOrdinalAuditStatus:
+  case TPM_ORD_SetOrdinalAuditStatus:
+  case TPM_ORD_SetRedirection:
+  case TPM_ORD_FieldUpgrade:
+  case TSC_ORD_PhysicalPresence:
+    status = TPM_DISABLED_CMD;
+    goto abort_egress;
+    break;
+    
+  } // End ORD Switch
+  
+  // Call TCS with command
+  
+  TPMTRY(TPM_IOERROR, VTSP_RawTransmit( dmi->TCSContext,inbuf, outbuf) );
+  
+  goto egress;
+  
+ abort_egress:
+  vtpmloginfo(VTPM_LOG_VTPM, "TPM Command Failed in tpmpassthrough.\n");
+ egress:
+  
+  return status;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/vtpm_manager.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/vtpm_manager.c Fri Sep  9 16:30:54 2005
@@ -0,0 +1,735 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// vtpm_manager.c
+// 
+//  This file will house the main logic of the VTPM Manager
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+#ifndef VTPM_MULTI_VM
+#include <pthread.h>
+#include <errno.h>
+#include <aio.h>
+#include <time.h>
+#endif
+
+#include "vtpm_manager.h"
+#include "vtpmpriv.h"
+#include "vtsp.h"
+#include "bsg.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+
+#include "log.h"
+#include "buffer.h"
+
+VTPM_GLOBALS *vtpm_globals=NULL;
+
+#ifdef VTPM_MULTI_VM
+ #define vtpmhandlerloginfo(module,fmt,args...) vtpmloginfo (module, fmt, 
##args );
+ #define vtpmhandlerloginfomore(module,fmt,args...) vtpmloginfomore (module, 
fmt, ##args );
+ #define vtpmhandlerlogerror(module,fmt,args...) vtpmlogerror (module, fmt, 
##args );
+#else 
+ #define vtpmhandlerloginfo(module,fmt,args...) vtpmloginfo (module, "[%d]: " 
fmt, threadType, ##args );
+ #define vtpmhandlerloginfomore(module,fmt,args...) vtpmloginfomore (module, 
fmt, ##args );
+ #define vtpmhandlerlogerror(module,fmt,args...) vtpmlogerror (module, "[%d]: 
" fmt, threadType, ##args );
+#endif
+
+// --------------------------- Static Auths --------------------------
+#ifdef USE_FIXED_SRK_AUTH
+
+static BYTE FIXED_SRK_AUTH[20] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff,
+                                  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff};
+
+static BYTE FIXED_EK_AUTH[20] =  {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff,
+                                  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff};
+
+#endif
+                                  
+// -------------------------- Hash table functions --------------------
+
+static unsigned int hashfunc32(void *ky) {
+  return (* (UINT32 *) ky);
+}
+
+static int equals32(void *k1, void *k2) {
+  return (*(UINT32 *) k1 == *(UINT32 *) k2);
+}
+
+// --------------------------- Functions ------------------------------
+
+TPM_RESULT VTPM_Create_Service(){
+  
+  TPM_RESULT status = TPM_SUCCESS;
+  
+  // Generate Auth's for SRK & Owner
+#ifdef USE_FIXED_SRK_AUTH
+  memcpy(vtpm_globals->owner_usage_auth, FIXED_SRK_AUTH, sizeof(TPM_AUTHDATA));
+  memcpy(vtpm_globals->srk_usage_auth, FIXED_EK_AUTH, sizeof(TPM_AUTHDATA));
+#else    
+  Crypto_GetRandom(vtpm_globals->owner_usage_auth, sizeof(TPM_AUTHDATA) );
+  Crypto_GetRandom(vtpm_globals->srk_usage_auth, sizeof(TPM_AUTHDATA) );  
+#endif
+  
+  // Take Owership of TPM
+  CRYPTO_INFO ek_cryptoInfo;
+  
+  vtpmloginfo(VTPM_LOG_VTPM, "Attempting Pubek Read. NOTE: Failure is ok.\n");
+  status = VTSP_ReadPubek(vtpm_globals->manager_tcs_handle, &ek_cryptoInfo);
+  
+  // If we can read PubEK then there is no owner and we should take it.
+  if (status == TPM_SUCCESS) { 
+    TPMTRYRETURN(VTSP_TakeOwnership(vtpm_globals->manager_tcs_handle,
+                                   (const 
TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth, 
+                                   (const 
TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
+                                   &ek_cryptoInfo,
+                                   &vtpm_globals->keyAuth)); 
+  
+    TPMTRYRETURN(VTSP_DisablePubekRead(vtpm_globals->manager_tcs_handle,
+                                       (const 
TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth,  
+                                       &vtpm_globals->keyAuth));     
+  }
+  
+  // Generate storage key's auth
+  Crypto_GetRandom(  &vtpm_globals->storage_key_usage_auth, 
+                    sizeof(TPM_AUTHDATA) );
+  
+  TCS_AUTH osap;
+  TPM_AUTHDATA sharedsecret;
+  
+  TPMTRYRETURN( VTSP_OSAP(vtpm_globals->manager_tcs_handle,
+                         TPM_ET_SRK,
+                         0, 
+                         (const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
+                         &sharedsecret, 
+                         &osap) ); 
+  
+  TPMTRYRETURN( VTSP_CreateWrapKey( vtpm_globals->manager_tcs_handle,
+                                   TPM_KEY_BIND,
+                                   (const 
TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth,
+                                   TPM_SRK_KEYHANDLE, 
+                                   (const TPM_AUTHDATA*)&sharedsecret,
+                                   &vtpm_globals->storageKeyWrap,
+                                   &osap) );
+  
+  vtpm_globals->keyAuth.fContinueAuthSession = TRUE;
+  
+  goto egress;
+  
+ abort_egress:
+  exit(1);
+  
+ egress:
+  vtpmloginfo(VTPM_LOG_VTPM, "New VTPM Service initialized (Status = %d).\n", 
status);
+  return status;
+  
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+#ifdef VTPM_MULTI_VM
+int VTPM_Service_Handler(){
+#else
+void *VTPM_Service_Handler(void *threadTypePtr){
+#endif
+  TPM_RESULT      status =  TPM_FAIL; // Should never return
+  UINT32          dmi, in_param_size, cmd_size, out_param_size, 
out_message_size, out_message_size_full, dmi_cmd_size;
+  BYTE            *cmd_header, *in_param, *out_message, *dmi_cmd;
+  buffer_t        *command_buf=NULL, *result_buf=NULL;
+  TPM_TAG         tag;
+  TPM_COMMAND_CODE ord;
+  VTPM_DMI_RESOURCE *dmi_res;
+  int  size_read, size_write, i;
+  
+#ifndef VTPM_MULTI_VM
+  int threadType = *(int *) threadTypePtr;
+  
+  // async io structures
+  struct aiocb dmi_aio;
+  struct aiocb *dmi_aio_a[1];
+  dmi_aio_a[0] = &dmi_aio;
+#endif
+  
+#ifdef DUMMY_BACKEND
+  int dummy_rx;  
+#endif
+  
+  // TODO: Reinsert ifdefs to enable support for MULTI-VM 
+  
+  cmd_header = (BYTE *) malloc(VTPM_COMMAND_HEADER_SIZE_SRV);
+  command_buf = (buffer_t *) malloc(sizeof(buffer_t));
+  result_buf = (buffer_t *) malloc(sizeof(buffer_t));
+  
+#ifndef VTPM_MULTI_VM
+  TPM_RESULT *ret_value = (TPM_RESULT *) malloc(sizeof(TPM_RESULT));
+#endif
+  
+  int *tx_fh, *rx_fh;
+  
+#ifdef VTPM_MULTI_VM
+  rx_fh = &vtpm_globals->be_fh;
+#else
+  if (threadType == BE_LISTENER_THREAD) {
+#ifdef DUMMY_BACKEND    
+    dummy_rx = -1;
+    rx_fh = &dummy_rx;
+#else
+    rx_fh = &vtpm_globals->be_fh;
+#endif
+  } else { // DMI_LISTENER_THREAD
+    rx_fh = &vtpm_globals->vtpm_rx_fh;
+  }
+#endif
+  
+#ifndef VTPM_MULTI_VM
+  int fh;
+  if (threadType == BE_LISTENER_THREAD) {
+    tx_fh = &vtpm_globals->be_fh;
+    if ( (fh = open(GUEST_RX_FIFO, O_RDWR)) == -1) {
+      if ( mkfifo(GUEST_RX_FIFO, S_IWUSR | S_IRUSR ) ){
+                               *ret_value = TPM_FAIL;
+                               pthread_exit(ret_value);
+      }
+    } else 
+      close(fh);
+    
+  } else { // else DMI_LISTENER_THREAD
+    // tx_fh will be set once the DMI is identified
+    // But we need to make sure the read pip is created.
+    if ( (fh = open(VTPM_RX_FIFO, O_RDWR)) == -1) {
+      if ( mkfifo(VTPM_RX_FIFO, S_IWUSR | S_IRUSR ) ){
+       *ret_value = TPM_FAIL;
+       pthread_exit(ret_value);
+      }
+    } else 
+      close(fh);
+    
+  }
+#endif
+  
+  while(1) {
+    
+    if (threadType == BE_LISTENER_THREAD) {
+      vtpmhandlerloginfo(VTPM_LOG_VTPM, "Waiting for Guest requests & ctrl 
messages.\n");
+    } else 
+      vtpmhandlerloginfo(VTPM_LOG_VTPM, "Waiting for DMI messages.\n");
+    
+    
+    if (*rx_fh < 0) {
+      if (threadType == BE_LISTENER_THREAD) 
+#ifdef DUMMY_BACKEND
+       *rx_fh = open("/tmp/in.fifo", O_RDWR);
+#else
+        *rx_fh = open(VTPM_BE_DEV, O_RDWR);
+#endif
+      else  // DMI Listener   
+       *rx_fh = open(VTPM_RX_FIFO, O_RDWR);
+      
+    }
+    
+    if (*rx_fh < 0) {
+      vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't open inbound fh.\n");
+#ifdef VTPM_MULTI_VM
+      return TPM_IOERROR; 
+#else
+      *ret_value = TPM_IOERROR;
+      pthread_exit(ret_value);
+#endif
+    }
+    
+    size_read = read(*rx_fh, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV);
+    if (size_read > 0) {
+      vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "RECV[%d}: 0x", size_read);
+      for (i=0; i<size_read; i++) 
+               vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", 
cmd_header[i]);
+    } else {
+      vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't read from BE. Aborting... \n");
+      close(*rx_fh);
+      *rx_fh = -1;
+      goto abort_command;
+    }
+
+    if (size_read < (int) VTPM_COMMAND_HEADER_SIZE_SRV) {
+      vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "\n");
+      vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command shorter than normal header 
(%d bytes). Aborting...\n", size_read);
+      goto abort_command;
+    }
+    
+    BSG_UnpackList(cmd_header, 4,
+                  BSG_TYPE_UINT32, &dmi,
+                  BSG_TPM_TAG, &tag,
+                  BSG_TYPE_UINT32, &in_param_size,
+                  BSG_TPM_COMMAND_CODE, &ord );
+    
+    // Note that in_param_size is in the client's context
+    cmd_size = in_param_size - VTPM_COMMAND_HEADER_SIZE_CLT;
+    if (cmd_size > 0) {
+      in_param = (BYTE *) malloc(cmd_size);
+      size_read = read( *rx_fh, in_param, cmd_size);
+      if (size_read > 0) {
+       for (i=0; i<size_read; i++) 
+         vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", in_param[i]);
+       
+      } else {
+        vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error reading from BE. Aborting... 
\n");
+       close(*rx_fh);
+       *rx_fh = -1;
+       goto abort_command;
+      }
+      vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+      
+      if (size_read < (int) cmd_size) {
+       vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+       vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command read(%d) is shorter than 
header indicates(%d). Aborting...\n", size_read, cmd_size);
+       goto abort_command;
+      }
+    } else {
+      in_param = NULL;
+      vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+    }            
+    
+    if ((threadType != BE_LISTENER_THREAD) && (dmi == 0)) {
+      vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempt to access dom0 commands from 
DMI interface. Aborting...\n");
+      goto abort_command;
+    }
+    
+    dmi_res = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map, 
&dmi);
+    if (dmi_res == NULL) {
+      vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempted access to non-existent DMI 
in domain: %d. Aborting...\n", dmi);
+      goto abort_command;
+    }
+    if (!dmi_res->connected) {
+      vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempted access to disconnected DMI 
in domain: %d. Aborting...\n", dmi);
+      goto abort_command;
+    }
+    
+    if (threadType != BE_LISTENER_THREAD) 
+      tx_fh = &dmi_res->vtpm_tx_fh;
+    // else we set this before the while loop since it doesn't change.
+    
+    if ( (buffer_init_convert(command_buf, cmd_size, in_param) != TPM_SUCCESS) 
|| 
+        (buffer_init(result_buf, 0, 0) != TPM_SUCCESS) ) {
+      vtpmhandlerlogerror(VTPM_LOG_VTPM, "Failed to setup buffers. 
Aborting...\n");
+      goto abort_command;
+    }
+    
+    // Dispatch it as either control or user request.
+    if (tag == VTPM_TAG_REQ) { 
+      if (dmi_res->dmi_id == VTPM_CTL_DM){ 
+       switch (ord) {
+       case VTPM_ORD_OPEN:
+         status = VTPM_Handle_New_DMI(command_buf);
+         break;
+          
+       case VTPM_ORD_CLOSE:
+         status = VTPM_Handle_Close_DMI(command_buf);
+         break;
+          
+       case VTPM_ORD_DELETE:
+         status = VTPM_Handle_Delete_DMI(command_buf);
+         break;
+       default:
+         status = TPM_BAD_ORDINAL; 
+       } // switch
+      } else {
+       
+       switch (ord) {                
+       case VTPM_ORD_SAVENVM:
+         status= VTPM_Handle_Save_NVM(dmi_res,
+                                      command_buf, 
+                                      result_buf);
+         break;
+       case VTPM_ORD_LOADNVM:
+         status= VTPM_Handle_Load_NVM(dmi_res, 
+                                      command_buf, 
+                                      result_buf);
+         break;
+         
+       case VTPM_ORD_TPMCOMMAND:
+         status= VTPM_Handle_TPM_Command(dmi_res, 
+                                         command_buf, 
+                                         result_buf);
+         break;
+         
+       default:
+         status = TPM_BAD_ORDINAL; 
+       } // switch
+      }
+    } else { // This is not a VTPM Command at all
+      
+      if (threadType == BE_LISTENER_THREAD) {
+       if (dmi == 0) {
+         // This usually indicates a FE/BE driver.
+         vtpmhandlerlogerror(VTPM_LOG_VTPM, "Illegal use of TPM command from 
dom0\n");
+         status = TPM_FAIL;
+       } else {
+         vtpmhandlerloginfo(VTPM_LOG_VTPM, "Forwarding command to DMI.\n");
+         
+         if (dmi_res->guest_tx_fh < 0)
+           dmi_res->guest_tx_fh = open(dmi_res->guest_tx_fname, O_WRONLY | 
O_NONBLOCK);
+          
+         if (dmi_res->guest_tx_fh < 0){
+           vtpmhandlerlogerror(VTPM_LOG_VTPM, "VTPM ERROR: Can't open outbound 
fh to dmi.\n");
+           status = TPM_IOERROR;
+           goto abort_with_error;
+         }        
+          
+         //Note: Send message + dmi_id
+         if (cmd_size) {
+           dmi_cmd = (BYTE *) malloc(VTPM_COMMAND_HEADER_SIZE_SRV + cmd_size);
+           dmi_cmd_size = VTPM_COMMAND_HEADER_SIZE_SRV + cmd_size;
+           memcpy(dmi_cmd, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV);
+           memcpy(dmi_cmd + VTPM_COMMAND_HEADER_SIZE_SRV, in_param, cmd_size);
+           size_write = write(dmi_res->guest_tx_fh, dmi_cmd, dmi_cmd_size);
+           
+           if (size_write > 0) {
+             vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT (DMI): 0x");
+             for (i=0; i<VTPM_COMMAND_HEADER_SIZE_SRV + cmd_size; i++) {
+               vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", dmi_cmd[i]);
+             }
+             vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+           } else {
+              vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error writing to DMI. 
Aborting... \n");
+             close(dmi_res->guest_tx_fh);
+             dmi_res->guest_tx_fh = -1;
+              status = TPM_IOERROR;
+             goto abort_with_error;
+           }
+           free(dmi_cmd);
+         } else {
+           dmi_cmd_size = VTPM_COMMAND_HEADER_SIZE_SRV;
+           size_write = write(dmi_res->guest_tx_fh, cmd_header, 
VTPM_COMMAND_HEADER_SIZE_SRV );
+           if (size_write > 0) {
+             for (i=0; i<VTPM_COMMAND_HEADER_SIZE_SRV; i++) 
+               vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", 
cmd_header[i]);
+             
+             vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+           } else {
+              vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error writing to DMI. 
Aborting... \n");
+             close(dmi_res->guest_tx_fh);
+             dmi_res->guest_tx_fh = -1;
+              status = TPM_IOERROR;
+             goto abort_with_error;
+           }
+         }
+          
+         if (size_write != (int) dmi_cmd_size) 
+           vtpmhandlerlogerror(VTPM_LOG_VTPM, "Could not write entire command 
to DMI (%d/%d)\n", size_write, dmi_cmd_size);
+         buffer_free(command_buf);
+         
+         if (vtpm_globals->guest_rx_fh < 0) 
+           vtpm_globals->guest_rx_fh = open(GUEST_RX_FIFO, O_RDONLY);
+          
+         if (vtpm_globals->guest_rx_fh < 0){
+           vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't open inbound fh to 
dmi.\n");
+            status = TPM_IOERROR;
+           goto abort_with_error;
+         }                  
+         
+          size_read = read( vtpm_globals->guest_rx_fh, cmd_header, 
VTPM_COMMAND_HEADER_SIZE_SRV);
+         if (size_read > 0) {
+           vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "RECV (DMI): 0x");
+           for (i=0; i<size_read; i++) 
+             vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cmd_header[i]);
+           
+         } else {
+            vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error reading from DMI. 
Aborting... \n");
+           close(vtpm_globals->guest_rx_fh);
+           vtpm_globals->guest_rx_fh = -1;
+            status = TPM_IOERROR;
+           goto abort_with_error;
+         }
+          
+         if (size_read < (int) VTPM_COMMAND_HEADER_SIZE_SRV) {
+           //vtpmdeepsublog("\n");
+           vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command from DMI shorter than 
normal header. Aborting...\n");
+            status = TPM_IOERROR;
+           goto abort_with_error;
+         }
+          
+         BSG_UnpackList(cmd_header, 4,
+                        BSG_TYPE_UINT32, &dmi,
+                        BSG_TPM_TAG, &tag,
+                        BSG_TYPE_UINT32, &in_param_size,
+                        BSG_TPM_COMMAND_CODE, &status );
+        
+         // Note that in_param_size is in the client's context
+         cmd_size = in_param_size - VTPM_COMMAND_HEADER_SIZE_CLT;
+         if (cmd_size > 0) {
+           in_param = (BYTE *) malloc(cmd_size);
+           size_read = read( vtpm_globals->guest_rx_fh, in_param, cmd_size);
+           if (size_read > 0) {
+             for (i=0; i<size_read; i++) 
+               vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", in_param[i]);
+             
+           } else {
+              vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error reading from BE. 
Aborting... \n");
+             close(vtpm_globals->guest_rx_fh);
+             vtpm_globals->guest_rx_fh = -1;
+              status = TPM_IOERROR;
+             goto abort_with_error;
+           }
+           vtpmhandlerloginfomore(VTPM_LOG_VTPM, "\n");
+            
+           if (size_read < (int)cmd_size) {
+             vtpmhandlerloginfomore(VTPM_LOG_VTPM, "\n");
+             vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command read(%d) from DMI is 
shorter than header indicates(%d). Aborting...\n", size_read, cmd_size);
+              status = TPM_IOERROR;
+             goto abort_with_error;
+           }
+         } else {
+           in_param = NULL;
+           vtpmhandlerloginfomore(VTPM_LOG_VTPM, "\n");
+         }
+                           
+         if (buffer_init_convert(result_buf, cmd_size, in_param) != 
TPM_SUCCESS) {
+           vtpmhandlerlogerror(VTPM_LOG_VTPM, "Failed to setup buffers. 
Aborting...\n");
+            status = TPM_FAIL;
+           goto abort_with_error;
+         }
+         
+         vtpmhandlerloginfo(VTPM_LOG_VTPM, "Sending DMI's response to 
guest.\n");
+       } // end else for if (dmi==0)
+        
+      } else { // This is a DMI lister thread. Thus this is from a DMI
+#ifdef VTPM_MULTI_VM
+       vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempt to use unsupported direct 
access to TPM.\n");
+       vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "Bad Command. dmi:%d, tag:%d, 
size:%d, ord:%d, Params: ", dmi, tag, in_param_size, ord);
+       for (UINT32 q=0; q<cmd_size; q++) 
+         vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", in_param[q]);
+       
+       vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+        
+       status = TPM_FAIL;
+#else
+       
+#endif
+      } // end else for if BE Listener
+    } // end else for is VTPM Command
+    
+    // Send response to Backend
+    if (*tx_fh < 0) {
+      if (threadType == BE_LISTENER_THREAD) 
+#ifdef DUMMY_BACKEND
+       *tx_fh = open("/tmp/out.fifo", O_RDWR);
+#else
+        *tx_fh = open(VTPM_BE_DEV, O_RDWR);
+#endif
+      else  // DMI Listener
+       *tx_fh = open(dmi_res->vtpm_tx_fname, O_WRONLY);
+    }
+    
+    if (*tx_fh < 0) {
+      vtpmhandlerlogerror(VTPM_LOG_VTPM, "VTPM ERROR: Can't open outbound 
fh.\n");
+#ifdef VTPM_MULTI_VM
+      return TPM_IOERROR; 
+#else
+      *ret_value = TPM_IOERROR;
+      pthread_exit(ret_value);
+#endif
+    }        
+    
+ abort_with_error:
+    // Prepend VTPM header with destination DM stamped
+    out_param_size = buffer_len(result_buf);
+    out_message_size = VTPM_COMMAND_HEADER_SIZE_CLT + out_param_size;
+    out_message_size_full = VTPM_COMMAND_HEADER_SIZE_SRV + out_param_size;
+    out_message = (BYTE *) malloc (out_message_size_full);
+    
+    BSG_PackList(out_message, 4,
+                BSG_TYPE_UINT32, (BYTE *) &dmi,
+                BSG_TPM_TAG, (BYTE *) &tag,
+                BSG_TYPE_UINT32, (BYTE *) &out_message_size,
+                BSG_TPM_RESULT, (BYTE *) &status);
+    
+    if (buffer_len(result_buf) > 0) 
+      memcpy(out_message + VTPM_COMMAND_HEADER_SIZE_SRV, result_buf->bytes, 
out_param_size);
+    
+    
+    //Note: Send message + dmi_id
+    size_write = write(*tx_fh, out_message, out_message_size_full );
+    if (size_write > 0) {
+      vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT: 0x");
+      for (i=0; i < out_message_size_full; i++) 
+       vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", out_message[i]);
+      
+      vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");            
+    } else {
+      vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error writing to BE. Aborting... 
\n");
+      close(*tx_fh);
+      *tx_fh = -1;
+      goto abort_command;
+    }
+    free(out_message);
+    
+    if (size_write < (int)out_message_size_full) {
+      vtpmhandlerlogerror(VTPM_LOG_VTPM, "Unable to write full command to BE 
(%d/%d)\n", size_write, out_message_size_full);
+      goto abort_command;
+    }
+    
+  abort_command:
+    //free buffers
+    bzero(cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV);
+    //free(in_param); // This was converted to command_buf. No need to free 
+    if (command_buf != result_buf) 
+      buffer_free(result_buf);
+    
+    buffer_free(command_buf);
+    
+#ifndef VTPM_MULTI_VM
+    if (threadType != BE_LISTENER_THREAD) {
+#endif
+      if ( (vtpm_globals->DMI_table_dirty) &&
+          (VTPM_SaveService() != TPM_SUCCESS) ) {
+       vtpmhandlerlogerror(VTPM_LOG_VTPM, "ERROR: Unable to save manager 
data.\n");
+      }
+#ifndef VTPM_MULTI_VM
+    }
+#endif
+    
+  } // End while(1)
+  
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+TPM_RESULT VTPM_Init_Service() {
+  TPM_RESULT status = TPM_FAIL;   
+  BYTE *randomsead;
+       UINT32 randomsize;
+       
+  if ((vtpm_globals = (VTPM_GLOBALS *) malloc(sizeof(VTPM_GLOBALS))) == NULL){
+               status = TPM_FAIL;
+               goto abort_egress;
+       }
+       memset(vtpm_globals, 0, sizeof(VTPM_GLOBALS));
+  vtpm_globals->be_fh = -1;
+
+#ifndef VTPM_MULTI_VM
+  vtpm_globals->vtpm_rx_fh = -1;
+  vtpm_globals->guest_rx_fh = -1;
+#endif
+  if ((vtpm_globals->dmi_map = create_hashtable(10, hashfunc32, equals32)) == 
NULL){
+               status = TPM_FAIL;
+               goto abort_egress;
+       }
+  
+  vtpm_globals->DMI_table_dirty = FALSE;
+  
+  // Create new TCS Object
+  vtpm_globals->manager_tcs_handle = 0;
+  
+  TPMTRYRETURN(TCS_create());
+  
+  // Create TCS Context for service
+  TPMTRYRETURN( TCS_OpenContext(&vtpm_globals->manager_tcs_handle ) );
+
+       TPMTRYRETURN( TCSP_GetRandom(vtpm_globals->manager_tcs_handle, 
+                                                                               
                                         &randomsize, 
+                                                                               
                                         &randomsead));
+
+       Crypto_Init(randomsead, randomsize);
+       TPMTRYRETURN( TCS_FreeMemory (vtpm_globals->manager_tcs_handle, 
randomsead)); 
+       
+  // Create OIAP session for service's authorized commands
+  TPMTRYRETURN( VTSP_OIAP( vtpm_globals->manager_tcs_handle, 
+                          &vtpm_globals->keyAuth) );
+  vtpm_globals->keyAuth.fContinueAuthSession = TRUE;
+
+       // If failed, create new Service.
+  if (VTPM_LoadService() != TPM_SUCCESS)
+    TPMTRYRETURN( VTPM_Create_Service() );    
+
+  
+  //Load Storage Key 
+  TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle,
+                             TPM_SRK_KEYHANDLE,
+                             &vtpm_globals->storageKeyWrap,
+                             (const 
TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
+                             &vtpm_globals->storageKeyHandle,
+                             &vtpm_globals->keyAuth,
+                             &vtpm_globals->storageKey) );
+  
+  // Create entry for Dom0 for control messages
+  TPMTRYRETURN( VTPM_Handle_New_DMI(NULL) );
+  
+  // --------------------- Command handlers ---------------------------
+  
+  goto egress;
+  
+ abort_egress:
+ egress:
+  
+  return(status);
+}
+ 
+void VTPM_Stop_Service() {
+  VTPM_DMI_RESOURCE *dmi_res;
+  struct hashtable_itr *dmi_itr;
+  
+  // Close all the TCS contexts. TCS should evict keys based on this
+  if (hashtable_count(vtpm_globals->dmi_map) > 0) {
+    dmi_itr = hashtable_iterator(vtpm_globals->dmi_map);
+    do {
+      dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr);
+      if (dmi_res->connected) 
+                               if (close_dmi( dmi_res ) != TPM_SUCCESS) 
+                                       vtpmlogerror(VTPM_LOG_VTPM, "Failed to 
close dmi %d properly.\n", dmi_res->dmi_id);
+      
+    } while (hashtable_iterator_advance(dmi_itr));
+               free (dmi_itr);
+  }
+  
+       
+  TCS_CloseContext(vtpm_globals->manager_tcs_handle);
+  
+  if ( (vtpm_globals->DMI_table_dirty) &&
+       (VTPM_SaveService() != TPM_SUCCESS) )
+    vtpmlogerror(VTPM_LOG_VTPM, "Unable to save manager data.\n");
+  
+  hashtable_destroy(vtpm_globals->dmi_map, 1);
+  free(vtpm_globals);
+  
+  close(vtpm_globals->be_fh);
+  Crypto_Exit();
+       
+  vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager stopped.\n");
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/vtpm_manager.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/vtpm_manager.h Fri Sep  9 16:30:54 2005
@@ -0,0 +1,137 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// vtpm_manager.h
+// 
+//  Public Interface header for VTPM Manager
+//
+// ==================================================================
+
+#ifndef __VTPM_MANAGER_H__
+#define __VTPM_MANAGER_H__
+
+#include "tcg.h"
+
+#define VTPM_TAG_REQ 0x01c1
+#define VTPM_TAG_RSP 0x01c4
+#define COMMAND_BUFFER_SIZE 4096
+
+// Header sizes. Note Header MAY include the DMI
+#define VTPM_COMMAND_HEADER_SIZE_SRV ( sizeof(UINT32) + sizeof(TPM_TAG) + 
sizeof(UINT32) + sizeof(TPM_COMMAND_CODE))
+#define VTPM_COMMAND_HEADER_SIZE_CLT (                  sizeof(TPM_TAG) + 
sizeof(UINT32) + sizeof(TPM_COMMAND_CODE))
+
+// ********************** Public Functions *************************
+TPM_RESULT VTPM_Init_Service(); // Start VTPM Service
+void VTPM_Stop_Service();  // Stop VTPM Service
+#ifdef VTPM_MULTI_VM
+int VTPM_Service_Handler();
+#else
+void *VTPM_Service_Handler(void *threadTypePtr);
+#endif
+
+//************************ Command Codes ****************************
+#define VTPM_ORD_OPEN              1   // ULM Creates New DMI
+#define VTPM_ORD_CLOSE             2   // ULM Closes a DMI
+#define VTPM_ORD_DELETE            3   // ULM Permemently Deletes DMI
+#define VTPM_ORD_SAVENVM          4   // DMI requests Secrets Unseal
+#define VTPM_ORD_LOADNVM          5   // DMI requests Secrets Saved
+#define VTPM_ORD_TPMCOMMAND       6   // DMI issues HW TPM Command
+
+//************************ Return Codes ****************************
+#define VTPM_SUCCESS               0
+#define VTPM_FAIL                  1
+#define VTPM_UNSUPPORTED           2
+#define VTPM_FORBIDDEN             3
+#define VTPM_RESTORE_CONTEXT_FAILED    4
+#define VTPM_INVALID_REQUEST       5
+
+/******************* Command Parameter API *************************
+
+VTPM Command Format
+  dmi: 4 bytes                  // Source of message. 
+                                // WARNING: This is prepended by the channel. 
+                                // Thus it is received by VTPM Manager, 
+                                // but not sent by DMI
+  tpm tag: 2 bytes
+  command size: 4 bytes         // Size of command including header but not DMI
+  ord: 4 bytes                  // Command ordinal above
+  parameters: size - 10 bytes   // Command Parameter
+
+VTPM Response Format
+  tpm tag: 2 bytes
+  response_size: 4 bytes
+  status: 4 bytes         
+  parameters: size - 10 bytes
+
+
+VTPM_Open:
+  Input Parameters:
+    Domain_type: 1 byte
+    domain_id: 4 bytes
+    instance_id: 4 bytes
+  Output Parameters:
+    None
+    
+VTPM_Close
+  Input Parameters:
+    instance_id: 4 bytes
+  Output Parameters:
+    None
+
+VTPM_Delete
+  Input Parameters:
+    instance_id: 4 bytes
+  Output Parameters:
+    None
+
+VTPM_SaveNVM
+  Input Parameters:
+    data: n bytes (Header indicates size of data)
+  Output Parameters:
+    None
+
+VTPM_LoadNVM
+  Input Parameters:
+    None
+  Output Parameters:
+    data: n bytes (Header indicates size of data)
+
+VTPM_TPMCommand
+  Input Parameters:
+    TPM Command Byte Stream: n bytes 
+  Output Parameters:
+    TPM Reponse Byte Stream: n bytes 
+
+*********************************************************************/
+
+#endif //_VTPM_MANAGER_H_
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/vtpmd.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/vtpmd.c        Fri Sep  9 16:30:54 2005
@@ -0,0 +1,134 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// vtpmd.c
+// 
+//  Application
+//
+// ===================================================================
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "vtpm_manager.h"
+#include "vtpmpriv.h"
+#include "tcg.h"
+#include "log.h"
+
+#ifndef VTPM_MULTI_VM
+ #include <pthread.h>
+#endif
+
+void signal_handler(int reason) {
+#ifndef VTPM_MULTI_VM
+
+  if (pthread_equal(pthread_self(), vtpm_globals->master_pid)) {
+    if (reason >= 0) { // Reason is a signal
+      vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager shutting down for signal 
%d.\n", reason);
+    } else  {// Reason is a TPM_RESULT * -1
+      vtpmloginfo(VTPM_LOG_VTPM,"VTPM Manager shuting down for: %s\n", 
tpm_get_error_name(-1 * reason) );
+    }
+    
+    return;
+  } else {
+    vtpmloginfo(VTPM_LOG_VTPM, "Child shutting down\n");
+    pthread_exit(NULL);
+  }
+#else
+  VTPM_Stop_Service();
+  exit(-1);
+#endif
+}
+
+struct sigaction ctl_c_handler;
+
+int main(int argc, char **argv) {
+
+  vtpmloginfo(VTPM_LOG_VTPM, "Starting VTPM.\n");
+  
+  if (VTPM_Init_Service() != TPM_SUCCESS) {
+    vtpmlogerror(VTPM_LOG_VTPM, "Closing vtpmd due to error during 
startup.\n");
+    return -1;
+  }
+  
+  ctl_c_handler.sa_handler = signal_handler;
+  sigemptyset(&ctl_c_handler.sa_mask);
+  ctl_c_handler.sa_flags = 0;    
+  
+  if (sigaction(SIGINT, &ctl_c_handler, NULL) == -1) 
+    vtpmlogerror(VTPM_LOG_VTPM, "Could not install SIGINT handler. Ctl+break 
will not stop service gently.\n");
+  
+  // For easier debuggin with gdb
+  if (sigaction(SIGHUP, &ctl_c_handler, NULL) == -1) 
+    vtpmlogerror(VTPM_LOG_VTPM, "Could not install SIGHUP handler. Ctl+break 
will not stop service gently.\n");    
+  
+#ifdef VTPM_MULTI_VM
+  TPM_RESULT status = VTPM_Service_Handler();
+    
+  if (status != TPM_SUCCESS) 
+    vtpmlogerror(VTPM_LOG_VTPM, "VTPM Manager exited with status %s. It never 
should exit.\n", tpm_get_error_name(status));
+  
+  return -1;
+#else
+  sigset_t sig_mask;
+      
+  sigemptyset(&sig_mask);
+  sigaddset(&sig_mask, SIGPIPE);
+  sigprocmask(SIG_BLOCK, &sig_mask, NULL);
+  //pthread_mutex_init(&vtpm_globals->dmi_mutex, NULL);
+  pthread_t be_thread, dmi_thread;
+  int betype_be, dmitype_dmi;
+  
+  vtpm_globals->master_pid = pthread_self();
+  
+  betype_be = BE_LISTENER_THREAD;
+  if (pthread_create(&be_thread, NULL, VTPM_Service_Handler, &betype_be) != 0) 
{
+    vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch BE Thread.\n");
+    exit(-1);
+  }
+  
+  dmitype_dmi = DMI_LISTENER_THREAD;
+  if (pthread_create(&dmi_thread, NULL, VTPM_Service_Handler, &dmitype_dmi) != 
0) {
+    vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch DMI Thread.\n");
+    exit(-1);
+  }
+  
+  //Join the other threads until exit time.
+  pthread_join(be_thread, NULL);
+  pthread_join(dmi_thread, NULL);
+  
+  VTPM_Stop_Service();
+  return 0;
+#endif
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/vtpmpriv.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/vtpmpriv.h     Fri Sep  9 16:30:54 2005
@@ -0,0 +1,151 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// vtpmpriv.h
+// 
+//  Structures and functions private to the manager
+//
+// ==================================================================
+
+#ifndef __VTPMPRIV_H__
+#define __VTPMPRIV_H__
+
+#include "tcg.h"
+#include "tcs.h"
+#include "buffer.h"
+#include "crypto.h"
+
+#define STATE_FILE    "/var/vtpm/VTPM"
+#define DMI_NVM_FILE  "/var/vtpm/vtpm_dm_%d.data"
+#define VTPM_BE_DEV   "/dev/vtpm"
+#define VTPM_CTL_DM         0
+
+#ifndef VTPM_MUTLI_VM
+ #include <sys/types.h>
+ #define GUEST_TX_FIFO "/var/vtpm/fifos/guest-to-%d.fifo"
+ #define GUEST_RX_FIFO "/var/vtpm/fifos/guest-from-all.fifo"
+
+ #define VTPM_TX_FIFO  "/var/vtpm/fifos/vtpm-to-%d.fifo"
+ #define VTPM_RX_FIFO  "/var/vtpm/fifos/vtpm-from-all.fifo"
+
+ #define BE_LISTENER_THREAD 1
+ #define DMI_LISTENER_THREAD 2
+
+ // Seconds until DMI timeout. Timeouts result in DMI being out
+ // of sync, which may require a reboot of DMI and guest to recover
+ // from. Don't set this to low. Also note that DMI may issue a TPM
+ // call so we should expect time to process at DMI + TPM processing.
+ #define DMI_TIMEOUT 90 
+#endif
+
+
+// ------------------------ Private Structures -----------------------
+typedef struct VTPM_DMI_RESOURCE_T {
+  // I/O info for Manager to talk to DMI's over FIFOs
+#ifndef VTPM_MUTLI_VM
+  int                   guest_tx_fh;          // open GUEST_TX_FIFO
+  int                   vtpm_tx_fh;           // open VTPM_TX_FIFO
+  char                  *guest_tx_fname;      // open GUEST_TX_FIFO
+  char                  *vtpm_tx_fname;       // open VTPM_TX_FIFO
+  
+  pid_t                 dmi_pid;
+#endif
+  // Non-persistent Information
+  bool                  connected;
+  UINT32                dmi_domain_id;
+  TCS_CONTEXT_HANDLE    TCSContext;     // TCS Handle
+  char                  *NVMLocation;   // NULL term string indicating location
+                                        // of NVM.
+  // Persistent Information about DMI
+  UINT32                dmi_id;
+  TPM_DIGEST            NVM_measurement;  // Equal to the SHA1 of the blob
+  TPM_DIGEST            DMI_measurement;  // Correct measurement of the owning 
DMI
+} VTPM_DMI_RESOURCE;
+
+typedef struct tdVTPM_GLOBALS {
+  // Non-persistent data
+  int                 be_fh;                  // File handle to ipc used to 
communicate with backend
+#ifndef VTPM_MULTI_VM
+  int                 vtpm_rx_fh;
+  int                 guest_rx_fh;
+  
+  pid_t               master_pid;
+#endif
+  struct hashtable    *dmi_map;               // Table of all DMI's known 
indexed by persistent instance #
+#ifndef VTPM_MULTI_VM
+  pthread_mutex_t     dmi_map_mutex;          // 
+#endif
+  TCS_CONTEXT_HANDLE  manager_tcs_handle;     // TCS Handle used by manager
+  TPM_HANDLE          storageKeyHandle;       // Key used by persistent store
+  CRYPTO_INFO         storageKey;             // For software encryption
+  TCS_AUTH            keyAuth;                // OIAP session for storageKey 
+  BOOL                DMI_table_dirty;        // Indicates that a command
+                                              // has updated the DMI table
+
+    
+  // Persistent Data
+  TPM_AUTHDATA        owner_usage_auth;       // OwnerAuth of real TPM
+  TPM_AUTHDATA        srk_usage_auth;         // SRK Auth of real TPM    
+  buffer_t            storageKeyWrap;         // Wrapped copy of storageKey
+
+  TPM_AUTHDATA        storage_key_usage_auth; 
+    
+}VTPM_GLOBALS;
+
+//Global dmi map
+extern VTPM_GLOBALS *vtpm_globals;
+
+// ********************** Command Handler Prototypes ***********************
+TPM_RESULT VTPM_Handle_Load_NVM(       VTPM_DMI_RESOURCE *myDMI, 
+                                        const buffer_t *inbuf, 
+                                        buffer_t *outbuf);
+
+TPM_RESULT VTPM_Handle_Save_NVM(       VTPM_DMI_RESOURCE *myDMI, 
+                                        const buffer_t *inbuf, 
+                                        buffer_t *outbuf);
+
+TPM_RESULT VTPM_Handle_TPM_Command(    VTPM_DMI_RESOURCE *dmi, 
+                                        buffer_t *inbuf, 
+                                        buffer_t *outbuf);
+
+TPM_RESULT VTPM_Handle_New_DMI(const buffer_t *param_buf);
+                                
+TPM_RESULT VTPM_Handle_Close_DMI(const buffer_t *param_buf);
+                                   
+TPM_RESULT VTPM_Handle_Delete_DMI(const buffer_t *param_buf);
+
+TPM_RESULT VTPM_SaveService(void);
+TPM_RESULT VTPM_LoadService(void);
+
+TPM_RESULT close_dmi( VTPM_DMI_RESOURCE *dmi_res);
+#endif // __VTPMPRIV_H__
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/vtsp.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/vtsp.c Fri Sep  9 16:30:54 2005
@@ -0,0 +1,810 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// vtsp.c
+// 
+//  Higher level interface to TCS for use in service.
+//
+// ==================================================================
+
+#include <string.h>
+#include "tcg.h"
+#include "tcs.h"
+#include "bsg.h"
+#include "log.h"
+#include "crypto.h"
+#include "vtsp.h"
+#include "buffer.h"
+
+#define  RSA_KEY_SIZE 0x0800
+
+/***********************************************************************************
+ * GenerateAuth: Generate authorization info to be sent back to application
+ *
+ * Parameters: outParamDigestText  The concatenation of output parameters to 
be SHA1ed
+ *    outParamDigestTextSize Size of inParamDigestText
+ *    HMACkey     Key to be used for HMACing
+ *          For OIAP use key.authUsage or PersistStore.ownerAuth
+ *          For OSAP use shared secret
+ *    pAuth     Authorization information from the application
+ *
+ * Return:  TPM_SUCCESS   Authorization data created
+ *    TPM_AUTHFAIL   Invalid (NULL) HMACkey presented for OSAP
+ 
*************************************************************************************/
+TPM_RESULT GenerateAuth( /*[IN]*/ const BYTE *inParamDigestText,
+                        /*[IN]*/ UINT32 inParamDigestTextSize,
+                        /*[IN]*/ const TPM_SECRET *HMACkey,  
+                        /*[IN,OUT]*/ TCS_AUTH *auth) {
+    
+  if (inParamDigestText == NULL || auth == NULL) 
+    return (TPM_AUTHFAIL);
+  else {
+    
+    //Generate new OddNonce
+    Crypto_GetRandom(auth->NonceOdd.nonce, sizeof(TPM_NONCE));
+    
+    // Create SHA1 inParamDigest
+    TPM_DIGEST inParamDigest;
+    Crypto_SHA1Full(inParamDigestText, inParamDigestTextSize, (BYTE *) 
&inParamDigest);
+    
+    // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
+    BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
+    
+    BSG_PackList(   hmacText, 4, 
+                   BSG_TPM_DIGEST, &inParamDigest,
+                   BSG_TPM_NONCE, &(auth->NonceEven),
+                   BSG_TPM_NONCE, &(auth->NonceOdd), 
+                   BSG_TYPE_BOOL, &(auth->fContinueAuthSession) );
+    
+    Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText), (BYTE *) HMACkey, 
sizeof(TPM_DIGEST), (BYTE *) &(auth->HMAC));
+    
+    return(TPM_SUCCESS);
+    
+  }
+}
+
+/***********************************************************************************
+ * VerifyAuth: Verify the authdata for a command requiring authorization
+ *
+ * Parameters: inParamDigestText  The concatenation of parameters to be SHA1ed
+ *    inParamDigestTextSize Size of inParamDigestText
+ *    authDataUsage   AuthDataUsage for the Entity being used
+ *          Key->authDataUsage or TPM_AUTH_OWNER
+ *    HMACkey     Key to be used for HMACing
+ *          For OIAP use key.authUsage or PersistStore.ownerAuth
+ *          For OSAP use NULL (It will be aquired from the Auth Session)
+ *          If unknown (default), assume OIAP
+ *    sessionAuth    A TCS_AUTH info for the session
+ *    pAuth     Authorization information from the application
+ *              hContext        If specified, on failed Auth, VerifyAuth will
+ *                                      generate a new OIAP session in place 
of themselves
+ *                                      destroyed session.
+ *
+ * Return:  TPM_SUCCESS   Authorization Verified
+ *    TPM_AUTHFAIL   Authorization Failed
+ *    TPM_FAIL    Failure during SHA1 routines
+ 
*************************************************************************************/
+TPM_RESULT VerifyAuth( /*[IN]*/ const BYTE *outParamDigestText,
+                      /*[IN]*/ UINT32 outParamDigestTextSize,
+                      /*[IN]*/ const TPM_SECRET *HMACkey,  
+                      /*[IN,OUT]*/ TCS_AUTH *auth,
+                      /*[IN]*/  TCS_CONTEXT_HANDLE hContext) {
+  if (outParamDigestText == NULL || auth == NULL) 
+    return (TPM_AUTHFAIL);
+  
+  
+  // Create SHA1 inParamDigest
+  TPM_DIGEST outParamDigest;
+  Crypto_SHA1Full(outParamDigestText, outParamDigestTextSize, (BYTE *) 
&outParamDigest);
+  
+  // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
+  TPM_DIGEST hm;
+  BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
+  
+  BSG_PackList(   hmacText, 4, 
+                 BSG_TPM_DIGEST, &outParamDigest,
+                 BSG_TPM_NONCE, &(auth->NonceEven),
+                 BSG_TPM_NONCE, &(auth->NonceOdd), 
+                 BSG_TYPE_BOOL, &(auth->fContinueAuthSession) );
+  
+  Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText),
+             (BYTE *) HMACkey, sizeof(TPM_DIGEST), (BYTE *) &hm);
+    
+  // Compare correct HMAC with provided one.
+  if (memcmp (&hm, &(auth->HMAC), sizeof(TPM_DIGEST)) == 0)  // 0 indicates 
equality
+    return (TPM_SUCCESS);
+  else {
+    VTSP_OIAP( hContext, auth);
+    return (TPM_AUTHFAIL);
+  }
+}
+
+TPM_RESULT VTSP_OIAP(const TCS_CONTEXT_HANDLE hContext,
+                    TCS_AUTH *auth) {
+  
+  vtpmloginfo(VTPM_LOG_VTSP, "OIAP.\n");
+  TPM_RESULT status = TPM_SUCCESS;                           
+  TPMTRYRETURN( TCSP_OIAP(hContext,
+                         &auth->AuthHandle,
+                         &auth->NonceEven) );
+  goto egress;
+  
+ abort_egress:
+  
+ egress:
+  
+  return status;
+}
+
+TPM_RESULT VTSP_OSAP(const TCS_CONTEXT_HANDLE hContext,
+                    const TPM_ENTITY_TYPE entityType,
+                    const UINT32 entityValue,
+                    const TPM_AUTHDATA *usageAuth,
+                    TPM_SECRET *sharedSecret, 
+                    TCS_AUTH *auth) {
+  
+  vtpmloginfo(VTPM_LOG_VTSP, "OSAP.\n");
+  TPM_RESULT status = TPM_SUCCESS;
+  TPM_NONCE nonceEvenOSAP, nonceOddOSAP;
+  
+  Crypto_GetRandom((BYTE *) &nonceOddOSAP, sizeof(TPM_NONCE) ); 
+  
+  TPMTRYRETURN( TCSP_OSAP(    hContext,
+                             TPM_ET_SRK,
+                             0, 
+                             nonceOddOSAP,
+                             &auth->AuthHandle, 
+                             &auth->NonceEven, 
+                             &nonceEvenOSAP) );
+  
+  // Calculating Session Secret
+  BYTE sharedSecretText[TPM_DIGEST_SIZE * 2];
+  
+  BSG_PackList(  sharedSecretText, 2,
+                BSG_TPM_NONCE, &nonceEvenOSAP,
+                BSG_TPM_NONCE, &nonceOddOSAP);
+  
+  Crypto_HMAC(sharedSecretText, sizeof(sharedSecretText), (BYTE *) usageAuth, 
TPM_DIGEST_SIZE, (BYTE *) sharedSecret);       
+    
+  goto egress;
+  
+ abort_egress:
+  
+ egress:
+  
+  return status;
+}
+
+
+
+TPM_RESULT VTSP_ReadPubek(   const TCS_CONTEXT_HANDLE hContext,
+                             CRYPTO_INFO *crypto_info) {
+  
+  TPM_RESULT status;
+  TPM_NONCE antiReplay;
+  TPM_DIGEST   checksum;
+  BYTE *pubEKtext;
+  UINT32 pubEKtextsize;
+  
+  vtpmloginfo(VTPM_LOG_VTSP, "Reading Public EK.\n");
+  
+  // GenerateAuth new nonceOdd    
+  Crypto_GetRandom(&antiReplay, sizeof(TPM_NONCE) );
+  
+  
+  TPMTRYRETURN( TCSP_ReadPubek(  hContext,
+                                antiReplay,
+                                &pubEKtextsize,
+                                &pubEKtext,
+                                &checksum) );
+  
+  
+  // Extract the remaining output parameters
+  TPM_PUBKEY pubEK;
+  
+  BSG_Unpack(BSG_TPM_PUBKEY, pubEKtext, (BYTE *) &pubEK);
+  
+  // Build CryptoInfo for the bindingKey
+  TPM_RSA_KEY_PARMS rsaKeyParms;
+  
+  BSG_Unpack(BSG_TPM_RSA_KEY_PARMS, 
+            pubEK.algorithmParms.parms, 
+            &rsaKeyParms);
+  
+  Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize, 
+                                 rsaKeyParms.exponent, 
+                                 pubEK.pubKey.keyLength, 
+                                 pubEK.pubKey.key, 
+                                 crypto_info);
+    
+  // Destroy rsaKeyParms
+  BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);
+
+  // Set encryption scheme
+  crypto_info->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;
+  //crypto_info->encScheme = pubEK.algorithmParms.encScheme;
+  crypto_info->algorithmID = pubEK.algorithmParms.algorithmID;
+  
+  goto egress;
+  
+ abort_egress:
+  
+ egress:
+  
+  return status;
+}
+
+TPM_RESULT VTSP_TakeOwnership(   const TCS_CONTEXT_HANDLE hContext,
+                                 const TPM_AUTHDATA *ownerAuth, 
+                                 const TPM_AUTHDATA *srkAuth,
+                                 CRYPTO_INFO *ek_cryptoInfo,
+                                 TCS_AUTH *auth) {
+  
+  vtpmloginfo(VTPM_LOG_VTSP, "Taking Ownership of TPM.\n");
+  
+  TPM_RESULT status = TPM_SUCCESS;
+  TPM_COMMAND_CODE command = TPM_ORD_TakeOwnership;
+  TPM_PROTOCOL_ID proto_id = TPM_PID_OWNER;
+  BYTE *new_srk;
+  
+  BYTE *paramText;        // Digest to make Auth.
+  UINT32 paramTextSize;
+  
+  // vars for srkpubkey parameter
+  TPM_KEY srkPub;
+  TPM_KEY_PARMS srkKeyInfo = {TPM_ALG_RSA, TPM_ES_RSAESOAEP_SHA1_MGF1, 
TPM_SS_NONE, 12, 0};
+  BYTE srkRSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00,   0x00, 
0x00, 0x00, 0x02,   0x00, 0x00, 0x00, 0x00};
+  srkKeyInfo.parms = (BYTE *) &srkRSAkeyInfo;
+  
+  struct pack_buf_t srkText;
+  
+  // GenerateAuth new nonceOdd    
+  Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+  
+  //These values are accurate for an enc(AuthData).
+  struct pack_buf_t encOwnerAuth, encSrkAuth;
+  
+  encOwnerAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256);
+  encSrkAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256);
+  
+  if (encOwnerAuth.data == NULL || encSrkAuth.data == NULL) {
+    vtpmloginfo(VTPM_LOG_VTSP, "Could not malloc encrypted auths.\n");
+    status = TPM_RESOURCES;
+    goto abort_egress;
+  }
+  
+  Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) ownerAuth, 
&encOwnerAuth.size, encOwnerAuth.data);
+  Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) srkAuth, 
&encSrkAuth.size, encSrkAuth.data);
+  
+  
+  // Build srk public key struct
+  srkPub.ver = TPM_STRUCT_VER_1_1;
+  srkPub.keyUsage = TPM_KEY_STORAGE;
+  srkPub.keyFlags = 0x00;
+  srkPub.authDataUsage = TPM_AUTH_ALWAYS;
+  memcpy(&srkPub.algorithmParms, &srkKeyInfo, sizeof(TPM_KEY_PARMS));
+  srkPub.PCRInfoSize = 0;
+  srkPub.PCRInfo = 0;
+  srkPub.pubKey.keyLength= 0;
+  srkPub.encDataSize = 0;
+  
+  srkText.data = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+  srkText.size = BSG_Pack(BSG_TPM_KEY, (BYTE *) &srkPub, srkText.data);
+  
+  paramText = (BYTE *) malloc(sizeof(BYTE) *  TCPA_MAX_BUFFER_LENGTH);
+  
+  paramTextSize = BSG_PackList(paramText, 5,
+                              BSG_TPM_COMMAND_CODE,&command,
+                              BSG_TPM_PROTOCOL_ID, &proto_id,
+                              BSG_TPM_SIZE32_DATA, &encOwnerAuth,
+                              BSG_TPM_SIZE32_DATA, &encSrkAuth,
+                              BSG_TPM_KEY, &srkPub);
+  
+  TPMTRYRETURN( GenerateAuth( paramText, paramTextSize, ownerAuth, auth) );
+  
+  new_srk = srkText.data;
+  TPMTRYRETURN( TCSP_TakeOwnership ( hContext,
+                                    proto_id,
+                                    encOwnerAuth.size, 
+                                    encOwnerAuth.data,
+                                    encSrkAuth.size,
+                                    encSrkAuth.data,
+                                    &srkText.size,
+                                    &new_srk, 
+                                    auth ) );
+  
+  
+  paramTextSize = BSG_PackList(paramText, 2, 
+                              BSG_TPM_RESULT, &status,
+                              BSG_TPM_COMMAND_CODE, &command);
+  memcpy(paramText + paramTextSize, new_srk, srkText.size);
+  paramTextSize += srkText.size;
+  
+  
+  TPMTRYRETURN( VerifyAuth(  paramText, paramTextSize,
+                            ownerAuth, auth, 
+                            hContext) );
+  
+  goto egress;
+  
+ abort_egress:
+  
+ egress:
+  
+  free(srkText.data);
+  free(encSrkAuth.data);
+  free(encOwnerAuth.data);
+  free(paramText);
+  
+  TCS_FreeMemory(hContext, new_srk);
+  
+  return status;
+}
+
+TPM_RESULT VTSP_DisablePubekRead( const TCS_CONTEXT_HANDLE    hContext,
+                                  const TPM_AUTHDATA          *ownerAuth, 
+                                  TCS_AUTH                    *auth) {
+  
+  vtpmloginfo(VTPM_LOG_VTSP, "Disabling Pubek Read.\n");
+  
+  TPM_RESULT status = TPM_SUCCESS;
+  TPM_COMMAND_CODE command = TPM_ORD_DisablePubekRead;
+  
+  BYTE *paramText;        // Digest to make Auth.
+  UINT32 paramTextSize;
+    
+  // Generate HMAC   
+  Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+  
+  paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+  
+  paramTextSize = BSG_PackList(paramText, 1,
+                              BSG_TPM_COMMAND_CODE, &command);
+  
+  TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+                             ownerAuth, auth) );
+  
+  // Call TCS
+  TPMTRYRETURN( TCSP_DisablePubekRead ( hContext, // in
+                                        auth) );
+  
+  // Verify Auth
+  paramTextSize = BSG_PackList(paramText, 2,
+                              BSG_TPM_RESULT, &status,
+                              BSG_TPM_COMMAND_CODE, &command);
+  
+  TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+                           ownerAuth, auth, 
+                           hContext) );
+  goto egress;
+  
+ abort_egress:
+ egress:
+  free(paramText);
+  return status;
+}
+
+TPM_RESULT VTSP_CreateWrapKey(  const TCS_CONTEXT_HANDLE hContext,
+                                const TPM_KEY_USAGE      usage,
+                                const TPM_AUTHDATA       *newKeyAuth,
+                                const TCS_KEY_HANDLE     parentHandle, 
+                                const TPM_AUTHDATA       *osapSharedSecret,
+                                buffer_t                 *pubKeyBuf,
+                                TCS_AUTH                 *auth) {
+  
+  int i;
+  TPM_RESULT status = TPM_SUCCESS;
+  TPM_COMMAND_CODE command = TPM_ORD_CreateWrapKey;
+  
+  vtpmloginfo(VTPM_LOG_VTSP, "Creating new key of type %d.\n", usage);
+  
+  // vars for Calculate encUsageAuth
+  BYTE *paramText;      
+  UINT32 paramTextSize;
+  
+  // vars for Calculate encUsageAuth
+  BYTE XORbuffer[sizeof(TPM_SECRET) + sizeof(TPM_NONCE)];
+  TPM_DIGEST XORKey1;
+  UINT32 XORbufferSize;
+  TPM_SECRET encUsageAuth, encMigrationAuth;
+  
+  // vars for Flatten newKey prototype
+  BYTE *flatKey = (BYTE *) malloc(sizeof(BYTE) *  TCPA_MAX_BUFFER_LENGTH);
+  UINT32 flatKeySize = TCPA_MAX_BUFFER_LENGTH;                                 
   
+  struct pack_buf_t newKeyText;
+  
+  // Fill in newKey
+  TPM_KEY newKey;
+  
+  BYTE RSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00,   0x00, 0x00, 
0x00, 0x02,   0x00, 0x00, 0x00, 0x00};
+  newKey.algorithmParms.algorithmID = TPM_ALG_RSA;
+  newKey.algorithmParms.parms = (BYTE *) &RSAkeyInfo;
+  newKey.algorithmParms.parmSize = 12;
+  
+  switch (usage) {
+  case TPM_KEY_SIGNING:
+    vtpmloginfo(VTPM_LOG_VTSP, "Creating Signing Key...\n");
+    newKey.keyUsage = TPM_KEY_SIGNING;
+    newKey.algorithmParms.encScheme = TPM_ES_NONE;
+    newKey.algorithmParms.sigScheme = TPM_SS_RSASSAPKCS1v15_SHA1;
+    break;
+  case TPM_KEY_STORAGE:
+    vtpmloginfo(VTPM_LOG_VTSP, "Creating Storage Key...\n");
+    newKey.keyUsage = TPM_KEY_STORAGE;
+    newKey.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;
+    newKey.algorithmParms.sigScheme = TPM_SS_NONE;
+    break;
+  case TPM_KEY_BIND:
+    vtpmloginfo(VTPM_LOG_VTSP, "Creating Binding Key...\n");
+    newKey.keyUsage = TPM_KEY_BIND;
+    newKey.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;
+    newKey.algorithmParms.sigScheme = TPM_SS_NONE;
+    break;
+  default:
+    vtpmloginfo(VTPM_LOG_VTSP, "Cannot create key. Invalid Key Type.\n");
+    status = TPM_BAD_PARAMETER;
+    goto abort_egress;
+  }
+  
+  
+  newKey.ver = TPM_STRUCT_VER_1_1;
+  
+  newKey.keyFlags = 0;
+  newKey.authDataUsage = TPM_AUTH_ALWAYS;
+  newKey.pubKey.keyLength= 0;
+  newKey.encDataSize = 0;
+  newKey.encData = NULL;
+  
+  // FIXME: Support PCR bindings
+  newKey.PCRInfoSize = 0;
+  newKey.PCRInfo = NULL;
+  
+  // Calculate encUsageAuth                                    
+  XORbufferSize = BSG_PackList(  XORbuffer, 2, 
+                                BSG_TPM_SECRET, osapSharedSecret,
+                                BSG_TPM_NONCE, &auth->NonceEven);
+  Crypto_SHA1Full(XORbuffer, XORbufferSize, (BYTE *) &XORKey1);
+  
+  // FIXME: No support for migratable keys.
+  for (i=0; i < TPM_DIGEST_SIZE; i++) 
+    ((BYTE *) &encUsageAuth)[i] = ((BYTE *) &XORKey1)[i] ^ ((BYTE *) 
newKeyAuth)[i];
+  
+  // Flatten newKey prototype
+  flatKeySize = BSG_Pack(BSG_TPM_KEY, (BYTE *) &newKey, flatKey);
+  newKeyText.data = flatKey;
+  newKeyText.size = flatKeySize;
+  
+  // GenerateAuth new nonceOdd    
+  Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+  
+  // Generate HMAC
+  paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+  
+  paramTextSize = BSG_PackList(paramText, 3,
+                              BSG_TPM_COMMAND_CODE, &command,
+                              BSG_TPM_AUTHDATA, &encUsageAuth,
+                              BSG_TPM_AUTHDATA, &encMigrationAuth);
+  memcpy(paramText + paramTextSize, newKeyText.data, newKeyText.size);
+  paramTextSize += newKeyText.size;
+  
+  
+  TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+                             osapSharedSecret, auth) );
+  
+  // Call TCS
+  TPMTRYRETURN( TCSP_CreateWrapKey(  hContext, 
+                                    parentHandle,
+                                    encUsageAuth,
+                                    encMigrationAuth,
+                                    &newKeyText.size,
+                                    &newKeyText.data,
+                                    auth) );
+  
+  // Verify Auth
+  paramTextSize = BSG_PackList(paramText, 2,
+                              BSG_TPM_RESULT, &status,
+                              BSG_TPM_COMMAND_CODE, &command);
+  memcpy(paramText + paramTextSize, newKeyText.data, newKeyText.size);
+  paramTextSize += newKeyText.size;
+  
+  TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+                           osapSharedSecret, auth, 0) );
+  
+  // Unpack/return key structure
+  TPMTRYRETURN(buffer_init(pubKeyBuf, 0, 0) );
+  TPMTRYRETURN(buffer_append_raw(pubKeyBuf, newKeyText.size, newKeyText.data) 
);
+  
+  goto egress;
+  
+ abort_egress:
+  
+ egress:
+  
+  free(flatKey);
+  free(paramText);
+  TCS_FreeMemory(hContext, newKeyText.data);
+  
+  return status;
+}
+
+TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE    hContext,
+                        const TCS_KEY_HANDLE        hUnwrappingKey,
+                        const buffer_t              *rgbWrappedKeyBlob,
+                        const TPM_AUTHDATA          *parentAuth,
+                        TPM_HANDLE                  *newKeyHandle,
+                        TCS_AUTH                    *auth,
+                        CRYPTO_INFO                 *cryptoinfo /*= NULL*/) {
+  
+  
+  vtpmloginfo(VTPM_LOG_VTSP, "Loading Key.\n%s","");
+  
+  TPM_RESULT status = TPM_SUCCESS;
+  TPM_COMMAND_CODE command = TPM_ORD_LoadKey;
+  
+  BYTE *paramText;        // Digest to make Auth.
+  UINT32 paramTextSize;
+  
+  if ((rgbWrappedKeyBlob == NULL) || (parentAuth == NULL) || 
+      (newKeyHandle==NULL) || (auth==NULL)) {
+    status = TPM_BAD_PARAMETER;
+    goto abort_egress;
+  }
+  
+  // Generate Extra TCS Parameters
+  TPM_HANDLE phKeyHMAC;
+  
+  // Generate HMAC
+  Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+  
+  paramText = (BYTE *) malloc(sizeof(BYTE) *  TCPA_MAX_BUFFER_LENGTH);
+  
+  paramTextSize = BSG_PackList(paramText, 1,
+                              BSG_TPM_COMMAND_CODE, &command);
+  
+  memcpy(paramText + paramTextSize, rgbWrappedKeyBlob->bytes, 
buffer_len(rgbWrappedKeyBlob));
+  paramTextSize += buffer_len(rgbWrappedKeyBlob);
+  
+  TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+                             parentAuth, auth) );
+  
+  // Call TCS
+  TPMTRYRETURN( TCSP_LoadKeyByBlob(  hContext,
+                                    hUnwrappingKey,
+                                    buffer_len(rgbWrappedKeyBlob),
+                                    rgbWrappedKeyBlob->bytes,
+                                    auth,
+                                    newKeyHandle,
+                                    &phKeyHMAC) );
+  
+  // Verify Auth
+  paramTextSize = BSG_PackList(paramText, 3,
+                              BSG_TPM_RESULT, &status,
+                              BSG_TPM_COMMAND_CODE, &command,
+                              BSG_TPM_HANDLE, newKeyHandle);
+  
+  TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+                           parentAuth, auth, 
+                           hContext) );
+  
+  // Unpack/return key structure
+  if (cryptoinfo != NULL) {
+    TPM_KEY newKey;
+    
+    BSG_Unpack(BSG_TPM_KEY, rgbWrappedKeyBlob->bytes , &newKey);
+    TPM_RSA_KEY_PARMS rsaKeyParms;
+    
+    BSG_Unpack(BSG_TPM_RSA_KEY_PARMS, 
+              newKey.algorithmParms.parms, 
+              &rsaKeyParms);
+    
+    Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize, 
+                                   rsaKeyParms.exponent, 
+                                   newKey.pubKey.keyLength, 
+                                   newKey.pubKey.key, 
+                                   cryptoinfo);
+    
+    // Destroy rsaKeyParms
+    BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);
+    
+    // Set encryption scheme
+    cryptoinfo->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;
+  }
+  
+  goto egress;
+  
+ abort_egress:
+  
+ egress:
+  
+  free(paramText);
+  return status;
+}
+
+TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE    hContext,
+                        const TPM_KEY_HANDLE        key_handle,
+                        const buffer_t              *bound_data,
+                        const TPM_AUTHDATA          *usage_auth,
+                        buffer_t                    *clear_data,
+                        TCS_AUTH                    *auth) {
+  
+  vtpmloginfo(VTPM_LOG_VTSP, "Unbinding %d bytes of data.\n", 
buffer_len(bound_data));
+  
+  TPM_RESULT status = TPM_SUCCESS;
+  TPM_COMMAND_CODE command = TPM_ORD_UnBind;
+  
+  BYTE *paramText;        // Digest to make Auth.
+  UINT32 paramTextSize;
+  
+  // Generate Extra TCS Parameters
+  struct pack_buf_t clear_data32;
+  BYTE *clear_data_text;
+  UINT32 clear_data_size;
+  
+  // Generate HMAC   
+  Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+  
+  struct pack_buf_t bound_data32 = {bound_data->size, bound_data->bytes};
+  
+  paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+  
+  paramTextSize = BSG_PackList(paramText, 2,
+                              BSG_TPM_COMMAND_CODE, &command,
+                              BSG_TPM_SIZE32_DATA, &bound_data32);
+  
+  TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+                             usage_auth, auth) );
+  
+  // Call TCS
+  TPMTRYRETURN( TCSP_UnBind( hContext,
+                            key_handle,
+                            buffer_len(bound_data),
+                            bound_data->bytes,
+                            auth,
+                            &clear_data_size,
+                            &clear_data_text) );
+  
+  
+  // Verify Auth
+  clear_data32.size = clear_data_size;
+  clear_data32.data = clear_data_text;
+  paramTextSize = BSG_PackList(paramText, 3,
+                              BSG_TPM_RESULT, &status,
+                              BSG_TPM_COMMAND_CODE, &command,
+                              BSG_TPM_SIZE32_DATA, &clear_data32);
+  
+  TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+                           usage_auth, auth, 
+                           hContext) );
+  
+  // Unpack/return key structure
+  TPMTRYRETURN(buffer_init(clear_data, 0, 0));
+  TPMTRYRETURN(buffer_append_raw (clear_data, clear_data_size, 
clear_data_text) );
+  
+  goto egress;
+  
+ abort_egress:
+  
+ egress:
+  
+  free(paramText);
+  TCS_FreeMemory(hContext, clear_data_text);
+  
+  return status;
+}
+
+TPM_RESULT VTSP_Bind(   CRYPTO_INFO *cryptoInfo, 
+                       const buffer_t *inData, 
+                       buffer_t *outData)               
+{
+  vtpmloginfo(VTPM_LOG_VTSP, "Binding %d bytes of data.\n", 
buffer_len(inData));
+  TPM_BOUND_DATA boundData;
+  UINT32 i;
+  
+  // Fill boundData's accessory information
+  boundData.ver = TPM_STRUCT_VER_1_1;
+  boundData.payload = TPM_PT_BIND;
+  boundData.payloadData = inData->bytes;
+  
+  // Pack boundData before encryption
+  BYTE* flatBoundData = (BYTE *)malloc(sizeof(BYTE) * 
+                                      (sizeof(TPM_VERSION) +
+                                       sizeof(TPM_PAYLOAD_TYPE) +
+                                       buffer_len(inData)));
+  if (flatBoundData == NULL) {
+    return TPM_NOSPACE;
+  }
+  UINT32 flatBoundDataSize = 0;
+  flatBoundDataSize = BSG_PackList(  flatBoundData, 2, 
+                                    BSG_TPM_VERSION, &boundData.ver, 
+                                    BSG_TYPE_BYTE, &boundData.payload);
+  
+  memcpy(flatBoundData+flatBoundDataSize, inData->bytes, buffer_len(inData));
+  flatBoundDataSize += buffer_len(inData);
+  
+  BYTE out_tmp[RSA_KEY_SIZE/8]; // RSAEnc does not do blocking, So this is 
what will come out.
+  UINT32 out_tmp_size;
+  
+  // Encrypt flatBoundData
+  Crypto_RSAEnc( cryptoInfo, 
+                flatBoundDataSize, 
+                flatBoundData, 
+                &out_tmp_size, 
+                out_tmp);
+  
+  if (out_tmp_size > RSA_KEY_SIZE/8) {
+    // The result of RSAEnc should be a fixed size based on key size.
+    vtpmlogerror(VTPM_LOG_VTSP, "Enc buffer just overflowed.\n");
+  }
+  
+  buffer_init(outData, 0, NULL);
+  buffer_append_raw(outData, out_tmp_size, out_tmp);
+  
+  vtpmloginfo(VTPM_LOG_TXDATA, "Bind Generated[%d] = 0x", out_tmp_size);
+  for(i = 0 ; i < out_tmp_size ; i++) {
+    vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out_tmp[i]);
+  }
+  vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
+  
+  // Free flatBoundData
+  free(flatBoundData);
+  
+  return TPM_SUCCESS;
+}
+
+// Function Reaches into unsupported TCS command, beware.
+TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE    hContext,
+                            const buffer_t *inbuf,
+                            buffer_t *outbuf ) {
+  
+  vtpmloginfo(VTPM_LOG_VTSP, "Passthrough in use.\n");
+  TPM_RESULT status = TPM_SUCCESS;
+  
+  // Generate Extra TCS Parameters
+  BYTE *resultText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+  UINT32 resultTextSize =  TCPA_MAX_BUFFER_LENGTH;
+  
+  // Call TCS                          
+  TPMTRYRETURN( TCSP_RawTransmitData(buffer_len(inbuf), inbuf->bytes, 
+                                    &resultTextSize, resultText) );
+  
+  // Unpack/return key structure
+  TPMTRYRETURN(buffer_init (outbuf, resultTextSize, resultText) );             
                   
+  goto egress;
+  
+ abort_egress:
+  
+ egress:
+  TCS_FreeMemory(hContext, resultText);
+  free(resultText);
+  return status;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/vtsp.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/vtsp.h Fri Sep  9 16:30:54 2005
@@ -0,0 +1,102 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// vtsp.h
+// 
+//  Higher level interface to TCS.
+//
+// ==================================================================
+
+#ifndef __VTSP_H__
+#define __VTSP_H__
+
+#include "tcg.h"
+#include "tcs.h"
+
+#define KEY_BUFFER_SIZE 2048
+
+TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE    hContext,
+                            const buffer_t *inbuf,
+                            buffer_t *outbuf );
+
+TPM_RESULT VTSP_OIAP(  const TCS_CONTEXT_HANDLE hContext,
+                       TCS_AUTH *auth);
+                       
+TPM_RESULT VTSP_OSAP(  const TCS_CONTEXT_HANDLE hContext,
+                       const TPM_ENTITY_TYPE entityType,
+                       const UINT32 entityValue,
+                       const TPM_AUTHDATA *usageAuth,
+                       TPM_SECRET *sharedsecret, 
+                       TCS_AUTH *auth);
+
+TPM_RESULT VTSP_ReadPubek(   const TCS_CONTEXT_HANDLE hContext,
+                             CRYPTO_INFO *cypto_info);
+
+TPM_RESULT VTSP_TakeOwnership(   const TCS_CONTEXT_HANDLE hContext,
+                                 const TPM_AUTHDATA *ownerAuth, 
+                                 const TPM_AUTHDATA *srkAuth,
+                                 CRYPTO_INFO *ek_cryptoInfo,
+                                 TCS_AUTH *auth);
+                               
+TPM_RESULT VTSP_DisablePubekRead( const TCS_CONTEXT_HANDLE    hContext,
+                                  const TPM_AUTHDATA *ownerAuth, 
+                                  TCS_AUTH                    *auth);
+                               
+TPM_RESULT VTSP_CreateWrapKey(  const TCS_CONTEXT_HANDLE hContext,
+                                const TPM_KEY_USAGE      usage,
+                                const TPM_AUTHDATA       *newKeyAuth,
+                                const TCS_KEY_HANDLE     parentHandle, 
+                                const TPM_AUTHDATA       *osapSharedSecret,
+                                buffer_t                 *pubKeyBuf,
+                                TCS_AUTH                 *auth);
+
+TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE    hContext,
+                        const TCS_KEY_HANDLE        hUnwrappingKey,
+                        const buffer_t              *rgbWrappedKeyBlob,
+                        const TPM_AUTHDATA          *parentAuth,
+                        TPM_HANDLE                  *newKeyHandle,
+                        TCS_AUTH                    *pAuth,
+                        CRYPTO_INFO                 *cryptoinfo);
+
+TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE    hContext,
+                        const TPM_KEY_HANDLE        key_handle,
+                        const buffer_t              *bound_data,
+                        const TPM_AUTHDATA          *usage_auth,
+                        buffer_t                    *clear_data,
+                        TCS_AUTH                    *auth);
+                        
+TPM_RESULT VTSP_Bind(   CRYPTO_INFO *cryptoInfo,
+            const buffer_t *inData, 
+            buffer_t *outData);
+                        
+#endif //_VTSP_H_
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/tcs/Makefile
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/tcs/Makefile   Fri Sep  9 16:30:54 2005
@@ -0,0 +1,18 @@
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+BIN            = libTCS.a
+
+all: build
+
+build: $(BIN)
+
+install: build
+
+clean:
+       rm -f *.a *.so *.o *.rpm $(DEP_FILES)
+
+mrproper: clean
+
+$(BIN): $(OBJS)
+       $(AR) rcs $(BIN) $(OBJS)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/tcs/contextmgr.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/tcs/contextmgr.c       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,219 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// contextmgr.c
+// 
+//  This file contains the context management functions for TCS.
+// 
+// ==================================================================
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include "tcs.h"
+#include "contextmgr.h"
+#include "log.h"
+
+BYTE* AddMemBlock(CONTEXT_HANDLE* pContextHandle, // in
+                 int    BlockSize)  { // in
+  
+  BLOCK* pCurrentBlock = NULL;
+  BLOCK* pBlock = NULL;
+                    
+  // check incoming params
+  if (pContextHandle == NULL || BlockSize == 0)
+    return NULL;
+
+  // Create New Block
+  pBlock = (BLOCK *)malloc(sizeof(BLOCK));
+  if (pBlock == NULL)
+    return (0);
+
+  pBlock->aMemory = (BYTE *)malloc(sizeof(BYTE) * BlockSize);
+  if (pBlock->aMemory == NULL)
+    return (0);
+
+  memset(pBlock->aMemory, 0, BlockSize);
+  pBlock->nBlockSize = BlockSize;
+  pBlock->pNextBlock = NULL;
+  
+  // search for the last block created where to add the 
+  // newly created block
+  if(pContextHandle->pTopBlock != NULL) {
+    pCurrentBlock = pContextHandle->pTopBlock;
+    while(pCurrentBlock->pNextBlock != NULL)
+      pCurrentBlock = pCurrentBlock->pNextBlock;
+    
+    
+    pCurrentBlock->pNextBlock= pBlock;
+  } else
+    pContextHandle->pTopBlock = pBlock;
+  
+  
+  pContextHandle->nBlockCount++;
+  
+  return pBlock->aMemory;
+}
+
+
+BOOL DeleteMemBlock(CONTEXT_HANDLE* pContextHandle, // in
+                    BYTE*   pTCPA_BYTEs) { // in
+  BLOCK* pCurrentBlock = NULL;
+  BLOCK* pParentBlock = NULL;
+  BOOL bFound = FALSE;
+  
+  if (pContextHandle == NULL) 
+    return FALSE;
+
+  
+  // Search for the Block in the context by aMemory pointer
+  pParentBlock = NULL;
+  pCurrentBlock = pContextHandle->pTopBlock;
+  
+  while(pCurrentBlock != NULL) {
+    // If aMemory block is found, delete it 
+    if(pCurrentBlock->aMemory == pTCPA_BYTEs || pTCPA_BYTEs == NULL) {
+      // if it is the top Block, remove it from the top, 
+      // otherwise remove it from the ParentBlock and stitch 
+      // the NextBlock to the ParentBlock
+      if(pParentBlock == NULL)
+       pContextHandle->pTopBlock = pContextHandle->pTopBlock->pNextBlock;
+      else
+       pParentBlock->pNextBlock = pCurrentBlock->pNextBlock;
+      
+      // delete memory Block associated with pointer pTCPA_BYTEs
+      free(pCurrentBlock->aMemory);
+      pCurrentBlock->aMemory = NULL;
+      
+      free(pCurrentBlock);
+      pCurrentBlock = pParentBlock;
+      
+      pContextHandle->nBlockCount--;
+      bFound = TRUE;
+    }
+  
+    if(pCurrentBlock != NULL) {
+      pParentBlock = pCurrentBlock;
+      pCurrentBlock = pCurrentBlock->pNextBlock;
+    }
+  }
+  
+  return bFound;
+}
+
+BOOL AddHandleToList(CONTEXT_HANDLE* pContextHandle, // in
+                    TPM_RESOURCE_TYPE type, // in
+                    TPM_HANDLE    handle)  { // in
+  HANDLE_LIST* pNewHandle = NULL;
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Adding Handle to list\n");
+  if (pContextHandle == NULL)
+    return 0;
+  
+  pNewHandle = (HANDLE_LIST *)malloc(sizeof(HANDLE_LIST));
+  
+  if (pNewHandle == NULL) 
+    return (0);
+  
+  pNewHandle->handle = handle;
+  pNewHandle->type = type;
+  pNewHandle->pNextHandle = pContextHandle->pHandleList;
+  
+  pContextHandle->pHandleList = pNewHandle;
+  
+  return 1;
+}
+
+BOOL DeleteHandleFromList(   CONTEXT_HANDLE*     pContextHandle, // in
+                             TPM_HANDLE          handle) { // in
+    
+  HANDLE_LIST *pCurrentHandle = pContextHandle->pHandleList, 
+    *pLastHandle = pCurrentHandle;
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Deleting Handle from list\n");
+  
+  if (pContextHandle == NULL)
+    return 0;
+  
+  while (1) {
+    
+    if (pCurrentHandle->handle == handle) { // Found element
+      if (pCurrentHandle == pLastHandle) { // First element in list 
+       pContextHandle->pHandleList = pCurrentHandle->pNextHandle;
+       free(pCurrentHandle);
+      } else { // Ordinary element
+       pLastHandle->pNextHandle = pCurrentHandle->pNextHandle;
+       free(pCurrentHandle);
+      }
+      
+      return 1;
+      
+    } else { // Not found yet;
+      pLastHandle = pCurrentHandle;
+      pCurrentHandle = pCurrentHandle->pNextHandle;
+      if (pCurrentHandle == NULL) // Found end of list
+       return 0;
+    }
+    
+  }
+}
+
+BOOL FreeHandleList(    CONTEXT_HANDLE*     pContextHandle) { // in
+  HANDLE_LIST* pCurrentHandle;
+  BOOL returncode = TRUE;
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Freeing all handles for context\n");
+  
+  if (pContextHandle == NULL)
+    return 1;
+  
+  pCurrentHandle = pContextHandle->pHandleList;
+  while (pCurrentHandle != NULL) {
+    
+    switch (pCurrentHandle->type) {
+    case TPM_RT_KEY:
+      returncode = returncode && !TCSP_EvictKey((TCS_CONTEXT_HANDLE) 
pContextHandle, pCurrentHandle->handle);
+      break;
+    case TPM_RT_AUTH:
+      returncode = returncode && !TCSP_TerminateHandle((TCS_CONTEXT_HANDLE) 
pContextHandle, pCurrentHandle->handle);
+      break;
+    default:
+      returncode = FALSE;
+    }
+    
+    pCurrentHandle = pCurrentHandle->pNextHandle;
+    
+  }
+  
+  return 1;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/tcs/contextmgr.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/tcs/contextmgr.h       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,81 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// contextmgr.c
+// 
+//  This file contains the context management functions for TCS.
+// 
+// ==================================================================
+
+#ifndef __CONTEXTMGR_H__
+#define __CONTEXTMGR_H__
+
+#include "tcg.h"
+
+#define BLOCK_SIZE 300
+
+typedef struct block {
+  int nBlockSize;
+  BYTE* aMemory;
+  struct block* pNextBlock;
+} BLOCK;
+
+typedef struct handle_List {
+  TPM_HANDLE handle;
+  TPM_RESOURCE_TYPE type;
+  struct handle_List* pNextHandle;
+} HANDLE_LIST;
+
+typedef struct context_handle {
+  int nBlockCount;
+  BLOCK* pTopBlock;
+  HANDLE_LIST* pHandleList;
+} CONTEXT_HANDLE;
+
+BYTE* AddMemBlock(  CONTEXT_HANDLE*     pContextHandle, // in
+                    int                 BlockSize);  // in
+
+BOOL DeleteMemBlock(CONTEXT_HANDLE* pContextHandle, // in
+                    BYTE*           pTCPA_BYTEs); // in
+
+
+BOOL AddHandleToList(   CONTEXT_HANDLE*     pContextHandle, // in
+                        TPM_RESOURCE_TYPE   type, // in
+                        TPM_HANDLE          handle); // in
+
+BOOL DeleteHandleFromList(   CONTEXT_HANDLE*     pContextHandle, // in
+                             TPM_HANDLE          handle); // in
+
+BOOL FreeHandleList(    CONTEXT_HANDLE*     pContextHandle); // in
+
+#endif //_CONTEXTMGR_H_
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/tcs/tcs.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/tcs/tcs.c      Fri Sep  9 16:30:54 2005
@@ -0,0 +1,1102 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// tcs.c
+// 
+//  This file contains the functions that implement a TCS.
+// 
+// ==================================================================
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+
+#include "tcg.h"
+#include "bsg.h"
+#include "tcs.h"
+#include "contextmgr.h"
+#include "tpmddl.h"
+#include "log.h"
+
+// Static Global Vars for the TCS
+static BOOL TCS_m_bConnected;
+static int TCS_m_nCount = 0;
+
+#define TCPA_MAX_BUFFER_LENGTH 0x2000
+
+static BYTE InBuf [TCPA_MAX_BUFFER_LENGTH];
+static BYTE OutBuf[TCPA_MAX_BUFFER_LENGTH];
+
+
+// 
---------------------------------------------------------------------------------
+// Initialization/Uninitialization SubComponent API
+// 
---------------------------------------------------------------------------------
+TPM_RESULT TCS_create() {
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TPM_RESULT result = TPM_FAIL;
+  TCS_m_bConnected = FALSE;
+  
+  if (TCS_m_nCount == 0) {
+    vtpmloginfo(VTPM_LOG_TCS, "Constructing new TCS:\n");
+    hRes = TDDL_Open();
+    
+    if (hRes == TDDL_SUCCESS) {
+      TCS_m_bConnected = TRUE;
+      result = TPM_SUCCESS;
+    }
+  } else
+    TCS_m_bConnected = TRUE;
+  
+  TCS_m_nCount++;
+  
+  return(result);
+}
+
+
+void TCS_destroy()
+{
+  // FIXME: Should iterate through all open contexts and close them.
+  TCS_m_nCount--;
+  
+  if (TCS_m_bConnected == TRUE && TCS_m_nCount == 0) {
+    vtpmloginfo(VTPM_LOG_TCS, "Destructing TCS:\n");
+    TDDL_Close();
+    TCS_m_bConnected = FALSE;
+  }
+  
+}
+
+TPM_RESULT TCS_Malloc(  TCS_CONTEXT_HANDLE  hContext, // in
+                        UINT32              MemSize, // in
+                        BYTE**              ppMemPtr) {// out
+
+  TPM_RESULT returnCode = TPM_FAIL;
+  CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE*)hContext;
+  
+  if (pContextHandle != NULL && ppMemPtr != NULL) {
+    *ppMemPtr = (BYTE *)AddMemBlock(pContextHandle, MemSize);
+    returnCode = TPM_SUCCESS;
+  }
+  
+  return returnCode;
+}
+
+TPM_RESULT TCS_FreeMemory(  TCS_CONTEXT_HANDLE  hContext, // in
+                            BYTE*               pMemory) { // in
+  TPM_RESULT returnCode = TPM_FAIL;
+  CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE*)hContext;
+  
+  if ( (pContextHandle != NULL && pMemory != NULL) &&
+       (DeleteMemBlock(pContextHandle, pMemory) == TRUE) )
+    returnCode = TPM_SUCCESS;
+ 
+  
+  return returnCode;
+}
+
+TPM_RESULT TCS_OpenContext(TCS_CONTEXT_HANDLE* hContext) { // out
+  TPM_RESULT returnCode = TPM_FAIL;
+  
+  vtpmloginfo(VTPM_LOG_TCS, "Calling TCS_OpenContext:\n");
+  
+  // hContext must point to a null memory context handle
+  if(*hContext == HANDLE_NULL) {
+    CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE 
*)malloc(sizeof(CONTEXT_HANDLE));
+    if (pContextHandle == NULL) 
+      return TPM_SIZE;
+    
+    
+    // initialize to 0
+    pContextHandle->nBlockCount = 0;
+    pContextHandle->pTopBlock = NULL;
+    pContextHandle->pHandleList = NULL;
+    
+    // Create New Block
+    AddMemBlock(pContextHandle, BLOCK_SIZE);
+    
+    *hContext = (TCS_CONTEXT_HANDLE)pContextHandle;
+    returnCode = TPM_SUCCESS;
+  }
+  
+  return(returnCode);
+}
+
+TPM_RESULT TCS_CloseContext(TCS_CONTEXT_HANDLE hContext) {// in
+  //FIXME: TCS SHOULD Track track failed auths and make sure
+  //we don't try and re-free them here.
+  TPM_RESULT returnCode = TPM_FAIL;
+  
+  CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE*)hContext;
+  
+  if(pContextHandle != NULL) {
+    // Print test info
+    vtpmloginfo(VTPM_LOG_TCS, "Calling TCS_CloseContext.\n");
+      
+    // free memory for all the blocks
+    DeleteMemBlock(pContextHandle, NULL );      
+    pContextHandle->pTopBlock = NULL;
+    
+    FreeHandleList(pContextHandle);
+    if (pContextHandle->pHandleList != NULL) 
+      vtpmlogerror(VTPM_LOG_TCS, "Not all handles evicted from TPM.\n");
+    
+    // Release the TPM's resources
+    free(pContextHandle);
+    returnCode = TPM_SUCCESS;
+  }
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Finished closing context\n");
+  return(returnCode);
+}
+
+// ------------------------------------------------------------------
+// Internal Functions
+// ------------------------------------------------------------------
+int packAuth(BYTE* dst, TCS_AUTH* auth) {
+  // CHECK: according to the command specs, the outgoing auth params are:
+  // nonceEven
+  // nonceOdd
+  // continueAuthSession
+  // auth digest for return params
+  //
+  // this is a bit different than this code...
+  
+  return BSG_PackList(dst, 4, 
+                     BSG_TYPE_UINT32, &(auth->AuthHandle), 
+                     BSG_TPM_NONCE, &(auth->NonceOdd), 
+                     BSG_TYPE_BOOL, &(auth->fContinueAuthSession), 
+                     BSG_TPM_AUTHDATA, &(auth->HMAC));
+}
+
+int unpackAuth(TCS_AUTH* auth, BYTE* src) {
+  return BSG_UnpackList(src, 3, 
+                       BSG_TPM_NONCE, &(auth->NonceEven), 
+                       BSG_TYPE_BOOL, &(auth->fContinueAuthSession), 
+                       BSG_TPM_AUTHDATA, &(auth->HMAC));
+}
+
+// ------------------------------------------------------------------
+// Authorization Commands
+// ------------------------------------------------------------------
+
+TPM_RESULT TCSP_OIAP(TCS_CONTEXT_HANDLE hContext, // in
+                    TCS_AUTHHANDLE*  authHandle, // out 
+                    TPM_NONCE*   nonce0)  // out
+{
+  // setup input/output parameters block
+  TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+  TPM_COMMAND_CODE ordinal = TPM_ORD_OIAP;
+  UINT32 paramSize = 0;
+  TPM_RESULT returnCode = TPM_SUCCESS;
+  
+  // setup the TPM driver input and output buffers
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TDDL_UINT32  InLength = TCPA_MAX_BUFFER_LENGTH;
+  TDDL_UINT32  OutLength = TCPA_MAX_BUFFER_LENGTH;
+  
+  // check input params
+  if (authHandle == NULL || nonce0 == NULL) 
+    return TPM_BAD_PARAMETER;
+  
+  // Convert Byte Input parameter in the input byte stream InBuf
+  InLength = BSG_PackList(InBuf, 3, 
+                         BSG_TPM_TAG, &tag, 
+                         BSG_TYPE_UINT32, &paramSize, 
+                         BSG_TPM_COMMAND_CODE, &ordinal);
+    
+  // fill paramSize again as we now have the correct size
+  BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+  
+  // call the TPM driver
+  if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) 
+      == TDDL_SUCCESS) {
+    
+    // unpack to get the tag, paramSize, & returnCode
+    int i = BSG_UnpackList( OutBuf, 3, 
+                           BSG_TPM_TAG, &tag, 
+                           BSG_TYPE_UINT32, &paramSize, 
+                           BSG_TPM_COMMAND_CODE, &returnCode);
+    
+    if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+      // Extract the remaining output parameters
+      BSG_UnpackList(OutBuf+i, 2, 
+                    BSG_TYPE_UINT32, authHandle, 
+                    BSG_TPM_NONCE, nonce0);
+      
+      if (!AddHandleToList((CONTEXT_HANDLE *)hContext, TPM_RT_AUTH, 
*authHandle)) 
+        vtpmlogerror(VTPM_LOG_TCS, "New AuthHandle not recorded\n");
+      
+      vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+    } else 
+      vtpmlogerror(VTPM_LOG_TCS, "Failed with return code %s\n", 
tpm_get_error_name(returnCode));
+    
+  }
+  
+  return(returnCode);
+}
+
+TPM_RESULT TCSP_OSAP(TCS_CONTEXT_HANDLE hContext,  // in
+                    TPM_ENTITY_TYPE  entityType,  // in
+                    UINT32    entityValue, // in
+                    TPM_NONCE   nonceOddOSAP, // in
+                    TCS_AUTHHANDLE*  authHandle,  // out 
+                    TPM_NONCE*   nonceEven,  // out
+                    TPM_NONCE*   nonceEvenOSAP) // out
+{
+  // setup input/output parameters block
+  TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+  UINT32 paramSize = 0;
+  TPM_COMMAND_CODE ordinal = TPM_ORD_OSAP;
+  TPM_RESULT returnCode = TPM_SUCCESS;
+  
+  // setup the TPM driver input and output buffers
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TDDL_UINT32  InLength = TCPA_MAX_BUFFER_LENGTH;
+  TDDL_UINT32  OutLength = TCPA_MAX_BUFFER_LENGTH;
+  
+  // check input params
+  if (authHandle == NULL || nonceEven == NULL || nonceEvenOSAP == NULL)
+    return TPM_BAD_PARAMETER;
+  
+  // Convert Byte Input parameter in the input byte stream InBuf
+  InLength = BSG_PackList(InBuf, 6, 
+                         BSG_TPM_TAG, &tag, 
+                         BSG_TYPE_UINT32, &paramSize, 
+                         BSG_TPM_COMMAND_CODE, &ordinal, 
+                         BSG_TYPE_UINT16, &entityType, 
+                         BSG_TYPE_UINT32, &entityValue, 
+                         BSG_TPM_NONCE, &nonceOddOSAP);
+  
+  // fill paramSize again as we now have the correct size
+  BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+  
+  // call the TPM driver
+  if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) 
+            == TDDL_SUCCESS) {
+
+    // unpack to get the tag, paramSize, & returnCode
+    int i = BSG_UnpackList(OutBuf, 3, 
+                          BSG_TPM_TAG, &tag, 
+                          BSG_TYPE_UINT32, &paramSize, 
+                          BSG_TPM_COMMAND_CODE, &returnCode);
+    
+    if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+      // Extract the remaining output parameters
+      BSG_UnpackList(OutBuf+i, 3, 
+                    BSG_TYPE_UINT32, authHandle, 
+                    BSG_TPM_NONCE, nonceEven, 
+                    BSG_TPM_NONCE, nonceEvenOSAP);
+      
+      if (!AddHandleToList((CONTEXT_HANDLE *)hContext, TPM_RT_AUTH, 
*authHandle)) {
+           vtpmlogerror(VTPM_LOG_TCS, "New AuthHandle not recorded\n");
+      }
+      
+      vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+    } else 
+      vtpmlogerror(VTPM_LOG_TCS, "Failed with return code %s\n", 
tpm_get_error_name(returnCode));
+    
+  }
+  
+  return(returnCode);
+}
+
+TPM_RESULT TCSP_TakeOwnership(TCS_CONTEXT_HANDLE hContext,   // in
+                             UINT16    protocolID,   // in
+                             UINT32    encOwnerAuthSize, // in 
+                             BYTE*    encOwnerAuth,  // in
+                             UINT32    encSrkAuthSize,  // in
+                             BYTE*    encSrkAuth,   // in
+                             UINT32*    SrkSize,   // in, out
+                             BYTE**    Srk,    // in, out
+                             TCS_AUTH*   ownerAuth)   // in, out
+{
+  // setup input/output parameters block
+  TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+  UINT32 paramSize = 0;
+  TPM_COMMAND_CODE ordinal = TPM_ORD_TakeOwnership;
+  TPM_RESULT returnCode = TPM_SUCCESS;
+  
+  // setup the TPM driver input and output buffers
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+  TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+  
+  // check input params
+  if (encOwnerAuth == NULL || encSrkAuth == NULL || SrkSize == NULL || *Srk == 
NULL) 
+    return TPM_BAD_PARAMETER;
+  
+  // Convert Byte Input parameter in the input byte stream InBuf
+  InLength = BSG_PackList(InBuf, 5, 
+                         BSG_TPM_TAG, &tag, 
+                         BSG_TYPE_UINT32, &paramSize, 
+                         BSG_TPM_COMMAND_CODE, &ordinal, 
+                         BSG_TYPE_UINT16, &protocolID, 
+                         BSG_TYPE_UINT32, &encOwnerAuthSize);
+  
+  memcpy(InBuf+InLength, encOwnerAuth, encOwnerAuthSize);
+  InLength += encOwnerAuthSize;
+  InLength += BSG_Pack(   BSG_TYPE_UINT32, 
+                         &encSrkAuthSize, 
+                         InBuf+InLength);
+  memcpy(InBuf+InLength, encSrkAuth, encSrkAuthSize);
+  InLength += encSrkAuthSize;
+  memcpy(InBuf+InLength, *Srk, *SrkSize);
+  InLength += *SrkSize;
+  InLength += packAuth(InBuf+InLength, ownerAuth);
+  // fill paramSize again as we now have the correct size
+  BSG_Pack(BSG_TYPE_UINT32, 
+          &InLength, 
+          InBuf+2);
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+  
+  // call the TPM driver
+  if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) 
+              == TDDL_SUCCESS){
+    
+    // unpack to get the tag, paramSize, & returnCode
+    int i = BSG_UnpackList( OutBuf, 3, 
+                           BSG_TPM_TAG, &tag, 
+                           BSG_TYPE_UINT32, &paramSize, 
+                           BSG_TPM_COMMAND_CODE, &returnCode);
+    
+    if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+      // Extract the remaining output parameters
+      TPM_KEY srkPub;
+      i += BSG_Unpack(BSG_TPM_KEY,  OutBuf+i,  &srkPub); 
+      unpackAuth(ownerAuth, OutBuf+i);
+      
+      // fill output params
+      BYTE tempBuf[1024];
+      *SrkSize = BSG_Pack(BSG_TPM_KEY,  &srkPub, tempBuf);
+      if (TCS_Malloc(hContext, *SrkSize, Srk) == TPM_FAIL) {
+       return(TPM_SIZE);
+      }
+      memcpy(*Srk, tempBuf, *SrkSize);
+      
+      vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d", paramSize);
+    } else 
+      vtpmlogerror(VTPM_LOG_TCS, "TCSP_TakeOwnership Failed with return code 
%s\n", tpm_get_error_name(returnCode));
+  }
+  
+  return(returnCode);
+}
+
+
+TPM_RESULT TCSP_DisablePubekRead (  TCS_CONTEXT_HANDLE hContext, // in
+                                    TCS_AUTH*   ownerAuth) { // in, out
+ 
+  // setup input/output parameters block
+  TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+  UINT32 paramSize = 0;
+  TPM_COMMAND_CODE ordinal = TPM_ORD_DisablePubekRead;
+  TPM_RESULT returnCode = TPM_SUCCESS;
+  
+  // setup the TPM driver input and output buffers
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+  TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+    
+  // Convert Byte Input parameter in the input byte stream InBuf
+  InLength = BSG_PackList(InBuf, 3, 
+                         BSG_TPM_TAG, &tag, 
+                         BSG_TYPE_UINT32, &paramSize, 
+                         BSG_TPM_COMMAND_CODE, &ordinal);
+  
+  InLength += packAuth(InBuf+InLength, ownerAuth);
+ 
+  // fill paramSize again as we now have the correct size
+  BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+  
+  // call the TPM driver
+  if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) 
+              == TDDL_SUCCESS){
+    
+    // unpack to get the tag, paramSize, & returnCode
+    int i = BSG_UnpackList( OutBuf, 3, 
+                           BSG_TPM_TAG, &tag, 
+                           BSG_TYPE_UINT32, &paramSize, 
+                           BSG_TPM_COMMAND_CODE, &returnCode);
+    
+    if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+      // Extract the remaining output parameters
+      unpackAuth(ownerAuth, OutBuf+i);
+    } else 
+      vtpmlogerror(VTPM_LOG_TCS, "TCSP_DisablePubekRead Failed with return 
code %s\n", tpm_get_error_name(returnCode));
+  }
+  
+  return(returnCode);
+}
+
+
+TPM_RESULT TCSP_TerminateHandle(TCS_CONTEXT_HANDLE hContext, // in
+                                TCS_AUTHHANDLE  handle)  // in
+{
+  // setup input/output parameters block
+  TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+  UINT32 paramSize = 0;
+  TPM_COMMAND_CODE ordinal = TPM_ORD_Terminate_Handle;
+  TPM_RESULT returnCode = TPM_SUCCESS;
+  
+  // setup the TPM driver input and output buffers
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TDDL_UINT32  InLength = TCPA_MAX_BUFFER_LENGTH;
+  TDDL_UINT32  OutLength = TCPA_MAX_BUFFER_LENGTH;
+  
+  // Convert Byte Input parameter in the input byte stream InBuf
+  InLength = BSG_PackList(InBuf, 4, 
+                         BSG_TPM_TAG, &tag, 
+                         BSG_TYPE_UINT32, &paramSize, 
+                         BSG_TPM_COMMAND_CODE, &ordinal, 
+                         BSG_TYPE_UINT32, &handle);
+  // fill paramSize again as we now have the correct size
+  BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+  
+  // call the TPM driver
+  if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) 
+              == TDDL_SUCCESS) {
+    
+    // unpack to get the tag, paramSize, & returnCode
+    BSG_UnpackList(OutBuf, 3, 
+                          BSG_TPM_TAG, &tag, 
+                          BSG_TYPE_UINT32, &paramSize, 
+                          BSG_TPM_COMMAND_CODE, &returnCode);
+    
+    if (!DeleteHandleFromList((CONTEXT_HANDLE *)hContext, handle)) 
+      vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n");
+       
+    
+    if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+      // Print debug info
+      
+      vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d", paramSize);
+    } else 
+      vtpmlogerror(VTPM_LOG_TCS, "TCSP_TerminateHandle Failed with return code 
%s\n", tpm_get_error_name(returnCode));
+    
+  }
+  
+  return(returnCode);
+}
+
+// TPM Mandatory
+TPM_RESULT TCSP_Extend( TCS_CONTEXT_HANDLE hContext, // in
+                        TPM_PCRINDEX  pcrNum,  // in
+                        TPM_DIGEST  inDigest, // in
+                        TPM_PCRVALUE*  outDigest) // out
+{
+  // setup input/output parameters block
+  TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+  UINT32 paramSize = 0;
+  TPM_COMMAND_CODE ordinal = TPM_ORD_Extend;
+  TPM_RESULT returnCode = TPM_SUCCESS;
+  
+  // setup the TPM driver input and output buffers
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TDDL_UINT32  InLength = TCPA_MAX_BUFFER_LENGTH;
+  TDDL_UINT32  OutLength = TCPA_MAX_BUFFER_LENGTH;
+  
+  // Convert Byte Input parameter in the input byte stream InBuf
+  InLength = BSG_PackList(InBuf, 5, 
+                         BSG_TPM_TAG, &tag, 
+                         BSG_TYPE_UINT32, &paramSize, 
+                         BSG_TPM_COMMAND_CODE, &ordinal, 
+                         BSG_TYPE_UINT32, &pcrNum, 
+                         BSG_TPM_DIGEST, &inDigest);
+  // fill paramSize again as we now have the correct size
+  BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+  
+  // call the TPM driver
+  if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) 
+              == TDDL_SUCCESS) {
+    
+    // unpack to get the tag, paramSize, & returnCode
+    int i = BSG_UnpackList(OutBuf, 3, 
+                          BSG_TPM_TAG, &tag, 
+                          BSG_TYPE_UINT32, &paramSize, 
+                          BSG_TPM_COMMAND_CODE, &returnCode);
+    
+    if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND){
+      // Extract the remaining output parameters
+      BSG_Unpack(BSG_TPM_PCRVALUE, OutBuf+i, outDigest);
+      
+      vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+    } else 
+      vtpmlogerror(VTPM_LOG_TCS, "TCSP_Extend Failed with return code %s\n", 
tpm_get_error_name(returnCode));
+  }
+  
+  return(returnCode);
+}
+
+TPM_RESULT TCSP_Seal(   TCS_CONTEXT_HANDLE hContext,  // in
+                        TCS_KEY_HANDLE  keyHandle,  // in
+                        TPM_ENCAUTH   encAuth,  // in
+                        UINT32    pcrInfoSize, // in
+                        BYTE*    PcrInfo,  // in
+                        UINT32    inDataSize,  // in
+                        BYTE*    inData,   // in
+                        TCS_AUTH*   pubAuth,  // in, out
+                        UINT32*    SealedDataSize, // out
+                        BYTE**    SealedData)  // out
+{
+  // setup input/output parameters block
+  TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+  UINT32 paramSize = 0;
+  TPM_COMMAND_CODE ordinal = TPM_ORD_Seal;
+  TPM_RESULT returnCode = TPM_SUCCESS;
+  
+  // setup the TPM driver input and output buffers
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TDDL_UINT32  InLength = TCPA_MAX_BUFFER_LENGTH;
+  TDDL_UINT32  OutLength = TCPA_MAX_BUFFER_LENGTH;
+  
+  // check input params
+  if (inData == NULL || pubAuth == NULL || SealedDataSize == NULL || 
*SealedData == NULL)
+    return TPM_BAD_PARAMETER;
+  
+  // Convert Byte Input parameter in the input byte stream InBuf
+  InLength = BSG_PackList(InBuf, 6, 
+                         BSG_TPM_TAG, &tag, 
+                         BSG_TYPE_UINT32, &paramSize, 
+                         BSG_TPM_COMMAND_CODE, &ordinal, 
+                         BSG_TYPE_UINT32, &keyHandle, 
+                         BSG_TPM_ENCAUTH, encAuth, 
+                         BSG_TYPE_UINT32, &pcrInfoSize);
+  memcpy(InBuf+InLength, PcrInfo, pcrInfoSize);
+  InLength += pcrInfoSize;
+  InLength += BSG_Pack(BSG_TYPE_UINT32, &inDataSize, InBuf+InLength);
+  memcpy(InBuf+InLength, inData, inDataSize);
+  InLength += inDataSize;
+  InLength += packAuth(InBuf+InLength, pubAuth);
+  // fill paramSize again as we now have the correct size
+  BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+    
+  // call the TPM driver
+  if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) 
+              == TDDL_SUCCESS) {
+    // unpack OutBuf to get the tag, paramSize, & returnCode
+    int i = BSG_UnpackList(OutBuf, 3, 
+                          BSG_TPM_TAG, &tag, 
+                          BSG_TYPE_UINT32, &paramSize, 
+                          BSG_TPM_COMMAND_CODE, &returnCode);
+    
+    if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+      // Extract the remaining output parameters
+      TPM_STORED_DATA sealedData;
+      
+      i += BSG_Unpack(BSG_TPM_STORED_DATA, OutBuf+i, &sealedData); 
+      unpackAuth(pubAuth, OutBuf+i);
+      
+      // fill SealedData
+      BYTE tempBuf[1024];
+      *SealedDataSize = BSG_Pack(BSG_TPM_STORED_DATA, &sealedData, tempBuf);
+      if (TCS_Malloc(hContext, *SealedDataSize, SealedData) == TPM_FAIL) {
+       return TPM_SIZE;
+      }
+      memcpy(*SealedData, tempBuf, *SealedDataSize);
+      
+      vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+    } else 
+      vtpmlogerror(VTPM_LOG_TCS, "TCSP_Seal Failed with return code %s\n", 
tpm_get_error_name(returnCode));
+  }
+  
+  return(returnCode);
+}
+
+TPM_RESULT TCSP_Unseal(TCS_CONTEXT_HANDLE hContext,  // in
+                      TCS_KEY_HANDLE  parentHandle, // in
+                      UINT32    SealedDataSize, // in
+                      BYTE*    SealedData,  // in
+                      TCS_AUTH*   parentAuth,  // in, out
+                      TCS_AUTH*   dataAuth,  // in, out
+                      UINT32*   DataSize,  // out
+                      BYTE**    Data)   // out
+{
+  // setup input/output parameters block
+  TPM_TAG tag = TPM_TAG_RQU_AUTH2_COMMAND;
+  UINT32 paramSize = 0;
+  TPM_COMMAND_CODE ordinal = TPM_ORD_Unseal;
+  TPM_RESULT returnCode = TPM_SUCCESS;
+  
+  // setup the TPM driver input and output buffers
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+  TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+  
+  // check input params
+  if (SealedData == NULL || parentAuth == NULL || dataAuth == NULL || 
+      DataSize == NULL || Data == NULL) 
+    return TPM_BAD_PARAMETER;
+  
+  
+  // Convert Byte Input parameter in the input byte stream InBuf
+  InLength = BSG_PackList(InBuf, 4, 
+                                     BSG_TPM_TAG, &tag, 
+                          BSG_TYPE_UINT32, &paramSize, 
+                          BSG_TPM_COMMAND_CODE, &ordinal, 
+                          BSG_TYPE_UINT32, &parentHandle);
+  memcpy(InBuf+InLength, SealedData, SealedDataSize);
+  InLength += SealedDataSize;
+  InLength += packAuth(InBuf+InLength, parentAuth);
+  InLength += packAuth(InBuf+InLength, dataAuth);
+  // fill paramSize again as we now have the correct size
+  BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+    
+  // call the TPM driver
+  if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == 
TDDL_SUCCESS) {
+    // unpack OutBuf to get the tag, paramSize, & returnCode
+    int i = BSG_UnpackList( OutBuf, 3, 
+                            BSG_TPM_TAG, &tag, 
+                            BSG_TYPE_UINT32, &paramSize, 
+                            BSG_TPM_COMMAND_CODE, &returnCode);
+    
+    if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH2_COMMAND) {
+      // Extract the remaining output parameters
+      i += BSG_Unpack(BSG_TYPE_UINT32, OutBuf+i, DataSize);
+      if (TCS_Malloc(hContext, *DataSize, Data) == TPM_FAIL) {
+        return TPM_SIZE;
+      }
+      memcpy(*Data, OutBuf+i, *DataSize);
+      i += *DataSize;
+      i += unpackAuth(parentAuth, OutBuf+i);
+      unpackAuth(dataAuth, OutBuf+i);
+      
+      vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+    } else 
+      vtpmlogerror(VTPM_LOG_TCS, "TCSP_Unseal Failed with return code %s\n", 
tpm_get_error_name(returnCode));
+  }
+  
+  return(returnCode);
+}
+
+TPM_RESULT TCSP_UnBind(TCS_CONTEXT_HANDLE hContext,  // in
+                      TCS_KEY_HANDLE  keyHandle,  // in
+                      UINT32    inDataSize,  // in
+                      BYTE*    inData,   // in
+                      TCS_AUTH*   privAuth,  // in, out
+                      UINT32*   outDataSize, // out
+                      BYTE**    outData)  // out
+{
+  // setup input/output parameters block
+  TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+  UINT32 paramSize = 0;
+  TPM_COMMAND_CODE ordinal = TPM_ORD_UnBind;
+  TPM_RESULT returnCode = TPM_SUCCESS;
+  
+  // setup the TPM driver input and output buffers
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TDDL_UINT32  InLength = TCPA_MAX_BUFFER_LENGTH;
+  TDDL_UINT32  OutLength = TCPA_MAX_BUFFER_LENGTH;
+  
+  // check input params
+  if (inData == NULL || privAuth == NULL || outDataSize == NULL || *outData == 
NULL)
+    return TPM_BAD_PARAMETER;
+  
+  // Convert Byte Input parameter in the input byte stream InBuf
+  InLength = BSG_PackList(InBuf, 5, 
+                         BSG_TPM_TAG, &tag, 
+                         BSG_TYPE_UINT32, &paramSize, 
+                         BSG_TPM_COMMAND_CODE, &ordinal, 
+                         BSG_TYPE_UINT32, &keyHandle, 
+                         BSG_TYPE_UINT32, &inDataSize);
+  memcpy(InBuf+InLength, inData, inDataSize);
+  InLength += inDataSize;
+  InLength += packAuth(InBuf+InLength, privAuth);
+  // fill paramSize again as we now have the correct size
+  BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "\n\tSending paramSize = %d", InLength);
+  
+  // call the TPM driver
+  if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == 
TDDL_SUCCESS) {
+    // unpack OutBuf to get the tag, paramSize, & returnCode
+    int i = BSG_UnpackList(OutBuf, 3, 
+                          BSG_TPM_TAG, &tag, 
+                          BSG_TYPE_UINT32, &paramSize, 
+                          BSG_TPM_COMMAND_CODE, &returnCode);
+    
+    if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+      // Extract the remaining output parameters
+      i += BSG_Unpack(BSG_TYPE_UINT32, OutBuf+i, outDataSize);
+      if (TCS_Malloc(hContext, *outDataSize, outData) == TPM_FAIL)
+        return TPM_SIZE;
+    
+      memcpy(*outData, OutBuf+i, *outDataSize);
+      i += *outDataSize;
+      unpackAuth(privAuth, OutBuf+i);
+      
+      vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+    } else 
+      vtpmlogerror(VTPM_LOG_TCS, "TCSP_UnBind Failed with return code %s\n", 
tpm_get_error_name(returnCode));
+  }
+  
+  return(returnCode);
+}
+
+TPM_RESULT TCSP_CreateWrapKey(TCS_CONTEXT_HANDLE hContext,   // in
+                             TCS_KEY_HANDLE  hWrappingKey,  // in
+                             TPM_ENCAUTH  KeyUsageAuth,  // in
+                             TPM_ENCAUTH  KeyMigrationAuth, // in
+                             UINT32*    pcKeySize,   // in, out
+                             BYTE**    prgbKey,   // in, out
+                             TCS_AUTH*   pAuth)    // in, out
+{
+  // setup input/output parameters block
+  TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+  UINT32 paramSize = 0;
+  TPM_COMMAND_CODE ordinal = TPM_ORD_CreateWrapKey;
+  TPM_RESULT returnCode = TPM_SUCCESS;
+  
+  // setup the TPM driver input and output buffers
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TDDL_UINT32  InLength = TCPA_MAX_BUFFER_LENGTH;
+  TDDL_UINT32  OutLength = TCPA_MAX_BUFFER_LENGTH;
+  
+  // check input params
+  if (pcKeySize == NULL || *prgbKey == NULL || pAuth == NULL)
+    return TPM_BAD_PARAMETER;
+  
+  
+  // Convert Byte Input parameter in the input byte stream InBuf
+  InLength = BSG_PackList(InBuf, 6, 
+                         BSG_TPM_TAG, &tag, 
+                         BSG_TYPE_UINT32, &paramSize, 
+                         BSG_TPM_COMMAND_CODE, &ordinal, 
+                         BSG_TYPE_UINT32, &hWrappingKey, 
+                         BSG_TPM_ENCAUTH, KeyUsageAuth, 
+                         BSG_TPM_ENCAUTH, KeyMigrationAuth); 
+  memcpy(InBuf+InLength, *prgbKey, *pcKeySize);
+  InLength += *pcKeySize;
+  InLength += packAuth(InBuf+InLength, pAuth);
+  // fill paramSize again as we now have the correct size
+  BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+  
+  // call the TPM driver
+  if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == 
TDDL_SUCCESS) {
+    // unpack OutBuf to get the tag, paramSize, & returnCode
+    int i = BSG_UnpackList(OutBuf, 3, 
+                          BSG_TPM_TAG, &tag, 
+                          BSG_TYPE_UINT32, &paramSize, 
+                          BSG_TPM_RESULT, &returnCode);
+    
+    if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+      // Extract the remaining output parameters
+      TPM_KEY wrappedKey;
+      
+      i += BSG_Unpack(BSG_TPM_KEY, OutBuf+i, &wrappedKey);
+      unpackAuth(pAuth, OutBuf+i);
+      
+      // Fill prgbKey
+      BYTE tempBuf[1024];
+      *pcKeySize = BSG_Pack(BSG_TPM_KEY, &wrappedKey, tempBuf);
+      if (TCS_Malloc(hContext, *pcKeySize, prgbKey) == TPM_FAIL) 
+        return TPM_SIZE;
+      
+      memcpy(*prgbKey, tempBuf, *pcKeySize);
+      
+      vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+    } else 
+      vtpmlogerror(VTPM_LOG_TCS, "TCSP_CreateWrapKey Failed with return code 
%s\n", tpm_get_error_name(returnCode)); 
+  }
+  
+  return(returnCode);
+}
+
+TPM_RESULT TCSP_LoadKeyByBlob(TCS_CONTEXT_HANDLE hContext,    // in
+                             TCS_KEY_HANDLE  hUnwrappingKey,   // in
+                             UINT32    cWrappedKeyBlobSize, // in
+                             BYTE*    rgbWrappedKeyBlob,  // in
+                             TCS_AUTH*   pAuth,     // in, out
+                             TCS_KEY_HANDLE*  phKeyTCSI,    // out
+                             TCS_KEY_HANDLE*  phKeyHMAC)    // out
+{
+  // setup input/output parameters block
+  TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+  UINT32 paramSize = 0;
+  TPM_COMMAND_CODE ordinal = TPM_ORD_LoadKey;
+  TPM_RESULT returnCode = TPM_SUCCESS;
+  
+  // setup the TPM driver input and output buffers
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TDDL_UINT32  InLength = TCPA_MAX_BUFFER_LENGTH;
+  TDDL_UINT32  OutLength = TCPA_MAX_BUFFER_LENGTH;
+  
+  // check input params
+  if (rgbWrappedKeyBlob == NULL || pAuth == NULL || phKeyTCSI == NULL || 
phKeyHMAC == NULL) 
+    return TPM_BAD_PARAMETER; 
+  
+  *phKeyHMAC = hUnwrappingKey; // the parent key is the one that the TPM use 
to make the HMAC calc
+  
+  // Convert Byte Input parameter in the input byte stream InBuf
+  InLength = BSG_PackList(InBuf, 4, 
+                         BSG_TPM_TAG, &tag, 
+                         BSG_TYPE_UINT32, &paramSize, 
+                         BSG_TPM_COMMAND_CODE, &ordinal, 
+                         BSG_TYPE_UINT32, &hUnwrappingKey);
+  memcpy(InBuf+InLength, rgbWrappedKeyBlob, cWrappedKeyBlobSize);
+  InLength += cWrappedKeyBlobSize;
+  InLength += packAuth(InBuf+InLength, pAuth);
+  // fill paramSize again as we now have the correct size
+  BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+  
+  // call the TPM driver
+  if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == 
TDDL_SUCCESS) {
+    // unpack OutBuf to get the tag, paramSize, & returnCode
+    int i = BSG_UnpackList(OutBuf, 3, 
+                          BSG_TPM_TAG, &tag, 
+                          BSG_TYPE_UINT32, &paramSize, 
+                          BSG_TPM_COMMAND_CODE, &returnCode);
+    
+    if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+      // Extract the remaining output parameters
+      i += BSG_Unpack(BSG_TYPE_UINT32, 
+                     OutBuf+i, 
+                     phKeyTCSI);
+      unpackAuth(pAuth, OutBuf+i);
+      
+      if (!AddHandleToList((CONTEXT_HANDLE *)hContext, TPM_RT_KEY, 
*phKeyTCSI)) {
+        vtpmlogerror(VTPM_LOG_TCS, "New KeyHandle not recorded\n");
+      }
+      
+      vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+     } else 
+      vtpmlogerror(VTPM_LOG_TCS, "TCSP_LoadKeyByBlob Failed with return code 
%s\n", tpm_get_error_name(returnCode));
+  }
+  
+  return(returnCode);
+}
+
+TPM_RESULT TCSP_EvictKey(TCS_CONTEXT_HANDLE hContext, // in
+                        TCS_KEY_HANDLE  hKey)  // in
+{
+  // setup input/output parameters block
+  TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+  UINT32 paramSize = 0;
+  TPM_COMMAND_CODE ordinal = TPM_ORD_EvictKey;
+  TPM_RESULT returnCode = TPM_SUCCESS;
+  
+  // setup the TPM driver input and output buffers
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TDDL_UINT32  InLength = TCPA_MAX_BUFFER_LENGTH;
+  TDDL_UINT32  OutLength = TCPA_MAX_BUFFER_LENGTH;
+  
+  // Convert Byte Input parameter in the input byte stream InBuf
+  InLength = BSG_PackList(InBuf, 4, 
+                         BSG_TPM_TAG, &tag, 
+                         BSG_TYPE_UINT32, &paramSize, 
+                         BSG_TPM_COMMAND_CODE, &ordinal, 
+                         BSG_TYPE_UINT32, &hKey);
+  // fill paramSize again as we now have the correct size
+  BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+  
+  // call the TPM driver
+  if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == 
TDDL_SUCCESS) {
+    // unpack OutBuf to get the tag, paramSize, & returnCode
+    BSG_UnpackList(OutBuf, 3, 
+                          BSG_TPM_TAG, &tag, 
+                          BSG_TYPE_UINT32, &paramSize, 
+                          BSG_TPM_COMMAND_CODE, &returnCode);
+    
+    if (!DeleteHandleFromList((CONTEXT_HANDLE *)hContext, hKey)) {
+      vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n");
+    }   
+    
+    if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+      vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+    } else {
+      vtpmlogerror(VTPM_LOG_TCS, "TCSP_EvictKey Failed with return code %s\n", 
tpm_get_error_name(returnCode));
+    }
+  }
+  
+  return(returnCode);
+}
+
+TPM_RESULT TCSP_GetRandom(TCS_CONTEXT_HANDLE hContext,  // in
+                         UINT32*    bytesRequested, // in, out
+                         BYTE**    randomBytes) // out
+{
+  // setup input/output parameters block
+  TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+  UINT32 paramSize = 0;
+  TPM_COMMAND_CODE ordinal = TPM_ORD_GetRandom;
+  TPM_RESULT returnCode = TPM_SUCCESS;
+  
+  // setup the TPM driver input and output buffers
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TDDL_UINT32  InLength = TCPA_MAX_BUFFER_LENGTH;
+  TDDL_UINT32  OutLength = TCPA_MAX_BUFFER_LENGTH;
+  
+  // check input params
+  if (bytesRequested == NULL || *randomBytes == NULL){
+    return TPM_BAD_PARAMETER;
+  }
+  
+  // Convert Byte Input parameter in the input byte stream InBuf
+  InLength = BSG_PackList(InBuf, 4, 
+                         BSG_TPM_TAG, &tag, 
+                         BSG_TYPE_UINT32, &paramSize, 
+                         BSG_TPM_COMMAND_CODE, &ordinal, 
+                         BSG_TYPE_UINT32, bytesRequested);
+  // fill paramSize again as we now have the correct size
+  BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+  
+  // call the TPM driver
+  if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == 
TDDL_SUCCESS) {
+    // unpack OutBuf to get the tag, paramSize, & returnCode
+    int i = BSG_UnpackList(OutBuf, 3, 
+                          BSG_TPM_TAG, &tag, 
+                          BSG_TYPE_UINT32, &paramSize, 
+                          BSG_TPM_COMMAND_CODE, &returnCode);
+    
+    if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+      // Extract the remaining output parameters
+      BSG_Unpack(BSG_TYPE_UINT32, OutBuf+i, bytesRequested);
+      if (TCS_Malloc(hContext, *bytesRequested, randomBytes) == TPM_FAIL) {
+        return TPM_SIZE;
+      }
+      memcpy(*randomBytes, OutBuf+i+sizeof(UINT32), *bytesRequested);
+      
+      vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+    } else {
+      vtpmlogerror(VTPM_LOG_TCS, "TCSP_GetRandom Failed with return code 
%s\n", tpm_get_error_name(returnCode));
+    }
+  }
+  
+  return(returnCode);
+}
+
+
+TPM_RESULT TCSP_ReadPubek(TCS_CONTEXT_HANDLE   hContext,               // in
+                         TPM_NONCE            antiReplay,             // in
+                         UINT32*              pubEndorsementKeySize,  // out
+                         BYTE**               pubEndorsementKey,      // out
+                         TPM_DIGEST*          checksum)               // out
+{
+  // setup input/output parameters block
+  TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+  UINT32 paramSize = 0;
+  TPM_COMMAND_CODE ordinal = TPM_ORD_ReadPubek;
+  TPM_RESULT returnCode = TPM_SUCCESS;
+  
+  // setup the TPM driver input and output buffers
+  TDDL_RESULT hRes = TDDL_E_FAIL;
+  TDDL_UINT32  InLength = TCPA_MAX_BUFFER_LENGTH;
+  TDDL_UINT32   OutLength = TCPA_MAX_BUFFER_LENGTH;
+  
+  // check input params
+  if (pubEndorsementKeySize == NULL || pubEndorsementKey == NULL || checksum 
== NULL) {
+    return TPM_BAD_PARAMETER;
+  }
+  
+  // Convert Byte Input parameter in the input byte stream InBuf
+  InLength = BSG_PackList(InBuf, 4, 
+                         BSG_TPM_TAG, &tag, 
+                         BSG_TYPE_UINT32, &paramSize, 
+                         BSG_TPM_COMMAND_CODE, &ordinal, 
+                         BSG_TPM_NONCE, &antiReplay);
+  // fill paramSize again as we now have the correct size
+  BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+  
+  vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+  
+  // call the TPM driver
+  if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == 
TDDL_SUCCESS) {
+    // unpack OutBuf to get the tag, paramSize, & returnCode
+    int i = BSG_UnpackList(OutBuf, 3, 
+                          BSG_TPM_TAG, &tag, 
+                          BSG_TYPE_UINT32, &paramSize, 
+                          BSG_TPM_COMMAND_CODE, &returnCode);
+    
+    if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+      // Extract the remaining output parameters
+      TPM_PUBKEY pubEK;
+      i += BSG_UnpackList(OutBuf+i, 2, 
+                         BSG_TPM_PUBKEY, &pubEK, 
+                         BSG_TPM_DIGEST, checksum);
+      
+      // fill EndorsementKey
+      BYTE tempBuf[1024];
+      *pubEndorsementKeySize = BSG_Pack(BSG_TPM_PUBKEY, &pubEK, tempBuf);
+      if (TCS_Malloc(hContext, *pubEndorsementKeySize, pubEndorsementKey) == 
TPM_FAIL) {
+        return TPM_SIZE;
+      }
+      memcpy(*pubEndorsementKey, tempBuf, *pubEndorsementKeySize);
+      
+      vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+    } else {
+      vtpmlogerror(VTPM_LOG_TCS, "TCSP_ReadPubek Failed with return code 
%s\n", tpm_get_error_name(returnCode));
+    }
+  }
+  
+  return(returnCode);
+}
+
+TPM_RESULT TCSP_RawTransmitData(   UINT32 inDataSize,  // in
+                                  BYTE *inData,       // in
+                                  UINT32 *outDataSize,// in/out
+                                  BYTE *outData) {    // out     
+  
+  TDDL_RESULT hRes;
+  
+  vtpmloginfo(VTPM_LOG_TCS, "Calling TransmitData directly.\n");
+  //FIXME: Add Context Management
+  hRes = TDDL_TransmitData( inData, 
+                           inDataSize, 
+                           outData, 
+                           outDataSize);
+  
+  if (hRes == TDDL_SUCCESS) {
+    return TPM_SUCCESS;
+  } else {
+    vtpmlogerror(VTPM_LOG_TCS, "TCSP_RawTransmitData Failed with return code 
%s\n", tpm_get_error_name(TPM_IOERROR));
+    return TPM_IOERROR;
+  }
+  
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/tcs/tcs.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/tcs/tcs.h      Fri Sep  9 16:30:54 2005
@@ -0,0 +1,238 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// tcs.h
+// 
+//  This file declares the TCS API
+// 
+// ==================================================================
+
+#ifndef __TCS_H__
+#define __TCS_H__
+
+#include "tcg.h"
+#include "buffer.h"
+
+#define HANDLE_NULL 0
+
+// ------------------------------------------------------------------
+// Exposed API
+// ------------------------------------------------------------------
+
+TPM_RESULT TCS_create();
+void TCS_destroy();
+
+TPM_RESULT TCS_OpenContext( /* OUT */ TCS_CONTEXT_HANDLE* hContext );
+
+TPM_RESULT TCS_CloseContext ( /* IN */ TCS_CONTEXT_HANDLE hContext );
+
+TPM_RESULT TCS_Malloc ( TCS_CONTEXT_HANDLE hContext, // in
+                       UINT32   MemSize, // in
+                       BYTE**   ppMemPtr ); //out
+
+TPM_RESULT TCS_FreeMemory ( TCS_CONTEXT_HANDLE hContext, // in
+                           BYTE*    pMemory);  // in
+
+// ------------------------------------------------------------------
+// Exposed API
+// ------------------------------------------------------------------
+
+// TPM v1.1B Command Set
+
+// Authorzation
+TPM_RESULT TCSP_OIAP( TCS_CONTEXT_HANDLE hContext, // in
+                     TCS_AUTHHANDLE*  authHandle, // out 
+                     TPM_NONCE*   nonce0  // out
+                     );
+
+TPM_RESULT TCSP_OSAP (  TCS_CONTEXT_HANDLE hContext,  // in
+                       TPM_ENTITY_TYPE entityType,  // in
+                       UINT32    entityValue, // in
+                       TPM_NONCE   nonceOddOSAP, // in
+                       TCS_AUTHHANDLE*  authHandle,  // out 
+                       TPM_NONCE*   nonceEven,  // out
+                       TPM_NONCE*   nonceEvenOSAP // out
+                       );
+
+TPM_RESULT TCSP_TakeOwnership (  TCS_CONTEXT_HANDLE hContext,   // in
+                                UINT16    protocolID,   // in
+                                UINT32    encOwnerAuthSize, // in 
+                                BYTE*    encOwnerAuth,  // in
+                                UINT32    encSrkAuthSize,  // in
+                                BYTE*    encSrkAuth,   // in
+                                UINT32*    SrkSize,   // in, out
+                                BYTE**    Srk,    // in, out
+                                TCS_AUTH*   ownerAuth   // in, out
+                                );
+
+TPM_RESULT TCSP_DisablePubekRead (  TCS_CONTEXT_HANDLE hContext, // in
+                                    TCS_AUTH*   ownerAuth // in, out
+                                    );
+
+TPM_RESULT TCSP_TerminateHandle (  TCS_CONTEXT_HANDLE hContext, // in
+                                  TCS_AUTHHANDLE  handle  // in
+                                  );
+
+TPM_RESULT TCSP_FlushSpecific (  TCS_CONTEXT_HANDLE hContext, // in
+                                TCS_AUTHHANDLE  handle,  // in
+                                TPM_RESOURCE_TYPE resourceType //in 
+                                );
+
+// TPM Mandatory
+TPM_RESULT TCSP_Extend (  TCS_CONTEXT_HANDLE hContext, // in
+                         TPM_PCRINDEX  pcrNum,  // in
+                         TPM_DIGEST   inDigest, // in
+                         TPM_PCRVALUE*   outDigest // out
+                         );
+
+TPM_RESULT TCSP_PcrRead (  TCS_CONTEXT_HANDLE hContext, // in
+                          TPM_PCRINDEX  pcrNum,  // in
+                          TPM_PCRVALUE*  outDigest // out
+                          );
+
+TPM_RESULT TCSP_Quote (  TCS_CONTEXT_HANDLE hContext,  // in
+                        TCS_KEY_HANDLE  keyHandle,  // in
+                        TPM_NONCE   antiReplay,  // in
+                        UINT32*    PcrDataSize, // in, out
+                        BYTE**    PcrData,  // in, out
+                        TCS_AUTH*   privAuth,  // in, out
+                        UINT32*    sigSize,  // out
+                        BYTE**    sig    // out
+                        );
+
+TPM_RESULT TCSP_Seal (  TCS_CONTEXT_HANDLE hContext,  // in
+                       TCS_KEY_HANDLE  keyHandle,  // in
+                       TPM_ENCAUTH  encAuth,  // in
+                       UINT32    pcrInfoSize, // in
+                       BYTE*    PcrInfo,  // in
+                       UINT32    inDataSize,  // in
+                       BYTE*    inData,   // in
+                       TCS_AUTH*   pubAuth,  // in, out
+                       UINT32*    SealedDataSize, // out
+                       BYTE**    SealedData  // out
+                       );
+
+TPM_RESULT TCSP_Unseal (  TCS_CONTEXT_HANDLE hContext,  // in
+                         TCS_KEY_HANDLE  parentHandle, // in
+                         UINT32    SealedDataSize, // in
+                         BYTE*    SealedData,  // in
+                         TCS_AUTH*   parentAuth,  // in, out
+                         TCS_AUTH*   dataAuth,  // in, out
+                         UINT32*    DataSize,  // out
+                         BYTE**    Data   // out
+                         );
+
+TPM_RESULT TCSP_DirWriteAuth (  TCS_CONTEXT_HANDLE hContext,  // in
+                               TPM_DIRINDEX  dirIndex,  // in
+                               TPM_DIRVALUE  newContents, // in
+                               TCS_AUTH*   ownerAuth  // in, out
+                               );
+
+TPM_RESULT TCSP_DirRead (  TCS_CONTEXT_HANDLE hContext, // in
+                          TPM_DIRINDEX  dirIndex, // in
+                          TPM_DIRVALUE*  dirValue // out
+                          );
+
+TPM_RESULT TCSP_UnBind (  TCS_CONTEXT_HANDLE hContext,  // in
+                         TCS_KEY_HANDLE  keyHandle,  // in
+                         UINT32    inDataSize,  // in
+                         BYTE*    inData,   // in
+                         TCS_AUTH*   privAuth,  // in, out
+                         UINT32*    outDataSize, // out
+                         BYTE**    outData   // out
+                         );
+
+TPM_RESULT TCSP_CreateWrapKey (  TCS_CONTEXT_HANDLE hContext,   // in
+                                TCS_KEY_HANDLE  hWrappingKey,  // in
+                                TPM_ENCAUTH  KeyUsageAuth,  // in
+                                TPM_ENCAUTH  KeyMigrationAuth, // in
+                                UINT32*    pcKeySize,   // in, out
+                                BYTE**    prgbKey,   // in, out
+                                TCS_AUTH*   pAuth    // in, out
+                                );
+
+TPM_RESULT TCSP_LoadKeyByBlob (  TCS_CONTEXT_HANDLE hContext,    // in
+                                TCS_KEY_HANDLE  hUnwrappingKey,   // in
+                                UINT32    cWrappedKeyBlobSize, // in
+                                BYTE*    rgbWrappedKeyBlob,  // in
+                                TCS_AUTH*   pAuth,     // in, out
+                                TCS_KEY_HANDLE*  phKeyTCSI,    // out
+                                TCS_KEY_HANDLE*  phKeyHMAC    // out
+                                );
+
+TPM_RESULT TCSP_GetPubKey (  TCS_CONTEXT_HANDLE hContext,  // in
+                            TCS_KEY_HANDLE  hKey,   // in
+                            TCS_AUTH*   pAuth,   // in, out
+                            UINT32*    pcPubKeySize, // out
+                            BYTE**    prgbPubKey  // out
+                            ); 
+
+TPM_RESULT TCSP_EvictKey (  TCS_CONTEXT_HANDLE hContext, // in
+                           TCS_KEY_HANDLE  hKey  // in
+                           );
+
+TPM_RESULT TCSP_Sign (  TCS_CONTEXT_HANDLE hContext,  // in
+                       TCS_KEY_HANDLE  keyHandle,  // in
+                       UINT32    areaToSignSize, // in
+                       BYTE*    areaToSign,  // in
+                       TCS_AUTH*   privAuth,  // in, out
+                       UINT32*    sigSize,  // out
+                       BYTE**    sig    // out
+                       );
+
+TPM_RESULT TCSP_GetRandom (  TCS_CONTEXT_HANDLE hContext,  // in
+                            UINT32*    bytesRequested, // in, out
+                            BYTE**    randomBytes  // out
+                            );
+
+TPM_RESULT TCSP_StirRandom (  TCS_CONTEXT_HANDLE hContext, // in
+                             UINT32    inDataSize, // in
+                             BYTE*    inData  // in
+                             );
+
+TPM_RESULT TCSP_ReadPubek (  TCS_CONTEXT_HANDLE hContext,    // in
+                            TPM_NONCE   antiReplay,    // in
+                            UINT32*    pubEndorsementKeySize, // out
+                            BYTE**    pubEndorsementKey,  // out
+                            TPM_DIGEST*  checksum    // out
+                            );
+
+
+// Non-Standard TCSP call to give direct access to TransmitData.
+// Key and Auth Management is done before transfering command to TDDL.
+TPM_RESULT TCSP_RawTransmitData(UINT32 inDataSize,  // in
+                               BYTE *inData,       // in
+                               UINT32 *outDataSize,// in/out
+                               BYTE *outData);     // out
+
+#endif //TCS_H
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/tcs/tpmddl.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/tcs/tpmddl.h   Fri Sep  9 16:30:54 2005
@@ -0,0 +1,69 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// tpmddl.c
+// 
+//  This file defines the TDDLI API
+//
+// ==================================================================
+
+#ifndef __TPMDDL_H__
+#define __TPMDDL_H__
+
+#define TDDL_CAP_PROP_MANUFACTURER 0x0001
+
+#define TDDL_E_FAIL 1
+#define TDDL_E_SUCCESS 0
+#define TDDL_SUCCESS 0
+
+typedef unsigned int TDDL_UINT32;
+typedef TDDL_UINT32 TDDL_RESULT;
+typedef unsigned char TDDL_BYTE;
+
+TDDL_RESULT TDDL_Open();
+void TDDL_Close();
+TDDL_RESULT TDDL_TransmitData( TDDL_BYTE* in,
+                              TDDL_UINT32 insize,
+                              TDDL_BYTE* out,
+                              TDDL_UINT32* outsize);
+TDDL_RESULT TDDL_GetStatus();
+TDDL_RESULT TDDL_GetCapability( TDDL_UINT32 cap,
+                               TDDL_UINT32 sub,
+                               TDDL_BYTE* buffer,
+                               TDDL_UINT32* size);
+TDDL_RESULT TDDL_SetCapability( TDDL_UINT32 cap,
+                               TDDL_UINT32 sub,
+                               TDDL_BYTE* buffer,
+                               TDDL_UINT32* size);
+
+#endif // __TPMDDL_H__
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/tcs/transmit.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/tcs/transmit.c Fri Sep  9 16:30:54 2005
@@ -0,0 +1,131 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "tcg.h"
+#include "buffer.h"
+#include "log.h"
+#include "tpmddl.h"
+
+// flag to track whether TDDL has been opened
+static int g_TDDL_open = 0;
+static int g_fd = -1;              // the fd to the TPM
+
+TPM_RESULT
+TDDL_TransmitData( TDDL_BYTE* in,
+                  TDDL_UINT32 insize,
+                  TDDL_BYTE* out,
+                  TDDL_UINT32* outsize) {
+  TPM_RESULT status = TPM_SUCCESS;
+  TDDL_UINT32 i;
+  
+  vtpmloginfo(VTPM_LOG_TXDATA, "Sending buffer = 0x");
+  for(i = 0 ; i < insize ; i++) 
+    vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", in[i]);
+
+  vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
+  
+  ssize_t size = 0;
+  int fd = g_fd;
+  
+  // send the request
+  size = write (fd, in, insize);
+  if (size < 0) {
+    vtpmlogerror(VTPM_LOG_TXDATA, "write() failed");
+    ERRORDIE (TPM_IOERROR);
+  }
+  else if ((TDDL_UINT32) size < insize) {
+    vtpmlogerror(VTPM_LOG_TXDATA, "Wrote %d instead of %d bytes!\n", size, 
insize);
+    // ... ?
+  }
+
+  // read the response
+  size = read (fd, out, TCPA_MAX_BUFFER_LENGTH);
+  if (size < 0) {
+    vtpmlogerror(VTPM_LOG_TXDATA, "read() failed");
+    ERRORDIE (TPM_IOERROR);
+  }
+  
+  vtpmloginfo(VTPM_LOG_TXDATA, "Receiving buffer = 0x");
+  for(i = 0 ; i < size ; i++) 
+    vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out[i]);
+
+  vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
+
+  *outsize = size;
+  // close connection
+  goto egress;
+  
+ abort_egress:
+ egress:
+  return status;
+}
+
+TPM_RESULT TDDL_Open() {
+  
+  TDDL_RESULT status = TDDL_SUCCESS;
+  int fd = -1;
+  
+  if (g_TDDL_open)
+    return TPM_FAIL;
+  
+  fd = open ("/dev/tpm0", O_RDWR);
+  if (fd < 0) {
+    vtpmlogerror(VTPM_LOG_TXDATA, "TPM open failed");
+    return TPM_IOERROR;
+  }
+  
+  g_fd = fd;
+  g_TDDL_open = 1;
+  
+  return status;
+}
+
+void TDDL_Close() {
+  if (! g_TDDL_open)
+        return;
+
+  if (g_fd>= 0) {
+    if (close(g_fd) < 0) 
+      vtpmlogerror(VTPM_LOG_TXDATA, "closeing tpm failed");
+    
+    g_fd = -1;
+  }
+    
+  g_TDDL_open = 0;
+  
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/Makefile
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/util/Makefile  Fri Sep  9 16:30:54 2005
@@ -0,0 +1,18 @@
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+BIN            = libTCGUtils.a
+
+all: build
+
+build: $(BIN)
+
+install: build
+
+clean:
+       rm -f *.a *.so *.o *.rpm $(DEP_FILES)
+
+mrproper: clean
+
+$(BIN): $(OBJS)
+       $(AR) rcs $(BIN) $(OBJS)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/bsg.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/util/bsg.c     Fri Sep  9 16:30:54 2005
@@ -0,0 +1,830 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// bsg.cpp
+// 
+//  This file will handle all the TPM Byte Stream functions
+// 
+// ==================================================================
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <malloc.h>
+#include "tcg.h"
+#include "crypto.h"
+#include "bsg.h"
+#include "log.h"
+
+static int g_log_recursion_level = 0;
+
+// a largest buffer size. if we get a buf size bigger than this when unpacking,
+// will complain!
+#define BSG_MAX_BUF_SIZE (1<<18)
+
+#define bsglog(fmt, ...) do { \
+    int __i; \
+    for (__i=0; __i < g_log_recursion_level; __i++) {               \
+      vtpmloginfomore (VTPM_LOG_BSG, "%s", "  ");                           \
+    }                                                                 \
+    vtpmloginfomore (VTPM_LOG_BSG, fmt, __VA_ARGS__);                         \
+  } while (0)
+
+
+// FIXME:  trigger the selfcheck--need to use glibc hook to do this
+//BOOL dummy1 = BSG_static_selfcheck();
+
+
+// Interpretting Types
+// -------------------
+// 
+// Incoming Types are composed of two parts {format, info} squished into a
+// BSG_UINT32.  The first 4 bits is a format spec indicating what type of
+// data it is.  If the first 4 bits are zero the info corresponds to a value in
+// BSG_s_fmt[]. This is a structure whose composition is described in
+// BSG_s_fmt[]. If the value is non-zero, info corresponds to the size of the
+// data (in bytes) being passed in. For example a UINT32 being passed in would
+// have a format of (__FMT_CONST | 4). If both, the format and info are zero,
+// this is interpretted as the end of the structure, and the result is 
returned.
+
+// these flags are mutually exclusive, so I'll just make them
+// format values which indicate the semantics of the 'info' part and the source
+// data. The above description has been accordingly adjusted.
+
+// format values for determining what type of data the incoming type is
+// it's a 4 bit value, occupying the high 4 bits
+#define __FMT_CONST (1UL << 28) // Constant sized value
+#define __FMT_DATA  (2UL << 28) // Believed to be raw data NOT {size,data}
+#define __FMT_SIZE  (3UL << 28) // A size. Used in FMT_SIZE??_DATA.
+#define __FMT_HSIZE (4UL << 28) // A number of handles
+#define __FMT_PACKED (5UL << 28) // 'info' is unused; the source data consists
+                                 // of {size32, data} but we're to pack only 
the
+                                 // data as that is already packed, and so
+                                 // can/must be unpacked without
+                                 // explicitly reading it size
+
+#define __FMT_MASK  0x0FFFFFFFUL // this masks out the 4-bit format
+#define __FMT_MASK_SIZE(type)   ((type) & __FMT_MASK)
+#define __FMT_MASK_FORMAT(type) ((type) & (~__FMT_MASK))
+
+// constant (8/16/32-bits)
+#define FMT_U8 (__FMT_CONST | 1UL)
+#define FMT_U16 (__FMT_CONST | 2UL)
+#define FMT_U32 (__FMT_CONST | 4UL)
+
+// const with a compiler-computed size
+#define FMT_SIZEOF(type) (__FMT_CONST | sizeof(type))
+
+// other data (size bytes) 
+// Used primarily for DIGESTS -> FMT_DATA(20)
+#define FMT_DATA(size) (__FMT_DATA | ((BSG_UINT32) (size) & __FMT_MASK))
+
+// 16/32-bit size followed by N bytes of data
+#define FMT_SIZE16_DATA (__FMT_SIZE | 2UL)
+#define FMT_SIZE32_DATA (__FMT_SIZE | 4UL)
+
+// 16-bit size followed by N key handles
+#define FMT_SIZE16_HANDLES (__FMT_HSIZE | 2UL)
+
+#define DIGEST_SIZE 20 
+typedef BSG_UINT32 BSG_HANDLE;
+
+// TCPA_AUTH has 11 fields!
+#define MAX_FIELDS 11
+typedef struct BSG_Format
+{
+  BSG_Type type;
+  const char* name;
+  BSG_UINT32 fields[MAX_FIELDS + 1];
+} BSG_Format;
+
+/*
+ * TCPA structure data formats
+ */
+// this has to be manually kept in sync with the
+// Type enum!! the static_selfcheck() function should be used regularly!
+static BSG_Format s_fmt[] =
+{
+  {BSG_TYPE_UINT32, "BSG_TYPE_UINT32", {FMT_U32, 0}},
+  {BSG_TYPE_UINT16, "BSG_TYPE_UINT16", {FMT_U16, 0}},
+  {BSG_TYPE_BYTE, "BSG_TYPE_BYTE", {FMT_U8, 0}},
+  {BSG_TYPE_BOOL, "BSG_TYPE_BOOL", {FMT_U8, 0}},
+  {BSG_TPM_SIZE32_DATA, "BSG_TPM_SIZE32_DATA", {FMT_SIZE32_DATA, 0}},
+  {BSG_TPM_TAG, "BSG_TPM_TAG", {FMT_SIZEOF(TPM_TAG), 0}},
+  {BSG_TPM_HANDLE, "BSG_TPM_HANDLE", {FMT_SIZEOF(TPM_HANDLE), 0}},
+  {BSG_TPM_RESULT, "BSG_TPM_RESULT", {FMT_SIZEOF(TPM_RESULT), 0}},
+  {BSG_TPM_RESOURCE_TYPE, "BSG_TPM_RESOURCE_TYPE", 
{FMT_SIZEOF(TPM_RESOURCE_TYPE), 0}},
+  {BSG_TPM_COMMAND_CODE, "BSG_TPM_COMMAND_CODE", {FMT_U32, 0}},
+  {BSG_TPM_AUTH_DATA_USAGE, "BSG_TPM_AUTH_DATA_USAGE", {FMT_U8, 0}},
+  {BSG_TPM_ALGORITHM_ID, "BSG_TPM_ALGORITHM_ID", {FMT_U32, 0}},
+  {BSG_TPM_PROTOCOL_ID, "BSG_TPM_PROTOCOL_ID", {FMT_SIZEOF(TPM_PROTOCOL_ID), 
0}},
+  {BSG_TPM_KEY_USAGE, "BSG_TPM_KEY_USAGE", {FMT_U16, 0}},
+  {BSG_TPM_ENC_SCHEME, "BSG_TPM_ENC_SCHEME", {FMT_U16, 0}},
+  {BSG_TPM_SIG_SCHEME, "BSG_TPM_SIG_SCHEME", {FMT_U16, 0}},
+  {BSG_TPM_MIGRATE_SCHEME, "BSG_TPM_MIGRATE_SCHEME", {FMT_U16, 0}},
+  {BSG_TPM_KEY_FLAGS, "BSG_TPM_KEY_FLAGS", {FMT_U32, 0}},
+    
+  {BSG_TPM_AUTHDATA, "BSG_TPM_AUTHDATA", {FMT_DATA(DIGEST_SIZE), 0}},
+  {BSG_TPM_SECRET, "BSG_TPM_SECRET", {BSG_TPM_AUTHDATA, 0}},
+  {BSG_TPM_ENCAUTH, "BSG_TPM_ENCAUTH", {BSG_TPM_AUTHDATA, 0}},
+  {BSG_TPM_PAYLOAD_TYPE, "BSG_TPM_PAYLOAD_TYPE", 
{FMT_SIZEOF(TPM_PAYLOAD_TYPE), 0}},
+  
+  {BSG_TPM_VERSION, "BSG_TPM_VERSION", {FMT_DATA(4), 0}}, // vers 1.2
+  {BSG_TPM_DIGEST, "BSG_TPM_DIGEST", {FMT_DATA(DIGEST_SIZE), 0}},
+  {BSG_TPM_COMPOSITE_HASH, "BSG_TPM_COMPOSITE_HASH", {BSG_TPM_DIGEST, 0}},
+  {BSG_TPM_CHOSENID_HASH, "BSG_TPM_CHOSENID_HASH", {BSG_TPM_DIGEST, 0}},
+  
+  {BSG_TPM_NONCE, "BSG_TPM_NONCE", {FMT_DATA(DIGEST_SIZE), 0}},
+  {BSG_TPM_KEY_HANDLE, "BSG_TPM_KEY_HANDLE", {FMT_SIZEOF(TPM_KEY_HANDLE), 0}},
+  {BSG_TPM_KEY_HANDLE_LIST, "BSG_TPM_KEY_HANDLE_LIST",
+   {FMT_SIZE16_HANDLES, 0}},
+  
+  {BSG_TPM_KEY_PARMS, "BSG_TPM_KEY_PARMS", {
+      BSG_TPM_ALGORITHM_ID,
+      BSG_TPM_ENC_SCHEME,
+      BSG_TPM_SIG_SCHEME,
+      FMT_SIZE32_DATA,
+      0}},
+  {BSG_TPM_RSA_KEY_PARMS, "BSG_TPM_RSA_KEY_PARMS", {
+      FMT_U32, FMT_U32, FMT_SIZE32_DATA, 0}},
+  {BSG_TPM_STORE_PUBKEY, "BSG_TPM_STORE_PUBKEY", {FMT_SIZE32_DATA, 0}},
+  {BSG_TPM_PUBKEY, "BSG_TPM_PUBKEY", {BSG_TPM_KEY_PARMS, BSG_TPM_STORE_PUBKEY, 
0}},
+  {BSG_TPM_KEY, "BSG_TPM_KEY", {
+      BSG_TPM_VERSION,
+      BSG_TPM_KEY_USAGE,
+      BSG_TPM_KEY_FLAGS,
+      BSG_TPM_AUTH_DATA_USAGE,
+      BSG_TPM_KEY_PARMS,
+      FMT_SIZE32_DATA,        // the PCR_INFO
+      BSG_TPM_STORE_PUBKEY,
+      FMT_SIZE32_DATA,        // the encrypted part
+      0}},
+  
+  {BSG_TPM_MIGRATIONKEYAUTH, "BSG_TPM_MIGRATIONKEYAUTH", {
+      BSG_TPM_PUBKEY,
+      BSG_TPM_MIGRATE_SCHEME,
+      BSG_TPM_DIGEST, 0}},
+  
+  {BSG_TCPA_AUDIT_EVENT, "TCPA_AUDIT_EVENT", {
+      BSG_TPM_COMMAND_CODE,
+      BSG_TPM_RESULT, 0 }},
+  
+  {BSG_TCPA_EVENT_CERT, "TCPA_EVENT_CERT", {
+      BSG_TPM_DIGEST,
+      BSG_TPM_DIGEST,
+      FMT_DATA(2),
+      FMT_SIZE32_DATA, 0}},
+  
+  {BSG_TPM_PCR_SELECTION, "BSG_TPM_PCR_SELECTION", {FMT_SIZE16_DATA, 0} },
+  {BSG_TPM_PCR_COMPOSITE, "BSG_TPM_PCR_COMPOSITE", { BSG_TPM_PCR_SELECTION,
+                                                    FMT_SIZE32_DATA,
+                                                    0} },
+
+  {BSG_TPM_PCR_INFO, "BSG_TPM_PCR_INFO", { BSG_TPM_PCR_SELECTION,
+                                          BSG_TPM_COMPOSITE_HASH, 
+                                          BSG_TPM_COMPOSITE_HASH,
+                                          0} },
+  
+  
+  {BSG_TPM_STORED_DATA, "BSG_TPM_STORED_DATA", {
+      BSG_TPM_VERSION,
+      FMT_SIZE32_DATA,
+      FMT_SIZE32_DATA,
+      0}},
+  {BSG_TPM_SYMMETRIC_KEY, "BSG_TPM_SYMMETRIC_KEY", {
+      BSG_TPM_ALGORITHM_ID,
+      BSG_TPM_ENC_SCHEME,
+      FMT_SIZE16_DATA,
+      0}},
+  {BSG_TPM_STORE_PRIVKEY, "BSG_TPM_STORE_PRIVKEY", {FMT_SIZE32_DATA, 0}},
+  {BSG_TPM_STORE_ASYMKEY, "BSG_TPM_STORE_ASYMKEY", {
+      BSG_TPM_PAYLOAD_TYPE,
+      BSG_TPM_SECRET,
+      BSG_TPM_SECRET,
+      BSG_TPM_DIGEST,
+      BSG_TPM_STORE_PRIVKEY,
+      0}},
+  {BSG_TPM_MIGRATE_ASYMKEY, "BSG_TPM_MIGRATE_ASYMKEY", {
+      BSG_TPM_PAYLOAD_TYPE,
+      BSG_TPM_SECRET,
+      BSG_TPM_DIGEST,
+      FMT_U32,
+      BSG_TPM_STORE_PRIVKEY,
+      0}},
+  
+  {BSG_TPM_QUOTE_INFO, "BSG_TPM_QUOTE_INFO", {
+      BSG_TPM_VERSION,
+      FMT_DATA(4),
+      BSG_TPM_COMPOSITE_HASH,
+      BSG_TPM_NONCE,
+      0}},
+  
+  {BSG_TPM_IDENTITY_CONTENTS, "BSG_TPM_IDENTITY_CONTENTS", {
+      BSG_TPM_VERSION,
+      FMT_U32,
+      BSG_TPM_CHOSENID_HASH,
+      BSG_TPM_PUBKEY,
+      0}},
+  
+  {BSG_TPM_PCRVALUE, "BSG_TPM_PCRVALUE", {FMT_DATA(DIGEST_SIZE), 0}},
+  
+  {BSG_TCPA_PCR_FLAGS, "TCPA_PCR_FLAGS", {
+      FMT_U8,
+      FMT_U8,
+      0}},
+  
+  {BSG_TCS_AUTH, "TCS_AUTH", {
+      BSG_TYPE_UINT32, 
+      BSG_TPM_NONCE, 
+      BSG_TPM_NONCE, 
+      BSG_TYPE_BOOL, 
+      BSG_TPM_AUTHDATA, 
+      0}},
+  
+  {BSG_TPM_KEY_NONSENSITIVE, "BSG_TPM_KEY_NONSENSITIVE", {
+      BSG_TPM_VERSION,
+      BSG_TPM_KEY_USAGE,
+      BSG_TPM_KEY_FLAGS,
+      BSG_TPM_AUTH_DATA_USAGE,
+      BSG_TPM_KEY_PARMS,
+      FMT_SIZE32_DATA,
+      BSG_TPM_STORE_PUBKEY,
+      0}},
+  
+  {BSG_PACKED, "BSG_PACKED", {
+      __FMT_PACKED,
+      0 }},
+  
+  {BSG_TYPE_MAX, "", {0}},
+};
+
+
+static const BSG_Format* find_format (BSG_Type t) {
+  BSG_Format * f = s_fmt;
+  
+  if (t >= BSG_TYPE_MAX) {
+    return NULL;
+  }
+  
+  // WARNING: this depends on the enum and s_fmt[] array being in sync! make
+  // sure to run the static_selfcheck() to make sure
+  f = s_fmt + (t - BSG_TYPE_FIRST);
+  
+  return f;
+}
+
+//
+// a consistency-checking routine which can be run at compile time
+// (ie. immediately after compilation)
+//
+// tasks:
+// - verify that s_fmt has one entry per Type t, and that entry is at s_fmt[t]
+//
+// conditions:
+// - need that s_fmt[0] is the first type listed in the Type enum! ie the first
+//   Type has value 0, not 1
+//
+// FIXME: should have a function be passed in here which is called if the test
+// fails. Then the caller can decide what to do: abort, notify, whatever
+// 
+BOOL BSG_static_selfcheck ()
+{
+  int i;
+
+  for (i=BSG_TYPE_FIRST; i <= BSG_TYPE_MAX; i++) {
+    if (s_fmt[i - BSG_TYPE_FIRST].type != i) {
+      bsglog ("%s\n", "BSG: static_selfcheck failed!\n");
+      bsglog ("failure at %i, allegedly %s\n",
+             i, s_fmt[i - BSG_TYPE_FIRST].name);
+      abort();
+      return FALSE;
+    }
+  }
+  
+  bsglog ("%s\n", "BSG: static_selfcheck success!");
+  return TRUE;
+}
+
+
+/**
+ * Flatten a TCPA structure into a buffer in big-endian format
+ * @type: TCPA structure type
+ * @src: (IN) TCPA structure (OUT) end of TCPA structure
+ * @dst: (OUT) flattened data
+ * Returns: Flattened size or -1 for unknown types
+ */
+// make it so that it can just run through the whole process and return
+// the packed size, without packing anything. this will be done if dst is NULL.
+static int BSG_Pack_private(BSG_Type type, const BSG_BYTE** src, BSG_BYTE* dst)
+{
+  // check incoming parameters
+  if (*src == NULL)
+    return 0;
+  
+  const BSG_BYTE* s = *src;
+  BSG_BYTE* d = dst;
+  
+  BSG_UINT32 size   = __FMT_MASK_SIZE(type);
+  BSG_UINT32 format = __FMT_MASK_FORMAT(type);
+  
+  if (format == __FMT_CONST) // We are dealing with a fixed length value eg. 
UINT32
+    {
+      BSG_UINT32 val = 0;
+      switch (size) {
+      case 1: val = * (BYTE*) s; break;
+      case 2: val = * (unsigned short*) s; break;
+      case 4: val = * (BSG_UINT32*) s; break;
+      }
+      if (dst)
+       BSG_PackConst(val, size, d);
+
+      s += size;
+      d += size;
+    } else if (format == __FMT_DATA) { // We are dealing with raw data. Not 
sure when
+    // this is used.
+    
+      if (dst) {
+        bsglog ("BSG: __FMT_DATA size %d, src %p, dst %p\n", size, s, d);
+        memcpy(d, s, size);
+      }
+
+      s += size;
+      d += size;
+  } else if (format == __FMT_SIZE || format == __FMT_HSIZE) { // It's a size, 
followed by that much data or handles
+    
+    BSG_UINT32 psize = 0;
+    switch (size) {
+    case 1: psize = * (BYTE*) s; break;
+    case 2: psize = * (unsigned short*) s; break;
+    case 4: psize = * (BSG_UINT32*) s; break;
+    }
+        
+    if (dst)
+      BSG_PackConst(psize, size, d);
+
+    s += size;
+    d += size;
+    
+    // now 's' points to an address, so cast it to BSG_BYTE**
+    const BSG_BYTE* pdata = * ((BSG_BYTE**) s);
+    s += sizeof(BSG_BYTE*);
+    
+    if (format == __FMT_HSIZE) {// This is a list of psize Handles
+      if (dst) {
+       BSG_HANDLE* d2 = (BSG_HANDLE*) d;
+       BSG_HANDLE* p2 = (BSG_HANDLE*) pdata;
+       BSG_UINT32 i;
+       for (i = 0; i < psize; i++) 
+         d2[i] = BSG_UnpackConst((BSG_BYTE*)(p2 + i), 4);
+       
+      }
+      d += psize * sizeof(BSG_HANDLE);
+    } else {// If it's not psize handles, it's psize data.
+      if (psize > 0) {
+       if (dst) {
+         bsglog ("BSG: __FMT_SIZE, size=%d, src=%p, dst=%p\n",
+                 psize, pdata, d);
+         memcpy(d, pdata, psize);
+       }
+      }
+      d += psize;
+    }
+  } else if (format == __FMT_PACKED) {
+    // the source buffer is a pack_constbuf_t, which has a size and a
+    // pointer. just copy the buffer value, the size is not included in the
+    // output stream.
+    pack_constbuf_t * buf = (pack_constbuf_t*) s;
+    
+    if (dst) {
+      bsglog ("BSG: __FMT_PACKED, size=%d, src=%p, dst=%p\n",
+             buf->size, buf->data, d);
+      memcpy(d, buf->data, buf->size);
+    }
+        
+    s += buf->size;
+    d += buf->size;
+  } else if (format == 0) {// No flags are set. This is a structure & it should
+                          // be looked up in the bsg_s_fmt[]
+    
+    const BSG_Format* x = find_format (type);
+    if (x == NULL) {
+      vtpmloginfo(VTPM_LOG_BSG, "BSG_Pack: cannot find type %d\n", type);
+      return -1;
+    }
+    
+    if (dst)
+      bsglog ("BSG_Pack type %s\n", x->name);
+    
+    
+    // iterate through the fields
+    const BSG_UINT32* f = x->fields;
+    for (; *f; f++) {
+      int fsize;
+      
+      g_log_recursion_level++;
+      fsize = BSG_Pack_private((BSG_Type) *f, &s, dst ? d : NULL);
+      g_log_recursion_level--;
+      
+      if (fsize <= 0)
+       return fsize;
+      
+      d += fsize;
+    }
+  } else {
+    vtpmlogerror(VTPM_LOG_BSG, "BSG_Pack(): Unknown format %d\n", format);
+    return -1;
+  }
+  
+  *src = s;
+  return (d - dst);
+}
+
+/**
+ * Unflatten a TCPA structure from a buffer in big-endian format
+ * @type: TCPA structure type
+ * @src: flattened data
+ * @dst: (IN) TCPA structure (OUT) end of TCPA structure
+ * Returns: Flattened size
+ * Note: Returns flattened size NOT the unpacked structure size
+ */
+static int BSG_Unpack_private(BSG_Type type, const BSG_BYTE* src, BSG_BYTE** 
dst) {
+  // check incoming parameters
+  if (src == NULL)
+    return 0;
+  
+  
+  const BSG_BYTE* s = src;
+  BSG_BYTE* d = dst ? *dst:NULL;
+  if (dst && !d)
+    dst = NULL;
+  
+  BSG_UINT32 size = __FMT_MASK_SIZE(type);
+  BSG_UINT32 format = __FMT_MASK_FORMAT(type);
+  
+  if (format == __FMT_CONST) {// We are dealing with a fixed length value ie. 
UINT32
+
+    BSG_UINT32 val = BSG_UnpackConst(s, size);
+
+    if (dst) {
+      switch (size) {
+      case 1: *(BYTE *) d = (BSG_BYTE) val; break;
+      case 2: *(unsigned short*) d = (unsigned short) val; break;
+      case 4: *(BSG_UINT32*) d = (BSG_UINT32) val; break;
+      }
+    }
+
+    s += size;
+    d += size;
+  } else if (format == __FMT_DATA) {// We are dealing with raw data. Not sure 
when this is used.
+    if (dst)
+      memcpy(d, s, size);
+
+    d += size;
+    s += size;
+  } else if (format == __FMT_SIZE || format == __FMT_HSIZE) {// It's a size, 
followed by that much data or handles
+    
+    BSG_UINT32 psize = BSG_UnpackConst(s, size);
+    
+    if (psize > BSG_MAX_BUF_SIZE) {
+      vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack runs into var-sized data bigger 
than %u bytes!!\n",
+              BSG_MAX_BUF_SIZE);
+      return -1;
+    }
+    
+    if (dst) {
+      switch (size) {
+      case 1: *(BYTE *) d = (BSG_BYTE) psize; break;
+      case 2: *(unsigned short*) d = (unsigned short) psize; break;
+      case 4: *(BSG_UINT32*) d = (BSG_UINT32) psize; break;
+      }
+    }
+
+    s += size;
+    d += size;
+    
+    BSG_BYTE* pdata = NULL;
+    
+    if (psize) {
+      if (format == __FMT_HSIZE) { // This is a list of psize Handles
+       if (dst) {
+         BSG_HANDLE* s2 = (BSG_HANDLE*) s;
+         pdata = (BSG_BYTE *)malloc(psize * sizeof(BSG_HANDLE));
+          if (!pdata)
+            return -1;
+          
+         BSG_HANDLE* p2 = (BSG_HANDLE*) pdata;
+         BSG_UINT32 i;
+         for (i = 0; i < psize; i++) {
+           BSG_PackConst(s2[i], 4, (BSG_BYTE*)(p2 + i));
+         }
+       }
+       s += psize * sizeof(BSG_HANDLE);
+      } else { // If it's not psize handles, it's psize data.
+       if (dst) {
+         pdata = (BSG_BYTE *)malloc(sizeof(BSG_BYTE) * psize);
+          if (!pdata)
+            return -1;
+         memcpy(pdata, s, psize);
+       }
+       s += psize;
+      }
+    }
+    if (dst)
+      *(void**) d = pdata;
+
+    d += sizeof(void*);
+  } else if (format == __FMT_PACKED) {
+
+    // this doesn't make sense for unpacking!
+    vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack() called with format __FMT_PACKED. "
+                                                          "This does not make 
sense\n");
+    
+    return -1;
+  } else if (format == 0) {// No flags are set. This is a structure & it should
+                          // be looked up in the bsg_s_fmt[]
+
+    const BSG_Format* x = find_format (type);
+    if (x == NULL) {
+      vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack: cannot find type %d\n", type);
+      return -1;
+    }
+    
+    const BSG_UINT32* f = x->fields;
+    for (; *f; f++) {
+      int fsize = BSG_Unpack_private((BSG_Type) *f, s, dst ? &d:NULL);
+      if (fsize <= 0)
+       return fsize;
+      s += fsize;
+    }
+  }
+
+  if (dst)
+    *dst = d;
+  return (s - src);
+}
+
+/**
+ * Free memory associated with unpacked TCPA structure
+ * @type: TCPA structure type
+ * @src: (IN) TCPA structure (OUT) end of TCPA structure
+ * Note: Destroy should be called on all structures created with Unpack
+ *       to ensure that any allocated memory is freed
+ */
+static void BSG_Destroy_private(BSG_Type type, BSG_BYTE** src) {
+  BSG_BYTE* s = *src;
+  
+  BSG_UINT32 size = __FMT_MASK_SIZE(type);
+  BSG_UINT32 format = __FMT_MASK_FORMAT(type);
+  
+  if ((src == NULL) || (*src == NULL)) {
+        vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy() called with NULL src\n");
+    return;
+  }
+
+  if (format == __FMT_CONST || format == __FMT_DATA)
+    s += size;
+  else if (format == __FMT_SIZE || format == __FMT_HSIZE) {
+    s += size;
+    BSG_BYTE* ptr = *(BSG_BYTE**) s;
+    if (ptr)
+      free(ptr);
+    s += sizeof(void*);
+  } else if (format == __FMT_PACKED) {
+
+    // this doesn't make sense for unpacking, hence also for Destroy()
+    vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy() called with format __FMT_PACKED. 
"
+                                                          "This does not make 
sense\n");
+    
+    return;
+  } else if (format == 0) {
+    const BSG_Format* x = find_format (type);
+    if (x == NULL) {
+      vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy: cannot find type %d\n", type);
+      return;
+    }
+    
+    const BSG_UINT32* f = x->fields;
+    for (; *f; f++)
+      BSG_Destroy_private((BSG_Type) *f, &s);
+  }
+
+  *src = s;
+}
+
+int BSG_Pack(BSG_Type type, const void* src, BSG_BYTE* dst)
+{
+  const BSG_BYTE* src2 = (const BSG_BYTE*) src;
+  return BSG_Pack_private(type, &src2, dst);
+}
+
+int BSG_Unpack(BSG_Type type, const BSG_BYTE* src, void* dst)
+{
+  BSG_BYTE* dst2 = (BSG_BYTE*) dst;
+  return BSG_Unpack_private(type, src, dst ? &dst2:NULL);
+}
+
+void BSG_Destroy(BSG_Type type, void* src)
+{
+  BSG_BYTE* src2 = (BSG_BYTE*) src;
+  BSG_Destroy_private(type, &src2);
+}
+    
+/**
+ * Pack a 8/16/32-bit constant into a buffer in big-endian format
+ * @val: constant value
+ * @size: constant size in bytes (1, 2, or 4)
+ * @dst: (OUT) buffer
+ */
+void BSG_PackConst(BSG_UINT32 val, int size, BSG_BYTE* dst) {
+  bsglog ("BSG: PackConst on %d of size %i into address %p\n", val, size, dst);
+  
+  switch (size) {
+  case 4:
+    dst[0] = (BSG_BYTE)((val >> 24) & 0xff);
+    dst[1] = (BSG_BYTE)((val >> 16) & 0xff);
+    dst[2] = (BSG_BYTE)((val >> 8) & 0xff);
+    dst[3] = (BSG_BYTE)(val & 0xff);
+    break;
+  case 2:
+    dst[0] = (BSG_BYTE)((val >> 8) & 0xff);
+    dst[1] = (BSG_BYTE)(val & 0xff);
+    break;
+  case 1:
+    dst[0] = (BSG_BYTE)(val & 0xff);
+    break;
+  }
+}
+
+/**
+ * Unpack a 8/16/32-bit constant from a buffer in big-endian format
+ * @src: buffer
+ * @size: constant size in bytes (1, 2, or 4)
+ */
+BSG_UINT32 BSG_UnpackConst(const BSG_BYTE* src, int size) {
+  BSG_UINT32 val = 0;
+  
+  if (src == NULL) 
+    return 0;
+  
+  switch (size) {
+  case 4:
+    val = (((BSG_UINT32) src[0]) << 24
+          | ((BSG_UINT32) src[1]) << 16
+          | ((BSG_UINT32) src[2]) << 8
+          | (BSG_UINT32) src[3]);
+    break;
+  case 2:
+    val = (((BSG_UINT32) src[0]) << 8 | (BSG_UINT32) src[1]);
+    break;
+  case 1:
+    val = (BSG_UINT32) src[0];
+    break;
+  }  
+  return val;
+}
+
+// Pack a list of parameters. Beware not to send values, but rather you must
+// send a pointer to your values Instead. This includes UINT32's.
+int BSG_PackList( BSG_BYTE* dst, int ParamCount, ... ) {
+  int ParamNumber;
+  BSG_Type format; 
+  BSG_BYTE* val = NULL;
+  int size=0;
+  
+  va_list paramList;
+  va_start( paramList, ParamCount );
+
+  for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
+    //Strangeness with int is because gcc wanted an int rather than a enum of 
ints.
+    format =  (BSG_Type) va_arg( paramList, int );
+    val = va_arg( paramList, BSG_BYTE* );    
+    size += BSG_Pack(format, val, dst == NULL ? NULL : dst + size);
+  }
+  
+  va_end (paramList);
+  
+  return size;
+}
+
+// Unpack a list of parameters. 
+int BSG_UnpackList( const BSG_BYTE* src, int ParamCount, ... ) {
+  int ParamNumber = 0;
+  BSG_Type format; 
+  BSG_BYTE* val = NULL;
+  int size = 0;
+  
+  va_list paramList;
+  va_start( paramList, ParamCount );
+  
+  for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
+    format = (BSG_Type) va_arg( paramList, int );
+    val  = va_arg( paramList, BSG_BYTE* );
+    
+    size += BSG_Unpack(format, src + size, val);
+  }
+  
+  va_end( paramList );   
+  
+  return size;
+}
+
+// Destroy any memory allocated by calls to unpack 
+void BSG_DestroyList(int ParamCount, ... ) {
+  int ParamNumber = 0;
+  BSG_Type argType; 
+  BSG_BYTE* paramValue = NULL;
+  
+  va_list paramList;
+  va_start( paramList, ParamCount );
+  
+  for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
+    argType = (BSG_Type) va_arg( paramList, int );
+    paramValue  = va_arg( paramList, BSG_BYTE* );
+    
+    BSG_Destroy(argType, paramValue);
+  }
+  
+  va_end( paramList );   
+  
+  return;
+}
+
+
+// and a tuple version
+TPM_RESULT BSG_DestroyTuple (int numParams, pack_tuple_t params[]) {
+  int i;
+  
+  for (i = 0; i < numParams; i++)
+    BSG_Destroy (params[i].type, params[i].addr);
+
+  return TPM_SUCCESS;
+}
+
+
+//
+// wrappers of Pack and PackList which malloc the ouput buffer. to be freed
+// by the caller later
+//
+
+int BSG_PackMalloc (BSG_Type type, const void* src, BSG_BYTE** o_dst) {
+  int size = BSG_Pack (type, src, NULL);
+  BSG_BYTE * dest = (BSG_BYTE*) malloc (size);
+  if (dest == NULL)
+    return -1;
+
+  size = BSG_Pack(type, src, dest);
+  *o_dst = dest;
+  return size;
+}
+
+
+
+int BSG_PackListMalloc(BSG_BYTE** outBuffer, int ParamCount, ... ) {
+  va_list args;
+  int size;
+  
+  va_start (args, ParamCount);
+  size = BSG_PackList (NULL, ParamCount, args);
+  va_end (args);
+  
+  BSG_BYTE * dest = (BSG_BYTE*) malloc (size);
+  if (dest == NULL)
+    return -1;
+
+  va_start (args, ParamCount);
+  size = BSG_PackList (dest, ParamCount, args);
+  va_end (args);
+  
+  *outBuffer = dest;
+  return size;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/bsg.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/util/bsg.h     Fri Sep  9 16:30:54 2005
@@ -0,0 +1,166 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// bsg.h
+// 
+//  This file contains API's for the TPM Byte Stream functions
+//
+// ==================================================================
+
+#ifndef __BSG_H__
+#define __BSG_H__
+
+#include <stdarg.h>
+#include "buffer.h"
+
+typedef unsigned int BSG_UINT32;
+typedef unsigned char BSG_BYTE;
+
+// forward decl
+struct pack_const_tuple_t;
+
+struct pack_tuple_t;
+
+
+/**
+ * Byte stream generator
+ */
+// this has to be manually kept in sync with the
+// s_fmt array!!
+// but now we have a self-check function which can make sure things are well
+// (if used!) 
+typedef enum BSG_Type
+{ 
+  BSG_TYPE_FIRST = 1,
+  BSG_TYPE_UINT32 = 1, // start at 1 so that Type 0 only serves as an
+                       // unused/special value
+  BSG_TYPE_UINT16,
+  BSG_TYPE_BYTE,
+  BSG_TYPE_BOOL,
+  BSG_TPM_SIZE32_DATA,  // a 32 bit unsigned size, followed by
+                        // a pointer to that much data. can pass a
+                        // struct pack_buf_t as the param
+  BSG_TPM_TAG,
+  BSG_TPM_HANDLE,
+  BSG_TPM_RESULT,
+  BSG_TPM_RESOURCE_TYPE,
+  BSG_TPM_COMMAND_CODE,
+  BSG_TPM_AUTH_DATA_USAGE,
+  BSG_TPM_ALGORITHM_ID,
+  BSG_TPM_PROTOCOL_ID,
+  BSG_TPM_KEY_USAGE,
+  BSG_TPM_ENC_SCHEME,
+  BSG_TPM_SIG_SCHEME,
+  BSG_TPM_MIGRATE_SCHEME,
+  BSG_TPM_KEY_FLAGS,
+  BSG_TPM_AUTHDATA,
+  BSG_TPM_SECRET,
+  BSG_TPM_ENCAUTH,
+  BSG_TPM_PAYLOAD_TYPE,
+  
+  BSG_TPM_VERSION,
+  BSG_TPM_DIGEST,
+  BSG_TPM_COMPOSITE_HASH,
+  BSG_TPM_CHOSENID_HASH,
+  BSG_TPM_NONCE,
+  BSG_TPM_KEY_HANDLE,
+  BSG_TPM_KEY_HANDLE_LIST,
+  BSG_TPM_KEY_PARMS,
+  BSG_TPM_RSA_KEY_PARMS,
+  BSG_TPM_STORE_PUBKEY,
+  BSG_TPM_PUBKEY,
+  BSG_TPM_KEY,
+  
+  BSG_TPM_MIGRATIONKEYAUTH,
+  BSG_TCPA_AUDIT_EVENT,
+  BSG_TCPA_EVENT_CERT,
+  BSG_TPM_PCR_SELECTION,
+  BSG_TPM_PCR_COMPOSITE,
+  BSG_TPM_PCR_INFO,
+  BSG_TPM_STORED_DATA,
+  BSG_TPM_SYMMETRIC_KEY,
+  BSG_TPM_STORE_PRIVKEY,
+  BSG_TPM_STORE_ASYMKEY,
+  BSG_TPM_MIGRATE_ASYMKEY,
+  BSG_TPM_QUOTE_INFO,
+  BSG_TPM_IDENTITY_CONTENTS,
+  BSG_TPM_PCRVALUE,
+  BSG_TCPA_PCR_FLAGS,
+  BSG_TCS_AUTH,
+  
+  // this is the BSG_TPM_KEY struct without the encData field
+  BSG_TPM_KEY_NONSENSITIVE,
+  
+  BSG_PACKED,
+  
+  BSG_TYPE_MAX
+} BSG_Type;
+
+struct pack_const_tuple_t {
+  BSG_Type type;
+  const void * addr;
+};
+
+
+typedef struct pack_tuple_t {
+  BSG_Type type;
+  void * addr;
+} pack_tuple_t;
+
+int BSG_Pack(BSG_Type type, const void* src, BSG_BYTE* dst);
+int BSG_Unpack(BSG_Type type, const BSG_BYTE* src, void* dst);
+void BSG_Destroy(BSG_Type type, void* src);
+
+// wrappers of Pack and PackList which malloc the ouput buffer. to be freed
+// by the caller later. returns size of allocated buffer, or -1 in case
+// allocation failed
+int BSG_PackMalloc (BSG_Type type, const void* src, BSG_BYTE** o_dst);
+int BSG_PackListMalloc (BSG_BYTE** outBuffer, int ParamCount, ... );
+
+// a va_list version of PackList
+int BSG_PackList(BSG_BYTE* outBuffer, int ParamCount, ... );
+int BSG_UnpackList(const BSG_BYTE* inBuffer, int ParamCount, ... );
+void BSG_DestroyList(int ParamCount, ... );
+
+// wrapper of PackList which uses a buffer_t
+TPM_RESULT BSG_PackListBuf (buffer_t * o_buf, int ParamCount, ...);
+
+// and a tuple version
+TPM_RESULT BSG_DestroyTuple (int numParams, pack_tuple_t params[]);
+
+void BSG_PackConst(BSG_UINT32 val, int size, BSG_BYTE* dst);
+BSG_UINT32 BSG_UnpackConst(const BSG_BYTE* src, int size);
+
+BOOL BSG_static_selfcheck ();
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/buffer.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/util/buffer.c  Fri Sep  9 16:30:54 2005
@@ -0,0 +1,213 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/param.h>
+
+#include "tcg.h"
+#include "bsg.h"
+#include "buffer.h"
+
+static TPM_RESULT buffer_priv_realloc (buffer_t * buf, tpm_size_t newsize);
+
+//
+// buffer functions!
+//
+
+TPM_RESULT buffer_init (buffer_t * buf, tpm_size_t initsize, const BYTE* 
initval) {
+  if (initsize == 0) {
+    memset(buf, 0, sizeof(*buf));
+    return TPM_SUCCESS;
+  }
+  
+  
+  buf->bytes = (BYTE*) malloc (initsize);
+  if (buf->bytes == NULL) 
+    return TPM_RESOURCES;
+  
+  buf->size = initsize;
+  buf->alloc_size = initsize;
+  
+  if (initval)
+    memcpy (buf->bytes, initval, initsize);
+  
+  buf->is_owner = TRUE;
+  
+  return TPM_SUCCESS;
+}
+
+TPM_RESULT buffer_init_convert (buffer_t * buf, tpm_size_t initsize, BYTE* 
initval) {
+  
+  buf->size = initsize;
+  buf->alloc_size = initsize;
+  buf->bytes = initval;
+  
+  buf->is_owner = TRUE;
+  
+  return TPM_SUCCESS;
+}
+
+TPM_RESULT buffer_init_copy (buffer_t * buf, const buffer_t * src) {
+  TPM_RESULT status = buffer_init (buf, src->size, src->bytes);
+  buf->is_owner = TRUE;
+  
+  return status;
+}
+
+
+
+// make an alias to a constant array
+TPM_RESULT buffer_init_const (buffer_t * buf, tpm_size_t size, const BYTE* 
val) {
+  // TODO: try to enforce the const things somehow!
+  buf->bytes = (BYTE*) val;
+  buf->size = size;
+  buf->alloc_size = 0;        // this field is now unneeded
+  
+  buf->is_owner = FALSE;
+  
+  return TPM_SUCCESS;
+}
+
+// make an alias into buf, with given offset and length
+// if len = 0, make the alias go to the end of buf
+TPM_RESULT buffer_init_alias (buffer_t * buf, const buffer_t * b,
+                              tpm_size_t offset, tpm_size_t len) {
+  if (offset + len > b->size) {
+    return TPM_NOSPACE;
+  }
+  
+  buf->bytes = b->bytes + offset;
+  buf->size = len > 0 ? len : b->size - offset;
+  
+  //VS/ buf->alloc_size = 0;
+  if (len ==0)
+    buf->alloc_size = b->alloc_size - offset;
+  else 
+    buf->alloc_size = MIN(b->alloc_size - offset, len);
+  
+        
+  buf->is_owner = FALSE;
+  
+  return TPM_SUCCESS;
+}
+    
+
+// copy into the start of dest
+TPM_RESULT buffer_copy (buffer_t * dest, const buffer_t* src)
+{
+  TPM_RESULT status = TPM_SUCCESS;
+    
+  if (dest->alloc_size < src->size) {  
+    status = buffer_priv_realloc (dest, src->size);
+    STATUSCHECK (status);
+  }
+  
+  memcpy (dest->bytes, src->bytes, src->size);
+  dest->size = src->size;
+  
+  //VS/ dest->is_owner = TRUE;
+  
+ abort_egress:
+
+  return status;
+}
+
+
+
+BOOL buffer_eq (const buffer_t * a, const buffer_t * b) {
+  return (a->size == b->size && memcmp (a->bytes, b->bytes, a->size) == 0);
+}
+
+
+void buffer_memset (buffer_t * buf, BYTE b) {
+  memset (buf->bytes, b, buf->size);
+}
+
+
+TPM_RESULT buffer_append_raw (buffer_t * buf, tpm_size_t len, const BYTE* 
bytes) {
+  TPM_RESULT status = TPM_SUCCESS;
+  
+  if (buf->alloc_size < buf->size + len) {
+    status = buffer_priv_realloc (buf, buf->size + len);
+    STATUSCHECK (status);
+  }
+  
+  memcpy (buf->bytes + buf->size, bytes, len);
+  
+  buf->size += len;
+  
+  goto egress;
+  
+ abort_egress:
+  
+ egress:
+  
+  return status;
+}
+
+tpm_size_t buffer_len (const buffer_t* buf) {
+  return buf->size;
+}
+
+TPM_RESULT buffer_free (buffer_t * buf) {
+  if (buf && buf->is_owner && buf->bytes != NULL) {
+    free (buf->bytes);
+    buf->bytes = NULL;
+  }
+  
+  return TPM_SUCCESS;
+}
+
+TPM_RESULT buffer_priv_realloc (buffer_t * buf, tpm_size_t newsize) {
+  
+  // we want to realloc to twice the size, or the new size, whichever
+  // bigger
+  
+  BYTE * tmpbuf = NULL;
+  
+  newsize = MAX (buf->alloc_size * 2, newsize);
+  
+  tmpbuf = (BYTE*) realloc (buf->bytes, newsize);
+  if (tmpbuf == NULL) 
+    return TPM_SIZE;
+  
+  
+  buf->bytes = tmpbuf;
+  buf->alloc_size = newsize;
+  
+  return TPM_SUCCESS;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/buffer.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/util/buffer.h  Fri Sep  9 16:30:54 2005
@@ -0,0 +1,103 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+#ifndef __VTPM_BUFFER_H__
+#define __VTPM_BUFFER_H__
+
+#include <stddef.h>             // for pointer NULL
+#include "tcg.h"
+
+// structure to enable use of FMT_SIZE32_DATA in BSG_Unpack
+typedef struct pack_buf_t {
+  UINT32 size;
+  BYTE * data;
+} pack_buf_t;
+
+// and a const version for Pack
+typedef struct pack_constbuf_t {
+  UINT32 size;
+  const BYTE* data;
+} pack_constbuf_t;
+
+typedef UINT32 tpm_size_t;
+
+// first version, probably will be expanded...
+
+#define NULL_BUF {0,0,0,0}
+
+typedef struct {
+  // private!!
+  tpm_size_t size, alloc_size;
+  BYTE * bytes;
+  
+  BOOL is_owner;              // do we own this buffer, and need to free it?
+} buffer_t;
+
+// allocate the buffer if initsize > 0, copying over initval if provided
+TPM_RESULT buffer_init (buffer_t * buf,
+                        tpm_size_t initsize,
+                        const BYTE* initval);
+
+// Create a new buffer from a BYTE *. Use buffer_free to destroy original BYTE 
*
+TPM_RESULT buffer_init_convert (buffer_t * buf, 
+                                tpm_size_t initsize, 
+                                BYTE* initval);
+
+// make an alias to a constant array, no copying
+TPM_RESULT buffer_init_const (buffer_t * buf, tpm_size_t size, const BYTE* 
val);
+
+// make an alias into buf, with given offset and length
+// if len = 0, make the alias go to the end of buf
+TPM_RESULT buffer_init_alias (buffer_t * buf, const buffer_t * b,
+                              tpm_size_t offset, tpm_size_t);
+
+// "copy constructor"
+TPM_RESULT buffer_init_copy (buffer_t * buf, const buffer_t * src);
+
+
+// copy into the start of a
+TPM_RESULT buffer_copy (buffer_t * dest, const buffer_t* src);
+
+// are they equal?
+BOOL buffer_eq (const buffer_t * a, const buffer_t * b);
+
+// set the buffer to a constant byte
+void buffer_memset (buffer_t * buf, BYTE b);
+
+tpm_size_t buffer_len (const buffer_t* buf);
+
+TPM_RESULT buffer_free (buffer_t * buf);
+
+TPM_RESULT buffer_append_raw (buffer_t * buf, tpm_size_t len, const BYTE* 
bytes);
+
+#endif // _TOOLS_H_
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/depend
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/util/depend    Fri Sep  9 16:30:54 2005
@@ -0,0 +1,7 @@
+hashtable.o: hashtable.c hashtable.h hashtable_private.h
+hashtable_itr.o: hashtable_itr.c hashtable.h hashtable_private.h \
+  hashtable_itr.h
+bsg.o: bsg.c tcg.h ../crypto/crypto.h ../crypto/sym_crypto.h buffer.h \
+  bsg.h log.h
+log.o: log.c buffer.h tcg.h
+buffer.o: buffer.c tcg.h bsg.h buffer.h
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/hashtable.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/util/hashtable.c       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx> 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "hashtable.h"
+#include "hashtable_private.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+/*
+Credit for primes table: Aaron Krowne
+ http://br.endernet.org/~akrowne/
+ http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
+*/
+static const unsigned int primes[] = {
+53, 97, 193, 389,
+769, 1543, 3079, 6151,
+12289, 24593, 49157, 98317,
+196613, 393241, 786433, 1572869,
+3145739, 6291469, 12582917, 25165843,
+50331653, 100663319, 201326611, 402653189,
+805306457, 1610612741
+};
+const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
+const float max_load_factor = 0.65;
+
+/*****************************************************************************/
+struct hashtable *
+create_hashtable(unsigned int minsize,
+                 unsigned int (*hashf) (void*),
+                 int (*eqf) (void*,void*))
+{
+    struct hashtable *h;
+    unsigned int pindex, size = primes[0];
+    /* Check requested hashtable isn't too large */
+    if (minsize > (1u << 30)) return NULL;
+    /* Enforce size as prime */
+    for (pindex=0; pindex < prime_table_length; pindex++) {
+        if (primes[pindex] > minsize) { size = primes[pindex]; break; }
+    }
+    h = (struct hashtable *)malloc(sizeof(struct hashtable));
+    if (NULL == h) return NULL; /*oom*/
+    h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
+    if (NULL == h->table) { free(h); return NULL; } /*oom*/
+    memset(h->table, 0, size * sizeof(struct entry *));
+    h->tablelength  = size;
+    h->primeindex   = pindex;
+    h->entrycount   = 0;
+    h->hashfn       = hashf;
+    h->eqfn         = eqf;
+    h->loadlimit    = (unsigned int) ceil(size * max_load_factor);
+#ifdef HASHTABLE_THREADED    
+    pthread_mutex_init(&h->mutex, NULL);
+#endif
+    return h;
+}
+
+/*****************************************************************************/
+unsigned int
+hash(struct hashtable *h, void *k)
+{
+    unsigned int i = h->hashfn(k);
+    i += ~(i << 9);
+    i ^=  ((i >> 14) | (i << 18)); /* >>> */
+    i +=  (i << 4);
+    i ^=  ((i >> 10) | (i << 22)); /* >>> */
+    return i;
+}
+
+/*****************************************************************************/
+static int
+hashtable_expand(struct hashtable *h)
+{
+    /* Double the size of the table to accomodate more entries */
+    struct entry **newtable;
+    struct entry *e;
+    struct entry **pE;
+    unsigned int newsize, i, index;
+    /* Check we're not hitting max capacity */
+    if (h->primeindex == (prime_table_length - 1)) return 0;
+    newsize = primes[++(h->primeindex)];
+
+    newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
+    if (NULL != newtable)
+    {
+        memset(newtable, 0, newsize * sizeof(struct entry *));
+        /* This algorithm is not 'stable'. ie. it reverses the list
+         * when it transfers entries between the tables */
+        for (i = 0; i < h->tablelength; i++) {
+            while (NULL != (e = h->table[i])) {
+                h->table[i] = e->next;
+                index = indexFor(newsize,e->h);
+                e->next = newtable[index];
+                newtable[index] = e;
+            }
+        }
+        free(h->table);
+        h->table = newtable;
+    }
+    /* Plan B: realloc instead */
+    else 
+    {
+        newtable = (struct entry **)
+                   realloc(h->table, newsize * sizeof(struct entry *));
+        if (NULL == newtable) { (h->primeindex)--; return 0; }
+        h->table = newtable;
+        memset(newtable[h->tablelength], 0, newsize - h->tablelength);
+        for (i = 0; i < h->tablelength; i++) {
+            for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
+                index = indexFor(newsize,e->h);
+                if (index == i)
+                {
+                    pE = &(e->next);
+                }
+                else
+                {
+                    *pE = e->next;
+                    e->next = newtable[index];
+                    newtable[index] = e;
+                }
+            }
+        }
+    }
+    h->tablelength = newsize;
+    h->loadlimit   = (unsigned int) ceil(newsize * max_load_factor);
+    return -1;
+}
+
+/*****************************************************************************/
+unsigned int
+hashtable_count(struct hashtable *h)
+{
+    unsigned int count;
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_lock(&h->mutex);
+#endif    
+    count = h->entrycount;
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_unlock(&h->mutex);
+#endif
+    return count;
+}
+
+/*****************************************************************************/
+int
+hashtable_insert(struct hashtable *h, void *k, void *v)
+{
+    /* This method allows duplicate keys - but they shouldn't be used */
+    unsigned int index;
+    struct entry *e;
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_lock(&h->mutex);
+#endif   
+    if (++(h->entrycount) > h->loadlimit)
+    {
+        /* Ignore the return value. If expand fails, we should
+         * still try cramming just this value into the existing table
+         * -- we may not have memory for a larger table, but one more
+         * element may be ok. Next time we insert, we'll try expanding again.*/
+        hashtable_expand(h);
+    }
+    e = (struct entry *)malloc(sizeof(struct entry));
+    if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
+    e->h = hash(h,k);
+    index = indexFor(h->tablelength,e->h);
+    e->k = k;
+    e->v = v;
+    e->next = h->table[index];
+    h->table[index] = e;
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_unlock(&h->mutex);
+#endif   
+    return -1;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_search(struct hashtable *h, void *k)
+{
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_lock(&h->mutex);
+#endif   
+    struct entry *e;
+    unsigned int hashvalue, index;
+    hashvalue = hash(h,k);
+    index = indexFor(h->tablelength,hashvalue);
+    e = h->table[index];
+    while (NULL != e)
+    {
+        /* Check hash value to short circuit heavier comparison */
+        if ((hashvalue == e->h) && (h->eqfn(k, e->k))) {
+#ifdef HASHTABLE_THREADED
+          pthread_mutex_unlock(&h->mutex);
+#endif   
+          return e->v;
+        }
+        e = e->next;
+    }
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_unlock(&h->mutex);
+#endif   
+    return NULL;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_remove(struct hashtable *h, void *k)
+{
+    /* TODO: consider compacting the table when the load factor drops enough,
+     *       or provide a 'compact' method. */
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_lock(&h->mutex);
+#endif   
+    struct entry *e;
+    struct entry **pE;
+    void *v;
+    unsigned int hashvalue, index;
+
+    hashvalue = hash(h,k);
+    index = indexFor(h->tablelength,hash(h,k));
+    pE = &(h->table[index]);
+    e = *pE;
+    while (NULL != e)
+    {
+        /* Check hash value to short circuit heavier comparison */
+        if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+        {
+            *pE = e->next;
+            h->entrycount--;
+            v = e->v;
+            freekey(e->k);
+            free(e);
+            return v;
+        }
+        pE = &(e->next);
+        e = e->next;
+    }
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_unlock(&h->mutex);
+#endif   
+    return NULL;
+}
+
+/*****************************************************************************/
+/* destroy */
+void
+hashtable_destroy(struct hashtable *h, int free_values)
+{
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_lock(&h->mutex);
+#endif   
+    unsigned int i;
+    struct entry *e, *f;
+    struct entry **table = h->table;
+    if (free_values)
+    {
+        for (i = 0; i < h->tablelength; i++)
+        {
+            e = table[i];
+            while (NULL != e)
+            { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
+        }
+    }
+    else
+    {
+        for (i = 0; i < h->tablelength; i++)
+        {
+            e = table[i];
+            while (NULL != e)
+            { f = e; e = e->next; freekey(f->k); free(f); }
+        }
+    }
+    free(h->table);
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_destroy(&h->mutex);
+#endif   
+    free(h);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/hashtable.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/util/hashtable.h       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx> 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef __HASHTABLE_CWC22_H__
+#define __HASHTABLE_CWC22_H__
+
+struct hashtable;
+
+/* Example of use:
+ *
+ *      struct hashtable  *h;
+ *      struct some_key   *k;
+ *      struct some_value *v;
+ *
+ *      static unsigned int         hash_from_key_fn( void *k );
+ *      static int                  keys_equal_fn ( void *key1, void *key2 );
+ *
+ *      h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
+ *      k = (struct some_key *)     malloc(sizeof(struct some_key));
+ *      v = (struct some_value *)   malloc(sizeof(struct some_value));
+ *
+ *      (initialise k and v to suitable values)
+ * 
+ *      if (! hashtable_insert(h,k,v) )
+ *      {     exit(-1);               }
+ *
+ *      if (NULL == (found = hashtable_search(h,k) ))
+ *      {    printf("not found!");                  }
+ *
+ *      if (NULL == (found = hashtable_remove(h,k) ))
+ *      {    printf("Not found\n");                 }
+ *
+ */
+
+/* Macros may be used to define type-safe(r) hashtable access functions, with
+ * methods specialized to take known key and value types as parameters.
+ * 
+ * Example:
+ *
+ * Insert this at the start of your file:
+ *
+ * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
+ *
+ * This defines the functions 'insert_some', 'search_some' and 'remove_some'.
+ * These operate just like hashtable_insert etc., with the same parameters,
+ * but their function signatures have 'struct some_key *' rather than
+ * 'void *', and hence can generate compile time errors if your program is
+ * supplying incorrect data as a key (and similarly for value).
+ *
+ * Note that the hash and key equality functions passed to create_hashtable
+ * still take 'void *' parameters instead of 'some key *'. This shouldn't be
+ * a difficult issue as they're only defined and passed once, and the other
+ * functions will ensure that only valid keys are supplied to them.
+ *
+ * The cost for this checking is increased code size and runtime overhead
+ * - if performance is important, it may be worth switching back to the
+ * unsafe methods once your program has been debugged with the safe methods.
+ * This just requires switching to some simple alternative defines - eg:
+ * #define insert_some hashtable_insert
+ *
+ */
+
+/*****************************************************************************
+ * create_hashtable
+   
+ * @name                    create_hashtable
+ * @param   minsize         minimum initial size of hashtable
+ * @param   hashfunction    function for hashing keys
+ * @param   key_eq_fn       function for determining key equality
+ * @return                  newly created hashtable or NULL on failure
+ */
+
+struct hashtable *
+create_hashtable(unsigned int minsize,
+                 unsigned int (*hashfunction) (void*),
+                 int (*key_eq_fn) (void*,void*));
+
+/*****************************************************************************
+ * hashtable_insert
+   
+ * @name        hashtable_insert
+ * @param   h   the hashtable to insert into
+ * @param   k   the key - hashtable claims ownership and will free on removal
+ * @param   v   the value - does not claim ownership
+ * @return      non-zero for successful insertion
+ *
+ * This function will cause the table to expand if the insertion would take
+ * the ratio of entries to table size over the maximum load factor.
+ *
+ * This function does not check for repeated insertions with a duplicate key.
+ * The value returned when using a duplicate key is undefined -- when
+ * the hashtable changes size, the order of retrieval of duplicate key
+ * entries is reversed.
+ * If in doubt, remove before insert.
+ */
+
+int 
+hashtable_insert(struct hashtable *h, void *k, void *v);
+
+#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
+int fnname (struct hashtable *h, keytype *k, valuetype *v) \
+{ \
+    return hashtable_insert(h,k,v); \
+}
+
+/*****************************************************************************
+ * hashtable_search
+   
+ * @name        hashtable_search
+ * @param   h   the hashtable to search
+ * @param   k   the key to search for  - does not claim ownership
+ * @return      the value associated with the key, or NULL if none found
+ */
+
+void *
+hashtable_search(struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
+valuetype * fnname (struct hashtable *h, keytype *k) \
+{ \
+    return (valuetype *) (hashtable_search(h,k)); \
+}
+
+/*****************************************************************************
+ * hashtable_remove
+   
+ * @name        hashtable_remove
+ * @param   h   the hashtable to remove the item from
+ * @param   k   the key to search for  - does not claim ownership
+ * @return      the value associated with the key, or NULL if none found
+ */
+
+void * /* returns value */
+hashtable_remove(struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
+valuetype * fnname (struct hashtable *h, keytype *k) \
+{ \
+    return (valuetype *) (hashtable_remove(h,k)); \
+}
+
+
+/*****************************************************************************
+ * hashtable_count
+   
+ * @name        hashtable_count
+ * @param   h   the hashtable
+ * @return      the number of items stored in the hashtable
+ */
+unsigned int
+hashtable_count(struct hashtable *h);
+
+
+/*****************************************************************************
+ * hashtable_destroy
+   
+ * @name        hashtable_destroy
+ * @param   h   the hashtable
+ * @param       free_values     whether to call 'free' on the remaining values
+ */
+
+void
+hashtable_destroy(struct hashtable *h, int free_values);
+
+#endif /* __HASHTABLE_CWC22_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/hashtable_itr.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/util/hashtable_itr.c   Fri Sep  9 16:30:54 2005
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx> 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "hashtable.h"
+#include "hashtable_private.h"
+#include "hashtable_itr.h"
+#include <stdlib.h> /* defines NULL */
+
+/*****************************************************************************/
+/* hashtable_iterator    - iterator constructor */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h)
+{
+    unsigned int i, tablelength;
+    struct hashtable_itr *itr = (struct hashtable_itr *)
+        malloc(sizeof(struct hashtable_itr));
+    if (NULL == itr) return NULL;
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_lock(&h->mutex);
+#endif   
+    itr->h = h;
+    itr->e = NULL;
+    itr->parent = NULL;
+    tablelength = h->tablelength;
+    itr->index = tablelength;
+    if (0 == h->entrycount) {
+#ifdef HASHTABLE_THREADED
+      pthread_mutex_unlock(&h->mutex);
+#endif   
+      return itr;
+    }
+
+    for (i = 0; i < tablelength; i++)
+    {
+        if (NULL != h->table[i])
+        {
+            itr->e = h->table[i];
+            itr->index = i;
+            break;
+        }
+    }
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_unlock(&h->mutex);
+#endif   
+    return itr;
+}
+
+/*****************************************************************************/
+/* key      - return the key of the (key,value) pair at the current position */
+/* value    - return the value of the (key,value) pair at the current position 
*/
+
+void *
+hashtable_iterator_key(struct hashtable_itr *i)
+{ return i->e->k; }
+
+void *
+hashtable_iterator_value(struct hashtable_itr *i)
+{ return i->e->v; }
+
+/*****************************************************************************/
+/* advance - advance the iterator to the next element
+ *           returns zero if advanced to end of table */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr)
+{
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_lock(&itr->h->mutex);
+#endif   
+    unsigned int j,tablelength;
+    struct entry **table;
+    struct entry *next;
+    int ret;
+    if (NULL == itr->e) { /* stupidity check */
+      ret = 0; 
+      goto egress;
+    }
+
+    next = itr->e->next;
+    if (NULL != next)
+    {
+        itr->parent = itr->e;
+        itr->e = next;
+        ret = -1;
+        goto egress;
+    }
+
+    tablelength = itr->h->tablelength;
+    itr->parent = NULL;
+    if (tablelength <= (j = ++(itr->index)))
+    {
+        itr->e = NULL;
+        ret = 0;
+        goto egress;
+    }
+    table = itr->h->table;
+    while (NULL == (next = table[j]))
+    {
+        if (++j >= tablelength)
+        {
+            itr->index = tablelength;
+            itr->e = NULL;
+            ret = 0;
+            goto egress;
+        }
+    }
+    itr->index = j;
+    itr->e = next;
+    ret = -1;
+
+ egress:
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_unlock(&itr->h->mutex);
+#endif   
+    return ret;
+}
+
+/*****************************************************************************/
+/* remove - remove the entry at the current iterator position
+ *          and advance the iterator, if there is a successive
+ *          element.
+ *          If you want the value, read it before you remove:
+ *          beware memory leaks if you don't.
+ *          Returns zero if end of iteration. */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr)
+{
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_lock(&itr->h->mutex);
+#endif 
+    struct entry *remember_e, *remember_parent;
+    int ret;
+
+    /* Do the removal */
+    if (NULL == (itr->parent))
+    {
+        /* element is head of a chain */
+        itr->h->table[itr->index] = itr->e->next;
+    } else {
+        /* element is mid-chain */
+        itr->parent->next = itr->e->next;
+    }
+    /* itr->e is now outside the hashtable */
+    remember_e = itr->e;
+    itr->h->entrycount--;
+    freekey(remember_e->k);
+
+    /* Advance the iterator, correcting the parent */
+    remember_parent = itr->parent;
+    ret = hashtable_iterator_advance(itr);
+    if (itr->parent == remember_e) { itr->parent = remember_parent; }
+    free(remember_e);
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_unlock(&itr->h->mutex);
+#endif 
+    return ret;
+}
+
+/*****************************************************************************/
+int /* returns zero if not found */
+hashtable_iterator_search(struct hashtable_itr *itr,
+                          struct hashtable *h, void *k)
+{
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_lock(&h->mutex);
+#endif 
+    struct entry *e, *parent;
+    unsigned int hashvalue, index;
+    int ret;
+    
+    hashvalue = hash(h,k);
+    index = indexFor(h->tablelength,hashvalue);
+
+    e = h->table[index];
+    parent = NULL;
+    while (NULL != e)
+    {
+        /* Check hash value to short circuit heavier comparison */
+        if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+        {
+            itr->index = index;
+            itr->e = e;
+            itr->parent = parent;
+            itr->h = h;
+            ret= -1;
+            goto egress;
+        }
+        parent = e;
+        e = e->next;
+    }
+  ret = 0;
+    
+egress:
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_lock(&h->mutex);
+#endif 
+    return ret;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/hashtable_itr.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/util/hashtable_itr.h   Fri Sep  9 16:30:54 2005
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx> 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef __HASHTABLE_ITR_CWC22__
+#define __HASHTABLE_ITR_CWC22__
+#include "hashtable.h"
+#include "hashtable_private.h" /* needed to enable inlining */
+
+/*****************************************************************************/
+/* This struct is only concrete here to allow the inlining of two of the
+ * accessor functions. */
+struct hashtable_itr
+{
+    struct hashtable *h;
+    struct entry *e;
+    struct entry *parent;
+    unsigned int index;
+};
+
+
+/*****************************************************************************/
+/* hashtable_iterator
+ */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h);
+
+/*****************************************************************************/
+/* hashtable_iterator_key
+ * - return the value of the (key,value) pair at the current position */
+
+void *hashtable_iterator_key(struct hashtable_itr *i);
+
+/*****************************************************************************/
+/* value - return the value of the (key,value) pair at the current position */
+
+void *hashtable_iterator_value(struct hashtable_itr *i);
+
+/*****************************************************************************/
+/* advance - advance the iterator to the next element
+ *           returns zero if advanced to end of table */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* remove - remove current element and advance the iterator to the next element
+ *          NB: if you need the value to free it, read it before
+ *          removing. ie: beware memory leaks!
+ *          returns zero if advanced to end of table */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* search - overwrite the supplied iterator, to point to the entry
+ *          matching the supplied key.
+            h points to the hashtable to be searched.
+ *          returns zero if not found. */
+int
+hashtable_iterator_search(struct hashtable_itr *itr,
+                          struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \
+int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \
+{ \
+    return (hashtable_iterator_search(i,h,k)); \
+}
+
+
+
+#endif /* __HASHTABLE_ITR_CWC22__*/
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/hashtable_private.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/util/hashtable_private.h       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx> 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HASHTABLE_PRIVATE_CWC22_H__
+#define __HASHTABLE_PRIVATE_CWC22_H__
+
+#include "hashtable.h"
+#ifdef HASHTABLE_THREADED
+#include <pthread.h>
+#endif
+
+/*****************************************************************************/
+struct entry
+{
+    void *k, *v;
+    unsigned int h;
+    struct entry *next;
+};
+
+struct hashtable {
+    unsigned int tablelength;
+    struct entry **table;
+    unsigned int entrycount;
+    unsigned int loadlimit;
+    unsigned int primeindex;
+    unsigned int (*hashfn) (void *k);
+    int (*eqfn) (void *k1, void *k2);
+#ifdef HASHTABLE_THREADED
+    pthread_mutex_t mutex;
+#endif
+};
+
+/*****************************************************************************/
+unsigned int
+hash(struct hashtable *h, void *k);
+
+/*****************************************************************************/
+/* indexFor */
+static inline unsigned int
+indexFor(unsigned int tablelength, unsigned int hashvalue) {
+    return (hashvalue % tablelength);
+};
+
+/* Only works if tablelength == 2^N */
+/*static inline unsigned int
+indexFor(unsigned int tablelength, unsigned int hashvalue)
+{
+    return (hashvalue & (tablelength - 1u));
+}
+*/
+
+/*****************************************************************************/
+#define freekey(X) free(X)
+/*define freekey(X) ; */
+
+
+/*****************************************************************************/
+
+#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/log.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/util/log.c     Fri Sep  9 16:30:54 2005
@@ -0,0 +1,142 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "buffer.h"
+#include "tcg.h"
+
+// Helper code for the consts, eg. to produce messages for error codes.
+
+typedef struct error_code_entry_t {
+  TPM_RESULT code;
+  char * code_name;
+  char * msg;
+} error_code_entry_t;
+
+static const error_code_entry_t error_msgs [] = {    
+  { TPM_SUCCESS, "TPM_SUCCESS", "Successful completion of the operation" },
+  { TPM_AUTHFAIL, "TPM_AUTHFAIL", "Authentication failed" },
+  { TPM_BADINDEX, "TPM_BADINDEX", "The index to a PCR, DIR or other register 
is incorrect" },
+  { TPM_BAD_PARAMETER, "TPM_BAD_PARAMETER", "One or more parameter is bad" },
+  { TPM_AUDITFAILURE, "TPM_AUDITFAILURE", "An operation completed successfully 
but the auditing of that operation failed." },
+  { TPM_CLEAR_DISABLED, "TPM_CLEAR_DISABLED", "The clear disable flag is set 
and all clear operations now require physical access" },
+  { TPM_DEACTIVATED, "TPM_DEACTIVATED", "The TPM is deactivated" },
+  { TPM_DISABLED, "TPM_DISABLED", "The TPM is disabled" },
+  { TPM_DISABLED_CMD, "TPM_DISABLED_CMD", "The target command has been 
disabled" },
+  { TPM_FAIL, "TPM_FAIL", "The operation failed" },
+  { TPM_BAD_ORDINAL, "TPM_BAD_ORDINAL", "The ordinal was unknown or 
inconsistent" },
+  { TPM_INSTALL_DISABLED, "TPM_INSTALL_DISABLED", "The ability to install an 
owner is disabled" },
+  { TPM_INVALID_KEYHANDLE, "TPM_INVALID_KEYHANDLE", "The key handle presented 
was invalid" },
+  { TPM_KEYNOTFOUND, "TPM_KEYNOTFOUND", "The target key was not found" },
+  { TPM_INAPPROPRIATE_ENC, "TPM_INAPPROPRIATE_ENC", "Unacceptable encryption 
scheme" },
+  { TPM_MIGRATEFAIL, "TPM_MIGRATEFAIL", "Migration authorization failed" },
+  { TPM_INVALID_PCR_INFO, "TPM_INVALID_PCR_INFO", "PCR information could not 
be interpreted" },
+  { TPM_NOSPACE, "TPM_NOSPACE", "No room to load key." },
+  { TPM_NOSRK, "TPM_NOSRK", "There is no SRK set" },
+  { TPM_NOTSEALED_BLOB, "TPM_NOTSEALED_BLOB", "An encrypted blob is invalid or 
was not created by this TPM" },
+  { TPM_OWNER_SET, "TPM_OWNER_SET", "There is already an Owner" },
+  { TPM_RESOURCES, "TPM_RESOURCES", "The TPM has insufficient internal 
resources to perform the requested action." },
+  { TPM_SHORTRANDOM, "TPM_SHORTRANDOM", "A random string was too short" },
+  { TPM_SIZE, "TPM_SIZE", "The TPM does not have the space to perform the 
operation." },
+  { TPM_WRONGPCRVAL, "TPM_WRONGPCRVAL", "The named PCR value does not match 
the current PCR value." },
+  { TPM_BAD_PARAM_SIZE, "TPM_BAD_PARAM_SIZE", "The paramSize argument to the 
command has the incorrect value" },
+  { TPM_SHA_THREAD, "TPM_SHA_THREAD", "There is no existing SHA-1 thread." },
+  { TPM_SHA_ERROR, "TPM_SHA_ERROR", "The calculation is unable to proceed 
because the existing SHA-1 thread has already encountered an error." },
+  { TPM_FAILEDSELFTEST, "TPM_FAILEDSELFTEST", "Self-test has failed and the 
TPM has shutdown." },
+  { TPM_AUTH2FAIL, "TPM_AUTH2FAIL", "The authorization for the second key in a 
2 key function failed authorization" },
+  { TPM_BADTAG, "TPM_BADTAG", "The tag value sent to for a command is invalid" 
},
+  { TPM_IOERROR, "TPM_IOERROR", "An IO error occurred transmitting information 
to the TPM" },
+  { TPM_ENCRYPT_ERROR, "TPM_ENCRYPT_ERROR", "The encryption process had a 
problem." },
+  { TPM_DECRYPT_ERROR, "TPM_DECRYPT_ERROR", "The decryption process did not 
complete." },
+  { TPM_INVALID_AUTHHANDLE, "TPM_INVALID_AUTHHANDLE", "An invalid handle was 
used." },
+  { TPM_NO_ENDORSEMENT, "TPM_NO_ENDORSEMENT", "The TPM does not a EK 
installed" },
+  { TPM_INVALID_KEYUSAGE, "TPM_INVALID_KEYUSAGE", "The usage of a key is not 
allowed" },
+  { TPM_WRONG_ENTITYTYPE, "TPM_WRONG_ENTITYTYPE", "The submitted entity type 
is not allowed" },
+  { TPM_INVALID_POSTINIT, "TPM_INVALID_POSTINIT", "The command was received in 
the wrong sequence relative to TPM_Init and a subsequent TPM_Startup" },
+  { TPM_INAPPROPRIATE_SIG, "TPM_INAPPROPRIATE_SIG", "Signed data cannot 
include additional DER information" },
+  { TPM_BAD_KEY_PROPERTY, "TPM_BAD_KEY_PROPERTY", "The key properties in 
TPM_KEY_PARMs are not supported by this TPM" },
+  
+  { TPM_BAD_MIGRATION, "TPM_BAD_MIGRATION", "The migration properties of this 
key are incorrect." },
+  { TPM_BAD_SCHEME, "TPM_BAD_SCHEME", "The signature or encryption scheme for 
this key is incorrect or not permitted in this situation." },
+  { TPM_BAD_DATASIZE, "TPM_BAD_DATASIZE", "The size of the data (or blob) 
parameter is bad or inconsistent with the referenced key" },
+  { TPM_BAD_MODE, "TPM_BAD_MODE", "A mode parameter is bad, such as capArea or 
subCapArea for TPM_GetCapability, phsicalPresence parameter for 
TPM_PhysicalPresence, or migrationType for TPM_CreateMigrationBlob." },
+  { TPM_BAD_PRESENCE, "TPM_BAD_PRESENCE", "Either the physicalPresence or 
physicalPresenceLock bits have the wrong value" },
+  { TPM_BAD_VERSION, "TPM_BAD_VERSION", "The TPM cannot perform this version 
of the capability" },
+  { TPM_NO_WRAP_TRANSPORT, "TPM_NO_WRAP_TRANSPORT", "The TPM does not allow 
for wrapped transport sessions" },
+  { TPM_AUDITFAIL_UNSUCCESSFUL, "TPM_AUDITFAIL_UNSUCCESSFUL", "TPM audit 
construction failed and the underlying command was returning a failure code 
also" },
+  { TPM_AUDITFAIL_SUCCESSFUL, "TPM_AUDITFAIL_SUCCESSFUL", "TPM audit 
construction failed and the underlying command was returning success" },
+  { TPM_NOTRESETABLE, "TPM_NOTRESETABLE", "Attempt to reset a PCR register 
that does not have the resettable attribute" },
+  { TPM_NOTLOCAL, "TPM_NOTLOCAL", "Attempt to reset a PCR register that 
requires locality and locality modifier not part of command transport" },
+  { TPM_BAD_TYPE, "TPM_BAD_TYPE", "Make identity blob not properly typed" },
+  { TPM_INVALID_RESOURCE, "TPM_INVALID_RESOURCE", "When saving context 
identified resource type does not match actual resource" },
+  { TPM_NOTFIPS, "TPM_NOTFIPS", "The TPM is attempting to execute a command 
only available when in FIPS mode" },
+  { TPM_INVALID_FAMILY, "TPM_INVALID_FAMILY", "The command is attempting to 
use an invalid family ID" },
+  { TPM_NO_NV_PERMISSION, "TPM_NO_NV_PERMISSION", "The permission to 
manipulate the NV storage is not available" },
+  { TPM_REQUIRES_SIGN, "TPM_REQUIRES_SIGN", "The operation requires a signed 
command" },
+  { TPM_KEY_NOTSUPPORTED, "TPM_KEY_NOTSUPPORTED", "Wrong operation to load an 
NV key" },
+  { TPM_AUTH_CONFLICT, "TPM_AUTH_CONFLICT", "NV_LoadKey blob requires both 
owner and blob authorization" },
+  { TPM_AREA_LOCKED, "TPM_AREA_LOCKED", "The NV area is locked and not 
writtable" },
+  { TPM_BAD_LOCALITY, "TPM_BAD_LOCALITY", "The locality is incorrect for the 
attempted operation" },
+  { TPM_READ_ONLY, "TPM_READ_ONLY", "The NV area is read only and can't be 
written to" },
+  { TPM_PER_NOWRITE, "TPM_PER_NOWRITE", "There is no protection on the write 
to the NV area" },
+  { TPM_FAMILYCOUNT, "TPM_FAMILYCOUNT", "The family count value does not 
match" },
+  { TPM_WRITE_LOCKED, "TPM_WRITE_LOCKED", "The NV area has already been 
written to" },
+  { TPM_BAD_ATTRIBUTES, "TPM_BAD_ATTRIBUTES", "The NV area attributes 
conflict" },
+  { TPM_INVALID_STRUCTURE, "TPM_INVALID_STRUCTURE", "The structure tag and 
version are invalid or inconsistent" },
+  { TPM_KEY_OWNER_CONTROL, "TPM_KEY_OWNER_CONTROL", "The key is under control 
of the TPM Owner and can only be evicted by the TPM Owner." },
+  { TPM_BAD_COUNTER, "TPM_BAD_COUNTER", "The counter handle is incorrect" },
+  { TPM_NOT_FULLWRITE, "TPM_NOT_FULLWRITE", "The write is not a complete write 
of the area" },
+  { TPM_CONTEXT_GAP, "TPM_CONTEXT_GAP", "The gap between saved context counts 
is too large" },
+  { TPM_MAXNVWRITES, "TPM_MAXNVWRITES", "The maximum number of NV writes 
without an owner has been exceeded" },
+  { TPM_NOOPERATOR, "TPM_NOOPERATOR", "No operator authorization value is set" 
},
+  { TPM_RESOURCEMISSING, "TPM_RESOURCEMISSING", "The resource pointed to by 
context is not loaded" },
+  { TPM_DELEGATE_LOCK, "TPM_DELEGATE_LOCK", "The delegate administration is 
locked" },
+  { TPM_DELEGATE_FAMILY, "TPM_DELEGATE_FAMILY", "Attempt to manage a family 
other then the delegated family" },
+  { TPM_DELEGATE_ADMIN, "TPM_DELEGATE_ADMIN", "Delegation table management not 
enabled" },
+  { TPM_TRANSPORT_EXCLUSIVE, "TPM_TRANSPORT_EXCLUSIVE", "There was a command 
executed outside of an exclusive transport session" },
+};
+
+
+// helper function for the error codes:
+const char* tpm_get_error_name (TPM_RESULT code) {
+  // just do a linear scan for now
+  unsigned i;
+  for (i = 0; i < sizeof(error_msgs)/sizeof(error_msgs[0]); i++) 
+    if (code == error_msgs[i].code) 
+      return error_msgs[i].code_name;
+  
+    return "Failed to find code name for given code";
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/log.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/util/log.h     Fri Sep  9 16:30:54 2005
@@ -0,0 +1,92 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+#ifndef __VTPM_LOG_H__
+#define __VTPM_LOG_H__
+
+#include <stdint.h>             // for uint32_t
+#include <stddef.h>             // for pointer NULL
+
+// =========================== LOGGING ==============================
+
+// the logging module numbers
+#define VTPM_LOG_CRYPTO      1
+#define VTPM_LOG_BSG         2
+#define VTPM_LOG_TXDATA      3
+#define VTPM_LOG_TCS         4
+#define VTPM_LOG_TCS_DEEP    5
+#define VTPM_LOG_VTSP        6
+#define VTPM_LOG_VTPM        7
+#define VTPM_LOG_VTPM_DEEP   8
+
+static char *module_names[] = { "",
+                                "CRYPTO",
+                                "BSG",
+                                "TXDATA",
+                                "TCS",
+                                "TCS",
+                                "VTSP",
+                                "VTPM",
+                                "VTPM"
+                              };
+
+// Default to standard logging
+#ifndef LOGGING_MODULES
+#define LOGGING_MODULES (BITMASK(VTPM_LOG_VTPM))
+#endif
+
+// bit-access macros
+#define BITMASK(idx)      ( 1U << (idx) )
+#define GETBIT(num,idx)   ( ((num) & BITMASK(idx)) >> idx )
+#define SETBIT(num,idx)   (num) |= BITMASK(idx)
+#define CLEARBIT(num,idx) (num) &= ( ~ BITMASK(idx) )
+
+#define vtpmloginfo(module, fmt, args...) \
+  if (GETBIT (LOGGING_MODULES, module) == 1) {                         \
+    fprintf (stdout, "INFO[%s]: " fmt, module_names[module], ##args); \
+  }
+
+#define vtpmloginfomore(module, fmt, args...) \
+  if (GETBIT (LOGGING_MODULES, module) == 1) {                       \
+    fprintf (stdout, fmt,##args);                                    \
+  }
+                               
+#define vtpmlogerror(module, fmt, args...) \
+  fprintf (stderr, "ERROR[%s]: " fmt, module_names[module], ##args);
+                               
+//typedef UINT32 tpm_size_t;
+                        
+// helper function for the error codes:
+const char* tpm_get_error_name (TPM_RESULT code);
+
+#endif // _VTPM_LOG_H_
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/tcg.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/vtpm_manager/util/tcg.h     Fri Sep  9 16:30:54 2005
@@ -0,0 +1,486 @@
+// ===================================================================
+// 
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions 
+// are met:
+//
+//   * Redistributions of source code must retain the above copyright 
+//     notice, this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following 
+//     disclaimer in the documentation and/or other materials provided 
+//     with the distribution.
+//   * Neither the name of Intel Corporation nor the names of its 
+//     contributors may be used to endorse or promote products derived
+//     from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+// 
+// tcg.h
+// 
+//  This file contains all the structure and type definitions
+//
+// ==================================================================
+
+#ifndef __TCG_H__
+#define __TCG_H__
+
+// This pragma is used to disallow structure padding
+#pragma pack(push, 1)
+
+// *************************** TYPEDEFS *********************************
+typedef unsigned char BYTE;
+typedef unsigned char BOOL;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32;
+typedef unsigned long long UINT64;
+
+typedef UINT32 TPM_RESULT;
+typedef UINT32 TPM_PCRINDEX;
+typedef UINT32 TPM_DIRINDEX;
+typedef UINT32 TPM_HANDLE;
+typedef TPM_HANDLE TPM_AUTHHANDLE;
+typedef TPM_HANDLE TCPA_HASHHANDLE;
+typedef TPM_HANDLE TCPA_HMACHANDLE;
+typedef TPM_HANDLE TCPA_ENCHANDLE;
+typedef TPM_HANDLE TPM_KEY_HANDLE;
+typedef TPM_HANDLE TCPA_ENTITYHANDLE;
+typedef UINT32 TPM_RESOURCE_TYPE;
+typedef UINT32 TPM_COMMAND_CODE;
+typedef UINT16 TPM_PROTOCOL_ID;
+typedef BYTE TPM_AUTH_DATA_USAGE;
+typedef UINT16 TPM_ENTITY_TYPE;
+typedef UINT32 TPM_ALGORITHM_ID;
+typedef UINT16 TPM_KEY_USAGE;
+typedef UINT16 TPM_STARTUP_TYPE;
+typedef UINT32 TPM_CAPABILITY_AREA;
+typedef UINT16 TPM_ENC_SCHEME;
+typedef UINT16 TPM_SIG_SCHEME;
+typedef UINT16 TPM_MIGRATE_SCHEME;
+typedef UINT16 TPM_PHYSICAL_PRESENCE;
+typedef UINT32 TPM_KEY_FLAGS;
+
+#define TPM_DIGEST_SIZE 20  // Don't change this
+typedef BYTE TPM_AUTHDATA[TPM_DIGEST_SIZE];
+typedef TPM_AUTHDATA TPM_SECRET;
+typedef TPM_AUTHDATA TPM_ENCAUTH;
+typedef BYTE TPM_PAYLOAD_TYPE;
+typedef UINT16 TPM_TAG;
+
+// Data Types of the TCS
+typedef UINT32 TCS_AUTHHANDLE;  // Handle addressing a authorization session
+typedef UINT32 TCS_CONTEXT_HANDLE; // Basic context handle
+typedef UINT32 TCS_KEY_HANDLE;  // Basic key handle
+
+// ************************* STRUCTURES **********************************
+
+typedef struct TPM_VERSION {
+  BYTE major;
+  BYTE minor;
+  BYTE revMajor;
+  BYTE revMinor;
+} TPM_VERSION;
+ 
+static const TPM_VERSION TPM_STRUCT_VER_1_1 = { 1,1,0,0 };
+
+typedef struct TPM_DIGEST {
+  BYTE digest[TPM_DIGEST_SIZE];
+} TPM_DIGEST;
+
+typedef TPM_DIGEST TPM_PCRVALUE;
+typedef TPM_DIGEST TPM_COMPOSITE_HASH;
+typedef TPM_DIGEST TPM_DIRVALUE;
+typedef TPM_DIGEST TPM_HMAC;
+typedef TPM_DIGEST TPM_CHOSENID_HASH;
+
+typedef struct TPM_NONCE {
+  BYTE nonce[TPM_DIGEST_SIZE];
+} TPM_NONCE;
+
+typedef struct TPM_KEY_PARMS {
+  TPM_ALGORITHM_ID algorithmID;
+  TPM_ENC_SCHEME encScheme;
+  TPM_SIG_SCHEME sigScheme;
+  UINT32 parmSize;
+  BYTE* parms;
+} TPM_KEY_PARMS;
+
+typedef struct TPM_RSA_KEY_PARMS {  
+  UINT32 keyLength; 
+  UINT32 numPrimes; 
+  UINT32 exponentSize;
+  BYTE* exponent;
+} TPM_RSA_KEY_PARMS;
+
+typedef struct TPM_STORE_PUBKEY {
+  UINT32 keyLength;
+  BYTE* key;
+} TPM_STORE_PUBKEY;
+
+typedef struct TPM_PUBKEY {
+  TPM_KEY_PARMS algorithmParms;
+  TPM_STORE_PUBKEY pubKey;
+} TPM_PUBKEY;
+
+typedef struct TPM_KEY {
+  TPM_VERSION         ver;
+  TPM_KEY_USAGE       keyUsage;
+  TPM_KEY_FLAGS       keyFlags;
+  TPM_AUTH_DATA_USAGE authDataUsage;
+  TPM_KEY_PARMS       algorithmParms; 
+  UINT32              PCRInfoSize;
+  BYTE*               PCRInfo; // this should be a TPM_PCR_INFO, or NULL
+  TPM_STORE_PUBKEY    pubKey;
+  UINT32              encDataSize;
+  BYTE*               encData;
+} TPM_KEY;
+
+typedef struct TPM_PCR_SELECTION { 
+  UINT16 sizeOfSelect;        /// in bytes
+  BYTE* pcrSelect;
+} TPM_PCR_SELECTION;
+
+typedef struct TPM_PCR_COMPOSITE { 
+  TPM_PCR_SELECTION select;
+  UINT32 valueSize;
+  TPM_PCRVALUE* pcrValue;
+} TPM_PCR_COMPOSITE;
+
+
+typedef struct TPM_PCR_INFO {
+  TPM_PCR_SELECTION pcrSelection;
+  TPM_COMPOSITE_HASH digestAtRelease;
+  TPM_COMPOSITE_HASH digestAtCreation;
+} TPM_PCR_INFO;
+
+
+typedef struct TPM_BOUND_DATA {
+  TPM_VERSION ver;
+  TPM_PAYLOAD_TYPE payload;
+  BYTE* payloadData;
+} TPM_BOUND_DATA;
+
+typedef struct TPM_STORED_DATA { 
+  TPM_VERSION ver;
+  UINT32 sealInfoSize;
+  BYTE* sealInfo;
+  UINT32 encDataSize;
+  BYTE* encData;
+} TPM_STORED_DATA;
+
+typedef struct TCS_AUTH {
+  TCS_AUTHHANDLE  AuthHandle;
+  TPM_NONCE   NonceOdd;   // system 
+  TPM_NONCE   NonceEven;   // TPM 
+  BOOL   fContinueAuthSession;
+  TPM_AUTHDATA  HMAC;
+} TCS_AUTH;
+
+// **************************** CONSTANTS *********************************
+
+// BOOL values
+#define TRUE 0x01
+#define FALSE 0x00
+
+#define TCPA_MAX_BUFFER_LENGTH 0x2000
+
+//
+// TPM_COMMAND_CODE values
+#define TPM_PROTECTED_ORDINAL 0x00000000UL
+#define TPM_UNPROTECTED_ORDINAL 0x80000000UL
+#define TPM_CONNECTION_ORDINAL 0x40000000UL
+#define TPM_VENDOR_ORDINAL 0x20000000UL
+
+#define TPM_ORD_OIAP                     (10UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OSAP                     (11UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuth               (12UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_TakeOwnership            (13UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuthAsymStart      (14UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuthAsymFinish     (15UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuthOwner          (16UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Extend                   (20UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PcrRead                  (21UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Quote                    (22UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Seal                     (23UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Unseal                   (24UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DirWriteAuth             (25UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DirRead                  (26UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_UnBind                   (30UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateWrapKey            (31UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadKey                  (32UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetPubKey                (33UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_EvictKey                 (34UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateMigrationBlob      (40UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReWrapKey                (41UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ConvertMigrationBlob     (42UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_AuthorizeMigrationKey    (43UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateMaintenanceArchive (44UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadMaintenanceArchive   (45UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_KillMaintenanceFeature   (46UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadManuMaintPub         (47UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReadManuMaintPub         (48UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CertifyKey               (50UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Sign                     (60UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetRandom                (70UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_StirRandom               (71UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SelfTestFull             (80UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SelfTestStartup          (81UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CertifySelfTest          (82UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ContinueSelfTest         (83UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetTestResult            (84UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Reset                    (90UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OwnerClear               (91UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DisableOwnerClear        (92UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ForceClear               (93UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DisableForceClear        (94UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetCapabilitySigned      (100UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetCapability            (101UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetCapabilityOwner       (102UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OwnerSetDisable          (110UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PhysicalEnable           (111UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PhysicalDisable          (112UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetOwnerInstall          (113UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PhysicalSetDeactivated   (114UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetTempDeactivated       (115UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateEndorsementKeyPair (120UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_MakeIdentity             (121UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ActivateIdentity         (122UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReadPubek                (124UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OwnerReadPubek           (125UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DisablePubekRead         (126UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetAuditEvent            (130UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetAuditEventSigned      (131UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetOrdinalAuditStatus    (140UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetOrdinalAuditStatus    (141UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Terminate_Handle         (150UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Init                     (151UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SaveState                (152UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Startup                  (153UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetRedirection           (154UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1Start                (160UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1Update               (161UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1Complete             (162UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1CompleteExtend       (163UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_FieldUpgrade             (170UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SaveKeyContext           (180UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadKeyContext           (181UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SaveAuthContext          (182UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadAuthContext          (183UL + TPM_PROTECTED_ORDINAL)
+#define TSC_ORD_PhysicalPresence         (10UL + TPM_CONNECTION_ORDINAL)
+
+
+
+//
+// TPM_RESULT values
+//
+// just put in the whole table from spec 1.2
+              
+#define TPM_BASE   0x0 // The start of TPM return codes
+#define TPM_VENDOR_ERROR 0x00000400 // Mask to indicate that the error code is 
vendor specific for vendor specific commands
+#define TPM_NON_FATAL  0x00000800 // Mask to indicate that the error code is a 
non-fatal failure.
+
+#define TPM_SUCCESS   TPM_BASE // Successful completion of the operation
+#define TPM_AUTHFAIL      TPM_BASE + 1 // Authentication failed
+#define TPM_BADINDEX      TPM_BASE + 2 // The index to a PCR, DIR or other 
register is incorrect
+#define TPM_BAD_PARAMETER     TPM_BASE + 3 // One or more parameter is bad
+#define TPM_AUDITFAILURE     TPM_BASE + 4 // An operation completed 
successfully but the auditing of that operation failed.
+#define TPM_CLEAR_DISABLED     TPM_BASE + 5 // The clear disable flag is set 
and all clear operations now require physical access
+#define TPM_DEACTIVATED     TPM_BASE + 6 // The TPM is deactivated
+#define TPM_DISABLED      TPM_BASE + 7 // The TPM is disabled
+#define TPM_DISABLED_CMD     TPM_BASE + 8 // The target command has been 
disabled
+#define TPM_FAIL       TPM_BASE + 9 // The operation failed
+#define TPM_BAD_ORDINAL     TPM_BASE + 10 // The ordinal was unknown or 
inconsistent
+#define TPM_INSTALL_DISABLED   TPM_BASE + 11 // The ability to install an 
owner is disabled
+#define TPM_INVALID_KEYHANDLE  TPM_BASE + 12 // The key handle presented was 
invalid
+#define TPM_KEYNOTFOUND     TPM_BASE + 13 // The target key was not found
+#define TPM_INAPPROPRIATE_ENC  TPM_BASE + 14 // Unacceptable encryption scheme
+#define TPM_MIGRATEFAIL     TPM_BASE + 15 // Migration authorization failed
+#define TPM_INVALID_PCR_INFO   TPM_BASE + 16 // PCR information could not be 
interpreted
+#define TPM_NOSPACE      TPM_BASE + 17 // No room to load key.
+#define TPM_NOSRK       TPM_BASE + 18 // There is no SRK set
+#define TPM_NOTSEALED_BLOB     TPM_BASE + 19 // An encrypted blob is invalid 
or was not created by this TPM
+#define TPM_OWNER_SET      TPM_BASE + 20 // There is already an Owner
+#define TPM_RESOURCES      TPM_BASE + 21 // The TPM has insufficient internal 
resources to perform the requested action.
+#define TPM_SHORTRANDOM     TPM_BASE + 22 // A random string was too short
+#define TPM_SIZE       TPM_BASE + 23 // The TPM does not have the space to 
perform the operation.
+#define TPM_WRONGPCRVAL     TPM_BASE + 24 // The named PCR value does not 
match the current PCR value.
+#define TPM_BAD_PARAM_SIZE     TPM_BASE + 25 // The paramSize argument to the 
command has the incorrect value
+#define TPM_SHA_THREAD      TPM_BASE + 26 // There is no existing SHA-1 thread.
+#define TPM_SHA_ERROR      TPM_BASE + 27 // The calculation is unable to 
proceed because the existing SHA-1 thread has already encountered an error.
+#define TPM_FAILEDSELFTEST     TPM_BASE + 28 // Self-test has failed and the 
TPM has shutdown.
+#define TPM_AUTH2FAIL      TPM_BASE + 29 // The authorization for the second 
key in a 2 key function failed authorization
+#define TPM_BADTAG       TPM_BASE + 30 // The tag value sent to for a command 
is invalid
+#define TPM_IOERROR      TPM_BASE + 31 // An IO error occurred transmitting 
information to the TPM
+#define TPM_ENCRYPT_ERROR     TPM_BASE + 32 // The encryption process had a 
problem.
+#define TPM_DECRYPT_ERROR     TPM_BASE + 33 // The decryption process did not 
complete.
+#define TPM_INVALID_AUTHHANDLE TPM_BASE + 34 // An invalid handle was used.
+#define TPM_NO_ENDORSEMENT     TPM_BASE + 35 // The TPM does not a EK installed
+#define TPM_INVALID_KEYUSAGE   TPM_BASE + 36 // The usage of a key is not 
allowed
+#define TPM_WRONG_ENTITYTYPE   TPM_BASE + 37 // The submitted entity type is 
not allowed
+#define TPM_INVALID_POSTINIT   TPM_BASE + 38 // The command was received in 
the wrong sequence relative to TPM_Init and a subsequent TPM_Startup
+#define TPM_INAPPROPRIATE_SIG  TPM_BASE + 39 // Signed data cannot include 
additional DER information
+#define TPM_BAD_KEY_PROPERTY   TPM_BASE + 40 // The key properties in 
TPM_KEY_PARMs are not supported by this TPM
+
+#define TPM_BAD_MIGRATION      TPM_BASE + 41 // The migration properties of 
this key are incorrect.
+#define TPM_BAD_SCHEME       TPM_BASE + 42 // The signature or encryption 
scheme for this key is incorrect or not permitted in this situation.
+#define TPM_BAD_DATASIZE      TPM_BASE + 43 // The size of the data (or blob) 
parameter is bad or inconsistent with the referenced key
+#define TPM_BAD_MODE       TPM_BASE + 44 // A mode parameter is bad, such as 
capArea or subCapArea for TPM_GetCapability, phsicalPresence parameter for 
TPM_PhysicalPresence, or migrationType for TPM_CreateMigrationBlob.
+#define TPM_BAD_PRESENCE      TPM_BASE + 45 // Either the physicalPresence or 
physicalPresenceLock bits have the wrong value
+#define TPM_BAD_VERSION      TPM_BASE + 46 // The TPM cannot perform this 
version of the capability
+#define TPM_NO_WRAP_TRANSPORT     TPM_BASE + 47 // The TPM does not allow for 
wrapped transport sessions
+#define TPM_AUDITFAIL_UNSUCCESSFUL TPM_BASE + 48 // TPM audit construction 
failed and the underlying command was returning a failure code also
+#define TPM_AUDITFAIL_SUCCESSFUL   TPM_BASE + 49 // TPM audit construction 
failed and the underlying command was returning success
+#define TPM_NOTRESETABLE      TPM_BASE + 50 // Attempt to reset a PCR register 
that does not have the resettable attribute
+#define TPM_NOTLOCAL       TPM_BASE + 51 // Attempt to reset a PCR register 
that requires locality and locality modifier not part of command transport
+#define TPM_BAD_TYPE       TPM_BASE + 52 // Make identity blob not properly 
typed
+#define TPM_INVALID_RESOURCE     TPM_BASE + 53 // When saving context 
identified resource type does not match actual resource
+#define TPM_NOTFIPS       TPM_BASE + 54 // The TPM is attempting to execute a 
command only available when in FIPS mode
+#define TPM_INVALID_FAMILY      TPM_BASE + 55 // The command is attempting to 
use an invalid family ID
+#define TPM_NO_NV_PERMISSION     TPM_BASE + 56 // The permission to manipulate 
the NV storage is not available
+#define TPM_REQUIRES_SIGN      TPM_BASE + 57 // The operation requires a 
signed command
+#define TPM_KEY_NOTSUPPORTED     TPM_BASE + 58 // Wrong operation to load an 
NV key
+#define TPM_AUTH_CONFLICT      TPM_BASE + 59 // NV_LoadKey blob requires both 
owner and blob authorization
+#define TPM_AREA_LOCKED      TPM_BASE + 60 // The NV area is locked and not 
writtable
+#define TPM_BAD_LOCALITY      TPM_BASE + 61 // The locality is incorrect for 
the attempted operation
+#define TPM_READ_ONLY       TPM_BASE + 62 // The NV area is read only and 
can't be written to
+#define TPM_PER_NOWRITE      TPM_BASE + 63 // There is no protection on the 
write to the NV area
+#define TPM_FAMILYCOUNT      TPM_BASE + 64 // The family count value does not 
match
+#define TPM_WRITE_LOCKED      TPM_BASE + 65 // The NV area has already been 
written to
+#define TPM_BAD_ATTRIBUTES      TPM_BASE + 66 // The NV area attributes 
conflict
+#define TPM_INVALID_STRUCTURE     TPM_BASE + 67 // The structure tag and 
version are invalid or inconsistent
+#define TPM_KEY_OWNER_CONTROL     TPM_BASE + 68 // The key is under control of 
the TPM Owner and can only be evicted by the TPM Owner.
+#define TPM_BAD_COUNTER      TPM_BASE + 69 // The counter handle is incorrect
+#define TPM_NOT_FULLWRITE      TPM_BASE + 70 // The write is not a complete 
write of the area
+#define TPM_CONTEXT_GAP      TPM_BASE + 71 // The gap between saved context 
counts is too large
+#define TPM_MAXNVWRITES      TPM_BASE + 72 // The maximum number of NV writes 
without an owner has been exceeded
+#define TPM_NOOPERATOR       TPM_BASE + 73 // No operator authorization value 
is set
+#define TPM_RESOURCEMISSING     TPM_BASE + 74 // The resource pointed to by 
context is not loaded
+#define TPM_DELEGATE_LOCK      TPM_BASE + 75 // The delegate administration is 
locked
+#define TPM_DELEGATE_FAMILY     TPM_BASE + 76 // Attempt to manage a family 
other then the delegated family
+#define TPM_DELEGATE_ADMIN      TPM_BASE + 77 // Delegation table management 
not enabled
+#define TPM_TRANSPORT_EXCLUSIVE    TPM_BASE + 78 // There was a command 
executed outside of an exclusive transport session
+
+// TPM_TAG values
+#define TPM_TAG_RQU_COMMAND 0x00c1
+#define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2
+#define TPM_TAG_RQU_AUTH2_COMMAND 0x00c3
+#define TPM_TAG_RSP_COMMAND 0x00c4
+#define TPM_TAG_RSP_AUTH1_COMMAND 0x00c5
+#define TPM_TAG_RSP_AUTH2_COMMAND 0x00c6
+
+// TPM_PAYLOAD_TYPE values
+#define TPM_PT_ASYM 0x01
+#define TPM_PT_BIND 0x02
+#define TPM_PT_MIGRATE 0x03
+#define TPM_PT_MAINT 0x04
+#define TPM_PT_SEAL 0x05
+
+// TPM_ENTITY_TYPE values
+#define TPM_ET_KEYHANDLE 0x0001
+#define TPM_ET_OWNER 0x0002
+#define TPM_ET_DATA 0x0003
+#define TPM_ET_SRK 0x0004
+#define TPM_ET_KEY 0x0005
+
+/// TPM_ResourceTypes
+#define TPM_RT_KEY      0x00000001
+#define TPM_RT_AUTH     0x00000002
+#define TPM_RT_TRANS    0x00000004
+#define TPM_RT_CONTEXT  0x00000005
+
+// TPM_PROTOCOL_ID values
+#define TPM_PID_OIAP 0x0001
+#define TPM_PID_OSAP 0x0002
+#define TPM_PID_ADIP 0x0003
+#define TPM_PID_ADCP 0x0004
+#define TPM_PID_OWNER 0x0005
+
+// TPM_ALGORITHM_ID values
+#define TPM_ALG_RSA 0x00000001
+#define TPM_ALG_DES 0x00000002
+#define TPM_ALG_3DES 0X00000003
+#define TPM_ALG_SHA 0x00000004
+#define TPM_ALG_HMAC 0x00000005
+#define TCPA_ALG_AES 0x00000006
+
+// TPM_ENC_SCHEME values
+#define TPM_ES_NONE 0x0001
+#define TPM_ES_RSAESPKCSv15 0x0002
+#define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003
+
+// TPM_SIG_SCHEME values
+#define TPM_SS_NONE 0x0001
+#define TPM_SS_RSASSAPKCS1v15_SHA1 0x0002
+#define TPM_SS_RSASSAPKCS1v15_DER 0x0003
+
+// TPM_KEY_USAGE values
+#define TPM_KEY_EK 0x0000 
+#define TPM_KEY_SIGNING 0x0010
+#define TPM_KEY_STORAGE 0x0011
+#define TPM_KEY_IDENTITY 0x0012
+#define TPM_KEY_AUTHCHANGE 0X0013
+#define TPM_KEY_BIND 0x0014
+#define TPM_KEY_LEGACY 0x0015
+
+// TPM_AUTH_DATA_USAGE values
+#define TPM_AUTH_NEVER 0x00
+#define TPM_AUTH_ALWAYS 0x01
+
+// Key Handle of owner and srk
+#define TPM_OWNER_KEYHANDLE 0x40000001
+#define TPM_SRK_KEYHANDLE 0x40000000
+
+// ---------------------- Functions for checking TPM_RESULTs -----------------
+
+// FIXME: Review use of these and delete unneeded ones.
+
+// these are really badly dependent on local structure:
+// DEPENDS: local var 'status' of type TPM_RESULT
+// DEPENDS: label 'abort_egress' which cleans up and returns the status
+#define ERRORDIE(s) do { status = s; \
+                         fprintf (stderr, "*** ERRORDIE in %s, line %i\n", 
__func__, __LINE__); \
+                         goto abort_egress; } \
+                    while (0)
+
+// ASSUME: the return value used after the abort_egress label has been set
+// already (eg. the 'status' local var)
+#define STATUSCHECK(s) if (s != TPM_SUCCESS) { \
+                            fprintf (stderr, "*** ERR in %s, line %i\n", 
__func__, __LINE__); \
+                            goto abort_egress; \
+                        }
+
+// DEPENDS: local var 'status' of type TPM_RESULT
+// DEPENDS: label 'abort_egress' which cleans up and returns the status
+// Try command c. If it fails, set status to s and goto shame.
+#define TPMTRY(s,c) if (c != TPM_SUCCESS) { \
+                       status = s; \
+                       goto abort_egress; \
+                    }
+
+// Try command c. If it fails, print error message, set status to actual 
return code. Goto shame
+#define TPMTRYRETURN(c) do { status = c; \
+                             if (status != TPM_SUCCESS) { \
+                               printf("ERROR in %s:%i code: %s.\n", __func__, 
__LINE__, tpm_get_error_name(status)); \
+                               goto abort_egress; \
+                             } \
+                        } while(0)    
+
+
+#pragma pack(pop)
+
+#endif //__TCPA_H__
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xenstore_client.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/tools/xenstore/xenstore_client.c  Fri Sep  9 16:30:54 2005
@@ -0,0 +1,130 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2005 by Christian Limpach
+ *
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <xs.h>
+
+static void
+usage(const char *progname)
+{
+#if defined(CLIENT_read)
+    errx(1, "Usage: %s [-h] [-p] key [...]", progname);
+#elif defined(CLIENT_write)
+    errx(1, "Usage: %s [-h] key value [...]", progname);
+#elif defined(CLIENT_rm)
+    errx(1, "Usage: %s [-h] key [...]", progname);
+#endif
+}
+
+int
+main(int argc, char **argv)
+{
+    struct xs_handle *xsh;
+    bool success;
+    int ret = 0;
+#if defined(CLIENT_read)
+    char *val;
+    int prefix = 0;
+#endif
+
+    xsh = xs_domain_open();
+    if (xsh == NULL)
+       err(1, "xs_domain_open");
+
+    while (1) {
+       int c, index = 0;
+       static struct option long_options[] = {
+           {"help", 0, 0, 'h'},
+#if defined(CLIENT_read)
+           {"prefix", 0, 0, 'p'},
+#endif
+           {0, 0, 0, 0}
+       };
+
+       c = getopt_long(argc, argv, "h"
+#if defined(CLIENT_read)
+                       "p"
+#endif
+                       , long_options, &index);
+       if (c == -1)
+           break;
+
+       switch (c) {
+       case 'h':
+           usage(argv[0]);
+           /* NOTREACHED */
+#if defined(CLIENT_read)
+       case 'p':
+           prefix = 1;
+           break;
+#endif
+       }
+    }
+
+    if (optind == argc) {
+       usage(argv[0]);
+       /* NOTREACHED */
+    }
+#if defined(CLIENT_write)
+    if ((argc - optind) % 1) {
+       usage(argv[0]);
+       /* NOTREACHED */
+    }
+#endif
+
+    /* XXX maybe find longest common prefix */
+    success = xs_transaction_start(xsh, "/");
+    if (!success)
+       errx(1, "couldn't start transaction");
+
+    while (optind < argc) {
+#if defined(CLIENT_read)
+       val = xs_read(xsh, argv[optind], NULL);
+       if (val == NULL) {
+           warnx("couldn't read path %s", argv[optind]);
+           ret = 1;
+           goto out;
+       }
+       if (prefix)
+           printf("%s: ", argv[optind]);
+       printf("%s\n", val);
+       free(val);
+       optind++;
+#elif defined(CLIENT_write)
+       success = xs_write(xsh, argv[optind], argv[optind + 1],
+                          strlen(argv[optind + 1]), O_CREAT);
+       if (!success) {
+           warnx("could not write path %s", argv[optind]);
+           ret = 1;
+           goto out;
+       }
+       optind += 2;
+#elif defined(CLIENT_rm)
+       success = xs_rm(xsh, argv[optind]);
+       if (!success) {
+           warnx("could not remove path %s", argv[optind]);
+           ret = 1;
+           goto out;
+       }
+       optind++;
+#endif
+    }
+
+ out:
+    success = xs_transaction_end(xsh, ret ? true : false);
+    if (!success)
+       errx(1, "couldn't end transaction");
+
+    return ret;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/shadow_guest32.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/xen/arch/x86/shadow_guest32.c     Fri Sep  9 16:30:54 2005
@@ -0,0 +1,18 @@
+#define GUEST_PGENTRY_32
+#if defined (__x86_64__)
+
+#include "shadow.c"
+struct shadow_ops MODE_D_HANDLER = {
+    .guest_paging_levels              = 2,
+    .invlpg                     = shadow_invlpg_64,
+    .fault                      = shadow_fault_64,
+    .update_pagetables          = shadow_update_pagetables,
+    .sync_all                   = sync_all,
+    .remove_all_write_access    = remove_all_write_access,
+    .do_update_va_mapping       = do_update_va_mapping,
+    .mark_mfn_out_of_sync       = mark_mfn_out_of_sync,
+    .is_out_of_sync             = is_out_of_sync,
+    .gva_to_gpa                 = gva_to_gpa_64,
+};
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/memory.c
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/xen/common/memory.c       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,214 @@
+/******************************************************************************
+ * memory.c
+ *
+ * Code to handle memory-related requests.
+ *
+ * Copyright (c) 2003-2004, B Dragovic
+ * Copyright (c) 2003-2005, K A Fraser
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+#include <xen/perfc.h>
+#include <xen/sched.h>
+#include <xen/event.h>
+#include <xen/shadow.h>
+#include <asm/current.h>
+#include <asm/hardirq.h>
+#include <public/memory.h>
+
+static long
+increase_reservation(
+    struct domain *d, 
+    unsigned long *extent_list, 
+    unsigned int   nr_extents,
+    unsigned int   extent_order,
+    unsigned int   flags,
+    int           *preempted)
+{
+    struct pfn_info *page;
+    unsigned long    i;
+
+    if ( (extent_list != NULL) &&
+         !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
+        return 0;
+
+    if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) )
+    {
+        DPRINTK("Only I/O-capable domains may allocate > order-0 memory.\n");
+        return 0;
+    }
+
+    for ( i = 0; i < nr_extents; i++ )
+    {
+        if ( hypercall_preempt_check() )
+        {
+            *preempted = 1;
+            return i;
+        }
+
+        if ( unlikely((page = alloc_domheap_pages(
+            d, extent_order, flags)) == NULL) )
+        {
+            DPRINTK("Could not allocate order=%d extent: id=%d flags=%x\n",
+                    extent_order, d->domain_id, flags);
+            return i;
+        }
+
+        /* Inform the domain of the new page's machine address. */ 
+        if ( (extent_list != NULL) &&
+             (__put_user(page_to_pfn(page), &extent_list[i]) != 0) )
+            return i;
+    }
+
+    return nr_extents;
+}
+    
+static long
+decrease_reservation(
+    struct domain *d, 
+    unsigned long *extent_list, 
+    unsigned int   nr_extents,
+    unsigned int   extent_order,
+    unsigned int   flags,
+    int           *preempted)
+{
+    struct pfn_info *page;
+    unsigned long    i, j, mpfn;
+
+    if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
+        return 0;
+
+    for ( i = 0; i < nr_extents; i++ )
+    {
+        if ( hypercall_preempt_check() )
+        {
+            *preempted = 1;
+            return i;
+        }
+
+        if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
+            return i;
+
+        for ( j = 0; j < (1 << extent_order); j++ )
+        {
+            if ( unlikely((mpfn + j) >= max_page) )
+            {
+                DPRINTK("Domain %u page number out of range (%lx >= %lx)\n", 
+                        d->domain_id, mpfn + j, max_page);
+                return i;
+            }
+            
+            page = &frame_table[mpfn + j];
+            if ( unlikely(!get_page(page, d)) )
+            {
+                DPRINTK("Bad page free for domain %u\n", d->domain_id);
+                return i;
+            }
+
+            if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
+                put_page_and_type(page);
+            
+            if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
+                put_page(page);
+
+            shadow_sync_and_drop_references(d, page);
+
+            put_page(page);
+        }
+    }
+
+    return nr_extents;
+}
+
+/*
+ * To allow safe resume of do_memory_op() after preemption, we need to know 
+ * at what point in the page list to resume. For this purpose I steal the 
+ * high-order bits of the @cmd parameter, which are otherwise unused and zero.
+ */
+#define START_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
+
+long do_memory_op(int cmd, void *arg)
+{
+    struct domain *d;
+    int rc, start_extent, op, flags = 0, preempted = 0;
+    struct xen_memory_reservation reservation;
+
+    op = cmd & ((1 << START_EXTENT_SHIFT) - 1);
+
+    switch ( op )
+    {
+    case XENMEM_increase_reservation:
+    case XENMEM_decrease_reservation:
+        if ( copy_from_user(&reservation, arg, sizeof(reservation)) )
+            return -EFAULT;
+
+        start_extent = cmd >> START_EXTENT_SHIFT;
+        if ( unlikely(start_extent > reservation.nr_extents) )
+            return -EINVAL;
+        
+        if ( reservation.extent_start != NULL )
+            reservation.extent_start += start_extent;
+        reservation.nr_extents -= start_extent;
+
+        if ( (reservation.address_bits != 0) &&
+             (reservation.address_bits <
+              (get_order_from_pages(max_page) + PAGE_SHIFT)) )
+        {
+            if ( reservation.address_bits < 31 )
+                return -ENOMEM;
+            flags = ALLOC_DOM_DMA;
+        }
+
+        if ( likely(reservation.domid == DOMID_SELF) )
+            d = current->domain;
+        else if ( !IS_PRIV(current->domain) )
+            return -EPERM;
+        else if ( (d = find_domain_by_id(reservation.domid)) == NULL )
+            return -ESRCH;
+
+        rc = ((op == XENMEM_increase_reservation) ?
+              increase_reservation : decrease_reservation)(
+                  d,
+                  reservation.extent_start,
+                  reservation.nr_extents,
+                  reservation.extent_order,
+                  flags,
+                  &preempted);
+
+        if ( unlikely(reservation.domid != DOMID_SELF) )
+            put_domain(d);
+
+        rc += start_extent;
+
+        if ( preempted )
+            return hypercall2_create_continuation(
+                __HYPERVISOR_memory_op, op | (rc << START_EXTENT_SHIFT), arg);
+
+        break;
+
+    case XENMEM_maximum_ram_page:
+        if ( put_user(max_page, (unsigned long *)arg) )
+            return -EFAULT;
+        rc = 0;
+        break;
+
+    default:
+        rc = -ENOSYS;
+        break;
+    }
+
+    return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/shadow_ops.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/xen/include/asm-x86/shadow_ops.h  Fri Sep  9 16:30:54 2005
@@ -0,0 +1,130 @@
+/******************************************************************************
+ * include/asm-x86/shadow_ops.h
+ * 
+ * Copyright (c) 2005 Michael A Fetterman
+ * Based on an earlier implementation by Ian Pratt et al
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that 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
+ */
+
+#ifndef _XEN_SHADOW_OPS_H
+#define _XEN_SHADOW_OPS_H
+
+#if defined( GUEST_PGENTRY_32 )
+
+#define GUEST_L1_PAGETABLE_ENTRIES     L1_PAGETABLE_ENTRIES_32
+#define GUEST_L2_PAGETABLE_ENTRIES     L2_PAGETABLE_ENTRIES_32
+#define GUEST_ROOT_PAGETABLE_ENTRIES   ROOT_PAGETABLE_ENTRIES_32
+#define GUEST_L2_PAGETABLE_SHIFT       L2_PAGETABLE_SHIFT_32
+
+#define guest_l1_pgentry_t      l1_pgentry_32_t
+#define guest_l2_pgentry_t      l2_pgentry_32_t
+#define guest_root_pgentry_t    l2_pgentry_32_t
+
+#define guest_l1e_get_paddr     l1e_get_paddr_32
+#define guest_l2e_get_paddr     l2e_get_paddr_32
+
+#define guest_get_pte_flags     get_pte_flags_32
+#define guest_put_pte_flags     put_pte_flags_32
+
+#define guest_l1e_get_flags     l1e_get_flags_32
+#define guest_l2e_get_flags     l2e_get_flags_32
+#define guest_root_get_flags          l2e_get_flags_32
+#define guest_root_get_intpte         l2e_get_intpte
+
+#define guest_l1e_empty         l1e_empty_32
+#define guest_l2e_empty         l2e_empty_32
+
+#define guest_l1e_from_pfn      l1e_from_pfn_32
+#define guest_l2e_from_pfn      l2e_from_pfn_32
+
+#define guest_l1e_from_paddr    l1e_from_paddr_32
+#define guest_l2e_from_paddr    l2e_from_paddr_32
+
+#define guest_l1e_from_page     l1e_from_page_32
+#define guest_l2e_from_page     l2e_from_page_32
+
+#define guest_l1e_add_flags     l1e_add_flags_32
+#define guest_l2e_add_flags     l2e_add_flags_32
+
+#define guest_l1e_remove_flag   l1e_remove_flags_32
+#define guest_l2e_remove_flag   l2e_remove_flags_32
+
+#define guest_l1e_has_changed   l1e_has_changed_32
+#define guest_l2e_has_changed   l2e_has_changed_32
+#define root_entry_has_changed  l2e_has_changed_32
+
+#define guest_l1_table_offset   l1_table_offset_32
+#define guest_l2_table_offset   l2_table_offset_32
+
+#define guest_linear_l1_table   linear_pg_table_32
+#define guest_linear_l2_table   linear_l2_table_32
+
+#define guest_va_to_l1mfn       va_to_l1mfn_32
+
+#else
+
+#define GUEST_L1_PAGETABLE_ENTRIES      L1_PAGETABLE_ENTRIES
+#define GUEST_L2_PAGETABLE_ENTRIES      L2_PAGETABLE_ENTRIES
+#define GUEST_ROOT_PAGETABLE_ENTRIES    ROOT_PAGETABLE_ENTRIES
+#define GUEST_L2_PAGETABLE_SHIFT        L2_PAGETABLE_SHIFT
+
+#define guest_l1_pgentry_t      l1_pgentry_t
+#define guest_l2_pgentry_t      l2_pgentry_t
+#define guest_root_pgentry_t    l4_pgentry_t
+
+#define guest_l1e_get_paddr     l1e_get_paddr
+#define guest_l2e_get_paddr     l2e_get_paddr
+
+#define guest_get_pte_flags     get_pte_flags
+#define guest_put_pte_flags     put_pte_flags
+
+#define guest_l1e_get_flags     l1e_get_flags
+#define guest_l2e_get_flags     l2e_get_flags
+#define guest_root_get_flags    l4e_get_flags
+#define guest_root_get_intpte   l4e_get_intpte
+
+#define guest_l1e_empty         l1e_empty
+#define guest_l2e_empty         l2e_empty
+
+#define guest_l1e_from_pfn      l1e_from_pfn
+#define guest_l2e_from_pfn      l2e_from_pfn
+
+#define guest_l1e_from_paddr    l1e_from_paddr
+#define guest_l2e_from_paddr    l2e_from_paddr
+
+#define guest_l1e_from_page     l1e_from_page
+#define guest_l2e_from_page     l2e_from_page
+
+#define guest_l1e_add_flags     l1e_add_flags
+#define guest_l2e_add_flags     l2e_add_flags
+
+#define guest_l1e_remove_flag   l1e_remove_flags
+#define guest_l2e_remove_flag   l2e_remove_flags
+
+#define guest_l1e_has_changed   l1e_has_changed
+#define guest_l2e_has_changed   l2e_has_changed
+#define root_entry_has_changed  l4e_has_changed
+
+#define guest_l1_table_offset   l1_table_offset
+#define guest_l2_table_offset   l2_table_offset
+
+#define guest_linear_l1_table   linear_pg_table
+#define guest_linear_l2_table   linear_l2_table
+
+#define guest_va_to_l1mfn       va_to_l1mfn
+#endif
+
+#endif /* _XEN_SHADOW_OPS_H */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/io/tpmif.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/xen/include/public/io/tpmif.h     Fri Sep  9 16:30:54 2005
@@ -0,0 +1,42 @@
+/******************************************************************************
+ * tpmif.h
+ *
+ * TPM I/O interface for Xen guest OSes.
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@xxxxxxxxxx
+ * Grant table support: Mahadevan Gomathisankaran
+ *
+ * This code has been derived from tools/libxc/xen/io/netif.h
+ *
+ * Copyright (c) 2003-2004, Keir Fraser
+ */
+
+#ifndef __XEN_PUBLIC_IO_TPMIF_H__
+#define __XEN_PUBLIC_IO_TPMIF_H__
+
+typedef struct {
+    unsigned long addr;   /* Machine address of packet.   */
+    int      ref;         /* grant table access reference */
+    u16      id;          /* Echoed in response message.  */
+    u16      size:15;     /* Packet size in bytes.        */
+    u16      mapped:1;
+} tpmif_tx_request_t;
+
+/*
+ * The TPMIF_TX_RING_SIZE defines the number of pages the
+ * front-end and backend can exchange (= size of array).
+ */
+typedef u32 TPMIF_RING_IDX;
+
+#define TPMIF_TX_RING_SIZE 16
+
+/* This structure must fit in a memory page. */
+typedef struct {
+    union {
+        tpmif_tx_request_t  req;
+    } ring[TPMIF_TX_RING_SIZE];
+} tpmif_tx_interface_t;
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/memory.h
--- /dev/null   Thu Sep  8 15:18:40 2005
+++ b/xen/include/public/memory.h       Fri Sep  9 16:30:54 2005
@@ -0,0 +1,50 @@
+/******************************************************************************
+ * memory.h
+ * 
+ * Memory reservation and information.
+ * 
+ * Copyright (c) 2005, Keir Fraser <keir@xxxxxxxxxxxxx>
+ */
+
+#ifndef __XEN_PUBLIC_MEMORY_H__
+#define __XEN_PUBLIC_MEMORY_H__
+
+/* arg == addr of struct xen_memory_reservation. */
+#define XENMEM_increase_reservation 0
+
+/* arg == addr of struct xen_memory_reservation. */
+#define XENMEM_decrease_reservation 1
+
+/* arg == addr of unsigned long. */
+#define XENMEM_maximum_ram_page     2
+
+typedef struct xen_memory_reservation {
+
+    /*
+     * MFN bases of extents to free (XENMEM_decrease_reservation).
+     * MFN bases of extents that were allocated (XENMEM_increase_reservation).
+     */
+    unsigned long *extent_start;
+
+    /* Number of extents, and size/alignment of each (2^extent_order pages). */
+    unsigned long  nr_extents;
+    unsigned int   extent_order;
+
+    /*
+     * XENMEM_increase_reservation: maximum # bits addressable by the user
+     * of the allocated region (e.g., I/O devices often have a 32-bit
+     * limitation even in 64-bit systems). If zero then the user has no
+     * addressing restriction.
+     * XENMEM_decrease_reservation: unused.
+     */
+    unsigned int   address_bits;
+
+    /*
+     * Domain whose reservation is being changed.
+     * Unprivileged domains can specify only DOMID_SELF.
+     */
+    domid_t        domid;
+
+} xen_memory_reservation_t;
+
+#endif /* __XEN_PUBLIC_MEMORY_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/arch/xen/kernel/ctrl_if.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/ctrl_if.c    Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,569 +0,0 @@
-/******************************************************************************
- * ctrl_if.c
- * 
- * Management functions for special interface to the domain controller.
- * 
- * Copyright (c) 2004, K A Fraser
- * 
- * This file may be distributed separately from the Linux kernel, or
- * incorporated into other software packages, subject to the following license:
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this source file (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <asm-xen/ctrl_if.h>
-#include <asm-xen/evtchn.h>
-
-#if 0
-#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
-                           __FILE__ , __LINE__ , ## _a )
-#else
-#define DPRINTK(_f, _a...) ((void)0)
-#endif
-
-/*
- * Extra ring macros to sync a consumer index up to the public producer index. 
- * Generally UNSAFE, but we use it for recovery and shutdown in some cases.
- */
-#define RING_DROP_PENDING_REQUESTS(_r)                                  \
-    do {                                                                \
-        (_r)->req_cons = (_r)->sring->req_prod;                         \
-    } while (0)
-#define RING_DROP_PENDING_RESPONSES(_r)                                 \
-    do {                                                                \
-        (_r)->rsp_cons = (_r)->sring->rsp_prod;                         \
-    } while (0)
-
-/*
- * Only used by initial domain which must create its own control-interface
- * event channel. This value is picked up by the user-space domain controller
- * via an ioctl.
- */
-int initdom_ctrlif_domcontroller_port = -1;
-
-static int        ctrl_if_evtchn;
-static int        ctrl_if_irq;
-static spinlock_t ctrl_if_lock;
-
-static struct irqaction ctrl_if_irq_action;
-
-static ctrl_front_ring_t ctrl_if_tx_ring;
-static ctrl_back_ring_t  ctrl_if_rx_ring;
-
-/* Incoming message requests. */
-    /* Primary message type -> message handler. */
-static ctrl_msg_handler_t ctrl_if_rxmsg_handler[256];
-    /* Primary message type -> callback in process context? */
-static unsigned long ctrl_if_rxmsg_blocking_context[256/sizeof(unsigned long)];
-    /* Is it late enough during bootstrap to use schedule_task()? */
-static int safe_to_schedule_task;
-    /* Queue up messages to be handled in process context. */
-static ctrl_msg_t ctrl_if_rxmsg_deferred[CONTROL_RING_SIZE];
-static CONTROL_RING_IDX ctrl_if_rxmsg_deferred_prod;
-static CONTROL_RING_IDX ctrl_if_rxmsg_deferred_cons;
-
-/* Incoming message responses: message identifier -> message handler/id. */
-static struct {
-    ctrl_msg_handler_t fn;
-    unsigned long      id;
-} ctrl_if_txmsg_id_mapping[CONTROL_RING_SIZE];
-
-/* For received messages that must be deferred to process context. */
-static void __ctrl_if_rxmsg_deferred(void *unused);
-static DECLARE_WORK(ctrl_if_rxmsg_deferred_work,
-                    __ctrl_if_rxmsg_deferred,
-                    NULL);
-
-/* Deferred callbacks for people waiting for space in the transmit ring. */
-static DECLARE_TASK_QUEUE(ctrl_if_tx_tq);
-
-static DECLARE_WAIT_QUEUE_HEAD(ctrl_if_tx_wait);
-static void __ctrl_if_tx_tasklet(unsigned long data);
-static DECLARE_TASKLET(ctrl_if_tx_tasklet, __ctrl_if_tx_tasklet, 0);
-
-static void __ctrl_if_rx_tasklet(unsigned long data);
-static DECLARE_TASKLET(ctrl_if_rx_tasklet, __ctrl_if_rx_tasklet, 0);
-
-#define get_ctrl_if() ((control_if_t *)((char *)HYPERVISOR_shared_info + 2048))
-
-static void ctrl_if_notify_controller(void)
-{
-    notify_via_evtchn(ctrl_if_evtchn);
-}
-
-static void ctrl_if_rxmsg_default_handler(ctrl_msg_t *msg, unsigned long id)
-{
-    msg->length = 0;
-    ctrl_if_send_response(msg);
-}
-
-static void __ctrl_if_tx_tasklet(unsigned long data)
-{
-    ctrl_msg_t *msg;
-    int         was_full = RING_FULL(&ctrl_if_tx_ring);
-    RING_IDX    i, rp;
-
-    i  = ctrl_if_tx_ring.rsp_cons;
-    rp = ctrl_if_tx_ring.sring->rsp_prod;
-    rmb(); /* Ensure we see all requests up to 'rp'. */
-
-    for ( ; i != rp; i++ )
-    {
-        msg = RING_GET_RESPONSE(&ctrl_if_tx_ring, i);
-        
-        DPRINTK("Rx-Rsp %u/%u :: %d/%d\n", i-1,
-                ctrl_if_tx_ring.sring->rsp_prod,
-                msg->type, msg->subtype);
-
-        /* Execute the callback handler, if one was specified. */
-        if ( msg->id != 0xFF )
-        {
-            (*ctrl_if_txmsg_id_mapping[msg->id].fn)(
-                msg, ctrl_if_txmsg_id_mapping[msg->id].id);
-            smp_mb(); /* Execute, /then/ free. */
-            ctrl_if_txmsg_id_mapping[msg->id].fn = NULL;
-        }
-    }
-
-    /*
-     * Step over messages in the ring /after/ finishing reading them. As soon 
-     * as the index is updated then the message may get blown away.
-     */
-    smp_mb();
-    ctrl_if_tx_ring.rsp_cons = i;
-            
-    if ( was_full && !RING_FULL(&ctrl_if_tx_ring) )
-    {
-        wake_up(&ctrl_if_tx_wait);
-        run_task_queue(&ctrl_if_tx_tq);
-    }
-}
-
-static void __ctrl_if_rxmsg_deferred(void *unused)
-{
-    ctrl_msg_t *msg;
-    CONTROL_RING_IDX dp;
-
-    dp = ctrl_if_rxmsg_deferred_prod;
-    rmb(); /* Ensure we see all deferred requests up to 'dp'. */
-
-    while ( ctrl_if_rxmsg_deferred_cons != dp )
-    {
-        msg = &ctrl_if_rxmsg_deferred[MASK_CONTROL_IDX(
-            ctrl_if_rxmsg_deferred_cons++)];
-        (*ctrl_if_rxmsg_handler[msg->type])(msg, 0);
-    }
-}
-
-static void __ctrl_if_rx_tasklet(unsigned long data)
-{
-    ctrl_msg_t    msg, *pmsg;
-    CONTROL_RING_IDX dp;
-    RING_IDX rp, i;
-
-    i  = ctrl_if_rx_ring.req_cons;
-    rp = ctrl_if_rx_ring.sring->req_prod;
-    dp = ctrl_if_rxmsg_deferred_prod;
-    rmb(); /* Ensure we see all requests up to 'rp'. */
- 
-    for ( ; i != rp; i++) 
-    {
-        pmsg = RING_GET_REQUEST(&ctrl_if_rx_ring, i);
-        memcpy(&msg, pmsg, offsetof(ctrl_msg_t, msg));
-
-        DPRINTK("Rx-Req %u/%u :: %d/%d\n", i-1,
-                ctrl_if_rx_ring.sring->req_prod,
-                msg.type, msg.subtype);
-
-        if ( msg.length > sizeof(msg.msg) )
-            msg.length = sizeof(msg.msg);
-        
-        if ( msg.length != 0 )
-            memcpy(msg.msg, pmsg->msg, msg.length);
-
-        if ( test_bit(msg.type, 
-                      (unsigned long *)&ctrl_if_rxmsg_blocking_context) )
-            memcpy(&ctrl_if_rxmsg_deferred[MASK_CONTROL_IDX(dp++)],
-                   &msg, offsetof(ctrl_msg_t, msg) + msg.length);
-        else
-            (*ctrl_if_rxmsg_handler[msg.type])(&msg, 0);
-    }
-
-    ctrl_if_rx_ring.req_cons = i;
-
-    if ( dp != ctrl_if_rxmsg_deferred_prod )
-    {
-        wmb();
-        ctrl_if_rxmsg_deferred_prod = dp;
-        schedule_work(&ctrl_if_rxmsg_deferred_work);
-    }
-}
-
-static irqreturn_t ctrl_if_interrupt(int irq, void *dev_id,
-                                     struct pt_regs *regs)
-{
-    if ( RING_HAS_UNCONSUMED_RESPONSES(&ctrl_if_tx_ring) )
-        tasklet_schedule(&ctrl_if_tx_tasklet);
-
-    if ( RING_HAS_UNCONSUMED_REQUESTS(&ctrl_if_rx_ring) )
-        tasklet_schedule(&ctrl_if_rx_tasklet);
-
-    return IRQ_HANDLED;
-}
-
-int
-ctrl_if_send_message_noblock(
-    ctrl_msg_t *msg, 
-    ctrl_msg_handler_t hnd,
-    unsigned long id)
-{
-    unsigned long flags;
-    ctrl_msg_t   *dmsg;
-    int           i;
-
-    spin_lock_irqsave(&ctrl_if_lock, flags);
-
-    if ( RING_FULL(&ctrl_if_tx_ring) )
-    {
-        spin_unlock_irqrestore(&ctrl_if_lock, flags);
-        return -EAGAIN;
-    }
-
-    msg->id = 0xFF;
-    if ( hnd != NULL )
-    {
-        for ( i = 0; ctrl_if_txmsg_id_mapping[i].fn != NULL; i++ )
-            continue;
-        ctrl_if_txmsg_id_mapping[i].fn = hnd;
-        ctrl_if_txmsg_id_mapping[i].id = id;
-        msg->id = i;
-    }
-
-    DPRINTK("Tx-Req %u/%u :: %d/%d\n", 
-            ctrl_if_tx_ring.req_prod_pvt, 
-            ctrl_if_tx_ring.rsp_cons,
-            msg->type, msg->subtype);
-
-    dmsg = RING_GET_REQUEST(&ctrl_if_tx_ring, 
-            ctrl_if_tx_ring.req_prod_pvt);
-    memcpy(dmsg, msg, sizeof(*msg));
-    ctrl_if_tx_ring.req_prod_pvt++;
-    RING_PUSH_REQUESTS(&ctrl_if_tx_ring);
-
-    spin_unlock_irqrestore(&ctrl_if_lock, flags);
-
-    ctrl_if_notify_controller();
-
-    return 0;
-}
-
-int
-ctrl_if_send_message_block(
-    ctrl_msg_t *msg, 
-    ctrl_msg_handler_t hnd, 
-    unsigned long id,
-    long wait_state)
-{
-    DECLARE_WAITQUEUE(wait, current);
-    int rc;
-
-    /* Fast path. */
-    if ( (rc = ctrl_if_send_message_noblock(msg, hnd, id)) != -EAGAIN )
-        return rc;
-
-    add_wait_queue(&ctrl_if_tx_wait, &wait);
-
-    for ( ; ; )
-    {
-        set_current_state(wait_state);
-
-        if ( (rc = ctrl_if_send_message_noblock(msg, hnd, id)) != -EAGAIN )
-            break;
-
-        rc = -ERESTARTSYS;
-        if ( signal_pending(current) && (wait_state == TASK_INTERRUPTIBLE) )
-            break;
-
-        schedule();
-    }
-
-    set_current_state(TASK_RUNNING);
-    remove_wait_queue(&ctrl_if_tx_wait, &wait);
-
-    return rc;
-}
-
-/* Allow a reponse-callback handler to find context of a blocked requester.  */
-struct rsp_wait {
-    ctrl_msg_t         *msg;  /* Buffer for the response message.            */
-    struct task_struct *task; /* The task that is blocked on the response.   */
-    int                 done; /* Indicate to 'task' that response is rcv'ed. */
-};
-
-static void __ctrl_if_get_response(ctrl_msg_t *msg, unsigned long id)
-{
-    struct rsp_wait    *wait = (struct rsp_wait *)id;
-    struct task_struct *task = wait->task;
-
-    memcpy(wait->msg, msg, sizeof(*msg));
-    wmb();
-    wait->done = 1;
-
-    wake_up_process(task);
-}
-
-int
-ctrl_if_send_message_and_get_response(
-    ctrl_msg_t *msg, 
-    ctrl_msg_t *rmsg,
-    long wait_state)
-{
-    struct rsp_wait wait;
-    int rc;
-
-    wait.msg  = rmsg;
-    wait.done = 0;
-    wait.task = current;
-
-    if ( (rc = ctrl_if_send_message_block(msg, __ctrl_if_get_response,
-                                          (unsigned long)&wait,
-                                          wait_state)) != 0 )
-        return rc;
-
-    for ( ; ; )
-    {
-        /* NB. Can't easily support TASK_INTERRUPTIBLE here. */
-        set_current_state(TASK_UNINTERRUPTIBLE);
-        if ( wait.done )
-            break;
-        schedule();
-    }
-
-    set_current_state(TASK_RUNNING);
-    return 0;
-}
-
-int
-ctrl_if_enqueue_space_callback(
-    struct tq_struct *task)
-{
-    /* Fast path. */
-    if ( !RING_FULL(&ctrl_if_tx_ring) )
-        return 0;
-
-    (void)queue_task(task, &ctrl_if_tx_tq);
-
-    /*
-     * We may race execution of the task queue, so return re-checked status. If
-     * the task is not executed despite the ring being non-full then we will
-     * certainly return 'not full'.
-     */
-    smp_mb();
-    return RING_FULL(&ctrl_if_tx_ring);
-}
-
-void
-ctrl_if_send_response(
-    ctrl_msg_t *msg)
-{
-    unsigned long flags;
-    ctrl_msg_t   *dmsg;
-
-    /*
-     * NB. The response may the original request message, modified in-place.
-     * In this situation we may have src==dst, so no copying is required.
-     */
-    spin_lock_irqsave(&ctrl_if_lock, flags);
-
-    DPRINTK("Tx-Rsp %u :: %d/%d\n", 
-            ctrl_if_rx_ring.rsp_prod_pvt, 
-            msg->type, msg->subtype);
-
-    dmsg = RING_GET_RESPONSE(&ctrl_if_rx_ring, 
-            ctrl_if_rx_ring.rsp_prod_pvt);
-    if ( dmsg != msg )
-        memcpy(dmsg, msg, sizeof(*msg));
-
-    ctrl_if_rx_ring.rsp_prod_pvt++;
-    RING_PUSH_RESPONSES(&ctrl_if_rx_ring);
-
-    spin_unlock_irqrestore(&ctrl_if_lock, flags);
-
-    ctrl_if_notify_controller();
-}
-
-int
-ctrl_if_register_receiver(
-    u8 type, 
-    ctrl_msg_handler_t hnd, 
-    unsigned int flags)
-{
-    unsigned long _flags;
-    int inuse;
-
-    spin_lock_irqsave(&ctrl_if_lock, _flags);
-
-    inuse = (ctrl_if_rxmsg_handler[type] != ctrl_if_rxmsg_default_handler);
-
-    if ( inuse )
-    {
-        printk(KERN_INFO "Receiver %p already established for control "
-               "messages of type %d.\n", ctrl_if_rxmsg_handler[type], type);
-    }
-    else
-    {
-        ctrl_if_rxmsg_handler[type] = hnd;
-        clear_bit(type, (unsigned long *)&ctrl_if_rxmsg_blocking_context);
-        if ( flags == CALLBACK_IN_BLOCKING_CONTEXT )
-        {
-            set_bit(type, (unsigned long *)&ctrl_if_rxmsg_blocking_context);
-            if ( !safe_to_schedule_task )
-                BUG();
-        }
-    }
-
-    spin_unlock_irqrestore(&ctrl_if_lock, _flags);
-
-    return !inuse;
-}
-
-void 
-ctrl_if_unregister_receiver(
-    u8 type,
-    ctrl_msg_handler_t hnd)
-{
-    unsigned long flags;
-
-    spin_lock_irqsave(&ctrl_if_lock, flags);
-
-    if ( ctrl_if_rxmsg_handler[type] != hnd )
-        printk(KERN_INFO "Receiver %p is not registered for control "
-               "messages of type %d.\n", hnd, type);
-    else
-        ctrl_if_rxmsg_handler[type] = ctrl_if_rxmsg_default_handler;
-
-    spin_unlock_irqrestore(&ctrl_if_lock, flags);
-
-    /* Ensure that @hnd will not be executed after this function returns. */
-    tasklet_unlock_wait(&ctrl_if_rx_tasklet);
-}
-
-void ctrl_if_suspend(void)
-{
-    teardown_irq(ctrl_if_irq, &ctrl_if_irq_action);
-    unbind_evtchn_from_irq(ctrl_if_evtchn);
-}
-
-void ctrl_if_resume(void)
-{
-    control_if_t *ctrl_if = get_ctrl_if();
-
-    if ( xen_start_info.flags & SIF_INITDOMAIN )
-    {
-        /*
-         * The initial domain must create its own domain-controller link.
-         * The controller is probably not running at this point, but will
-         * pick up its end of the event channel from 
-         */
-        evtchn_op_t op;
-       extern void bind_evtchn_to_cpu(unsigned port, unsigned cpu);
-
-        op.cmd = EVTCHNOP_bind_interdomain;
-        op.u.bind_interdomain.dom1 = DOMID_SELF;
-        op.u.bind_interdomain.dom2 = DOMID_SELF;
-        op.u.bind_interdomain.port1 = 0;
-        op.u.bind_interdomain.port2 = 0;
-        if ( HYPERVISOR_event_channel_op(&op) != 0 )
-            BUG();
-        xen_start_info.domain_controller_evtchn = op.u.bind_interdomain.port1;
-        initdom_ctrlif_domcontroller_port   = op.u.bind_interdomain.port2;
-       bind_evtchn_to_cpu(op.u.bind_interdomain.port1, 0);
-    }
-
-    /* Sync up with shared indexes. */
-    FRONT_RING_ATTACH(&ctrl_if_tx_ring, &ctrl_if->tx_ring, CONTROL_RING_MEM);
-    BACK_RING_ATTACH(&ctrl_if_rx_ring, &ctrl_if->rx_ring, CONTROL_RING_MEM);
-
-    ctrl_if_evtchn = xen_start_info.domain_controller_evtchn;
-    ctrl_if_irq    = bind_evtchn_to_irq(ctrl_if_evtchn);
-
-    memset(&ctrl_if_irq_action, 0, sizeof(ctrl_if_irq_action));
-    ctrl_if_irq_action.handler = ctrl_if_interrupt;
-    ctrl_if_irq_action.name    = "ctrl-if";
-    (void)setup_irq(ctrl_if_irq, &ctrl_if_irq_action);
-}
-
-void __init ctrl_if_init(void)
-{
-    control_if_t *ctrl_if = get_ctrl_if();
-    int i;
-
-    for ( i = 0; i < 256; i++ )
-        ctrl_if_rxmsg_handler[i] = ctrl_if_rxmsg_default_handler;
-
-    FRONT_RING_ATTACH(&ctrl_if_tx_ring, &ctrl_if->tx_ring, CONTROL_RING_MEM);
-    BACK_RING_ATTACH(&ctrl_if_rx_ring, &ctrl_if->rx_ring, CONTROL_RING_MEM);
-    
-    spin_lock_init(&ctrl_if_lock);
-
-    ctrl_if_resume();
-}
-
-
-/* This is called after it is safe to call schedule_task(). */
-static int __init ctrl_if_late_setup(void)
-{
-    safe_to_schedule_task = 1;
-    return 0;
-}
-__initcall(ctrl_if_late_setup);
-
-
-/*
- * !! The following are DANGEROUS FUNCTIONS !!
- * Use with care [for example, see xencons_force_flush()].
- */
-
-int ctrl_if_transmitter_empty(void)
-{
-    return (ctrl_if_tx_ring.sring->req_prod == ctrl_if_tx_ring.rsp_cons);
-    
-}
-
-void ctrl_if_discard_responses(void)
-{
-    RING_DROP_PENDING_RESPONSES(&ctrl_if_tx_ring);
-}
-
-EXPORT_SYMBOL(ctrl_if_send_message_noblock);
-EXPORT_SYMBOL(ctrl_if_send_message_block);
-EXPORT_SYMBOL(ctrl_if_send_message_and_get_response);
-EXPORT_SYMBOL(ctrl_if_enqueue_space_callback);
-EXPORT_SYMBOL(ctrl_if_send_response);
-EXPORT_SYMBOL(ctrl_if_register_receiver);
-EXPORT_SYMBOL(ctrl_if_unregister_receiver);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c       Thu Sep 
 8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,573 +0,0 @@
-/******************************************************************************
- * blktap_controlmsg.c
- * 
- * XenLinux virtual block-device tap.
- * Control interfaces to the frontend and backend drivers.
- * 
- * Copyright (c) 2004, Andrew Warfield
- *
- */
- 
-#include "blktap.h"
-#include <asm-xen/evtchn.h>
-
-static char *blkif_state_name[] = {
-    [BLKIF_STATE_CLOSED]       = "closed",
-    [BLKIF_STATE_DISCONNECTED] = "disconnected",
-    [BLKIF_STATE_CONNECTED]    = "connected",
-};
-
-static char *blkif_status_name[] = {
-    [BLKIF_INTERFACE_STATUS_CLOSED]       = "closed",
-    [BLKIF_INTERFACE_STATUS_DISCONNECTED] = "disconnected",
-    [BLKIF_INTERFACE_STATUS_CONNECTED]    = "connected",
-    [BLKIF_INTERFACE_STATUS_CHANGED]      = "changed",
-};
-
-unsigned int blktap_be_state = BLKIF_STATE_CLOSED;
-unsigned int blktap_be_evtchn;
-
-/*-----[ Control Messages to/from Frontend VMs ]--------------------------*/
-
-#define BLKIF_HASHSZ 1024
-#define BLKIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(BLKIF_HASHSZ-1))
-
-static kmem_cache_t *blkif_cachep;
-static blkif_t      *blkif_hash[BLKIF_HASHSZ];
-
-blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle)
-{
-    blkif_t *blkif = blkif_hash[BLKIF_HASH(domid, handle)];
-    while ( (blkif != NULL) && 
-            ((blkif->domid != domid) || (blkif->handle != handle)) )
-        blkif = blkif->hash_next;
-    return blkif;
-}
-
-static void __blkif_disconnect_complete(void *arg)
-{
-    blkif_t              *blkif = (blkif_t *)arg;
-    ctrl_msg_t            cmsg;
-    blkif_be_disconnect_t disc;
-#ifdef CONFIG_XEN_BLKDEV_GRANT
-    struct gnttab_unmap_grant_ref op;
-#endif
-
-    /*
-     * These can't be done in blkif_disconnect() because at that point there
-     * may be outstanding requests at the disc whose asynchronous responses
-     * must still be notified to the remote driver.
-     */
-#ifdef CONFIG_XEN_BLKDEV_GRANT
-    op.host_addr = blkif->shmem_vaddr;
-    op.handle         = blkif->shmem_handle;
-    op.dev_bus_addr   = 0;
-    BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
-#endif
-    vfree(blkif->blk_ring.sring);
-
-    /* Construct the deferred response message. */
-    cmsg.type         = CMSG_BLKIF_BE;
-    cmsg.subtype      = CMSG_BLKIF_BE_DISCONNECT;
-    cmsg.id           = blkif->disconnect_rspid;
-    cmsg.length       = sizeof(blkif_be_disconnect_t);
-    disc.domid        = blkif->domid;
-    disc.blkif_handle = blkif->handle;
-    disc.status       = BLKIF_BE_STATUS_OKAY;
-    memcpy(cmsg.msg, &disc, sizeof(disc));
-
-    /*
-     * Make sure message is constructed /before/ status change, because
-     * after the status change the 'blkif' structure could be deallocated at
-     * any time. Also make sure we send the response /after/ status change,
-     * as otherwise a subsequent CONNECT request could spuriously fail if
-     * another CPU doesn't see the status change yet.
-     */
-    mb();
-    if ( blkif->status != DISCONNECTING )
-        BUG();
-    blkif->status = DISCONNECTED;
-    mb();
-
-    /* Send the successful response. */
-    ctrl_if_send_response(&cmsg);
-}
-
-void blkif_disconnect_complete(blkif_t *blkif)
-{
-    INIT_WORK(&blkif->work, __blkif_disconnect_complete, (void *)blkif);
-    schedule_work(&blkif->work);
-}
-
-void blkif_ptfe_create(blkif_be_create_t *create)
-{
-    blkif_t      *blkif, **pblkif;
-    domid_t       domid  = create->domid;
-    unsigned int  handle = create->blkif_handle;
-
-
-    /* May want to store info on the connecting domain here. */
-
-    DPRINTK("PT got BE_CREATE\n");
-
-    if ( (blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL)) == NULL )
-    {
-        WPRINTK("Could not create blkif: out of memory\n");
-        create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
-        return;
-    }
-
-    /* blkif struct init code from blkback.c */
-    memset(blkif, 0, sizeof(*blkif));
-    blkif->domid  = domid;
-    blkif->handle = handle;
-    blkif->status = DISCONNECTED;  
-    spin_lock_init(&blkif->blk_ring_lock);
-    atomic_set(&blkif->refcnt, 0);
-
-    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
-    while ( *pblkif != NULL )
-    {
-        if ( ((*pblkif)->domid == domid) && ((*pblkif)->handle == handle) )
-        {
-            WPRINTK("Could not create blkif: already exists\n");
-            create->status = BLKIF_BE_STATUS_INTERFACE_EXISTS;
-            kmem_cache_free(blkif_cachep, blkif);
-            return;
-        }
-        pblkif = &(*pblkif)->hash_next;
-    }
-
-    blkif->hash_next = *pblkif;
-    *pblkif = blkif;
-
-    create->status = BLKIF_BE_STATUS_OKAY;
-}
-
-
-void blkif_ptfe_destroy(blkif_be_destroy_t *destroy)
-{
-    /* Clear anything that we initialized above. */
-
-    domid_t       domid  = destroy->domid;
-    unsigned int  handle = destroy->blkif_handle;
-    blkif_t     **pblkif, *blkif;
-
-    DPRINTK("PT got BE_DESTROY\n");
-    
-    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
-    while ( (blkif = *pblkif) != NULL )
-    {
-        if ( (blkif->domid == domid) && (blkif->handle == handle) )
-        {
-            if ( blkif->status != DISCONNECTED )
-                goto still_connected;
-            goto destroy;
-        }
-        pblkif = &blkif->hash_next;
-    }
-
-    destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
-    return;
-
- still_connected:
-    destroy->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
-    return;
-
- destroy:
-    *pblkif = blkif->hash_next;
-    kmem_cache_free(blkif_cachep, blkif);
-    destroy->status = BLKIF_BE_STATUS_OKAY;
-}
-
-void blkif_ptfe_connect(blkif_be_connect_t *connect)
-{
-    domid_t        domid  = connect->domid;
-    unsigned int   handle = connect->blkif_handle;
-    unsigned int   evtchn = connect->evtchn;
-    unsigned long  shmem_frame = connect->shmem_frame;
-    struct vm_struct *vma;
-#ifdef CONFIG_XEN_BLKDEV_GRANT
-    int ref = connect->shmem_ref;
-#else
-    pgprot_t       prot;
-    int            error;
-#endif
-    blkif_t       *blkif;
-    blkif_sring_t *sring;
-
-    DPRINTK("PT got BE_CONNECT\n");
-
-    blkif = blkif_find_by_handle(domid, handle);
-    if ( unlikely(blkif == NULL) )
-    {
-        WPRINTK("blkif_connect attempted for non-existent blkif (%u,%u)\n", 
-                connect->domid, connect->blkif_handle); 
-        connect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
-        return;
-    }
-
-    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
-    {
-        connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
-        return;
-    }
-
-#ifndef CONFIG_XEN_BLKDEV_GRANT
-    prot = __pgprot(_KERNPG_TABLE);
-    error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr),
-                                    shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
-                                    prot, domid);
-    if ( error != 0 )
-    {
-        if ( error == -ENOMEM ) 
-            connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
-        else if ( error == -EFAULT )
-            connect->status = BLKIF_BE_STATUS_MAPPING_ERROR;
-        else
-            connect->status = BLKIF_BE_STATUS_ERROR;
-        vfree(vma->addr);
-        return;
-    }
-#else
-    { /* Map: Use the Grant table reference */
-        struct gnttab_map_grant_ref op;
-        op.host_addr = VMALLOC_VMADDR(vma->addr);
-        op.flags            = GNTMAP_host_map;
-        op.ref              = ref;
-        op.dom              = domid;
-       
-        BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
-       
-        handle = op.handle;
-       
-        if (op.handle < 0) {
-            DPRINTK(" Grant table operation failure !\n");
-            connect->status = BLKIF_BE_STATUS_MAPPING_ERROR;
-            vfree(vma->addr);
-            return;
-        }
-
-        blkif->shmem_ref = ref;
-        blkif->shmem_handle = handle;
-        blkif->shmem_vaddr = VMALLOC_VMADDR(vma->addr);
-    }
-#endif
-
-    if ( blkif->status != DISCONNECTED )
-    {
-        connect->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
-        vfree(vma->addr);
-        return;
-    }
-
-    sring = (blkif_sring_t *)vma->addr;
-    SHARED_RING_INIT(sring);
-    BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
-    
-    blkif->evtchn        = evtchn;
-    blkif->shmem_frame   = shmem_frame;
-    blkif->status        = CONNECTED;
-    blkif_get(blkif);
-
-    bind_evtchn_to_irqhandler(
-        evtchn, blkif_ptfe_int, 0, "blkif-pt-backend", blkif);
-
-    connect->status = BLKIF_BE_STATUS_OKAY;
-}
-
-int blkif_ptfe_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id)
-{
-    domid_t       domid  = disconnect->domid;
-    unsigned int  handle = disconnect->blkif_handle;
-    blkif_t      *blkif;
-
-    DPRINTK("PT got BE_DISCONNECT\n");
-    
-    blkif = blkif_find_by_handle(domid, handle);
-    if ( unlikely(blkif == NULL) )
-    {
-        WPRINTK("blkif_disconnect attempted for non-existent blkif"
-                " (%u,%u)\n", disconnect->domid, disconnect->blkif_handle); 
-        disconnect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
-        return 1; /* Caller will send response error message. */
-    }
-
-    if ( blkif->status == CONNECTED )
-    {
-        blkif->status = DISCONNECTING;
-        blkif->disconnect_rspid = rsp_id;
-        wmb(); /* Let other CPUs see the status change. */
-        unbind_evtchn_from_irqhandler(blkif->evtchn, blkif);
-        blkif_deschedule(blkif);
-        blkif_put(blkif);
-        return 0; /* Caller should not send response message. */
-    }
-
-    disconnect->status = BLKIF_BE_STATUS_OKAY;
-    return 1;
-}
-
-/*-----[ Control Messages to/from Backend VM ]----------------------------*/
-
-/* Tell the controller to bring up the interface. */
-static void blkif_ptbe_send_interface_connect(void)
-{
-    ctrl_msg_t cmsg = {
-        .type    = CMSG_BLKIF_FE,
-        .subtype = CMSG_BLKIF_FE_INTERFACE_CONNECT,
-        .length  = sizeof(blkif_fe_interface_connect_t),
-    };
-    blkif_fe_interface_connect_t *msg = (void*)cmsg.msg;
-    msg->handle      = 0;
-    msg->shmem_frame = virt_to_mfn(blktap_be_ring.sring);
-    
-    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
-
-static void blkif_ptbe_close(void)
-{
-}
-
-/* Move from CLOSED to DISCONNECTED state. */
-static void blkif_ptbe_disconnect(void)
-{
-    blkif_sring_t *sring;
-    
-    sring = (blkif_sring_t *)__get_free_page(GFP_KERNEL);
-    SHARED_RING_INIT(sring);
-    FRONT_RING_INIT(&blktap_be_ring, sring, PAGE_SIZE);
-    blktap_be_state  = BLKIF_STATE_DISCONNECTED;
-    DPRINTK("Blkif-Passthrough-BE is now DISCONNECTED.\n");
-    blkif_ptbe_send_interface_connect();
-}
-
-static void blkif_ptbe_connect(blkif_fe_interface_status_t *status)
-{
-    int err = 0;
-    
-    blktap_be_evtchn = status->evtchn;
-
-    err = bind_evtchn_to_irqhandler(
-        blktap_be_evtchn, blkif_ptbe_int, SA_SAMPLE_RANDOM, "blkif", NULL);
-    if ( err ) {
-       WPRINTK("blkfront bind_evtchn_to_irqhandler failed (%d)\n", err);
-        return;
-    } else {
-       /* transtion to connected in case we need to do a 
-           a partion probe on a whole disk */
-        blktap_be_state = BLKIF_STATE_CONNECTED;
-    }
-}
-
-static void unexpected(blkif_fe_interface_status_t *status)
-{
-    WPRINTK(" TAP: Unexpected blkif status %s in state %s\n", 
-           blkif_status_name[status->status],
-           blkif_state_name[blktap_be_state]);
-}
-
-static void blkif_ptbe_status(
-    blkif_fe_interface_status_t *status)
-{
-    if ( status->handle != 0 )
-    {
-        DPRINTK("Status change on unsupported blkif %d\n",
-               status->handle);
-        return;
-    }
-
-    DPRINTK("ptbe_status: got %s\n", blkif_status_name[status->status]);
-    
-    switch ( status->status )
-    {
-    case BLKIF_INTERFACE_STATUS_CLOSED:
-        switch ( blktap_be_state )
-        {
-        case BLKIF_STATE_CLOSED:
-            unexpected(status);
-            break;
-        case BLKIF_STATE_DISCONNECTED:
-        case BLKIF_STATE_CONNECTED:
-            unexpected(status);
-            blkif_ptbe_close();
-            break;
-        }
-        break;
-        
-    case BLKIF_INTERFACE_STATUS_DISCONNECTED:
-        switch ( blktap_be_state )
-        {
-        case BLKIF_STATE_CLOSED:
-            blkif_ptbe_disconnect();
-            break;
-        case BLKIF_STATE_DISCONNECTED:
-        case BLKIF_STATE_CONNECTED:
-            printk(KERN_ALERT "*** add recovery code to the tap driver. 
***\n");
-            unexpected(status);
-            break;
-        }
-        break;
-        
-    case BLKIF_INTERFACE_STATUS_CONNECTED:
-        switch ( blktap_be_state )
-        {
-        case BLKIF_STATE_CLOSED:
-            unexpected(status);
-            blkif_ptbe_disconnect();
-            blkif_ptbe_connect(status);
-            break;
-        case BLKIF_STATE_DISCONNECTED:
-            blkif_ptbe_connect(status);
-            break;
-        case BLKIF_STATE_CONNECTED:
-            unexpected(status);
-            blkif_ptbe_connect(status);
-            break;
-        }
-        break;
-
-   case BLKIF_INTERFACE_STATUS_CHANGED:
-        switch ( blktap_be_state )
-        {
-        case BLKIF_STATE_CLOSED:
-        case BLKIF_STATE_DISCONNECTED:
-            unexpected(status);
-            break;
-        case BLKIF_STATE_CONNECTED:
-            /* vbd_update(); */
-            /* tap doesn't really get state changes... */
-            unexpected(status);
-            break;
-        }
-       break;
-       
-    default:
-        DPRINTK("Status change to unknown value %d\n", status->status);
-        break;
-    }
-}
-
-/*-----[ All control messages enter here: ]-------------------------------*/
-
-void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
-{
-    switch ( msg->type )
-    {
-    case CMSG_BLKIF_FE:
-
-        switch ( msg->subtype )
-        {
-        case CMSG_BLKIF_FE_INTERFACE_STATUS:
-            blkif_ptbe_status((blkif_fe_interface_status_t *) &msg->msg[0]);
-            break;
-
-        default:
-            goto parse_error;
-        }
-
-        break;
-
-    case CMSG_BLKIF_BE:
-        
-        /* send a copy of the message to user if wanted */
-        
-        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
-             (blktap_mode & BLKTAP_MODE_COPY_FE) ) {
-            
-            blktap_write_ctrl_ring(msg);
-            blktap_kick_user();
-        }
-        
-        switch ( msg->subtype )
-        {
-        case CMSG_BLKIF_BE_CREATE:
-            blkif_ptfe_create((blkif_be_create_t *)&msg->msg[0]);
-            break; 
-        case CMSG_BLKIF_BE_DESTROY:
-            blkif_ptfe_destroy((blkif_be_destroy_t *)&msg->msg[0]);
-            break;        
-        case CMSG_BLKIF_BE_CONNECT:
-            blkif_ptfe_connect((blkif_be_connect_t *)&msg->msg[0]);
-            break;        
-        case CMSG_BLKIF_BE_DISCONNECT:
-            if ( !blkif_ptfe_disconnect((blkif_be_disconnect_t *)&msg->msg[0],
-                    msg->id) )
-                return;
-            break;        
-
-        /* We just ignore anything to do with vbds for now. */
-        
-        case CMSG_BLKIF_BE_VBD_CREATE:
-            DPRINTK("PT got VBD_CREATE\n");
-            ((blkif_be_vbd_create_t *)&msg->msg[0])->status 
-                = BLKIF_BE_STATUS_OKAY;
-            break;
-        case CMSG_BLKIF_BE_VBD_DESTROY:
-            DPRINTK("PT got VBD_DESTROY\n");
-            ((blkif_be_vbd_destroy_t *)&msg->msg[0])->status
-                = BLKIF_BE_STATUS_OKAY;
-            break;
-        default:
-            goto parse_error;
-        }
-
-        break;
-    }
-
-    ctrl_if_send_response(msg);
-    return;
-
- parse_error:
-    msg->length = 0;
-    ctrl_if_send_response(msg);
-}
-
-/*-----[ Initialization ]-------------------------------------------------*/
-
-void __init blkif_interface_init(void)
-{
-    blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t), 
-                                     0, 0, NULL, NULL);
-    memset(blkif_hash, 0, sizeof(blkif_hash));
-    
-    blktap_be_ring.sring = NULL;
-}
-
-
-
-/* Debug : print the current ring indices. */
-
-void print_fe_ring_idxs(void)
-{
-    int i;
-    blkif_t *blkif;
-            
-    WPRINTK("FE Rings: \n---------\n");
-    for ( i = 0; i < BLKIF_HASHSZ; i++) { 
-        blkif = blkif_hash[i];
-        while (blkif != NULL) {
-            if (blkif->status == DISCONNECTED) {
-                WPRINTK("(%2d,%2d) DISCONNECTED\n", 
-                   blkif->domid, blkif->handle);
-            } else if (blkif->status == DISCONNECTING) {
-                WPRINTK("(%2d,%2d) DISCONNECTING\n", 
-                   blkif->domid, blkif->handle);
-            } else if (blkif->blk_ring.sring == NULL) {
-                WPRINTK("(%2d,%2d) CONNECTED, but null sring!\n", 
-                   blkif->domid, blkif->handle);
-            } else {
-                blkif_get(blkif);
-                WPRINTK("(%2d,%2d): req_cons: %2d, rsp_prod_prv: %2d "
-                    "| req_prod: %2d, rsp_prod: %2d\n",
-                    blkif->domid, blkif->handle,
-                    blkif->blk_ring.req_cons,
-                    blkif->blk_ring.rsp_prod_pvt,
-                    blkif->blk_ring.sring->req_prod,
-                    blkif->blk_ring.sring->rsp_prod);
-                blkif_put(blkif);
-            } 
-            blkif = blkif->hash_next;
-        }
-    }
-}        
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/blktap/blktap_datapath.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap_datapath.c Thu Sep  8 
15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,449 +0,0 @@
-/******************************************************************************
- * blktap_datapath.c
- * 
- * XenLinux virtual block-device tap.
- * Block request routing data path.
- * 
- * Copyright (c) 2004, Andrew Warfield
- * -- see full header in blktap.c
- */
- 
-#include "blktap.h"
-#include <asm-xen/evtchn.h>
-
-/*-----[ The data paths ]-------------------------------------------------*/
-
-/* Connection to a single backend domain. */
-blkif_front_ring_t blktap_be_ring;
-
-/*-----[ Tracking active requests ]---------------------------------------*/
-
-/* this must be the same as MAX_PENDING_REQS in blkback.c */
-#define MAX_ACTIVE_REQS ((ACTIVE_RING_IDX)64U)
-
-active_req_t     active_reqs[MAX_ACTIVE_REQS];
-ACTIVE_RING_IDX  active_req_ring[MAX_ACTIVE_REQS];
-spinlock_t       active_req_lock = SPIN_LOCK_UNLOCKED;
-ACTIVE_RING_IDX  active_prod, active_cons;
-#define MASK_ACTIVE_IDX(_i) ((_i)&(MAX_ACTIVE_REQS-1))
-#define ACTIVE_IDX(_ar) (_ar - active_reqs)
-#define NR_ACTIVE_REQS (MAX_ACTIVE_REQS - active_prod + active_cons)
-
-inline active_req_t *get_active_req(void) 
-{
-    ACTIVE_RING_IDX idx;
-    active_req_t *ar;
-    unsigned long flags;
-        
-    ASSERT(active_cons != active_prod);   
-    
-    spin_lock_irqsave(&active_req_lock, flags);
-    idx =  active_req_ring[MASK_ACTIVE_IDX(active_cons++)];
-    ar = &active_reqs[idx];
-    spin_unlock_irqrestore(&active_req_lock, flags);
-    
-    return ar;
-}
-
-inline void free_active_req(active_req_t *ar) 
-{
-    unsigned long flags;
-        
-    spin_lock_irqsave(&active_req_lock, flags);
-    active_req_ring[MASK_ACTIVE_IDX(active_prod++)] = ACTIVE_IDX(ar);
-    spin_unlock_irqrestore(&active_req_lock, flags);
-}
-
-active_req_t *lookup_active_req(ACTIVE_RING_IDX idx)
-{
-    return &active_reqs[idx];   
-}
-
-void active_reqs_init(void)
-{
-    ACTIVE_RING_IDX i;
-    
-    active_cons = 0;
-    active_prod = MAX_ACTIVE_REQS;
-    memset(active_reqs, 0, sizeof(active_reqs));
-    for ( i = 0; i < MAX_ACTIVE_REQS; i++ )
-        active_req_ring[i] = i;
-}
-
-/* Requests passing through the tap to the backend hijack the id field
- * in the request message.  In it we put the AR index _AND_ the fe domid.
- * the domid is used by the backend to map the pages properly.
- */
-
-static inline unsigned long MAKE_ID(domid_t fe_dom, ACTIVE_RING_IDX idx)
-{
-    return ( (fe_dom << 16) | MASK_ACTIVE_IDX(idx) );
-}
-
-/*-----[ Ring helpers ]---------------------------------------------------*/
-
-static void maybe_trigger_blktap_schedule(void);
-
-inline int write_resp_to_fe_ring(blkif_t *blkif, blkif_response_t *rsp)
-{
-    blkif_response_t *resp_d;
-    active_req_t *ar;
-    
-    ar = &active_reqs[ID_TO_IDX(rsp->id)];
-    rsp->id = ar->id;
-            
-    resp_d = RING_GET_RESPONSE(&blkif->blk_ring,
-            blkif->blk_ring.rsp_prod_pvt);
-    memcpy(resp_d, rsp, sizeof(blkif_response_t));
-    wmb();
-    blkif->blk_ring.rsp_prod_pvt++;
-            
-    blkif_put(ar->blkif);
-    free_active_req(ar);
-    
-    return 0;
-}
-
-inline int write_req_to_be_ring(blkif_request_t *req)
-{
-    blkif_request_t *req_d;
-
-    if ( blktap_be_state != BLKIF_STATE_CONNECTED ) {
-        WPRINTK("Tap trying to access an unconnected backend!\n");
-        return 0;
-    }
-    
-    req_d = RING_GET_REQUEST(&blktap_be_ring,
-            blktap_be_ring.req_prod_pvt);
-    memcpy(req_d, req, sizeof(blkif_request_t));
-    wmb();
-    blktap_be_ring.req_prod_pvt++;
-            
-    return 0;
-}
-
-void kick_fe_domain(blkif_t *blkif) 
-{
-    RING_PUSH_RESPONSES(&blkif->blk_ring);
-    notify_via_evtchn(blkif->evtchn);
-    DPRINTK("notified FE(dom %u)\n", blkif->domid);
-
-    /* We just feed up a batch of request slots... */
-    maybe_trigger_blktap_schedule();
-    
-}
-
-void kick_be_domain(void)
-{
-    if ( blktap_be_state != BLKIF_STATE_CONNECTED ) 
-        return;
-    
-    wmb(); /* Ensure that the frontend can see the requests. */
-    RING_PUSH_REQUESTS(&blktap_be_ring);
-    notify_via_evtchn(blktap_be_evtchn);
-    DPRINTK("notified BE\n");
-}
-
-/*-----[ Data to/from Frontend (client) VMs ]-----------------------------*/
-
-/*-----[ Scheduler list maint -from blkback ]--- */
-
-static struct list_head blkio_schedule_list;
-static spinlock_t blkio_schedule_list_lock;
-
-static int __on_blkdev_list(blkif_t *blkif)
-{
-    return blkif->blkdev_list.next != NULL;
-}
-
-static void remove_from_blkdev_list(blkif_t *blkif)
-{
-    unsigned long flags;
-    if ( !__on_blkdev_list(blkif) ) return;
-    spin_lock_irqsave(&blkio_schedule_list_lock, flags);
-    if ( __on_blkdev_list(blkif) )
-    {
-        list_del(&blkif->blkdev_list);
-        blkif->blkdev_list.next = NULL;
-        blkif_put(blkif);
-    }
-    spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
-}
-
-static void add_to_blkdev_list_tail(blkif_t *blkif)
-{
-    unsigned long flags;
-    if ( __on_blkdev_list(blkif) ) return;
-    spin_lock_irqsave(&blkio_schedule_list_lock, flags);
-    if ( !__on_blkdev_list(blkif) && (blkif->status == CONNECTED) )
-    {
-        list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
-        blkif_get(blkif);
-    }
-    spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
-}
-
-
-/*-----[ Scheduler functions - from blkback ]--- */
-
-static DECLARE_WAIT_QUEUE_HEAD(blkio_schedule_wait);
-
-static int do_block_io_op(blkif_t *blkif, int max_to_do);
-
-static int blkio_schedule(void *arg)
-{
-    DECLARE_WAITQUEUE(wq, current);
-
-    blkif_t          *blkif;
-    struct list_head *ent;
-
-    daemonize(
-        "xentapd"
-        );
-
-    for ( ; ; )
-    {
-        /* Wait for work to do. */
-        add_wait_queue(&blkio_schedule_wait, &wq);
-        set_current_state(TASK_INTERRUPTIBLE);
-        if ( (NR_ACTIVE_REQS == MAX_ACTIVE_REQS) || 
-             list_empty(&blkio_schedule_list) )
-            schedule();
-        __set_current_state(TASK_RUNNING);
-        remove_wait_queue(&blkio_schedule_wait, &wq);
-
-        /* Queue up a batch of requests. */
-        while ( (NR_ACTIVE_REQS < MAX_ACTIVE_REQS) &&
-                !list_empty(&blkio_schedule_list) )
-        {
-            ent = blkio_schedule_list.next;
-            blkif = list_entry(ent, blkif_t, blkdev_list);
-            blkif_get(blkif);
-            remove_from_blkdev_list(blkif);
-            if ( do_block_io_op(blkif, BATCH_PER_DOMAIN) )
-                add_to_blkdev_list_tail(blkif);
-            blkif_put(blkif);
-        }
-    }
-}
-
-static void maybe_trigger_blktap_schedule(void)
-{
-    /*
-     * Needed so that two processes, who together make the following predicate
-     * true, don't both read stale values and evaluate the predicate
-     * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
-     */
-    smp_mb();
-
-    if ( (NR_ACTIVE_REQS < (MAX_ACTIVE_REQS/2)) &&
-         !list_empty(&blkio_schedule_list) ) 
-        wake_up(&blkio_schedule_wait);
-}
-
-void blkif_deschedule(blkif_t *blkif)
-{
-    remove_from_blkdev_list(blkif);
-}
-
-void __init blkdev_schedule_init(void)
-{
-    spin_lock_init(&blkio_schedule_list_lock);
-    INIT_LIST_HEAD(&blkio_schedule_list);
-
-    if ( kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
-        BUG();
-}
-    
-/*-----[ Interrupt entry from a frontend ]------ */
-
-irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs)
-{
-    blkif_t *blkif = dev_id;
-
-    add_to_blkdev_list_tail(blkif);
-    maybe_trigger_blktap_schedule();
-    return IRQ_HANDLED;
-}
-
-/*-----[ Other Frontend Ring functions ]-------- */
-
-/* irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs)*/
-static int do_block_io_op(blkif_t *blkif, int max_to_do)
-{
-    /* we have pending messages from the real frontend. */
-
-    blkif_request_t *req_s;
-    RING_IDX i, rp;
-    unsigned long flags;
-    active_req_t *ar;
-    int more_to_do = 0;
-    int notify_be = 0, notify_user = 0;
-    
-    /* lock both rings */
-    spin_lock_irqsave(&blkif_io_lock, flags);
-
-    rp = blkif->blk_ring.sring->req_prod;
-    rmb();
-    
-    for ( i = blkif->blk_ring.req_cons; 
-         (i != rp) && 
-            !RING_REQUEST_CONS_OVERFLOW(&blkif->blk_ring, i);
-          i++ )
-    {
-        
-        if ((--max_to_do == 0) || (NR_ACTIVE_REQS == MAX_ACTIVE_REQS)) 
-        {
-            more_to_do = 1;
-            break;
-        }
-        
-        req_s = RING_GET_REQUEST(&blkif->blk_ring, i);
-        /* This is a new request:  
-         * Assign an active request record, and remap the id. 
-         */
-        ar = get_active_req();
-        ar->id = req_s->id;
-        ar->nr_pages = req_s->nr_segments; 
-        blkif_get(blkif);
-        ar->blkif = blkif;
-        req_s->id = MAKE_ID(blkif->domid, ACTIVE_IDX(ar));
-        /* WPRINTK("%3u < %3lu\n", ID_TO_IDX(req_s->id), ar->id); */
-
-        /* FE -> BE interposition point is here. */
-        
-        /* ------------------------------------------------------------- */
-        /* BLKIF_OP_PROBE_HACK:                                          */
-        /* Signal to the backend that we are a tap domain.               */
-
-        if (req_s->operation == BLKIF_OP_PROBE) {
-            DPRINTK("Adding BLKTAP_COOKIE to PROBE request.\n");
-            req_s->frame_and_sects[1] = BLKTAP_COOKIE;
-        }
-
-        /* ------------------------------------------------------------- */
-
-        /* If we are in MODE_INTERCEPT_FE or MODE_COPY_FE: */
-        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
-             (blktap_mode & BLKTAP_MODE_COPY_FE) ) {
-            
-            /* Copy the response message to UFERing */
-            /* In MODE_INTERCEPT_FE, map attached pages into the app vma */
-            /* In MODE_COPY_FE_PAGES, copy attached pages into the app vma */
-
-            DPRINTK("req->UFERing\n"); 
-            blktap_write_fe_ring(req_s);
-            notify_user = 1;
-        }
-
-        /* If we are not in MODE_INTERCEPT_FE or MODE_INTERCEPT_BE: */
-        if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
-               (blktap_mode & BLKTAP_MODE_INTERCEPT_BE)) ) {
-            
-            /* be included to prevent noise from the fe when its off */
-            /* copy the request message to the BERing */
-
-            DPRINTK("blktap: FERing[%u] -> BERing[%u]\n", 
-                    (unsigned)i & (RING_SIZE(&blktap_be_ring)-1),
-                    (unsigned)blktap_be_ring.req_prod_pvt & 
-                    (RING_SIZE((&blktap_be_ring)-1)));
-            
-            write_req_to_be_ring(req_s);
-            notify_be = 1;
-        }
-    }
-
-    blkif->blk_ring.req_cons = i;
-    
-    /* unlock rings */
-    spin_unlock_irqrestore(&blkif_io_lock, flags);
-    
-    if (notify_user)
-        blktap_kick_user();
-    if (notify_be)
-        kick_be_domain();
-    
-    return more_to_do;
-}
-
-/*-----[ Data to/from Backend (server) VM ]------------------------------*/
-
-
-irqreturn_t blkif_ptbe_int(int irq, void *dev_id, 
-                                  struct pt_regs *ptregs)
-{
-    blkif_response_t  *resp_s;
-    blkif_t *blkif;
-    RING_IDX rp, i;
-    unsigned long flags;
-
-    DPRINTK("PT got BE interrupt.\n");
-
-    /* lock both rings */
-    spin_lock_irqsave(&blkif_io_lock, flags);
-    
-    rp = blktap_be_ring.sring->rsp_prod;
-    rmb();
-      
-    for ( i = blktap_be_ring.rsp_cons; i != rp; i++)
-    {
-        resp_s = RING_GET_RESPONSE(&blktap_be_ring, i);
-        
-        /* BE -> FE interposition point is here. */
-    
-        blkif = active_reqs[ID_TO_IDX(resp_s->id)].blkif;
-        
-        /* If we are in MODE_INTERCEPT_BE or MODE_COPY_BE: */
-        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
-             (blktap_mode & BLKTAP_MODE_COPY_BE) ) {
-
-            /* Copy the response message to UBERing */
-            /* In MODE_INTERCEPT_BE, map attached pages into the app vma */
-            /* In MODE_COPY_BE_PAGES, copy attached pages into the app vma */
-
-            DPRINTK("rsp->UBERing\n"); 
-            blktap_write_be_ring(resp_s);
-            blktap_kick_user();
-
-        }
-       
-        /* If we are NOT in MODE_INTERCEPT_BE or MODE_INTERCEPT_FE: */
-        if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
-               (blktap_mode & BLKTAP_MODE_INTERCEPT_FE)) ) {
-            
-            /* (fe included to prevent random interference from the BE) */
-            /* Copy the response message to FERing */
-         
-            DPRINTK("blktap: BERing[%u] -> FERing[%u]\n", 
-                    (unsigned)i & (RING_SIZE(&blkif->blk_ring)-1),
-                    (unsigned)blkif->blk_ring.rsp_prod_pvt & 
-                    (RING_SIZE((&blkif->blk_ring)-1)));
-
-            write_resp_to_fe_ring(blkif, resp_s);
-            kick_fe_domain(blkif);
-
-        }
-    }
-    
-    blktap_be_ring.rsp_cons = i;
-    
-
-    spin_unlock_irqrestore(&blkif_io_lock, flags);
-    
-    return IRQ_HANDLED;
-}
-
-/* Debug : print the current ring indices. */
-
-void print_be_ring_idxs(void)
-{
-    if (blktap_be_ring.sring != NULL) {
-        WPRINTK("BE Ring: \n--------\n");
-        WPRINTK("BE: rsp_cons: %2d, req_prod_prv: %2d "
-            "| req_prod: %2d, rsp_prod: %2d\n",
-            blktap_be_ring.rsp_cons,
-            blktap_be_ring.req_prod_pvt,
-            blktap_be_ring.sring->req_prod,
-            blktap_be_ring.sring->rsp_prod);
-    }
-}        
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/drivers/xen/blktap/blktap_userdev.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap_userdev.c  Thu Sep  8 
15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,801 +0,0 @@
-/******************************************************************************
- * blktap_userdev.c
- * 
- * XenLinux virtual block-device tap.
- * Control interface between the driver and a character device.
- * 
- * Copyright (c) 2004, Andrew Warfield
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/miscdevice.h>
-#include <linux/errno.h>
-#include <linux/major.h>
-#include <linux/gfp.h>
-#include <linux/poll.h>
-#include <asm/pgalloc.h>
-#include <asm/tlbflush.h>
-#include <asm-xen/xen-public/io/blkif.h> /* for control ring. */
-#ifdef CONFIG_XEN_BLKDEV_GRANT
-#include <asm-xen/xen-public/grant_table.h>
-#endif
-
-#include "blktap.h"
-
-
-unsigned long blktap_mode = BLKTAP_MODE_PASSTHROUGH;
-
-/* Only one process may open /dev/xen/blktap at any time. */
-static unsigned long blktap_dev_inuse;
-unsigned long blktap_ring_ok; /* make this ring->state */
-
-/* for poll: */
-static wait_queue_head_t blktap_wait;
-
-/* Rings up to user space. */
-static blkif_front_ring_t blktap_ufe_ring;
-static blkif_back_ring_t  blktap_ube_ring;
-static ctrl_front_ring_t  blktap_uctrl_ring;
-
-/* local prototypes */
-static int blktap_read_fe_ring(void);
-static int blktap_read_be_ring(void);
-
-
-/* -------[ mmap region ]--------------------------------------------- */
-/*
- * We use a big chunk of address space to map in-flight requests into,
- * and export this region up to user-space.  See the comments in blkback
- * about this -- the two must be kept in sync if the tap is used as a 
- * passthrough.
- */
-
-#define MAX_PENDING_REQS 64
-
-/* immediately before the mmap area, we have a bunch of pages reserved
- * for shared memory rings.
- */
-#define RING_PAGES 3 /* Ctrl, Front, and Back */ 
-
-/* Where things are inside the device mapping. */
-struct vm_area_struct *blktap_vma = NULL;
-unsigned long mmap_vstart;  /* Kernel pages for mapping in data. */
-unsigned long rings_vstart; /* start of mmaped vma               */
-unsigned long user_vstart;  /* start of user mappings            */
-
-#define MMAP_PAGES_PER_REQUEST \
-    (BLKIF_MAX_SEGMENTS_PER_REQUEST + 1)
-#define MMAP_PAGES             \
-    (MAX_PENDING_REQS * MMAP_PAGES_PER_REQUEST)
-#define MMAP_VADDR(_start, _req,_seg)                \
-    ( _start +                                       \
-     ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \
-     ((_seg) * PAGE_SIZE))
-
-/* -------[ grant handles ]------------------------------------------- */
-
-#ifdef CONFIG_XEN_BLKDEV_GRANT
-/* When using grant tables to map a frame for device access then the
- * handle returned must be used to unmap the frame. This is needed to
- * drop the ref count on the frame.
- */
-struct grant_handle_pair
-{
-    u16  kernel;
-    u16  user;
-};
-static struct grant_handle_pair pending_grant_handles[MMAP_PAGES];
-#define pending_handle(_idx, _i) \
-    (pending_grant_handles[((_idx) * BLKIF_MAX_SEGMENTS_PER_REQUEST) + (_i)])
-#define BLKTAP_INVALID_HANDLE(_g) \
-    (((_g->kernel) == 0xFFFF) && ((_g->user) == 0xFFFF))
-#define BLKTAP_INVALIDATE_HANDLE(_g) do {       \
-    (_g)->kernel = 0xFFFF; (_g)->user = 0xFFFF; \
-    } while(0)
-    
-#endif
-
-
-/* -------[ blktap vm ops ]------------------------------------------- */
-
-static struct page *blktap_nopage(struct vm_area_struct *vma,
-                                             unsigned long address,
-                                             int *type)
-{
-    /*
-     * if the page has not been mapped in by the driver then generate
-     * a SIGBUS to the domain.
-     */
-
-    force_sig(SIGBUS, current);
-
-    return 0;
-}
-
-struct vm_operations_struct blktap_vm_ops = {
-    nopage:   blktap_nopage,
-};
-
-/* -------[ blktap file ops ]----------------------------------------- */
-
-static int blktap_open(struct inode *inode, struct file *filp)
-{
-    blkif_sring_t *sring;
-    ctrl_sring_t *csring;
-    
-    if ( test_and_set_bit(0, &blktap_dev_inuse) )
-        return -EBUSY;
-    
-    /* Allocate the ctrl ring. */
-    csring = (ctrl_sring_t *)get_zeroed_page(GFP_KERNEL);
-    if (csring == NULL)
-        goto fail_nomem;
-
-    SetPageReserved(virt_to_page(csring));
-    
-    SHARED_RING_INIT(csring);
-    FRONT_RING_INIT(&blktap_uctrl_ring, csring, PAGE_SIZE);
-
-    /* Allocate the fe ring. */
-    sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
-    if (sring == NULL)
-        goto fail_free_ctrl;
-
-    SetPageReserved(virt_to_page(sring));
-    
-    SHARED_RING_INIT(sring);
-    FRONT_RING_INIT(&blktap_ufe_ring, sring, PAGE_SIZE);
-
-    /* Allocate the be ring. */
-    sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
-    if (sring == NULL)
-        goto fail_free_fe;
-
-    SetPageReserved(virt_to_page(sring));
-    
-    SHARED_RING_INIT(sring);
-    BACK_RING_INIT(&blktap_ube_ring, sring, PAGE_SIZE);
-
-    DPRINTK(KERN_ALERT "blktap open.\n");
-
-    return 0;
-    
- fail_free_ctrl:
-    free_page( (unsigned long) blktap_uctrl_ring.sring);
-
- fail_free_fe:
-    free_page( (unsigned long) blktap_ufe_ring.sring);
-
- fail_nomem:
-    return -ENOMEM;
-}
-
-static int blktap_release(struct inode *inode, struct file *filp)
-{
-    blktap_dev_inuse = 0;
-    blktap_ring_ok = 0;
-
-    DPRINTK(KERN_ALERT "blktap closed.\n");
-
-    /* Free the ring page. */
-    ClearPageReserved(virt_to_page(blktap_uctrl_ring.sring));
-    free_page((unsigned long) blktap_uctrl_ring.sring);
-
-    ClearPageReserved(virt_to_page(blktap_ufe_ring.sring));
-    free_page((unsigned long) blktap_ufe_ring.sring);
-
-    ClearPageReserved(virt_to_page(blktap_ube_ring.sring));
-    free_page((unsigned long) blktap_ube_ring.sring);
-
-    /* Clear any active mappings and free foreign map table */
-    if (blktap_vma != NULL) {
-        zap_page_range(blktap_vma, blktap_vma->vm_start, 
-                       blktap_vma->vm_end - blktap_vma->vm_start, NULL);
-        blktap_vma = NULL;
-    }
-
-    return 0;
-}
-
-/* Note on mmap:
- * We need to map pages to user space in a way that will allow the block
- * subsystem set up direct IO to them.  This couldn't be done before, because
- * there isn't really a sane way to make a user virtual address down to a 
- * physical address when the page belongs to another domain.
- *
- * My first approach was to map the page in to kernel memory, add an entry
- * for it in the physical frame list (using alloc_lomem_region as in blkback)
- * and then attempt to map that page up to user space.  This is disallowed
- * by xen though, which realizes that we don't really own the machine frame
- * underlying the physical page.
- *
- * The new approach is to provide explicit support for this in xen linux.
- * The VMA now has a flag, VM_FOREIGN, to indicate that it contains pages
- * mapped from other vms.  vma->vm_private_data is set up as a mapping 
- * from pages to actual page structs.  There is a new clause in get_user_pages
- * that does the right thing for this sort of mapping.
- * 
- * blktap_mmap sets up this mapping.  Most of the real work is done in
- * blktap_write_fe_ring below.
- */
-static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-    int size;
-    struct page **map;
-    int i;
-
-    DPRINTK(KERN_ALERT "blktap mmap (%lx, %lx)\n",
-           vma->vm_start, vma->vm_end);
-
-    vma->vm_flags |= VM_RESERVED;
-    vma->vm_ops = &blktap_vm_ops;
-
-    size = vma->vm_end - vma->vm_start;
-    if ( size != ( (MMAP_PAGES + RING_PAGES) << PAGE_SHIFT ) ) {
-        printk(KERN_INFO 
-               "blktap: you _must_ map exactly %d pages!\n",
-               MMAP_PAGES + RING_PAGES);
-        return -EAGAIN;
-    }
-
-    size >>= PAGE_SHIFT;
-    DPRINTK(KERN_INFO "blktap: 2 rings + %d pages.\n", size-1);
-    
-    rings_vstart = vma->vm_start;
-    user_vstart  = rings_vstart + (RING_PAGES << PAGE_SHIFT);
-    
-    /* Map the ring pages to the start of the region and reserve it. */
-
-    /* not sure if I really need to do this... */
-    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-    DPRINTK("Mapping ctrl_ring page %lx.\n", __pa(blktap_uctrl_ring.sring));
-    if (remap_pfn_range(vma, vma->vm_start, 
-                         __pa(blktap_uctrl_ring.sring) >> PAGE_SHIFT, 
-                         PAGE_SIZE, vma->vm_page_prot)) 
-        goto fail;
-
-
-    DPRINTK("Mapping be_ring page %lx.\n", __pa(blktap_ube_ring.sring));
-    if (remap_pfn_range(vma, vma->vm_start + PAGE_SIZE, 
-                         __pa(blktap_ube_ring.sring) >> PAGE_SHIFT, 
-                         PAGE_SIZE, vma->vm_page_prot)) 
-        goto fail;
-
-    DPRINTK("Mapping fe_ring page %lx.\n", __pa(blktap_ufe_ring.sring));
-    if (remap_pfn_range(vma, vma->vm_start + ( 2 * PAGE_SIZE ), 
-                         __pa(blktap_ufe_ring.sring) >> PAGE_SHIFT, 
-                         PAGE_SIZE, vma->vm_page_prot)) 
-        goto fail;
-
-    /* Mark this VM as containing foreign pages, and set up mappings. */
-    map = kmalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT)
-                  * sizeof(struct page_struct*),
-                  GFP_KERNEL);
-    if (map == NULL) goto fail;
-
-    for (i=0; i<((vma->vm_end - vma->vm_start) >> PAGE_SHIFT); i++)
-        map[i] = NULL;
-    
-    vma->vm_private_data = map;
-    vma->vm_flags |= VM_FOREIGN;
-
-    blktap_vma = vma;
-    blktap_ring_ok = 1;
-
-    return 0;
- fail:
-    /* Clear any active mappings. */
-    zap_page_range(vma, vma->vm_start, 
-                   vma->vm_end - vma->vm_start, NULL);
-
-    return -ENOMEM;
-}
-
-static int blktap_ioctl(struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg)
-{
-    switch(cmd) {
-    case BLKTAP_IOCTL_KICK_FE: /* There are fe messages to process. */
-        return blktap_read_fe_ring();
-
-    case BLKTAP_IOCTL_KICK_BE: /* There are be messages to process. */
-        return blktap_read_be_ring();
-
-    case BLKTAP_IOCTL_SETMODE:
-        if (BLKTAP_MODE_VALID(arg)) {
-            blktap_mode = arg;
-            /* XXX: may need to flush rings here. */
-            printk(KERN_INFO "blktap: set mode to %lx\n", arg);
-            return 0;
-        }
-    case BLKTAP_IOCTL_PRINT_IDXS:
-        {
-            print_be_ring_idxs();
-            print_fe_ring_idxs();
-            WPRINTK("User Rings: \n-----------\n");
-            WPRINTK("UF: rsp_cons: %2d, req_prod_prv: %2d "
-                            "| req_prod: %2d, rsp_prod: %2d\n",
-                            blktap_ufe_ring.rsp_cons,
-                            blktap_ufe_ring.req_prod_pvt,
-                            blktap_ufe_ring.sring->req_prod,
-                            blktap_ufe_ring.sring->rsp_prod);
-            WPRINTK("UB: req_cons: %2d, rsp_prod_prv: %2d "
-                            "| req_prod: %2d, rsp_prod: %2d\n",
-                            blktap_ube_ring.req_cons,
-                            blktap_ube_ring.rsp_prod_pvt,
-                            blktap_ube_ring.sring->req_prod,
-                            blktap_ube_ring.sring->rsp_prod);
-            
-        }
-    }
-    return -ENOIOCTLCMD;
-}
-
-static unsigned int blktap_poll(struct file *file, poll_table *wait)
-{
-        poll_wait(file, &blktap_wait, wait);
-
-        if ( RING_HAS_UNPUSHED_REQUESTS(&blktap_uctrl_ring) ||
-             RING_HAS_UNPUSHED_REQUESTS(&blktap_ufe_ring)   ||
-             RING_HAS_UNPUSHED_RESPONSES(&blktap_ube_ring) ) {
-
-            flush_tlb_all();
-
-            RING_PUSH_REQUESTS(&blktap_uctrl_ring);
-            RING_PUSH_REQUESTS(&blktap_ufe_ring);
-            RING_PUSH_RESPONSES(&blktap_ube_ring);
-            return POLLIN | POLLRDNORM;
-        }
-
-        return 0;
-}
-
-void blktap_kick_user(void)
-{
-    /* blktap_ring->req_prod = blktap_req_prod; */
-    wake_up_interruptible(&blktap_wait);
-}
-
-static struct file_operations blktap_fops = {
-    owner:    THIS_MODULE,
-    poll:     blktap_poll,
-    ioctl:    blktap_ioctl,
-    open:     blktap_open,
-    release:  blktap_release,
-    mmap:     blktap_mmap,
-};
-    
-/*-----[ Data to/from user space ]----------------------------------------*/
-
-static void fast_flush_area(int idx, int nr_pages)
-{
-#ifdef CONFIG_XEN_BLKDEV_GRANT
-    struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
-    unsigned int i, op = 0;
-    struct grant_handle_pair *handle;
-    unsigned long ptep;
-
-    for (i=0; i<nr_pages; i++)
-    {
-        handle = &pending_handle(idx, i);
-        if (!BLKTAP_INVALID_HANDLE(handle))
-        {
-
-            unmap[op].host_addr = MMAP_VADDR(mmap_vstart, idx, i);
-            unmap[op].dev_bus_addr = 0;
-            unmap[op].handle = handle->kernel;
-            op++;
-
-            if (create_lookup_pte_addr(blktap_vma->vm_mm,
-                                       MMAP_VADDR(user_vstart, idx, i), 
-                                       &ptep) !=0) {
-                DPRINTK("Couldn't get a pte addr!\n");
-                return;
-            }
-            unmap[op].host_addr    = ptep;
-            unmap[op].dev_bus_addr = 0;
-            unmap[op].handle       = handle->user;
-            op++;
-            
-            BLKTAP_INVALIDATE_HANDLE(handle);
-        }
-    }
-    if ( unlikely(HYPERVISOR_grant_table_op(
-        GNTTABOP_unmap_grant_ref, unmap, op)))
-        BUG();
-#else
-    multicall_entry_t mcl[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-    int               i;
-
-    for ( i = 0; i < nr_pages; i++ )
-    {
-        MULTI_update_va_mapping(mcl+i, MMAP_VADDR(mmap_vstart, idx, i),
-                                __pte(0), 0);
-    }
-
-    mcl[nr_pages-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
-    if ( unlikely(HYPERVISOR_multicall(mcl, nr_pages) != 0) )
-        BUG();
-#endif
-}
-
-
-int blktap_write_fe_ring(blkif_request_t *req)
-{
-    blkif_request_t *target;
-    int i, ret = 0;
-#ifdef CONFIG_XEN_BLKDEV_GRANT
-    struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
-    int op;
-#else
-    unsigned long remap_prot;
-    multicall_entry_t mcl[BLKIF_MAX_SEGMENTS_PER_REQUEST+1];
-    mmu_update_t mmu[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-#endif
-
-    /*
-     * This is called to pass a request from the real frontend domain's
-     * blkif ring to the character device.
-     */
-
-    if ( ! blktap_ring_ok ) {
-        DPRINTK("blktap: ufe_ring not ready for a request!\n");
-        return 0;
-    }
-
-    if ( RING_FULL(&blktap_ufe_ring) ) {
-        PRINTK("blktap: fe_ring is full, can't add.\n");
-        return 0;
-    }
-
-    flush_cache_all(); /* a noop on intel... */
-
-    target = RING_GET_REQUEST(&blktap_ufe_ring, blktap_ufe_ring.req_prod_pvt);
-    memcpy(target, req, sizeof(*req));
-
-    /* Map the foreign pages directly in to the application */
-#ifdef CONFIG_XEN_BLKDEV_GRANT
-    op = 0;
-    for (i=0; i<target->nr_segments; i++) {
-
-        unsigned long uvaddr;
-        unsigned long kvaddr;
-        unsigned long ptep;
-
-        uvaddr = MMAP_VADDR(user_vstart, ID_TO_IDX(req->id), i);
-        kvaddr = MMAP_VADDR(mmap_vstart, ID_TO_IDX(req->id), i);
-
-        /* Map the remote page to kernel. */
-        map[op].host_addr = kvaddr;
-        map[op].dom   = ID_TO_DOM(req->id);
-        map[op].ref   = blkif_gref_from_fas(target->frame_and_sects[i]);
-        map[op].flags = GNTMAP_host_map;
-        /* This needs a bit more thought in terms of interposition: 
-         * If we want to be able to modify pages during write using 
-         * grant table mappings, the guest will either need to allow 
-         * it, or we'll need to incur a copy. */
-        if (req->operation == BLKIF_OP_WRITE)
-            map[op].flags |= GNTMAP_readonly;
-        op++;
-
-        /* Now map it to user. */
-        ret = create_lookup_pte_addr(blktap_vma->vm_mm, uvaddr, &ptep);
-        if (ret)
-        {
-            DPRINTK("Couldn't get a pte addr!\n");
-            goto fail;
-        }
-
-        map[op].host_addr = ptep;
-        map[op].dom       = ID_TO_DOM(req->id);
-        map[op].ref       = blkif_gref_from_fas(target->frame_and_sects[i]);
-        map[op].flags     = GNTMAP_host_map | GNTMAP_application_map
-                            | GNTMAP_contains_pte;
-        /* Above interposition comment applies here as well. */
-        if (req->operation == BLKIF_OP_WRITE)
-            map[op].flags |= GNTMAP_readonly;
-        op++;
-    }
-
-    if ( unlikely(HYPERVISOR_grant_table_op(
-            GNTTABOP_map_grant_ref, map, op)))
-        BUG();
-
-    op = 0;
-    for (i=0; i<(target->nr_segments*2); i+=2) {
-        unsigned long uvaddr;
-        unsigned long kvaddr;
-        unsigned long offset;
-        int cancel = 0;
-
-        uvaddr = MMAP_VADDR(user_vstart, ID_TO_IDX(req->id), i/2);
-        kvaddr = MMAP_VADDR(mmap_vstart, ID_TO_IDX(req->id), i/2);
-
-        if ( unlikely(map[i].handle < 0) ) {
-            DPRINTK("Error on kernel grant mapping (%d)\n", map[i].handle);
-            ret = map[i].handle;
-            cancel = 1;
-        }
-
-        if ( unlikely(map[i+1].handle < 0) ) {
-            DPRINTK("Error on user grant mapping (%d)\n", map[i+1].handle);
-            ret = map[i+1].handle;
-            cancel = 1;
-        }
-
-        if (cancel) 
-            goto fail;
-
-        /* Set the necessary mappings in p2m and in the VM_FOREIGN 
-         * vm_area_struct to allow user vaddr -> struct page lookups
-         * to work.  This is needed for direct IO to foreign pages. */
-        phys_to_machine_mapping[__pa(kvaddr) >> PAGE_SHIFT] =
-            FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT);
-
-        offset = (uvaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
-        ((struct page **)blktap_vma->vm_private_data)[offset] =
-            pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
-
-        /* Save handles for unmapping later. */
-        pending_handle(ID_TO_IDX(req->id), i/2).kernel = map[i].handle;
-        pending_handle(ID_TO_IDX(req->id), i/2).user   = map[i+1].handle;
-    }
-    
-#else
-
-    remap_prot = _PAGE_PRESENT|_PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_RW;
-
-    for (i=0; i<target->nr_segments; i++) {
-        unsigned long buf;
-        unsigned long uvaddr;
-        unsigned long kvaddr;
-        unsigned long offset;
-        unsigned long ptep;
-
-        buf   = target->frame_and_sects[i] & PAGE_MASK;
-        uvaddr = MMAP_VADDR(user_vstart, ID_TO_IDX(req->id), i);
-        kvaddr = MMAP_VADDR(mmap_vstart, ID_TO_IDX(req->id), i);
-
-        MULTI_update_va_mapping_otherdomain(
-            mcl+i, 
-            kvaddr, 
-            pfn_pte_ma(buf >> PAGE_SHIFT, __pgprot(remap_prot)),
-            0,
-            ID_TO_DOM(req->id));
-
-        phys_to_machine_mapping[__pa(kvaddr)>>PAGE_SHIFT] =
-            FOREIGN_FRAME(buf >> PAGE_SHIFT);
-
-        ret = create_lookup_pte_addr(blktap_vma->vm_mm, uvaddr, &ptep);
-        if (ret)
-        { 
-            DPRINTK("error getting pte\n");
-            goto fail;
-        }
-
-        mmu[i].ptr = ptep;
-        mmu[i].val = (target->frame_and_sects[i] & PAGE_MASK)
-            | pgprot_val(blktap_vma->vm_page_prot);
-
-        offset = (uvaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
-        ((struct page **)blktap_vma->vm_private_data)[offset] =
-            pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
-    }
-    
-    /* Add the mmu_update call. */
-    mcl[i].op = __HYPERVISOR_mmu_update;
-    mcl[i].args[0] = (unsigned long)mmu;
-    mcl[i].args[1] = target->nr_segments;
-    mcl[i].args[2] = 0;
-    mcl[i].args[3] = ID_TO_DOM(req->id);
-
-    BUG_ON(HYPERVISOR_multicall(mcl, target->nr_segments+1) != 0);
-
-    /* Make sure it all worked. */
-    for ( i = 0; i < target->nr_segments; i++ )
-    {
-        if ( unlikely(mcl[i].result != 0) )
-        {
-            DPRINTK("invalid buffer -- could not remap it\n");
-            ret = mcl[i].result;
-            goto fail;
-        }
-    }
-    if ( unlikely(mcl[i].result != 0) )
-    {
-        DPRINTK("direct remapping of pages to /dev/blktap failed.\n");
-        ret = mcl[i].result;
-        goto fail;
-    }
-#endif /* CONFIG_XEN_BLKDEV_GRANT */
-
-    /* Mark mapped pages as reserved: */
-    for ( i = 0; i < target->nr_segments; i++ )
-    {
-        unsigned long kvaddr;
-
-        kvaddr = MMAP_VADDR(mmap_vstart, ID_TO_IDX(req->id), i);
-        SetPageReserved(pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT));
-    }
-
-
-    blktap_ufe_ring.req_prod_pvt++;
-    
-    return 0;
-
- fail:
-    fast_flush_area(ID_TO_IDX(req->id), target->nr_segments);
-    return ret;
-}
-
-int blktap_write_be_ring(blkif_response_t *rsp)
-{
-    blkif_response_t *target;
-
-    /*
-     * This is called to pass a request from the real backend domain's
-     * blkif ring to the character device.
-     */
-
-    if ( ! blktap_ring_ok ) {
-        DPRINTK("blktap: be_ring not ready for a request!\n");
-        return 0;
-    }
-
-    /* No test for fullness in the response direction. */
-
-    target = RING_GET_RESPONSE(&blktap_ube_ring,
-            blktap_ube_ring.rsp_prod_pvt);
-    memcpy(target, rsp, sizeof(*rsp));
-
-    /* no mapping -- pages were mapped in blktap_write_fe_ring() */
-
-    blktap_ube_ring.rsp_prod_pvt++;
-    
-    return 0;
-}
-
-static int blktap_read_fe_ring(void)
-{
-    /* This is called to read responses from the UFE ring. */
-
-    RING_IDX i, j, rp;
-    blkif_response_t *resp_s;
-    blkif_t *blkif;
-    active_req_t *ar;
-
-    DPRINTK("blktap_read_fe_ring()\n");
-
-    /* if we are forwarding from UFERring to FERing */
-    if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) {
-
-        /* for each outstanding message on the UFEring  */
-        rp = blktap_ufe_ring.sring->rsp_prod;
-        rmb();
-        
-        for ( i = blktap_ufe_ring.rsp_cons; i != rp; i++ )
-        {
-            resp_s = RING_GET_RESPONSE(&blktap_ufe_ring, i);
-            
-            DPRINTK("resp->fe_ring\n");
-            ar = lookup_active_req(ID_TO_IDX(resp_s->id));
-            blkif = ar->blkif;
-            for (j = 0; j < ar->nr_pages; j++) {
-                unsigned long vaddr;
-                struct page **map = blktap_vma->vm_private_data;
-                int offset; 
-
-                vaddr  = MMAP_VADDR(user_vstart, ID_TO_IDX(resp_s->id), j);
-                offset = (vaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
-
-                ClearPageReserved(virt_to_page(vaddr));
-                map[offset] = NULL;
-            }
-
-            fast_flush_area(ID_TO_IDX(resp_s->id), ar->nr_pages);
-            zap_page_range(blktap_vma, 
-                    MMAP_VADDR(user_vstart, ID_TO_IDX(resp_s->id), 0), 
-                    ar->nr_pages << PAGE_SHIFT, NULL);
-            write_resp_to_fe_ring(blkif, resp_s);
-            blktap_ufe_ring.rsp_cons = i + 1;
-            kick_fe_domain(blkif);
-        }
-    }
-    return 0;
-}
-
-static int blktap_read_be_ring(void)
-{
-    /* This is called to read requests from the UBE ring. */
-
-    RING_IDX i, rp;
-    blkif_request_t *req_s;
-
-    DPRINTK("blktap_read_be_ring()\n");
-
-    /* if we are forwarding from UFERring to FERing */
-    if (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) {
-
-        /* for each outstanding message on the UFEring  */
-        rp = blktap_ube_ring.sring->req_prod;
-        rmb();
-        for ( i = blktap_ube_ring.req_cons; i != rp; i++ )
-        {
-            req_s = RING_GET_REQUEST(&blktap_ube_ring, i);
-
-            DPRINTK("req->be_ring\n");
-            write_req_to_be_ring(req_s);
-            kick_be_domain();
-        }
-        
-        blktap_ube_ring.req_cons = i;
-    }
-
-    return 0;
-}
-
-int blktap_write_ctrl_ring(ctrl_msg_t *msg)
-{
-    ctrl_msg_t *target;
-
-    if ( ! blktap_ring_ok ) {
-        DPRINTK("blktap: be_ring not ready for a request!\n");
-        return 0;
-    }
-
-    /* No test for fullness in the response direction. */
-
-    target = RING_GET_REQUEST(&blktap_uctrl_ring,
-            blktap_uctrl_ring.req_prod_pvt);
-    memcpy(target, msg, sizeof(*msg));
-
-    blktap_uctrl_ring.req_prod_pvt++;
-    
-    /* currently treat the ring as unidirectional. */
-    blktap_uctrl_ring.rsp_cons = blktap_uctrl_ring.sring->rsp_prod;
-    
-    return 0;
-       
-}
-
-/* -------[ blktap module setup ]------------------------------------- */
-
-static struct miscdevice blktap_miscdev = {
-    .minor        = BLKTAP_MINOR,
-    .name         = "blktap",
-    .fops         = &blktap_fops,
-    .devfs_name   = "misc/blktap",
-};
-
-int blktap_init(void)
-{
-    int err, i, j;
-    struct page *page;
-
-    page = balloon_alloc_empty_page_range(MMAP_PAGES);
-    BUG_ON(page == NULL);
-    mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
-
-#ifdef CONFIG_XEN_BLKDEV_GRANT
-    for (i=0; i<MAX_PENDING_REQS ; i++)
-        for (j=0; j<BLKIF_MAX_SEGMENTS_PER_REQUEST; j++)
-            BLKTAP_INVALIDATE_HANDLE(&pending_handle(i, j));
-#endif
-
-    err = misc_register(&blktap_miscdev);
-    if ( err != 0 )
-    {
-        printk(KERN_ALERT "Couldn't register /dev/misc/blktap (%d)\n", err);
-        return err;
-    }
-
-    init_waitqueue_head(&blktap_wait);
-
-
-    return 0;
-}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/ctrl_if.h
--- a/linux-2.6-xen-sparse/include/asm-xen/ctrl_if.h    Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,160 +0,0 @@
-/******************************************************************************
- * ctrl_if.h
- * 
- * Management functions for special interface to the domain controller.
- * 
- * Copyright (c) 2004, K A Fraser
- * 
- * This file may be distributed separately from the Linux kernel, or
- * incorporated into other software packages, subject to the following license:
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this source file (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef __ASM_XEN__CTRL_IF_H__
-#define __ASM_XEN__CTRL_IF_H__
-
-#include <asm-xen/hypervisor.h>
-#include <asm-xen/queues.h>
-
-typedef control_msg_t ctrl_msg_t;
-
-/*
- * Callback function type. Called for asynchronous processing of received
- * request messages, and responses to previously-transmitted request messages.
- * The parameters are (@msg, @id).
- *  @msg: Original request/response message (not a copy). The message can be
- *        modified in-place by the handler (e.g., a response callback can
- *        turn a request message into a response message in place). The message
- *        is no longer accessible after the callback handler returns -- if the
- *        message is required to persist for longer then it must be copied.
- *  @id:  (Response callbacks only) The 'id' that was specified when the
- *        original request message was queued for transmission.
- */
-typedef void (*ctrl_msg_handler_t)(ctrl_msg_t *, unsigned long);
-
-/*
- * Send @msg to the domain controller. Execute @hnd when a response is
- * received, passing the response message and the specified @id. This
- * operation will not block: it will return -EAGAIN if there is no space.
- * Notes:
- *  1. The @msg is copied if it is transmitted and so can be freed after this
- *     function returns.
- *  2. If @hnd is NULL then no callback is executed.
- */
-int
-ctrl_if_send_message_noblock(
-    ctrl_msg_t *msg, 
-    ctrl_msg_handler_t hnd,
-    unsigned long id);
-
-/*
- * Send @msg to the domain controller. Execute @hnd when a response is
- * received, passing the response message and the specified @id. This
- * operation will block until the message is sent, or a signal is received
- * for the calling process (unless @wait_state is TASK_UNINTERRUPTIBLE).
- * Notes:
- *  1. The @msg is copied if it is transmitted and so can be freed after this
- *     function returns.
- *  2. If @hnd is NULL then no callback is executed.
- */
-int
-ctrl_if_send_message_block(
-    ctrl_msg_t *msg, 
-    ctrl_msg_handler_t hnd, 
-    unsigned long id, 
-    long wait_state);
-
-/*
- * Send @msg to the domain controller. Block until the response is received,
- * and then copy it into the provided buffer, @rmsg.
- */
-int
-ctrl_if_send_message_and_get_response(
-    ctrl_msg_t *msg,
-    ctrl_msg_t *rmsg,
-    long wait_state);
-
-/*
- * Request a callback when there is /possibly/ space to immediately send a
- * message to the domain controller. This function returns 0 if there is
- * already space to trasnmit a message --- in this case the callback task /may/
- * still be executed. If this function returns 1 then the callback /will/ be
- * executed when space becomes available.
- */
-int
-ctrl_if_enqueue_space_callback(
-    struct tq_struct *task);
-
-/*
- * Send a response (@msg) to a message from the domain controller. This will 
- * never block.
- * Notes:
- *  1. The @msg is copied and so can be freed after this function returns.
- *  2. The @msg may be the original request message, modified in-place.
- */
-void
-ctrl_if_send_response(
-    ctrl_msg_t *msg);
-
-/*
- * Register a receiver for typed messages from the domain controller. The 
- * handler (@hnd) is called for every received message of specified @type.
- * Returns TRUE (non-zero) if the handler was successfully registered.
- * If CALLBACK_IN_BLOCKING CONTEXT is specified in @flags then callbacks will
- * occur in a context in which it is safe to yield (i.e., process context).
- */
-#define CALLBACK_IN_BLOCKING_CONTEXT 1
-int ctrl_if_register_receiver(
-    u8 type, 
-    ctrl_msg_handler_t hnd,
-    unsigned int flags);
-
-/*
- * Unregister a receiver for typed messages from the domain controller. The 
- * handler (@hnd) will not be executed after this function returns.
- */
-void
-ctrl_if_unregister_receiver(
-    u8 type, ctrl_msg_handler_t hnd);
-
-/* Suspend/resume notifications. */
-void ctrl_if_suspend(void);
-void ctrl_if_resume(void);
-
-/* Start-of-day setup. */
-void ctrl_if_init(void);
-
-/*
- * Returns TRUE if there are no outstanding message requests at the domain
- * controller. This can be used to ensure that messages have really flushed
- * through when it is not possible to use the response-callback interface.
- * WARNING: If other subsystems are using the control interface then this
- * function might never return TRUE!
- */
-int ctrl_if_transmitter_empty(void);  /* !! DANGEROUS FUNCTION !! */
-
-/*
- * Manually discard response messages from the domain controller. 
- * WARNING: This is usually done automatically -- this function should only
- * be called when normal interrupt mechanisms are disabled!
- */
-void ctrl_if_discard_responses(void); /* !! DANGEROUS FUNCTION !! */
-
-#endif /* __ASM_XEN__CONTROL_IF_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 
linux-2.6-xen-sparse/include/asm-xen/linux-public/suspend.h
--- a/linux-2.6-xen-sparse/include/asm-xen/linux-public/suspend.h       Thu Sep 
 8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,43 +0,0 @@
-/******************************************************************************
- * suspend.h
- * 
- * Copyright (c) 2003-2004, K A Fraser
- * 
- * This file may be distributed separately from the Linux kernel, or
- * incorporated into other software packages, subject to the following license:
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this source file (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef __ASM_XEN_SUSPEND_H__
-#define __ASM_XEN_SUSPEND_H__
-
-typedef struct suspend_record_st {
-    /* To be filled in before resume. */
-    start_info_t resume_info;
-    /*
-     * The number of a machine frame containing, in sequence, the number of
-     * each machine frame that contains PFN -> MFN translation table data.
-     */
-    unsigned long pfn_to_mfn_frame_list;
-    /* Number of entries in the PFN -> MFN translation table. */
-    unsigned long nr_pfns;
-} suspend_record_t;
-
-#endif /* __ASM_XEN_SUSPEND_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_curl_devel
--- a/tools/check/check_curl_devel      Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,11 +0,0 @@
-#!/bin/bash
-# CHECK-BUILD
-
-function error {
-    echo 'Check for libcurl includes failed.'
-    exit 1
-}
-
-set -e
-[ -e /usr/include/curl ] || error
-[ -e /usr/include/curl/curl.h ] || error
\ No newline at end of file
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_curl_lib
--- a/tools/check/check_curl_lib        Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,10 +0,0 @@
-#!/bin/bash
-# CHECK-BUILD CHECK-INSTALL
-
-function error {
-        echo 'Check for CURL library failed.'
-        exit 1
-}
-
-set -e
-ldconfig -p | grep libcurl.so || error
\ No newline at end of file
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/backend.hotplug
--- a/tools/examples/backend.hotplug    Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,21 +0,0 @@
-#! /bin/sh
-
-#DEVPATH=/devices/xen-backend/vif-1-0
-#ACTION=add
-
-PATH=/etc/xen/scripts:$PATH
-
-DEV=$(basename "$DEVPATH")
-case "$ACTION" in
-  add)
-    case "$DEV" in
-      vif-*)
-        vif=$(echo "$DEV" | sed 's/-\([0-9]*\)-\([0-9]*\)/\1.\2/')
-        vif-bridge up domain=unknown vif="$vif" mac=fe:ff:ff:ff:ff:ff 
bridge=xen-br0 >/dev/null 2>&1
-        ;;
-    esac
-    ;;
-  remove)
-    ;;
-esac
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/firmware/vmxassist/TODO
--- a/tools/firmware/vmxassist/TODO     Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,8 +0,0 @@
-
-- Use the VME extensions (interrupt handling)
-
-- Use E820 map in vmxassist instead of cmos hack
-
-- Add ACPI support (Nitin's patch)
-
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/lowlevel/xu/xu.c
--- a/tools/python/xen/lowlevel/xu/xu.c Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,1781 +0,0 @@
-/******************************************************************************
- * utils.c
- * 
- * Copyright (c) 2004, K A Fraser
- */
-
-#include <Python.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/mman.h>
-#include <sys/poll.h>
-#include <sys/sysmacros.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <xenctrl.h>
-
-#include <xen/xen.h>
-#include <xen/io/domain_controller.h>
-#include <xen/linux/privcmd.h>
-
-#define XENPKG "xen.lowlevel.xu"
-
-/* Needed for Python versions earlier than 2.3. */
-#ifndef PyMODINIT_FUNC
-#define PyMODINIT_FUNC DL_EXPORT(void)
-#endif
-
-/* NB. The following should be kept in sync with the kernel's evtchn driver. */
-#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
-#define EVTCHN_DEV_MAJOR 10
-#define EVTCHN_DEV_MINOR 201
-/* /dev/xen/evtchn ioctls: */
-/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
-#define EVTCHN_RESET  _IO('E', 1)
-/* EVTCHN_BIND: Bind to teh specified event-channel port. */
-#define EVTCHN_BIND   _IO('E', 2)
-/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
-#define EVTCHN_UNBIND _IO('E', 3)
-
-/* Set the close-on-exec flag on a file descriptor.  Doesn't currently bother
- * to check for errors. */
-/*
-static void set_cloexec(int fd)
-{
-    int flags = fcntl(fd, F_GETFD, 0);
-
-    if ( flags < 0 )
-       return;
-
-    flags |= FD_CLOEXEC;
-    fcntl(fd, F_SETFD, flags);
-}
-*/
-/*
- * *********************** XCS INTERFACE ***********************
- */
-
-#include <arpa/inet.h>
-#include <xcs_proto.h>
-
-static int xcs_ctrl_fd = -1; /* control connection to the xcs server. */
-static int xcs_data_fd = -1; /*    data connection to the xcs server. */
-static unsigned long  xcs_session_id = 0;
-
-static int xcs_ctrl_send(xcs_msg_t *msg);
-static int xcs_ctrl_read(xcs_msg_t *msg);
-static int xcs_data_send(xcs_msg_t *msg);
-static int xcs_data_read(xcs_msg_t *msg);
-
-static int xcs_connect(char *path)
-{
-    struct sockaddr_un addr;
-    int ret, len, flags;
-    xcs_msg_t msg;
-
-    if (xcs_data_fd != -1) /* already connected */
-        return 0;
-    
-    xcs_ctrl_fd = socket(AF_UNIX, SOCK_STREAM, 0);
-    if (xcs_ctrl_fd < 0)
-    {
-        printf("error creating xcs socket!\n");
-        goto fail;
-    }
-    
-    addr.sun_family = AF_UNIX;
-    strcpy(addr.sun_path, path);
-    len = sizeof(addr.sun_family) + strlen(addr.sun_path) + 1;
-
-    ret = connect(xcs_ctrl_fd, (struct sockaddr *)&addr, len);
-    if (ret < 0) 
-    {
-        printf("error connecting to xcs(ctrl)! (%d)\n", errno);
-        goto ctrl_fd_fail;
-    }
-
-    /*set_cloexec(xcs_ctrl_fd);*/
-            
-    msg.type = XCS_CONNECT_CTRL;
-    msg.u.connect.session_id = xcs_session_id;
-    xcs_ctrl_send(&msg);
-    xcs_ctrl_read(&msg); /* TODO: timeout + error! */
-    
-    if (msg.result != XCS_RSLT_OK)
-    {
-        printf("error connecting xcs control channel!\n");
-        goto ctrl_fd_fail;
-    }
-    xcs_session_id = msg.u.connect.session_id;
-    
-    /* now the data connection. */
-    xcs_data_fd = socket(AF_UNIX, SOCK_STREAM, 0);
-    if (xcs_data_fd < 0)
-    {
-        printf("error creating xcs data socket!\n");
-        goto ctrl_fd_fail;
-    }
-    
-    addr.sun_family = AF_UNIX;
-    strcpy(addr.sun_path, path);
-    len = sizeof(addr.sun_family) + strlen(addr.sun_path) + 1;
-    
-    ret = connect(xcs_data_fd, (struct sockaddr *)&addr, len);
-    if (ret < 0) 
-    {
-        printf("error connecting to xcs(data)! (%d)\n", errno);
-        goto data_fd_fail;
-    }
-
-    //set_cloexec(xcs_data_fd);
-    msg.type = XCS_CONNECT_DATA;
-    msg.u.connect.session_id = xcs_session_id;
-    xcs_data_send(&msg);
-    xcs_data_read(&msg); /* TODO: timeout + error! */
-    
-    if (msg.result != XCS_RSLT_OK)
-    {
-        printf("error connecting xcs control channel!\n");
-        goto ctrl_fd_fail;
-    }
-    
-    if ( ((flags = fcntl(xcs_data_fd, F_GETFL, 0)) < 0) ||
-        (fcntl(xcs_data_fd, F_SETFL, flags | O_NONBLOCK) < 0) )
-    {
-        printf("Unable to set non-blocking status on data socket.");
-        goto data_fd_fail;
-    }
-    
-    return 0;
-
-data_fd_fail: 
-    close(xcs_data_fd);  
-    xcs_data_fd = -1;  
-    
-ctrl_fd_fail:
-    close(xcs_ctrl_fd);
-    xcs_ctrl_fd = -1; 
-     
-fail:
-    return -1;
-    
-}
-
-static void xcs_disconnect(void)
-{
-    close(xcs_data_fd);
-    xcs_data_fd = -1;
-    close(xcs_ctrl_fd);
-    xcs_ctrl_fd = -1;
-}
-
-static int xcs_ctrl_read(xcs_msg_t *msg)
-{
-    int ret;
-    
-    ret = read(xcs_ctrl_fd, msg, sizeof(xcs_msg_t));
-    return ret;
-}
-
-static int xcs_ctrl_send(xcs_msg_t *msg)
-{
-    int ret;
-    
-    ret = send(xcs_ctrl_fd, msg, sizeof(xcs_msg_t), 0);
-    return ret;
-}
-
-static int xcs_data_read(xcs_msg_t *msg)
-{
-    int ret;
-    
-    ret = read(xcs_data_fd, msg, sizeof(xcs_msg_t));
-    return ret;
-}
-
-static int xcs_data_send(xcs_msg_t *msg)
-{
-    int ret;
-    
-    ret = send(xcs_data_fd, msg, sizeof(xcs_msg_t), 0);
-    return ret;
-}
-
-
-typedef struct kme_st {
-    xcs_msg_t         msg;
-    struct kme_st    *next;
-} xcs_msg_ent_t;
-    
-
-#define XCS_RING_SIZE 64
-static xcs_msg_ent_t *req_ring[64];
-static unsigned req_prod = 0;
-static unsigned req_cons = 0;
-
-static xcs_msg_ent_t *rsp_ring[64];
-static unsigned rsp_prod = 0;
-static unsigned rsp_cons = 0;
-
-#define REQ_RING_ENT(_idx) (req_ring[(_idx) % XCS_RING_SIZE])
-#define RSP_RING_ENT(_idx) (rsp_ring[(_idx) % XCS_RING_SIZE]) 
-#define REQ_RING_FULL ( req_prod - req_cons == XCS_RING_SIZE )
-#define RSP_RING_FULL ( rsp_prod - rsp_cons == XCS_RING_SIZE )
-#define REQ_RING_EMPTY ( req_prod == req_cons )
-#define RSP_RING_EMPTY ( rsp_prod == rsp_cons )
-/*
- * *********************** NOTIFIER ***********************
- */
-
-typedef struct {
-    PyObject_HEAD;
-    int evtchn_fd;
-} xu_notifier_object;
-
-static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
-{
-    xcs_msg_ent_t *ent;
-    int ret;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-         
-    while ((!REQ_RING_FULL) && (!RSP_RING_FULL))
-    {
-        ent = (xcs_msg_ent_t *)malloc(sizeof(xcs_msg_ent_t));
-        ret = xcs_data_read(&ent->msg);
-
-        if (ret == -1)
-        {
-            free(ent);
-            if ( errno == EINTR )
-                continue;
-            if ( errno == EAGAIN )
-                break;
-            return PyErr_SetFromErrno(PyExc_IOError);
-        }
-        
-        switch (ent->msg.type)
-        {
-        case XCS_REQUEST:
-            REQ_RING_ENT(req_prod) = ent;
-            req_prod++;
-            continue;
-
-        case XCS_RESPONSE:
-            RSP_RING_ENT(rsp_prod) = ent;
-            rsp_prod++;
-            continue;
-            
-        case XCS_VIRQ:
-            ret = ent->msg.u.control.local_port;
-            free(ent);
-            return PyInt_FromLong(ret);
-
-        default:
-            /*printf("Throwing away xcs msg type: %u\n", ent->msg.type);*/
-            free(ent);
-        }
-    }
-    
-    if (!REQ_RING_EMPTY) 
-    {
-        return 
PyInt_FromLong(REQ_RING_ENT(req_cons)->msg.u.control.local_port); 
-    }
-    
-    if (!RSP_RING_EMPTY) 
-    {
-        return 
PyInt_FromLong(RSP_RING_ENT(rsp_cons)->msg.u.control.local_port); 
-    }
-    
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_notifier_bind_virq(PyObject *self, 
-            PyObject *args, PyObject *kwds)
-{
-    int virq;
-    xcs_msg_t kmsg;
-
-    static char *kwd_list[] = { "virq", NULL };
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
-        return NULL;
-    
-    kmsg.type = XCS_VIRQ_BIND;
-    kmsg.u.virq.virq  = virq;
-    xcs_ctrl_send(&kmsg);
-    xcs_ctrl_read(&kmsg);
-    
-    if ( kmsg.result != XCS_RSLT_OK )
-    {  
-        Py_INCREF(Py_None);
-        return Py_None;
-    }
-    
-    return PyInt_FromLong(kmsg.u.virq.port);
-}
-
-static PyObject *xu_notifier_virq_send(PyObject *self, 
-            PyObject *args, PyObject *kwds)
-{
-    int port;
-    xcs_msg_t kmsg;
-
-    static char *kwd_list[] = { "port", NULL };
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
-        return NULL;
-    
-    kmsg.type = XCS_VIRQ;
-    kmsg.u.control.local_port  = port;
-    xcs_ctrl_send(&kmsg);
-    xcs_ctrl_read(&kmsg);
-    
-    if ( kmsg.result != XCS_RSLT_OK )
-    {  
-        Py_INCREF(Py_None);
-        return Py_None;
-    }
-    
-    return PyInt_FromLong(kmsg.u.virq.port);
-}
-
-static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
-{
-    return PyInt_FromLong(xcs_data_fd);
-}
-
-static PyMethodDef xu_notifier_methods[] = {
-    { "read",
-      (PyCFunction)xu_notifier_read,
-      METH_VARARGS,
-      "Read a @port with pending notifications.\n" },
-
-    { "bind_virq",
-      (PyCFunction)xu_notifier_bind_virq,
-      METH_VARARGS | METH_KEYWORDS,
-      "Get notifications for a virq.\n" 
-      " virq [int]: VIRQ to bind.\n\n" },
-      
-    { "virq_send",
-      (PyCFunction)xu_notifier_virq_send,
-      METH_VARARGS | METH_KEYWORDS,
-      "Fire a virq notification.\n" 
-      " port [int]: port that VIRQ is bound to.\n\n" },
-
-    { "fileno", 
-      (PyCFunction)xu_notifier_fileno,
-      METH_VARARGS,
-      "Return the file descriptor for the notification channel.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_notifier_type;
-
-/* connect to xcs if we aren't already, and return a dummy object. */
-static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun;
-    int i;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
-
-    for (i = 0; i < XCS_RING_SIZE; i++) 
-        REQ_RING_ENT(i) = RSP_RING_ENT(i) = NULL;
-    
-    (void)xcs_connect(XCS_SUN_PATH);
-    
-
-    return (PyObject *)xun;
-}
-
-static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
-{
-    return Py_FindMethod(xu_notifier_methods, obj, name);
-}
-
-static void xu_notifier_dealloc(PyObject *self)
-{
-    xcs_disconnect();
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_notifier_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "notifier",
-    sizeof(xu_notifier_object),
-    0,
-    xu_notifier_dealloc, /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_notifier_getattr, /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** MESSAGE ***********************
- */
-
-#define TYPE(_x,_y) (((_x)<<8)|(_y))
-
-#define P2C(_struct, _field, _ctype)                                      \
-    do {                                                                  \
-        PyObject *obj;                                                    \
-        if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL )     \
-        {                                                                 \
-            if ( PyInt_Check(obj) )                                       \
-            {                                                             \
-                ((_struct *)&xum->msg.msg[0])->_field =                   \
-                  (_ctype)PyInt_AsLong(obj);                              \
-                dict_items_parsed++;                                      \
-            }                                                             \
-            else if ( PyLong_Check(obj) )                                 \
-            {                                                             \
-                ((_struct *)&xum->msg.msg[0])->_field =                   \
-                  (_ctype)PyLong_AsUnsignedLongLong(obj);                 \
-                dict_items_parsed++;                                      \
-            }                                                             \
-        }                                                                 \
-        xum->msg.length = sizeof(_struct);                                \
-    } while ( 0 )
-
-/** Set a char[] field in a struct from a Python string.
- * Can't do this in P2C because of the typing.
- */
-#define P2CSTRING(_struct, _field)                                        \
-    do {                                                                  \
-        PyObject *obj;                                                    \
-        if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL )     \
-        {                                                                 \
-            if ( PyString_Check(obj) )                                    \
-            {                                                             \
-                _struct * _cobj = (_struct *)&xum->msg.msg[0];            \
-                int _field_n = sizeof(_cobj->_field);                     \
-                memset(_cobj->_field, 0, _field_n);                       \
-                strncpy(_cobj->_field,                                    \
-                        PyString_AsString(obj),                           \
-                        _field_n - 1);                                    \
-                dict_items_parsed++;                                      \
-            }                                                             \
-        }                                                                 \
-        xum->msg.length = sizeof(_struct);                                \
-    } while ( 0 )
-
-#define C2P(_struct, _field, _pytype, _ctype)                             \
-    do {                                                                  \
-        PyObject *obj = Py ## _pytype ## _From ## _ctype                  \
-                        (((_struct *)&xum->msg.msg[0])->_field);          \
-        if ( dict == NULL ) dict = PyDict_New();                          \
-        PyDict_SetItemString(dict, #_field, obj);                         \
-    } while ( 0 )
-
-#define PSTR2CHAR(_struct, _field)                                        \
- do {                                                                     \
-     PyObject *obj;                                                       \
-        if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL )     \
-        {                                                                 \
-            if ( PyString_Check(obj) )                                    \
-            {                                                             \
-                char *buffer = PyString_AsString(obj);                    \
-                                                                          \
-                strcpy(((_struct *)&xum->msg.msg[0])->_field,             \
-                        buffer);                                          \
-                /* Should complain about length - think later */          \
-                dict_items_parsed++;                                      \
-            }                                                             \
-        }                                                                 \
-        xum->msg.length = sizeof(_struct);                                \
- } while ( 0 )
-
-typedef struct {
-    PyObject_HEAD;
-    control_msg_t msg;
-} xu_message_object;
-
-static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-    char *str;
-    int len;
-
-    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
-        return NULL;
-
-    if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
-    {
-        PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
-        return NULL;
-    }
-
-    memcpy(&xum->msg.msg[xum->msg.length], str, len);
-    xum->msg.length += len;
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-    PyObject *payload;
-    int dict_items_parsed = 0;
-
-    if ( !PyArg_ParseTuple(args, "O", &payload) )
-        return NULL;
-
-    if ( !PyDict_Check(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
-        return NULL;
-    }
-
-    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
-    {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS):
-        P2C(blkif_fe_driver_status_t, max_handle, u32);
-        break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
-        P2C(netif_fe_driver_status_t, max_handle, u32);
-        break;
-    }
-
-    if ( dict_items_parsed != PyDict_Size(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
-        return NULL;
-    }
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-    PyObject *dict = NULL;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
-    {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS):
-        C2P(blkif_fe_interface_status_t, handle, Int, Long);
-        C2P(blkif_fe_interface_status_t, status, Int, Long);
-        C2P(blkif_fe_interface_status_t, evtchn, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS):
-        C2P(blkif_fe_driver_status_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
-        C2P(blkif_fe_interface_connect_t, handle,      Int, Long);
-        C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
-        C2P(blkif_fe_interface_connect_t, shmem_ref  , Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
-        C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
-        C2P(blkif_be_create_t, domid,        Int, Long);
-        C2P(blkif_be_create_t, blkif_handle, Int, Long);
-        C2P(blkif_be_create_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
-        C2P(blkif_be_destroy_t, domid,        Int, Long);
-        C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
-        C2P(blkif_be_destroy_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
-        C2P(blkif_be_connect_t, domid,        Int, Long);
-        C2P(blkif_be_connect_t, blkif_handle, Int, Long);
-        C2P(blkif_be_connect_t, shmem_frame,  Int, Long);
-        C2P(blkif_be_connect_t, shmem_ref,    Int, Long);
-        C2P(blkif_be_connect_t, evtchn,       Int, Long);
-        C2P(blkif_be_connect_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
-        C2P(blkif_be_disconnect_t, domid,        Int, Long);
-        C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
-        C2P(blkif_be_disconnect_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
-        C2P(blkif_be_vbd_create_t, domid,        Int, Long);
-        C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
-        C2P(blkif_be_vbd_create_t, pdevice,      Int, Long);
-        C2P(blkif_be_vbd_create_t, dev_handle,   Int, Long);
-        C2P(blkif_be_vbd_create_t, vdevice,      Int, Long);
-        C2P(blkif_be_vbd_create_t, readonly,     Int, Long);
-        C2P(blkif_be_vbd_create_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
-        C2P(blkif_be_vbd_destroy_t, domid,        Int, Long);
-        C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
-        C2P(blkif_be_vbd_destroy_t, vdevice,      Int, Long);
-        C2P(blkif_be_vbd_destroy_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS):
-        C2P(blkif_be_driver_status_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS):
-        C2P(netif_fe_interface_status_t, handle, Int, Long);
-        C2P(netif_fe_interface_status_t, status, Int, Long);
-        C2P(netif_fe_interface_status_t, evtchn, Int, Long);
-        C2P(netif_fe_interface_status_t, mac[0], Int, Long);
-        C2P(netif_fe_interface_status_t, mac[1], Int, Long);
-        C2P(netif_fe_interface_status_t, mac[2], Int, Long);
-        C2P(netif_fe_interface_status_t, mac[3], Int, Long);
-        C2P(netif_fe_interface_status_t, mac[4], Int, Long);
-        C2P(netif_fe_interface_status_t, mac[5], Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
-        C2P(netif_fe_driver_status_t, status,        Int, Long);
-        C2P(netif_fe_driver_status_t, max_handle,    Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
-        C2P(netif_fe_interface_connect_t, handle,         Int, Long);
-        C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
-        C2P(netif_fe_interface_connect_t, tx_shmem_ref,   Int, Long);
-        C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
-        C2P(netif_fe_interface_connect_t, rx_shmem_ref,   Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
-        C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
-        C2P(netif_be_create_t, domid,        Int, Long);
-        C2P(netif_be_create_t, netif_handle, Int, Long);
-        C2P(netif_be_create_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
-        C2P(netif_be_destroy_t, domid,        Int, Long);
-        C2P(netif_be_destroy_t, netif_handle, Int, Long);
-        C2P(netif_be_destroy_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREDITLIMIT):
-        C2P(netif_be_creditlimit_t, domid,        Int, Long);
-        C2P(netif_be_creditlimit_t, netif_handle, Int, Long);
-        C2P(netif_be_creditlimit_t, credit_bytes, Int, Long);
-        C2P(netif_be_creditlimit_t, period_usec,  Int, Long);
-        C2P(netif_be_creditlimit_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
-        C2P(netif_be_connect_t, domid,          Int, Long);
-        C2P(netif_be_connect_t, netif_handle,   Int, Long);
-        C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
-        C2P(netif_be_connect_t, tx_shmem_ref,   Int, Long);
-        C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
-        C2P(netif_be_connect_t, rx_shmem_ref,   Int, Long);
-        C2P(netif_be_connect_t, evtchn,         Int, Long);
-        C2P(netif_be_connect_t, status,         Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
-        C2P(netif_be_disconnect_t, domid,        Int, Long);
-        C2P(netif_be_disconnect_t, netif_handle, Int, Long);
-        C2P(netif_be_disconnect_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS):
-        C2P(netif_be_driver_status_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED):
-        C2P(usbif_fe_interface_status_changed_t, status, Int, Long);
-        C2P(usbif_fe_interface_status_changed_t, evtchn, Int, Long);
-        C2P(usbif_fe_interface_status_changed_t, domid, Int, Long);
-        C2P(usbif_fe_interface_status_changed_t, bandwidth, Int, Long);
-       C2P(usbif_fe_interface_status_changed_t, num_ports, Int, Long);
-        return dict;
-    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED):
-        C2P(usbif_fe_driver_status_changed_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT):
-        C2P(usbif_fe_interface_connect_t, shmem_frame, Int, Long);
-        return dict;
-    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT):
-        return dict;
-    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE):
-        C2P(usbif_be_create_t, domid, Int, Long);
-        C2P(usbif_be_create_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY):
-        C2P(usbif_be_destroy_t, domid, Int, Long);
-        C2P(usbif_be_destroy_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT):
-        C2P(usbif_be_connect_t, domid, Int, Long);
-        C2P(usbif_be_connect_t, shmem_frame, Int, Long);
-        C2P(usbif_be_connect_t, evtchn, Int, Long);
-        C2P(usbif_be_connect_t, bandwidth, Int, Long);
-        C2P(usbif_be_connect_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT):
-        C2P(usbif_be_disconnect_t, domid, Int, Long);
-        C2P(usbif_be_disconnect_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DRIVER_STATUS_CHANGED):
-        C2P(usbif_be_driver_status_changed_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT):
-        C2P(usbif_be_claim_port_t, domid, Int, Long);
-        C2P(usbif_be_claim_port_t, usbif_port, Int, Long);
-        C2P(usbif_be_claim_port_t, status, Int, Long);
-        C2P(usbif_be_claim_port_t, path, String, String);
-        return dict;
-    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT):
-        C2P(usbif_be_release_port_t, path, String, String);
-        return dict;
-    case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
-        C2P(mem_request_t, target, Int, Long);
-        C2P(mem_request_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_OFF):
-        C2P(vcpu_hotplug_t, vcpu, Int, Long);
-        C2P(vcpu_hotplug_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_ON):
-        C2P(vcpu_hotplug_t, vcpu, Int, Long);
-        C2P(vcpu_hotplug_t, status, Int, Long);
-        return dict;
-    }
-
-    return PyString_FromStringAndSize((char *)xum->msg.msg, xum->msg.length);
-}
-
-static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    return Py_BuildValue("{s:i,s:i,s:i}",
-                         "type",    xum->msg.type,
-                         "subtype", xum->msg.subtype,
-                         "id",      xum->msg.id);
-}
-
-static PyMethodDef xu_message_methods[] = {
-    { "append_payload", 
-      (PyCFunction)xu_message_append_payload,
-      METH_VARARGS,
-      "Append @str to the message payload.\n" },
-
-    { "set_response_fields",
-      (PyCFunction)xu_message_set_response_fields,
-      METH_VARARGS,
-      "Fill in the response fields in a message that was passed to us.\n" },
-
-    { "get_payload",
-      (PyCFunction)xu_message_get_payload,
-      METH_VARARGS,
-      "Return the message payload in string form.\n" },
-
-    { "get_header",
-      (PyCFunction)xu_message_get_header,
-      METH_VARARGS,
-      "Returns a dictionary of values for @type, @subtype, and @id.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_message_type;
-
-static PyObject *xu_message_new(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum;
-    int type, subtype, id, dict_items_parsed = 0;
-    PyObject *payload = NULL;
-
-    if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
-        return NULL;
-
-    xum = PyObject_New(xu_message_object, &xu_message_type);
-
-    xum->msg.type    = type;
-    xum->msg.subtype = subtype;
-    xum->msg.id      = id;
-    xum->msg.length  = 0;
-
-    if ( payload == NULL )
-        return (PyObject *)xum;
-
-    if ( !PyDict_Check(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
-        PyObject_Del((PyObject *)xum);
-        return NULL;
-    }
-
-    switch ( TYPE(type, subtype) )
-    {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS):
-        P2C(blkif_fe_interface_status_t, handle, u32);
-        P2C(blkif_fe_interface_status_t, status, u32);
-        P2C(blkif_fe_interface_status_t, evtchn, u16);
-        P2C(blkif_fe_interface_status_t, domid,  u16);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
-        P2C(blkif_be_create_t, domid,        u32);
-        P2C(blkif_be_create_t, blkif_handle, u32);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
-        P2C(blkif_be_destroy_t, domid,        u32);
-        P2C(blkif_be_destroy_t, blkif_handle, u32);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
-        P2C(blkif_be_connect_t, domid,        u32);
-        P2C(blkif_be_connect_t, blkif_handle, u32);
-        P2C(blkif_be_connect_t, shmem_frame,  unsigned long);
-        P2C(blkif_be_connect_t, shmem_ref,    u32);
-        P2C(blkif_be_connect_t, evtchn,       u16);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
-        P2C(blkif_be_disconnect_t, domid,        u32);
-        P2C(blkif_be_disconnect_t, blkif_handle, u32);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
-        P2C(blkif_be_vbd_create_t, domid,        u32);
-        P2C(blkif_be_vbd_create_t, blkif_handle, u32);
-        P2C(blkif_be_vbd_create_t, pdevice,      blkif_pdev_t);
-        P2C(blkif_be_vbd_create_t, dev_handle,   u32);
-        P2C(blkif_be_vbd_create_t, vdevice,      blkif_vdev_t);
-        P2C(blkif_be_vbd_create_t, readonly,     u16);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
-        P2C(blkif_be_vbd_destroy_t, domid,        u32);
-        P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
-        P2C(blkif_be_vbd_destroy_t, vdevice,      blkif_vdev_t);
-        break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS):
-        P2C(netif_fe_interface_status_t, handle, u32);
-        P2C(netif_fe_interface_status_t, status, u32);
-        P2C(netif_fe_interface_status_t, evtchn, u16);
-        P2C(netif_fe_interface_status_t, domid,  u16);
-        P2C(netif_fe_interface_status_t, mac[0], u8);
-        P2C(netif_fe_interface_status_t, mac[1], u8);
-        P2C(netif_fe_interface_status_t, mac[2], u8);
-        P2C(netif_fe_interface_status_t, mac[3], u8);
-        P2C(netif_fe_interface_status_t, mac[4], u8);
-        P2C(netif_fe_interface_status_t, mac[5], u8);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
-        P2C(netif_be_create_t, domid,        u32);
-        P2C(netif_be_create_t, netif_handle, u32);
-        P2C(netif_be_create_t, mac[0],       u8);
-        P2C(netif_be_create_t, mac[1],       u8);
-        P2C(netif_be_create_t, mac[2],       u8);
-        P2C(netif_be_create_t, mac[3],       u8);
-        P2C(netif_be_create_t, mac[4],       u8);
-        P2C(netif_be_create_t, mac[5],       u8);
-        P2C(netif_be_create_t, be_mac[0],    u8);
-        P2C(netif_be_create_t, be_mac[1],    u8);
-        P2C(netif_be_create_t, be_mac[2],    u8);
-        P2C(netif_be_create_t, be_mac[3],    u8);
-        P2C(netif_be_create_t, be_mac[4],    u8);
-        P2C(netif_be_create_t, be_mac[5],    u8);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
-        P2C(netif_be_destroy_t, domid,        u32);
-        P2C(netif_be_destroy_t, netif_handle, u32);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREDITLIMIT):
-        P2C(netif_be_creditlimit_t, domid,        u32);
-        P2C(netif_be_creditlimit_t, netif_handle, u32);
-        P2C(netif_be_creditlimit_t, credit_bytes, u32);
-        P2C(netif_be_creditlimit_t, period_usec,  u32);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
-        P2C(netif_be_connect_t, domid,          u32);
-        P2C(netif_be_connect_t, netif_handle,   u32);
-        P2C(netif_be_connect_t, tx_shmem_frame, unsigned long);
-        P2C(netif_be_connect_t, tx_shmem_ref,   u32); 
-        P2C(netif_be_connect_t, rx_shmem_frame, unsigned long);
-        P2C(netif_be_connect_t, rx_shmem_ref,   u32); 
-        P2C(netif_be_connect_t, evtchn,         u16); 
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
-        P2C(netif_be_disconnect_t, domid,        u32);
-        P2C(netif_be_disconnect_t, netif_handle, u32);
-        break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
-        P2C(netif_fe_driver_status_t, status,        u32);
-        P2C(netif_fe_driver_status_t, max_handle,    u32);
-        break;
-    case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
-        P2C(mem_request_t, target, u32);
-        break;
-    case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_OFF):
-        P2C(vcpu_hotplug_t, vcpu, u32);
-        P2C(vcpu_hotplug_t, status, u32);
-        break;
-    case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_ON):
-        P2C(vcpu_hotplug_t, vcpu, u32);
-        P2C(vcpu_hotplug_t, status, u32);
-        break;
-    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED):
-        P2C(usbif_fe_interface_status_changed_t, status, u32);
-        P2C(usbif_fe_interface_status_changed_t, evtchn, u16);
-        P2C(usbif_fe_interface_status_changed_t, domid, domid_t);
-        P2C(usbif_fe_interface_status_changed_t, bandwidth, u32);
-       P2C(usbif_fe_interface_status_changed_t, num_ports, u32);
-        break;
-    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(usbif_fe_driver_status_changed_t, status, u32);
-        break;
-    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT):
-        P2C(usbif_fe_interface_connect_t, shmem_frame, unsigned long);
-        break;
-    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT):
-        break;
-    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE):
-        P2C(usbif_be_create_t, domid, domid_t);
-        P2C(usbif_be_create_t, status, u32);
-        break;
-    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY):
-        P2C(usbif_be_destroy_t, domid, domid_t);
-        P2C(usbif_be_destroy_t, status, u32);
-        break;
-    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT):
-        P2C(usbif_be_connect_t, domid, domid_t);
-        P2C(usbif_be_connect_t, shmem_frame, unsigned long);
-        P2C(usbif_be_connect_t, evtchn, u32);
-        P2C(usbif_be_connect_t, bandwidth, u32);
-        P2C(usbif_be_connect_t, status, u32);
-        break;
-    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT):
-        P2C(usbif_be_disconnect_t, domid, domid_t);
-        P2C(usbif_be_disconnect_t, status, u32);
-        break;
-    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DRIVER_STATUS_CHANGED):
-        P2C(usbif_be_driver_status_changed_t, status, u32);
-        break;
-    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT):
-        P2C(usbif_be_claim_port_t, domid, domid_t);
-        P2C(usbif_be_claim_port_t, usbif_port, u32);
-        P2C(usbif_be_claim_port_t, status, u32);
-        PSTR2CHAR(usbif_be_claim_port_t, path);
-        printf("dict items parsed = %d", dict_items_parsed);
-        break;
-    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT):
-        PSTR2CHAR(usbif_be_release_port_t, path);
-        break;
-    case TYPE(CMSG_SHUTDOWN, CMSG_SHUTDOWN_SYSRQ):
-        P2C(shutdown_sysrq_t, key, char);
-        break;
-    }
-
-    if ( dict_items_parsed != PyDict_Size(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
-        PyObject_Del((PyObject *)xum);
-        return NULL;
-    }
-
-    return (PyObject *)xum;
-}
-
-static PyObject *xu_message_getattr(PyObject *obj, char *name)
-{
-    xu_message_object *xum;
-    if ( strcmp(name, "MAX_PAYLOAD") == 0 )
-        return PyInt_FromLong(sizeof(xum->msg.msg));
-    return Py_FindMethod(xu_message_methods, obj, name);
-}
-
-static void xu_message_dealloc(PyObject *self)
-{
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_message_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "message",
-    sizeof(xu_message_object),
-    0,
-    xu_message_dealloc,   /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_message_getattr,   /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** PORT ***********************
- */
-
-typedef struct xu_port_object {
-    PyObject_HEAD;
-    int xc_handle;
-    int connected;
-    u32 remote_dom;
-    int local_port, remote_port;
-    struct xu_port_object *fix_next;
-} xu_port_object;
-
-static PyObject *port_error;
-
-static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    control_msg_t     *cmsg;
-    unsigned          i;
-    xcs_msg_ent_t    *ent = NULL;
-    
-    for ( i = req_cons; (i != req_prod); i++ ) {
-        ent = REQ_RING_ENT(i);
-        if (ent == NULL) 
-            continue;
-        if (ent->msg.u.control.remote_dom == xup->remote_dom)
-            break;
-    }
-    
-    if ((ent == NULL) ||
-        (ent->msg.u.control.remote_dom != xup->remote_dom)) 
-        goto none;
-
-    cmsg = &ent->msg.u.control.msg;
-    xum = PyObject_New(xu_message_object, &xu_message_type);
-    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
-    if ( xum->msg.length > sizeof(xum->msg.msg) )
-        xum->msg.length = sizeof(xum->msg.msg);
-    free(ent);
-    
-    /* remove the entry from the ring and advance the consumer if possible */
-    REQ_RING_ENT(i) = NULL;
-    while ( (REQ_RING_ENT(req_cons) == NULL) && (!REQ_RING_EMPTY) )
-        req_cons++;
-    
-    return (PyObject *)xum;
-    
-none:
-    Py_INCREF(Py_None);
-    return Py_None;
-    
-}
-
-static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    xcs_msg_t          kmsg;
-
-    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
-        return NULL;
-
-    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
-    {
-        PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
-        return NULL;        
-    }
-
-    kmsg.type = XCS_REQUEST;
-    kmsg.u.control.remote_dom = xup->remote_dom;
-    memcpy(&kmsg.u.control.msg, &xum->msg, sizeof(control_msg_t));
-    xcs_data_send(&kmsg);
-    
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    control_msg_t     *cmsg;
-    unsigned          i;
-    xcs_msg_ent_t    *ent = NULL;
-    
-    for ( i = rsp_cons; (i != rsp_prod); i++ ) {
-        ent = RSP_RING_ENT(i);
-        if (ent == NULL) 
-            continue;
-        if (ent->msg.u.control.remote_dom == xup->remote_dom)
-            break;
-    }
-    
-    if ((ent == NULL) ||
-        (ent->msg.u.control.remote_dom != xup->remote_dom))
-         goto none;
-
-    cmsg = &ent->msg.u.control.msg;
-    xum = PyObject_New(xu_message_object, &xu_message_type);
-    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
-    if ( xum->msg.length > sizeof(xum->msg.msg) )
-        xum->msg.length = sizeof(xum->msg.msg);
-    free(ent);
-    
-    /* remove the entry from the ring and advance the consumer if possible */
-    RSP_RING_ENT(i) = NULL;
-    while ( (RSP_RING_ENT(rsp_cons) == NULL) && (!RSP_RING_EMPTY) )
-        rsp_cons++;
-    
-    return (PyObject *)xum;
-    
-none:
-    Py_INCREF(Py_None);
-    return Py_None;
-    
-}
-
-static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    xcs_msg_t          kmsg;
-
-    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
-        return NULL;
-
-    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
-    {
-        PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
-        return NULL;        
-    }
-
-    kmsg.type = XCS_RESPONSE;
-    kmsg.u.control.remote_dom = xup->remote_dom;
-    memcpy(&kmsg.u.control.msg, &xum->msg, sizeof(control_msg_t));
-    xcs_data_send(&kmsg);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
-{
-    xu_port_object   *xup = (xu_port_object *)self;
-    xcs_msg_ent_t    *ent;
-    int               found = 0;
-    unsigned          i;
-  
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    for ( i = req_cons; (i != req_prod); i++ ) {
-        ent = REQ_RING_ENT(i);
-        if (ent == NULL) 
-            continue;
-        if (ent->msg.u.control.remote_dom == xup->remote_dom) {
-            found = 1;
-            break;
-        }
-    }
-    
-    return PyInt_FromLong(found);
-}
-
-static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
-{
-    xu_port_object   *xup = (xu_port_object *)self;
-    xcs_msg_ent_t    *ent;
-    int               found = 0;
-    unsigned          i;
-  
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    for ( i = rsp_cons; (i != rsp_prod); i++ ) {
-        ent = RSP_RING_ENT(i);
-        if (ent == NULL) 
-            continue;
-        if (ent->msg.u.control.remote_dom == xup->remote_dom) {
-            found = 1;
-            break;
-        }
-    }
-    
-    return PyInt_FromLong(found);
-}
-
-static void _xu_port_close(xu_port_object *xup )
-{
-    if ( xup->connected && xup->remote_dom != 0 )
-    {  
-        xcs_msg_t kmsg;
-        kmsg.type = XCS_CIF_FREE_CC;
-        kmsg.u.interface.dom         = xup->remote_dom;
-        kmsg.u.interface.local_port  = xup->local_port; 
-        kmsg.u.interface.remote_port = xup->remote_port;
-        xcs_ctrl_send(&kmsg);
-        xcs_ctrl_read(&kmsg);
-        xup->connected = 0;
-    }
-}
-
-static PyObject *xu_port_close(PyObject *self, PyObject *args)
-{
-    xu_port_object *xup = (xu_port_object *)self;
-
-    _xu_port_close(xup);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_port_register(PyObject *self, PyObject *args, 
-        PyObject *kwds)
-{
-    int type;
-    xcs_msg_t msg;
-    xu_port_object   *xup = (xu_port_object *)self;
-    static char *kwd_list[] = { "type", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
-                                      &type) )
-        return NULL;
-    
-    if (!xup->connected)
-    {
-        return PyInt_FromLong(0);
-    }
-    
-    msg.type = XCS_MSG_BIND;
-    msg.u.bind.port = xup->local_port;
-    msg.u.bind.type = type;
-    xcs_ctrl_send(&msg);
-    xcs_ctrl_read(&msg);
-    
-    if (msg.result != XCS_RSLT_OK)
-    {
-        return PyInt_FromLong(0);
-    }
-    
-    return PyInt_FromLong(1);        
-}
-
-static PyObject *xu_port_deregister(PyObject *self, PyObject *args,
-        PyObject *kwds)
-{
-    int type;
-    xcs_msg_t msg;
-    xu_port_object   *xup = (xu_port_object *)self;
-    static char *kwd_list[] = { "type", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
-                                      &type) )
-        return NULL;
-
-    if (!xup->connected)
-    {
-        return PyInt_FromLong(0);
-    }
-    
-    msg.type = XCS_MSG_UNBIND;
-    msg.u.bind.port = xup->local_port;
-    msg.u.bind.type = type;
-    xcs_ctrl_send(&msg);
-    xcs_ctrl_read(&msg);
-    
-    if (msg.result != XCS_RSLT_OK)
-    {
-        return PyInt_FromLong(0);
-    }
-    
-    return PyInt_FromLong(1);        
-}
-
-static PyMethodDef xu_port_methods[] = {
-
-    { "read_request",
-      (PyCFunction)xu_port_read_request,
-      METH_VARARGS,
-      "Read a request message from the control interface.\n" },
-
-    { "write_request",
-      (PyCFunction)xu_port_write_request,
-      METH_VARARGS,
-      "Write a request message to the control interface.\n" },
-
-    { "read_response",
-      (PyCFunction)xu_port_read_response,
-      METH_VARARGS,
-      "Read a response message from the control interface.\n" },
-
-    { "write_response",
-      (PyCFunction)xu_port_write_response,
-      METH_VARARGS,
-      "Write a response message to the control interface.\n" },
-
-    { "request_to_read",
-      (PyCFunction)xu_port_request_to_read,
-      METH_VARARGS,
-      "Returns TRUE if there is a request message to read.\n" },
-
-
-    { "response_to_read",
-      (PyCFunction)xu_port_response_to_read,
-      METH_VARARGS,
-      "Returns TRUE if there is a response message to read.\n" },
-
-    { "register",
-      (PyCFunction)xu_port_register,
-      METH_VARARGS | METH_KEYWORDS,
-      "Register to receive a type of message on this channel.\n" },
-      
-    { "deregister",
-      (PyCFunction)xu_port_deregister,
-      METH_VARARGS | METH_KEYWORDS,
-      "Stop receiving a type of message on this port.\n" },
-
-    { "close",
-      (PyCFunction)xu_port_close,
-      METH_VARARGS,
-      "Close the port.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_port_type;
-
-static PyObject *xu_port_new(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    xu_port_object *xup;
-    u32 dom;
-    int port1 = 0, port2 = 0;
-    xcs_msg_t kmsg;
-
-    static char *kwd_list[] = { "dom", "local_port", "remote_port", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list,
-                                      &dom, &port1, &port2) )
-        return NULL;
-
-    xup = PyObject_New(xu_port_object, &xu_port_type);
-
-    xup->connected  = 0;
-    xup->remote_dom = dom;
-    
-    kmsg.type = XCS_CIF_NEW_CC;
-    kmsg.u.interface.dom         = xup->remote_dom;
-    kmsg.u.interface.local_port  = port1; 
-    kmsg.u.interface.remote_port = port2;
-    xcs_ctrl_send(&kmsg);
-    xcs_ctrl_read(&kmsg);
-    
-    if ( kmsg.result != XCS_RSLT_OK ) 
-        goto fail1;
-        
-    xup->local_port  = kmsg.u.interface.local_port;
-    xup->remote_port = kmsg.u.interface.remote_port;
-    xup->connected = 1;
-                
-    return (PyObject *)xup;
-
- fail1:
-    PyObject_Del((PyObject *)xup);
-    PyErr_SetString(PyExc_ValueError, "cannot create port");
-    return NULL;
-}
-
-static PyObject *xu_port_getattr(PyObject *obj, char *name)
-{
-    xu_port_object *xup = (xu_port_object *)obj;
-
-    if ( strcmp(name, "local_port") == 0 )
-    {
-        return PyInt_FromLong(xup->connected ? xup->local_port : -1);
-    }
-    if ( strcmp(name, "remote_port") == 0 )
-    {
-        return PyInt_FromLong(xup->connected ? xup->remote_port : -1);
-    }
-    if ( strcmp(name, "remote_dom") == 0 )
-    {
-        return PyInt_FromLong(xup->remote_dom);
-    }
-    if ( strcmp(name, "connected") == 0 )
-    {
-        return PyInt_FromLong(xup->connected);
-    }
-    return Py_FindMethod(xu_port_methods, obj, name);
-}
-
-static void xu_port_dealloc(PyObject *self)
-{
-    xu_port_object *xup = (xu_port_object *)self;
-
-    _xu_port_close(xup);
-
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_port_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "port",
-    sizeof(xu_port_object),
-    0,
-    xu_port_dealloc,     /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_port_getattr,     /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** BUFFER ***********************
- */
-
-#define BUFSZ 65536
-#define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
-typedef unsigned int BUF_IDX;
-
-typedef struct {
-    PyObject_HEAD;
-    char        *buf;
-    unsigned int prod, cons;
-} xu_buffer_object;
-
-static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
-{
-    PyObject *str1, *str2;
-    int len1, len2, c = MASK_BUF_IDX(xub->cons);
-
-    len1 = xub->prod - xub->cons;
-    if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
-        len1 = BUFSZ - c;
-    if ( len1 > max )         /* clip to specified maximum */
-        len1 = max;
-    if ( len1 < 0 )           /* sanity */
-        len1 = 0;
-
-    if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
-        return NULL;
-
-    if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
-    {
-        len2 = max - len1;
-        if ( len2 > MASK_BUF_IDX(xub->prod) )
-            len2 = MASK_BUF_IDX(xub->prod);
-        if ( len2 > 0 )
-        {
-            str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
-            if ( str2 == NULL )
-                return NULL;
-            PyString_ConcatAndDel(&str1, str2);
-            if ( str1 == NULL )
-                return NULL;
-        }
-    }
-
-    return str1;
-}
-
-static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    int max = 1024;
-
-    if ( !PyArg_ParseTuple(args, "|i", &max) )
-        return NULL;
-    
-    return __xu_buffer_peek(xub, max);
-}
-
-static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    PyObject *str;
-    int max = 1024;
-
-    if ( !PyArg_ParseTuple(args, "|i", &max) )
-        return NULL;
-
-    if ( (str = __xu_buffer_peek(xub, max)) != NULL )
-        xub->cons += PyString_Size(str);
-
-    return str;
-}
-
-static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    int max, len;
-
-    if ( !PyArg_ParseTuple(args, "i", &max) )
-        return NULL;
-
-    len = xub->prod - xub->cons;
-    if ( len > max )
-        len = max;
-    if ( len < 0 )
-        len = 0;
-
-    xub->cons += len;
-
-    return PyInt_FromLong(len);
-}
-
-static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    char *str;
-    int len, len1, len2;
-
-    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
-        return NULL;
-
-    len1 = len;
-    if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
-        len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
-    if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
-        len1 = BUFSZ - (xub->prod - xub->cons);
-
-    if ( len1 == 0 )
-        return PyInt_FromLong(0);
-
-    memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
-    xub->prod += len1;
-
-    if ( len1 < len )
-    {
-        len2 = len - len1;
-        if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
-            len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
-        if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
-            len2 = BUFSZ - (xub->prod - xub->cons);
-        if ( len2 != 0 )
-        {
-            memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
-            xub->prod += len2;
-            return PyInt_FromLong(len1 + len2);
-        }
-    }
-
-    return PyInt_FromLong(len1);
-}
-
-static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( xub->cons == xub->prod )
-        return PyInt_FromLong(1);
-
-    return PyInt_FromLong(0);
-}
-
-static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (xub->prod - xub->cons) == BUFSZ )
-        return PyInt_FromLong(1);
-
-    return PyInt_FromLong(0);
-}
-
-static PyObject *xu_buffer_size(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    return PyInt_FromLong(xub->prod - xub->cons);
-}
-
-static PyObject *xu_buffer_space(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    return PyInt_FromLong(BUFSZ - (xub->prod - xub->cons));
-}
-
-static PyMethodDef xu_buffer_methods[] = {
-    { "peek", 
-      (PyCFunction)xu_buffer_peek,
-      METH_VARARGS,
-      "Peek up to @max bytes from the buffer. Returns a string.\n" },
-
-    { "read", 
-      (PyCFunction)xu_buffer_read,
-      METH_VARARGS,
-      "Read up to @max bytes from the buffer. Returns a string.\n" },
-
-    { "discard", 
-      (PyCFunction)xu_buffer_discard,
-      METH_VARARGS,
-      "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
-
-    { "write", 
-      (PyCFunction)xu_buffer_write,
-      METH_VARARGS,
-      "Write @string into buffer. Return number of bytes written.\n" },
-
-    { "empty", 
-      (PyCFunction)xu_buffer_empty,
-      METH_VARARGS,
-      "Return TRUE if the buffer is empty.\n" },
-
-    { "full", 
-      (PyCFunction)xu_buffer_full,
-      METH_VARARGS,
-      "Return TRUE if the buffer is full.\n" },
-
-    { "size", 
-      (PyCFunction)xu_buffer_size,
-      METH_VARARGS,
-      "Return number of bytes in the buffer.\n" },
-
-    { "space", 
-      (PyCFunction)xu_buffer_space,
-      METH_VARARGS,
-      "Return space left in the buffer.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_buffer_type;
-
-static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
-
-    if ( (xub->buf = malloc(BUFSZ)) == NULL )
-    {
-        PyObject_Del((PyObject *)xub);
-        return NULL;
-    }
-
-    xub->prod = xub->cons = 0;
-
-    return (PyObject *)xub;
-}
-
-static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
-{
-    return Py_FindMethod(xu_buffer_methods, obj, name);
-}
-
-static void xu_buffer_dealloc(PyObject *self)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    free(xub->buf);
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_buffer_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "buffer",
-    sizeof(xu_buffer_object),
-    0,
-    xu_buffer_dealloc,   /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_buffer_getattr,   /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** MODULE WRAPPER ***********************
- */
-
-static void handle_child_death(int dummy)
-{
-    while ( waitpid(-1, NULL, WNOHANG) > 0 )
-        continue;
-}
-
-static PyObject *xu_autoreap(PyObject *self, PyObject *args)
-{
-    struct sigaction sa;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    memset(&sa, 0, sizeof(sa));
-    sa.sa_handler = handle_child_death;
-    sigemptyset(&sa.sa_mask);
-    sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
-    (void)sigaction(SIGCHLD, &sa, NULL);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyMethodDef xu_methods[] = {
-    { "notifier", xu_notifier_new, METH_VARARGS, 
-      "Create a new notifier." },
-    { "message", xu_message_new, METH_VARARGS, 
-      "Create a new communications message." },
-    { "port", (PyCFunction)xu_port_new, METH_VARARGS | METH_KEYWORDS, 
-      "Create a new communications port." },
-    { "buffer", xu_buffer_new, METH_VARARGS, 
-      "Create a new ring buffer." },
-    { "autoreap", xu_autoreap, METH_VARARGS,
-      "Ensure that zombie children are automatically reaped by the OS." },
-    { NULL, NULL, 0, NULL }
-};
-
-PyMODINIT_FUNC initxu(void)
-{
-    PyObject *m, *d;
-
-    m = Py_InitModule(XENPKG, xu_methods);
-
-    d = PyModule_GetDict(m);
-    port_error = PyErr_NewException(XENPKG ".PortError", NULL, NULL);
-    PyDict_SetItemString(d, "PortError", port_error);
-
-    /* KAF: This ensures that we get debug output in a timely manner. */
-    setbuf(stdout, NULL);
-    setbuf(stderr, NULL);
-}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/messages.py
--- a/tools/python/xen/xend/server/messages.py  Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,462 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
-#============================================================================
-
-import sys
-import struct
-import types
-
-from xen.lowlevel import xu
-
-DEBUG = False
-
-#PORT_WILDCARD = 0xefffffff
-
-"""Wildcard for the control message types."""
-TYPE_WILDCARD = 0xffff
-
-""" All message formats.
-Added to incrementally for the various message types.
-See below.
-"""
-msg_formats = {}
-
-#============================================================================
-# Block interface message types.
-#============================================================================
-
-CMSG_BLKIF_BE = 1
-CMSG_BLKIF_FE = 2
-
-CMSG_BLKIF_FE_INTERFACE_STATUS      =  0
-CMSG_BLKIF_FE_DRIVER_STATUS         = 32
-CMSG_BLKIF_FE_INTERFACE_CONNECT     = 33
-CMSG_BLKIF_FE_INTERFACE_DISCONNECT  = 34
-CMSG_BLKIF_FE_INTERFACE_QUERY       = 35
-
-CMSG_BLKIF_BE_CREATE                =  0
-CMSG_BLKIF_BE_DESTROY               =  1
-CMSG_BLKIF_BE_CONNECT               =  2
-CMSG_BLKIF_BE_DISCONNECT            =  3
-CMSG_BLKIF_BE_VBD_CREATE            =  4
-CMSG_BLKIF_BE_VBD_DESTROY           =  5
-CMSG_BLKIF_BE_DRIVER_STATUS         = 32
-
-BLKIF_DRIVER_STATUS_DOWN            =  0
-BLKIF_DRIVER_STATUS_UP              =  1
-
-BLKIF_INTERFACE_STATUS_CLOSED       =  0 #/* Interface doesn't exist.    */
-BLKIF_INTERFACE_STATUS_DISCONNECTED =  1 #/* Exists but is disconnected. */
-BLKIF_INTERFACE_STATUS_CONNECTED    =  2 #/* Exists and is connected.    */
-BLKIF_INTERFACE_STATUS_CHANGED      =  3 #/* A device has been added or 
removed. */
-
-BLKIF_BE_STATUS_OKAY                =  0
-BLKIF_BE_STATUS_ERROR               =  1
-BLKIF_BE_STATUS_INTERFACE_EXISTS    =  2
-BLKIF_BE_STATUS_INTERFACE_NOT_FOUND =  3
-BLKIF_BE_STATUS_INTERFACE_CONNECTED =  4
-BLKIF_BE_STATUS_VBD_EXISTS          =  5
-BLKIF_BE_STATUS_VBD_NOT_FOUND       =  6
-BLKIF_BE_STATUS_OUT_OF_MEMORY       =  7
-BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND   =  8
-BLKIF_BE_STATUS_MAPPING_ERROR       =  9
-
-blkif_formats = {
-    'blkif_be_connect_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT),
-    # Connect be to fe (in response to blkif_fe_interface_connect_t).
-
-    'blkif_be_create_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE),
-    # Create be.
-
-    'blkif_be_disconnect_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT),
-    # Disconnect be from fe.
-
-    'blkif_be_destroy_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY),
-    # Destroy be (after disconnect).
-    # Make be do this even if no disconnect (and destroy all vbd too).
-
-    'blkif_be_vbd_create_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE),
-    # Create a vbd device.
-
-    'blkif_be_vbd_destroy_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY),
-    # Destroy a vbd.
-
-    # Add message to query be for state and vbds.
-
-    'blkif_fe_interface_status_t':
-    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS),
-    # Notify device status to fe.
-    # Also used to notify 'any' device change with status 
BLKIF_INTERFACE_STATUS_CHANGED.
-
-    'blkif_fe_driver_status_t':
-    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS),
-    # Comes from fe, treated as notifying that fe has come up/changed.
-    # Xend sets be(s) to BLKIF_INTERFACE_STATUS_DISCONNECTED,
-    # sends blkif_fe_interface_status_t to fe (from each be).
-    #
-    # Reply with i/f count.
-    # The i/f sends probes (using -ve trick), we reply with the info.
-
-    'blkif_fe_interface_connect_t':
-    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT),
-    # Comes from fe, passing shmem frame to use for be.
-    # fe sends when gets blkif_fe_interface_status_t with state 
NETIF_INTERFACE_STATUS_DISCONNECTED.
-    # Xend creates event channel and notifies be.
-    # Then notifies fe of event channel with blkif_fe_interface_status_t.
-
-    # Add message to kick fe to probe for devices.
-    # Just report new devices to fe?
-
-    # 
-    # Add message for fe to probe a device.
-    # And probing with id -1 should return first.
-    # And probing with id -n should return first device with id > n.
-    
-    # Add message to query fe for state and vbds.
-}
-
-msg_formats.update(blkif_formats)
-
-#============================================================================
-# Network interface message types.
-#============================================================================
-
-CMSG_NETIF_BE = 3
-CMSG_NETIF_FE = 4
-
-CMSG_NETIF_FE_INTERFACE_STATUS      =  0
-CMSG_NETIF_FE_DRIVER_STATUS         = 32
-CMSG_NETIF_FE_INTERFACE_CONNECT     = 33
-CMSG_NETIF_FE_INTERFACE_DISCONNECT  = 34
-CMSG_NETIF_FE_INTERFACE_QUERY       = 35
-
-CMSG_NETIF_BE_CREATE                =  0
-CMSG_NETIF_BE_DESTROY               =  1
-CMSG_NETIF_BE_CONNECT               =  2
-CMSG_NETIF_BE_DISCONNECT            =  3
-CMSG_NETIF_BE_CREDITLIMIT           =  4
-CMSG_NETIF_BE_DRIVER_STATUS         = 32
-
-NETIF_INTERFACE_STATUS_CLOSED       =  0 #/* Interface doesn't exist.    */
-NETIF_INTERFACE_STATUS_DISCONNECTED =  1 #/* Exists but is disconnected. */
-NETIF_INTERFACE_STATUS_CONNECTED    =  2 #/* Exists and is connected.    */
-NETIF_INTERFACE_STATUS_CHANGED      =  3 #/* A device has been added or 
removed. */
-
-NETIF_DRIVER_STATUS_DOWN            =  0
-NETIF_DRIVER_STATUS_UP              =  1
-
-netif_formats = {
-    'netif_be_connect_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT),
-
-    'netif_be_create_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE),
-
-    'netif_be_disconnect_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT),
-
-    'netif_be_destroy_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY),
-
-    'netif_be_creditlimit_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_CREDITLIMIT),
-
-    'netif_be_driver_status_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS),
-
-    'netif_fe_driver_status_t':
-    (CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS),
-
-    'netif_fe_interface_connect_t':
-    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT),
-
-    'netif_fe_interface_status_t':
-    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS),
-    }
-
-msg_formats.update(netif_formats)
-
-#============================================================================
-# USB interface message types.
-#============================================================================
-
-CMSG_USBIF_BE = 8
-CMSG_USBIF_FE = 9
-
-CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED = 0
-
-CMSG_USBIF_FE_DRIVER_STATUS_CHANGED = 32
-CMSG_USBIF_FE_INTERFACE_CONNECT     = 33
-CMSG_USBIF_FE_INTERFACE_DISCONNECT  = 34
-
-USBIF_DRIVER_STATUS_DOWN = 0
-USBIF_DRIVER_STATUS_UP   = 1
-
-USBIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
-USBIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
-USBIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
-
-CMSG_USBIF_BE_CREATE = 0
-CMSG_USBIF_BE_DESTROY = 1
-CMSG_USBIF_BE_CONNECT = 2
-
-CMSG_USBIF_BE_DISCONNECT = 3
-CMSG_USBIF_BE_CLAIM_PORT = 4
-CMSG_USBIF_BE_RELEASE_PORT = 5
-
-CMSG_USBIF_BE_DRIVER_STATUS_CHANGED = 32
-
-USBIF_BE_STATUS_OKAY = 0
-USBIF_BE_STATUS_ERROR = 1
-
-USBIF_BE_STATUS_INTERFACE_EXISTS = 2
-USBIF_BE_STATUS_INTERFACE_NOT_FOUND = 3
-USBIF_BE_STATUS_INTERFACE_CONNECTED = 4
-USBIF_BE_STATUS_OUT_OF_MEMORY = 7
-USBIF_BE_STATUS_MAPPING_ERROR = 9
-
-usbif_formats = {
-    'usbif_be_create_t':
-    (CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE),
-
-    'usbif_be_destroy_t':
-    (CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY),
-
-    'usbif_be_connect_t':
-    (CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT),
-
-    'usbif_be_disconnect_t':
-    (CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT),
-
-    'usbif_be_claim_port_t':
-    (CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT),
-
-    'usbif_be_release_port_t':
-    (CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT),
-
-    'usbif_fe_interface_status_changed_t':
-    (CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED),
-
-    'usbif_fe_driver_status_changed_t':
-    (CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED),
-
-    'usbif_fe_interface_connect_t':
-    (CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT),
-
-    'usbif_fe_interface_disconnect_t':
-    (CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT),
-   
-    }
-    
-msg_formats.update(usbif_formats)
-
-#============================================================================
-# Domain shutdown message types.
-#============================================================================
-
-CMSG_SHUTDOWN = 6
-
-CMSG_SHUTDOWN_POWEROFF  = 0
-CMSG_SHUTDOWN_REBOOT    = 1
-CMSG_SHUTDOWN_SUSPEND   = 2
-CMSG_SHUTDOWN_SYSRQ     = 3
-
-STOPCODE_shutdown       = 0
-STOPCODE_reboot         = 1
-STOPCODE_suspend        = 2
-STOPCODE_sysrq          = 3
-
-shutdown_formats = {
-    'shutdown_poweroff_t':
-    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_POWEROFF),
-    
-    'shutdown_reboot_t':
-    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_REBOOT),
-
-    'shutdown_suspend_t':
-    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SUSPEND),
-    
-    'shutdown_sysrq_t':
-    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SYSRQ)
-    }
-
-msg_formats.update(shutdown_formats)
-
-#============================================================================
-# Domain memory reservation message.
-#============================================================================
-
-CMSG_MEM_REQUEST = 7
-CMSG_MEM_REQUEST_SET = 0
-
-mem_request_formats = {
-    'mem_request_t':
-    (CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET)
-    }
-
-msg_formats.update(mem_request_formats)
-
-#============================================================================
-# Domain vcpu hotplug message.
-#============================================================================
-
-CMSG_VCPU_HOTPLUG     = 10
-CMSG_VCPU_HOTPLUG_OFF = 0
-CMSG_VCPU_HOTPLUG_ON  = 1
-
-vcpu_hotplug_formats = {
-    'vcpu_hotplug_off_t':
-    (CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_OFF),
-
-    'vcpu_hotplug_on_t':
-    (CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_ON)
-    }
-
-msg_formats.update(vcpu_hotplug_formats)
-
-#============================================================================
-class Msg:
-    pass
-
-_next_msgid = 0
-
-def nextid():
-    """Generate the next message id.
-
-    @return: message id
-    @rtype: int
-    """
-    global _next_msgid
-    _next_msgid += 1
-    return _next_msgid
-
-def packMsg(ty, params):
-    """Pack a message.
-    Any I{mac} parameter is passed in as an int[6] array and converted.
-
-    @param ty: message type name
-    @type ty: string
-    @param params: message parameters
-    @type params: dicy
-    @return: message
-    @rtype: xu message
-    """
-    msgid = nextid()
-    if DEBUG: print '>packMsg', msgid, ty, params
-    (major, minor) = msg_formats[ty]
-    args = {}
-    for (k, v) in params.items():
-        if k in ['mac', 'be_mac']:
-            for i in range(0, 6):
-                args['%s[%d]' % (k, i)] = v[i]
-        else:
-            args[k] = v
-    msg = xu.message(major, minor, msgid, args)
-    if DEBUG: print '<packMsg', msg.get_header()['id'], ty, args
-    return msg
-
-def unpackMsg(ty, msg):
-    """Unpack a message.
-    Any mac addresses in the message are converted to int[6] array
-    in the return dict.
-
-    @param ty:  message type
-    @type ty: string
-    @param msg: message
-    @type msg: xu message
-    @return: parameters
-    @rtype: dict
-    """
-    args = msg.get_payload()
-    if DEBUG: print '>unpackMsg', args
-    if isinstance(args, types.StringType):
-        args = {'value': args}
-    else:
-        mac = [0, 0, 0, 0, 0, 0]
-        macs = []
-        for (k, v) in args.items():
-            if k.startswith('mac['):
-                macs.append(k)
-                i = int(k[4:5])
-                mac[i] = v
-            else:
-                pass
-        if macs:
-            args['mac'] = mac
-            #print 'macs=', macs
-            #print 'args=', args
-            for k in macs:
-                del args[k]
-    if DEBUG:
-        msgid = msg.get_header()['id']
-        print '<unpackMsg', msgid, ty, args
-    return args
-
-def msgTypeName(ty, subty):
-    """Convert a message type, subtype pair to a message type name.
-
-    @param ty: message type
-    @type ty: int
-    @param subty: message subtype
-    @type ty: int
-    @return: message type name (or None)
-    @rtype: string or None
-    """
-    for (name, info) in msg_formats.items():
-        if info[0] == ty and info[1] == subty:
-            return name
-    return None
-
-def printMsg(msg, out=sys.stdout, all=False):
-    """Print a message.
-
-    @param msg: message
-    @type msg: xu message
-    @param out: where to print to
-    @type out: stream
-    @param all: print payload if true
-    @type all: bool
-    """
-    hdr = msg.get_header()
-    major = hdr['type']
-    minor = hdr['subtype']
-    msgid = hdr['id']
-    ty = msgTypeName(major, minor)
-    print >>out, 'message:', 'type=', ty, '%d:%d' % (major, minor), 'id=%d' % 
msgid
-    if all:
-        print >>out, 'payload=', msg.get_payload()
-
-
-def getMessageType(msg):
-    """Get a 2-tuple of the message type and subtype.
-
-    @param msg: message
-    @type  msg: xu message
-    @return: type info
-    @rtype:  (int, int)
-    """
-    hdr = msg.get_header()
-    return (hdr['type'], hdr.get('subtype'))
-
-def getMessageId(msg):
-    hdr = msg.get_header()
-    return hdr['id']
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/Makefile
--- a/tools/xcs/Makefile        Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,49 +0,0 @@
-# Makefile for XCS
-# Andrew Warfield, 2004
-
-XEN_ROOT=../..
-include $(XEN_ROOT)/tools/Rules.mk
-
-XCS_INSTALL_DIR = /usr/sbin
-
-INSTALL         = install
-INSTALL_PROG    = $(INSTALL) -m0755
-INSTALL_DIR     = $(INSTALL) -d -m0755
-
-CC       = gcc
-CFLAGS   = -Wall -Werror -g3 -D _XOPEN_SOURCE=600
-
-CFLAGS  += -I $(XEN_XC)
-CFLAGS  += -I $(XEN_LIBXC)
-
-SRCS    :=
-SRCS    += ctrl_interface.c
-SRCS    += bindings.c
-SRCS    += connection.c
-SRCS    += evtchn.c
-SRCS    += xcs.c
-
-HDRS     = $(wildcard *.h)
-OBJS     = $(patsubst %.c,%.o,$(SRCS))
-BIN      = xcs
-
-all: $(BIN) xcsdump
-
-clean:
-       $(RM) *.a *.so *.o *.rpm $(BIN) xcsdump
-
-xcsdump: xcsdump.c dump.c
-       $(CC) $(CFLAGS) -o xcsdump xcsdump.c -L$(XEN_LIBXC) \
-              ctrl_interface.c evtchn.c dump.c -lxenctrl
-
-$(BIN): $(OBJS)
-       $(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -lxenctrl 
-
-$(OBJS): $(HDRS)
-
-install: xcs xcsdump
-       $(INSTALL_DIR) -p $(DESTDIR)/$(XCS_INSTALL_DIR)
-       $(INSTALL_DIR) -p $(DESTDIR)/usr/include
-       $(INSTALL_PROG) xcs $(DESTDIR)/$(XCS_INSTALL_DIR)
-       $(INSTALL_PROG) xcsdump $(DESTDIR)/$(XCS_INSTALL_DIR)
-       $(INSTALL_PROG) xcs_proto.h $(DESTDIR)/usr/include
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/bindings.c
--- a/tools/xcs/bindings.c      Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,179 +0,0 @@
-/* bindings.c
- *
- * Manage subscriptions for the control interface switch.
- *
- * (c) 2004, Andrew Warfield
- *
- */
-
-/* Interfaces:
- *
- * xcs_bind   (port, type, connection)
- *   - Register connection to receive messages of this type.
- * xcs_unbind (port, type, connection)
- *   - Remove an existing registration. (Must be an exact match)
- * xcs_lookup (port, type)
- *   - Return a list of connections matching a registration.
- * 
- * - All connections have a connection.bindings list of current bindings.
- * - (port, type) pairs may be wildcarded with -1.
- */
- 
-#include <stdio.h>
-#include <stdlib.h> 
-#include <errno.h>
-#include <string.h>
-#include "xcs.h"
-
-
-typedef struct binding_ent_st {
-    connection_t          *con;
-    struct binding_ent_st *next;
-} binding_ent_t;
-
-#define BINDING_TABLE_SIZE       1024
-
-static binding_ent_t *binding_table[BINDING_TABLE_SIZE];
-        
-#define PORT_WILD(_ent) ((_ent)->port == PORT_WILDCARD)
-#define TYPE_WILD(_ent) ((_ent)->type == TYPE_WILDCARD)
-#define FULLY_WILD(_ent) (PORT_WILD(_ent) && TYPE_WILD(_ent))
-
-#define BINDING_HASH(_key) \
-    ((((_key)->port * 11) ^ (_key)->type) % BINDING_TABLE_SIZE)
-    
-    
-void init_bindings(void)
-{
-    memset(binding_table, 0, sizeof(binding_table));
-}
-
-static int table_add(binding_ent_t *table[],
-                            connection_t *con, 
-                            binding_key_t *key)
-{
-    binding_ent_t **curs, *ent;
-        
-    curs = &table[BINDING_HASH(key)];
-    
-    while (*curs != NULL) {
-        if ((*curs)->con == con) {
-            DPRINTF("Tried to add an ent that already existed.\n");
-            goto done;
-        }
-        curs = &(*curs)->next;
-    }
-    
-    if (connection_add_binding(con, key) != 0)
-    {
-       DPRINTF("couldn't add binding on connection (%lu)\n", con->id);
-       goto fail;
-    }
-    ent = (binding_ent_t *)malloc(sizeof(binding_ent_t));
-    if (ent == 0) {
-       DPRINTF("couldn't alloc binding ent!\n");
-       goto fail;
-    }
-    ent->con = con;
-    ent->next = NULL;
-    *curs = ent;
-    
-done:
-    return 0;
-
-fail:
-    return -1;
-}
-
-
-static inline int binding_has_colliding_hashes(connection_t *con, 
-                                               binding_key_t *key)
-{
-    int hash, count = 0;
-    binding_key_ent_t *ent;
-    
-    ent = con->bindings; 
-    hash = BINDING_HASH(key);
-    
-    while (ent != NULL) {
-        if (BINDING_HASH(&ent->key) == hash) count ++;
-        ent = ent->next;
-    }
-    
-    return (count > 1);
-}
-static int table_remove(binding_ent_t *table[],
-                            connection_t *con, 
-                            binding_key_t *key)
-{
-    binding_ent_t **curs, *ent;
-    
-    if (!binding_has_colliding_hashes(con, key))
-    {
-    
-        curs = &table[BINDING_HASH(key)];
-
-        while ((*curs != NULL) && ((*curs)->con != con))
-           curs = &(*curs)->next;
-
-        if (*curs != NULL) {
-           ent = *curs;
-           *curs = (*curs)->next;
-           free(ent);
-        }
-    }
-    
-    connection_remove_binding(con, key);
-    
-    return 0;    
-}
-
-int xcs_bind(connection_t *con, int port, u16 type)
-{
-    binding_key_t  key;
-    
-    key.port = port;
-    key.type = type;
-    
-    return table_add(binding_table, con, &key);  
-}
-
-int xcs_unbind(connection_t *con, int port, u16 type)
-{
-    binding_key_t  key;
-    
-    key.port = port;
-    key.type = type;
-    
-    return table_remove(binding_table, con, &key); 
-}
-
-
-static void for_each_binding(binding_ent_t *list, binding_key_t *key, 
-                void (*f)(connection_t *, void *), void *arg)
-{
-    while (list != NULL) 
-    {
-        if (connection_has_binding(list->con, key))
-            f(list->con, arg);
-        list = list->next;
-    }  
-}
-
-void xcs_lookup(int port, u16 type, void (*f)(connection_t *, void *), 
-                void *arg)
-{
-    binding_key_t  key;
-            
-    key.port  = port; key.type = type;
-    for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
-            
-    key.port  = port; key.type = TYPE_WILDCARD;
-    for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
-            
-    key.port  = PORT_WILDCARD; key.type = type;
-    for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
-            
-    key.port  = PORT_WILDCARD; key.type = TYPE_WILDCARD;
-    for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
-}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/connection.c
--- a/tools/xcs/connection.c    Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,157 +0,0 @@
-/*
- * connection.c
- *
- * State associated with a client connection to xcs.
- *
- * Copyright (c) 2004, Andrew Warfield
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "xcs.h"
-
-connection_t *connection_list = NULL;
-
-#define CONNECTED(_c) (((_c)->ctrl_fd != -1) || ((_c)->data_fd != -1))
-
-connection_t *get_con_by_session(unsigned long session_id)
-{
-    connection_t **c, *ent = NULL;
-    
-    c = &connection_list;
-    
-    DPRINTF("looking for id: %lu : %lu\n", session_id, (*c)->id);
-    
-    while (*c != NULL) 
-    {
-        if ((*c)->id == session_id) 
-            return (*c);
-        c = &(*c)->next;
-    }
-    
-    return ent;
-}
-
-connection_t *connection_new()
-{
-    connection_t *con;
-    
-    con = (connection_t *)malloc(sizeof(connection_t));
-    if (con == NULL)
-    {
-        DPRINTF("couldn't allocate a new connection\n");
-        return NULL;
-    }
-    
-    con->bindings = NULL;
-    con->data_fd = -1;
-    con->ctrl_fd = -1;
-    
-    /* connections need a unique session id. 
-     * - this approach probably gets fixed later, but for the moment
-     * is unique, and clearly identifies a connection.
-     */
-    con->id = (unsigned long)con;
-    
-    /* add it to the connection list */
-    con->next = connection_list;
-    connection_list = con;
-    
-    return (con);
-}
-
-void connection_free(connection_t *con)
-{
-    /* first free all subscribed bindings: */
-    
-    while (con->bindings != NULL)
-        xcs_unbind(con, con->bindings->key.port, con->bindings->key.type);
-    
-    /* now free the connection. */
-    free(con);
-}
-    
-int connection_add_binding(connection_t *con, binding_key_t *key)
-{
-    binding_key_ent_t *key_ent;
-    
-    key_ent = (binding_key_ent_t *)malloc(sizeof(binding_key_ent_t));
-    if (key_ent == NULL)
-    {
-        DPRINTF("couldn't alloc key in connection_add_binding\n");
-        return -1;    
-    }
-    
-    key_ent->key = *key;
-    key_ent->next = con->bindings;
-    con->bindings = key_ent;
-    
-    return 0;
-}
-
-int connection_remove_binding(connection_t *con, binding_key_t *key)
-{
-    binding_key_ent_t *key_ent;
-    binding_key_ent_t **curs = &con->bindings;
-    
-    while ((*curs != NULL) && (!BINDING_KEYS_EQUAL(&(*curs)->key, key)))
-        curs = &(*curs)->next;
-    
-    if (*curs != NULL) {
-        key_ent = *curs;
-        *curs = (*curs)->next;
-        free(key_ent);
-    }
-    
-    return 0;   
-}
-
-
-int connection_has_binding(connection_t *con, binding_key_t *key)
-{
-    binding_key_ent_t *ent;
-    int ret = 0;
-    
-    ent = con->bindings;
-    
-    while (ent != NULL) 
-    {
-        if (BINDING_KEYS_EQUAL(key, &ent->key))
-        {
-            ret = 1;
-            break;
-        }
-        ent = ent->next;
-    }
-    
-    return ret;
-}
-
-
-void gc_connection_list(void)
-{
-    connection_t **c, *ent = NULL;
-    struct timeval now, delta;
-
-    c = &connection_list;
-    gettimeofday(&now, NULL);
-
-    while ( *c != NULL )
-    {
-        if ( !CONNECTED(*c) )
-        {
-            timersub(&now, &(*c)->disconnect_time, &delta);
-            if ( delta.tv_sec >= XCS_SESSION_TIMEOUT )
-            {
-                DPRINTF("        : Freeing connection %lu after %lds\n", 
-                     (*c)->id, delta.tv_sec);
-                ent = *c;
-                *c = (*c)->next;
-                connection_free(ent);
-                continue;
-            }
-        }
-        c = &(*c)->next;
-    }
-}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/ctrl_interface.c
--- a/tools/xcs/ctrl_interface.c        Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,269 +0,0 @@
-/* control_interface.c
- *
- * Interfaces to control message rings to VMs.
- *
- * Most of this is directly based on the original xu interface to python 
- * written by Keir Fraser.
- *
- * (c) 2004, Andrew Warfield
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include "xcs.h"
-
-static int xc_handle = -1;
-
-/* Called at start-of-day when using the control channel interface. */
-int ctrl_chan_init(void)
-{
-    if ( (xc_handle = xc_interface_open()) == -1 )
-    {
-        DPRINTF("Could not open Xen control interface");
-        return -1;
-    }
-    
-    return 0;
-}
-
-static control_if_t *map_control_interface(int fd, unsigned long pfn,
-                                          u32 dom)
-{
-    char *vaddr = xc_map_foreign_range( fd, dom, PAGE_SIZE,
-                                       PROT_READ|PROT_WRITE, pfn );
-    if ( vaddr == NULL )
-        return NULL;
-    return (control_if_t *)(vaddr + 2048);
-}
-
-static void unmap_control_interface(int fd, control_if_t *c)
-{
-    char *vaddr = (char *)c - 2048;
-    (void)munmap(vaddr, PAGE_SIZE);
-}
-
-int ctrl_chan_notify(control_channel_t *cc)
-{
-    return xc_evtchn_send(xc_handle, cc->local_port);
-}
-
-int ctrl_chan_read_request(control_channel_t *cc, xcs_control_msg_t *dmsg)
-{
-    control_msg_t     *smsg;
-    RING_IDX          c = cc->tx_ring.req_cons;
-
-    if ( !RING_HAS_UNCONSUMED_REQUESTS(&cc->tx_ring) )
-    {
-        DPRINTF("no request to read\n");
-        return -1;
-    }
-    
-    rmb(); /* make sure we see the data associated with the request */
-    smsg = RING_GET_REQUEST(&cc->tx_ring, c);
-    memcpy(&dmsg->msg, smsg, sizeof(*smsg));
-    if ( dmsg->msg.length > sizeof(dmsg->msg.msg) )
-        dmsg->msg.length = sizeof(dmsg->msg.msg);
-    cc->tx_ring.req_cons++;
-    return 0;
-}
-
-int ctrl_chan_write_request(control_channel_t *cc, 
-                            xcs_control_msg_t *smsg)
-{
-    control_msg_t *dmsg;
-    RING_IDX       p = cc->rx_ring.req_prod_pvt;
-    
-    if ( RING_FULL(&cc->rx_ring) )
-    {
-        DPRINTF("no space to write request");
-        return -ENOSPC;
-    }
-
-    dmsg = RING_GET_REQUEST(&cc->rx_ring, p);
-    memcpy(dmsg, &smsg->msg, sizeof(*dmsg));
-
-    wmb();
-    cc->rx_ring.req_prod_pvt++;
-    RING_PUSH_REQUESTS(&cc->rx_ring);
-    
-    return 0;
-}
-
-int ctrl_chan_read_response(control_channel_t *cc, xcs_control_msg_t *dmsg)
-{
-    control_msg_t     *smsg;
-    RING_IDX          c = cc->rx_ring.rsp_cons;
-    
-    if ( !RING_HAS_UNCONSUMED_RESPONSES(&cc->rx_ring) )
-    {
-        DPRINTF("no response to read");
-        return -1;
-    }
-
-    rmb(); /* make sure we see the data associated with the request */
-    smsg = RING_GET_RESPONSE(&cc->rx_ring, c);
-    memcpy(&dmsg->msg, smsg, sizeof(*smsg));
-    if ( dmsg->msg.length > sizeof(dmsg->msg.msg) )
-        dmsg->msg.length = sizeof(dmsg->msg.msg);
-    cc->rx_ring.rsp_cons++;
-    return 0;
-}
-
-int ctrl_chan_write_response(control_channel_t *cc, 
-                             xcs_control_msg_t *smsg)
-{
-    control_msg_t  *dmsg;
-    RING_IDX        p = cc->tx_ring.rsp_prod_pvt;
-
-    /* akw: if the ring is synchronous, you should never need this test! */
-    /* (but it was in the original code... )                             */
-    if ( cc->tx_ring.req_cons == cc->tx_ring.rsp_prod_pvt )
-    {
-        DPRINTF("no space to write response");
-        return -ENOSPC;
-    }
-
-    dmsg = RING_GET_RESPONSE(&cc->tx_ring, p);
-    memcpy(dmsg, &smsg->msg, sizeof(*dmsg));
-
-    wmb();
-    cc->tx_ring.rsp_prod_pvt++;
-    RING_PUSH_RESPONSES(&cc->tx_ring);
-    
-    return 0;
-}
-
-int ctrl_chan_request_to_read(control_channel_t *cc)
-{
-    return (RING_HAS_UNCONSUMED_REQUESTS(&cc->tx_ring));
-}
-
-int ctrl_chan_space_to_write_request(control_channel_t *cc)
-{
-    return (!(RING_FULL(&cc->rx_ring)));
-}
-
-int ctrl_chan_response_to_read(control_channel_t *cc)
-{
-    return (RING_HAS_UNCONSUMED_RESPONSES(&cc->rx_ring));
-}
-
-int ctrl_chan_space_to_write_response(control_channel_t *cc)
-{
-    /* again, there is something fishy here. */
-    return ( cc->tx_ring.req_cons != cc->tx_ring.rsp_prod_pvt );
-}
-
-int ctrl_chan_connect(control_channel_t *cc)
-{
-    xc_dominfo_t info;
-
-    if ( cc->connected )
-    {
-       return 0;
-    }
-
-    if ( (xc_domain_getinfo(xc_handle, cc->remote_dom, 1, &info) != 1) ||
-         (info.domid != cc->remote_dom) )
-    {
-        DPRINTF("Failed to obtain domain status");
-        return -1;
-    }
-
-    cc->interface = 
-        map_control_interface(xc_handle, info.shared_info_frame,
-                             cc->remote_dom);
-
-    if ( cc->interface == NULL )
-    {
-        DPRINTF("Failed to map domain control interface");
-        return -1;
-    }
-
-    /* Synchronise ring indexes. */
-    BACK_RING_ATTACH(&cc->tx_ring, &cc->interface->tx_ring, CONTROL_RING_MEM);
-    FRONT_RING_ATTACH(&cc->rx_ring, &cc->interface->rx_ring, CONTROL_RING_MEM);
-
-    cc->connected = 1;
-
-    return 0;
-}
-
-void ctrl_chan_disconnect(control_channel_t *cc)
-{
-    if ( cc->connected )
-       unmap_control_interface(xc_handle, cc->interface);
-    cc->connected = 0;
-}
-
-
-control_channel_t *ctrl_chan_new(u32 dom, int local_port, int remote_port)
-{
-    control_channel_t *cc;
-   
-    cc = (control_channel_t *)malloc(sizeof(control_channel_t));
-    if ( cc == NULL ) return NULL;
-    
-    cc->connected  = 0;
-    cc->remote_dom = dom;
-
-    if ( dom == 0 )
-    {
-        /*
-         * The control-interface event channel for DOM0 is already set up.
-         * We use an ioctl to discover the port at our end of the channel.
-         */
-        local_port  = ioctl(xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, 
-                            NULL);
-        remote_port = -1; /* We don't need the remote end of the DOM0 link. */
-        if ( local_port < 0 )
-        {
-            DPRINTF("Could not open channel to DOM0");
-            goto fail;
-        }
-    }
-    else if ( xc_evtchn_bind_interdomain(xc_handle, 
-                                         DOMID_SELF, dom, 
-                                         &local_port, &remote_port) != 0 )
-    {
-        DPRINTF("Could not open channel to domain");
-        goto fail;
-    }
-
-    cc->local_port  = local_port;
-    cc->remote_port = remote_port;
-
-    if ( ctrl_chan_connect(cc) != 0 )
-        goto fail;
-
-    return cc;
-    
- fail:
-    if ( dom != 0 )
-        (void)xc_evtchn_close(xc_handle, DOMID_SELF, local_port);
- 
-    free(cc);
-    
-    return NULL;        
-}
-
-void ctrl_chan_free(control_channel_t *cc)
-{
-    ctrl_chan_disconnect(cc);
-    if ( cc->remote_dom != 0 )
-        (void)xc_evtchn_close(xc_handle, DOMID_SELF, cc->local_port);
-    free(cc);
-}
-
-
-/* other libxc commands: */
-
-int ctrl_chan_bind_virq(int virq, int *port)
-{
-    return xc_evtchn_bind_virq(xc_handle, virq, port);
-}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/dump.c
--- a/tools/xcs/dump.c  Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,506 +0,0 @@
-/*\
- *  Copyright (C) International Business Machines  Corp., 2005
- *  Author(s): Anthony Liguori <aliguori@xxxxxxxxxx>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; under version 2 of the License.
- * 
- *  This program is distributed in the hope that 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 <stdio.h>
-#include <stdarg.h>
-
-#include "dump.h"
-
-#define str(a) # a
-#define error(a, ...) do { \
- _error("%s:%s():L%d: " a, __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__);\
-  exit(1); \
-} while (0)
-#define warn(a, ...) do { \
- _error("%s:%s():L%d: " a, __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__);\
-} while (0)
-#define debug(a, ...) do { \
- _error(a, ## __VA_ARGS__);\
-} while (0)
-
-void _error(const char *fmt, ...);
-
-#define debug_begin(a, b) debug("CMSG_" a "_" b " {")
-#define debug_end(a, b) debug("}")
-#define debug_field(a, b, c) debug("\t." str(b) " = " c, a->b)
-#define debug_field_mac(a, b) \
-  debug("\t." str(b) " = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", \
-        a->b[0], a->b[1], a->b[2], a->b[3], a->b[4], a->b[5])
-
-#define debug_dump(a, b, c) debug_hex("\t." str(b) " = ", a->b, a->c)
-
-#include <stdint.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-
-static int strcount(const char *str, char ch)
-{
-       int i;
-       int count = 0;
-
-       for (i = 0; str[i]; i++) {
-               if (str[i] == ch) {
-                       count++;
-               }
-       }
-
-       return count;
-}
-
-void debug_hex(const char *info, const uint8_t *data, size_t length)
-{
-       int indent = strlen(info) + (strcount(info, '\t') * 8 - 1);
-       int words_per_row = (2 * (80 - indent - 2) / 7) & ~1;
-       size_t i;
-
-       for (i = 0; i < length; i += words_per_row) {
-               size_t ind;
-
-               if (i == 0) {
-                       fprintf(stderr, "%s", info);
-               } else {
-                       int j;
-                       for (j = 0; j < indent; j++) {
-                               fprintf(stderr, " ");
-                       }
-               }
-
-               for (ind = 0; ind < words_per_row; ind++) {
-                       if (ind % 2 == 0) {
-                               fprintf(stderr, " ");
-                       }
-
-                       if (i + ind < length) {
-                               fprintf(stderr, "%.2X", data[i + ind]);
-                       } else {
-                               fprintf(stderr, "  ");
-                       }
-               }
-
-               fprintf(stderr, " ");
-
-               for (ind = 0; ind < words_per_row; ind++) {
-                       if (i + ind < length) {
-                               if (isprint(data[i + ind])) {
-                                       fprintf(stderr, "%c", data[i + ind]);
-                               } else {
-                                       fprintf(stderr, ".");
-                               }
-                       } else {
-                               fprintf(stderr, " ");
-                       }
-               }
-               fprintf(stderr, "\n");
-       }
-}
-
-void dump_msg(const control_msg_t *msg, uint64_t flags)
-{
-       if ((flags & (1 << msg->type)) == 0) {
-               return;
-       }
-
-       switch (msg->type) {
-       case CMSG_CONSOLE:
-               if (msg->subtype == CMSG_CONSOLE_DATA) {
-                       debug_begin("CONSOLE", "DATA");
-                       debug_field(msg, length, "%u");
-                       debug_dump(msg, msg, length);
-                       debug_end("CONSOLE", "DATA");
-               } else {
-                       debug_begin("CONSOLE", "UNKNOWN");
-                       debug_field(msg, subtype, "%u");
-                       debug_field(msg, length, "%u");
-                       debug_dump(msg, msg, length);
-                       debug_end("CONSOLE", "UNKNOWN");
-               }
-               break;
-       case CMSG_BLKIF_BE:
-               if (msg->subtype == CMSG_BLKIF_BE_CREATE) {
-                       blkif_be_create_t *load;
-                       load = (blkif_be_create_t *)msg->msg;
-                       debug_begin("BLKIF_BE", "CREATE");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, blkif_handle, "%u");
-                       debug_field(load, status, "%u");
-                       debug_end("BLKIF_BE", "CREATE");
-               } else if (msg->subtype == CMSG_BLKIF_BE_DESTROY) {
-                       blkif_be_destroy_t *load;
-                       load = (blkif_be_destroy_t *)msg->msg;
-                       debug_begin("BLKIF_BE", "DESTROY");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, blkif_handle, "%u");
-                       debug_field(load, status, "%u");
-                       debug_end("BLKIF_BE", "DESTROY");
-               } else if (msg->subtype == CMSG_BLKIF_BE_CONNECT) {
-                       blkif_be_connect_t *load;
-                       load = (blkif_be_connect_t *)msg->msg;
-                       debug_begin("BLKIF_BE", "CONNECT");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, blkif_handle, "%u");
-                       debug_field(load, shmem_frame, "%lu");
-                       debug_field(load, evtchn, "%u");
-                       debug_field(load, status, "%u");
-                       debug_end("BLKIF_BE", "CONNECT");
-               } else if (msg->subtype == CMSG_BLKIF_BE_DISCONNECT) {
-                       blkif_be_disconnect_t *load;
-                       load = (blkif_be_disconnect_t *)msg->msg;
-                       debug_begin("BLKIF_BE", "DISCONNECT");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, blkif_handle, "%u");
-                       debug_field(load, status, "%u");
-                       debug_end("BLKIF_BE", "DISCONNECT");
-               } else if (msg->subtype == CMSG_BLKIF_BE_VBD_CREATE) {
-                       blkif_be_vbd_create_t *load;
-                       load = (blkif_be_vbd_create_t *)msg->msg;
-                       debug_begin("BLKIF_BE", "VBD_CREATE");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, blkif_handle, "%u");
-                       debug_field(load, pdevice, "%u");
-                       debug_field(load, vdevice, "%u");
-                       debug_field(load, readonly, "%u");
-                       debug_field(load, status, "%u");
-                       debug_end("BLKIF_BE", "VBD_CREATE");
-               } else if (msg->subtype == CMSG_BLKIF_BE_VBD_DESTROY) {
-                       blkif_be_vbd_destroy_t *load;
-                       load = (blkif_be_vbd_destroy_t *)msg->msg;
-                       debug_begin("BLKIF_BE", "VBD_DESTROY");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, blkif_handle, "%u");
-                       debug_field(load, vdevice, "%u");
-                       debug_field(load, status, "%u");
-                       debug_end("BLKIF_BE", "VBD_DESTROY");
-               } else if (msg->subtype == CMSG_BLKIF_BE_DRIVER_STATUS) {
-                       blkif_be_driver_status_t *load;
-                       load = (blkif_be_driver_status_t *)msg->msg;
-                       debug_begin("BLKIF_BE", "DRIVER_STATUS");
-                       debug_field(load, status, "%u");
-                       debug_end("BLKIF_BE", "DRIVER_STATUS");
-               } else {
-                       debug_begin("BLKIF_BE", "UNKNOWN");
-                       debug_field(msg, subtype, "%u");
-                       debug_field(msg, length, "%u");
-                       debug_dump(msg, msg, length);
-                       debug_end("BLKIF_BE", "UNKNOWN");
-               }
-               break;
-       case CMSG_BLKIF_FE:
-               if (msg->subtype == CMSG_BLKIF_FE_INTERFACE_STATUS) {
-                       blkif_fe_interface_status_t *load;
-                       load = (blkif_fe_interface_status_t *)msg->msg;
-                       debug_begin("BLKIF_FE", "INTERFACE_STATUS");
-                       debug_field(load, handle, "%u");
-                       debug_field(load, status, "%u");
-                       debug_field(load, evtchn, "%u");
-                       debug_field(load, domid, "%u");
-                       debug_end("BLKIF_FE", "INTERFACE_STATUS");
-               } else if (msg->subtype == CMSG_BLKIF_FE_DRIVER_STATUS) {
-                       blkif_fe_driver_status_t *load;
-                       load = (blkif_fe_driver_status_t *)msg->msg;
-                       debug_begin("BLKIF_FE", "DRIVER_STATUS");
-                       debug_field(load, status, "%u");
-                       debug_field(load, max_handle, "%u");
-                       debug_end("BLKIF_FE", "DRIVER_STATUS");
-               } else if (msg->subtype == CMSG_BLKIF_FE_INTERFACE_CONNECT) {
-                       blkif_fe_interface_connect_t *load;
-                       load = (blkif_fe_interface_connect_t *)msg->msg;
-                       debug_begin("BLKIF_FE", "INTERFACE_CONNECT");
-                       debug_field(load, handle, "%u");
-                       debug_field(load, shmem_frame, "%lu");
-                       debug_end("BLKIF_FE", "INTERFACE_CONNECT");
-               } else if (msg->subtype == CMSG_BLKIF_FE_INTERFACE_DISCONNECT) {
-                       blkif_fe_interface_disconnect_t *load;
-                       load = (blkif_fe_interface_disconnect_t *)msg->msg;
-                       debug_begin("BLKIF_FE", "INTERFACE_DISCONNECT");
-                       debug_field(load, handle, "%u");
-                       debug_end("BLKIF_FE", "INTERFACE_DISCONNECT");
-               } else if (msg->subtype == CMSG_BLKIF_FE_INTERFACE_QUERY) {
-                       blkif_fe_interface_query_t *load;
-                       load = (blkif_fe_interface_query_t *)msg->msg;
-                       debug_begin("BLKIF_FE", "INTERFACE_QUERY");
-                       debug_field(load, handle, "%u");
-                       debug_field(load, status, "%u");
-                       debug_field(load, evtchn, "%u");
-                       debug_field(load, domid, "%u");
-                       debug_end("BLKIF_FE", "INTERFACE_QUERY");
-               } else {
-                       debug_begin("BLKIF_FE", "UNKNOWN");
-                       debug_field(msg, subtype, "%u");
-                       debug_field(msg, length, "%u");
-                       debug_dump(msg, msg, length);
-                       debug_end("BLKIF_FE", "UNKNOWN");
-               }
-               break;
-       case CMSG_NETIF_BE:
-               if (msg->subtype == CMSG_NETIF_BE_CREATE) {
-                       netif_be_create_t *load;
-                       load = (netif_be_create_t *)msg->msg;
-                       debug_begin("NETIF_BE", "CREATE");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, netif_handle, "%u");
-                       debug_field_mac(load, mac);
-                       debug_field_mac(load, be_mac);
-                       debug_field(load, status, "%u");
-                       debug_end("NETIF_BE", "CREATE");
-               } else if (msg->subtype == CMSG_NETIF_BE_DESTROY) {
-                       netif_be_destroy_t *load;
-                       load = (netif_be_destroy_t *)msg->msg;
-                       debug_begin("NETIF_BE", "DESTROY");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, netif_handle, "%u");
-                       debug_field(load, status, "%u");
-                       debug_end("NETIF_BE", "DESTROY");
-               } else if (msg->subtype == CMSG_NETIF_BE_CONNECT) {
-                       netif_be_connect_t *load;
-                       load = (netif_be_connect_t *)msg->msg;
-                       debug_begin("NETIF_BE", "CONNECT");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, netif_handle, "%u");
-                       debug_field(load, tx_shmem_frame, "%lu");
-                       debug_field(load, rx_shmem_frame, "%lu");
-                       debug_field(load, evtchn, "%u");
-                       debug_field(load, status, "%u");
-                       debug_end("NETIF_BE", "CONNECT");
-               } else if (msg->subtype == CMSG_NETIF_BE_DISCONNECT) {
-                       netif_be_disconnect_t *load;
-                       load = (netif_be_disconnect_t *)msg->msg;
-                       debug_begin("NETIF_BE", "DISCONNECT");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, netif_handle, "%u");
-                       debug_field(load, status, "%u");
-                       debug_end("NETIF_BE", "DISCONNECT");
-               } else if (msg->subtype == CMSG_NETIF_BE_DRIVER_STATUS) {
-                       netif_be_driver_status_t *load;
-                       load = (netif_be_driver_status_t *)msg->msg;
-                       debug_begin("NETIF_BE", "DRIVER_STATUS");
-                       debug_field(load, status, "%u");
-                       debug_end("NETIF_BE", "DRIVER_STATUS");
-               } else {
-                       debug_begin("NETIF_BE", "UNKNOWN");
-                       debug_field(msg, subtype, "%u");
-                       debug_field(msg, length, "%u");
-                       debug_dump(msg, msg, length);
-                       debug_end("NETIF_BE", "UNKNOWN");
-               }
-               break;
-       case CMSG_NETIF_FE:
-               if (msg->subtype == CMSG_NETIF_FE_INTERFACE_STATUS) {
-                       netif_fe_interface_status_t *load;
-                       load = (netif_fe_interface_status_t *)msg->msg;
-                       debug_begin("NETIF_FE", "INTERFACE_STATUS");
-                       debug_field(load, handle, "%u");
-                       debug_field(load, status, "%u");
-                       debug_field(load, evtchn, "%u");
-                       debug_field_mac(load, mac);
-                       debug_field(load, domid, "%u");
-                       debug_end("NETIF_FE", "INTERFACE_STATUS");
-               } else if (msg->subtype == CMSG_NETIF_FE_DRIVER_STATUS) {
-                       netif_fe_driver_status_t *load;
-                       load = (netif_fe_driver_status_t *)msg->msg;
-                       debug_begin("NETIF_FE", "DRIVER_STATUS");
-                       debug_field(load, status, "%u");
-                       debug_field(load, max_handle, "%u");
-                       debug_end("NETIF_FE", "DRIVER_STATUS");
-               } else if (msg->subtype == CMSG_NETIF_FE_INTERFACE_CONNECT) {
-                       netif_fe_interface_connect_t *load;
-                       load = (netif_fe_interface_connect_t *)msg->msg;
-                       debug_begin("NETIF_FE", "INTERFACE_CONNECT");
-                       debug_field(load, handle, "%u");
-                       debug_field(load, tx_shmem_frame, "%lu");
-                       debug_field(load, rx_shmem_frame, "%lu");
-                       debug_end("NETIF_FE", "INTERFACE_CONNECT");
-               } else if (msg->subtype == CMSG_NETIF_FE_INTERFACE_DISCONNECT) {
-                       netif_fe_interface_disconnect_t *load;
-                       load = (netif_fe_interface_disconnect_t *)msg->msg;
-                       debug_begin("NETIF_FE", "INTERFACE_DISCONNECT");
-                       debug_field(load, handle, "%u");
-                       debug_end("NETIF_FE", "INTERFACE_DISCONNECT");
-               } else if (msg->subtype == CMSG_NETIF_FE_INTERFACE_QUERY) {
-                       netif_fe_interface_query_t *load;
-                       load = (netif_fe_interface_query_t *)msg->msg;
-                       debug_begin("NETIF_FE", "INTERFACE_QUERY");
-                       debug_field(load, handle, "%u");
-                       debug_field(load, status, "%u");
-                       debug_field(load, evtchn, "%u");
-                       debug_field_mac(load, mac);
-                       debug_field(load, domid, "%u");
-                       debug_end("NETIF_FE", "INTERFACE_QUERY");
-               } else {
-                       debug_begin("NETIF_FE", "UNKNOWN");
-                       debug_field(msg, subtype, "%u");
-                       debug_field(msg, length, "%u");
-                       debug_dump(msg, msg, length);
-                       debug_end("NETIF_FE", "UNKNOWN");
-               }
-               break;
-       case CMSG_SHUTDOWN:
-               if (msg->subtype == CMSG_SHUTDOWN_POWEROFF) {
-                       debug_begin("SHUTDOWN", "POWEROFF");
-                       debug_end("SHUTDOWN", "POWEROFF");
-               } else if (msg->subtype == CMSG_SHUTDOWN_REBOOT) {
-                       debug_begin("SHUTDOWN", "REBOOT");
-                       debug_end("SHUTDOWN", "REBOOT");
-               } else if (msg->subtype == CMSG_SHUTDOWN_SUSPEND) {
-                       debug_begin("SHUTDOWN", "SUSPEND");
-                       debug_end("SHUTDOWN", "SUSPEND");
-               } else if (msg->subtype == CMSG_SHUTDOWN_SYSRQ) {
-                       debug_begin("SHUTDOWN", "SYSRQ");
-                       debug_end("SHUTDOWN", "SYSRQ");
-               } else {
-                       debug_begin("SHUTDOWN", "UNKNOWN");
-                       debug_field(msg, subtype, "%u");
-                       debug_field(msg, length, "%u");
-                       debug_dump(msg, msg, length);
-                       debug_end("SHUTDOWN", "UNKNOWN");
-               }               
-               break;
-       case CMSG_MEM_REQUEST:
-               if (msg->subtype == CMSG_MEM_REQUEST_SET) {
-                       mem_request_t *load;
-                       load = (mem_request_t *)msg->msg;
-                       debug_begin("MEM_REQUEST", "SET");
-                       debug_field(load, target, "%u");
-                       debug_field(load, status, "%u");
-                       debug_end("MEM_REQUEST", "SET");
-               } else {
-                       debug_begin("MEM_REQUEST", "UNKNOWN");
-                       debug_field(msg, subtype, "%u");
-                       debug_field(msg, length, "%u");
-                       debug_dump(msg, msg, length);
-                       debug_end("MEM_REQUEST", "UNKNOWN");
-               }               
-               break;
-       case CMSG_USBIF_BE:
-               if (msg->subtype == CMSG_USBIF_BE_CREATE) {
-                       usbif_be_create_t *load;
-                       load = (usbif_be_create_t *)msg->msg;
-                       debug_begin("USBIF_BE", "CREATE");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, status, "%u");
-                       debug_end("USBIF_BE", "CREATE");
-               } else if (msg->subtype == CMSG_USBIF_BE_DESTROY) {
-                       usbif_be_destroy_t *load;
-                       load = (usbif_be_destroy_t *)msg->msg;
-                       debug_begin("USBIF_BE", "DESTROY");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, status, "%u");
-                       debug_end("USBIF_BE", "DESTROY");
-               } else if (msg->subtype == CMSG_USBIF_BE_CONNECT) {
-                       usbif_be_connect_t *load;
-                       load = (usbif_be_connect_t *)msg->msg;
-                       debug_begin("USBIF_BE", "CONNECT");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, shmem_frame, "%lu");
-                       debug_field(load, evtchn, "%u");
-                       debug_field(load, bandwidth, "%u");
-                       debug_field(load, status, "%u");
-                       debug_end("USBIF_BE", "CONNECT");
-               } else if (msg->subtype == CMSG_USBIF_BE_DISCONNECT) {
-                       usbif_be_disconnect_t *load;
-                       load = (usbif_be_disconnect_t *)msg->msg;
-                       debug_begin("USBIF_BE", "DISCONNECT");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, status, "%u");
-                       debug_end("USBIF_BE", "DISCONNECT");
-               } else if (msg->subtype == CMSG_USBIF_BE_CLAIM_PORT) {
-                       usbif_be_claim_port_t *load;
-                       load = (usbif_be_claim_port_t *)msg->msg;
-                       debug_begin("USBIF_BE", "CLAIM_PORT");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, usbif_port, "%u");
-                       debug_field(load, status, "%u");
-                       debug_field(load, path, "%s");
-                       debug_end("USBIF_BE", "CLAIM_PORT");
-               } else if (msg->subtype == CMSG_USBIF_BE_RELEASE_PORT) {
-                       usbif_be_release_port_t *load;
-                       load = (usbif_be_release_port_t *)msg->msg;
-                       debug_begin("USBIF_BE", "RELEASE_PORT");
-                       debug_field(load, path, "%s");
-                       debug_end("USBIF_BE", "RELEASE_PORT");
-               } else if (msg->subtype == CMSG_USBIF_BE_DRIVER_STATUS_CHANGED) 
{
-                       usbif_be_driver_status_changed_t *load;
-                       load = (usbif_be_driver_status_changed_t *)msg->msg;
-                       debug_begin("USBIF_BE", "DRIVER_STATUS_CHANGED");
-                       debug_field(load, status, "%u");
-                       debug_end("USBIF_BE", "DRIVER_STATUS_CHANGED");
-               } else {
-                       debug_begin("USBIF_BE", "UNKNOWN");
-                       debug_field(msg, subtype, "%u");
-                       debug_field(msg, length, "%u");
-                       debug_dump(msg, msg, length);
-                       debug_end("USBIF_BE", "UNKNOWN");
-               }
-               break;
-       case CMSG_USBIF_FE:
-               if (msg->subtype == CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED) {
-                       usbif_fe_interface_status_changed_t *load;
-                       load = (usbif_fe_interface_status_changed_t *)msg->msg;
-                       debug_begin("USBIF_FE", "INTERFACE_STATUS_CHANGED");
-                       debug_field(load, status, "%u");
-                       debug_field(load, evtchn, "%u");
-                       debug_field(load, domid, "%u");
-                       debug_field(load, bandwidth, "%u");
-                       debug_field(load, num_ports, "%u");
-                       debug_end("USBIF_FE", "INTERFACE_STATUS_CHANGED");
-               } else if (msg->subtype == CMSG_USBIF_FE_DRIVER_STATUS_CHANGED) 
{
-                       usbif_fe_driver_status_changed_t *load;
-                       load = (usbif_fe_driver_status_changed_t *)msg->msg;
-                       debug_begin("USBIF_FE", "DRIVER_STATUS_CHANGED");
-                       debug_field(load, status, "%u");
-                       debug_end("USBIF_FE", "DRIVER_STATUS_CHANGED");
-               } else if (msg->subtype == CMSG_USBIF_FE_INTERFACE_CONNECT) {
-                       usbif_fe_interface_connect_t *load;
-                       load = (usbif_fe_interface_connect_t *)msg->msg;
-                       debug_begin("USBIF_FE", "INTERFACE_CONNECT");
-                       debug_field(load, shmem_frame, "%lu");
-                       debug_end("USBIF_FE", "INTERFACE_CONNECT");
-               } else if (msg->subtype == CMSG_USBIF_FE_INTERFACE_DISCONNECT) {
-                       debug_begin("USBIF_FE", "INTERFACE_DISCONNECT");
-                       debug_end("USBIF_FE", "INTERFACE_DISCONNECT");
-               } else {
-                       debug_begin("USBIF_FE", "UNKNOWN");
-                       debug_field(msg, subtype, "%u");
-                       debug_field(msg, length, "%u");
-                       debug_dump(msg, msg, length);
-                       debug_end("USBIF_FE", "UNKNOWN");
-               }
-               break;
-       default:
-               debug_begin("UNKNOWN", "UNKNOWN");
-               debug_field(msg, type, "%u");
-               debug_field(msg, subtype, "%u");
-               debug_field(msg, length, "%u");
-               debug_dump(msg, msg, length);
-               debug_end("UNKNOWN", "UNKNOWN");
-               break;
-       }
-}
-
-void _error(const char *fmt, ...)
-{
-       va_list ap;
-       char buffer[4096];
-
-       va_start(ap, fmt);
-       vsnprintf(buffer, sizeof(buffer), fmt, ap);
-       va_end(ap);
-
-       fprintf(stderr, "%s\n", buffer);
-}
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/dump.h
--- a/tools/xcs/dump.h  Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,28 +0,0 @@
-/*\
- *  Copyright (C) International Business Machines  Corp., 2005
- *  Author(s): Anthony Liguori <aliguori@xxxxxxxxxx>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; under version 2 of the License.
- * 
- *  This program is distributed in the hope that 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
-\*/
-
-#ifndef XENCTLD_ERROR_H
-#define XENCTLD_ERROR_H
-
-#include <stdint.h>
-#include <xenctrl.h>
-#include <xen/io/domain_controller.h>
-
-void dump_msg(const control_msg_t *msg, uint64_t flags);
-
-#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/evtchn.c
--- a/tools/xcs/evtchn.c        Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,106 +0,0 @@
-/* evtchn.c
- *
- * Interfaces to event channel driver.
- *
- * Most of this is directly based on the original xu interface to python 
- * written by Keir Fraser.
- *
- * (c) 2004, Andrew Warfield
- *
- */
- 
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h> /* XOPEN drops makedev, this gets it back. */
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include "xcs.h"
-
-static int evtchn_fd = -1;
-
-/* NB. The following should be kept in sync with the kernel's evtchn driver. */
-#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
-#define EVTCHN_DEV_MAJOR 10
-#define EVTCHN_DEV_MINOR 201
-/* /dev/xen/evtchn ioctls: */
-/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
-#define EVTCHN_RESET  _IO('E', 1)
-/* EVTCHN_BIND: Bind to teh specified event-channel port. */
-#define EVTCHN_BIND   _IO('E', 2)
-/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
-#define EVTCHN_UNBIND _IO('E', 3)
-
-int evtchn_read()
-{
-    u16 v;
-    int bytes;
-
-    while ( (bytes = read(evtchn_fd, &v, sizeof(v))) == -1 )
-    {
-        if ( errno == EINTR )
-            continue;
-        /* EAGAIN was cased to return 'None' in the python version... */
-        return -errno;
-    }
-    
-    if ( bytes == sizeof(v) )
-        return v;
-    
-    /* bad return */
-    return -1;
-}
-
-void evtchn_unmask(u16 idx)
-{
-    (void)write(evtchn_fd, &idx, sizeof(idx));
-}
-
-int evtchn_bind(int idx)
-{
-    if ( ioctl(evtchn_fd, EVTCHN_BIND, idx) != 0 )
-        return -errno;
-    
-    return 0;
-}
-
-int evtchn_unbind(int idx)
-{
-    if ( ioctl(evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
-        return -errno;
-
-    return 0;
-}
-
-int evtchn_open(void)
-{
-    struct stat st;
-    
-    /* Make sure any existing device file links to correct device. */
-    if ( (lstat(EVTCHN_DEV_NAME, &st) != 0) ||
-         !S_ISCHR(st.st_mode) ||
-         (st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) )
-        (void)unlink(EVTCHN_DEV_NAME);
-
- reopen:
-    evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR); 
-    if ( evtchn_fd == -1 )
-    {
-        if ( (errno == ENOENT) &&
-             ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
-             (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, 
-                    makedev(EVTCHN_DEV_MAJOR,EVTCHN_DEV_MINOR)) == 0) )
-            goto reopen;
-        return -errno;
-    }
-    return evtchn_fd;
-}
-
-void evtchn_close()
-{
-    (void)close(evtchn_fd);
-    evtchn_fd = -1;
-}
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/xcs.c
--- a/tools/xcs/xcs.c   Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,973 +0,0 @@
-/* xcs.c 
- *
- * xcs - Xen Control Switch
- *
- * Copyright (c) 2004, Andrew Warfield
- */
- 
-/*
-
-  Things we need to select on in xcs:
-  
-  1. Events arriving on /dev/evtchn
-  
-    These will kick a function to read everything off the fd, and scan the
-    associated control message rings, resulting in notifications sent on
-    data channels to connected clients.
-    
-  2. New TCP connections on XCS_PORT.
-  
-    These will either be control (intially) or associated data connections.
-    
-    Control connections will instantiate or rebind to an existing connnection
-    struct.  The control channel is used to configure what events will be 
-    received on an associated data channel.  These two channels are split
-    out because the control channel is synchronous, all messages will return
-    a result from XCS.  The data channel is effectively asynchronous, events
-    may arrive in the middle of a control message exchange.  Additionally, 
-    Having two TCP connections allows the client side to have a blocking
-    listen loop for data messages, while independently interacting on the 
-    control channel at other places in the code.
-    
-    Data connections attach to an existing control struct, using a session
-    id that is passed during the control connect.  There is currently a 
-    one-to-one relationship between data and control channels, but there
-    could just as easily be many data channels, if there were a set of 
-    clients with identical interests, or if you wanted to trace an existing
-    client's data traffic.
-    
- 3. Messages arriving on open TCP connections.
-    There are three types of open connections:
-     
-    3a. Messages arriving on open control channel file descriptors.
- 
-        [description of the control protocol here]
- 
-    3b. Messages arriving on open data channel file descriptors.
- 
-        [description of the data protocol here]
-        
-    3c. Messages arriving on (new) unbound connections.
-    
-        A connection must issue a XCS_CONNECT message to specify what
-        it is, after which the connection is moved into one of the above 
-        two groups.
- 
- Additionally, we need a periodic timer to do housekeeping.
- 
- 4. Every XCS_GC_INTERVAL seconds, we need to clean up outstanding state. 
-    Specifically, we garbage collect any sessions (connection_t structs)
-    that have been unconnected for a period of time (XCS_SESSION_TIMEOUT), 
-    and close any connections that have been openned, but not connected
-    as a control or data connection (XCS_UFD_TIMEOUT).
-
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <errno.h>
-#include <malloc.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include "xcs.h"
-
-#undef fd_max
-#define fd_max(x,y) ((x) > (y) ? (x) : (y))
-
-/* ------[ Control channel interfaces ]------------------------------------*/
-
-static control_channel_t *cc_list[NR_EVENT_CHANNELS];
-static int *dom_port_map = 0;
-static int dom_port_map_size = 0;
-
-static void map_dom_to_port(u32 dom, int port)
-{
-    if (dom >= dom_port_map_size) {
-        dom_port_map = (int *)realloc(dom_port_map,
-                                      (dom + 256) * sizeof(dom_port_map[0]));
-
-        if (dom_port_map == NULL) {
-            perror("realloc(dom_port_map)");
-            exit(1);
-        }
-
-        for (; dom_port_map_size < dom + 256; dom_port_map_size++) {
-            dom_port_map[dom_port_map_size] = -1;
-        }
-    }
-
-    dom_port_map[dom] = port;
-}
-
-static int dom_to_port(u32 dom) 
-{
-    if (dom >= dom_port_map_size) return -1;
-
-    return dom_port_map[dom];
-}
-
-static void init_interfaces(void)
-{
-    memset(cc_list, 0, sizeof cc_list);
-}
-
-static control_channel_t *add_interface(u32 dom, int local_port, 
-                                        int remote_port)
-{
-    control_channel_t *cc=NULL, *oldcc;
-    int ret;
-    
-    if ((dom_to_port(dom) >= 0) && (cc_list[dom_to_port(dom)] != NULL))
-    {
-        return(cc_list[dom_to_port(dom)]);
-    }
-    
-    if (cc_list[local_port] == NULL) 
-    {
-        cc = ctrl_chan_new(dom, local_port, remote_port);
-    }
-    
-    if (cc == NULL)
-        return NULL;
-    
-    DPRINTF("added a new interface: dom: %u (l:%d,r:%d): %p\n",
-            dom, local_port, remote_port, cc);
-    DPRINTF("added a new interface: dom: %u (l:%d,r:%d): %p\n",
-            dom, cc->local_port, cc->remote_port, cc);
-    
-    if ((ret = evtchn_bind(cc->local_port)) != 0)
-    {
-        DPRINTF("Got control interface, but couldn't bind evtchan!(%d)\n", 
ret);
-        ctrl_chan_free(cc);
-        return NULL;
-    }
-    
-    if ( cc_list[cc->local_port] != NULL )
-    {
-        oldcc = cc_list[cc->local_port];
-        
-        if ((oldcc->remote_dom != cc->remote_dom) ||
-            (oldcc->remote_port != cc->remote_port))
-        {
-            DPRINTF("CC conflict! (port: %d, old dom: %u, new dom: %u, "
-                    "old ref_count: %d)\n",
-                    cc->local_port, oldcc->remote_dom, cc->remote_dom, 
-                    oldcc->ref_count);
-            map_dom_to_port(oldcc->remote_dom, -1);
-            ctrl_chan_free(cc_list[cc->local_port]);
-            cc_list[cc->local_port] = NULL;
-        }
-    }
-     
-    cc_list[cc->local_port] = cc;
-    map_dom_to_port(cc->remote_dom, cc->local_port);
-    cc->type = CC_TYPE_INTERDOMAIN;
-    cc->ref_count = 0;
-    return cc;
-}
-
-control_channel_t *add_virq(int virq)
-{
-    control_channel_t *cc;
-    int virq_port;
-    
-    if (ctrl_chan_bind_virq(virq, &virq_port) == -1)
-        return NULL;
-    
-    if ((cc_list[virq_port]       != NULL) && 
-        (cc_list[virq_port]->type != CC_TYPE_VIRQ))
-        return NULL; 
-    
-    if ((cc_list[virq_port]       != NULL) && 
-        (cc_list[virq_port]->type == CC_TYPE_VIRQ))
-        return cc_list[virq_port]; 
-    
-    cc = (control_channel_t *)malloc(sizeof(control_channel_t));
-    if ( cc == NULL ) return NULL;
-
-    memset(cc, 0, sizeof(control_channel_t));
-    cc->type       = CC_TYPE_VIRQ;
-    cc->local_port = virq_port;
-    cc->virq       = virq;
-    cc->ref_count  = 1;
-    
-    if (evtchn_bind(cc->local_port) != 0)
-    {
-        DPRINTF("Got control interface, but couldn't bind evtchan!\n");
-        free(cc);
-        return NULL;
-    }
-
-    cc_list[cc->local_port] = cc;
-
-    return cc;
-}
-
-void get_interface(control_channel_t *cc)
-{
-    if (cc != NULL)
-        cc->ref_count++;
-}
-    
-void put_interface(control_channel_t *cc)
-{
-    if (cc != NULL)
-    {
-        cc->ref_count--;
-        if (cc->ref_count <= 0)
-        {
-            DPRINTF("Freeing cc on port %d.\n", cc->local_port);
-            (void)evtchn_unbind(cc->local_port);
-            cc_list[cc->local_port] = NULL;
-            map_dom_to_port(cc->remote_dom, -1);
-            ctrl_chan_free(cc);
-        }
-    }
-}
-
-/* ------[ Simple helpers ]------------------------------------------------*/
-
-/* listen_socket() is straight from paul sheer's useful select_tut manpage. */
-static int listen_socket (char *listen_path) 
-{
-    struct sockaddr_un a;
-    int s;
-    int yes;
-
-    if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) 
-    {
-        perror ("socket");
-        return -1;
-    }
-    
-    yes = 1;
-
-    memset (&a, 0, sizeof (a));
-    a.sun_family = AF_UNIX;
-    strcpy(a.sun_path, listen_path);
-
-    /* remove an old socket if it exists. */
-    unlink(listen_path);
-
-    if (bind(s, (struct sockaddr *) &a, sizeof (a)) < 0) 
-    {
-        fprintf (stderr, "bind('%s'): %s\n", listen_path, strerror(errno));
-        close (s);
-        return -1;
-    }
-    DPRINTF ("accepting connections on path %s\n", listen_path);
-    listen (s, 10);
-    return s;
-}
-
-/* ------[ Message handlers ]----------------------------------------------*/
-
-#define NO_CHANGE     0
-#define CONNECTED     1
-#define DISCONNECTED  2
-int handle_connect_msg( xcs_msg_t *msg, int fd )
-{
-    xcs_connect_msg_t *cmsg = &msg->u.connect;
-    connection_t *con;
-    int ret = NO_CHANGE;
-    
-    switch (msg->type)
-    {
-        case XCS_CONNECT_CTRL:
-        {
-            if ( cmsg->session_id == 0 )
-            {
-                con = connection_new();
-                if ( con == NULL)
-                {
-                    msg->result = XCS_RSLT_FAILED;
-                    break;
-                }
-                msg->result      = XCS_RSLT_OK;
-                cmsg->session_id = con->id;
-                con->ctrl_fd     = fd;
-                ret = CONNECTED;
-                DPRINTF("New control connection\n");
-                break;
-            }
-
-            con = get_con_by_session(cmsg->session_id);
-            if ( con == NULL )
-            {
-                msg->result = XCS_RSLT_BADSESSION;
-                break;
-            }
-            if ( con->ctrl_fd != -1 )
-            {
-                msg->result = XCS_RSLT_CONINUSE;
-                break;
-            }
-            con->ctrl_fd   = fd;
-            msg->result   = XCS_RSLT_OK;
-            ret = CONNECTED;
-            DPRINTF("Rebound to control connection\n");
-            break;
-        }
-        case XCS_CONNECT_DATA:
-        {
-            con = get_con_by_session(cmsg->session_id);
-            if ( con == NULL )
-            {
-                msg->result = XCS_RSLT_BADSESSION;
-                break;
-            }
-            if ( con->data_fd != -1 )
-            {
-                msg->result = XCS_RSLT_CONINUSE;
-                break;
-            }
-            con->data_fd   = fd;
-            msg->result   = XCS_RSLT_OK;
-            ret = CONNECTED;
-            DPRINTF("Attached data connection\n");
-            break;
-
-        }
-        case XCS_CONNECT_BYE:
-        {
-            close ( fd );
-            ret = DISCONNECTED;
-            break;
-        }
-    }   
-    
-    return ret;
-}
-
-int handle_control_message( connection_t *con, xcs_msg_t *msg )
-{
-    int ret;
-    int reply_needed = 1;
-            
-    DPRINTF("Got message, type %u.\n", msg->type);
-
-    switch (msg->type)
-    {
-        case XCS_MSG_BIND:
-        {
-            xcs_bind_msg_t *bmsg = &msg->u.bind;
-
-            if ( ! BIND_MSG_VALID(bmsg) )
-            {
-                msg->result = XCS_RSLT_BADREQUEST;
-                break;
-            }
-            
-            ret = xcs_bind(con, bmsg->port, bmsg->type);
-            if (ret == 0) {
-                msg->result = XCS_RSLT_OK;
-            } else {
-                msg->result = XCS_RSLT_FAILED;
-            }
-            break;
-        }
-        case XCS_MSG_UNBIND:
-        {
-            xcs_bind_msg_t *bmsg = &msg->u.bind;
-
-            if ( ! BIND_MSG_VALID(bmsg) )
-            {
-                msg->result = XCS_RSLT_BADREQUEST;
-                break;
-            }
-            
-            ret = xcs_unbind(con, bmsg->port, bmsg->type);
-            if (ret == 0) {
-                msg->result = XCS_RSLT_OK;
-            } else {
-                msg->result = XCS_RSLT_FAILED;
-            }
-            break;
-        }    
-        case XCS_VIRQ_BIND:
-        {
-            control_channel_t *cc;
-            xcs_virq_msg_t *vmsg = &msg->u.virq;
-            if ( ! VIRQ_MSG_VALID(vmsg) )
-            {
-                msg->result = XCS_RSLT_BADREQUEST;
-                break;
-            }
-
-            cc = add_virq(vmsg->virq);
-            if (cc == NULL)
-            {
-                msg->result = XCS_RSLT_FAILED;
-                break;
-            }
-            ret = xcs_bind(con, cc->local_port, TYPE_VIRQ);
-            if (ret == 0) {
-                vmsg->port   = cc->local_port;
-                msg->result  = XCS_RSLT_OK;
-            } else {
-                msg->result = XCS_RSLT_FAILED;
-            }
-            break;
-        }
-
-        case XCS_CIF_NEW_CC:
-        {
-            control_channel_t *cc;
-            xcs_interface_msg_t *imsg = &msg->u.interface;
-
-            if ( ! INTERFACE_MSG_VALID(imsg) )
-            {
-                msg->result = XCS_RSLT_BADREQUEST;
-                break;
-            }
-
-            cc = add_interface(imsg->dom, imsg->local_port, imsg->remote_port);
-            if (cc != NULL) {
-                get_interface(cc);
-                msg->result       = XCS_RSLT_OK;
-                imsg->local_port  = cc->local_port;
-                imsg->remote_port = cc->remote_port;
-            } else {
-                msg->result = XCS_RSLT_FAILED;
-            }
-            break;
-        }
-
-        case XCS_CIF_FREE_CC:
-        {
-            control_channel_t *cc;
-            xcs_interface_msg_t *imsg = &msg->u.interface;
-
-            if ( ! INTERFACE_MSG_VALID(imsg) )
-            {
-                msg->result = XCS_RSLT_BADREQUEST;
-                break;
-            }
-
-            cc = add_interface(imsg->dom, imsg->local_port, imsg->remote_port);
-            if (cc != NULL) {
-                put_interface(cc);
-            } 
-            msg->result       = XCS_RSLT_OK;
-            break;
-        }
-    }
-    return reply_needed;
-}
-
-void handle_data_message( connection_t *con, xcs_msg_t *msg )
-{
-    control_channel_t *cc;
-    xcs_control_msg_t *cmsg = &msg->u.control;
-    int port;
-    
-    switch (msg->type)
-    {
-    case XCS_REQUEST:
-        if ( cmsg->remote_dom > MAX_DOMS )
-            break;
-        
-        port = dom_to_port(cmsg->remote_dom);
-        if (port == -1) break;
-        cc = cc_list[port];
-        if ((cc != NULL) && ( cc->type == CC_TYPE_INTERDOMAIN ))
-        {
-            DPRINTF("DN:REQ: dom:%d port: %d type: %d\n", 
-                    cc->remote_dom, cc->local_port, 
-                    cmsg->msg.type);
-            ctrl_chan_write_request(cc, cmsg);
-            ctrl_chan_notify(cc);
-        } else {
-            DPRINTF("tried to send a REQ to a null cc\n.");
-        }
-        break;
-
-    case XCS_RESPONSE:
-        if ( cmsg->remote_dom > MAX_DOMS )
-            break;
-        
-        port = dom_to_port(cmsg->remote_dom);
-        if (port == -1) break;
-        cc = cc_list[port];
-        if ((cc != NULL) && ( cc->type == CC_TYPE_INTERDOMAIN ))
-        {
-            DPRINTF("DN:RSP: dom:%d port: %d type: %d\n", 
-                    cc->remote_dom, cc->local_port, 
-                    cmsg->msg.type);
-            ctrl_chan_write_response(cc, cmsg);
-            ctrl_chan_notify(cc);
-        }
-        break;
-
-    case XCS_VIRQ:
-        if ( !(PORT_VALID(cmsg->local_port)) )
-            break;
-            
-        cc = cc_list[cmsg->local_port];
-        
-        if ((cc != NULL) && ( cc->type == CC_TYPE_VIRQ ))
-        {
-            DPRINTF("DN:VIRQ:  virq: %d port: %d\n", 
-                    cc->virq, cc->local_port);
-            ctrl_chan_notify(cc);
-        }
-        break;
-    }
-}
-    
-/* ------[ Control interface handler ]-------------------------------------*/
-
-/* passed as a function pointer to the lookup. */
-void send_kmsg(connection_t *c, void *arg)
-{
-    xcs_msg_t *msg = (xcs_msg_t *)arg;
-
-    DPRINTF("       -> CONNECTION %d\n", c->data_fd);
-    if (c->data_fd > 0)
-    {
-      send(c->data_fd, msg, sizeof(xcs_msg_t), 0);
-    }
-}
-
-int handle_ctrl_if(void)
-{
-    control_channel_t *cc;
-    control_msg_t     *msg;
-    xcs_msg_t          kmsg;
-    int                chan, ret;
-    
-    DPRINTF("Event thread kicked!\n");
-again:
-    while ((chan = evtchn_read()) > 0)
-    {
-        evtchn_unmask(chan);
-        cc = cc_list[chan];
-        if (cc_list[chan] == NULL) {
-            DPRINTF("event from unknown channel (%d)\n", chan);
-            continue;
-        }
-
-        if ( cc_list[chan]->type == CC_TYPE_VIRQ )
-        {
-            DPRINTF("UP:VIRQ: virq:%d port: %d\n",
-                    cc->virq, cc->local_port);
-            kmsg.type = XCS_VIRQ;
-            kmsg.u.control.local_port = cc->local_port;
-            xcs_lookup(cc->local_port, TYPE_VIRQ, send_kmsg, &kmsg);
-            continue;
-        }
-
-        while (ctrl_chan_request_to_read(cc))
-        {
-            msg = &kmsg.u.control.msg;
-            kmsg.type = XCS_REQUEST;
-            kmsg.u.control.remote_dom = cc->remote_dom;
-            kmsg.u.control.local_port = cc->local_port;
-            ret = ctrl_chan_read_request(cc, &kmsg.u.control);
-            DPRINTF("UP:REQ: dom:%d port: %d type: %d len: %d\n", 
-                    cc->remote_dom, cc->local_port, 
-                    msg->type, msg->length);
-            if (ret == 0)
-                xcs_lookup(cc->local_port, msg->type, send_kmsg, &kmsg);
-        }
-
-        while (ctrl_chan_response_to_read(cc))
-        {
-            msg = &kmsg.u.control.msg;
-            kmsg.type = XCS_RESPONSE;
-            kmsg.u.control.remote_dom = cc->remote_dom;
-            kmsg.u.control.local_port = cc->local_port;
-            ret = ctrl_chan_read_response(cc, &kmsg.u.control);
-            DPRINTF("UP:RSP: dom:%d port: %d type: %d len: %d\n", 
-                    cc->remote_dom, cc->local_port, 
-                    msg->type, msg->length);
-            if (ret == 0)
-                xcs_lookup(cc->local_port, msg->type, send_kmsg, &kmsg);
-        }
-    }
-    
-    if (chan == -EINTR)
-        goto again;
-    
-    return chan;
-}
-
-  
-/* ------[ Main xcs code / big select loop ]-------------------------------*/
-
-                
-typedef struct unbound_fd_st {
-    int                   fd;
-    struct timeval        born;
-    struct unbound_fd_st *next;
-} unbound_fd_t;
-
-/* This makes ufd point to the next entry in the list, so need to   *
- * break/continue if called while iterating.                        */
-void delete_ufd(unbound_fd_t **ufd)
-{
-    unbound_fd_t *del_ufd;
-    
-    del_ufd = *ufd;
-    *ufd    = (*ufd)->next;
-    free( del_ufd );
-}
-
-void gc_ufd_list( unbound_fd_t **ufd )
-{
-    struct timeval now, delta;
-    
-    gettimeofday(&now, NULL);
-    
-    while ( *ufd != NULL )
-    {
-        timersub(&now, &(*ufd)->born, &delta);
-        if (delta.tv_sec > XCS_UFD_TIMEOUT)
-        {
-            DPRINTF("GC-UFD: closing fd: %d\n", (*ufd)->fd);
-            close((*ufd)->fd);
-            delete_ufd(ufd);
-            continue;
-        }
-        ufd = &(*ufd)->next;
-    }
-}
-
-void daemonize_xcs(void)
-{
-    
-    /* detach from our controlling tty so that a shell does hang waiting for
-       stopped jobs. */
-    
-    pid_t pid = fork();
-    int fd;
-
-    if (pid == -1) {
-           perror("fork()");
-    } else if (pid) {
-           exit(0);
-    }
-
-    fd = open("/var/log/xcs.log", O_WRONLY | O_APPEND | O_CREAT);
-    if ( fd == -1 ) {
-        fprintf(stderr, "xcs couldn't open logfile.  Directing all output to "
-                "/dev/null instead.\n");
-        fd = open("/dev/null", O_WRONLY);
-    }
-    
-    setsid();
-    close(2);
-    close(1);
-    close(0);
-    dup(fd);
-    dup(fd);
-}
-
-
-static char *pidfilename = NULL;
-void cleanup(int sig)
-{
-    /* throw away our pidfile if we created one. */
-    if ( pidfilename != NULL ) 
-        unlink(pidfilename);
-    exit(0);
-}
-
-int main (int argc, char *argv[])
-{
-    int listen_fd, evtchn_fd;
-    unbound_fd_t *unbound_fd_list = NULL, **ufd;
-    struct timeval timeout = { XCS_GC_INTERVAL, 0 };
-    connection_t **con;
-    int c, daemonize;
-    FILE *pidfile;
-    struct stat s;
-    
-    daemonize = 1;
-    pidfile = NULL;
-
-    signal(SIGHUP, cleanup);
-    signal(SIGTERM, cleanup);
-    signal(SIGINT, cleanup);
-    
-    /* Do a bunch of stuff before potentially daemonizing so we can 
-     * print error messages sanely before redirecting output. */
-    
-    /* Initialize xc and event connections. */
-    if (ctrl_chan_init() != 0)
-    {
-        printf("Couldn't open conneciton to libxc.\n");
-        exit(-1);
-    }
-    
-    if ((evtchn_fd = evtchn_open()) < 0)
-    {
-        printf("Couldn't open event channel driver interface.\n");
-        exit(-1);
-    }
-   
-    /* Bind listen_fd to the client socket. */
-    listen_fd = listen_socket(XCS_SUN_PATH);
-     
-    while ((c = getopt (argc, argv, "ip:")) != -1)
-    {
-        switch (c)
-        {
-        case 'i': /* interactive */
-            daemonize = 0;
-            break;
-        case 'p': /* pid file */
-            pidfilename = optarg;
-            break;          
-        case '?':
-            if (isprint (optopt))
-                fprintf (stderr, "Unknown option `-%c'.\n", optopt);
-            else
-                fprintf (stderr,
-                    "Bad option character `\\x%x'.\n", optopt);
-            break;
-        }    
-    }
-    
-    if ( pidfilename != NULL )
-    {
-        if ( stat(pidfilename, &s) == 0 )
-        {
-            fprintf(stderr, "Thre specified pid file (%s) already exists.\n"
-                    "Is another instance of xcs running?\n", pidfilename);
-            exit(-1);
-        }
-
-        pidfile = fopen(pidfilename, "w");
-        if (pidfile == NULL)
-        {
-            fprintf(stderr, "Error openning pidfile (%s).\n", pidfilename);
-            exit(-1);
-        }
-    }
-        
-    if (daemonize == 1) 
-        daemonize_xcs();
-    
-    if (pidfile != NULL)
-    {
-        fprintf(pidfile, "%d", getpid());
-        fclose(pidfile); 
-    }
-    
-    
-    /* Initialize control interfaces, bindings. */
-    init_interfaces();
-    init_bindings();
-    
-   
-    for (;;)
-    {
-        int n = 0, ret;
-        fd_set rd, wr, er;
-        FD_ZERO ( &rd );
-        FD_ZERO ( &wr );
-        FD_ZERO ( &er );
-        
-        /* TCP listen fd: */
-        FD_SET ( listen_fd, &rd );
-        n = fd_max ( n, listen_fd );
-        
-        /* Evtchn fd: */
-        FD_SET ( evtchn_fd, &rd );
-        n = fd_max ( n, evtchn_fd );
-        
-        /* unbound connection fds: */
-        ufd = &unbound_fd_list;
-        while ((*ufd) != NULL) 
-        {
-            FD_SET ( (*ufd)->fd, &rd );
-            n = fd_max ( n, (*ufd)->fd );
-            ufd = &(*ufd)->next;
-        }
-        
-        /* control and data fds: */
-        con = &connection_list;
-        while ((*con) != NULL)
-        {
-            if ((*con)->ctrl_fd > 0)
-            {
-                FD_SET ( (*con)->ctrl_fd, &rd );
-                n = fd_max ( n, (*con)->ctrl_fd );
-            }
-            if ((*con)->data_fd > 0)
-            {
-                FD_SET ( (*con)->data_fd, &rd );
-                n = fd_max ( n, (*con)->data_fd );
-            }
-            con = &(*con)->next;
-        }
-        
-        ret = select ( n + 1, &rd, &wr, &er, &timeout );
-        
-        if ( (timeout.tv_sec == 0) && (timeout.tv_usec == 0) )
-        {
-            gc_ufd_list(&unbound_fd_list);
-            gc_connection_list();
-            timeout.tv_sec = XCS_GC_INTERVAL;
-        }
-        
-        if ( (ret == -1) && (errno == EINTR) )
-            continue;
-        if ( ret < 0 )
-        {
-            perror ("select()");
-            exit(-1);
-        }
-        
-        /* CASE 1: Events arriving on /dev/evtchn. */
-        
-        if ( FD_ISSET (evtchn_fd, &rd ))
-            handle_ctrl_if();
-        
-        /* CASE 2: New connection on the listen port. */
-        if ( FD_ISSET ( listen_fd, &rd ))
-        {
-            struct sockaddr_un remote_addr;
-            int size;
-            memset (&remote_addr, 0, sizeof (remote_addr));
-            size = sizeof remote_addr;
-            ret = accept(listen_fd, (struct sockaddr *)&remote_addr, 
(socklen_t *)&size);
-            if ( ret < 0 )
-            {
-                perror("accept()");
-            } else {
-                unbound_fd_t *new_ufd;
-                
-                new_ufd = (unbound_fd_t *)malloc(sizeof(*new_ufd));
-                
-                if (new_ufd != NULL)
-                {
-                    gettimeofday(&new_ufd->born, NULL);
-                    new_ufd->fd     = ret;
-                    new_ufd->next   = unbound_fd_list;
-                    unbound_fd_list = new_ufd; 
-                } else {
-                    perror("malloc unbound connection");
-                    close(ret);
-                }
-            }
-        }
-        
-        /* CASE 3a: Handle messages on control connections. */
-        
-        con = &connection_list;
-        while ( *con != NULL )
-        {
-            if ( ((*con)->ctrl_fd > 0) && (FD_ISSET((*con)->ctrl_fd, &rd)) )
-            {
-                xcs_msg_t msg;
-                memset (&msg, 0, sizeof(msg));
-                ret = read( (*con)->ctrl_fd, &msg, sizeof(msg) );
-                
-                if ( ret < 0 )
-                {
-                    perror("reading ctrl fd.");
-                } else if ( ret == 0 )
-                {
-                    DPRINTF("Control connection dropped.\n");
-                    close ( (*con)->ctrl_fd );
-                    (*con)->ctrl_fd = -1;
-                    gettimeofday(&(*con)->disconnect_time, NULL);
-                } else 
-                {
-                    if ( ret != sizeof(msg) )
-                    {
-                        DPRINTF("Unexpected frame size!\n");
-                        continue;
-                    }
-                    
-                    ret = handle_control_message( *con, &msg );
-                    
-                    if ( ret == 1 )
-                        send( (*con)->ctrl_fd, &msg, sizeof(msg), 0 );
-                }
-            }
-            con = &(*con)->next;
-        }
-        
-        /* CASE 3b: Handle messages on data connections. */
-        
-        con = &connection_list;
-        while ( *con != NULL )
-        {
-            if ( ((*con)->data_fd > 0) && (FD_ISSET((*con)->data_fd, &rd)) )
-            {
-                xcs_msg_t msg;
-                memset (&msg, 0, sizeof(msg));
-                ret = read( (*con)->data_fd, &msg, sizeof(msg) );
-                
-                if ( ret < 0 )
-                {
-                    perror("reading data fd.");
-                } else if ( ret == 0 )
-                {
-                    DPRINTF("Data connection dropped.\n");
-                    close ( (*con)->data_fd );
-                    (*con)->data_fd = -1;
-                    gettimeofday(&(*con)->disconnect_time, NULL);
-                } else 
-                {
-                    if ( ret != sizeof(msg) )
-                    {
-                        DPRINTF("Unexpected frame size!\n");
-                        continue;
-                    }
-                    
-                    handle_data_message( *con, &msg );
-                }
-            }
-            con = &(*con)->next;
-        }
-        
-        /* CASE 3c: Handle messages arriving on unbound connections. */
-        ufd = &unbound_fd_list;
-        while ((*ufd) != NULL)
-        {
-            if ( FD_ISSET( (*ufd)->fd, &rd ) )
-            {
-                xcs_msg_t msg;
-                memset (&msg, 0, sizeof(msg));
-                ret = read( (*ufd)->fd, &msg, sizeof(msg) );
-                
-                if ( ret == 0 )
-                {
-                    close ( (*ufd)->fd );
-                    delete_ufd(ufd);
-                    continue; /* we just advanced ufd */
-                } else {
-                    if ( ret != sizeof(msg) )
-                    {
-                        DPRINTF("Unexpected frame size!\n");
-                        continue;
-                    }
-                    
-                    ret = handle_connect_msg( &msg, (*ufd)->fd );
-                    
-                    if ( (ret == CONNECTED) || (ret == NO_CHANGE) )
-                        send( (*ufd)->fd, &msg, sizeof(msg), 0 );
-                    
-                    if ( (ret = CONNECTED) || (ret = DISCONNECTED) )
-                    {
-                        delete_ufd( ufd );
-                        continue;
-                    }
-                }
-            }
-            ufd = &(*ufd)->next;
-        }
-    }
-}
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/xcs.h
--- a/tools/xcs/xcs.h   Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,148 +0,0 @@
-/* xcs.h
- *
- * public interfaces for the control interface switch (xcs).
- *
- * (c) 2004, Andrew Warfield
- *
- */
-
-
-#ifndef __XCS_H__
-#define __XCS_H__
-
-#include <pthread.h>
-#include <xenctrl.h>
-#include <xen/xen.h>
-#include <xen/io/domain_controller.h>
-#include <xen/linux/privcmd.h>
-#include <sys/time.h>
-#include "xcs_proto.h"
-
-/* ------[ Debug macros ]--------------------------------------------------*/
-
-#if 0
-#define DPRINTF(_f, _a...) printf ( _f , ## _a )
-#else
-#define DPRINTF(_f, _a...) ((void)0)
-#endif
-
-/* ------[ XCS-specific defines and types ]--------------------------------*/
-
-#define MAX_DOMS            1024
-#define XCS_SESSION_TIMEOUT   10 /* (secs) disconnected session gc timeout */
-#define XCS_UFD_TIMEOUT        5 /* how long can connections be unbound?   */
-#define XCS_GC_INTERVAL        5 /* How often to run gc handlers.          */
-
-
-/* ------[ Other required defines ]----------------------------------------*/
-
-/* Size of a machine page frame. */
-#define PAGE_SIZE XC_PAGE_SIZE
-
-#ifndef timersub /* XOPEN and __BSD don't cooperate well... */
-#define timersub(a, b, result)                                                \
-  do {                                                                        \
-    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;                             \
-    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;                          \
-    if ((result)->tv_usec < 0) {                                              \
-      --(result)->tv_sec;                                                     \
-      (result)->tv_usec += 1000000;                                           \
-    }                                                                         \
-  } while (0)
-#endif /*timersub*/
-
-/* ------[ Bindings Interface ]--------------------------------------------*/
-
-/*forward declare connection_t */
-typedef struct connection_st connection_t;
-
-typedef struct {
-    int    port;
-    u16    type;
-} binding_key_t;
-
-typedef struct binding_key_ent_st {
-    binding_key_t              key;
-    struct binding_key_ent_st *next;
-} binding_key_ent_t;
-
-#define BINDING_KEYS_EQUAL(_k1, _k2) \
-    (((_k1)->port == (_k2)->port) && ((_k1)->type == (_k2)->type))
-
-int  xcs_bind(connection_t *con, int port, u16 type);
-int  xcs_unbind(connection_t *con, int port, u16 type);
-void xcs_lookup(int port, u16 type, void (*f)(connection_t *, void *), 
-        void *arg);
-void init_bindings(void);
-
-/* ------[ Connection Interface ]------------------------------------------*/
-
-struct connection_st {
-    unsigned long      id;              /* Unique session id             */
-    int                ctrl_fd;         /* TCP descriptors               */
-    int                data_fd;         /*                               */
-    binding_key_ent_t *bindings;        /* List of bindings              */
-    connection_t      *next;            /* Linked list of connections    */
-    struct timeval     disconnect_time; /*  "            "               */
-}; /* previously typedefed as connection_t */
-
-
-extern connection_t *connection_list;
-
-connection_t *get_con_by_session(unsigned long session_id);
-connection_t *connection_new();
-void connection_free(connection_t *con);
-int  connection_add_binding(connection_t *con, binding_key_t *key);
-int  connection_remove_binding(connection_t *con, binding_key_t *key);
-int  connection_has_binding(connection_t *con, binding_key_t *key);
-void gc_connection_list(void);
-
-/* ------[ Control Channel Interfaces ]------------------------------------*/
- 
-typedef struct {
-    int               connected;
-    int               ref_count;
-    int               type;
-    u32               remote_dom;
-    int               local_port;
-    int               remote_port;
-    control_if_t     *interface;
-    ctrl_back_ring_t  tx_ring;
-    ctrl_front_ring_t rx_ring;
-    int               virq;
-} control_channel_t;
-
-/* cc types that we care about */
-#define CC_TYPE_INTERDOMAIN  0
-#define CC_TYPE_VIRQ         1
-
-control_channel_t 
-     *ctrl_chan_new(u32 dom, int local_port, int remote_port);
-void  ctrl_chan_free(control_channel_t *cc);
-int   ctrl_chan_init(void);
-int   ctrl_chan_notify(control_channel_t *cc);
-int   ctrl_chan_read_request(control_channel_t *cc, xcs_control_msg_t *);
-int   ctrl_chan_write_request(control_channel_t *cc, 
-                            xcs_control_msg_t *smsg);
-int   ctrl_chan_read_response(control_channel_t *cc, xcs_control_msg_t *);
-int   ctrl_chan_write_response(control_channel_t *cc, 
-                             xcs_control_msg_t *smsg);
-int   ctrl_chan_request_to_read(control_channel_t *cc);
-int   ctrl_chan_space_to_write_request(control_channel_t *cc);
-int   ctrl_chan_response_to_read(control_channel_t *cc);
-int   ctrl_chan_space_to_write_response(control_channel_t *cc);
-int   ctrl_chan_connect(control_channel_t *cc);
-void  ctrl_chan_disconnect(control_channel_t *cc);
-int   ctrl_chan_bind_virq(int virq, int *port);
-
-/* ------[ Event notification interfaces ]---------------------------------*/
-
-
-int   evtchn_open(void);
-void  evtchn_close();
-int   evtchn_bind(int idx);
-int   evtchn_unbind(int idx);
-void  evtchn_unmask(u16 idx);
-int   evtchn_read();
-
-#endif /* __XCS_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/xcs_proto.h
--- a/tools/xcs/xcs_proto.h     Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,101 +0,0 @@
-/* xcs_proto.h
- *
- * protocol interfaces for the control interface switch (xcs).
- *
- * (c) 2004, Andrew Warfield
- *
- */
-
-#ifndef  __XCS_PROTO_H__
-#define  __XCS_PROTO_H__
-
-#define XCS_SUN_PATH     "/var/lib/xen/xcs_socket"
-
-/* xcs message types: */
-#define XCS_CONNECT_CTRL       0 /* This is a control connection.     */
-#define XCS_CONNECT_DATA       1 /* This is a data connection.        */
-#define XCS_CONNECT_BYE        2 /* Terminate a session.              */
-#define XCS_MSG_BIND           3 /* Register for a message type.      */
-#define XCS_MSG_UNBIND         4 /* Unregister for a message type.    */
-#define XCS_VIRQ_BIND          5 /* Register for a virq.              */
-#define XCS_MSG_WRITELOCK      6 /* Writelock a (dom,type) pair.      */
-#define XCS_CIF_NEW_CC         7 /* Create a new control channel.     */
-#define XCS_CIF_FREE_CC        8 /* Create a new control channel.     */
-#define XCS_REQUEST            9 /* This is a request message.        */
-#define XCS_RESPONSE          10 /* this is a response Message.       */
-#define XCS_VIRQ              11 /* this is a virq notification.      */
-
-/* xcs result values: */
-#define XCS_RSLT_OK            0
-#define XCS_RSLT_FAILED        1 /* something bad happened.           */
-#define XCS_RSLT_ARECONNECTED  2 /* attempt to over connect.          */
-#define XCS_RSLT_BADSESSION    3 /* request for unknown session id.   */
-#define XCS_RSLT_NOSESSION     4 /* tried to do something before NEW. */
-#define XCS_RSLT_CONINUSE      5 /* Requested connection is taken.    */
-#define XCS_RSLT_BADREQUEST    6 /* Request message didn't validate.  */
-
-/* Binding wildcards */
-#define PORT_WILDCARD  0xefffffff
-#define TYPE_WILDCARD  0xffff
-#define TYPE_VIRQ      0xfffe
-
-typedef struct {
-    unsigned long  session_id;
-} xcs_connect_msg_t;
-
-typedef struct {
-    int port;
-    u16 type;  
-} xcs_bind_msg_t;
-
-typedef struct {
-    int port;
-    u16 virq;  
-} xcs_virq_msg_t;
-
-typedef struct {
-    u32 dom;
-    int local_port;
-    int remote_port;
-} xcs_interface_msg_t;
-
-typedef struct {
-    u32           remote_dom;
-    int           local_port;
-    control_msg_t msg;
-} xcs_control_msg_t;
-
-typedef struct {
-    u32 type;
-    u32 result;
-    union {
-        xcs_connect_msg_t   connect;   /* These are xcs ctrl message types */
-        xcs_bind_msg_t      bind;
-        xcs_virq_msg_t      virq;
-        xcs_interface_msg_t interface;
-        
-        xcs_control_msg_t   control;   /* These are xcs data message types */
-    } u;
-} xcs_msg_t;
-
-/* message validation macros. */
-#define PORT_VALID(_p)                                                 \
-    ( (((_p) >= 0) && ((_p) < NR_EVENT_CHANNELS))                      \
-    || ((_p) == PORT_WILDCARD) )
-
-#define TYPE_VALID(_t)                                                 \
-    (  ((_t) < 256)                                                    \
-    || ((_t) == TYPE_VIRQ)                                             \
-    || ((_t) == TYPE_WILDCARD) )
-
-#define BIND_MSG_VALID(_b)                                             \
-    ( PORT_VALID((_b)->port) && TYPE_VALID((_b)->type) )
-    
-/* Port is overwritten, and we don't currently validate the requested virq. */
-#define VIRQ_MSG_VALID(_v) ( 1 )
-    
-/* Interfaces may return with ports of -1, but may not be requested as such */
-#define INTERFACE_MSG_VALID(_i)                                        \
-    ( PORT_VALID((_i)->local_port) && PORT_VALID((_i)->remote_port) )
-
-#endif /* __XCS_PROTO_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/xcsdump.c
--- a/tools/xcs/xcsdump.c       Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,206 +0,0 @@
-/* xcsdump.c
- *
- * little tool to sniff control messages.
- *
- * Copyright (c) 2004, Andrew Warfield
- *
- * Modifications by Anthony Liguori <aliguori@xxxxxxxxxx> are:
- *   Copyright (C) 2005, International Business Machines, Corp.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <ctype.h>
-#include <xenctrl.h>
-#include <xen/xen.h>
-#include <xen/io/domain_controller.h>
-#include <getopt.h>
-#include "xcs_proto.h"
-#include "xcs.h"
-
-#include "dump.h"
-
-static int xcs_ctrl_fd = -1; /* connection to the xcs server. */
-static int xcs_data_fd = -1; /* connection to the xcs server. */
-
-int sock_connect(char *path)
-{
-    struct sockaddr_un addr;
-    int ret, len, fd;
-
-    fd = socket(AF_UNIX, SOCK_STREAM, 0);
-    if (fd < 0)
-    {
-        printf("error creating xcs socket!\n");
-        return -1;
-    }
-
-    addr.sun_family = AF_UNIX;
-    strcpy(addr.sun_path, path);
-    len = sizeof(addr.sun_family) + strlen(addr.sun_path) + 1;
-
-    ret = connect(fd, (struct sockaddr *)&addr, len);
-    if (ret < 0) 
-    {
-        printf("error connecting to xcs!\n");
-        return -1;
-    }
-    
-    return fd;
-}
-
-void sock_disconnect(int *fd)
-{
-    close(*fd);
-    *fd = -1;
-}
-
-void xcs_read(int fd, xcs_msg_t *msg)
-{
-    int ret;
-    
-    ret = read(fd, msg, sizeof(xcs_msg_t));
-    if (ret != sizeof(xcs_msg_t)) {
-        printf("read error\n");
-        exit(-1);
-    }
-}
-
-void xcs_send(int fd, xcs_msg_t *msg)
-{
-    int ret;
-    
-    ret = send(fd, msg, sizeof(xcs_msg_t), 0);
-    if (ret != sizeof(xcs_msg_t) )
-    {
-        printf("send error\n");
-        exit(-1);
-    }
-}
-              
-
-int main(int argc, char* argv[])
-{
-    int ret;
-    xcs_msg_t msg;
-    control_msg_t *cmsg;
-    int verbose = 0;
-    int ch;
-
-    while ((ch = getopt(argc, argv, "hv:")) != -1)
-    {
-        switch (ch)
-        {
-        case 'v':
-            verbose = atoi(optarg);
-            break;
-        case 'h':
-           printf("Usage: %s [-v FLAGS]\n"
-"Displays XCS control message traffic.\n"
-"\n"
-"FLAGS is a bitmask where each bit (numbering starts from LSB) represents\n"
-"whether to display a particular message type.\n"
-"\n"
-"For example, -v 1022 will display all messages except for console messages.\n"
-                  , argv[0]);
-           exit(0);
-           break;
-        }
-    }
-    
-    ret = sock_connect(XCS_SUN_PATH);
-    if (ret < 0) 
-    {
-        printf("connect failed!\n"); 
-        exit(-1);
-    }
-    xcs_ctrl_fd = ret;
-    
-    memset(&msg, 0, sizeof(msg));
-    msg.type = XCS_CONNECT_CTRL;
-    xcs_send(xcs_ctrl_fd, &msg);
-    xcs_read(xcs_ctrl_fd, &msg);
-    if (msg.result != XCS_RSLT_OK)
-    {
-        printf("Error connecting control channel\n");
-        exit(-1);
-    }
-    
-    ret = sock_connect(XCS_SUN_PATH);
-    if (ret < 0) 
-    {
-        printf("connect failed!\n"); 
-        exit(-1);
-    }
-    xcs_data_fd = ret;
-    
-    msg.type = XCS_CONNECT_DATA;
-    /* session id is set from before... */
-    xcs_send(xcs_data_fd, &msg);
-    xcs_read(xcs_data_fd, &msg);
-    if (msg.result != XCS_RSLT_OK)
-    {
-        printf("Error connecting data channel\n");
-        exit(-1);
-    }
-    
-    msg.type = XCS_MSG_BIND;
-    msg.u.bind.port = PORT_WILDCARD;
-    msg.u.bind.type = TYPE_WILDCARD;
-    xcs_send(xcs_ctrl_fd, &msg);
-    xcs_read(xcs_ctrl_fd, &msg);
-    if (msg.result != XCS_RSLT_OK)
-    {
-        printf("Error binding.\n");
-        exit(-1);
-    }
-    
-    
-    while (1)
-    {
-        xcs_read(xcs_data_fd, &msg);
-        cmsg = &msg.u.control.msg;
-        
-        switch (msg.type)
-        {
-        case XCS_REQUEST:
-           if (!verbose || verbose & (1 << msg.u.control.msg.type))
-            {
-               printf("[REQUEST ] : (dom:%u port:%d) (type:(%d,%d) len %d)\n",
-                      msg.u.control.remote_dom,
-                      msg.u.control.local_port,
-                      msg.u.control.msg.type, 
-                      msg.u.control.msg.subtype, 
-                      msg.u.control.msg.length);
-
-               dump_msg(cmsg, verbose);
-           }
-           break; 
-        case XCS_RESPONSE:
-           if (!verbose || verbose & (1 << msg.u.control.msg.type))
-            {
-               printf("[RESPONSE] : (dom:%u port:%d) (type:(%d,%d) len %d)\n",
-                      msg.u.control.remote_dom,
-                      msg.u.control.local_port,
-                      msg.u.control.msg.type, 
-                      msg.u.control.msg.subtype, 
-                      msg.u.control.msg.length);
-
-               dump_msg(cmsg, verbose);
-           }
-           break;
-        case XCS_VIRQ:
-            printf("[VIRQ    ] : %d\n", msg.u.control.local_port);
-           break;
-        default:
-            printf("[UNKNOWN ] : %d\n", msg.type);
-        }
-    }
-    
-    return(0);
-}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/dom_mem_ops.c
--- a/xen/common/dom_mem_ops.c  Thu Sep  8 15:18:40 2005
+++ /dev/null   Fri Sep  9 16:30:54 2005
@@ -1,186 +0,0 @@
-/******************************************************************************
- * dom_mem_ops.c
- *
- * Code to handle memory related requests from domains eg. balloon driver.
- *
- * Copyright (c) 2003-2004, B Dragovic & K A Fraser.
- */
-
-#include <xen/config.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/mm.h>
-#include <xen/perfc.h>
-#include <xen/sched.h>
-#include <xen/event.h>
-#include <xen/shadow.h>
-#include <asm/current.h>
-#include <asm/hardirq.h>
-
-/*
- * To allow safe resume of do_dom_mem_op() after preemption, we need to know 
- * at what point in the page list to resume. For this purpose I steal the 
- * high-order bits of the @op parameter, which are otherwise unused and zero.
- */
-#define START_EXTENT_SHIFT 4 /* op[:4] == start_extent */
-
-#define PREEMPT_CHECK(_op)                          \
-    if ( hypercall_preempt_check() )                \
-        return hypercall5_create_continuation(      \
-            __HYPERVISOR_dom_mem_op,                \
-            (_op) | (i << START_EXTENT_SHIFT),      \
-            extent_list, nr_extents, extent_order,  \
-            (d == current->domain) ? DOMID_SELF : d->domain_id);
-
-static long
-alloc_dom_mem(struct domain *d, 
-              unsigned long *extent_list, 
-              unsigned long  start_extent,
-              unsigned int   nr_extents,
-              unsigned int   extent_order,
-                 unsigned int   flags)
-{
-    struct pfn_info *page;
-    unsigned long    i;
-
-    if ( (extent_list != NULL) && 
-         !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
-        return start_extent;
-
-    if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) )
-    {
-        DPRINTK("Only I/O-capable domains may allocate > order-0 memory.\n");
-        return start_extent;
-    }
-
-    for ( i = start_extent; i < nr_extents; i++ )
-    {
-        PREEMPT_CHECK(MEMOP_increase_reservation);
-
-        if ( unlikely((page = alloc_domheap_pages(d, extent_order,
-                                                  flags)) == NULL) )
-        {
-            DPRINTK("Could not allocate a frame\n");
-            return i;
-        }
-
-        /* Inform the domain of the new page's machine address. */ 
-        if ( (extent_list != NULL) && 
-             (__put_user(page_to_pfn(page), &extent_list[i]) != 0) )
-            return i;
-    }
-
-    return i;
-}
-    
-static long
-free_dom_mem(struct domain *d,
-             unsigned long *extent_list, 
-             unsigned long  start_extent,
-             unsigned int   nr_extents,
-             unsigned int   extent_order)
-{
-    struct pfn_info *page;
-    unsigned long    i, j, mpfn;
-
-    if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
-        return start_extent;
-
-    for ( i = start_extent; i < nr_extents; i++ )
-    {
-        PREEMPT_CHECK(MEMOP_decrease_reservation);
-
-        if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
-            return i;
-
-        for ( j = 0; j < (1 << extent_order); j++ )
-        {
-            if ( unlikely((mpfn + j) >= max_page) )
-            {
-                DPRINTK("Domain %u page number out of range (%lx >= %lx)\n", 
-                        d->domain_id, mpfn + j, max_page);
-                return i;
-            }
-            
-            page = &frame_table[mpfn + j];
-            if ( unlikely(!get_page(page, d)) )
-            {
-                DPRINTK("Bad page free for domain %u\n", d->domain_id);
-                return i;
-            }
-
-            if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
-                put_page_and_type(page);
-            
-            if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
-                put_page(page);
-
-            shadow_sync_and_drop_references(d, page);
-
-            put_page(page);
-        }
-    }
-
-    return i;
-}
-
-long
-do_dom_mem_op(unsigned long  op, 
-              unsigned long *extent_list, 
-              unsigned int   nr_extents,
-              unsigned int   extent_order,
-              domid_t        domid)
-{
-    struct domain *d;
-    unsigned long  rc, start_extent;
-    unsigned int   address_bits_order;
-
-    /* Extract @start_extent from @op. */
-    start_extent  = op >> START_EXTENT_SHIFT;
-    op           &= (1 << START_EXTENT_SHIFT) - 1;
-
-    /* seperate extent_order and address_bits_order */
-    address_bits_order = (extent_order >> 8) & 0xff;
-    extent_order &= 0xff;
-
-    if ( unlikely(start_extent > nr_extents) )
-        return -EINVAL;
-
-    if ( likely(domid == DOMID_SELF) )
-        d = current->domain;
-    else if ( unlikely(!IS_PRIV(current->domain)) )
-        return -EPERM;
-    else if ( unlikely((d = find_domain_by_id(domid)) == NULL) )
-        return -ESRCH;
-
-    switch ( op )
-    {
-    case MEMOP_increase_reservation:
-        rc = alloc_dom_mem(
-            d, extent_list, start_extent, nr_extents, extent_order,
-            (address_bits_order <= 32) ? ALLOC_DOM_DMA : 0);
-        break;
-    case MEMOP_decrease_reservation:
-        rc = free_dom_mem(
-            d, extent_list, start_extent, nr_extents, extent_order);
-        break;
-    default:
-        rc = -ENOSYS;
-        break;
-    }
-
-    if ( unlikely(domid != DOMID_SELF) )
-        put_domain(d);
-
-    return rc;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Merge (only) xen-ia64-unstable with latest xen-unstable, Xen patchbot -unstable <=