Changeset c98e6ee in mainline for kernel/generic/src


Ignore:
Timestamp:
2008-07-08T16:05:45Z (17 years ago)
Author:
Jiri Svoboda <jirik.svoboda@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f93f168
Parents:
b7f9087
Message:

Merge program-loader related stuff from dynload branch to trunk. (huge)

Location:
kernel/generic/src
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/lib/elf.c

    rb7f9087 rc98e6ee  
    5858
    5959static int segment_header(elf_segment_header_t *entry, elf_header_t *elf,
    60     as_t *as);
     60    as_t *as, int flags);
    6161static int section_header(elf_section_header_t *entry, elf_header_t *elf,
    6262    as_t *as);
     
    6868 * @param header Pointer to ELF header in memory
    6969 * @param as Created and properly mapped address space
     70 * @param flags A combination of ELD_F_*
    7071 * @return EE_OK on success
    7172 */
    72 unsigned int elf_load(elf_header_t *header, as_t * as)
     73unsigned int elf_load(elf_header_t *header, as_t * as, int flags)
    7374{
    7475        int i, rc;
     
    111112                seghdr = &((elf_segment_header_t *)(((uint8_t *) header) +
    112113                    header->e_phoff))[i];
    113                 rc = segment_header(seghdr, header, as);
     114                rc = segment_header(seghdr, header, as, flags);
    114115                if (rc != EE_OK)
    115116                        return rc;
     
    152153 */
    153154static int segment_header(elf_segment_header_t *entry, elf_header_t *elf,
    154     as_t *as)
    155 {
     155    as_t *as, int flags)
     156{
     157        char *interp;
     158
    156159        switch (entry->p_type) {
    157160        case PT_NULL:
     
    163166        case PT_DYNAMIC:
    164167        case PT_INTERP:
     168                interp = (char *)elf + entry->p_offset;
     169                /* FIXME */
     170                /*if (memcmp((uintptr_t)interp, (uintptr_t)ELF_INTERP_ZSTR,
     171                    ELF_INTERP_ZLEN) != 0) {
     172                        return EE_UNSUPPORTED;
     173                }*/
     174                if ((flags & ELD_F_LOADER) == 0) {
     175                        return EE_LOADER;
     176                }
     177                break;
    165178        case PT_SHLIB:
    166179        case PT_NOTE:
  • kernel/generic/src/main/kinit.c

    rb7f9087 rc98e6ee  
    4848#include <proc/task.h>
    4949#include <proc/thread.h>
     50#include <proc/program.h>
    5051#include <panic.h>
    5152#include <func.h>
     
    160161         */
    161162        count_t i;
    162         thread_t *threads[CONFIG_INIT_TASKS];
     163        program_t programs[CONFIG_INIT_TASKS];
    163164       
    164165        for (i = 0; i < init.cnt; i++) {
     
    168169                }
    169170
    170                 threads[i] = thread_create_program((void *) init.tasks[i].addr,
    171                     "uspace");
    172                
    173                 if (threads[i] != NULL) {
     171                int rc = program_create_from_image((void *) init.tasks[i].addr,
     172                    &programs[i]);
     173
     174                if (rc == 0 && programs[i].task != NULL) {
    174175                        /*
    175176                         * Set capabilities to init userspace tasks.
    176177                         */
    177                         cap_set(threads[i]->task, CAP_CAP | CAP_MEM_MANAGER |
     178                        cap_set(programs[i].task, CAP_CAP | CAP_MEM_MANAGER |
    178179                            CAP_IO_MANAGER | CAP_PREEMPT_CONTROL | CAP_IRQ_REG);
     180
    179181                       
    180182                        if (!ipc_phone_0)
    181                                 ipc_phone_0 = &threads[i]->task->answerbox;
     183                                ipc_phone_0 = &programs[i].task->answerbox;
     184                } else if (rc == 0) {
     185                        /* It was the program loader and was registered */
    182186                } else {
     187                        /* RAM disk image */
    183188                        int rd = init_rd((rd_header_t *) init.tasks[i].addr,
    184189                            init.tasks[i].size);
     
    194199         */
    195200        for (i = 0; i < init.cnt; i++) {
    196                 if (threads[i] != NULL) {
     201                if (programs[i].task != NULL) {
    197202                        thread_usleep(50000);
    198                         thread_ready(threads[i]);
     203                        program_ready(&programs[i]);
    199204                }
    200205        }
  • kernel/generic/src/mm/as.c

    rb7f9087 rc98e6ee  
    772772}
    773773
     774/** Change adress area flags.
     775 *
     776 * The idea is to have the same data, but with a different access mode.
     777 * This is needed e.g. for writing code into memory and then executing it.
     778 * In order for this to work properly, this may copy the data
     779 * into private anonymous memory (unless it's already there).
     780 *
     781 * @param as Address space.
     782 * @param flags Flags of the area memory.
     783 * @param address Address withing the area to be changed.
     784 *
     785 * @return Zero on success or a value from @ref errno.h on failure.
     786 */
     787int as_area_change_flags(as_t *as, int flags, uintptr_t address)
     788{
     789        as_area_t *area;
     790        uintptr_t base;
     791        link_t *cur;
     792        ipl_t ipl;
     793        int page_flags;
     794        uintptr_t *old_frame;
     795        index_t frame_idx;
     796        count_t used_pages;
     797
     798        /* Flags for the new memory mapping */
     799        page_flags = area_flags_to_page_flags(flags);
     800
     801        ipl = interrupts_disable();
     802        mutex_lock(&as->lock);
     803
     804        area = find_area_and_lock(as, address);
     805        if (!area) {
     806                mutex_unlock(&as->lock);
     807                interrupts_restore(ipl);
     808                return ENOENT;
     809        }
     810
     811        if (area->sh_info || area->backend != &anon_backend) {
     812                /* Copying shared areas not supported yet */
     813                /* Copying non-anonymous memory not supported yet */
     814                mutex_unlock(&area->lock);
     815                mutex_unlock(&as->lock);
     816                interrupts_restore(ipl);
     817                return ENOTSUP;
     818        }
     819
     820        base = area->base;
     821
     822        /*
     823         * Compute total number of used pages in the used_space B+tree
     824         */
     825        used_pages = 0;
     826
     827        for (cur = area->used_space.leaf_head.next;
     828            cur != &area->used_space.leaf_head; cur = cur->next) {
     829                btree_node_t *node;
     830                unsigned int i;
     831               
     832                node = list_get_instance(cur, btree_node_t, leaf_link);
     833                for (i = 0; i < node->keys; i++) {
     834                        used_pages += (count_t) node->value[i];
     835                }
     836        }
     837
     838        /* An array for storing frame numbers */
     839        old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
     840
     841        /*
     842         * Start TLB shootdown sequence.
     843         */
     844        tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
     845
     846        /*
     847         * Remove used pages from page tables and remember their frame
     848         * numbers.
     849         */
     850        frame_idx = 0;
     851
     852        for (cur = area->used_space.leaf_head.next;
     853            cur != &area->used_space.leaf_head; cur = cur->next) {
     854                btree_node_t *node;
     855                unsigned int i;
     856               
     857                node = list_get_instance(cur, btree_node_t, leaf_link);
     858                for (i = 0; i < node->keys; i++) {
     859                        uintptr_t b = node->key[i];
     860                        count_t j;
     861                        pte_t *pte;
     862                       
     863                        for (j = 0; j < (count_t) node->value[i]; j++) {
     864                                page_table_lock(as, false);
     865                                pte = page_mapping_find(as, b + j * PAGE_SIZE);
     866                                ASSERT(pte && PTE_VALID(pte) &&
     867                                    PTE_PRESENT(pte));
     868                                old_frame[frame_idx++] = PTE_GET_FRAME(pte);
     869
     870                                /* Remove old mapping */
     871                                page_mapping_remove(as, b + j * PAGE_SIZE);
     872                                page_table_unlock(as, false);
     873                        }
     874                }
     875        }
     876
     877        /*
     878         * Finish TLB shootdown sequence.
     879         */
     880
     881        tlb_invalidate_pages(as->asid, area->base, area->pages);
     882        /*
     883         * Invalidate potential software translation caches (e.g. TSB on
     884         * sparc64).
     885         */
     886        as_invalidate_translation_cache(as, area->base, area->pages);
     887        tlb_shootdown_finalize();
     888
     889        /*
     890         * Map pages back in with new flags. This step is kept separate
     891         * so that there's no instant when the memory area could be
     892         * accesed with both the old and the new flags at once.
     893         */
     894        frame_idx = 0;
     895
     896        for (cur = area->used_space.leaf_head.next;
     897            cur != &area->used_space.leaf_head; cur = cur->next) {
     898                btree_node_t *node;
     899                unsigned int i;
     900               
     901                node = list_get_instance(cur, btree_node_t, leaf_link);
     902                for (i = 0; i < node->keys; i++) {
     903                        uintptr_t b = node->key[i];
     904                        count_t j;
     905                       
     906                        for (j = 0; j < (count_t) node->value[i]; j++) {
     907                                page_table_lock(as, false);
     908
     909                                /* Insert the new mapping */
     910                                page_mapping_insert(as, b + j * PAGE_SIZE,
     911                                    old_frame[frame_idx++], page_flags);
     912
     913                                page_table_unlock(as, false);
     914                        }
     915                }
     916        }
     917
     918        free(old_frame);
     919
     920        mutex_unlock(&area->lock);
     921        mutex_unlock(&as->lock);
     922        interrupts_restore(ipl);
     923
     924        return 0;
     925}
     926
     927
    774928/** Handle page fault within the current address space.
    775929 *
     
    17671921}
    17681922
     1923/** Wrapper for as_area_change_flags(). */
     1924unative_t sys_as_area_change_flags(uintptr_t address, int flags)
     1925{
     1926        return (unative_t) as_area_change_flags(AS, flags, address);
     1927}
     1928
    17691929/** Wrapper for as_area_destroy(). */
    17701930unative_t sys_as_area_destroy(uintptr_t address)
  • kernel/generic/src/proc/task.c

    rb7f9087 rc98e6ee  
    3636 */
    3737
    38 #include <main/uinit.h>
    3938#include <proc/thread.h>
    4039#include <proc/task.h>
    41 #include <proc/uarg.h>
    4240#include <mm/as.h>
    4341#include <mm/slab.h>
     
    4745#include <arch.h>
    4846#include <arch/barrier.h>
    49 #include <panic.h>
    5047#include <adt/avl.h>
    5148#include <adt/btree.h>
    5249#include <adt/list.h>
    5350#include <ipc/ipc.h>
    54 #include <security/cap.h>
    55 #include <memstr.h>
     51#include <ipc/ipcrsc.h>
    5652#include <print.h>
    57 #include <lib/elf.h>
    5853#include <errno.h>
    5954#include <func.h>
    6055#include <syscall/copy.h>
    61 
    62 #ifndef LOADED_PROG_STACK_PAGES_NO
    63 #define LOADED_PROG_STACK_PAGES_NO 1
    64 #endif
    6556
    6657/** Spinlock protecting the tasks_tree AVL tree. */
     
    252243}
    253244
    254 unative_t sys_task_spawn(void *image, size_t size)
    255 {
    256         void *kimage = malloc(size, 0);
    257         if (kimage == NULL)
    258                 return ENOMEM;
    259        
    260         int rc = copy_from_uspace(kimage, image, size);
    261         if (rc != EOK)
    262                 return rc;
    263 
    264         /*
    265          * Not very efficient and it would be better to call it on code only,
    266          * but this whole function is a temporary hack anyway and one day it
    267          * will go in favor of the userspace dynamic loader.
    268          */
    269         smc_coherence_block(kimage, size);
    270        
    271         uspace_arg_t *kernel_uarg;
    272         kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
    273         if (kernel_uarg == NULL) {
    274                 free(kimage);
    275                 return ENOMEM;
    276         }
    277        
    278         kernel_uarg->uspace_entry =
    279             (void *) ((elf_header_t *) kimage)->e_entry;
    280         kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS;
    281         kernel_uarg->uspace_thread_function = NULL;
    282         kernel_uarg->uspace_thread_arg = NULL;
    283         kernel_uarg->uspace_uarg = NULL;
    284        
    285         as_t *as = as_create(0);
    286         if (as == NULL) {
    287                 free(kernel_uarg);
    288                 free(kimage);
    289                 return ENOMEM;
    290         }
    291        
    292         unsigned int erc = elf_load((elf_header_t *) kimage, as);
    293         if (erc != EE_OK) {
    294                 as_destroy(as);
    295                 free(kernel_uarg);
    296                 free(kimage);
    297                 return ENOENT;
    298         }
    299        
    300         as_area_t *area = as_area_create(as,
    301             AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
    302             LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS,
    303             AS_AREA_ATTR_NONE, &anon_backend, NULL);
    304         if (area == NULL) {
    305                 as_destroy(as);
    306                 free(kernel_uarg);
    307                 free(kimage);
    308                 return ENOMEM;
    309         }
    310        
    311         task_t *task = task_create(as, "app");
    312         if (task == NULL) {
    313                 as_destroy(as);
    314                 free(kernel_uarg);
    315                 free(kimage);
    316                 return ENOENT;
    317         }
    318        
    319         // FIXME: control the capabilities
    320         cap_set(task, cap_get(TASK));
    321        
    322         thread_t *thread = thread_create(uinit, kernel_uarg, task,
    323             THREAD_FLAG_USPACE, "user", false);
    324         if (thread == NULL) {
    325                 task_destroy(task);
    326                 as_destroy(as);
    327                 free(kernel_uarg);
    328                 free(kimage);
    329                 return ENOENT;
    330         }
    331        
    332         thread_ready(thread);
    333        
    334         return EOK;
    335 }
    336 
    337245/** Find task structure corresponding to task ID.
    338246 *
  • kernel/generic/src/proc/thread.c

    rb7f9087 rc98e6ee  
    673673}
    674674
    675 
    676 /** Create new user task with 1 thread from image
    677  *
    678  * @param program_addr Address of program executable image.
    679  * @param name Program name.
    680  *
    681  * @return Initialized main thread of the task or NULL on error.
    682  */
    683 thread_t *thread_create_program(void *program_addr, char *name)
    684 {
    685         as_t *as;
    686         as_area_t *area;
    687         unsigned int rc;
    688         task_t *task;
    689         uspace_arg_t *kernel_uarg;
    690        
    691         kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
    692         if (kernel_uarg == NULL)
    693                 return NULL;
    694        
    695         kernel_uarg->uspace_entry =
    696             (void *) ((elf_header_t *) program_addr)->e_entry;
    697         kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS;
    698         kernel_uarg->uspace_thread_function = NULL;
    699         kernel_uarg->uspace_thread_arg = NULL;
    700         kernel_uarg->uspace_uarg = NULL;
    701 
    702         as = as_create(0);
    703         if (as == NULL) {
    704                 free(kernel_uarg);
    705                 return NULL;
    706         }
    707 
    708         rc = elf_load((elf_header_t *) program_addr, as);
    709         if (rc != EE_OK) {
    710                 free(kernel_uarg);
    711                 as_destroy(as);
    712                 return NULL;
    713         }
    714        
    715         /*
    716          * Create the data as_area.
    717          */
    718         area = as_area_create(as,
    719                 AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
    720                 LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS,
    721                 AS_AREA_ATTR_NONE, &anon_backend, NULL);
    722         if (area == NULL) {
    723                 free(kernel_uarg);
    724                 as_destroy(as);
    725                 return NULL;
    726         }
    727        
    728         task = task_create(as, name);
    729         if (task == NULL) {
    730                 free(kernel_uarg);
    731                 as_destroy(as);
    732                 return NULL;
    733         }
    734        
    735         /*
    736          * Create the main thread.
    737          */
    738         return thread_create(uinit, kernel_uarg, task, THREAD_FLAG_USPACE,
    739             "uinit", false);
    740 }
    741 
    742 
    743675/** Update accounting of current thread.
    744676 *
  • kernel/generic/src/syscall/syscall.c

    rb7f9087 rc98e6ee  
    3939#include <proc/thread.h>
    4040#include <proc/task.h>
     41#include <proc/program.h>
    4142#include <mm/as.h>
    4243#include <print.h>
     
    4748#include <ipc/sysipc.h>
    4849#include <synch/futex.h>
     50#include <synch/smc.h>
    4951#include <ddi/ddi.h>
    5052#include <security/cap.h>
     
    124126       
    125127        (syshandler_t) sys_task_get_id,
    126         (syshandler_t) sys_task_spawn,
     128        (syshandler_t) sys_program_spawn_loader,
    127129       
    128130        /* Synchronization related syscalls. */
    129131        (syshandler_t) sys_futex_sleep_timeout,
    130132        (syshandler_t) sys_futex_wakeup,
     133        (syshandler_t) sys_smc_coherence,
    131134       
    132135        /* Address space related syscalls. */
    133136        (syshandler_t) sys_as_area_create,
    134137        (syshandler_t) sys_as_area_resize,
     138        (syshandler_t) sys_as_area_change_flags,
    135139        (syshandler_t) sys_as_area_destroy,
    136140       
Note: See TracChangeset for help on using the changeset viewer.