diff mbox

[Xen-devel,v2,34/41] arm : acpi create and map acpi tables

Message ID 1431893048-5214-35-git-send-email-parth.dixit@linaro.org
State New
Headers show

Commit Message

Parth Dixit May 17, 2015, 8:04 p.m. UTC
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.dixit@linaro.org>
---
 xen/arch/arm/domain_build.c | 108 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)

Comments

Parth Dixit July 5, 2015, 1:31 p.m. UTC | #1
+shannon

On 18 May 2015 at 01:34, Parth Dixit <parth.dixit@linaro.org> wrote:
> 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.dixit@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
>
diff mbox

Patch

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,