direct-io.hg

changeset 8031:cb215a84d1af

Update vtpm driver following the recent changes to the
xenbus driver and its semantics.

Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Nov 25 09:14:01 2005 +0100 (2005-11-25)
parents b0338759544e
children a8ac8be1a889
files docs/misc/vtpm.txt linux-2.6-xen-sparse/drivers/char/tpm/Kconfig linux-2.6-xen-sparse/drivers/xen/tpmback/common.h linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h tools/examples/Makefile tools/examples/vtpm tools/examples/vtpm-common.sh tools/examples/xen-backend.agent tools/examples/xen-backend.rules tools/python/xen/xend/image.py tools/python/xen/xend/server/tpmif.py tools/python/xen/xm/create.py
line diff
     1.1 --- a/docs/misc/vtpm.txt	Thu Nov 24 23:21:48 2005 +0100
     1.2 +++ b/docs/misc/vtpm.txt	Fri Nov 25 09:14:01 2005 +0100
     1.3 @@ -73,7 +73,14 @@ information about the domain where the v
     1.4  where the TPM backend has been compiled into - this has to be 
     1.5  domain 0  at the moment - and which TPM instance the user domain
     1.6  is supposed to talk to. Note that each running VM must use a 
     1.7 -different instance and that using instance 0 is NOT allowed.
     1.8 +different instance and that using instance 0 is NOT allowed. The
     1.9 +instance parameter is taken as the desired instance number, but
    1.10 +the actual instance number that is assigned to the virtual machine
    1.11 +can be different. This is the case if for example that particular
    1.12 +instance is already used by another virtual machine. The association
    1.13 +of which TPM instance number is used by which virtual machine is
    1.14 +kept in the file /etc/xen/vtpm.db. Associations are maintained by
    1.15 +domain name and instance number.
    1.16  
    1.17  Note: If you do not want TPM functionality for your user domain simply
    1.18  leave out the 'vtpm' line in the configuration file.
     2.1 --- a/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig	Thu Nov 24 23:21:48 2005 +0100
     2.2 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig	Fri Nov 25 09:14:01 2005 +0100
     2.3 @@ -18,15 +18,6 @@ config TCG_TPM
     2.4  	  compile this driver as a module, choose M here; the module 
     2.5  	  will be called tpm. If unsure, say N.
     2.6  
     2.7 -config TCG_TIS
     2.8 -	tristate "TPM Interface Specification 1.2 Interface"
     2.9 -	depends on TCG_TPM
    2.10 -	---help---
    2.11 -	  If you have a TPM security chip that is compliant with the
    2.12 -	  TCG TIS 1.2 TPM specification say Yes and it will be accessible
    2.13 -	  from within Linux.  To compile this driver as a module, choose
    2.14 -	  M here; the module will be called tpm_tis.
    2.15 -
    2.16  config TCG_NSC
    2.17  	tristate "National Semiconductor TPM Interface"
    2.18  	depends on TCG_TPM
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h	Thu Nov 24 23:21:48 2005 +0100
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h	Fri Nov 25 09:14:01 2005 +0100
     3.3 @@ -28,7 +28,7 @@
     3.4  #endif
     3.5  
     3.6  typedef struct tpmif_st {
     3.7 -        struct list_head tpmif_list;
     3.8 +	struct list_head tpmif_list;
     3.9  	/* Unique identifier for this interface. */
    3.10  	domid_t domid;
    3.11  	unsigned int handle;
    3.12 @@ -83,6 +83,11 @@ extern int num_frontends;
    3.13  
    3.14  #define MMAP_VADDR(t,_req) ((t)->mmap_vstart + ((_req) * PAGE_SIZE))
    3.15  
    3.16 +#ifndef TRUE
    3.17 +#define TRUE 1
    3.18 +#define FALSE 0
    3.19 +#endif
    3.20 +
    3.21  #endif /* __TPMIF__BACKEND__COMMON_H__ */
    3.22  
    3.23  /*
     4.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c	Thu Nov 24 23:21:48 2005 +0100
     4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c	Fri Nov 25 09:14:01 2005 +0100
     4.3 @@ -127,6 +127,10 @@ tpmif_map(tpmif_t *tpmif, unsigned long 
     4.4  		.u.bind_interdomain.remote_dom = tpmif->domid,
     4.5  		.u.bind_interdomain.remote_port = evtchn };
     4.6  
     4.7 +        if (tpmif->irq) {
     4.8 +                return 0;
     4.9 +        }
    4.10 +
    4.11  	if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL)
    4.12  		return -ENOMEM;
    4.13  
    4.14 @@ -149,7 +153,6 @@ tpmif_map(tpmif_t *tpmif, unsigned long 
    4.15  
    4.16  	tpmif->irq = bind_evtchn_to_irqhandler(
    4.17  		tpmif->evtchn, tpmif_be_int, 0, "tpmif-backend", tpmif);
    4.18 -	tpmif->status = CONNECTED;
    4.19  	tpmif->shmem_ref = shared_page;
    4.20  	tpmif->active = 1;
    4.21  
     5.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c	Thu Nov 24 23:21:48 2005 +0100
     5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c	Fri Nov 25 09:14:01 2005 +0100
     5.3 @@ -1,4 +1,5 @@
     5.4  /*  Xenbus code for tpmif backend
     5.5 +    Copyright (C) 2005 IBM Corporation
     5.6      Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
     5.7  
     5.8      This program is free software; you can redistribute it and/or modify
     5.9 @@ -29,72 +30,189 @@ struct backend_info
    5.10  
    5.11  	long int frontend_id;
    5.12  	long int instance; // instance of TPM
    5.13 +	u8 is_instance_set;// whether instance number has been set
    5.14  
    5.15  	/* watch front end for changes */
    5.16  	struct xenbus_watch backend_watch;
    5.17 +	XenbusState frontend_state;
    5.18 +};
    5.19  
    5.20 -	struct xenbus_watch watch;
    5.21 -	char * frontpath;
    5.22 -};
    5.23 +static void maybe_connect(struct backend_info *be);
    5.24 +static void connect(struct backend_info *be);
    5.25 +static int connect_ring(struct backend_info *be);
    5.26 +static void backend_changed(struct xenbus_watch *watch,
    5.27 +                            const char **vec, unsigned int len);
    5.28 +static void frontend_changed(struct xenbus_device *dev,
    5.29 +                             XenbusState frontend_state);
    5.30  
    5.31  static int tpmback_remove(struct xenbus_device *dev)
    5.32  {
    5.33  	struct backend_info *be = dev->data;
    5.34  
    5.35 -	if (be->watch.node)
    5.36 -		unregister_xenbus_watch(&be->watch);
    5.37 -	unregister_xenbus_watch(&be->backend_watch);
    5.38 +	if (be->backend_watch.node) {
    5.39 +		unregister_xenbus_watch(&be->backend_watch);
    5.40 +		kfree(be->backend_watch.node);
    5.41 +		be->backend_watch.node = NULL;
    5.42 +	}
    5.43 +	if (be->tpmif) {
    5.44 +		tpmif_put(be->tpmif);
    5.45 +		be->tpmif = NULL;
    5.46 +	}
    5.47 +	kfree(be);
    5.48 +	dev->data = NULL;
    5.49 +	return 0;
    5.50 +}
    5.51  
    5.52 -	tpmif_vtpm_close(be->instance);
    5.53 +static int tpmback_probe(struct xenbus_device *dev,
    5.54 +                         const struct xenbus_device_id *id)
    5.55 +{
    5.56 +	int err;
    5.57 +	struct backend_info *be = kmalloc(sizeof(struct backend_info),
    5.58 +	                                  GFP_KERNEL);
    5.59  
    5.60 -	if (be->tpmif)
    5.61 -		tpmif_put(be->tpmif);
    5.62 +	if (!be) {
    5.63 +		xenbus_dev_fatal(dev, -ENOMEM,
    5.64 +		                 "allocating backend structure");
    5.65 +		return -ENOMEM;
    5.66 +	}
    5.67 +
    5.68 +	memset(be, 0, sizeof(*be));
    5.69 +
    5.70 +	be->is_instance_set = FALSE;
    5.71 +	be->dev = dev;
    5.72 +	dev->data = be;
    5.73  
    5.74 -	kfree(be->frontpath);
    5.75 -	kfree(be);
    5.76 +	err = xenbus_watch_path2(dev, dev->nodename,
    5.77 +	                        "instance", &be->backend_watch,
    5.78 +	                        backend_changed);
    5.79 +	if (err) {
    5.80 +		goto fail;
    5.81 +	}
    5.82 +
    5.83 +	err = xenbus_switch_state(dev, NULL, XenbusStateInitWait);
    5.84 +	if (err) {
    5.85 +		goto fail;
    5.86 +	}
    5.87  	return 0;
    5.88 +fail:
    5.89 +	tpmback_remove(dev);
    5.90 +	return err;
    5.91  }
    5.92  
    5.93  
    5.94 -static void frontend_changed(struct xenbus_watch *watch,
    5.95 -			     const char **vec, unsigned int len)
    5.96 +static void backend_changed(struct xenbus_watch *watch,
    5.97 +                            const char **vec, unsigned int len)
    5.98  {
    5.99 -	unsigned long ringref;
   5.100 -	unsigned int evtchn;
   5.101 -	unsigned long ready = 1;
   5.102  	int err;
   5.103 -	struct xenbus_transaction *xbt;
   5.104 +	long instance;
   5.105  	struct backend_info *be
   5.106 -		= container_of(watch, struct backend_info, watch);
   5.107 +		= container_of(watch, struct backend_info, backend_watch);
   5.108 +	struct xenbus_device *dev = be->dev;
   5.109 +
   5.110 +	err = xenbus_scanf(NULL, dev->nodename,
   5.111 +	                   "instance","%li", &instance);
   5.112 +	if (XENBUS_EXIST_ERR(err)) {
   5.113 +		return;
   5.114 +	}
   5.115  
   5.116 -	/* If other end is gone, delete ourself. */
   5.117 -	if (vec && !xenbus_exists(NULL, be->frontpath, "")) {
   5.118 -		xenbus_rm(NULL, be->dev->nodename, "");
   5.119 -		device_unregister(&be->dev->dev);
   5.120 +	if (err != 1) {
   5.121 +		xenbus_dev_fatal(dev, err, "reading instance");
   5.122 +		return;
   5.123 +	}
   5.124 +
   5.125 +	if (be->is_instance_set != FALSE && be->instance != instance) {
   5.126 +		printk(KERN_WARNING
   5.127 +		       "tpmback: changing instance (from %ld to %ld) "
   5.128 +		       "not allowed.\n",
   5.129 +		       be->instance, instance);
   5.130  		return;
   5.131  	}
   5.132  
   5.133 +	if (be->is_instance_set == FALSE) {
   5.134 +		be->tpmif = tpmif_find(dev->otherend_id,
   5.135 +		                       instance);
   5.136 +		if (IS_ERR(be->tpmif)) {
   5.137 +			err = PTR_ERR(be->tpmif);
   5.138 +			be->tpmif = NULL;
   5.139 +			xenbus_dev_fatal(dev,err,"creating block interface");
   5.140 +			return;
   5.141 +		}
   5.142 +		be->instance = instance;
   5.143 +		be->is_instance_set = TRUE;
   5.144 +
   5.145 +		/*
   5.146 +		 * There's an unfortunate problem:
   5.147 +		 * Sometimes after a suspend/resume the
   5.148 +		 * state switch to XenbusStateInitialised happens
   5.149 +		 * *before* I get to this point here. Since then
   5.150 +		 * the connect_ring() must have failed (be->tpmif is
   5.151 +		 * still NULL), I just call it here again indirectly.
   5.152 +		 */
   5.153 +		if (be->frontend_state == XenbusStateInitialised) {
   5.154 +			frontend_changed(dev, be->frontend_state);
   5.155 +		}
   5.156 +	}
   5.157 +}
   5.158 +
   5.159 +
   5.160 +static void frontend_changed(struct xenbus_device *dev,
   5.161 +                             XenbusState frontend_state)
   5.162 +{
   5.163 +	struct backend_info *be = dev->data;
   5.164 +	int err;
   5.165 +
   5.166 +	be->frontend_state = frontend_state;
   5.167 +
   5.168 +	switch (frontend_state) {
   5.169 +	case XenbusStateInitialising:
   5.170 +	case XenbusStateConnected:
   5.171 +		break;
   5.172 +
   5.173 +	case XenbusStateInitialised:
   5.174 +		err = connect_ring(be);
   5.175 +		if (err) {
   5.176 +			return;
   5.177 +		}
   5.178 +		maybe_connect(be);
   5.179 +		break;
   5.180 +
   5.181 +	case XenbusStateClosing:
   5.182 +		xenbus_switch_state(dev, NULL, XenbusStateClosing);
   5.183 +		break;
   5.184 +
   5.185 +	case XenbusStateClosed:
   5.186 +		/*
   5.187 +		 * Notify the vTPM manager about the front-end
   5.188 +		 * having left.
   5.189 +		 */
   5.190 +		tpmif_vtpm_close(be->instance);
   5.191 +		device_unregister(&be->dev->dev);
   5.192 +		break;
   5.193 +
   5.194 +	case XenbusStateUnknown:
   5.195 +	case XenbusStateInitWait:
   5.196 +	default:
   5.197 +		xenbus_dev_fatal(dev, -EINVAL,
   5.198 +		                 "saw state %d at frontend",
   5.199 +		                 frontend_state);
   5.200 +		break;
   5.201 +	}
   5.202 +}
   5.203 +
   5.204 +
   5.205 +
   5.206 +static void maybe_connect(struct backend_info *be)
   5.207 +{
   5.208 +	int err;
   5.209 +
   5.210  	if (be->tpmif == NULL || be->tpmif->status == CONNECTED)
   5.211  		return;
   5.212  
   5.213 -	err = xenbus_gather(NULL, be->frontpath,
   5.214 -	                    "ring-ref", "%lu", &ringref,
   5.215 -			    "event-channel", "%u", &evtchn, NULL);
   5.216 -	if (err) {
   5.217 -		xenbus_dev_error(be->dev, err,
   5.218 -				 "reading %s/ring-ref and event-channel",
   5.219 -				 be->frontpath);
   5.220 -		return;
   5.221 -	}
   5.222 +	connect(be);
   5.223  
   5.224 -	err = tpmif_map(be->tpmif, ringref, evtchn);
   5.225 -	if (err) {
   5.226 -		xenbus_dev_error(be->dev, err,
   5.227 -				 "mapping shared-frame %lu port %u",
   5.228 -				 ringref, evtchn);
   5.229 -		return;
   5.230 -	}
   5.231 -
   5.232 +	/*
   5.233 +	 * Notify the vTPM manager about a new front-end.
   5.234 +	 */
   5.235  	err = tpmif_vtpm_open(be->tpmif,
   5.236  	                      be->frontend_id,
   5.237  	                      be->instance);
   5.238 @@ -107,157 +225,75 @@ static void frontend_changed(struct xenb
   5.239  		 */
   5.240  		return;
   5.241  	}
   5.242 +}
   5.243  
   5.244 -	/*
   5.245 -	 * Tell the front-end that we are ready to go -
   5.246 -	 * unless something bad happens
   5.247 -	 */
   5.248 +
   5.249 +static void connect(struct backend_info *be)
   5.250 +{
   5.251 +	struct xenbus_transaction *xbt;
   5.252 +	int err;
   5.253 +	struct xenbus_device *dev = be->dev;
   5.254 +	unsigned long ready = 1;
   5.255 +
   5.256  again:
   5.257  	xbt = xenbus_transaction_start();
   5.258  	if (IS_ERR(xbt)) {
   5.259 -		xenbus_dev_error(be->dev, err, "starting transaction");
   5.260 +		err = PTR_ERR(xbt);
   5.261 +		xenbus_dev_fatal(be->dev, err, "starting transaction");
   5.262  		return;
   5.263  	}
   5.264  
   5.265  	err = xenbus_printf(xbt, be->dev->nodename,
   5.266  	                    "ready", "%lu", ready);
   5.267  	if (err) {
   5.268 -		xenbus_dev_error(be->dev, err, "writing 'ready'");
   5.269 +		xenbus_dev_fatal(be->dev, err, "writing 'ready'");
   5.270  		goto abort;
   5.271  	}
   5.272  
   5.273 +	err = xenbus_switch_state(dev, xbt, XenbusStateConnected);
   5.274 +	if (err)
   5.275 +		goto abort;
   5.276 +
   5.277 +	be->tpmif->status = CONNECTED;
   5.278 +
   5.279  	err = xenbus_transaction_end(xbt, 0);
   5.280  	if (err == -EAGAIN)
   5.281  		goto again;
   5.282  	if (err) {
   5.283 -		xenbus_dev_error(be->dev, err, "end of transaction");
   5.284 -		goto abort;
   5.285 +		xenbus_dev_fatal(be->dev, err, "end of transaction");
   5.286  	}
   5.287 -
   5.288 -	xenbus_dev_ok(be->dev);
   5.289  	return;
   5.290  abort:
   5.291  	xenbus_transaction_end(xbt, 1);
   5.292  }
   5.293  
   5.294  
   5.295 -static void backend_changed(struct xenbus_watch *watch,
   5.296 -			    const char **vec, unsigned int len)
   5.297 +static int connect_ring(struct backend_info *be)
   5.298  {
   5.299 -	int err;
   5.300 -	long int instance;
   5.301 -	struct backend_info *be
   5.302 -		= container_of(watch, struct backend_info, backend_watch);
   5.303  	struct xenbus_device *dev = be->dev;
   5.304 -
   5.305 -	err = xenbus_scanf(NULL, dev->nodename, "instance", "%li", &instance);
   5.306 -	if (XENBUS_EXIST_ERR(err))
   5.307 -		return;
   5.308 -	if (err < 0) {
   5.309 -		xenbus_dev_error(dev, err, "reading 'instance' variable");
   5.310 -		return;
   5.311 -	}
   5.312 -
   5.313 -	if (be->instance != -1 && be->instance != instance) {
   5.314 -		printk(KERN_WARNING
   5.315 -		       "cannot change the instance\n");
   5.316 -		return;
   5.317 -	}
   5.318 -	be->instance = instance;
   5.319 -
   5.320 -	if (be->tpmif == NULL) {
   5.321 -		unsigned int len = max(XS_WATCH_PATH, XS_WATCH_TOKEN) + 1;
   5.322 -		const char *vec[len];
   5.323 -
   5.324 -		be->tpmif = tpmif_find(be->frontend_id,
   5.325 -		                       instance);
   5.326 -		if (IS_ERR(be->tpmif)) {
   5.327 -			err = PTR_ERR(be->tpmif);
   5.328 -			be->tpmif = NULL;
   5.329 -			xenbus_dev_error(dev, err, "creating interface");
   5.330 -			return;
   5.331 -		}
   5.332 -
   5.333 -		vec[XS_WATCH_PATH] = be->frontpath;
   5.334 -		vec[XS_WATCH_TOKEN] = NULL;
   5.335 -
   5.336 -		/* Pass in NULL node to skip exist test. */
   5.337 -		frontend_changed(&be->watch, vec, len);
   5.338 -	}
   5.339 -}
   5.340 -
   5.341 -
   5.342 -static int tpmback_probe(struct xenbus_device *dev,
   5.343 -			 const struct xenbus_device_id *id)
   5.344 -{
   5.345 -	struct backend_info *be;
   5.346 -	char *frontend;
   5.347 +	unsigned long ring_ref;
   5.348 +	unsigned int evtchn;
   5.349  	int err;
   5.350  
   5.351 -	be = kmalloc(sizeof(*be), GFP_KERNEL);
   5.352 -	if (!be) {
   5.353 -		xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
   5.354 -		err = -ENOMEM;
   5.355 -	}
   5.356 -
   5.357 -	memset(be, 0, sizeof(*be));
   5.358 -
   5.359 -	frontend = NULL;
   5.360 -	err = xenbus_gather(NULL, dev->nodename,
   5.361 -			    "frontend-id", "%li", &be->frontend_id,
   5.362 -			    "frontend", NULL, &frontend,
   5.363 -			    NULL);
   5.364 -	if (XENBUS_EXIST_ERR(err))
   5.365 -		goto free_be;
   5.366 -	if (err < 0) {
   5.367 +	err = xenbus_gather(NULL, dev->otherend,
   5.368 +	                    "ring-ref", "%lu", &ring_ref,
   5.369 +			    "event-channel", "%u", &evtchn, NULL);
   5.370 +	if (err) {
   5.371  		xenbus_dev_error(dev, err,
   5.372 -				 "reading %s/frontend or frontend-id",
   5.373 -				 dev->nodename);
   5.374 -		goto free_be;
   5.375 -	}
   5.376 -	if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) {
   5.377 -		/* If we can't get a frontend path and a frontend-id,
   5.378 -		 * then our bus-id is no longer valid and we need to
   5.379 -		 * destroy the backend device.
   5.380 -		 */
   5.381 -		err = -ENOENT;
   5.382 -		goto free_be;
   5.383 +				 "reading %s/ring-ref and event-channel",
   5.384 +				 dev->otherend);
   5.385 +		return err;
   5.386  	}
   5.387 -
   5.388 -	be->dev = dev;
   5.389 -	be->backend_watch.node     = dev->nodename;
   5.390 -	/* Implicitly calls backend_changed() once. */
   5.391 -	be->backend_watch.callback = backend_changed;
   5.392 -	be->instance = -1;
   5.393 -	err = register_xenbus_watch(&be->backend_watch);
   5.394 -	if (err) {
   5.395 -		be->backend_watch.node = NULL;
   5.396 -		xenbus_dev_error(dev, err, "adding backend watch on %s",
   5.397 -				 dev->nodename);
   5.398 -		goto free_be;
   5.399 +	if (be->tpmif != NULL) {
   5.400 +		err = tpmif_map(be->tpmif, ring_ref, evtchn);
   5.401 +		if (err) {
   5.402 +			xenbus_dev_error(dev, err,
   5.403 +			    	         "mapping shared-frame %lu port %u",
   5.404 +				         ring_ref, evtchn);
   5.405 +			return err;
   5.406 +		}
   5.407  	}
   5.408 -
   5.409 -	be->frontpath = frontend;
   5.410 -	be->watch.node = be->frontpath;
   5.411 -	be->watch.callback = frontend_changed;
   5.412 -	err = register_xenbus_watch(&be->watch);
   5.413 -	if (err) {
   5.414 -		be->watch.node = NULL;
   5.415 -		xenbus_dev_error(dev, err,
   5.416 -				 "adding frontend watch on %s",
   5.417 -				 be->frontpath);
   5.418 -		goto free_be;
   5.419 -	}
   5.420 -
   5.421 -	dev->data = be;
   5.422 -	return err;
   5.423 -
   5.424 -free_be:
   5.425 -	if (be->backend_watch.node)
   5.426 -		unregister_xenbus_watch(&be->backend_watch);
   5.427 -	kfree(frontend);
   5.428 -	kfree(be);
   5.429 -	return err;
   5.430 +	return 0;
   5.431  }
   5.432  
   5.433  
   5.434 @@ -273,6 +309,7 @@ static struct xenbus_driver tpmback = {
   5.435  	.ids = tpmback_ids,
   5.436  	.probe = tpmback_probe,
   5.437  	.remove = tpmback_remove,
   5.438 +	.otherend_changed = frontend_changed,
   5.439  };
   5.440  
   5.441  
     6.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c	Thu Nov 24 23:21:48 2005 +0100
     6.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c	Fri Nov 25 09:14:01 2005 +0100
     6.3 @@ -73,7 +73,8 @@ static void tpmif_rx_action(unsigned lon
     6.4  static void tpmif_connect(u16 evtchn, domid_t domid);
     6.5  static DECLARE_TASKLET(tpmif_rx_tasklet, tpmif_rx_action, 0);
     6.6  static int tpm_allocate_buffers(struct tpm_private *tp);
     6.7 -static void tpmif_set_connected_state(struct tpm_private *tp, int newstate);
     6.8 +static void tpmif_set_connected_state(struct tpm_private *tp,
     6.9 +                                      u8 newstate);
    6.10  static int tpm_xmit(struct tpm_private *tp,
    6.11                      const u8 * buf, size_t count, int userbuffer,
    6.12                      void *remember);
    6.13 @@ -212,87 +213,46 @@ static int tpm_fe_send_upperlayer(const 
    6.14   XENBUS support code
    6.15  **************************************************************/
    6.16  
    6.17 -static void watch_for_status(struct xenbus_watch *watch,
    6.18 -			     const char **vec, unsigned int len)
    6.19 -{
    6.20 -	struct tpmfront_info *info;
    6.21 -	int err;
    6.22 -	unsigned long ready;
    6.23 -	struct tpm_private *tp = &my_private;
    6.24 -	const char *node = vec[XS_WATCH_PATH];
    6.25 -
    6.26 -	info = container_of(watch, struct tpmfront_info, watch);
    6.27 -	node += strlen(watch->node);
    6.28 -
    6.29 -	if (tp->connected)
    6.30 -		return;
    6.31 -
    6.32 -	err = xenbus_gather(NULL, watch->node,
    6.33 -	                    "ready", "%lu", &ready,
    6.34 -	                    NULL);
    6.35 -	if (err) {
    6.36 -		xenbus_dev_error(info->dev, err, "reading 'ready' field");
    6.37 -		return;
    6.38 -	}
    6.39 -
    6.40 -	tpmif_set_connected_state(tp, 1);
    6.41 -
    6.42 -	xenbus_dev_ok(info->dev);
    6.43 -}
    6.44 -
    6.45 -
    6.46  static int setup_tpmring(struct xenbus_device *dev,
    6.47 -                         struct tpmfront_info * info,
    6.48 -                         domid_t backend_id)
    6.49 +                         struct tpmfront_info * info)
    6.50  {
    6.51  	tpmif_tx_interface_t *sring;
    6.52  	struct tpm_private *tp = &my_private;
    6.53  	int err;
    6.54 -	evtchn_op_t op = {
    6.55 -		.cmd = EVTCHNOP_alloc_unbound,
    6.56 -		.u.alloc_unbound.dom = DOMID_SELF,
    6.57 -		.u.alloc_unbound.remote_dom = backend_id } ;
    6.58  
    6.59  	sring = (void *)__get_free_page(GFP_KERNEL);
    6.60  	if (!sring) {
    6.61 -		xenbus_dev_error(dev, -ENOMEM, "allocating shared ring");
    6.62 +		xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
    6.63  		return -ENOMEM;
    6.64  	}
    6.65  	tp->tx = sring;
    6.66  
    6.67  	tpm_allocate_buffers(tp);
    6.68  
    6.69 -	err = gnttab_grant_foreign_access(backend_id,
    6.70 -					  (virt_to_machine(tp->tx) >> PAGE_SHIFT),
    6.71 -					  0);
    6.72 -
    6.73 -	if (err == -ENOSPC) {
    6.74 +	err = xenbus_grant_ring(dev, virt_to_mfn(tp->tx));
    6.75 +	if (err < 0) {
    6.76  		free_page((unsigned long)sring);
    6.77  		tp->tx = NULL;
    6.78 -		xenbus_dev_error(dev, err, "allocating grant reference");
    6.79 -		return err;
    6.80 +		xenbus_dev_fatal(dev, err, "allocating grant reference");
    6.81 +		goto fail;
    6.82  	}
    6.83  	info->ring_ref = err;
    6.84  
    6.85 -	err = HYPERVISOR_event_channel_op(&op);
    6.86 -	if (err) {
    6.87 -		gnttab_end_foreign_access(info->ring_ref, 0,
    6.88 -					  (unsigned long)sring);
    6.89 -		tp->tx = NULL;
    6.90 -		xenbus_dev_error(dev, err, "allocating event channel");
    6.91 -		return err;
    6.92 -	}
    6.93 +	err = xenbus_alloc_evtchn(dev, &tp->evtchn);
    6.94 +	if (err)
    6.95 +		goto fail;
    6.96  
    6.97 -	tpmif_connect(op.u.alloc_unbound.port, backend_id);
    6.98 +	tpmif_connect(tp->evtchn, dev->otherend_id);
    6.99  
   6.100  	return 0;
   6.101 +fail:
   6.102 +	return err;
   6.103  }
   6.104  
   6.105  
   6.106  static void destroy_tpmring(struct tpmfront_info *info, struct tpm_private *tp)
   6.107  {
   6.108 -	tpmif_set_connected_state(tp,0);
   6.109 -
   6.110 +	tpmif_set_connected_state(tp, FALSE);
   6.111  	if ( tp->tx != NULL ) {
   6.112  		gnttab_end_foreign_access(info->ring_ref, 0,
   6.113  					  (unsigned long)tp->tx);
   6.114 @@ -308,42 +268,20 @@ static void destroy_tpmring(struct tpmfr
   6.115  static int talk_to_backend(struct xenbus_device *dev,
   6.116                             struct tpmfront_info *info)
   6.117  {
   6.118 -	char *backend;
   6.119 -	const char *message;
   6.120 +	const char *message = NULL;
   6.121  	int err;
   6.122 -	int backend_id;
   6.123  	struct xenbus_transaction *xbt;
   6.124  
   6.125 -	backend = NULL;
   6.126 -	err = xenbus_gather(NULL, dev->nodename,
   6.127 -			    "backend-id", "%i", &backend_id,
   6.128 -			    "backend", NULL, &backend,
   6.129 -			    NULL);
   6.130 -	if (XENBUS_EXIST_ERR(err))
   6.131 -		goto out;
   6.132 -	if (backend && strlen(backend) == 0) {
   6.133 -		err = -ENOENT;
   6.134 -		goto out;
   6.135 -	}
   6.136 -	if (err < 0) {
   6.137 -		xenbus_dev_error(dev, err, "reading %s/backend or backend-id",
   6.138 -				 dev->nodename);
   6.139 -		goto out;
   6.140 -	}
   6.141 -
   6.142 -	info->backend_id      = backend_id;
   6.143 -	my_private.backend_id = backend_id;
   6.144 -
   6.145 -	err = setup_tpmring(dev, info, backend_id);
   6.146 +	err = setup_tpmring(dev, info);
   6.147  	if (err) {
   6.148 -		xenbus_dev_error(dev, err, "setting up ring");
   6.149 +		xenbus_dev_fatal(dev, err, "setting up ring");
   6.150  		goto out;
   6.151  	}
   6.152  
   6.153  again:
   6.154  	xbt = xenbus_transaction_start();
   6.155  	if (IS_ERR(xbt)) {
   6.156 -		xenbus_dev_error(dev, err, "starting transaction");
   6.157 +		xenbus_dev_fatal(dev, err, "starting transaction");
   6.158  		goto destroy_tpmring;
   6.159  	}
   6.160  
   6.161 @@ -361,36 +299,62 @@ again:
   6.162  		goto abort_transaction;
   6.163  	}
   6.164  
   6.165 +	err = xenbus_switch_state(dev, xbt, XenbusStateInitialised);
   6.166 +	if (err) {
   6.167 +		goto abort_transaction;
   6.168 +	}
   6.169 +
   6.170  	err = xenbus_transaction_end(xbt, 0);
   6.171  	if (err == -EAGAIN)
   6.172  		goto again;
   6.173  	if (err) {
   6.174 -		xenbus_dev_error(dev, err, "completing transaction");
   6.175 +		xenbus_dev_fatal(dev, err, "completing transaction");
   6.176  		goto destroy_tpmring;
   6.177  	}
   6.178 -
   6.179 -	info->watch.node = backend;
   6.180 -	info->watch.callback = watch_for_status;
   6.181 -	err = register_xenbus_watch(&info->watch);
   6.182 -	if (err) {
   6.183 -		xenbus_dev_error(dev, err, "registering watch on backend");
   6.184 -		goto destroy_tpmring;
   6.185 -	}
   6.186 -
   6.187 -	info->backend = backend;
   6.188 -
   6.189  	return 0;
   6.190  
   6.191  abort_transaction:
   6.192  	xenbus_transaction_end(xbt, 1);
   6.193 -	xenbus_dev_error(dev, err, "%s", message);
   6.194 +	if (message)
   6.195 +		xenbus_dev_error(dev, err, "%s", message);
   6.196  destroy_tpmring:
   6.197  	destroy_tpmring(info, &my_private);
   6.198  out:
   6.199 -	kfree(backend);
   6.200  	return err;
   6.201  }
   6.202  
   6.203 +/**
   6.204 + * Callback received when the backend's state changes.
   6.205 + */
   6.206 +static void backend_changed(struct xenbus_device *dev,
   6.207 +			    XenbusState backend_state)
   6.208 +{
   6.209 +	struct tpm_private *tp = &my_private;
   6.210 +	DPRINTK("\n");
   6.211 +
   6.212 +	switch (backend_state) {
   6.213 +	case XenbusStateInitialising:
   6.214 +	case XenbusStateInitWait:
   6.215 +	case XenbusStateInitialised:
   6.216 +	case XenbusStateUnknown:
   6.217 +		break;
   6.218 +
   6.219 +	case XenbusStateConnected:
   6.220 +		tpmif_set_connected_state(tp, TRUE);
   6.221 +		break;
   6.222 +
   6.223 +	case XenbusStateClosing:
   6.224 +		tpmif_set_connected_state(tp, FALSE);
   6.225 +		break;
   6.226 +
   6.227 +	case XenbusStateClosed:
   6.228 +        	if (tp->is_suspended == FALSE) {
   6.229 +        	        device_unregister(&dev->dev);
   6.230 +        	}
   6.231 +	        break;
   6.232 +	}
   6.233 +}
   6.234 +
   6.235  
   6.236  static int tpmfront_probe(struct xenbus_device *dev,
   6.237                            const struct xenbus_device_id *id)
   6.238 @@ -398,8 +362,6 @@ static int tpmfront_probe(struct xenbus_
   6.239  	int err;
   6.240  	struct tpmfront_info *info;
   6.241  	int handle;
   6.242 -	int len = max(XS_WATCH_PATH, XS_WATCH_TOKEN) + 1;
   6.243 -	const char *vec[len];
   6.244  
   6.245  	err = xenbus_scanf(NULL, dev->nodename,
   6.246  	                   "handle", "%i", &handle);
   6.247 @@ -407,19 +369,19 @@ static int tpmfront_probe(struct xenbus_
   6.248  		return err;
   6.249  
   6.250  	if (err < 0) {
   6.251 -		xenbus_dev_error(dev,err,"reading virtual-device");
   6.252 +		xenbus_dev_fatal(dev,err,"reading virtual-device");
   6.253  		return err;
   6.254  	}
   6.255  
   6.256  	info = kmalloc(sizeof(*info), GFP_KERNEL);
   6.257  	if (!info) {
   6.258 -		xenbus_dev_error(dev,err,"allocating info structure");
   6.259 +		err = -ENOMEM;
   6.260 +		xenbus_dev_fatal(dev,err,"allocating info structure");
   6.261  		return err;
   6.262  	}
   6.263  	memset(info, 0x0, sizeof(*info));
   6.264  
   6.265  	info->dev = dev;
   6.266 -	info->handle = handle;
   6.267  	dev->data = info;
   6.268  
   6.269  	err = talk_to_backend(dev, info);
   6.270 @@ -428,41 +390,33 @@ static int tpmfront_probe(struct xenbus_
   6.271  		dev->data = NULL;
   6.272  		return err;
   6.273  	}
   6.274 -
   6.275 -	vec[XS_WATCH_PATH]  = info->watch.node;
   6.276 -	vec[XS_WATCH_TOKEN] = NULL;
   6.277 -	watch_for_status(&info->watch, vec, len);
   6.278 -
   6.279  	return 0;
   6.280  }
   6.281  
   6.282 +
   6.283  static int tpmfront_remove(struct xenbus_device *dev)
   6.284  {
   6.285  	struct tpmfront_info *info = dev->data;
   6.286 -	if (info->backend)
   6.287 -		unregister_xenbus_watch(&info->watch);
   6.288  
   6.289  	destroy_tpmring(info, &my_private);
   6.290  
   6.291 -	kfree(info->backend);
   6.292  	kfree(info);
   6.293 -
   6.294  	return 0;
   6.295  }
   6.296  
   6.297  static int
   6.298  tpmfront_suspend(struct xenbus_device *dev)
   6.299  {
   6.300 -	struct tpmfront_info *info = dev->data;
   6.301  	struct tpm_private *tp = &my_private;
   6.302  	u32 ctr = 0;
   6.303  
   6.304  	/* lock, so no app can send */
   6.305  	down(&suspend_lock);
   6.306 +	tp->is_suspended = TRUE;
   6.307  
   6.308  	while (atomic_read(&tp->tx_busy) && ctr <= 25) {
   6.309 -	        if ((ctr % 10) == 0)
   6.310 -			printk("INFO: Waiting for outstanding request.\n");
   6.311 +		if ((ctr % 10) == 0)
   6.312 +			printk("TPM-FE [INFO]: Waiting for outstanding request.\n");
   6.313  		/*
   6.314  		 * Wait for a request to be responded to.
   6.315  		 */
   6.316 @@ -474,15 +428,10 @@ tpmfront_suspend(struct xenbus_device *d
   6.317  		/*
   6.318  		 * A temporary work-around.
   6.319  		 */
   6.320 -		printk("WARNING: Resetting busy flag.");
   6.321 +		printk("TPM-FE [WARNING]: Resetting busy flag.");
   6.322  		atomic_set(&tp->tx_busy, 0);
   6.323  	}
   6.324  
   6.325 -	unregister_xenbus_watch(&info->watch);
   6.326 -
   6.327 -	kfree(info->backend);
   6.328 -	info->backend = NULL;
   6.329 -
   6.330  	return 0;
   6.331  }
   6.332  
   6.333 @@ -492,8 +441,6 @@ tpmfront_resume(struct xenbus_device *de
   6.334  	struct tpmfront_info *info = dev->data;
   6.335  	int err = talk_to_backend(dev, info);
   6.336  
   6.337 -	/* unlock, so apps can resume sending */
   6.338 -	up(&suspend_lock);
   6.339  
   6.340  	return err;
   6.341  }
   6.342 @@ -530,12 +477,13 @@ static struct xenbus_driver tpmfront = {
   6.343  	.probe = tpmfront_probe,
   6.344  	.remove =  tpmfront_remove,
   6.345  	.resume = tpmfront_resume,
   6.346 +	.otherend_changed = backend_changed,
   6.347  	.suspend = tpmfront_suspend,
   6.348  };
   6.349  
   6.350  static void __init init_tpm_xenbus(void)
   6.351  {
   6.352 -	xenbus_register_driver(&tpmfront);
   6.353 +	xenbus_register_frontend(&tpmfront);
   6.354  }
   6.355  
   6.356  
   6.357 @@ -628,12 +576,13 @@ tpm_xmit(struct tpm_private *tp,
   6.358  	spin_lock_irq(&tp->tx_lock);
   6.359  
   6.360  	if (unlikely(atomic_read(&tp->tx_busy))) {
   6.361 -		printk("There's an outstanding request/response on the way!\n");
   6.362 +		printk("tpm_xmit: There's an outstanding request/response "
   6.363 +		       "on the way!\n");
   6.364  		spin_unlock_irq(&tp->tx_lock);
   6.365  		return -EBUSY;
   6.366  	}
   6.367  
   6.368 -	if (tp->connected != 1) {
   6.369 +	if (tp->is_connected != TRUE) {
   6.370  		spin_unlock_irq(&tp->tx_lock);
   6.371  		return -EIO;
   6.372  	}
   6.373 @@ -705,24 +654,40 @@ static void tpmif_notify_upperlayer(stru
   6.374  	down(&upperlayer_lock);
   6.375  
   6.376  	if (upperlayer_tpmfe != NULL) {
   6.377 -		switch (tp->connected) {
   6.378 -			case 1:
   6.379 -				upperlayer_tpmfe->status(TPMFE_STATUS_CONNECTED);
   6.380 -			break;
   6.381 -
   6.382 -			default:
   6.383 -				upperlayer_tpmfe->status(0);
   6.384 -			break;
   6.385 +		if (tp->is_connected) {
   6.386 +			upperlayer_tpmfe->status(TPMFE_STATUS_CONNECTED);
   6.387 +		} else {
   6.388 +			upperlayer_tpmfe->status(0);
   6.389  		}
   6.390  	}
   6.391  	up(&upperlayer_lock);
   6.392  }
   6.393  
   6.394  
   6.395 -static void tpmif_set_connected_state(struct tpm_private *tp, int newstate)
   6.396 +static void tpmif_set_connected_state(struct tpm_private *tp, u8 is_connected)
   6.397  {
   6.398 -	if (newstate != tp->connected) {
   6.399 -		tp->connected = newstate;
   6.400 +	/*
   6.401 +	 * Don't notify upper layer if we are in suspend mode and
   6.402 +	 * should disconnect - assumption is that we will resume
   6.403 +	 * The semaphore keeps apps from sending.
   6.404 +	 */
   6.405 +	if (is_connected == FALSE && tp->is_suspended == TRUE) {
   6.406 +		return;
   6.407 +	}
   6.408 +
   6.409 +	/*
   6.410 +	 * Unlock the semaphore if we are connected again
   6.411 +	 * after being suspended - now resuming.
   6.412 +	 * This also removes the suspend state.
   6.413 +	 */
   6.414 +	if (is_connected == TRUE && tp->is_suspended == TRUE) {
   6.415 +		tp->is_suspended = FALSE;
   6.416 +		/* unlock, so apps can resume sending */
   6.417 +		up(&suspend_lock);
   6.418 +	}
   6.419 +
   6.420 +	if (is_connected != tp->is_connected) {
   6.421 +		tp->is_connected = is_connected;
   6.422  		tpmif_notify_upperlayer(tp);
   6.423  	}
   6.424  }
     7.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h	Thu Nov 24 23:21:48 2005 +0100
     7.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h	Fri Nov 25 09:14:01 2005 +0100
     7.3 @@ -1,12 +1,17 @@
     7.4  #ifndef TPM_FRONT_H
     7.5  #define TPM_FRONT_H
     7.6  
     7.7 +#ifndef TRUE
     7.8 +#define TRUE 1
     7.9 +#define FALSE 0
    7.10 +#endif
    7.11  
    7.12 -struct tpm_private
    7.13 -{
    7.14 +struct tpm_private {
    7.15  	tpmif_tx_interface_t *tx;
    7.16 -	unsigned int evtchn, irq;
    7.17 -	int connected;
    7.18 +	unsigned int evtchn;
    7.19 +	unsigned int irq;
    7.20 +	u8 is_connected;
    7.21 +	u8 is_suspended;
    7.22  
    7.23  	spinlock_t tx_lock;
    7.24  
    7.25 @@ -16,25 +21,18 @@ struct tpm_private
    7.26  	void *tx_remember;
    7.27  	domid_t backend_id;
    7.28  	wait_queue_head_t wait_q;
    7.29 +
    7.30  };
    7.31  
    7.32 -
    7.33 -struct tpmfront_info
    7.34 -{
    7.35 -	struct xenbus_watch watch;
    7.36 -	int handle;
    7.37 +struct tpmfront_info {
    7.38  	struct xenbus_device *dev;
    7.39 -	char *backend;
    7.40  	int ring_ref;
    7.41 -	domid_t backend_id;
    7.42  };
    7.43  
    7.44 -
    7.45 -struct tx_buffer
    7.46 -{
    7.47 +struct tx_buffer {
    7.48  	unsigned int size;	// available space in data
    7.49  	unsigned int len;	// used space in data
    7.50 -	unsigned char *data;    // pointer to a page
    7.51 +	unsigned char *data;	// pointer to a page
    7.52  };
    7.53  
    7.54  #endif
     8.1 --- a/tools/examples/Makefile	Thu Nov 24 23:21:48 2005 +0100
     8.2 +++ b/tools/examples/Makefile	Fri Nov 25 09:14:01 2005 +0100
     8.3 @@ -26,9 +26,10 @@ XEN_SCRIPTS += network-route vif-route
     8.4  XEN_SCRIPTS += network-nat vif-nat
     8.5  XEN_SCRIPTS += block
     8.6  XEN_SCRIPTS += block-enbd block-nbd
     8.7 +XEN_SCRIPTS += vtpm
     8.8  XEN_SCRIPT_DATA = xen-script-common.sh
     8.9  XEN_SCRIPT_DATA += xen-hotplug-common.sh xen-network-common.sh vif-common.sh
    8.10 -XEN_SCRIPT_DATA += block-common.sh
    8.11 +XEN_SCRIPT_DATA += block-common.sh vtpm-common.sh
    8.12  
    8.13  XEN_HOTPLUG_DIR = /etc/hotplug
    8.14  XEN_HOTPLUG_SCRIPTS = xen-backend.agent
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/examples/vtpm	Fri Nov 25 09:14:01 2005 +0100
     9.3 @@ -0,0 +1,23 @@
     9.4 +#!/bin/sh
     9.5 +
     9.6 +dir=$(dirname "$0")
     9.7 +. "$dir/vtpm-common.sh"
     9.8 +
     9.9 +
    9.10 +case "$command" in
    9.11 +    online | offline)
    9.12 +        exit 0
    9.13 +        ;;
    9.14 +esac
    9.15 +
    9.16 +case "$command" in
    9.17 +  add)
    9.18 +    vtpm_create_instance
    9.19 +  ;;
    9.20 +  remove)
    9.21 +    vtpm_remove_instance
    9.22 +  ;;
    9.23 +esac
    9.24 +
    9.25 +log debug "Successful vTPM operation '$command'."
    9.26 +success
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/examples/vtpm-common.sh	Fri Nov 25 09:14:01 2005 +0100
    10.3 @@ -0,0 +1,281 @@
    10.4 +#
    10.5 +# Copyright (c) 2005 IBM Corporation
    10.6 +# Copyright (c) 2005 XenSource Ltd.
    10.7 +#
    10.8 +# This library is free software; you can redistribute it and/or
    10.9 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
   10.10 +# License as published by the Free Software Foundation.
   10.11 +#
   10.12 +# This library is distributed in the hope that it will be useful,
   10.13 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.14 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   10.15 +# Lesser General Public License for more details.
   10.16 +#
   10.17 +# You should have received a copy of the GNU Lesser General Public
   10.18 +# License along with this library; if not, write to the Free Software
   10.19 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   10.20 +#
   10.21 +
   10.22 +dir=$(dirname "$0")
   10.23 +. "$dir/xen-hotplug-common.sh"
   10.24 +
   10.25 +findCommand "$@"
   10.26 +if [ "$command" != "online" ]  &&
   10.27 +   [ "$command" != "offline" ] &&
   10.28 +   [ "$command" != "add" ]     &&
   10.29 +   [ "$command" != "remove" ]
   10.30 +then
   10.31 +	log err "Invalid command: $command"
   10.32 +	exit 1
   10.33 +fi
   10.34 +
   10.35 +
   10.36 +XENBUS_PATH="${XENBUS_PATH:?}"
   10.37 +
   10.38 +
   10.39 +VTPMDB="/etc/xen/vtpm.db"
   10.40 +
   10.41 +#In the vtpm-impl file some commands should be defined:
   10.42 +#      vtpm_create, vtpm_setup, vtpm_reset, etc. (see below)
   10.43 +#This should be indicated by setting VTPM_IMPL_DEFINED.
   10.44 +if [ -r "$dir/vtpm-impl" ]; then
   10.45 +	. "$dir/vtpm-impl"
   10.46 +fi
   10.47 +
   10.48 +if [ -z "$VTPM_IMPL_DEFINED" ]; then
   10.49 +	function vtpm_create () {
   10.50 +		true
   10.51 +	}
   10.52 +	function vtpm_setup() {
   10.53 +		true
   10.54 +	}
   10.55 +	function vtpm_reset() {
   10.56 +		true
   10.57 +	}
   10.58 +	function vtpm_suspend() {
   10.59 +		true
   10.60 +	}
   10.61 +	function vtpm_resume() {
   10.62 +		true
   10.63 +	}
   10.64 +fi
   10.65 +
   10.66 +#Find the instance number for the vtpm given the name of the domain
   10.67 +# Parameters
   10.68 +# - vmname : the name of the vm
   10.69 +# Return value
   10.70 +#  Returns '0' if instance number could not be found, otherwise
   10.71 +#  it returns the instance number in the variable 'instance'
   10.72 +function find_instance () {
   10.73 +	local vmname=$1
   10.74 +	local ret=0
   10.75 +	instance=`cat $VTPMDB |                    \
   10.76 +	          awk -vvmname=$vmname             \
   10.77 +	          '{                               \
   10.78 +	             if ( 1 != index($1,"#")) {    \
   10.79 +	               if ( $1 == vmname ) {       \
   10.80 +	                 print $2;                 \
   10.81 +	                 exit;                     \
   10.82 +	               }                           \
   10.83 +	             }                             \
   10.84 +	           }'`
   10.85 +	if [ "$instance" != "" ]; then
   10.86 +		ret=1
   10.87 +	fi
   10.88 +	return $ret
   10.89 +}
   10.90 +
   10.91 +
   10.92 +# Check whether a particular instance number is still available
   10.93 +# returns '1' if it is available
   10.94 +function is_free_instancenum () {
   10.95 +	local instance=$1
   10.96 +	local avail=1
   10.97 +
   10.98 +	#Allowed instance number range: 1-255
   10.99 +	if [ $instance -eq 0 -o $instance -gt 255 ]; then
  10.100 +		avail=0
  10.101 +	else
  10.102 +		instances=`cat $VTPMDB |                 \
  10.103 +		           gawk                          \
  10.104 +		           '{                            \
  10.105 +		               if (1 != index($1,"#")) { \
  10.106 +		                 printf("%s ",$2);       \
  10.107 +		               }                         \
  10.108 +		            }'`
  10.109 +		for i in $instances; do
  10.110 +			if [ $i -eq $instance ]; then
  10.111 +				avail=0
  10.112 +				break
  10.113 +			fi
  10.114 +		done
  10.115 +	fi
  10.116 +	return $avail
  10.117 +}
  10.118 +
  10.119 +
  10.120 +# Get an available instance number given the database
  10.121 +# Returns an unused instance number
  10.122 +function get_free_instancenum () {
  10.123 +	local ctr
  10.124 +	local instances
  10.125 +	local don
  10.126 +	instances=`cat $VTPMDB |                 \
  10.127 +	           gawk                          \
  10.128 +	           '{                            \
  10.129 +	               if (1 != index($1,"#")) { \
  10.130 +	                 printf("%s ",$2);       \
  10.131 +	               }                         \
  10.132 +	            }'`
  10.133 +	ctr=1
  10.134 +	don=0
  10.135 +	while [ $don -eq 0 ]; do
  10.136 +		local found
  10.137 +		found=0
  10.138 +		for i in $instances; do
  10.139 +			if [ $i -eq $ctr ]; then
  10.140 +				found=1;
  10.141 +				break;
  10.142 +			fi
  10.143 +		done
  10.144 +
  10.145 +		if [ $found -eq 0 ]; then
  10.146 +			don=1
  10.147 +			break
  10.148 +		fi
  10.149 +		let ctr=ctr+1
  10.150 +	done
  10.151 +	let instance=$ctr
  10.152 +}
  10.153 +
  10.154 +
  10.155 +# Add a domain name and instance number to the DB file
  10.156 +function add_instance () {
  10.157 +	local vmname=$1
  10.158 +	local inst=$2
  10.159 +
  10.160 +	if [ ! -f $VTPMDB ]; then
  10.161 +		echo "#Database for VM to vTPM association" > $VTPMDB
  10.162 +		echo "#1st column: domain name" >> $VTPMDB
  10.163 +		echo "#2nd column: TPM instance number" >> $VTPMDB
  10.164 +	fi
  10.165 +	validate_entry $vmname $inst
  10.166 +	if [ $? -eq 0 ]; then
  10.167 +		echo "$vmname $inst" >> $VTPMDB
  10.168 +	fi
  10.169 +}
  10.170 +
  10.171 +
  10.172 +#Validate whether an entry is the same as passed to this
  10.173 +#function
  10.174 +function validate_entry () {
  10.175 +	local rc=0
  10.176 +	local vmname=$1
  10.177 +	local inst=$2
  10.178 +	local res
  10.179 +	res=`cat $VTPMDB |             \
  10.180 +	     gawk -vvmname=$vmname     \
  10.181 +	          -vinst=$inst         \
  10.182 +	     '{                        \
  10.183 +	         if ( 1 == index($1,"#")) {\
  10.184 +	         } else                \
  10.185 +	         if ( $1 == vmname &&  \
  10.186 +	              $2 == inst) {    \
  10.187 +	            printf("1");       \
  10.188 +	            exit;              \
  10.189 +	         } else                \
  10.190 +	         if ( $1 == vmname ||  \
  10.191 +	              $2 == inst) {    \
  10.192 +	            printf("2");       \
  10.193 +	            exit;              \
  10.194 +	         }                     \
  10.195 +	     }'`
  10.196 +
  10.197 +	if [ "$res" == "1" ]; then
  10.198 +		let rc=1
  10.199 +	elif [ "$res" == "2" ]; then
  10.200 +		let rc=2
  10.201 +	fi
  10.202 +	return $rc
  10.203 +}
  10.204 +
  10.205 +
  10.206 +#Remove an entry from the vTPM database given its domain name
  10.207 +function remove_entry () {
  10.208 +	local vmname=$1
  10.209 +	local VTPMDB_TMP="$VTPMDB".tmp
  10.210 +	`cat $VTPMDB |             \
  10.211 +	 gawk -vvmname=$vmname     \
  10.212 +	 '{                        \
  10.213 +	    if ( $1 != vmname ) {  \
  10.214 +	      print $0;            \
  10.215 +	    }                      \
  10.216 +	 '} > $VTPMDB_TMP`
  10.217 +	if [ -e $VTPMDB_TMP ]; then
  10.218 +		mv -f $VTPMDB_TMP $VTPMDB
  10.219 +	else
  10.220 +		log err "Error creating temporary file '$VTPMDB_TMP'."
  10.221 +	fi
  10.222 +}
  10.223 +
  10.224 +
  10.225 +#Create a vTPM instance
  10.226 +# If no entry in the TPM database is found, the instance is
  10.227 +# created and an entry added to the database.
  10.228 +function vtpm_create_instance () {
  10.229 +	local domname=$(xenstore_read "$XENBUS_PATH"/domain)
  10.230 +	local res
  10.231 +	set +e
  10.232 +	find_instance $domname
  10.233 +	res=$?
  10.234 +	if [ $res -eq 0 ]; then
  10.235 +		#Try to give the preferred instance to the domain
  10.236 +		instance=$(xenstore_read "$XENBUS_PATH"/pref_instance)
  10.237 +		if [ "$instance" != "" ]; then
  10.238 +			is_free_instancenum $instance
  10.239 +			res=$?
  10.240 +			if [ $res -eq 0 ]; then
  10.241 +				get_free_instancenum
  10.242 +			fi
  10.243 +		else
  10.244 +			get_free_instancenum
  10.245 +		fi
  10.246 +		add_instance $domname $instance
  10.247 +		if [ "$REASON" == "create" ]; then
  10.248 +			vtpm_create $instance
  10.249 +		elif [ "$REASON" == "hibernate" ]; then
  10.250 +			vtpm_resume $instance $domname
  10.251 +		else
  10.252 +			#default case for 'now'
  10.253 +			vtpm_create $instance
  10.254 +		fi
  10.255 +	fi
  10.256 +	if [ "$REASON" == "create" ]; then
  10.257 +		vtpm_reset $instance
  10.258 +	elif [ "$REASON" == "hibernate" ]; then
  10.259 +		vtpm_setup $instance
  10.260 +	else
  10.261 +		#default case for 'now'
  10.262 +		vtpm_reset $instance
  10.263 +	fi
  10.264 +	xenstore_write $XENBUS_PATH/instance $instance
  10.265 +	set -e
  10.266 +}
  10.267 +
  10.268 +
  10.269 +#Remove an instance
  10.270 +function vtpm_remove_instance () {
  10.271 +	local domname=$(xenstore_read "$XENBUS_PATH"/domain)
  10.272 +	set +e
  10.273 +	find_instance $domname
  10.274 +	res=$?
  10.275 +	if [ $res -eq 0 ]; then
  10.276 +		#Something is really wrong with the DB
  10.277 +		log err "vTPM DB file $VTPMDB has no entry for '$domname'"
  10.278 +	else
  10.279 +		if [ "$REASON" == "hibernate" ]; then
  10.280 +			vtpm_suspend $instance
  10.281 +		fi
  10.282 +	fi
  10.283 +	set -e
  10.284 +}
    11.1 --- a/tools/examples/xen-backend.agent	Thu Nov 24 23:21:48 2005 +0100
    11.2 +++ b/tools/examples/xen-backend.agent	Fri Nov 25 09:14:01 2005 +0100
    11.3 @@ -6,6 +6,9 @@ case "$XENBUS_TYPE" in
    11.4    vbd)
    11.5      /etc/xen/scripts/block "$ACTION"
    11.6      ;;
    11.7 +  vtpm)
    11.8 +    /etc/xen/scripts/vtpm "$ACTION"
    11.9 +    ;;
   11.10    vif)
   11.11      [ -n "$script" ] && $script "$ACTION"
   11.12      ;;
    12.1 --- a/tools/examples/xen-backend.rules	Thu Nov 24 23:21:48 2005 +0100
    12.2 +++ b/tools/examples/xen-backend.rules	Fri Nov 25 09:14:01 2005 +0100
    12.3 @@ -1,4 +1,5 @@
    12.4  SUBSYSTEM=="xen-backend", KERNEL=="vbd*", RUN+="/etc/xen/scripts/block $env{ACTION}"
    12.5 +SUBSYSTEM=="xen-backend", KERNEL=="vtpm*", RUN+="/etc/xen/scripts/vtpm $env{ACTION}"
    12.6  SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="online", RUN+="$env{script} online"
    12.7  SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="offline", RUN+="$env{script} offline"
    12.8  SUBSYSTEM=="xen-backend", ACTION=="remove", RUN+="/bin/bash -c '/usr/bin/xenstore-rm -t $$(/usr/bin/xenstore-read $env{XENBUS_PATH}/frontend)'"
    13.1 --- a/tools/python/xen/xend/image.py	Thu Nov 24 23:21:48 2005 +0100
    13.2 +++ b/tools/python/xen/xend/image.py	Fri Nov 25 09:14:01 2005 +0100
    13.3 @@ -293,7 +293,7 @@ class VmxImageHandler(ImageHandler):
    13.4                 ret.append("-bridge")
    13.5                 ret.append("%s" % bridge)
    13.6              if name == 'vtpm':
    13.7 -               instance = sxp.child_value(info, 'instance')
    13.8 +               instance = sxp.child_value(info, 'pref_instance')
    13.9                 ret.append("-instance")
   13.10                 ret.append("%s" % instance)
   13.11          return ret
    14.1 --- a/tools/python/xen/xend/server/tpmif.py	Thu Nov 24 23:21:48 2005 +0100
    14.2 +++ b/tools/python/xen/xend/server/tpmif.py	Fri Nov 25 09:14:01 2005 +0100
    14.3 @@ -38,10 +38,10 @@ class TPMifController(DevController):
    14.4      def getDeviceDetails(self, config):
    14.5          """@see DevController.getDeviceDetails"""
    14.6  
    14.7 -        devid = int(sxp.child_value(config, 'instance', '0'))
    14.8 +        devid = int(sxp.child_value(config, 'pref_instance', '0'))
    14.9          log.info("The domain has a TPM with instance %d." % devid)
   14.10  
   14.11 -        back  = { 'instance' : "%i" % devid }
   14.12 +        back  = { 'pref_instance' : "%i" % devid }
   14.13          front = { 'handle' : "%i" % devid }
   14.14  
   14.15          return (devid, back, front)
    15.1 --- a/tools/python/xen/xm/create.py	Thu Nov 24 23:21:48 2005 +0100
    15.2 +++ b/tools/python/xen/xm/create.py	Fri Nov 25 09:14:01 2005 +0100
    15.3 @@ -220,11 +220,9 @@ gopts.var('netif', val='no|yes',
    15.4            fn=set_bool, default=0,
    15.5            use="Make the domain a network interface backend.")
    15.6  
    15.7 -gopts.var('tpmif', val='frontend=DOM',
    15.8 -          fn=append_value, default=[],
    15.9 -          use="""Make the domain a TPM interface backend. If frontend is given,
   15.10 -          the frontend in that domain is connected to this backend (not
   15.11 -          completely implemented, yet)""")
   15.12 +gopts.var('tpmif', val='no|yes',
   15.13 +          fn=append_value, default=0,
   15.14 +          use="Make the domain a TPM interface backend.")
   15.15  
   15.16  gopts.var('disk', val='phy:DEV,VDEV,MODE[,DOM]',
   15.17            fn=append_value, default=[],
   15.18 @@ -273,9 +271,13 @@ gopts.var('vif', val="type=TYPE,mac=MAC,
   15.19  
   15.20  gopts.var('vtpm', val="instance=INSTANCE,backend=DOM",
   15.21            fn=append_value, default=[],
   15.22 -          use="""Add a tpm interface. On the backend side us the the given
   15.23 -          instance as virtual TPM instance. Use the backend in the given
   15.24 -          domain.""")
   15.25 +          use="""Add a TPM interface. On the backend side use the given
   15.26 +          instance as virtual TPM instance. The given number is merely the
   15.27 +          preferred instance number. The hotplug script will determine
   15.28 +          which instance number will actually be assigned to the domain.
   15.29 +          The associtation between virtual machine and the TPM instance
   15.30 +          number can be found in /etc/xen/vtpm.db. Use the backend in the
   15.31 +          given domain.""")
   15.32  
   15.33  gopts.var('nics', val="NUM",
   15.34            fn=set_int, default=1,
   15.35 @@ -465,34 +467,20 @@ def configure_vtpm(config_devs, vals):
   15.36              if instance == "VTPMD":
   15.37                  instance = "0"
   15.38              else:
   15.39 -                try:
   15.40 -                    if int(instance) == 0:
   15.41 -                        err('VM config error: vTPM instance must not be 0.')
   15.42 -                except ValueError:
   15.43 -                    err('Vm config error: could not parse instance number.')
   15.44 +                if instance != None:
   15.45 +                    try:
   15.46 +                        if int(instance) == 0:
   15.47 +                            err('VM config error: vTPM instance must not be 0.')
   15.48 +                    except ValueError:
   15.49 +                        err('Vm config error: could not parse instance number.')
   15.50              backend = d.get('backend')
   15.51              config_vtpm = ['vtpm']
   15.52              if instance:
   15.53 -                config_vtpm.append(['instance', instance])
   15.54 +                config_vtpm.append(['pref_instance', instance])
   15.55              if backend:
   15.56                  config_vtpm.append(['backend', backend])
   15.57              config_devs.append(['device', config_vtpm])
   15.58  
   15.59 -def configure_tpmif(config_devs, vals):
   15.60 -    """Create the config for virtual TPM interfaces.
   15.61 -    """
   15.62 -    tpmif = vals.tpmif
   15.63 -    tpmif_n = 1
   15.64 -    for idx in range(0, tpmif_n):
   15.65 -        if idx < len(tpmif):
   15.66 -            d = tpmif[idx]
   15.67 -            frontend = d.get('frontend')
   15.68 -            config_tpmif = ['tpmif']
   15.69 -            if frontend:
   15.70 -                config_tpmif.append(['frontend', frontend])
   15.71 -            config_devs.append(['device', config_tpmif])
   15.72 -
   15.73 -
   15.74  def configure_vifs(config_devs, vals):
   15.75      """Create the config for virtual network interfaces.
   15.76      """
   15.77 @@ -685,22 +673,6 @@ def preprocess_vtpm(vals):
   15.78          vtpms.append(d)
   15.79      vals.vtpm = vtpms
   15.80  
   15.81 -def preprocess_tpmif(vals):
   15.82 -    if not vals.tpmif: return
   15.83 -    tpmifs = []
   15.84 -    for tpmif in vals.tpmif:
   15.85 -        d = {}
   15.86 -        a = tpmif.split(',')
   15.87 -        for b in a:
   15.88 -            (k, v) = b.strip().split('=', 1)
   15.89 -            k = k.strip()
   15.90 -            v = v.strip()
   15.91 -            if k not in ['frontend']:
   15.92 -                err('Invalid tpmif specifier: ' + vtpm)
   15.93 -            d[k] = v
   15.94 -        tpmifs.append(d)
   15.95 -    vals.tpmif = tpmifs
   15.96 -
   15.97  def preprocess_ip(vals):
   15.98      if vals.ip or vals.dhcp != 'off':
   15.99          dummy_nfs_server = '1.2.3.4'
  15.100 @@ -791,7 +763,6 @@ def preprocess(vals):
  15.101      preprocess_nfs(vals)
  15.102      preprocess_vnc(vals)
  15.103      preprocess_vtpm(vals)
  15.104 -    preprocess_tpmif(vals)
  15.105           
  15.106  def make_domain(opts, config):
  15.107      """Create, build and start a domain.