x86/suspend: Fix restoration of guest state across S3/S4
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 20 Jun 2018 07:43:57 +0000 (15:43 +0800)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 4 Jul 2018 11:12:14 +0000 (12:12 +0100)
The call to freeze_domains() in enter_state() guarentees that we are
running in idle context for the duration of S3/S4.

In restore_rest_processor_state(), the stts() is problematic as it
unilaterally sets %cr0.ts even in fully_eager FPU context.  It also fails to
account for the non-lazy xsave state.  Luckily, these are both latent bugs, as
the FPU state is corrected by the subsequent context switch away from the idle
vcpu.

Another aspect is that the !is_idle_vcpu(curr) paths in
restore_rest_processor_state() are actually dead code, and removing
these highlights that the segment saving logic is also unused.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/acpi/suspend.c

index eecf357a9efe9b17dcaffa98641f956cd1d52f9d..00e6012f541000afd5a5222f102f1505ef165b47 100644 (file)
 static unsigned long saved_lstar, saved_cstar;
 static unsigned long saved_sysenter_esp, saved_sysenter_eip;
 static unsigned long saved_fs_base, saved_gs_base, saved_kernel_gs_base;
-static uint16_t saved_segs[4];
 static uint64_t saved_xcr0;
 
 void save_rest_processor_state(void)
 {
-    vcpu_save_fpu(current);
-
-    asm volatile (
-        "movw %%ds,(%0); movw %%es,2(%0); movw %%fs,4(%0); movw %%gs,6(%0)"
-        : : "r" (saved_segs) : "memory" );
     saved_fs_base = rdfsbase();
     saved_gs_base = rdgsbase();
     rdmsrl(MSR_SHADOW_GS_BASE, saved_kernel_gs_base);
@@ -46,8 +40,6 @@ void save_rest_processor_state(void)
 
 void restore_rest_processor_state(void)
 {
-    struct vcpu *curr = current;
-
     load_TR();
 
     /* Recover syscall MSRs */
@@ -69,32 +61,9 @@ void restore_rest_processor_state(void)
         wrmsr(MSR_IA32_SYSENTER_CS, __HYPERVISOR_CS, 0);
     }
 
-    if ( !is_idle_vcpu(curr) )
-    {
-        asm volatile (
-            "movw (%0),%%ds; movw 2(%0),%%es; movw 4(%0),%%fs"
-            : : "r" (saved_segs) : "memory" );
-        do_set_segment_base(SEGBASE_GS_USER_SEL, saved_segs[3]);
-    }
-
     if ( cpu_has_xsave && !set_xcr0(saved_xcr0) )
         BUG();
 
-    /* Maybe load the debug registers. */
-    BUG_ON(!is_pv_vcpu(curr));
-    if ( !is_idle_vcpu(curr) && curr->arch.debugreg[7] )
-    {
-        write_debugreg(0, curr->arch.debugreg[0]);
-        write_debugreg(1, curr->arch.debugreg[1]);
-        write_debugreg(2, curr->arch.debugreg[2]);
-        write_debugreg(3, curr->arch.debugreg[3]);
-        write_debugreg(6, curr->arch.debugreg[6]);
-        write_debugreg(7, curr->arch.debugreg[7]);
-    }
-
-    /* Reload FPU state on next FPU use. */
-    stts();
-
     wrmsrl(MSR_IA32_CR_PAT, XEN_MSR_PAT);
 
     mtrr_bp_restore();