mirror of
https://github.com/CTCaer/switch-l4t-atf.git
synced 2024-12-04 08:53:37 +00:00
Merge pull request #172 from soby-mathew/sm/asm_assert
Introduce asm assert and optimize crash reporting
This commit is contained in:
commit
6397bf6a99
9
Makefile
9
Makefile
@ -60,7 +60,9 @@ CTX_INCLUDE_FPREGS := 0
|
||||
# Determine the version of ARM GIC architecture to use for interrupt management
|
||||
# in EL3. The platform port can change this value if needed.
|
||||
ARM_GIC_ARCH := 2
|
||||
|
||||
# Flag used to indicate if ASM_ASSERTION should be enabled for the build.
|
||||
# This defaults to being present in DEBUG builds only.
|
||||
ASM_ASSERTION := ${DEBUG}
|
||||
|
||||
# Checkpatch ignores
|
||||
CHECK_IGNORE = --ignore COMPLEX_MACRO
|
||||
@ -90,8 +92,8 @@ endif
|
||||
VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}(${BUILD_TYPE}):${BUILD_STRING}
|
||||
|
||||
BL_COMMON_SOURCES := common/bl_common.c \
|
||||
common/debug.c \
|
||||
common/tf_printf.c \
|
||||
common/aarch64/debug.S \
|
||||
lib/aarch64/cache_helpers.S \
|
||||
lib/aarch64/misc_helpers.S \
|
||||
lib/aarch64/xlat_helpers.c \
|
||||
@ -207,6 +209,9 @@ $(eval $(call add_define,CTX_INCLUDE_FPREGS))
|
||||
# Process ARM_GIC_ARCH flag
|
||||
$(eval $(call add_define,ARM_GIC_ARCH))
|
||||
|
||||
# Process ASM_ASSERTION flag
|
||||
$(eval $(call assert_boolean,ASM_ASSERTION))
|
||||
$(eval $(call add_define,ASM_ASSERTION))
|
||||
|
||||
ASFLAGS += -nostdinc -ffreestanding -Wa,--fatal-warnings \
|
||||
-Werror -Wmissing-include-dirs \
|
||||
|
@ -82,13 +82,22 @@ func bl31_entrypoint
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Set the exception vector and zero tpidr_el3
|
||||
* until the crash reporting is set up
|
||||
* Initialise cpu_data early to enable crash
|
||||
* reporting to have access to crash stack.
|
||||
* Since crash reporting depends on cpu_data to
|
||||
* report the unhandled exception, not
|
||||
* doing so can lead to recursive exceptions due
|
||||
* to a NULL TPIDR_EL3
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
bl init_cpu_data_ptr
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Set the exception vector.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
adr x1, runtime_exceptions
|
||||
msr vbar_el3, x1
|
||||
msr tpidr_el3, xzr
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* The initial state of the Architectural feature trap register
|
||||
@ -146,15 +155,6 @@ func bl31_entrypoint
|
||||
ldr x1, =__COHERENT_RAM_UNALIGNED_SIZE__
|
||||
bl zeromem16
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Initialise cpu_data and crash reporting
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
#if CRASH_REPORTING
|
||||
bl init_crash_reporting
|
||||
#endif
|
||||
bl init_cpu_data_ptr
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Use SP_EL0 for the C runtime stack.
|
||||
* ---------------------------------------------
|
||||
|
@ -34,11 +34,13 @@
|
||||
#include <plat_macros.S>
|
||||
#include <platform_def.h>
|
||||
|
||||
.globl dump_state_and_die
|
||||
.globl dump_intr_state_and_die
|
||||
.globl init_crash_reporting
|
||||
.globl report_unhandled_exception
|
||||
.globl report_unhandled_interrupt
|
||||
.globl el3_panic
|
||||
|
||||
#if CRASH_REPORTING
|
||||
#define REG_SIZE 0x8
|
||||
|
||||
/* ------------------------------------------------------
|
||||
* The below section deals with dumping the system state
|
||||
* when an unhandled exception is taken in EL3.
|
||||
@ -46,267 +48,326 @@
|
||||
* be dumped during a unhandled exception is given below.
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
.section .rodata.dump_reg_name, "aS"
|
||||
caller_saved_regs: .asciz "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",\
|
||||
"x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16",\
|
||||
"x17", "x18", ""
|
||||
.section .rodata.crash_prints, "aS"
|
||||
print_spacer:
|
||||
.asciz " =\t\t0x"
|
||||
|
||||
callee_saved_regs: .asciz "x19", "x20", "x21", "x22", "x23", "x24",\
|
||||
"x25", "x26", "x27", "x28", "x29", "x30", ""
|
||||
cpu_ectlr_reg:
|
||||
.asciz "cpuectlr_el1 =\t\t0x"
|
||||
|
||||
el3_sys_regs: .asciz "scr_el3", "sctlr_el3", "cptr_el3", "tcr_el3",\
|
||||
"daif", "mair_el3", "spsr_el3", "elr_el3", "ttbr0_el3", "esr_el3",\
|
||||
"sp_el3", "far_el3", ""
|
||||
gp_regs:
|
||||
.asciz "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",\
|
||||
"x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",\
|
||||
"x16", "x17", "x18", "x19", "x20", "x21", "x22",\
|
||||
"x23", "x24", "x25", "x26", "x27", "x28", "x29", ""
|
||||
el3_sys_regs:
|
||||
.asciz "scr_el3", "sctlr_el3", "cptr_el3", "tcr_el3",\
|
||||
"daif", "mair_el3", "spsr_el3", "elr_el3", "ttbr0_el3",\
|
||||
"esr_el3", "far_el3", ""
|
||||
|
||||
non_el3_sys_0_regs: .asciz "spsr_el1", "elr_el1", "spsr_abt", "spsr_und",\
|
||||
"spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\
|
||||
"csselr_el1", "sp_el1", "esr_el1", "ttbr0_el1", "ttbr1_el1",\
|
||||
"mair_el1", "amair_el1", "tcr_el1", "tpidr_el1", ""
|
||||
non_el3_sys_regs:
|
||||
.asciz "spsr_el1", "elr_el1", "spsr_abt", "spsr_und",\
|
||||
"spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\
|
||||
"csselr_el1", "sp_el1", "esr_el1", "ttbr0_el1", "ttbr1_el1",\
|
||||
"mair_el1", "amair_el1", "tcr_el1", "tpidr_el1", "tpidr_el0",\
|
||||
"tpidrro_el0", "dacr32_el2", "ifsr32_el2", "par_el1",\
|
||||
"mpidr_el1", "afsr0_el1", "afsr1_el1", "contextidr_el1",\
|
||||
"vbar_el1", "cntp_ctl_el0", "cntp_cval_el0", "cntv_ctl_el0",\
|
||||
"cntv_cval_el0", "cntkctl_el1", "fpexc32_el2", "sp_el0", ""
|
||||
|
||||
non_el3_sys_1_regs: .asciz "tpidr_el0", "tpidrro_el0", "dacr32_el2",\
|
||||
"ifsr32_el2", "par_el1", "far_el1", "afsr0_el1", "afsr1_el1",\
|
||||
"contextidr_el1", "vbar_el1", "cntp_ctl_el0", "cntp_cval_el0",\
|
||||
"cntv_ctl_el0", "cntv_cval_el0", "cntkctl_el1", "fpexc32_el2",\
|
||||
"sp_el0", ""
|
||||
panic_msg:
|
||||
.asciz "PANIC in EL3 at x30 = 0x"
|
||||
excpt_msg:
|
||||
.asciz "Unhandled Exception in EL3.\nx30 =\t\t0x"
|
||||
intr_excpt_msg:
|
||||
.asciz "Unhandled Interrupt Exception in EL3.\nx30 =\t\t0x"
|
||||
|
||||
/*
|
||||
* Helper function to print newline to console.
|
||||
*/
|
||||
func print_newline
|
||||
mov x0, '\n'
|
||||
b plat_crash_console_putc
|
||||
|
||||
/*
|
||||
* Helper function to print from crash buf.
|
||||
* The print loop is controlled by the buf size and
|
||||
* ascii reg name list which is passed in x6. The
|
||||
* function returns the crash buf address in x0.
|
||||
* Clobbers : x0 - x7, sp
|
||||
*/
|
||||
func size_controlled_print
|
||||
/* Save the lr */
|
||||
mov sp, x30
|
||||
/* load the crash buf address */
|
||||
mrs x7, tpidr_el3
|
||||
test_size_list:
|
||||
/* Calculate x5 always as it will be clobbered by asm_print_hex */
|
||||
mrs x5, tpidr_el3
|
||||
add x5, x5, #CPU_DATA_CRASH_BUF_SIZE
|
||||
/* Test whether we have reached end of crash buf */
|
||||
cmp x7, x5
|
||||
b.eq exit_size_print
|
||||
ldrb w4, [x6]
|
||||
/* Test whether we are at end of list */
|
||||
cbz w4, exit_size_print
|
||||
mov x4, x6
|
||||
/* asm_print_str updates x4 to point to next entry in list */
|
||||
bl asm_print_str
|
||||
/* update x6 with the updated list pointer */
|
||||
mov x6, x4
|
||||
adr x4, print_spacer
|
||||
bl asm_print_str
|
||||
ldr x4, [x7], #REG_SIZE
|
||||
bl asm_print_hex
|
||||
bl print_newline
|
||||
b test_size_list
|
||||
exit_size_print:
|
||||
mov x30, sp
|
||||
ret
|
||||
|
||||
/*
|
||||
* Helper function to store x8 - x15 registers to
|
||||
* the crash buf. The system registers values are
|
||||
* copied to x8 to x15 by the caller which are then
|
||||
* copied to the crash buf by this function.
|
||||
* x0 points to the crash buf. It then calls
|
||||
* size_controlled_print to print to console.
|
||||
* Clobbers : x0 - x7, sp
|
||||
*/
|
||||
func str_in_crash_buf_print
|
||||
/* restore the crash buf address in x0 */
|
||||
mrs x0, tpidr_el3
|
||||
stp x8, x9, [x0]
|
||||
stp x10, x11, [x0, #REG_SIZE * 2]
|
||||
stp x12, x13, [x0, #REG_SIZE * 4]
|
||||
stp x14, x15, [x0, #REG_SIZE * 6]
|
||||
b size_controlled_print
|
||||
|
||||
/* ------------------------------------------------------
|
||||
* This macro calculates the offset to crash buf from
|
||||
* cpu_data and stores it in tpidr_el3. It also saves x0
|
||||
* and x1 in the crash buf by using sp as a temporary
|
||||
* register.
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
.macro prepare_crash_buf_save_x0_x1
|
||||
/* we can corrupt this reg to free up x0 */
|
||||
mov sp, x0
|
||||
/* tpidr_el3 contains the address to cpu_data structure */
|
||||
mrs x0, tpidr_el3
|
||||
/* Calculate the Crash buffer offset in cpu_data */
|
||||
add x0, x0, #CPU_DATA_CRASH_BUF_OFFSET
|
||||
/* Store crash buffer address in tpidr_el3 */
|
||||
msr tpidr_el3, x0
|
||||
str x1, [x0, #REG_SIZE]
|
||||
mov x1, sp
|
||||
str x1, [x0]
|
||||
.endm
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Currently we are stack limited. Hence make sure that
|
||||
* we dont try to dump more than 20 registers using the
|
||||
* stack.
|
||||
* This function allows to report a crash (if crash
|
||||
* reporting is enabled) when an unhandled exception
|
||||
* occurs. It prints the CPU state via the crash console
|
||||
* making use of the crash buf. This function will
|
||||
* not return.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func report_unhandled_exception
|
||||
prepare_crash_buf_save_x0_x1
|
||||
adr x0, excpt_msg
|
||||
mov sp, x0
|
||||
/* This call will not return */
|
||||
b do_crash_reporting
|
||||
|
||||
#define REG_SIZE 0x8
|
||||
|
||||
/* The caller saved registers are X0 to X18 */
|
||||
#define CALLER_SAVED_REG_SIZE (20 * REG_SIZE)
|
||||
/* The caller saved registers are X19 to X30 */
|
||||
#define CALLEE_SAVED_REG_SIZE (12 * REG_SIZE)
|
||||
/* The EL3 sys regs*/
|
||||
#define EL3_SYS_REG_SIZE (12 * REG_SIZE)
|
||||
/* The non EL3 sys regs set-0 */
|
||||
#define NON_EL3_SYS_0_REG_SIZE (18 * REG_SIZE)
|
||||
/* The non EL3 sys regs set-1 */
|
||||
#define NON_EL3_SYS_1_REG_SIZE (18 * REG_SIZE)
|
||||
/* -----------------------------------------------------
|
||||
* This function allows to report a crash (if crash
|
||||
* reporting is enabled) when an unhandled interrupt
|
||||
* occurs. It prints the CPU state via the crash console
|
||||
* making use of the crash buf. This function will
|
||||
* not return.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func report_unhandled_interrupt
|
||||
prepare_crash_buf_save_x0_x1
|
||||
adr x0, intr_excpt_msg
|
||||
mov sp, x0
|
||||
/* This call will not return */
|
||||
b do_crash_reporting
|
||||
|
||||
.macro print_caller_saved_regs
|
||||
sub sp, sp, #CALLER_SAVED_REG_SIZE
|
||||
stp x0, x1, [sp]
|
||||
stp x2, x3, [sp, #(REG_SIZE * 2)]
|
||||
stp x4, x5, [sp, #(REG_SIZE * 4)]
|
||||
stp x6, x7, [sp, #(REG_SIZE * 6)]
|
||||
stp x8, x9, [sp, #(REG_SIZE * 8)]
|
||||
stp x10, x11, [sp, #(REG_SIZE * 10)]
|
||||
stp x12, x13, [sp, #(REG_SIZE * 12)]
|
||||
stp x14, x15, [sp, #(REG_SIZE * 14)]
|
||||
stp x16, x17, [sp, #(REG_SIZE * 16)]
|
||||
stp x18, xzr, [sp, #(REG_SIZE * 18)]
|
||||
adr x0, caller_saved_regs
|
||||
mov x1, sp
|
||||
bl print_string_value
|
||||
add sp, sp, #CALLER_SAVED_REG_SIZE
|
||||
.endm
|
||||
/* -----------------------------------------------------
|
||||
* This function allows to report a crash (if crash
|
||||
* reporting is enabled) when panic() is invoked from
|
||||
* C Runtime. It prints the CPU state via the crash
|
||||
* console making use of the crash buf. This function
|
||||
* will not return.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func el3_panic
|
||||
msr spsel, #1
|
||||
prepare_crash_buf_save_x0_x1
|
||||
adr x0, panic_msg
|
||||
mov sp, x0
|
||||
/* This call will not return */
|
||||
b do_crash_reporting
|
||||
|
||||
.macro print_callee_saved_regs
|
||||
sub sp, sp, CALLEE_SAVED_REG_SIZE
|
||||
stp x19, x20, [sp]
|
||||
stp x21, x22, [sp, #(REG_SIZE * 2)]
|
||||
stp x23, x24, [sp, #(REG_SIZE * 4)]
|
||||
stp x25, x26, [sp, #(REG_SIZE * 6)]
|
||||
stp x27, x28, [sp, #(REG_SIZE * 8)]
|
||||
stp x29, x30, [sp, #(REG_SIZE * 10)]
|
||||
adr x0, callee_saved_regs
|
||||
mov x1, sp
|
||||
bl print_string_value
|
||||
add sp, sp, #CALLEE_SAVED_REG_SIZE
|
||||
.endm
|
||||
/* ------------------------------------------------------------
|
||||
* The common crash reporting functionality. It requires x0
|
||||
* and x1 has already been stored in crash buf, sp points to
|
||||
* crash message and tpidr_el3 contains the crash buf address.
|
||||
* The function does the following:
|
||||
* - Retrieve the crash buffer from tpidr_el3
|
||||
* - Store x2 to x6 in the crash buffer
|
||||
* - Initialise the crash console.
|
||||
* - Print the crash message by using the address in sp.
|
||||
* - Print x30 value to the crash console.
|
||||
* - Print x0 - x7 from the crash buf to the crash console.
|
||||
* - Print x8 - x29 (in groups of 8 registers) using the
|
||||
* crash buf to the crash console.
|
||||
* - Print el3 sys regs (in groups of 8 registers) using the
|
||||
* crash buf to the crash console.
|
||||
* - Print non el3 sys regs (in groups of 8 registers) using
|
||||
* the crash buf to the crash console.
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
func do_crash_reporting
|
||||
/* Retrieve the crash buf from tpidr_el3 */
|
||||
mrs x0, tpidr_el3
|
||||
/* Store x2 - x6, x30 in the crash buffer */
|
||||
stp x2, x3, [x0, #REG_SIZE * 2]
|
||||
stp x4, x5, [x0, #REG_SIZE * 4]
|
||||
stp x6, x30, [x0, #REG_SIZE * 6]
|
||||
/* Initialize the crash console */
|
||||
bl plat_crash_console_init
|
||||
/* Verify the console is initialized */
|
||||
cbz x0, crash_panic
|
||||
/* Print the crash message. sp points to the crash message */
|
||||
mov x4, sp
|
||||
bl asm_print_str
|
||||
/* load the crash buf address */
|
||||
mrs x0, tpidr_el3
|
||||
/* report x30 first from the crash buf */
|
||||
ldr x4, [x0, #REG_SIZE * 7]
|
||||
bl asm_print_hex
|
||||
bl print_newline
|
||||
/* Load the crash buf address */
|
||||
mrs x0, tpidr_el3
|
||||
/* Now mov x7 into crash buf */
|
||||
str x7, [x0, #REG_SIZE * 7]
|
||||
|
||||
.macro print_el3_sys_regs
|
||||
sub sp, sp, #EL3_SYS_REG_SIZE
|
||||
mrs x9, scr_el3
|
||||
mrs x10, sctlr_el3
|
||||
mrs x11, cptr_el3
|
||||
mrs x12, tcr_el3
|
||||
mrs x13, daif
|
||||
mrs x14, mair_el3
|
||||
mrs x15, spsr_el3 /*save the elr and spsr regs seperately*/
|
||||
mrs x16, elr_el3
|
||||
mrs x17, ttbr0_el3
|
||||
mrs x8, esr_el3
|
||||
mrs x7, far_el3
|
||||
/* Report x0 - x29 values stored in crash buf*/
|
||||
/* Store the ascii list pointer in x6 */
|
||||
adr x6, gp_regs
|
||||
/* Print x0 to x7 from the crash buf */
|
||||
bl size_controlled_print
|
||||
/* Store x8 - x15 in crash buf and print */
|
||||
bl str_in_crash_buf_print
|
||||
/* Load the crash buf address */
|
||||
mrs x0, tpidr_el3
|
||||
/* Store the rest of gp regs and print */
|
||||
stp x16, x17, [x0]
|
||||
stp x18, x19, [x0, #REG_SIZE * 2]
|
||||
stp x20, x21, [x0, #REG_SIZE * 4]
|
||||
stp x22, x23, [x0, #REG_SIZE * 6]
|
||||
bl size_controlled_print
|
||||
/* Load the crash buf address */
|
||||
mrs x0, tpidr_el3
|
||||
stp x24, x25, [x0]
|
||||
stp x26, x27, [x0, #REG_SIZE * 2]
|
||||
stp x28, x29, [x0, #REG_SIZE * 4]
|
||||
bl size_controlled_print
|
||||
|
||||
stp x9, x10, [sp]
|
||||
stp x11, x12, [sp, #(REG_SIZE * 2)]
|
||||
stp x13, x14, [sp, #(REG_SIZE * 4)]
|
||||
stp x15, x16, [sp, #(REG_SIZE * 6)]
|
||||
stp x17, x8, [sp, #(REG_SIZE * 8)]
|
||||
stp x0, x7, [sp, #(REG_SIZE * 10)] /* sp_el3 is in x0 */
|
||||
|
||||
adr x0, el3_sys_regs
|
||||
mov x1, sp
|
||||
bl print_string_value
|
||||
add sp, sp, #EL3_SYS_REG_SIZE
|
||||
.endm
|
||||
|
||||
.macro print_non_el3_sys_0_regs
|
||||
sub sp, sp, #NON_EL3_SYS_0_REG_SIZE
|
||||
mrs x9, spsr_el1
|
||||
mrs x10, elr_el1
|
||||
mrs x11, spsr_abt
|
||||
mrs x12, spsr_und
|
||||
mrs x13, spsr_irq
|
||||
mrs x14, spsr_fiq
|
||||
mrs x15, sctlr_el1
|
||||
mrs x16, actlr_el1
|
||||
mrs x17, cpacr_el1
|
||||
mrs x8, csselr_el1
|
||||
|
||||
stp x9, x10, [sp]
|
||||
stp x11, x12, [sp, #(REG_SIZE * 2)]
|
||||
stp x13, x14, [sp, #(REG_SIZE * 4)]
|
||||
stp x15, x16, [sp, #(REG_SIZE * 6)]
|
||||
stp x17, x8, [sp, #(REG_SIZE * 8)]
|
||||
/* Print the el3 sys registers */
|
||||
adr x6, el3_sys_regs
|
||||
mrs x8, scr_el3
|
||||
mrs x9, sctlr_el3
|
||||
mrs x10, cptr_el3
|
||||
mrs x11, tcr_el3
|
||||
mrs x12, daif
|
||||
mrs x13, mair_el3
|
||||
mrs x14, spsr_el3
|
||||
mrs x15, elr_el3
|
||||
bl str_in_crash_buf_print
|
||||
mrs x8, ttbr0_el3
|
||||
mrs x9, esr_el3
|
||||
mrs x10, far_el3
|
||||
bl str_in_crash_buf_print
|
||||
|
||||
/* Print the non el3 sys registers */
|
||||
adr x6, non_el3_sys_regs
|
||||
mrs x8, spsr_el1
|
||||
mrs x9, elr_el1
|
||||
mrs x10, spsr_abt
|
||||
mrs x11, spsr_und
|
||||
mrs x12, spsr_irq
|
||||
mrs x13, spsr_fiq
|
||||
mrs x14, sctlr_el1
|
||||
mrs x15, actlr_el1
|
||||
bl str_in_crash_buf_print
|
||||
mrs x8, cpacr_el1
|
||||
mrs x9, csselr_el1
|
||||
mrs x10, sp_el1
|
||||
mrs x11, esr_el1
|
||||
mrs x12, ttbr0_el1
|
||||
mrs x13, ttbr1_el1
|
||||
mrs x14, mair_el1
|
||||
mrs x15, amair_el1
|
||||
mrs x16, tcr_el1
|
||||
mrs x17, tpidr_el1
|
||||
bl str_in_crash_buf_print
|
||||
mrs x8, tcr_el1
|
||||
mrs x9, tpidr_el1
|
||||
mrs x10, tpidr_el0
|
||||
mrs x11, tpidrro_el0
|
||||
mrs x12, dacr32_el2
|
||||
mrs x13, ifsr32_el2
|
||||
mrs x14, par_el1
|
||||
mrs x15, mpidr_el1
|
||||
bl str_in_crash_buf_print
|
||||
mrs x8, afsr0_el1
|
||||
mrs x9, afsr1_el1
|
||||
mrs x10, contextidr_el1
|
||||
mrs x11, vbar_el1
|
||||
mrs x12, cntp_ctl_el0
|
||||
mrs x13, cntp_cval_el0
|
||||
mrs x14, cntv_ctl_el0
|
||||
mrs x15, cntv_cval_el0
|
||||
bl str_in_crash_buf_print
|
||||
mrs x8, cntkctl_el1
|
||||
mrs x9, fpexc32_el2
|
||||
mrs x10, sp_el0
|
||||
bl str_in_crash_buf_print
|
||||
|
||||
stp x10, x11, [sp, #(REG_SIZE * 10)]
|
||||
stp x12, x13, [sp, #(REG_SIZE * 12)]
|
||||
stp x14, x15, [sp, #(REG_SIZE * 14)]
|
||||
stp x16, x17, [sp, #(REG_SIZE * 16)]
|
||||
/* Print the CPUECTLR_EL1 reg */
|
||||
mrs x0, midr_el1
|
||||
lsr x0, x0, #MIDR_PN_SHIFT
|
||||
and x0, x0, #MIDR_PN_MASK
|
||||
cmp x0, #MIDR_PN_A57
|
||||
b.eq 1f
|
||||
cmp x0, #MIDR_PN_A53
|
||||
b.ne 2f
|
||||
1:
|
||||
adr x4, cpu_ectlr_reg
|
||||
bl asm_print_str
|
||||
mrs x4, CPUECTLR_EL1
|
||||
bl asm_print_hex
|
||||
bl print_newline
|
||||
2:
|
||||
|
||||
adr x0, non_el3_sys_0_regs
|
||||
mov x1, sp
|
||||
bl print_string_value
|
||||
add sp, sp, #NON_EL3_SYS_0_REG_SIZE
|
||||
.endm
|
||||
/* Print the gic registers */
|
||||
plat_print_gic_regs
|
||||
|
||||
.macro print_non_el3_sys_1_regs
|
||||
sub sp, sp, #NON_EL3_SYS_1_REG_SIZE
|
||||
/* Print the interconnect registers */
|
||||
plat_print_interconnect_regs
|
||||
|
||||
mrs x9, tpidr_el0
|
||||
mrs x10, tpidrro_el0
|
||||
mrs x11, dacr32_el2
|
||||
mrs x12, ifsr32_el2
|
||||
mrs x13, par_el1
|
||||
mrs x14, far_el1
|
||||
mrs x15, afsr0_el1
|
||||
mrs x16, afsr1_el1
|
||||
mrs x17, contextidr_el1
|
||||
mrs x8, vbar_el1
|
||||
|
||||
stp x9, x10, [sp]
|
||||
stp x11, x12, [sp, #(REG_SIZE * 2)]
|
||||
stp x13, x14, [sp, #(REG_SIZE * 4)]
|
||||
stp x15, x16, [sp, #(REG_SIZE * 6)]
|
||||
stp x17, x8, [sp, #(REG_SIZE * 8)]
|
||||
|
||||
mrs x10, cntp_ctl_el0
|
||||
mrs x11, cntp_cval_el0
|
||||
mrs x12, cntv_ctl_el0
|
||||
mrs x13, cntv_cval_el0
|
||||
mrs x14, cntkctl_el1
|
||||
mrs x15, fpexc32_el2
|
||||
mrs x8, sp_el0
|
||||
|
||||
stp x10, x11, [sp, #(REG_SIZE *10)]
|
||||
stp x12, x13, [sp, #(REG_SIZE * 12)]
|
||||
stp x14, x15, [sp, #(REG_SIZE * 14)]
|
||||
stp x8, xzr, [sp, #(REG_SIZE * 16)]
|
||||
|
||||
adr x0, non_el3_sys_1_regs
|
||||
mov x1, sp
|
||||
bl print_string_value
|
||||
add sp, sp, #NON_EL3_SYS_1_REG_SIZE
|
||||
.endm
|
||||
|
||||
.macro init_crash_stack
|
||||
msr cntfrq_el0, x0 /* we can corrupt this reg to free up x0 */
|
||||
mrs x0, tpidr_el3
|
||||
|
||||
/* Check if tpidr is initialized */
|
||||
cbz x0, infinite_loop
|
||||
|
||||
ldr x0, [x0, #CPU_DATA_CRASH_STACK_OFFSET]
|
||||
/* store the x30 and sp to stack */
|
||||
str x30, [x0, #-(REG_SIZE)]!
|
||||
mov x30, sp
|
||||
str x30, [x0, #-(REG_SIZE)]!
|
||||
mov sp, x0
|
||||
mrs x0, cntfrq_el0
|
||||
.endm
|
||||
|
||||
/* ---------------------------------------------------
|
||||
* The below function initializes the crash dump stack ,
|
||||
* and prints the system state. This function
|
||||
* will not return.
|
||||
* ---------------------------------------------------
|
||||
*/
|
||||
func dump_state_and_die
|
||||
init_crash_stack
|
||||
print_caller_saved_regs
|
||||
b print_state
|
||||
|
||||
func dump_intr_state_and_die
|
||||
init_crash_stack
|
||||
print_caller_saved_regs
|
||||
plat_print_gic_regs /* fall through to print_state */
|
||||
|
||||
print_state:
|
||||
/* copy the original x30 from stack */
|
||||
ldr x30, [sp, #REG_SIZE]
|
||||
print_callee_saved_regs
|
||||
/* copy the original SP_EL3 from stack to x0 and rewind stack */
|
||||
ldr x0, [sp], #(REG_SIZE * 2)
|
||||
print_el3_sys_regs
|
||||
print_non_el3_sys_0_regs
|
||||
print_non_el3_sys_1_regs
|
||||
|
||||
#else /* CRASH_REPORING */
|
||||
|
||||
func dump_state_and_die
|
||||
dump_intr_state_and_die:
|
||||
/* Done reporting */
|
||||
b crash_panic
|
||||
|
||||
#else /* CRASH_REPORTING */
|
||||
func report_unhandled_exception
|
||||
report_unhandled_interrupt:
|
||||
b crash_panic
|
||||
#endif /* CRASH_REPORING */
|
||||
|
||||
infinite_loop:
|
||||
b infinite_loop
|
||||
|
||||
|
||||
#define PCPU_CRASH_STACK_SIZE 0x140
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Per-cpu crash stacks in normal memory.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
declare_stack pcpu_crash_stack, tzfw_normal_stacks, \
|
||||
PCPU_CRASH_STACK_SIZE, PLATFORM_CORE_COUNT
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Provides each CPU with a small stacks for reporting
|
||||
* unhandled exceptions, and stores the stack address
|
||||
* in cpu_data
|
||||
*
|
||||
* This can be called without a runtime stack
|
||||
* clobbers: x0 - x4
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func init_crash_reporting
|
||||
mov x4, x30
|
||||
mov x2, #0
|
||||
adr x3, pcpu_crash_stack
|
||||
init_crash_loop:
|
||||
mov x0, x2
|
||||
bl _cpu_data_by_index
|
||||
add x3, x3, #PCPU_CRASH_STACK_SIZE
|
||||
str x3, [x0, #CPU_DATA_CRASH_STACK_OFFSET]
|
||||
add x2, x2, #1
|
||||
cmp x2, #PLATFORM_CORE_COUNT
|
||||
b.lo init_crash_loop
|
||||
ret x4
|
||||
func crash_panic
|
||||
b crash_panic
|
||||
|
@ -60,7 +60,7 @@
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
|
||||
bl dump_state_and_die
|
||||
bl report_unhandled_exception
|
||||
.endm
|
||||
|
||||
|
||||
@ -142,7 +142,7 @@ interrupt_exit_\label:
|
||||
* where the interrupt was generated.
|
||||
*/
|
||||
interrupt_error_\label:
|
||||
bl dump_intr_state_and_die
|
||||
bl report_unhandled_interrupt
|
||||
.endm
|
||||
|
||||
|
||||
@ -158,7 +158,6 @@ interrupt_error_\label:
|
||||
.endm
|
||||
|
||||
.section .vectors, "ax"; .align 11
|
||||
|
||||
.align 7
|
||||
runtime_exceptions:
|
||||
/* -----------------------------------------------------
|
||||
@ -170,7 +169,7 @@ sync_exception_sp_el0:
|
||||
* We don't expect any synchronous exceptions from EL3
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
bl dump_state_and_die
|
||||
bl report_unhandled_exception
|
||||
check_vector_size sync_exception_sp_el0
|
||||
|
||||
.align 7
|
||||
@ -180,17 +179,17 @@ sync_exception_sp_el0:
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
irq_sp_el0:
|
||||
bl dump_intr_state_and_die
|
||||
bl report_unhandled_interrupt
|
||||
check_vector_size irq_sp_el0
|
||||
|
||||
.align 7
|
||||
fiq_sp_el0:
|
||||
bl dump_intr_state_and_die
|
||||
bl report_unhandled_interrupt
|
||||
check_vector_size fiq_sp_el0
|
||||
|
||||
.align 7
|
||||
serror_sp_el0:
|
||||
bl dump_state_and_die
|
||||
bl report_unhandled_exception
|
||||
check_vector_size serror_sp_el0
|
||||
|
||||
/* -----------------------------------------------------
|
||||
@ -206,22 +205,22 @@ sync_exception_sp_elx:
|
||||
* There is a high probability that SP_EL3 is corrupted.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
bl dump_state_and_die
|
||||
bl report_unhandled_exception
|
||||
check_vector_size sync_exception_sp_elx
|
||||
|
||||
.align 7
|
||||
irq_sp_elx:
|
||||
bl dump_intr_state_and_die
|
||||
bl report_unhandled_interrupt
|
||||
check_vector_size irq_sp_elx
|
||||
|
||||
.align 7
|
||||
fiq_sp_elx:
|
||||
bl dump_intr_state_and_die
|
||||
bl report_unhandled_interrupt
|
||||
check_vector_size fiq_sp_elx
|
||||
|
||||
.align 7
|
||||
serror_sp_elx:
|
||||
bl dump_state_and_die
|
||||
bl report_unhandled_exception
|
||||
check_vector_size serror_sp_elx
|
||||
|
||||
/* -----------------------------------------------------
|
||||
@ -258,7 +257,7 @@ fiq_aarch64:
|
||||
|
||||
.align 7
|
||||
serror_aarch64:
|
||||
bl dump_state_and_die
|
||||
bl report_unhandled_exception
|
||||
check_vector_size serror_aarch64
|
||||
|
||||
/* -----------------------------------------------------
|
||||
@ -295,7 +294,7 @@ fiq_aarch32:
|
||||
|
||||
.align 7
|
||||
serror_aarch32:
|
||||
bl dump_state_and_die
|
||||
bl report_unhandled_exception
|
||||
check_vector_size serror_aarch32
|
||||
|
||||
.align 7
|
||||
@ -473,7 +472,7 @@ smc_prohibited:
|
||||
|
||||
rt_svc_fw_critical_error:
|
||||
msr spsel, #1 /* Switch to SP_ELx */
|
||||
bl dump_state_and_die
|
||||
bl report_unhandled_exception
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* The following functions are used to saved and restore
|
||||
|
@ -32,13 +32,5 @@
|
||||
#include <cpu_data.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/* verify assembler offsets match data structures */
|
||||
CASSERT(CPU_DATA_CRASH_STACK_OFFSET == __builtin_offsetof
|
||||
(cpu_data_t, crash_stack),
|
||||
assert_cpu_data_crash_stack_offset_mismatch);
|
||||
|
||||
CASSERT((1 << CPU_DATA_LOG2SIZE) == sizeof(cpu_data_t),
|
||||
assert_cpu_data_log2size_mismatch);
|
||||
|
||||
/* The per_cpu_ptr_cache_t space allocation */
|
||||
cpu_data_t percpu_data[PLATFORM_CORE_COUNT];
|
||||
|
188
common/aarch64/debug.S
Normal file
188
common/aarch64/debug.S
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of ARM nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
|
||||
.globl asm_print_str
|
||||
.globl asm_print_hex
|
||||
.globl asm_assert
|
||||
.globl do_panic
|
||||
|
||||
/* Since the max decimal input number is 65536 */
|
||||
#define MAX_DEC_DIVISOR 10000
|
||||
/* The offset to add to get ascii for numerals '0 - 9' */
|
||||
#define ASCII_OFFSET_NUM 0x30
|
||||
|
||||
#if ASM_ASSERTION
|
||||
.section .rodata.assert_str, "aS"
|
||||
assert_msg1:
|
||||
.asciz "ASSERT: File "
|
||||
assert_msg2:
|
||||
.asciz " Line "
|
||||
|
||||
/*
|
||||
* This macro is intended to be used to print the
|
||||
* line number in decimal. Used by asm_assert macro.
|
||||
* The max number expected is 65536.
|
||||
* In: x4 = the decimal to print.
|
||||
* Clobber: x30, x0, x1, x2, x5, x6
|
||||
*/
|
||||
.macro asm_print_line_dec
|
||||
mov x6, #10 /* Divide by 10 after every loop iteration */
|
||||
mov x5, #MAX_DEC_DIVISOR
|
||||
1:
|
||||
udiv x0, x4, x5 /* Get the quotient */
|
||||
msub x4, x0, x5, x4 /* Find the remainder */
|
||||
add x0, x0, #ASCII_OFFSET_NUM /* Convert to ascii */
|
||||
bl plat_crash_console_putc
|
||||
udiv x5, x5, x6 /* Reduce divisor */
|
||||
cbnz x5, 1b
|
||||
.endm
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* Assertion support in assembly.
|
||||
* The below function helps to support assertions in assembly where we do not
|
||||
* have a C runtime stack. Arguments to the function are :
|
||||
* x0 - File name
|
||||
* x1 - Line no
|
||||
* Clobber list : x30, x0, x1, x2, x3, x4, x5, x6.
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
func asm_assert
|
||||
mov x5, x0
|
||||
mov x6, x1
|
||||
/* Ensure the console is initialized */
|
||||
bl plat_crash_console_init
|
||||
/* Check if the console is initialized */
|
||||
cbz x0, _assert_loop
|
||||
/* The console is initialized */
|
||||
adr x4, assert_msg1
|
||||
bl asm_print_str
|
||||
mov x4, x5
|
||||
bl asm_print_str
|
||||
adr x4, assert_msg2
|
||||
bl asm_print_str
|
||||
/* Check if line number higher than max permitted */
|
||||
tst x6, #~0xffff
|
||||
b.ne _assert_loop
|
||||
mov x4, x6
|
||||
asm_print_line_dec
|
||||
_assert_loop:
|
||||
b _assert_loop
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function prints a string from address in x4.
|
||||
* In: x4 = pointer to string.
|
||||
* Clobber: x30, x0, x1, x2, x3
|
||||
*/
|
||||
func asm_print_str
|
||||
mov x3, x30
|
||||
1:
|
||||
ldrb w0, [x4], #0x1
|
||||
cbz x0, 2f
|
||||
bl plat_crash_console_putc
|
||||
b 1b
|
||||
2:
|
||||
ret x3
|
||||
|
||||
/*
|
||||
* This function prints a hexadecimal number in x4.
|
||||
* In: x4 = the hexadecimal to print.
|
||||
* Clobber: x30, x0, x5, x1, x2, x3
|
||||
*/
|
||||
func asm_print_hex
|
||||
mov x3, x30
|
||||
mov x5, #64 /* No of bits to convert to ascii */
|
||||
1:
|
||||
sub x5, x5, #4
|
||||
lsrv x0, x4, x5
|
||||
and x0, x0, #0xf
|
||||
cmp x0, #0xA
|
||||
b.lo 2f
|
||||
/* Add by 0x27 in addition to ASCII_OFFSET_NUM
|
||||
* to get ascii for characters 'a - f'.
|
||||
*/
|
||||
add x0, x0, #0x27
|
||||
2:
|
||||
add x0, x0, #ASCII_OFFSET_NUM
|
||||
bl plat_crash_console_putc
|
||||
cbnz x5, 1b
|
||||
ret x3
|
||||
|
||||
/***********************************************************
|
||||
* The common implementation of do_panic for all BL stages
|
||||
***********************************************************/
|
||||
|
||||
.section .rodata.panic_str, "aS"
|
||||
panic_msg: .asciz "PANIC at PC : 0x"
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* do_panic assumes that it is invoked from a C Runtime Environment ie a
|
||||
* valid stack exists. This call will not return.
|
||||
* Clobber list : if CRASH_REPORTING is not enabled then x30, x0 - x6
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* This is for the non el3 BL stages to compile through */
|
||||
.weak el3_panic
|
||||
|
||||
func do_panic
|
||||
#if CRASH_REPORTING
|
||||
str x0, [sp, #-0x10]!
|
||||
mrs x0, currentel
|
||||
ubfx x0, x0, #2, #2
|
||||
cmp x0, #0x3
|
||||
ldr x0, [sp], #0x10
|
||||
b.eq el3_panic
|
||||
#endif
|
||||
|
||||
panic_common:
|
||||
/*
|
||||
* el3_panic will be redefined by the BL31
|
||||
* crash reporting mechanism (if enabled)
|
||||
*/
|
||||
el3_panic:
|
||||
mov x6, x30
|
||||
bl plat_crash_console_init
|
||||
/* Check if the console is initialized */
|
||||
cbz x0, _panic_loop
|
||||
/* The console is initialized */
|
||||
adr x4, panic_msg
|
||||
bl asm_print_str
|
||||
mov x4, x6
|
||||
/* The panic location is lr -4 */
|
||||
sub x4, x4, #4
|
||||
bl asm_print_hex
|
||||
_panic_loop:
|
||||
b _panic_loop
|
||||
|
@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of ARM nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <console.h>
|
||||
#include <debug.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/******************************************************************
|
||||
* This function is invoked from assembler error handling routines and
|
||||
* prints out the string and the value in 64 bit hex format. These
|
||||
* are passed to the function as input parameters.
|
||||
********************************************************************/
|
||||
void print_string_value(char *s, unsigned long *mem)
|
||||
{
|
||||
unsigned char i, temp;
|
||||
unsigned long val;
|
||||
|
||||
while (*s) {
|
||||
i = 16;
|
||||
while (*s)
|
||||
console_putc(*s++);
|
||||
|
||||
s++;
|
||||
|
||||
console_putc('\t');
|
||||
console_putc(':');
|
||||
console_putc('0');
|
||||
console_putc('x');
|
||||
|
||||
val = *mem++;
|
||||
|
||||
while (i--) {
|
||||
temp = (val >> (i << 2)) & 0xf;
|
||||
if (temp < 0xa)
|
||||
console_putc('0' + temp);
|
||||
else
|
||||
console_putc('A' + (temp - 0xa));
|
||||
}
|
||||
console_putc('\n');
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* The common implementation of do_panic for all BL stages
|
||||
***********************************************************/
|
||||
|
||||
#if DEBUG
|
||||
void __dead2 do_panic(const char *file, int line)
|
||||
{
|
||||
tf_printf("PANIC in file: %s line: %d\n", file, line);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
#else
|
||||
void __dead2 do_panic(void)
|
||||
{
|
||||
unsigned long pc_reg;
|
||||
__asm__ volatile("mov %0, x30\n"
|
||||
: "=r" (pc_reg) : );
|
||||
|
||||
/* x30 reports the next eligible instruction whereas we want the
|
||||
* place where panic() is invoked. Hence decrement by 4.
|
||||
*/
|
||||
tf_printf("PANIC in PC location 0x%016X\n", pc_reg - 0x4);
|
||||
while (1)
|
||||
;
|
||||
|
||||
}
|
||||
#endif
|
@ -15,6 +15,7 @@ Contents
|
||||
* Boot Loader stage 3-1 (BL3-1)
|
||||
* PSCI implementation (in BL3-1)
|
||||
* Interrupt Management framework (in BL3-1)
|
||||
* Crash Reporting mechanism (in BL3-1)
|
||||
4. C Library
|
||||
5. Storage abstraction layer
|
||||
|
||||
@ -268,10 +269,18 @@ the following macro defined. In the ARM FVP port, this file is found in
|
||||
* **Macro : plat_print_gic_regs**
|
||||
|
||||
This macro allows the crash reporting routine to print GIC registers
|
||||
in case of an unhandled IRQ or FIQ in BL3-1. This aids in debugging and
|
||||
in case of an unhandled exception in BL3-1. This aids in debugging and
|
||||
this macro can be defined to be empty in case GIC register reporting is
|
||||
not desired.
|
||||
|
||||
* **Macro : plat_print_interconnect_regs**
|
||||
|
||||
This macro allows the crash reporting routine to print interconnect registers
|
||||
in case of an unhandled exception in BL3-1. This aids in debugging and
|
||||
this macro can be defined to be empty in case interconnect register reporting
|
||||
is not desired. In the ARM FVP port, the CCI snoop control registers are
|
||||
reported.
|
||||
|
||||
### Other mandatory modifications
|
||||
|
||||
The following mandatory modifications may be implemented in any file
|
||||
@ -1265,6 +1274,41 @@ interrupts as Group1 interrupts. It reads the group value corresponding to the
|
||||
interrupt id from the relevant _Interrupt Group Register_ (`GICD_IGROUPRn`). It
|
||||
uses the group value to determine the type of interrupt.
|
||||
|
||||
3.5 Crash Reporting mechanism (in BL3-1)
|
||||
----------------------------------------------
|
||||
BL3-1 implements a crash reporting mechanism which prints the various registers
|
||||
of the CPU to enable quick crash analysis and debugging. It requires that a console
|
||||
is designated as the crash console by the platform which will used to print the
|
||||
register dump.
|
||||
|
||||
The following functions must be implemented by the platform if it wants crash reporting
|
||||
mechanism in BL3-1. The functions are implemented in assembly so that they can be
|
||||
invoked without a C Runtime stack.
|
||||
|
||||
### Function : plat_crash_console_init
|
||||
|
||||
Argument : void
|
||||
Return : int
|
||||
|
||||
This API is used by the crash reporting mechanism to intialize the crash console.
|
||||
It should only use the general purpose registers x0 to x2 to do the initiaization
|
||||
and returns 1 on success.
|
||||
|
||||
The FVP port designates the PL011_UART0 as the crash console and calls the
|
||||
console_core_init() to initialize the console.
|
||||
|
||||
### Function : plat_crash_console_putc
|
||||
|
||||
Argument : int
|
||||
Return : int
|
||||
|
||||
This API is used by the crash reporting mechanism to print a character on the
|
||||
designated crash console. It should only use general purpose registers x1 and
|
||||
x2 to do its work. The parameter and the return value are in general purpose
|
||||
register x0.
|
||||
|
||||
The FVP port designates the PL011_UART0 as the crash console and calls the
|
||||
console_core_putc() to print the character on the console.
|
||||
|
||||
4. C Library
|
||||
-------------
|
||||
|
@ -181,6 +181,11 @@ performed.
|
||||
BL3-1. This option defaults to the value of `DEBUG` - i.e. by default
|
||||
this is only enabled for a debug build of the firmware.
|
||||
|
||||
* `ASM_ASSERTION`: This flag determines whether the assertion checks within
|
||||
assembly source files are enabled or not. This option defaults to the
|
||||
value of `DEBUG` - i.e. by default this is only enabled for a debug
|
||||
build of the firmware.
|
||||
|
||||
### Creating a Firmware Image Package
|
||||
|
||||
FIPs are automatically created as part of the build instructions described in
|
||||
|
178
drivers/arm/pl011/pl011_console.S
Normal file
178
drivers/arm/pl011/pl011_console.S
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of ARM nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <pl011.h>
|
||||
|
||||
.globl console_init
|
||||
.globl console_putc
|
||||
.globl console_core_init
|
||||
.globl console_core_putc
|
||||
.globl console_getc
|
||||
|
||||
/*
|
||||
* The console base is in the data section and not in .bss
|
||||
* even though it is zero-init. In particular, this allows
|
||||
* the console functions to start using this variable before
|
||||
* the runtime memory is initialized for images which do not
|
||||
* need to copy the .data section from ROM to RAM.
|
||||
*/
|
||||
.section .data.console_base ; .align 3
|
||||
console_base: .quad 0x0
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_init(unsigned long base_addr,
|
||||
* unsigned int uart_clk, unsigned int baud_rate)
|
||||
* Function to initialize the console without a
|
||||
* C Runtime to print debug information. It saves
|
||||
* the console base to the data section.
|
||||
* In: x0 - console base address
|
||||
* w1 - Uart clock in Hz
|
||||
* w2 - Baud rate
|
||||
* out: return 1 on success.
|
||||
* Clobber list : x1 - x3
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_init
|
||||
adrp x3, console_base
|
||||
str x0, [x3, :lo12:console_base]
|
||||
b console_core_init
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_core_init(unsigned long base_addr,
|
||||
* unsigned int uart_clk, unsigned int baud_rate)
|
||||
* Function to initialize the console without a
|
||||
* C Runtime to print debug information. This
|
||||
* function will be accessed by console_init and
|
||||
* crash reporting.
|
||||
* In: x0 - console base address
|
||||
* w1 - Uart clock in Hz
|
||||
* w2 - Baud rate
|
||||
* Out: return 1 on success
|
||||
* Clobber list : x1, x2
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_core_init
|
||||
/* Check the input base address */
|
||||
cbz x0, init_fail
|
||||
/* Check baud rate and uart clock for sanity */
|
||||
cbz w1, init_fail
|
||||
cbz w2, init_fail
|
||||
/* Program the baudrate */
|
||||
/* Divisor = (Uart clock * 4) / baudrate */
|
||||
lsl w1, w1, #2
|
||||
udiv w2, w1, w2
|
||||
/* IBRD = Divisor >> 6 */
|
||||
lsr w1, w2, #6
|
||||
/* Write the IBRD */
|
||||
str w1, [x0, #UARTIBRD]
|
||||
/* FBRD = Divisor & 0x3F */
|
||||
and w1, w2, #0x3f
|
||||
/* Write the FBRD */
|
||||
str w1, [x0, #UARTFBRD]
|
||||
mov w1, #PL011_LINE_CONTROL
|
||||
str w1, [x0, #UARTLCR_H]
|
||||
/* Clear any pending errors */
|
||||
str wzr, [x0, #UARTECR]
|
||||
/* Enable tx, rx, and uart overall */
|
||||
mov w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
|
||||
str w1, [x0, #UARTCR]
|
||||
mov w0, #1
|
||||
init_fail:
|
||||
ret
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_putc(int c)
|
||||
* Function to output a character over the
|
||||
* console. It returns the character printed on
|
||||
* success or -1 on error.
|
||||
* In : x0 - character to be printed
|
||||
* Out : return -1 on error else return character.
|
||||
* Clobber list : x1, x2
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_putc
|
||||
adrp x2, console_base
|
||||
ldr x1, [x2, :lo12:console_base]
|
||||
b console_core_putc
|
||||
|
||||
/* --------------------------------------------------------
|
||||
* int console_core_putc(int c, unsigned int base_addr)
|
||||
* Function to output a character over the console. It
|
||||
* returns the character printed on success or -1 on error.
|
||||
* In : w0 - character to be printed
|
||||
* x1 - console base address
|
||||
* Out : return -1 on error else return character.
|
||||
* Clobber list : x2
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
func console_core_putc
|
||||
/* Check the input parameter */
|
||||
cbz x1, putc_error
|
||||
/* Prepend '\r' to '\n' */
|
||||
cmp w0, #0xA
|
||||
b.ne 2f
|
||||
1:
|
||||
/* Check if the transmit FIFO is full */
|
||||
ldr w2, [x1, #UARTFR]
|
||||
tbnz w2, #PL011_UARTFR_TXFF_BIT, 1b
|
||||
mov w2, #0xD
|
||||
str w2, [x1, #UARTDR]
|
||||
2:
|
||||
/* Check if the transmit FIFO is full */
|
||||
ldr w2, [x1, #UARTFR]
|
||||
tbnz w2, #PL011_UARTFR_TXFF_BIT, 2b
|
||||
str w0, [x1, #UARTDR]
|
||||
ret
|
||||
putc_error:
|
||||
mov w0, #-1
|
||||
ret
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_getc(void)
|
||||
* Function to get a character from the console.
|
||||
* It returns the character grabbed on success
|
||||
* or -1 on error.
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_getc
|
||||
adrp x0, console_base
|
||||
ldr x1, [x0, :lo12:console_base]
|
||||
cbz x1, getc_error
|
||||
1:
|
||||
/* Check if the receive FIFO is empty */
|
||||
ldr w0, [x1, #UARTFR]
|
||||
tbnz w0, #PL011_UARTFR_RXFE_BIT, 1b
|
||||
ldr w0, [x1, #UARTDR]
|
||||
ret
|
||||
getc_error:
|
||||
mov w0, #-1
|
||||
ret
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of ARM nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <console.h>
|
||||
#include <pl011.h>
|
||||
|
||||
static unsigned long uart_base;
|
||||
|
||||
void console_init(unsigned long base_addr)
|
||||
{
|
||||
/* TODO: assert() internally calls printf() and will result in
|
||||
* an infinite loop. This needs to be fixed with some kind of
|
||||
* exception mechanism or early panic support. This also applies
|
||||
* to the other assert() calls below.
|
||||
*/
|
||||
assert(base_addr);
|
||||
|
||||
/* Initialise internal base address variable */
|
||||
uart_base = base_addr;
|
||||
|
||||
/* Baud Rate */
|
||||
#if defined(PL011_INTEGER) && defined(PL011_FRACTIONAL)
|
||||
pl011_write_ibrd(uart_base, PL011_INTEGER);
|
||||
pl011_write_fbrd(uart_base, PL011_FRACTIONAL);
|
||||
#else
|
||||
pl011_setbaudrate(uart_base, PL011_BAUDRATE);
|
||||
#endif
|
||||
|
||||
pl011_write_lcr_h(uart_base, PL011_LINE_CONTROL);
|
||||
|
||||
/* Clear any pending errors */
|
||||
pl011_write_ecr(uart_base, 0);
|
||||
|
||||
/* Enable tx, rx, and uart overall */
|
||||
pl011_write_cr(uart_base, PL011_UARTCR_RXE | PL011_UARTCR_TXE |
|
||||
PL011_UARTCR_UARTEN);
|
||||
|
||||
}
|
||||
|
||||
#define WAIT_UNTIL_UART_FREE(base) \
|
||||
while ((pl011_read_fr(base) & PL011_UARTFR_TXFF)) \
|
||||
continue
|
||||
|
||||
int console_putc(int c)
|
||||
{
|
||||
/* If the console has not been initialized then return an error
|
||||
* code. Asserting here would result in recursion and stack
|
||||
* exhaustion
|
||||
*/
|
||||
if (!uart_base)
|
||||
return -1;
|
||||
|
||||
if (c == '\n') {
|
||||
WAIT_UNTIL_UART_FREE(uart_base);
|
||||
pl011_write_dr(uart_base, '\r');
|
||||
}
|
||||
|
||||
WAIT_UNTIL_UART_FREE(uart_base);
|
||||
pl011_write_dr(uart_base, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
int console_getc(void)
|
||||
{
|
||||
assert(uart_base);
|
||||
|
||||
while ((pl011_read_fr(uart_base) & PL011_UARTFR_RXFE) != 0)
|
||||
;
|
||||
return pl011_read_dr(uart_base);
|
||||
}
|
@ -32,9 +32,14 @@
|
||||
#define __CPU_DATA_H__
|
||||
|
||||
/* Offsets for the cpu_data structure */
|
||||
#define CPU_DATA_CRASH_STACK_OFFSET 0x10
|
||||
#define CPU_DATA_CRASH_BUF_OFFSET 0x10
|
||||
#if CRASH_REPORTING
|
||||
#define CPU_DATA_LOG2SIZE 7
|
||||
#else
|
||||
#define CPU_DATA_LOG2SIZE 6
|
||||
|
||||
#endif
|
||||
/* need enough space in crash buffer to save 8 registers */
|
||||
#define CPU_DATA_CRASH_BUF_SIZE 64
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <arch_helpers.h>
|
||||
@ -61,9 +66,21 @@
|
||||
|
||||
typedef struct cpu_data {
|
||||
void *cpu_context[2];
|
||||
uint64_t crash_stack;
|
||||
#if CRASH_REPORTING
|
||||
uint64_t crash_buf[CPU_DATA_CRASH_BUF_SIZE >> 3];
|
||||
#endif
|
||||
} __aligned(CACHE_WRITEBACK_GRANULE) cpu_data_t;
|
||||
|
||||
#if CRASH_REPORTING
|
||||
/* verify assembler offsets match data structures */
|
||||
CASSERT(CPU_DATA_CRASH_BUF_OFFSET == __builtin_offsetof
|
||||
(cpu_data_t, crash_buf),
|
||||
assert_cpu_data_crash_stack_offset_mismatch);
|
||||
#endif
|
||||
|
||||
CASSERT((1 << CPU_DATA_LOG2SIZE) == sizeof(cpu_data_t),
|
||||
assert_cpu_data_log2size_mismatch);
|
||||
|
||||
struct cpu_data *_cpu_data_by_index(uint32_t cpu_index);
|
||||
struct cpu_data *_cpu_data_by_mpidr(uint64_t mpidr);
|
||||
|
||||
|
@ -162,3 +162,36 @@ wait_for_entrypoint:
|
||||
.macro get_up_stack _name, _size
|
||||
ldr x0, =(\_name + \_size)
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Helper macro to generate the best mov/movk combinations according
|
||||
* the value to be moved. The 16 bits from '_shift' are tested and
|
||||
* if not zero, they are moved into '_reg' without affecting
|
||||
* other bits.
|
||||
*/
|
||||
.macro _mov_imm16 _reg, _val, _shift
|
||||
.if (\_val >> \_shift) & 0xffff
|
||||
.if (\_val & (1 << \_shift - 1))
|
||||
movk \_reg, (\_val >> \_shift) & 0xffff, LSL \_shift
|
||||
.else
|
||||
mov \_reg, \_val & (0xffff << \_shift)
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Helper macro to load arbitrary values into 32 or 64-bit registers
|
||||
* which generates the best mov/movk combinations. Many base addresses
|
||||
* are 64KB aligned the macro will eliminate updating bits 15:0 in
|
||||
* that case
|
||||
*/
|
||||
.macro mov_imm _reg, _val
|
||||
.if (\_val) == 0
|
||||
mov \_reg, #0
|
||||
.else
|
||||
_mov_imm16 \_reg, (\_val), 0
|
||||
_mov_imm16 \_reg, (\_val), 16
|
||||
_mov_imm16 \_reg, (\_val), 32
|
||||
_mov_imm16 \_reg, (\_val), 48
|
||||
.endif
|
||||
.endm
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@ -28,14 +28,19 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <pl011.h>
|
||||
|
||||
void pl011_setbaudrate(unsigned long base_addr, unsigned int baudrate)
|
||||
{
|
||||
unsigned int divisor;
|
||||
assert(baudrate);
|
||||
divisor = (PL011_CLK_IN_HZ * 4) / baudrate;
|
||||
pl011_write_ibrd(base_addr, divisor >> 6);
|
||||
pl011_write_fbrd(base_addr, divisor & 0x3F);
|
||||
}
|
||||
/*
|
||||
* Assembler macro to enable asm_assert. Use this macro wherever
|
||||
* assert is required in assembly.
|
||||
*/
|
||||
#define ASM_ASSERT(_cc) \
|
||||
.ifndef .L_assert_filename ;\
|
||||
.pushsection .rodata.str1.1, "aS" ;\
|
||||
.L_assert_filename: ;\
|
||||
.string __FILE__ ;\
|
||||
.popsection ;\
|
||||
.endif ;\
|
||||
b._cc 1f ;\
|
||||
adr x0, .L_assert_filename ;\
|
||||
mov x1, __LINE__ ;\
|
||||
b asm_assert ;\
|
||||
1:
|
@ -52,22 +52,9 @@
|
||||
|
||||
#define ERROR(...) tf_printf("ERROR: " __VA_ARGS__)
|
||||
|
||||
|
||||
/* For the moment this Panic function is very basic, Report an error and
|
||||
* spin. This can be expanded in the future to provide more information.
|
||||
*/
|
||||
#if DEBUG
|
||||
void __dead2 do_panic(const char *file, int line);
|
||||
#define panic() do_panic(__FILE__, __LINE__)
|
||||
|
||||
#else
|
||||
void __dead2 do_panic(void);
|
||||
#define panic() do_panic()
|
||||
|
||||
#endif
|
||||
|
||||
void print_string_value(char *s, unsigned long *mem);
|
||||
void tf_printf(const char *fmt, ...);
|
||||
|
||||
|
||||
#endif /* __DEBUG_H__ */
|
||||
|
@ -65,8 +65,11 @@
|
||||
/* Status register bit definitions */
|
||||
#define CHANGE_PENDING_BIT (1 << 0)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* Function declarations */
|
||||
void cci_enable_coherency(unsigned long mpidr);
|
||||
void cci_disable_coherency(unsigned long mpidr);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __CCI_400_H__ */
|
||||
|
@ -31,9 +31,6 @@
|
||||
#ifndef __PL011_H__
|
||||
#define __PL011_H__
|
||||
|
||||
#include <mmio.h>
|
||||
|
||||
|
||||
/* PL011 Registers */
|
||||
#define UARTDR 0x000
|
||||
#define UARTRSR 0x004
|
||||
@ -68,6 +65,9 @@
|
||||
#define PL011_UARTFR_DSR (1 << 1) /* Data set ready */
|
||||
#define PL011_UARTFR_CTS (1 << 0) /* Clear to send */
|
||||
|
||||
#define PL011_UARTFR_TXFF_BIT 5 /* Transmit FIFO full bit in UARTFR register */
|
||||
#define PL011_UARTFR_RXFE_BIT 4 /* Receive FIFO empty bit in UARTFR register */
|
||||
|
||||
/* Control reg bits */
|
||||
#define PL011_UARTCR_CTSEN (1 << 15) /* CTS hardware flow control enable */
|
||||
#define PL011_UARTCR_RTSEN (1 << 14) /* RTS hardware flow control enable */
|
||||
@ -78,14 +78,6 @@
|
||||
#define PL011_UARTCR_LBE (1 << 7) /* Loopback enable */
|
||||
#define PL011_UARTCR_UARTEN (1 << 0) /* UART Enable */
|
||||
|
||||
#if !defined(PL011_BAUDRATE)
|
||||
#define PL011_BAUDRATE 115200
|
||||
#endif
|
||||
|
||||
#if !defined(PL011_CLK_IN_HZ)
|
||||
#define PL011_CLK_IN_HZ 24000000
|
||||
#endif
|
||||
|
||||
#if !defined(PL011_LINE_CONTROL)
|
||||
/* FIFO Enabled / No Parity / 8 Data bit / One Stop Bit */
|
||||
#define PL011_LINE_CONTROL (PL011_UARTLCR_H_FEN | PL011_UARTLCR_H_WLEN_8)
|
||||
@ -103,58 +95,4 @@
|
||||
#define PL011_UARTLCR_H_PEN (1 << 1) /* Parity Enable */
|
||||
#define PL011_UARTLCR_H_BRK (1 << 0) /* Send break */
|
||||
|
||||
/*******************************************************************************
|
||||
* Pl011 CPU interface accessors for writing registers
|
||||
******************************************************************************/
|
||||
|
||||
static inline void pl011_write_ibrd(unsigned long base, unsigned int val)
|
||||
{
|
||||
mmio_write_32(base + UARTIBRD, val);
|
||||
}
|
||||
|
||||
static inline void pl011_write_fbrd(unsigned long base, unsigned int val)
|
||||
{
|
||||
mmio_write_32(base + UARTFBRD, val);
|
||||
}
|
||||
|
||||
static inline void pl011_write_lcr_h(unsigned long base, unsigned int val)
|
||||
{
|
||||
mmio_write_32(base + UARTLCR_H, val);
|
||||
}
|
||||
|
||||
static inline void pl011_write_ecr(unsigned long base, unsigned int val)
|
||||
{
|
||||
mmio_write_32(base + UARTECR, val);
|
||||
}
|
||||
|
||||
static inline void pl011_write_cr(unsigned long base, unsigned int val)
|
||||
{
|
||||
mmio_write_32(base + UARTCR, val);
|
||||
}
|
||||
|
||||
static inline void pl011_write_dr(unsigned long base, unsigned int val)
|
||||
{
|
||||
mmio_write_32(base + UARTDR, val);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Pl011 CPU interface accessors for reading registers
|
||||
******************************************************************************/
|
||||
|
||||
static inline unsigned int pl011_read_fr(unsigned long base)
|
||||
{
|
||||
return mmio_read_32(base + UARTFR);
|
||||
}
|
||||
|
||||
static inline unsigned int pl011_read_dr(unsigned long base)
|
||||
{
|
||||
return mmio_read_32(base + UARTDR);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function prototypes
|
||||
******************************************************************************/
|
||||
|
||||
void pl011_setbaudrate(unsigned long base_addr, unsigned int baudrate);
|
||||
|
||||
#endif /* __PL011_H__ */
|
||||
|
@ -31,7 +31,8 @@
|
||||
#ifndef __CONSOLE_H__
|
||||
#define __CONSOLE_H__
|
||||
|
||||
void console_init(unsigned long base_addr);
|
||||
int console_init(unsigned long base_addr,
|
||||
unsigned int uart_clk, unsigned int baud_rate);
|
||||
int console_putc(int c);
|
||||
int console_getc(void);
|
||||
|
||||
|
@ -72,6 +72,8 @@ uint32_t plat_interrupt_type_to_line(uint32_t type,
|
||||
unsigned int platform_get_core_pos(unsigned long mpidr);
|
||||
unsigned long platform_get_stack(unsigned long mpidr);
|
||||
void plat_report_exception(unsigned long);
|
||||
void plat_crash_console_init(unsigned long base_addr);
|
||||
int plat_crash_console_putc(int c);
|
||||
|
||||
/*******************************************************************************
|
||||
* Mandatory BL1 functions
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <assert_macros.S>
|
||||
|
||||
.globl get_afflvl_shift
|
||||
.globl mpidr_mask_lower_afflvls
|
||||
@ -46,7 +47,6 @@
|
||||
.globl enable_vfp
|
||||
#endif
|
||||
|
||||
|
||||
func get_afflvl_shift
|
||||
cmp x0, #3
|
||||
cinc x0, x0, eq
|
||||
@ -79,6 +79,10 @@ func smc
|
||||
* -----------------------------------------------------------------------
|
||||
*/
|
||||
func zeromem16
|
||||
#if ASM_ASSERTION
|
||||
tst x0, #0xf
|
||||
ASM_ASSERT(eq)
|
||||
#endif
|
||||
add x2, x0, x1
|
||||
/* zero 16 bytes at a time */
|
||||
z_loop16:
|
||||
@ -105,6 +109,11 @@ z_end: ret
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
func memcpy16
|
||||
#if ASM_ASSERTION
|
||||
orr x3, x0, x1
|
||||
tst x3, #0xf
|
||||
ASM_ASSERT(eq)
|
||||
#endif
|
||||
/* copy 16 bytes at a time */
|
||||
m_loop16:
|
||||
cmp x2, #16
|
||||
@ -145,7 +154,6 @@ func disable_mmu_icache_el3
|
||||
mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT)
|
||||
b do_disable_mmu
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* Enable the use of VFP at EL3
|
||||
* ---------------------------------------------------------------------------
|
||||
|
@ -37,6 +37,8 @@
|
||||
.weak platform_is_primary_cpu
|
||||
.weak platform_check_mpidr
|
||||
.weak plat_report_exception
|
||||
.weak plat_crash_console_init
|
||||
.weak plat_crash_console_putc
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* int platform_get_core_pos(int mpidr);
|
||||
@ -79,3 +81,20 @@ func platform_check_mpidr
|
||||
*/
|
||||
func plat_report_exception
|
||||
ret
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Placeholder function which should be redefined by
|
||||
* each platform.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_init
|
||||
mov x0, #0
|
||||
ret
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Placeholder function which should be redefined by
|
||||
* each platform.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_putc
|
||||
ret
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <asm_macros.S>
|
||||
#include <bl_common.h>
|
||||
#include <gic_v2.h>
|
||||
#include <pl011.h>
|
||||
#include "../drivers/pwrc/fvp_pwrc.h"
|
||||
#include "../fvp_def.h"
|
||||
|
||||
@ -39,6 +40,8 @@
|
||||
.globl plat_secondary_cold_boot_setup
|
||||
.globl platform_mem_init
|
||||
.globl plat_report_exception
|
||||
.globl plat_crash_console_init
|
||||
.globl plat_crash_console_putc
|
||||
|
||||
.macro fvp_choose_gicmmap param1, param2, x_tmp, w_tmp, res
|
||||
ldr \x_tmp, =VE_SYSREGS_BASE + V2M_SYS_ID
|
||||
@ -187,3 +190,30 @@ func plat_report_exception
|
||||
add x1, x1, #V2M_SYS_LED
|
||||
str w0, [x1]
|
||||
ret
|
||||
|
||||
/* Define a crash console for the plaform */
|
||||
#define FVP_CRASH_CONSOLE_BASE PL011_UART0_BASE
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int plat_crash_console_init(void)
|
||||
* Function to initialize the crash console
|
||||
* without a C Runtime to print crash report.
|
||||
* Clobber list : x0, x1, x2
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_init
|
||||
mov_imm x0, FVP_CRASH_CONSOLE_BASE
|
||||
mov_imm x1, PL011_UART0_CLK_IN_HZ
|
||||
mov_imm x2, PL011_BAUDRATE
|
||||
b console_core_init
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int plat_crash_console_putc(void)
|
||||
* Function to print a character on the crash
|
||||
* console without a C Runtime.
|
||||
* Clobber list : x1, x2
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_putc
|
||||
mov_imm x1, FVP_CRASH_CONSOLE_BASE
|
||||
b console_core_putc
|
||||
|
@ -73,7 +73,7 @@ void bl1_early_platform_setup(void)
|
||||
const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
|
||||
|
||||
/* Initialize the console to provide early debug support */
|
||||
console_init(PL011_UART0_BASE);
|
||||
console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
|
||||
|
||||
/* Allow BL1 to see the whole Trusted RAM */
|
||||
bl1_tzram_layout.total_base = TZRAM_BASE;
|
||||
|
@ -168,7 +168,7 @@ struct entry_point_info *bl2_plat_get_bl31_ep_info(void)
|
||||
void bl2_early_platform_setup(meminfo_t *mem_layout)
|
||||
{
|
||||
/* Initialize the console to provide early debug support */
|
||||
console_init(PL011_UART0_BASE);
|
||||
console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
|
||||
|
||||
/* Setup the BL2 memory layout */
|
||||
bl2_tzram_layout = *mem_layout;
|
||||
|
@ -143,7 +143,7 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2,
|
||||
void *plat_params_from_bl2)
|
||||
{
|
||||
/* Initialize the console to provide early debug support */
|
||||
console_init(PL011_UART0_BASE);
|
||||
console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
|
||||
|
||||
/* Initialize the platform config for future decision making */
|
||||
fvp_config_setup();
|
||||
|
@ -72,7 +72,7 @@ void bl32_early_platform_setup(void)
|
||||
* Initialize a different console than already in use to display
|
||||
* messages from TSP
|
||||
*/
|
||||
console_init(PL011_UART1_BASE);
|
||||
console_init(PL011_UART1_BASE, PL011_UART1_CLK_IN_HZ, PL011_BAUDRATE);
|
||||
|
||||
/* Initialize the platform config for future decision making */
|
||||
fvp_config_setup();
|
||||
|
@ -198,6 +198,13 @@
|
||||
#define PL011_UART2_BASE 0x1c0b0000
|
||||
#define PL011_UART3_BASE 0x1c0c0000
|
||||
|
||||
#define PL011_BAUDRATE 115200
|
||||
|
||||
#define PL011_UART0_CLK_IN_HZ 24000000
|
||||
#define PL011_UART1_CLK_IN_HZ 24000000
|
||||
#define PL011_UART2_CLK_IN_HZ 24000000
|
||||
#define PL011_UART3_CLK_IN_HZ 24000000
|
||||
|
||||
/*******************************************************************************
|
||||
* TrustZone address space controller related constants
|
||||
******************************************************************************/
|
||||
|
@ -27,31 +27,79 @@
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cci400.h>
|
||||
#include <gic_v2.h>
|
||||
#include <plat_config.h>
|
||||
#include "platform_def.h"
|
||||
|
||||
.section .rodata.gic_reg_name, "aS"
|
||||
gic_regs: .asciz "gic_iar", "gic_ctlr", ""
|
||||
gic_regs:
|
||||
.asciz "gic_hppir", "gic_ahppir", "gic_ctlr", ""
|
||||
gicd_pend_reg:
|
||||
.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
|
||||
newline:
|
||||
.asciz "\n"
|
||||
spacer:
|
||||
.asciz ":\t\t0x"
|
||||
|
||||
/* Currently we have only 2 GIC registers to report */
|
||||
#define GIC_REG_SIZE (2 * 8)
|
||||
/* ---------------------------------------------
|
||||
* The below macro prints out relevant GIC
|
||||
* registers whenever an unhandled exception is
|
||||
* taken in BL31.
|
||||
* Clobbers: x0 - x10, x16, sp
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
.macro plat_print_gic_regs
|
||||
adr x0, plat_config;
|
||||
ldr w0, [x0, #CONFIG_GICC_BASE_OFFSET]
|
||||
/* gic base address is now in x0 */
|
||||
ldr w1, [x0, #GICC_IAR]
|
||||
ldr w2, [x0, #GICC_CTLR]
|
||||
sub sp, sp, #GIC_REG_SIZE
|
||||
stp x1, x2, [sp] /* we store the gic registers as 64 bit */
|
||||
adr x0, gic_regs
|
||||
mov x1, sp
|
||||
bl print_string_value
|
||||
add sp, sp, #GIC_REG_SIZE
|
||||
adr x0, plat_config
|
||||
ldr w16, [x0, #CONFIG_GICC_BASE_OFFSET]
|
||||
cbz x16, 1f
|
||||
/* gic base address is now in x16 */
|
||||
adr x6, gic_regs /* Load the gic reg list to x6 */
|
||||
/* Load the gic regs to gp regs used by str_in_crash_buf_print */
|
||||
ldr w8, [x16, #GICC_HPPIR]
|
||||
ldr w9, [x16, #GICC_AHPPIR]
|
||||
ldr w10, [x16, #GICC_CTLR]
|
||||
/* Store to the crash buf and print to cosole */
|
||||
bl str_in_crash_buf_print
|
||||
|
||||
/* Print the GICD_ISPENDR regs */
|
||||
add x7, x16, #GICD_ISPENDR
|
||||
adr x4, gicd_pend_reg
|
||||
bl asm_print_str
|
||||
2:
|
||||
sub x4, x7, x16
|
||||
cmp x4, #0x280
|
||||
b.eq 1f
|
||||
bl asm_print_hex
|
||||
adr x4, spacer
|
||||
bl asm_print_str
|
||||
ldr x4, [x7], #8
|
||||
bl asm_print_hex
|
||||
adr x4, newline
|
||||
bl asm_print_str
|
||||
b 2b
|
||||
1:
|
||||
.endm
|
||||
|
||||
.section .rodata.cci_reg_name, "aS"
|
||||
cci_iface_regs:
|
||||
.asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
|
||||
|
||||
/* ------------------------------------------------
|
||||
* The below macro prints out relevant interconnect
|
||||
* registers whenever an unhandled exception is
|
||||
* taken in BL31.
|
||||
* Clobbers: x0 - x9, sp
|
||||
* ------------------------------------------------
|
||||
*/
|
||||
.macro plat_print_interconnect_regs
|
||||
adr x6, cci_iface_regs
|
||||
/* Store in x7 the base address of the first interface */
|
||||
mov_imm x7, (CCI400_BASE + SLAVE_IFACE3_OFFSET)
|
||||
ldr w8, [x7, #SNOOP_CTRL_REG]
|
||||
/* Store in x7 the base address of the second interface */
|
||||
mov_imm x7, (CCI400_BASE + SLAVE_IFACE4_OFFSET)
|
||||
ldr w9, [x7, #SNOOP_CTRL_REG]
|
||||
/* Store to the crash buf and print to console */
|
||||
bl str_in_crash_buf_print
|
||||
.endm
|
||||
|
@ -45,8 +45,7 @@ $(eval $(call add_define,TSP_RAM_LOCATION_ID))
|
||||
|
||||
PLAT_INCLUDES := -Iplat/fvp/include/
|
||||
|
||||
PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/pl011.c \
|
||||
drivers/arm/pl011/pl011_console.c \
|
||||
PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/pl011_console.S \
|
||||
drivers/io/io_fip.c \
|
||||
drivers/io/io_memmap.c \
|
||||
drivers/io/io_semihosting.c \
|
||||
|
Loading…
Reference in New Issue
Block a user