diff options
| -rw-r--r-- | arch/x86/xen/enlighten.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 225ffdc3c4ca..9c808693afad 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 | */ |
| 126 | static int have_vcpu_info_placement = 1; | 126 | static int have_vcpu_info_placement = 1; |
| 127 | 127 | ||
| 128 | struct 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 | */ | ||
| 139 | static DEFINE_PER_CPU(struct tls_descs, shadow_tls_desc); | ||
| 140 | |||
| 128 | static void clamp_max_cpus(void) | 141 | static 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, | |||
| 548 | static void load_TLS_descriptor(struct thread_struct *t, | 561 | static 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 | } |
