From d182b5b35a4ce05e31fa2d9955f5ee69d4715f06 Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Thu, 13 Nov 2008 21:45:30 +0200 Subject: [PATCH] Initial changes for execve() support --- include/l4/glue/arm/memory.h | 8 +- tasks/fs0/include/syscalls.h | 2 +- tasks/fs0/main.c | 3 + tasks/fs0/src/syscalls.c | 42 +++++ tasks/libl4/include/l4lib/arch-arm/utcb.h | 14 +- tasks/libl4/include/l4lib/ipcdefs.h | 2 +- tasks/libposix/execve.c | 66 +++++++ tasks/mm0/include/file.h | 2 + tasks/mm0/include/lib/elf.h | 61 +++++++ tasks/mm0/include/lib/elfsect.h | 60 ++++++ tasks/mm0/include/lib/elfsym.h | 59 ++++++ tasks/mm0/include/syscalls.h | 1 + tasks/mm0/include/task.h | 3 + tasks/mm0/main.c | 8 + tasks/mm0/src/execve.c | 213 ++++++++++++++++++++++ tasks/mm0/src/file.c | 58 ++++++ tasks/mm0/src/user.c | 3 + tasks/test0/include/tests.h | 1 + tasks/test0/main.c | 3 +- tasks/test0/src/clonetest.c | 4 + tasks/test0/src/exectest.c | 14 ++ 21 files changed, 618 insertions(+), 9 deletions(-) create mode 100644 tasks/libposix/execve.c create mode 100644 tasks/mm0/include/lib/elf.h create mode 100644 tasks/mm0/include/lib/elfsect.h create mode 100644 tasks/mm0/include/lib/elfsym.h create mode 100644 tasks/mm0/src/execve.c create mode 100644 tasks/test0/src/exectest.c diff --git a/include/l4/glue/arm/memory.h b/include/l4/glue/arm/memory.h index 4c27416..bd34e2d 100644 --- a/include/l4/glue/arm/memory.h +++ b/include/l4/glue/arm/memory.h @@ -33,12 +33,16 @@ #define page_align(addr) (((unsigned int)(addr)) & \ (~PAGE_MASK)) -#define is_aligned(val, mask) (!(((unsigned long)val) & mask)) -#define is_page_aligned(val) (!(((unsigned long)val) & PAGE_MASK)) +#define is_aligned(val, mask) (!(((unsigned long)(val)) & mask)) +#define is_page_aligned(val) (!(((unsigned long)(val)) & PAGE_MASK)) +#define page_boundary(x) is_page_aligned(x) /* Align to given size */ #define align(addr, size) (((unsigned int)(addr)) & (~(size-1))) +/* The bytes left until the end of the page that x is in */ +#define TILL_PAGE_ENDS(x) (PAGE_SIZE - ((unsigned long)(x) & PAGE_MASK)) + /* Extract page frame number from address and vice versa. */ #define __pfn(x) (((unsigned long)(x)) >> PAGE_BITS) #define __pfn_to_addr(x) (((unsigned long)(x)) << PAGE_BITS) diff --git a/tasks/fs0/include/syscalls.h b/tasks/fs0/include/syscalls.h index fe4ec20..b10b892 100644 --- a/tasks/fs0/include/syscalls.h +++ b/tasks/fs0/include/syscalls.h @@ -15,7 +15,7 @@ int sys_mkdir(struct tcb *sender, const char *pathname, unsigned int mode); int sys_chdir(struct tcb *sender, const char *pathname); /* Calls from pager that completes a posix call */ - +int pager_open_bypath(struct tcb *pager, char *pathname); int pager_sys_open(struct tcb *sender, l4id_t opener, int fd); int pager_sys_read(struct tcb *sender, unsigned long vnum, unsigned long f_offset, unsigned long npages, void *pagebuf); diff --git a/tasks/fs0/main.c b/tasks/fs0/main.c index 830bcee..b14fbd2 100644 --- a/tasks/fs0/main.c +++ b/tasks/fs0/main.c @@ -98,6 +98,9 @@ void handle_fs_requests(void) case L4_IPC_TAG_PAGER_OPEN: ret = pager_sys_open(sender, (l4id_t)mr[0], (int)mr[1]); break; + case L4_IPC_TAG_PAGER_OPEN_BYPATH: + ret = pager_open_bypath(sender, (char *)mr[0]); + break; case L4_IPC_TAG_PAGER_WRITE: ret = pager_sys_write(sender, (unsigned long)mr[0], (unsigned long)mr[1], (unsigned long)mr[2], (void *)mr[3]); diff --git a/tasks/fs0/src/syscalls.c b/tasks/fs0/src/syscalls.c index 63a3367..ff25e55 100644 --- a/tasks/fs0/src/syscalls.c +++ b/tasks/fs0/src/syscalls.c @@ -64,6 +64,48 @@ int pager_sys_open(struct tcb *pager, l4id_t opener, int fd) return 0; } +/* This is called when the pager needs to open a vfs file via its path */ +int pager_open_bypath(struct tcb *pager, char *pathname) +{ + struct pathdata *pdata; + struct tcb *task; + struct vnode *v; + int retval; + + // printf("%s/%s\n", __TASKNAME__, __FUNCTION__); + if (pager->tid != PAGER_TID) + return -EINVAL; + + // printf("%s/%s\n", __TASKNAME__, __FUNCTION__); + + /* Parse path data */ + if (IS_ERR(pdata = pathdata_parse(pathname, + alloca(strlen(pathname) + 1), + task))) + return (int)pdata; + + /* Search the vnode by that path */ + if (IS_ERR(v = vfs_lookup_bypath(pdata))) { + retval = (int)v; + goto out; + } + + /* + * Write file information, they will + * be sent via the return reply. + */ + write_mr(L4SYS_ARG0, v->vnum); + write_mr(L4SYS_ARG1, v->size); + + return 0; + +out: + pathdata_destroy(pdata); + return retval; + +} + + /* Directories only for now */ void print_vnode(struct vnode *v) { diff --git a/tasks/libl4/include/l4lib/arch-arm/utcb.h b/tasks/libl4/include/l4lib/arch-arm/utcb.h index b001b0b..8e8c112 100644 --- a/tasks/libl4/include/l4lib/arch-arm/utcb.h +++ b/tasks/libl4/include/l4lib/arch-arm/utcb.h @@ -54,16 +54,22 @@ static inline void write_mr(unsigned int offset, unsigned int val) * map-in the task utcb and read those arguments from there. */ -static inline void copy_to_utcb(void *arg, int offset, int size) +static inline int copy_to_utcb(void *arg, int offset, int size) { - BUG_ON(offset + size > PAGE_SIZE); + if (offset + size > PAGE_SIZE) + return -1; + memcpy(utcb_page + offset, arg, size); + return 0; } -static inline void copy_from_utcb(void *buf, int offset, int size) +static inline int copy_from_utcb(void *buf, int offset, int size) { - BUG_ON(offset + size > PAGE_SIZE); + if (offset + size > PAGE_SIZE) + return -1; + memcpy(buf, utcb_page + offset, size); + return 0; } #endif /* !__ASSEMBLY__ */ diff --git a/tasks/libl4/include/l4lib/ipcdefs.h b/tasks/libl4/include/l4lib/ipcdefs.h index d1ca887..e59d677 100644 --- a/tasks/libl4/include/l4lib/ipcdefs.h +++ b/tasks/libl4/include/l4lib/ipcdefs.h @@ -59,5 +59,5 @@ #define L4_IPC_TAG_PAGER_UPDATE_STATS 45 /* Pager updates file stats in vfs */ #define L4_IPC_TAG_NOTIFY_FORK 46 /* Pager notifies vfs of process fork */ #define L4_IPC_TAG_NOTIFY_EXIT 47 /* Pager notifies vfs of process exit */ - +#define L4_IPC_TAG_PAGER_OPEN_BYPATH 48 /* Pager opens a vfs file by pathname */ #endif /* __IPCDEFS_H__ */ diff --git a/tasks/libposix/execve.c b/tasks/libposix/execve.c new file mode 100644 index 0000000..ec0ea0a --- /dev/null +++ b/tasks/libposix/execve.c @@ -0,0 +1,66 @@ +/* + * l4/posix glue for execve() + * + * Copyright (C) 2007 Bahadir Balban + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include INC_GLUE(memory.h) + + +struct sys_execve_args { + char *path; + char **argv; + char **envp; +}; + +static inline int l4_execve(const char *pathname, char *const argv[], char *const envp[]) +{ + int err = 0; + + write_mr(L4SYS_ARG0, (unsigned long)pathname); + write_mr(L4SYS_ARG1, (unsigned long)argv); + write_mr(L4SYS_ARG2, (unsigned long)envp); + + + /* Call pager with open() request. Check ipc error. */ + if ((err = l4_sendrecv(PAGER_TID, PAGER_TID, L4_IPC_TAG_EXECVE)) < 0) { + printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err); + return err; + } + /* Check if syscall itself was successful */ + if ((err = l4_get_retval()) < 0) { + printf("%s: OPEN Error: %d.\n", __FUNCTION__, err); + return err; + } + + return err; +} + +int execve(const char *pathname, char *const argv[], char *const envp[]) +{ + int ret; + + ret = l4_execve(pathname, argv, envp); + + /* If error, return positive error code */ + if (ret < 0) { + errno = -ret; + return -1; + } + /* else return value */ + return ret; + +} + diff --git a/tasks/mm0/include/file.h b/tasks/mm0/include/file.h index 273becf..e6c9315 100644 --- a/tasks/mm0/include/file.h +++ b/tasks/mm0/include/file.h @@ -16,6 +16,8 @@ int sys_lseek(struct tcb *sender, int fd, off_t offset, int whence); int sys_close(struct tcb *sender, int fd); int sys_fsync(struct tcb *sender, int fd); int file_open(struct tcb *opener, int fd); + +struct vm_file *do_open2(struct tcb *task, int fd, unsigned long vnum, unsigned long length); int flush_file_pages(struct vm_file *f); struct vfs_file_data { diff --git a/tasks/mm0/include/lib/elf.h b/tasks/mm0/include/lib/elf.h new file mode 100644 index 0000000..63f36ee --- /dev/null +++ b/tasks/mm0/include/lib/elf.h @@ -0,0 +1,61 @@ +/* + * Definitions for Executable Linking Format + * Based on Portable Formats Specification v1.1 + * + * Copyright (C) 2008 Bahadir Balban + */ + +#ifndef __ELF_H__ +#define __ELF_H__ + +#include + +/* ELF identification indices */ +#define EI_MAG0 0 +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_PAD 7 + +/* Size of ELF identification field */ +#define EI_NIDENT 16 + +/* Values for ELF identification fields */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' + +/* Values for the ELF Class field */ +#define ELFCLASSNONE 0 +#define ELFCLASS32 1 +#define ELFCLASS64 2 + +/* Values for the ELF Data field */ +#define ELFDATANONE 0 +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + + +struct elf_header { + u8 e_ident[EI_NIDENT]; /* ELF identification */ + u16 e_type; /* Object file type */ + u16 e_machine; /* Machine architecture */ + u32 e_version; /* Object file version */ + u32 e_entry; /* Virtual entry address */ + u32 e_phoff; /* Program header offset */ + u32 e_shoff; /* Section header offset */ + u32 e_flags; /* Processor specific flags */ + u16 e_ehsize; /* ELF header size */ + u16 e_phentsize; /* Program header entry size */ + u16 e_phnum; /* Number of program headers */ + u16 e_shentsize; /* Section header entry size */ + u16 e_shnum; /* Number of section headers */ + u16 e_shstrndx; /* Shtable index for strings */ +} __attribute__((__packed__)); + + +#endif /* __ELF_H__ */ diff --git a/tasks/mm0/include/lib/elfsect.h b/tasks/mm0/include/lib/elfsect.h new file mode 100644 index 0000000..033ba07 --- /dev/null +++ b/tasks/mm0/include/lib/elfsect.h @@ -0,0 +1,60 @@ +/* + * Definitions for ELF Sections + * Based on Portable Formats Specification v1.1 + * + * Copyright (C) 2008 Bahadir Balban + */ + +#ifndef __ELFSECT_H__ +#define __ELFSECT_H__ + +#include + +/* Special section indices */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xFF00 +#define SHN_LOPROC 0xFF00 +#define SHN_HIPROC 0xFF1F +#define SHN_ABS 0xFFF1 +#define SHN_COMMON 0xFFF2 +#define SHN_HIRESERVE 0xFFFF + + +struct elf_section_header { + u32 sh_name; /* Index to section header str table for name */ + u32 sh_type; /* Categorises section's semantics */ + u32 sh_flags; /* Flags that define various attributes */ + u32 sh_addr; /* Virtual address for section */ + u32 sh_offset; /* Offset to contents from file beginning */ + u32 sh_size; /* Size of section (note SHT_NOBITS) */ + u32 sh_link; + u32 sh_info; /* Extra section info */ + u32 sh_addralign; /* Section alignment in power of 2 */ + u32 sh_entsize; /* Size of each entry if fixed */ +} __attribute__((__packed__)); + +/* Section type codes */ +#define SHT_NULL 0 /* Inactive */ +#define SHT_PROGBITS 1 /* Program contents */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking info */ +#define SHT_NOTE 7 /* Optional, additional info */ +#define SHT_NOBITS 8 /* Does not occupy file space */ +#define SHT_REL 9 /* Relocation entries */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Symbols for dynamic linking */ +#define SHT_LOPROC 0x70000000 /* Reserved for processors */ +#define SHT_HIPROC 0x7FFFFFFF /* Reserved for processors */ +#define SHT_LOUSER 0x80000000 /* Reserved for user progs */ +#define SHT_HIUSER 0xFFFFFFFF /* Reserved for user progs */ + +/* Section attribute flags */ +#define SHF_WRITE (1 << 0) /* Writeable */ +#define SHF_ALLOC (1 << 1) /* Occupies actual memory */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MASCPROC 0xF0000000 /* Reserved for processors */ + +#endif /* __ELFSECT_H__ */ diff --git a/tasks/mm0/include/lib/elfsym.h b/tasks/mm0/include/lib/elfsym.h new file mode 100644 index 0000000..c3a3353 --- /dev/null +++ b/tasks/mm0/include/lib/elfsym.h @@ -0,0 +1,59 @@ +/* + * Definitions for ELF Symbol tables, symbols + * Based on Portable Formats Specification v1.1 + * + * Copyright (C) 2008 Bahadir Balban + */ +#ifndef __ELFSYM_H__ +#define __ELFSYM_H__ + +#include + +struct elf_symbol_entry { + u32 st_name; /* Index into string table */ + u32 st_value; /* Symbol value; address, aboslute etc. */ + u32 st_size; /* Number of bytes contained in object */ + u8 st_info; /* Type and binding attributes */ + u8 st_other; /* Unused, 0 */ + u16 st_shndx; /* Section header index associated with entry */ +} __attribute__((__packed__)); + +/* To manipulate binding and type attributes on st_info field */ +#define ELF32_ST_BIND(i) ((i) >> 4) +#define ELF32_ST_TYPE(i) ((i) & 0xF) +#define ELF32_ST_INFO(b, t) (((b) << 4) + ((t) & 0xF)) + +/* Symbol binding codes */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +/* Symbol types */ +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + +/* Relocation structures */ +struct elf_rel { + u32 r_offset; + u32 r_info; +} __attribute__((__packed__)); + +struct elf_rela { + u32 r_offset; + u32 r_info; + s32 r_addend; +} __attribute__((__packed__)); + +/* Macros to manipulate r_info field */ +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((u8)(i)) +#define ELF32_R_INFO(s,t) (((s) << 8) + (u8)(t)) + +#endif /* __ELFSYM_H__ */ diff --git a/tasks/mm0/include/syscalls.h b/tasks/mm0/include/syscalls.h index cb885b9..e2610cb 100644 --- a/tasks/mm0/include/syscalls.h +++ b/tasks/mm0/include/syscalls.h @@ -31,6 +31,7 @@ int sys_shmdt(struct tcb *requester, const void *shmaddr); int sys_shmget(key_t key, int size, int shmflg); +int sys_execve(struct tcb *sender, char *pathname, char *argv[], char *envp[]); int sys_fork(struct tcb *parent); int sys_clone(struct tcb *parent, void *child_stack, unsigned int clone_flags); void sys_exit(struct tcb *task, int status); diff --git a/tasks/mm0/include/task.h b/tasks/mm0/include/task.h index 2932655..cc0b4e0 100644 --- a/tasks/mm0/include/task.h +++ b/tasks/mm0/include/task.h @@ -17,6 +17,9 @@ #define __TASKNAME__ __PAGERNAME__ +#define ARGS_MAX DEFAULT_ENV_SIZE +#define PATH_MAX PAGE_SIZE + #define TASK_FILES_MAX 32 /* POSIX minimum is 4Kb */ diff --git a/tasks/mm0/main.c b/tasks/mm0/main.c index 034bc69..5d90bc9 100644 --- a/tasks/mm0/main.c +++ b/tasks/mm0/main.c @@ -135,6 +135,14 @@ void handle_requests(void) sys_exit(sender, (int)mr[0]); return; } + case L4_IPC_TAG_EXECVE: { + ret = sys_execve(sender, (char *)mr[0], + (char **)mr[1], (char **)mr[2]); + if (ret < 0) + break; /* We reply for errors */ + else + return; /* else we're done */ + } case L4_IPC_TAG_BRK: { // ret = sys_brk(sender, (void *)mr[0]); // break; diff --git a/tasks/mm0/src/execve.c b/tasks/mm0/src/execve.c new file mode 100644 index 0000000..7ac44fc --- /dev/null +++ b/tasks/mm0/src/execve.c @@ -0,0 +1,213 @@ +/* + * Program execution + * + * Copyright (C) 2008 Bahadir Balban + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Different from vfs_open(), which validates an already opened + * file descriptor, this call opens a new vfs file by the pager + * using the given path. The vnum handle and file length is returned + * since the pager uses this information to access file pages. + */ +int vfs_open_bypath(const char *pathname, unsigned long *vnum, unsigned long *length) +{ + int err = 0; + struct tcb *vfs; + + // printf("%s/%s\n", __TASKNAME__, __FUNCTION__); + + if (!(vfs = find_task(VFS_TID))) + return -ESRCH; + + /* + * Copy string to vfs utcb. + * + * FIXME: There's a chance we're overwriting other tasks' + * ipc information that is on the vfs utcb. + */ + strcpy(vfs->utcb, pathname); + + l4_save_ipcregs(); + + write_mr(L4SYS_ARG0, (unsigned long)vfs->utcb); + + if ((err = l4_sendrecv(VFS_TID, VFS_TID, + L4_IPC_TAG_PAGER_OPEN_BYPATH)) < 0) { + printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err); + goto out; + } + + /* Check if syscall was successful */ + if ((err = l4_get_retval()) < 0) { + printf("%s: VFS open error: %d.\n", + __FUNCTION__, err); + goto out; + } + + /* Read file information */ + *vnum = read_mr(L4SYS_ARG0); + *length = read_mr(L4SYS_ARG1); + +out: + l4_restore_ipcregs(); + return err; +} + + +int do_execve(char *filename) +{ + int err; + unsigned long vnum, length; + struct vm_file *f; + + /* Get file info from vfs */ + if ((err = vfs_open_bypath(filename, &vnum, &length)) < 0) + return err; + + /* Create and get the file structure */ + if (IS_ERR(f = do_open2(0, 0, vnum, length))) + return (int)f; + + + /* Determine file segments to be mapped */ + + /* See if an interpreter (dynamic linker) is needed */ + + /* Destroy all threads in the same thread group except group leader */ + + /* Release all task resources, do almost everything done in exit() */ + + /* + * Create new process address space. Start by mapping all + * static file segments. We will need brk() for bss. + */ + + +#if 0 +TODO: +Dynamic Linking. + + /* Find the interpreter executable file, if needed */ + + /* + * Map all dynamic linker file segments + * (should not clash with original executable + */ + + /* Set up registers to run dynamic linker (exchange_registers()) */ + + /* Run the interpreter */ + + /* + * The interpreter: + * - May need some initial info (dyn sym tables) at a certain location + * - Will find necessary shared library files in userspace + * (will use open/read). + * - Map them into process address space via mmap() + * - Reinitialise references to symbols in the shared libraries + * - Jump to the entry point of main executable. + */ +#endif + return -1; +} + + +/* + * Copies a null-terminated ragged array (i.e. argv[0]) from userspace into + * buffer. If any page boundary is hit, unmaps previous page, validates and + * maps the new page. + */ +int copy_user_ragged(struct tcb *task, char *buf[], char *user[], int maxlength) +{ + return 0; +} + +/* + * Copy from one buffer to another. Stop if maxlength or + * a page boundary is hit. + */ +int strncpy_page(char *to, char *from, int maxlength) +{ + int count = 0; + + do { + if ((to[count] = from[count]) == '\0') + break; + count++; + } while (count < maxlength && !page_boundary(&from[count])); + + if (page_boundary(&from[count])) + return -EFAULT; + if (count == maxlength) + return -E2BIG; + + return 0; +} + +/* + * Copies a userspace string into buffer. If a page boundary is hit, + * unmaps the previous page, validates and maps the new page + */ +int copy_user_string(struct tcb *task, char *buf, char *user, int maxlength) +{ + int count = maxlength; + char *mapped = 0; + int copied = 0; + int err = 0; + + /* Map the first page the user buffer is in */ + if (!(mapped = pager_validate_map_user_range(task, user, + TILL_PAGE_ENDS(user), + VM_READ))) + return -EINVAL; + + while ((err = strncpy_page(&buf[copied], mapped, count)) < 0) { + if (err == -E2BIG) + return err; + if (err == -EFAULT) { + pager_unmap_user_range(mapped, TILL_PAGE_ENDS(mapped)); + copied += TILL_PAGE_ENDS(mapped); + count -= TILL_PAGE_ENDS(mapped); + if (!(mapped = + pager_validate_map_user_range(task, user + copied, + TILL_PAGE_ENDS(user + copied), + VM_READ))) + return -EINVAL; + } + } + + /* Unmap the final page */ + pager_unmap_user_range(mapped, TILL_PAGE_ENDS(mapped)); + + return 0; +} + +int sys_execve(struct tcb *sender, char *pathname, char *argv[], char *envp[]) +{ + int err; + char *path = kzalloc(PATH_MAX); + + /* Copy the executable path string */ + if ((err = copy_user_string(sender, path, pathname, PATH_MAX)) < 0) + return err; + printf("%s: Copied pathname: %s\n", __FUNCTION__, path); + + return do_execve(path); +} + + + diff --git a/tasks/mm0/src/file.c b/tasks/mm0/src/file.c index 0eca30b..b4d2e25 100644 --- a/tasks/mm0/src/file.c +++ b/tasks/mm0/src/file.c @@ -1,4 +1,6 @@ /* + * File read, write, open and close. + * * Copyright (C) 2008 Bahadir Balban */ #include @@ -118,6 +120,62 @@ out: return err; } +/* + * Initialise a new file and the descriptor for it from given file data. + * Could be called by an actual task or a pager + */ +struct vm_file *do_open2(struct tcb *task, int fd, unsigned long vnum, unsigned long length) +{ + struct vm_file *vmfile; + + /* Is this an open by a task (as opposed to by the pager)? */ + if (task) { + /* fd slot must be empty */ + BUG_ON(task->files->fd[fd].vnum != 0); + BUG_ON(task->files->fd[fd].cursor != 0); + + /* Assign vnum to given fd on the task */ + task->files->fd[fd].vnum = vnum; + task->files->fd[fd].cursor = 0; + } + + /* Check if that vm_file is already in the list */ + list_for_each_entry(vmfile, &global_vm_files.list, list) { + + /* Check whether it is a vfs file and if so vnums match. */ + if ((vmfile->type & VM_FILE_VFS) && + vm_file_to_vnum(vmfile) == vnum) { + + /* Task opener? */ + if (task) + /* Add a reference to it from the task */ + task->files->fd[fd].vmfile = vmfile; + + vmfile->openers++; + return vmfile; + } + } + + /* Otherwise allocate a new one for this vnode */ + if (IS_ERR(vmfile = vfs_file_create())) + return vmfile; + + /* Initialise and add a reference to it from the task */ + vm_file_to_vnum(vmfile) = vnum; + vmfile->length = length; + vmfile->vm_obj.pager = &file_pager; + + /* Task opener? */ + if (task) + task->files->fd[fd].vmfile = vmfile; + vmfile->openers++; + + /* Add to file list */ + global_add_vm_file(vmfile); + + return vmfile; +} + /* Initialise a new file and the descriptor for it from given file data */ int do_open(struct tcb *task, int fd, unsigned long vnum, unsigned long length) { diff --git a/tasks/mm0/src/user.c b/tasks/mm0/src/user.c index 3809baf..f33e78e 100644 --- a/tasks/mm0/src/user.c +++ b/tasks/mm0/src/user.c @@ -40,6 +40,9 @@ int pager_validate_user_range(struct tcb *user, void *userptr, unsigned long siz * Validates and maps the user virtual address range to the pager. * Every virtual page needs to be mapped individually because it's * not guaranteed pages are physically contiguous. + * + * FIXME: There's no logic here to make non-contiguous physical pages + * to get mapped virtually contiguous. */ void *pager_validate_map_user_range(struct tcb *user, void *userptr, unsigned long size, unsigned int vm_flags) diff --git a/tasks/test0/include/tests.h b/tasks/test0/include/tests.h index 946435a..23a75fb 100644 --- a/tasks/test0/include/tests.h +++ b/tasks/test0/include/tests.h @@ -10,5 +10,6 @@ int dirtest(void); int fileio(void); int fileio2(void); int clonetest(void); +void exectest(void); #endif /* __TEST0_TESTS_H__ */ diff --git a/tasks/test0/main.c b/tasks/test0/main.c index 3f5d5b1..adbd32b 100644 --- a/tasks/test0/main.c +++ b/tasks/test0/main.c @@ -33,11 +33,12 @@ void main(void) dirtest(); + exectest(); + /* Check mmap/munmap */ mmaptest(); printf("Forking...\n"); - if ((pid = fork()) < 0) printf("Error forking...\n"); diff --git a/tasks/test0/src/clonetest.c b/tasks/test0/src/clonetest.c index 2ac63a5..f508b47 100644 --- a/tasks/test0/src/clonetest.c +++ b/tasks/test0/src/clonetest.c @@ -47,3 +47,7 @@ int clonetest(void) return 0; } + + + + diff --git a/tasks/test0/src/exectest.c b/tasks/test0/src/exectest.c new file mode 100644 index 0000000..9827728 --- /dev/null +++ b/tasks/test0/src/exectest.c @@ -0,0 +1,14 @@ +/* + * Execve test. + */ + +#include +#include +#include +#include + +void exectest(void) +{ + execve("/usr/home/bahadir/executable", 0, 0); +} +