1 /* This file contains code for initialization of protected mode, to initialize
2 * code and data segment descriptors, and to initialize global descriptors
3 * for local descriptors in the process table.
4 */
5
6 #include <assert.h>
7 #include <string.h>
8
9 #include <machine/multiboot.h>
10
11 #include "kernel/kernel.h"
12
13 #include "archconst.h"
14 #include "arch_proto.h"
15
16 #include <sys/exec.h>
17 #include <libexec.h>
18
19 struct tss_s tss[CONFIG_MAX_CPUS];
20 extern int exc_vector_table;
21
22 int prot_init_done = 0;
23
vir2phys(void * vir)24 phys_bytes vir2phys(void *vir)
25 {
26 /* defined in kernel.lds */
27 extern char _kern_vir_base, _kern_phys_base;
28 u32_t offset = (vir_bytes) &_kern_vir_base -
29 (vir_bytes) &_kern_phys_base;
30 return (phys_bytes)vir - offset;
31 }
32
tss_init(unsigned cpu,void * kernel_stack)33 int tss_init(unsigned cpu, void * kernel_stack)
34 {
35
36 struct tss_s * t = &tss[cpu];
37
38 /*
39 * make space for process pointer and cpu id and point to the first
40 * usable word
41 */
42 t->sp0 = ((unsigned) kernel_stack) - ARM_STACK_TOP_RESERVED;
43 /*
44 * set the cpu id at the top of the stack so we know on which cpu is
45 * this stack in use when we trap to kernel
46 */
47 *((reg_t *)(t->sp0 + 1 * sizeof(reg_t))) = cpu;
48
49 return 0;
50 }
51
bootmod(int pnr)52 multiboot_module_t *bootmod(int pnr)
53 {
54 int i;
55
56 assert(pnr >= 0);
57
58 /* Search for desired process in boot process
59 * list. The first NR_TASKS ones do not correspond
60 * to a module, however, so we don't search those.
61 */
62 for(i = NR_TASKS; i < NR_BOOT_PROCS; i++) {
63 int p;
64 p = i - NR_TASKS;
65 if(image[i].proc_nr == pnr) {
66 assert(p < MULTIBOOT_MAX_MODS);
67 assert(p < kinfo.mbi.mi_mods_count);
68 return &kinfo.module_list[p];
69 }
70 }
71
72 panic("boot module %d not found", pnr);
73 }
74
75 int booting_cpu = 0;
76
prot_init(void)77 void prot_init(void)
78 {
79 /* tell the HW where we stored our vector table */
80 write_vbar((reg_t)&exc_vector_table);
81
82 /* Set up a new post-relocate bootstrap pagetable so that
83 * we can map in VM, and we no longer rely on pre-relocated
84 * data.
85 */
86
87 pg_clear();
88 pg_identity(&kinfo); /* Still need 1:1 for device memory . */
89 pg_mapkernel();
90 pg_load();
91
92 prot_init_done = 1;
93 }
94
95 static int alloc_for_vm = 0;
96
arch_post_init(void)97 void arch_post_init(void)
98 {
99 /* Let memory mapping code know what's going on at bootstrap time */
100 struct proc *vm;
101 vm = proc_addr(VM_PROC_NR);
102 get_cpulocal_var(ptproc) = vm;
103 pg_info(&vm->p_seg.p_ttbr, &vm->p_seg.p_ttbr_v);
104 }
105
libexec_pg_alloc(struct exec_info * execi,vir_bytes vaddr,size_t len)106 static int libexec_pg_alloc(struct exec_info *execi, vir_bytes vaddr, size_t len)
107 {
108 pg_map(PG_ALLOCATEME, vaddr, vaddr+len, &kinfo);
109 pg_load();
110 memset((char *) vaddr, 0, len);
111 alloc_for_vm += len;
112 return OK;
113 }
114
arch_boot_proc(struct boot_image * ip,struct proc * rp)115 void arch_boot_proc(struct boot_image *ip, struct proc *rp)
116 {
117 multiboot_module_t *mod;
118 struct ps_strings *psp;
119 char *sp;
120
121 if(rp->p_nr < 0) return;
122
123 mod = bootmod(rp->p_nr);
124
125 /* Important special case: we put VM in the bootstrap pagetable
126 * so it can run.
127 */
128
129 if(rp->p_nr == VM_PROC_NR) {
130 struct exec_info execi;
131
132 memset(&execi, 0, sizeof(execi));
133
134 /* exec parameters */
135 execi.stack_high = kinfo.user_sp;
136 execi.stack_size = 64 * 1024; /* not too crazy as it must be preallocated */
137 execi.proc_e = ip->endpoint;
138 execi.hdr = (char *) mod->mod_start; /* phys mem direct */
139 execi.filesize = execi.hdr_len = mod->mod_end - mod->mod_start;
140 strlcpy(execi.progname, ip->proc_name, sizeof(execi.progname));
141 execi.frame_len = 0;
142
143 /* callbacks for use in the kernel */
144 execi.copymem = libexec_copy_memcpy;
145 execi.clearmem = libexec_clear_memset;
146 execi.allocmem_prealloc_junk = libexec_pg_alloc;
147 execi.allocmem_prealloc_cleared = libexec_pg_alloc;
148 execi.allocmem_ondemand = libexec_pg_alloc;
149 execi.clearproc = NULL;
150
151 /* parse VM ELF binary and alloc/map it into bootstrap pagetable */
152 if(libexec_load_elf(&execi) != OK)
153 panic("VM loading failed");
154
155 /* Setup a ps_strings struct on the stack, pointing to the
156 * following argv, envp. */
157 sp = (char *)execi.stack_high;
158 sp -= sizeof(struct ps_strings);
159 psp = (struct ps_strings *) sp;
160
161 /* Take the stack pointer down three words to give startup code
162 * something to use as "argc", "argv" and "envp".
163 */
164 sp -= (sizeof(void *) + sizeof(void *) + sizeof(int));
165
166 // linear address space, so it is available.
167 psp->ps_argvstr = (char **)(sp + sizeof(int));
168 psp->ps_nargvstr = 0;
169 psp->ps_envstr = psp->ps_argvstr + sizeof(void *);
170 psp->ps_nenvstr = 0;
171
172 arch_proc_init(rp, execi.pc, (vir_bytes)sp,
173 execi.stack_high - sizeof(struct ps_strings),
174 ip->proc_name);
175
176 /* Free VM blob that was just copied into existence. */
177 add_memmap(&kinfo, mod->mod_start, mod->mod_end-mod->mod_start);
178 mod->mod_end = mod->mod_start = 0;
179
180 /* Remember them */
181 kinfo.vm_allocated_bytes = alloc_for_vm;
182 }
183 }
184