x86, wakeup, sleep: Use pvops functions for changing GDT entries
authorkonrad@kernel.org <konrad@kernel.org>
Fri, 5 Apr 2013 20:42:24 +0000 (16:42 -0400)
committerH. Peter Anvin <hpa@linux.intel.com>
Thu, 11 Apr 2013 22:41:15 +0000 (15:41 -0700)
We check the TSS descriptor before we try to dereference it.
Also we document what the value '9' actually means using the
AMD64 Architecture Programmer's Manual Volume 2, pg 90:
"Hex value 9: Available 64-bit TSS" and pg 91:
"The available 32-bit TSS (09h), which is redefined as the
available 64-bit TSS."

Without this, on Xen, where the GDT is available as R/O (to
protect the hypervisor from the guest modifying it), we end up
with a pagetable fault.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Link: http://lkml.kernel.org/r/1365194544-14648-5-git-send-email-konrad.wilk@oracle.com
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
arch/x86/power/cpu.c

index 82c39c5323491339950c8fa91b7f10624b6a2e07..168da8429032cbc94ba02fa77b6428be5c57e92e 100644 (file)
@@ -132,7 +132,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
@@ -141,7 +144,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