[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
# HG changeset patch # User awilliam@xxxxxxxxxxx # Node ID 4b51d081378d6783cce48255ffb7655931f26d63 # Parent c4b68afe97d36b87c460d1bef3eac135f66d9fc9 # Parent 2245974798126074c31521b0903cc7e67e8aec23 merge with xen-unstable.hg --- tools/libxc/xc_aout9.h | 30 tools/libxc/xc_load_aout9.c | 178 - Makefile | 5 docs/Makefile | 3 linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c | 2 linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c | 134 + linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c | 43 linux-2.6-xen-sparse/drivers/xen/blkback/common.h | 1 linux-2.6-xen-sparse/drivers/xen/blkback/interface.c | 22 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c | 73 linux-2.6-xen-sparse/drivers/xen/core/xen_sysfs.c | 100 linux-2.6-xen-sparse/drivers/xen/netback/interface.c | 8 linux-2.6-xen-sparse/drivers/xen/netback/loopback.c | 5 linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 65 linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c | 6 linux-2.6-xen-sparse/drivers/xen/tpmback/common.h | 11 linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c | 10 linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c | 91 linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c | 37 linux-2.6-xen-sparse/include/linux/skbuff.h | 42 linux-2.6-xen-sparse/net/core/dev.c | 238 +- linux-2.6-xen-sparse/net/core/skbuff.c | 144 + patches/linux-2.6.16.13/net-gso.patch | 1974 +++++++++++++++++++ patches/linux-2.6.16.13/xenoprof-generic.patch | 81 tools/Makefile | 3 tools/examples/Makefile | 2 tools/examples/vtpm | 6 tools/examples/vtpm-common.sh | 36 tools/examples/vtpm-impl | 136 + tools/libxc/Makefile | 1 tools/libxc/xc_ia64_stubs.c | 11 tools/libxc/xc_linux_build.c | 8 tools/libxc/xg_private.h | 7 tools/python/xen/lowlevel/xc/xc.c | 29 tools/python/xen/xend/XendNode.py | 4 tools/python/xen/xend/balloon.py | 71 tools/python/xen/xm/main.py | 37 tools/vtpm/Rules.mk | 3 tools/vtpm/tpm_emulator-0.3-x86_64.patch | 238 +- tools/vtpm/tpm_emulator.patch | 1120 ++++++++++ tools/vtpm/vtpm.patch | 236 +- tools/vtpm_manager/Rules.mk | 3 tools/vtpm_manager/manager/dmictl.c | 57 tools/vtpm_manager/manager/securestorage.c | 29 tools/vtpm_manager/manager/vtpm_manager.c | 11 tools/vtpm_manager/manager/vtpm_manager.h | 10 tools/vtpm_manager/manager/vtpm_manager_handler.c | 75 tools/vtpm_manager/manager/vtpmd.c | 40 tools/vtpm_manager/manager/vtpmpriv.h | 13 tools/vtpm_manager/manager/vtsp.c | 11 tools/vtpm_manager/manager/vtsp.h | 2 tools/vtpm_manager/tcs/tcs.c | 43 tools/vtpm_manager/tcs/tcs.h | 5 tools/vtpm_manager/tcs/transmit.c | 42 tools/vtpm_manager/util/tcg.h | 5 tools/xenstat/xentop/xentop.1 | 9 tools/xenstat/xentop/xentop.c | 84 tools/xm-test/tests/info/02_info_compiledata_pos.py | 3 xen/Makefile | 12 xen/arch/x86/dom0_ops.c | 1 xen/arch/x86/hvm/svm/svm.c | 40 xen/arch/x86/hvm/vioapic.c | 41 xen/arch/x86/hvm/vlapic.c | 38 xen/arch/x86/hvm/vmx/vmx.c | 150 - xen/arch/x86/microcode.c | 138 - xen/arch/x86/oprofile/nmi_int.c | 2 xen/arch/x86/oprofile/xenoprof.c | 358 ++- xen/arch/x86/smp.c | 5 xen/arch/x86/x86_emulate.c | 9 xen/common/kernel.c | 5 xen/common/page_alloc.c | 12 xen/include/asm-x86/bitops.h | 30 xen/include/asm-x86/hvm/vcpu.h | 3 xen/include/asm-x86/hvm/vlapic.h | 62 xen/include/public/dom0_ops.h | 1 xen/include/public/hvm/ioreq.h | 5 xen/include/public/io/netif.h | 33 xen/include/public/version.h | 5 xen/include/public/xenoprof.h | 9 xen/include/xen/mm.h | 1 xen/include/xen/xenoprof.h | 1 81 files changed, 5191 insertions(+), 1463 deletions(-) diff -r c4b68afe97d3 -r 4b51d081378d Makefile --- a/Makefile Wed Jun 28 07:51:52 2006 -0600 +++ b/Makefile Wed Jun 28 07:52:21 2006 -0600 @@ -123,7 +123,10 @@ clean:: # clean, but blow away kernel build tree plus tarballs .PHONY: distclean -distclean: clean +distclean: + $(MAKE) -C xen distclean + $(MAKE) -C tools distclean + $(MAKE) -C docs distclean rm -rf dist patches/tmp for i in $(ALLKERNELS) ; do $(MAKE) $$i-delete ; done for i in $(ALLSPARSETREES) ; do $(MAKE) $$i-mrproper ; done diff -r c4b68afe97d3 -r 4b51d081378d docs/Makefile --- a/docs/Makefile Wed Jun 28 07:51:52 2006 -0600 +++ b/docs/Makefile Wed Jun 28 07:52:21 2006 -0600 @@ -80,6 +80,9 @@ clean: rm -rf man5 rm -rf man1 +.PHONY: distclean +distclean: clean + .PHONY: install install: all rm -rf $(DESTDIR)$(pkgdocdir) diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c --- a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c Wed Jun 28 07:52:21 2006 -0600 @@ -264,7 +264,7 @@ static void contiguous_bitmap_clear( } /* Protected by balloon_lock. */ -#define MAX_CONTIG_ORDER 7 +#define MAX_CONTIG_ORDER 9 /* 2MB */ static unsigned long discontig_frames[1<<MAX_CONTIG_ORDER]; /* Ensure multi-page extents are contiguous in machine memory. */ diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c --- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Wed Jun 28 07:52:21 2006 -0600 @@ -28,6 +28,7 @@ #include <xen/interface/xen.h> #include <xen/interface/xenoprof.h> +#include <../../../drivers/oprofile/cpu_buffer.h> static int xenoprof_start(void); static void xenoprof_stop(void); @@ -50,6 +51,11 @@ int ovf_irq[NR_CPUS]; /* cpu model type string - copied from Xen memory space on XENOPROF_init command */ char cpu_type[XENOPROF_CPU_TYPE_SIZE]; +/* Passive sample buffers shared with Xen */ +xenoprof_buf_t *p_xenoprof_buf[MAX_OPROF_DOMAINS][MAX_VIRT_CPUS]; +/* Passive shared buffer area */ +char *p_shared_buffer[MAX_OPROF_DOMAINS]; + #ifdef CONFIG_PM static int xenoprof_suspend(struct sys_device * dev, pm_message_t state) @@ -102,16 +108,14 @@ static void __exit exit_driverfs(void) #endif /* CONFIG_PM */ unsigned long long oprofile_samples = 0; - -static irqreturn_t -xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs) +unsigned long long p_oprofile_samples = 0; + +unsigned int pdomains; +struct xenoprof_passive passive_domains[MAX_OPROF_DOMAINS]; + +static void xenoprof_add_pc(xenoprof_buf_t *buf, int is_passive) { int head, tail, size; - struct xenoprof_buf * buf; - int cpu; - - cpu = smp_processor_id(); - buf = xenoprof_buf[cpu]; head = buf->event_head; tail = buf->event_tail; @@ -122,7 +126,10 @@ xenoprof_ovf_interrupt(int irq, void * d oprofile_add_pc(buf->event_log[tail].eip, buf->event_log[tail].mode, buf->event_log[tail].event); - oprofile_samples++; + if (!is_passive) + oprofile_samples++; + else + p_oprofile_samples++; tail++; } tail = 0; @@ -131,11 +138,47 @@ xenoprof_ovf_interrupt(int irq, void * d oprofile_add_pc(buf->event_log[tail].eip, buf->event_log[tail].mode, buf->event_log[tail].event); - oprofile_samples++; + if (!is_passive) + oprofile_samples++; + else + p_oprofile_samples++; tail++; } buf->event_tail = tail; +} + +static void xenoprof_handle_passive(void) +{ + int i, j; + + for (i = 0; i < pdomains; i++) + for (j = 0; j < passive_domains[i].nbuf; j++) { + xenoprof_buf_t *buf = p_xenoprof_buf[i][j]; + if (buf->event_head == buf->event_tail) + continue; + oprofile_add_pc(IGNORED_PC, CPU_MODE_PASSIVE_START, passive_domains[i].domain_id); + xenoprof_add_pc(buf, 1); + oprofile_add_pc(IGNORED_PC, CPU_MODE_PASSIVE_STOP, passive_domains[i].domain_id); + } +} + +static irqreturn_t +xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs) +{ + struct xenoprof_buf * buf; + int cpu; + static unsigned long flag; + + cpu = smp_processor_id(); + buf = xenoprof_buf[cpu]; + + xenoprof_add_pc(buf, 0); + + if (is_primary && !test_and_set_bit(0, &flag)) { + xenoprof_handle_passive(); + clear_bit(0, &flag); + } return IRQ_HANDLED; } @@ -312,6 +355,63 @@ out: return ret; } +static int xenoprof_set_passive(int * p_domains, + unsigned int pdoms) +{ + int ret; + int i, j; + int vm_size; + int npages; + struct xenoprof_buf *buf; + pgprot_t prot = __pgprot(_KERNPG_TABLE); + + if (!is_primary) + return 0; + + if (pdoms > MAX_OPROF_DOMAINS) + return -E2BIG; + + ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_passive_list, NULL); + if (ret) + return ret; + + for (i = 0; i < pdoms; i++) { + passive_domains[i].domain_id = p_domains[i]; + passive_domains[i].max_samples = 2048; + ret = HYPERVISOR_xenoprof_op(XENOPROF_set_passive, &passive_domains[i]); + if (ret) + return ret; + + npages = (passive_domains[i].bufsize * passive_domains[i].nbuf - 1) / PAGE_SIZE + 1; + vm_size = npages * PAGE_SIZE; + + p_shared_buffer[i] = (char *)vm_map_xen_pages(passive_domains[i].buf_maddr, + vm_size, prot); + if (!p_shared_buffer[i]) { + ret = -ENOMEM; + goto out; + } + + for (j = 0; j < passive_domains[i].nbuf; j++) { + buf = (struct xenoprof_buf *) + &p_shared_buffer[i][j * passive_domains[i].bufsize]; + BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS); + p_xenoprof_buf[i][buf->vcpu_id] = buf; + } + + } + + pdomains = pdoms; + return 0; + +out: + for (j = 0; j < i; j++) { + vunmap(p_shared_buffer[j]); + p_shared_buffer[j] = NULL; + } + + return ret; +} struct op_counter_config counter_config[OP_MAX_COUNTER]; @@ -346,6 +446,7 @@ struct oprofile_operations xenoprof_ops struct oprofile_operations xenoprof_ops = { .create_files = xenoprof_create_files, .set_active = xenoprof_set_active, + .set_passive = xenoprof_set_passive, .setup = xenoprof_setup, .shutdown = xenoprof_shutdown, .start = xenoprof_start, @@ -420,6 +521,8 @@ int __init oprofile_arch_init(struct opr void __exit oprofile_arch_exit(void) { + int i; + if (using_xenoprof) exit_driverfs(); @@ -427,6 +530,13 @@ void __exit oprofile_arch_exit(void) vunmap(shared_buffer); shared_buffer = NULL; } - if (is_primary) + if (is_primary) { + for (i = 0; i < pdomains; i++) + if (p_shared_buffer[i]) { + vunmap(p_shared_buffer[i]); + p_shared_buffer[i] = NULL; + } HYPERVISOR_xenoprof_op(XENOPROF_shutdown, NULL); -} + } + +} diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Wed Jun 28 07:52:21 2006 -0600 @@ -172,7 +172,7 @@ static unsigned long current_target(void static int increase_reservation(unsigned long nr_pages) { - unsigned long *frame_list, pfn, i, flags; + unsigned long *frame_list, frame, pfn, i, flags; struct page *page; long rc; struct xen_memory_reservation reservation = { @@ -185,8 +185,11 @@ static int increase_reservation(unsigned nr_pages = PAGE_SIZE / sizeof(unsigned long); frame_list = (unsigned long *)__get_free_page(GFP_KERNEL); - if (frame_list == NULL) - return -ENOMEM; + if (frame_list == NULL) { + frame_list = &frame; + if (nr_pages > 1) + nr_pages = 1; + } balloon_lock(flags); @@ -202,14 +205,17 @@ static int increase_reservation(unsigned rc = HYPERVISOR_memory_op( XENMEM_populate_physmap, &reservation); if (rc < nr_pages) { - int ret; - /* We hit the Xen hard limit: reprobe. */ - set_xen_guest_handle(reservation.extent_start, frame_list); - reservation.nr_extents = rc; - ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, - &reservation); - BUG_ON(ret != rc); - hard_limit = current_pages + rc - driver_pages; + if (rc > 0) { + int ret; + + /* We hit the Xen hard limit: reprobe. */ + reservation.nr_extents = rc; + ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, + &reservation); + BUG_ON(ret != rc); + } + if (rc >= 0) + hard_limit = current_pages + rc - driver_pages; goto out; } @@ -247,14 +253,15 @@ static int increase_reservation(unsigned out: balloon_unlock(flags); - free_page((unsigned long)frame_list); + if (frame_list != &frame) + free_page((unsigned long)frame_list); return 0; } static int decrease_reservation(unsigned long nr_pages) { - unsigned long *frame_list, pfn, i, flags; + unsigned long *frame_list, frame, pfn, i, flags; struct page *page; void *v; int need_sleep = 0; @@ -269,8 +276,11 @@ static int decrease_reservation(unsigned nr_pages = PAGE_SIZE / sizeof(unsigned long); frame_list = (unsigned long *)__get_free_page(GFP_KERNEL); - if (frame_list == NULL) - return -ENOMEM; + if (frame_list == NULL) { + frame_list = &frame; + if (nr_pages > 1) + nr_pages = 1; + } for (i = 0; i < nr_pages; i++) { if ((page = alloc_page(GFP_HIGHUSER)) == NULL) { @@ -321,7 +331,8 @@ static int decrease_reservation(unsigned balloon_unlock(flags); - free_page((unsigned long)frame_list); + if (frame_list != &frame) + free_page((unsigned long)frame_list); return need_sleep; } diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/drivers/xen/blkback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Wed Jun 28 07:52:21 2006 -0600 @@ -95,6 +95,7 @@ typedef struct blkif_st { } blkif_t; blkif_t *blkif_alloc(domid_t domid); +void blkif_disconnect(blkif_t *blkif); void blkif_free(blkif_t *blkif); int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn); diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/drivers/xen/blkback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Wed Jun 28 07:52:21 2006 -0600 @@ -32,6 +32,7 @@ #include "common.h" #include <xen/evtchn.h> +#include <linux/kthread.h> static kmem_cache_t *blkif_cachep; @@ -139,22 +140,33 @@ int blkif_map(blkif_t *blkif, unsigned l return 0; } -void blkif_free(blkif_t *blkif) +void blkif_disconnect(blkif_t *blkif) { + if (blkif->xenblkd) { + kthread_stop(blkif->xenblkd); + blkif->xenblkd = NULL; + } + atomic_dec(&blkif->refcnt); wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0); + atomic_inc(&blkif->refcnt); - /* Already disconnected? */ - if (blkif->irq) + if (blkif->irq) { unbind_from_irqhandler(blkif->irq, blkif); - - vbd_free(&blkif->vbd); + blkif->irq = 0; + } if (blkif->blk_ring.sring) { unmap_frontend_page(blkif); free_vm_area(blkif->blk_ring_area); + blkif->blk_ring.sring = NULL; } +} +void blkif_free(blkif_t *blkif) +{ + if (!atomic_dec_and_test(&blkif->refcnt)) + BUG(); kmem_cache_free(blkif_cachep, blkif); } diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Wed Jun 28 07:52:21 2006 -0600 @@ -42,7 +42,6 @@ static int connect_ring(struct backend_i static int connect_ring(struct backend_info *); static void backend_changed(struct xenbus_watch *, const char **, unsigned int); - static void update_blkif_status(blkif_t *blkif) { @@ -73,6 +72,70 @@ static void update_blkif_status(blkif_t } +/**************************************************************** + * sysfs interface for VBD I/O requests + */ + +#ifdef CONFIG_SYSFS + +#define VBD_SHOW(name, format, args...) \ + static ssize_t show_##name(struct device *_dev, \ + struct device_attribute *attr, \ + char *buf) \ + { \ + struct xenbus_device *dev = to_xenbus_device(_dev); \ + struct backend_info *be = dev->dev.driver_data; \ + \ + return sprintf(buf, format, ##args); \ + } \ + DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) + +VBD_SHOW(oo_req, "%d\n", be->blkif->st_oo_req); +VBD_SHOW(rd_req, "%d\n", be->blkif->st_rd_req); +VBD_SHOW(wr_req, "%d\n", be->blkif->st_wr_req); + +static struct attribute *vbdstat_attrs[] = { + &dev_attr_oo_req.attr, + &dev_attr_rd_req.attr, + &dev_attr_wr_req.attr, + NULL +}; + +static struct attribute_group vbdstat_group = { + .name = "statistics", + .attrs = vbdstat_attrs, +}; + +int xenvbd_sysfs_addif(struct xenbus_device *dev) +{ + int error = 0; + + error = sysfs_create_group(&dev->dev.kobj, + &vbdstat_group); + if (error) + goto fail; + + return 0; + +fail: + sysfs_remove_group(&dev->dev.kobj, + &vbdstat_group); + return error; +} + +void xenvbd_sysfs_delif(struct xenbus_device *dev) +{ + sysfs_remove_group(&dev->dev.kobj, + &vbdstat_group); +} + +#else + +#define xenvbd_sysfs_addif(dev) (0) +#define xenvbd_sysfs_delif(dev) ((void)0) + +#endif /* CONFIG_SYSFS */ + static ssize_t show_physical_device(struct device *_dev, struct device_attribute *attr, char *buf) { @@ -105,15 +168,17 @@ static int blkback_remove(struct xenbus_ kfree(be->backend_watch.node); be->backend_watch.node = NULL; } + if (be->blkif) { - if (be->blkif->xenblkd) - kthread_stop(be->blkif->xenblkd); + blkif_disconnect(be->blkif); + vbd_free(&be->blkif->vbd); blkif_free(be->blkif); be->blkif = NULL; } device_remove_file(&dev->dev, &dev_attr_physical_device); device_remove_file(&dev->dev, &dev_attr_mode); + xenvbd_sysfs_delif(dev); kfree(be); dev->dev.driver_data = NULL; @@ -236,6 +301,7 @@ static void backend_changed(struct xenbu device_create_file(&dev->dev, &dev_attr_physical_device); device_create_file(&dev->dev, &dev_attr_mode); + xenvbd_sysfs_addif(dev); /* We're potentially connected now */ update_blkif_status(be->blkif); @@ -273,6 +339,7 @@ static void frontend_changed(struct xenb break; case XenbusStateClosing: + blkif_disconnect(be->blkif); xenbus_switch_state(dev, XenbusStateClosing); break; diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/drivers/xen/core/xen_sysfs.c --- a/linux-2.6-xen-sparse/drivers/xen/core/xen_sysfs.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/core/xen_sysfs.c Wed Jun 28 07:52:21 2006 -0600 @@ -58,15 +58,17 @@ HYPERVISOR_ATTR_RO(minor); static ssize_t extra_show(struct hyp_sysfs_attr *attr, char *buffer) { - int ret; - char *extra = kmalloc(XEN_EXTRAVERSION_LEN, GFP_KERNEL); + int ret = -ENOMEM; + char *extra; + + extra = kmalloc(XEN_EXTRAVERSION_LEN, GFP_KERNEL); if (extra) { ret = HYPERVISOR_xen_version(XENVER_extraversion, extra); if (!ret) - return sprintf(buffer, "%s\n", extra); + ret = sprintf(buffer, "%s\n", extra); kfree(extra); - } else - ret = -ENOMEM; + } + return ret; } @@ -86,7 +88,8 @@ static struct attribute_group version_gr static int __init xen_sysfs_version_init(void) { - return sysfs_create_group(&hypervisor_subsys.kset.kobj, &version_group); + return sysfs_create_group(&hypervisor_subsys.kset.kobj, + &version_group); } static void xen_sysfs_version_destroy(void) @@ -98,16 +101,16 @@ static void xen_sysfs_version_destroy(vo static ssize_t compiler_show(struct hyp_sysfs_attr *attr, char *buffer) { - int ret; - struct xen_compile_info *info = - kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); + int ret = -ENOMEM; + struct xen_compile_info *info; + + info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); if (info) { ret = HYPERVISOR_xen_version(XENVER_compile_info, info); if (!ret) ret = sprintf(buffer, "%s\n", info->compiler); kfree(info); - } else - ret = -ENOMEM; + } return ret; } @@ -116,7 +119,7 @@ HYPERVISOR_ATTR_RO(compiler); static ssize_t compiled_by_show(struct hyp_sysfs_attr *attr, char *buffer) { - int ret; + int ret = -ENOMEM; struct xen_compile_info *info; info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); @@ -125,8 +128,8 @@ static ssize_t compiled_by_show(struct h if (!ret) ret = sprintf(buffer, "%s\n", info->compile_by); kfree(info); - } else - ret = -ENOMEM; + } + return ret; } @@ -134,7 +137,7 @@ HYPERVISOR_ATTR_RO(compiled_by); static ssize_t compile_date_show(struct hyp_sysfs_attr *attr, char *buffer) { - int ret; + int ret = -ENOMEM; struct xen_compile_info *info; info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); @@ -143,8 +146,8 @@ static ssize_t compile_date_show(struct if (!ret) ret = sprintf(buffer, "%s\n", info->compile_date); kfree(info); - } else - ret = -ENOMEM; + } + return ret; } @@ -178,15 +181,17 @@ static void xen_compilation_destroy(void static ssize_t capabilities_show(struct hyp_sysfs_attr *attr, char *buffer) { - int ret; - char *caps = kmalloc(XEN_CAPABILITIES_INFO_LEN, GFP_KERNEL); + int ret = -ENOMEM; + char *caps; + + caps = kmalloc(XEN_CAPABILITIES_INFO_LEN, GFP_KERNEL); if (caps) { ret = HYPERVISOR_xen_version(XENVER_capabilities, caps); if (!ret) ret = sprintf(buffer, "%s\n", caps); kfree(caps); - } else - ret = -ENOMEM; + } + return ret; } @@ -194,15 +199,17 @@ HYPERVISOR_ATTR_RO(capabilities); static ssize_t changeset_show(struct hyp_sysfs_attr *attr, char *buffer) { - int ret; - char *cset = kmalloc(XEN_CHANGESET_INFO_LEN, GFP_KERNEL); + int ret = -ENOMEM; + char *cset; + + cset = kmalloc(XEN_CHANGESET_INFO_LEN, GFP_KERNEL); if (cset) { ret = HYPERVISOR_xen_version(XENVER_changeset, cset); if (!ret) ret = sprintf(buffer, "%s\n", cset); kfree(cset); - } else - ret = -ENOMEM; + } + return ret; } @@ -210,36 +217,51 @@ HYPERVISOR_ATTR_RO(changeset); static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer) { - int ret; - struct xen_platform_parameters *parms = - kmalloc(sizeof(struct xen_platform_parameters), GFP_KERNEL); + int ret = -ENOMEM; + struct xen_platform_parameters *parms; + + parms = kmalloc(sizeof(struct xen_platform_parameters), GFP_KERNEL); if (parms) { - ret = HYPERVISOR_xen_version(XENVER_platform_parameters, parms); + ret = HYPERVISOR_xen_version(XENVER_platform_parameters, + parms); if (!ret) ret = sprintf(buffer, "%lx\n", parms->virt_start); kfree(parms); - } else - ret = -ENOMEM; + } + return ret; } HYPERVISOR_ATTR_RO(virtual_start); + +static ssize_t pagesize_show(struct hyp_sysfs_attr *attr, char *buffer) +{ + int ret; + + ret = HYPERVISOR_xen_version(XENVER_pagesize, NULL); + if (ret > 0) + ret = sprintf(buffer, "%x\n", ret); + + return ret; +} + +HYPERVISOR_ATTR_RO(pagesize); /* eventually there will be several more features to export */ static ssize_t xen_feature_show(int index, char *buffer) { - int ret; - - struct xen_feature_info *info = - kmalloc(sizeof(struct xen_feature_info), GFP_KERNEL); + int ret = -ENOMEM; + struct xen_feature_info *info; + + info = kmalloc(sizeof(struct xen_feature_info), GFP_KERNEL); if (info) { info->submap_idx = index; ret = HYPERVISOR_xen_version(XENVER_get_features, info); if (!ret) ret = sprintf(buffer, "%d\n", info->submap); kfree(info); - } else - ret = -ENOMEM; + } + return ret; } @@ -254,6 +276,7 @@ static struct attribute *xen_properties_ &capabilities_attr.attr, &changeset_attr.attr, &virtual_start_attr.attr, + &pagesize_attr.attr, &writable_pt_attr.attr, NULL }; @@ -271,7 +294,8 @@ static int __init xen_properties_init(vo static void xen_properties_destroy(void) { - sysfs_remove_group(&hypervisor_subsys.kset.kobj, &xen_properties_group); + sysfs_remove_group(&hypervisor_subsys.kset.kobj, + &xen_properties_group); } static int __init hyper_sysfs_init(void) diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/drivers/xen/netback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Wed Jun 28 07:52:21 2006 -0600 @@ -37,9 +37,9 @@ static void __netif_up(netif_t *netif) static void __netif_up(netif_t *netif) { struct net_device *dev = netif->dev; - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); netif->active = 1; - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); enable_irq(netif->irq); netif_schedule_work(netif); } @@ -48,9 +48,9 @@ static void __netif_down(netif_t *netif) { struct net_device *dev = netif->dev; disable_irq(netif->irq); - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); netif->active = 0; - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); netif_deschedule_work(netif); } diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/drivers/xen/netback/loopback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c Wed Jun 28 07:52:21 2006 -0600 @@ -125,6 +125,10 @@ static struct ethtool_ops network_ethtoo { .get_tx_csum = ethtool_op_get_tx_csum, .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, }; /* @@ -152,6 +156,7 @@ static void loopback_construct(struct ne dev->features = (NETIF_F_HIGHDMA | NETIF_F_LLTX | + NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM); diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Jun 28 07:52:21 2006 -0600 @@ -43,7 +43,7 @@ static void netif_idx_release(u16 pendin static void netif_idx_release(u16 pending_idx); static void netif_page_release(struct page *page); static void make_tx_response(netif_t *netif, - u16 id, + netif_tx_request_t *txp, s8 st); static int make_rx_response(netif_t *netif, u16 id, @@ -481,7 +481,7 @@ inline static void net_tx_action_dealloc netif = pending_tx_info[pending_idx].netif; - make_tx_response(netif, pending_tx_info[pending_idx].req.id, + make_tx_response(netif, &pending_tx_info[pending_idx].req, NETIF_RSP_OKAY); pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; @@ -490,14 +490,16 @@ inline static void net_tx_action_dealloc } } -static void netbk_tx_err(netif_t *netif, RING_IDX end) +static void netbk_tx_err(netif_t *netif, netif_tx_request_t *txp, RING_IDX end) { RING_IDX cons = netif->tx.req_cons; do { - netif_tx_request_t *txp = RING_GET_REQUEST(&netif->tx, cons); - make_tx_response(netif, txp->id, NETIF_RSP_ERROR); - } while (++cons < end); + make_tx_response(netif, txp, NETIF_RSP_ERROR); + if (++cons >= end) + break; + txp = RING_GET_REQUEST(&netif->tx, cons); + } while (1); netif->tx.req_cons = cons; netif_schedule_work(netif); netif_put(netif); @@ -508,7 +510,7 @@ static int netbk_count_requests(netif_t { netif_tx_request_t *first = txp; RING_IDX cons = netif->tx.req_cons; - int frags = 1; + int frags = 0; while (txp->flags & NETTXF_more_data) { if (frags >= work_to_do) { @@ -543,7 +545,7 @@ static gnttab_map_grant_ref_t *netbk_get skb_frag_t *frags = shinfo->frags; netif_tx_request_t *txp; unsigned long pending_idx = *((u16 *)skb->data); - RING_IDX cons = netif->tx.req_cons + 1; + RING_IDX cons = netif->tx.req_cons; int i, start; /* Skip first skb fragment if it is on same page as header fragment. */ @@ -581,7 +583,7 @@ static int netbk_tx_check_mop(struct sk_ err = mop->status; if (unlikely(err)) { txp = &pending_tx_info[pending_idx].req; - make_tx_response(netif, txp->id, NETIF_RSP_ERROR); + make_tx_response(netif, txp, NETIF_RSP_ERROR); pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; netif_put(netif); } else { @@ -614,7 +616,7 @@ static int netbk_tx_check_mop(struct sk_ /* Error on this fragment: respond to client with an error. */ txp = &pending_tx_info[pending_idx].req; - make_tx_response(netif, txp->id, NETIF_RSP_ERROR); + make_tx_response(netif, txp, NETIF_RSP_ERROR); pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; netif_put(netif); @@ -668,6 +670,7 @@ static void net_tx_action(unsigned long struct sk_buff *skb; netif_t *netif; netif_tx_request_t txreq; + struct netif_tx_extra txtra; u16 pending_idx; RING_IDX i; gnttab_map_grant_ref_t *mop; @@ -726,22 +729,37 @@ static void net_tx_action(unsigned long } netif->remaining_credit -= txreq.size; + work_to_do--; + netif->tx.req_cons = ++i; + + if (txreq.flags & NETTXF_extra_info) { + if (work_to_do-- <= 0) { + DPRINTK("Missing extra info\n"); + netbk_tx_err(netif, &txreq, i); + continue; + } + + memcpy(&txtra, RING_GET_REQUEST(&netif->tx, i), + sizeof(txtra)); + netif->tx.req_cons = ++i; + } + ret = netbk_count_requests(netif, &txreq, work_to_do); if (unlikely(ret < 0)) { - netbk_tx_err(netif, i - ret); + netbk_tx_err(netif, &txreq, i - ret); continue; } i += ret; if (unlikely(ret > MAX_SKB_FRAGS + 1)) { DPRINTK("Too many frags\n"); - netbk_tx_err(netif, i); + netbk_tx_err(netif, &txreq, i); continue; } if (unlikely(txreq.size < ETH_HLEN)) { DPRINTK("Bad packet size: %d\n", txreq.size); - netbk_tx_err(netif, i); + netbk_tx_err(netif, &txreq, i); continue; } @@ -750,25 +768,31 @@ static void net_tx_action(unsigned long DPRINTK("txreq.offset: %x, size: %u, end: %lu\n", txreq.offset, txreq.size, (txreq.offset &~PAGE_MASK) + txreq.size); - netbk_tx_err(netif, i); + netbk_tx_err(netif, &txreq, i); continue; } pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)]; data_len = (txreq.size > PKT_PROT_LEN && - ret < MAX_SKB_FRAGS + 1) ? + ret < MAX_SKB_FRAGS) ? PKT_PROT_LEN : txreq.size; skb = alloc_skb(data_len+16, GFP_ATOMIC); if (unlikely(skb == NULL)) { DPRINTK("Can't allocate a skb in start_xmit.\n"); - netbk_tx_err(netif, i); + netbk_tx_err(netif, &txreq, i); break; } /* Packets passed to netif_rx() must have some headroom. */ skb_reserve(skb, 16); + + if (txreq.flags & NETTXF_gso) { + skb_shinfo(skb)->gso_size = txtra.u.gso.size; + skb_shinfo(skb)->gso_segs = txtra.u.gso.segs; + skb_shinfo(skb)->gso_type = txtra.u.gso.type; + } gnttab_set_map_op(mop, MMAP_VADDR(pending_idx), GNTMAP_host_map | GNTMAP_readonly, @@ -782,7 +806,7 @@ static void net_tx_action(unsigned long __skb_put(skb, data_len); - skb_shinfo(skb)->nr_frags = ret - 1; + skb_shinfo(skb)->nr_frags = ret; if (data_len < txreq.size) { skb_shinfo(skb)->nr_frags++; skb_shinfo(skb)->frags[0].page = @@ -898,7 +922,7 @@ irqreturn_t netif_be_int(int irq, void * } static void make_tx_response(netif_t *netif, - u16 id, + netif_tx_request_t *txp, s8 st) { RING_IDX i = netif->tx.rsp_prod_pvt; @@ -906,8 +930,11 @@ static void make_tx_response(netif_t *ne int notify; resp = RING_GET_RESPONSE(&netif->tx, i); - resp->id = id; + resp->id = txp->id; resp->status = st; + + if (txp->flags & NETTXF_extra_info) + RING_GET_RESPONSE(&netif->tx, ++i)->status = NETIF_RSP_NULL; netif->tx.rsp_prod_pvt = ++i; RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->tx, notify); diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Wed Jun 28 07:52:21 2006 -0600 @@ -101,6 +101,12 @@ static int netback_probe(struct xenbus_d goto abort_transaction; } + err = xenbus_printf(xbt, dev->nodename, "feature-tso", "%d", 1); + if (err) { + message = "writing feature-tso"; + goto abort_transaction; + } + err = xenbus_transaction_end(xbt, 0); } while (err == -EAGAIN); diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/drivers/xen/tpmback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Wed Jun 28 07:52:21 2006 -0600 @@ -21,6 +21,8 @@ pr_debug("(file=%s, line=%d) " _f, \ __FILE__ , __LINE__ , ## _a ) +struct backend_info; + typedef struct tpmif_st { struct list_head tpmif_list; /* Unique identifier for this interface. */ @@ -43,7 +45,7 @@ typedef struct tpmif_st { struct list_head list; /* scheduling list */ atomic_t refcnt; - long int tpm_instance; + struct backend_info *bi; unsigned long mmap_vstart; grant_handle_t shmem_handle; @@ -54,7 +56,7 @@ typedef struct tpmif_st { } tpmif_t; void tpmif_disconnect_complete(tpmif_t * tpmif); -tpmif_t *tpmif_find(domid_t domid, long int instance); +tpmif_t *tpmif_find(domid_t domid, struct backend_info *bi); void tpmif_interface_init(void); void tpmif_interface_exit(void); void tpmif_schedule_work(tpmif_t * tpmif); @@ -63,10 +65,11 @@ void tpmif_xenbus_exit(void); void tpmif_xenbus_exit(void); int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn); irqreturn_t tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs); -int tpmif_vtpm_open(tpmif_t *tpmif, domid_t domain, u32 instance); -int tpmif_vtpm_close(u32 instance); + +long int tpmback_get_instance(struct backend_info *bi); int vtpm_release_packets(tpmif_t * tpmif, int send_msgs); + #define tpmif_get(_b) (atomic_inc(&(_b)->refcnt)) #define tpmif_put(_b) \ diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Wed Jun 28 07:52:21 2006 -0600 @@ -20,7 +20,7 @@ int num_frontends = 0; LIST_HEAD(tpmif_list); -static tpmif_t *alloc_tpmif(domid_t domid, long int instance) +static tpmif_t *alloc_tpmif(domid_t domid, struct backend_info *bi) { tpmif_t *tpmif; @@ -31,7 +31,7 @@ static tpmif_t *alloc_tpmif(domid_t domi memset(tpmif, 0, sizeof (*tpmif)); tpmif->domid = domid; tpmif->status = DISCONNECTED; - tpmif->tpm_instance = instance; + tpmif->bi = bi; snprintf(tpmif->devname, sizeof(tpmif->devname), "tpmif%d", domid); atomic_set(&tpmif->refcnt, 1); @@ -54,12 +54,12 @@ static void free_tpmif(tpmif_t * tpmif) kmem_cache_free(tpmif_cachep, tpmif); } -tpmif_t *tpmif_find(domid_t domid, long int instance) +tpmif_t *tpmif_find(domid_t domid, struct backend_info *bi) { tpmif_t *tpmif; list_for_each_entry(tpmif, &tpmif_list, tpmif_list) { - if (tpmif->tpm_instance == instance) { + if (tpmif->bi == bi) { if (tpmif->domid == domid) { tpmif_get(tpmif); return tpmif; @@ -69,7 +69,7 @@ tpmif_t *tpmif_find(domid_t domid, long } } - return alloc_tpmif(domid, instance); + return alloc_tpmif(domid, bi); } static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page) diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Wed Jun 28 07:52:21 2006 -0600 @@ -161,7 +161,7 @@ static struct packet *packet_alloc(tpmif if (NULL != pak) { if (tpmif) { pak->tpmif = tpmif; - pak->tpm_instance = tpmif->tpm_instance; + pak->tpm_instance = tpmback_get_instance(tpmif->bi); tpmif_get(tpmif); } pak->data_len = size; @@ -685,95 +685,6 @@ static struct miscdevice vtpms_miscdevic }; /*************************************************************** - Virtual TPM functions and data stuctures -***************************************************************/ - -static u8 create_cmd[] = { - 1, 193, /* 0: TPM_TAG_RQU_COMMAMD */ - 0, 0, 0, 19, /* 2: length */ - 0, 0, 0, 0x1, /* 6: VTPM_ORD_OPEN */ - 0, /* 10: VTPM type */ - 0, 0, 0, 0, /* 11: domain id */ - 0, 0, 0, 0 /* 15: instance id */ -}; - -int tpmif_vtpm_open(tpmif_t * tpmif, domid_t domid, u32 instance) -{ - int rc = 0; - struct packet *pak; - - pak = packet_alloc(tpmif, - sizeof (create_cmd), - create_cmd[1], - PACKET_FLAG_DISCARD_RESPONSE | - PACKET_FLAG_CHECK_RESPONSESTATUS); - if (pak) { - u8 buf[sizeof (create_cmd)]; - u32 domid_no = htonl((u32) domid); - u32 instance_no = htonl(instance); - - memcpy(buf, create_cmd, sizeof (create_cmd)); - - memcpy(&buf[11], &domid_no, sizeof (u32)); - memcpy(&buf[15], &instance_no, sizeof (u32)); - - /* copy the buffer into the packet */ - rc = packet_set(pak, buf, sizeof (buf)); - - if (rc == 0) { - pak->tpm_instance = 0; - rc = vtpm_queue_packet(pak); - } - if (rc < 0) { - /* could not be queued or built */ - packet_free(pak); - } - } else { - rc = -ENOMEM; - } - return rc; -} - -static u8 destroy_cmd[] = { - 1, 193, /* 0: TPM_TAG_RQU_COMMAMD */ - 0, 0, 0, 14, /* 2: length */ - 0, 0, 0, 0x2, /* 6: VTPM_ORD_CLOSE */ - 0, 0, 0, 0 /* 10: instance id */ -}; - -int tpmif_vtpm_close(u32 instid) -{ - int rc = 0; - struct packet *pak; - - pak = packet_alloc(NULL, - sizeof (destroy_cmd), - destroy_cmd[1], PACKET_FLAG_DISCARD_RESPONSE); - if (pak) { - u8 buf[sizeof (destroy_cmd)]; - u32 instid_no = htonl(instid); - - memcpy(buf, destroy_cmd, sizeof (destroy_cmd)); - memcpy(&buf[10], &instid_no, sizeof (u32)); - - /* copy the buffer into the packet */ - rc = packet_set(pak, buf, sizeof (buf)); - - if (rc == 0) { - pak->tpm_instance = 0; - rc = vtpm_queue_packet(pak); - } - if (rc < 0) { - /* could not be queued or built */ - packet_free(pak); - } - } else { - rc = -ENOMEM; - } - return rc; -} - -/*************************************************************** Utility functions ***************************************************************/ diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Wed Jun 28 07:52:21 2006 -0600 @@ -45,6 +45,14 @@ static void frontend_changed(struct xenb static void frontend_changed(struct xenbus_device *dev, enum xenbus_state frontend_state); +long int tpmback_get_instance(struct backend_info *bi) +{ + long int res = -1; + if (bi && bi->is_instance_set) + res = bi->instance; + return res; +} + static int tpmback_remove(struct xenbus_device *dev) { struct backend_info *be = dev->dev.driver_data; @@ -57,6 +65,7 @@ static int tpmback_remove(struct xenbus_ be->backend_watch.node = NULL; } if (be->tpmif) { + be->tpmif->bi = NULL; vtpm_release_packets(be->tpmif, 0); tpmif_put(be->tpmif); be->tpmif = NULL; @@ -150,15 +159,10 @@ static void frontend_changed(struct xenb break; case XenbusStateClosing: - be->tpmif->tpm_instance = -1; + be->instance = -1; break; case XenbusStateClosed: - /* - * Notify the vTPM manager about the front-end - * having left. - */ - tpmif_vtpm_close(be->instance); device_unregister(&be->dev->dev); tpmback_remove(dev); break; @@ -177,28 +181,10 @@ static void frontend_changed(struct xenb static void maybe_connect(struct backend_info *be) { - int err; - if (be->tpmif == NULL || be->tpmif->status == CONNECTED) return; connect(be); - - /* - * Notify the vTPM manager about a new front-end. - */ - err = tpmif_vtpm_open(be->tpmif, - be->frontend_id, - be->instance); - if (err) { - xenbus_dev_error(be->dev, err, - "queueing vtpm open packet"); - /* - * Should close down this device and notify FE - * about closure. - */ - return; - } } @@ -256,8 +242,7 @@ static int connect_ring(struct backend_i } if (!be->tpmif) { - be->tpmif = tpmif_find(dev->otherend_id, - be->instance); + be->tpmif = tpmif_find(dev->otherend_id, be); if (IS_ERR(be->tpmif)) { err = PTR_ERR(be->tpmif); be->tpmif = NULL; diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/include/linux/skbuff.h --- a/linux-2.6-xen-sparse/include/linux/skbuff.h Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/include/linux/skbuff.h Wed Jun 28 07:52:21 2006 -0600 @@ -134,9 +134,10 @@ struct skb_shared_info { struct skb_shared_info { atomic_t dataref; unsigned short nr_frags; - unsigned short tso_size; - unsigned short tso_segs; - unsigned short ufo_size; + unsigned short gso_size; + /* Warning: this field is not always filled in (UFO)! */ + unsigned short gso_segs; + unsigned short gso_type; unsigned int ip6_frag_id; struct sk_buff *frag_list; skb_frag_t frags[MAX_SKB_FRAGS]; @@ -166,6 +167,14 @@ enum { SKB_FCLONE_UNAVAILABLE, SKB_FCLONE_ORIG, SKB_FCLONE_CLONE, +}; + +enum { + SKB_GSO_TCPV4 = 1 << 0, + SKB_GSO_UDPV4 = 1 << 1, + + /* This indicates the skb is from an untrusted source. */ + SKB_GSO_DODGY = 1 << 2, }; /** @@ -1157,18 +1166,34 @@ static inline int skb_can_coalesce(struc return 0; } +static inline int __skb_linearize(struct sk_buff *skb) +{ + return __pskb_pull_tail(skb, skb->data_len) ? 0 : -ENOMEM; +} + /** * skb_linearize - convert paged skb to linear one * @skb: buffer to linarize - * @gfp: allocation mode * * If there is no free memory -ENOMEM is returned, otherwise zero * is returned and the old skb data released. */ -extern int __skb_linearize(struct sk_buff *skb, gfp_t gfp); -static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp) -{ - return __skb_linearize(skb, gfp); +static inline int skb_linearize(struct sk_buff *skb) +{ + return skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0; +} + +/** + * skb_linearize_cow - make sure skb is linear and writable + * @skb: buffer to process + * + * If there is no free memory -ENOMEM is returned, otherwise zero + * is returned and the old skb data released. + */ +static inline int skb_linearize_cow(struct sk_buff *skb) +{ + return skb_is_nonlinear(skb) || skb_cloned(skb) ? + __skb_linearize(skb) : 0; } /** @@ -1263,6 +1288,7 @@ extern void skb_split(struct sk_b struct sk_buff *skb1, const u32 len); extern void skb_release_data(struct sk_buff *skb); +extern struct sk_buff *skb_segment(struct sk_buff *skb, int features); static inline void *skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer) diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/net/core/dev.c --- a/linux-2.6-xen-sparse/net/core/dev.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/net/core/dev.c Wed Jun 28 07:52:21 2006 -0600 @@ -115,6 +115,7 @@ #include <net/iw_handler.h> #endif /* CONFIG_NET_RADIO */ #include <asm/current.h> +#include <linux/err.h> #ifdef CONFIG_XEN #include <net/ip.h> @@ -1038,7 +1039,7 @@ static inline void net_timestamp(struct * taps currently in use. */ -void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) +static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) { struct packet_type *ptype; @@ -1112,6 +1113,45 @@ out: return ret; } +/** + * skb_gso_segment - Perform segmentation on skb. + * @skb: buffer to segment + * @features: features for the output path (see dev->features) + * + * This function segments the given skb and returns a list of segments. + * + * It may return NULL if the skb requires no segmentation. This is + * only possible when GSO is used for verifying header integrity. + */ +struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) +{ + struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); + struct packet_type *ptype; + int type = skb->protocol; + + BUG_ON(skb_shinfo(skb)->frag_list); + BUG_ON(skb->ip_summed != CHECKSUM_HW); + + skb->mac.raw = skb->data; + skb->mac_len = skb->nh.raw - skb->data; + __skb_pull(skb, skb->mac_len); + + rcu_read_lock(); + list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) { + if (ptype->type == type && !ptype->dev && ptype->gso_segment) { + segs = ptype->gso_segment(skb, features); + break; + } + } + rcu_read_unlock(); + + __skb_push(skb, skb->data - skb->mac.raw); + + return segs; +} + +EXPORT_SYMBOL(skb_gso_segment); + /* Take action when hardware reception checksum errors are detected. */ #ifdef CONFIG_BUG void netdev_rx_csum_fault(struct net_device *dev) @@ -1148,75 +1188,108 @@ static inline int illegal_highdma(struct #define illegal_highdma(dev, skb) (0) #endif -/* Keep head the same: replace data */ -int __skb_linearize(struct sk_buff *skb, gfp_t gfp_mask) -{ - unsigned int size; - u8 *data; - long offset; - struct skb_shared_info *ninfo; - int headerlen = skb->data - skb->head; - int expand = (skb->tail + skb->data_len) - skb->end; - - if (skb_shared(skb)) - BUG(); - - if (expand <= 0) - expand = 0; - - size = skb->end - skb->head + expand; - size = SKB_DATA_ALIGN(size); - data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask); - if (!data) - return -ENOMEM; - - /* Copy entire thing */ - if (skb_copy_bits(skb, -headerlen, data, headerlen + skb->len)) - BUG(); - - /* Set up shinfo */ - ninfo = (struct skb_shared_info*)(data + size); - atomic_set(&ninfo->dataref, 1); - ninfo->tso_size = skb_shinfo(skb)->tso_size; - ninfo->tso_segs = skb_shinfo(skb)->tso_segs; - ninfo->nr_frags = 0; - ninfo->frag_list = NULL; - - /* Offset between the two in bytes */ - offset = data - skb->head; - - /* Free old data. */ - skb_release_data(skb); - - skb->head = data; - skb->end = data + size; - - /* Set up new pointers */ - skb->h.raw += offset; - skb->nh.raw += offset; - skb->mac.raw += offset; - skb->tail += offset; - skb->data += offset; - - /* We are no longer a clone, even if we were. */ - skb->cloned = 0; - - skb->tail += skb->data_len; - skb->data_len = 0; +struct dev_gso_cb { + void (*destructor)(struct sk_buff *skb); +}; + +#define DEV_GSO_CB(skb) ((struct dev_gso_cb *)(skb)->cb) + +static void dev_gso_skb_destructor(struct sk_buff *skb) +{ + struct dev_gso_cb *cb; + + do { + struct sk_buff *nskb = skb->next; + + skb->next = nskb->next; + nskb->next = NULL; + kfree_skb(nskb); + } while (skb->next); + + cb = DEV_GSO_CB(skb); + if (cb->destructor) + cb->destructor(skb); +} + +/** + * dev_gso_segment - Perform emulated hardware segmentation on skb. + * @skb: buffer to segment + * + * This function segments the given skb and stores the list of segments + * in skb->next. + */ +static int dev_gso_segment(struct sk_buff *skb) +{ + struct net_device *dev = skb->dev; + struct sk_buff *segs; + int features = dev->features & ~(illegal_highdma(dev, skb) ? + NETIF_F_SG : 0); + + segs = skb_gso_segment(skb, features); + + /* Verifying header integrity only. */ + if (!segs) + return 0; + + if (unlikely(IS_ERR(segs))) + return PTR_ERR(segs); + + skb->next = segs; + DEV_GSO_CB(skb)->destructor = skb->destructor; + skb->destructor = dev_gso_skb_destructor; + + return 0; +} + +int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + if (likely(!skb->next)) { + if (netdev_nit) + dev_queue_xmit_nit(skb, dev); + + if (netif_needs_gso(dev, skb)) { + if (unlikely(dev_gso_segment(skb))) + goto out_kfree_skb; + if (skb->next) + goto gso; + } + + return dev->hard_start_xmit(skb, dev); + } + +gso: + do { + struct sk_buff *nskb = skb->next; + int rc; + + skb->next = nskb->next; + nskb->next = NULL; + rc = dev->hard_start_xmit(nskb, dev); + if (unlikely(rc)) { + nskb->next = skb->next; + skb->next = nskb; + return rc; + } + if (unlikely(netif_queue_stopped(dev) && skb->next)) + return NETDEV_TX_BUSY; + } while (skb->next); + + skb->destructor = DEV_GSO_CB(skb)->destructor; + +out_kfree_skb: + kfree_skb(skb); return 0; } #define HARD_TX_LOCK(dev, cpu) { \ if ((dev->features & NETIF_F_LLTX) == 0) { \ - spin_lock(&dev->xmit_lock); \ - dev->xmit_lock_owner = cpu; \ + netif_tx_lock(dev); \ } \ } #define HARD_TX_UNLOCK(dev) { \ if ((dev->features & NETIF_F_LLTX) == 0) { \ - dev->xmit_lock_owner = -1; \ - spin_unlock(&dev->xmit_lock); \ + netif_tx_unlock(dev); \ } \ } @@ -1289,9 +1362,19 @@ int dev_queue_xmit(struct sk_buff *skb) struct Qdisc *q; int rc = -ENOMEM; + /* If a checksum-deferred packet is forwarded to a device that needs a + * checksum, correct the pointers and force checksumming. + */ + if (skb_checksum_setup(skb)) + goto out_kfree_skb; + + /* GSO will handle the following emulations directly. */ + if (netif_needs_gso(dev, skb)) + goto gso; + if (skb_shinfo(skb)->frag_list && !(dev->features & NETIF_F_FRAGLIST) && - __skb_linearize(skb, GFP_ATOMIC)) + __skb_linearize(skb)) goto out_kfree_skb; /* Fragmented skb is linearized if device does not support SG, @@ -1300,31 +1383,26 @@ int dev_queue_xmit(struct sk_buff *skb) */ if (skb_shinfo(skb)->nr_frags && (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) && - __skb_linearize(skb, GFP_ATOMIC)) + __skb_linearize(skb)) goto out_kfree_skb; - /* If a checksum-deferred packet is forwarded to a device that needs a - * checksum, correct the pointers and force checksumming. - */ - if(skb_checksum_setup(skb)) - goto out_kfree_skb; - /* If packet is not checksummed and device does not support * checksumming for this protocol, complete checksumming here. */ if (skb->ip_summed == CHECKSUM_HW && - (!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) && + (!(dev->features & NETIF_F_GEN_CSUM) && (!(dev->features & NETIF_F_IP_CSUM) || skb->protocol != htons(ETH_P_IP)))) if (skb_checksum_help(skb, 0)) goto out_kfree_skb; +gso: spin_lock_prefetch(&dev->queue_lock); /* Disable soft irqs for various locks below. Also * stops preemption for RCU. */ - local_bh_disable(); + rcu_read_lock_bh(); /* Updates of qdisc are serialized by queue_lock. * The struct Qdisc which is pointed to by qdisc is now a @@ -1358,8 +1436,8 @@ int dev_queue_xmit(struct sk_buff *skb) /* The device has no queue. Common case for software devices: loopback, all the sorts of tunnels... - Really, it is unlikely that xmit_lock protection is necessary here. - (f.e. loopback and IP tunnels are clean ignoring statistics + Really, it is unlikely that netif_tx_lock protection is necessary + here. (f.e. loopback and IP tunnels are clean ignoring statistics counters.) However, it is possible, that they rely on protection made by us here. @@ -1375,11 +1453,8 @@ int dev_queue_xmit(struct sk_buff *skb) HARD_TX_LOCK(dev, cpu); if (!netif_queue_stopped(dev)) { - if (netdev_nit) - dev_queue_xmit_nit(skb, dev); - rc = 0; - if (!dev->hard_start_xmit(skb, dev)) { + if (!dev_hard_start_xmit(skb, dev)) { HARD_TX_UNLOCK(dev); goto out; } @@ -1398,13 +1473,13 @@ int dev_queue_xmit(struct sk_buff *skb) } rc = -ENETDOWN; - local_bh_enable(); + rcu_read_unlock_bh(); out_kfree_skb: kfree_skb(skb); return rc; out: - local_bh_enable(); + rcu_read_unlock_bh(); return rc; } @@ -2732,7 +2807,7 @@ int register_netdevice(struct net_device BUG_ON(dev->reg_state != NETREG_UNINITIALIZED); spin_lock_init(&dev->queue_lock); - spin_lock_init(&dev->xmit_lock); + spin_lock_init(&dev->_xmit_lock); dev->xmit_lock_owner = -1; #ifdef CONFIG_NET_CLS_ACT spin_lock_init(&dev->ingress_lock); @@ -2776,9 +2851,7 @@ int register_netdevice(struct net_device /* Fix illegal SG+CSUM combinations. */ if ((dev->features & NETIF_F_SG) && - !(dev->features & (NETIF_F_IP_CSUM | - NETIF_F_NO_CSUM | - NETIF_F_HW_CSUM))) { + !(dev->features & NETIF_F_ALL_CSUM)) { printk("%s: Dropping NETIF_F_SG since no checksum feature.\n", dev->name); dev->features &= ~NETIF_F_SG; @@ -3330,7 +3403,6 @@ EXPORT_SYMBOL(__dev_get_by_index); EXPORT_SYMBOL(__dev_get_by_index); EXPORT_SYMBOL(__dev_get_by_name); EXPORT_SYMBOL(__dev_remove_pack); -EXPORT_SYMBOL(__skb_linearize); EXPORT_SYMBOL(dev_valid_name); EXPORT_SYMBOL(dev_add_pack); EXPORT_SYMBOL(dev_alloc_name); diff -r c4b68afe97d3 -r 4b51d081378d linux-2.6-xen-sparse/net/core/skbuff.c --- a/linux-2.6-xen-sparse/net/core/skbuff.c Wed Jun 28 07:51:52 2006 -0600 +++ b/linux-2.6-xen-sparse/net/core/skbuff.c Wed Jun 28 07:52:21 2006 -0600 @@ -165,9 +165,9 @@ struct sk_buff *__alloc_skb(unsigned int shinfo = skb_shinfo(skb); atomic_set(&shinfo->dataref, 1); shinfo->nr_frags = 0; - shinfo->tso_size = 0; - shinfo->tso_segs = 0; - shinfo->ufo_size = 0; + shinfo->gso_size = 0; + shinfo->gso_segs = 0; + shinfo->gso_type = 0; shinfo->ip6_frag_id = 0; shinfo->frag_list = NULL; @@ -237,9 +237,9 @@ struct sk_buff *alloc_skb_from_cache(kme shinfo = skb_shinfo(skb); atomic_set(&shinfo->dataref, 1); shinfo->nr_frags = 0; - shinfo->tso_size = 0; - shinfo->tso_segs = 0; - shinfo->ufo_size = 0; + shinfo->gso_size = 0; + shinfo->gso_segs = 0; + shinfo->gso_type = 0; shinfo->ip6_frag_id = 0; shinfo->frag_list = NULL; @@ -524,8 +524,9 @@ static void copy_skb_header(struct sk_bu new->tc_index = old->tc_index; #endif atomic_set(&new->users, 1); - skb_shinfo(new)->tso_size = skb_shinfo(old)->tso_size; - skb_shinfo(new)->tso_segs = skb_shinfo(old)->tso_segs; + skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size; + skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs; + skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type; } /** @@ -1799,6 +1800,133 @@ int skb_append_datato_frags(struct sock return 0; } + +/** + * skb_segment - Perform protocol segmentation on skb. + * @skb: buffer to segment + * @features: features for the output path (see dev->features) + * + * This function performs segmentation on the given skb. It returns + * the segment at the given position. It returns NULL if there are + * no more segments to generate, or when an error is encountered. + */ +struct sk_buff *skb_segment(struct sk_buff *skb, int features) +{ + struct sk_buff *segs = NULL; + struct sk_buff *tail = NULL; + unsigned int mss = skb_shinfo(skb)->gso_size; + unsigned int doffset = skb->data - skb->mac.raw; + unsigned int offset = doffset; + unsigned int headroom; + unsigned int len; + int sg = features & NETIF_F_SG; + int nfrags = skb_shinfo(skb)->nr_frags; + int err = -ENOMEM; + int i = 0; + int pos; + + __skb_push(skb, doffset); + headroom = skb_headroom(skb); + pos = skb_headlen(skb); + + do { + struct sk_buff *nskb; + skb_frag_t *frag; + int hsize, nsize; + int k; + int size; + + len = skb->len - offset; + if (len > mss) + len = mss; + + hsize = skb_headlen(skb) - offset; + if (hsize < 0) + hsize = 0; + nsize = hsize + doffset; + if (nsize > len + doffset || !sg) + nsize = len + doffset; + + nskb = alloc_skb(nsize + headroom, GFP_ATOMIC); + if (unlikely(!nskb)) + goto err; + + if (segs) + tail->next = nskb; + else + segs = nskb; + tail = nskb; + + nskb->dev = skb->dev; + nskb->priority = skb->priority; + nskb->protocol = skb->protocol; + nskb->dst = dst_clone(skb->dst); + memcpy(nskb->cb, skb->cb, sizeof(skb->cb)); + nskb->pkt_type = skb->pkt_type; + nskb->mac_len = skb->mac_len; + + skb_reserve(nskb, headroom); + nskb->mac.raw = nskb->data; + nskb->nh.raw = nskb->data + skb->mac_len; + nskb->h.raw = nskb->nh.raw + (skb->h.raw - skb->nh.raw); + memcpy(skb_put(nskb, doffset), skb->data, doffset); + + if (!sg) { + nskb->csum = skb_copy_and_csum_bits(skb, offset, + skb_put(nskb, len), + len, 0); + continue; + } + + frag = skb_shinfo(nskb)->frags; + k = 0; + + nskb->ip_summed = CHECKSUM_HW; + nskb->csum = skb->csum; + memcpy(skb_put(nskb, hsize), skb->data + offset, hsize); + + while (pos < offset + len) { + BUG_ON(i >= nfrags); + + *frag = skb_shinfo(skb)->frags[i]; + get_page(frag->page); + size = frag->size; + + if (pos < offset) { + frag->page_offset += offset - pos; + frag->size -= offset - pos; + } + + k++; + + if (pos + size <= offset + len) { + i++; + pos += size; + } else { + frag->size -= pos + size - (offset + len); + break; + } + + frag++; + } + + skb_shinfo(nskb)->nr_frags = k; + nskb->data_len = len - hsize; + nskb->len += nskb->data_len; + nskb->truesize += nskb->data_len; + } while ((offset += len) < skb->len); + + return segs; + +err: + while ((skb = segs)) { + segs = skb->next; + kfree(skb); + } + return ERR_PTR(err); +} + +EXPORT_SYMBOL_GPL(skb_segment); void __init skb_init(void) { diff -r c4b68afe97d3 -r 4b51d081378d patches/linux-2.6.16.13/xenoprof-generic.patch --- a/patches/linux-2.6.16.13/xenoprof-generic.patch Wed Jun 28 07:51:52 2006 -0600 +++ b/patches/linux-2.6.16.13/xenoprof-generic.patch Wed Jun 28 07:52:21 2006 -0600 @@ -1,6 +1,6 @@ diff -pruN ../pristine-linux-2.6.16.13/d -diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c ./drivers/oprofile/buffer_sync.c ---- ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c 2006-05-02 22:38:44.000000000 +0100 -+++ ./drivers/oprofile/buffer_sync.c 2006-05-04 17:41:51.000000000 +0100 +diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c ./drivers/oprofile/buffer_sync.c +--- ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c 2006-05-03 05:38:44.000000000 +0800 ++++ ./drivers/oprofile/buffer_sync.c 2006-06-27 12:14:53.000000000 +0800 @@ -6,6 +6,10 @@ * * @author John Levon <levon@xxxxxxxxxxxxxxxxx> @@ -12,7 +12,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d * This is the core of the buffer management. Each * CPU buffer is processed and entered into the * global event buffer. Such processing is necessary -@@ -275,15 +279,24 @@ static void add_cpu_switch(int i) +@@ -275,15 +279,30 @@ static void add_cpu_switch(int i) last_cookie = INVALID_COOKIE; } @@ -33,7 +33,13 @@ diff -pruN ../pristine-linux-2.6.16.13/d + break; + case CPU_MODE_XEN: + add_event_entry(XEN_ENTER_SWITCH_CODE); -+ break; ++ break; ++ case CPU_MODE_PASSIVE_START: ++ add_event_entry(PASSIVE_START_CODE); ++ break; ++ case CPU_MODE_PASSIVE_STOP: ++ add_event_entry(PASSIVE_STOP_CODE); ++ break; + default: + break; + } @@ -43,7 +49,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d static void add_user_ctx_switch(struct task_struct const * task, unsigned long cookie) { -@@ -348,9 +361,9 @@ static int add_us_sample(struct mm_struc +@@ -348,9 +367,9 @@ static int add_us_sample(struct mm_struc * for later lookup from userspace. */ static int @@ -55,7 +61,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d add_sample_entry(s->eip, s->event); return 1; } else if (mm) { -@@ -496,7 +509,7 @@ void sync_buffer(int cpu) +@@ -496,10 +515,11 @@ void sync_buffer(int cpu) struct mm_struct *mm = NULL; struct task_struct * new; unsigned long cookie = 0; @@ -64,34 +70,62 @@ diff -pruN ../pristine-linux-2.6.16.13/d unsigned int i; sync_buffer_state state = sb_buffer_start; unsigned long available; -@@ -513,12 +526,12 @@ void sync_buffer(int cpu) ++ int domain_switch = NO_DOMAIN_SWITCH; + + down(&buffer_sem); + +@@ -513,12 +533,19 @@ void sync_buffer(int cpu) struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos]; if (is_code(s->eip)) { - if (s->event <= CPU_IS_KERNEL) { -+ if (s->event <= CPU_MODE_XEN) { ++ if (s->event < CPU_TRACE_BEGIN) { /* kernel/userspace switch */ - in_kernel = s->event; + cpu_mode = s->event; if (state == sb_buffer_start) state = sb_sample_start; - add_kernel_ctx_switch(s->event); -+ add_cpu_mode_switch(s->event); ++ ++ if (s->event == CPU_MODE_PASSIVE_START) ++ domain_switch = DOMAIN_SWITCH_START_EVENT1; ++ else if (s->event == CPU_MODE_PASSIVE_STOP) ++ domain_switch = DOMAIN_SWITCH_STOP_EVENT1; ++ ++ if (domain_switch != DOMAIN_SWITCH_START_EVENT2) ++ add_cpu_mode_switch(s->event); } else if (s->event == CPU_TRACE_BEGIN) { state = sb_bt_start; add_trace_begin(); -@@ -536,7 +549,7 @@ void sync_buffer(int cpu) +@@ -535,11 +562,20 @@ void sync_buffer(int cpu) + add_user_ctx_switch(new, cookie); } } else { - if (state >= sb_bt_start && +- if (state >= sb_bt_start && - !add_sample(mm, s, in_kernel)) { -+ !add_sample(mm, s, cpu_mode)) { - if (state == sb_bt_start) { - state = sb_bt_ignore; - atomic_inc(&oprofile_stats.bt_lost_no_mapping); -diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c ./drivers/oprofile/cpu_buffer.c ---- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c 2006-05-02 22:38:44.000000000 +0100 -+++ ./drivers/oprofile/cpu_buffer.c 2006-05-04 17:41:51.000000000 +0100 +- if (state == sb_bt_start) { +- state = sb_bt_ignore; +- atomic_inc(&oprofile_stats.bt_lost_no_mapping); ++ if (domain_switch == DOMAIN_SWITCH_START_EVENT1) { ++ add_event_entry(s->event); ++ domain_switch = DOMAIN_SWITCH_START_EVENT2; ++ } else if (domain_switch == DOMAIN_SWITCH_START_EVENT1) { ++ add_sample_entry(s->eip, s->event); ++ } else if (domain_switch == DOMAIN_SWITCH_STOP_EVENT1) { ++ domain_switch = NO_DOMAIN_SWITCH; ++ } else { ++ if (state >= sb_bt_start && ++ !add_sample(mm, s, cpu_mode)) { ++ if (state == sb_bt_start) { ++ state = sb_bt_ignore; ++ atomic_inc(&oprofile_stats.bt_lost_no_mapping); ++ } + } + } + } +diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c ./drivers/oprofile/cpu_buffer.c +--- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c 2006-05-03 05:38:44.000000000 +0800 ++++ ./drivers/oprofile/cpu_buffer.c 2006-06-19 22:43:53.000000000 +0800 @@ -6,6 +6,10 @@ * * @author John Levon <levon@xxxxxxxxxxxxxxxxx> @@ -139,13 +173,12 @@ diff -pruN ../pristine-linux-2.6.16.13/d { struct task_struct * task; -@@ -181,16 +185,16 @@ static int log_sample(struct oprofile_cp +@@ -181,16 +185,14 @@ static int log_sample(struct oprofile_cp return 0; } - is_kernel = !!is_kernel; -+ WARN_ON(cpu_mode > CPU_MODE_XEN); - +- task = current; /* notice a switch from user->kernel or vice versa */ @@ -161,9 +194,9 @@ diff -pruN ../pristine-linux-2.6.16.13/d /* notice a task switch */ if (cpu_buf->last_task != task) { cpu_buf->last_task = task; -diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h ./drivers/oprofile/cpu_buffer.h ---- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h 2006-05-02 22:38:44.000000000 +0100 -+++ ./drivers/oprofile/cpu_buffer.h 2006-05-04 17:41:51.000000000 +0100 +diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h ./drivers/oprofile/cpu_buffer.h +--- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h 2006-05-03 05:38:44.000000000 +0800 ++++ ./drivers/oprofile/cpu_buffer.h 2006-06-27 10:38:08.000000000 +0800 @@ -36,7 +36,7 @@ struct oprofile_cpu_buffer { volatile unsigned long tail_pos; unsigned long buffer_size; @@ -173,22 +206,26 @@ diff -pruN ../pristine-linux-2.6.16.13/d int tracing; struct op_sample * buffer; unsigned long sample_received; -@@ -51,7 +51,9 @@ extern struct oprofile_cpu_buffer cpu_bu +@@ -51,7 +51,13 @@ extern struct oprofile_cpu_buffer cpu_bu void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf); /* transient events for the CPU buffer -> event buffer */ -#define CPU_IS_KERNEL 1 -#define CPU_TRACE_BEGIN 2 -+#define CPU_MODE_USER 0 -+#define CPU_MODE_KERNEL 1 -+#define CPU_MODE_XEN 2 -+#define CPU_TRACE_BEGIN 3 ++#define CPU_MODE_USER 0 ++#define CPU_MODE_KERNEL 1 ++#define CPU_MODE_XEN 2 ++#define CPU_MODE_PASSIVE_START 3 ++#define CPU_MODE_PASSIVE_STOP 4 ++#define CPU_TRACE_BEGIN 5 ++ ++#define IGNORED_PC 0 #endif /* OPROFILE_CPU_BUFFER_H */ -diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h ./drivers/oprofile/event_buffer.h ---- ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h 2006-05-02 22:38:44.000000000 +0100 -+++ ./drivers/oprofile/event_buffer.h 2006-05-04 17:41:51.000000000 +0100 -@@ -29,11 +29,12 @@ void wake_up_buffer_waiter(void); +diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h ./drivers/oprofile/event_buffer.h +--- ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h 2006-05-03 05:38:44.000000000 +0800 ++++ ./drivers/oprofile/event_buffer.h 2006-06-19 22:43:53.000000000 +0800 +@@ -29,11 +29,14 @@ void wake_up_buffer_waiter(void); #define CPU_SWITCH_CODE 2 #define COOKIE_SWITCH_CODE 3 #define KERNEL_ENTER_SWITCH_CODE 4 @@ -199,12 +236,14 @@ diff -pruN ../pristine-linux-2.6.16.13/d #define TRACE_BEGIN_CODE 8 #define TRACE_END_CODE 9 +#define XEN_ENTER_SWITCH_CODE 10 ++#define PASSIVE_START_CODE 11 ++#define PASSIVE_STOP_CODE 12 #define INVALID_COOKIE ~0UL #define NO_COOKIE 0UL -diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c ./drivers/oprofile/oprof.c ---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c 2006-05-02 22:38:44.000000000 +0100 -+++ ./drivers/oprofile/oprof.c 2006-05-04 17:41:51.000000000 +0100 +diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c ./drivers/oprofile/oprof.c +--- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c 2006-05-03 05:38:44.000000000 +0800 ++++ ./drivers/oprofile/oprof.c 2006-06-19 23:45:17.000000000 +0800 @@ -5,6 +5,10 @@ * @remark Read the file COPYING * @@ -225,7 +264,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d struct oprofile_operations oprofile_ops; unsigned long oprofile_started; -@@ -33,6 +37,19 @@ static DECLARE_MUTEX(start_sem); +@@ -33,6 +37,32 @@ static DECLARE_MUTEX(start_sem); */ static int timer = 0; @@ -242,23 +281,37 @@ diff -pruN ../pristine-linux-2.6.16.13/d + return err; +} + ++int oprofile_set_passive(int passive_domains[], unsigned int pdomains) ++{ ++ int err; ++ ++ if (!oprofile_ops.set_passive) ++ return -EINVAL; ++ ++ down(&start_sem); ++ err = oprofile_ops.set_passive(passive_domains, pdomains); ++ up(&start_sem); ++ return err; ++} ++ int oprofile_setup(void) { int err; -diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h ./drivers/oprofile/oprof.h ---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h 2006-05-02 22:38:44.000000000 +0100 -+++ ./drivers/oprofile/oprof.h 2006-05-04 17:41:51.000000000 +0100 -@@ -35,5 +35,7 @@ void oprofile_create_files(struct super_ +diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h ./drivers/oprofile/oprof.h +--- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h 2006-05-03 05:38:44.000000000 +0800 ++++ ./drivers/oprofile/oprof.h 2006-06-19 23:42:36.000000000 +0800 +@@ -35,5 +35,8 @@ void oprofile_create_files(struct super_ void oprofile_timer_init(struct oprofile_operations * ops); int oprofile_set_backtrace(unsigned long depth); + +int oprofile_set_active(int active_domains[], unsigned int adomains); ++int oprofile_set_passive(int passive_domains[], unsigned int pdomains); #endif /* OPROF_H */ -diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c ./drivers/oprofile/oprofile_files.c ---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c 2006-05-02 22:38:44.000000000 +0100 -+++ ./drivers/oprofile/oprofile_files.c 2006-05-04 17:41:51.000000000 +0100 +diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c ./drivers/oprofile/oprofile_files.c +--- ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c 2006-05-03 05:38:44.000000000 +0800 ++++ ./drivers/oprofile/oprofile_files.c 2006-06-19 23:29:07.000000000 +0800 @@ -5,15 +5,21 @@ * @remark Read the file COPYING * @@ -282,7 +335,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d unsigned long fs_buffer_size = 131072; unsigned long fs_cpu_buffer_size = 8192; unsigned long fs_buffer_watershed = 32768; /* FIXME: tune */ -@@ -117,11 +123,108 @@ static ssize_t dump_write(struct file * +@@ -117,11 +123,202 @@ static ssize_t dump_write(struct file * static struct file_operations dump_fops = { .write = dump_write, }; @@ -384,17 +437,110 @@ diff -pruN ../pristine-linux-2.6.16.13/d + .write = adomain_write, +}; + ++static unsigned int pdomains = 0; ++static int passive_domains[MAX_OPROF_DOMAINS]; ++static DEFINE_MUTEX(pdom_mutex); ++ ++static ssize_t pdomain_write(struct file * file, char const __user * buf, ++ size_t count, loff_t * offset) ++{ ++ char *tmpbuf; ++ char *startp, *endp; ++ int i; ++ unsigned long val; ++ ssize_t retval = count; ++ ++ if (*offset) ++ return -EINVAL; ++ if (count > TMPBUFSIZE - 1) ++ return -EINVAL; ++ ++ if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL))) ++ return -ENOMEM; ++ ++ if (copy_from_user(tmpbuf, buf, count)) { ++ kfree(tmpbuf); ++ return -EFAULT; ++ } ++ tmpbuf[count] = 0; ++ ++ mutex_lock(&pdom_mutex); ++ ++ startp = tmpbuf; ++ /* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */ ++ for (i = 0; i <= MAX_OPROF_DOMAINS; i++) { ++ val = simple_strtoul(startp, &endp, 0); ++ if (endp == startp) ++ break; ++ while (ispunct(*endp) || isspace(*endp)) ++ endp++; ++ passive_domains[i] = val; ++ if (passive_domains[i] != val) ++ /* Overflow, force error below */ ++ i = MAX_OPROF_DOMAINS + 1; ++ startp = endp; ++ } ++ /* Force error on trailing junk */ ++ pdomains = *startp ? MAX_OPROF_DOMAINS + 1 : i; ++ ++ kfree(tmpbuf); ++ ++ if (pdomains > MAX_OPROF_DOMAINS ++ || oprofile_set_passive(passive_domains, pdomains)) { ++ pdomains = 0; ++ retval = -EINVAL; ++ } ++ ++ mutex_unlock(&pdom_mutex); ++ return retval; ++} ++ ++static ssize_t pdomain_read(struct file * file, char __user * buf, ++ size_t count, loff_t * offset) ++{ ++ char * tmpbuf; ++ size_t len; ++ int i; ++ ssize_t retval; ++ ++ if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL))) ++ return -ENOMEM; ++ ++ mutex_lock(&pdom_mutex); ++ ++ len = 0; ++ for (i = 0; i < pdomains; i++) ++ len += snprintf(tmpbuf + len, ++ len < TMPBUFSIZE ? TMPBUFSIZE - len : 0, ++ "%u ", passive_domains[i]); ++ WARN_ON(len > TMPBUFSIZE); ++ if (len != 0 && len <= TMPBUFSIZE) ++ tmpbuf[len-1] = '\n'; ++ ++ mutex_unlock(&pdom_mutex); ++ ++ retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len); ++ ++ kfree(tmpbuf); ++ return retval; ++} ++ ++static struct file_operations passive_domain_ops = { ++ .read = pdomain_read, ++ .write = pdomain_write, ++}; ++ void oprofile_create_files(struct super_block * sb, struct dentry * root) { oprofilefs_create_file(sb, root, "enable", &enable_fops); oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666); + oprofilefs_create_file(sb, root, "active_domains", &active_domain_ops); ++ oprofilefs_create_file(sb, root, "passive_domains", &passive_domain_ops); oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops); oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size); oprofilefs_create_ulong(sb, root, "buffer_watershed", &fs_buffer_watershed); -diff -pruN ../pristine-linux-2.6.16.13/include/linux/oprofile.h ./include/linux/oprofile.h ---- ../pristine-linux-2.6.16.13/include/linux/oprofile.h 2006-05-02 22:38:44.000000000 +0100 -+++ ./include/linux/oprofile.h 2006-05-04 17:41:51.000000000 +0100 +--- ../pristine-linux-2.6.16.13/include/linux/oprofile.h 2006-05-03 05:38:44.000000000 +0800 ++++ ./include/linux/oprofile.h 2006-06-19 23:52:00.000000000 +0800 @@ -16,6 +16,8 @@ #include <linux/types.h> #include <linux/spinlock.h> @@ -404,12 +550,15 @@ diff -pruN ../pristine-linux-2.6.16.13/i struct super_block; struct dentry; -@@ -27,6 +29,8 @@ struct oprofile_operations { +@@ -27,6 +29,11 @@ struct oprofile_operations { /* create any necessary configuration files in the oprofile fs. * Optional. */ int (*create_files)(struct super_block * sb, struct dentry * root); + /* setup active domains with Xen */ + int (*set_active)(int *active_domains, unsigned int adomains); ++ /* setup passive domains with Xen */ ++ int (*set_passive)(int *passive_domains, unsigned int pdomains); ++ /* Do any necessary interrupt setup. Optional. */ int (*setup)(void); /* Do any necessary interrupt shutdown. Optional. */ diff -r c4b68afe97d3 -r 4b51d081378d tools/Makefile --- a/tools/Makefile Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/Makefile Wed Jun 28 07:52:21 2006 -0600 @@ -45,6 +45,9 @@ clean: check_clean done $(MAKE) ioemuclean +.PHONY: distclean +distclean: clean + .PHONY: check check: $(MAKE) -C check diff -r c4b68afe97d3 -r 4b51d081378d tools/examples/Makefile --- a/tools/examples/Makefile Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/examples/Makefile Wed Jun 28 07:52:21 2006 -0600 @@ -32,7 +32,7 @@ XEN_SCRIPT_DATA = xen-script-common.sh l XEN_SCRIPT_DATA = xen-script-common.sh locking.sh logging.sh XEN_SCRIPT_DATA += xen-hotplug-common.sh xen-network-common.sh vif-common.sh XEN_SCRIPT_DATA += block-common.sh vtpm-common.sh vtpm-hotplug-common.sh -XEN_SCRIPT_DATA += vtpm-migration.sh +XEN_SCRIPT_DATA += vtpm-migration.sh vtpm-impl XEN_HOTPLUG_DIR = /etc/hotplug XEN_HOTPLUG_SCRIPTS = xen-backend.agent diff -r c4b68afe97d3 -r 4b51d081378d tools/examples/vtpm --- a/tools/examples/vtpm Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/examples/vtpm Wed Jun 28 07:52:21 2006 -0600 @@ -9,13 +9,7 @@ case "$command" in add) vtpm_create_instance ;; - online) - vtpm_create_instance - ;; remove) - vtpm_remove_instance - ;; - offline) vtpm_remove_instance ;; esac diff -r c4b68afe97d3 -r 4b51d081378d tools/examples/vtpm-common.sh --- a/tools/examples/vtpm-common.sh Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/examples/vtpm-common.sh Wed Jun 28 07:52:21 2006 -0600 @@ -23,7 +23,7 @@ VTPMDB="/etc/xen/vtpm.db" VTPMDB="/etc/xen/vtpm.db" #In the vtpm-impl file some commands should be defined: -# vtpm_create, vtpm_setup, vtpm_reset, etc. (see below) +# vtpm_create, vtpm_setup, vtpm_start, etc. (see below) #This should be indicated by setting VTPM_IMPL_DEFINED. if [ -r "$dir/vtpm-impl" ]; then . "$dir/vtpm-impl" @@ -36,7 +36,7 @@ if [ -z "$VTPM_IMPL_DEFINED" ]; then function vtpm_setup() { true } - function vtpm_reset() { + function vtpm_start() { true } function vtpm_suspend() { @@ -256,22 +256,22 @@ function vtpm_create_instance () { else instance=$(vtpmdb_get_free_instancenum) fi - if [ "$reason" == "create" ]; then - vtpm_create $instance - else - vtpm_resume $instance $domname - fi + + vtpm_create $instance + if [ $vtpm_fatal_error -eq 0 ]; then vtpmdb_add_instance $domname $instance fi + else + if [ "$reason" == "resume" ]; then + vtpm_resume $instance + else + vtpm_start $instance + fi fi release_lock vtpmdb - if [ $vtpm_fatal_error -eq 0 -a \ - "$reason" == "create" ]; then - vtpm_reset $instance - fi xenstore_write $XENBUS_PATH/instance $instance } @@ -283,19 +283,17 @@ function vtpm_remove_instance () { local instance reason domname domname=$(xenstore_read "$XENBUS_PATH"/domain) - if [ "$doname" != "" ]; then + if [ "$domname" != "" ]; then claim_lock vtpmdb instance=$(vtpmdb_find_instance $domname) if [ "$instance" != "0" ]; then - if [ "$reason" == "suspend" ]; then - vtpm_suspend $instance - fi - fi - fi - - release_lock vtpmdb + vtpm_suspend $instance + fi + + release_lock vtpmdb + fi } diff -r c4b68afe97d3 -r 4b51d081378d tools/libxc/Makefile --- a/tools/libxc/Makefile Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/libxc/Makefile Wed Jun 28 07:52:21 2006 -0600 @@ -31,7 +31,6 @@ GUEST_SRCS-y += xc_load_elf.c GUEST_SRCS-y += xc_load_elf.c GUEST_SRCS-y += xg_private.c GUEST_SRCS-$(CONFIG_IA64) += xc_ia64_stubs.c -GUEST_SRCS-$(CONFIG_PLAN9) += xc_load_aout9.c GUEST_SRCS-$(CONFIG_MIGRATE) += xc_linux_restore.c xc_linux_save.c GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c diff -r c4b68afe97d3 -r 4b51d081378d tools/libxc/xc_ia64_stubs.c --- a/tools/libxc/xc_ia64_stubs.c Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/libxc/xc_ia64_stubs.c Wed Jun 28 07:52:21 2006 -0600 @@ -38,23 +38,12 @@ int xc_linux_restore(int xc_handle, int return -1; } -int -xc_plan9_build(int xc_handle, - uint32_t domid, - const char *image_name, - const char *cmdline, - unsigned int control_evtchn, unsigned long flags) -{ - PERROR("xc_plan9_build not implemented\n"); - return -1; -} /* VMM uses put_user to copy pfn_list to guest buffer, this maybe fail, VMM doesn't handle this now. This method will touch guest buffer to make sure the buffer's mapping is tracked by VMM, */ - int xc_ia64_get_pfn_list(int xc_handle, uint32_t domid, xen_pfn_t *pfn_buf, diff -r c4b68afe97d3 -r 4b51d081378d tools/libxc/xc_linux_build.c --- a/tools/libxc/xc_linux_build.c Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/libxc/xc_linux_build.c Wed Jun 28 07:52:21 2006 -0600 @@ -7,7 +7,6 @@ #include <xenctrl.h> #include "xc_elf.h" -#include "xc_aout9.h" #include <stdlib.h> #include <unistd.h> #include <inttypes.h> @@ -34,10 +33,6 @@ #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) #define round_pgdown(_p) ((_p)&PAGE_MASK) - -#ifdef __ia64__ -#define probe_aout9(image,image_size,load_funcs) 1 -#endif struct initrd_info { enum { INITRD_none, INITRD_file, INITRD_mem } type; @@ -124,8 +119,7 @@ static int probeimageformat(const char * struct load_funcs *load_funcs) { if ( probe_elf(image, image_size, load_funcs) && - probe_bin(image, image_size, load_funcs) && - probe_aout9(image, image_size, load_funcs) ) + probe_bin(image, image_size, load_funcs) ) { ERROR( "Unrecognized image format" ); return -EINVAL; diff -r c4b68afe97d3 -r 4b51d081378d tools/libxc/xg_private.h --- a/tools/libxc/xg_private.h Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/libxc/xg_private.h Wed Jun 28 07:52:21 2006 -0600 @@ -196,8 +196,5 @@ int probe_elf(const char *image, unsigne struct load_funcs *funcs); int probe_bin(const char *image, unsigned long image_size, struct load_funcs *funcs); -int probe_aout9(const char *image, unsigned long image_size, - struct load_funcs *funcs); - -#endif - + +#endif /* XG_PRIVATE_H */ diff -r c4b68afe97d3 -r 4b51d081378d tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/python/xen/lowlevel/xc/xc.c Wed Jun 28 07:52:21 2006 -0600 @@ -582,6 +582,12 @@ static PyObject *pyxc_readconsolering(Xc } +static unsigned long pages_to_kib(unsigned long pages) +{ + return pages * (XC_PAGE_SIZE / 1024); +} + + static PyObject *pyxc_pages_to_kib(XcObject *self, PyObject *args) { unsigned long pages; @@ -589,13 +595,7 @@ static PyObject *pyxc_pages_to_kib(XcObj if (!PyArg_ParseTuple(args, "l", &pages)) return NULL; - return PyLong_FromUnsignedLong(pages * (XC_PAGE_SIZE / 1024)); -} - - -static unsigned long pages_to_mb(unsigned long pages) -{ - return (pages * (XC_PAGE_SIZE / 1024) + 1023) / 1024; + return PyLong_FromUnsignedLong(pages_to_kib(pages)); } @@ -618,13 +618,14 @@ static PyObject *pyxc_physinfo(XcObject if(q>cpu_cap) *(q-1)=0; - return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:i,s:s}", + return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:l,s:i,s:s}", "threads_per_core", info.threads_per_core, "cores_per_socket", info.cores_per_socket, "sockets_per_node", info.sockets_per_node, "nr_nodes", info.nr_nodes, - "total_memory", pages_to_mb(info.total_pages), - "free_memory", pages_to_mb(info.free_pages), + "total_memory", pages_to_kib(info.total_pages), + "free_memory", pages_to_kib(info.free_pages), + "scrub_memory", pages_to_kib(info.scrub_pages), "cpu_khz", info.cpu_khz, "hw_caps", cpu_cap); } @@ -637,6 +638,7 @@ static PyObject *pyxc_xeninfo(XcObject * xen_capabilities_info_t xen_caps; xen_platform_parameters_t p_parms; long xen_version; + long xen_pagesize; char str[128]; xen_version = xc_version(self->xc_handle, XENVER_version, NULL); @@ -658,11 +660,16 @@ static PyObject *pyxc_xeninfo(XcObject * sprintf(str, "virt_start=0x%lx", p_parms.virt_start); - return Py_BuildValue("{s:i,s:i,s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s}", + xen_pagesize = xc_version(self->xc_handle, XENVER_pagesize, NULL); + if (xen_pagesize < 0 ) + return PyErr_SetFromErrno(xc_error); + + return Py_BuildValue("{s:i,s:i,s:s,s:s,s:i,s:s,s:s,s:s,s:s,s:s,s:s}", "xen_major", xen_version >> 16, "xen_minor", (xen_version & 0xffff), "xen_extra", xen_extra, "xen_caps", xen_caps, + "xen_pagesize", xen_pagesize, "platform_params", str, "xen_changeset", xen_chgset, "cc_compiler", xen_cc.compiler, diff -r c4b68afe97d3 -r 4b51d081378d tools/python/xen/xend/XendNode.py --- a/tools/python/xen/xend/XendNode.py Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/python/xen/xend/XendNode.py Wed Jun 28 07:52:21 2006 -0600 @@ -64,6 +64,9 @@ class XendNode: info['cores_per_socket'] * info['threads_per_core']) info['cpu_mhz'] = info['cpu_khz'] / 1000 + # physinfo is in KiB + info['total_memory'] = info['total_memory'] / 1024 + info['free_memory'] = info['free_memory'] / 1024 ITEM_ORDER = ['nr_cpus', 'nr_nodes', @@ -86,6 +89,7 @@ class XendNode: 'xen_minor', 'xen_extra', 'xen_caps', + 'xen_pagesize', 'platform_params', 'xen_changeset', 'cc_compiler', diff -r c4b68afe97d3 -r 4b51d081378d tools/python/xen/xend/balloon.py --- a/tools/python/xen/xend/balloon.py Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/python/xen/xend/balloon.py Wed Jun 28 07:52:21 2006 -0600 @@ -29,9 +29,7 @@ from XendError import VmError PROC_XEN_BALLOON = '/proc/xen/balloon' -BALLOON_OUT_SLACK = 1 # MiB. We need this because the physinfo details are - # rounded. -RETRY_LIMIT = 10 +RETRY_LIMIT = 20 RETRY_LIMIT_INCR = 5 ## # The time to sleep between retries grows linearly, using this value (in @@ -68,22 +66,22 @@ def _get_proc_balloon(label): f.close() def get_dom0_current_alloc(): - """Returns the current memory allocation (in MiB) of dom0.""" + """Returns the current memory allocation (in KiB) of dom0.""" kb = _get_proc_balloon(labels['current']) if kb == None: raise VmError('Failed to query current memory allocation of dom0.') - return kb / 1024 + return kb def get_dom0_target_alloc(): - """Returns the target memory allocation (in MiB) of dom0.""" + """Returns the target memory allocation (in KiB) of dom0.""" kb = _get_proc_balloon(labels['target']) if kb == None: raise VmError('Failed to query target memory allocation of dom0.') - return kb / 1024 + return kb -def free(required): +def free(need_mem): """Balloon out memory from the privileged domain so that there is the specified required amount (in KiB) free. """ @@ -92,9 +90,10 @@ def free(required): # to balloon out to free some up. Memory freed by a destroyed domain may # not appear in the free_memory field immediately, because it needs to be # scrubbed before it can be released to the free list, which is done - # asynchronously by Xen; ballooning is asynchronous also. No matter where - # we expect the free memory to come from, therefore, we need to wait for - # it to become available. + # asynchronously by Xen; ballooning is asynchronous also. Such memory + # does, however, need to be accounted for when calculating how much dom0 + # needs to balloon. No matter where we expect the free memory to come + # from, we need to wait for it to become available. # # We are not allowed to balloon below dom0_min_mem, or if dom0_min_mem # is 0, we cannot balloon at all. Memory can still become available @@ -108,43 +107,49 @@ def free(required): # usage, so we recheck the required alloc each time around the loop, but # track the last used value so that we don't trigger too many watches. - need_mem = (required + 1023) / 1024 + BALLOON_OUT_SLACK - xroot = XendRoot.instance() xc = xen.lowlevel.xc.xc() try: - dom0_min_mem = xroot.get_dom0_min_mem() + dom0_min_mem = xroot.get_dom0_min_mem() * 1024 retries = 0 sleep_time = SLEEP_TIME_GROWTH last_new_alloc = None rlimit = RETRY_LIMIT while retries < rlimit: - free_mem = xc.physinfo()['free_memory'] + physinfo = xc.physinfo() + free_mem = physinfo['free_memory'] + scrub_mem = physinfo['scrub_memory'] if free_mem >= need_mem: - log.debug("Balloon: free %d; need %d; done.", free_mem, - need_mem) + log.debug("Balloon: %d KiB free; need %d; done.", + free_mem, need_mem) return if retries == 0: - rlimit += ((need_mem - free_mem)/1024) * RETRY_LIMIT_INCR - log.debug("Balloon: free %d; need %d; retries: %d.", - free_mem, need_mem, rlimit) + rlimit += ((need_mem - free_mem)/1024/1024) * RETRY_LIMIT_INCR + log.debug("Balloon: %d KiB free; %d to scrub; need %d; retries: %d.", + free_mem, scrub_mem, need_mem, rlimit) if dom0_min_mem > 0: dom0_alloc = get_dom0_current_alloc() - new_alloc = dom0_alloc - (need_mem - free_mem) + new_alloc = dom0_alloc - (need_mem - free_mem - scrub_mem) - if (new_alloc >= dom0_min_mem and - new_alloc != last_new_alloc): - log.debug("Balloon: setting dom0 target to %d.", - new_alloc) - dom0 = XendDomain.instance().privilegedDomain() - dom0.setMemoryTarget(new_alloc) - last_new_alloc = new_alloc - # Continue to retry, waiting for ballooning. + if free_mem + scrub_mem >= need_mem: + if last_new_alloc == None: + log.debug("Balloon: waiting on scrubbing") + last_new_alloc = dom0_alloc + else: + if (new_alloc >= dom0_min_mem and + new_alloc != last_new_alloc): + new_alloc_mb = new_alloc / 1024 # Round down + log.debug("Balloon: setting dom0 target to %d MiB.", + new_alloc_mb) + dom0 = XendDomain.instance().privilegedDomain() + dom0.setMemoryTarget(new_alloc_mb) + last_new_alloc = new_alloc + # Continue to retry, waiting for ballooning or scrubbing. time.sleep(sleep_time) if retries < 2 * RETRY_LIMIT: @@ -154,15 +159,15 @@ def free(required): # Not enough memory; diagnose the problem. if dom0_min_mem == 0: raise VmError(('Not enough free memory and dom0_min_mem is 0, so ' - 'I cannot release any more. I need %d MiB but ' + 'I cannot release any more. I need %d KiB but ' 'only have %d.') % (need_mem, free_mem)) elif new_alloc < dom0_min_mem: raise VmError( - ('I need %d MiB, but dom0_min_mem is %d and shrinking to ' - '%d MiB would leave only %d MiB free.') % + ('I need %d KiB, but dom0_min_mem is %d and shrinking to ' + '%d KiB would leave only %d KiB free.') % (need_mem, dom0_min_mem, dom0_min_mem, - free_mem + dom0_alloc - dom0_min_mem)) + free_mem + scrub_mem + dom0_alloc - dom0_min_mem)) else: raise VmError('The privileged domain did not balloon!') diff -r c4b68afe97d3 -r 4b51d081378d tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/python/xen/xm/main.py Wed Jun 28 07:52:21 2006 -0600 @@ -887,7 +887,7 @@ def parse_dev_info(info): 'ring-ref' : get_info('ring-ref', int, -1), } -def has_long_option(args): +def arg_check_for_resource_list(args, name): use_long = 0 try: (options, params) = getopt.gnu_getopt(args, 'l', ['long']) @@ -898,16 +898,19 @@ def has_long_option(args): for (k, v) in options: if k in ['-l', '--long']: use_long = 1 - return (use_long, params) - -def xm_network_list(args): - arg_check(args, "network-list", 1, 2) - - (use_long, params) = has_long_option(args) if len(params) == 0: print 'No domain parameter given' - sys.exit(1) + usage(name) + if len(params) > 1: + print 'No multiple domain parameters allowed' + usage(name) + + return (use_long, params) + +def xm_network_list(args): + (use_long, params) = arg_check_for_resource_list(args, "network-list") + dom = params[0] if use_long: devs = server.xend.domain.getDeviceSxprs(dom, 'vif') @@ -931,13 +934,8 @@ def xm_network_list(args): % ni) def xm_block_list(args): - arg_check(args, "block-list", 1, 2) - - (use_long, params) = has_long_option(args) - - if len(params) == 0: - print 'No domain parameter given' - sys.exit(1) + (use_long, params) = arg_check_for_resource_list(args, "block-list") + dom = params[0] if use_long: devs = server.xend.domain.getDeviceSxprs(dom, 'vbd') @@ -960,13 +958,8 @@ def xm_block_list(args): % ni) def xm_vtpm_list(args): - arg_check(args, "vtpm-list", 1, 2) - - (use_long, params) = has_long_option(args) - - if len(params) == 0: - print 'No domain parameter given' - sys.exit(1) + (use_long, params) = arg_check_for_resource_list(args, "vtpm-list") + dom = params[0] if use_long: devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm') diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm/Rules.mk --- a/tools/vtpm/Rules.mk Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm/Rules.mk Wed Jun 28 07:52:21 2006 -0600 @@ -33,8 +33,7 @@ OBJS = $(patsubst %.c,%.o,$(SRCS)) -include $(DEP_FILES) -# Emulator does not work on 64-bit systems, and may be broken on 32 right now -BUILD_EMULATOR = n +BUILD_EMULATOR = y # Make sure these are just rules .PHONY : all build install clean diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm/tpm_emulator-0.3-x86_64.patch --- a/tools/vtpm/tpm_emulator-0.3-x86_64.patch Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm/tpm_emulator-0.3-x86_64.patch Wed Jun 28 07:52:21 2006 -0600 @@ -1,6 +1,49 @@ diff -uprN tpm_emulator-0.3/crypto/gmp_k -diff -uprN tpm_emulator-0.3/crypto/gmp_kernel_wrapper.c tpm_emulator-0.3-x86_64/crypto/gmp_kernel_wrapper.c ---- tpm_emulator-0.3/crypto/gmp_kernel_wrapper.c 2006-01-10 04:21:45.000000000 -0800 -+++ tpm_emulator-0.3-x86_64/crypto/gmp_kernel_wrapper.c 2006-05-26 11:26:02.000000000 -0700 +diff -uprN orig/tpm_emulator-0.3/Makefile tpm_emulator-0.3-x86_64/Makefile +--- orig/tpm_emulator-0.3/Makefile 2006-01-10 04:21:45.000000000 -0800 ++++ tpm_emulator-0.3-x86_64/Makefile 2006-08-29 15:08:20.532342768 -0700 +@@ -7,6 +7,7 @@ + KERNEL_RELEASE := $(shell uname -r) + KERNEL_BUILD := /lib/modules/$(KERNEL_RELEASE)/build + MOD_SUBDIR := misc ++COMPILE_ARCH ?= $(shell uname -m | sed -e s/i.86/x86_32/) + + # module settings + MODULE_NAME := tpm_emulator +@@ -17,8 +18,14 @@ VERSION_BUILD := $(shell date +"%s") + # enable/disable DEBUG messages + EXTRA_CFLAGS += -Wall -DDEBUG -g + ++ifeq ($(COMPILE_ARCH),x86_64) ++LIBDIR = lib64 ++else ++LIBDIR = lib ++endif ++ + # GNU MP configuration +-GMP_LIB := /usr/lib/libgmp.a ++GMP_LIB := /usr/$(LIBDIR)/libgmp.a + GMP_HEADER := /usr/include/gmp.h + + # sources and objects +diff -uprN orig/tpm_emulator-0.3/README tpm_emulator-0.3-x86_64/README +--- orig/tpm_emulator-0.3/README 2006-01-10 04:21:45.000000000 -0800 ++++ tpm_emulator-0.3-x86_64/README 2006-08-29 15:07:43.530967832 -0700 +@@ -43,6 +43,12 @@ Example: + GMP_LIB := /usr/lib/libgmp.a + GMP_HEADER := /usr/include/gmp.h + ++GNU MP Library on 64 bit Systems ++-------------------------------------------------------------------------- ++Some 64-bit kernels have problems with importing the user-space gmp ++library (/usr/lib*/libgmp.a) into kernel space. These kernels will require ++that the gmp library be recompiled for kernel space with -mcmodel=kernel. ++ + Installation + -------------------------------------------------------------------------- + The compilation and installation process uses the build environment for +diff -uprN orig/tpm_emulator-0.3/crypto/gmp_kernel_wrapper.c tpm_emulator-0.3-x86_64/crypto/gmp_kernel_wrapper.c +--- orig/tpm_emulator-0.3/crypto/gmp_kernel_wrapper.c 2006-01-10 04:21:45.000000000 -0800 ++++ tpm_emulator-0.3-x86_64/crypto/gmp_kernel_wrapper.c 2006-08-29 15:07:43.525968592 -0700 @@ -79,7 +79,7 @@ void __attribute__ ((regparm(0))) *kerne { void *ret = (void*)kmalloc(size, GFP_KERNEL); @@ -19,9 +62,9 @@ diff -uprN tpm_emulator-0.3/crypto/gmp_k memcpy(ret, oldptr, old_size); kfree(oldptr); return ret; -diff -uprN tpm_emulator-0.3/linux_module.c tpm_emulator-0.3-x86_64/linux_module.c ---- tpm_emulator-0.3/linux_module.c 2006-01-10 04:21:45.000000000 -0800 -+++ tpm_emulator-0.3-x86_64/linux_module.c 2006-05-26 11:26:02.000000000 -0700 +diff -uprN orig/tpm_emulator-0.3/linux_module.c tpm_emulator-0.3-x86_64/linux_module.c +--- orig/tpm_emulator-0.3/linux_module.c 2006-01-10 04:21:45.000000000 -0800 ++++ tpm_emulator-0.3-x86_64/linux_module.c 2006-08-29 15:07:43.526968440 -0700 @@ -72,7 +72,7 @@ static int tpm_release(struct inode *ino static ssize_t tpm_read(struct file *file, char *buf, size_t count, loff_t *ppos) @@ -40,9 +83,9 @@ diff -uprN tpm_emulator-0.3/linux_module down(&tpm_mutex); *ppos = 0; if (tpm_response.data != NULL) kfree(tpm_response.data); -diff -uprN tpm_emulator-0.3/linux_module.h tpm_emulator-0.3-x86_64/linux_module.h ---- tpm_emulator-0.3/linux_module.h 2006-01-10 04:21:45.000000000 -0800 -+++ tpm_emulator-0.3-x86_64/linux_module.h 2006-05-26 11:26:02.000000000 -0700 +diff -uprN orig/tpm_emulator-0.3/linux_module.h tpm_emulator-0.3-x86_64/linux_module.h +--- orig/tpm_emulator-0.3/linux_module.h 2006-01-10 04:21:45.000000000 -0800 ++++ tpm_emulator-0.3-x86_64/linux_module.h 2006-08-29 15:07:43.527968288 -0700 @@ -28,8 +28,10 @@ /* module settings */ @@ -54,52 +97,9 @@ diff -uprN tpm_emulator-0.3/linux_module #include "tpm_version.h" #define TPM_DEVICE_MINOR 224 -diff -uprN tpm_emulator-0.3/Makefile tpm_emulator-0.3-x86_64/Makefile ---- tpm_emulator-0.3/Makefile 2006-01-10 04:21:45.000000000 -0800 -+++ tpm_emulator-0.3-x86_64/Makefile 2006-05-26 11:26:02.000000000 -0700 -@@ -7,6 +7,7 @@ - KERNEL_RELEASE := $(shell uname -r) - KERNEL_BUILD := /lib/modules/$(KERNEL_RELEASE)/build - MOD_SUBDIR := misc -+COMPILE_ARCH ?= $(shell uname -m | sed -e s/i.86/x86_32/) - - # module settings - MODULE_NAME := tpm_emulator -@@ -17,8 +18,14 @@ VERSION_BUILD := $(shell date +"%s") - # enable/disable DEBUG messages - EXTRA_CFLAGS += -Wall -DDEBUG -g - -+ifeq ($(COMPILE_ARCH),x86_64) -+LIBDIR = lib64 -+else -+LIBDIR = lib -+endif -+ - # GNU MP configuration --GMP_LIB := /usr/lib/libgmp.a -+GMP_LIB := /usr/$(LIBDIR)/libgmp.a - GMP_HEADER := /usr/include/gmp.h - - # sources and objects -diff -uprN tpm_emulator-0.3/README tpm_emulator-0.3-x86_64/README ---- tpm_emulator-0.3/README 2006-01-10 04:21:45.000000000 -0800 -+++ tpm_emulator-0.3-x86_64/README 2006-05-26 11:26:02.000000000 -0700 -@@ -43,6 +43,12 @@ Example: - GMP_LIB := /usr/lib/libgmp.a - GMP_HEADER := /usr/include/gmp.h - -+GNU MP Library on 64 bit Systems -+-------------------------------------------------------------------------- -+Some 64-bit kernels have problems with importing the user-space gmp -+library (/usr/lib*/libgmp.a) into kernel space. These kernels will require -+that the gmp library be recompiled for kernel space with -mcmodel=kernel. -+ - Installation - -------------------------------------------------------------------------- - The compilation and installation process uses the build environment for -diff -uprN tpm_emulator-0.3/tpm/tpm_credentials.c tpm_emulator-0.3-x86_64/tpm/tpm_credentials.c ---- tpm_emulator-0.3/tpm/tpm_credentials.c 2006-01-10 04:21:45.000000000 -0800 -+++ tpm_emulator-0.3-x86_64/tpm/tpm_credentials.c 2006-05-26 11:26:02.000000000 -0700 +diff -uprN orig/tpm_emulator-0.3/tpm/tpm_credentials.c tpm_emulator-0.3-x86_64/tpm/tpm_credentials.c +--- orig/tpm_emulator-0.3/tpm/tpm_credentials.c 2006-01-10 04:21:45.000000000 -0800 ++++ tpm_emulator-0.3-x86_64/tpm/tpm_credentials.c 2006-08-29 15:07:43.530967832 -0700 @@ -47,16 +47,16 @@ int tpm_compute_pubkey_checksum(TPM_NONC TPM_RESULT tpm_get_pubek(TPM_PUBKEY *pubEndorsementKey) @@ -140,9 +140,9 @@ diff -uprN tpm_emulator-0.3/tpm/tpm_cred publicPortion->algorithmParms.algorithmID = TPM_ALG_RSA; publicPortion->algorithmParms.encScheme = srk->encScheme; publicPortion->algorithmParms.sigScheme = srk->sigScheme; -diff -uprN tpm_emulator-0.3/tpm/tpm_crypto.c tpm_emulator-0.3-x86_64/tpm/tpm_crypto.c ---- tpm_emulator-0.3/tpm/tpm_crypto.c 2006-01-10 04:21:45.000000000 -0800 -+++ tpm_emulator-0.3-x86_64/tpm/tpm_crypto.c 2006-05-26 11:26:02.000000000 -0700 +diff -uprN orig/tpm_emulator-0.3/tpm/tpm_crypto.c tpm_emulator-0.3-x86_64/tpm/tpm_crypto.c +--- orig/tpm_emulator-0.3/tpm/tpm_crypto.c 2006-01-10 04:21:45.000000000 -0800 ++++ tpm_emulator-0.3-x86_64/tpm/tpm_crypto.c 2006-08-29 15:07:43.531967680 -0700 @@ -182,7 +182,8 @@ TPM_RESULT TPM_CertifyKey(TPM_KEY_HANDLE TPM_KEY_DATA *cert, *key; sha1_ctx_t sha1_ctx; @@ -192,10 +192,10 @@ diff -uprN tpm_emulator-0.3/tpm/tpm_cryp free_TPM_KEY_PARMS(certifyInfo->algorithmParms); return TPM_FAIL; } -diff -uprN tpm_emulator-0.3/tpm/tpm_data.c tpm_emulator-0.3-x86_64/tpm/tpm_data.c ---- tpm_emulator-0.3/tpm/tpm_data.c 2006-01-10 04:21:45.000000000 -0800 -+++ tpm_emulator-0.3-x86_64/tpm/tpm_data.c 2006-05-26 11:26:02.000000000 -0700 -@@ -214,7 +214,7 @@ static int read_from_file(uint8_t **data +diff -uprN orig/tpm_emulator-0.3/tpm/tpm_data.c tpm_emulator-0.3-x86_64/tpm/tpm_data.c +--- orig/tpm_emulator-0.3/tpm/tpm_data.c 2006-01-10 04:21:45.000000000 -0800 ++++ tpm_emulator-0.3-x86_64/tpm/tpm_data.c 2006-08-29 15:08:20.535342312 -0700 +@@ -214,23 +214,30 @@ static int read_from_file(uint8_t **data int tpm_store_permanent_data(void) { uint8_t *buf, *ptr; @@ -203,8 +203,35 @@ diff -uprN tpm_emulator-0.3/tpm/tpm_data + UINT32 buf_length, len; /* marshal data */ - buf_length = len = sizeof_TPM_STCLEAR_FLAGS(tpmData.stclear.flags) -@@ -242,13 +242,14 @@ int tpm_store_permanent_data(void) +- buf_length = len = sizeof_TPM_STCLEAR_FLAGS(tpmData.stclear.flags) +- + sizeof_TPM_PERMANENT_FLAGS(tpmData.permanent.flags) + 2 +- + sizeof_TPM_PERMANENT_DATA(tpmData.permanent.data); ++ buf_length = len = 4 + sizeof_TPM_STCLEAR_FLAGS(tpmData.stclear.flags) ++ + sizeof_TPM_PERMANENT_FLAGS(tpmData.permanent.flags) ++ + sizeof_TPM_STANY_FLAGS(tpmData.stany.flags) + 2 ++ + sizeof_TPM_STCLEAR_DATA(tpmData.stclear.data) ++ + sizeof_TPM_PERMANENT_DATA(tpmData.permanent.data) ++ + sizeof_TPM_STANY_DATA(tpmData.stany.data); + buf = ptr = tpm_malloc(buf_length); + if (buf == NULL + || tpm_marshal_TPM_VERSION(&ptr, &len, &tpmData.permanent.data.version) + || tpm_marshal_TPM_STCLEAR_FLAGS(&ptr, &len, &tpmData.stclear.flags) + || tpm_marshal_TPM_PERMANENT_FLAGS(&ptr, &len, &tpmData.permanent.flags) ++ || tpm_marshal_TPM_STANY_FLAGS(&ptr, &len, &tpmData.stany.flags) + || tpm_marshal_BOOL(&ptr, &len, tpmData.permanent.flags.selfTestSucceeded) + || tpm_marshal_BOOL(&ptr, &len, tpmData.permanent.flags.owned) +- || tpm_marshal_TPM_PERMANENT_DATA(&ptr, &len, &tpmData.permanent.data)) { ++ || tpm_marshal_TPM_STCLEAR_DATA(&ptr, &len, &tpmData.stclear.data) ++ || tpm_marshal_TPM_PERMANENT_DATA(&ptr, &len, &tpmData.permanent.data) ++ || tpm_marshal_TPM_STANY_DATA(&ptr, &len, &tpmData.stany.data)) { + tpm_free(buf); + return -1; + } ++ + if (write_to_file(buf, buf_length - len)) { + tpm_free(buf); + return -1; +@@ -242,24 +249,29 @@ int tpm_store_permanent_data(void) int tpm_restore_permanent_data(void) { uint8_t *buf, *ptr; @@ -221,9 +248,25 @@ diff -uprN tpm_emulator-0.3/tpm/tpm_data /* unmarshal data */ if (tpm_unmarshal_TPM_VERSION(&ptr, &len, &ver) || memcmp(&ver, &tpmData.permanent.data.version, sizeof(TPM_VERSION)) -diff -uprN tpm_emulator-0.3/tpm/tpm_marshalling.c tpm_emulator-0.3-x86_64/tpm/tpm_marshalling.c ---- tpm_emulator-0.3/tpm/tpm_marshalling.c 2006-01-10 04:21:45.000000000 -0800 -+++ tpm_emulator-0.3-x86_64/tpm/tpm_marshalling.c 2006-05-26 11:26:02.000000000 -0700 + || tpm_unmarshal_TPM_STCLEAR_FLAGS(&ptr, &len, &tpmData.stclear.flags) + || tpm_unmarshal_TPM_PERMANENT_FLAGS(&ptr, &len, &tpmData.permanent.flags) ++ || tpm_unmarshal_TPM_STANY_FLAGS(&ptr, &len, &tpmData.stany.flags) + || tpm_unmarshal_BOOL(&ptr, &len, &tpmData.permanent.flags.selfTestSucceeded) + || tpm_unmarshal_BOOL(&ptr, &len, &tpmData.permanent.flags.owned) +- || tpm_unmarshal_TPM_PERMANENT_DATA(&ptr, &len, &tpmData.permanent.data)) { ++ || tpm_unmarshal_TPM_STCLEAR_DATA(&ptr, &len, &tpmData.stclear.data) ++ || tpm_unmarshal_TPM_PERMANENT_DATA(&ptr, &len, &tpmData.permanent.data) ++ || tpm_unmarshal_TPM_STANY_DATA(&ptr, &len, &tpmData.stany.data)) { + tpm_free(buf); + return -1; + } ++ + tpm_free(buf); + return 0; + } +diff -uprN orig/tpm_emulator-0.3/tpm/tpm_marshalling.c tpm_emulator-0.3-x86_64/tpm/tpm_marshalling.c +--- orig/tpm_emulator-0.3/tpm/tpm_marshalling.c 2006-01-10 04:21:45.000000000 -0800 ++++ tpm_emulator-0.3-x86_64/tpm/tpm_marshalling.c 2006-08-29 15:08:20.537342008 -0700 @@ -1212,7 +1212,7 @@ int tpm_unmarshal_TPM_STANY_FLAGS(BYTE * int tpm_marshal_RSA(BYTE **ptr, UINT32 *length, rsa_private_key_t *v) @@ -233,9 +276,92 @@ diff -uprN tpm_emulator-0.3/tpm/tpm_mars if (*length < sizeof_RSA((*v))) return -1; if (v->size > 0) { rsa_export_modulus(v, &(*ptr)[6], &m_len); -diff -uprN tpm_emulator-0.3/tpm/tpm_owner.c tpm_emulator-0.3-x86_64/tpm/tpm_owner.c ---- tpm_emulator-0.3/tpm/tpm_owner.c 2006-01-10 04:21:45.000000000 -0800 -+++ tpm_emulator-0.3-x86_64/tpm/tpm_owner.c 2006-05-26 11:26:02.000000000 -0700 +@@ -1356,6 +1356,66 @@ int tpm_unmarshal_TPM_PERMANENT_DATA(BYT + return 0; + } + ++int tpm_marshal_TPM_STCLEAR_DATA(BYTE **ptr, UINT32 *length, TPM_STCLEAR_DATA *v) ++{ ++ if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag) ++ || tpm_marshal_TPM_NONCE(ptr, length, &v->contextNonceKey) ++ || tpm_marshal_TPM_COUNT_ID(ptr, length, v->countID) ) return -1; ++ ++ return 0; ++} ++ ++int tpm_unmarshal_TPM_STCLEAR_DATA(BYTE **ptr, UINT32 *length, TPM_STCLEAR_DATA *v) ++{ ++ if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag) ++ || tpm_unmarshal_TPM_NONCE(ptr, length, &v->contextNonceKey) ++ || tpm_unmarshal_TPM_COUNT_ID(ptr, length, &v->countID) ) return -1; ++ ++ return 0; ++} ++ ++int tpm_marshal_TPM_STANY_DATA(BYTE **ptr, UINT32 *length, TPM_STANY_DATA *v) ++{ ++ UINT32 i; ++ if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag) ++ || tpm_marshal_TPM_NONCE(ptr, length, &v->contextNonceSession) ++ || tpm_marshal_TPM_DIGEST(ptr, length, &v->auditDigest) ++ || tpm_marshal_BOOL(ptr, length, v->auditSession) ++ || tpm_marshal_TPM_CURRENT_TICKS(ptr, length, &v->currentTicks) ++ || tpm_marshal_UINT32(ptr, length, v->contextCount) ++ || tpm_marshal_UINT32_ARRAY(ptr, length, v->contextList, TPM_MAX_SESSION_LIST)) return -1; ++ for (i = 0; i < TPM_MAX_SESSIONS; i++) { ++ if (tpm_marshal_TPM_SESSION_DATA(ptr, length, &v->sessions[i])) return -1; ++ } ++ for (i = 0; i < TPM_MAX_SESSIONS_DAA; i++) { ++ if (tpm_marshal_TPM_DAA_SESSION_DATA(ptr, length, &v->sessionsDAA[i])) return -1; ++ } ++ if (tpm_marshal_TPM_TRANSHANDLE(ptr, length, v->transExclusive)) return -1; ++ ++ return 0; ++} ++ ++int tpm_unmarshal_TPM_STANY_DATA(BYTE **ptr, UINT32 *length, TPM_STANY_DATA *v) ++{ ++ UINT32 i; ++ if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag) ++ || tpm_unmarshal_TPM_NONCE(ptr, length, &v->contextNonceSession) ++ || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->auditDigest) ++ || tpm_unmarshal_BOOL(ptr, length, &v->auditSession) ++ || tpm_unmarshal_TPM_CURRENT_TICKS(ptr, length, &v->currentTicks) ++ || tpm_unmarshal_UINT32(ptr, length, &v->contextCount) ++ || tpm_unmarshal_UINT32_ARRAY(ptr, length, v->contextList, TPM_MAX_SESSION_LIST)) return -1; ++ for (i = 0; i < TPM_MAX_SESSIONS; i++) { ++ if (tpm_unmarshal_TPM_SESSION_DATA(ptr, length, &v->sessions[i])) return -1; ++ } ++ for (i = 0; i < TPM_MAX_SESSIONS_DAA; i++) { ++ if (tpm_unmarshal_TPM_DAA_SESSION_DATA(ptr, length, &v->sessionsDAA[i])) return -1; ++ } ++ if (tpm_unmarshal_TPM_TRANSHANDLE(ptr, length, &v->transExclusive)) return -1; ++ ++ return 0; ++} ++ + int tpm_marshal_TPM_SESSION_DATA(BYTE **ptr, UINT32 *length, TPM_SESSION_DATA *v) + { + if (tpm_marshal_BYTE(ptr, length, v->type) +diff -uprN orig/tpm_emulator-0.3/tpm/tpm_marshalling.h tpm_emulator-0.3-x86_64/tpm/tpm_marshalling.h +--- orig/tpm_emulator-0.3/tpm/tpm_marshalling.h 2006-01-10 04:21:45.000000000 -0800 ++++ tpm_emulator-0.3-x86_64/tpm/tpm_marshalling.h 2006-08-29 15:08:20.538341856 -0700 +@@ -420,6 +420,12 @@ int tpm_unmarshal_TPM_KEY_DATA(BYTE **pt + int tpm_marshal_TPM_PERMANENT_DATA(BYTE **ptr, UINT32 *length, TPM_PERMANENT_DATA *); + int tpm_unmarshal_TPM_PERMANENT_DATA(BYTE **ptr, UINT32 *length, TPM_PERMANENT_DATA *); + ++int tpm_marshal_TPM_STCLEAR_DATA(BYTE **ptr, UINT32 *length, TPM_STCLEAR_DATA *v); ++int tpm_unmarshal_TPM_STCLEAR_DATA(BYTE **ptr, UINT32 *length, TPM_STCLEAR_DATA *v); ++ ++int tpm_marshal_TPM_STANY_DATA(BYTE **ptr, UINT32 *length, TPM_STANY_DATA *v); ++int tpm_unmarshal_TPM_STANY_DATA(BYTE **ptr, UINT32 *length, TPM_STANY_DATA *v); ++ + int tpm_marshal_TPM_SESSION_DATA(BYTE **ptr, UINT32 *length, TPM_SESSION_DATA *v); + int tpm_unmarshal_TPM_SESSION_DATA(BYTE **ptr, UINT32 *length, TPM_SESSION_DATA *v); + +diff -uprN orig/tpm_emulator-0.3/tpm/tpm_owner.c tpm_emulator-0.3-x86_64/tpm/tpm_owner.c +--- orig/tpm_emulator-0.3/tpm/tpm_owner.c 2006-01-10 04:21:45.000000000 -0800 ++++ tpm_emulator-0.3-x86_64/tpm/tpm_owner.c 2006-08-29 15:07:43.535967072 -0700 @@ -108,7 +108,7 @@ TPM_RESULT TPM_TakeOwnership(TPM_PROTOCO TPM_RESULT res; rsa_private_key_t *ek = &tpmData.permanent.data.endorsementKey; @@ -255,9 +381,63 @@ diff -uprN tpm_emulator-0.3/tpm/tpm_owne /* setup tpmProof and set state to owned */ tpm_get_random_bytes(tpmData.permanent.data.tpmProof.nonce, sizeof(tpmData.permanent.data.tpmProof.nonce)); -diff -uprN tpm_emulator-0.3/tpm/tpm_storage.c tpm_emulator-0.3-x86_64/tpm/tpm_storage.c ---- tpm_emulator-0.3/tpm/tpm_storage.c 2006-01-10 04:21:45.000000000 -0800 -+++ tpm_emulator-0.3-x86_64/tpm/tpm_storage.c 2006-05-26 14:33:18.000000000 -0700 +diff -uprN orig/tpm_emulator-0.3/tpm/tpm_startup.c tpm_emulator-0.3-x86_64/tpm/tpm_startup.c +--- orig/tpm_emulator-0.3/tpm/tpm_startup.c 2006-01-10 04:21:45.000000000 -0800 ++++ tpm_emulator-0.3-x86_64/tpm/tpm_startup.c 2006-08-29 15:08:20.538341856 -0700 +@@ -41,24 +41,29 @@ void TPM_Init(TPM_STARTUP_TYPE startupTy + TPM_RESULT TPM_Startup(TPM_STARTUP_TYPE startupType) + { + int i; ++ int restore_fail; + info("TPM_Startup(%d)", startupType); + if (tpmData.stany.flags.postInitialise == FALSE) return TPM_INVALID_POSTINIT; +- /* reset STANY_FLAGS */ +- SET_TO_ZERO(&tpmData.stany.flags); +- tpmData.stany.flags.tag = TPM_TAG_STANY_FLAGS; +- /* reset STANY_DATA (invalidates ALL sessions) */ +- SET_TO_ZERO(&tpmData.stany.data); +- tpmData.stany.data.tag = TPM_TAG_STANY_DATA; +- /* init session-context nonce */ +- SET_TO_RAND(&tpmData.stany.data.contextNonceSession); ++ ++ /* try and restore state to get EK, SRK, etc */ ++ restore_fail = tpm_restore_permanent_data(); ++ + /* set data and flags according to the given startup type */ + if (startupType == TPM_ST_CLEAR) { ++ /* reset STANY_FLAGS */ ++ SET_TO_ZERO(&tpmData.stany.flags); ++ tpmData.stany.flags.tag = TPM_TAG_STANY_FLAGS; ++ /* reset STANY_DATA (invalidates ALL sessions) */ ++ SET_TO_ZERO(&tpmData.stany.data); ++ tpmData.stany.data.tag = TPM_TAG_STANY_DATA; ++ /* init session-context nonce */ ++ SET_TO_RAND(&tpmData.stany.data.contextNonceSession); + /* reset PCR values */ + for (i = 0; i < TPM_NUM_PCR; i++) { +- if (tpmData.permanent.data.pcrAttrib[i].pcrReset) +- SET_TO_ZERO(tpmData.permanent.data.pcrValue[i].digest); ++ if (!tpmData.permanent.data.pcrAttrib[i].pcrReset) ++ SET_TO_ZERO(&tpmData.permanent.data.pcrValue[i].digest); + else +- SET_TO_0xFF(tpmData.permanent.data.pcrValue[i].digest); ++ SET_TO_0xFF(&tpmData.permanent.data.pcrValue[i].digest); + } + /* reset STCLEAR_FLAGS */ + SET_TO_ZERO(&tpmData.stclear.flags); +@@ -77,7 +82,8 @@ TPM_RESULT TPM_Startup(TPM_STARTUP_TYPE + /* init key-context nonce */ + SET_TO_RAND(&tpmData.stclear.data.contextNonceKey); + } else if (startupType == TPM_ST_STATE) { +- if (tpm_restore_permanent_data()) { ++ /* restore must have been successful for TPM_ST_STATE */ ++ if (restore_fail) { + error("restoring permanent data failed"); + tpmData.permanent.data.testResult = "tpm_restore_permanent_data() failed"; + tpmData.permanent.flags.selfTestSucceeded = FALSE; +diff -uprN orig/tpm_emulator-0.3/tpm/tpm_storage.c tpm_emulator-0.3-x86_64/tpm/tpm_storage.c +--- orig/tpm_emulator-0.3/tpm/tpm_storage.c 2006-01-10 04:21:45.000000000 -0800 ++++ tpm_emulator-0.3-x86_64/tpm/tpm_storage.c 2006-08-29 15:07:43.537966768 -0700 @@ -58,6 +58,7 @@ int encrypt_sealed_data(TPM_KEY_DATA *ke BYTE *enc, UINT32 *enc_size) { @@ -482,3 +662,76 @@ diff -uprN tpm_emulator-0.3/tpm/tpm_stor if (tpm_setup_key_parms(key, &pubKey->algorithmParms) != 0) { tpm_free(pubKey->pubKey.key); return TPM_FAIL; +diff -uprN orig/tpm_emulator-0.3/tpm/tpm_structures.h tpm_emulator-0.3-x86_64/tpm/tpm_structures.h +--- orig/tpm_emulator-0.3/tpm/tpm_structures.h 2006-01-10 04:21:45.000000000 -0800 ++++ tpm_emulator-0.3-x86_64/tpm/tpm_structures.h 2006-08-29 15:08:20.545340792 -0700 +@@ -1723,6 +1723,7 @@ typedef struct tdTPM_DAA_ISSUER { + TPM_DIGEST DAA_digest_gamma; + BYTE DAA_generic_q[26]; + } TPM_DAA_ISSUER; ++#define sizeof_TPM_DAA_ISSUER(s) (2 + (20 * 6) + 26 ) + + /* + * TPM_DAA_TPM ([TPM_Part2], Section 22.8) +@@ -1738,6 +1739,7 @@ typedef struct tdTPM_DAA_TPM { + TPM_DIGEST DAA_rekey; + UINT32 DAA_count; + } TPM_DAA_TPM; ++#define sizeof_TPM_DAA_TPM(s) (2 + (4 * 20) + 4) + + /* + * TPM_DAA_CONTEXT ([TPM_Part2], Section 22.9) +@@ -1752,6 +1754,7 @@ typedef struct tdTPM_DAA_CONTEXT { + BYTE DAA_scratch[256]; + BYTE DAA_stage; + } TPM_DAA_CONTEXT; ++#define sizeof_TPM_DAA_CONTEXT(s) (2 + (3 * 20) + 256 + 1) + + /* + * TPM_DAA_JOINDATA ([TPM_Part2], Section 22.10) +@@ -1763,6 +1766,7 @@ typedef struct tdTPM_DAA_JOINDATA { + BYTE DAA_join_u1[138]; /* WATCH: 138 (v1.2 rev 85) */ + TPM_DIGEST DAA_digest_n0; + } TPM_DAA_JOINDATA; ++#define sizeof_TPM_DAA_JOINDATA(s) (1 + 1 + 20) + + /* + * TPM_DAA_BLOB ([TPM_Part2], Section 22.12) +@@ -2033,6 +2037,7 @@ typedef struct tdTPM_STCLEAR_DATA { + TPM_COUNT_ID countID; + //UINT32 ownerReference; + } TPM_STCLEAR_DATA; ++#define sizeof_TPM_STCLEAR_DATA(s) (2 + 20 + 4) + + /* + * TPM_SESSION_DATA +@@ -2069,6 +2074,11 @@ typedef struct tdTPM_DAA_SESSION_DATA { + TPM_DAA_JOINDATA DAA_joinSession; + TPM_HANDLE handle; + } TPM_DAA_SESSION_DATA; ++#define sizeof_TPM_DAA_SESSION_DATA(s) ( 1 \ ++ + sizeof_TPM_DAA_ISSUER(s.DAA_issuerSettings) \ ++ + sizeof_TPM_DAA_TPM(s.DAA_tpmSpecific) \ ++ + sizeof_TPM_DAA_CONTEXT(s.DAA_session) \ ++ + sizeof_TPM_DAA_JOINDATA(s.DAA_joinSession) + 4) + + /* + * TPM_STANY_DATA ([TPM_Part2], Section 7.6) +@@ -2095,6 +2105,17 @@ typedef struct tdTPM_STANY_DATA { + TPM_DAA_SESSION_DATA sessionsDAA[TPM_MAX_SESSIONS_DAA]; + TPM_TRANSHANDLE transExclusive; + } TPM_STANY_DATA; ++#define sizeof_TPM_STANY_DATA(s) (2 + 20 + 20 + 1 \ ++ + sizeof_TPM_CURRENT_TICKS(s.currentTicks) \ ++ + 4 + (4 * TPM_MAX_SESSION_LIST) \ ++ + (sizeof_TPM_SESSION_DATA(s.sessions[0]) * TPM_MAX_SESSION_LIST) \ ++ + (sizeof_TPM_DAA_SESSION_DATA(s.sessionsDAA[0]) * TPM_MAX_SESSIONS_DAA) + 4) ++ ++#define sizeof_TPM_PERMANENT_DATA(s) (2 + 4 + 4*20 \ ++ + sizeof_RSA(s.endorsementKey) + TPM_ORD_MAX/8 \ ++ + (1+TPM_MAX_KEYS)*sizeof_TPM_KEY_DATA(s.srk) \ ++ + TPM_NUM_PCR*(sizeof_TPM_PCR_ATTRIBUTES(x)+20) \ ++ + TPM_MAX_COUNTERS*sizeof_TPM_COUNTER_VALUE2(x) + 1 + 4 + 20) + + /* + * TPM_DATA diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm/tpm_emulator.patch --- a/tools/vtpm/tpm_emulator.patch Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm/tpm_emulator.patch Wed Jun 28 07:52:21 2006 -0600 @@ -1,68 +1,63 @@ diff -uprN orig/tpm_emulator-0.2-x86_64/ -diff -uprN orig/tpm_emulator-0.2-x86_64/AUTHORS tpm_emulator/AUTHORS ---- orig/tpm_emulator-0.2-x86_64/AUTHORS 2005-08-15 00:58:57.000000000 -0700 -+++ tpm_emulator/AUTHORS 2005-09-14 20:27:22.000000000 -0700 -@@ -1 +1,2 @@ +diff -uprN tpm_emulator-0.3-x86_64/AUTHORS tpm_emulator/AUTHORS +--- tpm_emulator-0.3-x86_64/AUTHORS 2006-08-29 15:07:21.618299064 -0700 ++++ tpm_emulator/AUTHORS 2006-08-29 15:26:17.099679656 -0700 +@@ -1,2 +1,3 @@ Mario Strasser <mast@xxxxxxx> -+INTEL Corp <> -diff -uprN orig/tpm_emulator-0.2-x86_64/ChangeLog tpm_emulator/ChangeLog ---- orig/tpm_emulator-0.2-x86_64/ChangeLog 2005-08-15 00:58:57.000000000 -0700 -+++ tpm_emulator/ChangeLog 2005-09-14 20:27:22.000000000 -0700 -@@ -1,3 +1,7 @@ -+2005-08-16: INTEL Corp -+ * Set default permissions to PCRs -+ * Changed device to /dev/tpm0 -+ - 2005-08-15 Mario Strasser <mast@xxxxxxx> - * all: some typos corrected - * tpm_integrity.c: bug in TPM_Extend fixed -diff -uprN orig/tpm_emulator-0.2-x86_64/linux_module.h tpm_emulator/linux_module.h ---- orig/tpm_emulator-0.2-x86_64/linux_module.h 2005-09-15 19:21:14.844078720 -0700 -+++ tpm_emulator/linux_module.h 2005-09-14 20:27:22.000000000 -0700 -@@ -1,5 +1,6 @@ - /* Software-Based Trusted Platform Module (TPM) Emulator for Linux - * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, -+ * Copyright (C) 2005 INTEL Corp. - * - * This module is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published -@@ -35,7 +36,7 @@ - #include "tpm_version.h" - - #define TPM_DEVICE_MINOR 224 --#define TPM_DEVICE_NAME "tpm" -+#define TPM_DEVICE_NAME "tpm0" - #define TPM_MODULE_NAME "tpm_emulator" - - /* debug and log output functions */ -diff -uprN orig/tpm_emulator-0.2-x86_64/Makefile tpm_emulator/Makefile ---- orig/tpm_emulator-0.2-x86_64/Makefile 2005-09-15 19:21:14.845078568 -0700 -+++ tpm_emulator/Makefile 2005-09-14 20:27:22.000000000 -0700 -@@ -1,16 +1,22 @@ + Heiko Stamer <stamer@xxxxxxxx> [DAA] ++INTEL Corp <> [Dropped to Ring3] +diff -uprN tpm_emulator-0.3-x86_64/ChangeLog tpm_emulator/ChangeLog +--- tpm_emulator-0.3-x86_64/ChangeLog 2006-08-29 15:07:21.618299064 -0700 ++++ tpm_emulator/ChangeLog 2006-08-29 15:26:17.100679504 -0700 +@@ -1,3 +1,6 @@ ++2005-08-16 Intel Corp ++ * Moved module out of kernel to run as a ring 3 app ++ + 2005-12-24 Mario Strasser <mast@xxxxxxx> + * tpm_transport.c, tpm_marshalling.c, tpm_structures.h: + Transport session functionality added +diff -uprN tpm_emulator-0.3-x86_64/Makefile tpm_emulator/Makefile +--- tpm_emulator-0.3-x86_64/Makefile 2006-08-29 15:08:20.532342768 -0700 ++++ tpm_emulator/Makefile 2006-08-29 15:27:39.559143912 -0700 +@@ -1,22 +1,31 @@ # Software-Based Trusted Platform Module (TPM) Emulator for Linux # Copyright (C) 2004 Mario Strasser <mast@xxxxxxx> -+# Copyright (C) 2005 INTEL Corp. ++# Copyright (C) 2006 INTEL Corp. # - # $Id: Makefile 10 2005-04-26 20:59:50Z mast $ - -+XEN_ROOT := ../../.. -+EUID := $(shell id -u) -+ - # kernel settings - KERNEL_RELEASE := $(shell uname -r) + # $Id: Makefile 69 2005-12-13 12:55:52Z mast $ + +-# kernel settings +-KERNEL_RELEASE := $(shell uname -r) -KERNEL_BUILD := /lib/modules/$(KERNEL_RELEASE)/build -+CUR_DIR := $(shell pwd) -+LINUX_VERSION := $(shell cat $(CUR_DIR)/$(XEN_ROOT)/buildconfigs/mk.linux-2.6-xen | grep "LINUX_VER" | grep "2.6" | gawk '{ print $$3 }' ) -+KERNEL_BUILD := $(XEN_ROOT)/linux-$(LINUX_VERSION)-xen - MOD_SUBDIR := misc +-MOD_SUBDIR := misc COMPILE_ARCH ?= $(shell uname -m | sed -e s/i.86/x86_32/) # module settings -MODULE_NAME := tpm_emulator +BIN := tpm_emulator VERSION_MAJOR := 0 - VERSION_MINOR := 2 + VERSION_MINOR := 3 VERSION_BUILD := $(shell date +"%s") -@@ -34,11 +38,9 @@ DIRS := . crypto tpm + +-# enable/disable DEBUG messages +-EXTRA_CFLAGS += -Wall -DDEBUG -g ++# Installation program and options ++INSTALL = install ++INSTALL_PROG = $(INSTALL) -m0755 ++INSTALL_DIR = $(INSTALL) -d -m0755 ++ ++# Xen tools installation directory ++TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin ++ ++CC := gcc ++CFLAGS += -g -Wall $(INCLUDE) -DDEBUG ++CFLAGS += -I. -Itpm ++ ++# Is the simulator running in it's own vm? ++#CFLAGS += -DVTPM_MULTI_VM + + ifeq ($(COMPILE_ARCH),x86_64) + LIBDIR = lib64 +@@ -34,38 +43,31 @@ DIRS := . crypto tpm SRCS := $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.c)) OBJS := $(patsubst %.c, %.o, $(SRCS)) SRCS += $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.h)) @@ -71,29 +66,37 @@ diff -uprN orig/tpm_emulator-0.2-x86_64/ -obj-m := $(MODULE_NAME).o -$(MODULE_NAME)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a -+obj-m := $(BIN).o ++obj-m := $(BIN) +$(BIN)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a EXTRA_CFLAGS += -I$(src) -I$(src)/crypto -I$(src)/tpm -@@ -49,23 +51,17 @@ all: $(src)/crypto/gmp.h $(src)/crypto/l - @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules - - install: + # do not print "Entering directory ..." + MAKEFLAGS += --no-print-directory + +-all: $(src)/crypto/gmp.h $(src)/crypto/libgmp.a version +- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules ++all: $(BIN) ++ ++$(BIN): $(src)/crypto/gmp.h $(src)/crypto/libgmp.a version $(SRCS) $(OBJS) ++ $(CC) $(CFLAGS) $(OBJS) $(src)/crypto/libgmp.a -o $(BIN) ++ ++%.o: %.c ++ $(CC) $(CFLAGS) -c $< -o $@ + +-install: - @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules_install - test -d /var/tpm || mkdir /var/tpm - test -c /dev/tpm || mknod /dev/tpm c 10 224 - chmod 666 /dev/tpm - depmod -a -+ @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) INSTALL_MOD_PATH=$(DESTDIR) modules_install -+ test -d $(DESTDIR)/var/tpm || mkdir $(DESTDIR)/var/tpm -+ test -d $(DESTDIR)/dev || mkdir $(DESTDIR)/dev -+ test -c $(DESTDIR)/dev/tpm0 || [ $(EUID) -ne 0 ] || mknod $(DESTDIR)/dev/tpm0 c 10 224 -+ [ $(EUID) -ne 0 ] || chmod 666 $(DESTDIR)/dev/tpm0 ++install: $(BIN) ++ $(INSTALL_PROG) $(BIN) $(TOOLS_INSTALL_DIR) clean: - @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) clean - rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a +- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) clean +- rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a ++ rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a $(OBJS) -dist: $(DISTSRC) - rm -rf $(DISTDIR) @@ -103,25 +106,421 @@ diff -uprN orig/tpm_emulator-0.2-x86_64/ - tar -chzf $(DISTDIR).tar.gz $(DISTDIR) - rm -rf $(DISTDIR) +mrproper: clean ++ rm -f $(BIN) tpm_version.h $(src)/crypto/libgmp.a: test -f $(src)/crypto/libgmp.a || ln -s $(GMP_LIB) $(src)/crypto/libgmp.a -diff -uprN orig/tpm_emulator-0.2-x86_64/README tpm_emulator/README ---- orig/tpm_emulator-0.2-x86_64/README 2005-08-15 00:58:57.000000000 -0700 -+++ tpm_emulator/README 2005-09-14 20:27:22.000000000 -0700 -@@ -13,7 +13,8 @@ $Id: README 8 2005-01-25 21:11:45Z jmoli +diff -uprN tpm_emulator-0.3-x86_64/README tpm_emulator/README +--- tpm_emulator-0.3-x86_64/README 2006-08-29 15:07:43.530967832 -0700 ++++ tpm_emulator/README 2006-08-29 15:26:17.105678744 -0700 +@@ -13,7 +13,8 @@ $Id: README 78 2006-01-07 10:45:39Z mast Copyright -------------------------------------------------------------------------- Copyright (C) 2004 Mario Strasser <mast@xxxxxxx> and Swiss Federal -Institute of Technology (ETH) Zurich. + Institute of Technology (ETH) Zurich. -+Copyright (C) 2005 ++Copyright (C) 2005 INTEL Corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -diff -uprN orig/tpm_emulator-0.2-x86_64/tpm/tpm_data.c tpm_emulator/tpm/tpm_data.c ---- orig/tpm_emulator-0.2-x86_64/tpm/tpm_data.c 2005-09-15 19:21:14.847078264 -0700 -+++ tpm_emulator/tpm/tpm_data.c 2005-09-14 20:27:22.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/README.1st tpm_emulator/README.1st +--- tpm_emulator-0.3-x86_64/README.1st 1969-12-31 16:00:00.000000000 -0800 ++++ tpm_emulator/README.1st 2006-08-29 15:26:17.105678744 -0700 +@@ -0,0 +1 @@ ++Note that you must manually create /tmp/tpm_in.fifo and /tmp/tpm_out.fifo for this emulator to work. +diff -uprN tpm_emulator-0.3-x86_64/crypto/gmp_kernel_wrapper.c tpm_emulator/crypto/gmp_kernel_wrapper.c +--- tpm_emulator-0.3-x86_64/crypto/gmp_kernel_wrapper.c 2006-08-29 15:07:43.525968592 -0700 ++++ tpm_emulator/crypto/gmp_kernel_wrapper.c 2006-08-29 15:26:17.101679352 -0700 +@@ -1,5 +1,6 @@ + /* Software-Based Trusted Platform Module (TPM) Emulator for Linux + * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, ++ * Copyright (C) 2005 INTEL Corp + * + * This module is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published +@@ -24,15 +25,10 @@ int __gmp_junk; + void __attribute__ ((regparm(0))) __gmp_assert_fail(const char *filename, + int linenum, const char *expr) + { +- panic(KERN_CRIT TPM_MODULE_NAME "%s:%d: GNU MP assertion failed: %s\n", ++ error("%s:%d: GNU MP assertion failed: %s\n", + filename, linenum, expr); + } + +-void __attribute__ ((regparm(0))) abort(void) +-{ +- panic(KERN_CRIT TPM_MODULE_NAME "GNU MP abort() was called\n"); +-} +- + /* overwrite GNU MP random functions (used by mpz/millerrabin.c) */ + + void __attribute__ ((regparm(0))) gmp_randinit(gmp_randstate_t rstate, +@@ -77,20 +73,19 @@ void __attribute__ ((regparm(0))) mpz_ur + + void __attribute__ ((regparm(0))) *kernel_allocate(size_t size) + { +- void *ret = (void*)kmalloc(size, GFP_KERNEL); +- if (!ret) panic(KERN_CRIT TPM_MODULE_NAME +- "GMP: cannot allocate memory (size=%Zu)\n", size); ++ void *ret = (void*)malloc(size); ++ if (!ret) error("GMP: cannot allocate memory (size=%Zu)\n", size); + return ret; + } + + void __attribute__ ((regparm(0))) *kernel_reallocate(void *oldptr, + size_t old_size, size_t new_size) + { +- void *ret = (void*)kmalloc(new_size, GFP_KERNEL); +- if (!ret) panic(KERN_CRIT TPM_MODULE_NAME "GMP: Cannot reallocate memory " ++ void *ret = (void*)malloc(new_size); ++ if (!ret) error("GMP: Cannot reallocate memory " + "(old_size=%Zu new_size=%Zu)\n", old_size, new_size); + memcpy(ret, oldptr, old_size); +- kfree(oldptr); ++ free(oldptr); + return ret; + } + +@@ -99,7 +94,7 @@ void __attribute__ ((regparm(0))) kernel + /* overwrite used memory */ + if (blk_ptr != NULL) { + memset(blk_ptr, 0, blk_size); +- kfree(blk_ptr); ++ free(blk_ptr); + } + } + +diff -uprN tpm_emulator-0.3-x86_64/crypto/rsa.c tpm_emulator/crypto/rsa.c +--- tpm_emulator-0.3-x86_64/crypto/rsa.c 2006-08-29 15:07:21.618299064 -0700 ++++ tpm_emulator/crypto/rsa.c 2006-08-29 15:26:17.102679200 -0700 +@@ -1,5 +1,6 @@ + /* Software-Based Trusted Platform Module (TPM) Emulator for Linux + * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, ++ * Copyright (C) 2005 INTEL Corp + * + * This module is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published +@@ -381,7 +382,7 @@ static int encode_message(int type, uint + msg[0] = 0x00; + get_random_bytes(&msg[1], SHA1_DIGEST_LENGTH); + sha1_init(&ctx); +- sha1_update(&ctx, "TCPA", 4); ++ sha1_update(&ctx, (uint8_t *) "TCPA", 4); + sha1_final(&ctx, &msg[1 + SHA1_DIGEST_LENGTH]); + memset(&msg[1 + 2 * SHA1_DIGEST_LENGTH], 0x00, + msg_len - data_len - 2 * SHA1_DIGEST_LENGTH - 2); +@@ -429,7 +430,7 @@ static int decode_message(int type, uint + mask_generation(&msg[1], SHA1_DIGEST_LENGTH, + &msg[1 + SHA1_DIGEST_LENGTH], msg_len - SHA1_DIGEST_LENGTH - 1); + sha1_init(&ctx); +- sha1_update(&ctx, "TCPA", 4); ++ sha1_update(&ctx, (uint8_t *) "TCPA", 4); + sha1_final(&ctx, &msg[1]); + if (memcmp(&msg[1], &msg[1 + SHA1_DIGEST_LENGTH], + SHA1_DIGEST_LENGTH) != 0) return -1; +diff -uprN tpm_emulator-0.3-x86_64/linux_module.c tpm_emulator/linux_module.c +--- tpm_emulator-0.3-x86_64/linux_module.c 2006-08-29 15:07:43.526968440 -0700 ++++ tpm_emulator/linux_module.c 1969-12-31 16:00:00.000000000 -0800 +@@ -1,194 +0,0 @@ +-/* Software-Based Trusted Platform Module (TPM) Emulator for Linux +- * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, +- * +- * This module is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published +- * by the Free Software Foundation; either version 2 of the License, +- * or (at your option) any later version. +- * +- * This module 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 General Public License for more details. +- * +- * $Id: linux_module.c 76 2006-01-02 22:17:58Z hstamer $ +- */ +- +-#include <linux/module.h> +-#include <linux/kernel.h> +-#include <linux/init.h> +-#include <linux/miscdevice.h> +-#include <linux/poll.h> +-#include "linux_module.h" +-#include "tpm/tpm_emulator.h" +- +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Mario Strasser <mast@xxxxxxx>"); +-MODULE_DESCRIPTION("Trusted Platform Module (TPM) Emulator"); +-MODULE_SUPPORTED_DEVICE(TPM_DEVICE_NAME); +- +-/* module startup parameters */ +-char *startup = "save"; +-module_param(startup, charp, 0444); +-MODULE_PARM_DESC(startup, " Sets the startup mode of the TPM. " +- "Possible values are 'clear', 'save' (default) and 'deactivated."); +-char *storage_file = "/var/tpm/tpm_emulator-1.2.0.2"; +-module_param(storage_file, charp, 0644); +-MODULE_PARM_DESC(storage_file, " Sets the persistent-data storage " +- "file of the TPM."); +- +-/* TPM lock */ +-static struct semaphore tpm_mutex; +- +-/* TPM command response */ +-static struct { +- uint8_t *data; +- uint32_t size; +-} tpm_response; +- +-/* module state */ +-#define STATE_IS_OPEN 0 +-static uint32_t module_state; +- +-static int tpm_open(struct inode *inode, struct file *file) +-{ +- debug("%s()", __FUNCTION__); +- if (test_and_set_bit(STATE_IS_OPEN, (void*)&module_state)) return -EBUSY; +- return 0; +-} +- +-static int tpm_release(struct inode *inode, struct file *file) +-{ +- debug("%s()", __FUNCTION__); +- clear_bit(STATE_IS_OPEN, (void*)&module_state); +- down(&tpm_mutex); +- if (tpm_response.data != NULL) { +- kfree(tpm_response.data); +- tpm_response.data = NULL; +- } +- up(&tpm_mutex); +- return 0; +-} +- +-static ssize_t tpm_read(struct file *file, char *buf, size_t count, loff_t *ppos) +-{ +- debug("%s(%Zu)", __FUNCTION__, count); +- down(&tpm_mutex); +- if (tpm_response.data != NULL) { +- count = min(count, (size_t)tpm_response.size - (size_t)*ppos); +- count -= copy_to_user(buf, &tpm_response.data[*ppos], count); +- *ppos += count; +- if ((size_t)tpm_response.size == (size_t)*ppos) { +- kfree(tpm_response.data); +- tpm_response.data = NULL; +- } +- } else { +- count = 0; +- } +- up(&tpm_mutex); +- return count; +-} +- +-static ssize_t tpm_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +-{ +- debug("%s(%Zu)", __FUNCTION__, count); +- down(&tpm_mutex); +- *ppos = 0; +- if (tpm_response.data != NULL) kfree(tpm_response.data); +- if (tpm_handle_command(buf, count, &tpm_response.data, +- &tpm_response.size) != 0) { +- count = -EILSEQ; +- tpm_response.data = NULL; +- } +- up(&tpm_mutex); +- return count; +-} +- +-#define TPMIOC_CANCEL _IO('T', 0x00) +-#define TPMIOC_TRANSMIT _IO('T', 0x01) +- +-static int tpm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +-{ +- debug("%s(%d, %p)", __FUNCTION__, cmd, (char*)arg); +- if (cmd == TPMIOC_TRANSMIT) { +- uint32_t count = ntohl(*(uint32_t*)(arg + 2)); +- down(&tpm_mutex); +- if (tpm_response.data != NULL) kfree(tpm_response.data); +- if (tpm_handle_command((char*)arg, count, &tpm_response.data, +- &tpm_response.size) == 0) { +- tpm_response.size -= copy_to_user((char*)arg, tpm_response.data, +- tpm_response.size); +- kfree(tpm_response.data); +- tpm_response.data = NULL; +- } else { +- tpm_response.size = 0; +- tpm_response.data = NULL; +- } +- up(&tpm_mutex); +- return tpm_response.size; +- } +- return -1; +-} +- +-struct file_operations fops = { +- .owner = THIS_MODULE, +- .open = tpm_open, +- .release = tpm_release, +- .read = tpm_read, +- .write = tpm_write, +- .ioctl = tpm_ioctl, +-}; +- +-static struct miscdevice tpm_dev = { +- .minor = TPM_DEVICE_MINOR, +- .name = TPM_DEVICE_NAME, +- .fops = &fops, +-}; +- +-int __init init_tpm_module(void) +-{ +- int res = misc_register(&tpm_dev); +- if (res != 0) { +- error("misc_register() failed for minor %d\n", TPM_DEVICE_MINOR); +- return res; +- } +- /* initialize variables */ +- sema_init(&tpm_mutex, 1); +- module_state = 0; +- tpm_response.data = NULL; +- /* initialize TPM emulator */ +- if (!strcmp(startup, "clear")) { +- tpm_emulator_init(1); +- } else if (!strcmp(startup, "save")) { +- tpm_emulator_init(2); +- } else if (!strcmp(startup, "deactivated")) { +- tpm_emulator_init(3); +- } else { +- error("invalid startup mode '%s'; must be 'clear', " +- "'save' (default) or 'deactivated", startup); +- misc_deregister(&tpm_dev); +- return -EINVAL; +- } +- return 0; +-} +- +-void __exit cleanup_tpm_module(void) +-{ +- tpm_emulator_shutdown(); +- misc_deregister(&tpm_dev); +- if (tpm_response.data != NULL) kfree(tpm_response.data); +-} +- +-module_init(init_tpm_module); +-module_exit(cleanup_tpm_module); +- +-uint64_t tpm_get_ticks(void) +-{ +- static struct timespec old_time = {0, 0}; +- struct timespec new_time = current_kernel_time(); +- uint64_t ticks = (uint64_t)(old_time.tv_sec - new_time.tv_sec) * 1000000 +- + (old_time.tv_nsec - new_time.tv_nsec) / 1000; +- old_time = new_time; +- return (ticks > 0) ? ticks : 1; +-} +- +diff -uprN tpm_emulator-0.3-x86_64/linux_module.h tpm_emulator/linux_module.h +--- tpm_emulator-0.3-x86_64/linux_module.h 2006-08-29 15:07:43.527968288 -0700 ++++ tpm_emulator/linux_module.h 2006-08-29 15:26:17.103679048 -0700 +@@ -1,5 +1,6 @@ + /* Software-Based Trusted Platform Module (TPM) Emulator for Linux + * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, ++ * Copyright (C) 2005 INTEL Corp + * + * This module is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published +@@ -17,17 +18,22 @@ + #ifndef _LINUX_MODULE_H_ + #define _LINUX_MODULE_H_ + +-#include <linux/version.h> +-#include <linux/kernel.h> +-#include <linux/slab.h> ++#include <malloc.h> ++#include <stdint.h> ++#include <stdio.h> ++#include <string.h> + #include <linux/types.h> +-#include <linux/string.h> +-#include <linux/random.h> +-#include <linux/time.h> +-#include <asm/byteorder.h> + +-/* module settings */ ++#include <endian.h> ++#define __BYTEORDER_HAS_U64__ ++#ifdef LITTLE_ENDIAN ++ #include <linux/byteorder/little_endian.h> ++#else ++ #include <linux/byteorder/big_endian.h> ++#endif + ++/* module settings */ ++#define min(A,B) ((A)<(B)?(A):(B)) + #ifndef STR + #define STR(s) __STR__(s) + #define __STR__(s) #s +@@ -38,35 +44,36 @@ + #define TPM_DEVICE_NAME "tpm" + #define TPM_MODULE_NAME "tpm_emulator" + +-/* debug and log output functions */ +- + #ifdef DEBUG +-#define debug(fmt, ...) printk(KERN_DEBUG "%s %s:%d: Debug: " fmt "\n", \ +- TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__) ++#define debug(fmt, ...) printf("TPMD: %s:%d: Debug: " fmt "\n", \ ++ __FILE__, __LINE__, ## __VA_ARGS__) + #else + #define debug(fmt, ...) + #endif +-#define info(fmt, ...) printk(KERN_INFO "%s %s:%d: Info: " fmt "\n", \ +- TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__) +-#define error(fmt, ...) printk(KERN_ERR "%s %s:%d: Error: " fmt "\n", \ +- TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__) +-#define alert(fmt, ...) printk(KERN_ALERT "%s %s:%d: Alert: " fmt "\n", \ +- TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__) ++#define info(fmt, ...) printf("TPMD: %s:%d: Info: " fmt "\n", \ ++ __FILE__, __LINE__, ## __VA_ARGS__) ++#define error(fmt, ...) printf("TPMD: %s:%d: Error: " fmt "\n", \ ++ __FILE__, __LINE__, ## __VA_ARGS__) ++#define alert(fmt, ...) printf("TPMD: %s:%d: Alert: " fmt "\n", \ ++ __FILE__, __LINE__, ## __VA_ARGS__) + + /* memory allocation */ + + static inline void *tpm_malloc(size_t size) + { +- return kmalloc(size, GFP_KERNEL); ++ return malloc(size); + } + + static inline void tpm_free(const void *ptr) + { +- if (ptr != NULL) kfree(ptr); ++ if (ptr != NULL) free( (void *) ptr); + } + + /* random numbers */ + ++//FIXME; ++void get_random_bytes(void *buf, int nbytes); ++ + static inline void tpm_get_random_bytes(void *buf, int nbytes) + { + get_random_bytes(buf, nbytes); +@@ -86,9 +93,9 @@ uint64_t tpm_get_ticks(void); + #define CPU_TO_LE16(x) __cpu_to_le16(x) + + #define BE64_TO_CPU(x) __be64_to_cpu(x) +-#define LE64_TO_CPU(x) __be64_to_cpu(x) ++#define LE64_TO_CPU(x) __le64_to_cpu(x) + #define BE32_TO_CPU(x) __be32_to_cpu(x) +-#define LE32_TO_CPU(x) __be32_to_cpu(x) ++#define LE32_TO_CPU(x) __le32_to_cpu(x) + #define BE16_TO_CPU(x) __be16_to_cpu(x) + #define LE16_TO_CPU(x) __le16_to_cpu(x) + +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_audit.c tpm_emulator/tpm/tpm_audit.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_audit.c 2006-08-29 15:07:21.620298760 -0700 ++++ tpm_emulator/tpm/tpm_audit.c 2006-08-29 15:26:17.107678440 -0700 @@ -1,6 +1,7 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -130,15 +529,1213 @@ diff -uprN orig/tpm_emulator-0.2-x86_64/ * * This module is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published -@@ -85,6 +86,11 @@ void tpm_init_data(void) - tpmData.permanent.data.version.revMinor = VERSION_MINOR; - /* setup PCR attributes */ - for (i = 0; i < TPM_NUM_PCR; i++) { -+ int j; -+ for (j=0; j < TPM_NUM_LOCALITY; j++) { -+ tpmData.permanent.data.pcrAttrib[i].pcrExtendLocal[j] = TRUE; +@@ -45,14 +46,14 @@ void tpm_audit_request(TPM_COMMAND_CODE + tpmData.permanent.data.auditMonotonicCounter++; + } + /* update audit digest */ +- *((UINT16*)&buf[0]) = cpu_to_be16(TPM_TAG_AUDIT_EVENT_IN); +- *((UINT32*)&buf[2]) = cpu_to_be32(ordinal); ++ *((UINT16*)&buf[0]) = CPU_TO_BE16(TPM_TAG_AUDIT_EVENT_IN); ++ *((UINT32*)&buf[2]) = CPU_TO_BE32(ordinal); + sha1_init(&sha1_ctx); + sha1_update(&sha1_ctx, req->param, req->paramSize); + sha1_final(&sha1_ctx, &buf[6]); +- *((UINT16*)&buf[26]) = cpu_to_be16(TPM_TAG_COUNTER_VALUE); ++ *((UINT16*)&buf[26]) = CPU_TO_BE16(TPM_TAG_COUNTER_VALUE); + memset(&buf[30], 0, 4); +- *((UINT32*)&buf[34]) = cpu_to_be32(tpmData.permanent.data.auditMonotonicCounter); ++ *((UINT32*)&buf[34]) = CPU_TO_BE32(tpmData.permanent.data.auditMonotonicCounter); + sha1_init(&sha1_ctx); + sha1_update(&sha1_ctx, tpmData.stany.data.auditDigest.digest, + sizeof(TPM_DIGEST)); +@@ -70,15 +71,15 @@ void tpm_audit_response(TPM_COMMAND_CODE + && (AUDIT_STATUS[ord / 8] & (1 << (ord & 0x07)))) { + info("tpm_audit_response()"); + /* update audit digest */ +- *((UINT16*)&buf[0]) = cpu_to_be16(TPM_TAG_AUDIT_EVENT_OUT); +- *((UINT32*)&buf[2]) = cpu_to_be32(ordinal); ++ *((UINT16*)&buf[0]) = CPU_TO_BE16(TPM_TAG_AUDIT_EVENT_OUT); ++ *((UINT32*)&buf[2]) = CPU_TO_BE32(ordinal); + sha1_init(&sha1_ctx); + sha1_update(&sha1_ctx, rsp->param, rsp->paramSize); + sha1_final(&sha1_ctx, &buf[6]); +- *((UINT16*)&buf[26]) = cpu_to_be16(TPM_TAG_COUNTER_VALUE); ++ *((UINT16*)&buf[26]) = CPU_TO_BE16(TPM_TAG_COUNTER_VALUE); + memset(&buf[30], 0, 4); +- *((UINT32*)&buf[34]) = cpu_to_be32(tpmData.permanent.data.auditMonotonicCounter); +- *((UINT32*)&buf[34]) = cpu_to_be32(rsp->result); ++ *((UINT32*)&buf[34]) = CPU_TO_BE32(tpmData.permanent.data.auditMonotonicCounter); ++ *((UINT32*)&buf[34]) = CPU_TO_BE32(rsp->result); + sha1_init(&sha1_ctx); + sha1_update(&sha1_ctx, tpmData.stany.data.auditDigest.digest, + sizeof(TPM_DIGEST)); +@@ -158,7 +159,7 @@ TPM_RESULT TPM_GetAuditDigestSigned(TPM_ + } + memcpy(&buf[0], "\x05\x00ADIG", 6); + memcpy(&buf[6], antiReplay->nonce, 20); +- *(UINT32*)&buf[26] = cpu_to_be32(buf_size - 30); ++ *(UINT32*)&buf[26] = CPU_TO_BE32(buf_size - 30); + memcpy(&buf[30], auditDigest->digest, 20); + ptr = &buf[50]; + len = buf_size - 50; +@@ -198,4 +199,3 @@ TPM_RESULT TPM_SetOrdinalAuditStatus(TPM + } + return TPM_SUCCESS; + } +- +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_authorization.c tpm_emulator/tpm/tpm_authorization.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_authorization.c 2006-08-29 15:07:21.620298760 -0700 ++++ tpm_emulator/tpm/tpm_authorization.c 2006-08-29 15:26:17.108678288 -0700 +@@ -1,6 +1,7 @@ + /* Software-Based Trusted Platform Module (TPM) Emulator for Linux + * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, + * Swiss Federal Institute of Technology (ETH) Zurich ++ * Copyright (C) 2005 INTEL Corp + * + * This module is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published +@@ -279,7 +280,7 @@ TPM_RESULT tpm_verify_auth(TPM_AUTH *aut + { + hmac_ctx_t ctx; + TPM_SESSION_DATA *session; +- UINT32 auth_handle = cpu_to_be32(auth->authHandle); ++ UINT32 auth_handle = CPU_TO_BE32(auth->authHandle); + + info("tpm_verify_auth(%08x)", auth->authHandle); + /* get dedicated authorization or transport session */ +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_capability.c tpm_emulator/tpm/tpm_capability.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_capability.c 2006-08-29 15:07:21.620298760 -0700 ++++ tpm_emulator/tpm/tpm_capability.c 2006-08-29 15:26:17.109678136 -0700 +@@ -1,6 +1,7 @@ + /* Software-Based Trusted Platform Module (TPM) Emulator for Linux + * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, + * Swiss Federal Institute of Technology (ETH) Zurich ++ * Copyright (C) 2005 INTEL Corp + * + * This module is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published +@@ -406,7 +407,7 @@ TPM_RESULT TPM_GetCapability(TPM_CAPABIL + + case TPM_CAP_KEY_HANDLE: + debug("[TPM_CAP_KEY_HANDLE]"); +- subCapSize = cpu_to_be32(TPM_RT_KEY); ++ subCapSize = CPU_TO_BE32(TPM_RT_KEY); + return cap_handle(4, (BYTE*)&subCapSize, respSize, resp); + + case TPM_CAP_CHECK_LOADED: +@@ -480,4 +481,3 @@ TPM_RESULT TPM_GetCapability(TPM_CAPABIL + return TPM_BAD_MODE; + } + } +- +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_cmd_handler.c tpm_emulator/tpm/tpm_cmd_handler.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_cmd_handler.c 2006-08-29 15:07:21.621298608 -0700 ++++ tpm_emulator/tpm/tpm_cmd_handler.c 2006-08-29 15:26:17.113677528 -0700 +@@ -1,6 +1,7 @@ + /* Software-Based Trusted Platform Module (TPM) Emulator for Linux + * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, + * Swiss Federal Institute of Technology (ETH) Zurich ++ * Copyright (C) 2005 INTEL Corp + * + * This module is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published +@@ -73,7 +74,7 @@ void tpm_compute_in_param_digest(TPM_REQ + { + sha1_ctx_t sha1; + UINT32 offset = tpm_get_param_offset(req->ordinal); +- UINT32 ord = cpu_to_be32(req->ordinal); ++ UINT32 ord = CPU_TO_BE32(req->ordinal); + + /* compute SHA1 hash */ + if (offset <= req->paramSize) { +@@ -89,8 +90,8 @@ void tpm_compute_in_param_digest(TPM_REQ + void tpm_compute_out_param_digest(TPM_COMMAND_CODE ordinal, TPM_RESPONSE *rsp) + { + sha1_ctx_t sha1; +- UINT32 res = cpu_to_be32(rsp->result); +- UINT32 ord = cpu_to_be32(ordinal); ++ UINT32 res = CPU_TO_BE32(rsp->result); ++ UINT32 ord = CPU_TO_BE32(ordinal); + + /* compute SHA1 hash */ + sha1_init(&sha1); +@@ -3123,7 +3124,7 @@ static void tpm_setup_rsp_auth(TPM_COMMA + hmac_update(&hmac, rsp->auth2->digest, sizeof(rsp->auth2->digest)); + #if 0 + if (tpm_get_auth(rsp->auth2->authHandle)->type == TPM_ST_OIAP) { +- UINT32 handle = cpu_to_be32(rsp->auth2->authHandle); ++ UINT32 handle = CPU_TO_BE32(rsp->auth2->authHandle); + hmac_update(&hmac, (BYTE*)&handle, 4); + } + #endif +@@ -3138,7 +3139,7 @@ static void tpm_setup_rsp_auth(TPM_COMMA + hmac_update(&hmac, rsp->auth1->digest, sizeof(rsp->auth1->digest)); + #if 0 + if (tpm_get_auth(rsp->auth1->authHandle)->type == TPM_ST_OIAP) { +- UINT32 handle = cpu_to_be32(rsp->auth1->authHandle); ++ UINT32 handle = CPU_TO_BE32(rsp->auth1->authHandle); + hmac_update(&hmac, (BYTE*)&handle, 4); + } + #endif +@@ -3221,7 +3222,9 @@ extern const char *tpm_error_to_string(T + void tpm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp) + { + TPM_RESULT res; +- ++ ++ req->tag = (BYTE) req->tag; // FIXME: Why is this here ++ + /* setup authorisation as well as response tag and size */ + memset(rsp, 0, sizeof(*rsp)); + switch (req->tag) { +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_crypto.c tpm_emulator/tpm/tpm_crypto.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_crypto.c 2006-08-29 15:07:43.531967680 -0700 ++++ tpm_emulator/tpm/tpm_crypto.c 2006-08-29 15:26:17.114677376 -0700 +@@ -1,6 +1,7 @@ + /* Software-Based Trusted Platform Module (TPM) Emulator for Linux + * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, + * Swiss Federal Institute of Technology (ETH) Zurich ++ * Copyright (C) 2005 INTEL Corp + * + * This module is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published +@@ -106,7 +107,7 @@ TPM_RESULT tpm_sign(TPM_KEY_DATA *key, T + /* setup TPM_SIGN_INFO structure */ + memcpy(&buf[0], "\x05\x00SIGN", 6); + memcpy(&buf[6], auth->nonceOdd.nonce, 20); +- *(UINT32*)&buf[26] = cpu_to_be32(areaToSignSize); ++ *(UINT32*)&buf[26] = CPU_TO_BE32(areaToSignSize); + memcpy(&buf[30], areaToSign, areaToSignSize); + if (rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1, + buf, areaToSignSize + 30, *sig)) { +@@ -383,4 +384,3 @@ TPM_RESULT TPM_CertifyKey2(TPM_KEY_HANDL + } + return TPM_SUCCESS; + } +- +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_daa.c tpm_emulator/tpm/tpm_daa.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_daa.c 2006-08-29 15:07:21.622298456 -0700 ++++ tpm_emulator/tpm/tpm_daa.c 2006-08-29 15:26:17.119676616 -0700 +@@ -700,14 +700,14 @@ info("tested until here"); + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x00", 1); ++ sha1_update(&sha1, (BYTE *) "\x00", 1); + sha1_final(&sha1, scratch); + sha1_init(&sha1); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x01", 1); ++ sha1_update(&sha1, (BYTE *) "\x01", 1); + sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH); + mpz_init(f), mpz_init(q); + mpz_import(f, 2 * SHA1_DIGEST_LENGTH, 1, 1, 0, 0, scratch); +@@ -787,14 +787,14 @@ info("tested until here"); + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x00", 1); ++ sha1_update(&sha1, (BYTE *) "\x00", 1); + sha1_final(&sha1, scratch); + sha1_init(&sha1); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x01", 1); ++ sha1_update(&sha1, (BYTE *) "\x01", 1); + sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH); + mpz_init(f), mpz_init(q); + mpz_import(f, 2 * SHA1_DIGEST_LENGTH, 1, 1, 0, 0, scratch); +@@ -1440,14 +1440,14 @@ info("tested until here"); + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x00", 1); ++ sha1_update(&sha1, (BYTE *) "\x00", 1); + sha1_final(&sha1, scratch); + sha1_init(&sha1); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x01", 1); ++ sha1_update(&sha1, (BYTE *) "\x01", 1); + sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH); + mpz_init(f), mpz_init(q); + mpz_import(f, 2 * SHA1_DIGEST_LENGTH, 1, 1, 0, 0, scratch); +@@ -1660,14 +1660,14 @@ info("tested until here"); + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x00", 1); ++ sha1_update(&sha1, (BYTE *) "\x00", 1); + sha1_final(&sha1, scratch); + sha1_init(&sha1); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x01", 1); ++ sha1_update(&sha1, (BYTE *) "\x01", 1); + sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH); + mpz_init(f), mpz_init(q); + mpz_import(f, 2 * SHA1_DIGEST_LENGTH, 1, 1, 0, 0, scratch); +@@ -1740,14 +1740,14 @@ info("tested until here"); + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x00", 1); ++ sha1_update(&sha1, (BYTE *) "\x00", 1); + sha1_final(&sha1, scratch); + sha1_init(&sha1); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x01", 1); ++ sha1_update(&sha1, (BYTE *) "\x01", 1); + sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH); + mpz_init(f), mpz_init(q); + mpz_import(f, 2 * SHA1_DIGEST_LENGTH, 1, 1, 0, 0, scratch); +@@ -2828,14 +2828,14 @@ TPM_RESULT TPM_DAA_Sign(TPM_HANDLE handl + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x00", 1); ++ sha1_update(&sha1, (BYTE *) "\x00", 1); + sha1_final(&sha1, scratch); + sha1_init(&sha1); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x01", 1); ++ sha1_update(&sha1, (BYTE *) "\x01", 1); + sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH); + mpz_init(f), mpz_init(q); + mpz_import(f, 2 * SHA1_DIGEST_LENGTH, 1, 1, 0, 0, scratch); +@@ -3050,7 +3050,7 @@ TPM_RESULT TPM_DAA_Sign(TPM_HANDLE handl + sha1_init(&sha1); + sha1_update(&sha1, (BYTE*) &session->DAA_session.DAA_digest, + sizeof(session->DAA_session.DAA_digest)); +- sha1_update(&sha1, "\x01", 1); ++ sha1_update(&sha1, (BYTE *) "\x01", 1); + sha1_update(&sha1, inputData1, inputSize1); + sha1_final(&sha1, (BYTE*) &session->DAA_session.DAA_digest); + } +@@ -3078,7 +3078,7 @@ TPM_RESULT TPM_DAA_Sign(TPM_HANDLE handl + sha1_init(&sha1); + sha1_update(&sha1, (BYTE*) &session->DAA_session.DAA_digest, + sizeof(session->DAA_session.DAA_digest)); +- sha1_update(&sha1, "\x01", 1); ++ sha1_update(&sha1, (BYTE *) "\x01", 1); + rsa_export_modulus(&aikData->key, scratch, &size); + sha1_update(&sha1, scratch, size); + sha1_final(&sha1, (BYTE*) &session->DAA_session.DAA_digest); +@@ -3134,14 +3134,14 @@ TPM_RESULT TPM_DAA_Sign(TPM_HANDLE handl + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x00", 1); ++ sha1_update(&sha1, (BYTE *) "\x00", 1); + sha1_final(&sha1, scratch); + sha1_init(&sha1); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x01", 1); ++ sha1_update(&sha1, (BYTE *) "\x01", 1); + sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH); + mpz_init(f), mpz_init(q); + mpz_import(f, 2 * SHA1_DIGEST_LENGTH, 1, 1, 0, 0, scratch); +@@ -3213,14 +3213,14 @@ TPM_RESULT TPM_DAA_Sign(TPM_HANDLE handl + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x00", 1); ++ sha1_update(&sha1, (BYTE *) "\x00", 1); + sha1_final(&sha1, scratch); + sha1_init(&sha1); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, + sizeof(session->DAA_tpmSpecific.DAA_rekey)); + sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, + sizeof(session->DAA_tpmSpecific.DAA_count)); +- sha1_update(&sha1, "\x01", 1); ++ sha1_update(&sha1, (BYTE *) "\x01", 1); + sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH); + mpz_init(f), mpz_init(q); + mpz_import(f, 2 * SHA1_DIGEST_LENGTH, 1, 1, 0, 0, scratch); +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_data.c tpm_emulator/tpm/tpm_data.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_data.c 2006-08-29 15:08:20.535342312 -0700 ++++ tpm_emulator/tpm/tpm_data.c 2006-08-29 15:26:17.121676312 -0700 +@@ -150,44 +150,43 @@ void tpm_release_data(void) + + #ifdef TPM_STORE_TO_FILE + +-#include <linux/fs.h> +-#include <linux/unistd.h> +-#include <asm/uaccess.h> ++#include <sys/types.h> ++#include <sys/stat.h> ++#include <fcntl.h> ++#include <unistd.h> + + #define TPM_STORAGE_FILE "/var/tpm/tpm_emulator-1.2." STR(VERSION_MAJOR) "." STR(VERSION_MINOR) + + static int write_to_file(uint8_t *data, size_t data_length) + { + int res; +- struct file *fp; +- mm_segment_t old_fs = get_fs(); +- fp = filp_open(TPM_STORAGE_FILE, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR); +- if (IS_ERR(fp)) return -1; +- set_fs(get_ds()); +- res = fp->f_op->write(fp, data, data_length, &fp->f_pos); +- set_fs(old_fs); +- filp_close(fp, NULL); ++ int fp; ++ fp = open(TPM_STORAGE_FILE, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR); ++ res = write(fp, data, data_length); ++ close(fp); + return (res == data_length) ? 0 : -1; + } + + static int read_from_file(uint8_t **data, size_t *data_length) + { + int res; +- struct file *fp; +- mm_segment_t old_fs = get_fs(); +- fp = filp_open(TPM_STORAGE_FILE, O_RDONLY, 0); +- if (IS_ERR(fp)) return -1; +- *data_length = (size_t)fp->f_dentry->d_inode->i_size; +- /* *data_length = i_size_read(fp->f_dentry->d_inode); */ ++ int fp, file_status; ++ struct stat file_info; ++ fp = open(TPM_STORAGE_FILE, O_RDONLY, 0); ++ file_status = fstat(fp, &file_info); ++ if (file_status < 0) { ++ close(fp); ++ return -1; ++ } ++ ++ *data_length = file_info.st_size; + *data = tpm_malloc(*data_length); + if (*data == NULL) { +- filp_close(fp, NULL); ++ close(fp); + return -1; + } +- set_fs(get_ds()); +- res = fp->f_op->read(fp, *data, *data_length, &fp->f_pos); +- set_fs(old_fs); +- filp_close(fp, NULL); ++ res = read(fp, *data, *data_length); ++ close(fp); + if (res != *data_length) { + tpm_free(*data); + return -1; +@@ -278,7 +277,7 @@ int tpm_restore_permanent_data(void) + + int tpm_erase_permanent_data(void) + { +- int res = write_to_file("", 0); ++ int res = write_to_file((uint8_t *) "", 0); + return res; + } + +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_data.c.orig tpm_emulator/tpm/tpm_data.c.orig +--- tpm_emulator-0.3-x86_64/tpm/tpm_data.c.orig 1969-12-31 16:00:00.000000000 -0800 ++++ tpm_emulator/tpm/tpm_data.c.orig 2006-08-29 15:26:08.469991568 -0700 +@@ -0,0 +1,284 @@ ++/* Software-Based Trusted Platform Module (TPM) Emulator for Linux ++ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, ++ * Swiss Federal Institute of Technology (ETH) Zurich ++ * ++ * This module is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published ++ * by the Free Software Foundation; either version 2 of the License, ++ * or (at your option) any later version. ++ * ++ * This module 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 General Public License for more details. ++ * ++ * $Id: tpm_data.c 36 2005-10-26 20:31:19Z hstamer $ ++ */ ++ ++#include "tpm_emulator.h" ++#include "tpm_structures.h" ++#include "tpm_marshalling.h" ++#include "linux_module.h" ++ ++TPM_DATA tpmData; ++ ++BOOL tpm_get_physical_presence(void) ++{ ++ return (tpmData.stclear.flags.physicalPresence || TRUE); ++} ++ ++static inline void init_pcr_attr(int pcr, BOOL reset, BYTE rl, BYTE el) ++{ ++ int i; ++ tpmData.permanent.data.pcrAttrib[pcr].pcrReset = reset; ++ for (i = 0; i < TPM_NUM_LOCALITY; i++) { ++ tpmData.permanent.data.pcrAttrib[pcr].pcrResetLocal[i] = (rl & (1 << i)); ++ tpmData.permanent.data.pcrAttrib[pcr].pcrExtendLocal[i] = (el & (1 << i)); ++ } ++} ++ ++void tpm_init_data(void) ++{ ++ /* endorsement key */ ++ uint8_t ek_n[] = "\xa8\xdb\xa9\x42\xa8\xf3\xb8\x06\x85\x90\x76\x93\xad\xf7" ++ "\x74\xec\x3f\xd3\x3d\x9d\xe8\x2e\xff\x15\xed\x0e\xce\x5f\x93" ++ "\x92\xeb\xd1\x96\x2b\x72\x18\x81\x79\x12\x9d\x9c\x40\xd7\x1a" ++ "\x21\xda\x5f\x56\xe0\xc9\x48\x31\xdd\x96\xdc\xbb\x45\xc6\x8e" ++ "\xad\x58\x23\xcb\xbe\xbb\x13\x2d\x6b\x86\xc5\x57\xf5\xdd\x48" ++ "\xc1\x3d\xcd\x4d\xda\x81\xc4\x43\x17\xaa\x05\x40\x33\x62\x0a" ++ "\x59\xdb\x28\xcd\xb5\x08\x31\xbb\x06\xf5\xf7\x71\xae\x21\xa8" ++ "\xf2\x2f\x0e\x17\x80\x5d\x9c\xdf\xaa\xe9\x89\x09\x54\x65\x2b" ++ "\x46\xfb\x9d\xb2\x00\x70\x63\x0d\x9a\x6d\x3d\x5e\x11\x78\x65" ++ "\x90\xe6\x26\xee\x77\xbe\x08\xff\x07\x60\x5a\xcc\xf1\x0a\xbd" ++ "\x44\x92\x6b\xca\xb6\xce\x66\xf9\x93\x40\xae\xf3\x3e\x53\x02" ++ "\x3c\xa6\x81\xb3\xbe\xad\x6e\x6c\xa6\xf0\xeb\xdf\xe9\xa2\x83" ++ "\x36\x0e\x52\x0d\x64\x17\xd9\xff\xa1\x74\x7c\x2b\xbc\x6a\xcc" ++ "\xe5\x4e\xb4\x52\xd9\xec\x43\xbd\x26\x6a\x2b\x19\x19\x6e\x97" ++ "\xb8\x1d\x9f\x7b\xe7\x32\x2d\xdd\x7c\x51\xc8\xe4\xf3\x02\xd4" ++ "\x7c\x90\x44\xa0\x33\x72\x81\x75\xa9\x16\x27\x5c\x00\x1d\x07" ++ "\x81\xd4\xf7\xac\xcb\xfe\xd6\x60\x03\x6f\x7a\xcc\x00\xd1\xc4" ++ "\x85\x37"; ++ uint8_t ek_e[] = "\x01\x00\x01"; ++ uint8_t ek_p[] = "\xd7\xea\x61\x15\x8b\xa3\x71\xdf\xa8\x74\x77\xca\x88\x95" ++ "\xd0\x76\x17\x43\x2c\xf6\x23\x27\x44\xb9\x0e\x18\x35\x7e\xe4" ++ "\xc3\xcb\x13\x6e\xfc\x38\x02\x1e\x77\x26\x40\x9d\x17\xb2\x39" ++ "\x9c\x7f\x5f\x98\xe6\xf2\x55\x0c\x12\x05\x4c\xb3\x51\xae\x29" ++ "\xe7\xcd\xce\x41\x0b\x28\x4d\x97\x13\x4b\x60\xc8\xd8\x70\x81" ++ "\xf9\x1c\x12\x44\xdf\x53\x0a\x87\x9d\x33\x92\x4a\x34\x69\xf0" ++ "\x70\x5e\x1b\x5d\x65\xc7\x84\x90\xa2\x62\xdf\x83\x14\x10\x69" ++ "\xe2\xa7\x18\x43\xd7\x1f\x60\xc9\x03\x8f\xd6\xa4\xce\xb2\x9d" ++ "\x40\x37\x70\x17\x4c\xe3\x69\xd4\x59"; ++ uint8_t ek_q[] = "\xc8\x34\xd2\xd0\x7c\xfa\xdc\x68\xe2\x72\xd7\x92\xe2\x50" ++ "\x93\xfc\xbb\x72\x55\x4d\x6b\x7a\x0c\x0b\xcf\x87\x66\x1f\x81" ++ "\x71\xf3\x50\xcb\xaa\xe6\x43\x7e\xbe\x11\xc4\xec\x00\x53\xf4" ++ "\x78\x13\x2b\x59\x26\x4a\x9f\x91\x61\x8f\xa7\x07\x64\x11\x5a" ++ "\xf4\xaf\x9c\x9b\x5a\x5d\x69\x20\x17\x55\x74\xba\xd8\xe4\x59" ++ "\x39\x1a\x0a\x7b\x4a\x30\xf0\xc8\x7f\xd9\xaf\x72\xc5\xb6\x71" ++ "\xd1\xc0\x8b\x5b\xa2\x2e\xa7\x15\xca\x50\x75\x10\x48\x9c\x2b" ++ "\x18\xb9\x67\x8f\x5d\x64\xc3\x28\x9f\x2f\x16\x2f\x08\xda\x47" ++ "\xec\x86\x43\x0c\x80\x99\x07\x34\x0f"; ++ int i; ++ /* reset all data to NULL, FALSE or 0 */ ++ memset(&tpmData, 0, sizeof(tpmData)); ++ tpmData.permanent.data.tag = TPM_TAG_PERMANENT_DATA; ++ /* set permanent flags */ ++ tpmData.permanent.flags.tag = TPM_TAG_PERMANENT_FLAGS; ++ tpmData.permanent.flags.disable = FALSE; ++ tpmData.permanent.flags.deactivated = FALSE; ++ tpmData.permanent.flags.ownership = TRUE; ++ tpmData.permanent.flags.readPubek = TRUE; ++ tpmData.permanent.flags.allowMaintenance = TRUE; ++ tpmData.permanent.flags.enableRevokeEK = TRUE; ++ /* set TPM vision */ ++ tpmData.permanent.data.version.major = 1; ++ tpmData.permanent.data.version.minor = 2; ++ tpmData.permanent.data.version.revMajor = VERSION_MAJOR; ++ tpmData.permanent.data.version.revMinor = VERSION_MINOR; ++ /* setup PCR attributes */ ++ for (i = 0; i < min(16, TPM_NUM_PCR); i++) { ++ init_pcr_attr(i, FALSE, 0x00, 0x1f); ++ } ++ if (TPM_NUM_PCR >= 24) { ++ init_pcr_attr(16, TRUE, 0x1f, 0x1f); ++ init_pcr_attr(17, TRUE, 0x10, 0x1c); ++ init_pcr_attr(18, TRUE, 0x10, 0x1c); ++ init_pcr_attr(19, TRUE, 0x10, 0x0c); ++ init_pcr_attr(20, TRUE, 0x14, 0x0e); ++ init_pcr_attr(21, TRUE, 0x04, 0x04); ++ init_pcr_attr(22, TRUE, 0x04, 0x04); ++ init_pcr_attr(23, TRUE, 0x1f, 0x1f); ++ } ++ for (i = 24; i < TPM_NUM_PCR; i++) { ++ init_pcr_attr(i, TRUE, 0x00, 0x00); ++ } ++ /* set tick type */ ++ tpmData.permanent.data.tickType = TICK_INC; ++#ifdef TPM_GENERATE_EK ++ /* generate a new endorsement key */ ++ rsa_generate_key(&tpmData.permanent.data.endorsementKey, 2048); ++#else ++ /* setup endorsement key */ ++ rsa_import_key(&tpmData.permanent.data.endorsementKey, ++ RSA_MSB_FIRST, ek_n, 256, ek_e, 3, ek_p, ek_q); ++#endif ++#ifdef TPM_GENERATE_SEED_DAA ++ /* generate the DAA seed (cf. [TPM_Part2], v1.2 rev 85, Section 7.4) */ ++ tpm_get_random_bytes(tpmData.permanent.data.tpmDAASeed.digest, ++ sizeof(tpmData.permanent.data.tpmDAASeed.digest)); ++#else ++ /* FIXME: setup DAA seed */ ++ memcpy(tpmData.permanent.data.tpmDAASeed.digest, ++ "\x77\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" ++ "\x00\x00\x00\x77", 20); ++#endif ++ ++ memcpy(tpmData.permanent.data.ekReset.nonce, "\xde\xad\xbe\xef", 4); ++} ++ ++void tpm_release_data(void) ++{ ++ int i; ++ /* release the EK, SRK as well as all other rsa keys */ ++ if (tpmData.permanent.data.endorsementKey.size > 0) ++ rsa_release_private_key(&tpmData.permanent.data.endorsementKey); ++ if (tpmData.permanent.data.srk.valid) ++ rsa_release_private_key(&tpmData.permanent.data.srk.key); ++ for (i = 0; i < TPM_MAX_KEYS; i++) ++ if (tpmData.permanent.data.keys[i].valid) ++ rsa_release_private_key(&tpmData.permanent.data.keys[i].key); ++} ++ ++#ifdef TPM_STORE_TO_FILE ++ ++#include <linux/fs.h> ++#include <linux/unistd.h> ++#include <asm/uaccess.h> ++ ++#define TPM_STORAGE_FILE "/var/tpm/tpm_emulator-1.2." STR(VERSION_MAJOR) "." STR(VERSION_MINOR) ++ ++static int write_to_file(uint8_t *data, size_t data_length) ++{ ++ int res; ++ struct file *fp; ++ mm_segment_t old_fs = get_fs(); ++ fp = filp_open(TPM_STORAGE_FILE, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR); ++ if (IS_ERR(fp)) return -1; ++ set_fs(get_ds()); ++ res = fp->f_op->write(fp, data, data_length, &fp->f_pos); ++ set_fs(old_fs); ++ filp_close(fp, NULL); ++ return (res == data_length) ? 0 : -1; ++} ++ ++static int read_from_file(uint8_t **data, size_t *data_length) ++{ ++ int res; ++ struct file *fp; ++ mm_segment_t old_fs = get_fs(); ++ fp = filp_open(TPM_STORAGE_FILE, O_RDONLY, 0); ++ if (IS_ERR(fp)) return -1; ++ *data_length = (size_t)fp->f_dentry->d_inode->i_size; ++ /* *data_length = i_size_read(fp->f_dentry->d_inode); */ ++ *data = tpm_malloc(*data_length); ++ if (*data == NULL) { ++ filp_close(fp, NULL); ++ return -1; ++ } ++ set_fs(get_ds()); ++ res = fp->f_op->read(fp, *data, *data_length, &fp->f_pos); ++ set_fs(old_fs); ++ filp_close(fp, NULL); ++ if (res != *data_length) { ++ tpm_free(*data); ++ return -1; ++ } ++ return 0; ++} ++ ++#else ++ ++static int write_to_file(uint8_t *data, size_t data_length) ++{ ++ info("TPM_STORE_TO_FILE disabled, no data written"); ++ return 0; ++} ++ ++static int read_from_file(uint8_t **data, size_t *data_length) ++{ ++ info("TPM_STORE_TO_FILE disabled, no data read"); ++ return 0; ++} ++ ++#endif /* TPM_STORE_TO_FILE */ ++ ++int tpm_store_permanent_data(void) ++{ ++ uint8_t *buf, *ptr; ++ UINT32 buf_length, len; ++ ++ /* marshal data */ ++ buf_length = len = 4 + sizeof_TPM_STCLEAR_FLAGS(tpmData.stclear.flags) ++ + sizeof_TPM_PERMANENT_FLAGS(tpmData.permanent.flags) ++ + sizeof_TPM_STANY_FLAGS(tpmData.stany.flags) + 2 ++ + sizeof_TPM_STCLEAR_DATA(tpmData.stclear.data) ++ + sizeof_TPM_PERMANENT_DATA(tpmData.permanent.data) ++ + sizeof_TPM_STANY_DATA(tpmData.stany.data); ++ buf = ptr = tpm_malloc(buf_length); ++ if (buf == NULL ++ || tpm_marshal_TPM_VERSION(&ptr, &len, &tpmData.permanent.data.version) ++ || tpm_marshal_TPM_STCLEAR_FLAGS(&ptr, &len, &tpmData.stclear.flags) ++ || tpm_marshal_TPM_PERMANENT_FLAGS(&ptr, &len, &tpmData.permanent.flags) ++ || tpm_marshal_TPM_STANY_FLAGS(&ptr, &len, &tpmData.stany.flags) ++ || tpm_marshal_BOOL(&ptr, &len, tpmData.permanent.flags.selfTestSucceeded) ++ || tpm_marshal_BOOL(&ptr, &len, tpmData.permanent.flags.owned) ++ || tpm_marshal_TPM_STCLEAR_DATA(&ptr, &len, &tpmData.stclear.data) ++ || tpm_marshal_TPM_PERMANENT_DATA(&ptr, &len, &tpmData.permanent.data) ++ || tpm_marshal_TPM_STANY_DATA(&ptr, &len, &tpmData.stany.data)) { ++ tpm_free(buf); ++ return -1; ++ } ++ ++ if (write_to_file(buf, buf_length - len)) { ++ tpm_free(buf); ++ return -1; ++ } ++ tpm_free(buf); ++ return 0; ++} ++ ++int tpm_restore_permanent_data(void) ++{ ++ uint8_t *buf, *ptr; ++ size_t buf_length; ++ UINT32 len; ++ TPM_VERSION ver; ++ ++ /* read data */ ++ if (read_from_file(&buf, &buf_length)) return -1; ++ ptr = buf; ++ len = (uint32_t) buf_length; ++ /* unmarshal data */ ++ if (tpm_unmarshal_TPM_VERSION(&ptr, &len, &ver) ++ || memcmp(&ver, &tpmData.permanent.data.version, sizeof(TPM_VERSION)) ++ || tpm_unmarshal_TPM_STCLEAR_FLAGS(&ptr, &len, &tpmData.stclear.flags) ++ || tpm_unmarshal_TPM_PERMANENT_FLAGS(&ptr, &len, &tpmData.permanent.flags) ++ || tpm_unmarshal_TPM_STANY_FLAGS(&ptr, &len, &tpmData.stany.flags) ++ || tpm_unmarshal_BOOL(&ptr, &len, &tpmData.permanent.flags.selfTestSucceeded) ++ || tpm_unmarshal_BOOL(&ptr, &len, &tpmData.permanent.flags.owned) ++ || tpm_unmarshal_TPM_STCLEAR_DATA(&ptr, &len, &tpmData.stclear.data) ++ || tpm_unmarshal_TPM_PERMANENT_DATA(&ptr, &len, &tpmData.permanent.data) ++ || tpm_unmarshal_TPM_STANY_DATA(&ptr, &len, &tpmData.stany.data)) { ++ tpm_free(buf); ++ return -1; ++ } ++ ++ tpm_free(buf); ++ return 0; ++} ++ ++int tpm_erase_permanent_data(void) ++{ ++ int res = write_to_file("", 0); ++ return res; ++} ++ +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_deprecated.c tpm_emulator/tpm/tpm_deprecated.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_deprecated.c 2006-08-29 15:07:21.622298456 -0700 ++++ tpm_emulator/tpm/tpm_deprecated.c 2006-08-29 15:26:17.122676160 -0700 +@@ -1,6 +1,7 @@ + /* Software-Based Trusted Platform Module (TPM) Emulator for Linux + * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, + * Swiss Federal Institute of Technology (ETH) Zurich ++ * Copyright (C) 2005 INTEL Corp + * + * This module is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published +@@ -50,7 +51,7 @@ TPM_RESULT TPM_SaveKeyContext(TPM_KEY_HA + BYTE *ptr; + UINT32 len; + info("TPM_SaveKeyContext()"); +- res = TPM_SaveContext(keyHandle, TPM_RT_KEY, "SaveKeyContext..", ++ res = TPM_SaveContext(keyHandle, TPM_RT_KEY, (BYTE*)"SaveKeyContext..", + keyContextSize, &contextBlob); + if (res != TPM_SUCCESS) return res; + len = *keyContextSize; +@@ -82,7 +83,7 @@ TPM_RESULT TPM_SaveAuthContext(TPM_AUTHH + BYTE *ptr; + UINT32 len; + info("TPM_SaveAuthContext()"); +- res = TPM_SaveContext(authHandle, TPM_RT_KEY, "SaveAuthContext.", ++ res = TPM_SaveContext(authHandle, TPM_RT_KEY, (BYTE*)"SaveAuthContext.", + authContextSize, &contextBlob); + if (res != TPM_SUCCESS) return res; + len = *authContextSize; +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_emulator.h tpm_emulator/tpm/tpm_emulator.h +--- tpm_emulator-0.3-x86_64/tpm/tpm_emulator.h 2006-08-29 15:07:21.648294504 -0700 ++++ tpm_emulator/tpm/tpm_emulator.h 2006-08-29 15:26:17.122676160 -0700 +@@ -1,5 +1,6 @@ + /* Software-Based Trusted Platform Module (TPM) Emulator for Linux + * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, ++ * Copyright (C) 2005 INTEL Corp + * + * This module is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published +@@ -22,7 +23,8 @@ + /* TPM configuration */ + #define TPM_STORE_TO_FILE 1 + #undef TPM_STRONG_PERSISTENCE +-#undef TPM_GENERATE_EK ++//#undef TPM_GENERATE_EK ++#define TPM_GENERATE_EK + #undef TPM_GENERATE_SEED_DAA + + #define TPM_MANUFACTURER 0x4554485A /* 'ETHZ' */ +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_integrity.c tpm_emulator/tpm/tpm_integrity.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_integrity.c 2006-08-29 15:07:21.645294960 -0700 ++++ tpm_emulator/tpm/tpm_integrity.c 2006-08-29 15:26:17.123676008 -0700 +@@ -1,6 +1,7 @@ + /* Software-Based Trusted Platform Module (TPM) Emulator for Linux + * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, + * Swiss Federal Institute of Technology (ETH) Zurich ++ * Copyright (C) 2005 INTEL Corp + * + * This module is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published +@@ -194,4 +195,3 @@ TPM_RESULT tpm_verify_pcr(TPM_KEY_DATA * + } + return TPM_SUCCESS; + } +- +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_structures.h tpm_emulator/tpm/tpm_structures.h +--- tpm_emulator-0.3-x86_64/tpm/tpm_structures.h 2006-08-29 15:08:20.545340792 -0700 ++++ tpm_emulator/tpm/tpm_structures.h 2006-08-29 15:26:17.125675704 -0700 +@@ -1,6 +1,7 @@ + /* Software-Based Trusted Platform Module (TPM) Emulator for Linux + * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, + * Swiss Federal Institute of Technology (ETH) Zurich ++ * Copyright (C) 2005 INTEL Corp + * + * This module is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published +@@ -18,7 +19,7 @@ + #ifndef _TPM_STRUCTURES_H_ + #define _TPM_STRUCTURES_H_ + +-#include <linux/types.h> ++//#include <linux/types.h> + #include "crypto/rsa.h" + + /* +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_testing.c tpm_emulator/tpm/tpm_testing.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_testing.c 2006-08-29 15:07:21.646294808 -0700 ++++ tpm_emulator/tpm/tpm_testing.c 2006-08-29 15:26:17.127675400 -0700 +@@ -1,6 +1,7 @@ + /* Software-Based Trusted Platform Module (TPM) Emulator for Linux + * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, + * Swiss Federal Institute of Technology (ETH) Zurich ++ * Copyright (C) 2005 INTEL Corp + * + * This module is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published +@@ -95,24 +96,24 @@ static int tpm_test_sha1(void) + struct { + uint8_t *data; uint32_t repetitions; uint8_t *digest; + } test_cases[] = {{ +- "abc", 1, +- "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D" ++ (uint8_t*)"abc", 1, ++ (uint8_t*)"\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D" + }, { +- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1, +- "\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1" ++ (uint8_t*)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1, ++ (uint8_t*)"\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1" + }, { +- "a", 1000000, +- "\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F" ++ (uint8_t*)"a", 1000000, ++ (uint8_t*)"\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F" + }, { +- "0123456701234567012345670123456701234567012345670123456701234567", 10, +- "\xDE\xA3\x56\xA2\xCD\xDD\x90\xC7\xA7\xEC\xED\xC5\xEB\xB5\x63\x93\x4F\x46\x04\x52" ++ (uint8_t*)"0123456701234567012345670123456701234567012345670123456701234567", 10, ++ (uint8_t*)"\xDE\xA3\x56\xA2\xCD\xDD\x90\xC7\xA7\xEC\xED\xC5\xEB\xB5\x63\x93\x4F\x46\x04\x52" + }}; + + debug("tpm_test_sha1()"); + for (i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) { + sha1_init(&ctx); + for (j = 0; j < test_cases[i].repetitions; j++) +- sha1_update(&ctx, test_cases[i].data, strlen(test_cases[i].data)); ++ sha1_update(&ctx, test_cases[i].data, strlen((char*)test_cases[i].data)); + sha1_final(&ctx, digest); + if (memcmp(digest, test_cases[i].digest, SHA1_DIGEST_LENGTH) != 0) return -1; + } +@@ -128,41 +129,41 @@ static int tpm_test_hmac(void) + struct { + uint8_t *key, key_len, *data, data_len, *digest; + } test_cases[] = {{ +- "\x0b", 20, "Hi There", 8, +- "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00" ++ (uint8_t*)"\x0b", 20, (uint8_t*)"Hi There", 8, ++ (uint8_t*)"\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00" + }, { +- "Jefe", 4, "what do ya want for nothing?", 28, +- "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79" ++ (uint8_t*)"Jefe", 4, (uint8_t*)"what do ya want for nothing?", 28, ++ (uint8_t*)"\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79" + }, { +- "\xaa", 20, "\xdd", 50, +- "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3" ++ (uint8_t*)"\xaa", 20, (uint8_t*)"\xdd", 50, ++ (uint8_t*)"\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3" + }, { +- "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" +- "\x15\x16\x17\x18\x19", 25, "\xcd", 50, +- "\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda" ++ (uint8_t*)"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" ++ "\x15\x16\x17\x18\x19", 25, (uint8_t*)"\xcd", 50, ++ (uint8_t*)"\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda" + }, { +- "\x0c", 20, "Test With Truncation", 20, +- "\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04" ++ (uint8_t*)"\x0c", 20, (uint8_t*)"Test With Truncation", 20, ++ (uint8_t*)"\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04" + }, { +- "\xaa", 80, "Test Using Larger Than Block-Size Key - Hash Key First", 54, +- "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12" ++ (uint8_t*)"\xaa", 80, (uint8_t*)"Test Using Larger Than Block-Size Key - Hash Key First", 54, ++ (uint8_t*)"\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12" + }, { +- "\xaa", 80, +- "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73, +- "\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91" ++ (uint8_t*)"\xaa", 80, ++ (uint8_t*)"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73, ++ (uint8_t*)"\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91" + }}; + + debug("tpm_test_hmac()"); + for (i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) { +- if (strlen(test_cases[i].key) < test_cases[i].key_len) { ++ if (strlen((char*)test_cases[i].key) < test_cases[i].key_len) { + uint8_t key[test_cases[i].key_len]; + memset(key, test_cases[i].key[0], test_cases[i].key_len); + hmac_init(&ctx, key, test_cases[i].key_len); + } else { + hmac_init(&ctx, test_cases[i].key, test_cases[i].key_len); + } +- for (j = 0; j < test_cases[i].data_len; j += strlen(test_cases[i].data)) { +- hmac_update(&ctx, test_cases[i].data, strlen(test_cases[i].data)); ++ for (j = 0; j < test_cases[i].data_len; j += strlen((char*)test_cases[i].data)) { ++ hmac_update(&ctx, test_cases[i].data, strlen((char*)test_cases[i].data)); + } + hmac_final(&ctx, digest); + if (memcmp(digest, test_cases[i].digest, SHA1_DIGEST_LENGTH) != 0) return -1; +@@ -173,9 +174,9 @@ static int tpm_test_hmac(void) + static int tpm_test_rsa_EK(void) + { + int res = 0; +- char *data = "RSA PKCS #1 v1.5 Test-String"; ++ uint8_t *data = (uint8_t*)"RSA PKCS #1 v1.5 Test-String"; + uint8_t buf[256]; +- size_t buf_len, data_len = strlen(data); ++ size_t buf_len, data_len = strlen((char*)data); + rsa_private_key_t priv_key; + rsa_public_key_t pub_key; + +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_ticks.c tpm_emulator/tpm/tpm_ticks.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_ticks.c 2006-08-29 15:07:21.646294808 -0700 ++++ tpm_emulator/tpm/tpm_ticks.c 2006-08-29 15:26:17.128675248 -0700 +@@ -1,6 +1,7 @@ + /* Software-Based Trusted Platform Module (TPM) Emulator for Linux + * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, + * Swiss Federal Institute of Technology (ETH) Zurich ++ * Copyright (C) 2005 INTEL Corp + * + * This module is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published +@@ -37,9 +38,7 @@ TPM_RESULT TPM_SetTickType(TPM_TICKTYPE + TPM_RESULT TPM_GetTicks(TPM_CURRENT_TICKS *currentTime) + { + info("TPM_GetTicks()"); +- memcpy(currentTime, &tpmData.stany.data.currentTicks, +- sizeof(TPM_CURRENT_TICKS)); +- return TPM_SUCCESS; ++ return TPM_DISABLED_CMD; + } + + TPM_RESULT TPM_TickStampBlob(TPM_KEY_HANDLE keyHandle, TPM_NONCE *antiReplay, +@@ -47,61 +46,12 @@ TPM_RESULT TPM_TickStampBlob(TPM_KEY_HAN + TPM_CURRENT_TICKS *currentTicks, + UINT32 *sigSize, BYTE **sig) + { +- TPM_RESULT res; +- TPM_KEY_DATA *key; +- BYTE *info, *p; +- UINT32 info_length, length; + info("TPM_TickStampBlob()"); +- /* get key */ +- key = tpm_get_key(keyHandle); +- if (key == NULL) return TPM_INVALID_KEYHANDLE; +- /* verify authorization */ +- res = tpm_verify_auth(auth1, key->usageAuth, keyHandle); +- if (res != TPM_SUCCESS) return res; +- if (key->keyUsage != TPM_KEY_SIGNING && key->keyUsage != TPM_KEY_LEGACY +- && key->keyUsage != TPM_KEY_IDENTITY) return TPM_INVALID_KEYUSAGE; +- /* get current ticks */ +- TPM_GetTicks(currentTicks); +- /* sign data using signature scheme PKCS1_SHA1 and TPM_SIGN_INFO container */ +- *sigSize = key->key.size >> 3; +- *sig = tpm_malloc(*sigSize); +- if (*sig == NULL) return TPM_FAIL; +- /* setup TPM_SIGN_INFO structure */ +- info_length = 30 + sizeof(TPM_DIGEST) + sizeof_TPM_CURRENT_TICKS(currentTicks); +- info = tpm_malloc(info_length); +- if (info == NULL) { +- tpm_free(*sig); +- return TPM_FAIL; +- } +- memcpy(&info[0], "\x05\x00TSTP", 6); +- memcpy(&info[6], antiReplay->nonce, 20); +- *(UINT32*)&info[26] = cpu_to_be32(20 +- + sizeof_TPM_CURRENT_TICKS(currentTicks)); +- memcpy(&info[30], digestToStamp->digest, sizeof(TPM_DIGEST)); +- p = &info[30 + sizeof(TPM_DIGEST)]; +- length = sizeof_TPM_CURRENT_TICKS(currentTicks); +- if (tpm_marshal_TPM_CURRENT_TICKS(&p, &length, currentTicks) +- || rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1, info, info_length, *sig)) { +- tpm_free(*sig); +- tpm_free(info); +- return TPM_FAIL; +- } +- return TPM_SUCCESS; ++ return TPM_DISABLED_CMD; + } + + void tpm_update_ticks(void) + { +- if (tpmData.stany.data.currentTicks.tag == 0) { +- tpmData.stany.data.currentTicks.tag = TPM_TAG_CURRENT_TICKS; +- tpmData.stany.data.currentTicks.currentTicks += tpm_get_ticks(); +- tpmData.stany.data.currentTicks.tickType = tpmData.permanent.data.tickType; +- tpm_get_random_bytes(tpmData.stany.data.currentTicks.tickNonce.nonce, +- sizeof(TPM_NONCE)); +- tpmData.stany.data.currentTicks.tickRate = 1; +- tpmData.stany.data.currentTicks.tickSecurity = TICK_SEC_NO_CHECK; +- } else { +- tpmData.stany.data.currentTicks.currentTicks += tpm_get_ticks(); +- } + } + + +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_transport.c tpm_emulator/tpm/tpm_transport.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_transport.c 2006-08-29 15:07:21.647294656 -0700 ++++ tpm_emulator/tpm/tpm_transport.c 2006-08-29 15:26:17.129675096 -0700 +@@ -59,7 +59,7 @@ static int decrypt_transport_auth(TPM_KE + static void transport_log_in(TPM_COMMAND_CODE ordinal, BYTE parameters[20], + BYTE pubKeyHash[20], TPM_DIGEST *transDigest) + { +- UINT32 tag = cpu_to_be32(TPM_TAG_TRANSPORT_LOG_IN); ++ UINT32 tag = CPU_TO_BE32(TPM_TAG_TRANSPORT_LOG_IN); + BYTE *ptr, buf[sizeof_TPM_TRANSPORT_LOG_IN(x)]; + UINT32 len = sizeof(buf); + sha1_ctx_t sha1; +@@ -76,7 +76,7 @@ static void transport_log_in(TPM_COMMAND + static void transport_log_out(TPM_CURRENT_TICKS *currentTicks, BYTE parameters[20], + TPM_MODIFIER_INDICATOR locality, TPM_DIGEST *transDigest) + { +- UINT32 tag = cpu_to_be32(TPM_TAG_TRANSPORT_LOG_OUT); ++ UINT32 tag = CPU_TO_BE32(TPM_TAG_TRANSPORT_LOG_OUT); + BYTE *ptr, buf[sizeof_TPM_TRANSPORT_LOG_OUT(x)]; + UINT32 len = sizeof(buf); + sha1_ctx_t sha1; +@@ -191,7 +191,7 @@ static void decrypt_wrapped_command(BYTE + sha1_update(&sha1, auth->nonceOdd.nonce, sizeof(auth->nonceOdd.nonce)); + sha1_update(&sha1, "in", 2); + sha1_update(&sha1, secret, sizeof(TPM_SECRET)); +- j = cpu_to_be32(i); ++ j = CPU_TO_BE32(i); + sha1_update(&sha1, (BYTE*)&j, 4); + sha1_final(&sha1, mask); + for (j = 0; j < sizeof(mask) && buf_len > 0; j++) { +@@ -213,7 +213,7 @@ static void encrypt_wrapped_command(BYTE + sha1_update(&sha1, auth->nonceOdd.nonce, sizeof(auth->nonceOdd.nonce)); + sha1_update(&sha1, "out", 3); + sha1_update(&sha1, secret, sizeof(TPM_SECRET)); +- j = cpu_to_be32(i); ++ j = CPU_TO_BE32(i); + sha1_update(&sha1, (BYTE*)&j, 4); + sha1_final(&sha1, mask); + for (j = 0; j < sizeof(mask) && buf_len > 0; j++) { +@@ -253,9 +253,9 @@ TPM_RESULT TPM_ExecuteTransport(UINT32 i + /* verify authorization */ + tpm_compute_in_param_digest(&req); + sha1_init(&sha1); +- res = cpu_to_be32(TPM_ORD_ExecuteTransport); ++ res = CPU_TO_BE32(TPM_ORD_ExecuteTransport); + sha1_update(&sha1, (BYTE*)&res, 4); +- res = cpu_to_be32(inWrappedCmdSize); ++ res = CPU_TO_BE32(inWrappedCmdSize); + sha1_update(&sha1, (BYTE*)&res, 4); + sha1_update(&sha1, req.auth1.digest, sizeof(req.auth1.digest)); + sha1_final(&sha1, auth1->digest); +@@ -357,7 +357,7 @@ TPM_RESULT TPM_ReleaseTransportSigned(TP + /* setup a TPM_SIGN_INFO structure */ + memcpy(&buf[0], "\x05\x00TRAN", 6); + memcpy(&buf[6], antiReplay->nonce, 20); +- *(UINT32*)&buf[26] = cpu_to_be32(20); ++ *(UINT32*)&buf[26] = CPU_TO_BE32(20); + memcpy(&buf[30], session->transInternal.transDigest.digest, 20); + /* sign info structure */ + res = tpm_sign(key, auth1, TRUE, buf, sizeof(buf), signature, signSize); +diff -uprN tpm_emulator-0.3-x86_64/tpm_version.h tpm_emulator/tpm_version.h +--- tpm_emulator-0.3-x86_64/tpm_version.h 2006-08-29 15:07:21.649294352 -0700 ++++ tpm_emulator/tpm_version.h 1969-12-31 16:00:00.000000000 -0800 +@@ -1,6 +0,0 @@ +-#ifndef _TPM_VERSION_H_ +-#define _TPM_VERSION_H_ +-#define VERSION_MAJOR 0 +-#define VERSION_MINOR 3 +-#define VERSION_BUILD 1136893683 +-#endif /* _TPM_VERSION_H_ */ +diff -uprN tpm_emulator-0.3-x86_64/tpmd.c tpm_emulator/tpmd.c +--- tpm_emulator-0.3-x86_64/tpmd.c 1969-12-31 16:00:00.000000000 -0800 ++++ tpm_emulator/tpmd.c 2006-08-29 15:26:17.130674944 -0700 +@@ -0,0 +1,141 @@ ++/* Software-Based Trusted Platform Module (TPM) Emulator for Linux ++ * Copyright (C) 2005 INTEL Corp ++ * ++ * This module is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published ++ * by the Free Software Foundation; either version 2 of the License, ++ * or (at your option) any later version. ++ * ++ * This module 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 General Public License for more details. ++ * ++ */ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <unistd.h> ++#include <string.h> ++#include <sys/types.h> ++#include <sys/stat.h> ++#include <fcntl.h> ++#include <sys/time.h> ++ ++#include "tpm_emulator.h" ++ ++#define TPM_RX_FNAME "/tmp/tpm_in.fifo" ++#define TPM_TX_FNAME "/tmp/tpm_out.fifo" ++ ++#define BUFFER_SIZE 2048 ++ ++static int devurandom=0; ++ ++void get_random_bytes(void *buf, int nbytes) { ++ ++ if (devurandom == 0) { ++ devurandom = open("/dev/urandom", O_RDONLY); ++ } ++ ++ if (read(devurandom, buf, nbytes) != nbytes) { ++ printf("Can't get random number.\n"); ++ exit(-1); ++ } ++} ++ ++uint64_t tpm_get_ticks(void) ++{ ++ //struct timeval tv; ++ //int gettimeofday(&tv, struct timezone *tz); ++ return 0; ++} ++ ++int main(int argc, char **argv) ++{ ++ uint8_t in[BUFFER_SIZE], *out; ++ uint32_t out_size; ++ int in_size, written; ++ int i; ++ ++ int tpm_tx_fh=-1, tpm_rx_fh=-1; ++ if (argc < 2) { ++ printf("Usage: tpmd clear|save|deactivated\n" ); ++ return -1; ++ } ++ ++ /* initialize TPM emulator */ ++ if (!strcmp(argv[1], "clear")) { ++ printf("Initializing tpm: %s\n", argv[1]); ++ tpm_emulator_init(1); ++ } else if (!strcmp(argv[1], "save")) { ++ printf("Initializing tpm: %s\n", argv[1]); ++ tpm_emulator_init(2); ++ } else if (!strcmp(argv[1], "deactivated")) { ++ printf("Initializing tpm: %s\n", argv[1]); ++ tpm_emulator_init(3); ++ } else { ++ printf("invalid startup mode '%s'; must be 'clear', " ++ "'save' (default) or 'deactivated", argv[1]); ++ return -1; ++ } ++ ++ while (1) { ++abort_command: ++ if (tpm_rx_fh < 0) { ++ tpm_rx_fh = open(TPM_RX_FNAME, O_RDONLY); + } -+ - tpmData.permanent.data.pcrAttrib[i].pcrReset = TRUE; - } - /* set tick type */ ++ ++ if (tpm_rx_fh < 0) { ++ printf("ERROR: failed to open devices to listen to guest.\n"); ++ return -1; ++ } ++ ++ if (tpm_tx_fh < 0) { ++ tpm_tx_fh = open(TPM_TX_FNAME, O_WRONLY); ++ } ++ ++ if (tpm_tx_fh < 0) { ++ printf("ERROR: failed to open devices to respond to guest.\n"); ++ return -1; ++ } ++ ++ in_size = read(tpm_rx_fh, in, BUFFER_SIZE); ++ if (in_size < 6) { // Magic size of minium TPM command ++ printf("Recv[%d] to small: 0x", in_size); ++ if (in_size <= 0) { ++ close(tpm_rx_fh); ++ tpm_rx_fh = -1; ++ goto abort_command; ++ } ++ } else { ++ printf("Recv[%d]: 0x", in_size); ++ for (i=0; i< in_size; i++) ++ printf("%x ", in[i]); ++ printf("\n"); ++ } ++ ++ ++ if (tpm_handle_command(in, in_size, &out, &out_size) != 0) { ++ printf("ERROR: Handler Failed.\n"); ++ } ++ ++ written = write(tpm_tx_fh, out, out_size); ++ ++ if (written != out_size ) { ++ printf("ERROR: Part of response not written %d/%d.\nAttempt: ", written, out_size); ++ } else { ++ printf("Sent[%Zu]: ", out_size); ++ } ++ for (i=0; i< out_size; i++) ++ printf("%x ", out[i]); ++ printf("\n"); ++ tpm_free(out); ++ ++ } // loop ++ ++ tpm_emulator_shutdown(); ++ ++ close(tpm_tx_fh); ++ close(tpm_rx_fh); ++ ++} diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm/vtpm.patch --- a/tools/vtpm/vtpm.patch Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm/vtpm.patch Wed Jun 28 07:52:21 2006 -0600 @@ -1,13 +1,13 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ -diff -uprN orig/tpm_emulator-0.3-x86_64/AUTHORS vtpm/AUTHORS ---- orig/tpm_emulator-0.3-x86_64/AUTHORS 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/AUTHORS 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/AUTHORS vtpm/AUTHORS +--- tpm_emulator-0.3-x86_64/AUTHORS 2006-08-29 15:07:21.618299064 -0700 ++++ vtpm/AUTHORS 2006-08-29 15:12:07.184886344 -0700 @@ -1,2 +1,3 @@ Mario Strasser <mast@xxxxxxx> Heiko Stamer <stamer@xxxxxxxx> [DAA] +INTEL Corp <> [VTPM Extensions] -diff -uprN orig/tpm_emulator-0.3-x86_64/ChangeLog vtpm/ChangeLog ---- orig/tpm_emulator-0.3-x86_64/ChangeLog 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/ChangeLog 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/ChangeLog vtpm/ChangeLog +--- tpm_emulator-0.3-x86_64/ChangeLog 2006-08-29 15:07:21.618299064 -0700 ++++ vtpm/ChangeLog 2006-08-29 15:12:07.185886192 -0700 @@ -1,3 +1,7 @@ +2005-08-16 Intel Corp + * Moved module out of kernel to run as a ring 3 app @@ -16,9 +16,117 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ 2005-12-24 Mario Strasser <mast@xxxxxxx> * tpm_transport.c, tpm_marshalling.c, tpm_structures.h: Transport session functionality added -diff -uprN orig/tpm_emulator-0.3-x86_64/crypto/gmp_kernel_wrapper.c vtpm/crypto/gmp_kernel_wrapper.c ---- orig/tpm_emulator-0.3-x86_64/crypto/gmp_kernel_wrapper.c 2006-05-30 12:28:02.000000000 -0700 -+++ vtpm/crypto/gmp_kernel_wrapper.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/Makefile vtpm/Makefile +--- tpm_emulator-0.3-x86_64/Makefile 2006-08-29 15:08:20.532342768 -0700 ++++ vtpm/Makefile 2006-08-29 15:13:53.023796384 -0700 +@@ -1,22 +1,31 @@ + # Software-Based Trusted Platform Module (TPM) Emulator for Linux + # Copyright (C) 2004 Mario Strasser <mast@xxxxxxx> ++# Copyright (C) 2006 INTEL Corp. + # + # $Id: Makefile 69 2005-12-13 12:55:52Z mast $ + +-# kernel settings +-KERNEL_RELEASE := $(shell uname -r) +-KERNEL_BUILD := /lib/modules/$(KERNEL_RELEASE)/build +-MOD_SUBDIR := misc + COMPILE_ARCH ?= $(shell uname -m | sed -e s/i.86/x86_32/) + + # module settings +-MODULE_NAME := tpm_emulator ++BIN := vtpmd + VERSION_MAJOR := 0 + VERSION_MINOR := 3 + VERSION_BUILD := $(shell date +"%s") + +-# enable/disable DEBUG messages +-EXTRA_CFLAGS += -Wall -DDEBUG -g ++# Installation program and options ++INSTALL = install ++INSTALL_PROG = $(INSTALL) -m0755 ++INSTALL_DIR = $(INSTALL) -d -m0755 ++ ++# Xen tools installation directory ++TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin ++ ++CC := gcc ++CFLAGS += -g -Wall $(INCLUDE) -DDEBUG ++CFLAGS += -I. -Itpm -I../../vtpm_manager/manager ++ ++# Is the simulator running in it's own vm? ++#CFLAGS += -DVTPM_MULTI_VM + + ifeq ($(COMPILE_ARCH),x86_64) + LIBDIR = lib64 +@@ -34,38 +43,31 @@ DIRS := . crypto tpm + SRCS := $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.c)) + OBJS := $(patsubst %.c, %.o, $(SRCS)) + SRCS += $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.h)) +-DISTSRC := ./README ./AUTHORS ./ChangeLog ./Makefile $(SRCS) +-DISTDIR := tpm_emulator-$(VERSION_MAJOR).$(VERSION_MINOR) + +-obj-m := $(MODULE_NAME).o +-$(MODULE_NAME)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a ++obj-m := $(BIN) ++$(BIN)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a + + EXTRA_CFLAGS += -I$(src) -I$(src)/crypto -I$(src)/tpm + + # do not print "Entering directory ..." + MAKEFLAGS += --no-print-directory + +-all: $(src)/crypto/gmp.h $(src)/crypto/libgmp.a version +- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules ++all: $(BIN) ++ ++$(BIN): $(src)/crypto/gmp.h $(src)/crypto/libgmp.a version $(SRCS) $(OBJS) ++ $(CC) $(CFLAGS) $(OBJS) $(src)/crypto/libgmp.a -o $(BIN) ++ ++%.o: %.c ++ $(CC) $(CFLAGS) -c $< -o $@ + +-install: +- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules_install +- test -d /var/tpm || mkdir /var/tpm +- test -c /dev/tpm || mknod /dev/tpm c 10 224 +- chmod 666 /dev/tpm +- depmod -a ++install: $(BIN) ++ $(INSTALL_PROG) $(BIN) $(TOOLS_INSTALL_DIR) + + clean: +- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) clean +- rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a ++ rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a $(OBJS) + +-dist: $(DISTSRC) +- rm -rf $(DISTDIR) +- mkdir $(DISTDIR) +- cp --parents $(DISTSRC) $(DISTDIR)/ +- rm -f $(DISTDIR)/crypto/gmp.h +- tar -chzf $(DISTDIR).tar.gz $(DISTDIR) +- rm -rf $(DISTDIR) ++mrproper: clean ++ rm -f $(BIN) tpm_version.h + + $(src)/crypto/libgmp.a: + test -f $(src)/crypto/libgmp.a || ln -s $(GMP_LIB) $(src)/crypto/libgmp.a +diff -uprN tpm_emulator-0.3-x86_64/README vtpm/README +--- tpm_emulator-0.3-x86_64/README 2006-08-29 15:07:43.530967832 -0700 ++++ vtpm/README 2006-08-29 15:12:07.190885432 -0700 +@@ -13,7 +13,8 @@ $Id: README 78 2006-01-07 10:45:39Z mast + Copyright + -------------------------------------------------------------------------- + Copyright (C) 2004 Mario Strasser <mast@xxxxxxx> and Swiss Federal +-Institute of Technology (ETH) Zurich. ++ Institute of Technology (ETH) Zurich. ++Copyright (C) 2005 INTEL Corp + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff -uprN tpm_emulator-0.3-x86_64/crypto/gmp_kernel_wrapper.c vtpm/crypto/gmp_kernel_wrapper.c +--- tpm_emulator-0.3-x86_64/crypto/gmp_kernel_wrapper.c 2006-08-29 15:07:43.525968592 -0700 ++++ vtpm/crypto/gmp_kernel_wrapper.c 2006-08-29 15:12:07.186886040 -0700 @@ -1,5 +1,6 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -78,9 +186,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ } } -diff -uprN orig/tpm_emulator-0.3-x86_64/crypto/rsa.c vtpm/crypto/rsa.c ---- orig/tpm_emulator-0.3-x86_64/crypto/rsa.c 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/crypto/rsa.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/crypto/rsa.c vtpm/crypto/rsa.c +--- tpm_emulator-0.3-x86_64/crypto/rsa.c 2006-08-29 15:07:21.618299064 -0700 ++++ vtpm/crypto/rsa.c 2006-08-29 15:12:07.187885888 -0700 @@ -1,5 +1,6 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -106,8 +214,8 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ sha1_final(&ctx, &msg[1]); if (memcmp(&msg[1], &msg[1 + SHA1_DIGEST_LENGTH], SHA1_DIGEST_LENGTH) != 0) return -1; -diff -uprN orig/tpm_emulator-0.3-x86_64/linux_module.c vtpm/linux_module.c ---- orig/tpm_emulator-0.3-x86_64/linux_module.c 2006-05-30 12:28:02.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/linux_module.c vtpm/linux_module.c +--- tpm_emulator-0.3-x86_64/linux_module.c 2006-08-29 15:07:43.526968440 -0700 +++ vtpm/linux_module.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,194 +0,0 @@ -/* Software-Based Trusted Platform Module (TPM) Emulator for Linux @@ -304,9 +412,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ - return (ticks > 0) ? ticks : 1; -} - -diff -uprN orig/tpm_emulator-0.3-x86_64/linux_module.h vtpm/linux_module.h ---- orig/tpm_emulator-0.3-x86_64/linux_module.h 2006-05-30 12:28:02.000000000 -0700 -+++ vtpm/linux_module.h 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/linux_module.h vtpm/linux_module.h +--- tpm_emulator-0.3-x86_64/linux_module.h 2006-08-29 15:07:43.527968288 -0700 ++++ vtpm/linux_module.h 2006-08-29 15:12:07.189885584 -0700 @@ -1,5 +1,6 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -406,116 +514,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ #define BE16_TO_CPU(x) __be16_to_cpu(x) #define LE16_TO_CPU(x) __le16_to_cpu(x) -diff -uprN orig/tpm_emulator-0.3-x86_64/Makefile vtpm/Makefile ---- orig/tpm_emulator-0.3-x86_64/Makefile 2006-05-30 12:28:02.000000000 -0700 -+++ vtpm/Makefile 2006-05-30 12:23:26.000000000 -0700 -@@ -1,22 +1,31 @@ - # Software-Based Trusted Platform Module (TPM) Emulator for Linux - # Copyright (C) 2004 Mario Strasser <mast@xxxxxxx> -+# Copyright (C) 2006 INTEL Corp. - # - # $Id: Makefile 69 2005-12-13 12:55:52Z mast $ - --# kernel settings --KERNEL_RELEASE := $(shell uname -r) --KERNEL_BUILD := /lib/modules/$(KERNEL_RELEASE)/build --MOD_SUBDIR := misc - COMPILE_ARCH ?= $(shell uname -m | sed -e s/i.86/x86_32/) - - # module settings --MODULE_NAME := tpm_emulator -+BIN := vtpmd - VERSION_MAJOR := 0 - VERSION_MINOR := 3 - VERSION_BUILD := $(shell date +"%s") - --# enable/disable DEBUG messages --EXTRA_CFLAGS += -Wall -DDEBUG -g -+# Installation program and options -+INSTALL = install -+INSTALL_PROG = $(INSTALL) -m0755 -+INSTALL_DIR = $(INSTALL) -d -m0755 -+ -+# Xen tools installation directory -+TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin -+ -+CC := gcc -+CFLAGS += -g -Wall $(INCLUDE) -DDEBUG -+CFLAGS += -I. -Itpm -I../../vtpm_manager/manager -+ -+# Is the simulator running in it's own vm? -+#CFLAGS += -DVTPM_MULTI_VM - - ifeq ($(COMPILE_ARCH),x86_64) - LIBDIR = lib64 -@@ -34,38 +43,31 @@ DIRS := . crypto tpm - SRCS := $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.c)) - OBJS := $(patsubst %.c, %.o, $(SRCS)) - SRCS += $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.h)) --DISTSRC := ./README ./AUTHORS ./ChangeLog ./Makefile $(SRCS) --DISTDIR := tpm_emulator-$(VERSION_MAJOR).$(VERSION_MINOR) - --obj-m := $(MODULE_NAME).o --$(MODULE_NAME)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a -+obj-m := $(BIN) -+$(BIN)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a - - EXTRA_CFLAGS += -I$(src) -I$(src)/crypto -I$(src)/tpm - - # do not print "Entering directory ..." - MAKEFLAGS += --no-print-directory - --all: $(src)/crypto/gmp.h $(src)/crypto/libgmp.a version -- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules -+all: $(BIN) -+ -+$(BIN): $(src)/crypto/gmp.h $(src)/crypto/libgmp.a version $(SRCS) $(OBJS) -+ $(CC) $(CFLAGS) $(OBJS) $(src)/crypto/libgmp.a -o $(BIN) -+ -+%.o: %.c -+ $(CC) $(CFLAGS) -c $< -o $@ - - install: -- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules_install -- test -d /var/tpm || mkdir /var/tpm -- test -c /dev/tpm || mknod /dev/tpm c 10 224 -- chmod 666 /dev/tpm -- depmod -a -+ $(INSTALL_PROG) $(BIN) $(TOOLS_INSTALL_DIR) - - clean: -- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) clean -- rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a -+ rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a $(OBJS) - --dist: $(DISTSRC) -- rm -rf $(DISTDIR) -- mkdir $(DISTDIR) -- cp --parents $(DISTSRC) $(DISTDIR)/ -- rm -f $(DISTDIR)/crypto/gmp.h -- tar -chzf $(DISTDIR).tar.gz $(DISTDIR) -- rm -rf $(DISTDIR) -+mrproper: clean -+ rm -f $(BIN) tpm_version.h - - $(src)/crypto/libgmp.a: - test -f $(src)/crypto/libgmp.a || ln -s $(GMP_LIB) $(src)/crypto/libgmp.a -diff -uprN orig/tpm_emulator-0.3-x86_64/README vtpm/README ---- orig/tpm_emulator-0.3-x86_64/README 2006-05-30 12:28:02.000000000 -0700 -+++ vtpm/README 2006-05-30 12:23:26.000000000 -0700 -@@ -13,7 +13,8 @@ $Id: README 78 2006-01-07 10:45:39Z mast - Copyright - -------------------------------------------------------------------------- - Copyright (C) 2004 Mario Strasser <mast@xxxxxxx> and Swiss Federal --Institute of Technology (ETH) Zurich. -+ Institute of Technology (ETH) Zurich. -+Copyright (C) 2005 INTEL Corp - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by -diff -uprN orig/tpm_emulator-0.3-x86_64/tpm/tpm_audit.c vtpm/tpm/tpm_audit.c ---- orig/tpm_emulator-0.3-x86_64/tpm/tpm_audit.c 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/tpm/tpm_audit.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_audit.c vtpm/tpm/tpm_audit.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_audit.c 2006-08-29 15:07:21.620298760 -0700 ++++ vtpm/tpm/tpm_audit.c 2006-08-29 15:12:07.191885280 -0700 @@ -1,6 +1,7 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -578,9 +579,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ return TPM_SUCCESS; } - -diff -uprN orig/tpm_emulator-0.3-x86_64/tpm/tpm_authorization.c vtpm/tpm/tpm_authorization.c ---- orig/tpm_emulator-0.3-x86_64/tpm/tpm_authorization.c 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/tpm/tpm_authorization.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_authorization.c vtpm/tpm/tpm_authorization.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_authorization.c 2006-08-29 15:07:21.620298760 -0700 ++++ vtpm/tpm/tpm_authorization.c 2006-08-29 15:12:07.192885128 -0700 @@ -1,6 +1,7 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -598,9 +599,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ info("tpm_verify_auth(%08x)", auth->authHandle); /* get dedicated authorization or transport session */ -diff -uprN orig/tpm_emulator-0.3-x86_64/tpm/tpm_capability.c vtpm/tpm/tpm_capability.c ---- orig/tpm_emulator-0.3-x86_64/tpm/tpm_capability.c 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/tpm/tpm_capability.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_capability.c vtpm/tpm/tpm_capability.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_capability.c 2006-08-29 15:07:21.620298760 -0700 ++++ vtpm/tpm/tpm_capability.c 2006-08-29 15:12:07.193884976 -0700 @@ -1,6 +1,7 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -623,9 +624,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ } } - -diff -uprN orig/tpm_emulator-0.3-x86_64/tpm/tpm_cmd_handler.c vtpm/tpm/tpm_cmd_handler.c ---- orig/tpm_emulator-0.3-x86_64/tpm/tpm_cmd_handler.c 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/tpm/tpm_cmd_handler.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_cmd_handler.c vtpm/tpm/tpm_cmd_handler.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_cmd_handler.c 2006-08-29 15:07:21.621298608 -0700 ++++ vtpm/tpm/tpm_cmd_handler.c 2006-08-29 15:12:07.197884368 -0700 @@ -1,6 +1,7 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -683,9 +684,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ /* setup authorisation as well as response tag and size */ memset(rsp, 0, sizeof(*rsp)); switch (req->tag) { -diff -uprN orig/tpm_emulator-0.3-x86_64/tpm/tpm_crypto.c vtpm/tpm/tpm_crypto.c ---- orig/tpm_emulator-0.3-x86_64/tpm/tpm_crypto.c 2006-05-30 12:28:02.000000000 -0700 -+++ vtpm/tpm/tpm_crypto.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_crypto.c vtpm/tpm/tpm_crypto.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_crypto.c 2006-08-29 15:07:43.531967680 -0700 ++++ vtpm/tpm/tpm_crypto.c 2006-08-29 15:12:07.198884216 -0700 @@ -1,6 +1,7 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -708,9 +709,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ return TPM_SUCCESS; } - -diff -uprN orig/tpm_emulator-0.3-x86_64/tpm/tpm_daa.c vtpm/tpm/tpm_daa.c ---- orig/tpm_emulator-0.3-x86_64/tpm/tpm_daa.c 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/tpm/tpm_daa.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_daa.c vtpm/tpm/tpm_daa.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_daa.c 2006-08-29 15:07:21.622298456 -0700 ++++ vtpm/tpm/tpm_daa.c 2006-08-29 15:12:07.203883456 -0700 @@ -700,14 +700,14 @@ info("tested until here"); sizeof(session->DAA_tpmSpecific.DAA_rekey)); sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, @@ -865,9 +866,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH); mpz_init(f), mpz_init(q); mpz_import(f, 2 * SHA1_DIGEST_LENGTH, 1, 1, 0, 0, scratch); -diff -uprN orig/tpm_emulator-0.3-x86_64/tpm/tpm_data.c vtpm/tpm/tpm_data.c ---- orig/tpm_emulator-0.3-x86_64/tpm/tpm_data.c 2006-05-30 12:28:02.000000000 -0700 -+++ vtpm/tpm/tpm_data.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_data.c vtpm/tpm/tpm_data.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_data.c 2006-08-29 15:08:20.535342312 -0700 ++++ vtpm/tpm/tpm_data.c 2006-08-29 15:12:07.206883000 -0700 @@ -1,6 +1,7 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -1177,7 +1178,7 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ } #else -@@ -267,7 +462,6 @@ int tpm_restore_permanent_data(void) +@@ -278,7 +473,6 @@ int tpm_restore_permanent_data(void) int tpm_erase_permanent_data(void) { @@ -1186,9 +1187,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ return res; } - -diff -uprN orig/tpm_emulator-0.3-x86_64/tpm/tpm_deprecated.c vtpm/tpm/tpm_deprecated.c ---- orig/tpm_emulator-0.3-x86_64/tpm/tpm_deprecated.c 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/tpm/tpm_deprecated.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_deprecated.c vtpm/tpm/tpm_deprecated.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_deprecated.c 2006-08-29 15:07:21.622298456 -0700 ++++ vtpm/tpm/tpm_deprecated.c 2006-08-29 15:12:07.207882848 -0700 @@ -1,6 +1,7 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -1215,9 +1216,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ authContextSize, &contextBlob); if (res != TPM_SUCCESS) return res; len = *authContextSize; -diff -uprN orig/tpm_emulator-0.3-x86_64/tpm/tpm_emulator.h vtpm/tpm/tpm_emulator.h ---- orig/tpm_emulator-0.3-x86_64/tpm/tpm_emulator.h 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/tpm/tpm_emulator.h 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_emulator.h vtpm/tpm/tpm_emulator.h +--- tpm_emulator-0.3-x86_64/tpm/tpm_emulator.h 2006-08-29 15:07:21.648294504 -0700 ++++ vtpm/tpm/tpm_emulator.h 2006-08-29 15:12:07.208882696 -0700 @@ -1,5 +1,6 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -1235,9 +1236,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ #undef TPM_GENERATE_SEED_DAA #define TPM_MANUFACTURER 0x4554485A /* 'ETHZ' */ -diff -uprN orig/tpm_emulator-0.3-x86_64/tpm/tpm_integrity.c vtpm/tpm/tpm_integrity.c ---- orig/tpm_emulator-0.3-x86_64/tpm/tpm_integrity.c 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/tpm/tpm_integrity.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_integrity.c vtpm/tpm/tpm_integrity.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_integrity.c 2006-08-29 15:07:21.645294960 -0700 ++++ vtpm/tpm/tpm_integrity.c 2006-08-29 15:12:07.208882696 -0700 @@ -1,6 +1,7 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -1251,9 +1252,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ return TPM_SUCCESS; } - -diff -uprN orig/tpm_emulator-0.3-x86_64/tpm/tpm_structures.h vtpm/tpm/tpm_structures.h ---- orig/tpm_emulator-0.3-x86_64/tpm/tpm_structures.h 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/tpm/tpm_structures.h 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_structures.h vtpm/tpm/tpm_structures.h +--- tpm_emulator-0.3-x86_64/tpm/tpm_structures.h 2006-08-29 15:08:20.545340792 -0700 ++++ vtpm/tpm/tpm_structures.h 2006-08-29 15:12:07.211882240 -0700 @@ -1,6 +1,7 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -1271,9 +1272,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ #include "crypto/rsa.h" /* -diff -uprN orig/tpm_emulator-0.3-x86_64/tpm/tpm_testing.c vtpm/tpm/tpm_testing.c ---- orig/tpm_emulator-0.3-x86_64/tpm/tpm_testing.c 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/tpm/tpm_testing.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_testing.c vtpm/tpm/tpm_testing.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_testing.c 2006-08-29 15:07:21.646294808 -0700 ++++ vtpm/tpm/tpm_testing.c 2006-08-29 15:12:07.213881936 -0700 @@ -1,6 +1,7 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -1389,9 +1390,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ rsa_private_key_t priv_key; rsa_public_key_t pub_key; -diff -uprN orig/tpm_emulator-0.3-x86_64/tpm/tpm_ticks.c vtpm/tpm/tpm_ticks.c ---- orig/tpm_emulator-0.3-x86_64/tpm/tpm_ticks.c 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/tpm/tpm_ticks.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_ticks.c vtpm/tpm/tpm_ticks.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_ticks.c 2006-08-29 15:07:21.646294808 -0700 ++++ vtpm/tpm/tpm_ticks.c 2006-08-29 15:12:07.235878592 -0700 @@ -1,6 +1,7 @@ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>, @@ -1474,9 +1475,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ } -diff -uprN orig/tpm_emulator-0.3-x86_64/tpm/tpm_transport.c vtpm/tpm/tpm_transport.c ---- orig/tpm_emulator-0.3-x86_64/tpm/tpm_transport.c 2006-01-10 04:21:45.000000000 -0800 -+++ vtpm/tpm/tpm_transport.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpm/tpm_transport.c vtpm/tpm/tpm_transport.c +--- tpm_emulator-0.3-x86_64/tpm/tpm_transport.c 2006-08-29 15:07:21.647294656 -0700 ++++ vtpm/tpm/tpm_transport.c 2006-08-29 15:12:07.239877984 -0700 @@ -59,7 +59,7 @@ static int decrypt_transport_auth(TPM_KE static void transport_log_in(TPM_COMMAND_CODE ordinal, BYTE parameters[20], BYTE pubKeyHash[20], TPM_DIGEST *transDigest) @@ -1534,9 +1535,9 @@ diff -uprN orig/tpm_emulator-0.3-x86_64/ memcpy(&buf[30], session->transInternal.transDigest.digest, 20); /* sign info structure */ res = tpm_sign(key, auth1, TRUE, buf, sizeof(buf), signature, signSize); -diff -uprN orig/tpm_emulator-0.3-x86_64/tpmd.c vtpm/tpmd.c ---- orig/tpm_emulator-0.3-x86_64/tpmd.c 1969-12-31 16:00:00.000000000 -0800 -+++ vtpm/tpmd.c 2006-05-30 12:23:26.000000000 -0700 +diff -uprN tpm_emulator-0.3-x86_64/tpmd.c vtpm/tpmd.c +--- tpm_emulator-0.3-x86_64/tpmd.c 1969-12-31 16:00:00.000000000 -0800 ++++ vtpm/tpmd.c 2006-08-29 15:12:07.240877832 -0700 @@ -0,0 +1,207 @@ +/* Software-Based Trusted Platform Module (TPM) Emulator for Linux + * Copyright (C) 2005 INTEL Corp diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm_manager/Rules.mk --- a/tools/vtpm_manager/Rules.mk Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm_manager/Rules.mk Wed Jun 28 07:52:21 2006 -0600 @@ -56,6 +56,9 @@ CFLAGS += -DLOGGING_MODULES="(BITMASK(VT # vtpm_manager listens on fifo's rather than backend #CFLAGS += -DDUMMY_BACKEND +# TCS talks to fifo's rather than /dev/tpm. TPM Emulator assumed on fifos +#CFLAGS += -DDUMMY_TPM + # Do not have manager launch DMs. #CFLAGS += -DMANUAL_DM_LAUNCH diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm_manager/manager/dmictl.c --- a/tools/vtpm_manager/manager/dmictl.c Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm_manager/manager/dmictl.c Wed Jun 28 07:52:21 2006 -0600 @@ -76,14 +76,13 @@ TPM_RESULT VTPM_Handle_New_DMI(const buf VTPM_DMI_RESOURCE *new_dmi=NULL; TPM_RESULT status=TPM_FAIL; - BYTE type; - UINT32 dmi_id, domain_id, *dmi_id_key; + BYTE type, startup_mode; + UINT32 dmi_id, *dmi_id_key=NULL; if (param_buf == NULL) { // Assume creation of Dom 0 control - type = 0; - domain_id = VTPM_CTL_DM; + type = VTPM_TYPE_NON_MIGRATABLE; dmi_id = VTPM_CTL_DM; - } else if (buffer_len(param_buf) != sizeof(BYTE) + sizeof(UINT32) *2) { + } else if (buffer_len(param_buf) != sizeof(BYTE) + sizeof(BYTE) + sizeof(UINT32)) { vtpmloginfo(VTPM_LOG_VTPM, "New DMI command wrong length: %d.\n", buffer_len(param_buf)); status = TPM_BAD_PARAMETER; goto abort_egress; @@ -91,13 +90,13 @@ TPM_RESULT VTPM_Handle_New_DMI(const buf vtpm_globals->connected_dmis++; // Put this here so we don't count Dom0 BSG_UnpackList( param_buf->bytes, 3, BSG_TYPE_BYTE, &type, - BSG_TYPE_UINT32, &domain_id, + BSG_TYPE_BYTE, &startup_mode, BSG_TYPE_UINT32, &dmi_id); } - + new_dmi = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map, &dmi_id); if (new_dmi == NULL) { - vtpmloginfo(VTPM_LOG_VTPM, "Creating new DMI instance %d attached on domain %d.\n", dmi_id, domain_id); + vtpmloginfo(VTPM_LOG_VTPM, "Creating new DMI instance %d attached.\n", dmi_id ); // Brand New DMI. Initialize the persistent pieces if ((new_dmi = (VTPM_DMI_RESOURCE *) malloc (sizeof(VTPM_DMI_RESOURCE))) == NULL) { status = TPM_RESOURCES; @@ -106,32 +105,44 @@ TPM_RESULT VTPM_Handle_New_DMI(const buf memset(new_dmi, 0, sizeof(VTPM_DMI_RESOURCE)); new_dmi->dmi_id = dmi_id; new_dmi->connected = FALSE; + + if (type != VTPM_TYPE_MIGRATED) { + new_dmi->dmi_type = type; + } else { + vtpmlogerror(VTPM_LOG_VTPM, "Creation of VTPM with illegal type.\n"); + status = TPM_BAD_PARAMETER; + goto free_egress; + } if ((dmi_id_key = (UINT32 *) malloc (sizeof(UINT32))) == NULL) { status = TPM_RESOURCES; - goto abort_egress; + goto free_egress; } *dmi_id_key = new_dmi->dmi_id; // install into map if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, new_dmi)){ - free(new_dmi); - free(dmi_id_key); + vtpmlogerror(VTPM_LOG_VTPM, "Failed to insert instance into table. Aborting.\n", dmi_id); status = TPM_FAIL; - goto egress; + goto free_egress; } } else - vtpmloginfo(VTPM_LOG_VTPM, "Re-attaching DMI instance %d on domain %d .\n", dmi_id, domain_id); + vtpmloginfo(VTPM_LOG_VTPM, "Re-attaching DMI instance %d.\n", dmi_id); if (new_dmi->connected) { vtpmlogerror(VTPM_LOG_VTPM, "Attempt to re-attach, currently attached instance %d. Ignoring\n", dmi_id); status = TPM_BAD_PARAMETER; - goto egress; - } - + goto abort_egress; + } + + if (type == VTPM_TYPE_MIGRATED) { + vtpmlogerror(VTPM_LOG_VTPM, "Attempt to re-attach previously migrated instance %d without recovering first. Ignoring\n", dmi_id); + status = TPM_BAD_PARAMETER; + goto abort_egress; + } + // Initialize the Non-persistent pieces - new_dmi->dmi_domain_id = domain_id; new_dmi->NVMLocation = NULL; new_dmi->TCSContext = 0; @@ -144,9 +155,13 @@ TPM_RESULT VTPM_Handle_New_DMI(const buf // Design specific new DMI code. // Includes: create IPCs, Measuring DMI, and maybe launching DMI - status = VTPM_New_DMI_Extra(new_dmi); - goto egress; - + status = VTPM_New_DMI_Extra(new_dmi, startup_mode); + goto egress; + + free_egress: // Error that requires freeing of newly allocated dmi + free(new_dmi); + free(dmi_id_key); + abort_egress: vtpmlogerror(VTPM_LOG_VTPM, "Failed to create DMI id=%d due to status=%s. Cleaning.\n", dmi_id, tpm_get_error_name(status)); close_dmi(new_dmi ); @@ -221,7 +236,7 @@ TPM_RESULT VTPM_Handle_Delete_DMI( const goto abort_egress; } - //TODO: Automatically delete file dmi_res->NVMLocation + //vtpm scripts delete file dmi_res->NVMLocation for us // Close DMI first TPMTRYRETURN(close_dmi( dmi_res )); diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm_manager/manager/securestorage.c --- a/tools/vtpm_manager/manager/securestorage.c Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm_manager/manager/securestorage.c Wed Jun 28 07:52:21 2006 -0600 @@ -190,8 +190,7 @@ TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI long bytes_written; buffer_t sealed_NVM; - - vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Save_NVMing[%d]: 0x\n", buffer_len(inbuf)); + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Saving %d bytes of NVM.\n", buffer_len(inbuf)); TPMTRYRETURN( envelope_encrypt(inbuf, &vtpm_globals->storageKey, @@ -310,6 +309,7 @@ TPM_RESULT VTPM_SaveManagerData(void) { UINT32 bootKeySize = buffer_len(&vtpm_globals->bootKeyWrap); struct pack_buf_t storage_key_pack = {storageKeySize, vtpm_globals->storageKeyWrap.bytes}; struct pack_buf_t boot_key_pack = {bootKeySize, vtpm_globals->bootKeyWrap.bytes}; + BYTE vtpm_manager_gen = VTPM_MANAGER_GEN; struct hashtable_itr *dmi_itr; VTPM_DMI_RESOURCE *dmi_res; @@ -321,7 +321,8 @@ TPM_RESULT VTPM_SaveManagerData(void) { boot_key_size = sizeof(UINT32) + // bootkeysize bootKeySize; // boot key - TPMTRYRETURN(buffer_init(&clear_flat_global, 3*sizeof(TPM_DIGEST) + // Auths + TPMTRYRETURN(buffer_init(&clear_flat_global,sizeof(BYTE) + // manager version + 3*sizeof(TPM_DIGEST) + // Auths sizeof(UINT32) +// storagekeysize storageKeySize, NULL) ); // storage key @@ -332,7 +333,8 @@ TPM_RESULT VTPM_SaveManagerData(void) { boot_key_size = BSG_PackList(flat_boot_key, 1, BSG_TPM_SIZE32_DATA, &boot_key_pack); - BSG_PackList(clear_flat_global.bytes, 3, + BSG_PackList(clear_flat_global.bytes, 4, + BSG_TYPE_BYTE, &vtpm_manager_gen, BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth, BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth, BSG_TPM_SIZE32_DATA, &storage_key_pack); @@ -348,7 +350,7 @@ TPM_RESULT VTPM_SaveManagerData(void) { flat_dmis = (BYTE *) malloc( (hashtable_count(vtpm_globals->dmi_map) - 1) * // num DMIS (-1 for Dom0) - (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)) ); // Per DMI info + (sizeof(UINT32) +sizeof(BYTE) + 2*sizeof(TPM_DIGEST)) ); // Per DMI info dmi_itr = hashtable_iterator(vtpm_globals->dmi_map); do { @@ -360,8 +362,9 @@ TPM_RESULT VTPM_SaveManagerData(void) { continue; - flat_dmis_size += BSG_PackList( flat_dmis + flat_dmis_size, 3, + flat_dmis_size += BSG_PackList( flat_dmis + flat_dmis_size, 4, BSG_TYPE_UINT32, &dmi_res->dmi_id, + BSG_TYPE_BYTE, &dmi_res->dmi_type, BSG_TPM_DIGEST, &dmi_res->NVM_measurement, BSG_TPM_DIGEST, &dmi_res->DMI_measurement); @@ -408,6 +411,7 @@ TPM_RESULT VTPM_LoadManagerData(void) { buffer_t unsealed_data; struct pack_buf_t storage_key_pack, boot_key_pack; UINT32 *dmi_id_key, enc_size; + BYTE vtpm_manager_gen; VTPM_DMI_RESOURCE *dmi_res; struct stat file_stat; @@ -458,8 +462,14 @@ TPM_RESULT VTPM_LoadManagerData(void) { &unsealed_data) ); step_size += enc_size; + if (*unsealed_data.bytes != VTPM_MANAGER_GEN) { + // Once there is more than one gen, this will include some compatability stuff + vtpmlogerror(VTPM_LOG_VTPM, "Warning: Manager Data file is gen %d, which this manager is gen %d.\n", vtpm_manager_gen, VTPM_MANAGER_GEN); + } + // Global Values needing to be saved - BSG_UnpackList( unsealed_data.bytes, 3, + BSG_UnpackList( unsealed_data.bytes, 4, + BSG_TYPE_BYTE, &vtpm_manager_gen, BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth, BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth, BSG_TPM_SIZE32_DATA, &storage_key_pack); @@ -469,7 +479,7 @@ TPM_RESULT VTPM_LoadManagerData(void) { // Per DMI values to be saved while ( step_size < fh_size ){ - if (fh_size - step_size < (long) (sizeof(UINT32) + 2*sizeof(TPM_DIGEST))) { + if (fh_size - step_size < (long) (sizeof(UINT32) + sizeof(BYTE) + 2*sizeof(TPM_DIGEST))) { vtpmlogerror(VTPM_LOG_VTPM, "Encountered %ld extra bytes at end of manager state.\n", fh_size-step_size); step_size = fh_size; } else { @@ -478,8 +488,9 @@ TPM_RESULT VTPM_LoadManagerData(void) { dmi_res->connected = FALSE; - step_size += BSG_UnpackList(flat_table + step_size, 3, + step_size += BSG_UnpackList(flat_table + step_size, 4, BSG_TYPE_UINT32, &dmi_res->dmi_id, + BSG_TYPE_BYTE, &dmi_res->dmi_type, BSG_TPM_DIGEST, &dmi_res->NVM_measurement, BSG_TPM_DIGEST, &dmi_res->DMI_measurement); diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm_manager/manager/vtpm_manager.c --- a/tools/vtpm_manager/manager/vtpm_manager.c Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm_manager/manager/vtpm_manager.c Wed Jun 28 07:52:21 2006 -0600 @@ -92,8 +92,9 @@ TPM_RESULT VTPM_Create_Manager(){ status = VTSP_ReadPubek(vtpm_globals->manager_tcs_handle, &ek_cryptoInfo); // If we can read PubEK then there is no owner and we should take it. + // We use the abilty to read the pubEK to flag that the TPM is owned. + // FIXME: Change to just trying to take ownership and react to the status if (status == TPM_SUCCESS) { - vtpmloginfo(VTPM_LOG_VTPM, "Failed to readEK meaning TPM has an owner. Creating Keys off existing SRK.\n"); TPMTRYRETURN(VTSP_TakeOwnership(vtpm_globals->manager_tcs_handle, (const TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth, &SRK_AUTH, @@ -103,6 +104,8 @@ TPM_RESULT VTPM_Create_Manager(){ TPMTRYRETURN(VTSP_DisablePubekRead(vtpm_globals->manager_tcs_handle, (const TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth, &vtpm_globals->keyAuth)); + } else { + vtpmloginfo(VTPM_LOG_VTPM, "Failed to readEK meaning TPM has an owner. Creating Keys off existing SRK.\n"); } // Generate storage key's auth @@ -165,7 +168,7 @@ TPM_RESULT VTPM_Create_Manager(){ &vtpm_globals->bootKey, TRUE ) ); - printf("***************************** FIXME: SAVE NEW STATE *******\n"); + TPMTRYRETURN( VTSP_SaveState(vtpm_globals->manager_tcs_handle) ); goto egress; abort_egress: @@ -181,7 +184,7 @@ TPM_RESULT VTPM_Init_Manager() { TPM_RESULT VTPM_Init_Manager() { TPM_RESULT status = TPM_FAIL, serviceStatus; BYTE *randomsead; - UINT32 randomsize; + UINT32 randomsize=256; if ((vtpm_globals = (VTPM_GLOBALS *) malloc(sizeof(VTPM_GLOBALS))) == NULL){ status = TPM_FAIL; @@ -216,7 +219,7 @@ TPM_RESULT VTPM_Init_Manager() { &vtpm_globals->keyAuth) ); vtpm_globals->keyAuth.fContinueAuthSession = TRUE; - // If failed, create new Manager. + // If failed, create new Manager. serviceStatus = VTPM_LoadManagerData(); if (serviceStatus == TPM_IOERROR) { vtpmloginfo(VTPM_LOG_VTPM, "Failed to read manager file. Assuming first time initialization.\n"); diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm_manager/manager/vtpm_manager.h --- a/tools/vtpm_manager/manager/vtpm_manager.h Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm_manager/manager/vtpm_manager.h Wed Jun 28 07:52:21 2006 -0600 @@ -73,6 +73,12 @@ #define VTPM_RESTORE_CONTEXT_FAILED 4 #define VTPM_INVALID_REQUEST 5 +//*********************** Parameter Values ************************* +#define VTPM_TYPE_NON_MIGRATABLE 0x00 +#define VTPM_TYPE_MIGRATABLE 0x01 +#define VTPM_TYPE_MIGRATED 0xFF // VTPM has been migrated. + // VTPM can be recovered or deleted only + /******************* Command Parameter API ************************* VTPM Command Format @@ -94,8 +100,8 @@ VTPM Response Format VTPM_Open: Input Parameters: - Domain_type: 1 byte - domain_id: 4 bytes + Domain_type: 1 byte + startup_mode: 1 byte // Cold Boot = 1, resume = 2, deactive = 3 instance_id: 4 bytes Output Parameters: None diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm_manager/manager/vtpm_manager_handler.c --- a/tools/vtpm_manager/manager/vtpm_manager_handler.c Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm_manager/manager/vtpm_manager_handler.c Wed Jun 28 07:52:21 2006 -0600 @@ -78,13 +78,14 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ip BOOL is_priv, char *thread_name) { TPM_RESULT status = TPM_FAIL; // Should never return - UINT32 dmi, in_param_size, cmd_size, out_param_size, out_message_size, out_message_size_full; - BYTE *cmd_header, *in_param, *out_message; + UINT32 dmi, in_param_size, cmd_size, out_param_size, out_message_size, reply_size; + BYTE *cmd_header=NULL, *in_param=NULL, *out_message=NULL, *reply; buffer_t *command_buf=NULL, *result_buf=NULL; TPM_TAG tag; TPM_COMMAND_CODE ord; VTPM_DMI_RESOURCE *dmi_res; int size_read, size_write, i; + BOOL add_header=TRUE; // This indicates to prepend a header on result_buf before sending cmd_header = (BYTE *) malloc(VTPM_COMMAND_HEADER_SIZE_SRV); command_buf = (buffer_t *) malloc(sizeof(buffer_t)); @@ -100,7 +101,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ip // Read command header size_read = vtpm_ipc_read(rx_ipc_h, NULL, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV); if (size_read > 0) { - vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "RECV[%d}: 0x", size_read); + vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "RECV[%d]: 0x", size_read); for (i=0; i<size_read; i++) vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cmd_header[i]); } else { @@ -165,6 +166,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ip (!dmi_res->connected) ) { vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempted access to non-existent or disconnected DMI %d. Aborting...\n", dmi); status = TPM_BAD_PARAMETER; + goto abort_with_error; } if (tag == VTPM_TAG_REQ) { @@ -176,9 +178,14 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ip status = vtpm_manager_handle_tpm_cmd(fw_tx_ipc_h, fw_rx_ipc_h, dmi_res, cmd_header, command_buf, result_buf, thread_name); // This means calling the DMI failed, not that the cmd failed in the DMI + // Since the return will be interpretted by a TPM app, all errors are IO_ERRORs to the app if (status != TPM_SUCCESS) { + status = TPM_IOERROR; goto abort_with_error; } + // Unlike all other commands, forwarded commands yield a result_buf that includes the DMI's status. This + // should be forwarded to the caller VM + add_header = FALSE; } else { // We are not supposed to forward TPM commands at all. int i; @@ -205,38 +212,43 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ip #ifndef VTPM_MULTI_VM abort_with_error: #endif - - // Prepend VTPM header with destination DM stamped - out_param_size = buffer_len(result_buf); - out_message_size = VTPM_COMMAND_HEADER_SIZE_CLT + out_param_size; - out_message_size_full = VTPM_COMMAND_HEADER_SIZE_SRV + out_param_size; - out_message = (BYTE *) malloc (out_message_size_full); - - BSG_PackList(out_message, 4, - BSG_TYPE_UINT32, (BYTE *) &dmi, - BSG_TPM_TAG, (BYTE *) &tag, - BSG_TYPE_UINT32, (BYTE *) &out_message_size, - BSG_TPM_RESULT, (BYTE *) &status); - - if (buffer_len(result_buf) > 0) - memcpy(out_message + VTPM_COMMAND_HEADER_SIZE_SRV, result_buf->bytes, out_param_size); - - //Note: Send message + dmi_id - size_write = vtpm_ipc_write(tx_ipc_h, dmi_res->tx_vtpm_ipc_h, out_message, out_message_size_full ); + + if (add_header) { + // Prepend VTPM header with destination DM stamped + out_param_size = buffer_len(result_buf); + out_message_size = VTPM_COMMAND_HEADER_SIZE_CLT + out_param_size; + reply_size = VTPM_COMMAND_HEADER_SIZE_SRV + out_param_size; + out_message = (BYTE *) malloc (reply_size); + reply = out_message; + + BSG_PackList(out_message, 4, + BSG_TYPE_UINT32, (BYTE *) &dmi, + BSG_TPM_TAG, (BYTE *) &tag, + BSG_TYPE_UINT32, (BYTE *) &out_message_size, + BSG_TPM_RESULT, (BYTE *) &status); + + if (buffer_len(result_buf) > 0) + memcpy(out_message + VTPM_COMMAND_HEADER_SIZE_SRV, result_buf->bytes, out_param_size); + //Note: Send message + dmi_id + } else { + reply = result_buf->bytes; + reply_size = buffer_len(result_buf); + } + size_write = vtpm_ipc_write(tx_ipc_h, (dmi_res ? dmi_res->tx_vtpm_ipc_h : NULL), reply, reply_size ); if (size_write > 0) { vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT: 0x"); - for (i=0; i < out_message_size_full; i++) - vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", out_message[i]); + for (i=0; i < reply_size; i++) + vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", reply[i]); vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); } else { vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s had error writing to ipc. Aborting... \n", thread_name); goto abort_command; } - free(out_message); - - if (size_write < (int)out_message_size_full) { - vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s unable to write full command to ipc (%d/%d)\n", thread_name, size_write, out_message_size_full); + free(out_message); out_message=NULL; + + if (size_write < (int)reply_size) { + vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s unable to write full command to ipc (%d/%d)\n", thread_name, size_write, reply_size); goto abort_command; } @@ -246,9 +258,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ip //free buffers bzero(cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV); //free(in_param); // This was converted to command_buf. No need to free - if (command_buf != result_buf) - buffer_free(result_buf); - + buffer_free(result_buf); buffer_free(command_buf); // If we have a write lock, save the manager table @@ -258,6 +268,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ip } vtpm_lock_unlock(); + add_header = TRUE; // Reset to the default } // End while(1) } @@ -369,6 +380,7 @@ TPM_RESULT vtpm_manager_handle_tpm_cmd(v dmi_cmd_size = VTPM_COMMAND_HEADER_SIZE_SRV; size_write = vtpm_ipc_write(tx_ipc_h, dmi_res->tx_tpm_ipc_h, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV ); if (size_write > 0) { + vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT (DMI): 0x"); for (i=0; i<VTPM_COMMAND_HEADER_SIZE_SRV; i++) vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cmd_header[i]); @@ -438,7 +450,8 @@ TPM_RESULT vtpm_manager_handle_tpm_cmd(v vtpmhandlerloginfomore(VTPM_LOG_VTPM, "\n"); } - if (buffer_init_convert(result_buf, adj_param_size, in_param) != TPM_SUCCESS) { + if ( (buffer_init(result_buf, VTPM_COMMAND_HEADER_SIZE_SRV, cmd_header) != TPM_SUCCESS) || + (buffer_append_raw(result_buf, adj_param_size, in_param) != TPM_SUCCESS) ) { vtpmhandlerlogerror(VTPM_LOG_VTPM, "Failed to setup buffers. Aborting...\n"); status = TPM_FAIL; goto abort_with_error; diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm_manager/manager/vtpmd.c --- a/tools/vtpm_manager/manager/vtpmd.c Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm_manager/manager/vtpmd.c Wed Jun 28 07:52:21 2006 -0600 @@ -64,14 +64,6 @@ #define VTPM_TX_HP_FNAME "/var/vtpm/fifos/to_console.fifo" #define VTPM_RX_HP_FNAME "/var/vtpm/fifos/from_console.fifo" - -#define GUEST_TX_FIFO "/var/vtpm/fifos/guest-to-%d.fifo" -#define GUEST_RX_FIFO "/var/vtpm/fifos/guest-from-all.fifo" - -#define VTPM_TX_FIFO "/var/vtpm/fifos/vtpm-to-%d.fifo" -#define VTPM_RX_FIFO "/var/vtpm/fifos/vtpm-from-all.fifo" - - struct vtpm_thread_params_s { vtpm_ipc_handle_t *tx_ipc_h; vtpm_ipc_handle_t *rx_ipc_h; @@ -113,7 +105,7 @@ void signal_handler(int reason) { struct sigaction ctl_c_handler; -TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res) { +TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res, BYTE startup_mode) { TPM_RESULT status = TPM_SUCCESS; int fh; @@ -150,14 +142,14 @@ TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_R // Measure DMI // FIXME: This will measure DMI. Until then use a fixed DMI_Measurement value - // Also, this mechanism is specific to 1 VM. + // Also, this mechanism is specific to 1 VM architecture. /* fh = open(TPM_EMULATOR_PATH, O_RDONLY); stat_ret = fstat(fh, &file_stat); if (stat_ret == 0) dmi_size = file_stat.st_size; else { - vtpmlogerror(VTPM_LOG_VTPM, "Could not open tpm_emulator!!\n"); + vtpmlogerror(VTPM_LOG_VTPM, "Could not open vtpmd!!\n"); status = TPM_IOERROR; goto abort_egress; } @@ -179,10 +171,20 @@ TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_R status = TPM_RESOURCES; goto abort_egress; } else if (pid == 0) { - if ( stat(dmi_res->NVMLocation, &file_info) == -1) + switch (startup_mode) { + case TPM_ST_CLEAR: execl (TPM_EMULATOR_PATH, "vtmpd", "clear", dmi_id_str, NULL); - else + break; + case TPM_ST_STATE: execl (TPM_EMULATOR_PATH, "vtpmd", "save", dmi_id_str, NULL); + break; + case TPM_ST_DEACTIVATED: + execl (TPM_EMULATOR_PATH, "vtpmd", "deactivated", dmi_id_str, NULL); + break; + default: + status = TPM_BAD_PARAMETER; + goto abort_egress; + } // Returning from these at all is an error. vtpmlogerror(VTPM_LOG_VTPM, "Could not exec to launch vtpm\n"); @@ -309,7 +311,7 @@ int main(int argc, char **argv) { be_thread_params.fw_tpm = TRUE; be_thread_params.fw_tx_ipc_h = NULL; be_thread_params.fw_rx_ipc_h = &rx_tpm_ipc_h; - be_thread_params.is_priv = TRUE; //FIXME: Change when HP is up + be_thread_params.is_priv = FALSE; be_thread_params.thread_name = "Backend Listener"; dmi_thread_params.tx_ipc_h = NULL; @@ -318,7 +320,7 @@ int main(int argc, char **argv) { dmi_thread_params.fw_tx_ipc_h = NULL; dmi_thread_params.fw_rx_ipc_h = NULL; dmi_thread_params.is_priv = FALSE; - dmi_thread_params.thread_name = "VTPM Listeners"; + dmi_thread_params.thread_name = "VTPM Listener"; hp_thread_params.tx_ipc_h = &tx_hp_ipc_h; hp_thread_params.rx_ipc_h = &rx_hp_ipc_h; @@ -345,10 +347,10 @@ int main(int argc, char **argv) { } -// if (pthread_create(&hp_thread, NULL, vtpm_manager_thread, &hp_thread_params) != 0) { -// vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch HP Thread.\n"); -// exit(-1); -// } + if (pthread_create(&hp_thread, NULL, vtpm_manager_thread, &hp_thread_params) != 0) { + vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch HP Thread.\n"); + exit(-1); + } //Join the other threads until exit time. pthread_join(be_thread, NULL); diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm_manager/manager/vtpmpriv.h --- a/tools/vtpm_manager/manager/vtpmpriv.h Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm_manager/manager/vtpmpriv.h Wed Jun 28 07:52:21 2006 -0600 @@ -40,15 +40,19 @@ #ifndef __VTPMPRIV_H__ #define __VTPMPRIV_H__ +#include "vtpm_manager.h" #include "tcg.h" #include "tcs.h" #include "buffer.h" #include "crypto.h" #include "vtpm_ipc.h" -#define STATE_FILE "/var/vtpm/VTPM" -#define DMI_NVM_FILE "/var/vtpm/vtpm_dm_%d.data" -#define VTPM_CTL_DM 0 +#define VTPM_MANAGER_GEN 2 // This is incremented when the manager's table + // is changed. It's used for backwards compatability + +#define STATE_FILE "/var/vtpm/VTPM" +#define DMI_NVM_FILE "/var/vtpm/vtpm_dm_%d.data" +#define VTPM_CTL_DM 0 // ------------------------ Private Structures ----------------------- typedef struct VTPM_DMI_RESOURCE_T { @@ -70,6 +74,7 @@ typedef struct VTPM_DMI_RESOURCE_T { // of NVM. // Persistent Information about DMI UINT32 dmi_id; + BYTE dmi_type; TPM_DIGEST NVM_measurement; // Equal to the SHA1 of the blob TPM_DIGEST DMI_measurement; // Correct measurement of the owning DMI } VTPM_DMI_RESOURCE; @@ -138,7 +143,7 @@ TPM_RESULT VTPM_SaveManagerData(void); TPM_RESULT VTPM_SaveManagerData(void); TPM_RESULT VTPM_LoadManagerData(void); -TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res); +TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res, BYTE startup_mode); TPM_RESULT VTPM_Close_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res); diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm_manager/manager/vtsp.c --- a/tools/vtpm_manager/manager/vtsp.c Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm_manager/manager/vtsp.c Wed Jun 28 07:52:21 2006 -0600 @@ -971,6 +971,17 @@ TPM_RESULT VTSP_Unseal(const TCS_CONTEXT return status; } +TPM_RESULT VTSP_SaveState( const TCS_CONTEXT_HANDLE hContext) { + + vtpmloginfo(VTPM_LOG_VTSP, "Calling TPM_SaveState.\n"); + + TPM_RESULT status = TPM_SUCCESS; + + // Call TCS + return ( TCSP_SaveState ( hContext ) ); + +} + // Function Reaches into unsupported TCS command, beware. TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE hContext, diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm_manager/manager/vtsp.h --- a/tools/vtpm_manager/manager/vtsp.h Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm_manager/manager/vtsp.h Wed Jun 28 07:52:21 2006 -0600 @@ -118,4 +118,6 @@ TPM_RESULT VTSP_Unseal(const TCS_CONTEXT TCS_AUTH *auth, TCS_AUTH *dataAuth); +TPM_RESULT VTSP_SaveState( const TCS_CONTEXT_HANDLE hContext); + #endif //_VTSP_H_ diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm_manager/tcs/tcs.c --- a/tools/vtpm_manager/tcs/tcs.c Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm_manager/tcs/tcs.c Wed Jun 28 07:52:21 2006 -0600 @@ -1126,6 +1126,49 @@ TPM_RESULT TCSP_ReadPubek(TCS_CONTEXT_HA return(returnCode); } + +TPM_RESULT TCSP_SaveState(TCS_CONTEXT_HANDLE hContext) // in +{ + // setup input/output parameters block + TPM_TAG tag = TPM_TAG_RQU_COMMAND; + UINT32 paramSize = 0; + TPM_COMMAND_CODE ordinal = TPM_ORD_SaveState; + TPM_RESULT returnCode = TPM_SUCCESS; + + // setup the TPM driver input and output buffers + TDDL_RESULT hRes = TDDL_E_FAIL; + TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH; + TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH; + + // Convert Byte Input parameter in the input byte stream InBuf + InLength = BSG_PackList(InBuf, 3, + BSG_TPM_TAG, &tag, + BSG_TYPE_UINT32, ¶mSize, + BSG_TPM_COMMAND_CODE, &ordinal); + // fill paramSize again as we now have the correct size + BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2); + + vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength); + + // call the TPM driver + if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == TDDL_SUCCESS) { + // unpack OutBuf to get the tag, paramSize, & returnCode + BSG_UnpackList(OutBuf, 3, + BSG_TPM_TAG, &tag, + BSG_TYPE_UINT32, ¶mSize, + BSG_TPM_COMMAND_CODE, &returnCode); + + if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) { + vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize); + } else { + vtpmlogerror(VTPM_LOG_TCS, "TCSP_SaveState Failed with return code %s\n", tpm_get_error_name(returnCode)); + } + } + + return(returnCode); +} + + TPM_RESULT TCSP_RawTransmitData( UINT32 inDataSize, // in BYTE *inData, // in UINT32 *outDataSize,// in/out diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm_manager/tcs/tcs.h --- a/tools/vtpm_manager/tcs/tcs.h Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm_manager/tcs/tcs.h Wed Jun 28 07:52:21 2006 -0600 @@ -229,7 +229,10 @@ TPM_RESULT TCSP_ReadPubek ( TCS_CONTEXT ); -// Non-Standard TCSP call to give direct access to TransmitData. +// Non-Standard TCSP calls +TPM_RESULT TCSP_SaveState(TCS_CONTEXT_HANDLE hContext); // in + +//Give direct access to TransmitData. // Key and Auth Management is done before transfering command to TDDL. TPM_RESULT TCSP_RawTransmitData(UINT32 inDataSize, // in BYTE *inData, // in diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm_manager/tcs/transmit.c --- a/tools/vtpm_manager/tcs/transmit.c Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm_manager/tcs/transmit.c Wed Jun 28 07:52:21 2006 -0600 @@ -43,7 +43,17 @@ // flag to track whether TDDL has been opened static int g_TDDL_open = 0; -static int g_fd = -1; // the fd to the TPM +static int g_tx_fd = -1; // the fd to the TPM + +#ifndef DUMMY_TPM + #define TPM_TX_FNAME "/dev/tpm0" + static int *g_rx_fdp = &g_tx_fd; +#else + #define TPM_TX_FNAME "/tmp/tpm_in.fifo" + #define TPM_RX_FNAME "/tmp/tpm_out.fifo" + static int g_rx_fd = -1; + static int *g_rx_fdp = &g_rx_fd; // the fd to the TPM +#endif TPM_RESULT TDDL_TransmitData( TDDL_BYTE* in, @@ -60,10 +70,9 @@ TDDL_TransmitData( TDDL_BYTE* in, vtpmloginfomore(VTPM_LOG_TXDATA, "\n"); ssize_t size = 0; - int fd = g_fd; // send the request - size = write (fd, in, insize); + size = write (g_tx_fd, in, insize); if (size < 0) { vtpmlogerror(VTPM_LOG_TXDATA, "write() failed"); ERRORDIE (TPM_IOERROR); @@ -74,7 +83,7 @@ TDDL_TransmitData( TDDL_BYTE* in, } // read the response - size = read (fd, out, TCPA_MAX_BUFFER_LENGTH); + size = read (*g_rx_fdp, out, TCPA_MAX_BUFFER_LENGTH); if (size < 0) { vtpmlogerror(VTPM_LOG_TXDATA, "read() failed"); ERRORDIE (TPM_IOERROR); @@ -98,18 +107,20 @@ TPM_RESULT TDDL_Open() { TPM_RESULT TDDL_Open() { TDDL_RESULT status = TDDL_SUCCESS; - int fd = -1; if (g_TDDL_open) return TPM_FAIL; - - fd = open ("/dev/tpm0", O_RDWR); - if (fd < 0) { + +#ifdef DUMMY_TPM + *g_rx_fdp = open (TPM_RX_FNAME, O_RDWR); +#endif + + g_tx_fd = open (TPM_TX_FNAME, O_RDWR); + if (g_tx_fd < 0) { vtpmlogerror(VTPM_LOG_TXDATA, "TPM open failed"); return TPM_IOERROR; } - g_fd = fd; g_TDDL_open = 1; return status; @@ -119,13 +130,18 @@ void TDDL_Close() { if (! g_TDDL_open) return; - if (g_fd>= 0) { - if (close(g_fd) < 0) + if (g_tx_fd>= 0) { + if (close(g_tx_fd) < 0) vtpmlogerror(VTPM_LOG_TXDATA, "closeing tpm failed"); - - g_fd = -1; + g_tx_fd = -1; } + if (*g_rx_fdp>= 0) { + if (close(*g_rx_fdp) < 0) + vtpmlogerror(VTPM_LOG_TXDATA, "closeing tpm failed"); + *g_rx_fdp = -1; + } + g_TDDL_open = 0; } diff -r c4b68afe97d3 -r 4b51d081378d tools/vtpm_manager/util/tcg.h --- a/tools/vtpm_manager/util/tcg.h Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/vtpm_manager/util/tcg.h Wed Jun 28 07:52:21 2006 -0600 @@ -389,6 +389,11 @@ typedef struct pack_constbuf_t { #define TPM_DELEGATE_ADMIN TPM_BASE + 77 // Delegation table management not enabled #define TPM_TRANSPORT_EXCLUSIVE TPM_BASE + 78 // There was a command executed outside of an exclusive transport session +// TPM_STARTUP_TYPE values +#define TPM_ST_CLEAR 0x0001 +#define TPM_ST_STATE 0x0002 +#define TPM_ST_DEACTIVATED 0x003 + // TPM_TAG values #define TPM_TAG_RQU_COMMAND 0x00c1 #define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2 diff -r c4b68afe97d3 -r 4b51d081378d tools/xenstat/xentop/xentop.1 --- a/tools/xenstat/xentop/xentop.1 Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/xenstat/xentop/xentop.1 Wed Jun 28 07:52:21 2006 -0600 @@ -25,6 +25,8 @@ [\fB\-n\fR] [\fB\-r\fR] [\fB\-v\fR] +[\fB\-b\fR] +[\fB\-i\fRITERATIONS] .SH DESCRIPTION \fBxentop\fR displays information about the Xen system and domains, in a @@ -50,6 +52,13 @@ repeat table header before each domain .TP \fB\-v\fR, \fB\-\-vcpus\fR output VCPU data +.TP +\fB\-b\fR, \fB\-\-batch\fR +output data in batch mode (to stdout) +.TP +\fB\-i\fR, \fB\-\-iterations\fR=\fIITERATIONS\fR +maximum number of iterations xentop should produce before ending + .SH "INTERACTIVE COMMANDS" All interactive commands are case-insensitive. diff -r c4b68afe97d3 -r 4b51d081378d tools/xenstat/xentop/xentop.c --- a/tools/xenstat/xentop/xentop.c Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/xenstat/xentop/xentop.c Wed Jun 28 07:52:21 2006 -0600 @@ -153,6 +153,9 @@ field_id sort_field = FIELD_DOMID; field_id sort_field = FIELD_DOMID; unsigned int first_domain_index = 0; unsigned int delay = 3; +unsigned int batch = 0; +unsigned int loop = 1; +unsigned int iterations = 0; int show_vcpus = 0; int show_networks = 0; int repeat_header = 0; @@ -179,6 +182,8 @@ static void usage(const char *program) "-n, --networks output vif network data\n" "-r, --repeat-header repeat table header before each domain\n" "-v, --vcpus output vcpu data\n" + "-b, --batch output in batch mode, no user input accepted\n" + "-i, --iterations number of iterations before exiting\n" "\n" XENTOP_BUGSTO, program); return; @@ -236,9 +241,15 @@ static void print(const char *fmt, ...) { va_list args; - if(current_row() < lines()-1) { + if (!batch) { + if((current_row() < lines()-1)) { + va_start(args, fmt); + vw_printw(stdscr, fmt, args); + va_end(args); + } + } else { va_start(args, fmt); - vw_printw(stdscr, fmt, args); + vprintf(fmt, args); va_end(args); } } @@ -803,6 +814,7 @@ static void top(void) do_network(domains[i]); } + if(!batch) do_bottom_line(); } @@ -818,9 +830,11 @@ int main(int argc, char **argv) { "repeat-header", no_argument, NULL, 'r' }, { "vcpus", no_argument, NULL, 'v' }, { "delay", required_argument, NULL, 'd' }, + { "batch", no_argument, NULL, 'b' }, + { "iterations", required_argument, NULL, 'i' }, { 0, 0, 0, 0 }, }; - const char *sopts = "hVbnvd:"; + const char *sopts = "hVbnvd:bi:"; if (atexit(cleanup) != 0) fail("Failed to install cleanup handler.\n"); @@ -847,6 +861,13 @@ int main(int argc, char **argv) case 'd': delay = atoi(optarg); break; + case 'b': + batch = 1; + break; + case 'i': + iterations = atoi(optarg); + loop = 0; + break; } } @@ -855,28 +876,41 @@ int main(int argc, char **argv) if (xhandle == NULL) fail("Failed to initialize xenstat library\n"); - /* Begin curses stuff */ - initscr(); - start_color(); - cbreak(); - noecho(); - nonl(); - keypad(stdscr, TRUE); - halfdelay(5); - use_default_colors(); - init_pair(1, -1, COLOR_YELLOW); - - do { - gettimeofday(&curtime, NULL); - if(ch != ERR || (curtime.tv_sec - oldtime.tv_sec) >= delay) { - clear(); - top(); - oldtime = curtime; - refresh(); - } - ch = getch(); - } while (handle_key(ch)); - + if (!batch) { + /* Begin curses stuff */ + initscr(); + start_color(); + cbreak(); + noecho(); + nonl(); + keypad(stdscr, TRUE); + halfdelay(5); + use_default_colors(); + init_pair(1, -1, COLOR_YELLOW); + + do { + gettimeofday(&curtime, NULL); + if(ch != ERR || (curtime.tv_sec - oldtime.tv_sec) >= delay) { + clear(); + top(); + oldtime = curtime; + refresh(); + if ((!loop) && !(--iterations)) + break; + } + ch = getch(); + } while (handle_key(ch)); + } else { + do { + gettimeofday(&curtime, NULL); + top(); + oldtime = curtime; + sleep(delay); + if ((!loop) && !(--iterations)) + break; + } while (1); + } + /* Cleanup occurs in cleanup(), so no work to do here. */ return 0; diff -r c4b68afe97d3 -r 4b51d081378d tools/xm-test/tests/info/02_info_compiledata_pos.py --- a/tools/xm-test/tests/info/02_info_compiledata_pos.py Wed Jun 28 07:51:52 2006 -0600 +++ b/tools/xm-test/tests/info/02_info_compiledata_pos.py Wed Jun 28 07:52:21 2006 -0600 @@ -24,7 +24,8 @@ for line in lines: map[pieces[0]] = pieces[1] for field in ["cores_per_socket", "threads_per_core", "cpu_mhz", - "total_memory", "free_memory", "xen_major", "xen_minor"]: + "total_memory", "free_memory", "xen_major", "xen_minor", + "xen_pagesize"]: val = map[field] if not val.isdigit(): FAIL("Numeric field %s not all-numbers: %s" % (field, val)) diff -r c4b68afe97d3 -r 4b51d081378d xen/Makefile --- a/xen/Makefile Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/Makefile Wed Jun 28 07:52:21 2006 -0600 @@ -14,8 +14,8 @@ default: build .PHONY: dist dist: install -.PHONY: build install clean cscope TAGS tags -build install debug clean cscope TAGS tags:: +.PHONY: build install clean distclean cscope TAGS tags +build install debug clean distclean cscope TAGS tags:: make -f Rules.mk _$@ .PHONY: _build @@ -49,6 +49,10 @@ _clean: delete-unfresh-files rm -f include/asm *.o $(TARGET)* *~ core rm -f include/asm-*/asm-offsets.h rm -f include/xen/acm_policy.h + +.PHONY: _distclean +_distclean: clean + rm -f tags TAGS cscope.files cscope.in.out cscope.out cscope.po.out $(TARGET).gz: $(TARGET) gzip -f -9 < $< > $@.new @@ -132,11 +136,11 @@ endef .PHONY: _TAGS _TAGS: - $(all_sources) | etags - + rm -f TAGS && $(all_sources) | xargs etags -a .PHONY: _tags _tags: - $(all_sources) | xargs ctags + rm -f TAGS && $(all_sources) | xargs ctags -a .PHONY: _cscope _cscope: diff -r c4b68afe97d3 -r 4b51d081378d xen/arch/x86/dom0_ops.c --- a/xen/arch/x86/dom0_ops.c Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/arch/x86/dom0_ops.c Wed Jun 28 07:52:21 2006 -0600 @@ -194,6 +194,7 @@ long arch_do_dom0_op(struct dom0_op *op, pi->nr_nodes = 1; pi->total_pages = total_pages; pi->free_pages = avail_domheap_pages(); + pi->scrub_pages = avail_scrub_pages(); pi->cpu_khz = cpu_khz; memset(pi->hw_cap, 0, sizeof(pi->hw_cap)); memcpy(pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4); diff -r c4b68afe97d3 -r 4b51d081378d xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/arch/x86/hvm/svm/svm.c Wed Jun 28 07:52:21 2006 -0600 @@ -47,7 +47,6 @@ #include <asm/shadow_64.h> #endif #include <public/sched.h> -#include <public/hvm/ioreq.h> #define SVM_EXTRA_DEBUG @@ -66,8 +65,6 @@ extern int svm_instrlen(struct cpu_user_ extern int svm_instrlen(struct cpu_user_regs *regs, int mode); extern void svm_dump_inst(unsigned long eip); extern int svm_dbg_on; -void svm_manual_event_injection32(struct vcpu *v, struct cpu_user_regs *regs, - int vector, int has_code); void svm_dump_regs(const char *from, struct cpu_user_regs *regs); static void svm_relinquish_guest_resources(struct domain *d); @@ -215,17 +212,6 @@ static void svm_store_cpu_guest_regs( if ( regs != NULL ) { -#if defined (__x86_64__) - regs->rip = vmcb->rip; - regs->rsp = vmcb->rsp; - regs->rflags = vmcb->rflags; - regs->cs = vmcb->cs.sel; - regs->ds = vmcb->ds.sel; - regs->es = vmcb->es.sel; - regs->ss = vmcb->ss.sel; - regs->gs = vmcb->gs.sel; - regs->fs = vmcb->fs.sel; -#elif defined (__i386__) regs->eip = vmcb->rip; regs->esp = vmcb->rsp; regs->eflags = vmcb->rflags; @@ -235,14 +221,14 @@ static void svm_store_cpu_guest_regs( regs->ss = vmcb->ss.sel; regs->gs = vmcb->gs.sel; regs->fs = vmcb->fs.sel; -#endif } if ( crs != NULL ) { - crs[0] = vmcb->cr0; - crs[3] = vmcb->cr3; - crs[4] = vmcb->cr4; + /* Returning the guest's regs */ + crs[0] = v->arch.hvm_svm.cpu_shadow_cr0; + crs[3] = v->arch.hvm_svm.cpu_cr3; + crs[4] = v->arch.hvm_svm.cpu_shadow_cr4; } } @@ -258,13 +244,11 @@ static inline int long_mode_do_msr_read( { u64 msr_content = 0; struct vcpu *vc = current; - // struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content; struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb; switch (regs->ecx) { case MSR_EFER: - // msr_content = msr->msr_items[SVM_INDEX_MSR_EFER]; msr_content = vmcb->efer; msr_content &= ~EFER_SVME; break; @@ -813,7 +797,8 @@ void arch_svm_do_resume(struct vcpu *v) reset_stack_and_jump( svm_asm_do_resume ); } else { - printk("VCPU core pinned: %d to %d\n", + if (svm_dbg_on) + printk("VCPU core pinned: %d to %d\n", v->arch.hvm_svm.launch_core, smp_processor_id() ); v->arch.hvm_svm.launch_core = smp_processor_id(); svm_migrate_timers( v ); @@ -1008,6 +993,10 @@ static void svm_vmexit_do_cpuid(struct v clear_bit(X86_FEATURE_HT, &edx); /* clear the hyperthread bit */ ebx &= 0xFF00FFFF; /* clear the logical processor count when HTT=0 */ ebx |= 0x00010000; /* set to 1 just for precaution */ + + /* Disable machine check architecture */ + clear_bit(X86_FEATURE_MCA, &edx); + clear_bit(X86_FEATURE_MCE, &edx); } else if ( ( input > 0x00000005 ) && ( input < 0x80000000 ) ) { @@ -2582,7 +2571,7 @@ void walk_shadow_and_guest_pt(unsigned l spte = l1e_empty(); - // This is actually overkill - we only need to make sure the hl2 is in-sync. + /* This is actually overkill - we only need to make sure the hl2 is in-sync. */ shadow_sync_va(v, gva); gpte.l1 = 0; @@ -2812,8 +2801,11 @@ asmlinkage void svm_vmexit_handler(struc } case VMEXIT_EXCEPTION_DF: - printk("Guest double fault"); - BUG(); + /* Debug info to hopefully help debug WHY the guest double-faulted. */ + svm_dump_vmcb(__func__, vmcb); + svm_dump_regs(__func__, ®s); + svm_dump_inst(svm_rip2pointer(vmcb)); + svm_inject_exception(v, TRAP_double_fault, 1, 0); break; case VMEXIT_INTR: diff -r c4b68afe97d3 -r 4b51d081378d xen/arch/x86/hvm/vioapic.c --- a/xen/arch/x86/hvm/vioapic.c Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/arch/x86/hvm/vioapic.c Wed Jun 28 07:52:21 2006 -0600 @@ -40,6 +40,9 @@ #include <asm/hvm/support.h> #include <asm/current.h> +/* HACK: Route IRQ0 only to VCPU0 to prevent time jumps. */ +#define IRQ0_SPECIAL_ROUTING 1 + #if defined(__ia64__) #define opt_hvm_debug_level opt_vmx_debug_level #endif @@ -392,12 +395,12 @@ static void ioapic_deliver(hvm_vioapic_t uint8_t trig_mode = s->redirtbl[irqno].RedirForm.trigmod; uint32_t deliver_bitmask; - HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "IOAPIC deliver: " + HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "dest %x dest_mode %x delivery_mode %x vector %x trig_mode %x\n", dest, dest_mode, delivery_mode, vector, trig_mode); - deliver_bitmask = - ioapic_get_delivery_bitmask(s, dest, dest_mode, vector, delivery_mode); + deliver_bitmask = ioapic_get_delivery_bitmask( + s, dest, dest_mode, vector, delivery_mode); if (!deliver_bitmask) { HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic deliver " @@ -411,15 +414,19 @@ static void ioapic_deliver(hvm_vioapic_t { struct vlapic* target; - target = apic_round_robin( - s->domain, dest_mode, vector, deliver_bitmask); +#ifdef IRQ0_SPECIAL_ROUTING + if (irqno == 0) + target = s->lapic_info[0]; + else +#endif + target = apic_round_robin(s->domain, dest_mode, + vector, deliver_bitmask); if (target) ioapic_inj_irq(s, target, vector, trig_mode, delivery_mode); - else{ - HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic deliver " + else + HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "null round robin mask %x vector %x delivery_mode %x\n", deliver_bitmask, vector, deliver_bitmask); - } break; } @@ -429,6 +436,13 @@ static void ioapic_deliver(hvm_vioapic_t uint8_t bit; for (bit = 0; bit < s->lapic_count; bit++) { if (deliver_bitmask & (1 << bit)) { +#ifdef IRQ0_SPECIAL_ROUTING + if ( (irqno == 0) && (bit !=0) ) + { + printk("PIT irq to bit %x\n", bit); + domain_crash_synchronous(); + } +#endif if (s->lapic_info[bit]) { ioapic_inj_irq(s, s->lapic_info[bit], vector, trig_mode, delivery_mode); @@ -450,14 +464,9 @@ static void ioapic_deliver(hvm_vioapic_t static int ioapic_get_highest_irq(hvm_vioapic_t *s) { - uint32_t irqs; - - ASSERT(s); - - irqs = s->irr & ~s->isr & ~s->imr; - return __fls(irqs); -} - + uint32_t irqs = s->irr & ~s->isr & ~s->imr; + return fls(irqs) - 1; +} static void service_ioapic(hvm_vioapic_t *s) { diff -r c4b68afe97d3 -r 4b51d081378d xen/arch/x86/hvm/vlapic.c --- a/xen/arch/x86/hvm/vlapic.c Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/arch/x86/hvm/vlapic.c Wed Jun 28 07:52:21 2006 -0600 @@ -50,7 +50,7 @@ int vlapic_find_highest_irr(struct vlapi { int result; - result = find_highest_bit((uint32_t *)&vlapic->irr[0], INTR_LEN_32); + result = find_highest_bit(vlapic->irr, MAX_VECTOR); if ( result != -1 && result < 16 ) { @@ -79,14 +79,14 @@ int vlapic_find_highest_isr(struct vlapi { int result; - result = find_highest_bit((uint32_t *)&vlapic->isr[0], INTR_LEN_32); + result = find_highest_bit(vlapic->isr, MAX_VECTOR); if ( result != -1 && result < 16 ) { int i = 0; printk("VLAPIC: isr on reserved bits %d, isr is\n ", result); - for ( i = 0; i < INTR_LEN_32; i += 2 ) - printk("%d: 0x%08x%08x\n", i, vlapic->isr[i], vlapic->isr[i+1]); + for ( i = 0; i < ARRAY_SIZE(vlapic->isr); i++ ) + printk("%d: %p\n", i, (void *)vlapic->isr[i]); return -1; } @@ -212,18 +212,19 @@ static int vlapic_accept_irq(struct vcpu if ( test_and_set_bit(vector, &vlapic->irr[0]) ) { - printk("<vlapic_accept_irq>" - "level trig mode repeatedly for vector %d\n", vector); + HVM_DBG_LOG(DBG_LEVEL_VLAPIC, + "level trig mode repeatedly for vector %d\n", vector); break; } if ( level ) { - printk("<vlapic_accept_irq> level trig mode for vector %d\n", - vector); + HVM_DBG_LOG(DBG_LEVEL_VLAPIC, + "level trig mode for vector %d\n", vector); set_bit(vector, &vlapic->tmr[0]); } evtchn_set_pending(v, iopacket_port(v)); + result = 1; break; @@ -308,8 +309,15 @@ struct vlapic* apic_round_robin(struct d old = next = d->arch.hvm_domain.round_info[vector]; - do { - /* the vcpu array is arranged according to vcpu_id */ + /* the vcpu array is arranged according to vcpu_id */ + do + { + next++; + if ( !d->vcpu[next] || + !test_bit(_VCPUF_initialised, &d->vcpu[next]->vcpu_flags) || + next == MAX_VIRT_CPUS ) + next = 0; + if ( test_bit(next, &bitmap) ) { target = d->vcpu[next]->arch.hvm_vcpu.vlapic; @@ -321,12 +329,6 @@ struct vlapic* apic_round_robin(struct d } break; } - - next ++; - if ( !d->vcpu[next] || - !test_bit(_VCPUF_initialised, &d->vcpu[next]->vcpu_flags) || - next == MAX_VIRT_CPUS ) - next = 0; } while ( next != old ); d->arch.hvm_domain.round_info[vector] = next; @@ -896,7 +898,7 @@ vlapic_check_direct_intr(struct vcpu *v, struct vlapic *vlapic = VLAPIC(v); int type; - type = __fls(vlapic->direct_intr.deliver_mode); + type = fls(vlapic->direct_intr.deliver_mode) - 1; if ( type == -1 ) return -1; @@ -956,7 +958,7 @@ int cpu_has_apic_interrupt(struct vcpu* } return 0; } - + void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode) { struct vlapic *vlapic = VLAPIC(v); diff -r c4b68afe97d3 -r 4b51d081378d xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 28 07:52:21 2006 -0600 @@ -337,6 +337,7 @@ static void vmx_restore_msrs(struct vcpu clear_bit(i, &guest_flags); } } + #else /* __i386__ */ #define vmx_save_segments(v) ((void)0) @@ -355,6 +356,63 @@ static inline int long_mode_do_msr_write } #endif /* __i386__ */ + +#define loaddebug(_v,_reg) \ + __asm__ __volatile__ ("mov %0,%%db" #_reg : : "r" ((_v)->debugreg[_reg])) +#define savedebug(_v,_reg) \ + __asm__ __volatile__ ("mov %%db" #_reg ",%0" : : "r" ((_v)->debugreg[_reg])) + +static inline void vmx_save_dr(struct vcpu *v) +{ + if ( v->arch.hvm_vcpu.flag_dr_dirty ) + { + savedebug(&v->arch.guest_context, 0); + savedebug(&v->arch.guest_context, 1); + savedebug(&v->arch.guest_context, 2); + savedebug(&v->arch.guest_context, 3); + savedebug(&v->arch.guest_context, 6); + + v->arch.hvm_vcpu.flag_dr_dirty = 0; + + v->arch.hvm_vcpu.u.vmx.exec_control |= CPU_BASED_MOV_DR_EXITING; + __vmwrite(CPU_BASED_VM_EXEC_CONTROL, + v->arch.hvm_vcpu.u.vmx.exec_control); + } +} + +static inline void __restore_debug_registers(struct vcpu *v) +{ + loaddebug(&v->arch.guest_context, 0); + loaddebug(&v->arch.guest_context, 1); + loaddebug(&v->arch.guest_context, 2); + loaddebug(&v->arch.guest_context, 3); + /* No 4 and 5 */ + loaddebug(&v->arch.guest_context, 6); + /* DR7 is loaded from the vmcs. */ +} + +/* + * DR7 is saved and restored on every vmexit. Other debug registers only + * need to be restored if their value is going to affect execution -- i.e., + * if one of the breakpoints is enabled. So mask out all bits that don't + * enable some breakpoint functionality. + * + * This is in part necessary because bit 10 of DR7 is hardwired to 1, so a + * simple if( guest_dr7 ) will always return true. As long as we're masking, + * we might as well do it right. + */ +#define DR7_ACTIVE_MASK 0xff + +static inline void vmx_restore_dr(struct vcpu *v) +{ + unsigned long guest_dr7; + + __vmread(GUEST_DR7, &guest_dr7); + + /* Assumes guest does not have DR access at time of context switch. */ + if ( unlikely(guest_dr7 & DR7_ACTIVE_MASK) ) + __restore_debug_registers(v); +} static void vmx_freeze_time(struct vcpu *v) { @@ -371,11 +429,13 @@ static void vmx_ctxt_switch_from(struct vmx_freeze_time(v); vmx_save_segments(v); vmx_load_msrs(); + vmx_save_dr(v); } static void vmx_ctxt_switch_to(struct vcpu *v) { vmx_restore_msrs(v); + vmx_restore_dr(v); } void stop_vmx(void) @@ -866,55 +926,20 @@ static void vmx_vmexit_do_cpuid(struct c CASE_GET_REG_P(R15, r15) #endif -static void vmx_dr_access (unsigned long exit_qualification, struct cpu_user_regs *regs) -{ - unsigned int reg; - unsigned long *reg_p = 0; +static void vmx_dr_access(unsigned long exit_qualification, + struct cpu_user_regs *regs) +{ struct vcpu *v = current; - unsigned long eip; - - __vmread(GUEST_RIP, &eip); - - reg = exit_qualification & DEBUG_REG_ACCESS_NUM; - - HVM_DBG_LOG(DBG_LEVEL_1, - "vmx_dr_access : eip=%lx, reg=%d, exit_qualification = %lx", - eip, reg, exit_qualification); - - switch ( exit_qualification & DEBUG_REG_ACCESS_REG ) { - CASE_GET_REG_P(EAX, eax); - CASE_GET_REG_P(ECX, ecx); - CASE_GET_REG_P(EDX, edx); - CASE_GET_REG_P(EBX, ebx); - CASE_GET_REG_P(EBP, ebp); - CASE_GET_REG_P(ESI, esi); - CASE_GET_REG_P(EDI, edi); - CASE_EXTEND_GET_REG_P; - case REG_ESP: - break; - default: - __hvm_bug(regs); - } - - switch (exit_qualification & DEBUG_REG_ACCESS_TYPE) { - case TYPE_MOV_TO_DR: - /* don't need to check the range */ - if (reg != REG_ESP) - v->arch.guest_context.debugreg[reg] = *reg_p; - else { - unsigned long value; - __vmread(GUEST_RSP, &value); - v->arch.guest_context.debugreg[reg] = value; - } - break; - case TYPE_MOV_FROM_DR: - if (reg != REG_ESP) - *reg_p = v->arch.guest_context.debugreg[reg]; - else { - __vmwrite(GUEST_RSP, v->arch.guest_context.debugreg[reg]); - } - break; - } + + v->arch.hvm_vcpu.flag_dr_dirty = 1; + + /* We could probably be smarter about this */ + __restore_debug_registers(v); + + /* Allow guest direct access to DR registers */ + v->arch.hvm_vcpu.u.vmx.exec_control &= ~CPU_BASED_MOV_DR_EXITING; + __vmwrite(CPU_BASED_VM_EXEC_CONTROL, + v->arch.hvm_vcpu.u.vmx.exec_control); } /* @@ -2080,10 +2105,19 @@ asmlinkage void vmx_vmexit_handler(struc { void store_cpu_user_regs(struct cpu_user_regs *regs); - store_cpu_user_regs(®s); - __vm_clear_bit(GUEST_PENDING_DBG_EXCEPTIONS, PENDING_DEBUG_EXC_BS); - - domain_pause_for_debugger(); + if ( test_bit(_DOMF_debugging, &v->domain->domain_flags) ) + { + store_cpu_user_regs(®s); + domain_pause_for_debugger(); + __vm_clear_bit(GUEST_PENDING_DBG_EXCEPTIONS, + PENDING_DEBUG_EXC_BS); + } + else + { + vmx_reflect_exception(v); + __vm_clear_bit(GUEST_PENDING_DBG_EXCEPTIONS, + PENDING_DEBUG_EXC_BS); + } break; } @@ -2139,9 +2173,17 @@ asmlinkage void vmx_vmexit_handler(struc vmx_vmexit_do_extint(®s); break; case EXIT_REASON_PENDING_INTERRUPT: + /* + * Not sure exactly what the purpose of this is. The only bits set + * and cleared at this point are CPU_BASED_VIRTUAL_INTR_PENDING. + * (in io.c:{enable,disable}_irq_window(). So presumably we want to + * set it to the original value... + */ + v->arch.hvm_vcpu.u.vmx.exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING; + v->arch.hvm_vcpu.u.vmx.exec_control |= + (MONITOR_CPU_BASED_EXEC_CONTROLS & CPU_BASED_VIRTUAL_INTR_PENDING); __vmwrite(CPU_BASED_VM_EXEC_CONTROL, - MONITOR_CPU_BASED_EXEC_CONTROLS); - v->arch.hvm_vcpu.u.vmx.exec_control = MONITOR_CPU_BASED_EXEC_CONTROLS; + v->arch.hvm_vcpu.u.vmx.exec_control); break; case EXIT_REASON_TASK_SWITCH: __hvm_bug(®s); diff -r c4b68afe97d3 -r 4b51d081378d xen/arch/x86/microcode.c --- a/xen/arch/x86/microcode.c Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/arch/x86/microcode.c Wed Jun 28 07:52:21 2006 -0600 @@ -83,9 +83,9 @@ #include <asm/processor.h> #define pr_debug(x...) ((void)0) -#define DECLARE_MUTEX(_m) DEFINE_SPINLOCK(_m) -#define down(_m) spin_lock(_m) -#define up(_m) spin_unlock(_m) +#define DEFINE_MUTEX(_m) DEFINE_SPINLOCK(_m) +#define mutex_lock(_m) spin_lock(_m) +#define mutex_unlock(_m) spin_unlock(_m) #define vmalloc(_s) xmalloc_bytes(_s) #define vfree(_p) xfree(_p) @@ -95,7 +95,10 @@ MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL"); #endif -#define MICROCODE_VERSION "1.14" +static int verbose; +boolean_param("microcode.verbose", verbose); + +#define MICROCODE_VERSION "1.14a" #define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ #define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */ @@ -119,21 +122,22 @@ static DEFINE_SPINLOCK(microcode_update_ static DEFINE_SPINLOCK(microcode_update_lock); /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ -static DECLARE_MUTEX(microcode_sem); +static DEFINE_MUTEX(microcode_mutex); static void __user *user_buffer; /* user area microcode data buffer */ static unsigned int user_buffer_size; /* it's size */ typedef enum mc_error_code { MC_SUCCESS = 0, - MC_NOTFOUND = 1, - MC_MARKED = 2, - MC_ALLOCATED = 3, + MC_IGNORED = 1, + MC_NOTFOUND = 2, + MC_MARKED = 3, + MC_ALLOCATED = 4, } mc_error_code_t; static struct ucode_cpu_info { unsigned int sig; - unsigned int pf; + unsigned int pf, orig_pf; unsigned int rev; unsigned int cksum; mc_error_code_t err; @@ -163,6 +167,7 @@ static void collect_cpu_info (void *unus rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); uci->pf = 1 << ((val[1] >> 18) & 7); } + uci->orig_pf = uci->pf; } wrmsr(MSR_IA32_UCODE_REV, 0, 0); @@ -196,23 +201,34 @@ static inline void mark_microcode_update pr_debug(" Checksum 0x%x\n", cksum); if (mc_header->rev < uci->rev) { - printk(KERN_ERR "microcode: CPU%d not 'upgrading' to earlier revision" - " 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); - goto out; + if (uci->err == MC_NOTFOUND) { + uci->err = MC_IGNORED; + uci->cksum = mc_header->rev; + } else if (uci->err == MC_IGNORED && uci->cksum < mc_header->rev) + uci->cksum = mc_header->rev; } else if (mc_header->rev == uci->rev) { - /* notify the caller of success on this cpu */ - uci->err = MC_SUCCESS; - printk(KERN_ERR "microcode: CPU%d already at revision" - " 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); - goto out; - } - - pr_debug("microcode: CPU%d found a matching microcode update with " - " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); - uci->cksum = cksum; - uci->pf = pf; /* keep the original mc pf for cksum calculation */ - uci->err = MC_MARKED; /* found the match */ -out: + if (uci->err < MC_MARKED) { + /* notify the caller of success on this cpu */ + uci->err = MC_SUCCESS; + } + } else if (uci->err != MC_ALLOCATED || mc_header->rev > uci->mc->hdr.rev) { + pr_debug("microcode: CPU%d found a matching microcode update with " + " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); + uci->cksum = cksum; + uci->pf = pf; /* keep the original mc pf for cksum calculation */ + uci->err = MC_MARKED; /* found the match */ + for_each_online_cpu(cpu_num) { + if (ucode_cpu_info + cpu_num != uci + && ucode_cpu_info[cpu_num].mc == uci->mc) { + uci->mc = NULL; + break; + } + } + if (uci->mc != NULL) { + vfree(uci->mc); + uci->mc = NULL; + } + } return; } @@ -251,13 +267,11 @@ static int find_matching_ucodes (void) error = -EINVAL; goto out; } - - for (cpu_num = 0; cpu_num < num_online_cpus(); cpu_num++) { + + for_each_online_cpu(cpu_num) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; - if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/ - continue; - - if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->pf)) + + if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->orig_pf)) mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum); } @@ -294,18 +308,19 @@ static int find_matching_ucodes (void) error = -EFAULT; goto out; } - for (cpu_num = 0; cpu_num < num_online_cpus(); cpu_num++) { + for_each_online_cpu(cpu_num) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; - if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/ - continue; - if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->pf)) { + + if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->orig_pf)) { mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum); } } } } /* now check if any cpu has matched */ - for (cpu_num = 0, allocated_flag = 0, sum = 0; cpu_num < num_online_cpus(); cpu_num++) { + allocated_flag = 0; + sum = 0; + for_each_online_cpu(cpu_num) { if (ucode_cpu_info[cpu_num].err == MC_MARKED) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; if (!allocated_flag) { @@ -367,7 +382,13 @@ static void do_update_one (void * unused struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; if (uci->mc == NULL) { - printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num); + if (verbose) { + if (uci->err == MC_SUCCESS) + printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n", + cpu_num, uci->rev); + else + printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num); + } return; } @@ -416,16 +437,19 @@ static int do_microcode_update (void) } out_free: - for (i = 0; i < num_online_cpus(); i++) { + for_each_online_cpu(i) { if (ucode_cpu_info[i].mc) { int j; void *tmp = ucode_cpu_info[i].mc; vfree(tmp); - for (j = i; j < num_online_cpus(); j++) { + for_each_online_cpu(j) { if (ucode_cpu_info[j].mc == tmp) ucode_cpu_info[j].mc = NULL; } } + if (ucode_cpu_info[i].err == MC_IGNORED && verbose) + printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision" + " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev); } out: return error; @@ -433,21 +457,21 @@ out: int microcode_update(void *buf, unsigned long len) { - int ret; - - if (len < DEFAULT_UCODE_TOTALSIZE) { - printk(KERN_ERR "microcode: not enough data\n"); - return -EINVAL; - } - - down(µcode_sem); - - user_buffer = (void __user *) buf; - user_buffer_size = (int) len; - - ret = do_microcode_update(); - - up(µcode_sem); - - return ret; -} + int ret; + + if (len < DEFAULT_UCODE_TOTALSIZE) { + printk(KERN_ERR "microcode: not enough data\n"); + return -EINVAL; + } + + mutex_lock(µcode_mutex); + + user_buffer = (void __user *) buf; + user_buffer_size = (int) len; + + ret = do_microcode_update(); + + mutex_unlock(µcode_mutex); + + return ret; +} diff -r c4b68afe97d3 -r 4b51d081378d xen/arch/x86/oprofile/nmi_int.c --- a/xen/arch/x86/oprofile/nmi_int.c Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/arch/x86/oprofile/nmi_int.c Wed Jun 28 07:52:21 2006 -0600 @@ -269,7 +269,7 @@ static int __init p4_init(char * cpu_typ { __u8 cpu_model = current_cpu_data.x86_model; - if (cpu_model > 4) + if ((cpu_model > 6) || (cpu_model == 5)) return 0; #ifndef CONFIG_SMP diff -r c4b68afe97d3 -r 4b51d081378d xen/arch/x86/oprofile/xenoprof.c --- a/xen/arch/x86/oprofile/xenoprof.c Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/arch/x86/oprofile/xenoprof.c Wed Jun 28 07:52:21 2006 -0600 @@ -13,9 +13,13 @@ /* Limit amount of pages used for shared buffer (per domain) */ #define MAX_OPROF_SHARED_PAGES 32 -domid_t active_domains[MAX_OPROF_DOMAINS]; +struct domain *active_domains[MAX_OPROF_DOMAINS]; int active_ready[MAX_OPROF_DOMAINS]; unsigned int adomains; + +struct domain *passive_domains[MAX_OPROF_DOMAINS]; +unsigned int pdomains; + unsigned int activated; struct domain *primary_profiler; int xenoprof_state = XENOPROF_IDLE; @@ -25,6 +29,7 @@ u64 corrupted_buffer_samples; u64 corrupted_buffer_samples; u64 lost_samples; u64 active_samples; +u64 passive_samples; u64 idle_samples; u64 others_samples; @@ -44,9 +49,15 @@ int is_active(struct domain *d) return ((x != NULL) && (x->domain_type == XENOPROF_DOMAIN_ACTIVE)); } +int is_passive(struct domain *d) +{ + struct xenoprof *x = d->xenoprof; + return ((x != NULL) && (x->domain_type == XENOPROF_DOMAIN_PASSIVE)); +} + int is_profiled(struct domain *d) { - return is_active(d); + return (is_active(d) || is_passive(d)); } static void xenoprof_reset_stat(void) @@ -56,6 +67,7 @@ static void xenoprof_reset_stat(void) corrupted_buffer_samples = 0; lost_samples = 0; active_samples = 0; + passive_samples = 0; idle_samples = 0; others_samples = 0; } @@ -83,13 +95,122 @@ static void xenoprof_reset_buf(struct do } } +char *alloc_xenoprof_buf(struct domain *d, int npages) +{ + char *rawbuf; + int i, order; + + /* allocate pages to store sample buffer shared with domain */ + order = get_order_from_pages(npages); + rawbuf = alloc_xenheap_pages(order); + if ( rawbuf == NULL ) + { + printk("alloc_xenoprof_buf(): memory allocation failed\n"); + return 0; + } + + /* Share pages so that kernel can map it */ + for ( i = 0; i < npages; i++ ) + share_xen_page_with_guest( + virt_to_page(rawbuf + i * PAGE_SIZE), + d, XENSHARE_writable); + + return rawbuf; +} + +int alloc_xenoprof_struct(struct domain *d, int max_samples, int is_passive) +{ + struct vcpu *v; + int nvcpu, npages, bufsize, max_bufsize; + int i; + + d->xenoprof = xmalloc(struct xenoprof); + + if ( d->xenoprof == NULL ) + { + printk ("alloc_xenoprof_struct(): memory " + "allocation (xmalloc) failed\n"); + return -ENOMEM; + } + + memset(d->xenoprof, 0, sizeof(*d->xenoprof)); + + nvcpu = 0; + for_each_vcpu ( d, v ) + nvcpu++; + + /* reduce buffer size if necessary to limit pages allocated */ + bufsize = sizeof(struct xenoprof_buf) + + (max_samples - 1) * sizeof(struct event_log); + max_bufsize = (MAX_OPROF_SHARED_PAGES * PAGE_SIZE) / nvcpu; + if ( bufsize > max_bufsize ) + { + bufsize = max_bufsize; + max_samples = ( (max_bufsize - sizeof(struct xenoprof_buf)) / + sizeof(struct event_log) ) + 1; + } + + npages = (nvcpu * bufsize - 1) / PAGE_SIZE + 1; + + d->xenoprof->rawbuf = alloc_xenoprof_buf(is_passive ? dom0 : d, npages); + + if ( d->xenoprof->rawbuf == NULL ) + { + xfree(d->xenoprof); + d->xenoprof = NULL; + return -ENOMEM; + } + + d->xenoprof->npages = npages; + d->xenoprof->nbuf = nvcpu; + d->xenoprof->bufsize = bufsize; + d->xenoprof->domain_ready = 0; + d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED; + + /* Update buffer pointers for active vcpus */ + i = 0; + for_each_vcpu ( d, v ) + { + d->xenoprof->vcpu[v->vcpu_id].event_size = max_samples; + d->xenoprof->vcpu[v->vcpu_id].buffer = + (struct xenoprof_buf *)&d->xenoprof->rawbuf[i * bufsize]; + d->xenoprof->vcpu[v->vcpu_id].buffer->event_size = max_samples; + d->xenoprof->vcpu[v->vcpu_id].buffer->vcpu_id = v->vcpu_id; + + i++; + /* in the unlikely case that the number of active vcpus changes */ + if ( i >= nvcpu ) + break; + } + + return 0; +} + +void free_xenoprof_pages(struct domain *d) +{ + struct xenoprof *x; + int order; + + x = d->xenoprof; + if ( x == NULL ) + return; + + if ( x->rawbuf != NULL ) + { + order = get_order_from_pages(x->npages); + free_xenheap_pages(x->rawbuf, order); + } + + xfree(x); + d->xenoprof = NULL; +} + int active_index(struct domain *d) { int i; - domid_t id = d->domain_id; for ( i = 0; i < adomains; i++ ) - if ( active_domains[i] == id ) + if ( active_domains[i] == d ) return i; return -1; @@ -132,47 +253,116 @@ int reset_active(struct domain *d) x->domain_ready = 0; x->domain_type = XENOPROF_DOMAIN_IGNORED; active_ready[ind] = 0; + active_domains[ind] = NULL; activated--; + put_domain(d); + if ( activated <= 0 ) adomains = 0; return 0; } -int reset_active_list(void) +void reset_passive(struct domain *d) +{ + struct xenoprof *x; + + if (d==0) + return; + + x = d->xenoprof; + if ( x == NULL ) + return; + + x->domain_type = XENOPROF_DOMAIN_IGNORED; + + return; +} + +void reset_active_list(void) { int i; - struct domain *d; for ( i = 0; i < adomains; i++ ) { if ( active_ready[i] ) { - d = find_domain_by_id(active_domains[i]); - if ( d != NULL ) - { - reset_active(d); - put_domain(d); - } + reset_active(active_domains[i]); } } adomains = 0; activated = 0; - - return 0; +} + +void reset_passive_list(void) +{ + int i; + + for ( i = 0; i < pdomains; i++ ) + { + reset_passive(passive_domains[i]); + put_domain(passive_domains[i]); + passive_domains[i] = NULL; + } + + pdomains = 0; } int add_active_list (domid_t domid) { + struct domain *d; + if ( adomains >= MAX_OPROF_DOMAINS ) return -E2BIG; - active_domains[adomains] = domid; + d = find_domain_by_id(domid); + if ( d == NULL ) + return -EINVAL; + + active_domains[adomains] = d; active_ready[adomains] = 0; adomains++; return 0; +} + +int add_passive_list(XEN_GUEST_HANDLE(void) arg) +{ + struct xenoprof_passive passive; + struct domain *d; + int ret = 0; + + if ( pdomains >= MAX_OPROF_DOMAINS ) + return -E2BIG; + + if ( copy_from_guest(&passive, arg, 1) ) + return -EFAULT; + + d = find_domain_by_id(passive.domain_id); + if ( d == NULL ) + return -EINVAL; + + if ( (d->xenoprof == NULL) && + ((ret = alloc_xenoprof_struct(d, passive.max_samples, 1)) < 0) ) { + put_domain(d); + return -ENOMEM; + } + + d->xenoprof->domain_type = XENOPROF_DOMAIN_PASSIVE; + passive.nbuf = d->xenoprof->nbuf; + passive.bufsize = d->xenoprof->bufsize; + passive.buf_maddr = __pa(d->xenoprof->rawbuf); + + if ( copy_to_guest(arg, &passive, 1) ) { + put_domain(d); + return -EFAULT; + } + + passive_domains[pdomains] = d; + pdomains++; + + return ret; } void xenoprof_log_event( @@ -231,7 +421,10 @@ void xenoprof_log_event( if ( head >= size ) head = 0; buf->event_head = head; - active_samples++; + if ( is_active(vcpu->domain) ) + active_samples++; + else + passive_samples++; if ( mode == 0 ) buf->user_samples++; else if ( mode == 1 ) @@ -241,114 +434,6 @@ void xenoprof_log_event( } } -char *alloc_xenoprof_buf(struct domain *d, int npages) -{ - char *rawbuf; - int i, order; - - /* allocate pages to store sample buffer shared with domain */ - order = get_order_from_pages(npages); - rawbuf = alloc_xenheap_pages(order); - if ( rawbuf == NULL ) - { - printk("alloc_xenoprof_buf(): memory allocation failed\n"); - return 0; - } - - /* Share pages so that kernel can map it */ - for ( i = 0; i < npages; i++ ) - share_xen_page_with_guest( - virt_to_page(rawbuf + i * PAGE_SIZE), - d, XENSHARE_writable); - - return rawbuf; -} - -int alloc_xenoprof_struct(struct domain *d, int max_samples) -{ - struct vcpu *v; - int nvcpu, npages, bufsize, max_bufsize; - int i; - - d->xenoprof = xmalloc(struct xenoprof); - - if ( d->xenoprof == NULL ) - { - printk ("alloc_xenoprof_struct(): memory " - "allocation (xmalloc) failed\n"); - return -ENOMEM; - } - - memset(d->xenoprof, 0, sizeof(*d->xenoprof)); - - nvcpu = 0; - for_each_vcpu ( d, v ) - nvcpu++; - - /* reduce buffer size if necessary to limit pages allocated */ - bufsize = sizeof(struct xenoprof_buf) + - (max_samples - 1) * sizeof(struct event_log); - max_bufsize = (MAX_OPROF_SHARED_PAGES * PAGE_SIZE) / nvcpu; - if ( bufsize > max_bufsize ) - { - bufsize = max_bufsize; - max_samples = ( (max_bufsize - sizeof(struct xenoprof_buf)) / - sizeof(struct event_log) ) + 1; - } - - npages = (nvcpu * bufsize - 1) / PAGE_SIZE + 1; - d->xenoprof->rawbuf = alloc_xenoprof_buf(d, npages); - if ( d->xenoprof->rawbuf == NULL ) - { - xfree(d->xenoprof); - d->xenoprof = NULL; - return -ENOMEM; - } - - d->xenoprof->npages = npages; - d->xenoprof->nbuf = nvcpu; - d->xenoprof->bufsize = bufsize; - d->xenoprof->domain_ready = 0; - d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED; - - /* Update buffer pointers for active vcpus */ - i = 0; - for_each_vcpu ( d, v ) - { - d->xenoprof->vcpu[v->vcpu_id].event_size = max_samples; - d->xenoprof->vcpu[v->vcpu_id].buffer = - (struct xenoprof_buf *)&d->xenoprof->rawbuf[i * bufsize]; - d->xenoprof->vcpu[v->vcpu_id].buffer->event_size = max_samples; - d->xenoprof->vcpu[v->vcpu_id].buffer->vcpu_id = v->vcpu_id; - - i++; - /* in the unlikely case that the number of active vcpus changes */ - if ( i >= nvcpu ) - break; - } - - return 0; -} - -void free_xenoprof_pages(struct domain *d) -{ - struct xenoprof *x; - int order; - - x = d->xenoprof; - if ( x == NULL ) - return; - - if ( x->rawbuf != NULL ) - { - order = get_order_from_pages(x->npages); - free_xenheap_pages(x->rawbuf, order); - } - - xfree(x); - d->xenoprof = NULL; -} - int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg) { struct xenoprof_init xenoprof_init; @@ -373,7 +458,7 @@ int xenoprof_op_init(XEN_GUEST_HANDLE(vo * is called. Memory is then kept until domain is destroyed. */ if ( (d->xenoprof == NULL) && - ((ret = alloc_xenoprof_struct(d, xenoprof_init.max_samples)) < 0) ) + ((ret = alloc_xenoprof_struct(d, xenoprof_init.max_samples, 0)) < 0) ) goto err; xenoprof_reset_buf(d); @@ -429,7 +514,14 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN case XENOPROF_reset_active_list: { - ret = reset_active_list(); + reset_active_list(); + ret = 0; + break; + } + case XENOPROF_reset_passive_list: + { + reset_passive_list(); + ret = 0; break; } case XENOPROF_set_active: @@ -440,6 +532,13 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN if ( copy_from_guest(&domid, arg, 1) ) return -EFAULT; ret = add_active_list(domid); + break; + } + case XENOPROF_set_passive: + { + if ( xenoprof_state != XENOPROF_IDLE ) + return -EPERM; + ret = add_passive_list(arg); break; } case XENOPROF_reserve_counters: @@ -484,14 +583,20 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN break; case XENOPROF_enable_virq: + { + int i; if ( current->domain == primary_profiler ) { nmi_enable_virq(); xenoprof_reset_stat(); + for ( i = 0; i < pdomains; i++ ) { + xenoprof_reset_buf(passive_domains[i]); + } } xenoprof_reset_buf(current->domain); ret = set_active(current->domain); break; + } case XENOPROF_start: ret = -EPERM; @@ -525,6 +630,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN xenoprof_state = XENOPROF_IDLE; nmi_release_counters(); nmi_disable_virq(); + reset_passive_list(); ret = 0; } break; diff -r c4b68afe97d3 -r 4b51d081378d xen/arch/x86/smp.c --- a/xen/arch/x86/smp.c Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/arch/x86/smp.c Wed Jun 28 07:52:21 2006 -0600 @@ -302,8 +302,9 @@ int on_selected_cpus( static void stop_this_cpu (void *dummy) { - clear_bit(smp_processor_id(), &cpu_online_map); - + cpu_clear(smp_processor_id(), cpu_online_map); + + local_irq_disable(); disable_local_APIC(); for ( ; ; ) diff -r c4b68afe97d3 -r 4b51d081378d xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/arch/x86/x86_emulate.c Wed Jun 28 07:52:21 2006 -0600 @@ -374,9 +374,8 @@ do{ __asm__ __volatile__ ( /* Access/update address held in a register, based on addressing mode. */ #define register_address(sel, reg) \ - ((ad_bytes == sizeof(unsigned long)) ? (reg) : \ - ((mode == X86EMUL_MODE_REAL) ? /* implies ad_bytes == 2 */ \ - (((unsigned long)(sel) << 4) + ((reg) & 0xffff)) : \ + (((mode == X86EMUL_MODE_REAL) ? ((unsigned long)(sel) << 4) : 0) + \ + ((ad_bytes == sizeof(unsigned long)) ? (reg) : \ ((reg) & ((1UL << (ad_bytes << 3)) - 1)))) #define register_address_increment(reg, inc) \ do { \ @@ -510,10 +509,6 @@ x86_emulate_memop( } done_prefixes: - /* Note quite the same as 80386 real mode, but hopefully good enough. */ - if ( (mode == X86EMUL_MODE_REAL) && (ad_bytes != 2) ) - goto cannot_emulate; - /* REX prefix. */ if ( (mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40) ) { diff -r c4b68afe97d3 -r 4b51d081378d xen/common/kernel.c --- a/xen/common/kernel.c Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/common/kernel.c Wed Jun 28 07:52:21 2006 -0600 @@ -212,6 +212,11 @@ long do_xen_version(int cmd, XEN_GUEST_H return 0; } + case XENVER_pagesize: + { + return (!guest_handle_is_null(arg) ? -EINVAL : PAGE_SIZE); + } + } return -ENOSYS; diff -r c4b68afe97d3 -r 4b51d081378d xen/common/page_alloc.c --- a/xen/common/page_alloc.c Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/common/page_alloc.c Wed Jun 28 07:52:21 2006 -0600 @@ -61,6 +61,7 @@ custom_param("lowmem_emergency_pool", pa static DEFINE_SPINLOCK(page_scrub_lock); LIST_HEAD(page_scrub_list); +static unsigned long scrub_pages; /********************* * ALLOCATION BITMAP @@ -696,6 +697,7 @@ void free_domheap_pages(struct page_info { spin_lock(&page_scrub_lock); list_add(&pg[i].list, &page_scrub_list); + scrub_pages++; spin_unlock(&page_scrub_lock); } } @@ -784,9 +786,10 @@ static void page_scrub_softirq(void) /* Remove peeled pages from the list. */ ent->next->prev = &page_scrub_list; page_scrub_list.next = ent->next; - + scrub_pages -= (i+1); + spin_unlock(&page_scrub_lock); - + /* Working backwards, scrub each page in turn. */ while ( ent != &page_scrub_list ) { @@ -798,6 +801,11 @@ static void page_scrub_softirq(void) free_heap_pages(pfn_dom_zone_type(page_to_mfn(pg)), pg, 0); } } while ( (NOW() - start) < MILLISECS(1) ); +} + +unsigned long avail_scrub_pages(void) +{ + return scrub_pages; } static __init int page_scrub_init(void) diff -r c4b68afe97d3 -r 4b51d081378d xen/include/asm-x86/bitops.h --- a/xen/include/asm-x86/bitops.h Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/include/asm-x86/bitops.h Wed Jun 28 07:52:21 2006 -0600 @@ -335,8 +335,6 @@ static inline unsigned long ffz(unsigned return word; } -#define fls64(x) generic_fls64(x) - /** * ffs - find first bit set * @x: the word to search @@ -345,15 +343,15 @@ static inline unsigned long ffz(unsigned * the libc and compiler builtin ffs routines, therefore * differs in spirit from the above ffz (man ffs). */ -static inline int ffs(int x) -{ - int r; - - __asm__("bsfl %1,%0\n\t" +static inline int ffs(unsigned long x) +{ + long r; + + __asm__("bsf %1,%0\n\t" "jnz 1f\n\t" - "movl $-1,%0\n" + "mov $-1,%0\n" "1:" : "=r" (r) : "rm" (x)); - return r+1; + return (int)r+1; } /** @@ -362,15 +360,15 @@ static inline int ffs(int x) * * This is defined the same way as ffs. */ -static inline int fls(int x) -{ - int r; - - __asm__("bsrl %1,%0\n\t" +static inline int fls(unsigned long x) +{ + long r; + + __asm__("bsr %1,%0\n\t" "jnz 1f\n\t" - "movl $-1,%0\n" + "mov $-1,%0\n" "1:" : "=r" (r) : "rm" (x)); - return r+1; + return (int)r+1; } /** diff -r c4b68afe97d3 -r 4b51d081378d xen/include/asm-x86/hvm/vcpu.h --- a/xen/include/asm-x86/hvm/vcpu.h Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/include/asm-x86/hvm/vcpu.h Wed Jun 28 07:52:21 2006 -0600 @@ -38,6 +38,9 @@ struct hvm_vcpu { /* For AP startup */ unsigned long init_sipi_sipi_state; + /* Flags */ + int flag_dr_dirty; + union { struct arch_vmx_struct vmx; struct arch_svm_struct svm; diff -r c4b68afe97d3 -r 4b51d081378d xen/include/asm-x86/hvm/vlapic.h --- a/xen/include/asm-x86/hvm/vlapic.h Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/include/asm-x86/hvm/vlapic.h Wed Jun 28 07:52:21 2006 -0600 @@ -23,52 +23,12 @@ #include <asm/msr.h> #include <public/hvm/ioreq.h> -#if defined(__i386__) || defined(__x86_64__) -static inline int __fls(uint32_t word) +static __inline__ int find_highest_bit(unsigned long *data, int nr_bits) { - int bit; - - __asm__("bsrl %1,%0" - :"=r" (bit) - :"rm" (word)); - return word ? bit : -1; -} -#else -#define __fls(x) generic_fls(x) -static __inline__ int generic_fls(uint32_t x) -{ - int r = 31; - - if (!x) - return -1; - if (!(x & 0xffff0000u)) { - x <<= 16; - r -= 16; - } - if (!(x & 0xff000000u)) { - x <<= 8; - r -= 8; - } - if (!(x & 0xf0000000u)) { - x <<= 4; - r -= 4; - } - if (!(x & 0xc0000000u)) { - x <<= 2; - r -= 2; - } - if (!(x & 0x80000000u)) { - x <<= 1; - r -= 1; - } - return r; -} -#endif - -static __inline__ int find_highest_bit(uint32_t *data, int length) -{ - while(length && !data[--length]); - return __fls(data[length]) + 32 * length; + int length = BITS_TO_LONGS(nr_bits); + while ( length && !data[--length] ) + continue; + return (fls(data[length]) - 1) + (length * BITS_PER_LONG); } #define VLAPIC(v) (v->arch.hvm_vcpu.vlapic) @@ -146,17 +106,17 @@ typedef struct direct_intr_info { int source[6]; } direct_intr_info_t; -struct vlapic -{ - //FIXME check what would be 64 bit on EM64T +#define MAX_VECTOR 256 + +struct vlapic { uint32_t version; uint32_t status; uint32_t id; uint32_t vcpu_id; unsigned long base_address; - uint32_t isr[8]; - uint32_t irr[INTR_LEN_32]; - uint32_t tmr[INTR_LEN_32]; + unsigned long isr[BITS_TO_LONGS(MAX_VECTOR)]; + unsigned long irr[BITS_TO_LONGS(MAX_VECTOR)]; + unsigned long tmr[BITS_TO_LONGS(MAX_VECTOR)]; uint32_t task_priority; uint32_t processor_priority; uint32_t logical_dest; diff -r c4b68afe97d3 -r 4b51d081378d xen/include/public/dom0_ops.h --- a/xen/include/public/dom0_ops.h Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/include/public/dom0_ops.h Wed Jun 28 07:52:21 2006 -0600 @@ -231,6 +231,7 @@ struct dom0_physinfo { uint32_t cpu_khz; uint64_t total_pages; uint64_t free_pages; + uint64_t scrub_pages; uint32_t hw_cap[8]; }; typedef struct dom0_physinfo dom0_physinfo_t; diff -r c4b68afe97d3 -r 4b51d081378d xen/include/public/hvm/ioreq.h --- a/xen/include/public/hvm/ioreq.h Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/include/public/hvm/ioreq.h Wed Jun 28 07:52:21 2006 -0600 @@ -58,11 +58,6 @@ struct ioreq { }; typedef struct ioreq ioreq_t; -#define MAX_VECTOR 256 -#define BITS_PER_BYTE 8 -#define INTR_LEN (MAX_VECTOR/(BITS_PER_BYTE * sizeof(uint64_t))) -#define INTR_LEN_32 (MAX_VECTOR/(BITS_PER_BYTE * sizeof(uint32_t))) - struct global_iodata { uint16_t pic_elcr; uint16_t pic_irr; diff -r c4b68afe97d3 -r 4b51d081378d xen/include/public/io/netif.h --- a/xen/include/public/io/netif.h Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/include/public/io/netif.h Wed Jun 28 07:52:21 2006 -0600 @@ -19,6 +19,16 @@ * the appropriate req_event or rsp_event field in the shared ring. */ +/* + * This is the 'wire' format for packets: + * Request 1: netif_tx_request -- NETTXF_* (any flags) + * [Request 2: netif_tx_extra] (only if request 1 has NETTXF_extra_info) + * Request 3: netif_tx_request -- NETTXF_more_data + * Request 4: netif_tx_request -- NETTXF_more_data + * ... + * Request N: netif_tx_request -- 0 + */ + /* Protocol checksum field is blank in the packet (hardware offload)? */ #define _NETTXF_csum_blank (0) #define NETTXF_csum_blank (1U<<_NETTXF_csum_blank) @@ -27,9 +37,16 @@ #define _NETTXF_data_validated (1) #define NETTXF_data_validated (1U<<_NETTXF_data_validated) -/* Packet continues in the request. */ +/* Packet continues in the next request descriptor. */ #define _NETTXF_more_data (2) #define NETTXF_more_data (1U<<_NETTXF_more_data) + +/* Packet has GSO fields in the following descriptor (netif_tx_extra.u.gso). */ +#define _NETTXF_gso (3) +#define NETTXF_gso (1U<<_NETTXF_gso) + +/* This descriptor is followed by an extra-info descriptor (netif_tx_extra). */ +#define NETTXF_extra_info (NETTXF_gso) struct netif_tx_request { grant_ref_t gref; /* Reference to buffer page */ @@ -39,6 +56,18 @@ struct netif_tx_request { uint16_t size; /* Packet size in bytes. */ }; typedef struct netif_tx_request netif_tx_request_t; + +/* This structure needs to fit within netif_tx_request for compatibility. */ +struct netif_tx_extra { + union { + /* NETTXF_gso: Generic Segmentation Offload. */ + struct netif_tx_gso { + uint16_t size; /* GSO MSS. */ + uint16_t segs; /* GSO segment count. */ + uint16_t type; /* GSO type. */ + } gso; + } u; +}; struct netif_tx_response { uint16_t id; @@ -78,6 +107,8 @@ DEFINE_RING_TYPES(netif_rx, struct netif #define NETIF_RSP_DROPPED -2 #define NETIF_RSP_ERROR -1 #define NETIF_RSP_OKAY 0 +/* No response: used for auxiliary requests (e.g., netif_tx_extra). */ +#define NETIF_RSP_NULL 1 #endif diff -r c4b68afe97d3 -r 4b51d081378d xen/include/public/version.h --- a/xen/include/public/version.h Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/include/public/version.h Wed Jun 28 07:52:21 2006 -0600 @@ -10,7 +10,7 @@ #ifndef __XEN_PUBLIC_VERSION_H__ #define __XEN_PUBLIC_VERSION_H__ -/* NB. All ops return zero on success, except XENVER_version. */ +/* NB. All ops return zero on success, except XENVER_{version,pagesize} */ /* arg == NULL; returns major:minor (16:16). */ #define XENVER_version 0 @@ -54,6 +54,9 @@ typedef struct xen_feature_info xen_feat /* Declares the features reported by XENVER_get_features. */ #include "features.h" +/* arg == NULL; returns host memory page size. */ +#define XENVER_pagesize 7 + #endif /* __XEN_PUBLIC_VERSION_H__ */ /* diff -r c4b68afe97d3 -r 4b51d081378d xen/include/public/xenoprof.h --- a/xen/include/public/xenoprof.h Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/include/public/xenoprof.h Wed Jun 28 07:52:21 2006 -0600 @@ -80,6 +80,15 @@ typedef struct xenoprof_counter xenoprof typedef struct xenoprof_counter xenoprof_counter_t; DEFINE_XEN_GUEST_HANDLE(xenoprof_counter_t); +typedef struct xenoprof_passive { + uint16_t domain_id; + int32_t max_samples; + int32_t nbuf; + int32_t bufsize; + uint64_t buf_maddr; +} xenoprof_passive_t; +DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t); + #endif /* __XEN_PUBLIC_XENOPROF_H__ */ diff -r c4b68afe97d3 -r 4b51d081378d xen/include/xen/mm.h --- a/xen/include/xen/mm.h Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/include/xen/mm.h Wed Jun 28 07:52:21 2006 -0600 @@ -91,6 +91,7 @@ extern struct list_head page_scrub_list; if ( !list_empty(&page_scrub_list) ) \ raise_softirq(PAGE_SCRUB_SOFTIRQ); \ } while ( 0 ) +unsigned long avail_scrub_pages(void); #include <asm/mm.h> diff -r c4b68afe97d3 -r 4b51d081378d xen/include/xen/xenoprof.h --- a/xen/include/xen/xenoprof.h Wed Jun 28 07:51:52 2006 -0600 +++ b/xen/include/xen/xenoprof.h Wed Jun 28 07:52:21 2006 -0600 @@ -14,6 +14,7 @@ #define XENOPROF_DOMAIN_IGNORED 0 #define XENOPROF_DOMAIN_ACTIVE 1 +#define XENOPROF_DOMAIN_PASSIVE 2 #define XENOPROF_IDLE 0 #define XENOPROF_COUNTERS_RESERVED 1 diff -r c4b68afe97d3 -r 4b51d081378d patches/linux-2.6.16.13/net-gso.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/linux-2.6.16.13/net-gso.patch Wed Jun 28 07:52:21 2006 -0600 @@ -0,0 +1,2907 @@ +diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt +index 3c0a5ba..847cedb 100644 +--- a/Documentation/networking/netdevices.txt ++++ b/Documentation/networking/netdevices.txt +@@ -42,9 +42,9 @@ dev->get_stats: + Context: nominally process, but don't sleep inside an rwlock + + dev->hard_start_xmit: +- Synchronization: dev->xmit_lock spinlock. ++ Synchronization: netif_tx_lock spinlock. + When the driver sets NETIF_F_LLTX in dev->features this will be +- called without holding xmit_lock. In this case the driver ++ called without holding netif_tx_lock. In this case the driver + has to lock by itself when needed. It is recommended to use a try lock + for this and return -1 when the spin lock fails. + The locking there should also properly protect against +@@ -62,12 +62,12 @@ dev->hard_start_xmit: + Only valid when NETIF_F_LLTX is set. + + dev->tx_timeout: +- Synchronization: dev->xmit_lock spinlock. ++ Synchronization: netif_tx_lock spinlock. + Context: BHs disabled + Notes: netif_queue_stopped() is guaranteed true + + dev->set_multicast_list: +- Synchronization: dev->xmit_lock spinlock. ++ Synchronization: netif_tx_lock spinlock. + Context: BHs disabled + + dev->poll: +diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c +index 4be9769..2e7cac7 100644 +--- a/drivers/block/aoe/aoenet.c ++++ b/drivers/block/aoe/aoenet.c +@@ -95,9 +95,8 @@ mac_addr(char addr[6]) + static struct sk_buff * + skb_check(struct sk_buff *skb) + { +- if (skb_is_nonlinear(skb)) + if ((skb = skb_share_check(skb, GFP_ATOMIC))) +- if (skb_linearize(skb, GFP_ATOMIC) < 0) { ++ if (skb_linearize(skb)) { + dev_kfree_skb(skb); + return NULL; + } +diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +index a2408d7..c90e620 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +@@ -821,7 +821,8 @@ void ipoib_mcast_restart_task(void *dev_ + + ipoib_mcast_stop_thread(dev, 0); + +- spin_lock_irqsave(&dev->xmit_lock, flags); ++ local_irq_save(flags); ++ netif_tx_lock(dev); + spin_lock(&priv->lock); + + /* +@@ -896,7 +897,8 @@ void ipoib_mcast_restart_task(void *dev_ + } + + spin_unlock(&priv->lock); +- spin_unlock_irqrestore(&dev->xmit_lock, flags); ++ netif_tx_unlock(dev); ++ local_irq_restore(flags); + + /* We have to cancel outside of the spinlock */ + list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { +diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c +index 6711eb6..8d2351f 100644 +--- a/drivers/media/dvb/dvb-core/dvb_net.c ++++ b/drivers/media/dvb/dvb-core/dvb_net.c +@@ -1052,7 +1052,7 @@ static void wq_set_multicast_list (void + + dvb_net_feed_stop(dev); + priv->rx_mode = RX_MODE_UNI; +- spin_lock_bh(&dev->xmit_lock); ++ netif_tx_lock_bh(dev); + + if (dev->flags & IFF_PROMISC) { + dprintk("%s: promiscuous mode\n", dev->name); +@@ -1077,7 +1077,7 @@ static void wq_set_multicast_list (void + } + } + +- spin_unlock_bh(&dev->xmit_lock); ++ netif_tx_unlock_bh(dev); + dvb_net_feed_start(dev); + } + +diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c +index dd41049..6615583 100644 +--- a/drivers/net/8139cp.c ++++ b/drivers/net/8139cp.c +@@ -794,7 +794,7 @@ #endif + entry = cp->tx_head; + eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; + if (dev->features & NETIF_F_TSO) +- mss = skb_shinfo(skb)->tso_size; ++ mss = skb_shinfo(skb)->gso_size; + + if (skb_shinfo(skb)->nr_frags == 0) { + struct cp_desc *txd = &cp->tx_ring[entry]; +diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c +index a24200d..b5e39a1 100644 +--- a/drivers/net/bnx2.c ++++ b/drivers/net/bnx2.c +@@ -1593,7 +1593,7 @@ bnx2_tx_int(struct bnx2 *bp) + skb = tx_buf->skb; + #ifdef BCM_TSO + /* partial BD completions possible with TSO packets */ +- if (skb_shinfo(skb)->tso_size) { ++ if (skb_shinfo(skb)->gso_size) { + u16 last_idx, last_ring_idx; + + last_idx = sw_cons + +@@ -1948,7 +1948,7 @@ bnx2_poll(struct net_device *dev, int *b + return 1; + } + +-/* Called with rtnl_lock from vlan functions and also dev->xmit_lock ++/* Called with rtnl_lock from vlan functions and also netif_tx_lock + * from set_multicast. + */ + static void +@@ -4403,7 +4403,7 @@ bnx2_vlan_rx_kill_vid(struct net_device + } + #endif + +-/* Called with dev->xmit_lock. ++/* Called with netif_tx_lock. + * hard_start_xmit is pseudo-lockless - a lock is only required when + * the tx queue is full. This way, we get the benefit of lockless + * operations most of the time without the complexities to handle +@@ -4441,7 +4441,7 @@ bnx2_start_xmit(struct sk_buff *skb, str + (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16)); + } + #ifdef BCM_TSO +- if ((mss = skb_shinfo(skb)->tso_size) && ++ if ((mss = skb_shinfo(skb)->gso_size) && + (skb->len > (bp->dev->mtu + ETH_HLEN))) { + u32 tcp_opt_len, ip_tcp_len; + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index bcf9f17..e970921 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -1145,8 +1145,7 @@ int bond_sethwaddr(struct net_device *bo + } + + #define BOND_INTERSECT_FEATURES \ +- (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\ +- NETIF_F_TSO|NETIF_F_UFO) ++ (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_TSO | NETIF_F_UFO) + + /* + * Compute the common dev->feature set available to all slaves. Some +@@ -1164,9 +1163,7 @@ static int bond_compute_features(struct + features &= (slave->dev->features & BOND_INTERSECT_FEATURES); + + if ((features & NETIF_F_SG) && +- !(features & (NETIF_F_IP_CSUM | +- NETIF_F_NO_CSUM | +- NETIF_F_HW_CSUM))) ++ !(features & NETIF_F_ALL_CSUM)) + features &= ~NETIF_F_SG; + + /* +@@ -4147,7 +4144,7 @@ static int bond_init(struct net_device * + */ + bond_dev->features |= NETIF_F_VLAN_CHALLENGED; + +- /* don't acquire bond device's xmit_lock when ++ /* don't acquire bond device's netif_tx_lock when + * transmitting */ + bond_dev->features |= NETIF_F_LLTX; + +diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c +index 30ff8ea..7b7d360 100644 +--- a/drivers/net/chelsio/sge.c ++++ b/drivers/net/chelsio/sge.c +@@ -1419,7 +1419,7 @@ int t1_start_xmit(struct sk_buff *skb, s + struct cpl_tx_pkt *cpl; + + #ifdef NETIF_F_TSO +- if (skb_shinfo(skb)->tso_size) { ++ if (skb_shinfo(skb)->gso_size) { + int eth_type; + struct cpl_tx_pkt_lso *hdr; + +@@ -1434,7 +1434,7 @@ #ifdef NETIF_F_TSO + hdr->ip_hdr_words = skb->nh.iph->ihl; + hdr->tcp_hdr_words = skb->h.th->doff; + hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type, +- skb_shinfo(skb)->tso_size)); ++ skb_shinfo(skb)->gso_size)); + hdr->len = htonl(skb->len - sizeof(*hdr)); + cpl = (struct cpl_tx_pkt *)hdr; + sge->stats.tx_lso_pkts++; +diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c +index fa29402..681d284 100644 +--- a/drivers/net/e1000/e1000_main.c ++++ b/drivers/net/e1000/e1000_main.c +@@ -2526,7 +2526,7 @@ #ifdef NETIF_F_TSO + uint8_t ipcss, ipcso, tucss, tucso, hdr_len; + int err; + +- if (skb_shinfo(skb)->tso_size) { ++ if (skb_shinfo(skb)->gso_size) { + if (skb_header_cloned(skb)) { + err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); + if (err) +@@ -2534,7 +2534,7 @@ #ifdef NETIF_F_TSO + } + + hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); +- mss = skb_shinfo(skb)->tso_size; ++ mss = skb_shinfo(skb)->gso_size; + if (skb->protocol == ntohs(ETH_P_IP)) { + skb->nh.iph->tot_len = 0; + skb->nh.iph->check = 0; +@@ -2651,7 +2651,7 @@ #ifdef NETIF_F_TSO + * tso gets written back prematurely before the data is fully + * DMAd to the controller */ + if (!skb->data_len && tx_ring->last_tx_tso && +- !skb_shinfo(skb)->tso_size) { ++ !skb_shinfo(skb)->gso_size) { + tx_ring->last_tx_tso = 0; + size -= 4; + } +@@ -2893,7 +2893,7 @@ #endif + } + + #ifdef NETIF_F_TSO +- mss = skb_shinfo(skb)->tso_size; ++ mss = skb_shinfo(skb)->gso_size; + /* The controller does a simple calculation to + * make sure there is enough room in the FIFO before + * initiating the DMA for each buffer. The calc is: +@@ -2935,7 +2935,7 @@ #endif + #ifdef NETIF_F_TSO + /* Controller Erratum workaround */ + if (!skb->data_len && tx_ring->last_tx_tso && +- !skb_shinfo(skb)->tso_size) ++ !skb_shinfo(skb)->gso_size) + count++; + #endif + +diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c +index 3682ec6..c35f16e 100644 +--- a/drivers/net/forcedeth.c ++++ b/drivers/net/forcedeth.c +@@ -482,9 +482,9 @@ #define LPA_1000HALF 0x0400 + * critical parts: + * - rx is (pseudo-) lockless: it relies on the single-threading provided + * by the arch code for interrupts. +- * - tx setup is lockless: it relies on dev->xmit_lock. Actual submission ++ * - tx setup is lockless: it relies on netif_tx_lock. Actual submission + * needs dev->priv->lock :-( +- * - set_multicast_list: preparation lockless, relies on dev->xmit_lock. ++ * - set_multicast_list: preparation lockless, relies on netif_tx_lock. + */ + + /* in dev: base, irq */ +@@ -1016,7 +1016,7 @@ static void drain_ring(struct net_device + + /* + * nv_start_xmit: dev->hard_start_xmit function +- * Called with dev->xmit_lock held. ++ * Called with netif_tx_lock held. + */ + static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) + { +@@ -1105,8 +1105,8 @@ static int nv_start_xmit(struct sk_buff + np->tx_skbuff[nr] = skb; + + #ifdef NETIF_F_TSO +- if (skb_shinfo(skb)->tso_size) +- tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT); ++ if (skb_shinfo(skb)->gso_size) ++ tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT); + else + #endif + tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0); +@@ -1203,7 +1203,7 @@ static void nv_tx_done(struct net_device + + /* + * nv_tx_timeout: dev->tx_timeout function +- * Called with dev->xmit_lock held. ++ * Called with netif_tx_lock held. + */ + static void nv_tx_timeout(struct net_device *dev) + { +@@ -1524,7 +1524,7 @@ static int nv_change_mtu(struct net_devi + * Changing the MTU is a rare event, it shouldn't matter. + */ + disable_irq(dev->irq); +- spin_lock_bh(&dev->xmit_lock); ++ netif_tx_lock_bh(dev); + spin_lock(&np->lock); + /* stop engines */ + nv_stop_rx(dev); +@@ -1559,7 +1559,7 @@ static int nv_change_mtu(struct net_devi + nv_start_rx(dev); + nv_start_tx(dev); + spin_unlock(&np->lock); +- spin_unlock_bh(&dev->xmit_lock); ++ netif_tx_unlock_bh(dev); + enable_irq(dev->irq); + } + return 0; +@@ -1594,7 +1594,7 @@ static int nv_set_mac_address(struct net + memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN); + + if (netif_running(dev)) { +- spin_lock_bh(&dev->xmit_lock); ++ netif_tx_lock_bh(dev); + spin_lock_irq(&np->lock); + + /* stop rx engine */ +@@ -1606,7 +1606,7 @@ static int nv_set_mac_address(struct net + /* restart rx engine */ + nv_start_rx(dev); + spin_unlock_irq(&np->lock); +- spin_unlock_bh(&dev->xmit_lock); ++ netif_tx_unlock_bh(dev); + } else { + nv_copy_mac_to_hw(dev); + } +@@ -1615,7 +1615,7 @@ static int nv_set_mac_address(struct net + + /* + * nv_set_multicast: dev->set_multicast function +- * Called with dev->xmit_lock held. ++ * Called with netif_tx_lock held. + */ + static void nv_set_multicast(struct net_device *dev) + { +diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c +index 102c1f0..d12605f 100644 +--- a/drivers/net/hamradio/6pack.c ++++ b/drivers/net/hamradio/6pack.c +@@ -308,9 +308,9 @@ static int sp_set_mac_address(struct net + { + struct sockaddr_ax25 *sa = addr; + +- spin_lock_irq(&dev->xmit_lock); ++ netif_tx_lock_bh(dev); + memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN); +- spin_unlock_irq(&dev->xmit_lock); ++ netif_tx_unlock_bh(dev); + + return 0; + } +@@ -767,9 +767,9 @@ static int sixpack_ioctl(struct tty_stru + break; + } + +- spin_lock_irq(&dev->xmit_lock); ++ netif_tx_lock_bh(dev); + memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN); +- spin_unlock_irq(&dev->xmit_lock); ++ netif_tx_unlock_bh(dev); + + err = 0; + break; +diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c +index dc5e9d5..5c66f5a 100644 +--- a/drivers/net/hamradio/mkiss.c ++++ b/drivers/net/hamradio/mkiss.c +@@ -357,9 +357,9 @@ static int ax_set_mac_address(struct net + { + struct sockaddr_ax25 *sa = addr; + +- spin_lock_irq(&dev->xmit_lock); ++ netif_tx_lock_bh(dev); + memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN); +- spin_unlock_irq(&dev->xmit_lock); ++ netif_tx_unlock_bh(dev); + + return 0; + } +@@ -886,9 +886,9 @@ static int mkiss_ioctl(struct tty_struct + break; + } + +- spin_lock_irq(&dev->xmit_lock); ++ netif_tx_lock_bh(dev); + memcpy(dev->dev_addr, addr, AX25_ADDR_LEN); +- spin_unlock_irq(&dev->xmit_lock); ++ netif_tx_unlock_bh(dev); + + err = 0; + break; +diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c +index 31fb2d7..2e222ef 100644 +--- a/drivers/net/ifb.c ++++ b/drivers/net/ifb.c +@@ -76,13 +76,13 @@ static void ri_tasklet(unsigned long dev + dp->st_task_enter++; + if ((skb = skb_peek(&dp->tq)) == NULL) { + dp->st_txq_refl_try++; +- if (spin_trylock(&_dev->xmit_lock)) { ++ if (netif_tx_trylock(_dev)) { + dp->st_rxq_enter++; + while ((skb = skb_dequeue(&dp->rq)) != NULL) { + skb_queue_tail(&dp->tq, skb); + dp->st_rx2tx_tran++; + } +- spin_unlock(&_dev->xmit_lock); ++ netif_tx_unlock(_dev); + } else { + /* reschedule */ + dp->st_rxq_notenter++; +@@ -110,7 +110,7 @@ static void ri_tasklet(unsigned long dev + } + } + +- if (spin_trylock(&_dev->xmit_lock)) { ++ if (netif_tx_trylock(_dev)) { + dp->st_rxq_check++; + if ((skb = skb_peek(&dp->rq)) == NULL) { + dp->tasklet_pending = 0; +@@ -118,10 +118,10 @@ static void ri_tasklet(unsigned long dev + netif_wake_queue(_dev); + } else { + dp->st_rxq_rsch++; +- spin_unlock(&_dev->xmit_lock); ++ netif_tx_unlock(_dev); + goto resched; + } +- spin_unlock(&_dev->xmit_lock); ++ netif_tx_unlock(_dev); + } else { + resched: + dp->tasklet_pending = 1; +diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c +index a9f49f0..339d4a7 100644 +--- a/drivers/net/irda/vlsi_ir.c ++++ b/drivers/net/irda/vlsi_ir.c +@@ -959,7 +959,7 @@ static int vlsi_hard_start_xmit(struct s + || (now.tv_sec==ready.tv_sec && now.tv_usec>=ready.tv_usec)) + break; + udelay(100); +- /* must not sleep here - we are called under xmit_lock! */ ++ /* must not sleep here - called under netif_tx_lock! */ + } + } + +diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c +index f9f77e4..bdab369 100644 +--- a/drivers/net/ixgb/ixgb_main.c ++++ b/drivers/net/ixgb/ixgb_main.c +@@ -1163,7 +1163,7 @@ #ifdef NETIF_F_TSO + uint16_t ipcse, tucse, mss; + int err; + +- if(likely(skb_shinfo(skb)->tso_size)) { ++ if(likely(skb_shinfo(skb)->gso_size)) { + if (skb_header_cloned(skb)) { + err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); + if (err) +@@ -1171,7 +1171,7 @@ #ifdef NETIF_F_TSO + } + + hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); +- mss = skb_shinfo(skb)->tso_size; ++ mss = skb_shinfo(skb)->gso_size; + skb->nh.iph->tot_len = 0; + skb->nh.iph->check = 0; + skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr, +diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c +index 690a1aa..9bcaa80 100644 +--- a/drivers/net/loopback.c ++++ b/drivers/net/loopback.c +@@ -74,7 +74,7 @@ static void emulate_large_send_offload(s + struct iphdr *iph = skb->nh.iph; + struct tcphdr *th = (struct tcphdr*)(skb->nh.raw + (iph->ihl * 4)); + unsigned int doffset = (iph->ihl + th->doff) * 4; +- unsigned int mtu = skb_shinfo(skb)->tso_size + doffset; ++ unsigned int mtu = skb_shinfo(skb)->gso_size + doffset; + unsigned int offset = 0; + u32 seq = ntohl(th->seq); + u16 id = ntohs(iph->id); +@@ -139,7 +139,7 @@ #ifndef LOOPBACK_MUST_CHECKSUM + #endif + + #ifdef LOOPBACK_TSO +- if (skb_shinfo(skb)->tso_size) { ++ if (skb_shinfo(skb)->gso_size) { + BUG_ON(skb->protocol != htons(ETH_P_IP)); + BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP); + +diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c +index c0998ef..0fac9d5 100644 +--- a/drivers/net/mv643xx_eth.c ++++ b/drivers/net/mv643xx_eth.c +@@ -1107,7 +1107,7 @@ static int mv643xx_eth_start_xmit(struct + + #ifdef MV643XX_CHECKSUM_OFFLOAD_TX + if (has_tiny_unaligned_frags(skb)) { +- if ((skb_linearize(skb, GFP_ATOMIC) != 0)) { ++ if (__skb_linearize(skb)) { + stats->tx_dropped++; + printk(KERN_DEBUG "%s: failed to linearize tiny " + "unaligned fragment\n", dev->name); +diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c +index 9d6d254..c9ed624 100644 +--- a/drivers/net/natsemi.c ++++ b/drivers/net/natsemi.c +@@ -323,12 +323,12 @@ performance critical codepaths: + The rx process only runs in the interrupt handler. Access from outside + the interrupt handler is only permitted after disable_irq(). + +-The rx process usually runs under the dev->xmit_lock. If np->intr_tx_reap ++The rx process usually runs under the netif_tx_lock. If np->intr_tx_reap + is set, then access is permitted under spin_lock_irq(&np->lock). + + Thus configuration functions that want to access everything must call + disable_irq(dev->irq); +- spin_lock_bh(dev->xmit_lock); ++ netif_tx_lock_bh(dev); + spin_lock_irq(&np->lock); + + IV. Notes +diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c +index 8cc0d0b..e53b313 100644 +--- a/drivers/net/r8169.c ++++ b/drivers/net/r8169.c +@@ -2171,7 +2171,7 @@ static int rtl8169_xmit_frags(struct rtl + static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) + { + if (dev->features & NETIF_F_TSO) { +- u32 mss = skb_shinfo(skb)->tso_size; ++ u32 mss = skb_shinfo(skb)->gso_size; + + if (mss) + return LargeSend | ((mss & MSSMask) << MSSShift); +diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c +index b7f00d6..439f45f 100644 +--- a/drivers/net/s2io.c ++++ b/drivers/net/s2io.c +@@ -3522,8 +3522,8 @@ #endif + txdp->Control_1 = 0; + txdp->Control_2 = 0; + #ifdef NETIF_F_TSO +- mss = skb_shinfo(skb)->tso_size; +- if (mss) { ++ mss = skb_shinfo(skb)->gso_size; ++ if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4) { + txdp->Control_1 |= TXD_TCP_LSO_EN; + txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); + } +@@ -3543,10 +3543,10 @@ #endif + } + + frg_len = skb->len - skb->data_len; +- if (skb_shinfo(skb)->ufo_size) { ++ if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) { + int ufo_size; + +- ufo_size = skb_shinfo(skb)->ufo_size; ++ ufo_size = skb_shinfo(skb)->gso_size; + ufo_size &= ~7; + txdp->Control_1 |= TXD_UFO_EN; + txdp->Control_1 |= TXD_UFO_MSS(ufo_size); +@@ -3572,7 +3572,7 @@ #endif + txdp->Host_Control = (unsigned long) skb; + txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); + +- if (skb_shinfo(skb)->ufo_size) ++ if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) + txdp->Control_1 |= TXD_UFO_EN; + + frg_cnt = skb_shinfo(skb)->nr_frags; +@@ -3587,12 +3587,12 @@ #endif + (sp->pdev, frag->page, frag->page_offset, + frag->size, PCI_DMA_TODEVICE); + txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size); +- if (skb_shinfo(skb)->ufo_size) ++ if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) + txdp->Control_1 |= TXD_UFO_EN; + } + txdp->Control_1 |= TXD_GATHER_CODE_LAST; + +- if (skb_shinfo(skb)->ufo_size) ++ if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) + frg_cnt++; /* as Txd0 was used for inband header */ + + tx_fifo = mac_control->tx_FIFO_start[queue]; +@@ -3606,7 +3606,7 @@ #ifdef NETIF_F_TSO + if (mss) + val64 |= TX_FIFO_SPECIAL_FUNC; + #endif +- if (skb_shinfo(skb)->ufo_size) ++ if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) + val64 |= TX_FIFO_SPECIAL_FUNC; + writeq(val64, &tx_fifo->List_Control); + +diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c +index 0618cd5..2a55eb3 100644 +--- a/drivers/net/sky2.c ++++ b/drivers/net/sky2.c +@@ -1125,7 +1125,7 @@ static unsigned tx_le_req(const struct s + count = sizeof(dma_addr_t) / sizeof(u32); + count += skb_shinfo(skb)->nr_frags * count; + +- if (skb_shinfo(skb)->tso_size) ++ if (skb_shinfo(skb)->gso_size) + ++count; + + if (skb->ip_summed == CHECKSUM_HW) +@@ -1197,7 +1197,7 @@ static int sky2_xmit_frame(struct sk_buf + } + + /* Check for TCP Segmentation Offload */ +- mss = skb_shinfo(skb)->tso_size; ++ mss = skb_shinfo(skb)->gso_size; + if (mss != 0) { + /* just drop the packet if non-linear expansion fails */ + if (skb_header_cloned(skb) && +diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c +index caf4102..fc9164a 100644 +--- a/drivers/net/tg3.c ++++ b/drivers/net/tg3.c +@@ -3664,7 +3664,7 @@ static int tg3_start_xmit(struct sk_buff + #if TG3_TSO_SUPPORT != 0 + mss = 0; + if (skb->len > (tp->dev->mtu + ETH_HLEN) && +- (mss = skb_shinfo(skb)->tso_size) != 0) { ++ (mss = skb_shinfo(skb)->gso_size) != 0) { + int tcp_opt_len, ip_tcp_len; + + if (skb_header_cloned(skb) && +diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c +index 5b1af39..11de5af 100644 +--- a/drivers/net/tulip/winbond-840.c ++++ b/drivers/net/tulip/winbond-840.c +@@ -1605,11 +1605,11 @@ #ifdef CONFIG_PM + * - get_stats: + * spin_lock_irq(np->lock), doesn't touch hw if not present + * - hard_start_xmit: +- * netif_stop_queue + spin_unlock_wait(&dev->xmit_lock); ++ * synchronize_irq + netif_tx_disable; + * - tx_timeout: +- * netif_device_detach + spin_unlock_wait(&dev->xmit_lock); ++ * netif_device_detach + netif_tx_disable; + * - set_multicast_list +- * netif_device_detach + spin_unlock_wait(&dev->xmit_lock); ++ * netif_device_detach + netif_tx_disable; + * - interrupt handler + * doesn't touch hw if not present, synchronize_irq waits for + * running instances of the interrupt handler. +@@ -1635,11 +1635,10 @@ static int w840_suspend (struct pci_dev + netif_device_detach(dev); + update_csr6(dev, 0); + iowrite32(0, ioaddr + IntrEnable); +- netif_stop_queue(dev); + spin_unlock_irq(&np->lock); + +- spin_unlock_wait(&dev->xmit_lock); + synchronize_irq(dev->irq); ++ netif_tx_disable(dev); + + np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff; + +diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c +index 4c76cb7..30c48c9 100644 +--- a/drivers/net/typhoon.c ++++ b/drivers/net/typhoon.c +@@ -340,7 +340,7 @@ #define typhoon_synchronize_irq(x) synch + #endif + + #if defined(NETIF_F_TSO) +-#define skb_tso_size(x) (skb_shinfo(x)->tso_size) ++#define skb_tso_size(x) (skb_shinfo(x)->gso_size) + #define TSO_NUM_DESCRIPTORS 2 + #define TSO_OFFLOAD_ON TYPHOON_OFFLOAD_TCP_SEGMENT + #else +diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c +index ed1f837..2eb6b5f 100644 +--- a/drivers/net/via-velocity.c ++++ b/drivers/net/via-velocity.c +@@ -1899,6 +1899,13 @@ static int velocity_xmit(struct sk_buff + + int pktlen = skb->len; + ++#ifdef VELOCITY_ZERO_COPY_SUPPORT ++ if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) { ++ kfree_skb(skb); ++ return 0; ++ } ++#endif ++ + spin_lock_irqsave(&vptr->lock, flags); + + index = vptr->td_curr[qnum]; +@@ -1914,8 +1921,6 @@ static int velocity_xmit(struct sk_buff + */ + if (pktlen < ETH_ZLEN) { + /* Cannot occur until ZC support */ +- if(skb_linearize(skb, GFP_ATOMIC)) +- return 0; + pktlen = ETH_ZLEN; + memcpy(tdinfo->buf, skb->data, skb->len); + memset(tdinfo->buf + skb->len, 0, ETH_ZLEN - skb->len); +@@ -1933,7 +1938,6 @@ #ifdef VELOCITY_ZERO_COPY_SUPPORT + int nfrags = skb_shinfo(skb)->nr_frags; + tdinfo->skb = skb; + if (nfrags > 6) { +- skb_linearize(skb, GFP_ATOMIC); + memcpy(tdinfo->buf, skb->data, skb->len); + tdinfo->skb_dma[0] = tdinfo->buf_dma; + td_ptr->tdesc0.pktsize = +diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c +index 6fd0bf7..75237c1 100644 +--- a/drivers/net/wireless/orinoco.c ++++ b/drivers/net/wireless/orinoco.c +@@ -1835,7 +1835,9 @@ static int __orinoco_program_rids(struct + /* Set promiscuity / multicast*/ + priv->promiscuous = 0; + priv->mc_count = 0; +- __orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */ ++ ++ /* FIXME: what about netif_tx_lock */ ++ __orinoco_set_multicast_list(dev); + + return 0; + } +diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c +index 82cb4af..57cec40 100644 +--- a/drivers/s390/net/qeth_eddp.c ++++ b/drivers/s390/net/qeth_eddp.c +@@ -421,7 +421,7 @@ #endif /* CONFIG_QETH_VLAN */ + } + tcph = eddp->skb->h.th; + while (eddp->skb_offset < eddp->skb->len) { +- data_len = min((int)skb_shinfo(eddp->skb)->tso_size, ++ data_len = min((int)skb_shinfo(eddp->skb)->gso_size, + (int)(eddp->skb->len - eddp->skb_offset)); + /* prepare qdio hdr */ + if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){ +@@ -516,20 +516,20 @@ qeth_eddp_calc_num_pages(struct qeth_edd + + QETH_DBF_TEXT(trace, 5, "eddpcanp"); + /* can we put multiple skbs in one page? */ +- skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len); ++ skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len); + if (skbs_per_page > 1){ +- ctx->num_pages = (skb_shinfo(skb)->tso_segs + 1) / ++ ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) / + skbs_per_page + 1; + ctx->elements_per_skb = 1; + } else { + /* no -> how many elements per skb? */ +- ctx->elements_per_skb = (skb_shinfo(skb)->tso_size + hdr_len + ++ ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len + + PAGE_SIZE) >> PAGE_SHIFT; + ctx->num_pages = ctx->elements_per_skb * +- (skb_shinfo(skb)->tso_segs + 1); ++ (skb_shinfo(skb)->gso_segs + 1); + } + ctx->num_elements = ctx->elements_per_skb * +- (skb_shinfo(skb)->tso_segs + 1); ++ (skb_shinfo(skb)->gso_segs + 1); + } + + static inline struct qeth_eddp_context * +diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c +index dba7f7f..d9cc997 100644 +--- a/drivers/s390/net/qeth_main.c ++++ b/drivers/s390/net/qeth_main.c +@@ -4454,7 +4454,7 @@ qeth_send_packet(struct qeth_card *card, + queue = card->qdio.out_qs + [qeth_get_priority_queue(card, skb, ipv, cast_type)]; + +- if (skb_shinfo(skb)->tso_size) ++ if (skb_shinfo(skb)->gso_size) + large_send = card->options.large_send; + + /*are we able to do TSO ? If so ,prepare and send it from here */ +@@ -4501,7 +4501,7 @@ qeth_send_packet(struct qeth_card *card, + card->stats.tx_packets++; + card->stats.tx_bytes += skb->len; + #ifdef CONFIG_QETH_PERF_STATS +- if (skb_shinfo(skb)->tso_size && ++ if (skb_shinfo(skb)->gso_size && + !(large_send == QETH_LARGE_SEND_NO)) { + card->perf_stats.large_send_bytes += skb->len; + card->perf_stats.large_send_cnt++; +diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h +index 1286dde..89cbf34 100644 +--- a/drivers/s390/net/qeth_tso.h ++++ b/drivers/s390/net/qeth_tso.h +@@ -51,7 +51,7 @@ qeth_tso_fill_header(struct qeth_card *c + hdr->ext.hdr_version = 1; + hdr->ext.hdr_len = 28; + /*insert non-fix values */ +- hdr->ext.mss = skb_shinfo(skb)->tso_size; ++ hdr->ext.mss = skb_shinfo(skb)->gso_size; + hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4); + hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len - + sizeof(struct qeth_hdr_tso)); +diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h +index 93535f0..9269df7 100644 +--- a/include/linux/ethtool.h ++++ b/include/linux/ethtool.h +@@ -408,6 +408,8 @@ #define ETHTOOL_STSO 0x0000001f /* Set + #define ETHTOOL_GPERMADDR 0x00000020 /* Get permanent hardware address */ + #define ETHTOOL_GUFO 0x00000021 /* Get UFO enable (ethtool_value) */ + #define ETHTOOL_SUFO 0x00000022 /* Set UFO enable (ethtool_value) */ ++#define ETHTOOL_GGSO 0x00000023 /* Get GSO enable (ethtool_value) */ ++#define ETHTOOL_SGSO 0x00000024 /* Set GSO enable (ethtool_value) */ + + /* compatibility with older code */ + #define SPARC_ETH_GSET ETHTOOL_GSET +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index 7fda03d..47b0965 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -230,7 +230,8 @@ enum netdev_state_t + __LINK_STATE_SCHED, + __LINK_STATE_NOCARRIER, + __LINK_STATE_RX_SCHED, +- __LINK_STATE_LINKWATCH_PENDING ++ __LINK_STATE_LINKWATCH_PENDING, ++ __LINK_STATE_QDISC_RUNNING, + }; + + +@@ -306,9 +307,17 @@ #define NETIF_F_HW_VLAN_TX 128 /* Transm + #define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw acceleration */ + #define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */ + #define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */ +-#define NETIF_F_TSO 2048 /* Can offload TCP/IP segmentation */ ++#define NETIF_F_GSO 2048 /* Enable software GSO. */ + #define NETIF_F_LLTX 4096 /* LockLess TX */ +-#define NETIF_F_UFO 8192 /* Can offload UDP Large Send*/ ++ ++ /* Segmentation offload features */ ++#define NETIF_F_GSO_SHIFT 16 ++#define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT) ++#define NETIF_F_UFO (SKB_GSO_UDPV4 << NETIF_F_GSO_SHIFT) ++#define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT) ++ ++#define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM) ++#define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM) + + struct net_device *next_sched; + +@@ -394,6 +403,9 @@ #define NETIF_F_UFO 8192 + struct list_head qdisc_list; + unsigned long tx_queue_len; /* Max frames per queue allowed */ + ++ /* Partially transmitted GSO packet. */ ++ struct sk_buff *gso_skb; ++ + /* ingress path synchronizer */ + spinlock_t ingress_lock; + struct Qdisc *qdisc_ingress; +@@ -402,7 +414,7 @@ #define NETIF_F_UFO 8192 + * One part is mostly used on xmit path (device) + */ + /* hard_start_xmit synchronizer */ +- spinlock_t xmit_lock ____cacheline_aligned_in_smp; ++ spinlock_t _xmit_lock ____cacheline_aligned_in_smp; + /* cpu id of processor entered to hard_start_xmit or -1, + if nobody entered there. + */ +@@ -527,6 +539,8 @@ struct packet_type { + struct net_device *, + struct packet_type *, + struct net_device *); ++ struct sk_buff *(*gso_segment)(struct sk_buff *skb, ++ int features); + void *af_packet_priv; + struct list_head list; + }; +@@ -693,7 +707,8 @@ extern int dev_change_name(struct net_d + extern int dev_set_mtu(struct net_device *, int); + extern int dev_set_mac_address(struct net_device *, + struct sockaddr *); +-extern void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev); ++extern int dev_hard_start_xmit(struct sk_buff *skb, ++ struct net_device *dev); + + extern void dev_init(void); + +@@ -900,11 +915,43 @@ static inline void __netif_rx_complete(s + clear_bit(__LINK_STATE_RX_SCHED, &dev->state); + } + ++static inline void netif_tx_lock(struct net_device *dev) ++{ ++ spin_lock(&dev->_xmit_lock); ++ dev->xmit_lock_owner = smp_processor_id(); ++} ++ ++static inline void netif_tx_lock_bh(struct net_device *dev) ++{ ++ spin_lock_bh(&dev->_xmit_lock); ++ dev->xmit_lock_owner = smp_processor_id(); ++} ++ ++static inline int netif_tx_trylock(struct net_device *dev) ++{ ++ int err = spin_trylock(&dev->_xmit_lock); ++ if (!err) ++ dev->xmit_lock_owner = smp_processor_id(); ++ return err; ++} ++ ++static inline void netif_tx_unlock(struct net_device *dev) ++{ ++ dev->xmit_lock_owner = -1; ++ spin_unlock(&dev->_xmit_lock); ++} ++ ++static inline void netif_tx_unlock_bh(struct net_device *dev) ++{ ++ dev->xmit_lock_owner = -1; ++ spin_unlock_bh(&dev->_xmit_lock); ++} ++ + static inline void netif_tx_disable(struct net_device *dev) + { +- spin_lock_bh(&dev->xmit_lock); ++ netif_tx_lock_bh(dev); + netif_stop_queue(dev); +- spin_unlock_bh(&dev->xmit_lock); ++ netif_tx_unlock_bh(dev); + } + + /* These functions live elsewhere (drivers/net/net_init.c, but related) */ +@@ -932,6 +979,7 @@ extern int netdev_max_backlog; + extern int weight_p; + extern int netdev_set_master(struct net_device *dev, struct net_device *master); + extern int skb_checksum_help(struct sk_buff *skb, int inward); ++extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features); + #ifdef CONFIG_BUG + extern void netdev_rx_csum_fault(struct net_device *dev); + #else +@@ -951,6 +999,18 @@ #endif + + extern void linkwatch_run_queue(void); + ++static inline int skb_gso_ok(struct sk_buff *skb, int features) ++{ ++ int feature = skb_shinfo(skb)->gso_size ? ++ skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0; ++ return (features & feature) == feature; ++} ++ ++static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) ++{ ++ return !skb_gso_ok(skb, dev->features); ++} ++ + #endif /* __KERNEL__ */ + + #endif /* _LINUX_DEV_H */ +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index ad7cc22..b19d45d 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -134,9 +134,10 @@ struct skb_frag_struct { + struct skb_shared_info { + atomic_t dataref; + unsigned short nr_frags; +- unsigned short tso_size; +- unsigned short tso_segs; +- unsigned short ufo_size; ++ unsigned short gso_size; ++ /* Warning: this field is not always filled in (UFO)! */ ++ unsigned short gso_segs; ++ unsigned short gso_type; + unsigned int ip6_frag_id; + struct sk_buff *frag_list; + skb_frag_t frags[MAX_SKB_FRAGS]; +@@ -168,6 +169,14 @@ enum { + SKB_FCLONE_CLONE, + }; + ++enum { ++ SKB_GSO_TCPV4 = 1 << 0, ++ SKB_GSO_UDPV4 = 1 << 1, ++ ++ /* This indicates the skb is from an untrusted source. */ ++ SKB_GSO_DODGY = 1 << 2, ++}; ++ + /** + * struct sk_buff - socket buffer + * @next: Next buffer in list +@@ -1148,18 +1157,34 @@ static inline int skb_can_coalesce(struc + return 0; + } + ++static inline int __skb_linearize(struct sk_buff *skb) ++{ ++ return __pskb_pull_tail(skb, skb->data_len) ? 0 : -ENOMEM; ++} ++ + /** + * skb_linearize - convert paged skb to linear one + * @skb: buffer to linarize +- * @gfp: allocation mode + * + * If there is no free memory -ENOMEM is returned, otherwise zero + * is returned and the old skb data released. + */ +-extern int __skb_linearize(struct sk_buff *skb, gfp_t gfp); +-static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp) ++static inline int skb_linearize(struct sk_buff *skb) ++{ ++ return skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0; ++} ++ ++/** ++ * skb_linearize_cow - make sure skb is linear and writable ++ * @skb: buffer to process ++ * ++ * If there is no free memory -ENOMEM is returned, otherwise zero ++ * is returned and the old skb data released. ++ */ ++static inline int skb_linearize_cow(struct sk_buff *skb) + { +- return __skb_linearize(skb, gfp); ++ return skb_is_nonlinear(skb) || skb_cloned(skb) ? ++ __skb_linearize(skb) : 0; + } + + /** +@@ -1254,6 +1279,7 @@ extern void skb_split(struct sk_b + struct sk_buff *skb1, const u32 len); + + extern void skb_release_data(struct sk_buff *skb); ++extern struct sk_buff *skb_segment(struct sk_buff *skb, int features); + + static inline void *skb_header_pointer(const struct sk_buff *skb, int offset, + int len, void *buffer) +diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h +index b94d1ad..75b5b93 100644 +--- a/include/net/pkt_sched.h ++++ b/include/net/pkt_sched.h +@@ -218,12 +218,13 @@ extern struct qdisc_rate_table *qdisc_ge + struct rtattr *tab); + extern void qdisc_put_rtab(struct qdisc_rate_table *tab); + +-extern int qdisc_restart(struct net_device *dev); ++extern void __qdisc_run(struct net_device *dev); + + static inline void qdisc_run(struct net_device *dev) + { +- while (!netif_queue_stopped(dev) && qdisc_restart(dev) < 0) +- /* NOTHING */; ++ if (!netif_queue_stopped(dev) && ++ !test_and_set_bit(__LINK_STATE_QDISC_RUNNING, &dev->state)) ++ __qdisc_run(dev); + } + + extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, +diff --git a/include/net/protocol.h b/include/net/protocol.h +index 6dc5970..0d2dcdb 100644 +--- a/include/net/protocol.h ++++ b/include/net/protocol.h +@@ -37,6 +37,8 @@ #define MAX_INET_PROTOS 256 /* Must be + struct net_protocol { + int (*handler)(struct sk_buff *skb); + void (*err_handler)(struct sk_buff *skb, u32 info); ++ struct sk_buff *(*gso_segment)(struct sk_buff *skb, ++ int features); + int no_policy; + }; + +diff --git a/include/net/sock.h b/include/net/sock.h +index f63d0d5..a8e8d21 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -1064,9 +1064,13 @@ static inline void sk_setup_caps(struct + { + __sk_dst_set(sk, dst); + sk->sk_route_caps = dst->dev->features; ++ if (sk->sk_route_caps & NETIF_F_GSO) ++ sk->sk_route_caps |= NETIF_F_TSO; + if (sk->sk_route_caps & NETIF_F_TSO) { + if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len) + sk->sk_route_caps &= ~NETIF_F_TSO; ++ else ++ sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; + } + } + +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 77f21c6..70e1d5f 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -552,13 +552,13 @@ #include <net/tcp_ecn.h> + */ + static inline int tcp_skb_pcount(const struct sk_buff *skb) + { +- return skb_shinfo(skb)->tso_segs; ++ return skb_shinfo(skb)->gso_segs; + } + + /* This is valid iff tcp_skb_pcount() > 1. */ + static inline int tcp_skb_mss(const struct sk_buff *skb) + { +- return skb_shinfo(skb)->tso_size; ++ return skb_shinfo(skb)->gso_size; + } + + static inline void tcp_dec_pcount_approx(__u32 *count, +@@ -1063,6 +1063,8 @@ extern struct request_sock_ops tcp_reque + + extern int tcp_v4_destroy_sock(struct sock *sk); + ++extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features); ++ + #ifdef CONFIG_PROC_FS + extern int tcp4_proc_init(void); + extern void tcp4_proc_exit(void); +diff --git a/net/atm/clip.c b/net/atm/clip.c +index 1842a4e..6dc21a7 100644 +--- a/net/atm/clip.c ++++ b/net/atm/clip.c +@@ -101,7 +101,7 @@ static void unlink_clip_vcc(struct clip_ + printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n",clip_vcc); + return; + } +- spin_lock_bh(&entry->neigh->dev->xmit_lock); /* block clip_start_xmit() */ ++ netif_tx_lock_bh(entry->neigh->dev); /* block clip_start_xmit() */ + entry->neigh->used = jiffies; + for (walk = &entry->vccs; *walk; walk = &(*walk)->next) + if (*walk == clip_vcc) { +@@ -125,7 +125,7 @@ static void unlink_clip_vcc(struct clip_ + printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc " + "0x%p)\n",entry,clip_vcc); + out: +- spin_unlock_bh(&entry->neigh->dev->xmit_lock); ++ netif_tx_unlock_bh(entry->neigh->dev); + } + + /* The neighbour entry n->lock is held. */ +diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c +index 0b33a7b..180e79b 100644 +--- a/net/bridge/br_device.c ++++ b/net/bridge/br_device.c +@@ -146,9 +146,9 @@ static int br_set_tx_csum(struct net_dev + struct net_bridge *br = netdev_priv(dev); + + if (data) +- br->feature_mask |= NETIF_F_IP_CSUM; ++ br->feature_mask |= NETIF_F_NO_CSUM; + else +- br->feature_mask &= ~NETIF_F_IP_CSUM; ++ br->feature_mask &= ~NETIF_F_ALL_CSUM; + + br_features_recompute(br); + return 0; +@@ -185,6 +185,6 @@ void br_dev_setup(struct net_device *dev + dev->set_mac_address = br_set_mac_address; + dev->priv_flags = IFF_EBRIDGE; + +- dev->features = NETIF_F_SG | NETIF_F_FRAGLIST +- | NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_IP_CSUM; ++ dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | ++ NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST; + } +diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c +index 2d24fb4..00b1128 100644 +--- a/net/bridge/br_forward.c ++++ b/net/bridge/br_forward.c +@@ -32,7 +32,7 @@ static inline int should_deliver(const s + int br_dev_queue_push_xmit(struct sk_buff *skb) + { + /* drop mtu oversized packets except tso */ +- if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->tso_size) ++ if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->gso_size) + kfree_skb(skb); + else { + #ifdef CONFIG_BRIDGE_NETFILTER +diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c +index f36b35e..0617146 100644 +--- a/net/bridge/br_if.c ++++ b/net/bridge/br_if.c +@@ -385,17 +385,28 @@ void br_features_recompute(struct net_br + struct net_bridge_port *p; + unsigned long features, checksum; + +- features = br->feature_mask &~ NETIF_F_IP_CSUM; +- checksum = br->feature_mask & NETIF_F_IP_CSUM; ++ checksum = br->feature_mask & NETIF_F_ALL_CSUM ? NETIF_F_NO_CSUM : 0; ++ features = br->feature_mask & ~NETIF_F_ALL_CSUM; + + list_for_each_entry(p, &br->port_list, list) { +- if (!(p->dev->features +- & (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM))) ++ unsigned long feature = p->dev->features; ++ ++ if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM)) ++ checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM; ++ if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM)) ++ checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM; ++ if (!(feature & NETIF_F_IP_CSUM)) + checksum = 0; +- features &= p->dev->features; ++ ++ if (feature & NETIF_F_GSO) ++ feature |= NETIF_F_TSO; ++ feature |= NETIF_F_GSO; ++ ++ features &= feature; + } + +- br->dev->features = features | checksum | NETIF_F_LLTX; ++ br->dev->features = features | checksum | NETIF_F_LLTX | ++ NETIF_F_GSO_ROBUST; + } + + /* called with RTNL */ +diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c +index 9e27373..588207f 100644 +--- a/net/bridge/br_netfilter.c ++++ b/net/bridge/br_netfilter.c +@@ -743,7 +743,7 @@ static int br_nf_dev_queue_xmit(struct s + { + if (skb->protocol == htons(ETH_P_IP) && + skb->len > skb->dev->mtu && +- !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) ++ !skb_shinfo(skb)->gso_size) + return ip_fragment(skb, br_dev_queue_push_xmit); + else + return br_dev_queue_push_xmit(skb); +diff --git a/net/core/dev.c b/net/core/dev.c +index 12a214c..32e1056 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -115,6 +115,7 @@ #include <linux/wireless.h> /* Note : w + #include <net/iw_handler.h> + #endif /* CONFIG_NET_RADIO */ + #include <asm/current.h> ++#include <linux/err.h> + + /* + * The list of packet types we will receive (as opposed to discard) +@@ -1032,7 +1033,7 @@ static inline void net_timestamp(struct + * taps currently in use. + */ + +-void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) ++static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) + { + struct packet_type *ptype; + +@@ -1106,6 +1107,45 @@ out: + return ret; + } + ++/** ++ * skb_gso_segment - Perform segmentation on skb. ++ * @skb: buffer to segment ++ * @features: features for the output path (see dev->features) ++ * ++ * This function segments the given skb and returns a list of segments. ++ * ++ * It may return NULL if the skb requires no segmentation. This is ++ * only possible when GSO is used for verifying header integrity. ++ */ ++struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) ++{ ++ struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); ++ struct packet_type *ptype; ++ int type = skb->protocol; ++ ++ BUG_ON(skb_shinfo(skb)->frag_list); ++ BUG_ON(skb->ip_summed != CHECKSUM_HW); ++ ++ skb->mac.raw = skb->data; ++ skb->mac_len = skb->nh.raw - skb->data; ++ __skb_pull(skb, skb->mac_len); ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) { ++ if (ptype->type == type && !ptype->dev && ptype->gso_segment) { ++ segs = ptype->gso_segment(skb, features); ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ ++ __skb_push(skb, skb->data - skb->mac.raw); ++ ++ return segs; ++} ++ ++EXPORT_SYMBOL(skb_gso_segment); ++ + /* Take action when hardware reception checksum errors are detected. */ + #ifdef CONFIG_BUG + void netdev_rx_csum_fault(struct net_device *dev) +@@ -1142,75 +1182,108 @@ #else + #define illegal_highdma(dev, skb) (0) + #endif + +-/* Keep head the same: replace data */ +-int __skb_linearize(struct sk_buff *skb, gfp_t gfp_mask) +-{ +- unsigned int size; +- u8 *data; +- long offset; +- struct skb_shared_info *ninfo; +- int headerlen = skb->data - skb->head; +- int expand = (skb->tail + skb->data_len) - skb->end; +- +- if (skb_shared(skb)) +- BUG(); +- +- if (expand <= 0) +- expand = 0; +- +- size = skb->end - skb->head + expand; +- size = SKB_DATA_ALIGN(size); +- data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask); +- if (!data) +- return -ENOMEM; +- +- /* Copy entire thing */ +- if (skb_copy_bits(skb, -headerlen, data, headerlen + skb->len)) +- BUG(); +- +- /* Set up shinfo */ +- ninfo = (struct skb_shared_info*)(data + size); +- atomic_set(&ninfo->dataref, 1); +- ninfo->tso_size = skb_shinfo(skb)->tso_size; +- ninfo->tso_segs = skb_shinfo(skb)->tso_segs; +- ninfo->nr_frags = 0; +- ninfo->frag_list = NULL; +- +- /* Offset between the two in bytes */ +- offset = data - skb->head; +- +- /* Free old data. */ +- skb_release_data(skb); +- +- skb->head = data; +- skb->end = data + size; +- +- /* Set up new pointers */ +- skb->h.raw += offset; +- skb->nh.raw += offset; +- skb->mac.raw += offset; +- skb->tail += offset; +- skb->data += offset; +- +- /* We are no longer a clone, even if we were. */ +- skb->cloned = 0; +- +- skb->tail += skb->data_len; +- skb->data_len = 0; ++struct dev_gso_cb { ++ void (*destructor)(struct sk_buff *skb); ++}; ++ ++#define DEV_GSO_CB(skb) ((struct dev_gso_cb *)(skb)->cb) ++ ++static void dev_gso_skb_destructor(struct sk_buff *skb) ++{ ++ struct dev_gso_cb *cb; ++ ++ do { ++ struct sk_buff *nskb = skb->next; ++ ++ skb->next = nskb->next; ++ nskb->next = NULL; ++ kfree_skb(nskb); ++ } while (skb->next); ++ ++ cb = DEV_GSO_CB(skb); ++ if (cb->destructor) ++ cb->destructor(skb); ++} ++ ++/** ++ * dev_gso_segment - Perform emulated hardware segmentation on skb. ++ * @skb: buffer to segment ++ * ++ * This function segments the given skb and stores the list of segments ++ * in skb->next. ++ */ ++static int dev_gso_segment(struct sk_buff *skb) ++{ ++ struct net_device *dev = skb->dev; ++ struct sk_buff *segs; ++ int features = dev->features & ~(illegal_highdma(dev, skb) ? ++ NETIF_F_SG : 0); ++ ++ segs = skb_gso_segment(skb, features); ++ ++ /* Verifying header integrity only. */ ++ if (!segs) ++ return 0; ++ ++ if (unlikely(IS_ERR(segs))) ++ return PTR_ERR(segs); ++ ++ skb->next = segs; ++ DEV_GSO_CB(skb)->destructor = skb->destructor; ++ skb->destructor = dev_gso_skb_destructor; ++ ++ return 0; ++} ++ ++int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ if (likely(!skb->next)) { ++ if (netdev_nit) ++ dev_queue_xmit_nit(skb, dev); ++ ++ if (netif_needs_gso(dev, skb)) { ++ if (unlikely(dev_gso_segment(skb))) ++ goto out_kfree_skb; ++ if (skb->next) ++ goto gso; ++ } ++ ++ return dev->hard_start_xmit(skb, dev); ++ } ++ ++gso: ++ do { ++ struct sk_buff *nskb = skb->next; ++ int rc; ++ ++ skb->next = nskb->next; ++ nskb->next = NULL; ++ rc = dev->hard_start_xmit(nskb, dev); ++ if (unlikely(rc)) { ++ nskb->next = skb->next; ++ skb->next = nskb; ++ return rc; ++ } ++ if (unlikely(netif_queue_stopped(dev) && skb->next)) ++ return NETDEV_TX_BUSY; ++ } while (skb->next); ++ ++ skb->destructor = DEV_GSO_CB(skb)->destructor; ++ ++out_kfree_skb: ++ kfree_skb(skb); + return 0; + } + + #define HARD_TX_LOCK(dev, cpu) { \ + if ((dev->features & NETIF_F_LLTX) == 0) { \ +- spin_lock(&dev->xmit_lock); \ +- dev->xmit_lock_owner = cpu; \ ++ netif_tx_lock(dev); \ + } \ + } + + #define HARD_TX_UNLOCK(dev) { \ + if ((dev->features & NETIF_F_LLTX) == 0) { \ +- dev->xmit_lock_owner = -1; \ +- spin_unlock(&dev->xmit_lock); \ ++ netif_tx_unlock(dev); \ + } \ + } + +@@ -1246,9 +1319,13 @@ int dev_queue_xmit(struct sk_buff *skb) + struct Qdisc *q; + int rc = -ENOMEM; + ++ /* GSO will handle the following emulations directly. */ ++ if (netif_needs_gso(dev, skb)) ++ goto gso; ++ + if (skb_shinfo(skb)->frag_list && + !(dev->features & NETIF_F_FRAGLIST) && +- __skb_linearize(skb, GFP_ATOMIC)) ++ __skb_linearize(skb)) + goto out_kfree_skb; + + /* Fragmented skb is linearized if device does not support SG, +@@ -1257,25 +1334,26 @@ int dev_queue_xmit(struct sk_buff *skb) + */ + if (skb_shinfo(skb)->nr_frags && + (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) && +- __skb_linearize(skb, GFP_ATOMIC)) ++ __skb_linearize(skb)) + goto out_kfree_skb; + + /* If packet is not checksummed and device does not support + * checksumming for this protocol, complete checksumming here. + */ + if (skb->ip_summed == CHECKSUM_HW && +- (!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) && ++ (!(dev->features & NETIF_F_GEN_CSUM) && + (!(dev->features & NETIF_F_IP_CSUM) || + skb->protocol != htons(ETH_P_IP)))) + if (skb_checksum_help(skb, 0)) + goto out_kfree_skb; + ++gso: + spin_lock_prefetch(&dev->queue_lock); + + /* Disable soft irqs for various locks below. Also + * stops preemption for RCU. + */ +- local_bh_disable(); ++ rcu_read_lock_bh(); + + /* Updates of qdisc are serialized by queue_lock. + * The struct Qdisc which is pointed to by qdisc is now a +@@ -1309,8 +1387,8 @@ #endif + /* The device has no queue. Common case for software devices: + loopback, all the sorts of tunnels... + +- Really, it is unlikely that xmit_lock protection is necessary here. +- (f.e. loopback and IP tunnels are clean ignoring statistics ++ Really, it is unlikely that netif_tx_lock protection is necessary ++ here. (f.e. loopback and IP tunnels are clean ignoring statistics + counters.) + However, it is possible, that they rely on protection + made by us here. +@@ -1326,11 +1404,8 @@ #endif + HARD_TX_LOCK(dev, cpu); + + if (!netif_queue_stopped(dev)) { +- if (netdev_nit) +- dev_queue_xmit_nit(skb, dev); +- + rc = 0; +- if (!dev->hard_start_xmit(skb, dev)) { ++ if (!dev_hard_start_xmit(skb, dev)) { + HARD_TX_UNLOCK(dev); + goto out; + } +@@ -1349,13 +1424,13 @@ #endif + } + + rc = -ENETDOWN; +- local_bh_enable(); ++ rcu_read_unlock_bh(); + + out_kfree_skb: + kfree_skb(skb); + return rc; + out: +- local_bh_enable(); ++ rcu_read_unlock_bh(); + return rc; + } + +@@ -2670,7 +2745,7 @@ int register_netdevice(struct net_device + BUG_ON(dev->reg_state != NETREG_UNINITIALIZED); + + spin_lock_init(&dev->queue_lock); +- spin_lock_init(&dev->xmit_lock); ++ spin_lock_init(&dev->_xmit_lock); + dev->xmit_lock_owner = -1; + #ifdef CONFIG_NET_CLS_ACT + spin_lock_init(&dev->ingress_lock); +@@ -2714,9 +2789,7 @@ #endif + + /* Fix illegal SG+CSUM combinations. */ + if ((dev->features & NETIF_F_SG) && +- !(dev->features & (NETIF_F_IP_CSUM | +- NETIF_F_NO_CSUM | _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |