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