summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/asm-generic/memory_layout.h7
-rw-r--r--include/asm-generic/reloc.h69
-rw-r--r--include/linux/reset.h6
-rw-r--r--include/restart.h15
-rw-r--r--include/soc/fsl/fsl_udc.h3
-rw-r--r--include/soc/stm32/reboot.h6
6 files changed, 101 insertions, 5 deletions
diff --git a/include/asm-generic/memory_layout.h b/include/asm-generic/memory_layout.h
index 5cfd2a43a0..7593e18da1 100644
--- a/include/asm-generic/memory_layout.h
+++ b/include/asm-generic/memory_layout.h
@@ -23,4 +23,11 @@
#define MALLOC_SIZE CONFIG_MALLOC_SIZE
#define STACK_SIZE CONFIG_STACK_SIZE
+/*
+ * This generates a useless load from the specified symbol
+ * to ensure linker garbage collection doesn't delete it
+ */
+#define __keep_symbolref(sym) \
+ __asm__ __volatile__("": :"r"(&sym) :)
+
#endif /* __ASM_GENERIC_MEMORY_LAYOUT_H */
diff --git a/include/asm-generic/reloc.h b/include/asm-generic/reloc.h
index 90459371eb..06fccbd6f3 100644
--- a/include/asm-generic/reloc.h
+++ b/include/asm-generic/reloc.h
@@ -3,8 +3,77 @@
#ifndef _ASM_GENERIC_RELOC_H_
#define _ASM_GENERIC_RELOC_H_
+#include <linux/build_bug.h>
+#include <linux/compiler.h>
+
#ifndef global_variable_offset
#define global_variable_offset() get_runtime_offset()
#endif
+/*
+ * Using sizeof() on incomplete types always fails, so we use GCC's
+ * __builtin_object_size() instead. This is the mechanism underlying
+ * FORTIFY_SOURCE. &symbol should always be something GCC can compute
+ * a size for, even without annotations, unless it's incomplete.
+ * The second argument ensures we get 0 for failure.
+ */
+#define __has_type_complete(sym) __builtin_object_size(&(sym), 2)
+
+#define __has_type_byte_array(sym) (sizeof(*sym) == 1 + __must_be_array(sym))
+
+/*
+ * runtime_address() defined below is supposed to be used exclusively
+ * with linker defined symbols, e.g. unsigned char input_end[].
+ *
+ * We can't completely ensure that, but this gets us close enough
+ * to avoid most abuse of runtime_address().
+ */
+#define __is_incomplete_byte_array(sym) \
+ (!__has_type_complete(sym) && __has_type_byte_array(sym))
+
+/*
+ * While accessing global variables before C environment is setup is
+ * questionable, we can't avoid it when we decide to write our
+ * relocation routines in C. This invites a tricky problem with
+ * this naive code:
+ *
+ * var = &variable + global_variable_offset(); relocate_to_current_adr();
+ *
+ * Compiler is within rights to rematerialize &variable after
+ * relocate_to_current_adr(), which is unfortunate because we
+ * then end up adding a relocated &variable with the relocation
+ * offset once more. We avoid this here by hiding address with
+ * RELOC_HIDE. This is required as a simple compiler barrier()
+ * with "memory" clobber is not immune to compiler proving that
+ * &sym fits in a register and as such is unaffected by the memory
+ * clobber. barrier_data(&sym) would work too, but that comes with
+ * aforementioned compiler "memory" barrier, that we don't care for.
+ *
+ * We don't necessarily need the volatile variable assignment when
+ * using the compiler-gcc.h RELOC_HIDE implementation as __asm__
+ * __volatile__ takes care of it, but the generic RELOC_HIDE
+ * implementation has GCC misscompile runtime_address() when not passing
+ * in a volatile object. Volatile casts instead of variable assignments
+ * also led to miscompilations with GCC v11.1.1 for THUMB2.
+ */
+
+#define runtime_address(sym) ({ \
+ void *volatile __addrof_sym = (sym); \
+ if (!__is_incomplete_byte_array(sym)) \
+ __unsafe_runtime_address(); \
+ RELOC_HIDE(__addrof_sym, global_variable_offset()); \
+})
+
+/*
+ * Above will fail for "near" objects, e.g. data in the same
+ * translation unit or with LTO, as the compiler can be smart
+ * enough to omit relocation entry and just generate PC relative
+ * accesses leading to base address being added twice. We try to
+ * catch most of these here by triggering an error when runtime_address()
+ * is used with anything that is not a byte array of unknown size.
+ */
+extern void *__compiletime_error(
+ "runtime_address() may only be called on linker defined symbols."
+) __unsafe_runtime_address(void);
+
#endif
diff --git a/include/linux/reset.h b/include/linux/reset.h
index c1282a84c7..2d788547f4 100644
--- a/include/linux/reset.h
+++ b/include/linux/reset.h
@@ -49,6 +49,12 @@ static inline int reset_control_deassert(struct reset_control *rstc)
}
static inline struct reset_control *
+of_reset_control_get(struct device_node *node, const char *id)
+{
+ return NULL;
+}
+
+static inline struct reset_control *
reset_control_get(struct device_d *dev, const char *id)
{
return NULL;
diff --git a/include/restart.h b/include/restart.h
index 2d15c7598a..15f30bb7ad 100644
--- a/include/restart.h
+++ b/include/restart.h
@@ -2,13 +2,24 @@
#ifndef __INCLUDE_RESTART_H
#define __INCLUDE_RESTART_H
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+
+struct device_node;
+
void restart_handlers_print(void);
void __noreturn restart_machine(void);
-struct restart_handler *restart_handler_get_by_name(const char *name);
+struct restart_handler *restart_handler_get_by_name(const char *name, int flags);
+
+struct device_node;
struct restart_handler {
void (*restart)(struct restart_handler *);
int priority;
+#define RESTART_FLAG_WARM_BOOTROM BIT(0)
+ int flags;
+ struct device_node *of_node;
const char *name;
struct list_head list;
};
@@ -19,6 +30,4 @@ int restart_handler_register_fn(const char *name,
#define RESTART_DEFAULT_PRIORITY 100
-unsigned int of_get_restart_priority(struct device_node *node);
-
#endif /* __INCLUDE_RESTART_H */
diff --git a/include/soc/fsl/fsl_udc.h b/include/soc/fsl/fsl_udc.h
index aa1db2fb38..c1abe222ba 100644
--- a/include/soc/fsl/fsl_udc.h
+++ b/include/soc/fsl/fsl_udc.h
@@ -385,6 +385,9 @@ int imx_barebox_start_usb(void __iomem *dr, void *dest);
int imx6_barebox_load_usb(void *dest);
int imx6_barebox_start_usb(void *dest);
+int imx7_barebox_load_usb(void *dest);
+int imx7_barebox_start_usb(void *dest);
+
int imx8mm_barebox_load_usb(void *dest);
int imx8mm_barebox_start_usb(void *dest);
diff --git a/include/soc/stm32/reboot.h b/include/soc/stm32/reboot.h
index d6c731f59f..cf0d0286e7 100644
--- a/include/soc/stm32/reboot.h
+++ b/include/soc/stm32/reboot.h
@@ -5,10 +5,12 @@
#include <linux/compiler.h>
+struct device_d;
+
#ifdef CONFIG_RESET_STM32
-void stm32mp_system_restart_init(void __iomem *rcc);
+void stm32mp_system_restart_init(struct device_d *rcc);
#else
-static inline void stm32mp_system_restart_init(void __iomem *rcc)
+static inline void stm32mp_system_restart_init(struct device_d *rcc)
{
}
#endif