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] Merged.

# HG changeset patch
# User emellor@xxxxxxxxxxxxxxxxxxxxxx
# Node ID 28a117c5ea94ef73c01cd46c6f87c576f1580c83
# Parent  42474df9b24804392bd84a853c1474b7dcc24952
# Parent  9c81a3c5b33b868632a83806e88f2328c11c2e93
Merged.

diff -r 42474df9b248 -r 28a117c5ea94 docs/misc/vtpm.txt
--- a/docs/misc/vtpm.txt        Fri Nov 25 11:19:03 2005
+++ b/docs/misc/vtpm.txt        Fri Nov 25 11:19:09 2005
@@ -73,7 +73,14 @@
 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.
+different instance and that using instance 0 is NOT allowed. The
+instance parameter is taken as the desired instance number, but
+the actual instance number that is assigned to the virtual machine
+can be different. This is the case if for example that particular
+instance is already used by another virtual machine. The association
+of which TPM instance number is used by which virtual machine is
+kept in the file /etc/xen/vtpm.db. Associations are maintained by
+domain name and instance number.
 
 Note: If you do not want TPM functionality for your user domain simply
 leave out the 'vtpm' line in the configuration file.
diff -r 42474df9b248 -r 28a117c5ea94 
linux-2.6-xen-sparse/arch/xen/i386/mm/init.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c      Fri Nov 25 11:19:03 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c      Fri Nov 25 11:19:09 2005
@@ -708,7 +708,7 @@
                        panic("pgtable_cache_init(): cannot create pmd cache");
        }
        pgd_cache = kmem_cache_create("pgd",
-#if 0 /* How the heck _this_ works in native linux ??? */
+#ifndef CONFIG_XEN
                                PTRS_PER_PGD*sizeof(pgd_t),
                                PTRS_PER_PGD*sizeof(pgd_t),
 #else
@@ -717,7 +717,7 @@
 #endif
                                0,
                                pgd_ctor,
-                               pgd_dtor);
+                               PTRS_PER_PMD == 1 ? pgd_dtor : NULL);
        if (!pgd_cache)
                panic("pgtable_cache_init(): Cannot create pgd cache");
 }
diff -r 42474df9b248 -r 28a117c5ea94 
linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c   Fri Nov 25 11:19:03 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c   Fri Nov 25 11:19:09 2005
@@ -28,8 +28,6 @@
 #include <asm/hypervisor.h>
 
 static void pgd_test_and_unpin(pgd_t *pgd);
-#define suspend_disable        preempt_disable
-#define suspend_enable preempt_enable
 
 void show_mem(void)
 {
@@ -279,26 +277,31 @@
 {
        unsigned long flags;
 
-#ifdef CONFIG_X86_PAE
-       /* Ensure pgd resides below 4GB. */
-       int rc = xen_create_contiguous_region((unsigned long)pgd, 0, 32);
-       BUG_ON(rc);
+       if (PTRS_PER_PMD > 1) {
+#ifdef CONFIG_XEN
+               /* Ensure pgd resides below 4GB. */
+               int rc = xen_create_contiguous_region(
+                       (unsigned long)pgd, 0, 32);
+               BUG_ON(rc);
 #endif
-
-       if (HAVE_SHARED_KERNEL_PMD) {
+               if (HAVE_SHARED_KERNEL_PMD)
+                       memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
+                              swapper_pg_dir, sizeof(pgd_t));
+       } else {
+               if (!HAVE_SHARED_KERNEL_PMD)
+                       spin_lock_irqsave(&pgd_lock, flags);
                memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
                       swapper_pg_dir + USER_PTRS_PER_PGD,
                       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
-               return;
-       }
-
-       memset(pgd, 0, PTRS_PER_PGD*sizeof(pgd_t));
-
-       spin_lock_irqsave(&pgd_lock, flags);
-       pgd_list_add(pgd);
-       spin_unlock_irqrestore(&pgd_lock, flags);
-}
-
+               memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+               if (!HAVE_SHARED_KERNEL_PMD) {
+                       pgd_list_add(pgd);
+                       spin_unlock_irqrestore(&pgd_lock, flags);
+               }
+       }
+}
+
+/* never called when PTRS_PER_PMD > 1 */
 void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused)
 {
        unsigned long flags; /* can be called from interrupt context */
@@ -315,7 +318,7 @@
 
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-       int i = 0;
+       int i;
        pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
 
        pgd_test_and_unpin(pgd);
@@ -323,34 +326,31 @@
        if (PTRS_PER_PMD == 1 || !pgd)
                return pgd;
 
+       for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
+               pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
+               if (!pmd)
+                       goto out_oom;
+               set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
+       }
+
        if (!HAVE_SHARED_KERNEL_PMD) {
-               /* alloc and copy kernel pmd */
                unsigned long flags;
                pgd_t *copy_pgd = pgd_offset_k(PAGE_OFFSET);
                pud_t *copy_pud = pud_offset(copy_pgd, PAGE_OFFSET);
                pmd_t *copy_pmd = pmd_offset(copy_pud, PAGE_OFFSET);
                pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
-               if (0 == pmd)
+               ++i;
+               if (!pmd)
                        goto out_oom;
 
                spin_lock_irqsave(&pgd_lock, flags);
                memcpy(pmd, copy_pmd, PAGE_SIZE);
-               spin_unlock_irqrestore(&pgd_lock, flags);
                make_lowmem_page_readonly(pmd);
                set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd)));
-       }
-
-       /* alloc user pmds */
-       for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
-               pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
-               if (!pmd)
-                       goto out_oom;
-               suspend_disable();
-               if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
-                       make_lowmem_page_readonly(pmd);
-               set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
-               suspend_enable();
-       }
+               pgd_list_add(pgd);
+               spin_unlock_irqrestore(&pgd_lock, flags);
+       }
+
        return pgd;
 
 out_oom:
@@ -364,28 +364,25 @@
 {
        int i;
 
-       suspend_disable();
        pgd_test_and_unpin(pgd);
 
        /* in the PAE case user pgd entries are overwritten before usage */
        if (PTRS_PER_PMD > 1) {
                for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
                        pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
-                       set_pgd(&pgd[i], __pgd(0));
-                       make_lowmem_page_writable(pmd);
                        kmem_cache_free(pmd_cache, pmd);
                }
                if (!HAVE_SHARED_KERNEL_PMD) {
+                       unsigned long flags;
                        pmd_t *pmd = (void 
*)__va(pgd_val(pgd[USER_PTRS_PER_PGD])-1);
-                       set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(0));
+                       spin_lock_irqsave(&pgd_lock, flags);
+                       pgd_list_del(pgd);
+                       spin_unlock_irqrestore(&pgd_lock, flags);
                        make_lowmem_page_writable(pmd);
                        memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
                        kmem_cache_free(pmd_cache, pmd);
                }
        }
-
-       suspend_enable();
-
        /* in the non-PAE case, free_pgtables() clears user pgd entries */
        kmem_cache_free(pgd_cache, pgd);
 }
