On Mon, 26 Jan 2026, Oleksii Moisieiev wrote:
> On 23/01/2026 03:51, Stefano Stabellini wrote:
> > Not a full review, but I found three issues plus some spurious changes
> >
> >
> > On Wed, 21 Jan 2026, Oleksii Moisieiev wrote:
> >> diff --git a/docs/misc/xen-command-line.pandoc 
> >> b/docs/misc/xen-command-line.pandoc
> >> index 15f7a315a4..268df3010b 100644
> >> --- a/docs/misc/xen-command-line.pandoc
> >> +++ b/docs/misc/xen-command-line.pandoc
> >> @@ -789,7 +789,7 @@ Specify the bit width of the DMA heap.
> >>                   cpuid-faulting=<bool>, msr-relaxed=<bool>,
> >>                   pf-fixup=<bool> ] (x86)
> >>   
> >> -    = List of [ sve=<integer> ] (Arm64)
> >> +    = List of [ sve=<integer> ] (Arm)
> >>   
> >>   Controls for how dom0 is constructed on x86 systems.
> > Spurious change
> >
> >
> >> diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c
> >> index e4407d6e3f..be0e6263ae 100644
> >> --- a/tools/libs/light/libxl_arm.c
> >> +++ b/tools/libs/light/libxl_arm.c
> >> @@ -240,6 +240,10 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
> >>       case LIBXL_ARM_SCI_TYPE_SCMI_SMC:
> >>           config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC;
> >>           break;
> >> +    case LIBXL_ARM_SCI_TYPE_SCMI_SMC_MULTIAGENT:
> >> +        config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA;
> >> +        config->arch.arm_sci_agent_id = 
> >> d_config->b_info.arch_arm.arm_sci.agent_id;
> >> +        break;
> >>       default:
> >>           LOG(ERROR, "Unknown ARM_SCI type %d",
> >>               d_config->b_info.arch_arm.arm_sci.type);
> >> diff --git a/tools/libs/light/libxl_types.idl 
> >> b/tools/libs/light/libxl_types.idl
> >> index 4a958f69f4..9bfbf09145 100644
> >> --- a/tools/libs/light/libxl_types.idl
> >> +++ b/tools/libs/light/libxl_types.idl
> >> @@ -554,11 +554,13 @@ libxl_sve_type = Enumeration("sve_type", [
> >>   
> >>   libxl_arm_sci_type = Enumeration("arm_sci_type", [
> >>       (0, "none"),
> >> -    (1, "scmi_smc")
> >> +    (1, "scmi_smc"),
> >> +    (2, "scmi_smc_multiagent")
> >>       ], init_val = "LIBXL_ARM_SCI_TYPE_NONE")
> >>   
> >>   libxl_arm_sci = Struct("arm_sci", [
> >>       ("type", libxl_arm_sci_type),
> >> +    ("agent_id", uint8)
> >>       ])
> >>   
> >>   libxl_rdm_reserve = Struct("rdm_reserve", [
> >> diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
> >> index 1cc41f1bff..0c389d25f9 100644
> >> --- a/tools/xl/xl_parse.c
> >> +++ b/tools/xl/xl_parse.c
> >> @@ -1306,6 +1306,18 @@ static int parse_arm_sci_config(XLU_Config *cfg, 
> >> libxl_arm_sci *arm_sci,
> >>               }
> >>           }
> >>   
> >> +        if (MATCH_OPTION("agent_id", ptr, oparg)) {
> >> +            unsigned long val = parse_ulong(oparg);
> >> +
> >> +            if (!val || val > 255) {
> >> +                fprintf(stderr, "An invalid ARM_SCI agent_id specified 
> >> (%lu). Valid range [1..255]\n",
> >> +                        val);
> >> +                ret = ERROR_INVAL;
> >> +                goto out;
> >> +            }
> >> +            arm_sci->agent_id = val;
> >> +        }
> >> +
> >>           ptr = strtok(NULL, ",");
> >>       }
> >>   
> >> diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
> >> index 4181c10538..ddadc89148 100644
> >> --- a/xen/arch/arm/dom0less-build.c
> >> +++ b/xen/arch/arm/dom0less-build.c
> >> @@ -299,6 +299,17 @@ static int __init domu_dt_sci_parse(struct 
> >> dt_device_node *node,
> >>           d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE;
> >>       else if ( !strcmp(sci_type, "scmi_smc") )
> >>           d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC;
> >> +    else if ( !strcmp(sci_type, "scmi_smc_multiagent") )
> >> +    {
> >> +        uint32_t agent_id = 0;
> >> +
> >> +        if ( !dt_property_read_u32(node, "xen,sci-agent-id", &agent_id) ||
> >> +             agent_id > UINT8_MAX )
> >> +            return -EINVAL;
> >> +
> >> +        d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA;
> >> +        d_cfg->arch.arm_sci_agent_id = agent_id;
> >> +    }
> >>       else
> >>       {
> >>           printk(XENLOG_ERR "xen,sci_type in not valid (%s) for domain 
> >> %s\n",
> >> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> >> index 986a456f17..0796561306 100644
> >> --- a/xen/arch/arm/domain_build.c
> >> +++ b/xen/arch/arm/domain_build.c
> >> @@ -86,6 +86,37 @@ int __init parse_arch_dom0_param(const char *s, const 
> >> char *e)
> >>       return -EINVAL;
> >>   }
> >>   
> >> +/* SCMI agent ID for dom0 obtained from xen,sci container */
> >> +#define SCMI_AGENT_ID_INVALID UINT8_MAX
> >> +
> >> +static uint8_t __init get_dom0_scmi_agent_id(void)
> >> +{
> >> +    const struct dt_device_node *config_node;
> >> +    u32 val;
> >> +    const struct dt_property *prop;
> >> +
> >> +    config_node = dt_find_compatible_node(NULL, NULL, "xen,sci");
> >> +    if ( !config_node )
> >> +        return SCMI_AGENT_ID_INVALID;
> >> +
> >> +    prop = dt_find_property(config_node, "xen,dom0-sci-agent-id", NULL);
> >> +    if ( !prop )
> >> +        return SCMI_AGENT_ID_INVALID;
> >> +
> >> +    if ( !dt_property_read_u32(config_node, "xen,dom0-sci-agent-id", 
> >> &val) )
> >> +        return SCMI_AGENT_ID_INVALID;
> >> +
> >> +    if ( val >= SCMI_AGENT_ID_INVALID )
> >> +    {
> >> +         printk(XENLOG_WARNING
> >> +             "Invalid xen,dom0-sci-agent-id=%u, SCMI disabled for Dom0\n",
> >> +             val);
> >> +        return SCMI_AGENT_ID_INVALID;
> >> +    }
> >> +
> >> +    return val;
> >> +}
> >> +
> >>   /* Override macros from asm/page.h to make them work with mfn_t */
> >>   #undef virt_to_mfn
> >>   #define virt_to_mfn(va) _mfn(__virt_to_mfn(va))
> >> @@ -509,7 +540,7 @@ static int __init write_properties(struct domain *d, 
> >> struct kernel_info *kinfo,
> >>                    dt_property_name_is_equal(prop, 
> >> "linux,uefi-mmap-start") ||
> >>                    dt_property_name_is_equal(prop, "linux,uefi-mmap-size") 
> >> ||
> >>                    dt_property_name_is_equal(prop, 
> >> "linux,uefi-mmap-desc-size") ||
> >> -                 dt_property_name_is_equal(prop, 
> >> "linux,uefi-mmap-desc-ver"))
> >> +                 dt_property_name_is_equal(prop, 
> >> "linux,uefi-mmap-desc-ver") )
> >>                   continue;
> > Spurious change
> >
> >
> >> +static int scmi_dt_assign_device(struct domain *d,
> >> +                                 struct dt_phandle_args *ac_spec)
> >> +{
> >> +    struct scmi_channel *agent_channel;
> >> +    uint32_t scmi_device_id = ac_spec->args[0];
> >> +    int ret;
> >> +
> >> +    if ( !d->arch.sci_data )
> >> +        return 0;
> >> +
> >> +    /* The access-controllers is specified for DT dev, but it's not a 
> >> SCMI */
> >> +    if ( ac_spec->np != scmi_data.dt_dev )
> >> +        return 0;
> > This comparison can erroneously fail when the pointers point to
> > different copies of the same data
> >
> >
> >> +    agent_channel = d->arch.sci_data;
> >> +
> >> +    spin_lock(&agent_channel->lock);
> >> +
> >> +    ret = scmi_assign_device(agent_channel->agent_id, scmi_device_id,
> >> +                             SCMI_BASE_DEVICE_ACCESS_ALLOW);
> >> +    if ( ret )
> >> +    {
> >> +        printk(XENLOG_ERR
> >> +               "scmi: could not assign dev for %pd agent:%d dev_id:%u 
> >> (%d)",
> >> +               d, agent_channel->agent_id, scmi_device_id, ret);
> >> +    }
> >> +
> >> +    spin_unlock(&agent_channel->lock);
> >> +    return ret;
> >> +}
> >> +
> >> +static int collect_agent_id(struct scmi_channel *agent_channel)
> >> +{
> >> +    int ret;
> >> +    scmi_msg_header_t hdr;
> >> +    struct scmi_msg_base_discover_agent_p2a da_rx;
> >> +    struct scmi_msg_base_discover_agent_a2p da_tx;
> >> +
> >> +    ret = map_channel_memory(agent_channel);
> >> +    if ( ret )
> >> +        return ret;
> >> +
> >> +    hdr.id = SCMI_BASE_DISCOVER_AGENT;
> >> +    hdr.type = 0;
> >> +    hdr.protocol = SCMI_BASE_PROTOCOL;
> >> +
> >> +    da_tx.agent_id = agent_channel->agent_id;
> >> +
> >> +    ret = do_smc_xfer(agent_channel, &hdr, &da_tx, sizeof(da_tx), &da_rx,
> >> +                        sizeof(da_rx));
> >> +    if ( agent_channel->domain_id != DOMID_XEN )
> >> +        unmap_channel_memory(agent_channel);
> >> +    if ( ret )
> >> +        return ret;
> >> +
> >> +    printk(XENLOG_DEBUG "id=0x%x name=%s\n", da_rx.agent_id, da_rx.name);
> >> +    agent_channel->agent_id = da_rx.agent_id;
> >> +    return 0;
> >> +}
> >> +
> >> +static __init int collect_agents(struct dt_device_node *scmi_node)
> >> +{
> >> +    const struct dt_device_node *config_node;
> >> +    const __be32 *prop;
> >> +    uint32_t len;
> >> +    const __be32 *end;
> >> +    uint32_t cells_per_entry = 3; /* Default to 3 cells if property is 
> >> absent. */
> >> +
> >> +    config_node = dt_find_compatible_node(NULL, NULL, "xen,sci");
> >> +    if ( !config_node )
> >> +    {
> >> +        printk(XENLOG_WARNING "scmi: xen,sci node not found, no agents to 
> >> collect.\n");
> >> +        return -ENOENT;
> >> +    }
> >> +
> >> +    /* Check for the optional '#scmi-secondary-agents-cells' property. */
> >> +    if ( dt_property_read_u32(config_node, "#scmi-secondary-agents-cells",
> >> +                              &cells_per_entry) )
> >> +    {
> >> +        if ( cells_per_entry != 2 && cells_per_entry != 3 )
> >> +        {
> >> +            printk(XENLOG_ERR "scmi: Invalid #scmi-secondary-agents-cells 
> >> value: %u\n",
> >> +                   cells_per_entry);
> >> +            return -EINVAL;
> >> +        }
> >> +    }
> >> +
> >> +    prop = dt_get_property(config_node, SCMI_SECONDARY_AGENTS, &len);
> >> +    if ( !prop )
> >> +    {
> >> +        printk(XENLOG_ERR "scmi: No %s property found, no agents to 
> >> collect.\n",
> >> +               SCMI_SECONDARY_AGENTS);
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    /* Validate that the property length is a multiple of the cell size. 
> >> */
> >> +    if ( len == 0 || len % (cells_per_entry * sizeof(uint32_t)) != 0 )
> >> +    {
> >> +        printk(XENLOG_ERR "scmi: Invalid length of %s property: %u for %u 
> >> cells per entry\n",
> >> +               SCMI_SECONDARY_AGENTS, len, cells_per_entry);
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    end = (const __be32 *)((const u8 *)prop + len);
> >> +
> >> +    for ( ; prop < end; )
> >> +    {
> >> +        uint32_t agent_id;
> >> +        uint32_t smc_id;
> >> +        uint32_t shmem_phandle;
> >> +        struct dt_device_node *node;
> >> +        u64 addr, size;
> >> +        int ret;
> >> +        struct scmi_channel *agent_channel;
> >> +
> >> +        smc_id = be32_to_cpu(*prop++);
> >> +        shmem_phandle = be32_to_cpu(*prop++);
> >> +
> >> +        if ( cells_per_entry == 3 )
> >> +            agent_id = be32_to_cpu(*prop++);
> >> +        else
> >> +            agent_id = SCMI_BASE_AGENT_ID_OWN;
> >> +
> >> +        node = dt_find_node_by_phandle(shmem_phandle);
> >> +        if ( !node )
> >> +        {
> >> +            printk(XENLOG_ERR "scmi: Could not find shmem node for agent 
> >> %u\n",
> >> +                   agent_id);
> >> +            return -EINVAL;
> >> +        }
> >> +
> >> +        ret = dt_device_get_address(node, 0, &addr, &size);
> >> +        if ( ret )
> >> +        {
> >> +            printk(XENLOG_ERR
> >> +                   "scmi: Could not read shmem address for agent %u: 
> >> %d\n",
> >> +                   agent_id, ret);
> >> +            return ret;
> >> +        }
> >> +
> >> +        if ( !IS_ALIGNED(size, SCMI_SHMEM_MAPPED_SIZE) )
> >> +        {
> >> +            printk(XENLOG_ERR "scmi: shmem memory is not aligned\n");
> >> +            return -EINVAL;
> >> +        }
> >> +
> >> +        agent_channel = smc_create_channel(agent_id, smc_id, addr);
> >> +        if ( IS_ERR(agent_channel) )
> >> +        {
> >> +            printk(XENLOG_ERR "scmi: Could not create channel for agent 
> >> %u: %ld\n",
> >> +                   agent_id, PTR_ERR(agent_channel));
> >> +            return PTR_ERR(agent_channel);
> >> +        }
> >> +
> >> +        if ( cells_per_entry == 2 )
> >> +        {
> >> +            ret = collect_agent_id(agent_channel);
> >> +            if ( ret )
> >> +                return ret;
> >> +        }
> >> +
> >> +        printk(XENLOG_DEBUG "scmi: Agent %u SMC %X addr %lx\n", 
> >> agent_channel->agent_id,
> >> +               smc_id, (unsigned long)addr);
> >> +    }
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static int scmi_domain_init(struct domain *d,
> >> +                            struct xen_domctl_createdomain *config)
> >> +{
> >> +    struct scmi_channel *channel;
> >> +    int ret;
> >> +
> >> +    if ( !scmi_data.initialized )
> >> +        return 0;
> >> +
> >> +    /*
> >> +     * SCMI support is configured via:
> >> +     * - For dom0: xen,dom0-sci-agent-id property under the xen,sci 
> >> container
> >> +     * - For dom0less: xen,sci-agent-id in the domain node
> >> +     * The config->arch.arm_sci_type and config->arch.arm_sci_agent_id
> >> +     * are already set by domain_build.c or dom0less-build.c
> >> +     */
> >> +
> >> +    if ( config->arch.arm_sci_type == XEN_DOMCTL_CONFIG_ARM_SCI_NONE )
> >> +        return 0;
> >> +
> >> +    channel = acquire_scmi_channel(d, config->arch.arm_sci_agent_id);
> >> +    if ( IS_ERR(channel) )
> >> +    {
> >> +        printk(XENLOG_ERR
> >> +               "scmi: Failed to acquire SCMI channel for agent_id %u: 
> >> %ld\n",
> >> +               config->arch.arm_sci_agent_id, PTR_ERR(channel));
> >> +        return PTR_ERR(channel);
> >> +    }
> >> +
> >> +    printk(XENLOG_INFO
> >> +           "scmi: Acquire channel id = 0x%x, domain_id = %d paddr = 
> >> 0x%lx\n",
> >> +           channel->agent_id, channel->domain_id, channel->paddr);
> >> +
> >> +    /*
> >> +     * Dom0 (if present) needs to have an access to the guest memory range
> >> +     * to satisfy iomem_access_permitted() check in 
> >> XEN_DOMCTL_iomem_permission
> >> +     * domctl.
> >> +     */
> >> +    if ( hardware_domain && !is_hardware_domain(d) )
> >> +    {
> >> +        ret = iomem_permit_access(hardware_domain, 
> >> paddr_to_pfn(channel->paddr),
> >> +                                  paddr_to_pfn(channel->paddr + PAGE_SIZE 
> >> - 1));
> >> +        if ( ret )
> >> +            goto error;
> >> +    }
> >> +
> >> +    d->arch.sci_data = channel;
> >> +    d->arch.sci_enabled = true;
> >> +
> >> +    return 0;
> >> +
> >> +error:
> >> +    relinquish_scmi_channel(channel);
> >> +    return ret;
> >> +}
> >> +
> >> +int scmi_domain_sanitise_config(struct xen_domctl_createdomain *config)
> >> +{
> >> +    if ( config->arch.arm_sci_type != XEN_DOMCTL_CONFIG_ARM_SCI_NONE &&
> >> +         config->arch.arm_sci_type != 
> >> XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA )
> >> +    {
> >> +        dprintk(XENLOG_INFO, "scmi: Unsupported ARM_SCI type\n");
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static int scmi_relinquish_resources(struct domain *d)
> >> +{
> >> +    int ret;
> >> +    struct scmi_channel *channel, *agent_channel;
> >> +    scmi_msg_header_t hdr;
> >> +    struct scmi_msg_base_reset_agent_cfg_a2p tx;
> >> +
> >> +    if ( !d->arch.sci_data )
> >> +        return 0;
> >> +
> >> +    agent_channel = d->arch.sci_data;
> >> +
> >> +    spin_lock(&agent_channel->lock);
> >> +    tx.agent_id = agent_channel->agent_id;
> >> +    spin_unlock(&agent_channel->lock);
> >> +
> >> +    channel = get_channel_by_id(scmi_data.hyp_channel_agent_id);
> >> +    if ( !channel )
> >> +    {
> >> +        printk(XENLOG_ERR
> >> +               "scmi: Unable to get Hypervisor scmi channel for domain 
> >> %d\n",
> >> +               d->domain_id);
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    hdr.id = SCMI_BASE_RESET_AGENT_CONFIGURATION;
> >> +    hdr.type = 0;
> >> +    hdr.protocol = SCMI_BASE_PROTOCOL;
> >> +
> >> +    tx.flags = 0;
> > is this correct?
> >
> >
> >> +    ret = do_smc_xfer(channel, &hdr, &tx, sizeof(tx), NULL, 0);
> >> +    if ( ret == -EOPNOTSUPP )
> >> +        return 0;
> >> +
> >> +    return ret;
> >> +}
> >> +
> >> +static void scmi_domain_destroy(struct domain *d)
> >> +{
> >> +    struct scmi_channel *channel;
> >> +
> >> +    if ( !d->arch.sci_data )
> >> +        return;
> >> +
> >> +    channel = d->arch.sci_data;
> >> +    spin_lock(&channel->lock);
> >> +
> >> +    relinquish_scmi_channel(channel);
> >> +    printk(XENLOG_DEBUG "scmi: Free domain %d\n", d->domain_id);
> >> +
> >> +    d->arch.sci_data = NULL;
> >> +    d->arch.sci_enabled = false;
> >> +
> >> +    spin_unlock(&channel->lock);
> >> +}
> >> +
> >> +static bool scmi_handle_call(struct cpu_user_regs *regs)
> >> +{
> >> +    uint32_t fid = (uint32_t)get_user_reg(regs, 0);
> >> +    struct scmi_channel *agent_channel;
> >> +    struct domain *d = current->domain;
> >> +    struct arm_smccc_res resp;
> >> +    bool res = false;
> >> +
> >> +    if ( !sci_domain_is_enabled(d) )
> >> +        return false;
> >> +
> >> +    agent_channel = d->arch.sci_data;
> >> +    spin_lock(&agent_channel->lock);
> >> +
> >> +    if ( agent_channel->func_id != fid )
> >> +    {
> >> +        res = false;
> >> +        goto unlock;
> >> +    }
> >> +
> >> +    arm_smccc_1_1_smc(fid,
> >> +                      get_user_reg(regs, 1),
> >> +                      get_user_reg(regs, 2),
> >> +                      get_user_reg(regs, 3),
> >> +                      get_user_reg(regs, 4),
> >> +                      get_user_reg(regs, 5),
> >> +                      get_user_reg(regs, 6),
> >> +                      get_user_reg(regs, 7),
> >> +                      &resp);
> >> +
> >> +    set_user_reg(regs, 0, resp.a0);
> >> +    set_user_reg(regs, 1, resp.a1);
> >> +    set_user_reg(regs, 2, resp.a2);
> >> +    set_user_reg(regs, 3, resp.a3);
> >> +    res = true;
> >> +unlock:
> >> +    spin_unlock(&agent_channel->lock);
> >> +
> >> +    return res;
> >> +}
> >> +
> >> +static const struct sci_mediator_ops scmi_ops = {
> >> +    .domain_init = scmi_domain_init,
> >> +    .domain_destroy = scmi_domain_destroy,
> >> +    .relinquish_resources = scmi_relinquish_resources,
> >> +    .handle_call = scmi_handle_call,
> >> +    .dom0_dt_handle_node = scmi_dt_handle_node,
> >> +    .domain_sanitise_config = scmi_domain_sanitise_config,
> >> +    .assign_dt_device = scmi_dt_assign_device,
> >> +};
> >> +
> >> +static int __init scmi_check_smccc_ver(void)
> >> +{
> >> +    if ( smccc_ver < ARM_SMCCC_VERSION_1_1 )
> >> +    {
> >> +        printk(XENLOG_WARNING
> >> +               "scmi: No SMCCC 1.1 support, SCMI calls forwarding 
> >> disabled\n");
> >> +        return -ENOSYS;
> >> +    }
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static int __init scmi_dt_hyp_channel_read(struct dt_device_node 
> >> *scmi_node,
> >> +                                           struct scmi_data *scmi_data,
> >> +                                           u64 *addr)
> >> +{
> >> +    int ret;
> >> +    u64 size;
> >> +
> >> +    if ( !dt_property_read_u32(scmi_node, "arm,smc-id", 
> >> &scmi_data->func_id) )
> >> +    {
> >> +        printk(XENLOG_ERR "scmi: unable to read smc-id from DT\n");
> >> +        return -ENOENT;
> >> +    }
> >> +
> >> +    ret = scmi_dt_read_hyp_channel_addr(scmi_node, addr, &size);
> >> +    if ( IS_ERR_VALUE(ret) )
> >> +        return -ENOENT;
> >> +
> >> +    if ( !IS_ALIGNED(size, SCMI_SHMEM_MAPPED_SIZE) )
> >> +    {
> >> +        printk(XENLOG_ERR "scmi: shmem memory is not aligned\n");
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static __init int scmi_probe(struct dt_device_node *scmi_node, const void 
> >> *data)
> >> +{
> >> +    u64 addr;
> >> +    int ret;
> >> +    struct scmi_channel *channel;
> >> +    unsigned int n_agents;
> >> +    scmi_msg_header_t hdr;
> >> +    struct scmi_msg_base_attributes_p2a rx;
> >> +
> >> +    ASSERT(scmi_node != NULL);
> >> +
> >> +    /*
> >> +     * Only bind to the SCMI node provided by Xen under the xen,sci 
> >> container
> >> +     * (e.g. /chosen/xen/xen_scmi_config/scmi). This avoids binding to 
> >> firmware
> >> +     * SCMI nodes that belong to the host OSPM and keeps the mediator 
> >> scoped to
> >> +     * Xen-provided configuration only.
> >> +     */
> >> +    if ( !scmi_is_under_xen_sci(scmi_node) )
> >> +        return -ENODEV;
> >> +
> >> +    INIT_LIST_HEAD(&scmi_data.channel_list);
> >> +    spin_lock_init(&scmi_data.channel_list_lock);
> >> +
> >> +    if ( !acpi_disabled )
> >> +    {
> >> +        printk(XENLOG_WARNING "scmi: is not supported when using ACPI\n");
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    ret = scmi_check_smccc_ver();
> >> +    if ( ret )
> >> +        return ret;
> >> +
> >> +    ret = scmi_dt_hyp_channel_read(scmi_node, &scmi_data, &addr);
> >> +    if ( ret )
> >> +        return ret;
> >> +
> >> +    scmi_data.dt_dev = scmi_node;
> >> +
> >> +    channel = smc_create_channel(SCMI_BASE_AGENT_ID_OWN, 
> >> scmi_data.func_id, addr);
> >> +    if ( IS_ERR(channel) )
> >> +        goto out;
> >> +
> >> +    /* Mark as Xen management channel before collecting agent ID */
> >> +    channel->domain_id = DOMID_XEN;
> >> +
> >> +    /* Request agent id for Xen management channel  */
> >> +    ret = collect_agent_id(channel);
> >> +    if ( ret )
> >> +        goto error;
> >> +
> >> +    /* Save the agent id for Xen management channel */
> >> +    scmi_data.hyp_channel_agent_id = channel->agent_id;
> >> +
> >> +    hdr.id = SCMI_BASE_PROTOCOL_ATTIBUTES;
> >> +    hdr.type = 0;
> >> +    hdr.protocol = SCMI_BASE_PROTOCOL;
> >> +
> >> +    ret = do_smc_xfer(channel, &hdr, NULL, 0, &rx, sizeof(rx));
> >> +    if ( ret )
> >> +        goto error;
> >> +
> >> +    n_agents = SCMI_FIELD_GET(SCMI_BASE_ATTR_NUM_AGENT, rx.attributes);
> >> +    printk(XENLOG_DEBUG "scmi: Got agent count %d\n", n_agents);
> >> +    ret = collect_agents(scmi_node);
> >> +    if ( ret )
> >> +        goto error;
> >> +
> >> +    ret = sci_register(&scmi_ops);
> >> +    if ( ret )
> >> +    {
> >> +        printk(XENLOG_ERR "SCMI: mediator already registered (ret = 
> >> %d)\n",
> >> +               ret);
> >> +        return ret;
> >> +    }
> >> +
> >> +    scmi_data.initialized = true;
> >> +    goto out;
> >> +
> >> +error:
> >> +    unmap_channel_memory(channel);
> > This might cause the ASSERT at the beginning of unmap_channel_memory to
> > trigger
> >
> >
> Great finding... First `goto error` could be called after 
> `collect_agent_id`.
> So in case if we receive -ENOMEM from `ioremap_nocache` inside 
> `map_channel_memory`
> ASSERT will fire.
> 
> I'm planning to refactor this as follows:
> 
>      static void unmap_channel_memory(struct scmi_channel *channel)
>      {
>          ASSERT(channel);
> 
>          if ( !channel->shmem )
>              return;
>          ...
>       }
> 
> This will cause function to skip iounmap if shmem is NULL;
> What do you think?

Yes that's better

Reply via email to