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