Deleted Added
full compact
aim_machdep.c (176222) aim_machdep.c (176742)
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>
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: head/sys/powerpc/aim/machdep.c 176222 2008-02-12 20:55:51Z marcel $");
58__FBSDID("$FreeBSD: head/sys/powerpc/aim/machdep.c 176742 2008-03-02 17:05:57Z raj $");
59
60#include "opt_compat.h"
61#include "opt_ddb.h"
62#include "opt_kstack_pages.h"
63#include "opt_msgbuf.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/signalvar.h>
88#include <sys/sysctl.h>
89#include <sys/sysent.h>
90#include <sys/sysproto.h>
91#include <sys/ucontext.h>
92#include <sys/uio.h>
93#include <sys/vmmeter.h>
94#include <sys/vnode.h>
95
96#include <net/netisr.h>
97
98#include <vm/vm.h>
99#include <vm/vm_extern.h>
100#include <vm/vm_kern.h>
101#include <vm/vm_page.h>
102#include <vm/vm_map.h>
103#include <vm/vm_object.h>
104#include <vm/vm_pager.h>
105
106#include <machine/bat.h>
107#include <machine/cpu.h>
108#include <machine/elf.h>
109#include <machine/fpu.h>
59
60#include "opt_compat.h"
61#include "opt_ddb.h"
62#include "opt_kstack_pages.h"
63#include "opt_msgbuf.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/signalvar.h>
88#include <sys/sysctl.h>
89#include <sys/sysent.h>
90#include <sys/sysproto.h>
91#include <sys/ucontext.h>
92#include <sys/uio.h>
93#include <sys/vmmeter.h>
94#include <sys/vnode.h>
95
96#include <net/netisr.h>
97
98#include <vm/vm.h>
99#include <vm/vm_extern.h>
100#include <vm/vm_kern.h>
101#include <vm/vm_page.h>
102#include <vm/vm_map.h>
103#include <vm/vm_object.h>
104#include <vm/vm_pager.h>
105
106#include <machine/bat.h>
107#include <machine/cpu.h>
108#include <machine/elf.h>
109#include <machine/fpu.h>
110#include <machine/kdb.h>
110#include <machine/md_var.h>
111#include <machine/metadata.h>
112#include <machine/mmuvar.h>
113#include <machine/pcb.h>
114#include <machine/powerpc.h>
115#include <machine/reg.h>
116#include <machine/sigframe.h>
117#include <machine/trap.h>
118#include <machine/vmparam.h>
119
120#include <ddb/ddb.h>
121
122#include <dev/ofw/openfirm.h>
123
124#ifdef DDB
125extern vm_offset_t ksym_start, ksym_end;
126#endif
127
128int cold = 1;
129
130static struct pcpu pcpu0;
131static struct trapframe frame0;
132
133vm_offset_t kstack0;
134vm_offset_t kstack0_phys;
135
136char machine[] = "powerpc";
137SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
138
139static int cacheline_size = CACHELINESIZE;
140SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size,
141 CTLFLAG_RD, &cacheline_size, 0, "");
142
143static void cpu_startup(void *);
144SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
145
146void powerpc_init(u_int, u_int, u_int, void *);
147
148int save_ofw_mapping(void);
149int restore_ofw_mapping(void);
150
151void install_extint(void (*)(void));
152
153int setfault(faultbuf); /* defined in locore.S */
154
155static int grab_mcontext(struct thread *, mcontext_t *, int);
156
157void asm_panic(char *);
158
159long Maxmem = 0;
160long realmem = 0;
161
162struct pmap ofw_pmap;
163extern int ofmsr;
164
165struct bat battable[16];
166
167struct kva_md_info kmi;
168
169void setPQL2(int *const size, int *const ways);
170
171void
172setPQL2(int *const size, int *const ways)
173{
174 return;
175}
176
177static void
178powerpc_ofw_shutdown(void *junk, int howto)
179{
180 if (howto & RB_HALT) {
181 OF_halt();
182 }
183 OF_reboot();
184}
185
186static void
187cpu_startup(void *dummy)
188{
189
190 /*
191 * Initialise the decrementer-based clock.
192 */
193 decr_init();
194
195 /*
196 * Good {morning,afternoon,evening,night}.
197 */
198 cpu_setup(PCPU_GET(cpuid));
199
200 /* startrtclock(); */
201#ifdef PERFMON
202 perfmon_init();
203#endif
204 printf("real memory = %ld (%ld MB)\n", ptoa(physmem),
205 ptoa(physmem) / 1048576);
206 realmem = physmem;
207
208 /*
209 * Display any holes after the first chunk of extended memory.
210 */
211 if (bootverbose) {
212 int indx;
213
214 printf("Physical memory chunk(s):\n");
215 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
216 int size1 = phys_avail[indx + 1] - phys_avail[indx];
217
218 printf("0x%08x - 0x%08x, %d bytes (%d pages)\n",
219 phys_avail[indx], phys_avail[indx + 1] - 1, size1,
220 size1 / PAGE_SIZE);
221 }
222 }
223
224 vm_ksubmap_init(&kmi);
225
226 printf("avail memory = %ld (%ld MB)\n", ptoa(cnt.v_free_count),
227 ptoa(cnt.v_free_count) / 1048576);
228
229 /*
230 * Set up buffers, so they can be used to read disk labels.
231 */
232 bufinit();
233 vm_pager_bufferinit();
234
235 EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0,
236 SHUTDOWN_PRI_LAST);
237}
238
239extern char kernel_text[], _end[];
240
241extern void *trapcode, *trapsize;
242extern void *alitrap, *alisize;
243extern void *dsitrap, *dsisize;
244extern void *decrint, *decrsize;
245extern void *extint, *extsize;
246extern void *dblow, *dbsize;
247extern void *vectrap, *vectrapsize;
248
249void
250powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
251{
252 struct pcpu *pc;
253 vm_offset_t end, off;
254 void *kmdp;
255 char *env;
256
257 end = 0;
258 kmdp = NULL;
259
260 /*
261 * Parse metadata if present and fetch parameters. Must be done
262 * before console is inited so cninit gets the right value of
263 * boothowto.
264 */
265 if (mdp != NULL) {
266 preload_metadata = mdp;
267 kmdp = preload_search_by_type("elf kernel");
268 if (kmdp != NULL) {
269 boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
270 kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
271 end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
272#ifdef DDB
273 ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
274 ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
275#endif
276 }
277 }
278
279 /*
280 * Init params/tunables that can be overridden by the loader
281 */
282 init_param1();
283
284 /*
285 * Start initializing proc0 and thread0.
286 */
287 proc_linkup0(&proc0, &thread0);
288 thread0.td_frame = &frame0;
289
290 /*
291 * Set up per-cpu data.
292 */
293 pc = &pcpu0;
294 pcpu_init(pc, 0, sizeof(struct pcpu));
295 pc->pc_curthread = &thread0;
296 pc->pc_curpcb = thread0.td_pcb;
297 pc->pc_cpuid = 0;
298
299 __asm __volatile("mtsprg 0, %0" :: "r"(pc));
300
301 mutex_init();
302
303 /*
304 * Initialize the console before printing anything.
305 */
306 cninit();
307
308 /*
309 * Complain if there is no metadata.
310 */
311 if (mdp == NULL || kmdp == NULL) {
312 printf("powerpc_init: no loader metadata.\n");
313 }
314
315 kdb_init();
316
317 kobj_machdep_init();
318
319 /*
320 * XXX: Initialize the interrupt tables.
321 * Disable translation in case the vector area
322 * hasn't been mapped (G5)
323 */
324 mtmsr(mfmsr() & ~(PSL_IR | PSL_DR));
325 isync();
326 bcopy(&trapcode, (void *)EXC_RST, (size_t)&trapsize);
327 bcopy(&trapcode, (void *)EXC_MCHK, (size_t)&trapsize);
328 bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
329 bcopy(&trapcode, (void *)EXC_ISI, (size_t)&trapsize);
330 bcopy(&trapcode, (void *)EXC_EXI, (size_t)&trapsize);
331 bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize);
332 bcopy(&trapcode, (void *)EXC_PGM, (size_t)&trapsize);
333 bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize);
334 bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize);
335 bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize);
336 bcopy(&trapcode, (void *)EXC_TRC, (size_t)&trapsize);
337 bcopy(&trapcode, (void *)EXC_FPA, (size_t)&trapsize);
338 bcopy(&vectrap, (void *)EXC_VEC, (size_t)&vectrapsize);
339 bcopy(&trapcode, (void *)EXC_VECAST, (size_t)&trapsize);
340 bcopy(&trapcode, (void *)EXC_THRM, (size_t)&trapsize);
341 bcopy(&trapcode, (void *)EXC_BPT, (size_t)&trapsize);
342#ifdef KDB
343 bcopy(&dblow, (void *)EXC_RST, (size_t)&dbsize);
344 bcopy(&dblow, (void *)EXC_MCHK, (size_t)&dbsize);
345 bcopy(&dblow, (void *)EXC_PGM, (size_t)&dbsize);
346 bcopy(&dblow, (void *)EXC_TRC, (size_t)&dbsize);
347 bcopy(&dblow, (void *)EXC_BPT, (size_t)&dbsize);
348#endif
349 __syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD);
350
351 /*
352 * Make sure translation has been enabled
353 */
354 mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI);
355 isync();
356
357 /*
358 * Initialise virtual memory.
359 */
360 pmap_mmu_install(MMU_TYPE_OEA, 0); /* XXX temporary */
361 pmap_bootstrap(startkernel, endkernel);
362
363 /*
364 * Initialize params/tunables that are derived from memsize
365 */
366 init_param2(physmem);
367
368 /*
369 * Grab booted kernel's name
370 */
371 env = getenv("kernelname");
372 if (env != NULL) {
373 strlcpy(kernelname, env, sizeof(kernelname));
374 freeenv(env);
375 }
376
377 /*
378 * Finish setting up thread0.
379 */
380 thread0.td_kstack = kstack0;
381 thread0.td_pcb = (struct pcb *)
382 (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
383
384 /*
385 * Map and initialise the message buffer.
386 */
387 for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
388 pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off);
389 msgbufinit(msgbufp, MSGBUF_SIZE);
390
391#ifdef KDB
392 if (boothowto & RB_KDB)
393 kdb_enter(KDB_WHY_BOOTFLAGS,
394 "Boot flags requested debugger");
395#endif
396}
397
398void
399bzero(void *buf, size_t len)
400{
401 caddr_t p;
402
403 p = buf;
404
405 while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) {
406 *p++ = 0;
407 len--;
408 }
409
410 while (len >= sizeof(u_long) * 8) {
411 *(u_long*) p = 0;
412 *((u_long*) p + 1) = 0;
413 *((u_long*) p + 2) = 0;
414 *((u_long*) p + 3) = 0;
415 len -= sizeof(u_long) * 8;
416 *((u_long*) p + 4) = 0;
417 *((u_long*) p + 5) = 0;
418 *((u_long*) p + 6) = 0;
419 *((u_long*) p + 7) = 0;
420 p += sizeof(u_long) * 8;
421 }
422
423 while (len >= sizeof(u_long)) {
424 *(u_long*) p = 0;
425 len -= sizeof(u_long);
426 p += sizeof(u_long);
427 }
428
429 while (len) {
430 *p++ = 0;
431 len--;
432 }
433}
434
435void
436sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
437{
438 struct trapframe *tf;
439 struct sigframe *sfp;
440 struct sigacts *psp;
441 struct sigframe sf;
442 struct thread *td;
443 struct proc *p;
444 int oonstack, rndfsize;
445 int sig;
446 int code;
447
448 td = curthread;
449 p = td->td_proc;
450 PROC_LOCK_ASSERT(p, MA_OWNED);
451 sig = ksi->ksi_signo;
452 code = ksi->ksi_code;
453 psp = p->p_sigacts;
454 mtx_assert(&psp->ps_mtx, MA_OWNED);
455 tf = td->td_frame;
456 oonstack = sigonstack(tf->fixreg[1]);
457
458 rndfsize = ((sizeof(sf) + 15) / 16) * 16;
459
460 CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
461 catcher, sig);
462
463 /*
464 * Save user context
465 */
466 memset(&sf, 0, sizeof(sf));
467 grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0);
468 sf.sf_uc.uc_sigmask = *mask;
469 sf.sf_uc.uc_stack = td->td_sigstk;
470 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
471 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
472
473 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
474
475 /*
476 * Allocate and validate space for the signal handler context.
477 */
478 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
479 SIGISMEMBER(psp->ps_sigonstack, sig)) {
480 sfp = (struct sigframe *)(td->td_sigstk.ss_sp +
481 td->td_sigstk.ss_size - rndfsize);
482 } else {
483 sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize);
484 }
485
486 /*
487 * Translate the signal if appropriate (Linux emu ?)
488 */
489 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
490 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
491
492 /*
493 * Save the floating-point state, if necessary, then copy it.
494 */
495 /* XXX */
496
497 /*
498 * Set up the registers to return to sigcode.
499 *
500 * r1/sp - sigframe ptr
501 * lr - sig function, dispatched to by blrl in trampoline
502 * r3 - sig number
503 * r4 - SIGINFO ? &siginfo : exception code
504 * r5 - user context
505 * srr0 - trampoline function addr
506 */
507 tf->lr = (register_t)catcher;
508 tf->fixreg[1] = (register_t)sfp;
509 tf->fixreg[FIRSTARG] = sig;
510 tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc;
511 if (SIGISMEMBER(psp->ps_siginfo, sig)) {
512 /*
513 * Signal handler installed with SA_SIGINFO.
514 */
515 tf->fixreg[FIRSTARG+1] = (register_t)&sfp->sf_si;
516
517 /*
518 * Fill siginfo structure.
519 */
520 sf.sf_si = ksi->ksi_info;
521 sf.sf_si.si_signo = sig;
111#include <machine/md_var.h>
112#include <machine/metadata.h>
113#include <machine/mmuvar.h>
114#include <machine/pcb.h>
115#include <machine/powerpc.h>
116#include <machine/reg.h>
117#include <machine/sigframe.h>
118#include <machine/trap.h>
119#include <machine/vmparam.h>
120
121#include <ddb/ddb.h>
122
123#include <dev/ofw/openfirm.h>
124
125#ifdef DDB
126extern vm_offset_t ksym_start, ksym_end;
127#endif
128
129int cold = 1;
130
131static struct pcpu pcpu0;
132static struct trapframe frame0;
133
134vm_offset_t kstack0;
135vm_offset_t kstack0_phys;
136
137char machine[] = "powerpc";
138SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
139
140static int cacheline_size = CACHELINESIZE;
141SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size,
142 CTLFLAG_RD, &cacheline_size, 0, "");
143
144static void cpu_startup(void *);
145SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
146
147void powerpc_init(u_int, u_int, u_int, void *);
148
149int save_ofw_mapping(void);
150int restore_ofw_mapping(void);
151
152void install_extint(void (*)(void));
153
154int setfault(faultbuf); /* defined in locore.S */
155
156static int grab_mcontext(struct thread *, mcontext_t *, int);
157
158void asm_panic(char *);
159
160long Maxmem = 0;
161long realmem = 0;
162
163struct pmap ofw_pmap;
164extern int ofmsr;
165
166struct bat battable[16];
167
168struct kva_md_info kmi;
169
170void setPQL2(int *const size, int *const ways);
171
172void
173setPQL2(int *const size, int *const ways)
174{
175 return;
176}
177
178static void
179powerpc_ofw_shutdown(void *junk, int howto)
180{
181 if (howto & RB_HALT) {
182 OF_halt();
183 }
184 OF_reboot();
185}
186
187static void
188cpu_startup(void *dummy)
189{
190
191 /*
192 * Initialise the decrementer-based clock.
193 */
194 decr_init();
195
196 /*
197 * Good {morning,afternoon,evening,night}.
198 */
199 cpu_setup(PCPU_GET(cpuid));
200
201 /* startrtclock(); */
202#ifdef PERFMON
203 perfmon_init();
204#endif
205 printf("real memory = %ld (%ld MB)\n", ptoa(physmem),
206 ptoa(physmem) / 1048576);
207 realmem = physmem;
208
209 /*
210 * Display any holes after the first chunk of extended memory.
211 */
212 if (bootverbose) {
213 int indx;
214
215 printf("Physical memory chunk(s):\n");
216 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
217 int size1 = phys_avail[indx + 1] - phys_avail[indx];
218
219 printf("0x%08x - 0x%08x, %d bytes (%d pages)\n",
220 phys_avail[indx], phys_avail[indx + 1] - 1, size1,
221 size1 / PAGE_SIZE);
222 }
223 }
224
225 vm_ksubmap_init(&kmi);
226
227 printf("avail memory = %ld (%ld MB)\n", ptoa(cnt.v_free_count),
228 ptoa(cnt.v_free_count) / 1048576);
229
230 /*
231 * Set up buffers, so they can be used to read disk labels.
232 */
233 bufinit();
234 vm_pager_bufferinit();
235
236 EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0,
237 SHUTDOWN_PRI_LAST);
238}
239
240extern char kernel_text[], _end[];
241
242extern void *trapcode, *trapsize;
243extern void *alitrap, *alisize;
244extern void *dsitrap, *dsisize;
245extern void *decrint, *decrsize;
246extern void *extint, *extsize;
247extern void *dblow, *dbsize;
248extern void *vectrap, *vectrapsize;
249
250void
251powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
252{
253 struct pcpu *pc;
254 vm_offset_t end, off;
255 void *kmdp;
256 char *env;
257
258 end = 0;
259 kmdp = NULL;
260
261 /*
262 * Parse metadata if present and fetch parameters. Must be done
263 * before console is inited so cninit gets the right value of
264 * boothowto.
265 */
266 if (mdp != NULL) {
267 preload_metadata = mdp;
268 kmdp = preload_search_by_type("elf kernel");
269 if (kmdp != NULL) {
270 boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
271 kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
272 end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
273#ifdef DDB
274 ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
275 ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
276#endif
277 }
278 }
279
280 /*
281 * Init params/tunables that can be overridden by the loader
282 */
283 init_param1();
284
285 /*
286 * Start initializing proc0 and thread0.
287 */
288 proc_linkup0(&proc0, &thread0);
289 thread0.td_frame = &frame0;
290
291 /*
292 * Set up per-cpu data.
293 */
294 pc = &pcpu0;
295 pcpu_init(pc, 0, sizeof(struct pcpu));
296 pc->pc_curthread = &thread0;
297 pc->pc_curpcb = thread0.td_pcb;
298 pc->pc_cpuid = 0;
299
300 __asm __volatile("mtsprg 0, %0" :: "r"(pc));
301
302 mutex_init();
303
304 /*
305 * Initialize the console before printing anything.
306 */
307 cninit();
308
309 /*
310 * Complain if there is no metadata.
311 */
312 if (mdp == NULL || kmdp == NULL) {
313 printf("powerpc_init: no loader metadata.\n");
314 }
315
316 kdb_init();
317
318 kobj_machdep_init();
319
320 /*
321 * XXX: Initialize the interrupt tables.
322 * Disable translation in case the vector area
323 * hasn't been mapped (G5)
324 */
325 mtmsr(mfmsr() & ~(PSL_IR | PSL_DR));
326 isync();
327 bcopy(&trapcode, (void *)EXC_RST, (size_t)&trapsize);
328 bcopy(&trapcode, (void *)EXC_MCHK, (size_t)&trapsize);
329 bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
330 bcopy(&trapcode, (void *)EXC_ISI, (size_t)&trapsize);
331 bcopy(&trapcode, (void *)EXC_EXI, (size_t)&trapsize);
332 bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize);
333 bcopy(&trapcode, (void *)EXC_PGM, (size_t)&trapsize);
334 bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize);
335 bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize);
336 bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize);
337 bcopy(&trapcode, (void *)EXC_TRC, (size_t)&trapsize);
338 bcopy(&trapcode, (void *)EXC_FPA, (size_t)&trapsize);
339 bcopy(&vectrap, (void *)EXC_VEC, (size_t)&vectrapsize);
340 bcopy(&trapcode, (void *)EXC_VECAST, (size_t)&trapsize);
341 bcopy(&trapcode, (void *)EXC_THRM, (size_t)&trapsize);
342 bcopy(&trapcode, (void *)EXC_BPT, (size_t)&trapsize);
343#ifdef KDB
344 bcopy(&dblow, (void *)EXC_RST, (size_t)&dbsize);
345 bcopy(&dblow, (void *)EXC_MCHK, (size_t)&dbsize);
346 bcopy(&dblow, (void *)EXC_PGM, (size_t)&dbsize);
347 bcopy(&dblow, (void *)EXC_TRC, (size_t)&dbsize);
348 bcopy(&dblow, (void *)EXC_BPT, (size_t)&dbsize);
349#endif
350 __syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD);
351
352 /*
353 * Make sure translation has been enabled
354 */
355 mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI);
356 isync();
357
358 /*
359 * Initialise virtual memory.
360 */
361 pmap_mmu_install(MMU_TYPE_OEA, 0); /* XXX temporary */
362 pmap_bootstrap(startkernel, endkernel);
363
364 /*
365 * Initialize params/tunables that are derived from memsize
366 */
367 init_param2(physmem);
368
369 /*
370 * Grab booted kernel's name
371 */
372 env = getenv("kernelname");
373 if (env != NULL) {
374 strlcpy(kernelname, env, sizeof(kernelname));
375 freeenv(env);
376 }
377
378 /*
379 * Finish setting up thread0.
380 */
381 thread0.td_kstack = kstack0;
382 thread0.td_pcb = (struct pcb *)
383 (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
384
385 /*
386 * Map and initialise the message buffer.
387 */
388 for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
389 pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off);
390 msgbufinit(msgbufp, MSGBUF_SIZE);
391
392#ifdef KDB
393 if (boothowto & RB_KDB)
394 kdb_enter(KDB_WHY_BOOTFLAGS,
395 "Boot flags requested debugger");
396#endif
397}
398
399void
400bzero(void *buf, size_t len)
401{
402 caddr_t p;
403
404 p = buf;
405
406 while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) {
407 *p++ = 0;
408 len--;
409 }
410
411 while (len >= sizeof(u_long) * 8) {
412 *(u_long*) p = 0;
413 *((u_long*) p + 1) = 0;
414 *((u_long*) p + 2) = 0;
415 *((u_long*) p + 3) = 0;
416 len -= sizeof(u_long) * 8;
417 *((u_long*) p + 4) = 0;
418 *((u_long*) p + 5) = 0;
419 *((u_long*) p + 6) = 0;
420 *((u_long*) p + 7) = 0;
421 p += sizeof(u_long) * 8;
422 }
423
424 while (len >= sizeof(u_long)) {
425 *(u_long*) p = 0;
426 len -= sizeof(u_long);
427 p += sizeof(u_long);
428 }
429
430 while (len) {
431 *p++ = 0;
432 len--;
433 }
434}
435
436void
437sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
438{
439 struct trapframe *tf;
440 struct sigframe *sfp;
441 struct sigacts *psp;
442 struct sigframe sf;
443 struct thread *td;
444 struct proc *p;
445 int oonstack, rndfsize;
446 int sig;
447 int code;
448
449 td = curthread;
450 p = td->td_proc;
451 PROC_LOCK_ASSERT(p, MA_OWNED);
452 sig = ksi->ksi_signo;
453 code = ksi->ksi_code;
454 psp = p->p_sigacts;
455 mtx_assert(&psp->ps_mtx, MA_OWNED);
456 tf = td->td_frame;
457 oonstack = sigonstack(tf->fixreg[1]);
458
459 rndfsize = ((sizeof(sf) + 15) / 16) * 16;
460
461 CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
462 catcher, sig);
463
464 /*
465 * Save user context
466 */
467 memset(&sf, 0, sizeof(sf));
468 grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0);
469 sf.sf_uc.uc_sigmask = *mask;
470 sf.sf_uc.uc_stack = td->td_sigstk;
471 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
472 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
473
474 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
475
476 /*
477 * Allocate and validate space for the signal handler context.
478 */
479 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
480 SIGISMEMBER(psp->ps_sigonstack, sig)) {
481 sfp = (struct sigframe *)(td->td_sigstk.ss_sp +
482 td->td_sigstk.ss_size - rndfsize);
483 } else {
484 sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize);
485 }
486
487 /*
488 * Translate the signal if appropriate (Linux emu ?)
489 */
490 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
491 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
492
493 /*
494 * Save the floating-point state, if necessary, then copy it.
495 */
496 /* XXX */
497
498 /*
499 * Set up the registers to return to sigcode.
500 *
501 * r1/sp - sigframe ptr
502 * lr - sig function, dispatched to by blrl in trampoline
503 * r3 - sig number
504 * r4 - SIGINFO ? &siginfo : exception code
505 * r5 - user context
506 * srr0 - trampoline function addr
507 */
508 tf->lr = (register_t)catcher;
509 tf->fixreg[1] = (register_t)sfp;
510 tf->fixreg[FIRSTARG] = sig;
511 tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc;
512 if (SIGISMEMBER(psp->ps_siginfo, sig)) {
513 /*
514 * Signal handler installed with SA_SIGINFO.
515 */
516 tf->fixreg[FIRSTARG+1] = (register_t)&sfp->sf_si;
517
518 /*
519 * Fill siginfo structure.
520 */
521 sf.sf_si = ksi->ksi_info;
522 sf.sf_si.si_signo = sig;
522 sf.sf_si.si_addr = (void *) ((tf->exc == EXC_DSI) ?
523 tf->dar : tf->srr0);
523 sf.sf_si.si_addr = (void *)((tf->exc == EXC_DSI) ?
524 tf->cpu.aim.dar : tf->srr0);
524 } else {
525 /* Old FreeBSD-style arguments. */
526 tf->fixreg[FIRSTARG+1] = code;
527 tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ?
525 } else {
526 /* Old FreeBSD-style arguments. */
527 tf->fixreg[FIRSTARG+1] = code;
528 tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ?
528 tf->dar : tf->srr0;
529 tf->cpu.aim.dar : tf->srr0;
529 }
530 mtx_unlock(&psp->ps_mtx);
531 PROC_UNLOCK(p);
532
533 tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
534
535 /*
536 * copy the frame out to userland.
537 */
538 if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
539 /*
540 * Process has trashed its stack. Kill it.
541 */
542 CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp);
543 PROC_LOCK(p);
544 sigexit(td, SIGILL);
545 }
546
547 CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td,
548 tf->srr0, tf->fixreg[1]);
549
550 PROC_LOCK(p);
551 mtx_lock(&psp->ps_mtx);
552}
553
554int
555sigreturn(struct thread *td, struct sigreturn_args *uap)
556{
557 struct proc *p;
558 ucontext_t uc;
559 int error;
560
561 CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
562
563 if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
564 CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
565 return (EFAULT);
566 }
567
568 error = set_mcontext(td, &uc.uc_mcontext);
569 if (error != 0)
570 return (error);
571
572 p = td->td_proc;
573 PROC_LOCK(p);
574 td->td_sigmask = uc.uc_sigmask;
575 SIG_CANTMASK(td->td_sigmask);
576 signotify(td);
577 PROC_UNLOCK(p);
578
579 CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
580 td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
581
582 return (EJUSTRETURN);
583}
584
585#ifdef COMPAT_FREEBSD4
586int
587freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
588{
589
590 return sigreturn(td, (struct sigreturn_args *)uap);
591}
592#endif
593
594/*
595 * Construct a PCB from a trapframe. This is called from kdb_trap() where
596 * we want to start a backtrace from the function that caused us to enter
597 * the debugger. We have the context in the trapframe, but base the trace
598 * on the PCB. The PCB doesn't have to be perfect, as long as it contains
599 * enough for a backtrace.
600 */
601void
602makectx(struct trapframe *tf, struct pcb *pcb)
603{
604
605 pcb->pcb_lr = tf->srr0;
606 pcb->pcb_sp = tf->fixreg[1];
607}
608
609/*
610 * get_mcontext/sendsig helper routine that doesn't touch the
611 * proc lock
612 */
613static int
614grab_mcontext(struct thread *td, mcontext_t *mcp, int flags)
615{
616 struct pcb *pcb;
617
618 pcb = td->td_pcb;
619
620 memset(mcp, 0, sizeof(mcontext_t));
621
622 mcp->mc_vers = _MC_VERSION;
623 mcp->mc_flags = 0;
624 memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe));
625 if (flags & GET_MC_CLEAR_RET) {
626 mcp->mc_gpr[3] = 0;
627 mcp->mc_gpr[4] = 0;
628 }
629
630 /*
631 * This assumes that floating-point context is *not* lazy,
632 * so if the thread has used FP there would have been a
633 * FP-unavailable exception that would have set things up
634 * correctly.
635 */
636 if (pcb->pcb_flags & PCB_FPU) {
637 KASSERT(td == curthread,
638 ("get_mcontext: fp save not curthread"));
639 critical_enter();
640 save_fpu(td);
641 critical_exit();
642 mcp->mc_flags |= _MC_FP_VALID;
643 memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
644 memcpy(mcp->mc_fpreg, pcb->pcb_fpu.fpr, 32*sizeof(double));
645 }
646
647 /* XXX Altivec context ? */
648
649 mcp->mc_len = sizeof(*mcp);
650
651 return (0);
652}
653
654int
655get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
656{
657 int error;
658
659 error = grab_mcontext(td, mcp, flags);
660 if (error == 0) {
661 PROC_LOCK(curthread->td_proc);
662 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
663 PROC_UNLOCK(curthread->td_proc);
664 }
665
666 return (error);
667}
668
669int
670set_mcontext(struct thread *td, const mcontext_t *mcp)
671{
672 struct pcb *pcb;
673 struct trapframe *tf;
674
675 pcb = td->td_pcb;
676 tf = td->td_frame;
677
678 if (mcp->mc_vers != _MC_VERSION ||
679 mcp->mc_len != sizeof(*mcp))
680 return (EINVAL);
681
682 /*
683 * Don't let the user set privileged MSR bits
684 */
685 if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) {
686 return (EINVAL);
687 }
688
689 memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame));
690
691 if (mcp->mc_flags & _MC_FP_VALID) {
692 if ((pcb->pcb_flags & PCB_FPU) != PCB_FPU) {
693 critical_enter();
694 enable_fpu(td);
695 critical_exit();
696 }
697 memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double));
698 memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double));
699 }
700
701 /* XXX Altivec context? */
702
703 return (0);
704}
705
706void
707cpu_boot(int howto)
708{
709}
710
711void
712cpu_initclocks(void)
713{
714
715 decr_tc_init();
716}
717
718/* Get current clock frequency for the given cpu id. */
719int
720cpu_est_clockrate(int cpu_id, uint64_t *rate)
721{
722
723 return (ENXIO);
724}
725
726/*
727 * Shutdown the CPU as much as possible.
728 */
729void
730cpu_halt(void)
731{
732
733 OF_exit();
734}
735
736void
737cpu_idle(void)
738{
739 /* TODO: Insert code to halt (until next interrupt) */
740
741#ifdef INVARIANTS
742 if ((mfmsr() & PSL_EE) != PSL_EE) {
743 struct thread *td = curthread;
744 printf("td msr %x\n", td->td_md.md_saved_msr);
745 panic("ints disabled in idleproc!");
746 }
747#endif
748}
749
750/*
751 * Set set up registers on exec.
752 */
753void
754exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
755{
756 struct trapframe *tf;
757 struct ps_strings arginfo;
758
759 tf = trapframe(td);
760 bzero(tf, sizeof *tf);
761 tf->fixreg[1] = -roundup(-stack + 8, 16);
762
763 /*
764 * XXX Machine-independent code has already copied arguments and
765 * XXX environment to userland. Get them back here.
766 */
767 (void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo));
768
769 /*
770 * Set up arguments for _start():
771 * _start(argc, argv, envp, obj, cleanup, ps_strings);
772 *
773 * Notes:
774 * - obj and cleanup are the auxilliary and termination
775 * vectors. They are fixed up by ld.elf_so.
776 * - ps_strings is a NetBSD extention, and will be
777 * ignored by executables which are strictly
778 * compliant with the SVR4 ABI.
779 *
780 * XXX We have to set both regs and retval here due to different
781 * XXX calling convention in trap.c and init_main.c.
782 */
783 /*
784 * XXX PG: these get overwritten in the syscall return code.
785 * execve() should return EJUSTRETURN, like it does on NetBSD.
786 * Emulate by setting the syscall return value cells. The
787 * registers still have to be set for init's fork trampoline.
788 */
789 td->td_retval[0] = arginfo.ps_nargvstr;
790 td->td_retval[1] = (register_t)arginfo.ps_argvstr;
791 tf->fixreg[3] = arginfo.ps_nargvstr;
792 tf->fixreg[4] = (register_t)arginfo.ps_argvstr;
793 tf->fixreg[5] = (register_t)arginfo.ps_envstr;
794 tf->fixreg[6] = 0; /* auxillary vector */
795 tf->fixreg[7] = 0; /* termination vector */
796 tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */
797
798 tf->srr0 = entry;
799 tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
800 td->td_pcb->pcb_flags = 0;
801}
802
803int
804fill_regs(struct thread *td, struct reg *regs)
805{
806 struct trapframe *tf;
807
808 tf = td->td_frame;
809 memcpy(regs, tf, sizeof(struct reg));
810
811 return (0);
812}
813
814int
815fill_dbregs(struct thread *td, struct dbreg *dbregs)
816{
817 /* No debug registers on PowerPC */
818 return (ENOSYS);
819}
820
821int
822fill_fpregs(struct thread *td, struct fpreg *fpregs)
823{
824 struct pcb *pcb;
825
826 pcb = td->td_pcb;
827
828 if ((pcb->pcb_flags & PCB_FPU) == 0)
829 memset(fpregs, 0, sizeof(struct fpreg));
830 else
831 memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg));
832
833 return (0);
834}
835
836int
837set_regs(struct thread *td, struct reg *regs)
838{
839 struct trapframe *tf;
840
841 tf = td->td_frame;
842 memcpy(tf, regs, sizeof(struct reg));
843
844 return (0);
845}
846
847int
848set_dbregs(struct thread *td, struct dbreg *dbregs)
849{
850 /* No debug registers on PowerPC */
851 return (ENOSYS);
852}
853
854int
855set_fpregs(struct thread *td, struct fpreg *fpregs)
856{
857 struct pcb *pcb;
858
859 pcb = td->td_pcb;
860 if ((pcb->pcb_flags & PCB_FPU) == 0)
861 enable_fpu(td);
862 memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg));
863
864 return (0);
865}
866
867int
868ptrace_set_pc(struct thread *td, unsigned long addr)
869{
870 struct trapframe *tf;
871
872 tf = td->td_frame;
873 tf->srr0 = (register_t)addr;
874
875 return (0);
876}
877
878int
879ptrace_single_step(struct thread *td)
880{
881 struct trapframe *tf;
882
883 tf = td->td_frame;
884 tf->srr1 |= PSL_SE;
885
886 return (0);
887}
888
889int
890ptrace_clear_single_step(struct thread *td)
891{
892 struct trapframe *tf;
893
894 tf = td->td_frame;
895 tf->srr1 &= ~PSL_SE;
896
897 return (0);
898}
899
530 }
531 mtx_unlock(&psp->ps_mtx);
532 PROC_UNLOCK(p);
533
534 tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
535
536 /*
537 * copy the frame out to userland.
538 */
539 if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
540 /*
541 * Process has trashed its stack. Kill it.
542 */
543 CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp);
544 PROC_LOCK(p);
545 sigexit(td, SIGILL);
546 }
547
548 CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td,
549 tf->srr0, tf->fixreg[1]);
550
551 PROC_LOCK(p);
552 mtx_lock(&psp->ps_mtx);
553}
554
555int
556sigreturn(struct thread *td, struct sigreturn_args *uap)
557{
558 struct proc *p;
559 ucontext_t uc;
560 int error;
561
562 CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
563
564 if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
565 CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
566 return (EFAULT);
567 }
568
569 error = set_mcontext(td, &uc.uc_mcontext);
570 if (error != 0)
571 return (error);
572
573 p = td->td_proc;
574 PROC_LOCK(p);
575 td->td_sigmask = uc.uc_sigmask;
576 SIG_CANTMASK(td->td_sigmask);
577 signotify(td);
578 PROC_UNLOCK(p);
579
580 CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
581 td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
582
583 return (EJUSTRETURN);
584}
585
586#ifdef COMPAT_FREEBSD4
587int
588freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
589{
590
591 return sigreturn(td, (struct sigreturn_args *)uap);
592}
593#endif
594
595/*
596 * Construct a PCB from a trapframe. This is called from kdb_trap() where
597 * we want to start a backtrace from the function that caused us to enter
598 * the debugger. We have the context in the trapframe, but base the trace
599 * on the PCB. The PCB doesn't have to be perfect, as long as it contains
600 * enough for a backtrace.
601 */
602void
603makectx(struct trapframe *tf, struct pcb *pcb)
604{
605
606 pcb->pcb_lr = tf->srr0;
607 pcb->pcb_sp = tf->fixreg[1];
608}
609
610/*
611 * get_mcontext/sendsig helper routine that doesn't touch the
612 * proc lock
613 */
614static int
615grab_mcontext(struct thread *td, mcontext_t *mcp, int flags)
616{
617 struct pcb *pcb;
618
619 pcb = td->td_pcb;
620
621 memset(mcp, 0, sizeof(mcontext_t));
622
623 mcp->mc_vers = _MC_VERSION;
624 mcp->mc_flags = 0;
625 memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe));
626 if (flags & GET_MC_CLEAR_RET) {
627 mcp->mc_gpr[3] = 0;
628 mcp->mc_gpr[4] = 0;
629 }
630
631 /*
632 * This assumes that floating-point context is *not* lazy,
633 * so if the thread has used FP there would have been a
634 * FP-unavailable exception that would have set things up
635 * correctly.
636 */
637 if (pcb->pcb_flags & PCB_FPU) {
638 KASSERT(td == curthread,
639 ("get_mcontext: fp save not curthread"));
640 critical_enter();
641 save_fpu(td);
642 critical_exit();
643 mcp->mc_flags |= _MC_FP_VALID;
644 memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
645 memcpy(mcp->mc_fpreg, pcb->pcb_fpu.fpr, 32*sizeof(double));
646 }
647
648 /* XXX Altivec context ? */
649
650 mcp->mc_len = sizeof(*mcp);
651
652 return (0);
653}
654
655int
656get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
657{
658 int error;
659
660 error = grab_mcontext(td, mcp, flags);
661 if (error == 0) {
662 PROC_LOCK(curthread->td_proc);
663 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
664 PROC_UNLOCK(curthread->td_proc);
665 }
666
667 return (error);
668}
669
670int
671set_mcontext(struct thread *td, const mcontext_t *mcp)
672{
673 struct pcb *pcb;
674 struct trapframe *tf;
675
676 pcb = td->td_pcb;
677 tf = td->td_frame;
678
679 if (mcp->mc_vers != _MC_VERSION ||
680 mcp->mc_len != sizeof(*mcp))
681 return (EINVAL);
682
683 /*
684 * Don't let the user set privileged MSR bits
685 */
686 if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) {
687 return (EINVAL);
688 }
689
690 memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame));
691
692 if (mcp->mc_flags & _MC_FP_VALID) {
693 if ((pcb->pcb_flags & PCB_FPU) != PCB_FPU) {
694 critical_enter();
695 enable_fpu(td);
696 critical_exit();
697 }
698 memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double));
699 memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double));
700 }
701
702 /* XXX Altivec context? */
703
704 return (0);
705}
706
707void
708cpu_boot(int howto)
709{
710}
711
712void
713cpu_initclocks(void)
714{
715
716 decr_tc_init();
717}
718
719/* Get current clock frequency for the given cpu id. */
720int
721cpu_est_clockrate(int cpu_id, uint64_t *rate)
722{
723
724 return (ENXIO);
725}
726
727/*
728 * Shutdown the CPU as much as possible.
729 */
730void
731cpu_halt(void)
732{
733
734 OF_exit();
735}
736
737void
738cpu_idle(void)
739{
740 /* TODO: Insert code to halt (until next interrupt) */
741
742#ifdef INVARIANTS
743 if ((mfmsr() & PSL_EE) != PSL_EE) {
744 struct thread *td = curthread;
745 printf("td msr %x\n", td->td_md.md_saved_msr);
746 panic("ints disabled in idleproc!");
747 }
748#endif
749}
750
751/*
752 * Set set up registers on exec.
753 */
754void
755exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
756{
757 struct trapframe *tf;
758 struct ps_strings arginfo;
759
760 tf = trapframe(td);
761 bzero(tf, sizeof *tf);
762 tf->fixreg[1] = -roundup(-stack + 8, 16);
763
764 /*
765 * XXX Machine-independent code has already copied arguments and
766 * XXX environment to userland. Get them back here.
767 */
768 (void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo));
769
770 /*
771 * Set up arguments for _start():
772 * _start(argc, argv, envp, obj, cleanup, ps_strings);
773 *
774 * Notes:
775 * - obj and cleanup are the auxilliary and termination
776 * vectors. They are fixed up by ld.elf_so.
777 * - ps_strings is a NetBSD extention, and will be
778 * ignored by executables which are strictly
779 * compliant with the SVR4 ABI.
780 *
781 * XXX We have to set both regs and retval here due to different
782 * XXX calling convention in trap.c and init_main.c.
783 */
784 /*
785 * XXX PG: these get overwritten in the syscall return code.
786 * execve() should return EJUSTRETURN, like it does on NetBSD.
787 * Emulate by setting the syscall return value cells. The
788 * registers still have to be set for init's fork trampoline.
789 */
790 td->td_retval[0] = arginfo.ps_nargvstr;
791 td->td_retval[1] = (register_t)arginfo.ps_argvstr;
792 tf->fixreg[3] = arginfo.ps_nargvstr;
793 tf->fixreg[4] = (register_t)arginfo.ps_argvstr;
794 tf->fixreg[5] = (register_t)arginfo.ps_envstr;
795 tf->fixreg[6] = 0; /* auxillary vector */
796 tf->fixreg[7] = 0; /* termination vector */
797 tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */
798
799 tf->srr0 = entry;
800 tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
801 td->td_pcb->pcb_flags = 0;
802}
803
804int
805fill_regs(struct thread *td, struct reg *regs)
806{
807 struct trapframe *tf;
808
809 tf = td->td_frame;
810 memcpy(regs, tf, sizeof(struct reg));
811
812 return (0);
813}
814
815int
816fill_dbregs(struct thread *td, struct dbreg *dbregs)
817{
818 /* No debug registers on PowerPC */
819 return (ENOSYS);
820}
821
822int
823fill_fpregs(struct thread *td, struct fpreg *fpregs)
824{
825 struct pcb *pcb;
826
827 pcb = td->td_pcb;
828
829 if ((pcb->pcb_flags & PCB_FPU) == 0)
830 memset(fpregs, 0, sizeof(struct fpreg));
831 else
832 memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg));
833
834 return (0);
835}
836
837int
838set_regs(struct thread *td, struct reg *regs)
839{
840 struct trapframe *tf;
841
842 tf = td->td_frame;
843 memcpy(tf, regs, sizeof(struct reg));
844
845 return (0);
846}
847
848int
849set_dbregs(struct thread *td, struct dbreg *dbregs)
850{
851 /* No debug registers on PowerPC */
852 return (ENOSYS);
853}
854
855int
856set_fpregs(struct thread *td, struct fpreg *fpregs)
857{
858 struct pcb *pcb;
859
860 pcb = td->td_pcb;
861 if ((pcb->pcb_flags & PCB_FPU) == 0)
862 enable_fpu(td);
863 memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg));
864
865 return (0);
866}
867
868int
869ptrace_set_pc(struct thread *td, unsigned long addr)
870{
871 struct trapframe *tf;
872
873 tf = td->td_frame;
874 tf->srr0 = (register_t)addr;
875
876 return (0);
877}
878
879int
880ptrace_single_step(struct thread *td)
881{
882 struct trapframe *tf;
883
884 tf = td->td_frame;
885 tf->srr1 |= PSL_SE;
886
887 return (0);
888}
889
890int
891ptrace_clear_single_step(struct thread *td)
892{
893 struct trapframe *tf;
894
895 tf = td->td_frame;
896 tf->srr1 &= ~PSL_SE;
897
898 return (0);
899}
900
901void
902kdb_cpu_clear_singlestep(void)
903{
904
905 kdb_frame->srr1 &= ~PSL_SE;
906}
907
908void
909kdb_cpu_set_singlestep(void)
910{
911
912 kdb_frame->srr1 |= PSL_SE;
913}
914
900/*
901 * Initialise a struct pcpu.
902 */
903void
904cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
905{
906
907}
908
909void
910spinlock_enter(void)
911{
912 struct thread *td;
913
914 td = curthread;
915 if (td->td_md.md_spinlock_count == 0)
916 td->td_md.md_saved_msr = intr_disable();
917 td->td_md.md_spinlock_count++;
918 critical_enter();
919}
920
921void
922spinlock_exit(void)
923{
924 struct thread *td;
925
926 td = curthread;
927 critical_exit();
928 td->td_md.md_spinlock_count--;
929 if (td->td_md.md_spinlock_count == 0)
930 intr_restore(td->td_md.md_saved_msr);
931}
932
933/*
934 * kcopy(const void *src, void *dst, size_t len);
935 *
936 * Copy len bytes from src to dst, aborting if we encounter a fatal
937 * page fault.
938 *
939 * kcopy() _must_ save and restore the old fault handler since it is
940 * called by uiomove(), which may be in the path of servicing a non-fatal
941 * page fault.
942 */
943int
944kcopy(const void *src, void *dst, size_t len)
945{
946 struct thread *td;
947 faultbuf env, *oldfault;
948 int rv;
949
950 td = PCPU_GET(curthread);
951 oldfault = td->td_pcb->pcb_onfault;
952 if ((rv = setfault(env)) != 0) {
953 td->td_pcb->pcb_onfault = oldfault;
954 return rv;
955 }
956
957 memcpy(dst, src, len);
958
959 td->td_pcb->pcb_onfault = oldfault;
960 return (0);
961}
962
963void
964asm_panic(char *pstr)
965{
966 panic(pstr);
967}
968
969int db_trap_glue(struct trapframe *); /* Called from trap_subr.S */
970
971int
972db_trap_glue(struct trapframe *frame)
973{
974 if (!(frame->srr1 & PSL_PR)
975 && (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC
976 || (frame->exc == EXC_PGM
977 && (frame->srr1 & 0x20000))
978 || frame->exc == EXC_BPT
979 || frame->exc == EXC_DSI)) {
980 int type = frame->exc;
981 if (type == EXC_PGM && (frame->srr1 & 0x20000)) {
982 type = T_BREAKPOINT;
983 }
984 return (kdb_trap(type, 0, frame));
985 }
986
987 return (0);
988}
915/*
916 * Initialise a struct pcpu.
917 */
918void
919cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
920{
921
922}
923
924void
925spinlock_enter(void)
926{
927 struct thread *td;
928
929 td = curthread;
930 if (td->td_md.md_spinlock_count == 0)
931 td->td_md.md_saved_msr = intr_disable();
932 td->td_md.md_spinlock_count++;
933 critical_enter();
934}
935
936void
937spinlock_exit(void)
938{
939 struct thread *td;
940
941 td = curthread;
942 critical_exit();
943 td->td_md.md_spinlock_count--;
944 if (td->td_md.md_spinlock_count == 0)
945 intr_restore(td->td_md.md_saved_msr);
946}
947
948/*
949 * kcopy(const void *src, void *dst, size_t len);
950 *
951 * Copy len bytes from src to dst, aborting if we encounter a fatal
952 * page fault.
953 *
954 * kcopy() _must_ save and restore the old fault handler since it is
955 * called by uiomove(), which may be in the path of servicing a non-fatal
956 * page fault.
957 */
958int
959kcopy(const void *src, void *dst, size_t len)
960{
961 struct thread *td;
962 faultbuf env, *oldfault;
963 int rv;
964
965 td = PCPU_GET(curthread);
966 oldfault = td->td_pcb->pcb_onfault;
967 if ((rv = setfault(env)) != 0) {
968 td->td_pcb->pcb_onfault = oldfault;
969 return rv;
970 }
971
972 memcpy(dst, src, len);
973
974 td->td_pcb->pcb_onfault = oldfault;
975 return (0);
976}
977
978void
979asm_panic(char *pstr)
980{
981 panic(pstr);
982}
983
984int db_trap_glue(struct trapframe *); /* Called from trap_subr.S */
985
986int
987db_trap_glue(struct trapframe *frame)
988{
989 if (!(frame->srr1 & PSL_PR)
990 && (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC
991 || (frame->exc == EXC_PGM
992 && (frame->srr1 & 0x20000))
993 || frame->exc == EXC_BPT
994 || frame->exc == EXC_DSI)) {
995 int type = frame->exc;
996 if (type == EXC_PGM && (frame->srr1 & 0x20000)) {
997 type = T_BREAKPOINT;
998 }
999 return (kdb_trap(type, 0, frame));
1000 }
1001
1002 return (0);
1003}