Re: [PATCH 1/2] docs/livepatch: Add new compiler considerations doc

From: Marcos Paulo de Souza
Date: Wed May 29 2024 - 10:14:20 EST


From: mpdesouza@xxxxxxxx

On Wed, 2 Sep 2020 15:45:33 +0200 (CEST) Miroslav Benes <mbenes@xxxxxxx> wrote:

> Hi,
>
> first, I'm sorry for the late reply. Thanks, Josh, for the reminder.
>
> CCing Nicolai. Nicolai, could you take a look at the proposed
> documentation too, please? You have more up-to-date experience.
>
> On Tue, 21 Jul 2020, Joe Lawrence wrote:
>
> > +Examples
> > +========
> > +
> > +Interprocedural optimization (IPA)
> > +----------------------------------
> > +
> > +Function inlining is probably the most common compiler optimization that
> > +affects livepatching. In a simple example, inlining transforms the original
> > +code::
> > +
> > + foo() { ... [ foo implementation ] ... }
> > +
> > + bar() { ... foo() ... }
> > +
> > +to::
> > +
> > + bar() { ... [ foo implementation ] ... }
> > +
> > +Inlining is comparable to macro expansion, however the compiler may inline
> > +cases which it determines worthwhile (while preserving original call/return
> > +semantics in others) or even partially inline pieces of functions (see cold
> > +functions in GCC function suffixes section below).
> > +
> > +To safely livepatch ``foo()`` from the previous example, all of its callers
> > +need to be taken into consideration. For those callers that the compiler had
> > +inlined ``foo()``, a livepatch should include a new version of the calling
> > +function such that it:
> > +
> > + 1. Calls a new, patched version of the inlined function, or
> > + 2. Provides an updated version of the caller that contains its own inlined
> > + and updated version of the inlined function
>
> I'm afraid the above could cause a confusion...
>
> "1. Calls a new, patched version of the inlined function, or". The
> function is not inlined in this case. Would it be more understandable to
> use function names?
>
> 1. Calls a new, patched version of function foo(), or
> 2. Provides an updated version of bar() that contains its own inlined and
> updated version of foo() (as seen in the example above).
>
> Not to say that it is again a call of the compiler to decide that, so one
> usually prepares an updated version of foo() and updated version of bar()
> calling to it. Updated foo() has to be there for non-inlined cases anyway.
>
> > +
> > +Other interesting IPA examples include:
> > +
> > +- *IPA-SRA*: removal of unused parameters, replace parameters passed by
> > + referenced by parameters passed by value. This optimization basically
>
> s/referenced/reference/
>
> > + violates ABI.
> > +
> > + .. note::
> > + GCC changes the name of function. See GCC function suffixes
> > + section below.
> > +
> > +- *IPA-CP*: find values passed to functions are constants and then optimizes
> > + accordingly Several clones of a function are possible if a set is limited.
>
> "...accordingly. Several..."
>
> [...]
>
> > + void cdev_put(struct cdev *p)
> > + {
> > + if (p) {
> > + struct module *owner = p->owner;
> > + kobject_put(&p->kobj);
> > + module_put(owner);
> > + }
> > + }
>
> git am complained here about whitespace damage.
>
> [...]
>
> > +kgraft-analysis-tool
> > +--------------------
> > +
> > +With the -fdump-ipa-clones flag, GCC will dump IPA clones that were created
> > +by all inter-procedural optimizations in ``<source>.000i.ipa-clones`` files.
> > +
> > +kgraft-analysis-tool pretty-prints those IPA cloning decisions. The full
> > +list of affected functions provides additional updates that the source-based
> > +livepatch author may need to consider. For example, for the function
> > +``scatterwalk_unmap()``:
> > +
> > +::
> > +
> > + $ ./kgraft-ipa-analysis.py --symbol=scatterwalk_unmap aesni-intel_glue.i.000i.ipa-clones
> > + Function: scatterwalk_unmap/2930 (include/crypto/scatterwalk.h:81:60)
> > + isra: scatterwalk_unmap.isra.2/3142 (include/crypto/scatterwalk.h:81:60)
> > + inlining to: helper_rfc4106_decrypt/3007 (arch/x86/crypto/aesni-intel_glue.c:1016:12)
> > + inlining to: helper_rfc4106_decrypt/3007 (arch/x86/crypto/aesni-intel_glue.c:1016:12)
> > + inlining to: helper_rfc4106_encrypt/3006 (arch/x86/crypto/aesni-intel_glue.c:939:12)
> > +
> > + Affected functions: 3
> > + scatterwalk_unmap.isra.2/3142 (include/crypto/scatterwalk.h:81:60)
> > + helper_rfc4106_decrypt/3007 (arch/x86/crypto/aesni-intel_glue.c:1016:12)
> > + helper_rfc4106_encrypt/3006 (arch/x86/crypto/aesni-intel_glue.c:939:12)
>
> The example for the github is not up-to-date. The tool now expects
> file_list with *.ipa-clones files and the output is a bit different for
> the recent kernel.
>
> $ echo arch/x86/crypto/aesni-intel_glue.c.000i.ipa-clones | kgraft-ipa-analysis.py --symbol=scatterwalk_unmap /dev/stdin
> Parsing file (1/1): arch/x86/crypto/aesni-intel_glue.c.000i.ipa-clones
> Function: scatterwalk_unmap/3935 (./include/crypto/scatterwalk.h:59:20) [REMOVED] [object file: arch/x86/crypto/aesni-intel_glue.c.000i.ipa-clones]
> isra: scatterwalk_unmap.isra.8/4117 (./include/crypto/scatterwalk.h:59:20) [REMOVED]
> inlining to: gcmaes_crypt_by_sg/4019 (arch/x86/crypto/aesni-intel_glue.c:682:12) [REMOVED] [edges: 4]
> constprop: gcmaes_crypt_by_sg.constprop.13/4182 (arch/x86/crypto/aesni-intel_glue.c:682:12)
>
> Affected functions: 3
> scatterwalk_unmap.isra.8/4117 (./include/crypto/scatterwalk.h:59:20) [REMOVED]
> gcmaes_crypt_by_sg/4019 (arch/x86/crypto/aesni-intel_glue.c:682:12) [REMOVED]
> gcmaes_crypt_by_sg.constprop.13/4182 (arch/x86/crypto/aesni-intel_glue.c:682:12)
>
>
>
> The rest looks great. Thanks a lot, Joe, for putting it together.

I think that we should start provinding a "Livepatch creation how-to", something
similar, but for now I believe that some documentation is better than no
documentation. This document can evolve to reach such point in the future, but
for now, with Miroslav suggestions applied:

Acked-by: Marcos Paulo de Souza <mpdesouza@xxxxxxxx>

>
> Miroslav