Ignore:
Timestamp:
2012-11-26T19:02:45Z (12 years ago)
Author:
Adam Hraska <adam.hraska+hos@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
04552324
Parents:
5d230a30 (diff), 7462674 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merged mainline,1723.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/arm32/src/mm/page_fault.c

    r5d230a30 r69146b93  
    4242#include <print.h>
    4343
    44 /** Returns value stored in fault status register.
     44
     45/**
     46 * FSR encoding ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition.
     47 *
     48 * B3.13.3 page B3-1406 (PDF page 1406)
     49 */
     50typedef enum {
     51        DFSR_SOURCE_ALIGN = 0x0001,
     52        DFSR_SOURCE_CACHE_MAINTENANCE = 0x0004,
     53        DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1 = 0x000c,
     54        DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2 = 0x000e,
     55        DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1 = 0x040c,
     56        DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2 = 0x040e,
     57        DFSR_SOURCE_TRANSLATION_L1 = 0x0005,
     58        DFSR_SOURCE_TRANSLATION_L2 = 0x0007,
     59        DFSR_SOURCE_ACCESS_FLAG_L1 = 0x0003,  /**< @note: This used to be alignment enc. */
     60        DFSR_SOURCE_ACCESS_FLAG_L2 = 0x0006,
     61        DFSR_SOURCE_DOMAIN_L1 = 0x0009,
     62        DFSR_SOURCE_DOMAIN_L2 = 0x000b,
     63        DFSR_SOURCE_PERMISSION_L1 = 0x000d,
     64        DFSR_SOURCE_PERMISSION_L2 = 0x000f,
     65        DFSR_SOURCE_DEBUG = 0x0002,
     66        DFSR_SOURCE_SYNC_EXTERNAL = 0x0008,
     67        DFSR_SOURCE_TLB_CONFLICT = 0x0400,
     68        DFSR_SOURCE_LOCKDOWN = 0x0404, /**< @note: Implementation defined */
     69        DFSR_SOURCE_COPROCESSOR = 0x040a, /**< @note Implementation defined */
     70        DFSR_SOURCE_SYNC_PARITY = 0x0409,
     71        DFSR_SOURCE_ASYNC_EXTERNAL = 0x0406,
     72        DFSR_SOURCE_ASYNC_PARITY = 0x0408,
     73        DFSR_SOURCE_MASK = 0x0000040f,
     74} dfsr_source_t;
     75
     76static inline const char * dfsr_source_to_str(dfsr_source_t source)
     77{
     78        switch (source) {
     79        case DFSR_SOURCE_TRANSLATION_L1:
     80                return "Translation fault L1";
     81        case DFSR_SOURCE_TRANSLATION_L2:
     82                return "Translation fault L2";
     83        case DFSR_SOURCE_PERMISSION_L1:
     84                return "Permission fault L1";
     85        case DFSR_SOURCE_PERMISSION_L2:
     86                return "Permission fault L2";
     87        case DFSR_SOURCE_ALIGN:
     88                return "Alignment fault";
     89        case DFSR_SOURCE_CACHE_MAINTENANCE:
     90                return "Instruction cache maintenance fault";
     91        case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1:
     92                return "Synchronous external abort on translation table walk level 1";
     93        case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2:
     94                return "Synchronous external abort on translation table walk level 2";
     95        case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1:
     96                return "Synchronous parity error on translation table walk level 1";
     97        case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2:
     98                return "Synchronous parity error on translation table walk level 2";
     99        case DFSR_SOURCE_ACCESS_FLAG_L1:
     100                return "Access flag fault L1";
     101        case DFSR_SOURCE_ACCESS_FLAG_L2:
     102                return "Access flag fault L2";
     103        case DFSR_SOURCE_DOMAIN_L1:
     104                return "Domain fault L1";
     105        case DFSR_SOURCE_DOMAIN_L2:
     106                return "Domain flault L2";
     107        case DFSR_SOURCE_DEBUG:
     108                return "Debug event";
     109        case DFSR_SOURCE_SYNC_EXTERNAL:
     110                return "Synchronous external abort";
     111        case DFSR_SOURCE_TLB_CONFLICT:
     112                return "TLB conflict abort";
     113        case DFSR_SOURCE_LOCKDOWN:
     114                return "Lockdown (Implementation defined)";
     115        case DFSR_SOURCE_COPROCESSOR:
     116                return "Coprocessor abort (Implementation defined)";
     117        case DFSR_SOURCE_SYNC_PARITY:
     118                return "Synchronous parity error on memory access";
     119        case DFSR_SOURCE_ASYNC_EXTERNAL:
     120                return "Asynchronous external abort";
     121        case DFSR_SOURCE_ASYNC_PARITY:
     122                return "Asynchronous parity error on memory access";
     123        case DFSR_SOURCE_MASK:
     124                break;
     125        }
     126        return "Unknown data abort";
     127}
     128
     129
     130/** Returns value stored in comnbined/data fault status register.
    45131 *
    46132 *  @return Value stored in CP15 fault status register (FSR).
    47  */
    48 static inline fault_status_t read_fault_status_register(void)
    49 {
    50         fault_status_union_t fsu;
     133 *
     134 *  "VMSAv6 added a fifth fault status bit (bit[10]) to both the IFSR and DFSR.
     135 *  It is IMPLEMENTATION DEFINED how this bit is encoded in earlier versions of
     136 *  the architecture. A write flag (bit[11] of the DFSR) has also been
     137 *  introduced."
     138 *  ARM Architecture Reference Manual version i ch. B4.6 (PDF p. 719)
     139 *
     140 *  See ch. B4.9.6 for location of data/instruction FSR.
     141 *
     142 */
     143static inline fault_status_t read_data_fault_status_register(void)
     144{
     145        fault_status_t fsu;
    51146       
    52         /* fault status is stored in CP15 register 5 */
     147        /* Combined/Data fault status is stored in CP15 register 5, c0. */
    53148        asm volatile (
    54149                "mrc p15, 0, %[dummy], c5, c0, 0"
    55                 : [dummy] "=r" (fsu.dummy)
     150                : [dummy] "=r" (fsu.raw)
    56151        );
    57152       
    58         return fsu.fs;
    59 }
    60 
    61 /** Returns FAR (fault address register) content.
    62  *
    63  * @return FAR (fault address register) content (address that caused a page
     153        return fsu;
     154}
     155
     156/** Returns DFAR (fault address register) content.
     157 *
     158 * This register is equivalent to FAR on pre armv6 machines.
     159 *
     160 * @return DFAR (fault address register) content (address that caused a page
    64161 *         fault)
    65162 */
    66 static inline uintptr_t read_fault_address_register(void)
     163static inline uintptr_t read_data_fault_address_register(void)
    67164{
    68165        uintptr_t ret;
     
    77174}
    78175
     176#if defined(PROCESSOR_armv4) | defined(PROCESSOR_armv5)
    79177/** Decides whether read or write into memory is requested.
    80178 *
     
    97195                panic("page_fault - instruction does not access memory "
    98196                    "(instr_code: %#0" PRIx32 ", badvaddr:%p).",
    99                     instr_union.pc, (void *) badvaddr);
     197                    *(uint32_t*)instr_union.instr, (void *) badvaddr);
    100198                return PF_ACCESS_EXEC;
    101199        }
     
    136234            inst, (void *) badvaddr);
    137235}
     236#endif
    138237
    139238/** Handles "data abort" exception (load or store at invalid address).
     
    145244void data_abort(unsigned int exc_no, istate_t *istate)
    146245{
    147         fault_status_t fsr __attribute__ ((unused)) =
    148             read_fault_status_register();
    149         uintptr_t badvaddr = read_fault_address_register();
    150 
    151         pf_access_t access = get_memory_access_type(istate->pc, badvaddr);
    152 
    153         int ret = as_page_fault(badvaddr, access, istate);
    154 
    155         if (ret == AS_PF_FAULT) {
    156                 fault_if_from_uspace(istate, "Page fault: %#x.", badvaddr);
    157                 panic_memtrap(istate, access, badvaddr, NULL);
     246        const uintptr_t badvaddr = read_data_fault_address_register();
     247        const fault_status_t fsr = read_data_fault_status_register();
     248        const dfsr_source_t source = fsr.raw & DFSR_SOURCE_MASK;
     249
     250        switch (source) {
     251        case DFSR_SOURCE_TRANSLATION_L1:
     252        case DFSR_SOURCE_TRANSLATION_L2:
     253        case DFSR_SOURCE_PERMISSION_L1:
     254        case DFSR_SOURCE_PERMISSION_L2:
     255                /* Page fault is handled further down */
     256                break;
     257        case DFSR_SOURCE_ALIGN:
     258        case DFSR_SOURCE_CACHE_MAINTENANCE:
     259        case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1:
     260        case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2:
     261        case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1:
     262        case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2:
     263        case DFSR_SOURCE_ACCESS_FLAG_L1:
     264        case DFSR_SOURCE_ACCESS_FLAG_L2:
     265        case DFSR_SOURCE_DOMAIN_L1:
     266        case DFSR_SOURCE_DOMAIN_L2:
     267        case DFSR_SOURCE_DEBUG:
     268        case DFSR_SOURCE_SYNC_EXTERNAL:
     269        case DFSR_SOURCE_TLB_CONFLICT:
     270        case DFSR_SOURCE_LOCKDOWN:
     271        case DFSR_SOURCE_COPROCESSOR:
     272        case DFSR_SOURCE_SYNC_PARITY:
     273        case DFSR_SOURCE_ASYNC_EXTERNAL:
     274        case DFSR_SOURCE_ASYNC_PARITY:
     275        case DFSR_SOURCE_MASK:
     276                /* Weird abort stuff */
     277                fault_if_from_uspace(istate, "Unhandled abort %s at address: "
     278                    "%#x.", dfsr_source_to_str(source), badvaddr);
     279                panic("Unhandled abort %s at address: %#x.",
     280                    dfsr_source_to_str(source), badvaddr);
    158281        }
     282
     283#if defined(PROCESSOR_armv6) | defined(PROCESSOR_armv7_a)
     284        const pf_access_t access =
     285            fsr.data.wr ? PF_ACCESS_WRITE : PF_ACCESS_READ;
     286#elif defined(PROCESSOR_armv4) | defined(PROCESSOR_armv5)
     287        const pf_access_t access = get_memory_access_type(istate->pc, badvaddr);
     288#else
     289#error "Unsupported architecture"
     290#endif
     291        as_page_fault(badvaddr, access, istate);
    159292}
    160293
     
    167300void prefetch_abort(unsigned int exc_no, istate_t *istate)
    168301{
    169         int ret = as_page_fault(istate->pc, PF_ACCESS_EXEC, istate);
    170 
    171         if (ret == AS_PF_FAULT) {
    172                 fault_if_from_uspace(istate,
    173                     "Page fault - prefetch_abort: %#x.", istate->pc);
    174                 panic_memtrap(istate, PF_ACCESS_EXEC, istate->pc, NULL);
    175         }
     302        as_page_fault(istate->pc, PF_ACCESS_EXEC, istate);
    176303}
    177304
Note: See TracChangeset for help on using the changeset viewer.