2 * Copyright 2013 Texas Instruments, Inc.
3 * Russ Dill <russ.dill@ti.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
13 #include <linux/kernel.h>
14 #include <linux/err.h>
16 #include <asm/fncpy.h>
23 * pie_arch_fixup - arch specific fixups of copied PIE code
24 * @chunk: identifier to be used with kern_to_pie/pie_to_phys
25 * @base: virtual address of start of copied PIE section
26 * @tail: virtual address of tail data in copied PIE
27 * @offset: offset to apply to relocation entries.
29 * When this code is done executing, it should be possible to jump to code
30 * so long as it is located at the given offset.
32 extern int pie_arch_fixup(struct pie_chunk *chunk, void *base, void *tail,
33 unsigned long offset);
36 * pie_arch_fill_tail - arch specific tail information for copied PIE
37 * @tail: virtual address of tail data in copied PIE to be filled
38 * @common_start: virtual address of common code within kernel data
39 * @common_end: virtual end address of common code within kernel data
40 * @overlay_start: virtual address of first overlay within kernel data
41 * @code_start: virtual address of this overlay within kernel data
42 * @code_end: virtual end address of this overlay within kernel data
44 * Fill tail data with data necessary to for pie_arch_fixup to perform
45 * relocations. If tail is NULL, do not update data, but still calculate
46 * the number of bytes required.
48 * Returns number of bytes required/used for tail on success, -EERROR otherwise.
50 extern int pie_arch_fill_tail(void *tail, void *common_start, void *common_end,
51 void *overlay_start, void *code_start, void *code_end,
52 void *rel_start, void *rel_end);
57 * __pie_load_data - load and fixup PIE code from kernel data
58 * @pool: pool to allocate memory from and copy code into
59 * @start: virtual start address in kernel of chunk specific code
60 * @end: virtual end address in kernel of chunk specific code
61 * @phys: %true to fixup to physical address of destination, %false to
62 * fixup to virtual address of destination
64 * Returns 0 on success, -EERROR otherwise
66 extern struct pie_chunk *__pie_load_data(struct gen_pool *pool, bool phys,
67 void *start, void *end,
68 void *rel_start, void *rel_end);
71 * pie_to_phys - translate a virtual PIE address into a physical one
72 * @chunk: identifier returned by pie_load_sections
73 * @addr: virtual address within pie chunk
75 * Returns physical address on success, -1 otherwise
77 extern phys_addr_t pie_to_phys(struct pie_chunk *chunk, unsigned long addr);
79 extern void __iomem *__kern_to_pie(struct pie_chunk *chunk, void *ptr);
82 * pie_free - free the pool space used by an pie chunk
83 * @chunk: identifier returned by pie_load_sections
85 extern void pie_free(struct pie_chunk *chunk);
87 #define __pie_load_sections(pool, name, phys) ({ \
88 extern char __pie_##name##_start[]; \
89 extern char __pie_##name##_end[]; \
90 extern char __pie_rel_##name##_start[]; \
91 extern char __pie_rel_##name##_end[]; \
93 __pie_load_data(pool, phys, \
94 __pie_##name##_start, __pie_##name##_end, \
95 __pie_rel_##name##_start, __pie_rel_##name##_end); \
99 * Required for any symbol within an PIE section that is referenced by the
102 #define EXPORT_PIE_SYMBOL(sym) extern typeof(sym) sym __weak
104 /* For marking data and functions that should be part of a PIE */
105 #define __pie(name) __attribute__ ((__section__(".pie." #name ".text")))
106 #define __pie_data(name) __attribute__ ((__section__(".pie." #name ".data")))
110 static inline struct pie_chunk *__pie_load_data(struct gen_pool *pool,
111 void *start, void *end, bool phys)
113 return ERR_PTR(-EINVAL);
116 static inline phys_addr_t pie_to_phys(struct pie_chunk *chunk,
122 static inline void __iomem *__kern_to_pie(struct pie_chunk *chunk, void *ptr)
127 static inline void pie_free(struct pie_chunk *chunk)
131 #define __pie_load_sections(pool, name, phys) ({ ERR_PTR(-EINVAL); })
133 #define EXPORT_PIE_SYMBOL(sym)
136 #define __pie_data(name)
141 * pie_load_sections - load and fixup sections associated with the given name
142 * @pool: pool to allocate memory from and copy code into
143 * fixup to virtual address of destination
144 * @name: the name given to __pie() and __pie_data() when marking
147 * Returns 0 on success, -EERROR otherwise
149 #define pie_load_sections(pool, name) ({ \
150 __pie_load_sections(pool, name, false); \
154 * pie_load_sections_phys - load and fixup sections associated with the given
155 * name for execution with the MMU off
157 * @pool: pool to allocate memory from and copy code into
158 * fixup to virtual address of destination
159 * @name: the name given to __pie() and __pie_data() when marking
162 * Returns 0 on success, -EERROR otherwise
164 #define pie_load_sections_phys(pool, name) ({ \
165 __pie_load_sections(pool, name, true); \
169 * kern_to_pie - convert a kernel symbol to the virtual address of where
170 * that symbol is loaded into the given PIE chunk.
172 * @chunk: identifier returned by pie_load_sections
173 * @p: symbol to convert
175 * Return type is the same as type passed
177 #define kern_to_pie(chunk, p) ({ \
178 void *__ptr = (void *) (p); \
179 typeof(p) __result = (typeof(p)) __kern_to_pie(chunk, __ptr); \
184 * kern_to_fn - convert a kernel function symbol to the virtual address of where
185 * that symbol is loaded into the given PIE chunk
187 * @chunk: identifier returned by pie_load_sections
188 * @p: function to convert
190 * Return type is the same as type passed
192 #define fn_to_pie(chunk, funcp) ({ \
193 uintptr_t __kern_addr, __pie_addr; \
195 __kern_addr = fnptr_to_addr(funcp); \
196 __pie_addr = kern_to_pie(chunk, __kern_addr); \
198 fnptr_translate(funcp, __pie_addr); \