2023-10-19 09:16:07

by Juergen Gross

[permalink] [raw]
Subject: [PATCH v3 0/5] x86/paravirt: Get rid of paravirt patching

This is a small series getting rid of paravirt patching by switching
completely to alternative patching for the same functionality.

The basic idea is to add the capability to switch from indirect to
direct calls via a special alternative patching option.

This removes _some_ of the paravirt macro maze, but most of it needs
to stay due to the need of hiding the call instructions from the
compiler in order to avoid needless register save/restore.

What is going away is the nasty stacking of alternative and paravirt
patching and (of course) the special .parainstructions linker section.

I have tested the series on bare metal and as Xen PV domain to still
work.

Note that objtool might need some changes to cope with the new
indirect call patching mechanism. Additionally some paravirt handling
can probably be removed from it.

Changes in V3:
- split v2 patch 3 into 2 patches as requested by Peter and Ingo

Changes in V2:
- split last patch into 2
- rebase of patch 2 as suggested by Peter
- addressed Peter's comments for patch 3

Juergen Gross (5):
x86/paravirt: move some functions and defines to alternative
x86/alternative: add indirect call patching
x86/paravirt: introduce ALT_NOT_XEN
x86/paravirt: switch mixed paravirt/alternative calls to alternative_2
x86/paravirt: remove no longer needed paravirt patching code

arch/x86/include/asm/alternative.h | 26 ++++-
arch/x86/include/asm/paravirt.h | 79 +++++----------
arch/x86/include/asm/paravirt_types.h | 73 +++-----------
arch/x86/include/asm/qspinlock_paravirt.h | 4 +-
arch/x86/include/asm/text-patching.h | 12 ---
arch/x86/kernel/alternative.c | 116 ++++++++++------------
arch/x86/kernel/callthunks.c | 17 ++--
arch/x86/kernel/kvm.c | 4 +-
arch/x86/kernel/module.c | 20 +---
arch/x86/kernel/paravirt.c | 54 ++--------
arch/x86/kernel/vmlinux.lds.S | 13 ---
arch/x86/tools/relocs.c | 2 +-
arch/x86/xen/irq.c | 2 +-
13 files changed, 137 insertions(+), 285 deletions(-)

--
2.35.3


2023-10-19 09:16:10

by Juergen Gross

[permalink] [raw]
Subject: [PATCH v3 1/5] x86/paravirt: move some functions and defines to alternative

As a preparation for replacing paravirt patching completely by
alternative patching, move some backend functions and #defines to
alternative code and header.

Signed-off-by: Juergen Gross <[email protected]>
Acked-by: Peter Zijlstra (Intel) <[email protected]>
---
arch/x86/include/asm/alternative.h | 16 ++++++++++++
arch/x86/include/asm/paravirt.h | 12 ---------
arch/x86/include/asm/paravirt_types.h | 4 +--
arch/x86/include/asm/qspinlock_paravirt.h | 4 +--
arch/x86/kernel/alternative.c | 10 ++++++++
arch/x86/kernel/kvm.c | 4 +--
arch/x86/kernel/paravirt.c | 30 +++++++----------------
arch/x86/xen/irq.c | 2 +-
8 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index 9c4da699e11a..67e50bd40bb8 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -330,6 +330,22 @@ static inline int alternatives_text_reserved(void *start, void *end)
*/
#define ASM_NO_INPUT_CLOBBER(clbr...) "i" (0) : clbr

+/* Macro for creating assembler functions avoiding any C magic. */
+#define DEFINE_ASM_FUNC(func, instr, sec) \
+ asm (".pushsection " #sec ", \"ax\"\n" \
+ ".global " #func "\n\t" \
+ ".type " #func ", @function\n\t" \
+ ASM_FUNC_ALIGN "\n" \
+ #func ":\n\t" \
+ ASM_ENDBR \
+ instr "\n\t" \
+ ASM_RET \
+ ".size " #func ", . - " #func "\n\t" \
+ ".popsection")
+
+void x86_BUG(void);
+void x86_nop(void);
+
#else /* __ASSEMBLY__ */

#ifdef CONFIG_SMP
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index 6c8ff12140ae..ed5c7342f2ef 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -726,18 +726,6 @@ static __always_inline unsigned long arch_local_irq_save(void)
#undef PVOP_VCALL4
#undef PVOP_CALL4

-#define DEFINE_PARAVIRT_ASM(func, instr, sec) \
- asm (".pushsection " #sec ", \"ax\"\n" \
- ".global " #func "\n\t" \
- ".type " #func ", @function\n\t" \
- ASM_FUNC_ALIGN "\n" \
- #func ":\n\t" \
- ASM_ENDBR \
- instr "\n\t" \
- ASM_RET \
- ".size " #func ", . - " #func "\n\t" \
- ".popsection")
-
extern void default_banner(void);
void native_pv_lock_init(void) __init;

diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 772d03487520..9f84dc074f88 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -542,8 +542,6 @@ int paravirt_disable_iospace(void);
__PVOP_VCALL(op, PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \
PVOP_CALL_ARG3(arg3), PVOP_CALL_ARG4(arg4))

-void _paravirt_nop(void);
-void paravirt_BUG(void);
unsigned long paravirt_ret0(void);
#ifdef CONFIG_PARAVIRT_XXL
u64 _paravirt_ident_64(u64);
@@ -553,7 +551,7 @@ void pv_native_irq_enable(void);
unsigned long pv_native_read_cr2(void);
#endif

-#define paravirt_nop ((void *)_paravirt_nop)
+#define paravirt_nop ((void *)x86_nop)

extern struct paravirt_patch_site __parainstructions[],
__parainstructions_end[];
diff --git a/arch/x86/include/asm/qspinlock_paravirt.h b/arch/x86/include/asm/qspinlock_paravirt.h
index 85b6e3609cb9..ef9697f20129 100644
--- a/arch/x86/include/asm/qspinlock_paravirt.h
+++ b/arch/x86/include/asm/qspinlock_paravirt.h
@@ -56,8 +56,8 @@ __PV_CALLEE_SAVE_REGS_THUNK(__pv_queued_spin_unlock_slowpath, ".spinlock.text");
"pop %rdx\n\t" \
FRAME_END

-DEFINE_PARAVIRT_ASM(__raw_callee_save___pv_queued_spin_unlock,
- PV_UNLOCK_ASM, .spinlock.text);
+DEFINE_ASM_FUNC(__raw_callee_save___pv_queued_spin_unlock,
+ PV_UNLOCK_ASM, .spinlock.text);

#else /* CONFIG_64BIT */

diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 73be3931e4f0..1c8dd8e05f3f 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -385,6 +385,16 @@ apply_relocation(u8 *buf, size_t len, u8 *dest, u8 *src, size_t src_len)
}
}

+/* Low-level backend functions usable from alternative code replacements. */
+DEFINE_ASM_FUNC(x86_nop, "", .entry.text);
+EXPORT_SYMBOL_GPL(x86_nop);
+
+noinstr void x86_BUG(void)
+{
+ BUG();
+}
+EXPORT_SYMBOL_GPL(x86_BUG);
+
/*
* Replace instructions with better alternatives for this CPU type. This runs
* before SMP is initialized to avoid SMP problems with self modifying code.
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index b8ab9ee5896c..4ca59dccc15a 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -803,8 +803,8 @@ extern bool __raw_callee_save___kvm_vcpu_is_preempted(long);
"cmpb $0, " __stringify(KVM_STEAL_TIME_preempted) "+steal_time(%rax)\n\t" \
"setne %al\n\t"

-DEFINE_PARAVIRT_ASM(__raw_callee_save___kvm_vcpu_is_preempted,
- PV_VCPU_PREEMPTED_ASM, .text);
+DEFINE_ASM_FUNC(__raw_callee_save___kvm_vcpu_is_preempted,
+ PV_VCPU_PREEMPTED_ASM, .text);
#endif

static void __init kvm_guest_init(void)
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 97f1436c1a20..32792b033de2 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -34,14 +34,8 @@
#include <asm/io_bitmap.h>
#include <asm/gsseg.h>

-/*
- * nop stub, which must not clobber anything *including the stack* to
- * avoid confusing the entry prologues.
- */
-DEFINE_PARAVIRT_ASM(_paravirt_nop, "", .entry.text);
-
/* stub always returning 0. */
-DEFINE_PARAVIRT_ASM(paravirt_ret0, "xor %eax,%eax", .entry.text);
+DEFINE_ASM_FUNC(paravirt_ret0, "xor %eax,%eax", .entry.text);

void __init default_banner(void)
{
@@ -49,12 +43,6 @@ void __init default_banner(void)
pv_info.name);
}

