ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c @ 6989:7a45b8ccef01

Some cleanup in tpm-related files.

Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Sep 21 10:13:11 2005 +0000 (2005-09-21)
parents 3233e7ecfa9f
children 55fc0ecc19c3
line source
1 /******************************************************************************
2 * drivers/xen/tpmback/interface.c
3 *
4 * Vritual TPM interface management.
5 *
6 * Copyright (c) 2005, IBM Corporation
7 *
8 * Author: Stefan Berger, stefanb@us.ibm.com
9 *
10 * This code has been derived from drivers/xen/netback/interface.c
11 * Copyright (c) 2004, Keir Fraser
12 */
14 #include "common.h"
15 #include <asm-xen/balloon.h>
17 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
19 #define TPMIF_HASHSZ (2 << 5)
20 #define TPMIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(TPMIF_HASHSZ-1))
22 static kmem_cache_t *tpmif_cachep;
23 int num_frontends = 0;
25 LIST_HEAD(tpmif_list);
27 tpmif_t *
28 alloc_tpmif(domid_t domid, long int instance)
29 {
30 struct page *page;
31 tpmif_t *tpmif;
33 tpmif = kmem_cache_alloc(tpmif_cachep, GFP_KERNEL);
34 if (!tpmif)
35 return ERR_PTR(-ENOMEM);
37 memset(tpmif, 0, sizeof (*tpmif));
38 tpmif->domid = domid;
39 tpmif->status = DISCONNECTED;
40 tpmif->tpm_instance = instance;
41 atomic_set(&tpmif->refcnt, 1);
43 page = balloon_alloc_empty_page_range(TPMIF_TX_RING_SIZE);
44 BUG_ON(page == NULL);
45 tpmif->mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
47 list_add(&tpmif->tpmif_list, &tpmif_list);
48 num_frontends++;
50 return tpmif;
51 }
53 void
54 free_tpmif(tpmif_t * tpmif)
55 {
56 num_frontends--;
57 list_del(&tpmif->tpmif_list);
58 kmem_cache_free(tpmif_cachep, tpmif);
59 }
61 tpmif_t *
62 tpmif_find(domid_t domid, long int instance)
63 {
64 tpmif_t *tpmif;
66 list_for_each_entry(tpmif, &tpmif_list, tpmif_list) {
67 if (tpmif->tpm_instance == instance) {
68 if (tpmif->domid == domid) {
69 tpmif_get(tpmif);
70 return tpmif;
71 } else {
72 return NULL;
73 }
74 }
75 }
77 return alloc_tpmif(domid, instance);
78 }
80 static int
81 map_frontend_page(tpmif_t * tpmif, unsigned long localaddr,
82 unsigned long shared_page)
83 {
84 struct gnttab_map_grant_ref op = {
85 .host_addr = localaddr,
86 .flags = GNTMAP_host_map,
87 .ref = shared_page,
88 .dom = tpmif->domid,
89 };
91 BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
93 if (op.handle < 0) {
94 DPRINTK(" Grant table operation failure !\n");
95 return op.handle;
96 }
98 tpmif->shmem_ref = shared_page;
99 tpmif->shmem_handle = op.handle;
100 tpmif->shmem_vaddr = localaddr;
101 return 0;
102 }
104 static void
105 unmap_frontend_page(tpmif_t * tpmif)
106 {
107 struct gnttab_unmap_grant_ref op;
109 op.host_addr = tpmif->shmem_vaddr;
110 op.handle = tpmif->shmem_handle;
111 op.dev_bus_addr = 0;
113 BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
114 }
116 int
117 tpmif_map(tpmif_t * tpmif, unsigned long shared_page, unsigned int evtchn)
118 {
119 struct vm_struct *vma;
120 evtchn_op_t op = {.cmd = EVTCHNOP_bind_interdomain };
121 int err;
123 BUG_ON(tpmif->remote_evtchn);
125 if ((vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL)
126 return -ENOMEM;
128 err = map_frontend_page(tpmif, VMALLOC_VMADDR(vma->addr), shared_page);
129 if (err) {
130 vfree(vma->addr);
131 return err;
132 }
134 op.u.bind_interdomain.dom1 = DOMID_SELF;
135 op.u.bind_interdomain.dom2 = tpmif->domid;
136 op.u.bind_interdomain.port1 = 0;
137 op.u.bind_interdomain.port2 = evtchn;
138 err = HYPERVISOR_event_channel_op(&op);
139 if (err) {
140 unmap_frontend_page(tpmif);
141 vfree(vma->addr);
142 return err;
143 }
145 tpmif->evtchn = op.u.bind_interdomain.port1;
146 tpmif->remote_evtchn = evtchn;
148 tpmif->tx = (tpmif_tx_interface_t *) vma->addr;
150 bind_evtchn_to_irqhandler(tpmif->evtchn,
151 tpmif_be_int, 0, "tpmif-backend", tpmif);
152 tpmif->status = CONNECTED;
153 tpmif->shmem_ref = shared_page;
154 tpmif->active = 1;
156 return 0;
157 }
159 static void
160 __tpmif_disconnect_complete(void *arg)
161 {
162 evtchn_op_t op = {.cmd = EVTCHNOP_close };
163 tpmif_t *tpmif = (tpmif_t *) arg;
165 op.u.close.port = tpmif->evtchn;
166 op.u.close.dom = DOMID_SELF;
167 HYPERVISOR_event_channel_op(&op);
168 op.u.close.port = tpmif->remote_evtchn;
169 op.u.close.dom = tpmif->domid;
170 HYPERVISOR_event_channel_op(&op);
172 if (tpmif->evtchn)
173 unbind_evtchn_from_irqhandler(tpmif->evtchn, tpmif);
175 if (tpmif->tx) {
176 unmap_frontend_page(tpmif);
177 vfree(tpmif->tx);
178 }
180 free_tpmif(tpmif);
181 }
183 void
184 tpmif_disconnect_complete(tpmif_t * tpmif)
185 {
186 INIT_WORK(&tpmif->work, __tpmif_disconnect_complete, (void *)tpmif);
187 schedule_work(&tpmif->work);
188 }
190 void __init
191 tpmif_interface_init(void)
192 {
193 tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof (tpmif_t),
194 0, 0, NULL, NULL);
195 }