diff options
author | Paul Mundt <lethal@linux-sh.org> | 2009-08-15 03:06:41 +0900 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-08-15 03:06:41 +0900 |
commit | 8010fbe7a67c2f993cbb11b9d8b7e98528256dd1 (patch) | |
tree | 861fc7d33fe08b33818b9401f2ba1b32edd82505 | |
parent | 112e58471de3431fbd03dee514777ad4a66a77b2 (diff) |
sh: TLB fast path optimizations for load/store exceptions.
This only bothers with the TLB entry flush in the case of the initial
page write exception, as it is unecessary in the case of the load/store
exceptions.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r-- | arch/sh/kernel/cpu/sh3/entry.S | 2 | ||||
-rw-r--r-- | arch/sh/mm/fault_32.c | 26 |
2 files changed, 14 insertions, 14 deletions
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index bbaf2bd118e..a701fac8ed4 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S @@ -124,7 +124,7 @@ ENTRY(tlb_miss_store) .align 2 ENTRY(initial_page_write) bra call_handle_tlbmiss - mov #1, r5 + mov #2, r5 .align 2 ENTRY(tlb_protection_violation_load) diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index 41840647f65..f1c93c880ed 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c @@ -327,7 +327,6 @@ handle_tlbmiss(struct pt_regs *regs, unsigned long writeaccess, pmd_t *pmd; pte_t *pte; pte_t entry; - int ret = 1; /* * We don't take page faults for P1, P2, and parts of P4, these @@ -338,40 +337,41 @@ handle_tlbmiss(struct pt_regs *regs, unsigned long writeaccess, pgd = pgd_offset_k(address); } else { if (unlikely(address >= TASK_SIZE || !current->mm)) - goto out; + return 1; pgd = pgd_offset(current->mm, address); } pud = pud_offset(pgd, address); if (pud_none_or_clear_bad(pud)) - goto out; + return 1; pmd = pmd_offset(pud, address); if (pmd_none_or_clear_bad(pmd)) - goto out; + return 1; pte = pte_offset_kernel(pmd, address); entry = *pte; if (unlikely(pte_none(entry) || pte_not_present(entry))) - goto out; + return 1; if (unlikely(writeaccess && !pte_write(entry))) - goto out; + return 1; if (writeaccess) entry = pte_mkdirty(entry); entry = pte_mkyoung(entry); + set_pte(pte, entry); + #if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SMP) /* - * ITLB is not affected by "ldtlb" instruction. - * So, we need to flush the entry by ourselves. + * SH-4 does not set MMUCR.RC to the corresponding TLB entry in + * the case of an initial page write exception, so we need to + * flush it in order to avoid potential TLB entry duplication. */ - local_flush_tlb_one(get_asid(), address & PAGE_MASK); + if (writeaccess == 2) + local_flush_tlb_one(get_asid(), address & PAGE_MASK); #endif - set_pte(pte, entry); update_mmu_cache(NULL, address, entry); - ret = 0; -out: - return ret; + return 0; } |