|
108 | 108 | * code through spec map. This allows BPF applications to quickly fetch the |
109 | 109 | * actual value at runtime using a simple BPF-side code. |
110 | 110 | * |
111 | | - * With basics out of the way, let's go over less immeditately obvious aspects |
| 111 | + * With basics out of the way, let's go over less immediately obvious aspects |
112 | 112 | * of supporting USDTs. |
113 | 113 | * |
114 | 114 | * First, there is no special USDT BPF program type. It is actually just |
|
189 | 189 | #define USDT_NOTE_TYPE 3 |
190 | 190 | #define USDT_NOTE_NAME "stapsdt" |
191 | 191 |
|
192 | | -/* should match exactly enum __bpf_usdt_arg_type from bpf_usdt.bpf.h */ |
| 192 | +/* should match exactly enum __bpf_usdt_arg_type from usdt.bpf.h */ |
193 | 193 | enum usdt_arg_type { |
194 | 194 | USDT_ARG_CONST, |
195 | 195 | USDT_ARG_REG, |
196 | 196 | USDT_ARG_REG_DEREF, |
197 | 197 | }; |
198 | 198 |
|
199 | | -/* should match exactly struct __bpf_usdt_arg_spec from bpf_usdt.bpf.h */ |
| 199 | +/* should match exactly struct __bpf_usdt_arg_spec from usdt.bpf.h */ |
200 | 200 | struct usdt_arg_spec { |
201 | 201 | __u64 val_off; |
202 | 202 | enum usdt_arg_type arg_type; |
@@ -328,9 +328,9 @@ static int sanity_check_usdt_elf(Elf *elf, const char *path) |
328 | 328 | return -EBADF; |
329 | 329 | } |
330 | 330 |
|
331 | | -#if __BYTE_ORDER == __LITTLE_ENDIAN |
| 331 | +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ |
332 | 332 | endianness = ELFDATA2LSB; |
333 | | -#elif __BYTE_ORDER == __BIG_ENDIAN |
| 333 | +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
334 | 334 | endianness = ELFDATA2MSB; |
335 | 335 | #else |
336 | 336 | # error "Unrecognized __BYTE_ORDER__" |
@@ -843,7 +843,7 @@ static int bpf_link_usdt_detach(struct bpf_link *link) |
843 | 843 | sizeof(*new_free_ids)); |
844 | 844 | /* If we couldn't resize free_spec_ids, we'll just leak |
845 | 845 | * a bunch of free IDs; this is very unlikely to happen and if |
846 | | - * system is so exausted on memory, it's the least of user's |
| 846 | + * system is so exhausted on memory, it's the least of user's |
847 | 847 | * concerns, probably. |
848 | 848 | * So just do our best here to return those IDs to usdt_manager. |
849 | 849 | */ |
@@ -1269,6 +1269,61 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec |
1269 | 1269 | return len; |
1270 | 1270 | } |
1271 | 1271 |
|
| 1272 | +#elif defined(__s390x__) |
| 1273 | + |
| 1274 | +/* Do not support __s390__ for now, since user_pt_regs is broken with -m31. */ |
| 1275 | + |
| 1276 | +static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg) |
| 1277 | +{ |
| 1278 | + unsigned int reg; |
| 1279 | + int arg_sz, len; |
| 1280 | + long off; |
| 1281 | + |
| 1282 | + if (sscanf(arg_str, " %d @ %ld ( %%r%u ) %n", &arg_sz, &off, ®, &len) == 3) { |
| 1283 | + /* Memory dereference case, e.g., -2@-28(%r15) */ |
| 1284 | + arg->arg_type = USDT_ARG_REG_DEREF; |
| 1285 | + arg->val_off = off; |
| 1286 | + if (reg > 15) { |
| 1287 | + pr_warn("usdt: unrecognized register '%%r%u'\n", reg); |
| 1288 | + return -EINVAL; |
| 1289 | + } |
| 1290 | + arg->reg_off = offsetof(user_pt_regs, gprs[reg]); |
| 1291 | + } else if (sscanf(arg_str, " %d @ %%r%u %n", &arg_sz, ®, &len) == 2) { |
| 1292 | + /* Register read case, e.g., -8@%r0 */ |
| 1293 | + arg->arg_type = USDT_ARG_REG; |
| 1294 | + arg->val_off = 0; |
| 1295 | + if (reg > 15) { |
| 1296 | + pr_warn("usdt: unrecognized register '%%r%u'\n", reg); |
| 1297 | + return -EINVAL; |
| 1298 | + } |
| 1299 | + arg->reg_off = offsetof(user_pt_regs, gprs[reg]); |
| 1300 | + } else if (sscanf(arg_str, " %d @ %ld %n", &arg_sz, &off, &len) == 2) { |
| 1301 | + /* Constant value case, e.g., 4@71 */ |
| 1302 | + arg->arg_type = USDT_ARG_CONST; |
| 1303 | + arg->val_off = off; |
| 1304 | + arg->reg_off = 0; |
| 1305 | + } else { |
| 1306 | + pr_warn("usdt: unrecognized arg #%d spec '%s'\n", arg_num, arg_str); |
| 1307 | + return -EINVAL; |
| 1308 | + } |
| 1309 | + |
| 1310 | + arg->arg_signed = arg_sz < 0; |
| 1311 | + if (arg_sz < 0) |
| 1312 | + arg_sz = -arg_sz; |
| 1313 | + |
| 1314 | + switch (arg_sz) { |
| 1315 | + case 1: case 2: case 4: case 8: |
| 1316 | + arg->arg_bitshift = 64 - arg_sz * 8; |
| 1317 | + break; |
| 1318 | + default: |
| 1319 | + pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n", |
| 1320 | + arg_num, arg_str, arg_sz); |
| 1321 | + return -EINVAL; |
| 1322 | + } |
| 1323 | + |
| 1324 | + return len; |
| 1325 | +} |
| 1326 | + |
1272 | 1327 | #else |
1273 | 1328 |
|
1274 | 1329 | static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg) |
|
0 commit comments