[PATCH] powerpc: Add missing icache flushes for hugepages
[linux-block.git] / arch / powerpc / mm / hugetlbpage.c
1 /*
2  * PPC64 (POWER4) Huge TLB Page Support for Kernel.
3  *
4  * Copyright (C) 2003 David Gibson, IBM Corporation.
5  *
6  * Based on the IA-32 version:
7  * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com>
8  */
9
10 #include <linux/init.h>
11 #include <linux/fs.h>
12 #include <linux/mm.h>
13 #include <linux/hugetlb.h>
14 #include <linux/pagemap.h>
15 #include <linux/smp_lock.h>
16 #include <linux/slab.h>
17 #include <linux/err.h>
18 #include <linux/sysctl.h>
19 #include <asm/mman.h>
20 #include <asm/pgalloc.h>
21 #include <asm/tlb.h>
22 #include <asm/tlbflush.h>
23 #include <asm/mmu_context.h>
24 #include <asm/machdep.h>
25 #include <asm/cputable.h>
26 #include <asm/tlb.h>
27
28 #include <linux/sysctl.h>
29
30 #define NUM_LOW_AREAS   (0x100000000UL >> SID_SHIFT)
31 #define NUM_HIGH_AREAS  (PGTABLE_RANGE >> HTLB_AREA_SHIFT)
32
33 /* Modelled after find_linux_pte() */
34 pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
35 {
36         pgd_t *pg;
37         pud_t *pu;
38         pmd_t *pm;
39         pte_t *pt;
40
41         BUG_ON(! in_hugepage_area(mm->context, addr));
42
43         addr &= HPAGE_MASK;
44
45         pg = pgd_offset(mm, addr);
46         if (!pgd_none(*pg)) {
47                 pu = pud_offset(pg, addr);
48                 if (!pud_none(*pu)) {
49                         pm = pmd_offset(pu, addr);
50 #ifdef CONFIG_PPC_64K_PAGES
51                         /* Currently, we use the normal PTE offset within full
52                          * size PTE pages, thus our huge PTEs are scattered in
53                          * the PTE page and we do waste some. We may change
54                          * that in the future, but the current mecanism keeps
55                          * things much simpler
56                          */
57                         if (!pmd_none(*pm)) {
58                                 /* Note: pte_offset_* are all equivalent on
59                                  * ppc64 as we don't have HIGHMEM
60                                  */
61                                 pt = pte_offset_kernel(pm, addr);
62                                 return pt;
63                         }
64 #else /* CONFIG_PPC_64K_PAGES */
65                         /* On 4k pages, we put huge PTEs in the PMD page */
66                         pt = (pte_t *)pm;
67                         return pt;
68 #endif /* CONFIG_PPC_64K_PAGES */
69                 }
70         }
71
72         return NULL;
73 }
74
75 pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
76 {
77         pgd_t *pg;
78         pud_t *pu;
79         pmd_t *pm;
80         pte_t *pt;
81
82         BUG_ON(! in_hugepage_area(mm->context, addr));
83
84         addr &= HPAGE_MASK;
85
86         pg = pgd_offset(mm, addr);
87         pu = pud_alloc(mm, pg, addr);
88
89         if (pu) {
90                 pm = pmd_alloc(mm, pu, addr);
91                 if (pm) {
92 #ifdef CONFIG_PPC_64K_PAGES
93                         /* See comment in huge_pte_offset. Note that if we ever
94                          * want to put the page size in the PMD, we would have
95                          * to open code our own pte_alloc* function in order
96                          * to populate and set the size atomically
97                          */
98                         pt = pte_alloc_map(mm, pm, addr);
99 #else /* CONFIG_PPC_64K_PAGES */
100                         pt = (pte_t *)pm;
101 #endif /* CONFIG_PPC_64K_PAGES */
102                         return pt;
103                 }
104         }
105
106         return NULL;
107 }
108
109 void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
110                      pte_t *ptep, pte_t pte)
111 {
112         if (pte_present(*ptep)) {
113                 /* We open-code pte_clear because we need to pass the right
114                  * argument to hpte_update (huge / !huge)
115                  */
116                 unsigned long old = pte_update(ptep, ~0UL);
117                 if (old & _PAGE_HASHPTE)
118                         hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1);
119                 flush_tlb_pending();
120         }
121         *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
122 }
123
124 pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
125                               pte_t *ptep)
126 {
127         unsigned long old = pte_update(ptep, ~0UL);
128
129         if (old & _PAGE_HASHPTE)
130                 hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1);
131         *ptep = __pte(0);
132
133         return __pte(old);
134 }
135
136 /*
137  * This function checks for proper alignment of input addr and len parameters.
138  */
139 int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
140 {
141         if (len & ~HPAGE_MASK)
142                 return -EINVAL;
143         if (addr & ~HPAGE_MASK)
144                 return -EINVAL;
145         if (! (within_hugepage_low_range(addr, len)
146                || within_hugepage_high_range(addr, len)) )
147                 return -EINVAL;
148         return 0;
149 }
150
151 static void flush_low_segments(void *parm)
152 {
153         u16 areas = (unsigned long) parm;
154         unsigned long i;
155
156         asm volatile("isync" : : : "memory");
157
158         BUILD_BUG_ON((sizeof(areas)*8) != NUM_LOW_AREAS);
159
160         for (i = 0; i < NUM_LOW_AREAS; i++) {
161                 if (! (areas & (1U << i)))
162                         continue;
163                 asm volatile("slbie %0"
164                              : : "r" ((i << SID_SHIFT) | SLBIE_C));
165         }
166
167         asm volatile("isync" : : : "memory");
168 }
169
170 static void flush_high_segments(void *parm)
171 {
172         u16 areas = (unsigned long) parm;
173         unsigned long i, j;
174
175         asm volatile("isync" : : : "memory");
176
177         BUILD_BUG_ON((sizeof(areas)*8) != NUM_HIGH_AREAS);
178
179         for (i = 0; i < NUM_HIGH_AREAS; i++) {
180                 if (! (areas & (1U << i)))
181                         continue;
182                 for (j = 0; j < (1UL << (HTLB_AREA_SHIFT-SID_SHIFT)); j++)
183                         asm volatile("slbie %0"
184                                      :: "r" (((i << HTLB_AREA_SHIFT)
185                                              + (j << SID_SHIFT)) | SLBIE_C));
186         }
187
188         asm volatile("isync" : : : "memory");
189 }
190
191 static int prepare_low_area_for_htlb(struct mm_struct *mm, unsigned long area)
192 {
193         unsigned long start = area << SID_SHIFT;
194         unsigned long end = (area+1) << SID_SHIFT;
195         struct vm_area_struct *vma;
196
197         BUG_ON(area >= NUM_LOW_AREAS);
198
199         /* Check no VMAs are in the region */
200         vma = find_vma(mm, start);
201         if (vma && (vma->vm_start < end))
202                 return -EBUSY;
203
204         return 0;
205 }
206
207 static int prepare_high_area_for_htlb(struct mm_struct *mm, unsigned long area)
208 {
209         unsigned long start = area << HTLB_AREA_SHIFT;
210         unsigned long end = (area+1) << HTLB_AREA_SHIFT;
211         struct vm_area_struct *vma;
212
213         BUG_ON(area >= NUM_HIGH_AREAS);
214
215         /* Hack, so that each addresses is controlled by exactly one
216          * of the high or low area bitmaps, the first high area starts
217          * at 4GB, not 0 */
218         if (start == 0)
219                 start = 0x100000000UL;
220
221         /* Check no VMAs are in the region */
222         vma = find_vma(mm, start);
223         if (vma && (vma->vm_start < end))
224                 return -EBUSY;
225
226         return 0;
227 }
228
229 static int open_low_hpage_areas(struct mm_struct *mm, u16 newareas)
230 {
231         unsigned long i;
232
233         BUILD_BUG_ON((sizeof(newareas)*8) != NUM_LOW_AREAS);
234         BUILD_BUG_ON((sizeof(mm->context.low_htlb_areas)*8) != NUM_LOW_AREAS);
235
236         newareas &= ~(mm->context.low_htlb_areas);
237         if (! newareas)
238                 return 0; /* The segments we want are already open */
239
240         for (i = 0; i < NUM_LOW_AREAS; i++)
241                 if ((1 << i) & newareas)
242                         if (prepare_low_area_for_htlb(mm, i) != 0)
243                                 return -EBUSY;
244
245         mm->context.low_htlb_areas |= newareas;
246
247         /* update the paca copy of the context struct */
248         get_paca()->context = mm->context;
249
250         /* the context change must make it to memory before the flush,
251          * so that further SLB misses do the right thing. */
252         mb();
253         on_each_cpu(flush_low_segments, (void *)(unsigned long)newareas, 0, 1);
254
255         return 0;
256 }
257
258 static int open_high_hpage_areas(struct mm_struct *mm, u16 newareas)
259 {
260         unsigned long i;
261
262         BUILD_BUG_ON((sizeof(newareas)*8) != NUM_HIGH_AREAS);
263         BUILD_BUG_ON((sizeof(mm->context.high_htlb_areas)*8)
264                      != NUM_HIGH_AREAS);
265
266         newareas &= ~(mm->context.high_htlb_areas);
267         if (! newareas)
268                 return 0; /* The areas we want are already open */
269
270         for (i = 0; i < NUM_HIGH_AREAS; i++)
271                 if ((1 << i) & newareas)
272                         if (prepare_high_area_for_htlb(mm, i) != 0)
273                                 return -EBUSY;
274
275         mm->context.high_htlb_areas |= newareas;
276
277         /* update the paca copy of the context struct */
278         get_paca()->context = mm->context;
279
280         /* the context change must make it to memory before the flush,
281          * so that further SLB misses do the right thing. */
282         mb();
283         on_each_cpu(flush_high_segments, (void *)(unsigned long)newareas, 0, 1);
284
285         return 0;
286 }
287
288 int prepare_hugepage_range(unsigned long addr, unsigned long len)
289 {
290         int err = 0;
291
292         if ( (addr+len) < addr )
293                 return -EINVAL;
294
295         if (addr < 0x100000000UL)
296                 err = open_low_hpage_areas(current->mm,
297                                           LOW_ESID_MASK(addr, len));
298         if ((addr + len) > 0x100000000UL)
299                 err = open_high_hpage_areas(current->mm,
300                                             HTLB_AREA_MASK(addr, len));
301         if (err) {
302                 printk(KERN_DEBUG "prepare_hugepage_range(%lx, %lx)"
303                        " failed (lowmask: 0x%04hx, highmask: 0x%04hx)\n",
304                        addr, len,
305                        LOW_ESID_MASK(addr, len), HTLB_AREA_MASK(addr, len));
306                 return err;
307         }
308
309         return 0;
310 }
311
312 struct page *
313 follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
314 {
315         pte_t *ptep;
316         struct page *page;
317
318         if (! in_hugepage_area(mm->context, address))
319                 return ERR_PTR(-EINVAL);
320
321         ptep = huge_pte_offset(mm, address);
322         page = pte_page(*ptep);
323         if (page)
324                 page += (address % HPAGE_SIZE) / PAGE_SIZE;
325
326         return page;
327 }
328
329 int pmd_huge(pmd_t pmd)
330 {
331         return 0;
332 }
333
334 struct page *
335 follow_huge_pmd(struct mm_struct *mm, unsigned long address,
336                 pmd_t *pmd, int write)
337 {
338         BUG();
339         return NULL;
340 }
341
342 /* Because we have an exclusive hugepage region which lies within the
343  * normal user address space, we have to take special measures to make
344  * non-huge mmap()s evade the hugepage reserved regions. */
345 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
346                                      unsigned long len, unsigned long pgoff,
347                                      unsigned long flags)
348 {
349         struct mm_struct *mm = current->mm;
350         struct vm_area_struct *vma;
351         unsigned long start_addr;
352
353         if (len > TASK_SIZE)
354                 return -ENOMEM;
355
356         if (addr) {
357                 addr = PAGE_ALIGN(addr);
358                 vma = find_vma(mm, addr);
359                 if (((TASK_SIZE - len) >= addr)
360                     && (!vma || (addr+len) <= vma->vm_start)
361                     && !is_hugepage_only_range(mm, addr,len))
362                         return addr;
363         }
364         if (len > mm->cached_hole_size) {
365                 start_addr = addr = mm->free_area_cache;
366         } else {
367                 start_addr = addr = TASK_UNMAPPED_BASE;
368                 mm->cached_hole_size = 0;
369         }
370
371 full_search:
372         vma = find_vma(mm, addr);
373         while (TASK_SIZE - len >= addr) {
374                 BUG_ON(vma && (addr >= vma->vm_end));
375
376                 if (touches_hugepage_low_range(mm, addr, len)) {
377                         addr = ALIGN(addr+1, 1<<SID_SHIFT);
378                         vma = find_vma(mm, addr);
379                         continue;
380                 }
381                 if (touches_hugepage_high_range(mm, addr, len)) {
382                         addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);
383                         vma = find_vma(mm, addr);
384                         continue;
385                 }
386                 if (!vma || addr + len <= vma->vm_start) {
387                         /*
388                          * Remember the place where we stopped the search:
389                          */
390                         mm->free_area_cache = addr + len;
391                         return addr;
392                 }
393                 if (addr + mm->cached_hole_size < vma->vm_start)
394                         mm->cached_hole_size = vma->vm_start - addr;
395                 addr = vma->vm_end;
396                 vma = vma->vm_next;
397         }
398
399         /* Make sure we didn't miss any holes */
400         if (start_addr != TASK_UNMAPPED_BASE) {
401                 start_addr = addr = TASK_UNMAPPED_BASE;
402                 mm->cached_hole_size = 0;
403                 goto full_search;
404         }
405         return -ENOMEM;
406 }
407
408 /*
409  * This mmap-allocator allocates new areas top-down from below the
410  * stack's low limit (the base):
411  *
412  * Because we have an exclusive hugepage region which lies within the
413  * normal user address space, we have to take special measures to make
414  * non-huge mmap()s evade the hugepage reserved regions.
415  */
416 unsigned long
417 arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
418                           const unsigned long len, const unsigned long pgoff,
419                           const unsigned long flags)
420 {
421         struct vm_area_struct *vma, *prev_vma;
422         struct mm_struct *mm = current->mm;
423         unsigned long base = mm->mmap_base, addr = addr0;
424         unsigned long largest_hole = mm->cached_hole_size;
425         int first_time = 1;
426
427         /* requested length too big for entire address space */
428         if (len > TASK_SIZE)
429                 return -ENOMEM;
430
431         /* dont allow allocations above current base */
432         if (mm->free_area_cache > base)
433                 mm->free_area_cache = base;
434
435         /* requesting a specific address */
436         if (addr) {
437                 addr = PAGE_ALIGN(addr);
438                 vma = find_vma(mm, addr);
439                 if (TASK_SIZE - len >= addr &&
440                                 (!vma || addr + len <= vma->vm_start)
441                                 && !is_hugepage_only_range(mm, addr,len))
442                         return addr;
443         }
444
445         if (len <= largest_hole) {
446                 largest_hole = 0;
447                 mm->free_area_cache = base;
448         }
449 try_again:
450         /* make sure it can fit in the remaining address space */
451         if (mm->free_area_cache < len)
452                 goto fail;
453
454         /* either no address requested or cant fit in requested address hole */
455         addr = (mm->free_area_cache - len) & PAGE_MASK;
456         do {
457 hugepage_recheck:
458                 if (touches_hugepage_low_range(mm, addr, len)) {
459                         addr = (addr & ((~0) << SID_SHIFT)) - len;
460                         goto hugepage_recheck;
461                 } else if (touches_hugepage_high_range(mm, addr, len)) {
462                         addr = (addr & ((~0UL) << HTLB_AREA_SHIFT)) - len;
463                         goto hugepage_recheck;
464                 }
465
466                 /*
467                  * Lookup failure means no vma is above this address,
468                  * i.e. return with success:
469                  */
470                 if (!(vma = find_vma_prev(mm, addr, &prev_vma)))
471                         return addr;
472
473                 /*
474                  * new region fits between prev_vma->vm_end and
475                  * vma->vm_start, use it:
476                  */
477                 if (addr+len <= vma->vm_start &&
478                           (!prev_vma || (addr >= prev_vma->vm_end))) {
479                         /* remember the address as a hint for next time */
480                         mm->cached_hole_size = largest_hole;
481                         return (mm->free_area_cache = addr);
482                 } else {
483                         /* pull free_area_cache down to the first hole */
484                         if (mm->free_area_cache == vma->vm_end) {
485                                 mm->free_area_cache = vma->vm_start;
486                                 mm->cached_hole_size = largest_hole;
487                         }
488                 }
489
490                 /* remember the largest hole we saw so far */
491                 if (addr + largest_hole < vma->vm_start)
492                         largest_hole = vma->vm_start - addr;
493
494                 /* try just below the current vma->vm_start */
495                 addr = vma->vm_start-len;
496         } while (len <= vma->vm_start);
497
498 fail:
499         /*
500          * if hint left us with no space for the requested
501          * mapping then try again:
502          */
503         if (first_time) {
504                 mm->free_area_cache = base;
505                 largest_hole = 0;
506                 first_time = 0;
507                 goto try_again;
508         }
509         /*
510          * A failed mmap() very likely causes application failure,
511          * so fall back to the bottom-up function here. This scenario
512          * can happen with large stack limits and large mmap()
513          * allocations.
514          */
515         mm->free_area_cache = TASK_UNMAPPED_BASE;
516         mm->cached_hole_size = ~0UL;
517         addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
518         /*
519          * Restore the topdown base:
520          */
521         mm->free_area_cache = base;
522         mm->cached_hole_size = ~0UL;
523
524         return addr;
525 }
526
527 static unsigned long htlb_get_low_area(unsigned long len, u16 segmask)
528 {
529         unsigned long addr = 0;
530         struct vm_area_struct *vma;
531
532         vma = find_vma(current->mm, addr);
533         while (addr + len <= 0x100000000UL) {
534                 BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */
535
536                 if (! __within_hugepage_low_range(addr, len, segmask)) {
537                         addr = ALIGN(addr+1, 1<<SID_SHIFT);
538                         vma = find_vma(current->mm, addr);
539                         continue;
540                 }
541
542                 if (!vma || (addr + len) <= vma->vm_start)
543                         return addr;
544                 addr = ALIGN(vma->vm_end, HPAGE_SIZE);
545                 /* Depending on segmask this might not be a confirmed
546                  * hugepage region, so the ALIGN could have skipped
547                  * some VMAs */
548                 vma = find_vma(current->mm, addr);
549         }
550
551         return -ENOMEM;
552 }
553
554 static unsigned long htlb_get_high_area(unsigned long len, u16 areamask)
555 {
556         unsigned long addr = 0x100000000UL;
557         struct vm_area_struct *vma;
558
559         vma = find_vma(current->mm, addr);
560         while (addr + len <= TASK_SIZE_USER64) {
561                 BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */
562
563                 if (! __within_hugepage_high_range(addr, len, areamask)) {
564                         addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);
565                         vma = find_vma(current->mm, addr);
566                         continue;
567                 }
568
569                 if (!vma || (addr + len) <= vma->vm_start)
570                         return addr;
571                 addr = ALIGN(vma->vm_end, HPAGE_SIZE);
572                 /* Depending on segmask this might not be a confirmed
573                  * hugepage region, so the ALIGN could have skipped
574                  * some VMAs */
575                 vma = find_vma(current->mm, addr);
576         }
577
578         return -ENOMEM;
579 }
580
581 unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
582                                         unsigned long len, unsigned long pgoff,
583                                         unsigned long flags)
584 {
585         int lastshift;
586         u16 areamask, curareas;
587
588         if (HPAGE_SHIFT == 0)
589                 return -EINVAL;
590         if (len & ~HPAGE_MASK)
591                 return -EINVAL;
592
593         if (!cpu_has_feature(CPU_FTR_16M_PAGE))
594                 return -EINVAL;
595
596         if (test_thread_flag(TIF_32BIT)) {
597                 curareas = current->mm->context.low_htlb_areas;
598
599                 /* First see if we can do the mapping in the existing
600                  * low areas */
601                 addr = htlb_get_low_area(len, curareas);
602                 if (addr != -ENOMEM)
603                         return addr;
604
605                 lastshift = 0;
606                 for (areamask = LOW_ESID_MASK(0x100000000UL-len, len);
607                      ! lastshift; areamask >>=1) {
608                         if (areamask & 1)
609                                 lastshift = 1;
610
611                         addr = htlb_get_low_area(len, curareas | areamask);
612                         if ((addr != -ENOMEM)
613                             && open_low_hpage_areas(current->mm, areamask) == 0)
614                                 return addr;
615                 }
616         } else {
617                 curareas = current->mm->context.high_htlb_areas;
618
619                 /* First see if we can do the mapping in the existing
620                  * high areas */
621                 addr = htlb_get_high_area(len, curareas);
622                 if (addr != -ENOMEM)
623                         return addr;
624
625                 lastshift = 0;
626                 for (areamask = HTLB_AREA_MASK(TASK_SIZE_USER64-len, len);
627                      ! lastshift; areamask >>=1) {
628                         if (areamask & 1)
629                                 lastshift = 1;
630
631                         addr = htlb_get_high_area(len, curareas | areamask);
632                         if ((addr != -ENOMEM)
633                             && open_high_hpage_areas(current->mm, areamask) == 0)
634                                 return addr;
635                 }
636         }
637         printk(KERN_DEBUG "hugetlb_get_unmapped_area() unable to open"
638                " enough areas\n");
639         return -ENOMEM;
640 }
641
642 /*
643  * Called by asm hashtable.S for doing lazy icache flush
644  */
645 static unsigned int hash_huge_page_do_lazy_icache(unsigned long rflags,
646                                                   pte_t pte, int trap)
647 {
648         struct page *page;
649         int i;
650
651         if (!pfn_valid(pte_pfn(pte)))
652                 return rflags;
653
654         page = pte_page(pte);
655
656         /* page is dirty */
657         if (!test_bit(PG_arch_1, &page->flags) && !PageReserved(page)) {
658                 if (trap == 0x400) {
659                         for (i = 0; i < (HPAGE_SIZE / PAGE_SIZE); i++)
660                                 __flush_dcache_icache(page_address(page+i));
661                         set_bit(PG_arch_1, &page->flags);
662                 } else {
663                         rflags |= HPTE_R_N;
664                 }
665         }
666         return rflags;
667 }
668
669 int hash_huge_page(struct mm_struct *mm, unsigned long access,
670                    unsigned long ea, unsigned long vsid, int local,
671                    unsigned long trap)
672 {
673         pte_t *ptep;
674         unsigned long old_pte, new_pte;
675         unsigned long va, rflags, pa;
676         long slot;
677         int err = 1;
678
679         ptep = huge_pte_offset(mm, ea);
680
681         /* Search the Linux page table for a match with va */
682         va = (vsid << 28) | (ea & 0x0fffffff);
683
684         /*
685          * If no pte found or not present, send the problem up to
686          * do_page_fault
687          */
688         if (unlikely(!ptep || pte_none(*ptep)))
689                 goto out;
690
691         /* 
692          * Check the user's access rights to the page.  If access should be
693          * prevented then send the problem up to do_page_fault.
694          */
695         if (unlikely(access & ~pte_val(*ptep)))
696                 goto out;
697         /*
698          * At this point, we have a pte (old_pte) which can be used to build
699          * or update an HPTE. There are 2 cases:
700          *
701          * 1. There is a valid (present) pte with no associated HPTE (this is 
702          *      the most common case)
703          * 2. There is a valid (present) pte with an associated HPTE. The
704          *      current values of the pp bits in the HPTE prevent access
705          *      because we are doing software DIRTY bit management and the
706          *      page is currently not DIRTY. 
707          */
708
709
710         do {
711                 old_pte = pte_val(*ptep);
712                 if (old_pte & _PAGE_BUSY)
713                         goto out;
714                 new_pte = old_pte | _PAGE_BUSY |
715                         _PAGE_ACCESSED | _PAGE_HASHPTE;
716         } while(old_pte != __cmpxchg_u64((unsigned long *)ptep,
717                                          old_pte, new_pte));
718
719         rflags = 0x2 | (!(new_pte & _PAGE_RW));
720         /* _PAGE_EXEC -> HW_NO_EXEC since it's inverted */
721         rflags |= ((new_pte & _PAGE_EXEC) ? 0 : HPTE_R_N);
722         if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
723                 /* No CPU has hugepages but lacks no execute, so we
724                  * don't need to worry about that case */
725                 rflags = hash_huge_page_do_lazy_icache(rflags, __pte(old_pte),
726                                                        trap);
727
728         /* Check if pte already has an hpte (case 2) */
729         if (unlikely(old_pte & _PAGE_HASHPTE)) {
730                 /* There MIGHT be an HPTE for this pte */
731                 unsigned long hash, slot;
732
733                 hash = hpt_hash(va, HPAGE_SHIFT);
734                 if (old_pte & _PAGE_F_SECOND)
735                         hash = ~hash;
736                 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
737                 slot += (old_pte & _PAGE_F_GIX) >> 12;
738
739                 if (ppc_md.hpte_updatepp(slot, rflags, va, mmu_huge_psize,
740                                          local) == -1)
741                         old_pte &= ~_PAGE_HPTEFLAGS;
742         }
743
744         if (likely(!(old_pte & _PAGE_HASHPTE))) {
745                 unsigned long hash = hpt_hash(va, HPAGE_SHIFT);
746                 unsigned long hpte_group;
747
748                 pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT;
749
750 repeat:
751                 hpte_group = ((hash & htab_hash_mask) *
752                               HPTES_PER_GROUP) & ~0x7UL;
753
754                 /* clear HPTE slot informations in new PTE */
755                 new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE;
756
757                 /* Add in WIMG bits */
758                 /* XXX We should store these in the pte */
759                 /* --BenH: I think they are ... */
760                 rflags |= _PAGE_COHERENT;
761
762                 /* Insert into the hash table, primary slot */
763                 slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, 0,
764                                           mmu_huge_psize);
765
766                 /* Primary is full, try the secondary */
767                 if (unlikely(slot == -1)) {
768                         new_pte |= _PAGE_F_SECOND;
769                         hpte_group = ((~hash & htab_hash_mask) *
770                                       HPTES_PER_GROUP) & ~0x7UL; 
771                         slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags,
772                                                   HPTE_V_SECONDARY,
773                                                   mmu_huge_psize);
774                         if (slot == -1) {
775                                 if (mftb() & 0x1)
776                                         hpte_group = ((hash & htab_hash_mask) *
777                                                       HPTES_PER_GROUP)&~0x7UL;
778
779                                 ppc_md.hpte_remove(hpte_group);
780                                 goto repeat;
781                         }
782                 }
783
784                 if (unlikely(slot == -2))
785                         panic("hash_huge_page: pte_insert failed\n");
786
787                 new_pte |= (slot << 12) & _PAGE_F_GIX;
788         }
789
790         /*
791          * No need to use ldarx/stdcx here
792          */
793         *ptep = __pte(new_pte & ~_PAGE_BUSY);
794
795         err = 0;
796
797  out:
798         return err;
799 }