diff --git a/tasks/mm0/include/utcb.h b/tasks/mm0/include/utcb.h index e380cb6..9f20344 100644 --- a/tasks/mm0/include/utcb.h +++ b/tasks/mm0/include/utcb.h @@ -3,14 +3,21 @@ #include #include + +#define UTCB_PREFAULT (1 << 0) /* Prefaults utcb pages after mapping */ +#define UTCB_NEW_SHM (1 << 1) /* Creates a new shm segment for utcb */ +#define UTCB_NEW_ADDRESS (1 << 2) /* Allocates a virtual address for utcb */ + int utcb_pool_init(void); void *utcb_new_address(void); int utcb_delete_address(void *utcb_addr); - /* IPC to send utcb address information to tasks */ void *task_send_utcb_address(struct tcb *sender, l4id_t taskid); +int utcb_map_to_task(struct tcb *owner, struct tcb *mapper, unsigned int flags); +int utcb_unmap_from_task(struct tcb *owner, struct tcb *mapper); + /* Prefault an *mmaped* utcb */ int utcb_prefault(struct tcb *task, unsigned int vmflags); diff --git a/tasks/mm0/src/clone.c b/tasks/mm0/src/clone.c index f8e79e9..e23f01c 100755 --- a/tasks/mm0/src/clone.c +++ b/tasks/mm0/src/clone.c @@ -55,11 +55,10 @@ int sys_fork(struct tcb *parent) int err; struct tcb *child; struct exregs_data exregs; - struct vm_file *utcb_shm; struct task_ids ids = { .tid = TASK_ID_INVALID, .spid = parent->spid, - .tgid = TASK_ID_INVALID /* FIXME: !!! FIX THIS */ + .tgid = TASK_ID_INVALID, /* FIXME: !!! FIX THIS */ }; /* Make all shadows in this task read-only */ @@ -76,25 +75,14 @@ int sys_fork(struct tcb *parent) /* Set child's fork return value to 0 */ memset(&exregs, 0, sizeof(exregs)); exregs_set_mr(&exregs, MR_RETURN, 0); + + /* Do the actual exregs call to c0 */ if ((err = l4_exchange_registers(&exregs, child->tid)) < 0) BUG(); - /* Create new utcb for child since it can't use its parent's */ - child->utcb = utcb_new_address(); - - /* - * Create the utcb shared memory segment - * available for child to shmat() - */ - if (IS_ERR(utcb_shm = shm_new((key_t)child->utcb, - __pfn(DEFAULT_UTCB_SIZE)))) - return (int)utcb_shm; - - /* - * Map and prefault child utcb to vfs so that vfs need not - * call us to map it. - */ - task_map_prefault_utcb(find_task(VFS_TID), child); + /* Create and prefault a utcb for child and map it to vfs task */ + utcb_map_to_task(child, find_task(VFS_TID), + UTCB_NEW_ADDRESS | UTCB_NEW_SHM | UTCB_PREFAULT); /* We can now notify vfs about forked process */ vfs_notify_fork(child, parent); @@ -112,7 +100,6 @@ int sys_fork(struct tcb *parent) int sys_clone(struct tcb *parent, void *child_stack, unsigned int flags) { struct task_ids ids; - struct vm_file *utcb_shm; struct tcb *child; ids.tid = TASK_ID_INVALID; @@ -123,19 +110,9 @@ int sys_clone(struct tcb *parent, void *child_stack, unsigned int flags) TCB_SHARED_VM | TCB_SHARED_FILES))) return (int)child; - /* Allocate a unique utcb address for child */ - child->utcb = utcb_new_address(); - - /* - * Create the utcb shared memory segment - * available for child to shmat() - */ - if (IS_ERR(utcb_shm = shm_new((key_t)child->utcb, - __pfn(DEFAULT_UTCB_SIZE)))) - return (int)utcb_shm; - - /* Map and prefault child's utcb to vfs task */ - task_map_prefault_utcb(find_task(VFS_TID), child); + /* Create and prefault a utcb for child and map it to vfs task */ + utcb_map_to_task(child, find_task(VFS_TID), + UTCB_NEW_ADDRESS | UTCB_NEW_SHM | UTCB_PREFAULT); /* Set up child stack marks with given stack argument */ child->stack_end = (unsigned long)child_stack; @@ -158,6 +135,3 @@ int sys_clone(struct tcb *parent, void *child_stack, unsigned int flags) - - - diff --git a/tasks/mm0/src/task.c b/tasks/mm0/src/task.c index 8df579d..774d78f 100644 --- a/tasks/mm0/src/task.c +++ b/tasks/mm0/src/task.c @@ -444,27 +444,6 @@ struct tcb *task_exec(struct vm_file *f, unsigned long task_region_start, return task; } -/* Maps and prefaults the utcb of a task into another task */ -void task_map_prefault_utcb(struct tcb *mapper, struct tcb *owner) -{ - BUG_ON(!owner->utcb); - - /* - * First internally map the utcb as a shm area. We use - * such posix semantics on purpose to have a unified - * way of doing similar operations. - */ - BUG_ON(IS_ERR(shmat_shmget_internal(mapper, - (key_t)owner->utcb, - owner->utcb))); - - /* Prefault the owner's utcb to mapper's address space */ - for (int i = 0; i < __pfn(DEFAULT_UTCB_SIZE); i++) - prefault_page(mapper, (unsigned long)owner->utcb + - __pfn_to_addr(i), VM_READ | VM_WRITE); - -} - /* * During its initialisation FS0 wants to learn how many boot tasks * are running, and their tids, which includes itself. This function @@ -487,12 +466,7 @@ int send_task_data(struct tcb *vfs) BUG_ON(!vfs->utcb); /* Attach mm0 to vfs's utcb segment just like a normal task */ - BUG_ON(IS_ERR(shmat_shmget_internal(self, (key_t)vfs->utcb, vfs->utcb))); - - /* Prefault those pages to self. */ - for (int i = 0; i < __pfn(DEFAULT_UTCB_SIZE); i++) - prefault_page(self, (unsigned long)vfs->utcb + __pfn_to_addr(i), - VM_READ | VM_WRITE); + utcb_map_to_task(vfs, self, UTCB_PREFAULT); /* Write all requested task information to utcb's user buffer area */ tdata_head = (struct task_data_head *)vfs->utcb; diff --git a/tasks/mm0/src/utcb.c b/tasks/mm0/src/utcb.c index e531f63..e2f4d05 100644 --- a/tasks/mm0/src/utcb.c +++ b/tasks/mm0/src/utcb.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include INC_GLUE(memlayout.h) @@ -70,3 +71,36 @@ void *task_send_utcb_address(struct tcb *sender, l4id_t taskid) return 0; } +int utcb_map_to_task(struct tcb *owner, struct tcb *mapper, unsigned int flags) +{ + struct vm_file *utcb_shm; + + /* Allocate a new utcb address */ + if (flags & UTCB_NEW_ADDRESS) + owner->utcb = utcb_new_address(); + else if (!owner->utcb) + BUG(); + + /* Create a new shared memory segment for utcb */ + if (flags & UTCB_NEW_SHM) + if (IS_ERR(utcb_shm = shm_new((key_t)owner->utcb, + __pfn(DEFAULT_UTCB_SIZE)))) + return (int)utcb_shm; + + /* Map the utcb to mapper */ + if (IS_ERR(shmat_shmget_internal(mapper, (key_t)owner->utcb, + owner->utcb))) + BUG(); + + /* Prefault the owner's utcb to mapper's address space */ + if (flags & UTCB_PREFAULT) + for (int i = 0; i < __pfn(DEFAULT_UTCB_SIZE); i++) + prefault_page(mapper, (unsigned long)owner->utcb + + __pfn_to_addr(i), VM_READ | VM_WRITE); + return 0; +} + +int utcb_unmap_from_task(struct tcb *owner, struct tcb *mapper) +{ + return 0; +}