Subversion Repositories HelenOS

Rev

Rev 1191 | Rev 1227 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (C) 2006 Jakub Jermar
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. #include <ddi/ddi.h>
  30. #include <ddi/ddi_arg.h>
  31. #include <proc/task.h>
  32. #include <security/cap.h>
  33. #include <mm/frame.h>
  34. #include <mm/page.h>
  35. #include <mm/as.h>
  36. #include <synch/spinlock.h>
  37. #include <arch.h>
  38. #include <align.h>
  39. #include <errno.h>
  40.  
  41. /** Map piece of physical memory into virtual address space of specified task.
  42.  *
  43.  * @param id Task ID of the destination task.
  44.  * @param pf Physical frame address of the starting frame.
  45.  * @param vp Virtual page address of the starting page.
  46.  * @param pages Number of pages to map.
  47.  * @param writable If true, the mapping will be created writable.
  48.  *
  49.  * @return 0 on success, EPERM if the caller lacks capabilities to use this syscall,
  50.  *     ENOENT if there is no task matching the specified ID and ENOMEM if
  51.  *     there was a problem in creating address space area.
  52.  */
  53. static int ddi_map_physmem(task_id_t id, __address pf, __address vp, count_t pages, bool writable)
  54. {
  55.     ipl_t ipl;
  56.     cap_t caps;
  57.     task_t *t;
  58.     int flags;
  59.     count_t i;
  60.    
  61.     /*
  62.      * Make sure the caller is authorised to make this syscall.
  63.      */
  64.     caps = cap_get(TASK);
  65.     if (!(caps & CAP_MEM_MANAGER))
  66.         return EPERM;
  67.    
  68.     ipl = interrupts_disable();
  69.     spinlock_lock(&tasks_lock);
  70.    
  71.     t = task_find_by_id(id);
  72.    
  73.     if (!t) {
  74.         /*
  75.          * There is no task with the specified ID.
  76.          */
  77.         spinlock_unlock(&tasks_lock);
  78.         interrupts_restore(ipl);
  79.         return ENOENT;
  80.     }
  81.  
  82.     /*
  83.      * TODO: We are currently lacking support for task destroying.
  84.      * Once it is added to the kernel, we must take care to
  85.      * synchronize in a way that prevents race conditions here.
  86.      */
  87.    
  88.     /* Lock the task and release the lock protecting tasks_btree. */
  89.     spinlock_lock(&t->lock);
  90.     spinlock_unlock(&tasks_lock);
  91.    
  92.     flags = AS_AREA_DEVICE | AS_AREA_READ;
  93.     if (writable)
  94.         flags |= AS_AREA_WRITE;
  95.     if (!as_area_create(t->as, flags, pages * PAGE_SIZE, vp)) {
  96.         /*
  97.          * The address space area could not have been created.
  98.          * We report it using ENOMEM.
  99.          */
  100.         spinlock_unlock(&t->lock);
  101.         interrupts_restore(ipl);
  102.         return ENOMEM;
  103.     }
  104.    
  105.     /* Initialize page tables. */
  106.     for (i = 0; i < pages; i++)
  107.         as_set_mapping(t->as, vp + i * PAGE_SIZE, pf + i * FRAME_SIZE);
  108.  
  109.     spinlock_unlock(&t->lock);
  110.     interrupts_restore(ipl);
  111.     return 0;
  112. }
  113.  
  114. /** Enable range of I/O space for task.
  115.  *
  116.  * @param id Task ID of the destination task.
  117.  * @param ioaddr Starting I/O address.
  118.  * @param size Size of the enabled I/O space..
  119.  *
  120.  * @return 0 on success, EPERM if the caller lacks capabilities to use this syscall,
  121.  *     ENOENT if there is no task matching the specified ID.
  122.  */
  123. static int ddi_enable_iospace(task_id_t id, __address ioaddr, size_t size)
  124. {
  125.     ipl_t ipl;
  126.     cap_t caps;
  127.     task_t *t;
  128.     int rc;
  129.    
  130.     /*
  131.      * Make sure the caller is authorised to make this syscall.
  132.      */
  133.     caps = cap_get(TASK);
  134.     if (!(caps & CAP_IO_MANAGER))
  135.         return EPERM;
  136.    
  137.     ipl = interrupts_disable();
  138.     spinlock_lock(&tasks_lock);
  139.    
  140.     t = task_find_by_id(id);
  141.    
  142.     if (!t) {
  143.         /*
  144.          * There is no task with the specified ID.
  145.          */
  146.         spinlock_unlock(&tasks_lock);
  147.         interrupts_restore(ipl);
  148.         return ENOENT;
  149.     }
  150.  
  151.     /*
  152.      * TODO: We are currently lacking support for task destroying.
  153.      * Once it is added to the kernel, we must take care to
  154.      * synchronize in a way that prevents race conditions here.
  155.      */
  156.    
  157.     /* Lock the task and release the lock protecting tasks_btree. */
  158.     spinlock_lock(&t->lock);
  159.     spinlock_unlock(&tasks_lock);
  160.  
  161.     rc = ddi_enable_iospace_arch(t, ioaddr, size);
  162.    
  163.     spinlock_unlock(&t->lock);
  164.     interrupts_restore(ipl);
  165.     return rc;
  166. }
  167.  
  168. /** Wrapper for SYS_MAP_PHYSMEM syscall.
  169.  *
  170.  * @param User space address of memory DDI argument structure.
  171.  *
  172.  * @return 0 on success, otherwise it returns error code found in errno.h
  173.  */
  174. __native sys_map_physmem(ddi_memarg_t *uspace_mem_arg)
  175. {
  176.     ddi_memarg_t arg;
  177.    
  178.     copy_from_uspace(&arg, uspace_mem_arg, sizeof(ddi_memarg_t));
  179.     return (__native) ddi_map_physmem((task_id_t) arg.task_id, ALIGN_DOWN((__address) arg.phys_base, FRAME_SIZE),
  180.                       ALIGN_DOWN((__address) arg.virt_base, PAGE_SIZE), (count_t) arg.pages,
  181.                       (bool) arg.writable);
  182. }
  183.  
  184. /** Wrapper for SYS_ENABLE_IOSPACE syscall.
  185.  *
  186.  * @param User space address of DDI argument structure.
  187.  *
  188.  * @return 0 on success, otherwise it returns error code found in errno.h
  189.  */
  190. __native sys_enable_iospace(ddi_ioarg_t *uspace_io_arg)
  191. {
  192.     ddi_ioarg_t arg;
  193.    
  194.     copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t));
  195.     return (__native) ddi_enable_iospace((task_id_t) arg.task_id, (__address) arg.ioaddr, (size_t) arg.size);
  196. }
  197.  
  198. __native ddi_int_control(__native enable, __native *flags)
  199. {
  200.     if (! cap_get(TASK) & CAP_INT_CONTROL)
  201.         return EPERM;
  202.     return ddi_int_control_arch(enable, flags);
  203. }
  204.  
  205.