[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC 18/20] libxc/acpi: Build ACPI tables for HVMlite guests
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx> --- tools/libxc/Makefile | 22 +++- tools/libxc/include/xc_dom.h | 1 + tools/libxc/xc_acpi.c | 268 ++++++++++++++++++++++++++++++++++++++ tools/libxc/xc_dom_x86.c | 7 + tools/libxl/libxl_x86.c | 19 +-- xen/common/libacpi/Makefile | 5 +- xen/common/libacpi/acpi2_0.h | 2 +- xen/common/libacpi/build.c | 2 +- xen/common/libacpi/dsdt_empty.asl | 22 ++++ 9 files changed, 335 insertions(+), 13 deletions(-) create mode 100644 tools/libxc/xc_acpi.c create mode 100644 xen/common/libacpi/dsdt_empty.asl diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index 608404f..9569e54 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -79,6 +79,26 @@ GUEST_SRCS-y += $(ELF_SRCS-y) $(patsubst %.c,%.o,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign $(patsubst %.c,%.opic,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign +ACPI_PATH = $(XEN_ROOT)/xen/common/libacpi +vpath %.c $(ACPI_PATH) +ACPI_FILES = dsdt_anycpu.c dsdt_15cpu.c static_tables.c +ACPI_FILES += dsdt_anycpu_qemu_xen.c dsdt_empty.c build.c +ACPI_SRCS = $(patsubst %.c,$(ACPI_PATH)/%.c,$(ACPI_FILES)) + +.NOTPARALLEL: $(ACPI_SRCS) +$(ACPI_SRCS): + make -C $(ACPI_PATH) + +$(patsubst %.c,%.o,$(ACPI_SRCS)): CFLAGS += -I$(ACPI_PATH) +$(patsubst %.c,%.opic,$(ACPI_SRCS)): CFLAGS += -I$(ACPI_PATH) +xc_acpi.o: CFLAGS += -I$(ACPI_PATH) +xc_acpi.opic: CFLAGS += -I$(ACPI_PATH) + +GUEST_SRCS-y += $(ACPI_FILES) + +$(patsubst %.c,%.o,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign +$(patsubst %.c,%.opic,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign + # new domain builder GUEST_SRCS-y += xc_dom_core.c xc_dom_boot.c GUEST_SRCS-y += xc_dom_elfloader.c @@ -89,7 +109,7 @@ GUEST_SRCS-$(CONFIG_ARM) += xc_dom_armzimageloader.c GUEST_SRCS-y += xc_dom_binloader.c GUEST_SRCS-y += xc_dom_compat_linux.c -GUEST_SRCS-$(CONFIG_X86) += xc_dom_x86.c +GUEST_SRCS-$(CONFIG_X86) += xc_dom_x86.c xc_acpi.c GUEST_SRCS-$(CONFIG_X86) += xc_cpuid_x86.c GUEST_SRCS-$(CONFIG_ARM) += xc_dom_arm.c diff --git a/tools/libxc/include/xc_dom.h b/tools/libxc/include/xc_dom.h index 6ebe946..3842fb1 100644 --- a/tools/libxc/include/xc_dom.h +++ b/tools/libxc/include/xc_dom.h @@ -407,6 +407,7 @@ void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t first, xen_pfn_t count, xen_pfn_t *count_out); void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn); void xc_dom_unmap_all(struct xc_dom_image *dom); +int xc_dom_build_acpi(struct xc_dom_image *dom); static inline void *xc_dom_seg_to_ptr_pages(struct xc_dom_image *dom, struct xc_dom_seg *seg, diff --git a/tools/libxc/xc_acpi.c b/tools/libxc/xc_acpi.c new file mode 100644 index 0000000..3173d49 --- /dev/null +++ b/tools/libxc/xc_acpi.c @@ -0,0 +1,268 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include <assert.h> + +#include <xen/xen.h> +#include <xen/foreign/x86_32.h> +#include <xen/foreign/x86_64.h> +#include <xen/hvm/hvm_info_table.h> +#include <xen/io/protocols.h> + +#include "xg_private.h" +#include "xc_dom.h" +#include "xenctrl.h" + +#include "acpi2_0.h" + +#define RESERVED_MEMORY_DYNAMIC_START 0xFC001000 +#define ACPI_PHYSICAL_ADDRESS 0x000EA020 + +/* Initial allocation for ACPI tables */ +#define NUM_ACPI_PAGES 16 + +#define PFN(paddr) ((paddr) >> PAGE_SHIFT) + +extern unsigned char dsdt_anycpu[], dsdt_15cpu[], dsdt_empty[]; +extern int dsdt_anycpu_len, dsdt_15cpu_len, dsdt_empty_len; + +static uint64_t alloc_up, alloc_down; +static unsigned long base_addr; + +/* Assumes contiguous physical space */ +static unsigned long virt_to_phys(void *v) +{ + return (((unsigned long)v - base_addr) + RESERVED_MEMORY_DYNAMIC_START); +} + +static void *mem_alloc(uint32_t size, uint32_t align) +{ + uint64_t s, e; + + /* Align to at least 16 bytes. */ + if ( align < 16 ) + align = 16; + + s = (alloc_up + align) & ~((uint64_t)align - 1); + e = s + size - 1; + + /* TODO: Reallocate memory */ + if ((e < s) || (e >= alloc_down)) return NULL; + + while ( PFN(alloc_up) != PFN(e) ) + { + alloc_up += PAGE_SIZE; + } + + alloc_up = e; + + return (void *)(unsigned long)s; +} + +static int init_acpi_config(struct xc_dom_image *dom, + struct acpi_config *config) +{ + xc_interface *xch = dom->xch; + uint32_t domid = dom->guest_domid; + xc_dominfo_t info; + int i, rc; + + memset(config, 0, sizeof(*config)); + + config->dsdt_anycpu = config->dsdt_15cpu = dsdt_empty; + config->dsdt_anycpu_len = config->dsdt_15cpu_len = dsdt_empty_len; + + rc = xc_domain_getinfo(xch, domid, 1, &info); + if ( rc < 0 ) + { + DOMPRINTF("%s: getdomaininfo failed (rc=%d)", __FUNCTION__, rc); + return rc; + } + + config->apic_mode = 1; + + if ( dom->nr_vnodes ) + { + struct acpi_numa *numa = &config->numa; + + numa->vmemrange = calloc(dom->nr_vmemranges, + sizeof(*numa->vmemrange)); + numa->vdistance = calloc(dom->nr_vnodes, + sizeof(*numa->vdistance)); + numa->vcpu_to_vnode = calloc(config->nr_vcpus, + sizeof(*numa->vcpu_to_vnode)); + if ( !numa->vmemrange || !numa->vdistance || !numa->vcpu_to_vnode ) + { + DOMPRINTF("%s: Out of memory", __FUNCTION__); + free(numa->vmemrange); + free(numa->vdistance); + free(numa->vcpu_to_vnode); + return -ENOMEM; + } + + rc = xc_domain_getvnuma(xch, domid, &numa->nr_vnodes, + &numa->nr_vmemranges, + &config->nr_vcpus, numa->vmemrange, + numa->vdistance, numa->vcpu_to_vnode); + + if ( rc ) + { + DOMPRINTF("%s: xc_domain_getvnuma failed (rc=%d)", __FUNCTION__, rc); + return rc; + } + } + else + config->nr_vcpus = info.max_vcpu_id + 1; + + config->vcpu_online = calloc((HVM_MAX_VCPUS + 7) / 8, + sizeof(*config->vcpu_online)); + if ( config->vcpu_online == NULL ) + { + DOMPRINTF("%s: Can't allocate vcpu_online", __FUNCTION__); + return -ENOMEM; + } + + for (i=0; i<config->nr_vcpus; i++) + config->vcpu_online[i / 8] |= 1 << (i & 7); + + config->mem_ops.alloc = mem_alloc; + config->mem_ops.v2p = virt_to_phys; + + return 0; +} + +int xc_dom_build_acpi(struct xc_dom_image *dom) +{ + struct acpi_config config; + uint32_t domid = dom->guest_domid; + xc_interface *xch = dom->xch; + int rc, i, acpi_pages_num; + xen_pfn_t extent, *extents; + void *acpi_pages, *acpi_physical; + void *guest_info_page, *guest_acpi_pages; + + rc = init_acpi_config(dom, &config); + if ( rc ) + { + DOMPRINTF("%s: init_acpi_config failed (rc=%d)", __FUNCTION__, rc); + return rc; + } + + /* + * Pages to hold ACPI tables and one page for acpi_info, which + * will be the first one in this region. + */ + acpi_pages = xc_memalign(xch, PAGE_SIZE, NUM_ACPI_PAGES * PAGE_SIZE); + if ( !acpi_pages ) + { + DOMPRINTF("%s: Can't allocate acpi pages", __FUNCTION__); + rc = -1; + goto out; + } + + config.acpi_info_page = acpi_pages; + + /* Set up allocator memory */ + base_addr = alloc_up = (unsigned long)acpi_pages + PAGE_SIZE; + alloc_down = (unsigned long)acpi_pages + (NUM_ACPI_PAGES * PAGE_SIZE); + + /* Map page that will hold RSDP */ + extent = PFN(ACPI_PHYSICAL_ADDRESS); + rc = xc_domain_populate_physmap_exact(xch, domid, 1, 0, 0, &extent); + if ( rc ) + { + DOMPRINTF("%s: xc_domain_populate_physmap failed with %d", + __FUNCTION__, rc); + goto out; + } + acpi_physical = xc_map_foreign_range(xch, domid, PAGE_SIZE, + PROT_READ | PROT_WRITE, + PFN(ACPI_PHYSICAL_ADDRESS)); + if ( !acpi_physical ) + { + DOMPRINTF("%s: Can't map acpi_physical", __FUNCTION__); + rc = -1; + goto out; + } + + /* Build the tables */ + acpi_build_tables(&config, (unsigned long)acpi_physical); + + /* Copy acpi_info page into guest's memory */ + extent = PFN(ACPI_INFO_PHYSICAL_ADDRESS); + rc = xc_domain_populate_physmap_exact(xch, domid, 1, 0, 0, &extent); + if ( rc ) + { + DOMPRINTF("%s: xc_domain_populate_physmap failed with %d\n", + __FUNCTION__, rc); + goto out; + } + guest_info_page = xc_map_foreign_range(xch, domid, PAGE_SIZE, + PROT_READ | PROT_WRITE, + PFN(ACPI_INFO_PHYSICAL_ADDRESS)); + if ( !guest_info_page ) + { + DOMPRINTF("%s: Can't map acpi_info_page", __FUNCTION__); + rc = -1; + goto out; + } + memcpy(guest_info_page, acpi_pages, PAGE_SIZE); + + /* Copy ACPI tables into guest's memory */ + acpi_pages_num = ((alloc_up - (unsigned long)acpi_pages + + (PAGE_SIZE - 1)) >> PAGE_SHIFT) - 1; + extents = malloc(acpi_pages_num * sizeof(*extents)); + if ( !extents ) + { + DOMPRINTF("%s: Can't allocate extents array", __FUNCTION__); + rc = -ENOMEM; + goto out; + } + for (i = 0; i < acpi_pages_num; i++) + extents[i] = PFN(RESERVED_MEMORY_DYNAMIC_START) + i; + rc = xc_domain_populate_physmap_exact(xch, domid, acpi_pages_num, + 0, 0, extents); + if ( rc ) + { + DOMPRINTF("%s: xc_domain_populate_physmap failed with %d", + __FUNCTION__, rc); + goto out; + } + guest_acpi_pages = xc_map_foreign_range(xch, domid, + PAGE_SIZE * acpi_pages_num, + PROT_READ | PROT_WRITE, + PFN(RESERVED_MEMORY_DYNAMIC_START)); + if ( !guest_acpi_pages ) + { + DOMPRINTF("%s Can't map guest_acpi_pages", __FUNCTION__); + rc = -1; + goto out; + } + + memcpy(guest_acpi_pages, acpi_pages + PAGE_SIZE, + acpi_pages_num * PAGE_SIZE); + +out: + munmap(guest_acpi_pages, acpi_pages_num * PAGE_SIZE); + munmap(guest_info_page, PAGE_SIZE); + munmap(acpi_physical, PAGE_SIZE); + free(extents); + free(acpi_pages); + free(config.vcpu_online); + free(config.numa.vmemrange); + free(config.numa.vdistance); + free(config.numa.vcpu_to_vnode); + + return rc; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c index bdec40a..8698b36 100644 --- a/tools/libxc/xc_dom_x86.c +++ b/tools/libxc/xc_dom_x86.c @@ -643,6 +643,13 @@ static int alloc_magic_pages_hvm(struct xc_dom_image *dom) DOMPRINTF("Unable to reserve memory for the start info"); goto out; } + + rc = xc_dom_build_acpi(dom); + if ( rc != 0 ) + { + DOMPRINTF("Unable to build ACPI tables"); + goto out; + } } else { diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c index 46cfafb..ef6c239 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 + /* + * HVM guests without device model will want + * to have LAPIC emulation. + */ + xc_config->emulation_flags = XEN_X86_EMU_LAPIC; + } else xc_config->emulation_flags = 0; - } return 0; } diff --git a/xen/common/libacpi/Makefile b/xen/common/libacpi/Makefile index efef589..a1f233f 100644 --- a/xen/common/libacpi/Makefile +++ b/xen/common/libacpi/Makefile @@ -17,7 +17,8 @@ XEN_ROOT = $(CURDIR)/../../.. include $(XEN_ROOT)/Config.mk -C_SRC = build.c dsdt_anycpu.c dsdt_15cpu.c static_tables.c dsdt_anycpu_qemu_xen.c +C_SRC = build.c dsdt_anycpu.c dsdt_15cpu.c static_tables.c +C_SRC += dsdt_anycpu_qemu_xen.c dsdt_empty.c OBJS = $(patsubst %.c,%.o,$(C_SRC)) CFLAGS_xeninclude = -I$(XEN_ROOT)/tools/include @@ -58,7 +59,7 @@ iasl: clean: rm -rf *.o $(IASL_VER) $(IASL_VER).tar.gz $(DEPS) - rm -rf ssdt_*.h dsdt*.c *~ *.aml *.hex mk_dsdt dsdt_*.asl + rm -rf ssdt_*.h dsdt*.c *~ *.aml *.hex mk_dsdt dsdt_*cpu*.asl distclean: clean diff --git a/xen/common/libacpi/acpi2_0.h b/xen/common/libacpi/acpi2_0.h index 0525a1e..458fb49 100644 --- a/xen/common/libacpi/acpi2_0.h +++ b/xen/common/libacpi/acpi2_0.h @@ -516,7 +516,7 @@ struct acpi_config { struct acpi_mem_ops mem_ops; }; -void acpi_build_tables(struct acpi_config *config, unsigned int physical); +void acpi_build_tables(struct acpi_config *config, unsigned long physical); #endif /* _ACPI_2_0_H_ */ diff --git a/xen/common/libacpi/build.c b/xen/common/libacpi/build.c index eb8c632..e53b4a7 100644 --- a/xen/common/libacpi/build.c +++ b/xen/common/libacpi/build.c @@ -480,7 +480,7 @@ static int new_vm_gid(struct acpi_config *config) return 1; } -void acpi_build_tables(struct acpi_config *config, unsigned int physical) +void acpi_build_tables(struct acpi_config *config, unsigned long physical) { struct acpi_20_rsdp *rsdp; struct acpi_20_rsdt *rsdt; diff --git a/xen/common/libacpi/dsdt_empty.asl b/xen/common/libacpi/dsdt_empty.asl new file mode 100644 index 0000000..25c0b95 --- /dev/null +++ b/xen/common/libacpi/dsdt_empty.asl @@ -0,0 +1,22 @@ +/****************************************************************************** + * DSDT for Xen with Qemu device model + * + * Copyright (c) 2004, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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/>. + */ + +DefinitionBlock ("DSDT.aml", "DSDT", 2, "Xen", "HVM", 0) +{ + +} -- 2.4.3 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |