1
2
3
4
5
6
7
8
9
10#include <linux/errno.h>
11#include <linux/err.h>
12#include <linux/interrupt.h>
13#include <linux/freezer.h>
14#include <xen/xen.h>
15#include <xen/events.h>
16#include <xen/interface/io/tpmif.h>
17#include <xen/grant_table.h>
18#include <xen/xenbus.h>
19#include <xen/page.h>
20#include "tpm.h"
21#include <xen/platform_pci.h>
22
23struct tpm_private {
24 struct tpm_chip *chip;
25 struct xenbus_device *dev;
26
27 struct vtpm_shared_page *shr;
28
29 unsigned int evtchn;
30 int ring_ref;
31 domid_t backend_id;
32 int irq;
33 wait_queue_head_t read_queue;
34};
35
36enum status_bits {
37 VTPM_STATUS_RUNNING = 0x1,
38 VTPM_STATUS_IDLE = 0x2,
39 VTPM_STATUS_RESULT = 0x4,
40 VTPM_STATUS_CANCELED = 0x8,
41};
42
43static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
44 bool check_cancel, bool *canceled)
45{
46 u8 status = chip->ops->status(chip);
47
48 *canceled = false;
49 if ((status & mask) == mask)
50 return true;
51 if (check_cancel && chip->ops->req_canceled(chip, status)) {
52 *canceled = true;
53 return true;
54 }
55 return false;
56}
57
58static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
59 unsigned long timeout, wait_queue_head_t *queue,
60 bool check_cancel)
61{
62 unsigned long stop;
63 long rc;
64 u8 status;
65 bool canceled = false;
66
67
68 status = chip->ops->status(chip);
69 if ((status & mask) == mask)
70 return 0;
71
72 stop = jiffies + timeout;
73
74 if (chip->flags & TPM_CHIP_FLAG_IRQ) {
75again:
76 timeout = stop - jiffies;
77 if ((long)timeout <= 0)
78 return -ETIME;
79 rc = wait_event_interruptible_timeout(*queue,
80 wait_for_tpm_stat_cond(chip, mask, check_cancel,
81 &canceled),
82 timeout);
83 if (rc > 0) {
84 if (canceled)
85 return -ECANCELED;
86 return 0;
87 }
88 if (rc == -ERESTARTSYS && freezing(current)) {
89 clear_thread_flag(TIF_SIGPENDING);
90 goto again;
91 }
92 } else {
93 do {
94 tpm_msleep(TPM_TIMEOUT);
95 status = chip->ops->status(chip);
96 if ((status & mask) == mask)
97 return 0;
98 } while (time_before(jiffies, stop));
99 }
100 return -ETIME;
101}
102
103static u8 vtpm_status(struct tpm_chip *chip)
104{
105 struct tpm_private *priv = dev_get_drvdata(&chip->dev);
106 switch (priv->shr->state) {
107 case VTPM_STATE_IDLE:
108 return VTPM_STATUS_IDLE | VTPM_STATUS_CANCELED;
109 case VTPM_STATE_FINISH:
110 return VTPM_STATUS_IDLE | VTPM_STATUS_RESULT;
111 case VTPM_STATE_SUBMIT:
112 case VTPM_STATE_CANCEL:
113 return VTPM_STATUS_RUNNING;
114 default:
115 return 0;
116 }
117}
118
119static bool vtpm_req_canceled(struct tpm_chip *chip, u8 status)
120{
121 return status & VTPM_STATUS_CANCELED;
122}
123
124static void vtpm_cancel(struct tpm_chip *chip)
125{
126 struct tpm_private *priv = dev_get_drvdata(&chip->dev);
127 priv->shr->state = VTPM_STATE_CANCEL;
128 wmb();
129 notify_remote_via_evtchn(priv->evtchn);
130}
131
132static unsigned int shr_data_offset(struct vtpm_shared_page *shr)
133{
134 return sizeof(*shr) + sizeof(u32) * shr->nr_extra_pages;
135}
136
137static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
138{
139 struct tpm_private *priv = dev_get_drvdata(&chip->dev);
140 struct vtpm_shared_page *shr = priv->shr;
141 unsigned int offset = shr_data_offset(shr);
142
143 u32 ordinal;
144 unsigned long duration;
145
146 if (offset > PAGE_SIZE)
147 return -EINVAL;
148
149 if (offset + count > PAGE_SIZE)
150 return -EINVAL;
151
152
153 if (wait_for_tpm_stat(chip, VTPM_STATUS_IDLE, chip->timeout_c,
154 &priv->read_queue, true) < 0) {
155 vtpm_cancel(chip);
156 return -ETIME;
157 }
158
159 memcpy(offset + (u8 *)shr, buf, count);
160 shr->length = count;
161 barrier();
162 shr->state = VTPM_STATE_SUBMIT;
163 wmb();
164 notify_remote_via_evtchn(priv->evtchn);
165
166 ordinal = be32_to_cpu(((struct tpm_header *)buf)->ordinal);
167 duration = tpm_calc_ordinal_duration(chip, ordinal);
168
169 if (wait_for_tpm_stat(chip, VTPM_STATUS_IDLE, duration,
170 &priv->read_queue, true) < 0) {
171
172 vtpm_cancel(chip);
173 return -ETIME;
174 }
175
176 return 0;
177}
178
179static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
180{
181 struct tpm_private *priv = dev_get_drvdata(&chip->dev);
182 struct vtpm_shared_page *shr = priv->shr;
183 unsigned int offset = shr_data_offset(shr);
184 size_t length = shr->length;
185
186 if (shr->state == VTPM_STATE_IDLE)
187 return -ECANCELED;
188
189
190 if (wait_for_tpm_stat(chip, VTPM_STATUS_RESULT, chip->timeout_c,
191 &priv->read_queue, true) < 0) {
192 vtpm_cancel(chip);
193 return -ETIME;
194 }
195
196 if (offset > PAGE_SIZE)
197 return -EIO;
198
199 if (offset + length > PAGE_SIZE)
200 length = PAGE_SIZE - offset;
201
202 if (length > count)
203 length = count;
204
205 memcpy(buf, offset + (u8 *)shr, length);
206
207 return length;
208}
209
210static const struct tpm_class_ops tpm_vtpm = {
211 .status = vtpm_status,
212 .recv = vtpm_recv,
213 .send = vtpm_send,
214 .cancel = vtpm_cancel,
215 .req_complete_mask = VTPM_STATUS_IDLE | VTPM_STATUS_RESULT,
216 .req_complete_val = VTPM_STATUS_IDLE | VTPM_STATUS_RESULT,
217 .req_canceled = vtpm_req_canceled,
218};
219
220static irqreturn_t tpmif_interrupt(int dummy, void *dev_id)
221{
222 struct tpm_private *priv = dev_id;
223
224 switch (priv->shr->state) {
225 case VTPM_STATE_IDLE:
226 case VTPM_STATE_FINISH:
227 wake_up_interruptible(&priv->read_queue);
228 break;
229 case VTPM_STATE_SUBMIT:
230 case VTPM_STATE_CANCEL:
231 default:
232 break;
233 }
234 return IRQ_HANDLED;
235}
236
237static int setup_chip(struct device *dev, struct tpm_private *priv)
238{
239 struct tpm_chip *chip;
240
241 chip = tpmm_chip_alloc(dev, &tpm_vtpm);
242 if (IS_ERR(chip))
243 return PTR_ERR(chip);
244
245 init_waitqueue_head(&priv->read_queue);
246
247 priv->chip = chip;
248 dev_set_drvdata(&chip->dev, priv);
249
250 return 0;
251}
252
253
254static int setup_ring(struct xenbus_device *dev, struct tpm_private *priv)
255{
256 struct xenbus_transaction xbt;
257 const char *message = NULL;
258 int rv;
259 grant_ref_t gref;
260
261 priv->shr = (void *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
262 if (!priv->shr) {
263 xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
264 return -ENOMEM;
265 }
266
267 rv = xenbus_grant_ring(dev, priv->shr, 1, &gref);
268 if (rv < 0)
269 return rv;
270
271 priv->ring_ref = gref;
272
273 rv = xenbus_alloc_evtchn(dev, &priv->evtchn);
274 if (rv)
275 return rv;
276
277 rv = bind_evtchn_to_irqhandler(priv->evtchn, tpmif_interrupt, 0,
278 "tpmif", priv);
279 if (rv <= 0) {
280 xenbus_dev_fatal(dev, rv, "allocating TPM irq");
281 return rv;
282 }
283 priv->irq = rv;
284
285 again:
286 rv = xenbus_transaction_start(&xbt);
287 if (rv) {
288 xenbus_dev_fatal(dev, rv, "starting transaction");
289 return rv;
290 }
291
292 rv = xenbus_printf(xbt, dev->nodename,
293 "ring-ref", "%u", priv->ring_ref);
294 if (rv) {
295 message = "writing ring-ref";
296 goto abort_transaction;
297 }
298
299 rv = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
300 priv->evtchn);
301 if (rv) {
302 message = "writing event-channel";
303 goto abort_transaction;
304 }
305
306 rv = xenbus_printf(xbt, dev->nodename, "feature-protocol-v2", "1");
307 if (rv) {
308 message = "writing feature-protocol-v2";
309 goto abort_transaction;
310 }
311
312 rv = xenbus_transaction_end(xbt, 0);
313 if (rv == -EAGAIN)
314 goto again;
315 if (rv) {
316 xenbus_dev_fatal(dev, rv, "completing transaction");
317 return rv;
318 }
319
320 xenbus_switch_state(dev, XenbusStateInitialised);
321
322 return 0;
323
324 abort_transaction:
325 xenbus_transaction_end(xbt, 1);
326 if (message)
327 xenbus_dev_error(dev, rv, "%s", message);
328
329 return rv;
330}
331
332static void ring_free(struct tpm_private *priv)
333{
334 if (!priv)
335 return;
336
337 if (priv->ring_ref)
338 gnttab_end_foreign_access(priv->ring_ref, 0,
339 (unsigned long)priv->shr);
340 else
341 free_page((unsigned long)priv->shr);
342
343 if (priv->irq)
344 unbind_from_irqhandler(priv->irq, priv);
345
346 kfree(priv);
347}
348
349static int tpmfront_probe(struct xenbus_device *dev,
350 const struct xenbus_device_id *id)
351{
352 struct tpm_private *priv;
353 int rv;
354
355 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
356 if (!priv) {
357 xenbus_dev_fatal(dev, -ENOMEM, "allocating priv structure");
358 return -ENOMEM;
359 }
360
361 rv = setup_chip(&dev->dev, priv);
362 if (rv) {
363 kfree(priv);
364 return rv;
365 }
366
367 rv = setup_ring(dev, priv);
368 if (rv) {
369 ring_free(priv);
370 return rv;
371 }
372
373 tpm_get_timeouts(priv->chip);
374
375 return tpm_chip_register(priv->chip);
376}
377
378static int tpmfront_remove(struct xenbus_device *dev)
379{
380 struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
381 struct tpm_private *priv = dev_get_drvdata(&chip->dev);
382 tpm_chip_unregister(chip);
383 ring_free(priv);
384 dev_set_drvdata(&chip->dev, NULL);
385 return 0;
386}
387
388static int tpmfront_resume(struct xenbus_device *dev)
389{
390
391 tpmfront_remove(dev);
392 return tpmfront_probe(dev, NULL);
393}
394
395static void backend_changed(struct xenbus_device *dev,
396 enum xenbus_state backend_state)
397{
398 switch (backend_state) {
399 case XenbusStateInitialised:
400 case XenbusStateConnected:
401 if (dev->state == XenbusStateConnected)
402 break;
403
404 if (!xenbus_read_unsigned(dev->otherend, "feature-protocol-v2",
405 0)) {
406 xenbus_dev_fatal(dev, -EINVAL,
407 "vTPM protocol 2 required");
408 return;
409 }
410 xenbus_switch_state(dev, XenbusStateConnected);
411 break;
412
413 case XenbusStateClosing:
414 case XenbusStateClosed:
415 device_unregister(&dev->dev);
416 xenbus_frontend_closed(dev);
417 break;
418 default:
419 break;
420 }
421}
422
423static const struct xenbus_device_id tpmfront_ids[] = {
424 { "vtpm" },
425 { "" }
426};
427MODULE_ALIAS("xen:vtpm");
428
429static struct xenbus_driver tpmfront_driver = {
430 .ids = tpmfront_ids,
431 .probe = tpmfront_probe,
432 .remove = tpmfront_remove,
433 .resume = tpmfront_resume,
434 .otherend_changed = backend_changed,
435};
436
437static int __init xen_tpmfront_init(void)
438{
439 if (!xen_domain())
440 return -ENODEV;
441
442 if (!xen_has_pv_devices())
443 return -ENODEV;
444
445 return xenbus_register_frontend(&tpmfront_driver);
446}
447module_init(xen_tpmfront_init);
448
449static void __exit xen_tpmfront_exit(void)
450{
451 xenbus_unregister_driver(&tpmfront_driver);
452}
453module_exit(xen_tpmfront_exit);
454
455MODULE_AUTHOR("Daniel De Graaf <dgdegra@tycho.nsa.gov>");
456MODULE_DESCRIPTION("Xen vTPM Driver");
457MODULE_LICENSE("GPL");
458