From: Ruslan Ruslichenko <[email protected]> Register custom 'smmu_gerror_cmdq' handler within plugin subsystem.
This enables external plugins to dynamically inject Command Queue errors and trigger GERROR interrupts. Signed-off-by: Ruslan Ruslichenko <[email protected]> --- hw/arm/smmuv3.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index c08d58c579..e80b80e843 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -27,6 +27,8 @@ #include "hw/pci/pci.h" #include "cpu.h" #include "exec/target_page.h" +#include "qemu/plugin.h" +#include "qom/object.h" #include "trace.h" #include "qemu/log.h" #include "qemu/error-report.h" @@ -42,6 +44,55 @@ ((ptw_info).stage == SMMU_STAGE_2 && \ (cfg)->s2cfg.record_faults)) +static void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, + uint32_t gerror_mask); + +typedef struct { + uint64_t base_addr; + Object *found_obj; +} SMMUSearchArgs; + +static int smmu_match_addr_cb(Object *obj, void *opaque) +{ + SMMUSearchArgs *args = (SMMUSearchArgs *)opaque; + + if (object_dynamic_cast(obj, TYPE_ARM_SMMUV3)) { + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + if (sbd->mmio[0].addr == args->base_addr) { + args->found_obj = obj; + return 1; + } + } + + return 0; +} + +static void smmu_inject_gerror_cmdq(void *target_data, void *fault_data) +{ + uint64_t base_address = *(uint64_t *)target_data; + SMMUCmdError cmd_error = *(SMMUCmdError*)fault_data; + Object *obj = NULL; + + if (base_address) { + SMMUSearchArgs args = { .base_addr = base_address, .found_obj = NULL }; + object_child_foreach_recursive(object_get_root(), smmu_match_addr_cb, &args); + + obj = args.found_obj; + } else { + obj = object_resolve_path_type("", TYPE_ARM_SMMUV3, NULL); + } + + if (!obj) { + return; + } + + SMMUv3State *s = ARM_SMMUV3(obj); + + smmu_write_cmdq_err(s, cmd_error); + smmuv3_trigger_irq(s, SMMU_IRQ_GERROR, R_GERROR_CMDQ_ERR_MASK); +} + /** * smmuv3_trigger_irq - pulse @irq if enabled and update * GERROR register in case of GERROR interrupt @@ -2130,6 +2181,9 @@ static void smmuv3_class_init(ObjectClass *klass, const void *data) dc->hotpluggable = false; dc->user_creatable = true; + plugin_register_custom_fault("smmu_gerror_cmdq", + smmu_inject_gerror_cmdq); + object_class_property_set_description(klass, "accel", "Enable SMMUv3 accelerator support. Allows host SMMUv3 to be " "configured in nested mode for vfio-pci dev assignment"); -- 2.43.0
