diff options
-rw-r--r-- | arch/arm/mach-mvebu/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/spl.c | 12 | ||||
-rw-r--r-- | arch/sandbox/cpu/os.c | 59 | ||||
-rw-r--r-- | arch/sandbox/cpu/start.c | 16 | ||||
-rw-r--r-- | arch/sandbox/include/asm/global_data.h | 1 | ||||
-rw-r--r-- | board/sandbox/README.sandbox | 46 | ||||
-rw-r--r-- | cmd/Kconfig | 13 | ||||
-rw-r--r-- | common/board_f.c | 2 | ||||
-rw-r--r-- | common/bootstage.c | 7 | ||||
-rw-r--r-- | common/command.c | 14 | ||||
-rw-r--r-- | common/image-fdt.c | 33 | ||||
-rw-r--r-- | configs/sandbox_defconfig | 2 | ||||
-rw-r--r-- | drivers/core/Kconfig | 9 | ||||
-rw-r--r-- | drivers/core/fdtaddr.c | 9 | ||||
-rw-r--r-- | drivers/core/root.c | 21 | ||||
-rw-r--r-- | drivers/core/simple-bus.c | 1 | ||||
-rw-r--r-- | include/asm-generic/global_data.h | 4 | ||||
-rw-r--r-- | include/configs/sandbox.h | 4 | ||||
-rw-r--r-- | include/div64.h | 70 | ||||
-rw-r--r-- | include/dm/fdtaddr.h | 21 | ||||
-rw-r--r-- | include/fdtdec.h | 5 | ||||
-rw-r--r-- | include/initcall.h | 19 | ||||
-rw-r--r-- | include/os.h | 11 | ||||
-rw-r--r-- | include/pci.h | 1 | ||||
-rw-r--r-- | lib/Kconfig | 57 | ||||
-rw-r--r-- | lib/div64.c | 20 | ||||
-rw-r--r-- | lib/fdtdec.c | 7 | ||||
-rw-r--r-- | lib/trace.c | 17 | ||||
-rw-r--r-- | scripts/config_whitelist.txt | 5 |
29 files changed, 335 insertions, 152 deletions
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index f5fd60d..f99bd3b 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -14,6 +14,7 @@ config ARMADA_32BIT select SPL_OF_CONTROL if SPL select SPL_SIMPLE_BUS if SPL select SUPPORT_SPL + select TRANSLATION_OFFSET config ARMADA_64BIT bool diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c index 9dd7c84..530b98c1 100644 --- a/arch/arm/mach-mvebu/spl.c +++ b/arch/arm/mach-mvebu/spl.c @@ -93,15 +93,21 @@ void board_init_f(ulong dummy) */ #endif + /* + * Use special translation offset for SPL. This needs to be + * configured *before* spl_init() is called as this function + * calls dm_init() which calls the bind functions of the + * device drivers. Here the base address needs to be configured + * (translated) correctly. + */ + gd->translation_offset = 0xd0000000 - 0xf1000000; + ret = spl_init(); if (ret) { debug("spl_init() failed: %d\n", ret); hang(); } - /* Use special translation offset for SPL */ - dm_set_translation_offset(0xd0000000 - 0xf1000000); - preloader_console_init(); timer_init(); diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index a8d01e4..47dfb47 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -209,8 +209,8 @@ void os_tty_raw(int fd, bool allow_sigs) void *os_malloc(size_t length) { - struct os_mem_hdr *hdr; int page_size = getpagesize(); + struct os_mem_hdr *hdr; /* * Use an address that is hopefully available to us so that pointers @@ -229,30 +229,34 @@ void *os_malloc(size_t length) void os_free(void *ptr) { - struct os_mem_hdr *hdr = ptr; + int page_size = getpagesize(); + struct os_mem_hdr *hdr; - hdr--; - if (ptr) - munmap(hdr, hdr->length + sizeof(*hdr)); + if (ptr) { + hdr = ptr - page_size; + munmap(hdr, hdr->length + page_size); + } } void *os_realloc(void *ptr, size_t length) { - struct os_mem_hdr *hdr = ptr; + int page_size = getpagesize(); + struct os_mem_hdr *hdr; void *buf = NULL; - hdr--; - if (length != 0) { + if (length) { buf = os_malloc(length); if (!buf) return buf; if (ptr) { + hdr = ptr - page_size; if (length > hdr->length) length = hdr->length; memcpy(buf, ptr, length); } } - os_free(ptr); + if (ptr) + os_free(ptr); return buf; } @@ -786,3 +790,40 @@ int os_mprotect_allow(void *start, size_t len) return mprotect(start, len, PROT_READ | PROT_WRITE); } + +void *os_find_text_base(void) +{ + char line[500]; + void *base = NULL; + int len; + int fd; + + /* + * This code assumes that the first line of /proc/self/maps holds + * information about the text, for example: + * + * 5622d9907000-5622d9a55000 r-xp 00000000 08:01 15067168 u-boot + * + * The first hex value is assumed to be the address. + * + * This is tested in Linux 4.15. + */ + fd = open("/proc/self/maps", O_RDONLY); + if (fd == -1) + return NULL; + len = read(fd, line, sizeof(line)); + if (len > 0) { + char *end = memchr(line, '-', len); + + if (end) { + unsigned long long addr; + + *end = '\0'; + if (sscanf(line, "%llx", &addr) == 1) + base = (void *)addr; + } + } + close(fd); + + return base; +} diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 2f5e6e9..82828f0 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -303,10 +303,8 @@ int board_run_command(const char *cmdline) static void setup_ram_buf(struct sandbox_state *state) { /* Zero the RAM buffer if we didn't read it, to keep valgrind happy */ - if (!state->ram_buf_read) { + if (!state->ram_buf_read) memset(state->ram_buf, '\0', state->ram_size); - printf("clear %p %x\n", state->ram_buf, state->ram_size); - } gd->arch.ram_buf = state->ram_buf; gd->ram_size = state->ram_size; @@ -328,6 +326,10 @@ int main(int argc, char *argv[]) gd_t data; int ret; + memset(&data, '\0', sizeof(data)); + gd = &data; + gd->arch.text_base = os_find_text_base(); + ret = state_init(); if (ret) goto err; @@ -340,8 +342,6 @@ int main(int argc, char *argv[]) if (ret) goto err; - memset(&data, '\0', sizeof(data)); - gd = &data; #if CONFIG_VAL(SYS_MALLOC_F_LEN) gd->malloc_base = CONFIG_MALLOC_F_ADDR; #endif @@ -350,6 +350,12 @@ int main(int argc, char *argv[]) #endif setup_ram_buf(state); + /* + * Set up the relocation offset here, since sandbox symbols are always + * relocated by the OS before sandbox is entered. + */ + gd->reloc_off = (ulong)gd->arch.text_base; + /* Do pre- and post-relocation init */ board_init_f(0); diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h index f6a6a34..f4ce72d 100644 --- a/arch/sandbox/include/asm/global_data.h +++ b/arch/sandbox/include/asm/global_data.h @@ -12,6 +12,7 @@ /* Architecture-specific global data */ struct arch_global_data { uint8_t *ram_buf; /* emulated RAM buffer */ + void *text_base; /* pointer to base of text region */ }; #include <asm-generic/global_data.h> diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox index 9b09404..48c1e2b 100644 --- a/board/sandbox/README.sandbox +++ b/board/sandbox/README.sandbox @@ -392,6 +392,49 @@ state_setprop() which does this automatically and avoids running out of space. See existing code for examples. +Debugging the init sequence +--------------------------- + +If you get a failure in the initcall sequence, like this: + + initcall sequence 0000560775957c80 failed at call 0000000000048134 (err=-96) + +Then you use can use grep to see which init call failed, e.g.: + + $ grep 0000000000048134 u-boot.map + stdio_add_devices + +Of course another option is to run it with a debugger such as gdb: + + $ gdb u-boot + ... + (gdb) br initcall.h:41 + Breakpoint 1 at 0x4db9d: initcall.h:41. (2 locations) + +Note that two locations are reported, since this function is used in both +board_init_f() and board_init_r(). + + (gdb) r + Starting program: /tmp/b/sandbox/u-boot + [Thread debugging using libthread_db enabled] + Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". + + U-Boot 2018.09-00264-ge0c2ba9814-dirty (Sep 22 2018 - 12:21:46 -0600) + + DRAM: 128 MiB + MMC: + + Breakpoint 1, initcall_run_list (init_sequence=0x5555559619e0 <init_sequence_f>) + at /scratch/sglass/cosarm/src/third_party/u-boot/files/include/initcall.h:41 + 41 printf("initcall sequence %p failed at call %p (err=%d)\n", + (gdb) print *init_fnc_ptr + $1 = (const init_fnc_t) 0x55555559c114 <stdio_add_devices> + (gdb) + + +This approach can be used on normal boards as well as sandbox. + + Testing ------- @@ -434,6 +477,9 @@ that are mapped into that memory: 0 CONFIG_SYS_FDT_LOAD_ADDR Device tree e000 CONFIG_BLOBLIST_ADDR Blob list 10000 CONFIG_MALLOC_F_ADDR Early memory allocation + f0000 CONFIG_PRE_CON_BUF_ADDR Pre-console buffer + 100000 CONFIG_TRACE_EARLY_ADDR Early trace buffer (if enabled) += -- diff --git a/cmd/Kconfig b/cmd/Kconfig index 5d1999e..67d23ca 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -53,6 +53,17 @@ config SYS_PROMPT This string is displayed in the command line to the left of the cursor. +config SYS_XTRACE + string "Command execution tracer" + depends on CMDLINE + default y if CMDLINE + help + This option enables the possiblity to print all commands before + executing them and after all variables are evaluated (similar + to Bash's xtrace/'set -x' feature). + To enable the tracer a variable "xtrace" needs to be defined in + the environment. + menu "Autoboot options" config AUTOBOOT @@ -1900,7 +1911,7 @@ config CMD_TRACE Enables a command to control using of function tracing within U-Boot. This allows recording of call traces including timing information. The command can write data to memory for exporting - for analsys (e.g. using bootchart). See doc/README.trace for full + for analysis (e.g. using bootchart). See doc/README.trace for full details. config CMD_AVB diff --git a/common/board_f.c b/common/board_f.c index 149a722..7ef20f2 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -714,7 +714,7 @@ static int setup_reloc(void) * just after the default vector table location, so at 0x400 */ gd->reloc_off = gd->relocaddr - (CONFIG_SYS_TEXT_BASE + 0x400); -#else +#elif !defined(CONFIG_SANDBOX) gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE; #endif #endif diff --git a/common/bootstage.c b/common/bootstage.c index 9793b85..56ef91a 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -99,6 +99,13 @@ ulong bootstage_add_record(enum bootstage_id id, const char *name, struct bootstage_data *data = gd->bootstage; struct bootstage_record *rec; + /* + * initf_bootstage() is called very early during boot but since hang() + * calls bootstage_error() we can be called before bootstage is set up. + * Add a check to avoid this. + */ + if (!data) + return mark; if (flags & BOOTSTAGEF_ALLOC) id = data->next_id++; diff --git a/common/command.c b/common/command.c index e14d1fa..e192bb2 100644 --- a/common/command.c +++ b/common/command.c @@ -574,6 +574,20 @@ enum command_ret_t cmd_process(int flag, int argc, char * const argv[], enum command_ret_t rc = CMD_RET_SUCCESS; cmd_tbl_t *cmdtp; +#if defined(CONFIG_SYS_XTRACE) + char *xtrace; + + xtrace = env_get("xtrace"); + if (xtrace) { + puts("+"); + for (int i = 0; i < argc; i++) { + puts(" "); + puts(argv[i]); + } + puts("\n"); + } +#endif + /* Look up command in command table */ cmdtp = find_cmd(argv[0]); if (cmdtp == NULL) { diff --git a/common/image-fdt.c b/common/image-fdt.c index 9ed00b7..eb552ca 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -279,7 +279,6 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, int fdt_noffset; #endif const char *select = NULL; - int ok_no_fdt = 0; *of_flat_tree = NULL; *of_size = 0; @@ -462,17 +461,24 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, struct andr_img_hdr *hdr = buf; ulong fdt_data, fdt_len; - if (android_image_get_second(hdr, &fdt_data, &fdt_len) != 0) - goto no_fdt; + if (!android_image_get_second(hdr, &fdt_data, &fdt_len) && + !fdt_check_header((char *)fdt_data)) { + fdt_blob = (char *)fdt_data; + if (fdt_totalsize(fdt_blob) != fdt_len) + goto error; - fdt_blob = (char *)fdt_data; - if (fdt_check_header(fdt_blob) != 0) - goto no_fdt; + debug("## Using FDT in Android image second area\n"); + } else { + fdt_addr = env_get_hex("fdtaddr", 0); + if (!fdt_addr) + goto no_fdt; - if (fdt_totalsize(fdt_blob) != fdt_len) - goto error; + fdt_blob = map_sysmem(fdt_addr, 0); + if (fdt_check_header(fdt_blob)) + goto no_fdt; - debug("## Using FDT found in Android image second area\n"); + debug("## Using FDT at ${fdtaddr}=Ox%lx\n", fdt_addr); + } #endif } else { debug("## No Flattened Device Tree\n"); @@ -487,14 +493,9 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, return 0; no_fdt: - ok_no_fdt = 1; + debug("Continuing to boot without FDT\n"); + return 0; error: - *of_flat_tree = NULL; - *of_size = 0; - if (!select && ok_no_fdt) { - debug("Continuing to boot without FDT\n"); - return 0; - } return 1; } diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index bb508a8..ba28db6 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -16,7 +16,7 @@ CONFIG_CONSOLE_RECORD=y CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000 CONFIG_SILENT_CONSOLE=y CONFIG_PRE_CONSOLE_BUFFER=y -CONFIG_PRE_CON_BUF_ADDR=0x100000 +CONFIG_PRE_CON_BUF_ADDR=0xf0000 CONFIG_LOG_MAX_LEVEL=6 CONFIG_LOG_ERROR_RETURN=y CONFIG_DISPLAY_BOARDINFO_LATE=y diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index ddf2fb3..2d195ae 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -225,6 +225,15 @@ config SPL_OF_TRANSLATE used for the address translation. This function is faster and smaller in size than fdt_translate_address(). +config TRANSLATION_OFFSET + bool "Platforms specific translation offset" + depends on DM && OF_CONTROL + help + Some platforms need a special address translation. Those + platforms (e.g. mvebu in SPL) can configure a translation + offset by enabling this option and setting the translation_offset + variable in the GD in their platform- / board-specific code. + config OF_ISA_BUS bool depends on OF_TRANSLATE diff --git a/drivers/core/fdtaddr.c b/drivers/core/fdtaddr.c index e113f1d..c287386 100644 --- a/drivers/core/fdtaddr.c +++ b/drivers/core/fdtaddr.c @@ -74,13 +74,16 @@ fdt_addr_t devfdt_get_addr_index(struct udevice *dev, int index) } } +#if defined(CONFIG_TRANSLATION_OFFSET) /* * Some platforms need a special address translation. Those * platforms (e.g. mvebu in SPL) can configure a translation - * offset in the DM by calling dm_set_translation_offset() that - * will get added to all addresses returned by devfdt_get_addr(). + * offset by setting this value in the GD and enaling this + * feature via CONFIG_TRANSLATION_OFFSET. This value will + * get added to all addresses returned by devfdt_get_addr(). */ - addr += dm_get_translation_offset(); + addr += gd->translation_offset; +#endif return addr; #else diff --git a/drivers/core/root.c b/drivers/core/root.c index e6ec7fa..8fa0966 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -25,10 +25,6 @@ DECLARE_GLOBAL_DATA_PTR; -struct root_priv { - fdt_addr_t translation_offset; /* optional translation offset */ -}; - static const struct driver_info root_info = { .name = "root_driver", }; @@ -52,22 +48,6 @@ void dm_fixup_for_gd_move(struct global_data *new_gd) } } -fdt_addr_t dm_get_translation_offset(void) -{ - struct udevice *root = dm_root(); - struct root_priv *priv = dev_get_priv(root); - - return priv->translation_offset; -} - -void dm_set_translation_offset(fdt_addr_t offs) -{ - struct udevice *root = dm_root(); - struct root_priv *priv = dev_get_priv(root); - - priv->translation_offset = offs; -} - #if defined(CONFIG_NEEDS_MANUAL_RELOC) void fix_drivers(void) { @@ -420,7 +400,6 @@ int dm_init_and_scan(bool pre_reloc_only) U_BOOT_DRIVER(root_driver) = { .name = "root_driver", .id = UCLASS_ROOT, - .priv_auto_alloc_size = sizeof(struct root_priv), }; /* This is the root uclass */ diff --git a/drivers/core/simple-bus.c b/drivers/core/simple-bus.c index e16d8a9..7fc23ef 100644 --- a/drivers/core/simple-bus.c +++ b/drivers/core/simple-bus.c @@ -60,4 +60,5 @@ U_BOOT_DRIVER(simple_bus_drv) = { .name = "generic_simple_bus", .id = UCLASS_SIMPLE_BUS, .of_match = generic_simple_bus_ids, + .flags = DM_FLAG_PRE_RELOC, }; diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 78dcf40..65ee3e5 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -20,6 +20,7 @@ */ #ifndef __ASSEMBLY__ +#include <fdtdec.h> #include <membuff.h> #include <linux/list.h> @@ -133,6 +134,9 @@ typedef struct global_data { struct spl_handoff *spl_handoff; # endif #endif +#if defined(CONFIG_TRANSLATION_OFFSET) + fdt_addr_t translation_offset; /* optional translation offset */ +#endif } gd_t; #endif diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index e36a5fe..bf03bae 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -8,11 +8,11 @@ #ifdef FTRACE #define CONFIG_TRACE +#define CONFIG_CMD_TRACE #define CONFIG_TRACE_BUFFER_SIZE (16 << 20) -#define CONFIG_TRACE_EARLY_SIZE (8 << 20) +#define CONFIG_TRACE_EARLY_SIZE (16 << 20) #define CONFIG_TRACE_EARLY #define CONFIG_TRACE_EARLY_ADDR 0x00100000 - #endif #ifndef CONFIG_SPL_BUILD diff --git a/include/div64.h b/include/div64.h index 76563ef..8b92d2b 100644 --- a/include/div64.h +++ b/include/div64.h @@ -9,11 +9,11 @@ * * The semantics of do_div() are: * - * uint32_t do_div(uint64_t *n, uint32_t base) + * u32 do_div(u64 *n, u32 base) * { - * uint32_t remainder = *n % base; - * *n = *n / base; - * return remainder; + * u32 remainder = *n % base; + * *n = *n / base; + * return remainder; * } * * NOTE: macro parameter n is evaluated multiple times, @@ -26,10 +26,10 @@ #if BITS_PER_LONG == 64 # define do_div(n,base) ({ \ - uint32_t __base = (base); \ - uint32_t __rem; \ - __rem = ((uint64_t)(n)) % __base; \ - (n) = ((uint64_t)(n)) / __base; \ + u32 __base = (base); \ + u32 __rem; \ + __rem = ((u64)(n)) % __base; \ + (n) = ((u64)(n)) / __base; \ __rem; \ }) @@ -62,8 +62,8 @@ * Hence this monstrous macro (static inline doesn't always \ * do the trick here). \ */ \ - uint64_t ___res, ___x, ___t, ___m, ___n = (n); \ - uint32_t ___p, ___bias; \ + u64 ___res, ___x, ___t, ___m, ___n = (n); \ + u32 ___p, ___bias; \ \ /* determine MSB of b */ \ ___p = 1 << ilog2(___b); \ @@ -110,7 +110,7 @@ * possible, otherwise that'll need extra overflow \ * handling later. \ */ \ - uint32_t ___bits = -(___m & -___m); \ + u32 ___bits = -(___m & -___m); \ ___bits |= ___m >> 32; \ ___bits = (~___bits) << 1; \ /* \ @@ -150,61 +150,61 @@ /* * Default C implementation for __arch_xprod_64() * - * Prototype: uint64_t __arch_xprod_64(const uint64_t m, uint64_t n, bool bias) + * Prototype: u64 __arch_xprod_64(const u64 m, u64 n, bool bias) * Semantic: retval = ((bias ? m : 0) + m * n) >> 64 * * The product is a 128-bit value, scaled down to 64 bits. * Assuming constant propagation to optimize away unused conditional code. * Architectures may provide their own optimized assembly implementation. */ -static inline uint64_t __arch_xprod_64(const uint64_t m, uint64_t n, bool bias) +static inline u64 __arch_xprod_64(const u64 m, u64 n, bool bias) { - uint32_t m_lo = m; - uint32_t m_hi = m >> 32; - uint32_t n_lo = n; - uint32_t n_hi = n >> 32; - uint64_t res, tmp; + u32 m_lo = m; + u32 m_hi = m >> 32; + u32 n_lo = n; + u32 n_hi = n >> 32; + u64 res, tmp; if (!bias) { - res = ((uint64_t)m_lo * n_lo) >> 32; + res = ((u64)m_lo * n_lo) >> 32; } else if (!(m & ((1ULL << 63) | (1ULL << 31)))) { /* there can't be any overflow here */ - res = (m + (uint64_t)m_lo * n_lo) >> 32; + res = (m + (u64)m_lo * n_lo) >> 32; } else { - res = m + (uint64_t)m_lo * n_lo; + res = m + (u64)m_lo * n_lo; tmp = (res < m) ? (1ULL << 32) : 0; res = (res >> 32) + tmp; } if (!(m & ((1ULL << 63) | (1ULL << 31)))) { /* there can't be any overflow here */ - res += (uint64_t)m_lo * n_hi; - res += (uint64_t)m_hi * n_lo; + res += (u64)m_lo * n_hi; + res += (u64)m_hi * n_lo; res >>= 32; } else { - tmp = res += (uint64_t)m_lo * n_hi; - res += (uint64_t)m_hi * n_lo; + tmp = res += (u64)m_lo * n_hi; + res += (u64)m_hi * n_lo; tmp = (res < tmp) ? (1ULL << 32) : 0; res = (res >> 32) + tmp; } - res += (uint64_t)m_hi * n_hi; + res += (u64)m_hi * n_hi; return res; } #endif #ifndef __div64_32 -extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor); +extern u32 __div64_32(u64 *dividend, u32 divisor); #endif /* The unnecessary pointer compare is there * to check for type safety (n must be 64bit) */ # define do_div(n,base) ({ \ - uint32_t __base = (base); \ - uint32_t __rem; \ - (void)(((typeof((n)) *)0) == ((uint64_t *)0)); \ + u32 __base = (base); \ + u32 __rem; \ + (void)(((typeof((n)) *)0) == ((u64 *)0)); \ if (__builtin_constant_p(__base) && \ is_power_of_2(__base)) { \ __rem = (n) & (__base - 1); \ @@ -212,14 +212,14 @@ extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor); } else if (__div64_const32_is_OK && \ __builtin_constant_p(__base) && \ __base != 0) { \ - uint32_t __res_lo, __n_lo = (n); \ + u32 __res_lo, __n_lo = (n); \ (n) = __div64_const32(n, __base); \ /* the remainder can be computed with 32-bit regs */ \ __res_lo = (n); \ __rem = __n_lo - __res_lo * __base; \ } else if (likely(((n) >> 32) == 0)) { \ - __rem = (uint32_t)(n) % __base; \ - (n) = (uint32_t)(n) / __base; \ + __rem = (u32)(n) % __base; \ + (n) = (u32)(n) / __base; \ } else \ __rem = __div64_32(&(n), __base); \ __rem; \ @@ -234,9 +234,9 @@ extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor); /* Wrapper for do_div(). Doesn't modify dividend and returns * the result, not remainder. */ -static inline uint64_t lldiv(uint64_t dividend, uint32_t divisor) +static inline u64 lldiv(u64 dividend, u32 divisor) { - uint64_t __res = dividend; + u64 __res = dividend; do_div(__res, divisor); return(__res); } diff --git a/include/dm/fdtaddr.h b/include/dm/fdtaddr.h index c171d9b..3bc2599 100644 --- a/include/dm/fdtaddr.h +++ b/include/dm/fdtaddr.h @@ -120,25 +120,4 @@ fdt_addr_t devfdt_get_addr_size_index(struct udevice *dev, int index, */ fdt_addr_t devfdt_get_addr_name(struct udevice *dev, const char *name); -/** - * dm_set_translation_offset() - Set translation offset - * @offs: Translation offset - * - * Some platforms need a special address translation. Those - * platforms (e.g. mvebu in SPL) can configure a translation - * offset in the DM by calling this function. It will be - * added to all addresses returned in devfdt_get_addr(). - */ -void dm_set_translation_offset(fdt_addr_t offs); - -/** - * dm_get_translation_offset() - Get translation offset - * - * This function returns the translation offset that can - * be configured by calling dm_set_translation_offset(). - * - * @return translation offset for the device address (0 as default). - */ -fdt_addr_t dm_get_translation_offset(void); - #endif diff --git a/include/fdtdec.h b/include/fdtdec.h index 266c582..110aa6a 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -1029,7 +1029,10 @@ int fdtdec_setup_memory_banksize(void); * @param phandle phandle to set for the given node * @return 0 on success or a negative error code on failure */ -int fdtdec_set_phandle(void *blob, int node, uint32_t phandle); +static inline int fdtdec_set_phandle(void *blob, int node, uint32_t phandle) +{ + return fdt_setprop_u32(blob, node, "phandle", phandle); +} /** * fdtdec_add_reserved_memory() - add or find a reserved-memory node diff --git a/include/initcall.h b/include/initcall.h index 3ac01aa..78d15af 100644 --- a/include/initcall.h +++ b/include/initcall.h @@ -8,12 +8,11 @@ typedef int (*init_fnc_t)(void); -#include <common.h> -#include <initcall.h> -#include <efi.h> - -DECLARE_GLOBAL_DATA_PTR; - +/* + * To enable debugging. add #define DEBUG at the top of the including file. + * + * To find a symbol, use grep on u-boot.map + */ static inline int initcall_run_list(const init_fnc_t init_sequence[]) { const init_fnc_t *init_fnc_ptr; @@ -22,13 +21,17 @@ static inline int initcall_run_list(const init_fnc_t init_sequence[]) unsigned long reloc_ofs = 0; int ret; - if (gd->flags & GD_FLG_RELOC) + /* + * Sandbox is relocated by the OS, so symbols always appear at + * the relocated address. + */ + if (IS_ENABLED(CONFIG_SANDBOX) || (gd->flags & GD_FLG_RELOC)) reloc_ofs = gd->reloc_off; #ifdef CONFIG_EFI_APP reloc_ofs = (unsigned long)image_base; #endif debug("initcall: %p", (char *)*init_fnc_ptr - reloc_ofs); - if (gd->flags & GD_FLG_RELOC) + if (reloc_ofs) debug(" (relocated to %p)\n", (char *)*init_fnc_ptr); else debug("\n"); diff --git a/include/os.h b/include/os.h index 6f33b08..7a4f78b 100644 --- a/include/os.h +++ b/include/os.h @@ -364,4 +364,15 @@ int os_write_file(const char *name, const void *buf, int size); */ int os_read_file(const char *name, void **bufp, int *sizep); +/* + * os_find_text_base() - Find the text section in this running process + * + * This tries to find the address of the text section in this running process. + * It can be useful to map the address of functions to the address listed in + * the u-boot.map file. + * + * @return address if found, else NULL + */ +void *os_find_text_base(void); + #endif diff --git a/include/pci.h b/include/pci.h index 9668503..066238a 100644 --- a/include/pci.h +++ b/include/pci.h @@ -405,6 +405,7 @@ #define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */ #define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */ #define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */ +#define PCI_MSI_FLAGS_MASKBIT 0x0100 /* Per-vector masking capable */ #define PCI_MSI_RFU 3 /* Rest of capability flags */ #define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */ #define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */ diff --git a/lib/Kconfig b/lib/Kconfig index 2120216..05f82d4 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -165,6 +165,63 @@ config RBTREE config BITREVERSE bool "Bit reverse library from Linux" +config TRACE + bool "Support for tracing of function calls and timing" + imply CMD_TRACE + help + Enables function tracing within U-Boot. This allows recording of call + traces including timing information. The command can write data to + memory for exporting for analysis (e.g. using bootchart). + See doc/README.trace for full details. + +config TRACE_BUFFER_SIZE + hex "Size of trace buffer in U-Boot" + depends on TRACE + default 0x01000000 + help + Sets the size of the trace buffer in U-Boot. This is allocated from + memory during relocation. If this buffer is too small, the trace + history will be truncated, with later records omitted. + + If early trace is enabled (i.e. before relocation), this buffer must + be large enough to include all the data from the early trace buffer as + well, since this is copied over to the main buffer during relocation. + + A trace record is emitted for each function call and each record is + 12 bytes (see struct trace_call). A suggested minimum size is 1MB. If + the size is too small then 'trace stats' will show a message saying + how many records were dropped due to buffer overflow. + +config TRACE_EARLY + bool "Enable tracing before relocation" + depends on TRACE + help + Sometimes it is helpful to trace execution of U-Boot before + relocation. This is possible by using a arch-specific, fixed buffer + position in memory. Enable this option to start tracing as early as + possible after U-Boot starts. + +config TRACE_EARLY_SIZE + hex "Size of early trace buffer in U-Boot" + depends on TRACE_EARLY + default 0x00100000 + help + Sets the size of the early trace buffer in bytes. This is used to hold + tracing information before relocation. + +config TRACE_EARLY_ADDR + hex "Address of early trace buffer in U-Boot" + depends on TRACE_EARLY + default 0x00100000 + help + Sets the address of the early trace buffer in U-Boot. This memory + must be accessible before relocation. + + A trace record is emitted for each function call and each record is + 12 bytes (see struct trace_call). A suggested minimum size is 1MB. If + the size is too small then the message which says the amount of early + data being coped will the the same as the + source lib/dhry/Kconfig menu "Security support" diff --git a/lib/div64.c b/lib/div64.c index 206f582..62933c9 100644 --- a/lib/div64.c +++ b/lib/div64.c @@ -25,19 +25,25 @@ #if BITS_PER_LONG == 32 #ifndef __div64_32 -uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base) +/* + * Don't instrument this function as it may be called from tracing code, since + * it needs to read the timer and this often requires calling do_div(), which + * calls this function. + */ +uint32_t __attribute__((weak, no_instrument_function)) __div64_32(u64 *n, + u32 base) { - uint64_t rem = *n; - uint64_t b = base; - uint64_t res, d = 1; - uint32_t high = rem >> 32; + u64 rem = *n; + u64 b = base; + u64 res, d = 1; + u32 high = rem >> 32; /* Reduce the thing a bit first */ res = 0; if (high >= base) { high /= base; - res = (uint64_t) high << 32; - rem -= (uint64_t) (high*base) << 32; + res = (u64)high << 32; + rem -= (u64)(high * base) << 32; } while ((int64_t)b > 0 && b < rem) { diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 9c9c302..fea44a9 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1261,13 +1261,6 @@ __weak void *board_fdt_blob_setup(void) } #endif -int fdtdec_set_phandle(void *blob, int node, uint32_t phandle) -{ - fdt32_t value = cpu_to_fdt32(phandle); - - return fdt_setprop(blob, node, "phandle", &value, sizeof(value)); -} - static int fdtdec_init_reserved_memory(void *blob) { int na, ns, node, err; diff --git a/lib/trace.c b/lib/trace.c index bb089c2..9956442 100644 --- a/lib/trace.c +++ b/lib/trace.c @@ -183,7 +183,8 @@ int trace_list_functions(void *buff, int buff_size, unsigned int *needed) /* Work out how must of the buffer we used */ *needed = ptr - buff; if (ptr > end) - return -1; + return -ENOSPC; + return 0; } @@ -227,7 +228,8 @@ int trace_list_calls(void *buff, int buff_size, unsigned *needed) /* Work out how must of the buffer we used */ *needed = ptr - buff; if (ptr > end) - return -1; + return -ENOSPC; + return 0; } @@ -294,7 +296,8 @@ int __attribute__((no_instrument_function)) trace_init(void *buff, trace_enabled = 0; hdr = map_sysmem(CONFIG_TRACE_EARLY_ADDR, CONFIG_TRACE_EARLY_SIZE); - end = (char *)&hdr->ftrace[hdr->ftrace_count]; + end = (char *)&hdr->ftrace[min(hdr->ftrace_count, + hdr->ftrace_size)]; used = end - (char *)hdr; printf("trace: copying %08lx bytes of early data from %x to %08lx\n", used, CONFIG_TRACE_EARLY_ADDR, @@ -302,7 +305,7 @@ int __attribute__((no_instrument_function)) trace_init(void *buff, memcpy(buff, hdr, used); #else puts("trace: already enabled\n"); - return -1; + return -EALREADY; #endif } hdr = (struct trace_hdr *)buff; @@ -310,7 +313,7 @@ int __attribute__((no_instrument_function)) trace_init(void *buff, if (needed > buff_size) { printf("trace: buffer size %zd bytes: at least %zd needed\n", buff_size, needed); - return -1; + return -ENOSPC; } if (was_disabled) @@ -327,6 +330,7 @@ int __attribute__((no_instrument_function)) trace_init(void *buff, hdr->depth_limit = 15; trace_enabled = 1; trace_inited = 1; + return 0; } @@ -346,7 +350,7 @@ int __attribute__((no_instrument_function)) trace_early_init(void) if (needed > buff_size) { printf("trace: buffer size is %zd bytes, at least %zd needed\n", buff_size, needed); - return -1; + return -ENOSPC; } memset(hdr, '\0', needed); @@ -361,6 +365,7 @@ int __attribute__((no_instrument_function)) trace_early_init(void) printf("trace: early enable at %08x\n", CONFIG_TRACE_EARLY_ADDR); trace_enabled = 1; + return 0; } #endif diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 421362d..3e6bdf8 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -4401,11 +4401,6 @@ CONFIG_TMU_TIMER CONFIG_TPL_PAD_TO CONFIG_TPM_TIS_BASE_ADDRESS CONFIG_TPS6586X_POWER -CONFIG_TRACE -CONFIG_TRACE_BUFFER_SIZE -CONFIG_TRACE_EARLY -CONFIG_TRACE_EARLY_ADDR -CONFIG_TRACE_EARLY_SIZE CONFIG_TRAILBLAZER CONFIG_TRATS CONFIG_TSEC |