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

[Xen-devel] [PATCH v2 21/21] xen/arm: split domain_build.c



domain_build.c is too large.

Move all the ACPI specific device tree generating functions from
domain_build.c to acpi/acpi_dt_build.c.

Signed-off-by: Stefano Stabellini <stefanos@xxxxxxxxxx>
---
 xen/arch/arm/acpi/Makefile        |   1 +
 xen/arch/arm/acpi/acpi_dt_build.c | 588 ++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/acpi/acpi_dt_build.h |  32 +++
 xen/arch/arm/domain_build.c       | 582 +------------------------------------
 4 files changed, 626 insertions(+), 577 deletions(-)
 create mode 100644 xen/arch/arm/acpi/acpi_dt_build.c
 create mode 100644 xen/arch/arm/acpi/acpi_dt_build.h

diff --git a/xen/arch/arm/acpi/Makefile b/xen/arch/arm/acpi/Makefile
index 23963f8..ac0804b 100644
--- a/xen/arch/arm/acpi/Makefile
+++ b/xen/arch/arm/acpi/Makefile
@@ -1,2 +1,3 @@
 obj-y += lib.o
+obj-y += acpi_dt_build.o
 obj-y += boot.init.o
diff --git a/xen/arch/arm/acpi/acpi_dt_build.c 
b/xen/arch/arm/acpi/acpi_dt_build.c
new file mode 100644
index 0000000..19f70a1
--- /dev/null
+++ b/xen/arch/arm/acpi/acpi_dt_build.c
@@ -0,0 +1,588 @@
+#include <xen/mm.h>
+#include <xen/sched.h>
+#include <xen/acpi.h>
+#include <xen/event.h>
+#include <xen/iocap.h>
+#include <xen/device_tree.h>
+#include <xen/libfdt/libfdt.h>
+#include <xen/irq.h>
+#include <asm/irq.h>
+#include <acpi/actables.h>
+#include "acpi_dt_build.h"
+#include "../kernel.h"
+
+/* Override macros from asm/page.h to make them work with mfn_t */
+#undef virt_to_mfn
+#define virt_to_mfn(va) _mfn(__virt_to_mfn(va))
+
+#define ACPI_DOM0_FDT_MIN_SIZE 4096
+
+static int acpi_iomem_deny_access(struct domain *d)
+{
+    acpi_status status;
+    struct acpi_table_spcr *spcr = NULL;
+    unsigned long mfn;
+    int rc;
+
+    /* Firstly permit full MMIO capabilities. */
+    rc = iomem_permit_access(d, 0UL, ~0UL);
+    if ( rc )
+        return rc;
+
+    /* TODO: Deny MMIO access for SMMU, GIC ITS */
+    status = acpi_get_table(ACPI_SIG_SPCR, 0,
+                            (struct acpi_table_header **)&spcr);
+
+    if ( ACPI_FAILURE(status) )
+    {
+        printk("Failed to get SPCR table\n");
+        return -EINVAL;
+    }
+
+    mfn = spcr->serial_port.address >> PAGE_SHIFT;
+    /* Deny MMIO access for UART */
+    rc = iomem_deny_access(d, mfn, mfn + 1);
+    if ( rc )
+        return rc;
+
+    /* Deny MMIO access for GIC regions */
+    return gic_iomem_deny_access(d);
+}
+
+static int acpi_route_spis(struct domain *d)
+{
+    int i, res;
+    struct irq_desc *desc;
+
+    /*
+     * Route the IRQ to hardware domain and permit the access.
+     * The interrupt type will be set by set by the hardware domain.
+     */
+    for( i = NR_LOCAL_IRQS; i < vgic_num_irqs(d); i++ )
+    {
+        /*
+         * TODO: Exclude the SPIs SMMU uses which should not be routed to
+         * the hardware domain.
+         */
+        desc = irq_to_desc(i);
+        if ( desc->action != NULL)
+            continue;
+
+        /* XXX: Shall we use a proper devname? */
+        res = map_irq_to_domain(d, i, true, "ACPI");
+        if ( res )
+            return res;
+    }
+
+    return 0;
+}
+
+static int acpi_make_hypervisor_node(const struct kernel_info *kinfo,
+                                     struct membank tbl_add[])
+{
+    const char compat[] =
+        "xen,xen-"__stringify(XEN_VERSION)"."__stringify(XEN_SUBVERSION)"\0"
+        "xen,xen";
+    int res;
+    /* Convenience alias */
+    void *fdt = kinfo->fdt;
+
+    dt_dprintk("Create hypervisor node\n");
+
+    /* See linux Documentation/devicetree/bindings/arm/xen.txt */
+    res = fdt_begin_node(fdt, "hypervisor");
+    if ( res )
+        return res;
+
+    /* Cannot use fdt_property_string due to embedded nulls */
+    res = fdt_property(fdt, "compatible", compat, sizeof(compat));
+    if ( res )
+        return res;
+
+    res = acpi_make_efi_nodes(fdt, tbl_add);
+    if ( res )
+        return res;
+
+    res = fdt_end_node(fdt);
+
+    return res;
+}
+
+/*
+ * Prepare a minimal DTB for Dom0 which contains bootargs, initrd, memory
+ * information, EFI table.
+ */
+static int create_acpi_dtb(struct kernel_info *kinfo, struct membank tbl_add[])
+{
+    int new_size;
+    int ret;
+
+    dt_dprintk("Prepare a min DTB for DOM0\n");
+
+    /* Allocate min size for DT */
+    new_size = ACPI_DOM0_FDT_MIN_SIZE;
+    kinfo->fdt = xmalloc_bytes(new_size);
+
+    if ( kinfo->fdt == NULL )
+        return -ENOMEM;
+
+    /* Create a new empty DT for DOM0 */
+    ret = fdt_create(kinfo->fdt, new_size);
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_finish_reservemap(kinfo->fdt);
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_begin_node(kinfo->fdt, "/");
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_property_cell(kinfo->fdt, "#address-cells", 2);
+    if ( ret )
+        return ret;
+
+    ret = fdt_property_cell(kinfo->fdt, "#size-cells", 1);
+    if ( ret )
+        return ret;
+
+    /* Create a chosen node for DOM0 */
+    ret = make_chosen_node(kinfo);
+    if ( ret )
+        goto err;
+
+    ret = acpi_make_hypervisor_node(kinfo, tbl_add);
+    if ( ret )
+        goto err;
+
+    ret = fdt_end_node(kinfo->fdt);
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_finish(kinfo->fdt);
+    if ( ret < 0 )
+        goto err;
+
+    return 0;
+
+  err:
+    printk("Device tree generation failed (%d).\n", ret);
+    xfree(kinfo->fdt);
+    return -EINVAL;
+}
+
+static void acpi_map_other_tables(struct domain *d)
+{
+    int i;
+    unsigned long res;
+    u64 addr, size;
+
+    /* Map all ACPI tables to Dom0 using 1:1 mappings. */
+    for( i = 0; i < acpi_gbl_root_table_list.count; i++ )
+    {
+        addr = acpi_gbl_root_table_list.tables[i].address;
+        size = acpi_gbl_root_table_list.tables[i].length;
+        res = map_regions_p2mt(d,
+                               gaddr_to_gfn(addr),
+                               PFN_UP(size),
+                               maddr_to_mfn(addr),
+                               p2m_mmio_direct_c);
+        if ( res )
+        {
+             panic(XENLOG_ERR "Unable to map ACPI region 0x%"PRIx64
+                   " - 0x%"PRIx64" in domain \n",
+                   addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1);
+        }
+    }
+}
+
+static int acpi_create_rsdp(struct domain *d, struct membank tbl_add[])
+{
+
+    struct acpi_table_rsdp *rsdp = NULL;
+    u64 addr;
+    u64 table_size = sizeof(struct acpi_table_rsdp);
+    u8 *base_ptr;
+    u8 checksum;
+
+    addr = acpi_os_get_root_pointer();
+    if ( !addr  )
+    {
+        printk("Unable to get acpi root pointer\n");
+        return -EINVAL;
+    }
+    rsdp = acpi_os_map_memory(addr, table_size);
+    base_ptr = d->arch.efi_acpi_table
+               + acpi_get_table_offset(tbl_add, TBL_RSDP);
+    memcpy(base_ptr, rsdp, table_size);
+    acpi_os_unmap_memory(rsdp, table_size);
+
+    rsdp = (struct acpi_table_rsdp *)base_ptr;
+    /* Replace xsdt_physical_address */
+    rsdp->xsdt_physical_address = tbl_add[TBL_XSDT].start;
+    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, rsdp), table_size);
+    rsdp->checksum = rsdp->checksum - checksum;
+
+    tbl_add[TBL_RSDP].start = d->arch.efi_acpi_gpa
+                              + acpi_get_table_offset(tbl_add, TBL_RSDP);
+    tbl_add[TBL_RSDP].size = table_size;
+
+    return 0;
+}
+
+static void acpi_xsdt_modify_entry(u64 entry[], unsigned long entry_count,
+                                   char *signature, u64 addr)
+{
+    int i;
+    struct acpi_table_header *table;
+    u64 size = sizeof(struct acpi_table_header);
+
+    for( i = 0; i < entry_count; i++ )
+    {
+        table = acpi_os_map_memory(entry[i], size);
+        if ( ACPI_COMPARE_NAME(table->signature, signature) )
+        {
+            entry[i] = addr;
+            acpi_os_unmap_memory(table, size);
+            break;
+        }
+        acpi_os_unmap_memory(table, size);
+    }
+}
+
+static int acpi_create_xsdt(struct domain *d, struct membank tbl_add[])
+{
+    struct acpi_table_header *table = NULL;
+    struct acpi_table_rsdp *rsdp_tbl;
+    struct acpi_table_xsdt *xsdt = NULL;
+    u64 table_size, addr;
+    unsigned long entry_count;
+    u8 *base_ptr;
+    u8 checksum;
+
+    addr = acpi_os_get_root_pointer();
+    if ( !addr )
+    {
+        printk("Unable to get acpi root pointer\n");
+        return -EINVAL;
+    }
+    rsdp_tbl = acpi_os_map_memory(addr, sizeof(struct acpi_table_rsdp));
+    table = acpi_os_map_memory(rsdp_tbl->xsdt_physical_address,
+                               sizeof(struct acpi_table_header));
+
+    /* Add place for STAO table in XSDT table */
+    table_size = table->length + sizeof(u64);
+    entry_count = (table->length - sizeof(struct acpi_table_header))
+                  / sizeof(u64);
+    base_ptr = d->arch.efi_acpi_table
+               + acpi_get_table_offset(tbl_add, TBL_XSDT);
+    memcpy(base_ptr, table, table->length);
+    acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+    acpi_os_unmap_memory(rsdp_tbl, sizeof(struct acpi_table_rsdp));
+
+    xsdt = (struct acpi_table_xsdt *)base_ptr;
+    acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count,
+                           ACPI_SIG_FADT, tbl_add[TBL_FADT].start);
+    acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count,
+                           ACPI_SIG_MADT, tbl_add[TBL_MADT].start);
+    xsdt->table_offset_entry[entry_count] = tbl_add[TBL_STAO].start;
+
+    xsdt->header.length = table_size;
+    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, xsdt), table_size);
+    xsdt->header.checksum -= checksum;
+
+    tbl_add[TBL_XSDT].start = d->arch.efi_acpi_gpa
+                              + acpi_get_table_offset(tbl_add, TBL_XSDT);
+    tbl_add[TBL_XSDT].size = table_size;
+
+    return 0;
+}
+
+static int acpi_create_stao(struct domain *d, struct membank tbl_add[])
+{
+    struct acpi_table_header *table = NULL;
+    struct acpi_table_stao *stao = NULL;
+    u32 table_size = sizeof(struct acpi_table_stao);
+    u32 offset = acpi_get_table_offset(tbl_add, TBL_STAO);
+    acpi_status status;
+    u8 *base_ptr, checksum;
+
+    /* Copy OEM and ASL compiler fields from another table, use MADT */
+    status = acpi_get_table(ACPI_SIG_MADT, 0, &table);
+
+    if ( ACPI_FAILURE(status) )
+    {
+        const char *msg = acpi_format_exception(status);
+
+        printk("STAO: Failed to get MADT table, %s\n", msg);
+        return -EINVAL;
+    }
+
+    base_ptr = d->arch.efi_acpi_table + offset;
+    memcpy(base_ptr, table, sizeof(struct acpi_table_header));
+
+    stao = (struct acpi_table_stao *)base_ptr;
+    memcpy(stao->header.signature, ACPI_SIG_STAO, 4);
+    stao->header.revision = 1;
+    stao->header.length = table_size;
+    stao->ignore_uart = 1;
+    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, stao), table_size);
+    stao->header.checksum -= checksum;
+
+    tbl_add[TBL_STAO].start = d->arch.efi_acpi_gpa + offset;
+    tbl_add[TBL_STAO].size = table_size;
+
+    return 0;
+}
+
+static int acpi_create_madt(struct domain *d, struct membank tbl_add[])
+{
+    struct acpi_table_header *table = NULL;
+    struct acpi_table_madt *madt = NULL;
+    struct acpi_subtable_header *header;
+    struct acpi_madt_generic_distributor *gicd;
+    u32 table_size = sizeof(struct acpi_table_madt);
+    u32 offset = acpi_get_table_offset(tbl_add, TBL_MADT);
+    int ret;
+    acpi_status status;
+    u8 *base_ptr, checksum;
+
+    status = acpi_get_table(ACPI_SIG_MADT, 0, &table);
+
+    if ( ACPI_FAILURE(status) )
+    {
+        const char *msg = acpi_format_exception(status);
+
+        printk("Failed to get MADT table, %s\n", msg);
+        return -EINVAL;
+    }
+
+    base_ptr = d->arch.efi_acpi_table + offset;
+    memcpy(base_ptr, table, table_size);
+
+    /* Add Generic Distributor. */
+    header = acpi_table_get_entry_madt(ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
+    if ( !header )
+    {
+        printk("Can't get GICD entry\n");
+        return -EINVAL;
+    }
+    gicd = container_of(header, struct acpi_madt_generic_distributor, header);
+    memcpy(base_ptr + table_size, gicd,
+                sizeof(struct acpi_madt_generic_distributor));
+    table_size += sizeof(struct acpi_madt_generic_distributor);
+
+    /* Add other subtables. */
+    ret = gic_make_hwdom_madt(d, offset + table_size);
+    if ( ret < 0 )
+    {
+        printk("Failed to get other subtables\n");
+        return -EINVAL;
+    }
+    table_size += ret;
+
+    madt = (struct acpi_table_madt *)base_ptr;
+    madt->header.length = table_size;
+    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, madt), table_size);
+    madt->header.checksum -= checksum;
+
+    tbl_add[TBL_MADT].start = d->arch.efi_acpi_gpa + offset;
+    tbl_add[TBL_MADT].size = table_size;
+
+    return 0;
+}
+
+static int acpi_create_fadt(struct domain *d, struct membank tbl_add[])
+{
+    struct acpi_table_header *table = NULL;
+    struct acpi_table_fadt *fadt = NULL;
+    u64 table_size;
+    acpi_status status;
+    u8 *base_ptr;
+    u8 checksum;
+
+    status = acpi_get_table(ACPI_SIG_FADT, 0, &table);
+
+    if ( ACPI_FAILURE(status) )
+    {
+        const char *msg = acpi_format_exception(status);
+
+        printk("Failed to get FADT table, %s\n", msg);
+        return -EINVAL;
+    }
+
+    table_size = table->length;
+    base_ptr = d->arch.efi_acpi_table
+               + acpi_get_table_offset(tbl_add, TBL_FADT);
+    memcpy(base_ptr, table, table_size);
+    fadt = (struct acpi_table_fadt *)base_ptr;
+
+    /* Set PSCI_COMPLIANT and PSCI_USE_HVC */
+    fadt->arm_boot_flags |= (ACPI_FADT_PSCI_COMPLIANT | 
ACPI_FADT_PSCI_USE_HVC);
+    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, fadt), table_size);
+    fadt->header.checksum -= checksum;
+
+    tbl_add[TBL_FADT].start = d->arch.efi_acpi_gpa
+                              + acpi_get_table_offset(tbl_add, TBL_FADT);
+    tbl_add[TBL_FADT].size = table_size;
+
+    return 0;
+}
+
+static int estimate_acpi_efi_size(struct domain *d, struct kernel_info *kinfo)
+{
+    size_t efi_size, acpi_size, madt_size;
+    u64 addr;
+    struct acpi_table_rsdp *rsdp_tbl;
+    struct acpi_table_header *table;
+
+    efi_size = estimate_efi_size(kinfo->mem.nr_banks);
+
+    acpi_size = ROUNDUP(sizeof(struct acpi_table_fadt), 8);
+    acpi_size += ROUNDUP(sizeof(struct acpi_table_stao), 8);
+
+    madt_size = gic_get_hwdom_madt_size(d);
+    acpi_size += ROUNDUP(madt_size, 8);
+
+    addr = acpi_os_get_root_pointer();
+    if ( !addr )
+    {
+        printk("Unable to get acpi root pointer\n");
+        return -EINVAL;
+    }
+
+    rsdp_tbl = acpi_os_map_memory(addr, sizeof(struct acpi_table_rsdp));
+    if ( !rsdp_tbl )
+    {
+        printk("Unable to map RSDP table\n");
+        return -EINVAL;
+    }
+
+    table = acpi_os_map_memory(rsdp_tbl->xsdt_physical_address,
+                               sizeof(struct acpi_table_header));
+    acpi_os_unmap_memory(rsdp_tbl, sizeof(struct acpi_table_rsdp));
+    if ( !table )
+    {
+        printk("Unable to map XSDT table\n");
+        return -EINVAL;
+    }
+
+    /* Add place for STAO table in XSDT table */
+    acpi_size += ROUNDUP(table->length + sizeof(u64), 8);
+    acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+
+    acpi_size += ROUNDUP(sizeof(struct acpi_table_rsdp), 8);
+    d->arch.efi_acpi_len = PAGE_ALIGN(ROUNDUP(efi_size, 8)
+                                      + ROUNDUP(acpi_size, 8));
+
+    return 0;
+}
+
+int prepare_acpi(struct domain *d, struct kernel_info *kinfo)
+{
+    int rc = 0;
+    int order;
+    struct membank tbl_add[TBL_MMAX] = {};
+
+    rc = estimate_acpi_efi_size(d, kinfo);
+    if ( rc != 0 )
+        return rc;
+
+    order = get_order_from_bytes(d->arch.efi_acpi_len);
+    d->arch.efi_acpi_table = alloc_xenheap_pages(order, 0);
+    if ( d->arch.efi_acpi_table == NULL )
+    {
+        printk("unable to allocate memory!\n");
+        return -ENOMEM;
+    }
+    memset(d->arch.efi_acpi_table, 0, d->arch.efi_acpi_len);
+
+    /*
+     * For ACPI, Dom0 doesn't use kinfo->gnttab_start to get the grant table
+     * region. So we use it as the ACPI table mapped address. Also it needs to
+     * check if the size of grant table region is enough for those ACPI tables.
+     */
+    d->arch.efi_acpi_gpa = kinfo->gnttab_start;
+    if ( kinfo->gnttab_size < d->arch.efi_acpi_len )
+    {
+        printk("The grant table region is not enough to fit the ACPI 
tables!\n");
+        return -EINVAL;
+    }
+
+    rc = acpi_create_fadt(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_create_madt(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_create_stao(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_create_xsdt(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_create_rsdp(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    acpi_map_other_tables(d);
+    acpi_create_efi_system_table(d, tbl_add);
+    acpi_create_efi_mmap_table(d, &kinfo->mem, tbl_add);
+
+    /* Map the EFI and ACPI tables to Dom0 */
+    rc = map_regions_p2mt(d,
+                          gaddr_to_gfn(d->arch.efi_acpi_gpa),
+                          PFN_UP(d->arch.efi_acpi_len),
+                          virt_to_mfn(d->arch.efi_acpi_table),
+                          p2m_mmio_direct_c);
+    if ( rc != 0 )
+    {
+        printk(XENLOG_ERR "Unable to map EFI/ACPI table 0x%"PRIx64
+               " - 0x%"PRIx64" in domain %d\n",
+               d->arch.efi_acpi_gpa & PAGE_MASK,
+               PAGE_ALIGN(d->arch.efi_acpi_gpa + d->arch.efi_acpi_len) - 1,
+               d->domain_id);
+        return rc;
+    }
+
+    /*
+     * Flush the cache for this region, otherwise DOM0 may read wrong data when
+     * the cache is disabled.
+     */
+    clean_and_invalidate_dcache_va_range(d->arch.efi_acpi_table,
+                                         d->arch.efi_acpi_len);
+
+    rc = create_acpi_dtb(kinfo, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_route_spis(d);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_iomem_deny_access(d);
+    if ( rc != 0 )
+        return rc;
+
+    /*
+     * All PPIs have been registered, allocate the event channel
+     * interrupts.
+     */
+    evtchn_allocate(d);
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/acpi/acpi_dt_build.h 
b/xen/arch/arm/acpi/acpi_dt_build.h
new file mode 100644
index 0000000..08e7aab
--- /dev/null
+++ b/xen/arch/arm/acpi/acpi_dt_build.h
@@ -0,0 +1,32 @@
+#ifndef __ARCH_ARM_ACPI_ACPI_DT_BUILD_H__
+#define __ARCH_ARM_ACPI_ACPI_DT_BUILD_H__
+
+#include <xen/sched.h>
+#include "../kernel.h"
+
+int map_irq_to_domain(struct domain *d, unsigned int irq,
+                      bool need_mapping, const char *devname);
+int make_chosen_node(const struct kernel_info *kinfo);
+void evtchn_allocate(struct domain *d);
+
+#ifndef CONFIG_ACPI
+static inline int prepare_acpi(struct domain *d, struct kernel_info *kinfo)
+{
+    /* Only booting with ACPI will hit here */
+    BUG();
+    return -EINVAL;
+}
+#else
+int prepare_acpi(struct domain *d, struct kernel_info *kinfo);
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 9f58002..01aa0cf 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -24,6 +24,7 @@
 
 #include <xen/irq.h>
 #include <xen/grant_table.h>
+#include "acpi/acpi_dt_build.h"
 #include "kernel.h"
 
 static unsigned int __initdata opt_dom0_max_vcpus;
@@ -599,8 +600,6 @@ static int make_memory_node(const struct domain *d,
     return res;
 }
 
-static void evtchn_allocate(struct domain *d);
-
 static int make_hypervisor_node(struct domain *d,
                                 const struct kernel_info *kinfo,
                                 int addrcells, int sizecells)
@@ -958,7 +957,7 @@ static int make_timer_node(const struct domain *d, void 
*fdt,
  * on ACPI systems, and DomUs started directly from Xen based on device
  * tree information.
  */
-static int make_chosen_node(const struct kernel_info *kinfo)
+int make_chosen_node(const struct kernel_info *kinfo)
 {
     int res;
     const char *bootargs = NULL;
@@ -999,8 +998,8 @@ static int make_chosen_node(const struct kernel_info *kinfo)
     return res;
 }
 
-static int map_irq_to_domain(struct domain *d, unsigned int irq,
-                             bool need_mapping, const char *devname)
+int map_irq_to_domain(struct domain *d, unsigned int irq,
+                      bool need_mapping, const char *devname)
 
 {
     int res;
@@ -1700,577 +1699,6 @@ static int prepare_dtb_hwdom(struct domain *d, struct 
kernel_info *kinfo)
     return -EINVAL;
 }
 
-#ifdef CONFIG_ACPI
-#define ACPI_DOM0_FDT_MIN_SIZE 4096
-
-static int acpi_iomem_deny_access(struct domain *d)
-{
-    acpi_status status;
-    struct acpi_table_spcr *spcr = NULL;
-    unsigned long mfn;
-    int rc;
-
-    /* Firstly permit full MMIO capabilities. */
-    rc = iomem_permit_access(d, 0UL, ~0UL);
-    if ( rc )
-        return rc;
-
-    /* TODO: Deny MMIO access for SMMU, GIC ITS */
-    status = acpi_get_table(ACPI_SIG_SPCR, 0,
-                            (struct acpi_table_header **)&spcr);
-
-    if ( ACPI_FAILURE(status) )
-    {
-        printk("Failed to get SPCR table\n");
-        return -EINVAL;
-    }
-
-    mfn = spcr->serial_port.address >> PAGE_SHIFT;
-    /* Deny MMIO access for UART */
-    rc = iomem_deny_access(d, mfn, mfn + 1);
-    if ( rc )
-        return rc;
-
-    /* Deny MMIO access for GIC regions */
-    return gic_iomem_deny_access(d);
-}
-
-static int acpi_route_spis(struct domain *d)
-{
-    int i, res;
-    struct irq_desc *desc;
-
-    /*
-     * Route the IRQ to hardware domain and permit the access.
-     * The interrupt type will be set by set by the hardware domain.
-     */
-    for( i = NR_LOCAL_IRQS; i < vgic_num_irqs(d); i++ )
-    {
-        /*
-         * TODO: Exclude the SPIs SMMU uses which should not be routed to
-         * the hardware domain.
-         */
-        desc = irq_to_desc(i);
-        if ( desc->action != NULL)
-            continue;
-
-        /* XXX: Shall we use a proper devname? */
-        res = map_irq_to_domain(d, i, true, "ACPI");
-        if ( res )
-            return res;
-    }
-
-    return 0;
-}
-
-static int acpi_make_hypervisor_node(const struct kernel_info *kinfo,
-                                     struct membank tbl_add[])
-{
-    const char compat[] =
-        "xen,xen-"__stringify(XEN_VERSION)"."__stringify(XEN_SUBVERSION)"\0"
-        "xen,xen";
-    int res;
-    /* Convenience alias */
-    void *fdt = kinfo->fdt;
-
-    dt_dprintk("Create hypervisor node\n");
-
-    /* See linux Documentation/devicetree/bindings/arm/xen.txt */
-    res = fdt_begin_node(fdt, "hypervisor");
-    if ( res )
-        return res;
-
-    /* Cannot use fdt_property_string due to embedded nulls */
-    res = fdt_property(fdt, "compatible", compat, sizeof(compat));
-    if ( res )
-        return res;
-
-    res = acpi_make_efi_nodes(fdt, tbl_add);
-    if ( res )
-        return res;
-
-    res = fdt_end_node(fdt);
-
-    return res;
-}
-
-/*
- * Prepare a minimal DTB for Dom0 which contains bootargs, initrd, memory
- * information, EFI table.
- */
-static int create_acpi_dtb(struct kernel_info *kinfo, struct membank tbl_add[])
-{
-    int new_size;
-    int ret;
-
-    dt_dprintk("Prepare a min DTB for DOM0\n");
-
-    /* Allocate min size for DT */
-    new_size = ACPI_DOM0_FDT_MIN_SIZE;
-    kinfo->fdt = xmalloc_bytes(new_size);
-
-    if ( kinfo->fdt == NULL )
-        return -ENOMEM;
-
-    /* Create a new empty DT for DOM0 */
-    ret = fdt_create(kinfo->fdt, new_size);
-    if ( ret < 0 )
-        goto err;
-
-    ret = fdt_finish_reservemap(kinfo->fdt);
-    if ( ret < 0 )
-        goto err;
-
-    ret = fdt_begin_node(kinfo->fdt, "/");
-    if ( ret < 0 )
-        goto err;
-
-    ret = fdt_property_cell(kinfo->fdt, "#address-cells", 2);
-    if ( ret )
-        return ret;
-
-    ret = fdt_property_cell(kinfo->fdt, "#size-cells", 1);
-    if ( ret )
-        return ret;
-
-    /* Create a chosen node for DOM0 */
-    ret = make_chosen_node(kinfo);
-    if ( ret )
-        goto err;
-
-    ret = acpi_make_hypervisor_node(kinfo, tbl_add);
-    if ( ret )
-        goto err;
-
-    ret = fdt_end_node(kinfo->fdt);
-    if ( ret < 0 )
-        goto err;
-
-    ret = fdt_finish(kinfo->fdt);
-    if ( ret < 0 )
-        goto err;
-
-    return 0;
-
-  err:
-    printk("Device tree generation failed (%d).\n", ret);
-    xfree(kinfo->fdt);
-    return -EINVAL;
-}
-
-static void acpi_map_other_tables(struct domain *d)
-{
-    int i;
-    unsigned long res;
-    u64 addr, size;
-
-    /* Map all ACPI tables to Dom0 using 1:1 mappings. */
-    for( i = 0; i < acpi_gbl_root_table_list.count; i++ )
-    {
-        addr = acpi_gbl_root_table_list.tables[i].address;
-        size = acpi_gbl_root_table_list.tables[i].length;
-        res = map_regions_p2mt(d,
-                               gaddr_to_gfn(addr),
-                               PFN_UP(size),
-                               maddr_to_mfn(addr),
-                               p2m_mmio_direct_c);
-        if ( res )
-        {
-             panic(XENLOG_ERR "Unable to map ACPI region 0x%"PRIx64
-                   " - 0x%"PRIx64" in domain \n",
-                   addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1);
-        }
-    }
-}
-
-static int acpi_create_rsdp(struct domain *d, struct membank tbl_add[])
-{
-
-    struct acpi_table_rsdp *rsdp = NULL;
-    u64 addr;
-    u64 table_size = sizeof(struct acpi_table_rsdp);
-    u8 *base_ptr;
-    u8 checksum;
-
-    addr = acpi_os_get_root_pointer();
-    if ( !addr  )
-    {
-        printk("Unable to get acpi root pointer\n");
-        return -EINVAL;
-    }
-    rsdp = acpi_os_map_memory(addr, table_size);
-    base_ptr = d->arch.efi_acpi_table
-               + acpi_get_table_offset(tbl_add, TBL_RSDP);
-    memcpy(base_ptr, rsdp, table_size);
-    acpi_os_unmap_memory(rsdp, table_size);
-
-    rsdp = (struct acpi_table_rsdp *)base_ptr;
-    /* Replace xsdt_physical_address */
-    rsdp->xsdt_physical_address = tbl_add[TBL_XSDT].start;
-    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, rsdp), table_size);
-    rsdp->checksum = rsdp->checksum - checksum;
-
-    tbl_add[TBL_RSDP].start = d->arch.efi_acpi_gpa
-                              + acpi_get_table_offset(tbl_add, TBL_RSDP);
-    tbl_add[TBL_RSDP].size = table_size;
-
-    return 0;
-}
-
-static void acpi_xsdt_modify_entry(u64 entry[], unsigned long entry_count,
-                                   char *signature, u64 addr)
-{
-    int i;
-    struct acpi_table_header *table;
-    u64 size = sizeof(struct acpi_table_header);
-
-    for( i = 0; i < entry_count; i++ )
-    {
-        table = acpi_os_map_memory(entry[i], size);
-        if ( ACPI_COMPARE_NAME(table->signature, signature) )
-        {
-            entry[i] = addr;
-            acpi_os_unmap_memory(table, size);
-            break;
-        }
-        acpi_os_unmap_memory(table, size);
-    }
-}
-
-static int acpi_create_xsdt(struct domain *d, struct membank tbl_add[])
-{
-    struct acpi_table_header *table = NULL;
-    struct acpi_table_rsdp *rsdp_tbl;
-    struct acpi_table_xsdt *xsdt = NULL;
-    u64 table_size, addr;
-    unsigned long entry_count;
-    u8 *base_ptr;
-    u8 checksum;
-
-    addr = acpi_os_get_root_pointer();
-    if ( !addr )
-    {
-        printk("Unable to get acpi root pointer\n");
-        return -EINVAL;
-    }
-    rsdp_tbl = acpi_os_map_memory(addr, sizeof(struct acpi_table_rsdp));
-    table = acpi_os_map_memory(rsdp_tbl->xsdt_physical_address,
-                               sizeof(struct acpi_table_header));
-
-    /* Add place for STAO table in XSDT table */
-    table_size = table->length + sizeof(u64);
-    entry_count = (table->length - sizeof(struct acpi_table_header))
-                  / sizeof(u64);
-    base_ptr = d->arch.efi_acpi_table
-               + acpi_get_table_offset(tbl_add, TBL_XSDT);
-    memcpy(base_ptr, table, table->length);
-    acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
-    acpi_os_unmap_memory(rsdp_tbl, sizeof(struct acpi_table_rsdp));
-
-    xsdt = (struct acpi_table_xsdt *)base_ptr;
-    acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count,
-                           ACPI_SIG_FADT, tbl_add[TBL_FADT].start);
-    acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count,
-                           ACPI_SIG_MADT, tbl_add[TBL_MADT].start);
-    xsdt->table_offset_entry[entry_count] = tbl_add[TBL_STAO].start;
-
-    xsdt->header.length = table_size;
-    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, xsdt), table_size);
-    xsdt->header.checksum -= checksum;
-
-    tbl_add[TBL_XSDT].start = d->arch.efi_acpi_gpa
-                              + acpi_get_table_offset(tbl_add, TBL_XSDT);
-    tbl_add[TBL_XSDT].size = table_size;
-
-    return 0;
-}
-
-static int acpi_create_stao(struct domain *d, struct membank tbl_add[])
-{
-    struct acpi_table_header *table = NULL;
-    struct acpi_table_stao *stao = NULL;
-    u32 table_size = sizeof(struct acpi_table_stao);
-    u32 offset = acpi_get_table_offset(tbl_add, TBL_STAO);
-    acpi_status status;
-    u8 *base_ptr, checksum;
-
-    /* Copy OEM and ASL compiler fields from another table, use MADT */
-    status = acpi_get_table(ACPI_SIG_MADT, 0, &table);
-
-    if ( ACPI_FAILURE(status) )
-    {
-        const char *msg = acpi_format_exception(status);
-
-        printk("STAO: Failed to get MADT table, %s\n", msg);
-        return -EINVAL;
-    }
-
-    base_ptr = d->arch.efi_acpi_table + offset;
-    memcpy(base_ptr, table, sizeof(struct acpi_table_header));
-
-    stao = (struct acpi_table_stao *)base_ptr;
-    memcpy(stao->header.signature, ACPI_SIG_STAO, 4);
-    stao->header.revision = 1;
-    stao->header.length = table_size;
-    stao->ignore_uart = 1;
-    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, stao), table_size);
-    stao->header.checksum -= checksum;
-
-    tbl_add[TBL_STAO].start = d->arch.efi_acpi_gpa + offset;
-    tbl_add[TBL_STAO].size = table_size;
-
-    return 0;
-}
-
-static int acpi_create_madt(struct domain *d, struct membank tbl_add[])
-{
-    struct acpi_table_header *table = NULL;
-    struct acpi_table_madt *madt = NULL;
-    struct acpi_subtable_header *header;
-    struct acpi_madt_generic_distributor *gicd;
-    u32 table_size = sizeof(struct acpi_table_madt);
-    u32 offset = acpi_get_table_offset(tbl_add, TBL_MADT);
-    int ret;
-    acpi_status status;
-    u8 *base_ptr, checksum;
-
-    status = acpi_get_table(ACPI_SIG_MADT, 0, &table);
-
-    if ( ACPI_FAILURE(status) )
-    {
-        const char *msg = acpi_format_exception(status);
-
-        printk("Failed to get MADT table, %s\n", msg);
-        return -EINVAL;
-    }
-
-    base_ptr = d->arch.efi_acpi_table + offset;
-    memcpy(base_ptr, table, table_size);
-
-    /* Add Generic Distributor. */
-    header = acpi_table_get_entry_madt(ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
-    if ( !header )
-    {
-        printk("Can't get GICD entry\n");
-        return -EINVAL;
-    }
-    gicd = container_of(header, struct acpi_madt_generic_distributor, header);
-    memcpy(base_ptr + table_size, gicd,
-                sizeof(struct acpi_madt_generic_distributor));
-    table_size += sizeof(struct acpi_madt_generic_distributor);
-
-    /* Add other subtables. */
-    ret = gic_make_hwdom_madt(d, offset + table_size);
-    if ( ret < 0 )
-    {
-        printk("Failed to get other subtables\n");
-        return -EINVAL;
-    }
-    table_size += ret;
-
-    madt = (struct acpi_table_madt *)base_ptr;
-    madt->header.length = table_size;
-    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, madt), table_size);
-    madt->header.checksum -= checksum;
-
-    tbl_add[TBL_MADT].start = d->arch.efi_acpi_gpa + offset;
-    tbl_add[TBL_MADT].size = table_size;
-
-    return 0;
-}
-
-static int acpi_create_fadt(struct domain *d, struct membank tbl_add[])
-{
-    struct acpi_table_header *table = NULL;
-    struct acpi_table_fadt *fadt = NULL;
-    u64 table_size;
-    acpi_status status;
-    u8 *base_ptr;
-    u8 checksum;
-
-    status = acpi_get_table(ACPI_SIG_FADT, 0, &table);
-
-    if ( ACPI_FAILURE(status) )
-    {
-        const char *msg = acpi_format_exception(status);
-
-        printk("Failed to get FADT table, %s\n", msg);
-        return -EINVAL;
-    }
-
-    table_size = table->length;
-    base_ptr = d->arch.efi_acpi_table
-               + acpi_get_table_offset(tbl_add, TBL_FADT);
-    memcpy(base_ptr, table, table_size);
-    fadt = (struct acpi_table_fadt *)base_ptr;
-
-    /* Set PSCI_COMPLIANT and PSCI_USE_HVC */
-    fadt->arm_boot_flags |= (ACPI_FADT_PSCI_COMPLIANT | 
ACPI_FADT_PSCI_USE_HVC);
-    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, fadt), table_size);
-    fadt->header.checksum -= checksum;
-
-    tbl_add[TBL_FADT].start = d->arch.efi_acpi_gpa
-                              + acpi_get_table_offset(tbl_add, TBL_FADT);
-    tbl_add[TBL_FADT].size = table_size;
-
-    return 0;
-}
-
-static int estimate_acpi_efi_size(struct domain *d, struct kernel_info *kinfo)
-{
-    size_t efi_size, acpi_size, madt_size;
-    u64 addr;
-    struct acpi_table_rsdp *rsdp_tbl;
-    struct acpi_table_header *table;
-
-    efi_size = estimate_efi_size(kinfo->mem.nr_banks);
-
-    acpi_size = ROUNDUP(sizeof(struct acpi_table_fadt), 8);
-    acpi_size += ROUNDUP(sizeof(struct acpi_table_stao), 8);
-
-    madt_size = gic_get_hwdom_madt_size(d);
-    acpi_size += ROUNDUP(madt_size, 8);
-
-    addr = acpi_os_get_root_pointer();
-    if ( !addr )
-    {
-        printk("Unable to get acpi root pointer\n");
-        return -EINVAL;
-    }
-
-    rsdp_tbl = acpi_os_map_memory(addr, sizeof(struct acpi_table_rsdp));
-    if ( !rsdp_tbl )
-    {
-        printk("Unable to map RSDP table\n");
-        return -EINVAL;
-    }
-
-    table = acpi_os_map_memory(rsdp_tbl->xsdt_physical_address,
-                               sizeof(struct acpi_table_header));
-    acpi_os_unmap_memory(rsdp_tbl, sizeof(struct acpi_table_rsdp));
-    if ( !table )
-    {
-        printk("Unable to map XSDT table\n");
-        return -EINVAL;
-    }
-
-    /* Add place for STAO table in XSDT table */
-    acpi_size += ROUNDUP(table->length + sizeof(u64), 8);
-    acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
-
-    acpi_size += ROUNDUP(sizeof(struct acpi_table_rsdp), 8);
-    d->arch.efi_acpi_len = PAGE_ALIGN(ROUNDUP(efi_size, 8)
-                                      + ROUNDUP(acpi_size, 8));
-
-    return 0;
-}
-
-static int prepare_acpi(struct domain *d, struct kernel_info *kinfo)
-{
-    int rc = 0;
-    int order;
-    struct membank tbl_add[TBL_MMAX] = {};
-
-    rc = estimate_acpi_efi_size(d, kinfo);
-    if ( rc != 0 )
-        return rc;
-
-    order = get_order_from_bytes(d->arch.efi_acpi_len);
-    d->arch.efi_acpi_table = alloc_xenheap_pages(order, 0);
-    if ( d->arch.efi_acpi_table == NULL )
-    {
-        printk("unable to allocate memory!\n");
-        return -ENOMEM;
-    }
-    memset(d->arch.efi_acpi_table, 0, d->arch.efi_acpi_len);
-
-    /*
-     * For ACPI, Dom0 doesn't use kinfo->gnttab_start to get the grant table
-     * region. So we use it as the ACPI table mapped address. Also it needs to
-     * check if the size of grant table region is enough for those ACPI tables.
-     */
-    d->arch.efi_acpi_gpa = kinfo->gnttab_start;
-    if ( kinfo->gnttab_size < d->arch.efi_acpi_len )
-    {
-        printk("The grant table region is not enough to fit the ACPI 
tables!\n");
-        return -EINVAL;
-    }
-
-    rc = acpi_create_fadt(d, tbl_add);
-    if ( rc != 0 )
-        return rc;
-
-    rc = acpi_create_madt(d, tbl_add);
-    if ( rc != 0 )
-        return rc;
-
-    rc = acpi_create_stao(d, tbl_add);
-    if ( rc != 0 )
-        return rc;
-
-    rc = acpi_create_xsdt(d, tbl_add);
-    if ( rc != 0 )
-        return rc;
-
-    rc = acpi_create_rsdp(d, tbl_add);
-    if ( rc != 0 )
-        return rc;
-
-    acpi_map_other_tables(d);
-    acpi_create_efi_system_table(d, tbl_add);
-    acpi_create_efi_mmap_table(d, &kinfo->mem, tbl_add);
-
-    /* Map the EFI and ACPI tables to Dom0 */
-    rc = map_regions_p2mt(d,
-                          gaddr_to_gfn(d->arch.efi_acpi_gpa),
-                          PFN_UP(d->arch.efi_acpi_len),
-                          virt_to_mfn(d->arch.efi_acpi_table),
-                          p2m_mmio_direct_c);
-    if ( rc != 0 )
-    {
-        printk(XENLOG_ERR "Unable to map EFI/ACPI table 0x%"PRIx64
-               " - 0x%"PRIx64" in domain %d\n",
-               d->arch.efi_acpi_gpa & PAGE_MASK,
-               PAGE_ALIGN(d->arch.efi_acpi_gpa + d->arch.efi_acpi_len) - 1,
-               d->domain_id);
-        return rc;
-    }
-
-    /*
-     * Flush the cache for this region, otherwise DOM0 may read wrong data when
-     * the cache is disabled.
-     */
-    clean_and_invalidate_dcache_va_range(d->arch.efi_acpi_table,
-                                         d->arch.efi_acpi_len);
-
-    rc = create_acpi_dtb(kinfo, tbl_add);
-    if ( rc != 0 )
-        return rc;
-
-    rc = acpi_route_spis(d);
-    if ( rc != 0 )
-        return rc;
-
-    rc = acpi_iomem_deny_access(d);
-    if ( rc != 0 )
-        return rc;
-
-    /*
-     * All PPIs have been registered, allocate the event channel
-     * interrupts.
-     */
-    evtchn_allocate(d);
-
-    return 0;
-}
-#else
-static int prepare_acpi(struct domain *d, struct kernel_info *kinfo)
-{
-    /* Only booting with ACPI will hit here */
-    BUG();
-    return -EINVAL;
-}
-#endif
 static void dtb_load(struct kernel_info *kinfo)
 {
     unsigned long left;
@@ -2343,7 +1771,7 @@ static void initrd_load(struct kernel_info *kinfo)
  * Note that this should only be called once all PPIs used by the
  * hardware domain have been registered.
  */
-static void evtchn_allocate(struct domain *d)
+void evtchn_allocate(struct domain *d)
 {
     int res;
     u64 val;
-- 
1.9.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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