]> err.no Git - linux-2.6/blobdiff - arch/i386/kernel/vm86.c
Merge master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / arch / i386 / kernel / vm86.c
index d3b4c540eb6435b10a148b0a454207704606be2c..fc1993564f98c35a4ca31902ca01fa3a1f9a8664 100644 (file)
@@ -134,17 +134,16 @@ struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs)
        return ret;
 }
 
-static void mark_screen_rdonly(struct task_struct * tsk)
+static void mark_screen_rdonly(struct mm_struct *mm)
 {
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
-       pte_t *pte, *mapped;
+       pte_t *pte;
+       spinlock_t *ptl;
        int i;
 
-       preempt_disable();
-       spin_lock(&tsk->mm->page_table_lock);
-       pgd = pgd_offset(tsk->mm, 0xA0000);
+       pgd = pgd_offset(mm, 0xA0000);
        if (pgd_none_or_clear_bad(pgd))
                goto out;
        pud = pud_offset(pgd, 0xA0000);
@@ -153,16 +152,14 @@ static void mark_screen_rdonly(struct task_struct * tsk)
        pmd = pmd_offset(pud, 0xA0000);
        if (pmd_none_or_clear_bad(pmd))
                goto out;
-       pte = mapped = pte_offset_map(pmd, 0xA0000);
+       pte = pte_offset_map_lock(mm, pmd, 0xA0000, &ptl);
        for (i = 0; i < 32; i++) {
                if (pte_present(*pte))
                        set_pte(pte, pte_wrprotect(*pte));
                pte++;
        }
-       pte_unmap(mapped);
+       pte_unmap_unlock(pte, ptl);
 out:
-       spin_unlock(&tsk->mm->page_table_lock);
-       preempt_enable();
        flush_tlb();
 }
 
@@ -222,7 +219,7 @@ asmlinkage int sys_vm86(struct pt_regs regs)
                        goto out;
                case VM86_PLUS_INSTALL_CHECK:
                        /* NOTE: on old vm86 stuff this will return the error
-                          from verify_area(), because the subfunction is
+                          from access_ok(), because the subfunction is
                           interpreted as (invalid) address to vm86_struct.
                           So the installation check works.
                         */
@@ -294,8 +291,8 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
  */
        info->regs32->eax = 0;
        tsk->thread.saved_esp0 = tsk->thread.esp0;
-       asm volatile("mov %%fs,%0":"=m" (tsk->thread.saved_fs));
-       asm volatile("mov %%gs,%0":"=m" (tsk->thread.saved_gs));
+       savesegment(fs, tsk->thread.saved_fs);
+       savesegment(gs, tsk->thread.saved_gs);
 
        tss = &per_cpu(init_tss, get_cpu());
        tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
@@ -306,7 +303,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
 
        tsk->thread.screen_bitmap = info->screen_bitmap;
        if (info->flags & VM86_SCREEN_BITMAP)
-               mark_screen_rdonly(tsk);
+               mark_screen_rdonly(tsk->mm);
        __asm__ __volatile__(
                "xorl %%eax,%%eax; movl %%eax,%%fs; movl %%eax,%%gs\n\t"
                "movl %0,%%esp\n\t"
@@ -542,7 +539,7 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
        unsigned char opcode;
        unsigned char __user *csp;
        unsigned char __user *ssp;
-       unsigned short ip, sp;
+       unsigned short ip, sp, orig_flags;
        int data32, pref_done;
 
 #define CHECK_IF_IN_TRAP \
@@ -551,8 +548,12 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
 #define VM86_FAULT_RETURN do { \
        if (VMPI.force_return_for_pic  && (VEFLAGS & (IF_MASK | VIF_MASK))) \
                return_to_32bit(regs, VM86_PICRETURN); \
+       if (orig_flags & TF_MASK) \
+               handle_vm86_trap(regs, 0, 1); \
        return; } while (0)
 
+       orig_flags = *(unsigned short *)&regs->eflags;
+
        csp = (unsigned char __user *) (regs->cs << 4);
        ssp = (unsigned char __user *) (regs->ss << 4);
        sp = SP(regs);