Changeset 850235d in mainline for kernel/arch/arm32/src


Ignore:
Timestamp:
2013-03-10T14:56:21Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
05bab88
Parents:
ea906c29 (diff), 2277e03 (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:

Merge mainline changes

Location:
kernel/arch/arm32/src
Files:
4 added
1 deleted
9 edited

Legend:

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

    rea906c29 r850235d  
    4949#include <str.h>
    5050#include <arch/ras.h>
     51#include <sysinfo/sysinfo.h>
    5152
    5253/** Performs arm32-specific initialization before main_bsp() is called. */
     
    116117{
    117118        machine_input_init();
     119        const char *platform = machine_get_platform_name();
     120
     121        sysinfo_set_item_data("platform", NULL, (void *) platform,
     122            str_size(platform));
    118123}
    119124
     
    133138        uint8_t *stck;
    134139       
    135         stck = &THREAD->kstack[STACK_SIZE - SP_DELTA];
     140        stck = &THREAD->kstack[STACK_SIZE];
    136141        supervisor_sp = (uintptr_t) stck;
    137142}
  • kernel/arch/arm32/src/cpu/cpu.c

    rea906c29 r850235d  
    3434 */
    3535
     36#include <arch/cache.h>
    3637#include <arch/cpu.h>
     38#include <arch/cp15.h>
    3739#include <cpu.h>
    3840#include <arch.h>
    3941#include <print.h>
    4042
    41 /** Number of indexes left out in the #imp_data array */
    42 #define IMP_DATA_START_OFFSET 0x40
    43 
    44 /** Implementators (vendor) names */
    45 static const char *imp_data[] = {
    46         "?",                                    /* IMP_DATA_START_OFFSET */
    47         "ARM Ltd",                              /* 0x41 */
    48         "",                                     /* 0x42 */
    49         "",                                     /* 0x43 */
    50         "Digital Equipment Corporation",        /* 0x44 */
    51         "", "", "", "", "", "", "", "", "", "", /* 0x45 - 0x4e */
    52         "", "", "", "", "", "", "", "", "", "", /* 0x4f - 0x58 */
    53         "", "", "", "", "", "", "", "", "", "", /* 0x59 - 0x62 */
    54         "", "", "", "", "", "",                 /* 0x63 - 0x68 */
    55         "Intel Corporation"                     /* 0x69 */
    56 };
    57 
    58 /** Length of the #imp_data array */
    59 static unsigned int imp_data_length = sizeof(imp_data) / sizeof(char *);
     43static inline unsigned log2(unsigned val)
     44{
     45        unsigned log = 0;
     46        --val;
     47        while (val) {
     48                ++log;
     49                val >>= 1;
     50        }
     51        return log;
     52}
     53
     54static unsigned dcache_ways(unsigned level);
     55static unsigned dcache_sets(unsigned level);
     56static unsigned dcache_linesize_log(unsigned level);
     57
     58
     59/** Implementers (vendor) names */
     60static const char * implementer(unsigned id)
     61{
     62        switch (id)
     63        {
     64        case 0x41: return "ARM Limited";
     65        case 0x44: return "Digital Equipment Corporation";
     66        case 0x4d: return "Motorola, Freescale Semiconductor Inc.";
     67        case 0x51: return "Qualcomm Inc.";
     68        case 0x56: return "Marvell Semiconductor Inc.";
     69        case 0x69: return "Intel Corporation";
     70        }
     71        return "Unknown implementer";
     72}
    6073
    6174/** Architecture names */
    62 static const char *arch_data[] = {
    63         "?",       /* 0x0 */
    64         "4",       /* 0x1 */
    65         "4T",      /* 0x2 */
    66         "5",       /* 0x3 */
    67         "5T",      /* 0x4 */
    68         "5TE",     /* 0x5 */
    69         "5TEJ",    /* 0x6 */
    70         "6"        /* 0x7 */
    71 };
    72 
    73 /** Length of the #arch_data array */
    74 static unsigned int arch_data_length = sizeof(arch_data) / sizeof(char *);
     75static const char * architecture_string(cpu_arch_t *arch)
     76{
     77        static const char *arch_data[] = {
     78                "ARM",       /* 0x0 */
     79                "ARMv4",       /* 0x1 */
     80                "ARMv4T",      /* 0x2 */
     81                "ARMv5",       /* 0x3 */
     82                "ARMv5T",      /* 0x4 */
     83                "ARMv5TE",     /* 0x5 */
     84                "ARMv5TEJ",    /* 0x6 */
     85                "ARMv6"        /* 0x7 */
     86        };
     87        if (arch->arch_num < (sizeof(arch_data) / sizeof(arch_data[0])))
     88                return arch_data[arch->arch_num];
     89        else
     90                return arch_data[0];
     91}
    7592
    7693
    7794/** Retrieves processor identification from CP15 register 0.
    78  * 
     95 *
    7996 * @param cpu Structure for storing CPU identification.
     97 * See page B4-1630 of ARM Architecture Reference Manual.
    8098 */
    8199static void arch_cpu_identify(cpu_arch_t *cpu)
    82100{
    83         uint32_t ident;
    84         asm volatile (
    85                 "mrc p15, 0, %[ident], c0, c0, 0\n"
    86                 : [ident] "=r" (ident)
    87         );
     101        const uint32_t ident = MIDR_read();
     102
     103        cpu->imp_num = (ident >> MIDR_IMPLEMENTER_SHIFT) & MIDR_IMPLEMENTER_MASK;
     104        cpu->variant_num = (ident >> MIDR_VARIANT_SHIFT) & MIDR_VARIANT_MASK;
     105        cpu->arch_num = (ident >> MIDR_ARCHITECTURE_SHIFT) & MIDR_ARCHITECTURE_MASK;
     106        cpu->prim_part_num = (ident >> MIDR_PART_NUMBER_SHIFT) & MIDR_PART_NUMBER_MASK;
     107        cpu->rev_num = (ident >> MIDR_REVISION_SHIFT) & MIDR_REVISION_MASK;
     108
     109        // TODO CPUs with arch_num == 0xf use CPUID scheme for identification
     110        cpu->dcache_levels = dcache_levels();
     111
     112        for (unsigned i = 0; i < cpu->dcache_levels; ++i) {
     113                cpu->dcache[i].ways = dcache_ways(i);
     114                cpu->dcache[i].sets = dcache_sets(i);
     115                cpu->dcache[i].way_shift = 31 - log2(cpu->dcache[i].ways);
     116                cpu->dcache[i].set_shift = dcache_linesize_log(i);
     117                cpu->dcache[i].line_size = 1 << dcache_linesize_log(i);
     118                printf("Found DCache L%u: %u-way, %u sets, %u byte lines "
     119                    "(shifts: w%u, s%u)\n", i + 1, cpu->dcache[i].ways,
     120                    cpu->dcache[i].sets, cpu->dcache[i].line_size,
     121                    cpu->dcache[i].way_shift, cpu->dcache[i].set_shift);
     122        }
     123}
     124
     125/** Enables unaligned access and caching for armv6+ */
     126void cpu_arch_init(void)
     127{
     128        uint32_t control_reg = SCTLR_read();
    88129       
    89         cpu->imp_num = ident >> 24;
    90         cpu->variant_num = (ident << 8) >> 28;
    91         cpu->arch_num = (ident << 12) >> 28;
    92         cpu->prim_part_num = (ident << 16) >> 20;
    93         cpu->rev_num = (ident << 28) >> 28;
    94 }
    95 
    96 /** Does nothing on ARM. */
    97 void cpu_arch_init(void)
    98 {
     130        /* Turn off tex remap, RAZ/WI prior to armv7 */
     131        control_reg &= ~SCTLR_TEX_REMAP_EN_FLAG;
     132        /* Turn off accessed flag, RAZ/WI prior to armv7 */
     133        control_reg &= ~(SCTLR_ACCESS_FLAG_EN_FLAG | SCTLR_HW_ACCESS_FLAG_EN_FLAG);
     134
     135        /* Unaligned access is supported on armv6+ */
     136#if defined(PROCESSOR_ARCH_armv7_a) | defined(PROCESSOR_ARCH_armv6)
     137        /* Enable unaligned access, RAZ/WI prior to armv6
     138         * switchable on armv6, RAO/WI writes on armv7,
     139         * see ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition
     140         * L.3.1 (p. 2456) */
     141        control_reg |= SCTLR_UNALIGNED_EN_FLAG;
     142        /* Disable alignment checks, this turns unaligned access to undefined,
     143         * unless U bit is set. */
     144        control_reg &= ~SCTLR_ALIGN_CHECK_EN_FLAG;
     145        /* Enable caching, On arm prior to armv7 there is only one level
     146         * of caches. Data cache is coherent.
     147         * "This means that the behavior of accesses from the same observer to
     148         * different VAs, that are translated to the same PA
     149         * with the same memory attributes, is fully coherent."
     150         *    ARM Architecture Reference Manual ARMv7-A and ARMv7-R Edition
     151         *    B3.11.1 (p. 1383)
     152         * We are safe to turn this on. For arm v6 see ch L.6.2 (p. 2469)
     153         * L2 Cache for armv7 is enabled by default (i.e. controlled by
     154         * this flag).
     155         */
     156        control_reg |= SCTLR_CACHE_EN_FLAG;
     157#endif
     158#ifdef PROCESSOR_ARCH_armv7_a
     159         /* ICache coherency is elaborate on in barrier.h.
     160          * VIPT and PIPT caches need maintenance only on code modify,
     161          * so it should be safe for general use.
     162          * Enable branch predictors too as they follow the same rules
     163          * as ICache and they can be flushed together
     164          */
     165        if ((CTR_read() & CTR_L1I_POLICY_MASK) != CTR_L1I_POLICY_AIVIVT) {
     166                control_reg |=
     167                    SCTLR_INST_CACHE_EN_FLAG | SCTLR_BRANCH_PREDICT_EN_FLAG;
     168        }
     169#endif
     170        SCTLR_write(control_reg);
     171
     172#ifdef CONFIG_FPU
     173        fpu_setup();
     174#endif
     175
     176#ifdef PROCESSOR_ARCH_armv7_a
     177        if ((ID_PFR1_read() & ID_PFR1_GEN_TIMER_EXT_MASK) !=
     178            ID_PFR1_GEN_TIMER_EXT) {
     179                PMCR_write(PMCR_read() | PMCR_E_FLAG | PMCR_D_FLAG);
     180                PMCNTENSET_write(PMCNTENSET_CYCLE_COUNTER_EN_FLAG);
     181        }
     182#endif
    99183}
    100184
    101185/** Retrieves processor identification and stores it to #CPU.arch */
    102 void cpu_identify(void) 
     186void cpu_identify(void)
    103187{
    104188        arch_cpu_identify(&CPU->arch);
     
    108192void cpu_print_report(cpu_t *m)
    109193{
    110         const char *vendor = imp_data[0];
    111         const char *architecture = arch_data[0];
    112         cpu_arch_t * cpu_arch = &m->arch;
    113 
    114         if ((cpu_arch->imp_num) > 0 &&
    115             (cpu_arch->imp_num < (imp_data_length + IMP_DATA_START_OFFSET))) {
    116                 vendor = imp_data[cpu_arch->imp_num - IMP_DATA_START_OFFSET];
    117         }
    118 
    119         if ((cpu_arch->arch_num) > 0 &&
    120             (cpu_arch->arch_num < arch_data_length)) {
    121                 architecture = arch_data[cpu_arch->arch_num];
    122         }
    123 
    124         printf("cpu%d: vendor=%s, architecture=ARM%s, part number=%x, "
     194        printf("cpu%d: vendor=%s, architecture=%s, part number=%x, "
    125195            "variant=%x, revision=%x\n",
    126             m->id, vendor, architecture, cpu_arch->prim_part_num,
    127             cpu_arch->variant_num, cpu_arch->rev_num);
     196            m->id, implementer(m->arch.imp_num),
     197            architecture_string(&m->arch), m->arch.prim_part_num,
     198            m->arch.variant_num, m->arch.rev_num);
     199}
     200
     201/** See chapter B4.1.19 of ARM Architecture Reference Manual */
     202static unsigned dcache_linesize_log(unsigned level)
     203{
     204#ifdef PROCESSOR_ARCH_armv7_a
     205        CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT);
     206        const unsigned ls_log = 2 +
     207            ((CCSIDR_read() >> CCSIDR_LINESIZE_SHIFT) & CCSIDR_LINESIZE_MASK);
     208        return ls_log + 2; //return log2(bytes)
     209#endif
     210        return 0;
     211
     212}
     213
     214/** See chapter B4.1.19 of ARM Architecture Reference Manual */
     215static unsigned dcache_ways(unsigned level)
     216{
     217#ifdef PROCESSOR_ARCH_armv7_a
     218        CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT);
     219        const unsigned ways = 1 +
     220            ((CCSIDR_read() >> CCSIDR_ASSOC_SHIFT) & CCSIDR_ASSOC_MASK);
     221        return ways;
     222#endif
     223        return 0;
     224}
     225
     226/** See chapter B4.1.19 of ARM Architecture Reference Manual */
     227static unsigned dcache_sets(unsigned level)
     228{
     229#ifdef PROCESSOR_ARCH_armv7_a
     230        CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT);
     231        const unsigned sets = 1 +
     232            ((CCSIDR_read() >> CCSIDR_NUMSETS_SHIFT) & CCSIDR_NUMSETS_MASK);
     233        return sets;
     234#endif
     235        return 0;
     236}
     237
     238unsigned dcache_levels(void)
     239{
     240        unsigned levels = 0;
     241#ifdef PROCESSOR_ARCH_armv7_a
     242        const uint32_t val = CLIDR_read();
     243        for (unsigned i = 1; i <= 7; ++i) {
     244                const unsigned ctype = CLIDR_CACHE(i, val);
     245                switch (ctype) {
     246                case CLIDR_DCACHE_ONLY:
     247                case CLIDR_SEP_CACHE:
     248                case CLIDR_UNI_CACHE:
     249                        ++levels;
     250                default:
     251                        (void)0;
     252                }
     253        }
     254#endif
     255        return levels;
     256}
     257
     258static void dcache_clean_manual(unsigned level, bool invalidate,
     259    unsigned ways, unsigned sets, unsigned way_shift, unsigned set_shift)
     260{
     261
     262        for (unsigned i = 0; i < ways; ++i) {
     263                for (unsigned j = 0; j < sets; ++j) {
     264                        const uint32_t val =
     265                            ((level & 0x7) << 1) |
     266                            (j << set_shift) | (i << way_shift);
     267                        if (invalidate)
     268                                DCCISW_write(val);
     269                        else
     270                                DCCSW_write(val);
     271                }
     272        }
     273}
     274
     275void dcache_flush(void)
     276{
     277        /* See ARM Architecture Reference Manual ch. B4.2.1 p. B4-1724 */
     278        const unsigned levels = dcache_levels();
     279        for (unsigned i = 0; i < levels; ++i) {
     280                const unsigned ways = dcache_ways(i);
     281                const unsigned sets = dcache_sets(i);
     282                const unsigned way_shift =  31 - log2(ways);
     283                const unsigned set_shift = dcache_linesize_log(i);
     284                dcache_clean_manual(i, false, ways, sets, way_shift, set_shift);
     285        }
     286}
     287
     288void dcache_flush_invalidate(void)
     289{
     290        /* See ARM Architecture Reference Manual ch. B4.2.1 p. B4-1724 */
     291        const unsigned levels = dcache_levels();
     292        for (unsigned i = 0; i < levels; ++i) {
     293                const unsigned ways = dcache_ways(i);
     294                const unsigned sets = dcache_sets(i);
     295                const unsigned way_shift =  31 - log2(ways);
     296                const unsigned set_shift = dcache_linesize_log(i);
     297                dcache_clean_manual(i, true, ways, sets, way_shift, set_shift);
     298        }
     299}
     300
     301
     302void cpu_dcache_flush(void)
     303{
     304        for (unsigned i = 0; i < CPU->arch.dcache_levels; ++i)
     305                dcache_clean_manual(i, false,
     306                    CPU->arch.dcache[i].ways, CPU->arch.dcache[i].sets,
     307                    CPU->arch.dcache[i].way_shift, CPU->arch.dcache[i].set_shift);
     308}
     309
     310void cpu_dcache_flush_invalidate(void)
     311{
     312        const unsigned levels =  dcache_levels();
     313        for (unsigned i = 0; i < levels; ++i)
     314                dcache_clean_manual(i, true,
     315                    CPU->arch.dcache[i].ways, CPU->arch.dcache[i].sets,
     316                    CPU->arch.dcache[i].way_shift, CPU->arch.dcache[i].set_shift);
     317}
     318
     319void icache_invalidate(void)
     320{
     321        ICIALLU_write(0);
    128322}
    129323
  • kernel/arch/arm32/src/dummy.S

    rea906c29 r850235d  
    3232.global asm_delay_loop
    3333
    34 .global fpu_context_restore
    35 .global fpu_context_save
    36 .global fpu_enable
    37 .global fpu_init
    38 
    3934.global sys_tls_set
    4035.global dummy
     
    4641        mov     pc, lr
    4742
    48 fpu_context_restore:
    49         mov     pc, lr
    50    
    51 fpu_context_save:
    52         mov     pc, lr
    53    
    54 fpu_enable:
    55         mov     pc, lr
    56 
    57 fpu_init:
    58         mov     pc, lr
    59    
    6043# not used on ARM
    6144sys_tls_set:
  • kernel/arch/arm32/src/exception.c

    rea906c29 r850235d  
    3939#include <interrupt.h>
    4040#include <arch/mm/page_fault.h>
     41#include <arch/cp15.h>
    4142#include <arch/barrier.h>
    4243#include <print.h>
     
    7374        /* make it LDR instruction and store at exception vector */
    7475        *vector = handler_address_ptr | LDR_OPCODE;
    75         smc_coherence(*vector);
     76        smc_coherence(vector);
    7677       
    7778        /* store handler's address */
     
    117118
    118119#ifdef HIGH_EXCEPTION_VECTORS
    119 /** Activates use of high exception vectors addresses. */
     120/** Activates use of high exception vectors addresses.
     121 *
     122 * "High vectors were introduced into some implementations of ARMv4 and are
     123 * required in ARMv6 implementations. High vectors allow the exception vector
     124 * locations to be moved from their normal address range 0x00000000-0x0000001C
     125 * at the bottom of the 32-bit address space, to an alternative address range
     126 * 0xFFFF0000-0xFFFF001C near the top of the address space. These alternative
     127 * locations are known as the high vectors.
     128 *
     129 * Prior to ARMv6, it is IMPLEMENTATION DEFINED whether the high vectors are
     130 * supported. When they are, a hardware configuration input selects whether
     131 * the normal vectors or the high vectors are to be used from
     132 * reset." ARM Architecture Reference Manual A2.6.11 (p. 64 in the PDF).
     133 *
     134 * ARM920T (gta02) TRM A2.3.5 (PDF p. 36) and ARM926EJ-S (icp) 2.3.2 (PDF p. 42)
     135 * say that armv4 an armv5 chips that we support implement this.
     136 */
    120137static void high_vectors(void)
    121138{
    122         uint32_t control_reg;
    123        
    124         asm volatile (
    125                 "mrc p15, 0, %[control_reg], c1, c0"
    126                 : [control_reg] "=r" (control_reg)
    127         );
     139        uint32_t control_reg = SCTLR_read();
    128140       
    129141        /* switch on the high vectors bit */
    130         control_reg |= CP15_R1_HIGH_VECTORS_BIT;
    131        
    132         asm volatile (
    133                 "mcr p15, 0, %[control_reg], c1, c0"
    134                 :: [control_reg] "r" (control_reg)
    135         );
     142        control_reg |= SCTLR_HIGH_VECTORS_EN_FLAG;
     143       
     144        SCTLR_write(control_reg);
    136145}
    137146#endif
     
    144153{
    145154        machine_irq_exception(exc_no, istate);
     155}
     156
     157/** Undefined instruction exception handler.
     158 *
     159 * Calls scheduler_fpu_lazy_request
     160 */
     161static void undef_insn_exception(unsigned int exc_no, istate_t *istate)
     162{
     163#ifdef CONFIG_FPU
     164        if (handle_if_fpu_exception()) {
     165                /*
     166                 * Retry the failing instruction,
     167                 * ARM Architecture Reference Manual says on p.B1-1169
     168                 * that offset for undef instruction exception is 4
     169                 */
     170                istate->pc -= 4;
     171                return;
     172        }
     173#endif
     174        fault_if_from_uspace(istate, "Undefined instruction.");
     175        panic_badtrap(istate, exc_no, "Undefined instruction.");
    146176}
    147177
     
    153183void exception_init(void)
    154184{
     185        // TODO check for availability of high vectors for <= armv5
    155186#ifdef HIGH_EXCEPTION_VECTORS
    156187        high_vectors();
     
    158189        install_exception_handlers();
    159190       
     191        exc_register(EXC_UNDEF_INSTR, "undefined instruction", true,
     192            (iroutine_t) undef_insn_exception);
    160193        exc_register(EXC_IRQ, "interrupt", true,
    161194            (iroutine_t) irq_exception);
  • kernel/arch/arm32/src/mach/gta02/gta02.c

    rea906c29 r850235d  
    2727 */
    2828
    29 /** @addtogroup arm32gxemul
     29/** @addtogroup arm32gta02
    3030 * @{
    3131 */
  • kernel/arch/arm32/src/machine_func.c

    rea906c29 r850235d  
    4141#include <arch/mach/gta02/gta02.h>
    4242#include <arch/mach/integratorcp/integratorcp.h>
    43 #include <arch/mach/testarm/testarm.h>
     43#include <arch/mach/beagleboardxm/beagleboardxm.h>
     44#include <arch/mach/beaglebone/beaglebone.h>
    4445
    4546/** Pointer to machine_ops structure being used. */
     
    5152#if defined(MACHINE_gta02)
    5253        machine_ops = &gta02_machine_ops;
    53 #elif defined(MACHINE_testarm)
    54         machine_ops = &gxemul_machine_ops;
    5554#elif defined(MACHINE_integratorcp)
    5655        machine_ops = &icp_machine_ops;
     56#elif defined(MACHINE_beagleboardxm)
     57        machine_ops = &bbxm_machine_ops;
     58#elif defined(MACHINE_beaglebone)
     59        machine_ops = &bbone_machine_ops;
    5760#else
    5861#error Machine type not defined.
     
    131134}
    132135
     136const char * machine_get_platform_name(void)
     137{
     138        if (machine_ops->machine_get_platform_name)
     139                return machine_ops->machine_get_platform_name();
     140        return NULL;
     141}
    133142/** @}
    134143 */
  • kernel/arch/arm32/src/mm/page.c

    rea906c29 r850235d  
    5252void page_arch_init(void)
    5353{
    54         int flags = PAGE_CACHEABLE;
     54        int flags = PAGE_CACHEABLE | PAGE_EXEC;
    5555        page_mapping_operations = &pt_mapping_operations;
    5656
    5757        page_table_lock(AS_KERNEL, true);
    5858       
    59         uintptr_t cur;
    60 
    6159        /* Kernel identity mapping */
    62         for (cur = PHYSMEM_START_ADDR;
    63             cur < min(config.identity_size, config.physmem_end);
     60        //FIXME: We need to consider the possibility that
     61        //identity_base > identity_size and physmem_end.
     62        //This might lead to overflow if identity_size is too big.
     63        for (uintptr_t cur = PHYSMEM_START_ADDR;
     64            cur < min(KA2PA(config.identity_base) +
     65                config.identity_size, config.physmem_end);
    6466            cur += FRAME_SIZE)
    6567                page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
  • kernel/arch/arm32/src/mm/page_fault.c

    rea906c29 r850235d  
    3434 */
    3535#include <panic.h>
     36#include <arch/cp15.h>
    3637#include <arch/exception.h>
    3738#include <arch/mm/page_fault.h>
     
    4243#include <print.h>
    4344
    44 /** Returns value stored in fault status register.
    45  *
    46  *  @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;
    51        
    52         /* fault status is stored in CP15 register 5 */
    53         asm volatile (
    54                 "mrc p15, 0, %[dummy], c5, c0, 0"
    55                 : [dummy] "=r" (fsu.dummy)
    56         );
    57        
    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
    64  *         fault)
    65  */
    66 static inline uintptr_t read_fault_address_register(void)
    67 {
    68         uintptr_t ret;
    69        
    70         /* fault adress is stored in CP15 register 6 */
    71         asm volatile (
    72                 "mrc p15, 0, %[ret], c6, c0, 0"
    73                 : [ret] "=r" (ret)
    74         );
    75        
    76         return ret;
    77 }
    78 
     45
     46/**
     47 * FSR encoding ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition.
     48 *
     49 * B3.13.3 page B3-1406 (PDF page 1406)
     50 */
     51typedef enum {
     52        DFSR_SOURCE_ALIGN = 0x0001,
     53        DFSR_SOURCE_CACHE_MAINTENANCE = 0x0004,
     54        DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1 = 0x000c,
     55        DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2 = 0x000e,
     56        DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1 = 0x040c,
     57        DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2 = 0x040e,
     58        DFSR_SOURCE_TRANSLATION_L1 = 0x0005,
     59        DFSR_SOURCE_TRANSLATION_L2 = 0x0007,
     60        DFSR_SOURCE_ACCESS_FLAG_L1 = 0x0003,  /**< @note: This used to be alignment enc. */
     61        DFSR_SOURCE_ACCESS_FLAG_L2 = 0x0006,
     62        DFSR_SOURCE_DOMAIN_L1 = 0x0009,
     63        DFSR_SOURCE_DOMAIN_L2 = 0x000b,
     64        DFSR_SOURCE_PERMISSION_L1 = 0x000d,
     65        DFSR_SOURCE_PERMISSION_L2 = 0x000f,
     66        DFSR_SOURCE_DEBUG = 0x0002,
     67        DFSR_SOURCE_SYNC_EXTERNAL = 0x0008,
     68        DFSR_SOURCE_TLB_CONFLICT = 0x0400,
     69        DFSR_SOURCE_LOCKDOWN = 0x0404, /**< @note: Implementation defined */
     70        DFSR_SOURCE_COPROCESSOR = 0x040a, /**< @note Implementation defined */
     71        DFSR_SOURCE_SYNC_PARITY = 0x0409,
     72        DFSR_SOURCE_ASYNC_EXTERNAL = 0x0406,
     73        DFSR_SOURCE_ASYNC_PARITY = 0x0408,
     74        DFSR_SOURCE_MASK = 0x0000040f,
     75} dfsr_source_t;
     76
     77static inline const char * dfsr_source_to_str(dfsr_source_t source)
     78{
     79        switch (source) {
     80        case DFSR_SOURCE_TRANSLATION_L1:
     81                return "Translation fault L1";
     82        case DFSR_SOURCE_TRANSLATION_L2:
     83                return "Translation fault L2";
     84        case DFSR_SOURCE_PERMISSION_L1:
     85                return "Permission fault L1";
     86        case DFSR_SOURCE_PERMISSION_L2:
     87                return "Permission fault L2";
     88        case DFSR_SOURCE_ALIGN:
     89                return "Alignment fault";
     90        case DFSR_SOURCE_CACHE_MAINTENANCE:
     91                return "Instruction cache maintenance fault";
     92        case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1:
     93                return "Synchronous external abort on translation table walk level 1";
     94        case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2:
     95                return "Synchronous external abort on translation table walk level 2";
     96        case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1:
     97                return "Synchronous parity error on translation table walk level 1";
     98        case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2:
     99                return "Synchronous parity error on translation table walk level 2";
     100        case DFSR_SOURCE_ACCESS_FLAG_L1:
     101                return "Access flag fault L1";
     102        case DFSR_SOURCE_ACCESS_FLAG_L2:
     103                return "Access flag fault L2";
     104        case DFSR_SOURCE_DOMAIN_L1:
     105                return "Domain fault L1";
     106        case DFSR_SOURCE_DOMAIN_L2:
     107                return "Domain flault L2";
     108        case DFSR_SOURCE_DEBUG:
     109                return "Debug event";
     110        case DFSR_SOURCE_SYNC_EXTERNAL:
     111                return "Synchronous external abort";
     112        case DFSR_SOURCE_TLB_CONFLICT:
     113                return "TLB conflict abort";
     114        case DFSR_SOURCE_LOCKDOWN:
     115                return "Lockdown (Implementation defined)";
     116        case DFSR_SOURCE_COPROCESSOR:
     117                return "Coprocessor abort (Implementation defined)";
     118        case DFSR_SOURCE_SYNC_PARITY:
     119                return "Synchronous parity error on memory access";
     120        case DFSR_SOURCE_ASYNC_EXTERNAL:
     121                return "Asynchronous external abort";
     122        case DFSR_SOURCE_ASYNC_PARITY:
     123                return "Asynchronous parity error on memory access";
     124        case DFSR_SOURCE_MASK:
     125                break;
     126        }
     127        return "Unknown data abort";
     128}
     129
     130#if defined(PROCESSOR_ARCH_armv4) | defined(PROCESSOR_ARCH_armv5)
    79131/** Decides whether read or write into memory is requested.
    80132 *
     
    97149                panic("page_fault - instruction does not access memory "
    98150                    "(instr_code: %#0" PRIx32 ", badvaddr:%p).",
    99                     instr_union.pc, (void *) badvaddr);
     151                    *(uint32_t*)instr_union.instr, (void *) badvaddr);
    100152                return PF_ACCESS_EXEC;
    101153        }
     
    136188            inst, (void *) badvaddr);
    137189}
     190#endif
    138191
    139192/** Handles "data abort" exception (load or store at invalid address).
     
    145198void data_abort(unsigned int exc_no, istate_t *istate)
    146199{
    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);
    158         }
     200        const uintptr_t badvaddr = DFAR_read();
     201        const fault_status_t fsr = { .raw = DFSR_read() };
     202        const dfsr_source_t source = fsr.raw & DFSR_SOURCE_MASK;
     203
     204        switch (source) {
     205        case DFSR_SOURCE_TRANSLATION_L1:
     206        case DFSR_SOURCE_TRANSLATION_L2:
     207        case DFSR_SOURCE_PERMISSION_L1:
     208        case DFSR_SOURCE_PERMISSION_L2:
     209                /* Page fault is handled further down */
     210                break;
     211        case DFSR_SOURCE_ALIGN:
     212        case DFSR_SOURCE_CACHE_MAINTENANCE:
     213        case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1:
     214        case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2:
     215        case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1:
     216        case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2:
     217        case DFSR_SOURCE_ACCESS_FLAG_L1:
     218        case DFSR_SOURCE_ACCESS_FLAG_L2:
     219        case DFSR_SOURCE_DOMAIN_L1:
     220        case DFSR_SOURCE_DOMAIN_L2:
     221        case DFSR_SOURCE_DEBUG:
     222        case DFSR_SOURCE_SYNC_EXTERNAL:
     223        case DFSR_SOURCE_TLB_CONFLICT:
     224        case DFSR_SOURCE_LOCKDOWN:
     225        case DFSR_SOURCE_COPROCESSOR:
     226        case DFSR_SOURCE_SYNC_PARITY:
     227        case DFSR_SOURCE_ASYNC_EXTERNAL:
     228        case DFSR_SOURCE_ASYNC_PARITY:
     229        case DFSR_SOURCE_MASK:
     230                /* Weird abort stuff */
     231                fault_if_from_uspace(istate, "Unhandled abort %s at address: "
     232                    "%#x.", dfsr_source_to_str(source), badvaddr);
     233                panic("Unhandled abort %s at address: %#x.",
     234                    dfsr_source_to_str(source), badvaddr);
     235        }
     236
     237#if defined(PROCESSOR_ARCH_armv6) | defined(PROCESSOR_ARCH_armv7_a)
     238        const pf_access_t access =
     239            fsr.data.wr ? PF_ACCESS_WRITE : PF_ACCESS_READ;
     240#elif defined(PROCESSOR_ARCH_armv4) | defined(PROCESSOR_ARCH_armv5)
     241        const pf_access_t access = get_memory_access_type(istate->pc, badvaddr);
     242#else
     243#error "Unsupported architecture"
     244#endif
     245        as_page_fault(badvaddr, access, istate);
    159246}
    160247
     
    167254void prefetch_abort(unsigned int exc_no, istate_t *istate)
    168255{
    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         }
     256        as_page_fault(istate->pc, PF_ACCESS_EXEC, istate);
    176257}
    177258
  • kernel/arch/arm32/src/ras.c

    rea906c29 r850235d  
    6767void ras_check(unsigned int n, istate_t *istate)
    6868{
    69         uintptr_t rewrite_pc = istate->pc;
     69        bool restart_needed = false;
     70        uintptr_t restart_pc = 0;
    7071
    7172        if (istate_from_uspace(istate)) {
     
    7374                        if ((ras_page[RAS_START] < istate->pc) &&
    7475                            (ras_page[RAS_END] > istate->pc)) {
    75                                 rewrite_pc = ras_page[RAS_START];
     76                                restart_needed = true;
     77                                restart_pc = ras_page[RAS_START];
    7678                        }
    7779                        ras_page[RAS_START] = 0;
    7880                        ras_page[RAS_END] = 0xffffffff;
    79                 }       
     81                }
    8082        }
    8183
    8284        exc_dispatch(n, istate);
    83 
    84         istate->pc = rewrite_pc;
     85        if (restart_needed)
     86                istate->pc = restart_pc;
    8587}
    8688
Note: See TracChangeset for help on using the changeset viewer.