LCOV - code coverage report
Current view: top level - vlib - physmem.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 51 76 67.1 %
Date: 2023-10-26 01:39:38 Functions: 8 9 88.9 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2018 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #include <unistd.h>
      17             : #include <sys/types.h>
      18             : #include <sys/mount.h>
      19             : #include <sys/mman.h>
      20             : #include <fcntl.h>
      21             : #include <sys/stat.h>
      22             : #include <unistd.h>
      23             : 
      24             : #include <vppinfra/clib.h>
      25             : #include <vppinfra/linux/sysfs.h>
      26             : #include <vlib/vlib.h>
      27             : #include <vlib/physmem.h>
      28             : #include <vlib/unix/unix.h>
      29             : #include <vlib/pci/pci.h>
      30             : #include <vlib/linux/vfio.h>
      31             : 
      32             : #if defined(__x86_64__) && !defined(CLIB_SANITIZE_ADDR)
      33             : /* we keep physmem in low 38 bits of VA address space as some
      34             :    IOMMU implamentation cannot map above that range */
      35             : #define VLIB_PHYSMEM_DEFAULT_BASE_ADDDR         (1ULL << 36)
      36             : #else
      37             : /* let kernel decide */
      38             : #define VLIB_PHYSMEM_DEFAULT_BASE_ADDDR         0
      39             : #endif
      40             : 
      41             : clib_error_t *
      42        2300 : vlib_physmem_shared_map_create (vlib_main_t * vm, char *name, uword size,
      43             :                                 u32 log2_page_sz, u32 numa_node,
      44             :                                 u32 * map_index)
      45             : {
      46        2300 :   clib_pmalloc_main_t *pm = vm->physmem_main.pmalloc_main;
      47        2300 :   vlib_physmem_main_t *vpm = &vm->physmem_main;
      48             :   vlib_physmem_map_t *map;
      49             :   clib_pmalloc_arena_t *a;
      50        2300 :   clib_error_t *error = 0;
      51             :   void *va;
      52             :   uword i;
      53             : 
      54        2300 :   va = clib_pmalloc_create_shared_arena (pm, name, size, log2_page_sz,
      55             :                                          numa_node);
      56             : 
      57        2300 :   if (va == 0)
      58        1725 :     return clib_error_return (0, "%U", format_clib_error,
      59             :                               clib_pmalloc_last_error (pm));
      60             : 
      61         575 :   a = clib_pmalloc_get_arena (pm, va);
      62             : 
      63         575 :   pool_get (vpm->maps, map);
      64         575 :   *map_index = map->index = map - vpm->maps;
      65         575 :   map->base = va;
      66         575 :   map->fd = a->fd;
      67         575 :   map->n_pages = a->n_pages * a->subpages_per_page;
      68         575 :   map->log2_page_size = a->log2_subpage_sz;
      69         575 :   map->numa_node = a->numa_node;
      70             : 
      71        9775 :   for (i = 0; i < a->n_pages; i++)
      72             :     {
      73             :       uword pa =
      74        9200 :         clib_pmalloc_get_pa (pm, (u8 *) va + (i << a->log2_subpage_sz));
      75             : 
      76             :       /* maybe iova */
      77        9200 :       if (pa == 0)
      78           0 :         pa = pointer_to_uword (va);
      79             : 
      80        9200 :       vec_add1 (map->page_table, pa);
      81             :     }
      82             : 
      83         575 :   return error;
      84             : }
      85             : 
      86             : vlib_physmem_map_t *
      87        1157 : vlib_physmem_get_map (vlib_main_t * vm, u32 index)
      88             : {
      89        1157 :   vlib_physmem_main_t *vpm = &vm->physmem_main;
      90        1157 :   return pool_elt_at_index (vpm->maps, index);
      91             : }
      92             : 
      93             : clib_error_t *
      94         575 : vlib_physmem_init (vlib_main_t * vm)
      95             : {
      96         575 :   vlib_physmem_main_t *vpm = &vm->physmem_main;
      97         575 :   clib_error_t *error = 0;
      98         575 :   u64 *pt = 0;
      99             :   void *p;
     100             : 
     101             :   /* check if pagemap is accessible */
     102         575 :   pt = clib_mem_vm_get_paddr (&pt, min_log2 (sysconf (_SC_PAGESIZE)), 1);
     103         575 :   if (pt && pt[0])
     104         575 :     vpm->flags |= VLIB_PHYSMEM_MAIN_F_HAVE_PAGEMAP;
     105         575 :   vec_free (pt);
     106             : 
     107         575 :   if ((error = linux_vfio_init (vm)))
     108           0 :     return error;
     109             : 
     110         575 :   p = clib_mem_alloc_aligned (sizeof (clib_pmalloc_main_t),
     111             :                               CLIB_CACHE_LINE_BYTES);
     112         575 :   memset (p, 0, sizeof (clib_pmalloc_main_t));
     113         575 :   vpm->pmalloc_main = (clib_pmalloc_main_t *) p;
     114             : 
     115         575 :   if (vpm->base_addr == 0)
     116         575 :     vpm->base_addr = VLIB_PHYSMEM_DEFAULT_BASE_ADDDR;
     117             : 
     118         575 :   clib_pmalloc_init (vpm->pmalloc_main, vpm->base_addr, vpm->max_size);
     119             : 
     120             :   /* update base_addr and max_size per actual allocation */
     121         575 :   vpm->base_addr = (uword) vpm->pmalloc_main->base;
     122         575 :   vpm->max_size = (uword) vpm->pmalloc_main->max_pages <<
     123         575 :     vpm->pmalloc_main->def_log2_page_sz;
     124             : 
     125         575 :   return error;
     126             : }
     127             : 
     128             : static clib_error_t *
     129           0 : show_physmem (vlib_main_t * vm,
     130             :               unformat_input_t * input, vlib_cli_command_t * cmd)
     131             : {
     132           0 :   vlib_physmem_main_t *vpm = &vm->physmem_main;
     133           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     134           0 :   u32 verbose = 0, map = 0;
     135             : 
     136           0 :   if (unformat_user (input, unformat_line_input, line_input))
     137             :     {
     138           0 :       while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     139             :         {
     140           0 :           if (unformat (line_input, "verbose"))
     141           0 :             verbose = 1;
     142           0 :           else if (unformat (line_input, "v"))
     143           0 :             verbose = 1;
     144           0 :           else if (unformat (line_input, "detail"))
     145           0 :             verbose = 2;
     146           0 :           else if (unformat (line_input, "d"))
     147           0 :             verbose = 2;
     148           0 :           else if (unformat (line_input, "map"))
     149           0 :             map = 1;
     150             :           else
     151           0 :             break;
     152             :         }
     153           0 :       unformat_free (line_input);
     154             :     }
     155             : 
     156           0 :   if (map)
     157           0 :     vlib_cli_output (vm, " %U", format_pmalloc_map, vpm->pmalloc_main);
     158             :   else
     159           0 :     vlib_cli_output (vm, " %U", format_pmalloc, vpm->pmalloc_main, verbose);
     160             : 
     161           0 :   return 0;
     162             : }
     163             : 
     164             : /* *INDENT-OFF* */
     165      285289 : VLIB_CLI_COMMAND (show_physmem_command, static) = {
     166             :   .path = "show physmem",
     167             :   .short_help = "show physmem [verbose | detail | map]",
     168             :   .function = show_physmem,
     169             : };
     170             : /* *INDENT-ON* */
     171             : 
     172             : static clib_error_t *
     173         575 : vlib_physmem_config (vlib_main_t * vm, unformat_input_t * input)
     174             : {
     175         575 :   vlib_physmem_main_t *vpm = &vm->physmem_main;
     176             : 
     177        1150 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     178             :     {
     179         575 :       if (unformat (input, "base-addr 0x%lx", &vpm->base_addr))
     180             :         ;
     181         575 :       else if (unformat (input, "max-size %U",
     182             :                          unformat_memory_size, &vpm->max_size))
     183             :         ;
     184             :       else
     185           0 :         return unformat_parse_error (input);
     186             :     }
     187             : 
     188         575 :   unformat_free (input);
     189         575 :   return 0;
     190             : }
     191             : 
     192        7514 : VLIB_EARLY_CONFIG_FUNCTION (vlib_physmem_config, "physmem");
     193             : 
     194             : /*
     195             :  * fd.io coding-style-patch-verification: ON
     196             :  *
     197             :  * Local Variables:
     198             :  * eval: (c-set-style "gnu")
     199             :  * End:
     200             :  */

Generated by: LCOV version 1.14