diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c index 43804a6c7a..f44ee21293 100644 --- a/xen/arch/arm/gic-v3-its.c +++ b/xen/arch/arm/gic-v3-its.c @@ -136,6 +136,21 @@ static const struct its_quirk *__init gicv3_its_find_quirk( return NULL; } +static void __init gicv3_its_collect_fw_attrs(struct host_its *hw_its) +{ + /* + * An ITS subnode property describes memory transactions made by that ITS. + * Do not inherit it into the global host LPI/Redistributor policy. + */ + if ( !hw_its->dt_node || + !dt_property_read_bool(hw_its->dt_node, "dma-noncoherent") ) + return; + + hw_its->quirk_flags |= GICV3_QUIRK_MEM_NC_NS; + printk("GICv3: ITS @%#"PRIpaddr" marked dma-noncoherent\n", + hw_its->addr); +} + static void __init gicv3_its_collect_quirks(struct host_its *hw_its) { const struct its_quirk *quirk = gicv3_its_find_quirk(hw_its); @@ -146,6 +161,8 @@ static void __init gicv3_its_collect_quirks(struct host_its *hw_its) gicv3_lpi_update_host_flags(quirk->lpi_flags); printk("GICv3: enabling workaround for ITS: %s\n", quirk->desc); } + + gicv3_its_collect_fw_attrs(hw_its); } uint64_t gicv3_mem_get_cacheability(uint32_t flags) diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c index accfd48a74..1cf49430ea 100644 --- a/xen/arch/arm/gic-v3-lpi.c +++ b/xen/arch/arm/gic-v3-lpi.c @@ -7,7 +7,9 @@ * Copyright (C) 2016,2017 - ARM Ltd */ +#include #include +#include #include #include #include @@ -102,6 +104,20 @@ void __init gicv3_lpi_update_host_flags(uint32_t flags) host_lpi_flags |= flags; } +static void __init gicv3_lpi_collect_fw_attrs(void) +{ + /* + * A top-level GIC node property describes the Redistributor side of the + * LPI path. Do not inherit it into per-ITS policy. + */ + if ( !acpi_disabled || + !dt_property_read_bool(dt_interrupt_controller, "dma-noncoherent") ) + return; + + gicv3_lpi_update_host_flags(GICV3_QUIRK_MEM_NC_NS); + printk("GICv3: Redistributors marked dma-noncoherent\n"); +} + static union host_lpi *gic_get_host_lpi(uint32_t plpi) { union host_lpi *block; @@ -443,7 +459,7 @@ integer_param("max_lpi_bits", max_lpi_bits); * to the page with the actual "union host_lpi" entries. Our LPI limit * avoids excessive memory usage. */ -int gicv3_lpi_init_host_lpis(unsigned int host_lpi_bits) +int __init gicv3_lpi_init_host_lpis(unsigned int host_lpi_bits) { unsigned int nr_lpi_ptrs; int rc; @@ -451,6 +467,8 @@ int gicv3_lpi_init_host_lpis(unsigned int host_lpi_bits) /* We rely on the data structure being atomically accessible. */ BUILD_BUG_ON(sizeof(union host_lpi) > sizeof(unsigned long)); + gicv3_lpi_collect_fw_attrs(); + /* * An implementation needs to support at least 14 bits of LPI IDs. * Tell the user about it, the actual number is reported below.