Changeset 7c23af9 in mainline


Ignore:
Timestamp:
2006-05-14T17:16:52Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
14b502e2
Parents:
68965ec5
Message:

Added support to IPC for simple page sharing.

Location:
generic
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • generic/include/ipc/ipc.h

    r68965ec5 r7c23af9  
    123123/** Interrupt notification */
    124124#define IPC_M_INTERRUPT         4
     125/** Send as_area over ipc
     126 * - ARG2 - src base address
     127 * - ARG3 - size of src as(filled automatically by kernel)
     128 * - on answer ARG1 - dst base adress
     129 */
     130#define IPC_M_AS_SEND           5
    125131
    126132
  • generic/include/mm/as.h

    r68965ec5 r7c23af9  
    3030#define __AS_H__
    3131
     32/** Address space area flags. */
     33#define AS_AREA_READ    1
     34#define AS_AREA_WRITE   2
     35#define AS_AREA_EXEC    4
     36#define AS_AREA_DEVICE  8
     37
     38
     39#ifdef KERNEL
     40
    3241#include <mm/as_arg.h>
    3342#include <arch/mm/page.h>
     
    5463#define FLAG_AS_KERNEL      (1 << 0)    /**< Kernel address space. */
    5564
    56 /** Address space area flags. */
    57 #define AS_AREA_READ    1
    58 #define AS_AREA_WRITE   2
    59 #define AS_AREA_EXEC    4
    60 #define AS_AREA_DEVICE  8
    6165
    6266/** Address space area attributes. */
     
    130134extern void as_switch(as_t *old, as_t *new);
    131135extern void as_free(as_t *as);
     136int as_area_steal(task_t *src_task, __address src_base, size_t acc_size, __address dst_base);
     137extern size_t as_get_size(__address base);
    132138
    133139/* Interface to be implemented by architectures. */
     
    140146extern __native sys_as_area_resize(__address address, size_t size, int flags);
    141147extern __native sys_as_area_destroy(__address address);
    142 extern __native sys_as_area_accept(as_area_acptsnd_arg_t *uspace_accept_arg);
    143 extern __native sys_as_area_send(as_area_acptsnd_arg_t *uspace_send_arg);
     148
     149#endif /* KERNEL */
    144150
    145151#endif
  • generic/include/syscall/syscall.h

    r68965ec5 r7c23af9  
    4141        SYS_AS_AREA_RESIZE,
    4242        SYS_AS_AREA_DESTROY,
    43         SYS_AS_AREA_ACCEPT,
    44         SYS_AS_AREA_SEND,
    4543        SYS_IPC_CALL_SYNC_FAST,
    4644        SYS_IPC_CALL_SYNC,
  • generic/src/ipc/sysipc.c

    r68965ec5 r7c23af9  
    4141#include <syscall/copy.h>
    4242#include <security/cap.h>
     43#include <mm/as.h>
    4344
    4445#define GET_CHECK_PHONE(phone,phoneid,err) { \
     
    8384        if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_ME_TO)
    8485                return 1;
     86        if (IPC_GET_METHOD(call->data) == IPC_M_AS_SEND)
     87                return 1;
    8588        return 0;
    8689}
    8790
    8891/** Interpret process answer as control information */
    89 static inline void answer_preprocess(call_t *answer, ipc_data_t *olddata)
     92static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata)
    9093{
    9194        int phoneid;
     
    106109
    107110        if (!olddata)
    108                 return;
     111                return 0;
    109112
    110113        if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
     
    125128                                          &TASK->answerbox);
    126129                }
    127         }
     130        } else if (IPC_GET_METHOD(*olddata) == IPC_M_AS_SEND) {
     131                if (!IPC_GET_RETVAL(answer->data)) { /* Accepted, handle As_area receival */
     132                        return as_area_steal(answer->sender,
     133                                             IPC_GET_ARG2(*olddata),IPC_GET_ARG3(*olddata),
     134                                             IPC_GET_ARG1(answer->data));
     135                }
     136        }
     137        return 0;
    128138}
    129139
     
    135145{
    136146        int newphid;
     147        size_t size;
    137148
    138149        switch (IPC_GET_METHOD(call->data)) {
     
    146157                call->private = newphid;
    147158                break;
     159        case IPC_M_AS_SEND:
     160                size = as_get_size(IPC_GET_ARG2(call->data));
     161                if (!size) {
     162                        return EPERM;
     163                }
     164                IPC_SET_ARG3(call->data, size);
     165                break;
    148166        default:
    149167                break;
     
    377395        ipc_data_t saved_data;
    378396        int saveddata = 0;
     397        int rc;
    379398
    380399        call = get_call(callid);
     
    390409        IPC_SET_ARG1(call->data, arg1);
    391410        IPC_SET_ARG2(call->data, arg2);
    392         answer_preprocess(call, saveddata ? &saved_data : NULL);
     411        rc = answer_preprocess(call, saveddata ? &saved_data : NULL);
    393412
    394413        ipc_answer(&TASK->answerbox, call);
    395         return 0;
     414        return rc;
    396415}
    397416
     
    417436                return rc;
    418437
    419         answer_preprocess(call, saveddata ? &saved_data : NULL);
     438        rc = answer_preprocess(call, saveddata ? &saved_data : NULL);
    420439       
    421440        ipc_answer(&TASK->answerbox, call);
    422441
    423         return 0;
     442        return rc;
    424443}
    425444
  • generic/src/mm/as.c

    r68965ec5 r7c23af9  
    365365}
    366366
    367 /** Send address space area to another task.
    368  *
    369  * Address space area is sent to the specified task.
    370  * If the destination task is willing to accept the
    371  * area, a new area is created according to the
    372  * source area. Moreover, any existing mapping
     367/** Steal address space area from another task.
     368 *
     369 * Address space area is stolen from another task
     370 * Moreover, any existing mapping
    373371 * is copied as well, providing thus a mechanism
    374372 * for sharing group of pages. The source address
    375373 * space area and any associated mapping is preserved.
    376374 *
    377  * @param dst_id Task ID of the accepting task.
     375 * @param src_task Pointer of source task
    378376 * @param src_base Base address of the source address space area.
     377 * @param acc_size Expected size of the source area
     378 * @param dst_base Target base address
    379379 *
    380380 * @return Zero on success or ENOENT if there is no such task or
     
    384384 *         address space area.
    385385 */
    386 int as_area_send(task_id_t dst_id, __address src_base)
     386int as_area_steal(task_t *src_task, __address src_base, size_t acc_size,
     387                  __address dst_base)
    387388{
    388389        ipl_t ipl;
    389         task_t *t;
    390390        count_t i;
    391         as_t *dst_as;
    392         __address dst_base;
     391        as_t *src_as;       
    393392        int src_flags;
    394393        size_t src_size;
    395394        as_area_t *src_area, *dst_area;
    396        
     395
    397396        ipl = interrupts_disable();
    398         spinlock_lock(&tasks_lock);
    399        
    400         t = task_find_by_id(dst_id);
    401         if (!NULL) {
    402                 spinlock_unlock(&tasks_lock);
    403                 interrupts_restore(ipl);
    404                 return ENOENT;
    405         }
    406 
    407         spinlock_lock(&t->lock);
    408         spinlock_unlock(&tasks_lock);
    409 
    410         dst_as = t->as;
    411         dst_base = (__address) t->accept_arg.base;
    412        
    413         if (dst_as == AS) {
    414                 /*
    415                  * The two tasks share the entire address space.
    416                  * Return error since there is no point in continuing.
    417                  */
    418                 spinlock_unlock(&t->lock);
    419                 interrupts_restore(ipl);
    420                 return EPERM;
    421         }
    422        
    423         spinlock_lock(&AS->lock);
    424         src_area = find_area_and_lock(AS, src_base);
     397        spinlock_lock(&src_task->lock);
     398        src_as = src_task->as;
     399       
     400        spinlock_lock(&src_as->lock);
     401        src_area = find_area_and_lock(src_as, src_base);
    425402        if (!src_area) {
    426403                /*
    427404                 * Could not find the source address space area.
    428405                 */
    429                 spinlock_unlock(&t->lock);
    430                 spinlock_unlock(&AS->lock);
     406                spinlock_unlock(&src_task->lock);
     407                spinlock_unlock(&src_as->lock);
    431408                interrupts_restore(ipl);
    432409                return ENOENT;
     
    435412        src_flags = src_area->flags;
    436413        spinlock_unlock(&src_area->lock);
    437         spinlock_unlock(&AS->lock);
    438 
    439         if ((t->accept_arg.task_id != TASK->taskid) || (t->accept_arg.size != src_size) ||
    440             (t->accept_arg.flags != src_flags)) {
    441                 /*
    442                  * Discrepancy in either task ID, size or flags.
    443                  */
    444                 spinlock_unlock(&t->lock);
     414        spinlock_unlock(&src_as->lock);
     415
     416
     417        if (src_size != acc_size) {
     418                spinlock_unlock(&src_task->lock);
    445419                interrupts_restore(ipl);
    446420                return EPERM;
    447421        }
    448        
    449422        /*
    450423         * Create copy of the source address space area.
     
    453426         * preliminary as_page_fault() calls.
    454427         */
    455         dst_area = as_area_create(dst_as, src_flags, src_size, dst_base, AS_AREA_ATTR_PARTIAL);
     428        dst_area = as_area_create(AS, src_flags, src_size, dst_base, AS_AREA_ATTR_PARTIAL);
    456429        if (!dst_area) {
    457430                /*
    458431                 * Destination address space area could not be created.
    459432                 */
    460                 spinlock_unlock(&t->lock);
     433                spinlock_unlock(&src_task->lock);
    461434                interrupts_restore(ipl);
    462435                return ENOMEM;
    463436        }
    464437       
    465         memsetb((__address) &t->accept_arg, sizeof(as_area_acptsnd_arg_t), 0);
    466         spinlock_unlock(&t->lock);
     438        spinlock_unlock(&src_task->lock);
    467439       
    468440        /*
    469441         * Avoid deadlock by first locking the address space with lower address.
    470442         */
    471         if (dst_as < AS) {
    472                 spinlock_lock(&dst_as->lock);
     443        if (AS < src_as) {
    473444                spinlock_lock(&AS->lock);
     445                spinlock_lock(&src_as->lock);
    474446        } else {
    475447                spinlock_lock(&AS->lock);
    476                 spinlock_lock(&dst_as->lock);
     448                spinlock_lock(&src_as->lock);
    477449        }
    478450       
     
    481453                __address frame;
    482454                       
    483                 page_table_lock(AS, false);
    484                 pte = page_mapping_find(AS, src_base + i*PAGE_SIZE);
     455                page_table_lock(src_as, false);
     456                pte = page_mapping_find(src_as, src_base + i*PAGE_SIZE);
    485457                if (pte && PTE_VALID(pte)) {
    486458                        ASSERT(PTE_PRESENT(pte));
     
    488460                        if (!(src_flags & AS_AREA_DEVICE))
    489461                                frame_reference_add(ADDR2PFN(frame));
    490                         page_table_unlock(AS, false);
     462                        page_table_unlock(src_as, false);
    491463                } else {
    492                         page_table_unlock(AS, false);
     464                        page_table_unlock(src_as, false);
    493465                        continue;
    494466                }
    495467               
    496                 page_table_lock(dst_as, false);
    497                 page_mapping_insert(dst_as, dst_base + i*PAGE_SIZE, frame, area_flags_to_page_flags(src_flags));
    498                 page_table_unlock(dst_as, false);
     468                page_table_lock(AS, false);
     469                page_mapping_insert(AS, dst_base + i*PAGE_SIZE, frame, area_flags_to_page_flags(src_flags));
     470                page_table_unlock(AS, false);
    499471        }
    500472
     
    509481       
    510482        spinlock_unlock(&AS->lock);
    511         spinlock_unlock(&dst_as->lock);
     483        spinlock_unlock(&src_as->lock);
    512484        interrupts_restore(ipl);
    513485       
     
    946918}
    947919
     920/** Return size of address space of current task pointed to by base */
     921size_t as_get_size(__address base)
     922{
     923        ipl_t ipl;
     924        as_area_t *src_area;
     925        size_t size;
     926
     927        ipl = interrupts_disable();
     928        src_area = find_area_and_lock(AS, base);
     929        if (src_area){
     930                size = src_area->pages * PAGE_SIZE;
     931                spinlock_unlock(&src_area->lock);
     932        } else {
     933                size = 0;
     934        }
     935        interrupts_restore(ipl);
     936        return size;
     937}
     938
    948939/*
    949940 * Address space related syscalls.
     
    971962}
    972963
    973 /** Prepare task for accepting address space area from another task.
    974  *
    975  * @param uspace_accept_arg Accept structure passed from userspace.
    976  *
    977  * @return EPERM if the task ID encapsulated in @uspace_accept_arg references
    978  *         TASK. Otherwise zero is returned.
    979  */
    980 __native sys_as_area_accept(as_area_acptsnd_arg_t *uspace_accept_arg)
    981 {
    982         as_area_acptsnd_arg_t arg;
    983         int rc;
    984        
    985         rc = copy_from_uspace(&arg, uspace_accept_arg, sizeof(as_area_acptsnd_arg_t));
    986         if (rc != 0)
    987                 return rc;
    988        
    989         if (!arg.size)
    990                 return (__native) EPERM;
    991        
    992         if (arg.task_id == TASK->taskid) {
    993                 /*
    994                  * Accepting from itself is not allowed.
    995                  */
    996                 return (__native) EPERM;
    997         }
    998        
    999         memcpy(&TASK->accept_arg, &arg, sizeof(as_area_acptsnd_arg_t));
    1000        
    1001         return 0;
    1002 }
    1003 
    1004 /** Wrapper for as_area_send. */
    1005 __native sys_as_area_send(as_area_acptsnd_arg_t *uspace_send_arg)
    1006 {
    1007         as_area_acptsnd_arg_t arg;
    1008         int rc;
    1009        
    1010         rc = copy_from_uspace(&arg, uspace_send_arg, sizeof(as_area_acptsnd_arg_t));
    1011         if (rc != 0)
    1012                 return rc;
    1013 
    1014         if (!arg.size)
    1015                 return (__native) EPERM;
    1016        
    1017         if (arg.task_id == TASK->taskid) {
    1018                 /*
    1019                  * Sending to itself is not allowed.
    1020                  */
    1021                 return (__native) EPERM;
    1022         }
    1023 
    1024         return (__native) as_area_send(arg.task_id, (__address) arg.base);
    1025 }
  • generic/src/syscall/syscall.c

    r68965ec5 r7c23af9  
    8787        sys_as_area_resize,
    8888        sys_as_area_destroy,
    89         sys_as_area_accept,
    90         sys_as_area_send,
    9189
    9290        /* IPC related syscalls. */
Note: See TracChangeset for help on using the changeset viewer.