Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 664fd6d5 in mainline


Ignore:
Timestamp:
2013-01-06T19:20:33Z (9 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master
Children:
de36fdd
Parents:
b5a3b50
Message:

arm32: Check access to CP10 and CP11 before using fpu instructions.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/arm32/src/fpu_context.c

    rb5a3b50 r664fd6d5  
    5858        FPEXC_EX_FLAG = (1 << 31),
    5959        FPEXC_ENABLED_FLAG = (1 << 30),
     60};
     61
     62/* See Architecture reference manual ch. B4.1.40 */
     63enum {
     64        CPACR_CP10_MASK = 0x3 << 20,
     65        CPACR_CP11_MASK = 0x3 << 22,
     66        CPACR_CP10_USER_ACCESS = CPACR_CP10_MASK,
     67        CPACR_CP11_USER_ACCESS = CPACR_CP11_MASK,
    6068};
    6169
     
    228236}
    229237
     238static int fpu_have_coprocessor_access()
     239{
     240        uint32_t cpacr;
     241        asm volatile ("MRC p15, 0, %0, c1, c0, 2" :"=r" (cpacr)::);
     242        /* FPU needs access to coprocessor 10 and 11.
     243         * Moreover they need to have same access enabledd */
     244        if (((cpacr & CPACR_CP10_MASK) == CPACR_CP10_USER_ACCESS) &&
     245           ((cpacr & CPACR_CP11_MASK) == CPACR_CP11_USER_ACCESS))
     246                return 1;
     247
     248        return 0;
     249}
     250
     251static void fpu_enable_coprocessor_access()
     252{
     253        uint32_t cpacr;
     254        asm volatile ("mrc p15, 0, %0, c1, c0, 2" :"=r" (cpacr)::);
     255        /* FPU needs access to coprocessor 10 and 11.
     256         * Moreover, they need to have same access enabled */
     257        cpacr |= CPACR_CP10_USER_ACCESS;
     258        cpacr |= CPACR_CP11_USER_ACCESS;
     259        asm volatile ("mcr p15, 0, %0, c1, c0, 2" :"=r" (cpacr)::);
     260}
     261
     262
    230263void fpu_init(void)
    231264{
     265        /* Enable coprocessor access*/
     266        fpu_enable_coprocessor_access();
     267
     268        /* Check if we succeeded */
     269        if (!fpu_have_coprocessor_access())
     270                return;
     271
    232272        /* Clear all fpu flags */
    233273        fpexc_write(0);
     
    241281void fpu_setup(void)
    242282{
     283        /* Check if we have access */
     284        if (!fpu_have_coprocessor_access())
     285                return;
     286
    243287        uint32_t fpsid = 0;
    244288        asm volatile (
     
    288332bool handle_if_fpu_exception(void)
    289333{
     334        /* Check if we have access */
     335        if (!fpu_have_coprocessor_access())
     336                return false;
     337
    290338        const uint32_t fpexc = fpexc_read();
    291339        if (fpexc & FPEXC_ENABLED_FLAG) {
     
    305353void fpu_enable(void)
    306354{
     355        /* Check if we have access */
     356        if (!fpu_have_coprocessor_access())
     357                return;
    307358        /* Enable FPU instructions */
    308359        fpexc_write(fpexc_read() | FPEXC_ENABLED_FLAG);
     
    311362void fpu_disable(void)
    312363{
     364        /* Check if we have access */
     365        if (!fpu_have_coprocessor_access())
     366                return;
    313367        /* Disable FPU instructions */
    314368        fpexc_write(fpexc_read() & ~FPEXC_ENABLED_FLAG);
     
    317371void fpu_context_save(fpu_context_t *ctx)
    318372{
     373        /* Check if we have access */
     374        if (!fpu_have_coprocessor_access())
     375                return;
    319376        const uint32_t fpexc = fpexc_read();
    320377
     
    329386void fpu_context_restore(fpu_context_t *ctx)
    330387{
     388        /* Check if we have access */
     389        if (!fpu_have_coprocessor_access())
     390                return;
    331391        if (restore_context)
    332392                restore_context(ctx);
Note: See TracChangeset for help on using the changeset viewer.