]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
x86/paravirt: Use relative reference for the original instruction offset
authorHou Wenlong <houwenlong.hwl@antgroup.com>
Fri, 9 Jun 2023 09:45:31 +0000 (17:45 +0800)
committerBorislav Petkov (AMD) <bp@alien8.de>
Mon, 13 Nov 2023 11:23:27 +0000 (12:23 +0100)
Similar to the alternative patching, use a relative reference for original
instruction offset rather than absolute one, which saves 8 bytes for one
PARA_SITE entry on x86_64.  As a result, a R_X86_64_PC32 relocation is
generated instead of an R_X86_64_64 one, which also reduces relocation
metadata on relocatable builds. Hardcode the alignment to 4 now.

  [ bp: Massage commit message. ]

Signed-off-by: Hou Wenlong <houwenlong.hwl@antgroup.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Juergen Gross <jgross@suse.com>
Link: https://lore.kernel.org/r/9e6053107fbaabc0d33e5d2865c5af2c67ec9925.1686301237.git.houwenlong.hwl@antgroup.com
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/kernel/alternative.c
arch/x86/kernel/callthunks.c

index 6c8ff12140aea9a860ccd229c1bf74acc7948b07..d9384e9d97f6284e9dde27ec127bf9677548d903 100644 (file)
@@ -743,16 +743,16 @@ void native_pv_lock_init(void) __init;
 
 #else  /* __ASSEMBLY__ */
 
-#define _PVSITE(ptype, ops, word, algn)                \
+#define _PVSITE(ptype, ops)                    \
 771:;                                          \
        ops;                                    \
 772:;                                          \
        .pushsection .parainstructions,"a";     \
-        .align algn;                           \
-        word 771b;                             \
+        .align 4;                              \
+        .long 771b-.;                          \
         .byte ptype;                           \
         .byte 772b-771b;                       \
-        _ASM_ALIGN;                            \
+        .align 4;                              \
        .popsection
 
 
@@ -760,7 +760,7 @@ void native_pv_lock_init(void) __init;
 #ifdef CONFIG_PARAVIRT_XXL
 
 #define PARA_PATCH(off)                ((off) / 8)
-#define PARA_SITE(ptype, ops)  _PVSITE(ptype, ops, .quad, 8)
+#define PARA_SITE(ptype, ops)  _PVSITE(ptype, ops)
 #define PARA_INDIRECT(addr)    *addr(%rip)
 
 #ifdef CONFIG_DEBUG_ENTRY
index 772d03487520e595ba458ae9032f8a0a2dc00101..e1bfb719fca339175f39acd0f1dda51a53a30ca6 100644 (file)
@@ -5,7 +5,7 @@
 #ifndef __ASSEMBLY__
 /* These all sit in the .parainstructions section to tell us what to patch. */
 struct paravirt_patch_site {
-       u8 *instr;              /* original instructions */
+       s32 instr_offset;       /* original instructions */
        u8 type;                /* type of this instruction */
        u8 len;                 /* length of original instruction */
 };
@@ -263,11 +263,11 @@ extern struct paravirt_patch_template pv_ops;
 #define _paravirt_alt(insn_string, type)               \
        "771:\n\t" insn_string "\n" "772:\n"            \
        ".pushsection .parainstructions,\"a\"\n"        \
-       _ASM_ALIGN "\n"                                 \
-       _ASM_PTR " 771b\n"                              \
+       "  .align 4\n"                                  \
+       "  .long 771b-.\n"                              \
        "  .byte " type "\n"                            \
        "  .byte 772b-771b\n"                           \
-       _ASM_ALIGN "\n"                                 \
+       "  .align 4\n"                                  \
        ".popsection\n"
 
 /* Generate patchable code, with the default asm parameters. */
index 73be3931e4f0608315093495259100e915702be7..be35c8ccf8267b874ca691874440cab799968e9f 100644 (file)
@@ -1431,20 +1431,22 @@ void __init_or_module apply_paravirt(struct paravirt_patch_site *start,
 {
        struct paravirt_patch_site *p;
        char insn_buff[MAX_PATCH_LEN];
+       u8 *instr;
 
        for (p = start; p < end; p++) {
                unsigned int used;
 
+               instr = (u8 *)&p->instr_offset + p->instr_offset;
                BUG_ON(p->len > MAX_PATCH_LEN);
                /* prep the buffer with the original instructions */
-               memcpy(insn_buff, p->instr, p->len);
-               used = paravirt_patch(p->type, insn_buff, (unsigned long)p->instr, p->len);
+               memcpy(insn_buff, instr, p->len);
+               used = paravirt_patch(p->type, insn_buff, (unsigned long)instr, p->len);
 
                BUG_ON(used > p->len);
 
                /* Pad the rest with nops */
                add_nops(insn_buff + used, p->len - used);
-               text_poke_early(p->instr, insn_buff, p->len);
+               text_poke_early(instr, insn_buff, p->len);
        }
 }
 extern struct paravirt_patch_site __start_parainstructions[],
index e9ad518a5003cdcb714fb111158549052fb38a5f..57e5c2e75c2a7953953bac9ee9f79b8ff4dc6995 100644 (file)
@@ -240,7 +240,7 @@ patch_paravirt_call_sites(struct paravirt_patch_site *start,
        struct paravirt_patch_site *p;
 
        for (p = start; p < end; p++)
-               patch_call(p->instr, ct);
+               patch_call((void *)&p->instr_offset + p->instr_offset, ct);
 }
 
 static __init_or_module void