crypto-native: fix CPU detection for SHA2 code
[vpp.git] / src / vppinfra / linux / sysfs.c
1 /*
2  * Copyright (c) 2017 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 <vppinfra/clib.h>
17 #include <vppinfra/clib_error.h>
18 #include <vppinfra/format.h>
19 #include <vppinfra/bitmap.h>
20
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <dirent.h>
25
26 __clib_export clib_error_t *
27 clib_sysfs_write (char *file_name, char *fmt, ...)
28 {
29   u8 *s;
30   int fd;
31   clib_error_t *error = 0;
32
33   fd = open (file_name, O_WRONLY);
34   if (fd < 0)
35     return clib_error_return_unix (0, "open `%s'", file_name);
36
37   va_list va;
38   va_start (va, fmt);
39   s = va_format (0, fmt, &va);
40   va_end (va);
41
42   if (write (fd, s, vec_len (s)) < 0)
43     error = clib_error_return_unix (0, "write `%s'", file_name);
44
45   vec_free (s);
46   close (fd);
47   return error;
48 }
49
50 __clib_export clib_error_t *
51 clib_sysfs_read (char *file_name, char *fmt, ...)
52 {
53   unformat_input_t input;
54   u8 *s = 0;
55   int fd;
56   ssize_t sz;
57   uword result;
58
59   fd = open (file_name, O_RDONLY);
60   if (fd < 0)
61     return clib_error_return_unix (0, "open `%s'", file_name);
62
63   vec_validate (s, 4095);
64
65   sz = read (fd, s, vec_len (s));
66   if (sz < 0)
67     {
68       close (fd);
69       vec_free (s);
70       return clib_error_return_unix (0, "read `%s'", file_name);
71     }
72
73   vec_set_len (s, sz);
74   unformat_init_vector (&input, s);
75
76   va_list va;
77   va_start (va, fmt);
78   result = va_unformat (&input, fmt, &va);
79   va_end (va);
80
81   vec_free (s);
82   close (fd);
83
84   if (result == 0)
85     return clib_error_return (0, "unformat error");
86
87   return 0;
88 }
89
90
91 clib_error_t *
92 clib_sysfs_set_nr_hugepages (int numa_node, int log2_page_size, int nr)
93 {
94   clib_error_t *error = 0;
95   struct stat sb;
96   u8 *p = 0;
97   uword page_size;
98
99   if (log2_page_size == 0)
100     log2_page_size = min_log2 (clib_mem_get_default_hugepage_size ());
101
102   page_size = 1ULL << (log2_page_size - 10);
103
104   p = format (p, "/sys/devices/system/node/node%u%c", numa_node, 0);
105
106   if (stat ((char *) p, &sb) == 0)
107     {
108       if (S_ISDIR (sb.st_mode) == 0)
109         {
110           error = clib_error_return (0, "'%s' is not directory", p);
111           goto done;
112         }
113     }
114   else if (numa_node == 0)
115     {
116       vec_reset_length (p);
117       p = format (p, "/sys/kernel/mm%c", 0);
118       if (stat ((char *) p, &sb) < 0 || S_ISDIR (sb.st_mode) == 0)
119         {
120           error = clib_error_return (0, "'%s' does not exist or it is not "
121                                      "directory", p);
122           goto done;
123         }
124     }
125   else
126     {
127       error = clib_error_return (0, "'%s' does not exist", p);
128       goto done;
129     }
130
131   vec_dec_len (p, 1);
132   p = format (p, "/hugepages/hugepages-%ukB/nr_hugepages%c", page_size, 0);
133   clib_sysfs_write ((char *) p, "%d", nr);
134
135 done:
136   vec_free (p);
137   return error;
138 }
139
140
141 static clib_error_t *
142 clib_sysfs_get_xxx_hugepages (char *type, int numa_node,
143                               int log2_page_size, int *val)
144 {
145   clib_error_t *error = 0;
146   struct stat sb;
147   u8 *p = 0;
148
149   uword page_size;
150
151   if (log2_page_size == 0)
152     log2_page_size = min_log2 (clib_mem_get_default_hugepage_size ());
153
154   page_size = 1ULL << (log2_page_size - 10);
155
156
157   p = format (p, "/sys/devices/system/node/node%u%c", numa_node, 0);
158
159   if (stat ((char *) p, &sb) == 0)
160     {
161       if (S_ISDIR (sb.st_mode) == 0)
162         {
163           error = clib_error_return (0, "'%s' is not directory", p);
164           goto done;
165         }
166     }
167   else if (numa_node == 0)
168     {
169       vec_reset_length (p);
170       p = format (p, "/sys/kernel/mm%c", 0);
171       if (stat ((char *) p, &sb) < 0 || S_ISDIR (sb.st_mode) == 0)
172         {
173           error = clib_error_return (0, "'%s' does not exist or it is not "
174                                      "directory", p);
175           goto done;
176         }
177     }
178   else
179     {
180       error = clib_error_return (0, "'%s' does not exist", p);
181       goto done;
182     }
183
184   vec_dec_len (p, 1);
185   p = format (p, "/hugepages/hugepages-%ukB/%s_hugepages%c", page_size,
186               type, 0);
187   error = clib_sysfs_read ((char *) p, "%d", val);
188
189 done:
190   vec_free (p);
191   return error;
192 }
193
194 clib_error_t *
195 clib_sysfs_get_free_hugepages (int numa_node, int log2_page_size, int *v)
196 {
197   return clib_sysfs_get_xxx_hugepages ("free", numa_node, log2_page_size, v);
198 }
199
200 clib_error_t *
201 clib_sysfs_get_nr_hugepages (int numa_node, int log2_page_size, int *v)
202 {
203   return clib_sysfs_get_xxx_hugepages ("nr", numa_node, log2_page_size, v);
204 }
205
206 clib_error_t *
207 clib_sysfs_get_surplus_hugepages (int numa_node, int log2_page_size, int *v)
208 {
209   return clib_sysfs_get_xxx_hugepages ("surplus", numa_node, log2_page_size,
210                                        v);
211 }
212
213 clib_error_t *
214 clib_sysfs_prealloc_hugepages (int numa_node, int log2_page_size, int nr)
215 {
216   clib_error_t *error = 0;
217   int n, needed;
218   uword page_size;
219
220   if (log2_page_size == 0)
221     log2_page_size = min_log2 (clib_mem_get_default_hugepage_size ());
222
223   page_size = 1ULL << (log2_page_size - 10);
224
225   error = clib_sysfs_get_free_hugepages (numa_node, log2_page_size, &n);
226   if (error)
227     return error;
228   needed = nr - n;
229   if (needed <= 0)
230     return 0;
231
232   error = clib_sysfs_get_nr_hugepages (numa_node, log2_page_size, &n);
233   if (error)
234     return error;
235   clib_warning ("pre-allocating %u additional %uK hugepages on numa node %u",
236                 needed, page_size, numa_node);
237   return clib_sysfs_set_nr_hugepages (numa_node, log2_page_size, n + needed);
238 }
239
240 __clib_export clib_bitmap_t *
241 clib_sysfs_read_bitmap (char *fmt, ...)
242 {
243   FILE *fp;
244   uword *r = 0;
245   va_list va;
246   u8 *filename;
247
248   va_start (va, fmt);
249   filename = va_format (0, fmt, &va);
250   va_end (va);
251   vec_add1 (filename, 0);
252
253   fp = fopen ((char *) filename, "r");
254   vec_free (filename);
255
256   if (fp != NULL)
257     {
258       u8 *buffer = 0;
259       vec_validate (buffer, 256 - 1);
260       if (fgets ((char *) buffer, 256, fp))
261         {
262           unformat_input_t in;
263           unformat_init_string (&in, (char *) buffer,
264                                 strlen ((char *) buffer));
265           if (unformat (&in, "%U", unformat_bitmap_list, &r) != 1)
266             clib_warning ("unformat_bitmap_list failed");
267           unformat_free (&in);
268         }
269       vec_free (buffer);
270       fclose (fp);
271     }
272   return r;
273 }
274
275 /*
276  * fd.io coding-style-patch-verification: ON
277  *
278  * Local Variables:
279  * eval: (c-set-style "gnu")
280  * End:
281  */