machdep_kdb.c revision 132474
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 132474 2004-07-20 23:00:02Z 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>
66129198Scognet#include <machine/reg.h>
67129198Scognet#include <machine/cpu.h>
68129198Scognet
69129198Scognet#include <vm/vm.h>
70129198Scognet#include <vm/pmap.h>
71129198Scognet#include <vm/vm.h>
72129198Scognet#include <vm/vm_object.h>
73129198Scognet#include <vm/vm_page.h>
74129198Scognet#include <vm/vm_pager.h>
75129198Scognet#include <vm/vm_map.h>
76129198Scognet#include <vm/vnode_pager.h>
77129198Scognet#include <machine/pmap.h>
78129198Scognet#include <machine/vmparam.h>
79129198Scognet#include <machine/pcb.h>
80129198Scognet#include <machine/undefined.h>
81129198Scognet#include <machine/machdep.h>
82129198Scognet#include <machine/metadata.h>
83129198Scognet#include <machine/armreg.h>
84129198Scognet
85129198Scognet#define MDROOT_ADDR 0xd0400000
86129198Scognet
87129198Scognetuint32_t cpu_reset_address = 0;
88129198Scognetint cold = 1;
89129198Scognetvm_offset_t vector_page;
90129198Scognet
91129198Scognetstatic void *
92129198Scognetgetframe(struct thread *td, int sig, int *onstack)
93129198Scognet{
94129198Scognet	struct trapframe *tf = td->td_frame;
95129198Scognet
96129198Scognet	*onstack = sigonstack(tf->tf_usr_sp);
97129198Scognet	if (*onstack)
98129198Scognet		return (void*)(td->td_sigstk.ss_sp + td->td_sigstk.ss_size);
99129198Scognet	return (void*)(tf->tf_usr_sp);
100129198Scognet}
101129198Scognet
102129198Scognetvoid
103129198Scognetsendsig(catcher, sig, mask, code)
104129198Scognet	sig_t catcher;
105129198Scognet	int sig;
106129198Scognet	sigset_t *mask;
107129198Scognet	u_long code;
108129198Scognet{
109129198Scognet	struct thread *td = curthread;
110129198Scognet	struct trapframe *tf = td->td_frame;
111129198Scognet	struct sigframe *fp, frame;
112129198Scognet	struct sigacts *psp = td->td_proc->p_sigacts;
113129198Scognet	int onstack;
114129198Scognet
115129198Scognet	fp = getframe(td, sig, &onstack);
116129198Scognet	/* make room on the stack */
117129198Scognet	fp--;
118129198Scognet
119129198Scognet	/* make the stack aligned */
120129198Scognet	(u_int)fp = _ALIGN(fp);
121129198Scognet	/* Populate the siginfo frame. */
122129198Scognet	frame.sf_si.si_signo = sig;
123129198Scognet	frame.sf_si.si_code = code;
124129198Scognet	frame.sf_uc.uc_sigmask = *mask;
125129198Scognet	frame.sf_uc.uc_link = NULL;
126129198Scognet	frame.sf_uc.uc_flags |= td->td_sigstk.ss_flags & SS_ONSTACK ?
127129198Scognet	    _UC_SETSTACK : _UC_CLRSTACK;
128129198Scognet	memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack));
129129198Scognet	get_mcontext(td, &frame.sf_uc.uc_mcontext,
130129198Scognet	    (uint32_t)&frame.sf_uc.uc_flags);
131129198Scognet	PROC_UNLOCK(td->td_proc);
132129198Scognet	mtx_unlock(&psp->ps_mtx);
133129198Scognet	if (copyout(&frame, (void*)fp, sizeof(frame)) != 0)
134129198Scognet		sigexit(td, SIGILL);
135129198Scognet	/*
136129198Scognet	 * Build context to run handler in.  We invoke the handler
137129198Scognet	 * directly, only returning via the trampoline.  Note the
138129198Scognet	 * trampoline version numbers are coordinated with machine-
139129198Scognet	 * dependent code in libc.
140129198Scognet	 */
141129198Scognet
142129198Scognet	tf->tf_r0 = sig;
143129198Scognet	tf->tf_r1 = (int)&fp->sf_si;
144129198Scognet	tf->tf_r2 = (int)&fp->sf_uc;
145129198Scognet
146129198Scognet	/* the trampoline uses r5 as the uc address */
147129198Scognet	tf->tf_r5 = (int)&fp->sf_uc;
148129198Scognet	tf->tf_pc = (int)catcher;
149129198Scognet	tf->tf_usr_sp = (int)fp;
150129198Scognet	if (onstack)
151129198Scognet		td->td_sigstk.ss_flags |= SS_ONSTACK;
152129198Scognet	PROC_LOCK(td->td_proc);
153129198Scognet	mtx_lock(&psp->ps_mtx);
154129198Scognet}
155129198Scognet
156129198Scognetstruct kva_md_info kmi;
157129198Scognet
158129198Scognet/*
159129198Scognet * arm32_vector_init:
160129198Scognet *
161129198Scognet *	Initialize the vector page, and select whether or not to
162129198Scognet *	relocate the vectors.
163129198Scognet *
164129198Scognet *	NOTE: We expect the vector page to be mapped at its expected
165129198Scognet *	destination.
166129198Scognet */
167129198Scognet
168129198Scognetextern unsigned int page0[], page0_data[];
169129198Scognetvoid
170129198Scognetarm_vector_init(vm_offset_t va, int which)
171129198Scognet{
172129198Scognet	unsigned int *vectors = (int *) va;
173129198Scognet	unsigned int *vectors_data = vectors + (page0_data - page0);
174129198Scognet	int vec;
175129198Scognet
176129198Scognet	/*
177129198Scognet	 * Loop through the vectors we're taking over, and copy the
178129198Scognet	 * vector's insn and data word.
179129198Scognet	 */
180129198Scognet	for (vec = 0; vec < ARM_NVEC; vec++) {
181129198Scognet		if ((which & (1 << vec)) == 0) {
182129198Scognet			/* Don't want to take over this vector. */
183129198Scognet			continue;
184129198Scognet		}
185129198Scognet		vectors[vec] = page0[vec];
186129198Scognet		vectors_data[vec] = page0_data[vec];
187129198Scognet	}
188129198Scognet
189129198Scognet	/* Now sync the vectors. */
190129198Scognet	cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int));
191129198Scognet
192129198Scognet	vector_page = va;
193129198Scognet
194129198Scognet	if (va == ARM_VECTORS_HIGH) {
195129198Scognet		/*
196129198Scognet		 * Assume the MD caller knows what it's doing here, and
197129198Scognet		 * really does want the vector page relocated.
198129198Scognet		 *
199129198Scognet		 * Note: This has to be done here (and not just in
200129198Scognet		 * cpu_setup()) because the vector page needs to be
201129198Scognet		 * accessible *before* cpu_startup() is called.
202129198Scognet		 * Think ddb(9) ...
203129198Scognet		 *
204129198Scognet		 * NOTE: If the CPU control register is not readable,
205129198Scognet		 * this will totally fail!  We'll just assume that
206129198Scognet		 * any system that has high vector support has a
207129198Scognet		 * readable CPU control register, for now.  If we
208129198Scognet		 * ever encounter one that does not, we'll have to
209129198Scognet		 * rethink this.
210129198Scognet		 */
211129198Scognet		cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC);
212129198Scognet	}
213129198Scognet}
214129198Scognet
215129198Scognetstatic void
216129198Scognetcpu_startup(void *dummy)
217129198Scognet{
218129198Scognet	struct pcb *pcb = thread0.td_pcb;
219129198Scognet	vm_ksubmap_init(&kmi);
220129198Scognet	bufinit();
221129198Scognet	vm_pager_bufferinit();
222129198Scognet	pcb->un_32.pcb32_und_sp = (u_int)thread0.td_kstack +
223129198Scognet	    USPACE_UNDEF_STACK_TOP;
224129198Scognet	pcb->un_32.pcb32_sp = (u_int)thread0.td_kstack +
225129198Scognet	    USPACE_SVC_STACK_TOP;
226129198Scognet	vector_page_setprot(VM_PROT_READ);
227129198Scognet	pmap_update(pmap_kernel());
228129198Scognet	pmap_set_pcb_pagedir(pmap_kernel(), pcb);
229129198Scognet	cpu_setup("");
230129198Scognet	identify_arm_cpu();
231129198Scognet	thread0.td_frame = (struct trapframe *)pcb->un_32.pcb32_sp - 1;
232129198Scognet}
233129198Scognet
234129198ScognetSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
235129198Scognet
236129198Scognetvoid
237129198Scognetcpu_idle(void)
238129198Scognet{
239129198Scognet}
240129198Scognet
241129198Scognetint
242129198Scognetfill_regs(struct thread *td, struct reg *regs)
243129198Scognet{
244129198Scognet	struct trapframe *tf = td->td_frame;
245129198Scognet	bcopy(&tf->tf_r0, regs->r, sizeof(regs->r));
246129198Scognet	regs->r_sp = tf->tf_usr_sp;
247129198Scognet	regs->r_lr = tf->tf_usr_lr;
248129198Scognet	regs->r_pc = tf->tf_pc;
249129198Scognet	regs->r_cpsr = tf->tf_spsr;
250129198Scognet	return (0);
251129198Scognet}
252129198Scognetint
253129198Scognetfill_fpregs(struct thread *td, struct fpreg *regs)
254129198Scognet{
255129198Scognet	bzero(regs, sizeof(*regs));
256129198Scognet	return (0);
257129198Scognet}
258129198Scognet
259129198Scognetint
260129198Scognetset_regs(struct thread *td, struct reg *regs)
261129198Scognet{
262129198Scognet	struct trapframe *tf = td->td_frame;
263129198Scognet
264129198Scognet	bcopy(regs->r, &tf->tf_r0, sizeof(*regs->r));
265129198Scognet	tf->tf_usr_sp = regs->r_sp;
266129198Scognet	tf->tf_usr_lr = regs->r_lr;
267129198Scognet	tf->tf_pc = regs->r_pc;
268129198Scognet	tf->tf_spsr &=  ~PSR_FLAGS;
269129198Scognet	tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS;
270129198Scognet	while(1);
271129198Scognet	return (0);
272129198Scognet}
273129198Scognet
274129198Scognetint
275129198Scognetset_fpregs(struct thread *td, struct fpreg *regs)
276129198Scognet{
277129198Scognet	return (0);
278129198Scognet}
279129198Scognet
280129198Scognetint
281129198Scognetfill_dbregs(struct thread *td, struct dbreg *regs)
282129198Scognet{
283129198Scognet	return (0);
284129198Scognet}
285129198Scognetint
286129198Scognetset_dbregs(struct thread *td, struct dbreg *regs)
287129198Scognet{
288129198Scognet	return (0);
289129198Scognet}
290129198Scognet
291129198Scognetvoid
292129198Scognetcpu_halt(void)
293129198Scognet{
294129198Scognet	cpu_reset();
295129198Scognet}
296129198Scognet
297129198Scognetint
298129198Scognetptrace_single_step(struct thread *td)
299129198Scognet{
300132474Scognet	/* XXX */
301129198Scognet	return (0);
302129198Scognet}
303129198Scognet
304129198Scognetint
305132474Scognetptrace_clear_single_step(struct thread *td)
306132474Scognet{
307132474Scognet	/* XXX */
308132474Scognet	return (0);
309132474Scognet}
310132474Scognet
311132474Scognetint
312129198Scognetptrace_set_pc(struct thread *td, unsigned long addr)
313129198Scognet{
314132474Scognet	td->td_frame->tf_pc = addr;
315129198Scognet	return (0);
316129198Scognet}
317129198Scognet
318129198Scognetvoid
319129198Scognetcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
320129198Scognet{
321129198Scognet}
322129198Scognet
323129198Scognet/*
324129198Scognet * Clear registers on exec
325129198Scognet */
326129198Scognetvoid
327129198Scognetexec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
328129198Scognet{
329129198Scognet	struct trapframe *tf = td->td_frame;
330129198Scognet
331129198Scognet	memset(tf, 0, sizeof(*tf));
332129198Scognet	tf->tf_usr_sp = stack;
333129198Scognet	tf->tf_usr_lr = entry;
334129198Scognet	tf->tf_svc_lr = 0x77777777;
335129198Scognet	tf->tf_pc = entry;
336129198Scognet	tf->tf_spsr = PSR_USR32_MODE;
337129198Scognet}
338129198Scognet
339129198Scognet/*
340129198Scognet * Build siginfo_t for SA thread
341129198Scognet */
342129198Scognetvoid
343129198Scognetcpu_thread_siginfo(int sig, u_long code, siginfo_t *si)
344129198Scognet{
345129198Scognet	printf("cpu_thread_siginfo\n");
346129198Scognet}
347129198Scognet
348129198Scognet/*
349129198Scognet * Get machine context.
350129198Scognet */
351129198Scognetint
352129198Scognetget_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
353129198Scognet{
354129198Scognet	struct trapframe *tf = td->td_frame;
355129198Scognet	__greg_t *gr = mcp->__gregs;
356129198Scognet
357129198Scognet	/* Save General Register context. */
358129198Scognet	gr[_REG_R0]   = tf->tf_r0;
359129198Scognet	gr[_REG_R1]   = tf->tf_r1;
360129198Scognet	gr[_REG_R2]   = tf->tf_r2;
361129198Scognet	gr[_REG_R3]   = tf->tf_r3;
362129198Scognet	gr[_REG_R4]   = tf->tf_r4;
363129198Scognet	gr[_REG_R5]   = tf->tf_r5;
364129198Scognet	gr[_REG_R6]   = tf->tf_r6;
365129198Scognet	gr[_REG_R7]   = tf->tf_r7;
366129198Scognet	gr[_REG_R8]   = tf->tf_r8;
367129198Scognet	gr[_REG_R9]   = tf->tf_r9;
368129198Scognet	gr[_REG_R10]  = tf->tf_r10;
369129198Scognet	gr[_REG_R11]  = tf->tf_r11;
370129198Scognet	gr[_REG_R12]  = tf->tf_r12;
371129198Scognet	gr[_REG_SP]   = tf->tf_usr_sp;
372129198Scognet	gr[_REG_LR]   = tf->tf_usr_lr;
373129198Scognet	gr[_REG_PC]   = tf->tf_pc;
374129198Scognet	gr[_REG_CPSR] = tf->tf_spsr;
375129198Scognet
376129198Scognet	return (0);
377129198Scognet}
378129198Scognet
379129198Scognet/*
380129198Scognet * Set machine context.
381129198Scognet *
382129198Scognet * However, we don't set any but the user modifiable flags, and we won't
383129198Scognet * touch the cs selector.
384129198Scognet */
385129198Scognetint
386129198Scognetset_mcontext(struct thread *td, const mcontext_t *mcp)
387129198Scognet{
388129198Scognet	panic("SET_MCONTEXT AHAHAH\n");
389129198Scognet	return (0);
390129198Scognet}
391129198Scognet
392129198Scognet#ifdef COMPAT_FREEBSD4
393129198Scognetint
394129198Scognetfreebsd4_sigreturn(td, uap)
395129198Scognet	struct thread *td;
396129198Scognet	struct freebsd4_sigreturn_args /* {
397129198Scognet		const ucontext4 *sigcntxp;
398129198Scognet	} */ *uap;
399129198Scognet{
400129198Scognet	return (0);
401129198Scognet}
402129198Scognet#endif
403129198Scognet
404129198Scognet/*
405129198Scognet * MPSAFE
406129198Scognet */
407129198Scognetint
408129198Scognetsigreturn(td, uap)
409129198Scognet	struct thread *td;
410129198Scognet	struct sigreturn_args /* {
411129198Scognet		const __ucontext *sigcntxp;
412129198Scognet	} */ *uap;
413129198Scognet{
414129198Scognet	return (0);
415129198Scognet}
416129198Scognet
417129198Scognet
418132054Scognet/*
419132054Scognet * Construct a PCB from a trapframe. This is called from kdb_trap() where
420132054Scognet * we want to start a backtrace from the function that caused us to enter
421132054Scognet * the debugger. We have the context in the trapframe, but base the trace
422132054Scognet * on the PCB. The PCB doesn't have to be perfect, as long as it contains
423132054Scognet * enough for a backtrace.
424132054Scognet */
425132054Scognetvoid
426132054Scognetmakectx(struct trapframe *tf, struct pcb *pcb)
427132054Scognet{
428132054Scognet	pcb->un_32.pcb32_r8 = tf->tf_r8;
429132054Scognet	pcb->un_32.pcb32_r9 = tf->tf_r9;
430132054Scognet	pcb->un_32.pcb32_r10 = tf->tf_r10;
431132054Scognet	pcb->un_32.pcb32_r11 = tf->tf_r11;
432132054Scognet	pcb->un_32.pcb32_r12 = tf->tf_r12;
433132054Scognet	pcb->un_32.pcb32_pc = tf->tf_pc;
434132054Scognet	pcb->un_32.pcb32_lr = tf->tf_usr_lr;
435132054Scognet	pcb->un_32.pcb32_sp = tf->tf_usr_sp;
436132054Scognet}
437