[Xen-devel] [PATCH] x86/suspend: Simplify system table handling on resume

Andrew Cooper posted 1 patch 1 week ago
Failed in applying to current master (apply log)
xen/arch/x86/acpi/suspend.c     | 14 +++++++++++++-
xen/arch/x86/acpi/wakeup_prot.S | 13 +------------
xen/arch/x86/traps.c            | 21 ---------------------
xen/include/asm-x86/desc.h      |  2 --
4 files changed, 14 insertions(+), 36 deletions(-)

[Xen-devel] [PATCH] x86/suspend: Simplify system table handling on resume

Posted by Andrew Cooper 1 week ago
load_TR() is used exclusively in the resume path, but jumps through a lot of
unnecessary hoops.

As suspend/resume is strictly on CPU0 in idle context, the correct GDT to use
is boot_gdt, which means it doesn't need saving on suspend.  Similarly, the
correct IDT to use can be derived, and the LDT is guaranteed to be NUL.

The TR is still correct in the GDT, but needs the busy bit clearing before we
can reload it.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wl@xen.org>
CC: Roger Pau Monné <roger.pau@citrix.com>

A slightly different option would be to call load_system_tables() rather than
opencoding part of it in restore_rest_processor_state().  However, that is
more setup than is necessary.  Thoughts?
---
 xen/arch/x86/acpi/suspend.c     | 14 +++++++++++++-
 xen/arch/x86/acpi/wakeup_prot.S | 13 +------------
 xen/arch/x86/traps.c            | 21 ---------------------
 xen/include/asm-x86/desc.h      |  2 --
 4 files changed, 14 insertions(+), 36 deletions(-)

diff --git a/xen/arch/x86/acpi/suspend.c b/xen/arch/x86/acpi/suspend.c
index ba9d2e13a7..a6f2584645 100644
--- a/xen/arch/x86/acpi/suspend.c
+++ b/xen/arch/x86/acpi/suspend.c
@@ -41,7 +41,19 @@ void save_rest_processor_state(void)
 
 void restore_rest_processor_state(void)
 {
-    load_TR();
+    unsigned int cpu = smp_processor_id();
+    seg_desc_t *gdt = per_cpu(gdt, cpu) - FIRST_RESERVED_GDT_ENTRY;
+    struct tss64 *tss = &per_cpu(tss_page, cpu).tss;
+    const struct desc_ptr idtr = {
+        .base = (unsigned long)idt_tables[cpu],
+        .limit = (IDT_ENTRIES * sizeof(idt_entry_t)) - 1,
+    };
+
+    _set_tssldt_desc(gdt + TSS_ENTRY, (unsigned long)tss,
+                     sizeof(*tss) - 1, SYS_DESC_tss_avail);
+    lidt(&idtr);
+    ltr(TSS_SELECTOR);
+    lldt(0);
 
     /* Recover syscall MSRs */
     wrmsrl(MSR_LSTAR, saved_lstar);
diff --git a/xen/arch/x86/acpi/wakeup_prot.S b/xen/arch/x86/acpi/wakeup_prot.S
index 9e9fcc1ab6..74261cb4f1 100644
--- a/xen/arch/x86/acpi/wakeup_prot.S
+++ b/xen/arch/x86/acpi/wakeup_prot.S
@@ -34,10 +34,6 @@ ENTRY(do_suspend_lowlevel)
 
         mov     %ss, REF(saved_ss)
 
-        sgdt    REF(saved_gdt)
-        sidt    REF(saved_idt)
-        sldt    REF(saved_ldt)
-
         mov     %cr0, GREG(ax)
         mov     GREG(ax), REF(saved_cr0)
 
@@ -55,6 +51,7 @@ ENTRY(do_suspend_lowlevel)
 
 
 ENTRY(__ret_point)
+        lgdt    boot_gdtr(%rip)
 
         /* mmu_cr4_features contains latest cr4 setting */
         mov     REF(mmu_cr4_features), GREG(ax)
@@ -66,10 +63,6 @@ ENTRY(__ret_point)
         mov     REF(saved_cr0), GREG(ax)
         mov     GREG(ax), %cr0
 
-        lgdt    REF(saved_gdt)
-        lidt    REF(saved_idt)
-        lldt    REF(saved_ldt)
-
         mov     REF(saved_ss), %ss
         LOAD_GREG(sp)
 
@@ -129,9 +122,5 @@ DECLARE_GREG(13)
 DECLARE_GREG(14)
 DECLARE_GREG(15)
 
-saved_gdt:      .quad   0,0
-saved_idt:      .quad   0,0
-saved_ldt:      .quad   0,0
-
 saved_cr0:      .quad   0
 saved_cr3:      .quad   0
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 23069e25ec..b424687f85 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -1901,27 +1901,6 @@ static void __init set_intr_gate(unsigned int n, void *addr)
     __set_intr_gate(n, 0, addr);
 }
 
-void load_TR(void)
-{
-    struct tss64 *tss = &this_cpu(tss_page).tss;
-    struct desc_ptr old_gdt, tss_gdt = {
-        .base = (long)(this_cpu(gdt) - FIRST_RESERVED_GDT_ENTRY),
-        .limit = LAST_RESERVED_GDT_BYTE
-    };
-
-    _set_tssldt_desc(
-        this_cpu(gdt) + TSS_ENTRY - FIRST_RESERVED_GDT_ENTRY,
-        (unsigned long)tss, sizeof(*tss) - 1, SYS_DESC_tss_avail);
-    _set_tssldt_desc(
-        this_cpu(compat_gdt) + TSS_ENTRY - FIRST_RESERVED_GDT_ENTRY,
-        (unsigned long)tss, sizeof(*tss) - 1, SYS_DESC_tss_busy);
-
-    /* Switch to non-compat GDT (which has B bit clear) to execute LTR. */
-    asm volatile (
-        "sgdt %0; lgdt %2; ltr %w1; lgdt %0"
-        : "=m" (old_gdt) : "rm" (TSS_SELECTOR), "m" (tss_gdt) : "memory" );
-}
-
 static unsigned int calc_ler_msr(void)
 {
     switch ( boot_cpu_data.x86_vendor )
diff --git a/xen/include/asm-x86/desc.h b/xen/include/asm-x86/desc.h
index 603b9a9013..24db3e9510 100644
--- a/xen/include/asm-x86/desc.h
+++ b/xen/include/asm-x86/desc.h
@@ -216,8 +216,6 @@ DECLARE_PER_CPU(seg_desc_t *, compat_gdt);
 DECLARE_PER_CPU(l1_pgentry_t, compat_gdt_l1e);
 DECLARE_PER_CPU(bool, full_gdt_loaded);
 
-extern void load_TR(void);
-
 static inline void lgdt(const struct desc_ptr *gdtr)
 {
     __asm__ __volatile__ ( "lgdt %0" :: "m" (*gdtr) : "memory" );
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel