Changeset fbcdeb8 in mainline for uspace/lib/c/generic/ddi.c


Ignore:
Timestamp:
2011-12-19T17:30:39Z (13 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
58f6229
Parents:
24cf31f1
Message:

Remove the two-phase way of creating virtual memory areas (first asking for a mappable address and then mapping it) which was prone to race conditions when two or more calls to as_get_mappable_page() and as_area_create() were interleaved. This for example caused the e1k driver to randomly fail.

The memory area related syscalls and IPC calls have all been altered to accept a special value (void *) -1, representing a demand to atomically search for a mappable address space "hole" and map to it.

Individual changes:

  • IPC_M_SHARE_OUT: the destination address space area is supplied by the kernel, the callee only specifies the lower bound

(the address is returned to the callee via a pointer in an IPC reply argument)

  • IPC_M_SHARE_IN: the destination address space ares is supplied by the kernel, the callee only specifies the lower bound

(the address is returned to the caller as usual via an IPC argument)

  • SYS_AS_GET_UNMAPPED_AREA was removed
  • dummy implementations of SYS_PHYSMEM_UNMAP and SYS_IOSPACE_DISABLE were added for the sake of symmetry (they do nothing yet)
  • SYS_PHYSMEM_MAP and SYS_DMAMEM_MAP were altered to accept (void *) -1 as address space area base and a lower bound
  • kernel as_area_create() and as_area_share() were altered to accept (void *) -1 as address space area base and a lower bound
  • uspace libraries and programs were altered to reflect the new API
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/ddi.c

    r24cf31f1 rfbcdeb8  
    4545#include <align.h>
    4646#include <libarch/config.h>
     47#include "private/libc.h"
    4748
    4849/** Return unique device number.
     
    6162 *
    6263 * @param phys  Physical address of the starting frame.
    63  * @param virt  Virtual address of the starting page.
    6464 * @param pages Number of pages to map.
    6565 * @param flags Flags for the new address space area.
     66 * @param virt  Virtual address of the starting page.
    6667 *
    6768 * @return EOK on success
     
    7273 *
    7374 */
    74 int physmem_map(void *phys, void *virt, size_t pages, unsigned int flags)
     75int physmem_map(void *phys, size_t pages, unsigned int flags, void **virt)
    7576{
    76         return __SYSCALL4(SYS_PHYSMEM_MAP, (sysarg_t) phys,
    77             (sysarg_t) virt, pages, flags);
     77        return __SYSCALL5(SYS_PHYSMEM_MAP, (sysarg_t) phys,
     78            pages, flags, (sysarg_t) virt, (sysarg_t) __entry);
    7879}
    7980
     
    8182    unsigned int flags, void **phys)
    8283{
    83         return (int) __SYSCALL5(SYS_DMAMEM_MAP, (sysarg_t) virt,
    84             (sysarg_t) size, (sysarg_t) map_flags, (sysarg_t) flags,
    85             (sysarg_t) phys);
     84        return (int) __SYSCALL6(SYS_DMAMEM_MAP, (sysarg_t) size,
     85            (sysarg_t) map_flags, (sysarg_t) flags & ~DMAMEM_FLAGS_ANONYMOUS,
     86            (sysarg_t) phys, (sysarg_t) virt, 0);
    8687}
    8788
     
    8990    unsigned int flags, void **phys, void **virt)
    9091{
    91         *virt = as_get_mappable_page(size);
    92         if (*virt == NULL)
    93                 return ENOMEM;
    94        
    95         return dmamem_map(*virt, size, map_flags,
    96             flags | DMAMEM_FLAGS_ANONYMOUS, phys);
     92        return (int) __SYSCALL6(SYS_DMAMEM_MAP, (sysarg_t) size,
     93            (sysarg_t) map_flags, (sysarg_t) flags | DMAMEM_FLAGS_ANONYMOUS,
     94            (sysarg_t) phys, (sysarg_t) virt, (sysarg_t) __entry);
    9795}
    9896
    99 int dmamem_unmap(void *virt, size_t size, unsigned int flags)
     97int dmamem_unmap(void *virt, size_t size)
    10098{
    101         return __SYSCALL3(SYS_DMAMEM_UNMAP, (sysarg_t) virt, (sysarg_t) size,
    102             (sysarg_t) flags);
     99        return __SYSCALL3(SYS_DMAMEM_UNMAP, (sysarg_t) virt, (sysarg_t) size, 0);
    103100}
    104101
     
    138135 * @param pio_addr I/O start address.
    139136 * @param size     Size of the I/O region.
    140  * @param use_addr Address where the final address for
    141  *                 application's PIO will be stored.
     137 * @param virt     Virtual address for application's
     138 *                 PIO operations.
    142139 *
    143  * @return Zero on success or negative error code.
     140 * @return EOK on success.
     141 * @return Negative error code on failure.
    144142 *
    145143 */
    146 int pio_enable(void *pio_addr, size_t size, void **use_addr)
     144int pio_enable(void *pio_addr, size_t size, void **virt)
    147145{
    148         void *phys;
    149         void *virt;
    150         size_t offset;
    151         unsigned int pages;
    152        
    153146#ifdef IO_SPACE_BOUNDARY
    154147        if (pio_addr < IO_SPACE_BOUNDARY) {
    155                 *use_addr = pio_addr;
     148                *virt = pio_addr;
    156149                return iospace_enable(task_get_id(), pio_addr, size);
    157150        }
    158151#endif
    159152       
    160         phys = (void *) ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
    161         offset = pio_addr - phys;
    162         pages = ALIGN_UP(offset + size, PAGE_SIZE) >> PAGE_WIDTH;
    163         virt = as_get_mappable_page(pages << PAGE_WIDTH);
    164         *use_addr = virt + offset;
    165         return physmem_map(phys, virt, pages, AS_AREA_READ | AS_AREA_WRITE);
     153        void *phys_frame =
     154            (void *) ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
     155        size_t offset = pio_addr - phys_frame;
     156        size_t pages = SIZE2PAGES(offset + size);
     157       
     158        void *virt_page;
     159        int rc = physmem_map(phys_frame, pages,
     160            AS_AREA_READ | AS_AREA_WRITE, &virt_page);
     161        if (rc != EOK)
     162                return rc;
     163       
     164        *virt = virt_page + offset;
     165        return EOK;
    166166}
    167167
Note: See TracChangeset for help on using the changeset viewer.