-/* Undefined instruction for dealing with missing ops pointers. */
-noinstr void paravirt_BUG(void)
-{
- BUG();
-}
-
static unsigned paravirt_patch_call(void *insn_buff, const void *target,
unsigned long addr, unsigned len)
{
@@ -64,11 +52,11 @@ static unsigned paravirt_patch_call(void *insn_buff, const void *target,
}

#ifdef CONFIG_PARAVIRT_XXL
-DEFINE_PARAVIRT_ASM(_paravirt_ident_64, "mov %rdi, %rax", .text);
-DEFINE_PARAVIRT_ASM(pv_native_save_fl, "pushf; pop %rax", .noinstr.text);
-DEFINE_PARAVIRT_ASM(pv_native_irq_disable, "cli", .noinstr.text);
-DEFINE_PARAVIRT_ASM(pv_native_irq_enable, "sti", .noinstr.text);
-DEFINE_PARAVIRT_ASM(pv_native_read_cr2, "mov %cr2, %rax", .noinstr.text);
+DEFINE_ASM_FUNC(_paravirt_ident_64, "mov %rdi, %rax", .text);
+DEFINE_ASM_FUNC(pv_native_save_fl, "pushf; pop %rax", .noinstr.text);
+DEFINE_ASM_FUNC(pv_native_irq_disable, "cli", .noinstr.text);
+DEFINE_ASM_FUNC(pv_native_irq_enable, "sti", .noinstr.text);
+DEFINE_ASM_FUNC(pv_native_read_cr2, "mov %cr2, %rax", .noinstr.text);
#endif

DEFINE_STATIC_KEY_TRUE(virt_spin_lock_key);
@@ -96,9 +84,9 @@ unsigned int paravirt_patch(u8 type, void *insn_buff, unsigned long addr,
unsigned ret;

if (opfunc == NULL)
- /* If there's no function, patch it with paravirt_BUG() */
- ret = paravirt_patch_call(insn_buff, paravirt_BUG, addr, len);
- else if (opfunc == _paravirt_nop)
+ /* If there's no function, patch it with x86_BUG() */
+ ret = paravirt_patch_call(insn_buff, x86_BUG, addr, len);
+ else if (opfunc == x86_nop)
ret = 0;
else
/* Otherwise call the function. */
diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c
index 6092fea7d651..5d132f5a5d7d 100644
--- a/arch/x86/xen/irq.c
+++ b/arch/x86/xen/irq.c
@@ -45,7 +45,7 @@ static const typeof(pv_ops) xen_irq_ops __initconst = {
/* Initial interrupt flag handling only called while interrupts off. */
.save_fl = __PV_IS_CALLEE_SAVE(paravirt_ret0),
.irq_disable = __PV_IS_CALLEE_SAVE(paravirt_nop),
- .irq_enable = __PV_IS_CALLEE_SAVE(paravirt_BUG),
+ .irq_enable = __PV_IS_CALLEE_SAVE(x86_BUG),

.safe_halt = xen_safe_halt,
.halt = xen_halt,
--
2.35.3

2023-10-19 09:16:23

by Juergen Gross

[permalink] [raw]
Subject: [PATCH v3 3/5] x86/paravirt: introduce ALT_NOT_XEN

Introduce the macro ALT_NOT_XEN as a short form of
ALT_NOT(X86_FEATURE_XENPV).

Suggested-by: Peter Zijlstra (Intel) <[email protected]>
Signed-off-by: Juergen Gross <[email protected]>
---
V3:
- split off from next patch
---
arch/x86/include/asm/paravirt.h | 42 ++++++++++++---------------
arch/x86/include/asm/paravirt_types.h | 3 ++
2 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index ed5c7342f2ef..3749311d51c3 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -142,8 +142,7 @@ static inline void write_cr0(unsigned long x)
static __always_inline unsigned long read_cr2(void)
{
return PVOP_ALT_CALLEE0(unsigned long, mmu.read_cr2,
- "mov %%cr2, %%rax;",
- ALT_NOT(X86_FEATURE_XENPV));
+ "mov %%cr2, %%rax;", ALT_NOT_XEN);
}

static __always_inline void write_cr2(unsigned long x)
@@ -154,13 +153,12 @@ static __always_inline void write_cr2(unsigned long x)
static inline unsigned long __read_cr3(void)
{
return PVOP_ALT_CALL0(unsigned long, mmu.read_cr3,
- "mov %%cr3, %%rax;", ALT_NOT(X86_FEATURE_XENPV));
+ "mov %%cr3, %%rax;", ALT_NOT_XEN);
}

static inline void write_cr3(unsigned long x)
{
- PVOP_ALT_VCALL1(mmu.write_cr3, x,
- "mov %%rdi, %%cr3", ALT_NOT(X86_FEATURE_XENPV));
+ PVOP_ALT_VCALL1(mmu.write_cr3, x, "mov %%rdi, %%cr3", ALT_NOT_XEN);
}

static inline void __write_cr4(unsigned long x)
@@ -182,7 +180,7 @@ extern noinstr void pv_native_wbinvd(void);

static __always_inline void wbinvd(void)
{
- PVOP_ALT_VCALL0(cpu.wbinvd, "wbinvd", ALT_NOT(X86_FEATURE_XENPV));
+ PVOP_ALT_VCALL0(cpu.wbinvd, "wbinvd", ALT_NOT_XEN);
}

static inline u64 paravirt_read_msr(unsigned msr)
@@ -390,27 +388,25 @@ static inline void paravirt_release_p4d(unsigned long pfn)
static inline pte_t __pte(pteval_t val)
{
return (pte_t) { PVOP_ALT_CALLEE1(pteval_t, mmu.make_pte, val,
- "mov %%rdi, %%rax",
- ALT_NOT(X86_FEATURE_XENPV)) };
+ "mov %%rdi, %%rax", ALT_NOT_XEN) };
}

static inline pteval_t pte_val(pte_t pte)
{
return PVOP_ALT_CALLEE1(pteval_t, mmu.pte_val, pte.pte,
- "mov %%rdi, %%rax", ALT_NOT(X86_FEATURE_XENPV));
+ "mov %%rdi, %%rax", ALT_NOT_XEN);
}

static inline pgd_t __pgd(pgdval_t val)
{
return (pgd_t) { PVOP_ALT_CALLEE1(pgdval_t, mmu.make_pgd, val,
- "mov %%rdi, %%rax",
- ALT_NOT(X86_FEATURE_XENPV)) };
+ "mov %%rdi, %%rax", ALT_NOT_XEN) };
}

static inline pgdval_t pgd_val(pgd_t pgd)
{
return PVOP_ALT_CALLEE1(pgdval_t, mmu.pgd_val, pgd.pgd,
- "mov %%rdi, %%rax", ALT_NOT(X86_FEATURE_XENPV));
+ "mov %%rdi, %%rax", ALT_NOT_XEN);
}

#define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION
@@ -444,14 +440,13 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
static inline pmd_t __pmd(pmdval_t val)
{
return (pmd_t) { PVOP_ALT_CALLEE1(pmdval_t, mmu.make_pmd, val,
- "mov %%rdi, %%rax",
- ALT_NOT(X86_FEATURE_XENPV)) };
+ "mov %%rdi, %%rax", ALT_NOT_XEN) };
}

static inline pmdval_t pmd_val(pmd_t pmd)
{
return PVOP_ALT_CALLEE1(pmdval_t, mmu.pmd_val, pmd.pmd,
- "mov %%rdi, %%rax", ALT_NOT(X86_FEATURE_XENPV));
+ "mov %%rdi, %%rax", ALT_NOT_XEN);
}

static inline void set_pud(pud_t *pudp, pud_t pud)
@@ -464,7 +459,7 @@ static inline pud_t __pud(pudval_t val)
pudval_t ret;

ret = PVOP_ALT_CALLEE1(pudval_t, mmu.make_pud, val,
- "mov %%rdi, %%rax", ALT_NOT(X86_FEATURE_XENPV));
+ "mov %%rdi, %%rax", ALT_NOT_XEN);

return (pud_t) { ret };
}
@@ -472,7 +467,7 @@ static inline pud_t __pud(pudval_t val)
static inline pudval_t pud_val(pud_t pud)
{
return PVOP_ALT_CALLEE1(pudval_t, mmu.pud_val, pud.pud,
- "mov %%rdi, %%rax", ALT_NOT(X86_FEATURE_XENPV));
+ "mov %%rdi, %%rax", ALT_NOT_XEN);
}

static inline void pud_clear(pud_t *pudp)
@@ -492,8 +487,7 @@ static inline void set_p4d(p4d_t *p4dp, p4d_t p4d)
static inline p4d_t __p4d(p4dval_t val)
{
p4dval_t ret = PVOP_ALT_CALLEE1(p4dval_t, mmu.make_p4d, val,
- "mov %%rdi, %%rax",
- ALT_NOT(X86_FEATURE_XENPV));
+ "mov %%rdi, %%rax", ALT_NOT_XEN);

return (p4d_t) { ret };
}
@@ -501,7 +495,7 @@ static inline p4d_t __p4d(p4dval_t val)
static inline p4dval_t p4d_val(p4d_t p4d)
{
return PVOP_ALT_CALLEE1(p4dval_t, mmu.p4d_val, p4d.p4d,
- "mov %%rdi, %%rax", ALT_NOT(X86_FEATURE_XENPV));
+ "mov %%rdi, %%rax", ALT_NOT_XEN);
}

static inline void __set_pgd(pgd_t *pgdp, pgd_t pgd)
@@ -687,17 +681,17 @@ bool __raw_callee_save___native_vcpu_is_preempted(long cpu);
static __always_inline unsigned long arch_local_save_flags(void)
{
return PVOP_ALT_CALLEE0(unsigned long, irq.save_fl, "pushf; pop %%rax;",
- ALT_NOT(X86_FEATURE_XENPV));
+ ALT_NOT_XEN);
}

static __always_inline void arch_local_irq_disable(void)
{
- PVOP_ALT_VCALLEE0(irq.irq_disable, "cli;", ALT_NOT(X86_FEATURE_XENPV));
+ PVOP_ALT_VCALLEE0(irq.irq_disable, "cli;", ALT_NOT_XEN);
}

static __always_inline void arch_local_irq_enable(void)
{
- PVOP_ALT_VCALLEE0(irq.irq_enable, "sti;", ALT_NOT(X86_FEATURE_XENPV));
+ PVOP_ALT_VCALLEE0(irq.irq_enable, "sti;", ALT_NOT_XEN);
}

static __always_inline unsigned long arch_local_irq_save(void)
@@ -759,7 +753,7 @@ void native_pv_lock_init(void) __init;
.endm

#define SAVE_FLAGS ALTERNATIVE "PARA_IRQ_save_fl;", "pushf; pop %rax;", \
- ALT_NOT(X86_FEATURE_XENPV)
+ ALT_NOT_XEN
#endif
#endif /* CONFIG_PARAVIRT_XXL */
#endif /* CONFIG_X86_64 */
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 9f84dc074f88..e99db1360d2a 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -557,5 +557,8 @@ extern struct paravirt_patch_site __parainstructions[],
__parainstructions_end[];

#endif /* __ASSEMBLY__ */
+
+#define ALT_NOT_XEN ALT_NOT(X86_FEATURE_XENPV)
+
#endif /* CONFIG_PARAVIRT */
#endif /* _ASM_X86_PARAVIRT_TYPES_H */
--
2.35.3

2023-10-19 09:16:41

by Juergen Gross

[permalink] [raw]
Subject: [PATCH v3 4/5] x86/paravirt: switch mixed paravirt/alternative calls to alternative_2

Instead of stacking alternative and paravirt patching, use the new
ALT_FLAG_CALL flag to switch those mixed calls to pure alternative
handling.

This eliminates the need to be careful regarding the sequence of
alternative and paravirt patching.

