xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Konrad Rzeszutek Wilk <konrad@darnok.org>
To: Haozhong Zhang <haozhong.zhang@intel.com>
Cc: Wei Liu <wei.liu2@citrix.com>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	Ian Jackson <ian.jackson@eu.citrix.com>,
	xen-devel@lists.xen.org, Jan Beulich <jbeulich@suse.com>,
	Xiao Guangrong <guangrong.xiao@linux.intel.com>
Subject: Re: [RFC XEN PATCH 11/16] tools/libacpi: load ACPI built by the device model
Date: Fri, 27 Jan 2017 16:40:43 -0500	[thread overview]
Message-ID: <20170127214042.GF18581@localhost.localdomain> (raw)
In-Reply-To: <20161010003235.4213-12-haozhong.zhang@intel.com>

On Mon, Oct 10, 2016 at 08:32:30AM +0800, Haozhong Zhang wrote:
> ACPI tables built by the device model, whose signatures do not
> conflict with tables built by Xen (except SSDT), are loaded after ACPI
> tables built by Xen.
> 
> ACPI namespace devices built by the device model, whose names do not
> conflict with devices built by Xen, are assembled and placed in SSDTs
> after ACPI tables built by Xen.
> 
> Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
> ---
> Cc: Jan Beulich <jbeulich@suse.com>
> Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Wei Liu <wei.liu2@citrix.com>
> ---
>  tools/firmware/hvmloader/util.c |  12 +++
>  tools/libacpi/acpi2_0.h         |   2 +
>  tools/libacpi/build.c           | 216 ++++++++++++++++++++++++++++++++++++++++
>  tools/libacpi/libacpi.h         |   5 +
>  4 files changed, 235 insertions(+)
> 
> diff --git a/tools/firmware/hvmloader/util.c b/tools/firmware/hvmloader/util.c
> index dba954a..e6530cd 100644
> --- a/tools/firmware/hvmloader/util.c
> +++ b/tools/firmware/hvmloader/util.c
> @@ -998,6 +998,18 @@ void hvmloader_acpi_build_tables(struct acpi_config *config,
>      if ( !strncmp(xenstore_read("platform/acpi_s4", "1"), "1", 1)  )
>          config->table_flags |= ACPI_HAS_SSDT_S4;
>  
> +    s = xenstore_read(HVM_XS_DM_ACPI_ADDRESS, NULL);
> +    if ( s )
> +    {
> +        config->dm.addr = strtoll(s, NULL, 0);
> +
> +        s = xenstore_read(HVM_XS_DM_ACPI_LENGTH, NULL);
> +        if ( s )
> +            config->dm.length = strtoll(s, NULL, 0);
> +        else
> +            config->dm.addr = 0;
> +    }
> +
>      config->table_flags |= (ACPI_HAS_TCPA | ACPI_HAS_IOAPIC | ACPI_HAS_WAET);
>  
>      config->tis_hdr = (uint16_t *)ACPI_TIS_HDR_ADDRESS;
> diff --git a/tools/libacpi/acpi2_0.h b/tools/libacpi/acpi2_0.h
> index 775eb7a..7414470 100644
> --- a/tools/libacpi/acpi2_0.h
> +++ b/tools/libacpi/acpi2_0.h
> @@ -430,6 +430,7 @@ struct acpi_20_slit {
>  #define ACPI_2_0_WAET_SIGNATURE ASCII32('W','A','E','T')
>  #define ACPI_2_0_SRAT_SIGNATURE ASCII32('S','R','A','T')
>  #define ACPI_2_0_SLIT_SIGNATURE ASCII32('S','L','I','T')
> +#define ACPI_2_0_SSDT_SIGNATURE ASCII32('S','S','D','T')
>  
>  /*
>   * Table revision numbers.
> @@ -445,6 +446,7 @@ struct acpi_20_slit {
>  #define ACPI_1_0_FADT_REVISION 0x01
>  #define ACPI_2_0_SRAT_REVISION 0x01
>  #define ACPI_2_0_SLIT_REVISION 0x01
> +#define ACPI_2_0_SSDT_REVISION 0x02
>  
>  #pragma pack ()
>  
> diff --git a/tools/libacpi/build.c b/tools/libacpi/build.c
> index 47dae01..829a365 100644
> --- a/tools/libacpi/build.c
> +++ b/tools/libacpi/build.c
> @@ -20,6 +20,7 @@
>  #include "ssdt_s4.h"
>  #include "ssdt_tpm.h"
>  #include "ssdt_pm.h"
> +#include "aml_build.h"
>  #include <xen/hvm/hvm_info_table.h>
>  #include <xen/hvm/hvm_xs_strings.h>
>  #include <xen/hvm/params.h>
> @@ -55,6 +56,34 @@ struct acpi_info {
>      uint64_t pci_hi_min, pci_hi_len; /* 24, 32 - PCI I/O hole boundaries */
>  };
>  
> +#define DM_ACPI_BLOB_TYPE_TABLE 0 /* ACPI table */
> +#define DM_ACPI_BLOB_TYPE_NSDEV 1 /* AML definition of an ACPI namespace device */
> +
> +/* ACPI tables of following signatures should not appear in DM ACPI */

It would be good to have some form of build check to check against
this list..
> +static const uint64_t dm_acpi_signature_blacklist[] = {
> +    ACPI_2_0_RSDP_SIGNATURE,
> +    ACPI_2_0_FACS_SIGNATURE,
> +    ACPI_2_0_FADT_SIGNATURE,
> +    ACPI_2_0_MADT_SIGNATURE,
> +    ACPI_2_0_RSDT_SIGNATURE,
> +    ACPI_2_0_XSDT_SIGNATURE,
> +    ACPI_2_0_TCPA_SIGNATURE,
> +    ACPI_2_0_HPET_SIGNATURE,
> +    ACPI_2_0_WAET_SIGNATURE,
> +    ACPI_2_0_SRAT_SIGNATURE,
> +    ACPI_2_0_SLIT_SIGNATURE,
> +};
> +
> +/* ACPI namespace devices of following names should not appear in DM ACPI */
> +static const char *dm_acpi_devname_blacklist[] = {
> +    "MEM0",
> +    "PCI0",
> +    "AC",
> +    "BAT0",
> +    "BAT1",
> +    "TPM",

.. and this one.

But I am not even sure how one would do that?

Perhaps add a big warning:

"Make sure to add your table name if you this code (libacpi) is
constructing it. "?

Or maybe have some 'register_acpi_table' function which will expand
this blacklist?

> +};
> +
>  static void set_checksum(
>      void *table, uint32_t checksum_offset, uint32_t length)
>  {
> @@ -339,6 +368,190 @@ static int construct_passthrough_tables(struct acpi_ctxt *ctxt,
>      return nr_added;
>  }
>  
> +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))

