/** * Map RAM. * * \param pager pager implementing Sigma0 protocol * \return #0 on success * -#L4SIGMA0_NOTALIGNED phys, virt, or size not aligned * -#L4SIGMA0_IPCERROR IPC error * -#L4SIGMA0_NOFPAGE no fpage received */ L4_CV int l4sigma0_map_mem(l4_cap_idx_t pager, l4_addr_t phys, l4_addr_t virt, l4_addr_t size) { l4_addr_t d = L4_SUPERPAGESIZE; unsigned l = L4_LOG2_SUPERPAGESIZE; l4_msgtag_t tag; int error; l4_utcb_t *utcb = l4_utcb(); if ((phys & (d-1)) || (size & (d-1)) || (virt & (d-1))) { l = L4_LOG2_PAGESIZE; d = L4_PAGESIZE; } if ((phys & (d-1)) || (size & (d-1)) || (virt & (d-1))) return -L4SIGMA0_NOTALIGNED; for (; size>0; phys+=d, size-=d, virt+=d) { do { l4_msg_regs_t *m = l4_utcb_mr_u(utcb); l4_buf_regs_t *b = l4_utcb_br_u(utcb); tag = l4_msgtag(L4_PROTO_SIGMA0, 2, 0, 0); m->mr[0] = SIGMA0_REQ_FPAGE_RAM; m->mr[1] = l4_fpage(phys, l, L4_FPAGE_RWX).raw; b->bdr = 0; b->br[0] = L4_ITEM_MAP; b->br[1] = l4_fpage(virt, l, L4_FPAGE_RWX).raw; tag = l4_ipc_call(pager, utcb, tag, L4_IPC_NEVER); if (l4_msgtag_has_error(tag)) error = l4_utcb_tcr_u(utcb)->error; else error = 0; } while (error == L4_IPC_SECANCELED || error == L4_IPC_SEABORTED); if (error) return -L4SIGMA0_IPCERROR; if (l4_msgtag_items(tag) < 1) return -L4SIGMA0_NOFPAGE; } return 0; }
/* * Function ide_write (drive, sec, buf, length) * * Invokes an IPC to the IDE driver. The buffer is mapped read- * only to the driver, and the driver unmaps the buffer prior to * sending the reply IPC. * */ int ide_write(dword_t drive, dword_t sec, void *buf, dword_t length) { l4_msgdope_t result; dword_t dw0, dw1, dw2; l4_fpage_t fp; l4_idearg_t arg; int r; length = (length + L4_IDE_SECTOR_SIZE-1) & ~(L4_IDE_SECTOR_SIZE-1); arg.args.pos = sec; arg.args.length = length / L4_IDE_SECTOR_SIZE; arg.args.drive = drive; arg.args.write = 1; /* Create fpage that contains the buffer. */ dw0 = (dword_t) buf & PAGE_MASK; dw1 = ((dword_t) buf + length + PAGE_SIZE-1) & PAGE_MASK; for ( r = PAGE_BITS-1, dw2 = (dw1-dw0) >> PAGE_BITS; dw2 > 0; dw2 >>= 1, r++ ) {} fp = l4_fpage(dw0, r, 0, 0); r = l4_ipc_call(idedrv_id, (void *) 2, /* Map fpage */ (dword_t) buf, (dword_t) fp.fpage, (dword_t) arg.raw, (void *) 0, &dw0, &dw1, &dw2, L4_IPC_NEVER, &result); return r; }
static void l4x_flush_page(struct mm_struct *mm, unsigned long address, unsigned long vaddr, int size, unsigned long flush_rights, unsigned long caller) { l4_msgtag_t tag; if (IS_ENABLED(CONFIG_ARM)) return; if (mm && mm->context.l4x_unmap_mode == L4X_UNMAP_MODE_SKIP) return; if ((address & PAGE_MASK) == 0) address = PAGE0_PAGE_ADDRESS; if (likely(mm)) { unmap_log_add(mm, vaddr, size, flush_rights, caller); return; } /* do the real flush */ if (mm && !l4_is_invalid_cap(mm->context.task)) { /* Direct flush in the child, use virtual address in the * child address space */ tag = L4XV_FN(l4_msgtag_t, l4_task_unmap(mm->context.task, l4_fpage(vaddr & PAGE_MASK, size, flush_rights), L4_FP_ALL_SPACES)); } else { /* Flush all pages in all childs using the 'physical' * address known in the Linux server */ tag = L4XV_FN(l4_msgtag_t, l4_task_unmap(L4RE_THIS_TASK_CAP, l4_fpage(address & PAGE_MASK, size, flush_rights), L4_FP_OTHER_SPACES)); } if (l4_error(tag)) l4x_printf("l4_task_unmap error %ld\n", l4_error(tag)); }
static inline void l4x_unmap_self(unsigned long a) { l4_msgtag_t t; if (0) printk("dma-self-unmap: %08lx\n", a); a &= PAGE_MASK; t = L4XV_FN(l4_msgtag_t, l4_task_unmap(L4_BASE_TASK_CAP, l4_fpage(a, PAGE_SHIFT, L4_FPAGE_RWX), L4_FP_ALL_SPACES)); if (l4_error(t)) printk("dma-remap: internal unmapping of %08lx failed\n", a); }
static inline void l4x_map_self(unsigned long src, unsigned long dst, unsigned mapflags) { l4_msgtag_t t; if (0) printk("dma-self-map: %08lx -> %08lx [%x]\n", src, dst, mapflags); src &= PAGE_MASK; dst &= PAGE_MASK; t = L4XV_FN(l4_msgtag_t, l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, l4_fpage(src, PAGE_SHIFT, L4_FPAGE_RWX), dst | L4_MAP_ITEM_MAP | mapflags)); if (l4_error(t)) printk("dma-remap: internal mapping failed: %08lx -> %08lx\n", src, dst); }
void l4x_unmap_log_flush(void) { unsigned i; struct unmap_log_t *log; unsigned long flags; local_irq_save(flags); log = this_cpu_ptr(&unmap_log); for (i = 0; i < log->cnt; ++i) { l4_msgtag_t tag; struct mm_struct *mm = log->log[i].mm; if (unlikely(l4_is_invalid_cap(mm->context.task))) continue; tag = L4XV_FN(l4_msgtag_t, l4_task_unmap(mm->context.task, l4_fpage(log->log[i].addr, log->log[i].size, log->log[i].rights), L4_FP_ALL_SPACES)); if (unlikely(l4_error(tag))) { l4x_printf("l4_task_unmap error %ld: t=%lx\n", l4_error(tag), mm->context.task); WARN_ON(1); } else if (0) l4x_printf("flushing(%d) %lx:%08lx[%d,%x]\n", i, mm->context.task, log->log[i].addr, log->log[i].size, log->log[i].rights); } log->cnt = 0; local_irq_restore(flags); }
static void get_fb(void) { l4_addr_t fpage_addr; l4_size_t fpage_size; l4dm_dataspace_t ds; CORBA_Environment env = dice_default_environment; int i, pages, error; struct stat st; /* check if we're running under L4Linux */ if (stat("/proc/l4", &st) == -1) { fprintf(stderr, "Error: /proc/l4 doesn't exist, not running on L4Linux?!\n"); exit(1); } /* ask for 'con' (timeout = 5000 ms) */ if (names_waitfor_name(CON_NAMES_STR, &con_l4id, 5000) == 0) { fprintf(stderr, "PANIC: %s not registered at names", CON_NAMES_STR); exit(1); } INFO("Found my console through names, it's at "l4util_idfmt".\n", l4util_idstr(con_l4id)); PRINT("Screenshot'ing, please smile... ;-)\n"); /* get screenshot */ if (con_if_screenshot_call(&con_l4id, get_vc, &ds, &xres, &yres, &bpp, &env)) { fprintf(stderr, "Could not get screenshot\n"); exit(1); } INFO("Got screenshot: res: %dx%d, bpp: %d\n", xres, yres, bpp); if (l4dm_mem_size(&ds, &fb_size)) { fprintf(stderr, "Couldn't get size of data space\n"); exit(1); } INFO("Size of data space: %d\n", fb_size); if ((fb_mem = malloc(fb_size)) == NULL) { fprintf(stderr, "Couldn't malloc %d Bytes of memory!\n", fb_size); exit(1); } raw_pic_size = xres*yres*3; if ((raw_pic_mem = malloc(raw_pic_size)) == NULL) { fprintf(stderr, "Couldn't malloc %d bytes of memory!\n", raw_pic_size); exit(1); } pages = fb_size / L4_PAGESIZE; // size is always a multiple of L4_PAGESIZE? for (i = 0; i < pages; i++) { /* unmap memory */ l4_fpage_unmap(l4_fpage((l4_umword_t)map_page, L4_LOG2_PAGESIZE, L4_FPAGE_RW, L4_MAP_ITEM_MAP), L4_FP_FLUSH_PAGE|L4_FP_ALL_SPACES); /* page in L4 page */ if ((error = l4dm_map_pages(&ds, i*L4_PAGESIZE, L4_PAGESIZE, (l4_addr_t)map_page, L4_LOG2_PAGESIZE, 0, L4DM_RO, &fpage_addr,&fpage_size)) < 0) { fprintf(stderr, "Error %d requesting ds %d at ds_manager " l4util_idfmt"\n", error, ds.id, l4util_idstr(ds.manager)); l4dm_close(&ds); exit(error); } memcpy(fb_mem + i*L4_PAGESIZE, map_page, L4_PAGESIZE); } if (l4dm_close(&ds)) { fprintf(stderr, "Error on closing dataspace, expect memory leakage...\n"); } }
static void l4x_flush_page(struct mm_struct *mm, unsigned long address, unsigned long vaddr, int size, unsigned long flush_rights) { l4_msgtag_t tag; if (mm && mm->context.l4x_unmap_mode == L4X_UNMAP_MODE_SKIP) return; /* some checks: */ if (address > 0x80000000UL) { unsigned long remap; remap = find_ioremap_entry(address); /* VU: it may happen, that memory is not remapped but mapped in * user space, if a task mmaps /dev/mem but never accesses it. * Therefore, we fail silently... */ if (!remap) return; address = remap; } else if ((address & PAGE_MASK) == 0) address = PAGE0_PAGE_ADDRESS; #if 0 /* only for debugging */ else { if ((address >= (unsigned long)high_memory) && (address < 0x80000000UL)) { printk("flushing non physical page (0x%lx)\n", address); enter_kdebug("flush_page: non physical page"); } } #endif /* do the real flush */ if (mm && !l4_is_invalid_cap(mm->context.task)) { L4XV_V(f); if (!mm->context.task) l4x_printf("%s: Ups, task == 0\n", __func__); /* Direct flush in the child, use virtual address in the * child address space */ L4XV_L(f); tag = l4_task_unmap(mm->context.task, l4_fpage(vaddr & PAGE_MASK, size, flush_rights), L4_FP_ALL_SPACES); L4XV_U(f); } else { L4XV_V(f); /* Flush all pages in all childs using the 'physical' * address known in the Linux server */ L4XV_L(f); tag = l4_task_unmap(L4RE_THIS_TASK_CAP, l4_fpage(address & PAGE_MASK, size, flush_rights), L4_FP_OTHER_SPACES); L4XV_U(f); } if (l4_error(tag)) l4x_printf("l4_task_unmap error %ld\n", l4_error(tag)); }
int main(dword_t mb_magic, struct multiboot_info *mbi) { CORBA_Environment env = idl4_default_environment; int i,j,msg[8] = { 0,0x6100,0x0100,0,0,0,0,0 }; struct mod_list *mods; l4_msgdope_t result; Elf32_Phdr *phdr; l4_threadid_t msvr; int mobj, pagerid, tobj; int blockID=0; int found_root=0; int totalBlock=0; init_global_data(); printf("Booter task (%x) starting, pager is %X\n", booter.raw, sigma0.raw); check_multiboot_header(mb_magic,&mbi); printf("Multiboot header found at %X\n", (dword_t) mbi); mods = (mod_list*) mbi->mods_addr; secure_modules(mods, (int)mbi->mods_count); launch_aux_pager(); task[0].active=1; task[0].root.svr.raw=0; task[0].root.obj=0; task[0].memory.svr=sigma0; task[0].memory.obj=DEFAULT_OBJECT; strncpy(task[0].cmdline,(char*)mods[BOOTER_MODULE_NR].cmdline,MAXLENGTH); task[0].task_id=booter; task[0].owner=booter; // ************************************************************************* // *** bootup sequence if (mbi->mods_count < (BOOTER_MODULE_NR+2)) enter_kdebug("nothing to load"); mods = (struct mod_list *) mbi->mods_addr; nexttask = booter; (void)nexttask.id.task++; for (j=BOOTER_MODULE_NR+1;j<(int)mbi->mods_count;j++) { Elf32_Ehdr *file_hdr; // *** check sanity of elf file file_hdr = (Elf32_Ehdr *) mods[j].mod_start; if (file_hdr->e_ident[EI_MAG0] != ELFMAG0 || file_hdr->e_ident[EI_MAG1] != ELFMAG1 || file_hdr->e_ident[EI_MAG2] != ELFMAG2 || file_hdr->e_ident[EI_MAG3] != ELFMAG3) { i=0; while ((i<MAXBLOCKS) && (block[i].active)) i++; if (i<MAXBLOCKS) { block[i].active=1; block[i].phys_addr=(int)mods[j].mod_start; block[i].capacity=((int)mods[j].mod_end-(int)mods[j].mod_start)/512; block[i].blocksize=512; totalBlock++; if (found_root) { char name[20]; sprintf(name,"hd%c",'a'+(blockID++)); directory_link(dev.svr,dev.obj,3,name,&booter,MAXTASKS+i,&env); } } continue; } if (file_hdr->e_type != ET_EXEC) enter_kdebug("unexpected e_type"); if (file_hdr->e_machine != EM_386) enter_kdebug("not an intel binary"); if (file_hdr->e_version != EV_CURRENT) enter_kdebug("version mismatch?"); if (file_hdr->e_flags != 0) enter_kdebug("unexpected flags?"); if (file_hdr->e_phnum <= 0) enter_kdebug("No loadable program sections"); // *** create the task. this will map the trampoline code into page 0 // of the newly created address space printf("Task %d: %s\n",(int)nexttask.id.task,(char*)mods[j].cmdline); l4_task_new(nexttask, 255, 0, 0, auxpager); // *** if the memory server is already running, make it the new task's // pager. (should be replaced by dynamic object creation) if (j>(BOOTER_MODULE_NR+1)) { if (creator_create(memsvr,DEFAULT_OBJECT,sizeof(api_mem)/sizeof(int), (sdword*)&api_mem,&msvr,&mobj,&env)!=ESUCCESS) enter_kdebug("Memory object creation failed"); memory_set_maxpages(msvr,mobj,99999999,&env); memory_attach(msvr,mobj,&nexttask,&env); memory_get_pagerid(msvr,mobj,&pagerid,&env); l4_ipc_send(nexttask,0,TRAMPOLINE_NEW_PAGER,pagerid,0,L4_IPC_NEVER,&result); } else { msvr = sigma0;mobj=DEFAULT_OBJECT; } // *** allocate struct for the task tobj=0; while ((tobj<MAXTASKS) && (task[tobj].active)) tobj++; if (tobj==MAXTASKS) enter_kdebug("Too many tasks"); task[tobj].active=1; if (found_root) { task[tobj].root.svr=root.svr; task[tobj].root.obj=root.obj; } else { task[tobj].root.svr.raw=0; task[tobj].root.obj=0; } task[tobj].memory.svr=msvr; task[tobj].memory.obj=mobj; strncpy(task[tobj].cmdline,(char*)mods[j].cmdline,MAXLENGTH); task[tobj].cmdline[MAXLENGTH-1]=0; task[tobj].task_id=nexttask; task[tobj].owner=booter; // *** parse all the headers phdr = (Elf32_Phdr *) (file_hdr->e_phoff + (unsigned int) file_hdr); for (i=0;i<file_hdr->e_phnum;i++) if (phdr[i].p_type == PT_LOAD) { // *** notify the trampoline l4_ipc_send(nexttask,0,TRAMPOLINE_RECEIVE,(int)phdr[i].p_vaddr, (int)phdr[i].p_filesz,L4_IPC_NEVER,&result); msg[6]=(int)phdr[i].p_filesz; msg[7]=(int)file_hdr + phdr[i].p_offset; // *** send the string ipc. this will cause a bunch of pagefaults, // which will be handled by the child's pager #ifdef DEBUG printf("Copying segment of size %x from address %x to %x\n",msg[6],msg[7],(int)phdr[i].p_vaddr); #endif l4_ipc_send(nexttask,&msg,0,0,0,L4_IPC_NEVER,&result); // *** zero out any bss segments if (phdr[i].p_memsz>phdr[i].p_filesz) { int zero_base = phdr[i].p_vaddr+phdr[i].p_filesz; int zero_size = phdr[i].p_memsz-phdr[i].p_filesz; #ifdef DEBUG printf("Erasing zone at %x, size %x\n",zero_base,zero_size); #endif l4_ipc_send(nexttask,0,TRAMPOLINE_ZERO_ZONE, zero_base,zero_size,L4_IPC_NEVER,&result); } } // *** if this is the memory server, change the pager to sigma0 if (j==(BOOTER_MODULE_NR+1)) l4_ipc_send(nexttask,0,TRAMPOLINE_NEW_PAGER,sigma0.raw,0,L4_IPC_NEVER,&result); // *** start the program #ifdef DEBUG printf("Jumping to program entry point at %x [objID=%d]\n\n",(int)file_hdr->e_entry,tobj); #endif l4_ipc_send(nexttask,0,TRAMPOLINE_LAUNCH,tobj,file_hdr->e_entry,L4_IPC_NEVER,&result); // *** wait until thread leaves the trampoline code for (i=0;i<3;i++) l4_thread_switch(nexttask); // *** flush the trampoline l4_fpage_unmap(l4_fpage((int)&_trampoline,L4_LOG2_PAGESIZE,0,0),L4_FP_FLUSH_PAGE); // *** see about the supported interfaces if (j==(BOOTER_MODULE_NR+1)) { memsvr=nexttask; if (generic_implements(nexttask,DEFAULT_OBJECT,sizeof(api_creator)/sizeof(int),(sdword*)&api_creator,&env)!=EYES) enter_kdebug("Memory server does not support Creator API"); if (creator_can_create(nexttask,DEFAULT_OBJECT,sizeof(api_mem)/sizeof(int),(sdword*)&api_mem,&env)!=EYES) enter_kdebug("Memory server cannot create memory objects"); } if (!found_root) if (generic_implements(nexttask,DEFAULT_OBJECT,sizeof(api_creator)/sizeof(int),(sdword*)&api_creator,&env)==EYES) if (creator_can_create(nexttask,DEFAULT_OBJECT,sizeof(api_directory)/sizeof(int),(sdword*)&api_directory,&env)==EYES) { root.svr=nexttask;found_root=1; #ifdef DEBUG printf("Found root nameserver (%X), creating /...\n",root.svr.raw); #endif if (creator_create(root.svr,DEFAULT_OBJECT,sizeof(api_directory)/sizeof(int),(sdword*)&api_directory,&root.svr,&root.obj,&env)!=ESUCCESS) enter_kdebug("Root directory creation failed"); if (creator_create(root.svr,DEFAULT_OBJECT,sizeof(api_directory)/sizeof(int),(sdword*)&api_directory,&dev.svr,&dev.obj,&env)!=ESUCCESS) enter_kdebug("/dev directory creation failed"); if (generic_implements(root.svr,root.obj,sizeof(api_directory)/sizeof(int),(sdword*)&api_directory,&env)!=EYES) enter_kdebug("Defective root directory"); if (directory_link(root.svr,root.obj,3,"dev",&dev.svr,dev.obj,&env)!=ESUCCESS) enter_kdebug("Cannot link dev into /"); if (directory_link(dev.svr,dev.obj,7,"tasksvr",&booter,0,&env)!=ESUCCESS) enter_kdebug("Cannot link tasksvr into /dev/"); for (int i=0;i<MAXBLOCKS;i++) if (block[i].active) { char name[20]; sprintf(name,"hd%c",'a'+(blockID++)); directory_link(dev.svr,dev.obj,3,name,&booter,MAXTASKS+i,&env); } for (int k=0;k<MAXTASKS;k++) if ((task[k].active) && (!task[k].root.svr.raw)) { task[k].root.svr=root.svr; task[k].root.obj=root.obj; } #ifdef DEBUG printf("Root creation completed, all servers notified\n\n"); #endif } (void)nexttask.id.task++; } // *** modify the trampoline to work with elf launcher // *** this is BAD magic! int *m1=(int*)(((int)&_m1)+1); int *m2=(int*)(((int)&_m2)+1); *m1=0x04041001; *m2=0x04041001; if (totalBlock) printf("Created %d block device(s)\n",totalBlock); // *** enter server loop booter_server(); }