The Design and Implementation of the FreeBSD Operating System, Second Edition
[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/xen/gnttab.c

Version: -  FREEBSD  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  cheribsd  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD8-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  3  -  10 

    1 /******************************************************************************
    2  * gnttab.c
    3  * 
    4  * Two sets of functionality:
    5  * 1. Granting foreign access to our memory reservation.
    6  * 2. Accessing others' memory reservations via grant references.
    7  * (i.e., mechanisms for both sender and recipient of grant references)
    8  * 
    9  * Copyright (c) 2005, Christopher Clark
   10  * Copyright (c) 2004, K A Fraser
   11  */
   12 
   13 #include <sys/cdefs.h>
   14 __FBSDID("$FreeBSD: head/sys/xen/gnttab.c 267534 2014-06-16 08:48:42Z royger $");
   15 
   16 #include "opt_global.h"
   17 #include "opt_pmap.h"
   18 
   19 #include <sys/param.h>
   20 #include <sys/systm.h>
   21 #include <sys/bus.h>
   22 #include <sys/conf.h>
   23 #include <sys/module.h>
   24 #include <sys/kernel.h>
   25 #include <sys/lock.h>
   26 #include <sys/malloc.h>
   27 #include <sys/mman.h>
   28 #include <sys/limits.h>
   29 #include <sys/rman.h>
   30 #include <machine/resource.h>
   31 
   32 #include <xen/xen-os.h>
   33 #include <xen/hypervisor.h>
   34 #include <machine/xen/synch_bitops.h>
   35 
   36 #include <xen/hypervisor.h>
   37 #include <xen/gnttab.h>
   38 
   39 #include <vm/vm.h>
   40 #include <vm/vm_kern.h>
   41 #include <vm/vm_extern.h>
   42 #include <vm/pmap.h>
   43 
   44 #define cmpxchg(a, b, c) atomic_cmpset_int((volatile u_int *)(a),(b),(c))
   45 
   46 /* External tools reserve first few grant table entries. */
   47 #define NR_RESERVED_ENTRIES 8
   48 #define GREFS_PER_GRANT_FRAME (PAGE_SIZE / sizeof(grant_entry_t))
   49 
   50 static grant_ref_t **gnttab_list;
   51 static unsigned int nr_grant_frames;
   52 static unsigned int boot_max_nr_grant_frames;
   53 static int gnttab_free_count;
   54 static grant_ref_t gnttab_free_head;
   55 static struct mtx gnttab_list_lock;
   56 
   57 #ifdef XENHVM
   58 /*
   59  * Resource representing allocated physical address space
   60  * for the grant table metainfo
   61  */
   62 static struct resource *gnttab_pseudo_phys_res;
   63 
   64 /* Resource id for allocated physical address space. */
   65 static int gnttab_pseudo_phys_res_id;
   66 #endif
   67 
   68 static grant_entry_t *shared;
   69 
   70 static struct gnttab_free_callback *gnttab_free_callback_list = NULL;
   71 
   72 static int gnttab_expand(unsigned int req_entries);
   73 
   74 #define RPP (PAGE_SIZE / sizeof(grant_ref_t))
   75 #define gnttab_entry(entry) (gnttab_list[(entry) / RPP][(entry) % RPP])
   76 
   77 static int
   78 get_free_entries(int count, int *entries)
   79 {
   80         int ref, error;
   81         grant_ref_t head;
   82 
   83         mtx_lock(&gnttab_list_lock);
   84         if ((gnttab_free_count < count) &&
   85             ((error = gnttab_expand(count - gnttab_free_count)) != 0)) {
   86                 mtx_unlock(&gnttab_list_lock);
   87                 return (error);
   88         }
   89         ref = head = gnttab_free_head;
   90         gnttab_free_count -= count;
   91         while (count-- > 1)
   92                 head = gnttab_entry(head);
   93         gnttab_free_head = gnttab_entry(head);
   94         gnttab_entry(head) = GNTTAB_LIST_END;
   95         mtx_unlock(&gnttab_list_lock);
   96 
   97         *entries = ref;
   98         return (0);
   99 }
  100 
  101 static void
  102 do_free_callbacks(void)
  103 {
  104         struct gnttab_free_callback *callback, *next;
  105 
  106         callback = gnttab_free_callback_list;
  107         gnttab_free_callback_list = NULL;
  108 
  109         while (callback != NULL) {
  110                 next = callback->next;
  111                 if (gnttab_free_count >= callback->count) {
  112                         callback->next = NULL;
  113                         callback->fn(callback->arg);
  114                 } else {
  115                         callback->next = gnttab_free_callback_list;
  116                         gnttab_free_callback_list = callback;
  117                 }
  118                 callback = next;
  119         }
  120 }
  121 
  122 static inline void
  123 check_free_callbacks(void)
  124 {
  125         if (__predict_false(gnttab_free_callback_list != NULL))
  126                 do_free_callbacks();
  127 }
  128 
  129 static void
  130 put_free_entry(grant_ref_t ref)
  131 {
  132 
  133         mtx_lock(&gnttab_list_lock);
  134         gnttab_entry(ref) = gnttab_free_head;
  135         gnttab_free_head = ref;
  136         gnttab_free_count++;
  137         check_free_callbacks();
  138         mtx_unlock(&gnttab_list_lock);
  139 }
  140 
  141 /*
  142  * Public grant-issuing interface functions
  143  */
  144 
  145 int
  146 gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly,
  147         grant_ref_t *result)
  148 {
  149         int error, ref;
  150 
  151         error = get_free_entries(1, &ref);
  152 
  153         if (__predict_false(error))
  154                 return (error);
  155 
  156         shared[ref].frame = frame;
  157         shared[ref].domid = domid;
  158         wmb();
  159         shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
  160 
  161         if (result)
  162                 *result = ref;
  163 
  164         return (0);
  165 }
  166 
  167 void
  168 gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
  169                                 unsigned long frame, int readonly)
  170 {
  171 
  172         shared[ref].frame = frame;
  173         shared[ref].domid = domid;
  174         wmb();
  175         shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
  176 }
  177 
  178 int
  179 gnttab_query_foreign_access(grant_ref_t ref)
  180 {
  181         uint16_t nflags;
  182 
  183         nflags = shared[ref].flags;
  184 
  185         return (nflags & (GTF_reading|GTF_writing));
  186 }
  187 
  188 int
  189 gnttab_end_foreign_access_ref(grant_ref_t ref)
  190 {
  191         uint16_t flags, nflags;
  192 
  193         nflags = shared[ref].flags;
  194         do {
  195                 if ( (flags = nflags) & (GTF_reading|GTF_writing) ) {
  196                         printf("%s: WARNING: g.e. still in use!\n", __func__);
  197                         return (0);
  198                 }
  199         } while ((nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) !=
  200                flags);
  201 
  202         return (1);
  203 }
  204 
  205 void
  206 gnttab_end_foreign_access(grant_ref_t ref, void *page)
  207 {
  208         if (gnttab_end_foreign_access_ref(ref)) {
  209                 put_free_entry(ref);
  210                 if (page != NULL) {
  211                         free(page, M_DEVBUF);
  212                 }
  213         }
  214         else {
  215                 /* XXX This needs to be fixed so that the ref and page are
  216                    placed on a list to be freed up later. */
  217                 printf("%s: WARNING: leaking g.e. and page still in use!\n",
  218                        __func__);
  219         }
  220 }
  221 
  222 void
  223 gnttab_end_foreign_access_references(u_int count, grant_ref_t *refs)
  224 {
  225         grant_ref_t *last_ref;
  226         grant_ref_t  head;
  227         grant_ref_t  tail;
  228 
  229         head = GNTTAB_LIST_END;
  230         tail = *refs;
  231         last_ref = refs + count;
  232         while (refs != last_ref) {
  233 
  234                 if (gnttab_end_foreign_access_ref(*refs)) {
  235                         gnttab_entry(*refs) = head;
  236                         head = *refs;
  237                 } else {
  238                         /*
  239                          * XXX This needs to be fixed so that the ref 
  240                          * is placed on a list to be freed up later.
  241                          */
  242                         printf("%s: WARNING: leaking g.e. still in use!\n",
  243                                __func__);
  244                         count--;
  245                 }
  246                 refs++;
  247         }
  248 
  249         if (count != 0) {
  250                 mtx_lock(&gnttab_list_lock);
  251                 gnttab_free_count += count;
  252                 gnttab_entry(tail) = gnttab_free_head;
  253                 gnttab_free_head = head;
  254                 mtx_unlock(&gnttab_list_lock);
  255         }
  256 }
  257 
  258 int
  259 gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn,
  260     grant_ref_t *result)
  261 {
  262         int error, ref;
  263 
  264         error = get_free_entries(1, &ref);
  265         if (__predict_false(error))
  266                 return (error);
  267 
  268         gnttab_grant_foreign_transfer_ref(ref, domid, pfn);
  269 
  270         *result = ref;
  271         return (0);
  272 }
  273 
  274 void
  275 gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid,
  276         unsigned long pfn)
  277 {
  278         shared[ref].frame = pfn;
  279         shared[ref].domid = domid;
  280         wmb();
  281         shared[ref].flags = GTF_accept_transfer;
  282 }
  283 
  284 unsigned long
  285 gnttab_end_foreign_transfer_ref(grant_ref_t ref)
  286 {
  287         unsigned long frame;
  288         uint16_t      flags;
  289 
  290         /*
  291          * If a transfer is not even yet started, try to reclaim the grant
  292          * reference and return failure (== 0).
  293          */
  294         while (!((flags = shared[ref].flags) & GTF_transfer_committed)) {
  295                 if ( synch_cmpxchg(&shared[ref].flags, flags, 0) == flags )
  296                         return (0);
  297                 cpu_relax();
  298         }
  299 
  300         /* If a transfer is in progress then wait until it is completed. */
  301         while (!(flags & GTF_transfer_completed)) {
  302                 flags = shared[ref].flags;
  303                 cpu_relax();
  304         }
  305 
  306         /* Read the frame number /after/ reading completion status. */
  307         rmb();
  308         frame = shared[ref].frame;
  309         KASSERT(frame != 0, ("grant table inconsistent"));
  310 
  311         return (frame);
  312 }
  313 
  314 unsigned long
  315 gnttab_end_foreign_transfer(grant_ref_t ref)
  316 {
  317         unsigned long frame = gnttab_end_foreign_transfer_ref(ref);
  318 
  319         put_free_entry(ref);
  320         return (frame);
  321 }
  322 
  323 void
  324 gnttab_free_grant_reference(grant_ref_t ref)
  325 {
  326 
  327         put_free_entry(ref);
  328 }
  329 
  330 void
  331 gnttab_free_grant_references(grant_ref_t head)
  332 {
  333         grant_ref_t ref;
  334         int count = 1;
  335 
  336         if (head == GNTTAB_LIST_END)
  337                 return;
  338 
  339         ref = head;
  340         while (gnttab_entry(ref) != GNTTAB_LIST_END) {
  341                 ref = gnttab_entry(ref);
  342                 count++;
  343         }
  344         mtx_lock(&gnttab_list_lock);
  345         gnttab_entry(ref) = gnttab_free_head;
  346         gnttab_free_head = head;
  347         gnttab_free_count += count;
  348         check_free_callbacks();
  349         mtx_unlock(&gnttab_list_lock);
  350 }
  351 
  352 int
  353 gnttab_alloc_grant_references(uint16_t count, grant_ref_t *head)
  354 {
  355         int ref, error;
  356 
  357         error = get_free_entries(count, &ref);
  358         if (__predict_false(error))
  359                 return (error);
  360 
  361         *head = ref;
  362         return (0);
  363 }
  364 
  365 int
  366 gnttab_empty_grant_references(const grant_ref_t *private_head)
  367 {
  368 
  369         return (*private_head == GNTTAB_LIST_END);
  370 }
  371 
  372 int
  373 gnttab_claim_grant_reference(grant_ref_t *private_head)
  374 {
  375         grant_ref_t g = *private_head;
  376 
  377         if (__predict_false(g == GNTTAB_LIST_END))
  378                 return (g);
  379         *private_head = gnttab_entry(g);
  380         return (g);
  381 }
  382 
  383 void
  384 gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t  release)
  385 {
  386 
  387         gnttab_entry(release) = *private_head;
  388         *private_head = release;
  389 }
  390 
  391 void
  392 gnttab_request_free_callback(struct gnttab_free_callback *callback,
  393     void (*fn)(void *), void *arg, uint16_t count)
  394 {
  395 
  396         mtx_lock(&gnttab_list_lock);
  397         if (callback->next)
  398                 goto out;
  399         callback->fn = fn;
  400         callback->arg = arg;
  401         callback->count = count;
  402         callback->next = gnttab_free_callback_list;
  403         gnttab_free_callback_list = callback;
  404         check_free_callbacks();
  405  out:
  406         mtx_unlock(&gnttab_list_lock);
  407 
  408 }
  409 
  410 void
  411 gnttab_cancel_free_callback(struct gnttab_free_callback *callback)
  412 {
  413         struct gnttab_free_callback **pcb;
  414 
  415         mtx_lock(&gnttab_list_lock);
  416         for (pcb = &gnttab_free_callback_list; *pcb; pcb = &(*pcb)->next) {
  417                 if (*pcb == callback) {
  418                         *pcb = callback->next;
  419                         break;
  420                 }
  421         }
  422         mtx_unlock(&gnttab_list_lock);
  423 }
  424 
  425 
  426 static int
  427 grow_gnttab_list(unsigned int more_frames)
  428 {
  429         unsigned int new_nr_grant_frames, extra_entries, i;
  430 
  431         new_nr_grant_frames = nr_grant_frames + more_frames;
  432         extra_entries       = more_frames * GREFS_PER_GRANT_FRAME;
  433 
  434         for (i = nr_grant_frames; i < new_nr_grant_frames; i++)
  435         {
  436                 gnttab_list[i] = (grant_ref_t *)
  437                         malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
  438 
  439                 if (!gnttab_list[i])
  440                         goto grow_nomem;
  441         }
  442 
  443         for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames;
  444              i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++)
  445                 gnttab_entry(i) = i + 1;
  446 
  447         gnttab_entry(i) = gnttab_free_head;
  448         gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames;
  449         gnttab_free_count += extra_entries;
  450 
  451         nr_grant_frames = new_nr_grant_frames;
  452 
  453         check_free_callbacks();
  454 
  455         return (0);
  456 
  457 grow_nomem:
  458         for ( ; i >= nr_grant_frames; i--)
  459                 free(gnttab_list[i], M_DEVBUF);
  460         return (ENOMEM);
  461 }
  462 
  463 static unsigned int
  464 __max_nr_grant_frames(void)
  465 {
  466         struct gnttab_query_size query;
  467         int rc;
  468 
  469         query.dom = DOMID_SELF;
  470 
  471         rc = HYPERVISOR_grant_table_op(GNTTABOP_query_size, &query, 1);
  472         if ((rc < 0) || (query.status != GNTST_okay))
  473                 return (4); /* Legacy max supported number of frames */
  474 
  475         return (query.max_nr_frames);
  476 }
  477 
  478 static inline
  479 unsigned int max_nr_grant_frames(void)
  480 {
  481         unsigned int xen_max = __max_nr_grant_frames();
  482 
  483         if (xen_max > boot_max_nr_grant_frames)
  484                 return (boot_max_nr_grant_frames);
  485         return (xen_max);
  486 }
  487 
  488 #ifdef notyet
  489 /*
  490  * XXX needed for backend support
  491  *
  492  */
  493 static int
  494 map_pte_fn(pte_t *pte, struct page *pmd_page,
  495                       unsigned long addr, void *data)
  496 {
  497         unsigned long **frames = (unsigned long **)data;
  498 
  499         set_pte_at(&init_mm, addr, pte, pfn_pte_ma((*frames)[0], PAGE_KERNEL));
  500         (*frames)++;
  501         return 0;
  502 }
  503 
  504 static int
  505 unmap_pte_fn(pte_t *pte, struct page *pmd_page,
  506                         unsigned long addr, void *data)
  507 {
  508 
  509         set_pte_at(&init_mm, addr, pte, __pte(0));
  510         return 0;
  511 }
  512 #endif
  513 
  514 #ifndef XENHVM
  515 
  516 static int
  517 gnttab_map(unsigned int start_idx, unsigned int end_idx)
  518 {
  519         struct gnttab_setup_table setup;
  520         u_long *frames;
  521 
  522         unsigned int nr_gframes = end_idx + 1;
  523         int i, rc;
  524 
  525         frames = malloc(nr_gframes * sizeof(unsigned long), M_DEVBUF, M_NOWAIT);
  526         if (!frames)
  527                 return (ENOMEM);
  528 
  529         setup.dom        = DOMID_SELF;
  530         setup.nr_frames  = nr_gframes;
  531         set_xen_guest_handle(setup.frame_list, frames);
  532 
  533         rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
  534         if (rc == -ENOSYS) {
  535                 free(frames, M_DEVBUF);
  536                 return (ENOSYS);
  537         }
  538         KASSERT(!(rc || setup.status),
  539             ("unexpected result from grant_table_op"));
  540 
  541         if (shared == NULL) {
  542                 vm_offset_t area;
  543 
  544                 area = kva_alloc(PAGE_SIZE * max_nr_grant_frames());
  545                 KASSERT(area, ("can't allocate VM space for grant table"));
  546                 shared = (grant_entry_t *)area;
  547         }
  548 
  549         for (i = 0; i < nr_gframes; i++)
  550                 PT_SET_MA(((caddr_t)shared) + i*PAGE_SIZE, 
  551                     ((vm_paddr_t)frames[i]) << PAGE_SHIFT | PG_RW | PG_V);
  552 
  553         free(frames, M_DEVBUF);
  554 
  555         return (0);
  556 }
  557 
  558 int
  559 gnttab_resume(device_t dev)
  560 {
  561 
  562         if (max_nr_grant_frames() < nr_grant_frames)
  563                 return (ENOSYS);
  564         return (gnttab_map(0, nr_grant_frames - 1));
  565 }
  566 
  567 int
  568 gnttab_suspend(void)
  569 {
  570         int i;
  571 
  572         for (i = 0; i < nr_grant_frames; i++)
  573                 pmap_kremove((vm_offset_t) shared + i * PAGE_SIZE);
  574 
  575         return (0);
  576 }
  577 
  578 #else /* XENHVM */
  579 
  580 static vm_paddr_t resume_frames;
  581 
  582 static int
  583 gnttab_map(unsigned int start_idx, unsigned int end_idx)
  584 {
  585         struct xen_add_to_physmap xatp;
  586         unsigned int i = end_idx;
  587 
  588         /*
  589          * Loop backwards, so that the first hypercall has the largest index,
  590          * ensuring that the table will grow only once.
  591          */
  592         do {
  593                 xatp.domid = DOMID_SELF;
  594                 xatp.idx = i;
  595                 xatp.space = XENMAPSPACE_grant_table;
  596                 xatp.gpfn = (resume_frames >> PAGE_SHIFT) + i;
  597                 if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
  598                         panic("HYPERVISOR_memory_op failed to map gnttab");
  599         } while (i-- > start_idx);
  600 
  601         if (shared == NULL) {
  602                 vm_offset_t area;
  603 
  604                 area = kva_alloc(PAGE_SIZE * max_nr_grant_frames());
  605                 KASSERT(area, ("can't allocate VM space for grant table"));
  606                 shared = (grant_entry_t *)area;
  607         }
  608 
  609         for (i = start_idx; i <= end_idx; i++) {
  610                 pmap_kenter((vm_offset_t) shared + i * PAGE_SIZE,
  611                     resume_frames + i * PAGE_SIZE);
  612         }
  613 
  614         return (0);
  615 }
  616 
  617 int
  618 gnttab_resume(device_t dev)
  619 {
  620         unsigned int max_nr_gframes, nr_gframes;
  621 
  622         nr_gframes = nr_grant_frames;
  623         max_nr_gframes = max_nr_grant_frames();
  624         if (max_nr_gframes < nr_gframes)
  625                 return (ENOSYS);
  626 
  627         if (!resume_frames) {
  628                 KASSERT(dev != NULL,
  629                     ("No resume frames and no device provided"));
  630 
  631                 gnttab_pseudo_phys_res = bus_alloc_resource(dev,
  632                     SYS_RES_MEMORY, &gnttab_pseudo_phys_res_id, 0, ~0,
  633                     PAGE_SIZE * max_nr_gframes, RF_ACTIVE);
  634                 if (gnttab_pseudo_phys_res == NULL)
  635                         panic("Unable to reserve physical memory for gnttab");
  636                 resume_frames = rman_get_start(gnttab_pseudo_phys_res);
  637         }
  638 
  639         return (gnttab_map(0, nr_gframes - 1));
  640 }
  641 
  642 #endif
  643 
  644 static int
  645 gnttab_expand(unsigned int req_entries)
  646 {
  647         int error;
  648         unsigned int cur, extra;
  649 
  650         cur = nr_grant_frames;
  651         extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
  652                  GREFS_PER_GRANT_FRAME);
  653         if (cur + extra > max_nr_grant_frames())
  654                 return (ENOSPC);
  655 
  656         error = gnttab_map(cur, cur + extra - 1);
  657         if (!error)
  658                 error = grow_gnttab_list(extra);
  659 
  660         return (error);
  661 }
  662 
  663 int 
  664 gnttab_init(device_t dev)
  665 {
  666         int i;
  667         unsigned int max_nr_glist_frames;
  668         unsigned int nr_init_grefs;
  669 
  670         if (!is_running_on_xen())
  671                 return (ENODEV);
  672 
  673         nr_grant_frames = 1;
  674         boot_max_nr_grant_frames = __max_nr_grant_frames();
  675 
  676         /* Determine the maximum number of frames required for the
  677          * grant reference free list on the current hypervisor.
  678          */
  679         max_nr_glist_frames = (boot_max_nr_grant_frames *
  680                                GREFS_PER_GRANT_FRAME /
  681                                (PAGE_SIZE / sizeof(grant_ref_t)));
  682 
  683         gnttab_list = malloc(max_nr_glist_frames * sizeof(grant_ref_t *),
  684             M_DEVBUF, M_NOWAIT);
  685 
  686         if (gnttab_list == NULL)
  687                 return (ENOMEM);
  688 
  689         for (i = 0; i < nr_grant_frames; i++) {
  690                 gnttab_list[i] = (grant_ref_t *)
  691                         malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
  692                 if (gnttab_list[i] == NULL)
  693                         goto ini_nomem;
  694         }
  695 
  696         if (gnttab_resume(dev))
  697                 return (ENODEV);
  698 
  699         nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME;
  700 
  701         for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++)
  702                 gnttab_entry(i) = i + 1;
  703 
  704         gnttab_entry(nr_init_grefs - 1) = GNTTAB_LIST_END;
  705         gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES;
  706         gnttab_free_head  = NR_RESERVED_ENTRIES;
  707 
  708         if (bootverbose)
  709                 printf("Grant table initialized\n");
  710 
  711         return (0);
  712 
  713 ini_nomem:
  714         for (i--; i >= 0; i--)
  715                 free(gnttab_list[i], M_DEVBUF);
  716         free(gnttab_list, M_DEVBUF);
  717         return (ENOMEM);
  718 
  719 }
  720 
  721 MTX_SYSINIT(gnttab, &gnttab_list_lock, "GNTTAB LOCK", MTX_DEF); 

Cache object: 809b9cb5f9386d28fc85b7d368d83a73


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.