[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Merge with xen-ia64-unstable.hg
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID 856caf975abd50b78c15f41cc8ab52372059fcf3 # Parent 4b51d081378d6783cce48255ffb7655931f26d63 # Parent 3f8d9b128d711e5e2f6e7af2a236272aad3c5817 Merge with xen-ia64-unstable.hg --- buildconfigs/linux-defconfig_xen_x86_32 | 1 buildconfigs/linux-defconfig_xen_x86_64 | 1 docs/man/xm.pod.1 | 93 - docs/misc/vtpm.txt | 47 linux-2.6-xen-sparse/arch/i386/kernel/smp-xen.c | 1 linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c | 7 linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c | 12 linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c | 29 linux-2.6-xen-sparse/drivers/char/tpm/Kconfig | 13 linux-2.6-xen-sparse/drivers/char/tpm/Makefile | 1 linux-2.6-xen-sparse/drivers/char/tpm/tpm.c | 873 ++++++++-- linux-2.6-xen-sparse/drivers/char/tpm/tpm.h | 74 linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c | 183 +- linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h | 42 linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c | 60 linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c | 42 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c | 83 linux-2.6-xen-sparse/drivers/xen/core/evtchn.c | 5 linux-2.6-xen-sparse/drivers/xen/core/gnttab.c | 4 linux-2.6-xen-sparse/drivers/xen/core/xen_sysfs.c | 39 linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 67 linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c | 2 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 56 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c | 71 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h | 2 linux-2.6-xen-sparse/include/asm-ia64/synch_bitops.h | 2 patches/linux-2.6.16.13/fix-hz-suspend.patch | 9 patches/linux-2.6.16.13/net-gso.patch | 8 patches/linux-2.6.16.13/tpm_plugin_2.6.17.patch | 704 ++++++++ patches/linux-2.6.16.13/xenoprof-generic.patch | 9 tools/examples/Makefile | 2 tools/examples/vtpm-addtodb | 10 tools/examples/vtpm-common.sh | 13 tools/firmware/hvmloader/Makefile | 6 tools/firmware/hvmloader/acpi_madt.c | 2 tools/firmware/hvmloader/hvmloader.c | 8 tools/firmware/hvmloader/mp_tables.c | 426 ++++ tools/firmware/rombios/Makefile | 36 tools/firmware/rombios/rombios.c | 30 tools/libxc/xc_hvm_build.c | 9 tools/libxc/xc_linux_build.c | 17 tools/libxc/xc_linux_save.c | 23 tools/libxc/xc_load_elf.c | 29 tools/libxc/xg_private.h | 14 tools/python/xen/xend/XendLogging.py | 2 tools/python/xen/xm/cfgbootpolicy.py | 2 tools/python/xen/xm/create.py | 3 tools/python/xen/xm/dumppolicy.py | 4 tools/python/xen/xm/labels.py | 3 tools/python/xen/xm/loadpolicy.py | 4 tools/python/xen/xm/main.py | 2 tools/python/xen/xm/makepolicy.py | 4 tools/python/xen/xm/shutdown.py | 5 tools/xenstat/libxenstat/src/xenstat.c | 174 + tools/xenstat/libxenstat/src/xenstat.h | 22 tools/xenstat/xentop/xentop.c | 154 + tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py | 11 tools/xm-test/tests/vtpm/03_vtpm-susp_res.py | 94 - tools/xm-test/tests/vtpm/04_vtpm-loc_migr.py | 24 tools/xm-test/tests/vtpm/05_vtpm-loc_migr.py | 24 tools/xm-test/tests/vtpm/06_vtpm-susp_res_pcrs.py | 139 + tools/xm-test/tests/vtpm/07_vtpm-mig_pcrs.py | 132 + tools/xm-test/tests/vtpm/08_vtpm-mig_pcrs.py | 132 + tools/xm-test/tests/vtpm/Makefile.am | 5 tools/xm-test/tests/vtpm/vtpm_utils.py | 2 xen/arch/x86/domain.c | 7 xen/arch/x86/hvm/svm/svm.c | 2 xen/arch/x86/hvm/vmx/vmcs.c | 7 xen/arch/x86/smpboot.c | 3 xen/arch/x86/x86_emulate.c | 2 xen/common/elf.c | 23 xen/common/grant_table.c | 12 xen/common/memory.c | 9 xen/common/page_alloc.c | 4 xen/common/sched_credit.c | 7 xen/common/schedule.c | 21 xen/common/softirq.c | 16 xen/common/timer.c | 9 xen/drivers/char/console.c | 12 xen/include/asm-ia64/grant_table.h | 5 xen/include/asm-x86/grant_table.h | 5 xen/include/public/arch-ia64.h | 2 xen/include/public/arch-x86_32.h | 2 xen/include/public/arch-x86_64.h | 2 xen/include/public/io/netif.h | 53 xen/include/public/memory.h | 12 xen/include/xen/lib.h | 18 xen/include/xen/timer.h | 6 88 files changed, 3632 insertions(+), 714 deletions(-) diff -r 4b51d081378d -r 856caf975abd buildconfigs/linux-defconfig_xen_x86_32 --- a/buildconfigs/linux-defconfig_xen_x86_32 Wed Jun 28 07:52:21 2006 -0600 +++ b/buildconfigs/linux-defconfig_xen_x86_32 Mon Jul 03 08:35:12 2006 +0100 @@ -1902,6 +1902,7 @@ CONFIG_HANGCHECK_TIMER=m # TPM devices # CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m CONFIG_TCG_NSC=m CONFIG_TCG_ATMEL=m CONFIG_TCG_INFINEON=m diff -r 4b51d081378d -r 856caf975abd buildconfigs/linux-defconfig_xen_x86_64 --- a/buildconfigs/linux-defconfig_xen_x86_64 Wed Jun 28 07:52:21 2006 -0600 +++ b/buildconfigs/linux-defconfig_xen_x86_64 Mon Jul 03 08:35:12 2006 +0100 @@ -1765,6 +1765,7 @@ CONFIG_HANGCHECK_TIMER=m # TPM devices # CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m CONFIG_TCG_NSC=m CONFIG_TCG_ATMEL=m CONFIG_TCG_INFINEON=m diff -r 4b51d081378d -r 856caf975abd docs/man/xm.pod.1 --- a/docs/man/xm.pod.1 Wed Jun 28 07:52:21 2006 -0600 +++ b/docs/man/xm.pod.1 Mon Jul 03 08:35:12 2006 +0100 @@ -875,13 +875,42 @@ the currently enforced access control po the currently enforced access control policy. The default for I<type> is 'dom'. The labels are arranged in alphabetical order. -=item B<addlabel> I<configfile> I<label> [I<policy>] +=item B<addlabel> I<label> dom I<configfile> [I<policy>] + +=item B<addlabel> I<label> res I<resource> [I<policy>] Adds the security label with name I<label> to a domain -I<configfile>. Unless specified, the default I<policy> is the +I<configfile> (dom) or to the global resource label file for the +given I<resource> (res). Unless specified, the default I<policy> is the currently enforced access control policy. This subcommand also verifies that the I<policy> definition supports the specified I<label> name. + +=item B<rmlabel> dom I<configfile> + +=item B<rmlabel> res I<resource> + +Works the same as the I<addlabel> command (above), except that this +command will remove the label from the domain I<configfile> (dom) or +the global resource label file (res). + +=item B<getlabel> dom I<configfile> + +=item B<getlabel> res I<resource> + +Shows the label for the given I<configfile> or I<resource> + +=item B<resources> + +Lists all resources in the global resource label file. Each resource +is listed with its associated label and policy name. + +=item B<dry-run> I<configfile> + +Determines if the specified I<configfile> describes a domain with a valid +security configuration for type enforcement. The test shows the policy +decision made for each resource label against the domain label as well as +the overall decision. B<CONFIGURING SECURITY> @@ -960,17 +989,18 @@ B<ATTACHING A SECURITY LABEL TO A DOMAIN =over 4 -This subcommand attaches a security label to a domain configuration -file, here a HomeBanking label. The example policy ensures that this -domain does not share information with other non-hombanking user -domains (i.e., domains labeled as dom_Fun or dom_Boinc) and that it -will not run simultaneously with domains labeled as dom_Fun. +The I<addlabel> subcommand can attach a security label to a domain +configuration file, here a HomeBanking label. The example policy +ensures that this domain does not share information with other +non-hombanking user domains (i.e., domains labeled as dom_Fun or +dom_Boinc) and that it will not run simultaneously with domains +labeled as dom_Fun. We assume that the specified myconfig.xm configuration file actually instantiates a domain that runs workloads related to home-banking, probably just a browser environment for online-banking. - xm addlabel myconfig.xm dom_HomeBanking + xm addlabel dom_HomeBanking dom myconfig.xm The very simple configuration file might now look as printed below. The I<addlabel> subcommand added the B<access_control> entry at @@ -997,6 +1027,38 @@ permitted". =back +B<ATTACHING A SECURITY LABEL TO A RESOURCE> + +=over 4 + +The I<addlabel> subcommand can also be used to attach a security +label to a resource. Following the home banking example from above, +we can label a disk resource (e.g., a physical partition or a file) +to make it accessible to the home banking domain. The example policy +provides a resource label, res_LogicalDiskPartition1(hda1), that is +compatible with the HomeBanking domain label. + + xm addlabel "res_LogicalDiskPartition1(hda1)" res phy:hda6 + +After labeling this disk resource, it can be attached to the domain +by adding a line to the domain configuration file. The line below +attaches this disk to the domain at boot time. + + disk = [ 'phy:hda6,sda2,w' ] + +Alternatively, the resource can be attached after booting the domain +by using the I<block-attach> subcommand. + + xm block-attach homebanking phy:hda6 sda2 w + +Note that labeled resources cannot be used when security is turned +off. Any attempt to use labeled resources with security turned off +will result in a failure with a corresponding error message. The +solution is to enable security or, if security is no longer desired, +to remove the resource label using the I<rmlabel> subcommand. + +=back + B<STARTING AND LISTING LABELED DOMAINS> =over 4 @@ -1008,6 +1070,21 @@ B<STARTING AND LISTING LABELED DOMAINS> Name ID ... Time(s) Label homebanking 23 ... 4.4 dom_HomeBanking Domain-0 0 ... 2658.8 dom_SystemManagement + +=back + +B<LISTING LABELED RESOURCES> + +=over 4 + + xm resources + + phy:hda6 + policy: example.chwall_ste.client_v1 + label: res_LogicalDiskPartition1(hda1) + file:/xen/disk_image/disk.img + policy: example.chwall_ste.client_v1 + label: res_LogicalDiskPartition2(hda2) =back diff -r 4b51d081378d -r 856caf975abd docs/misc/vtpm.txt --- a/docs/misc/vtpm.txt Wed Jun 28 07:52:21 2006 -0600 +++ b/docs/misc/vtpm.txt Mon Jul 03 08:35:12 2006 +0100 @@ -1,5 +1,5 @@ Copyright: IBM Corporation (C), Intel Co Copyright: IBM Corporation (C), Intel Corporation -17 August 2005 +29 June 2006 Authors: Stefan Berger <stefanb@xxxxxxxxxx> (IBM), Employees of Intel Corp @@ -9,23 +9,33 @@ that the user is fairly familiar with co that the user is fairly familiar with compiling and installing XEN and Linux on a machine. -Production Prerequisites: An x86-based machine machine with an ATMEL or -National Semiconductor (NSC) TPM on the motherboard. +Production Prerequisites: An x86-based machine machine with a +Linux-supported TPM on the motherboard (NSC, Atmel, Infineon, TPM V1.2). Development Prerequisites: An emulator for TESTING ONLY is provided -Compiling XEN tree: -------------------- +Compiling the XEN tree: +----------------------- Compile the XEN tree as usual after the following lines set in the linux-2.6.??-xen/.config file: -CONFIG_XEN_TPMDEV_BACKEND=y +CONFIG_XEN_TPMDEV_BACKEND=m + +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m (supported after 2.6.17-rc4) +CONFIG_TCG_NSC=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +CONFIG_TCG_XEN=m +<possible other TPM drivers supported by Linux> + +If the frontend driver needs to be compiled into the user domain +kernel, then the following two lines should be changed. CONFIG_TCG_TPM=y -CONFIG_TCG_NSC=m -CONFIG_TCG_ATMEL=m CONFIG_TCG_XEN=y + You must also enable the virtual TPM to be built: @@ -63,7 +73,7 @@ available. It works similar to making a available. It works similar to making a network interface available to a domain. -kernel = "/boot/vmlinuz-2.6.12-xenU" +kernel = "/boot/vmlinuz-2.6.x" ramdisk = "/xen/initrd_domU/U1_ramdisk.img" memory = 32 name = "TPMUserDomain0" @@ -92,7 +102,7 @@ Running the TPM: Running the TPM: ---------------- -To run the vTPM, dev device /dev/vtpm must be available. +To run the vTPM, the device /dev/vtpm must be available. Verify that 'ls -l /dev/vtpm' shows the following output: crw------- 1 root root 10, 225 Aug 11 06:58 /dev/vtpm @@ -101,16 +111,26 @@ mknod /dev/vtpm c 10 225 mknod /dev/vtpm c 10 225 Make sure that the vTPM is running in domain 0. To do this run the -following +following: + +modprobe tpmbk /usr/bin/vtpm_managerd Start a user domain using the 'xm create' command. Once you are in the -shell of the user domain, you should be able to do the following: +shell of the user domain, you should be able to do the following as +user 'root': -> cd /sys/devices/vtpm +Insert the TPM frontend into the kernel if it has been compiled as a +kernel module. + +> modprobe tpm_xenu + +Check the status of the TPM + +> cd /sys/devices/xen/vtpm-0 > ls -cancel caps pcrs pubek +[...] cancel caps pcrs pubek [...] > cat pcrs PCR-00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 PCR-01: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/arch/i386/kernel/smp-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/smp-xen.c Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/smp-xen.c Mon Jul 03 08:35:12 2006 +0100 @@ -442,6 +442,7 @@ void flush_tlb_mm(struct mm_struct * mm) { xen_tlb_flush_mask(&mm->cpu_vm_mask); } void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) { xen_invlpg_mask(&vma->vm_mm->cpu_vm_mask, va); } +EXPORT_SYMBOL(flush_tlb_page); void flush_tlb_all(void) { xen_tlb_flush_all(); } diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Mon Jul 03 08:35:12 2006 +0100 @@ -989,12 +989,11 @@ static void stop_hz_timer(void) smp_mb(); - /* Leave ourselves in 'tick mode' if rcu or softirq pending. */ - if (rcu_needs_cpu(cpu) || local_softirq_pending()) { + /* Leave ourselves in 'tick mode' if rcu or softirq or timer pending. */ + if (rcu_needs_cpu(cpu) || local_softirq_pending() || + (j = next_timer_interrupt(), time_before_eq(j, jiffies))) { cpu_clear(cpu, nohz_cpu_mask); j = jiffies + 1; - } else { - j = next_timer_interrupt(); } BUG_ON(HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0); diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c --- a/linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c Mon Jul 03 08:35:12 2006 +0100 @@ -60,7 +60,7 @@ void *kmap_atomic_pte(struct page *page, void kunmap_atomic(void *kvaddr, enum km_type type) { -#ifdef CONFIG_DEBUG_HIGHMEM +#if defined(CONFIG_DEBUG_HIGHMEM) || defined(CONFIG_XEN) unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); @@ -69,7 +69,9 @@ void kunmap_atomic(void *kvaddr, enum km preempt_check_resched(); return; } +#endif +#if defined(CONFIG_DEBUG_HIGHMEM) if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx)) BUG(); @@ -79,6 +81,14 @@ void kunmap_atomic(void *kvaddr, enum km */ pte_clear(&init_mm, vaddr, kmap_pte-idx); __flush_tlb_one(vaddr); +#elif defined(CONFIG_XEN) + /* + * We must ensure there are no dangling pagetable references when + * returning memory to Xen (decrease_reservation). + * XXX TODO: We could make this faster by only zapping when + * kmap_flush_unused is called but that is trickier and more invasive. + */ + pte_clear(&init_mm, vaddr, kmap_pte-idx); #endif dec_preempt_count(); diff -r 4b51d081378d -r 856caf975abd 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:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c Mon Jul 03 08:35:12 2006 +0100 @@ -271,10 +271,6 @@ int xen_create_contiguous_region( int xen_create_contiguous_region( unsigned long vstart, unsigned int order, unsigned int address_bits) { - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; unsigned long *in_frames = discontig_frames, out_frame; unsigned long frame, i, flags; long rc; @@ -301,7 +297,7 @@ int xen_create_contiguous_region( if (xen_feature(XENFEAT_auto_translated_physmap)) return 0; - if (order > MAX_CONTIG_ORDER) + if (unlikely(order > MAX_CONTIG_ORDER)) return -ENOMEM; set_xen_guest_handle(exchange.in.extent_start, in_frames); @@ -313,11 +309,7 @@ int xen_create_contiguous_region( /* 1. Zap current PTEs, remembering MFNs. */ for (i = 0; i < (1UL<<order); i++) { - pgd = pgd_offset_k(vstart + (i*PAGE_SIZE)); - pud = pud_offset(pgd, (vstart + (i*PAGE_SIZE))); - pmd = pmd_offset(pud, (vstart + (i*PAGE_SIZE))); - pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE))); - in_frames[i] = pte_mfn(*pte); + in_frames[i] = pfn_to_mfn((__pa(vstart) >> PAGE_SHIFT) + i); if (HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE), __pte_ma(0), 0)) BUG(); @@ -372,10 +364,6 @@ int xen_create_contiguous_region( void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order) { - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; unsigned long *out_frames = discontig_frames, in_frame; unsigned long frame, i, flags; long rc; @@ -397,7 +385,7 @@ void xen_destroy_contiguous_region(unsig !test_bit(__pa(vstart) >> PAGE_SHIFT, contiguous_bitmap)) return; - if (order > MAX_CONTIG_ORDER) + if (unlikely(order > MAX_CONTIG_ORDER)) return; set_xen_guest_handle(exchange.in.extent_start, &in_frame); @@ -410,16 +398,13 @@ void xen_destroy_contiguous_region(unsig contiguous_bitmap_clear(__pa(vstart) >> PAGE_SHIFT, 1UL << order); /* 1. Find start MFN of contiguous extent. */ - pgd = pgd_offset_k(vstart); - pud = pud_offset(pgd, vstart); - pmd = pmd_offset(pud, vstart); - pte = pte_offset_kernel(pmd, vstart); - in_frame = pte_mfn(*pte); + in_frame = pfn_to_mfn(__pa(vstart) >> PAGE_SHIFT); /* 2. Zap current PTEs. */ for (i = 0; i < (1UL<<order); i++) { if (HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE), - __pte_ma(0), 0)); + __pte_ma(0), 0)) + BUG(); set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, INVALID_P2M_ENTRY); out_frames[i] = (__pa(vstart) >> PAGE_SHIFT) + i; @@ -430,7 +415,7 @@ void xen_destroy_contiguous_region(unsig success = (exchange.nr_exchanged == 1); BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0))); BUG_ON(success && (rc != 0)); - if (rc == -ENOSYS) { + if (unlikely(rc == -ENOSYS)) { /* Compatibility when XENMEM_exchange is unsupported. */ if (HYPERVISOR_memory_op(XENMEM_decrease_reservation, &exchange.in) != 1) diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/drivers/char/tpm/Kconfig --- a/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig Mon Jul 03 08:35:12 2006 +0100 @@ -20,9 +20,18 @@ config TCG_TPM Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI and CONFIG_PNPACPI. +config TCG_TIS + tristate "TPM Interface Specification 1.2 Interface" + depends on TCG_TPM + ---help--- + If you have a TPM security chip that is compliant with the + TCG TIS 1.2 TPM specification say Yes and it will be accessible + from within Linux. To compile this driver as a module, choose + M here; the module will be called tpm_tis. + config TCG_NSC tristate "National Semiconductor TPM Interface" - depends on TCG_TPM && !XEN_UNPRIVILEGED_GUEST + depends on TCG_TPM && PNPACPI ---help--- If you have a TPM security chip from National Semicondutor say Yes and it will be accessible from within Linux. To @@ -31,7 +40,7 @@ config TCG_NSC config TCG_ATMEL tristate "Atmel TPM Interface" - depends on TCG_TPM && !XEN_UNPRIVILEGED_GUEST + depends on TCG_TPM ---help--- If you have a TPM security chip from Atmel say Yes and it will be accessible from within Linux. To compile this driver diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/drivers/char/tpm/Makefile --- a/linux-2.6-xen-sparse/drivers/char/tpm/Makefile Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/Makefile Mon Jul 03 08:35:12 2006 +0100 @@ -5,6 +5,7 @@ ifdef CONFIG_ACPI ifdef CONFIG_ACPI obj-$(CONFIG_TCG_TPM) += tpm_bios.o endif +obj-$(CONFIG_TCG_TIS) += tpm_tis.o obj-$(CONFIG_TCG_NSC) += tpm_nsc.o obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/drivers/char/tpm/tpm.c --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm.c Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.c Mon Jul 03 08:35:12 2006 +0100 @@ -30,15 +30,295 @@ enum tpm_const { TPM_MINOR = 224, /* officially assigned */ - TPM_MIN_BUFSIZE = 2048, - TPM_MAX_BUFSIZE = 64 * 1024, +#ifndef CONFIG_XEN + TPM_BUFSIZE = 2048, +#endif TPM_NUM_DEVICES = 256, - TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int)) }; + +enum tpm_duration { + TPM_SHORT = 0, + TPM_MEDIUM = 1, + TPM_LONG = 2, + TPM_UNDEFINED, +}; + +#define TPM_MAX_ORDINAL 243 +#define TPM_MAX_PROTECTED_ORDINAL 12 +#define TPM_PROTECTED_ORDINAL_MASK 0xFF static LIST_HEAD(tpm_chip_list); static DEFINE_SPINLOCK(driver_lock); -static int dev_mask[TPM_NUM_MASK_ENTRIES]; +static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); + +/* + * Array with one entry per ordinal defining the maximum amount + * of time the chip could take to return the result. The ordinal + * designation of short, medium or long is defined in a table in + * TCG Specification TPM Main Part 2 TPM Structures Section 17. The + * values of the SHORT, MEDIUM, and LONG durations are retrieved + * from the chip during initialization with a call to tpm_get_timeouts. + */ +static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = { + TPM_UNDEFINED, /* 0 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 5 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 10 */ + TPM_SHORT, +}; + +static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { + TPM_UNDEFINED, /* 0 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 5 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 10 */ + TPM_SHORT, + TPM_MEDIUM, + TPM_LONG, + TPM_LONG, + TPM_MEDIUM, /* 15 */ + TPM_SHORT, + TPM_SHORT, + TPM_MEDIUM, + TPM_LONG, + TPM_SHORT, /* 20 */ + TPM_SHORT, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_SHORT, /* 25 */ + TPM_SHORT, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_MEDIUM, /* 30 */ + TPM_LONG, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, /* 35 */ + TPM_MEDIUM, + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_MEDIUM, /* 40 */ + TPM_LONG, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, /* 45 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_LONG, + TPM_MEDIUM, /* 50 */ + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 55 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_MEDIUM, /* 60 */ + TPM_MEDIUM, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_MEDIUM, /* 65 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 70 */ + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 75 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_LONG, /* 80 */ + TPM_UNDEFINED, + TPM_MEDIUM, + TPM_LONG, + TPM_SHORT, + TPM_UNDEFINED, /* 85 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 90 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, /* 95 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_MEDIUM, /* 100 */ + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 105 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 110 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, /* 115 */ + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_LONG, /* 120 */ + TPM_LONG, + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_SHORT, + TPM_SHORT, /* 125 */ + TPM_SHORT, + TPM_LONG, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, /* 130 */ + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_SHORT, + TPM_MEDIUM, + TPM_UNDEFINED, /* 135 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 140 */ + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 145 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 150 */ + TPM_MEDIUM, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, /* 155 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 160 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 165 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_LONG, /* 170 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 175 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_MEDIUM, /* 180 */ + TPM_SHORT, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_MEDIUM, /* 185 */ + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 190 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 195 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 200 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, + TPM_SHORT, /* 205 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_MEDIUM, /* 210 */ + TPM_UNDEFINED, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_UNDEFINED, /* 215 */ + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, + TPM_SHORT, /* 220 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, /* 225 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 230 */ + TPM_LONG, + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 235 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 240 */ + TPM_UNDEFINED, + TPM_MEDIUM, +}; static void user_reader_timeout(unsigned long ptr) { @@ -47,28 +327,58 @@ static void user_reader_timeout(unsigned schedule_work(&chip->work); } -static void timeout_work(void * ptr) +static void timeout_work(void *ptr) { struct tpm_chip *chip = ptr; down(&chip->buffer_mutex); atomic_set(&chip->data_pending, 0); +#ifndef CONFIG_XEN + memset(chip->data_buffer, 0, TPM_BUFSIZE); +#else memset(chip->data_buffer, 0, get_chip_buffersize(chip)); +#endif up(&chip->buffer_mutex); } + +/* + * Returns max number of jiffies to wait + */ +unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, + u32 ordinal) +{ + int duration_idx = TPM_UNDEFINED; + int duration = 0; + + if (ordinal < TPM_MAX_ORDINAL) + duration_idx = tpm_ordinal_duration[ordinal]; + else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) < + TPM_MAX_PROTECTED_ORDINAL) + duration_idx = + tpm_protected_ordinal_duration[ordinal & + TPM_PROTECTED_ORDINAL_MASK]; + + if (duration_idx != TPM_UNDEFINED) + duration = chip->vendor.duration[duration_idx]; + if (duration <= 0) + return 2 * 60 * HZ; + else + return duration; +} +EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); /* * Internal kernel interface to transmit TPM commands */ -static ssize_t tpm_transmit(struct tpm_chip * chip, const char *buf, +static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, size_t bufsiz) { ssize_t rc; - u32 count; + u32 count, ordinal; unsigned long stop; count = be32_to_cpu(*((__be32 *) (buf + 2))); - + ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); if (count == 0) return -ENODATA; if (count > bufsiz) { @@ -79,21 +389,23 @@ static ssize_t tpm_transmit(struct tpm_c down(&chip->tpm_mutex); - if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) { + if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) { dev_err(chip->dev, "tpm_transmit: tpm_send: error %zd\n", rc); goto out; } - stop = jiffies + 2 * 60 * HZ; + if (chip->vendor.irq) + goto out_recv; + + stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); do { - u8 status = chip->vendor->status(chip); - if ((status & chip->vendor->req_complete_mask) == - chip->vendor->req_complete_val) { + u8 status = chip->vendor.status(chip); + if ((status & chip->vendor.req_complete_mask) == + chip->vendor.req_complete_val) goto out_recv; - } - - if ((status == chip->vendor->req_canceled)) { + + if ((status == chip->vendor.req_canceled)) { dev_err(chip->dev, "Operation Canceled\n"); rc = -ECANCELED; goto out; @@ -103,14 +415,13 @@ static ssize_t tpm_transmit(struct tpm_c rmb(); } while (time_before(jiffies, stop)); - - chip->vendor->cancel(chip); + chip->vendor.cancel(chip); dev_err(chip->dev, "Operation Timed out\n"); rc = -ETIME; goto out; out_recv: - rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz); + rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz); if (rc < 0) dev_err(chip->dev, "tpm_transmit: tpm_recv: error %zd\n", rc); @@ -120,17 +431,247 @@ out: } #define TPM_DIGEST_SIZE 20 -#define CAP_PCR_RESULT_SIZE 18 -static const u8 cap_pcr[] = { +#define TPM_ERROR_SIZE 10 +#define TPM_RET_CODE_IDX 6 +#define TPM_GET_CAP_RET_SIZE_IDX 10 +#define TPM_GET_CAP_RET_UINT32_1_IDX 14 +#define TPM_GET_CAP_RET_UINT32_2_IDX 18 +#define TPM_GET_CAP_RET_UINT32_3_IDX 22 +#define TPM_GET_CAP_RET_UINT32_4_IDX 26 +#define TPM_GET_CAP_PERM_DISABLE_IDX 16 +#define TPM_GET_CAP_PERM_INACTIVE_IDX 18 +#define TPM_GET_CAP_RET_BOOL_1_IDX 14 +#define TPM_GET_CAP_TEMP_INACTIVE_IDX 16 + +#define TPM_CAP_IDX 13 +#define TPM_CAP_SUBCAP_IDX 21 + +enum tpm_capabilities { + TPM_CAP_FLAG = 4, + TPM_CAP_PROP = 5, +}; + +enum tpm_sub_capabilities { + TPM_CAP_PROP_PCR = 0x1, + TPM_CAP_PROP_MANUFACTURER = 0x3, + TPM_CAP_FLAG_PERM = 0x8, + TPM_CAP_FLAG_VOL = 0x9, + TPM_CAP_PROP_OWNER = 0x11, + TPM_CAP_PROP_TIS_TIMEOUT = 0x15, + TPM_CAP_PROP_TIS_DURATION = 0x20, +}; + +/* + * This is a semi generic GetCapability command for use + * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG + * and their associated sub_capabilities. + */ + +static const u8 tpm_cap[] = { 0, 193, /* TPM_TAG_RQU_COMMAND */ 0, 0, 0, 22, /* length */ 0, 0, 0, 101, /* TPM_ORD_GetCapability */ - 0, 0, 0, 5, - 0, 0, 0, 4, - 0, 0, 1, 1 + 0, 0, 0, 0, /* TPM_CAP_<TYPE> */ + 0, 0, 0, 4, /* TPM_CAP_SUB_<TYPE> size */ + 0, 0, 1, 0 /* TPM_CAP_SUB_<TYPE> */ }; -#define READ_PCR_RESULT_SIZE 30 +static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len, + char *desc) +{ + int err; + + len = tpm_transmit(chip, data, len); + if (len < 0) + return len; + if (len == TPM_ERROR_SIZE) { + err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))); + dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); + return err; + } + return 0; +} + +void tpm_gen_interrupt(struct tpm_chip *chip) +{ + u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; + ssize_t rc; + + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_PROP; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; + + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the timeouts"); +} +EXPORT_SYMBOL_GPL(tpm_gen_interrupt); + +void tpm_get_timeouts(struct tpm_chip *chip) +{ + u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; + ssize_t rc; + u32 timeout; + + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_PROP; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; + + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the timeouts"); + if (rc) + goto duration; + + if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) + != 4 * sizeof(u32)) + goto duration; + + /* Don't overwrite default if value is 0 */ + timeout = + be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))); + if (timeout) + chip->vendor.timeout_a = msecs_to_jiffies(timeout); + timeout = + be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX))); + if (timeout) + chip->vendor.timeout_b = msecs_to_jiffies(timeout); + timeout = + be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX))); + if (timeout) + chip->vendor.timeout_c = msecs_to_jiffies(timeout); + timeout = + be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX))); + if (timeout) + chip->vendor.timeout_d = msecs_to_jiffies(timeout); + +duration: + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_PROP; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION; + + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the durations"); + if (rc) + return; + + if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) + != 3 * sizeof(u32)) + return; + + chip->vendor.duration[TPM_SHORT] = + msecs_to_jiffies(be32_to_cpu + (*((__be32 *) (data + + TPM_GET_CAP_RET_UINT32_1_IDX)))); + chip->vendor.duration[TPM_MEDIUM] = + msecs_to_jiffies(be32_to_cpu + (*((__be32 *) (data + + TPM_GET_CAP_RET_UINT32_2_IDX)))); + chip->vendor.duration[TPM_LONG] = + msecs_to_jiffies(be32_to_cpu + (*((__be32 *) (data + + TPM_GET_CAP_RET_UINT32_3_IDX)))); +} +EXPORT_SYMBOL_GPL(tpm_get_timeouts); + +void tpm_continue_selftest(struct tpm_chip *chip) +{ + u8 data[] = { + 0, 193, /* TPM_TAG_RQU_COMMAND */ + 0, 0, 0, 10, /* length */ + 0, 0, 0, 83, /* TPM_ORD_GetCapability */ + }; + + tpm_transmit(chip, data, sizeof(data)); +} +EXPORT_SYMBOL_GPL(tpm_continue_selftest); + +ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, + char *buf) +{ + u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; + ssize_t rc; + + struct tpm_chip *chip = dev_get_drvdata(dev); + if (chip == NULL) + return -ENODEV; + + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_FLAG; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; + + rc = transmit_cmd(chip, data, sizeof(data), + "attemtping to determine the permanent state"); + if (rc) + return 0; + return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); +} +EXPORT_SYMBOL_GPL(tpm_show_enabled); + +ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, + char *buf) +{ + u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; + ssize_t rc; + + struct tpm_chip *chip = dev_get_drvdata(dev); + if (chip == NULL) + return -ENODEV; + + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_FLAG; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; + + rc = transmit_cmd(chip, data, sizeof(data), + "attemtping to determine the permanent state"); + if (rc) + return 0; + return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); +} +EXPORT_SYMBOL_GPL(tpm_show_active); + +ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, + char *buf) +{ + u8 data[sizeof(tpm_cap)]; + ssize_t rc; + + struct tpm_chip *chip = dev_get_drvdata(dev); + if (chip == NULL) + return -ENODEV; + + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_PROP; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; + + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the owner state"); + if (rc) + return 0; + return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); +} +EXPORT_SYMBOL_GPL(tpm_show_owned); + +ssize_t tpm_show_temp_deactivated(struct device * dev, + struct device_attribute * attr, char *buf) +{ + u8 data[sizeof(tpm_cap)]; + ssize_t rc; + + struct tpm_chip *chip = dev_get_drvdata(dev); + if (chip == NULL) + return -ENODEV; + + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_FLAG; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; + + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the temporary state"); + if (rc) + return 0; + return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); +} +EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); + static const u8 pcrread[] = { 0, 193, /* TPM_TAG_RQU_COMMAND */ 0, 0, 0, 14, /* length */ @@ -141,8 +682,8 @@ ssize_t tpm_show_pcrs(struct device *dev ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, char *buf) { - u8 data[READ_PCR_RESULT_SIZE]; - ssize_t len; + u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)]; + ssize_t rc; int i, j, num_pcrs; __be32 index; char *str = buf; @@ -151,29 +692,24 @@ ssize_t tpm_show_pcrs(struct device *dev if (chip == NULL) return -ENODEV; - memcpy(data, cap_pcr, sizeof(cap_pcr)); - if ((len = tpm_transmit(chip, data, sizeof(data))) - < CAP_PCR_RESULT_SIZE) { - dev_dbg(chip->dev, "A TPM error (%d) occurred " - "attempting to determine the number of PCRS\n", - be32_to_cpu(*((__be32 *) (data + 6)))); + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_PROP; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; + + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the number of PCRS"); + if (rc) return 0; - } num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); - for (i = 0; i < num_pcrs; i++) { memcpy(data, pcrread, sizeof(pcrread)); index = cpu_to_be32(i); memcpy(data + 10, &index, 4); - if ((len = tpm_transmit(chip, data, sizeof(data))) - < READ_PCR_RESULT_SIZE){ - dev_dbg(chip->dev, "A TPM error (%d) occurred" - " attempting to read PCR %d of %d\n", - be32_to_cpu(*((__be32 *) (data + 6))), - i, num_pcrs); + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to read a PCR"); + if (rc) goto out; - } str += sprintf(str, "PCR-%02d: ", i); for (j = 0; j < TPM_DIGEST_SIZE; j++) str += sprintf(str, "%02X ", *(data + 10 + j)); @@ -195,7 +731,7 @@ ssize_t tpm_show_pubek(struct device *de char *buf) { u8 *data; - ssize_t len; + ssize_t err; int i, rc; char *str = buf; @@ -209,14 +745,10 @@ ssize_t tpm_show_pubek(struct device *de memcpy(data, readpubek, sizeof(readpubek)); - if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) < - READ_PUBEK_RESULT_SIZE) { - dev_dbg(chip->dev, "A TPM error (%d) occurred " - "attempting to read the PUBEK\n", - be32_to_cpu(*((__be32 *) (data + 6)))); - rc = 0; + err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE, + "attempting to read the PUBEK"); + if (err) goto out; - } /* ignore header 10 bytes @@ -246,66 +778,109 @@ ssize_t tpm_show_pubek(struct device *de if ((i + 1) % 16 == 0) str += sprintf(str, "\n"); } +out: rc = str - buf; -out: kfree(data); return rc; } EXPORT_SYMBOL_GPL(tpm_show_pubek); -#define CAP_VER_RESULT_SIZE 18 +#define CAP_VERSION_1_1 6 +#define CAP_VERSION_1_2 0x1A +#define CAP_VERSION_IDX 13 static const u8 cap_version[] = { 0, 193, /* TPM_TAG_RQU_COMMAND */ 0, 0, 0, 18, /* length */ 0, 0, 0, 101, /* TPM_ORD_GetCapability */ - 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0 }; -#define CAP_MANUFACTURER_RESULT_SIZE 18 -static const u8 cap_manufacturer[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 22, /* length */ - 0, 0, 0, 101, /* TPM_ORD_GetCapability */ - 0, 0, 0, 5, - 0, 0, 0, 4, - 0, 0, 1, 3 -}; - ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, char *buf) { - u8 data[sizeof(cap_manufacturer)]; - ssize_t len; + u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; + ssize_t rc; char *str = buf; struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; - memcpy(data, cap_manufacturer, sizeof(cap_manufacturer)); - - if ((len = tpm_transmit(chip, data, sizeof(data))) < - CAP_MANUFACTURER_RESULT_SIZE) - return len; + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_PROP; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; + + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the manufacturer"); + if (rc) + return 0; str += sprintf(str, "Manufacturer: 0x%x\n", - be32_to_cpu(*((__be32 *) (data + 14)))); + be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); memcpy(data, cap_version, sizeof(cap_version)); - - if ((len = tpm_transmit(chip, data, sizeof(data))) < - CAP_VER_RESULT_SIZE) - return len; - - str += - sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n", - (int) data[14], (int) data[15], (int) data[16], - (int) data[17]); - + data[CAP_VERSION_IDX] = CAP_VERSION_1_1; + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the 1.1 version"); + if (rc) + goto out; + + str += sprintf(str, + "TCG version: %d.%d\nFirmware version: %d.%d\n", + (int) data[14], (int) data[15], (int) data[16], + (int) data[17]); + +out: return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_caps); + +ssize_t tpm_show_caps_1_2(struct device * dev, + struct device_attribute * attr, char *buf) +{ + u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; + ssize_t len; + char *str = buf; + + struct tpm_chip *chip = dev_get_drvdata(dev); + if (chip == NULL) + return -ENODEV; + + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_PROP; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; + + if ((len = tpm_transmit(chip, data, sizeof(data))) <= + TPM_ERROR_SIZE) { + dev_dbg(chip->dev, "A TPM error (%d) occurred " + "attempting to determine the manufacturer\n", + be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); + return 0; + } + + str += sprintf(str, "Manufacturer: 0x%x\n", + be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); + + memcpy(data, cap_version, sizeof(cap_version)); + data[CAP_VERSION_IDX] = CAP_VERSION_1_2; + + if ((len = tpm_transmit(chip, data, sizeof(data))) <= + TPM_ERROR_SIZE) { + dev_err(chip->dev, "A TPM error (%d) occurred " + "attempting to determine the 1.2 version\n", + be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); + goto out; + } + str += sprintf(str, + "TCG version: %d.%d\nFirmware version: %d.%d\n", + (int) data[16], (int) data[17], (int) data[18], + (int) data[19]); + +out: + return str - buf; +} +EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -314,7 +889,7 @@ ssize_t tpm_store_cancel(struct device * if (chip == NULL) return 0; - chip->vendor->cancel(chip); + chip->vendor.cancel(chip); return count; } EXPORT_SYMBOL_GPL(tpm_store_cancel); @@ -330,7 +905,7 @@ int tpm_open(struct inode *inode, struct spin_lock(&driver_lock); list_for_each_entry(pos, &tpm_chip_list, list) { - if (pos->vendor->miscdev.minor == minor) { + if (pos->vendor.miscdev.minor == minor) { chip = pos; break; } @@ -352,7 +927,12 @@ int tpm_open(struct inode *inode, struct spin_unlock(&driver_lock); - chip->data_buffer = kmalloc(get_chip_buffersize(chip) * sizeof(u8), GFP_KERNEL); +#ifndef CONFIG_XEN + chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); +#else + chip->data_buffer = kmalloc(get_chip_buffersize(chip) * sizeof(u8), + GFP_KERNEL); +#endif if (chip->data_buffer == NULL) { chip->num_opens--; put_device(chip->dev); @@ -388,7 +968,7 @@ EXPORT_SYMBOL_GPL(tpm_release); EXPORT_SYMBOL_GPL(tpm_release); ssize_t tpm_write(struct file *file, const char __user *buf, - size_t size, loff_t * off) + size_t size, loff_t *off) { struct tpm_chip *chip = file->private_data; int in_size = size, out_size; @@ -400,8 +980,13 @@ ssize_t tpm_write(struct file *file, con down(&chip->buffer_mutex); +#ifndef CONFIG_XEN + if (in_size > TPM_BUFSIZE) + in_size = TPM_BUFSIZE; +#else if (in_size > get_chip_buffersize(chip)) in_size = get_chip_buffersize(chip); +#endif if (copy_from_user (chip->data_buffer, (void __user *) buf, in_size)) { @@ -410,11 +995,17 @@ ssize_t tpm_write(struct file *file, con } /* atomic tpm command send and result receive */ - out_size = tpm_transmit(chip, chip->data_buffer, +#ifndef CONFIG_XEN + out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); +#else + out_size = tpm_transmit(chip, chip->data_buffer, get_chip_buffersize(chip)); +#endif atomic_set(&chip->data_pending, out_size); +#ifdef CONFIG_XEN atomic_set(&chip->data_position, 0); +#endif up(&chip->buffer_mutex); /* Set a timeout by which the reader must come claim the result */ @@ -422,42 +1013,59 @@ ssize_t tpm_write(struct file *file, con return in_size; } - EXPORT_SYMBOL_GPL(tpm_write); -ssize_t tpm_read(struct file * file, char __user *buf, - size_t size, loff_t * off) +ssize_t tpm_read(struct file *file, char __user *buf, + size_t size, loff_t *off) { struct tpm_chip *chip = file->private_data; int ret_size; +#ifdef CONFIG_XEN int pos, pending = 0; - +#endif + +#ifndef CONFIG_XEN + del_singleshot_timer_sync(&chip->user_read_timer); + flush_scheduled_work(); +#endif ret_size = atomic_read(&chip->data_pending); +#ifndef CONFIG_XEN + atomic_set(&chip->data_pending, 0); +#endif if (ret_size > 0) { /* relay data */ if (size < ret_size) ret_size = size; +#ifdef CONFIG_XEN pos = atomic_read(&chip->data_position); - +#endif down(&chip->buffer_mutex); +#ifndef CONFIG_XEN + if (copy_to_user(buf, chip->data_buffer, ret_size)) +#else if (copy_to_user(buf, &chip->data_buffer[pos], ret_size)) { +#endif ret_size = -EFAULT; +#ifdef CONFIG_XEN } else { pending = atomic_read(&chip->data_pending) - ret_size; if ( pending ) { - atomic_set( &chip->data_pending, pending ); - atomic_set( &chip->data_position, pos+ret_size ); + atomic_set(&chip->data_pending, pending); + atomic_set(&chip->data_position, + pos+ret_size); } } +#endif up(&chip->buffer_mutex); } - - if ( ret_size <= 0 || pending == 0 ) { - atomic_set( &chip->data_pending, 0 ); + +#ifdef CONFIG_XEN + if ( ret_size <= 0 || pending == 0 ) { + atomic_set(&chip->data_pending, 0); del_singleshot_timer_sync(&chip->user_read_timer); flush_scheduled_work(); } - +#endif return ret_size; } EXPORT_SYMBOL_GPL(tpm_read); @@ -478,14 +1086,13 @@ void tpm_remove_hardware(struct device * spin_unlock(&driver_lock); dev_set_drvdata(dev, NULL); - misc_deregister(&chip->vendor->miscdev); - kfree(chip->vendor->miscdev.name); - - sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); + misc_deregister(&chip->vendor.miscdev); + kfree(chip->vendor.miscdev.name); + + sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); tpm_bios_log_teardown(chip->bios_dir); - dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= - ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); + clear_bit(chip->dev_num, dev_mask); kfree(chip); @@ -536,18 +1143,18 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume); * upon errant exit from this function specific probe function should call * pci_disable_device */ -int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry) +struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific + *entry) { #define DEVNAME_SIZE 7 char *devname; struct tpm_chip *chip; - int i, j; /* Driver specific per-device data */ chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) - return -ENOMEM; + return NULL; init_MUTEX(&chip->buffer_mutex); init_MUTEX(&chip->tpm_mutex); @@ -559,51 +1166,37 @@ int tpm_register_hardware(struct device chip->user_read_timer.function = user_reader_timeout; chip->user_read_timer.data = (unsigned long) chip; - chip->vendor = entry; - - if (entry->buffersize < TPM_MIN_BUFSIZE) { - entry->buffersize = TPM_MIN_BUFSIZE; - } else if (entry->buffersize > TPM_MAX_BUFSIZE) { - entry->buffersize = TPM_MAX_BUFSIZE; - } - - chip->dev_num = -1; - - for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++) - for (j = 0; j < 8 * sizeof(int); j++) - if ((dev_mask[i] & (1 << j)) == 0) { - chip->dev_num = - i * TPM_NUM_MASK_ENTRIES + j; - dev_mask[i] |= 1 << j; - goto dev_num_search_complete; - } - -dev_num_search_complete: - if (chip->dev_num < 0) { + memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific)); + + chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES); + + if (chip->dev_num >= TPM_NUM_DEVICES) { dev_err(dev, "No available tpm device numbers\n"); kfree(chip); - return -ENODEV; + return NULL; } else if (chip->dev_num == 0) - chip->vendor->miscdev.minor = TPM_MINOR; + chip->vendor.miscdev.minor = TPM_MINOR; else - chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR; + chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR; + + set_bit(chip->dev_num, dev_mask); devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL); scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num); - chip->vendor->miscdev.name = devname; - - chip->vendor->miscdev.dev = dev; + chip->vendor.miscdev.name = devname; + + chip->vendor.miscdev.dev = dev; chip->dev = get_device(dev); - if (misc_register(&chip->vendor->miscdev)) { + if (misc_register(&chip->vendor.miscdev)) { dev_err(chip->dev, "unable to misc_register %s, minor %d\n", - chip->vendor->miscdev.name, - chip->vendor->miscdev.minor); + chip->vendor.miscdev.name, + chip->vendor.miscdev.minor); put_device(dev); + clear_bit(chip->dev_num, dev_mask); kfree(chip); - dev_mask[i] &= !(1 << j); - return -ENODEV; + return NULL; } spin_lock(&driver_lock); @@ -614,11 +1207,11 @@ dev_num_search_complete: spin_unlock(&driver_lock); - sysfs_create_group(&dev->kobj, chip->vendor->attr_group); + sysfs_create_group(&dev->kobj, chip->vendor.attr_group); chip->bios_dir = tpm_bios_log_setup(devname); - return 0; + return chip; } EXPORT_SYMBOL_GPL(tpm_register_hardware); diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/drivers/char/tpm/tpm.h --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm.h Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.h Mon Jul 03 08:35:12 2006 +0100 @@ -24,6 +24,14 @@ #include <linux/fs.h> #include <linux/miscdevice.h> #include <linux/platform_device.h> +#include <linux/io.h> + +#ifdef CONFIG_XEN +enum tpm_bufsize { + TPM_MIN_BUFFERSIZE = 2048, + TPM_MAX_BUFFERSIZE = 64 * 1024, +}; +#endif enum tpm_timeout { TPM_TIMEOUT = 5, /* msecs */ @@ -41,18 +49,32 @@ extern ssize_t tpm_show_pcrs(struct devi char *); extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr, char *); +extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr, + char *); extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr, const char *, size_t); +extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr, + char *); +extern ssize_t tpm_show_active(struct device *, struct device_attribute *attr, + char *); +extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr, + char *); +extern ssize_t tpm_show_temp_deactivated(struct device *, + struct device_attribute *attr, char *); struct tpm_chip; struct tpm_vendor_specific { - u8 req_complete_mask; - u8 req_complete_val; - u8 req_canceled; + const u8 req_complete_mask; + const u8 req_complete_val; + const u8 req_canceled; +#ifdef CONFIG_XEN u32 buffersize; +#endif void __iomem *iobase; /* ioremapped address */ unsigned long base; /* TPM base address */ + + int irq; int region_size; int have_region; @@ -63,6 +85,13 @@ struct tpm_vendor_specific { u8 (*status) (struct tpm_chip *); struct miscdevice miscdev; struct attribute_group *attr_group; + struct list_head list; + int locality; + unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */ + unsigned long duration[3]; /* jiffies */ + + wait_queue_head_t read_queue; + wait_queue_head_t int_queue; }; struct tpm_chip { @@ -75,19 +104,26 @@ struct tpm_chip { /* Data passed to and from the tpm via the read/write calls */ u8 *data_buffer; atomic_t data_pending; +#ifdef CONFIG_XEN atomic_t data_position; +#endif struct semaphore buffer_mutex; struct timer_list user_read_timer; /* user needs to claim result */ struct work_struct work; struct semaphore tpm_mutex; /* tpm is processing */ - struct tpm_vendor_specific *vendor; + struct tpm_vendor_specific vendor; struct dentry **bios_dir; struct list_head list; +#ifdef CONFIG_XEN + void *priv; +#endif }; + +#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) static inline int tpm_read_index(int base, int index) { @@ -101,13 +137,35 @@ static inline void tpm_write_index(int b outb(value & 0xFF, base+1); } +#ifdef CONFIG_XEN static inline u32 get_chip_buffersize(struct tpm_chip *chip) { - return chip->vendor->buffersize; + u32 size = chip->vendor.buffersize; + if (size > TPM_MAX_BUFFERSIZE) { + return TPM_MAX_BUFFERSIZE; + } else if (size < TPM_MIN_BUFFERSIZE) { + return TPM_MIN_BUFFERSIZE; + } + return size; } -extern int tpm_register_hardware(struct device *, - struct tpm_vendor_specific *); +static inline void *chip_get_private(const struct tpm_chip *chip) +{ + return chip->priv; +} + +static inline void chip_set_private(struct tpm_chip *chip, void *priv) +{ + chip->priv = priv; +} +#endif + +extern void tpm_get_timeouts(struct tpm_chip *); +extern void tpm_gen_interrupt(struct tpm_chip *); +extern void tpm_continue_selftest(struct tpm_chip *); +extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); +extern struct tpm_chip* tpm_register_hardware(struct device *, + const struct tpm_vendor_specific *); extern int tpm_open(struct inode *, struct file *); extern int tpm_release(struct inode *, struct file *); extern ssize_t tpm_write(struct file *, const char __user *, size_t, @@ -121,7 +179,7 @@ extern struct dentry ** tpm_bios_log_set extern struct dentry ** tpm_bios_log_setup(char *); extern void tpm_bios_log_teardown(struct dentry **); #else -static inline struct dentry* tpm_bios_log_setup(char *name) +static inline struct dentry ** tpm_bios_log_setup(char *name) { return NULL; } diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c Mon Jul 03 08:35:12 2006 +0100 @@ -29,8 +29,6 @@ enum { STATUS_READY = 0x04 }; -#define MIN(x,y) ((x) < (y)) ? (x) : (y) - struct transmission { struct list_head next; @@ -49,26 +47,6 @@ enum { TRANSMISSION_FLAG_WAS_QUEUED = 0x1 }; -struct vtpm_state { - struct transmission *current_request; - spinlock_t req_list_lock; - wait_queue_head_t req_wait_queue; - - struct list_head queued_requests; - - struct transmission *current_response; - spinlock_t resp_list_lock; - wait_queue_head_t resp_wait_queue; // processes waiting for responses - - struct transmission *req_cancelled; // if a cancellation was encounterd - - u8 vd_status; - u8 flags; - - unsigned long disconnect_time; - - struct tpm_virtual_device *tpmvd; -}; enum { DATAEX_FLAG_QUEUED_ONLY = 0x1 @@ -76,7 +54,6 @@ enum { /* local variables */ -static struct vtpm_state *vtpms; /* local function prototypes */ static int _vtpm_send_queued(struct tpm_chip *chip); @@ -160,11 +137,16 @@ static inline void transmission_free(str /* * Lower layer uses this function to make a response available. */ -int vtpm_vd_recv(const unsigned char *buffer, size_t count, const void *ptr) +int vtpm_vd_recv(const struct tpm_chip *chip, + const unsigned char *buffer, size_t count, + void *ptr) { unsigned long flags; int ret_size = 0; struct transmission *t; + struct vtpm_state *vtpms; + + vtpms = (struct vtpm_state *)chip_get_private(chip); /* * The list with requests must contain one request @@ -173,26 +155,11 @@ int vtpm_vd_recv(const unsigned char *bu */ spin_lock_irqsave(&vtpms->resp_list_lock, flags); if (vtpms->current_request != ptr) { - printk("WARNING: The request pointer is different than the " - "pointer the shared memory driver returned to me. " - "%p != %p\n", - vtpms->current_request, ptr); - } - - /* - * If the request has been cancelled, just quit here - */ - if (vtpms->req_cancelled == (struct transmission *)ptr) { - if (vtpms->current_request == vtpms->req_cancelled) { - vtpms->current_request = NULL; - } - transmission_free(vtpms->req_cancelled); - vtpms->req_cancelled = NULL; spin_unlock_irqrestore(&vtpms->resp_list_lock, flags); return 0; } - if (NULL != (t = vtpms->current_request)) { + if ((t = vtpms->current_request)) { transmission_free(t); vtpms->current_request = NULL; } @@ -217,8 +184,12 @@ int vtpm_vd_recv(const unsigned char *bu /* * Lower layer indicates its status (connected/disconnected) */ -void vtpm_vd_status(u8 vd_status) -{ +void vtpm_vd_status(const struct tpm_chip *chip, u8 vd_status) +{ + struct vtpm_state *vtpms; + + vtpms = (struct vtpm_state *)chip_get_private(chip); + vtpms->vd_status = vd_status; if ((vtpms->vd_status & TPM_VD_STATUS_CONNECTED) == 0) { vtpms->disconnect_time = jiffies; @@ -233,6 +204,9 @@ static int vtpm_recv(struct tpm_chip *ch { int rc = 0; unsigned long flags; + struct vtpm_state *vtpms; + + vtpms = (struct vtpm_state *)chip_get_private(chip); /* * Check if the previous operation only queued the command @@ -251,7 +225,7 @@ static int vtpm_recv(struct tpm_chip *ch * Return a response of up to 30 '0's. */ - count = MIN(count, 30); + count = min_t(size_t, count, 30); memset(buf, 0x0, count); return count; } @@ -270,7 +244,7 @@ static int vtpm_recv(struct tpm_chip *ch if (vtpms->current_response) { struct transmission *t = vtpms->current_response; vtpms->current_response = NULL; - rc = MIN(count, t->response_len); + rc = min(count, t->response_len); memcpy(buf, t->response, rc); transmission_free(t); } @@ -284,6 +258,9 @@ static int vtpm_send(struct tpm_chip *ch int rc = 0; unsigned long flags; struct transmission *t = transmission_alloc(); + struct vtpm_state *vtpms; + + vtpms = (struct vtpm_state *)chip_get_private(chip); if (!t) return -ENOMEM; @@ -327,8 +304,7 @@ static int vtpm_send(struct tpm_chip *ch vtpms->current_request = t; - rc = vtpm_vd_send(chip, - vtpms->tpmvd->tpm_private, + rc = vtpm_vd_send(vtpms->tpm_private, buf, count, t); @@ -373,6 +349,8 @@ static int _vtpm_send_queued(struct tpm_ int error = 0; long flags; unsigned char buffer[1]; + struct vtpm_state *vtpms; + vtpms = (struct vtpm_state *)chip_get_private(chip); spin_lock_irqsave(&vtpms->req_list_lock, flags); @@ -387,8 +365,7 @@ static int _vtpm_send_queued(struct tpm_ vtpms->current_request = qt; spin_unlock_irqrestore(&vtpms->req_list_lock, flags); - rc = vtpm_vd_send(chip, - vtpms->tpmvd->tpm_private, + rc = vtpm_vd_send(vtpms->tpm_private, qt->request, qt->request_len, qt); @@ -427,9 +404,21 @@ static void vtpm_cancel(struct tpm_chip static void vtpm_cancel(struct tpm_chip *chip) { unsigned long flags; + struct vtpm_state *vtpms = (struct vtpm_state *)chip_get_private(chip); + spin_lock_irqsave(&vtpms->resp_list_lock,flags); - vtpms->req_cancelled = vtpms->current_request; + if (!vtpms->current_response && vtpms->current_request) { + spin_unlock_irqrestore(&vtpms->resp_list_lock, flags); + interruptible_sleep_on(&vtpms->resp_wait_queue); + spin_lock_irqsave(&vtpms->resp_list_lock,flags); + } + + if (vtpms->current_response) { + struct transmission *t = vtpms->current_response; + vtpms->current_response = NULL; + transmission_free(t); + } spin_unlock_irqrestore(&vtpms->resp_list_lock,flags); } @@ -438,6 +427,9 @@ static u8 vtpm_status(struct tpm_chip *c { u8 rc = 0; unsigned long flags; + struct vtpm_state *vtpms; + + vtpms = (struct vtpm_state *)chip_get_private(chip); spin_lock_irqsave(&vtpms->resp_list_lock, flags); /* @@ -449,7 +441,10 @@ static u8 vtpm_status(struct tpm_chip *c if (vtpms->current_response || 0 != (vtpms->flags & DATAEX_FLAG_QUEUED_ONLY)) { rc = STATUS_DATA_AVAIL; - } + } else if (!vtpms->current_response && !vtpms->current_request) { + rc = STATUS_READY; + } + spin_unlock_irqrestore(&vtpms->resp_list_lock, flags); return rc; } @@ -465,18 +460,29 @@ static struct file_operations vtpm_ops = static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); +static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL); +static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); +static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); +static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, + NULL); static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL); static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel); static struct attribute *vtpm_attrs[] = { &dev_attr_pubek.attr, &dev_attr_pcrs.attr, + &dev_attr_enabled.attr, + &dev_attr_active.attr, + &dev_attr_owned.attr, + &dev_attr_temp_deactivated.attr, &dev_attr_caps.attr, &dev_attr_cancel.attr, NULL, }; static struct attribute_group vtpm_attr_grp = { .attrs = vtpm_attrs }; + +#define TPM_LONG_TIMEOUT (10 * 60 * HZ) static struct tpm_vendor_specific tpm_vtpm = { .recv = vtpm_recv, @@ -486,61 +492,56 @@ static struct tpm_vendor_specific tpm_vt .req_complete_mask = STATUS_BUSY | STATUS_DATA_AVAIL, .req_complete_val = STATUS_DATA_AVAIL, .req_canceled = STATUS_READY, - .base = 0, .attr_group = &vtpm_attr_grp, .miscdev = { .fops = &vtpm_ops, }, -}; - -static struct platform_device *pdev; - -int __init init_vtpm(struct tpm_virtual_device *tvd) -{ - int rc; - - /* vtpms is global - only allow one user */ - if (vtpms) - return -EBUSY; + .duration = { + TPM_LONG_TIMEOUT, + TPM_LONG_TIMEOUT, + TPM_LONG_TIMEOUT, + }, +}; + +struct tpm_chip *init_vtpm(struct device *dev, + struct tpm_virtual_device *tvd, + struct tpm_private *tp) +{ + long rc; + struct tpm_chip *chip; + struct vtpm_state *vtpms; vtpms = kzalloc(sizeof(struct vtpm_state), GFP_KERNEL); if (!vtpms) - return -ENOMEM; + return ERR_PTR(-ENOMEM); vtpm_state_init(vtpms); vtpms->tpmvd = tvd; - - pdev = platform_device_register_simple("tpm_vtpm", -1, NULL, 0); - if (IS_ERR(pdev)) { - rc = PTR_ERR(pdev); - goto err_free_mem; - } + vtpms->tpm_private = tp; if (tvd) tpm_vtpm.buffersize = tvd->max_tx_size; - if ((rc = tpm_register_hardware(&pdev->dev, &tpm_vtpm)) < 0) { - goto err_unreg_pdev; - } - - return 0; - -err_unreg_pdev: - platform_device_unregister(pdev); + chip = tpm_register_hardware(dev, &tpm_vtpm); + if (!chip) { + rc = -ENODEV; + goto err_free_mem; + } + + chip_set_private(chip, vtpms); + + return chip; + err_free_mem: kfree(vtpms); - vtpms = NULL; - - return rc; -} - -void __exit cleanup_vtpm(void) -{ - struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); - if (chip) { - tpm_remove_hardware(chip->dev); - platform_device_unregister(pdev); - } + + return ERR_PTR(rc); +} + +void cleanup_vtpm(struct device *dev) +{ + struct tpm_chip *chip = dev_get_drvdata(dev); + struct vtpm_state *vtpms = (struct vtpm_state*)chip_get_private(chip); + tpm_remove_hardware(dev); kfree(vtpms); - vtpms = NULL; -} +} diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h Mon Jul 03 08:35:12 2006 +0100 @@ -12,6 +12,26 @@ struct tpm_virtual_device { * for allocation of buffers. */ unsigned int max_tx_size; +}; + +struct vtpm_state { + struct transmission *current_request; + spinlock_t req_list_lock; + wait_queue_head_t req_wait_queue; + + struct list_head queued_requests; + + struct transmission *current_response; + spinlock_t resp_list_lock; + wait_queue_head_t resp_wait_queue; // processes waiting for responses + + u8 vd_status; + u8 flags; + + unsigned long disconnect_time; + + struct tpm_virtual_device *tpmvd; + /* * The following is a private structure of the underlying * driver. It is passed as parameter in the send function. @@ -19,20 +39,30 @@ struct tpm_virtual_device { struct tpm_private *tpm_private; }; + enum vdev_status { TPM_VD_STATUS_DISCONNECTED = 0x0, TPM_VD_STATUS_CONNECTED = 0x1 }; /* this function is called from tpm_vtpm.c */ -int vtpm_vd_send(struct tpm_chip *tc, - struct tpm_private * tp, +int vtpm_vd_send(struct tpm_private * tp, const u8 * buf, size_t count, void *ptr); /* these functions are offered by tpm_vtpm.c */ -int __init init_vtpm(struct tpm_virtual_device *); -void __exit cleanup_vtpm(void); -int vtpm_vd_recv(const unsigned char *buffer, size_t count, const void *ptr); -void vtpm_vd_status(u8 status); +struct tpm_chip *init_vtpm(struct device *, + struct tpm_virtual_device *, + struct tpm_private *); +void cleanup_vtpm(struct device *); +int vtpm_vd_recv(const struct tpm_chip* chip, + const unsigned char *buffer, size_t count, void *ptr); +void vtpm_vd_status(const struct tpm_chip *, u8 status); + +static inline struct tpm_private *tpm_private_from_dev(struct device *dev) +{ + struct tpm_chip *chip = dev_get_drvdata(dev); + struct vtpm_state *vtpms = chip_get_private(chip); + return vtpms->tpm_private; +} #endif diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c Mon Jul 03 08:35:12 2006 +0100 @@ -34,6 +34,7 @@ */ #include <linux/errno.h> +#include <linux/err.h> #include <linux/interrupt.h> #include <linux/mutex.h> #include <asm/uaccess.h> @@ -41,12 +42,15 @@ #include <xen/interface/grant_table.h> #include <xen/interface/io/tpmif.h> #include <xen/xenbus.h> +#include "tpm.h" #include "tpm_vtpm.h" #undef DEBUG /* local structures */ struct tpm_private { + struct tpm_chip *chip; + tpmif_tx_interface_t *tx; atomic_t refcnt; unsigned int evtchn; @@ -60,6 +64,7 @@ struct tpm_private { atomic_t tx_busy; void *tx_remember; + domid_t backend_id; wait_queue_head_t wait_q; @@ -95,6 +100,7 @@ static int tpm_xmit(struct tpm_private * const u8 * buf, size_t count, int userbuffer, void *remember); static void destroy_tpmring(struct tpm_private *tp); +void __exit tpmif_exit(void); #define DPRINTK(fmt, args...) \ pr_debug("xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args) @@ -199,8 +205,7 @@ static DEFINE_MUTEX(suspend_lock); /* * Send data via this module by calling this function */ -int vtpm_vd_send(struct tpm_chip *chip, - struct tpm_private *tp, +int vtpm_vd_send(struct tpm_private *tp, const u8 * buf, size_t count, void *ptr) { int sent; @@ -331,7 +336,7 @@ static void backend_changed(struct xenbu static void backend_changed(struct xenbus_device *dev, enum xenbus_state backend_state) { - struct tpm_private *tp = dev->dev.driver_data; + struct tpm_private *tp = tpm_private_from_dev(&dev->dev); DPRINTK("\n"); switch (backend_state) { @@ -358,6 +363,9 @@ static void backend_changed(struct xenbu } } +struct tpm_virtual_device tvd = { + .max_tx_size = PAGE_SIZE * TPMIF_TX_RING_SIZE, +}; static int tpmfront_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) @@ -368,6 +376,12 @@ static int tpmfront_probe(struct xenbus_ if (!tp) return -ENOMEM; + + tp->chip = init_vtpm(&dev->dev, &tvd, tp); + + if (IS_ERR(tp->chip)) { + return PTR_ERR(tp->chip); + } err = xenbus_scanf(XBT_NIL, dev->nodename, "handle", "%i", &handle); @@ -380,12 +394,10 @@ static int tpmfront_probe(struct xenbus_ } tp->dev = dev; - dev->dev.driver_data = tp; err = talk_to_backend(dev, tp); if (err) { tpm_private_put(); - dev->dev.driver_data = NULL; return err; } return 0; @@ -394,16 +406,16 @@ static int tpmfront_probe(struct xenbus_ static int tpmfront_remove(struct xenbus_device *dev) { - struct tpm_private *tp = (struct tpm_private *)dev->dev.driver_data; + struct tpm_private *tp = tpm_private_from_dev(&dev->dev); destroy_tpmring(tp); + cleanup_vtpm(&dev->dev); return 0; } static int tpmfront_suspend(struct xenbus_device *dev) { - struct tpm_private *tp = (struct tpm_private *)dev->dev.driver_data; + struct tpm_private *tp = tpm_private_from_dev(&dev->dev); u32 ctr; - /* lock, so no app can send */ mutex_lock(&suspend_lock); tp->is_suspended = 1; @@ -431,7 +443,7 @@ static int tpmfront_suspend(struct xenbu static int tpmfront_resume(struct xenbus_device *dev) { - struct tpm_private *tp = (struct tpm_private *)dev->dev.driver_data; + struct tpm_private *tp = tpm_private_from_dev(&dev->dev); destroy_tpmring(tp); return talk_to_backend(dev, tp); } @@ -548,7 +560,7 @@ static void tpmif_rx_action(unsigned lon offset += tocopy; } - vtpm_vd_recv(buffer, received, tp->tx_remember); + vtpm_vd_recv(tp->chip, buffer, received, tp->tx_remember); kfree(buffer); exit: @@ -638,6 +650,7 @@ static int tpm_xmit(struct tpm_private * atomic_set(&tp->tx_busy, 1); tp->tx_remember = remember; + mb(); DPRINTK("Notifying backend via event channel %d\n", @@ -657,9 +670,9 @@ static void tpmif_notify_upperlayer(stru * to the BE. */ if (tp->is_connected) { - vtpm_vd_status(TPM_VD_STATUS_CONNECTED); + vtpm_vd_status(tp->chip, TPM_VD_STATUS_CONNECTED); } else { - vtpm_vd_status(TPM_VD_STATUS_DISCONNECTED); + vtpm_vd_status(tp->chip, TPM_VD_STATUS_DISCONNECTED); } } @@ -699,13 +712,10 @@ static void tpmif_set_connected_state(st * ================================================================= */ -struct tpm_virtual_device tvd = { - .max_tx_size = PAGE_SIZE * TPMIF_TX_RING_SIZE, -}; static int __init tpmif_init(void) { - int rc; + long rc = 0; struct tpm_private *tp; if ((xen_start_info->flags & SIF_INITDOMAIN)) { @@ -717,11 +727,6 @@ static int __init tpmif_init(void) rc = -ENOMEM; goto failexit; } - - tvd.tpm_private = tp; - rc = init_vtpm(&tvd); - if (rc) - goto init_vtpm_failed; IPRINTK("Initialising the vTPM driver.\n"); if ( gnttab_alloc_grant_references ( TPMIF_TX_RING_SIZE, @@ -734,19 +739,16 @@ static int __init tpmif_init(void) return 0; gnttab_alloc_failed: - cleanup_vtpm(); -init_vtpm_failed: tpm_private_put(); failexit: - return rc; -} - - -static void __exit tpmif_exit(void) + return (int)rc; +} + + +void __exit tpmif_exit(void) { exit_tpm_xenbus(); - cleanup_vtpm(); tpm_private_put(); gnttab_free_grant_references(gref_head); } diff -r 4b51d081378d -r 856caf975abd 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:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Mon Jul 03 08:35:12 2006 +0100 @@ -75,6 +75,9 @@ static unsigned long current_pages; static unsigned long current_pages; static unsigned long target_pages; +/* We increase/decrease in batches which fit in a page */ +static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)]; + /* VM /proc information for memory */ extern unsigned long totalram_pages; @@ -95,6 +98,11 @@ static void balloon_process(void *unused static void balloon_process(void *unused); static DECLARE_WORK(balloon_worker, balloon_process, NULL); static struct timer_list balloon_timer; + +/* When ballooning out (allocating memory to return to Xen) we don't really + want the kernel to try too hard since that can trigger the oom killer. */ +#define GFP_BALLOON \ + (GFP_HIGHUSER | __GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC) #define PAGE_TO_LIST(p) (&(p)->lru) #define LIST_TO_PAGE(l) list_entry((l), struct page, lru) @@ -172,7 +180,7 @@ static unsigned long current_target(void static int increase_reservation(unsigned long nr_pages) { - unsigned long *frame_list, frame, pfn, i, flags; + unsigned long pfn, i, flags; struct page *page; long rc; struct xen_memory_reservation reservation = { @@ -181,15 +189,8 @@ static int increase_reservation(unsigned .domid = DOMID_SELF }; - if (nr_pages > (PAGE_SIZE / sizeof(unsigned long))) - nr_pages = PAGE_SIZE / sizeof(unsigned long); - - frame_list = (unsigned long *)__get_free_page(GFP_KERNEL); - if (frame_list == NULL) { - frame_list = &frame; - if (nr_pages > 1) - nr_pages = 1; - } + if (nr_pages > ARRAY_SIZE(frame_list)) + nr_pages = ARRAY_SIZE(frame_list); balloon_lock(flags); @@ -253,15 +254,12 @@ static int increase_reservation(unsigned out: balloon_unlock(flags); - if (frame_list != &frame) - free_page((unsigned long)frame_list); - return 0; } static int decrease_reservation(unsigned long nr_pages) { - unsigned long *frame_list, frame, pfn, i, flags; + unsigned long pfn, i, flags; struct page *page; void *v; int need_sleep = 0; @@ -272,18 +270,11 @@ static int decrease_reservation(unsigned .domid = DOMID_SELF }; - if (nr_pages > (PAGE_SIZE / sizeof(unsigned long))) - nr_pages = PAGE_SIZE / sizeof(unsigned long); - - frame_list = (unsigned long *)__get_free_page(GFP_KERNEL); - if (frame_list == NULL) { - frame_list = &frame; - if (nr_pages > 1) - nr_pages = 1; - } + if (nr_pages > ARRAY_SIZE(frame_list)) + nr_pages = ARRAY_SIZE(frame_list); for (i = 0; i < nr_pages; i++) { - if ((page = alloc_page(GFP_HIGHUSER)) == NULL) { + if ((page = alloc_page(GFP_BALLOON)) == NULL) { nr_pages = i; need_sleep = 1; break; @@ -330,9 +321,6 @@ static int decrease_reservation(unsigned totalram_pages = current_pages; balloon_unlock(flags); - - if (frame_list != &frame) - free_page((unsigned long)frame_list); return need_sleep; } diff -r 4b51d081378d -r 856caf975abd 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:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Mon Jul 03 08:35:12 2006 +0100 @@ -75,8 +75,6 @@ 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, \ @@ -106,56 +104,39 @@ static struct attribute_group vbdstat_gr .attrs = vbdstat_attrs, }; +VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor); +VBD_SHOW(mode, "%s\n", be->mode); + int xenvbd_sysfs_addif(struct xenbus_device *dev) { - int error = 0; + int error; - error = sysfs_create_group(&dev->dev.kobj, - &vbdstat_group); + error = device_create_file(&dev->dev, &dev_attr_physical_device); + if (error) + goto fail1; + + error = device_create_file(&dev->dev, &dev_attr_mode); if (error) - goto fail; - + goto fail2; + + error = sysfs_create_group(&dev->dev.kobj, &vbdstat_group); + if (error) + goto fail3; + return 0; - -fail: - sysfs_remove_group(&dev->dev.kobj, - &vbdstat_group); + +fail3: sysfs_remove_group(&dev->dev.kobj, &vbdstat_group); +fail2: device_remove_file(&dev->dev, &dev_attr_mode); +fail1: device_remove_file(&dev->dev, &dev_attr_physical_device); 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) -{ - struct xenbus_device *dev = to_xenbus_device(_dev); - struct backend_info *be = dev->dev.driver_data; - return sprintf(buf, "%x:%x\n", be->major, be->minor); -} -DEVICE_ATTR(physical_device, S_IRUSR | S_IRGRP | S_IROTH, - show_physical_device, NULL); - - -static ssize_t show_mode(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, "%s\n", be->mode); -} -DEVICE_ATTR(mode, S_IRUSR | S_IRGRP | S_IROTH, show_mode, NULL); - + sysfs_remove_group(&dev->dev.kobj, &vbdstat_group); + device_remove_file(&dev->dev, &dev_attr_mode); + device_remove_file(&dev->dev, &dev_attr_physical_device); +} static int blkback_remove(struct xenbus_device *dev) { @@ -176,9 +157,8 @@ static int blkback_remove(struct xenbus_ be->blkif = NULL; } - device_remove_file(&dev->dev, &dev_attr_physical_device); - device_remove_file(&dev->dev, &dev_attr_mode); - xenvbd_sysfs_delif(dev); + if (be->major || be->minor) + xenvbd_sysfs_delif(dev); kfree(be); dev->dev.driver_data = NULL; @@ -293,15 +273,18 @@ static void backend_changed(struct xenbu err = vbd_create(be->blkif, handle, major, minor, (NULL == strchr(be->mode, 'w'))); if (err) { - be->major = 0; - be->minor = 0; + be->major = be->minor = 0; xenbus_dev_fatal(dev, err, "creating vbd structure"); return; } - device_create_file(&dev->dev, &dev_attr_physical_device); - device_create_file(&dev->dev, &dev_attr_mode); - xenvbd_sysfs_addif(dev); + err = xenvbd_sysfs_addif(dev); + if (err) { + vbd_free(&be->blkif->vbd); + be->major = be->minor = 0; + xenbus_dev_fatal(dev, err, "creating sysfs entries"); + return; + } /* We're potentially connected now */ update_blkif_status(be->blkif); diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/drivers/xen/core/evtchn.c --- a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c Mon Jul 03 08:35:12 2006 +0100 @@ -219,7 +219,10 @@ asmlinkage void evtchn_do_upcall(struct vcpu_info->evtchn_upcall_pending = 0; - /* NB. No need for a barrier here -- XCHG is a barrier on x86. */ +#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */ + /* Clear master pending flag /before/ clearing selector flag. */ + rmb(); +#endif l1 = xchg(&vcpu_info->evtchn_pending_sel, 0); while (l1 != 0) { l1i = __ffs(l1); diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/drivers/xen/core/gnttab.c --- a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c Mon Jul 03 08:35:12 2006 +0100 @@ -169,7 +169,7 @@ int gnttab_end_foreign_access_ref(grant_ printk(KERN_ALERT "WARNING: g.e. still in use!\n"); return 0; } - } while ((nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) != + } while ((nflags = synch_cmpxchg_subword(&shared[ref].flags, flags, 0)) != flags); return 1; @@ -224,7 +224,7 @@ unsigned long gnttab_end_foreign_transfe * reference and return failure (== 0). */ while (!((flags = shared[ref].flags) & GTF_transfer_committed)) { - if (synch_cmpxchg(&shared[ref].flags, flags, 0) == flags) + if (synch_cmpxchg_subword(&shared[ref].flags, flags, 0) == flags) return 0; cpu_relax(); } diff -r 4b51d081378d -r 856caf975abd 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:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/core/xen_sysfs.c Mon Jul 03 08:35:12 2006 +0100 @@ -8,12 +8,14 @@ */ #include <linux/config.h> +#include <linux/err.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <asm/hypervisor.h> #include <xen/features.h> #include <xen/hypervisor_sysfs.h> +#include <xen/xenbus.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mike D. Day <ncmike@xxxxxxxxxx>"); @@ -95,6 +97,37 @@ static void xen_sysfs_version_destroy(vo static void xen_sysfs_version_destroy(void) { sysfs_remove_group(&hypervisor_subsys.kset.kobj, &version_group); +} + +/* UUID */ + +static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer) +{ + char *vm, *val; + int ret; + + vm = xenbus_read(XBT_NIL, "vm", "", NULL); + if (IS_ERR(vm)) + return PTR_ERR(vm); + val = xenbus_read(XBT_NIL, vm, "uuid", NULL); + kfree(vm); + if (IS_ERR(val)) + return PTR_ERR(val); + ret = sprintf(buffer, "%s\n", val); + kfree(val); + return ret; +} + +HYPERVISOR_ATTR_RO(uuid); + +static int __init xen_sysfs_uuid_init(void) +{ + return sysfs_create_file(&hypervisor_subsys.kset.kobj, &uuid_attr.attr); +} + +static void xen_sysfs_uuid_destroy(void) +{ + sysfs_remove_file(&hypervisor_subsys.kset.kobj, &uuid_attr.attr); } /* xen compilation attributes */ @@ -314,10 +347,15 @@ static int __init hyper_sysfs_init(void) ret = xen_compilation_init(); if (ret) goto comp_out; + ret = xen_sysfs_uuid_init(); + if (ret) + goto uuid_out; ret = xen_properties_init(); if (!ret) goto out; + xen_sysfs_uuid_destroy(); +uuid_out: xen_compilation_destroy(); comp_out: xen_sysfs_version_destroy(); @@ -331,6 +369,7 @@ static void hyper_sysfs_exit(void) { xen_properties_destroy(); xen_compilation_destroy(); + xen_sysfs_uuid_destroy(); xen_sysfs_version_destroy(); xen_sysfs_type_destroy(); diff -r 4b51d081378d -r 856caf975abd 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:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Mon Jul 03 08:35:12 2006 +0100 @@ -663,6 +663,34 @@ static void netbk_fill_frags(struct sk_b } } +int netbk_get_extras(netif_t *netif, struct netif_extra_info *extras, + int work_to_do) +{ + struct netif_extra_info *extra; + RING_IDX cons = netif->tx.req_cons; + + do { + if (unlikely(work_to_do-- <= 0)) { + DPRINTK("Missing extra info\n"); + return -EBADR; + } + + extra = (struct netif_extra_info *) + RING_GET_REQUEST(&netif->tx, cons); + if (unlikely(!extra->type || + extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) { + netif->tx.req_cons = ++cons; + DPRINTK("Invalid extra type: %d\n", extra->type); + return -EINVAL; + } + + memcpy(&extras[extra->type - 1], extra, sizeof(*extra)); + netif->tx.req_cons = ++cons; + } while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE); + + return work_to_do; +} + /* Called after netfront has transmitted */ static void net_tx_action(unsigned long unused) { @@ -670,7 +698,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; + struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1]; u16 pending_idx; RING_IDX i; gnttab_map_grant_ref_t *mop; @@ -732,16 +760,15 @@ static void net_tx_action(unsigned long work_to_do--; netif->tx.req_cons = ++i; + memset(extras, 0, sizeof(extras)); if (txreq.flags & NETTXF_extra_info) { - if (work_to_do-- <= 0) { - DPRINTK("Missing extra info\n"); - netbk_tx_err(netif, &txreq, i); + work_to_do = netbk_get_extras(netif, extras, + work_to_do); + if (unlikely(work_to_do < 0)) { + netbk_tx_err(netif, &txreq, 0); continue; } - - memcpy(&txtra, RING_GET_REQUEST(&netif->tx, i), - sizeof(txtra)); - netif->tx.req_cons = ++i; + i = netif->tx.req_cons; } ret = netbk_count_requests(netif, &txreq, work_to_do); @@ -751,7 +778,7 @@ static void net_tx_action(unsigned long } i += ret; - if (unlikely(ret > MAX_SKB_FRAGS + 1)) { + if (unlikely(ret > MAX_SKB_FRAGS)) { DPRINTK("Too many frags\n"); netbk_tx_err(netif, &txreq, i); continue; @@ -788,10 +815,24 @@ static void net_tx_action(unsigned long /* 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; + if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) { + struct netif_extra_info *gso; + gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; + + /* Currently on TCPv4 S.O. is supported. */ + if (gso->u.gso.type != XEN_NETIF_GSO_TCPV4) { + DPRINTK("Bad GSO type %d.\n", gso->u.gso.type); + kfree_skb(skb); + netbk_tx_err(netif, &txreq, i); + break; + } + + skb_shinfo(skb)->gso_size = gso->u.gso.size; + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; + + /* Header must be checked, and gso_segs computed. */ + skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; + skb_shinfo(skb)->gso_segs = 0; } gnttab_set_map_op(mop, MMAP_VADDR(pending_idx), diff -r 4b51d081378d -r 856caf975abd 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:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Mon Jul 03 08:35:12 2006 +0100 @@ -101,11 +101,13 @@ static int netback_probe(struct xenbus_d goto abort_transaction; } +#if 0 /* KAF: After the protocol is finalised. */ err = xenbus_printf(xbt, dev->nodename, "feature-tso", "%d", 1); if (err) { message = "writing feature-tso"; goto abort_transaction; } +#endif err = xenbus_transaction_end(xbt, 0); } while (err == -EAGAIN); diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Mon Jul 03 08:35:12 2006 +0100 @@ -463,7 +463,7 @@ static int network_open(struct net_devic static inline int netfront_tx_slot_available(struct netfront_info *np) { - return RING_FREE_REQUESTS(&np->tx) >= MAX_SKB_FRAGS + 1; + return RING_FREE_REQUESTS(&np->tx) >= MAX_SKB_FRAGS + 2; } static inline void network_maybe_wake_tx(struct net_device *dev) @@ -491,7 +491,13 @@ static void network_tx_buf_gc(struct net rmb(); /* Ensure we see responses up to 'rp'. */ for (cons = np->tx.rsp_cons; cons != prod; cons++) { - id = RING_GET_RESPONSE(&np->tx, cons)->id; + struct netif_tx_response *txrsp; + + txrsp = RING_GET_RESPONSE(&np->tx, cons); + if (txrsp->status == NETIF_RSP_NULL) + continue; + + id = txrsp->id; skb = np->tx_skbs[id]; if (unlikely(gnttab_query_foreign_access( np->grant_tx_ref[id]) != 0)) { @@ -719,6 +725,7 @@ static int network_start_xmit(struct sk_ unsigned short id; struct netfront_info *np = netdev_priv(dev); struct netif_tx_request *tx; + struct netif_extra_info *extra; char *data = skb->data; RING_IDX i; grant_ref_t ref; @@ -739,7 +746,8 @@ static int network_start_xmit(struct sk_ spin_lock_irq(&np->tx_lock); if (unlikely(!netif_carrier_ok(dev) || - (frags > 1 && !xennet_can_sg(dev)))) { + (frags > 1 && !xennet_can_sg(dev)) || + netif_needs_gso(dev, skb))) { spin_unlock_irq(&np->tx_lock); goto drop; } @@ -762,10 +770,29 @@ static int network_start_xmit(struct sk_ tx->size = len; tx->flags = 0; + extra = NULL; + if (skb->ip_summed == CHECKSUM_HW) /* local packet? */ tx->flags |= NETTXF_csum_blank | NETTXF_data_validated; if (skb->proto_data_valid) /* remote but checksummed? */ tx->flags |= NETTXF_data_validated; + + if (skb_shinfo(skb)->gso_size) { + struct netif_extra_info *gso = (struct netif_extra_info *) + RING_GET_REQUEST(&np->tx, ++i); + + if (extra) + extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE; + else + tx->flags |= NETTXF_extra_info; + + gso->u.gso.size = skb_shinfo(skb)->gso_size; + gso->u.gso.type = XEN_NETIF_GSO_TCPV4; + + gso->type = XEN_NETIF_EXTRA_TYPE_GSO; + gso->flags = 0; + extra = gso; + } np->tx.req_prod_pvt = i + 1; @@ -1065,9 +1092,28 @@ static int xennet_set_sg(struct net_devi return ethtool_op_set_sg(dev, data); } +static int xennet_set_tso(struct net_device *dev, u32 data) +{ + if (data) { + struct netfront_info *np = netdev_priv(dev); + int val; + + if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-tso", + "%d", &val) < 0) + val = 0; +#if 0 /* KAF: After the protocol is finalised. */ + if (!val) +#endif + return -ENOSYS; + } + + return ethtool_op_set_tso(dev, data); +} + static void xennet_set_features(struct net_device *dev) { - xennet_set_sg(dev, 1); + if (!xennet_set_sg(dev, 1)) + xennet_set_tso(dev, 1); } static void network_connect(struct net_device *dev) @@ -1148,6 +1194,8 @@ static struct ethtool_ops network_ethtoo .set_tx_csum = ethtool_op_set_tx_csum, .get_sg = ethtool_op_get_sg, .set_sg = xennet_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = xennet_set_tso, }; #ifdef CONFIG_SYSFS diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Mon Jul 03 08:35:12 2006 +0100 @@ -886,29 +886,6 @@ EXPORT_SYMBOL_GPL(unregister_xenstore_no EXPORT_SYMBOL_GPL(unregister_xenstore_notifier); -static int all_devices_ready_(struct device *dev, void *data) -{ - struct xenbus_device *xendev = to_xenbus_device(dev); - int *result = data; - - if (xendev->state != XenbusStateConnected) { - *result = 0; - return 1; - } - - return 0; -} - - -static int all_devices_ready(void) -{ - int ready = 1; - bus_for_each_dev(&xenbus_frontend.bus, NULL, &ready, - all_devices_ready_); - return ready; -} - - void xenbus_probe(void *unused) { BUG_ON((xenstored_ready <= 0)); @@ -1060,6 +1037,43 @@ postcore_initcall(xenbus_probe_init); postcore_initcall(xenbus_probe_init); +static int is_disconnected_device(struct device *dev, void *data) +{ + struct xenbus_device *xendev = to_xenbus_device(dev); + + /* + * A device with no driver will never connect. We care only about + * devices which should currently be in the process of connecting. + */ + if (!dev->driver) + return 0; + + return (xendev->state != XenbusStateConnected); +} + +static int exists_disconnected_device(void) +{ + return bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, + is_disconnected_device); +} + +static int print_device_status(struct device *dev, void *data) +{ + struct xenbus_device *xendev = to_xenbus_device(dev); + + if (!dev->driver) { + /* Information only: is this too noisy? */ + printk(KERN_INFO "XENBUS: Device with no driver: %s\n", + xendev->nodename); + } else if (xendev->state != XenbusStateConnected) { + printk(KERN_WARNING "XENBUS: Timeout connecting " + "to device: %s (state %d)\n", + xendev->nodename, xendev->state); + } + + return 0; +} + /* * On a 10 second timeout, wait for all devices currently configured. We need * to do this to guarantee that the filesystems and / or network devices @@ -1081,13 +1095,12 @@ static int __init wait_for_devices(void) if (!is_running_on_xen()) return -ENODEV; - while (time_before(jiffies, timeout)) { - if (all_devices_ready()) - return 0; + while (time_before(jiffies, timeout) && exists_disconnected_device()) schedule_timeout_interruptible(HZ/10); - } - - printk(KERN_WARNING "XENBUS: Timeout connecting to devices!\n"); + + bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, + print_device_status); + return 0; } diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h Mon Jul 03 08:35:12 2006 +0100 @@ -138,4 +138,6 @@ static __inline__ int synch_var_test_bit synch_const_test_bit((nr),(addr)) : \ synch_var_test_bit((nr),(addr))) +#define synch_cmpxchg_subword synch_cmpxchg + #endif /* __XEN_SYNCH_BITOPS_H__ */ diff -r 4b51d081378d -r 856caf975abd linux-2.6-xen-sparse/include/asm-ia64/synch_bitops.h --- a/linux-2.6-xen-sparse/include/asm-ia64/synch_bitops.h Wed Jun 28 07:52:21 2006 -0600 +++ b/linux-2.6-xen-sparse/include/asm-ia64/synch_bitops.h Mon Jul 03 08:35:12 2006 +0100 @@ -58,4 +58,6 @@ static __inline__ int synch_var_test_bit synch_const_test_bit((nr),(addr)) : \ synch_var_test_bit((nr),(addr))) +#define synch_cmpxchg_subword synch_cmpxchg + #endif /* __XEN_SYNCH_BITOPS_H__ */ diff -r 4b51d081378d -r 856caf975abd patches/linux-2.6.16.13/net-gso.patch --- a/patches/linux-2.6.16.13/net-gso.patch Wed Jun 28 07:52:21 2006 -0600 +++ b/patches/linux-2.6.16.13/net-gso.patch Mon Jul 03 08:35:12 2006 +0100 @@ -2225,7 +2225,7 @@ index d64e2ec..7494823 100644 err = ipcomp_compress(x, skb); iph = skb->nh.iph; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c -index 00aa80e..84130c9 100644 +index 00aa80e..30c81a8 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -257,6 +257,7 @@ #include <linux/smp_lock.h> @@ -2281,7 +2281,7 @@ index 00aa80e..84130c9 100644 from += copy; copied += copy; -@@ -2026,6 +2021,71 @@ int tcp_getsockopt(struct sock *sk, int +@@ -2026,6 +2021,77 @@ int tcp_getsockopt(struct sock *sk, int } @@ -2306,12 +2306,18 @@ index 00aa80e..84130c9 100644 + if (!pskb_may_pull(skb, thlen)) + goto out; + -+ segs = NULL; -+ if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) -+ goto out; -+ + oldlen = (u16)~skb->len; + __skb_pull(skb, thlen); ++ ++ if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { ++ /* Packet is from an untrusted source, reset gso_segs. */ ++ int mss = skb_shinfo(skb)->gso_size; ++ ++ skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss; ++ ++ segs = NULL; ++ goto out; ++ } + + segs = skb_segment(skb, features); + if (IS_ERR(segs)) diff -r 4b51d081378d -r 856caf975abd patches/linux-2.6.16.13/xenoprof-generic.patch --- a/patches/linux-2.6.16.13/xenoprof-generic.patch Wed Jun 28 07:52:21 2006 -0600 +++ b/patches/linux-2.6.16.13/xenoprof-generic.patch Mon Jul 03 08:35:12 2006 +0100 @@ -123,6 +123,21 @@ diff -pru ../pristine-linux-2.6.16.13/dr } } } +diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.h ./drivers/oprofile/buffer_sync.h +--- ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.h 2006-05-03 05:38:44.000000000 +0800 ++++ ./drivers/oprofile/buffer_sync.h 2006-06-27 12:12:09.000000000 +0800 +@@ -9,6 +9,11 @@ + + #ifndef OPROFILE_BUFFER_SYNC_H + #define OPROFILE_BUFFER_SYNC_H ++ ++#define NO_DOMAIN_SWITCH -1 ++#define DOMAIN_SWITCH_START_EVENT1 0 ++#define DOMAIN_SWITCH_START_EVENT2 1 ++#define DOMAIN_SWITCH_STOP_EVENT1 2 + + /* add the necessary profiling hooks */ + int sync_start(void); 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 diff -r 4b51d081378d -r 856caf975abd tools/examples/Makefile --- a/tools/examples/Makefile Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/examples/Makefile Mon Jul 03 08:35:12 2006 +0100 @@ -26,7 +26,7 @@ XEN_SCRIPTS += network-nat vif-nat XEN_SCRIPTS += network-nat vif-nat XEN_SCRIPTS += block XEN_SCRIPTS += block-enbd block-nbd -XEN_SCRIPTS += vtpm vtpm-delete +XEN_SCRIPTS += vtpm vtpm-delete vtpm-addtodb XEN_SCRIPTS += xen-hotplug-cleanup XEN_SCRIPTS += external-device-migrate XEN_SCRIPT_DATA = xen-script-common.sh locking.sh logging.sh diff -r 4b51d081378d -r 856caf975abd tools/examples/vtpm-common.sh --- a/tools/examples/vtpm-common.sh Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/examples/vtpm-common.sh Mon Jul 03 08:35:12 2006 +0100 @@ -347,16 +347,9 @@ function isLocalAddress() { # 2nd: name of the domain to migrate # 3rd: the migration step to perform function vtpm_migration_step() { - local instance res - instance=$(vtpmdb_find_instance $2) - if [ "$instance" == "" ]; then - echo "Error: Translation of domain name ($2) to instance failed. Check /etc/xen/vtpm.db" - log err "Error during translation of domain name" - else - res=$(isLocalAddress $1) - if [ "$res" == "0" ]; then - vtpm_migrate $1 $2 $3 - fi + local res=$(isLocalAddress $1) + if [ "$res" == "0" ]; then + vtpm_migrate $1 $2 $3 fi } diff -r 4b51d081378d -r 856caf975abd tools/firmware/hvmloader/Makefile --- a/tools/firmware/hvmloader/Makefile Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/firmware/hvmloader/Makefile Mon Jul 03 08:35:12 2006 +0100 @@ -45,9 +45,9 @@ LDFLAGS = -m32 -nostdlib -Wl,-N -Wl,-Tt .PHONY: all all: hvmloader -hvmloader: roms.h hvmloader.c acpi_madt.c - $(CC) $(CFLAGS) -c hvmloader.c acpi_madt.c - $(CC) $(LDFLAGS) -o hvmloader.tmp hvmloader.o acpi_madt.o +hvmloader: roms.h hvmloader.c acpi_madt.c mp_tables.c + $(CC) $(CFLAGS) -c hvmloader.c acpi_madt.c mp_tables.c + $(CC) $(LDFLAGS) -o hvmloader.tmp hvmloader.o acpi_madt.o mp_tables.o $(OBJCOPY) hvmloader.tmp hvmloader rm -f hvmloader.tmp diff -r 4b51d081378d -r 856caf975abd tools/firmware/hvmloader/acpi_madt.c --- a/tools/firmware/hvmloader/acpi_madt.c Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/firmware/hvmloader/acpi_madt.c Mon Jul 03 08:35:12 2006 +0100 @@ -51,7 +51,7 @@ static int validate_hvm_info(struct hvm_ } /* xc_vmx_builder wrote hvm info at 0x9F800. Return it. */ -static struct hvm_info_table * +struct hvm_info_table * get_hvm_info_table(void) { struct hvm_info_table *t; diff -r 4b51d081378d -r 856caf975abd tools/firmware/hvmloader/hvmloader.c --- a/tools/firmware/hvmloader/hvmloader.c Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/firmware/hvmloader/hvmloader.c Mon Jul 03 08:35:12 2006 +0100 @@ -23,6 +23,7 @@ */ #include "roms.h" #include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */ +#include <xen/hvm/hvm_info_table.h> /* memory map */ #define VGABIOS_PHYSICAL_ADDRESS 0x000C0000 @@ -71,6 +72,8 @@ asm( extern int get_acpi_enabled(void); extern int acpi_madt_update(unsigned char* acpi_start); +extern void create_mp_tables(void); +struct hvm_info_table *get_hvm_info_table(void); static inline void outw(unsigned short addr, unsigned short val) @@ -162,10 +165,15 @@ int int main(void) { + struct hvm_info_table *t = get_hvm_info_table(); + puts("HVM Loader\n"); puts("Loading ROMBIOS ...\n"); memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios)); + if (t->apic_enabled) + create_mp_tables(); + if (cirrus_check()) { puts("Loading Cirrus VGABIOS ...\n"); memcpy((void *)VGABIOS_PHYSICAL_ADDRESS, diff -r 4b51d081378d -r 856caf975abd tools/firmware/rombios/Makefile --- a/tools/firmware/rombios/Makefile Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/firmware/rombios/Makefile Mon Jul 03 08:35:12 2006 +0100 @@ -1,13 +1,9 @@ BIOS_BUILDS = BIOS-bochs-latest -BIOS_BUILDS = BIOS-bochs-latest -#BIOS_BUILDS += BIOS-bochs-2-processors -#BIOS_BUILDS += BIOS-bochs-4-processors -#BIOS_BUILDS += BIOS-bochs-8-processors .PHONY: all all: bios .PHONY: bios -bios: biossums ${BIOS_BUILDS} +bios: biossums BIOS-bochs-latest .PHONY: clean clean: @@ -26,36 +22,6 @@ BIOS-bochs-latest: rombios.c biossums ./biossums BIOS-bochs-latest rm -f _rombios_.s -BIOS-bochs-2-processors: rombios.c biossums - gcc -DBX_SMP_PROCESSORS=2 -E -P $< > _rombios2_.c - bcc -o rombios2.s -C-c -D__i86__ -0 -S _rombios2_.c - sed -e 's/^\.text//' -e 's/^\.data//' rombios2.s > _rombios2_.s - as86 _rombios2_.s -b tmp2.bin -u- -w- -g -0 -j -O -l rombios2.txt - -perl makesym.perl < rombios2.txt > rombios2.sym - mv tmp2.bin BIOS-bochs-2-processors - ./biossums BIOS-bochs-2-processors - rm -f _rombios2_.s - -BIOS-bochs-4-processors: rombios.c biossums - gcc -DBX_SMP_PROCESSORS=4 -E -P $< > _rombios4_.c - bcc -o rombios4.s -C-c -D__i86__ -0 -S _rombios4_.c - sed -e 's/^\.text//' -e 's/^\.data//' rombios4.s > _rombios4_.s - as86 _rombios4_.s -b tmp4.bin -u- -w- -g -0 -j -O -l rombios4.txt - -perl makesym.perl < rombios4.txt > rombios4.sym - mv tmp4.bin BIOS-bochs-4-processors - ./biossums BIOS-bochs-4-processors - rm -f _rombios4_.s - -BIOS-bochs-8-processors: rombios.c biossums - gcc -DBX_SMP_PROCESSORS=8 -E -P $< > _rombios8_.c - bcc -o rombios8.s -C-c -D__i86__ -0 -S _rombios8_.c - sed -e 's/^\.text//' -e 's/^\.data//' rombios8.s > _rombios8_.s - as86 _rombios8_.s -b tmp8.bin -u- -w- -g -0 -j -O -l rombios8.txt - -perl makesym.perl < rombios8.txt > rombios8.sym - mv tmp8.bin BIOS-bochs-8-processors - ./biossums BIOS-bochs-8-processors - rm -f _rombios8_.s - biossums: biossums.c gcc -o biossums biossums.c diff -r 4b51d081378d -r 856caf975abd tools/firmware/rombios/rombios.c --- a/tools/firmware/rombios/rombios.c Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/firmware/rombios/rombios.c Mon Jul 03 08:35:12 2006 +0100 @@ -10514,6 +10514,34 @@ static Bit8u vgafont8[128*8]= 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, }; +#ifdef HVMASSIST +// +// MP Tables +// just carve out some blank space for HVMLOADER to write the MP tables to +// +// NOTE: There should be enough space for a 32 processor entry MP table +// +ASM_START +.org 0xcc00 +db 0x5F, 0x5F, 0x5F, 0x48, 0x56, 0x4D, 0x4D, 0x50 ;; ___HVMMP +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 64 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 128 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 192 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 256 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 320 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 384 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 448 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 512 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 576 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 640 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 704 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 768 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 832 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 896 bytes +ASM_END + +#else // !HVMASSIST + ASM_START .org 0xcc00 // bcc-generated data will be placed here @@ -10835,3 +10863,5 @@ db 0,0,0,0 ;; MP feature bytes 2-5. #endif ASM_END + +#endif // HVMASSIST diff -r 4b51d081378d -r 856caf975abd tools/libxc/xc_hvm_build.c --- a/tools/libxc/xc_hvm_build.c Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/libxc/xc_hvm_build.c Mon Jul 03 08:35:12 2006 +0100 @@ -4,6 +4,7 @@ #define ELFSIZE 32 #include <stddef.h> +#include <inttypes.h> #include "xg_private.h" #include "xc_elf.h" #include <stdlib.h> @@ -188,7 +189,7 @@ static int setup_guest(int xc_handle, unsigned char e820_map_nr; struct domain_setup_info dsi; - unsigned long long v_end; + uint64_t v_end; unsigned long shared_page_frame = 0; shared_iopage_t *sp; @@ -208,11 +209,11 @@ static int setup_guest(int xc_handle, v_end = (unsigned long long)memsize << 20; IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n" - " Loaded HVM loader: %08lx->%08lx\n" - " TOTAL: %08lx->%016llx\n", + " Loaded HVM loader: %016"PRIx64"->%016"PRIx64"\n" + " TOTAL: %016"PRIx64"->%016"PRIx64"\n", dsi.v_kernstart, dsi.v_kernend, dsi.v_start, v_end); - IPRINTF(" ENTRY ADDRESS: %08lx\n", dsi.v_kernentry); + IPRINTF(" ENTRY ADDRESS: %016"PRIx64"\n", dsi.v_kernentry); if ( (v_end - dsi.v_start) > ((unsigned long long)nr_pages << PAGE_SHIFT) ) { diff -r 4b51d081378d -r 856caf975abd tools/libxc/xc_linux_build.c --- a/tools/libxc/xc_linux_build.c Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/libxc/xc_linux_build.c Mon Jul 03 08:35:12 2006 +0100 @@ -11,6 +11,9 @@ #include <unistd.h> #include <inttypes.h> #include <zlib.h> + +/* Handy for printing out '0' prepended values at native pointer size */ +#define _p(a) ((void *) ((ulong)a)) #if defined(__i386__) #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED) @@ -502,8 +505,6 @@ static int setup_guest(int xc_handle, goto error_out; } -#define _p(a) ((void *) (a)) - IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n" " Loaded kernel: %p->%p\n" " Init. ramdisk: %p->%p\n" @@ -766,9 +767,9 @@ static int setup_guest(int xc_handle, goto error_out; } -#define NR(_l,_h,_s) \ - (((((_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \ - ((_l) & ~((1UL<<(_s))-1))) >> (_s)) +#define NR(_l,_h,_s) \ + (((((unsigned long)(_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \ + ((unsigned long)(_l) & ~((1UL<<(_s))-1))) >> (_s)) #if defined(__i386__) if ( dsi.pae_kernel != PAEKERN_no ) { @@ -796,8 +797,6 @@ static int setup_guest(int xc_handle, break; #endif } - -#define _p(a) ((void *) (a)) IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"); IPRINTF(" Loaded kernel: %p->%p\n", _p(dsi.v_kernstart), @@ -819,8 +818,8 @@ static int setup_guest(int xc_handle, if ( ((v_end - dsi.v_start)>>PAGE_SHIFT) > nr_pages ) { PERROR("Initial guest OS requires too much space\n" - "(%luMB is greater than %luMB limit)\n", - (v_end-dsi.v_start)>>20, nr_pages>>(20-PAGE_SHIFT)); + "(%pMB is greater than %luMB limit)\n", + _p((v_end-dsi.v_start)>>20), nr_pages>>(20-PAGE_SHIFT)); goto error_out; } diff -r 4b51d081378d -r 856caf975abd tools/libxc/xc_linux_save.c --- a/tools/libxc/xc_linux_save.c Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/libxc/xc_linux_save.c Mon Jul 03 08:35:12 2006 +0100 @@ -415,11 +415,11 @@ static int suspend_and_state(int (*suspe ** which entries do not require canonicalization (in particular, those ** entries which map the virtual address reserved for the hypervisor). */ -void canonicalize_pagetable(unsigned long type, unsigned long pfn, - const void *spage, void *dpage) -{ - - int i, pte_last, xen_start, xen_end; +int canonicalize_pagetable(unsigned long type, unsigned long pfn, + const void *spage, void *dpage) +{ + + int i, pte_last, xen_start, xen_end, race = 0; uint64_t pte; /* @@ -481,7 +481,8 @@ void canonicalize_pagetable(unsigned lon is quite feasible under live migration */ DPRINTF("PT Race: [%08lx,%d] pte=%llx, mfn=%08lx\n", type, i, (unsigned long long)pte, mfn); - pfn = 0; /* zap it - we'll retransmit this page later */ + pfn = 0; /* zap it - we'll retransmit this page later */ + race = 1; /* inform the caller of race; fatal if !live */ } else pfn = mfn_to_pfn(mfn); @@ -496,7 +497,7 @@ void canonicalize_pagetable(unsigned lon } - return; + return race; } @@ -567,7 +568,7 @@ int xc_linux_save(int xc_handle, int io_ int rc = 1, i, j, last_iter, iter = 0; int live = (flags & XCFLAGS_LIVE); int debug = (flags & XCFLAGS_DEBUG); - int sent_last_iter, skip_this_iter; + int race = 0, sent_last_iter, skip_this_iter; /* The new domain's shared-info frame number. */ unsigned long shared_info_frame; @@ -1000,7 +1001,11 @@ int xc_linux_save(int xc_handle, int io_ if (pagetype >= L1TAB && pagetype <= L4TAB) { /* We have a pagetable page: need to rewrite it. */ - canonicalize_pagetable(pagetype, pfn, spage, page); + race = + canonicalize_pagetable(pagetype, pfn, spage, page); + + if(race && !live) + goto out; if (ratewrite(io_fd, page, PAGE_SIZE) != PAGE_SIZE) { ERR("Error when writing to state file (4)"); diff -r 4b51d081378d -r 856caf975abd tools/libxc/xc_load_elf.c --- a/tools/libxc/xc_load_elf.c Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/libxc/xc_load_elf.c Mon Jul 03 08:35:12 2006 +0100 @@ -68,7 +68,7 @@ static int parseelfimage(const char *ima Elf_Ehdr *ehdr = (Elf_Ehdr *)image; Elf_Phdr *phdr; Elf_Shdr *shdr; - unsigned long kernstart = ~0UL, kernend=0UL, vaddr, virt_base, elf_pa_off; + Elf_Addr kernstart = ~0, kernend = 0, vaddr, virt_base, elf_pa_off; const char *shstrtab; char *guestinfo=NULL, *p; int h, virt_base_defined, elf_pa_off_defined; @@ -162,15 +162,19 @@ static int parseelfimage(const char *ima /* Initial guess for virt_base is 0 if it is not explicitly defined. */ p = strstr(guestinfo, "VIRT_BASE="); virt_base_defined = (p != NULL); - virt_base = virt_base_defined ? strtoul(p+10, &p, 0) : 0; + virt_base = virt_base_defined ? strtoull(p+10, &p, 0) : 0; /* Initial guess for elf_pa_off is virt_base if not explicitly defined. */ p = strstr(guestinfo, "ELF_PADDR_OFFSET="); elf_pa_off_defined = (p != NULL); - elf_pa_off = elf_pa_off_defined ? strtoul(p+17, &p, 0) : virt_base; + elf_pa_off = elf_pa_off_defined ? strtoull(p+17, &p, 0) : virt_base; if ( elf_pa_off_defined && !virt_base_defined ) - goto bad_image; + { + ERROR("Neither ELF_PADDR_OFFSET nor VIRT_BASE found in __xen_guest" + " section."); + return -EINVAL; + } for ( h = 0; h < ehdr->e_phnum; h++ ) { @@ -179,7 +183,11 @@ static int parseelfimage(const char *ima continue; vaddr = phdr->p_paddr - elf_pa_off + virt_base; if ( (vaddr + phdr->p_memsz) < vaddr ) - goto bad_image; + { + ERROR("ELF program header %d is too large.", h); + return -EINVAL; + } + if ( vaddr < kernstart ) kernstart = vaddr; if ( (vaddr + phdr->p_memsz) > kernend ) @@ -196,13 +204,16 @@ static int parseelfimage(const char *ima dsi->v_kernentry = ehdr->e_entry; if ( (p = strstr(guestinfo, "VIRT_ENTRY=")) != NULL ) - dsi->v_kernentry = strtoul(p+11, &p, 0); + dsi->v_kernentry = strtoull(p+11, &p, 0); if ( (kernstart > kernend) || (dsi->v_kernentry < kernstart) || (dsi->v_kernentry > kernend) || (dsi->v_start > kernstart) ) - goto bad_image; + { + ERROR("ELF start or entries are out of bounds."); + return -EINVAL; + } if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL ) dsi->load_symtab = 1; @@ -214,10 +225,6 @@ static int parseelfimage(const char *ima loadelfsymtab(image, 0, 0, NULL, dsi); return 0; - - bad_image: - ERROR("Malformed ELF image."); - return -EINVAL; } static int diff -r 4b51d081378d -r 856caf975abd tools/libxc/xg_private.h --- a/tools/libxc/xg_private.h Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/libxc/xg_private.h Mon Jul 03 08:35:12 2006 +0100 @@ -132,13 +132,13 @@ typedef unsigned long l4_pgentry_t; struct domain_setup_info { - unsigned long v_start; - unsigned long v_end; - unsigned long v_kernstart; - unsigned long v_kernend; - unsigned long v_kernentry; - - unsigned long elf_paddr_offset; + uint64_t v_start; + uint64_t v_end; + uint64_t v_kernstart; + uint64_t v_kernend; + uint64_t v_kernentry; + + uint64_t elf_paddr_offset; #define PAEKERN_no 0 #define PAEKERN_yes 1 diff -r 4b51d081378d -r 856caf975abd tools/python/xen/xend/XendLogging.py --- a/tools/python/xen/xend/XendLogging.py Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/python/xen/xend/XendLogging.py Mon Jul 03 08:35:12 2006 +0100 @@ -43,7 +43,7 @@ BACKUP_COUNT = 5 BACKUP_COUNT = 5 STDERR_FORMAT = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s" -LOGFILE_FORMAT = "[%(asctime)s %(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s" +LOGFILE_FORMAT = "[%(asctime)s %(name)s %(process)d] %(levelname)s (%(module)s:%(lineno)d) %(message)s" DATE_FORMAT = "%Y-%m-%d %H:%M:%S" diff -r 4b51d081378d -r 856caf975abd tools/python/xen/xm/cfgbootpolicy.py --- a/tools/python/xen/xm/cfgbootpolicy.py Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/python/xen/xm/cfgbootpolicy.py Mon Jul 03 08:35:12 2006 +0100 @@ -22,8 +22,6 @@ import traceback import traceback import tempfile import os, stat -import re -import commands import shutil import string from xen.util.security import ACMError, err diff -r 4b51d081378d -r 856caf975abd tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/python/xen/xm/create.py Mon Jul 03 08:35:12 2006 +0100 @@ -21,11 +21,8 @@ """ import os import os.path -import string import sys import socket -import commands -import time import re import xmlrpclib diff -r 4b51d081378d -r 856caf975abd tools/python/xen/xm/dumppolicy.py --- a/tools/python/xen/xm/dumppolicy.py Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/python/xen/xm/dumppolicy.py Mon Jul 03 08:35:12 2006 +0100 @@ -19,10 +19,6 @@ """ import sys import traceback -import os -import commands -import shutil -import string from xen.util.security import ACMError, err, dump_policy diff -r 4b51d081378d -r 856caf975abd tools/python/xen/xm/labels.py --- a/tools/python/xen/xm/labels.py Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/python/xen/xm/labels.py Mon Jul 03 08:35:12 2006 +0100 @@ -20,9 +20,6 @@ """ import sys import traceback -import os -import commands -import shutil import string from xen.util.security import ACMError, err, list_labels, active_policy from xen.util.security import vm_label_re, res_label_re, all_label_re diff -r 4b51d081378d -r 856caf975abd tools/python/xen/xm/loadpolicy.py --- a/tools/python/xen/xm/loadpolicy.py Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/python/xen/xm/loadpolicy.py Mon Jul 03 08:35:12 2006 +0100 @@ -20,10 +20,6 @@ """ import sys import traceback -import os -import commands -import shutil -import string from xen.util.security import ACMError, err, load_policy diff -r 4b51d081378d -r 856caf975abd tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/python/xen/xm/main.py Mon Jul 03 08:35:12 2006 +0100 @@ -556,7 +556,7 @@ def xm_vcpu_list(args): def xm_reboot(args): - arg_check(args, "reboot", 1, 4) + arg_check(args, "reboot", 1, 3) from xen.xm import shutdown shutdown.main(["shutdown", "-R"] + args) diff -r 4b51d081378d -r 856caf975abd tools/python/xen/xm/makepolicy.py --- a/tools/python/xen/xm/makepolicy.py Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/python/xen/xm/makepolicy.py Mon Jul 03 08:35:12 2006 +0100 @@ -19,10 +19,6 @@ """ import sys import traceback -import os -import commands -import shutil -import string from xen.util.security import ACMError, err, make_policy diff -r 4b51d081378d -r 856caf975abd tools/python/xen/xm/shutdown.py --- a/tools/python/xen/xm/shutdown.py Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/python/xen/xm/shutdown.py Mon Jul 03 08:35:12 2006 +0100 @@ -17,8 +17,6 @@ """Domain shutdown. """ -import string -import sys import time from xen.xend.XendClient import server @@ -92,7 +90,8 @@ def main_all(opts, args): shutdown(opts, None, mode, opts.vals.wait) def main_dom(opts, args): - if len(args) < 1: opts.err('Missing domain') + if len(args) == 0: opts.err('No domain parameter given') + if len(args) > 1: opts.err('No multiple domain parameters allowed') dom = args[0] mode = shutdown_mode(opts) shutdown(opts, [ dom ], mode, opts.vals.wait) diff -r 4b51d081378d -r 856caf975abd tools/xenstat/libxenstat/src/xenstat.c --- a/tools/xenstat/libxenstat/src/xenstat.c Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/xenstat/libxenstat/src/xenstat.c Mon Jul 03 08:35:12 2006 +0100 @@ -20,6 +20,11 @@ #include <stdio.h> #include <string.h> #include <unistd.h> +#include <linux/compiler.h> +#include <fcntl.h> +#include <dirent.h> +#include <sys/types.h> +#include <sys/stat.h> #include <xs.h> #include "xenstat.h" @@ -36,6 +41,7 @@ struct xenstat_handle { struct xs_handle *xshandle; /* xenstore handle */ int page_size; FILE *procnetdev; + DIR *sysfsvbd; char xen_version[VERSION_SIZE]; /* xen version running on this node */ }; @@ -62,6 +68,8 @@ struct xenstat_domain { unsigned int ssid; unsigned int num_networks; xenstat_network *networks; /* Array of length num_networks */ + unsigned int num_vbds; + xenstat_vbd *vbds; }; struct xenstat_vcpu { @@ -82,6 +90,15 @@ struct xenstat_network { unsigned long long terrs; unsigned long long tdrop; }; + +struct xenstat_vbd { + unsigned int dev; + unsigned long long oo_reqs; + unsigned long long rd_reqs; + unsigned long long wr_reqs; +}; +#define SYSFS_VBD_PATH "/sys/devices/xen-backend/" + /* * Data-collection types @@ -108,12 +125,15 @@ static int xenstat_collect_vcpus(xensta static int xenstat_collect_vcpus(xenstat_node * node); static int xenstat_collect_networks(xenstat_node * node); static int xenstat_collect_xen_version(xenstat_node * node); +static int xenstat_collect_vbds(xenstat_node * node); static void xenstat_free_vcpus(xenstat_node * node); static void xenstat_free_networks(xenstat_node * node); static void xenstat_free_xen_version(xenstat_node * node); +static void xenstat_free_vbds(xenstat_node * node); static void xenstat_uninit_vcpus(xenstat_handle * handle); static void xenstat_uninit_networks(xenstat_handle * handle); static void xenstat_uninit_xen_version(xenstat_handle * handle); +static void xenstat_uninit_vbds(xenstat_handle * handle); static char *xenstat_get_domain_name(xenstat_handle * handle, unsigned int domain_id); static xenstat_collector collectors[] = { @@ -122,7 +142,9 @@ static xenstat_collector collectors[] = { XENSTAT_NETWORK, xenstat_collect_networks, xenstat_free_networks, xenstat_uninit_networks }, { XENSTAT_XEN_VERSION, xenstat_collect_xen_version, - xenstat_free_xen_version, xenstat_uninit_xen_version } + xenstat_free_xen_version, xenstat_uninit_xen_version }, + { XENSTAT_VBD, xenstat_collect_vbds, + xenstat_free_vbds, xenstat_uninit_vbds } }; #define NUM_COLLECTORS (sizeof(collectors)/sizeof(xenstat_collector)) @@ -259,6 +281,8 @@ xenstat_node *xenstat_get_node(xenstat_h domain->ssid = domaininfo[i].ssidref; domain->num_networks = 0; domain->networks = NULL; + domain->num_vbds = 0; + domain->vbds = NULL; domain++; } @@ -448,6 +472,21 @@ xenstat_network *xenstat_domain_network( { if (domain->networks && 0 <= network && network < domain->num_networks) return &(domain->networks[network]); + return NULL; +} + +/* Get the number of VBDs for a given domain */ +unsigned int xenstat_domain_num_vbds(xenstat_domain * domain) +{ + return domain->num_vbds; +} + +/* Get the VBD handle to obtain VBD stats */ +xenstat_vbd *xenstat_domain_vbd(xenstat_domain * domain, + unsigned int vbd) +{ + if (domain->vbds && 0 <= vbd && vbd < domain->num_vbds) + return &(domain->vbds[vbd]); return NULL; } @@ -710,6 +749,139 @@ static void xenstat_uninit_xen_version(x { } +/* + * VBD functions + */ + +static int read_attributes_vbd(const char *vbd_directory, const char *what, char *ret, int cap) +{ + static char file_name[80]; + int fd, num_read; + + sprintf(file_name, "%s/%s/%s", SYSFS_VBD_PATH, vbd_directory, what); + fd = open(file_name, O_RDONLY, 0); + if (fd==-1) return -1; + num_read = read(fd, ret, cap - 1); + close(fd); + if (num_read<=0) return -1; + ret[num_read] = '\0'; + return num_read; +} + +/* Collect information about VBDs */ +static int xenstat_collect_vbds(xenstat_node * node) +{ + struct dirent *dp; + + if (node->handle->sysfsvbd == NULL) { + node->handle->sysfsvbd = opendir(SYSFS_VBD_PATH); + if (node->handle->sysfsvbd == NULL) { + perror("Error opening " SYSFS_VBD_PATH); + return 0; + } + } + + rewinddir(node->handle->sysfsvbd); + + for(dp = readdir(node->handle->sysfsvbd); dp != NULL ; + dp = readdir(node->handle->sysfsvbd)) { + xenstat_domain *domain; + xenstat_vbd vbd; + unsigned int domid; + int ret; + char buf[256]; + + + ret = sscanf(dp->d_name, "vbd-%u-%u", &domid, &vbd.dev); + if (ret != 2) { + continue; + } + printf("%s is VBD.\n",dp->d_name); + + domain = xenstat_node_domain(node, domid); + if (domain == NULL) { + fprintf(stderr, + "Found interface vbd-%u-%u but domain %u" + " does not exist.\n", + domid, vbd.dev, domid); + continue; + } + + if((read_attributes_vbd(dp->d_name, "statistics/oo_req", buf, 256)<=0) + || ((ret = sscanf(buf, "%llu", &vbd.oo_reqs)) != 1)) + { + continue; + } + + if((read_attributes_vbd(dp->d_name, "statistics/rd_req", buf, 256)<=0) + || ((ret = sscanf(buf, "%llu", &vbd.rd_reqs)) != 1)) + { + continue; + } + + if((read_attributes_vbd(dp->d_name, "statistics/wr_req", buf, 256)<=0) + || ((ret = sscanf(buf, "%llu", &vbd.wr_reqs)) != 1)) + { + continue; + } + + + if (domain->vbds == NULL) { + domain->num_vbds = 1; + domain->vbds = malloc(sizeof(xenstat_vbd)); + } else { + domain->num_vbds++; + domain->vbds = realloc(domain->vbds, + domain->num_vbds * + sizeof(xenstat_vbd)); + } + if (domain->vbds == NULL) + return 0; + domain->vbds[domain->num_vbds - 1] = vbd; + } + + return 1; +} + +/* Free VBD information */ +static void xenstat_free_vbds(xenstat_node * node) +{ + unsigned int i; + for (i = 0; i < node->num_domains; i++) + free(node->domains[i].vbds); +} + +/* Free VBD information in handle */ +static void xenstat_uninit_vbds(xenstat_handle * handle) +{ + if (handle->sysfsvbd) + closedir(handle->sysfsvbd); +} + +/* Get the major number of VBD device */ +unsigned int xenstat_vbd_dev(xenstat_vbd * vbd) +{ + return vbd->dev; +} + +/* Get the number of OO(Out of) requests */ +unsigned long long xenstat_vbd_oo_reqs(xenstat_vbd * vbd) +{ + return vbd->oo_reqs; +} + +/* Get the number of READ requests */ +unsigned long long xenstat_vbd_rd_reqs(xenstat_vbd * vbd) +{ + return vbd->rd_reqs; +} + +/* Get the number of WRITE requests */ +unsigned long long xenstat_vbd_wr_reqs(xenstat_vbd * vbd) +{ + return vbd->wr_reqs; +} + static char *xenstat_get_domain_name(xenstat_handle *handle, unsigned int domain_id) { char path[80]; diff -r 4b51d081378d -r 856caf975abd tools/xenstat/libxenstat/src/xenstat.h --- a/tools/xenstat/libxenstat/src/xenstat.h Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/xenstat/libxenstat/src/xenstat.h Mon Jul 03 08:35:12 2006 +0100 @@ -23,6 +23,7 @@ typedef struct xenstat_node xenstat_node typedef struct xenstat_node xenstat_node; typedef struct xenstat_vcpu xenstat_vcpu; typedef struct xenstat_network xenstat_network; +typedef struct xenstat_vbd xenstat_vbd; /* Initialize the xenstat library. Returns a handle to be used with * subsequent calls to the xenstat library, or NULL if an error occurs. */ @@ -35,7 +36,8 @@ void xenstat_uninit(xenstat_handle * han #define XENSTAT_VCPU 0x1 #define XENSTAT_NETWORK 0x2 #define XENSTAT_XEN_VERSION 0x4 -#define XENSTAT_ALL (XENSTAT_VCPU|XENSTAT_NETWORK|XENSTAT_XEN_VERSION) +#define XENSTAT_VBD 0x8 +#define XENSTAT_ALL (XENSTAT_VCPU|XENSTAT_NETWORK|XENSTAT_XEN_VERSION|XENSTAT_VBD) /* Get all available information about a node */ xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags); @@ -117,6 +119,13 @@ xenstat_network *xenstat_domain_network( xenstat_network *xenstat_domain_network(xenstat_domain * domain, unsigned int network); +/* Get the number of VBDs for a given domain */ +unsigned int xenstat_domain_num_vbds(xenstat_domain *); + +/* Get the VBD handle to obtain VBD stats */ +xenstat_vbd *xenstat_domain_vbd(xenstat_domain * domain, + unsigned int vbd); + /* * VCPU functions - extract information from a xenstat_vcpu */ @@ -156,3 +165,14 @@ unsigned long long xenstat_network_terrs /* Get the number of transmit drops for this network */ unsigned long long xenstat_network_tdrop(xenstat_network * network); + +/* + * VBD functions - extract information from a xen_vbd + */ +/* Get the device number for Virtual Block Device */ +unsigned int xenstat_vbd_dev(xenstat_vbd * vbd); + +/* Get the number of OO/RD/WR requests for vbd */ +unsigned long long xenstat_vbd_oo_reqs(xenstat_vbd * vbd); +unsigned long long xenstat_vbd_rd_reqs(xenstat_vbd * vbd); +unsigned long long xenstat_vbd_wr_reqs(xenstat_vbd * vbd); diff -r 4b51d081378d -r 856caf975abd tools/xenstat/xentop/xentop.c --- a/tools/xenstat/xentop/xentop.c Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/xenstat/xentop/xentop.c Mon Jul 03 08:35:12 2006 +0100 @@ -27,6 +27,7 @@ #include <sys/time.h> #include <time.h> #include <unistd.h> +#include <linux/kdev_t.h> #include <xenstat.h> @@ -65,6 +66,7 @@ static int compare(unsigned long long, u static int compare(unsigned long long, unsigned long long); static int compare_domains(xenstat_domain **, xenstat_domain **); static unsigned long long tot_net_bytes( xenstat_domain *, int); +static unsigned long long tot_vbd_reqs( xenstat_domain *, int); /* Field functions */ static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2); @@ -91,6 +93,15 @@ static void print_ssid(xenstat_domain *d static void print_ssid(xenstat_domain *domain); static int compare_name(xenstat_domain *domain1, xenstat_domain *domain2); static void print_name(xenstat_domain *domain); +static int compare_vbds(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_vbds(xenstat_domain *domain); +static int compare_vbd_oo(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_vbd_oo(xenstat_domain *domain); +static int compare_vbd_rd(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_vbd_rd(xenstat_domain *domain); +static int compare_vbd_wr(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_vbd_wr(xenstat_domain *domain); + /* Section printing functions */ static void do_summary(void); @@ -99,6 +110,7 @@ static void do_domain(xenstat_domain *); static void do_domain(xenstat_domain *); static void do_vcpu(xenstat_domain *); static void do_network(xenstat_domain *); +static void do_vbd(xenstat_domain *); static void top(void); /* Field types */ @@ -116,6 +128,10 @@ typedef enum field_id { FIELD_NETS, FIELD_NET_TX, FIELD_NET_RX, + FIELD_VBDS, + FIELD_VBD_OO, + FIELD_VBD_RD, + FIELD_VBD_WR, FIELD_SSID } field_id; @@ -140,7 +156,11 @@ field fields[] = { { FIELD_NETS, "NETS", 4, compare_nets, print_nets }, { FIELD_NET_TX, "NETTX(k)", 8, compare_net_tx, print_net_tx }, { FIELD_NET_RX, "NETRX(k)", 8, compare_net_rx, print_net_rx }, - { FIELD_SSID, "SSID", 4, compare_ssid, print_ssid } + { FIELD_NET_RX, "VBDS", 8, compare_vbds, print_vbds }, + { FIELD_NET_RX, "VBD_OO", 8, compare_vbd_oo, print_vbd_oo }, + { FIELD_NET_RX, "VBD_RD", 8, compare_vbd_rd, print_vbd_rd }, + { FIELD_NET_RX, "VBD_WR", 8, compare_vbd_wr, print_vbd_wr }, + { FIELD_SSID, "SSID", 4, compare_ssid, print_ssid } }; const unsigned int NUM_FIELDS = sizeof(fields)/sizeof(field); @@ -158,6 +178,7 @@ unsigned int iterations = 0; unsigned int iterations = 0; int show_vcpus = 0; int show_networks = 0; +int show_vbds = 0; int repeat_header = 0; #define PROMPT_VAL_LEN 80 char *prompt = NULL; @@ -180,6 +201,7 @@ static void usage(const char *program) "-V, --version output version information and exit\n" "-d, --delay=SECONDS seconds between updates (default 3)\n" "-n, --networks output vif network data\n" + "-b, --vbds output vbd block device 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" @@ -289,6 +311,9 @@ static int handle_key(int ch) switch(ch) { case 'n': case 'N': show_networks ^= 1; + break; + case 'b': case 'B': + show_vbds ^= 1; break; case 'r': case 'R': repeat_header ^= 1; @@ -585,6 +610,96 @@ static unsigned long long tot_net_bytes( return total; } +/* Compares number of virtual block devices of two domains, + returning -1,0,1 for * <,=,> */ +static int compare_vbds(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(xenstat_domain_num_vbds(domain1), + xenstat_domain_num_vbds(domain2)); +} + +/* Prints number of virtual block devices statistic */ +static void print_vbds(xenstat_domain *domain) +{ + print("%4u", xenstat_domain_num_vbds(domain)); +} + +/* Compares number of total VBD OO requests of two domains, + returning -1,0,1 * for <,=,> */ +static int compare_vbd_oo(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(tot_vbd_reqs(domain1, FIELD_VBD_OO), + tot_vbd_reqs(domain2, FIELD_VBD_OO)); +} + +/* Prints number of total VBD OO requests statistic */ +static void print_vbd_oo(xenstat_domain *domain) +{ + print("%8llu", tot_vbd_reqs(domain, FIELD_VBD_OO)); +} + +/* Compares number of total VBD READ requests of two domains, + returning -1,0,1 * for <,=,> */ +static int compare_vbd_rd(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(tot_vbd_reqs(domain1, FIELD_VBD_RD), + tot_vbd_reqs(domain2, FIELD_VBD_RD)); +} + +/* Prints number of total VBD READ requests statistic */ +static void print_vbd_rd(xenstat_domain *domain) +{ + print("%8llu", tot_vbd_reqs(domain, FIELD_VBD_RD)); +} + +/* Compares number of total VBD WRITE requests of two domains, + returning -1,0,1 * for <,=,> */ +static int compare_vbd_wr(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(tot_vbd_reqs(domain1,FIELD_VBD_WR), + tot_vbd_reqs(domain2,FIELD_VBD_WR)); +} + +/* Prints number of total VBD WRITE requests statistic */ +static void print_vbd_wr(xenstat_domain *domain) +{ + print("%8llu", tot_vbd_reqs(domain,FIELD_VBD_WR)); +} + +/* Gets number of total VBD requests statistic, + * if flag is FIELD_VBD_OO, then OO requests, + * if flag is FIELD_VBD_RD, then READ requests and + * if flag is FIELD_VBD_WR, then WRITE requests. + */ +static unsigned long long tot_vbd_reqs(xenstat_domain *domain, int flag) +{ + int i = 0; + xenstat_vbd *vbd; + unsigned num_vbds = 0; + unsigned long long total = 0; + + num_vbds = xenstat_domain_num_vbds(domain); + + for ( i=0 ; i < num_vbds ; i++) { + vbd = xenstat_domain_vbd(domain,i); + switch(flag) { + case FIELD_VBD_OO: + total += xenstat_vbd_oo_reqs(vbd); + break; + case FIELD_VBD_RD: + total += xenstat_vbd_rd_reqs(vbd); + break; + case FIELD_VBD_WR: + total += xenstat_vbd_wr_reqs(vbd); + break; + default: + break; + } + } + + return total; +} + /* Compares security id (ssid) of two domains, returning -1,0,1 for <,=,> */ static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2) { @@ -680,6 +795,13 @@ void do_bottom_line(void) addch(A_REVERSE | 'N'); attr_addstr(show_networks ? COLOR_PAIR(1) : 0, "etworks"); addstr(" "); + + /* VBDs */ + attr_addstr(show_vbds ? COLOR_PAIR(1) : 0, "v"); + addch(A_REVERSE | 'B'); + attr_addstr(show_vbds ? COLOR_PAIR(1) : 0, "ds"); + addstr(" "); + /* vcpus */ addch(A_REVERSE | 'V'); @@ -769,6 +891,28 @@ void do_network(xenstat_domain *domain) } } + +/* Output all VBD information */ +void do_vbd(xenstat_domain *domain) +{ + int i = 0; + xenstat_vbd *vbd; + unsigned num_vbds = 0; + + num_vbds = xenstat_domain_num_vbds(domain); + + for (i=0 ; i< num_vbds; i++) { + vbd = xenstat_domain_vbd(domain,i); + + print("VBD %4u [%2x:%2x] OO: %8llu RD: %8llu WR: %8llu\n", + xenstat_vbd_dev(vbd), + MAJOR(xenstat_vbd_dev(vbd)), MINOR(xenstat_vbd_dev(vbd)), + xenstat_vbd_oo_reqs(vbd), + xenstat_vbd_rd_reqs(vbd), + xenstat_vbd_wr_reqs(vbd)); + } +} + static void top(void) { xenstat_domain **domains; @@ -812,6 +956,8 @@ static void top(void) do_vcpu(domains[i]); if (show_networks) do_network(domains[i]); + if (show_vbds) + do_vbd(domains[i]); } if(!batch) @@ -827,6 +973,7 @@ int main(int argc, char **argv) { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { "networks", no_argument, NULL, 'n' }, + { "vbds", no_argument, NULL, 'x' }, { "repeat-header", no_argument, NULL, 'r' }, { "vcpus", no_argument, NULL, 'v' }, { "delay", required_argument, NULL, 'd' }, @@ -834,7 +981,7 @@ int main(int argc, char **argv) { "iterations", required_argument, NULL, 'i' }, { 0, 0, 0, 0 }, }; - const char *sopts = "hVbnvd:bi:"; + const char *sopts = "hVnxrvd:bi:"; if (atexit(cleanup) != 0) fail("Failed to install cleanup handler.\n"); @@ -851,6 +998,9 @@ int main(int argc, char **argv) exit(0); case 'n': show_networks = 1; + break; + case 'x': + show_vbds = 1; break; case 'r': repeat_header = 1; diff -r 4b51d081378d -r 856caf975abd tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py --- a/tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py Mon Jul 03 08:35:12 2006 +0100 @@ -14,16 +14,15 @@ import os.path config = {"vtpm":"instance=1,backend=0"} domain = XmTestDomain(extraConfig=config) +domName = domain.getName() try: console = domain.start() except DomainError, e: if verbose: print e.extra - vtpm_cleanup(domain.getName()) - FAIL("Unable to create domain") - -domName = domain.getName() + vtpm_cleanup(domName) + FAIL("Unable to create domain (%s)" % domName) try: console.sendInput("input") @@ -33,11 +32,11 @@ except ConsoleError, e: FAIL(str(e)) try: - run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs") + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") except ConsoleError, e: saveLog(console.getHistory()) vtpm_cleanup(domName) - FAIL(str(e)) + FAIL("No result from dumping the PCRs") if re.search("No such file",run["output"]): vtpm_cleanup(domName) diff -r 4b51d081378d -r 856caf975abd tools/xm-test/tests/vtpm/03_vtpm-susp_res.py --- a/tools/xm-test/tests/vtpm/03_vtpm-susp_res.py Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/xm-test/tests/vtpm/03_vtpm-susp_res.py Mon Jul 03 08:35:12 2006 +0100 @@ -15,6 +15,7 @@ import os.path config = {"vtpm":"instance=1,backend=0"} domain = XmTestDomain(extraConfig=config) +domName = domain.getName() consoleHistory = "" try: @@ -22,10 +23,8 @@ except DomainError, e: except DomainError, e: if verbose: print e.extra - vtpm_cleanup(domain.getName()) - FAIL("Unable to create domain") - -domName = domain.getName() + vtpm_cleanup(domName) + FAIL("Unable to create domain (%s)" % domName) try: console.sendInput("input") @@ -35,11 +34,11 @@ except ConsoleError, e: FAIL(str(e)) try: - run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs") + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") except ConsoleError, e: saveLog(console.getHistory()) vtpm_cleanup(domName) - FAIL(str(e)) + FAIL("No result from dumping the PCRs") if re.search("No such file",run["output"]): vtpm_cleanup(domName) @@ -48,50 +47,59 @@ consoleHistory = console.getHistory() consoleHistory = console.getHistory() domain.closeConsole() -try: - status, ouptut = traceCommand("xm save %s %s.save" % - (domName, domName), - timeout=30) +loop = 0 +while loop < 3: + try: + status, ouptut = traceCommand("xm save %s %s.save" % + (domName, domName), + timeout=30) -except TimeoutError, e: - saveLog(consoleHistory) - vtpm_cleanup(domName) - FAIL(str(e)) + except TimeoutError, e: + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL(str(e)) -if status != 0: - saveLog(consoleHistory) - vtpm_cleanup(domName) - FAIL("xm save did not succeed") + if status != 0: + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL("xm save did not succeed") -try: - status, ouptut = traceCommand("xm restore %s.save" % - (domName), - timeout=30) -except TimeoutError, e: + try: + status, ouptut = traceCommand("xm restore %s.save" % + (domName), + timeout=30) + except TimeoutError, e: + os.remove("%s.save" % domName) + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL(str(e)) + os.remove("%s.save" % domName) - saveLog(consoleHistory) - vtpm_cleanup(domName) - FAIL(str(e)) -os.remove("%s.save" % domName) + if status != 0: + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL("xm restore did not succeed") -if status != 0: - saveLog(consoleHistory) - vtpm_cleanup(domName) - FAIL("xm restore did not succeed") + try: + console = domain.getConsole() + except ConsoleError, e: + vtpm_cleanup(domName) + FAIL(str(e)) -try: - console = domain.getConsole() -except ConsoleError, e: - vtpm_cleanup(domName) - FAIL(str(e)) + try: + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") + except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL(str(e)) -try: - run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs") -except ConsoleError, e: - saveLog(console.getHistory()) - vtpm_cleanup(domName) - FAIL(str(e)) + if not re.search("PCR-00:",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") + + loop += 1 domain.closeConsole() @@ -99,5 +107,3 @@ domain.stop() vtpm_cleanup(domName) -if not re.search("PCR-00:",run["output"]): - FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") diff -r 4b51d081378d -r 856caf975abd tools/xm-test/tests/vtpm/04_vtpm-loc_migr.py --- a/tools/xm-test/tests/vtpm/04_vtpm-loc_migr.py Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/xm-test/tests/vtpm/04_vtpm-loc_migr.py Mon Jul 03 08:35:12 2006 +0100 @@ -16,6 +16,7 @@ import os.path config = {"vtpm":"instance=1,backend=0"} domain = XmTestDomain(extraConfig=config) +domName = domain.getName() consoleHistory = "" try: @@ -23,10 +24,8 @@ except DomainError, e: except DomainError, e: if verbose: print e.extra - vtpm_cleanup(domain.getName()) - FAIL("Unable to create domain") - -domName = domain.getName() + vtpm_cleanup(domName) + FAIL("Unable to create domain (%s)" % domName) try: console.sendInput("input") @@ -36,11 +35,11 @@ except ConsoleError, e: FAIL(str(e)) try: - run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs") + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") except ConsoleError, e: saveLog(console.getHistory()) vtpm_cleanup(domName) - FAIL(str(e)) + FAIL("No result from dumping the PCRs") if re.search("No such file",run["output"]): vtpm_cleanup(domName) @@ -83,11 +82,17 @@ while loop < 3: FAIL(str(e)) try: - run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs") + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") except ConsoleError, e: saveLog(console.getHistory()) vtpm_cleanup(domName) - FAIL(str(e)) + FAIL("No result from dumping the PCRs") + + if not re.search("PCR-00:",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") + loop += 1 domain.closeConsole() @@ -95,6 +100,3 @@ domain.stop() domain.stop() vtpm_cleanup(domName) - -if not re.search("PCR-00:",run["output"]): - FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") diff -r 4b51d081378d -r 856caf975abd tools/xm-test/tests/vtpm/05_vtpm-loc_migr.py --- a/tools/xm-test/tests/vtpm/05_vtpm-loc_migr.py Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/xm-test/tests/vtpm/05_vtpm-loc_migr.py Mon Jul 03 08:35:12 2006 +0100 @@ -16,6 +16,7 @@ import os.path config = {"vtpm":"instance=1,backend=0"} domain = XmTestDomain(extraConfig=config) +domName = domain.getName() consoleHistory = "" try: @@ -23,10 +24,8 @@ except DomainError, e: except DomainError, e: if verbose: print e.extra - vtpm_cleanup(domain.getName()) - FAIL("Unable to create domain") - -domName = domain.getName() + vtpm_cleanup(domName) + FAIL("Unable to create domain (%s)" % domName) try: console.sendInput("input") @@ -36,11 +35,11 @@ except ConsoleError, e: FAIL(str(e)) try: - run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs") + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") except ConsoleError, e: saveLog(console.getHistory()) vtpm_cleanup(domName) - FAIL(str(e)) + FAIL("No result from dumping the PCRs") if re.search("No such file",run["output"]): vtpm_cleanup(domName) @@ -83,11 +82,17 @@ while loop < 3: FAIL(str(e)) try: - run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs") + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") except ConsoleError, e: saveLog(console.getHistory()) vtpm_cleanup(domName) - FAIL(str(e)) + FAIL("No result from dumping the PCRs") + + if not re.search("PCR-00:",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") + loop += 1 domain.closeConsole() @@ -95,6 +100,3 @@ domain.stop() domain.stop() vtpm_cleanup(domName) - -if not re.search("PCR-00:",run["output"]): - FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") diff -r 4b51d081378d -r 856caf975abd tools/xm-test/tests/vtpm/Makefile.am --- a/tools/xm-test/tests/vtpm/Makefile.am Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/xm-test/tests/vtpm/Makefile.am Mon Jul 03 08:35:12 2006 +0100 @@ -4,7 +4,10 @@ TESTS = 01_vtpm-list_pos.test \ 02_vtpm-cat_pcrs.test \ 03_vtpm-susp_res.test \ 04_vtpm-loc_migr.test \ - 05_vtpm-loc_migr.test + 05_vtpm-loc_migr.test \ + 06_vtpm-susp_res_pcrs.test \ + 07_vtpm-mig_pcrs.test \ + 08_vtpm-mig_pcrs.test XFAIL_TESTS = diff -r 4b51d081378d -r 856caf975abd tools/xm-test/tests/vtpm/vtpm_utils.py --- a/tools/xm-test/tests/vtpm/vtpm_utils.py Wed Jun 28 07:52:21 2006 -0600 +++ b/tools/xm-test/tests/vtpm/vtpm_utils.py Mon Jul 03 08:35:12 2006 +0100 @@ -16,4 +16,4 @@ if output == "": FAIL("virtual TPM manager must be started to run this test") def vtpm_cleanup(domName): - traceCommand("/etc/xen/scripts/vtpm-delete %s" % domName) + traceCommand("/etc/xen/scripts/vtpm-delete %s" % domName) diff -r 4b51d081378d -r 856caf975abd xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/arch/x86/domain.c Mon Jul 03 08:35:12 2006 +0100 @@ -67,16 +67,11 @@ static void default_idle(void) void idle_loop(void) { - int cpu = smp_processor_id(); - for ( ; ; ) { page_scrub_schedule_work(); - default_idle(); - - if ( softirq_pending(cpu) ) - do_softirq(); + do_softirq(); } } diff -r 4b51d081378d -r 856caf975abd xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/arch/x86/hvm/svm/svm.c Mon Jul 03 08:35:12 2006 +0100 @@ -2697,9 +2697,9 @@ asmlinkage void svm_vmexit_handler(struc if (exit_reason == -1) { + svm_dump_vmcb(__func__, vmcb); printk("%s: exit_reason == -1 - Did someone clobber the VMCB\n", __func__); - BUG(); domain_crash_synchronous(); } diff -r 4b51d081378d -r 856caf975abd xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Mon Jul 03 08:35:12 2006 +0100 @@ -36,6 +36,7 @@ #include <xen/kernel.h> #include <asm/shadow.h> #include <xen/keyhandler.h> + #if CONFIG_PAGING_LEVELS >= 3 #include <asm/shadow_64.h> #endif @@ -440,7 +441,6 @@ static int construct_vmcs(struct vcpu *v memset(arch_vmx, 0, sizeof(struct arch_vmx_struct)); spin_lock_init(&arch_vmx->vmcs_lock); - arch_vmx->active_cpu = -1; /* * Create a new VMCS @@ -450,7 +450,7 @@ static int construct_vmcs(struct vcpu *v return -ENOMEM; } - vmx_clear_vmcs(v); + __vmx_clear_vmcs(v); vmx_load_vmcs(v); if ((error = construct_vmcs_controls(arch_vmx))) { @@ -495,6 +495,9 @@ void vmx_destroy_vmcs(struct vcpu *v) void vmx_destroy_vmcs(struct vcpu *v) { struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx; + + if ( arch_vmx->vmcs == NULL ) + return; vmx_clear_vmcs(v); diff -r 4b51d081378d -r 856caf975abd xen/arch/x86/smpboot.c --- a/xen/arch/x86/smpboot.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/arch/x86/smpboot.c Mon Jul 03 08:35:12 2006 +0100 @@ -1197,8 +1197,7 @@ int __devinit __cpu_up(unsigned int cpu) cpu_set(cpu, smp_commenced_mask); while (!cpu_isset(cpu, cpu_online_map)) { mb(); - if (softirq_pending(0)) - do_softirq(); + process_pending_timers(); } return 0; } diff -r 4b51d081378d -r 856caf975abd xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/arch/x86/x86_emulate.c Mon Jul 03 08:35:12 2006 +0100 @@ -118,7 +118,7 @@ static uint8_t opcode_table[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xC7 */ ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM, 0, 0, - 0, 0, ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImm|ModRM, + 0, 0, ByteOp|DstMem|SrcImm|ModRM|Mov, DstMem|SrcImm|ModRM|Mov, /* 0xC8 - 0xCF */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xD7 */ diff -r 4b51d081378d -r 856caf975abd xen/common/elf.c --- a/xen/common/elf.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/common/elf.c Mon Jul 03 08:35:12 2006 +0100 @@ -23,7 +23,7 @@ int parseelfimage(struct domain_setup_in Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr; Elf_Phdr *phdr; Elf_Shdr *shdr; - unsigned long kernstart = ~0UL, kernend=0UL, vaddr, virt_base, elf_pa_off; + Elf_Addr kernstart = ~0, kernend = 0, vaddr, virt_base, elf_pa_off; char *shstrtab, *guestinfo=NULL, *p; char *elfbase = (char *)dsi->image_addr; int h, virt_base_defined, elf_pa_off_defined; @@ -95,7 +95,11 @@ int parseelfimage(struct domain_setup_in elf_pa_off = elf_pa_off_defined ? simple_strtoul(p+17, &p, 0) : virt_base; if ( elf_pa_off_defined && !virt_base_defined ) - goto bad_image; + { + printk("ERROR: Neither ELF_PADDR_OFFSET nor VIRT_BASE found in" + " __xen_guest section.\n"); + return -EINVAL; + } for ( h = 0; h < ehdr->e_phnum; h++ ) { @@ -104,7 +108,11 @@ int parseelfimage(struct domain_setup_in continue; vaddr = phdr->p_paddr - elf_pa_off + virt_base; if ( (vaddr + phdr->p_memsz) < vaddr ) - goto bad_image; + { + printk("ERROR: ELF program header %d is too large.\n", h); + return -EINVAL; + } + if ( vaddr < kernstart ) kernstart = vaddr; if ( (vaddr + phdr->p_memsz) > kernend ) @@ -127,7 +135,10 @@ int parseelfimage(struct domain_setup_in (dsi->v_kernentry < kernstart) || (dsi->v_kernentry > kernend) || (dsi->v_start > kernstart) ) - goto bad_image; + { + printk("ERROR: ELF start or entries are out of bounds.\n"); + return -EINVAL; + } if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL ) dsi->load_symtab = 1; @@ -139,10 +150,6 @@ int parseelfimage(struct domain_setup_in loadelfsymtab(dsi, 0); return 0; - - bad_image: - printk("Malformed ELF image.\n"); - return -EINVAL; } int loadelfimage(struct domain_setup_info *dsi) diff -r 4b51d081378d -r 856caf975abd xen/common/grant_table.c --- a/xen/common/grant_table.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/common/grant_table.c Mon Jul 03 08:35:12 2006 +0100 @@ -287,10 +287,10 @@ __gnttab_map_grant_ref( if ( !(op->flags & GNTMAP_readonly) && !(act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) ) - clear_bit(_GTF_writing, &sha->flags); + gnttab_clear_flag(_GTF_writing, &sha->flags); if ( !act->pin ) - clear_bit(_GTF_reading, &sha->flags); + gnttab_clear_flag(_GTF_reading, &sha->flags); unlock_out: spin_unlock(&rd->grant_table->lock); @@ -425,10 +425,10 @@ __gnttab_unmap_grant_ref( if ( ((act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0) && !(flags & GNTMAP_readonly) ) - clear_bit(_GTF_writing, &sha->flags); + gnttab_clear_flag(_GTF_writing, &sha->flags); if ( act->pin == 0 ) - clear_bit(_GTF_reading, &sha->flags); + gnttab_clear_flag(_GTF_reading, &sha->flags); unmap_out: op->status = rc; @@ -889,11 +889,11 @@ gnttab_release_mappings( } if ( (act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0 ) - clear_bit(_GTF_writing, &sha->flags); + gnttab_clear_flag(_GTF_writing, &sha->flags); } if ( act->pin == 0 ) - clear_bit(_GTF_reading, &sha->flags); + gnttab_clear_flag(_GTF_reading, &sha->flags); spin_unlock(&rd->grant_table->lock); diff -r 4b51d081378d -r 856caf975abd xen/common/memory.c --- a/xen/common/memory.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/common/memory.c Mon Jul 03 08:35:12 2006 +0100 @@ -169,6 +169,15 @@ guest_remove_page( if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) put_page(page); + + if ( unlikely((page->count_info & PGC_count_mask) != 1) ) + { + /* We'll make this a guest-visible error in future, so take heed! */ + DPRINTK("Dom%d freeing in-use page %lx (pseudophys %lx):" + " count=%x type=%lx\n", + d->domain_id, mfn, get_gpfn_from_mfn(mfn), + page->count_info, page->u.inuse.type_info); + } guest_physmap_remove_page(d, gmfn, mfn); diff -r 4b51d081378d -r 856caf975abd xen/common/page_alloc.c --- a/xen/common/page_alloc.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/common/page_alloc.c Mon Jul 03 08:35:12 2006 +0100 @@ -388,7 +388,6 @@ void scrub_heap_pages(void) { void *p; unsigned long pfn; - int cpu = smp_processor_id(); printk("Scrubbing Free RAM: "); @@ -398,8 +397,7 @@ void scrub_heap_pages(void) if ( (pfn % ((100*1024*1024)/PAGE_SIZE)) == 0 ) printk("."); - if ( unlikely(softirq_pending(cpu)) ) - do_softirq(); + process_pending_timers(); /* Quick lock-free check. */ if ( allocated_in_map(pfn) ) diff -r 4b51d081378d -r 856caf975abd xen/common/sched_credit.c --- a/xen/common/sched_credit.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/common/sched_credit.c Mon Jul 03 08:35:12 2006 +0100 @@ -622,9 +622,12 @@ csched_dom_cntl( if ( cmd->u.credit.weight != 0 ) { - csched_priv.weight -= sdom->weight; + if ( !list_empty(&sdom->active_sdom_elem) ) + { + csched_priv.weight -= sdom->weight; + csched_priv.weight += cmd->u.credit.weight; + } sdom->weight = cmd->u.credit.weight; - csched_priv.weight += sdom->weight; } if ( cmd->u.credit.cap != (uint16_t)~0U ) diff -r 4b51d081378d -r 856caf975abd xen/common/schedule.c --- a/xen/common/schedule.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/common/schedule.c Mon Jul 03 08:35:12 2006 +0100 @@ -389,11 +389,32 @@ long do_set_timer_op(s_time_t timeout) long do_set_timer_op(s_time_t timeout) { struct vcpu *v = current; + s_time_t offset = timeout - NOW(); if ( timeout == 0 ) + { stop_timer(&v->timer); + } + else if ( unlikely(timeout < 0) || /* overflow into 64th bit? */ + unlikely((offset > 0) && ((uint32_t)(offset >> 50) != 0)) ) + { + /* + * Linux workaround: occasionally we will see timeouts a long way in + * the future due to wrapping in Linux's jiffy time handling. We check + * for timeouts wrapped negative, and for positive timeouts more than + * about 13 days in the future (2^50ns). The correct fix is to trigger + * an interrupt immediately (since Linux in fact has pending work to + * do in this situation). + */ + DPRINTK("Warning: huge timeout set by domain %d (vcpu %d):" + " %"PRIx64"\n", + v->domain->domain_id, v->vcpu_id, (uint64_t)timeout); + send_timer_event(v); + } else + { set_timer(&v->timer, timeout); + } return 0; } diff -r 4b51d081378d -r 856caf975abd xen/common/softirq.c --- a/xen/common/softirq.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/common/softirq.c Mon Jul 03 08:35:12 2006 +0100 @@ -23,17 +23,23 @@ static softirq_handler softirq_handlers[ asmlinkage void do_softirq(void) { - unsigned int i, cpu = smp_processor_id(); + unsigned int i, cpu; unsigned long pending; - pending = softirq_pending(cpu); - ASSERT(pending != 0); + for ( ; ; ) + { + /* + * Initialise @cpu on every iteration: SCHEDULE_SOFTIRQ may move + * us to another processor. + */ + cpu = smp_processor_id(); + if ( (pending = softirq_pending(cpu)) == 0 ) + break; - do { i = find_first_set_bit(pending); clear_bit(i, &softirq_pending(cpu)); (*softirq_handlers[i])(); - } while ( (pending = softirq_pending(cpu)) != 0 ); + } } void open_softirq(int nr, softirq_handler handler) diff -r 4b51d081378d -r 856caf975abd xen/common/timer.c --- a/xen/common/timer.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/common/timer.c Mon Jul 03 08:35:12 2006 +0100 @@ -327,6 +327,15 @@ static void timer_softirq_action(void) } +void process_pending_timers(void) +{ + unsigned int cpu = smp_processor_id(); + ASSERT(!in_irq() && local_irq_is_enabled()); + if ( test_and_clear_bit(TIMER_SOFTIRQ, &softirq_pending(cpu)) ) + timer_softirq_action(); +} + + static void dump_timerq(unsigned char key) { struct timer *t; diff -r 4b51d081378d -r 856caf975abd xen/drivers/char/console.c --- a/xen/drivers/char/console.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/drivers/char/console.c Mon Jul 03 08:35:12 2006 +0100 @@ -528,8 +528,7 @@ void console_endboot(void) printk("%d... ", 3-i); for ( j = 0; j < 100; j++ ) { - if ( softirq_pending(smp_processor_id()) ) - do_softirq(); + process_pending_timers(); mdelay(10); } } @@ -741,6 +740,15 @@ void panic(const char *fmt, ...) machine_restart(0); } +void __bug(char *file, int line) +{ + console_start_sync(); + debugtrace_dump(); + printk("BUG at %s:%d\n", file, line); + FORCE_CRASH(); + for ( ; ; ) ; +} + /* * Local variables: * mode: C diff -r 4b51d081378d -r 856caf975abd xen/include/asm-ia64/grant_table.h --- a/xen/include/asm-ia64/grant_table.h Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/include/asm-ia64/grant_table.h Mon Jul 03 08:35:12 2006 +0100 @@ -55,4 +55,9 @@ void guest_physmap_add_page(struct domai #define gnttab_log_dirty(d, f) ((void)0) +static inline void gnttab_clear_flag(unsigned long nr, uint16_t *addr) +{ + clear_bit(nr, addr); +} + #endif /* __ASM_GRANT_TABLE_H__ */ diff -r 4b51d081378d -r 856caf975abd xen/include/asm-x86/grant_table.h --- a/xen/include/asm-x86/grant_table.h Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/include/asm-x86/grant_table.h Mon Jul 03 08:35:12 2006 +0100 @@ -33,4 +33,9 @@ int destroy_grant_host_mapping( #define gnttab_log_dirty(d, f) mark_dirty((d), (f)) +static inline void gnttab_clear_flag(unsigned long nr, uint16_t *addr) +{ + clear_bit(nr, addr); +} + #endif /* __ASM_GRANT_TABLE_H__ */ diff -r 4b51d081378d -r 856caf975abd xen/include/public/arch-ia64.h --- a/xen/include/public/arch-ia64.h Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/include/public/arch-ia64.h Mon Jul 03 08:35:12 2006 +0100 @@ -39,6 +39,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); #define MAX_VIRT_CPUS 64 #ifndef __ASSEMBLY__ + +typedef unsigned long xen_ulong_t; #define MAX_NR_SECTION 32 /* at most 32 memory holes */ struct mm_section { diff -r 4b51d081378d -r 856caf975abd xen/include/public/arch-x86_32.h --- a/xen/include/public/arch-x86_32.h Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/include/public/arch-x86_32.h Mon Jul 03 08:35:12 2006 +0100 @@ -97,6 +97,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); #define MAX_VIRT_CPUS 32 #ifndef __ASSEMBLY__ + +typedef unsigned long xen_ulong_t; /* * Send an array of these to HYPERVISOR_set_trap_table() diff -r 4b51d081378d -r 856caf975abd xen/include/public/arch-x86_64.h --- a/xen/include/public/arch-x86_64.h Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/include/public/arch-x86_64.h Mon Jul 03 08:35:12 2006 +0100 @@ -104,6 +104,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); #define MAX_VIRT_CPUS 32 #ifndef __ASSEMBLY__ + +typedef unsigned long xen_ulong_t; /* * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base) diff -r 4b51d081378d -r 856caf975abd xen/include/public/io/netif.h --- a/xen/include/public/io/netif.h Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/include/public/io/netif.h Mon Jul 03 08:35:12 2006 +0100 @@ -23,8 +23,9 @@ * 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 3: netif_tx_extra] (only if request 2 has XEN_NETIF_EXTRA_MORE) * Request 4: netif_tx_request -- NETTXF_more_data + * Request 5: netif_tx_request -- NETTXF_more_data * ... * Request N: netif_tx_request -- 0 */ @@ -41,12 +42,9 @@ #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) +/* Packet to be followed by extra descriptor(s). */ +#define _NETTXF_extra_info (3) +#define NETTXF_extra_info (1U<<_NETTXF_extra_info) struct netif_tx_request { grant_ref_t gref; /* Reference to buffer page */ @@ -57,15 +55,42 @@ struct netif_tx_request { }; typedef struct netif_tx_request netif_tx_request_t; -/* This structure needs to fit within netif_tx_request for compatibility. */ -struct netif_tx_extra { +/* Types of netif_extra_info descriptors. */ +#define XEN_NETIF_EXTRA_TYPE_NONE (0) /* Never used - invalid */ +#define XEN_NETIF_EXTRA_TYPE_GSO (1) /* u.gso */ +#define XEN_NETIF_EXTRA_TYPE_MAX (2) + +/* netif_extra_info flags. */ +#define _XEN_NETIF_EXTRA_FLAG_MORE (0) +#define XEN_NETIF_EXTRA_FLAG_MORE (1U<<_XEN_NETIF_EXTRA_FLAG_MORE) + +/* GSO types - only TCPv4 currently supported. */ +#define XEN_NETIF_GSO_TCPV4 (1) + +/* + * This structure needs to fit within both netif_tx_request and + * netif_rx_response for compatibility. + */ +struct netif_extra_info { + uint8_t type; /* XEN_NETIF_EXTRA_TYPE_* */ + uint8_t flags; /* XEN_NETIF_EXTRA_FLAG_* */ + 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. */ + struct { + /* + * Maximum payload size of each segment. For example, for TCP this + * is just the path MSS. + */ + uint16_t size; + + /* + * GSO type. This determines the protocol of the packet and any + * extra features required to segment the packet properly. + */ + uint16_t type; /* XEN_NETIF_GSO_* */ } gso; + + uint16_t pad[3]; } u; }; diff -r 4b51d081378d -r 856caf975abd xen/include/public/memory.h --- a/xen/include/public/memory.h Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/include/public/memory.h Mon Jul 03 08:35:12 2006 +0100 @@ -32,7 +32,7 @@ struct xen_memory_reservation { XEN_GUEST_HANDLE(xen_pfn_t) extent_start; /* Number of extents, and size/alignment of each (2^extent_order pages). */ - unsigned long nr_extents; + xen_ulong_t nr_extents; unsigned int extent_order; /* @@ -90,7 +90,7 @@ struct xen_memory_exchange { * command will be non-zero. * 5. THIS FIELD MUST BE INITIALISED TO ZERO BY THE CALLER! */ - unsigned long nr_exchanged; + xen_ulong_t nr_exchanged; }; typedef struct xen_memory_exchange xen_memory_exchange_t; DEFINE_XEN_GUEST_HANDLE(xen_memory_exchange_t); @@ -148,8 +148,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_machphys_mfn */ #define XENMEM_machphys_mapping 12 struct xen_machphys_mapping { - unsigned long v_start, v_end; /* Start and end virtual addresses. */ - unsigned long max_mfn; /* Maximum MFN that can be looked up. */ + xen_ulong_t v_start, v_end; /* Start and end virtual addresses. */ + xen_ulong_t max_mfn; /* Maximum MFN that can be looked up. */ }; typedef struct xen_machphys_mapping xen_machphys_mapping_t; DEFINE_XEN_GUEST_HANDLE(xen_machphys_mapping_t); @@ -170,7 +170,7 @@ struct xen_add_to_physmap { unsigned int space; /* Index into source mapping space. */ - unsigned long idx; + xen_ulong_t idx; /* GPFN where the source mapping page should appear. */ xen_pfn_t gpfn; @@ -188,7 +188,7 @@ struct xen_translate_gpfn_list { domid_t domid; /* Length of list. */ - unsigned long nr_gpfns; + xen_ulong_t nr_gpfns; /* List of GPFNs to translate. */ XEN_GUEST_HANDLE(xen_pfn_t) gpfn_list; diff -r 4b51d081378d -r 856caf975abd xen/include/xen/lib.h --- a/xen/include/xen/lib.h Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/include/xen/lib.h Mon Jul 03 08:35:12 2006 +0100 @@ -8,19 +8,23 @@ #include <xen/xmalloc.h> #include <xen/string.h> -#define BUG() do { \ - debugtrace_dump(); \ - printk("BUG at %s:%d\n", __FILE__, __LINE__); \ - FORCE_CRASH(); \ -} while ( 0 ) - +extern void __bug(char *file, int line) __attribute__((noreturn)); +#define BUG() __bug(__FILE__, __LINE__) #define BUG_ON(_p) do { if (_p) BUG(); } while ( 0 ) /* Force a compilation error if condition is true */ #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2 * !!(condition)])) #ifndef NDEBUG -#define ASSERT(_p) { if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s\n", #_p , __LINE__, __FILE__); BUG(); } } +#define ASSERT(_p) \ + do { \ + if ( !(_p) ) \ + { \ + printk("Assertion '%s' failed, line %d, file %s\n", #_p , \ + __LINE__, __FILE__); \ + BUG(); \ + } \ + } while ( 0 ) #else #define ASSERT(_p) ((void)0) #endif diff -r 4b51d081378d -r 856caf975abd xen/include/xen/timer.h --- a/xen/include/xen/timer.h Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/include/xen/timer.h Mon Jul 03 08:35:12 2006 +0100 @@ -89,6 +89,12 @@ extern void kill_timer(struct timer *tim extern void kill_timer(struct timer *timer); /* + * Process pending timers on this CPU. This should be called periodically + * when performing work that prevents softirqs from running in a timely manner. + */ +extern void process_pending_timers(void); + +/* * Bootstrap initialisation. Must be called before any other timer function. */ extern void timer_init(void); diff -r 4b51d081378d -r 856caf975abd patches/linux-2.6.16.13/fix-hz-suspend.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/linux-2.6.16.13/fix-hz-suspend.patch Mon Jul 03 08:35:12 2006 +0100 @@ -0,0 +1,26 @@ +diff -pruN ../pristine-linux-2.6.16.13/kernel/timer.c ./kernel/timer.c +--- ../pristine-linux-2.6.16.13/kernel/timer.c 2006-05-02 22:38:44.000000000 +0100 ++++ ./kernel/timer.c 2006-06-29 14:34:12.788957720 +0100 +@@ -555,6 +555,22 @@ found: + } + spin_unlock(&base->t_base.lock); + ++ /* ++ * It can happen that other CPUs service timer IRQs and increment ++ * jiffies, but we have not yet got a local timer tick to process ++ * the timer wheels. In that case, the expiry time can be before ++ * jiffies, but since the high-resolution timer here is relative to ++ * jiffies, the default expression when high-resolution timers are ++ * not active, ++ * ++ * time_before(MAX_JIFFY_OFFSET + jiffies, expires) ++ * ++ * would falsely evaluate to true. If that is the case, just ++ * return jiffies so that we can immediately fire the local timer ++ */ ++ if (time_before(expires, jiffies)) ++ return jiffies; ++ + if (time_before(hr_expires, expires)) + return hr_expires; + diff -r 4b51d081378d -r 856caf975abd patches/linux-2.6.16.13/tpm_plugin_2.6.17.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/linux-2.6.16.13/tpm_plugin_2.6.17.patch Mon Jul 03 08:35:12 2006 +0100 @@ -0,0 +1,1546 @@ +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.c ./drivers/char/tpm/tpm_atmel.c +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.c 2006-06-26 18:05:03.000000000 -0400 ++++ ./drivers/char/tpm/tpm_atmel.c 2006-06-26 18:16:33.000000000 -0400 +@@ -47,12 +47,12 @@ static int tpm_atml_recv(struct tpm_chip + return -EIO; + + for (i = 0; i < 6; i++) { +- status = ioread8(chip->vendor->iobase + 1); ++ status = ioread8(chip->vendor.iobase + 1); + if ((status & ATML_STATUS_DATA_AVAIL) == 0) { + dev_err(chip->dev, "error reading header\n"); + return -EIO; + } +- *buf++ = ioread8(chip->vendor->iobase); ++ *buf++ = ioread8(chip->vendor.iobase); + } + + /* size of the data received */ +@@ -63,7 +63,7 @@ static int tpm_atml_recv(struct tpm_chip + dev_err(chip->dev, + "Recv size(%d) less than available space\n", size); + for (; i < size; i++) { /* clear the waiting data anyway */ +- status = ioread8(chip->vendor->iobase + 1); ++ status = ioread8(chip->vendor.iobase + 1); + if ((status & ATML_STATUS_DATA_AVAIL) == 0) { + dev_err(chip->dev, "error reading data\n"); + return -EIO; +@@ -74,16 +74,16 @@ static int tpm_atml_recv(struct tpm_chip + + /* read all the data available */ + for (; i < size; i++) { +- status = ioread8(chip->vendor->iobase + 1); ++ status = ioread8(chip->vendor.iobase + 1); + if ((status & ATML_STATUS_DATA_AVAIL) == 0) { + dev_err(chip->dev, "error reading data\n"); + return -EIO; + } +- *buf++ = ioread8(chip->vendor->iobase); ++ *buf++ = ioread8(chip->vendor.iobase); + } + + /* make sure data available is gone */ +- status = ioread8(chip->vendor->iobase + 1); ++ status = ioread8(chip->vendor.iobase + 1); + + if (status & ATML_STATUS_DATA_AVAIL) { + dev_err(chip->dev, "data available is stuck\n"); +@@ -100,7 +100,7 @@ static int tpm_atml_send(struct tpm_chip + dev_dbg(chip->dev, "tpm_atml_send:\n"); + for (i = 0; i < count; i++) { + dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); +- iowrite8(buf[i], chip->vendor->iobase); ++ iowrite8(buf[i], chip->vendor.iobase); + } + + return count; +@@ -108,12 +108,12 @@ static int tpm_atml_send(struct tpm_chip + + static void tpm_atml_cancel(struct tpm_chip *chip) + { +- iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1); ++ iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1); + } + + static u8 tpm_atml_status(struct tpm_chip *chip) + { +- return ioread8(chip->vendor->iobase + 1); ++ return ioread8(chip->vendor.iobase + 1); + } + + static struct file_operations atmel_ops = { +@@ -140,7 +140,7 @@ static struct attribute* atmel_attrs[] = + + static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs }; + +-static struct tpm_vendor_specific tpm_atmel = { ++static const struct tpm_vendor_specific tpm_atmel = { + .recv = tpm_atml_recv, + .send = tpm_atml_send, + .cancel = tpm_atml_cancel, +@@ -159,10 +159,10 @@ static void atml_plat_remove(void) + struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); + + if (chip) { +- if (chip->vendor->have_region) +- atmel_release_region(chip->vendor->base, +- chip->vendor->region_size); +- atmel_put_base_addr(chip->vendor); ++ if (chip->vendor.have_region) ++ atmel_release_region(chip->vendor.base, ++ chip->vendor.region_size); ++ atmel_put_base_addr(chip->vendor.iobase); + tpm_remove_hardware(chip->dev); + platform_device_unregister(pdev); + } +@@ -179,18 +179,22 @@ static struct device_driver atml_drv = { + static int __init init_atmel(void) + { + int rc = 0; ++ void __iomem *iobase = NULL; ++ int have_region, region_size; ++ unsigned long base; ++ struct tpm_chip *chip; + + driver_register(&atml_drv); + +- if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) { ++ if ((iobase = atmel_get_base_addr(&base, ®ion_size)) == NULL) { + rc = -ENODEV; + goto err_unreg_drv; + } + +- tpm_atmel.have_region = ++ have_region = + (atmel_request_region +- (tpm_atmel.base, tpm_atmel.region_size, +- "tpm_atmel0") == NULL) ? 0 : 1; ++ (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1; ++ + + if (IS_ERR + (pdev = +@@ -199,17 +203,25 @@ static int __init init_atmel(void) + goto err_rel_reg; + } + +- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) ++ if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) { ++ rc = -ENODEV; + goto err_unreg_dev; ++ } ++ ++ chip->vendor.iobase = iobase; ++ chip->vendor.base = base; ++ chip->vendor.have_region = have_region; ++ chip->vendor.region_size = region_size; ++ + return 0; + + err_unreg_dev: + platform_device_unregister(pdev); + err_rel_reg: +- atmel_put_base_addr(&tpm_atmel); +- if (tpm_atmel.have_region) +- atmel_release_region(tpm_atmel.base, +- tpm_atmel.region_size); ++ atmel_put_base_addr(iobase); ++ if (have_region) ++ atmel_release_region(base, ++ region_size); + err_unreg_drv: + driver_unregister(&atml_drv); + return rc; +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.h ./drivers/char/tpm/tpm_atmel.h +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.h 2006-06-26 18:05:03.000000000 -0400 ++++ ./drivers/char/tpm/tpm_atmel.h 2006-06-26 18:16:33.000000000 -0400 +@@ -28,13 +28,12 @@ + #define atmel_request_region request_mem_region + #define atmel_release_region release_mem_region + +-static inline void atmel_put_base_addr(struct tpm_vendor_specific +- *vendor) ++static inline void atmel_put_base_addr(void __iomem *iobase) + { +- iounmap(vendor->iobase); ++ iounmap(iobase); + } + +-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor) ++static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) + { + struct device_node *dn; + unsigned long address, size; +@@ -71,9 +70,9 @@ static void __iomem * atmel_get_base_add + else + size = reg[naddrc]; + +- vendor->base = address; +- vendor->region_size = size; +- return ioremap(vendor->base, vendor->region_size); ++ *base = address; ++ *region_size = size; ++ return ioremap(*base, *region_size); + } + #else + #define atmel_getb(chip, offset) inb(chip->vendor->base + offset) +@@ -106,14 +105,12 @@ static int atmel_verify_tpm11(void) + return 0; + } + +-static inline void atmel_put_base_addr(struct tpm_vendor_specific +- *vendor) ++static inline void atmel_put_base_addr(void __iomem *iobase) + { + } + + /* Determine where to talk to device */ +-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific +- *vendor) ++static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) + { + int lo, hi; + +@@ -123,9 +120,9 @@ static void __iomem * atmel_get_base_add + lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); + hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); + +- vendor->base = (hi << 8) | lo; +- vendor->region_size = 2; ++ *base = (hi << 8) | lo; ++ *region_size = 2; + +- return ioport_map(vendor->base, vendor->region_size); ++ return ioport_map(*base, *region_size); + } + #endif +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_bios.c ./drivers/char/tpm/tpm_bios.c +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_bios.c 2006-06-26 18:05:03.000000000 -0400 ++++ ./drivers/char/tpm/tpm_bios.c 2006-06-26 18:16:33.000000000 -0400 +@@ -29,6 +29,11 @@ + #define MAX_TEXT_EVENT 1000 /* Max event string length */ + #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ + ++enum bios_platform_class { ++ BIOS_CLIENT = 0x00, ++ BIOS_SERVER = 0x01, ++}; ++ + struct tpm_bios_log { + void *bios_event_log; + void *bios_event_log_end; +@@ -36,9 +41,18 @@ struct tpm_bios_log { + + struct acpi_tcpa { + struct acpi_table_header hdr; +- u16 reserved; +- u32 log_max_len __attribute__ ((packed)); +- u32 log_start_addr __attribute__ ((packed)); ++ u16 platform_class; ++ union { ++ struct client_hdr { ++ u32 log_max_len __attribute__ ((packed)); ++ u64 log_start_addr __attribute__ ((packed)); ++ } client; ++ struct server_hdr { ++ u16 reserved; ++ u64 log_max_len __attribute__ ((packed)); ++ u64 log_start_addr __attribute__ ((packed)); ++ } server; ++ }; + }; + + struct tcpa_event { +@@ -91,6 +105,12 @@ static const char* tcpa_event_type_strin + "Non-Host Info" + }; + ++struct tcpa_pc_event { ++ u32 event_id; ++ u32 event_size; ++ u8 event_data[0]; ++}; ++ + enum tcpa_pc_event_ids { + SMBIOS = 1, + BIS_CERT, +@@ -100,14 +120,15 @@ enum tcpa_pc_event_ids { + NVRAM, + OPTION_ROM_EXEC, + OPTION_ROM_CONFIG, +- OPTION_ROM_MICROCODE, ++ OPTION_ROM_MICROCODE = 10, + S_CRTM_VERSION, + S_CRTM_CONTENTS, + POST_CONTENTS, ++ HOST_TABLE_OF_DEVICES, + }; + + static const char* tcpa_pc_event_id_strings[] = { +- "" ++ "", + "SMBIOS", + "BIS Certificate", + "POST BIOS ", +@@ -116,10 +137,12 @@ static const char* tcpa_pc_event_id_stri + "NVRAM", + "Option ROM", + "Option ROM config", +- "Option ROM microcode", ++ "", ++ "Option ROM microcode ", + "S-CRTM Version", +- "S-CRTM Contents", +- "S-CRTM POST Contents", ++ "S-CRTM Contents ", ++ "POST Contents ", ++ "Table of Devices", + }; + + /* returns pointer to start of pos. entry of tcg log */ +@@ -191,7 +214,7 @@ static int get_event_name(char *dest, st + const char *name = ""; + char data[40] = ""; + int i, n_len = 0, d_len = 0; +- u32 event_id; ++ struct tcpa_pc_event *pc_event; + + switch(event->event_type) { + case PREBOOT: +@@ -220,31 +243,32 @@ static int get_event_name(char *dest, st + } + break; + case EVENT_TAG: +- event_id = be32_to_cpu(*((u32 *)event_entry)); ++ pc_event = (struct tcpa_pc_event *)event_entry; + + /* ToDo Row data -> Base64 */ + +- switch (event_id) { ++ switch (pc_event->event_id) { + case SMBIOS: + case BIS_CERT: + case CMOS: + case NVRAM: + case OPTION_ROM_EXEC: + case OPTION_ROM_CONFIG: +- case OPTION_ROM_MICROCODE: + case S_CRTM_VERSION: +- case S_CRTM_CONTENTS: +- case POST_CONTENTS: +- name = tcpa_pc_event_id_strings[event_id]; ++ name = tcpa_pc_event_id_strings[pc_event->event_id]; + n_len = strlen(name); + break; ++ /* hash data */ + case POST_BIOS_ROM: + case ESCD: +- name = tcpa_pc_event_id_strings[event_id]; ++ case OPTION_ROM_MICROCODE: ++ case S_CRTM_CONTENTS: ++ case POST_CONTENTS: ++ name = tcpa_pc_event_id_strings[pc_event->event_id]; + n_len = strlen(name); + for (i = 0; i < 20; i++) +- d_len += sprintf(data, "%02x", +- event_entry[8 + i]); ++ d_len += sprintf(&data[2*i], "%02x", ++ pc_event->event_data[i]); + break; + default: + break; +@@ -260,52 +284,13 @@ static int get_event_name(char *dest, st + + static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) + { ++ struct tcpa_event *event = v; ++ char *data = v; ++ int i; + +- char *eventname; +- char data[4]; +- u32 help; +- int i, len; +- struct tcpa_event *event = (struct tcpa_event *) v; +- unsigned char *event_entry = +- (unsigned char *) (v + sizeof(struct tcpa_event)); +- +- eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); +- if (!eventname) { +- printk(KERN_ERR "%s: ERROR - No Memory for event name\n ", +- __func__); +- return -ENOMEM; +- } +- +- /* 1st: PCR used is in little-endian format (4 bytes) */ +- help = le32_to_cpu(event->pcr_index); +- memcpy(data, &help, 4); +- for (i = 0; i < 4; i++) +- seq_putc(m, data[i]); +- +- /* 2nd: SHA1 (20 bytes) */ +- for (i = 0; i < 20; i++) +- seq_putc(m, event->pcr_value[i]); +- +- /* 3rd: event type identifier (4 bytes) */ +- help = le32_to_cpu(event->event_type); +- memcpy(data, &help, 4); +- for (i = 0; i < 4; i++) ++ for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++) + seq_putc(m, data[i]); + +- len = 0; +- +- len += get_event_name(eventname, event, event_entry); +- +- /* 4th: filename <= 255 + \'0' delimiter */ +- if (len > TCG_EVENT_NAME_LEN_MAX) +- len = TCG_EVENT_NAME_LEN_MAX; +- +- for (i = 0; i < len; i++) +- seq_putc(m, eventname[i]); +- +- /* 5th: delimiter */ +- seq_putc(m, '\0'); +- + return 0; + } + +@@ -353,6 +338,7 @@ static int tpm_ascii_bios_measurements_s + /* 4th: eventname <= max + \'0' delimiter */ + seq_printf(m, " %s\n", eventname); + ++ kfree(eventname); + return 0; + } + +@@ -376,6 +362,7 @@ static int read_log(struct tpm_bios_log + struct acpi_tcpa *buff; + acpi_status status; + struct acpi_table_header *virt; ++ u64 len, start; + + if (log->bios_event_log != NULL) { + printk(KERN_ERR +@@ -396,27 +383,37 @@ static int read_log(struct tpm_bios_log + return -EIO; + } + +- if (buff->log_max_len == 0) { ++ switch(buff->platform_class) { ++ case BIOS_SERVER: ++ len = buff->server.log_max_len; ++ start = buff->server.log_start_addr; ++ break; ++ case BIOS_CLIENT: ++ default: ++ len = buff->client.log_max_len; ++ start = buff->client.log_start_addr; ++ break; ++ } ++ if (!len) { + printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); + return -EIO; + } + + /* malloc EventLog space */ +- log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL); ++ log->bios_event_log = kmalloc(len, GFP_KERNEL); + if (!log->bios_event_log) { +- printk +- ("%s: ERROR - Not enough Memory for BIOS measurements\n", +- __func__); ++ printk("%s: ERROR - Not enough Memory for BIOS measurements\n", ++ __func__); + return -ENOMEM; + } + +- log->bios_event_log_end = log->bios_event_log + buff->log_max_len; ++ log->bios_event_log_end = log->bios_event_log + len; + +- acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt); ++ acpi_os_map_memory(start, len, (void *) &virt); + +- memcpy(log->bios_event_log, virt, buff->log_max_len); ++ memcpy(log->bios_event_log, virt, len); + +- acpi_os_unmap_memory(virt, buff->log_max_len); ++ acpi_os_unmap_memory(virt, len); + return 0; + } + +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_infineon.c ./drivers/char/tpm/tpm_infineon.c +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_infineon.c 2006-06-26 18:05:03.000000000 -0400 ++++ ./drivers/char/tpm/tpm_infineon.c 2006-06-26 18:16:33.000000000 -0400 +@@ -15,6 +15,7 @@ + * License. + */ + ++#include <linux/init.h> + #include <linux/pnp.h> + #include "tpm.h" + +@@ -104,7 +105,7 @@ static int empty_fifo(struct tpm_chip *c + + if (clear_wrfifo) { + for (i = 0; i < 4096; i++) { +- status = inb(chip->vendor->base + WRFIFO); ++ status = inb(chip->vendor.base + WRFIFO); + if (status == 0xff) { + if (check == 5) + break; +@@ -124,8 +125,8 @@ static int empty_fifo(struct tpm_chip *c + */ + i = 0; + do { +- status = inb(chip->vendor->base + RDFIFO); +- status = inb(chip->vendor->base + STAT); ++ status = inb(chip->vendor.base + RDFIFO); ++ status = inb(chip->vendor.base + STAT); + i++; + if (i == TPM_MAX_TRIES) + return -EIO; +@@ -138,7 +139,7 @@ static int wait(struct tpm_chip *chip, i + int status; + int i; + for (i = 0; i < TPM_MAX_TRIES; i++) { +- status = inb(chip->vendor->base + STAT); ++ status = inb(chip->vendor.base + STAT); + /* check the status-register if wait_for_bit is set */ + if (status & 1 << wait_for_bit) + break; +@@ -157,7 +158,7 @@ static int wait(struct tpm_chip *chip, i + static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) + { + wait(chip, STAT_XFE); +- outb(sendbyte, chip->vendor->base + WRFIFO); ++ outb(sendbyte, chip->vendor.base + WRFIFO); + } + + /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more +@@ -204,7 +205,7 @@ recv_begin: + ret = wait(chip, STAT_RDA); + if (ret) + return -EIO; +- buf[i] = inb(chip->vendor->base + RDFIFO); ++ buf[i] = inb(chip->vendor.base + RDFIFO); + } + + if (buf[0] != TPM_VL_VER) { +@@ -219,7 +220,7 @@ recv_begin: + + for (i = 0; i < size; i++) { + wait(chip, STAT_RDA); +- buf[i] = inb(chip->vendor->base + RDFIFO); ++ buf[i] = inb(chip->vendor.base + RDFIFO); + } + + if ((size == 0x6D00) && (buf[1] == 0x80)) { +@@ -268,7 +269,7 @@ static int tpm_inf_send(struct tpm_chip + u8 count_high, count_low, count_4, count_3, count_2, count_1; + + /* Disabling Reset, LP and IRQC */ +- outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD); ++ outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD); + + ret = empty_fifo(chip, 1); + if (ret) { +@@ -319,7 +320,7 @@ static void tpm_inf_cancel(struct tpm_ch + + static u8 tpm_inf_status(struct tpm_chip *chip) + { +- return inb(chip->vendor->base + STAT); ++ return inb(chip->vendor.base + STAT); + } + + static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); +@@ -346,7 +347,7 @@ static struct file_operations inf_ops = + .release = tpm_release, + }; + +-static struct tpm_vendor_specific tpm_inf = { ++static const struct tpm_vendor_specific tpm_inf = { + .recv = tpm_inf_recv, + .send = tpm_inf_send, + .cancel = tpm_inf_cancel, +@@ -375,6 +376,7 @@ static int __devinit tpm_inf_pnp_probe(s + int version[2]; + int productid[2]; + char chipname[20]; ++ struct tpm_chip *chip; + + /* read IO-ports through PnP */ + if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && +@@ -395,14 +397,13 @@ static int __devinit tpm_inf_pnp_probe(s + goto err_last; + } + /* publish my base address and request region */ +- tpm_inf.base = TPM_INF_BASE; + if (request_region +- (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { ++ (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { + rc = -EINVAL; + goto err_last; + } +- if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN, +- "tpm_infineon0") == NULL) { ++ if (request_region ++ (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) { + rc = -EINVAL; + goto err_last; + } +@@ -442,9 +443,9 @@ static int __devinit tpm_inf_pnp_probe(s + + /* configure TPM with IO-ports */ + outb(IOLIMH, TPM_INF_ADDR); +- outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA); ++ outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA); + outb(IOLIML, TPM_INF_ADDR); +- outb((tpm_inf.base & 0xff), TPM_INF_DATA); ++ outb((TPM_INF_BASE & 0xff), TPM_INF_DATA); + + /* control if IO-ports are set correctly */ + outb(IOLIMH, TPM_INF_ADDR); +@@ -452,10 +453,10 @@ static int __devinit tpm_inf_pnp_probe(s + outb(IOLIML, TPM_INF_ADDR); + iol = inb(TPM_INF_DATA); + +- if ((ioh << 8 | iol) != tpm_inf.base) { ++ if ((ioh << 8 | iol) != TPM_INF_BASE) { + dev_err(&dev->dev, +- "Could not set IO-ports to 0x%lx\n", +- tpm_inf.base); ++ "Could not set IO-ports to 0x%x\n", ++ TPM_INF_BASE); + rc = -EIO; + goto err_release_region; + } +@@ -466,15 +467,15 @@ static int __devinit tpm_inf_pnp_probe(s + outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); + + /* disable RESET, LP and IRQC */ +- outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD); ++ outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD); + + /* Finally, we're done, print some infos */ + dev_info(&dev->dev, "TPM found: " + "config base 0x%x, " + "io base 0x%x, " +- "chip version %02x%02x, " +- "vendor id %x%x (Infineon), " +- "product id %02x%02x" ++ "chip version 0x%02x%02x, " ++ "vendor id 0x%x%x (Infineon), " ++ "product id 0x%02x%02x" + "%s\n", + TPM_INF_ADDR, + TPM_INF_BASE, +@@ -482,11 +483,10 @@ static int __devinit tpm_inf_pnp_probe(s + vendorid[0], vendorid[1], + productid[0], productid[1], chipname); + +- rc = tpm_register_hardware(&dev->dev, &tpm_inf); +- if (rc < 0) { +- rc = -ENODEV; ++ if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) { + goto err_release_region; + } ++ chip->vendor.base = TPM_INF_BASE; + return 0; + } else { + rc = -ENODEV; +@@ -494,7 +494,7 @@ static int __devinit tpm_inf_pnp_probe(s + } + + err_release_region: +- release_region(tpm_inf.base, TPM_INF_PORT_LEN); ++ release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); + release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); + + err_last: +@@ -506,7 +506,8 @@ static __devexit void tpm_inf_pnp_remove + struct tpm_chip *chip = pnp_get_drvdata(dev); + + if (chip) { +- release_region(chip->vendor->base, TPM_INF_PORT_LEN); ++ release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); ++ release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); + tpm_remove_hardware(chip->dev); + } + } +@@ -520,7 +521,7 @@ static struct pnp_driver tpm_inf_pnp = { + }, + .id_table = tpm_pnp_tbl, + .probe = tpm_inf_pnp_probe, +- .remove = tpm_inf_pnp_remove, ++ .remove = __devexit_p(tpm_inf_pnp_remove), + }; + + static int __init init_inf(void) +@@ -538,5 +539,5 @@ module_exit(cleanup_inf); + + MODULE_AUTHOR("Marcel Selhorst <selhorst@xxxxxxxxxxxxx>"); + MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); +-MODULE_VERSION("1.7"); ++MODULE_VERSION("1.8"); + MODULE_LICENSE("GPL"); +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_nsc.c ./drivers/char/tpm/tpm_nsc.c +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_nsc.c 2006-06-26 18:05:03.000000000 -0400 ++++ ./drivers/char/tpm/tpm_nsc.c 2006-06-26 18:16:33.000000000 -0400 +@@ -71,7 +71,7 @@ static int wait_for_stat(struct tpm_chip + unsigned long stop; + + /* status immediately available check */ +- *data = inb(chip->vendor->base + NSC_STATUS); ++ *data = inb(chip->vendor.base + NSC_STATUS); + if ((*data & mask) == val) + return 0; + +@@ -79,7 +79,7 @@ static int wait_for_stat(struct tpm_chip + stop = jiffies + 10 * HZ; + do { + msleep(TPM_TIMEOUT); +- *data = inb(chip->vendor->base + 1); ++ *data = inb(chip->vendor.base + 1); + if ((*data & mask) == val) + return 0; + } +@@ -94,9 +94,9 @@ static int nsc_wait_for_ready(struct tpm + unsigned long stop; + + /* status immediately available check */ +- status = inb(chip->vendor->base + NSC_STATUS); ++ status = inb(chip->vendor.base + NSC_STATUS); + if (status & NSC_STATUS_OBF) +- status = inb(chip->vendor->base + NSC_DATA); ++ status = inb(chip->vendor.base + NSC_DATA); + if (status & NSC_STATUS_RDY) + return 0; + +@@ -104,9 +104,9 @@ static int nsc_wait_for_ready(struct tpm + stop = jiffies + 100; + do { + msleep(TPM_TIMEOUT); +- status = inb(chip->vendor->base + NSC_STATUS); ++ status = inb(chip->vendor.base + NSC_STATUS); + if (status & NSC_STATUS_OBF) +- status = inb(chip->vendor->base + NSC_DATA); ++ status = inb(chip->vendor.base + NSC_DATA); + if (status & NSC_STATUS_RDY) + return 0; + } +@@ -132,7 +132,7 @@ static int tpm_nsc_recv(struct tpm_chip + return -EIO; + } + if ((data = +- inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) { ++ inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) { + dev_err(chip->dev, "not in normal mode (0x%x)\n", + data); + return -EIO; +@@ -148,7 +148,7 @@ static int tpm_nsc_recv(struct tpm_chip + } + if (data & NSC_STATUS_F0) + break; +- *p = inb(chip->vendor->base + NSC_DATA); ++ *p = inb(chip->vendor.base + NSC_DATA); + } + + if ((data & NSC_STATUS_F0) == 0 && +@@ -156,7 +156,7 @@ static int tpm_nsc_recv(struct tpm_chip + dev_err(chip->dev, "F0 not set\n"); + return -EIO; + } +- if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) { ++ if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) { + dev_err(chip->dev, + "expected end of command(0x%x)\n", data); + return -EIO; +@@ -182,7 +182,7 @@ static int tpm_nsc_send(struct tpm_chip + * fix it. Not sure why this is needed, we followed the flow + * chart in the manual to the letter. + */ +- outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND); ++ outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND); + + if (nsc_wait_for_ready(chip) != 0) + return -EIO; +@@ -192,7 +192,7 @@ static int tpm_nsc_send(struct tpm_chip + return -EIO; + } + +- outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND); ++ outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND); + if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) { + dev_err(chip->dev, "IBR timeout\n"); + return -EIO; +@@ -204,26 +204,26 @@ static int tpm_nsc_send(struct tpm_chip + "IBF timeout (while writing data)\n"); + return -EIO; + } +- outb(buf[i], chip->vendor->base + NSC_DATA); ++ outb(buf[i], chip->vendor.base + NSC_DATA); + } + + if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { + dev_err(chip->dev, "IBF timeout\n"); + return -EIO; + } +- outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND); ++ outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND); + + return count; + } + + static void tpm_nsc_cancel(struct tpm_chip *chip) + { +- outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND); ++ outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND); + } + + static u8 tpm_nsc_status(struct tpm_chip *chip) + { +- return inb(chip->vendor->base + NSC_STATUS); ++ return inb(chip->vendor.base + NSC_STATUS); + } + + static struct file_operations nsc_ops = { +@@ -250,7 +250,7 @@ static struct attribute * nsc_attrs[] = + + static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs }; + +-static struct tpm_vendor_specific tpm_nsc = { ++static const struct tpm_vendor_specific tpm_nsc = { + .recv = tpm_nsc_recv, + .send = tpm_nsc_send, + .cancel = tpm_nsc_cancel, +@@ -268,7 +268,7 @@ static void __devexit tpm_nsc_remove(str + { + struct tpm_chip *chip = dev_get_drvdata(dev); + if ( chip ) { +- release_region(chip->vendor->base, 2); ++ release_region(chip->vendor.base, 2); + tpm_remove_hardware(chip->dev); + } + } +@@ -286,7 +286,8 @@ static int __init init_nsc(void) + int rc = 0; + int lo, hi; + int nscAddrBase = TPM_ADDR; +- ++ struct tpm_chip *chip; ++ unsigned long base; + + /* verify that it is a National part (SID) */ + if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) { +@@ -300,7 +301,7 @@ static int __init init_nsc(void) + + hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI); + lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO); +- tpm_nsc.base = (hi<<8) | lo; ++ base = (hi<<8) | lo; + + /* enable the DPM module */ + tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01); +@@ -320,13 +321,15 @@ static int __init init_nsc(void) + if ((rc = platform_device_register(pdev)) < 0) + goto err_free_dev; + +- if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) { ++ if (request_region(base, 2, "tpm_nsc0") == NULL ) { + rc = -EBUSY; + goto err_unreg_dev; + } + +- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0) ++ if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) { ++ rc = -ENODEV; + goto err_rel_reg; ++ } + + dev_dbg(&pdev->dev, "NSC TPM detected\n"); + dev_dbg(&pdev->dev, +@@ -361,10 +364,12 @@ static int __init init_nsc(void) + "NSC TPM revision %d\n", + tpm_read_index(nscAddrBase, 0x27) & 0x1F); + ++ chip->vendor.base = base; ++ + return 0; + + err_rel_reg: +- release_region(tpm_nsc.base, 2); ++ release_region(base, 2); + err_unreg_dev: + platform_device_unregister(pdev); + err_free_dev: +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_tis.c ./drivers/char/tpm/tpm_tis.c +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_tis.c 1969-12-31 19:00:00.000000000 -0500 ++++ ./drivers/char/tpm/tpm_tis.c 2006-06-26 18:16:33.000000000 -0400 +@@ -0,0 +1,665 @@ ++/* ++ * Copyright (C) 2005, 2006 IBM Corporation ++ * ++ * Authors: ++ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx> ++ * Kylene Hall <kjhall@xxxxxxxxxx> ++ * ++ * Device driver for TCG/TCPA TPM (trusted platform module). ++ * Specifications at www.trustedcomputinggroup.org ++ * ++ * This device driver implements the TPM interface as defined in ++ * the TCG TPM Interface Spec version 1.2, revision 1.0. ++ * ++ * 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 the Free Software Foundation, version 2 of the ++ * License. ++ */ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/pnp.h> ++#include <linux/interrupt.h> ++#include <linux/wait.h> ++#include "tpm.h" ++ ++#define TPM_HEADER_SIZE 10 ++ ++enum tis_access { ++ TPM_ACCESS_VALID = 0x80, ++ TPM_ACCESS_ACTIVE_LOCALITY = 0x20, ++ TPM_ACCESS_REQUEST_PENDING = 0x04, ++ TPM_ACCESS_REQUEST_USE = 0x02, ++}; ++ ++enum tis_status { ++ TPM_STS_VALID = 0x80, ++ TPM_STS_COMMAND_READY = 0x40, ++ TPM_STS_GO = 0x20, ++ TPM_STS_DATA_AVAIL = 0x10, ++ TPM_STS_DATA_EXPECT = 0x08, ++}; ++ ++enum tis_int_flags { ++ TPM_GLOBAL_INT_ENABLE = 0x80000000, ++ TPM_INTF_BURST_COUNT_STATIC = 0x100, ++ TPM_INTF_CMD_READY_INT = 0x080, ++ TPM_INTF_INT_EDGE_FALLING = 0x040, ++ TPM_INTF_INT_EDGE_RISING = 0x020, ++ TPM_INTF_INT_LEVEL_LOW = 0x010, ++ TPM_INTF_INT_LEVEL_HIGH = 0x008, ++ TPM_INTF_LOCALITY_CHANGE_INT = 0x004, ++ TPM_INTF_STS_VALID_INT = 0x002, ++ TPM_INTF_DATA_AVAIL_INT = 0x001, ++}; ++ ++enum tis_defaults { ++ TIS_MEM_BASE = 0xFED40000, ++ TIS_MEM_LEN = 0x5000, ++ TIS_SHORT_TIMEOUT = 750, /* ms */ ++ TIS_LONG_TIMEOUT = 2000, /* 2 sec */ ++}; ++ ++#define TPM_ACCESS(l) (0x0000 | ((l) << 12)) ++#define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) ++#define TPM_INT_VECTOR(l) (0x000C | ((l) << 12)) ++#define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) ++#define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) ++#define TPM_STS(l) (0x0018 | ((l) << 12)) ++#define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) ++ ++#define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) ++#define TPM_RID(l) (0x0F04 | ((l) << 12)) ++ ++static LIST_HEAD(tis_chips); ++static DEFINE_SPINLOCK(tis_lock); ++ ++static int check_locality(struct tpm_chip *chip, int l) ++{ ++ if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & ++ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == ++ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ++ return chip->vendor.locality = l; ++ ++ return -1; ++} ++ ++static void release_locality(struct tpm_chip *chip, int l, int force) ++{ ++ if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & ++ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == ++ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ++ iowrite8(TPM_ACCESS_ACTIVE_LOCALITY, ++ chip->vendor.iobase + TPM_ACCESS(l)); ++} ++ ++static int request_locality(struct tpm_chip *chip, int l) ++{ ++ unsigned long stop; ++ long rc; ++ ++ if (check_locality(chip, l) >= 0) ++ return l; ++ ++ iowrite8(TPM_ACCESS_REQUEST_USE, ++ chip->vendor.iobase + TPM_ACCESS(l)); ++ ++ if (chip->vendor.irq) { ++ rc = wait_event_interruptible_timeout(chip->vendor.int_queue, ++ (check_locality ++ (chip, l) >= 0), ++ chip->vendor.timeout_a); ++ if (rc > 0) ++ return l; ++ ++ } else { ++ /* wait for burstcount */ ++ stop = jiffies + chip->vendor.timeout_a; ++ do { ++ if (check_locality(chip, l) >= 0) ++ return l; ++ msleep(TPM_TIMEOUT); ++ } ++ while (time_before(jiffies, stop)); ++ } ++ return -1; ++} ++ ++static u8 tpm_tis_status(struct tpm_chip *chip) ++{ ++ return ioread8(chip->vendor.iobase + ++ TPM_STS(chip->vendor.locality)); ++} ++ ++static void tpm_tis_ready(struct tpm_chip *chip) ++{ ++ /* this causes the current command to be aborted */ ++ iowrite8(TPM_STS_COMMAND_READY, ++ chip->vendor.iobase + TPM_STS(chip->vendor.locality)); ++} ++ ++static int get_burstcount(struct tpm_chip *chip) ++{ ++ unsigned long stop; ++ int burstcnt; ++ ++ /* wait for burstcount */ ++ /* which timeout value, spec has 2 answers (c & d) */ ++ stop = jiffies + chip->vendor.timeout_d; ++ do { ++ burstcnt = ioread8(chip->vendor.iobase + ++ TPM_STS(chip->vendor.locality) + 1); ++ burstcnt += ioread8(chip->vendor.iobase + ++ TPM_STS(chip->vendor.locality) + ++ 2) << 8; ++ if (burstcnt) ++ return burstcnt; ++ msleep(TPM_TIMEOUT); ++ } while (time_before(jiffies, stop)); ++ return -EBUSY; ++} ++ ++static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, ++ wait_queue_head_t *queue) ++{ ++ unsigned long stop; ++ long rc; ++ u8 status; ++ ++ /* check current status */ ++ status = tpm_tis_status(chip); ++ if ((status & mask) == mask) ++ return 0; ++ ++ if (chip->vendor.irq) { ++ rc = wait_event_interruptible_timeout(*queue, ++ ((tpm_tis_status ++ (chip) & mask) == ++ mask), timeout); ++ if (rc > 0) ++ return 0; ++ } else { ++ stop = jiffies + timeout; ++ do { ++ msleep(TPM_TIMEOUT); ++ status = tpm_tis_status(chip); ++ if ((status & mask) == mask) ++ return 0; ++ } while (time_before(jiffies, stop)); ++ } ++ return -ETIME; ++} ++ ++static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) ++{ ++ int size = 0, burstcnt; ++ while (size < count && ++ wait_for_stat(chip, ++ TPM_STS_DATA_AVAIL | TPM_STS_VALID, ++ chip->vendor.timeout_c, ++ &chip->vendor.read_queue) ++ == 0) { ++ burstcnt = get_burstcount(chip); ++ for (; burstcnt > 0 && size < count; burstcnt--) ++ buf[size++] = ioread8(chip->vendor.iobase + ++ TPM_DATA_FIFO(chip->vendor. ++ locality)); ++ } ++ return size; ++} ++ ++static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) ++{ ++ int size = 0; ++ int expected, status; ++ ++ if (count < TPM_HEADER_SIZE) { ++ size = -EIO; ++ goto out; ++ } ++ ++ /* read first 10 bytes, including tag, paramsize, and result */ ++ if ((size = ++ recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) { ++ dev_err(chip->dev, "Unable to read header\n"); ++ goto out; ++ } ++ ++ expected = be32_to_cpu(*(__be32 *) (buf + 2)); ++ if (expected > count) { ++ size = -EIO; ++ goto out; ++ } ++ ++ if ((size += ++ recv_data(chip, &buf[TPM_HEADER_SIZE], ++ expected - TPM_HEADER_SIZE)) < expected) { ++ dev_err(chip->dev, "Unable to read remainder of result\n"); ++ size = -ETIME; ++ goto out; ++ } ++ ++ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, ++ &chip->vendor.int_queue); ++ status = tpm_tis_status(chip); ++ if (status & TPM_STS_DATA_AVAIL) { /* retry? */ ++ dev_err(chip->dev, "Error left over data\n"); ++ size = -EIO; ++ goto out; ++ } ++ ++out: ++ tpm_tis_ready(chip); ++ release_locality(chip, chip->vendor.locality, 0); ++ return size; ++} ++ ++/* ++ * If interrupts are used (signaled by an irq set in the vendor structure) ++ * tpm.c can skip polling for the data to be available as the interrupt is ++ * waited for here ++ */ ++static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) ++{ ++ int rc, status, burstcnt; ++ size_t count = 0; ++ u32 ordinal; ++ ++ if (request_locality(chip, 0) < 0) ++ return -EBUSY; ++ ++ status = tpm_tis_status(chip); ++ if ((status & TPM_STS_COMMAND_READY) == 0) { ++ tpm_tis_ready(chip); ++ if (wait_for_stat ++ (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, ++ &chip->vendor.int_queue) < 0) { ++ rc = -ETIME; ++ goto out_err; ++ } ++ } ++ ++ while (count < len - 1) { ++ burstcnt = get_burstcount(chip); ++ for (; burstcnt > 0 && count < len - 1; burstcnt--) { ++ iowrite8(buf[count], chip->vendor.iobase + ++ TPM_DATA_FIFO(chip->vendor.locality)); ++ count++; ++ } ++ ++ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, ++ &chip->vendor.int_queue); ++ status = tpm_tis_status(chip); ++ if ((status & TPM_STS_DATA_EXPECT) == 0) { ++ rc = -EIO; ++ goto out_err; ++ } ++ } ++ ++ /* write last byte */ ++ iowrite8(buf[count], ++ chip->vendor.iobase + ++ TPM_DATA_FIFO(chip->vendor.locality)); ++ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, ++ &chip->vendor.int_queue); ++ status = tpm_tis_status(chip); ++ if ((status & TPM_STS_DATA_EXPECT) != 0) { ++ rc = -EIO; ++ goto out_err; ++ } ++ ++ /* go and do it */ ++ iowrite8(TPM_STS_GO, ++ chip->vendor.iobase + TPM_STS(chip->vendor.locality)); ++ ++ if (chip->vendor.irq) { ++ ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); ++ if (wait_for_stat ++ (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, ++ tpm_calc_ordinal_duration(chip, ordinal), ++ &chip->vendor.read_queue) < 0) { ++ rc = -ETIME; ++ goto out_err; ++ } ++ } ++ return len; ++out_err: ++ tpm_tis_ready(chip); ++ release_locality(chip, chip->vendor.locality, 0); ++ return rc; ++} ++ ++static struct file_operations tis_ops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .open = tpm_open, ++ .read = tpm_read, ++ .write = tpm_write, ++ .release = tpm_release, ++}; ++ ++static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); ++static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); ++static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL); ++static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); ++static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); ++static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, ++ NULL); ++static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); ++static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); ++ ++static struct attribute *tis_attrs[] = { ++ &dev_attr_pubek.attr, ++ &dev_attr_pcrs.attr, ++ &dev_attr_enabled.attr, ++ &dev_attr_active.attr, ++ &dev_attr_owned.attr, ++ &dev_attr_temp_deactivated.attr, ++ &dev_attr_caps.attr, ++ &dev_attr_cancel.attr, NULL, ++}; ++ ++static struct attribute_group tis_attr_grp = { ++ .attrs = tis_attrs ++}; ++ ++static struct tpm_vendor_specific tpm_tis = { ++ .status = tpm_tis_status, ++ .recv = tpm_tis_recv, ++ .send = tpm_tis_send, ++ .cancel = tpm_tis_ready, ++ .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, ++ .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, ++ .req_canceled = TPM_STS_COMMAND_READY, ++ .attr_group = &tis_attr_grp, ++ .miscdev = { ++ .fops = &tis_ops,}, ++}; ++ ++static irqreturn_t tis_int_probe(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ struct tpm_chip *chip = (struct tpm_chip *) dev_id; ++ u32 interrupt; ++ ++ interrupt = ioread32(chip->vendor.iobase + ++ TPM_INT_STATUS(chip->vendor.locality)); ++ ++ if (interrupt == 0) ++ return IRQ_NONE; ++ ++ chip->vendor.irq = irq; ++ ++ /* Clear interrupts handled with TPM_EOI */ ++ iowrite32(interrupt, ++ chip->vendor.iobase + ++ TPM_INT_STATUS(chip->vendor.locality)); ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ struct tpm_chip *chip = (struct tpm_chip *) dev_id; ++ u32 interrupt; ++ int i; ++ ++ interrupt = ioread32(chip->vendor.iobase + ++ TPM_INT_STATUS(chip->vendor.locality)); ++ ++ if (interrupt == 0) ++ return IRQ_NONE; ++ ++ if (interrupt & TPM_INTF_DATA_AVAIL_INT) ++ wake_up_interruptible(&chip->vendor.read_queue); ++ if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) ++ for (i = 0; i < 5; i++) ++ if (check_locality(chip, i) >= 0) ++ break; ++ if (interrupt & ++ (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT | ++ TPM_INTF_CMD_READY_INT)) ++ wake_up_interruptible(&chip->vendor.int_queue); ++ ++ /* Clear interrupts handled with TPM_EOI */ ++ iowrite32(interrupt, ++ chip->vendor.iobase + ++ TPM_INT_STATUS(chip->vendor.locality)); ++ return IRQ_HANDLED; ++} ++ ++static int interrupts = 1; ++module_param(interrupts, bool, 0444); ++MODULE_PARM_DESC(interrupts, "Enable interrupts"); ++ ++static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, ++ const struct pnp_device_id *pnp_id) ++{ ++ u32 vendor, intfcaps, intmask; ++ int rc, i; ++ unsigned long start, len; ++ struct tpm_chip *chip; ++ ++ start = pnp_mem_start(pnp_dev, 0); ++ len = pnp_mem_len(pnp_dev, 0); ++ ++ if (!start) ++ start = TIS_MEM_BASE; ++ if (!len) ++ len = TIS_MEM_LEN; ++ ++ if (!(chip = tpm_register_hardware(&pnp_dev->dev, &tpm_tis))) ++ return -ENODEV; ++ ++ chip->vendor.iobase = ioremap(start, len); ++ if (!chip->vendor.iobase) { ++ rc = -EIO; ++ goto out_err; ++ } ++ ++ vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); ++ ++ /* Default timeouts */ ++ chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); ++ chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); ++ chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); ++ chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); ++ ++ dev_info(&pnp_dev->dev, ++ "1.2 TPM (device-id 0x%X, rev-id %d)\n", ++ vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); ++ ++ /* Figure out the capabilities */ ++ intfcaps = ++ ioread32(chip->vendor.iobase + ++ TPM_INTF_CAPS(chip->vendor.locality)); ++ dev_dbg(&pnp_dev->dev, "TPM interface capabilities (0x%x):\n", ++ intfcaps); ++ if (intfcaps & TPM_INTF_BURST_COUNT_STATIC) ++ dev_dbg(&pnp_dev->dev, "\tBurst Count Static\n"); ++ if (intfcaps & TPM_INTF_CMD_READY_INT) ++ dev_dbg(&pnp_dev->dev, "\tCommand Ready Int Support\n"); ++ if (intfcaps & TPM_INTF_INT_EDGE_FALLING) ++ dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Falling\n"); ++ if (intfcaps & TPM_INTF_INT_EDGE_RISING) ++ dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Rising\n"); ++ if (intfcaps & TPM_INTF_INT_LEVEL_LOW) ++ dev_dbg(&pnp_dev->dev, "\tInterrupt Level Low\n"); ++ if (intfcaps & TPM_INTF_INT_LEVEL_HIGH) ++ dev_dbg(&pnp_dev->dev, "\tInterrupt Level High\n"); ++ if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) ++ dev_dbg(&pnp_dev->dev, "\tLocality Change Int Support\n"); ++ if (intfcaps & TPM_INTF_STS_VALID_INT) ++ dev_dbg(&pnp_dev->dev, "\tSts Valid Int Support\n"); ++ if (intfcaps & TPM_INTF_DATA_AVAIL_INT) ++ dev_dbg(&pnp_dev->dev, "\tData Avail Int Support\n"); ++ ++ if (request_locality(chip, 0) != 0) { ++ rc = -ENODEV; ++ goto out_err; ++ } ++ ++ /* INTERRUPT Setup */ ++ init_waitqueue_head(&chip->vendor.read_queue); ++ init_waitqueue_head(&chip->vendor.int_queue); ++ ++ intmask = ++ ioread32(chip->vendor.iobase + ++ TPM_INT_ENABLE(chip->vendor.locality)); ++ ++ intmask |= TPM_INTF_CMD_READY_INT ++ | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT ++ | TPM_INTF_STS_VALID_INT; ++ ++ iowrite32(intmask, ++ chip->vendor.iobase + ++ TPM_INT_ENABLE(chip->vendor.locality)); ++ if (interrupts) { ++ chip->vendor.irq = ++ ioread8(chip->vendor.iobase + ++ TPM_INT_VECTOR(chip->vendor.locality)); ++ ++ for (i = 3; i < 16 && chip->vendor.irq == 0; i++) { ++ iowrite8(i, chip->vendor.iobase + ++ TPM_INT_VECTOR(chip->vendor.locality)); ++ if (request_irq ++ (i, tis_int_probe, SA_SHIRQ, ++ chip->vendor.miscdev.name, chip) != 0) { ++ dev_info(chip->dev, ++ "Unable to request irq: %d for probe\n", ++ i); ++ continue; ++ } ++ ++ /* Clear all existing */ ++ iowrite32(ioread32 ++ (chip->vendor.iobase + ++ TPM_INT_STATUS(chip->vendor.locality)), ++ chip->vendor.iobase + ++ TPM_INT_STATUS(chip->vendor.locality)); ++ ++ /* Turn on */ ++ iowrite32(intmask | TPM_GLOBAL_INT_ENABLE, ++ chip->vendor.iobase + ++ TPM_INT_ENABLE(chip->vendor.locality)); ++ ++ /* Generate Interrupts */ ++ tpm_gen_interrupt(chip); ++ ++ /* Turn off */ ++ iowrite32(intmask, ++ chip->vendor.iobase + ++ TPM_INT_ENABLE(chip->vendor.locality)); ++ free_irq(i, chip); ++ } ++ } ++ if (chip->vendor.irq) { ++ iowrite8(chip->vendor.irq, ++ chip->vendor.iobase + ++ TPM_INT_VECTOR(chip->vendor.locality)); ++ if (request_irq ++ (chip->vendor.irq, tis_int_handler, SA_SHIRQ, ++ chip->vendor.miscdev.name, chip) != 0) { ++ dev_info(chip->dev, ++ "Unable to request irq: %d for use\n", ++ chip->vendor.irq); ++ chip->vendor.irq = 0; ++ } else { ++ /* Clear all existing */ ++ iowrite32(ioread32 ++ (chip->vendor.iobase + ++ TPM_INT_STATUS(chip->vendor.locality)), ++ chip->vendor.iobase + ++ TPM_INT_STATUS(chip->vendor.locality)); ++ ++ /* Turn on */ ++ iowrite32(intmask | TPM_GLOBAL_INT_ENABLE, ++ chip->vendor.iobase + ++ TPM_INT_ENABLE(chip->vendor.locality)); ++ } ++ } ++ ++ INIT_LIST_HEAD(&chip->vendor.list); ++ spin_lock(&tis_lock); ++ list_add(&chip->vendor.list, &tis_chips); ++ spin_unlock(&tis_lock); ++ ++ tpm_get_timeouts(chip); ++ tpm_continue_selftest(chip); ++ ++ return 0; ++out_err: ++ if (chip->vendor.iobase) ++ iounmap(chip->vendor.iobase); ++ tpm_remove_hardware(chip->dev); ++ return rc; ++} ++ ++static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg) ++{ ++ return tpm_pm_suspend(&dev->dev, msg); ++} ++ ++static int tpm_tis_pnp_resume(struct pnp_dev *dev) ++{ ++ return tpm_pm_resume(&dev->dev); ++} ++ ++static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { ++ {"PNP0C31", 0}, /* TPM */ ++ {"ATM1200", 0}, /* Atmel */ ++ {"IFX0102", 0}, /* Infineon */ ++ {"BCM0101", 0}, /* Broadcom */ ++ {"NSC1200", 0}, /* National */ ++ /* Add new here */ ++ {"", 0}, /* User Specified */ ++ {"", 0} /* Terminator */ ++}; ++ ++static struct pnp_driver tis_pnp_driver = { ++ .name = "tpm_tis", ++ .id_table = tpm_pnp_tbl, ++ .probe = tpm_tis_pnp_init, ++ .suspend = tpm_tis_pnp_suspend, ++ .resume = tpm_tis_pnp_resume, ++}; ++ ++#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2 ++module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, ++ sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); ++MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); ++ ++static int __init init_tis(void) ++{ ++ return pnp_register_driver(&tis_pnp_driver); ++} ++ ++static void __exit cleanup_tis(void) ++{ ++ struct tpm_vendor_specific *i, *j; ++ struct tpm_chip *chip; ++ spin_lock(&tis_lock); ++ list_for_each_entry_safe(i, j, &tis_chips, list) { ++ chip = to_tpm_chip(i); ++ iowrite32(~TPM_GLOBAL_INT_ENABLE & ++ ioread32(chip->vendor.iobase + ++ TPM_INT_ENABLE(chip->vendor. ++ locality)), ++ chip->vendor.iobase + ++ TPM_INT_ENABLE(chip->vendor.locality)); ++ release_locality(chip, chip->vendor.locality, 1); ++ if (chip->vendor.irq) ++ free_irq(chip->vendor.irq, chip); ++ iounmap(i->iobase); ++ list_del(&i->list); ++ tpm_remove_hardware(chip->dev); ++ } ++ spin_unlock(&tis_lock); ++ pnp_unregister_driver(&tis_pnp_driver); ++} ++ ++module_init(init_tis); ++module_exit(cleanup_tis); ++MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)"); ++MODULE_DESCRIPTION("TPM Driver"); ++MODULE_VERSION("2.0"); ++MODULE_LICENSE("GPL"); + diff -r 4b51d081378d -r 856caf975abd tools/examples/vtpm-addtodb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/examples/vtpm-addtodb Mon Jul 03 08:35:12 2006 +0100 @@ -0,0 +1,10 @@ +#!/bin/sh + +# This script must be called with the following parameters to have +# an entry added to the TPM-to-domain associations table in /etc/xen/vtpm.db +# vtpm-addtodb <dom name> <instance number> + +dir=$(dirname "$0") +. "$dir/vtpm-common.sh" + +vtpmdb_add_instance $1 $2 diff -r 4b51d081378d -r 856caf975abd tools/firmware/hvmloader/mp_tables.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/firmware/hvmloader/mp_tables.c Mon Jul 03 08:35:12 2006 +0100 @@ -0,0 +1,426 @@ +/* + * mp_tables.c: Dynamically writes MP table info into the ROMBIOS. + * + * In order to work with various VCPU counts, this code reads the VCPU count + * for the HVM partition and creates the correct MP tables for the VCPU count + * and places the information into a predetermined location set aside in the + * ROMBIOS during build time. + * + * Please note that many of the values, such as the CPU's + * family/model/stepping, are hard-coded based upon the values that were used + * in the ROMBIOS and may need to be modified or calculated dynamically to + * correspond with what an HVM guest's CPUID returns. + * + * Travis Betak, travis.betak@xxxxxxx + * Copyright (c) 2006, AMD. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + */ + + +/* FIXME find a header that already has types defined!!! */ +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned int uint32_t; +typedef signed int int32_t; +#ifdef __i386__ +typedef unsigned long long uint64_t; +typedef signed long long int64_t; +#else +typedef unsigned long uint64_t; +typedef signed long int64_t; +#endif + +#define ROMBIOS_SEG 0xF000 +#define ROMBIOS_BEGIN 0x000F0000 +#define ROMBIOS_SIZE 0x00010000 +#define ROMBIOS_MAXOFFSET 0x0000FFFF +#define ROMBIOS_END (ROMBIOS_BEGIN + ROMBIOS_SIZE) + +/* number of non-processor MP table entries */ +#define NR_NONPROC_ENTRIES 18 + +#define ENTRY_TYPE_PROCESSOR 0 +#define ENTRY_TYPE_BUS 1 +#define ENTRY_TYPE_IOAPIC 2 +#define ENTRY_TYPE_IO_INTR 3 +#define ENTRY_TYPE_LOCAL_INTR 4 + +#define CPU_FLAG_ENABLED 0x01 +#define CPU_FLAG_BSP 0x02 + +/* TODO change this to correspond with what the guest's see's from CPUID */ +#define CPU_SIG_FAMILY 0x06 +#define CPU_SIG_MODEL 0x00 +#define CPU_SIG_STEPPING 0x00 +#define CPU_SIGNATURE ((CPU_SIG_FAMILY << 8) \ + | (CPU_SIG_MODEL << 4) \ + | (CPU_SIG_STEPPING)) +#define CPU_FEATURE_FPU (1U << 0) +#define CPU_FEATURE_MCE (1U << 7) +#define CPU_FEATURE_CX8 (1U << 8) +#define CPU_FEATURE_APIC (1U << 9) +#define CPU_FEATURES (CPU_FEATURE_FPU | CPU_FEATURE_APIC) + +#define BUS_TYPE_LENGTH 6 +#define BUS_TYPE_STR_ISA "ISA " + +#define LAPIC_BASE_ADDR 0xFEE00000 + +#define IOAPIC_VERSION 0x11 +#define IOAPIC_BASE_ADDR 0xFEC00000 +#define IOAPIC_FLAG_ENABLED (1U << 0) + +#define INTR_TYPE_INT 0 +#define INTR_TYPE_NMI 1 +#define INTR_TYPE_SMI 2 +#define INTR_TYPE_EXTINT 3 + +#define INTR_FLAGS 0 + +#define INTR_MAX_NR 16 + +extern int puts(const char *); /* for printing */ +extern int get_vcpu_nr(void); /* for the guest's VCPU count */ + +/* + * The following structures are defined in the MuliProcessor Specifiation v1.4 + */ + +/* MP Floating Pointer Structure */ +struct mp_floating_pointer_struct { + uint8_t signature[4]; + uint32_t mp_table; + uint8_t length; + uint8_t revision; + uint8_t checksum; + uint8_t feature[5]; +}; + +/* MP Configuration Table */ +struct mp_config_table { + uint8_t signature[4]; + uint16_t length; + uint8_t revision; + uint8_t checksum; + uint8_t oem_id[8]; + uint8_t vendor_id[12]; + uint32_t oem_table; + uint16_t oem_table_sz; + uint16_t nr_entries; + uint32_t lapic; + uint16_t extended_length; + uint8_t extended_checksum; + uint8_t reserved; +}; + +/* MP Processor Entry */ +struct mp_proc_entry { + uint8_t type; + uint8_t lapic_id; + uint8_t lapic_version; + uint8_t cpu_flags; + uint32_t cpu_signature; + uint32_t feature_flags; + uint8_t reserved[8]; +}; + +/* MP Bus Entry */ +struct mp_bus_entry { + uint8_t type; + uint8_t bus_id; + uint8_t bus_type_str[6]; +}; + +/* MP IOAPIC Entry */ +struct mp_ioapic_entry { + uint8_t type; + uint8_t ioapic_id; + uint8_t ioapic_version; + uint8_t ioapic_flags; + uint32_t ioapic_addr; +}; + +/* MP IO Interrupt Entry */ +struct mp_io_intr_entry { + uint8_t type; + uint8_t intr_type; + uint16_t io_intr_flags; + uint8_t src_bus_id; + uint8_t src_bus_irq; + uint8_t dst_ioapic_id; + uint8_t dst_ioapic_intin; +}; + +/* MP Local Interrupt Entry */ +struct mp_local_intr_entry { + uint8_t type; + uint8_t intr_type; + uint16_t local_intr_flags; + uint8_t src_bus_id; + uint8_t src_bus_irq; + uint8_t dst_lapic_id; + uint8_t dst_lapic_lintin; +}; + + +/* + * fill_mp_config_table - fills in the information for the MP config table + * + * When calculating the length and nr_entries fields, keep in mind that there + * are always 18 non-processor entries and N processor entries + * + * N vcpu entries + * 1 bus entry + * 1 IOAPIC entry + * + 16 IO intr. entries + * ---------------------- + * 18 + N total entries + */ +void fill_mp_config_table(struct mp_config_table *mpct) +{ + int vcpu_nr; + + vcpu_nr = get_vcpu_nr(); + + /* fill in the MP configuration table signature, "PCMP" */ + mpct->signature[0] = 'P'; + mpct->signature[1] = 'C'; + mpct->signature[2] = 'M'; + mpct->signature[3] = 'P'; + + mpct->length = sizeof(struct mp_config_table) + + vcpu_nr * sizeof(struct mp_proc_entry) + + sizeof(struct mp_ioapic_entry) + + sizeof(struct mp_bus_entry) + + 16 * sizeof(struct mp_local_intr_entry); + + mpct->revision = 4; + + /* + * We'll fill in the checksum later after all of the + * entries have been created + */ + mpct->checksum = 0; + + /* fill in the OEM ID string, "_HVMCPU_" */ + mpct->oem_id[0] = '_'; mpct->oem_id[3] = 'M'; mpct->oem_id[6] = 'U'; + mpct->oem_id[1] = 'H'; mpct->oem_id[4] = 'C'; mpct->oem_id[7] = '_'; + mpct->oem_id[2] = 'V'; mpct->oem_id[5] = 'P'; + + /* fill in the Vendor ID string, "XEN " */ + mpct->vendor_id[0] = 'X'; mpct->vendor_id[6] = ' '; + mpct->vendor_id[1] = 'E'; mpct->vendor_id[7] = ' '; + mpct->vendor_id[2] = 'N'; mpct->vendor_id[8] = ' '; + mpct->vendor_id[3] = ' '; mpct->vendor_id[9] = ' '; + mpct->vendor_id[4] = ' '; mpct->vendor_id[10] = ' '; + mpct->vendor_id[5] = ' '; mpct->vendor_id[11] = ' '; + + mpct->oem_table = 0; + mpct->oem_table_sz = 0; + + mpct->nr_entries = vcpu_nr + NR_NONPROC_ENTRIES; + + mpct->lapic = LAPIC_BASE_ADDR; + mpct->extended_length = 0; + mpct->extended_checksum = 0; +} + + +/* calculates the checksum for the MP configuration table */ +void fill_mp_config_table_checksum(struct mp_config_table *mpct) +{ + int i; + uint8_t checksum; + + checksum = 0; + for (i = 0; i < mpct->length; ++i) + checksum += ((uint8_t *)(mpct))[i]; + mpct->checksum = -checksum; +} + + +/* fills in an MP processor entry for VCPU 'vcpu_id' */ +void fill_mp_proc_entry(struct mp_proc_entry *mppe, int vcpu_id) +{ + mppe->type = ENTRY_TYPE_PROCESSOR; + mppe->lapic_id = vcpu_id; + mppe->lapic_version = 0x11; + mppe->cpu_flags = CPU_FLAG_ENABLED; + if (vcpu_id == 0) + mppe->cpu_flags |= CPU_FLAG_BSP; + mppe->cpu_signature = CPU_SIGNATURE; + mppe->feature_flags = CPU_FEATURES; +} + + +/* fills in an MP bus entry of type 'type' and bus ID 'bus_id' */ +void fill_mp_bus_entry(struct mp_bus_entry *mpbe, int bus_id, const char *type) +{ + int i; + + mpbe->type = ENTRY_TYPE_BUS; + mpbe->bus_id = bus_id; + for (i = 0; i < BUS_TYPE_LENGTH; ++i) + mpbe->bus_type_str[i] = type[i]; /* FIXME length check? */ +} + + +/* fills in an MP IOAPIC entry for IOAPIC 'ioapic_id' */ +void fill_mp_ioapic_entry(struct mp_ioapic_entry *mpie, int ioapic_id) +{ + mpie->type = ENTRY_TYPE_IOAPIC; + mpie->ioapic_id = ioapic_id; + mpie->ioapic_version = IOAPIC_VERSION; + mpie->ioapic_flags = IOAPIC_FLAG_ENABLED; + mpie->ioapic_addr = IOAPIC_BASE_ADDR; +} + + +/* fills in an IO interrupt entry for IOAPIC 'ioapic_id' */ +void fill_mp_io_intr_entry(struct mp_io_intr_entry *mpiie, + int src_bus_irq, int ioapic_id, int dst_ioapic_intin) +{ + mpiie->type = ENTRY_TYPE_IO_INTR; + mpiie->intr_type = INTR_TYPE_INT; + mpiie->io_intr_flags = INTR_FLAGS; + mpiie->src_bus_id = 0; + mpiie->src_bus_irq = src_bus_irq; + mpiie->dst_ioapic_id = ioapic_id; + mpiie->dst_ioapic_intin = dst_ioapic_intin; +} + + +/* fill in the mp floating processor structure */ +void fill_mpfps(struct mp_floating_pointer_struct *mpfps, uint32_t mpct) +{ + int i; + uint8_t checksum; + + + mpfps->signature[0] = '_'; + mpfps->signature[1] = 'M'; + mpfps->signature[2] = 'P'; + mpfps->signature[3] = '_'; + + mpfps->mp_table = mpct; + mpfps->length = 1; + mpfps->revision = 4; + mpfps->checksum = 0; + for (i = 0; i < 5; ++i) + mpfps->feature[i] = 0; + + /* compute the checksum for our new table */ + checksum = 0; + for (i = 0; i < sizeof(struct mp_floating_pointer_struct); ++i) + checksum += ((uint8_t *)(mpfps))[i]; + mpfps->checksum = -checksum; +} + + +/* + * find_mp_table_start - searchs through BIOS memory for '___HVMMP' signature + * + * The '___HVMMP' signature is created by the ROMBIOS and designates a chunk + * of space inside the ROMBIOS that is safe for us to write our MP table info + */ +void* get_mp_table_start(void) +{ + char *bios_mem; + for (bios_mem = (char *)ROMBIOS_BEGIN; + bios_mem != (char *)ROMBIOS_END; + ++bios_mem) + if (bios_mem[0] == '_' && bios_mem[1] == '_' && + bios_mem[2] == '_' && bios_mem[3] == 'H' && + bios_mem[4] == 'V' && bios_mem[5] == 'M' && + bios_mem[6] == 'M' && bios_mem[7] == 'P') + return bios_mem; + + return (void *)-1; +} + + +/* recalculate the new ROMBIOS checksum after adding MP tables */ +void reset_bios_checksum(void) +{ + uint32_t i; + uint8_t checksum; + + checksum = 0; + for (i = 0; i < ROMBIOS_MAXOFFSET; ++i) + checksum += ((uint8_t *)(ROMBIOS_BEGIN))[i]; + + *((uint8_t *)(ROMBIOS_BEGIN + ROMBIOS_MAXOFFSET)) = -checksum; +} + + +/* create_mp_tables - creates MP tables for the guest based upon config data */ +void create_mp_tables(void) +{ + void *mp_table_base; + char *p; + struct mp_config_table *mp_config_table; + int vcpu_nr; + int i; + + vcpu_nr = get_vcpu_nr(); + + puts("Creating MP tables ...\n"); + + /* find the 'safe' place in ROMBIOS for the MP tables */ + mp_table_base = get_mp_table_start(); + if (mp_table_base == (void *)-1) { + puts("Couldn't find start point for MP tables\n"); + return; + } + p = mp_table_base; + + fill_mp_config_table((struct mp_config_table *)p); + + /* save the location of the MP config table for a little later*/ + mp_config_table = (struct mp_config_table *)p; + p += sizeof(struct mp_config_table); + + for (i = 0; i < vcpu_nr; ++i) { + fill_mp_proc_entry((struct mp_proc_entry *)p, i); + p += sizeof(struct mp_proc_entry); + } + + fill_mp_bus_entry((struct mp_bus_entry *)p, 0, BUS_TYPE_STR_ISA); + p += sizeof(struct mp_bus_entry); + + fill_mp_ioapic_entry((struct mp_ioapic_entry *)p, vcpu_nr); + p += sizeof(struct mp_ioapic_entry); + + for (i = 0; i < INTR_MAX_NR; ++i) { + fill_mp_io_intr_entry((struct mp_io_intr_entry *)p, + i, vcpu_nr, i); + p += sizeof(struct mp_io_intr_entry); + } + + /* find the next 16-byte boundary to place the mp floating pointer */ + while ((unsigned long)p & 0xF) + ++p; + + fill_mpfps((struct mp_floating_pointer_struct *)p, + (uint32_t)mp_table_base); + + /* calculate the MP configuration table's checksum */ + fill_mp_config_table_checksum(mp_config_table); + + /* finally, recalculate the ROMBIOS checksum */ + reset_bios_checksum(); +} diff -r 4b51d081378d -r 856caf975abd tools/xm-test/tests/vtpm/06_vtpm-susp_res_pcrs.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/xm-test/tests/vtpm/06_vtpm-susp_res_pcrs.py Mon Jul 03 08:35:12 2006 +0100 @@ -0,0 +1,139 @@ +#!/usr/bin/python + +# Copyright (C) International Business Machines Corp., 2006 +# Author: Stefan Berger <stefanb@xxxxxxxxxx> + +# Positive Test: create domain with virtual TPM attached at build time, +# extend a pcr +# check list of pcrs; suspend and resume the domain and +# check list of pcrs again and validate extended pcr + +from XmTestLib import * +from vtpm_utils import * +import commands +import os +import os.path + +config = {"vtpm":"instance=1,backend=0"} +domain = XmTestDomain(extraConfig=config) +domName = domain.getName() +consoleHistory = "" + +try: + console = domain.start() +except DomainError, e: + if verbose: + print e.extra + vtpm_cleanup(domName) + FAIL("Unable to create domain (%s)" % domName) + +try: + console.sendInput("input") +except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL(str(e)) + +try: + run = console.runCmd("mknod /dev/tpm0 c 10 224") +except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Error while creating /dev/tpm0") + +try: + run = console.runCmd("echo -ne \"\\x00\\xc1\\x00\\x00\\x00\\x22\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\0xf\\x10\\x11\\x12\\x13\\x14\" > /dev/tpm0") +except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Error while extending PCR 0") + +try: + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") +except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("No result from dumping the PCRs") + + +if re.search("No such file",run["output"]): + vtpm_cleanup(domName) + FAIL("TPM frontend support not compiled into (domU?) kernel") + +if not re.search("PCR-00:",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side: \n%s" % run["output"]) + +if not re.search("PCR-00: 1E A7 BD",run["output"]): + saveLog(console.getHistory()) + FAIL("Extend did not lead to expected result (1E A7 BD ...): \n%s" % run["output"]) + +consoleHistory = console.getHistory() +domain.closeConsole() + +loop = 0 +while loop < 3: + try: + status, ouptut = traceCommand("xm save %s %s.save" % + (domName, domName), + timeout=30) + + except TimeoutError, e: + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL(str(e)) + + if status != 0: + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL("xm save did not succeed") + + try: + status, ouptut = traceCommand("xm restore %s.save" % + (domName), + timeout=30) + except TimeoutError, e: + os.remove("%s.save" % domName) + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL(str(e)) + + os.remove("%s.save" % domName) + + if status != 0: + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL("xm restore did not succeed") + + try: + console = domain.getConsole() + except ConsoleError, e: + vtpm_cleanup(domName) + FAIL(str(e)) + + try: + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") + except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL(str(e)) + + if not re.search("PCR-00:",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") + + if not re.search("PCR-00: 1E A7 BD",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM lost PCR 0 value: \n%s" % run["output"]) + + loop += 1 + +domain.closeConsole() + +domain.stop() + +vtpm_cleanup(domName) + diff -r 4b51d081378d -r 856caf975abd tools/xm-test/tests/vtpm/07_vtpm-mig_pcrs.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/xm-test/tests/vtpm/07_vtpm-mig_pcrs.py Mon Jul 03 08:35:12 2006 +0100 @@ -0,0 +1,132 @@ +#!/usr/bin/python + +# Copyright (C) International Business Machines Corp., 2006 +# Author: Stefan Berger <stefanb@xxxxxxxxxx> + +# Positive Test: create domain with virtual TPM attached at build time, +# extend a pcr +# check list of pcrs; locally migrate the domain and +# check list of pcrs again and validate extended pcr +# This test does local live migration. + +from XmTestLib import * +from vtpm_utils import * +import commands +import os +import os.path + +config = {"vtpm":"instance=1,backend=0"} +domain = XmTestDomain(extraConfig=config) +domName = domain.getName() +consoleHistory = "" + +try: + console = domain.start() +except DomainError, e: + if verbose: + print e.extra + vtpm_cleanup(domName) + FAIL("Unable to create domain (%s)" % domName) + +try: + console.sendInput("input") +except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL(str(e)) + +try: + run = console.runCmd("mknod /dev/tpm0 c 10 224") +except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Error while creating /dev/tpm0") + +try: + run = console.runCmd("echo -ne \"\\x00\\xc1\\x00\\x00\\x00\\x22\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\0xf\\x10\\x11\\x12\\x13\\x14\" > /dev/tpm0") +except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Error while extending PCR 0") + +try: + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") +except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("No result from dumping the PCRs") + + +if re.search("No such file",run["output"]): + vtpm_cleanup(domName) + FAIL("TPM frontend support not compiled into (domU?) kernel") + +if not re.search("PCR-00:",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side: \n%s" % run["output"]) + +if not re.search("PCR-00: 1E A7 BD",run["output"]): + saveLog(console.getHistory()) + FAIL("Extend did not lead to expected result (1E A7 BD ...): \n%s" % run["output"]) + +consoleHistory = console.getHistory() +domain.closeConsole() + +old_domid = domid(domName) + +loop = 0 +while loop < 3: + try: + status, ouptut = traceCommand("xm migrate -l %s localhost" % + domName, + timeout=90) + except TimeoutError, e: + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL(str(e)) + + if status != 0: + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL("xm migrate did not succeed. External device migration activated?") + + + domName = domain.getName() + new_domid = domid(domName) + + if (old_domid == new_domid): + vtpm_cleanup(domName) + FAIL("xm migrate failed, domain id is still %s (loop=%d)" % + (old_domid,loop)) + + try: + console = domain.getConsole() + except ConsoleError, e: + vtpm_cleanup(domName) + FAIL(str(e)) + + try: + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") + except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("No result from dumping the PCRs") + + if not re.search("PCR-00:",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") + + if not re.search("PCR-00: 1E A7 BD",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM lost PCR 0 value: \n%s" % run["output"]) + + loop += 1 + +domain.closeConsole() + +domain.stop() + +vtpm_cleanup(domName) diff -r 4b51d081378d -r 856caf975abd tools/xm-test/tests/vtpm/08_vtpm-mig_pcrs.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/xm-test/tests/vtpm/08_vtpm-mig_pcrs.py Mon Jul 03 08:35:12 2006 +0100 @@ -0,0 +1,132 @@ +#!/usr/bin/python + +# Copyright (C) International Business Machines Corp., 2006 +# Author: Stefan Berger <stefanb@xxxxxxxxxx> + +# Positive Test: create domain with virtual TPM attached at build time, +# extend a pcr +# check list of pcrs; locally migrate the domain and +# check list of pcrs again and validate extended pcr +# This test does local (non-live) migration. + +from XmTestLib import * +from vtpm_utils import * +import commands +import os +import os.path + +config = {"vtpm":"instance=1,backend=0"} +domain = XmTestDomain(extraConfig=config) +domName = domain.getName() +consoleHistory = "" + +try: + console = domain.start() +except DomainError, e: + if verbose: + print e.extra + vtpm_cleanup(domName) + FAIL("Unable to create domain (%s)" % domName) + +try: + console.sendInput("input") +except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL(str(e)) + +try: + run = console.runCmd("mknod /dev/tpm0 c 10 224") +except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Error while creating /dev/tpm0") + +try: + run = console.runCmd("echo -ne \"\\x00\\xc1\\x00\\x00\\x00\\x22\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\0xf\\x10\\x11\\x12\\x13\\x14\" > /dev/tpm0") +except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Error while extending PCR 0") + +try: + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") +except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("No result from dumping the PCRs") + + +if re.search("No such file",run["output"]): + vtpm_cleanup(domName) + FAIL("TPM frontend support not compiled into (domU?) kernel") + +if not re.search("PCR-00:",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side: \n%s" % run["output"]) + +if not re.search("PCR-00: 1E A7 BD",run["output"]): + saveLog(console.getHistory()) + FAIL("Extend did not lead to expected result (1E A7 BD ...): \n%s" % run["output"]) + +consoleHistory = console.getHistory() +domain.closeConsole() + +old_domid = domid(domName) + +loop = 0 +while loop < 3: + try: + status, ouptut = traceCommand("xm migrate %s localhost" % + domName, + timeout=90) + except TimeoutError, e: + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL(str(e)) + + if status != 0: + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL("xm migrate did not succeed. External device migration activated?") + + + domName = domain.getName() + new_domid = domid(domName) + + if (old_domid == new_domid): + vtpm_cleanup(domName) + FAIL("xm migrate failed, domain id is still %s (loop=%d)" % + (old_domid,loop)) + + try: + console = domain.getConsole() + except ConsoleError, e: + vtpm_cleanup(domName) + FAIL(str(e)) + + try: + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") + except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("No result from dumping the PCRs") + + if not re.search("PCR-00:",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") + + if not re.search("PCR-00: 1E A7 BD",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM lost PCR 0 value: \n%s" % run["output"]) + + loop += 1 + +domain.closeConsole() + +domain.stop() + +vtpm_cleanup(domName) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |