This patch disables the smmu node in IORT table for hardware domain.
Also patches the output_base of pci_rc id_array with output_base of
smmu node id_array.
Signed-off-by: Manish Jaggi <mja...@cavium.com>
---
xen/arch/arm/domain_build.c | 142
+++++++++++++++++++++++++++++++++++++++++++-
xen/include/acpi/actbl2.h | 3 +-
xen/include/asm-arm/acpi.h | 1 +
3 files changed, 144 insertions(+), 2 deletions(-)
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index d6d6c94..9f41d0e 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -32,6 +32,7 @@ integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);
int dom0_11_mapping = 1;
static u64 __initdata dom0_mem;
+static u8 *iort_base_ptr;
static void __init parse_dom0_mem(const char *s)
{
@@ -1336,6 +1337,96 @@ static int prepare_dtb(struct domain *d, struct
kernel_info *kinfo)
#ifdef CONFIG_ACPI
#define ACPI_DOM0_FDT_MIN_SIZE 4096
+static void patch_output_ref(struct acpi_iort_id_mapping *pci_idmap,
+ struct acpi_iort_node *smmu_node)
+{
+ struct acpi_iort_id_mapping *idmap = NULL;
+ int i;
+ for (i=0; i < smmu_node->mapping_count; i++) {
+ if(!idmap)
+ idmap = (struct acpi_iort_id_mapping*)((u8*)smmu_node
+ + smmu_node->mapping_offset);
+ else
+ idmap++;
+
+ if (pci_idmap->output_base == idmap->input_base) {
+ pci_idmap->output_base = idmap->output_base;
+ pci_idmap->output_reference = idmap->output_reference;
+ }
+ }
+}
+
+static void fixup_pcirc_node(struct acpi_iort_node *node)
+{
+ struct acpi_iort_id_mapping *idmap = NULL;
+ struct acpi_iort_node *onode;
+ int i=0;
+
+ for (i=0; i < node->mapping_count; i++) {
+ if(!idmap)
+ idmap = (struct acpi_iort_id_mapping*)((u8*)node +
+ + node->mapping_offset);
+ else
+ idmap++;
+
+ onode = (struct acpi_iort_node*)(iort_base_ptr +
+ idmap->output_reference);
+ switch (onode->type)
+ {
+ case ACPI_IORT_NODE_ITS_GROUP:
+ continue;
+ case ACPI_IORT_NODE_SMMU:
+ case ACPI_IORT_NODE_SMMU_V3:
+ patch_output_ref(idmap, onode);
+ break;
+ }
+ }
+}
+
+static int hide_smmu_iort(void)
+{
+ u32 i;
+ u32 node_offset = 0;
+ struct acpi_table_iort *iort_table;
+ struct acpi_iort_node *node = NULL;
+
+ iort_table = (struct acpi_table_iort *)iort_base_ptr;
+
+ for (i=0; i < iort_table->node_count; i++) {
+ if (!node){
+ node = (struct acpi_iort_node *)(iort_base_ptr +
+ iort_table->node_offset);
+ node_offset = iort_table->node_offset;
+ } else {
+ node = (struct acpi_iort_node *)(iort_base_ptr +
+ node_offset);
+ }
+
+ node_offset += node->length;
+ if (node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX)
+ fixup_pcirc_node(node);
+ }
+
+ node_offset = 0;
+ node = NULL;
+ for (i=0; i < iort_table->node_count; i++) {
+ if (!node){
+ node = (struct acpi_iort_node *)(iort_base_ptr +
+ iort_table->node_offset);
+ node_offset = iort_table->node_offset;
+ } else {
+ node = (struct acpi_iort_node *)(iort_base_ptr +
+ node_offset);
+ }
+ node_offset += node->length;
+ if ((node->type == ACPI_IORT_NODE_SMMU) ||
+ (node->type == ACPI_IORT_NODE_SMMU_V3))
+ node->type = ACPI_IORT_NODE_RESERVED;
+ }
+
+ return 0;
+}
+
static int acpi_iomem_deny_access(struct domain *d)
{
acpi_status status;
@@ -1348,7 +1439,12 @@ static int acpi_iomem_deny_access(struct domain *d)
if ( rc )
return rc;
- /* TODO: Deny MMIO access for SMMU, GIC ITS */
+ /* Hide SMMU from IORT */
+ rc = hide_smmu_iort();
+ if (rc)
+ return rc;
+
+ /* Deny MMIO access for GIC ITS */
status = acpi_get_table(ACPI_SIG_SPCR, 0,
(struct acpi_table_header **)&spcr);
@@ -1646,6 +1742,8 @@ static int acpi_create_xsdt(struct domain *d,
struct membank tbl_add[])
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);
+ acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count,
+ ACPI_SIG_IORT, tbl_add[TBL_IORT].start);
xsdt->table_offset_entry[entry_count] = tbl_add[TBL_STAO].start;
xsdt->header.length = table_size;
@@ -1794,11 +1892,23 @@ static int estimate_acpi_efi_size(struct domain
*d, struct kernel_info *kinfo)
{
size_t efi_size, acpi_size, madt_size;
u64 addr;
+ acpi_status status;
struct acpi_table_rsdp *rsdp_tbl;
struct acpi_table_header *table;
+ struct acpi_table_header *iort_table;
efi_size = estimate_efi_size(kinfo->mem.nr_banks);
+ status = acpi_get_table(ACPI_SIG_IORT, 0, &iort_table);
+
+ if ( ACPI_FAILURE(status) )
+ {
+ const char *msg = acpi_format_exception(status);
+
+ printk("Failed to get IORT table, %s\n", msg);
+ return -EINVAL;
+ }
+
acpi_size = ROUNDUP(sizeof(struct acpi_table_fadt), 8);
acpi_size += ROUNDUP(sizeof(struct acpi_table_stao), 8);
@@ -1839,6 +1949,8 @@ static int estimate_acpi_efi_size(struct domain
*d, struct kernel_info *kinfo)
acpi_size += ROUNDUP(table->length + sizeof(u64), 8);
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+ /* Add size of iort */
+ acpi_size += iort_table->length;
acpi_size += ROUNDUP(sizeof(struct acpi_table_rsdp), 8);
d->arch.efi_acpi_len = PAGE_ALIGN(ROUNDUP(efi_size, 8)
+ ROUNDUP(acpi_size, 8));
@@ -1846,6 +1958,30 @@ static int estimate_acpi_efi_size(struct domain
*d, struct kernel_info *kinfo)
return 0;
}
+static int acpi_create_iort(struct domain *d, struct membank tbl_add[])
+{
+ struct acpi_table_header *table;
+ acpi_status status;
+
+ status = acpi_get_table(ACPI_SIG_IORT, 0,
+ (struct acpi_table_header **)&table);
+ if ( ACPI_FAILURE(status) )
+ {
+ printk("Failed to get IORT table\n");
+ return -EINVAL;
+ }
+
+ iort_base_ptr = d->arch.efi_acpi_table
+ + acpi_get_table_offset(tbl_add, TBL_IORT);
+ ACPI_MEMCPY(iort_base_ptr, table, table->length);
+
+ tbl_add[TBL_IORT].start = d->arch.efi_acpi_gpa
+ + acpi_get_table_offset(tbl_add, TBL_IORT);
+ tbl_add[TBL_IORT].size = table->length;
+
+ return 0;
+}
+
static int prepare_acpi(struct domain *d, struct kernel_info *kinfo)
{
int rc = 0;
@@ -1889,6 +2025,10 @@ static int prepare_acpi(struct domain *d, struct
kernel_info *kinfo)
if ( rc != 0 )
return rc;
+ rc = acpi_create_iort(d, tbl_add);
+ if ( rc != 0 )
+ return rc;
+
rc = acpi_create_xsdt(d, tbl_add);
if ( rc != 0 )
return rc;
diff --git a/xen/include/acpi/actbl2.h b/xen/include/acpi/actbl2.h
index 42beac4..f180ea5 100644
--- a/xen/include/acpi/actbl2.h
+++ b/xen/include/acpi/actbl2.h
@@ -591,7 +591,8 @@ enum acpi_iort_node_type {
ACPI_IORT_NODE_NAMED_COMPONENT = 0x01,
ACPI_IORT_NODE_PCI_ROOT_COMPLEX = 0x02,
ACPI_IORT_NODE_SMMU = 0x03,
- ACPI_IORT_NODE_SMMU_V3 = 0x04
+ ACPI_IORT_NODE_SMMU_V3 = 0x04,
+ ACPI_IORT_NODE_RESERVED = 0xff
};
struct acpi_iort_id_mapping {
diff --git a/xen/include/asm-arm/acpi.h b/xen/include/asm-arm/acpi.h
index 9f954d3..1cc0167 100644
--- a/xen/include/asm-arm/acpi.h
+++ b/xen/include/asm-arm/acpi.h
@@ -36,6 +36,7 @@ typedef enum {
TBL_FADT,
TBL_MADT,
TBL_STAO,
+ TBL_IORT,
TBL_XSDT,
TBL_RSDP,
TBL_EFIT,
--
2.7.4
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel