Commit 8840e14c authored by Vineet Gupta's avatar Vineet Gupta

ARC: mm: Improve Duplicate PD Fault handler

 - Move the verbosity knob from .data to .bss by using inverted logic
 - No need to readout PD1 descriptor
 - clip the non pfn bits of PD0 to avoid clipping inside the loop
Signed-off-by: default avatarVineet Gupta <vgupta@synopsys.com>
parent 9acdc911
...@@ -856,15 +856,15 @@ void arc_mmu_init(void) ...@@ -856,15 +856,15 @@ void arc_mmu_init(void)
* the duplicate one. * the duplicate one.
* -Knob to be verbose abt it.(TODO: hook them up to debugfs) * -Knob to be verbose abt it.(TODO: hook them up to debugfs)
*/ */
volatile int dup_pd_verbose = 1;/* Be slient abt it or complain (default) */ volatile int dup_pd_silent; /* Be slient abt it or complain (default) */
void do_tlb_overlap_fault(unsigned long cause, unsigned long address, void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
struct pt_regs *regs) struct pt_regs *regs)
{ {
int set, way, n;
unsigned long flags, is_valid;
struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu;
unsigned int pd0[mmu->ways], pd1[mmu->ways]; unsigned int pd0[mmu->ways];
unsigned long flags;
int set;
local_irq_save(flags); local_irq_save(flags);
...@@ -874,14 +874,16 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, ...@@ -874,14 +874,16 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
/* loop thru all sets of TLB */ /* loop thru all sets of TLB */
for (set = 0; set < mmu->sets; set++) { for (set = 0; set < mmu->sets; set++) {
int is_valid, way;
/* read out all the ways of current set */ /* read out all the ways of current set */
for (way = 0, is_valid = 0; way < mmu->ways; way++) { for (way = 0, is_valid = 0; way < mmu->ways; way++) {
write_aux_reg(ARC_REG_TLBINDEX, write_aux_reg(ARC_REG_TLBINDEX,
SET_WAY_TO_IDX(mmu, set, way)); SET_WAY_TO_IDX(mmu, set, way));
write_aux_reg(ARC_REG_TLBCOMMAND, TLBRead); write_aux_reg(ARC_REG_TLBCOMMAND, TLBRead);
pd0[way] = read_aux_reg(ARC_REG_TLBPD0); pd0[way] = read_aux_reg(ARC_REG_TLBPD0);
pd1[way] = read_aux_reg(ARC_REG_TLBPD1);
is_valid |= pd0[way] & _PAGE_PRESENT; is_valid |= pd0[way] & _PAGE_PRESENT;
pd0[way] &= PAGE_MASK;
} }
/* If all the WAYS in SET are empty, skip to next SET */ /* If all the WAYS in SET are empty, skip to next SET */
...@@ -890,33 +892,31 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, ...@@ -890,33 +892,31 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
/* Scan the set for duplicate ways: needs a nested loop */ /* Scan the set for duplicate ways: needs a nested loop */
for (way = 0; way < mmu->ways - 1; way++) { for (way = 0; way < mmu->ways - 1; way++) {
int n;
if (!pd0[way]) if (!pd0[way])
continue; continue;
for (n = way + 1; n < mmu->ways; n++) { for (n = way + 1; n < mmu->ways; n++) {
if ((pd0[way] & PAGE_MASK) == if (pd0[way] != pd0[n])
(pd0[n] & PAGE_MASK)) { continue;
if (dup_pd_verbose) { if (!dup_pd_silent)
pr_info("Duplicate PD's @" pr_info("Dup TLB PD0 %08x @ set %d ways %d,%d\n",
"[%d:%d]/[%d:%d]\n", pd0[way], set, way, n);
set, way, set, n);
pr_info("TLBPD0[%u]: %08x\n",
way, pd0[way]);
}
/* /*
* clear entry @way and not @n. This is * clear entry @way and not @n.
* critical to our optimised loop * This is critical to our optimised loop
*/ */
pd0[way] = pd1[way] = 0; pd0[way] = 0;
write_aux_reg(ARC_REG_TLBINDEX, write_aux_reg(ARC_REG_TLBINDEX,
SET_WAY_TO_IDX(mmu, set, way)); SET_WAY_TO_IDX(mmu, set, way));
__tlb_entry_erase(); __tlb_entry_erase();
} }
} }
} }
}
local_irq_restore(flags); local_irq_restore(flags);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment