[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Merged.
# HG changeset patch # User emellor@xxxxxxxxxxxxxxxxxxxxxx # Node ID 28a117c5ea94ef73c01cd46c6f87c576f1580c83 # Parent 42474df9b24804392bd84a853c1474b7dcc24952 # Parent 9c81a3c5b33b868632a83806e88f2328c11c2e93 Merged. diff -r 42474df9b248 -r 28a117c5ea94 docs/misc/vtpm.txt --- a/docs/misc/vtpm.txt Fri Nov 25 11:19:03 2005 +++ b/docs/misc/vtpm.txt Fri Nov 25 11:19:09 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 42474df9b248 -r 28a117c5ea94 linux-2.6-xen-sparse/arch/xen/i386/mm/init.c --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c Fri Nov 25 11:19:03 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c Fri Nov 25 11:19:09 2005 @@ -708,7 +708,7 @@ panic("pgtable_cache_init(): cannot create pmd cache"); } pgd_cache = kmem_cache_create("pgd", -#if 0 /* How the heck _this_ works in native linux ??? */ +#ifndef CONFIG_XEN PTRS_PER_PGD*sizeof(pgd_t), PTRS_PER_PGD*sizeof(pgd_t), #else @@ -717,7 +717,7 @@ #endif 0, pgd_ctor, - pgd_dtor); + PTRS_PER_PMD == 1 ? pgd_dtor : NULL); if (!pgd_cache) panic("pgtable_cache_init(): Cannot create pgd cache"); } diff -r 42474df9b248 -r 28a117c5ea94 linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c Fri Nov 25 11:19:03 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c Fri Nov 25 11:19:09 2005 @@ -28,8 +28,6 @@ #include <asm/hypervisor.h> static void pgd_test_and_unpin(pgd_t *pgd); -#define suspend_disable preempt_disable -#define suspend_enable preempt_enable void show_mem(void) { @@ -279,26 +277,31 @@ { unsigned long flags; -#ifdef CONFIG_X86_PAE - /* Ensure pgd resides below 4GB. */ - int rc = xen_create_contiguous_region((unsigned long)pgd, 0, 32); - BUG_ON(rc); + if (PTRS_PER_PMD > 1) { +#ifdef CONFIG_XEN + /* Ensure pgd resides below 4GB. */ + int rc = xen_create_contiguous_region( + (unsigned long)pgd, 0, 32); + BUG_ON(rc); #endif - - if (HAVE_SHARED_KERNEL_PMD) { + if (HAVE_SHARED_KERNEL_PMD) + memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD, + swapper_pg_dir, sizeof(pgd_t)); + } else { + if (!HAVE_SHARED_KERNEL_PMD) + spin_lock_irqsave(&pgd_lock, flags); memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD, swapper_pg_dir + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); - return; - } - - memset(pgd, 0, PTRS_PER_PGD*sizeof(pgd_t)); - - spin_lock_irqsave(&pgd_lock, flags); - pgd_list_add(pgd); - spin_unlock_irqrestore(&pgd_lock, flags); -} - + memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t)); + if (!HAVE_SHARED_KERNEL_PMD) { + pgd_list_add(pgd); + spin_unlock_irqrestore(&pgd_lock, flags); + } + } +} + +/* never called when PTRS_PER_PMD > 1 */ void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused) { unsigned long flags; /* can be called from interrupt context */ @@ -315,7 +318,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm) { - int i = 0; + int i; pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL); pgd_test_and_unpin(pgd); @@ -323,34 +326,31 @@ if (PTRS_PER_PMD == 1 || !pgd) return pgd; + for (i = 0; i < USER_PTRS_PER_PGD; ++i) { + pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL); + if (!pmd) + goto out_oom; + set_pgd(&pgd[i], __pgd(1 + __pa(pmd))); + } + if (!HAVE_SHARED_KERNEL_PMD) { - /* alloc and copy kernel pmd */ unsigned long flags; pgd_t *copy_pgd = pgd_offset_k(PAGE_OFFSET); pud_t *copy_pud = pud_offset(copy_pgd, PAGE_OFFSET); pmd_t *copy_pmd = pmd_offset(copy_pud, PAGE_OFFSET); pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL); - if (0 == pmd) + ++i; + if (!pmd) goto out_oom; spin_lock_irqsave(&pgd_lock, flags); memcpy(pmd, copy_pmd, PAGE_SIZE); - spin_unlock_irqrestore(&pgd_lock, flags); make_lowmem_page_readonly(pmd); set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd))); - } - - /* alloc user pmds */ - for (i = 0; i < USER_PTRS_PER_PGD; ++i) { - pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL); - if (!pmd) - goto out_oom; - suspend_disable(); - if (test_bit(PG_pinned, &virt_to_page(pgd)->flags)) - make_lowmem_page_readonly(pmd); - set_pgd(&pgd[i], __pgd(1 + __pa(pmd))); - suspend_enable(); - } + pgd_list_add(pgd); + spin_unlock_irqrestore(&pgd_lock, flags); + } + return pgd; out_oom: @@ -364,28 +364,25 @@ { int i; - suspend_disable(); pgd_test_and_unpin(pgd); /* in the PAE case user pgd entries are overwritten before usage */ if (PTRS_PER_PMD > 1) { for (i = 0; i < USER_PTRS_PER_PGD; ++i) { pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1); - set_pgd(&pgd[i], __pgd(0)); - make_lowmem_page_writable(pmd); kmem_cache_free(pmd_cache, pmd); } if (!HAVE_SHARED_KERNEL_PMD) { + unsigned long flags; pmd_t *pmd = (void *)__va(pgd_val(pgd[USER_PTRS_PER_PGD])-1); - set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(0)); + spin_lock_irqsave(&pgd_lock, flags); + pgd_list_del(pgd); + spin_unlock_irqrestore(&pgd_lock, flags); make_lowmem_page_writable(pmd); memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t)); kmem_cache_free(pmd_cache, pmd); } } - - suspend_enable(); - /* in the non-PAE case, free_pgtables() clears user pgd entries */ kmem_cache_free(pgd_cache, pgd); } @@ -510,9 +507,6 @@ static void __pgd_pin(pgd_t *pgd) { - /* PAE PGDs with no kernel PMD cannot be pinned. Bail right now. */ - if ((PTRS_PER_PMD > 1) && pgd_none(pgd[USER_PTRS_PER_PGD])) - return; pgd_walk(pgd, PAGE_KERNEL_RO); xen_pgd_pin(__pa(pgd)); set_bit(PG_pinned, &virt_to_page(pgd)->flags); @@ -527,10 +521,8 @@ static void pgd_test_and_unpin(pgd_t *pgd) { - suspend_disable(); if (test_bit(PG_pinned, &virt_to_page(pgd)->flags)) __pgd_unpin(pgd); - suspend_enable(); } void mm_pin(struct mm_struct *mm) diff -r 42474df9b248 -r 28a117c5ea94 linux-2.6-xen-sparse/drivers/char/tpm/Kconfig --- a/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig Fri Nov 25 11:19:03 2005 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig Fri Nov 25 11:19:09 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 42474df9b248 -r 28a117c5ea94 linux-2.6-xen-sparse/drivers/xen/tpmback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Fri Nov 25 11:19:03 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Fri Nov 25 11:19:09 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 42474df9b248 -r 28a117c5ea94 linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Fri Nov 25 11:19:03 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Fri Nov 25 11:19:09 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 42474df9b248 -r 28a117c5ea94 linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Fri Nov 25 11:19:03 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Fri Nov 25 11:19:09 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 42474df9b248 -r 28a117c5ea94 linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Fri Nov 25 11:19:03 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Fri Nov 25 11:19:09 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 42474df9b248 -r 28a117c5ea94 linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h Fri Nov 25 11:19:03 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h Fri Nov 25 11:19:09 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 42474df9b248 -r 28a117c5ea94 patches/linux-2.6.12/pmd-shared.patch --- a/patches/linux-2.6.12/pmd-shared.patch Fri Nov 25 11:19:03 2005 +++ b/patches/linux-2.6.12/pmd-shared.patch Fri Nov 25 11:19:09 2005 @@ -1,15 +1,3 @@ -diff -urNpP linux-2.6.12/arch/i386/mm/init.c linux-2.6.12.new/arch/i386/mm/init.c ---- linux-2.6.12/arch/i386/mm/init.c 2005-06-17 20:48:29.000000000 +0100 -+++ linux-2.6.12.new/arch/i386/mm/init.c 2005-07-11 16:28:09.778165582 +0100 -@@ -634,7 +634,7 @@ void __init pgtable_cache_init(void) - PTRS_PER_PGD*sizeof(pgd_t), - 0, - pgd_ctor, -- PTRS_PER_PMD == 1 ? pgd_dtor : NULL); -+ pgd_dtor); - if (!pgd_cache) - panic("pgtable_cache_init(): Cannot create pgd cache"); - } diff -urNpP linux-2.6.12/arch/i386/mm/pageattr.c linux-2.6.12.new/arch/i386/mm/pageattr.c --- linux-2.6.12/arch/i386/mm/pageattr.c 2005-06-17 20:48:29.000000000 +0100 +++ linux-2.6.12.new/arch/i386/mm/pageattr.c 2005-07-11 16:28:09.775165494 +0100 @@ -23,31 +11,45 @@ spin_lock_irqsave(&pgd_lock, flags); diff -urNpP linux-2.6.12/arch/i386/mm/pgtable.c linux-2.6.12.new/arch/i386/mm/pgtable.c ---- linux-2.6.12/arch/i386/mm/pgtable.c 2005-06-17 20:48:29.000000000 +0100 -+++ linux-2.6.12.new/arch/i386/mm/pgtable.c 2005-07-11 16:32:01.478023726 +0100 -@@ -199,14 +199,14 @@ void pgd_ctor(void *pgd, kmem_cache_t *c +--- linux-2.6.12/arch/i386/mm/pgtable.c 2005-11-24 21:51:49.000000000 +0000 ++++ linux-2.6.12.new/arch/i386/mm/pgtable.c 2005-11-24 22:06:04.000000000 +0000 +@@ -199,19 +199,22 @@ void pgd_ctor(void *pgd, kmem_cache_t *c { unsigned long flags; - if (PTRS_PER_PMD == 1) -+ if (!HAVE_SHARED_KERNEL_PMD) - spin_lock_irqsave(&pgd_lock, flags); - - memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD, - swapper_pg_dir + USER_PTRS_PER_PGD, - (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); - +- spin_lock_irqsave(&pgd_lock, flags); +- +- memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD, +- swapper_pg_dir + USER_PTRS_PER_PGD, +- (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); +- - if (PTRS_PER_PMD > 1) -+ if (HAVE_SHARED_KERNEL_PMD) - return; - - pgd_list_add(pgd); -@@ -214,11 +214,13 @@ void pgd_ctor(void *pgd, kmem_cache_t *c - memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t)); +- return; +- +- pgd_list_add(pgd); +- spin_unlock_irqrestore(&pgd_lock, flags); +- memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t)); ++ if (PTRS_PER_PMD > 1) { ++ if (HAVE_SHARED_KERNEL_PMD) ++ memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD, ++ swapper_pg_dir, sizeof(pgd_t)); ++ } else { ++ if (!HAVE_SHARED_KERNEL_PMD) ++ spin_lock_irqsave(&pgd_lock, flags); ++ memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD, ++ swapper_pg_dir + USER_PTRS_PER_PGD, ++ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); ++ memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t)); ++ if (!HAVE_SHARED_KERNEL_PMD) { ++ pgd_list_add(pgd); ++ spin_unlock_irqrestore(&pgd_lock, flags); ++ } ++ } } --/* never called when PTRS_PER_PMD > 1 */ - void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused) + /* never called when PTRS_PER_PMD > 1 */ +@@ -219,6 +222,9 @@ void pgd_dtor(void *pgd, kmem_cache_t *c { unsigned long flags; /* can be called from interrupt context */ @@ -57,38 +59,32 @@ spin_lock_irqsave(&pgd_lock, flags); pgd_list_del(pgd); spin_unlock_irqrestore(&pgd_lock, flags); -@@ -226,12 +228,29 @@ void pgd_dtor(void *pgd, kmem_cache_t *c - - pgd_t *pgd_alloc(struct mm_struct *mm) - { -- int i; -+ int i = 0; - pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL); - - if (PTRS_PER_PMD == 1 || !pgd) - return pgd; - +@@ -238,6 +244,24 @@ pgd_t *pgd_alloc(struct mm_struct *mm) + goto out_oom; + set_pgd(&pgd[i], __pgd(1 + __pa(pmd))); + } ++ + if (!HAVE_SHARED_KERNEL_PMD) { -+ /* alloc and copy kernel pmd */ + unsigned long flags; + pgd_t *copy_pgd = pgd_offset_k(PAGE_OFFSET); + pud_t *copy_pud = pud_offset(copy_pgd, PAGE_OFFSET); + pmd_t *copy_pmd = pmd_offset(copy_pud, PAGE_OFFSET); + pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL); -+ if (0 == pmd) ++ ++i; ++ if (!pmd) + goto out_oom; + + spin_lock_irqsave(&pgd_lock, flags); + memcpy(pmd, copy_pmd, PAGE_SIZE); ++ set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd))); ++ pgd_list_add(pgd); + spin_unlock_irqrestore(&pgd_lock, flags); -+ set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd))); + } + -+ /* alloc user pmds */ - for (i = 0; i < USER_PTRS_PER_PGD; ++i) { - pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL); - if (!pmd) -@@ -252,9 +271,16 @@ void pgd_free(pgd_t *pgd) + return pgd; + + out_oom: +@@ -252,9 +276,21 @@ void pgd_free(pgd_t *pgd) int i; /* in the PAE case user pgd entries are overwritten before usage */ @@ -101,7 +97,12 @@ + kmem_cache_free(pmd_cache, pmd); + } + if (!HAVE_SHARED_KERNEL_PMD) { ++ unsigned long flags; + pmd_t *pmd = (void *)__va(pgd_val(pgd[USER_PTRS_PER_PGD])-1); ++ spin_lock_irqsave(&pgd_lock, flags); ++ pgd_list_del(pgd); ++ spin_unlock_irqrestore(&pgd_lock, flags); ++ memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t)); + kmem_cache_free(pmd_cache, pmd); + } + } diff -r 42474df9b248 -r 28a117c5ea94 tools/examples/Makefile --- a/tools/examples/Makefile Fri Nov 25 11:19:03 2005 +++ b/tools/examples/Makefile Fri Nov 25 11:19:09 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 42474df9b248 -r 28a117c5ea94 tools/examples/xen-backend.agent --- a/tools/examples/xen-backend.agent Fri Nov 25 11:19:03 2005 +++ b/tools/examples/xen-backend.agent Fri Nov 25 11:19:09 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 42474df9b248 -r 28a117c5ea94 tools/examples/xen-backend.rules --- a/tools/examples/xen-backend.rules Fri Nov 25 11:19:03 2005 +++ b/tools/examples/xen-backend.rules Fri Nov 25 11:19:09 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 42474df9b248 -r 28a117c5ea94 tools/ioemu/exec.c --- a/tools/ioemu/exec.c Fri Nov 25 11:19:03 2005 +++ b/tools/ioemu/exec.c Fri Nov 25 11:19:09 2005 @@ -262,13 +262,24 @@ unsigned long size, unsigned long phys_offset) { - if (mmio_cnt == MAX_MMIO) { - fprintf(logfile, "too many mmio regions\n"); - exit(-1); - } - mmio[mmio_cnt].io_index = phys_offset; - mmio[mmio_cnt].start = start_addr; - mmio[mmio_cnt++].size = size; + int i; + + for (i = 0; i < mmio_cnt; i++) { + if(mmio[i].start == start_addr) { + mmio[i].io_index = phys_offset; + mmio[i].size = size; + return; + } + } + + if (mmio_cnt == MAX_MMIO) { + fprintf(logfile, "too many mmio regions\n"); + exit(-1); + } + + mmio[mmio_cnt].io_index = phys_offset; + mmio[mmio_cnt].start = start_addr; + mmio[mmio_cnt++].size = size; } /* mem_read and mem_write are arrays of functions containing the diff -r 42474df9b248 -r 28a117c5ea94 tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Fri Nov 25 11:19:03 2005 +++ b/tools/python/xen/xend/image.py Fri Nov 25 11:19:09 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 42474df9b248 -r 28a117c5ea94 tools/python/xen/xend/server/tpmif.py --- a/tools/python/xen/xend/server/tpmif.py Fri Nov 25 11:19:03 2005 +++ b/tools/python/xen/xend/server/tpmif.py Fri Nov 25 11:19:09 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 42474df9b248 -r 28a117c5ea94 tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Fri Nov 25 11:19:03 2005 +++ b/tools/python/xen/xm/create.py Fri Nov 25 11:19:09 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 42474df9b248 -r 28a117c5ea94 xen/arch/x86/dom0_ops.c --- a/xen/arch/x86/dom0_ops.c Fri Nov 25 11:19:03 2005 +++ b/xen/arch/x86/dom0_ops.c Fri Nov 25 11:19:09 2005 @@ -248,7 +248,7 @@ case DOM0_GETPAGEFRAMEINFO2: { -#define GPF2_BATCH 128 +#define GPF2_BATCH (PAGE_SIZE / sizeof(unsigned long)) int n,j; int num = op->u.getpageframeinfo2.num; domid_t dom = op->u.getpageframeinfo2.domain; @@ -285,12 +285,9 @@ struct pfn_info *page; unsigned long mfn = l_arr[j]; - if ( unlikely(mfn >= max_page) ) - goto e2_err; - page = &frame_table[mfn]; - - if ( likely(get_page(page, d)) ) + + if ( likely(pfn_valid(mfn) && get_page(page, d)) ) { unsigned long type = 0; @@ -316,10 +313,7 @@ put_page(page); } else - { - e2_err: l_arr[j] |= XTAB; - } } @@ -329,7 +323,7 @@ break; } - n += j; + n += k; } free_xenheap_page(l_arr); diff -r 42474df9b248 -r 28a117c5ea94 xen/common/acm_ops.c --- a/xen/common/acm_ops.c Fri Nov 25 11:19:03 2005 +++ b/xen/common/acm_ops.c Fri Nov 25 11:19:09 2005 @@ -49,15 +49,11 @@ int acm_authorize_acm_ops(struct domain *d, enum acm_operation pops) { - /* all policy management functions are restricted to privileged domains, - * soon we will introduce finer-grained privileges for policy operations - */ + /* currently, policy management functions are restricted to privileged domains */ if (!IS_PRIV(d)) - { - printk("%s: ACM management authorization denied ERROR!\n", __func__); - return ACM_ACCESS_DENIED; - } - return ACM_ACCESS_PERMITTED; + return -EPERM; + + return 0; } long do_acm_op(struct acm_op * u_acm_op) @@ -65,10 +61,8 @@ long ret = 0; struct acm_op curop, *op = &curop; - /* check here policy decision for policy commands */ - /* for now allow DOM0 only, later indepedently */ if (acm_authorize_acm_ops(current->domain, POLICY)) - return -EACCES; + return -EPERM; if (copy_from_user(op, u_acm_op, sizeof(*op))) return -EFAULT; @@ -80,43 +74,32 @@ { case ACM_SETPOLICY: { - if (acm_authorize_acm_ops(current->domain, SETPOLICY)) - return -EACCES; - printkd("%s: setting policy.\n", __func__); - ret = acm_set_policy(op->u.setpolicy.pushcache, - op->u.setpolicy.pushcache_size, 1); - if (ret == ACM_OK) - ret = 0; - else - ret = -ESRCH; + ret = acm_authorize_acm_ops(current->domain, SETPOLICY); + if (!ret) + ret = acm_set_policy(op->u.setpolicy.pushcache, + op->u.setpolicy.pushcache_size, 1); } break; case ACM_GETPOLICY: { - if (acm_authorize_acm_ops(current->domain, GETPOLICY)) - return -EACCES; - printkd("%s: getting policy.\n", __func__); - ret = acm_get_policy(op->u.getpolicy.pullcache, - op->u.getpolicy.pullcache_size); - if (ret == ACM_OK) - ret = 0; - else - ret = -ESRCH; + ret = acm_authorize_acm_ops(current->domain, GETPOLICY); + if (!ret) + ret = acm_get_policy(op->u.getpolicy.pullcache, + op->u.getpolicy.pullcache_size); + if (!ret) + copy_to_user(u_acm_op, op, sizeof(*op)); } break; case ACM_DUMPSTATS: { - if (acm_authorize_acm_ops(current->domain, DUMPSTATS)) - return -EACCES; - printkd("%s: dumping statistics.\n", __func__); - ret = acm_dump_statistics(op->u.dumpstats.pullcache, - op->u.dumpstats.pullcache_size); - if (ret == ACM_OK) - ret = 0; - else - ret = -ESRCH; + ret = acm_authorize_acm_ops(current->domain, DUMPSTATS); + if (!ret) + ret = acm_dump_statistics(op->u.dumpstats.pullcache, + op->u.dumpstats.pullcache_size); + if (!ret) + copy_to_user(u_acm_op, op, sizeof(*op)); } break; @@ -124,31 +107,39 @@ { ssidref_t ssidref; - if (acm_authorize_acm_ops(current->domain, GETSSID)) - return -EACCES; - printkd("%s: getting SSID.\n", __func__); + ret = acm_authorize_acm_ops(current->domain, GETSSID); + if (ret) + break; + if (op->u.getssid.get_ssid_by == SSIDREF) ssidref = op->u.getssid.id.ssidref; - else if (op->u.getssid.get_ssid_by == DOMAINID) { + else if (op->u.getssid.get_ssid_by == DOMAINID) + { struct domain *subj = find_domain_by_id(op->u.getssid.id.domainid); if (!subj) - return -ESRCH; /* domain not found */ - if (subj->ssid == NULL) { + { + ret = -ESRCH; /* domain not found */ + break; + } + if (subj->ssid == NULL) + { put_domain(subj); - return -ESRCH; + ret = -ESRCH; + break; } ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref; put_domain(subj); - } else - return -ESRCH; - + } + else + { + ret = -ESRCH; + break; + } ret = acm_get_ssid(ssidref, op->u.getssid.ssidbuf, op->u.getssid.ssidbuf_size); - if (ret == ACM_OK) - ret = 0; - else - ret = -ESRCH; + if (!ret) + copy_to_user(u_acm_op, op, sizeof(*op)); } break; @@ -156,51 +147,75 @@ { ssidref_t ssidref1, ssidref2; - if (acm_authorize_acm_ops(current->domain, GETDECISION)) { - ret = -EACCES; - goto out; - } - printkd("%s: getting access control decision.\n", __func__); - if (op->u.getdecision.get_decision_by1 == SSIDREF) { + ret = acm_authorize_acm_ops(current->domain, GETDECISION); + if (ret) + break; + + if (op->u.getdecision.get_decision_by1 == SSIDREF) ssidref1 = op->u.getdecision.id1.ssidref; - } - else if (op->u.getdecision.get_decision_by1 == DOMAINID) { + else if (op->u.getdecision.get_decision_by1 == DOMAINID) + { struct domain *subj = find_domain_by_id(op->u.getdecision.id1.domainid); - if (!subj) { + if (!subj) + { ret = -ESRCH; /* domain not found */ - goto out; - } - if (subj->ssid == NULL) { + break; + } + if (subj->ssid == NULL) + { put_domain(subj); ret = -ESRCH; - goto out; + break; } ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref; put_domain(subj); - } else { - ret = -ESRCH; - goto out; - } - if (op->u.getdecision.get_decision_by2 == SSIDREF) { + } + else + { + ret = -ESRCH; + break; + } + if (op->u.getdecision.get_decision_by2 == SSIDREF) ssidref2 = op->u.getdecision.id2.ssidref; - } - else if (op->u.getdecision.get_decision_by2 == DOMAINID) { + else if (op->u.getdecision.get_decision_by2 == DOMAINID) + { struct domain *subj = find_domain_by_id(op->u.getdecision.id2.domainid); - if (!subj) { + if (!subj) + { ret = -ESRCH; /* domain not found */ - goto out; - } - if (subj->ssid == NULL) { + break;; + } + if (subj->ssid == NULL) + { put_domain(subj); - return -ESRCH; + ret = -ESRCH; + break; } ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref; put_domain(subj); - } else { - ret = -ESRCH; - goto out; + } + else + { + ret = -ESRCH; + break; } ret = acm_get_decision(ssidref1, ssidref2, op->u.getdecision.hook); + + if (ret == ACM_ACCESS_PERMITTED) + { + op->u.getdecision.acm_decision = ACM_ACCESS_PERMITTED; + ret = 0; + } + else if (ret == ACM_ACCESS_DENIED) + { + op->u.getdecision.acm_decision = ACM_ACCESS_DENIED; + ret = 0; + } + else + ret = -ESRCH; + + if (!ret) + copy_to_user(u_acm_op, op, sizeof(*op)); } break; @@ -208,20 +223,6 @@ ret = -ESRCH; } - out: - if (ret == ACM_ACCESS_PERMITTED) { - op->u.getdecision.acm_decision = ACM_ACCESS_PERMITTED; - ret = 0; - } else if (ret == ACM_ACCESS_DENIED) { - op->u.getdecision.acm_decision = ACM_ACCESS_DENIED; - ret = 0; - } else { - op->u.getdecision.acm_decision = ACM_ACCESS_DENIED; - if (ret > 0) - ret = -ret; - } - /* copy decision back to user space */ - copy_to_user(u_acm_op, op, sizeof(*op)); return ret; } diff -r 42474df9b248 -r 28a117c5ea94 tools/examples/vtpm --- /dev/null Fri Nov 25 11:19:03 2005 +++ b/tools/examples/vtpm Fri Nov 25 11:19:09 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 42474df9b248 -r 28a117c5ea94 tools/examples/vtpm-common.sh --- /dev/null Fri Nov 25 11:19:03 2005 +++ b/tools/examples/vtpm-common.sh Fri Nov 25 11:19:09 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 |