[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 13/16] xen/riscv: implementation of aplic and imsic operations
On 06.05.2025 18:51, Oleksii Kurochko wrote: > --- a/xen/arch/riscv/aplic-priv.h > +++ b/xen/arch/riscv/aplic-priv.h > @@ -14,6 +14,7 @@ > #ifndef ASM__RISCV_PRIV_APLIC_H > #define ASM__RISCV_PRIV_APLIC_H > > +#include <xen/spinlock.h> > #include <xen/types.h> > > #include <asm/aplic.h> > @@ -27,6 +28,9 @@ struct aplic_priv { > /* registers */ > volatile struct aplic_regs *regs; > > + /* lock */ > + spinlock_t lock; Nit: I don't see much value in such entirely redundant comments. Useful contents might be to say what the lock actually is intended to guard. > @@ -119,9 +121,118 @@ static int __init cf_check aplic_init(void) > return 0; > } > > +static void aplic_irq_enable(struct irq_desc *desc) > +{ > + unsigned long flags; > + > + /* > + * 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(spin_is_locked(&desc->lock)); Iirc I said so before: This being an IRQ-safe lock, ... > + spin_lock_irqsave(&aplic.lock, flags); ... there's no need to use spin_lock_irqsave() here; plain spin_lock() will do (and avoid the need for the local variable). Same elsewhere, obviously. > +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; > + 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)); > + > + 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); > + value = desc->irq; > + value |= cpu << APLIC_TARGET_HART_IDX_SHIFT; > + value |= group_index << (lhxw + APLIC_TARGET_HART_IDX_SHIFT) ; > + > + spin_lock(&aplic.lock); > + > + writel(value, &aplic.regs->target[desc->irq - 1]); > + > + spin_unlock(&aplic.lock); Hmm, interesting, here you use the plain functions, but there's no assertion as to desc->lock being held. Such aspects would better be consistent throughout all hooks. > @@ -159,6 +270,8 @@ static int __init aplic_preinit(struct dt_device_node > *node, const void *dat) > > dt_irq_xlate = aplic_irq_xlate; > > + spin_lock_init(&aplic.lock); Can't you have the struct field have a suitable initializer? > +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; > + > + 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) > +{ > + unsigned long flags; > + > + spin_lock_irqsave(&imsic_cfg.lock, flags); > + /* > + * 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. (l) What's this 'l' in parentheses here to indicate? > + */ > + imsic_local_eix_update(irq, 1, false, true); > + spin_unlock_irqrestore(&imsic_cfg.lock, flags); > +} > + > +void imsic_irq_disable(unsigned int irq) > +{ > + unsigned long flags; > + > + spin_lock_irqsave(&imsic_cfg.lock, flags); > + imsic_local_eix_update(irq, 1, false, false); > + spin_unlock_irqrestore(&imsic_cfg.lock, flags); > +} The sole caller of the function has doubly turned off IRQs already; perhaps no need to it a 3rd time, unless other callers are to appear? Same for imsic_irq_enable() as it looks. > @@ -274,6 +373,11 @@ int __init imsic_init(const struct dt_device_node *node) > goto imsic_init_err; > } > > + spin_lock_init(&imsic_cfg.lock); Again - suitable initializer for the field instead? > --- a/xen/arch/riscv/include/asm/aplic.h > +++ b/xen/arch/riscv/include/asm/aplic.h > @@ -1,7 +1,7 @@ > /* SPDX-License-Identifier: MIT */ > > /* > - * xen/arch/riscv/asm/include/aplic.h > + * xen/arch/riscv/aplic.h Please get this right when/where the file is introduced. Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |