void *vm_mappages(phys_bytes p, int pages) { vir_bytes loc; int r; pt_t *pt = &vmprocess->vm_pt; /* Where in our virtual address space can we put it? */ loc = findhole(pages); if(loc == NO_MEM) { printf("vm_mappages: findhole failed\n"); return NULL; } /* Map this page into our address space. */ if((r=pt_writemap(vmprocess, pt, loc, p, VM_PAGE_SIZE*pages, ARCH_VM_PTE_PRESENT | ARCH_VM_PTE_USER | ARCH_VM_PTE_RW #if defined(__arm__) | ARM_VM_PTE_WT #endif , 0)) != OK) { printf("vm_mappages writemap failed\n"); return NULL; } if((r=sys_vmctl(SELF, VMCTL_FLUSHTLB, 0)) != OK) { panic("VMCTL_FLUSHTLB failed: %d", r); } assert(loc); return (void *) loc; }
// write id:value, unless value is empty, in which case we erase the id void writeMacro(char *id) { eraseentry(id); // we need to know the macro value length to allocate space for it // we don't realistically have enough buffer space handy to parse it into // so this is a two-pass operation: first we measure the text, then on // the second pass we stuff it into the eeprom // // measure length of macro value // we get here with inchar = first char of macro and fetchptr one past that // char *fetchmark = --fetchptr; // back up and mark first char of macro text primec(); // re-prime expval = 0; // zero the count parsestring(&countByte); // now expval is the macro value length if (!expval) return; // empty string? we're done int addr = findhole(strlen(id) + expval + 2); // longjmps on fail if (addr >= 0) { saveString(addr, id); // reset parse context fetchptr = fetchmark; primec(); expval = addr + strlen(id) + 1; // set up address for saveByte parsestring(&saveByte); saveByte(0); } }
/* * Look for free space in the vmap. */ static uintptr_t vmapalloc(usize size) { int i, n, o; PTE *pd, *pt; int pdsz, ptsz; pd = (PTE*)(PDMAP+PDX(PDMAP)*4096); pd += PDX(VMAP); pdsz = VMAPSZ/PGLSZ(1); /* * Look directly in the PD entries if the size is * larger than the range mapped by a single entry. */ if(size >= PGLSZ(1)) { n = HOWMANY(size, PGLSZ(1)); if((o = findhole(pd, pdsz, n)) != -1) return VMAP + o*PGLSZ(1); return 0; } /* * Size is smaller than that mapped by a single PD entry. * Look for an already mapped PT page that has room. */ n = HOWMANY(size, PGLSZ(0)); ptsz = PGLSZ(0)/sizeof(PTE); for(i = 0; i < pdsz; i++) { if(!(pd[i] & PteP) || (pd[i] & PtePS)) continue; pt = (PTE*)(PDMAP+(PDX(VMAP)+i)*4096); if((o = findhole(pt, ptsz, n)) != -1) return VMAP + i*PGLSZ(1) + o*PGLSZ(0); } /* * Nothing suitable, start using a new PD entry. */ if((o = findhole(pd, pdsz, 1)) != -1) return VMAP + o*PGLSZ(1); return 0; }
// Parse and store a function definition // void cmd_function(void) { char id[IDLEN+1]; // buffer for id getsym(); // eat "function", get putative id if ((sym != s_undef) && (sym != s_script_eeprom) && (sym != s_script_progmem) && (sym != s_script_file)) unexpected(M_id); strncpy(id, idbuf, IDLEN+1); // save id string through value parse eraseentry(id); getsym(); // eat the id, move on to '{' if (sym != s_lcurly) expected(s_lcurly); // measure the macro text using skipstatement // fetchptr is on the character after '{' // // BUG: This is broken for file scripts char *startmark = (char *) fetchptr; // mark first char of macro text void skipstatement(void); skipstatement(); // gobble it up without executing it char *endmark = (char *) fetchptr; // and note the char past '}' // endmark is past the closing '}' - back up and find it do { --endmark; } while ((endmark > startmark) && (*endmark != '}')); int idlen = strlen(id); int addr = findhole(idlen + (endmark-startmark) + 2); // longjmps on fail if (addr >= 0) { saveString(addr, id); // write the id and its terminator addr += idlen + 1; // advance to payload offset while (startmark < endmark) eewrite(addr++, *startmark++); eewrite(addr, 0); } msgpl(M_saved); }
/*===========================================================================* * vm_allocpage * *===========================================================================*/ PUBLIC void *vm_allocpage(phys_bytes *phys, int reason) { /* Allocate a page for use by VM itself. */ phys_bytes newpage; vir_bytes loc; pt_t *pt; int r; static int level = 0; void *ret; pt = &vmprocess->vm_pt; assert(reason >= 0 && reason < VMP_CATEGORIES); level++; assert(level >= 1); assert(level <= 2); if(level > 1 || !(vmprocess->vm_flags & VMF_HASPT) || !meminit_done) { int r; void *s; s=vm_getsparepage(phys); level--; if(!s) { util_stacktrace(); printf("VM: warning: out of spare pages\n"); } return s; } /* VM does have a pagetable, so get a page and map it in there. * Where in our virtual address space can we put it? */ loc = findhole(pt, arch_vir2map(vmprocess, vmprocess->vm_stacktop), vmprocess->vm_arch.vm_data_top); if(loc == NO_MEM) { level--; printf("VM: vm_allocpage: findhole failed\n"); return NULL; } /* Allocate page of memory for use by VM. As VM * is trusted, we don't have to pre-clear it. */ if((newpage = alloc_mem(CLICKSPERPAGE, 0)) == NO_MEM) { level--; printf("VM: vm_allocpage: alloc_mem failed\n"); return NULL; } *phys = CLICK2ABS(newpage); /* Map this page into our address space. */ if((r=pt_writemap(vmprocess, pt, loc, *phys, I386_PAGE_SIZE, I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE, 0)) != OK) { free_mem(newpage, CLICKSPERPAGE); printf("vm_allocpage writemap failed\n"); level--; return NULL; } if((r=sys_vmctl(SELF, VMCTL_FLUSHTLB, 0)) != OK) { panic("VMCTL_FLUSHTLB failed: %d", r); } level--; /* Return user-space-ready pointer to it. */ ret = (void *) arch_map2vir(vmprocess, loc); return ret; }
/*===========================================================================* * vm_allocpage * *===========================================================================*/ void *vm_allocpages(phys_bytes *phys, int reason, int pages) { /* Allocate a page for use by VM itself. */ phys_bytes newpage; vir_bytes loc; pt_t *pt; int r; static int level = 0; void *ret; u32_t mem_flags = 0; pt = &vmprocess->vm_pt; assert(reason >= 0 && reason < VMP_CATEGORIES); assert(pages > 0); level++; assert(level >= 1); assert(level <= 2); if((level > 1) || !pt_init_done) { void *s; if(pages == 1) s=vm_getsparepage(phys); else if(pages == 4) s=vm_getsparepagedir(phys); else panic("%d pages", pages); level--; if(!s) { util_stacktrace(); printf("VM: warning: out of spare pages\n"); } if(!is_staticaddr(s)) vm_self_pages++; return s; } #if defined(__arm__) if (reason == VMP_PAGEDIR) { mem_flags |= PAF_ALIGN16K; } #endif /* VM does have a pagetable, so get a page and map it in there. * Where in our virtual address space can we put it? */ loc = findhole(pages); if(loc == NO_MEM) { level--; printf("VM: vm_allocpage: findhole failed\n"); return NULL; } /* Allocate page of memory for use by VM. As VM * is trusted, we don't have to pre-clear it. */ if((newpage = alloc_mem(pages, mem_flags)) == NO_MEM) { level--; printf("VM: vm_allocpage: alloc_mem failed\n"); return NULL; } *phys = CLICK2ABS(newpage); /* Map this page into our address space. */ if((r=pt_writemap(vmprocess, pt, loc, *phys, VM_PAGE_SIZE*pages, ARCH_VM_PTE_PRESENT | ARCH_VM_PTE_USER | ARCH_VM_PTE_RW #if defined(__arm__) | ARM_VM_PTE_WB | ARM_VM_PTE_SHAREABLE #endif , 0)) != OK) { free_mem(newpage, pages); printf("vm_allocpage writemap failed\n"); level--; return NULL; } if((r=sys_vmctl(SELF, VMCTL_FLUSHTLB, 0)) != OK) { panic("VMCTL_FLUSHTLB failed: %d", r); } level--; /* Return user-space-ready pointer to it. */ ret = (void *) loc; vm_self_pages++; return ret; }