Index: xen/xen-unstable.hg/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c =================================================================== --- xen.orig/xen-unstable.hg/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c +++ xen/xen-unstable.hg/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c @@ -22,7 +22,6 @@ LIST_HEAD(tpmif_list); static tpmif_t *alloc_tpmif(domid_t domid, long int instance) { - struct page *page; tpmif_t *tpmif; tpmif = kmem_cache_alloc(tpmif_cachep, GFP_KERNEL); @@ -35,9 +34,10 @@ static tpmif_t *alloc_tpmif(domid_t domi tpmif->tpm_instance = instance; atomic_set(&tpmif->refcnt, 1); - page = balloon_alloc_empty_page_range(TPMIF_TX_RING_SIZE); - BUG_ON(page == NULL); - tpmif->mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); + tpmif->pagerange = balloon_alloc_empty_page_range(TPMIF_TX_RING_SIZE); + BUG_ON(tpmif->pagerange == NULL); + tpmif->mmap_vstart = (unsigned long)pfn_to_kaddr( + page_to_pfn(tpmif->pagerange)); list_add(&tpmif->tpmif_list, &tpmif_list); num_frontends++; @@ -49,6 +49,7 @@ static void free_tpmif(tpmif_t * tpmif) { num_frontends--; list_del(&tpmif->tpmif_list); + balloon_dealloc_empty_page_range(tpmif->pagerange, TPMIF_TX_RING_SIZE); kmem_cache_free(tpmif_cachep, tpmif); } @@ -115,11 +116,11 @@ int tpmif_map(tpmif_t *tpmif, unsigned l .cmd = EVTCHNOP_bind_interdomain, .u.bind_interdomain.remote_dom = tpmif->domid, .u.bind_interdomain.remote_port = evtchn, - }; + }; - if (tpmif->irq) { - return 0; - } + if (tpmif->irq) { + return 0; + } if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL) return -ENOMEM; Index: xen/xen-unstable.hg/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c =================================================================== --- xen.orig/xen-unstable.hg/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c +++ xen/xen-unstable.hg/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c @@ -49,6 +49,8 @@ static int tpmback_remove(struct xenbus_ { struct backend_info *be = dev->data; + if (!be) return 0; + if (be->backend_watch.node) { unregister_xenbus_watch(&be->backend_watch); kfree(be->backend_watch.node); @@ -119,37 +121,9 @@ static void backend_changed(struct xenbu return; } - if (be->is_instance_set != 0 && 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 == 0) { - 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 = 1; - - /* - * 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); - } } } @@ -186,6 +160,7 @@ static void frontend_changed(struct xenb */ tpmif_vtpm_close(be->instance); device_unregister(&be->dev->dev); + tpmback_remove(dev); break; case XenbusStateUnknown: @@ -279,6 +254,18 @@ static int connect_ring(struct backend_i dev->otherend); return err; } + + if (!be->tpmif) { + be->tpmif = tpmif_find(dev->otherend_id, + be->instance); + if (IS_ERR(be->tpmif)) { + err = PTR_ERR(be->tpmif); + be->tpmif = NULL; + xenbus_dev_fatal(dev,err,"creating vtpm interface"); + return err; + } + } + if (be->tpmif != NULL) { err = tpmif_map(be->tpmif, ring_ref, evtchn); if (err) { Index: xen/xen-unstable.hg/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h =================================================================== --- xen.orig/xen-unstable.hg/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h +++ xen/xen-unstable.hg/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h @@ -49,6 +49,7 @@ typedef struct tpmif_st { grant_handle_t shmem_handle; grant_ref_t shmem_ref; + struct page *pagerange; } tpmif_t; void tpmif_disconnect_complete(tpmif_t * tpmif); Index: xen/xen-unstable.hg/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c =================================================================== --- xen.orig/xen-unstable.hg/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c +++ xen/xen-unstable.hg/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c @@ -271,6 +271,7 @@ int _packet_write(struct packet *pak, struct gnttab_map_grant_ref map_op; struct gnttab_unmap_grant_ref unmap_op; tpmif_tx_request_t *tx; + unsigned long pfn, mfn, mfn_orig; tx = &tpmif->tx->ring[i].req; @@ -293,9 +294,12 @@ int _packet_write(struct packet *pak, DPRINTK(" Grant table operation failure !\n"); return 0; } - set_phys_to_machine(__pa(MMAP_VADDR(tpmif, i)) >> PAGE_SHIFT, - FOREIGN_FRAME(map_op. - dev_bus_addr >> PAGE_SHIFT)); + + pfn = __pa(MMAP_VADDR(tpmif, i)) >> PAGE_SHIFT; + mfn = FOREIGN_FRAME(map_op.dev_bus_addr >> PAGE_SHIFT); + mfn_orig = phys_to_machine_mapping[pfn]; + + set_phys_to_machine(pfn, mfn); tocopy = MIN(size - offset, PAGE_SIZE); @@ -307,6 +311,8 @@ int _packet_write(struct packet *pak, } tx->size = tocopy; + set_phys_to_machine(pfn, mfn_orig); + gnttab_set_unmap_op(&unmap_op, MMAP_VADDR(tpmif, i), GNTMAP_host_map, handle);