kpatch-build: clarify ppc64le comments

Clarify some of the comment wording in the new ppc64le code.
This commit is contained in:
Josh Poimboeuf 2017-07-25 11:38:48 -05:00
parent e3ccff0cab
commit 339938c0a9
6 changed files with 58 additions and 54 deletions

View File

@ -3,9 +3,9 @@ KPATCH_BUILD ?= /lib/modules/$(shell uname -r)/build
KPATCH_MAKE = $(MAKE) -C $(KPATCH_BUILD) M=$(PWD)
LDFLAGS += $(KPATCH_LDFLAGS)
# ppc64le kernel modules are expected to compiled with
# -mcmodel=large flag. This enable 64-bit relocations,
# instead of 32-bit offset from TOC pointer.
# ppc64le kernel modules are expected to compile with the
# -mcmodel=large flag. This enables 64-bit relocations
# instead of a 32-bit offset from the TOC pointer.
PROCESSOR = $(shell uname -p)
ifeq ($(PROCESSOR), ppc64le)
KBUILD_CFLAGS_MODULE += -mcmodel=large

View File

@ -184,10 +184,11 @@ static int rela_equal(struct rela *rela1, struct rela *rela2)
* 00000000000000b4 000000b90000000a R_PPC64_REL24 0000000000000000 printk + 0
* 00000000000000bc 000000a10000000a R_PPC64_REL24 0000000000000000 dump_stack + 0
*
* with -mcmodel=large on ppc64le, gcc might generate entries in .toc section for symbol
* reference in relocation sections. There are chances of symbol referenced by toc + offset
* may point to different symbols in original and patched .o. Compare the symbols by
* reading its corresponding toc + offset rela from .toc section.
* With -mcmodel=large on ppc64le, GCC might generate entries in the .toc
* section for relocation symbol references. The .toc offsets may change
* between the original and patched .o, so comparing ".toc + offset" isn't
* right. Compare the .toc-based symbols by reading the corresponding relas
* from the .toc section.
*/
if (!strcmp(rela1->sym->name, ".toc") &&
!strcmp(rela2->sym->name, ".toc")) {
@ -237,9 +238,8 @@ static void kpatch_compare_correlated_rela_section(struct section *sec)
struct rela *rela1, *rela2 = NULL;
/*
* Don't compare relocation entries for .toc section.
* .toc and .rela.toc sections are included as standard
* elements.
* On ppc64le, don't compare the .rela.toc section. The .toc and
* .rela.toc sections are included as standard elements.
*/
if (!strcmp(sec->name, ".rela.toc")) {
sec->status = SAME;
@ -1011,10 +1011,12 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
#ifdef __powerpc__
/*
* With -mcmodel=large, the relative relocation or
* R_PPC64_REL24 type is limited to functions only.
* rela->sym->sec should have been replaced with it's
* section symbol already. If not bail out.
* With -mcmodel=large, R_PPC64_REL24 is only used for
* functions. Assuming the function is bundled in a
* section, the section symbol should have been
* replaced with a text symbol already. Otherwise,
* bail out. If we hit this situation, more core is
* needed here to calculate the value of 'add_off'.
*/
if (rela->type == R_PPC64_REL24)
ERROR("Unexpected relocation type R_PPC64_REL24 for %s\n", rela->sym->name);
@ -1220,9 +1222,9 @@ static void kpatch_include_standard_elements(struct kpatch_elf *kelf)
}
/*
* rela.toc section holds reference to symbols,
* referred by function section relocation
* entries. Include all of the symbols.
* On ppc64le, the .rela.toc section refers to symbols which
* are needed for function symbol relocations. Include all the
* symbols.
*/
if (!strcmp(sec->name, ".rela.toc"))
{
@ -2254,8 +2256,8 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
sym_objname = objname;
/*
* function prologue generated by gcc6 on ppc64le has
* the sequence:
* On ppc64le, the function prologue generated by GCC 6
* has the sequence:
*
* .globl my_func
* .type my_func, @function
@ -2264,12 +2266,10 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
* .reloc ., R_PPC64_ENTRY ; optional
* ld r2,-8(r12)
* add r2,r2,r12
* .localentry my_func, .-my_func
* .localentry my_func, .-my_func
*
* first entry past function global entry point is optional
* and has the relocation type R_PPC64_ENTRY. We should *not*
* skip this entry while building up the rela list, rather
* skip it's lookup.
* The R_PPC64_ENTRY is optional and its symbol might
* have an empty name. Leave it as a normal rela.
*/
if (rela->type == R_PPC64_ENTRY)
continue;
@ -2291,17 +2291,19 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
*/
#ifdef __powerpc__
/*
* An exported symbol, might be local to an object file
* and any access to the function might be through localentry
* (toc+offset) instead of global offset.
* An exported symbol might be local to an
* object file and any access to the function
* might be through localentry (toc+offset)
* instead of global offset.
*
* fs/proc/proc_sysctl::sysctl_head_grab:
* 166: 0000000000000000 256 FUNC GLOBAL DEFAULT [<localentry>: 8] 42 unregister_sysctl_table
* 167: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND .TOC.
*
* These type of function have the sym->type == STT_FUNC, treat them as local
* symbol. This creates an entry under klp.relocations and relocation
* is handled by livepatch.
* These type of symbols have a type of
* STT_FUNC. Treat them like local symbols.
* They will be handled by the livepatch
* relocation code.
*/
if (lookup_is_exported_symbol(table, rela->sym->name)) {
if (rela->sym->type != STT_FUNC)

View File

@ -201,8 +201,10 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
* 0000000000000058 0000003900000026 R_PPC64_ADDR64 0000000000000000 __per_cpu_offset + 0
* [...]
*
* when more .o files are linked together, the .toc entries might get re-arranged. Capture new .toc rela
* offset value, which will be used below to setting the rela->addend. */
* On ppc64le, when .o files are linked together, the .toc
* entries might get re-arranged. Capture the new .toc rela
* offset value, which is used below to set the rela->addend.
*/
toc_offset = rela->addend;
base = rela->sym->sec;
@ -245,10 +247,11 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
rela->offset = krelas[index].offset;
/*
* gcc6 adds offset for 0x8 for every local function entry in
* .toc section, for avoiding setup of toc but when the previously
* local function becomes global, toc is anyways setup. So remove
* the wrong addend.
* GCC 6+ adds 0x8 to the offset of every local function entry
* in the .toc section, for avoiding the setup of the toc when
* the function is called locally. But when the previously
* local function becomes global, we don't want to skip the
* .toc setup anymore.
*/
if (!strcmp(base->name, ".toc") &&
rela->sym->type == STT_FUNC && rela->sym->bind == STB_LOCAL) {

View File

@ -160,12 +160,12 @@ gcc_version_check() {
return 1
fi
# On ppc64le, livepatch relies on gcc support for -mprofile-kernel flag.
# Script with differnet checks is run during kernel build, to ensure that
# the required gcc supports is available. This check is done during kernel
# build by:
# <linux-sources>/arch/powerpc/tools/gcc-check-mprofile-kernel.sh
# Postpond the check until kernel build, instead of duplicating it here.
# On ppc64le, livepatch needs the GCC -mprofile-kernel flag. A script
# is run during the kernel build to ensure the flag is present:
#
# <linux>/arch/powerpc/tools/gcc-check-mprofile-kernel.sh
#
# Postpone the check to the kernel build instead of duplicating it here.
if [[ $ARCH = "ppc64le" ]]; then
return
else

View File

@ -85,8 +85,7 @@ int is_debug_section(struct section *sec)
(((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2)
/*
* function prologue generated by gcc6 on ppc64le has
* the sequence:
* On ppc64le, the function prologue generated by GCC 6+ has the sequence:
*
* .globl my_func
* .type my_func, @function
@ -95,15 +94,12 @@ int is_debug_section(struct section *sec)
* .reloc ., R_PPC64_ENTRY ; optional
* ld r2,-8(r12)
* add r2,r2,r12
* .localentry my_func, .-my_func
* .localentry my_func, .-my_func
*
* my_func is resolved by .TOC.-my_func to a 64-bit offset stored
* above the global entry point. my_func st_value is set 0x8, for
* calling into the .localentry of the function.
*
* Number of instructions between global and local entry point of a
* function is mostly 8 instructions. i.e st_other == 3. The count of
* instruction can be decoded only for local function symbols.
* my_func is the global entry point, which, when called, sets up the TOC.
* .localentry is the local entry point, for calls to the function from within
* the object file. The local entry point is 8 bytes after the global entry
* point.
*/
static int is_localentry_sym(struct symbol *sym)
{
@ -381,6 +377,7 @@ void kpatch_create_symbol_list(struct kpatch_elf *kelf)
}
sym->sec->sym = sym;
} else if (sym->type == STT_SECTION) {
sym->sec->secsym = sym;
/* use the section name as the symbol name */

View File

@ -15,9 +15,11 @@ if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
obj=$2
# skip copying the original .o files, when .tmp_mc_*.o
# is passed from recordmcount.pl.
# skip copying the temporary .o files created by
# recordmcount.pl
[[ $obj = */.tmp_mc_*.o ]] && break;
[[ $obj = */.tmp_*.o ]] && obj=${obj/.tmp_/}
case "$obj" in
*.mod.o|\