aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm
diff options
context:
space:
mode:
authorKirill A. Shutemov <kirill@shutemov.name>2010-07-22 08:20:22 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-07-27 05:48:41 -0400
commit33a9c41bf5d8adae9d882513e617c4c645195e71 (patch)
treeadcb4a60ff55f9b3f88eaeeca628f7398300121e /arch/arm/mm
parent6338a6aa7c082f11d55712251e14178c68bf5869 (diff)
ARM: 6255/1: Workaround infinity loop in handling of translation faults
On ARM one Linux PGD entry contains two hardware entries (see page tables layout in pgtable.h). We normally guarantee that we always fill both L1 entries. But create_mapping() doesn't follow the rule. It can create inidividual L1 entries, so here we have to call pmd_none() check in do_translation_fault() for the entry really corresponded to address, not for the first of pair. Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm')
-rw-r--r--arch/arm/mm/fault.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 84131c832430..564b1c4829e4 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -413,7 +413,16 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
413 pmd_k = pmd_offset(pgd_k, addr); 413 pmd_k = pmd_offset(pgd_k, addr);
414 pmd = pmd_offset(pgd, addr); 414 pmd = pmd_offset(pgd, addr);
415 415
416 if (pmd_none(*pmd_k)) 416 /*
417 * On ARM one Linux PGD entry contains two hardware entries (see page
418 * tables layout in pgtable.h). We normally guarantee that we always
419 * fill both L1 entries. But create_mapping() doesn't follow the rule.
420 * It can create inidividual L1 entries, so here we have to call
421 * pmd_none() check for the entry really corresponded to address, not
422 * for the first of pair.
423 */
424 index = (addr >> SECTION_SHIFT) & 1;
425 if (pmd_none(pmd_k[index]))
417 goto bad_area; 426 goto bad_area;
418 427
419 copy_pmd(pmd, pmd_k); 428 copy_pmd(pmd, pmd_k);