aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-powerpc
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-07-08 01:54:40 -0400
committerJosh Boyer <jwboyer@linux.vnet.ibm.com>2008-07-09 13:36:17 -0400
commit1bc54c03117b90716e0dedd7abb2a20405de65df (patch)
tree8e82fd610abaff36f1e20b5aaaf7bdeaee883aac /include/asm-powerpc
parentbeae4c03c0fe69cf7d57518aa0572ad21730b8be (diff)
powerpc: rework 4xx PTE access and TLB miss
This is some preliminary work to improve TLB management on SW loaded TLB powerpc platforms. This introduce support for non-atomic PTE operations in pgtable-ppc32.h and removes write back to the PTE from the TLB miss handlers. In addition, the DSI interrupt code no longer tries to fixup write permission, this is left to generic code, and _PAGE_HWWRITE is gone. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Diffstat (limited to 'include/asm-powerpc')
-rw-r--r--include/asm-powerpc/pgtable-ppc32.h61
1 files changed, 46 insertions, 15 deletions
diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h
index e1d2bb57f1d5..11eede4a2906 100644
--- a/include/asm-powerpc/pgtable-ppc32.h
+++ b/include/asm-powerpc/pgtable-ppc32.h
@@ -182,6 +182,9 @@ extern int icache_44x_need_flush;
182#define _PMD_SIZE_16M 0x0e0 182#define _PMD_SIZE_16M 0x0e0
183#define PMD_PAGE_SIZE(pmdval) (1024 << (((pmdval) & _PMD_SIZE) >> 4)) 183#define PMD_PAGE_SIZE(pmdval) (1024 << (((pmdval) & _PMD_SIZE) >> 4))
184 184
185/* Until my rework is finished, 40x still needs atomic PTE updates */
186#define PTE_ATOMIC_UPDATES 1
187
185#elif defined(CONFIG_44x) 188#elif defined(CONFIG_44x)
186/* 189/*
187 * Definitions for PPC440 190 * Definitions for PPC440
@@ -253,17 +256,17 @@ extern int icache_44x_need_flush;
253 */ 256 */
254 257
255#define _PAGE_PRESENT 0x00000001 /* S: PTE valid */ 258#define _PAGE_PRESENT 0x00000001 /* S: PTE valid */
256#define _PAGE_RW 0x00000002 /* S: Write permission */ 259#define _PAGE_RW 0x00000002 /* S: Write permission */
257#define _PAGE_FILE 0x00000004 /* S: nonlinear file mapping */ 260#define _PAGE_FILE 0x00000004 /* S: nonlinear file mapping */
261#define _PAGE_HWEXEC 0x00000004 /* H: Execute permission */
258#define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */ 262#define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */
259#define _PAGE_HWWRITE 0x00000010 /* H: Dirty & RW */ 263#define _PAGE_DIRTY 0x00000010 /* S: Page dirty */
260#define _PAGE_HWEXEC 0x00000020 /* H: Execute permission */ 264#define _PAGE_USER 0x00000040 /* S: User page */
261#define _PAGE_USER 0x00000040 /* S: User page */ 265#define _PAGE_ENDIAN 0x00000080 /* H: E bit */
262#define _PAGE_ENDIAN 0x00000080 /* H: E bit */ 266#define _PAGE_GUARDED 0x00000100 /* H: G bit */
263#define _PAGE_GUARDED 0x00000100 /* H: G bit */ 267#define _PAGE_COHERENT 0x00000200 /* H: M bit */
264#define _PAGE_DIRTY 0x00000200 /* S: Page dirty */ 268#define _PAGE_NO_CACHE 0x00000400 /* H: I bit */
265#define _PAGE_NO_CACHE 0x00000400 /* H: I bit */ 269#define _PAGE_WRITETHRU 0x00000800 /* H: W bit */
266#define _PAGE_WRITETHRU 0x00000800 /* H: W bit */
267 270
268/* TODO: Add large page lowmem mapping support */ 271/* TODO: Add large page lowmem mapping support */
269#define _PMD_PRESENT 0 272#define _PMD_PRESENT 0
@@ -273,6 +276,7 @@ extern int icache_44x_need_flush;
273/* ERPN in a PTE never gets cleared, ignore it */ 276/* ERPN in a PTE never gets cleared, ignore it */
274#define _PTE_NONE_MASK 0xffffffff00000000ULL 277#define _PTE_NONE_MASK 0xffffffff00000000ULL
275 278
279
276#elif defined(CONFIG_FSL_BOOKE) 280#elif defined(CONFIG_FSL_BOOKE)
277/* 281/*
278 MMU Assist Register 3: 282 MMU Assist Register 3:
@@ -315,6 +319,9 @@ extern int icache_44x_need_flush;
315#define _PMD_PRESENT_MASK (PAGE_MASK) 319#define _PMD_PRESENT_MASK (PAGE_MASK)
316#define _PMD_BAD (~PAGE_MASK) 320#define _PMD_BAD (~PAGE_MASK)
317 321
322/* Until my rework is finished, FSL BookE still needs atomic PTE updates */
323#define PTE_ATOMIC_UPDATES 1
324
318#elif defined(CONFIG_8xx) 325#elif defined(CONFIG_8xx)
319/* Definitions for 8xx embedded chips. */ 326/* Definitions for 8xx embedded chips. */
320#define _PAGE_PRESENT 0x0001 /* Page is valid */ 327#define _PAGE_PRESENT 0x0001 /* Page is valid */
@@ -345,6 +352,9 @@ extern int icache_44x_need_flush;
345 352
346#define _PTE_NONE_MASK _PAGE_ACCESSED 353#define _PTE_NONE_MASK _PAGE_ACCESSED
347 354
355/* Until my rework is finished, 8xx still needs atomic PTE updates */
356#define PTE_ATOMIC_UPDATES 1
357
348#else /* CONFIG_6xx */ 358#else /* CONFIG_6xx */
349/* Definitions for 60x, 740/750, etc. */ 359/* Definitions for 60x, 740/750, etc. */
350#define _PAGE_PRESENT 0x001 /* software: pte contains a translation */ 360#define _PAGE_PRESENT 0x001 /* software: pte contains a translation */
@@ -365,6 +375,10 @@ extern int icache_44x_need_flush;
365#define _PMD_PRESENT 0 375#define _PMD_PRESENT 0
366#define _PMD_PRESENT_MASK (PAGE_MASK) 376#define _PMD_PRESENT_MASK (PAGE_MASK)
367#define _PMD_BAD (~PAGE_MASK) 377#define _PMD_BAD (~PAGE_MASK)
378
379/* Hash table based platforms need atomic updates of the linux PTE */
380#define PTE_ATOMIC_UPDATES 1
381
368#endif 382#endif
369 383
370/* 384/*
@@ -557,9 +571,11 @@ extern void add_hash_page(unsigned context, unsigned long va,
557 * low PTE word since we expect ALL flag bits to be there 571 * low PTE word since we expect ALL flag bits to be there
558 */ 572 */
559#ifndef CONFIG_PTE_64BIT 573#ifndef CONFIG_PTE_64BIT
560static inline unsigned long pte_update(pte_t *p, unsigned long clr, 574static inline unsigned long pte_update(pte_t *p,
575 unsigned long clr,
561 unsigned long set) 576 unsigned long set)
562{ 577{
578#ifdef PTE_ATOMIC_UPDATES
563 unsigned long old, tmp; 579 unsigned long old, tmp;
564 580
565 __asm__ __volatile__("\ 581 __asm__ __volatile__("\
@@ -572,16 +588,26 @@ static inline unsigned long pte_update(pte_t *p, unsigned long clr,
572 : "=&r" (old), "=&r" (tmp), "=m" (*p) 588 : "=&r" (old), "=&r" (tmp), "=m" (*p)
573 : "r" (p), "r" (clr), "r" (set), "m" (*p) 589 : "r" (p), "r" (clr), "r" (set), "m" (*p)
574 : "cc" ); 590 : "cc" );
591#else /* PTE_ATOMIC_UPDATES */
592 unsigned long old = pte_val(*p);
593 *p = __pte((old & ~clr) | set);
594#endif /* !PTE_ATOMIC_UPDATES */
595
575#ifdef CONFIG_44x 596#ifdef CONFIG_44x
576 if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC)) 597 if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC))
577 icache_44x_need_flush = 1; 598 icache_44x_need_flush = 1;
578#endif 599#endif
579 return old; 600 return old;
580} 601}
581#else 602#else /* CONFIG_PTE_64BIT */
582static inline unsigned long long pte_update(pte_t *p, unsigned long clr, 603/* TODO: Change that to only modify the low word and move set_pte_at()
583 unsigned long set) 604 * out of line
605 */
606static inline unsigned long long pte_update(pte_t *p,
607 unsigned long clr,
608 unsigned long set)
584{ 609{
610#ifdef PTE_ATOMIC_UPDATES
585 unsigned long long old; 611 unsigned long long old;
586 unsigned long tmp; 612 unsigned long tmp;
587 613
@@ -596,13 +622,18 @@ static inline unsigned long long pte_update(pte_t *p, unsigned long clr,
596 : "=&r" (old), "=&r" (tmp), "=m" (*p) 622 : "=&r" (old), "=&r" (tmp), "=m" (*p)
597 : "r" (p), "r" ((unsigned long)(p) + 4), "r" (clr), "r" (set), "m" (*p) 623 : "r" (p), "r" ((unsigned long)(p) + 4), "r" (clr), "r" (set), "m" (*p)
598 : "cc" ); 624 : "cc" );
625#else /* PTE_ATOMIC_UPDATES */
626 unsigned long long old = pte_val(*p);
627 *p = __pte((old & ~clr) | set);
628#endif /* !PTE_ATOMIC_UPDATES */
629
599#ifdef CONFIG_44x 630#ifdef CONFIG_44x
600 if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC)) 631 if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC))
601 icache_44x_need_flush = 1; 632 icache_44x_need_flush = 1;
602#endif 633#endif
603 return old; 634 return old;
604} 635}
605#endif 636#endif /* CONFIG_PTE_64BIT */
606 637
607/* 638/*
608 * set_pte stores a linux PTE into the linux page table. 639 * set_pte stores a linux PTE into the linux page table.
@@ -671,7 +702,7 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
671({ \ 702({ \
672 int __changed = !pte_same(*(__ptep), __entry); \ 703 int __changed = !pte_same(*(__ptep), __entry); \
673 if (__changed) { \ 704 if (__changed) { \
674 __ptep_set_access_flags(__ptep, __entry, __dirty); \ 705 __ptep_set_access_flags(__ptep, __entry, __dirty); \
675 flush_tlb_page_nohash(__vma, __address); \ 706 flush_tlb_page_nohash(__vma, __address); \
676 } \ 707 } \
677 __changed; \ 708 __changed; \