That may want to go libacpi.h ?
> +
> +static int check_signature_collision(uint64_t sig)

bool
> +{
> +    int i;

unsigned int

> +    for ( i = 0; i < ARRAY_SIZE(dm_acpi_signature_blacklist); i++ )
> +    {
> +        if ( sig == dm_acpi_signature_blacklist[i] )
> +            return 1;

return true

> +    }
> +    return 0;
> +}
> +
> +static int check_devname_collision(const char *name)

bool
> +{
> +    int i;

unsigned int

> +    for ( i = 0; i < ARRAY_SIZE(dm_acpi_devname_blacklist); i++ )
> +    {
> +        if ( !strncmp(name, dm_acpi_devname_blacklist[i], 4) )

That 4 could be a #define
> +            return 1;
> +    }
> +    return 0;
> +}
> +
> +static const char *xs_read_dm_acpi_blob_key(struct acpi_ctxt *ctxt,
> +                                            const char *name, const char *key)
> +{
> +#define DM_ACPI_BLOB_PATH_MAX_LENGTH 30
> +    char path[DM_ACPI_BLOB_PATH_MAX_LENGTH];
> +    snprintf(path, DM_ACPI_BLOB_PATH_MAX_LENGTH, HVM_XS_DM_ACPI_ROOT"/%s/%s",
> +             name, key);
> +    return ctxt->xs_ops.read(ctxt, path);

#undef DM_APCI_BLOB... but perhaps that should go in
xen/include/public/hvm/hvm_xs_strings.h ?

> +}
> +
> +static int construct_dm_table(struct acpi_ctxt *ctxt,

bool
> +                              unsigned long *table_ptrs, int nr_tables,

unsigned int nr_tables
> +                              const void *blob, uint32_t length)
> +{
> +    const struct acpi_header *header = blob;
> +    uint8_t *buffer;
> +
> +    if ( check_signature_collision(header->signature) )
> +        return 0;
> +
> +    if ( header->length > length || header->length == 0 )
> +        return 0;
> +
> +    buffer = ctxt->mem_ops.alloc(ctxt, header->length, 16);
> +    if ( !buffer )
> +        return 0;
> +    memcpy(buffer, header, header->length);
> +
> +    /* some device models (e.g. QEMU) does not set checksum */
> +    set_checksum(buffer, offsetof(struct acpi_header, checksum),
> +                 header->length);
> +
> +    table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, buffer);
> +
> +    return 1;
> +}
> +
> +static int construct_dm_nsdev(struct acpi_ctxt *ctxt,

bool
> +                              unsigned long *table_ptrs, int nr_tables,

unsigned int
> +                              const char *dev_name,
> +                              const void *blob, uint32_t blob_length)
> +{
> +    struct acpi_header ssdt, *header;
> +    uint8_t *buffer;
> +
> +    if ( check_devname_collision(dev_name) )
> +        return 0;
> +
> +    /* built ACPI namespace device from [name, blob] */
> +    buffer = aml_build_begin(ctxt);
> +    aml_prepend_blob(buffer, blob, blob_length);
> +    aml_prepend_device(buffer, dev_name);
> +    aml_prepend_scope(buffer, "\\_SB");
> +
> +    /* build SSDT header */
> +    ssdt.signature = ACPI_2_0_SSDT_SIGNATURE;
> +    ssdt.revision = ACPI_2_0_SSDT_REVISION;
> +    fixed_strcpy(ssdt.oem_id, ACPI_OEM_ID);
> +    fixed_strcpy(ssdt.oem_table_id, ACPI_OEM_TABLE_ID);
> +    ssdt.oem_revision = ACPI_OEM_REVISION;
> +    ssdt.creator_id = ACPI_CREATOR_ID;
> +    ssdt.creator_revision = ACPI_CREATOR_REVISION;
> +
> +    /* prepend SSDT header to ACPI namespace device */
> +    aml_prepend_blob(buffer, &ssdt, sizeof(ssdt));
> +    header = (struct acpi_header *) buffer;
> +    header->length = aml_build_end();
> +
> +    /* calculate checksum of SSDT */
> +    set_checksum(header, offsetof(struct acpi_header, checksum),
> +                 header->length);
> +
> +    table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, buffer);
> +
> +    return 1;

