diff mbox

[v3,11/23] xsplice: Add support for alternatives

Message ID 1455300361-13092-12-git-send-email-konrad.wilk@oracle.com (mailing list archive)
State New, archived
Headers show

Commit Message

Konrad Rzeszutek Wilk Feb. 12, 2016, 6:05 p.m. UTC
From: Ross Lagerwall <ross.lagerwall@citrix.com>

Add support for applying alternative sections within xsplice modules. At
module load time, apply an alternative sections that are found.

Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 xen/arch/x86/Makefile             |  2 +-
 xen/arch/x86/alternative.c        | 12 ++++++------
 xen/common/xsplice.c              | 10 +++++++++-
 xen/include/asm-x86/alternative.h |  1 +
 4 files changed, 17 insertions(+), 8 deletions(-)

Comments

Andrew Cooper Feb. 16, 2016, 7:41 p.m. UTC | #1
On 12/02/16 18:05, Konrad Rzeszutek Wilk wrote:
> diff --git a/xen/common/xsplice.c b/xen/common/xsplice.c
> index d863a99..65b1f11 100644
> --- a/xen/common/xsplice.c
> +++ b/xen/common/xsplice.c
> @@ -695,7 +695,7 @@ static int find_special_sections(struct payload *payload,
>      if ( sec )
>      {
>          if ( ( !sec->sec->sh_size ) ||
> -             ( sec->sec->sh_size % sizeof *sec->load_addr ) )
> +             ( sec->sec->sh_size % sizeof (struct exception_table_entry) ) )

This hunk looks like it wants to be in the previous patch.

>              return -EINVAL;
>  
>          payload->start_ex_table = (struct exception_table_entry *)sec->load_addr;
> @@ -703,6 +703,14 @@ static int find_special_sections(struct payload *payload,
>  
>          sort_exception_table(payload->start_ex_table, payload->stop_ex_table);
>      }
> +    sec = xsplice_elf_sec_by_name(elf, ".altinstructions");
> +    if ( sec )
> +    {
> +        local_irq_disable();
> +        apply_alternatives((struct alt_instr *)sec->load_addr,
> +                           (struct alt_instr *)(sec->load_addr + sec->sec->sh_size));
> +        local_irq_enable();
> +    }

None of that code is active, and it can't be made active at this point. 
Interrupts absolutely shouldn't be disabled here.  Instead, the
assertion in apply_alternatives() should be modified as you are adding a
new valid usecase.

Also, modifications like this in a function named
find_special_sections() seem wrong.  It looks like the function would be
better named prepare_payload() or similar.

~Andrew
diff mbox

Patch

diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index 51d12ac..8cce4ba 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -6,7 +6,7 @@  subdir-y += mm
 subdir-y += oprofile
 subdir-y += x86_64
 
-obj-bin-y += alternative.init.o
+obj-bin-y += alternative.o
 obj-y += apic.o
 obj-y += bitops.o
 obj-bin-y += bzimage.init.o
diff --git a/xen/arch/x86/alternative.c b/xen/arch/x86/alternative.c
index 46ac0fd..8d895ad 100644
--- a/xen/arch/x86/alternative.c
+++ b/xen/arch/x86/alternative.c
@@ -28,7 +28,7 @@ 
 extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
 
 #ifdef K8_NOP1
-static const unsigned char k8nops[] __initconst = {
+static const unsigned char k8nops[] = {
     K8_NOP1,
     K8_NOP2,
     K8_NOP3,
@@ -52,7 +52,7 @@  static const unsigned char * const k8_nops[ASM_NOP_MAX+1] = {
 #endif
 
 #ifdef P6_NOP1
-static const unsigned char p6nops[] __initconst = {
+static const unsigned char p6nops[] = {
     P6_NOP1,
     P6_NOP2,
     P6_NOP3,
@@ -75,7 +75,7 @@  static const unsigned char * const p6_nops[ASM_NOP_MAX+1] = {
 };
 #endif
 
-static const unsigned char * const *ideal_nops __initdata = k8_nops;
+static const unsigned char * const *ideal_nops = k8_nops;
 
 static int __init mask_nmi_callback(const struct cpu_user_regs *regs, int cpu)
 {
@@ -100,7 +100,7 @@  static void __init arch_init_ideal_nops(void)
 }
 
 /* Use this to add nops to a buffer, then text_poke the whole buffer. */
-static void __init add_nops(void *insns, unsigned int len)
+static void add_nops(void *insns, unsigned int len)
 {
     while ( len > 0 )
     {
@@ -127,7 +127,7 @@  static void __init add_nops(void *insns, unsigned int len)
  *
  * This routine is called with local interrupt disabled.
  */
-static void *__init text_poke_early(void *addr, const void *opcode, size_t len)
+static void *text_poke_early(void *addr, const void *opcode, size_t len)
 {
     memcpy(addr, opcode, len);
     sync_core();
@@ -142,7 +142,7 @@  static void *__init text_poke_early(void *addr, const void *opcode, size_t len)
  * APs have less capabilities than the boot processor are not handled.
  * Tough. Make sure you disable such features by hand.
  */
-static void __init apply_alternatives(struct alt_instr *start, struct alt_instr *end)
+void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
 {
     struct alt_instr *a;
     u8 *instr, *replacement;
diff --git a/xen/common/xsplice.c b/xen/common/xsplice.c
index d863a99..65b1f11 100644
--- a/xen/common/xsplice.c
+++ b/xen/common/xsplice.c
@@ -695,7 +695,7 @@  static int find_special_sections(struct payload *payload,
     if ( sec )
     {
         if ( ( !sec->sec->sh_size ) ||
-             ( sec->sec->sh_size % sizeof *sec->load_addr ) )
+             ( sec->sec->sh_size % sizeof (struct exception_table_entry) ) )
             return -EINVAL;
 
         payload->start_ex_table = (struct exception_table_entry *)sec->load_addr;
@@ -703,6 +703,14 @@  static int find_special_sections(struct payload *payload,
 
         sort_exception_table(payload->start_ex_table, payload->stop_ex_table);
     }
+    sec = xsplice_elf_sec_by_name(elf, ".altinstructions");
+    if ( sec )
+    {
+        local_irq_disable();
+        apply_alternatives((struct alt_instr *)sec->load_addr,
+                           (struct alt_instr *)(sec->load_addr + sec->sec->sh_size));
+        local_irq_enable();
+    }
 #endif
     return 0;
 }
diff --git a/xen/include/asm-x86/alternative.h b/xen/include/asm-x86/alternative.h
index 1056630..6a62113 100644
--- a/xen/include/asm-x86/alternative.h
+++ b/xen/include/asm-x86/alternative.h
@@ -23,6 +23,7 @@  struct alt_instr {
     u8  replacementlen;     /* length of new instruction, <= instrlen */
 };
 
+extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
 extern void alternative_instructions(void);
 
 #define OLDINSTR(oldinstr)      "661:\n\t" oldinstr "\n662:\n"