]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/powerpc/aim/aim_machdep.c
Install the SLB miss trap-handling code in the SLB-based MMU driver set up,
[FreeBSD/FreeBSD.git] / sys / powerpc / aim / aim_machdep.c
1 /*-
2  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
3  * Copyright (C) 1995, 1996 TooLs GmbH.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by TooLs GmbH.
17  * 4. The name of TooLs GmbH may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 /*-
32  * Copyright (C) 2001 Benno Rice
33  * All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  * 2. Redistributions in binary form must reproduce the above copyright
41  *    notice, this list of conditions and the following disclaimer in the
42  *    documentation and/or other materials provided with the distribution.
43  *
44  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
45  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
49  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
50  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
52  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
53  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54  *      $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $
55  */
56
57 #include <sys/cdefs.h>
58 __FBSDID("$FreeBSD$");
59
60 #include "opt_compat.h"
61 #include "opt_ddb.h"
62 #include "opt_kstack_pages.h"
63 #include "opt_platform.h"
64
65 #include <sys/param.h>
66 #include <sys/proc.h>
67 #include <sys/systm.h>
68 #include <sys/bio.h>
69 #include <sys/buf.h>
70 #include <sys/bus.h>
71 #include <sys/cons.h>
72 #include <sys/cpu.h>
73 #include <sys/eventhandler.h>
74 #include <sys/exec.h>
75 #include <sys/imgact.h>
76 #include <sys/kdb.h>
77 #include <sys/kernel.h>
78 #include <sys/ktr.h>
79 #include <sys/linker.h>
80 #include <sys/lock.h>
81 #include <sys/malloc.h>
82 #include <sys/mbuf.h>
83 #include <sys/msgbuf.h>
84 #include <sys/mutex.h>
85 #include <sys/ptrace.h>
86 #include <sys/reboot.h>
87 #include <sys/rwlock.h>
88 #include <sys/signalvar.h>
89 #include <sys/syscallsubr.h>
90 #include <sys/sysctl.h>
91 #include <sys/sysent.h>
92 #include <sys/sysproto.h>
93 #include <sys/ucontext.h>
94 #include <sys/uio.h>
95 #include <sys/vmmeter.h>
96 #include <sys/vnode.h>
97
98 #include <net/netisr.h>
99
100 #include <vm/vm.h>
101 #include <vm/vm_extern.h>
102 #include <vm/vm_kern.h>
103 #include <vm/vm_page.h>
104 #include <vm/vm_map.h>
105 #include <vm/vm_object.h>
106 #include <vm/vm_pager.h>
107
108 #include <machine/altivec.h>
109 #ifndef __powerpc64__
110 #include <machine/bat.h>
111 #endif
112 #include <machine/cpu.h>
113 #include <machine/elf.h>
114 #include <machine/fpu.h>
115 #include <machine/hid.h>
116 #include <machine/kdb.h>
117 #include <machine/md_var.h>
118 #include <machine/metadata.h>
119 #include <machine/mmuvar.h>
120 #include <machine/pcb.h>
121 #include <machine/reg.h>
122 #include <machine/sigframe.h>
123 #include <machine/spr.h>
124 #include <machine/trap.h>
125 #include <machine/vmparam.h>
126 #include <machine/ofw_machdep.h>
127
128 #include <ddb/ddb.h>
129
130 #include <dev/ofw/openfirm.h>
131
132 #ifdef __powerpc64__
133 #include "mmu_oea64.h"
134 #endif
135
136 #ifndef __powerpc64__
137 struct bat      battable[16];
138 #endif
139
140 #ifndef __powerpc64__
141 /* Bits for running on 64-bit systems in 32-bit mode. */
142 extern void     *testppc64, *testppc64size;
143 extern void     *restorebridge, *restorebridgesize;
144 extern void     *rfid_patch, *rfi_patch1, *rfi_patch2;
145 extern void     *trapcode64;
146
147 extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
148 #endif
149
150 extern void     *rstcode, *rstcodeend;
151 extern void     *trapcode, *trapcodeend;
152 extern void     *generictrap, *generictrap64;
153 extern void     *alitrap, *aliend;
154 extern void     *dsitrap, *dsiend;
155 extern void     *decrint, *decrsize;
156 extern void     *extint, *extsize;
157 extern void     *dblow, *dbend;
158 extern void     *imisstrap, *imisssize;
159 extern void     *dlmisstrap, *dlmisssize;
160 extern void     *dsmisstrap, *dsmisssize;
161
162 extern void *ap_pcpu;
163
164 void aim_cpu_init(vm_offset_t toc);
165
166 void
167 aim_cpu_init(vm_offset_t toc)
168 {
169         size_t          trap_offset, trapsize;
170         vm_offset_t     trap;
171         register_t      msr, scratch;
172         uint8_t         *cache_check;
173         int             cacheline_warn;
174         #ifndef __powerpc64__
175         int             ppc64;
176         #endif
177
178         trap_offset = 0;
179         cacheline_warn = 0;
180
181         /* Various very early CPU fix ups */
182         switch (mfpvr() >> 16) {
183                 /*
184                  * PowerPC 970 CPUs have a misfeature requested by Apple that
185                  * makes them pretend they have a 32-byte cacheline. Turn this
186                  * off before we measure the cacheline size.
187                  */
188                 case IBM970:
189                 case IBM970FX:
190                 case IBM970MP:
191                 case IBM970GX:
192                         scratch = mfspr(SPR_HID5);
193                         scratch &= ~HID5_970_DCBZ_SIZE_HI;
194                         mtspr(SPR_HID5, scratch);
195                         break;
196         #ifdef __powerpc64__
197                 case IBMPOWER7:
198                 case IBMPOWER7PLUS:
199                 case IBMPOWER8:
200                 case IBMPOWER8E:
201                         /* XXX: get from ibm,slb-size in device tree */
202                         n_slbs = 32;
203                         break;
204         #endif
205         }
206
207         /*
208          * Initialize the interrupt tables and figure out our cache line
209          * size and whether or not we need the 64-bit bridge code.
210          */
211
212         /*
213          * Disable translation in case the vector area hasn't been
214          * mapped (G5). Note that no OFW calls can be made until
215          * translation is re-enabled.
216          */
217
218         msr = mfmsr();
219         mtmsr((msr & ~(PSL_IR | PSL_DR)) | PSL_RI);
220
221         /*
222          * Measure the cacheline size using dcbz
223          *
224          * Use EXC_PGM as a playground. We are about to overwrite it
225          * anyway, we know it exists, and we know it is cache-aligned.
226          */
227
228         cache_check = (void *)EXC_PGM;
229
230         for (cacheline_size = 0; cacheline_size < 0x100; cacheline_size++)
231                 cache_check[cacheline_size] = 0xff;
232
233         __asm __volatile("dcbz 0,%0":: "r" (cache_check) : "memory");
234
235         /* Find the first byte dcbz did not zero to get the cache line size */
236         for (cacheline_size = 0; cacheline_size < 0x100 &&
237             cache_check[cacheline_size] == 0; cacheline_size++);
238
239         /* Work around psim bug */
240         if (cacheline_size == 0) {
241                 cacheline_warn = 1;
242                 cacheline_size = 32;
243         }
244
245         #ifndef __powerpc64__
246         /*
247          * Figure out whether we need to use the 64 bit PMAP. This works by
248          * executing an instruction that is only legal on 64-bit PPC (mtmsrd),
249          * and setting ppc64 = 0 if that causes a trap.
250          */
251
252         ppc64 = 1;
253
254         bcopy(&testppc64, (void *)EXC_PGM,  (size_t)&testppc64size);
255         __syncicache((void *)EXC_PGM, (size_t)&testppc64size);
256
257         __asm __volatile("\
258                 mfmsr %0;       \
259                 mtsprg2 %1;     \
260                                 \
261                 mtmsrd %0;      \
262                 mfsprg2 %1;"
263             : "=r"(scratch), "=r"(ppc64));
264
265         if (ppc64)
266                 cpu_features |= PPC_FEATURE_64;
267
268         /*
269          * Now copy restorebridge into all the handlers, if necessary,
270          * and set up the trap tables.
271          */
272
273         if (cpu_features & PPC_FEATURE_64) {
274                 /* Patch the two instances of rfi -> rfid */
275                 bcopy(&rfid_patch,&rfi_patch1,4);
276         #ifdef KDB
277                 /* rfi_patch2 is at the end of dbleave */
278                 bcopy(&rfid_patch,&rfi_patch2,4);
279         #endif
280         }
281         #else /* powerpc64 */
282         cpu_features |= PPC_FEATURE_64;
283         #endif
284
285         trapsize = (size_t)&trapcodeend - (size_t)&trapcode;
286
287         /*
288          * Copy generic handler into every possible trap. Special cases will get
289          * different ones in a minute.
290          */
291         for (trap = EXC_RST; trap < EXC_LAST; trap += 0x20)
292                 bcopy(&trapcode, (void *)trap, trapsize);
293
294         #ifndef __powerpc64__
295         if (cpu_features & PPC_FEATURE_64) {
296                 /*
297                  * Copy a code snippet to restore 32-bit bridge mode
298                  * to the top of every non-generic trap handler
299                  */
300
301                 trap_offset += (size_t)&restorebridgesize;
302                 bcopy(&restorebridge, (void *)EXC_RST, trap_offset);
303                 bcopy(&restorebridge, (void *)EXC_DSI, trap_offset);
304                 bcopy(&restorebridge, (void *)EXC_ALI, trap_offset);
305                 bcopy(&restorebridge, (void *)EXC_PGM, trap_offset);
306                 bcopy(&restorebridge, (void *)EXC_MCHK, trap_offset);
307                 bcopy(&restorebridge, (void *)EXC_TRC, trap_offset);
308                 bcopy(&restorebridge, (void *)EXC_BPT, trap_offset);
309         }
310         #endif
311
312         bcopy(&rstcode, (void *)(EXC_RST + trap_offset), (size_t)&rstcodeend -
313             (size_t)&rstcode);
314
315 #ifdef KDB
316         bcopy(&dblow, (void *)(EXC_MCHK + trap_offset), (size_t)&dbend -
317             (size_t)&dblow);
318         bcopy(&dblow, (void *)(EXC_PGM + trap_offset), (size_t)&dbend -
319             (size_t)&dblow);
320         bcopy(&dblow, (void *)(EXC_TRC + trap_offset), (size_t)&dbend -
321             (size_t)&dblow);
322         bcopy(&dblow, (void *)(EXC_BPT + trap_offset), (size_t)&dbend -
323             (size_t)&dblow);
324 #endif
325         bcopy(&alitrap,  (void *)(EXC_ALI + trap_offset),  (size_t)&aliend -
326             (size_t)&alitrap);
327         bcopy(&dsitrap,  (void *)(EXC_DSI + trap_offset),  (size_t)&dsiend -
328             (size_t)&dsitrap);
329
330         #ifdef __powerpc64__
331         /* Set TOC base so that the interrupt code can get at it */
332         *((void **)TRAP_GENTRAP) = &generictrap;
333         *((register_t *)TRAP_TOCBASE) = toc;
334         #else
335         /* Set branch address for trap code */
336         if (cpu_features & PPC_FEATURE_64)
337                 *((void **)TRAP_GENTRAP) = &generictrap64;
338         else
339                 *((void **)TRAP_GENTRAP) = &generictrap;
340         *((void **)TRAP_TOCBASE) = _GLOBAL_OFFSET_TABLE_;
341
342         /* G2-specific TLB miss helper handlers */
343         bcopy(&imisstrap, (void *)EXC_IMISS,  (size_t)&imisssize);
344         bcopy(&dlmisstrap, (void *)EXC_DLMISS,  (size_t)&dlmisssize);
345         bcopy(&dsmisstrap, (void *)EXC_DSMISS,  (size_t)&dsmisssize);
346         #endif
347         __syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD);
348
349         /*
350          * Restore MSR
351          */
352         mtmsr(msr);
353
354         /* Warn if cachline size was not determined */
355         if (cacheline_warn == 1) {
356                 printf("WARNING: cacheline size undetermined, setting to 32\n");
357         }
358
359         /*
360          * Initialise virtual memory. Use BUS_PROBE_GENERIC priority
361          * in case the platform module had a better idea of what we
362          * should do.
363          */
364         if (cpu_features & PPC_FEATURE_64)
365                 pmap_mmu_install(MMU_TYPE_G5, BUS_PROBE_GENERIC);
366         else
367                 pmap_mmu_install(MMU_TYPE_OEA, BUS_PROBE_GENERIC);
368 }
369
370 /*
371  * Shutdown the CPU as much as possible.
372  */
373 void
374 cpu_halt(void)
375 {
376
377         OF_exit();
378 }
379
380 int
381 ptrace_single_step(struct thread *td)
382 {
383         struct trapframe *tf;
384
385         tf = td->td_frame;
386         tf->srr1 |= PSL_SE;
387
388         return (0);
389 }
390
391 int
392 ptrace_clear_single_step(struct thread *td)
393 {
394         struct trapframe *tf;
395
396         tf = td->td_frame;
397         tf->srr1 &= ~PSL_SE;
398
399         return (0);
400 }
401
402 void
403 kdb_cpu_clear_singlestep(void)
404 {
405
406         kdb_frame->srr1 &= ~PSL_SE;
407 }
408
409 void
410 kdb_cpu_set_singlestep(void)
411 {
412
413         kdb_frame->srr1 |= PSL_SE;
414 }
415
416 /*
417  * Initialise a struct pcpu.
418  */
419 void
420 cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
421 {
422 #ifdef __powerpc64__
423 /* Copy the SLB contents from the current CPU */
424 memcpy(pcpu->pc_slb, PCPU_GET(slb), sizeof(pcpu->pc_slb));
425 #endif
426 }
427
428 #ifndef __powerpc64__
429 uint64_t
430 va_to_vsid(pmap_t pm, vm_offset_t va)
431 {
432         return ((pm->pm_sr[(uintptr_t)va >> ADDR_SR_SHFT]) & SR_VSID_MASK);
433 }
434
435 #endif
436
437 vm_offset_t
438 pmap_early_io_map(vm_paddr_t pa, vm_size_t size)
439 {
440
441         return (pa);
442 }
443
444 /* From p3-53 of the MPC7450 RISC Microprocessor Family Reference Manual */
445 void
446 flush_disable_caches(void)
447 {
448         register_t msr;
449         register_t msscr0;
450         register_t cache_reg;
451         volatile uint32_t *memp;
452         uint32_t temp;
453         int i;
454         int x;
455
456         msr = mfmsr();
457         powerpc_sync();
458         mtmsr(msr & ~(PSL_EE | PSL_DR));
459         msscr0 = mfspr(SPR_MSSCR0);
460         msscr0 &= ~MSSCR0_L2PFE;
461         mtspr(SPR_MSSCR0, msscr0);
462         powerpc_sync();
463         isync();
464         __asm__ __volatile__("dssall; sync");
465         powerpc_sync();
466         isync();
467         __asm__ __volatile__("dcbf 0,%0" :: "r"(0));
468         __asm__ __volatile__("dcbf 0,%0" :: "r"(0));
469         __asm__ __volatile__("dcbf 0,%0" :: "r"(0));
470
471         /* Lock the L1 Data cache. */
472         mtspr(SPR_LDSTCR, mfspr(SPR_LDSTCR) | 0xFF);
473         powerpc_sync();
474         isync();
475
476         mtspr(SPR_LDSTCR, 0);
477
478         /*
479          * Perform this in two stages: Flush the cache starting in RAM, then do it
480          * from ROM.
481          */
482         memp = (volatile uint32_t *)0x00000000;
483         for (i = 0; i < 128 * 1024; i++) {
484                 temp = *memp;
485                 __asm__ __volatile__("dcbf 0,%0" :: "r"(memp));
486                 memp += 32/sizeof(*memp);
487         }
488
489         memp = (volatile uint32_t *)0xfff00000;
490         x = 0xfe;
491
492         for (; x != 0xff;) {
493                 mtspr(SPR_LDSTCR, x);
494                 for (i = 0; i < 128; i++) {
495                         temp = *memp;
496                         __asm__ __volatile__("dcbf 0,%0" :: "r"(memp));
497                         memp += 32/sizeof(*memp);
498                 }
499                 x = ((x << 1) | 1) & 0xff;
500         }
501         mtspr(SPR_LDSTCR, 0);
502
503         cache_reg = mfspr(SPR_L2CR);
504         if (cache_reg & L2CR_L2E) {
505                 cache_reg &= ~(L2CR_L2IO_7450 | L2CR_L2DO_7450);
506                 mtspr(SPR_L2CR, cache_reg);
507                 powerpc_sync();
508                 mtspr(SPR_L2CR, cache_reg | L2CR_L2HWF);
509                 while (mfspr(SPR_L2CR) & L2CR_L2HWF)
510                         ; /* Busy wait for cache to flush */
511                 powerpc_sync();
512                 cache_reg &= ~L2CR_L2E;
513                 mtspr(SPR_L2CR, cache_reg);
514                 powerpc_sync();
515                 mtspr(SPR_L2CR, cache_reg | L2CR_L2I);
516                 powerpc_sync();
517                 while (mfspr(SPR_L2CR) & L2CR_L2I)
518                         ; /* Busy wait for L2 cache invalidate */
519                 powerpc_sync();
520         }
521
522         cache_reg = mfspr(SPR_L3CR);
523         if (cache_reg & L3CR_L3E) {
524                 cache_reg &= ~(L3CR_L3IO | L3CR_L3DO);
525                 mtspr(SPR_L3CR, cache_reg);
526                 powerpc_sync();
527                 mtspr(SPR_L3CR, cache_reg | L3CR_L3HWF);
528                 while (mfspr(SPR_L3CR) & L3CR_L3HWF)
529                         ; /* Busy wait for cache to flush */
530                 powerpc_sync();
531                 cache_reg &= ~L3CR_L3E;
532                 mtspr(SPR_L3CR, cache_reg);
533                 powerpc_sync();
534                 mtspr(SPR_L3CR, cache_reg | L3CR_L3I);
535                 powerpc_sync();
536                 while (mfspr(SPR_L3CR) & L3CR_L3I)
537                         ; /* Busy wait for L3 cache invalidate */
538                 powerpc_sync();
539         }
540
541         mtspr(SPR_HID0, mfspr(SPR_HID0) & ~HID0_DCE);
542         powerpc_sync();
543         isync();
544
545         mtmsr(msr);
546 }
547
548 void
549 cpu_sleep()
550 {
551         static u_quad_t timebase = 0;
552         static register_t sprgs[4];
553         static register_t srrs[2];
554
555         jmp_buf resetjb;
556         struct thread *fputd;
557         struct thread *vectd;
558         register_t hid0;
559         register_t msr;
560         register_t saved_msr;
561
562         ap_pcpu = pcpup;
563
564         PCPU_SET(restore, &resetjb);
565
566         saved_msr = mfmsr();
567         fputd = PCPU_GET(fputhread);
568         vectd = PCPU_GET(vecthread);
569         if (fputd != NULL)
570                 save_fpu(fputd);
571         if (vectd != NULL)
572                 save_vec(vectd);
573         if (setjmp(resetjb) == 0) {
574                 sprgs[0] = mfspr(SPR_SPRG0);
575                 sprgs[1] = mfspr(SPR_SPRG1);
576                 sprgs[2] = mfspr(SPR_SPRG2);
577                 sprgs[3] = mfspr(SPR_SPRG3);
578                 srrs[0] = mfspr(SPR_SRR0);
579                 srrs[1] = mfspr(SPR_SRR1);
580                 timebase = mftb();
581                 powerpc_sync();
582                 flush_disable_caches();
583                 hid0 = mfspr(SPR_HID0);
584                 hid0 = (hid0 & ~(HID0_DOZE | HID0_NAP)) | HID0_SLEEP;
585                 powerpc_sync();
586                 isync();
587                 msr = mfmsr() | PSL_POW;
588                 mtspr(SPR_HID0, hid0);
589                 powerpc_sync();
590
591                 while (1)
592                         mtmsr(msr);
593         }
594         platform_smp_timebase_sync(timebase, 0);
595         PCPU_SET(curthread, curthread);
596         PCPU_SET(curpcb, curthread->td_pcb);
597         pmap_activate(curthread);
598         powerpc_sync();
599         mtspr(SPR_SPRG0, sprgs[0]);
600         mtspr(SPR_SPRG1, sprgs[1]);
601         mtspr(SPR_SPRG2, sprgs[2]);
602         mtspr(SPR_SPRG3, sprgs[3]);
603         mtspr(SPR_SRR0, srrs[0]);
604         mtspr(SPR_SRR1, srrs[1]);
605         mtmsr(saved_msr);
606         if (fputd == curthread)
607                 enable_fpu(curthread);
608         if (vectd == curthread)
609                 enable_vec(curthread);
610         powerpc_sync();
611 }
612