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

[Xen-devel] [PATCH v2 22/23] libxl/acpi: Build ACPI tables for HVMlite guests



Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>
---
v2:
* Only initialize ACPI tables here but don't load them just yet
  (store them in acpi_modeuls[])
* Reorder .gitignore changes

 .gitignore                   |  12 ++-
 tools/libacpi/build.c        |   7 +-
 tools/libacpi/libacpi.h      |  15 +++-
 tools/libxl/Makefile         |  17 +++-
 tools/libxl/libxl_arch.h     |   3 +
 tools/libxl/libxl_dom.c      |   1 +
 tools/libxl/libxl_x86.c      |  29 +++++--
 tools/libxl/libxl_x86_acpi.c | 199 +++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_x86_acpi.h |  35 ++++++++
 9 files changed, 298 insertions(+), 20 deletions(-)
 create mode 100644 tools/libxl/libxl_x86_acpi.c
 create mode 100644 tools/libxl/libxl_x86_acpi.h

diff --git a/.gitignore b/.gitignore
index d6ba3dd..cf6ede9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -170,15 +170,19 @@ tools/include/xen/*
 tools/include/xen-xsm/*
 tools/include/xen-foreign/*.(c|h|size)
 tools/include/xen-foreign/checker
-tools/libxl/libxlu_cfg_y.output
+tools/libxl/_libxl.api-for-check
+tools/libxl/*.api-ok
 tools/libxl/*.pc
 tools/libxl/*.pc.in
-tools/libxl/xl
+tools/libxl/dsdt*.c
+tools/libxl/dsdt_*.asl
+tools/libxl/libxlu_cfg_y.output
+tools/libxl/mk_dsdt
+tools/libxl/ssdt_*.h
 tools/libxl/testenum
 tools/libxl/testenum.c
 tools/libxl/tmp.*
-tools/libxl/_libxl.api-for-check
-tools/libxl/*.api-ok
+tools/libxl/xl
 tools/misc/cpuperf/cpuperf-perfcntr
 tools/misc/cpuperf/cpuperf-xen
 tools/misc/xc_shadow
diff --git a/tools/libacpi/build.c b/tools/libacpi/build.c
index 2432eb9..1778b88 100644
--- a/tools/libacpi/build.c
+++ b/tools/libacpi/build.c
@@ -21,6 +21,7 @@
 #include "ssdt_tpm.h"
 #include "ssdt_pm.h"
 #include "x86.h"
+#include <xen/hvm/hvm_info_table.h>
 #include <xen/hvm/hvm_xs_strings.h>
 #include <xen/hvm/params.h>
 
@@ -491,7 +492,7 @@ static int new_vm_gid(struct acpi_ctxt *ctxt,
     return 1;
 }
 
-void acpi_build_tables(struct acpi_ctxt *ctxt, struct acpi_config *config)
+int acpi_build_tables(struct acpi_ctxt *ctxt, struct acpi_config *config)
 {
     struct acpi_info *acpi_info;
     struct acpi_20_rsdp *rsdp;
@@ -626,11 +627,11 @@ void acpi_build_tables(struct acpi_ctxt *ctxt, struct 
acpi_config *config)
     if ( !new_vm_gid(ctxt, config, acpi_info) )
         goto oom;
 
-    return;
+    return 0;
 
 oom:
     printf("unable to build ACPI tables: out of memory\n");
-
+    return -1;
 }
 
 /*
diff --git a/tools/libacpi/libacpi.h b/tools/libacpi/libacpi.h
index ce2d50b..da20278 100644
--- a/tools/libacpi/libacpi.h
+++ b/tools/libacpi/libacpi.h
@@ -48,6 +48,15 @@ struct acpi_ctxt {
         void (*free)(struct acpi_ctxt *ctxt, void *v, uint32_t size);
         unsigned long (*v2p)(struct acpi_ctxt *ctxt, void *v);
     } mem_ops;
+
+    unsigned int page_size;
+    unsigned int page_shift;
+
+    /* Memory allocator */
+    unsigned long alloc_base_paddr;
+    unsigned long alloc_base_vaddr;
+    unsigned long alloc_currp;
+    unsigned long alloc_end;
 };
 
 struct acpi_config {
@@ -80,13 +89,13 @@ struct acpi_config {
      * This must match the OperationRegion(BIOS, SystemMemory, ....)
      * definition in the DSDT
      */
-    unsigned int infop;
+    unsigned long infop;
 
     /* RSDP address */
-    unsigned int rsdp;
+    unsigned long rsdp;
 };
 
-void acpi_build_tables(struct acpi_ctxt *ctxt, struct acpi_config *config);
+int acpi_build_tables(struct acpi_ctxt *ctxt, struct acpi_config *config);
 
 #endif /* __LIBACPI_H__ */
 
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 3a2d64a..a148374 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -75,7 +75,20 @@ else
 LIBXL_OBJS-y += libxl_no_colo.o
 endif
 
-LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o libxl_x86.o libxl_psr.o
+ACPI_PATH  = $(XEN_ROOT)/tools/libacpi
+ACPI_FILES = dsdt_pvh.c
+ACPI_OBJS  = $(patsubst %.c,%.o,$(ACPI_FILES)) build.o static_tables.o
+$(ACPI_FILES): acpi
+$(ACPI_OBJS): CFLAGS += -I. -DSTDUTILS=\"$(CURDIR)/libxl_x86_acpi.h\"
+vpath build.c $(ACPI_PATH)/
+vpath static_tables.c $(ACPI_PATH)/
+LIBXL_OBJS-$(CONFIG_X86) += $(ACPI_OBJS)
+
+.PHONY: acpi
+acpi:
+       $(MAKE) -C $(ACPI_PATH) ACPI_BUILD_DIR=$(shell pwd)
+
+LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o libxl_x86.o libxl_psr.o 
libxl_x86_acpi.o
 LIBXL_OBJS-$(CONFIG_ARM) += libxl_nocpuid.o libxl_arm.o libxl_libfdt_compat.o
 
 ifeq ($(CONFIG_NetBSD),y)
@@ -166,6 +179,7 @@ $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
 $(XL_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.h # libxl_json.h needs 
it.
 
 libxl_dom.o: CFLAGS += -I$(XEN_ROOT)/tools  # include libacpi/x86.h
+libxl_x86_acpi.o: CFLAGS += -I$(XEN_ROOT)/tools
 
 SAVE_HELPER_OBJS = libxl_save_helper.o _libxl_save_msgs_helper.o
 $(SAVE_HELPER_OBJS): CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenevtchn)
@@ -308,6 +322,7 @@ clean:
        $(RM) -f testidl.c.new testidl.c *.api-ok
        $(RM) -f xenlight.pc
        $(RM) -f xlutil.pc
+       $(MAKE) -C $(ACPI_PATH) ACPI_BUILD_DIR=$(shell pwd) clean
 
 distclean: clean
        $(RM) -f xenlight.pc.in xlutil.pc.in
diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h
index 34a853c..7c6536b 100644
--- a/tools/libxl/libxl_arch.h
+++ b/tools/libxl/libxl_arch.h
@@ -62,4 +62,7 @@ int libxl__arch_domain_construct_memmap(libxl__gc *gc,
                                         uint32_t domid,
                                         struct xc_dom_image *dom);
 
+int libxl__dom_load_acpi(libxl__gc *gc,
+                        libxl_domain_build_info *info,
+                        struct xc_dom_image *dom);
 #endif
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 3a1daae..7dbf614 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -657,6 +657,7 @@ static int libxl__build_dom(libxl__gc *gc, uint32_t domid,
         LOGE(ERROR, "xc_dom_build_image failed");
         goto out;
     }
+
     if ( (ret = xc_dom_boot_image(dom)) != 0 ) {
         LOGE(ERROR, "xc_dom_boot_image failed");
         goto out;
diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c
index 7654e20..42f2139 100644
--- a/tools/libxl/libxl_x86.c
+++ b/tools/libxl/libxl_x86.c
@@ -8,15 +8,18 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
                                       xc_domain_configuration_t *xc_config)
 {
 
-    if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM &&
-        d_config->b_info.device_model_version !=
-        LIBXL_DEVICE_MODEL_VERSION_NONE) {
-        /* HVM domains with a device model. */
-        xc_config->emulation_flags = XEN_X86_EMU_ALL;
-    } else {
-        /* PV or HVM domains without a device model. */
+    if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM) {
+        if (d_config->b_info.device_model_version !=
+            LIBXL_DEVICE_MODEL_VERSION_NONE)
+            xc_config->emulation_flags = XEN_X86_EMU_ALL;
+        else if (libxl_defbool_val(d_config->b_info.u.hvm.apic))
+            /*
+             * HVM guests without device model may want
+             * to have LAPIC emulation.
+             */
+            xc_config->emulation_flags = XEN_X86_EMU_LAPIC;
+    } else 
         xc_config->emulation_flags = 0;
-    }
 
     return 0;
 }
