linux/drivers/iommu/iova.c
<<
>>
Prefs
   1/*
   2 * Copyright © 2006-2009, Intel Corporation.
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms and conditions of the GNU General Public License,
   6 * version 2, as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope it will be useful, but WITHOUT
   9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  11 * more details.
  12 *
  13 * You should have received a copy of the GNU General Public License along with
  14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  15 * Place - Suite 330, Boston, MA 02111-1307 USA.
  16 *
  17 * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
  18 */
  19
  20#include <linux/iova.h>
  21#include <linux/module.h>
  22#include <linux/slab.h>
  23
  24void
  25init_iova_domain(struct iova_domain *iovad, unsigned long granule,
  26        unsigned long start_pfn, unsigned long pfn_32bit)
  27{
  28        /*
  29         * IOVA granularity will normally be equal to the smallest
  30         * supported IOMMU page size; both *must* be capable of
  31         * representing individual CPU pages exactly.
  32         */
  33        BUG_ON((granule > PAGE_SIZE) || !is_power_of_2(granule));
  34
  35        spin_lock_init(&iovad->iova_rbtree_lock);
  36        iovad->rbroot = RB_ROOT;
  37        iovad->cached32_node = NULL;
  38        iovad->granule = granule;
  39        iovad->start_pfn = start_pfn;
  40        iovad->dma_32bit_pfn = pfn_32bit;
  41}
  42EXPORT_SYMBOL_GPL(init_iova_domain);
  43
  44static struct rb_node *
  45__get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn)
  46{
  47        if ((*limit_pfn != iovad->dma_32bit_pfn) ||
  48                (iovad->cached32_node == NULL))
  49                return rb_last(&iovad->rbroot);
  50        else {
  51                struct rb_node *prev_node = rb_prev(iovad->cached32_node);
  52                struct iova *curr_iova =
  53                        container_of(iovad->cached32_node, struct iova, node);
  54                *limit_pfn = curr_iova->pfn_lo - 1;
  55                return prev_node;
  56        }
  57}
  58
  59static void
  60__cached_rbnode_insert_update(struct iova_domain *iovad,
  61        unsigned long limit_pfn, struct iova *new)
  62{
  63        if (limit_pfn != iovad->dma_32bit_pfn)
  64                return;
  65        iovad->cached32_node = &new->node;
  66}
  67
  68static void
  69__cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free)
  70{
  71        struct iova *cached_iova;
  72        struct rb_node *curr;
  73
  74        if (!iovad->cached32_node)
  75                return;
  76        curr = iovad->cached32_node;
  77        cached_iova = container_of(curr, struct iova, node);
  78
  79        if (free->pfn_lo >= cached_iova->pfn_lo) {
  80                struct rb_node *node = rb_next(&free->node);
  81                struct iova *iova = container_of(node, struct iova, node);
  82
  83                /* only cache if it's below 32bit pfn */
  84                if (node && iova->pfn_lo < iovad->dma_32bit_pfn)
  85                        iovad->cached32_node = node;
  86                else
  87                        iovad->cached32_node = NULL;
  88        }
  89}
  90
  91/*
  92 * Computes the padding size required, to make the start address
  93 * naturally aligned on the power-of-two order of its size
  94 */
  95static unsigned int
  96iova_get_pad_size(unsigned int size, unsigned int limit_pfn)
  97{
  98        return (limit_pfn + 1 - size) & (__roundup_pow_of_two(size) - 1);
  99}
 100
 101static int __alloc_and_insert_iova_range(struct iova_domain *iovad,
 102                unsigned long size, unsigned long limit_pfn,
 103                        struct iova *new, bool size_aligned)
 104{
 105        struct rb_node *prev, *curr = NULL;
 106        unsigned long flags;
 107        unsigned long saved_pfn;
 108        unsigned int pad_size = 0;
 109
 110        /* Walk the tree backwards */
 111        spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
 112        saved_pfn = limit_pfn;
 113        curr = __get_cached_rbnode(iovad, &limit_pfn);
 114        prev = curr;
 115        while (curr) {
 116                struct iova *curr_iova = container_of(curr, struct iova, node);
 117
 118                if (limit_pfn < curr_iova->pfn_lo)
 119                        goto move_left;
 120                else if (limit_pfn < curr_iova->pfn_hi)
 121                        goto adjust_limit_pfn;
 122                else {
 123                        if (size_aligned)
 124                                pad_size = iova_get_pad_size(size, limit_pfn);
 125                        if ((curr_iova->pfn_hi + size + pad_size) <= limit_pfn)
 126                                break;  /* found a free slot */
 127                }
 128adjust_limit_pfn:
 129                limit_pfn = curr_iova->pfn_lo - 1;
 130move_left:
 131                prev = curr;
 132                curr = rb_prev(curr);
 133        }
 134
 135        if (!curr) {
 136                if (size_aligned)
 137                        pad_size = iova_get_pad_size(size, limit_pfn);
 138                if ((iovad->start_pfn + size + pad_size) > limit_pfn) {
 139                        spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
 140                        return -ENOMEM;
 141                }
 142        }
 143
 144        /* pfn_lo will point to size aligned address if size_aligned is set */
 145        new->pfn_lo = limit_pfn - (size + pad_size) + 1;
 146        new->pfn_hi = new->pfn_lo + size - 1;
 147
 148        /* Insert the new_iova into domain rbtree by holding writer lock */
 149        /* Add new node and rebalance tree. */
 150        {
 151                struct rb_node **entry, *parent = NULL;
 152
 153                /* If we have 'prev', it's a valid place to start the
 154                   insertion. Otherwise, start from the root. */
 155                if (prev)
 156                        entry = &prev;
 157                else
 158                        entry = &iovad->rbroot.rb_node;
 159
 160                /* Figure out where to put new node */
 161                while (*entry) {
 162                        struct iova *this = container_of(*entry,
 163                                                        struct iova, node);
 164                        parent = *entry;
 165
 166                        if (new->pfn_lo < this->pfn_lo)
 167                                entry = &((*entry)->rb_left);
 168                        else if (new->pfn_lo > this->pfn_lo)
 169                                entry = &((*entry)->rb_right);
 170                        else
 171                                BUG(); /* this should not happen */
 172                }
 173
 174                /* Add new node and rebalance tree. */
 175                rb_link_node(&new->node, parent, entry);
 176                rb_insert_color(&new->node, &iovad->rbroot);
 177        }
 178        __cached_rbnode_insert_update(iovad, saved_pfn, new);
 179
 180        spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
 181
 182
 183        return 0;
 184}
 185
 186static void
 187iova_insert_rbtree(struct rb_root *root, struct iova *iova)
 188{
 189        struct rb_node **new = &(root->rb_node), *parent = NULL;
 190        /* Figure out where to put new node */
 191        while (*new) {
 192                struct iova *this = container_of(*new, struct iova, node);
 193
 194                parent = *new;
 195
 196                if (iova->pfn_lo < this->pfn_lo)
 197                        new = &((*new)->rb_left);
 198                else if (iova->pfn_lo > this->pfn_lo)
 199                        new = &((*new)->rb_right);
 200                else
 201                        BUG(); /* this should not happen */
 202        }
 203        /* Add new node and rebalance tree. */
 204        rb_link_node(&iova->node, parent, new);
 205        rb_insert_color(&iova->node, root);
 206}
 207
 208static struct kmem_cache *iova_cache;
 209static unsigned int iova_cache_users;
 210static DEFINE_MUTEX(iova_cache_mutex);
 211
 212struct iova *alloc_iova_mem(void)
 213{
 214        return kmem_cache_alloc(iova_cache, GFP_ATOMIC);
 215}
 216EXPORT_SYMBOL(alloc_iova_mem);
 217
 218void free_iova_mem(struct iova *iova)
 219{
 220        kmem_cache_free(iova_cache, iova);
 221}
 222EXPORT_SYMBOL(free_iova_mem);
 223
 224int iova_cache_get(void)
 225{
 226        mutex_lock(&iova_cache_mutex);
 227        if (!iova_cache_users) {
 228                iova_cache = kmem_cache_create(
 229                        "iommu_iova", sizeof(struct iova), 0,
 230                        SLAB_HWCACHE_ALIGN, NULL);
 231                if (!iova_cache) {
 232                        mutex_unlock(&iova_cache_mutex);
 233                        printk(KERN_ERR "Couldn't create iova cache\n");
 234                        return -ENOMEM;
 235                }
 236        }
 237
 238        iova_cache_users++;
 239        mutex_unlock(&iova_cache_mutex);
 240
 241        return 0;
 242}
 243EXPORT_SYMBOL_GPL(iova_cache_get);
 244
 245void iova_cache_put(void)
 246{
 247        mutex_lock(&iova_cache_mutex);
 248        if (WARN_ON(!iova_cache_users)) {
 249                mutex_unlock(&iova_cache_mutex);
 250                return;
 251        }
 252        iova_cache_users--;
 253        if (!iova_cache_users)
 254                kmem_cache_destroy(iova_cache);
 255        mutex_unlock(&iova_cache_mutex);
 256}
 257EXPORT_SYMBOL_GPL(iova_cache_put);
 258
 259/**
 260 * alloc_iova - allocates an iova
 261 * @iovad: - iova domain in question
 262 * @size: - size of page frames to allocate
 263 * @limit_pfn: - max limit address
 264 * @size_aligned: - set if size_aligned address range is required
 265 * This function allocates an iova in the range iovad->start_pfn to limit_pfn,
 266 * searching top-down from limit_pfn to iovad->start_pfn. If the size_aligned
 267 * flag is set then the allocated address iova->pfn_lo will be naturally
 268 * aligned on roundup_power_of_two(size).
 269 */
 270struct iova *
 271alloc_iova(struct iova_domain *iovad, unsigned long size,
 272        unsigned long limit_pfn,
 273        bool size_aligned)
 274{
 275        struct iova *new_iova;
 276        int ret;
 277
 278        new_iova = alloc_iova_mem();
 279        if (!new_iova)
 280                return NULL;
 281
 282        ret = __alloc_and_insert_iova_range(iovad, size, limit_pfn,
 283                        new_iova, size_aligned);
 284
 285        if (ret) {
 286                free_iova_mem(new_iova);
 287                return NULL;
 288        }
 289
 290        return new_iova;
 291}
 292EXPORT_SYMBOL_GPL(alloc_iova);
 293
 294/**
 295 * find_iova - find's an iova for a given pfn
 296 * @iovad: - iova domain in question.
 297 * @pfn: - page frame number
 298 * This function finds and returns an iova belonging to the
 299 * given doamin which matches the given pfn.
 300 */
 301struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn)
 302{
 303        unsigned long flags;
 304        struct rb_node *node;
 305
 306        /* Take the lock so that no other thread is manipulating the rbtree */
 307        spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
 308        node = iovad->rbroot.rb_node;
 309        while (node) {
 310                struct iova *iova = container_of(node, struct iova, node);
 311
 312                /* If pfn falls within iova's range, return iova */
 313                if ((pfn >= iova->pfn_lo) && (pfn <= iova->pfn_hi)) {
 314                        spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
 315                        /* We are not holding the lock while this iova
 316                         * is referenced by the caller as the same thread
 317                         * which called this function also calls __free_iova()
 318                         * and it is by design that only one thread can possibly
 319                         * reference a particular iova and hence no conflict.
 320                         */
 321                        return iova;
 322                }
 323
 324                if (pfn < iova->pfn_lo)
 325                        node = node->rb_left;
 326                else if (pfn > iova->pfn_lo)
 327                        node = node->rb_right;
 328        }
 329
 330        spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
 331        return NULL;
 332}
 333EXPORT_SYMBOL_GPL(find_iova);
 334
 335/**
 336 * __free_iova - frees the given iova
 337 * @iovad: iova domain in question.
 338 * @iova: iova in question.
 339 * Frees the given iova belonging to the giving domain
 340 */
 341void
 342__free_iova(struct iova_domain *iovad, struct iova *iova)
 343{
 344        unsigned long flags;
 345
 346        spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
 347        __cached_rbnode_delete_update(iovad, iova);
 348        rb_erase(&iova->node, &iovad->rbroot);
 349        spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
 350        free_iova_mem(iova);
 351}
 352EXPORT_SYMBOL_GPL(__free_iova);
 353
 354/**
 355 * free_iova - finds and frees the iova for a given pfn
 356 * @iovad: - iova domain in question.
 357 * @pfn: - pfn that is allocated previously
 358 * This functions finds an iova for a given pfn and then
 359 * frees the iova from that domain.
 360 */
 361void
 362free_iova(struct iova_domain *iovad, unsigned long pfn)
 363{
 364        struct iova *iova = find_iova(iovad, pfn);
 365
 366        if (iova)
 367                __free_iova(iovad, iova);
 368
 369}
 370EXPORT_SYMBOL_GPL(free_iova);
 371
 372/**
 373 * put_iova_domain - destroys the iova doamin
 374 * @iovad: - iova domain in question.
 375 * All the iova's in that domain are destroyed.
 376 */
 377void put_iova_domain(struct iova_domain *iovad)
 378{
 379        struct rb_node *node;
 380        unsigned long flags;
 381
 382        spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
 383        node = rb_first(&iovad->rbroot);
 384        while (node) {
 385                struct iova *iova = container_of(node, struct iova, node);
 386
 387                rb_erase(node, &iovad->rbroot);
 388                free_iova_mem(iova);
 389                node = rb_first(&iovad->rbroot);
 390        }
 391        spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
 392}
 393EXPORT_SYMBOL_GPL(put_iova_domain);
 394
 395static int
 396__is_range_overlap(struct rb_node *node,
 397        unsigned long pfn_lo, unsigned long pfn_hi)
 398{
 399        struct iova *iova = container_of(node, struct iova, node);
 400
 401        if ((pfn_lo <= iova->pfn_hi) && (pfn_hi >= iova->pfn_lo))
 402                return 1;
 403        return 0;
 404}
 405
 406static inline struct iova *
 407alloc_and_init_iova(unsigned long pfn_lo, unsigned long pfn_hi)
 408{
 409        struct iova *iova;
 410
 411        iova = alloc_iova_mem();
 412        if (iova) {
 413                iova->pfn_lo = pfn_lo;
 414                iova->pfn_hi = pfn_hi;
 415        }
 416
 417        return iova;
 418}
 419
 420static struct iova *
 421__insert_new_range(struct iova_domain *iovad,
 422        unsigned long pfn_lo, unsigned long pfn_hi)
 423{
 424        struct iova *iova;
 425
 426        iova = alloc_and_init_iova(pfn_lo, pfn_hi);
 427        if (iova)
 428                iova_insert_rbtree(&iovad->rbroot, iova);
 429
 430        return iova;
 431}
 432
 433static void
 434__adjust_overlap_range(struct iova *iova,
 435        unsigned long *pfn_lo, unsigned long *pfn_hi)
 436{
 437        if (*pfn_lo < iova->pfn_lo)
 438                iova->pfn_lo = *pfn_lo;
 439        if (*pfn_hi > iova->pfn_hi)
 440                *pfn_lo = iova->pfn_hi + 1;
 441}
 442
 443/**
 444 * reserve_iova - reserves an iova in the given range
 445 * @iovad: - iova domain pointer
 446 * @pfn_lo: - lower page frame address
 447 * @pfn_hi:- higher pfn adderss
 448 * This function allocates reserves the address range from pfn_lo to pfn_hi so
 449 * that this address is not dished out as part of alloc_iova.
 450 */
 451struct iova *
 452reserve_iova(struct iova_domain *iovad,
 453        unsigned long pfn_lo, unsigned long pfn_hi)
 454{
 455        struct rb_node *node;
 456        unsigned long flags;
 457        struct iova *iova;
 458        unsigned int overlap = 0;
 459
 460        spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
 461        for (node = rb_first(&iovad->rbroot); node; node = rb_next(node)) {
 462                if (__is_range_overlap(node, pfn_lo, pfn_hi)) {
 463                        iova = container_of(node, struct iova, node);
 464                        __adjust_overlap_range(iova, &pfn_lo, &pfn_hi);
 465                        if ((pfn_lo >= iova->pfn_lo) &&
 466                                (pfn_hi <= iova->pfn_hi))
 467                                goto finish;
 468                        overlap = 1;
 469
 470                } else if (overlap)
 471                                break;
 472        }
 473
 474        /* We are here either because this is the first reserver node
 475         * or need to insert remaining non overlap addr range
 476         */
 477        iova = __insert_new_range(iovad, pfn_lo, pfn_hi);
 478finish:
 479
 480        spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
 481        return iova;
 482}
 483EXPORT_SYMBOL_GPL(reserve_iova);
 484
 485/**
 486 * copy_reserved_iova - copies the reserved between domains
 487 * @from: - source doamin from where to copy
 488 * @to: - destination domin where to copy
 489 * This function copies reserved iova's from one doamin to
 490 * other.
 491 */
 492void
 493copy_reserved_iova(struct iova_domain *from, struct iova_domain *to)
 494{
 495        unsigned long flags;
 496        struct rb_node *node;
 497
 498        spin_lock_irqsave(&from->iova_rbtree_lock, flags);
 499        for (node = rb_first(&from->rbroot); node; node = rb_next(node)) {
 500                struct iova *iova = container_of(node, struct iova, node);
 501                struct iova *new_iova;
 502
 503                new_iova = reserve_iova(to, iova->pfn_lo, iova->pfn_hi);
 504                if (!new_iova)
 505                        printk(KERN_ERR "Reserve iova range %lx@%lx failed\n",
 506                                iova->pfn_lo, iova->pfn_lo);
 507        }
 508        spin_unlock_irqrestore(&from->iova_rbtree_lock, flags);
 509}
 510EXPORT_SYMBOL_GPL(copy_reserved_iova);
 511
 512struct iova *
 513split_and_remove_iova(struct iova_domain *iovad, struct iova *iova,
 514                      unsigned long pfn_lo, unsigned long pfn_hi)
 515{
 516        unsigned long flags;
 517        struct iova *prev = NULL, *next = NULL;
 518
 519        spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
 520        if (iova->pfn_lo < pfn_lo) {
 521                prev = alloc_and_init_iova(iova->pfn_lo, pfn_lo - 1);
 522                if (prev == NULL)
 523                        goto error;
 524        }
 525        if (iova->pfn_hi > pfn_hi) {
 526                next = alloc_and_init_iova(pfn_hi + 1, iova->pfn_hi);
 527                if (next == NULL)
 528                        goto error;
 529        }
 530
 531        __cached_rbnode_delete_update(iovad, iova);
 532        rb_erase(&iova->node, &iovad->rbroot);
 533
 534        if (prev) {
 535                iova_insert_rbtree(&iovad->rbroot, prev);
 536                iova->pfn_lo = pfn_lo;
 537        }
 538        if (next) {
 539                iova_insert_rbtree(&iovad->rbroot, next);
 540                iova->pfn_hi = pfn_hi;
 541        }
 542        spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
 543
 544        return iova;
 545
 546error:
 547        spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
 548        if (prev)
 549                free_iova_mem(prev);
 550        return NULL;
 551}
 552
 553MODULE_AUTHOR("Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>");
 554MODULE_LICENSE("GPL");
 555