first and last commit

This commit is contained in:
Chris Nutter committed 2023-07-08 13:03:17 -07:00
commit 1bf4efd552
2612 files changed
+636500

No files matched your search

+627
View File
@@ -0,0 +1,627 @@
/*
* Copyright (C) 2007-2011 Apple Inc. All rights reserved.
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <arch/arm/assembler.h>
.text
#define ALL_ROUTINES 1
// Define isb as a nop for older architectures
#if !ARCH_ARMv7
#define isb nop
#define dsb nop
#endif /* ! ARCH_ARMv7 */
ARM_FUNCTION _arm_read_cpsr
mrs r0, cpsr
bx lr
#if ALL_ROUTINES
ARM_FUNCTION _arm_read_main_id
mrc p15, 0, r0, c0, c0, 0
bx lr
#endif
#if ALL_ROUTINES
ARM_FUNCTION _arm_read_cache_id
mrc p15, 0, r0, c0, c0, 1
bx lr
ARM_FUNCTION _arm_read_cache_level_id
mrc p15, 1, r0, c0, c0, 1
bx lr
ARM_FUNCTION _arm_read_cache_size_selection
mrc p15, 2, r0, c0, c0, 0
bx lr
ARM_FUNCTION _arm_write_cache_size_selection
mcr p15, 2, r0, c0, c0, 0
isb
bx lr
ARM_FUNCTION _arm_read_cache_size_id
mrc p15, 1, r0, c0, c0, 0
bx lr
#endif
#if ALL_ROUTINES
ARM_FUNCTION _arm_read_extended_feature_regs
mov r12, r0
mrc p15, 0, r0, c0, c1, 0
mrc p15, 0, r1, c0, c1, 1
mrc p15, 0, r2, c0, c1, 2
mrc p15, 0, r3, c0, c1, 3
stmia r12!, { r0-r3 }
mrc p15, 0, r0, c0, c1, 4
mrc p15, 0, r1, c0, c1, 5
mrc p15, 0, r2, c0, c1, 6
mrc p15, 0, r3, c0, c1, 7
stmia r12!, { r0-r3 }
mrc p15, 0, r0, c0, c2, 0
mrc p15, 0, r1, c0, c2, 1
mrc p15, 0, r2, c0, c2, 2
mrc p15, 0, r3, c0, c2, 3
stmia r12!, { r0-r3 }
mrc p15, 0, r0, c0, c2, 4
mrc p15, 0, r1, c0, c2, 5
mrc p15, 0, r2, c0, c2, 6
mrc p15, 0, r3, c0, c2, 7
stmia r12, { r0-r3 }
bx lr
#endif
#if ALL_ROUTINES
ARM_FUNCTION _arm_read_memory_model_feature_regs
mov r12, r0
mrc p15, 0, r0, c0, c1, 4
mrc p15, 0, r1, c0, c1, 5
mrc p15, 0, r2, c0, c1, 6
mrc p15, 0, r3, c0, c1, 7
stmia r12, { r0-r3 }
bx lr
#endif
#if ALL_ROUTINES
ARM_FUNCTION _arm_read_instruction_set_attribute_regs
mov r12, r0
mrc p15, 0, r0, c0, c2, 0
mrc p15, 0, r1, c0, c2, 1
mrc p15, 0, r2, c0, c2, 2
mrc p15, 0, r3, c0, c2, 3
stmia r12!, { r0-r3 }
mrc p15, 0, r0, c0, c2, 4
mrc p15, 0, r1, c0, c2, 5
stmia r12!, { r0-r1 }
bx lr
#endif
ARM_FUNCTION _arm_read_cr
mrc p15, 0, r0, c1, c0, 0
bx lr
ARM_FUNCTION _arm_write_cr
mcr p15, 0, r0, c1, c0, 0
isb
bx lr
ARM_FUNCTION _arm_read_aux_cr
mrc p15, 0, r0, c1, c0, 1
bx lr
ARM_FUNCTION _arm_write_aux_cr
mcr p15, 0, r0, c1, c0, 1
isb
bx lr
ARM_FUNCTION _arm_write_dar
mcr p15, 0, r0, c3, c0, 0
isb
bx lr
ARM_FUNCTION _arm_write_ttb
mcr p15, 0, r0, c2, c0, 0
isb
bx lr
ARM_FUNCTION _arm_write_ttbcr
mcr p15, 0, r0, c2, c0, 2
isb
bx lr
ARM_FUNCTION _arm_read_ifsr
mrc p15, 0, r0, c5, c0, 1
bx lr
ARM_FUNCTION _arm_read_dfsr
mrc p15, 0, r0, c5, c0, 0
bx lr
ARM_FUNCTION _arm_read_ifar
#if ARCH_ARMv7
mrc p15, 0, r0, c6, c0, 2
bx lr
#endif
ARM_FUNCTION _arm_read_dfar
mrc p15, 0, r0, c6, c0, 0
bx lr
ARM_FUNCTION _arm_read_cp_access_cr
mrc p15, 0, r0, c1, c0, 2
bx lr
ARM_FUNCTION _arm_write_cp_access_cr
mcr p15, 0, r0, c1, c0, 2
isb
bx lr
#if WITH_VFP
ARM_FUNCTION _arm_read_fpexc
vmrs r0, fpexc
bx lr
ARM_FUNCTION _arm_write_fpexc
vmsr fpexc, r0
bx lr
ARM_FUNCTION _arm_read_fpscr
vmrs r0, fpscr
bx lr
ARM_FUNCTION _arm_write_fpscr
vmsr fpscr, r0
bx lr
// Reset core registers to a known value. Kingfisher doesnt
// do this on reset, and simulation traces will show 'x'
// uninitialized values otherwise. Prefer deterministic
ARM_FUNCTION _arm_init_fp_regs
vmov.i64 q0, #0
vmov q1, q0
vmov q2, q0
vmov q3, q0
vmov q4, q0
vmov q5, q0
vmov q6, q0
vmov q7, q0
#if FP_REGISTER_COUNT > 16
vmov q8, q0
vmov q9, q0
vmov q10, q0
vmov q11, q0
vmov q12, q0
vmov q13, q0
vmov q14, q0
vmov q15, q0
#endif
bx lr
#endif
#if ARCH_ARMv7
ARM_FUNCTION _arm_read_l2_aux_cr
mrc p15, 1, r0, c9, c0, 2
bx lr
ARM_FUNCTION _arm_write_l2_aux_cr
mcr p15, 1, r0, c9, c0, 2
isb
bx lr
ARM_FUNCTION _arm_read_pmreg
cmp r0, #0
bne 1f
mrc p15, 0, r0, c9, c12, 0
b 2f
1: cmp r0, #1
bne 1f
mrc p15, 0, r0, c9, c12, 1
b 2f
1: cmp r0, #2
bne 1f
mrc p15, 0, r0, c9, c12, 2
b 2f
1: cmp r0, #3
bne 1f
mrc p15, 0, r0, c9, c12, 3
b 2f
1: cmp r0, #4
bne 1f
mrc p15, 0, r0, c9, c12, 4
b 2f
1: cmp r0, #5
bne 1f
mrc p15, 0, r0, c9, c12, 5
b 2f
1: cmp r0, #6
bne 1f
mrc p15, 0, r0, c9, c13, 0
b 2f
1: cmp r0, #7
bne 1f
mrc p15, 0, r0, c9, c13, 1
b 2f
1: cmp r0, #8
bne 2f
mrc p15, 0, r0, c9, c13, 2
b 2f
1: cmp r0, #9
bne 2f
mcr p15, 0, r0, c9, c14, 0
b 2f
1: cmp r0, #10
bne 2f
mcr p15, 0, r0, c9, c14, 1
b 2f
1: cmp r0, #11
bne 2f
mcr p15, 0, r0, c9, c14, 2
2: isb
bx lr
ARM_FUNCTION _arm_write_pmreg
cmp r0, #0
bne 1f
mcr p15, 0, r1, c9, c12, 0
b 2f
1: cmp r0, #1
bne 1f
mcr p15, 0, r1, c9, c12, 1
b 2f
1: cmp r0, #2
bne 1f
mcr p15, 0, r1, c9, c12, 2
b 2f
1: cmp r0, #3
bne 1f
mcr p15, 0, r1, c9, c12, 3
b 2f
1: cmp r0, #4
bne 1f
mcr p15, 0, r1, c9, c12, 4
b 2f
1: cmp r0, #5
bne 1f
mcr p15, 0, r1, c9, c12, 5
b 2f
1: cmp r0, #6
bne 1f
mcr p15, 0, r1, c9, c13, 0
b 2f
1: cmp r0, #7
bne 1f
mcr p15, 0, r1, c9, c13, 1
b 2f
1: cmp r0, #8
bne 2f
mcr p15, 0, r1, c9, c13, 2
b 2f
1: cmp r0, #9
bne 2f
mcr p15, 0, r1, c9, c14, 0
b 2f
1: cmp r0, #10
bne 2f
mcr p15, 0, r1, c9, c14, 1
b 2f
1: cmp r0, #11
bne 2f
mcr p15, 0, r1, c9, c14, 2
2: isb
bx lr
#endif /* ARCH_ARMv7 */
#if ALL_ROUTINES
ARM_FUNCTION _arm_read_user_rw_tid
mrc p15, 0, r0, c13, c0, 2
bx lr
ARM_FUNCTION _arm_write_user_rw_tid
mcr p15, 0, r0, c13, c0, 2
isb
bx lr
ARM_FUNCTION _arm_read_user_ro_tid
mrc p15, 0, r0, c13, c0, 3
bx lr
ARM_FUNCTION _arm_write_user_ro_tid
mcr p15, 0, r0, c13, c0, 3
isb
bx lr
ARM_FUNCTION _arm_read_sup_tid
mrc p15, 0, r0, c13, c0, 4
bx lr
ARM_FUNCTION _arm_write_sup_tid
mcr p15, 0, r0, c13, c0, 4
isb
bx lr
#endif
ARM_FUNCTION _arm_read_perip_port_remap
mrc p15, 0, r0, c15, c2, 4
bx lr
ARM_FUNCTION _arm_write_perip_port_remap
mcr p15, 0, r0, c15, c2, 4
isb
bx lr
ARM_FUNCTION _arm_flush_tlbs
mov r0, #0
mcr p15, 0, r0, c8, c7, 0
dsb
isb
bx lr
#define EXT(x) _ ## x
#if ALL_ROUTINES
/* mpu routines */
#define WRITE_DATA_PROT_REGION(func, n) \
.global EXT(func); \
EXT(func): \
mcr p15, 0, r0, c6, c##n, 0; \
isb
bx lr
WRITE_DATA_PROT_REGION(arm_write_dprot_region_0, 0)
WRITE_DATA_PROT_REGION(arm_write_dprot_region_1, 1)
WRITE_DATA_PROT_REGION(arm_write_dprot_region_2, 2)
WRITE_DATA_PROT_REGION(arm_write_dprot_region_3, 3)
WRITE_DATA_PROT_REGION(arm_write_dprot_region_4, 4)
WRITE_DATA_PROT_REGION(arm_write_dprot_region_5, 5)
WRITE_DATA_PROT_REGION(arm_write_dprot_region_6, 6)
WRITE_DATA_PROT_REGION(arm_write_dprot_region_7, 7)
WRITE_DATA_PROT_REGION(arm_write_dprot_region_8, 8)
#define WRITE_INSTRUCTION_PROT_REGION(func, n) \
.global EXT(func); \
EXT(func): \
mcr p15, 0, r0, c6, c##n, 1; \
isb
bx lr
WRITE_INSTRUCTION_PROT_REGION(arm_write_iprot_region_0, 0)
WRITE_INSTRUCTION_PROT_REGION(arm_write_iprot_region_1, 1)
WRITE_INSTRUCTION_PROT_REGION(arm_write_iprot_region_2, 2)
WRITE_INSTRUCTION_PROT_REGION(arm_write_iprot_region_3, 3)
WRITE_INSTRUCTION_PROT_REGION(arm_write_iprot_region_4, 4)
WRITE_INSTRUCTION_PROT_REGION(arm_write_iprot_region_5, 5)
WRITE_INSTRUCTION_PROT_REGION(arm_write_iprot_region_6, 6)
WRITE_INSTRUCTION_PROT_REGION(arm_write_iprot_region_7, 7)
WRITE_INSTRUCTION_PROT_REGION(arm_write_iprot_region_8, 8)
.global _arm_write_data_prot_register
_arm_write_data_prot_register:
mcr p15, 0, r0, c5, c0, 0
isb
bx lr
.global _arm_write_ins_prot_register
_arm_write_ins_prot_register:
mcr p15, 0, r0, c5, c0, 1
isb
bx lr
.global _arm_write_cacheable_registers
_arm_write_cacheable_registers:
mcr p15, 0, r0, c2, c0, 0
mcr p15, 0, r1, c2, c0, 1
isb
bx lr
.global _arm_write_bufferable_register
_arm_write_bufferable_register:
mcr p15, 0, r0, c3, c0, 0
isb
bx lr
#endif
/* uint arch_enable_ints(void); */
ARM_FUNCTION _arch_enable_ints
mrs r0, cpsr
bic r1, r0, #(1<<7)
#if WITH_FIQ_TIMER
bic r1, r1, #(1<<6)
#endif
msr cpsr_c, r1
and r0, r0, #(1<<7)
bx lr
/* uint arch_disable_ints(void); */
ARM_FUNCTION _arch_disable_ints
mrs r0, cpsr
orr r1, r0, #(1<<7)
#if WITH_FIQ_TIMER
orr r1, r1, #(1<<6)
#endif
msr cpsr_c, r1
and r0, r0, #(1<<7)
bx lr
/* uint arch_restore_ints(uint state); */
ARM_FUNCTION _arch_restore_ints
mrs r1, cpsr
and r0, r0, #(1<<7)
bic r1, r1, #(1<<7)
orr r2, r1, r0
msr cpsr_c, r2
and r0, r1, #(1<<7)
bx lr
/* void arm_enable_fiqs(void); */
ARM_FUNCTION _arm_enable_fiqs
mrs r0, cpsr
bic r0, r0, #(1<<6)
msr cpsr_c, r0
bx lr
/* void arm_disable_fiqs(void); */
ARM_FUNCTION _arm_disable_fiqs
mrs r0, cpsr
orr r0, r0, #(1<<6)
msr cpsr_c, r0
bx lr
#if ARCH_ARMv7
ARM_FUNCTION _arm_read_vbar
mrc p15, 0, r0, c12, c0, 0
bx lr
ARM_FUNCTION _arm_write_vbar
mcr p15,0, r0, c12, c0, 0
bx lr
#endif
#if ARCH_ARMv7
ARM_FUNCTION _arm_flush_branch_predictor
mov r0, #0
mcr p15, 0, r0, c7, c5, 6 /* flush the branch predictor cache */
isb
mov pc, lr
#endif
/* void arm_memory_barrier(void); */
ARM_FUNCTION _arm_memory_barrier
#if ARCH_ARMv7
dmb
#endif
bx lr
#ifdef PRODUCT_EMBEDDEDIOP
/* <rdar://problem/16290859> WFI errata workaround for Cortex-A5 */
dummy_store:
.long 0xaaaabbbb
.balign 32
#endif //PRODUCT_EMBEDDEDIOP
ARM_FUNCTION _arch_halt
#if !NO_ARM_HALT
# if ARCH_ARMv7
dsb
#ifdef PRODUCT_EMBEDDEDIOP
str r0, dummy_store
#endif //PRODUCT_EMBEDDEDIOP
wfi
# else
mov r0, #0
mcr p15, 0, r0, c7, c0, 4 /* wait for interrupt */
# endif
#endif
bx lr
ARM_FUNCTION _arch_spin
#if ARCH_ARMv7 || ARCH_ARMv8
wfe
#endif
b _arch_spin
#if WITH_ARM_DCC
ARM_FUNCTION _read_dtr
mrc p14, 0, r0, c0, c5, 0
bx lr
ARM_FUNCTION _write_dtr
mcr p14, 0, r0, c0, c5, 0
isb
bx lr
ARM_FUNCTION _read_dscr
mrc p14, 0, r0, c0, c1, 0
bx lr
#endif /* WITH_ARM_DCC */
#if CPU_APPLE_SWIFT
ARM_FUNCTION _swift_read_l2cerrsts
mrc p15, 1, r0, c15, c2, 5
bx lr
ARM_FUNCTION _swift_write_l2cerrsts
mcr p15, 1, r0, c15, c2, 5
isb
bx lr
ARM_FUNCTION _swift_read_l2cerradr
mrc p15, 1, r0, c15, c2, 7
bx lr
ARM_FUNCTION _swift_write_l2cerradr
mcr p15, 1, r0, c15, c2, 7
isb
bx lr
#endif /* CPU_APPLE_SWIFT */
+320
View File
@@ -0,0 +1,320 @@
/*
* Copyright (C) 2007-2010 Apple Inc. All rights reserved.
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <arch/arm/assembler.h>
.text
/*
* Cache functions for ARM v7
*/
/* perform loop unrolling to optimize for multi-line operations rdar://problem/6722268 */
ARM_FUNCTION _arm_clean_dcache_line_8
mcr p15, 0, r0, c7, c10, 1 // clean L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_clean_dcache_line_7
mcr p15, 0, r0, c7, c10, 1 // clean L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_clean_dcache_line_6
mcr p15, 0, r0, c7, c10, 1 // clean L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_clean_dcache_line_5
mcr p15, 0, r0, c7, c10, 1 // clean L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_clean_dcache_line_4
mcr p15, 0, r0, c7, c10, 1 // clean L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_clean_dcache_line_3
mcr p15, 0, r0, c7, c10, 1 // clean L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_clean_dcache_line_2
mcr p15, 0, r0, c7, c10, 1 // clean L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_clean_dcache_line
mcr p15, 0, r0, c7, c10, 1 // clean L1/L2 line by MVA
dmb
bx lr
/* perform loop unrolling to optimize for multi-line operations rdar://problem/6722268 */
ARM_FUNCTION _arm_invalidate_dcache_line_8
mcr p15, 0, r0, c7, c6, 1 // invalidate L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_invalidate_dcache_line_7
mcr p15, 0, r0, c7, c6, 1 // invalidate L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_invalidate_dcache_line_6
mcr p15, 0, r0, c7, c6, 1 // invalidate L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_invalidate_dcache_line_5
mcr p15, 0, r0, c7, c6, 1 // invalidate L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_invalidate_dcache_line_4
mcr p15, 0, r0, c7, c6, 1 // invalidate L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_invalidate_dcache_line_3
mcr p15, 0, r0, c7, c6, 1 // invalidate L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_invalidate_dcache_line_2
mcr p15, 0, r0, c7, c6, 1 // invalidate L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_invalidate_dcache_line
mcr p15, 0, r0, c7, c6, 1 // invalidate L1/L2 line by MVA
dmb
bx lr
/* perform loop unrolling to optimize for multi-line operations rdar://problem/6722268 */
ARM_FUNCTION _arm_clean_invalidate_dcache_line_8
mcr p15, 0, r0, c7, c14, 1 // clean/invalidate L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_clean_invalidate_dcache_line_7
mcr p15, 0, r0, c7, c14, 1 // clean/invalidate L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_clean_invalidate_dcache_line_6
mcr p15, 0, r0, c7, c14, 1 // clean/invalidate L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_clean_invalidate_dcache_line_5
mcr p15, 0, r0, c7, c14, 1 // clean/invalidate L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_clean_invalidate_dcache_line_4
mcr p15, 0, r0, c7, c14, 1 // clean/invalidate L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_clean_invalidate_dcache_line_3
mcr p15, 0, r0, c7, c14, 1 // clean/invalidate L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_clean_invalidate_dcache_line_2
mcr p15, 0, r0, c7, c14, 1 // clean/invalidate L1/L2 line by MVA
add r0, r0, #(CPU_CACHELINE_SIZE)
ARM_FUNCTION _arm_clean_invalidate_dcache_line
mcr p15, 0, r0, c7, c14, 1 // clean/invalidate L1/L2 line by MVA
dmb
bx lr
ARM_FUNCTION _arm_clean_dcache
mov r2, #((1 << CPU_CACHEINDEX_SHIFT) << CPU_CACHELINE_SHIFT)
1:
sub r2, r2, #(1 << CPU_CACHELINE_SHIFT)
mov r1, #((1 << CPU_CACHESET_SHIFT) << (32-CPU_CACHESET_SHIFT))
2:
subs r1, r1, #(1 << (32-CPU_CACHESET_SHIFT))
orr r0, r1, r2
mcr p15, 0, r0, c7, c10, 2 // clean one line by way and set
bne 2b
cmp r2, #0
bne 1b
#if L2_CACHE_SIZE
mov r2, #((1 << L2_CACHE_SETS) << 6)
1:
sub r2, r2, #(1 << 6)
mov r1, #((1 << 3) << 29)
2:
subs r1, r1, #(1 << 29)
orr r0, r1, r2
orr r0, r0, #(1 << 1)
mcr p15, 0, r0, c7, c10, 2 // clean one line by way and set
bne 2b
cmp r2, #0
bne 1b
#endif
mov r0, #0
dmb
bx lr
ARM_FUNCTION _arm_clean_invalidate_dcache
mov r2, #((1 << CPU_CACHEINDEX_SHIFT) << CPU_CACHELINE_SHIFT)
1:
sub r2, r2, #(1 << CPU_CACHELINE_SHIFT)
mov r1, #((1 << CPU_CACHESET_SHIFT) << (32-CPU_CACHESET_SHIFT))
2:
subs r1, r1, #(1 << (32-CPU_CACHESET_SHIFT))
orr r0, r1, r2
mcr p15, 0, r0, c7, c14, 2 // clean and invalidate one line by way and set
bne 2b
cmp r2, #0
bne 1b
#if L2_CACHE_SIZE
mov r2, #((1 << L2_CACHE_SETS) << 6)
1:
sub r2, r2, #(1 << 6)
mov r1, #((1 << 3) << 29)
2:
subs r1, r1, #(1 << 29)
orr r0, r1, r2
orr r0, r0, #(1 << 1)
mcr p15, 0, r0, c7, c14, 2 // clean and invalidate one line by way and set
bne 2b
cmp r2, #0
bne 1b
#endif
mov r0, #0
dmb
bx lr
ARM_FUNCTION _arm_invalidate_dcache
// This is a fancy way of writing "0". Thr first sub will make this (1<<CPU_CACHESET_SHIFT)-1
mov r1, #((1 << CPU_CACHESET_SHIFT) << (32-CPU_CACHESET_SHIFT))
mov r2, #((1 << CPU_CACHEINDEX_SHIFT) << CPU_CACHELINE_SHIFT)
1:
sub r1, r1, #(1 << (32-CPU_CACHESET_SHIFT))
orr r0, r1, r2
2:
#if (1 << CPU_CACHEINDEX_SHIFT) < 16
#error "Not enough cache sets for unroll in _arm_invalidate_dcache"
#endif
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
sub r0, r0, #(1 << CPU_CACHELINE_SHIFT)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
cmp r0, r1
bne 2b
cmp r1, #0
bne 1b
#if L2_CACHE_SIZE
mov r2, #((1 << L2_CACHE_SETS) << 6)
1:
sub r2, r2, #(1 << 6)
mov r1, #((1 << 3) << 29)
2:
subs r1, r1, #(1 << 29)
orr r0, r1, r2
orr r0, r0, #(1 << 1)
mcr p15, 0, r0, c7, c6, 2 // invalidate one line by way and set
bne 2b
cmp r2, #0
bne 1b
#endif
dmb
bx lr
ARM_FUNCTION _arm_invalidate_icache
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 /* invalidate icache + btb (if supported) */
dsb
isb
bx lr
ARM_FUNCTION _arm_clean_caches
stmfd sp!, {lr}
bl _arm_clean_dcache
bl _arm_invalidate_icache
ldmfd sp!, {lr}
bx lr
#if WITH_L1_PARITY
ARM_FUNCTION _arm_enable_l1parity
mrc p15, 0, r0, c1, c0, 1
#if CPU_ARM_CORTEX_A8
orr r0, r0, #(1 << 3) // set the L1PE bit
#elif CPU_ARM_CORTEX_A5
orr r0, r0, #(1 << 9) // set the "parity on" bit
#endif
mcr p15, 0, r0, c1, c0, 1
isb
bx lr
#endif
ARM_FUNCTION _arm_drain_write_buffer
mov r0, #0
dsb
isb
bx lr
+83
View File
@@ -0,0 +1,83 @@
#include <debug.h>
#include <sys/menu.h>
#include <arch/arm/arm.h>
void arm_l1cache_dump(int dcache, unsigned int mva)
{
register unsigned index = (mva >> 6) & 0x7f;
unsigned way, addr, word, data0, data1;
unsigned tag, i, parity, tmp;
unsigned lookup;
unsigned cr = arm_read_cr();
arm_write_cr(cr & ~((1 << 12) | (1 << 2)));
lookup = (mva != -1UL);
for (way=0; way<4; way++) {
if (!lookup) index = 0;
do {
addr = (way << 30) | (index << 6);
if (dcache) {
__asm__ volatile("mcr p15,0,%0,c15,c2,6" ::"r"(addr));
__asm__ volatile("mrc p15,0,%0,c15,c0,0" :"=r"(tag));
} else {
__asm__ volatile("mcr p15,0,%0,c15,c3,6" ::"r"(addr));
__asm__ volatile("mrc p15,0,%0,c15,c1,0" :"=r"(tag));
}
tag <<= 12;
for (word = 0; word < 16; word++) {
addr = (way << 30) | (index << 6) | (word << 2);
if (dcache) {
__asm__ volatile("mcr p15,0,%0,c15,c2,7" ::"r"(addr));
__asm__ volatile("mrc p15,0,%0,c15,c0,0" :"=r"(data0));
__asm__ volatile("mrc p15,0,%0,c15,c0,1" :"=r"(data1));
} else {
__asm__ volatile("mcr p15,0,%0,c15,c3,7" ::"r"(addr));
__asm__ volatile("mrc p15,0,%0,c15,c1,0" :"=r"(data0));
__asm__ volatile("mrc p15,0,%0,c15,c1,1" :"=r"(data1));
}
if (word == 0)
printf("PA %08x: %c ", tag | ((index & 0x3f) << 6),
dcache && (data1&1) ? 'D':' ');
parity = 0;
tmp = data0;
for (i=0; i<8; i++) {
parity ^= tmp & 0x01010101;
tmp >>= 1;
}
parity &= 0x01010101;
parity = (parity >> 21) | (parity >> 14) | (parity >> 7) | parity;
if ((parity ^ (data1 >> 2)) & 0xf)
printf(" >%08x-%x<", data0, (data1>>2)&0xf);
else
printf(" %08x", data0);
}
printf("\n");
} while (!lookup && (++index < 128));
}
arm_clean_dcache();
arm_write_cr(cr);
}
void dump_l1caches(int disable)
{
unsigned cr;
cr = arm_read_cr();
if (disable) {
arm_write_cr(cr & ~((1<<12)|(1<<2)));
arm_clean_dcache();
}
arm_l1cache_dump(0, -1);
arm_l1cache_dump(1, -1);
if (disable)
arm_write_cr(cr);
}
#if defined(WITH_MENU) && WITH_MENU
static int do_l1dump(int argc, struct cmd_arg *args) { dump_l1caches(1); return 0; }
MENU_COMMAND_DEVELOPMENT(l1dump, do_l1dump, "dump L1 i/d contents", NULL);
#endif
+164
View File
@@ -0,0 +1,164 @@
/*
* Copyright (c) 2009 Apple Inc. All rights reserved.
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <arch/arm/arm.h>
#include <arch/arch_task.h>
#include <arch/arm/assembler.h>
/*
* Task context switch support.
*
* Basic VFP/Neon floating point context switch only.
*/
/*
* Code here must remain synchronised with the structure and offsets defined in arch_task.h:
*
* struct arch_task {
* uint32_t regs[10]; // r4-r11, r13, r14
* #if WITH_VFP
* uint32_t fpscr;
* uint32_t fpexc;
* uint32_t fpinst;
* uint32_t fpinst2;
* uint64_t fpregs[32]; // assume VFP-D32
* #endif
* };
*/
/*
* void arch_task_context_switch(struct arch_task *old, struct arch_task *new_task);
*/
ARM_FUNCTION _arch_task_context_switch
/* save non-volatile core registers */
stmia r0, { r4-r11, r13, r14 }
#if WITH_VFP
#if !WITH_VFP_ALWAYS_ON
/* save fpexc */
vmrs r2, fpexc
str r2, [r0, #ARM_ARCH_TASK_FPEXC]
/* check FP enable state */
tst r2, #FPEXC_EN
beq L_fp_save_done
/* save fpscr */
vmrs r4, fpscr
str r4, [r0, #ARM_ARCH_TASK_FPSCR]
#endif
/* save the FP registers */
add r3, r0, #ARM_ARCH_TASK_FPREGS
vstm.64 r3!, { d0-d15 }
#if FP_REGISTER_COUNT > 16
vstm.64 r3, { d16-d31 }
#endif
L_fp_save_done:
#endif /* WITH_VFP */
/* select the context we're going to switch to and invoke the context restore */
mov r0, r1
b _arch_task_context_restore
/*
* void arch_task_context_restore(struct arch_task *restore_context)
*/
ARM_FUNCTION _arch_task_context_restore
#if WITH_VFP
#if !WITH_VFP_ALWAYS_ON
/* restore fpexc */
ldr r2, [r0, #ARM_ARCH_TASK_FPEXC]
vmsr fpexc, r2
/* check FP enable state */
tst r2, #FPEXC_EN
beq L_fp_restore_done
/* restore fpscr */
ldr r4, [r0, #ARM_ARCH_TASK_FPSCR]
vmsr fpscr, r4
#endif
/* restore the FP registers */
add r3, r0, #ARM_ARCH_TASK_FPREGS
vldm.64 r3!, { d0-d15 }
#if FP_REGISTER_COUNT > 16
vldm.64 r3, { d16-d31 }
#endif
L_fp_restore_done:
#endif /* WITH_VFP */
/* restore non-volatile core registers */
ldmia r0, { r4-r11, r13, r14 }
bx lr
#if WITH_VFP && !WITH_VFP_ALWAYS_ON
/*
* void arm_call_fpsaved(void *arg, void (*func)(void *arg))
*/
.globl _arm_call_fpsaved
_arm_call_fpsaved:
stmfd sp!, {lr}
/* fetch fpexc and check FP enable state */
vmrs r2, fpexc
tst r2, #FPEXC_EN
beq 1f /* bypass save if VFP is off */
/* save fpscr */
vmrs r3, fpscr
push {r3}
/* save the FP registers */
#if FP_REGISTER_COUNT > 16
vpush { d16-d31 }
#endif
vpush { d0-d15 }
1:
/* stack fpexc last, always guranteed to be on the stack */
push {r2}
/* unconditionally enable VFP for this call */
orr r2, r2, #FPEXC_EN
vmsr fpexc, r2
/* branch to the routine */
blx r1
/* pop fpexc and test whether FP was saved */
pop {r2}
tst r2, #FPEXC_EN
beq 2f
/* restore the FP registers */
vpop { d0-d15 }
#if FP_REGISTER_COUNT > 16
vpop { d16-d31 }
#endif
/* restore fpcsr */
pop {r3}
vmsr fpscr, r2
2:
/* restore fpexc last, may disable VFP */
vmsr fpexc, r2
ldmfd sp!, {lr}
bx lr
#endif /* WITH_VFP */
+60
View File
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <arch/arm/arm.h>
#include <lib/libc.h>
#include <sys.h>
#include <sys/menu.h>
#if defined(WITH_MENU) && WITH_MENU
extern char cortex_hang_start, cortex_hang_ffe, cortex_hang_end;
typedef uint32_t (*hang_func_t)(uint32_t);
static uint8_t *hang_buffer = NULL;
static hang_func_t cortex_hang;
static int do_hang(int argc, struct cmd_arg *args)
{
u_int32_t count = 10000;
utime_t before, after;
int i, ret, always = 0;
char *entry_point;
if (argc > 1)
count = args[1].u;
if (!strcmp(args[0].str, "hangloop"))
always = 1;
if (hang_buffer == NULL) {
hang_buffer = malloc(8192);
entry_point = (char *)((((uint32_t)hang_buffer + 0xfff) & ~0xfff) -
(&cortex_hang_ffe + 2 - &cortex_hang_start));
memcpy(entry_point, &cortex_hang_start, &cortex_hang_end - &cortex_hang_start);
arm_clean_dcache();
arm_invalidate_icache();
cortex_hang = (hang_func_t)(entry_point+1); /* Thumb */
printf("Created hang code buffer; base = %p, entry = %p\n", hang_buffer, cortex_hang);
}
for (i=0; (i<100) || always; i++) {
printf("Try %3d: ", i+1);
before = system_time();
ret = cortex_hang(count);
after = system_time();
printf("complete; time = %6d\n", after-before);
if (ret != 0) printf(" EARLY EXIT!\n");
}
return 0;
}
MENU_COMMAND_DEBUG(hang, do_hang, "try to hang cortex", NULL);
MENU_COMMAND_DEBUG(hangloop, do_hang, "try to hang cortex - run forever", NULL);
#endif
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
.text
.global _cortex_hang_start, _cortex_hang_ffe, _cortex_hang_end
.thumb
.syntax unified
// Believe it or not, without this, it does not fail
#define NOP mov r8,r8
// R0 holds the number of iterations we should run
// start this routine at a page boundary
_cortex_hang_start:
// save some registers and set aside a word
push {r4,r5,r6,r7,lr}
sub sp, #4
1:
cmp r0, #0
beq 1f
NOP // 0xff0
NOP // 0xff2
NOP // 0xff4
NOP // 0xff6
subs r0, #1 // 0xff8
str.w ip, [sp] // 0xffa
_cortex_hang_ffe:
bl 1b // 0xffe
1:
add sp, #4
pop {r4,r5,r6,r7,pc}
bx lr
_cortex_hang_end:
+276
View File
@@ -0,0 +1,276 @@
/*
* Copyright (C) 2007-2013 Apple Inc. All rights reserved.
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <arch.h>
#include <arch/arm/arm.h>
#include <debug.h>
#include <platform.h>
#include <platform/memmap.h>
#if PERIPH_PORT_REMAP
static void config_periph_port_remap(void *base, size_t len);
#endif
#if WITH_EARLY_ICACHE && WITH_L1_PARITY
#error Early i-cache init and L1 parity enable are mutually exclusive
#endif
int arch_cpu_init(bool resume)
{
u_int32_t cr, aux_cr;
aux_cr = 0;
#if WITH_CACHE
/* make sure the cpu caches are invalidated */
#if !WITH_EARLY_ICACHE
/* d-cache init is deferred if we're turning i-cache on early */
arm_invalidate_dcache();
#endif
arm_invalidate_icache();
#endif
#if ARCH_ARMv7
aux_cr = arm_read_aux_cr();
#if CPU_ARM_CORTEX_A8
// Ask platform if WFI should be enabled or not
if (platform_get_core_idle_enable()) {
aux_cr &= ~(1 << 8);
} else {
aux_cr |= (1 << 8);
}
#endif
#if WITH_ARCHITECTED_L2
/* Manage the v7 L2 cache */
# if WITH_AUX_L2_ENABLE_BIT && L2_CACHE_SIZE
aux_cr |= (1 << 1);
# else
aux_cr &= ~(1 << 1);
# endif
#endif
#if SET_AUX_SMP_BIT
/* Set SMP bit; enable snooping within cluster and sharing of L2 */
aux_cr |= (1 << 6);
#endif
arm_write_aux_cr(aux_cr);
#endif
/* read control register default value */
cr = arm_read_cr();
#if WITH_BRANCH_PREDICTION
/* turn on branch predictor */
cr |= (1 << 11);
#endif
#if WITH_CACHE && WITH_EARLY_ICACHE
/* early i-cache enable */
cr |= (1 << 12);
arm_write_cr(cr);
#endif
#if PERIPH_PORT_REMAP
/* do any peripheral port remapping */
config_periph_port_remap((void *)PERIPH_BASE, PERIPH_LEN);
#endif
#if WITH_CACHE
#if WITH_EARLY_ICACHE
/* d-cache invalidation delayed until this point */
arm_invalidate_dcache();
#else
/* turn on i-cache */
cr |= (1 << 12);
#endif
/* turn on d-cache */
cr |= (1 << 2);
#if WITH_L1_PARITY
arm_enable_l1parity();
#endif
#endif
#if WITH_UNALIGNED_MEM
/* enable unaligned access handler */
cr &= ~(1 << 1);
#if !ARCH_ARMv7
cr |= (1 << 22);
#endif
#endif
/* enable the caches and etc. before setting up the translation table */
arm_write_cr(cr);
#if WITH_MMU
/* set up the translation table and then turn on the MMU */
arm_mmu_init(resume);
cr |= (1 << 0);
arm_write_cr(cr);
#endif
#if WITH_VFP
/* initialize VFP */
arm_fp_init();
#if WITH_VFP_ALWAYS_ON
arm_fp_enable(true);
#endif
#endif
return 0;
}
int arch_cpu_quiesce(void)
{
u_int32_t cr, aux_cr;
aux_cr = 0;
#if ARCH_ARMv7
aux_cr = arm_read_aux_cr();
#if CPU_ARM_CORTEX_A8
/* turn WFI on */
aux_cr &= ~(1 << 8);
#endif
arm_write_aux_cr(aux_cr);
#endif
#if WITH_CACHE && !CLEAN_INV_CACHE_ON_QUIESCE
/* clean the d-cache */
arm_clean_dcache();
#endif
/* read the control regiser base value */
cr = arm_read_cr();
#if WITH_MMU
/* turn off the mmu */
cr &= ~(1 << 0);
#endif
#if WITH_CACHE
/* turn off d-cache */
cr &= ~(1 << 2);
/* turn off i-cache */
cr &= ~(1 << 12);
#endif
#if WITH_BRANCH_PREDICTION
/* turn off branch predictor */
cr &= ~(1 << 11);
#endif
#if WITH_UNALIGNED_MEM
/* disable unaligned access handler */
cr |= (1 << 1);
cr &= ~(1 << 22);
#endif
/* disable the MMU, caches and etc. */
arm_write_cr(cr);
#if WITH_CACHE && CLEAN_INV_CACHE_ON_QUIESCE
/* clean and/or invalidate the caches */
arm_clean_invalidate_dcache();
arm_invalidate_icache();
#endif
#if CPU_APPLE_SWIFT
#if !CLEAN_INV_CACHE_ON_QUIESCE
/* Invalidate all lines in the L1-D cache */
arm_invalidate_dcache();
#endif
/* Clear any pending L2C errors */
swift_write_l2cerrsts(0);
swift_write_l2cerradr(0);
#endif /* CPU_APPLE_SWIFT */
return 0;
}
int arch_cpu_init_posttasks(void)
{
#if WITH_ARM_DCC
/* initialize the DCC mechanism */
arm_dcc_init();
#endif
return 0;
}
u_int32_t arch_get_noncached_address(u_int32_t address)
{
#if WITH_MMU
return arm_get_noncached_address(address);
#else
return address; /* not really any other choice... */
#endif
}
#if PERIPH_PORT_REMAP
static void config_periph_port_remap(void *base, size_t len)
{
uint32_t val = (uint32_t)base;
switch (len) {
case 0: val |= 0x0; break;
case 0x1000: val |= 0x3; break;
case 0x2000: val |= 0x4; break;
case 0x4000: val |= 0x5; break;
case 0x8000: val |= 0x6; break;
case 0x10000: val |= 0x7; break;
case 0x20000: val |= 0x8; break;
case 0x40000: val |= 0x9; break;
case 0x80000: val |= 0xa; break;
case 0x100000: val |= 0xb; break;
case 0x200000: val |= 0xc; break;
case 0x400000: val |= 0xd; break;
case 0x800000: val |= 0xe; break;
case 0x1000000: val |= 0xf; break;
case 0x2000000: val |= 0x10; break;
case 0x4000000: val |= 0x11; break;
case 0x8000000: val |= 0x12; break;
case 0x10000000: val |= 0x13; break;
case 0x20000000: val |= 0x14; break;
case 0x40000000: val |= 0x15; break;
case 0x80000000: val |= 0x16; break;
}
arm_write_perip_port_remap(val);
}
#endif
static bool cpu_setup_mmu(bool resume)
{
#if WITH_MMU
arm_mmu_init(resume);
return true;
#endif
#if WITH_MPU
arm_mpu_init();
return true;
#endif
return false;
}
+108
View File
@@ -0,0 +1,108 @@
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <arch.h>
#include <debug.h>
#include <sys.h>
#include <sys/task.h>
#include <lib/cbuf.h>
#define DSCR_WDTR_FULL (1L<<29)
#define DSCR_RDTR_FULL (1L<<30)
#if ARM_DCC_SYNCHRONOUS
static bool dcc_wait_tx = true;
#else
static bool dcc_wait_tx;
#endif
#ifndef DCC_TX_BUFFER_SIZE
# define DCC_TX_BUFFER_SIZE 256
#endif
static struct cbuf *dcc_output_cbuf;
extern u_int32_t read_dtr(void);
extern void write_dtr(u_int32_t c);
extern u_int32_t read_dscr(void);
void arm_write_dcc_char(int c)
{
if (dcc_wait_tx) {
while (read_dscr() & DSCR_WDTR_FULL);
write_dtr(c);
} else {
if (dcc_output_cbuf != 0)
cbuf_write_char(dcc_output_cbuf, c);
}
}
int arm_read_dcc_char(void)
{
while (!(read_dscr() & DSCR_RDTR_FULL));
return read_dtr();
}
int arm_read_dcc_char_nowait(void)
{
if (!(read_dscr() & DSCR_RDTR_FULL))
return -1;
return read_dtr();
}
static int dcc_read_task(void *arg)
{
for(;;) {
int c;
c = arm_read_dcc_char_nowait();
if (c >= 0) {
if (c != '\r')
debug_pushchar(c);
}
task_sleep(1 * 1000);
}
return 0;
}
static int dcc_write_task(void *arg)
{
for(;;) {
ssize_t ret;
char c;
ret = cbuf_read_char(dcc_output_cbuf, &c);
if (ret == 1) {
while(read_dscr() & DSCR_WDTR_FULL)
task_yield();
write_dtr(c);
}
task_sleep(1 * 1000);
}
return 0;
}
int arm_dcc_init(void)
{
if (arm_read_dcc_char_nowait() >= 0)
dcc_wait_tx = true;
if (!dcc_wait_tx) {
dcc_output_cbuf = cbuf_create(DCC_TX_BUFFER_SIZE, NULL);
task_start(task_create("dcc write", &dcc_write_task, NULL, 256));
}
task_start(task_create("dcc read", &dcc_read_task, NULL, 512));
return 0;
}
+19
View File
@@ -0,0 +1,19 @@
# Copyright (C) 2007 Apple Inc. All rights reserved.
#
# This document is the property of Apple Inc.
# It is considered confidential and proprietary.
#
# This document may not be reproduced or transmitted in any form,
# in whole or in part, without the express written permission of
# Apple Inc.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
OPTIONS += \
WITH_ARM_DCC=1
MODULES += \
lib/cbuf
ALL_OBJS += \
$(LOCAL_DIR)/dcc.o
+39
View File
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2010 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <arch/arm/assembler.h>
.text
// u_int32_t arch_get_entropy(volatile u_int32_t *counter_address)
//
// arch_get_entropy exploits the uncertainty in the asynchronous boundary crossing
// between the CPU and a counter. To work correctly, the CPU and counter must be
// derived from clocks with relative jitter (PLL vs. OSC). Ideally the inner loop,
// up to 32 iterations, should consume a large part of the effective read period of
// the counter.
//
ARM_FUNCTION _arch_get_entropy
mov r1, r0
mov r0, #0
mov r2, #32
1:
mov r3, r2
2:
subs r3, r3, #1
bne 2b
ldr r3, [r1]
and r3, r3, #1
orr r0, r3, r0, lsl #1
subs r2, r2, #1
bne 1b
bx lr
+195
View File
@@ -0,0 +1,195 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2007-2013 Apple Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <arch/arm/arm.h>
#include <arch/arm/assembler.h>
/*
* struct arm_exception_frame {
* uint32_t sp;
* uint32_t lr;
* uint32_t spsr;
* uint32_t r[13];
* uint32_t pc;
* uint64_t fpr[32];
* uint32_t fpscr;
* uint32_t fpexc;
* };
*
* Note that when returning to the mode in which the exception was
* taken that set the I and F bits to mask interrupts and clear the
* T bit so that we stay in ARM mode.
*/
#if VFP_REV >= 3
#define VFP_SAVE \
vstmdb.64 sp!, {d0-d3} ; \
vstmdb.64 sp!, {d4-d7} ; \
vstmdb.64 sp!, {d8-d11} ; \
vstmdb.64 sp!, {d12-d15} ; \
vstmdb.64 sp!, {d16-d19} ; \
vstmdb.64 sp!, {d20-d23} ; \
vstmdb.64 sp!, {d24-d27} ; \
vstmdb.64 sp!, {d28-d31} ; \
fmrx r1, fpscr ; \
stmfd sp!, { r1 } ; \
fmrx r1, fpexc ; \
stmfd sp!, { r1 }
#define VFP_LOAD \
ldmfd sp!, { r1 } ; \
fmxr fpexc, r1 ; \
ldmfd sp!, { r1 } ; \
vldmia.64 sp!, {d28-d31} ; \
vldmia.64 sp!, {d24-d27} ; \
vldmia.64 sp!, {d20-d23} ; \
vldmia.64 sp!, {d16-d19} ; \
vldmia.64 sp!, {d12-d15} ; \
vldmia.64 sp!, {d8-d11} ; \
vldmia.64 sp!, {d4-d7} ; \
vldmia.64 sp!, {d0-d3} ; \
fmxr fpscr, r1
#else
#define VFP_SAVE
#define VFP_LOAD
#endif
#define PUSH_EXCEPTION_FRAME \
stmfd sp!, { r0-r12, lr } ; \
mrs r0, spsr ; \
stmfd sp!, { r0 } ; \
orr r0, r0, #0xc0 ; \
bic r0, r0, #(1 << 5) ; \
mrs r1, cpsr ; \
msr cpsr_c, r0 ; \
mov r2, sp ; \
mov r3, lr ; \
msr cpsr_c, r1 ; \
stmfd sp!, { r2-r3 }
#define POP_EXCEPTION_FRAME \
add sp, sp, #12 ; \
ldmfd sp!, { r0-r12, pc }^
.text
/*
* Interrupt handling.
*
* Note that FIQ is not intended to be "fast", but rather an NMI.
*/
ARM_FUNCTION ___arm_irq
sub lr, lr, #4 /* fix up return address */
PUSH_EXCEPTION_FRAME
VFP_SAVE
#if ARCH_ARMv7
mrs r1, cpsr
bic r1, #0x100 /* re-enable imprecise data aborts */
msr cpsr_x, r1
#endif
bl _arm_irq /* call handler */
VFP_LOAD
POP_EXCEPTION_FRAME
ARM_FUNCTION ___arm_fiq
sub lr, lr, #4 /* fix up return address */
/*
* We can't use PUSH_EXCEPTION_FRAME here as we need to save banked registers,
* but the only difference should be the re-saving of r8-r12 in the saved mode.
*/
stmfd sp!, { r0-r12, lr } /* save unbanked registers */
mrs r0, spsr /* save spsr */
stmfd sp!, { r0 }
add r4, sp, #36 /* address of r8 in save frame */
orr r0, r0, #0xc0 /* mask interrupts and swap to previous mode */
mrs r1, cpsr
msr cpsr_c, r0
stmia r4, { r8-r12 } /* save banked registers */
mov r2, sp /* grab sp & lr, swap back and save them */
mov r3, lr
msr cpsr_c, r1
#if ARCH_ARMv7
bic r1, #0x100 /* re-enable imprecise data aborts */
msr cpsr_x, r1
#endif
stmfd sp!, { r2-r3 }
VFP_SAVE
bl _arm_fiq /* call handler */
VFP_LOAD
POP_EXCEPTION_FRAME
/*
* Exception handling.
*
* In each case, the handler is expected to populate the
* exception frame structure and call the high-level dispatch
* routine. Note that we don't support resuming from any
* exceptions other than IRQ/FIQ.
*
*/
ARM_FUNCTION ___arm_undefined
PUSH_EXCEPTION_FRAME
mov r0, sp
bl _arm_undefined
b .
ARM_FUNCTION ___arm_syscall
PUSH_EXCEPTION_FRAME
mov r0, sp
bl _arm_syscall
b .
ARM_FUNCTION ___arm_prefetch_abort
sub lr, lr, #4
PUSH_EXCEPTION_FRAME
mov r0, sp
bl _arm_prefetch_abort
b .
ARM_FUNCTION ___arm_data_abort
PUSH_EXCEPTION_FRAME
mov r0, sp
bl _arm_data_abort
b .
ARM_FUNCTION ___arm_reserved
b .
+83
View File
@@ -0,0 +1,83 @@
/*
* Copyright (C) 2009-2015 Apple Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <arch.h>
#include <arch/arm/arm.h>
#include <debug.h>
#include <sys/task.h>
/*
* VFP/Neon support
*/
#if WITH_VFP
void
arm_fp_init(void)
{
u_int32_t cr;
cr = arm_read_cp_access_cr();
cr |= CPACR_CP_BITS(10, CPACR_CP_FULL) | CPACR_CP_BITS(11, CPACR_CP_FULL);
arm_write_cp_access_cr(cr);
}
#if WITH_VFP_ALWAYS_ON
void
arm_fp_enable(bool enable)
{
arm_write_fpexc(FPEXC_EN);
/* reset VFP/NEON state */
arm_write_fpscr(FPSCR_DEFAULT);
/* zero init VFP/NEON registers */
arm_init_fp_regs();
}
#endif /* WITH_VFP_ALWAYS_ON */
bool
arch_task_fp_enable(bool enable)
{
bool current;
u_int32_t cr;
struct task *t;
struct arch_task *at;
/* get the current FP enable state */
t = task_get_current_task();
at = &t->arch;
current = (at->fpexc & FPEXC_EN);
if (enable != current) {
/* fetch current hardware state */
cr = arm_read_fpexc();
if (enable) {
/* enable VFP/NEON */
at->fpexc = FPEXC_EN;
arm_write_fpexc(at->fpexc);
/* reset VFP/NEON state */
at->fpscr = 0;
arm_write_fpscr(FPSCR_DEFAULT);
} else {
/* disable VFP/NEON */
at->fpexc = cr & ~FPEXC_EN;
arm_write_fpexc(at->fpexc);
}
return(!enable);
}
return(enable);
}
#endif /* WITH_VFP */
+560
View File
@@ -0,0 +1,560 @@
/*
* Copyright (C) 2007-2010 Apple Inc. All rights reserved.
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <debug.h>
#include <arch.h>
#include <arch/arch_task.h>
#include <arch/arm/arm.h>
#include <sys.h>
#include <lib/libc.h>
extern void platform_irq(void);
extern void platform_fiq(void);
static const char *arm_abort_decode_status(unsigned int dfsr);
static const char *arm_decode_mode(unsigned int status_reg);
static void arm_exception_abort(struct arm_exception_frame *frame,
const char *kind,
unsigned int fsr,
unsigned int far) __noreturn;
static struct arm_exception_frame *arm_get_exception_frame(void) __pure;
static struct arm_exception_frame *arm_get_interrupt_frame(void) __pure;
static struct arm_exception_frame *arm_get_fiq_frame(void) __pure;
static void arm_print_frame_registers(struct arm_exception_frame *frame, const char *prefix);
static void arm_backtrace(const char *prefix, u_int32_t pc, u_int32_t fp, u_int32_t stack_base, u_int32_t stack_len);
static void arm_stack_for_status_reg(u_int32_t status_reg, u_int32_t *stack_base, u_int32_t *stack_len);
static bool exception_dump_near_pc;
#if WITH_MMU
static char status_str[32];
static const char *
arm_abort_decode_status(unsigned int fsr)
{
/* mask bit 10 & low 4 bits for cause decoding */
fsr &= FSR_CAUSE_MASK;
/* ARMv4v5 architecture reference B4-20 */
switch (fsr) {
case 0x01:
case 0x03:
return("alignment error");
case 0x04:
return("icache operation error");
case 0x0c:
case 0x0e:
return("external abort on translation");
case 0x05:
case 0x07:
return("translation error");
case 0x09:
case 0x0b:
return("domain violation");
case 0x0d:
case 0x0f:
return("permission violation");
case 0x08:
case 0x0a: /* this code is deprecated in ARMv7*/
return("precise external abort");
case 0x406:
return("imprecise external abort"); /* ARMv7 */
case 0x40a:
return("coprocessor data abort");
case 0x408:
return("data cache parity error"); /* ARMv7 */
case 0x409:
return("instruction cache parity error"); /* ARMv7 */
case 0x02:
return("debug event");
}
snprintf(status_str, sizeof(status_str), "<unknown cause 0x%03x>", fsr);
return(status_str);
}
#endif
static const char *
arm_decode_mode(unsigned int status_reg)
{
switch (CPSR_MODE(status_reg)) {
case CPSR_MODE_USER:
return("user");
case CPSR_MODE_FIQ:
return("FIQ");
case CPSR_MODE_IRQ:
return("IRQ");
case CPSR_MODE_SUPERVISOR:
return("supervisor");
case CPSR_MODE_ABORT:
return("abort");
case CPSR_MODE_UNDEFINED:
return("undefined");
case CPSR_MODE_SYSTEM:
return("system");
}
return("<unknown>");
}
void
arm_data_abort(struct arm_exception_frame *frame)
{
unsigned int fsr = arm_read_dfsr();
unsigned int far = arm_read_dfar();
frame->pc -= 8;
if (fsr == 0x408) {
arm_l1cache_dump(1, far);
}
arm_exception_abort(frame, "data abort", fsr, far);
}
void
arm_prefetch_abort(struct arm_exception_frame *frame)
{
unsigned int fsr = arm_read_ifsr();
unsigned int far = arm_read_ifar();
frame->pc -= 4;
if (fsr == 0x409) {
arm_l1cache_dump(0, far);
}
arm_exception_abort(frame, "prefetch abort", fsr, far);
}
void
arm_undefined(struct arm_exception_frame *frame)
{
exception_dump_near_pc = true;
frame->pc -= (frame->spsr & CPSR_STATE_THUMB) ? 2: 4;
arm_exception_abort(frame, "undefined instruction", ~0, frame->pc);
}
void
arm_syscall(struct arm_exception_frame *frame)
{
exception_dump_near_pc = true;
frame->pc -= (frame->spsr & CPSR_STATE_THUMB) ? 2: 4;
arm_exception_abort(frame, "syscall", arm_read_ifsr(), frame->pc);
}
static void
arm_exception_abort(struct arm_exception_frame *frame, const char *kind, unsigned int fsr, unsigned int far)
{
#if WITH_MMU
panic("ARM %s abort in %s mode at 0x%08x due to %s:\n"
" far 0x%08x fsr 0x%08x\n"
" r0 0x%08x 0x%08x 0x%08x 0x%08x\n"
" r4 0x%08x 0x%08x 0x%08x 0x%08x\n"
" r8 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n"
" sp 0x%08x lr 0x%08x spsr 0x%08x\n",
kind, arm_decode_mode(frame->spsr), frame->pc, arm_abort_decode_status(fsr), far, fsr,
frame->r[0], frame->r[1], frame->r[2], frame->r[3],
frame->r[4], frame->r[5], frame->r[6], frame->r[7],
frame->r[8], frame->r[9], frame->r[10], frame->r[11], frame->r[12],
frame->sp, frame->lr, frame->spsr);
#else
panic("ARM %s abort in %s mode at 0x%08x\n"
" r0 0x%08x 0x%08x 0x%08x 0x%08x\n"
" r4 0x%08x 0x%08x 0x%08x 0x%08x\n"
" r8 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n"
" sp 0x%08x lr 0x%08x spsr 0x%08x\n",
kind, arm_decode_mode(frame->spsr), frame->pc,
frame->r[0], frame->r[1], frame->r[2], frame->r[3],
frame->r[4], frame->r[5], frame->r[6], frame->r[7],
frame->r[8], frame->r[9], frame->r[10], frame->r[11], frame->r[12],
frame->sp, frame->lr, frame->spsr);
#endif
}
void
arm_irq() /* __attribute__ ((naked)) */
{
#if WITH_FIQ_TIMER
// Currently only defined on M7, M7 uses a FIQ for thetimer, and we need to hold off timer interrupts
// until we are done running ISR code to prevent unwanted preemption (e.g. <rdar://problem/16757466>)
arm_disable_fiqs();
#endif
_irq_enter_critical_section();
platform_irq();
_irq_exit_critical_section();
#if WITH_FIQ_TIMER
arm_enable_fiqs();
#endif
}
void
arm_fiq() /* __attribute__ ((naked)) */
{
_irq_enter_critical_section();
platform_fiq();
_irq_exit_critical_section();
}
/*
* Accessors for exception frame information.
*
* These may return NULL if we don't believe the frame requested is currently valid.
*
* Note that not all possible cases of nesting are necessarily handled here; only those
* that are likely to be interesting in the case of a fatality.
*/
static struct arm_exception_frame *
arm_get_exception_frame(void)
{
/*
* As exceptions are considered fatal, we don't expect to be asked for
* the exception frame in any other context.
*/
switch (CPSR_MODE(arm_read_cpsr())) {
case CPSR_MODE_ABORT:
case CPSR_MODE_UNDEFINED:
return((struct arm_exception_frame *)exc_stack_top - 1);
default:
return(NULL);
}
}
static struct arm_exception_frame *
arm_get_interrupt_frame(void)
{
switch (CPSR_MODE(arm_read_cpsr())) {
case CPSR_MODE_ABORT:
case CPSR_MODE_UNDEFINED:
/*
* In some configurations the IRQ and exception stacks share a top,
* in which case we can't return the IRQ frame because the exception
* frame has overwritten it.
*/
if (&irq_stack_top == &exc_stack_top)
return(NULL);
/*
* If we took an exception while servicing an interrupt, the IRQ frame
* will be valid.
*/
if (CPSR_MODE_IRQ != arm_get_exception_frame()->spsr)
return(NULL);
break;
case CPSR_MODE_IRQ:
/* we're in interrupt mode, so the frame is valid */
break;
case CPSR_MODE_FIQ:
/*
* If we took a FIQ while in interrupt mode, the IRQ frame will be
* valid.
*/
if (CPSR_MODE_IRQ != CPSR_MODE(arm_get_fiq_frame()->spsr))
return(NULL);
break;
default:
/* the interrupt frame is invalid in other modes */
return(NULL);
}
return ((struct arm_exception_frame *)irq_stack_top - 1);
}
static struct arm_exception_frame *
arm_get_fiq_frame(void)
{
switch (CPSR_MODE(arm_read_cpsr())) {
case CPSR_MODE_ABORT:
case CPSR_MODE_UNDEFINED:
/*
* If we took an exception while servicing a FIQ, the frame
* will be valid.
*/
if (CPSR_MODE_FIQ != CPSR_MODE(arm_get_exception_frame()->spsr))
return(NULL);
break;
case CPSR_MODE_FIQ:
/* we're in FIQ mode, so the frame is valid */
break;
default:
/* the FIQ frame is invalid in other modes */
return(NULL);
}
return((struct arm_exception_frame *)fiq_stack_top - 1);
}
/*
* arm_print_frame_registers
*
* Print the registers from an exception frame.
*/
static void
arm_print_frame_registers(struct arm_exception_frame *frame, const char *prefix)
{
dprintf(DEBUG_CRITICAL,
"%sr0 0x%08x 0x%08x 0x%08x 0x%08x\n"
"%sr4 0x%08x 0x%08x 0x%08x 0x%08x\n"
"%sr8 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n"
"%spc 0x%08x sp 0x%08x lr 0x%08x spsr 0x%08x\n",
prefix, frame->r[0], frame->r[1], frame->r[2], frame->r[3],
prefix, frame->r[4], frame->r[5], frame->r[6], frame->r[7],
prefix, frame->r[8], frame->r[9], frame->r[10], frame->r[11], frame->r[12],
prefix, frame->pc, frame->sp, frame->lr, frame->spsr);
}
/*
* arm_backtrace
*
* Print a backtrace until we run out of frames on the stack.
*/
static void
arm_backtrace(const char *prefix, u_int32_t pc, u_int32_t fp, u_int32_t stack_base, u_int32_t stack_len)
{
u_int32_t prev_fp;
u_int32_t stack_top;
u_int32_t *fpp;
/* print the mode prefix and current pc for starters */
dprintf(DEBUG_CRITICAL, " %10s 0x%08x 0x%08x\n", prefix, pc, fp);
/* sanity check our arguments as much as we can */
if ((stack_base % 4) || /* bump these to CPU_CACHELINE_SIZE if/when stack allocation gets smarter */
(stack_len % 4) ||
(stack_len < 16) ||
(stack_len > 100 * 1024)) {
dprintf(DEBUG_CRITICAL, "improbable stack, base %p size 0x%08x (task smashed?)\n", (void *)stack_base, stack_len);
return;
}
/* loop unwinding frames until we leave the stack region */
prev_fp = stack_base;
stack_top = stack_base + stack_len;
for (;;) {
/*
* Frame pointer must be aligned, must be above the previous frame, must not point outside the stack.
*
* It would be nice to have a sentinel to allow differentiating clean termination from a smashed
* stack, but that would require support in the interrupt and exception handlers.
*/
if ((fp % 4) || (fp <= prev_fp) || (fp > stack_top))
return;
/*
* Looks like it's inside the stack, so go ahead and deref it.
*/
fpp = (u_int32_t *)fp;
prev_fp = fp;
fp = fpp[0];
/*
* Print the return address for this frame.
*/
dprintf(DEBUG_CRITICAL, " 0x%08x 0x%08x\n", fpp[1], fp);
}
}
/*
* arm_stack_for_status_reg
*
* Returns the base and size of the stack for the given status register value if it's "special".
*/
static void
arm_stack_for_status_reg(u_int32_t status_reg, u_int32_t *stack_base, u_int32_t *stack_len)
{
*stack_base = 0;
*stack_len = 0;
#ifdef STACK_BASE
*stack_base = (void *)STACK_BASE;
switch (CPSR_MODE(status_reg)) {
case CPSR_MODE_FIQ:
*stack_len = FIQ_STACK_SIZE;
break;
case CPSR_MODE_IRQ:
*stack_len = IRQ_STACK_SIZE;
break;
case CPSR_MODE_ABORT:
case CPSR_MODE_UNDEFINED:
*stack_len = EXCEPTION_STACK_SIZE;
break;
}
#else
switch (CPSR_MODE(status_reg)) {
case CPSR_MODE_FIQ:
*stack_base = (u_int32_t)fiq_stack_top - FIQ_STACK_SIZE;
*stack_len = FIQ_STACK_SIZE;
break;
case CPSR_MODE_IRQ:
*stack_base = (u_int32_t)irq_stack_top - IRQ_STACK_SIZE;
*stack_len = IRQ_STACK_SIZE;
break;
case CPSR_MODE_ABORT:
case CPSR_MODE_UNDEFINED:
*stack_base = (u_int32_t)exc_stack_top - EXCEPTION_STACK_SIZE;
*stack_len = EXCEPTION_STACK_SIZE;
break;
}
#endif
}
/*
* arch_backtrace_current_task
*
* Print a backtrace for the current task.
*
* We support being called with the following context nesting:
*
* supervisor
* supervisor interrupt
* supervisor FIQ
* supervisor exception
* supervisor interrupt FIQ
* supervisor interrupt exception
* supervisor FIQ exception
* supervisor interrupt FIQ exception
*
*/
void
arch_backtrace_current_task(void *stack_base, size_t stack_len)
{
struct arm_exception_frame *exception_frame, *fiq_frame, *interrupt_frame, *outer_frame;
u_int32_t esb, esl;
u_int32_t base, count, *insn, offending_pc;
uintptr_t btext = (uintptr_t)__segment_start(__TEXT);
uintptr_t etext = (uintptr_t)__segment_end(__TEXT);
/*
* Find the stack limits for the current context and then backtrace it.
*/
arm_stack_for_status_reg(arm_read_cpsr(), &esb, &esl);
if (0 == esl) {
esb = (u_int32_t)stack_base;
esl = stack_len;
}
arm_backtrace(arm_decode_mode(arm_read_cpsr()),
(u_int32_t)&arch_backtrace_current_task, (u_int32_t)__builtin_frame_address(0),
esb, esl);
/*
* Find valid saved contexts, for the case where we may be in an exception state.
*/
exception_frame = arm_get_exception_frame();
fiq_frame = arm_get_fiq_frame();
interrupt_frame = arm_get_interrupt_frame();
outer_frame = NULL;
/*
* If we have a valid exception context, backtrace the context it was called from first.
* That context may be supervisor, FIQ or interrupt mode. If it was FIQ mode, we will
* dump the context the FIQ was called from next.
*/
if (NULL != exception_frame) {
/* dump registers at entry to exception mode */
arm_print_frame_registers(exception_frame, " ");
/*
* If the exception handler thought that the data around the PC was worth
* displaying, and we think the PC was inside the text section, display it here.
*/
if (true == exception_dump_near_pc) {
offending_pc = exception_frame->pc;
if ((offending_pc >= btext) && (offending_pc <= etext)) {
if ((offending_pc - btext) < 8) {
base = btext;
} else {
base = offending_pc - 8;
}
dprintf(DEBUG_CRITICAL, " [0x%08x:", base);
for (count = 0; count < 4; count++) {
insn = (u_int32_t *)base + count;
dprintf(DEBUG_CRITICAL, " 0x%08x", *insn);
}
dprintf(DEBUG_CRITICAL, "]\n");
} else {
dprintf(DEBUG_CRITICAL, " [pc 0x%08x not in text %p-%p]\n",
offending_pc, (void *)btext, (void *)etext);
}
}
/*
* If the exception occurred in a context with a special stack (FIQ or interrupt)
* backtrace that stack here.
*/
arm_stack_for_status_reg(exception_frame->spsr, &esb, &esl);
if (0 != esl) {
arm_backtrace(arm_decode_mode(exception_frame->spsr),
exception_frame->pc, exception_frame->r[7],
esb, esl);
} else {
/* the outer context is in the exception frame */
outer_frame = exception_frame;
}
}
/*
* If we have a valid FIQ context, backtrace the context it was invoked from now.
*/
if (NULL != fiq_frame) {
/* dump registers at entry to FIQ mode */
arm_print_frame_registers(fiq_frame, " ");
/*
* If the FIQ occurred from interrupt mode, backtrace the interrupt mode stack here.
*/
arm_stack_for_status_reg(fiq_frame->spsr, &esb, &esl);
if (0 != esl) {
arm_backtrace(arm_decode_mode(fiq_frame->spsr),
fiq_frame->pc, fiq_frame->r[7],
esb, esl);
} else {
/* the outer context is in the FIQ frame */
outer_frame = fiq_frame;
}
}
/*
* If we have an interrupt-saved context, fetch the task state from it.
*/
if (NULL != interrupt_frame) {
/* dump registers at entry to interrupt mode */
arm_print_frame_registers(interrupt_frame, " ");
outer_frame = interrupt_frame;
}
/*
* Print the task context backtrace from the outer frame.
*/
if (NULL != outer_frame) {
arm_backtrace(arm_decode_mode(outer_frame->spsr),
outer_frame->pc, outer_frame->r[7],
(u_int32_t)stack_base, (u_int32_t)stack_len);
}
}
/*
* arch_backtrace_task
*
* Print a backtrace from a saved task context.
*/
void
arch_backtrace_task(struct arch_task *arch_task, void *stack_base, size_t stack_len)
{
arm_backtrace("supervisor", arch_task->regs[ARM_ARCH_TASK_LR], arch_task->regs[ARM_ARCH_TASK_FP],
(u_int32_t)stack_base, (u_int32_t)stack_len);
}
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright (C) 2006-2011 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#ifndef __ARCH_TASK_H
#define __ARCH_TASK_H
/*
* Note that this structure is known implicitly by code in context.S, and
* must be kept in sync.
*/
#if defined(__arm__)
#ifndef __ASSEMBLY__
struct arch_task {
/*
* Core registers.
*/
uint32_t regs[10]; // r4-r11, r13, r14
#if WITH_VFP
/*
* VFP/Neon registers.
*
* Note that layout must be kept in sync with offset defines below.
*/
uint32_t fpexc;
uint32_t fpscr;
uint64_t fpregs[32];
#endif
};
#endif /* __ASSEMBLY__ */
/*
* Indices for useful core registers.
*/
#define ARM_ARCH_TASK_FP 3
#define ARM_ARCH_TASK_SP 8
#define ARM_ARCH_TASK_LR 9
/*
* VFP/Neon field offsets - it would be nice to generate these automatically.
*/
#define ARM_ARCH_TASK_FP_OFFSET 40
#define ARM_ARCH_TASK_FPEXC (ARM_ARCH_TASK_FP_OFFSET + 0)
#define ARM_ARCH_TASK_FPSCR (ARM_ARCH_TASK_FP_OFFSET + 4)
#define ARM_ARCH_TASK_FPREGS (ARM_ARCH_TASK_FP_OFFSET + 8)
#elif defined(__arm64__)
#ifndef __ASSEMBLY__
typedef __uint128_t uint128_t;
struct arch_task {
/* Core registers */
uint64_t regs[29]; // x0-x28
uint64_t fp;
uint64_t lr;
uint64_t sp;
#if WITH_VFP
/* Neon registers */
union {
uint128_t q;
uint64_t d;
uint32_t s;
} vregs[32]; // v0-v31
uint32_t fpsr;
uint32_t fpcr;
#endif
};
#endif /* __ASSEMBLY__ */
#endif /* __arm64__ */
#endif /* ! __ARCH_TASK_H */
+320
View File
@@ -0,0 +1,320 @@
/*
* Copyright (C) 2007-2011 Apple Inc. All rights reserved.
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#ifndef __ARM_H
#define __ARM_H
#ifndef __ASSEMBLER__
#include <compiler.h>
#include <non_posix_types.h>
#include <stdbool.h>
#include <stdint.h>
__BEGIN_DECLS
unsigned int arm_read_cpsr(void) __pure;
unsigned int arm_read_main_id(void) __pure;
unsigned int arm_read_cache_id(void) __pure;
unsigned int arm_read_cache_level_id(void) __pure;
unsigned int arm_read_cache_size_selection(void) __pure;
void arm_write_cache_size_selection(unsigned int);
unsigned int arm_read_cache_size_id(void) __pure;
void arm_read_memory_model_feature_regs(unsigned int regs[4]) __pure;
void arm_read_instruction_set_attribute_regs(unsigned int regs[6]) __pure;
void arm_read_extended_feature_regs(unsigned int regs[16]) __pure;
unsigned int arm_read_cr(void) __pure;
void arm_write_cr(unsigned int cr);
unsigned int arm_read_aux_cr(void) __pure;
void arm_write_aux_cr(unsigned int cr);
unsigned int arm_read_perip_port_remap(void) __pure;
void arm_write_perip_port_remap(unsigned int val);
extern uint32_t arm_read_cp_access_cr(void) __pure;
extern void arm_write_cp_access_cr(uint32_t val);
extern void arm_fp_init(void);
extern void arm_fp_enable(bool);
extern uint32_t arm_read_fpexc(void) __pure;
extern void arm_write_fpexc(uint32_t val);
extern uint32_t arm_read_fpscr(void) __pure;
extern void arm_write_fpscr(uint32_t val);
extern void arm_init_fp_regs();
#if ARCH_ARMv7
extern uint32_t arm_read_l2_aux_cr(void) __pure;
extern void arm_write_l2_aux_cr(uint32_t val);
typedef enum {
ARM_PMCR = 0, /* The order here matches a jump table in asm.S */
ARM_PMCNTENSET,
ARM_PMCNTENCLR,
ARM_PMOVSR,
ARM_PMSWINC,
ARM_PMSELR,
ARM_PMCCNTR,
ARM_PMXEVTYPER,
ARM_PMXEVCNTR,
ARM_PMUSERNR,
ARM_PMINTENSET,
ARM_PMINTENCLR,
} arm_pmreg_t;
extern uint32_t arm_read_pmreg(arm_pmreg_t reg) __pure;
extern void arm_write_pmreg(arm_pmreg_t reg, uint32_t val);
#endif /* ARCH_ARMv7 */
#if ARCH_ARMv8
extern void arm_write_mair(uint64_t mair);
extern void arm_write_tcr(uint64_t tcr);
extern void arm_write_ttbr0(void *ttbr0);
extern void arm_store_pte(uint64_t *ent_p, uint64_t ent);
#if WITH_L2_AS_RAM
extern uint64_t arm_read_l2_cramconfig(void);
#endif
#endif /* ARCH_ARMv8 */
void arm_mmu_init(bool resume);
void arm_mpu_init(void);
uint32_t arm_get_noncached_address(uint32_t address);
void arm_write_dar(unsigned int dar);
void arm_write_ttb(void *tt);
void arm_write_ttbcr(unsigned int ttbc);
#if WITH_MMU
#define FSR_CAUSE_MASK ((1 << 10) | (0xF << 0))
unsigned int arm_read_ifsr(void) __pure;
unsigned int arm_read_dfsr(void) __pure;
unsigned int arm_read_dfar(void) __pure;
unsigned int arm_read_ifar(void) __pure;
#else
# define arm_read_ifsr() ~0
# define arm_read_dfsr() ~0
# define arm_read_dfar() ~0
# define arm_read_ifar() ~0
#endif
#if WITH_CACHE_DEBUG
void arm_l1cache_dump(int dcache, unsigned int addr);
#else
#define arm_l1cache_dump(dcache, addr)
#endif
/*
* Exception frame saved at the top of the exception/interrupt stacks.
*/
struct arm_exception_frame {
uint32_t sp; /* saved stack pointer (r13) */
uint32_t lr; /* saved link register (r14) */
uint32_t spsr; /* saved cpsr */
uint32_t r[13]; /* r0 - r12 */
uint32_t pc; /* saved pc (r15) */
};
struct arm_exception_frame64 {
uint64_t regs[29]; // x0-x28
uint64_t fp;
uint64_t lr;
uint64_t sp;
uint32_t spsr;
uint32_t reserved0;
uint64_t pc;
uint64_t far;
uint32_t esr;
uint32_t reserved1;
};
extern void *irq_stack_top; /* stacks defined in start.S */
extern void *fiq_stack_top;
extern void *exc_stack_top;
extern void *svc_stack_top;
void arm_flush_tlbs(void);
void arm_invalidate_dcache(void);
void arm_invalidate_icache(void);
void arm_clean_caches(void);
void arm_clean_dcache(void);
void arm_clean_dcache_line(addr_t addr);
void arm_clean_dcache_line_2(addr_t addr);
void arm_clean_dcache_line_3(addr_t addr);
void arm_clean_dcache_line_4(addr_t addr);
void arm_clean_dcache_line_5(addr_t addr);
void arm_clean_dcache_line_6(addr_t addr);
void arm_clean_dcache_line_7(addr_t addr);
void arm_clean_dcache_line_8(addr_t addr);
void arm_invalidate_dcache_line(addr_t addr);
void arm_invalidate_dcache_line_2(addr_t addr);
void arm_invalidate_dcache_line_3(addr_t addr);
void arm_invalidate_dcache_line_4(addr_t addr);
void arm_invalidate_dcache_line_5(addr_t addr);
void arm_invalidate_dcache_line_6(addr_t addr);
void arm_invalidate_dcache_line_7(addr_t addr);
void arm_invalidate_dcache_line_8(addr_t addr);
void arm_clean_invalidate_dcache_line(addr_t addr);
void arm_clean_invalidate_dcache_line_2(addr_t addr);
void arm_clean_invalidate_dcache_line_3(addr_t addr);
void arm_clean_invalidate_dcache_line_4(addr_t addr);
void arm_clean_invalidate_dcache_line_5(addr_t addr);
void arm_clean_invalidate_dcache_line_6(addr_t addr);
void arm_clean_invalidate_dcache_line_7(addr_t addr);
void arm_clean_invalidate_dcache_line_8(addr_t addr);
void arm_clean_invalidate_dcache(void);
void arm_enable_l1parity(void);
void arm_drain_write_buffer(void);
void arm_flush_branch_predictor(void);
void arm_init_vfp(void);
void arm_enable_vfp(void);
void arm_disable_vfp(void);
void arm_enable_fiqs(void);
void arm_disable_fiqs(void);
unsigned int arm_read_vbar(void);
void arm_write_vbar(unsigned int addr);
void arm_memory_barrier(void);
/* mmu stuff */
#ifdef ARCH_ARMv8
typedef enum {
kARMMMUDeviceRX,
kARMMMUDeviceR,
kARMMMUDeviceRW,
kARMMMUNormalRX,
kARMMMUNormalR,
kARMMMUNormalRW,
kARMMMUNumExtendedAttr,
} arm_mmu_extended_attr_t;
void arm_mmu_map_range(addr_t vaddr, addr_t paddr, size_t size, arm_mmu_extended_attr_t attr);
// map in place using the specified attributes
void arm_mmu_map_rw(addr_t addr, size_t size);
void arm_mmu_map_rx(addr_t addr, size_t size);
void arm_mmu_map_ro(addr_t addr, size_t size);
void arm_mmu_map_device_rw(addr_t addr, size_t size);
void arm_mmu_map_device_rx(addr_t addr, size_t size);
void arm_mmu_map_device_ro(addr_t addr, size_t size);
#else
typedef enum {
kARMMMUStronglyOrdered = 0,
kARMMMUDevice,
kARMMMUNormal,
kARMMMUInnerNormalOuterNoncached,
kARMMMUWriteCombined,
kARMMMUNormalRX,
kARMMMUNumAttr,
} arm_mmu_attr_t;
// Section and page mapping is explicit as there is always a fixed
// granule at each level (without LPAE) in ARMv4-ARMv7.
void arm_mmu_map_section(addr_t vaddr, addr_t paddr, arm_mmu_attr_t attr, bool shared);
void arm_mmu_map_section_range(addr_t vaddr, addr_t paddr, size_t sections, arm_mmu_attr_t attr, bool shared, bool flush);
#endif
/* mpu stuff */
void mpu_init(void);
void arm_write_dprot_region_0(uint32_t base_size);
void arm_write_dprot_region_1(uint32_t base_size);
void arm_write_dprot_region_2(uint32_t base_size);
void arm_write_dprot_region_3(uint32_t base_size);
void arm_write_dprot_region_4(uint32_t base_size);
void arm_write_dprot_region_5(uint32_t base_size);
void arm_write_dprot_region_6(uint32_t base_size);
void arm_write_dprot_region_7(uint32_t base_size);
void arm_write_iprot_region_0(uint32_t base_size);
void arm_write_iprot_region_1(uint32_t base_size);
void arm_write_iprot_region_2(uint32_t base_size);
void arm_write_iprot_region_3(uint32_t base_size);
void arm_write_iprot_region_4(uint32_t base_size);
void arm_write_iprot_region_5(uint32_t base_size);
void arm_write_iprot_region_6(uint32_t base_size);
void arm_write_iprot_region_7(uint32_t base_size);
void arm_write_data_prot_register(uint32_t prot);
void arm_write_ins_prot_register(uint32_t prot);
void arm_write_cacheable_registers(uint32_t dcache, uint32_t icache);
void arm_write_bufferable_register(uint32_t buff);
/* thread id */
uint32_t arm_read_user_ro_tid(void) __pure;
uint32_t arm_read_user_rw_tid(void) __pure;
uint32_t arm_read_sup_tid(void) __pure;
void arm_write_user_ro_tid(uint32_t tid);
void arm_write_user_rw_tid(uint32_t tid);
void arm_write_sup_tid(uint32_t tid);
/* DCC based debug */
void arm_write_dcc_char(int c);
int arm_read_dcc_char(void);
int arm_read_dcc_char_nowait(void);
int arm_dcc_init(void);
#if CPU_APPLE_SWIFT
extern uint32_t swift_read_l2cerrsts(void) __pure;
extern void swift_write_l2cerrsts(uint32_t l2cerrsts);
extern uint32_t swift_read_l2cerradr(void) __pure;
extern void swift_write_l2cerradr(uint32_t l2cerradr);
#endif /* CPU_APPLE_SWIFT */
/* FP support */
#if WITH_VFP
void arm_call_fpsaved(void *arg, void (*func)(void *arg));
#endif
__END_DECLS
#endif /* __ASSEMBLER__ */
#define CPSR_MODE(_x) ((_x) & 0x1f)
#define CPSR_MODE_USER 0x10
#define CPSR_MODE_FIQ 0x11
#define CPSR_MODE_IRQ 0x12
#define CPSR_MODE_SUPERVISOR 0x13
#define CPSR_MODE_ABORT 0x17
#define CPSR_MODE_UNDEFINED 0x1b
#define CPSR_MODE_SYSTEM 0x1f
#define CPSR_STATE_THUMB 0x20
#define CPACR_CP_BITS(_cp, _bits) ((_bits) << ((_cp) * 2))
#define CPACR_CP_DENIED 0x0
#define CPACR_CP_PRIVILEGED 0x1
#define CPACR_CP_FULL 0x3
#define FPEXC_EX (1<<31)
#define FPEXC_EN (1<<30)
#define FPEXC_FP2V (1<<28)
#define FPSCR_DEFAULT (1<<25) | (1<<24) // DN, FZ bits
#endif
+34
View File
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
/*
* Declare a globally-visible ARM function
*/
.macro ARM_FUNCTION
.text
.arm
.balign 4
.global $0
$0:
.endmacro
/*
* Declare a globally-visible THUMB function
*/
.macro THUMB_FUNCTION
.text
.thumb_func $0
.balign 2
.global $0
$0:
.endmacro
+1
View File
@@ -0,0 +1 @@
_start
+176
View File
@@ -0,0 +1,176 @@
/*
* Copyright (C) 2006-2011 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <debug.h>
#include <compiler.h>
#include <sys.h>
#include <arch.h>
#include <arch/arm/arm.h>
#include <platform.h>
#include <platform/memmap.h>
#define SECTION_SIZE MB
#define LARGE_PAGE_SIZE 65536
#define PAGE_SIZE 4096
#define TTBCR_PD1 (1 << 5)
typedef u_int32_t tt_ent;
/* needs to be in non-static, initialized data for successful patching
* during IOP firmware loading */
u_int32_t tt_size __attribute__((used)) = MMU_TT_SIZE;
tt_ent *tt = (void *)0xffffffff;
/* ARM MMU first-level section descriptor definitions */
#define ARM_DESC_SECT ((0 << 18) | (1 << 1))
#define ARM_SECT_B (1 << 2)
#define ARM_SECT_C (1 << 3)
#define ARM_SECT_XN (1 << 4)
#define ARM_SECT_DOMAIN(_d) ((_d) << 5)
#define ARM_SECT_TEX(_t) ((_t) << 12)
#define ARM_SECT_SHARED (1 << 16)
#define ARM_SECT_FULLACC ((0 << 15) | (3 << 10))
#define ARM_SECT_EXEC (ARM_SECT_DOMAIN(0))
#define ARM_SECT_NOEXEC (ARM_SECT_DOMAIN(1) | ARM_SECT_XN)
#define ARM_SECT_READ_ONLY (1 << 15)
/* Non-normal memory needs XN set (and consequently a client domain assignment) to avoid
* instruction prefetch to those regions */
static u_int32_t sect_flags[] = {
[kARMMMUStronglyOrdered] = ARM_SECT_NOEXEC | ARM_SECT_FULLACC,
[kARMMMUDevice] = ARM_SECT_NOEXEC | ARM_SECT_B | ARM_SECT_FULLACC,
[kARMMMUNormal] = ARM_SECT_EXEC | ARM_SECT_C | ARM_SECT_B | ARM_SECT_FULLACC,
[kARMMMUInnerNormalOuterNoncached] = ARM_SECT_EXEC | ARM_SECT_TEX(4) | ARM_SECT_C | ARM_SECT_B | ARM_SECT_FULLACC,
[kARMMMUWriteCombined] = ARM_SECT_NOEXEC | ARM_SECT_TEX(1) | ARM_SECT_FULLACC,
[kARMMMUNormalRX] = ARM_SECT_DOMAIN(1) | ARM_SECT_C | ARM_SECT_B | ARM_SECT_READ_ONLY | ARM_SECT_FULLACC,
};
static tt_ent attr_to_sect_flags(arm_mmu_attr_t attr)
{
if (attr >= kARMMMUNumAttr)
attr = kARMMMUStronglyOrdered;
return sect_flags[attr];
}
void arm_mmu_map_section(addr_t vaddr, addr_t paddr, arm_mmu_attr_t attr, bool shared)
{
if ((vaddr & (SECTION_SIZE - 1)) != 0)
panic("section virtual address base is nonzero");
if ((paddr & (SECTION_SIZE - 1)) != 0)
panic("section physical address base is nonzero");
tt[vaddr / MB] = paddr | ARM_DESC_SECT | attr_to_sect_flags(attr) | (shared ? ARM_SECT_SHARED : 0);
arm_clean_dcache_line((unsigned long)&tt[vaddr / MB]);
arm_flush_tlbs();
}
void arm_mmu_map_section_range(addr_t vaddr, addr_t paddr, size_t sections, arm_mmu_attr_t attr, bool shared, bool flush)
{
tt_ent entry, *tt_ptr;
addr_t flush_start, flush_stop;
u_int32_t cnt;
if ((vaddr & (SECTION_SIZE - 1)) != 0)
panic("section range virtual address base is nonzero");
if ((paddr & (SECTION_SIZE - 1)) != 0)
panic("section range physical address base is nonzero");
entry = paddr | ARM_DESC_SECT | attr_to_sect_flags(attr) | (shared ? ARM_SECT_SHARED : 0);
tt_ptr = &tt[vaddr / MB];
while (sections > 0) {
cnt = (sections < 16) ? sections : 16;
switch (cnt) {
case 16 : tt_ptr[15] = entry + MB * 15;
case 15 : tt_ptr[14] = entry + MB * 14;
case 14 : tt_ptr[13] = entry + MB * 13;
case 13 : tt_ptr[12] = entry + MB * 12;
case 12 : tt_ptr[11] = entry + MB * 11;
case 11 : tt_ptr[10] = entry + MB * 10;
case 10 : tt_ptr[ 9] = entry + MB * 9;
case 9 : tt_ptr[ 8] = entry + MB * 8;
case 8 : tt_ptr[ 7] = entry + MB * 7;
case 7 : tt_ptr[ 6] = entry + MB * 6;
case 6 : tt_ptr[ 5] = entry + MB * 5;
case 5 : tt_ptr[ 4] = entry + MB * 4;
case 4 : tt_ptr[ 3] = entry + MB * 3;
case 3 : tt_ptr[ 2] = entry + MB * 2;
case 2 : tt_ptr[ 1] = entry + MB * 1;
case 1 : tt_ptr[ 0] = entry + MB * 0;
}
entry += MB * cnt;
tt_ptr += cnt;
sections -= cnt;
}
if (flush) {
flush_start = ((addr_t)&tt[vaddr / MB]) & ~CPU_CACHELINE_SIZE;
flush_stop = ((addr_t)tt_ptr + (CPU_CACHELINE_SIZE - 1)) & ~CPU_CACHELINE_SIZE;
while (flush_start < flush_stop) {
arm_clean_dcache_line(flush_start);
flush_start += CPU_CACHELINE_SIZE;
}
arm_flush_tlbs();
}
}
void arm_mmu_init(bool resume)
{
#ifdef MMU_TT_BASE
/* TT usually at the end of memory */
tt = (tt_ent *)MMU_TT_BASE;
#endif
if (false == resume) {
/* identity map everything using the translation table as noncached */
arm_mmu_map_section_range(0, 0, MMU_TT_SIZE / sizeof(tt_ent), kARMMMUStronglyOrdered, false, false);
}
/* let the platform code get a shot at mapping some ranges */
platform_mmu_setup(resume);
/* set up the domain register */
arm_write_dar(0x7); /* domain 0 manager, domain 1 client */
/* write the new translation table */
#if MMU_TT_SIZE == 0x4000
arm_write_ttbcr(0);
#elif (MMU_TT_SIZE == 0x1000) && (WITH_MMU_SECURITY_EXTENSIONS)
arm_write_ttbcr(2 | TTBCR_PD1);
#else
#error "Must set up TTBCR appropriately for translation table smaller than 16 kB"
#endif
arm_write_ttb(tt);
arm_flush_tlbs();
}
u_int32_t arm_get_noncached_address(u_int32_t address)
{
#ifdef MMU_NONCACHE0_SIZE
if (((int32_t)(address - MMU_NONCACHE0_PBASE) >= 0) && ((address - MMU_NONCACHE0_PBASE) < MMU_NONCACHE0_SIZE)) {
return address - MMU_NONCACHE0_PBASE + MMU_NONCACHE0_VBASE;
}
#endif
#ifdef MMU_NONCACHE1_SIZE
if (((int32_t)(address - MMU_NONCACHE1_PBASE) >= 0) && ((address - MMU_NONCACHE1_PBASE) < MMU_NONCACHE1_SIZE)) {
return address - MMU_NONCACHE1_PBASE + MMU_NONCACHE1_VBASE;
}
#endif
return 0xFFFFFFFF;
}
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <arch.h>
#include <platform/memmap.h>
#include <sys.h>
void arm_mpu_init(void)
{
/* set everything as fully cached, except for the hardware register region */
arm_write_iprot_region_0(0x0000003f);
arm_write_dprot_region_0(0x0000003f);
#ifdef PERIPH_BASE
arm_write_dprot_region_1((PERIPH_BASE | (0x1F - ((PERIPH_LEN == 0) ? 0 : (__builtin_clz(PERIPH_LEN) + 1))) << 1) | 1);
#endif
arm_write_ins_prot_register(0x3); // region 0 full access
arm_write_data_prot_register(0xf); // region 0 & 1 full access
arm_write_cacheable_registers(0x1, 0x1); // region 0 data and instruction is cacheable
arm_write_bufferable_register(0x1); // data region 0 is write bufferable
}
+248
View File
@@ -0,0 +1,248 @@
# Copyright (C) 2007-2010 Apple Inc. All rights reserved.
# Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
#
# This document is the property of Apple Computer, Inc.
# It is considered confidential and proprietary.
#
# This document may not be reproduced or transmitted in any form,
# in whole or in part, without the express written permission of
# Apple Computer, Inc.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
#
# ARM CPU config
#
# sanity check
ifeq ($(ARM_CPU),)
$(error ARM_CPU is not set)
endif
ifneq ($(ARM_ARCH),)
$(info ARM_ARCH does not need to be set at the platform level)
endif
################################################################################
# Per-CPU configuration
################################################################################
#
# Apple Swift
#
ifeq ($(ARM_CPU),apple-swift)
ARM_ARCH ?= armv7
ARM_ARCH_OPTIONS := ARCH_ARMv7=1 WITH_VFP=1
OPTIONS += \
CPU_APPLE_SWIFT=1 \
WITH_MMU=1 \
WITH_MMU_SECURITY_EXTENSIONS=1 \
WITH_CACHE=1 \
CPU_CACHELINE_SIZE=64 \
CPU_CACHELINE_SHIFT=6 \
CPU_CACHEINDEX_SHIFT=8 \
CPU_CACHESET_SHIFT=3 \
WITH_BRANCH_PREDICTION=1 \
WITH_UNALIGNED_MEM=1 \
WITH_L1_PARITY=1 \
PAGE_SIZE=4096
ALL_OBJS += \
$(LOCAL_DIR)/cache_v7.o \
$(LOCAL_DIR)/mmu.o \
$(LOCAL_DIR)/fp.o
endif
#
# ARM Cortex A8
#
ifeq ($(ARM_CPU),cortex-a8)
ARM_ARCH ?= armv7
ARM_ARCH_OPTIONS := ARCH_ARMv7=1 WITH_VFP=1
OPTIONS += \
CPU_ARM_CORTEX_A8=1 \
WITH_MMU=1 \
WITH_MMU_SECURITY_EXTENSIONS=1 \
WITH_CACHE=1 \
CPU_CACHELINE_SIZE=64 \
CPU_CACHELINE_SHIFT=6 \
CPU_CACHEINDEX_SHIFT=7 \
CPU_CACHESET_SHIFT=2 \
WITH_BRANCH_PREDICTION=1 \
WITH_UNALIGNED_MEM=1 \
WITH_L1_PARITY=1 \
WITH_CACHE_DEBUG=1 \
WITH_ARCHITECTED_L2=1 \
WITH_AUX_L2_ENABLE_BIT=1 \
PAGE_SIZE=4096
ALL_OBJS += \
$(LOCAL_DIR)/cache_v7.o \
$(LOCAL_DIR)/mmu.o \
$(LOCAL_DIR)/fp.o \
$(LOCAL_DIR)/cachedebug_a8.o
# Turned off to save space, enable as needed
ifeq ($(APPLICATION),XXX_iBoot)
ALL_OBJS += \
$(LOCAL_DIR)/cortex_hang.o \
$(LOCAL_DIR)/cortex_debug.o
endif
endif
#
# ARM Cortex A9
#
ifeq ($(ARM_CPU),cortex-a9)
ARM_ARCH ?= armv7
ARM_ARCH_OPTIONS := ARCH_ARMv7=1 WITH_VFP=1
OPTIONS += \
CPU_ARM_CORTEX_A9=1 \
WITH_MMU=1 \
WITH_MMU_SECURITY_EXTENSIONS=1 \
WITH_CACHE=1 \
CPU_CACHELINE_SIZE=32 \
CPU_CACHELINE_SHIFT=5 \
CPU_CACHEINDEX_SHIFT=8 \
CPU_CACHESET_SHIFT=2 \
WITH_BRANCH_PREDICTION=1 \
WITH_UNALIGNED_MEM=1 \
WITH_L1_PARITY=1 \
SET_AUX_SMP_BIT=1 \
PAGE_SIZE=4096
ALL_OBJS += \
$(LOCAL_DIR)/cache_v7.o \
$(LOCAL_DIR)/mmu.o \
$(LOCAL_DIR)/fp.o
endif
#
# ARM Cortex A5 "Sparrow"
#
ifeq ($(ARM_CPU),cortex-a5)
ARM_ARCH ?= armv7
ARM_ARCH_OPTIONS := ARCH_ARMv7=1 WITH_VFP=1
OPTIONS += \
CPU_ARM_CORTEX_A5=1 \
FP_REGISTER_COUNT=32 \
WITH_MMU=1 \
WITH_MMU_SECURITY_EXTENSIONS=1 \
WITH_CACHE=1 \
CPU_CACHELINE_SIZE=32 \
CPU_CACHELINE_SHIFT=5 \
CPU_CACHEINDEX_SHIFT=8 \
CPU_CACHESET_SHIFT=2 \
WITH_BRANCH_PREDICTION=1 \
WITH_UNALIGNED_MEM=1 \
SET_AUX_SMP_BIT=1 \
PAGE_SIZE=4096
ALL_OBJS += \
$(LOCAL_DIR)/cache_v7.o \
$(LOCAL_DIR)/mmu.o \
$(LOCAL_DIR)/fp.o
endif
#
# ARM Cortex A7 "Kingfisher"
#
ifeq ($(ARM_CPU),cortex-a7)
ARM_ARCH ?= armv7k
ARM_ARCH_OPTIONS := ARCH_ARMv7=1 WITH_VFP=1 WITH_VFP_ALWAYS_ON=1
OPTIONS += \
CPU_ARM_CORTEX_A7=1 \
VFP_REV=4 \
FP_REGISTER_COUNT=32 \
WITH_MMU=1 \
WITH_MMU_SECURITY_EXTENSIONS=1 \
WITH_CACHE=1 \
WITH_EARLY_ICACHE=1 \
CPU_CACHELINE_SIZE=64 \
CPU_CACHELINE_SHIFT=6 \
CPU_CACHEINDEX_SHIFT=7 \
CPU_CACHESET_SHIFT=2 \
WITH_BRANCH_PREDICTION=1 \
WITH_UNALIGNED_MEM=1 \
WITH_ARCHITECTED_L2=1 \
SET_AUX_SMP_BIT=1 \
PAGE_SIZE=4096
ALL_OBJS += \
$(LOCAL_DIR)/cache_v7.o \
$(LOCAL_DIR)/mmu.o \
$(LOCAL_DIR)/fp.o
endif
################################################################################
# General and conditional configuration
################################################################################
# sanity check
ifeq ($(ARM_ARCH),)
$(error ARM_ARCH not set, no valid CPU selected)
endif
# build for the proper cpu
OPTIONS += ARCH_ARM=1
GLOBAL_ALLFLAGS += -arch $(ARM_ARCH) $(addprefix -D,$(ARM_ARCH_OPTIONS))
GLOBAL_LDFLAGS += -arch $(ARM_ARCH)
# Tell the build system how libraries should be tagged
LIBRARY_TAG += $(ARM_ARCH)
LIBRARY_OPTIONS += ARCH=arm ARM_ARCH=$(ARM_ARCH)
# Always build libbuiltin, to partially override the gcc static library.
LIBRARY_MODULES += lib/libbuiltin
# set up to build with thumb
WITH_THUMB ?= true
ifeq ($(WITH_THUMB),true)
THUMBFLAGS := -mthumb
LIBRARY_TAG += thumb
else
THUMBFLAGS := -mno-thumb
LIBRARY_TAG += arm
endif
GLOBAL_ALLFLAGS += $(THUMBFLAGS)
GLOBAL_INCLUDES += $(LOCAL_DIR)/include
# Defaults for stack sizes
# These are override in platform/.../rules.mk
ifeq ($(IRQ_STACK_SIZE),)
IRQ_STACK_SIZE ?= 2048
endif
ifeq ($(FIQ_STACK_SIZE),)
FIQ_STACK_SIZE ?= 1024
endif
ifeq ($(EXCEPTION_STACK_SIZE),)
EXCEPTION_STACK_SIZE ?= 2048
endif
ifeq ($(BOOTSTRAP_STACK_SIZE),)
BOOTSTRAP_STACK_SIZE ?= 2048
endif
OPTIONS += \
IRQ_STACK_SIZE=$(IRQ_STACK_SIZE) \
FIQ_STACK_SIZE=$(FIQ_STACK_SIZE) \
EXCEPTION_STACK_SIZE=$(EXCEPTION_STACK_SIZE) \
BOOTSTRAP_STACK_SIZE=$(BOOTSTRAP_STACK_SIZE)
# Force start.o and asm.o to link first
ALL_OBJS := \
$(LOCAL_DIR)/start.o \
$(LOCAL_DIR)/asm.o \
$(ALL_OBJS)
# Code common to all cores
ALL_OBJS += \
$(LOCAL_DIR)/cpu.o \
$(LOCAL_DIR)/context.o \
$(LOCAL_DIR)/entropy.o \
$(LOCAL_DIR)/exceptions.o \
$(LOCAL_DIR)/handlers.o \
$(LOCAL_DIR)/task.o
LINKER_EXPORTS := $(LOCAL_DIR)/link.exp
# if someone requests DCC, add it in
ifeq ($(WITH_DCC),true)
OPTIONS += ARM_DCC_SYNCHRONOUS=1
include $(LOCAL_DIR)/dcc/rules.mk
endif
+343
View File
@@ -0,0 +1,343 @@
/*
* Copyright (C) 2007-2014 Apple Inc. All rights reserved.
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <platform/memmap.h>
.text
.balign 4
.no_dead_strip _start
.global _start
_start:
b __reset
ldr pc, vectoraddr + 4
ldr pc, vectoraddr + 8
ldr pc, vectoraddr + 12
ldr pc, vectoraddr + 16
ldr pc, vectoraddr + 20
ldr pc, vectoraddr + 24
ldr pc, vectoraddr + 28
vectoraddr:
.word __reset
.word ___arm_undefined
.word ___arm_syscall
.word ___arm_prefetch_abort
.word ___arm_data_abort
.word ___arm_reserved
.word ___arm_irq
.word ___arm_fiq
__reset:
/*
* Test the running versus desired the start of the text
* to determine if relocaiton is required
*/
adr r0, _start
ldr r1, L_TEXT_START
cmp r0, r1
#ifdef PLATFORM_START_FUNCTION
/*
* r0 and r1 must be preserved
* 'eq' will be true if no text relocation is required
*/
bl PLATFORM_START_FUNCTION
#endif
/* re-test the running start versus desired start of the text */
cmp r0, r1
beq __do_relocate_data
/* relocate to the desired text location and branch to it */
ldr r2, L_TEXT_END
sub r2, r2, r1
__relocate_loop:
subs r2, r2, #4
ldr r3, [r0, r2]
str r3, [r1, r2]
bne __relocate_loop
#if ARCH_ARMv7
/* prevent speculation to the desired text location */
dsb
isb
#endif
/* branch into the desired text location */
bx r1
/* test if the data if needs to be relocated */
__do_relocate_data:
ldr r0, L_DATA_RO_START
mov r1, #0x00001000 // Round up to a 4K page
sub r1, r1, #1 //
add r0, r0, r1 //
bic r0, r0, r1 //
ldr r1, L_DATA_START
cmp r0, r1
beq __stacksetup
/* relocate the data */
ldr r2, L_DATA_END
sub r2, r2, r1
__relocate_data_loop:
subs r2, r2, #4
ldr r3, [r0, r2]
str r3, [r1, r2]
bne __relocate_data_loop
__stacksetup:
/* set up the stack for irq, fiq, abort, undefined, and lastly supervisor mode */
mrs r0, cpsr
bic r0, r0, #0x1f
orr r1, r0, #0x12 // irq
msr cpsr_c, r1
mov lr, #0
ldr sp, _irq_stack_top
orr r1, r0, #0x11 // fiq
msr cpsr_c, r1
mov lr, #0
ldr sp, _fiq_stack_top
orr r1, r0, #0x17 // abort
msr cpsr_c, r1
mov lr, #0
ldr sp, _exc_stack_top
orr r1, r0, #0x1b // undefined
msr cpsr_c, r1
mov lr, #0
ldr sp, _exc_stack_top
orr r1, r0, #0x13 // supervisor
msr cpsr_c, r1
ldr sp, _svc_stack_top
#if ARCH_ARMv7
mrs r1, cpsr
bic r1, #0x100 // enable imprecise data aborts
msr cpsr_x, r1
#endif
#if SUPPORT_SLEEP
/* look at the global wakeup flag, avoid clearing the BSS and go straight to wake up */
.global _platform_wakeup
ldr r1, _arch_sleep_magic /* will be zero on the wake path, nonzero otherwise */
eor r0, r0, r0
cmp r0, r1
bne __do_bss
ldr r0, L__platform_wakeup
mov lr, pc
bx r0
#endif
__do_bss:
/* clear the bss section */
ldr r0, L_BSS_START
ldr r1, L_BSS_END
mov r2, #0
mov r3, #0
mov r4, #0
mov r5, #0
mov r6, #0
mov r7, #0
mov r8, #0
mov r10, #0
sub r12, r1, r0
/* If there are less than 256 bytes, skip this loop */
subs r12, r12, #256
blo __bss_lessthan256
__bss_loop256:
/* Clear 256 bytes at a time */
subs r12, #256
stmia r0!, {r2-r8, r10}
stmia r0!, {r2-r8, r10}
stmia r0!, {r2-r8, r10}
stmia r0!, {r2-r8, r10}
stmia r0!, {r2-r8, r10}
stmia r0!, {r2-r8, r10}
stmia r0!, {r2-r8, r10}
stmia r0!, {r2-r8, r10}
bge __bss_loop256
__bss_lessthan256:
/* If are less than 32 bytes left to handle, skip this loop */
adds r12, r12, #(256 - 32)
bcc __bss_lessthan32
__bss_loop32:
/* Clear 32 bytes at a time */
subs r12, r12, #32
stmia r0!, {r2-r8, r10}
bge __bss_loop32
__bss_lessthan32:
/* If there's nothing left to go, skip this loop */
adds r12, r12, #32
beq __bss_done
__bss_loop4:
/* Clear 4 bytes at a time */
subs r12, r12, #4
str r2, [r0],#4
bgt __bss_loop4
__bss_done:
/* branch to main */
ldr r0, L__main
mov lr, pc
bx r0
b .
.org 0x200
L__build_banner_string:
.ascii CONFIG_PROGNAME_STRING
.ascii " for "
.ascii CONFIG_BOARD_STRING
.ascii ", Copyright 2007-2016, Apple Inc."
.org 0x240
L__build_style_string:
.ascii BUILD_STYLE
/* This will get replaced by macho_post_process.py so that the build tag
is accurate even for iterative desktop builds that don't rebuild start.o */
.org 0x280
_build_tag_string_contents:
/* Placeholder for macho_post_process.py. Placing the UUID here allows
debuggers to locate the UUID based on the address of the vectors */
.org 0x300
_UUID:
.space 0x20
.global _build_banner_string
_build_banner_string:
.long L__build_banner_string
.global _build_style_string
_build_style_string:
.long L__build_style_string
.global _build_tag_string
_build_tag_string:
.long _build_tag_string_contents
L__main:
.long __main
/* linked start and end addresses of the text */
L_TEXT_START:
.long (TEXT_BASE)
L_TEXT_END:
.long section$start$__DATA$__zerofill
/* start address of the data in the read only text */
L_DATA_RO_START:
.long segment$end$__TEXT
/* linked start and end addresses of the data */
L_DATA_START:
.long segment$start$__DATA
L_DATA_END:
.long section$start$__DATA$__zerofill
/* linked start and end addresses of the zero-filled range */
L_BSS_START:
.long section$start$__DATA$__zerofill
L_BSS_END:
.long segment$end$__DATA
/*
* Stacks.
*
* The following stacks must be defined:
*
* bootstrap stack
* Used as the stack for the initial thread.
*
* exception stack
* Used when handling exceptions other than interrupts.
*
* interrupt stack
* Used when handling regular interrupts.
*
* fiq stack
* Used when handling FIQ interrupts.
*/
.global _irq_stack_top
.global _fiq_stack_top
.global _exc_stack_top
.global _svc_stack_top
#ifndef STACK_SIZE
/*
* This is a bit hokey, as the platform doesn't really know
* what the bootstrap stack size should be.
*/
# define STACK_SIZE BOOTSTRAP_STACK_SIZE
#endif
#if APPLICATION_EMBEDDEDIOP
/*
* Locally-allocated stacks.
*/
_irq_stack_top:
.long irq_stack + IRQ_STACK_SIZE
_fiq_stack_top:
.long fiq_stack + FIQ_STACK_SIZE
_exc_stack_top:
.long exc_stack + EXCEPTION_STACK_SIZE
_svc_stack_top:
.long svc_stack + STACK_SIZE
/* allocate stacks here */
.lcomm irq_stack, IRQ_STACK_SIZE, 4
.lcomm fiq_stack, FIQ_STACK_SIZE, 4
.lcomm exc_stack, EXCEPTION_STACK_SIZE, 4
.lcomm svc_stack, STACK_SIZE, 4
#elif defined(STACK_BASE)
/*
* Simple stack layout with just one allocation in STACK_BASE/STACK_SIZE
* supplied by the platform definition.
*
* Bootstrap stack starts at the top of the allocation,
* exception stack and interrupt stack share the same
* chunk at the bottom.
*/
_fiq_stack_top:
.long STACK_BASE + FIQ_STACK_SIZE
_exc_stack_top:
_irq_stack_top:
.long STACK_BASE + IRQ_STACK_SIZE
_svc_stack_top:
.long STACK_BASE + STACK_SIZE
#else
# error No stack defined
#endif
#if SUPPORT_SLEEP
.global _arch_sleep_magic
_arch_sleep_magic:
.long 0xffffffff
L__platform_wakeup:
.long _platform_wakeup
#endif
+61
View File
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <debug.h>
#include <sys/types.h>
#include <sys.h>
#include <sys/task.h>
static void arch_task_trampoline(void) __noreturn;
static void
arch_task_trampoline(void)
{
/* exit the critical section we implicitly started with */
exit_critical_section();
dprintf(DEBUG_SPEW, "arch_task_trampoline: task %p (%s) routine %p, arg %p\n",
current_task, current_task->name, current_task->routine, current_task->arg);
/* call the start routine */
int ret = current_task->routine(current_task->arg);
dprintf(DEBUG_SPEW, "arch_task_trampoline: task %p (%s) exits with %d\n",
current_task, current_task->name, ret);
task_exit(ret);
/* never return */
}
int
arch_task_create(struct task *t)
{
int i;
for (i=0; i < 10; i++)
t->arch.regs[i] = 0;
/* set the default starting point to be arch_task_trampoline */
t->arch.regs[ARM_ARCH_TASK_LR] = (uint32_t)&arch_task_trampoline;
/* the ARM describes some encodings of SP ops (pre/post increment and/or decrement) as
potentially reaching above the SP by a word. Our toolchain might not emit such encodings,
but we'd rather be safe than sorry. Originally, we took off 4 bytes, but
to better align the stacks for some of the newer ABIs (e.g. armv7k), we'll consistently
take off 16 bytes from the top of the stack */
t->arch.regs[ARM_ARCH_TASK_SP] = (uint32_t)t->stack_base + t->stack_len - 16;
t->arch.regs[ARM_ARCH_TASK_FP] = 0;
#if WITH_VFP
t->arch.fpexc = 0; /* default state is FP disabled */
#endif
return 0;
}