[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH 07/26] x86/paravirt: Persist .parainstructions.runtime



Persist .parainstructions.runtime in memory. We will use it to
patch paravirt-ops at runtime.

The extra memory footprint depends on chosen config options but the
inlined queued_spin_unlock() presents an edge case:

 $ objdump -h vmlinux|grep .parainstructions
 Idx Name                       Size      VMA
        LMA                File-off  Algn
  27 .parainstructions          0001013c  ffffffff82895000
        0000000002895000   01c95000  2**3
  28 .parainstructions.runtime  0000cd2c  ffffffff828a5140
        00000000028a5140   01ca5140  2**3

(The added footprint is the size of the .parainstructions.runtime
section.)

  $ size vmlinux
  text       data       bss        dec      hex       filename
  13726196   12302814   14094336   40123346 2643bd2   vmlinux

Signed-off-by: Ankur Arora <ankur.a.arora@xxxxxxxxxx>
---
 arch/x86/include/asm/alternative.h |  1 +
 arch/x86/kernel/alternative.c      | 16 +++++++++++++++-
 arch/x86/kernel/module.c           | 28 +++++++++++++++++++++++-----
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/alternative.h 
b/arch/x86/include/asm/alternative.h
index db91a7731d87..d19546c14ff6 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -76,6 +76,7 @@ extern void apply_alternatives(struct alt_instr *start, 
struct alt_instr *end);
 struct module;
 
 void alternatives_module_add(struct module *mod, char *name,
+                            void *para, void *para_end,
                             void *locks, void *locks_end,
                             void *text, void *text_end);
 void alternatives_module_del(struct module *mod);
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 09e4ee0e09a2..8189ac21624c 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -482,6 +482,12 @@ struct alt_module {
        struct module   *mod;
        char            *name;
 
+#ifdef CONFIG_PARAVIRT_RUNTIME
+       /* ptrs to paravirt sites */
+       struct paravirt_patch_site *para;
+       struct paravirt_patch_site *para_end;
+#endif
+
        /* ptrs to lock prefixes */
        const s32       *locks;
        const s32       *locks_end;
@@ -496,6 +502,7 @@ struct alt_module {
 static LIST_HEAD(alt_modules);
 
 void __init_or_module alternatives_module_add(struct module *mod, char *name,
+                                             void *para, void *para_end,
                                              void *locks, void *locks_end,
                                              void *text,  void *text_end)
 {
@@ -506,7 +513,7 @@ void __init_or_module alternatives_module_add(struct module 
*mod, char *name,
        if (!noreplace_smp && (num_present_cpus() == 1 || setup_max_cpus <= 1))
                uniproc_patched = true;
 #endif
-       if (!uniproc_patched)
+       if (!IS_ENABLED(CONFIG_PARAVIRT_RUNTIME) && !uniproc_patched)
                return;
 
        mutex_lock(&text_mutex);
@@ -516,6 +523,11 @@ void __init_or_module alternatives_module_add(struct 
module *mod, char *name,
        alt->mod        = mod;
        alt->name       = name;
 
+#ifdef CONFIG_PARAVIRT_RUNTIME
+       alt->para       = para;
+       alt->para_end   = para_end;
+#endif
+
        if (num_possible_cpus() != 1 || uniproc_patched) {
                /* Remember only if we'll need to undo it. */
                alt->locks      = locks;
@@ -733,6 +745,8 @@ void __init alternative_instructions(void)
        apply_alternatives(__alt_instructions, __alt_instructions_end);
 
        alternatives_module_add(NULL, "core kernel",
+                               __parainstructions_runtime,
+                               __parainstructions_runtime_end,
                                __smp_locks, __smp_locks_end,
                                _text, _etext);
 
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index fc3d35198b09..7b2632184c11 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -248,12 +248,30 @@ int module_finalize(const Elf_Ehdr *hdr,
                void *aseg = (void *)alt->sh_addr;
                apply_alternatives(aseg, aseg + alt->sh_size);
        }
-       if (locks && text) {
-               void *lseg = (void *)locks->sh_addr;
-               void *tseg = (void *)text->sh_addr;
+       if (para_run || (locks && text)) {
+               void *pseg, *pseg_end;
+               void *lseg, *lseg_end;
+               void *tseg, *tseg_end;
+
+               pseg = pseg_end = NULL;
+               lseg = lseg_end = NULL;
+               tseg = tseg_end = NULL;
+               if (para_run) {
+                       pseg = (void *)para_run->sh_addr;
+                       pseg_end = pseg + para_run->sh_size;
+               }
+
+               if (locks && text) {
+                       tseg = (void *)text->sh_addr;
+                       tseg_end = tseg + text->sh_size;
+
+                       lseg = (void *)locks->sh_addr;
+                       lseg_end = lseg + locks->sh_size;
+               }
                alternatives_module_add(me, me->name,
-                                       lseg, lseg + locks->sh_size,
-                                       tseg, tseg + text->sh_size);
+                                       pseg, pseg_end,
+                                       lseg, lseg_end,
+                                       tseg, tseg_end);
        }
 
        if (para) {
-- 
2.20.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.