diff options
author | Matt Fleming <matt@console-pimps.org> | 2009-11-19 16:11:05 -0500 |
---|---|---|
committer | Matt Fleming <matt@console-pimps.org> | 2010-01-16 09:29:06 -0500 |
commit | 24ef7fc4dcc57afa0c33166c25bfe7676ffd4296 (patch) | |
tree | d6fc5129f2dbb0534521f5a5111e2bed3cd0f0a7 /arch/sh | |
parent | 8eda55142080f0373b1f0268fe6d6807f193e713 (diff) |
sh: Acquire some more page flags for SH-5.
We need some more page flags to hook up _PAGE_WIRED (and eventually
other things). So use the unused PTE bits above the PPN field as no
implementations use these for anything currently.
Now that we have _PAGE_WIRED let's provide the SH-5 functions for wiring
up TLB entries.
Signed-off-by: Matt Fleming <matt@console-pimps.org>
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/include/asm/page.h | 2 | ||||
-rw-r--r-- | arch/sh/include/asm/pgtable_64.h | 15 | ||||
-rw-r--r-- | arch/sh/include/asm/tlb.h | 41 | ||||
-rw-r--r-- | arch/sh/mm/tlbflush_64.c | 2 |
4 files changed, 57 insertions, 3 deletions
diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index a86c0f1d05d4..61e58105adc3 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h | |||
@@ -88,7 +88,7 @@ typedef struct { unsigned long pgd; } pgd_t; | |||
88 | #define __pte(x) ((pte_t) { (x) } ) | 88 | #define __pte(x) ((pte_t) { (x) } ) |
89 | #else | 89 | #else |
90 | typedef struct { unsigned long long pte_low; } pte_t; | 90 | typedef struct { unsigned long long pte_low; } pte_t; |
91 | typedef struct { unsigned long pgprot; } pgprot_t; | 91 | typedef struct { unsigned long long pgprot; } pgprot_t; |
92 | typedef struct { unsigned long pgd; } pgd_t; | 92 | typedef struct { unsigned long pgd; } pgd_t; |
93 | #define pte_val(x) ((x).pte_low) | 93 | #define pte_val(x) ((x).pte_low) |
94 | #define __pte(x) ((pte_t) { (x) } ) | 94 | #define __pte(x) ((pte_t) { (x) } ) |
diff --git a/arch/sh/include/asm/pgtable_64.h b/arch/sh/include/asm/pgtable_64.h index dd381588c695..0ee46776dad6 100644 --- a/arch/sh/include/asm/pgtable_64.h +++ b/arch/sh/include/asm/pgtable_64.h | |||
@@ -123,8 +123,21 @@ static __inline__ void set_pte(pte_t *pteptr, pte_t pteval) | |||
123 | #define _PAGE_DIRTY 0x400 /* software: page accessed in write */ | 123 | #define _PAGE_DIRTY 0x400 /* software: page accessed in write */ |
124 | #define _PAGE_ACCESSED 0x800 /* software: page referenced */ | 124 | #define _PAGE_ACCESSED 0x800 /* software: page referenced */ |
125 | 125 | ||
126 | /* Wrapper for extended mode pgprot twiddling */ | ||
127 | #define _PAGE_EXT(x) ((unsigned long long)(x) << 32) | ||
128 | |||
129 | /* | ||
130 | * We can use the sign-extended bits in the PTEL to get 32 bits of | ||
131 | * software flags. This works for now because no implementations uses | ||
132 | * anything above the PPN field. | ||
133 | */ | ||
134 | #define _PAGE_WIRED _PAGE_EXT(0x001) /* software: wire the tlb entry */ | ||
135 | |||
136 | #define _PAGE_CLEAR_FLAGS (_PAGE_PRESENT | _PAGE_FILE | _PAGE_SHARED | \ | ||
137 | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_WIRED) | ||
138 | |||
126 | /* Mask which drops software flags */ | 139 | /* Mask which drops software flags */ |
127 | #define _PAGE_FLAGS_HARDWARE_MASK 0xfffffffffffff3dbLL | 140 | #define _PAGE_FLAGS_HARDWARE_MASK (NEFF_MASK & ~(_PAGE_CLEAR_FLAGS)) |
128 | 141 | ||
129 | /* | 142 | /* |
130 | * HugeTLB support | 143 | * HugeTLB support |
diff --git a/arch/sh/include/asm/tlb.h b/arch/sh/include/asm/tlb.h index 3ed2f7a05416..dfc8fcd8ee50 100644 --- a/arch/sh/include/asm/tlb.h +++ b/arch/sh/include/asm/tlb.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #ifdef CONFIG_MMU | 11 | #ifdef CONFIG_MMU |
12 | #include <asm/pgalloc.h> | 12 | #include <asm/pgalloc.h> |
13 | #include <asm/tlbflush.h> | 13 | #include <asm/tlbflush.h> |
14 | #include <asm/mmu_context.h> | ||
14 | 15 | ||
15 | /* | 16 | /* |
16 | * TLB handling. This allows us to remove pages from the page | 17 | * TLB handling. This allows us to remove pages from the page |
@@ -100,6 +101,46 @@ tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) | |||
100 | #ifdef CONFIG_CPU_SH4 | 101 | #ifdef CONFIG_CPU_SH4 |
101 | extern void tlb_wire_entry(struct vm_area_struct *, unsigned long, pte_t); | 102 | extern void tlb_wire_entry(struct vm_area_struct *, unsigned long, pte_t); |
102 | extern void tlb_unwire_entry(void); | 103 | extern void tlb_unwire_entry(void); |
104 | #elif defined(CONFIG_SUPERH64) | ||
105 | static int dtlb_entry; | ||
106 | static unsigned long long dtlb_entries[64]; | ||
107 | |||
108 | static inline void tlb_wire_entry(struct vm_area_struct *vma, | ||
109 | unsigned long addr, pte_t pte) | ||
110 | { | ||
111 | unsigned long long entry; | ||
112 | unsigned long paddr, flags; | ||
113 | |||
114 | BUG_ON(dtlb_entry == 64); | ||
115 | |||
116 | local_irq_save(flags); | ||
117 | |||
118 | entry = sh64_get_wired_dtlb_entry(); | ||
119 | dtlb_entries[dtlb_entry++] = entry; | ||
120 | |||
121 | paddr = pte_val(pte) & _PAGE_FLAGS_HARDWARE_MASK; | ||
122 | paddr &= ~PAGE_MASK; | ||
123 | |||
124 | sh64_setup_tlb_slot(entry, addr, get_asid(), paddr); | ||
125 | |||
126 | local_irq_restore(flags); | ||
127 | } | ||
128 | |||
129 | static inline void tlb_unwire_entry(void) | ||
130 | { | ||
131 | unsigned long long entry; | ||
132 | unsigned long flags; | ||
133 | |||
134 | BUG_ON(!dtlb_entry); | ||
135 | |||
136 | local_irq_save(flags); | ||
137 | entry = dtlb_entries[dtlb_entry--]; | ||
138 | |||
139 | sh64_teardown_tlb_slot(entry); | ||
140 | sh64_put_wired_dtlb_entry(entry); | ||
141 | |||
142 | local_irq_restore(flags); | ||
143 | } | ||
103 | #else | 144 | #else |
104 | static inline void tlb_wire_entry(struct vm_area_struct *vma , | 145 | static inline void tlb_wire_entry(struct vm_area_struct *vma , |
105 | unsigned long addr, pte_t pte) | 146 | unsigned long addr, pte_t pte) |
diff --git a/arch/sh/mm/tlbflush_64.c b/arch/sh/mm/tlbflush_64.c index de0b0e881823..706da1d3a67a 100644 --- a/arch/sh/mm/tlbflush_64.c +++ b/arch/sh/mm/tlbflush_64.c | |||
@@ -36,7 +36,7 @@ extern void die(const char *,struct pt_regs *,long); | |||
36 | 36 | ||
37 | static inline void print_prots(pgprot_t prot) | 37 | static inline void print_prots(pgprot_t prot) |
38 | { | 38 | { |
39 | printk("prot is 0x%08lx\n",pgprot_val(prot)); | 39 | printk("prot is 0x%016llx\n",pgprot_val(prot)); |
40 | 40 | ||
41 | printk("%s %s %s %s %s\n",PPROT(_PAGE_SHARED),PPROT(_PAGE_READ), | 41 | printk("%s %s %s %s %s\n",PPROT(_PAGE_SHARED),PPROT(_PAGE_READ), |
42 | PPROT(_PAGE_EXECUTE),PPROT(_PAGE_WRITE),PPROT(_PAGE_USER)); | 42 | PPROT(_PAGE_EXECUTE),PPROT(_PAGE_WRITE),PPROT(_PAGE_USER)); |