[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Update vtpm driver following the recent changes to the
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID cb215a84d1af0aa0143e52a459607f54503a51a7 # Parent b0338759544e116337f25d5cdebc59c38a6d40c5 Update vtpm driver following the recent changes to the xenbus driver and its semantics. Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx> diff -r b0338759544e -r cb215a84d1af docs/misc/vtpm.txt --- a/docs/misc/vtpm.txt Thu Nov 24 22:21:48 2005 +++ b/docs/misc/vtpm.txt Fri Nov 25 08:14:01 2005 @@ -73,7 +73,14 @@ where the TPM backend has been compiled into - this has to be domain 0 at the moment - and which TPM instance the user domain is supposed to talk to. Note that each running VM must use a -different instance and that using instance 0 is NOT allowed. +different instance and that using instance 0 is NOT allowed. The +instance parameter is taken as the desired instance number, but +the actual instance number that is assigned to the virtual machine +can be different. This is the case if for example that particular +instance is already used by another virtual machine. The association +of which TPM instance number is used by which virtual machine is +kept in the file /etc/xen/vtpm.db. Associations are maintained by +domain name and instance number. Note: If you do not want TPM functionality for your user domain simply leave out the 'vtpm' line in the configuration file. diff -r b0338759544e -r cb215a84d1af linux-2.6-xen-sparse/drivers/char/tpm/Kconfig --- a/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig Thu Nov 24 22:21:48 2005 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig Fri Nov 25 08:14:01 2005 @@ -17,15 +17,6 @@ obtained at: <http://sourceforge.net/projects/trousers>. To compile this driver as a module, choose M here; the module will be called tpm. If unsure, say N. - -config TCG_TIS - tristate "TPM Interface Specification 1.2 Interface" - depends on TCG_TPM - ---help--- - If you have a TPM security chip that is compliant with the - TCG TIS 1.2 TPM specification say Yes and it will be accessible - from within Linux. To compile this driver as a module, choose - M here; the module will be called tpm_tis. config TCG_NSC tristate "National Semiconductor TPM Interface" diff -r b0338759544e -r cb215a84d1af linux-2.6-xen-sparse/drivers/xen/tpmback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Thu Nov 24 22:21:48 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Fri Nov 25 08:14:01 2005 @@ -28,7 +28,7 @@ #endif typedef struct tpmif_st { - struct list_head tpmif_list; + struct list_head tpmif_list; /* Unique identifier for this interface. */ domid_t domid; unsigned int handle; @@ -83,6 +83,11 @@ #define MMAP_VADDR(t,_req) ((t)->mmap_vstart + ((_req) * PAGE_SIZE)) +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + #endif /* __TPMIF__BACKEND__COMMON_H__ */ /* diff -r b0338759544e -r cb215a84d1af linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Thu Nov 24 22:21:48 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Fri Nov 25 08:14:01 2005 @@ -127,6 +127,10 @@ .u.bind_interdomain.remote_dom = tpmif->domid, .u.bind_interdomain.remote_port = evtchn }; + if (tpmif->irq) { + return 0; + } + if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL) return -ENOMEM; @@ -149,7 +153,6 @@ tpmif->irq = bind_evtchn_to_irqhandler( tpmif->evtchn, tpmif_be_int, 0, "tpmif-backend", tpmif); - tpmif->status = CONNECTED; tpmif->shmem_ref = shared_page; tpmif->active = 1; diff -r b0338759544e -r cb215a84d1af linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Thu Nov 24 22:21:48 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Fri Nov 25 08:14:01 2005 @@ -1,4 +1,5 @@ /* Xenbus code for tpmif backend + Copyright (C) 2005 IBM Corporation Copyright (C) 2005 Rusty Russell <rusty@xxxxxxxxxxxxxxx> This program is free software; you can redistribute it and/or modify @@ -29,72 +30,189 @@ long int frontend_id; long int instance; // instance of TPM + u8 is_instance_set;// whether instance number has been set /* watch front end for changes */ struct xenbus_watch backend_watch; - - struct xenbus_watch watch; - char * frontpath; + XenbusState frontend_state; }; +static void maybe_connect(struct backend_info *be); +static void connect(struct backend_info *be); +static int connect_ring(struct backend_info *be); +static void backend_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len); +static void frontend_changed(struct xenbus_device *dev, + XenbusState frontend_state); + static int tpmback_remove(struct xenbus_device *dev) { struct backend_info *be = dev->data; - if (be->watch.node) - unregister_xenbus_watch(&be->watch); - unregister_xenbus_watch(&be->backend_watch); - - tpmif_vtpm_close(be->instance); - - if (be->tpmif) + if (be->backend_watch.node) { + unregister_xenbus_watch(&be->backend_watch); + kfree(be->backend_watch.node); + be->backend_watch.node = NULL; + } + if (be->tpmif) { tpmif_put(be->tpmif); - - kfree(be->frontpath); + be->tpmif = NULL; + } kfree(be); + dev->data = NULL; return 0; } - -static void frontend_changed(struct xenbus_watch *watch, - const char **vec, unsigned int len) -{ - unsigned long ringref; - unsigned int evtchn; - unsigned long ready = 1; - int err; - struct xenbus_transaction *xbt; +static int tpmback_probe(struct xenbus_device *dev, + const struct xenbus_device_id *id) +{ + int err; + struct backend_info *be = kmalloc(sizeof(struct backend_info), + GFP_KERNEL); + + if (!be) { + xenbus_dev_fatal(dev, -ENOMEM, + "allocating backend structure"); + return -ENOMEM; + } + + memset(be, 0, sizeof(*be)); + + be->is_instance_set = FALSE; + be->dev = dev; + dev->data = be; + + err = xenbus_watch_path2(dev, dev->nodename, + "instance", &be->backend_watch, + backend_changed); + if (err) { + goto fail; + } + + err = xenbus_switch_state(dev, NULL, XenbusStateInitWait); + if (err) { + goto fail; + } + return 0; +fail: + tpmback_remove(dev); + return err; +} + + +static void backend_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + int err; + long instance; struct backend_info *be - = container_of(watch, struct backend_info, watch); - - /* If other end is gone, delete ourself. */ - if (vec && !xenbus_exists(NULL, be->frontpath, "")) { - xenbus_rm(NULL, be->dev->nodename, ""); + = container_of(watch, struct backend_info, backend_watch); + struct xenbus_device *dev = be->dev; + + err = xenbus_scanf(NULL, dev->nodename, + "instance","%li", &instance); + if (XENBUS_EXIST_ERR(err)) { + return; + } + + if (err != 1) { + xenbus_dev_fatal(dev, err, "reading instance"); + return; + } + + if (be->is_instance_set != FALSE && 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 == FALSE) { + 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 = TRUE; + + /* + * 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); + } + } +} + + +static void frontend_changed(struct xenbus_device *dev, + XenbusState frontend_state) +{ + struct backend_info *be = dev->data; + int err; + + be->frontend_state = frontend_state; + + switch (frontend_state) { + case XenbusStateInitialising: + case XenbusStateConnected: + break; + + case XenbusStateInitialised: + err = connect_ring(be); + if (err) { + return; + } + maybe_connect(be); + break; + + case XenbusStateClosing: + xenbus_switch_state(dev, NULL, XenbusStateClosing); + break; + + case XenbusStateClosed: + /* + * Notify the vTPM manager about the front-end + * having left. + */ + tpmif_vtpm_close(be->instance); device_unregister(&be->dev->dev); - return; - } + break; + + case XenbusStateUnknown: + case XenbusStateInitWait: + default: + xenbus_dev_fatal(dev, -EINVAL, + "saw state %d at frontend", + frontend_state); + break; + } +} + + + +static void maybe_connect(struct backend_info *be) +{ + int err; if (be->tpmif == NULL || be->tpmif->status == CONNECTED) return; - err = xenbus_gather(NULL, be->frontpath, - "ring-ref", "%lu", &ringref, - "event-channel", "%u", &evtchn, NULL); - if (err) { - xenbus_dev_error(be->dev, err, - "reading %s/ring-ref and event-channel", - be->frontpath); - return; - } - - err = tpmif_map(be->tpmif, ringref, evtchn); - if (err) { - xenbus_dev_error(be->dev, err, - "mapping shared-frame %lu port %u", - ringref, evtchn); - return; - } - + connect(be); + + /* + * Notify the vTPM manager about a new front-end. + */ err = tpmif_vtpm_open(be->tpmif, be->frontend_id, be->instance); @@ -107,157 +225,75 @@ */ return; } - - /* - * Tell the front-end that we are ready to go - - * unless something bad happens - */ +} + + +static void connect(struct backend_info *be) +{ + struct xenbus_transaction *xbt; + int err; + struct xenbus_device *dev = be->dev; + unsigned long ready = 1; + again: xbt = xenbus_transaction_start(); if (IS_ERR(xbt)) { - xenbus_dev_error(be->dev, err, "starting transaction"); + err = PTR_ERR(xbt); + xenbus_dev_fatal(be->dev, err, "starting transaction"); return; } err = xenbus_printf(xbt, be->dev->nodename, "ready", "%lu", ready); if (err) { - xenbus_dev_error(be->dev, err, "writing 'ready'"); + xenbus_dev_fatal(be->dev, err, "writing 'ready'"); goto abort; } + + err = xenbus_switch_state(dev, xbt, XenbusStateConnected); + if (err) + goto abort; + + be->tpmif->status = CONNECTED; err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; if (err) { - xenbus_dev_error(be->dev, err, "end of transaction"); - goto abort; - } - - xenbus_dev_ok(be->dev); + xenbus_dev_fatal(be->dev, err, "end of transaction"); + } return; abort: xenbus_transaction_end(xbt, 1); } -static void backend_changed(struct xenbus_watch *watch, - const char **vec, unsigned int len) -{ - int err; - long int instance; - struct backend_info *be - = container_of(watch, struct backend_info, backend_watch); +static int connect_ring(struct backend_info *be) +{ struct xenbus_device *dev = be->dev; - - err = xenbus_scanf(NULL, dev->nodename, "instance", "%li", &instance); - if (XENBUS_EXIST_ERR(err)) - return; - if (err < 0) { - xenbus_dev_error(dev, err, "reading 'instance' variable"); - return; - } - - if (be->instance != -1 && be->instance != instance) { - printk(KERN_WARNING - "cannot change the instance\n"); - return; - } - be->instance = instance; - - if (be->tpmif == NULL) { - unsigned int len = max(XS_WATCH_PATH, XS_WATCH_TOKEN) + 1; - const char *vec[len]; - - be->tpmif = tpmif_find(be->frontend_id, - instance); - if (IS_ERR(be->tpmif)) { - err = PTR_ERR(be->tpmif); - be->tpmif = NULL; - xenbus_dev_error(dev, err, "creating interface"); - return; + unsigned long ring_ref; + unsigned int evtchn; + int err; + + err = xenbus_gather(NULL, dev->otherend, + "ring-ref", "%lu", &ring_ref, + "event-channel", "%u", &evtchn, NULL); + if (err) { + xenbus_dev_error(dev, err, + "reading %s/ring-ref and event-channel", + dev->otherend); + return err; + } + if (be->tpmif != NULL) { + err = tpmif_map(be->tpmif, ring_ref, evtchn); + if (err) { + xenbus_dev_error(dev, err, + "mapping shared-frame %lu port %u", + ring_ref, evtchn); + return err; } - - vec[XS_WATCH_PATH] = be->frontpath; - vec[XS_WATCH_TOKEN] = NULL; - - /* Pass in NULL node to skip exist test. */ - frontend_changed(&be->watch, vec, len); - } -} - - -static int tpmback_probe(struct xenbus_device *dev, - const struct xenbus_device_id *id) -{ - struct backend_info *be; - char *frontend; - int err; - - be = kmalloc(sizeof(*be), GFP_KERNEL); - if (!be) { - xenbus_dev_error(dev, -ENOMEM, "allocating backend structure"); - err = -ENOMEM; - } - - memset(be, 0, sizeof(*be)); - - frontend = NULL; - err = xenbus_gather(NULL, dev->nodename, - "frontend-id", "%li", &be->frontend_id, - "frontend", NULL, &frontend, - NULL); - if (XENBUS_EXIST_ERR(err)) - goto free_be; - if (err < 0) { - xenbus_dev_error(dev, err, - "reading %s/frontend or frontend-id", - dev->nodename); - goto free_be; - } - if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) { - /* If we can't get a frontend path and a frontend-id, - * then our bus-id is no longer valid and we need to - * destroy the backend device. - */ - err = -ENOENT; - goto free_be; - } - - be->dev = dev; - be->backend_watch.node = dev->nodename; - /* Implicitly calls backend_changed() once. */ - be->backend_watch.callback = backend_changed; - be->instance = -1; - err = register_xenbus_watch(&be->backend_watch); - if (err) { - be->backend_watch.node = NULL; - xenbus_dev_error(dev, err, "adding backend watch on %s", - dev->nodename); - goto free_be; - } - - be->frontpath = frontend; - be->watch.node = be->frontpath; - be->watch.callback = frontend_changed; - err = register_xenbus_watch(&be->watch); - if (err) { - be->watch.node = NULL; - xenbus_dev_error(dev, err, - "adding frontend watch on %s", - be->frontpath); - goto free_be; - } - - dev->data = be; - return err; - -free_be: - if (be->backend_watch.node) - unregister_xenbus_watch(&be->backend_watch); - kfree(frontend); - kfree(be); - return err; + } + return 0; } @@ -273,6 +309,7 @@ .ids = tpmback_ids, .probe = tpmback_probe, .remove = tpmback_remove, + .otherend_changed = frontend_changed, }; diff -r b0338759544e -r cb215a84d1af linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Thu Nov 24 22:21:48 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Fri Nov 25 08:14:01 2005 @@ -73,7 +73,8 @@ static void tpmif_connect(u16 evtchn, domid_t domid); static DECLARE_TASKLET(tpmif_rx_tasklet, tpmif_rx_action, 0); static int tpm_allocate_buffers(struct tpm_private *tp); -static void tpmif_set_connected_state(struct tpm_private *tp, int newstate); +static void tpmif_set_connected_state(struct tpm_private *tp, + u8 newstate); static int tpm_xmit(struct tpm_private *tp, const u8 * buf, size_t count, int userbuffer, void *remember); @@ -212,87 +213,46 @@ XENBUS support code **************************************************************/ -static void watch_for_status(struct xenbus_watch *watch, - const char **vec, unsigned int len) -{ - struct tpmfront_info *info; - int err; - unsigned long ready; - struct tpm_private *tp = &my_private; - const char *node = vec[XS_WATCH_PATH]; - - info = container_of(watch, struct tpmfront_info, watch); - node += strlen(watch->node); - - if (tp->connected) - return; - - err = xenbus_gather(NULL, watch->node, - "ready", "%lu", &ready, - NULL); - if (err) { - xenbus_dev_error(info->dev, err, "reading 'ready' field"); - return; - } - - tpmif_set_connected_state(tp, 1); - - xenbus_dev_ok(info->dev); -} - - static int setup_tpmring(struct xenbus_device *dev, - struct tpmfront_info * info, - domid_t backend_id) + struct tpmfront_info * info) { tpmif_tx_interface_t *sring; struct tpm_private *tp = &my_private; int err; - evtchn_op_t op = { - .cmd = EVTCHNOP_alloc_unbound, - .u.alloc_unbound.dom = DOMID_SELF, - .u.alloc_unbound.remote_dom = backend_id } ; sring = (void *)__get_free_page(GFP_KERNEL); if (!sring) { - xenbus_dev_error(dev, -ENOMEM, "allocating shared ring"); + xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring"); return -ENOMEM; } tp->tx = sring; tpm_allocate_buffers(tp); - err = gnttab_grant_foreign_access(backend_id, - (virt_to_machine(tp->tx) >> PAGE_SHIFT), - 0); - - if (err == -ENOSPC) { + err = xenbus_grant_ring(dev, virt_to_mfn(tp->tx)); + if (err < 0) { free_page((unsigned long)sring); tp->tx = NULL; - xenbus_dev_error(dev, err, "allocating grant reference"); - return err; + xenbus_dev_fatal(dev, err, "allocating grant reference"); + goto fail; } info->ring_ref = err; - err = HYPERVISOR_event_channel_op(&op); - if (err) { - gnttab_end_foreign_access(info->ring_ref, 0, - (unsigned long)sring); - tp->tx = NULL; - xenbus_dev_error(dev, err, "allocating event channel"); - return err; - } - - tpmif_connect(op.u.alloc_unbound.port, backend_id); + err = xenbus_alloc_evtchn(dev, &tp->evtchn); + if (err) + goto fail; + + tpmif_connect(tp->evtchn, dev->otherend_id); return 0; +fail: + return err; } static void destroy_tpmring(struct tpmfront_info *info, struct tpm_private *tp) { - tpmif_set_connected_state(tp,0); - + tpmif_set_connected_state(tp, FALSE); if ( tp->tx != NULL ) { gnttab_end_foreign_access(info->ring_ref, 0, (unsigned long)tp->tx); @@ -308,42 +268,20 @@ static int talk_to_backend(struct xenbus_device *dev, struct tpmfront_info *info) { - char *backend; - const char *message; + const char *message = NULL; int err; - int backend_id; struct xenbus_transaction *xbt; - backend = NULL; - err = xenbus_gather(NULL, dev->nodename, - "backend-id", "%i", &backend_id, - "backend", NULL, &backend, - NULL); - if (XENBUS_EXIST_ERR(err)) - goto out; - if (backend && strlen(backend) == 0) { - err = -ENOENT; - goto out; - } - if (err < 0) { - xenbus_dev_error(dev, err, "reading %s/backend or backend-id", - dev->nodename); - goto out; - } - - info->backend_id = backend_id; - my_private.backend_id = backend_id; - - err = setup_tpmring(dev, info, backend_id); + err = setup_tpmring(dev, info); if (err) { - xenbus_dev_error(dev, err, "setting up ring"); + xenbus_dev_fatal(dev, err, "setting up ring"); goto out; } again: xbt = xenbus_transaction_start(); if (IS_ERR(xbt)) { - xenbus_dev_error(dev, err, "starting transaction"); + xenbus_dev_fatal(dev, err, "starting transaction"); goto destroy_tpmring; } @@ -361,34 +299,60 @@ goto abort_transaction; } + err = xenbus_switch_state(dev, xbt, XenbusStateInitialised); + if (err) { + goto abort_transaction; + } + err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; if (err) { - xenbus_dev_error(dev, err, "completing transaction"); + xenbus_dev_fatal(dev, err, "completing transaction"); goto destroy_tpmring; } - - info->watch.node = backend; - info->watch.callback = watch_for_status; - err = register_xenbus_watch(&info->watch); - if (err) { - xenbus_dev_error(dev, err, "registering watch on backend"); - goto destroy_tpmring; - } - - info->backend = backend; - return 0; abort_transaction: xenbus_transaction_end(xbt, 1); - xenbus_dev_error(dev, err, "%s", message); + if (message) + xenbus_dev_error(dev, err, "%s", message); destroy_tpmring: destroy_tpmring(info, &my_private); out: - kfree(backend); return err; +} + +/** + * Callback received when the backend's state changes. + */ +static void backend_changed(struct xenbus_device *dev, + XenbusState backend_state) +{ + struct tpm_private *tp = &my_private; + DPRINTK("\n"); + + switch (backend_state) { + case XenbusStateInitialising: + case XenbusStateInitWait: + case XenbusStateInitialised: + case XenbusStateUnknown: + break; + + case XenbusStateConnected: + tpmif_set_connected_state(tp, TRUE); + break; + + case XenbusStateClosing: + tpmif_set_connected_state(tp, FALSE); + break; + + case XenbusStateClosed: + if (tp->is_suspended == FALSE) { + device_unregister(&dev->dev); + } + break; + } } @@ -398,8 +362,6 @@ int err; struct tpmfront_info *info; int handle; - int len = max(XS_WATCH_PATH, XS_WATCH_TOKEN) + 1; - const char *vec[len]; err = xenbus_scanf(NULL, dev->nodename, "handle", "%i", &handle); @@ -407,19 +369,19 @@ return err; if (err < 0) { - xenbus_dev_error(dev,err,"reading virtual-device"); + xenbus_dev_fatal(dev,err,"reading virtual-device"); return err; } info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) { - xenbus_dev_error(dev,err,"allocating info structure"); + err = -ENOMEM; + xenbus_dev_fatal(dev,err,"allocating info structure"); return err; } memset(info, 0x0, sizeof(*info)); info->dev = dev; - info->handle = handle; dev->data = info; err = talk_to_backend(dev, info); @@ -428,41 +390,33 @@ dev->data = NULL; return err; } - - vec[XS_WATCH_PATH] = info->watch.node; - vec[XS_WATCH_TOKEN] = NULL; - watch_for_status(&info->watch, vec, len); - return 0; } + static int tpmfront_remove(struct xenbus_device *dev) { struct tpmfront_info *info = dev->data; - if (info->backend) - unregister_xenbus_watch(&info->watch); destroy_tpmring(info, &my_private); - kfree(info->backend); kfree(info); - return 0; } static int tpmfront_suspend(struct xenbus_device *dev) { - struct tpmfront_info *info = dev->data; struct tpm_private *tp = &my_private; u32 ctr = 0; /* lock, so no app can send */ down(&suspend_lock); + tp->is_suspended = TRUE; while (atomic_read(&tp->tx_busy) && ctr <= 25) { - if ((ctr % 10) == 0) - printk("INFO: Waiting for outstanding request.\n"); + if ((ctr % 10) == 0) + printk("TPM-FE [INFO]: Waiting for outstanding request.\n"); /* * Wait for a request to be responded to. */ @@ -474,14 +428,9 @@ /* * A temporary work-around. */ - printk("WARNING: Resetting busy flag."); + printk("TPM-FE [WARNING]: Resetting busy flag."); atomic_set(&tp->tx_busy, 0); } - - unregister_xenbus_watch(&info->watch); - - kfree(info->backend); - info->backend = NULL; return 0; } @@ -492,8 +441,6 @@ struct tpmfront_info *info = dev->data; int err = talk_to_backend(dev, info); - /* unlock, so apps can resume sending */ - up(&suspend_lock); return err; } @@ -530,12 +477,13 @@ .probe = tpmfront_probe, .remove = tpmfront_remove, .resume = tpmfront_resume, + .otherend_changed = backend_changed, .suspend = tpmfront_suspend, }; static void __init init_tpm_xenbus(void) { - xenbus_register_driver(&tpmfront); + xenbus_register_frontend(&tpmfront); } @@ -628,12 +576,13 @@ spin_lock_irq(&tp->tx_lock); if (unlikely(atomic_read(&tp->tx_busy))) { - printk("There's an outstanding request/response on the way!\n"); + printk("tpm_xmit: There's an outstanding request/response " + "on the way!\n"); spin_unlock_irq(&tp->tx_lock); return -EBUSY; } - if (tp->connected != 1) { + if (tp->is_connected != TRUE) { spin_unlock_irq(&tp->tx_lock); return -EIO; } @@ -705,24 +654,40 @@ down(&upperlayer_lock); if (upperlayer_tpmfe != NULL) { - switch (tp->connected) { - case 1: - upperlayer_tpmfe->status(TPMFE_STATUS_CONNECTED); - break; - - default: - upperlayer_tpmfe->status(0); - break; + if (tp->is_connected) { + upperlayer_tpmfe->status(TPMFE_STATUS_CONNECTED); + } else { + upperlayer_tpmfe->status(0); } } up(&upperlayer_lock); } -static void tpmif_set_connected_state(struct tpm_private *tp, int newstate) -{ - if (newstate != tp->connected) { - tp->connected = newstate; +static void tpmif_set_connected_state(struct tpm_private *tp, u8 is_connected) +{ + /* + * Don't notify upper layer if we are in suspend mode and + * should disconnect - assumption is that we will resume + * The semaphore keeps apps from sending. + */ + if (is_connected == FALSE && tp->is_suspended == TRUE) { + return; + } + + /* + * Unlock the semaphore if we are connected again + * after being suspended - now resuming. + * This also removes the suspend state. + */ + if (is_connected == TRUE && tp->is_suspended == TRUE) { + tp->is_suspended = FALSE; + /* unlock, so apps can resume sending */ + up(&suspend_lock); + } + + if (is_connected != tp->is_connected) { + tp->is_connected = is_connected; tpmif_notify_upperlayer(tp); } } diff -r b0338759544e -r cb215a84d1af linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h Thu Nov 24 22:21:48 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h Fri Nov 25 08:14:01 2005 @@ -1,12 +1,17 @@ #ifndef TPM_FRONT_H #define TPM_FRONT_H +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif -struct tpm_private -{ +struct tpm_private { tpmif_tx_interface_t *tx; - unsigned int evtchn, irq; - int connected; + unsigned int evtchn; + unsigned int irq; + u8 is_connected; + u8 is_suspended; spinlock_t tx_lock; @@ -16,25 +21,18 @@ void *tx_remember; domid_t backend_id; wait_queue_head_t wait_q; + }; - -struct tpmfront_info -{ - struct xenbus_watch watch; - int handle; +struct tpmfront_info { struct xenbus_device *dev; - char *backend; int ring_ref; - domid_t backend_id; }; - -struct tx_buffer -{ +struct tx_buffer { unsigned int size; // available space in data unsigned int len; // used space in data - unsigned char *data; // pointer to a page + unsigned char *data; // pointer to a page }; #endif diff -r b0338759544e -r cb215a84d1af tools/examples/Makefile --- a/tools/examples/Makefile Thu Nov 24 22:21:48 2005 +++ b/tools/examples/Makefile Fri Nov 25 08:14:01 2005 @@ -26,9 +26,10 @@ XEN_SCRIPTS += network-nat vif-nat XEN_SCRIPTS += block XEN_SCRIPTS += block-enbd block-nbd +XEN_SCRIPTS += vtpm XEN_SCRIPT_DATA = xen-script-common.sh XEN_SCRIPT_DATA += xen-hotplug-common.sh xen-network-common.sh vif-common.sh -XEN_SCRIPT_DATA += block-common.sh +XEN_SCRIPT_DATA += block-common.sh vtpm-common.sh XEN_HOTPLUG_DIR = /etc/hotplug XEN_HOTPLUG_SCRIPTS = xen-backend.agent diff -r b0338759544e -r cb215a84d1af tools/examples/xen-backend.agent --- a/tools/examples/xen-backend.agent Thu Nov 24 22:21:48 2005 +++ b/tools/examples/xen-backend.agent Fri Nov 25 08:14:01 2005 @@ -5,6 +5,9 @@ case "$XENBUS_TYPE" in vbd) /etc/xen/scripts/block "$ACTION" + ;; + vtpm) + /etc/xen/scripts/vtpm "$ACTION" ;; vif) [ -n "$script" ] && $script "$ACTION" diff -r b0338759544e -r cb215a84d1af tools/examples/xen-backend.rules --- a/tools/examples/xen-backend.rules Thu Nov 24 22:21:48 2005 +++ b/tools/examples/xen-backend.rules Fri Nov 25 08:14:01 2005 @@ -1,4 +1,5 @@ SUBSYSTEM=="xen-backend", KERNEL=="vbd*", RUN+="/etc/xen/scripts/block $env{ACTION}" +SUBSYSTEM=="xen-backend", KERNEL=="vtpm*", RUN+="/etc/xen/scripts/vtpm $env{ACTION}" SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="online", RUN+="$env{script} online" SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="offline", RUN+="$env{script} offline" SUBSYSTEM=="xen-backend", ACTION=="remove", RUN+="/bin/bash -c '/usr/bin/xenstore-rm -t $$(/usr/bin/xenstore-read $env{XENBUS_PATH}/frontend)'" diff -r b0338759544e -r cb215a84d1af tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Thu Nov 24 22:21:48 2005 +++ b/tools/python/xen/xend/image.py Fri Nov 25 08:14:01 2005 @@ -293,7 +293,7 @@ ret.append("-bridge") ret.append("%s" % bridge) if name == 'vtpm': - instance = sxp.child_value(info, 'instance') + instance = sxp.child_value(info, 'pref_instance') ret.append("-instance") ret.append("%s" % instance) return ret diff -r b0338759544e -r cb215a84d1af tools/python/xen/xend/server/tpmif.py --- a/tools/python/xen/xend/server/tpmif.py Thu Nov 24 22:21:48 2005 +++ b/tools/python/xen/xend/server/tpmif.py Fri Nov 25 08:14:01 2005 @@ -38,10 +38,10 @@ def getDeviceDetails(self, config): """@see DevController.getDeviceDetails""" - devid = int(sxp.child_value(config, 'instance', '0')) + devid = int(sxp.child_value(config, 'pref_instance', '0')) log.info("The domain has a TPM with instance %d." % devid) - back = { 'instance' : "%i" % devid } + back = { 'pref_instance' : "%i" % devid } front = { 'handle' : "%i" % devid } return (devid, back, front) diff -r b0338759544e -r cb215a84d1af tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Thu Nov 24 22:21:48 2005 +++ b/tools/python/xen/xm/create.py Fri Nov 25 08:14:01 2005 @@ -220,11 +220,9 @@ fn=set_bool, default=0, use="Make the domain a network interface backend.") -gopts.var('tpmif', val='frontend=DOM', - fn=append_value, default=[], - use="""Make the domain a TPM interface backend. If frontend is given, - the frontend in that domain is connected to this backend (not - completely implemented, yet)""") +gopts.var('tpmif', val='no|yes', + fn=append_value, default=0, + use="Make the domain a TPM interface backend.") gopts.var('disk', val='phy:DEV,VDEV,MODE[,DOM]', fn=append_value, default=[], @@ -273,9 +271,13 @@ gopts.var('vtpm', val="instance=INSTANCE,backend=DOM", fn=append_value, default=[], - use="""Add a tpm interface. On the backend side us the the given - instance as virtual TPM instance. Use the backend in the given - domain.""") + use="""Add a TPM interface. On the backend side use the given + instance as virtual TPM instance. The given number is merely the + preferred instance number. The hotplug script will determine + which instance number will actually be assigned to the domain. + The associtation between virtual machine and the TPM instance + number can be found in /etc/xen/vtpm.db. Use the backend in the + given domain.""") gopts.var('nics', val="NUM", fn=set_int, default=1, @@ -465,33 +467,19 @@ if instance == "VTPMD": instance = "0" else: - try: - if int(instance) == 0: - err('VM config error: vTPM instance must not be 0.') - except ValueError: - err('Vm config error: could not parse instance number.') + if instance != None: + try: + if int(instance) == 0: + err('VM config error: vTPM instance must not be 0.') + except ValueError: + err('Vm config error: could not parse instance number.') backend = d.get('backend') config_vtpm = ['vtpm'] if instance: - config_vtpm.append(['instance', instance]) + config_vtpm.append(['pref_instance', instance]) if backend: config_vtpm.append(['backend', backend]) config_devs.append(['device', config_vtpm]) - -def configure_tpmif(config_devs, vals): - """Create the config for virtual TPM interfaces. - """ - tpmif = vals.tpmif - tpmif_n = 1 - for idx in range(0, tpmif_n): - if idx < len(tpmif): - d = tpmif[idx] - frontend = d.get('frontend') - config_tpmif = ['tpmif'] - if frontend: - config_tpmif.append(['frontend', frontend]) - config_devs.append(['device', config_tpmif]) - def configure_vifs(config_devs, vals): """Create the config for virtual network interfaces. @@ -685,22 +673,6 @@ vtpms.append(d) vals.vtpm = vtpms -def preprocess_tpmif(vals): - if not vals.tpmif: return - tpmifs = [] - for tpmif in vals.tpmif: - d = {} - a = tpmif.split(',') - for b in a: - (k, v) = b.strip().split('=', 1) - k = k.strip() - v = v.strip() - if k not in ['frontend']: - err('Invalid tpmif specifier: ' + vtpm) - d[k] = v - tpmifs.append(d) - vals.tpmif = tpmifs - def preprocess_ip(vals): if vals.ip or vals.dhcp != 'off': dummy_nfs_server = '1.2.3.4' @@ -791,7 +763,6 @@ preprocess_nfs(vals) preprocess_vnc(vals) preprocess_vtpm(vals) - preprocess_tpmif(vals) def make_domain(opts, config): """Create, build and start a domain. diff -r b0338759544e -r cb215a84d1af tools/examples/vtpm --- /dev/null Thu Nov 24 22:21:48 2005 +++ b/tools/examples/vtpm Fri Nov 25 08:14:01 2005 @@ -0,0 +1,23 @@ +#!/bin/sh + +dir=$(dirname "$0") +. "$dir/vtpm-common.sh" + + +case "$command" in + online | offline) + exit 0 + ;; +esac + +case "$command" in + add) + vtpm_create_instance + ;; + remove) + vtpm_remove_instance + ;; +esac + +log debug "Successful vTPM operation '$command'." +success diff -r b0338759544e -r cb215a84d1af tools/examples/vtpm-common.sh --- /dev/null Thu Nov 24 22:21:48 2005 +++ b/tools/examples/vtpm-common.sh Fri Nov 25 08:14:01 2005 @@ -0,0 +1,281 @@ +# +# Copyright (c) 2005 IBM Corporation +# Copyright (c) 2005 XenSource Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +dir=$(dirname "$0") +. "$dir/xen-hotplug-common.sh" + +findCommand "$@" +if [ "$command" != "online" ] && + [ "$command" != "offline" ] && + [ "$command" != "add" ] && + [ "$command" != "remove" ] +then + log err "Invalid command: $command" + exit 1 +fi + + +XENBUS_PATH="${XENBUS_PATH:?}" + + +VTPMDB="/etc/xen/vtpm.db" + +#In the vtpm-impl file some commands should be defined: +# vtpm_create, vtpm_setup, vtpm_reset, etc. (see below) +#This should be indicated by setting VTPM_IMPL_DEFINED. +if [ -r "$dir/vtpm-impl" ]; then + . "$dir/vtpm-impl" +fi + +if [ -z "$VTPM_IMPL_DEFINED" ]; then + function vtpm_create () { + true + } + function vtpm_setup() { + true + } + function vtpm_reset() { + true + } + function vtpm_suspend() { + true + } + function vtpm_resume() { + true + } +fi + +#Find the instance number for the vtpm given the name of the domain +# Parameters +# - vmname : the name of the vm +# Return value +# Returns '0' if instance number could not be found, otherwise +# it returns the instance number in the variable 'instance' +function find_instance () { + local vmname=$1 + local ret=0 + instance=`cat $VTPMDB | \ + awk -vvmname=$vmname \ + '{ \ + if ( 1 != index($1,"#")) { \ + if ( $1 == vmname ) { \ + print $2; \ + exit; \ + } \ + } \ + }'` + if [ "$instance" != "" ]; then + ret=1 + fi + return $ret +} + + +# Check whether a particular instance number is still available +# returns '1' if it is available +function is_free_instancenum () { + local instance=$1 + local avail=1 + + #Allowed instance number range: 1-255 + if [ $instance -eq 0 -o $instance -gt 255 ]; then + avail=0 + else + instances=`cat $VTPMDB | \ + gawk \ + '{ \ + if (1 != index($1,"#")) { \ + printf("%s ",$2); \ + } \ + }'` + for i in $instances; do + if [ $i -eq $instance ]; then + avail=0 + break + fi + done + fi + return $avail +} + + +# Get an available instance number given the database +# Returns an unused instance number +function get_free_instancenum () { + local ctr + local instances + local don + instances=`cat $VTPMDB | \ + gawk \ + '{ \ + if (1 != index($1,"#")) { \ + printf("%s ",$2); \ + } \ + }'` + ctr=1 + don=0 + while [ $don -eq 0 ]; do + local found + found=0 + for i in $instances; do + if [ $i -eq $ctr ]; then + found=1; + break; + fi + done + + if [ $found -eq 0 ]; then + don=1 + break + fi + let ctr=ctr+1 + done + let instance=$ctr +} + + +# Add a domain name and instance number to the DB file +function add_instance () { + local vmname=$1 + local inst=$2 + + if [ ! -f $VTPMDB ]; then + echo "#Database for VM to vTPM association" > $VTPMDB + echo "#1st column: domain name" >> $VTPMDB + echo "#2nd column: TPM instance number" >> $VTPMDB + fi + validate_entry $vmname $inst + if [ $? -eq 0 ]; then + echo "$vmname $inst" >> $VTPMDB + fi +} + + +#Validate whether an entry is the same as passed to this +#function +function validate_entry () { + local rc=0 + local vmname=$1 + local inst=$2 + local res + res=`cat $VTPMDB | \ + gawk -vvmname=$vmname \ + -vinst=$inst \ + '{ \ + if ( 1 == index($1,"#")) {\ + } else \ + if ( $1 == vmname && \ + $2 == inst) { \ + printf("1"); \ + exit; \ + } else \ + if ( $1 == vmname || \ + $2 == inst) { \ + printf("2"); \ + exit; \ + } \ + }'` + + if [ "$res" == "1" ]; then + let rc=1 + elif [ "$res" == "2" ]; then + let rc=2 + fi + return $rc +} + + +#Remove an entry from the vTPM database given its domain name +function remove_entry () { + local vmname=$1 + local VTPMDB_TMP="$VTPMDB".tmp + `cat $VTPMDB | \ + gawk -vvmname=$vmname \ + '{ \ + if ( $1 != vmname ) { \ + print $0; \ + } \ + '} > $VTPMDB_TMP` + if [ -e $VTPMDB_TMP ]; then + mv -f $VTPMDB_TMP $VTPMDB + else + log err "Error creating temporary file '$VTPMDB_TMP'." + fi +} + + +#Create a vTPM instance +# If no entry in the TPM database is found, the instance is +# created and an entry added to the database. +function vtpm_create_instance () { + local domname=$(xenstore_read "$XENBUS_PATH"/domain) + local res + set +e + find_instance $domname + res=$? + if [ $res -eq 0 ]; then + #Try to give the preferred instance to the domain + instance=$(xenstore_read "$XENBUS_PATH"/pref_instance) + if [ "$instance" != "" ]; then + is_free_instancenum $instance + res=$? + if [ $res -eq 0 ]; then + get_free_instancenum + fi + else + get_free_instancenum + fi + add_instance $domname $instance + if [ "$REASON" == "create" ]; then + vtpm_create $instance + elif [ "$REASON" == "hibernate" ]; then + vtpm_resume $instance $domname + else + #default case for 'now' + vtpm_create $instance + fi + fi + if [ "$REASON" == "create" ]; then + vtpm_reset $instance + elif [ "$REASON" == "hibernate" ]; then + vtpm_setup $instance + else + #default case for 'now' + vtpm_reset $instance + fi + xenstore_write $XENBUS_PATH/instance $instance + set -e +} + + +#Remove an instance +function vtpm_remove_instance () { + local domname=$(xenstore_read "$XENBUS_PATH"/domain) + set +e + find_instance $domname + res=$? + if [ $res -eq 0 ]; then + #Something is really wrong with the DB + log err "vTPM DB file $VTPMDB has no entry for '$domname'" + else + if [ "$REASON" == "hibernate" ]; then + vtpm_suspend $instance + fi + fi + set -e +} _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |