machdep.c revision 129198
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 129198 2004-05-14 11:46:45Z 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;
89int astpending = 0;
90vm_offset_t vector_page;
91
92static void *
93getframe(struct thread *td, int sig, int *onstack)
94{
95	struct trapframe *tf = td->td_frame;
96
97	*onstack = sigonstack(tf->tf_usr_sp);
98	if (*onstack)
99		return (void*)(td->td_sigstk.ss_sp + td->td_sigstk.ss_size);
100	return (void*)(tf->tf_usr_sp);
101}
102
103void
104sendsig(catcher, sig, mask, code)
105	sig_t catcher;
106	int sig;
107	sigset_t *mask;
108	u_long code;
109{
110	struct thread *td = curthread;
111	struct trapframe *tf = td->td_frame;
112	struct sigframe *fp, frame;
113	struct sigacts *psp = td->td_proc->p_sigacts;
114	int onstack;
115
116	fp = getframe(td, sig, &onstack);
117	/* make room on the stack */
118	fp--;
119
120	/* make the stack aligned */
121	(u_int)fp = _ALIGN(fp);
122	/* Populate the siginfo frame. */
123	frame.sf_si.si_signo = sig;
124	frame.sf_si.si_code = code;
125	frame.sf_uc.uc_sigmask = *mask;
126	frame.sf_uc.uc_link = NULL;
127	frame.sf_uc.uc_flags |= td->td_sigstk.ss_flags & SS_ONSTACK ?
128	    _UC_SETSTACK : _UC_CLRSTACK;
129	memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack));
130	get_mcontext(td, &frame.sf_uc.uc_mcontext,
131	    (uint32_t)&frame.sf_uc.uc_flags);
132	PROC_UNLOCK(td->td_proc);
133	mtx_unlock(&psp->ps_mtx);
134	if (copyout(&frame, (void*)fp, sizeof(frame)) != 0)
135		sigexit(td, SIGILL);
136	/*
137	 * Build context to run handler in.  We invoke the handler
138	 * directly, only returning via the trampoline.  Note the
139	 * trampoline version numbers are coordinated with machine-
140	 * dependent code in libc.
141	 */
142
143	tf->tf_r0 = sig;
144	tf->tf_r1 = (int)&fp->sf_si;
145	tf->tf_r2 = (int)&fp->sf_uc;
146
147	/* the trampoline uses r5 as the uc address */
148	tf->tf_r5 = (int)&fp->sf_uc;
149	tf->tf_pc = (int)catcher;
150	tf->tf_usr_sp = (int)fp;
151	if (onstack)
152		td->td_sigstk.ss_flags |= SS_ONSTACK;
153	PROC_LOCK(td->td_proc);
154	mtx_lock(&psp->ps_mtx);
155}
156
157struct kva_md_info kmi;
158
159/*
160 * arm32_vector_init:
161 *
162 *	Initialize the vector page, and select whether or not to
163 *	relocate the vectors.
164 *
165 *	NOTE: We expect the vector page to be mapped at its expected
166 *	destination.
167 */
168
169extern unsigned int page0[], page0_data[];
170void
171arm_vector_init(vm_offset_t va, int which)
172{
173	unsigned int *vectors = (int *) va;
174	unsigned int *vectors_data = vectors + (page0_data - page0);
175	int vec;
176
177	/*
178	 * Loop through the vectors we're taking over, and copy the
179	 * vector's insn and data word.
180	 */
181	for (vec = 0; vec < ARM_NVEC; vec++) {
182		if ((which & (1 << vec)) == 0) {
183			/* Don't want to take over this vector. */
184			continue;
185		}
186		vectors[vec] = page0[vec];
187		vectors_data[vec] = page0_data[vec];
188	}
189
190	/* Now sync the vectors. */
191	cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int));
192
193	vector_page = va;
194
195	if (va == ARM_VECTORS_HIGH) {
196		/*
197		 * Assume the MD caller knows what it's doing here, and
198		 * really does want the vector page relocated.
199		 *
200		 * Note: This has to be done here (and not just in
201		 * cpu_setup()) because the vector page needs to be
202		 * accessible *before* cpu_startup() is called.
203		 * Think ddb(9) ...
204		 *
205		 * NOTE: If the CPU control register is not readable,
206		 * this will totally fail!  We'll just assume that
207		 * any system that has high vector support has a
208		 * readable CPU control register, for now.  If we
209		 * ever encounter one that does not, we'll have to
210		 * rethink this.
211		 */
212		cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC);
213	}
214}
215
216static void
217cpu_startup(void *dummy)
218{
219	struct pcb *pcb = thread0.td_pcb;
220	vm_ksubmap_init(&kmi);
221	bufinit();
222	vm_pager_bufferinit();
223	pcb->un_32.pcb32_und_sp = (u_int)thread0.td_kstack +
224	    USPACE_UNDEF_STACK_TOP;
225	pcb->un_32.pcb32_sp = (u_int)thread0.td_kstack +
226	    USPACE_SVC_STACK_TOP;
227	vector_page_setprot(VM_PROT_READ);
228	pmap_update(pmap_kernel());
229	pmap_set_pcb_pagedir(pmap_kernel(), pcb);
230	cpu_setup("");
231	identify_arm_cpu();
232	thread0.td_frame = (struct trapframe *)pcb->un_32.pcb32_sp - 1;
233}
234
235SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
236
237void
238cpu_idle(void)
239{
240}
241
242int
243fill_regs(struct thread *td, struct reg *regs)
244{
245	struct trapframe *tf = td->td_frame;
246	bcopy(&tf->tf_r0, regs->r, sizeof(regs->r));
247	regs->r_sp = tf->tf_usr_sp;
248	regs->r_lr = tf->tf_usr_lr;
249	regs->r_pc = tf->tf_pc;
250	regs->r_cpsr = tf->tf_spsr;
251	return (0);
252}
253int
254fill_fpregs(struct thread *td, struct fpreg *regs)
255{
256	bzero(regs, sizeof(*regs));
257	return (0);
258}
259
260int
261set_regs(struct thread *td, struct reg *regs)
262{
263	struct trapframe *tf = td->td_frame;
264
265	bcopy(regs->r, &tf->tf_r0, sizeof(*regs->r));
266	tf->tf_usr_sp = regs->r_sp;
267	tf->tf_usr_lr = regs->r_lr;
268	tf->tf_pc = regs->r_pc;
269	tf->tf_spsr &=  ~PSR_FLAGS;
270	tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS;
271	while(1);
272	return (0);
273}
274
275int
276set_fpregs(struct thread *td, struct fpreg *regs)
277{
278	return (0);
279}
280
281int
282fill_dbregs(struct thread *td, struct dbreg *regs)
283{
284	return (0);
285}
286int
287set_dbregs(struct thread *td, struct dbreg *regs)
288{
289	return (0);
290}
291
292void
293cpu_halt(void)
294{
295	cpu_reset();
296}
297
298int
299ptrace_single_step(struct thread *td)
300{
301	return (0);
302}
303
304int
305ptrace_set_pc(struct thread *td, unsigned long addr)
306{
307	return (0);
308}
309
310void
311cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
312{
313}
314
315/*
316 * Clear registers on exec
317 */
318void
319exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
320{
321	struct trapframe *tf = td->td_frame;
322
323	memset(tf, 0, sizeof(*tf));
324	tf->tf_usr_sp = stack;
325	tf->tf_usr_lr = entry;
326	tf->tf_svc_lr = 0x77777777;
327	tf->tf_pc = entry;
328	tf->tf_spsr = PSR_USR32_MODE;
329}
330
331/*
332 * Build siginfo_t for SA thread
333 */
334void
335cpu_thread_siginfo(int sig, u_long code, siginfo_t *si)
336{
337	printf("cpu_thread_siginfo\n");
338}
339
340/*
341 * Get machine context.
342 */
343int
344get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
345{
346	struct trapframe *tf = td->td_frame;
347	__greg_t *gr = mcp->__gregs;
348
349	/* Save General Register context. */
350	gr[_REG_R0]   = tf->tf_r0;
351	gr[_REG_R1]   = tf->tf_r1;
352	gr[_REG_R2]   = tf->tf_r2;
353	gr[_REG_R3]   = tf->tf_r3;
354	gr[_REG_R4]   = tf->tf_r4;
355	gr[_REG_R5]   = tf->tf_r5;
356	gr[_REG_R6]   = tf->tf_r6;
357	gr[_REG_R7]   = tf->tf_r7;
358	gr[_REG_R8]   = tf->tf_r8;
359	gr[_REG_R9]   = tf->tf_r9;
360	gr[_REG_R10]  = tf->tf_r10;
361	gr[_REG_R11]  = tf->tf_r11;
362	gr[_REG_R12]  = tf->tf_r12;
363	gr[_REG_SP]   = tf->tf_usr_sp;
364	gr[_REG_LR]   = tf->tf_usr_lr;
365	gr[_REG_PC]   = tf->tf_pc;
366	gr[_REG_CPSR] = tf->tf_spsr;
367
368	return (0);
369}
370
371/*
372 * Set machine context.
373 *
374 * However, we don't set any but the user modifiable flags, and we won't
375 * touch the cs selector.
376 */
377int
378set_mcontext(struct thread *td, const mcontext_t *mcp)
379{
380	panic("SET_MCONTEXT AHAHAH\n");
381	return (0);
382}
383
384#ifdef COMPAT_FREEBSD4
385int
386freebsd4_sigreturn(td, uap)
387	struct thread *td;
388	struct freebsd4_sigreturn_args /* {
389		const ucontext4 *sigcntxp;
390	} */ *uap;
391{
392	return (0);
393}
394#endif
395
396/*
397 * MPSAFE
398 */
399int
400sigreturn(td, uap)
401	struct thread *td;
402	struct sigreturn_args /* {
403		const __ucontext *sigcntxp;
404	} */ *uap;
405{
406	return (0);
407}
408
409
410