For call depth tracking callthunks_setup() needs to be adapted to patch
calls at alternative patching sites instead of paravirt calls.

Signed-off-by: Juergen Gross <[email protected]>
Acked-by: Peter Zijlstra (Intel) <[email protected]>
---
arch/x86/include/asm/alternative.h | 5 +++--
arch/x86/include/asm/paravirt.h | 9 ++++++---
arch/x86/include/asm/paravirt_types.h | 26 +++++++++-----------------
arch/x86/kernel/callthunks.c | 17 ++++++++---------
arch/x86/kernel/module.c | 20 +++++---------------
5 files changed, 31 insertions(+), 46 deletions(-)

diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index dd63b96577e9..f6c0ff678e2e 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -89,6 +89,8 @@ struct alt_instr {
u8 replacementlen; /* length of new instruction */
} __packed;

+extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
+
/*
* Debug flag that can be tested to see whether alternative
* instructions were patched in already:
@@ -104,11 +106,10 @@ extern void apply_fineibt(s32 *start_retpoline, s32 *end_retpoine,
s32 *start_cfi, s32 *end_cfi);

struct module;
-struct paravirt_patch_site;

struct callthunk_sites {
s32 *call_start, *call_end;
- struct paravirt_patch_site *pv_start, *pv_end;
+ struct alt_instr *alt_start, *alt_end;
};

#ifdef CONFIG_CALL_THUNKS
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index 3749311d51c3..9c6c5cfa9fe2 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -740,20 +740,23 @@ void native_pv_lock_init(void) __init;

#ifdef CONFIG_X86_64
#ifdef CONFIG_PARAVIRT_XXL
+#ifdef CONFIG_DEBUG_ENTRY

#define PARA_PATCH(off) ((off) / 8)
#define PARA_SITE(ptype, ops) _PVSITE(ptype, ops, .quad, 8)
#define PARA_INDIRECT(addr) *addr(%rip)

-#ifdef CONFIG_DEBUG_ENTRY
.macro PARA_IRQ_save_fl
PARA_SITE(PARA_PATCH(PV_IRQ_save_fl),
ANNOTATE_RETPOLINE_SAFE;
call PARA_INDIRECT(pv_ops+PV_IRQ_save_fl);)
+ ANNOTATE_RETPOLINE_SAFE;
+ call PARA_INDIRECT(pv_ops+PV_IRQ_save_fl);
.endm

-#define SAVE_FLAGS ALTERNATIVE "PARA_IRQ_save_fl;", "pushf; pop %rax;", \
- ALT_NOT_XEN
+#define SAVE_FLAGS ALTERNATIVE_2 "PARA_IRQ_save_fl;", \
+ ALT_CALL_INSTR, ALT_CALL_ALWAYS, \
+ "pushf; pop %rax;", ALT_NOT_XEN
#endif
#endif /* CONFIG_PARAVIRT_XXL */
#endif /* CONFIG_X86_64 */
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index e99db1360d2a..323dca625eea 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -278,15 +278,11 @@ extern struct paravirt_patch_template pv_ops;
#define NATIVE_LABEL(a,x,b) "\n\t.globl " a #x "_" #b "\n" a #x "_" #b ":\n\t"

unsigned int paravirt_patch(u8 type, void *insn_buff, unsigned long addr, unsigned int len);
+#define paravirt_ptr(op) [paravirt_opptr] "m" (pv_ops.op)

int paravirt_disable_iospace(void);

