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

Re: [Xen-devel] [PATCH v4 20/21] libxl/acpi: Build ACPI tables for HVMlite guests



On Mon, Sep 19, 2016 at 08:19:38PM -0400, Boris Ostrovsky wrote:
> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>

The code mostly looks good.  Some nits below.

> ---
> Changes in v4:
> * Remove allocation-specific fields from struct acpi_ctxt and use
>   an enclosing struct libxl_acpi_ctxt.
> * Use private struct hvminfo (to deal with constified struct
>   acpi_config->hvminfo)
> 
>  .gitignore                   |  12 ++-
>  tools/libacpi/build.c        |   7 +-
>  tools/libacpi/libacpi.h      |   6 +-
>  tools/libxl/Makefile         |  18 +++-
>  tools/libxl/libxl_arch.h     |   3 +
>  tools/libxl/libxl_x86.c      |  30 ++++--
>  tools/libxl/libxl_x86_acpi.c | 243 
> +++++++++++++++++++++++++++++++++++++++++++
>  tools/libxl/libxl_x86_acpi.h |  35 +++++++
>  8 files changed, 334 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 5720e0f..9b6f58e 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -173,15 +173,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 00fb67e..47dae01 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 <xen/hvm/hvm_info_table.h>
>  #include <xen/hvm/hvm_xs_strings.h>
>  #include <xen/hvm/params.h>
>  #include <xen/memory.h>
> @@ -496,7 +497,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;
> @@ -631,11 +632,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 e386362..1d388f9 100644
> --- a/tools/libacpi/libacpi.h
> +++ b/tools/libacpi/libacpi.h
> @@ -78,10 +78,10 @@ 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;
>  
>      /* x86-specific parameters */
>      uint8_t (*lapic_id)(unsigned cpu);
> @@ -91,7 +91,7 @@ struct acpi_config {
>      uint8_t ioapic_id;
>  };
>  
> -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 90427ff..336358c 100644
> --- a/tools/libxl/Makefile
> +++ b/tools/libxl/Makefile
> @@ -75,7 +75,21 @@ 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. -DLIBACPI_STDUTILS=\"$(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=$(CURDIR)
> +-include acpi

Useless include?

> +
> +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)
> @@ -167,6 +181,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)
> @@ -309,6 +324,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=$(CURDIR) 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 253a037..7a70b01 100644
> --- a/tools/libxl/libxl_arch.h
> +++ b/tools/libxl/libxl_arch.h
> @@ -66,6 +66,9 @@ int libxl__arch_domain_construct_memmap(libxl__gc *gc,
>  
>  #define LAPIC_BASE_ADDRESS  0xfee00000
>  
> +int libxl__dom_load_acpi(libxl__gc *gc,
> +                      const libxl_domain_build_info *b_info,
> +                      struct xc_dom_image *dom);

Use space instead of tab please.

>  #endif
>  
>  #endif
> diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c
> index 2b221aa..d10b04b 100644
> --- a/tools/libxl/libxl_x86.c
> +++ b/tools/libxl/libxl_x86.c
> @@ -8,15 +8,19 @@ 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;
> -    }
>  

Coding style nit: We now forbid an else branch without braces. Please
add them here.

>      return 0;
>  }
> @@ -366,7 +370,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;

Use rc please.

> +
> +    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 )

Extraneous spaces here. And lift ret= bit out of if statement.

> +            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..1b38116
> --- /dev/null
> +++ b/tools/libxl/libxl_x86_acpi.c
> @@ -0,0 +1,243 @@
> +/*
> + * 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
> +
> +struct libxl_acpi_ctxt {
> +    struct acpi_ctxt c;
> +
> +    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;
> +};
> +
> +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)
> +{
> +    struct libxl_acpi_ctxt *libxl_ctxt =
> +        CONTAINER_OF(ctxt, struct libxl_acpi_ctxt, c);
> +
> +    return (((unsigned long)v - libxl_ctxt->alloc_base_vaddr) +
> +            libxl_ctxt->alloc_base_paddr);
> +}
> +
> +static void *mem_alloc(struct acpi_ctxt *ctxt,
> +                       uint32_t size, uint32_t align)
> +{
> +    struct libxl_acpi_ctxt *libxl_ctxt =
> +        CONTAINER_OF(ctxt, struct libxl_acpi_ctxt, c);
> +    unsigned long s, e;
> +
> +    /* Align to at least 16 bytes. */
> +    if (align < 16)
> +        align = 16;
> +
> +    s = (libxl_ctxt->alloc_currp + align) & ~((unsigned long)align - 1);
> +    e = s + size - 1;
> +
> +    /* TODO: Reallocate memory */
> +    if ((e < s) || (e >= libxl_ctxt->alloc_end))
> +        return NULL;
> +
> +    while (libxl_ctxt->alloc_currp >> libxl_ctxt->page_shift != 
> +           e >> libxl_ctxt->page_shift)
> +        libxl_ctxt->alloc_currp += libxl_ctxt->page_size;
> +
> +    libxl_ctxt->alloc_currp = e;
> +
> +    return (void *)s;
> +}
> +
> +static void acpi_mem_free(struct acpi_ctxt *ctxt,
> +                          void *v, uint32_t size)
> +{
> +}
> +
> +static uint8_t acpi_lapic_id(unsigned cpu)
> +{
> +    return cpu * 2;

Is this in accordance with hardware spec?

> +}
> +
> +static int init_acpi_config(libxl__gc *gc, 
> +                            struct xc_dom_image *dom,
> +                            const libxl_domain_build_info *b_info,
> +                            struct acpi_config *config)
> +{

Use goto style error handling in this function please.

> +    xc_interface *xch = dom->xch;
> +    uint32_t domid = dom->guest_domid;
> +    xc_dominfo_t info;
> +    struct hvm_info_table *hvminfo;
> +    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);

