qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2] Add ACPI tables for TPM


From: Michael S. Tsirkin
Subject: Re: [Qemu-devel] [PATCH v2] Add ACPI tables for TPM
Date: Wed, 30 Jul 2014 15:20:27 +0200

On Tue, Jul 29, 2014 at 06:52:19AM -0400, Stefan Berger wrote:
> From: Stefan Berger <address@hidden>
> 
> Add an SSDT ACPI table for the TPM device.
> Add a TCPA table for BIOS logging area when a TPM is being used.
> 
> The latter follows this spec here:
> 
> http://www.trustedcomputinggroup.org/files/static_page_files/DCD4188E-1A4B-B294-D050A155FB6F7385/TCG_ACPIGeneralSpecification_PublicReview.pdf
> 
> Signed-off-by: Stefan Berger <address@hidden>
> ---
>  hw/i386/Makefile.objs |  3 ++-
>  hw/i386/acpi-build.c  | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>  hw/i386/acpi-defs.h   | 11 +++++++++++
>  hw/i386/ssdt-tpm.dsl  | 43 +++++++++++++++++++++++++++++++++++++++++++
>  hw/tpm/tpm_tis.h      |  5 +----
>  include/hw/acpi/tpm.h | 29 +++++++++++++++++++++++++++++
>  include/sysemu/tpm.h  |  5 +++++
>  7 files changed, 137 insertions(+), 5 deletions(-)
>  create mode 100644 hw/i386/ssdt-tpm.dsl
>  create mode 100644 include/hw/acpi/tpm.h
> 
> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
> index 48014ab..3688cf8 100644
> --- a/hw/i386/Makefile.objs
> +++ b/hw/i386/Makefile.objs
> @@ -10,7 +10,8 @@ obj-y += bios-linker-loader.o
>  hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex \
>       hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex \
>       hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \
> -     hw/i386/q35-acpi-dsdt.hex hw/i386/ssdt-mem.hex
> +     hw/i386/q35-acpi-dsdt.hex hw/i386/ssdt-mem.hex \
> +     hw/i386/ssdt-tpm.hex
>  
>  iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
>      ; then echo "$(2)"; else echo "$(3)"; fi ;)
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index ebc5f03..d767e37 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -38,6 +38,8 @@
>  #include "hw/loader.h"
>  #include "hw/isa/isa.h"
>  #include "hw/acpi/memory_hotplug.h"
> +#include "sysemu/tpm.h"
> +#include "hw/acpi/tpm.h"
>  
>  /* Supported chipsets: */
>  #include "hw/acpi/piix4.h"
> @@ -75,6 +77,7 @@ typedef struct AcpiPmInfo {
>  
>  typedef struct AcpiMiscInfo {
>      bool has_hpet;
> +    bool has_tpm;
>      DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);
>      const unsigned char *dsdt_code;
>      unsigned dsdt_size;
> @@ -193,6 +196,7 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
>  static void acpi_get_misc_info(AcpiMiscInfo *info)
>  {
>      info->has_hpet = hpet_find();
> +    info->has_tpm = tpm_find();
>      info->pvpanic_port = pvpanic_port();
>  }
>  
> @@ -681,6 +685,7 @@ static inline char acpi_get_hex(uint32_t val)
>  
>  #include "hw/i386/ssdt-misc.hex"
>  #include "hw/i386/ssdt-pcihp.hex"
> +#include "hw/i386/ssdt-tpm.hex"
>  
>  static void
>  build_append_notify_method(GArray *device, const char *name,
> @@ -1167,6 +1172,40 @@ build_hpet(GArray *table_data, GArray *linker)
>                   (void *)hpet, "HPET", sizeof(*hpet), 1);
>  }
>  
> +static void
> +build_tpm_tcpa(GArray *table_data, GArray *linker)
> +{
> +    Acpi20Tcpa *tcpa;
> +    uint32_t log_area_minimum_length = TPM_LOG_AREA_MINIMUM_SIZE;
> +    uint64_t log_area_start_address;
> +    size_t len = log_area_minimum_length + sizeof(*tcpa);
> +
> +    log_area_start_address = table_data->len + sizeof(*tcpa);
> +
> +    tcpa = acpi_data_push(table_data, len);
> +
> +    tcpa->platform_class = cpu_to_le16(TPM_TCPA_ACPI_CLASS_CLIENT);
> +    tcpa->log_area_minimum_length = cpu_to_le32(log_area_minimum_length);
> +    tcpa->log_area_start_address = cpu_to_le64(log_area_start_address);
> +
> +    /* LASA address to be filled by Guest linker */

Hmm, you are simply allocating log area as part of the ACPI table.  It
works because bios happens to allocate tables from high memory.
But I think this is a problem in practice because
bios is allowed to allocate acpi memory differently.
On the other hand log presumably needs to reside in
physical memory somewhere.

If you need bios to allocate this memory, then we will
need a new allocation type for this, add it to linker
in bios and qemu.

Alternatively, find some other way to get hold of
physical memory.
Is there a way to disable the log completely?
As defined in your patch, I doubt there's anything there, ever ..



> +    bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
> +                                   ACPI_BUILD_TABLE_FILE,
> +                                   table_data, &tcpa->log_area_start_address,
> +                                   sizeof(tcpa->log_area_start_address));
> +    build_header(linker, table_data,
> +                 (void *)tcpa, "TCPA", sizeof(*tcpa), 2);
> +}
> +
> +static void
> +build_tpm_ssdt(GArray *table_data, GArray *linker)
> +{
> +    void *tpm_ptr;
> +
> +    tpm_ptr = acpi_data_push(table_data, sizeof(ssdt_tpm_aml));
> +    memcpy(tpm_ptr, ssdt_tpm_aml, sizeof(ssdt_tpm_aml));
> +}
> +
>  typedef enum {
>      MEM_AFFINITY_NOFLAGS      = 0,
>      MEM_AFFINITY_ENABLED      = (1 << 0),
> @@ -1489,6 +1528,13 @@ void acpi_build(PcGuestInfo *guest_info, 
> AcpiBuildTables *tables)
>          acpi_add_table(table_offsets, tables->table_data);
>          build_hpet(tables->table_data, tables->linker);
>      }
> +    if (misc.has_tpm) {
> +        acpi_add_table(table_offsets, tables->table_data);
> +        build_tpm_ssdt(tables->table_data, tables->linker);
> +
> +        acpi_add_table(table_offsets, tables->table_data);
> +        build_tpm_tcpa(tables->table_data, tables->linker);
> +    }
>      if (guest_info->numa_nodes) {
>          acpi_add_table(table_offsets, tables->table_data);
>          build_srat(tables->table_data, tables->linker, &cpu, guest_info);
> diff --git a/hw/i386/acpi-defs.h b/hw/i386/acpi-defs.h
> index e93babb..1bc974a 100644
> --- a/hw/i386/acpi-defs.h
> +++ b/hw/i386/acpi-defs.h
> @@ -314,4 +314,15 @@ struct AcpiTableMcfg {
>  } QEMU_PACKED;
>  typedef struct AcpiTableMcfg AcpiTableMcfg;
>  
> +/*
> + * TCPA Description Table
> + */
> +struct Acpi20Tcpa {
> +    ACPI_TABLE_HEADER_DEF                    /* ACPI common table header */
> +    uint16_t platform_class;
> +    uint32_t log_area_minimum_length;
> +    uint64_t log_area_start_address;
> +} QEMU_PACKED;
> +typedef struct Acpi20Tcpa Acpi20Tcpa;
> +
>  #endif
> diff --git a/hw/i386/ssdt-tpm.dsl b/hw/i386/ssdt-tpm.dsl
> new file mode 100644
> index 0000000..75d9691
> --- /dev/null
> +++ b/hw/i386/ssdt-tpm.dsl
> @@ -0,0 +1,43 @@
> +/*
> + * 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; either version 2 of the License, or
> + * (at your option) any later version.
> +
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> +
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +#include "hw/acpi/tpm.h"
> +
> +ACPI_EXTRACT_ALL_CODE ssdt_tpm_aml
> +
> +DefinitionBlock (
> +    "ssdt-tpm.aml",     // Output Filename
> +    "SSDT",             // Signature
> +    0x01,               // SSDT Compliance Revision
> +    "BXPC",             // OEMID
> +    "BXSSDT",           // TABLE ID
> +    0x1                 // OEM Revision
> +    )
> +{
> +    Scope(\_SB) {
> +        /* TPM with emulated TPM TIS interface */
> +        Device (TPM) {
> +            Name (_HID, EisaID ("PNP0C31"))
> +            Name (_CRS, ResourceTemplate ()
> +            {
> +                Memory32Fixed (ReadWrite, TPM_TIS_ADDR_BASE, 
> TPM_TIS_ADDR_SIZE)
> +                // older Linux tpm_tis drivers do not work with IRQ
> +                //IRQNoFlags () {TPM_TIS_IRQ}
> +            })
> +            Method (_STA, 0, NotSerialized) {
> +                Return (0x0F)
> +            }
> +        }
> +    }
> +}
> diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h
> index 916152a..6cdac24 100644
> --- a/hw/tpm/tpm_tis.h
> +++ b/hw/tpm/tpm_tis.h
> @@ -18,18 +18,15 @@
>  #define TPM_TPM_TIS_H
>  
>  #include "hw/isa/isa.h"
> +#include "hw/acpi/tpm.h"
>  #include "qemu-common.h"
>  
> -#define TPM_TIS_ADDR_BASE           0xFED40000
> -
>  #define TPM_TIS_NUM_LOCALITIES      5     /* per spec */
>  #define TPM_TIS_LOCALITY_SHIFT      12
>  #define TPM_TIS_NO_LOCALITY         0xff
>  
>  #define TPM_TIS_IS_VALID_LOCTY(x)   ((x) < TPM_TIS_NUM_LOCALITIES)
>  
> -#define TPM_TIS_IRQ                 5
> -
>  #define TPM_TIS_BUFFER_MAX          4096
>  
>  #define TYPE_TPM_TIS                "tpm-tis"
> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
> new file mode 100644
> index 0000000..792fcbf
> --- /dev/null
> +++ b/include/hw/acpi/tpm.h
> @@ -0,0 +1,29 @@
> +/*
> + * tpm.h - TPM ACPI definitions
> + *
> + * Copyright (C) 2014 IBM Corporation
> + *
> + * Authors:
> + *  Stefan Berger <address@hidden>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + * Implementation of the TIS interface according to specs found at
> + * http://www.trustedcomputinggroup.org
> + *
> + */
> +#ifndef HW_ACPI_TPM_H
> +#define HW_ACPI_TPM_H
> +
> +#define TPM_TIS_ADDR_BASE           0xFED40000
> +#define TPM_TIS_ADDR_SIZE           0x5000
> +
> +#define TPM_TIS_IRQ                 5
> +
> +#define TPM_LOG_AREA_MINIMUM_SIZE   (64 * 1024)
> +
> +#define TPM_TCPA_ACPI_CLASS_CLIENT  0
> +#define TPM_TCPA_ACPI_CLASS_SERVER  1
> +
> +#endif /* HW_ACPI_TPM_H */
> diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
> index 13febdd..7030109 100644
> --- a/include/sysemu/tpm.h
> +++ b/include/sysemu/tpm.h
> @@ -20,4 +20,9 @@ int tpm_config_parse(QemuOptsList *opts_list, const char 
> *optarg);
>  int tpm_init(void);
>  void tpm_cleanup(void);
>  
> +static inline bool tpm_find(void)
> +{
> +    return object_resolve_path_type("", "tpm-tis", NULL) != NULL;
> +}
> +
>  #endif /* QEMU_TPM_H */
> -- 
> 1.9.3



reply via email to

[Prev in Thread] Current Thread [Next in Thread]