summaryrefslogtreecommitdiffstats
path: root/arch/x86/power/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/power/cpu.c')
-rw-r--r--arch/x86/power/cpu.c28
1 files changed, 17 insertions, 11 deletions
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 3c68768d7a75..1cf5b300305e 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -25,16 +25,12 @@
#include <asm/cpu.h>
#ifdef CONFIG_X86_32
-static struct saved_context saved_context;
-
unsigned long saved_context_ebx;
unsigned long saved_context_esp, saved_context_ebp;
unsigned long saved_context_esi, saved_context_edi;
unsigned long saved_context_eflags;
-#else
-/* CONFIG_X86_64 */
-struct saved_context saved_context;
#endif
+struct saved_context saved_context;
/**
* __save_processor_state - save CPU registers before creating a
@@ -62,13 +58,20 @@ static void __save_processor_state(struct saved_context *ctxt)
* descriptor tables
*/
#ifdef CONFIG_X86_32
- store_gdt(&ctxt->gdt);
store_idt(&ctxt->idt);
#else
/* CONFIG_X86_64 */
- store_gdt((struct desc_ptr *)&ctxt->gdt_limit);
store_idt((struct desc_ptr *)&ctxt->idt_limit);
#endif
+ /*
+ * We save it here, but restore it only in the hibernate case.
+ * For ACPI S3 resume, this is loaded via 'early_gdt_desc' in 64-bit
+ * mode in "secondary_startup_64". In 32-bit mode it is done via
+ * 'pmode_gdt' in wakeup_start.
+ */
+ ctxt->gdt_desc.size = GDT_SIZE - 1;
+ ctxt->gdt_desc.address = (unsigned long)get_cpu_gdt_table(smp_processor_id());
+
store_tr(ctxt->tr);
/* XMM0..XMM15 should be handled by kernel_fpu_begin(). */
@@ -135,7 +138,10 @@ static void fix_processor_context(void)
{
int cpu = smp_processor_id();
struct tss_struct *t = &per_cpu(init_tss, cpu);
-
+#ifdef CONFIG_X86_64
+ struct desc_struct *desc = get_cpu_gdt_table(cpu);
+ tss_desc tss;
+#endif
set_tss_desc(cpu, t); /*
* This just modifies memory; should not be
* necessary. But... This is necessary, because
@@ -144,7 +150,9 @@ static void fix_processor_context(void)
*/
#ifdef CONFIG_X86_64
- get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9;
+ memcpy(&tss, &desc[GDT_ENTRY_TSS], sizeof(tss_desc));
+ tss.type = 0x9; /* The available 64-bit TSS (see AMD vol 2, pg 91 */
+ write_gdt_entry(desc, GDT_ENTRY_TSS, &tss, DESC_TSS);
syscall_init(); /* This sets MSR_*STAR and related */
#endif
@@ -183,11 +191,9 @@ static void __restore_processor_state(struct saved_context *ctxt)
* ltr is done i fix_processor_context().
*/
#ifdef CONFIG_X86_32
- load_gdt(&ctxt->gdt);
load_idt(&ctxt->idt);
#else
/* CONFIG_X86_64 */
- load_gdt((const struct desc_ptr *)&ctxt->gdt_limit);
load_idt((const struct desc_ptr *)&ctxt->idt_limit);
#endif
OpenPOWER on IntegriCloud