[RFC/PATCH] powerpc: rework 4xx PTE access and TLB miss
Kumar Gala
kumar.gala at freescale.com
Wed Jun 11 12:18:41 EST 2008
>
> Index: linux-work/include/asm-powerpc/pgtable-ppc32.h
> ===================================================================
> --- linux-work.orig/include/asm-powerpc/pgtable-ppc32.h 2008-06-10
> 18:13:47.000000000 +1000
> +++ linux-work/include/asm-powerpc/pgtable-ppc32.h 2008-06-10
> 18:16:49.000000000 +1000
> @@ -182,6 +182,9 @@ extern int icache_44x_need_flush;
> #define _PMD_SIZE_16M 0x0e0
> #define PMD_PAGE_SIZE(pmdval) (1024 << (((pmdval) & _PMD_SIZE) >> 4))
>
> +/* Until my rework is finished, 40x still needs atomic PTE updates */
> +#define PTE_ATOMIC_UPDATES 1
> +
> #elif defined(CONFIG_44x)
> /*
> * Definitions for PPC440
> @@ -253,17 +256,17 @@ extern int icache_44x_need_flush;
> */
>
> #define _PAGE_PRESENT 0x00000001 /* S: PTE valid */
> -#define _PAGE_RW 0x00000002 /* S: Write permission */
> +#define _PAGE_RW 0x00000002 /* S: Write permission */
> #define _PAGE_FILE 0x00000004 /* S: nonlinear file mapping */
> +#define _PAGE_HWEXEC 0x00000004 /* H: Execute permission */
I'm sure this is ok, but why can we overlay _PAGE_HWEXEC and _PAGE_FILE?
> #define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */
> -#define _PAGE_HWWRITE 0x00000010 /* H: Dirty & RW */
> -#define _PAGE_HWEXEC 0x00000020 /* H: Execute permission */
> -#define _PAGE_USER 0x00000040 /* S: User page */
> -#define _PAGE_ENDIAN 0x00000080 /* H: E bit */
> -#define _PAGE_GUARDED 0x00000100 /* H: G bit */
> -#define _PAGE_DIRTY 0x00000200 /* S: Page dirty */
> -#define _PAGE_NO_CACHE 0x00000400 /* H: I bit */
> -#define _PAGE_WRITETHRU 0x00000800 /* H: W bit */
> +#define _PAGE_DIRTY 0x00000010 /* S: Page dirty */
why the gap?
>
> +#define _PAGE_USER 0x00000040 /* S: User page */
> +#define _PAGE_ENDIAN 0x00000080 /* H: E bit */
> +#define _PAGE_GUARDED 0x00000100 /* H: G bit */
> +#define _PAGE_COHERENT 0x00000200 /* H: M bit */
> +#define _PAGE_NO_CACHE 0x00000400 /* H: I bit */
> +#define _PAGE_WRITETHRU 0x00000800 /* H: W bit */
>
> /* TODO: Add large page lowmem mapping support */
> #define _PMD_PRESENT 0
> @@ -273,6 +276,7 @@ extern int icache_44x_need_flush;
> /* ERPN in a PTE never gets cleared, ignore it */
> #define _PTE_NONE_MASK 0xffffffff00000000ULL
>
> +
> #elif defined(CONFIG_FSL_BOOKE)
> /*
> MMU Assist Register 3:
> @@ -315,6 +319,9 @@ extern int icache_44x_need_flush;
> #define _PMD_PRESENT_MASK (PAGE_MASK)
> #define _PMD_BAD (~PAGE_MASK)
>
> +/* Until my rework is finished, 40x still needs atomic PTE updates */
> +#define PTE_ATOMIC_UPDATES 1
fix comment
>
> +
> #elif defined(CONFIG_8xx)
> /* Definitions for 8xx embedded chips. */
> #define _PAGE_PRESENT 0x0001 /* Page is valid */
> @@ -345,6 +352,9 @@ extern int icache_44x_need_flush;
>
> #define _PTE_NONE_MASK _PAGE_ACCESSED
>
> +/* Until my rework is finished, 40x still needs atomic PTE updates */
> +#define PTE_ATOMIC_UPDATES 1
> +
fix comment
>
> #else /* CONFIG_6xx */
> /* Definitions for 60x, 740/750, etc. */
> #define _PAGE_PRESENT 0x001 /* software: pte contains a translation */
> @@ -365,6 +375,10 @@ extern int icache_44x_need_flush;
> #define _PMD_PRESENT 0
> #define _PMD_PRESENT_MASK (PAGE_MASK)
> #define _PMD_BAD (~PAGE_MASK)
> +
> +/* Hash tbale based platforms need atomic updates of the linux PTE */
tbale?
>
> +#define PTE_ATOMIC_UPDATES 1
> +
> #endif
>
> /*
> @@ -557,9 +571,11 @@ extern void add_hash_page(unsigned conte
> * low PTE word since we expect ALL flag bits to be there
> */
> #ifndef CONFIG_PTE_64BIT
> -static inline unsigned long pte_update(pte_t *p, unsigned long clr,
> +static inline unsigned long pte_update(pte_t *p,
> + unsigned long clr,
> unsigned long set)
> {
> +#ifdef PTE_ATOMIC_UPDATES
> unsigned long old, tmp;
>
> __asm__ __volatile__("\
> @@ -572,16 +588,26 @@ static inline unsigned long pte_update(p
> : "=&r" (old), "=&r" (tmp), "=m" (*p)
> : "r" (p), "r" (clr), "r" (set), "m" (*p)
> : "cc" );
> +#else /* PTE_ATOMIC_UPDATES */
> + unsigned long old = pte_val(*p);
> + *p = __pte((old & ~clr) | set);
> +#endif /* !PTE_ATOMIC_UPDATES */
> +
> #ifdef CONFIG_44x
> if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC))
> icache_44x_need_flush = 1;
> #endif
> return old;
> }
> -#else
> -static inline unsigned long long pte_update(pte_t *p, unsigned long
> clr,
> - unsigned long set)
> +#else /* CONFIG_PTE_64BIT */
> +/* TODO: Change that to only modify the low word and move
> set_pte_at()
> + * out of line
> + */
> +static inline unsigned long long pte_update(pte_t *p,
> + unsigned long clr,
> + unsigned long set)
> {
> +#ifdef PTE_ATOMIC_UPDATES
> unsigned long long old;
> unsigned long tmp;
>
> @@ -596,13 +622,18 @@ static inline unsigned long long pte_upd
> : "=&r" (old), "=&r" (tmp), "=m" (*p)
> : "r" (p), "r" ((unsigned long)(p) + 4), "r" (clr), "r" (set),
> "m" (*p)
> : "cc" );
> +#else /* PTE_ATOMIC_UPDATES */
> + unsigned long long old = pte_val(*p);
> + *p = __pte((old & ~clr) | set);
> +#endif /* !PTE_ATOMIC_UPDATES */
> +
> #ifdef CONFIG_44x
> if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC))
> icache_44x_need_flush = 1;
> #endif
> return old;
> }
> -#endif
> +#endif /* CONFIG_PTE_64BIT */
>
> /*
> * set_pte stores a linux PTE into the linux page table.
> @@ -665,7 +696,7 @@ static inline void __ptep_set_access_fla
> ({ \
> int __changed = !pte_same(*(__ptep), __entry); \
> if (__changed) { \
> - __ptep_set_access_flags(__ptep, __entry, __dirty); \
> + __ptep_set_access_flags(__ptep, __entry, __dirty); \
> flush_tlb_page_nohash(__vma, __address); \
> } \
> __changed; \
More information about the Linuxppc-dev
mailing list