Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/amd64/src/ddi/ddi.c

    r6eeb4a3 r9d58539  
    4242#include <errno.h>
    4343#include <arch/cpu.h>
    44 #include <cpu.h>
    4544#include <arch.h>
    4645#include <align.h>
     46
     47/** Enable I/O space range for task.
     48 *
     49 * Interrupts are disabled and task is locked.
     50 *
     51 * @param task   Task.
     52 * @param ioaddr Startign I/O space address.
     53 * @param size   Size of the enabled I/O range.
     54 *
     55 * @return 0 on success or an error code from errno.h.
     56 *
     57 */
     58int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size)
     59{
     60        size_t bits = ioaddr + size;
     61        if (bits > IO_PORTS)
     62                return ENOENT;
     63       
     64        if (task->arch.iomap.bits < bits) {
     65                /*
     66                 * The I/O permission bitmap is too small and needs to be grown.
     67                 */
     68               
     69                uint8_t *newmap = (uint8_t *) malloc(BITS2BYTES(bits), FRAME_ATOMIC);
     70                if (!newmap)
     71                        return ENOMEM;
     72               
     73                bitmap_t oldiomap;
     74                bitmap_initialize(&oldiomap, task->arch.iomap.map,
     75                    task->arch.iomap.bits);
     76                bitmap_initialize(&task->arch.iomap, newmap, bits);
     77               
     78                /*
     79                 * Mark the new range inaccessible.
     80                 */
     81                bitmap_set_range(&task->arch.iomap, oldiomap.bits,
     82                    bits - oldiomap.bits);
     83               
     84                /*
     85                 * In case there really existed smaller iomap,
     86                 * copy its contents and deallocate it.
     87                 */
     88                if (oldiomap.bits) {
     89                        bitmap_copy(&task->arch.iomap, &oldiomap,
     90                            oldiomap.bits);
     91                        free(oldiomap.map);
     92                }
     93        }
     94       
     95        /*
     96         * Enable the range and we are done.
     97         */
     98        bitmap_clear_range(&task->arch.iomap, (size_t) ioaddr, (size_t) size);
     99       
     100        /*
     101         * Increment I/O Permission bitmap generation counter.
     102         */
     103        task->arch.iomapver++;
     104       
     105        return 0;
     106}
    47107
    48108/** Install I/O Permission bitmap.
     
    58118        /* First, copy the I/O Permission Bitmap. */
    59119        irq_spinlock_lock(&TASK->lock, false);
    60        
    61120        size_t ver = TASK->arch.iomapver;
    62         size_t elements = TASK->arch.iomap.elements;
    63        
    64         if (elements > 0) {
    65                 ASSERT(TASK->arch.iomap.bits);
     121        size_t bits = TASK->arch.iomap.bits;
     122        if (bits) {
     123                ASSERT(TASK->arch.iomap.map);
    66124               
    67125                bitmap_t iomap;
    68                 bitmap_initialize(&iomap, TSS_IOMAP_SIZE * 8,
    69                     CPU->arch.tss->iomap);
    70                 bitmap_copy(&iomap, &TASK->arch.iomap, elements);
     126                bitmap_initialize(&iomap, CPU->arch.tss->iomap,
     127                    TSS_IOMAP_SIZE * 8);
     128                bitmap_copy(&iomap, &TASK->arch.iomap, bits);
    71129               
    72130                /*
     
    74132                 * I/O access.
    75133                 */
    76                 bitmap_set_range(&iomap, elements,
    77                     ALIGN_UP(elements, 8) - elements);
    78                
     134                bitmap_set_range(&iomap, bits, ALIGN_UP(bits, 8) - bits);
    79135                /*
    80136                 * It is safe to set the trailing eight bits because of the
    81137                 * extra convenience byte in TSS_IOMAP_SIZE.
    82138                 */
    83                 bitmap_set_range(&iomap, ALIGN_UP(elements, 8), 8);
     139                bitmap_set_range(&iomap, ALIGN_UP(bits, 8), 8);
    84140        }
    85        
    86141        irq_spinlock_unlock(&TASK->lock, false);
    87142       
    88143        /*
    89144         * Second, adjust TSS segment limit.
    90          * Take the extra ending byte with all bits set into account.
     145         * Take the extra ending byte will all bits set into account.
    91146         */
    92147        ptr_16_64_t cpugdtr;
     
    94149       
    95150        descriptor_t *gdt_p = (descriptor_t *) cpugdtr.base;
    96         size_t size = bitmap_size(elements);
    97         gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + size);
     151        gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + BITS2BYTES(bits));
    98152        gdtr_load(&cpugdtr);
    99153       
Note: See TracChangeset for help on using the changeset viewer.