]> err.no Git - linux-2.6/blobdiff - arch/x86/kernel/ldt.c
Merge branch 'generic-ipi' into generic-ipi-for-linus
[linux-2.6] / arch / x86 / kernel / ldt.c
index a8cdca3615bf632afae851a75391a7862959f528..a8449571858ae9dae444076d7c6b28daff795ee9 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/vmalloc.h>
-#include <linux/slab.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -21,9 +20,9 @@
 #include <asm/mmu_context.h>
 
 #ifdef CONFIG_SMP
-static void flush_ldt(void *null)
+static void flush_ldt(void *current_mm)
 {
-       if (current->active_mm)
+       if (current->active_mm == current_mm)
                load_LDT(&current->active_mm->context);
 }
 #endif
@@ -36,11 +35,12 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
        if (mincount <= pc->size)
                return 0;
        oldsize = pc->size;
-       mincount = (mincount + 511) & (~511);
+       mincount = (mincount + (PAGE_SIZE / LDT_ENTRY_SIZE - 1)) &
+                       (~(PAGE_SIZE / LDT_ENTRY_SIZE - 1));
        if (mincount * LDT_ENTRY_SIZE > PAGE_SIZE)
                newldt = vmalloc(mincount * LDT_ENTRY_SIZE);
        else
-               newldt = kmalloc(mincount * LDT_ENTRY_SIZE, GFP_KERNEL);
+               newldt = (void *)__get_free_page(GFP_KERNEL);
 
        if (!newldt)
                return -ENOMEM;
@@ -68,7 +68,7 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
                load_LDT(pc);
                mask = cpumask_of_cpu(smp_processor_id());
                if (!cpus_equal(current->mm->cpu_vm_mask, mask))
-                       smp_call_function(flush_ldt, NULL, 1, 1);
+                       smp_call_function(flush_ldt, current->mm, 1);
                preempt_enable();
 #else
                load_LDT(pc);
@@ -78,7 +78,7 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
                if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE)
                        vfree(oldldt);
                else
-                       kfree(oldldt);
+                       put_page(virt_to_page(oldldt));
        }
        return 0;
 }
@@ -129,7 +129,7 @@ void destroy_context(struct mm_struct *mm)
                if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE)
                        vfree(mm->context.ldt);
                else
-                       kfree(mm->context.ldt);
+                       put_page(virt_to_page(mm->context.ldt));
                mm->context.size = 0;
        }
 }
@@ -186,7 +186,7 @@ static int read_default_ldt(void __user *ptr, unsigned long bytecount)
 static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
 {
        struct mm_struct *mm = current->mm;
-       __u32 entry_1, entry_2;
+       struct desc_struct ldt;
        int error;
        struct user_desc ldt_info;
 
@@ -218,21 +218,18 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
        /* Allow LDTs to be cleared by the user. */
        if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
                if (oldmode || LDT_empty(&ldt_info)) {
-                       entry_1 = 0;
-                       entry_2 = 0;
+                       memset(&ldt, 0, sizeof(ldt));
                        goto install;
                }
        }
 
-       entry_1 = LDT_entry_a(&ldt_info);
-       entry_2 = LDT_entry_b(&ldt_info);
+       fill_ldt(&ldt, &ldt_info);
        if (oldmode)
-               entry_2 &= ~(1 << 20);
+               ldt.avl = 0;
 
        /* Install the new entry ...  */
 install:
-       write_ldt_entry(mm->context.ldt, ldt_info.entry_number, entry_1,
-                       entry_2);
+       write_ldt_entry(mm->context.ldt, ldt_info.entry_number, &ldt);
        error = 0;
 
 out_unlock: