machdep_kdb.c revision 141378
1129198Scognet/*	$NetBSD: arm32_machdep.c,v 1.44 2004/03/24 15:34:47 atatat Exp $	*/
2129198Scognet
3139735Simp/*-
4129198Scognet * Copyright (c) 2004 Olivier Houchard
5129198Scognet * Copyright (c) 1994-1998 Mark Brinicombe.
6129198Scognet * Copyright (c) 1994 Brini.
7129198Scognet * All rights reserved.
8129198Scognet *
9129198Scognet * This code is derived from software written for Brini by Mark Brinicombe
10129198Scognet *
11129198Scognet * Redistribution and use in source and binary forms, with or without
12129198Scognet * modification, are permitted provided that the following conditions
13129198Scognet * are met:
14129198Scognet * 1. Redistributions of source code must retain the above copyright
15129198Scognet *    notice, this list of conditions and the following disclaimer.
16129198Scognet * 2. Redistributions in binary form must reproduce the above copyright
17129198Scognet *    notice, this list of conditions and the following disclaimer in the
18129198Scognet *    documentation and/or other materials provided with the distribution.
19129198Scognet * 3. All advertising materials mentioning features or use of this software
20129198Scognet *    must display the following acknowledgement:
21129198Scognet *	This product includes software developed by Mark Brinicombe
22129198Scognet *	for the NetBSD Project.
23129198Scognet * 4. The name of the company nor the name of the author may be used to
24129198Scognet *    endorse or promote products derived from this software without specific
25129198Scognet *    prior written permission.
26129198Scognet *
27129198Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
28129198Scognet * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29129198Scognet * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30129198Scognet * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
31129198Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32129198Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33129198Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37129198Scognet * SUCH DAMAGE.
38129198Scognet *
39129198Scognet * Machine dependant functions for kernel setup
40129198Scognet *
41129198Scognet * Created      : 17/09/94
42129198Scognet * Updated	: 18/04/01 updated for new wscons
43129198Scognet */
44129198Scognet
45129198Scognet#include "opt_compat.h"
46129198Scognet#include <sys/cdefs.h>
47129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/machdep.c 141378 2005-02-06 01:55:08Z njl $");
48129198Scognet
49129198Scognet#include <sys/param.h>
50141378Snjl#include <sys/proc.h>
51129198Scognet#include <sys/systm.h>
52141249Snjl#include <sys/bio.h>
53141249Snjl#include <sys/buf.h>
54141249Snjl#include <sys/bus.h>
55141378Snjl#include <sys/cons.h>
56141237Snjl#include <sys/cpu.h>
57141378Snjl#include <sys/exec.h>
58129198Scognet#include <sys/imgact.h>
59129198Scognet#include <sys/kernel.h>
60129198Scognet#include <sys/linker.h>
61129198Scognet#include <sys/lock.h>
62129198Scognet#include <sys/malloc.h>
63129198Scognet#include <sys/mutex.h>
64129198Scognet#include <sys/pcpu.h>
65129198Scognet#include <sys/ptrace.h>
66141378Snjl#include <sys/signalvar.h>
67135653Scognet#include <sys/sysent.h>
68141378Snjl#include <sys/sysproto.h>
69140001Scognet#include <sys/uio.h>
70129198Scognet
71129198Scognet#include <vm/pmap.h>
72129198Scognet#include <vm/vm.h>
73141378Snjl#include <vm/vm_map.h>
74129198Scognet#include <vm/vm_object.h>
75129198Scognet#include <vm/vm_page.h>
76129198Scognet#include <vm/vm_pager.h>
77129198Scognet#include <vm/vnode_pager.h>
78141378Snjl
79141378Snjl#include <machine/armreg.h>
80141378Snjl#include <machine/cpu.h>
81141378Snjl#include <machine/machdep.h>
82141378Snjl#include <machine/md_var.h>
83141378Snjl#include <machine/metadata.h>
84141378Snjl#include <machine/pcb.h>
85129198Scognet#include <machine/pmap.h>
86141378Snjl#include <machine/reg.h>
87141378Snjl#include <machine/trap.h>
88141378Snjl#include <machine/undefined.h>
89129198Scognet#include <machine/vmparam.h>
90129198Scognet
91129198Scognet#define MDROOT_ADDR 0xd0400000
92129198Scognet
93129198Scognetuint32_t cpu_reset_address = 0;
94129198Scognetint cold = 1;
95129198Scognetvm_offset_t vector_page;
96129198Scognet
97129198Scognetvoid
98129198Scognetsendsig(catcher, sig, mask, code)
99129198Scognet	sig_t catcher;
100129198Scognet	int sig;
101129198Scognet	sigset_t *mask;
102129198Scognet	u_long code;
103129198Scognet{
104129198Scognet	struct thread *td = curthread;
105135653Scognet	struct proc *p = td->td_proc;
106129198Scognet	struct trapframe *tf = td->td_frame;
107129198Scognet	struct sigframe *fp, frame;
108129198Scognet	struct sigacts *psp = td->td_proc->p_sigacts;
109129198Scognet	int onstack;
110129198Scognet
111137215Scognet	onstack = sigonstack(td->td_frame->tf_usr_sp);
112137215Scognet
113137215Scognet	if ((td->td_flags & TDP_ALTSTACK) &&
114137215Scognet	    !(onstack) &&
115137215Scognet	    SIGISMEMBER(td->td_proc->p_sigacts->ps_sigonstack, sig)) {
116137215Scognet		fp = (void*)(td->td_sigstk.ss_sp + td->td_sigstk.ss_size);
117137215Scognet		td->td_sigstk.ss_flags |= SS_ONSTACK;
118137215Scognet	} else
119137215Scognet		fp = (void*)td->td_frame->tf_usr_sp;
120137215Scognet
121129198Scognet	/* make room on the stack */
122129198Scognet	fp--;
123129198Scognet
124129198Scognet	/* make the stack aligned */
125135653Scognet	fp = (struct sigframe *)STACKALIGN(fp);
126129198Scognet	/* Populate the siginfo frame. */
127129198Scognet	frame.sf_si.si_signo = sig;
128129198Scognet	frame.sf_si.si_code = code;
129129198Scognet	frame.sf_uc.uc_sigmask = *mask;
130129198Scognet	frame.sf_uc.uc_link = NULL;
131137215Scognet	frame.sf_uc.uc_flags = (td->td_pflags & TDP_ALTSTACK )
132137215Scognet	    ? ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE;
133135653Scognet	frame.sf_uc.uc_stack = td->td_sigstk;
134129198Scognet	memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack));
135137215Scognet	get_mcontext(td, &frame.sf_uc.uc_mcontext, 0);
136129198Scognet	PROC_UNLOCK(td->td_proc);
137129198Scognet	mtx_unlock(&psp->ps_mtx);
138129198Scognet	if (copyout(&frame, (void*)fp, sizeof(frame)) != 0)
139129198Scognet		sigexit(td, SIGILL);
140129198Scognet	/*
141129198Scognet	 * Build context to run handler in.  We invoke the handler
142129198Scognet	 * directly, only returning via the trampoline.  Note the
143129198Scognet	 * trampoline version numbers are coordinated with machine-
144129198Scognet	 * dependent code in libc.
145129198Scognet	 */
146129198Scognet
147129198Scognet	tf->tf_r0 = sig;
148129198Scognet	tf->tf_r1 = (int)&fp->sf_si;
149129198Scognet	tf->tf_r2 = (int)&fp->sf_uc;
150129198Scognet
151129198Scognet	/* the trampoline uses r5 as the uc address */
152129198Scognet	tf->tf_r5 = (int)&fp->sf_uc;
153129198Scognet	tf->tf_pc = (int)catcher;
154129198Scognet	tf->tf_usr_sp = (int)fp;
155135653Scognet	tf->tf_usr_lr = (int)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
156129198Scognet	PROC_LOCK(td->td_proc);
157129198Scognet	mtx_lock(&psp->ps_mtx);
158129198Scognet}
159129198Scognet
160129198Scognetstruct kva_md_info kmi;
161129198Scognet
162129198Scognet/*
163129198Scognet * arm32_vector_init:
164129198Scognet *
165129198Scognet *	Initialize the vector page, and select whether or not to
166129198Scognet *	relocate the vectors.
167129198Scognet *
168129198Scognet *	NOTE: We expect the vector page to be mapped at its expected
169129198Scognet *	destination.
170129198Scognet */
171129198Scognet
172129198Scognetextern unsigned int page0[], page0_data[];
173129198Scognetvoid
174129198Scognetarm_vector_init(vm_offset_t va, int which)
175129198Scognet{
176129198Scognet	unsigned int *vectors = (int *) va;
177129198Scognet	unsigned int *vectors_data = vectors + (page0_data - page0);
178129198Scognet	int vec;
179129198Scognet
180129198Scognet	/*
181129198Scognet	 * Loop through the vectors we're taking over, and copy the
182129198Scognet	 * vector's insn and data word.
183129198Scognet	 */
184129198Scognet	for (vec = 0; vec < ARM_NVEC; vec++) {
185129198Scognet		if ((which & (1 << vec)) == 0) {
186129198Scognet			/* Don't want to take over this vector. */
187129198Scognet			continue;
188129198Scognet		}
189129198Scognet		vectors[vec] = page0[vec];
190129198Scognet		vectors_data[vec] = page0_data[vec];
191129198Scognet	}
192129198Scognet
193129198Scognet	/* Now sync the vectors. */
194129198Scognet	cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int));
195129198Scognet
196129198Scognet	vector_page = va;
197129198Scognet
198129198Scognet	if (va == ARM_VECTORS_HIGH) {
199129198Scognet		/*
200129198Scognet		 * Assume the MD caller knows what it's doing here, and
201129198Scognet		 * really does want the vector page relocated.
202129198Scognet		 *
203129198Scognet		 * Note: This has to be done here (and not just in
204129198Scognet		 * cpu_setup()) because the vector page needs to be
205129198Scognet		 * accessible *before* cpu_startup() is called.
206129198Scognet		 * Think ddb(9) ...
207129198Scognet		 *
208129198Scognet		 * NOTE: If the CPU control register is not readable,
209129198Scognet		 * this will totally fail!  We'll just assume that
210129198Scognet		 * any system that has high vector support has a
211129198Scognet		 * readable CPU control register, for now.  If we
212129198Scognet		 * ever encounter one that does not, we'll have to
213129198Scognet		 * rethink this.
214129198Scognet		 */
215129198Scognet		cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC);
216129198Scognet	}
217129198Scognet}
218129198Scognet
219129198Scognetstatic void
220129198Scognetcpu_startup(void *dummy)
221129198Scognet{
222129198Scognet	struct pcb *pcb = thread0.td_pcb;
223137215Scognet
224129198Scognet	vm_ksubmap_init(&kmi);
225129198Scognet	bufinit();
226129198Scognet	vm_pager_bufferinit();
227129198Scognet	pcb->un_32.pcb32_und_sp = (u_int)thread0.td_kstack +
228129198Scognet	    USPACE_UNDEF_STACK_TOP;
229129198Scognet	pcb->un_32.pcb32_sp = (u_int)thread0.td_kstack +
230129198Scognet	    USPACE_SVC_STACK_TOP;
231129198Scognet	vector_page_setprot(VM_PROT_READ);
232129198Scognet	pmap_set_pcb_pagedir(pmap_kernel(), pcb);
233129198Scognet	cpu_setup("");
234129198Scognet	identify_arm_cpu();
235129198Scognet	thread0.td_frame = (struct trapframe *)pcb->un_32.pcb32_sp - 1;
236137215Scognet
237129198Scognet}
238129198Scognet
239129198ScognetSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
240129198Scognet
241141237Snjl/* Get current clock frequency for the given cpu id. */
242141237Snjlint
243141237Snjlcpu_est_clockrate(int cpu_id, uint64_t *rate)
244141237Snjl{
245141237Snjl
246141237Snjl	return (ENXIO);
247141237Snjl}
248141237Snjl
249129198Scognetvoid
250129198Scognetcpu_idle(void)
251129198Scognet{
252137215Scognet	cpu_sleep(0);
253129198Scognet}
254129198Scognet
255129198Scognetint
256129198Scognetfill_regs(struct thread *td, struct reg *regs)
257129198Scognet{
258129198Scognet	struct trapframe *tf = td->td_frame;
259129198Scognet	bcopy(&tf->tf_r0, regs->r, sizeof(regs->r));
260129198Scognet	regs->r_sp = tf->tf_usr_sp;
261129198Scognet	regs->r_lr = tf->tf_usr_lr;
262129198Scognet	regs->r_pc = tf->tf_pc;
263129198Scognet	regs->r_cpsr = tf->tf_spsr;
264129198Scognet	return (0);
265129198Scognet}
266129198Scognetint
267129198Scognetfill_fpregs(struct thread *td, struct fpreg *regs)
268129198Scognet{
269129198Scognet	bzero(regs, sizeof(*regs));
270129198Scognet	return (0);
271129198Scognet}
272129198Scognet
273129198Scognetint
274129198Scognetset_regs(struct thread *td, struct reg *regs)
275129198Scognet{
276129198Scognet	struct trapframe *tf = td->td_frame;
277129198Scognet
278137215Scognet	bcopy(regs->r, &tf->tf_r0, sizeof(regs->r));
279129198Scognet	tf->tf_usr_sp = regs->r_sp;
280129198Scognet	tf->tf_usr_lr = regs->r_lr;
281129198Scognet	tf->tf_pc = regs->r_pc;
282129198Scognet	tf->tf_spsr &=  ~PSR_FLAGS;
283129198Scognet	tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS;
284129198Scognet	return (0);
285129198Scognet}
286129198Scognet
287129198Scognetint
288129198Scognetset_fpregs(struct thread *td, struct fpreg *regs)
289129198Scognet{
290129198Scognet	return (0);
291129198Scognet}
292129198Scognet
293129198Scognetint
294129198Scognetfill_dbregs(struct thread *td, struct dbreg *regs)
295129198Scognet{
296129198Scognet	return (0);
297129198Scognet}
298129198Scognetint
299129198Scognetset_dbregs(struct thread *td, struct dbreg *regs)
300129198Scognet{
301129198Scognet	return (0);
302129198Scognet}
303129198Scognet
304140001Scognet
305140001Scognetstatic int
306140001Scognetptrace_read_int(struct thread *td, vm_offset_t addr, u_int32_t *v)
307140001Scognet{
308140001Scognet	struct iovec iov;
309140001Scognet	struct uio uio;
310140001Scognet	iov.iov_base = (caddr_t) v;
311140001Scognet	iov.iov_len = sizeof(u_int32_t);
312140001Scognet	uio.uio_iov = &iov;
313140001Scognet	uio.uio_iovcnt = 1;
314140001Scognet	uio.uio_offset = (off_t)addr;
315140001Scognet	uio.uio_resid = sizeof(u_int32_t);
316140001Scognet	uio.uio_segflg = UIO_SYSSPACE;
317140001Scognet	uio.uio_rw = UIO_READ;
318140001Scognet	uio.uio_td = td;
319140001Scognet	return proc_rwmem(td->td_proc, &uio);
320140001Scognet}
321140001Scognet
322140001Scognetstatic int
323140001Scognetptrace_write_int(struct thread *td, vm_offset_t addr, u_int32_t v)
324140001Scognet{
325140001Scognet	struct iovec iov;
326140001Scognet	struct uio uio;
327140001Scognet	iov.iov_base = (caddr_t) &v;
328140001Scognet	iov.iov_len = sizeof(u_int32_t);
329140001Scognet	uio.uio_iov = &iov;
330140001Scognet	uio.uio_iovcnt = 1;
331140001Scognet	uio.uio_offset = (off_t)addr;
332140001Scognet	uio.uio_resid = sizeof(u_int32_t);
333140001Scognet	uio.uio_segflg = UIO_SYSSPACE;
334140001Scognet	uio.uio_rw = UIO_WRITE;
335140001Scognet	uio.uio_td = td;
336140001Scognet	return proc_rwmem(td->td_proc, &uio);
337140001Scognet}
338140001Scognet
339129198Scognetint
340129198Scognetptrace_single_step(struct thread *td)
341129198Scognet{
342140001Scognet	int error;
343140001Scognet
344140001Scognet	KASSERT(td->td_md.md_ptrace_instr == 0,
345140001Scognet	 ("Didn't clear single step"));
346140001Scognet	error = ptrace_read_int(td, td->td_frame->tf_pc + 4,
347140001Scognet	    &td->td_md.md_ptrace_instr);
348140001Scognet	if (error)
349140001Scognet		return (error);
350140001Scognet	error = ptrace_write_int(td, td->td_frame->tf_pc + 4,
351140001Scognet	    PTRACE_BREAKPOINT);
352140001Scognet	if (error)
353140001Scognet		td->td_md.md_ptrace_instr = 0;
354140001Scognet	td->td_md.md_ptrace_addr = td->td_frame->tf_pc + 4;
355140001Scognet	return (error);
356129198Scognet}
357129198Scognet
358129198Scognetint
359132474Scognetptrace_clear_single_step(struct thread *td)
360132474Scognet{
361140001Scognet	if (td->td_md.md_ptrace_instr) {
362140001Scognet		ptrace_write_int(td, td->td_md.md_ptrace_addr,
363140001Scognet		    td->td_md.md_ptrace_instr);
364140001Scognet		td->td_md.md_ptrace_instr = 0;
365140001Scognet	}
366132474Scognet	return (0);
367132474Scognet}
368132474Scognet
369132474Scognetint
370129198Scognetptrace_set_pc(struct thread *td, unsigned long addr)
371129198Scognet{
372132474Scognet	td->td_frame->tf_pc = addr;
373129198Scognet	return (0);
374129198Scognet}
375129198Scognet
376129198Scognetvoid
377129198Scognetcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
378129198Scognet{
379129198Scognet}
380129198Scognet
381129198Scognet/*
382129198Scognet * Clear registers on exec
383129198Scognet */
384129198Scognetvoid
385129198Scognetexec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
386129198Scognet{
387129198Scognet	struct trapframe *tf = td->td_frame;
388129198Scognet
389129198Scognet	memset(tf, 0, sizeof(*tf));
390129198Scognet	tf->tf_usr_sp = stack;
391129198Scognet	tf->tf_usr_lr = entry;
392129198Scognet	tf->tf_svc_lr = 0x77777777;
393129198Scognet	tf->tf_pc = entry;
394129198Scognet	tf->tf_spsr = PSR_USR32_MODE;
395129198Scognet}
396129198Scognet
397129198Scognet/*
398129198Scognet * Build siginfo_t for SA thread
399129198Scognet */
400129198Scognetvoid
401129198Scognetcpu_thread_siginfo(int sig, u_long code, siginfo_t *si)
402129198Scognet{
403137215Scognet	bzero(si, sizeof(*si));
404137215Scognet	si->si_signo = sig;
405137215Scognet	si->si_code = code;
406129198Scognet}
407129198Scognet
408129198Scognet/*
409129198Scognet * Get machine context.
410129198Scognet */
411129198Scognetint
412129198Scognetget_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
413129198Scognet{
414129198Scognet	struct trapframe *tf = td->td_frame;
415129198Scognet	__greg_t *gr = mcp->__gregs;
416129198Scognet
417137215Scognet	if (clear_ret & GET_MC_CLEAR_RET)
418137215Scognet		gr[_REG_R0] = 0;
419137215Scognet	else
420137215Scognet		gr[_REG_R0]   = tf->tf_r0;
421129198Scognet	gr[_REG_R1]   = tf->tf_r1;
422129198Scognet	gr[_REG_R2]   = tf->tf_r2;
423129198Scognet	gr[_REG_R3]   = tf->tf_r3;
424129198Scognet	gr[_REG_R4]   = tf->tf_r4;
425129198Scognet	gr[_REG_R5]   = tf->tf_r5;
426129198Scognet	gr[_REG_R6]   = tf->tf_r6;
427129198Scognet	gr[_REG_R7]   = tf->tf_r7;
428129198Scognet	gr[_REG_R8]   = tf->tf_r8;
429129198Scognet	gr[_REG_R9]   = tf->tf_r9;
430129198Scognet	gr[_REG_R10]  = tf->tf_r10;
431129198Scognet	gr[_REG_R11]  = tf->tf_r11;
432129198Scognet	gr[_REG_R12]  = tf->tf_r12;
433129198Scognet	gr[_REG_SP]   = tf->tf_usr_sp;
434129198Scognet	gr[_REG_LR]   = tf->tf_usr_lr;
435129198Scognet	gr[_REG_PC]   = tf->tf_pc;
436129198Scognet	gr[_REG_CPSR] = tf->tf_spsr;
437129198Scognet
438129198Scognet	return (0);
439129198Scognet}
440129198Scognet
441129198Scognet/*
442129198Scognet * Set machine context.
443129198Scognet *
444129198Scognet * However, we don't set any but the user modifiable flags, and we won't
445129198Scognet * touch the cs selector.
446129198Scognet */
447129198Scognetint
448129198Scognetset_mcontext(struct thread *td, const mcontext_t *mcp)
449129198Scognet{
450137215Scognet	struct trapframe *tf = td->td_frame;
451137215Scognet	__greg_t *gr = mcp->__gregs;
452137215Scognet
453137215Scognet	tf->tf_r0 = gr[_REG_R0];
454137215Scognet	tf->tf_r1 = gr[_REG_R1];
455137215Scognet	tf->tf_r2 = gr[_REG_R2];
456137215Scognet	tf->tf_r3 = gr[_REG_R3];
457137215Scognet	tf->tf_r4 = gr[_REG_R4];
458137215Scognet	tf->tf_r5 = gr[_REG_R5];
459137215Scognet	tf->tf_r6 = gr[_REG_R6];
460137215Scognet	tf->tf_r7 = gr[_REG_R7];
461137215Scognet	tf->tf_r8 = gr[_REG_R8];
462137215Scognet	tf->tf_r9 = gr[_REG_R9];
463137215Scognet	tf->tf_r10 = gr[_REG_R10];
464137215Scognet	tf->tf_r11 = gr[_REG_R11];
465137215Scognet	tf->tf_r12 = gr[_REG_R12];
466137215Scognet	tf->tf_usr_sp = gr[_REG_SP];
467137215Scognet	tf->tf_usr_lr = gr[_REG_LR];
468137215Scognet	tf->tf_pc = gr[_REG_PC];
469137215Scognet	tf->tf_spsr = gr[_REG_CPSR];
470137215Scognet
471129198Scognet	return (0);
472129198Scognet}
473129198Scognet
474129198Scognet/*
475129198Scognet * MPSAFE
476129198Scognet */
477129198Scognetint
478129198Scognetsigreturn(td, uap)
479129198Scognet	struct thread *td;
480129198Scognet	struct sigreturn_args /* {
481129198Scognet		const __ucontext *sigcntxp;
482129198Scognet	} */ *uap;
483129198Scognet{
484135653Scognet	struct proc *p = td->td_proc;
485135653Scognet	struct sigframe sf;
486135653Scognet	struct trapframe *tf;
487135653Scognet	int spsr;
488135653Scognet
489135653Scognet	if (uap == NULL)
490135653Scognet		return (EFAULT);
491135653Scognet	if (copyin(uap->sigcntxp, &sf, sizeof(sf)))
492135653Scognet		return (EFAULT);
493135653Scognet	/*
494135653Scognet	 * Make sure the processor mode has not been tampered with and
495135653Scognet	 * interrupts have not been disabled.
496135653Scognet	 */
497135653Scognet	spsr = sf.sf_uc.uc_mcontext.__gregs[_REG_CPSR];
498135653Scognet	if ((spsr & PSR_MODE) != PSR_USR32_MODE ||
499135653Scognet	    (spsr & (I32_bit | F32_bit)) != 0)
500135653Scognet		return (EINVAL);
501135653Scognet		/* Restore register context. */
502135653Scognet	tf = td->td_frame;
503137215Scognet	set_mcontext(td, &sf.sf_uc.uc_mcontext);
504135653Scognet
505135653Scognet	/* Restore signal mask. */
506135653Scognet	PROC_LOCK(p);
507135653Scognet	td->td_sigmask = sf.sf_uc.uc_sigmask;
508135653Scognet	SIG_CANTMASK(td->td_sigmask);
509135653Scognet	signotify(td);
510135653Scognet	PROC_UNLOCK(p);
511135653Scognet
512135653Scognet	return (EJUSTRETURN);
513129198Scognet}
514129198Scognet
515129198Scognet
516132054Scognet/*
517132054Scognet * Construct a PCB from a trapframe. This is called from kdb_trap() where
518132054Scognet * we want to start a backtrace from the function that caused us to enter
519132054Scognet * the debugger. We have the context in the trapframe, but base the trace
520132054Scognet * on the PCB. The PCB doesn't have to be perfect, as long as it contains
521132054Scognet * enough for a backtrace.
522132054Scognet */
523132054Scognetvoid
524132054Scognetmakectx(struct trapframe *tf, struct pcb *pcb)
525132054Scognet{
526132054Scognet	pcb->un_32.pcb32_r8 = tf->tf_r8;
527132054Scognet	pcb->un_32.pcb32_r9 = tf->tf_r9;
528132054Scognet	pcb->un_32.pcb32_r10 = tf->tf_r10;
529132054Scognet	pcb->un_32.pcb32_r11 = tf->tf_r11;
530132054Scognet	pcb->un_32.pcb32_r12 = tf->tf_r12;
531132054Scognet	pcb->un_32.pcb32_pc = tf->tf_pc;
532132054Scognet	pcb->un_32.pcb32_lr = tf->tf_usr_lr;
533132054Scognet	pcb->un_32.pcb32_sp = tf->tf_usr_sp;
534132054Scognet}
535