From: <bst...@fu...> - 2005-02-17 16:38:19
|
From: Bodo Stroesser <bst...@fu...> fix_range_common and flush_tlb_kernel_range_common don't work correctly, if a PGD (or PUD or PMD) is not present and start_addr (resp. start) is not aligned to a PGD boundary (or PUD or PMD boundary). Signed-off-by: Bodo Stroesser <bst...@fu...> --- diff -puN arch/um/kernel/tlb.c~fix_range_common arch/um/kernel/tlb.c --- linux-2.6.11-rc3-mm2/arch/um/kernel/tlb.c~fix_range_common 2005-02-17 17:07:06.000000000 +0100 +++ linux-2.6.11-rc3-mm2-root/arch/um/kernel/tlb.c 2005-02-17 17:23:19.000000000 +0100 @@ -170,46 +170,46 @@ void fix_range_common(struct mm_struct * for(addr = start_addr; addr < end_addr;){ npgd = pgd_offset(mm, addr); if(!pgd_present(*npgd)){ + end = (addr + PGDIR_SIZE) & ~(PGDIR_SIZE - 1); + if(end > end_addr) + end = end_addr; if(force || pgd_newpage(*npgd)){ - end = addr + PGDIR_SIZE; - if(end > end_addr) - end = end_addr; op_index = add_munmap(addr, end - addr, ops, op_index, last_op, mmu, &flush, do_ops); pgd_mkuptodate(*npgd); } - addr += PGDIR_SIZE; + addr = end; continue; } npud = pud_offset(npgd, addr); if(!pud_present(*npud)){ + end = (addr + PUD_SIZE) & ~(PUD_SIZE - 1); + if(end > end_addr) + end = end_addr; if(force || pud_newpage(*npud)){ - end = addr + PUD_SIZE; - if(end > end_addr) - end = end_addr; op_index = add_munmap(addr, end - addr, ops, op_index, last_op, mmu, &flush, do_ops); pud_mkuptodate(*npud); } - addr += PUD_SIZE; + addr = end; continue; } npmd = pmd_offset(npud, addr); if(!pmd_present(*npmd)){ + end = (addr + PMD_SIZE) & ~(PMD_SIZE - 1); + if(end > end_addr) + end = end_addr; if(force || pmd_newpage(*npmd)){ - end = addr + PMD_SIZE; - if(end > end_addr) - end = end_addr; op_index = add_munmap(addr, end - addr, ops, op_index, last_op, mmu, &flush, do_ops); pmd_mkuptodate(*npmd); } - addr += PMD_SIZE; + addr = end; continue; } @@ -259,52 +259,52 @@ int flush_tlb_kernel_range_common(unsign for(addr = start; addr < end;){ pgd = pgd_offset(mm, addr); if(!pgd_present(*pgd)){ + last = (addr + PGDIR_SIZE) & ~(PGDIR_SIZE - 1); + if(last > end) + last = end; if(pgd_newpage(*pgd)){ updated = 1; - last = addr + PGDIR_SIZE; - if(last > end) - last = end; err = os_unmap_memory((void *) addr, last - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); } - addr += PGDIR_SIZE; + addr = last; continue; } pud = pud_offset(pgd, addr); if(!pud_present(*pud)){ + last = (addr + PUD_SIZE) & ~(PUD_SIZE - 1); + if(last > end) + last = end; if(pud_newpage(*pud)){ updated = 1; - last = addr + PUD_SIZE; - if(last > end) - last = end; err = os_unmap_memory((void *) addr, last - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); } - addr += PUD_SIZE; + addr = last; continue; } pmd = pmd_offset(pud, addr); if(!pmd_present(*pmd)){ + last = (addr + PMD_SIZE) & ~(PMD_SIZE - 1); + if(last > end) + last = end; if(pmd_newpage(*pmd)){ updated = 1; - last = addr + PMD_SIZE; - if(last > end) - last = end; err = os_unmap_memory((void *) addr, last - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); } - addr += PMD_SIZE; + addr = last; continue; } _ |