1 /* system dependent functions for use inside the whole kernel. */
2
3 #include "kernel/kernel.h"
4
5 #include <unistd.h>
6 #include <ctype.h>
7 #include <string.h>
8 #include <minix/cpufeature.h>
9 #include <assert.h>
10 #include <signal.h>
11 #include <machine/vm.h>
12 #include <machine/signal.h>
13 #include <arm/armreg.h>
14
15 #include <minix/u64.h>
16
17 #include "archconst.h"
18 #include "arch_proto.h"
19 #include "kernel/proc.h"
20 #include "kernel/debug.h"
21 #include "ccnt.h"
22 #include "bsp_init.h"
23 #include "bsp_serial.h"
24
25 #include "glo.h"
26
27 void * k_stacks;
28
29
fpu_init(void)30 void fpu_init(void)
31 {
32 }
33
save_local_fpu(struct proc * pr,int retain)34 void save_local_fpu(struct proc *pr, int retain)
35 {
36 }
37
save_fpu(struct proc * pr)38 void save_fpu(struct proc *pr)
39 {
40 }
41
arch_proc_reset(struct proc * pr)42 void arch_proc_reset(struct proc *pr)
43 {
44 assert(pr->p_nr < NR_PROCS);
45
46 /* Clear process state. */
47 memset(&pr->p_reg, 0, sizeof(pr->p_reg));
48 if(iskerneln(pr->p_nr)) {
49 pr->p_reg.psr = INIT_TASK_PSR;
50 } else {
51 pr->p_reg.psr = INIT_PSR;
52 }
53 }
54
arch_proc_setcontext(struct proc * p,struct stackframe_s * state,int isuser,int trapstyle)55 void arch_proc_setcontext(struct proc *p, struct stackframe_s *state,
56 int isuser, int trapstyle)
57 {
58 assert(sizeof(p->p_reg) == sizeof(*state));
59 if(state != &p->p_reg) {
60 memcpy(&p->p_reg, state, sizeof(*state));
61 }
62
63 /* further code is instructed to not touch the context
64 * any more
65 */
66 p->p_misc_flags |= MF_CONTEXT_SET;
67
68 if(!(p->p_rts_flags)) {
69 printf("WARNINIG: setting full context of runnable process\n");
70 print_proc(p);
71 util_stacktrace();
72 }
73 }
74
arch_set_secondary_ipc_return(struct proc * p,u32_t val)75 void arch_set_secondary_ipc_return(struct proc *p, u32_t val)
76 {
77 p->p_reg.r1 = val;
78 }
79
restore_fpu(struct proc * pr)80 int restore_fpu(struct proc *pr)
81 {
82 return 0;
83 }
84
cpu_identify(void)85 void cpu_identify(void)
86 {
87 u32_t midr;
88 unsigned cpu = cpuid;
89
90 asm volatile("mrc p15, 0, %[midr], c0, c0, 0 @ read MIDR\n\t"
91 : [midr] "=r" (midr));
92
93 cpu_info[cpu].implementer = midr >> 24;
94 cpu_info[cpu].variant = (midr >> 20) & 0xF;
95 cpu_info[cpu].arch = (midr >> 16) & 0xF;
96 cpu_info[cpu].part = (midr >> 4) & 0xFFF;
97 cpu_info[cpu].revision = midr & 0xF;
98 cpu_info[cpu].freq = 660; /* 660 Mhz hardcoded */
99 }
100
arch_init(void)101 void arch_init(void)
102 {
103 u32_t value;
104
105 k_stacks = (void*) &k_stacks_start;
106 assert(!((vir_bytes) k_stacks % K_STACK_SIZE));
107
108 #ifndef CONFIG_SMP
109 /*
110 * use stack 0 and cpu id 0 on a single processor machine, SMP
111 * configuration does this in smp_init() for all cpus at once
112 */
113 tss_init(0, get_k_stack_top(0));
114 #endif
115
116
117 /* enable user space access to cycle counter */
118 /* set cycle counter to 0: ARM ARM B4.1.113 and B4.1.117 */
119 asm volatile ("MRC p15, 0, %0, c9, c12, 0\t\n": "=r" (value));
120 value |= PMU_PMCR_C; /* Reset counter */
121 value |= PMU_PMCR_E; /* Enable counter hardware */
122 asm volatile ("MCR p15, 0, %0, c9, c12, 0\t\n": : "r" (value));
123
124 /* enable CCNT counting: ARM ARM B4.1.116 */
125 value = PMU_PMCNTENSET_C; /* Enable PMCCNTR cycle counter */
126 asm volatile ("MCR p15, 0, %0, c9, c12, 1\t\n": : "r" (value));
127
128 /* enable cycle counter in user mode: ARM ARM B4.1.124 */
129 value = PMU_PMUSERENR_EN;
130 asm volatile ("MCR p15, 0, %0, c9, c14, 0\t\n": : "r" (value));
131 bsp_init();
132 }
133
134 /*===========================================================================*
135 * do_ser_debug *
136 *===========================================================================*/
do_ser_debug(void)137 void do_ser_debug(void)
138 {
139 }
140
arch_do_syscall(struct proc * proc)141 void arch_do_syscall(struct proc *proc)
142 {
143 /* do_ipc assumes that it's running because of the current process */
144 assert(proc == get_cpulocal_var(proc_ptr));
145 /* Make the system call, for real this time. */
146 proc->p_reg.retreg =
147 do_ipc(proc->p_reg.retreg, proc->p_reg.r1, proc->p_reg.r2);
148 }
149
150 reg_t svc_stack;
151
arch_finish_switch_to_user(void)152 struct proc * arch_finish_switch_to_user(void)
153 {
154 char * stk;
155 struct proc * p;
156
157 #ifdef CONFIG_SMP
158 stk = (char *)tss[cpuid].sp0;
159 #else
160 stk = (char *)tss[0].sp0;
161 #endif
162 svc_stack = (reg_t)stk;
163 /* set pointer to the process to run on the stack */
164 p = get_cpulocal_var(proc_ptr);
165 *((reg_t *)stk) = (reg_t) p;
166
167 /* turn interrupts on */
168 p->p_reg.psr &= ~(PSR_I|PSR_F);
169
170 return p;
171 }
172
fpu_sigcontext(struct proc * pr,struct sigframe_sigcontext * fr,struct sigcontext * sc)173 void fpu_sigcontext(struct proc *pr, struct sigframe_sigcontext *fr, struct sigcontext *sc)
174 {
175 }
176
arch_get_sp(struct proc * p)177 reg_t arch_get_sp(struct proc *p) { return p->p_reg.sp; }
178
get_randomness(struct k_randomness * rand,int source)179 void get_randomness(struct k_randomness *rand, int source)
180 {
181 }
182
arch_ser_init(void)183 void arch_ser_init(void)
184 {
185 bsp_ser_init();
186 }
187
188 /*===========================================================================*/
189 /* __switch_address_space */
190 /*===========================================================================*/
191 /*
192 * sets the ttbr register to the supplied value if it is not already set to the
193 * same value in which case it would only result in an extra TLB flush which is
194 * not desirable
195 */
__switch_address_space(struct proc * p,struct proc ** __ptproc)196 void __switch_address_space(struct proc *p, struct proc **__ptproc)
197 {
198 reg_t orig_ttbr, new_ttbr;
199
200 new_ttbr = p->p_seg.p_ttbr;
201 if (new_ttbr == 0)
202 return;
203
204 orig_ttbr = read_ttbr0();
205
206 /*
207 * test if ttbr is loaded with the current value to avoid unnecessary
208 * TLB flushes
209 */
210 if (new_ttbr == orig_ttbr)
211 return;
212
213 write_ttbr0(new_ttbr);
214
215 *__ptproc = p;
216
217 return;
218 }
219