On 21.05.2025 18:03, Oleksii Kurochko wrote:
> +static void aplic_set_irq_affinity(struct irq_desc *desc, const cpumask_t 
> *mask)
> +{
> +    unsigned int cpu;
> +    uint64_t group_index, base_ppn;
> +    uint32_t hhxw, lhxw ,hhxs, value;

Nit: Comma vs blank placement.

> +    const struct imsic_config *imsic = aplic.imsic_cfg;
> +
> +    /*
> +     * TODO: Currently, APLIC is supported only with MSI interrupts.
> +     *       If APLIC without MSI interrupts is required in the future,
> +     *       this function will need to be updated accordingly.
> +     */
> +    ASSERT(readl(&aplic.regs->domaincfg) & APLIC_DOMAINCFG_DM);
> +
> +    ASSERT(!cpumask_empty(mask));
> +
> +    ASSERT(spin_is_locked(&desc->lock));
> +
> +    cpu = cpuid_to_hartid(aplic_get_cpu_from_mask(mask));
> +    hhxw = imsic->group_index_bits;
> +    lhxw = imsic->hart_index_bits;
> +    hhxs = imsic->group_index_shift - IMSIC_MMIO_PAGE_SHIFT * 2;
> +    base_ppn = imsic->msi[cpu].base_addr >> IMSIC_MMIO_PAGE_SHIFT;
> +
> +    /* Update hart and EEID in the target register */
> +    group_index = (base_ppn >> (hhxs + IMSIC_MMIO_PAGE_SHIFT)) & (BIT(hhxw, 
> UL) - 1);

Nit: Line length.

I'm also puzzled by the various uses of IMSIC_MMIO_PAGE_SHIFT. Why do you
subtract double the value when calculating hhxs, just to add the value
back in here? There's no other usee of the variable afaics.

> +    value = desc->irq;
> +    value |= cpu << APLIC_TARGET_HART_IDX_SHIFT;
> +    value |= group_index << (lhxw + APLIC_TARGET_HART_IDX_SHIFT) ;

Nit: Stray blank.

> +    spin_lock(&aplic.lock);
> +
> +    writel(value, &aplic.regs->target[desc->irq - 1]);
> +
> +    spin_unlock(&aplic.lock);
> +}
> +
> +static const hw_irq_controller aplic_xen_irq_type = {
> +    .typename     = "aplic",
> +    .startup      = aplic_irq_startup,
> +    .shutdown     = aplic_irq_disable,
> +    .enable       = aplic_irq_enable,
> +    .disable      = aplic_irq_disable,
> +    .set_affinity = aplic_set_irq_affinity,

As indicated before, for functions you use as hooks you want to save
yourself (or someone else) future work by marking them cf_check right
away.

> --- a/xen/arch/riscv/imsic.c
> +++ b/xen/arch/riscv/imsic.c
> @@ -22,7 +22,124 @@
>  
>  #include <asm/imsic.h>
>  
> -static struct imsic_config imsic_cfg;
> +static struct imsic_config imsic_cfg = {
> +    .lock = SPIN_LOCK_UNLOCKED,
> +};
> +
> +#define IMSIC_DISABLE_EIDELIVERY    0
> +#define IMSIC_ENABLE_EIDELIVERY     1
> +#define IMSIC_DISABLE_EITHRESHOLD   1
> +#define IMSIC_ENABLE_EITHRESHOLD    0
> +
> +#define imsic_csr_write(c, v)   \
> +do {                            \
> +    csr_write(CSR_SISELECT, c); \
> +    csr_write(CSR_SIREG, v);    \
> +} while (0)
> +
> +#define imsic_csr_set(c, v)     \
> +do {                            \
> +    csr_write(CSR_SISELECT, c); \
> +    csr_set(CSR_SIREG, v);      \
> +} while (0)
> +
> +#define imsic_csr_clear(c, v)   \
> +do {                            \
> +    csr_write(CSR_SISELECT, c); \
> +    csr_clear(CSR_SIREG, v);    \
> +} while (0)
> +
> +void __init imsic_ids_local_delivery(bool enable)
> +{
> +    if ( enable )
> +    {
> +        imsic_csr_write(IMSIC_EITHRESHOLD, IMSIC_ENABLE_EITHRESHOLD);
> +        imsic_csr_write(IMSIC_EIDELIVERY, IMSIC_ENABLE_EIDELIVERY);
> +    }
> +    else
> +    {
> +        imsic_csr_write(IMSIC_EITHRESHOLD, IMSIC_DISABLE_EITHRESHOLD);
> +        imsic_csr_write(IMSIC_EIDELIVERY, IMSIC_DISABLE_EIDELIVERY);
> +    }
> +}
> +
> +static void imsic_local_eix_update(unsigned long base_id, unsigned long 
> num_id,
> +                                   bool pend, bool val)
> +{
> +    unsigned long id = base_id, last_id = base_id + num_id;
> +
> +    while ( id < last_id )
> +    {
> +        unsigned long isel, ireg;
> +        unsigned long start_id = id & (__riscv_xlen - 1);
> +        unsigned long chunk = __riscv_xlen - start_id;
> +        unsigned long count = (last_id - id < chunk) ? last_id - id : chunk;

Any reason you open-code min() here?

> +        isel = id / __riscv_xlen;
> +        isel *= __riscv_xlen / IMSIC_EIPx_BITS;
> +        isel += pend ? IMSIC_EIP0 : IMSIC_EIE0;
> +
> +        ireg = GENMASK(start_id + count - 1, start_id);
> +
> +        id += count;
> +
> +        if ( val )
> +            imsic_csr_set(isel, ireg);
> +        else
> +            imsic_csr_clear(isel, ireg);
> +    }
> +}
> +
> +void imsic_irq_enable(unsigned int irq)
> +{
> +    /*
> +    * The only caller of imsic_irq_enable() is aplic_irq_enable(), which
> +    * already runs with IRQs disabled. Therefore, there's no need to use
> +    * spin_lock_irqsave() in this function.
> +    *
> +    * This ASSERT is added as a safeguard: if imsic_irq_enable() is ever
> +    * called from a context where IRQs are not disabled,
> +    * spin_lock_irqsave() should be used instead of spin_lock().
> +    */
> +    ASSERT(!local_irq_is_enabled());
> +
> +    spin_lock(&imsic_cfg.lock);
> +    /*
> +     * There is no irq - 1 here (look at aplic_set_irq_type()) because:
> +     * From the spec:
> +     *   When an interrupt file supports distinct interrupt identities,
> +     *   valid identity numbers are between 1 and inclusive. The identity
> +     *   numbers within this range are said to be implemented by the 
> interrupt
> +     *   file; numbers outside this range are not implemented. The number 
> zero
> +     *   is never a valid interrupt identity.
> +     *   ...
> +     *   Bit positions in a valid eiek register that don’t correspond to a
> +     *   supported interrupt identity (such as bit 0 of eie0) are read-only 
> zeros.
> +     *
> +     * So in EIx registers interrupt i corresponds to bit i in comparison 
> wiht
> +     * APLIC's sourcecfg which starts from 0.
> +     */
> +    imsic_local_eix_update(irq, 1, false, true);
> +    spin_unlock(&imsic_cfg.lock);
> +}
> +
> +void imsic_irq_disable(unsigned int irq)
> +{
> +   /*
> +    * The only caller of imsic_irq_disable() is aplic_irq_enable(), which

s/enable/disable/ ?

Jan

Reply via email to