[RFC PATCH 71/73] x86/pvm: Adapt pushf/popf in this_cpu_cmpxchg16b_emu()

From: Lai Jiangshan
Date: Mon Feb 26 2024 - 10:28:09 EST


From: Hou Wenlong <houwenlong.hwl@xxxxxxxxxxxx>

The pushf/popf instructions in this_cpu_cmpxchg16b_emu() are
non-privilege instructions, so they cannot be trapped and emulated,
which could cause a boot failure. However, since the cmpxchg16b
instruction is supported for PVM guest. we can patch
this_cpu_cmpxchg16b_emu() and use cmpxchg16b directly.

Suggested-by: Lai Jiangshan <jiangshan.ljs@xxxxxxxxxxxx>
Signed-off-by: Hou Wenlong <houwenlong.hwl@xxxxxxxxxxxx>
Signed-off-by: Lai Jiangshan <jiangshan.ljs@xxxxxxxxxxxx>
---
arch/x86/kernel/pvm.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)

diff --git a/arch/x86/kernel/pvm.c b/arch/x86/kernel/pvm.c
index 1dc2c0fb7daa..567ea19d569c 100644
--- a/arch/x86/kernel/pvm.c
+++ b/arch/x86/kernel/pvm.c
@@ -413,6 +413,34 @@ __visible noinstr void pvm_event(struct pt_regs *regs)
common_interrupt(regs, vector);
}

+asm (
+ ".pushsection .rodata \n"
+ ".global pvm_cmpxchg16b_emu_template \n"
+ "pvm_cmpxchg16b_emu_template: \n"
+ " cmpxchg16b %gs:(%rsi) \n"
+ " ret \n"
+ ".global pvm_cmpxchg16b_emu_tail \n"
+ "pvm_cmpxchg16b_emu_tail: \n"
+ ".popsection \n"
+);
+
+extern u8 this_cpu_cmpxchg16b_emu[];
+extern u8 pvm_cmpxchg16b_emu_template[];
+extern u8 pvm_cmpxchg16b_emu_tail[];
+
+static void __init pvm_early_patch(void)
+{
+ /*
+ * The pushf/popf instructions in this_cpu_cmpxchg16b_emu() are
+ * non-privilege instructions, so they cannot be trapped and emulated,
+ * which could cause a boot failure. However, since the cmpxchg16b
+ * instruction is supported for PVM guest. we can patch
+ * this_cpu_cmpxchg16b_emu() and use cmpxchg16b directly.
+ */
+ memcpy(this_cpu_cmpxchg16b_emu, pvm_cmpxchg16b_emu_template,
+ (unsigned int)(pvm_cmpxchg16b_emu_tail - pvm_cmpxchg16b_emu_template));
+}
+
extern void pvm_early_kernel_event_entry(void);

/*
@@ -457,6 +485,8 @@ void __init pvm_early_setup(void)
wrmsrl(MSR_PVM_EVENT_ENTRY, (unsigned long)(void *)pvm_early_kernel_event_entry - 256);
wrmsrl(MSR_PVM_SUPERVISOR_REDZONE, PVM_SUPERVISOR_REDZONE_SIZE);
wrmsrl(MSR_PVM_RETS_RIP, (unsigned long)(void *)pvm_rets_rip);
+
+ pvm_early_patch();
}

void pvm_setup_event_handling(void)
--
2.19.1.6.gb485710b