1215976Sjmallett/***********************license start***************
2232812Sjmallett * Copyright (c) 2003-2010  Cavium Inc. (support@cavium.com). All rights
3215976Sjmallett * reserved.
4215976Sjmallett *
5215976Sjmallett *
6215976Sjmallett * Redistribution and use in source and binary forms, with or without
7215976Sjmallett * modification, are permitted provided that the following conditions are
8215976Sjmallett * met:
9215976Sjmallett *
10215976Sjmallett *   * Redistributions of source code must retain the above copyright
11215976Sjmallett *     notice, this list of conditions and the following disclaimer.
12215976Sjmallett *
13215976Sjmallett *   * Redistributions in binary form must reproduce the above
14215976Sjmallett *     copyright notice, this list of conditions and the following
15215976Sjmallett *     disclaimer in the documentation and/or other materials provided
16215976Sjmallett *     with the distribution.
17215976Sjmallett
18232812Sjmallett *   * Neither the name of Cavium Inc. nor the names of
19215976Sjmallett *     its contributors may be used to endorse or promote products
20215976Sjmallett *     derived from this software without specific prior written
21215976Sjmallett *     permission.
22215976Sjmallett
23215976Sjmallett * This Software, including technical data, may be subject to U.S. export  control
24215976Sjmallett * laws, including the U.S. Export Administration Act and its  associated
25215976Sjmallett * regulations, and may be subject to export or import  regulations in other
26215976Sjmallett * countries.
27215976Sjmallett
28215976Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30215976Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31215976Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32215976Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33215976Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34215976Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35215976Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36215976Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
37215976Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38215976Sjmallett ***********************license end**************************************/
39215976Sjmallett
40215976Sjmallett
41215976Sjmallett
42215976Sjmallett/**
43215976Sjmallett * @file
44215976Sjmallett *   cvmx-shmem supplies the cross application shared memory implementation
45215976Sjmallett *
46215976Sjmallett * <hr>$Revision: 41586 $<hr>
47215976Sjmallett */
48215976Sjmallett#include "cvmx.h"
49215976Sjmallett#include "cvmx-bootmem.h"
50215976Sjmallett#include "cvmx-tlb.h"
51215976Sjmallett#include "cvmx-shmem.h"
52215976Sjmallett
53215976Sjmallett//#define DEBUG
54215976Sjmallett
55215976Sjmallettstruct cvmx_shmem_smdr *__smdr = NULL;
56215976Sjmallett
57215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_USER
58215976Sjmallettstatic int __cvmx_shmem_devmemfd = 0;   /* fd for /dev/mem */
59215976Sjmallett#endif
60215976Sjmallett
61215976Sjmallett#define __CHECK_APP_SMDR  do { \
62215976Sjmallett                if (__smdr == NULL) { \
63215976Sjmallett                    cvmx_dprintf("cvmx_shmem: %s is not set up, Quit line %d \n", \
64215976Sjmallett                        CVMX_SHMEM_DSCPTR_NAME, __LINE__ ); \
65215976Sjmallett                    exit(-1); \
66215976Sjmallett                } \
67215976Sjmallett              }while(0)
68215976Sjmallett
69215976Sjmallett
70215976Sjmallett
71215976Sjmallett/**
72215976Sjmallett * @INTERNAL
73215976Sjmallett * Virtual sbrk, assigning virtual address in a global virtual address space.
74215976Sjmallett *
75215976Sjmallett * @param alignment   alignment requirement in bytes
76215976Sjmallett * @param size        size in bytes
77215976Sjmallett */
78215976Sjmallettstatic inline void *__cvmx_shmem_vsbrk_64(uint64_t alignment, uint64_t size)
79215976Sjmallett{
80215976Sjmallett    uint64_t nbase_64 = CAST64(__smdr->break64);
81215976Sjmallett    void *nbase = NULL;
82215976Sjmallett
83215976Sjmallett    /* Skip unaligned bytes */
84215976Sjmallett    if (nbase_64 & alignment)
85215976Sjmallett        nbase_64 += ~(nbase_64 & alignment) + 1;
86215976Sjmallett
87215976Sjmallett    if (nbase_64 + size  <  CVMX_SHMEM_VADDR64_END)
88215976Sjmallett    {
89215976Sjmallett        nbase = CASTPTR(void *, nbase_64);
90215976Sjmallett        __smdr->break64 = nbase + size;
91215976Sjmallett    }
92215976Sjmallett
93215976Sjmallett    return nbase;
94215976Sjmallett}
95215976Sjmallett
96215976Sjmallett/**
97215976Sjmallett * @INTERNAL
98215976Sjmallett * Initialize all SMDR entries, only need to be called once
99215976Sjmallett *
100215976Sjmallett * @param smdr pointer to the SMDR
101215976Sjmallett */
102215976Sjmallettstatic inline void __smdr_new(struct cvmx_shmem_smdr *smdr) {
103215976Sjmallett
104215976Sjmallett    if (smdr != NULL)
105215976Sjmallett    {
106215976Sjmallett        int i;
107215976Sjmallett
108215976Sjmallett        cvmx_spinlock_init (&smdr->lock);
109215976Sjmallett        cvmx_spinlock_lock (&smdr->lock);
110215976Sjmallett
111215976Sjmallett        for ( i = 0; i < CVMX_SHMEM_NUM_DSCPTR; i++ )
112215976Sjmallett        {
113215976Sjmallett            smdr -> shmd[i].owner = CVMX_SHMEM_OWNER_NONE;
114215976Sjmallett            smdr -> shmd[i].is_named_block = 0;
115215976Sjmallett            smdr -> shmd[i].use_count = 0;
116215976Sjmallett            smdr -> shmd[i].name = NULL;
117215976Sjmallett            smdr -> shmd[i].vaddr = NULL;
118215976Sjmallett            smdr -> shmd[i].paddr = 0;
119215976Sjmallett            smdr -> shmd[i].size = 0;
120215976Sjmallett            smdr -> shmd[i].alignment = 0;
121215976Sjmallett        };
122215976Sjmallett
123215976Sjmallett        /* Init vaddr */
124215976Sjmallett        smdr->break64 = (void *)CVMX_SHMEM_VADDR64_START;
125215976Sjmallett        cvmx_spinlock_unlock (&smdr->lock);
126215976Sjmallett    }
127215976Sjmallett
128215976Sjmallett    /* Make sure the shmem descriptor region is created */
129215976Sjmallett    __CHECK_APP_SMDR;
130215976Sjmallett};
131215976Sjmallett
132215976Sjmallett
133215976Sjmallett
134215976Sjmallett/**
135215976Sjmallett * @INTERNAL
136215976Sjmallett * Initialize __smdr pointer, if SMDR exits already. If not, create a new
137215976Sjmallett * one.  Once SMDR is created (as a bootmem named block), it is persistent.
138215976Sjmallett */
139215976Sjmallettstatic inline struct cvmx_shmem_smdr *__smdr_init()
140215976Sjmallett{
141215976Sjmallett    const cvmx_bootmem_named_block_desc_t *smdr_nblk = NULL;
142215976Sjmallett    size_t smdr_size = sizeof(*__smdr);
143215976Sjmallett    char *smdr_name = CVMX_SHMEM_DSCPTR_NAME;
144215976Sjmallett
145215976Sjmallett    __smdr = (struct cvmx_shmem_smdr *) cvmx_bootmem_alloc_named(smdr_size, 0x10000, smdr_name);
146215976Sjmallett
147215976Sjmallett    if (__smdr)
148215976Sjmallett       __smdr_new (__smdr);
149215976Sjmallett    else
150215976Sjmallett    {
151215976Sjmallett        /* Check if SMDR exists already */
152215976Sjmallett        smdr_nblk = cvmx_bootmem_find_named_block(smdr_name);
153215976Sjmallett        if (smdr_nblk)
154215976Sjmallett        {
155215976Sjmallett            __smdr = (struct cvmx_shmem_smdr *)
156215976Sjmallett            (cvmx_phys_to_ptr(smdr_nblk->base_addr));
157215976Sjmallett
158215976Sjmallett            cvmx_spinlock_lock (&__smdr->lock);
159215976Sjmallett            if (smdr_nblk->size != smdr_size)
160215976Sjmallett            {
161215976Sjmallett                cvmx_dprintf("SMDR named block is created by another "
162215976Sjmallett                    "application with different size %lu, "
163215976Sjmallett                    "expecting %lu \n",
164215976Sjmallett                    (long unsigned int)smdr_nblk->size, (long unsigned int)smdr_size);
165215976Sjmallett                __smdr = NULL;
166215976Sjmallett            }
167215976Sjmallett            cvmx_spinlock_unlock (&__smdr->lock);
168215976Sjmallett        }
169215976Sjmallett    }
170215976Sjmallett
171215976Sjmallett   if (!__smdr)
172215976Sjmallett       cvmx_dprintf("cvmx_shmem: Failed to allocate or find SMDR from bootmem \n");
173215976Sjmallett
174215976Sjmallett   return __smdr;
175215976Sjmallett};
176215976Sjmallett
177215976Sjmallett
178215976Sjmallett/**
179215976Sjmallett * @INTERNAL
180215976Sjmallett * Generic Iterator function for all SMDR entries
181215976Sjmallett *
182215976Sjmallett * @param void(*f)(dscptr) the function to be invoked for every descriptor
183215976Sjmallett * @param param
184215976Sjmallett *
185215976Sjmallett * @return the descriptor iterator stopped at.
186215976Sjmallett */
187215976Sjmallettstatic struct cvmx_shmem_dscptr *__smdr_iterator(struct cvmx_shmem_dscptr *(*f)(struct cvmx_shmem_dscptr *dscptr, void *p), void *param )
188215976Sjmallett{
189215976Sjmallett    struct cvmx_shmem_dscptr *d, *dscptr = NULL;
190215976Sjmallett    int i;
191215976Sjmallett
192215976Sjmallett    __CHECK_APP_SMDR;
193215976Sjmallett
194215976Sjmallett    for (i = 0; i < CVMX_SHMEM_NUM_DSCPTR; i++)
195215976Sjmallett    {
196215976Sjmallett        d = &__smdr->shmd[i];
197215976Sjmallett        if ((dscptr = (*f)(d, param)) != NULL)
198215976Sjmallett            break;      /* stop iteration */
199215976Sjmallett    }
200215976Sjmallett
201215976Sjmallett   return dscptr;
202215976Sjmallett}
203215976Sjmallett
204215976Sjmallett
205215976Sjmallett/**
206215976Sjmallett * @INTERNAL
207215976Sjmallett * SMDR name match functor. to be used for iterator.
208215976Sjmallett *
209215976Sjmallett * @param dscptr  descriptor passed in by the iterator
210215976Sjmallett * @param   name    string to match against
211215976Sjmallett *
212215976Sjmallett * @return !NULL   descriptor matched
213215976Sjmallett *     NULL    not match
214215976Sjmallett */
215215976Sjmallettstatic struct cvmx_shmem_dscptr *__cvmx_shmem_smdr_match_name(struct cvmx_shmem_dscptr *dscptr, void *name)
216215976Sjmallett{
217215976Sjmallett    char *name_to_match = (char *) name;
218215976Sjmallett    struct cvmx_shmem_dscptr *ret = NULL;
219215976Sjmallett
220215976Sjmallett    if (dscptr->owner == CVMX_SHMEM_OWNER_NONE)
221215976Sjmallett        return NULL;
222215976Sjmallett
223215976Sjmallett    if (strcmp(dscptr->name, name_to_match) == 0)
224215976Sjmallett        ret =  dscptr;
225215976Sjmallett
226215976Sjmallett    return ret;
227215976Sjmallett}
228215976Sjmallett
229215976Sjmallett/**
230215976Sjmallett * @INTERNAL
231215976Sjmallett * Find by name
232215976Sjmallett *
233215976Sjmallett * @param   name    string to match against
234215976Sjmallett *
235215976Sjmallett * @return !NULL    descriptor matched
236215976Sjmallett *          NULL    not match
237215976Sjmallett */
238215976Sjmallettstatic struct cvmx_shmem_dscptr *__cvmx_shmem_smdr_find_by_name(char *name)
239215976Sjmallett{
240215976Sjmallett    return __smdr_iterator( __cvmx_shmem_smdr_match_name, name);
241215976Sjmallett}
242215976Sjmallett
243215976Sjmallett/**
244215976Sjmallett * @INTERNAL
245215976Sjmallett * SMDR is free functor. to be used for iterator.
246215976Sjmallett *
247215976Sjmallett * @param dscptr  descriptor passed in by the iterator
248215976Sjmallett * @param nouse
249215976Sjmallett *
250215976Sjmallett * @return !NULL  descriptor is free
251215976Sjmallett *          NULL  descriptor is not free
252215976Sjmallett */
253215976Sjmallettstatic struct cvmx_shmem_dscptr *__cvmx_shmem_smdr_is_free(struct cvmx_shmem_dscptr* dscptr, void *nouse)
254215976Sjmallett{
255215976Sjmallett    if (dscptr->owner == CVMX_SHMEM_OWNER_NONE)
256215976Sjmallett        return dscptr;
257215976Sjmallett    else
258215976Sjmallett        return NULL;
259215976Sjmallett}
260215976Sjmallett
261215976Sjmallett/**
262215976Sjmallett * @INTERNAL
263215976Sjmallett * Search SMDR to find the first free descriptor
264215976Sjmallett *
265215976Sjmallett * @return !NULL   free descriptor found
266215976Sjmallett *     NULL    nothing found
267215976Sjmallett */
268215976Sjmallettstruct cvmx_shmem_dscptr *__cvmx_shmem_smdr_find_free_dscptr(void)
269215976Sjmallett{
270215976Sjmallett    return __smdr_iterator(__cvmx_shmem_smdr_is_free, NULL);
271215976Sjmallett}
272215976Sjmallett
273215976Sjmallett/**
274215976Sjmallett * @INTERNAL
275215976Sjmallett * free a descriptor
276215976Sjmallett *
277215976Sjmallett * @param dscptr  descriptor to be freed
278215976Sjmallett */
279215976Sjmallettstatic void __cvmx_shmem_smdr_free(struct cvmx_shmem_dscptr *dscptr)
280215976Sjmallett{
281215976Sjmallett    dscptr->owner = CVMX_SHMEM_OWNER_NONE;
282215976Sjmallett}
283215976Sjmallett
284215976Sjmallett
285215976Sjmallett/**
286215976Sjmallett * Per core shmem init function
287215976Sjmallett *
288215976Sjmallett * @return  cvmx_shmem_smdr*   pointer to __smdr
289215976Sjmallett */
290215976Sjmallettstruct cvmx_shmem_smdr *cvmx_shmem_init()
291215976Sjmallett{
292215976Sjmallett    return __smdr_init();
293215976Sjmallett}
294215976Sjmallett
295215976Sjmallett/**
296215976Sjmallett * Open shared memory based on named block
297215976Sjmallett *
298215976Sjmallett * @return  dscptr descriptor of the opened named block
299215976Sjmallett */
300215976Sjmallettstruct cvmx_shmem_dscptr *cvmx_shmem_named_block_open(char *name, uint32_t size, int oflag)
301215976Sjmallett{
302215976Sjmallett    const cvmx_bootmem_named_block_desc_t *shmem_nblk = NULL;
303215976Sjmallett    struct cvmx_shmem_dscptr *dscptr = NULL;
304215976Sjmallett    int nblk_allocated = 0; /* Assume we don't need to allocate a new
305215976Sjmallett                               bootmem block */
306215976Sjmallett    void *vaddr = NULL;
307215976Sjmallett    const uint64_t size_4k = 4*1024, size_512mb = 512*1024*1024;
308215976Sjmallett
309215976Sjmallett    __CHECK_APP_SMDR;
310215976Sjmallett
311215976Sjmallett    /* Check size, Make sure it is minimal 4K, no bigger than 512MB */
312215976Sjmallett    if (size > size_512mb) {
313215976Sjmallett        cvmx_dprintf("Shared memory size can not be bigger than 512MB \n");
314215976Sjmallett        return NULL;
315215976Sjmallett    }
316215976Sjmallett    if (size < size_4k)
317215976Sjmallett        size = size_4k;
318215976Sjmallett
319215976Sjmallett    size = __upper_power_of_two(size);
320215976Sjmallett
321215976Sjmallett    cvmx_spinlock_lock(&__smdr->lock);
322215976Sjmallett
323215976Sjmallett    shmem_nblk = cvmx_bootmem_find_named_block(name);
324215976Sjmallett    if ((shmem_nblk == NULL) &&  (oflag & CVMX_SHMEM_O_CREAT))
325215976Sjmallett    {
326215976Sjmallett       void *p;
327215976Sjmallett       /* The named block does not exist, create it if caller specifies
328215976Sjmallett          the O_CREAT flag */
329215976Sjmallett        nblk_allocated = 1;
330215976Sjmallett        p = cvmx_bootmem_alloc_named(size, size, name);
331215976Sjmallett        if (p)
332215976Sjmallett            shmem_nblk = cvmx_bootmem_find_named_block(name);
333215976Sjmallett#ifdef DEBUG
334215976Sjmallett        cvmx_dprintf("cvmx-shmem-dbg:"
335215976Sjmallett             "creating a new block %s: blk %p, shmem_nblk %p \n",
336215976Sjmallett             name, p, shmem_nblk);
337215976Sjmallett#endif
338215976Sjmallett    }
339215976Sjmallett
340215976Sjmallett    if (shmem_nblk == NULL)
341215976Sjmallett        goto err;
342215976Sjmallett
343215976Sjmallett    /* We are now holding a valid named block */
344215976Sjmallett
345215976Sjmallett    dscptr = __cvmx_shmem_smdr_find_by_name(name);
346215976Sjmallett    if (dscptr)
347215976Sjmallett    {
348215976Sjmallett        if (nblk_allocated)
349215976Sjmallett        {
350215976Sjmallett            /* name conflict between bootmem name space and SMDR name space */
351215976Sjmallett            cvmx_dprintf("cvmx-shmem: SMDR descriptor name conflict, %s \n", name);
352215976Sjmallett            goto err;
353215976Sjmallett        }
354215976Sjmallett        /* Make sure size and alignment matches with existing descriptor */
355215976Sjmallett        if ((size != dscptr->size) ||  (size != dscptr -> alignment))
356215976Sjmallett            goto err;
357215976Sjmallett    }
358215976Sjmallett    else
359215976Sjmallett    {
360215976Sjmallett        /* Create a new descriptor */
361215976Sjmallett        dscptr = __cvmx_shmem_smdr_find_free_dscptr();
362215976Sjmallett        if (dscptr)
363215976Sjmallett            goto init;
364215976Sjmallett        else
365215976Sjmallett        {
366215976Sjmallett            cvmx_dprintf("cvmx-shmem: SMDR out of descriptors \n");
367215976Sjmallett            goto err;
368215976Sjmallett        }
369215976Sjmallett    }
370215976Sjmallett
371215976Sjmallett    /* Maintain the reference count */
372215976Sjmallett    if (dscptr != NULL)
373215976Sjmallett        dscptr->use_count += 1;
374215976Sjmallett
375215976Sjmallett    cvmx_spinlock_unlock(&__smdr->lock);
376215976Sjmallett    return dscptr;
377215976Sjmallett
378215976Sjmalletterr:
379215976Sjmallett#ifdef DEBUG
380215976Sjmallett    cvmx_dprintf("cvmx-shmem-dbg: named block open failed \n");
381215976Sjmallett#endif
382215976Sjmallett
383215976Sjmallett    if (dscptr)
384215976Sjmallett        __cvmx_shmem_smdr_free(dscptr);
385215976Sjmallett    if (shmem_nblk && nblk_allocated)
386215976Sjmallett        cvmx_bootmem_free_named(name);
387215976Sjmallett    cvmx_spinlock_unlock(&__smdr->lock);
388215976Sjmallett
389215976Sjmallett    return NULL;
390215976Sjmallett
391215976Sjmallettinit:
392215976Sjmallett
393215976Sjmallett#ifdef DEBUG
394215976Sjmallett    cvmx_dprintf("cvmx-shmem-dbg: init SMDR descriptor %p \n", dscptr);
395215976Sjmallett#endif
396215976Sjmallett
397215976Sjmallett    /* Assign vaddr for single address space mapping */
398215976Sjmallett    vaddr = __cvmx_shmem_vsbrk_64(size, size);
399215976Sjmallett    if (vaddr == NULL) {
400215976Sjmallett        /* Failed to allocate virtual address, clean up */
401215976Sjmallett        goto err;
402215976Sjmallett    }
403215976Sjmallett
404215976Sjmallett#ifdef DEBUG
405215976Sjmallett    cvmx_dprintf("cmvx-shmem-dbg: allocated vaddr %p \n", vaddr);
406215976Sjmallett#endif
407215976Sjmallett    dscptr->vaddr = vaddr;
408215976Sjmallett
409215976Sjmallett    /* Store descriptor information,  name, alignment,size... */
410215976Sjmallett    dscptr->owner = cvmx_get_core_num();
411215976Sjmallett    dscptr->is_named_block = 1;
412215976Sjmallett    dscptr->use_count = 1;
413215976Sjmallett    dscptr->name =shmem_nblk->name ;
414215976Sjmallett    dscptr->paddr = shmem_nblk->base_addr;
415215976Sjmallett    dscptr->size = size;
416215976Sjmallett    dscptr->alignment = size;
417215976Sjmallett
418215976Sjmallett    /* Store permission bits */
419215976Sjmallett    if (oflag & CVMX_SHMEM_O_WRONLY)
420215976Sjmallett        dscptr->p_wronly = 1;
421215976Sjmallett    if (oflag & CVMX_SHMEM_O_RDWR)
422215976Sjmallett        dscptr->p_rdwr = 1;
423215976Sjmallett
424215976Sjmallett   cvmx_spinlock_unlock(&__smdr->lock);
425215976Sjmallett   return dscptr;
426215976Sjmallett}
427215976Sjmallett
428215976Sjmallett/**
429215976Sjmallett * @INTERNAL
430215976Sjmallett *
431215976Sjmallett *  For stand along SE application only.
432215976Sjmallett *
433215976Sjmallett *  Add TLB mapping to map the shared memory
434215976Sjmallett *
435215976Sjmallett *  @param dscptr  shared memory descriptor
436215976Sjmallett *  @param pflag   protection flags
437215976Sjmallett *
438215976Sjmallett *  @return vaddr  the virtual address mapped for the shared memory
439215976Sjmallett */
440215976Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_USER
441215976Sjmallettvoid *__cvmx_shmem_map_standalone(struct cvmx_shmem_dscptr *dscptr, int pflag)
442215976Sjmallett{
443215976Sjmallett    int free_index;
444215976Sjmallett
445215976Sjmallett    /* Find a free tlb entry */
446215976Sjmallett    free_index = cvmx_tlb_allocate_runtime_entry();
447215976Sjmallett
448215976Sjmallett    if (free_index < 0 )
449215976Sjmallett    {
450215976Sjmallett        cvmx_dprintf("cvmx-shmem: shmem_map failed, out TLB entries \n");
451215976Sjmallett        return NULL;
452215976Sjmallett    }
453215976Sjmallett
454215976Sjmallett#ifdef DEBUG
455215976Sjmallett    cvmx_dprintf("cmvx-shmem-dbg:"
456215976Sjmallett         "shmem_map TLB %d: vaddr %p paddr %lx, size %x \n",
457215976Sjmallett         free_index, dscptr->vaddr, dscptr->paddr, dscptr->size );
458215976Sjmallett#endif
459215976Sjmallett
460215976Sjmallett    cvmx_tlb_write_runtime_entry(free_index, CAST64(dscptr->vaddr),
461215976Sjmallett            dscptr->paddr, dscptr->size,
462215976Sjmallett            TLB_DIRTY | TLB_VALID | TLB_GLOBAL);
463215976Sjmallett
464215976Sjmallett    return dscptr -> vaddr;
465215976Sjmallett}
466215976Sjmallett#endif
467215976Sjmallett
468215976Sjmallett/**
469215976Sjmallett * @INTERNAL
470215976Sjmallett *
471215976Sjmallett *  For Linux user application only
472215976Sjmallett *
473215976Sjmallett *  Add mmap the shared memory
474215976Sjmallett *
475215976Sjmallett *  @param dscptr  shared memory descriptor
476215976Sjmallett *  @param pflag   protection flags
477215976Sjmallett *
478215976Sjmallett *  @return vaddr  the virtual address mapped for the shared memory
479215976Sjmallett */
480215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_USER
481215976Sjmallettstatic inline void *__cvmx_shmem_map_linux(struct cvmx_shmem_dscptr *dscptr, int pflag)
482215976Sjmallett{
483215976Sjmallett    void *vaddr = NULL;
484215976Sjmallett
485215976Sjmallett    if(__cvmx_shmem_devmemfd == 0)
486215976Sjmallett    {
487215976Sjmallett        __cvmx_shmem_devmemfd = open("/dev/mem", O_RDWR);
488215976Sjmallett        if (__cvmx_shmem_devmemfd < 0)
489215976Sjmallett        {
490215976Sjmallett            cvmx_dprintf("Failed to open /dev/mem\n");
491215976Sjmallett            exit(-1);
492215976Sjmallett        }
493215976Sjmallett    }
494215976Sjmallett
495215976Sjmallett    vaddr = mmap(dscptr->vaddr, dscptr->size, PROT_READ|PROT_WRITE,
496215976Sjmallett                 MAP_SHARED, __cvmx_shmem_devmemfd, 0);
497215976Sjmallett
498215976Sjmallett    /* Make sure the mmap maps to the same virtual address specified in
499215976Sjmallett     * descriptor
500215976Sjmallett     */
501215976Sjmallett    if ((vaddr!=NULL) && (vaddr != dscptr->vaddr))
502215976Sjmallett    {
503215976Sjmallett        munmap(vaddr, dscptr->size);
504215976Sjmallett        vaddr = NULL;
505215976Sjmallett    }
506215976Sjmallett    return vaddr;
507215976Sjmallett}
508215976Sjmallett#endif
509215976Sjmallett
510215976Sjmallett/**
511215976Sjmallett *  cvmx_shmem API
512215976Sjmallett *
513215976Sjmallett *  Add mapping for the shared memory
514215976Sjmallett *
515215976Sjmallett *  @param dscptr  shared memory descriptor
516215976Sjmallett *  @param pflag   protection flags
517215976Sjmallett *
518215976Sjmallett *  @return vaddr  the virtual address mapped for the shared memory
519215976Sjmallett */
520215976Sjmallettvoid *cvmx_shmem_map(struct cvmx_shmem_dscptr *dscptr, int pflag)
521215976Sjmallett{
522215976Sjmallett    void *vaddr = NULL;
523215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_USER
524215976Sjmallett    vaddr = __cvmx_shmem_map_linux(dscptr, pflag);
525215976Sjmallett#else
526215976Sjmallett    vaddr = __cvmx_shmem_map_standalone(dscptr, pflag);
527215976Sjmallett#endif
528215976Sjmallett    return vaddr;
529215976Sjmallett}
530215976Sjmallett
531215976Sjmallett
532215976Sjmallett/**
533215976Sjmallett * @INTERNAL
534215976Sjmallett *
535215976Sjmallett *  For Linux user application only
536215976Sjmallett *
537215976Sjmallett *  ummap the shared memory
538215976Sjmallett *
539215976Sjmallett *  @param dscptr  shared memory descriptor
540215976Sjmallett *
541215976Sjmallett */
542215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_USER
543215976Sjmallettstatic inline void __cvmx_shmem_unmap_linux(struct cvmx_shmem_dscptr* dscptr)
544215976Sjmallett{
545215976Sjmallett    if (__cvmx_shmem_devmemfd && dscptr)
546215976Sjmallett        munmap(dscptr->vaddr, dscptr->size);
547215976Sjmallett}
548215976Sjmallett#endif
549215976Sjmallett
550215976Sjmallett
551215976Sjmallett/**
552215976Sjmallett * @INTERNAL
553215976Sjmallett *
554215976Sjmallett *  For stand along SE application only.
555215976Sjmallett *
556215976Sjmallett *  ummap the shared memory
557215976Sjmallett *
558215976Sjmallett *  @param dscptr  shared memory descriptor
559215976Sjmallett *
560215976Sjmallett */
561215976Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_USER
562215976Sjmallettstatic inline void
563215976Sjmallett__cvmx_shmem_unmap_standalone(struct cvmx_shmem_dscptr *dscptr)
564215976Sjmallett{
565215976Sjmallett    int index;
566215976Sjmallett
567215976Sjmallett    index = cvmx_tlb_lookup(CAST64(dscptr->vaddr));
568215976Sjmallett
569215976Sjmallett#ifdef DEBUG
570215976Sjmallett    cvmx_dprintf("cmvx-shmem-dbg:"
571215976Sjmallett             "shmem_unmap TLB %d \n", index);
572215976Sjmallett#endif
573215976Sjmallett    cvmx_tlb_free_runtime_entry(index);
574215976Sjmallett}
575215976Sjmallett#endif
576215976Sjmallett
577215976Sjmallett/**
578215976Sjmallett *  ummap the shared memory
579215976Sjmallett *
580215976Sjmallett *  @param dscptr  shared memory descriptor
581215976Sjmallett *
582215976Sjmallett */
583215976Sjmallettvoid cvmx_shmem_unmap(struct cvmx_shmem_dscptr *dscptr)
584215976Sjmallett{
585215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_USER
586215976Sjmallett    __cvmx_shmem_unmap_linux(dscptr);
587215976Sjmallett#else
588215976Sjmallett    __cvmx_shmem_unmap_standalone(dscptr);
589215976Sjmallett#endif
590215976Sjmallett}
591215976Sjmallett
592215976Sjmallett/**
593215976Sjmallett * @INTERNAL
594215976Sjmallett *
595215976Sjmallett *  Common implementation of closing a descriptor.
596215976Sjmallett *
597215976Sjmallett *  @param dscptr  shared memory descriptor
598215976Sjmallett *  @param remove  1:  remove the descriptor and named block if this
599215976Sjmallett *                  this is the last user of the descriptor
600215976Sjmallett *             0:  do not remove
601215976Sjmallett *  @return  0:   Success
602215976Sjmallett *          !0:   Failed
603215976Sjmallett *
604215976Sjmallett */
605215976Sjmallettstatic inline int __cvmx_shmem_close_dscptr(struct cvmx_shmem_dscptr *dscptr, int remove)
606215976Sjmallett{
607215976Sjmallett    cvmx_spinlock_lock(&dscptr->lock);
608215976Sjmallett
609215976Sjmallett    if (dscptr->use_count >0)
610215976Sjmallett        dscptr->use_count-= 1;
611215976Sjmallett
612215976Sjmallett    if ((dscptr->use_count == 0) && remove)
613215976Sjmallett    {
614215976Sjmallett        /* Free this descriptor */
615215976Sjmallett        __cvmx_shmem_smdr_free(dscptr);
616215976Sjmallett
617215976Sjmallett        /* Free named block if this is the last user, and the block
618215976Sjmallett           is created by the application */
619215976Sjmallett        if (dscptr->is_named_block)
620215976Sjmallett        {
621215976Sjmallett#ifdef DEBUG
622215976Sjmallett            cvmx_dprintf("cvmx-shmem-dbg: remove named block %s \n", dscptr->name);
623215976Sjmallett#endif
624215976Sjmallett            cvmx_bootmem_phy_named_block_free(dscptr->name, 0);
625215976Sjmallett        }
626215976Sjmallett    }
627215976Sjmallett    cvmx_spinlock_unlock(&dscptr->lock);
628215976Sjmallett    return 0;
629215976Sjmallett}
630215976Sjmallett
631215976Sjmallett
632215976Sjmallett/**
633215976Sjmallett * @INTERNAL
634215976Sjmallett *
635215976Sjmallett *  For stand along SE application only.
636215976Sjmallett *
637215976Sjmallett *  close a descriptor.
638215976Sjmallett *
639215976Sjmallett *  @param dscptr  shared memory descriptor
640215976Sjmallett *  @param remove  1:  remove the descriptor and named block if this
641215976Sjmallett *                  this is the last user of the descriptor
642215976Sjmallett *             0:  do not remove
643215976Sjmallett *  @return  0:   Success
644215976Sjmallett *          !0:   Failed
645215976Sjmallett *
646215976Sjmallett */
647215976Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_USER
648215976Sjmallettstatic inline int __cvmx_shmem_close_standalone(struct cvmx_shmem_dscptr *dscptr, int remove)
649215976Sjmallett{
650215976Sjmallett    return __cvmx_shmem_close_dscptr(dscptr, remove);
651215976Sjmallett}
652215976Sjmallett#endif
653215976Sjmallett
654215976Sjmallett/**
655215976Sjmallett * @INTERNAL
656215976Sjmallett *
657215976Sjmallett *  For Linux user application only.
658215976Sjmallett *
659215976Sjmallett *  close a descriptor.
660215976Sjmallett *
661215976Sjmallett *  @param dscptr  shared memory descriptor
662215976Sjmallett *  @param remove  1:  remove the descriptor and named block if this
663215976Sjmallett *                  this is the last user of the descriptor
664215976Sjmallett *             0:  do not remove
665215976Sjmallett *  @return  0:   Success
666215976Sjmallett *          !0:   Failed
667215976Sjmallett *
668215976Sjmallett */
669215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_USER
670215976Sjmallettint __cvmx_shmem_close_linux(struct cvmx_shmem_dscptr *dscptr, int remove)
671215976Sjmallett{
672215976Sjmallett    int ret;
673215976Sjmallett    ret = __cvmx_shmem_close_dscptr(dscptr, remove);
674215976Sjmallett
675215976Sjmallett    if (ret && __cvmx_shmem_devmemfd)
676215976Sjmallett    {
677215976Sjmallett        close(__cvmx_shmem_devmemfd);
678215976Sjmallett         __cvmx_shmem_devmemfd=0;
679215976Sjmallett    }
680215976Sjmallett
681215976Sjmallett    return ret;
682215976Sjmallett
683215976Sjmallett}
684215976Sjmallett#endif
685215976Sjmallett
686215976Sjmallett/**
687215976Sjmallett *
688215976Sjmallett *  close a descriptor.
689215976Sjmallett *
690215976Sjmallett *  @param dscptr  shared memory descriptor
691215976Sjmallett *  @param remove  1:  remove the descriptor and named block if this
692215976Sjmallett *                  this is the last user of the descriptor
693215976Sjmallett *             0:  do not remove
694215976Sjmallett *  @return  0:   Success
695215976Sjmallett *          !0:   Failed
696215976Sjmallett *
697215976Sjmallett */
698215976Sjmallettint cvmx_shmem_close(struct cvmx_shmem_dscptr *dscptr, int remove)
699215976Sjmallett{
700215976Sjmallett    int ret;
701215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_USER
702215976Sjmallett    ret = __cvmx_shmem_close_linux(dscptr, remove);
703215976Sjmallett#else
704215976Sjmallett    ret = __cvmx_shmem_close_standalone(dscptr, remove);
705215976Sjmallett#endif
706215976Sjmallett    return ret;
707215976Sjmallett}
708215976Sjmallett
709215976Sjmallett#ifdef DEBUG
710215976Sjmallett/**
711215976Sjmallett * @INTERNAL
712215976Sjmallett *  SMDR non-free descriptor dump functor. to be used for iterator.
713215976Sjmallett *
714215976Sjmallett * @param dscptr  descriptor passed in by the iterator
715215976Sjmallett *
716215976Sjmallett * @return NULL  always
717215976Sjmallett */
718215976Sjmallettstatic struct cvmx_shmem_dscptr *__cvmx_shmem_smdr_display_dscptr(struct cvmx_shmem_dscptr *dscptr, void *nouse)
719215976Sjmallett{
720215976Sjmallett    if ((dscptr != NULL ) && (dscptr -> owner != CVMX_SHMEM_OWNER_NONE))
721215976Sjmallett    {
722215976Sjmallett        cvmx_dprintf("  %s: phy: %lx, size %d, alignment %lx, virt %p use_count %d\n",
723215976Sjmallett            dscptr->name, dscptr-> paddr,
724215976Sjmallett            dscptr->size, dscptr-> alignment,
725215976Sjmallett            dscptr->vaddr, dscptr->use_count);
726215976Sjmallett    }
727215976Sjmallett
728215976Sjmallett    return NULL;
729215976Sjmallett}
730215976Sjmallett#endif
731215976Sjmallett
732215976Sjmallett/**
733215976Sjmallett *  SMDR descriptor show
734215976Sjmallett *
735215976Sjmallett *  list all non-free descriptors
736215976Sjmallett */
737215976Sjmallettvoid cvmx_shmem_show(void)
738215976Sjmallett{
739215976Sjmallett    __CHECK_APP_SMDR;
740215976Sjmallett
741215976Sjmallett#ifdef DEBUG
742215976Sjmallett    cvmx_dprintf("SMDR descriptor list: \n");
743215976Sjmallett    cvmx_spinlock_lock(&__smdr->lock);
744215976Sjmallett    __smdr_iterator(__cvmx_shmem_smdr_display_dscptr, NULL);
745215976Sjmallett    cvmx_spinlock_unlock(&__smdr->lock);
746215976Sjmallett    cvmx_dprintf("\n\n");
747215976Sjmallett#endif
748215976Sjmallett}
749