Changeset f8ddd17 in mainline for kernel/generic/src/ddi/ddi.c


Ignore:
Timestamp:
2006-12-09T20:20:50Z (18 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b82a13c
Parents:
9ab9c2ec
Message:

Rework support for virtually indexed cache.
Instead of repeatedly flushing the data cache, which was a huge overkill, refuse to create an illegal address alias
in the kernel (again) and allocate appropriate page color in userspace instead. Extend the detection also to
SYS_PHYSMEM_MAP syscall.

Add support for tracking physical memory areas mappable by SYS_PHYSMEM_MAP.

Lots of coding style changes.

File:
1 edited

Legend:

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

    r9ab9c2ec rf8ddd17  
    4848#include <synch/spinlock.h>
    4949#include <syscall/copy.h>
     50#include <adt/btree.h>
    5051#include <arch.h>
    5152#include <align.h>
    5253#include <errno.h>
    5354
     55/** This lock protects the parea_btree. */
     56SPINLOCK_INITIALIZE(parea_lock);
     57
     58/** B+tree with enabled physical memory areas. */
     59static btree_t parea_btree;
     60
     61/** Initialize DDI. */
     62void ddi_init(void)
     63{
     64        btree_create(&parea_btree);
     65}
     66
     67/** Enable piece of physical memory for mapping by physmem_map().
     68 *
     69 * @param parea Pointer to physical area structure.
     70 *
     71 * @todo This function doesn't check for overlaps. It depends on the kernel to
     72 * create disjunct physical memory areas.
     73 */
     74void ddi_parea_register(parea_t *parea)
     75{
     76        ipl_t ipl;
     77
     78        ipl = interrupts_disable();
     79        spinlock_lock(&parea_lock);
     80       
     81        /*
     82         * TODO: we should really check for overlaps here.
     83         * However, we should be safe because the kernel is pretty sane and
     84         * memory of different devices doesn't overlap.
     85         */
     86        btree_insert(&parea_btree, (btree_key_t) parea->pbase, parea, NULL);
     87
     88        spinlock_unlock(&parea_lock);
     89        interrupts_restore(ipl);       
     90}
     91
    5492/** Map piece of physical memory into virtual address space of current task.
    5593 *
    56  * @param pf Physical frame address of the starting frame.
    57  * @param vp Virtual page address of the starting page.
     94 * @param pf Physical address of the starting frame.
     95 * @param vp Virtual address of the starting page.
    5896 * @param pages Number of pages to map.
    5997 * @param flags Address space area flags for the mapping.
    6098 *
    61  * @return 0 on success, EPERM if the caller lacks capabilities to use this syscall,
    62  *         ENOENT if there is no task matching the specified ID and ENOMEM if
    63  *         there was a problem in creating address space area.
     99 * @return 0 on success, EPERM if the caller lacks capabilities to use this
     100 *      syscall, ENOENT if there is no task matching the specified ID or the
     101 *      physical address space is not enabled for mapping and ENOMEM if there
     102 *      was a problem in creating address space area. ENOTSUP is returned when
     103 *      an attempt to create an illegal address alias is detected.
    64104 */
    65105static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, count_t pages, int flags)
     
    80120
    81121        ipl = interrupts_disable();
     122
     123        /*
     124         * Check if the physical memory area is enabled for mapping.
     125         * If the architecture supports virtually indexed caches, intercept
     126         * attempts to create an illegal address alias.
     127         */
     128        spinlock_lock(&parea_lock);
     129        parea_t *parea;
     130        btree_node_t *nodep;
     131        parea = btree_search(&parea_btree, (btree_key_t) pf, &nodep);
     132        if (!parea || parea->frames < pages || ((flags & AS_AREA_CACHEABLE) &&
     133                !parea->cacheable) || (!(flags & AS_AREA_CACHEABLE) &&
     134                parea->cacheable)) {
     135                /*
     136                 * This physical memory area cannot be mapped.
     137                 */
     138                spinlock_unlock(&parea_lock);
     139                interrupts_restore(ipl);
     140                return ENOENT;
     141        }
     142
     143#ifdef CONFIG_VIRT_IDX_DCACHE
     144        if (PAGE_COLOR(parea->vbase) != PAGE_COLOR(vp)) {
     145                /*
     146                 * Refuse to create an illegal address alias.
     147                 */
     148                spinlock_unlock(&parea_lock);
     149                interrupts_restore(ipl);
     150                return ENOTSUP;
     151        }
     152#endif /* CONFIG_VIRT_IDX_DCACHE */
     153
     154        spinlock_unlock(&parea_lock);
     155
    82156        spinlock_lock(&TASK->lock);
    83157       
     
    108182 * @param size Size of the enabled I/O space..
    109183 *
    110  * @return 0 on success, EPERM if the caller lacks capabilities to use this syscall,
    111  *        ENOENT if there is no task matching the specified ID.
     184 * @return 0 on success, EPERM if the caller lacks capabilities to use this
     185 *      syscall, ENOENT if there is no task matching the specified ID.
    112186 */
    113187static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr, size_t size)
     
    161235 * @return 0 on success, otherwise it returns error code found in errno.h
    162236 */
    163 unative_t sys_physmem_map(unative_t phys_base, unative_t virt_base, unative_t pages,
    164                         unative_t flags)
    165 {
    166         return (unative_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base, FRAME_SIZE),
    167                                           ALIGN_DOWN((uintptr_t) virt_base, PAGE_SIZE), (count_t) pages,
    168                                           (int) flags);
     237unative_t sys_physmem_map(unative_t phys_base, unative_t virt_base, unative_t
     238        pages, unative_t flags)
     239{
     240        return (unative_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base,
     241                FRAME_SIZE), ALIGN_DOWN((uintptr_t) virt_base, PAGE_SIZE),
     242                (count_t) pages, (int) flags);
    169243}
    170244
     
    184258                return (unative_t) rc;
    185259               
    186         return (unative_t) ddi_iospace_enable((task_id_t) arg.task_id, (uintptr_t) arg.ioaddr, (size_t) arg.size);
     260        return (unative_t) ddi_iospace_enable((task_id_t) arg.task_id,
     261                (uintptr_t) arg.ioaddr, (size_t) arg.size);
    187262}
    188263
    189264/** Disable or enable preemption.
    190265 *
    191  * @param enable If non-zero, the preemption counter will be decremented, leading to potential
    192  *               enabling of preemption. Otherwise the preemption counter will be incremented,
    193  *              preventing preemption from occurring.
     266 * @param enable If non-zero, the preemption counter will be decremented,
     267 *      leading to potential enabling of preemption. Otherwise the preemption
     268 *      counter will be incremented, preventing preemption from occurring.
    194269 *
    195270 * @return Zero on success or EPERM if callers capabilities are not sufficient.
Note: See TracChangeset for help on using the changeset viewer.