Hi Julien,

On Tue, Jan 08, 2019 at 02:07:30PM +0000, Julien Thierry wrote:
> + * Having two ways to control interrupt status is a bit complicated. Some
> + * locations like exception entries will have PSR.I bit set by the 
> architecture
> + * while PMR is unmasked.
> + * We need the irqflags to represent that interrupts are disabled in such 
> cases.
> + *
> + * For this, we lower the value read from PMR when the I bit is set so it is
> + * considered as an irq masking priority. (With PMR, lower value means 
> masking
> + * more interrupts).
> + */
> +#define _get_irqflags(daif_bits, pmr)                                        
> \
> +({                                                                   \
> +     unsigned long flags;                                            \
> +                                                                     \
> +     BUILD_BUG_ON(GIC_PRIO_IRQOFF < (GIC_PRIO_IRQON & ~PSR_I_BIT));  \
> +     asm volatile(ALTERNATIVE(                                       \
> +             "mov    %0, %1\n"                                       \
> +             "nop\n"                                                 \
> +             "nop",                                                  \
> +             "and    %0, %1, #" __stringify(PSR_I_BIT) "\n"          \
> +             "mvn    %0, %0\n"                                       \
> +             "and    %0, %0, %2",                                    \
> +             ARM64_HAS_IRQ_PRIO_MASKING)                             \

Can you write the last two instructions as a single:

                bic     %0, %2, %0

> +             : "=&r" (flags)                                         \
> +             : "r" (daif_bits), "r" (pmr)                            \
> +             : "memory");                                            \
> +                                                                     \
> +     flags;                                                          \
> +})
> +
> +/*
>   * Save the current interrupt enable state.
>   */
>  static inline unsigned long arch_local_save_flags(void)
>  {
> -     unsigned long flags;
> -     asm volatile(
> -             "mrs    %0, daif                // arch_local_save_flags"
> -             : "=r" (flags)
> +     unsigned long daif_bits;
> +     unsigned long pmr; // Only used if alternative is on
> +
> +     daif_bits = read_sysreg(daif);
> +
> +     // Get PMR

Nitpick: don't use C++ (or arm asm) comment style in C code.

> +     asm volatile(ALTERNATIVE(
> +                     "nop",
> +                     "mrs_s  %0, " __stringify(SYS_ICC_PMR_EL1),
> +                     ARM64_HAS_IRQ_PRIO_MASKING)
> +             : "=&r" (pmr)
>               :
>               : "memory");
> +
> +     return _get_irqflags(daif_bits, pmr);
> +}

I find this confusing spread over two inline asm statements. IIUC, you
want something like below (it could be written as inline asm but I need
to understand it first):

        daif_bits = read_sysreg(daif);

        if (system_uses_irq_prio_masking()) {
                pmr = read_gicreg(ICC_PMR_EL1);
                flags = pmr & ~(daif_bits & PSR_I_BIT);
        } else {
                flags = daif_bits;
        }

        return flags;

In the case where the interrupts are disabled at the PSR level, is the
PMR value still relevant? Could we just return the GIC_PRIO_IRQOFF?
Something like:

        flags = read_sysreg(daif);

        if (system_uses_irq_prio_masking())
                flags = flags & PSR_I_BIT ?
                        GIC_PRIO_IRQOFF : read_gicreg(ICC_PMR_EL1);

-- 
Catalin

Reply via email to