Browse Source

Merge tag 'pull-24apr19' of git://git.denx.de/u-boot-dm

Various minor sandbox iumprovements
Fixes for tracing with sandbox
Refactoring for boot_get_fdt()
Tom Rini 5 years ago
parent
commit
7d99406742

+ 1 - 0
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

+ 9 - 3
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();

+ 50 - 9
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;
+}

+ 11 - 5
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);
 

+ 1 - 0
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>

+ 46 - 0
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)
+=
 
 
 --

+ 12 - 1
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

+ 1 - 1
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

+ 7 - 0
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++;
 

+ 14 - 0
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) {

+ 17 - 16
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;
 }
 

+ 1 - 1
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

+ 9 - 0
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

+ 6 - 3
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

+ 0 - 21
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 */

+ 1 - 0
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,
 };

+ 4 - 0
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
 

+ 2 - 2
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

+ 35 - 35
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);
 }

+ 0 - 21
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

+ 4 - 1
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

+ 11 - 8
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");

+ 11 - 0
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

+ 1 - 0
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) */

+ 57 - 0
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"

+ 13 - 7
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) {

+ 0 - 7
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;

+ 11 - 6
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

+ 0 - 5
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