blob: d1eb780ea6bb8c512427e98b6ede15f71561d184 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
2 * Copyright (c) 2018, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
8#include <platform.h>
9#include <spinlock.h>
10#include <stdarg.h>
11#include <stdio.h>
12
13/* Lock to avoid concurrent accesses to the serial console */
14static spinlock_t printf_lock;
15
16/*
17 * Print the MPID header, e.g.: [cpu 0x0100]
18 *
19 * If SHELL_COLOR == 1, this also prints shell's color escape sequences to ease
20 * identifying which CPU displays the message. There are 8 standard colors so
21 * if the platform has more than 8 CPUs, some colors will be reused.
22 */
23#if SHELL_COLOR
24#define PRINT_MPID_HDR(_mpid) \
25 do { \
26 unsigned int linear_id = platform_get_core_pos(_mpid); \
27 printf("\033[1;%u;40m", 30 + (linear_id & 0x7)); \
28 printf("[cpu 0x%.4x] ", _mpid); \
29 printf("\033[0m"); \
30 } while (0)
31#else
32#define PRINT_MPID_HDR(_mpid) \
33 printf("[cpu 0x%.4x] ", _mpid)
34#endif /* SHELL_COLOR */
35
36void mp_printf(const char *fmt, ...)
37{
38 va_list ap;
39 char str[256];
40 /*
41 * As part of testing Firmware Update feature on Cortex-A57 CPU, an
42 * issue was discovered while printing in NS_BL1U stage. The issue
43 * appears when the second call to `NOTICE()` is made in the
44 * `ns_bl1u_main()`. As a result of this issue the CPU hangs and the
45 * debugger is also not able to connect anymore.
46 *
47 * After further debugging and experiments it was found that if
48 * `read_mpidr_el1()` is avoided or volatile qualifier is used for
49 * reading the mpidr, this issue gets resolved.
50 *
51 * NOTE: The actual/real reason why this happens is still not known.
52 * Moreover this problem is not encountered on Cortex-A53 CPU.
53 */
54 volatile unsigned int mpid = read_mpidr_el1() & 0xFFFF;
55
56 /*
57 * TODO: It would be simpler to use vprintf() instead of
58 * vsnprintf() + printf(), we wouldn't need to declare a static buffer
59 * for storing the product of vsnprintf(). Unfortunately our C library
60 * doesn't provide vprintf() at the moment.
61 * Import vprintf() code from FreeBSD C library to our local C library.
62 */
63 va_start(ap, fmt);
64 vsnprintf(str, sizeof(str), fmt, ap);
65 str[sizeof(str) - 1] = 0;
66 va_end(ap);
67
68 spin_lock(&printf_lock);
69 PRINT_MPID_HDR(mpid);
70 printf("%s", str);
71 spin_unlock(&printf_lock);
72}