1433d6423SLionel Sambuc /* system dependent functions for use inside the whole kernel. */
2433d6423SLionel Sambuc
3433d6423SLionel Sambuc #include "kernel/kernel.h"
4433d6423SLionel Sambuc
5433d6423SLionel Sambuc #include <unistd.h>
6433d6423SLionel Sambuc #include <ctype.h>
7433d6423SLionel Sambuc #include <string.h>
8433d6423SLionel Sambuc #include <minix/cpufeature.h>
9433d6423SLionel Sambuc #include <assert.h>
10433d6423SLionel Sambuc #include <signal.h>
11433d6423SLionel Sambuc #include <machine/vm.h>
12433d6423SLionel Sambuc #include <machine/signal.h>
13433d6423SLionel Sambuc #include <arm/armreg.h>
14433d6423SLionel Sambuc
15433d6423SLionel Sambuc #include <minix/u64.h>
16433d6423SLionel Sambuc
17433d6423SLionel Sambuc #include "archconst.h"
18433d6423SLionel Sambuc #include "arch_proto.h"
19433d6423SLionel Sambuc #include "kernel/proc.h"
20433d6423SLionel Sambuc #include "kernel/debug.h"
21433d6423SLionel Sambuc #include "ccnt.h"
22433d6423SLionel Sambuc #include "bsp_init.h"
23433d6423SLionel Sambuc #include "bsp_serial.h"
24433d6423SLionel Sambuc
25433d6423SLionel Sambuc #include "glo.h"
26433d6423SLionel Sambuc
27433d6423SLionel Sambuc void * k_stacks;
28433d6423SLionel Sambuc
29433d6423SLionel Sambuc
fpu_init(void)30433d6423SLionel Sambuc void fpu_init(void)
31433d6423SLionel Sambuc {
32433d6423SLionel Sambuc }
33433d6423SLionel Sambuc
save_local_fpu(struct proc * pr,int retain)34433d6423SLionel Sambuc void save_local_fpu(struct proc *pr, int retain)
35433d6423SLionel Sambuc {
36433d6423SLionel Sambuc }
37433d6423SLionel Sambuc
save_fpu(struct proc * pr)38433d6423SLionel Sambuc void save_fpu(struct proc *pr)
39433d6423SLionel Sambuc {
40433d6423SLionel Sambuc }
41433d6423SLionel Sambuc
arch_proc_reset(struct proc * pr)42433d6423SLionel Sambuc void arch_proc_reset(struct proc *pr)
43433d6423SLionel Sambuc {
44433d6423SLionel Sambuc assert(pr->p_nr < NR_PROCS);
45433d6423SLionel Sambuc
46433d6423SLionel Sambuc /* Clear process state. */
47433d6423SLionel Sambuc memset(&pr->p_reg, 0, sizeof(pr->p_reg));
48433d6423SLionel Sambuc if(iskerneln(pr->p_nr)) {
49433d6423SLionel Sambuc pr->p_reg.psr = INIT_TASK_PSR;
50433d6423SLionel Sambuc } else {
51433d6423SLionel Sambuc pr->p_reg.psr = INIT_PSR;
52433d6423SLionel Sambuc }
53433d6423SLionel Sambuc }
54433d6423SLionel Sambuc
arch_proc_setcontext(struct proc * p,struct stackframe_s * state,int isuser,int trapstyle)55433d6423SLionel Sambuc void arch_proc_setcontext(struct proc *p, struct stackframe_s *state,
56433d6423SLionel Sambuc int isuser, int trapstyle)
57433d6423SLionel Sambuc {
58433d6423SLionel Sambuc assert(sizeof(p->p_reg) == sizeof(*state));
59433d6423SLionel Sambuc if(state != &p->p_reg) {
60433d6423SLionel Sambuc memcpy(&p->p_reg, state, sizeof(*state));
61433d6423SLionel Sambuc }
62433d6423SLionel Sambuc
63433d6423SLionel Sambuc /* further code is instructed to not touch the context
64433d6423SLionel Sambuc * any more
65433d6423SLionel Sambuc */
66433d6423SLionel Sambuc p->p_misc_flags |= MF_CONTEXT_SET;
67433d6423SLionel Sambuc
68433d6423SLionel Sambuc if(!(p->p_rts_flags)) {
69433d6423SLionel Sambuc printf("WARNINIG: setting full context of runnable process\n");
70433d6423SLionel Sambuc print_proc(p);
71433d6423SLionel Sambuc util_stacktrace();
72433d6423SLionel Sambuc }
73433d6423SLionel Sambuc }
74433d6423SLionel Sambuc
arch_set_secondary_ipc_return(struct proc * p,u32_t val)75433d6423SLionel Sambuc void arch_set_secondary_ipc_return(struct proc *p, u32_t val)
76433d6423SLionel Sambuc {
77433d6423SLionel Sambuc p->p_reg.r1 = val;
78433d6423SLionel Sambuc }
79433d6423SLionel Sambuc
restore_fpu(struct proc * pr)80433d6423SLionel Sambuc int restore_fpu(struct proc *pr)
81433d6423SLionel Sambuc {
82433d6423SLionel Sambuc return 0;
83433d6423SLionel Sambuc }
84433d6423SLionel Sambuc
cpu_identify(void)85433d6423SLionel Sambuc void cpu_identify(void)
86433d6423SLionel Sambuc {
87433d6423SLionel Sambuc u32_t midr;
88433d6423SLionel Sambuc unsigned cpu = cpuid;
89433d6423SLionel Sambuc
90433d6423SLionel Sambuc asm volatile("mrc p15, 0, %[midr], c0, c0, 0 @ read MIDR\n\t"
91433d6423SLionel Sambuc : [midr] "=r" (midr));
92433d6423SLionel Sambuc
93433d6423SLionel Sambuc cpu_info[cpu].implementer = midr >> 24;
94433d6423SLionel Sambuc cpu_info[cpu].variant = (midr >> 20) & 0xF;
95433d6423SLionel Sambuc cpu_info[cpu].arch = (midr >> 16) & 0xF;
96433d6423SLionel Sambuc cpu_info[cpu].part = (midr >> 4) & 0xFFF;
97433d6423SLionel Sambuc cpu_info[cpu].revision = midr & 0xF;
98433d6423SLionel Sambuc cpu_info[cpu].freq = 660; /* 660 Mhz hardcoded */
99433d6423SLionel Sambuc }
100433d6423SLionel Sambuc
arch_init(void)101433d6423SLionel Sambuc void arch_init(void)
102433d6423SLionel Sambuc {
103433d6423SLionel Sambuc u32_t value;
104433d6423SLionel Sambuc
105433d6423SLionel Sambuc k_stacks = (void*) &k_stacks_start;
106433d6423SLionel Sambuc assert(!((vir_bytes) k_stacks % K_STACK_SIZE));
107433d6423SLionel Sambuc
108433d6423SLionel Sambuc #ifndef CONFIG_SMP
109433d6423SLionel Sambuc /*
110433d6423SLionel Sambuc * use stack 0 and cpu id 0 on a single processor machine, SMP
111433d6423SLionel Sambuc * configuration does this in smp_init() for all cpus at once
112433d6423SLionel Sambuc */
113433d6423SLionel Sambuc tss_init(0, get_k_stack_top(0));
114433d6423SLionel Sambuc #endif
115433d6423SLionel Sambuc
116433d6423SLionel Sambuc
117433d6423SLionel Sambuc /* enable user space access to cycle counter */
118433d6423SLionel Sambuc /* set cycle counter to 0: ARM ARM B4.1.113 and B4.1.117 */
119433d6423SLionel Sambuc asm volatile ("MRC p15, 0, %0, c9, c12, 0\t\n": "=r" (value));
120433d6423SLionel Sambuc value |= PMU_PMCR_C; /* Reset counter */
121433d6423SLionel Sambuc value |= PMU_PMCR_E; /* Enable counter hardware */
122433d6423SLionel Sambuc asm volatile ("MCR p15, 0, %0, c9, c12, 0\t\n": : "r" (value));
123433d6423SLionel Sambuc
124433d6423SLionel Sambuc /* enable CCNT counting: ARM ARM B4.1.116 */
125433d6423SLionel Sambuc value = PMU_PMCNTENSET_C; /* Enable PMCCNTR cycle counter */
126433d6423SLionel Sambuc asm volatile ("MCR p15, 0, %0, c9, c12, 1\t\n": : "r" (value));
127433d6423SLionel Sambuc
128433d6423SLionel Sambuc /* enable cycle counter in user mode: ARM ARM B4.1.124 */
129433d6423SLionel Sambuc value = PMU_PMUSERENR_EN;
130433d6423SLionel Sambuc asm volatile ("MCR p15, 0, %0, c9, c14, 0\t\n": : "r" (value));
131433d6423SLionel Sambuc bsp_init();
132433d6423SLionel Sambuc }
133433d6423SLionel Sambuc
134433d6423SLionel Sambuc /*===========================================================================*
135433d6423SLionel Sambuc * do_ser_debug *
136433d6423SLionel Sambuc *===========================================================================*/
do_ser_debug(void)137*6077d1adSDr. Florian Grätz void do_ser_debug(void)
138433d6423SLionel Sambuc {
139433d6423SLionel Sambuc }
140433d6423SLionel Sambuc
arch_do_syscall(struct proc * proc)141433d6423SLionel Sambuc void arch_do_syscall(struct proc *proc)
142433d6423SLionel Sambuc {
143433d6423SLionel Sambuc /* do_ipc assumes that it's running because of the current process */
144433d6423SLionel Sambuc assert(proc == get_cpulocal_var(proc_ptr));
145433d6423SLionel Sambuc /* Make the system call, for real this time. */
146433d6423SLionel Sambuc proc->p_reg.retreg =
147433d6423SLionel Sambuc do_ipc(proc->p_reg.retreg, proc->p_reg.r1, proc->p_reg.r2);
148433d6423SLionel Sambuc }
149433d6423SLionel Sambuc
150433d6423SLionel Sambuc reg_t svc_stack;
151433d6423SLionel Sambuc
arch_finish_switch_to_user(void)152433d6423SLionel Sambuc struct proc * arch_finish_switch_to_user(void)
153433d6423SLionel Sambuc {
154433d6423SLionel Sambuc char * stk;
155433d6423SLionel Sambuc struct proc * p;
156433d6423SLionel Sambuc
157433d6423SLionel Sambuc #ifdef CONFIG_SMP
158433d6423SLionel Sambuc stk = (char *)tss[cpuid].sp0;
159433d6423SLionel Sambuc #else
160433d6423SLionel Sambuc stk = (char *)tss[0].sp0;
161433d6423SLionel Sambuc #endif
162433d6423SLionel Sambuc svc_stack = (reg_t)stk;
163433d6423SLionel Sambuc /* set pointer to the process to run on the stack */
164433d6423SLionel Sambuc p = get_cpulocal_var(proc_ptr);
165433d6423SLionel Sambuc *((reg_t *)stk) = (reg_t) p;
166433d6423SLionel Sambuc
167433d6423SLionel Sambuc /* turn interrupts on */
168433d6423SLionel Sambuc p->p_reg.psr &= ~(PSR_I|PSR_F);
169433d6423SLionel Sambuc
170433d6423SLionel Sambuc return p;
171433d6423SLionel Sambuc }
172433d6423SLionel Sambuc
fpu_sigcontext(struct proc * pr,struct sigframe_sigcontext * fr,struct sigcontext * sc)173433d6423SLionel Sambuc void fpu_sigcontext(struct proc *pr, struct sigframe_sigcontext *fr, struct sigcontext *sc)
174433d6423SLionel Sambuc {
175433d6423SLionel Sambuc }
176433d6423SLionel Sambuc
arch_get_sp(struct proc * p)177433d6423SLionel Sambuc reg_t arch_get_sp(struct proc *p) { return p->p_reg.sp; }
178433d6423SLionel Sambuc
get_randomness(struct k_randomness * rand,int source)179433d6423SLionel Sambuc void get_randomness(struct k_randomness *rand, int source)
180433d6423SLionel Sambuc {
181433d6423SLionel Sambuc }
182433d6423SLionel Sambuc
arch_ser_init(void)183433d6423SLionel Sambuc void arch_ser_init(void)
184433d6423SLionel Sambuc {
185433d6423SLionel Sambuc bsp_ser_init();
186433d6423SLionel Sambuc }
187433d6423SLionel Sambuc
188433d6423SLionel Sambuc /*===========================================================================*/
189433d6423SLionel Sambuc /* __switch_address_space */
190433d6423SLionel Sambuc /*===========================================================================*/
191433d6423SLionel Sambuc /*
192433d6423SLionel Sambuc * sets the ttbr register to the supplied value if it is not already set to the
193433d6423SLionel Sambuc * same value in which case it would only result in an extra TLB flush which is
194433d6423SLionel Sambuc * not desirable
195433d6423SLionel Sambuc */
__switch_address_space(struct proc * p,struct proc ** __ptproc)196433d6423SLionel Sambuc void __switch_address_space(struct proc *p, struct proc **__ptproc)
197433d6423SLionel Sambuc {
198433d6423SLionel Sambuc reg_t orig_ttbr, new_ttbr;
199433d6423SLionel Sambuc
200433d6423SLionel Sambuc new_ttbr = p->p_seg.p_ttbr;
201433d6423SLionel Sambuc if (new_ttbr == 0)
202433d6423SLionel Sambuc return;
203433d6423SLionel Sambuc
204433d6423SLionel Sambuc orig_ttbr = read_ttbr0();
205433d6423SLionel Sambuc
206433d6423SLionel Sambuc /*
207433d6423SLionel Sambuc * test if ttbr is loaded with the current value to avoid unnecessary
208433d6423SLionel Sambuc * TLB flushes
209433d6423SLionel Sambuc */
210433d6423SLionel Sambuc if (new_ttbr == orig_ttbr)
211433d6423SLionel Sambuc return;
212433d6423SLionel Sambuc
213433d6423SLionel Sambuc write_ttbr0(new_ttbr);
214433d6423SLionel Sambuc
215433d6423SLionel Sambuc *__ptproc = p;
216433d6423SLionel Sambuc
217433d6423SLionel Sambuc return;
218433d6423SLionel Sambuc }
219