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