@@ -510,9 +507,6 @@
 
 static void __pgd_pin(pgd_t *pgd)
 {
-       /* PAE PGDs with no kernel PMD cannot be pinned. Bail right now. */
-       if ((PTRS_PER_PMD > 1) && pgd_none(pgd[USER_PTRS_PER_PGD]))
-               return;
        pgd_walk(pgd, PAGE_KERNEL_RO);
        xen_pgd_pin(__pa(pgd));
        set_bit(PG_pinned, &virt_to_page(pgd)->flags);
@@ -527,10 +521,8 @@
 
 static void pgd_test_and_unpin(pgd_t *pgd)
 {
-       suspend_disable();
        if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
                __pgd_unpin(pgd);
-       suspend_enable();
 }
 
 void mm_pin(struct mm_struct *mm)
diff -r 42474df9b248 -r 28a117c5ea94 
linux-2.6-xen-sparse/drivers/char/tpm/Kconfig
--- a/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig     Fri Nov 25 11:19:03 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig     Fri Nov 25 11:19:09 2005
@@ -17,15 +17,6 @@
          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_TIS
-       tristate "TPM Interface Specification 1.2 Interface"
-       depends on TCG_TPM
-       ---help---
-         If you have a TPM security chip that is compliant with the
-         TCG TIS 1.2 TPM specification 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_tis.
 
 config TCG_NSC
        tristate "National Semiconductor TPM Interface"
diff -r 42474df9b248 -r 28a117c5ea94 
linux-2.6-xen-sparse/drivers/xen/tpmback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Fri Nov 25 11:19:03 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Fri Nov 25 11:19:09 2005
@@ -28,7 +28,7 @@
 #endif
 
 typedef struct tpmif_st {
-        struct list_head tpmif_list;
+       struct list_head tpmif_list;
        /* Unique identifier for this interface. */
        domid_t domid;
        unsigned int handle;
@@ -83,6 +83,11 @@
 
 #define MMAP_VADDR(t,_req) ((t)->mmap_vstart + ((_req) * PAGE_SIZE))
 
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
 #endif /* __TPMIF__BACKEND__COMMON_H__ */
 
 /*
diff -r 42474df9b248 -r 28a117c5ea94 
linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c      Fri Nov 25 
11:19:03 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c      Fri Nov 25 
11:19:09 2005
@@ -127,6 +127,10 @@
                .u.bind_interdomain.remote_dom = tpmif->domid,
                .u.bind_interdomain.remote_port = evtchn };
 
+        if (tpmif->irq) {
+                return 0;
+        }
+
        if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL)
                return -ENOMEM;
 
@@ -149,7 +153,6 @@
 
        tpmif->irq = bind_evtchn_to_irqhandler(
                tpmif->evtchn, tpmif_be_int, 0, "tpmif-backend", tpmif);
-       tpmif->status = CONNECTED;
        tpmif->shmem_ref = shared_page;
        tpmif->active = 1;
 
diff -r 42474df9b248 -r 28a117c5ea94 
linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Fri Nov 25 11:19:03 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Fri Nov 25 11:19:09 2005
@@ -1,4 +1,5 @@
 /*  Xenbus code for tpmif backend
+    Copyright (C) 2005 IBM Corporation
     Copyright (C) 2005 Rusty Russell <rusty@xxxxxxxxxxxxxxx>
 
     This program is free software; you can redistribute it and/or modify
@@ -29,72 +30,189 @@
 
        long int frontend_id;
        long int instance; // instance of TPM
+       u8 is_instance_set;// whether instance number has been set
 
        /* watch front end for changes */
        struct xenbus_watch backend_watch;
-
-       struct xenbus_watch watch;
-       char * frontpath;
+       XenbusState frontend_state;
 };
 
+static void maybe_connect(struct backend_info *be);
+static void connect(struct backend_info *be);
+static int connect_ring(struct backend_info *be);
+static void backend_changed(struct xenbus_watch *watch,
+                            const char **vec, unsigned int len);
+static void frontend_changed(struct xenbus_device *dev,
+                             XenbusState frontend_state);
+
 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)
+       if (be->backend_watch.node) {
+               unregister_xenbus_watch(&be->backend_watch);
+               kfree(be->backend_watch.node);
+               be->backend_watch.node = NULL;
+       }
+       if (be->tpmif) {
                tpmif_put(be->tpmif);
-
-       kfree(be->frontpath);
+               be->tpmif = NULL;
+       }
        kfree(be);
+       dev->data = NULL;
        return 0;
 }
 
-
-static void frontend_changed(struct xenbus_watch *watch,
-                            const char **vec, unsigned int len)
-{
-       unsigned long ringref;
-       unsigned int evtchn;
-       unsigned long ready = 1;
-       int err;
-       struct xenbus_transaction *xbt;
+static int tpmback_probe(struct xenbus_device *dev,
+                         const struct xenbus_device_id *id)
+{
+       int err;
+       struct backend_info *be = kmalloc(sizeof(struct backend_info),
+                                         GFP_KERNEL);
+
+       if (!be) {
+               xenbus_dev_fatal(dev, -ENOMEM,
+                                "allocating backend structure");
+               return -ENOMEM;
+       }
+
+       memset(be, 0, sizeof(*be));
+
+       be->is_instance_set = FALSE;
+       be->dev = dev;
+       dev->data = be;
+
+       err = xenbus_watch_path2(dev, dev->nodename,
+                               "instance", &be->backend_watch,
+                               backend_changed);
+       if (err) {
+               goto fail;
+       }
+
+       err = xenbus_switch_state(dev, NULL, XenbusStateInitWait);
+       if (err) {
+               goto fail;
+       }
+       return 0;
+fail:
+       tpmback_remove(dev);
+       return err;
+}
+
+
+static void backend_changed(struct xenbus_watch *watch,
+                            const char **vec, unsigned int len)
+{
+       int err;
+       long instance;
        struct backend_info *be
-               = container_of(watch, struct backend_info, watch);
-
-       /* If other end is gone, delete ourself. */
-       if (vec && !xenbus_exists(NULL, be->frontpath, "")) {
-               xenbus_rm(NULL, be->dev->nodename, "");
+               = container_of(watch, struct backend_info, backend_watch);
+       struct xenbus_device *dev = be->dev;
+
+       err = xenbus_scanf(NULL, dev->nodename,
+                          "instance","%li", &instance);
+       if (XENBUS_EXIST_ERR(err)) {
+               return;
+       }
+
+       if (err != 1) {
+               xenbus_dev_fatal(dev, err, "reading instance");
+               return;
+       }
+
+       if (be->is_instance_set != FALSE && be->instance != instance) {
+               printk(KERN_WARNING
+                      "tpmback: changing instance (from %ld to %ld) "
+                      "not allowed.\n",
+                      be->instance, instance);
+               return;
+       }
+
+       if (be->is_instance_set == FALSE) {
+               be->tpmif = tpmif_find(dev->otherend_id,
+                                      instance);
+               if (IS_ERR(be->tpmif)) {
+                       err = PTR_ERR(be->tpmif);
+                       be->tpmif = NULL;
+                       xenbus_dev_fatal(dev,err,"creating block interface");
+                       return;
+               }
+               be->instance = instance;
+               be->is_instance_set = TRUE;
+
+               /*
+                * There's an unfortunate problem:
+                * Sometimes after a suspend/resume the
+                * state switch to XenbusStateInitialised happens
+                * *before* I get to this point here. Since then
+                * the connect_ring() must have failed (be->tpmif is
+                * still NULL), I just call it here again indirectly.
+                */
+               if (be->frontend_state == XenbusStateInitialised) {
+                       frontend_changed(dev, be->frontend_state);
+               }
+       }
+}
+
+
+static void frontend_changed(struct xenbus_device *dev,
+                             XenbusState frontend_state)
+{
+       struct backend_info *be = dev->data;
+       int err;
+
+       be->frontend_state = frontend_state;
+
+       switch (frontend_state) {
+       case XenbusStateInitialising:
+       case XenbusStateConnected:
+               break;
+
+       case XenbusStateInitialised:
+               err = connect_ring(be);
+               if (err) {
+                       return;
+               }
+               maybe_connect(be);
+               break;
+
+       case XenbusStateClosing:
+               xenbus_switch_state(dev, NULL, XenbusStateClosing);
+               break;
+
+       case XenbusStateClosed:
+               /*
+                * Notify the vTPM manager about the front-end
+                * having left.
+                */
+               tpmif_vtpm_close(be->instance);
                device_unregister(&be->dev->dev);
-               return;
-       }
+               break;
+
+       case XenbusStateUnknown:
+       case XenbusStateInitWait:
+       default:
+               xenbus_dev_fatal(dev, -EINVAL,
+                                "saw state %d at frontend",
+                                frontend_state);
+               break;
+       }
+}
+
+
+
+static void maybe_connect(struct backend_info *be)
+{
+       int err;
 
        if (be->tpmif == NULL || be->tpmif->status == CONNECTED)
                return;
 
-       err = xenbus_gather(NULL, 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;
-       }
-
-       err = tpmif_map(be->tpmif, ringref, evtchn);
-       if (err) {
-               xenbus_dev_error(be->dev, err,
-                                "mapping shared-frame %lu port %u",
-                                ringref, evtchn);
-               return;
-       }
-
+       connect(be);
+
+       /*
+        * Notify the vTPM manager about a new front-end.
+        */
        err = tpmif_vtpm_open(be->tpmif,
                              be->frontend_id,
                              be->instance);
@@ -107,157 +225,75 @@
                 */
                return;
        }
-
-       /*
-        * Tell the front-end that we are ready to go -
-        * unless something bad happens
-        */
+}
+
+
+static void connect(struct backend_info *be)
+{
+       struct xenbus_transaction *xbt;
+       int err;
+       struct xenbus_device *dev = be->dev;
+       unsigned long ready = 1;
+
 again:
        xbt = xenbus_transaction_start();
        if (IS_ERR(xbt)) {
-               xenbus_dev_error(be->dev, err, "starting transaction");
+               err = PTR_ERR(xbt);
+               xenbus_dev_fatal(be->dev, err, "starting transaction");
                return;
        }
 
        err = xenbus_printf(xbt, be->dev->nodename,
                            "ready", "%lu", ready);
        if (err) {
-               xenbus_dev_error(be->dev, err, "writing 'ready'");
+               xenbus_dev_fatal(be->dev, err, "writing 'ready'");
                goto abort;
        }
+
+       err = xenbus_switch_state(dev, xbt, XenbusStateConnected);
+       if (err)
+               goto abort;
+
+       be->tpmif->status = CONNECTED;
 
        err = xenbus_transaction_end(xbt, 0);
        if (err == -EAGAIN)
                goto again;
        if (err) {
-               xenbus_dev_error(be->dev, err, "end of transaction");
-               goto abort;
-       }
-
-       xenbus_dev_ok(be->dev);
+               xenbus_dev_fatal(be->dev, err, "end of transaction");
+       }
        return;
 abort:
        xenbus_transaction_end(xbt, 1);
 }
 
 
