Changeset 850235d in mainline for kernel/arch/arm32


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
Files:
9 added
1 deleted
21 edited
2 moved

Legend:

Unmodified
Added
Removed
  • kernel/arch/arm32/Makefile.inc

    rea906c29 r850235d  
    3333ATSIGN = %
    3434
    35 GCC_CFLAGS += -march=armv4 -fno-omit-frame-pointer -mapcs-frame
     35GCC_CFLAGS += -fno-omit-frame-pointer -mapcs-frame -march=$(subst _,-,$(PROCESSOR_ARCH)) -mno-unaligned-access
     36
     37ifeq ($(CONFIG_FPU),y)
     38# This is necessary to allow vmsr insn and fpexc manipulation
     39# Use vfp32 to allow context save/restore of d16-d31 regs.
     40AFLAGS += -mfloat-abi=hard -mfpu=vfp3
     41endif
    3642
    3743BITS = 32
     
    6268        arch/$(KARCH)/src/ras.c
    6369
     70ifeq ($(CONFIG_FPU),y)
     71        ARCH_SOURCES += arch/$(KARCH)/src/fpu_context.c
     72        ARCH_SOURCES += arch/$(KARCH)/src/fpu.s
     73endif
     74
    6475ifeq ($(MACHINE),gta02)
    6576        ARCH_SOURCES += arch/$(KARCH)/src/mach/gta02/gta02.c
    66 endif
    67 
    68 ifeq ($(MACHINE),testarm)
    69         ARCH_SOURCES += arch/$(KARCH)/src/mach/testarm/testarm.c
    7077endif
    7178
     
    7481endif
    7582
     83ifeq ($(MACHINE),beagleboardxm)
     84        ARCH_SOURCES += arch/$(KARCH)/src/mach/beagleboardxm/beagleboardxm.c
     85endif
     86
     87ifeq ($(MACHINE),beaglebone)
     88        ARCH_SOURCES += arch/$(KARCH)/src/mach/beaglebone/beaglebone.c
     89endif
     90
    7691ifeq ($(CONFIG_PL050),y)
    7792        ARCH_SOURCES += genarch/src/drivers/pl050/pl050.c
  • kernel/arch/arm32/_link.ld.in

    rea906c29 r850235d  
    99#ifdef MACHINE_gta02
    1010#define KERNEL_LOAD_ADDRESS 0xb0a08000
     11#elif defined MACHINE_beagleboardxm
     12#define KERNEL_LOAD_ADDRESS 0x80a00000
     13#elif defined MACHINE_beaglebone
     14#define KERNEL_LOAD_ADDRESS 0x80a00000
    1115#else
    1216#define KERNEL_LOAD_ADDRESS 0x80a00000
  • kernel/arch/arm32/include/arch/asm.h

    rea906c29 r850235d  
    4343#include <trace.h>
    4444
    45 /** No such instruction on ARM to sleep CPU. */
     45/** CPU specific way to sleep cpu.
     46 *
     47 * ARMv7 introduced wait for event and wait for interrupt (wfe/wfi).
     48 * ARM920T has custom coprocessor action to do the same. See ARM920T Technical
     49 * Reference Manual ch 4.9 p. 4-23 (103 in the PDF)
     50 * ARM926EJ-S uses the same coprocessor instruction as ARM920T. See ARM926EJ-S
     51 * chapter 2.3.8 p.2-22 (52 in the PDF)
     52 *
     53 * @note Although mcr p15, 0, R0, c7, c0, 4 is defined in ARM Architecture
     54 * reference manual for armv4/5 CP15 implementation is mandatory only for
     55 * armv6+.
     56 */
    4657NO_TRACE static inline void cpu_sleep(void)
    4758{
     59#ifdef PROCESSOR_ARCH_armv7_a
     60        asm volatile ( "wfe" );
     61#elif defined(PROCESSOR_ARCH_armv6) | defined(PROCESSOR_arm926ej_s) | defined(PROCESSOR_arm920t)
     62        asm volatile ( "mcr p15, 0, R0, c7, c0, 4" );
     63#endif
    4864}
    4965
  • kernel/arch/arm32/include/arch/barrier.h

    rea906c29 r850235d  
    3737#define KERN_arm32_BARRIER_H_
    3838
    39 /*
    40  * TODO: implement true ARM memory barriers for macros below.
    41  */
     39#ifdef KERNEL
     40#include <arch/cp15.h>
     41#else
     42#include <libarch/cp15.h>
     43#endif
     44
    4245#define CS_ENTER_BARRIER()  asm volatile ("" ::: "memory")
    4346#define CS_LEAVE_BARRIER()  asm volatile ("" ::: "memory")
    4447
     48#if defined PROCESSOR_ARCH_armv7_a
     49/* ARMv7 uses instructions for memory barriers see ARM Architecture reference
     50 * manual for details:
     51 * DMB: ch. A8.8.43 page A8-376
     52 * DSB: ch. A8.8.44 page A8-378
     53 * See ch. A3.8.3 page A3-148 for details about memory barrier implementation
     54 * and functionality on armv7 architecture.
     55 */
     56#define memory_barrier()  asm volatile ("dmb" ::: "memory")
     57#define read_barrier()    asm volatile ("dsb" ::: "memory")
     58#define write_barrier()   asm volatile ("dsb st" ::: "memory")
     59#define inst_barrier()    asm volatile ("isb" ::: "memory")
     60#elif defined PROCESSOR_ARCH_armv6 | defined KERNEL
     61/*
     62 * ARMv6 introduced user access of the following commands:
     63 * - Prefetch flush
     64 * - Data synchronization barrier
     65 * - Data memory barrier
     66 * - Clean and prefetch range operations.
     67 * ARM Architecture Reference Manual version I ch. B.3.2.1 p. B3-4
     68 */
     69/* ARMv6- use system control coprocessor (CP15) for memory barrier instructions.
     70 * Although at least mcr p15, 0, r0, c7, c10, 4 is mentioned in earlier archs,
     71 * CP15 implementation is mandatory only for armv6+.
     72 */
     73#define memory_barrier()  CP15DMB_write(0)
     74#define read_barrier()    CP15DSB_write(0)
     75#define write_barrier()   read_barrier()
     76#define inst_barrier()    CP15ISB_write(0)
     77#else
     78/* Older manuals mention syscalls as a way to implement cache coherency and
     79 * barriers. See for example ARM Architecture Reference Manual Version D
     80 * chapter 2.7.4 Prefetching and self-modifying code (p. A2-28)
     81 */
     82// TODO implement on per PROCESSOR basis or via syscalls
    4583#define memory_barrier()  asm volatile ("" ::: "memory")
    4684#define read_barrier()    asm volatile ("" ::: "memory")
    4785#define write_barrier()   asm volatile ("" ::: "memory")
     86#define inst_barrier()    asm volatile ("" ::: "memory")
     87#endif
    4888
     89/*
     90 * There are multiple ways ICache can be implemented on ARM machines. Namely
     91 * PIPT, VIPT, and ASID and VMID tagged VIVT (see ARM Architecture Reference
     92 * Manual B3.11.2 (p. 1383).  However, CortexA8 Manual states: "For maximum
     93 * compatibility across processors, ARM recommends that operating systems target
     94 * the ARMv7 base architecture that uses ASID-tagged VIVT instruction caches,
     95 * and do not assume the presence of the IVIPT extension. Software that relies
     96 * on the IVIPT extension might fail in an unpredictable way on an ARMv7
     97 * implementation that does not include the IVIPT extension." (7.2.6 p. 245).
     98 * Only PIPT invalidates cache for all VA aliases if one block is invalidated.
     99 *
     100 * @note: Supporting ASID and VMID tagged VIVT may need to add ICache
     101 * maintenance to other places than just smc.
     102 */
     103
     104#if defined PROCESSOR_ARCH_armv7_a | defined PROCESSOR_ARCH_armv6 | defined KERNEL
     105/* Available on all supported arms,
     106 * invalidates entire ICache so the written value does not matter. */
     107//TODO might be PL1 only on armv5-
     108#define smc_coherence(a) \
     109do { \
     110        DCCMVAU_write((uint32_t)(a));  /* Flush changed memory */\
     111        write_barrier();               /* Wait for completion */\
     112        ICIALLU_write(0);              /* Flush ICache */\
     113        inst_barrier();                /* Wait for Inst refetch */\
     114} while (0)
     115/* @note: Cache type register is not available in uspace. We would need
     116 * to export the cache line value, or use syscall for uspace smc_coherence */
     117#define smc_coherence_block(a, l) \
     118do { \
     119        for (uintptr_t addr = (uintptr_t)a; addr < (uintptr_t)a + l; addr += 4)\
     120                smc_coherence(addr); \
     121} while (0)
     122#else
    49123#define smc_coherence(a)
    50124#define smc_coherence_block(a, l)
     125#endif
     126
    51127
    52128#endif
  • kernel/arch/arm32/include/arch/cache.h

    rea906c29 r850235d  
    11/*
    2  * Copyright (c) 2011 Martin Sucha
     2 * Copyright (c) 2013 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 /** @addtogroup fs
     29/** @addtogroup arm32
    3030 * @{
    31  */
     31 */
     32/** @file
     33 *  @brief Security Extensions Routines
     34 */
    3235
    33 #ifndef EXT2FS_EXT2FS_H_
    34 #define EXT2FS_EXT2FS_H_
     36#ifndef KERN_arm32_CACHE_H_
     37#define KERN_arm32_CACHE_H_
    3538
    36 #include <libext2.h>
    37 #include <libfs.h>
    38 #include <sys/types.h>
     39unsigned dcache_levels(void);
    3940
    40 #define min(a, b)               ((a) < (b) ? (a) : (b))
    41 
    42 extern vfs_out_ops_t ext2fs_ops;
    43 extern libfs_ops_t ext2fs_libfs_ops;
    44 
    45 extern int ext2fs_global_init(void);
    46 extern int ext2fs_global_fini(void);
     41void dcache_flush(void);
     42void dcache_flush_invalidate(void);
     43void cpu_dcache_flush(void);
     44void cpu_dcache_flush_invalidate(void);
     45void icache_invalidate(void);
    4746
    4847#endif
     48/** @}
     49 */
    4950
    50 /**
    51  * @}
    52  */
  • kernel/arch/arm32/include/arch/cpu.h

    rea906c29 r850235d  
    4040#include <arch/asm.h>
    4141
     42enum {
     43        ARM_MAX_CACHE_LEVELS = 7,
     44};
    4245
    43 /** Struct representing ARM CPU identifiaction. */
     46/** Struct representing ARM CPU identification. */
    4447typedef struct {
    45         /** Implementator (vendor) number. */
     48        /** Implementor (vendor) number. */
    4649        uint32_t imp_num;
    4750
     
    5760        /** Revision number. */
    5861        uint32_t rev_num;
     62
     63        struct {
     64                unsigned ways;
     65                unsigned sets;
     66                unsigned line_size;
     67                unsigned way_shift;
     68                unsigned set_shift;
     69        } dcache[ARM_MAX_CACHE_LEVELS];
     70        unsigned dcache_levels;
    5971} cpu_arch_t;
    6072
  • kernel/arch/arm32/include/arch/cycle.h

    rea906c29 r850235d  
    3838
    3939#include <trace.h>
     40#include <arch/cp15.h>
    4041
    4142/** Return count of CPU cycles.
     
    4849NO_TRACE static inline uint64_t get_cycle(void)
    4950{
     51#ifdef PROCESSOR_ARCH_armv7_a
     52        if ((ID_PFR1_read() & ID_PFR1_GEN_TIMER_EXT_MASK) ==
     53            ID_PFR1_GEN_TIMER_EXT) {
     54            uint32_t low = 0, high = 0;
     55            asm volatile( "MRRC p15, 0, %[low], %[high], c14": [low]"=r"(low), [high]"=r"(high));
     56           return ((uint64_t)high << 32) | low;
     57        } else {
     58                return (uint64_t)PMCCNTR_read() * 64;
     59        }
     60#endif
    5061        return 0;
    5162}
  • kernel/arch/arm32/include/arch/fpu_context.h

    rea906c29 r850235d  
    3131 */
    3232/** @file
    33  *  @brief FPU context (not implemented).
    34  *
    35  *  GXemul doesn't support FPU on its ARM CPU.
     33 *  @brief FPU context.
    3634 */
    3735
     
    4139#include <typedefs.h>
    4240
    43 #define FPU_CONTEXT_ALIGN    0
     41#define FPU_CONTEXT_ALIGN    8
    4442
     43/* ARM Architecture reference manual, p B-1529.
     44 */
    4545typedef struct {
     46        uint32_t fpexc;
     47        uint32_t fpscr;
     48        uint32_t s[64];
    4649} fpu_context_t;
     50
     51void fpu_setup(void);
     52
     53bool handle_if_fpu_exception(void);
    4754
    4855#endif
  • kernel/arch/arm32/include/arch/mach/beagleboardxm/beagleboardxm.h

    rea906c29 r850235d  
    11/*
    2  * Copyright (c) 2006 Ondrej Palkovsky
     2 * Copyright (c) 2012 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    29 /** @addtogroup amd64debug
     28/** @addtogroup arm32beagleboardxm beagleboardxm
     29 *  @brief BeagleBoard-xM platform.
     30 *  @ingroup arm32
    3031 * @{
    3132 */
    3233/** @file
     34 *  @brief BeagleBoard platform driver.
    3335 */
    3436
    35 #ifndef KERN_amd64_DEBUGGER_H_
    36 #define KERN_amd64_DEBUGGER_H_
     37#ifndef KERN_arm32_beagleboardxm_H_
     38#define KERN_arm32_beagleboardxm_H_
    3739
    38 #include <typedefs.h>
     40#include <arch/machine_func.h>
    3941
    40 #define BKPOINTS_MAX  4
    41 
    42 /* Flags that are passed to breakpoint_add function */
    43 #define BKPOINT_INSTR       0x1U
    44 #define BKPOINT_WRITE       0x2U
    45 #define BKPOINT_READ_WRITE  0x4U
    46 
    47 #define BKPOINT_CHECK_ZERO  0x8U
    48 
    49 
    50 extern void debugger_init(void);
    51 extern int breakpoint_add(const void *, const unsigned int, int);
    52 extern void breakpoint_del(int);
     42extern struct arm_machine_ops bbxm_machine_ops;
    5343
    5444#endif
     
    5646/** @}
    5747 */
     48
  • kernel/arch/arm32/include/arch/machine_func.h

    rea906c29 r850235d  
    108108extern size_t machine_get_irq_count(void);
    109109
     110extern const char * machine_get_platform_name(void);
     111
    110112#endif
    111113
  • kernel/arch/arm32/include/arch/mm/frame.h

    rea906c29 r850235d  
    4747
    4848#ifdef MACHINE_gta02
     49
     50#define PHYSMEM_START_ADDR       0x30008000
    4951#define BOOT_PAGE_TABLE_ADDRESS  0x30010000
     52
     53#elif defined MACHINE_beagleboardxm
     54
     55#define PHYSMEM_START_ADDR       0x80000000
     56#define BOOT_PAGE_TABLE_ADDRESS  0x80008000
     57
     58#elif defined MACHINE_beaglebone
     59
     60#define PHYSMEM_START_ADDR       0x80000000
     61#define BOOT_PAGE_TABLE_ADDRESS  0x80008000
     62
    5063#else
     64
     65#define PHYSMEM_START_ADDR       0x00000000
    5166#define BOOT_PAGE_TABLE_ADDRESS  0x00008000
     67
    5268#endif
    5369
    5470#define BOOT_PAGE_TABLE_START_FRAME     (BOOT_PAGE_TABLE_ADDRESS >> FRAME_WIDTH)
    5571#define BOOT_PAGE_TABLE_SIZE_IN_FRAMES  (BOOT_PAGE_TABLE_SIZE >> FRAME_WIDTH)
    56 
    57 #ifdef MACHINE_gta02
    58 #define PHYSMEM_START_ADDR      0x30008000
    59 #else
    60 #define PHYSMEM_START_ADDR      0x00000000
    61 #endif
    6272
    6373extern void frame_low_arch_init(void);
  • kernel/arch/arm32/include/arch/mm/page.h

    rea906c29 r850235d  
    4646#define PAGE_SIZE       FRAME_SIZE
    4747
     48#if (defined MACHINE_beagleboardxm) || (defined MACHINE_beaglebone)
     49#ifndef __ASM__
     50#       define KA2PA(x) ((uintptr_t) (x))
     51#       define PA2KA(x) ((uintptr_t) (x))
     52#else
     53#       define KA2PA(x) (x)
     54#       define PA2KA(x) (x)
     55#endif
     56#else
    4857#ifndef __ASM__
    4958#       define KA2PA(x) (((uintptr_t) (x)) - 0x80000000)
     
    5362#       define PA2KA(x) ((x) + 0x80000000)
    5463#endif
     64#endif
    5565
    5666/* Number of entries in each level. */
    57 #define PTL0_ENTRIES_ARCH       (1 << 12)       /* 4096 */
    58 #define PTL1_ENTRIES_ARCH       0
    59 #define PTL2_ENTRIES_ARCH       0
     67#define PTL0_ENTRIES_ARCH       (1 << 12)       /* 4096 */
     68#define PTL1_ENTRIES_ARCH       0
     69#define PTL2_ENTRIES_ARCH       0
    6070/* coarse page tables used (256 * 4 = 1KB per page) */
    61 #define PTL3_ENTRIES_ARCH       (1 << 8)        /* 256 */
     71#define PTL3_ENTRIES_ARCH       (1 << 8)        /* 256 */
    6272
    6373/* Page table sizes for each level. */
    64 #define PTL0_SIZE_ARCH          FOUR_FRAMES
    65 #define PTL1_SIZE_ARCH          0
    66 #define PTL2_SIZE_ARCH          0
    67 #define PTL3_SIZE_ARCH          ONE_FRAME
     74#define PTL0_SIZE_ARCH          FOUR_FRAMES
     75#define PTL1_SIZE_ARCH          0
     76#define PTL2_SIZE_ARCH          0
     77#define PTL3_SIZE_ARCH          ONE_FRAME
    6878
    6979/* Macros calculating indices into page tables for each level. */
    70 #define PTL0_INDEX_ARCH(vaddr)  (((vaddr) >> 20) & 0xfff)
    71 #define PTL1_INDEX_ARCH(vaddr)  0
    72 #define PTL2_INDEX_ARCH(vaddr)  0
    73 #define PTL3_INDEX_ARCH(vaddr)  (((vaddr) >> 12) & 0x0ff)
     80#define PTL0_INDEX_ARCH(vaddr)  (((vaddr) >> 20) & 0xfff)
     81#define PTL1_INDEX_ARCH(vaddr)  0
     82#define PTL2_INDEX_ARCH(vaddr)  0
     83#define PTL3_INDEX_ARCH(vaddr)  (((vaddr) >> 12) & 0x0ff)
    7484
    7585/* Get PTE address accessors for each level. */
    7686#define GET_PTL1_ADDRESS_ARCH(ptl0, i) \
    77         ((pte_t *) ((((pte_t *)(ptl0))[(i)].l0).coarse_table_addr << 10))
     87        ((pte_t *) ((((pte_t *)(ptl0))[(i)].l0).coarse_table_addr << 10))
    7888#define GET_PTL2_ADDRESS_ARCH(ptl1, i) \
    79         (ptl1)
     89        (ptl1)
    8090#define GET_PTL3_ADDRESS_ARCH(ptl2, i) \
    81         (ptl2)
     91        (ptl2)
    8292#define GET_FRAME_ADDRESS_ARCH(ptl3, i) \
    83         ((uintptr_t) ((((pte_t *)(ptl3))[(i)].l1).frame_base_addr << 12))
     93        ((uintptr_t) ((((pte_t *)(ptl3))[(i)].l1).frame_base_addr << 12))
    8494
    8595/* Set PTE address accessors for each level. */
    8696#define SET_PTL0_ADDRESS_ARCH(ptl0) \
    87         (set_ptl0_addr((pte_t *) (ptl0)))
     97        (set_ptl0_addr((pte_t *) (ptl0)))
    8898#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a) \
    89         (((pte_t *) (ptl0))[(i)].l0.coarse_table_addr = (a) >> 10)
     99        (((pte_t *) (ptl0))[(i)].l0.coarse_table_addr = (a) >> 10)
    90100#define SET_PTL2_ADDRESS_ARCH(ptl1, i, a)
    91101#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a)
    92102#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) \
    93         (((pte_t *) (ptl3))[(i)].l1.frame_base_addr = (a) >> 12)
     103        (((pte_t *) (ptl3))[(i)].l1.frame_base_addr = (a) >> 12)
    94104
    95105/* Get PTE flags accessors for each level. */
    96106#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
    97         get_pt_level0_flags((pte_t *) (ptl0), (size_t) (i))
     107        get_pt_level0_flags((pte_t *) (ptl0), (size_t) (i))
    98108#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
    99         PAGE_PRESENT
     109        PAGE_PRESENT
    100110#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
    101         PAGE_PRESENT
     111        PAGE_PRESENT
    102112#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
    103         get_pt_level1_flags((pte_t *) (ptl3), (size_t) (i))
     113        get_pt_level1_flags((pte_t *) (ptl3), (size_t) (i))
    104114
    105115/* Set PTE flags accessors for each level. */
    106116#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
    107         set_pt_level0_flags((pte_t *) (ptl0), (size_t) (i), (x))
     117        set_pt_level0_flags((pte_t *) (ptl0), (size_t) (i), (x))
    108118#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
    109119#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
     
    119129        set_pt_level1_present((pte_t *) (ptl3), (size_t) (i))
    120130
    121 /* Macros for querying the last-level PTE entries. */
    122 #define PTE_VALID_ARCH(pte) \
    123         (*((uint32_t *) (pte)) != 0)
    124 #define PTE_PRESENT_ARCH(pte) \
    125         (((pte_t *) (pte))->l0.descriptor_type != 0)
    126 #define PTE_GET_FRAME_ARCH(pte) \
    127         (((pte_t *) (pte))->l1.frame_base_addr << FRAME_WIDTH)
    128 #define PTE_WRITABLE_ARCH(pte) \
    129         (((pte_t *) (pte))->l1.access_permission_0 == PTE_AP_USER_RW_KERNEL_RW)
    130 #define PTE_EXECUTABLE_ARCH(pte) \
    131         1
    132 
    133 #ifndef __ASM__
    134 
    135 /** Level 0 page table entry. */
    136 typedef struct {
    137         /* 0b01 for coarse tables, see below for details */
    138         unsigned descriptor_type : 2;
    139         unsigned impl_specific : 3;
    140         unsigned domain : 4;
    141         unsigned should_be_zero : 1;
    142 
    143         /* Pointer to the coarse 2nd level page table (holding entries for small
    144          * (4KB) or large (64KB) pages. ARM also supports fine 2nd level page
    145          * tables that may hold even tiny pages (1KB) but they are bigger (4KB
    146          * per table in comparison with 1KB per the coarse table)
    147          */
    148         unsigned coarse_table_addr : 22;
    149 } ATTRIBUTE_PACKED pte_level0_t;
    150 
    151 /** Level 1 page table entry (small (4KB) pages used). */
    152 typedef struct {
    153 
    154         /* 0b10 for small pages */
    155         unsigned descriptor_type : 2;
    156         unsigned bufferable : 1;
    157         unsigned cacheable : 1;
    158 
    159         /* access permissions for each of 4 subparts of a page
    160          * (for each 1KB when small pages used */
    161         unsigned access_permission_0 : 2;
    162         unsigned access_permission_1 : 2;
    163         unsigned access_permission_2 : 2;
    164         unsigned access_permission_3 : 2;
    165         unsigned frame_base_addr : 20;
    166 } ATTRIBUTE_PACKED pte_level1_t;
    167 
    168 typedef union {
    169         pte_level0_t l0;
    170         pte_level1_t l1;
    171 } pte_t;
    172 
    173 /* Level 1 page tables access permissions */
    174 
    175 /** User mode: no access, privileged mode: no access. */
    176 #define PTE_AP_USER_NO_KERNEL_NO        0
    177 
    178 /** User mode: no access, privileged mode: read/write. */
    179 #define PTE_AP_USER_NO_KERNEL_RW        1
    180 
    181 /** User mode: read only, privileged mode: read/write. */
    182 #define PTE_AP_USER_RO_KERNEL_RW        2
    183 
    184 /** User mode: read/write, privileged mode: read/write. */
    185 #define PTE_AP_USER_RW_KERNEL_RW        3
    186 
    187 
    188 /* pte_level0_t and pte_level1_t descriptor_type flags */
    189 
    190 /** pte_level0_t and pte_level1_t "not present" flag (used in descriptor_type). */
    191 #define PTE_DESCRIPTOR_NOT_PRESENT      0
    192 
    193 /** pte_level0_t coarse page table flag (used in descriptor_type). */
    194 #define PTE_DESCRIPTOR_COARSE_TABLE     1
    195 
    196 /** pte_level1_t small page table flag (used in descriptor type). */
    197 #define PTE_DESCRIPTOR_SMALL_PAGE       2
    198 
    199 
    200 /** Sets the address of level 0 page table.
    201  *
    202  * @param pt Pointer to the page table to set.
    203  *
    204  */
    205 NO_TRACE static inline void set_ptl0_addr(pte_t *pt)
    206 {
    207         asm volatile (
    208                 "mcr p15, 0, %[pt], c2, c0, 0\n"
    209                 :: [pt] "r" (pt)
    210         );
    211 }
    212 
    213 
    214 /** Returns level 0 page table entry flags.
    215  *
    216  * @param pt Level 0 page table.
    217  * @param i  Index of the entry to return.
    218  *
    219  */
    220 NO_TRACE static inline int get_pt_level0_flags(pte_t *pt, size_t i)
    221 {
    222         pte_level0_t *p = &pt[i].l0;
    223         int np = (p->descriptor_type == PTE_DESCRIPTOR_NOT_PRESENT);
    224        
    225         return (np << PAGE_PRESENT_SHIFT) | (1 << PAGE_USER_SHIFT) |
    226             (1 << PAGE_READ_SHIFT) | (1 << PAGE_WRITE_SHIFT) |
    227             (1 << PAGE_EXEC_SHIFT) | (1 << PAGE_CACHEABLE_SHIFT);
    228 }
    229 
    230 /** Returns level 1 page table entry flags.
    231  *
    232  * @param pt Level 1 page table.
    233  * @param i  Index of the entry to return.
    234  *
    235  */
    236 NO_TRACE static inline int get_pt_level1_flags(pte_t *pt, size_t i)
    237 {
    238         pte_level1_t *p = &pt[i].l1;
    239        
    240         int dt = p->descriptor_type;
    241         int ap = p->access_permission_0;
    242        
    243         return ((dt == PTE_DESCRIPTOR_NOT_PRESENT) << PAGE_PRESENT_SHIFT) |
    244             ((ap == PTE_AP_USER_RO_KERNEL_RW) << PAGE_READ_SHIFT) |
    245             ((ap == PTE_AP_USER_RW_KERNEL_RW) << PAGE_READ_SHIFT) |
    246             ((ap == PTE_AP_USER_RW_KERNEL_RW) << PAGE_WRITE_SHIFT) |
    247             ((ap != PTE_AP_USER_NO_KERNEL_RW) << PAGE_USER_SHIFT) |
    248             ((ap == PTE_AP_USER_NO_KERNEL_RW) << PAGE_READ_SHIFT) |
    249             ((ap == PTE_AP_USER_NO_KERNEL_RW) << PAGE_WRITE_SHIFT) |
    250             (1 << PAGE_EXEC_SHIFT) |
    251             (p->bufferable << PAGE_CACHEABLE);
    252 }
    253 
    254 /** Sets flags of level 0 page table entry.
    255  *
    256  * @param pt    level 0 page table
    257  * @param i     index of the entry to be changed
    258  * @param flags new flags
    259  *
    260  */
    261 NO_TRACE static inline void set_pt_level0_flags(pte_t *pt, size_t i, int flags)
    262 {
    263         pte_level0_t *p = &pt[i].l0;
    264        
    265         if (flags & PAGE_NOT_PRESENT) {
    266                 p->descriptor_type = PTE_DESCRIPTOR_NOT_PRESENT;
    267                 /*
    268                  * Ensures that the entry will be recognized as valid when
    269                  * PTE_VALID_ARCH applied.
    270                  */
    271                 p->should_be_zero = 1;
    272         } else {
    273                 p->descriptor_type = PTE_DESCRIPTOR_COARSE_TABLE;
    274                 p->should_be_zero = 0;
    275         }
    276 }
    277 
    278 NO_TRACE static inline void set_pt_level0_present(pte_t *pt, size_t i)
    279 {
    280         pte_level0_t *p = &pt[i].l0;
    281 
    282         p->should_be_zero = 0;
    283         write_barrier();
    284         p->descriptor_type = PTE_DESCRIPTOR_COARSE_TABLE;
    285 }
    286 
    287 /** Sets flags of level 1 page table entry.
    288  *
    289  * We use same access rights for the whole page. When page
    290  * is not preset we store 1 in acess_rigts_3 so that at least
    291  * one bit is 1 (to mark correct page entry, see #PAGE_VALID_ARCH).
    292  *
    293  * @param pt    Level 1 page table.
    294  * @param i     Index of the entry to be changed.
    295  * @param flags New flags.
    296  *
    297  */
    298 NO_TRACE static inline void set_pt_level1_flags(pte_t *pt, size_t i, int flags)
    299 {
    300         pte_level1_t *p = &pt[i].l1;
    301        
    302         if (flags & PAGE_NOT_PRESENT)
    303                 p->descriptor_type = PTE_DESCRIPTOR_NOT_PRESENT;
    304         else
    305                 p->descriptor_type = PTE_DESCRIPTOR_SMALL_PAGE;
    306        
    307         p->cacheable = p->bufferable = (flags & PAGE_CACHEABLE) != 0;
    308        
    309         /* default access permission */
    310         p->access_permission_0 = p->access_permission_1 =
    311             p->access_permission_2 = p->access_permission_3 =
    312             PTE_AP_USER_NO_KERNEL_RW;
    313        
    314         if (flags & PAGE_USER)  {
    315                 if (flags & PAGE_READ) {
    316                         p->access_permission_0 = p->access_permission_1 =
    317                             p->access_permission_2 = p->access_permission_3 =
    318                             PTE_AP_USER_RO_KERNEL_RW;
    319                 }
    320                 if (flags & PAGE_WRITE) {
    321                         p->access_permission_0 = p->access_permission_1 =
    322                             p->access_permission_2 = p->access_permission_3 =
    323                             PTE_AP_USER_RW_KERNEL_RW;
    324                 }
    325         }
    326 }
    327 
    328 NO_TRACE static inline void set_pt_level1_present(pte_t *pt, size_t i)
    329 {
    330         pte_level1_t *p = &pt[i].l1;
    331 
    332         p->descriptor_type = PTE_DESCRIPTOR_SMALL_PAGE;
    333 }
    334        
    335 extern void page_arch_init(void);
    336 
    337 #endif /* __ASM__ */
     131#if defined(PROCESSOR_ARCH_armv6) | defined(PROCESSOR_ARCH_armv7_a)
     132#include "page_armv6.h"
     133#elif defined(PROCESSOR_ARCH_armv4) | defined(PROCESSOR_ARCH_armv5)
     134#include "page_armv4.h"
     135#else
     136#error "Unsupported architecture"
     137#endif
    338138
    339139#endif
  • kernel/arch/arm32/include/arch/mm/page_fault.h

    rea906c29 r850235d  
    4040
    4141
    42 /** Decribes CP15 "fault status register" (FSR). */
    43 typedef struct {
    44         unsigned status : 3;
    45         unsigned domain : 4;
    46         unsigned zero : 1;
    47         unsigned should_be_zero : 24;
    48 } ATTRIBUTE_PACKED fault_status_t;
    49 
    50 
    51 /** Help union used for casting integer value into #fault_status_t. */
     42/** Decribes CP15 "fault status register" (FSR).
     43 *
     44 * "VMSAv6 added a fifth fault status bit (bit[10]) to both the IFSR and DFSR.
     45 * It is IMPLEMENTATION DEFINED how this bit is encoded in earlier versions of
     46 * the architecture. A write flag (bit[11] of the DFSR) has also been
     47 * introduced."
     48 * ARM Architecture Reference Manual version i ch. B4.6 (PDF p. 719)
     49 *
     50 * See ARM Architecture Reference Manual ch. B4.9.6 (pdf p.743). for FSR info
     51 */
    5252typedef union {
    53         fault_status_t fs;
    54         uint32_t dummy;
    55 } fault_status_union_t;
     53        struct {
     54                unsigned status : 4;
     55                unsigned domain : 4;
     56                unsigned zero : 1;
     57                unsigned lpae : 1; /**< Needs LPAE support implemented */
     58                unsigned fs : 1; /**< armv6+ mandated, earlier IPLM. DEFINED */
     59                unsigned wr : 1; /**< armv6+ only */
     60                unsigned ext : 1 ; /**< external abort */
     61                unsigned cm : 1; /**< Cache maintenance, needs LPAE support */
     62                unsigned should_be_zero : 18;
     63        } data;
     64        struct {
     65                unsigned status : 4;
     66                unsigned sbz0 : 6;
     67                unsigned fs : 1;
     68                unsigned should_be_zero : 21;
     69        } inst;
     70        uint32_t raw;
     71} fault_status_t;
    5672
    5773
  • kernel/arch/arm32/include/arch/regutils.h

    rea906c29 r850235d  
    4141#define STATUS_REG_MODE_MASK         0x1f
    4242
    43 #define CP15_R1_HIGH_VECTORS_BIT     (1 << 13)
    44 
    4543/* ARM Processor Operation Modes */
    46 #define USER_MODE        0x10
    47 #define FIQ_MODE         0x11
    48 #define IRQ_MODE         0x12
    49 #define SUPERVISOR_MODE  0x13
    50 #define ABORT_MODE       0x17
    51 #define UNDEFINED_MODE   0x1b
    52 #define SYSTEM_MODE      0x1f
    53 
     44enum {
     45        USER_MODE = 0x10,
     46        FIQ_MODE = 0x11,
     47        IRQ_MODE = 0x12,
     48        SUPERVISOR_MODE = 0x13,
     49        MONITOR_MODE = 0x16,
     50        ABORT_MODE = 0x17,
     51        HYPERVISOR_MODE = 0x1a,
     52        UNDEFINED_MODE = 0x1b,
     53        SYSTEM_MODE = 0x1f,
     54        MODE_MASK = 0x1f,
     55};
    5456/* [CS]PRS manipulation macros */
    5557#define GEN_STATUS_READ(nm, reg) \
  • 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.