mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
Enable migration of a domain to the local machine - some timing
issues needed to be resolved by executing certain code early/later Restore the physical to machine array such that balloon-allocated pages can be deallocated. Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
This commit is contained in:
1 parent
d4184d7e40
commit
cfc4a77198
4 files changed
+34
-39
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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 domid, long int instance)
|
||||
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 long shared_page, unsigned int evtchn)
|
||||
.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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@ static int tpmback_remove(struct xenbus_device *dev)
|
||||
{
|
||||
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 xenbus_watch *watch,
|
||||
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 xenbus_device *dev,
|
||||
*/
|
||||
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_info *be)
|
||||
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) {
|
||||
|
||||