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 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 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 stak in use when we trap to kernel 46 */ 47 *((reg_t *)(t->sp0 + 1 * sizeof(reg_t))) = cpu; 48 49 return 0; 50 } 51 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 77 void prot_init() 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 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 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 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