PIE: Support embedding position independent executables
authorRuss Dill <Russ.Dill@ti.com>
Tue, 17 Sep 2013 08:10:23 +0000 (01:10 -0700)
committer黄涛 <huangtao@rock-chips.com>
Thu, 21 Nov 2013 05:39:21 +0000 (13:39 +0800)
commit2ecab0b339252a6427b52d03719c96f97f19e272
tree0b325933675512e6cd238861c949ca1bc7979561
parent49d083bd72f8fe93b1d76078be1da897f5e41e98
PIE: Support embedding position independent executables

This commit adds support for embedding PIEs into the kernel, loading them
into genalloc sections, performing necessary relocations, and running code
from them. This allows platforms that need to run code from SRAM, such
an during suspend/resume, to develop that code in C instead of assembly.

Functions and data for each PIE should be grouped into sections with the
__pie(<group>) and __pie_data(<group>) macros respectively. Any symbols or
functions that are to be accessed from outside the PIE should be marked with
EXPORT_PIE_SYMBOL(<sym>). For example:

static struct ddr_timings xyz_timings __pie_data(platformxyz) = {
[...]
};

void __pie(platformxyz) xyz_ddr_on(void *addr)
{
[...]
}
EXPORT_PIE_SYMBOL(xyz_ddr_on);

While the kernel can access exported symbols from the PIE, the PIE cannot
access symbols from the kernel, but can access data from the kernel and
call functions in the kernel so long as addresses are passed into the PIE.

PIEs are loaded from the kernel into a genalloc pool with pie_load_sections.
pie_load_sections allocates space within the pool, copies the neccesary
code/data, and performs any necessary relocations. A chunk identifier is
returned for removing the PIE from the pool, and for translating symbols.

Because the PIEs are dynamically relocated, special accessors must be used
to access PIE symbols from kernel code:

- kern_to_pie(chunk, ptr):   Translate a PIE symbol to the virtual address
                             it is loaded into within the pool.

- fn_to_pie(chunk, ptr):     Same as above, but for function pointers.

- sram_to_phys(chunk, addr): Translate a virtual address within a loaded PIE
                             to a physical address.

Loading a PIE involves three main steps. First a set of common functions to
cover built-ins emitted by gcc (memcpy, memmove, etc) is copied into the pool.
Then the actual PIE code and data is copied into the pool. Because the PIE
code is contained within an overlay with other PIEs, offsets to the common
functions are maintained. Finally, relocations are performed as necessary.

Signed-off-by: Russ Dill <Russ.Dill@ti.com>
Documentation/pie.txt [new file with mode: 0644]
Makefile
include/asm-generic/pie.lds.h [new file with mode: 0644]
include/asm-generic/vmlinux.lds.h
include/linux/pie.h [new file with mode: 0644]
lib/Kconfig
lib/Makefile
lib/pie.c [new file with mode: 0644]
pie/.gitignore [new file with mode: 0644]
pie/Makefile [new file with mode: 0644]
scripts/link-vmlinux.sh