machdep_kdb.c revision 135653
1129198Scognet/*	$NetBSD: arm32_machdep.c,v 1.44 2004/03/24 15:34:47 atatat Exp $	*/
2129198Scognet
3129198Scognet/*
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 135653 2004-09-23 22:12:28Z cognet $");
48129198Scognet
49129198Scognet#include <sys/param.h>
50129198Scognet#include <sys/systm.h>
51129198Scognet#include <sys/sysproto.h>
52129198Scognet#include <sys/signalvar.h>
53129198Scognet#include <sys/imgact.h>
54129198Scognet#include <sys/kernel.h>
55129198Scognet#include <sys/linker.h>
56129198Scognet#include <sys/lock.h>
57129198Scognet#include <sys/malloc.h>
58129198Scognet#include <sys/mutex.h>
59129198Scognet#include <sys/pcpu.h>
60129198Scognet#include <sys/proc.h>
61129198Scognet#include <sys/ptrace.h>
62129198Scognet#include <sys/cons.h>
63129198Scognet#include <sys/bio.h>
64129198Scognet#include <sys/buf.h>
65129198Scognet#include <sys/exec.h>
66135653Scognet#include <sys/sysent.h>
67129198Scognet#include <machine/reg.h>
68129198Scognet#include <machine/cpu.h>
69129198Scognet
70129198Scognet#include <vm/vm.h>
71129198Scognet#include <vm/pmap.h>
72129198Scognet#include <vm/vm.h>
73129198Scognet#include <vm/vm_object.h>
74129198Scognet#include <vm/vm_page.h>
75129198Scognet#include <vm/vm_pager.h>
76129198Scognet#include <vm/vm_map.h>
77129198Scognet#include <vm/vnode_pager.h>
78129198Scognet#include <machine/pmap.h>
79129198Scognet#include <machine/vmparam.h>
80129198Scognet#include <machine/pcb.h>
81129198Scognet#include <machine/undefined.h>
82129198Scognet#include <machine/machdep.h>
83129198Scognet#include <machine/metadata.h>
84129198Scognet#include <machine/armreg.h>
85135653Scognet#include <machine/md_var.h>
86129198Scognet
87129198Scognet#define MDROOT_ADDR 0xd0400000
88129198Scognet
89129198Scognetuint32_t cpu_reset_address = 0;
90129198Scognetint cold = 1;
91129198Scognetvm_offset_t vector_page;
92129198Scognet
93129198Scognetstatic void *
94129198Scognetgetframe(struct thread *td, int sig, int *onstack)
95129198Scognet{
96129198Scognet	struct trapframe *tf = td->td_frame;
97129198Scognet
98129198Scognet	*onstack = sigonstack(tf->tf_usr_sp);
99129198Scognet	if (*onstack)
100129198Scognet		return (void*)(td->td_sigstk.ss_sp + td->td_sigstk.ss_size);
101129198Scognet	return (void*)(tf->tf_usr_sp);
102129198Scognet}
103129198Scognet
104129198Scognetvoid
105129198Scognetsendsig(catcher, sig, mask, code)
106129198Scognet	sig_t catcher;
107129198Scognet	int sig;
108129198Scognet	sigset_t *mask;
109129198Scognet	u_long code;
110129198Scognet{
111129198Scognet	struct thread *td = curthread;
112135653Scognet	struct proc *p = td->td_proc;
113129198Scognet	struct trapframe *tf = td->td_frame;
114129198Scognet	struct sigframe *fp, frame;
115129198Scognet	struct sigacts *psp = td->td_proc->p_sigacts;
116129198Scognet	int onstack;
117129198Scognet
118129198Scognet	fp = getframe(td, sig, &onstack);
119129198Scognet	/* make room on the stack */
120129198Scognet	fp--;
121129198Scognet
122129198Scognet	/* make the stack aligned */
123135653Scognet	fp = (struct sigframe *)STACKALIGN(fp);
124129198Scognet	/* Populate the siginfo frame. */
125129198Scognet	frame.sf_si.si_signo = sig;
126129198Scognet	frame.sf_si.si_code = code;
127129198Scognet	frame.sf_uc.uc_sigmask = *mask;
128129198Scognet	frame.sf_uc.uc_link = NULL;
129129198Scognet	frame.sf_uc.uc_flags |= td->td_sigstk.ss_flags & SS_ONSTACK ?
130129198Scognet	    _UC_SETSTACK : _UC_CLRSTACK;
131135653Scognet	frame.sf_uc.uc_stack = td->td_sigstk;
132129198Scognet	memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack));
133129198Scognet	get_mcontext(td, &frame.sf_uc.uc_mcontext,
134129198Scognet	    (uint32_t)&frame.sf_uc.uc_flags);
135129198Scognet	PROC_UNLOCK(td->td_proc);
136129198Scognet	mtx_unlock(&psp->ps_mtx);
137129198Scognet	if (copyout(&frame, (void*)fp, sizeof(frame)) != 0)
138129198Scognet		sigexit(td, SIGILL);
139129198Scognet	/*
140129198Scognet	 * Build context to run handler in.  We invoke the handler
141129198Scognet	 * directly, only returning via the trampoline.  Note the
142129198Scognet	 * trampoline version numbers are coordinated with machine-
143129198Scognet	 * dependent code in libc.
144129198Scognet	 */
145129198Scognet
146129198Scognet	tf->tf_r0 = sig;
147129198Scognet	tf->tf_r1 = (int)&fp->sf_si;
148129198Scognet	tf->tf_r2 = (int)&fp->sf_uc;
149129198Scognet
150129198Scognet	/* the trampoline uses r5 as the uc address */
151129198Scognet	tf->tf_r5 = (int)&fp->sf_uc;
152129198Scognet	tf->tf_pc = (int)catcher;
153129198Scognet	tf->tf_usr_sp = (int)fp;
154135653Scognet	tf->tf_usr_lr = (int)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
155129198Scognet	if (onstack)
156129198Scognet		td->td_sigstk.ss_flags |= SS_ONSTACK;
157129198Scognet	PROC_LOCK(td->td_proc);
158129198Scognet	mtx_lock(&psp->ps_mtx);
159129198Scognet}
160129198Scognet
161129198Scognetstruct kva_md_info kmi;
162129198Scognet
163129198Scognet/*
164129198Scognet * arm32_vector_init:
165129198Scognet *
166129198Scognet *	Initialize the vector page, and select whether or not to
167129198Scognet *	relocate the vectors.
168129198Scognet *
169129198Scognet *	NOTE: We expect the vector page to be mapped at its expected
170129198Scognet *	destination.
171129198Scognet */
172129198Scognet
173129198Scognetextern unsigned int page0[], page0_data[];
174129198Scognetvoid
175129198Scognetarm_vector_init(vm_offset_t va, int which)
176129198Scognet{
177129198Scognet	unsigned int *vectors = (int *) va;
178129198Scognet	unsigned int *vectors_data = vectors + (page0_data - page0);
179129198Scognet	int vec;
180129198Scognet
181129198Scognet	/*
182129198Scognet	 * Loop through the vectors we're taking over, and copy the
183129198Scognet	 * vector's insn and data word.
184129198Scognet	 */
185129198Scognet	for (vec = 0; vec < ARM_NVEC; vec++) {
186129198Scognet		if ((which & (1 << vec)) == 0) {
187129198Scognet			/* Don't want to take over this vector. */
188129198Scognet			continue;
189129198Scognet		}
190129198Scognet		vectors[vec] = page0[vec];
191129198Scognet		vectors_data[vec] = page0_data[vec];
192129198Scognet	}
193129198Scognet
194129198Scognet	/* Now sync the vectors. */
195129198Scognet	cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int));
196129198Scognet
197129198Scognet	vector_page = va;
198129198Scognet
199129198Scognet	if (va == ARM_VECTORS_HIGH) {
200129198Scognet		/*
201129198Scognet		 * Assume the MD caller knows what it's doing here, and
202129198Scognet		 * really does want the vector page relocated.
203129198Scognet		 *
204129198Scognet		 * Note: This has to be done here (and not just in
205129198Scognet		 * cpu_setup()) because the vector page needs to be
206129198Scognet		 * accessible *before* cpu_startup() is called.
207129198Scognet		 * Think ddb(9) ...
208129198Scognet		 *
209129198Scognet		 * NOTE: If the CPU control register is not readable,
210129198Scognet		 * this will totally fail!  We'll just assume that
211129198Scognet		 * any system that has high vector support has a
212129198Scognet		 * readable CPU control register, for now.  If we
213129198Scognet		 * ever encounter one that does not, we'll have to
214129198Scognet		 * rethink this.
215129198Scognet		 */
216129198Scognet		cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC);
217129198Scognet	}
218129198Scognet}
219129198Scognet
220129198Scognetstatic void
221129198Scognetcpu_startup(void *dummy)
222129198Scognet{
223129198Scognet	struct pcb *pcb = thread0.td_pcb;
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_update(pmap_kernel());
233129198Scognet	pmap_set_pcb_pagedir(pmap_kernel(), pcb);
234129198Scognet	cpu_setup("");
235129198Scognet	identify_arm_cpu();
236129198Scognet	thread0.td_frame = (struct trapframe *)pcb->un_32.pcb32_sp - 1;
237129198Scognet}
238129198Scognet
239129198ScognetSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
240129198Scognet
241129198Scognetvoid
242129198Scognetcpu_idle(void)
243129198Scognet{
244129198Scognet}
245129198Scognet
246129198Scognetint
247129198Scognetfill_regs(struct thread *td, struct reg *regs)
248129198Scognet{
249129198Scognet	struct trapframe *tf = td->td_frame;
250129198Scognet	bcopy(&tf->tf_r0, regs->r, sizeof(regs->r));
251129198Scognet	regs->r_sp = tf->tf_usr_sp;
252129198Scognet	regs->r_lr = tf->tf_usr_lr;
253129198Scognet	regs->r_pc = tf->tf_pc;
254129198Scognet	regs->r_cpsr = tf->tf_spsr;
255129198Scognet	return (0);
256129198Scognet}
257129198Scognetint
258129198Scognetfill_fpregs(struct thread *td, struct fpreg *regs)
259129198Scognet{
260129198Scognet	bzero(regs, sizeof(*regs));
261129198Scognet	return (0);
262129198Scognet}
263129198Scognet
264129198Scognetint
265129198Scognetset_regs(struct thread *td, struct reg *regs)
266129198Scognet{
267129198Scognet	struct trapframe *tf = td->td_frame;
268129198Scognet
269129198Scognet	bcopy(regs->r, &tf->tf_r0, sizeof(*regs->r));
270129198Scognet	tf->tf_usr_sp = regs->r_sp;
271129198Scognet	tf->tf_usr_lr = regs->r_lr;
272129198Scognet	tf->tf_pc = regs->r_pc;
273129198Scognet	tf->tf_spsr &=  ~PSR_FLAGS;
274129198Scognet	tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS;
275129198Scognet	return (0);
276129198Scognet}
277129198Scognet
278129198Scognetint
279129198Scognetset_fpregs(struct thread *td, struct fpreg *regs)
280129198Scognet{
281129198Scognet	return (0);
282129198Scognet}
283129198Scognet
284129198Scognetint
285129198Scognetfill_dbregs(struct thread *td, struct dbreg *regs)
286129198Scognet{
287129198Scognet	return (0);
288129198Scognet}
289129198Scognetint
290129198Scognetset_dbregs(struct thread *td, struct dbreg *regs)
291129198Scognet{
292129198Scognet	return (0);
293129198Scognet}
294129198Scognet
295129198Scognetint
296129198Scognetptrace_single_step(struct thread *td)
297129198Scognet{
298132474Scognet	/* XXX */
299129198Scognet	return (0);
300129198Scognet}
301129198Scognet
302129198Scognetint
303132474Scognetptrace_clear_single_step(struct thread *td)
304132474Scognet{
305132474Scognet	/* XXX */
306132474Scognet	return (0);
307132474Scognet}
308132474Scognet
309132474Scognetint
310129198Scognetptrace_set_pc(struct thread *td, unsigned long addr)
311129198Scognet{
312132474Scognet	td->td_frame->tf_pc = addr;
313129198Scognet	return (0);
314129198Scognet}
315129198Scognet
316129198Scognetvoid
317129198Scognetcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
318129198Scognet{
319129198Scognet}
320129198Scognet
321129198Scognet/*
322129198Scognet * Clear registers on exec
323129198Scognet */
324129198Scognetvoid
325129198Scognetexec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
326129198Scognet{
327129198Scognet	struct trapframe *tf = td->td_frame;
328129198Scognet
329129198Scognet	memset(tf, 0, sizeof(*tf));
330129198Scognet	tf->tf_usr_sp = stack;
331129198Scognet	tf->tf_usr_lr = entry;
332129198Scognet	tf->tf_svc_lr = 0x77777777;
333129198Scognet	tf->tf_pc = entry;
334129198Scognet	tf->tf_spsr = PSR_USR32_MODE;
335129198Scognet}
336129198Scognet
337129198Scognet/*
338129198Scognet * Build siginfo_t for SA thread
339129198Scognet */
340129198Scognetvoid
341129198Scognetcpu_thread_siginfo(int sig, u_long code, siginfo_t *si)
342129198Scognet{
343129198Scognet	printf("cpu_thread_siginfo\n");
344129198Scognet}
345129198Scognet
346129198Scognet/*
347129198Scognet * Get machine context.
348129198Scognet */
349129198Scognetint
350129198Scognetget_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
351129198Scognet{
352129198Scognet	struct trapframe *tf = td->td_frame;
353129198Scognet	__greg_t *gr = mcp->__gregs;
354129198Scognet
355129198Scognet	/* Save General Register context. */
356129198Scognet	gr[_REG_R0]   = tf->tf_r0;
357129198Scognet	gr[_REG_R1]   = tf->tf_r1;
358129198Scognet	gr[_REG_R2]   = tf->tf_r2;
359129198Scognet	gr[_REG_R3]   = tf->tf_r3;
360129198Scognet	gr[_REG_R4]   = tf->tf_r4;
361129198Scognet	gr[_REG_R5]   = tf->tf_r5;
362129198Scognet	gr[_REG_R6]   = tf->tf_r6;
363129198Scognet	gr[_REG_R7]   = tf->tf_r7;
364129198Scognet	gr[_REG_R8]   = tf->tf_r8;
365129198Scognet	gr[_REG_R9]   = tf->tf_r9;
366129198Scognet	gr[_REG_R10]  = tf->tf_r10;
367129198Scognet	gr[_REG_R11]  = tf->tf_r11;
368129198Scognet	gr[_REG_R12]  = tf->tf_r12;
369129198Scognet	gr[_REG_SP]   = tf->tf_usr_sp;
370129198Scognet	gr[_REG_LR]   = tf->tf_usr_lr;
371129198Scognet	gr[_REG_PC]   = tf->tf_pc;
372129198Scognet	gr[_REG_CPSR] = tf->tf_spsr;
373129198Scognet
374129198Scognet	return (0);
375129198Scognet}
376129198Scognet
377129198Scognet/*
378129198Scognet * Set machine context.
379129198Scognet *
380129198Scognet * However, we don't set any but the user modifiable flags, and we won't
381129198Scognet * touch the cs selector.
382129198Scognet */
383129198Scognetint
384129198Scognetset_mcontext(struct thread *td, const mcontext_t *mcp)
385129198Scognet{
386129198Scognet	panic("SET_MCONTEXT AHAHAH\n");
387129198Scognet	return (0);
388129198Scognet}
389129198Scognet
390129198Scognet/*
391129198Scognet * MPSAFE
392129198Scognet */
393129198Scognetint
394129198Scognetsigreturn(td, uap)
395129198Scognet	struct thread *td;
396129198Scognet	struct sigreturn_args /* {
397129198Scognet		const __ucontext *sigcntxp;
398129198Scognet	} */ *uap;
399129198Scognet{
400135653Scognet	struct proc *p = td->td_proc;
401135653Scognet	struct sigframe sf;
402135653Scognet	struct trapframe *tf;
403135653Scognet	int spsr;
404135653Scognet
405135653Scognet	if (uap == NULL)
406135653Scognet		return (EFAULT);
407135653Scognet	if (copyin(uap->sigcntxp, &sf, sizeof(sf)))
408135653Scognet		return (EFAULT);
409135653Scognet	/*
410135653Scognet	 * Make sure the processor mode has not been tampered with and
411135653Scognet	 * interrupts have not been disabled.
412135653Scognet	 */
413135653Scognet	spsr = sf.sf_uc.uc_mcontext.__gregs[_REG_CPSR];
414135653Scognet	if ((spsr & PSR_MODE) != PSR_USR32_MODE ||
415135653Scognet	    (spsr & (I32_bit | F32_bit)) != 0)
416135653Scognet		return (EINVAL);
417135653Scognet		/* Restore register context. */
418135653Scognet	tf = td->td_frame;
419135653Scognet	memcpy((register_t *)tf + 1, &sf.sf_uc.uc_mcontext, sizeof(*tf) -
420135653Scognet	    4 * sizeof(register_t));
421135653Scognet#if 0
422135653Scognet	tf->tf_r0    = context.sc_r0;
423135653Scognet	tf->tf_r1    = context.sc_r1;
424135653Scognet	tf->tf_r2    = context.sc_r2;
425135653Scognet	tf->tf_r3    = context.sc_r3;
426135653Scognet	tf->tf_r4    = context.sc_r4;
427135653Scognet	tf->tf_r5    = context.sc_r5;
428135653Scognet	tf->tf_r6    = context.sc_r6;
429135653Scognet	tf->tf_r7    = context.sc_r7;
430135653Scognet	tf->tf_r8    = context.sc_r8;
431135653Scognet	tf->tf_r9    = context.sc_r9;
432135653Scognet	tf->tf_r10   = context.sc_r10;
433135653Scognet	tf->tf_r11   = context.sc_r11;
434135653Scognet	tf->tf_r12   = context.sc_r12;
435135653Scognet	tf->tf_usr_sp = context.sc_usr_sp;
436135653Scognet	tf->tf_usr_lr = context.sc_usr_lr;
437135653Scognet	tf->tf_svc_lr = context.sc_svc_lr;
438135653Scognet	tf->tf_pc    = context.sc_pc;
439135653Scognet#endif
440135653Scognet	tf->tf_pc = sf.sf_uc.uc_mcontext.__gregs[_REG_PC];
441135653Scognet	tf->tf_spsr = spsr;
442135653Scognet
443135653Scognet	/* Restore signal stack. */
444135653Scognet	if (sf.sf_uc.uc_flags & _UC_SETSTACK)
445135653Scognet		td->td_sigstk.ss_flags |= SS_ONSTACK;
446135653Scognet	else
447135653Scognet		td->td_sigstk.ss_flags &= ~SS_ONSTACK;
448135653Scognet
449135653Scognet	/* Restore signal mask. */
450135653Scognet	PROC_LOCK(p);
451135653Scognet	td->td_sigmask = sf.sf_uc.uc_sigmask;
452135653Scognet	SIG_CANTMASK(td->td_sigmask);
453135653Scognet	signotify(td);
454135653Scognet	PROC_UNLOCK(p);
455135653Scognet
456135653Scognet	return (EJUSTRETURN);
457129198Scognet}
458129198Scognet
459129198Scognet
460132054Scognet/*
461132054Scognet * Construct a PCB from a trapframe. This is called from kdb_trap() where
462132054Scognet * we want to start a backtrace from the function that caused us to enter
463132054Scognet * the debugger. We have the context in the trapframe, but base the trace
464132054Scognet * on the PCB. The PCB doesn't have to be perfect, as long as it contains
465132054Scognet * enough for a backtrace.
466132054Scognet */
467132054Scognetvoid
468132054Scognetmakectx(struct trapframe *tf, struct pcb *pcb)
469132054Scognet{
470132054Scognet	pcb->un_32.pcb32_r8 = tf->tf_r8;
471132054Scognet	pcb->un_32.pcb32_r9 = tf->tf_r9;
472132054Scognet	pcb->un_32.pcb32_r10 = tf->tf_r10;
473132054Scognet	pcb->un_32.pcb32_r11 = tf->tf_r11;
474132054Scognet	pcb->un_32.pcb32_r12 = tf->tf_r12;
475132054Scognet	pcb->un_32.pcb32_pc = tf->tf_pc;
476132054Scognet	pcb->un_32.pcb32_lr = tf->tf_usr_lr;
477132054Scognet	pcb->un_32.pcb32_sp = tf->tf_usr_sp;
478132054Scognet}
479