[PATCH] 8xx: map_page() skip pinned region and tlbie debugging aid
Marcelo Tosatti
marcelo.tosatti at cyclades.com
Mon Jun 27 00:30:04 EST 2005
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));
More information about the Linuxppc-embedded
mailing list