Hi Dan, On Sat, Jun 25, 2005 at 06:24:47PM -0400, Dan Malek wrote: > > On Jun 25, 2005, at 10:53 AM, Marcelo Tosatti wrote: > > >Dan: I dont think ioremap() is an issue because it never works inside > >the > >kernel's static virtual address space (which is the only one we're > >interested > >in having pinned at the moment). > > Take a close look at the initialization code. I believe it also > pins the IMMR space, which is subject to ioremap().
OK. Now that makes me think that the IMMR pinned entry is also always thrashed by the tlbie at map_page() :( The IMMR space is a 16kB window (correct?), so I wonder if it might be better to the use occupied pinned slot for another more accessed region (an 8MB one preferably!). > > source "drivers/Kconfig" > >diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S > >--- a/arch/ppc/kernel/misc.S > >+++ b/arch/ppc/kernel/misc.S > >@@ -565,6 +565,19 @@ _GLOBAL(_tlbie) > > SYNC_601 > > isync > > #else /* CONFIG_SMP */ > >+#ifdef CONFIG_DEBUG_PIN_TLBIE > >+/* check if the address being invalidated overlaps with the pinned > >region */ > >+ lis r4,(pin_area_start)@ha > >+ lwz r5,(pin_area_start)@l(4) > >+ cmplw r3, r5 > >+ blt 11f > >+ lis r4,(pin_area_end)@ha > >+ lwz r5,(pin_area_end)@l(4) > >+ cmplw r3, r5 > >+ bge 11f > >+ trap > >+#endif > >+11: > > tlbie r3 > > sync > > We don't need this kind of assembly code on the 8xx. Just define > _tlbie as a macro (which has always been done) and write this debug > stuff as C code. OK, makes sense. > >+#ifdef CONFIG_PIN_TLB > >+unsigned long pin_area_start = KERNELBASE; > >+unsigned long pin_area_end = KERNELBASE + 0x00800000; > >+#endif > > This only covers the kernel instruction space. We pin 24M bytes > of data plus 8M bytes of IMMR. Ok, I'll represent the pinned regions by a node structure ordered on a linked list and use that for both map_page() and the tlbie debugging aid. > >+#ifdef CONFIG_PIN_TLB > >+ if (va < pin_area_start || va >= pin_area_end) > >+#endif > >+ flush_HPTE(0, va, pmd_val(*pd)); > > We really want to see this generate an error. We shouldn't be > calling this on any of the pinned spaces. In the case of initially > mapping the kernel space, we should set up the page tables but > not call this far down that we get here. But the page tables are setup at this level: int map_page(unsigned long va, phys_addr_t pa, int flags) { pmd_t *pd; pte_t *pg; int err = -ENOMEM; spin_lock(&init_mm.page_table_lock); /* Use upper 10 bits of VA to index the first level map */ pd = pmd_offset(pgd_offset_k(va), va); /* Use middle 10 bits of VA to index the second-level map */ pg = pte_alloc_kernel(&init_mm, pd, va); if (pg != 0) { err = 0; set_pte(pg, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags))); if (mem_init_done) #ifdef CONFIG_PIN_TLB if (va < pin_area_start || va > pin_area_end) #endif flush_HPTE(0, va, pmd_val(*pd));