]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/powerpc/aim/isa3_hashtb.c
powerpc: Scale intrcnt by mp_ncpus
[FreeBSD/FreeBSD.git] / sys / powerpc / aim / isa3_hashtb.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND 4-Clause-BSD
3  *
4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Matt Thomas <matt@3am-software.com> of Allegro Networks, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 /*-
32  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
33  * Copyright (C) 1995, 1996 TooLs GmbH.
34  * All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  * 1. Redistributions of source code must retain the above copyright
40  *    notice, this list of conditions and the following disclaimer.
41  * 2. Redistributions in binary form must reproduce the above copyright
42  *    notice, this list of conditions and the following disclaimer in the
43  *    documentation and/or other materials provided with the distribution.
44  * 3. All advertising materials mentioning features or use of this software
45  *    must display the following acknowledgement:
46  *      This product includes software developed by TooLs GmbH.
47  * 4. The name of TooLs GmbH may not be used to endorse or promote products
48  *    derived from this software without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
51  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
52  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
53  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
55  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
56  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
57  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
58  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
59  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60  *
61  * $NetBSD: pmap.c,v 1.28 2000/03/26 20:42:36 kleink Exp $
62  */
63 /*-
64  * Copyright (C) 2001 Benno Rice.
65  * All rights reserved.
66  *
67  * Redistribution and use in source and binary forms, with or without
68  * modification, are permitted provided that the following conditions
69  * are met:
70  * 1. Redistributions of source code must retain the above copyright
71  *    notice, this list of conditions and the following disclaimer.
72  * 2. Redistributions in binary form must reproduce the above copyright
73  *    notice, this list of conditions and the following disclaimer in the
74  *    documentation and/or other materials provided with the distribution.
75  *
76  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
77  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
78  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
79  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
80  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
81  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
82  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
83  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
84  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
85  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
86  */
87
88 #include <sys/cdefs.h>
89 __FBSDID("$FreeBSD$");
90
91 /*
92  * Native 64-bit page table operations for running without a hypervisor.
93  */
94
95 #include <sys/param.h>
96 #include <sys/kernel.h>
97 #include <sys/ktr.h>
98 #include <sys/lock.h>
99 #include <sys/mutex.h>
100 #include <sys/proc.h>
101 #include <sys/sched.h>
102 #include <sys/sysctl.h>
103 #include <sys/systm.h>
104 #include <sys/rwlock.h>
105 #include <sys/endian.h>
106
107 #include <sys/kdb.h>
108
109 #include <vm/vm.h>
110 #include <vm/vm_param.h>
111 #include <vm/vm_kern.h>
112 #include <vm/vm_page.h>
113 #include <vm/vm_map.h>
114 #include <vm/vm_object.h>
115 #include <vm/vm_extern.h>
116 #include <vm/vm_pageout.h>
117
118 #include <machine/cpu.h>
119 #include <machine/hid.h>
120 #include <machine/md_var.h>
121 #include <machine/mmuvar.h>
122
123 #include "mmu_oea64.h"
124 #include "mmu_if.h"
125 #include "moea64_if.h"
126
127 #define PTESYNC()       __asm __volatile("ptesync");
128 #define TLBSYNC()       __asm __volatile("tlbsync; ptesync");
129 #define SYNC()          __asm __volatile("sync");
130 #define EIEIO()         __asm __volatile("eieio");
131
132 #define VSID_HASH_MASK  0x0000007fffffffffULL
133
134 /* POWER9 only permits a 64k partition table size. */
135 #define PART_SIZE       0x10000
136
137 static __inline void
138 TLBIE(uint64_t vpn)
139 {
140         vpn <<= ADDR_PIDX_SHFT;
141
142         __asm __volatile("tlbie %0" :: "r"(vpn) : "memory");
143         __asm __volatile("eieio; tlbsync; ptesync" ::: "memory");
144 }
145
146 #define DISABLE_TRANS(msr)      msr = mfmsr(); mtmsr(msr & ~PSL_DR)
147 #define ENABLE_TRANS(msr)       mtmsr(msr)
148
149 /*
150  * PTEG data.
151  */
152 static volatile struct pate *isa3_part_table;
153 static volatile struct lpte *isa3_hashtb_pteg_table;
154 static struct rwlock isa3_hashtb_eviction_lock;
155
156 /*
157  * PTE calls.
158  */
159 static int      isa3_hashtb_pte_insert(mmu_t, struct pvo_entry *);
160 static int64_t  isa3_hashtb_pte_synch(mmu_t, struct pvo_entry *);
161 static int64_t  isa3_hashtb_pte_clear(mmu_t, struct pvo_entry *, uint64_t);
162 static int64_t  isa3_hashtb_pte_replace(mmu_t, struct pvo_entry *, int);
163 static int64_t  isa3_hashtb_pte_unset(mmu_t mmu, struct pvo_entry *);
164
165 /*
166  * Utility routines.
167  */
168 static void     isa3_hashtb_bootstrap(mmu_t mmup, 
169                     vm_offset_t kernelstart, vm_offset_t kernelend);
170 static void     isa3_hashtb_cpu_bootstrap(mmu_t, int ap);
171 static void     tlbia(void);
172
173 static mmu_method_t isa3_hashtb_methods[] = {
174         /* Internal interfaces */
175         MMUMETHOD(mmu_bootstrap,        isa3_hashtb_bootstrap),
176         MMUMETHOD(mmu_cpu_bootstrap,    isa3_hashtb_cpu_bootstrap),
177
178         MMUMETHOD(moea64_pte_synch,     isa3_hashtb_pte_synch),
179         MMUMETHOD(moea64_pte_clear,     isa3_hashtb_pte_clear), 
180         MMUMETHOD(moea64_pte_unset,     isa3_hashtb_pte_unset), 
181         MMUMETHOD(moea64_pte_replace,   isa3_hashtb_pte_replace),       
182         MMUMETHOD(moea64_pte_insert,    isa3_hashtb_pte_insert),        
183
184         { 0, 0 }
185 };
186
187 MMU_DEF_INHERIT(isa3_mmu_native, MMU_TYPE_P9H, isa3_hashtb_methods,
188     0, oea64_mmu);
189
190 static int64_t
191 isa3_hashtb_pte_synch(mmu_t mmu, struct pvo_entry *pvo)
192 {
193         volatile struct lpte *pt = isa3_hashtb_pteg_table + pvo->pvo_pte.slot;
194         struct lpte properpt;
195         uint64_t ptelo;
196
197         PMAP_LOCK_ASSERT(pvo->pvo_pmap, MA_OWNED);
198
199         moea64_pte_from_pvo(pvo, &properpt);
200
201         rw_rlock(&isa3_hashtb_eviction_lock);
202         if ((be64toh(pt->pte_hi) & LPTE_AVPN_MASK) !=
203             (properpt.pte_hi & LPTE_AVPN_MASK)) {
204                 /* Evicted */
205                 rw_runlock(&isa3_hashtb_eviction_lock);
206                 return (-1);
207         }
208                 
209         PTESYNC();
210         ptelo = be64toh(pt->pte_lo);
211
212         rw_runlock(&isa3_hashtb_eviction_lock);
213         
214         return (ptelo & (LPTE_REF | LPTE_CHG));
215 }
216
217 static int64_t 
218 isa3_hashtb_pte_clear(mmu_t mmu, struct pvo_entry *pvo, uint64_t ptebit)
219 {
220         volatile struct lpte *pt = isa3_hashtb_pteg_table + pvo->pvo_pte.slot;
221         struct lpte properpt;
222         uint64_t ptelo;
223
224         PMAP_LOCK_ASSERT(pvo->pvo_pmap, MA_OWNED);
225
226         moea64_pte_from_pvo(pvo, &properpt);
227
228         rw_rlock(&isa3_hashtb_eviction_lock);
229         if ((be64toh(pt->pte_hi) & LPTE_AVPN_MASK) !=
230             (properpt.pte_hi & LPTE_AVPN_MASK)) {
231                 /* Evicted */
232                 rw_runlock(&isa3_hashtb_eviction_lock);
233                 return (-1);
234         }
235
236         if (ptebit == LPTE_REF) {
237                 /* See "Resetting the Reference Bit" in arch manual */
238                 PTESYNC();
239                 /* 2-step here safe: precision is not guaranteed */
240                 ptelo = be64toh(pt->pte_lo);
241
242                 /* One-byte store to avoid touching the C bit */
243                 ((volatile uint8_t *)(&pt->pte_lo))[6] =
244 #if BYTE_ORDER == BIG_ENDIAN
245                     ((uint8_t *)(&properpt.pte_lo))[6];
246 #else
247                     ((uint8_t *)(&properpt.pte_lo))[1];
248 #endif
249                 rw_runlock(&isa3_hashtb_eviction_lock);
250
251                 critical_enter();
252                 TLBIE(pvo->pvo_vpn);
253                 critical_exit();
254         } else {
255                 rw_runlock(&isa3_hashtb_eviction_lock);
256                 ptelo = isa3_hashtb_pte_unset(mmu, pvo);
257                 isa3_hashtb_pte_insert(mmu, pvo);
258         }
259
260         return (ptelo & (LPTE_REF | LPTE_CHG));
261 }
262
263 static int64_t
264 isa3_hashtb_pte_unset(mmu_t mmu, struct pvo_entry *pvo)
265 {
266         volatile struct lpte *pt = isa3_hashtb_pteg_table + pvo->pvo_pte.slot;
267         struct lpte properpt;
268         uint64_t ptelo;
269
270         moea64_pte_from_pvo(pvo, &properpt);
271
272         rw_rlock(&isa3_hashtb_eviction_lock);
273         if ((be64toh(pt->pte_hi & LPTE_AVPN_MASK)) !=
274             (properpt.pte_hi & LPTE_AVPN_MASK)) {
275                 /* Evicted */
276                 moea64_pte_overflow--;
277                 rw_runlock(&isa3_hashtb_eviction_lock);
278                 return (-1);
279         }
280
281         /*
282          * Invalidate the pte, briefly locking it to collect RC bits. No
283          * atomics needed since this is protected against eviction by the lock.
284          */
285         isync();
286         critical_enter();
287         pt->pte_hi = be64toh((pt->pte_hi & ~LPTE_VALID) | LPTE_LOCKED);
288         PTESYNC();
289         TLBIE(pvo->pvo_vpn);
290         ptelo = be64toh(pt->pte_lo);
291         *((volatile int32_t *)(&pt->pte_hi) + 1) = 0; /* Release lock */
292         critical_exit();
293         rw_runlock(&isa3_hashtb_eviction_lock);
294
295         /* Keep statistics */
296         moea64_pte_valid--;
297
298         return (ptelo & (LPTE_CHG | LPTE_REF));
299 }
300
301 static int64_t
302 isa3_hashtb_pte_replace(mmu_t mmu, struct pvo_entry *pvo, int flags)
303 {
304         volatile struct lpte *pt = isa3_hashtb_pteg_table + pvo->pvo_pte.slot;
305         struct lpte properpt;
306         int64_t ptelo;
307
308         if (flags == 0) {
309                 /* Just some software bits changing. */
310                 moea64_pte_from_pvo(pvo, &properpt);
311
312                 rw_rlock(&isa3_hashtb_eviction_lock);
313                 if ((be64toh(pt->pte_hi) & LPTE_AVPN_MASK) !=
314                     (properpt.pte_hi & LPTE_AVPN_MASK)) {
315                         rw_runlock(&isa3_hashtb_eviction_lock);
316                         return (-1);
317                 }
318                 pt->pte_hi = htobe64(properpt.pte_hi);
319                 ptelo = be64toh(pt->pte_lo);
320                 rw_runlock(&isa3_hashtb_eviction_lock);
321         } else {
322                 /* Otherwise, need reinsertion and deletion */
323                 ptelo = isa3_hashtb_pte_unset(mmu, pvo);
324                 isa3_hashtb_pte_insert(mmu, pvo);
325         }
326
327         return (ptelo);
328 }
329
330 static void
331 isa3_hashtb_cpu_bootstrap(mmu_t mmup, int ap)
332 {
333         int i = 0;
334         struct slb *slb = PCPU_GET(aim.slb);
335         register_t seg0;
336
337         /*
338          * Initialize segment registers and MMU
339          */
340
341         mtmsr(mfmsr() & ~PSL_DR & ~PSL_IR);
342
343         switch (mfpvr() >> 16) {
344         case IBMPOWER9:
345                 mtspr(SPR_HID0, mfspr(SPR_HID0) & ~HID0_RADIX);
346                 break;
347         }
348
349         /*
350          * Install kernel SLB entries
351          */
352
353         __asm __volatile ("slbia");
354         __asm __volatile ("slbmfee %0,%1; slbie %0;" : "=r"(seg0) :
355             "r"(0));
356
357         for (i = 0; i < n_slbs; i++) {
358                 if (!(slb[i].slbe & SLBE_VALID))
359                         continue;
360
361                 __asm __volatile ("slbmte %0, %1" :: 
362                     "r"(slb[i].slbv), "r"(slb[i].slbe)); 
363         }
364
365         /*
366          * Install page table
367          */
368
369         mtspr(SPR_PTCR,
370             ((uintptr_t)isa3_part_table & ~DMAP_BASE_ADDRESS) |
371              flsl((PART_SIZE >> 12) - 1));
372         tlbia();
373 }
374
375 static void
376 isa3_hashtb_bootstrap(mmu_t mmup, vm_offset_t kernelstart,
377     vm_offset_t kernelend)
378 {
379         vm_size_t       size;
380         vm_offset_t     off;
381         vm_paddr_t      pa;
382         register_t      msr;
383
384         moea64_early_bootstrap(mmup, kernelstart, kernelend);
385
386         /*
387          * Allocate PTEG table.
388          */
389
390         size = moea64_pteg_count * sizeof(struct lpteg);
391         CTR2(KTR_PMAP, "moea64_bootstrap: %d PTEGs, %lu bytes", 
392             moea64_pteg_count, size);
393         rw_init(&isa3_hashtb_eviction_lock, "pte eviction");
394
395         /*
396          * We now need to allocate memory. This memory, to be allocated,
397          * has to reside in a page table. The page table we are about to
398          * allocate. We don't have BAT. So drop to data real mode for a minute
399          * as a measure of last resort. We do this a couple times.
400          */
401
402         isa3_part_table =
403             (struct pate *)moea64_bootstrap_alloc(PART_SIZE, PART_SIZE);
404         if (hw_direct_map)
405                 isa3_part_table = (struct pate *)PHYS_TO_DMAP(
406                     (vm_offset_t)isa3_part_table);
407         /*
408          * PTEG table must be aligned on a 256k boundary, but can be placed
409          * anywhere with that alignment on POWER ISA 3+ systems.
410          */
411         isa3_hashtb_pteg_table = (struct lpte *)moea64_bootstrap_alloc(size, 
412             MAX(256*1024, size));
413         if (hw_direct_map)
414                 isa3_hashtb_pteg_table =
415                     (struct lpte *)PHYS_TO_DMAP((vm_offset_t)isa3_hashtb_pteg_table);
416         DISABLE_TRANS(msr);
417         bzero(__DEVOLATILE(void *, isa3_part_table), PART_SIZE);
418         isa3_part_table[0].pagetab =
419             ((uintptr_t)isa3_hashtb_pteg_table & ~DMAP_BASE_ADDRESS) |
420             (uintptr_t)(flsl((moea64_pteg_count - 1) >> 11));
421         bzero(__DEVOLATILE(void *, isa3_hashtb_pteg_table), moea64_pteg_count *
422             sizeof(struct lpteg));
423         ENABLE_TRANS(msr);
424
425         CTR1(KTR_PMAP, "moea64_bootstrap: PTEG table at %p", isa3_hashtb_pteg_table);
426
427         moea64_mid_bootstrap(mmup, kernelstart, kernelend);
428
429         /*
430          * Add a mapping for the page table itself if there is no direct map.
431          */
432         if (!hw_direct_map) {
433                 size = moea64_pteg_count * sizeof(struct lpteg);
434                 off = (vm_offset_t)(isa3_hashtb_pteg_table);
435                 DISABLE_TRANS(msr);
436                 for (pa = off; pa < off + size; pa += PAGE_SIZE)
437                         pmap_kenter(pa, pa);
438                 ENABLE_TRANS(msr);
439         }
440
441         /* Bring up virtual memory */
442         moea64_late_bootstrap(mmup, kernelstart, kernelend);
443 }
444
445 static void
446 tlbia(void)
447 {
448         vm_offset_t i;
449
450         i = 0xc00; /* IS = 11 */
451
452         TLBSYNC();
453
454         for (; i < 0x200000; i += 0x00001000) {
455                 __asm __volatile("tlbiel %0" :: "r"(i));
456         }
457
458         EIEIO();
459         TLBSYNC();
460 }
461
462 static int
463 atomic_pte_lock(volatile struct lpte *pte, uint64_t bitmask, uint64_t *oldhi)
464 {
465         int     ret;
466         uint32_t oldhihalf;
467
468         /*
469          * Note: in principle, if just the locked bit were set here, we
470          * could avoid needing the eviction lock. However, eviction occurs
471          * so rarely that it isn't worth bothering about in practice.
472          */
473
474         __asm __volatile (
475                 "1:\tlwarx %1, 0, %3\n\t"       /* load old value */
476                 "and. %0,%1,%4\n\t"             /* check if any bits set */
477                 "bne 2f\n\t"                    /* exit if any set */
478                 "stwcx. %5, 0, %3\n\t"          /* attempt to store */
479                 "bne- 1b\n\t"                   /* spin if failed */
480                 "li %0, 1\n\t"                  /* success - retval = 1 */
481                 "b 3f\n\t"                      /* we've succeeded */
482                 "2:\n\t"
483                 "stwcx. %1, 0, %3\n\t"          /* clear reservation (74xx) */
484                 "li %0, 0\n\t"                  /* failure - retval = 0 */
485                 "3:\n\t"
486                 : "=&r" (ret), "=&r"(oldhihalf), "=m" (pte->pte_hi)
487                 : "r" ((volatile char *)&pte->pte_hi + 4),
488                   "r" ((uint32_t)bitmask), "r" ((uint32_t)LPTE_LOCKED),
489                   "m" (pte->pte_hi)
490                 : "cr0", "cr1", "cr2", "memory");
491
492         *oldhi = (pte->pte_hi & 0xffffffff00000000ULL) | oldhihalf;
493
494         return (ret);
495 }
496
497 static uintptr_t
498 isa3_hashtb_insert_to_pteg(struct lpte *pvo_pt, uintptr_t slotbase,
499     uint64_t mask)
500 {
501         volatile struct lpte *pt;
502         uint64_t oldptehi, va;
503         uintptr_t k;
504         int i, j;
505
506         /* Start at a random slot */
507         i = mftb() % 8;
508         for (j = 0; j < 8; j++) {
509                 k = slotbase + (i + j) % 8;
510                 pt = &isa3_hashtb_pteg_table[k];
511                 /* Invalidate and seize lock only if no bits in mask set */
512                 if (atomic_pte_lock(pt, mask, &oldptehi)) /* Lock obtained */
513                         break;
514         }
515
516         if (j == 8)
517                 return (-1);
518
519         if (oldptehi & LPTE_VALID) {
520                 KASSERT(!(oldptehi & LPTE_WIRED), ("Unmapped wired entry"));
521                 /*
522                  * Need to invalidate old entry completely: see
523                  * "Modifying a Page Table Entry". Need to reconstruct
524                  * the virtual address for the outgoing entry to do that.
525                  */
526                 if (oldptehi & LPTE_BIG)
527                         va = oldptehi >> moea64_large_page_shift;
528                 else
529                         va = oldptehi >> ADDR_PIDX_SHFT;
530                 if (oldptehi & LPTE_HID)
531                         va = (((k >> 3) ^ moea64_pteg_mask) ^ va) &
532                             VSID_HASH_MASK;
533                 else
534                         va = ((k >> 3) ^ va) & VSID_HASH_MASK;
535                 va |= (oldptehi & LPTE_AVPN_MASK) <<
536                     (ADDR_API_SHFT64 - ADDR_PIDX_SHFT);
537                 PTESYNC();
538                 TLBIE(va);
539                 moea64_pte_valid--;
540                 moea64_pte_overflow++;
541         }
542
543         /*
544          * Update the PTE as per "Adding a Page Table Entry". Lock is released
545          * by setting the high doubleworld.
546          */
547         pt->pte_lo = htobe64(pvo_pt->pte_lo);
548         EIEIO();
549         pt->pte_hi = htobe64(pvo_pt->pte_hi);
550         PTESYNC();
551
552         /* Keep statistics */
553         moea64_pte_valid++;
554
555         return (k);
556 }
557
558 static int
559 isa3_hashtb_pte_insert(mmu_t mmu, struct pvo_entry *pvo)
560 {
561         struct lpte insertpt;
562         uintptr_t slot;
563
564         /* Initialize PTE */
565         moea64_pte_from_pvo(pvo, &insertpt);
566
567         /* Make sure further insertion is locked out during evictions */
568         rw_rlock(&isa3_hashtb_eviction_lock);
569
570         /*
571          * First try primary hash.
572          */
573         pvo->pvo_pte.slot &= ~7ULL; /* Base slot address */
574         slot = isa3_hashtb_insert_to_pteg(&insertpt, pvo->pvo_pte.slot,
575             LPTE_VALID | LPTE_WIRED | LPTE_LOCKED);
576         if (slot != -1) {
577                 rw_runlock(&isa3_hashtb_eviction_lock);
578                 pvo->pvo_pte.slot = slot;
579                 return (0);
580         }
581
582         /*
583          * Now try secondary hash.
584          */
585         pvo->pvo_vaddr ^= PVO_HID;
586         insertpt.pte_hi ^= LPTE_HID;
587         pvo->pvo_pte.slot ^= (moea64_pteg_mask << 3);
588         slot = isa3_hashtb_insert_to_pteg(&insertpt, pvo->pvo_pte.slot,
589             LPTE_VALID | LPTE_WIRED | LPTE_LOCKED);
590         if (slot != -1) {
591                 rw_runlock(&isa3_hashtb_eviction_lock);
592                 pvo->pvo_pte.slot = slot;
593                 return (0);
594         }
595
596         /*
597          * Out of luck. Find a PTE to sacrifice.
598          */
599
600         /* Lock out all insertions for a bit */
601         if (!rw_try_upgrade(&isa3_hashtb_eviction_lock)) {
602                 rw_runlock(&isa3_hashtb_eviction_lock);
603                 rw_wlock(&isa3_hashtb_eviction_lock);
604         }
605
606         slot = isa3_hashtb_insert_to_pteg(&insertpt, pvo->pvo_pte.slot,
607             LPTE_WIRED | LPTE_LOCKED);
608         if (slot != -1) {
609                 rw_wunlock(&isa3_hashtb_eviction_lock);
610                 pvo->pvo_pte.slot = slot;
611                 return (0);
612         }
613
614         /* Try other hash table. Now we're getting desperate... */
615         pvo->pvo_vaddr ^= PVO_HID;
616         insertpt.pte_hi ^= LPTE_HID;
617         pvo->pvo_pte.slot ^= (moea64_pteg_mask << 3);
618         slot = isa3_hashtb_insert_to_pteg(&insertpt, pvo->pvo_pte.slot,
619             LPTE_WIRED | LPTE_LOCKED);
620         if (slot != -1) {
621                 rw_wunlock(&isa3_hashtb_eviction_lock);
622                 pvo->pvo_pte.slot = slot;
623                 return (0);
624         }
625
626         /* No freeable slots in either PTEG? We're hosed. */
627         rw_wunlock(&isa3_hashtb_eviction_lock);
628         panic("moea64_pte_insert: overflow");
629         return (-1);
630 }
631