GCC 6 ошибка сдвига по потоку,

  CC      drivers/iommu/msm_iommu-v1.o
In file included from include/linux/io.h:22:0,
                 from drivers/iommu/msm_iommu-v1.c:18:
drivers/iommu/msm_iommu-v1.c: In function '__program_context':
arch/arm/mach-msm/include/mach/iommu_hw-v1.h:61:31: warning: 
result of '16777215 << 14' requires 39 bits to represent, 
but 'int' only has 32 bits [-Wshift-overflow=]
error, forbidden warning: iommu_hw-v1.h:61

Об этом уже спрашивали. Ошибка компиляции ядра Android gcc6 linaro 6 Единственным ответом была компиляция с

 # Ensure C builds don't fail on warnings 
 export CFLAGS="-Wno-error" 
 export CXXFLAGS="-Wno-error"

Для меня это не имеет смысла, зачем скрывать ошибку? Мы должны исправить их. Вот что я нашел до сих пор.

драйверы/iommu/msm_iommu-v1.c: в функции '__program_context'


static void __program_context(struct msm_iommu_drvdata *iommu_drvdata,
                  struct msm_iommu_ctx_drvdata *ctx_drvdata,
                  struct msm_iommu_priv *priv, bool is_secure,
                  bool program_m2v)
{
    unsigned int prrr, nmrr;
    phys_addr_t pn;
    void __iomem *base = iommu_drvdata->base;
    unsigned int ctx = ctx_drvdata->num;
    phys_addr_t pgtable = __pa(priv->pt.fl_table);

    __reset_context(base, ctx);

    pn = pgtable >> CB_TTBR0_ADDR_SHIFT;
    SET_TTBCR(base, ctx, 0);
    SET_CB_TTBR0_ADDR(base, ctx, pn);

    /* Enable context fault interrupt */
    SET_CB_SCTLR_CFIE(base, ctx, 1);

    /* Redirect all cacheable requests to L2 slave port. */
    SET_CB_ACTLR_BPRCISH(base, ctx, 1);
    SET_CB_ACTLR_BPRCOSH(base, ctx, 1);
    SET_CB_ACTLR_BPRCNSH(base, ctx, 1);

    /* Turn on TEX Remap */
    SET_CB_SCTLR_TRE(base, ctx, 1);

    /* Enable private ASID namespace */
    SET_CB_SCTLR_ASIDPNE(base, ctx, 1);

    /* Set TEX remap attributes */
    RCP15_PRRR(prrr);
    RCP15_NMRR(nmrr);
    SET_PRRR(base, ctx, prrr);
    SET_NMRR(base, ctx, nmrr);

    /* Configure page tables as inner-cacheable and shareable to reduce
     * the TLB miss penalty.
     */
    if (priv->pt.redirect) {
        SET_CB_TTBR0_S(base, ctx, 1);
        SET_CB_TTBR0_NOS(base, ctx, 1);
        SET_CB_TTBR0_IRGN1(base, ctx, 0); /* WB, WA */
        SET_CB_TTBR0_IRGN0(base, ctx, 1);
        SET_CB_TTBR0_RGN(base, ctx, 1);   /* WB, WA */
    }

    if (!is_secure) {
        if (program_m2v)
            program_all_m2v_tables(iommu_drvdata);

        SET_CBAR_N(base, ctx, 0);

        /* Stage 1 Context with Stage 2 bypass */
        SET_CBAR_TYPE(base, ctx, 1);

        /* Route page faults to the non-secure interrupt */
        SET_CBAR_IRPTNDX(base, ctx, 1);

        /* Set VMID to non-secure HLOS */
        SET_CBAR_VMID(base, ctx, 3);

        /* Bypass is treated as inner-shareable */
        SET_CBAR_BPSHCFG(base, ctx, 2);

        /* Do not downgrade memory attributes */
        SET_CBAR_MEMATTR(base, ctx, 0x0A);

    }

    msm_iommu_assign_ASID(iommu_drvdata, ctx_drvdata, priv);

    /* Enable the MMU */
    SET_CB_SCTLR_M(base, ctx, 1);
    mb();
}

арка/рука/mach-msm/include/mach/iommu_hw-v1.h


#define SET_FIELD(addr, mask, shift, v) \
do { \
    int t = readl_relaxed(addr); \
    writel_relaxed((t & ~((mask) << (shift))) + (((v) & \
            (mask)) << (shift)), addr); \
} while (0)

Насколько я могу судить, проблема заключается в функции writel_relaxed из arch/arm/include/asm/io.h.

#define writel_relaxed(v,c) ((void)__raw_writel((__force u32) \
                cpu_to_le32(v),c))

Файлы


iommu_hw- v1.h

msm_iommu-v1.c

arch/arm/include/asm/ io.h

Исходный код ядра Github


person Jcfunk    schedule 19.03.2017    source источник
comment
Что тут сложного для понимания? В предупреждении четко указано, что 16777215 << 14 приведет к переполнению 32-битной переменной, и, вероятно, это не ожидаемое поведение.   -  person Ajay Brahmakshatriya    schedule 19.03.2017
comment
16777215, вероятно, должно быть 16777215U   -  person Antti Haapala    schedule 19.03.2017


Ответы (2)


Ошибка возникает из-за расширения макроса SET_FIELD. 16777215, константа типа int, используется здесь как значение mask:

#define SET_FIELD(addr, mask, shift, v) \
do { \
    int t = readl_relaxed(addr); \
    writel_relaxed((t & ~((mask) << (shift))) + (((v) & \
            (mask)) << (shift)), addr); \
} while (0)

Константа, возможно, должна быть приведена к unsigned int или, возможно, даже к более широкому типу, если речь идет о 64-битной ARM. Однако неясно только из источника и предупреждения, где вызывается этот макрос SET_FIELD.

ИЛИ, возможно, путем приведения mask в макросе выше к (unsigned int).

person Antti Haapala    schedule 19.03.2017
comment
Так что мне нужно найти, где объявлено 16777215? - person Jcfunk; 19.03.2017
comment
@Jcfunk да, или, по крайней мере, какой из этих вызовов макросов в __program_context приводит к сбою - person Antti Haapala; 19.03.2017

Решение простыми словами. Используйте переменную большей ширины. Используйте unsigned long long вместо int.

Редактировать: если макрос вызывается для констант, а не для переменных, явным образом приведите константу к (unsigned long long). Я не уверен, что в стандартах C есть постоянные суффиксы для long-long.

person Ajay Brahmakshatriya    schedule 19.03.2017
comment
Это не переменные, а константы - person Antti Haapala; 19.03.2017