-static void backend_changed(struct xenbus_watch *watch,
-                           const char **vec, unsigned int len)
-{
-       int err;
-       long int instance;
-       struct backend_info *be
-               = container_of(watch, struct backend_info, backend_watch);
+static int connect_ring(struct backend_info *be)
+{
        struct xenbus_device *dev = be->dev;
-
-       err = xenbus_scanf(NULL, 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) {
-               unsigned int len = max(XS_WATCH_PATH, XS_WATCH_TOKEN) + 1;
-               const char *vec[len];
-
-               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;
+       unsigned long ring_ref;
+       unsigned int evtchn;
+       int err;
+
+       err = xenbus_gather(NULL, dev->otherend,
+                           "ring-ref", "%lu", &ring_ref,
+                           "event-channel", "%u", &evtchn, NULL);
+       if (err) {
+               xenbus_dev_error(dev, err,
+                                "reading %s/ring-ref and event-channel",
+                                dev->otherend);
+               return err;
+       }
+       if (be->tpmif != NULL) {
+               err = tpmif_map(be->tpmif, ring_ref, evtchn);
+               if (err) {
+                       xenbus_dev_error(dev, err,
+                                        "mapping shared-frame %lu port %u",
+                                        ring_ref, evtchn);
+                       return err;
                }
-
-               vec[XS_WATCH_PATH] = be->frontpath;
-               vec[XS_WATCH_TOKEN] = NULL;
-
-               /* Pass in NULL node to skip exist test. */
-               frontend_changed(&be->watch, vec, len);
-       }
-}
-
-
-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(NULL, 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(NULL, 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;
-       /* Implicitly calls backend_changed() once. */
-       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;
-       return err;
-
-free_be:
-       if (be->backend_watch.node)
-               unregister_xenbus_watch(&be->backend_watch);
-       kfree(frontend);
-       kfree(be);
-       return err;
+       }
+       return 0;
 }
 
 
@@ -273,6 +309,7 @@
        .ids = tpmback_ids,
        .probe = tpmback_probe,
        .remove = tpmback_remove,
+       .otherend_changed = frontend_changed,
 };
 
 
diff -r 42474df9b248 -r 28a117c5ea94 
linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c      Fri Nov 25 
11:19:03 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c      Fri Nov 25 
11:19:09 2005
@@ -73,7 +73,8 @@
 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 void tpmif_set_connected_state(struct tpm_private *tp,
+                                      u8 newstate);
 static int tpm_xmit(struct tpm_private *tp,
                     const u8 * buf, size_t count, int userbuffer,
                     void *remember);
@@ -212,87 +213,46 @@
  XENBUS support code
 **************************************************************/
 
-static void watch_for_status(struct xenbus_watch *watch,
-                            const char **vec, unsigned int len)
-{
-       struct tpmfront_info *info;
-       int err;
-       unsigned long ready;
-       struct tpm_private *tp = &my_private;
-       const char *node = vec[XS_WATCH_PATH];
-
-       info = container_of(watch, struct tpmfront_info, watch);
-       node += strlen(watch->node);
-
-       if (tp->connected)
-               return;
-
-       err = xenbus_gather(NULL, 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)
+                         struct tpmfront_info * info)
 {
        tpmif_tx_interface_t *sring;
        struct tpm_private *tp = &my_private;
        int err;
-       evtchn_op_t op = {
-               .cmd = EVTCHNOP_alloc_unbound,
-               .u.alloc_unbound.dom = DOMID_SELF,
-               .u.alloc_unbound.remote_dom = backend_id } ;
 
        sring = (void *)__get_free_page(GFP_KERNEL);
        if (!sring) {
-               xenbus_dev_error(dev, -ENOMEM, "allocating shared ring");
+               xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
                return -ENOMEM;
        }
        tp->tx = sring;
 
        tpm_allocate_buffers(tp);
 
-       err = gnttab_grant_foreign_access(backend_id,
-                                         (virt_to_machine(tp->tx) >> 
PAGE_SHIFT),
-                                         0);
-
-       if (err == -ENOSPC) {
+       err = xenbus_grant_ring(dev, virt_to_mfn(tp->tx));
+       if (err < 0) {
                free_page((unsigned long)sring);
                tp->tx = NULL;
-               xenbus_dev_error(dev, err, "allocating grant reference");
-               return err;
+               xenbus_dev_fatal(dev, err, "allocating grant reference");
+               goto fail;
        }
        info->ring_ref = err;
 
-       err = HYPERVISOR_event_channel_op(&op);
-       if (err) {
-               gnttab_end_foreign_access(info->ring_ref, 0,
-                                         (unsigned long)sring);
-               tp->tx = NULL;
-               xenbus_dev_error(dev, err, "allocating event channel");
-               return err;
-       }
-
-       tpmif_connect(op.u.alloc_unbound.port, backend_id);
+       err = xenbus_alloc_evtchn(dev, &tp->evtchn);
+       if (err)
+               goto fail;
+
+       tpmif_connect(tp->evtchn, dev->otherend_id);
 
        return 0;
+fail:
+       return err;
 }
 
 
 static void destroy_tpmring(struct tpmfront_info *info, struct tpm_private *tp)
 {
-       tpmif_set_connected_state(tp,0);
-
+       tpmif_set_connected_state(tp, FALSE);
        if ( tp->tx != NULL ) {
                gnttab_end_foreign_access(info->ring_ref, 0,
                                          (unsigned long)tp->tx);
@@ -308,42 +268,20 @@
 static int talk_to_backend(struct xenbus_device *dev,
                            struct tpmfront_info *info)
 {
-       char *backend;
-       const char *message;
+       const char *message = NULL;
        int err;
-       int backend_id;
        struct xenbus_transaction *xbt;
 
-       backend = NULL;
-       err = xenbus_gather(NULL, 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);
+       err = setup_tpmring(dev, info);
        if (err) {
-               xenbus_dev_error(dev, err, "setting up ring");
+               xenbus_dev_fatal(dev, err, "setting up ring");
                goto out;
        }
 
 again:
        xbt = xenbus_transaction_start();
        if (IS_ERR(xbt)) {
-               xenbus_dev_error(dev, err, "starting transaction");
+               xenbus_dev_fatal(dev, err, "starting transaction");
                goto destroy_tpmring;
        }
 
@@ -361,34 +299,60 @@
                goto abort_transaction;
        }
 
+       err = xenbus_switch_state(dev, xbt, XenbusStateInitialised);
+       if (err) {
+               goto abort_transaction;
+       }
+
        err = xenbus_transaction_end(xbt, 0);
        if (err == -EAGAIN)
                goto again;
        if (err) {
-               xenbus_dev_error(dev, err, "completing transaction");
+               xenbus_dev_fatal(dev, err, "completing transaction");
                goto destroy_tpmring;
        }
-
-       info->watch.node = backend;
-       info->watch.callback = watch_for_status;
-       err = register_xenbus_watch(&info->watch);
-       if (err) {
-               xenbus_dev_error(dev, err, "registering watch on backend");
-               goto destroy_tpmring;
-       }
-
-       info->backend = backend;
-
        return 0;
 
 abort_transaction:
        xenbus_transaction_end(xbt, 1);
-       xenbus_dev_error(dev, err, "%s", message);
+       if (message)
+               xenbus_dev_error(dev, err, "%s", message);
 destroy_tpmring:
        destroy_tpmring(info, &my_private);
 out:
-       kfree(backend);
        return err;
+}
+
+/**
+ * Callback received when the backend's state changes.
+ */
+static void backend_changed(struct xenbus_device *dev,
+                           XenbusState backend_state)
+{
+       struct tpm_private *tp = &my_private;
+       DPRINTK("\n");
+
+       switch (backend_state) {
+       case XenbusStateInitialising:
+       case XenbusStateInitWait:
+       case XenbusStateInitialised:
+       case XenbusStateUnknown:
+               break;
+
+       case XenbusStateConnected:
+               tpmif_set_connected_state(tp, TRUE);
+               break;
+
+       case XenbusStateClosing:
+               tpmif_set_connected_state(tp, FALSE);
+               break;
+
+       case XenbusStateClosed:
+               if (tp->is_suspended == FALSE) {
+                       device_unregister(&dev->dev);
+               }
+               break;
+       }
 }
 
 
@@ -398,8 +362,6 @@
        int err;
        struct tpmfront_info *info;
        int handle;
-       int len = max(XS_WATCH_PATH, XS_WATCH_TOKEN) + 1;
-       const char *vec[len];
 
        err = xenbus_scanf(NULL, dev->nodename,
                           "handle", "%i", &handle);
@@ -407,19 +369,19 @@
                return err;
 
        if (err < 0) {
-               xenbus_dev_error(dev,err,"reading virtual-device");
+               xenbus_dev_fatal(dev,err,"reading virtual-device");
                return err;
        }
 
        info = kmalloc(sizeof(*info), GFP_KERNEL);
        if (!info) {
-               xenbus_dev_error(dev,err,"allocating info structure");
+               err = -ENOMEM;
+               xenbus_dev_fatal(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);
@@ -428,41 +390,33 @@
                dev->data = NULL;
                return err;
        }
-
-       vec[XS_WATCH_PATH]  = info->watch.node;
-       vec[XS_WATCH_TOKEN] = NULL;
-       watch_for_status(&info->watch, vec, len);
-
        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;
        u32 ctr = 0;
 
        /* lock, so no app can send */
        down(&suspend_lock);
+       tp->is_suspended = TRUE;
 
        while (atomic_read(&tp->tx_busy) && ctr <= 25) {
-               if ((ctr % 10) == 0)
-                       printk("INFO: Waiting for outstanding request.\n");
+               if ((ctr % 10) == 0)
+                       printk("TPM-FE [INFO]: Waiting for outstanding 
request.\n");
                /*
                 * Wait for a request to be responded to.
                 */
@@ -474,14 +428,9 @@
                /*
                 * A temporary work-around.
                 */
-               printk("WARNING: Resetting busy flag.");
+               printk("TPM-FE [WARNING]: Resetting busy flag.");
                atomic_set(&tp->tx_busy, 0);
        }
-
-       unregister_xenbus_watch(&info->watch);
-
-       kfree(info->backend);
-       info->backend = NULL;
 
        return 0;
 }
@@ -492,8 +441,6 @@
        struct tpmfront_info *info = dev->data;
        int err = talk_to_backend(dev, info);
 
-       /* unlock, so apps can resume sending */
-       up(&suspend_lock);
 
        return err;
 }
@@ -530,12 +477,13 @@
        .probe = tpmfront_probe,
        .remove =  tpmfront_remove,
        .resume = tpmfront_resume,
+       .otherend_changed = backend_changed,
        .suspend = tpmfront_suspend,
 };
 
 static void __init init_tpm_xenbus(void)
 {
-       xenbus_register_driver(&tpmfront);
+       xenbus_register_frontend(&tpmfront);
 }
 
 
@@ -628,12 +576,13 @@
        spin_lock_irq(&tp->tx_lock);
 
        if (unlikely(atomic_read(&tp->tx_busy))) {
-               printk("There's an outstanding request/response on the way!\n");
+               printk("tpm_xmit: There's an outstanding request/response "
+                      "on the way!\n");
                spin_unlock_irq(&tp->tx_lock);
                return -EBUSY;
        }
 
-       if (tp->connected != 1) {
+       if (tp->is_connected != TRUE) {
                spin_unlock_irq(&tp->tx_lock);
                return -EIO;
        }
@@ -705,24 +654,40 @@
        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;
+               if (tp->is_connected) {
+                       upperlayer_tpmfe->status(TPMFE_STATUS_CONNECTED);
+               } else {
+                       upperlayer_tpmfe->status(0);
                }
        }
        up(&upperlayer_lock);
 }
 
 
