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: releng/5.1/sys/powerpc/powerpc/machdep.c 114983 2003-05-13 20:36:02Z jhb $");
59
60 #include "opt_ddb.h"
61 #include "opt_compat.h"
62 #include "opt_msgbuf.h"
63
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/eventhandler.h>
67 #include <sys/imgact.h>
68 #include <sys/sysproto.h>
69 #include <sys/lock.h>
70 #include <sys/mutex.h>
71 #include <sys/ktr.h>
72 #include <sys/signalvar.h>
73 #include <sys/kernel.h>
74 #include <sys/proc.h>
75 #include <sys/malloc.h>
76 #include <sys/reboot.h>
77 #include <sys/bio.h>
78 #include <sys/buf.h>
79 #include <sys/bus.h>
80 #include <sys/mbuf.h>
81 #include <sys/vmmeter.h>
82 #include <sys/msgbuf.h>
83 #include <sys/exec.h>
84 #include <sys/sysctl.h>
85 #include <sys/uio.h>
86 #include <sys/linker.h>
87 #include <sys/cons.h>
88 #include <sys/ucontext.h>
89 #include <sys/sysent.h>
90 #include <net/netisr.h>
91 #include <vm/vm.h>
92 #include <vm/vm_kern.h>
93 #include <vm/vm_page.h>
94 #include <vm/vm_map.h>
95 #include <vm/vm_extern.h>
96 #include <vm/vm_object.h>
97 #include <vm/vm_pager.h>
98 #include <sys/user.h>
99 #include <sys/ptrace.h>
100 #include <machine/bat.h>
101 #include <machine/clock.h>
102 #include <machine/md_var.h>
103 #include <machine/metadata.h>
104 #include <machine/reg.h>
105 #include <machine/fpu.h>
106 #include <machine/vmparam.h>
107 #include <machine/elf.h>
108 #include <machine/trap.h>
109 #include <machine/powerpc.h>
110 #include <dev/ofw/openfirm.h>
111 #include <ddb/ddb.h>
112 #include <sys/vnode.h>
113 #include <machine/sigframe.h>
114
115 int cold = 1;
116
117 char pcpu0[PAGE_SIZE];
118 char uarea0[UAREA_PAGES * PAGE_SIZE];
119 struct trapframe frame0;
120
121 vm_offset_t kstack0;
122 vm_offset_t kstack0_phys;
123
124 char machine[] = "powerpc";
125 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
126
127 static char model[128];
128 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, "");
129
130 static int cacheline_size = CACHELINESIZE;
131 SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size,
132 CTLFLAG_RD, &cacheline_size, 0, "");
133
134 char bootpath[256];
135
136 #ifdef DDB
137 /* start and end of kernel symbol table */
138 void *ksym_start, *ksym_end;
139 #endif /* DDB */
140
141 static void cpu_startup(void *);
142 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
143
144 void powerpc_init(u_int, u_int, u_int, void *);
145
146 int save_ofw_mapping(void);
147 int restore_ofw_mapping(void);
148
149 void install_extint(void (*)(void));
150
151 int setfault(faultbuf); /* defined in locore.S */
152
153 long Maxmem = 0;
154
155 struct pmap ofw_pmap;
156 extern int ofmsr;
157
158 struct bat battable[16];
159
160 struct kva_md_info kmi;
161
162 static void
163 powerpc_ofw_shutdown(void *junk, int howto)
164 {
165 if (howto & RB_HALT) {
166 OF_exit();
167 }
168 }
169
170 static void
171 cpu_startup(void *dummy)
172 {
173
174 /*
175 * Initialise the decrementer-based clock.
176 */
177 decr_init();
178
179 /*
180 * Good {morning,afternoon,evening,night}.
181 */
182 cpu_setup(PCPU_GET(cpuid));
183
184 /* startrtclock(); */
185 #ifdef PERFMON
186 perfmon_init();
187 #endif
188 printf("real memory = %ld (%ld MB)\n", ptoa(Maxmem),
189 ptoa(Maxmem) / 1048576);
190
191 /*
192 * Display any holes after the first chunk of extended memory.
193 */
194 if (bootverbose) {
195 int indx;
196
197 printf("Physical memory chunk(s):\n");
198 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
199 int size1 = phys_avail[indx + 1] - phys_avail[indx];
200
201 printf("0x%08x - 0x%08x, %d bytes (%d pages)\n",
202 phys_avail[indx], phys_avail[indx + 1] - 1, size1,
203 size1 / PAGE_SIZE);
204 }
205 }
206
207 vm_ksubmap_init(&kmi);
208
209 printf("avail memory = %ld (%ld MB)\n", ptoa(cnt.v_free_count),
210 ptoa(cnt.v_free_count) / 1048576);
211
212 /*
213 * Set up buffers, so they can be used to read disk labels.
214 */
215 bufinit();
216 vm_pager_bufferinit();
217
218 EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0,
219 SHUTDOWN_PRI_LAST);
220
221 #ifdef SMP
222 /*
223 * OK, enough kmem_alloc/malloc state should be up, lets get on with it!
224 */
225 mp_start(); /* fire up the secondaries */
226 mp_announce();
227 #endif /* SMP */
228 }
229
230 extern char kernel_text[], _end[];
231
232 extern void *trapcode, *trapsize;
233 extern void *alitrap, *alisize;
234 extern void *dsitrap, *dsisize;
235 extern void *isitrap, *isisize;
236 extern void *decrint, *decrsize;
237 extern void *tlbimiss, *tlbimsize;
238 extern void *tlbdlmiss, *tlbdlmsize;
239 extern void *tlbdsmiss, *tlbdsmsize;
240 extern void *extint, *extsize;
241
242 #if 0 /* XXX: interrupt handler. We'll get to this later */
243 extern void ext_intr(void);
244 #endif
245
246 #ifdef DDB
247 extern ddblow, ddbsize;
248 #endif
249 #ifdef IPKDB
250 extern ipkdblow, ipkdbsize;
251 #endif
252
253 void
254 powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
255 {
256 struct pcpu *pc;
257 vm_offset_t end, off;
258 void *kmdp;
259
260 end = 0;
261 kmdp = NULL;
262
263 /*
264 * Parse metadata if present and fetch parameters. Must be done
265 * before console is inited so cninit gets the right value of
266 * boothowto.
267 */
268 if (mdp != NULL) {
269 preload_metadata = mdp;
270 kmdp = preload_search_by_type("elf kernel");
271 if (kmdp != NULL) {
272 boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
273 kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
274 end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
275 }
276 }
277
278 /*
279 * Initialize the console before printing anything.
280 */
281 cninit();
282
283 /*
284 * Complain if there is no metadata.
285 */
286 if (mdp == NULL || kmdp == NULL) {
287 printf("powerpc_init: no loader metadata.\n");
288 }
289
290 #ifdef DDB
291 kdb_init();
292 #endif
293 /*
294 * XXX: Initialize the interrupt tables.
295 */
296 bcopy(&trapcode, (void *)EXC_MCHK, (size_t)&trapsize);
297 bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
298 bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize);
299 bcopy(&trapcode, (void *)EXC_EXI, (size_t)&trapsize);
300 bcopy(&trapcode, (void *)EXC_ALI, (size_t)&trapsize);
301 bcopy(&trapcode, (void *)EXC_PGM, (size_t)&trapsize);
302 bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize);
303 bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize);
304 bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize);
305 bcopy(&trapcode, (void *)EXC_TRC, (size_t)&trapsize);
306 __syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD);
307
308 /*
309 * Start initializing proc0 and thread0.
310 */
311 proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
312 proc0.p_uarea = (struct user *)uarea0;
313 proc0.p_stats = &proc0.p_uarea->u_stats;
314 thread0.td_frame = &frame0;
315
316 /*
317 * Set up per-cpu data.
318 */
319 pc = (struct pcpu *)(pcpu0 + PAGE_SIZE) - 1;
320 pcpu_init(pc, 0, sizeof(struct pcpu));
321 pc->pc_curthread = &thread0;
322 pc->pc_curpcb = thread0.td_pcb;
323 pc->pc_cpuid = 0;
324 /* pc->pc_mid = mid; */
325
326 __asm __volatile("mtsprg 0, %0" :: "r"(pc));
327
328 mutex_init();
329
330 /*
331 * Make sure translation has been enabled
332 */
333 mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI);
334
335 /*
336 * Initialise virtual memory.
337 */
338 pmap_bootstrap(startkernel, endkernel);
339
340 /*
341 * Initialize tunables.
342 */
343 init_param1();
344 init_param2(physmem);
345
346 /*
347 * Finish setting up thread0.
348 */
349 thread0.td_kstack = kstack0;
350 thread0.td_pcb = (struct pcb *)
351 (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
352
353 /*
354 * Map and initialise the message buffer.
355 */
356 for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
357 pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off);
358 msgbufinit(msgbufp, MSGBUF_SIZE);
359 }
360
361 void
362 bzero(void *buf, size_t len)
363 {
364 caddr_t p;
365
366 p = buf;
367
368 while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) {
369 *p++ = 0;
370 len--;
371 }
372
373 while (len >= sizeof(u_long) * 8) {
374 *(u_long*) p = 0;
375 *((u_long*) p + 1) = 0;
376 *((u_long*) p + 2) = 0;
377 *((u_long*) p + 3) = 0;
378 len -= sizeof(u_long) * 8;
379 *((u_long*) p + 4) = 0;
380 *((u_long*) p + 5) = 0;
381 *((u_long*) p + 6) = 0;
382 *((u_long*) p + 7) = 0;
383 p += sizeof(u_long) * 8;
384 }
385
386 while (len >= sizeof(u_long)) {
387 *(u_long*) p = 0;
388 len -= sizeof(u_long);
389 p += sizeof(u_long);
390 }
391
392 while (len) {
393 *p++ = 0;
394 len--;
395 }
396 }
397
398 void
399 sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
400 {
401 struct trapframe *tf;
402 struct sigframe *sfp;
403 struct sigacts *psp;
404 struct sigframe sf;
405 struct thread *td;
406 struct proc *p;
407 int oonstack, rndfsize;
408
409 td = curthread;
410 p = td->td_proc;
411 PROC_LOCK_ASSERT(p, MA_OWNED);
412 psp = p->p_sigacts;
413 mtx_assert(&psp->ps_mtx, MA_OWNED);
414 tf = td->td_frame;
415 oonstack = sigonstack(tf->fixreg[1]);
416
417 rndfsize = ((sizeof(sf) + 15) / 16) * 16;
418
419 CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
420 catcher, sig);
421
422 /*
423 * Save user context
424 */
425 memset(&sf, 0, sizeof(sf));
426 sf.sf_uc.uc_sigmask = *mask;
427 sf.sf_uc.uc_stack = p->p_sigstk;
428 sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
429 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
430
431 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
432 memcpy(&sf.sf_uc.uc_mcontext.mc_frame, tf, sizeof(struct trapframe));
433
434 /*
435 * Allocate and validate space for the signal handler context.
436 */
437 if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack &&
438 SIGISMEMBER(psp->ps_sigonstack, sig)) {
439 sfp = (struct sigframe *)((caddr_t)p->p_sigstk.ss_sp +
440 p->p_sigstk.ss_size - rndfsize);
441 } else {
442 sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize);
443 }
444
445 /*
446 * Translate the signal if appropriate (Linux emu ?)
447 */
448 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
449 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
450
451 /*
452 * Save the floating-point state, if necessary, then copy it.
453 */
454 /* XXX */
455
456 /*
457 * Set up the registers to return to sigcode.
458 *
459 * r1/sp - sigframe ptr
460 * lr - sig function, dispatched to by blrl in trampoline
461 * r3 - sig number
462 * r4 - SIGINFO ? &siginfo : exception code
463 * r5 - user context
464 * srr0 - trampoline function addr
465 */
466 tf->lr = (register_t)catcher;
467 tf->fixreg[1] = (register_t)sfp;
468 tf->fixreg[FIRSTARG] = sig;
469 tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc;
470 if (SIGISMEMBER(psp->ps_siginfo, sig)) {
471 /*
472 * Signal handler installed with SA_SIGINFO.
473 */
474 tf->fixreg[FIRSTARG+1] = (register_t)&sfp->sf_si;
475
476 /*
477 * Fill siginfo structure.
478 */
479 sf.sf_si.si_signo = sig;
480 sf.sf_si.si_code = code;
481 sf.sf_si.si_addr = (void *)tf->srr0;
482 } else {
483 /* Old FreeBSD-style arguments. */
484 tf->fixreg[FIRSTARG+1] = code;
485 }
486 mtx_unlock(&psp->ps_mtx);
487 PROC_UNLOCK(p);
488
489 tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
490
491 /*
492 * copy the frame out to userland.
493 */
494 if (copyout((caddr_t)&sf, (caddr_t)sfp, sizeof(sf)) != 0) {
495 /*
496 * Process has trashed its stack. Kill it.
497 */
498 CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp);
499 PROC_LOCK(p);
500 sigexit(td, SIGILL);
501 }
502
503 CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td,
504 tf->srr0, tf->fixreg[1]);
505
506 PROC_LOCK(p);
507 mtx_lock(&psp->ps_mtx);
508 }
509
510 int
511 sigreturn(struct thread *td, struct sigreturn_args *uap)
512 {
513 struct trapframe *tf;
514 struct proc *p;
515 ucontext_t uc;
516
517 CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
518
519 if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
520 CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
521 return (EFAULT);
522 }
523
524 /*
525 * Don't let the user set privileged MSR bits
526 */
527 tf = td->td_frame;
528 if ((uc.uc_mcontext.mc_frame.srr1 & PSL_USERSTATIC) !=
529 (tf->srr1 & PSL_USERSTATIC)) {
530 return (EINVAL);
531 }
532
533 /*
534 * Restore the user-supplied context
535 */
536 memcpy(tf, &uc.uc_mcontext.mc_frame, sizeof(struct trapframe));
537
538 p = td->td_proc;
539 PROC_LOCK(p);
540 td->td_sigmask = uc.uc_sigmask;
541 SIG_CANTMASK(td->td_sigmask);
542 signotify(td);
543 PROC_UNLOCK(p);
544
545 /*
546 * Restore FP state
547 */
548 /* XXX */
549
550 CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
551 td, tf->srr0, tf->fixreg[1]);
552
553 return (EJUSTRETURN);
554 }
555
556 #ifdef COMPAT_FREEBSD4
557 int
558 freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
559 {
560
561 return sigreturn(td, (struct sigreturn_args *)uap);
562 }
563 #endif
564
565 int
566 get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
567 {
568
569 return (ENOSYS);
570 }
571
572 int
573 set_mcontext(struct thread *td, const mcontext_t *mcp)
574 {
575
576 return (ENOSYS);
577 }
578
579 void
580 cpu_boot(int howto)
581 {
582 }
583
584 /*
585 * Shutdown the CPU as much as possible.
586 */
587 void
588 cpu_halt(void)
589 {
590
591 OF_exit();
592 }
593
594 /*
595 * Set set up registers on exec.
596 */
597 void
598 exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
599 {
600 struct trapframe *tf;
601 struct ps_strings arginfo;
602
603 tf = trapframe(td);
604 bzero(tf, sizeof *tf);
605 tf->fixreg[1] = -roundup(-stack + 8, 16);
606
607 /*
608 * XXX Machine-independent code has already copied arguments and
609 * XXX environment to userland. Get them back here.
610 */
611 (void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo));
612
613 /*
614 * Set up arguments for _start():
615 * _start(argc, argv, envp, obj, cleanup, ps_strings);
616 *
617 * Notes:
618 * - obj and cleanup are the auxilliary and termination
619 * vectors. They are fixed up by ld.elf_so.
620 * - ps_strings is a NetBSD extention, and will be
621 * ignored by executables which are strictly
622 * compliant with the SVR4 ABI.
623 *
624 * XXX We have to set both regs and retval here due to different
625 * XXX calling convention in trap.c and init_main.c.
626 */
627 /*
628 * XXX PG: these get overwritten in the syscall return code.
629 * execve() should return EJUSTRETURN, like it does on NetBSD.
630 * Emulate by setting the syscall return value cells. The
631 * registers still have to be set for init's fork trampoline.
632 */
633 td->td_retval[0] = arginfo.ps_nargvstr;
634 td->td_retval[1] = (register_t)arginfo.ps_argvstr;
635 tf->fixreg[3] = arginfo.ps_nargvstr;
636 tf->fixreg[4] = (register_t)arginfo.ps_argvstr;
637 tf->fixreg[5] = (register_t)arginfo.ps_envstr;
638 tf->fixreg[6] = 0; /* auxillary vector */
639 tf->fixreg[7] = 0; /* termination vector */
640 tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */
641
642 tf->srr0 = entry;
643 tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
644 td->td_pcb->pcb_flags = 0;
645 }
646
647 #if !defined(DDB)
648 void
649 Debugger(const char *msg)
650 {
651
652 printf("Debugger(\"%s\") called.\n", msg);
653 }
654 #endif /* !defined(DDB) */
655
656 /* XXX: dummy {fill,set}_[fp]regs */
657 int
658 fill_regs(struct thread *td, struct reg *regs)
659 {
660
661 return (ENOSYS);
662 }
663
664 int
665 fill_dbregs(struct thread *td, struct dbreg *dbregs)
666 {
667
668 return (ENOSYS);
669 }
670
671 int
672 fill_fpregs(struct thread *td, struct fpreg *fpregs)
673 {
674
675 return (ENOSYS);
676 }
677
678 int
679 set_regs(struct thread *td, struct reg *regs)
680 {
681
682 return (ENOSYS);
683 }
684
685 int
686 set_dbregs(struct thread *td, struct dbreg *dbregs)
687 {
688
689 return (ENOSYS);
690 }
691
692 int
693 set_fpregs(struct thread *td, struct fpreg *fpregs)
694 {
695
696 return (ENOSYS);
697 }
698
699 int
700 ptrace_set_pc(struct thread *td, unsigned long addr)
701 {
702
703 /* XXX: coming soon... */
704 return (ENOSYS);
705 }
706
707 int
708 ptrace_single_step(struct thread *td)
709 {
710
711 /* XXX: coming soon... */
712 return (ENOSYS);
713 }
714
715 /*
716 * Initialise a struct pcpu.
717 */
718 void
719 cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
720 {
721
722 pcpu->pc_current_asngen = 1;
723 }
724
725 /*
726 * kcopy(const void *src, void *dst, size_t len);
727 *
728 * Copy len bytes from src to dst, aborting if we encounter a fatal
729 * page fault.
730 *
731 * kcopy() _must_ save and restore the old fault handler since it is
732 * called by uiomove(), which may be in the path of servicing a non-fatal
733 * page fault.
734 */
735 int
736 kcopy(const void *src, void *dst, size_t len)
737 {
738 struct thread *td;
739 faultbuf env, *oldfault;
740 int rv;
741
742 td = PCPU_GET(curthread);
743 oldfault = td->td_pcb->pcb_onfault;
744 if ((rv = setfault(env)) != 0) {
745 td->td_pcb->pcb_onfault = oldfault;
746 return rv;
747 }
748
749 memcpy(dst, src, len);
750
751 td->td_pcb->pcb_onfault = oldfault;
752 return (0);
753 }
754
755
756 intptr_t
757 casuptr(intptr_t *p, intptr_t old, intptr_t new)
758 {
759 return (-1);
760 }
761
Cache object: e48e1a26967bea72ac66df4d9f2162b4
|