static void set_page_tables(void) { /* map every memory region to itself */ map_section(0, 0, 0x1000, CACHE_NONE); /* map RAM and enable caching for it */ map_section(DRAM_ORIG, CACHED_DRAM_ADDR, MEMORYSIZE, CACHE_ALL); map_section(DRAM_ORIG, BUFFERED_DRAM_ADDR, MEMORYSIZE, BUFFERED); }
void soc_map(uint32_t l1_address) { //Map Integrator map_section(l1_address, 0xf1000000, 0x10000000, FALSE); // map Timer map_section(l1_address, 0xf1300000, 0x13000000, FALSE); //map Pic map_section(l1_address, 0xf1400000, 0x14000000, FALSE); //Map UART map_section(l1_address, 0xf1600000, 0x16000000, FALSE); }
void mem_initialize(void) { u32 cr; u32 cookie = irq_kill(); gecko_printf("MEM: cleaning up\n"); _ic_inval(); _dc_inval(); _tlb_inval(); gecko_printf("MEM: unprotecting memory\n"); mem_protect(0,NULL,NULL); gecko_printf("MEM: mapping sections\n"); memset32(__page_table, 0, 16384); map_section(0x000, 0x000, 0x018, WRITEBACK_CACHE | DOMAIN(0) | AP_RWUSER); map_section(0x100, 0x100, 0x040, WRITEBACK_CACHE | DOMAIN(0) | AP_RWUSER); map_section(0x0d0, 0x0d0, 0x001, NONBUFFERABLE | DOMAIN(0) | AP_RWUSER); map_section(0x0d8, 0x0d8, 0x001, NONBUFFERABLE | DOMAIN(0) | AP_RWUSER); map_section(0xfff, 0xfff, 0x001, WRITEBACK_CACHE | DOMAIN(0) | AP_RWUSER); set_dacr(0xFFFFFFFF); //manager access for all domains, ignore AP set_ttbr((u32)__page_table); //configure translation table _drain_write_buffer(); cr = get_cr(); #ifndef NO_CACHES gecko_printf("MEM: enabling caches\n"); cr |= CR_DCACHE | CR_ICACHE; set_cr(cr); gecko_printf("MEM: enabling MMU\n"); cr |= CR_MMU; set_cr(cr); #endif gecko_printf("MEM: init done\n"); irq_restore(cookie); }
/** Create a mapping in an MMU context. * @param ctx Context to map in. * @param virt Virtual address to map. * @param phys Physical address to map to. * @param size Size of the mapping to create. * @return Whether created successfully. */ bool mmu_map(mmu_context_t *ctx, target_ptr_t virt, phys_ptr_t phys, target_size_t size) { uint32_t i; if(virt % PAGE_SIZE || phys % PAGE_SIZE || size % PAGE_SIZE) return false; /* Map using sections where possible. To do this, align up to a 1MB * boundary using small pages, map anything possible with sections, * then do the rest using small pages. If virtual and physical addresses * are at different offsets from a section boundary, we cannot map * using sections. */ if((virt % LARGE_PAGE_SIZE) == (phys % LARGE_PAGE_SIZE)) { while(virt % LARGE_PAGE_SIZE && size) { map_small(ctx, virt, phys); virt += PAGE_SIZE; phys += PAGE_SIZE; size -= PAGE_SIZE; } while(size / LARGE_PAGE_SIZE) { map_section(ctx, virt, phys); virt += LARGE_PAGE_SIZE; phys += LARGE_PAGE_SIZE; size -= LARGE_PAGE_SIZE; } } /* Map whatever remains. */ for(i = 0; i < size; i += PAGE_SIZE) map_small(ctx, virt + i, phys + i); return true; }
void load_section(Elf64_Ehdr *header, char *file, char *section_name, t_section *section_ptr) { Elf64_Half nb_entry; Elf64_Shdr *section; char *name; nb_entry = header->e_shnum; for (int i = 0; i < nb_entry; i++) { section = get_section(header, file, i); name = get_string(section->sh_name, header, file); if (!strcmp(name, section_name)) { section_ptr->data = map_section(file, section); section_ptr->size = section->sh_size; break; } } }
/* everything is based on this exec, we have an extra argument (execonly) to differentiate between the exec and fork_exec families. the difference is that the latter forks and then execs the process thereby returning in the parent */ static int fork_execve0(const char *path, char *const argv_ori[], char * const envptr[], int execonly) { int envid; int fd; u_int k = 0; struct Uenv cu; int argc; char **argv_tmp,*argv_p,**argv; u32 lmagic; char *cmagic = (char*)&lmagic; u32 entry_point = 0; int running_emulator = 0; char *emu_path = NULL; char **argv_ori_tmp = (char**)argv_ori; char **argv_ori_tmp2; #define FE_PATH (running_emulator ? emu_path : path) #ifdef PROCESS_TABLE int NewPid = 0; #endif char *extra_argv_space = NULL; #if 0 { extern void pr_fds(); fprintf(stderr,"FDS BEFORE EXEC PID: %d execonly: %d\n",getpid(),execonly); pr_fds; } #endif // printf("fork_execve0: path: %s\n",path); #if 0 for(argc = 0; argv_ori[argc] ; argc++) kprintf("%d) %s\n",argc,argv_ori[argc]); #endif proprintf("allocate env, and open file\n"); ISTART(misc,execve); ISTART(misc,step1); /* fprintf(stderr,"fe_nfs2 %s\n",FE_PATH); */ if (! (envid = sys_env_alloc (0))) { fprintf(stderr,"could not sys_env_alloc\n"); goto err; } open_binary: /* verify executable permission */ if (access(FE_PATH, X_OK) == -1) { /* access will set errno */ goto fork_execve0_end_error; } /* open the executable */ fd = open (FE_PATH, O_RDONLY, 0644); if (fd < 0) { /* open will set errno */ /*fprintf(stderr,"1could not open path %s, errno: %d\n",FE_PATH,errno);*/ goto fork_execve0_end_error; } STOPP(misc,step1); proprintf("read file and open interpreter if necessary\n"); ISTART(misc,step2); /* read in the magic number */ if (read(fd, cmagic, 2) < 2) { errno = ENOEXEC; goto fork_execve0_end_error_closefd; } /* check for interpreter */ if (cmagic[0] == '#' && cmagic[1] == '!') { int intersize; char inter[MAXINTERP+1], *interp; if ((intersize = read(fd,inter,MAXINTERP)) == -1) { errno = ENOEXEC; goto fork_execve0_end_error_closefd; } inter[intersize] = '\n'; interp = inter; /* skip spaces */ while ((*interp == ' ' || *interp == '\t') && *interp != '\n') interp++; { char **v = (char **)argv_ori_tmp; while(*v++); extra_argv_space = (char *)malloc((char *)v - (char *)argv_ori_tmp + MAXINTERP*(sizeof(char*))); if (!extra_argv_space) { fprintf(stderr,"execve could not allocate extra argv space for " "interpreted file\n"); goto fork_execve0_end_error_closefd; } } argv = (char **)extra_argv_space; *argv++ = interp; while (*interp != ' ' && *interp != '\t' && *interp != (char)0 && *interp != '\n') interp++; if (*interp != 0 && *interp != '\n') { /* more arguments, we only copy one more */ *interp++ = 0; /* skip spaces */ while ((*interp == ' ' || *interp == '\t') && *interp != '\n') interp++; *argv++ = interp; while (*interp != ' ' && *interp != '\t' && *interp != (char)0 && *interp != '\n') interp++; *interp = (char)0; } else { *interp = (char)0; } *argv++ = (char *)FE_PATH; argv_ori_tmp2 = argv_ori_tmp; argv_ori_tmp2++; while(*argv_ori_tmp2 != (char *) 0) {*argv++ = *argv_ori_tmp2++;} /* copy the 0 */ *argv++ = *argv_ori_tmp2++; argv = (char **)extra_argv_space; close(fd); /* verify executable permission */ if (access(argv[0], X_OK) == -1) { /* access will set errno */ goto fork_execve0_end_error; } fd = open (argv[0], O_RDONLY, 0644); if (fd < 0) { /* open will set errno */ /*fprintf(stderr,"2could not open path %s, errno: %d\n",argv[0],errno);*/ goto fork_execve0_end_error; } /* read in the magic number (and nesting of interpreters not allowed) */ if (read(fd, cmagic, 2) < 2 || (cmagic[0] == '#' && cmagic[1] == '!')) { errno = ENOEXEC; goto fork_execve0_end_error_closefd; } } else { argv = (char **)argv_ori_tmp; } STOPP(misc,step2); proprintf("read more magic and executable headers, check for emulation\n"); ISTART(misc,step3); if (read(fd, &cmagic[2], 2) < 2) { errno = ENOEXEC; goto fork_execve0_end_error_closefd; } /* see whether we need to run an emulator */ if (lmagic != 0700303000 && (lmagic & 0x0000ffff) != 0514) { if (running_emulator) { fprintf(stderr,"Emulator binary is in unrecognized executable " "format.\n"); goto fork_execve0_end_error_closefd; } else fprintf(stderr,"Unrecognized executable format; attempting to run " "emulator.\n"); close(fd); { char **v = (char **)argv_ori_tmp; while(*v++); extra_argv_space = (char *)malloc((char *)v - (char *)argv_ori_tmp + 2 * sizeof(char*)); if (!extra_argv_space) { fprintf(stderr,"execve could not allocate extra argv space for " "copying args for emulator\n"); goto fork_execve0_end_error_closefd; } } argv = (char **)extra_argv_space; running_emulator = 1; *argv++ = emu_path = getenv("EMULATOR"); if (!FE_PATH) { fprintf(stderr,"EMULATOR environment variable not set to emulator path; " "cannot run emulator.\n"); goto fork_execve0_end_error; } *argv++ = (char *)path; argv_ori_tmp2 = argv_ori_tmp; argv_ori_tmp2++; while(*argv_ori_tmp2 != (char *) 0) {*argv++ = *argv_ori_tmp2++;} /* copy the 0 */ *argv++ = *argv_ori_tmp2++; argv = (char **)extra_argv_space; argv_ori_tmp = argv; goto open_binary; } /* check for original ExOS (OpenBSD) format - remove eventually */ if (lmagic == 0700303000) { struct exec hdr; u_int byte_count, page_count; Pte *ptes; int i; #if 0 fprintf(stderr,"File uses old executable format.\n"); #endif /* allocate physical pages and read data into it. */ /* read a.out headers */ if (lseek(fd,0,SEEK_SET) == -1 || read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { fprintf(stderr,"Invalid executable format.\n"); errno = ENOEXEC; goto fork_execve0_end_error_closefd; } entry_point = hdr.a_entry; /* alloc this much memory */ byte_count = hdr.a_text + hdr.a_data + hdr.a_bss; page_count = PGNO(PGROUNDUP(byte_count)); /* allocate it in both child and parent areas */ if ((ptes = malloc(sizeof(Pte) * page_count)) == 0) { errno = ENOEXEC; goto fork_execve0_end_error_closefd; } for (i=0; i < page_count; i++) ptes[i] = PG_U|PG_W|PG_P; STOPP(misc,step3); proprintf("allocate childs vm in both parent and child, read text+data " "(sz %ld)\n", hdr.a_text + hdr.a_data); ISTART(misc,read0); if (sys_self_insert_pte_range(k, ptes, page_count, TEMP_REGION) < 0 || sys_insert_pte_range(k, &vpt[PGNO(TEMP_REGION)], page_count, UTEXT, k, envid) < 0 || read(fd, (void*)TEMP_REGION, hdr.a_text + hdr.a_data) != hdr.a_text + hdr.a_data) { fprintf (stderr,"Binary file invalid or corrupt.\n"); for (i=0; i < page_count; i++) ptes[i] = 0; sys_self_insert_pte_range(k, ptes, page_count, TEMP_REGION); sys_insert_pte_range(k, ptes, page_count, UTEXT, k, envid); free(ptes); errno = ENOEXEC; goto fork_execve0_end_error_closefd; } STOPP(misc,read0); /* zero the bss */ proprintf("bzero bss (sz %ld)\n",hdr.a_bss); ISTART(misc,read1); bzero((void*)(TEMP_REGION + hdr.a_text + hdr.a_data), hdr.a_bss); STOP(misc,read1); PRNAME(misc,read1); proprintf("unmap TEMP_REGION (sz %d pages)\n", page_count); ISTART(misc,step4); /* unmap the used TEMP_REGION */ for (i=0; i < page_count; i++) ptes[i] = 0; sys_self_insert_pte_range(k, ptes, page_count, TEMP_REGION); free(ptes); } else if ((lmagic & 0x0000ffff) == 0514) /* check for ExOS COFF format */ { FILHDR hdr; AOUTHDR opthdr; SCNHDR shdr; int s; /* allocate physical pages and read data into it. */ /* read file headers */ if (lseek(fd,0,SEEK_SET) == -1 || read(fd, &hdr, FILHSZ) != FILHSZ || hdr.f_opthdr != sizeof(opthdr) || !(hdr.f_flags & F_EXEC) || read(fd, &opthdr, hdr.f_opthdr) != hdr.f_opthdr) { fprintf(stderr,"Invalid executable format.\n"); errno = ENOEXEC; goto fork_execve0_end_error_closefd; } entry_point = opthdr.entry; /* ensure ZMAGIC */ if (opthdr.magic != ZMAGIC) { fprintf(stderr,"Exec cannot read non-ZMAGIC COFF executables.\n"); errno = ENOEXEC; goto fork_execve0_end_error_closefd; } STOPP(misc,step3); proprintf("read in and map/zero COFF sections then unmap\n"); ISTART(misc,read0); for (s=0; s < hdr.f_nscns; s++) if (read(fd, &shdr, SCNHSZ) != SCNHSZ || map_section(k, fd, &shdr, envid) == -1) { fprintf(stderr,"Invalid executable format.\n"); errno = ENOEXEC; goto fork_execve0_end_error_closefd; } STOPP(misc,read0); proprintf("nothing\n"); ISTART(misc,read1); STOP(misc,read1); PRNAME(misc,read1); proprintf("nothing\n"); ISTART(misc,step4); } else { fprintf(stderr, "Unknown file format.\n"); errno = ENOEXEC; goto fork_execve0_end_error_closefd; } STOPP(misc,step4); close (fd); proprintf("Allocate stack for child\n"); ISTART(misc,step5); /* allocate stack space for child */ if (sys_insert_pte (k, PG_U|PG_W|PG_P, USTACKTOP-NBPG, k, envid) < 0) { fprintf(stderr,"sys_insert_pte failed\n"); errno = ENOEXEC; goto fork_execve0_end_error; } STOPP(misc,step5); proprintf("ExecuteOnExecHandlers\n"); ISTART(misc,step6); if (ExecuteOnExecHandlers(k,envid,execonly) == -1) { fprintf(stderr,"cleanup code not done yet\n"); assert(-1); } STOPP(misc,step6); proprintf("Process table stuff\n"); ISTART(misc,step7); #ifdef PROCESS_TABLE if (execonly) { /* because true exec */ NewPid = getpid(); /* XXX -- this locking is ... up. I should really come up with a better convention as to what expects to be called with things locked and what doesn't */ dlockputs(__PROCD_LD,"fork_execve0 get lock "); EXOS_LOCK(PROCINFO_LOCK); dlockputs(__PROCD_LD,"... got lock\n"); EnterCritical (); ProcChangeEnv(NewPid,envid); EXOS_UNLOCK(PROCINFO_LOCK); dlockputs(__PROCD_LD,"fork_execve0 release lock\n"); ExitCritical (); } else { /* because we are forking */ NewPid = AllocateFreePid (envid); } #endif #ifdef PROCESS_TABLE cu = u; if (!execonly) { AddProcEntry (&cu, (char *)FE_PATH, (char **)argv, NewPid, UAREA.pid); if ((cu.parent_slot = GetChildSlot (NewPid)) < 0) { errno = ENOEXEC; goto fork_execve0_end_error; } } else { /* TO TOM: what do we do this for? */ strncpy (UAREA.name, argv[0], U_NAMEMAX-1); UAREA.name[U_NAMEMAX-1] = '\0'; } /* XXX -- on an exec we'll forget to unref our children's pids */ /* TO TOM: shouldnt this clearchildinfo be at the top */ ClearChildInfo (&cu); strncpy (cu.name, FE_PATH, U_NAMEMAX-1); cu.name[U_NAMEMAX-1] = '\0'; cu.u_chld_state_chng = 0; #endif /* PROCESS_TABLE */ cu.u_in_critical = 0; cu.u_status = U_RUN; cu.u_entprologue = entry_point; cu.u_next_timeout = 0; cu.u_in_pfault = 0; cu.u_revoked_pages = 0; cu.u_donate = -1; STOPP(misc,step7); proprintf("Argv and Environment copying\n"); ISTART(misc,step8); // printf("ENTERING ARGV COPY\n"); /* ----------------------------------------------------------------------------- */ /* allocate argv space for child */ { char *buf = (char *)ARGV_START_LOCAL; char **bufv = (char **)ARGV_START_LOCAL; int len,i; argc = 0; while (argv[argc] != 0) { //printf("argv[%d] = %p\n",argc,argv[argc]); argc++;} // printf("argv: %p, argc: %d\n",argv,argc); /* allocate pages */ { Pte *ptes; if ((ptes = malloc(sizeof(Pte) * NRARGVPG)) == 0) { return -1; } for (i=0; i < NRARGVPG; i++) ptes[i] = PG_U|PG_W|PG_P; if (sys_self_insert_pte_range(k, ptes, NRARGVPG, ARGV_START_LOCAL) < 0 || sys_insert_pte_range(k, &vpt[PGNO(ARGV_START_LOCAL)], NRARGVPG, ARGV_START, k, envid) < 0) { fprintf(stderr,"sys_insert_pte failed\n"); for (i=0; i < NRARGVPG; i++) ptes[i] = 0; sys_self_insert_pte_range(k, ptes, NRARGVPG, ARGV_START_LOCAL); sys_insert_pte_range(k, ptes, NRARGVPG, ARGV_START, k, envid); free(ptes); errno = ENOEXEC; goto fork_execve0_end_error_closefd; } free(ptes); } /* copy the args */ buf += (argc + 1) * sizeof(char *); for (i = 0; i < argc; i++) { // fprintf(stderr,"argv[%d] ",i); len = strlen(argv[i]) + 1; // fprintf(stderr,"length %d\n",len); if ((int)(buf + len) > ARGV_START_LOCAL + NRARGVPG*NBPG) { kprintf("Argv too large truncating\n"); break; } bufv[i] = buf - (ARGV_START_LOCAL - ARGV_START); // fprintf(stderr,"copied argument %d: %p %s (len %d) to %p bufv: %p\n",i,argv[i],argv[i],len,buf,bufv); memcpy(buf, argv[i],len); buf += len; } bufv[argc] = (char *)0; } // printf("DONE ARGV COPY\n"); /* ----------------------------------------------------------------------------- */ #if 0 /* COPY ARGUMENTS */ argc = 0; iptr = (int *)ARGV_START_LOCAL; argv_p = (char *)(ARGV_START_LOCAL + NBPG); while(*argv != (char *)0) { strcpy(argv_p,*argv); iptr[argc] = strlen(*argv) + 1; argv_p += strlen(*argv) + 1; /* fprintf(stderr,"%d len %d \"%s\" ",argc,cu.u_argv_lengths[argc],*argv); */ argc++; argv++; } iptr[argc] = -1; /* fprintf(stderr,"ARGC %d\n",argc); */ #endif #if 0 argc = 0; argv_p = (char *)&cu.u_argv_space; while(*argv != (char *)0) { strcpy(argv_p,*argv); cu.u_argv_lengths[argc] = strlen(*argv) + 1; argv_p += strlen(*argv) + 1; /* fprintf(stderr,"%d len %d \"%s\" ",argc,cu.u_argv_lengths[argc],*argv); */ argc++; argv++; if (argc == (UNIX_NR_ARGV - 1)) { fprintf(stderr,"argc (%d) is greater than maximum allowed (%d), truncating.\n", argc,UNIX_NR_ARGV - 1); break; } if ((int)argv_p > (int)&cu.u_argv_space[0] + UNIX_ARGV_SIZE) { fprintf(stderr,"too much data in argv (%d) max is %d\n", (int)argv_p - (int)&cu.u_argv_space[0],UNIX_ARGV_SIZE); break; } } cu.u_argv_lengths[argc] = -1; #endif /* COPY ENVIRONMENT */ argc = 0; (char * const *)argv_tmp = envptr; argv_p = (char *)&cu.u_env_space; if (argv_tmp) while(*argv_tmp != (char *)0) { strcpy(argv_p,*argv_tmp); cu.u_env_lengths[argc] = strlen(*argv_tmp) + 1; argv_p += strlen(*argv_tmp) + 1; /* fprintf(stderr,"%d len %d \"%s\" ",argc,cu.u_env_lengths[argc],*argv_tmp); */ argc++; argv_tmp++; if (argc == (UNIX_NR_ENV - 1)) { fprintf(stderr,"envc (%d) is greater than maximum allowed (%d), truncating.\n", argc,UNIX_NR_ENV - 1); break; } if ((int)argv_p > (int)&cu.u_env_space[0] + UNIX_ENV_SIZE) { fprintf(stderr,"too much data in envp (%d) max is %d (%s)\n", (int)argv_p - (int)&cu.u_env_space[0],UNIX_ENV_SIZE, __FILE__); break; } } cu.u_env_lengths[argc] = -1; /* fprintf(stderr,"ENVC %d\n",argc); */ if (sys_wru (0, envid, &cu) < 0) { fprintf (stderr,"sys_wru failed\n"); errno = ENOEXEC; goto fork_execve0_end_error; } STOPP(misc,step8); STOP(misc,execve); PRNAME(misc,execve); { extern void pr_fd_stat(void); pr_fd_stat(); } /*fprintf(stderr,"allocating quantum\n");*/ if (sys_quantum_alloc (k, -1, 0, envid) < 0) { fprintf (stderr,"could not alloc quantum\n"); errno = ENOEXEC; goto fork_execve0_end_error; } if (execonly) { ProcessFreeQuanta(__envid); sys_env_free (0, __envid); } return (NewPid); fork_execve0_end_error_closefd: close(fd); fork_execve0_end_error: ProcessFreeQuanta(__envid); sys_env_free (k, envid); err: if (extra_argv_space != NULL) free(extra_argv_space); return -1; }
/* * For a specified manual directory, read, store and sort section subdirs. * For each section specified, find and search matching subdirs. */ static void mandir(char **secv, char *path, char *name, int lspec) { DIR *dp; char **dirv; char **dv, **pdv; int len, dslen; if ((dp = opendir(path)) == NULL) return; if (lspec) DPRINTF("-- Searching mandir: %s\n", path); sortdir(dp, &dirv); /* Search in the order specified by MANSECTS */ for (; *secv; secv++) { len = strlen(*secv); for (dv = dirv; *dv; dv++) { dslen = strlen(*dv + 3); if (dslen > len) len = dslen; if (**secv == '\\') { if (strcmp(*secv + 1, *dv + 3) != 0) continue; } else if (strncasecmp(*secv, *dv + 3, len) != 0) { if (!all && (newsection = map_section(*secv, path)) == NULL) { continue; } if (newsection == NULL) newsection = ""; if (strncmp(newsection, *dv + 3, len) != 0) { continue; } } if (searchdir(path, *dv, name) == 0) continue; if (!all) { pdv = dirv; while (*pdv) { free(*pdv); pdv++; } (void) closedir(dp); free(dirv); return; } if (all && **dv == 'm' && *(dv + 1) && strcmp(*(dv + 1) + 3, *dv + 3) == 0) dv++; } } pdv = dirv; while (*pdv != NULL) { free(*pdv); pdv++; } free(dirv); (void) closedir(dp); }