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