Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/ddi/ddi.c

    r2fa10f6 r953bc1ef  
    4646#include <mm/frame.h>
    4747#include <mm/as.h>
    48 #include <synch/mutex.h>
     48#include <synch/spinlock.h>
    4949#include <syscall/copy.h>
    5050#include <adt/btree.h>
     
    5252#include <align.h>
    5353#include <errno.h>
    54 #include <trace.h>
    5554
    5655/** This lock protects the parea_btree. */
    57 static mutex_t parea_lock;
     56SPINLOCK_INITIALIZE(parea_lock);
    5857
    5958/** B+tree with enabled physical memory areas. */
    6059static btree_t parea_btree;
    6160
    62 /** Initialize DDI.
    63  *
    64  */
     61/** Initialize DDI. */
    6562void ddi_init(void)
    6663{
    6764        btree_create(&parea_btree);
    68         mutex_initialize(&parea_lock, MUTEX_PASSIVE);
    6965}
    7066
     
    7672void ddi_parea_register(parea_t *parea)
    7773{
    78         mutex_lock(&parea_lock);
     74        ipl_t ipl = interrupts_disable();
     75        spinlock_lock(&parea_lock);
    7976       
    8077        /*
     
    8380        btree_insert(&parea_btree, (btree_key_t) parea->pbase, parea, NULL);
    8481       
    85         mutex_unlock(&parea_lock);
     82        spinlock_unlock(&parea_lock);
     83        interrupts_restore(ipl);
    8684}
    8785
     
    10098 *
    10199 */
    102 NO_TRACE static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, size_t pages,
    103     unsigned int flags)
     100static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, size_t pages, int flags)
    104101{
    105102        ASSERT(TASK);
     
    118115        backend_data.frames = pages;
    119116       
     117        ipl_t ipl = interrupts_disable();
     118       
    120119        /* Find the zone of the physical memory */
    121         irq_spinlock_lock(&zones.lock, true);
     120        spinlock_lock(&zones.lock);
    122121        size_t znum = find_zone(ADDR2PFN(pf), pages, 0);
    123122       
     
    126125                 * -> assume it is hardware device and allow mapping
    127126                 */
    128                 irq_spinlock_unlock(&zones.lock, true);
     127                spinlock_unlock(&zones.lock);
    129128                goto map;
    130129        }
     
    132131        if (zones.info[znum].flags & ZONE_FIRMWARE) {
    133132                /* Frames are part of firmware */
    134                 irq_spinlock_unlock(&zones.lock, true);
     133                spinlock_unlock(&zones.lock);
    135134                goto map;
    136135        }
    137136       
    138137        if (zone_flags_available(zones.info[znum].flags)) {
    139                 /*
    140                  * Frames are part of physical memory, check if the memory
     138                /* Frames are part of physical memory, check if the memory
    141139                 * region is enabled for mapping.
    142140                 */
    143                 irq_spinlock_unlock(&zones.lock, true);
     141                spinlock_unlock(&zones.lock);
    144142               
    145                 mutex_lock(&parea_lock);
     143                spinlock_lock(&parea_lock);
    146144                btree_node_t *nodep;
    147145                parea_t *parea = (parea_t *) btree_search(&parea_btree,
    148146                    (btree_key_t) pf, &nodep);
    149147               
    150                 if ((!parea) || (parea->frames < pages)) {
    151                         mutex_unlock(&parea_lock);
     148                if ((!parea) || (parea->frames < pages))
    152149                        goto err;
    153                 }
    154150               
    155                 mutex_unlock(&parea_lock);
     151                spinlock_unlock(&parea_lock);
    156152                goto map;
    157153        }
    158154       
    159         irq_spinlock_unlock(&zones.lock, true);
    160        
    161155err:
     156        spinlock_unlock(&zones.lock);
     157        interrupts_restore(ipl);
    162158        return ENOENT;
    163159       
    164160map:
     161        spinlock_lock(&TASK->lock);
     162       
    165163        if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp,
    166164            AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) {
     
    169167                 * We report it using ENOMEM.
    170168                 */
     169                spinlock_unlock(&TASK->lock);
     170                interrupts_restore(ipl);
    171171                return ENOMEM;
    172172        }
     
    175175         * Mapping is created on-demand during page fault.
    176176         */
     177       
     178        spinlock_unlock(&TASK->lock);
     179        interrupts_restore(ipl);
    177180        return 0;
    178181}
     
    188191 *
    189192 */
    190 NO_TRACE static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr,
    191     size_t size)
     193static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr, size_t size)
    192194{
    193195        /*
     
    198200                return EPERM;
    199201       
    200         irq_spinlock_lock(&tasks_lock, true);
     202        ipl_t ipl = interrupts_disable();
     203        spinlock_lock(&tasks_lock);
    201204       
    202205        task_t *task = task_find_by_id(id);
     
    208211                 * context.
    209212                 */
    210                 irq_spinlock_unlock(&tasks_lock, true);
     213                spinlock_unlock(&tasks_lock);
     214                interrupts_restore(ipl);
    211215                return ENOENT;
    212216        }
    213217       
    214218        /* Lock the task and release the lock protecting tasks_btree. */
    215         irq_spinlock_exchange(&tasks_lock, &task->lock);
     219        spinlock_lock(&task->lock);
     220        spinlock_unlock(&tasks_lock);
    216221       
    217222        int rc = ddi_iospace_enable_arch(task, ioaddr, size);
    218223       
    219         irq_spinlock_unlock(&task->lock, true);
     224        spinlock_unlock(&task->lock);
     225        interrupts_restore(ipl);
    220226       
    221227        return rc;
     
    258264}
    259265
     266/** Disable or enable preemption.
     267 *
     268 * @param enable If non-zero, the preemption counter will be decremented,
     269 *               leading to potential enabling of preemption. Otherwise
     270 *               the preemption counter will be incremented, preventing
     271 *               preemption from occurring.
     272 *
     273 * @return Zero on success or EPERM if callers capabilities are not sufficient.
     274 *
     275 */
     276unative_t sys_preempt_control(int enable)
     277{
     278        if (!(cap_get(TASK) & CAP_PREEMPT_CONTROL))
     279                return EPERM;
     280       
     281        if (enable)
     282                preemption_enable();
     283        else
     284                preemption_disable();
     285       
     286        return 0;
     287}
     288
     289/** Disable or enable specified interrupts.
     290 *
     291 * @param irq the interrupt to be enabled/disabled.
     292 * @param enable if true enable the interrupt, disable otherwise.
     293 *
     294 * @retutn Zero on success, error code otherwise.
     295 */
     296unative_t sys_interrupt_enable(int irq, int enable)
     297{       
     298        cap_t task_cap = cap_get(TASK);
     299        if (!(task_cap & CAP_PREEMPT_CONTROL) || !(task_cap & CAP_IRQ_REG))
     300                return EPERM;
     301               
     302        if (irq < 0 || irq > 16) {
     303                return EINVAL;
     304        }
     305       
     306        uint16_t irq_mask = (uint16_t)(1 << irq);
     307        if (enable) {
     308                trap_virtual_enable_irqs(irq_mask);
     309        } else {
     310                trap_virtual_disable_irqs(irq_mask);
     311        }
     312       
     313        return 0;       
     314}
     315
    260316/** @}
    261317 */
Note: See TracChangeset for help on using the changeset viewer.