• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/trace_processor/types/gfp_flags.h"
18 
19 #include <array>
20 
21 namespace perfetto {
22 namespace trace_processor {
23 
24 namespace {
25 
26 struct Flag {
27   uint64_t mask;
28   const char* flag_name;
29 };
30 
31 using FlagArray = std::array<Flag, 37>;
32 
33 constexpr FlagArray v3_4 = {
34     {{(((0x10u) | (0x40u) | (0x80u) | (0x20000u) | (0x02u) | (0x08u)) |
35        (0x4000u) | (0x10000u) | (0x1000u) | (0x200u) | (0x400000u)),
36       "GFP_TRANSHUGE"},
37      {((0x10u) | (0x40u) | (0x80u) | (0x20000u) | (0x02u) | (0x08u)),
38       "GFP_HIGHUSER_MOVABLE"},
39      {((0x10u) | (0x40u) | (0x80u) | (0x20000u) | (0x02u)), "GFP_HIGHUSER"},
40      {((0x10u) | (0x40u) | (0x80u) | (0x20000u)), "GFP_USER"},
41      {((0x10u) | (0x40u) | (0x80u) | (0x80000u)), "GFP_TEMPORARY"},
42      {((0x10u) | (0x40u) | (0x80u)), "GFP_KERNEL"},
43      {((0x10u) | (0x40u)), "GFP_NOFS"},
44      {((0x20u)), "GFP_ATOMIC"},
45      {((0x10u)), "GFP_NOIO"},
46      {(0x20u), "GFP_HIGH"},
47      {(0x10u), "GFP_WAIT"},
48      {(0x40u), "GFP_IO"},
49      {(0x100u), "GFP_COLD"},
50      {(0x200u), "GFP_NOWARN"},
51      {(0x400u), "GFP_REPEAT"},
52      {(0x800u), "GFP_NOFAIL"},
53      {(0x1000u), "GFP_NORETRY"},
54      {(0x4000u), "GFP_COMP"},
55      {(0x8000u), "GFP_ZERO"},
56      {(0x10000u), "GFP_NOMEMALLOC"},
57      {(0x20000u), "GFP_HARDWALL"},
58      {(0x40000u), "GFP_THISNODE"},
59      {(0x80000u), "GFP_RECLAIMABLE"},
60      {(0x08u), "GFP_MOVABLE"},
61      {(0), "GFP_NOTRACK"},
62      {(0x400000u), "GFP_NO_KSWAPD"},
63      {(0x800000u), "GFP_OTHER_NODE"},
64      {0, nullptr}}};
65 
66 constexpr FlagArray v3_10 = {
67     {{(((0x10u) | (0x40u) | (0x80u) | (0x20000u) | (0x02u) | (0x08u)) |
68        (0x4000u) | (0x10000u) | (0x1000u) | (0x200u) | (0x400000u)),
69       "GFP_TRANSHUGE"},
70      {((0x10u) | (0x40u) | (0x80u) | (0x20000u) | (0x02u) | (0x08u)),
71       "GFP_HIGHUSER_MOVABLE"},
72      {((0x10u) | (0x40u) | (0x80u) | (0x20000u) | (0x02u)), "GFP_HIGHUSER"},
73      {((0x10u) | (0x40u) | (0x80u) | (0x20000u)), "GFP_USER"},
74      {((0x10u) | (0x40u) | (0x80u) | (0x80000u)), "GFP_TEMPORARY"},
75      {((0x10u) | (0x40u) | (0x80u)), "GFP_KERNEL"},
76      {((0x10u) | (0x40u)), "GFP_NOFS"},
77      {((0x20u)), "GFP_ATOMIC"},
78      {((0x10u)), "GFP_NOIO"},
79      {(0x20u), "GFP_HIGH"},
80      {(0x10u), "GFP_WAIT"},
81      {(0x40u), "GFP_IO"},
82      {(0x100u), "GFP_COLD"},
83      {(0x200u), "GFP_NOWARN"},
84      {(0x400u), "GFP_REPEAT"},
85      {(0x800u), "GFP_NOFAIL"},
86      {(0x1000u), "GFP_NORETRY"},
87      {(0x4000u), "GFP_COMP"},
88      {(0x8000u), "GFP_ZERO"},
89      {(0x10000u), "GFP_NOMEMALLOC"},
90      {(0x2000u), "GFP_MEMALLOC"},
91      {(0x20000u), "GFP_HARDWALL"},
92      {(0x40000u), "GFP_THISNODE"},
93      {(0x80000u), "GFP_RECLAIMABLE"},
94      {(0x100000u), "GFP_KMEMCG"},
95      {(0x08u), "GFP_MOVABLE"},
96      {(0x200000u), "GFP_NOTRACK"},
97      {(0x400000u), "GFP_NO_KSWAPD"},
98      {(0x800000u), "GFP_OTHER_NODE"},
99      {0, nullptr}}};
100 
101 constexpr FlagArray v4_4 = {
102     {{(((((((0x400000u | 0x2000000u)) | (0x40u) | (0x80u) | (0x20000u)) |
103           (0x02u)) |
104          (0x08u)) |
105         (0x4000u) | (0x10000u) | (0x1000u) | (0x200u)) &
106        ~(0x2000000u)),
107       "GFP_TRANSHUGE"},
108      {(((((0x400000u | 0x2000000u)) | (0x40u) | (0x80u) | (0x20000u)) |
109         (0x02u)) |
110        (0x08u)),
111       "GFP_HIGHUSER_MOVABLE"},
112      {((((0x400000u | 0x2000000u)) | (0x40u) | (0x80u) | (0x20000u)) | (0x02u)),
113       "GFP_HIGHUSER"},
114      {(((0x400000u | 0x2000000u)) | (0x40u) | (0x80u) | (0x20000u)),
115       "GFP_USER"},
116      {(((0x400000u | 0x2000000u)) | (0x40u) | (0x80u) | (0x10u)),
117       "GFP_TEMPORARY"},
118      {(((0x400000u | 0x2000000u)) | (0x40u) | (0x80u)), "GFP_KERNEL"},
119      {(((0x400000u | 0x2000000u)) | (0x40u)), "GFP_NOFS"},
120      {((0x20u) | (0x80000u) | (0x2000000u)), "GFP_ATOMIC"},
121      {(((0x400000u | 0x2000000u))), "GFP_NOIO"},
122      {(0x20u), "GFP_HIGH"},
123      {(0x80000u), "GFP_ATOMIC"},
124      {(0x40u), "GFP_IO"},
125      {(0x100u), "GFP_COLD"},
126      {(0x200u), "GFP_NOWARN"},
127      {(0x400u), "GFP_REPEAT"},
128      {(0x800u), "GFP_NOFAIL"},
129      {(0x1000u), "GFP_NORETRY"},
130      {(0x4000u), "GFP_COMP"},
131      {(0x8000u), "GFP_ZERO"},
132      {(0x10000u), "GFP_NOMEMALLOC"},
133      {(0x2000u), "GFP_MEMALLOC"},
134      {(0x20000u), "GFP_HARDWALL"},
135      {(0x40000u), "GFP_THISNODE"},
136      {(0x10u), "GFP_RECLAIMABLE"},
137      {(0x08u), "GFP_MOVABLE"},
138      {(0x200000u), "GFP_NOTRACK"},
139      {(0x400000u), "GFP_DIRECT_RECLAIM"},
140      {(0x2000000u), "GFP_KSWAPD_RECLAIM"},
141      {(0x800000u), "GFP_OTHER_NODE"},
142      {0, nullptr}}};
143 
144 constexpr FlagArray v4_14 = {
145     {{((((((((0x400000u | 0x1000000u)) | (0x40u) | (0x80u) | (0x20000u)) |
146            (0x02u)) |
147           (0x08u)) |
148          (0x4000u) | (0x10000u) | (0x200u)) &
149         ~((0x400000u | 0x1000000u))) |
150        (0x400000u)),
151       "GFP_TRANSHUGE"},
152      {(((((((0x400000u | 0x1000000u)) | (0x40u) | (0x80u) | (0x20000u)) |
153           (0x02u)) |
154          (0x08u)) |
155         (0x4000u) | (0x10000u) | (0x200u)) &
156        ~((0x400000u | 0x1000000u))),
157       "GFP_TRANSHUGE_LIGHT"},
158      {(((((0x400000u | 0x1000000u)) | (0x40u) | (0x80u) | (0x20000u)) |
159         (0x02u)) |
160        (0x08u)),
161       "GFP_HIGHUSER_MOVABLE"},
162      {((((0x400000u | 0x1000000u)) | (0x40u) | (0x80u) | (0x20000u)) | (0x02u)),
163       "GFP_HIGHUSER"},
164      {(((0x400000u | 0x1000000u)) | (0x40u) | (0x80u) | (0x20000u)),
165       "GFP_USER"},
166      {((((0x400000u | 0x1000000u)) | (0x40u) | (0x80u)) | (0x100000u)),
167       "GFP_KERNEL_ACCOUNT"},
168      {(((0x400000u | 0x1000000u)) | (0x40u) | (0x80u)), "GFP_KERNEL"},
169      {(((0x400000u | 0x1000000u)) | (0x40u)), "GFP_NOFS"},
170      {((0x20u) | (0x80000u) | (0x1000000u)), "GFP_ATOMIC"},
171      {(((0x400000u | 0x1000000u))), "GFP_NOIO"},
172      {((0x1000000u)), "GFP_NOWAIT"},
173      {(0x01u), "GFP_DMA"},
174      {(0x02u), "__GFP_HIGHMEM"},
175      {(0x04u), "GFP_DMA32"},
176      {(0x20u), "__GFP_HIGH"},
177      {(0x80000u), "__GFP_ATOMIC"},
178      {(0x40u), "__GFP_IO"},
179      {(0x80u), "__GFP_FS"},
180      {(0x100u), "__GFP_COLD"},
181      {(0x200u), "__GFP_NOWARN"},
182      {(0x400u), "__GFP_RETRY_MAYFAIL"},
183      {(0x800u), "__GFP_NOFAIL"},
184      {(0x1000u), "__GFP_NORETRY"},
185      {(0x4000u), "__GFP_COMP"},
186      {(0x8000u), "__GFP_ZERO"},
187      {(0x10000u), "__GFP_NOMEMALLOC"},
188      {(0x2000u), "__GFP_MEMALLOC"},
189      {(0x20000u), "__GFP_HARDWALL"},
190      {(0x40000u), "__GFP_THISNODE"},
191      {(0x10u), "__GFP_RECLAIMABLE"},
192      {(0x08u), "__GFP_MOVABLE"},
193      {(0x100000u), "__GFP_ACCOUNT"},
194      {(0x800000u), "__GFP_WRITE"},
195      {((0x400000u | 0x1000000u)), "__GFP_RECLAIM"},
196      {(0x400000u), "__GFP_DIRECT_RECLAIM"},
197      {(0x1000000u), "__GFP_KSWAPD_RECLAIM"},
198      {0, nullptr}}};
199 
200 // Get the bitmask closest to the kernel version. For versions less than 3.4
201 // and greater than 4.14 this may end up being inaccurate.
GetBitmaskVersion(VersionNumber version=VersionNumber{4, 4})202 const FlagArray* GetBitmaskVersion(VersionNumber version = VersionNumber{4,
203                                                                          4}) {
204   if (version < VersionNumber{3, 10}) {
205     return &v3_4;
206   } else if (version >= VersionNumber{3, 10} && version < VersionNumber{4, 4}) {
207     return &v3_10;
208   } else if (version >= VersionNumber{4, 4} && version < VersionNumber{4, 14}) {
209     return &v4_4;
210   } else {  // version >= 4.14
211     // TODO(hjd): Add newer kernel versions once we have access to them.
212     return &v4_14;
213   }
214 }
215 }  // namespace
216 
WriteGfpFlag(uint64_t value,std::optional<VersionNumber> version,base::StringWriter * writer)217 void WriteGfpFlag(uint64_t value,
218                   std::optional<VersionNumber> version,
219                   base::StringWriter* writer) {
220   // On all kernel versions if this flag is not set, return GFP_NOWAIT.
221   if (value == 0) {
222     writer->AppendString("GFP_NOWAIT");
223     return;
224   }
225 
226   std::string result;
227   const FlagArray* bitmasks = version.has_value()
228                                   ? GetBitmaskVersion(version.value())
229                                   : GetBitmaskVersion();
230 
231   // Based on trace_print_flags_seq() in the kernel.
232   size_t i = 0;
233   while (bitmasks->at(i).flag_name != nullptr) {
234     size_t current = i++;
235     uint64_t mask = bitmasks->at(current).mask;
236     const char* str = bitmasks->at(current).flag_name;
237 
238     if ((value & mask) != mask)
239       continue;
240     value &= ~mask;
241 
242     result += str;
243     result += "|";
244   }
245 
246   // Add any leftover flags.
247   if (value) {
248     writer->AppendString(result.c_str(), result.size());
249     writer->AppendString("0x", 2);
250     writer->AppendHexInt(value);
251   } else {
252     writer->AppendString(result.c_str(), result.size() - 1);
253   }
254 }
255 
256 }  // namespace trace_processor
257 }  // namespace perfetto
258