xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Haozhong Zhang <haozhong.zhang@intel.com>
To: xen-devel@lists.xen.org
Cc: Haozhong Zhang <haozhong.zhang@intel.com>,
	Xiao Guangrong <guangrong.xiao@linux.intel.com>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	Ian Jackson <ian.jackson@eu.citrix.com>,
	Jan Beulich <jbeulich@suse.com>, Wei Liu <wei.liu2@citrix.com>
Subject: [RFC XEN PATCH 10/16] tools/libacpi: add a simple AML builder
Date: Mon, 10 Oct 2016 08:32:29 +0800	[thread overview]
Message-ID: <20161010003235.4213-11-haozhong.zhang@intel.com> (raw)
In-Reply-To: <20161010003235.4213-1-haozhong.zhang@intel.com>

It is used by libacpi to generate SSDTs from ACPI namespace devices
built by the device model.

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/Makefile |   3 +-
 tools/libacpi/aml_build.c         | 254 ++++++++++++++++++++++++++++++++++++++
 tools/libacpi/aml_build.h         |  83 +++++++++++++
 tools/libxl/Makefile              |   3 +-
 4 files changed, 341 insertions(+), 2 deletions(-)
 create mode 100644 tools/libacpi/aml_build.c
 create mode 100644 tools/libacpi/aml_build.h

diff --git a/tools/firmware/hvmloader/Makefile b/tools/firmware/hvmloader/Makefile
index 77d7551..cf0dac3 100644
--- a/tools/firmware/hvmloader/Makefile
+++ b/tools/firmware/hvmloader/Makefile
@@ -79,11 +79,12 @@ smbios.o: CFLAGS += -D__SMBIOS_DATE__="\"$(SMBIOS_REL_DATE)\""
 
 ACPI_PATH = ../../libacpi
 ACPI_FILES = dsdt_anycpu.c dsdt_15cpu.c dsdt_anycpu_qemu_xen.c
-ACPI_OBJS = $(patsubst %.c,%.o,$(ACPI_FILES)) build.o static_tables.o
+ACPI_OBJS = $(patsubst %.c,%.o,$(ACPI_FILES)) build.o static_tables.o aml_build.o
 $(ACPI_OBJS): CFLAGS += -I. -DLIBACPI_STDUTILS=\"$(CURDIR)/util.h\"
 CFLAGS += -I$(ACPI_PATH)
 vpath build.c $(ACPI_PATH)
 vpath static_tables.c $(ACPI_PATH)
+vpath aml_build.c $(ACPI_PATH)
 OBJS += $(ACPI_OBJS)
 
 hvmloader: $(OBJS)
