# 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
|