return true.
> +}
> +
> +/*
> + * All ACPI stuffs built by the device model are placed in the guest
> + * buffer whose address and size are specified by config->dm.{addr, length},
> + * or XenStore keys HVM_XS_DM_ACPI_{ADDRESS, LENGTH}.

This should be also provided in
xen/include/public/hvm/hvm_xs_strings.h

Especially as you are in effect adding new keys and attributes to it.

> + *
> + * The data layout within the buffer is further specified by XenStore
> + * directories under HVM_XS_DM_ACPI_ROOT. Each directory specifies a

Is each directory the name of the DSDT object? In which case you
want to say a bit about the directory name and the limit (only four
characters long), don't use the ones that are built-in, etc..

But it looks like it can be anything. You extract the name from
the blob.

But we should still say what the directory names ought to be.

> + * data blob and contains following XenStore keys:
> + *
> + * - "type":
> + *   * DM_ACPI_BLOB_TYPE_TABLE
> + *     The data blob specified by this directory is an ACPI table.
> + *   * DM_ACPI_BLOB_TYPE_NSDEV
> + *     The data blob specified by this directory is an ACPI namespace device.
> + *     Its name is specified by the directory name, while the AML code of the
> + *     body of the AML device structure is in the data blob.

Could those be strings on XenStore? Strings are nice. "table" or
"nsdev"?
> + *
> + * - "length": the number of bytes in this data blob.
> + *
> + * - "offset": the offset in bytes of this data blob from the beginning of buffer
> + */
> +static int construct_dm_tables(struct acpi_ctxt *ctxt,

static unsigned int
> +                               unsigned long *table_ptrs,
> +                               int nr_tables,

unsigned int nr_tables
> +                               struct acpi_config *config)
> +{
> +    const char *s;
> +    char **dir;
> +    uint8_t type;
> +    void *blob;
> +    unsigned int num, length, offset, i;
> +    int nr_added = 0;

unsigned int
> +
> +    if ( !config->dm.addr )
> +        return 0;
> +
> +    dir = ctxt->xs_ops.directory(ctxt, HVM_XS_DM_ACPI_ROOT, &num);
> +    if ( !dir || !num )
> +        return 0;
> +
> +    if ( num > ACPI_MAX_SECONDARY_TABLES - nr_tables )
> +        return 0;
> +
> +    for ( i = 0; i < num; i++, dir++ )
> +    {

You probably want to check that *dir is not NULL. Just in case.

> +        s = xs_read_dm_acpi_blob_key(ctxt, *dir, "type");
> +        if ( !s )
> +            continue;
> +        type = (uint8_t)strtoll(s, NULL, 0);
> +
> +        s = xs_read_dm_acpi_blob_key(ctxt, *dir, "length");
> +        if ( !s )
> +            continue;
> +        length = (uint32_t)strtoll(s, NULL, 0);
> +
> +        s = xs_read_dm_acpi_blob_key(ctxt, *dir, "offset");
> +        if ( !s )
> +            continue;
> +        offset = (uint32_t)strtoll(s, NULL, 0);
> +
> +        blob = ctxt->mem_ops.p2v(ctxt, config->dm.addr + offset);
> +
> +        switch ( type )
> +        {
> +        case DM_ACPI_BLOB_TYPE_TABLE:
> +            nr_added += construct_dm_table(ctxt,
> +                                           table_ptrs, nr_tables + nr_added,
> +                                           blob, length);
> +            break;
> +        case DM_ACPI_BLOB_TYPE_NSDEV:
> +            nr_added += construct_dm_nsdev(ctxt,
> +                                           table_ptrs, nr_tables + nr_added,
> +                                           *dir, blob, length);
> +            break;
> +        default:
> +            /* skip blobs of unknown types */
> +            continue;
> +        }
> +    }
> +
> +    return nr_added;
> +}
> +
>  static int construct_secondary_tables(struct acpi_ctxt *ctxt,
>                                        unsigned long *table_ptrs,
>                                        struct acpi_config *config,
> @@ -461,6 +674,9 @@ static int construct_secondary_tables(struct acpi_ctxt *ctxt,
>      nr_tables += construct_passthrough_tables(ctxt, table_ptrs,
>                                                nr_tables, config);
>  
> +    /* Load any additional tables passed from device model (e.g. QEMU) */

Perhaps an period at the end of the sentence?

> +    nr_tables += construct_dm_tables(ctxt, table_ptrs, nr_tables, config);
> +
>      table_ptrs[nr_tables] = 0;
>      return nr_tables;
>  }
> diff --git a/tools/libacpi/libacpi.h b/tools/libacpi/libacpi.h
> index 12cafd8..684502d 100644
> --- a/tools/libacpi/libacpi.h
> +++ b/tools/libacpi/libacpi.h
> @@ -82,6 +82,11 @@ struct acpi_config {
>          uint32_t length;
>      } pt;
>  
> +    struct {
> +        uint32_t addr;
> +        uint32_t length;
> +    } dm;
> +
>      struct acpi_numa numa;
>      const struct hvm_info_table *hvminfo;
>  
> -- 
> 2.10.1
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> https://lists.xen.org/xen-devel

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  reply	other threads:[~2017-01-27 21:40 UTC|newest]

Thread overview: 77+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-10  0:32 [RFC XEN PATCH 00/16] Add vNVDIMM support to HVM domains Haozhong Zhang
2016-10-10  0:32 ` [RFC XEN PATCH 01/16] x86_64/mm: explicitly specify the location to place the frame table Haozhong Zhang
2016-12-09 21:35   ` Konrad Rzeszutek Wilk
2016-12-12  2:27     ` Haozhong Zhang
2016-12-12  8:25       ` Jan Beulich
2016-10-10  0:32 ` [RFC XEN PATCH 02/16] x86_64/mm: explicitly specify the location to place the M2P table Haozhong Zhang
2016-12-09 21:38   ` Konrad Rzeszutek Wilk
2016-12-12  2:31     ` Haozhong Zhang
2016-12-12  8:26       ` Jan Beulich
2016-12-12  8:35         ` Haozhong Zhang
2016-10-10  0:32 ` [RFC XEN PATCH 03/16] xen/x86: add a hypercall XENPF_pmem_add to report host pmem regions Haozhong Zhang
2016-10-11 19:13   ` Andrew Cooper
2016-12-09 22:02   ` Konrad Rzeszutek Wilk
2016-12-12  4:16     ` Haozhong Zhang
2016-12-12  8:30       ` Jan Beulich
2016-12-12  8:38         ` Haozhong Zhang
2016-12-12 14:44           ` Konrad Rzeszutek Wilk
2016-12-13  1:08             ` Haozhong Zhang
2016-12-22 11:58   ` Jan Beulich
2016-10-10  0:32 ` [RFC XEN PATCH 04/16] xen/x86: add XENMEM_populate_pmemmap to map host pmem pages to guest Haozhong Zhang
2016-12-09 22:22   ` Konrad Rzeszutek Wilk
2016-12-12  4:38     ` Haozhong Zhang
2016-12-22 12:19   ` Jan Beulich
2016-10-10  0:32 ` [RFC XEN PATCH 05/16] xen/x86: release pmem pages at domain destroy Haozhong Zhang
2016-12-09 22:27   ` Konrad Rzeszutek Wilk
2016-12-12  4:47     ` Haozhong Zhang
2016-12-22 12:22   ` Jan Beulich
2016-10-10  0:32 ` [RFC XEN PATCH 06/16] tools: reserve guest memory for ACPI from device model Haozhong Zhang
2017-01-27 20:44   ` Konrad Rzeszutek Wilk
2017-02-08  1:39     ` Haozhong Zhang
2017-02-08 14:31       ` Konrad Rzeszutek Wilk
2016-10-10  0:32 ` [RFC XEN PATCH 07/16] tools/libacpi: add callback acpi_ctxt.p2v to get a pointer from physical address Haozhong Zhang
2017-01-27 20:46   ` Konrad Rzeszutek Wilk
2017-02-08  1:42     ` Haozhong Zhang
2016-10-10  0:32 ` [RFC XEN PATCH 08/16] tools/libacpi: expose details of memory allocation callback Haozhong Zhang
2017-01-27 20:58   ` Konrad Rzeszutek Wilk
2017-02-08  2:12     ` Haozhong Zhang
2016-10-10  0:32 ` [RFC XEN PATCH 09/16] tools/libacpi: add callbacks to access XenStore Haozhong Zhang
2017-01-27 21:10   ` Konrad Rzeszutek Wilk
2017-02-08  2:19     ` Haozhong Zhang
2016-10-10  0:32 ` [RFC XEN PATCH 10/16] tools/libacpi: add a simple AML builder Haozhong Zhang
2017-01-27 21:19   ` Konrad Rzeszutek Wilk
2017-02-08  2:33     ` Haozhong Zhang
2016-10-10  0:32 ` [RFC XEN PATCH 11/16] tools/libacpi: load ACPI built by the device model Haozhong Zhang
2017-01-27 21:40   ` Konrad Rzeszutek Wilk [this message]
2017-02-08  5:38     ` Haozhong Zhang
2017-02-08 14:35       ` Konrad Rzeszutek Wilk
2016-10-10  0:32 ` [RFC XEN PATCH 12/16] tools/libxl: build qemu options from xl vNVDIMM configs Haozhong Zhang
2017-01-27 21:47   ` Konrad Rzeszutek Wilk
2017-02-08  5:42     ` Haozhong Zhang
2017-01-27 21:48   ` Konrad Rzeszutek Wilk
2017-02-08  5:47     ` Haozhong Zhang
2016-10-10  0:32 ` [RFC XEN PATCH 13/16] tools/libxl: add support to map host pmem device to guests Haozhong Zhang
2017-01-27 22:06   ` Konrad Rzeszutek Wilk
2017-01-27 22:09     ` Konrad Rzeszutek Wilk
2017-02-08  5:59     ` Haozhong Zhang
2017-02-08 14:37       ` Konrad Rzeszutek Wilk
2016-10-10  0:32 ` [RFC XEN PATCH 14/16] tools/libxl: add support to map files on pmem devices " Haozhong Zhang
2017-01-27 22:10   ` Konrad Rzeszutek Wilk
2017-02-08  6:03     ` Haozhong Zhang
2016-10-10  0:32 ` [RFC XEN PATCH 15/16] tools/libxl: handle return code of libxl__qmp_initializations() Haozhong Zhang
2017-01-27 22:11   ` Konrad Rzeszutek Wilk
2017-02-08  6:07     ` Haozhong Zhang
2017-02-08 10:31       ` Wei Liu
2017-02-09  2:47         ` Haozhong Zhang
2017-02-09 10:13           ` Wei Liu
2017-02-09 10:16             ` Wei Liu
2017-02-10  2:37             ` Haozhong Zhang
2017-02-10  8:11               ` Wei Liu
2017-02-10  8:23                 ` Wei Liu
2017-02-10  8:24                 ` Haozhong Zhang
2016-10-10  0:32 ` [RFC XEN PATCH 16/16] tools/libxl: initiate pmem mapping via qmp callback Haozhong Zhang
2017-01-27 22:13   ` Konrad Rzeszutek Wilk
2017-02-08  6:08     ` Haozhong Zhang
2016-10-24 16:37 ` [RFC XEN PATCH 00/16] Add vNVDIMM support to HVM domains Wei Liu
2016-10-25  6:55   ` Haozhong Zhang
2016-10-25 11:28     ` Wei Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170127214042.GF18581@localhost.localdomain \
    --to=konrad@darnok.org \
    --cc=andrew.cooper3@citrix.com \
    --cc=guangrong.xiao@linux.intel.com \
    --cc=haozhong.zhang@intel.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=jbeulich@suse.com \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).