diff --git a/tasks/fs0/SConstruct b/tasks/fs0/SConstruct index bae4e53..6c6b1e3 100644 --- a/tasks/fs0/SConstruct +++ b/tasks/fs0/SConstruct @@ -34,6 +34,10 @@ libmem_incpath = "../libmem" libl4_path = "../libl4" libl4_incpath1 = join(libl4_path, "include") +# libposix paths: +libposix_path = "../libposix" +libposix_incpath = join(libposix_path, "include") + # kernel paths: kernel_incpath = join(project_root, "include") @@ -52,13 +56,14 @@ env = Environment(CC = 'arm-none-linux-gnueabi-gcc', # such as stdarg.h e.g. for variable args, as in printk(). CCFLAGS = ['-g', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', '-Werror'], LINKFLAGS = ['-nostdlib', '-T' + ld_script, "-L" + libc_libpath, "-L" + libl4_path,\ - "-L" + libmem_path], + "-L" + libmem_path, "-L" + libposix_path], ASFLAGS = ['-D__ASSEMBLY__'], PROGSUFFIX = '.axf', # The suffix to use for final executable ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path - LIBS = [libc_name, 'gcc', 'libmc', 'libl4', 'gcc', libc_name], + LIBS = [libc_name, 'gcc', 'libmc', 'libl4', 'gcc', libc_name, "posix"], CPPFLAGS = "-D__USERSPACE__", - CPPPATH = ['#include', libl4_incpath1, kernel_incpath, libc_incpath, libmem_incpath]) + CPPPATH = ['#include', libl4_incpath1, kernel_incpath, libc_incpath, \ + libposix_incpath, libmem_incpath]) src = [glob("src/*.c"), glob("*.c"), glob("src/arch/arm/*.c"), glob("src/memfs/*.c"), glob("src/lib/*.c")] objs = env.Object(src) diff --git a/tasks/libl4/SConstruct b/tasks/libl4/SConstruct index d4a47f1..7a5de7f 100644 --- a/tasks/libl4/SConstruct +++ b/tasks/libl4/SConstruct @@ -8,6 +8,10 @@ import sys from os.path import join from string import split +# libposix paths: +libposix_libpath = "../libposix" +libposix_incpath = "../libposix/include/posix" + project_root = "../.." kernel_headers = join(project_root, "include") config_h = join(project_root, "include/l4/config.h") @@ -17,7 +21,8 @@ env = Environment(CC = 'arm-none-linux-gnueabi-gcc', LINKFLAGS = ['-nostdlib'], ASFLAGS = ['-D__ASSEMBLY__'], ENV = {'PATH' : os.environ['PATH']}, - LIBS = 'gcc') + LIBS = 'gcc', + CPPPATH = ['#include', libposix_incpath]) def extract_arch_subarch_plat(config_header): diff --git a/tasks/libl4/src/init.c b/tasks/libl4/src/init.c index bf1a9e4..09c991d 100644 --- a/tasks/libl4/src/init.c +++ b/tasks/libl4/src/init.c @@ -10,6 +10,8 @@ #include #include INC_GLUE(memlayout.h) #include +#include +#include __l4_ipc_t __l4_ipc = 0; __l4_map_t __l4_map = 0; @@ -71,6 +73,40 @@ static void *l4_utcb_page(void) return addr; } +/* + * Initialises a non-pager task's shared memory utcb page + * using posix semantics. + */ +int utcb_init(void) +{ + int shmid; + void *shmaddr; + + /* + * Initialise utcb only if we're not the pager. + * The pager does it differently for itself. + */ + if (self_tid() != PAGER_TID) { + + /* Obtain our utcb page address */ + utcb_page = l4_utcb_page(); + printf("%s: UTCB Read from mm0 as: 0x%x\n", __FUNCTION__, + (unsigned long)utcb_page); + + /* Use it as a key to create a shared memory region */ + BUG_ON((shmid = shmget((key_t)utcb_page, + PAGE_SIZE, IPC_CREAT)) < 0); + printf("Shmget success. shmid: %d\n", shmid); + + /* Attach to the region */ + BUG_ON((shmaddr = shmat(shmid, utcb_page, 0)) < 0); + BUG_ON(shmaddr != utcb_page); + printf("Shmat success. Attached %d @ 0x%x\n", shmid, (unsigned long)shmaddr); + } + + return 0; +} + void __l4_init(void) { kip = l4_kernel_interface(0, 0, 0); @@ -89,11 +125,6 @@ void __l4_init(void) __l4_kmem_grant = (__l4_kmem_grant_t)kip->kmem_grant; __l4_kmem_reclaim = (__l4_kmem_reclaim_t)kip->kmem_reclaim; - /* Initialise utcb only if we're not the pager */ - if (self_tid() != PAGER_TID) { - utcb_page = l4_utcb_page(); - printf("%s: UTCB Read from mm0 as: 0x%x\n", __FUNCTION__, - (unsigned long)utcb_page); - } + utcb_init(); } diff --git a/tasks/libposix/errno.c b/tasks/libposix/errno.c index 076f81a..e8cc407 100644 --- a/tasks/libposix/errno.c +++ b/tasks/libposix/errno.c @@ -1,8 +1,8 @@ #include -int errno; +int errno_variable; int *__errno_location(void) { - return &errno; + return &errno_variable; } diff --git a/tasks/libposix/shm.c b/tasks/libposix/shm.c index fcc7a5f..4cb7a9e 100644 --- a/tasks/libposix/shm.c +++ b/tasks/libposix/shm.c @@ -27,13 +27,13 @@ int l4_shmget(l4id_t key, int size, int shmflg) return err; } /* Check if syscall itself was successful */ - if ((err = l4_get_retval()) < 0) { + if (IS_ERR(err = l4_get_retval())) { printf("%s: SHMGET Error: %d.\n", __FUNCTION__, err); return err; - } - /* Obtain shmid. */ - return read_mr(L4SYS_ARG0); + + /* Otherwise err has the positive id number */ + return err; } void *l4_shmat(l4id_t shmid, const void *shmaddr, int shmflg) @@ -50,13 +50,13 @@ void *l4_shmat(l4id_t shmid, const void *shmaddr, int shmflg) return PTR_ERR(err); } /* Check if syscall itself was successful */ - if ((err = l4_get_retval()) < 0) { + if (IS_ERR(err = l4_get_retval())) { printf("%s: SHMAT Error: %d.\n", __FUNCTION__, err); return PTR_ERR(err); } /* Obtain shm base. */ - return (void *)read_mr(L4SYS_ARG0); + return (void *)err; } int l4_shmdt(const void *shmaddr) diff --git a/tasks/mm0/SConstruct b/tasks/mm0/SConstruct index 106edf2..4ce37c1 100644 --- a/tasks/mm0/SConstruct +++ b/tasks/mm0/SConstruct @@ -60,11 +60,12 @@ env = Environment(CC = 'arm-none-linux-gnueabi-gcc', # We don't use -nostdinc because sometimes we need standard headers, # such as stdarg.h e.g. for variable args, as in printk(). CCFLAGS = ['-g', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', '-Werror' ], - LINKFLAGS = ['-nostdlib', '-T' + ld_script, "-L" + libc_libpath, "-L" + libl4_path, "-L" + libmem_path], + LINKFLAGS = ['-nostdlib', '-T' + ld_script, "-L" + libc_libpath, "-L" + libl4_path, \ + "-L" + libposix_path, "-L" + libmem_path], ASFLAGS = ['-D__ASSEMBLY__'], PROGSUFFIX = '.axf', # The suffix to use for final executable ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path - LIBS = [libc_name, 'libl4', 'libmm', 'libmc', 'libkm', \ + LIBS = [libc_name, 'libl4', 'libmm', 'libmc', 'libkm', 'libposix', \ 'gcc', libc_name], # libgcc.a - This is required for division routines. CPPFLAGS = "-D__USERSPACE__", CPPPATH = ['#include', libl4_incpath, libc_incpath, kernel_incpath, \ diff --git a/tasks/mm0/include/mmap.h b/tasks/mm0/include/mmap.h index af42b9d..dcc3278 100644 --- a/tasks/mm0/include/mmap.h +++ b/tasks/mm0/include/mmap.h @@ -25,4 +25,6 @@ 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, unsigned long map_address, unsigned int flags, unsigned int pages); +int mmap_address_validate(unsigned long map_address, unsigned int vm_flags); + #endif /* __MM0_MMAP_H__ */ diff --git a/tasks/mm0/include/shm.h b/tasks/mm0/include/shm.h index ea8e87d..b0eb81f 100644 --- a/tasks/mm0/include/shm.h +++ b/tasks/mm0/include/shm.h @@ -12,7 +12,7 @@ struct shm_descriptor { struct list_head list; /* SHM list, used by mm0 */ struct vm_file *owner; void *shm_addr; /* The virtual address for segment. */ - unsigned long size; /* Size of the area */ + unsigned long size; /* Size of the area in pages */ unsigned int flags; int refcnt; }; @@ -23,12 +23,6 @@ struct shm_descriptor { #define SHM_SHMMIN 1 #define SHM_SHMMAX (PAGE_SIZE * 10) -/* - * NOTE: This flags the unique shm vaddr pool. If its not globally unique - * and shm areas are cached, on ARMv5 cache aliasing occurs. - */ -#define SHM_DISJOINT_VADDR_POOL - /* Initialises shared memory bookkeeping structures */ void shm_init(); diff --git a/tasks/mm0/src/mmap.c b/tasks/mm0/src/mmap.c index 1c00a1f..b8f4457 100644 --- a/tasks/mm0/src/mmap.c +++ b/tasks/mm0/src/mmap.c @@ -458,17 +458,18 @@ int mmap_address_validate(unsigned long map_address, unsigned int vm_flags) } else return 0; /* - * Shared mappings can *also* go in the utcb address space, - * taking in account that utcb's are shared mappings done - * by individual tasks. + * Shared mappings can go in task, utcb, and shared + * memory address space, */ } else if (vm_flags & VMA_SHARED) { if ((map_address >= UTCB_AREA_START && map_address < UTCB_AREA_END) || (map_address >= USER_AREA_START && - map_address < USER_AREA_END)) + map_address < USER_AREA_END) || + (map_address >= SHM_AREA_START && + map_address < SHM_AREA_END)) return 1; - else + else return 0; } else BUG(); diff --git a/tasks/mm0/src/shm.c b/tasks/mm0/src/shm.c index 5ed6ac8..bb1c107 100644 --- a/tasks/mm0/src/shm.c +++ b/tasks/mm0/src/shm.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Bahadir Balban + * Copyright (C) 2007, 2008 Bahadir Balban * * Posix shared memory implementation */ @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -27,8 +28,6 @@ /* The list of shared memory areas that are already set up and working */ static struct list_head shm_desc_list; -/* The single global in-memory swap file for shared memory segments */ - /* Unique shared memory ids */ static struct id_pool *shm_ids; @@ -47,16 +46,16 @@ void shm_init() } /* - * TODO: - * Implement means to return back ipc results, i.e. sender always does ipc_sendrecv() - * and it blocks on its own receive queue. Server then responds back without blocking. - * - * Later on: mmap can be done using vm_areas and phsyical pages can be accessed by vm_areas. + * Attaches to given shm segment mapped at shm_addr if the shm descriptor + * does not already have a base address assigned. If neither shm_addr nor + * the descriptor has an address, allocates one from the shm address pool. + * FIXME: This pool is currently outside the range of mmap'able addresses. */ -static int do_shmat(struct shm_descriptor *shm, void *shm_addr, int shmflg, - l4id_t tid) +static void *do_shmat(struct shm_descriptor *shm, void *shm_addr, int shmflg, + l4id_t tid) { struct tcb *task = find_task(tid); + unsigned int vmflags; int err; if (!task) { @@ -65,59 +64,60 @@ static int do_shmat(struct shm_descriptor *shm, void *shm_addr, int shmflg, BUG(); } - /* - * Currently shared memory base addresses are the same among all - * processes for every unique shm segment. They line up easier on - * the shm swap file this way. Also currently shm_addr argument is - * ignored, and mm0 allocates shm segment addresses. - */ - if (shm->shm_addr) - shm_addr = shm->shm_addr; - else - shm_addr = address_new(&shm_vaddr_pool, __pfn(shm->size)); + if (shm_addr) + shm_addr = (void *)page_align(shm_addr); - BUG_ON(!is_page_aligned(shm_addr)); + /* Determine mmap flags for segment */ + if (shmflg & SHM_RDONLY) + vmflags = VM_READ | VMA_SHARED | VMA_ANONYMOUS; + else + vmflags = VM_READ | VM_WRITE | + VMA_SHARED | VMA_ANONYMOUS; + + /* + * The first user of the segment who supplies a valid + * address sets the base address of the segment. Currently + * all tasks use the same address for each unique segment. + */ + + /* First user? */ + if (!shm->refcnt) + if (mmap_address_validate((unsigned long)shm_addr, vmflags)) + shm->shm_addr = shm_addr; + else + shm->shm_addr = address_new(&shm_vaddr_pool, + __pfn(shm->size)); + else /* Address must be already assigned */ + BUG_ON(!shm->shm_addr); /* * mmap the area to the process as shared. Page fault handler would * handle allocating and paging-in the shared pages. - * - * For anon && shared pages do_mmap() handles allocation of the - * shm swap file and the file offset for the segment. The segment can - * be identified because segment virtual address is globally unique - * per segment and its the same for all the system tasks. */ - if ((err = do_mmap(0, 0, task, (unsigned long)shm_addr, - VM_READ | VM_WRITE | VMA_ANONYMOUS | VMA_SHARED, - shm->size)) < 0) { + if ((err = do_mmap(0, 0, task, (unsigned long)shm->shm_addr, + vmflags, shm->size)) < 0) { printf("do_mmap: Mapping shm area failed with %d.\n", err); BUG(); - } else - printf("%s: %s: Success.\n", __TASKNAME__, __FUNCTION__); - + } /* Now update the shared memory descriptor */ shm->refcnt++; - return 0; + return shm->shm_addr; } -void *sys_shmat(l4id_t requester, l4id_t shmid, void *shmaddr, int shmflg) +int sys_shmat(l4id_t requester, l4id_t shmid, void *shmaddr, int shmflg) { struct shm_descriptor *shm_desc, *n; - int err; list_for_each_entry_safe(shm_desc, n, &shm_desc_list, list) { if (shm_desc->shmid == shmid) { - if ((err = do_shmat(shm_desc, shmaddr, - shmflg, requester) < 0)) { - l4_ipc_return(err); - return 0; - } else - break; + shmaddr = do_shmat(shm_desc, shmaddr, + shmflg, requester); + l4_ipc_return((int)shmaddr); + return 0; } } - l4_ipc_return(0); - + l4_ipc_return(-EINVAL); return 0; } @@ -158,42 +158,48 @@ int sys_shmdt(l4id_t requester, const void *shmaddr) return 0; } -static struct shm_descriptor *shm_new(key_t key) +static struct shm_descriptor *shm_new(key_t key, unsigned long npages) { /* It doesn't exist, so create a new one */ struct shm_descriptor *shm_desc; if ((shm_desc = kzalloc(sizeof(struct shm_descriptor))) < 0) return 0; - if ((shm_desc->shmid = id_new(shm_ids)) < 0) + if ((shm_desc->shmid = id_new(shm_ids)) < 0) { + kfree(shm_desc); return 0; - + } + BUG_ON(!npages); shm_desc->key = (int)key; + shm_desc->size = npages; INIT_LIST_HEAD(&shm_desc->list); list_add(&shm_desc->list, &shm_desc_list); + return shm_desc; } int sys_shmget(key_t key, int size, int shmflg) { struct shm_descriptor *shm_desc; + unsigned long npages; /* First check argument validity */ if (size > SHM_SHMMAX || size < SHM_SHMMIN) { l4_ipc_return(-EINVAL); return 0; - } + } else + npages = __pfn(page_align_up(size)); /* * IPC_PRIVATE means create a no-key shm area, i.e. private to this - * process so that it would only share it with its descendants. + * process so that it would only share it with its forked children. */ if (key == IPC_PRIVATE) { key = -1; /* Our meaning of no key */ - if (!shm_new(key)) + if (!(shm_desc = shm_new(key, npages))) l4_ipc_return(-ENOSPC); else - l4_ipc_return(0); + l4_ipc_return(shm_desc->shmid); return 0; } @@ -214,9 +220,10 @@ int sys_shmget(key_t key, int size, int shmflg) return 0; } } - /* Key doesn't exist and create set, so we create */ + + /* Key doesn't exist and create is set, so we create */ if (shmflg & IPC_CREAT) - if (!(shm_desc = shm_new(key))) + if (!(shm_desc = shm_new(key, npages))) l4_ipc_return(-ENOSPC); else l4_ipc_return(shm_desc->shmid);