machdep.c revision 132473
1/*	$NetBSD: arm32_machdep.c,v 1.44 2004/03/24 15:34:47 atatat Exp $	*/
2
3/*
4 * Copyright (c) 2004 Olivier Houchard
5 * Copyright (c) 1994-1998 Mark Brinicombe.
6 * Copyright (c) 1994 Brini.
7 * All rights reserved.
8 *
9 * This code is derived from software written for Brini by Mark Brinicombe
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 *    must display the following acknowledgement:
21 *	This product includes software developed by Mark Brinicombe
22 *	for the NetBSD Project.
23 * 4. The name of the company nor the name of the author may be used to
24 *    endorse or promote products derived from this software without specific
25 *    prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
28 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
31 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * Machine dependant functions for kernel setup
40 *
41 * Created      : 17/09/94
42 * Updated	: 18/04/01 updated for new wscons
43 */
44
45#include "opt_compat.h"
46#include <sys/cdefs.h>
47__FBSDID("$FreeBSD: head/sys/arm/arm/machdep.c 132473 2004-07-20 22:39:56Z cognet $");
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/sysproto.h>
52#include <sys/signalvar.h>
53#include <sys/imgact.h>
54#include <sys/kernel.h>
55#include <sys/linker.h>
56#include <sys/lock.h>
57#include <sys/malloc.h>
58#include <sys/mutex.h>
59#include <sys/pcpu.h>
60#include <sys/proc.h>
61#include <sys/ptrace.h>
62#include <sys/cons.h>
63#include <sys/bio.h>
64#include <sys/buf.h>
65#include <sys/exec.h>
66#include <machine/reg.h>
67#include <machine/cpu.h>
68
69#include <vm/vm.h>
70#include <vm/pmap.h>
71#include <vm/vm.h>
72#include <vm/vm_object.h>
73#include <vm/vm_page.h>
74#include <vm/vm_pager.h>
75#include <vm/vm_map.h>
76#include <vm/vnode_pager.h>
77#include <machine/pmap.h>
78#include <machine/vmparam.h>
79#include <machine/pcb.h>
80#include <machine/undefined.h>
81#include <machine/machdep.h>
82#include <machine/metadata.h>
83#include <machine/armreg.h>
84
85#define MDROOT_ADDR 0xd0400000
86
87uint32_t cpu_reset_address = 0;
88int cold = 1;
89vm_offset_t vector_page;
90
91static void *
92getframe(struct thread *td, int sig, int *onstack)
93{
94	struct trapframe *tf = td->td_frame;
95
96	*onstack = sigonstack(tf->tf_usr_sp);
97	if (*onstack)
98		return (void*)(td->td_sigstk.ss_sp + td->td_sigstk.ss_size);
99	return (void*)(tf->tf_usr_sp);
100}
101
102void
103sendsig(catcher, sig, mask, code)
104	sig_t catcher;
105	int sig;
106	sigset_t *mask;
107	u_long code;
108{
109	struct thread *td = curthread;
110	struct trapframe *tf = td->td_frame;
111	struct sigframe *fp, frame;
112	struct sigacts *psp = td->td_proc->p_sigacts;
113	int onstack;
114
115	fp = getframe(td, sig, &onstack);
116	/* make room on the stack */
117	fp--;
118
119	/* make the stack aligned */
120	(u_int)fp = _ALIGN(fp);
121	/* Populate the siginfo frame. */
122	frame.sf_si.si_signo = sig;
123	frame.sf_si.si_code = code;
124	frame.sf_uc.uc_sigmask = *mask;
125	frame.sf_uc.uc_link = NULL;
126	frame.sf_uc.uc_flags |= td->td_sigstk.ss_flags & SS_ONSTACK ?
127	    _UC_SETSTACK : _UC_CLRSTACK;
128	memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack));
129	get_mcontext(td, &frame.sf_uc.uc_mcontext,
130	    (uint32_t)&frame.sf_uc.uc_flags);
131	PROC_UNLOCK(td->td_proc);
132	mtx_unlock(&psp->ps_mtx);
133	if (copyout(&frame, (void*)fp, sizeof(frame)) != 0)
134		sigexit(td, SIGILL);
135	/*
136	 * Build context to run handler in.  We invoke the handler
137	 * directly, only returning via the trampoline.  Note the
138	 * trampoline version numbers are coordinated with machine-
139	 * dependent code in libc.
140	 */
141
142	tf->tf_r0 = sig;
143	tf->tf_r1 = (int)&fp->sf_si;
144	tf->tf_r2 = (int)&fp->sf_uc;
145
146	/* the trampoline uses r5 as the uc address */
147	tf->tf_r5 = (int)&fp->sf_uc;
148	tf->tf_pc = (int)catcher;
149	tf->tf_usr_sp = (int)fp;
150	if (onstack)
151		td->td_sigstk.ss_flags |= SS_ONSTACK;
152	PROC_LOCK(td->td_proc);
153	mtx_lock(&psp->ps_mtx);
154}
155
156struct kva_md_info kmi;
157
158/*
159 * arm32_vector_init:
160 *
161 *	Initialize the vector page, and select whether or not to
162 *	relocate the vectors.
163 *
164 *	NOTE: We expect the vector page to be mapped at its expected
165 *	destination.
166 */
167
168extern unsigned int page0[], page0_data[];
169void
170arm_vector_init(vm_offset_t va, int which)
171{
172	unsigned int *vectors = (int *) va;
173	unsigned int *vectors_data = vectors + (page0_data - page0);
174	int vec;
175
176	/*
177	 * Loop through the vectors we're taking over, and copy the
178	 * vector's insn and data word.
179	 */
180	for (vec = 0; vec < ARM_NVEC; vec++) {
181		if ((which & (1 << vec)) == 0) {
182			/* Don't want to take over this vector. */
183			continue;
184		}
185		vectors[vec] = page0[vec];
186		vectors_data[vec] = page0_data[vec];
187	}
188
189	/* Now sync the vectors. */
190	cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int));
191
192	vector_page = va;
193
194	if (va == ARM_VECTORS_HIGH) {
195		/*
196		 * Assume the MD caller knows what it's doing here, and
197		 * really does want the vector page relocated.
198		 *
199		 * Note: This has to be done here (and not just in
200		 * cpu_setup()) because the vector page needs to be
201		 * accessible *before* cpu_startup() is called.
202		 * Think ddb(9) ...
203		 *
204		 * NOTE: If the CPU control register is not readable,
205		 * this will totally fail!  We'll just assume that
206		 * any system that has high vector support has a
207		 * readable CPU control register, for now.  If we
208		 * ever encounter one that does not, we'll have to
209		 * rethink this.
210		 */
211		cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC);
212	}
213}
214
215static void
216cpu_startup(void *dummy)
217{
218	struct pcb *pcb = thread0.td_pcb;
219	vm_ksubmap_init(&kmi);
220	bufinit();
221	vm_pager_bufferinit();
222	pcb->un_32.pcb32_und_sp = (u_int)thread0.td_kstack +
223	    USPACE_UNDEF_STACK_TOP;
224	pcb->un_32.pcb32_sp = (u_int)thread0.td_kstack +
225	    USPACE_SVC_STACK_TOP;
226	vector_page_setprot(VM_PROT_READ);
227	pmap_update(pmap_kernel());
228	pmap_set_pcb_pagedir(pmap_kernel(), pcb);
229	cpu_setup("");
230	identify_arm_cpu();
231	thread0.td_frame = (struct trapframe *)pcb->un_32.pcb32_sp - 1;
232}
233
234SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
235
236void
237cpu_idle(void)
238{
239}
240
241int
242fill_regs(struct thread *td, struct reg *regs)
243{
244	struct trapframe *tf = td->td_frame;
245	bcopy(&tf->tf_r0, regs->r, sizeof(regs->r));
246	regs->r_sp = tf->tf_usr_sp;
247	regs->r_lr = tf->tf_usr_lr;
248	regs->r_pc = tf->tf_pc;
249	regs->r_cpsr = tf->tf_spsr;
250	return (0);
251}
252int
253fill_fpregs(struct thread *td, struct fpreg *regs)
254{
255	bzero(regs, sizeof(*regs));
256	return (0);
257}
258
259int
260set_regs(struct thread *td, struct reg *regs)
261{
262	struct trapframe *tf = td->td_frame;
263
264	bcopy(regs->r, &tf->tf_r0, sizeof(*regs->r));
265	tf->tf_usr_sp = regs->r_sp;
266	tf->tf_usr_lr = regs->r_lr;
267	tf->tf_pc = regs->r_pc;
268	tf->tf_spsr &=  ~PSR_FLAGS;
269	tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS;
270	while(1);
271	return (0);
272}
273
274int
275set_fpregs(struct thread *td, struct fpreg *regs)
276{
277	return (0);
278}
279
280int
281fill_dbregs(struct thread *td, struct dbreg *regs)
282{
283	return (0);
284}
285int
286set_dbregs(struct thread *td, struct dbreg *regs)
287{
288	return (0);
289}
290
291void
292cpu_halt(void)
293{
294	cpu_reset();
295}
296
297int
298ptrace_single_step(struct thread *td)
299{
300	return (0);
301}
302
303int
304ptrace_set_pc(struct thread *td, unsigned long addr)
305{
306	return (0);
307}
308
309void
310cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
311{
312}
313
314/*
315 * Clear registers on exec
316 */
317void
318exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
319{
320	struct trapframe *tf = td->td_frame;
321
322	memset(tf, 0, sizeof(*tf));
323	tf->tf_usr_sp = stack;
324	tf->tf_usr_lr = entry;
325	tf->tf_svc_lr = 0x77777777;
326	tf->tf_pc = entry;
327	tf->tf_spsr = PSR_USR32_MODE;
328}
329
330/*
331 * Build siginfo_t for SA thread
332 */
333void
334cpu_thread_siginfo(int sig, u_long code, siginfo_t *si)
335{
336	printf("cpu_thread_siginfo\n");
337}
338
339/*
340 * Get machine context.
341 */
342int
343get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
344{
345	struct trapframe *tf = td->td_frame;
346	__greg_t *gr = mcp->__gregs;
347
348	/* Save General Register context. */
349	gr[_REG_R0]   = tf->tf_r0;
350	gr[_REG_R1]   = tf->tf_r1;
351	gr[_REG_R2]   = tf->tf_r2;
352	gr[_REG_R3]   = tf->tf_r3;
353	gr[_REG_R4]   = tf->tf_r4;
354	gr[_REG_R5]   = tf->tf_r5;
355	gr[_REG_R6]   = tf->tf_r6;
356	gr[_REG_R7]   = tf->tf_r7;
357	gr[_REG_R8]   = tf->tf_r8;
358	gr[_REG_R9]   = tf->tf_r9;
359	gr[_REG_R10]  = tf->tf_r10;
360	gr[_REG_R11]  = tf->tf_r11;
361	gr[_REG_R12]  = tf->tf_r12;
362	gr[_REG_SP]   = tf->tf_usr_sp;
363	gr[_REG_LR]   = tf->tf_usr_lr;
364	gr[_REG_PC]   = tf->tf_pc;
365	gr[_REG_CPSR] = tf->tf_spsr;
366
367	return (0);
368}
369
370/*
371 * Set machine context.
372 *
373 * However, we don't set any but the user modifiable flags, and we won't
374 * touch the cs selector.
375 */
376int
377set_mcontext(struct thread *td, const mcontext_t *mcp)
378{
379	panic("SET_MCONTEXT AHAHAH\n");
380	return (0);
381}
382
383#ifdef COMPAT_FREEBSD4
384int
385freebsd4_sigreturn(td, uap)
386	struct thread *td;
387	struct freebsd4_sigreturn_args /* {
388		const ucontext4 *sigcntxp;
389	} */ *uap;
390{
391	return (0);
392}
393#endif
394
395/*
396 * MPSAFE
397 */
398int
399sigreturn(td, uap)
400	struct thread *td;
401	struct sigreturn_args /* {
402		const __ucontext *sigcntxp;
403	} */ *uap;
404{
405	return (0);
406}
407
408
409/*
410 * Construct a PCB from a trapframe. This is called from kdb_trap() where
411 * we want to start a backtrace from the function that caused us to enter
412 * the debugger. We have the context in the trapframe, but base the trace
413 * on the PCB. The PCB doesn't have to be perfect, as long as it contains
414 * enough for a backtrace.
415 */
416void
417makectx(struct trapframe *tf, struct pcb *pcb)
418{
419	pcb->un_32.pcb32_r8 = tf->tf_r8;
420	pcb->un_32.pcb32_r9 = tf->tf_r9;
421	pcb->un_32.pcb32_r10 = tf->tf_r10;
422	pcb->un_32.pcb32_r11 = tf->tf_r11;
423	pcb->un_32.pcb32_r12 = tf->tf_r12;
424	pcb->un_32.pcb32_pc = tf->tf_pc;
425	pcb->un_32.pcb32_lr = tf->tf_usr_lr;
426	pcb->un_32.pcb32_sp = tf->tf_usr_sp;
427}
428