booke_machdep.c revision 1.1.2.3 1 1.1.2.3 matt /* $NetBSD: booke_machdep.c,v 1.1.2.3 2011/10/14 17:21:25 matt Exp $ */
2 1.1.2.1 matt /*-
3 1.1.2.1 matt * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
4 1.1.2.1 matt * All rights reserved.
5 1.1.2.1 matt *
6 1.1.2.1 matt * This code is derived from software contributed to The NetBSD Foundation
7 1.1.2.1 matt * by Raytheon BBN Technologies Corp and Defense Advanced Research Projects
8 1.1.2.1 matt * Agency and which was developed by Matt Thomas of 3am Software Foundry.
9 1.1.2.1 matt *
10 1.1.2.1 matt * This material is based upon work supported by the Defense Advanced Research
11 1.1.2.1 matt * Projects Agency and Space and Naval Warfare Systems Center, Pacific, under
12 1.1.2.1 matt * Contract No. N66001-09-C-2073.
13 1.1.2.1 matt * Approved for Public Release, Distribution Unlimited
14 1.1.2.1 matt *
15 1.1.2.1 matt * Redistribution and use in source and binary forms, with or without
16 1.1.2.1 matt * modification, are permitted provided that the following conditions
17 1.1.2.1 matt * are met:
18 1.1.2.1 matt * 1. Redistributions of source code must retain the above copyright
19 1.1.2.1 matt * notice, this list of conditions and the following disclaimer.
20 1.1.2.1 matt * 2. Redistributions in binary form must reproduce the above copyright
21 1.1.2.1 matt * notice, this list of conditions and the following disclaimer in the
22 1.1.2.1 matt * documentation and/or other materials provided with the distribution.
23 1.1.2.1 matt *
24 1.1.2.1 matt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
25 1.1.2.1 matt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 1.1.2.1 matt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 1.1.2.1 matt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
28 1.1.2.1 matt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 1.1.2.1 matt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 1.1.2.1 matt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 1.1.2.1 matt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 1.1.2.1 matt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 1.1.2.1 matt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 1.1.2.1 matt * POSSIBILITY OF SUCH DAMAGE.
35 1.1.2.1 matt */
36 1.1.2.1 matt
37 1.1.2.1 matt #define __INTR_PRIVATE
38 1.1.2.1 matt #define _POWERPC_BUS_DMA_PRIVATE
39 1.1.2.1 matt
40 1.1.2.1 matt #include <sys/cdefs.h>
41 1.1.2.3 matt __KERNEL_RCSID(0, "$NetBSD: booke_machdep.c,v 1.1.2.3 2011/10/14 17:21:25 matt Exp $");
42 1.1.2.3 matt
43 1.1.2.3 matt #include "opt_modular.h"
44 1.1.2.1 matt
45 1.1.2.1 matt #include <sys/param.h>
46 1.1.2.1 matt #include <sys/cpu.h>
47 1.1.2.3 matt #include <sys/device.h>
48 1.1.2.1 matt #include <sys/intr.h>
49 1.1.2.1 matt #include <sys/mount.h>
50 1.1.2.1 matt #include <sys/msgbuf.h>
51 1.1.2.1 matt #include <sys/kernel.h>
52 1.1.2.1 matt #include <sys/reboot.h>
53 1.1.2.1 matt #include <sys/bus.h>
54 1.1.2.1 matt
55 1.1.2.1 matt #include <uvm/uvm_extern.h>
56 1.1.2.1 matt
57 1.1.2.3 matt #include <powerpc/cpuset.h>
58 1.1.2.3 matt #include <powerpc/pcb.h>
59 1.1.2.3 matt #include <powerpc/spr.h>
60 1.1.2.3 matt #include <powerpc/booke/spr.h>
61 1.1.2.3 matt #include <powerpc/booke/cpuvar.h>
62 1.1.2.1 matt
63 1.1.2.1 matt /*
64 1.1.2.1 matt * Global variables used here and there
65 1.1.2.1 matt */
66 1.1.2.1 matt struct user *proc0paddr;
67 1.1.2.1 matt paddr_t msgbuf_paddr;
68 1.1.2.1 matt psize_t pmemsize;
69 1.1.2.1 matt struct vm_map *mb_map;
70 1.1.2.1 matt struct vm_map *phys_map;
71 1.1.2.1 matt
72 1.1.2.3 matt #ifdef MODULAR
73 1.1.2.3 matt register_t cpu_psluserset = PSL_USERSET;
74 1.1.2.3 matt register_t cpu_pslusermod = PSL_USERMOD;
75 1.1.2.3 matt register_t cpu_pslusermask = PSL_USERMASK;
76 1.1.2.3 matt #endif
77 1.1.2.3 matt
78 1.1.2.1 matt static bus_addr_t booke_dma_phys_to_bus_mem(bus_dma_tag_t, bus_addr_t);
79 1.1.2.1 matt static bus_addr_t booke_dma_bus_mem_to_phys(bus_dma_tag_t, bus_addr_t);
80 1.1.2.1 matt
81 1.1.2.1 matt
82 1.1.2.1 matt struct powerpc_bus_dma_tag booke_bus_dma_tag = {
83 1.1.2.1 matt ._dmamap_create = _bus_dmamap_create,
84 1.1.2.1 matt ._dmamap_destroy = _bus_dmamap_destroy,
85 1.1.2.1 matt ._dmamap_load = _bus_dmamap_load,
86 1.1.2.1 matt ._dmamap_load_mbuf = _bus_dmamap_load_mbuf,
87 1.1.2.1 matt ._dmamap_load_uio = _bus_dmamap_load_uio,
88 1.1.2.1 matt ._dmamap_load_raw = _bus_dmamap_load_raw,
89 1.1.2.1 matt ._dmamap_unload = _bus_dmamap_unload,
90 1.1.2.1 matt ._dmamap_sync = _bus_dmamap_sync,
91 1.1.2.1 matt ._dmamem_alloc = _bus_dmamem_alloc,
92 1.1.2.1 matt ._dmamem_free = _bus_dmamem_free,
93 1.1.2.1 matt ._dmamem_map = _bus_dmamem_map,
94 1.1.2.1 matt ._dmamem_unmap = _bus_dmamem_unmap,
95 1.1.2.1 matt ._dmamem_mmap = _bus_dmamem_mmap,
96 1.1.2.1 matt ._dma_phys_to_bus_mem = booke_dma_phys_to_bus_mem,
97 1.1.2.1 matt ._dma_bus_mem_to_phys = booke_dma_bus_mem_to_phys,
98 1.1.2.1 matt };
99 1.1.2.1 matt
100 1.1.2.1 matt static bus_addr_t
101 1.1.2.1 matt booke_dma_phys_to_bus_mem(bus_dma_tag_t t, bus_addr_t a)
102 1.1.2.1 matt {
103 1.1.2.1 matt return a;
104 1.1.2.1 matt }
105 1.1.2.1 matt
106 1.1.2.1 matt static bus_addr_t
107 1.1.2.1 matt booke_dma_bus_mem_to_phys(bus_dma_tag_t t, bus_addr_t a)
108 1.1.2.1 matt {
109 1.1.2.1 matt return a;
110 1.1.2.1 matt }
111 1.1.2.1 matt
112 1.1.2.1 matt struct cpu_md_ops cpu_md_ops;
113 1.1.2.1 matt
114 1.1.2.3 matt struct cpu_softc cpu_softc[] = {
115 1.1.2.1 matt [0] = {
116 1.1.2.3 matt .cpu_ci = &cpu_info[0],
117 1.1.2.1 matt },
118 1.1.2.3 matt #ifdef MULTIPROCESSOR
119 1.1.2.3 matt [CPU_MAXNUM-1] = {
120 1.1.2.3 matt .cpu_ci = &cpu_info[CPU_MAXNUM-1],
121 1.1.2.3 matt },
122 1.1.2.3 matt #endif
123 1.1.2.1 matt };
124 1.1.2.3 matt struct cpu_info cpu_info[] = {
125 1.1.2.1 matt [0] = {
126 1.1.2.1 matt .ci_curlwp = &lwp0,
127 1.1.2.1 matt .ci_tlb_info = &pmap_tlb0_info,
128 1.1.2.3 matt .ci_softc = &cpu_softc[0],
129 1.1.2.1 matt .ci_cpl = IPL_HIGH,
130 1.1.2.3 matt .ci_idepth = -1,
131 1.1.2.1 matt },
132 1.1.2.3 matt #ifdef MULTIPROCESSOR
133 1.1.2.3 matt [CPU_MAXNUM-1] = {
134 1.1.2.3 matt .ci_curlwp = NULL,
135 1.1.2.3 matt .ci_tlb_info = &pmap_tlb0_info,
136 1.1.2.3 matt .ci_softc = &cpu_softc[CPU_MAXNUM-1],
137 1.1.2.3 matt .ci_cpl = IPL_HIGH,
138 1.1.2.3 matt .ci_idepth = -1,
139 1.1.2.3 matt },
140 1.1.2.3 matt #endif
141 1.1.2.1 matt };
142 1.1.2.3 matt CTASSERT(__arraycount(cpu_info) == __arraycount(cpu_softc));
143 1.1.2.1 matt
144 1.1.2.1 matt /*
145 1.1.2.1 matt * This should probably be in autoconf! XXX
146 1.1.2.1 matt */
147 1.1.2.1 matt char cpu_model[80];
148 1.1.2.1 matt char machine[] = MACHINE; /* from <machine/param.h> */
149 1.1.2.1 matt char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */
150 1.1.2.1 matt
151 1.1.2.1 matt char bootpath[256];
152 1.1.2.1 matt
153 1.1.2.1 matt #if NKSYMS || defined(DDB) || defined(MODULAR)
154 1.1.2.1 matt void *startsym, *endsym;
155 1.1.2.1 matt #endif
156 1.1.2.1 matt
157 1.1.2.3 matt #if defined(MULTIPROCESSOR)
158 1.1.2.3 matt volatile struct cpu_hatch_data cpu_hatch_data __cacheline_aligned;
159 1.1.2.3 matt #endif
160 1.1.2.1 matt
161 1.1.2.3 matt int fake_mapiodev = 1;
162 1.1.2.1 matt
163 1.1.2.1 matt void
164 1.1.2.2 matt booke_cpu_startup(const char *model)
165 1.1.2.1 matt {
166 1.1.2.1 matt vaddr_t minaddr, maxaddr;
167 1.1.2.1 matt char pbuf[9];
168 1.1.2.1 matt
169 1.1.2.2 matt strlcpy(cpu_model, model, sizeof(cpu_model));
170 1.1.2.2 matt
171 1.1.2.1 matt printf("%s%s", copyright, version);
172 1.1.2.1 matt
173 1.1.2.3 matt format_bytes(pbuf, sizeof(pbuf), ctob((uint64_t)physmem));
174 1.1.2.1 matt printf("total memory = %s\n", pbuf);
175 1.1.2.1 matt
176 1.1.2.1 matt minaddr = 0;
177 1.1.2.1 matt /*
178 1.1.2.1 matt * Allocate a submap for physio
179 1.1.2.1 matt */
180 1.1.2.1 matt phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
181 1.1.2.1 matt VM_PHYS_SIZE, 0, false, NULL);
182 1.1.2.1 matt
183 1.1.2.1 matt /*
184 1.1.2.1 matt * No need to allocate an mbuf cluster submap. Mbuf clusters
185 1.1.2.1 matt * are allocated via the pool allocator, and we use direct-mapped
186 1.1.2.1 matt * pool pages.
187 1.1.2.1 matt */
188 1.1.2.1 matt
189 1.1.2.1 matt format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
190 1.1.2.1 matt printf("avail memory = %s\n", pbuf);
191 1.1.2.1 matt
192 1.1.2.1 matt /*
193 1.1.2.3 matt * Register the tlb's evcnts
194 1.1.2.3 matt */
195 1.1.2.3 matt pmap_tlb_info_evcnt_attach(curcpu()->ci_tlb_info);
196 1.1.2.3 matt
197 1.1.2.3 matt /*
198 1.1.2.1 matt * Set up the board properties database.
199 1.1.2.1 matt */
200 1.1.2.1 matt board_info_init();
201 1.1.2.1 matt
202 1.1.2.1 matt /*
203 1.1.2.1 matt * Now that we have VM, malloc()s are OK in bus_space.
204 1.1.2.1 matt */
205 1.1.2.1 matt bus_space_mallocok();
206 1.1.2.1 matt fake_mapiodev = 0;
207 1.1.2.3 matt
208 1.1.2.3 matt #ifdef MULTIPROCESSOR
209 1.1.2.3 matt for (size_t i = 1; i < __arraycount(cpu_info); i++) {
210 1.1.2.3 matt struct cpu_info * const ci = &cpu_info[i];
211 1.1.2.3 matt struct cpu_softc * const cpu = &cpu_softc[i];
212 1.1.2.3 matt cpu->cpu_ci = ci;
213 1.1.2.3 matt cpu->cpu_bst = cpu_softc[0].cpu_bst;
214 1.1.2.3 matt cpu->cpu_le_bst = cpu_softc[0].cpu_le_bst;
215 1.1.2.3 matt cpu->cpu_bsh = cpu_softc[0].cpu_bsh;
216 1.1.2.3 matt cpu->cpu_highmem = cpu_softc[0].cpu_highmem;
217 1.1.2.3 matt ci->ci_softc = cpu;
218 1.1.2.3 matt ci->ci_tlb_info = &pmap_tlb0_info;
219 1.1.2.3 matt ci->ci_cpl = IPL_HIGH;
220 1.1.2.3 matt ci->ci_idepth = -1;
221 1.1.2.3 matt ci->ci_pmap_kern_segtab = curcpu()->ci_pmap_kern_segtab;
222 1.1.2.3 matt }
223 1.1.2.3 matt #endif /* MULTIPROCESSOR */
224 1.1.2.1 matt }
225 1.1.2.1 matt
226 1.1.2.1 matt static void
227 1.1.2.1 matt dumpsys(void)
228 1.1.2.1 matt {
229 1.1.2.1 matt
230 1.1.2.1 matt printf("dumpsys: TBD\n");
231 1.1.2.1 matt }
232 1.1.2.1 matt
233 1.1.2.1 matt /*
234 1.1.2.1 matt * Halt or reboot the machine after syncing/dumping according to howto.
235 1.1.2.1 matt */
236 1.1.2.1 matt void
237 1.1.2.1 matt cpu_reboot(int howto, char *what)
238 1.1.2.1 matt {
239 1.1.2.1 matt static int syncing;
240 1.1.2.1 matt static char str[256];
241 1.1.2.1 matt char *ap = str, *ap1 = ap;
242 1.1.2.1 matt
243 1.1.2.1 matt boothowto = howto;
244 1.1.2.1 matt if (!cold && !(howto & RB_NOSYNC) && !syncing) {
245 1.1.2.1 matt syncing = 1;
246 1.1.2.1 matt vfs_shutdown(); /* sync */
247 1.1.2.1 matt resettodr(); /* set wall clock */
248 1.1.2.1 matt }
249 1.1.2.1 matt
250 1.1.2.1 matt splhigh();
251 1.1.2.1 matt
252 1.1.2.1 matt if (!cold && (howto & RB_DUMP))
253 1.1.2.1 matt dumpsys();
254 1.1.2.1 matt
255 1.1.2.1 matt doshutdownhooks();
256 1.1.2.1 matt
257 1.1.2.1 matt pmf_system_shutdown(boothowto);
258 1.1.2.1 matt
259 1.1.2.1 matt if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
260 1.1.2.1 matt /* Power off here if we know how...*/
261 1.1.2.1 matt }
262 1.1.2.1 matt
263 1.1.2.1 matt if (howto & RB_HALT) {
264 1.1.2.1 matt printf("halted\n\n");
265 1.1.2.1 matt
266 1.1.2.1 matt goto reboot; /* XXX for now... */
267 1.1.2.1 matt
268 1.1.2.1 matt #ifdef DDB
269 1.1.2.1 matt printf("dropping to debugger\n");
270 1.1.2.1 matt while(1)
271 1.1.2.1 matt Debugger();
272 1.1.2.1 matt #endif
273 1.1.2.1 matt }
274 1.1.2.1 matt
275 1.1.2.1 matt printf("rebooting\n\n");
276 1.1.2.1 matt if (what && *what) {
277 1.1.2.1 matt if (strlen(what) > sizeof str - 5)
278 1.1.2.1 matt printf("boot string too large, ignored\n");
279 1.1.2.1 matt else {
280 1.1.2.1 matt strcpy(str, what);
281 1.1.2.1 matt ap1 = ap = str + strlen(str);
282 1.1.2.1 matt *ap++ = ' ';
283 1.1.2.1 matt }
284 1.1.2.1 matt }
285 1.1.2.1 matt *ap++ = '-';
286 1.1.2.1 matt if (howto & RB_SINGLE)
287 1.1.2.1 matt *ap++ = 's';
288 1.1.2.1 matt if (howto & RB_KDB)
289 1.1.2.1 matt *ap++ = 'd';
290 1.1.2.1 matt *ap++ = 0;
291 1.1.2.1 matt if (ap[-2] == '-')
292 1.1.2.1 matt *ap1 = 0;
293 1.1.2.1 matt
294 1.1.2.1 matt /* flush cache for msgbuf */
295 1.1.2.1 matt dcache_wb(msgbuf_paddr, round_page(MSGBUFSIZE));
296 1.1.2.1 matt
297 1.1.2.1 matt reboot:
298 1.1.2.1 matt __asm volatile("msync; isync");
299 1.1.2.1 matt (*cpu_md_ops.md_cpu_reset)();
300 1.1.2.1 matt
301 1.1.2.1 matt printf("%s: md_cpu_reset() failed!\n", __func__);
302 1.1.2.1 matt #ifdef DDB
303 1.1.2.1 matt for (;;)
304 1.1.2.1 matt Debugger();
305 1.1.2.1 matt #else
306 1.1.2.1 matt for (;;)
307 1.1.2.1 matt /* nothing */;
308 1.1.2.1 matt #endif
309 1.1.2.1 matt }
310 1.1.2.1 matt
311 1.1.2.1 matt /*
312 1.1.2.1 matt * mapiodev:
313 1.1.2.1 matt *
314 1.1.2.1 matt * Allocate vm space and mapin the I/O address. Use reserved TLB
315 1.1.2.1 matt * mapping if one is found.
316 1.1.2.1 matt */
317 1.1.2.1 matt void *
318 1.1.2.1 matt mapiodev(paddr_t pa, psize_t len)
319 1.1.2.1 matt {
320 1.1.2.1 matt const vsize_t off = pa & PAGE_MASK;
321 1.1.2.1 matt
322 1.1.2.1 matt /*
323 1.1.2.1 matt * See if we have reserved TLB entry for the pa. This needs to be
324 1.1.2.1 matt * true for console as we can't use uvm during early bootstrap.
325 1.1.2.1 matt */
326 1.1.2.3 matt void * const p = tlb_mapiodev(pa, len, false);
327 1.1.2.1 matt if (p != NULL)
328 1.1.2.1 matt return p;
329 1.1.2.1 matt
330 1.1.2.1 matt if (fake_mapiodev)
331 1.1.2.1 matt panic("mapiodev: no TLB entry reserved for %llx+%llx",
332 1.1.2.1 matt (long long)pa, (long long)len);
333 1.1.2.1 matt
334 1.1.2.1 matt pa = trunc_page(pa);
335 1.1.2.1 matt len = round_page(off + len);
336 1.1.2.1 matt vaddr_t va = uvm_km_alloc(kernel_map, len, 0, UVM_KMF_VAONLY);
337 1.1.2.1 matt
338 1.1.2.1 matt if (va == 0)
339 1.1.2.1 matt return NULL;
340 1.1.2.1 matt
341 1.1.2.1 matt for (va += len, pa += len; len > 0; len -= PAGE_SIZE) {
342 1.1.2.1 matt va -= PAGE_SIZE;
343 1.1.2.1 matt pa -= PAGE_SIZE;
344 1.1.2.3 matt pmap_kenter_pa(va, pa, VM_PROT_READ|VM_PROT_WRITE|PMAP_NOCACHE);
345 1.1.2.1 matt }
346 1.1.2.1 matt pmap_update(pmap_kernel());
347 1.1.2.1 matt return (void *)(va + off);
348 1.1.2.1 matt }
349 1.1.2.1 matt
350 1.1.2.1 matt void
351 1.1.2.1 matt unmapiodev(vaddr_t va, vsize_t len)
352 1.1.2.1 matt {
353 1.1.2.1 matt /* Nothing to do for reserved (ie. not uvm_km_alloc'd) mappings. */
354 1.1.2.1 matt if (va < VM_MIN_KERNEL_ADDRESS || va > VM_MAX_KERNEL_ADDRESS) {
355 1.1.2.1 matt tlb_unmapiodev(va, len);
356 1.1.2.1 matt return;
357 1.1.2.1 matt }
358 1.1.2.1 matt
359 1.1.2.1 matt len = round_page((va & PAGE_MASK) + len);
360 1.1.2.1 matt va = trunc_page(va);
361 1.1.2.1 matt
362 1.1.2.1 matt pmap_kremove(va, len);
363 1.1.2.1 matt uvm_km_free(kernel_map, va, len, UVM_KMF_VAONLY);
364 1.1.2.1 matt }
365 1.1.2.1 matt
366 1.1.2.1 matt void
367 1.1.2.1 matt cpu_evcnt_attach(struct cpu_info *ci)
368 1.1.2.1 matt {
369 1.1.2.1 matt struct cpu_softc * const cpu = ci->ci_softc;
370 1.1.2.1 matt const char * const xname = device_xname(ci->ci_dev);
371 1.1.2.1 matt
372 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_clock, EVCNT_TYPE_INTR,
373 1.1.2.1 matt NULL, xname, "clock");
374 1.1.2.1 matt evcnt_attach_dynamic_nozero(&cpu->cpu_ev_late_clock, EVCNT_TYPE_INTR,
375 1.1.2.1 matt NULL, xname, "late clock");
376 1.1.2.1 matt evcnt_attach_dynamic_nozero(&cpu->cpu_ev_exec_trap_sync, EVCNT_TYPE_TRAP,
377 1.1.2.1 matt NULL, xname, "exec pages synced (trap)");
378 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_traps, EVCNT_TYPE_TRAP,
379 1.1.2.1 matt NULL, xname, "traps");
380 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_kdsi, EVCNT_TYPE_TRAP,
381 1.1.2.1 matt &ci->ci_ev_traps, xname, "kernel DSI traps");
382 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_udsi, EVCNT_TYPE_TRAP,
383 1.1.2.1 matt &ci->ci_ev_traps, xname, "user DSI traps");
384 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_udsi_fatal, EVCNT_TYPE_TRAP,
385 1.1.2.1 matt &ci->ci_ev_udsi, xname, "user DSI failures");
386 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_kisi, EVCNT_TYPE_TRAP,
387 1.1.2.1 matt &ci->ci_ev_traps, xname, "kernel ISI traps");
388 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_isi, EVCNT_TYPE_TRAP,
389 1.1.2.1 matt &ci->ci_ev_traps, xname, "user ISI traps");
390 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_isi_fatal, EVCNT_TYPE_TRAP,
391 1.1.2.1 matt &ci->ci_ev_isi, xname, "user ISI failures");
392 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_scalls, EVCNT_TYPE_TRAP,
393 1.1.2.1 matt &ci->ci_ev_traps, xname, "system call traps");
394 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_pgm, EVCNT_TYPE_TRAP,
395 1.1.2.1 matt &ci->ci_ev_traps, xname, "PGM traps");
396 1.1.2.3 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_debug, EVCNT_TYPE_TRAP,
397 1.1.2.3 matt &ci->ci_ev_traps, xname, "debug traps");
398 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_fpu, EVCNT_TYPE_TRAP,
399 1.1.2.1 matt &ci->ci_ev_traps, xname, "FPU unavailable traps");
400 1.1.2.2 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_fpusw, EVCNT_TYPE_MISC,
401 1.1.2.1 matt &ci->ci_ev_fpu, xname, "FPU context switches");
402 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_ali, EVCNT_TYPE_TRAP,
403 1.1.2.1 matt &ci->ci_ev_traps, xname, "user alignment traps");
404 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_ali_fatal, EVCNT_TYPE_TRAP,
405 1.1.2.1 matt &ci->ci_ev_ali, xname, "user alignment traps");
406 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_umchk, EVCNT_TYPE_TRAP,
407 1.1.2.1 matt &ci->ci_ev_umchk, xname, "user MCHK failures");
408 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_vec, EVCNT_TYPE_TRAP,
409 1.1.2.2 matt &ci->ci_ev_traps, xname, "SPE unavailable");
410 1.1.2.2 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_vecsw, EVCNT_TYPE_MISC,
411 1.1.2.2 matt &ci->ci_ev_vec, xname, "SPE context switches");
412 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_ipi, EVCNT_TYPE_INTR,
413 1.1.2.1 matt NULL, xname, "IPIs");
414 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_tlbmiss_soft, EVCNT_TYPE_TRAP,
415 1.1.2.1 matt &ci->ci_ev_traps, xname, "soft tlb misses");
416 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_dtlbmiss_hard, EVCNT_TYPE_TRAP,
417 1.1.2.1 matt &ci->ci_ev_traps, xname, "data tlb misses");
418 1.1.2.1 matt evcnt_attach_dynamic_nozero(&ci->ci_ev_itlbmiss_hard, EVCNT_TYPE_TRAP,
419 1.1.2.1 matt &ci->ci_ev_traps, xname, "inst tlb misses");
420 1.1.2.1 matt }
421 1.1.2.1 matt
422 1.1.2.3 matt #ifdef MULTIPROCESSOR
423 1.1.2.3 matt register_t
424 1.1.2.3 matt cpu_hatch(void)
425 1.1.2.3 matt {
426 1.1.2.3 matt volatile struct cpuset_info * const csi = &cpuset_info;
427 1.1.2.3 matt const size_t id = cpu_number();
428 1.1.2.3 matt
429 1.1.2.3 matt /*
430 1.1.2.3 matt * We've hatched so tell the spinup code.
431 1.1.2.3 matt */
432 1.1.2.3 matt CPUSET_ADD(csi->cpus_hatched, id);
433 1.1.2.3 matt
434 1.1.2.3 matt /*
435 1.1.2.3 matt * Loop until running bit for this cpu is set.
436 1.1.2.3 matt */
437 1.1.2.3 matt while (!CPUSET_HAS_P(csi->cpus_running, id)) {
438 1.1.2.3 matt continue;
439 1.1.2.3 matt }
440 1.1.2.3 matt
441 1.1.2.3 matt /*
442 1.1.2.3 matt * Now that we are active, start the clocks.
443 1.1.2.3 matt */
444 1.1.2.3 matt cpu_initclocks();
445 1.1.2.3 matt
446 1.1.2.3 matt /*
447 1.1.2.3 matt * Return sp of the idlelwp. Which we should be already using but ...
448 1.1.2.3 matt */
449 1.1.2.3 matt return curcpu()->ci_curpcb->pcb_sp;
450 1.1.2.3 matt }
451 1.1.2.3 matt
452 1.1.2.3 matt void
453 1.1.2.3 matt cpu_boot_secondary_processors(void)
454 1.1.2.3 matt {
455 1.1.2.3 matt volatile struct cpuset_info * const csi = &cpuset_info;
456 1.1.2.3 matt CPU_INFO_ITERATOR cii;
457 1.1.2.3 matt struct cpu_info *ci;
458 1.1.2.3 matt __cpuset_t running = CPUSET_NULLSET;
459 1.1.2.3 matt
460 1.1.2.3 matt for (CPU_INFO_FOREACH(cii, ci)) {
461 1.1.2.3 matt /*
462 1.1.2.3 matt * Skip this CPU if it didn't sucessfully hatch.
463 1.1.2.3 matt */
464 1.1.2.3 matt if (! CPUSET_HAS_P(csi->cpus_hatched, cpu_index(ci)))
465 1.1.2.3 matt continue;
466 1.1.2.3 matt
467 1.1.2.3 matt KASSERT(!CPU_IS_PRIMARY(ci));
468 1.1.2.3 matt KASSERT(ci->ci_data.cpu_idlelwp);
469 1.1.2.3 matt
470 1.1.2.3 matt CPUSET_ADD(running, cpu_index(ci));
471 1.1.2.3 matt }
472 1.1.2.3 matt KASSERT(CPUSET_EQUAL_P(csi->cpus_hatched, running));
473 1.1.2.3 matt if (!CPUSET_EMPTY_P(running)) {
474 1.1.2.3 matt CPUSET_ADDSET(csi->cpus_running, running);
475 1.1.2.3 matt }
476 1.1.2.3 matt }
477 1.1.2.3 matt #endif
478 1.1.2.3 matt
479 1.1.2.1 matt uint32_t
480 1.1.2.1 matt cpu_read_4(bus_addr_t a)
481 1.1.2.1 matt {
482 1.1.2.1 matt struct cpu_softc * const cpu = curcpu()->ci_softc;
483 1.1.2.1 matt // printf(" %s(%p, %x, %x)", __func__, cpu->cpu_bst, cpu->cpu_bsh, a);
484 1.1.2.1 matt return bus_space_read_4(cpu->cpu_bst, cpu->cpu_bsh, a);
485 1.1.2.1 matt }
486 1.1.2.1 matt
487 1.1.2.1 matt uint8_t
488 1.1.2.1 matt cpu_read_1(bus_addr_t a)
489 1.1.2.1 matt {
490 1.1.2.1 matt struct cpu_softc * const cpu = curcpu()->ci_softc;
491 1.1.2.1 matt // printf(" %s(%p, %x, %x)", __func__, cpu->cpu_bst, cpu->cpu_bsh, a);
492 1.1.2.1 matt return bus_space_read_1(cpu->cpu_bst, cpu->cpu_bsh, a);
493 1.1.2.1 matt }
494 1.1.2.1 matt
495 1.1.2.1 matt void
496 1.1.2.1 matt cpu_write_4(bus_addr_t a, uint32_t v)
497 1.1.2.1 matt {
498 1.1.2.1 matt struct cpu_softc * const cpu = curcpu()->ci_softc;
499 1.1.2.1 matt bus_space_write_4(cpu->cpu_bst, cpu->cpu_bsh, a, v);
500 1.1.2.1 matt }
501 1.1.2.1 matt
502 1.1.2.1 matt void
503 1.1.2.1 matt cpu_write_1(bus_addr_t a, uint8_t v)
504 1.1.2.1 matt {
505 1.1.2.1 matt struct cpu_softc * const cpu = curcpu()->ci_softc;
506 1.1.2.1 matt bus_space_write_1(cpu->cpu_bst, cpu->cpu_bsh, a, v);
507 1.1.2.1 matt }
508 1.1.2.3 matt
509 1.1.2.3 matt void
510 1.1.2.3 matt booke_sstep(struct trapframe *tf)
511 1.1.2.3 matt {
512 1.1.2.3 matt KASSERT(tf->tf_srr1 & PSL_DE);
513 1.1.2.3 matt const uint32_t insn = ufetch_32((const void *)tf->tf_srr0);
514 1.1.2.3 matt register_t dbcr0 = DBCR0_IAC1 | DBCR0_IDM;
515 1.1.2.3 matt register_t dbcr1 = DBCR1_IAC1US_USER | DBCR1_IAC1ER_DS1;
516 1.1.2.3 matt if ((insn >> 28) == 4) {
517 1.1.2.3 matt uint32_t iac2 = 0;
518 1.1.2.3 matt if ((insn >> 26) == 0x12) {
519 1.1.2.3 matt const int32_t off = (((int32_t)insn << 6) >> 6) & ~3;
520 1.1.2.3 matt iac2 = ((insn & 2) ? 0 : tf->tf_srr0) + off;
521 1.1.2.3 matt dbcr0 |= DBCR0_IAC2;
522 1.1.2.3 matt } else if ((insn >> 26) == 0x10) {
523 1.1.2.3 matt const int16_t off = insn & ~3;
524 1.1.2.3 matt iac2 = ((insn & 2) ? 0 : tf->tf_srr0) + off;
525 1.1.2.3 matt dbcr0 |= DBCR0_IAC2;
526 1.1.2.3 matt } else if ((insn & 0xfc00ffde) == 0x4c000420) {
527 1.1.2.3 matt iac2 = tf->tf_ctr;
528 1.1.2.3 matt dbcr0 |= DBCR0_IAC2;
529 1.1.2.3 matt } else if ((insn & 0xfc00ffde) == 0x4c000020) {
530 1.1.2.3 matt iac2 = tf->tf_lr;
531 1.1.2.3 matt dbcr0 |= DBCR0_IAC2;
532 1.1.2.3 matt }
533 1.1.2.3 matt if (dbcr0 & DBCR0_IAC2) {
534 1.1.2.3 matt dbcr1 |= DBCR1_IAC2US_USER | DBCR1_IAC2ER_DS1;
535 1.1.2.3 matt mtspr(SPR_IAC2, iac2);
536 1.1.2.3 matt }
537 1.1.2.3 matt }
538 1.1.2.3 matt mtspr(SPR_IAC1, tf->tf_srr0 + 4);
539 1.1.2.3 matt mtspr(SPR_DBCR1, dbcr1);
540 1.1.2.3 matt mtspr(SPR_DBCR0, dbcr0);
541 1.1.2.3 matt }
542