# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1237482246 0
# Node ID e1562a36094e89fdebd952ccbfc78b9d3de2649f
# Parent 633e08774dab5b411ef7614fb9fc2e1a5eb2cb9c
x86: Ensure we execute LTR when running on non-compat GDT which has
busy bit clear in TSS descriptor.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/arch/x86/acpi/suspend.c | 6 +-----
xen/arch/x86/cpu/common.c | 3 +--
xen/arch/x86/traps.c | 23 +++++++++++++++++------
xen/include/asm-x86/desc.h | 4 +---
4 files changed, 20 insertions(+), 16 deletions(-)
diff -r 633e08774dab -r e1562a36094e xen/arch/x86/acpi/suspend.c
--- a/xen/arch/x86/acpi/suspend.c Thu Mar 19 14:01:56 2009 +0000
+++ b/xen/arch/x86/acpi/suspend.c Thu Mar 19 17:04:06 2009 +0000
@@ -31,13 +31,9 @@ void save_rest_processor_state(void)
void restore_rest_processor_state(void)
{
- int cpu = smp_processor_id();
- struct tss_struct *t = &init_tss[cpu];
struct vcpu *v = current;
- /* Rewriting the TSS desc is necessary to clear the Busy flag. */
- set_tss_desc(cpu, t);
- load_TR(cpu);
+ load_TR();
#if defined(CONFIG_X86_64)
/* Recover syscall MSRs */
diff -r 633e08774dab -r e1562a36094e xen/arch/x86/cpu/common.c
--- a/xen/arch/x86/cpu/common.c Thu Mar 19 14:01:56 2009 +0000
+++ b/xen/arch/x86/cpu/common.c Thu Mar 19 17:04:06 2009 +0000
@@ -614,8 +614,7 @@ void __cpuinit cpu_init(void)
BUG_ON((get_stack_bottom() & 15) != 0);
t->rsp0 = get_stack_bottom();
#endif
- set_tss_desc(cpu,t);
- load_TR(cpu);
+ load_TR();
asm volatile ( "lldt %%ax" : : "a" (0) );
/* Clear all 6 debug registers: */
diff -r 633e08774dab -r e1562a36094e xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c Thu Mar 19 14:01:56 2009 +0000
+++ b/xen/arch/x86/traps.c Thu Mar 19 17:04:06 2009 +0000
@@ -3004,20 +3004,31 @@ void set_intr_gate(unsigned int n, void
__set_intr_gate(n, 0, addr);
}
-void set_tss_desc(unsigned int n, void *addr)
-{
+void load_TR(void)
+{
+ struct tss_struct *tss = &init_tss[smp_processor_id()];
+ struct desc_ptr old_gdt, tss_gdt = {
+ .base = (long)(this_cpu(gdt_table) - FIRST_RESERVED_GDT_ENTRY),
+ .limit = LAST_RESERVED_GDT_BYTE
+ };
+
_set_tssldt_desc(
- per_cpu(gdt_table, n) + TSS_ENTRY - FIRST_RESERVED_GDT_ENTRY,
- (unsigned long)addr,
+ this_cpu(gdt_table) + TSS_ENTRY - FIRST_RESERVED_GDT_ENTRY,
+ (unsigned long)tss,
offsetof(struct tss_struct, __cacheline_filler) - 1,
9);
#ifdef CONFIG_COMPAT
_set_tssldt_desc(
- per_cpu(compat_gdt_table, n) + TSS_ENTRY - FIRST_RESERVED_GDT_ENTRY,
- (unsigned long)addr,
+ this_cpu(compat_gdt_table) + TSS_ENTRY - FIRST_RESERVED_GDT_ENTRY,
+ (unsigned long)tss,
offsetof(struct tss_struct, __cacheline_filler) - 1,
11);
#endif
+
+ /* Switch to non-compat GDT (which has B bit clear) to execute LTR. */
+ asm volatile (
+ "sgdt %1; lgdt %2; ltr %%ax; lgdt %1"
+ : : "a" (TSS_ENTRY << 3), "m" (old_gdt), "m" (tss_gdt) : "memory" );
}
void __devinit percpu_traps_init(void)
diff -r 633e08774dab -r e1562a36094e xen/include/asm-x86/desc.h
--- a/xen/include/asm-x86/desc.h Thu Mar 19 14:01:56 2009 +0000
+++ b/xen/include/asm-x86/desc.h Thu Mar 19 17:04:06 2009 +0000
@@ -56,8 +56,6 @@
#endif
#ifndef __ASSEMBLY__
-
-#define load_TR(n) __asm__ __volatile__ ("ltr %%ax" : : "a" (TSS_ENTRY<<3) )
#if defined(__x86_64__)
#define GUEST_KERNEL_RPL(d) (is_pv_32bit_domain(d) ? 1 : 3)
@@ -219,7 +217,7 @@ DECLARE_PER_CPU(struct desc_struct *, co
#endif
extern void set_intr_gate(unsigned int irq, void * addr);
-extern void set_tss_desc(unsigned int n, void *addr);
+extern void load_TR(void);
#endif /* !__ASSEMBLY__ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|