@@ -366,7 +369,15 @@ int libxl__arch_domain_finalise_hw_description(libxl__gc 
*gc,
                                                libxl_domain_build_info *info,
                                                struct xc_dom_image *dom)
 {
-    return 0;
+    int ret = 0;
+
+    if ((info->type == LIBXL_DOMAIN_TYPE_HVM) &&
+        (info->device_model_version == LIBXL_DEVICE_MODEL_VERSION_NONE)) {
+        if ( (ret = libxl__dom_load_acpi(gc, info, dom)) != 0 )
+            LOGE(ERROR, "libxl_dom_load_acpi failed");
+    }
+
+    return ret;
 }
 
 /* Return 0 on success, ERROR_* on failure. */
diff --git a/tools/libxl/libxl_x86_acpi.c b/tools/libxl/libxl_x86_acpi.c
new file mode 100644
index 0000000..88e69e2
--- /dev/null
+++ b/tools/libxl/libxl_x86_acpi.c
@@ -0,0 +1,199 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include "libxl_internal.h"
+#include "libxl_arch.h"
+#include <xen/hvm/hvm_info_table.h>
+#include <xen/hvm/e820.h>
+#include "libacpi/libacpi.h"
+
+#include <xc_dom.h>
+
+ /* Number of pages holding ACPI tables */
+#define NUM_ACPI_PAGES 16
+/* Store RSDP in the last 64 bytes of BIOS RO memory */
+#define RSDP_ADDRESS (0x100000 - 64)
+#define ACPI_INFO_PHYSICAL_ADDRESS 0xfc000000
+
+extern const unsigned char dsdt_pvh[];
+extern const unsigned int dsdt_pvh_len;
+
+/* Assumes contiguous physical space */
+static unsigned long virt_to_phys(struct acpi_ctxt *ctxt, void *v)
+{
+    return (((unsigned long)v - ctxt->alloc_base_vaddr) +
+            ctxt->alloc_base_paddr);
+}
+
+static void *mem_alloc(struct acpi_ctxt *ctxt, uint32_t size, uint32_t align)
+{
+    unsigned long s, e;
+
+    /* Align to at least 16 bytes. */
+    if (align < 16)
+        align = 16;
+
+    s = (ctxt->alloc_currp + align) & ~((unsigned long)align - 1);
+    e = s + size - 1;
+
+    /* TODO: Reallocate memory */
+    if ((e < s) || (e >= ctxt->alloc_end)) return NULL;
+
+    while (ctxt->alloc_currp >> ctxt->page_shift != 
+           e >> ctxt->page_shift)
+        ctxt->alloc_currp += ctxt->page_size;
+
+    ctxt->alloc_currp = e;
+
+    return (void *)s;
+}
+
+static int init_acpi_config(libxl__gc *gc, 
+                            struct xc_dom_image *dom,
+                            libxl_domain_build_info *b_info,
+                            struct acpi_config *config)
+{
+    xc_interface *xch = dom->xch;
+    uint32_t domid = dom->guest_domid;
+    xc_dominfo_t info;
+    int i, rc;
+
+    config->dsdt_anycpu = config->dsdt_15cpu = dsdt_pvh;
+    config->dsdt_anycpu_len = config->dsdt_15cpu_len = dsdt_pvh_len;
+
+    rc = xc_domain_getinfo(xch, domid, 1, &info);
+    if (rc < 0) {
+        LOG(ERROR, "%s: getdomaininfo failed (rc=%d)", __FUNCTION__, rc);
+        return rc;
+    }
+
+    config->hvminfo = libxl__zalloc(gc, sizeof(*config->hvminfo));
+
+    config->hvminfo->apic_mode = libxl_defbool_val(b_info->u.hvm.apic);
+
+    if (dom->nr_vnodes) {
+        struct acpi_numa *numa = &config->numa;
+
+        rc = xc_domain_getvnuma(xch, domid, &numa->nr_vnodes,
+                                &numa->nr_vmemranges,
+                                &config->hvminfo->nr_vcpus, NULL, NULL, NULL);
+       if (rc) {
+            LOG(ERROR, "%s: xc_domain_getvnuma failed (rc=%d)",
+                __FUNCTION__, rc);
+            return rc;
+        }
+
+        numa->vmemrange = libxl__zalloc(gc, dom->nr_vmemranges *
+                                        sizeof(*numa->vmemrange));
+        numa->vdistance = libxl__zalloc(gc, dom->nr_vnodes *
+                                         sizeof(*numa->vdistance));
+        numa->vcpu_to_vnode = libxl__zalloc(gc, config->hvminfo->nr_vcpus *
+                                             sizeof(*numa->vcpu_to_vnode));
+        rc = xc_domain_getvnuma(xch, domid, &numa->nr_vnodes,
+                                &numa->nr_vmemranges,
+                                &config->hvminfo->nr_vcpus, numa->vmemrange,
+                                numa->vdistance, numa->vcpu_to_vnode);
+       if (rc) {
+            LOG(ERROR, "%s: xc_domain_getvnuma failed (rc=%d)",
+                __FUNCTION__, rc);
+            return rc;
+        }
+    }
+    else
+        config->hvminfo->nr_vcpus = info.max_vcpu_id + 1;
+
+    for (i=0; i<config->hvminfo->nr_vcpus; i++)
+        config->hvminfo->vcpu_online[i / 8] |= 1 << (i & 7);
+
+    return 0;
+}
+
+int libxl__dom_load_acpi(libxl__gc *gc,
+                         libxl_domain_build_info *info,
+                         struct xc_dom_image *dom)
+{
+    struct acpi_config config = {0};
+    struct acpi_ctxt ctxt;
+    int rc, acpi_pages_num;
+    void *acpi_pages;
+    unsigned long page_mask;
+
+    if ((info->type != LIBXL_DOMAIN_TYPE_HVM) ||
+        (info->device_model_version != LIBXL_DEVICE_MODEL_VERSION_NONE))
+        return 0;
+
+    ctxt.page_size = XC_DOM_PAGE_SIZE(dom);
+    ctxt.page_shift =  XC_DOM_PAGE_SHIFT(dom);
+    page_mask = (1UL << ctxt.page_shift) - 1;
+
+    ctxt.mem_ops.alloc = mem_alloc;
+    ctxt.mem_ops.v2p = virt_to_phys;
+
+    rc = init_acpi_config(gc, dom, info, &config);
+    if (rc) {
+        LOG(ERROR, "%s: init_acpi_config failed (rc=%d)", __FUNCTION__, rc);
+        return rc;
+    }
+
+    config.rsdp = (unsigned long)libxl__malloc(gc, ctxt.page_size);
+    config.infop = (unsigned long)libxl__malloc(gc, ctxt.page_size);
+    /* Pages to hold ACPI tables */
+    acpi_pages =  libxl__malloc(gc, (NUM_ACPI_PAGES + 1) * ctxt.page_size);
+
+    /*
+     * Set up allocator memory.
+     * Start next to acpi_info page to avoid fracturing e820.
+     */
+    ctxt.alloc_base_paddr = ACPI_INFO_PHYSICAL_ADDRESS + ctxt.page_size;
+    ctxt.alloc_base_vaddr = ctxt.alloc_currp = (unsigned long)acpi_pages;
+    ctxt.alloc_end = (unsigned long)acpi_pages +
+        (NUM_ACPI_PAGES * ctxt.page_size);
+
+    /* Build the tables. */
+    rc = acpi_build_tables(&ctxt, &config);
+    if (rc) {
+        LOG(ERROR, "%s: acpi_build_tables failed with %d",
+            __FUNCTION__, rc);
+        goto out;
+    }
+
+    /* Calculate how many pages are needed for the tables. */
+    acpi_pages_num =
+        ((ctxt.alloc_currp - (unsigned long)acpi_pages) >> ctxt.page_shift) +
+        ((ctxt.alloc_currp & page_mask) ? 1 : 0);
+
+    dom->acpi_modules[0].data = (void *)config.rsdp;
+    dom->acpi_modules[0].length = 64;
+    dom->acpi_modules[0].guest_addr_out = RSDP_ADDRESS;
+
+    dom->acpi_modules[1].data = (void *)config.infop;
+    dom->acpi_modules[1].length = 4096;
+    dom->acpi_modules[1].guest_addr_out = ACPI_INFO_PHYSICAL_ADDRESS;
+
+    dom->acpi_modules[2].data = acpi_pages;
+    dom->acpi_modules[2].length = acpi_pages_num  << ctxt.page_shift;
+    dom->acpi_modules[2].guest_addr_out = ACPI_INFO_PHYSICAL_ADDRESS + 
ctxt.page_size;
+
+out:
+
+    return rc;
+
+}
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxl/libxl_x86_acpi.h b/tools/libxl/libxl_x86_acpi.h
new file mode 100644
index 0000000..17a8bd4
--- /dev/null
+++ b/tools/libxl/libxl_x86_acpi.h
@@ -0,0 +1,35 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef LIBXL_X86_ACPI_H
+#define LIBXL_X86_ACPI_H
+
+#include "libxl_internal.h"
+
+#define ASSERT(x) assert(x)
+
+static inline int test_bit(unsigned int b, void *p)
+{
+    return !!(((uint8_t *)p)[b>>3] & (1u<<(b&7)));
+}
+
+#endif /* LIBXL_X_86_ACPI_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
1.8.3.1


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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.