diff options
Diffstat (limited to 'arch/tile/mm')
-rw-r--r-- | arch/tile/mm/fault.c | 53 | ||||
-rw-r--r-- | arch/tile/mm/highmem.c | 88 | ||||
-rw-r--r-- | arch/tile/mm/homecache.c | 49 | ||||
-rw-r--r-- | arch/tile/mm/hugetlbpage.c | 3 | ||||
-rw-r--r-- | arch/tile/mm/init.c | 44 | ||||
-rw-r--r-- | arch/tile/mm/migrate_32.S | 1 | ||||
-rw-r--r-- | arch/tile/mm/migrate_64.S | 187 | ||||
-rw-r--r-- | arch/tile/mm/pgtable.c | 187 |
8 files changed, 440 insertions, 172 deletions
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c index 704f3e8a4385..25b7b90fd620 100644 --- a/arch/tile/mm/fault.c +++ b/arch/tile/mm/fault.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/mman.h> | 24 | #include <linux/mman.h> |
25 | #include <linux/mm.h> | 25 | #include <linux/mm.h> |
26 | #include <linux/smp.h> | 26 | #include <linux/smp.h> |
27 | #include <linux/smp_lock.h> | ||
28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
29 | #include <linux/init.h> | 28 | #include <linux/init.h> |
30 | #include <linux/tty.h> | 29 | #include <linux/tty.h> |
@@ -44,8 +43,11 @@ | |||
44 | 43 | ||
45 | #include <arch/interrupts.h> | 44 | #include <arch/interrupts.h> |
46 | 45 | ||
47 | static noinline void force_sig_info_fault(int si_signo, int si_code, | 46 | static noinline void force_sig_info_fault(const char *type, int si_signo, |
48 | unsigned long address, int fault_num, struct task_struct *tsk) | 47 | int si_code, unsigned long address, |
48 | int fault_num, | ||
49 | struct task_struct *tsk, | ||
50 | struct pt_regs *regs) | ||
49 | { | 51 | { |
50 | siginfo_t info; | 52 | siginfo_t info; |
51 | 53 | ||
@@ -60,23 +62,25 @@ static noinline void force_sig_info_fault(int si_signo, int si_code, | |||
60 | info.si_code = si_code; | 62 | info.si_code = si_code; |
61 | info.si_addr = (void __user *)address; | 63 | info.si_addr = (void __user *)address; |
62 | info.si_trapno = fault_num; | 64 | info.si_trapno = fault_num; |
65 | trace_unhandled_signal(type, regs, address, si_signo); | ||
63 | force_sig_info(si_signo, &info, tsk); | 66 | force_sig_info(si_signo, &info, tsk); |
64 | } | 67 | } |
65 | 68 | ||
66 | #ifndef __tilegx__ | 69 | #ifndef __tilegx__ |
67 | /* | 70 | /* |
68 | * Synthesize the fault a PL0 process would get by doing a word-load of | 71 | * Synthesize the fault a PL0 process would get by doing a word-load of |
69 | * an unaligned address or a high kernel address. Called indirectly | 72 | * an unaligned address or a high kernel address. |
70 | * from sys_cmpxchg() in kernel/intvec.S. | ||
71 | */ | 73 | */ |
72 | int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *regs) | 74 | SYSCALL_DEFINE2(cmpxchg_badaddr, unsigned long, address, |
75 | struct pt_regs *, regs) | ||
73 | { | 76 | { |
74 | if (address >= PAGE_OFFSET) | 77 | if (address >= PAGE_OFFSET) |
75 | force_sig_info_fault(SIGSEGV, SEGV_MAPERR, address, | 78 | force_sig_info_fault("atomic segfault", SIGSEGV, SEGV_MAPERR, |
76 | INT_DTLB_MISS, current); | 79 | address, INT_DTLB_MISS, current, regs); |
77 | else | 80 | else |
78 | force_sig_info_fault(SIGBUS, BUS_ADRALN, address, | 81 | force_sig_info_fault("atomic alignment fault", SIGBUS, |
79 | INT_UNALIGN_DATA, current); | 82 | BUS_ADRALN, address, |
83 | INT_UNALIGN_DATA, current, regs); | ||
80 | 84 | ||
81 | /* | 85 | /* |
82 | * Adjust pc to point at the actual instruction, which is unusual | 86 | * Adjust pc to point at the actual instruction, which is unusual |
@@ -291,7 +295,7 @@ static int handle_page_fault(struct pt_regs *regs, | |||
291 | /* | 295 | /* |
292 | * Early on, we need to check for migrating PTE entries; | 296 | * Early on, we need to check for migrating PTE entries; |
293 | * see homecache.c. If we find a migrating PTE, we wait until | 297 | * see homecache.c. If we find a migrating PTE, we wait until |
294 | * the backing page claims to be done migrating, then we procede. | 298 | * the backing page claims to be done migrating, then we proceed. |
295 | * For kernel PTEs, we rewrite the PTE and return and retry. | 299 | * For kernel PTEs, we rewrite the PTE and return and retry. |
296 | * Otherwise, we treat the fault like a normal "no PTE" fault, | 300 | * Otherwise, we treat the fault like a normal "no PTE" fault, |
297 | * rather than trying to patch up the existing PTE. | 301 | * rather than trying to patch up the existing PTE. |
@@ -472,8 +476,8 @@ bad_area_nosemaphore: | |||
472 | */ | 476 | */ |
473 | local_irq_enable(); | 477 | local_irq_enable(); |
474 | 478 | ||
475 | force_sig_info_fault(SIGSEGV, si_code, address, | 479 | force_sig_info_fault("segfault", SIGSEGV, si_code, address, |
476 | fault_num, tsk); | 480 | fault_num, tsk, regs); |
477 | return 0; | 481 | return 0; |
478 | } | 482 | } |
479 | 483 | ||
@@ -548,7 +552,8 @@ do_sigbus: | |||
548 | if (is_kernel_mode) | 552 | if (is_kernel_mode) |
549 | goto no_context; | 553 | goto no_context; |
550 | 554 | ||
551 | force_sig_info_fault(SIGBUS, BUS_ADRERR, address, fault_num, tsk); | 555 | force_sig_info_fault("bus error", SIGBUS, BUS_ADRERR, address, |
556 | fault_num, tsk, regs); | ||
552 | return 0; | 557 | return 0; |
553 | } | 558 | } |
554 | 559 | ||
@@ -563,10 +568,10 @@ do_sigbus: | |||
563 | /* | 568 | /* |
564 | * When we take an ITLB or DTLB fault or access violation in the | 569 | * When we take an ITLB or DTLB fault or access violation in the |
565 | * supervisor while the critical section bit is set, the hypervisor is | 570 | * supervisor while the critical section bit is set, the hypervisor is |
566 | * reluctant to write new values into the EX_CONTEXT_1_x registers, | 571 | * reluctant to write new values into the EX_CONTEXT_K_x registers, |
567 | * since that might indicate we have not yet squirreled the SPR | 572 | * since that might indicate we have not yet squirreled the SPR |
568 | * contents away and can thus safely take a recursive interrupt. | 573 | * contents away and can thus safely take a recursive interrupt. |
569 | * Accordingly, the hypervisor passes us the PC via SYSTEM_SAVE_1_2. | 574 | * Accordingly, the hypervisor passes us the PC via SYSTEM_SAVE_K_2. |
570 | * | 575 | * |
571 | * Note that this routine is called before homecache_tlb_defer_enter(), | 576 | * Note that this routine is called before homecache_tlb_defer_enter(), |
572 | * which means that we can properly unlock any atomics that might | 577 | * which means that we can properly unlock any atomics that might |
@@ -610,7 +615,7 @@ struct intvec_state do_page_fault_ics(struct pt_regs *regs, int fault_num, | |||
610 | * fault. We didn't set up a kernel stack on initial entry to | 615 | * fault. We didn't set up a kernel stack on initial entry to |
611 | * sys_cmpxchg, but instead had one set up by the fault, which | 616 | * sys_cmpxchg, but instead had one set up by the fault, which |
612 | * (because sys_cmpxchg never releases ICS) came to us via the | 617 | * (because sys_cmpxchg never releases ICS) came to us via the |
613 | * SYSTEM_SAVE_1_2 mechanism, and thus EX_CONTEXT_1_[01] are | 618 | * SYSTEM_SAVE_K_2 mechanism, and thus EX_CONTEXT_K_[01] are |
614 | * still referencing the original user code. We release the | 619 | * still referencing the original user code. We release the |
615 | * atomic lock and rewrite pt_regs so that it appears that we | 620 | * atomic lock and rewrite pt_regs so that it appears that we |
616 | * came from user-space directly, and after we finish the | 621 | * came from user-space directly, and after we finish the |
@@ -656,14 +661,6 @@ struct intvec_state do_page_fault_ics(struct pt_regs *regs, int fault_num, | |||
656 | } | 661 | } |
657 | 662 | ||
658 | /* | 663 | /* |
659 | * NOTE: the one other type of access that might bring us here | ||
660 | * are the memory ops in __tns_atomic_acquire/__tns_atomic_release, | ||
661 | * but we don't have to check specially for them since we can | ||
662 | * always safely return to the address of the fault and retry, | ||
663 | * since no separate atomic locks are involved. | ||
664 | */ | ||
665 | |||
666 | /* | ||
667 | * Now that we have released the atomic lock (if necessary), | 664 | * Now that we have released the atomic lock (if necessary), |
668 | * it's safe to spin if the PTE that caused the fault was migrating. | 665 | * it's safe to spin if the PTE that caused the fault was migrating. |
669 | */ | 666 | */ |
@@ -741,6 +738,7 @@ void do_page_fault(struct pt_regs *regs, int fault_num, | |||
741 | panic("Bad fault number %d in do_page_fault", fault_num); | 738 | panic("Bad fault number %d in do_page_fault", fault_num); |
742 | } | 739 | } |
743 | 740 | ||
741 | #if CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() | ||
744 | if (EX1_PL(regs->ex1) != USER_PL) { | 742 | if (EX1_PL(regs->ex1) != USER_PL) { |
745 | struct async_tlb *async; | 743 | struct async_tlb *async; |
746 | switch (fault_num) { | 744 | switch (fault_num) { |
@@ -784,6 +782,7 @@ void do_page_fault(struct pt_regs *regs, int fault_num, | |||
784 | return; | 782 | return; |
785 | } | 783 | } |
786 | } | 784 | } |
785 | #endif | ||
787 | 786 | ||
788 | handle_page_fault(regs, fault_num, is_page_fault, address, write); | 787 | handle_page_fault(regs, fault_num, is_page_fault, address, write); |
789 | } | 788 | } |
@@ -810,8 +809,6 @@ static void handle_async_page_fault(struct pt_regs *regs, | |||
810 | async->address, async->is_write); | 809 | async->address, async->is_write); |
811 | } | 810 | } |
812 | } | 811 | } |
813 | #endif /* CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() */ | ||
814 | |||
815 | 812 | ||
816 | /* | 813 | /* |
817 | * This routine effectively re-issues asynchronous page faults | 814 | * This routine effectively re-issues asynchronous page faults |
@@ -833,6 +830,8 @@ void do_async_page_fault(struct pt_regs *regs) | |||
833 | handle_async_page_fault(regs, ¤t->thread.sn_async_tlb); | 830 | handle_async_page_fault(regs, ¤t->thread.sn_async_tlb); |
834 | #endif | 831 | #endif |
835 | } | 832 | } |
833 | #endif /* CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() */ | ||
834 | |||
836 | 835 | ||
837 | void vmalloc_sync_all(void) | 836 | void vmalloc_sync_all(void) |
838 | { | 837 | { |
diff --git a/arch/tile/mm/highmem.c b/arch/tile/mm/highmem.c index 12ab137e7d4f..31dbbd9afe47 100644 --- a/arch/tile/mm/highmem.c +++ b/arch/tile/mm/highmem.c | |||
@@ -56,50 +56,6 @@ void kunmap(struct page *page) | |||
56 | } | 56 | } |
57 | EXPORT_SYMBOL(kunmap); | 57 | EXPORT_SYMBOL(kunmap); |
58 | 58 | ||
59 | static void debug_kmap_atomic_prot(enum km_type type) | ||
60 | { | ||
61 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
62 | static unsigned warn_count = 10; | ||
63 | |||
64 | if (unlikely(warn_count == 0)) | ||
65 | return; | ||
66 | |||
67 | if (unlikely(in_interrupt())) { | ||
68 | if (in_irq()) { | ||
69 | if (type != KM_IRQ0 && type != KM_IRQ1 && | ||
70 | type != KM_BIO_SRC_IRQ && | ||
71 | /* type != KM_BIO_DST_IRQ && */ | ||
72 | type != KM_BOUNCE_READ) { | ||
73 | WARN_ON(1); | ||
74 | warn_count--; | ||
75 | } | ||
76 | } else if (!irqs_disabled()) { /* softirq */ | ||
77 | if (type != KM_IRQ0 && type != KM_IRQ1 && | ||
78 | type != KM_SOFTIRQ0 && type != KM_SOFTIRQ1 && | ||
79 | type != KM_SKB_SUNRPC_DATA && | ||
80 | type != KM_SKB_DATA_SOFTIRQ && | ||
81 | type != KM_BOUNCE_READ) { | ||
82 | WARN_ON(1); | ||
83 | warn_count--; | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | |||
88 | if (type == KM_IRQ0 || type == KM_IRQ1 || type == KM_BOUNCE_READ || | ||
89 | type == KM_BIO_SRC_IRQ /* || type == KM_BIO_DST_IRQ */) { | ||
90 | if (!irqs_disabled()) { | ||
91 | WARN_ON(1); | ||
92 | warn_count--; | ||
93 | } | ||
94 | } else if (type == KM_SOFTIRQ0 || type == KM_SOFTIRQ1) { | ||
95 | if (irq_count() == 0 && !irqs_disabled()) { | ||
96 | WARN_ON(1); | ||
97 | warn_count--; | ||
98 | } | ||
99 | } | ||
100 | #endif | ||
101 | } | ||
102 | |||
103 | /* | 59 | /* |
104 | * Describe a single atomic mapping of a page on a given cpu at a | 60 | * Describe a single atomic mapping of a page on a given cpu at a |
105 | * given address, and allow it to be linked into a list. | 61 | * given address, and allow it to be linked into a list. |
@@ -240,10 +196,10 @@ void kmap_atomic_fix_kpte(struct page *page, int finished) | |||
240 | * When holding an atomic kmap is is not legal to sleep, so atomic | 196 | * When holding an atomic kmap is is not legal to sleep, so atomic |
241 | * kmaps are appropriate for short, tight code paths only. | 197 | * kmaps are appropriate for short, tight code paths only. |
242 | */ | 198 | */ |
243 | void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | 199 | void *kmap_atomic_prot(struct page *page, pgprot_t prot) |
244 | { | 200 | { |
245 | enum fixed_addresses idx; | ||
246 | unsigned long vaddr; | 201 | unsigned long vaddr; |
202 | int idx, type; | ||
247 | pte_t *pte; | 203 | pte_t *pte; |
248 | 204 | ||
249 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ | 205 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ |
@@ -255,8 +211,7 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | |||
255 | if (!PageHighMem(page)) | 211 | if (!PageHighMem(page)) |
256 | return page_address(page); | 212 | return page_address(page); |
257 | 213 | ||
258 | debug_kmap_atomic_prot(type); | 214 | type = kmap_atomic_idx_push(); |
259 | |||
260 | idx = type + KM_TYPE_NR*smp_processor_id(); | 215 | idx = type + KM_TYPE_NR*smp_processor_id(); |
261 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 216 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
262 | pte = kmap_get_pte(vaddr); | 217 | pte = kmap_get_pte(vaddr); |
@@ -269,28 +224,35 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | |||
269 | } | 224 | } |
270 | EXPORT_SYMBOL(kmap_atomic_prot); | 225 | EXPORT_SYMBOL(kmap_atomic_prot); |
271 | 226 | ||
272 | void *kmap_atomic(struct page *page, enum km_type type) | 227 | void *__kmap_atomic(struct page *page) |
273 | { | 228 | { |
274 | /* PAGE_NONE is a magic value that tells us to check immutability. */ | 229 | /* PAGE_NONE is a magic value that tells us to check immutability. */ |
275 | return kmap_atomic_prot(page, type, PAGE_NONE); | 230 | return kmap_atomic_prot(page, PAGE_NONE); |
276 | } | 231 | } |
277 | EXPORT_SYMBOL(kmap_atomic); | 232 | EXPORT_SYMBOL(__kmap_atomic); |
278 | 233 | ||
279 | void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type) | 234 | void __kunmap_atomic(void *kvaddr) |
280 | { | 235 | { |
281 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; | 236 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; |
282 | enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); | ||
283 | 237 | ||
284 | /* | 238 | if (vaddr >= __fix_to_virt(FIX_KMAP_END) && |
285 | * Force other mappings to Oops if they try to access this pte without | 239 | vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) { |
286 | * first remapping it. Keeping stale mappings around is a bad idea. | ||
287 | */ | ||
288 | if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx)) { | ||
289 | pte_t *pte = kmap_get_pte(vaddr); | 240 | pte_t *pte = kmap_get_pte(vaddr); |
290 | pte_t pteval = *pte; | 241 | pte_t pteval = *pte; |
242 | int idx, type; | ||
243 | |||
244 | type = kmap_atomic_idx(); | ||
245 | idx = type + KM_TYPE_NR*smp_processor_id(); | ||
246 | |||
247 | /* | ||
248 | * Force other mappings to Oops if they try to access this pte | ||
249 | * without first remapping it. Keeping stale mappings around | ||
250 | * is a bad idea. | ||
251 | */ | ||
291 | BUG_ON(!pte_present(pteval) && !pte_migrating(pteval)); | 252 | BUG_ON(!pte_present(pteval) && !pte_migrating(pteval)); |
292 | kmap_atomic_unregister(pte_page(pteval), vaddr); | 253 | kmap_atomic_unregister(pte_page(pteval), vaddr); |
293 | kpte_clear_flush(pte, vaddr); | 254 | kpte_clear_flush(pte, vaddr); |
255 | kmap_atomic_idx_pop(); | ||
294 | } else { | 256 | } else { |
295 | /* Must be a lowmem page */ | 257 | /* Must be a lowmem page */ |
296 | BUG_ON(vaddr < PAGE_OFFSET); | 258 | BUG_ON(vaddr < PAGE_OFFSET); |
@@ -300,19 +262,19 @@ void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type) | |||
300 | arch_flush_lazy_mmu_mode(); | 262 | arch_flush_lazy_mmu_mode(); |
301 | pagefault_enable(); | 263 | pagefault_enable(); |
302 | } | 264 | } |
303 | EXPORT_SYMBOL(kunmap_atomic_notypecheck); | 265 | EXPORT_SYMBOL(__kunmap_atomic); |
304 | 266 | ||
305 | /* | 267 | /* |
306 | * This API is supposed to allow us to map memory without a "struct page". | 268 | * This API is supposed to allow us to map memory without a "struct page". |
307 | * Currently we don't support this, though this may change in the future. | 269 | * Currently we don't support this, though this may change in the future. |
308 | */ | 270 | */ |
309 | void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) | 271 | void *kmap_atomic_pfn(unsigned long pfn) |
310 | { | 272 | { |
311 | return kmap_atomic(pfn_to_page(pfn), type); | 273 | return kmap_atomic(pfn_to_page(pfn)); |
312 | } | 274 | } |
313 | void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) | 275 | void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot) |
314 | { | 276 | { |
315 | return kmap_atomic_prot(pfn_to_page(pfn), type, prot); | 277 | return kmap_atomic_prot(pfn_to_page(pfn), prot); |
316 | } | 278 | } |
317 | 279 | ||
318 | struct page *kmap_atomic_to_page(void *ptr) | 280 | struct page *kmap_atomic_to_page(void *ptr) |
diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c index fb3b4a55cec4..cbe6f4f9eca3 100644 --- a/arch/tile/mm/homecache.c +++ b/arch/tile/mm/homecache.c | |||
@@ -37,6 +37,8 @@ | |||
37 | #include <asm/pgalloc.h> | 37 | #include <asm/pgalloc.h> |
38 | #include <asm/homecache.h> | 38 | #include <asm/homecache.h> |
39 | 39 | ||
40 | #include <arch/sim.h> | ||
41 | |||
40 | #include "migrate.h" | 42 | #include "migrate.h" |
41 | 43 | ||
42 | 44 | ||
@@ -177,23 +179,46 @@ void flush_remote(unsigned long cache_pfn, unsigned long cache_control, | |||
177 | panic("Unsafe to continue."); | 179 | panic("Unsafe to continue."); |
178 | } | 180 | } |
179 | 181 | ||
182 | void flush_remote_page(struct page *page, int order) | ||
183 | { | ||
184 | int i, pages = (1 << order); | ||
185 | for (i = 0; i < pages; ++i, ++page) { | ||
186 | void *p = kmap_atomic(page); | ||
187 | int hfh = 0; | ||
188 | int home = page_home(page); | ||
189 | #if CHIP_HAS_CBOX_HOME_MAP() | ||
190 | if (home == PAGE_HOME_HASH) | ||
191 | hfh = 1; | ||
192 | else | ||
193 | #endif | ||
194 | BUG_ON(home < 0 || home >= NR_CPUS); | ||
195 | finv_buffer_remote(p, PAGE_SIZE, hfh); | ||
196 | kunmap_atomic(p); | ||
197 | } | ||
198 | } | ||
199 | |||
180 | void homecache_evict(const struct cpumask *mask) | 200 | void homecache_evict(const struct cpumask *mask) |
181 | { | 201 | { |
182 | flush_remote(0, HV_FLUSH_EVICT_L2, mask, 0, 0, 0, NULL, NULL, 0); | 202 | flush_remote(0, HV_FLUSH_EVICT_L2, mask, 0, 0, 0, NULL, NULL, 0); |
183 | } | 203 | } |
184 | 204 | ||
185 | /* Return a mask of the cpus whose caches currently own these pages. */ | 205 | /* |
186 | static void homecache_mask(struct page *page, int pages, | 206 | * Return a mask of the cpus whose caches currently own these pages. |
187 | struct cpumask *home_mask) | 207 | * The return value is whether the pages are all coherently cached |
208 | * (i.e. none are immutable, incoherent, or uncached). | ||
209 | */ | ||
210 | static int homecache_mask(struct page *page, int pages, | ||
211 | struct cpumask *home_mask) | ||
188 | { | 212 | { |
189 | int i; | 213 | int i; |
214 | int cached_coherently = 1; | ||
190 | cpumask_clear(home_mask); | 215 | cpumask_clear(home_mask); |
191 | for (i = 0; i < pages; ++i) { | 216 | for (i = 0; i < pages; ++i) { |
192 | int home = page_home(&page[i]); | 217 | int home = page_home(&page[i]); |
193 | if (home == PAGE_HOME_IMMUTABLE || | 218 | if (home == PAGE_HOME_IMMUTABLE || |
194 | home == PAGE_HOME_INCOHERENT) { | 219 | home == PAGE_HOME_INCOHERENT) { |
195 | cpumask_copy(home_mask, cpu_possible_mask); | 220 | cpumask_copy(home_mask, cpu_possible_mask); |
196 | return; | 221 | return 0; |
197 | } | 222 | } |
198 | #if CHIP_HAS_CBOX_HOME_MAP() | 223 | #if CHIP_HAS_CBOX_HOME_MAP() |
199 | if (home == PAGE_HOME_HASH) { | 224 | if (home == PAGE_HOME_HASH) { |
@@ -201,11 +226,14 @@ static void homecache_mask(struct page *page, int pages, | |||
201 | continue; | 226 | continue; |
202 | } | 227 | } |
203 | #endif | 228 | #endif |
204 | if (home == PAGE_HOME_UNCACHED) | 229 | if (home == PAGE_HOME_UNCACHED) { |
230 | cached_coherently = 0; | ||
205 | continue; | 231 | continue; |
232 | } | ||
206 | BUG_ON(home < 0 || home >= NR_CPUS); | 233 | BUG_ON(home < 0 || home >= NR_CPUS); |
207 | cpumask_set_cpu(home, home_mask); | 234 | cpumask_set_cpu(home, home_mask); |
208 | } | 235 | } |
236 | return cached_coherently; | ||
209 | } | 237 | } |
210 | 238 | ||
211 | /* | 239 | /* |
@@ -217,13 +245,6 @@ static unsigned long cache_flush_length(unsigned long length) | |||
217 | return (length >= CHIP_L2_CACHE_SIZE()) ? HV_FLUSH_EVICT_L2 : length; | 245 | return (length >= CHIP_L2_CACHE_SIZE()) ? HV_FLUSH_EVICT_L2 : length; |
218 | } | 246 | } |
219 | 247 | ||
220 | /* On the simulator, confirm lines have been evicted everywhere. */ | ||
221 | static void validate_lines_evicted(unsigned long pfn, size_t length) | ||
222 | { | ||
223 | sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED, | ||
224 | (HV_PhysAddr)pfn << PAGE_SHIFT, length); | ||
225 | } | ||
226 | |||
227 | /* Flush a page out of whatever cache(s) it is in. */ | 248 | /* Flush a page out of whatever cache(s) it is in. */ |
228 | void homecache_flush_cache(struct page *page, int order) | 249 | void homecache_flush_cache(struct page *page, int order) |
229 | { | 250 | { |
@@ -234,7 +255,7 @@ void homecache_flush_cache(struct page *page, int order) | |||
234 | 255 | ||
235 | homecache_mask(page, pages, &home_mask); | 256 | homecache_mask(page, pages, &home_mask); |
236 | flush_remote(pfn, length, &home_mask, 0, 0, 0, NULL, NULL, 0); | 257 | flush_remote(pfn, length, &home_mask, 0, 0, 0, NULL, NULL, 0); |
237 | validate_lines_evicted(pfn, pages * PAGE_SIZE); | 258 | sim_validate_lines_evicted(PFN_PHYS(pfn), pages * PAGE_SIZE); |
238 | } | 259 | } |
239 | 260 | ||
240 | 261 | ||
@@ -391,7 +412,7 @@ void homecache_change_page_home(struct page *page, int order, int home) | |||
391 | pte_t *ptep = virt_to_pte(NULL, kva); | 412 | pte_t *ptep = virt_to_pte(NULL, kva); |
392 | pte_t pteval = *ptep; | 413 | pte_t pteval = *ptep; |
393 | BUG_ON(!pte_present(pteval) || pte_huge(pteval)); | 414 | BUG_ON(!pte_present(pteval) || pte_huge(pteval)); |
394 | *ptep = pte_set_home(pteval, home); | 415 | __set_pte(ptep, pte_set_home(pteval, home)); |
395 | } | 416 | } |
396 | } | 417 | } |
397 | 418 | ||
diff --git a/arch/tile/mm/hugetlbpage.c b/arch/tile/mm/hugetlbpage.c index 24688b697a8d..42cfcba4e1ef 100644 --- a/arch/tile/mm/hugetlbpage.c +++ b/arch/tile/mm/hugetlbpage.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
22 | #include <linux/hugetlb.h> | 22 | #include <linux/hugetlb.h> |
23 | #include <linux/pagemap.h> | 23 | #include <linux/pagemap.h> |
24 | #include <linux/smp_lock.h> | ||
25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
26 | #include <linux/err.h> | 25 | #include <linux/err.h> |
27 | #include <linux/sysctl.h> | 26 | #include <linux/sysctl.h> |
@@ -220,7 +219,7 @@ try_again: | |||
220 | if (mm->free_area_cache < len) | 219 | if (mm->free_area_cache < len) |
221 | goto fail; | 220 | goto fail; |
222 | 221 | ||
223 | /* either no address requested or cant fit in requested address hole */ | 222 | /* either no address requested or can't fit in requested address hole */ |
224 | addr = (mm->free_area_cache - len) & huge_page_mask(h); | 223 | addr = (mm->free_area_cache - len) & huge_page_mask(h); |
225 | do { | 224 | do { |
226 | /* | 225 | /* |
diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c index d89c9eacd162..4e10c4023028 100644 --- a/arch/tile/mm/init.c +++ b/arch/tile/mm/init.c | |||
@@ -53,26 +53,13 @@ | |||
53 | 53 | ||
54 | #include "migrate.h" | 54 | #include "migrate.h" |
55 | 55 | ||
56 | /* | ||
57 | * We could set FORCE_MAX_ZONEORDER to "(HPAGE_SHIFT - PAGE_SHIFT + 1)" | ||
58 | * in the Tile Kconfig, but this generates configure warnings. | ||
59 | * Do it here and force people to get it right to compile this file. | ||
60 | * The problem is that with 4KB small pages and 16MB huge pages, | ||
61 | * the default value doesn't allow us to group enough small pages | ||
62 | * together to make up a huge page. | ||
63 | */ | ||
64 | #if CONFIG_FORCE_MAX_ZONEORDER < HPAGE_SHIFT - PAGE_SHIFT + 1 | ||
65 | # error "Change FORCE_MAX_ZONEORDER in arch/tile/Kconfig to match page size" | ||
66 | #endif | ||
67 | |||
68 | #define clear_pgd(pmdptr) (*(pmdptr) = hv_pte(0)) | 56 | #define clear_pgd(pmdptr) (*(pmdptr) = hv_pte(0)) |
69 | 57 | ||
70 | #ifndef __tilegx__ | 58 | #ifndef __tilegx__ |
71 | unsigned long VMALLOC_RESERVE = CONFIG_VMALLOC_RESERVE; | 59 | unsigned long VMALLOC_RESERVE = CONFIG_VMALLOC_RESERVE; |
60 | EXPORT_SYMBOL(VMALLOC_RESERVE); | ||
72 | #endif | 61 | #endif |
73 | 62 | ||
74 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | ||
75 | |||
76 | /* Create an L2 page table */ | 63 | /* Create an L2 page table */ |
77 | static pte_t * __init alloc_pte(void) | 64 | static pte_t * __init alloc_pte(void) |
78 | { | 65 | { |
@@ -445,7 +432,7 @@ static pmd_t *__init get_pmd(pgd_t pgtables[], unsigned long va) | |||
445 | 432 | ||
446 | /* Temporary page table we use for staging. */ | 433 | /* Temporary page table we use for staging. */ |
447 | static pgd_t pgtables[PTRS_PER_PGD] | 434 | static pgd_t pgtables[PTRS_PER_PGD] |
448 | __attribute__((section(".init.page"))); | 435 | __attribute__((aligned(HV_PAGE_TABLE_ALIGN))); |
449 | 436 | ||
450 | /* | 437 | /* |
451 | * This maps the physical memory to kernel virtual address space, a total | 438 | * This maps the physical memory to kernel virtual address space, a total |
@@ -653,6 +640,17 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) | |||
653 | memcpy(pgd_base, pgtables, sizeof(pgtables)); | 640 | memcpy(pgd_base, pgtables, sizeof(pgtables)); |
654 | __install_page_table(pgd_base, __get_cpu_var(current_asid), | 641 | __install_page_table(pgd_base, __get_cpu_var(current_asid), |
655 | swapper_pgprot); | 642 | swapper_pgprot); |
643 | |||
644 | /* | ||
645 | * We just read swapper_pgprot and thus brought it into the cache, | ||
646 | * with its new home & caching mode. When we start the other CPUs, | ||
647 | * they're going to reference swapper_pgprot via their initial fake | ||
648 | * VA-is-PA mappings, which cache everything locally. At that | ||
649 | * time, if it's in our cache with a conflicting home, the | ||
650 | * simulator's coherence checker will complain. So, flush it out | ||
651 | * of our cache; we're not going to ever use it again anyway. | ||
652 | */ | ||
653 | __insn_finv(&swapper_pgprot); | ||
656 | } | 654 | } |
657 | 655 | ||
658 | /* | 656 | /* |
@@ -950,11 +948,7 @@ struct kmem_cache *pgd_cache; | |||
950 | 948 | ||
951 | void __init pgtable_cache_init(void) | 949 | void __init pgtable_cache_init(void) |
952 | { | 950 | { |
953 | pgd_cache = kmem_cache_create("pgd", | 951 | pgd_cache = kmem_cache_create("pgd", SIZEOF_PGD, SIZEOF_PGD, 0, NULL); |
954 | PTRS_PER_PGD*sizeof(pgd_t), | ||
955 | PTRS_PER_PGD*sizeof(pgd_t), | ||
956 | 0, | ||
957 | NULL); | ||
958 | if (!pgd_cache) | 952 | if (!pgd_cache) |
959 | panic("pgtable_cache_init(): Cannot create pgd cache"); | 953 | panic("pgtable_cache_init(): Cannot create pgd cache"); |
960 | } | 954 | } |
@@ -988,8 +982,12 @@ static long __write_once initfree = 1; | |||
988 | /* Select whether to free (1) or mark unusable (0) the __init pages. */ | 982 | /* Select whether to free (1) or mark unusable (0) the __init pages. */ |
989 | static int __init set_initfree(char *str) | 983 | static int __init set_initfree(char *str) |
990 | { | 984 | { |
991 | strict_strtol(str, 0, &initfree); | 985 | long val; |
992 | pr_info("initfree: %s free init pages\n", initfree ? "will" : "won't"); | 986 | if (strict_strtol(str, 0, &val) == 0) { |
987 | initfree = val; | ||
988 | pr_info("initfree: %s free init pages\n", | ||
989 | initfree ? "will" : "won't"); | ||
990 | } | ||
993 | return 1; | 991 | return 1; |
994 | } | 992 | } |
995 | __setup("initfree=", set_initfree); | 993 | __setup("initfree=", set_initfree); |
@@ -1060,7 +1058,7 @@ void free_initmem(void) | |||
1060 | 1058 | ||
1061 | /* | 1059 | /* |
1062 | * Free the pages mapped from 0xc0000000 that correspond to code | 1060 | * Free the pages mapped from 0xc0000000 that correspond to code |
1063 | * pages from 0xfd000000 that we won't use again after init. | 1061 | * pages from MEM_SV_INTRPT that we won't use again after init. |
1064 | */ | 1062 | */ |
1065 | free_init_pages("unused kernel text", | 1063 | free_init_pages("unused kernel text", |
1066 | (unsigned long)_sinittext - text_delta, | 1064 | (unsigned long)_sinittext - text_delta, |
diff --git a/arch/tile/mm/migrate_32.S b/arch/tile/mm/migrate_32.S index f738765cd1e6..ac01a7cdf77f 100644 --- a/arch/tile/mm/migrate_32.S +++ b/arch/tile/mm/migrate_32.S | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/linkage.h> | 18 | #include <linux/linkage.h> |
19 | #include <linux/threads.h> | 19 | #include <linux/threads.h> |
20 | #include <asm/page.h> | 20 | #include <asm/page.h> |
21 | #include <asm/thread_info.h> | ||
21 | #include <asm/types.h> | 22 | #include <asm/types.h> |
22 | #include <asm/asm-offsets.h> | 23 | #include <asm/asm-offsets.h> |
23 | #include <hv/hypervisor.h> | 24 | #include <hv/hypervisor.h> |
diff --git a/arch/tile/mm/migrate_64.S b/arch/tile/mm/migrate_64.S new file mode 100644 index 000000000000..e76fea688beb --- /dev/null +++ b/arch/tile/mm/migrate_64.S | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * Copyright 2011 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * This routine is a helper for migrating the home of a set of pages to | ||
15 | * a new cpu. See the documentation in homecache.c for more information. | ||
16 | */ | ||
17 | |||
18 | #include <linux/linkage.h> | ||
19 | #include <linux/threads.h> | ||
20 | #include <asm/page.h> | ||
21 | #include <asm/thread_info.h> | ||
22 | #include <asm/types.h> | ||
23 | #include <asm/asm-offsets.h> | ||
24 | #include <hv/hypervisor.h> | ||
25 | |||
26 | .text | ||
27 | |||
28 | /* | ||
29 | * First, some definitions that apply to all the code in the file. | ||
30 | */ | ||
31 | |||
32 | /* Locals (caller-save) */ | ||
33 | #define r_tmp r10 | ||
34 | #define r_save_sp r11 | ||
35 | |||
36 | /* What we save where in the stack frame; must include all callee-saves. */ | ||
37 | #define FRAME_SP 8 | ||
38 | #define FRAME_R30 16 | ||
39 | #define FRAME_R31 24 | ||
40 | #define FRAME_R32 32 | ||
41 | #define FRAME_R33 40 | ||
42 | #define FRAME_SIZE 48 | ||
43 | |||
44 | |||
45 | |||
46 | |||
47 | /* | ||
48 | * On entry: | ||
49 | * | ||
50 | * r0 the new context PA to install (moved to r_context) | ||
51 | * r1 PTE to use for context access (moved to r_access) | ||
52 | * r2 ASID to use for new context (moved to r_asid) | ||
53 | * r3 pointer to cpumask with just this cpu set in it (r_my_cpumask) | ||
54 | */ | ||
55 | |||
56 | /* Arguments (caller-save) */ | ||
57 | #define r_context_in r0 | ||
58 | #define r_access_in r1 | ||
59 | #define r_asid_in r2 | ||
60 | #define r_my_cpumask r3 | ||
61 | |||
62 | /* Locals (callee-save); must not be more than FRAME_xxx above. */ | ||
63 | #define r_save_ics r30 | ||
64 | #define r_context r31 | ||
65 | #define r_access r32 | ||
66 | #define r_asid r33 | ||
67 | |||
68 | /* | ||
69 | * Caller-save locals and frame constants are the same as | ||
70 | * for homecache_migrate_stack_and_flush. | ||
71 | */ | ||
72 | |||
73 | STD_ENTRY(flush_and_install_context) | ||
74 | /* | ||
75 | * Create a stack frame; we can't touch it once we flush the | ||
76 | * cache until we install the new page table and flush the TLB. | ||
77 | */ | ||
78 | { | ||
79 | move r_save_sp, sp | ||
80 | st sp, lr | ||
81 | addi sp, sp, -FRAME_SIZE | ||
82 | } | ||
83 | addi r_tmp, sp, FRAME_SP | ||
84 | { | ||
85 | st r_tmp, r_save_sp | ||
86 | addi r_tmp, sp, FRAME_R30 | ||
87 | } | ||
88 | { | ||
89 | st r_tmp, r30 | ||
90 | addi r_tmp, sp, FRAME_R31 | ||
91 | } | ||
92 | { | ||
93 | st r_tmp, r31 | ||
94 | addi r_tmp, sp, FRAME_R32 | ||
95 | } | ||
96 | { | ||
97 | st r_tmp, r32 | ||
98 | addi r_tmp, sp, FRAME_R33 | ||
99 | } | ||
100 | st r_tmp, r33 | ||
101 | |||
102 | /* Move some arguments to callee-save registers. */ | ||
103 | { | ||
104 | move r_context, r_context_in | ||
105 | move r_access, r_access_in | ||
106 | } | ||
107 | move r_asid, r_asid_in | ||
108 | |||
109 | /* Disable interrupts, since we can't use our stack. */ | ||
110 | { | ||
111 | mfspr r_save_ics, INTERRUPT_CRITICAL_SECTION | ||
112 | movei r_tmp, 1 | ||
113 | } | ||
114 | mtspr INTERRUPT_CRITICAL_SECTION, r_tmp | ||
115 | |||
116 | /* First, flush our L2 cache. */ | ||
117 | { | ||
118 | move r0, zero /* cache_pa */ | ||
119 | moveli r1, hw2_last(HV_FLUSH_EVICT_L2) /* cache_control */ | ||
120 | } | ||
121 | { | ||
122 | shl16insli r1, r1, hw1(HV_FLUSH_EVICT_L2) | ||
123 | move r2, r_my_cpumask /* cache_cpumask */ | ||
124 | } | ||
125 | { | ||
126 | shl16insli r1, r1, hw0(HV_FLUSH_EVICT_L2) | ||
127 | move r3, zero /* tlb_va */ | ||
128 | } | ||
129 | { | ||
130 | move r4, zero /* tlb_length */ | ||
131 | move r5, zero /* tlb_pgsize */ | ||
132 | } | ||
133 | { | ||
134 | move r6, zero /* tlb_cpumask */ | ||
135 | move r7, zero /* asids */ | ||
136 | } | ||
137 | { | ||
138 | move r8, zero /* asidcount */ | ||
139 | jal hv_flush_remote | ||
140 | } | ||
141 | bnez r0, 1f | ||
142 | |||
143 | /* Now install the new page table. */ | ||
144 | { | ||
145 | move r0, r_context | ||
146 | move r1, r_access | ||
147 | } | ||
148 | { | ||
149 | move r2, r_asid | ||
150 | movei r3, HV_CTX_DIRECTIO | ||
151 | } | ||
152 | jal hv_install_context | ||
153 | bnez r0, 1f | ||
154 | |||
155 | /* Finally, flush the TLB. */ | ||
156 | { | ||
157 | movei r0, 0 /* preserve_global */ | ||
158 | jal hv_flush_all | ||
159 | } | ||
160 | |||
161 | 1: /* Reset interrupts back how they were before. */ | ||
162 | mtspr INTERRUPT_CRITICAL_SECTION, r_save_ics | ||
163 | |||
164 | /* Restore the callee-saved registers and return. */ | ||
165 | addli lr, sp, FRAME_SIZE | ||
166 | { | ||
167 | ld lr, lr | ||
168 | addli r_tmp, sp, FRAME_R30 | ||
169 | } | ||
170 | { | ||
171 | ld r30, r_tmp | ||
172 | addli r_tmp, sp, FRAME_R31 | ||
173 | } | ||
174 | { | ||
175 | ld r31, r_tmp | ||
176 | addli r_tmp, sp, FRAME_R32 | ||
177 | } | ||
178 | { | ||
179 | ld r32, r_tmp | ||
180 | addli r_tmp, sp, FRAME_R33 | ||
181 | } | ||
182 | { | ||
183 | ld r33, r_tmp | ||
184 | addi sp, sp, FRAME_SIZE | ||
185 | } | ||
186 | jrp lr | ||
187 | STD_ENDPROC(flush_and_install_context) | ||
diff --git a/arch/tile/mm/pgtable.c b/arch/tile/mm/pgtable.c index 335c24621c41..de7d8e21e01d 100644 --- a/arch/tile/mm/pgtable.c +++ b/arch/tile/mm/pgtable.c | |||
@@ -41,7 +41,7 @@ | |||
41 | * The normal show_free_areas() is too verbose on Tile, with dozens | 41 | * The normal show_free_areas() is too verbose on Tile, with dozens |
42 | * of processors and often four NUMA zones each with high and lowmem. | 42 | * of processors and often four NUMA zones each with high and lowmem. |
43 | */ | 43 | */ |
44 | void show_mem(void) | 44 | void show_mem(unsigned int filter) |
45 | { | 45 | { |
46 | struct zone *zone; | 46 | struct zone *zone; |
47 | 47 | ||
@@ -134,14 +134,84 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t flags) | |||
134 | } | 134 | } |
135 | 135 | ||
136 | #if defined(CONFIG_HIGHPTE) | 136 | #if defined(CONFIG_HIGHPTE) |
137 | pte_t *_pte_offset_map(pmd_t *dir, unsigned long address, enum km_type type) | 137 | pte_t *_pte_offset_map(pmd_t *dir, unsigned long address) |
138 | { | 138 | { |
139 | pte_t *pte = kmap_atomic(pmd_page(*dir), type) + | 139 | pte_t *pte = kmap_atomic(pmd_page(*dir)) + |
140 | (pmd_ptfn(*dir) << HV_LOG2_PAGE_TABLE_ALIGN) & ~PAGE_MASK; | 140 | (pmd_ptfn(*dir) << HV_LOG2_PAGE_TABLE_ALIGN) & ~PAGE_MASK; |
141 | return &pte[pte_index(address)]; | 141 | return &pte[pte_index(address)]; |
142 | } | 142 | } |
143 | #endif | 143 | #endif |
144 | 144 | ||
145 | /** | ||
146 | * shatter_huge_page() - ensure a given address is mapped by a small page. | ||
147 | * | ||
148 | * This function converts a huge PTE mapping kernel LOWMEM into a bunch | ||
149 | * of small PTEs with the same caching. No cache flush required, but we | ||
150 | * must do a global TLB flush. | ||
151 | * | ||
152 | * Any caller that wishes to modify a kernel mapping that might | ||
153 | * have been made with a huge page should call this function, | ||
154 | * since doing so properly avoids race conditions with installing the | ||
155 | * newly-shattered page and then flushing all the TLB entries. | ||
156 | * | ||
157 | * @addr: Address at which to shatter any existing huge page. | ||
158 | */ | ||
159 | void shatter_huge_page(unsigned long addr) | ||
160 | { | ||
161 | pgd_t *pgd; | ||
162 | pud_t *pud; | ||
163 | pmd_t *pmd; | ||
164 | unsigned long flags = 0; /* happy compiler */ | ||
165 | #ifdef __PAGETABLE_PMD_FOLDED | ||
166 | struct list_head *pos; | ||
167 | #endif | ||
168 | |||
169 | /* Get a pointer to the pmd entry that we need to change. */ | ||
170 | addr &= HPAGE_MASK; | ||
171 | BUG_ON(pgd_addr_invalid(addr)); | ||
172 | BUG_ON(addr < PAGE_OFFSET); /* only for kernel LOWMEM */ | ||
173 | pgd = swapper_pg_dir + pgd_index(addr); | ||
174 | pud = pud_offset(pgd, addr); | ||
175 | BUG_ON(!pud_present(*pud)); | ||
176 | pmd = pmd_offset(pud, addr); | ||
177 | BUG_ON(!pmd_present(*pmd)); | ||
178 | if (!pmd_huge_page(*pmd)) | ||
179 | return; | ||
180 | |||
181 | /* | ||
182 | * Grab the pgd_lock, since we may need it to walk the pgd_list, | ||
183 | * and since we need some kind of lock here to avoid races. | ||
184 | */ | ||
185 | spin_lock_irqsave(&pgd_lock, flags); | ||
186 | if (!pmd_huge_page(*pmd)) { | ||
187 | /* Lost the race to convert the huge page. */ | ||
188 | spin_unlock_irqrestore(&pgd_lock, flags); | ||
189 | return; | ||
190 | } | ||
191 | |||
192 | /* Shatter the huge page into the preallocated L2 page table. */ | ||
193 | pmd_populate_kernel(&init_mm, pmd, | ||
194 | get_prealloc_pte(pte_pfn(*(pte_t *)pmd))); | ||
195 | |||
196 | #ifdef __PAGETABLE_PMD_FOLDED | ||
197 | /* Walk every pgd on the system and update the pmd there. */ | ||
198 | list_for_each(pos, &pgd_list) { | ||
199 | pmd_t *copy_pmd; | ||
200 | pgd = list_to_pgd(pos) + pgd_index(addr); | ||
201 | pud = pud_offset(pgd, addr); | ||
202 | copy_pmd = pmd_offset(pud, addr); | ||
203 | __set_pmd(copy_pmd, *pmd); | ||
204 | } | ||
205 | #endif | ||
206 | |||
207 | /* Tell every cpu to notice the change. */ | ||
208 | flush_remote(0, 0, NULL, addr, HPAGE_SIZE, HPAGE_SIZE, | ||
209 | cpu_possible_mask, NULL, 0); | ||
210 | |||
211 | /* Hold the lock until the TLB flush is finished to avoid races. */ | ||
212 | spin_unlock_irqrestore(&pgd_lock, flags); | ||
213 | } | ||
214 | |||
145 | /* | 215 | /* |
146 | * List of all pgd's needed so it can invalidate entries in both cached | 216 | * List of all pgd's needed so it can invalidate entries in both cached |
147 | * and uncached pgd's. This is essentially codepath-based locking | 217 | * and uncached pgd's. This is essentially codepath-based locking |
@@ -184,9 +254,9 @@ static void pgd_ctor(pgd_t *pgd) | |||
184 | BUG_ON(((u64 *)swapper_pg_dir)[pgd_index(MEM_USER_INTRPT)] != 0); | 254 | BUG_ON(((u64 *)swapper_pg_dir)[pgd_index(MEM_USER_INTRPT)] != 0); |
185 | #endif | 255 | #endif |
186 | 256 | ||
187 | clone_pgd_range(pgd + KERNEL_PGD_INDEX_START, | 257 | memcpy(pgd + KERNEL_PGD_INDEX_START, |
188 | swapper_pg_dir + KERNEL_PGD_INDEX_START, | 258 | swapper_pg_dir + KERNEL_PGD_INDEX_START, |
189 | KERNEL_PGD_PTRS); | 259 | KERNEL_PGD_PTRS * sizeof(pgd_t)); |
190 | 260 | ||
191 | pgd_list_add(pgd); | 261 | pgd_list_add(pgd); |
192 | spin_unlock_irqrestore(&pgd_lock, flags); | 262 | spin_unlock_irqrestore(&pgd_lock, flags); |
@@ -220,8 +290,11 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd) | |||
220 | 290 | ||
221 | struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | 291 | struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) |
222 | { | 292 | { |
223 | gfp_t flags = GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO|__GFP_COMP; | 293 | gfp_t flags = GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO; |
224 | struct page *p; | 294 | struct page *p; |
295 | #if L2_USER_PGTABLE_ORDER > 0 | ||
296 | int i; | ||
297 | #endif | ||
225 | 298 | ||
226 | #ifdef CONFIG_HIGHPTE | 299 | #ifdef CONFIG_HIGHPTE |
227 | flags |= __GFP_HIGHMEM; | 300 | flags |= __GFP_HIGHMEM; |
@@ -231,6 +304,18 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | |||
231 | if (p == NULL) | 304 | if (p == NULL) |
232 | return NULL; | 305 | return NULL; |
233 | 306 | ||
307 | #if L2_USER_PGTABLE_ORDER > 0 | ||
308 | /* | ||
309 | * Make every page have a page_count() of one, not just the first. | ||
310 | * We don't use __GFP_COMP since it doesn't look like it works | ||
311 | * correctly with tlb_remove_page(). | ||
312 | */ | ||
313 | for (i = 1; i < L2_USER_PGTABLE_PAGES; ++i) { | ||
314 | init_page_count(p+i); | ||
315 | inc_zone_page_state(p+i, NR_PAGETABLE); | ||
316 | } | ||
317 | #endif | ||
318 | |||
234 | pgtable_page_ctor(p); | 319 | pgtable_page_ctor(p); |
235 | return p; | 320 | return p; |
236 | } | 321 | } |
@@ -242,8 +327,15 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | |||
242 | */ | 327 | */ |
243 | void pte_free(struct mm_struct *mm, struct page *p) | 328 | void pte_free(struct mm_struct *mm, struct page *p) |
244 | { | 329 | { |
330 | int i; | ||
331 | |||
245 | pgtable_page_dtor(p); | 332 | pgtable_page_dtor(p); |
246 | __free_pages(p, L2_USER_PGTABLE_ORDER); | 333 | __free_page(p); |
334 | |||
335 | for (i = 1; i < L2_USER_PGTABLE_PAGES; ++i) { | ||
336 | __free_page(p+i); | ||
337 | dec_zone_page_state(p+i, NR_PAGETABLE); | ||
338 | } | ||
247 | } | 339 | } |
248 | 340 | ||
249 | void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte, | 341 | void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte, |
@@ -252,18 +344,11 @@ void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte, | |||
252 | int i; | 344 | int i; |
253 | 345 | ||
254 | pgtable_page_dtor(pte); | 346 | pgtable_page_dtor(pte); |
255 | tlb->need_flush = 1; | 347 | tlb_remove_page(tlb, pte); |
256 | if (tlb_fast_mode(tlb)) { | 348 | |
257 | struct page *pte_pages[L2_USER_PGTABLE_PAGES]; | 349 | for (i = 1; i < L2_USER_PGTABLE_PAGES; ++i) { |
258 | for (i = 0; i < L2_USER_PGTABLE_PAGES; ++i) | 350 | tlb_remove_page(tlb, pte + i); |
259 | pte_pages[i] = pte + i; | 351 | dec_zone_page_state(pte + i, NR_PAGETABLE); |
260 | free_pages_and_swap_cache(pte_pages, L2_USER_PGTABLE_PAGES); | ||
261 | return; | ||
262 | } | ||
263 | for (i = 0; i < L2_USER_PGTABLE_PAGES; ++i) { | ||
264 | tlb->pages[tlb->nr++] = pte + i; | ||
265 | if (tlb->nr >= FREE_PTE_NR) | ||
266 | tlb_flush_mmu(tlb, 0, 0); | ||
267 | } | 352 | } |
268 | } | 353 | } |
269 | 354 | ||
@@ -346,35 +431,51 @@ int get_remote_cache_cpu(pgprot_t prot) | |||
346 | return x + y * smp_width; | 431 | return x + y * smp_width; |
347 | } | 432 | } |
348 | 433 | ||
349 | void set_pte_order(pte_t *ptep, pte_t pte, int order) | 434 | /* |
435 | * Convert a kernel VA to a PA and homing information. | ||
436 | */ | ||
437 | int va_to_cpa_and_pte(void *va, unsigned long long *cpa, pte_t *pte) | ||
350 | { | 438 | { |
351 | unsigned long pfn = pte_pfn(pte); | 439 | struct page *page = virt_to_page(va); |
352 | struct page *page = pfn_to_page(pfn); | 440 | pte_t null_pte = { 0 }; |
353 | 441 | ||
354 | /* Update the home of a PTE if necessary */ | 442 | *cpa = __pa(va); |
355 | pte = pte_set_home(pte, page_home(page)); | ||
356 | 443 | ||
444 | /* Note that this is not writing a page table, just returning a pte. */ | ||
445 | *pte = pte_set_home(null_pte, page_home(page)); | ||
446 | |||
447 | return 0; /* return non-zero if not hfh? */ | ||
448 | } | ||
449 | EXPORT_SYMBOL(va_to_cpa_and_pte); | ||
450 | |||
451 | void __set_pte(pte_t *ptep, pte_t pte) | ||
452 | { | ||
357 | #ifdef __tilegx__ | 453 | #ifdef __tilegx__ |
358 | *ptep = pte; | 454 | *ptep = pte; |
359 | #else | 455 | #else |
360 | /* | 456 | # if HV_PTE_INDEX_PRESENT >= 32 || HV_PTE_INDEX_MIGRATING >= 32 |
361 | * When setting a PTE, write the high bits first, then write | 457 | # error Must write the present and migrating bits last |
362 | * the low bits. This sets the "present" bit only after the | 458 | # endif |
363 | * other bits are in place. If a particular PTE update | 459 | if (pte_present(pte)) { |
364 | * involves transitioning from one valid PTE to another, it | 460 | ((u32 *)ptep)[1] = (u32)(pte_val(pte) >> 32); |
365 | * may be necessary to call set_pte_order() more than once, | 461 | barrier(); |
366 | * transitioning via a suitable intermediate state. | 462 | ((u32 *)ptep)[0] = (u32)(pte_val(pte)); |
367 | * Note that this sequence also means that if we are transitioning | 463 | } else { |
368 | * from any migrating PTE to a non-migrating one, we will not | 464 | ((u32 *)ptep)[0] = (u32)(pte_val(pte)); |
369 | * see a half-updated PTE with the migrating bit off. | 465 | barrier(); |
370 | */ | 466 | ((u32 *)ptep)[1] = (u32)(pte_val(pte) >> 32); |
371 | #if HV_PTE_INDEX_PRESENT >= 32 || HV_PTE_INDEX_MIGRATING >= 32 | 467 | } |
372 | # error Must write the present and migrating bits last | 468 | #endif /* __tilegx__ */ |
373 | #endif | 469 | } |
374 | ((u32 *)ptep)[1] = (u32)(pte_val(pte) >> 32); | 470 | |
375 | barrier(); | 471 | void set_pte(pte_t *ptep, pte_t pte) |
376 | ((u32 *)ptep)[0] = (u32)(pte_val(pte)); | 472 | { |
377 | #endif | 473 | struct page *page = pfn_to_page(pte_pfn(pte)); |
474 | |||
475 | /* Update the home of a PTE if necessary */ | ||
476 | pte = pte_set_home(pte, page_home(page)); | ||
477 | |||
478 | __set_pte(ptep, pte); | ||
378 | } | 479 | } |
379 | 480 | ||
380 | /* Can this mm load a PTE with cached_priority set? */ | 481 | /* Can this mm load a PTE with cached_priority set? */ |