diff --git a/tools/libacpi/aml_build.c b/tools/libacpi/aml_build.c
new file mode 100644
index 0000000..b6f23f4
--- /dev/null
+++ b/tools/libacpi/aml_build.c
@@ -0,0 +1,254 @@
+/*
+ * tools/libacpi/aml_build.c
+ *
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * 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/>.
+ *
+ * Author: Haozhong Zhang <haozhong.zhang@intel.com>
+ */
+
+#include LIBACPI_STDUTILS
+#include "libacpi.h"
+#include "aml_build.h"
+
+#define AML_OP_SCOPE     0x10
+#define AML_OP_EXT       0x5B
+#define AML_OP_DEVICE    0x82
+
+#define ACPI_NAMESEG_LEN 4
+
+struct aml_build_alloctor {
+    struct acpi_ctxt *ctxt;
+    uint8_t *buf;
+    uint32_t capacity;
+    uint32_t used;
+};
+static struct aml_build_alloctor alloc;
+
+enum { ALLOC_OVERFLOW, ALLOC_NOT_NEEDED, ALLOC_NEEDED };
+
+static int alloc_needed(uint32_t size)
+{
+    uint32_t len = alloc.used + size;
+
+    if ( len < alloc.used )
+        return ALLOC_OVERFLOW;
+    else if ( len <= alloc.capacity )
+        return ALLOC_NOT_NEEDED;
+    else
+        return ALLOC_NEEDED;
+}
+
+static uint8_t *aml_buf_alloc(uint32_t size)
+{
+    int needed = alloc_needed(size);
+    uint8_t *buf = NULL;
+    struct acpi_ctxt *ctxt = alloc.ctxt;
+    uint32_t alloc_size, alloc_align = ctxt->min_alloc_align;
+
+    switch ( needed )
+    {
+    case ALLOC_OVERFLOW:
+        break;
+
+    case ALLOC_NEEDED:
+        alloc_size = (size + alloc_align) & ~(alloc_align - 1);
+        buf = ctxt->mem_ops.alloc(ctxt, alloc_size, alloc_align);
+        if ( !buf )
+            break;
+        if ( alloc.buf + alloc.capacity != buf )
+        {
+            buf = NULL;
+            break;
+        }
+        alloc.capacity += alloc_size;
+        alloc.used += size;
+        break;
+
+    case ALLOC_NOT_NEEDED:
+        buf = alloc.buf + alloc.used;
+        alloc.used += size;
+        break;
+
+    default:
+        break;
+    }
+
+    return buf;
+}
+
+static uint32_t get_package_length(uint8_t *pkg)
+{
+    uint32_t len;
+
+    len = pkg - alloc.buf;
+    len = alloc.used - len;
+
+    return len;
+}
+
+static void build_prepend_byte(uint8_t *buf, uint8_t byte)
+{
+    uint32_t len;
+
+    len = buf - alloc.buf;
+    len = alloc.used - len;
+
+    aml_buf_alloc(sizeof(uint8_t));
+    if ( len )
+        memmove(buf + 1, buf, len);
+    buf[0] = byte;
+}
+
+/*
+ * XXX: names of multiple segments (e.g. X.Y.Z) are not supported
+ */
+static void build_prepend_name(uint8_t *buf, const char *name)
+{
+    uint8_t *p = buf;
+    const char *s = name;
+    uint32_t len, name_len;
+
+    while ( *s == '\\' || *s == '^' )
+    {
+        build_prepend_byte(p, (uint8_t) *s);
+        ++p;
+        ++s;
+    }
+
+    if ( !*s )
+    {
+        build_prepend_byte(p, 0x00);
+        return;
+    }
+
+    len = p - alloc.buf;
+    len = alloc.used - len;
+    name_len = strlen(s);
+    ASSERT(strlen(s) <= ACPI_NAMESEG_LEN);
+
+    aml_buf_alloc(ACPI_NAMESEG_LEN);
+    if ( len )
+        memmove(p + ACPI_NAMESEG_LEN, p, len);
+    memcpy(p, s, name_len);
+    memcpy(p + name_len, "____", ACPI_NAMESEG_LEN - name_len);
+}
+
+enum {
+    PACKAGE_LENGTH_1BYTE_SHIFT = 6, /* Up to 63 - use extra 2 bits. */
+    PACKAGE_LENGTH_2BYTE_SHIFT = 4,
+    PACKAGE_LENGTH_3BYTE_SHIFT = 12,
+    PACKAGE_LENGTH_4BYTE_SHIFT = 20,
+};
+
+static void build_prepend_package_length(uint8_t *pkg, uint32_t length)
+{
+    uint8_t byte;
+    unsigned length_bytes;
+
+    if ( length + 1 < (1 << PACKAGE_LENGTH_1BYTE_SHIFT) )
+        length_bytes = 1;
+    else if ( length + 2 < (1 << PACKAGE_LENGTH_3BYTE_SHIFT) )
+        length_bytes = 2;
+    else if ( length + 3 < (1 << PACKAGE_LENGTH_4BYTE_SHIFT) )
+        length_bytes = 3;
+    else
+        length_bytes = 4;
+
+    length += length_bytes;
+
+    switch ( length_bytes )
+    {
+    case 1:
+        byte = length;
+        build_prepend_byte(pkg, byte);
+        return;
+    case 4:
+        byte = length >> PACKAGE_LENGTH_4BYTE_SHIFT;
+        build_prepend_byte(pkg, byte);
+        length &= (1 << PACKAGE_LENGTH_4BYTE_SHIFT) - 1;
+        /* fall through */
+    case 3:
+        byte = length >> PACKAGE_LENGTH_3BYTE_SHIFT;
+        build_prepend_byte(pkg, byte);
+        length &= (1 << PACKAGE_LENGTH_3BYTE_SHIFT) - 1;
+        /* fall through */
+    case 2:
+        byte = length >> PACKAGE_LENGTH_2BYTE_SHIFT;
+        build_prepend_byte(pkg, byte);
+        length &= (1 << PACKAGE_LENGTH_2BYTE_SHIFT) - 1;
+        /* fall through */
+    }
+    /*
+     * Most significant two bits of byte zero indicate how many following bytes
+     * are in PkgLength encoding.
+     */
+    byte = ((length_bytes - 1) << PACKAGE_LENGTH_1BYTE_SHIFT) | length;
+    build_prepend_byte(pkg, byte);
+}
+
+static void build_prepend_package(uint8_t *buf, uint8_t op)
+{
+    uint32_t length = get_package_length(buf);
+    build_prepend_package_length(buf, length);
+    build_prepend_byte(buf, op);
+}
+
+static void build_prepend_ext_packge(uint8_t *buf, uint8_t op)
+{
+    build_prepend_package(buf, op);
+    build_prepend_byte(buf, AML_OP_EXT);
+}
+
+void *aml_build_begin(struct acpi_ctxt *ctxt)
+{
+    alloc.ctxt = ctxt;
+    alloc.buf = ctxt->mem_ops.alloc(ctxt,
+                                    ctxt->min_alloc_unit, ctxt->min_alloc_align);
+    alloc.capacity = ctxt->min_alloc_unit;
+    alloc.used = 0;
+    return alloc.buf;
+}
+
+uint32_t aml_build_end(void)
+{
+    return alloc.used;
+}
+
+void aml_prepend_blob(uint8_t *buf, const void *blob, uint32_t blob_length)
+{
+    uint32_t len;
+
+    len = buf - alloc.buf;
+    len = alloc.used - len;
+
+    aml_buf_alloc(blob_length);
+    if ( len )
+        memmove(buf + blob_length, buf, len);
+
+    memcpy(buf, blob, blob_length);
+}
+
+void aml_prepend_device(uint8_t *buf, const char *name)
+{
+    build_prepend_name(buf, name);
+    build_prepend_ext_packge(buf, AML_OP_DEVICE);
+}
+
+void aml_prepend_scope(uint8_t *buf, const char *name)
+{
+    build_prepend_name(buf, name);
+    build_prepend_package(buf, AML_OP_SCOPE);
+}
diff --git a/tools/libacpi/aml_build.h b/tools/libacpi/aml_build.h
new file mode 100644
index 0000000..ed68f66
--- /dev/null
+++ b/tools/libacpi/aml_build.h
@@ -0,0 +1,83 @@
+/*
+ * tools/libacpi/aml_build.h
+ *
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * 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/>.
+ *
+ * Author: Haozhong Zhang <haozhong.zhang@intel.com>
+ */
+
+#ifndef _AML_BUILD_H_
+#define _AML_BUILD_H_
+
+#include <stdint.h>
+#include "libacpi.h"
+
+/*
+ * NB: All aml_prepend_* calls, which build AML code in one ACPI
+ *     table, should be placed between a pair of calls to
+ *     aml_build_begin() and aml_build_end().
+ */
+
+/**
+ * Reset the AML builder and begin a new round of building.
+ *
+ * Parameters:
+ *   @ctxt: ACPI context used by the AML builder
+ *
+ * Returns:
+ *   a pointer to the builder buffer where the AML code will be stored
+ */
+void *aml_build_begin(struct acpi_ctxt *ctxt);
+
+/**
+ * Mark the end of a round of AML building.
+ *
+ * Returns:
+ *  the number of bytes in the builder buffer built in this round
+ */
+uint32_t aml_build_end(void);
+
+/**
+ * Prepend a blob, which can contain arbitrary content, to the builder buffer.
+ *
+ * Parameters:
+ *   @buf:    pointer to the builder buffer
+ *   @blob:   pointer to the blob
+ *   @length: the number of bytes in the blob
+ */
+void aml_prepend_blob(uint8_t *buf, const void *blob, uint32_t length);
+
+/**
+ * Prepend an AML device structure to the builder buffer. The existing
+ * data in the builder buffer is included in the AML device.
+ *
+ * Parameters:
+ *   @buf:  pointer to the builder buffer
+ *   @name: the name of the device
+ */
+void aml_prepend_device(uint8_t *buf, const char *name);
+
+/**
+ * Prepend an AML scope structure to the builder buffer. The existing
+ * data in the builder buffer is included in the AML scope.
+ *
+ * Parameters:
+ *   @buf:  pointer to the builder buffer
+ *   @name: the name of the scope
+ */
+void aml_prepend_scope(uint8_t *buf, const char *name);
+
+#endif /* _AML_BUILD_H_ */
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index c4e4117..a904927 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -77,11 +77,12 @@ endif
 
 ACPI_PATH  = $(XEN_ROOT)/tools/libacpi
 ACPI_FILES = dsdt_pvh.c
-ACPI_OBJS  = $(patsubst %.c,%.o,$(ACPI_FILES)) build.o static_tables.o
+ACPI_OBJS  = $(patsubst %.c,%.o,$(ACPI_FILES)) build.o static_tables.o aml_build.o
 $(ACPI_FILES): acpi
 $(ACPI_OBJS): CFLAGS += -I. -DLIBACPI_STDUTILS=\"$(CURDIR)/libxl_x86_acpi.h\"
 vpath build.c $(ACPI_PATH)/
 vpath static_tables.c $(ACPI_PATH)/
+vpath aml_build.c $(ACPI_PATH)/
 LIBXL_OBJS-$(CONFIG_X86) += $(ACPI_OBJS)
 
 .PHONY: acpi
-- 
2.10.1


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

  parent reply	other threads:[~2016-10-10  0:32 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 ` Haozhong Zhang [this message]
2017-01-27 21:19   ` [RFC XEN PATCH 10/16] tools/libacpi: add a simple AML builder 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
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=20161010003235.4213-11-haozhong.zhang@intel.com \
    --to=haozhong.zhang@intel.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=guangrong.xiao@linux.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).