-/*
- * This generates an indirect call based on the operation type number.
- * The type number, computed in PARAVIRT_PATCH, is derived from the
- * offset into the paravirt_patch_template structure, and can therefore be
- * freely converted back into a structure offset.
- */
+/* This generates an indirect call based on the operation type number. */
#define PARAVIRT_CALL \
ANNOTATE_RETPOLINE_SAFE \
"call *%[paravirt_opptr];"
@@ -319,12 +315,6 @@ int paravirt_disable_iospace(void);
* However, x86_64 also has to clobber all caller saved registers, which
* unfortunately, are quite a bit (r8 - r11)
*
- * The call instruction itself is marked by placing its start address
- * and size into the .parainstructions section, so that
- * apply_paravirt() in arch/i386/kernel/alternative.c can do the
- * appropriate patching under the control of the backend pv_init_ops
- * implementation.
- *
* Unfortunately there's no way to get gcc to generate the args setup
* for the call, and then allow the call itself to be generated by an
* inline asm. Because of this, we must do the complete arg setup and
@@ -428,9 +418,10 @@ int paravirt_disable_iospace(void);
({ \
PVOP_CALL_ARGS; \
PVOP_TEST_NULL(op); \
- asm volatile(paravirt_alt(PARAVIRT_CALL) \
+ asm volatile(ALTERNATIVE(PARAVIRT_CALL, ALT_CALL_INSTR, \
+ ALT_CALL_ALWAYS) \
: call_clbr, ASM_CALL_CONSTRAINT \
- : paravirt_type(op), \
+ : paravirt_ptr(op), \
##__VA_ARGS__ \
: "memory", "cc" extra_clbr); \
ret; \
@@ -441,10 +432,11 @@ int paravirt_disable_iospace(void);
({ \
PVOP_CALL_ARGS; \
PVOP_TEST_NULL(op); \
- asm volatile(ALTERNATIVE(paravirt_alt(PARAVIRT_CALL), \
- alt, cond) \
+ asm volatile(ALTERNATIVE_2(PARAVIRT_CALL, \
+ ALT_CALL_INSTR, ALT_CALL_ALWAYS, \
+ alt, cond) \
: call_clbr, ASM_CALL_CONSTRAINT \
- : paravirt_type(op), \
+ : paravirt_ptr(op), \
##__VA_ARGS__ \
: "memory", "cc" extra_clbr); \
ret; \
diff --git a/arch/x86/kernel/callthunks.c b/arch/x86/kernel/callthunks.c
index faa9f2299848..200ea8087ddb 100644
--- a/arch/x86/kernel/callthunks.c
+++ b/arch/x86/kernel/callthunks.c
@@ -238,14 +238,13 @@ patch_call_sites(s32 *start, s32 *end, const struct core_text *ct)
}

static __init_or_module void
-patch_paravirt_call_sites(struct paravirt_patch_site *start,
- struct paravirt_patch_site *end,
- const struct core_text *ct)
+patch_alt_call_sites(struct alt_instr *start, struct alt_instr *end,
+ const struct core_text *ct)
{
- struct paravirt_patch_site *p;
+ struct alt_instr *a;

- for (p = start; p < end; p++)
- patch_call(p->instr, ct);
+ for (a = start; a < end; a++)
+ patch_call((u8 *)&a->instr_offset + a->instr_offset, ct);
}

static __init_or_module void
@@ -253,7 +252,7 @@ callthunks_setup(struct callthunk_sites *cs, const struct core_text *ct)
{
prdbg("Patching call sites %s\n", ct->name);
patch_call_sites(cs->call_start, cs->call_end, ct);
- patch_paravirt_call_sites(cs->pv_start, cs->pv_end, ct);
+ patch_alt_call_sites(cs->alt_start, cs->alt_end, ct);
prdbg("Patching call sites done%s\n", ct->name);
}

@@ -262,8 +261,8 @@ void __init callthunks_patch_builtin_calls(void)
struct callthunk_sites cs = {
.call_start = __call_sites,
.call_end = __call_sites_end,
- .pv_start = __parainstructions,
- .pv_end = __parainstructions_end
+ .alt_start = __alt_instructions,
+ .alt_end = __alt_instructions_end
};

if (!cpu_feature_enabled(X86_FEATURE_CALL_DEPTH))
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index 5f71a0cf4399..e18914c0e38a 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -276,7 +276,7 @@ int module_finalize(const Elf_Ehdr *hdr,
struct module *me)
{
const Elf_Shdr *s, *alt = NULL, *locks = NULL,
- *para = NULL, *orc = NULL, *orc_ip = NULL,
+ *orc = NULL, *orc_ip = NULL,
*retpolines = NULL, *returns = NULL, *ibt_endbr = NULL,
*calls = NULL, *cfi = NULL;
char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
@@ -286,8 +286,6 @@ int module_finalize(const Elf_Ehdr *hdr,
alt = s;
if (!strcmp(".smp_locks", secstrings + s->sh_name))
locks = s;
- if (!strcmp(".parainstructions", secstrings + s->sh_name))
- para = s;
if (!strcmp(".orc_unwind", secstrings + s->sh_name))
orc = s;
if (!strcmp(".orc_unwind_ip", secstrings + s->sh_name))
@@ -304,14 +302,6 @@ int module_finalize(const Elf_Ehdr *hdr,
ibt_endbr = s;
}

- /*
- * See alternative_instructions() for the ordering rules between the
- * various patching types.
- */
- if (para) {
- void *pseg = (void *)para->sh_addr;
- apply_paravirt(pseg, pseg + para->sh_size);
- }
if (retpolines || cfi) {
void *rseg = NULL, *cseg = NULL;
unsigned int rsize = 0, csize = 0;
@@ -341,7 +331,7 @@ int module_finalize(const Elf_Ehdr *hdr,
void *aseg = (void *)alt->sh_addr;
apply_alternatives(aseg, aseg + alt->sh_size);
}
- if (calls || para) {
+ if (calls || alt) {
struct callthunk_sites cs = {};

if (calls) {
@@ -349,9 +339,9 @@ int module_finalize(const Elf_Ehdr *hdr,
cs.call_end = (void *)calls->sh_addr + calls->sh_size;
}

- if (para) {
- cs.pv_start = (void *)para->sh_addr;
- cs.pv_end = (void *)para->sh_addr + para->sh_size;
+ if (alt) {
+ cs.alt_start = (void *)alt->sh_addr;
+ cs.alt_end = (void *)alt->sh_addr + alt->sh_size;
}

callthunks_patch_module_calls(&cs, me);
--
2.35.3

2023-10-19 09:16:56

by Juergen Gross

[permalink] [raw]
Subject: [PATCH v3 2/5] x86/alternative: add indirect call patching

In order to prepare replacing of paravirt patching with alternative
patching, add the capability to replace an indirect call with a direct
one to alternative patching.

This is done via a new flag ALT_FLAG_CALL as the target of the call
instruction needs to be evaluated using the value of the location
addressed by the indirect call. For convenience add a macro for a
default call instruction. In case it is being used without the new
flag being set, it will result in a BUG() when being executed. As in
most cases the feature used will be X86_FEATURE_ALWAYS add another
macro ALT_CALL_ALWAYS usable for the flags parameter of the ALTERNATIVE
macros.

For a complete replacement handle the special cases of calling a nop
function and an indirect call of NULL the same way as paravirt does.

Signed-off-by: Juergen Gross <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
---
arch/x86/include/asm/alternative.h | 5 ++++
arch/x86/kernel/alternative.c | 40 ++++++++++++++++++++++++++++++
2 files changed, 45 insertions(+)

diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index 67e50bd40bb8..dd63b96577e9 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -10,6 +10,9 @@

#define ALT_FLAG_NOT (1 << 0)
#define ALT_NOT(feature) ((ALT_FLAG_NOT << ALT_FLAGS_SHIFT) | (feature))
+#define ALT_FLAG_CALL (1 << 1)
+#define ALT_CALL(feature) ((ALT_FLAG_CALL << ALT_FLAGS_SHIFT) | (feature))
+#define ALT_CALL_ALWAYS ALT_CALL(X86_FEATURE_ALWAYS)

#ifndef __ASSEMBLY__

@@ -150,6 +153,8 @@ static inline int alternatives_text_reserved(void *start, void *end)
}
#endif /* CONFIG_SMP */

+#define ALT_CALL_INSTR "call x86_BUG"
+
#define b_replacement(num) "664"#num
#define e_replacement(num) "665"#num

diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 1c8dd8e05f3f..01b89a10d219 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -395,6 +395,40 @@ noinstr void x86_BUG(void)
}
EXPORT_SYMBOL_GPL(x86_BUG);

+/*
+ * Rewrite the "call x86_BUG" replacement to point to the target of the
+ * indirect pv_ops call "call *disp(%ip)".
+ */
+static int alt_replace_call(u8 *instr, u8 *insn_buff, struct alt_instr *a)
+{
+ void *target, *bug = &x86_BUG;
+
+ if (a->replacementlen != 5 || insn_buff[0] != CALL_INSN_OPCODE) {
+ pr_err("Alternative: ALT_FLAG_CALL set for a non-call replacement instruction\n");
+ pr_err(" Ignoring the flag for the instruction at %pS (%px)\n", instr, instr);
+ return 5;
+ }
+
+ if (a->instrlen != 6 || instr[0] != 0xff || instr[1] != 0x15) {
+ pr_err("Alternative: ALT_FLAG_CALL set for unrecognized indirect call\n");
+ pr_err(" Not replacing the instruction at %pS (%px)\n", instr, instr);
+ return -1;
+ }
+
+ /* ff 15 00 00 00 00 call *0x0(%rip) */
+ target = *(void **)(instr + a->instrlen + *(s32 *)(instr + 2));
+ if (!target)
+ target = bug;
+
+ /* (x86_BUG - .) + (target - x86_BUG) := target - . */
+ *(s32 *)(insn_buff + 1) += target - bug;
+
+ if (target == &x86_nop)
+ return 0;
+
+ return 5;
+}
+
/*
* Replace instructions with better alternatives for this CPU type. This runs
* before SMP is initialized to avoid SMP problems with self modifying code.
@@ -462,6 +496,12 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
memcpy(insn_buff, replacement, a->replacementlen);
insn_buff_sz = a->replacementlen;

+ if (a->flags & ALT_FLAG_CALL) {
+ insn_buff_sz = alt_replace_call(instr, insn_buff, a);
+ if (insn_buff_sz < 0)
+ continue;
+ }
+
for (; insn_buff_sz < a->instrlen; insn_buff_sz++)
insn_buff[insn_buff_sz] = 0x90;

--
2.35.3

2023-10-19 09:16:58

by Juergen Gross

[permalink] [raw]
Subject: [PATCH v3 5/5] x86/paravirt: remove no longer needed paravirt patching code

Now that paravirt is using the alternatives patching infrastructure,
remove the paravirt patching code.

Signed-off-by: Juergen Gross <[email protected]>
Acked-by: Peter Zijlstra (Intel) <[email protected]>
---
arch/x86/include/asm/paravirt.h | 18 --------
arch/x86/include/asm/paravirt_types.h | 40 ----------------
arch/x86/include/asm/text-patching.h | 12 -----
arch/x86/kernel/alternative.c | 66 +--------------------------
arch/x86/kernel/paravirt.c | 30 ------------
arch/x86/kernel/vmlinux.lds.S | 13 ------
arch/x86/tools/relocs.c | 2 +-
7 files changed, 3 insertions(+), 178 deletions(-)

diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index 9c6c5cfa9fe2..f09acce9432c 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -725,31 +725,13 @@ void native_pv_lock_init(void) __init;

#else /* __ASSEMBLY__ */

-#define _PVSITE(ptype, ops, word, algn) \
-771:; \
- ops; \
-772:; \
- .pushsection .parainstructions,"a"; \
- .align algn; \
- word 771b; \
- .byte ptype; \
- .byte 772b-771b; \
- _ASM_ALIGN; \
- .popsection
-
-
#ifdef CONFIG_X86_64
#ifdef CONFIG_PARAVIRT_XXL
#ifdef CONFIG_DEBUG_ENTRY

-#define PARA_PATCH(off) ((off) / 8)
-#define PARA_SITE(ptype, ops) _PVSITE(ptype, ops, .quad, 8)
#define PARA_INDIRECT(addr) *addr(%rip)

.macro PARA_IRQ_save_fl
- PARA_SITE(PARA_PATCH(PV_IRQ_save_fl),
- ANNOTATE_RETPOLINE_SAFE;
- call PARA_INDIRECT(pv_ops+PV_IRQ_save_fl);)
ANNOTATE_RETPOLINE_SAFE;
call PARA_INDIRECT(pv_ops+PV_IRQ_save_fl);
.endm
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 323dca625eea..756cb75d22b5 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -2,15 +2,6 @@
#ifndef _ASM_X86_PARAVIRT_TYPES_H
#define _ASM_X86_PARAVIRT_TYPES_H

-#ifndef __ASSEMBLY__
-/* These all sit in the .parainstructions section to tell us what to patch. */
-struct paravirt_patch_site {
- u8 *instr; /* original instructions */
- u8 type; /* type of this instruction */
- u8 len; /* length of original instruction */
-};
-#endif
-
#ifdef CONFIG_PARAVIRT

#ifndef __ASSEMBLY__
@@ -250,34 +241,6 @@ struct paravirt_patch_template {
extern struct pv_info pv_info;
extern struct paravirt_patch_template pv_ops;

-#define PARAVIRT_PATCH(x) \
- (offsetof(struct paravirt_patch_template, x) / sizeof(void *))
-
-#define paravirt_type(op) \
- [paravirt_typenum] "i" (PARAVIRT_PATCH(op)), \
- [paravirt_opptr] "m" (pv_ops.op)
-/*
- * Generate some code, and mark it as patchable by the
- * apply_paravirt() alternate instruction patcher.
- */
-#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" \
- " .byte " type "\n" \
- " .byte 772b-771b\n" \
- _ASM_ALIGN "\n" \
- ".popsection\n"
-
-/* Generate patchable code, with the default asm parameters. */
-#define paravirt_alt(insn_string) \
- _paravirt_alt(insn_string, "%c[paravirt_typenum]")
-
-/* Simple instruction patching code. */
-#define NATIVE_LABEL(a,x,b) "\n\t.globl " a #x "_" #b "\n" a #x "_" #b ":\n\t"
-
-unsigned int paravirt_patch(u8 type, void *insn_buff, unsigned long addr, unsigned int len);
#define paravirt_ptr(op) [paravirt_opptr] "m" (pv_ops.op)

int paravirt_disable_iospace(void);
@@ -545,9 +508,6 @@ unsigned long pv_native_read_cr2(void);

#define paravirt_nop ((void *)x86_nop)

-extern struct paravirt_patch_site __parainstructions[],
- __parainstructions_end[];
-
#endif /* __ASSEMBLY__ */

#define ALT_NOT_XEN ALT_NOT(X86_FEATURE_XENPV)
diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h
index 29832c338cdc..0b70653a98c1 100644
--- a/arch/x86/include/asm/text-patching.h
+++ b/arch/x86/include/asm/text-patching.h
@@ -6,18 +6,6 @@
#include <linux/stddef.h>
#include <asm/ptrace.h>

-struct paravirt_patch_site;
-#ifdef CONFIG_PARAVIRT
-void apply_paravirt(struct paravirt_patch_site *start,
- struct paravirt_patch_site *end);
-#else
-static inline void apply_paravirt(struct paravirt_patch_site *start,
- struct paravirt_patch_site *end)
-{}
-#define __parainstructions NULL
-#define __parainstructions_end NULL
-#endif
-
/*
* Currently, the max observed size in the kernel code is
* JUMP_LABEL_NOP_SIZE/RELATIVEJUMP_SIZE, which are 5.
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 01b89a10d219..48d4bb87dce8 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -160,7 +160,6 @@ extern s32 __retpoline_sites[], __retpoline_sites_end[];
extern s32 __return_sites[], __return_sites_end[];
extern s32 __cfi_sites[], __cfi_sites_end[];
extern s32 __ibt_endbr_seal[], __ibt_endbr_seal_end[];
-extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
extern s32 __smp_locks[], __smp_locks_end[];
void text_poke_early(void *addr, const void *opcode, size_t len);

@@ -1461,46 +1460,6 @@ int alternatives_text_reserved(void *start, void *end)
}
#endif /* CONFIG_SMP */

-#ifdef CONFIG_PARAVIRT
-
-/* Use this to add nops to a buffer, then text_poke the whole buffer. */
-static void __init_or_module add_nops(void *insns, unsigned int len)
-{
- while (len > 0) {
- unsigned int noplen = len;
- if (noplen > ASM_NOP_MAX)
- noplen = ASM_NOP_MAX;
- memcpy(insns, x86_nops[noplen], noplen);
- insns += noplen;
- len -= noplen;
- }
-}
-
-void __init_or_module apply_paravirt(struct paravirt_patch_site *start,
- struct paravirt_patch_site *end)
-{
- struct paravirt_patch_site *p;
- char insn_buff[MAX_PATCH_LEN];
-
- for (p = start; p < end; p++) {
- unsigned int used;
-
- 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);
-
- 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);
- }
-}
-extern struct paravirt_patch_site __start_parainstructions[],
- __stop_parainstructions[];
-#endif /* CONFIG_PARAVIRT */
-
/*
* Self-test for the INT3 based CALL emulation code.
*
@@ -1636,28 +1595,11 @@ void __init alternative_instructions(void)
*/

/*
- * Paravirt patching and alternative patching can be combined to
- * replace a function call with a short direct code sequence (e.g.
- * by setting a constant return value instead of doing that in an
- * external function).
- * In order to make this work the following sequence is required:
- * 1. set (artificial) features depending on used paravirt
- * functions which can later influence alternative patching
- * 2. apply paravirt patching (generally replacing an indirect
- * function call with a direct one)
- * 3. apply alternative patching (e.g. replacing a direct function
- * call with a custom code sequence)
- * Doing paravirt patching after alternative patching would clobber
- * the optimization of the custom code with a function call again.
+ * Make sure to set (artificial) features depending on used paravirt
+ * functions which can later influence alternative patching.
*/
paravirt_set_cap();

- /*
- * First patch paravirt functions, such that we overwrite the indirect
- * call with the direct call.
- */
- apply_paravirt(__parainstructions, __parainstructions_end);
-
__apply_fineibt(__retpoline_sites, __retpoline_sites_end,
__cfi_sites, __cfi_sites_end, true);

@@ -1668,10 +1610,6 @@ void __init alternative_instructions(void)
apply_retpolines(__retpoline_sites, __retpoline_sites_end);
apply_returns(__return_sites, __return_sites_end);

- /*
- * Then patch alternatives, such that those paravirt calls that are in
- * alternatives can be overwritten by their immediate fragments.
- */
apply_alternatives(__alt_instructions, __alt_instructions_end);

/*
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 32792b033de2..5358d43886ad 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -43,14 +43,6 @@ void __init default_banner(void)
pv_info.name);
}

-static unsigned paravirt_patch_call(void *insn_buff, const void *target,
- unsigned long addr, unsigned len)
-{
- __text_gen_insn(insn_buff, CALL_INSN_OPCODE,
- (void *)addr, target, CALL_INSN_SIZE);
- return CALL_INSN_SIZE;
-}
-
#ifdef CONFIG_PARAVIRT_XXL
DEFINE_ASM_FUNC(_paravirt_ident_64, "mov %rdi, %rax", .text);
DEFINE_ASM_FUNC(pv_native_save_fl, "pushf; pop %rax", .noinstr.text);
@@ -73,28 +65,6 @@ static void native_tlb_remove_table(struct mmu_gather *tlb, void *table)
tlb_remove_page(tlb, table);
}

-unsigned int paravirt_patch(u8 type, void *insn_buff, unsigned long addr,
- unsigned int len)
-{
- /*
- * Neat trick to map patch type back to the call within the
- * corresponding structure.
- */
- void *opfunc = *((void **)&pv_ops + type);
- unsigned ret;
-
- if (opfunc == NULL)
- /* If there's no function, patch it with x86_BUG() */
- ret = paravirt_patch_call(insn_buff, x86_BUG, addr, len);
- else if (opfunc == x86_nop)
- ret = 0;
- else
- /* Otherwise call the function. */
- ret = paravirt_patch_call(insn_buff, opfunc, addr, len);
-
- return ret;
-}
-
struct static_key paravirt_steal_enabled;
struct static_key paravirt_steal_rq_enabled;

diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index f15fb71f280e..1a3153dfaea8 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -270,19 +270,6 @@ SECTIONS
}
#endif

- /*
- * start address and size of operations which during runtime
- * can be patched with virtualization friendly instructions or
- * baremetal native ones. Think page table operations.
- * Details in paravirt_types.h
- */
- . = ALIGN(8);
- .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
- __parainstructions = .;
- *(.parainstructions)
- __parainstructions_end = .;
- }
-
#ifdef CONFIG_RETPOLINE
/*
* List of instructions that call/jmp/jcc to retpoline thunks
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index d30949e25ebd..a3bae2b24626 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -66,7 +66,7 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
[S_REL] =
"^(__init_(begin|end)|"
"__x86_cpu_dev_(start|end)|"
- "(__parainstructions|__alt_instructions)(_end)?|"
+ "__alt_instructions(_end)?|"
"(__iommu_table|__apicdrivers|__smp_locks)(_end)?|"
"__(start|end)_pci_.*|"
#if CONFIG_FW_LOADER
--
2.35.3

2023-10-19 11:34:23

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v3 1/5] x86/paravirt: move some functions and defines to alternative

Hi Juergen,

kernel test robot noticed the following build warnings:

[auto build test WARNING on kvm/queue]
[cannot apply to tip/x86/core]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Juergen-Gross/x86-paravirt-move-some-functions-and-defines-to-alternative/20231019-171709
base: https://git.kernel.org/pub/scm/virt/kvm/kvm.git queue
patch link: https://lore.kernel.org/r/20231019091520.14540-2-jgross%40suse.com
patch subject: [PATCH v3 1/5] x86/paravirt: move some functions and defines to alternative
reproduce: (https://download.01.org/0day-ci/archive/20231019/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

# many are suggestions rather than must-fix

ERROR:COMPLEX_MACRO: Macros with complex values should be enclosed in parentheses
#32: FILE: arch/x86/include/asm/alternative.h:334:
+#define DEFINE_ASM_FUNC(func, instr, sec) \
+ asm (".pushsection " #sec ", \"ax\"\n" \
+ ".global " #func "\n\t" \
+ ".type " #func ", @function\n\t" \
+ ASM_FUNC_ALIGN "\n" \
+ #func ":\n\t" \
+ ASM_ENDBR \
+ instr "\n\t" \
+ ASM_RET \
+ ".size " #func ", . - " #func "\n\t" \
+ ".popsection")

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2023-10-19 11:56:24

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] x86/paravirt: switch mixed paravirt/alternative calls to alternative_2

Hi Juergen,

kernel test robot noticed the following build warnings:

[auto build test WARNING on kvm/queue]
[cannot apply to tip/x86/core]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Juergen-Gross/x86-paravirt-move-some-functions-and-defines-to-alternative/20231019-171709
base: https://git.kernel.org/pub/scm/virt/kvm/kvm.git queue
patch link: https://lore.kernel.org/r/20231019091520.14540-5-jgross%40suse.com
patch subject: [PATCH v3 4/5] x86/paravirt: switch mixed paravirt/alternative calls to alternative_2
reproduce: (https://download.01.org/0day-ci/archive/20231019/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

# many are suggestions rather than must-fix

ERROR:BRACKET_SPACE: space prohibited before open square bracket '['
#92: FILE: arch/x86/include/asm/paravirt_types.h:281:
+#define paravirt_ptr(op) [paravirt_opptr] "m" (pv_ops.op)

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2023-10-19 12:09:35

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v3 5/5] x86/paravirt: remove no longer needed paravirt patching code

Hi Juergen,

kernel test robot noticed the following build warnings:

[auto build test WARNING on kvm/queue]
[cannot apply to tip/x86/core]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Juergen-Gross/x86-paravirt-move-some-functions-and-defines-to-alternative/20231019-171709
base: https://git.kernel.org/pub/scm/virt/kvm/kvm.git queue
patch link: https://lore.kernel.org/r/20231019091520.14540-6-jgross%40suse.com
patch subject: [PATCH v3 5/5] x86/paravirt: remove no longer needed paravirt patching code
reproduce: (https://download.01.org/0day-ci/archive/20231019/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

# many are suggestions rather than must-fix

WARNING:SPLIT_STRING: quoted string split across lines
#327: FILE: arch/x86/tools/relocs.c:69:
"__x86_cpu_dev_(start|end)|"
+ "__alt_instructions(_end)?|"

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2023-10-25 10:35:12

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v3 1/5] x86/paravirt: move some functions and defines to alternative

On Thu, Oct 19, 2023 at 11:15:16AM +0200, Juergen Gross wrote:
> +/* Low-level backend functions usable from alternative code replacements. */
> +DEFINE_ASM_FUNC(x86_nop, "", .entry.text);
> +EXPORT_SYMBOL_GPL(x86_nop);

This is all x86 code so you don't really need the "x86_" prefix - "nop"
is perfectly fine.

> +noinstr void x86_BUG(void)
> +{
> + BUG();
> +}
> +EXPORT_SYMBOL_GPL(x86_BUG);

That export is needed for?

Paravirt stuff in modules?

It builds here without it - I guess I need to do an allmodconfig.

--
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette

2023-10-25 13:32:05

by Juergen Gross

[permalink] [raw]
Subject: Re: [PATCH v3 1/5] x86/paravirt: move some functions and defines to alternative

On 25.10.23 12:34, Borislav Petkov wrote:
> On Thu, Oct 19, 2023 at 11:15:16AM +0200, Juergen Gross wrote:
>> +/* Low-level backend functions usable from alternative code replacements. */
>> +DEFINE_ASM_FUNC(x86_nop, "", .entry.text);
>> +EXPORT_SYMBOL_GPL(x86_nop);
>
> This is all x86 code so you don't really need the "x86_" prefix - "nop"
> is perfectly fine.

There is

#define nop() asm volatile ("nop")

in arch/x86/include/asm/special_insns.h already.

>
>> +noinstr void x86_BUG(void)
>> +{
>> + BUG();
>> +}
>> +EXPORT_SYMBOL_GPL(x86_BUG);
>
> That export is needed for?
>
> Paravirt stuff in modules?
>
> It builds here without it - I guess I need to do an allmodconfig.
>

It might not be needed now, but are you sure we won't need it in future?


Juergen


Attachments:
OpenPGP_0xB0DE9DD628BF132F.asc (3.08 kB)
OpenPGP public key
OpenPGP_signature.asc (505.00 B)
OpenPGP digital signature
Download all attachments

2023-10-25 13:45:04

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v3 1/5] x86/paravirt: move some functions and defines to alternative

On Wed, Oct 25, 2023 at 03:31:07PM +0200, Juergen Gross wrote:
> There is
>
> #define nop() asm volatile ("nop")
>
> in arch/x86/include/asm/special_insns.h already.

Then call it "nop_func" or so.

> It might not be needed now, but are you sure we won't need it in future?

No, I'm not.

What I'm sure of is: stuff should be added to the kernel only when
really needed. Not in the expectation that it might potentially be
needed at some point.

Thx.

--
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette

2023-10-25 13:57:50

by Juergen Gross

[permalink] [raw]
Subject: Re: [PATCH v3 1/5] x86/paravirt: move some functions and defines to alternative

On 25.10.23 15:44, Borislav Petkov wrote:
> On Wed, Oct 25, 2023 at 03:31:07PM +0200, Juergen Gross wrote:
>> There is
>>
>> #define nop() asm volatile ("nop")
>>
>> in arch/x86/include/asm/special_insns.h already.
>
> Then call it "nop_func" or so.

Okay.

>
>> It might not be needed now, but are you sure we won't need it in future?
>
> No, I'm not.
>
> What I'm sure of is: stuff should be added to the kernel only when
> really needed. Not in the expectation that it might potentially be
> needed at some point.

Will double check whether it is needed now.


Juergen


Attachments:
OpenPGP_0xB0DE9DD628BF132F.asc (3.08 kB)
OpenPGP public key
OpenPGP_signature.asc (505.00 B)
OpenPGP digital signature
Download all attachments

2023-10-26 02:45:58

by Oliver Sang

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] x86/paravirt: switch mixed paravirt/alternative calls to alternative_2



Hello,

kernel test robot noticed "BUG:unable_to_handle_page_fault_for_address" on:

commit: b0b8b06548f7984351b503ec5f5c13fa80bae6a2 ("[PATCH v3 4/5] x86/paravirt: switch mixed paravirt/alternative calls to alternative_2")
url: https://github.com/intel-lab-lkp/linux/commits/Juergen-Gross/x86-paravirt-move-some-functions-and-defines-to-alternative/20231019-171709
base: https://git.kernel.org/cgit/virt/kvm/kvm.git queue
patch link: https://lore.kernel.org/all/[email protected]/
patch subject: [PATCH v3 4/5] x86/paravirt: switch mixed paravirt/alternative calls to alternative_2

in testcase: boot

compiler: gcc-12
test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G

(please refer to attached dmesg/kmsg for entire log/backtrace)


+---------------------------------------------+------------+------------+
| | efa1a70f0b | b0b8b06548 |
+---------------------------------------------+------------+------------+
| BUG:unable_to_handle_page_fault_for_address | 0 | 14 |
| Oops:#[##] | 0 | 14 |
| EIP:apply_alternatives | 0 | 14 |
| Kernel_panic-not_syncing:Fatal_exception | 0 | 14 |
+---------------------------------------------+------------+------------+


If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-lkp/[email protected]


[ 1.382500][ T0] BUG: unable to handle page fault for address: 84864e91
[ 1.383633][ T0] #PF: supervisor read access in kernel mode
[ 1.384579][ T0] #PF: error_code(0x0000) - not-present page
[ 1.384579][ T0] *pde = 00000000
[ 1.384579][ T0] Oops: 0000 [#1] PREEMPT SMP
[ 1.384579][ T0] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.6.0-rc5-00101-gb0b8b06548f7 #1 7cb7f016c05986cc453a3ae4b37cd3712c62c0c0
[ 1.384579][ T0] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[ 1.384579][ T0] EIP: apply_alternatives (arch/x86/kernel/alternative.c:419 arch/x86/kernel/alternative.c:489)
[ 1.384579][ T0] Code: 3c 06 0f 85 4e 02 00 00 8b 85 ec fe ff ff 80 38 ff 0f 85 3f 02 00 00 80 78 01 15 0f 85 35 02 00 00 8b 8d ec fe ff ff 8b 41 02 <8b> 44 01 06 85 c0 74 17 89 c2 81 ea 60 18 7c c2 01 95 f3 fe ff ff
All code
========
0: 3c 06 cmp $0x6,%al
2: 0f 85 4e 02 00 00 jne 0x256
8: 8b 85 ec fe ff ff mov -0x114(%rbp),%eax
e: 80 38 ff cmpb $0xff,(%rax)
11: 0f 85 3f 02 00 00 jne 0x256
17: 80 78 01 15 cmpb $0x15,0x1(%rax)
1b: 0f 85 35 02 00 00 jne 0x256
21: 8b 8d ec fe ff ff mov -0x114(%rbp),%ecx
27: 8b 41 02 mov 0x2(%rcx),%eax
2a:* 8b 44 01 06 mov 0x6(%rcx,%rax,1),%eax <-- trapping instruction
2e: 85 c0 test %eax,%eax
30: 74 17 je 0x49
32: 89 c2 mov %eax,%edx
34: 81 ea 60 18 7c c2 sub $0xc27c1860,%edx
3a: 01 95 f3 fe ff ff add %edx,-0x10d(%rbp)

Code starting with the faulting instruction
===========================================
0: 8b 44 01 06 mov 0x6(%rcx,%rax,1),%eax
4: 85 c0 test %eax,%eax
6: 74 17 je 0x1f
8: 89 c2 mov %eax,%edx
a: 81 ea 60 18 7c c2 sub $0xc27c1860,%edx
10: 01 95 f3 fe ff ff add %edx,-0x10d(%rbp)
[ 1.384579][ T0] EAX: c37e7374 EBX: c37b7e3a ECX: c107db17 EDX: 00000005
[ 1.384579][ T0] ESI: c3ffc70a EDI: 00000000 EBP: c37b7f48 ESP: c37b7e00
[ 1.384579][ T0] DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 EFLAGS: 00210246
[ 1.384579][ T0] CR0: 80050033 CR2: 84864e91 CR3: 04037000 CR4: 000406d0
[ 1.384579][ T0] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[ 1.384579][ T0] DR6: fffe0ff0 DR7: 00000400
[ 1.384579][ T0] Call Trace:
[ 1.384579][ T0] ? show_regs (arch/x86/kernel/dumpstack.c:479)
[ 1.384579][ T0] ? __die (arch/x86/kernel/dumpstack.c:421 arch/x86/kernel/dumpstack.c:434)
[ 1.384579][ T0] ? oops_enter (kernel/panic.c:627)
[ 1.384579][ T0] ? page_fault_oops (arch/x86/mm/fault.c:707)
[ 1.384579][ T0] ? kernelmode_fixup_or_oops+0x9c/0xf4
[ 1.384579][ T0] ? __bad_area_nosemaphore+0x13f/0x260
[ 1.384579][ T0] ? insn_get_opcode (arch/x86/lib/insn.c:299)
[ 1.384579][ T0] ? insn_get_modrm (arch/x86/lib/insn.c:344)
[ 1.384579][ T0] ? insn_get_sib (arch/x86/lib/insn.c:422)
[ 1.384579][ T0] ? bad_area_nosemaphore (arch/x86/mm/fault.c:867)
[ 1.384579][ T0] ? do_user_addr_fault (arch/x86/mm/fault.c:1476)
[ 1.384579][ T0] ? optimize_nops (arch/x86/kernel/alternative.c:246)
[ 1.384579][ T0] ? exc_page_fault (arch/x86/include/asm/irqflags.h:26 arch/x86/include/asm/irqflags.h:67 arch/x86/include/asm/irqflags.h:127 arch/x86/mm/fault.c:1513 arch/x86/mm/fault.c:1561)
[ 1.384579][ T0] ? pvclock_clocksource_read_nowd (arch/x86/mm/fault.c:1518)
[ 1.384579][ T0] ? handle_exception (arch/x86/entry/entry_32.S:1049)
[ 1.384579][ T0] ? ___pte_free_tlb (arch/x86/include/asm/paravirt.h:92 arch/x86/mm/pgtable.c:57)
[ 1.384579][ T0] ? pvclock_clocksource_read_nowd (arch/x86/mm/fault.c:1518)
[ 1.384579][ T0] ? apply_alternatives (arch/x86/kernel/alternative.c:419 arch/x86/kernel/alternative.c:489)
[ 1.384579][ T0] ? pvclock_clocksource_read_nowd (arch/x86/mm/fault.c:1518)
[ 1.384579][ T0] ? apply_alternatives (arch/x86/kernel/alternative.c:419 arch/x86/kernel/alternative.c:489)
[ 1.384579][ T0] ? lock_acquire (kernel/locking/lockdep.c:5670 kernel/locking/lockdep.c:5744)
[ 1.384579][ T0] ? ___pte_free_tlb (arch/x86/include/asm/paravirt.h:92 arch/x86/mm/pgtable.c:57)
[ 1.384579][ T0] alternative_instructions (arch/x86/kernel/alternative.c:1677)
[ 1.384579][ T0] ? fpu__init_cpu (arch/x86/kernel/fpu/init.c:54)
[ 1.384579][ T0] arch_cpu_finalize_init (arch/x86/kernel/cpu/common.c:2407)
[ 1.384579][ T0] start_kernel (init/main.c:1035)
[ 1.384579][ T0] ? set_init_arg (init/main.c:530)
[ 1.384579][ T0] i386_start_kernel (arch/x86/kernel/head32.c:74)
[ 1.384579][ T0] startup_32_smp (arch/x86/kernel/head_32.S:305)
[ 1.384579][ T0] Modules linked in:
[ 1.384579][ T0] CR2: 0000000084864e91
[ 1.384579][ T0] ---[ end trace 0000000000000000 ]---
[ 1.384579][ T0] EIP: apply_alternatives (arch/x86/kernel/alternative.c:419 arch/x86/kernel/alternative.c:489)
[ 1.384579][ T0] Code: 3c 06 0f 85 4e 02 00 00 8b 85 ec fe ff ff 80 38 ff 0f 85 3f 02 00 00 80 78 01 15 0f 85 35 02 00 00 8b 8d ec fe ff ff 8b 41 02 <8b> 44 01 06 85 c0 74 17 89 c2 81 ea 60 18 7c c2 01 95 f3 fe ff ff
All code
========
0: 3c 06 cmp $0x6,%al
2: 0f 85 4e 02 00 00 jne 0x256
8: 8b 85 ec fe ff ff mov -0x114(%rbp),%eax
e: 80 38 ff cmpb $0xff,(%rax)
11: 0f 85 3f 02 00 00 jne 0x256
17: 80 78 01 15 cmpb $0x15,0x1(%rax)
1b: 0f 85 35 02 00 00 jne 0x256
21: 8b 8d ec fe ff ff mov -0x114(%rbp),%ecx
27: 8b 41 02 mov 0x2(%rcx),%eax
2a:* 8b 44 01 06 mov 0x6(%rcx,%rax,1),%eax <-- trapping instruction
2e: 85 c0 test %eax,%eax
30: 74 17 je 0x49
32: 89 c2 mov %eax,%edx
34: 81 ea 60 18 7c c2 sub $0xc27c1860,%edx
3a: 01 95 f3 fe ff ff add %edx,-0x10d(%rbp)

Code starting with the faulting instruction
===========================================
0: 8b 44 01 06 mov 0x6(%rcx,%rax,1),%eax
4: 85 c0 test %eax,%eax
6: 74 17 je 0x1f
8: 89 c2 mov %eax,%edx
a: 81 ea 60 18 7c c2 sub $0xc27c1860,%edx
10: 01 95 f3 fe ff ff add %edx,-0x10d(%rbp)


The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20231026/[email protected]



--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2023-10-26 06:33:56

by Juergen Gross

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] x86/paravirt: switch mixed paravirt/alternative calls to alternative_2

On 26.10.23 04:44, kernel test robot wrote:
>
>
> Hello,
>
> kernel test robot noticed "BUG:unable_to_handle_page_fault_for_address" on:
>
> commit: b0b8b06548f7984351b503ec5f5c13fa80bae6a2 ("[PATCH v3 4/5] x86/paravirt: switch mixed paravirt/alternative calls to alternative_2")
> url: https://github.com/intel-lab-lkp/linux/commits/Juergen-Gross/x86-paravirt-move-some-functions-and-defines-to-alternative/20231019-171709
> base: https://git.kernel.org/cgit/virt/kvm/kvm.git queue
> patch link: https://lore.kernel.org/all/[email protected]/
> patch subject: [PATCH v3 4/5] x86/paravirt: switch mixed paravirt/alternative calls to alternative_2
>
> in testcase: boot
>
> compiler: gcc-12
> test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G
>
> (please refer to attached dmesg/kmsg for entire log/backtrace)
>
>
> +---------------------------------------------+------------+------------+
> | | efa1a70f0b | b0b8b06548 |
> +---------------------------------------------+------------+------------+
> | BUG:unable_to_handle_page_fault_for_address | 0 | 14 |
> | Oops:#[##] | 0 | 14 |
> | EIP:apply_alternatives | 0 | 14 |
> | Kernel_panic-not_syncing:Fatal_exception | 0 | 14 |
> +---------------------------------------------+------------+------------+
>
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <[email protected]>
> | Closes: https://lore.kernel.org/oe-lkp/[email protected]
>
>
> [ 1.382500][ T0] BUG: unable to handle page fault for address: 84864e91
> [ 1.383633][ T0] #PF: supervisor read access in kernel mode
> [ 1.384579][ T0] #PF: error_code(0x0000) - not-present page
> [ 1.384579][ T0] *pde = 00000000
> [ 1.384579][ T0] Oops: 0000 [#1] PREEMPT SMP
> [ 1.384579][ T0] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.6.0-rc5-00101-gb0b8b06548f7 #1 7cb7f016c05986cc453a3ae4b37cd3712c62c0c0
> [ 1.384579][ T0] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
> [ 1.384579][ T0] EIP: apply_alternatives (arch/x86/kernel/alternative.c:419 arch/x86/kernel/alternative.c:489)
> [ 1.384579][ T0] Code: 3c 06 0f 85 4e 02 00 00 8b 85 ec fe ff ff 80 38 ff 0f 85 3f 02 00 00 80 78 01 15 0f 85 35 02 00 00 8b 8d ec fe ff ff 8b 41 02 <8b> 44 01 06 85 c0 74 17 89 c2 81 ea 60 18 7c c2 01 95 f3 fe ff ff
> All code
> ========
> 0: 3c 06 cmp $0x6,%al
> 2: 0f 85 4e 02 00 00 jne 0x256
> 8: 8b 85 ec fe ff ff mov -0x114(%rbp),%eax
> e: 80 38 ff cmpb $0xff,(%rax)
> 11: 0f 85 3f 02 00 00 jne 0x256
> 17: 80 78 01 15 cmpb $0x15,0x1(%rax)
> 1b: 0f 85 35 02 00 00 jne 0x256
> 21: 8b 8d ec fe ff ff mov -0x114(%rbp),%ecx
> 27: 8b 41 02 mov 0x2(%rcx),%eax
> 2a:* 8b 44 01 06 mov 0x6(%rcx,%rax,1),%eax <-- trapping instruction
> 2e: 85 c0 test %eax,%eax
> 30: 74 17 je 0x49
> 32: 89 c2 mov %eax,%edx
> 34: 81 ea 60 18 7c c2 sub $0xc27c1860,%edx
> 3a: 01 95 f3 fe ff ff add %edx,-0x10d(%rbp)
>
> Code starting with the faulting instruction
> ===========================================
> 0: 8b 44 01 06 mov 0x6(%rcx,%rax,1),%eax
> 4: 85 c0 test %eax,%eax
> 6: 74 17 je 0x1f
> 8: 89 c2 mov %eax,%edx
> a: 81 ea 60 18 7c c2 sub $0xc27c1860,%edx
> 10: 01 95 f3 fe ff ff add %edx,-0x10d(%rbp)
> [ 1.384579][ T0] EAX: c37e7374 EBX: c37b7e3a ECX: c107db17 EDX: 00000005
> [ 1.384579][ T0] ESI: c3ffc70a EDI: 00000000 EBP: c37b7f48 ESP: c37b7e00
> [ 1.384579][ T0] DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 EFLAGS: 00210246
> [ 1.384579][ T0] CR0: 80050033 CR2: 84864e91 CR3: 04037000 CR4: 000406d0
> [ 1.384579][ T0] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
> [ 1.384579][ T0] DR6: fffe0ff0 DR7: 00000400
> [ 1.384579][ T0] Call Trace:
> [ 1.384579][ T0] ? show_regs (arch/x86/kernel/dumpstack.c:479)
> [ 1.384579][ T0] ? __die (arch/x86/kernel/dumpstack.c:421 arch/x86/kernel/dumpstack.c:434)
> [ 1.384579][ T0] ? oops_enter (kernel/panic.c:627)
> [ 1.384579][ T0] ? page_fault_oops (arch/x86/mm/fault.c:707)
> [ 1.384579][ T0] ? kernelmode_fixup_or_oops+0x9c/0xf4
> [ 1.384579][ T0] ? __bad_area_nosemaphore+0x13f/0x260
> [ 1.384579][ T0] ? insn_get_opcode (arch/x86/lib/insn.c:299)
> [ 1.384579][ T0] ? insn_get_modrm (arch/x86/lib/insn.c:344)
> [ 1.384579][ T0] ? insn_get_sib (arch/x86/lib/insn.c:422)
> [ 1.384579][ T0] ? bad_area_nosemaphore (arch/x86/mm/fault.c:867)
> [ 1.384579][ T0] ? do_user_addr_fault (arch/x86/mm/fault.c:1476)
> [ 1.384579][ T0] ? optimize_nops (arch/x86/kernel/alternative.c:246)
> [ 1.384579][ T0] ? exc_page_fault (arch/x86/include/asm/irqflags.h:26 arch/x86/include/asm/irqflags.h:67 arch/x86/include/asm/irqflags.h:127 arch/x86/mm/fault.c:1513 arch/x86/mm/fault.c:1561)
> [ 1.384579][ T0] ? pvclock_clocksource_read_nowd (arch/x86/mm/fault.c:1518)
> [ 1.384579][ T0] ? handle_exception (arch/x86/entry/entry_32.S:1049)
> [ 1.384579][ T0] ? ___pte_free_tlb (arch/x86/include/asm/paravirt.h:92 arch/x86/mm/pgtable.c:57)
> [ 1.384579][ T0] ? pvclock_clocksource_read_nowd (arch/x86/mm/fault.c:1518)
> [ 1.384579][ T0] ? apply_alternatives (arch/x86/kernel/alternative.c:419 arch/x86/kernel/alternative.c:489)
> [ 1.384579][ T0] ? pvclock_clocksource_read_nowd (arch/x86/mm/fault.c:1518)
> [ 1.384579][ T0] ? apply_alternatives (arch/x86/kernel/alternative.c:419 arch/x86/kernel/alternative.c:489)
> [ 1.384579][ T0] ? lock_acquire (kernel/locking/lockdep.c:5670 kernel/locking/lockdep.c:5744)
> [ 1.384579][ T0] ? ___pte_free_tlb (arch/x86/include/asm/paravirt.h:92 arch/x86/mm/pgtable.c:57)
> [ 1.384579][ T0] alternative_instructions (arch/x86/kernel/alternative.c:1677)
> [ 1.384579][ T0] ? fpu__init_cpu (arch/x86/kernel/fpu/init.c:54)
> [ 1.384579][ T0] arch_cpu_finalize_init (arch/x86/kernel/cpu/common.c:2407)
> [ 1.384579][ T0] start_kernel (init/main.c:1035)
> [ 1.384579][ T0] ? set_init_arg (init/main.c:530)
> [ 1.384579][ T0] i386_start_kernel (arch/x86/kernel/head32.c:74)
> [ 1.384579][ T0] startup_32_smp (arch/x86/kernel/head_32.S:305)
> [ 1.384579][ T0] Modules linked in:
> [ 1.384579][ T0] CR2: 0000000084864e91
> [ 1.384579][ T0] ---[ end trace 0000000000000000 ]---
> [ 1.384579][ T0] EIP: apply_alternatives (arch/x86/kernel/alternative.c:419 arch/x86/kernel/alternative.c:489)
> [ 1.384579][ T0] Code: 3c 06 0f 85 4e 02 00 00 8b 85 ec fe ff ff 80 38 ff 0f 85 3f 02 00 00 80 78 01 15 0f 85 35 02 00 00 8b 8d ec fe ff ff 8b 41 02 <8b> 44 01 06 85 c0 74 17 89 c2 81 ea 60 18 7c c2 01 95 f3 fe ff ff
> All code
> ========
> 0: 3c 06 cmp $0x6,%al
> 2: 0f 85 4e 02 00 00 jne 0x256
> 8: 8b 85 ec fe ff ff mov -0x114(%rbp),%eax
> e: 80 38 ff cmpb $0xff,(%rax)
> 11: 0f 85 3f 02 00 00 jne 0x256
> 17: 80 78 01 15 cmpb $0x15,0x1(%rax)
> 1b: 0f 85 35 02 00 00 jne 0x256
> 21: 8b 8d ec fe ff ff mov -0x114(%rbp),%ecx
> 27: 8b 41 02 mov 0x2(%rcx),%eax
> 2a:* 8b 44 01 06 mov 0x6(%rcx,%rax,1),%eax <-- trapping instruction
> 2e: 85 c0 test %eax,%eax
> 30: 74 17 je 0x49
> 32: 89 c2 mov %eax,%edx
> 34: 81 ea 60 18 7c c2 sub $0xc27c1860,%edx
> 3a: 01 95 f3 fe ff ff add %edx,-0x10d(%rbp)
>
> Code starting with the faulting instruction
> ===========================================
> 0: 8b 44 01 06 mov 0x6(%rcx,%rax,1),%eax
> 4: 85 c0 test %eax,%eax
> 6: 74 17 je 0x1f
> 8: 89 c2 mov %eax,%edx
> a: 81 ea 60 18 7c c2 sub $0xc27c1860,%edx
> 10: 01 95 f3 fe ff ff add %edx,-0x10d(%rbp)
>
>
> The kernel config and materials to reproduce are available at:
> https://download.01.org/0day-ci/archive/20231026/[email protected]

Yay, 32-bit code.

I'll update the patch to consider X86_32, which has no %rip relative indirect
call.


Juergen


Attachments:
OpenPGP_0xB0DE9DD628BF132F.asc (3.08 kB)
OpenPGP public key
OpenPGP_signature.asc (505.00 B)
OpenPGP digital signature
Download all attachments

2023-10-26 09:03:48

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] x86/paravirt: switch mixed paravirt/alternative calls to alternative_2

Hi Juergen,

kernel test robot noticed the following build errors:

[auto build test ERROR on kvm/queue]
[also build test ERROR on tip/master linus/master v6.6-rc7 next-20231025]
[cannot apply to tip/x86/core kvm/linux-next tip/auto-latest]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Juergen-Gross/x86-paravirt-move-some-functions-and-defines-to-alternative/20231019-171709
base: https://git.kernel.org/pub/scm/virt/kvm/kvm.git queue
patch link: https://lore.kernel.org/r/20231019091520.14540-5-jgross%40suse.com
patch subject: [PATCH v3 4/5] x86/paravirt: switch mixed paravirt/alternative calls to alternative_2
config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20231026/[email protected]/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231026/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All errors (new ones prefixed by >>):

arch/x86/entry/entry_64.S: Assembler messages:
>> arch/x86/entry/entry_64.S:454: Error: no such instruction: `alt_call_instr'
arch/x86/entry/entry_64.S:319: Info: macro invoked from here
arch/x86/entry/entry_64.S:1138: Info: macro invoked from here


vim +454 arch/x86/entry/entry_64.S

6368558c37107b Thomas Gleixner 2020-05-21 442
cfa82a00533f70 Thomas Gleixner 2020-02-25 443 /**
cfa82a00533f70 Thomas Gleixner 2020-02-25 444 * idtentry_mce_db - Macro to generate entry stubs for #MC and #DB
cfa82a00533f70 Thomas Gleixner 2020-02-25 445 * @vector: Vector number
cfa82a00533f70 Thomas Gleixner 2020-02-25 446 * @asmsym: ASM symbol for the entry point
cfa82a00533f70 Thomas Gleixner 2020-02-25 447 * @cfunc: C function to be called
cfa82a00533f70 Thomas Gleixner 2020-02-25 448 *
cfa82a00533f70 Thomas Gleixner 2020-02-25 449 * The macro emits code to set up the kernel context for #MC and #DB
cfa82a00533f70 Thomas Gleixner 2020-02-25 450 *
cfa82a00533f70 Thomas Gleixner 2020-02-25 451 * If the entry comes from user space it uses the normal entry path
cfa82a00533f70 Thomas Gleixner 2020-02-25 452 * including the return to user space work and preemption checks on
cfa82a00533f70 Thomas Gleixner 2020-02-25 453 * exit.
cfa82a00533f70 Thomas Gleixner 2020-02-25 @454 *
cfa82a00533f70 Thomas Gleixner 2020-02-25 455 * If hits in kernel mode then it needs to go through the paranoid
cfa82a00533f70 Thomas Gleixner 2020-02-25 456 * entry as the exception can hit any random state. No preemption
cfa82a00533f70 Thomas Gleixner 2020-02-25 457 * check on exit to keep the paranoid path simple.
cfa82a00533f70 Thomas Gleixner 2020-02-25 458 */
cfa82a00533f70 Thomas Gleixner 2020-02-25 459 .macro idtentry_mce_db vector asmsym cfunc
cfa82a00533f70 Thomas Gleixner 2020-02-25 460 SYM_CODE_START(\asmsym)
4708ea14bef314 Josh Poimboeuf 2023-03-01 461 UNWIND_HINT_IRET_ENTRY
8f93402b92d443 Peter Zijlstra 2022-03-08 462 ENDBR
cfa82a00533f70 Thomas Gleixner 2020-02-25 463 ASM_CLAC
c64cc2802a784e Lai Jiangshan 2022-04-21 464 cld
cfa82a00533f70 Thomas Gleixner 2020-02-25 465
cfa82a00533f70 Thomas Gleixner 2020-02-25 466 pushq $-1 /* ORIG_RAX: no syscall to restart */
cfa82a00533f70 Thomas Gleixner 2020-02-25 467
cfa82a00533f70 Thomas Gleixner 2020-02-25 468 /*
cfa82a00533f70 Thomas Gleixner 2020-02-25 469 * If the entry is from userspace, switch stacks and treat it as
cfa82a00533f70 Thomas Gleixner 2020-02-25 470 * a normal entry.
cfa82a00533f70 Thomas Gleixner 2020-02-25 471 */
cfa82a00533f70 Thomas Gleixner 2020-02-25 472 testb $3, CS-ORIG_RAX(%rsp)
cfa82a00533f70 Thomas Gleixner 2020-02-25 473 jnz .Lfrom_usermode_switch_stack_\@
cfa82a00533f70 Thomas Gleixner 2020-02-25 474
c82965f9e53005 Chang S. Bae 2020-05-28 475 /* paranoid_entry returns GS information for paranoid_exit in EBX. */
cfa82a00533f70 Thomas Gleixner 2020-02-25 476 call paranoid_entry
cfa82a00533f70 Thomas Gleixner 2020-02-25 477
cfa82a00533f70 Thomas Gleixner 2020-02-25 478 UNWIND_HINT_REGS
cfa82a00533f70 Thomas Gleixner 2020-02-25 479
cfa82a00533f70 Thomas Gleixner 2020-02-25 480 movq %rsp, %rdi /* pt_regs pointer */
cfa82a00533f70 Thomas Gleixner 2020-02-25 481
cfa82a00533f70 Thomas Gleixner 2020-02-25 482 call \cfunc
cfa82a00533f70 Thomas Gleixner 2020-02-25 483
cfa82a00533f70 Thomas Gleixner 2020-02-25 484 jmp paranoid_exit
cfa82a00533f70 Thomas Gleixner 2020-02-25 485
cfa82a00533f70 Thomas Gleixner 2020-02-25 486 /* Switch to the regular task stack and use the noist entry point */
cfa82a00533f70 Thomas Gleixner 2020-02-25 487 .Lfrom_usermode_switch_stack_\@:
e2dcb5f1390715 Thomas Gleixner 2020-05-21 488 idtentry_body noist_\cfunc, has_error_code=0
cfa82a00533f70 Thomas Gleixner 2020-02-25 489

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2023-10-30 12:39:46

by Juergen Gross

[permalink] [raw]
Subject: Re: [PATCH v3 1/5] x86/paravirt: move some functions and defines to alternative

On 25.10.23 12:34, Borislav Petkov wrote:
> On Thu, Oct 19, 2023 at 11:15:16AM +0200, Juergen Gross wrote:
>> +/* Low-level backend functions usable from alternative code replacements. */
>> +DEFINE_ASM_FUNC(x86_nop, "", .entry.text);
>> +EXPORT_SYMBOL_GPL(x86_nop);
>
> This is all x86 code so you don't really need the "x86_" prefix - "nop"
> is perfectly fine.
>
>> +noinstr void x86_BUG(void)
>> +{
>> + BUG();
>> +}
>> +EXPORT_SYMBOL_GPL(x86_BUG);
>
> That export is needed for?
>
> Paravirt stuff in modules?
>
> It builds here without it - I guess I need to do an allmodconfig.
>

Turns out it is needed after all. With patch 4 applied I get:

ERROR: modpost: "BUG_func" [arch/x86/events/amd/power.ko] undefined!
ERROR: modpost: "BUG_func" [arch/x86/kernel/cpu/mce/mce-inject.ko] undefined!
ERROR: modpost: "BUG_func" [arch/x86/kernel/cpuid.ko] undefined!
ERROR: modpost: "BUG_func" [arch/x86/kvm/kvm.ko] undefined!
ERROR: modpost: "BUG_func" [arch/x86/kvm/kvm-intel.ko] undefined!
ERROR: modpost: "BUG_func" [arch/x86/kvm/kvm-amd.ko] undefined!
ERROR: modpost: "BUG_func" [fs/nfsd/nfsd.ko] undefined!
ERROR: modpost: "BUG_func" [crypto/aes_ti.ko] undefined!
ERROR: modpost: "BUG_func" [drivers/video/fbdev/uvesafb.ko] undefined!
ERROR: modpost: "BUG_func" [drivers/video/vgastate.ko] undefined!


Juergen


Attachments:
OpenPGP_0xB0DE9DD628BF132F.asc (3.08 kB)
OpenPGP public key
OpenPGP_signature.asc (505.00 B)
OpenPGP digital signature
Download all attachments