1 /*****************************************************************************
2 * drivers/xen/tpmback/interface.c
4 * Vritual TPM interface management.
6 * Copyright (c) 2005, IBM Corporation
8 * Author: Stefan Berger, stefanb@us.ibm.com
10 * This code has been derived from drivers/xen/netback/interface.c
11 * Copyright (c) 2004, Keir Fraser
15 #include <xen/balloon.h>
16 #include <xen/gnttab.h>
18 static kmem_cache_t *tpmif_cachep;
19 int num_frontends = 0;
21 LIST_HEAD(tpmif_list);
23 static tpmif_t *alloc_tpmif(domid_t domid, struct backend_info *bi)
27 tpmif = kmem_cache_alloc(tpmif_cachep, GFP_KERNEL);
29 return ERR_PTR(-ENOMEM);
31 memset(tpmif, 0, sizeof (*tpmif));
33 tpmif->status = DISCONNECTED;
35 snprintf(tpmif->devname, sizeof(tpmif->devname), "tpmif%d", domid);
36 atomic_set(&tpmif->refcnt, 1);
38 tpmif->pagerange = balloon_alloc_empty_page_range(TPMIF_TX_RING_SIZE);
39 BUG_ON(tpmif->pagerange == NULL);
40 tpmif->mmap_vstart = (unsigned long)pfn_to_kaddr(
41 page_to_pfn(tpmif->pagerange));
43 list_add(&tpmif->tpmif_list, &tpmif_list);
49 static void free_tpmif(tpmif_t * tpmif)
52 list_del(&tpmif->tpmif_list);
53 balloon_dealloc_empty_page_range(tpmif->pagerange, TPMIF_TX_RING_SIZE);
54 kmem_cache_free(tpmif_cachep, tpmif);
57 tpmif_t *tpmif_find(domid_t domid, struct backend_info *bi)
61 list_for_each_entry(tpmif, &tpmif_list, tpmif_list) {
62 if (tpmif->bi == bi) {
63 if (tpmif->domid == domid) {
67 return ERR_PTR(-EEXIST);
72 return alloc_tpmif(domid, bi);
75 static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
78 struct gnttab_map_grant_ref op;
80 gnttab_set_map_op(&op, (unsigned long)tpmif->tx_area->addr,
81 GNTMAP_host_map, shared_page, tpmif->domid);
83 lock_vm_area(tpmif->tx_area);
84 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
85 unlock_vm_area(tpmif->tx_area);
89 DPRINTK(" Grant table operation failure !\n");
93 tpmif->shmem_ref = shared_page;
94 tpmif->shmem_handle = op.handle;
99 static void unmap_frontend_page(tpmif_t *tpmif)
101 struct gnttab_unmap_grant_ref op;
104 gnttab_set_unmap_op(&op, (unsigned long)tpmif->tx_area->addr,
105 GNTMAP_host_map, tpmif->shmem_handle);
107 lock_vm_area(tpmif->tx_area);
108 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
109 unlock_vm_area(tpmif->tx_area);
113 int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn)
116 struct evtchn_bind_interdomain bind_interdomain;
122 if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL)
125 err = map_frontend_page(tpmif, shared_page);
127 free_vm_area(tpmif->tx_area);
132 bind_interdomain.remote_dom = tpmif->domid;
133 bind_interdomain.remote_port = evtchn;
135 err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
138 unmap_frontend_page(tpmif);
139 free_vm_area(tpmif->tx_area);
143 tpmif->evtchn = bind_interdomain.local_port;
145 tpmif->tx = (tpmif_tx_interface_t *)tpmif->tx_area->addr;
147 tpmif->irq = bind_evtchn_to_irqhandler(
148 tpmif->evtchn, tpmif_be_int, 0, tpmif->devname, tpmif);
149 tpmif->shmem_ref = shared_page;
155 void tpmif_disconnect_complete(tpmif_t *tpmif)
158 unbind_from_irqhandler(tpmif->irq, tpmif);
161 unmap_frontend_page(tpmif);
162 free_vm_area(tpmif->tx_area);
168 void __init tpmif_interface_init(void)
170 tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof (tpmif_t),
174 void __exit tpmif_interface_exit(void)
176 kmem_cache_destroy(tpmif_cachep);