1433d6423SLionel Sambuc /* This file contains code for initialization of protected mode, to initialize
2433d6423SLionel Sambuc * code and data segment descriptors, and to initialize global descriptors
3433d6423SLionel Sambuc * for local descriptors in the process table.
4433d6423SLionel Sambuc */
5433d6423SLionel Sambuc
6433d6423SLionel Sambuc #include <assert.h>
7433d6423SLionel Sambuc #include <string.h>
8433d6423SLionel Sambuc
9433d6423SLionel Sambuc #include <machine/multiboot.h>
10433d6423SLionel Sambuc
11433d6423SLionel Sambuc #include "kernel/kernel.h"
12433d6423SLionel Sambuc
13433d6423SLionel Sambuc #include "archconst.h"
14433d6423SLionel Sambuc #include "arch_proto.h"
15433d6423SLionel Sambuc
16433d6423SLionel Sambuc #include <sys/exec.h>
17433d6423SLionel Sambuc #include <libexec.h>
18433d6423SLionel Sambuc
19433d6423SLionel Sambuc struct tss_s tss[CONFIG_MAX_CPUS];
20433d6423SLionel Sambuc extern int exc_vector_table;
21433d6423SLionel Sambuc
22433d6423SLionel Sambuc int prot_init_done = 0;
23433d6423SLionel Sambuc
vir2phys(void * vir)24433d6423SLionel Sambuc phys_bytes vir2phys(void *vir)
25433d6423SLionel Sambuc {
26433d6423SLionel Sambuc /* defined in kernel.lds */
27433d6423SLionel Sambuc extern char _kern_vir_base, _kern_phys_base;
28433d6423SLionel Sambuc u32_t offset = (vir_bytes) &_kern_vir_base -
29433d6423SLionel Sambuc (vir_bytes) &_kern_phys_base;
30433d6423SLionel Sambuc return (phys_bytes)vir - offset;
31433d6423SLionel Sambuc }
32433d6423SLionel Sambuc
tss_init(unsigned cpu,void * kernel_stack)33433d6423SLionel Sambuc int tss_init(unsigned cpu, void * kernel_stack)
34433d6423SLionel Sambuc {
35433d6423SLionel Sambuc
36433d6423SLionel Sambuc struct tss_s * t = &tss[cpu];
37433d6423SLionel Sambuc
38433d6423SLionel Sambuc /*
39433d6423SLionel Sambuc * make space for process pointer and cpu id and point to the first
40433d6423SLionel Sambuc * usable word
41433d6423SLionel Sambuc */
42433d6423SLionel Sambuc t->sp0 = ((unsigned) kernel_stack) - ARM_STACK_TOP_RESERVED;
43433d6423SLionel Sambuc /*
44433d6423SLionel Sambuc * set the cpu id at the top of the stack so we know on which cpu is
45*d578d57bSGerhard Poul * this stack in use when we trap to kernel
46433d6423SLionel Sambuc */
47433d6423SLionel Sambuc *((reg_t *)(t->sp0 + 1 * sizeof(reg_t))) = cpu;
48433d6423SLionel Sambuc
49433d6423SLionel Sambuc return 0;
50433d6423SLionel Sambuc }
51433d6423SLionel Sambuc
bootmod(int pnr)52433d6423SLionel Sambuc multiboot_module_t *bootmod(int pnr)
53433d6423SLionel Sambuc {
54433d6423SLionel Sambuc int i;
55433d6423SLionel Sambuc
56433d6423SLionel Sambuc assert(pnr >= 0);
57433d6423SLionel Sambuc
58433d6423SLionel Sambuc /* Search for desired process in boot process
59433d6423SLionel Sambuc * list. The first NR_TASKS ones do not correspond
60433d6423SLionel Sambuc * to a module, however, so we don't search those.
61433d6423SLionel Sambuc */
62433d6423SLionel Sambuc for(i = NR_TASKS; i < NR_BOOT_PROCS; i++) {
63433d6423SLionel Sambuc int p;
64433d6423SLionel Sambuc p = i - NR_TASKS;
65433d6423SLionel Sambuc if(image[i].proc_nr == pnr) {
66433d6423SLionel Sambuc assert(p < MULTIBOOT_MAX_MODS);
67433d6423SLionel Sambuc assert(p < kinfo.mbi.mi_mods_count);
68433d6423SLionel Sambuc return &kinfo.module_list[p];
69433d6423SLionel Sambuc }
70433d6423SLionel Sambuc }
71433d6423SLionel Sambuc
72433d6423SLionel Sambuc panic("boot module %d not found", pnr);
73433d6423SLionel Sambuc }
74433d6423SLionel Sambuc
75433d6423SLionel Sambuc int booting_cpu = 0;
76433d6423SLionel Sambuc
prot_init(void)776077d1adSDr. Florian Grätz void prot_init(void)
78433d6423SLionel Sambuc {
79433d6423SLionel Sambuc /* tell the HW where we stored our vector table */
80433d6423SLionel Sambuc write_vbar((reg_t)&exc_vector_table);
81433d6423SLionel Sambuc
82433d6423SLionel Sambuc /* Set up a new post-relocate bootstrap pagetable so that
83433d6423SLionel Sambuc * we can map in VM, and we no longer rely on pre-relocated
84433d6423SLionel Sambuc * data.
85433d6423SLionel Sambuc */
86433d6423SLionel Sambuc
87433d6423SLionel Sambuc pg_clear();
88433d6423SLionel Sambuc pg_identity(&kinfo); /* Still need 1:1 for device memory . */
89433d6423SLionel Sambuc pg_mapkernel();
90433d6423SLionel Sambuc pg_load();
91433d6423SLionel Sambuc
92433d6423SLionel Sambuc prot_init_done = 1;
93433d6423SLionel Sambuc }
94433d6423SLionel Sambuc
95433d6423SLionel Sambuc static int alloc_for_vm = 0;
96433d6423SLionel Sambuc
arch_post_init(void)97433d6423SLionel Sambuc void arch_post_init(void)
98433d6423SLionel Sambuc {
99433d6423SLionel Sambuc /* Let memory mapping code know what's going on at bootstrap time */
100433d6423SLionel Sambuc struct proc *vm;
101433d6423SLionel Sambuc vm = proc_addr(VM_PROC_NR);
102433d6423SLionel Sambuc get_cpulocal_var(ptproc) = vm;
103433d6423SLionel Sambuc pg_info(&vm->p_seg.p_ttbr, &vm->p_seg.p_ttbr_v);
104433d6423SLionel Sambuc }
105433d6423SLionel Sambuc
libexec_pg_alloc(struct exec_info * execi,vir_bytes vaddr,size_t len)106433d6423SLionel Sambuc static int libexec_pg_alloc(struct exec_info *execi, vir_bytes vaddr, size_t len)
107433d6423SLionel Sambuc {
108433d6423SLionel Sambuc pg_map(PG_ALLOCATEME, vaddr, vaddr+len, &kinfo);
109433d6423SLionel Sambuc pg_load();
110433d6423SLionel Sambuc memset((char *) vaddr, 0, len);
111433d6423SLionel Sambuc alloc_for_vm += len;
112433d6423SLionel Sambuc return OK;
113433d6423SLionel Sambuc }
114433d6423SLionel Sambuc
arch_boot_proc(struct boot_image * ip,struct proc * rp)115433d6423SLionel Sambuc void arch_boot_proc(struct boot_image *ip, struct proc *rp)
116433d6423SLionel Sambuc {
117433d6423SLionel Sambuc multiboot_module_t *mod;
118433d6423SLionel Sambuc struct ps_strings *psp;
119433d6423SLionel Sambuc char *sp;
120433d6423SLionel Sambuc
121433d6423SLionel Sambuc if(rp->p_nr < 0) return;
122433d6423SLionel Sambuc
123433d6423SLionel Sambuc mod = bootmod(rp->p_nr);
124433d6423SLionel Sambuc
125433d6423SLionel Sambuc /* Important special case: we put VM in the bootstrap pagetable
126433d6423SLionel Sambuc * so it can run.
127433d6423SLionel Sambuc */
128433d6423SLionel Sambuc
129433d6423SLionel Sambuc if(rp->p_nr == VM_PROC_NR) {
130433d6423SLionel Sambuc struct exec_info execi;
131433d6423SLionel Sambuc
132433d6423SLionel Sambuc memset(&execi, 0, sizeof(execi));
133433d6423SLionel Sambuc
134433d6423SLionel Sambuc /* exec parameters */
135433d6423SLionel Sambuc execi.stack_high = kinfo.user_sp;
136433d6423SLionel Sambuc execi.stack_size = 64 * 1024; /* not too crazy as it must be preallocated */
137433d6423SLionel Sambuc execi.proc_e = ip->endpoint;
138433d6423SLionel Sambuc execi.hdr = (char *) mod->mod_start; /* phys mem direct */
139433d6423SLionel Sambuc execi.filesize = execi.hdr_len = mod->mod_end - mod->mod_start;
140433d6423SLionel Sambuc strlcpy(execi.progname, ip->proc_name, sizeof(execi.progname));
141433d6423SLionel Sambuc execi.frame_len = 0;
142433d6423SLionel Sambuc
143433d6423SLionel Sambuc /* callbacks for use in the kernel */
144433d6423SLionel Sambuc execi.copymem = libexec_copy_memcpy;
145433d6423SLionel Sambuc execi.clearmem = libexec_clear_memset;
146433d6423SLionel Sambuc execi.allocmem_prealloc_junk = libexec_pg_alloc;
147433d6423SLionel Sambuc execi.allocmem_prealloc_cleared = libexec_pg_alloc;
148433d6423SLionel Sambuc execi.allocmem_ondemand = libexec_pg_alloc;
149433d6423SLionel Sambuc execi.clearproc = NULL;
150433d6423SLionel Sambuc
151433d6423SLionel Sambuc /* parse VM ELF binary and alloc/map it into bootstrap pagetable */
152433d6423SLionel Sambuc if(libexec_load_elf(&execi) != OK)
153433d6423SLionel Sambuc panic("VM loading failed");
154433d6423SLionel Sambuc
155433d6423SLionel Sambuc /* Setup a ps_strings struct on the stack, pointing to the
156433d6423SLionel Sambuc * following argv, envp. */
157433d6423SLionel Sambuc sp = (char *)execi.stack_high;
158433d6423SLionel Sambuc sp -= sizeof(struct ps_strings);
159433d6423SLionel Sambuc psp = (struct ps_strings *) sp;
160433d6423SLionel Sambuc
161433d6423SLionel Sambuc /* Take the stack pointer down three words to give startup code
162433d6423SLionel Sambuc * something to use as "argc", "argv" and "envp".
163433d6423SLionel Sambuc */
164433d6423SLionel Sambuc sp -= (sizeof(void *) + sizeof(void *) + sizeof(int));
165433d6423SLionel Sambuc
166433d6423SLionel Sambuc // linear address space, so it is available.
167433d6423SLionel Sambuc psp->ps_argvstr = (char **)(sp + sizeof(int));
168433d6423SLionel Sambuc psp->ps_nargvstr = 0;
169433d6423SLionel Sambuc psp->ps_envstr = psp->ps_argvstr + sizeof(void *);
170433d6423SLionel Sambuc psp->ps_nenvstr = 0;
171433d6423SLionel Sambuc
172433d6423SLionel Sambuc arch_proc_init(rp, execi.pc, (vir_bytes)sp,
173433d6423SLionel Sambuc execi.stack_high - sizeof(struct ps_strings),
174433d6423SLionel Sambuc ip->proc_name);
175433d6423SLionel Sambuc
176433d6423SLionel Sambuc /* Free VM blob that was just copied into existence. */
177433d6423SLionel Sambuc add_memmap(&kinfo, mod->mod_start, mod->mod_end-mod->mod_start);
178433d6423SLionel Sambuc mod->mod_end = mod->mod_start = 0;
179433d6423SLionel Sambuc
180433d6423SLionel Sambuc /* Remember them */
181433d6423SLionel Sambuc kinfo.vm_allocated_bytes = alloc_for_vm;
182433d6423SLionel Sambuc }
183433d6423SLionel Sambuc }
184