-static void tpmif_set_connected_state(struct tpm_private *tp, int newstate)
-{
-       if (newstate != tp->connected) {
-               tp->connected = newstate;
+static void tpmif_set_connected_state(struct tpm_private *tp, u8 is_connected)
+{
+       /*
+        * Don't notify upper layer if we are in suspend mode and
+        * should disconnect - assumption is that we will resume
+        * The semaphore keeps apps from sending.
+        */
+       if (is_connected == FALSE && tp->is_suspended == TRUE) {
+               return;
+       }
+
+       /*
+        * Unlock the semaphore if we are connected again
+        * after being suspended - now resuming.
+        * This also removes the suspend state.
+        */
+       if (is_connected == TRUE && tp->is_suspended == TRUE) {
+               tp->is_suspended = FALSE;
+               /* unlock, so apps can resume sending */
+               up(&suspend_lock);
+       }
+
+       if (is_connected != tp->is_connected) {
+               tp->is_connected = is_connected;
                tpmif_notify_upperlayer(tp);
        }
 }
diff -r 42474df9b248 -r 28a117c5ea94 
linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h
--- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h      Fri Nov 25 
11:19:03 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h      Fri Nov 25 
11:19:09 2005
@@ -1,12 +1,17 @@
 #ifndef TPM_FRONT_H
 #define TPM_FRONT_H
 
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
 
-struct tpm_private
-{
+struct tpm_private {
        tpmif_tx_interface_t *tx;
-       unsigned int evtchn, irq;
-       int connected;
+       unsigned int evtchn;
+       unsigned int irq;
+       u8 is_connected;
+       u8 is_suspended;
 
        spinlock_t tx_lock;
 
@@ -16,25 +21,18 @@
        void *tx_remember;
        domid_t backend_id;
        wait_queue_head_t wait_q;
+
 };
 
-
-struct tpmfront_info
-{
-       struct xenbus_watch watch;
-       int handle;
+struct tpmfront_info {
        struct xenbus_device *dev;
-       char *backend;
        int ring_ref;
-       domid_t backend_id;
 };
 
-
-struct tx_buffer
-{
+struct tx_buffer {
        unsigned int size;      // available space in data
        unsigned int len;       // used space in data
-       unsigned char *data;    // pointer to a page
+       unsigned char *data;    // pointer to a page
 };
 
 #endif
diff -r 42474df9b248 -r 28a117c5ea94 patches/linux-2.6.12/pmd-shared.patch
--- a/patches/linux-2.6.12/pmd-shared.patch     Fri Nov 25 11:19:03 2005
+++ b/patches/linux-2.6.12/pmd-shared.patch     Fri Nov 25 11:19:09 2005
@@ -1,15 +1,3 @@
-diff -urNpP linux-2.6.12/arch/i386/mm/init.c 
linux-2.6.12.new/arch/i386/mm/init.c
---- linux-2.6.12/arch/i386/mm/init.c   2005-06-17 20:48:29.000000000 +0100
-+++ linux-2.6.12.new/arch/i386/mm/init.c       2005-07-11 16:28:09.778165582 
+0100
-@@ -634,7 +634,7 @@ void __init pgtable_cache_init(void)
-                               PTRS_PER_PGD*sizeof(pgd_t),
-                               0,
-                               pgd_ctor,
--                              PTRS_PER_PMD == 1 ? pgd_dtor : NULL);
-+                              pgd_dtor);
-       if (!pgd_cache)
-               panic("pgtable_cache_init(): Cannot create pgd cache");
- }
 diff -urNpP linux-2.6.12/arch/i386/mm/pageattr.c 
linux-2.6.12.new/arch/i386/mm/pageattr.c
 --- linux-2.6.12/arch/i386/mm/pageattr.c       2005-06-17 20:48:29.000000000 
+0100
 +++ linux-2.6.12.new/arch/i386/mm/pageattr.c   2005-07-11 16:28:09.775165494 
+0100
@@ -23,31 +11,45 @@
  
        spin_lock_irqsave(&pgd_lock, flags);
 diff -urNpP linux-2.6.12/arch/i386/mm/pgtable.c 
linux-2.6.12.new/arch/i386/mm/pgtable.c
---- linux-2.6.12/arch/i386/mm/pgtable.c        2005-06-17 20:48:29.000000000 
+0100
-+++ linux-2.6.12.new/arch/i386/mm/pgtable.c    2005-07-11 16:32:01.478023726 
+0100
-@@ -199,14 +199,14 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
+--- linux-2.6.12/arch/i386/mm/pgtable.c        2005-11-24 21:51:49.000000000 
+0000
++++ linux-2.6.12.new/arch/i386/mm/pgtable.c    2005-11-24 22:06:04.000000000 
+0000
+@@ -199,19 +199,22 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
  {
        unsigned long flags;
  
 -      if (PTRS_PER_PMD == 1)
-+      if (!HAVE_SHARED_KERNEL_PMD)
-               spin_lock_irqsave(&pgd_lock, flags);
- 
-       memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
-                       swapper_pg_dir + USER_PTRS_PER_PGD,
-                       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
- 
+-              spin_lock_irqsave(&pgd_lock, flags);
+-
+-      memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
+-                      swapper_pg_dir + USER_PTRS_PER_PGD,
+-                      (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+-
 -      if (PTRS_PER_PMD > 1)
-+      if (HAVE_SHARED_KERNEL_PMD)
-               return;
- 
-       pgd_list_add(pgd);
-@@ -214,11 +214,13 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
-       memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+-              return;
+-
+-      pgd_list_add(pgd);
+-      spin_unlock_irqrestore(&pgd_lock, flags);
+-      memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
++      if (PTRS_PER_PMD > 1) {
++              if (HAVE_SHARED_KERNEL_PMD)
++                      memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
++                             swapper_pg_dir, sizeof(pgd_t));
++      } else {
++              if (!HAVE_SHARED_KERNEL_PMD)
++                      spin_lock_irqsave(&pgd_lock, flags);
++              memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
++                     swapper_pg_dir + USER_PTRS_PER_PGD,
++                     (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
++              memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
++              if (!HAVE_SHARED_KERNEL_PMD) {
++                      pgd_list_add(pgd);
++                      spin_unlock_irqrestore(&pgd_lock, flags);
++              }
++      }
  }
  
--/* never called when PTRS_PER_PMD > 1 */
- void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused)
+ /* never called when PTRS_PER_PMD > 1 */
+@@ -219,6 +222,9 @@ void pgd_dtor(void *pgd, kmem_cache_t *c
  {
        unsigned long flags; /* can be called from interrupt context */
  
@@ -57,38 +59,32 @@
        spin_lock_irqsave(&pgd_lock, flags);
        pgd_list_del(pgd);
        spin_unlock_irqrestore(&pgd_lock, flags);
-@@ -226,12 +228,29 @@ void pgd_dtor(void *pgd, kmem_cache_t *c
- 
- pgd_t *pgd_alloc(struct mm_struct *mm)
- {
--      int i;
-+      int i = 0;
-       pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
- 
-       if (PTRS_PER_PMD == 1 || !pgd)
-               return pgd;
- 
+@@ -238,6 +244,24 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+                       goto out_oom;
+               set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
+       }
++
 +      if (!HAVE_SHARED_KERNEL_PMD) {
-+              /* alloc and copy kernel pmd */
 +              unsigned long flags;
 +              pgd_t *copy_pgd = pgd_offset_k(PAGE_OFFSET);
 +              pud_t *copy_pud = pud_offset(copy_pgd, PAGE_OFFSET);
 +              pmd_t *copy_pmd = pmd_offset(copy_pud, PAGE_OFFSET);
 +              pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
-+              if (0 == pmd)
++                ++i;
++              if (!pmd)
 +                      goto out_oom;
 +
 +              spin_lock_irqsave(&pgd_lock, flags);
 +              memcpy(pmd, copy_pmd, PAGE_SIZE);
++              set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd)));
++              pgd_list_add(pgd);
 +              spin_unlock_irqrestore(&pgd_lock, flags);
-+              set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd)));
 +      }
 +
