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

[xen staging-4.21] x86/pv: Provide better SYSCALL backwards compatibility in FRED mode



commit 9a0327bf537bdc1db559504e4a936108a28bd565
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Wed Jun 3 11:38:18 2026 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Wed Jun 3 11:38:18 2026 +0200

    x86/pv: Provide better SYSCALL backwards compatibility in FRED mode
    
    In FRED mode, the SYSCALL instruction does not modify %rcx/%r11.  All 
current
    software using SYSCALL expects the pre-FRED behaviour and spills %rcx/%r11
    around the invocation, which is why FRED not doing this goes largely
    unnoticed.
    
    However, consider the following migration scenario:
    
     * VM suspends.  Hypercall, so SYSCALL, %rcx/%r11 left unmodified
     * VM moves to a non-FRED system
     * Xen resumes the VM with a real SYSRET instruction
    
    Instead of resuming at the instruction following the SYSCALL instruction, 
the
    VM is resumed at whatever dead value was in %rcx.
    
    In FRED mode, manually adjust %rcx/%r11 when SYSCALL is used and when SYSRET
    would have been used.
    
    Regarding the choice of instructions in eretu_exit_to_guest(), a branch 
would
    be a context dependent 50/50 split (i.e. increased chance of mispredict), 
and
    only saves one instruction.  The CMOVs read the same cacheline that ERETU is
    about to process, so are as close to free as we can reasonably get.
    
    Fixes: 76193ef47d91 ("x86/pv: System call handling in FRED mode")
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
    master commit: c5a4b9125bed42d1947a48058119cd335294164b
    master date: 2026-05-28 16:19:16 +0100
---
 xen/arch/x86/traps.c             |  2 ++
 xen/arch/x86/x86_64/entry-fred.S | 12 +++++++++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 85d835ab43..9fdb08ce1a 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -2409,6 +2409,8 @@ void asmlinkage entry_from_pv(struct cpu_user_regs *regs)
 
             regs->ssx = l ? FLAT_KERNEL_SS   : FLAT_USER_SS32;
             regs->csx = l ? FLAT_KERNEL_CS64 : FLAT_USER_CS32;
+            regs->rcx = regs->rip;
+            regs->r11 = regs->rflags;
 
             if ( guest_kernel_mode(curr, regs) )
                 pv_hypercall(regs);
diff --git a/xen/arch/x86/x86_64/entry-fred.S b/xen/arch/x86/x86_64/entry-fred.S
index 2fa57beb93..e9c84423da 100644
--- a/xen/arch/x86/x86_64/entry-fred.S
+++ b/xen/arch/x86/x86_64/entry-fred.S
@@ -4,6 +4,7 @@
 
 #include <asm/asm_defns.h>
 #include <asm/page.h>
+#include <asm/processor.h>
 
         .section .text.entry, "ax", @progbits
 
@@ -26,7 +27,16 @@ FUNC(entry_FRED_R3, 4096)
 END(entry_FRED_R3)
 
 FUNC(eretu_exit_to_guest)
-        POP_GPRS
+        /*
+         * PV guests aren't aware of FRED.  If Xen in IDT mode would have used
+         * a SYSRET instruction, preserve the legacy behaviour for %rcx/%r11
+         */
+        testb   $TRAP_syscall >> 8, UREGS_entry_vector + 1(%rsp)
+
+        POP_GPRS /* Preserves flags */
+
+        cmovnz  EFRAME_rip(%rsp), %rcx
+        cmovnz  EFRAME_eflags(%rsp), %r11
 
         /*
          * Exceptions here are handled by redirecting either to
--
generated by git-patchbot for /home/xen/git/xen.git#staging-4.21



 


Rackspace

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