diff --git a/include/l4/api/syscall.h b/include/l4/api/syscall.h index db52639..87a7c73 100644 --- a/include/l4/api/syscall.h +++ b/include/l4/api/syscall.h @@ -26,18 +26,18 @@ #define syscalls_end_offset sys_time_offset #define SYSCALLS_TOTAL ((syscalls_end_offset >> 2) + 1) -int sys_ipc(struct syscall_args *); -int sys_thread_switch(struct syscall_args *); -int sys_thread_control(struct syscall_args *); -int sys_exchange_registers(struct syscall_args *); -int sys_schedule(struct syscall_args *); -int sys_unmap(struct syscall_args *); -int sys_space_control(struct syscall_args *); -int sys_ipc_control(struct syscall_args *); -int sys_map(struct syscall_args *); -int sys_getid(struct syscall_args *); -int sys_kread(struct syscall_args *); -int sys_kmem_control(struct syscall_args *); -int sys_time(struct syscall_args *); +int sys_ipc(struct syscall_context *); +int sys_thread_switch(struct syscall_context *); +int sys_thread_control(struct syscall_context *); +int sys_exchange_registers(struct syscall_context *); +int sys_schedule(struct syscall_context *); +int sys_unmap(struct syscall_context *); +int sys_space_control(struct syscall_context *); +int sys_ipc_control(struct syscall_context *); +int sys_map(struct syscall_context *); +int sys_getid(struct syscall_context *); +int sys_kread(struct syscall_context *); +int sys_kmem_control(struct syscall_context *); +int sys_time(struct syscall_context *); #endif /* __SYSCALL_H__ */ diff --git a/include/l4/glue/arm/syscall.h b/include/l4/glue/arm/syscall.h index 448a98c..c0c7071 100644 --- a/include/l4/glue/arm/syscall.h +++ b/include/l4/glue/arm/syscall.h @@ -23,7 +23,7 @@ extern unsigned int __syscall_page_start; * just after entering a system call exception. */ typedef struct syscall_context { - u32 spsr + u32 spsr; u32 r0; u32 r1; u32 r2; @@ -55,10 +55,10 @@ typedef struct msg_regs { /* Represents each syscall. We get argument registers * from stack for now. This is slower but the simplest. */ -typedef int (*syscall_fn_t)(struct syscall_args *regs); +typedef int (*syscall_fn_t)(struct syscall_context *regs); /* Entry point for syscall dispatching. Called from asm */ -int syscall(struct syscall_args *regs, unsigned long); +int syscall(struct syscall_context *regs, unsigned long); /* Syscall-related initialiser called during system init. */ void syscall_init(void); diff --git a/src/api/kip.c b/src/api/kip.c index 9e40279..e053714 100644 --- a/src/api/kip.c +++ b/src/api/kip.c @@ -57,7 +57,7 @@ int __sys_kread(int rd, void *dest) * support file positions, any such features aren't supported since this is call * is discarded after startup. */ -int sys_kread(struct syscall_args *a) +int sys_kread(struct syscall_context *a) { unsigned int *arg = KTCB_REF_ARG0(current); void *addr = (void *)arg[1]; /* Buffer address */ diff --git a/src/api/space.c b/src/api/space.c index 68c4cf3..7564c21 100644 --- a/src/api/space.c +++ b/src/api/space.c @@ -15,7 +15,7 @@ * well. struct list_head new_mappings; */ -int sys_map(struct syscall_args *regs) +int sys_map(syscall_context_t *regs) { unsigned long phys = regs->r0; unsigned long virt = regs->r1; @@ -41,7 +41,7 @@ found: } -int sys_unmap(struct syscall_args *regs) +int sys_unmap(syscall_context_t *regs) { unsigned long virt = regs->r0; unsigned long npages = regs->r1; diff --git a/src/api/syscall.c b/src/api/syscall.c index 2a41f82..d45678e 100644 --- a/src/api/syscall.c +++ b/src/api/syscall.c @@ -49,7 +49,7 @@ int sys_schedule(syscall_context_t *regs) return 0; } -int sys_space_control(struct syscall_args *regs) +int sys_space_control(syscall_context_t *regs) { return -ENOSYS; } diff --git a/src/api/thread.c b/src/api/thread.c index 1681033..ef927f8 100644 --- a/src/api/thread.c +++ b/src/api/thread.c @@ -10,7 +10,8 @@ #include #include #include -#include INC_ARCH(mm.h) +#include INC_ARCH(asm.h) +#include INC_SUBARCH(mm.h) int sys_thread_switch(syscall_context_t *regs) { @@ -60,6 +61,8 @@ int thread_start(struct task_ids *ids) return -EINVAL; } +extern unsigned int return_from_syscall; + /* * Copies the pre-syscall context of original thread into the kernel * stack of new thread. Modifies new thread's context registers so that @@ -75,15 +78,15 @@ int arch_setup_new_thread(struct ktcb *new, struct ktcb *orig) * a system call exception. We need the location where it * is saved relative to the start of ktcb. */ - void *syscall_context_offset = (void *)orig->syscall_regs - - (void *)orig; + unsigned long syscall_context_offset = + ((unsigned long)(orig->syscall_regs) - (unsigned long)orig); /* * Copy the saved context from original thread's * stack to new thread stack. */ - memcpy((void *)new + syscall_context_offset, - (void *)orig + syscall_context_offset, + memcpy((void *)((unsigned long)new + syscall_context_offset), + (void *)((unsigned long)orig + syscall_context_offset), sizeof(syscall_context_t)); /* @@ -98,8 +101,7 @@ int arch_setup_new_thread(struct ktcb *new, struct ktcb *orig) * the new thread schedules, it executes the end part of the system * call exception where the previous context is restored. */ - new->context.sp = (unsigned long)((void *)new + - syscall_context_offset); + new->context.sp = (unsigned long)new + syscall_context_offset; new->context.pc = (unsigned long)return_from_syscall; /* Copy other relevant fields from original ktcb */ @@ -140,7 +142,7 @@ int thread_create(struct task_ids *ids, unsigned int flags) goto out; } } - printk("Could not find given space, is ", + printk("Could not find given space, is " "SAMESPC/COPYSPC the right flag?\n"); BUG(); } diff --git a/src/arch/arm/exception.c b/src/arch/arm/exception.c index 25bb258..2e6b3e5 100644 --- a/src/arch/arm/exception.c +++ b/src/arch/arm/exception.c @@ -46,17 +46,16 @@ void fault_ipc_to_pager(u32 faulty_pc, u32 fsr, u32 far) /* * System calls save arguments (and message registers) on the kernel - * stack. They are then referenced from the caller's ktcb. Here, the - * same ktcb reference is set to the fault data so it gives the effect - * as if the ipc to the pager has the fault data in the message - * registers saved on the kernel stack during an ipc syscall. Also this - * way fault does not need to modify the actual utcb MRs in userspace. + * stack. They are then referenced from the caller's ktcb. Here, we + * forge a fault structure as if an ipc syscall has occured. Then + * the reference to the fault structure is set in the ktcb such that + * it lies on the mr0 offset when referred as the syscall context. */ /* Assign fault such that it overlaps as the MR0 reference in ktcb. */ - current->syscall_regs = (syscall_args_t *) + current->syscall_regs = (syscall_context_t *) ((unsigned long)&mr[0] - - offsetof(syscall_args_t, r3)); + offsetof(syscall_context_t, r3)); /* Send ipc to the task's pager */ ipc_sendrecv(current->pagerid, current->pagerid); diff --git a/src/arch/arm/v5/mm.c b/src/arch/arm/v5/mm.c index e3ca3af..8341b0f 100644 --- a/src/arch/arm/v5/mm.c +++ b/src/arch/arm/v5/mm.c @@ -365,12 +365,12 @@ void remove_mapping(unsigned long vaddr) */ pgd_table_t *copy_page_tables(pgd_table_t *from) { - struct pmd_table_t *pmd, *orig; - struct pgd_table_t *pgd; + pmd_table_t *pmd, *orig; + pgd_table_t *pgd; /* Allocate and copy pgd */ pgd = alloc_pgd(); - memcpy(pgd, from, sizeof(struct pgd_table_t)); + memcpy(pgd, from, sizeof(pgd_table_t)); /* Allocate and copy all valid pmds */ for (int i = 0; i < PGD_ENTRY_TOTAL; i++) { diff --git a/src/generic/time.c b/src/generic/time.c index 396903c..6b387a2 100644 --- a/src/generic/time.c +++ b/src/generic/time.c @@ -65,7 +65,7 @@ void update_system_time(void) } /* Read system time */ -int sys_time(struct syscall_args *args) +int sys_time(syscall_context_t *args) { struct timeval *tv = (struct timeval *)args->r0; int set = (int)args->r1; diff --git a/tasks/fs0/include/lib/idpool.h b/tasks/fs0/include/lib/idpool.h index fe2a047..34d8349 100644 --- a/tasks/fs0/include/lib/idpool.h +++ b/tasks/fs0/include/lib/idpool.h @@ -2,6 +2,9 @@ #define __MM0_IDPOOL_H__ #include +#include +#include INC_GLUE(memory.h) +#include struct id_pool { int nwords; @@ -9,7 +12,7 @@ struct id_pool { }; /* Copy one id pool to another by calculating its size */ -static inline void id_pool_copy(struct idpool *to, struct idpool *from, int totalbits) +static inline void id_pool_copy(struct id_pool *to, struct id_pool *from, int totalbits) { int nwords = BITWISE_GETWORD(totalbits); diff --git a/tasks/fs0/include/syscalls.h b/tasks/fs0/include/syscalls.h index 601b97f..4e4d15e 100644 --- a/tasks/fs0/include/syscalls.h +++ b/tasks/fs0/include/syscalls.h @@ -22,4 +22,8 @@ int pager_sys_write(l4id_t sender, unsigned long vnum, unsigned long f_offset, int pager_sys_close(l4id_t sender, l4id_t closer, int fd); int pager_update_stats(l4id_t sender, unsigned long vnum, unsigned long newsize); + +int pager_notify_fork(l4id_t sender, l4id_t parid, + l4id_t chid, unsigned long utcb_address); + #endif /* __FS0_SYSCALLS_H__ */ diff --git a/tasks/fs0/src/lib/idpool.c b/tasks/fs0/src/lib/idpool.c index 0c4639b..76e5970 100644 --- a/tasks/fs0/src/lib/idpool.c +++ b/tasks/fs0/src/lib/idpool.c @@ -10,12 +10,6 @@ #include INC_GLUE(memory.h) #include -static inline void id_pool_copy(struct idpool *to, struct idpool *from, int totalbits) -{ - int nwords = BITWISE_GETWORD(totalbits); - - memcpy(to, from, nwords * SZ_WORD + sizeof(struct id_pool)); -} struct id_pool *id_pool_new_init(int totalbits) { int nwords = BITWISE_GETWORD(totalbits); diff --git a/tasks/fs0/src/task.c b/tasks/fs0/src/task.c index 0a09d13..28bd0a0 100644 --- a/tasks/fs0/src/task.c +++ b/tasks/fs0/src/task.c @@ -72,6 +72,22 @@ int receive_pager_taskdata_orig(l4id_t *tdata) return 0; } +/* Allocate a task struct and initialise it */ +struct tcb *create_tcb(void) +{ + struct tcb *t; + + if (!(t = kmalloc(sizeof(*t)))) + return PTR_ERR(-ENOMEM); + + t->fdpool = id_pool_new_init(TASK_FILES_MAX); + INIT_LIST_HEAD(&t->list); + list_add_tail(&t->list, &tcb_head.list); + tcb_head.total++; + + return t; +} + /* * Receives ipc from pager about a new fork event and * the information on the resulting child task. @@ -80,7 +96,6 @@ int pager_notify_fork(l4id_t sender, l4id_t parid, l4id_t chid, unsigned long utcb_address) { struct tcb *child, *parent; - int err; // printf("%s/%s\n", __TASKNAME__, __FUNCTION__); BUG_ON(!(parent = find_task(parid))); @@ -136,22 +151,6 @@ struct task_data_head *receive_pager_taskdata(void) return (struct task_data_head *)utcb_page; } -/* Allocate a task struct and initialise it */ -struct tcb *create_tcb(void) -{ - struct tcb *t; - - if (!(t = kmalloc(sizeof(*t)))) - return PTR_ERR(-ENOMEM); - - t->fdpool = id_pool_new_init(TASK_FILES_MAX); - INIT_LIST_HEAD(&t->list); - list_add_tail(&t->list, &tcb_head.list); - tcb_head.total++; - - return t; -} - /* Attaches to task's utcb. FIXME: Add SHM_RDONLY and test it. */ int task_utcb_attach(struct tcb *t) { diff --git a/tasks/mm0/include/mmap.h b/tasks/mm0/include/mmap.h index 0050f1e..f4615f1 100644 --- a/tasks/mm0/include/mmap.h +++ b/tasks/mm0/include/mmap.h @@ -20,6 +20,9 @@ #define MAP_SHARED 0x01 #define MAP_PRIVATE 0x02 +struct vm_area *vma_new(unsigned long pfn_start, unsigned long npages, + unsigned int flags, unsigned long file_offset); + int do_munmap(void *vaddr, unsigned long size, struct tcb *task); int do_mmap(struct vm_file *mapfile, unsigned long f_offset, struct tcb *t, diff --git a/tasks/mm0/include/syscalls.h b/tasks/mm0/include/syscalls.h index 8fc3e46..e68423b 100644 --- a/tasks/mm0/include/syscalls.h +++ b/tasks/mm0/include/syscalls.h @@ -10,6 +10,7 @@ #define __MM0_SYSARGS_H__ #include +#include /* For reading argument data from a system call */ struct sys_mmap_args { @@ -43,7 +44,7 @@ struct sys_shmget_args { int sys_shmget(key_t key, int size, int shmflg); -int sys_fork(void); +int sys_fork(l4id_t parent); #endif /* __MM0_SYSARGS_H__ */ diff --git a/tasks/mm0/include/task.h b/tasks/mm0/include/task.h index 111b282..c3c866f 100644 --- a/tasks/mm0/include/task.h +++ b/tasks/mm0/include/task.h @@ -10,7 +10,7 @@ #include #include INC_GLUE(memlayout.h) #include -#include +#include #include #include #include diff --git a/tasks/mm0/main.c b/tasks/mm0/main.c index f15aa7a..ff4f3d9 100644 --- a/tasks/mm0/main.c +++ b/tasks/mm0/main.c @@ -120,7 +120,7 @@ void handle_requests(void) args->flags, args->fd, __pfn(args->offset)); break; } - case L4_IPC_TAG_MMAP: { + case L4_IPC_TAG_FORK: { sys_fork(sender); break; } diff --git a/tasks/mm0/src/clone.c b/tasks/mm0/src/clone.c index 37d5c4a..cd255ae 100755 --- a/tasks/mm0/src/clone.c +++ b/tasks/mm0/src/clone.c @@ -6,7 +6,12 @@ #include #include #include - +#include +#include +#include +#include +#include +#include /* * Copy all vmas from the given task and populate each with @@ -16,10 +21,10 @@ */ int copy_vmas(struct tcb *to, struct tcb *from) { - struct vm_area *vma, new_vma; + struct vm_area *vma, *new_vma; struct vm_obj_link *vmo_link, *new_link; - list_for_each_entry(vma, from->vm_area_list, list) { + list_for_each_entry(vma, &from->vm_area_list, list) { /* Create a new vma */ new_vma = vma_new(vma->pfn_start, vma->pfn_end - vma->pfn_start, @@ -44,7 +49,7 @@ int copy_vmas(struct tcb *to, struct tcb *from) &vma->vm_obj_list))); /* All link copying is finished, now add the new vma to task */ - list_add_tail(&vma_new->list, &to->vm_area_list); + list_add_tail(&new_vma->list, &to->vm_area_list); } return 0; @@ -78,16 +83,16 @@ int copy_tcb(struct tcb *to, struct tcb *from) /* Copy all file descriptors */ memcpy(to->fd, from->fd, TASK_FILES_MAX * sizeof(struct file_descriptor)); + + return 0; } /* * Sends vfs task information about forked child, and its utcb */ -void vfs_notify_fork(struct tcb *child, struct tcb *parent) +int vfs_notify_fork(struct tcb *child, struct tcb *parent) { int err; - struct task_data_head *tdata_head; - struct tcb *vfs; printf("%s/%s\n", __TASKNAME__, __FUNCTION__); @@ -96,7 +101,7 @@ void vfs_notify_fork(struct tcb *child, struct tcb *parent) /* Write parent and child information */ write_mr(L4SYS_ARG0, parent->tid); write_mr(L4SYS_ARG1, child->tid); - write_mr(L4SYS_ARG2, child->utcb); + write_mr(L4SYS_ARG2, (unsigned int)child->utcb); if ((err = l4_sendrecv(VFS_TID, VFS_TID, L4_IPC_TAG_NOTIFY_FORK)) < 0) { @@ -118,6 +123,7 @@ void vfs_notify_fork(struct tcb *child, struct tcb *parent) int do_fork(struct tcb *parent) { struct tcb *child; + struct vm_file *utcb_shm; struct task_ids ids = { .tid = TASK_ID_INVALID, .spid = parent->spid, @@ -130,7 +136,7 @@ int do_fork(struct tcb *parent) * Create a new L4 thread with parent's page tables * kernel stack and kernel-side tcb copied */ - child = task_create(&ids, THREAD_CREATE_COPYSPACE); + child = task_create(&ids, THREAD_CREATE_COPYSPC); /* Copy parent tcb to child */ copy_tcb(child, parent); @@ -142,9 +148,9 @@ int do_fork(struct tcb *parent) * Create the utcb shared memory segment * available for child to shmat() */ - if (IS_ERR(shm = shm_new((key_t)child->utcb, - __pfn(DEFAULT_UTCB_SIZE)))) { - l4_ipc_return((int)shm); + if (IS_ERR(utcb_shm = shm_new((key_t)child->utcb, + __pfn(DEFAULT_UTCB_SIZE)))) { + l4_ipc_return((int)utcb_shm); return 0; } /* FIXME: We should munmap() parent's utcb page from child */ @@ -153,7 +159,7 @@ int do_fork(struct tcb *parent) vfs_notify_fork(child, parent); /* Start forked child. */ - l4_thread_control(THREAD_RUN, ids); + l4_thread_control(THREAD_RUN, &ids); /* Return back to parent */ l4_ipc_return(child->tid); @@ -161,3 +167,11 @@ int do_fork(struct tcb *parent) return 0; } +int sys_fork(l4id_t sender) +{ + struct tcb *parent; + + BUG_ON(!(parent = find_task(sender))); + + return do_fork(parent); +} diff --git a/tasks/mm0/src/fault.c b/tasks/mm0/src/fault.c index 114a243..09daaa2 100644 --- a/tasks/mm0/src/fault.c +++ b/tasks/mm0/src/fault.c @@ -543,7 +543,7 @@ int vm_freeze_shadows(struct tcb *task) /* Map the page as read-only */ l4_map((void *)page_to_phys(p), - (void *)virtual, + (void *)virtual, 1, MAP_USR_RO_FLAGS, task->tid); } break;