XSDT table cannot be passed as is to DOM0 because xen creates additional
tables which have to be added to XSDT table entry.
Copy existing XSDT and modify table to add new entries.
Create status override table,xen environment table.
Copy the tables to DOM0 memory.

Signed-off-by: Parth Dixit <parth.di...@linaro.org>
---
 xen/arch/arm/domain_build.c | 108 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 90bdd01..36b072b 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -10,6 +10,7 @@
 #include <xen/errno.h>
 #include <xen/device_tree.h>
 #include <xen/acpi.h>
+#include <acpi/actables.h>
 #include <xen/efi.h>
 #include <xen/libfdt/libfdt.h>
 #include <xen/guest_access.h>
@@ -1225,16 +1226,123 @@ static int handle_node(struct domain *d, struct 
kernel_info *kinfo,
     return res;
 }
 #ifdef CONFIG_ACPI
+
+static int create_xen_acpi_tables(struct kernel_info *kinfo, struct domain *d,
+                                  struct membank tbl_add[])
+{
+    unsigned long res;
+    int offset=0;
+    u64 size;
+    u8 checksum;
+    u64 *table_entry;
+    u64 addr;
+    u8 *base_ptr;
+    struct acpi_table_xenv *xenv=NULL;
+    struct acpi_table_stao *stao=NULL;
+    struct acpi_table_header *table;
+    void * __user tbl_virt = (void * __user)(register_t)kinfo->acpi_paddr;
+
+    set_acpi_size(0);
+    addr = tbl_add[TBL_XSDT].start;
+    size = tbl_add[TBL_XSDT].size
+       - ( NR_NEW_XEN_TABLES*sizeof(acpi_native_uint) );
+
+    table = acpi_os_map_memory(addr, size);
+    size =   tbl_add[TBL_XSDT].size
+          +  tbl_add[TBL_XENV].size
+          +  tbl_add[TBL_STAO].size;
+
+    base_ptr = xzalloc_bytes(size);
+    if( base_ptr == NULL)
+        return -ENOMEM;
+
+    res = vgic_allocate_ppi(d);
+    if ( res < 0 )
+        panic("Unable to allocate a PPI for the event channel interrupt\n");
+
+    d->arch.evtchn_irq = res;
+
+    printk("Allocating PPI %u for event channel interrupt\n",
+           d->arch.evtchn_irq);
+
+   /* add xen env table */
+    tbl_add[TBL_XENV].start =(u64)(base_ptr);
+    xenv = (struct acpi_table_xenv *)(tbl_add[TBL_XENV].start);
+    ACPI_MEMCPY((void *)xenv, table, sizeof(struct acpi_table_header));
+    ACPI_MEMCPY(xenv->header.signature, ACPI_SIG_XENV, 4);
+    xenv->header.length = tbl_add[TBL_XENV].size;
+    ACPI_MEMCPY(xenv->header.oem_id, "XenVMM", 6);
+    xenv->header.revision = 1;
+    xenv->gnt_start = 0x00000010000000;
+    xenv->gnt_size = 0x20000;
+    xenv->evt_intr = d->arch.evtchn_irq;
+    xenv->evt_intr_flag = ( 0xff & EVT_CHN_INTR_TRIG );
+    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, xenv), 
tbl_add[TBL_XENV].size);
+    xenv->header.checksum = xenv->header.checksum - checksum;
+    tbl_add[TBL_XENV].start = (u64)(tbl_virt);
+    offset += tbl_add[TBL_XENV].size;
+
+    /* add stao table */
+    tbl_add[TBL_STAO].start =(u64)(base_ptr+offset);
+    stao = (struct acpi_table_stao *)(tbl_add[TBL_STAO].start);
+    ACPI_MEMCPY((void *)stao, table, sizeof(struct acpi_table_header));
+    ACPI_MEMCPY(stao->header.signature,ACPI_SIG_STAO, 4);
+    stao->header.length = tbl_add[TBL_STAO].size;
+    stao->uart = 1;
+    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, stao), 
tbl_add[TBL_STAO].size);
+    stao->header.checksum = stao->header.checksum - checksum;
+    tbl_add[TBL_STAO].start =(u64) (tbl_virt+offset);
+    offset += tbl_add[TBL_STAO].size;
+
+    /* fix xsdt table */
+    ACPI_MEMCPY(base_ptr+offset, table,table->length);
+    acpi_os_unmap_memory(table, table->length);
+
+    table = (struct acpi_table_header *)(base_ptr+offset);
+    table->length = tbl_add[TBL_XSDT].size;
+    table_entry = ACPI_CAST_PTR(u64,
+                                (base_ptr+offset + sizeof(struct 
acpi_table_header) ) );
+    table_entry +=
+        ( ( (table->length - sizeof(struct acpi_table_header) ) /
+            sizeof(acpi_native_uint) ) );
+
+    table_entry--;
+    *table_entry = tbl_add[TBL_XENV].start ;
+
+    table_entry--;
+    *table_entry = tbl_add[TBL_STAO].start;
+
+    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), table->length);
+    table->checksum =  table->checksum - checksum;
+    tbl_add[TBL_XSDT].start =(u64)(tbl_virt+offset);
+
+    res = raw_copy_to_guest_flush_dcache(tbl_virt, base_ptr, size);
+    if ( res != 0 )
+        panic("Unable to copy the stao to dom0 memory (left = %lu bytes)", 
res);
+    set_acpi_size(size);
+
+    xfree(base_ptr);
+
+    return 0;
+}
+
 static int prepare_acpi(struct domain *d, struct kernel_info *kinfo, struct 
membank tbl_add[])
 {
     unsigned long res;
     u64 addr, size;
     int i = 0;
+    struct acpi_table_rsdp *rsdp_tbl;
 
+    create_xen_acpi_tables(kinfo, d, tbl_add);
     addr = acpi_os_get_root_pointer();
     if( !addr )
         return -ENODEV;
 
+    rsdp_tbl = acpi_os_map_memory(addr, sizeof(struct acpi_table_rsdp) );
+    rsdp_tbl->xsdt_physical_address = tbl_add[TBL_XSDT].start;
+    acpi_os_unmap_memory(rsdp_tbl, sizeof(struct acpi_table_rsdp) );
+
+    /* map rsdp table */
     size = sizeof(struct acpi_table_rsdp);
 
     res = map_regions(d,
-- 
1.9.1


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

Reply via email to