-+      /* alloc user pmds */
-       for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
-               pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
-               if (!pmd)
-@@ -252,9 +271,16 @@ void pgd_free(pgd_t *pgd)
+       return pgd;
+ 
+ out_oom:
+@@ -252,9 +276,21 @@ void pgd_free(pgd_t *pgd)
        int i;
  
        /* in the PAE case user pgd entries are overwritten before usage */
@@ -101,7 +97,12 @@
 +                      kmem_cache_free(pmd_cache, pmd);
 +              }
 +              if (!HAVE_SHARED_KERNEL_PMD) {
++                      unsigned long flags;
 +                      pmd_t *pmd = (void 
*)__va(pgd_val(pgd[USER_PTRS_PER_PGD])-1);
++                      spin_lock_irqsave(&pgd_lock, flags);
++                      pgd_list_del(pgd);
++                      spin_unlock_irqrestore(&pgd_lock, flags);
++                      memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
 +                      kmem_cache_free(pmd_cache, pmd);
 +              }
 +      }
diff -r 42474df9b248 -r 28a117c5ea94 tools/examples/Makefile
--- a/tools/examples/Makefile   Fri Nov 25 11:19:03 2005
+++ b/tools/examples/Makefile   Fri Nov 25 11:19:09 2005
@@ -26,9 +26,10 @@
 XEN_SCRIPTS += network-nat vif-nat
 XEN_SCRIPTS += block
 XEN_SCRIPTS += block-enbd block-nbd
+XEN_SCRIPTS += vtpm
 XEN_SCRIPT_DATA = xen-script-common.sh
 XEN_SCRIPT_DATA += xen-hotplug-common.sh xen-network-common.sh vif-common.sh
-XEN_SCRIPT_DATA += block-common.sh
+XEN_SCRIPT_DATA += block-common.sh vtpm-common.sh
 
 XEN_HOTPLUG_DIR = /etc/hotplug
 XEN_HOTPLUG_SCRIPTS = xen-backend.agent
diff -r 42474df9b248 -r 28a117c5ea94 tools/examples/xen-backend.agent
--- a/tools/examples/xen-backend.agent  Fri Nov 25 11:19:03 2005
+++ b/tools/examples/xen-backend.agent  Fri Nov 25 11:19:09 2005
@@ -5,6 +5,9 @@
 case "$XENBUS_TYPE" in
   vbd)
     /etc/xen/scripts/block "$ACTION"
+    ;;
+  vtpm)
+    /etc/xen/scripts/vtpm "$ACTION"
     ;;
   vif)
     [ -n "$script" ] && $script "$ACTION"
diff -r 42474df9b248 -r 28a117c5ea94 tools/examples/xen-backend.rules
--- a/tools/examples/xen-backend.rules  Fri Nov 25 11:19:03 2005
+++ b/tools/examples/xen-backend.rules  Fri Nov 25 11:19:09 2005
@@ -1,4 +1,5 @@
 SUBSYSTEM=="xen-backend", KERNEL=="vbd*", RUN+="/etc/xen/scripts/block 
