aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/xen/enlighten.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 225ffdc3c4c..9c808693afa 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -125,6 +125,19 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info;
125 */ 125 */
126static int have_vcpu_info_placement = 1; 126static int have_vcpu_info_placement = 1;
127 127
128struct tls_descs {
129 struct desc_struct desc[3];
130};
131
132/*
133 * Updating the 3 TLS descriptors in the GDT on every task switch is
134 * surprisingly expensive so we avoid updating them if they haven't
135 * changed. Since Xen writes different descriptors than the one
136 * passed in the update_descriptor hypercall we keep shadow copies to
137 * compare against.
138 */
139static DEFINE_PER_CPU(struct tls_descs, shadow_tls_desc);
140
128static void clamp_max_cpus(void) 141static void clamp_max_cpus(void)
129{ 142{
130#ifdef CONFIG_SMP 143#ifdef CONFIG_SMP
@@ -548,9 +561,19 @@ static inline bool desc_equal(const struct desc_struct *d1,
548static void load_TLS_descriptor(struct thread_struct *t, 561static void load_TLS_descriptor(struct thread_struct *t,
549 unsigned int cpu, unsigned int i) 562 unsigned int cpu, unsigned int i)
550{ 563{
551 struct desc_struct *gdt = get_cpu_gdt_table(cpu); 564 struct desc_struct *shadow = &per_cpu(shadow_tls_desc, cpu).desc[i];
552 xmaddr_t maddr = arbitrary_virt_to_machine(&gdt[GDT_ENTRY_TLS_MIN+i]); 565 struct desc_struct *gdt;
553 struct multicall_space mc = __xen_mc_entry(0); 566 xmaddr_t maddr;
567 struct multicall_space mc;
568
569 if (desc_equal(shadow, &t->tls_array[i]))
570 return;
571
572 *shadow = t->tls_array[i];
573
574 gdt = get_cpu_gdt_table(cpu);
575 maddr = arbitrary_virt_to_machine(&gdt[GDT_ENTRY_TLS_MIN+i]);
576 mc = __xen_mc_entry(0);
554 577
555 MULTI_update_descriptor(mc.mc, maddr.maddr, t->tls_array[i]); 578 MULTI_update_descriptor(mc.mc, maddr.maddr, t->tls_array[i]);
556} 579}