diff -Naur -X exclude-files ac_cur/arch/um/kernel/tlb.c ac/arch/um/kernel/tlb.c --- ac_cur/arch/um/kernel/tlb.c Sat Nov 3 13:53:11 2001 +++ ac/arch/um/kernel/tlb.c Sat Nov 3 14:34:41 2001 @@ -12,6 +12,7 @@ #include "asm/processor.h" #include "asm/mmu_context.h" #include "asm/uaccess.h" +#include "asm/atomic.h" #include "user_util.h" #include "kern_util.h" #include "kern.h" @@ -53,7 +54,7 @@ r = 0; w = 0; } - if(force || !pte_present(*npte) || pte_newpage(*npte)){ + if(force || pte_newpage(*npte)){ if(munmap((void *) addr, PAGE_SIZE) < 0) panic("munmap failed, errno = %d\n", errno); @@ -77,14 +78,17 @@ } } -void flush_tlb_kernel_vm(void) +atomic_t vmchange_seq = ATOMIC_INIT(1); + +static void flush_kernel_vm_range(unsigned long start, unsigned long end, + int update_seq) { struct mm_struct *mm; pgd_t *npgd; pmd_t *npmd; pte_t *npte; unsigned long addr; - int r, w, x; + int r, w, x, updated = 0; mm = &init_mm; for(addr = start_vm; addr < end_vm;){ @@ -107,6 +111,7 @@ x = 1; } if(!pte_present(*npte) || pte_newpage(*npte)){ + updated = 1; if(munmap((void *) addr, PAGE_SIZE) < 0) panic("munmap failed, errno = %d\n", errno); @@ -114,13 +119,16 @@ map(addr, pte_address(*npte), PAGE_SIZE, r, w, x); } - else if(pte_newprot(*npte)) + else if(pte_newprot(*npte)){ + updated = 1; protect(addr, PAGE_SIZE, r, w, x); + } addr += PAGE_SIZE; } else { if(pmd_newpage(*npmd)){ + updated = 1; if(munmap((void *) addr, PMD_SIZE) < 0) panic("munmap failed, errno = %d\n", errno); @@ -128,6 +136,12 @@ addr += PMD_SIZE; } } + if(updated && update_seq) atomic_inc(&vmchange_seq); +} + +void flush_tlb_kernel_vm(void) +{ + flush_kernel_vm_range(start_vm, end_vm, 1); } void flush_tlb_range(struct mm_struct *mm, unsigned long start, @@ -138,16 +152,23 @@ /* Assumes that the range start ... end is entirely within * either process memory or kernel vm */ - if((start >= start_vm) && (start < end_vm)) flush_tlb_kernel_vm(); + if((start >= start_vm) && (start < end_vm)) + flush_kernel_vm_range(start, end, 1); else fix_range(mm, start, end, 0); } void flush_tlb_mm(struct mm_struct *mm) { + unsigned long seq; + if(mm != current->mm) return; fix_range(mm, 0, STACK_TOP, 0); - flush_tlb_kernel_vm(); + + seq = atomic_read(&vmchange_seq); + if(current->thread.vm_seq == seq) return; + current->thread.vm_seq = seq; + flush_kernel_vm_range(start_vm, end_vm, 0); } void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) @@ -164,7 +185,7 @@ void force_flush_all(void) { fix_range(current->mm, 0, STACK_TOP, 1); - flush_tlb_kernel_vm(); + flush_kernel_vm_range(start_vm, end_vm, 0); } pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) @@ -180,6 +201,11 @@ pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) { return(pte_offset(pmd, address)); +} + +pte_t *addr_pte(struct task_struct *task, unsigned long addr) +{ + return(pte_offset(pmd_offset(pgd_offset(task->mm, addr), addr), addr)); } /* diff -Naur -X exclude-files ac_cur/include/asm-um/pgtable.h ac/include/asm-um/pgtable.h --- ac_cur/include/asm-um/pgtable.h Sat Nov 3 14:20:44 2001 +++ ac/include/asm-um/pgtable.h Sat Nov 3 14:37:40 2001 @@ -211,9 +211,12 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval) { - *pteptr = pteval; - if(pte_present(*pteptr)) - *pteptr = pte_mknewpage(pte_mknewprot(*pteptr)); + /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so + * fix_range knows to unmap it. _PAGE_NEWPROT is specific to + * mapped pages. + */ + *pteptr = pte_mknewpage(pteval); + if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr); } /* diff -Naur -X exclude-files ac_cur/include/asm-um/processor-generic.h ac/include/asm-um/processor-generic.h --- ac_cur/include/asm-um/processor-generic.h Sat Nov 3 14:20:43 2001 +++ ac/include/asm-um/processor-generic.h Sat Nov 3 14:37:40 2001 @@ -44,7 +44,7 @@ int repeat_syscall; void *fault_addr; void *fault_catcher; - int sigreturn_syscall; + int vm_seq; struct { int op; union { @@ -118,7 +118,7 @@ err: 0, \ repeat_syscall: 0, \ fault_addr: NULL, \ - sigreturn_syscall: 0, \ + vm_seq: 0, \ request: { 0 } \ }