No need to have __FUNCTION__ -- LOG already prints that.

> +        return rc;
> +    }
> +
> +    hvminfo = libxl__zalloc(gc, sizeof(*hvminfo));
> +
> +    hvminfo->apic_mode = libxl_defbool_val(b_info->u.hvm.apic);
> +
> +    if (dom->nr_vnodes) {
> +        unsigned int *vcpu_to_vnode, *vdistance;
> +        struct xen_vmemrange *vmemrange;
> +        struct acpi_numa *numa = &config->numa;
> +
> +        rc = xc_domain_getvnuma(xch, domid, &numa->nr_vnodes,
> +                                &numa->nr_vmemranges,
> +                                &hvminfo->nr_vcpus, NULL, NULL, NULL);
> +        if (rc) {
> +            LOG(ERROR, "%s: xc_domain_getvnuma failed (rc=%d)",
> +                __FUNCTION__, rc);
> +            return rc;
> +        }
> +
> +        vmemrange = libxl__zalloc(gc, dom->nr_vmemranges * 
> sizeof(*vmemrange));
> +        vdistance = libxl__zalloc(gc, dom->nr_vnodes * sizeof(*vdistance));
> +        vcpu_to_vnode = libxl__zalloc(gc, hvminfo->nr_vcpus *
> +                                      sizeof(*vcpu_to_vnode));
> +        rc = xc_domain_getvnuma(xch, domid, &numa->nr_vnodes,
> +                                &numa->nr_vmemranges, &hvminfo->nr_vcpus,
> +                                vmemrange, vdistance, vcpu_to_vnode);
> +     if (rc) {
> +            LOG(ERROR, "%s: xc_domain_getvnuma failed (rc=%d)",
> +                __FUNCTION__, rc);
> +            return rc;
> +        }
> +        numa->vmemrange = vmemrange;
> +        numa->vdistance = vdistance;
> +        numa->vcpu_to_vnode = vcpu_to_vnode;
> +    }
> +    else
> +        hvminfo->nr_vcpus = info.max_vcpu_id + 1;

"else" should be right after "}" and please add braces.

> +
> +    for (i = 0; i < hvminfo->nr_vcpus; i++)
> +        hvminfo->vcpu_online[i / 8] |= 1 << (i & 7);
> +
> +    config->hvminfo = hvminfo;
> +
> +    config->lapic_base_address = LAPIC_BASE_ADDRESS;
> +    config->lapic_id = acpi_lapic_id;
> +
> +    return 0;
> +}
> +
> +int libxl__dom_load_acpi(libxl__gc *gc,
> +                         const libxl_domain_build_info *b_info,
> +                         struct xc_dom_image *dom)
> +{
> +    struct acpi_config config = {0};
> +    struct libxl_acpi_ctxt libxl_ctxt;
> +    int rc, acpi_pages_num;
> +    void *acpi_pages;
> +    unsigned long page_mask;
> +
> +    if ((b_info->type != LIBXL_DOMAIN_TYPE_HVM) ||
> +        (b_info->device_model_version != LIBXL_DEVICE_MODEL_VERSION_NONE))
> +        return 0;

Please don't use mixed-style error handling.

> +
> +    libxl_ctxt.page_size = XC_DOM_PAGE_SIZE(dom);
> +    libxl_ctxt.page_shift =  XC_DOM_PAGE_SHIFT(dom);
> +    page_mask = (1UL << libxl_ctxt.page_shift) - 1;
> +
> +    libxl_ctxt.c.mem_ops.alloc = mem_alloc;
> +    libxl_ctxt.c.mem_ops.v2p = virt_to_phys;
> +    libxl_ctxt.c.mem_ops.free = acpi_mem_free;
> +
> +    rc = init_acpi_config(gc, dom, b_info, &config);
> +    if (rc) {
> +        LOG(ERROR, "%s: init_acpi_config failed (rc=%d)", __FUNCTION__, rc);
> +        return rc;
> +    }
> +
> +    config.rsdp = (unsigned long)libxl__malloc(gc, libxl_ctxt.page_size);
> +    config.infop = (unsigned long)libxl__malloc(gc, libxl_ctxt.page_size);
> +    /* Pages to hold ACPI tables */
> +    acpi_pages =  libxl__malloc(gc, (NUM_ACPI_PAGES + 1) *
> +                                libxl_ctxt.page_size);
> +
> +    /*
> +     * Set up allocator memory.
> +     * Start next to acpi_info page to avoid fracturing e820.
> +     */
> +    libxl_ctxt.alloc_base_paddr = ACPI_INFO_PHYSICAL_ADDRESS +
> +        libxl_ctxt.page_size;
> +    libxl_ctxt.alloc_base_vaddr = libxl_ctxt.alloc_currp =
> +        (unsigned long)acpi_pages;
> +    libxl_ctxt.alloc_end = (unsigned long)acpi_pages +
> +        (NUM_ACPI_PAGES * libxl_ctxt.page_size);
> +
> +    /* Build the tables. */
> +    rc = acpi_build_tables(&libxl_ctxt.c, &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 =
> +        ((libxl_ctxt.alloc_currp - (unsigned long)acpi_pages)
> +         >> libxl_ctxt.page_shift) +
> +        ((libxl_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  << libxl_ctxt.page_shift;
> +    dom->acpi_modules[2].guest_addr_out = ACPI_INFO_PHYSICAL_ADDRESS +
> +        libxl_ctxt.page_size;
> +
> +out:
> +
> +    return rc;
> +

Extraneous line.

> +}
> +/*
> + * 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..3622dd0
> --- /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, const 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®.