memcpy(newldt, pc->ldt, oldsize*LDT_ENTRY_SIZE);
oldldt = pc->ldt;
memset(newldt+oldsize*LDT_ENTRY_SIZE, 0, (mincount-oldsize)*LDT_ENTRY_SIZE);
- wmb();
pc->ldt = newldt;
+ wmb();
pc->size = mincount;
+ wmb();
+
if (reload) {
load_LDT(pc);
#ifdef CONFIG_SMP
- if (current->mm->cpu_vm_mask != (1<<smp_processor_id()))
+ preempt_disable();
+ if (current->mm->cpu_vm_mask != (1 << smp_processor_id()))
smp_call_function(flush_ldt, 0, 1, 1);
+ preempt_enable();
#endif
}
- wmb();
if (oldsize) {
if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE)
vfree(oldldt);
static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
{
int err = alloc_ldt(new, old->size, 0);
- if (err < 0) {
- printk(KERN_WARNING "ldt allocation failed\n");
- new->size = 0;
+ if (err < 0)
return err;
- }
memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE);
return 0;
}
static inline void clear_LDT(void)
{
- set_ldt_desc(smp_processor_id(), &default_ldt[0], 5);
+ int cpu = get_cpu();
+
+ set_ldt_desc(cpu, &default_ldt[0], 5);
load_LDT_desc();
+ put_cpu();
}
/*
* load one particular LDT into the current CPU
*/
-static inline void load_LDT (mm_context_t *pc)
+static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
{
void *segments = pc->ldt;
int count = pc->size;
count = 5;
}
- set_ldt_desc(smp_processor_id(), segments, count);
+ set_ldt_desc(cpu, segments, count);
load_LDT_desc();
}
+static inline void load_LDT(mm_context_t *pc)
+{
+ int cpu = get_cpu();
+ load_LDT_nolock(pc, cpu);
+ put_cpu();
+}
+
#endif /* !__ASSEMBLY__ */
#endif
typedef struct {
int size;
struct semaphore sem;
- void * ldt;
+ void *ldt;
} mm_context_t;
#endif
* load the LDT, if the LDT is different:
*/
if (unlikely(prev->context.ldt != next->context.ldt))
- load_LDT(&next->context);
+ load_LDT_nolock(&next->context, cpu);
}
#ifdef CONFIG_SMP
else {
* tlb flush IPI delivery. We must reload %cr3.
*/
load_cr3(next->pgd);
- load_LDT(&next->context);
+ load_LDT_nolock(&next->context, cpu);
}
}
#endif