static void do_get(trapframe *tf, uint32_t cmd) { proc *curr = proc_cur(); spinlock_acquire(&curr->lock); // Find child index (includes node number and child number) int child_index = tf->regs.edx; uint8_t node_number = child_index >> 8; // First 8 bits are the node number uint8_t child_number = child_index & 0xff;// The last 8 bits for child number // cprintf("node %d get: dest node: %d, child: %d, home node: %d\n", // net_node, node_number, child_number, RRNODE(curr->home)); // When migrating, make sure to adjust eip! => entry == 0 // Trying to migrate home and this is not its home if(node_number == 0) { node_number = RRNODE(curr->home); } if (net_node != node_number) { // cprintf("sys_get: %p migrating to %d\n", curr, node_number); spinlock_release(&curr->lock); net_migrate(tf, node_number, 0); } proc *child = curr->child[child_number]; if(!child) child = &proc_null; // cprintf("No child process %d\n", child_index); if(child->state != PROC_STOP) proc_wait(curr, child, tf); spinlock_release(&curr->lock); // cprintf("do_get: current proc: %p, cpu_cur proc: %p\n", curr, cpu_cur()->proc); uint32_t dest = tf->regs.edi; //syscall.h uint32_t size = tf->regs.ecx; uint32_t src = tf->regs.esi; if(cmd & SYS_MEMOP) { int op = cmd & SYS_MEMOP; // Check if the destination range is okay if(dest < VM_USERLO || dest > VM_USERHI || dest + size > VM_USERHI) systrap(tf, T_GPFLT, 0); if(op == SYS_COPY) { // we have to check the source too if(src < VM_USERLO || src > VM_USERHI || src + size > VM_USERHI) systrap(tf, T_GPFLT, 0); pmap_copy(child->pdir, src, curr->pdir, dest, size); } else if(op == SYS_MERGE) { pmap_merge(child->rpdir, child->pdir, src, curr->pdir, dest, size); } else pmap_remove(curr->pdir, dest, size); } if(cmd & SYS_PERM) pmap_setperm(curr->pdir, dest, size, cmd & SYS_RW); if(cmd & SYS_REGS) usercopy(tf, 1, &child->sv, tf->regs.ebx, sizeof(procstate)); trap_return(tf); // syscall completed }
static void do_get(trapframe *tf, uint32_t cmd) { proc *p = proc_cur(); assert(p->state == PROC_RUN && p->runcpu == cpu_cur()); //cprintf("GET proc %x eip %x esp %x cmd %x\n", p, tf->eip, tf->esp, cmd); spinlock_acquire(&p->lock); // Find the named child process; DON'T create if it doesn't exist uint32_t cn = tf->regs.edx & 0xff; proc *cp = p->child[cn]; if (!cp) cp = &proc_null; // Synchronize with child if necessary. if (cp->state != PROC_STOP) proc_wait(p, cp, tf); // Since the child is now stopped, it's ours to control; // we no longer need our process lock - // and we don't want to be holding it if usercopy() below aborts. spinlock_release(&p->lock); // Get child's general register state if (cmd & SYS_REGS) { int len = offsetof(procstate, fx); // just integer regs if (cmd & SYS_FPU) len = sizeof(procstate); // whole shebang usercopy(tf, 1, &cp->sv, tf->regs.ebx, len); // Copy child process's trapframe into user space procstate *cs = (procstate*) tf->regs.ebx; memcpy(cs, &cp->sv, len); } uint32_t sva = tf->regs.esi; uint32_t dva = tf->regs.edi; uint32_t size = tf->regs.ecx; switch (cmd & SYS_MEMOP) { case 0: // no memory operation break; case SYS_COPY: case SYS_MERGE: // validate source region if (PTOFF(sva) || PTOFF(size) || sva < VM_USERLO || sva > VM_USERHI || size > VM_USERHI-sva) systrap(tf, T_GPFLT, 0); // fall thru... case SYS_ZERO: // validate destination region if (PTOFF(dva) || PTOFF(size) || dva < VM_USERLO || dva > VM_USERHI || size > VM_USERHI-dva) systrap(tf, T_GPFLT, 0); switch (cmd & SYS_MEMOP) { case SYS_ZERO: // zero memory and clear permissions pmap_remove(p->pdir, dva, size); break; case SYS_COPY: // copy from local src to dest in child pmap_copy(cp->pdir, sva, p->pdir, dva, size); break; case SYS_MERGE: // merge from local src to dest in child pmap_merge(cp->rpdir, cp->pdir, sva, p->pdir, dva, size); break; } break; default: systrap(tf, T_GPFLT, 0); } if (cmd & SYS_PERM) { // validate destination region if (PGOFF(dva) || PGOFF(size) || dva < VM_USERLO || dva > VM_USERHI || size > VM_USERHI-dva) systrap(tf, T_GPFLT, 0); if (!pmap_setperm(p->pdir, dva, size, cmd & SYS_RW)) panic("pmap_get: no memory to set permissions"); } if (cmd & SYS_SNAP) systrap(tf, T_GPFLT, 0); // only valid for PUT trap_return(tf); // syscall completed }
static void do_put(trapframe *tf, uint32_t cmd) { proc *curr = proc_cur(); spinlock_acquire(&curr->lock); uint32_t child_index = tf->regs.edx; uint8_t node_number = child_index >> 8 & 0xff; // First 8 bits are the node number uint8_t child_number = child_index & 0xff;// The last 8 bits for child number // cprintf("node %d put: dest node: %d, child: %d, home node: %d\n", // net_node, node_number, child_number, RRNODE(curr->home)); // When migrating, make sure to adjust eip! => entry == 0 // Trying to migrate home and this is not its home if(node_number == 0) { node_number = RRNODE(curr->home); } if (net_node != node_number) { // cprintf("sys_put: %p migrating to %d\n", curr, RRNODE(curr->home)); spinlock_release(&curr->lock); net_migrate(tf, node_number, 0); } proc *child = curr->child[child_number]; if(!child) child = proc_alloc(curr, child_number); if(child->state != PROC_STOP) proc_wait(curr, child, tf); spinlock_release(&curr->lock); // cprintf("do_put: current proc: %p, cpu_cur proc: %p\n", curr, cpu_cur()->proc); if(cmd & SYS_REGS) { usercopy(tf, 0, &child->sv, tf->regs.ebx, sizeof(procstate)); child->sv.tf.ds = CPU_GDT_UDATA | 3; child->sv.tf.es = CPU_GDT_UDATA | 3; child->sv.tf.cs = CPU_GDT_UCODE | 3; child->sv.tf.ss = CPU_GDT_UDATA | 3; child->sv.tf.eflags &= FL_USER; child->sv.tf.eflags |= FL_IF; } uint32_t dest = tf->regs.edi; //syscall.h uint32_t size = tf->regs.ecx; uint32_t src = tf->regs.esi; if(cmd & SYS_MEMOP) { int op = cmd & SYS_MEMOP; // Check if the destination range is okay if(dest < VM_USERLO || dest > VM_USERHI || dest + size > VM_USERHI) systrap(tf, T_GPFLT, 0); if(op == SYS_COPY) { // we have to check the source too if(src < VM_USERLO || src > VM_USERHI || src + size > VM_USERHI) systrap(tf, T_GPFLT, 0); pmap_copy(curr->pdir, src, child->pdir, dest, size); } else pmap_remove(child->pdir, dest, size); } if(cmd & SYS_PERM) pmap_setperm(child->pdir, dest, size, cmd & SYS_RW); if(cmd & SYS_SNAP) // copy pdir to rpdir pmap_copy(child->pdir, VM_USERLO, child->rpdir, VM_USERLO, VM_USERHI-VM_USERLO); if(cmd & SYS_START) proc_ready(child); trap_return(tf); // syscall completed }
static void do_put(trapframe *tf, uint32_t cmd) { proc *p = proc_cur(); assert(p->state == PROC_RUN && p->runcpu == cpu_cur()); cprintf("PUT proc %x eip %x esp %x cmd %x\n", p, tf->eip, tf->esp, cmd); spinlock_acquire(&p->lock); // Find the named child process; create if it doesn't exist uint32_t cn = tf->regs.edx & 0xff; proc *cp = p->child[cn]; if (!cp) { cp = proc_alloc(p, cn); if (!cp) // XX handle more gracefully panic("sys_put: no memory for child"); } // Synchronize with child if necessary. if (cp->state != PROC_STOP) proc_wait(p, cp, tf); // Since the child is now stopped, it's ours to control; // we no longer need our process lock - // and we don't want to be holding it if usercopy() below aborts. spinlock_release(&p->lock); // Put child's general register state if (cmd & SYS_REGS) { int len = offsetof(procstate, fx); // just integer regs if (cmd & SYS_FPU) len = sizeof(procstate); // whole shebang usercopy(tf,0,&cp->sv, tf->regs.ebx, len); // Copy user's trapframe into child process procstate *cs = (procstate*) tf->regs.ebx; memcpy(&cp->sv, cs, len); // Make sure process uses user-mode segments and eflag settings cp->sv.tf.ds = CPU_GDT_UDATA | 3; cp->sv.tf.es = CPU_GDT_UDATA | 3; cp->sv.tf.cs = CPU_GDT_UCODE | 3; cp->sv.tf.ss = CPU_GDT_UDATA | 3; cp->sv.tf.eflags &= FL_USER; cp->sv.tf.eflags |= FL_IF; // enable interrupts } uint32_t sva = tf->regs.esi; uint32_t dva = tf->regs.edi; uint32_t size = tf->regs.ecx; switch (cmd & SYS_MEMOP) { case 0: // no memory operation break; case SYS_COPY: // validate source region if (PTOFF(sva) || PTOFF(size) || sva < VM_USERLO || sva > VM_USERHI || size > VM_USERHI-sva) systrap(tf, T_GPFLT, 0); // fall thru... case SYS_ZERO: // validate destination region if (PTOFF(dva) || PTOFF(size) || dva < VM_USERLO || dva > VM_USERHI || size > VM_USERHI-dva) systrap(tf, T_GPFLT, 0); switch (cmd & SYS_MEMOP) { case SYS_ZERO: // zero memory and clear permissions pmap_remove(cp->pdir, dva, size); break; case SYS_COPY: // copy from local src to dest in child pmap_copy(p->pdir, sva, cp->pdir, dva, size); break; } break; default: systrap(tf, T_GPFLT, 0); } if (cmd & SYS_PERM) { // validate destination region if (PGOFF(dva) || PGOFF(size) || dva < VM_USERLO || dva > VM_USERHI || size > VM_USERHI-dva) systrap(tf, T_GPFLT, 0); if (!pmap_setperm(cp->pdir, dva, size, cmd & SYS_RW)) panic("pmap_put: no memory to set permissions"); } if (cmd & SYS_SNAP) // Snapshot child's state pmap_copy(cp->pdir, VM_USERLO, cp->rpdir, VM_USERLO, VM_USERHI-VM_USERLO); // Start the child if requested if (cmd & SYS_START) proc_ready(cp); trap_return(tf); // syscall completed }