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

[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


 


Rackspace

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