$env{ACTION}"
+SUBSYSTEM=="xen-backend", KERNEL=="vtpm*", RUN+="/etc/xen/scripts/vtpm 
$env{ACTION}"
 SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="online", RUN+="$env{script} 
online"
 SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="offline", 
RUN+="$env{script} offline"
 SUBSYSTEM=="xen-backend", ACTION=="remove", RUN+="/bin/bash -c 
'/usr/bin/xenstore-rm -t $$(/usr/bin/xenstore-read $env{XENBUS_PATH}/frontend)'"
diff -r 42474df9b248 -r 28a117c5ea94 tools/ioemu/exec.c
--- a/tools/ioemu/exec.c        Fri Nov 25 11:19:03 2005
+++ b/tools/ioemu/exec.c        Fri Nov 25 11:19:09 2005
@@ -262,13 +262,24 @@
                                   unsigned long size,
                                   unsigned long phys_offset)
 {
-        if (mmio_cnt == MAX_MMIO) {
-                fprintf(logfile, "too many mmio regions\n");
-                exit(-1);
-        }
-        mmio[mmio_cnt].io_index = phys_offset;
-        mmio[mmio_cnt].start = start_addr;
-        mmio[mmio_cnt++].size = size;
+    int i;
+
+    for (i = 0; i < mmio_cnt; i++) { 
+        if(mmio[i].start == start_addr) {
+            mmio[i].io_index = phys_offset;
+            mmio[i].size = size;
+            return;
+        }
+    }
+
+    if (mmio_cnt == MAX_MMIO) {
+        fprintf(logfile, "too many mmio regions\n");
+        exit(-1);
+    }
+
+    mmio[mmio_cnt].io_index = phys_offset;
+    mmio[mmio_cnt].start = start_addr;
+    mmio[mmio_cnt++].size = size;
 }
 
 /* mem_read and mem_write are arrays of functions containing the
diff -r 42474df9b248 -r 28a117c5ea94 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Fri Nov 25 11:19:03 2005
+++ b/tools/python/xen/xend/image.py    Fri Nov 25 11:19:09 2005
@@ -293,7 +293,7 @@
                ret.append("-bridge")
                ret.append("%s" % bridge)
             if name == 'vtpm':
-               instance = sxp.child_value(info, 'instance')
+               instance = sxp.child_value(info, 'pref_instance')
                ret.append("-instance")
                ret.append("%s" % instance)
         return ret
diff -r 42474df9b248 -r 28a117c5ea94 tools/python/xen/xend/server/tpmif.py
--- a/tools/python/xen/xend/server/tpmif.py     Fri Nov 25 11:19:03 2005
+++ b/tools/python/xen/xend/server/tpmif.py     Fri Nov 25 11:19:09 2005
@@ -38,10 +38,10 @@
     def getDeviceDetails(self, config):
         """@see DevController.getDeviceDetails"""
 
-        devid = int(sxp.child_value(config, 'instance', '0'))
+        devid = int(sxp.child_value(config, 'pref_instance', '0'))
         log.info("The domain has a TPM with instance %d." % devid)
 
-        back  = { 'instance' : "%i" % devid }
+        back  = { 'pref_instance' : "%i" % devid }
         front = { 'handle' : "%i" % devid }
 
         return (devid, back, front)
diff -r 42474df9b248 -r 28a117c5ea94 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Fri Nov 25 11:19:03 2005
+++ b/tools/python/xen/xm/create.py     Fri Nov 25 11:19:09 2005
@@ -220,11 +220,9 @@
           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('tpmif', val='no|yes',
+          fn=append_value, default=0,
+          use="Make the domain a TPM interface backend.")
 
 gopts.var('disk', val='phy:DEV,VDEV,MODE[,DOM]',
           fn=append_value, default=[],
@@ -273,9 +271,13 @@
 
 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.""")
+          use="""Add a TPM interface. On the backend side use the given
+          instance as virtual TPM instance. The given number is merely the
+          preferred instance number. The hotplug script will determine
+          which instance number will actually be assigned to the domain.
+          The associtation between virtual machine and the TPM instance
+          number can be found in /etc/xen/vtpm.db. Use the backend in the
+          given domain.""")
 
 gopts.var('nics', val="NUM",
           fn=set_int, default=1,
@@ -465,33 +467,19 @@
             if instance == "VTPMD":
                 instance = "0"
             else:
-                try:
-                    if int(instance) == 0:
-                        err('VM config error: vTPM instance must not be 0.')
-                except ValueError:
-                    err('Vm config error: could not parse instance number.')
+                if instance != None:
+                    try:
+                        if int(instance) == 0:
+                            err('VM config error: vTPM instance must not be 
0.')
+                    except ValueError:
+                        err('Vm config error: could not parse instance 
number.')
             backend = d.get('backend')
             config_vtpm = ['vtpm']
             if instance:
-                config_vtpm.append(['instance', instance])
+                config_vtpm.append(['pref_instance', instance])
             if backend:
                 config_vtpm.append(['backend', backend])
             config_devs.append(['device', config_vtpm])
-
-def configure_tpmif(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 configure_vifs(config_devs, vals):
     """Create the config for virtual network interfaces.
@@ -685,22 +673,6 @@
         vtpms.append(d)
     vals.vtpm = vtpms
 
-def preprocess_tpmif(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']:
-                err('Invalid tpmif specifier: ' + vtpm)
-            d[k] = v
-        tpmifs.append(d)
-    vals.tpmif = tpmifs
-
 def preprocess_ip(vals):
     if vals.ip or vals.dhcp != 'off':
         dummy_nfs_server = '1.2.3.4'
@@ -791,7 +763,6 @@
     preprocess_nfs(vals)
     preprocess_vnc(vals)
     preprocess_vtpm(vals)
-    preprocess_tpmif(vals)
          
 def make_domain(opts, config):
     """Create, build and start a domain.
diff -r 42474df9b248 -r 28a117c5ea94 xen/arch/x86/dom0_ops.c
--- a/xen/arch/x86/dom0_ops.c   Fri Nov 25 11:19:03 2005
+++ b/xen/arch/x86/dom0_ops.c   Fri Nov 25 11:19:09 2005
@@ -248,7 +248,7 @@
 
     case DOM0_GETPAGEFRAMEINFO2:
     {
-#define GPF2_BATCH 128
+#define GPF2_BATCH (PAGE_SIZE / sizeof(unsigned long)) 
         int n,j;
         int num = op->u.getpageframeinfo2.num;
         domid_t dom = op->u.getpageframeinfo2.domain;
@@ -285,12 +285,9 @@
                 struct pfn_info *page;
                 unsigned long mfn = l_arr[j];
 
-                if ( unlikely(mfn >= max_page) )
-                    goto e2_err;
-
                 page = &frame_table[mfn];
-  
-                if ( likely(get_page(page, d)) )
+
+                if ( likely(pfn_valid(mfn) && get_page(page, d)) ) 
                 {
                     unsigned long type = 0;
 
@@ -316,10 +313,7 @@
                     put_page(page);
                 }
                 else
-                {
-                e2_err:
                     l_arr[j] |= XTAB;
-                }
 
             }
 
@@ -329,7 +323,7 @@
                 break;
             }
 
-            n += j;
+            n += k;
         }
 
         free_xenheap_page(l_arr);
diff -r 42474df9b248 -r 28a117c5ea94 xen/common/acm_ops.c
--- a/xen/common/acm_ops.c      Fri Nov 25 11:19:03 2005
+++ b/xen/common/acm_ops.c      Fri Nov 25 11:19:09 2005
@@ -49,15 +49,11 @@
 
 int acm_authorize_acm_ops(struct domain *d, enum acm_operation pops)
 {
-    /* all policy management functions are restricted to privileged domains,
-     * soon we will introduce finer-grained privileges for policy operations
-     */
+    /* currently, policy management functions are restricted to privileged 
domains */
     if (!IS_PRIV(d))
-    {
-        printk("%s: ACM management authorization denied ERROR!\n", __func__);
-        return ACM_ACCESS_DENIED;
-    }
-    return ACM_ACCESS_PERMITTED;
+        return -EPERM;
+
+    return 0;
 }
 
 long do_acm_op(struct acm_op * u_acm_op)
@@ -65,10 +61,8 @@
     long ret = 0;
     struct acm_op curop, *op = &curop;
 
-    /* check here policy decision for policy commands */
-    /* for now allow DOM0 only, later indepedently    */
     if (acm_authorize_acm_ops(current->domain, POLICY))
-        return -EACCES;
+        return -EPERM;
 
     if (copy_from_user(op, u_acm_op, sizeof(*op)))
         return -EFAULT;
@@ -80,43 +74,32 @@
     {
     case ACM_SETPOLICY:
     {
-        if (acm_authorize_acm_ops(current->domain, SETPOLICY))
-            return -EACCES;
-        printkd("%s: setting policy.\n", __func__);
-        ret = acm_set_policy(op->u.setpolicy.pushcache,
-                             op->u.setpolicy.pushcache_size, 1);
-        if (ret == ACM_OK)
-            ret = 0;
-        else
-            ret = -ESRCH;
+        ret = acm_authorize_acm_ops(current->domain, SETPOLICY);
+        if (!ret)
+            ret = acm_set_policy(op->u.setpolicy.pushcache,
+                                 op->u.setpolicy.pushcache_size, 1);
     }
     break;
 
     case ACM_GETPOLICY:
     {
-        if (acm_authorize_acm_ops(current->domain, GETPOLICY))
-            return -EACCES;
-        printkd("%s: getting policy.\n", __func__);
-        ret = acm_get_policy(op->u.getpolicy.pullcache,
-                             op->u.getpolicy.pullcache_size);
-        if (ret == ACM_OK)
-            ret = 0;
-        else
-            ret = -ESRCH;
+        ret = acm_authorize_acm_ops(current->domain, GETPOLICY);
+        if (!ret)
+            ret = acm_get_policy(op->u.getpolicy.pullcache,
+                                 op->u.getpolicy.pullcache_size);
+        if (!ret)
+            copy_to_user(u_acm_op, op, sizeof(*op));
     }
     break;
 
     case ACM_DUMPSTATS:
     {
-        if (acm_authorize_acm_ops(current->domain, DUMPSTATS))
-            return -EACCES;
-        printkd("%s: dumping statistics.\n", __func__);
-        ret = acm_dump_statistics(op->u.dumpstats.pullcache,
-                                  op->u.dumpstats.pullcache_size);
-        if (ret == ACM_OK)
-            ret = 0;
-        else
-            ret = -ESRCH;
+        ret = acm_authorize_acm_ops(current->domain, DUMPSTATS);
+        if (!ret)
+            ret = acm_dump_statistics(op->u.dumpstats.pullcache,
+                                      op->u.dumpstats.pullcache_size);
+        if (!ret)
+            copy_to_user(u_acm_op, op, sizeof(*op));
     }
     break;
 
@@ -124,31 +107,39 @@
     {
         ssidref_t ssidref;
 
-        if (acm_authorize_acm_ops(current->domain, GETSSID))
-            return -EACCES;
-        printkd("%s: getting SSID.\n", __func__);
+        ret = acm_authorize_acm_ops(current->domain, GETSSID);
+        if (ret)
+            break;
+
         if (op->u.getssid.get_ssid_by == SSIDREF)
             ssidref = op->u.getssid.id.ssidref;
-        else if (op->u.getssid.get_ssid_by == DOMAINID) {
+        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 */
-            if (subj->ssid == NULL) {
+            {
+                ret = -ESRCH; /* domain not found */
+                break;
+            }
+            if (subj->ssid == NULL)
+            {
                 put_domain(subj);
-                return -ESRCH;
+                ret = -ESRCH;
+                break;
             }
             ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
             put_domain(subj);
-        } else
-            return -ESRCH;
-
+        }
+        else
+        {
+            ret = -ESRCH;
+            break;
+        }
         ret = acm_get_ssid(ssidref,
                            op->u.getssid.ssidbuf,
                            op->u.getssid.ssidbuf_size);
-        if (ret == ACM_OK)
-            ret = 0;
-        else
-            ret = -ESRCH;
+        if (!ret)
+            copy_to_user(u_acm_op, op, sizeof(*op));
     }
     break;
 
@@ -156,51 +147,75 @@
     {
         ssidref_t ssidref1, ssidref2;
 
-        if (acm_authorize_acm_ops(current->domain, GETDECISION)) {
-            ret = -EACCES;
-            goto out;
-        }
-        printkd("%s: getting access control decision.\n", __func__);
-        if (op->u.getdecision.get_decision_by1 == SSIDREF) {
+        ret = acm_authorize_acm_ops(current->domain, GETDECISION);
+        if (ret)
+            break;
+
+        if (op->u.getdecision.get_decision_by1 == SSIDREF)
             ssidref1 = op->u.getdecision.id1.ssidref;
-        }
-        else if (op->u.getdecision.get_decision_by1 == DOMAINID) {
+        else if (op->u.getdecision.get_decision_by1 == DOMAINID)
+        {
             struct domain *subj = 
find_domain_by_id(op->u.getdecision.id1.domainid);
-            if (!subj) {
+            if (!subj)
+            {
                 ret = -ESRCH; /* domain not found */
-                goto out;
-            }
-            if (subj->ssid == NULL) {
+                break;
+            }
+            if (subj->ssid == NULL)
+            {
                 put_domain(subj);
                 ret = -ESRCH;
-                goto out;
+                break;
             }
             ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
             put_domain(subj);
-        } else {
-            ret = -ESRCH;
-            goto out;
-        }
-        if (op->u.getdecision.get_decision_by2 == SSIDREF) {
+        }
+        else
+        {
+            ret = -ESRCH;
+            break;
+        }
+        if (op->u.getdecision.get_decision_by2 == SSIDREF)
             ssidref2 = op->u.getdecision.id2.ssidref;
-        }
-        else if (op->u.getdecision.get_decision_by2 == DOMAINID) {
+        else if (op->u.getdecision.get_decision_by2 == DOMAINID)
+        {
             struct domain *subj = 
find_domain_by_id(op->u.getdecision.id2.domainid);
-            if (!subj) {
+            if (!subj)
+            {
                 ret = -ESRCH; /* domain not found */
-                goto out;
-            }
-            if (subj->ssid == NULL) {
+                break;;
+            }
+            if (subj->ssid == NULL)
+            {
                 put_domain(subj);
-                return -ESRCH;
+                ret = -ESRCH;
+                break;
             }
             ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
             put_domain(subj);
-        } else {
-            ret = -ESRCH;
-            goto out;
+        }
+        else
+        {
+            ret = -ESRCH;
+            break;
         }
         ret = acm_get_decision(ssidref1, ssidref2, op->u.getdecision.hook);
+
+        if (ret == ACM_ACCESS_PERMITTED)
+        {
+            op->u.getdecision.acm_decision = ACM_ACCESS_PERMITTED;
+            ret = 0;
+        }
+        else if  (ret == ACM_ACCESS_DENIED)
+        {
+            op->u.getdecision.acm_decision = ACM_ACCESS_DENIED;
+            ret = 0;
+        }
+        else
+            ret = -ESRCH;
+
+        if (!ret)
+            copy_to_user(u_acm_op, op, sizeof(*op));
     }
     break;
 
@@ -208,20 +223,6 @@
         ret = -ESRCH;
     }
 
- out:
-    if (ret == ACM_ACCESS_PERMITTED) {
-        op->u.getdecision.acm_decision = ACM_ACCESS_PERMITTED;
-        ret = 0;
-    } else if  (ret == ACM_ACCESS_DENIED) {
-        op->u.getdecision.acm_decision = ACM_ACCESS_DENIED;
-        ret = 0;
-    } else {
-        op->u.getdecision.acm_decision = ACM_ACCESS_DENIED;
-        if (ret > 0)
-            ret = -ret;
-    }
-    /* copy decision back to user space */
-    copy_to_user(u_acm_op, op, sizeof(*op));
     return ret;
 }
 
diff -r 42474df9b248 -r 28a117c5ea94 tools/examples/vtpm
--- /dev/null   Fri Nov 25 11:19:03 2005
+++ b/tools/examples/vtpm       Fri Nov 25 11:19:09 2005
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+dir=$(dirname "$0")
+. "$dir/vtpm-common.sh"
+
+
+case "$command" in
+    online | offline)
+        exit 0
+        ;;
+esac
+
+case "$command" in
+  add)
+    vtpm_create_instance
+  ;;
+  remove)
+    vtpm_remove_instance
+  ;;
+esac
+
+log debug "Successful vTPM operation '$command'."
+success
diff -r 42474df9b248 -r 28a117c5ea94 tools/examples/vtpm-common.sh
--- /dev/null   Fri Nov 25 11:19:03 2005
+++ b/tools/examples/vtpm-common.sh     Fri Nov 25 11:19:09 2005
@@ -0,0 +1,281 @@
+#
+# Copyright (c) 2005 IBM Corporation
+# Copyright (c) 2005 XenSource Ltd.
+#
+# 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
+#
+
+dir=$(dirname "$0")
+. "$dir/xen-hotplug-common.sh"
+
+findCommand "$@"
+if [ "$command" != "online" ]  &&
+   [ "$command" != "offline" ] &&
+   [ "$command" != "add" ]     &&
+   [ "$command" != "remove" ]
+then
+       log err "Invalid command: $command"
+       exit 1
+fi
+
+
+XENBUS_PATH="${XENBUS_PATH:?}"
+
+
+VTPMDB="/etc/xen/vtpm.db"
+
+#In the vtpm-impl file some commands should be defined:
+#      vtpm_create, vtpm_setup, vtpm_reset, etc. (see below)
+#This should be indicated by setting VTPM_IMPL_DEFINED.
+if [ -r "$dir/vtpm-impl" ]; then
+       . "$dir/vtpm-impl"
+fi
+
+if [ -z "$VTPM_IMPL_DEFINED" ]; then
+       function vtpm_create () {
+               true
+       }
+       function vtpm_setup() {
+               true
+       }
+       function vtpm_reset() {
+               true
+       }
+       function vtpm_suspend() {
+               true
+       }
+       function vtpm_resume() {
+               true
+       }
+fi
+
+#Find the instance number for the vtpm given the name of the domain
+# Parameters
+# - vmname : the name of the vm
+# Return value
+#  Returns '0' if instance number could not be found, otherwise
+#  it returns the instance number in the variable 'instance'
+function find_instance () {
+       local vmname=$1
+       local ret=0
+       instance=`cat $VTPMDB |                    \
+                 awk -vvmname=$vmname             \
+                 '{                               \
+                    if ( 1 != index($1,"#")) {    \
+                      if ( $1 == vmname ) {       \
+                        print $2;                 \
+                        exit;                     \
+                      }                           \
+                    }                             \
+                  }'`
+       if [ "$instance" != "" ]; then
+               ret=1
+       fi
+       return $ret
+}
+
+
+# Check whether a particular instance number is still available
+# returns '1' if it is available
+function is_free_instancenum () {
+       local instance=$1
+       local avail=1
+
+       #Allowed instance number range: 1-255
+       if [ $instance -eq 0 -o $instance -gt 255 ]; then
+               avail=0
+       else
+               instances=`cat $VTPMDB |                 \
+                          gawk                          \
+                          '{                            \
+                              if (1 != index($1,"#")) { \
+                                printf("%s ",$2);       \
+                              }                         \
+                           }'`
+               for i in $instances; do
+                       if [ $i -eq $instance ]; then
+                               avail=0
+                               break
+                       fi
+               done
+       fi
+       return $avail
+}
+
+
+# Get an available instance number given the database
+# Returns an unused instance number
+function get_free_instancenum () {
+       local ctr
+       local instances
+       local don
+       instances=`cat $VTPMDB |                 \
+                  gawk                          \
+                  '{                            \
+                      if (1 != index($1,"#")) { \
+                        printf("%s ",$2);       \
+                      }                         \
+                   }'`
+       ctr=1
+       don=0
+       while [ $don -eq 0 ]; do
+               local found
+               found=0
+               for i in $instances; do
+                       if [ $i -eq $ctr ]; then
+                               found=1;
+                               break;
+                       fi
+               done
+
+               if [ $found -eq 0 ]; then
+                       don=1
+                       break
+               fi
+               let ctr=ctr+1
+       done
+       let instance=$ctr
+}
+
+
+# Add a domain name and instance number to the DB file
+function add_instance () {
+       local vmname=$1
+       local inst=$2
+
+       if [ ! -f $VTPMDB ]; then
+               echo "#Database for VM to vTPM association" > $VTPMDB
+               echo "#1st column: domain name" >> $VTPMDB
+               echo "#2nd column: TPM instance number" >> $VTPMDB
+       fi
+       validate_entry $vmname $inst
+       if [ $? -eq 0 ]; then
+               echo "$vmname $inst" >> $VTPMDB
+       fi
+}
+
+
+#Validate whether an entry is the same as passed to this
+#function
+function validate_entry () {
+       local rc=0
+       local vmname=$1
+       local inst=$2
+       local res
+       res=`cat $VTPMDB |             \
+            gawk -vvmname=$vmname     \
+                 -vinst=$inst         \
+            '{                        \
+                if ( 1 == index($1,"#")) {\
+                } else                \
+                if ( $1 == vmname &&  \
+                     $2 == inst) {    \
+                   printf("1");       \
+                   exit;              \
+                } else                \
+                if ( $1 == vmname ||  \
+                     $2 == inst) {    \
+                   printf("2");       \
+                   exit;              \
+                }                     \
+            }'`
+
+       if [ "$res" == "1" ]; then
+               let rc=1
+       elif [ "$res" == "2" ]; then
+               let rc=2
+       fi
+       return $rc
+}
+
+
+#Remove an entry from the vTPM database given its domain name
+function remove_entry () {
+       local vmname=$1
+       local VTPMDB_TMP="$VTPMDB".tmp
+       `cat $VTPMDB |             \
+        gawk -vvmname=$vmname     \
+        '{                        \
+           if ( $1 != vmname ) {  \
+             print $0;            \
+           }                      \
+        '} > $VTPMDB_TMP`
+       if [ -e $VTPMDB_TMP ]; then
+               mv -f $VTPMDB_TMP $VTPMDB
+       else
+               log err "Error creating temporary file '$VTPMDB_TMP'."
+       fi
+}
+
+
+#Create a vTPM instance
+# If no entry in the TPM database is found, the instance is
+# created and an entry added to the database.
+function vtpm_create_instance () {
+       local domname=$(xenstore_read "$XENBUS_PATH"/domain)
+       local res
+       set +e
+       find_instance $domname
+       res=$?
+       if [ $res -eq 0 ]; then
+               #Try to give the preferred instance to the domain
+               instance=$(xenstore_read "$XENBUS_PATH"/pref_instance)
+               if [ "$instance" != "" ]; then
+                       is_free_instancenum $instance
+                       res=$?
+                       if [ $res -eq 0 ]; then
+                               get_free_instancenum
+                       fi
+               else
+                       get_free_instancenum
+               fi
+               add_instance $domname $instance
+               if [ "$REASON" == "create" ]; then
+                       vtpm_create $instance
+               elif [ "$REASON" == "hibernate" ]; then
+                       vtpm_resume $instance $domname
+               else
+                       #default case for 'now'
+                       vtpm_create $instance
+               fi
+       fi
+       if [ "$REASON" == "create" ]; then
+               vtpm_reset $instance
+       elif [ "$REASON" == "hibernate" ]; then
+               vtpm_setup $instance
+       else
+               #default case for 'now'
+               vtpm_reset $instance
+       fi
+       xenstore_write $XENBUS_PATH/instance $instance
+       set -e
+}
+
+
+#Remove an instance
+function vtpm_remove_instance () {
+       local domname=$(xenstore_read "$XENBUS_PATH"/domain)
+       set +e
+       find_instance $domname
+       res=$?
+       if [ $res -eq 0 ]; then
+               #Something is really wrong with the DB
+               log err "vTPM DB file $VTPMDB has no entry for '$domname'"
+       else
+               if [ "$REASON" == "hibernate" ]; then
+                       vtpm_suspend $instance
+               fi
+       fi
+       set -e
+}

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

<Prev in Thread] Current Thread [Next in Thread>