Merge branch 'perf/urgent' into perf/core, to pick up fixes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
@@ -632,6 +632,8 @@ struct kvm_ppc_cpu_char {
|
||||
#define KVM_REG_PPC_TIDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbc)
|
||||
#define KVM_REG_PPC_PSSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbd)
|
||||
|
||||
#define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe)
|
||||
|
||||
/* Transactional Memory checkpointed state:
|
||||
* This is all GPRs, all VSX regs and a subset of SPRs
|
||||
*/
|
||||
|
||||
@@ -1,412 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* S390 version
|
||||
*
|
||||
* Derived from "include/asm-i386/unistd.h"
|
||||
*/
|
||||
|
||||
#ifndef _UAPI_ASM_S390_UNISTD_H_
|
||||
#define _UAPI_ASM_S390_UNISTD_H_
|
||||
|
||||
/*
|
||||
* This file contains the system call numbers.
|
||||
*/
|
||||
|
||||
#define __NR_exit 1
|
||||
#define __NR_fork 2
|
||||
#define __NR_read 3
|
||||
#define __NR_write 4
|
||||
#define __NR_open 5
|
||||
#define __NR_close 6
|
||||
#define __NR_restart_syscall 7
|
||||
#define __NR_creat 8
|
||||
#define __NR_link 9
|
||||
#define __NR_unlink 10
|
||||
#define __NR_execve 11
|
||||
#define __NR_chdir 12
|
||||
#define __NR_mknod 14
|
||||
#define __NR_chmod 15
|
||||
#define __NR_lseek 19
|
||||
#define __NR_getpid 20
|
||||
#define __NR_mount 21
|
||||
#define __NR_umount 22
|
||||
#define __NR_ptrace 26
|
||||
#define __NR_alarm 27
|
||||
#define __NR_pause 29
|
||||
#define __NR_utime 30
|
||||
#define __NR_access 33
|
||||
#define __NR_nice 34
|
||||
#define __NR_sync 36
|
||||
#define __NR_kill 37
|
||||
#define __NR_rename 38
|
||||
#define __NR_mkdir 39
|
||||
#define __NR_rmdir 40
|
||||
#define __NR_dup 41
|
||||
#define __NR_pipe 42
|
||||
#define __NR_times 43
|
||||
#define __NR_brk 45
|
||||
#define __NR_signal 48
|
||||
#define __NR_acct 51
|
||||
#define __NR_umount2 52
|
||||
#define __NR_ioctl 54
|
||||
#define __NR_fcntl 55
|
||||
#define __NR_setpgid 57
|
||||
#define __NR_umask 60
|
||||
#define __NR_chroot 61
|
||||
#define __NR_ustat 62
|
||||
#define __NR_dup2 63
|
||||
#define __NR_getppid 64
|
||||
#define __NR_getpgrp 65
|
||||
#define __NR_setsid 66
|
||||
#define __NR_sigaction 67
|
||||
#define __NR_sigsuspend 72
|
||||
#define __NR_sigpending 73
|
||||
#define __NR_sethostname 74
|
||||
#define __NR_setrlimit 75
|
||||
#define __NR_getrusage 77
|
||||
#define __NR_gettimeofday 78
|
||||
#define __NR_settimeofday 79
|
||||
#define __NR_symlink 83
|
||||
#define __NR_readlink 85
|
||||
#define __NR_uselib 86
|
||||
#define __NR_swapon 87
|
||||
#define __NR_reboot 88
|
||||
#define __NR_readdir 89
|
||||
#define __NR_mmap 90
|
||||
#define __NR_munmap 91
|
||||
#define __NR_truncate 92
|
||||
#define __NR_ftruncate 93
|
||||
#define __NR_fchmod 94
|
||||
#define __NR_getpriority 96
|
||||
#define __NR_setpriority 97
|
||||
#define __NR_statfs 99
|
||||
#define __NR_fstatfs 100
|
||||
#define __NR_socketcall 102
|
||||
#define __NR_syslog 103
|
||||
#define __NR_setitimer 104
|
||||
#define __NR_getitimer 105
|
||||
#define __NR_stat 106
|
||||
#define __NR_lstat 107
|
||||
#define __NR_fstat 108
|
||||
#define __NR_lookup_dcookie 110
|
||||
#define __NR_vhangup 111
|
||||
#define __NR_idle 112
|
||||
#define __NR_wait4 114
|
||||
#define __NR_swapoff 115
|
||||
#define __NR_sysinfo 116
|
||||
#define __NR_ipc 117
|
||||
#define __NR_fsync 118
|
||||
#define __NR_sigreturn 119
|
||||
#define __NR_clone 120
|
||||
#define __NR_setdomainname 121
|
||||
#define __NR_uname 122
|
||||
#define __NR_adjtimex 124
|
||||
#define __NR_mprotect 125
|
||||
#define __NR_sigprocmask 126
|
||||
#define __NR_create_module 127
|
||||
#define __NR_init_module 128
|
||||
#define __NR_delete_module 129
|
||||
#define __NR_get_kernel_syms 130
|
||||
#define __NR_quotactl 131
|
||||
#define __NR_getpgid 132
|
||||
#define __NR_fchdir 133
|
||||
#define __NR_bdflush 134
|
||||
#define __NR_sysfs 135
|
||||
#define __NR_personality 136
|
||||
#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
|
||||
#define __NR_getdents 141
|
||||
#define __NR_flock 143
|
||||
#define __NR_msync 144
|
||||
#define __NR_readv 145
|
||||
#define __NR_writev 146
|
||||
#define __NR_getsid 147
|
||||
#define __NR_fdatasync 148
|
||||
#define __NR__sysctl 149
|
||||
#define __NR_mlock 150
|
||||
#define __NR_munlock 151
|
||||
#define __NR_mlockall 152
|
||||
#define __NR_munlockall 153
|
||||
#define __NR_sched_setparam 154
|
||||
#define __NR_sched_getparam 155
|
||||
#define __NR_sched_setscheduler 156
|
||||
#define __NR_sched_getscheduler 157
|
||||
#define __NR_sched_yield 158
|
||||
#define __NR_sched_get_priority_max 159
|
||||
#define __NR_sched_get_priority_min 160
|
||||
#define __NR_sched_rr_get_interval 161
|
||||
#define __NR_nanosleep 162
|
||||
#define __NR_mremap 163
|
||||
#define __NR_query_module 167
|
||||
#define __NR_poll 168
|
||||
#define __NR_nfsservctl 169
|
||||
#define __NR_prctl 172
|
||||
#define __NR_rt_sigreturn 173
|
||||
#define __NR_rt_sigaction 174
|
||||
#define __NR_rt_sigprocmask 175
|
||||
#define __NR_rt_sigpending 176
|
||||
#define __NR_rt_sigtimedwait 177
|
||||
#define __NR_rt_sigqueueinfo 178
|
||||
#define __NR_rt_sigsuspend 179
|
||||
#define __NR_pread64 180
|
||||
#define __NR_pwrite64 181
|
||||
#define __NR_getcwd 183
|
||||
#define __NR_capget 184
|
||||
#define __NR_capset 185
|
||||
#define __NR_sigaltstack 186
|
||||
#define __NR_sendfile 187
|
||||
#define __NR_getpmsg 188
|
||||
#define __NR_putpmsg 189
|
||||
#define __NR_vfork 190
|
||||
#define __NR_pivot_root 217
|
||||
#define __NR_mincore 218
|
||||
#define __NR_madvise 219
|
||||
#define __NR_getdents64 220
|
||||
#define __NR_readahead 222
|
||||
#define __NR_setxattr 224
|
||||
#define __NR_lsetxattr 225
|
||||
#define __NR_fsetxattr 226
|
||||
#define __NR_getxattr 227
|
||||
#define __NR_lgetxattr 228
|
||||
#define __NR_fgetxattr 229
|
||||
#define __NR_listxattr 230
|
||||
#define __NR_llistxattr 231
|
||||
#define __NR_flistxattr 232
|
||||
#define __NR_removexattr 233
|
||||
#define __NR_lremovexattr 234
|
||||
#define __NR_fremovexattr 235
|
||||
#define __NR_gettid 236
|
||||
#define __NR_tkill 237
|
||||
#define __NR_futex 238
|
||||
#define __NR_sched_setaffinity 239
|
||||
#define __NR_sched_getaffinity 240
|
||||
#define __NR_tgkill 241
|
||||
/* Number 242 is reserved for tux */
|
||||
#define __NR_io_setup 243
|
||||
#define __NR_io_destroy 244
|
||||
#define __NR_io_getevents 245
|
||||
#define __NR_io_submit 246
|
||||
#define __NR_io_cancel 247
|
||||
#define __NR_exit_group 248
|
||||
#define __NR_epoll_create 249
|
||||
#define __NR_epoll_ctl 250
|
||||
#define __NR_epoll_wait 251
|
||||
#define __NR_set_tid_address 252
|
||||
#define __NR_fadvise64 253
|
||||
#define __NR_timer_create 254
|
||||
#define __NR_timer_settime 255
|
||||
#define __NR_timer_gettime 256
|
||||
#define __NR_timer_getoverrun 257
|
||||
#define __NR_timer_delete 258
|
||||
#define __NR_clock_settime 259
|
||||
#define __NR_clock_gettime 260
|
||||
#define __NR_clock_getres 261
|
||||
#define __NR_clock_nanosleep 262
|
||||
/* Number 263 is reserved for vserver */
|
||||
#define __NR_statfs64 265
|
||||
#define __NR_fstatfs64 266
|
||||
#define __NR_remap_file_pages 267
|
||||
#define __NR_mbind 268
|
||||
#define __NR_get_mempolicy 269
|
||||
#define __NR_set_mempolicy 270
|
||||
#define __NR_mq_open 271
|
||||
#define __NR_mq_unlink 272
|
||||
#define __NR_mq_timedsend 273
|
||||
#define __NR_mq_timedreceive 274
|
||||
#define __NR_mq_notify 275
|
||||
#define __NR_mq_getsetattr 276
|
||||
#define __NR_kexec_load 277
|
||||
#define __NR_add_key 278
|
||||
#define __NR_request_key 279
|
||||
#define __NR_keyctl 280
|
||||
#define __NR_waitid 281
|
||||
#define __NR_ioprio_set 282
|
||||
#define __NR_ioprio_get 283
|
||||
#define __NR_inotify_init 284
|
||||
#define __NR_inotify_add_watch 285
|
||||
#define __NR_inotify_rm_watch 286
|
||||
#define __NR_migrate_pages 287
|
||||
#define __NR_openat 288
|
||||
#define __NR_mkdirat 289
|
||||
#define __NR_mknodat 290
|
||||
#define __NR_fchownat 291
|
||||
#define __NR_futimesat 292
|
||||
#define __NR_unlinkat 294
|
||||
#define __NR_renameat 295
|
||||
#define __NR_linkat 296
|
||||
#define __NR_symlinkat 297
|
||||
#define __NR_readlinkat 298
|
||||
#define __NR_fchmodat 299
|
||||
#define __NR_faccessat 300
|
||||
#define __NR_pselect6 301
|
||||
#define __NR_ppoll 302
|
||||
#define __NR_unshare 303
|
||||
#define __NR_set_robust_list 304
|
||||
#define __NR_get_robust_list 305
|
||||
#define __NR_splice 306
|
||||
#define __NR_sync_file_range 307
|
||||
#define __NR_tee 308
|
||||
#define __NR_vmsplice 309
|
||||
#define __NR_move_pages 310
|
||||
#define __NR_getcpu 311
|
||||
#define __NR_epoll_pwait 312
|
||||
#define __NR_utimes 313
|
||||
#define __NR_fallocate 314
|
||||
#define __NR_utimensat 315
|
||||
#define __NR_signalfd 316
|
||||
#define __NR_timerfd 317
|
||||
#define __NR_eventfd 318
|
||||
#define __NR_timerfd_create 319
|
||||
#define __NR_timerfd_settime 320
|
||||
#define __NR_timerfd_gettime 321
|
||||
#define __NR_signalfd4 322
|
||||
#define __NR_eventfd2 323
|
||||
#define __NR_inotify_init1 324
|
||||
#define __NR_pipe2 325
|
||||
#define __NR_dup3 326
|
||||
#define __NR_epoll_create1 327
|
||||
#define __NR_preadv 328
|
||||
#define __NR_pwritev 329
|
||||
#define __NR_rt_tgsigqueueinfo 330
|
||||
#define __NR_perf_event_open 331
|
||||
#define __NR_fanotify_init 332
|
||||
#define __NR_fanotify_mark 333
|
||||
#define __NR_prlimit64 334
|
||||
#define __NR_name_to_handle_at 335
|
||||
#define __NR_open_by_handle_at 336
|
||||
#define __NR_clock_adjtime 337
|
||||
#define __NR_syncfs 338
|
||||
#define __NR_setns 339
|
||||
#define __NR_process_vm_readv 340
|
||||
#define __NR_process_vm_writev 341
|
||||
#define __NR_s390_runtime_instr 342
|
||||
#define __NR_kcmp 343
|
||||
#define __NR_finit_module 344
|
||||
#define __NR_sched_setattr 345
|
||||
#define __NR_sched_getattr 346
|
||||
#define __NR_renameat2 347
|
||||
#define __NR_seccomp 348
|
||||
#define __NR_getrandom 349
|
||||
#define __NR_memfd_create 350
|
||||
#define __NR_bpf 351
|
||||
#define __NR_s390_pci_mmio_write 352
|
||||
#define __NR_s390_pci_mmio_read 353
|
||||
#define __NR_execveat 354
|
||||
#define __NR_userfaultfd 355
|
||||
#define __NR_membarrier 356
|
||||
#define __NR_recvmmsg 357
|
||||
#define __NR_sendmmsg 358
|
||||
#define __NR_socket 359
|
||||
#define __NR_socketpair 360
|
||||
#define __NR_bind 361
|
||||
#define __NR_connect 362
|
||||
#define __NR_listen 363
|
||||
#define __NR_accept4 364
|
||||
#define __NR_getsockopt 365
|
||||
#define __NR_setsockopt 366
|
||||
#define __NR_getsockname 367
|
||||
#define __NR_getpeername 368
|
||||
#define __NR_sendto 369
|
||||
#define __NR_sendmsg 370
|
||||
#define __NR_recvfrom 371
|
||||
#define __NR_recvmsg 372
|
||||
#define __NR_shutdown 373
|
||||
#define __NR_mlock2 374
|
||||
#define __NR_copy_file_range 375
|
||||
#define __NR_preadv2 376
|
||||
#define __NR_pwritev2 377
|
||||
#define __NR_s390_guarded_storage 378
|
||||
#define __NR_statx 379
|
||||
#define __NR_s390_sthyi 380
|
||||
#define NR_syscalls 381
|
||||
|
||||
/*
|
||||
* There are some system calls that are not present on 64 bit, some
|
||||
* have a different name although they do the same (e.g. __NR_chown32
|
||||
* is __NR_chown on 64 bit).
|
||||
*/
|
||||
#ifndef __s390x__
|
||||
|
||||
#define __NR_time 13
|
||||
#define __NR_lchown 16
|
||||
#define __NR_setuid 23
|
||||
#define __NR_getuid 24
|
||||
#define __NR_stime 25
|
||||
#define __NR_setgid 46
|
||||
#define __NR_getgid 47
|
||||
#define __NR_geteuid 49
|
||||
#define __NR_getegid 50
|
||||
#define __NR_setreuid 70
|
||||
#define __NR_setregid 71
|
||||
#define __NR_getrlimit 76
|
||||
#define __NR_getgroups 80
|
||||
#define __NR_setgroups 81
|
||||
#define __NR_fchown 95
|
||||
#define __NR_ioperm 101
|
||||
#define __NR_setfsuid 138
|
||||
#define __NR_setfsgid 139
|
||||
#define __NR__llseek 140
|
||||
#define __NR__newselect 142
|
||||
#define __NR_setresuid 164
|
||||
#define __NR_getresuid 165
|
||||
#define __NR_setresgid 170
|
||||
#define __NR_getresgid 171
|
||||
#define __NR_chown 182
|
||||
#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */
|
||||
#define __NR_mmap2 192
|
||||
#define __NR_truncate64 193
|
||||
#define __NR_ftruncate64 194
|
||||
#define __NR_stat64 195
|
||||
#define __NR_lstat64 196
|
||||
#define __NR_fstat64 197
|
||||
#define __NR_lchown32 198
|
||||
#define __NR_getuid32 199
|
||||
#define __NR_getgid32 200
|
||||
#define __NR_geteuid32 201
|
||||
#define __NR_getegid32 202
|
||||
#define __NR_setreuid32 203
|
||||
#define __NR_setregid32 204
|
||||
#define __NR_getgroups32 205
|
||||
#define __NR_setgroups32 206
|
||||
#define __NR_fchown32 207
|
||||
#define __NR_setresuid32 208
|
||||
#define __NR_getresuid32 209
|
||||
#define __NR_setresgid32 210
|
||||
#define __NR_getresgid32 211
|
||||
#define __NR_chown32 212
|
||||
#define __NR_setuid32 213
|
||||
#define __NR_setgid32 214
|
||||
#define __NR_setfsuid32 215
|
||||
#define __NR_setfsgid32 216
|
||||
#define __NR_fcntl64 221
|
||||
#define __NR_sendfile64 223
|
||||
#define __NR_fadvise64_64 264
|
||||
#define __NR_fstatat64 293
|
||||
|
||||
#else
|
||||
|
||||
#define __NR_select 142
|
||||
#define __NR_getrlimit 191 /* SuS compliant getrlimit */
|
||||
#define __NR_lchown 198
|
||||
#define __NR_getuid 199
|
||||
#define __NR_getgid 200
|
||||
#define __NR_geteuid 201
|
||||
#define __NR_getegid 202
|
||||
#define __NR_setreuid 203
|
||||
#define __NR_setregid 204
|
||||
#define __NR_getgroups 205
|
||||
#define __NR_setgroups 206
|
||||
#define __NR_fchown 207
|
||||
#define __NR_setresuid 208
|
||||
#define __NR_getresuid 209
|
||||
#define __NR_setresgid 210
|
||||
#define __NR_getresgid 211
|
||||
#define __NR_chown 212
|
||||
#define __NR_setuid 213
|
||||
#define __NR_setgid 214
|
||||
#define __NR_setfsuid 215
|
||||
#define __NR_setfsgid 216
|
||||
#define __NR_newfstatat 293
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _UAPI_ASM_S390_UNISTD_H_ */
|
||||
@@ -210,6 +210,7 @@
|
||||
|
||||
#define X86_FEATURE_MBA ( 7*32+18) /* Memory Bandwidth Allocation */
|
||||
#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* "" Fill RSB on context switches */
|
||||
#define X86_FEATURE_SEV ( 7*32+20) /* AMD Secure Encrypted Virtualization */
|
||||
|
||||
#define X86_FEATURE_USE_IBPB ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */
|
||||
|
||||
|
||||
@@ -9,6 +9,35 @@ MAKE = make
|
||||
CFLAGS += -Wall -O2
|
||||
CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include
|
||||
|
||||
ifeq ($(srctree),)
|
||||
srctree := $(patsubst %/,%,$(dir $(CURDIR)))
|
||||
srctree := $(patsubst %/,%,$(dir $(srctree)))
|
||||
endif
|
||||
|
||||
FEATURE_USER = .bpf
|
||||
FEATURE_TESTS = libbfd disassembler-four-args
|
||||
FEATURE_DISPLAY = libbfd disassembler-four-args
|
||||
|
||||
check_feat := 1
|
||||
NON_CHECK_FEAT_TARGETS := clean bpftool_clean
|
||||
ifdef MAKECMDGOALS
|
||||
ifeq ($(filter-out $(NON_CHECK_FEAT_TARGETS),$(MAKECMDGOALS)),)
|
||||
check_feat := 0
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(check_feat),1)
|
||||
ifeq ($(FEATURES_DUMP),)
|
||||
include $(srctree)/tools/build/Makefile.feature
|
||||
else
|
||||
include $(FEATURES_DUMP)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(feature-disassembler-four-args), 1)
|
||||
CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
|
||||
endif
|
||||
|
||||
%.yacc.c: %.y
|
||||
$(YACC) -o $@ -d $<
|
||||
|
||||
|
||||
@@ -72,7 +72,14 @@ static void get_asm_insns(uint8_t *image, size_t len, int opcodes)
|
||||
|
||||
disassemble_init_for_target(&info);
|
||||
|
||||
#ifdef DISASM_FOUR_ARGS_SIGNATURE
|
||||
disassemble = disassembler(info.arch,
|
||||
bfd_big_endian(bfdf),
|
||||
info.mach,
|
||||
bfdf);
|
||||
#else
|
||||
disassemble = disassembler(bfdf);
|
||||
#endif
|
||||
assert(disassemble);
|
||||
|
||||
do {
|
||||
@@ -165,7 +172,8 @@ static uint8_t *get_last_jit_image(char *haystack, size_t hlen,
|
||||
{
|
||||
char *ptr, *pptr, *tmp;
|
||||
off_t off = 0;
|
||||
int ret, flen, proglen, pass, ulen = 0;
|
||||
unsigned int proglen;
|
||||
int ret, flen, pass, ulen = 0;
|
||||
regmatch_t pmatch[1];
|
||||
unsigned long base;
|
||||
regex_t regex;
|
||||
@@ -192,7 +200,7 @@ static uint8_t *get_last_jit_image(char *haystack, size_t hlen,
|
||||
}
|
||||
|
||||
ptr = haystack + off - (pmatch[0].rm_eo - pmatch[0].rm_so);
|
||||
ret = sscanf(ptr, "flen=%d proglen=%d pass=%d image=%lx",
|
||||
ret = sscanf(ptr, "flen=%d proglen=%u pass=%d image=%lx",
|
||||
&flen, &proglen, &pass, &base);
|
||||
if (ret != 4) {
|
||||
regfree(®ex);
|
||||
@@ -232,7 +240,7 @@ static uint8_t *get_last_jit_image(char *haystack, size_t hlen,
|
||||
}
|
||||
|
||||
assert(ulen == proglen);
|
||||
printf("%d bytes emitted from JIT compiler (pass:%d, flen:%d)\n",
|
||||
printf("%u bytes emitted from JIT compiler (pass:%d, flen:%d)\n",
|
||||
proglen, pass, flen);
|
||||
printf("%lx + <x>:\n", base);
|
||||
|
||||
|
||||
@@ -3,12 +3,16 @@ include ../../../scripts/utilities.mak
|
||||
|
||||
INSTALL ?= install
|
||||
RM ?= rm -f
|
||||
RMDIR ?= rmdir --ignore-fail-on-non-empty
|
||||
|
||||
# Make the path relative to DESTDIR, not prefix
|
||||
ifndef DESTDIR
|
||||
prefix ?= /usr/local
|
||||
ifeq ($(V),1)
|
||||
Q =
|
||||
else
|
||||
Q = @
|
||||
endif
|
||||
mandir ?= $(prefix)/share/man
|
||||
|
||||
prefix ?= /usr/local
|
||||
mandir ?= $(prefix)/man
|
||||
man8dir = $(mandir)/man8
|
||||
|
||||
MAN8_RST = $(wildcard *.rst)
|
||||
@@ -19,16 +23,27 @@ DOC_MAN8 = $(addprefix $(OUTPUT),$(_DOC_MAN8))
|
||||
man: man8
|
||||
man8: $(DOC_MAN8)
|
||||
|
||||
RST2MAN_DEP := $(shell command -v rst2man 2>/dev/null)
|
||||
|
||||
$(OUTPUT)%.8: %.rst
|
||||
rst2man $< > $@
|
||||
ifndef RST2MAN_DEP
|
||||
$(error "rst2man not found, but required to generate man pages")
|
||||
endif
|
||||
$(QUIET_GEN)rst2man $< > $@
|
||||
|
||||
clean:
|
||||
$(call QUIET_CLEAN, Documentation) $(RM) $(DOC_MAN8)
|
||||
$(call QUIET_CLEAN, Documentation)
|
||||
$(Q)$(RM) $(DOC_MAN8)
|
||||
|
||||
install: man
|
||||
$(call QUIET_INSTALL, Documentation-man) \
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)$(man8dir); \
|
||||
$(INSTALL) -m 644 $(DOC_MAN8) $(DESTDIR)$(man8dir);
|
||||
$(call QUIET_INSTALL, Documentation-man)
|
||||
$(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(man8dir)
|
||||
$(Q)$(INSTALL) -m 644 $(DOC_MAN8) $(DESTDIR)$(man8dir)
|
||||
|
||||
.PHONY: man man8 clean install
|
||||
uninstall:
|
||||
$(call QUIET_UNINST, Documentation-man)
|
||||
$(Q)$(RM) $(addprefix $(DESTDIR)$(man8dir)/,$(_DOC_MAN8))
|
||||
$(Q)$(RMDIR) $(DESTDIR)$(man8dir)
|
||||
|
||||
.PHONY: man man8 clean install uninstall
|
||||
.DEFAULT_GOAL := man
|
||||
|
||||
118
tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
Normal file
118
tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
Normal file
@@ -0,0 +1,118 @@
|
||||
================
|
||||
bpftool-cgroup
|
||||
================
|
||||
-------------------------------------------------------------------------------
|
||||
tool for inspection and simple manipulation of eBPF progs
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
:Manual section: 8
|
||||
|
||||
SYNOPSIS
|
||||
========
|
||||
|
||||
**bpftool** [*OPTIONS*] **cgroup** *COMMAND*
|
||||
|
||||
*OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } }
|
||||
|
||||
*COMMANDS* :=
|
||||
{ **show** | **list** | **attach** | **detach** | **help** }
|
||||
|
||||
MAP COMMANDS
|
||||
=============
|
||||
|
||||
| **bpftool** **cgroup { show | list }** *CGROUP*
|
||||
| **bpftool** **cgroup attach** *CGROUP* *ATTACH_TYPE* *PROG* [*ATTACH_FLAGS*]
|
||||
| **bpftool** **cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG*
|
||||
| **bpftool** **cgroup help**
|
||||
|
|
||||
| *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
|
||||
| *ATTACH_TYPE* := { **ingress** | **egress** | **sock_create** | **sock_ops** | **device** }
|
||||
| *ATTACH_FLAGS* := { **multi** | **override** }
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
**bpftool cgroup { show | list }** *CGROUP*
|
||||
List all programs attached to the cgroup *CGROUP*.
|
||||
|
||||
Output will start with program ID followed by attach type,
|
||||
attach flags and program name.
|
||||
|
||||
**bpftool cgroup attach** *CGROUP* *ATTACH_TYPE* *PROG* [*ATTACH_FLAGS*]
|
||||
Attach program *PROG* to the cgroup *CGROUP* with attach type
|
||||
*ATTACH_TYPE* and optional *ATTACH_FLAGS*.
|
||||
|
||||
*ATTACH_FLAGS* can be one of: **override** if a sub-cgroup installs
|
||||
some bpf program, the program in this cgroup yields to sub-cgroup
|
||||
program; **multi** if a sub-cgroup installs some bpf program,
|
||||
that cgroup program gets run in addition to the program in this
|
||||
cgroup.
|
||||
|
||||
Only one program is allowed to be attached to a cgroup with
|
||||
no attach flags or the **override** flag. Attaching another
|
||||
program will release old program and attach the new one.
|
||||
|
||||
Multiple programs are allowed to be attached to a cgroup with
|
||||
**multi**. They are executed in FIFO order (those that were
|
||||
attached first, run first).
|
||||
|
||||
Non-default *ATTACH_FLAGS* are supported by kernel version 4.14
|
||||
and later.
|
||||
|
||||
*ATTACH_TYPE* can be on of:
|
||||
**ingress** ingress path of the inet socket (since 4.10);
|
||||
**egress** egress path of the inet socket (since 4.10);
|
||||
**sock_create** opening of an inet socket (since 4.10);
|
||||
**sock_ops** various socket operations (since 4.12);
|
||||
**device** device access (since 4.15).
|
||||
|
||||
**bpftool cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG*
|
||||
Detach *PROG* from the cgroup *CGROUP* and attach type
|
||||
*ATTACH_TYPE*.
|
||||
|
||||
**bpftool prog help**
|
||||
Print short help message.
|
||||
|
||||
OPTIONS
|
||||
=======
|
||||
-h, --help
|
||||
Print short generic help message (similar to **bpftool help**).
|
||||
|
||||
-v, --version
|
||||
Print version number (similar to **bpftool version**).
|
||||
|
||||
-j, --json
|
||||
Generate JSON output. For commands that cannot produce JSON, this
|
||||
option has no effect.
|
||||
|
||||
-p, --pretty
|
||||
Generate human-readable JSON output. Implies **-j**.
|
||||
|
||||
-f, --bpffs
|
||||
Show file names of pinned programs.
|
||||
|
||||
EXAMPLES
|
||||
========
|
||||
|
|
||||
| **# mount -t bpf none /sys/fs/bpf/**
|
||||
| **# mkdir /sys/fs/cgroup/test.slice**
|
||||
| **# bpftool prog load ./device_cgroup.o /sys/fs/bpf/prog**
|
||||
| **# bpftool cgroup attach /sys/fs/cgroup/test.slice/ device id 1 allow_multi**
|
||||
|
||||
**# bpftool cgroup list /sys/fs/cgroup/test.slice/**
|
||||
|
||||
::
|
||||
|
||||
ID AttachType AttachFlags Name
|
||||
1 device allow_multi bpf_prog1
|
||||
|
||||
|
|
||||
| **# bpftool cgroup detach /sys/fs/cgroup/test.slice/ device id 1**
|
||||
| **# bpftool cgroup list /sys/fs/cgroup/test.slice/**
|
||||
|
||||
::
|
||||
|
||||
ID AttachType AttachFlags Name
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
**bpftool**\ (8), **bpftool-prog**\ (8), **bpftool-map**\ (8)
|
||||
@@ -15,13 +15,13 @@ SYNOPSIS
|
||||
*OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } }
|
||||
|
||||
*COMMANDS* :=
|
||||
{ **show** | **dump** | **update** | **lookup** | **getnext** | **delete**
|
||||
{ **show** | **list** | **dump** | **update** | **lookup** | **getnext** | **delete**
|
||||
| **pin** | **help** }
|
||||
|
||||
MAP COMMANDS
|
||||
=============
|
||||
|
||||
| **bpftool** **map show** [*MAP*]
|
||||
| **bpftool** **map { show | list }** [*MAP*]
|
||||
| **bpftool** **map dump** *MAP*
|
||||
| **bpftool** **map update** *MAP* **key** *BYTES* **value** *VALUE* [*UPDATE_FLAGS*]
|
||||
| **bpftool** **map lookup** *MAP* **key** *BYTES*
|
||||
@@ -31,12 +31,13 @@ MAP COMMANDS
|
||||
| **bpftool** **map help**
|
||||
|
|
||||
| *MAP* := { **id** *MAP_ID* | **pinned** *FILE* }
|
||||
| *VALUE* := { *BYTES* | *MAP* | *PROGRAM* }
|
||||
| *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
|
||||
| *VALUE* := { *BYTES* | *MAP* | *PROG* }
|
||||
| *UPDATE_FLAGS* := { **any** | **exist** | **noexist** }
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
**bpftool map show** [*MAP*]
|
||||
**bpftool map { show | list }** [*MAP*]
|
||||
Show information about loaded maps. If *MAP* is specified
|
||||
show information only about given map, otherwise list all
|
||||
maps currently loaded on the system.
|
||||
@@ -128,4 +129,4 @@ EXAMPLES
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
**bpftool**\ (8), **bpftool-prog**\ (8)
|
||||
**bpftool**\ (8), **bpftool-prog**\ (8), **bpftool-cgroup**\ (8)
|
||||
|
||||
@@ -15,22 +15,23 @@ SYNOPSIS
|
||||
*OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } }
|
||||
|
||||
*COMMANDS* :=
|
||||
{ **show** | **dump xlated** | **dump jited** | **pin** | **help** }
|
||||
{ **show** | **list** | **dump xlated** | **dump jited** | **pin** | **load** | **help** }
|
||||
|
||||
MAP COMMANDS
|
||||
=============
|
||||
|
||||
| **bpftool** **prog show** [*PROG*]
|
||||
| **bpftool** **prog { show | list }** [*PROG*]
|
||||
| **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes**}]
|
||||
| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}]
|
||||
| **bpftool** **prog pin** *PROG* *FILE*
|
||||
| **bpftool** **prog load** *OBJ* *FILE*
|
||||
| **bpftool** **prog help**
|
||||
|
|
||||
| *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
**bpftool prog show** [*PROG*]
|
||||
**bpftool prog { show | list }** [*PROG*]
|
||||
Show information about loaded programs. If *PROG* is
|
||||
specified show information only about given program, otherwise
|
||||
list all programs currently loaded on the system.
|
||||
@@ -57,6 +58,11 @@ DESCRIPTION
|
||||
|
||||
Note: *FILE* must be located in *bpffs* mount.
|
||||
|
||||
**bpftool prog load** *OBJ* *FILE*
|
||||
Load bpf program from binary *OBJ* and pin as *FILE*.
|
||||
|
||||
Note: *FILE* must be located in *bpffs* mount.
|
||||
|
||||
**bpftool prog help**
|
||||
Print short help message.
|
||||
|
||||
@@ -126,8 +132,10 @@ EXAMPLES
|
||||
|
|
||||
| **# mount -t bpf none /sys/fs/bpf/**
|
||||
| **# bpftool prog pin id 10 /sys/fs/bpf/prog**
|
||||
| **# bpftool prog load ./my_prog.o /sys/fs/bpf/prog2**
|
||||
| **# ls -l /sys/fs/bpf/**
|
||||
| -rw------- 1 root root 0 Jul 22 01:43 prog
|
||||
| -rw------- 1 root root 0 Jul 22 01:44 prog2
|
||||
|
||||
**# bpftool prog dum jited pinned /sys/fs/bpf/prog opcodes**
|
||||
|
||||
@@ -147,4 +155,4 @@ EXAMPLES
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
**bpftool**\ (8), **bpftool-map**\ (8)
|
||||
**bpftool**\ (8), **bpftool-map**\ (8), **bpftool-cgroup**\ (8)
|
||||
|
||||
@@ -16,17 +16,19 @@ SYNOPSIS
|
||||
|
||||
**bpftool** **version**
|
||||
|
||||
*OBJECT* := { **map** | **program** }
|
||||
*OBJECT* := { **map** | **program** | **cgroup** }
|
||||
|
||||
*OPTIONS* := { { **-V** | **--version** } | { **-h** | **--help** }
|
||||
| { **-j** | **--json** } [{ **-p** | **--pretty** }] }
|
||||
|
||||
*MAP-COMMANDS* :=
|
||||
{ **show** | **dump** | **update** | **lookup** | **getnext** | **delete**
|
||||
{ **show** | **list** | **dump** | **update** | **lookup** | **getnext** | **delete**
|
||||
| **pin** | **help** }
|
||||
|
||||
*PROG-COMMANDS* := { **show** | **dump jited** | **dump xlated** | **pin**
|
||||
| **help** }
|
||||
*PROG-COMMANDS* := { **show** | **list** | **dump jited** | **dump xlated** | **pin**
|
||||
| **load** | **help** }
|
||||
|
||||
*CGROUP-COMMANDS* := { **show** | **list** | **attach** | **detach** | **help** }
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
@@ -53,4 +55,4 @@ OPTIONS
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
**bpftool-map**\ (8), **bpftool-prog**\ (8)
|
||||
**bpftool-map**\ (8), **bpftool-prog**\ (8), **bpftool-cgroup**\ (8)
|
||||
|
||||
@@ -1,25 +1,10 @@
|
||||
include ../../scripts/Makefile.include
|
||||
|
||||
include ../../scripts/utilities.mak
|
||||
|
||||
ifeq ($(srctree),)
|
||||
srctree := $(patsubst %/,%,$(dir $(CURDIR)))
|
||||
srctree := $(patsubst %/,%,$(dir $(srctree)))
|
||||
srctree := $(patsubst %/,%,$(dir $(srctree)))
|
||||
#$(info Determined 'srctree' to be $(srctree))
|
||||
endif
|
||||
|
||||
ifneq ($(objtree),)
|
||||
#$(info Determined 'objtree' to be $(objtree))
|
||||
endif
|
||||
|
||||
ifneq ($(OUTPUT),)
|
||||
#$(info Determined 'OUTPUT' to be $(OUTPUT))
|
||||
# Adding $(OUTPUT) as a directory to look for source files,
|
||||
# because use generated output files as sources dependency
|
||||
# for flex/bison parsers.
|
||||
VPATH += $(OUTPUT)
|
||||
export VPATH
|
||||
endif
|
||||
|
||||
ifeq ($(V),1)
|
||||
@@ -28,16 +13,18 @@ else
|
||||
Q = @
|
||||
endif
|
||||
|
||||
BPF_DIR = $(srctree)/tools/lib/bpf/
|
||||
BPF_DIR = $(srctree)/tools/lib/bpf/
|
||||
|
||||
ifneq ($(OUTPUT),)
|
||||
BPF_PATH=$(OUTPUT)
|
||||
BPF_PATH = $(OUTPUT)
|
||||
else
|
||||
BPF_PATH=$(BPF_DIR)
|
||||
BPF_PATH = $(BPF_DIR)
|
||||
endif
|
||||
|
||||
LIBBPF = $(BPF_PATH)libbpf.a
|
||||
|
||||
BPFTOOL_VERSION=$(shell make --no-print-directory -sC ../../.. kernelversion)
|
||||
|
||||
$(LIBBPF): FORCE
|
||||
$(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(OUTPUT) $(OUTPUT)libbpf.a FEATURES_DUMP=$(FEATURE_DUMP_EXPORT)
|
||||
|
||||
@@ -45,22 +32,50 @@ $(LIBBPF)-clean:
|
||||
$(call QUIET_CLEAN, libbpf)
|
||||
$(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(OUTPUT) clean >/dev/null
|
||||
|
||||
prefix = /usr/local
|
||||
prefix ?= /usr/local
|
||||
bash_compdir ?= /usr/share/bash-completion/completions
|
||||
|
||||
CC = gcc
|
||||
|
||||
CFLAGS += -O2
|
||||
CFLAGS += -W -Wall -Wextra -Wno-unused-parameter -Wshadow
|
||||
CFLAGS += -D__EXPORTED_HEADERS__ -I$(srctree)/tools/include/uapi -I$(srctree)/tools/include -I$(srctree)/tools/lib/bpf -I$(srctree)/kernel/bpf/
|
||||
CFLAGS += -DPACKAGE='"bpftool"' -D__EXPORTED_HEADERS__ -I$(srctree)/tools/include/uapi -I$(srctree)/tools/include -I$(srctree)/tools/lib/bpf -I$(srctree)/kernel/bpf/
|
||||
CFLAGS += -DBPFTOOL_VERSION='"$(BPFTOOL_VERSION)"'
|
||||
LIBS = -lelf -lbfd -lopcodes $(LIBBPF)
|
||||
|
||||
INSTALL ?= install
|
||||
RM ?= rm -f
|
||||
|
||||
FEATURE_USER = .bpftool
|
||||
FEATURE_TESTS = libbfd disassembler-four-args
|
||||
FEATURE_DISPLAY = libbfd disassembler-four-args
|
||||
|
||||
check_feat := 1
|
||||
NON_CHECK_FEAT_TARGETS := clean uninstall doc doc-clean doc-install doc-uninstall
|
||||
ifdef MAKECMDGOALS
|
||||
ifeq ($(filter-out $(NON_CHECK_FEAT_TARGETS),$(MAKECMDGOALS)),)
|
||||
check_feat := 0
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(check_feat),1)
|
||||
ifeq ($(FEATURES_DUMP),)
|
||||
include $(srctree)/tools/build/Makefile.feature
|
||||
else
|
||||
include $(FEATURES_DUMP)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(feature-disassembler-four-args), 1)
|
||||
CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
|
||||
endif
|
||||
|
||||
include $(wildcard *.d)
|
||||
|
||||
all: $(OUTPUT)bpftool
|
||||
|
||||
SRCS=$(wildcard *.c)
|
||||
OBJS=$(patsubst %.c,$(OUTPUT)%.o,$(SRCS)) $(OUTPUT)disasm.o
|
||||
SRCS = $(wildcard *.c)
|
||||
OBJS = $(patsubst %.c,$(OUTPUT)%.o,$(SRCS)) $(OUTPUT)disasm.o
|
||||
|
||||
$(OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c
|
||||
$(QUIET_CC)$(COMPILE.c) -MMD -o $@ $<
|
||||
@@ -73,21 +88,34 @@ $(OUTPUT)%.o: %.c
|
||||
|
||||
clean: $(LIBBPF)-clean
|
||||
$(call QUIET_CLEAN, bpftool)
|
||||
$(Q)rm -rf $(OUTPUT)bpftool $(OUTPUT)*.o $(OUTPUT)*.d
|
||||
$(Q)$(RM) $(OUTPUT)bpftool $(OUTPUT)*.o $(OUTPUT)*.d
|
||||
|
||||
install:
|
||||
install -m 0755 -d $(prefix)/sbin
|
||||
install $(OUTPUT)bpftool $(prefix)/sbin/bpftool
|
||||
install -m 0755 -d $(bash_compdir)
|
||||
install -m 0644 bash-completion/bpftool $(bash_compdir)
|
||||
install: $(OUTPUT)bpftool
|
||||
$(call QUIET_INSTALL, bpftool)
|
||||
$(Q)$(INSTALL) -m 0755 -d $(DESTDIR)$(prefix)/sbin
|
||||
$(Q)$(INSTALL) $(OUTPUT)bpftool $(DESTDIR)$(prefix)/sbin/bpftool
|
||||
$(Q)$(INSTALL) -m 0755 -d $(DESTDIR)$(bash_compdir)
|
||||
$(Q)$(INSTALL) -m 0644 bash-completion/bpftool $(DESTDIR)$(bash_compdir)
|
||||
|
||||
uninstall:
|
||||
$(call QUIET_UNINST, bpftool)
|
||||
$(Q)$(RM) $(DESTDIR)$(prefix)/sbin/bpftool
|
||||
$(Q)$(RM) $(DESTDIR)$(bash_compdir)/bpftool
|
||||
|
||||
doc:
|
||||
$(Q)$(MAKE) -C Documentation/
|
||||
$(call descend,Documentation)
|
||||
|
||||
doc-clean:
|
||||
$(call descend,Documentation,clean)
|
||||
|
||||
doc-install:
|
||||
$(Q)$(MAKE) -C Documentation/ install
|
||||
$(call descend,Documentation,install)
|
||||
|
||||
doc-uninstall:
|
||||
$(call descend,Documentation,uninstall)
|
||||
|
||||
FORCE:
|
||||
|
||||
.PHONY: all clean FORCE install doc doc-install
|
||||
.PHONY: all FORCE clean install uninstall
|
||||
.PHONY: doc doc-clean doc-install doc-uninstall
|
||||
.DEFAULT_GOAL := all
|
||||
|
||||
@@ -52,16 +52,24 @@ _bpftool_once_attr()
|
||||
done
|
||||
}
|
||||
|
||||
# Takes a list of words in argument; adds them all to COMPREPLY if none of them
|
||||
# is already present on the command line. Returns no value.
|
||||
_bpftool_one_of_list()
|
||||
# Takes a list of words as argument; if any of those words is present on the
|
||||
# command line, return 0. Otherwise, return 1.
|
||||
_bpftool_search_list()
|
||||
{
|
||||
local w idx
|
||||
for w in $*; do
|
||||
for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
|
||||
[[ $w == ${words[idx]} ]] && return 1
|
||||
[[ $w == ${words[idx]} ]] && return 0
|
||||
done
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Takes a list of words in argument; adds them all to COMPREPLY if none of them
|
||||
# is already present on the command line. Returns no value.
|
||||
_bpftool_one_of_list()
|
||||
{
|
||||
_bpftool_search_list $* && return 1
|
||||
COMPREPLY+=( $( compgen -W "$*" -- "$cur" ) )
|
||||
}
|
||||
|
||||
@@ -197,7 +205,7 @@ _bpftool()
|
||||
|
||||
local PROG_TYPE='id pinned tag'
|
||||
case $command in
|
||||
show)
|
||||
show|list)
|
||||
[[ $prev != "$command" ]] && return 0
|
||||
COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
|
||||
return 0
|
||||
@@ -230,17 +238,21 @@ _bpftool()
|
||||
fi
|
||||
return 0
|
||||
;;
|
||||
load)
|
||||
_filedir
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
[[ $prev == $object ]] && \
|
||||
COMPREPLY=( $( compgen -W 'dump help pin show' -- \
|
||||
"$cur" ) )
|
||||
COMPREPLY=( $( compgen -W 'dump help pin load \
|
||||
show list' -- "$cur" ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
map)
|
||||
local MAP_TYPE='id pinned'
|
||||
case $command in
|
||||
show|dump)
|
||||
show|list|dump)
|
||||
case $prev in
|
||||
$command)
|
||||
COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
|
||||
@@ -343,7 +355,55 @@ _bpftool()
|
||||
*)
|
||||
[[ $prev == $object ]] && \
|
||||
COMPREPLY=( $( compgen -W 'delete dump getnext help \
|
||||
lookup pin show update' -- "$cur" ) )
|
||||
lookup pin show list update' -- "$cur" ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
cgroup)
|
||||
case $command in
|
||||
show|list)
|
||||
_filedir
|
||||
return 0
|
||||
;;
|
||||
attach|detach)
|
||||
local ATTACH_TYPES='ingress egress sock_create sock_ops \
|
||||
device'
|
||||
local ATTACH_FLAGS='multi override'
|
||||
local PROG_TYPE='id pinned tag'
|
||||
case $prev in
|
||||
$command)
|
||||
_filedir
|
||||
return 0
|
||||
;;
|
||||
ingress|egress|sock_create|sock_ops|device)
|
||||
COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
|
||||
"$cur" ) )
|
||||
return 0
|
||||
;;
|
||||
id)
|
||||
_bpftool_get_prog_ids
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
if ! _bpftool_search_list "$ATTACH_TYPES"; then
|
||||
COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \
|
||||
"$cur" ) )
|
||||
elif [[ "$command" == "attach" ]]; then
|
||||
# We have an attach type on the command line,
|
||||
# but it is not the previous word, or
|
||||
# "id|pinned|tag" (we already checked for
|
||||
# that). This should only leave the case when
|
||||
# we need attach flags for "attach" commamnd.
|
||||
_bpftool_one_of_list "$ATTACH_FLAGS"
|
||||
fi
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
[[ $prev == $object ]] && \
|
||||
COMPREPLY=( $( compgen -W 'help attach detach \
|
||||
show list' -- "$cur" ) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
308
tools/bpf/bpftool/cgroup.c
Normal file
308
tools/bpf/bpftool/cgroup.c
Normal file
@@ -0,0 +1,308 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
// Copyright (C) 2017 Facebook
|
||||
// Author: Roman Gushchin <guro@fb.com>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <bpf.h>
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#define HELP_SPEC_ATTACH_FLAGS \
|
||||
"ATTACH_FLAGS := { multi | override }"
|
||||
|
||||
#define HELP_SPEC_ATTACH_TYPES \
|
||||
"ATTACH_TYPE := { ingress | egress | sock_create | sock_ops | device }"
|
||||
|
||||
static const char * const attach_type_strings[] = {
|
||||
[BPF_CGROUP_INET_INGRESS] = "ingress",
|
||||
[BPF_CGROUP_INET_EGRESS] = "egress",
|
||||
[BPF_CGROUP_INET_SOCK_CREATE] = "sock_create",
|
||||
[BPF_CGROUP_SOCK_OPS] = "sock_ops",
|
||||
[BPF_CGROUP_DEVICE] = "device",
|
||||
[__MAX_BPF_ATTACH_TYPE] = NULL,
|
||||
};
|
||||
|
||||
static enum bpf_attach_type parse_attach_type(const char *str)
|
||||
{
|
||||
enum bpf_attach_type type;
|
||||
|
||||
for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
|
||||
if (attach_type_strings[type] &&
|
||||
is_prefix(str, attach_type_strings[type]))
|
||||
return type;
|
||||
}
|
||||
|
||||
return __MAX_BPF_ATTACH_TYPE;
|
||||
}
|
||||
|
||||
static int show_bpf_prog(int id, const char *attach_type_str,
|
||||
const char *attach_flags_str)
|
||||
{
|
||||
struct bpf_prog_info info = {};
|
||||
__u32 info_len = sizeof(info);
|
||||
int prog_fd;
|
||||
|
||||
prog_fd = bpf_prog_get_fd_by_id(id);
|
||||
if (prog_fd < 0)
|
||||
return -1;
|
||||
|
||||
if (bpf_obj_get_info_by_fd(prog_fd, &info, &info_len)) {
|
||||
close(prog_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (json_output) {
|
||||
jsonw_start_object(json_wtr);
|
||||
jsonw_uint_field(json_wtr, "id", info.id);
|
||||
jsonw_string_field(json_wtr, "attach_type",
|
||||
attach_type_str);
|
||||
jsonw_string_field(json_wtr, "attach_flags",
|
||||
attach_flags_str);
|
||||
jsonw_string_field(json_wtr, "name", info.name);
|
||||
jsonw_end_object(json_wtr);
|
||||
} else {
|
||||
printf("%-8u %-15s %-15s %-15s\n", info.id,
|
||||
attach_type_str,
|
||||
attach_flags_str,
|
||||
info.name);
|
||||
}
|
||||
|
||||
close(prog_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type)
|
||||
{
|
||||
__u32 prog_ids[1024] = {0};
|
||||
char *attach_flags_str;
|
||||
__u32 prog_cnt, iter;
|
||||
__u32 attach_flags;
|
||||
char buf[32];
|
||||
int ret;
|
||||
|
||||
prog_cnt = ARRAY_SIZE(prog_ids);
|
||||
ret = bpf_prog_query(cgroup_fd, type, 0, &attach_flags, prog_ids,
|
||||
&prog_cnt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (prog_cnt == 0)
|
||||
return 0;
|
||||
|
||||
switch (attach_flags) {
|
||||
case BPF_F_ALLOW_MULTI:
|
||||
attach_flags_str = "multi";
|
||||
break;
|
||||
case BPF_F_ALLOW_OVERRIDE:
|
||||
attach_flags_str = "override";
|
||||
break;
|
||||
case 0:
|
||||
attach_flags_str = "";
|
||||
break;
|
||||
default:
|
||||
snprintf(buf, sizeof(buf), "unknown(%x)", attach_flags);
|
||||
attach_flags_str = buf;
|
||||
}
|
||||
|
||||
for (iter = 0; iter < prog_cnt; iter++)
|
||||
show_bpf_prog(prog_ids[iter], attach_type_strings[type],
|
||||
attach_flags_str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_show(int argc, char **argv)
|
||||
{
|
||||
enum bpf_attach_type type;
|
||||
int cgroup_fd;
|
||||
int ret = -1;
|
||||
|
||||
if (argc < 1) {
|
||||
p_err("too few parameters for cgroup show");
|
||||
goto exit;
|
||||
} else if (argc > 1) {
|
||||
p_err("too many parameters for cgroup show");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
cgroup_fd = open(argv[0], O_RDONLY);
|
||||
if (cgroup_fd < 0) {
|
||||
p_err("can't open cgroup %s", argv[1]);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (json_output)
|
||||
jsonw_start_array(json_wtr);
|
||||
else
|
||||
printf("%-8s %-15s %-15s %-15s\n", "ID", "AttachType",
|
||||
"AttachFlags", "Name");
|
||||
|
||||
for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
|
||||
/*
|
||||
* Not all attach types may be supported, so it's expected,
|
||||
* that some requests will fail.
|
||||
* If we were able to get the show for at least one
|
||||
* attach type, let's return 0.
|
||||
*/
|
||||
if (show_attached_bpf_progs(cgroup_fd, type) == 0)
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (json_output)
|
||||
jsonw_end_array(json_wtr);
|
||||
|
||||
close(cgroup_fd);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int do_attach(int argc, char **argv)
|
||||
{
|
||||
enum bpf_attach_type attach_type;
|
||||
int cgroup_fd, prog_fd;
|
||||
int attach_flags = 0;
|
||||
int ret = -1;
|
||||
int i;
|
||||
|
||||
if (argc < 4) {
|
||||
p_err("too few parameters for cgroup attach");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
cgroup_fd = open(argv[0], O_RDONLY);
|
||||
if (cgroup_fd < 0) {
|
||||
p_err("can't open cgroup %s", argv[1]);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
attach_type = parse_attach_type(argv[1]);
|
||||
if (attach_type == __MAX_BPF_ATTACH_TYPE) {
|
||||
p_err("invalid attach type");
|
||||
goto exit_cgroup;
|
||||
}
|
||||
|
||||
argc -= 2;
|
||||
argv = &argv[2];
|
||||
prog_fd = prog_parse_fd(&argc, &argv);
|
||||
if (prog_fd < 0)
|
||||
goto exit_cgroup;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (is_prefix(argv[i], "multi")) {
|
||||
attach_flags |= BPF_F_ALLOW_MULTI;
|
||||
} else if (is_prefix(argv[i], "override")) {
|
||||
attach_flags |= BPF_F_ALLOW_OVERRIDE;
|
||||
} else {
|
||||
p_err("unknown option: %s", argv[i]);
|
||||
goto exit_cgroup;
|
||||
}
|
||||
}
|
||||
|
||||
if (bpf_prog_attach(prog_fd, cgroup_fd, attach_type, attach_flags)) {
|
||||
p_err("failed to attach program");
|
||||
goto exit_prog;
|
||||
}
|
||||
|
||||
if (json_output)
|
||||
jsonw_null(json_wtr);
|
||||
|
||||
ret = 0;
|
||||
|
||||
exit_prog:
|
||||
close(prog_fd);
|
||||
exit_cgroup:
|
||||
close(cgroup_fd);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int do_detach(int argc, char **argv)
|
||||
{
|
||||
enum bpf_attach_type attach_type;
|
||||
int prog_fd, cgroup_fd;
|
||||
int ret = -1;
|
||||
|
||||
if (argc < 4) {
|
||||
p_err("too few parameters for cgroup detach");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
cgroup_fd = open(argv[0], O_RDONLY);
|
||||
if (cgroup_fd < 0) {
|
||||
p_err("can't open cgroup %s", argv[1]);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
attach_type = parse_attach_type(argv[1]);
|
||||
if (attach_type == __MAX_BPF_ATTACH_TYPE) {
|
||||
p_err("invalid attach type");
|
||||
goto exit_cgroup;
|
||||
}
|
||||
|
||||
argc -= 2;
|
||||
argv = &argv[2];
|
||||
prog_fd = prog_parse_fd(&argc, &argv);
|
||||
if (prog_fd < 0)
|
||||
goto exit_cgroup;
|
||||
|
||||
if (bpf_prog_detach2(prog_fd, cgroup_fd, attach_type)) {
|
||||
p_err("failed to detach program");
|
||||
goto exit_prog;
|
||||
}
|
||||
|
||||
if (json_output)
|
||||
jsonw_null(json_wtr);
|
||||
|
||||
ret = 0;
|
||||
|
||||
exit_prog:
|
||||
close(prog_fd);
|
||||
exit_cgroup:
|
||||
close(cgroup_fd);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int do_help(int argc, char **argv)
|
||||
{
|
||||
if (json_output) {
|
||||
jsonw_null(json_wtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"Usage: %s %s { show | list } CGROUP\n"
|
||||
" %s %s attach CGROUP ATTACH_TYPE PROG [ATTACH_FLAGS]\n"
|
||||
" %s %s detach CGROUP ATTACH_TYPE PROG\n"
|
||||
" %s %s help\n"
|
||||
"\n"
|
||||
" " HELP_SPEC_ATTACH_TYPES "\n"
|
||||
" " HELP_SPEC_ATTACH_FLAGS "\n"
|
||||
" " HELP_SPEC_PROGRAM "\n"
|
||||
" " HELP_SPEC_OPTIONS "\n"
|
||||
"",
|
||||
bin_name, argv[-2], bin_name, argv[-2],
|
||||
bin_name, argv[-2], bin_name, argv[-2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct cmd cmds[] = {
|
||||
{ "show", do_show },
|
||||
{ "list", do_show },
|
||||
{ "attach", do_attach },
|
||||
{ "detach", do_detach },
|
||||
{ "help", do_help },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
int do_cgroup(int argc, char **argv)
|
||||
{
|
||||
return cmd_select(cmds, argc, argv, do_help);
|
||||
}
|
||||
@@ -34,6 +34,7 @@
|
||||
/* Author: Jakub Kicinski <kubakici@wp.pl> */
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fts.h>
|
||||
#include <libgen.h>
|
||||
#include <mntent.h>
|
||||
@@ -44,7 +45,9 @@
|
||||
#include <unistd.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/magic.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/vfs.h>
|
||||
|
||||
@@ -163,13 +166,49 @@ int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)
|
||||
return fd;
|
||||
}
|
||||
|
||||
int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
|
||||
int do_pin_fd(int fd, const char *name)
|
||||
{
|
||||
char err_str[ERR_MAX_LEN];
|
||||
unsigned int id;
|
||||
char *endptr;
|
||||
char *file;
|
||||
char *dir;
|
||||
int err = 0;
|
||||
|
||||
err = bpf_obj_pin(fd, name);
|
||||
if (!err)
|
||||
goto out;
|
||||
|
||||
file = malloc(strlen(name) + 1);
|
||||
strcpy(file, name);
|
||||
dir = dirname(file);
|
||||
|
||||
if (errno != EPERM || is_bpffs(dir)) {
|
||||
p_err("can't pin the object (%s): %s", name, strerror(errno));
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* Attempt to mount bpffs, then retry pinning. */
|
||||
err = mnt_bpffs(dir, err_str, ERR_MAX_LEN);
|
||||
if (!err) {
|
||||
err = bpf_obj_pin(fd, name);
|
||||
if (err)
|
||||
p_err("can't pin the object (%s): %s", name,
|
||||
strerror(errno));
|
||||
} else {
|
||||
err_str[ERR_MAX_LEN - 1] = '\0';
|
||||
p_err("can't mount BPF file system to pin the object (%s): %s",
|
||||
name, err_str);
|
||||
}
|
||||
|
||||
out_free:
|
||||
free(file);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
|
||||
{
|
||||
unsigned int id;
|
||||
char *endptr;
|
||||
int err;
|
||||
int fd;
|
||||
|
||||
@@ -195,35 +234,8 @@ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = bpf_obj_pin(fd, *argv);
|
||||
if (!err)
|
||||
goto out_close;
|
||||
err = do_pin_fd(fd, *argv);
|
||||
|
||||
file = malloc(strlen(*argv) + 1);
|
||||
strcpy(file, *argv);
|
||||
dir = dirname(file);
|
||||
|
||||
if (errno != EPERM || is_bpffs(dir)) {
|
||||
p_err("can't pin the object (%s): %s", *argv, strerror(errno));
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* Attempt to mount bpffs, then retry pinning. */
|
||||
err = mnt_bpffs(dir, err_str, ERR_MAX_LEN);
|
||||
if (!err) {
|
||||
err = bpf_obj_pin(fd, *argv);
|
||||
if (err)
|
||||
p_err("can't pin the object (%s): %s", *argv,
|
||||
strerror(errno));
|
||||
} else {
|
||||
err_str[ERR_MAX_LEN - 1] = '\0';
|
||||
p_err("can't mount BPF file system to pin the object (%s): %s",
|
||||
*argv, err_str);
|
||||
}
|
||||
|
||||
out_free:
|
||||
free(file);
|
||||
out_close:
|
||||
close(fd);
|
||||
return err;
|
||||
}
|
||||
@@ -403,3 +415,124 @@ void delete_pinned_obj_table(struct pinned_obj_table *tab)
|
||||
free(obj);
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
ifindex_to_name_ns(__u32 ifindex, __u32 ns_dev, __u32 ns_ino, char *buf)
|
||||
{
|
||||
struct stat st;
|
||||
int err;
|
||||
|
||||
err = stat("/proc/self/ns/net", &st);
|
||||
if (err) {
|
||||
p_err("Can't stat /proc/self: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (st.st_dev != ns_dev || st.st_ino != ns_ino)
|
||||
return NULL;
|
||||
|
||||
return if_indextoname(ifindex, buf);
|
||||
}
|
||||
|
||||
static int read_sysfs_hex_int(char *path)
|
||||
{
|
||||
char vendor_id_buf[8];
|
||||
int len;
|
||||
int fd;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
p_err("Can't open %s: %s", path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = read(fd, vendor_id_buf, sizeof(vendor_id_buf));
|
||||
close(fd);
|
||||
if (len < 0) {
|
||||
p_err("Can't read %s: %s", path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (len >= (int)sizeof(vendor_id_buf)) {
|
||||
p_err("Value in %s too long", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
vendor_id_buf[len] = 0;
|
||||
|
||||
return strtol(vendor_id_buf, NULL, 0);
|
||||
}
|
||||
|
||||
static int read_sysfs_netdev_hex_int(char *devname, const char *entry_name)
|
||||
{
|
||||
char full_path[64];
|
||||
|
||||
snprintf(full_path, sizeof(full_path), "/sys/class/net/%s/device/%s",
|
||||
devname, entry_name);
|
||||
|
||||
return read_sysfs_hex_int(full_path);
|
||||
}
|
||||
|
||||
const char *ifindex_to_bfd_name_ns(__u32 ifindex, __u64 ns_dev, __u64 ns_ino)
|
||||
{
|
||||
char devname[IF_NAMESIZE];
|
||||
int vendor_id;
|
||||
int device_id;
|
||||
|
||||
if (!ifindex_to_name_ns(ifindex, ns_dev, ns_ino, devname)) {
|
||||
p_err("Can't get net device name for ifindex %d: %s", ifindex,
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vendor_id = read_sysfs_netdev_hex_int(devname, "vendor");
|
||||
if (vendor_id < 0) {
|
||||
p_err("Can't get device vendor id for %s", devname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (vendor_id) {
|
||||
case 0x19ee:
|
||||
device_id = read_sysfs_netdev_hex_int(devname, "device");
|
||||
if (device_id != 0x4000 &&
|
||||
device_id != 0x6000 &&
|
||||
device_id != 0x6003)
|
||||
p_info("Unknown NFP device ID, assuming it is NFP-6xxx arch");
|
||||
return "NFP-6xxx";
|
||||
default:
|
||||
p_err("Can't get bfd arch name for device vendor id 0x%04x",
|
||||
vendor_id);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void print_dev_plain(__u32 ifindex, __u64 ns_dev, __u64 ns_inode)
|
||||
{
|
||||
char name[IF_NAMESIZE];
|
||||
|
||||
if (!ifindex)
|
||||
return;
|
||||
|
||||
printf(" dev ");
|
||||
if (ifindex_to_name_ns(ifindex, ns_dev, ns_inode, name))
|
||||
printf("%s", name);
|
||||
else
|
||||
printf("ifindex %u ns_dev %llu ns_ino %llu",
|
||||
ifindex, ns_dev, ns_inode);
|
||||
}
|
||||
|
||||
void print_dev_json(__u32 ifindex, __u64 ns_dev, __u64 ns_inode)
|
||||
{
|
||||
char name[IF_NAMESIZE];
|
||||
|
||||
if (!ifindex)
|
||||
return;
|
||||
|
||||
jsonw_name(json_wtr, "dev");
|
||||
jsonw_start_object(json_wtr);
|
||||
jsonw_uint_field(json_wtr, "ifindex", ifindex);
|
||||
jsonw_uint_field(json_wtr, "ns_dev", ns_dev);
|
||||
jsonw_uint_field(json_wtr, "ns_inode", ns_inode);
|
||||
if (ifindex_to_name_ns(ifindex, ns_dev, ns_inode, name))
|
||||
jsonw_string_field(json_wtr, "ifname", name);
|
||||
jsonw_end_object(json_wtr);
|
||||
}
|
||||
|
||||
@@ -76,7 +76,8 @@ static int fprintf_json(void *out, const char *fmt, ...)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes)
|
||||
void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
|
||||
const char *arch)
|
||||
{
|
||||
disassembler_ftype disassemble;
|
||||
struct disassemble_info info;
|
||||
@@ -100,6 +101,19 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes)
|
||||
else
|
||||
init_disassemble_info(&info, stdout,
|
||||
(fprintf_ftype) fprintf);
|
||||
|
||||
/* Update architecture info for offload. */
|
||||
if (arch) {
|
||||
const bfd_arch_info_type *inf = bfd_scan_arch(arch);
|
||||
|
||||
if (inf) {
|
||||
bfdf->arch_info = inf;
|
||||
} else {
|
||||
p_err("No libfd support for %s", arch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
info.arch = bfd_get_arch(bfdf);
|
||||
info.mach = bfd_get_mach(bfdf);
|
||||
info.buffer = image;
|
||||
@@ -107,7 +121,14 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes)
|
||||
|
||||
disassemble_init_for_target(&info);
|
||||
|
||||
#ifdef DISASM_FOUR_ARGS_SIGNATURE
|
||||
disassemble = disassembler(info.arch,
|
||||
bfd_big_endian(bfdf),
|
||||
info.mach,
|
||||
bfdf);
|
||||
#else
|
||||
disassemble = disassembler(bfdf);
|
||||
#endif
|
||||
assert(disassemble);
|
||||
|
||||
if (json_output)
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/version.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -85,7 +84,7 @@ static int do_help(int argc, char **argv)
|
||||
" %s batch file FILE\n"
|
||||
" %s version\n"
|
||||
"\n"
|
||||
" OBJECT := { prog | map }\n"
|
||||
" OBJECT := { prog | map | cgroup }\n"
|
||||
" " HELP_SPEC_OPTIONS "\n"
|
||||
"",
|
||||
bin_name, bin_name, bin_name);
|
||||
@@ -95,21 +94,13 @@ static int do_help(int argc, char **argv)
|
||||
|
||||
static int do_version(int argc, char **argv)
|
||||
{
|
||||
unsigned int version[3];
|
||||
|
||||
version[0] = LINUX_VERSION_CODE >> 16;
|
||||
version[1] = LINUX_VERSION_CODE >> 8 & 0xf;
|
||||
version[2] = LINUX_VERSION_CODE & 0xf;
|
||||
|
||||
if (json_output) {
|
||||
jsonw_start_object(json_wtr);
|
||||
jsonw_name(json_wtr, "version");
|
||||
jsonw_printf(json_wtr, "\"%u.%u.%u\"",
|
||||
version[0], version[1], version[2]);
|
||||
jsonw_printf(json_wtr, "\"%s\"", BPFTOOL_VERSION);
|
||||
jsonw_end_object(json_wtr);
|
||||
} else {
|
||||
printf("%s v%u.%u.%u\n", bin_name,
|
||||
version[0], version[1], version[2]);
|
||||
printf("%s v%s\n", bin_name, BPFTOOL_VERSION);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -173,6 +164,7 @@ static const struct cmd cmds[] = {
|
||||
{ "batch", do_batch },
|
||||
{ "prog", do_prog },
|
||||
{ "map", do_map },
|
||||
{ "cgroup", do_cgroup },
|
||||
{ "version", do_version },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -96,6 +96,8 @@ struct pinned_obj {
|
||||
int build_pinned_obj_table(struct pinned_obj_table *table,
|
||||
enum bpf_obj_type type);
|
||||
void delete_pinned_obj_table(struct pinned_obj_table *tab);
|
||||
void print_dev_plain(__u32 ifindex, __u64 ns_dev, __u64 ns_inode);
|
||||
void print_dev_json(__u32 ifindex, __u64 ns_dev, __u64 ns_inode);
|
||||
|
||||
struct cmd {
|
||||
const char *cmd;
|
||||
@@ -111,13 +113,18 @@ char *get_fdinfo(int fd, const char *key);
|
||||
int open_obj_pinned(char *path);
|
||||
int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type);
|
||||
int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32));
|
||||
int do_pin_fd(int fd, const char *name);
|
||||
|
||||
int do_prog(int argc, char **arg);
|
||||
int do_map(int argc, char **arg);
|
||||
int do_cgroup(int argc, char **arg);
|
||||
|
||||
int prog_parse_fd(int *argc, char ***argv);
|
||||
|
||||
void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes);
|
||||
void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
|
||||
const char *arch);
|
||||
void print_hex_data_json(uint8_t *data, size_t len);
|
||||
|
||||
const char *ifindex_to_bfd_name_ns(__u32 ifindex, __u64 ns_dev, __u64 ns_ino);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -66,6 +66,7 @@ static const char * const map_type_name[] = {
|
||||
[BPF_MAP_TYPE_HASH_OF_MAPS] = "hash_of_maps",
|
||||
[BPF_MAP_TYPE_DEVMAP] = "devmap",
|
||||
[BPF_MAP_TYPE_SOCKMAP] = "sockmap",
|
||||
[BPF_MAP_TYPE_CPUMAP] = "cpumap",
|
||||
};
|
||||
|
||||
static unsigned int get_possible_cpus(void)
|
||||
@@ -428,6 +429,9 @@ static int show_map_close_json(int fd, struct bpf_map_info *info)
|
||||
|
||||
jsonw_name(json_wtr, "flags");
|
||||
jsonw_printf(json_wtr, "%#x", info->map_flags);
|
||||
|
||||
print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
|
||||
|
||||
jsonw_uint_field(json_wtr, "bytes_key", info->key_size);
|
||||
jsonw_uint_field(json_wtr, "bytes_value", info->value_size);
|
||||
jsonw_uint_field(json_wtr, "max_entries", info->max_entries);
|
||||
@@ -469,7 +473,9 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)
|
||||
if (*info->name)
|
||||
printf("name %s ", info->name);
|
||||
|
||||
printf("flags 0x%x\n", info->map_flags);
|
||||
printf("flags 0x%x", info->map_flags);
|
||||
print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
|
||||
printf("\n");
|
||||
printf("\tkey %uB value %uB max_entries %u",
|
||||
info->key_size, info->value_size, info->max_entries);
|
||||
|
||||
@@ -861,7 +867,7 @@ static int do_help(int argc, char **argv)
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"Usage: %s %s show [MAP]\n"
|
||||
"Usage: %s %s { show | list } [MAP]\n"
|
||||
" %s %s dump MAP\n"
|
||||
" %s %s update MAP key BYTES value VALUE [UPDATE_FLAGS]\n"
|
||||
" %s %s lookup MAP key BYTES\n"
|
||||
@@ -885,6 +891,7 @@ static int do_help(int argc, char **argv)
|
||||
|
||||
static const struct cmd cmds[] = {
|
||||
{ "show", do_show },
|
||||
{ "list", do_show },
|
||||
{ "help", do_help },
|
||||
{ "dump", do_dump },
|
||||
{ "update", do_update },
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <bpf.h>
|
||||
#include <libbpf.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "disasm.h"
|
||||
@@ -65,6 +66,7 @@ static const char * const prog_type_name[] = {
|
||||
[BPF_PROG_TYPE_LWT_XMIT] = "lwt_xmit",
|
||||
[BPF_PROG_TYPE_SOCK_OPS] = "sock_ops",
|
||||
[BPF_PROG_TYPE_SK_SKB] = "sk_skb",
|
||||
[BPF_PROG_TYPE_CGROUP_DEVICE] = "cgroup_device",
|
||||
};
|
||||
|
||||
static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
|
||||
@@ -229,6 +231,8 @@ static void print_prog_json(struct bpf_prog_info *info, int fd)
|
||||
info->tag[0], info->tag[1], info->tag[2], info->tag[3],
|
||||
info->tag[4], info->tag[5], info->tag[6], info->tag[7]);
|
||||
|
||||
print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
|
||||
|
||||
if (info->load_time) {
|
||||
char buf[32];
|
||||
|
||||
@@ -286,6 +290,7 @@ static void print_prog_plain(struct bpf_prog_info *info, int fd)
|
||||
|
||||
printf("tag ");
|
||||
fprint_hex(stdout, info->tag, BPF_TAG_SIZE, "");
|
||||
print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
|
||||
printf("\n");
|
||||
|
||||
if (info->load_time) {
|
||||
@@ -402,6 +407,88 @@ static int do_show(int argc, char **argv)
|
||||
return err;
|
||||
}
|
||||
|
||||
#define SYM_MAX_NAME 256
|
||||
|
||||
struct kernel_sym {
|
||||
unsigned long address;
|
||||
char name[SYM_MAX_NAME];
|
||||
};
|
||||
|
||||
struct dump_data {
|
||||
unsigned long address_call_base;
|
||||
struct kernel_sym *sym_mapping;
|
||||
__u32 sym_count;
|
||||
char scratch_buff[SYM_MAX_NAME];
|
||||
};
|
||||
|
||||
static int kernel_syms_cmp(const void *sym_a, const void *sym_b)
|
||||
{
|
||||
return ((struct kernel_sym *)sym_a)->address -
|
||||
((struct kernel_sym *)sym_b)->address;
|
||||
}
|
||||
|
||||
static void kernel_syms_load(struct dump_data *dd)
|
||||
{
|
||||
struct kernel_sym *sym;
|
||||
char buff[256];
|
||||
void *tmp, *address;
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen("/proc/kallsyms", "r");
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
while (!feof(fp)) {
|
||||
if (!fgets(buff, sizeof(buff), fp))
|
||||
break;
|
||||
tmp = realloc(dd->sym_mapping,
|
||||
(dd->sym_count + 1) *
|
||||
sizeof(*dd->sym_mapping));
|
||||
if (!tmp) {
|
||||
out:
|
||||
free(dd->sym_mapping);
|
||||
dd->sym_mapping = NULL;
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
dd->sym_mapping = tmp;
|
||||
sym = &dd->sym_mapping[dd->sym_count];
|
||||
if (sscanf(buff, "%p %*c %s", &address, sym->name) != 2)
|
||||
continue;
|
||||
sym->address = (unsigned long)address;
|
||||
if (!strcmp(sym->name, "__bpf_call_base")) {
|
||||
dd->address_call_base = sym->address;
|
||||
/* sysctl kernel.kptr_restrict was set */
|
||||
if (!sym->address)
|
||||
goto out;
|
||||
}
|
||||
if (sym->address)
|
||||
dd->sym_count++;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
qsort(dd->sym_mapping, dd->sym_count,
|
||||
sizeof(*dd->sym_mapping), kernel_syms_cmp);
|
||||
}
|
||||
|
||||
static void kernel_syms_destroy(struct dump_data *dd)
|
||||
{
|
||||
free(dd->sym_mapping);
|
||||
}
|
||||
|
||||
static struct kernel_sym *kernel_syms_search(struct dump_data *dd,
|
||||
unsigned long key)
|
||||
{
|
||||
struct kernel_sym sym = {
|
||||
.address = key,
|
||||
};
|
||||
|
||||
return dd->sym_mapping ?
|
||||
bsearch(&sym, dd->sym_mapping, dd->sym_count,
|
||||
sizeof(*dd->sym_mapping), kernel_syms_cmp) : NULL;
|
||||
}
|
||||
|
||||
static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
@@ -411,8 +498,71 @@ static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...)
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void dump_xlated_plain(void *buf, unsigned int len, bool opcodes)
|
||||
static const char *print_call_pcrel(struct dump_data *dd,
|
||||
struct kernel_sym *sym,
|
||||
unsigned long address,
|
||||
const struct bpf_insn *insn)
|
||||
{
|
||||
if (sym)
|
||||
snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
|
||||
"%+d#%s", insn->off, sym->name);
|
||||
else
|
||||
snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
|
||||
"%+d#0x%lx", insn->off, address);
|
||||
return dd->scratch_buff;
|
||||
}
|
||||
|
||||
static const char *print_call_helper(struct dump_data *dd,
|
||||
struct kernel_sym *sym,
|
||||
unsigned long address)
|
||||
{
|
||||
if (sym)
|
||||
snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
|
||||
"%s", sym->name);
|
||||
else
|
||||
snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
|
||||
"0x%lx", address);
|
||||
return dd->scratch_buff;
|
||||
}
|
||||
|
||||
static const char *print_call(void *private_data,
|
||||
const struct bpf_insn *insn)
|
||||
{
|
||||
struct dump_data *dd = private_data;
|
||||
unsigned long address = dd->address_call_base + insn->imm;
|
||||
struct kernel_sym *sym;
|
||||
|
||||
sym = kernel_syms_search(dd, address);
|
||||
if (insn->src_reg == BPF_PSEUDO_CALL)
|
||||
return print_call_pcrel(dd, sym, address, insn);
|
||||
else
|
||||
return print_call_helper(dd, sym, address);
|
||||
}
|
||||
|
||||
static const char *print_imm(void *private_data,
|
||||
const struct bpf_insn *insn,
|
||||
__u64 full_imm)
|
||||
{
|
||||
struct dump_data *dd = private_data;
|
||||
|
||||
if (insn->src_reg == BPF_PSEUDO_MAP_FD)
|
||||
snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
|
||||
"map[id:%u]", insn->imm);
|
||||
else
|
||||
snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
|
||||
"0x%llx", (unsigned long long)full_imm);
|
||||
return dd->scratch_buff;
|
||||
}
|
||||
|
||||
static void dump_xlated_plain(struct dump_data *dd, void *buf,
|
||||
unsigned int len, bool opcodes)
|
||||
{
|
||||
const struct bpf_insn_cbs cbs = {
|
||||
.cb_print = print_insn,
|
||||
.cb_call = print_call,
|
||||
.cb_imm = print_imm,
|
||||
.private_data = dd,
|
||||
};
|
||||
struct bpf_insn *insn = buf;
|
||||
bool double_insn = false;
|
||||
unsigned int i;
|
||||
@@ -426,7 +576,7 @@ static void dump_xlated_plain(void *buf, unsigned int len, bool opcodes)
|
||||
double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
|
||||
|
||||
printf("% 4d: ", i);
|
||||
print_bpf_insn(print_insn, NULL, insn + i, true);
|
||||
print_bpf_insn(&cbs, NULL, insn + i, true);
|
||||
|
||||
if (opcodes) {
|
||||
printf(" ");
|
||||
@@ -455,8 +605,15 @@ static void print_insn_json(struct bpf_verifier_env *env, const char *fmt, ...)
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void dump_xlated_json(void *buf, unsigned int len, bool opcodes)
|
||||
static void dump_xlated_json(struct dump_data *dd, void *buf,
|
||||
unsigned int len, bool opcodes)
|
||||
{
|
||||
const struct bpf_insn_cbs cbs = {
|
||||
.cb_print = print_insn_json,
|
||||
.cb_call = print_call,
|
||||
.cb_imm = print_imm,
|
||||
.private_data = dd,
|
||||
};
|
||||
struct bpf_insn *insn = buf;
|
||||
bool double_insn = false;
|
||||
unsigned int i;
|
||||
@@ -471,7 +628,7 @@ static void dump_xlated_json(void *buf, unsigned int len, bool opcodes)
|
||||
|
||||
jsonw_start_object(json_wtr);
|
||||
jsonw_name(json_wtr, "disasm");
|
||||
print_bpf_insn(print_insn_json, NULL, insn + i, true);
|
||||
print_bpf_insn(&cbs, NULL, insn + i, true);
|
||||
|
||||
if (opcodes) {
|
||||
jsonw_name(json_wtr, "opcodes");
|
||||
@@ -506,6 +663,7 @@ static void dump_xlated_json(void *buf, unsigned int len, bool opcodes)
|
||||
static int do_dump(int argc, char **argv)
|
||||
{
|
||||
struct bpf_prog_info info = {};
|
||||
struct dump_data dd = {};
|
||||
__u32 len = sizeof(info);
|
||||
unsigned int buf_size;
|
||||
char *filepath = NULL;
|
||||
@@ -593,6 +751,14 @@ static int do_dump(int argc, char **argv)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
if ((member_len == &info.jited_prog_len &&
|
||||
info.jited_prog_insns == 0) ||
|
||||
(member_len == &info.xlated_prog_len &&
|
||||
info.xlated_prog_insns == 0)) {
|
||||
p_err("error retrieving insn dump: kernel.kptr_restrict set?");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
if (filepath) {
|
||||
fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
if (fd < 0) {
|
||||
@@ -609,17 +775,29 @@ static int do_dump(int argc, char **argv)
|
||||
goto err_free;
|
||||
}
|
||||
} else {
|
||||
if (member_len == &info.jited_prog_len)
|
||||
disasm_print_insn(buf, *member_len, opcodes);
|
||||
else
|
||||
if (member_len == &info.jited_prog_len) {
|
||||
const char *name = NULL;
|
||||
|
||||
if (info.ifindex) {
|
||||
name = ifindex_to_bfd_name_ns(info.ifindex,
|
||||
info.netns_dev,
|
||||
info.netns_ino);
|
||||
if (!name)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
disasm_print_insn(buf, *member_len, opcodes, name);
|
||||
} else {
|
||||
kernel_syms_load(&dd);
|
||||
if (json_output)
|
||||
dump_xlated_json(buf, *member_len, opcodes);
|
||||
dump_xlated_json(&dd, buf, *member_len, opcodes);
|
||||
else
|
||||
dump_xlated_plain(buf, *member_len, opcodes);
|
||||
dump_xlated_plain(&dd, buf, *member_len, opcodes);
|
||||
kernel_syms_destroy(&dd);
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
@@ -637,6 +815,30 @@ static int do_pin(int argc, char **argv)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int do_load(int argc, char **argv)
|
||||
{
|
||||
struct bpf_object *obj;
|
||||
int prog_fd;
|
||||
|
||||
if (argc != 2)
|
||||
usage();
|
||||
|
||||
if (bpf_prog_load(argv[0], BPF_PROG_TYPE_UNSPEC, &obj, &prog_fd)) {
|
||||
p_err("failed to load program");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (do_pin_fd(prog_fd, argv[1])) {
|
||||
p_err("failed to pin program");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (json_output)
|
||||
jsonw_null(json_wtr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_help(int argc, char **argv)
|
||||
{
|
||||
if (json_output) {
|
||||
@@ -645,26 +847,29 @@ static int do_help(int argc, char **argv)
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"Usage: %s %s show [PROG]\n"
|
||||
"Usage: %s %s { show | list } [PROG]\n"
|
||||
" %s %s dump xlated PROG [{ file FILE | opcodes }]\n"
|
||||
" %s %s dump jited PROG [{ file FILE | opcodes }]\n"
|
||||
" %s %s pin PROG FILE\n"
|
||||
" %s %s load OBJ FILE\n"
|
||||
" %s %s help\n"
|
||||
"\n"
|
||||
" " HELP_SPEC_PROGRAM "\n"
|
||||
" " HELP_SPEC_OPTIONS "\n"
|
||||
"",
|
||||
bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
|
||||
bin_name, argv[-2], bin_name, argv[-2]);
|
||||
bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct cmd cmds[] = {
|
||||
{ "show", do_show },
|
||||
{ "list", do_show },
|
||||
{ "help", do_help },
|
||||
{ "dump", do_dump },
|
||||
{ "pin", do_pin },
|
||||
{ "load", do_load },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ FILES= \
|
||||
test-hello.bin \
|
||||
test-libaudit.bin \
|
||||
test-libbfd.bin \
|
||||
test-disassembler-four-args.bin \
|
||||
test-liberty.bin \
|
||||
test-liberty-z.bin \
|
||||
test-cplus-demangle.bin \
|
||||
@@ -197,6 +198,9 @@ $(OUTPUT)test-libpython-version.bin:
|
||||
$(OUTPUT)test-libbfd.bin:
|
||||
$(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
|
||||
|
||||
$(OUTPUT)test-disassembler-four-args.bin:
|
||||
$(BUILD) -DPACKAGE='"perf"' -lbfd -lopcodes
|
||||
|
||||
$(OUTPUT)test-liberty.bin:
|
||||
$(CC) $(CFLAGS) -Wall -Werror -o $@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty
|
||||
|
||||
|
||||
15
tools/build/feature/test-disassembler-four-args.c
Normal file
15
tools/build/feature/test-disassembler-four-args.c
Normal file
@@ -0,0 +1,15 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <bfd.h>
|
||||
#include <dis-asm.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
bfd *abfd = bfd_openr(NULL, NULL);
|
||||
|
||||
disassembler(bfd_get_arch(abfd),
|
||||
bfd_big_endian(abfd),
|
||||
bfd_get_mach(abfd),
|
||||
abfd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
@@ -23,12 +24,13 @@
|
||||
#include <getopt.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
int monitor_device(const char *device_name,
|
||||
unsigned int line,
|
||||
u_int32_t handleflags,
|
||||
u_int32_t eventflags,
|
||||
uint32_t handleflags,
|
||||
uint32_t eventflags,
|
||||
unsigned int loops)
|
||||
{
|
||||
struct gpioevent_request req;
|
||||
@@ -145,8 +147,8 @@ int main(int argc, char **argv)
|
||||
const char *device_name = NULL;
|
||||
unsigned int line = -1;
|
||||
unsigned int loops = 0;
|
||||
u_int32_t handleflags = GPIOHANDLE_REQUEST_INPUT;
|
||||
u_int32_t eventflags = 0;
|
||||
uint32_t handleflags = GPIOHANDLE_REQUEST_INPUT;
|
||||
uint32_t eventflags = 0;
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "c:n:o:dsrf?")) != -1) {
|
||||
|
||||
@@ -7,9 +7,30 @@ CFLAGS = $(WARNINGS) -g $(shell getconf LFS_CFLAGS)
|
||||
|
||||
CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include
|
||||
|
||||
all: hv_kvp_daemon hv_vss_daemon hv_fcopy_daemon
|
||||
sbindir ?= /usr/sbin
|
||||
libexecdir ?= /usr/libexec
|
||||
sharedstatedir ?= /var/lib
|
||||
|
||||
ALL_PROGRAMS := hv_kvp_daemon hv_vss_daemon hv_fcopy_daemon
|
||||
|
||||
ALL_SCRIPTS := hv_get_dhcp_info.sh hv_get_dns_info.sh hv_set_ifconfig.sh
|
||||
|
||||
all: $(ALL_PROGRAMS)
|
||||
|
||||
%: %.c
|
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
|
||||
clean:
|
||||
$(RM) hv_kvp_daemon hv_vss_daemon hv_fcopy_daemon
|
||||
|
||||
install: all
|
||||
install -d -m 755 $(DESTDIR)$(sbindir); \
|
||||
install -d -m 755 $(DESTDIR)$(libexecdir)/hypervkvpd; \
|
||||
install -d -m 755 $(DESTDIR)$(sharedstatedir); \
|
||||
for program in $(ALL_PROGRAMS); do \
|
||||
install $$program -m 755 $(DESTDIR)$(sbindir); \
|
||||
done; \
|
||||
install -m 755 lsvmbus $(DESTDIR)$(sbindir); \
|
||||
for script in $(ALL_SCRIPTS); do \
|
||||
install $$script -m 755 $(DESTDIR)$(libexecdir)/hypervkvpd/$${script%.sh}; \
|
||||
done
|
||||
|
||||
@@ -16,6 +16,22 @@ extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
|
||||
size, unsigned long offset);
|
||||
#endif
|
||||
|
||||
#ifndef find_next_and_bit
|
||||
/**
|
||||
* find_next_and_bit - find the next set bit in both memory regions
|
||||
* @addr1: The first address to base the search on
|
||||
* @addr2: The second address to base the search on
|
||||
* @offset: The bitnumber to start searching at
|
||||
* @size: The bitmap size in bits
|
||||
*
|
||||
* Returns the bit number for the next set bit
|
||||
* If no bits are set, returns @size.
|
||||
*/
|
||||
extern unsigned long find_next_and_bit(const unsigned long *addr1,
|
||||
const unsigned long *addr2, unsigned long size,
|
||||
unsigned long offset);
|
||||
#endif
|
||||
|
||||
#ifndef find_next_zero_bit
|
||||
|
||||
/**
|
||||
|
||||
@@ -86,6 +86,62 @@ enum i915_mocs_table_index {
|
||||
I915_MOCS_CACHED,
|
||||
};
|
||||
|
||||
/*
|
||||
* Different engines serve different roles, and there may be more than one
|
||||
* engine serving each role. enum drm_i915_gem_engine_class provides a
|
||||
* classification of the role of the engine, which may be used when requesting
|
||||
* operations to be performed on a certain subset of engines, or for providing
|
||||
* information about that group.
|
||||
*/
|
||||
enum drm_i915_gem_engine_class {
|
||||
I915_ENGINE_CLASS_RENDER = 0,
|
||||
I915_ENGINE_CLASS_COPY = 1,
|
||||
I915_ENGINE_CLASS_VIDEO = 2,
|
||||
I915_ENGINE_CLASS_VIDEO_ENHANCE = 3,
|
||||
|
||||
I915_ENGINE_CLASS_INVALID = -1
|
||||
};
|
||||
|
||||
/**
|
||||
* DOC: perf_events exposed by i915 through /sys/bus/event_sources/drivers/i915
|
||||
*
|
||||
*/
|
||||
|
||||
enum drm_i915_pmu_engine_sample {
|
||||
I915_SAMPLE_BUSY = 0,
|
||||
I915_SAMPLE_WAIT = 1,
|
||||
I915_SAMPLE_SEMA = 2
|
||||
};
|
||||
|
||||
#define I915_PMU_SAMPLE_BITS (4)
|
||||
#define I915_PMU_SAMPLE_MASK (0xf)
|
||||
#define I915_PMU_SAMPLE_INSTANCE_BITS (8)
|
||||
#define I915_PMU_CLASS_SHIFT \
|
||||
(I915_PMU_SAMPLE_BITS + I915_PMU_SAMPLE_INSTANCE_BITS)
|
||||
|
||||
#define __I915_PMU_ENGINE(class, instance, sample) \
|
||||
((class) << I915_PMU_CLASS_SHIFT | \
|
||||
(instance) << I915_PMU_SAMPLE_BITS | \
|
||||
(sample))
|
||||
|
||||
#define I915_PMU_ENGINE_BUSY(class, instance) \
|
||||
__I915_PMU_ENGINE(class, instance, I915_SAMPLE_BUSY)
|
||||
|
||||
#define I915_PMU_ENGINE_WAIT(class, instance) \
|
||||
__I915_PMU_ENGINE(class, instance, I915_SAMPLE_WAIT)
|
||||
|
||||
#define I915_PMU_ENGINE_SEMA(class, instance) \
|
||||
__I915_PMU_ENGINE(class, instance, I915_SAMPLE_SEMA)
|
||||
|
||||
#define __I915_PMU_OTHER(x) (__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x))
|
||||
|
||||
#define I915_PMU_ACTUAL_FREQUENCY __I915_PMU_OTHER(0)
|
||||
#define I915_PMU_REQUESTED_FREQUENCY __I915_PMU_OTHER(1)
|
||||
#define I915_PMU_INTERRUPTS __I915_PMU_OTHER(2)
|
||||
#define I915_PMU_RC6_RESIDENCY __I915_PMU_OTHER(3)
|
||||
|
||||
#define I915_PMU_LAST I915_PMU_RC6_RESIDENCY
|
||||
|
||||
/* Each region is a minimum of 16k, and there are at most 255 of them.
|
||||
*/
|
||||
#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use
|
||||
@@ -450,6 +506,27 @@ typedef struct drm_i915_irq_wait {
|
||||
*/
|
||||
#define I915_PARAM_HAS_EXEC_FENCE_ARRAY 49
|
||||
|
||||
/*
|
||||
* Query whether every context (both per-file default and user created) is
|
||||
* isolated (insofar as HW supports). If this parameter is not true, then
|
||||
* freshly created contexts may inherit values from an existing context,
|
||||
* rather than default HW values. If true, it also ensures (insofar as HW
|
||||
* supports) that all state set by this context will not leak to any other
|
||||
* context.
|
||||
*
|
||||
* As not every engine across every gen support contexts, the returned
|
||||
* value reports the support of context isolation for individual engines by
|
||||
* returning a bitmask of each engine class set to true if that class supports
|
||||
* isolation.
|
||||
*/
|
||||
#define I915_PARAM_HAS_CONTEXT_ISOLATION 50
|
||||
|
||||
/* Frequency of the command streamer timestamps given by the *_TIMESTAMP
|
||||
* registers. This used to be fixed per platform but from CNL onwards, this
|
||||
* might vary depending on the parts.
|
||||
*/
|
||||
#define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51
|
||||
|
||||
typedef struct drm_i915_getparam {
|
||||
__s32 param;
|
||||
/*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#define BPF_ALU64 0x07 /* alu mode in double word width */
|
||||
|
||||
/* ld/ldx fields */
|
||||
#define BPF_DW 0x18 /* double word */
|
||||
#define BPF_DW 0x18 /* double word (64-bit) */
|
||||
#define BPF_XADD 0xc0 /* exclusive add */
|
||||
|
||||
/* alu/jmp fields */
|
||||
@@ -197,8 +197,14 @@ enum bpf_attach_type {
|
||||
*/
|
||||
#define BPF_F_STRICT_ALIGNMENT (1U << 0)
|
||||
|
||||
/* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */
|
||||
#define BPF_PSEUDO_MAP_FD 1
|
||||
|
||||
/* when bpf_call->src_reg == BPF_PSEUDO_CALL, bpf_call->imm == pc-relative
|
||||
* offset to another bpf function
|
||||
*/
|
||||
#define BPF_PSEUDO_CALL 1
|
||||
|
||||
/* flags for BPF_MAP_UPDATE_ELEM command */
|
||||
#define BPF_ANY 0 /* create new element or update existing */
|
||||
#define BPF_NOEXIST 1 /* create new element if it didn't exist */
|
||||
@@ -239,6 +245,7 @@ union bpf_attr {
|
||||
* BPF_F_NUMA_NODE is set).
|
||||
*/
|
||||
char map_name[BPF_OBJ_NAME_LEN];
|
||||
__u32 map_ifindex; /* ifindex of netdev to create on */
|
||||
};
|
||||
|
||||
struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */
|
||||
@@ -635,6 +642,14 @@ union bpf_attr {
|
||||
* @optlen: length of optval in bytes
|
||||
* Return: 0 or negative error
|
||||
*
|
||||
* int bpf_sock_ops_cb_flags_set(bpf_sock_ops, flags)
|
||||
* Set callback flags for sock_ops
|
||||
* @bpf_sock_ops: pointer to bpf_sock_ops_kern struct
|
||||
* @flags: flags value
|
||||
* Return: 0 for no error
|
||||
* -EINVAL if there is no full tcp socket
|
||||
* bits in flags that are not supported by current kernel
|
||||
*
|
||||
* int bpf_skb_adjust_room(skb, len_diff, mode, flags)
|
||||
* Grow or shrink room in sk_buff.
|
||||
* @skb: pointer to skb
|
||||
@@ -677,6 +692,10 @@ union bpf_attr {
|
||||
* @buf: buf to fill
|
||||
* @buf_size: size of the buf
|
||||
* Return : 0 on success or negative error code
|
||||
*
|
||||
* int bpf_override_return(pt_regs, rc)
|
||||
* @pt_regs: pointer to struct pt_regs
|
||||
* @rc: the return value to set
|
||||
*/
|
||||
#define __BPF_FUNC_MAPPER(FN) \
|
||||
FN(unspec), \
|
||||
@@ -736,7 +755,9 @@ union bpf_attr {
|
||||
FN(xdp_adjust_meta), \
|
||||
FN(perf_event_read_value), \
|
||||
FN(perf_prog_read_value), \
|
||||
FN(getsockopt),
|
||||
FN(getsockopt), \
|
||||
FN(override_return), \
|
||||
FN(sock_ops_cb_flags_set),
|
||||
|
||||
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
||||
* function eBPF program intends to call
|
||||
@@ -888,6 +909,9 @@ struct xdp_md {
|
||||
__u32 data;
|
||||
__u32 data_end;
|
||||
__u32 data_meta;
|
||||
/* Below access go through struct xdp_rxq_info */
|
||||
__u32 ingress_ifindex; /* rxq->dev->ifindex */
|
||||
__u32 rx_queue_index; /* rxq->queue_index */
|
||||
};
|
||||
|
||||
enum sk_action {
|
||||
@@ -910,6 +934,9 @@ struct bpf_prog_info {
|
||||
__u32 nr_map_ids;
|
||||
__aligned_u64 map_ids;
|
||||
char name[BPF_OBJ_NAME_LEN];
|
||||
__u32 ifindex;
|
||||
__u64 netns_dev;
|
||||
__u64 netns_ino;
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
struct bpf_map_info {
|
||||
@@ -920,6 +947,9 @@ struct bpf_map_info {
|
||||
__u32 max_entries;
|
||||
__u32 map_flags;
|
||||
char name[BPF_OBJ_NAME_LEN];
|
||||
__u32 ifindex;
|
||||
__u64 netns_dev;
|
||||
__u64 netns_ino;
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
/* User bpf_sock_ops struct to access socket values and specify request ops
|
||||
@@ -931,8 +961,9 @@ struct bpf_map_info {
|
||||
struct bpf_sock_ops {
|
||||
__u32 op;
|
||||
union {
|
||||
__u32 reply;
|
||||
__u32 replylong[4];
|
||||
__u32 args[4]; /* Optionally passed to bpf program */
|
||||
__u32 reply; /* Returned by bpf program */
|
||||
__u32 replylong[4]; /* Optionally returned by bpf prog */
|
||||
};
|
||||
__u32 family;
|
||||
__u32 remote_ip4; /* Stored in network byte order */
|
||||
@@ -941,8 +972,45 @@ struct bpf_sock_ops {
|
||||
__u32 local_ip6[4]; /* Stored in network byte order */
|
||||
__u32 remote_port; /* Stored in network byte order */
|
||||
__u32 local_port; /* stored in host byte order */
|
||||
__u32 is_fullsock; /* Some TCP fields are only valid if
|
||||
* there is a full socket. If not, the
|
||||
* fields read as zero.
|
||||
*/
|
||||
__u32 snd_cwnd;
|
||||
__u32 srtt_us; /* Averaged RTT << 3 in usecs */
|
||||
__u32 bpf_sock_ops_cb_flags; /* flags defined in uapi/linux/tcp.h */
|
||||
__u32 state;
|
||||
__u32 rtt_min;
|
||||
__u32 snd_ssthresh;
|
||||
__u32 rcv_nxt;
|
||||
__u32 snd_nxt;
|
||||
__u32 snd_una;
|
||||
__u32 mss_cache;
|
||||
__u32 ecn_flags;
|
||||
__u32 rate_delivered;
|
||||
__u32 rate_interval_us;
|
||||
__u32 packets_out;
|
||||
__u32 retrans_out;
|
||||
__u32 total_retrans;
|
||||
__u32 segs_in;
|
||||
__u32 data_segs_in;
|
||||
__u32 segs_out;
|
||||
__u32 data_segs_out;
|
||||
__u32 lost_out;
|
||||
__u32 sacked_out;
|
||||
__u32 sk_txhash;
|
||||
__u64 bytes_received;
|
||||
__u64 bytes_acked;
|
||||
};
|
||||
|
||||
/* Definitions for bpf_sock_ops_cb_flags */
|
||||
#define BPF_SOCK_OPS_RTO_CB_FLAG (1<<0)
|
||||
#define BPF_SOCK_OPS_RETRANS_CB_FLAG (1<<1)
|
||||
#define BPF_SOCK_OPS_STATE_CB_FLAG (1<<2)
|
||||
#define BPF_SOCK_OPS_ALL_CB_FLAGS 0x7 /* Mask of all currently
|
||||
* supported cb flags
|
||||
*/
|
||||
|
||||
/* List of known BPF sock_ops operators.
|
||||
* New entries can only be added at the end
|
||||
*/
|
||||
@@ -976,6 +1044,43 @@ enum {
|
||||
* a congestion threshold. RTTs above
|
||||
* this indicate congestion
|
||||
*/
|
||||
BPF_SOCK_OPS_RTO_CB, /* Called when an RTO has triggered.
|
||||
* Arg1: value of icsk_retransmits
|
||||
* Arg2: value of icsk_rto
|
||||
* Arg3: whether RTO has expired
|
||||
*/
|
||||
BPF_SOCK_OPS_RETRANS_CB, /* Called when skb is retransmitted.
|
||||
* Arg1: sequence number of 1st byte
|
||||
* Arg2: # segments
|
||||
* Arg3: return value of
|
||||
* tcp_transmit_skb (0 => success)
|
||||
*/
|
||||
BPF_SOCK_OPS_STATE_CB, /* Called when TCP changes state.
|
||||
* Arg1: old_state
|
||||
* Arg2: new_state
|
||||
*/
|
||||
};
|
||||
|
||||
/* List of TCP states. There is a build check in net/ipv4/tcp.c to detect
|
||||
* changes between the TCP and BPF versions. Ideally this should never happen.
|
||||
* If it does, we need to add code to convert them before calling
|
||||
* the BPF sock_ops function.
|
||||
*/
|
||||
enum {
|
||||
BPF_TCP_ESTABLISHED = 1,
|
||||
BPF_TCP_SYN_SENT,
|
||||
BPF_TCP_SYN_RECV,
|
||||
BPF_TCP_FIN_WAIT1,
|
||||
BPF_TCP_FIN_WAIT2,
|
||||
BPF_TCP_TIME_WAIT,
|
||||
BPF_TCP_CLOSE,
|
||||
BPF_TCP_CLOSE_WAIT,
|
||||
BPF_TCP_LAST_ACK,
|
||||
BPF_TCP_LISTEN,
|
||||
BPF_TCP_CLOSING, /* Now a valid state */
|
||||
BPF_TCP_NEW_SYN_RECV,
|
||||
|
||||
BPF_TCP_MAX_STATES /* Leave at the end! */
|
||||
};
|
||||
|
||||
#define TCP_BPF_IW 1001 /* Set TCP initial congestion window */
|
||||
@@ -995,7 +1100,8 @@ struct bpf_perf_event_value {
|
||||
#define BPF_DEVCG_DEV_CHAR (1ULL << 1)
|
||||
|
||||
struct bpf_cgroup_dev_ctx {
|
||||
__u32 access_type; /* (access << 16) | type */
|
||||
/* access_type encoded as (BPF_DEVCG_ACC_* << 16) | BPF_DEVCG_DEV_* */
|
||||
__u32 access_type;
|
||||
__u32 major;
|
||||
__u32 minor;
|
||||
};
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
|
||||
/* ld/ldx fields */
|
||||
#define BPF_SIZE(code) ((code) & 0x18)
|
||||
#define BPF_W 0x00
|
||||
#define BPF_H 0x08
|
||||
#define BPF_B 0x10
|
||||
#define BPF_W 0x00 /* 32-bit */
|
||||
#define BPF_H 0x08 /* 16-bit */
|
||||
#define BPF_B 0x10 /* 8-bit */
|
||||
/* eBPF BPF_DW 0x18 64-bit */
|
||||
#define BPF_MODE(code) ((code) & 0xe0)
|
||||
#define BPF_IMM 0x00
|
||||
#define BPF_ABS 0x20
|
||||
|
||||
944
tools/include/uapi/linux/if_link.h
Normal file
944
tools/include/uapi/linux/if_link.h
Normal file
@@ -0,0 +1,944 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI_LINUX_IF_LINK_H
|
||||
#define _UAPI_LINUX_IF_LINK_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netlink.h>
|
||||
|
||||
/* This struct should be in sync with struct rtnl_link_stats64 */
|
||||
struct rtnl_link_stats {
|
||||
__u32 rx_packets; /* total packets received */
|
||||
__u32 tx_packets; /* total packets transmitted */
|
||||
__u32 rx_bytes; /* total bytes received */
|
||||
__u32 tx_bytes; /* total bytes transmitted */
|
||||
__u32 rx_errors; /* bad packets received */
|
||||
__u32 tx_errors; /* packet transmit problems */
|
||||
__u32 rx_dropped; /* no space in linux buffers */
|
||||
__u32 tx_dropped; /* no space available in linux */
|
||||
__u32 multicast; /* multicast packets received */
|
||||
__u32 collisions;
|
||||
|
||||
/* detailed rx_errors: */
|
||||
__u32 rx_length_errors;
|
||||
__u32 rx_over_errors; /* receiver ring buff overflow */
|
||||
__u32 rx_crc_errors; /* recved pkt with crc error */
|
||||
__u32 rx_frame_errors; /* recv'd frame alignment error */
|
||||
__u32 rx_fifo_errors; /* recv'r fifo overrun */
|
||||
__u32 rx_missed_errors; /* receiver missed packet */
|
||||
|
||||
/* detailed tx_errors */
|
||||
__u32 tx_aborted_errors;
|
||||
__u32 tx_carrier_errors;
|
||||
__u32 tx_fifo_errors;
|
||||
__u32 tx_heartbeat_errors;
|
||||
__u32 tx_window_errors;
|
||||
|
||||
/* for cslip etc */
|
||||
__u32 rx_compressed;
|
||||
__u32 tx_compressed;
|
||||
|
||||
__u32 rx_nohandler; /* dropped, no handler found */
|
||||
};
|
||||
|
||||
/* The main device statistics structure */
|
||||
struct rtnl_link_stats64 {
|
||||
__u64 rx_packets; /* total packets received */
|
||||
__u64 tx_packets; /* total packets transmitted */
|
||||
__u64 rx_bytes; /* total bytes received */
|
||||
__u64 tx_bytes; /* total bytes transmitted */
|
||||
__u64 rx_errors; /* bad packets received */
|
||||
__u64 tx_errors; /* packet transmit problems */
|
||||
__u64 rx_dropped; /* no space in linux buffers */
|
||||
__u64 tx_dropped; /* no space available in linux */
|
||||
__u64 multicast; /* multicast packets received */
|
||||
__u64 collisions;
|
||||
|
||||
/* detailed rx_errors: */
|
||||
__u64 rx_length_errors;
|
||||
__u64 rx_over_errors; /* receiver ring buff overflow */
|
||||
__u64 rx_crc_errors; /* recved pkt with crc error */
|
||||
__u64 rx_frame_errors; /* recv'd frame alignment error */
|
||||
__u64 rx_fifo_errors; /* recv'r fifo overrun */
|
||||
__u64 rx_missed_errors; /* receiver missed packet */
|
||||
|
||||
/* detailed tx_errors */
|
||||
__u64 tx_aborted_errors;
|
||||
__u64 tx_carrier_errors;
|
||||
__u64 tx_fifo_errors;
|
||||
__u64 tx_heartbeat_errors;
|
||||
__u64 tx_window_errors;
|
||||
|
||||
/* for cslip etc */
|
||||
__u64 rx_compressed;
|
||||
__u64 tx_compressed;
|
||||
|
||||
__u64 rx_nohandler; /* dropped, no handler found */
|
||||
};
|
||||
|
||||
/* The struct should be in sync with struct ifmap */
|
||||
struct rtnl_link_ifmap {
|
||||
__u64 mem_start;
|
||||
__u64 mem_end;
|
||||
__u64 base_addr;
|
||||
__u16 irq;
|
||||
__u8 dma;
|
||||
__u8 port;
|
||||
};
|
||||
|
||||
/*
|
||||
* IFLA_AF_SPEC
|
||||
* Contains nested attributes for address family specific attributes.
|
||||
* Each address family may create a attribute with the address family
|
||||
* number as type and create its own attribute structure in it.
|
||||
*
|
||||
* Example:
|
||||
* [IFLA_AF_SPEC] = {
|
||||
* [AF_INET] = {
|
||||
* [IFLA_INET_CONF] = ...,
|
||||
* },
|
||||
* [AF_INET6] = {
|
||||
* [IFLA_INET6_FLAGS] = ...,
|
||||
* [IFLA_INET6_CONF] = ...,
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
|
||||
enum {
|
||||
IFLA_UNSPEC,
|
||||
IFLA_ADDRESS,
|
||||
IFLA_BROADCAST,
|
||||
IFLA_IFNAME,
|
||||
IFLA_MTU,
|
||||
IFLA_LINK,
|
||||
IFLA_QDISC,
|
||||
IFLA_STATS,
|
||||
IFLA_COST,
|
||||
#define IFLA_COST IFLA_COST
|
||||
IFLA_PRIORITY,
|
||||
#define IFLA_PRIORITY IFLA_PRIORITY
|
||||
IFLA_MASTER,
|
||||
#define IFLA_MASTER IFLA_MASTER
|
||||
IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */
|
||||
#define IFLA_WIRELESS IFLA_WIRELESS
|
||||
IFLA_PROTINFO, /* Protocol specific information for a link */
|
||||
#define IFLA_PROTINFO IFLA_PROTINFO
|
||||
IFLA_TXQLEN,
|
||||
#define IFLA_TXQLEN IFLA_TXQLEN
|
||||
IFLA_MAP,
|
||||
#define IFLA_MAP IFLA_MAP
|
||||
IFLA_WEIGHT,
|
||||
#define IFLA_WEIGHT IFLA_WEIGHT
|
||||
IFLA_OPERSTATE,
|
||||
IFLA_LINKMODE,
|
||||
IFLA_LINKINFO,
|
||||
#define IFLA_LINKINFO IFLA_LINKINFO
|
||||
IFLA_NET_NS_PID,
|
||||
IFLA_IFALIAS,
|
||||
IFLA_NUM_VF, /* Number of VFs if device is SR-IOV PF */
|
||||
IFLA_VFINFO_LIST,
|
||||
IFLA_STATS64,
|
||||
IFLA_VF_PORTS,
|
||||
IFLA_PORT_SELF,
|
||||
IFLA_AF_SPEC,
|
||||
IFLA_GROUP, /* Group the device belongs to */
|
||||
IFLA_NET_NS_FD,
|
||||
IFLA_EXT_MASK, /* Extended info mask, VFs, etc */
|
||||
IFLA_PROMISCUITY, /* Promiscuity count: > 0 means acts PROMISC */
|
||||
#define IFLA_PROMISCUITY IFLA_PROMISCUITY
|
||||
IFLA_NUM_TX_QUEUES,
|
||||
IFLA_NUM_RX_QUEUES,
|
||||
IFLA_CARRIER,
|
||||
IFLA_PHYS_PORT_ID,
|
||||
IFLA_CARRIER_CHANGES,
|
||||
IFLA_PHYS_SWITCH_ID,
|
||||
IFLA_LINK_NETNSID,
|
||||
IFLA_PHYS_PORT_NAME,
|
||||
IFLA_PROTO_DOWN,
|
||||
IFLA_GSO_MAX_SEGS,
|
||||
IFLA_GSO_MAX_SIZE,
|
||||
IFLA_PAD,
|
||||
IFLA_XDP,
|
||||
IFLA_EVENT,
|
||||
IFLA_NEW_NETNSID,
|
||||
IFLA_IF_NETNSID,
|
||||
IFLA_CARRIER_UP_COUNT,
|
||||
IFLA_CARRIER_DOWN_COUNT,
|
||||
IFLA_NEW_IFINDEX,
|
||||
__IFLA_MAX
|
||||
};
|
||||
|
||||
|
||||
#define IFLA_MAX (__IFLA_MAX - 1)
|
||||
|
||||
/* backwards compatibility for userspace */
|
||||
#ifndef __KERNEL__
|
||||
#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
|
||||
#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
|
||||
#endif
|
||||
|
||||
enum {
|
||||
IFLA_INET_UNSPEC,
|
||||
IFLA_INET_CONF,
|
||||
__IFLA_INET_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_INET_MAX (__IFLA_INET_MAX - 1)
|
||||
|
||||
/* ifi_flags.
|
||||
|
||||
IFF_* flags.
|
||||
|
||||
The only change is:
|
||||
IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are
|
||||
more not changeable by user. They describe link media
|
||||
characteristics and set by device driver.
|
||||
|
||||
Comments:
|
||||
- Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid
|
||||
- If neither of these three flags are set;
|
||||
the interface is NBMA.
|
||||
|
||||
- IFF_MULTICAST does not mean anything special:
|
||||
multicasts can be used on all not-NBMA links.
|
||||
IFF_MULTICAST means that this media uses special encapsulation
|
||||
for multicast frames. Apparently, all IFF_POINTOPOINT and
|
||||
IFF_BROADCAST devices are able to use multicasts too.
|
||||
*/
|
||||
|
||||
/* IFLA_LINK.
|
||||
For usual devices it is equal ifi_index.
|
||||
If it is a "virtual interface" (f.e. tunnel), ifi_link
|
||||
can point to real physical interface (f.e. for bandwidth calculations),
|
||||
or maybe 0, what means, that real media is unknown (usual
|
||||
for IPIP tunnels, when route to endpoint is allowed to change)
|
||||
*/
|
||||
|
||||
/* Subtype attributes for IFLA_PROTINFO */
|
||||
enum {
|
||||
IFLA_INET6_UNSPEC,
|
||||
IFLA_INET6_FLAGS, /* link flags */
|
||||
IFLA_INET6_CONF, /* sysctl parameters */
|
||||
IFLA_INET6_STATS, /* statistics */
|
||||
IFLA_INET6_MCAST, /* MC things. What of them? */
|
||||
IFLA_INET6_CACHEINFO, /* time values and max reasm size */
|
||||
IFLA_INET6_ICMP6STATS, /* statistics (icmpv6) */
|
||||
IFLA_INET6_TOKEN, /* device token */
|
||||
IFLA_INET6_ADDR_GEN_MODE, /* implicit address generator mode */
|
||||
__IFLA_INET6_MAX
|
||||
};
|
||||
|
||||
#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
|
||||
|
||||
enum in6_addr_gen_mode {
|
||||
IN6_ADDR_GEN_MODE_EUI64,
|
||||
IN6_ADDR_GEN_MODE_NONE,
|
||||
IN6_ADDR_GEN_MODE_STABLE_PRIVACY,
|
||||
IN6_ADDR_GEN_MODE_RANDOM,
|
||||
};
|
||||
|
||||
/* Bridge section */
|
||||
|
||||
enum {
|
||||
IFLA_BR_UNSPEC,
|
||||
IFLA_BR_FORWARD_DELAY,
|
||||
IFLA_BR_HELLO_TIME,
|
||||
IFLA_BR_MAX_AGE,
|
||||
IFLA_BR_AGEING_TIME,
|
||||
IFLA_BR_STP_STATE,
|
||||
IFLA_BR_PRIORITY,
|
||||
IFLA_BR_VLAN_FILTERING,
|
||||
IFLA_BR_VLAN_PROTOCOL,
|
||||
IFLA_BR_GROUP_FWD_MASK,
|
||||
IFLA_BR_ROOT_ID,
|
||||
IFLA_BR_BRIDGE_ID,
|
||||
IFLA_BR_ROOT_PORT,
|
||||
IFLA_BR_ROOT_PATH_COST,
|
||||
IFLA_BR_TOPOLOGY_CHANGE,
|
||||
IFLA_BR_TOPOLOGY_CHANGE_DETECTED,
|
||||
IFLA_BR_HELLO_TIMER,
|
||||
IFLA_BR_TCN_TIMER,
|
||||
IFLA_BR_TOPOLOGY_CHANGE_TIMER,
|
||||
IFLA_BR_GC_TIMER,
|
||||
IFLA_BR_GROUP_ADDR,
|
||||
IFLA_BR_FDB_FLUSH,
|
||||
IFLA_BR_MCAST_ROUTER,
|
||||
IFLA_BR_MCAST_SNOOPING,
|
||||
IFLA_BR_MCAST_QUERY_USE_IFADDR,
|
||||
IFLA_BR_MCAST_QUERIER,
|
||||
IFLA_BR_MCAST_HASH_ELASTICITY,
|
||||
IFLA_BR_MCAST_HASH_MAX,
|
||||
IFLA_BR_MCAST_LAST_MEMBER_CNT,
|
||||
IFLA_BR_MCAST_STARTUP_QUERY_CNT,
|
||||
IFLA_BR_MCAST_LAST_MEMBER_INTVL,
|
||||
IFLA_BR_MCAST_MEMBERSHIP_INTVL,
|
||||
IFLA_BR_MCAST_QUERIER_INTVL,
|
||||
IFLA_BR_MCAST_QUERY_INTVL,
|
||||
IFLA_BR_MCAST_QUERY_RESPONSE_INTVL,
|
||||
IFLA_BR_MCAST_STARTUP_QUERY_INTVL,
|
||||
IFLA_BR_NF_CALL_IPTABLES,
|
||||
IFLA_BR_NF_CALL_IP6TABLES,
|
||||
IFLA_BR_NF_CALL_ARPTABLES,
|
||||
IFLA_BR_VLAN_DEFAULT_PVID,
|
||||
IFLA_BR_PAD,
|
||||
IFLA_BR_VLAN_STATS_ENABLED,
|
||||
IFLA_BR_MCAST_STATS_ENABLED,
|
||||
IFLA_BR_MCAST_IGMP_VERSION,
|
||||
IFLA_BR_MCAST_MLD_VERSION,
|
||||
__IFLA_BR_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_BR_MAX (__IFLA_BR_MAX - 1)
|
||||
|
||||
struct ifla_bridge_id {
|
||||
__u8 prio[2];
|
||||
__u8 addr[6]; /* ETH_ALEN */
|
||||
};
|
||||
|
||||
enum {
|
||||
BRIDGE_MODE_UNSPEC,
|
||||
BRIDGE_MODE_HAIRPIN,
|
||||
};
|
||||
|
||||
enum {
|
||||
IFLA_BRPORT_UNSPEC,
|
||||
IFLA_BRPORT_STATE, /* Spanning tree state */
|
||||
IFLA_BRPORT_PRIORITY, /* " priority */
|
||||
IFLA_BRPORT_COST, /* " cost */
|
||||
IFLA_BRPORT_MODE, /* mode (hairpin) */
|
||||
IFLA_BRPORT_GUARD, /* bpdu guard */
|
||||
IFLA_BRPORT_PROTECT, /* root port protection */
|
||||
IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */
|
||||
IFLA_BRPORT_LEARNING, /* mac learning */
|
||||
IFLA_BRPORT_UNICAST_FLOOD, /* flood unicast traffic */
|
||||
IFLA_BRPORT_PROXYARP, /* proxy ARP */
|
||||
IFLA_BRPORT_LEARNING_SYNC, /* mac learning sync from device */
|
||||
IFLA_BRPORT_PROXYARP_WIFI, /* proxy ARP for Wi-Fi */
|
||||
IFLA_BRPORT_ROOT_ID, /* designated root */
|
||||
IFLA_BRPORT_BRIDGE_ID, /* designated bridge */
|
||||
IFLA_BRPORT_DESIGNATED_PORT,
|
||||
IFLA_BRPORT_DESIGNATED_COST,
|
||||
IFLA_BRPORT_ID,
|
||||
IFLA_BRPORT_NO,
|
||||
IFLA_BRPORT_TOPOLOGY_CHANGE_ACK,
|
||||
IFLA_BRPORT_CONFIG_PENDING,
|
||||
IFLA_BRPORT_MESSAGE_AGE_TIMER,
|
||||
IFLA_BRPORT_FORWARD_DELAY_TIMER,
|
||||
IFLA_BRPORT_HOLD_TIMER,
|
||||
IFLA_BRPORT_FLUSH,
|
||||
IFLA_BRPORT_MULTICAST_ROUTER,
|
||||
IFLA_BRPORT_PAD,
|
||||
IFLA_BRPORT_MCAST_FLOOD,
|
||||
IFLA_BRPORT_MCAST_TO_UCAST,
|
||||
IFLA_BRPORT_VLAN_TUNNEL,
|
||||
IFLA_BRPORT_BCAST_FLOOD,
|
||||
IFLA_BRPORT_GROUP_FWD_MASK,
|
||||
IFLA_BRPORT_NEIGH_SUPPRESS,
|
||||
__IFLA_BRPORT_MAX
|
||||
};
|
||||
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
|
||||
|
||||
struct ifla_cacheinfo {
|
||||
__u32 max_reasm_len;
|
||||
__u32 tstamp; /* ipv6InterfaceTable updated timestamp */
|
||||
__u32 reachable_time;
|
||||
__u32 retrans_time;
|
||||
};
|
||||
|
||||
enum {
|
||||
IFLA_INFO_UNSPEC,
|
||||
IFLA_INFO_KIND,
|
||||
IFLA_INFO_DATA,
|
||||
IFLA_INFO_XSTATS,
|
||||
IFLA_INFO_SLAVE_KIND,
|
||||
IFLA_INFO_SLAVE_DATA,
|
||||
__IFLA_INFO_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_INFO_MAX (__IFLA_INFO_MAX - 1)
|
||||
|
||||
/* VLAN section */
|
||||
|
||||
enum {
|
||||
IFLA_VLAN_UNSPEC,
|
||||
IFLA_VLAN_ID,
|
||||
IFLA_VLAN_FLAGS,
|
||||
IFLA_VLAN_EGRESS_QOS,
|
||||
IFLA_VLAN_INGRESS_QOS,
|
||||
IFLA_VLAN_PROTOCOL,
|
||||
__IFLA_VLAN_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_VLAN_MAX (__IFLA_VLAN_MAX - 1)
|
||||
|
||||
struct ifla_vlan_flags {
|
||||
__u32 flags;
|
||||
__u32 mask;
|
||||
};
|
||||
|
||||
enum {
|
||||
IFLA_VLAN_QOS_UNSPEC,
|
||||
IFLA_VLAN_QOS_MAPPING,
|
||||
__IFLA_VLAN_QOS_MAX
|
||||
};
|
||||
|
||||
#define IFLA_VLAN_QOS_MAX (__IFLA_VLAN_QOS_MAX - 1)
|
||||
|
||||
struct ifla_vlan_qos_mapping {
|
||||
__u32 from;
|
||||
__u32 to;
|
||||
};
|
||||
|
||||
/* MACVLAN section */
|
||||
enum {
|
||||
IFLA_MACVLAN_UNSPEC,
|
||||
IFLA_MACVLAN_MODE,
|
||||
IFLA_MACVLAN_FLAGS,
|
||||
IFLA_MACVLAN_MACADDR_MODE,
|
||||
IFLA_MACVLAN_MACADDR,
|
||||
IFLA_MACVLAN_MACADDR_DATA,
|
||||
IFLA_MACVLAN_MACADDR_COUNT,
|
||||
__IFLA_MACVLAN_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1)
|
||||
|
||||
enum macvlan_mode {
|
||||
MACVLAN_MODE_PRIVATE = 1, /* don't talk to other macvlans */
|
||||
MACVLAN_MODE_VEPA = 2, /* talk to other ports through ext bridge */
|
||||
MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */
|
||||
MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */
|
||||
MACVLAN_MODE_SOURCE = 16,/* use source MAC address list to assign */
|
||||
};
|
||||
|
||||
enum macvlan_macaddr_mode {
|
||||
MACVLAN_MACADDR_ADD,
|
||||
MACVLAN_MACADDR_DEL,
|
||||
MACVLAN_MACADDR_FLUSH,
|
||||
MACVLAN_MACADDR_SET,
|
||||
};
|
||||
|
||||
#define MACVLAN_FLAG_NOPROMISC 1
|
||||
|
||||
/* VRF section */
|
||||
enum {
|
||||
IFLA_VRF_UNSPEC,
|
||||
IFLA_VRF_TABLE,
|
||||
__IFLA_VRF_MAX
|
||||
};
|
||||
|
||||
#define IFLA_VRF_MAX (__IFLA_VRF_MAX - 1)
|
||||
|
||||
enum {
|
||||
IFLA_VRF_PORT_UNSPEC,
|
||||
IFLA_VRF_PORT_TABLE,
|
||||
__IFLA_VRF_PORT_MAX
|
||||
};
|
||||
|
||||
#define IFLA_VRF_PORT_MAX (__IFLA_VRF_PORT_MAX - 1)
|
||||
|
||||
/* MACSEC section */
|
||||
enum {
|
||||
IFLA_MACSEC_UNSPEC,
|
||||
IFLA_MACSEC_SCI,
|
||||
IFLA_MACSEC_PORT,
|
||||
IFLA_MACSEC_ICV_LEN,
|
||||
IFLA_MACSEC_CIPHER_SUITE,
|
||||
IFLA_MACSEC_WINDOW,
|
||||
IFLA_MACSEC_ENCODING_SA,
|
||||
IFLA_MACSEC_ENCRYPT,
|
||||
IFLA_MACSEC_PROTECT,
|
||||
IFLA_MACSEC_INC_SCI,
|
||||
IFLA_MACSEC_ES,
|
||||
IFLA_MACSEC_SCB,
|
||||
IFLA_MACSEC_REPLAY_PROTECT,
|
||||
IFLA_MACSEC_VALIDATION,
|
||||
IFLA_MACSEC_PAD,
|
||||
__IFLA_MACSEC_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_MACSEC_MAX (__IFLA_MACSEC_MAX - 1)
|
||||
|
||||
enum macsec_validation_type {
|
||||
MACSEC_VALIDATE_DISABLED = 0,
|
||||
MACSEC_VALIDATE_CHECK = 1,
|
||||
MACSEC_VALIDATE_STRICT = 2,
|
||||
__MACSEC_VALIDATE_END,
|
||||
MACSEC_VALIDATE_MAX = __MACSEC_VALIDATE_END - 1,
|
||||
};
|
||||
|
||||
/* IPVLAN section */
|
||||
enum {
|
||||
IFLA_IPVLAN_UNSPEC,
|
||||
IFLA_IPVLAN_MODE,
|
||||
IFLA_IPVLAN_FLAGS,
|
||||
__IFLA_IPVLAN_MAX
|
||||
};
|
||||
|
||||
#define IFLA_IPVLAN_MAX (__IFLA_IPVLAN_MAX - 1)
|
||||
|
||||
enum ipvlan_mode {
|
||||
IPVLAN_MODE_L2 = 0,
|
||||
IPVLAN_MODE_L3,
|
||||
IPVLAN_MODE_L3S,
|
||||
IPVLAN_MODE_MAX
|
||||
};
|
||||
|
||||
#define IPVLAN_F_PRIVATE 0x01
|
||||
#define IPVLAN_F_VEPA 0x02
|
||||
|
||||
/* VXLAN section */
|
||||
enum {
|
||||
IFLA_VXLAN_UNSPEC,
|
||||
IFLA_VXLAN_ID,
|
||||
IFLA_VXLAN_GROUP, /* group or remote address */
|
||||
IFLA_VXLAN_LINK,
|
||||
IFLA_VXLAN_LOCAL,
|
||||
IFLA_VXLAN_TTL,
|
||||
IFLA_VXLAN_TOS,
|
||||
IFLA_VXLAN_LEARNING,
|
||||
IFLA_VXLAN_AGEING,
|
||||
IFLA_VXLAN_LIMIT,
|
||||
IFLA_VXLAN_PORT_RANGE, /* source port */
|
||||
IFLA_VXLAN_PROXY,
|
||||
IFLA_VXLAN_RSC,
|
||||
IFLA_VXLAN_L2MISS,
|
||||
IFLA_VXLAN_L3MISS,
|
||||
IFLA_VXLAN_PORT, /* destination port */
|
||||
IFLA_VXLAN_GROUP6,
|
||||
IFLA_VXLAN_LOCAL6,
|
||||
IFLA_VXLAN_UDP_CSUM,
|
||||
IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
|
||||
IFLA_VXLAN_UDP_ZERO_CSUM6_RX,
|
||||
IFLA_VXLAN_REMCSUM_TX,
|
||||
IFLA_VXLAN_REMCSUM_RX,
|
||||
IFLA_VXLAN_GBP,
|
||||
IFLA_VXLAN_REMCSUM_NOPARTIAL,
|
||||
IFLA_VXLAN_COLLECT_METADATA,
|
||||
IFLA_VXLAN_LABEL,
|
||||
IFLA_VXLAN_GPE,
|
||||
__IFLA_VXLAN_MAX
|
||||
};
|
||||
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
|
||||
|
||||
struct ifla_vxlan_port_range {
|
||||
__be16 low;
|
||||
__be16 high;
|
||||
};
|
||||
|
||||
/* GENEVE section */
|
||||
enum {
|
||||
IFLA_GENEVE_UNSPEC,
|
||||
IFLA_GENEVE_ID,
|
||||
IFLA_GENEVE_REMOTE,
|
||||
IFLA_GENEVE_TTL,
|
||||
IFLA_GENEVE_TOS,
|
||||
IFLA_GENEVE_PORT, /* destination port */
|
||||
IFLA_GENEVE_COLLECT_METADATA,
|
||||
IFLA_GENEVE_REMOTE6,
|
||||
IFLA_GENEVE_UDP_CSUM,
|
||||
IFLA_GENEVE_UDP_ZERO_CSUM6_TX,
|
||||
IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
|
||||
IFLA_GENEVE_LABEL,
|
||||
__IFLA_GENEVE_MAX
|
||||
};
|
||||
#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)
|
||||
|
||||
/* PPP section */
|
||||
enum {
|
||||
IFLA_PPP_UNSPEC,
|
||||
IFLA_PPP_DEV_FD,
|
||||
__IFLA_PPP_MAX
|
||||
};
|
||||
#define IFLA_PPP_MAX (__IFLA_PPP_MAX - 1)
|
||||
|
||||
/* GTP section */
|
||||
|
||||
enum ifla_gtp_role {
|
||||
GTP_ROLE_GGSN = 0,
|
||||
GTP_ROLE_SGSN,
|
||||
};
|
||||
|
||||
enum {
|
||||
IFLA_GTP_UNSPEC,
|
||||
IFLA_GTP_FD0,
|
||||
IFLA_GTP_FD1,
|
||||
IFLA_GTP_PDP_HASHSIZE,
|
||||
IFLA_GTP_ROLE,
|
||||
__IFLA_GTP_MAX,
|
||||
};
|
||||
#define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1)
|
||||
|
||||
/* Bonding section */
|
||||
|
||||
enum {
|
||||
IFLA_BOND_UNSPEC,
|
||||
IFLA_BOND_MODE,
|
||||
IFLA_BOND_ACTIVE_SLAVE,
|
||||
IFLA_BOND_MIIMON,
|
||||
IFLA_BOND_UPDELAY,
|
||||
IFLA_BOND_DOWNDELAY,
|
||||
IFLA_BOND_USE_CARRIER,
|
||||
IFLA_BOND_ARP_INTERVAL,
|
||||
IFLA_BOND_ARP_IP_TARGET,
|
||||
IFLA_BOND_ARP_VALIDATE,
|
||||
IFLA_BOND_ARP_ALL_TARGETS,
|
||||
IFLA_BOND_PRIMARY,
|
||||
IFLA_BOND_PRIMARY_RESELECT,
|
||||
IFLA_BOND_FAIL_OVER_MAC,
|
||||
IFLA_BOND_XMIT_HASH_POLICY,
|
||||
IFLA_BOND_RESEND_IGMP,
|
||||
IFLA_BOND_NUM_PEER_NOTIF,
|
||||
IFLA_BOND_ALL_SLAVES_ACTIVE,
|
||||
IFLA_BOND_MIN_LINKS,
|
||||
IFLA_BOND_LP_INTERVAL,
|
||||
IFLA_BOND_PACKETS_PER_SLAVE,
|
||||
IFLA_BOND_AD_LACP_RATE,
|
||||
IFLA_BOND_AD_SELECT,
|
||||
IFLA_BOND_AD_INFO,
|
||||
IFLA_BOND_AD_ACTOR_SYS_PRIO,
|
||||
IFLA_BOND_AD_USER_PORT_KEY,
|
||||
IFLA_BOND_AD_ACTOR_SYSTEM,
|
||||
IFLA_BOND_TLB_DYNAMIC_LB,
|
||||
__IFLA_BOND_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1)
|
||||
|
||||
enum {
|
||||
IFLA_BOND_AD_INFO_UNSPEC,
|
||||
IFLA_BOND_AD_INFO_AGGREGATOR,
|
||||
IFLA_BOND_AD_INFO_NUM_PORTS,
|
||||
IFLA_BOND_AD_INFO_ACTOR_KEY,
|
||||
IFLA_BOND_AD_INFO_PARTNER_KEY,
|
||||
IFLA_BOND_AD_INFO_PARTNER_MAC,
|
||||
__IFLA_BOND_AD_INFO_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_BOND_AD_INFO_MAX (__IFLA_BOND_AD_INFO_MAX - 1)
|
||||
|
||||
enum {
|
||||
IFLA_BOND_SLAVE_UNSPEC,
|
||||
IFLA_BOND_SLAVE_STATE,
|
||||
IFLA_BOND_SLAVE_MII_STATUS,
|
||||
IFLA_BOND_SLAVE_LINK_FAILURE_COUNT,
|
||||
IFLA_BOND_SLAVE_PERM_HWADDR,
|
||||
IFLA_BOND_SLAVE_QUEUE_ID,
|
||||
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID,
|
||||
IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE,
|
||||
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE,
|
||||
__IFLA_BOND_SLAVE_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_BOND_SLAVE_MAX (__IFLA_BOND_SLAVE_MAX - 1)
|
||||
|
||||
/* SR-IOV virtual function management section */
|
||||
|
||||
enum {
|
||||
IFLA_VF_INFO_UNSPEC,
|
||||
IFLA_VF_INFO,
|
||||
__IFLA_VF_INFO_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_VF_INFO_MAX (__IFLA_VF_INFO_MAX - 1)
|
||||
|
||||
enum {
|
||||
IFLA_VF_UNSPEC,
|
||||
IFLA_VF_MAC, /* Hardware queue specific attributes */
|
||||
IFLA_VF_VLAN, /* VLAN ID and QoS */
|
||||
IFLA_VF_TX_RATE, /* Max TX Bandwidth Allocation */
|
||||
IFLA_VF_SPOOFCHK, /* Spoof Checking on/off switch */
|
||||
IFLA_VF_LINK_STATE, /* link state enable/disable/auto switch */
|
||||
IFLA_VF_RATE, /* Min and Max TX Bandwidth Allocation */
|
||||
IFLA_VF_RSS_QUERY_EN, /* RSS Redirection Table and Hash Key query
|
||||
* on/off switch
|
||||
*/
|
||||
IFLA_VF_STATS, /* network device statistics */
|
||||
IFLA_VF_TRUST, /* Trust VF */
|
||||
IFLA_VF_IB_NODE_GUID, /* VF Infiniband node GUID */
|
||||
IFLA_VF_IB_PORT_GUID, /* VF Infiniband port GUID */
|
||||
IFLA_VF_VLAN_LIST, /* nested list of vlans, option for QinQ */
|
||||
__IFLA_VF_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_VF_MAX (__IFLA_VF_MAX - 1)
|
||||
|
||||
struct ifla_vf_mac {
|
||||
__u32 vf;
|
||||
__u8 mac[32]; /* MAX_ADDR_LEN */
|
||||
};
|
||||
|
||||
struct ifla_vf_vlan {
|
||||
__u32 vf;
|
||||
__u32 vlan; /* 0 - 4095, 0 disables VLAN filter */
|
||||
__u32 qos;
|
||||
};
|
||||
|
||||
enum {
|
||||
IFLA_VF_VLAN_INFO_UNSPEC,
|
||||
IFLA_VF_VLAN_INFO, /* VLAN ID, QoS and VLAN protocol */
|
||||
__IFLA_VF_VLAN_INFO_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_VF_VLAN_INFO_MAX (__IFLA_VF_VLAN_INFO_MAX - 1)
|
||||
#define MAX_VLAN_LIST_LEN 1
|
||||
|
||||
struct ifla_vf_vlan_info {
|
||||
__u32 vf;
|
||||
__u32 vlan; /* 0 - 4095, 0 disables VLAN filter */
|
||||
__u32 qos;
|
||||
__be16 vlan_proto; /* VLAN protocol either 802.1Q or 802.1ad */
|
||||
};
|
||||
|
||||
struct ifla_vf_tx_rate {
|
||||
__u32 vf;
|
||||
__u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */
|
||||
};
|
||||
|
||||
struct ifla_vf_rate {
|
||||
__u32 vf;
|
||||
__u32 min_tx_rate; /* Min Bandwidth in Mbps */
|
||||
__u32 max_tx_rate; /* Max Bandwidth in Mbps */
|
||||
};
|
||||
|
||||
struct ifla_vf_spoofchk {
|
||||
__u32 vf;
|
||||
__u32 setting;
|
||||
};
|
||||
|
||||
struct ifla_vf_guid {
|
||||
__u32 vf;
|
||||
__u64 guid;
|
||||
};
|
||||
|
||||
enum {
|
||||
IFLA_VF_LINK_STATE_AUTO, /* link state of the uplink */
|
||||
IFLA_VF_LINK_STATE_ENABLE, /* link always up */
|
||||
IFLA_VF_LINK_STATE_DISABLE, /* link always down */
|
||||
__IFLA_VF_LINK_STATE_MAX,
|
||||
};
|
||||
|
||||
struct ifla_vf_link_state {
|
||||
__u32 vf;
|
||||
__u32 link_state;
|
||||
};
|
||||
|
||||
struct ifla_vf_rss_query_en {
|
||||
__u32 vf;
|
||||
__u32 setting;
|
||||
};
|
||||
|
||||
enum {
|
||||
IFLA_VF_STATS_RX_PACKETS,
|
||||
IFLA_VF_STATS_TX_PACKETS,
|
||||
IFLA_VF_STATS_RX_BYTES,
|
||||
IFLA_VF_STATS_TX_BYTES,
|
||||
IFLA_VF_STATS_BROADCAST,
|
||||
IFLA_VF_STATS_MULTICAST,
|
||||
IFLA_VF_STATS_PAD,
|
||||
IFLA_VF_STATS_RX_DROPPED,
|
||||
IFLA_VF_STATS_TX_DROPPED,
|
||||
__IFLA_VF_STATS_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_VF_STATS_MAX (__IFLA_VF_STATS_MAX - 1)
|
||||
|
||||
struct ifla_vf_trust {
|
||||
__u32 vf;
|
||||
__u32 setting;
|
||||
};
|
||||
|
||||
/* VF ports management section
|
||||
*
|
||||
* Nested layout of set/get msg is:
|
||||
*
|
||||
* [IFLA_NUM_VF]
|
||||
* [IFLA_VF_PORTS]
|
||||
* [IFLA_VF_PORT]
|
||||
* [IFLA_PORT_*], ...
|
||||
* [IFLA_VF_PORT]
|
||||
* [IFLA_PORT_*], ...
|
||||
* ...
|
||||
* [IFLA_PORT_SELF]
|
||||
* [IFLA_PORT_*], ...
|
||||
*/
|
||||
|
||||
enum {
|
||||
IFLA_VF_PORT_UNSPEC,
|
||||
IFLA_VF_PORT, /* nest */
|
||||
__IFLA_VF_PORT_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_VF_PORT_MAX (__IFLA_VF_PORT_MAX - 1)
|
||||
|
||||
enum {
|
||||
IFLA_PORT_UNSPEC,
|
||||
IFLA_PORT_VF, /* __u32 */
|
||||
IFLA_PORT_PROFILE, /* string */
|
||||
IFLA_PORT_VSI_TYPE, /* 802.1Qbg (pre-)standard VDP */
|
||||
IFLA_PORT_INSTANCE_UUID, /* binary UUID */
|
||||
IFLA_PORT_HOST_UUID, /* binary UUID */
|
||||
IFLA_PORT_REQUEST, /* __u8 */
|
||||
IFLA_PORT_RESPONSE, /* __u16, output only */
|
||||
__IFLA_PORT_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_PORT_MAX (__IFLA_PORT_MAX - 1)
|
||||
|
||||
#define PORT_PROFILE_MAX 40
|
||||
#define PORT_UUID_MAX 16
|
||||
#define PORT_SELF_VF -1
|
||||
|
||||
enum {
|
||||
PORT_REQUEST_PREASSOCIATE = 0,
|
||||
PORT_REQUEST_PREASSOCIATE_RR,
|
||||
PORT_REQUEST_ASSOCIATE,
|
||||
PORT_REQUEST_DISASSOCIATE,
|
||||
};
|
||||
|
||||
enum {
|
||||
PORT_VDP_RESPONSE_SUCCESS = 0,
|
||||
PORT_VDP_RESPONSE_INVALID_FORMAT,
|
||||
PORT_VDP_RESPONSE_INSUFFICIENT_RESOURCES,
|
||||
PORT_VDP_RESPONSE_UNUSED_VTID,
|
||||
PORT_VDP_RESPONSE_VTID_VIOLATION,
|
||||
PORT_VDP_RESPONSE_VTID_VERSION_VIOALTION,
|
||||
PORT_VDP_RESPONSE_OUT_OF_SYNC,
|
||||
/* 0x08-0xFF reserved for future VDP use */
|
||||
PORT_PROFILE_RESPONSE_SUCCESS = 0x100,
|
||||
PORT_PROFILE_RESPONSE_INPROGRESS,
|
||||
PORT_PROFILE_RESPONSE_INVALID,
|
||||
PORT_PROFILE_RESPONSE_BADSTATE,
|
||||
PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES,
|
||||
PORT_PROFILE_RESPONSE_ERROR,
|
||||
};
|
||||
|
||||
struct ifla_port_vsi {
|
||||
__u8 vsi_mgr_id;
|
||||
__u8 vsi_type_id[3];
|
||||
__u8 vsi_type_version;
|
||||
__u8 pad[3];
|
||||
};
|
||||
|
||||
|
||||
/* IPoIB section */
|
||||
|
||||
enum {
|
||||
IFLA_IPOIB_UNSPEC,
|
||||
IFLA_IPOIB_PKEY,
|
||||
IFLA_IPOIB_MODE,
|
||||
IFLA_IPOIB_UMCAST,
|
||||
__IFLA_IPOIB_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
IPOIB_MODE_DATAGRAM = 0, /* using unreliable datagram QPs */
|
||||
IPOIB_MODE_CONNECTED = 1, /* using connected QPs */
|
||||
};
|
||||
|
||||
#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1)
|
||||
|
||||
|
||||
/* HSR section */
|
||||
|
||||
enum {
|
||||
IFLA_HSR_UNSPEC,
|
||||
IFLA_HSR_SLAVE1,
|
||||
IFLA_HSR_SLAVE2,
|
||||
IFLA_HSR_MULTICAST_SPEC, /* Last byte of supervision addr */
|
||||
IFLA_HSR_SUPERVISION_ADDR, /* Supervision frame multicast addr */
|
||||
IFLA_HSR_SEQ_NR,
|
||||
IFLA_HSR_VERSION, /* HSR version */
|
||||
__IFLA_HSR_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1)
|
||||
|
||||
/* STATS section */
|
||||
|
||||
struct if_stats_msg {
|
||||
__u8 family;
|
||||
__u8 pad1;
|
||||
__u16 pad2;
|
||||
__u32 ifindex;
|
||||
__u32 filter_mask;
|
||||
};
|
||||
|
||||
/* A stats attribute can be netdev specific or a global stat.
|
||||
* For netdev stats, lets use the prefix IFLA_STATS_LINK_*
|
||||
*/
|
||||
enum {
|
||||
IFLA_STATS_UNSPEC, /* also used as 64bit pad attribute */
|
||||
IFLA_STATS_LINK_64,
|
||||
IFLA_STATS_LINK_XSTATS,
|
||||
IFLA_STATS_LINK_XSTATS_SLAVE,
|
||||
IFLA_STATS_LINK_OFFLOAD_XSTATS,
|
||||
IFLA_STATS_AF_SPEC,
|
||||
__IFLA_STATS_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_STATS_MAX (__IFLA_STATS_MAX - 1)
|
||||
|
||||
#define IFLA_STATS_FILTER_BIT(ATTR) (1 << (ATTR - 1))
|
||||
|
||||
/* These are embedded into IFLA_STATS_LINK_XSTATS:
|
||||
* [IFLA_STATS_LINK_XSTATS]
|
||||
* -> [LINK_XSTATS_TYPE_xxx]
|
||||
* -> [rtnl link type specific attributes]
|
||||
*/
|
||||
enum {
|
||||
LINK_XSTATS_TYPE_UNSPEC,
|
||||
LINK_XSTATS_TYPE_BRIDGE,
|
||||
__LINK_XSTATS_TYPE_MAX
|
||||
};
|
||||
#define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1)
|
||||
|
||||
/* These are stats embedded into IFLA_STATS_LINK_OFFLOAD_XSTATS */
|
||||
enum {
|
||||
IFLA_OFFLOAD_XSTATS_UNSPEC,
|
||||
IFLA_OFFLOAD_XSTATS_CPU_HIT, /* struct rtnl_link_stats64 */
|
||||
__IFLA_OFFLOAD_XSTATS_MAX
|
||||
};
|
||||
#define IFLA_OFFLOAD_XSTATS_MAX (__IFLA_OFFLOAD_XSTATS_MAX - 1)
|
||||
|
||||
/* XDP section */
|
||||
|
||||
#define XDP_FLAGS_UPDATE_IF_NOEXIST (1U << 0)
|
||||
#define XDP_FLAGS_SKB_MODE (1U << 1)
|
||||
#define XDP_FLAGS_DRV_MODE (1U << 2)
|
||||
#define XDP_FLAGS_HW_MODE (1U << 3)
|
||||
#define XDP_FLAGS_MODES (XDP_FLAGS_SKB_MODE | \
|
||||
XDP_FLAGS_DRV_MODE | \
|
||||
XDP_FLAGS_HW_MODE)
|
||||
#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | \
|
||||
XDP_FLAGS_MODES)
|
||||
|
||||
/* These are stored into IFLA_XDP_ATTACHED on dump. */
|
||||
enum {
|
||||
XDP_ATTACHED_NONE = 0,
|
||||
XDP_ATTACHED_DRV,
|
||||
XDP_ATTACHED_SKB,
|
||||
XDP_ATTACHED_HW,
|
||||
};
|
||||
|
||||
enum {
|
||||
IFLA_XDP_UNSPEC,
|
||||
IFLA_XDP_FD,
|
||||
IFLA_XDP_ATTACHED,
|
||||
IFLA_XDP_FLAGS,
|
||||
IFLA_XDP_PROG_ID,
|
||||
__IFLA_XDP_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
|
||||
|
||||
enum {
|
||||
IFLA_EVENT_NONE,
|
||||
IFLA_EVENT_REBOOT, /* internal reset / reboot */
|
||||
IFLA_EVENT_FEATURES, /* change in offload features */
|
||||
IFLA_EVENT_BONDING_FAILOVER, /* change in active slave */
|
||||
IFLA_EVENT_NOTIFY_PEERS, /* re-sent grat. arp/ndisc */
|
||||
IFLA_EVENT_IGMP_RESEND, /* re-sent IGMP JOIN */
|
||||
IFLA_EVENT_BONDING_OPTIONS, /* change in bonding options */
|
||||
};
|
||||
|
||||
#endif /* _UAPI_LINUX_IF_LINK_H */
|
||||
@@ -1362,6 +1362,96 @@ struct kvm_s390_ucas_mapping {
|
||||
/* Available with KVM_CAP_S390_CMMA_MIGRATION */
|
||||
#define KVM_S390_GET_CMMA_BITS _IOWR(KVMIO, 0xb8, struct kvm_s390_cmma_log)
|
||||
#define KVM_S390_SET_CMMA_BITS _IOW(KVMIO, 0xb9, struct kvm_s390_cmma_log)
|
||||
/* Memory Encryption Commands */
|
||||
#define KVM_MEMORY_ENCRYPT_OP _IOWR(KVMIO, 0xba, unsigned long)
|
||||
|
||||
struct kvm_enc_region {
|
||||
__u64 addr;
|
||||
__u64 size;
|
||||
};
|
||||
|
||||
#define KVM_MEMORY_ENCRYPT_REG_REGION _IOR(KVMIO, 0xbb, struct kvm_enc_region)
|
||||
#define KVM_MEMORY_ENCRYPT_UNREG_REGION _IOR(KVMIO, 0xbc, struct kvm_enc_region)
|
||||
|
||||
/* Secure Encrypted Virtualization command */
|
||||
enum sev_cmd_id {
|
||||
/* Guest initialization commands */
|
||||
KVM_SEV_INIT = 0,
|
||||
KVM_SEV_ES_INIT,
|
||||
/* Guest launch commands */
|
||||
KVM_SEV_LAUNCH_START,
|
||||
KVM_SEV_LAUNCH_UPDATE_DATA,
|
||||
KVM_SEV_LAUNCH_UPDATE_VMSA,
|
||||
KVM_SEV_LAUNCH_SECRET,
|
||||
KVM_SEV_LAUNCH_MEASURE,
|
||||
KVM_SEV_LAUNCH_FINISH,
|
||||
/* Guest migration commands (outgoing) */
|
||||
KVM_SEV_SEND_START,
|
||||
KVM_SEV_SEND_UPDATE_DATA,
|
||||
KVM_SEV_SEND_UPDATE_VMSA,
|
||||
KVM_SEV_SEND_FINISH,
|
||||
/* Guest migration commands (incoming) */
|
||||
KVM_SEV_RECEIVE_START,
|
||||
KVM_SEV_RECEIVE_UPDATE_DATA,
|
||||
KVM_SEV_RECEIVE_UPDATE_VMSA,
|
||||
KVM_SEV_RECEIVE_FINISH,
|
||||
/* Guest status and debug commands */
|
||||
KVM_SEV_GUEST_STATUS,
|
||||
KVM_SEV_DBG_DECRYPT,
|
||||
KVM_SEV_DBG_ENCRYPT,
|
||||
/* Guest certificates commands */
|
||||
KVM_SEV_CERT_EXPORT,
|
||||
|
||||
KVM_SEV_NR_MAX,
|
||||
};
|
||||
|
||||
struct kvm_sev_cmd {
|
||||
__u32 id;
|
||||
__u64 data;
|
||||
__u32 error;
|
||||
__u32 sev_fd;
|
||||
};
|
||||
|
||||
struct kvm_sev_launch_start {
|
||||
__u32 handle;
|
||||
__u32 policy;
|
||||
__u64 dh_uaddr;
|
||||
__u32 dh_len;
|
||||
__u64 session_uaddr;
|
||||
__u32 session_len;
|
||||
};
|
||||
|
||||
struct kvm_sev_launch_update_data {
|
||||
__u64 uaddr;
|
||||
__u32 len;
|
||||
};
|
||||
|
||||
|
||||
struct kvm_sev_launch_secret {
|
||||
__u64 hdr_uaddr;
|
||||
__u32 hdr_len;
|
||||
__u64 guest_uaddr;
|
||||
__u32 guest_len;
|
||||
__u64 trans_uaddr;
|
||||
__u32 trans_len;
|
||||
};
|
||||
|
||||
struct kvm_sev_launch_measure {
|
||||
__u64 uaddr;
|
||||
__u32 len;
|
||||
};
|
||||
|
||||
struct kvm_sev_guest_status {
|
||||
__u32 handle;
|
||||
__u32 policy;
|
||||
__u32 state;
|
||||
};
|
||||
|
||||
struct kvm_sev_dbg {
|
||||
__u64 src_uaddr;
|
||||
__u64 dst_uaddr;
|
||||
__u32 len;
|
||||
};
|
||||
|
||||
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
|
||||
#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
|
||||
|
||||
251
tools/include/uapi/linux/netlink.h
Normal file
251
tools/include/uapi/linux/netlink.h
Normal file
@@ -0,0 +1,251 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI__LINUX_NETLINK_H
|
||||
#define _UAPI__LINUX_NETLINK_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/socket.h> /* for __kernel_sa_family_t */
|
||||
#include <linux/types.h>
|
||||
|
||||
#define NETLINK_ROUTE 0 /* Routing/device hook */
|
||||
#define NETLINK_UNUSED 1 /* Unused number */
|
||||
#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
|
||||
#define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue */
|
||||
#define NETLINK_SOCK_DIAG 4 /* socket monitoring */
|
||||
#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */
|
||||
#define NETLINK_XFRM 6 /* ipsec */
|
||||
#define NETLINK_SELINUX 7 /* SELinux event notifications */
|
||||
#define NETLINK_ISCSI 8 /* Open-iSCSI */
|
||||
#define NETLINK_AUDIT 9 /* auditing */
|
||||
#define NETLINK_FIB_LOOKUP 10
|
||||
#define NETLINK_CONNECTOR 11
|
||||
#define NETLINK_NETFILTER 12 /* netfilter subsystem */
|
||||
#define NETLINK_IP6_FW 13
|
||||
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
|
||||
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
|
||||
#define NETLINK_GENERIC 16
|
||||
/* leave room for NETLINK_DM (DM Events) */
|
||||
#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
|
||||
#define NETLINK_ECRYPTFS 19
|
||||
#define NETLINK_RDMA 20
|
||||
#define NETLINK_CRYPTO 21 /* Crypto layer */
|
||||
#define NETLINK_SMC 22 /* SMC monitoring */
|
||||
|
||||
#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG
|
||||
|
||||
#define MAX_LINKS 32
|
||||
|
||||
struct sockaddr_nl {
|
||||
__kernel_sa_family_t nl_family; /* AF_NETLINK */
|
||||
unsigned short nl_pad; /* zero */
|
||||
__u32 nl_pid; /* port ID */
|
||||
__u32 nl_groups; /* multicast groups mask */
|
||||
};
|
||||
|
||||
struct nlmsghdr {
|
||||
__u32 nlmsg_len; /* Length of message including header */
|
||||
__u16 nlmsg_type; /* Message content */
|
||||
__u16 nlmsg_flags; /* Additional flags */
|
||||
__u32 nlmsg_seq; /* Sequence number */
|
||||
__u32 nlmsg_pid; /* Sending process port ID */
|
||||
};
|
||||
|
||||
/* Flags values */
|
||||
|
||||
#define NLM_F_REQUEST 0x01 /* It is request message. */
|
||||
#define NLM_F_MULTI 0x02 /* Multipart message, terminated by NLMSG_DONE */
|
||||
#define NLM_F_ACK 0x04 /* Reply with ack, with zero or error code */
|
||||
#define NLM_F_ECHO 0x08 /* Echo this request */
|
||||
#define NLM_F_DUMP_INTR 0x10 /* Dump was inconsistent due to sequence change */
|
||||
#define NLM_F_DUMP_FILTERED 0x20 /* Dump was filtered as requested */
|
||||
|
||||
/* Modifiers to GET request */
|
||||
#define NLM_F_ROOT 0x100 /* specify tree root */
|
||||
#define NLM_F_MATCH 0x200 /* return all matching */
|
||||
#define NLM_F_ATOMIC 0x400 /* atomic GET */
|
||||
#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
|
||||
|
||||
/* Modifiers to NEW request */
|
||||
#define NLM_F_REPLACE 0x100 /* Override existing */
|
||||
#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */
|
||||
#define NLM_F_CREATE 0x400 /* Create, if it does not exist */
|
||||
#define NLM_F_APPEND 0x800 /* Add to end of list */
|
||||
|
||||
/* Modifiers to DELETE request */
|
||||
#define NLM_F_NONREC 0x100 /* Do not delete recursively */
|
||||
|
||||
/* Flags for ACK message */
|
||||
#define NLM_F_CAPPED 0x100 /* request was capped */
|
||||
#define NLM_F_ACK_TLVS 0x200 /* extended ACK TVLs were included */
|
||||
|
||||
/*
|
||||
4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL
|
||||
4.4BSD CHANGE NLM_F_REPLACE
|
||||
|
||||
True CHANGE NLM_F_CREATE|NLM_F_REPLACE
|
||||
Append NLM_F_CREATE
|
||||
Check NLM_F_EXCL
|
||||
*/
|
||||
|
||||
#define NLMSG_ALIGNTO 4U
|
||||
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
|
||||
#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
|
||||
#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
|
||||
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
|
||||
#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
|
||||
#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
|
||||
(struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
|
||||
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
|
||||
(nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
|
||||
(nlh)->nlmsg_len <= (len))
|
||||
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
|
||||
|
||||
#define NLMSG_NOOP 0x1 /* Nothing. */
|
||||
#define NLMSG_ERROR 0x2 /* Error */
|
||||
#define NLMSG_DONE 0x3 /* End of a dump */
|
||||
#define NLMSG_OVERRUN 0x4 /* Data lost */
|
||||
|
||||
#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */
|
||||
|
||||
struct nlmsgerr {
|
||||
int error;
|
||||
struct nlmsghdr msg;
|
||||
/*
|
||||
* followed by the message contents unless NETLINK_CAP_ACK was set
|
||||
* or the ACK indicates success (error == 0)
|
||||
* message length is aligned with NLMSG_ALIGN()
|
||||
*/
|
||||
/*
|
||||
* followed by TLVs defined in enum nlmsgerr_attrs
|
||||
* if NETLINK_EXT_ACK was set
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nlmsgerr_attrs - nlmsgerr attributes
|
||||
* @NLMSGERR_ATTR_UNUSED: unused
|
||||
* @NLMSGERR_ATTR_MSG: error message string (string)
|
||||
* @NLMSGERR_ATTR_OFFS: offset of the invalid attribute in the original
|
||||
* message, counting from the beginning of the header (u32)
|
||||
* @NLMSGERR_ATTR_COOKIE: arbitrary subsystem specific cookie to
|
||||
* be used - in the success case - to identify a created
|
||||
* object or operation or similar (binary)
|
||||
* @__NLMSGERR_ATTR_MAX: number of attributes
|
||||
* @NLMSGERR_ATTR_MAX: highest attribute number
|
||||
*/
|
||||
enum nlmsgerr_attrs {
|
||||
NLMSGERR_ATTR_UNUSED,
|
||||
NLMSGERR_ATTR_MSG,
|
||||
NLMSGERR_ATTR_OFFS,
|
||||
NLMSGERR_ATTR_COOKIE,
|
||||
|
||||
__NLMSGERR_ATTR_MAX,
|
||||
NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1
|
||||
};
|
||||
|
||||
#define NETLINK_ADD_MEMBERSHIP 1
|
||||
#define NETLINK_DROP_MEMBERSHIP 2
|
||||
#define NETLINK_PKTINFO 3
|
||||
#define NETLINK_BROADCAST_ERROR 4
|
||||
#define NETLINK_NO_ENOBUFS 5
|
||||
#ifndef __KERNEL__
|
||||
#define NETLINK_RX_RING 6
|
||||
#define NETLINK_TX_RING 7
|
||||
#endif
|
||||
#define NETLINK_LISTEN_ALL_NSID 8
|
||||
#define NETLINK_LIST_MEMBERSHIPS 9
|
||||
#define NETLINK_CAP_ACK 10
|
||||
#define NETLINK_EXT_ACK 11
|
||||
|
||||
struct nl_pktinfo {
|
||||
__u32 group;
|
||||
};
|
||||
|
||||
struct nl_mmap_req {
|
||||
unsigned int nm_block_size;
|
||||
unsigned int nm_block_nr;
|
||||
unsigned int nm_frame_size;
|
||||
unsigned int nm_frame_nr;
|
||||
};
|
||||
|
||||
struct nl_mmap_hdr {
|
||||
unsigned int nm_status;
|
||||
unsigned int nm_len;
|
||||
__u32 nm_group;
|
||||
/* credentials */
|
||||
__u32 nm_pid;
|
||||
__u32 nm_uid;
|
||||
__u32 nm_gid;
|
||||
};
|
||||
|
||||
#ifndef __KERNEL__
|
||||
enum nl_mmap_status {
|
||||
NL_MMAP_STATUS_UNUSED,
|
||||
NL_MMAP_STATUS_RESERVED,
|
||||
NL_MMAP_STATUS_VALID,
|
||||
NL_MMAP_STATUS_COPY,
|
||||
NL_MMAP_STATUS_SKIP,
|
||||
};
|
||||
|
||||
#define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO
|
||||
#define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT)
|
||||
#define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr))
|
||||
#endif
|
||||
|
||||
#define NET_MAJOR 36 /* Major 36 is reserved for networking */
|
||||
|
||||
enum {
|
||||
NETLINK_UNCONNECTED = 0,
|
||||
NETLINK_CONNECTED,
|
||||
};
|
||||
|
||||
/*
|
||||
* <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
|
||||
* +---------------------+- - -+- - - - - - - - - -+- - -+
|
||||
* | Header | Pad | Payload | Pad |
|
||||
* | (struct nlattr) | ing | | ing |
|
||||
* +---------------------+- - -+- - - - - - - - - -+- - -+
|
||||
* <-------------- nlattr->nla_len -------------->
|
||||
*/
|
||||
|
||||
struct nlattr {
|
||||
__u16 nla_len;
|
||||
__u16 nla_type;
|
||||
};
|
||||
|
||||
/*
|
||||
* nla_type (16 bits)
|
||||
* +---+---+-------------------------------+
|
||||
* | N | O | Attribute Type |
|
||||
* +---+---+-------------------------------+
|
||||
* N := Carries nested attributes
|
||||
* O := Payload stored in network byte order
|
||||
*
|
||||
* Note: The N and O flag are mutually exclusive.
|
||||
*/
|
||||
#define NLA_F_NESTED (1 << 15)
|
||||
#define NLA_F_NET_BYTEORDER (1 << 14)
|
||||
#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
|
||||
|
||||
#define NLA_ALIGNTO 4
|
||||
#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
|
||||
#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
|
||||
|
||||
/* Generic 32 bitflags attribute content sent to the kernel.
|
||||
*
|
||||
* The value is a bitmap that defines the values being set
|
||||
* The selector is a bitmask that defines which value is legit
|
||||
*
|
||||
* Examples:
|
||||
* value = 0x0, and selector = 0x1
|
||||
* implies we are selecting bit 1 and we want to set its value to 0.
|
||||
*
|
||||
* value = 0x2, and selector = 0x2
|
||||
* implies we are selecting bit 2 and we want to set its value to 1.
|
||||
*
|
||||
*/
|
||||
struct nla_bitfield32 {
|
||||
__u32 value;
|
||||
__u32 selector;
|
||||
};
|
||||
|
||||
#endif /* _UAPI__LINUX_NETLINK_H */
|
||||
@@ -422,6 +422,27 @@ struct perf_event_attr {
|
||||
__u16 __reserved_2; /* align to __u64 */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure used by below PERF_EVENT_IOC_QUERY_BPF command
|
||||
* to query bpf programs attached to the same perf tracepoint
|
||||
* as the given perf event.
|
||||
*/
|
||||
struct perf_event_query_bpf {
|
||||
/*
|
||||
* The below ids array length
|
||||
*/
|
||||
__u32 ids_len;
|
||||
/*
|
||||
* Set by the kernel to indicate the number of
|
||||
* available programs
|
||||
*/
|
||||
__u32 prog_cnt;
|
||||
/*
|
||||
* User provided buffer to store program ids
|
||||
*/
|
||||
__u32 ids[0];
|
||||
};
|
||||
|
||||
#define perf_flags(attr) (*(&(attr)->read_format + 1))
|
||||
|
||||
/*
|
||||
@@ -437,6 +458,7 @@ struct perf_event_attr {
|
||||
#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *)
|
||||
#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)
|
||||
#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32)
|
||||
#define PERF_EVENT_IOC_QUERY_BPF _IOWR('$', 10, struct perf_event_query_bpf *)
|
||||
|
||||
enum perf_event_ioc_flags {
|
||||
PERF_IOC_FLAG_GROUP = 1U << 0,
|
||||
|
||||
@@ -1 +1 @@
|
||||
libbpf-y := libbpf.o bpf.o
|
||||
libbpf-y := libbpf.o bpf.o nlattr.o
|
||||
|
||||
@@ -93,7 +93,6 @@ export prefix libdir src obj
|
||||
# Shell quotes
|
||||
libdir_SQ = $(subst ','\'',$(libdir))
|
||||
libdir_relative_SQ = $(subst ','\'',$(libdir_relative))
|
||||
plugin_dir_SQ = $(subst ','\'',$(plugin_dir))
|
||||
|
||||
LIB_FILE = libbpf.a libbpf.so
|
||||
|
||||
@@ -150,7 +149,7 @@ CMD_TARGETS = $(LIB_FILE)
|
||||
|
||||
TARGETS = $(CMD_TARGETS)
|
||||
|
||||
all: fixdep $(VERSION_FILES) all_cmd
|
||||
all: fixdep all_cmd
|
||||
|
||||
all_cmd: $(CMD_TARGETS)
|
||||
|
||||
@@ -161,6 +160,12 @@ $(BPF_IN): force elfdep bpfdep
|
||||
@(test -f ../../include/uapi/linux/bpf_common.h -a -f ../../../include/uapi/linux/bpf_common.h && ( \
|
||||
(diff -B ../../include/uapi/linux/bpf_common.h ../../../include/uapi/linux/bpf_common.h >/dev/null) || \
|
||||
echo "Warning: Kernel ABI header at 'tools/include/uapi/linux/bpf_common.h' differs from latest version at 'include/uapi/linux/bpf_common.h'" >&2 )) || true
|
||||
@(test -f ../../include/uapi/linux/netlink.h -a -f ../../../include/uapi/linux/netlink.h && ( \
|
||||
(diff -B ../../include/uapi/linux/netlink.h ../../../include/uapi/linux/netlink.h >/dev/null) || \
|
||||
echo "Warning: Kernel ABI header at 'tools/include/uapi/linux/netlink.h' differs from latest version at 'include/uapi/linux/netlink.h'" >&2 )) || true
|
||||
@(test -f ../../include/uapi/linux/if_link.h -a -f ../../../include/uapi/linux/if_link.h && ( \
|
||||
(diff -B ../../include/uapi/linux/if_link.h ../../../include/uapi/linux/if_link.h >/dev/null) || \
|
||||
echo "Warning: Kernel ABI header at 'tools/include/uapi/linux/if_link.h' differs from latest version at 'include/uapi/linux/if_link.h'" >&2 )) || true
|
||||
$(Q)$(MAKE) $(build)=libbpf
|
||||
|
||||
$(OUTPUT)libbpf.so: $(BPF_IN)
|
||||
@@ -169,21 +174,11 @@ $(OUTPUT)libbpf.so: $(BPF_IN)
|
||||
$(OUTPUT)libbpf.a: $(BPF_IN)
|
||||
$(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
|
||||
|
||||
define update_dir
|
||||
(echo $1 > $@.tmp; \
|
||||
if [ -r $@ ] && cmp -s $@ $@.tmp; then \
|
||||
rm -f $@.tmp; \
|
||||
else \
|
||||
echo ' UPDATE $@'; \
|
||||
mv -f $@.tmp $@; \
|
||||
fi);
|
||||
endef
|
||||
|
||||
define do_install
|
||||
if [ ! -d '$(DESTDIR_SQ)$2' ]; then \
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
|
||||
fi; \
|
||||
$(INSTALL) $1 '$(DESTDIR_SQ)$2'
|
||||
$(INSTALL) $1 $(if $3,-m $3,) '$(DESTDIR_SQ)$2'
|
||||
endef
|
||||
|
||||
install_lib: all_cmd
|
||||
@@ -192,7 +187,8 @@ install_lib: all_cmd
|
||||
|
||||
install_headers:
|
||||
$(call QUIET_INSTALL, headers) \
|
||||
$(call do_install,bpf.h,$(prefix)/include/bpf,644)
|
||||
$(call do_install,bpf.h,$(prefix)/include/bpf,644); \
|
||||
$(call do_install,libbpf.h,$(prefix)/include/bpf,644);
|
||||
|
||||
install: install_lib
|
||||
|
||||
@@ -203,7 +199,7 @@ config-clean:
|
||||
$(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null
|
||||
|
||||
clean:
|
||||
$(call QUIET_CLEAN, libbpf) $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d .*.cmd \
|
||||
$(call QUIET_CLEAN, libbpf) $(RM) *.o *~ $(TARGETS) *.a *.so .*.d .*.cmd \
|
||||
$(RM) LIBBPF-CFLAGS
|
||||
$(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP.libbpf
|
||||
|
||||
@@ -213,10 +209,10 @@ PHONY += force elfdep bpfdep
|
||||
force:
|
||||
|
||||
elfdep:
|
||||
@if [ "$(feature-libelf)" != "1" ]; then echo "No libelf found"; exit -1 ; fi
|
||||
@if [ "$(feature-libelf)" != "1" ]; then echo "No libelf found"; exit 1 ; fi
|
||||
|
||||
bpfdep:
|
||||
@if [ "$(feature-bpf)" != "1" ]; then echo "BPF API too old"; exit -1 ; fi
|
||||
@if [ "$(feature-bpf)" != "1" ]; then echo "BPF API too old"; exit 1 ; fi
|
||||
|
||||
# Declare the contents of the .PHONY variable as phony. We keep that
|
||||
# information in a variable so we can use it in if_changed and friends.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
|
||||
/*
|
||||
* common eBPF ELF operations.
|
||||
*
|
||||
@@ -25,6 +27,16 @@
|
||||
#include <asm/unistd.h>
|
||||
#include <linux/bpf.h>
|
||||
#include "bpf.h"
|
||||
#include "libbpf.h"
|
||||
#include "nlattr.h"
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef SOL_NETLINK
|
||||
#define SOL_NETLINK 270
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When building perf, unistd.h is overridden. __NR_bpf is
|
||||
@@ -46,7 +58,9 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef min
|
||||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
static inline __u64 ptr_to_u64(const void *ptr)
|
||||
{
|
||||
@@ -413,3 +427,124 @@ int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len)
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
|
||||
{
|
||||
struct sockaddr_nl sa;
|
||||
int sock, seq = 0, len, ret = -1;
|
||||
char buf[4096];
|
||||
struct nlattr *nla, *nla_xdp;
|
||||
struct {
|
||||
struct nlmsghdr nh;
|
||||
struct ifinfomsg ifinfo;
|
||||
char attrbuf[64];
|
||||
} req;
|
||||
struct nlmsghdr *nh;
|
||||
struct nlmsgerr *err;
|
||||
socklen_t addrlen;
|
||||
int one = 1;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.nl_family = AF_NETLINK;
|
||||
|
||||
sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if (sock < 0) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK,
|
||||
&one, sizeof(one)) < 0) {
|
||||
fprintf(stderr, "Netlink error reporting not supported\n");
|
||||
}
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
|
||||
ret = -errno;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
addrlen = sizeof(sa);
|
||||
if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) {
|
||||
ret = -errno;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (addrlen != sizeof(sa)) {
|
||||
ret = -LIBBPF_ERRNO__INTERNAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
req.nh.nlmsg_type = RTM_SETLINK;
|
||||
req.nh.nlmsg_pid = 0;
|
||||
req.nh.nlmsg_seq = ++seq;
|
||||
req.ifinfo.ifi_family = AF_UNSPEC;
|
||||
req.ifinfo.ifi_index = ifindex;
|
||||
|
||||
/* started nested attribute for XDP */
|
||||
nla = (struct nlattr *)(((char *)&req)
|
||||
+ NLMSG_ALIGN(req.nh.nlmsg_len));
|
||||
nla->nla_type = NLA_F_NESTED | IFLA_XDP;
|
||||
nla->nla_len = NLA_HDRLEN;
|
||||
|
||||
/* add XDP fd */
|
||||
nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
|
||||
nla_xdp->nla_type = IFLA_XDP_FD;
|
||||
nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
|
||||
memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd));
|
||||
nla->nla_len += nla_xdp->nla_len;
|
||||
|
||||
/* if user passed in any flags, add those too */
|
||||
if (flags) {
|
||||
nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
|
||||
nla_xdp->nla_type = IFLA_XDP_FLAGS;
|
||||
nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags);
|
||||
memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags));
|
||||
nla->nla_len += nla_xdp->nla_len;
|
||||
}
|
||||
|
||||
req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
|
||||
|
||||
if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
|
||||
ret = -errno;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
len = recv(sock, buf, sizeof(buf), 0);
|
||||
if (len < 0) {
|
||||
ret = -errno;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
|
||||
nh = NLMSG_NEXT(nh, len)) {
|
||||
if (nh->nlmsg_pid != sa.nl_pid) {
|
||||
ret = -LIBBPF_ERRNO__WRNGPID;
|
||||
goto cleanup;
|
||||
}
|
||||
if (nh->nlmsg_seq != seq) {
|
||||
ret = -LIBBPF_ERRNO__INVSEQ;
|
||||
goto cleanup;
|
||||
}
|
||||
switch (nh->nlmsg_type) {
|
||||
case NLMSG_ERROR:
|
||||
err = (struct nlmsgerr *)NLMSG_DATA(nh);
|
||||
if (!err->error)
|
||||
continue;
|
||||
ret = err->error;
|
||||
nla_dump_errormsg(nh);
|
||||
goto cleanup;
|
||||
case NLMSG_DONE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
close(sock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
|
||||
/*
|
||||
* common eBPF ELF operations.
|
||||
*
|
||||
@@ -40,7 +42,7 @@ int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
|
||||
__u32 map_flags);
|
||||
|
||||
/* Recommend log buffer size */
|
||||
#define BPF_LOG_BUF_SIZE 65536
|
||||
#define BPF_LOG_BUF_SIZE (256 * 1024)
|
||||
int bpf_load_program_name(enum bpf_prog_type type, const char *name,
|
||||
const struct bpf_insn *insns,
|
||||
size_t insns_cnt, const char *license,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
|
||||
/*
|
||||
* Common eBPF ELF object loading operations.
|
||||
*
|
||||
@@ -106,6 +108,8 @@ static const char *libbpf_strerror_table[NR_ERRNO] = {
|
||||
[ERRCODE_OFFSET(PROG2BIG)] = "Program too big",
|
||||
[ERRCODE_OFFSET(KVER)] = "Incorrect kernel version",
|
||||
[ERRCODE_OFFSET(PROGTYPE)] = "Kernel doesn't support this program type",
|
||||
[ERRCODE_OFFSET(WRNGPID)] = "Wrong pid in netlink message",
|
||||
[ERRCODE_OFFSET(INVSEQ)] = "Invalid netlink sequence",
|
||||
};
|
||||
|
||||
int libbpf_strerror(int err, char *buf, size_t size)
|
||||
@@ -174,12 +178,19 @@ struct bpf_program {
|
||||
char *name;
|
||||
char *section_name;
|
||||
struct bpf_insn *insns;
|
||||
size_t insns_cnt;
|
||||
size_t insns_cnt, main_prog_cnt;
|
||||
enum bpf_prog_type type;
|
||||
|
||||
struct {
|
||||
struct reloc_desc {
|
||||
enum {
|
||||
RELO_LD64,
|
||||
RELO_CALL,
|
||||
} type;
|
||||
int insn_idx;
|
||||
int map_idx;
|
||||
union {
|
||||
int map_idx;
|
||||
int text_off;
|
||||
};
|
||||
} *reloc_desc;
|
||||
int nr_reloc;
|
||||
|
||||
@@ -234,6 +245,7 @@ struct bpf_object {
|
||||
} *reloc;
|
||||
int nr_reloc;
|
||||
int maps_shndx;
|
||||
int text_shndx;
|
||||
} efile;
|
||||
/*
|
||||
* All loaded bpf_object is linked in a list, which is
|
||||
@@ -307,8 +319,8 @@ bpf_program__init(void *data, size_t size, char *section_name, int idx,
|
||||
|
||||
prog->section_name = strdup(section_name);
|
||||
if (!prog->section_name) {
|
||||
pr_warning("failed to alloc name for prog under section %s\n",
|
||||
section_name);
|
||||
pr_warning("failed to alloc name for prog under section(%d) %s\n",
|
||||
idx, section_name);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -375,9 +387,13 @@ bpf_object__init_prog_names(struct bpf_object *obj)
|
||||
size_t pi, si;
|
||||
|
||||
for (pi = 0; pi < obj->nr_programs; pi++) {
|
||||
char *name = NULL;
|
||||
const char *name = NULL;
|
||||
|
||||
prog = &obj->programs[pi];
|
||||
if (prog->idx == obj->efile.text_shndx) {
|
||||
name = ".text";
|
||||
goto skip_search;
|
||||
}
|
||||
|
||||
for (si = 0; si < symbols->d_size / sizeof(GElf_Sym) && !name;
|
||||
si++) {
|
||||
@@ -387,6 +403,8 @@ bpf_object__init_prog_names(struct bpf_object *obj)
|
||||
continue;
|
||||
if (sym.st_shndx != prog->idx)
|
||||
continue;
|
||||
if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL)
|
||||
continue;
|
||||
|
||||
name = elf_strptr(obj->efile.elf,
|
||||
obj->efile.strtabidx,
|
||||
@@ -403,7 +421,7 @@ bpf_object__init_prog_names(struct bpf_object *obj)
|
||||
prog->section_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
skip_search:
|
||||
prog->name = strdup(name);
|
||||
if (!prog->name) {
|
||||
pr_warning("failed to allocate memory for prog sym %s\n",
|
||||
@@ -724,6 +742,24 @@ bpf_object__init_maps(struct bpf_object *obj)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool section_have_execinstr(struct bpf_object *obj, int idx)
|
||||
{
|
||||
Elf_Scn *scn;
|
||||
GElf_Shdr sh;
|
||||
|
||||
scn = elf_getscn(obj->efile.elf, idx);
|
||||
if (!scn)
|
||||
return false;
|
||||
|
||||
if (gelf_getshdr(scn, &sh) != &sh)
|
||||
return false;
|
||||
|
||||
if (sh.sh_flags & SHF_EXECINSTR)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int bpf_object__elf_collect(struct bpf_object *obj)
|
||||
{
|
||||
Elf *elf = obj->efile.elf;
|
||||
@@ -745,29 +781,29 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
|
||||
|
||||
idx++;
|
||||
if (gelf_getshdr(scn, &sh) != &sh) {
|
||||
pr_warning("failed to get section header from %s\n",
|
||||
obj->path);
|
||||
pr_warning("failed to get section(%d) header from %s\n",
|
||||
idx, obj->path);
|
||||
err = -LIBBPF_ERRNO__FORMAT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
name = elf_strptr(elf, ep->e_shstrndx, sh.sh_name);
|
||||
if (!name) {
|
||||
pr_warning("failed to get section name from %s\n",
|
||||
obj->path);
|
||||
pr_warning("failed to get section(%d) name from %s\n",
|
||||
idx, obj->path);
|
||||
err = -LIBBPF_ERRNO__FORMAT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
data = elf_getdata(scn, 0);
|
||||
if (!data) {
|
||||
pr_warning("failed to get section data from %s(%s)\n",
|
||||
name, obj->path);
|
||||
pr_warning("failed to get section(%d) data from %s(%s)\n",
|
||||
idx, name, obj->path);
|
||||
err = -LIBBPF_ERRNO__FORMAT;
|
||||
goto out;
|
||||
}
|
||||
pr_debug("section %s, size %ld, link %d, flags %lx, type=%d\n",
|
||||
name, (unsigned long)data->d_size,
|
||||
pr_debug("section(%d) %s, size %ld, link %d, flags %lx, type=%d\n",
|
||||
idx, name, (unsigned long)data->d_size,
|
||||
(int)sh.sh_link, (unsigned long)sh.sh_flags,
|
||||
(int)sh.sh_type);
|
||||
|
||||
@@ -793,6 +829,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
|
||||
} else if ((sh.sh_type == SHT_PROGBITS) &&
|
||||
(sh.sh_flags & SHF_EXECINSTR) &&
|
||||
(data->d_size > 0)) {
|
||||
if (strcmp(name, ".text") == 0)
|
||||
obj->efile.text_shndx = idx;
|
||||
err = bpf_object__add_program(obj, data->d_buf,
|
||||
data->d_size, name, idx);
|
||||
if (err) {
|
||||
@@ -805,6 +843,14 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
|
||||
} else if (sh.sh_type == SHT_REL) {
|
||||
void *reloc = obj->efile.reloc;
|
||||
int nr_reloc = obj->efile.nr_reloc + 1;
|
||||
int sec = sh.sh_info; /* points to other section */
|
||||
|
||||
/* Only do relo for section with exec instructions */
|
||||
if (!section_have_execinstr(obj, sec)) {
|
||||
pr_debug("skip relo %s(%d) for section(%d)\n",
|
||||
name, idx, sec);
|
||||
continue;
|
||||
}
|
||||
|
||||
reloc = realloc(reloc,
|
||||
sizeof(*obj->efile.reloc) * nr_reloc);
|
||||
@@ -820,6 +866,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
|
||||
obj->efile.reloc[n].shdr = sh;
|
||||
obj->efile.reloc[n].data = data;
|
||||
}
|
||||
} else {
|
||||
pr_debug("skip section(%d) %s\n", idx, name);
|
||||
}
|
||||
if (err)
|
||||
goto out;
|
||||
@@ -854,11 +902,14 @@ bpf_object__find_prog_by_idx(struct bpf_object *obj, int idx)
|
||||
}
|
||||
|
||||
static int
|
||||
bpf_program__collect_reloc(struct bpf_program *prog,
|
||||
size_t nr_maps, GElf_Shdr *shdr,
|
||||
Elf_Data *data, Elf_Data *symbols,
|
||||
int maps_shndx, struct bpf_map *maps)
|
||||
bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,
|
||||
Elf_Data *data, struct bpf_object *obj)
|
||||
{
|
||||
Elf_Data *symbols = obj->efile.symbols;
|
||||
int text_shndx = obj->efile.text_shndx;
|
||||
int maps_shndx = obj->efile.maps_shndx;
|
||||
struct bpf_map *maps = obj->maps;
|
||||
size_t nr_maps = obj->nr_maps;
|
||||
int i, nrels;
|
||||
|
||||
pr_debug("collecting relocating info for: '%s'\n",
|
||||
@@ -891,8 +942,11 @@ bpf_program__collect_reloc(struct bpf_program *prog,
|
||||
GELF_R_SYM(rel.r_info));
|
||||
return -LIBBPF_ERRNO__FORMAT;
|
||||
}
|
||||
pr_debug("relo for %lld value %lld name %d\n",
|
||||
(long long) (rel.r_info >> 32),
|
||||
(long long) sym.st_value, sym.st_name);
|
||||
|
||||
if (sym.st_shndx != maps_shndx) {
|
||||
if (sym.st_shndx != maps_shndx && sym.st_shndx != text_shndx) {
|
||||
pr_warning("Program '%s' contains non-map related relo data pointing to section %u\n",
|
||||
prog->section_name, sym.st_shndx);
|
||||
return -LIBBPF_ERRNO__RELOC;
|
||||
@@ -901,6 +955,17 @@ bpf_program__collect_reloc(struct bpf_program *prog,
|
||||
insn_idx = rel.r_offset / sizeof(struct bpf_insn);
|
||||
pr_debug("relocation: insn_idx=%u\n", insn_idx);
|
||||
|
||||
if (insns[insn_idx].code == (BPF_JMP | BPF_CALL)) {
|
||||
if (insns[insn_idx].src_reg != BPF_PSEUDO_CALL) {
|
||||
pr_warning("incorrect bpf_call opcode\n");
|
||||
return -LIBBPF_ERRNO__RELOC;
|
||||
}
|
||||
prog->reloc_desc[i].type = RELO_CALL;
|
||||
prog->reloc_desc[i].insn_idx = insn_idx;
|
||||
prog->reloc_desc[i].text_off = sym.st_value;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) {
|
||||
pr_warning("bpf: relocation: invalid relo for insns[%d].code 0x%x\n",
|
||||
insn_idx, insns[insn_idx].code);
|
||||
@@ -922,6 +987,7 @@ bpf_program__collect_reloc(struct bpf_program *prog,
|
||||
return -LIBBPF_ERRNO__RELOC;
|
||||
}
|
||||
|
||||
prog->reloc_desc[i].type = RELO_LD64;
|
||||
prog->reloc_desc[i].insn_idx = insn_idx;
|
||||
prog->reloc_desc[i].map_idx = map_idx;
|
||||
}
|
||||
@@ -960,28 +1026,77 @@ bpf_object__create_maps(struct bpf_object *obj)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bpf_program__reloc_text(struct bpf_program *prog, struct bpf_object *obj,
|
||||
struct reloc_desc *relo)
|
||||
{
|
||||
struct bpf_insn *insn, *new_insn;
|
||||
struct bpf_program *text;
|
||||
size_t new_cnt;
|
||||
|
||||
if (relo->type != RELO_CALL)
|
||||
return -LIBBPF_ERRNO__RELOC;
|
||||
|
||||
if (prog->idx == obj->efile.text_shndx) {
|
||||
pr_warning("relo in .text insn %d into off %d\n",
|
||||
relo->insn_idx, relo->text_off);
|
||||
return -LIBBPF_ERRNO__RELOC;
|
||||
}
|
||||
|
||||
if (prog->main_prog_cnt == 0) {
|
||||
text = bpf_object__find_prog_by_idx(obj, obj->efile.text_shndx);
|
||||
if (!text) {
|
||||
pr_warning("no .text section found yet relo into text exist\n");
|
||||
return -LIBBPF_ERRNO__RELOC;
|
||||
}
|
||||
new_cnt = prog->insns_cnt + text->insns_cnt;
|
||||
new_insn = realloc(prog->insns, new_cnt * sizeof(*insn));
|
||||
if (!new_insn) {
|
||||
pr_warning("oom in prog realloc\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(new_insn + prog->insns_cnt, text->insns,
|
||||
text->insns_cnt * sizeof(*insn));
|
||||
prog->insns = new_insn;
|
||||
prog->main_prog_cnt = prog->insns_cnt;
|
||||
prog->insns_cnt = new_cnt;
|
||||
}
|
||||
insn = &prog->insns[relo->insn_idx];
|
||||
insn->imm += prog->main_prog_cnt - relo->insn_idx;
|
||||
pr_debug("added %zd insn from %s to prog %s\n",
|
||||
text->insns_cnt, text->section_name, prog->section_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bpf_program__relocate(struct bpf_program *prog, struct bpf_object *obj)
|
||||
{
|
||||
int i;
|
||||
int i, err;
|
||||
|
||||
if (!prog || !prog->reloc_desc)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < prog->nr_reloc; i++) {
|
||||
int insn_idx, map_idx;
|
||||
struct bpf_insn *insns = prog->insns;
|
||||
if (prog->reloc_desc[i].type == RELO_LD64) {
|
||||
struct bpf_insn *insns = prog->insns;
|
||||
int insn_idx, map_idx;
|
||||
|
||||
insn_idx = prog->reloc_desc[i].insn_idx;
|
||||
map_idx = prog->reloc_desc[i].map_idx;
|
||||
insn_idx = prog->reloc_desc[i].insn_idx;
|
||||
map_idx = prog->reloc_desc[i].map_idx;
|
||||
|
||||
if (insn_idx >= (int)prog->insns_cnt) {
|
||||
pr_warning("relocation out of range: '%s'\n",
|
||||
prog->section_name);
|
||||
return -LIBBPF_ERRNO__RELOC;
|
||||
if (insn_idx >= (int)prog->insns_cnt) {
|
||||
pr_warning("relocation out of range: '%s'\n",
|
||||
prog->section_name);
|
||||
return -LIBBPF_ERRNO__RELOC;
|
||||
}
|
||||
insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
|
||||
insns[insn_idx].imm = obj->maps[map_idx].fd;
|
||||
} else {
|
||||
err = bpf_program__reloc_text(prog, obj,
|
||||
&prog->reloc_desc[i]);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
|
||||
insns[insn_idx].imm = obj->maps[map_idx].fd;
|
||||
}
|
||||
|
||||
zfree(&prog->reloc_desc);
|
||||
@@ -1024,7 +1139,6 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
|
||||
Elf_Data *data = obj->efile.reloc[i].data;
|
||||
int idx = shdr->sh_info;
|
||||
struct bpf_program *prog;
|
||||
size_t nr_maps = obj->nr_maps;
|
||||
|
||||
if (shdr->sh_type != SHT_REL) {
|
||||
pr_warning("internal error at %d\n", __LINE__);
|
||||
@@ -1033,16 +1147,13 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
|
||||
|
||||
prog = bpf_object__find_prog_by_idx(obj, idx);
|
||||
if (!prog) {
|
||||
pr_warning("relocation failed: no %d section\n",
|
||||
idx);
|
||||
pr_warning("relocation failed: no section(%d)\n", idx);
|
||||
return -LIBBPF_ERRNO__RELOC;
|
||||
}
|
||||
|
||||
err = bpf_program__collect_reloc(prog, nr_maps,
|
||||
err = bpf_program__collect_reloc(prog,
|
||||
shdr, data,
|
||||
obj->efile.symbols,
|
||||
obj->efile.maps_shndx,
|
||||
obj->maps);
|
||||
obj);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1195,6 +1306,8 @@ bpf_object__load_progs(struct bpf_object *obj)
|
||||
int err;
|
||||
|
||||
for (i = 0; i < obj->nr_programs; i++) {
|
||||
if (obj->programs[i].idx == obj->efile.text_shndx)
|
||||
continue;
|
||||
err = bpf_program__load(&obj->programs[i],
|
||||
obj->license,
|
||||
obj->kern_version);
|
||||
@@ -1721,6 +1834,50 @@ BPF_PROG_TYPE_FNS(tracepoint, BPF_PROG_TYPE_TRACEPOINT);
|
||||
BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP);
|
||||
BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT);
|
||||
|
||||
#define BPF_PROG_SEC(string, type) { string, sizeof(string) - 1, type }
|
||||
static const struct {
|
||||
const char *sec;
|
||||
size_t len;
|
||||
enum bpf_prog_type prog_type;
|
||||
} section_names[] = {
|
||||
BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER),
|
||||
BPF_PROG_SEC("kprobe/", BPF_PROG_TYPE_KPROBE),
|
||||
BPF_PROG_SEC("kretprobe/", BPF_PROG_TYPE_KPROBE),
|
||||
BPF_PROG_SEC("classifier", BPF_PROG_TYPE_SCHED_CLS),
|
||||
BPF_PROG_SEC("action", BPF_PROG_TYPE_SCHED_ACT),
|
||||
BPF_PROG_SEC("tracepoint/", BPF_PROG_TYPE_TRACEPOINT),
|
||||
BPF_PROG_SEC("xdp", BPF_PROG_TYPE_XDP),
|
||||
BPF_PROG_SEC("perf_event", BPF_PROG_TYPE_PERF_EVENT),
|
||||
BPF_PROG_SEC("cgroup/skb", BPF_PROG_TYPE_CGROUP_SKB),
|
||||
BPF_PROG_SEC("cgroup/sock", BPF_PROG_TYPE_CGROUP_SOCK),
|
||||
BPF_PROG_SEC("cgroup/dev", BPF_PROG_TYPE_CGROUP_DEVICE),
|
||||
BPF_PROG_SEC("lwt_in", BPF_PROG_TYPE_LWT_IN),
|
||||
BPF_PROG_SEC("lwt_out", BPF_PROG_TYPE_LWT_OUT),
|
||||
BPF_PROG_SEC("lwt_xmit", BPF_PROG_TYPE_LWT_XMIT),
|
||||
BPF_PROG_SEC("sockops", BPF_PROG_TYPE_SOCK_OPS),
|
||||
BPF_PROG_SEC("sk_skb", BPF_PROG_TYPE_SK_SKB),
|
||||
};
|
||||
#undef BPF_PROG_SEC
|
||||
|
||||
static enum bpf_prog_type bpf_program__guess_type(struct bpf_program *prog)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!prog->section_name)
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(section_names); i++)
|
||||
if (strncmp(prog->section_name, section_names[i].sec,
|
||||
section_names[i].len) == 0)
|
||||
return section_names[i].prog_type;
|
||||
|
||||
err:
|
||||
pr_warning("failed to guess program type based on section name %s\n",
|
||||
prog->section_name);
|
||||
|
||||
return BPF_PROG_TYPE_UNSPEC;
|
||||
}
|
||||
|
||||
int bpf_map__fd(struct bpf_map *map)
|
||||
{
|
||||
return map ? map->fd : -EINVAL;
|
||||
@@ -1818,7 +1975,7 @@ long libbpf_get_error(const void *ptr)
|
||||
int bpf_prog_load(const char *file, enum bpf_prog_type type,
|
||||
struct bpf_object **pobj, int *prog_fd)
|
||||
{
|
||||
struct bpf_program *prog;
|
||||
struct bpf_program *prog, *first_prog = NULL;
|
||||
struct bpf_object *obj;
|
||||
int err;
|
||||
|
||||
@@ -1826,13 +1983,30 @@ int bpf_prog_load(const char *file, enum bpf_prog_type type,
|
||||
if (IS_ERR(obj))
|
||||
return -ENOENT;
|
||||
|
||||
prog = bpf_program__next(NULL, obj);
|
||||
if (!prog) {
|
||||
bpf_object__for_each_program(prog, obj) {
|
||||
/*
|
||||
* If type is not specified, try to guess it based on
|
||||
* section name.
|
||||
*/
|
||||
if (type == BPF_PROG_TYPE_UNSPEC) {
|
||||
type = bpf_program__guess_type(prog);
|
||||
if (type == BPF_PROG_TYPE_UNSPEC) {
|
||||
bpf_object__close(obj);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
bpf_program__set_type(prog, type);
|
||||
if (prog->idx != obj->efile.text_shndx && !first_prog)
|
||||
first_prog = prog;
|
||||
}
|
||||
|
||||
if (!first_prog) {
|
||||
pr_warning("object file doesn't contain bpf program\n");
|
||||
bpf_object__close(obj);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
bpf_program__set_type(prog, type);
|
||||
err = bpf_object__load(obj);
|
||||
if (err) {
|
||||
bpf_object__close(obj);
|
||||
@@ -1840,6 +2014,6 @@ int bpf_prog_load(const char *file, enum bpf_prog_type type,
|
||||
}
|
||||
|
||||
*pobj = obj;
|
||||
*prog_fd = bpf_program__fd(prog);
|
||||
*prog_fd = bpf_program__fd(first_prog);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
|
||||
/*
|
||||
* Common eBPF ELF object loading operations.
|
||||
*
|
||||
@@ -42,6 +44,8 @@ enum libbpf_errno {
|
||||
LIBBPF_ERRNO__PROG2BIG, /* Program too big */
|
||||
LIBBPF_ERRNO__KVER, /* Incorrect kernel version */
|
||||
LIBBPF_ERRNO__PROGTYPE, /* Kernel doesn't support this program type */
|
||||
LIBBPF_ERRNO__WRNGPID, /* Wrong pid in netlink message */
|
||||
LIBBPF_ERRNO__INVSEQ, /* Invalid netlink sequence */
|
||||
__LIBBPF_ERRNO__END,
|
||||
};
|
||||
|
||||
@@ -246,4 +250,6 @@ long libbpf_get_error(const void *ptr);
|
||||
|
||||
int bpf_prog_load(const char *file, enum bpf_prog_type type,
|
||||
struct bpf_object **pobj, int *prog_fd);
|
||||
|
||||
int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags);
|
||||
#endif
|
||||
|
||||
187
tools/lib/bpf/nlattr.c
Normal file
187
tools/lib/bpf/nlattr.c
Normal file
@@ -0,0 +1,187 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
|
||||
/*
|
||||
* NETLINK Netlink attributes
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include "nlattr.h"
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
|
||||
[NLA_U8] = sizeof(uint8_t),
|
||||
[NLA_U16] = sizeof(uint16_t),
|
||||
[NLA_U32] = sizeof(uint32_t),
|
||||
[NLA_U64] = sizeof(uint64_t),
|
||||
[NLA_STRING] = 1,
|
||||
[NLA_FLAG] = 0,
|
||||
};
|
||||
|
||||
static int nla_len(const struct nlattr *nla)
|
||||
{
|
||||
return nla->nla_len - NLA_HDRLEN;
|
||||
}
|
||||
|
||||
static struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
|
||||
{
|
||||
int totlen = NLA_ALIGN(nla->nla_len);
|
||||
|
||||
*remaining -= totlen;
|
||||
return (struct nlattr *) ((char *) nla + totlen);
|
||||
}
|
||||
|
||||
static int nla_ok(const struct nlattr *nla, int remaining)
|
||||
{
|
||||
return remaining >= sizeof(*nla) &&
|
||||
nla->nla_len >= sizeof(*nla) &&
|
||||
nla->nla_len <= remaining;
|
||||
}
|
||||
|
||||
static void *nla_data(const struct nlattr *nla)
|
||||
{
|
||||
return (char *) nla + NLA_HDRLEN;
|
||||
}
|
||||
|
||||
static int nla_type(const struct nlattr *nla)
|
||||
{
|
||||
return nla->nla_type & NLA_TYPE_MASK;
|
||||
}
|
||||
|
||||
static int validate_nla(struct nlattr *nla, int maxtype,
|
||||
struct nla_policy *policy)
|
||||
{
|
||||
struct nla_policy *pt;
|
||||
unsigned int minlen = 0;
|
||||
int type = nla_type(nla);
|
||||
|
||||
if (type < 0 || type > maxtype)
|
||||
return 0;
|
||||
|
||||
pt = &policy[type];
|
||||
|
||||
if (pt->type > NLA_TYPE_MAX)
|
||||
return 0;
|
||||
|
||||
if (pt->minlen)
|
||||
minlen = pt->minlen;
|
||||
else if (pt->type != NLA_UNSPEC)
|
||||
minlen = nla_attr_minlen[pt->type];
|
||||
|
||||
if (nla_len(nla) < minlen)
|
||||
return -1;
|
||||
|
||||
if (pt->maxlen && nla_len(nla) > pt->maxlen)
|
||||
return -1;
|
||||
|
||||
if (pt->type == NLA_STRING) {
|
||||
char *data = nla_data(nla);
|
||||
if (data[nla_len(nla) - 1] != '\0')
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int nlmsg_len(const struct nlmsghdr *nlh)
|
||||
{
|
||||
return nlh->nlmsg_len - NLMSG_HDRLEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create attribute index based on a stream of attributes.
|
||||
* @arg tb Index array to be filled (maxtype+1 elements).
|
||||
* @arg maxtype Maximum attribute type expected and accepted.
|
||||
* @arg head Head of attribute stream.
|
||||
* @arg len Length of attribute stream.
|
||||
* @arg policy Attribute validation policy.
|
||||
*
|
||||
* Iterates over the stream of attributes and stores a pointer to each
|
||||
* attribute in the index array using the attribute type as index to
|
||||
* the array. Attribute with a type greater than the maximum type
|
||||
* specified will be silently ignored in order to maintain backwards
|
||||
* compatibility. If \a policy is not NULL, the attribute will be
|
||||
* validated using the specified policy.
|
||||
*
|
||||
* @see nla_validate
|
||||
* @return 0 on success or a negative error code.
|
||||
*/
|
||||
static int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
|
||||
struct nla_policy *policy)
|
||||
{
|
||||
struct nlattr *nla;
|
||||
int rem, err;
|
||||
|
||||
memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
|
||||
|
||||
nla_for_each_attr(nla, head, len, rem) {
|
||||
int type = nla_type(nla);
|
||||
|
||||
if (type > maxtype)
|
||||
continue;
|
||||
|
||||
if (policy) {
|
||||
err = validate_nla(nla, maxtype, policy);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (tb[type])
|
||||
fprintf(stderr, "Attribute of type %#x found multiple times in message, "
|
||||
"previous attribute is being ignored.\n", type);
|
||||
|
||||
tb[type] = nla;
|
||||
}
|
||||
|
||||
err = 0;
|
||||
errout:
|
||||
return err;
|
||||
}
|
||||
|
||||
/* dump netlink extended ack error message */
|
||||
int nla_dump_errormsg(struct nlmsghdr *nlh)
|
||||
{
|
||||
struct nla_policy extack_policy[NLMSGERR_ATTR_MAX + 1] = {
|
||||
[NLMSGERR_ATTR_MSG] = { .type = NLA_STRING },
|
||||
[NLMSGERR_ATTR_OFFS] = { .type = NLA_U32 },
|
||||
};
|
||||
struct nlattr *tb[NLMSGERR_ATTR_MAX + 1], *attr;
|
||||
struct nlmsgerr *err;
|
||||
char *errmsg = NULL;
|
||||
int hlen, alen;
|
||||
|
||||
/* no TLVs, nothing to do here */
|
||||
if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS))
|
||||
return 0;
|
||||
|
||||
err = (struct nlmsgerr *)NLMSG_DATA(nlh);
|
||||
hlen = sizeof(*err);
|
||||
|
||||
/* if NLM_F_CAPPED is set then the inner err msg was capped */
|
||||
if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
|
||||
hlen += nlmsg_len(&err->msg);
|
||||
|
||||
attr = (struct nlattr *) ((void *) err + hlen);
|
||||
alen = nlh->nlmsg_len - hlen;
|
||||
|
||||
if (nla_parse(tb, NLMSGERR_ATTR_MAX, attr, alen, extack_policy) != 0) {
|
||||
fprintf(stderr,
|
||||
"Failed to parse extended error attributes\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tb[NLMSGERR_ATTR_MSG])
|
||||
errmsg = (char *) nla_data(tb[NLMSGERR_ATTR_MSG]);
|
||||
|
||||
fprintf(stderr, "Kernel error message: %s\n", errmsg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
72
tools/lib/bpf/nlattr.h
Normal file
72
tools/lib/bpf/nlattr.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
|
||||
/*
|
||||
* NETLINK Netlink attributes
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef __NLATTR_H
|
||||
#define __NLATTR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <linux/netlink.h>
|
||||
/* avoid multiple definition of netlink features */
|
||||
#define __LINUX_NETLINK_H
|
||||
|
||||
/**
|
||||
* Standard attribute types to specify validation policy
|
||||
*/
|
||||
enum {
|
||||
NLA_UNSPEC, /**< Unspecified type, binary data chunk */
|
||||
NLA_U8, /**< 8 bit integer */
|
||||
NLA_U16, /**< 16 bit integer */
|
||||
NLA_U32, /**< 32 bit integer */
|
||||
NLA_U64, /**< 64 bit integer */
|
||||
NLA_STRING, /**< NUL terminated character string */
|
||||
NLA_FLAG, /**< Flag */
|
||||
NLA_MSECS, /**< Micro seconds (64bit) */
|
||||
NLA_NESTED, /**< Nested attributes */
|
||||
__NLA_TYPE_MAX,
|
||||
};
|
||||
|
||||
#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
|
||||
|
||||
/**
|
||||
* @ingroup attr
|
||||
* Attribute validation policy.
|
||||
*
|
||||
* See section @core_doc{core_attr_parse,Attribute Parsing} for more details.
|
||||
*/
|
||||
struct nla_policy {
|
||||
/** Type of attribute or NLA_UNSPEC */
|
||||
uint16_t type;
|
||||
|
||||
/** Minimal length of payload required */
|
||||
uint16_t minlen;
|
||||
|
||||
/** Maximal length of payload allowed */
|
||||
uint16_t maxlen;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup attr
|
||||
* Iterate over a stream of attributes
|
||||
* @arg pos loop counter, set to current attribute
|
||||
* @arg head head of attribute stream
|
||||
* @arg len length of attribute stream
|
||||
* @arg rem initialized to len, holds bytes currently remaining in stream
|
||||
*/
|
||||
#define nla_for_each_attr(pos, head, len, rem) \
|
||||
for (pos = head, rem = len; \
|
||||
nla_ok(pos, rem); \
|
||||
pos = nla_next(pos, &(rem)))
|
||||
|
||||
int nla_dump_errormsg(struct nlmsghdr *nlh);
|
||||
|
||||
#endif /* __NLATTR_H */
|
||||
@@ -22,22 +22,29 @@
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#if !defined(find_next_bit)
|
||||
#if !defined(find_next_bit) || !defined(find_next_zero_bit) || \
|
||||
!defined(find_next_and_bit)
|
||||
|
||||
/*
|
||||
* This is a common helper function for find_next_bit and
|
||||
* find_next_zero_bit. The difference is the "invert" argument, which
|
||||
* is XORed with each fetched word before searching it for one bits.
|
||||
* This is a common helper function for find_next_bit, find_next_zero_bit, and
|
||||
* find_next_and_bit. The differences are:
|
||||
* - The "invert" argument, which is XORed with each fetched word before
|
||||
* searching it for one bits.
|
||||
* - The optional "addr2", which is anded with "addr1" if present.
|
||||
*/
|
||||
static unsigned long _find_next_bit(const unsigned long *addr,
|
||||
unsigned long nbits, unsigned long start, unsigned long invert)
|
||||
static inline unsigned long _find_next_bit(const unsigned long *addr1,
|
||||
const unsigned long *addr2, unsigned long nbits,
|
||||
unsigned long start, unsigned long invert)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
if (unlikely(start >= nbits))
|
||||
return nbits;
|
||||
|
||||
tmp = addr[start / BITS_PER_LONG] ^ invert;
|
||||
tmp = addr1[start / BITS_PER_LONG];
|
||||
if (addr2)
|
||||
tmp &= addr2[start / BITS_PER_LONG];
|
||||
tmp ^= invert;
|
||||
|
||||
/* Handle 1st word. */
|
||||
tmp &= BITMAP_FIRST_WORD_MASK(start);
|
||||
@@ -48,7 +55,10 @@ static unsigned long _find_next_bit(const unsigned long *addr,
|
||||
if (start >= nbits)
|
||||
return nbits;
|
||||
|
||||
tmp = addr[start / BITS_PER_LONG] ^ invert;
|
||||
tmp = addr1[start / BITS_PER_LONG];
|
||||
if (addr2)
|
||||
tmp &= addr2[start / BITS_PER_LONG];
|
||||
tmp ^= invert;
|
||||
}
|
||||
|
||||
return min(start + __ffs(tmp), nbits);
|
||||
@@ -62,7 +72,7 @@ static unsigned long _find_next_bit(const unsigned long *addr,
|
||||
unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
|
||||
unsigned long offset)
|
||||
{
|
||||
return _find_next_bit(addr, size, offset, 0UL);
|
||||
return _find_next_bit(addr, NULL, size, offset, 0UL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -104,6 +114,15 @@ unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
|
||||
unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
|
||||
unsigned long offset)
|
||||
{
|
||||
return _find_next_bit(addr, size, offset, ~0UL);
|
||||
return _find_next_bit(addr, NULL, size, offset, ~0UL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef find_next_and_bit
|
||||
unsigned long find_next_and_bit(const unsigned long *addr1,
|
||||
const unsigned long *addr2, unsigned long size,
|
||||
unsigned long offset)
|
||||
{
|
||||
return _find_next_bit(addr1, addr2, size, offset, 0UL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -30,10 +30,13 @@ static void pager_preexec(void)
|
||||
* have real input
|
||||
*/
|
||||
fd_set in;
|
||||
fd_set exception;
|
||||
|
||||
FD_ZERO(&in);
|
||||
FD_ZERO(&exception);
|
||||
FD_SET(0, &in);
|
||||
select(1, &in, NULL, &in, NULL);
|
||||
FD_SET(0, &exception);
|
||||
select(1, &in, NULL, &exception, NULL);
|
||||
|
||||
setenv("LESS", "FRSX", 0);
|
||||
}
|
||||
|
||||
@@ -138,6 +138,7 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
|
||||
"__reiserfs_panic",
|
||||
"lbug_with_loc",
|
||||
"fortify_panic",
|
||||
"usercopy_abort",
|
||||
};
|
||||
|
||||
if (func->bind == STB_WEAK)
|
||||
@@ -543,18 +544,14 @@ static int add_call_destinations(struct objtool_file *file)
|
||||
dest_off = insn->offset + insn->len + insn->immediate;
|
||||
insn->call_dest = find_symbol_by_offset(insn->sec,
|
||||
dest_off);
|
||||
/*
|
||||
* FIXME: Thanks to retpolines, it's now considered
|
||||
* normal for a function to call within itself. So
|
||||
* disable this warning for now.
|
||||
*/
|
||||
#if 0
|
||||
if (!insn->call_dest) {
|
||||
WARN_FUNC("can't find call dest symbol at offset 0x%lx",
|
||||
insn->sec, insn->offset, dest_off);
|
||||
|
||||
if (!insn->call_dest && !insn->ignore) {
|
||||
WARN_FUNC("unsupported intra-function call",
|
||||
insn->sec, insn->offset);
|
||||
WARN("If this is a retpoline, please patch it in with alternatives and annotate it with ANNOTATE_NOSPEC_ALTERNATIVE.");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
} else if (rela->sym->type == STT_SECTION) {
|
||||
insn->call_dest = find_symbol_by_offset(rela->sym->sec,
|
||||
rela->addend+4);
|
||||
@@ -598,7 +595,7 @@ static int handle_group_alt(struct objtool_file *file,
|
||||
struct instruction *orig_insn,
|
||||
struct instruction **new_insn)
|
||||
{
|
||||
struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump;
|
||||
struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump = NULL;
|
||||
unsigned long dest_off;
|
||||
|
||||
last_orig_insn = NULL;
|
||||
@@ -614,28 +611,30 @@ static int handle_group_alt(struct objtool_file *file,
|
||||
last_orig_insn = insn;
|
||||
}
|
||||
|
||||
if (!next_insn_same_sec(file, last_orig_insn)) {
|
||||
WARN("%s: don't know how to handle alternatives at end of section",
|
||||
special_alt->orig_sec->name);
|
||||
return -1;
|
||||
}
|
||||
if (next_insn_same_sec(file, last_orig_insn)) {
|
||||
fake_jump = malloc(sizeof(*fake_jump));
|
||||
if (!fake_jump) {
|
||||
WARN("malloc failed");
|
||||
return -1;
|
||||
}
|
||||
memset(fake_jump, 0, sizeof(*fake_jump));
|
||||
INIT_LIST_HEAD(&fake_jump->alts);
|
||||
clear_insn_state(&fake_jump->state);
|
||||
|
||||
fake_jump = malloc(sizeof(*fake_jump));
|
||||
if (!fake_jump) {
|
||||
WARN("malloc failed");
|
||||
return -1;
|
||||
fake_jump->sec = special_alt->new_sec;
|
||||
fake_jump->offset = -1;
|
||||
fake_jump->type = INSN_JUMP_UNCONDITIONAL;
|
||||
fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
|
||||
fake_jump->ignore = true;
|
||||
}
|
||||
memset(fake_jump, 0, sizeof(*fake_jump));
|
||||
INIT_LIST_HEAD(&fake_jump->alts);
|
||||
clear_insn_state(&fake_jump->state);
|
||||
|
||||
fake_jump->sec = special_alt->new_sec;
|
||||
fake_jump->offset = -1;
|
||||
fake_jump->type = INSN_JUMP_UNCONDITIONAL;
|
||||
fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
|
||||
fake_jump->ignore = true;
|
||||
|
||||
if (!special_alt->new_len) {
|
||||
if (!fake_jump) {
|
||||
WARN("%s: empty alternative at end of section",
|
||||
special_alt->orig_sec->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*new_insn = fake_jump;
|
||||
return 0;
|
||||
}
|
||||
@@ -648,6 +647,8 @@ static int handle_group_alt(struct objtool_file *file,
|
||||
|
||||
last_new_insn = insn;
|
||||
|
||||
insn->ignore = orig_insn->ignore_alts;
|
||||
|
||||
if (insn->type != INSN_JUMP_CONDITIONAL &&
|
||||
insn->type != INSN_JUMP_UNCONDITIONAL)
|
||||
continue;
|
||||
@@ -656,8 +657,14 @@ static int handle_group_alt(struct objtool_file *file,
|
||||
continue;
|
||||
|
||||
dest_off = insn->offset + insn->len + insn->immediate;
|
||||
if (dest_off == special_alt->new_off + special_alt->new_len)
|
||||
if (dest_off == special_alt->new_off + special_alt->new_len) {
|
||||
if (!fake_jump) {
|
||||
WARN("%s: alternative jump to end of section",
|
||||
special_alt->orig_sec->name);
|
||||
return -1;
|
||||
}
|
||||
insn->jump_dest = fake_jump;
|
||||
}
|
||||
|
||||
if (!insn->jump_dest) {
|
||||
WARN_FUNC("can't find alternative jump destination",
|
||||
@@ -672,7 +679,8 @@ static int handle_group_alt(struct objtool_file *file,
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_add(&fake_jump->list, &last_new_insn->list);
|
||||
if (fake_jump)
|
||||
list_add(&fake_jump->list, &last_new_insn->list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -729,10 +737,6 @@ static int add_special_section_alts(struct objtool_file *file)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Ignore retpoline alternatives. */
|
||||
if (orig_insn->ignore_alts)
|
||||
continue;
|
||||
|
||||
new_insn = NULL;
|
||||
if (!special_alt->group || special_alt->new_len) {
|
||||
new_insn = find_insn(file, special_alt->new_sec,
|
||||
@@ -848,8 +852,14 @@ static int add_switch_table(struct objtool_file *file, struct symbol *func,
|
||||
* This is a fairly uncommon pattern which is new for GCC 6. As of this
|
||||
* writing, there are 11 occurrences of it in the allmodconfig kernel.
|
||||
*
|
||||
* As of GCC 7 there are quite a few more of these and the 'in between' code
|
||||
* is significant. Esp. with KASAN enabled some of the code between the mov
|
||||
* and jmpq uses .rodata itself, which can confuse things.
|
||||
*
|
||||
* TODO: Once we have DWARF CFI and smarter instruction decoding logic,
|
||||
* ensure the same register is used in the mov and jump instructions.
|
||||
*
|
||||
* NOTE: RETPOLINE made it harder still to decode dynamic jumps.
|
||||
*/
|
||||
static struct rela *find_switch_table(struct objtool_file *file,
|
||||
struct symbol *func,
|
||||
@@ -871,12 +881,25 @@ static struct rela *find_switch_table(struct objtool_file *file,
|
||||
text_rela->addend + 4);
|
||||
if (!rodata_rela)
|
||||
return NULL;
|
||||
|
||||
file->ignore_unreachables = true;
|
||||
return rodata_rela;
|
||||
}
|
||||
|
||||
/* case 3 */
|
||||
func_for_each_insn_continue_reverse(file, func, insn) {
|
||||
/*
|
||||
* Backward search using the @first_jump_src links, these help avoid
|
||||
* much of the 'in between' code. Which avoids us getting confused by
|
||||
* it.
|
||||
*/
|
||||
for (insn = list_prev_entry(insn, list);
|
||||
|
||||
&insn->list != &file->insn_list &&
|
||||
insn->sec == func->sec &&
|
||||
insn->offset >= func->offset;
|
||||
|
||||
insn = insn->first_jump_src ?: list_prev_entry(insn, list)) {
|
||||
|
||||
if (insn->type == INSN_JUMP_DYNAMIC)
|
||||
break;
|
||||
|
||||
@@ -906,14 +929,32 @@ static struct rela *find_switch_table(struct objtool_file *file,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int add_func_switch_tables(struct objtool_file *file,
|
||||
struct symbol *func)
|
||||
{
|
||||
struct instruction *insn, *prev_jump = NULL;
|
||||
struct instruction *insn, *last = NULL, *prev_jump = NULL;
|
||||
struct rela *rela, *prev_rela = NULL;
|
||||
int ret;
|
||||
|
||||
func_for_each_insn(file, func, insn) {
|
||||
if (!last)
|
||||
last = insn;
|
||||
|
||||
/*
|
||||
* Store back-pointers for unconditional forward jumps such
|
||||
* that find_switch_table() can back-track using those and
|
||||
* avoid some potentially confusing code.
|
||||
*/
|
||||
if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest &&
|
||||
insn->offset > last->offset &&
|
||||
insn->jump_dest->offset > insn->offset &&
|
||||
!insn->jump_dest->first_jump_src) {
|
||||
|
||||
insn->jump_dest->first_jump_src = insn;
|
||||
last = insn->jump_dest;
|
||||
}
|
||||
|
||||
if (insn->type != INSN_JUMP_DYNAMIC)
|
||||
continue;
|
||||
|
||||
@@ -1089,11 +1130,11 @@ static int decode_sections(struct objtool_file *file)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = add_call_destinations(file);
|
||||
ret = add_special_section_alts(file);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = add_special_section_alts(file);
|
||||
ret = add_call_destinations(file);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1720,10 +1761,12 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
|
||||
|
||||
insn->visited = true;
|
||||
|
||||
list_for_each_entry(alt, &insn->alts, list) {
|
||||
ret = validate_branch(file, alt->insn, state);
|
||||
if (ret)
|
||||
return 1;
|
||||
if (!insn->ignore_alts) {
|
||||
list_for_each_entry(alt, &insn->alts, list) {
|
||||
ret = validate_branch(file, alt->insn, state);
|
||||
if (ret)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (insn->type) {
|
||||
@@ -1893,13 +1936,19 @@ static bool ignore_unreachable_insn(struct instruction *insn)
|
||||
if (is_kasan_insn(insn) || is_ubsan_insn(insn))
|
||||
return true;
|
||||
|
||||
if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest) {
|
||||
insn = insn->jump_dest;
|
||||
continue;
|
||||
if (insn->type == INSN_JUMP_UNCONDITIONAL) {
|
||||
if (insn->jump_dest &&
|
||||
insn->jump_dest->func == insn->func) {
|
||||
insn = insn->jump_dest;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (insn->offset + insn->len >= insn->func->offset + insn->func->len)
|
||||
break;
|
||||
|
||||
insn = list_next_entry(insn, list);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ struct instruction {
|
||||
bool alt_group, visited, dead_end, ignore, hint, save, restore, ignore_alts;
|
||||
struct symbol *call_dest;
|
||||
struct instruction *jump_dest;
|
||||
struct instruction *first_jump_src;
|
||||
struct list_head alts;
|
||||
struct symbol *func;
|
||||
struct stack_op stack_op;
|
||||
|
||||
@@ -98,6 +98,11 @@ static int create_orc_entry(struct section *u_sec, struct section *ip_relasec,
|
||||
struct orc_entry *orc;
|
||||
struct rela *rela;
|
||||
|
||||
if (!insn_sec->sym) {
|
||||
WARN("missing symbol for section %s", insn_sec->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* populate ORC data */
|
||||
orc = (struct orc_entry *)u_sec->data->d_buf + idx;
|
||||
memcpy(orc, o, sizeof(*orc));
|
||||
|
||||
@@ -30,6 +30,10 @@ OPTIONS for 'convert'
|
||||
-i::
|
||||
Specify input perf data file path.
|
||||
|
||||
-f::
|
||||
--force::
|
||||
Don't complain, do it.
|
||||
|
||||
-v::
|
||||
--verbose::
|
||||
Be more verbose (show counter open errors, etc).
|
||||
|
||||
@@ -10,15 +10,19 @@ PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
|
||||
|
||||
out := $(OUTPUT)arch/s390/include/generated/asm
|
||||
header := $(out)/syscalls_64.c
|
||||
sysdef := $(srctree)/tools/arch/s390/include/uapi/asm/unistd.h
|
||||
sysprf := $(srctree)/tools/perf/arch/s390/entry/syscalls/
|
||||
syskrn := $(srctree)/arch/s390/kernel/syscalls/syscall.tbl
|
||||
sysprf := $(srctree)/tools/perf/arch/s390/entry/syscalls
|
||||
sysdef := $(sysprf)/syscall.tbl
|
||||
systbl := $(sysprf)/mksyscalltbl
|
||||
|
||||
# Create output directory if not already present
|
||||
_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
|
||||
|
||||
$(header): $(sysdef) $(systbl)
|
||||
$(Q)$(SHELL) '$(systbl)' '$(CC)' $(sysdef) > $@
|
||||
@(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
|
||||
(diff -B $(sysdef) $(syskrn) >/dev/null) \
|
||||
|| echo "Warning: Kernel ABI header at '$(sysdef)' differs from latest version at '$(syskrn)'" >&2 )) || true
|
||||
$(Q)$(SHELL) '$(systbl)' $(sysdef) > $@
|
||||
|
||||
clean::
|
||||
$(call QUIET_CLEAN, s390) $(RM) $(header)
|
||||
|
||||
@@ -3,25 +3,23 @@
|
||||
#
|
||||
# Generate system call table for perf
|
||||
#
|
||||
#
|
||||
# Copyright IBM Corp. 2017
|
||||
# Copyright IBM Corp. 2017, 2018
|
||||
# Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
|
||||
#
|
||||
|
||||
gcc=$1
|
||||
input=$2
|
||||
SYSCALL_TBL=$1
|
||||
|
||||
if ! test -r $input; then
|
||||
if ! test -r $SYSCALL_TBL; then
|
||||
echo "Could not read input file" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
create_table()
|
||||
{
|
||||
local max_nr
|
||||
local max_nr nr abi sc discard
|
||||
|
||||
echo 'static const char *syscalltbl_s390_64[] = {'
|
||||
while read sc nr; do
|
||||
while read nr abi sc discard; do
|
||||
printf '\t[%d] = "%s",\n' $nr $sc
|
||||
max_nr=$nr
|
||||
done
|
||||
@@ -29,8 +27,6 @@ create_table()
|
||||
echo "#define SYSCALLTBL_S390_64_MAX_ID $max_nr"
|
||||
}
|
||||
|
||||
|
||||
$gcc -m64 -E -dM -x c $input \
|
||||
|sed -ne 's/^#define __NR_//p' \
|
||||
|sort -t' ' -k2 -nu \
|
||||
grep -E "^[[:digit:]]+[[:space:]]+(common|64)" $SYSCALL_TBL \
|
||||
|sort -k1 -n \
|
||||
|create_table
|
||||
|
||||
390
tools/perf/arch/s390/entry/syscalls/syscall.tbl
Normal file
390
tools/perf/arch/s390/entry/syscalls/syscall.tbl
Normal file
@@ -0,0 +1,390 @@
|
||||
# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
|
||||
#
|
||||
# System call table for s390
|
||||
#
|
||||
# Format:
|
||||
#
|
||||
# <nr> <abi> <syscall> <entry-64bit> <compat-entry>
|
||||
#
|
||||
# where <abi> can be common, 64, or 32
|
||||
|
||||
1 common exit sys_exit sys_exit
|
||||
2 common fork sys_fork sys_fork
|
||||
3 common read sys_read compat_sys_s390_read
|
||||
4 common write sys_write compat_sys_s390_write
|
||||
5 common open sys_open compat_sys_open
|
||||
6 common close sys_close sys_close
|
||||
7 common restart_syscall sys_restart_syscall sys_restart_syscall
|
||||
8 common creat sys_creat compat_sys_creat
|
||||
9 common link sys_link compat_sys_link
|
||||
10 common unlink sys_unlink compat_sys_unlink
|
||||
11 common execve sys_execve compat_sys_execve
|
||||
12 common chdir sys_chdir compat_sys_chdir
|
||||
13 32 time - compat_sys_time
|
||||
14 common mknod sys_mknod compat_sys_mknod
|
||||
15 common chmod sys_chmod compat_sys_chmod
|
||||
16 32 lchown - compat_sys_s390_lchown16
|
||||
19 common lseek sys_lseek compat_sys_lseek
|
||||
20 common getpid sys_getpid sys_getpid
|
||||
21 common mount sys_mount compat_sys_mount
|
||||
22 common umount sys_oldumount compat_sys_oldumount
|
||||
23 32 setuid - compat_sys_s390_setuid16
|
||||
24 32 getuid - compat_sys_s390_getuid16
|
||||
25 32 stime - compat_sys_stime
|
||||
26 common ptrace sys_ptrace compat_sys_ptrace
|
||||
27 common alarm sys_alarm sys_alarm
|
||||
29 common pause sys_pause sys_pause
|
||||
30 common utime sys_utime compat_sys_utime
|
||||
33 common access sys_access compat_sys_access
|
||||
34 common nice sys_nice sys_nice
|
||||
36 common sync sys_sync sys_sync
|
||||
37 common kill sys_kill sys_kill
|
||||
38 common rename sys_rename compat_sys_rename
|
||||
39 common mkdir sys_mkdir compat_sys_mkdir
|
||||
40 common rmdir sys_rmdir compat_sys_rmdir
|
||||
41 common dup sys_dup sys_dup
|
||||
42 common pipe sys_pipe compat_sys_pipe
|
||||
43 common times sys_times compat_sys_times
|
||||
45 common brk sys_brk compat_sys_brk
|
||||
46 32 setgid - compat_sys_s390_setgid16
|
||||
47 32 getgid - compat_sys_s390_getgid16
|
||||
48 common signal sys_signal compat_sys_signal
|
||||
49 32 geteuid - compat_sys_s390_geteuid16
|
||||
50 32 getegid - compat_sys_s390_getegid16
|
||||
51 common acct sys_acct compat_sys_acct
|
||||
52 common umount2 sys_umount compat_sys_umount
|
||||
54 common ioctl sys_ioctl compat_sys_ioctl
|
||||
55 common fcntl sys_fcntl compat_sys_fcntl
|
||||
57 common setpgid sys_setpgid sys_setpgid
|
||||
60 common umask sys_umask sys_umask
|
||||
61 common chroot sys_chroot compat_sys_chroot
|
||||
62 common ustat sys_ustat compat_sys_ustat
|
||||
63 common dup2 sys_dup2 sys_dup2
|
||||
64 common getppid sys_getppid sys_getppid
|
||||
65 common getpgrp sys_getpgrp sys_getpgrp
|
||||
66 common setsid sys_setsid sys_setsid
|
||||
67 common sigaction sys_sigaction compat_sys_sigaction
|
||||
70 32 setreuid - compat_sys_s390_setreuid16
|
||||
71 32 setregid - compat_sys_s390_setregid16
|
||||
72 common sigsuspend sys_sigsuspend compat_sys_sigsuspend
|
||||
73 common sigpending sys_sigpending compat_sys_sigpending
|
||||
74 common sethostname sys_sethostname compat_sys_sethostname
|
||||
75 common setrlimit sys_setrlimit compat_sys_setrlimit
|
||||
76 32 getrlimit - compat_sys_old_getrlimit
|
||||
77 common getrusage sys_getrusage compat_sys_getrusage
|
||||
78 common gettimeofday sys_gettimeofday compat_sys_gettimeofday
|
||||
79 common settimeofday sys_settimeofday compat_sys_settimeofday
|
||||
80 32 getgroups - compat_sys_s390_getgroups16
|
||||
81 32 setgroups - compat_sys_s390_setgroups16
|
||||
83 common symlink sys_symlink compat_sys_symlink
|
||||
85 common readlink sys_readlink compat_sys_readlink
|
||||
86 common uselib sys_uselib compat_sys_uselib
|
||||
87 common swapon sys_swapon compat_sys_swapon
|
||||
88 common reboot sys_reboot compat_sys_reboot
|
||||
89 common readdir - compat_sys_old_readdir
|
||||
90 common mmap sys_old_mmap compat_sys_s390_old_mmap
|
||||
91 common munmap sys_munmap compat_sys_munmap
|
||||
92 common truncate sys_truncate compat_sys_truncate
|
||||
93 common ftruncate sys_ftruncate compat_sys_ftruncate
|
||||
94 common fchmod sys_fchmod sys_fchmod
|
||||
95 32 fchown - compat_sys_s390_fchown16
|
||||
96 common getpriority sys_getpriority sys_getpriority
|
||||
97 common setpriority sys_setpriority sys_setpriority
|
||||
99 common statfs sys_statfs compat_sys_statfs
|
||||
100 common fstatfs sys_fstatfs compat_sys_fstatfs
|
||||
101 32 ioperm - -
|
||||
102 common socketcall sys_socketcall compat_sys_socketcall
|
||||
103 common syslog sys_syslog compat_sys_syslog
|
||||
104 common setitimer sys_setitimer compat_sys_setitimer
|
||||
105 common getitimer sys_getitimer compat_sys_getitimer
|
||||
106 common stat sys_newstat compat_sys_newstat
|
||||
107 common lstat sys_newlstat compat_sys_newlstat
|
||||
108 common fstat sys_newfstat compat_sys_newfstat
|
||||
110 common lookup_dcookie sys_lookup_dcookie compat_sys_lookup_dcookie
|
||||
111 common vhangup sys_vhangup sys_vhangup
|
||||
112 common idle - -
|
||||
114 common wait4 sys_wait4 compat_sys_wait4
|
||||
115 common swapoff sys_swapoff compat_sys_swapoff
|
||||
116 common sysinfo sys_sysinfo compat_sys_sysinfo
|
||||
117 common ipc sys_s390_ipc compat_sys_s390_ipc
|
||||
118 common fsync sys_fsync sys_fsync
|
||||
119 common sigreturn sys_sigreturn compat_sys_sigreturn
|
||||
120 common clone sys_clone compat_sys_clone
|
||||
121 common setdomainname sys_setdomainname compat_sys_setdomainname
|
||||
122 common uname sys_newuname compat_sys_newuname
|
||||
124 common adjtimex sys_adjtimex compat_sys_adjtimex
|
||||
125 common mprotect sys_mprotect compat_sys_mprotect
|
||||
126 common sigprocmask sys_sigprocmask compat_sys_sigprocmask
|
||||
127 common create_module - -
|
||||
128 common init_module sys_init_module compat_sys_init_module
|
||||
129 common delete_module sys_delete_module compat_sys_delete_module
|
||||
130 common get_kernel_syms - -
|
||||
131 common quotactl sys_quotactl compat_sys_quotactl
|
||||
132 common getpgid sys_getpgid sys_getpgid
|
||||
133 common fchdir sys_fchdir sys_fchdir
|
||||
134 common bdflush sys_bdflush compat_sys_bdflush
|
||||
135 common sysfs sys_sysfs compat_sys_sysfs
|
||||
136 common personality sys_s390_personality sys_s390_personality
|
||||
137 common afs_syscall - -
|
||||
138 32 setfsuid - compat_sys_s390_setfsuid16
|
||||
139 32 setfsgid - compat_sys_s390_setfsgid16
|
||||
140 32 _llseek - compat_sys_llseek
|
||||
141 common getdents sys_getdents compat_sys_getdents
|
||||
142 32 _newselect - compat_sys_select
|
||||
142 64 select sys_select -
|
||||
143 common flock sys_flock sys_flock
|
||||
144 common msync sys_msync compat_sys_msync
|
||||
145 common readv sys_readv compat_sys_readv
|
||||
146 common writev sys_writev compat_sys_writev
|
||||
147 common getsid sys_getsid sys_getsid
|
||||
148 common fdatasync sys_fdatasync sys_fdatasync
|
||||
149 common _sysctl sys_sysctl compat_sys_sysctl
|
||||
150 common mlock sys_mlock compat_sys_mlock
|
||||
151 common munlock sys_munlock compat_sys_munlock
|
||||
152 common mlockall sys_mlockall sys_mlockall
|
||||
153 common munlockall sys_munlockall sys_munlockall
|
||||
154 common sched_setparam sys_sched_setparam compat_sys_sched_setparam
|
||||
155 common sched_getparam sys_sched_getparam compat_sys_sched_getparam
|
||||
156 common sched_setscheduler sys_sched_setscheduler compat_sys_sched_setscheduler
|
||||
157 common sched_getscheduler sys_sched_getscheduler sys_sched_getscheduler
|
||||
158 common sched_yield sys_sched_yield sys_sched_yield
|
||||
159 common sched_get_priority_max sys_sched_get_priority_max sys_sched_get_priority_max
|
||||
160 common sched_get_priority_min sys_sched_get_priority_min sys_sched_get_priority_min
|
||||
161 common sched_rr_get_interval sys_sched_rr_get_interval compat_sys_sched_rr_get_interval
|
||||
162 common nanosleep sys_nanosleep compat_sys_nanosleep
|
||||
163 common mremap sys_mremap compat_sys_mremap
|
||||
164 32 setresuid - compat_sys_s390_setresuid16
|
||||
165 32 getresuid - compat_sys_s390_getresuid16
|
||||
167 common query_module - -
|
||||
168 common poll sys_poll compat_sys_poll
|
||||
169 common nfsservctl - -
|
||||
170 32 setresgid - compat_sys_s390_setresgid16
|
||||
171 32 getresgid - compat_sys_s390_getresgid16
|
||||
172 common prctl sys_prctl compat_sys_prctl
|
||||
173 common rt_sigreturn sys_rt_sigreturn compat_sys_rt_sigreturn
|
||||
174 common rt_sigaction sys_rt_sigaction compat_sys_rt_sigaction
|
||||
175 common rt_sigprocmask sys_rt_sigprocmask compat_sys_rt_sigprocmask
|
||||
176 common rt_sigpending sys_rt_sigpending compat_sys_rt_sigpending
|
||||
177 common rt_sigtimedwait sys_rt_sigtimedwait compat_sys_rt_sigtimedwait
|
||||
178 common rt_sigqueueinfo sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo
|
||||
179 common rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend
|
||||
180 common pread64 sys_pread64 compat_sys_s390_pread64
|
||||
181 common pwrite64 sys_pwrite64 compat_sys_s390_pwrite64
|
||||
182 32 chown - compat_sys_s390_chown16
|
||||
183 common getcwd sys_getcwd compat_sys_getcwd
|
||||
184 common capget sys_capget compat_sys_capget
|
||||
185 common capset sys_capset compat_sys_capset
|
||||
186 common sigaltstack sys_sigaltstack compat_sys_sigaltstack
|
||||
187 common sendfile sys_sendfile64 compat_sys_sendfile
|
||||
188 common getpmsg - -
|
||||
189 common putpmsg - -
|
||||
190 common vfork sys_vfork sys_vfork
|
||||
191 32 ugetrlimit - compat_sys_getrlimit
|
||||
191 64 getrlimit sys_getrlimit -
|
||||
192 32 mmap2 - compat_sys_s390_mmap2
|
||||
193 32 truncate64 - compat_sys_s390_truncate64
|
||||
194 32 ftruncate64 - compat_sys_s390_ftruncate64
|
||||
195 32 stat64 - compat_sys_s390_stat64
|
||||
196 32 lstat64 - compat_sys_s390_lstat64
|
||||
197 32 fstat64 - compat_sys_s390_fstat64
|
||||
198 32 lchown32 - compat_sys_lchown
|
||||
198 64 lchown sys_lchown -
|
||||
199 32 getuid32 - sys_getuid
|
||||
199 64 getuid sys_getuid -
|
||||
200 32 getgid32 - sys_getgid
|
||||
200 64 getgid sys_getgid -
|
||||
201 32 geteuid32 - sys_geteuid
|
||||
201 64 geteuid sys_geteuid -
|
||||
202 32 getegid32 - sys_getegid
|
||||
202 64 getegid sys_getegid -
|
||||
203 32 setreuid32 - sys_setreuid
|
||||
203 64 setreuid sys_setreuid -
|
||||
204 32 setregid32 - sys_setregid
|
||||
204 64 setregid sys_setregid -
|
||||
205 32 getgroups32 - compat_sys_getgroups
|
||||
205 64 getgroups sys_getgroups -
|
||||
206 32 setgroups32 - compat_sys_setgroups
|
||||
206 64 setgroups sys_setgroups -
|
||||
207 32 fchown32 - sys_fchown
|
||||
207 64 fchown sys_fchown -
|
||||
208 32 setresuid32 - sys_setresuid
|
||||
208 64 setresuid sys_setresuid -
|
||||
209 32 getresuid32 - compat_sys_getresuid
|
||||
209 64 getresuid sys_getresuid -
|
||||
210 32 setresgid32 - sys_setresgid
|
||||
210 64 setresgid sys_setresgid -
|
||||
211 32 getresgid32 - compat_sys_getresgid
|
||||
211 64 getresgid sys_getresgid -
|
||||
212 32 chown32 - compat_sys_chown
|
||||
212 64 chown sys_chown -
|
||||
213 32 setuid32 - sys_setuid
|
||||
213 64 setuid sys_setuid -
|
||||
214 32 setgid32 - sys_setgid
|
||||
214 64 setgid sys_setgid -
|
||||
215 32 setfsuid32 - sys_setfsuid
|
||||
215 64 setfsuid sys_setfsuid -
|
||||
216 32 setfsgid32 - sys_setfsgid
|
||||
216 64 setfsgid sys_setfsgid -
|
||||
217 common pivot_root sys_pivot_root compat_sys_pivot_root
|
||||
218 common mincore sys_mincore compat_sys_mincore
|
||||
219 common madvise sys_madvise compat_sys_madvise
|
||||
220 common getdents64 sys_getdents64 compat_sys_getdents64
|
||||
221 32 fcntl64 - compat_sys_fcntl64
|
||||
222 common readahead sys_readahead compat_sys_s390_readahead
|
||||
223 32 sendfile64 - compat_sys_sendfile64
|
||||
224 common setxattr sys_setxattr compat_sys_setxattr
|
||||
225 common lsetxattr sys_lsetxattr compat_sys_lsetxattr
|
||||
226 common fsetxattr sys_fsetxattr compat_sys_fsetxattr
|
||||
227 common getxattr sys_getxattr compat_sys_getxattr
|
||||
228 common lgetxattr sys_lgetxattr compat_sys_lgetxattr
|
||||
229 common fgetxattr sys_fgetxattr compat_sys_fgetxattr
|
||||
230 common listxattr sys_listxattr compat_sys_listxattr
|
||||
231 common llistxattr sys_llistxattr compat_sys_llistxattr
|
||||
232 common flistxattr sys_flistxattr compat_sys_flistxattr
|
||||
233 common removexattr sys_removexattr compat_sys_removexattr
|
||||
234 common lremovexattr sys_lremovexattr compat_sys_lremovexattr
|
||||
235 common fremovexattr sys_fremovexattr compat_sys_fremovexattr
|
||||
236 common gettid sys_gettid sys_gettid
|
||||
237 common tkill sys_tkill sys_tkill
|
||||
238 common futex sys_futex compat_sys_futex
|
||||
239 common sched_setaffinity sys_sched_setaffinity compat_sys_sched_setaffinity
|
||||
240 common sched_getaffinity sys_sched_getaffinity compat_sys_sched_getaffinity
|
||||
241 common tgkill sys_tgkill sys_tgkill
|
||||
243 common io_setup sys_io_setup compat_sys_io_setup
|
||||
244 common io_destroy sys_io_destroy compat_sys_io_destroy
|
||||
245 common io_getevents sys_io_getevents compat_sys_io_getevents
|
||||
246 common io_submit sys_io_submit compat_sys_io_submit
|
||||
247 common io_cancel sys_io_cancel compat_sys_io_cancel
|
||||
248 common exit_group sys_exit_group sys_exit_group
|
||||
249 common epoll_create sys_epoll_create sys_epoll_create
|
||||
250 common epoll_ctl sys_epoll_ctl compat_sys_epoll_ctl
|
||||
251 common epoll_wait sys_epoll_wait compat_sys_epoll_wait
|
||||
252 common set_tid_address sys_set_tid_address compat_sys_set_tid_address
|
||||
253 common fadvise64 sys_fadvise64_64 compat_sys_s390_fadvise64
|
||||
254 common timer_create sys_timer_create compat_sys_timer_create
|
||||
255 common timer_settime sys_timer_settime compat_sys_timer_settime
|
||||
256 common timer_gettime sys_timer_gettime compat_sys_timer_gettime
|
||||
257 common timer_getoverrun sys_timer_getoverrun sys_timer_getoverrun
|
||||
258 common timer_delete sys_timer_delete sys_timer_delete
|
||||
259 common clock_settime sys_clock_settime compat_sys_clock_settime
|
||||
260 common clock_gettime sys_clock_gettime compat_sys_clock_gettime
|
||||
261 common clock_getres sys_clock_getres compat_sys_clock_getres
|
||||
262 common clock_nanosleep sys_clock_nanosleep compat_sys_clock_nanosleep
|
||||
264 32 fadvise64_64 - compat_sys_s390_fadvise64_64
|
||||
265 common statfs64 sys_statfs64 compat_sys_statfs64
|
||||
266 common fstatfs64 sys_fstatfs64 compat_sys_fstatfs64
|
||||
267 common remap_file_pages sys_remap_file_pages compat_sys_remap_file_pages
|
||||
268 common mbind sys_mbind compat_sys_mbind
|
||||
269 common get_mempolicy sys_get_mempolicy compat_sys_get_mempolicy
|
||||
270 common set_mempolicy sys_set_mempolicy compat_sys_set_mempolicy
|
||||
271 common mq_open sys_mq_open compat_sys_mq_open
|
||||
272 common mq_unlink sys_mq_unlink compat_sys_mq_unlink
|
||||
273 common mq_timedsend sys_mq_timedsend compat_sys_mq_timedsend
|
||||
274 common mq_timedreceive sys_mq_timedreceive compat_sys_mq_timedreceive
|
||||
275 common mq_notify sys_mq_notify compat_sys_mq_notify
|
||||
276 common mq_getsetattr sys_mq_getsetattr compat_sys_mq_getsetattr
|
||||
277 common kexec_load sys_kexec_load compat_sys_kexec_load
|
||||
278 common add_key sys_add_key compat_sys_add_key
|
||||
279 common request_key sys_request_key compat_sys_request_key
|
||||
280 common keyctl sys_keyctl compat_sys_keyctl
|
||||
281 common waitid sys_waitid compat_sys_waitid
|
||||
282 common ioprio_set sys_ioprio_set sys_ioprio_set
|
||||
283 common ioprio_get sys_ioprio_get sys_ioprio_get
|
||||
284 common inotify_init sys_inotify_init sys_inotify_init
|
||||
285 common inotify_add_watch sys_inotify_add_watch compat_sys_inotify_add_watch
|
||||
286 common inotify_rm_watch sys_inotify_rm_watch sys_inotify_rm_watch
|
||||
287 common migrate_pages sys_migrate_pages compat_sys_migrate_pages
|
||||
288 common openat sys_openat compat_sys_openat
|
||||
289 common mkdirat sys_mkdirat compat_sys_mkdirat
|
||||
290 common mknodat sys_mknodat compat_sys_mknodat
|
||||
291 common fchownat sys_fchownat compat_sys_fchownat
|
||||
292 common futimesat sys_futimesat compat_sys_futimesat
|
||||
293 32 fstatat64 - compat_sys_s390_fstatat64
|
||||
293 64 newfstatat sys_newfstatat -
|
||||
294 common unlinkat sys_unlinkat compat_sys_unlinkat
|
||||
295 common renameat sys_renameat compat_sys_renameat
|
||||
296 common linkat sys_linkat compat_sys_linkat
|
||||
297 common symlinkat sys_symlinkat compat_sys_symlinkat
|
||||
298 common readlinkat sys_readlinkat compat_sys_readlinkat
|
||||
299 common fchmodat sys_fchmodat compat_sys_fchmodat
|
||||
300 common faccessat sys_faccessat compat_sys_faccessat
|
||||
301 common pselect6 sys_pselect6 compat_sys_pselect6
|
||||
302 common ppoll sys_ppoll compat_sys_ppoll
|
||||
303 common unshare sys_unshare compat_sys_unshare
|
||||
304 common set_robust_list sys_set_robust_list compat_sys_set_robust_list
|
||||
305 common get_robust_list sys_get_robust_list compat_sys_get_robust_list
|
||||
306 common splice sys_splice compat_sys_splice
|
||||
307 common sync_file_range sys_sync_file_range compat_sys_s390_sync_file_range
|
||||
308 common tee sys_tee compat_sys_tee
|
||||
309 common vmsplice sys_vmsplice compat_sys_vmsplice
|
||||
310 common move_pages sys_move_pages compat_sys_move_pages
|
||||
311 common getcpu sys_getcpu compat_sys_getcpu
|
||||
312 common epoll_pwait sys_epoll_pwait compat_sys_epoll_pwait
|
||||
313 common utimes sys_utimes compat_sys_utimes
|
||||
314 common fallocate sys_fallocate compat_sys_s390_fallocate
|
||||
315 common utimensat sys_utimensat compat_sys_utimensat
|
||||
316 common signalfd sys_signalfd compat_sys_signalfd
|
||||
317 common timerfd - -
|
||||
318 common eventfd sys_eventfd sys_eventfd
|
||||
319 common timerfd_create sys_timerfd_create sys_timerfd_create
|
||||
320 common timerfd_settime sys_timerfd_settime compat_sys_timerfd_settime
|
||||
321 common timerfd_gettime sys_timerfd_gettime compat_sys_timerfd_gettime
|
||||
322 common signalfd4 sys_signalfd4 compat_sys_signalfd4
|
||||
323 common eventfd2 sys_eventfd2 sys_eventfd2
|
||||
324 common inotify_init1 sys_inotify_init1 sys_inotify_init1
|
||||
325 common pipe2 sys_pipe2 compat_sys_pipe2
|
||||
326 common dup3 sys_dup3 sys_dup3
|
||||
327 common epoll_create1 sys_epoll_create1 sys_epoll_create1
|
||||
328 common preadv sys_preadv compat_sys_preadv
|
||||
329 common pwritev sys_pwritev compat_sys_pwritev
|
||||
330 common rt_tgsigqueueinfo sys_rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo
|
||||
331 common perf_event_open sys_perf_event_open compat_sys_perf_event_open
|
||||
332 common fanotify_init sys_fanotify_init sys_fanotify_init
|
||||
333 common fanotify_mark sys_fanotify_mark compat_sys_fanotify_mark
|
||||
334 common prlimit64 sys_prlimit64 compat_sys_prlimit64
|
||||
335 common name_to_handle_at sys_name_to_handle_at compat_sys_name_to_handle_at
|
||||
336 common open_by_handle_at sys_open_by_handle_at compat_sys_open_by_handle_at
|
||||
337 common clock_adjtime sys_clock_adjtime compat_sys_clock_adjtime
|
||||
338 common syncfs sys_syncfs sys_syncfs
|
||||
339 common setns sys_setns sys_setns
|
||||
340 common process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv
|
||||
341 common process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev
|
||||
342 common s390_runtime_instr sys_s390_runtime_instr sys_s390_runtime_instr
|
||||
343 common kcmp sys_kcmp compat_sys_kcmp
|
||||
344 common finit_module sys_finit_module compat_sys_finit_module
|
||||
345 common sched_setattr sys_sched_setattr compat_sys_sched_setattr
|
||||
346 common sched_getattr sys_sched_getattr compat_sys_sched_getattr
|
||||
347 common renameat2 sys_renameat2 compat_sys_renameat2
|
||||
348 common seccomp sys_seccomp compat_sys_seccomp
|
||||
349 common getrandom sys_getrandom compat_sys_getrandom
|
||||
350 common memfd_create sys_memfd_create compat_sys_memfd_create
|
||||
351 common bpf sys_bpf compat_sys_bpf
|
||||
352 common s390_pci_mmio_write sys_s390_pci_mmio_write compat_sys_s390_pci_mmio_write
|
||||
353 common s390_pci_mmio_read sys_s390_pci_mmio_read compat_sys_s390_pci_mmio_read
|
||||
354 common execveat sys_execveat compat_sys_execveat
|
||||
355 common userfaultfd sys_userfaultfd sys_userfaultfd
|
||||
356 common membarrier sys_membarrier sys_membarrier
|
||||
357 common recvmmsg sys_recvmmsg compat_sys_recvmmsg
|
||||
358 common sendmmsg sys_sendmmsg compat_sys_sendmmsg
|
||||
359 common socket sys_socket sys_socket
|
||||
360 common socketpair sys_socketpair compat_sys_socketpair
|
||||
361 common bind sys_bind compat_sys_bind
|
||||
362 common connect sys_connect compat_sys_connect
|
||||
363 common listen sys_listen sys_listen
|
||||
364 common accept4 sys_accept4 compat_sys_accept4
|
||||
365 common getsockopt sys_getsockopt compat_sys_getsockopt
|
||||
366 common setsockopt sys_setsockopt compat_sys_setsockopt
|
||||
367 common getsockname sys_getsockname compat_sys_getsockname
|
||||
368 common getpeername sys_getpeername compat_sys_getpeername
|
||||
369 common sendto sys_sendto compat_sys_sendto
|
||||
370 common sendmsg sys_sendmsg compat_sys_sendmsg
|
||||
371 common recvfrom sys_recvfrom compat_sys_recvfrom
|
||||
372 common recvmsg sys_recvmsg compat_sys_recvmsg
|
||||
373 common shutdown sys_shutdown sys_shutdown
|
||||
374 common mlock2 sys_mlock2 compat_sys_mlock2
|
||||
375 common copy_file_range sys_copy_file_range compat_sys_copy_file_range
|
||||
376 common preadv2 sys_preadv2 compat_sys_preadv2
|
||||
377 common pwritev2 sys_pwritev2 compat_sys_pwritev2
|
||||
378 common s390_guarded_storage sys_s390_guarded_storage compat_sys_s390_guarded_storage
|
||||
379 common statx sys_statx compat_sys_statx
|
||||
380 common s390_sthyi sys_s390_sthyi compat_sys_s390_sthyi
|
||||
@@ -2245,7 +2245,7 @@ static int perf_c2c__browse_cacheline(struct hist_entry *he)
|
||||
c2c_browser__update_nr_entries(browser);
|
||||
|
||||
while (1) {
|
||||
key = hist_browser__run(browser, "? - help");
|
||||
key = hist_browser__run(browser, "? - help", true);
|
||||
|
||||
switch (key) {
|
||||
case 's':
|
||||
@@ -2314,7 +2314,7 @@ static int perf_c2c__hists_browse(struct hists *hists)
|
||||
c2c_browser__update_nr_entries(browser);
|
||||
|
||||
while (1) {
|
||||
key = hist_browser__run(browser, "? - help");
|
||||
key = hist_browser__run(browser, "? - help", true);
|
||||
|
||||
switch (key) {
|
||||
case 'q':
|
||||
|
||||
@@ -530,7 +530,8 @@ static int report__browse_hists(struct report *rep)
|
||||
case 1:
|
||||
ret = perf_evlist__tui_browse_hists(evlist, help, NULL,
|
||||
rep->min_percent,
|
||||
&session->header.env);
|
||||
&session->header.env,
|
||||
true);
|
||||
/*
|
||||
* Usually "ret" is the last pressed key, and we only
|
||||
* care if the key notifies us to switch data file.
|
||||
|
||||
@@ -283,8 +283,9 @@ static void perf_top__print_sym_table(struct perf_top *top)
|
||||
|
||||
printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
|
||||
|
||||
if (hists->stats.nr_lost_warned !=
|
||||
hists->stats.nr_events[PERF_RECORD_LOST]) {
|
||||
if (!top->record_opts.overwrite &&
|
||||
(hists->stats.nr_lost_warned !=
|
||||
hists->stats.nr_events[PERF_RECORD_LOST])) {
|
||||
hists->stats.nr_lost_warned =
|
||||
hists->stats.nr_events[PERF_RECORD_LOST];
|
||||
color_fprintf(stdout, PERF_COLOR_RED,
|
||||
@@ -611,7 +612,8 @@ static void *display_thread_tui(void *arg)
|
||||
|
||||
perf_evlist__tui_browse_hists(top->evlist, help, &hbt,
|
||||
top->min_percent,
|
||||
&top->session->header.env);
|
||||
&top->session->header.env,
|
||||
!top->record_opts.overwrite);
|
||||
|
||||
done = 1;
|
||||
return NULL;
|
||||
@@ -807,15 +809,23 @@ static void perf_event__process_sample(struct perf_tool *tool,
|
||||
|
||||
static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
|
||||
{
|
||||
struct record_opts *opts = &top->record_opts;
|
||||
struct perf_evlist *evlist = top->evlist;
|
||||
struct perf_sample sample;
|
||||
struct perf_evsel *evsel;
|
||||
struct perf_mmap *md;
|
||||
struct perf_session *session = top->session;
|
||||
union perf_event *event;
|
||||
struct machine *machine;
|
||||
u64 end, start;
|
||||
int ret;
|
||||
|
||||
while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) {
|
||||
ret = perf_evlist__parse_sample(top->evlist, event, &sample);
|
||||
md = opts->overwrite ? &evlist->overwrite_mmap[idx] : &evlist->mmap[idx];
|
||||
if (perf_mmap__read_init(md, opts->overwrite, &start, &end) < 0)
|
||||
return;
|
||||
|
||||
while ((event = perf_mmap__read_event(md, opts->overwrite, &start, end)) != NULL) {
|
||||
ret = perf_evlist__parse_sample(evlist, event, &sample);
|
||||
if (ret) {
|
||||
pr_err("Can't parse sample, err = %d\n", ret);
|
||||
goto next_event;
|
||||
@@ -869,16 +879,120 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
|
||||
} else
|
||||
++session->evlist->stats.nr_unknown_events;
|
||||
next_event:
|
||||
perf_evlist__mmap_consume(top->evlist, idx);
|
||||
perf_mmap__consume(md, opts->overwrite);
|
||||
}
|
||||
|
||||
perf_mmap__read_done(md);
|
||||
}
|
||||
|
||||
static void perf_top__mmap_read(struct perf_top *top)
|
||||
{
|
||||
bool overwrite = top->record_opts.overwrite;
|
||||
struct perf_evlist *evlist = top->evlist;
|
||||
unsigned long long start, end;
|
||||
int i;
|
||||
|
||||
start = rdclock();
|
||||
if (overwrite)
|
||||
perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_DATA_PENDING);
|
||||
|
||||
for (i = 0; i < top->evlist->nr_mmaps; i++)
|
||||
perf_top__mmap_read_idx(top, i);
|
||||
|
||||
if (overwrite) {
|
||||
perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
|
||||
perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING);
|
||||
}
|
||||
end = rdclock();
|
||||
|
||||
if ((end - start) > (unsigned long long)top->delay_secs * NSEC_PER_SEC)
|
||||
ui__warning("Too slow to read ring buffer.\n"
|
||||
"Please try increasing the period (-c) or\n"
|
||||
"decreasing the freq (-F) or\n"
|
||||
"limiting the number of CPUs (-C)\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Check per-event overwrite term.
|
||||
* perf top should support consistent term for all events.
|
||||
* - All events don't have per-event term
|
||||
* E.g. "cpu/cpu-cycles/,cpu/instructions/"
|
||||
* Nothing change, return 0.
|
||||
* - All events have same per-event term
|
||||
* E.g. "cpu/cpu-cycles,no-overwrite/,cpu/instructions,no-overwrite/
|
||||
* Using the per-event setting to replace the opts->overwrite if
|
||||
* they are different, then return 0.
|
||||
* - Events have different per-event term
|
||||
* E.g. "cpu/cpu-cycles,overwrite/,cpu/instructions,no-overwrite/"
|
||||
* Return -1
|
||||
* - Some of the event set per-event term, but some not.
|
||||
* E.g. "cpu/cpu-cycles/,cpu/instructions,no-overwrite/"
|
||||
* Return -1
|
||||
*/
|
||||
static int perf_top__overwrite_check(struct perf_top *top)
|
||||
{
|
||||
struct record_opts *opts = &top->record_opts;
|
||||
struct perf_evlist *evlist = top->evlist;
|
||||
struct perf_evsel_config_term *term;
|
||||
struct list_head *config_terms;
|
||||
struct perf_evsel *evsel;
|
||||
int set, overwrite = -1;
|
||||
|
||||
evlist__for_each_entry(evlist, evsel) {
|
||||
set = -1;
|
||||
config_terms = &evsel->config_terms;
|
||||
list_for_each_entry(term, config_terms, list) {
|
||||
if (term->type == PERF_EVSEL__CONFIG_TERM_OVERWRITE)
|
||||
set = term->val.overwrite ? 1 : 0;
|
||||
}
|
||||
|
||||
/* no term for current and previous event (likely) */
|
||||
if ((overwrite < 0) && (set < 0))
|
||||
continue;
|
||||
|
||||
/* has term for both current and previous event, compare */
|
||||
if ((overwrite >= 0) && (set >= 0) && (overwrite != set))
|
||||
return -1;
|
||||
|
||||
/* no term for current event but has term for previous one */
|
||||
if ((overwrite >= 0) && (set < 0))
|
||||
return -1;
|
||||
|
||||
/* has term for current event */
|
||||
if ((overwrite < 0) && (set >= 0)) {
|
||||
/* if it's first event, set overwrite */
|
||||
if (evsel == perf_evlist__first(evlist))
|
||||
overwrite = set;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((overwrite >= 0) && (opts->overwrite != overwrite))
|
||||
opts->overwrite = overwrite;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int perf_top_overwrite_fallback(struct perf_top *top,
|
||||
struct perf_evsel *evsel)
|
||||
{
|
||||
struct record_opts *opts = &top->record_opts;
|
||||
struct perf_evlist *evlist = top->evlist;
|
||||
struct perf_evsel *counter;
|
||||
|
||||
if (!opts->overwrite)
|
||||
return 0;
|
||||
|
||||
/* only fall back when first event fails */
|
||||
if (evsel != perf_evlist__first(evlist))
|
||||
return 0;
|
||||
|
||||
evlist__for_each_entry(evlist, counter)
|
||||
counter->attr.write_backward = false;
|
||||
opts->overwrite = false;
|
||||
ui__warning("fall back to non-overwrite mode\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int perf_top__start_counters(struct perf_top *top)
|
||||
@@ -888,12 +1002,33 @@ static int perf_top__start_counters(struct perf_top *top)
|
||||
struct perf_evlist *evlist = top->evlist;
|
||||
struct record_opts *opts = &top->record_opts;
|
||||
|
||||
if (perf_top__overwrite_check(top)) {
|
||||
ui__error("perf top only support consistent per-event "
|
||||
"overwrite setting for all events\n");
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
perf_evlist__config(evlist, opts, &callchain_param);
|
||||
|
||||
evlist__for_each_entry(evlist, counter) {
|
||||
try_again:
|
||||
if (perf_evsel__open(counter, top->evlist->cpus,
|
||||
top->evlist->threads) < 0) {
|
||||
|
||||
/*
|
||||
* Specially handle overwrite fall back.
|
||||
* Because perf top is the only tool which has
|
||||
* overwrite mode by default, support
|
||||
* both overwrite and non-overwrite mode, and
|
||||
* require consistent mode for all events.
|
||||
*
|
||||
* May move it to generic code with more tools
|
||||
* have similar attribute.
|
||||
*/
|
||||
if (perf_missing_features.write_backward &&
|
||||
perf_top_overwrite_fallback(top, counter))
|
||||
goto try_again;
|
||||
|
||||
if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
|
||||
if (verbose > 0)
|
||||
ui__warning("%s\n", msg);
|
||||
@@ -1033,7 +1168,7 @@ static int __cmd_top(struct perf_top *top)
|
||||
|
||||
perf_top__mmap_read(top);
|
||||
|
||||
if (hits == top->samples)
|
||||
if (opts->overwrite || (hits == top->samples))
|
||||
ret = perf_evlist__poll(top->evlist, 100);
|
||||
|
||||
if (resize) {
|
||||
@@ -1127,6 +1262,7 @@ int cmd_top(int argc, const char **argv)
|
||||
.uses_mmap = true,
|
||||
},
|
||||
.proc_map_timeout = 500,
|
||||
.overwrite = 1,
|
||||
},
|
||||
.max_stack = sysctl_perf_event_max_stack,
|
||||
.sym_pcnt_filter = 5,
|
||||
|
||||
@@ -33,7 +33,6 @@ arch/s390/include/uapi/asm/kvm.h
|
||||
arch/s390/include/uapi/asm/kvm_perf.h
|
||||
arch/s390/include/uapi/asm/ptrace.h
|
||||
arch/s390/include/uapi/asm/sie.h
|
||||
arch/s390/include/uapi/asm/unistd.h
|
||||
arch/arm/include/uapi/asm/kvm.h
|
||||
arch/arm64/include/uapi/asm/kvm.h
|
||||
arch/alpha/include/uapi/asm/errno.h
|
||||
|
||||
27
tools/perf/pmu-events/arch/arm64/cortex-a53/branch.json
Normal file
27
tools/perf/pmu-events/arch/arm64/cortex-a53/branch.json
Normal file
@@ -0,0 +1,27 @@
|
||||
[
|
||||
{,
|
||||
"EventCode": "0x7A",
|
||||
"EventName": "BR_INDIRECT_SPEC",
|
||||
"BriefDescription": "Branch speculatively executed - Indirect branch"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xC9",
|
||||
"EventName": "BR_COND",
|
||||
"BriefDescription": "Conditional branch executed"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xCA",
|
||||
"EventName": "BR_INDIRECT_MISPRED",
|
||||
"BriefDescription": "Indirect branch mispredicted"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xCB",
|
||||
"EventName": "BR_INDIRECT_MISPRED_ADDR",
|
||||
"BriefDescription": "Indirect branch mispredicted because of address miscompare"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xCC",
|
||||
"EventName": "BR_COND_MISPRED",
|
||||
"BriefDescription": "Conditional branch mispredicted"
|
||||
}
|
||||
]
|
||||
22
tools/perf/pmu-events/arch/arm64/cortex-a53/bus.json
Normal file
22
tools/perf/pmu-events/arch/arm64/cortex-a53/bus.json
Normal file
@@ -0,0 +1,22 @@
|
||||
[
|
||||
{,
|
||||
"EventCode": "0x60",
|
||||
"EventName": "BUS_ACCESS_LD",
|
||||
"BriefDescription": "Bus access - Read"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0x61",
|
||||
"EventName": "BUS_ACCESS_ST",
|
||||
"BriefDescription": "Bus access - Write"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xC0",
|
||||
"EventName": "EXT_MEM_REQ",
|
||||
"BriefDescription": "External memory request"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xC1",
|
||||
"EventName": "EXT_MEM_REQ_NC",
|
||||
"BriefDescription": "Non-cacheable external memory request"
|
||||
}
|
||||
]
|
||||
27
tools/perf/pmu-events/arch/arm64/cortex-a53/cache.json
Normal file
27
tools/perf/pmu-events/arch/arm64/cortex-a53/cache.json
Normal file
@@ -0,0 +1,27 @@
|
||||
[
|
||||
{,
|
||||
"EventCode": "0xC2",
|
||||
"EventName": "PREFETCH_LINEFILL",
|
||||
"BriefDescription": "Linefill because of prefetch"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xC3",
|
||||
"EventName": "PREFETCH_LINEFILL_DROP",
|
||||
"BriefDescription": "Instruction Cache Throttle occurred"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xC4",
|
||||
"EventName": "READ_ALLOC_ENTER",
|
||||
"BriefDescription": "Entering read allocate mode"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xC5",
|
||||
"EventName": "READ_ALLOC",
|
||||
"BriefDescription": "Read allocate mode"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xC8",
|
||||
"EventName": "EXT_SNOOP",
|
||||
"BriefDescription": "SCU Snooped data from another CPU for this CPU"
|
||||
}
|
||||
]
|
||||
22
tools/perf/pmu-events/arch/arm64/cortex-a53/memory.json
Normal file
22
tools/perf/pmu-events/arch/arm64/cortex-a53/memory.json
Normal file
@@ -0,0 +1,22 @@
|
||||
[
|
||||
{,
|
||||
"EventCode": "0x60",
|
||||
"EventName": "BUS_ACCESS_LD",
|
||||
"BriefDescription": "Bus access - Read"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0x61",
|
||||
"EventName": "BUS_ACCESS_ST",
|
||||
"BriefDescription": "Bus access - Write"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xC0",
|
||||
"EventName": "EXT_MEM_REQ",
|
||||
"BriefDescription": "External memory request"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xC1",
|
||||
"EventName": "EXT_MEM_REQ_NC",
|
||||
"BriefDescription": "Non-cacheable external memory request"
|
||||
}
|
||||
]
|
||||
32
tools/perf/pmu-events/arch/arm64/cortex-a53/other.json
Normal file
32
tools/perf/pmu-events/arch/arm64/cortex-a53/other.json
Normal file
@@ -0,0 +1,32 @@
|
||||
[
|
||||
{,
|
||||
"EventCode": "0x86",
|
||||
"EventName": "EXC_IRQ",
|
||||
"BriefDescription": "Exception taken, IRQ"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0x87",
|
||||
"EventName": "EXC_FIQ",
|
||||
"BriefDescription": "Exception taken, FIQ"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xC6",
|
||||
"EventName": "PRE_DECODE_ERR",
|
||||
"BriefDescription": "Pre-decode error"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xD0",
|
||||
"EventName": "L1I_CACHE_ERR",
|
||||
"BriefDescription": "L1 Instruction Cache (data or tag) memory error"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xD1",
|
||||
"EventName": "L1D_CACHE_ERR",
|
||||
"BriefDescription": "L1 Data Cache (data, tag or dirty) memory error, correctable or non-correctable"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xD2",
|
||||
"EventName": "TLB_ERR",
|
||||
"BriefDescription": "TLB memory error"
|
||||
}
|
||||
]
|
||||
52
tools/perf/pmu-events/arch/arm64/cortex-a53/pipeline.json
Normal file
52
tools/perf/pmu-events/arch/arm64/cortex-a53/pipeline.json
Normal file
@@ -0,0 +1,52 @@
|
||||
[
|
||||
{,
|
||||
"EventCode": "0xC7",
|
||||
"EventName": "STALL_SB_FULL",
|
||||
"BriefDescription": "Data Write operation that stalls the pipeline because the store buffer is full"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xE0",
|
||||
"EventName": "OTHER_IQ_DEP_STALL",
|
||||
"BriefDescription": "Cycles that the DPU IQ is empty and that is not because of a recent micro-TLB miss, instruction cache miss or pre-decode error"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xE1",
|
||||
"EventName": "IC_DEP_STALL",
|
||||
"BriefDescription": "Cycles the DPU IQ is empty and there is an instruction cache miss being processed"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xE2",
|
||||
"EventName": "IUTLB_DEP_STALL",
|
||||
"BriefDescription": "Cycles the DPU IQ is empty and there is an instruction micro-TLB miss being processed"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xE3",
|
||||
"EventName": "DECODE_DEP_STALL",
|
||||
"BriefDescription": "Cycles the DPU IQ is empty and there is a pre-decode error being processed"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xE4",
|
||||
"EventName": "OTHER_INTERLOCK_STALL",
|
||||
"BriefDescription": "Cycles there is an interlock other than Advanced SIMD/Floating-point instructions or load/store instruction"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xE5",
|
||||
"EventName": "AGU_DEP_STALL",
|
||||
"BriefDescription": "Cycles there is an interlock for a load/store instruction waiting for data to calculate the address in the AGU"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xE6",
|
||||
"EventName": "SIMD_DEP_STALL",
|
||||
"BriefDescription": "Cycles there is an interlock for an Advanced SIMD/Floating-point operation."
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xE7",
|
||||
"EventName": "LD_DEP_STALL",
|
||||
"BriefDescription": "Cycles there is a stall in the Wr stage because of a load miss"
|
||||
},
|
||||
{,
|
||||
"EventCode": "0xE8",
|
||||
"EventName": "ST_DEP_STALL",
|
||||
"BriefDescription": "Cycles there is a stall in the Wr stage because of a store"
|
||||
}
|
||||
]
|
||||
@@ -13,3 +13,4 @@
|
||||
#
|
||||
#Family-model,Version,Filename,EventType
|
||||
0x00000000420f5160,v1,cavium,core
|
||||
0x00000000410fd03[[:xdigit:]],v1,cortex-a53,core
|
||||
|
||||
|
@@ -31,10 +31,12 @@ static int count_samples(struct perf_evlist *evlist, int *sample_count,
|
||||
int i;
|
||||
|
||||
for (i = 0; i < evlist->nr_mmaps; i++) {
|
||||
struct perf_mmap *map = &evlist->overwrite_mmap[i];
|
||||
union perf_event *event;
|
||||
u64 start, end;
|
||||
|
||||
perf_mmap__read_catchup(&evlist->overwrite_mmap[i]);
|
||||
while ((event = perf_mmap__read_backward(&evlist->overwrite_mmap[i])) != NULL) {
|
||||
perf_mmap__read_init(map, true, &start, &end);
|
||||
while ((event = perf_mmap__read_event(map, true, &start, end)) != NULL) {
|
||||
const u32 type = event->header.type;
|
||||
|
||||
switch (type) {
|
||||
@@ -49,6 +51,7 @@ static int count_samples(struct perf_evlist *evlist, int *sample_count,
|
||||
return TEST_FAIL;
|
||||
}
|
||||
}
|
||||
perf_mmap__read_done(map);
|
||||
}
|
||||
return TEST_OK;
|
||||
}
|
||||
|
||||
@@ -22,10 +22,23 @@ trace_libc_inet_pton_backtrace() {
|
||||
expected[4]="rtt min.*"
|
||||
expected[5]="[0-9]+\.[0-9]+[[:space:]]+probe_libc:inet_pton:\([[:xdigit:]]+\)"
|
||||
expected[6]=".*inet_pton[[:space:]]\($libc\)$"
|
||||
expected[7]="getaddrinfo[[:space:]]\($libc\)$"
|
||||
expected[8]=".*\(.*/bin/ping.*\)$"
|
||||
case "$(uname -m)" in
|
||||
s390x)
|
||||
eventattr='call-graph=dwarf'
|
||||
expected[7]="gaih_inet[[:space:]]\(inlined\)$"
|
||||
expected[8]="__GI_getaddrinfo[[:space:]]\(inlined\)$"
|
||||
expected[9]="main[[:space:]]\(.*/bin/ping.*\)$"
|
||||
expected[10]="__libc_start_main[[:space:]]\($libc\)$"
|
||||
expected[11]="_start[[:space:]]\(.*/bin/ping.*\)$"
|
||||
;;
|
||||
*)
|
||||
eventattr='max-stack=3'
|
||||
expected[7]="getaddrinfo[[:space:]]\($libc\)$"
|
||||
expected[8]=".*\(.*/bin/ping.*\)$"
|
||||
;;
|
||||
esac
|
||||
|
||||
perf trace --no-syscalls -e probe_libc:inet_pton/max-stack=3/ ping -6 -c 1 ::1 2>&1 | grep -v ^$ | while read line ; do
|
||||
perf trace --no-syscalls -e probe_libc:inet_pton/$eventattr/ ping -6 -c 1 ::1 2>&1 | grep -v ^$ | while read line ; do
|
||||
echo $line
|
||||
echo "$line" | egrep -q "${expected[$idx]}"
|
||||
if [ $? -ne 0 ] ; then
|
||||
@@ -33,7 +46,7 @@ trace_libc_inet_pton_backtrace() {
|
||||
exit 1
|
||||
fi
|
||||
let idx+=1
|
||||
[ $idx -eq 9 ] && break
|
||||
[ -z "${expected[$idx]}" ] && break
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
@@ -608,7 +608,8 @@ static int hist_browser__title(struct hist_browser *browser, char *bf, size_t si
|
||||
return browser->title ? browser->title(browser, bf, size) : 0;
|
||||
}
|
||||
|
||||
int hist_browser__run(struct hist_browser *browser, const char *help)
|
||||
int hist_browser__run(struct hist_browser *browser, const char *help,
|
||||
bool warn_lost_event)
|
||||
{
|
||||
int key;
|
||||
char title[160];
|
||||
@@ -638,8 +639,9 @@ int hist_browser__run(struct hist_browser *browser, const char *help)
|
||||
nr_entries = hist_browser__nr_entries(browser);
|
||||
ui_browser__update_nr_entries(&browser->b, nr_entries);
|
||||
|
||||
if (browser->hists->stats.nr_lost_warned !=
|
||||
browser->hists->stats.nr_events[PERF_RECORD_LOST]) {
|
||||
if (warn_lost_event &&
|
||||
(browser->hists->stats.nr_lost_warned !=
|
||||
browser->hists->stats.nr_events[PERF_RECORD_LOST])) {
|
||||
browser->hists->stats.nr_lost_warned =
|
||||
browser->hists->stats.nr_events[PERF_RECORD_LOST];
|
||||
ui_browser__warn_lost_events(&browser->b);
|
||||
@@ -2763,7 +2765,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
|
||||
bool left_exits,
|
||||
struct hist_browser_timer *hbt,
|
||||
float min_pcnt,
|
||||
struct perf_env *env)
|
||||
struct perf_env *env,
|
||||
bool warn_lost_event)
|
||||
{
|
||||
struct hists *hists = evsel__hists(evsel);
|
||||
struct hist_browser *browser = perf_evsel_browser__new(evsel, hbt, env);
|
||||
@@ -2844,7 +2847,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
|
||||
|
||||
nr_options = 0;
|
||||
|
||||
key = hist_browser__run(browser, helpline);
|
||||
key = hist_browser__run(browser, helpline,
|
||||
warn_lost_event);
|
||||
|
||||
if (browser->he_selection != NULL) {
|
||||
thread = hist_browser__selected_thread(browser);
|
||||
@@ -3184,7 +3188,8 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
|
||||
|
||||
static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
|
||||
int nr_events, const char *help,
|
||||
struct hist_browser_timer *hbt)
|
||||
struct hist_browser_timer *hbt,
|
||||
bool warn_lost_event)
|
||||
{
|
||||
struct perf_evlist *evlist = menu->b.priv;
|
||||
struct perf_evsel *pos;
|
||||
@@ -3203,7 +3208,9 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
|
||||
case K_TIMER:
|
||||
hbt->timer(hbt->arg);
|
||||
|
||||
if (!menu->lost_events_warned && menu->lost_events) {
|
||||
if (!menu->lost_events_warned &&
|
||||
menu->lost_events &&
|
||||
warn_lost_event) {
|
||||
ui_browser__warn_lost_events(&menu->b);
|
||||
menu->lost_events_warned = true;
|
||||
}
|
||||
@@ -3224,7 +3231,8 @@ browse_hists:
|
||||
key = perf_evsel__hists_browse(pos, nr_events, help,
|
||||
true, hbt,
|
||||
menu->min_pcnt,
|
||||
menu->env);
|
||||
menu->env,
|
||||
warn_lost_event);
|
||||
ui_browser__show_title(&menu->b, title);
|
||||
switch (key) {
|
||||
case K_TAB:
|
||||
@@ -3282,7 +3290,8 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
|
||||
int nr_entries, const char *help,
|
||||
struct hist_browser_timer *hbt,
|
||||
float min_pcnt,
|
||||
struct perf_env *env)
|
||||
struct perf_env *env,
|
||||
bool warn_lost_event)
|
||||
{
|
||||
struct perf_evsel *pos;
|
||||
struct perf_evsel_menu menu = {
|
||||
@@ -3309,13 +3318,15 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
|
||||
menu.b.width = line_len;
|
||||
}
|
||||
|
||||
return perf_evsel_menu__run(&menu, nr_entries, help, hbt);
|
||||
return perf_evsel_menu__run(&menu, nr_entries, help,
|
||||
hbt, warn_lost_event);
|
||||
}
|
||||
|
||||
int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
|
||||
struct hist_browser_timer *hbt,
|
||||
float min_pcnt,
|
||||
struct perf_env *env)
|
||||
struct perf_env *env,
|
||||
bool warn_lost_event)
|
||||
{
|
||||
int nr_entries = evlist->nr_entries;
|
||||
|
||||
@@ -3325,7 +3336,7 @@ single_entry:
|
||||
|
||||
return perf_evsel__hists_browse(first, nr_entries, help,
|
||||
false, hbt, min_pcnt,
|
||||
env);
|
||||
env, warn_lost_event);
|
||||
}
|
||||
|
||||
if (symbol_conf.event_group) {
|
||||
@@ -3342,5 +3353,6 @@ single_entry:
|
||||
}
|
||||
|
||||
return __perf_evlist__tui_browse_hists(evlist, nr_entries, help,
|
||||
hbt, min_pcnt, env);
|
||||
hbt, min_pcnt, env,
|
||||
warn_lost_event);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@ struct hist_browser {
|
||||
|
||||
struct hist_browser *hist_browser__new(struct hists *hists);
|
||||
void hist_browser__delete(struct hist_browser *browser);
|
||||
int hist_browser__run(struct hist_browser *browser, const char *help);
|
||||
int hist_browser__run(struct hist_browser *browser, const char *help,
|
||||
bool warn_lost_event);
|
||||
void hist_browser__init(struct hist_browser *browser,
|
||||
struct hists *hists);
|
||||
#endif /* _PERF_UI_BROWSER_HISTS_H_ */
|
||||
|
||||
@@ -715,28 +715,11 @@ union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, int
|
||||
return perf_mmap__read_forward(md);
|
||||
}
|
||||
|
||||
union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx)
|
||||
{
|
||||
struct perf_mmap *md = &evlist->mmap[idx];
|
||||
|
||||
/*
|
||||
* No need to check messup for backward ring buffer:
|
||||
* We can always read arbitrary long data from a backward
|
||||
* ring buffer unless we forget to pause it before reading.
|
||||
*/
|
||||
return perf_mmap__read_backward(md);
|
||||
}
|
||||
|
||||
union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
|
||||
{
|
||||
return perf_evlist__mmap_read_forward(evlist, idx);
|
||||
}
|
||||
|
||||
void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
|
||||
{
|
||||
perf_mmap__read_catchup(&evlist->mmap[idx]);
|
||||
}
|
||||
|
||||
void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
|
||||
{
|
||||
perf_mmap__consume(&evlist->mmap[idx], false);
|
||||
|
||||
@@ -133,10 +133,6 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
|
||||
|
||||
union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist,
|
||||
int idx);
|
||||
union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist,
|
||||
int idx);
|
||||
void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);
|
||||
|
||||
void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
|
||||
|
||||
int perf_evlist__open(struct perf_evlist *evlist);
|
||||
|
||||
@@ -41,17 +41,7 @@
|
||||
|
||||
#include "sane_ctype.h"
|
||||
|
||||
static struct {
|
||||
bool sample_id_all;
|
||||
bool exclude_guest;
|
||||
bool mmap2;
|
||||
bool cloexec;
|
||||
bool clockid;
|
||||
bool clockid_wrong;
|
||||
bool lbr_flags;
|
||||
bool write_backward;
|
||||
bool group_read;
|
||||
} perf_missing_features;
|
||||
struct perf_missing_features perf_missing_features;
|
||||
|
||||
static clockid_t clockid;
|
||||
|
||||
|
||||
@@ -149,6 +149,20 @@ union u64_swap {
|
||||
u32 val32[2];
|
||||
};
|
||||
|
||||
struct perf_missing_features {
|
||||
bool sample_id_all;
|
||||
bool exclude_guest;
|
||||
bool mmap2;
|
||||
bool cloexec;
|
||||
bool clockid;
|
||||
bool clockid_wrong;
|
||||
bool lbr_flags;
|
||||
bool write_backward;
|
||||
bool group_read;
|
||||
};
|
||||
|
||||
extern struct perf_missing_features perf_missing_features;
|
||||
|
||||
struct cpu_map;
|
||||
struct target;
|
||||
struct thread_map;
|
||||
|
||||
@@ -430,7 +430,8 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
|
||||
int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
|
||||
struct hist_browser_timer *hbt,
|
||||
float min_pcnt,
|
||||
struct perf_env *env);
|
||||
struct perf_env *env,
|
||||
bool warn_lost_event);
|
||||
int script_browse(const char *script_opt);
|
||||
#else
|
||||
static inline
|
||||
@@ -438,7 +439,8 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
|
||||
const char *help __maybe_unused,
|
||||
struct hist_browser_timer *hbt __maybe_unused,
|
||||
float min_pcnt __maybe_unused,
|
||||
struct perf_env *env __maybe_unused)
|
||||
struct perf_env *env __maybe_unused,
|
||||
bool warn_lost_event __maybe_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -22,29 +22,27 @@ size_t perf_mmap__mmap_len(struct perf_mmap *map)
|
||||
|
||||
/* When check_messup is true, 'end' must points to a good entry */
|
||||
static union perf_event *perf_mmap__read(struct perf_mmap *map,
|
||||
u64 start, u64 end, u64 *prev)
|
||||
u64 *startp, u64 end)
|
||||
{
|
||||
unsigned char *data = map->base + page_size;
|
||||
union perf_event *event = NULL;
|
||||
int diff = end - start;
|
||||
int diff = end - *startp;
|
||||
|
||||
if (diff >= (int)sizeof(event->header)) {
|
||||
size_t size;
|
||||
|
||||
event = (union perf_event *)&data[start & map->mask];
|
||||
event = (union perf_event *)&data[*startp & map->mask];
|
||||
size = event->header.size;
|
||||
|
||||
if (size < sizeof(event->header) || diff < (int)size) {
|
||||
event = NULL;
|
||||
goto broken_event;
|
||||
}
|
||||
if (size < sizeof(event->header) || diff < (int)size)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Event straddles the mmap boundary -- header should always
|
||||
* be inside due to u64 alignment of output.
|
||||
*/
|
||||
if ((start & map->mask) + size != ((start + size) & map->mask)) {
|
||||
unsigned int offset = start;
|
||||
if ((*startp & map->mask) + size != ((*startp + size) & map->mask)) {
|
||||
unsigned int offset = *startp;
|
||||
unsigned int len = min(sizeof(*event), size), cpy;
|
||||
void *dst = map->event_copy;
|
||||
|
||||
@@ -59,20 +57,19 @@ static union perf_event *perf_mmap__read(struct perf_mmap *map,
|
||||
event = (union perf_event *)map->event_copy;
|
||||
}
|
||||
|
||||
start += size;
|
||||
*startp += size;
|
||||
}
|
||||
|
||||
broken_event:
|
||||
if (prev)
|
||||
*prev = start;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/*
|
||||
* legacy interface for mmap read.
|
||||
* Don't use it. Use perf_mmap__read_event().
|
||||
*/
|
||||
union perf_event *perf_mmap__read_forward(struct perf_mmap *map)
|
||||
{
|
||||
u64 head;
|
||||
u64 old = map->prev;
|
||||
|
||||
/*
|
||||
* Check if event was unmapped due to a POLLHUP/POLLERR.
|
||||
@@ -82,13 +79,26 @@ union perf_event *perf_mmap__read_forward(struct perf_mmap *map)
|
||||
|
||||
head = perf_mmap__read_head(map);
|
||||
|
||||
return perf_mmap__read(map, old, head, &map->prev);
|
||||
return perf_mmap__read(map, &map->prev, head);
|
||||
}
|
||||
|
||||
union perf_event *perf_mmap__read_backward(struct perf_mmap *map)
|
||||
/*
|
||||
* Read event from ring buffer one by one.
|
||||
* Return one event for each call.
|
||||
*
|
||||
* Usage:
|
||||
* perf_mmap__read_init()
|
||||
* while(event = perf_mmap__read_event()) {
|
||||
* //process the event
|
||||
* perf_mmap__consume()
|
||||
* }
|
||||
* perf_mmap__read_done()
|
||||
*/
|
||||
union perf_event *perf_mmap__read_event(struct perf_mmap *map,
|
||||
bool overwrite,
|
||||
u64 *startp, u64 end)
|
||||
{
|
||||
u64 head, end;
|
||||
u64 start = map->prev;
|
||||
union perf_event *event;
|
||||
|
||||
/*
|
||||
* Check if event was unmapped due to a POLLHUP/POLLERR.
|
||||
@@ -96,40 +106,19 @@ union perf_event *perf_mmap__read_backward(struct perf_mmap *map)
|
||||
if (!refcount_read(&map->refcnt))
|
||||
return NULL;
|
||||
|
||||
head = perf_mmap__read_head(map);
|
||||
if (!head)
|
||||
if (startp == NULL)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* 'head' pointer starts from 0. Kernel minus sizeof(record) form
|
||||
* it each time when kernel writes to it, so in fact 'head' is
|
||||
* negative. 'end' pointer is made manually by adding the size of
|
||||
* the ring buffer to 'head' pointer, means the validate data can
|
||||
* read is the whole ring buffer. If 'end' is positive, the ring
|
||||
* buffer has not fully filled, so we must adjust 'end' to 0.
|
||||
*
|
||||
* However, since both 'head' and 'end' is unsigned, we can't
|
||||
* simply compare 'end' against 0. Here we compare '-head' and
|
||||
* the size of the ring buffer, where -head is the number of bytes
|
||||
* kernel write to the ring buffer.
|
||||
*/
|
||||
if (-head < (u64)(map->mask + 1))
|
||||
end = 0;
|
||||
else
|
||||
end = head + map->mask + 1;
|
||||
/* non-overwirte doesn't pause the ringbuffer */
|
||||
if (!overwrite)
|
||||
end = perf_mmap__read_head(map);
|
||||
|
||||
return perf_mmap__read(map, start, end, &map->prev);
|
||||
}
|
||||
event = perf_mmap__read(map, startp, end);
|
||||
|
||||
void perf_mmap__read_catchup(struct perf_mmap *map)
|
||||
{
|
||||
u64 head;
|
||||
if (!overwrite)
|
||||
map->prev = *startp;
|
||||
|
||||
if (!refcount_read(&map->refcnt))
|
||||
return;
|
||||
|
||||
head = perf_mmap__read_head(map);
|
||||
map->prev = head;
|
||||
return event;
|
||||
}
|
||||
|
||||
static bool perf_mmap__empty(struct perf_mmap *map)
|
||||
@@ -267,41 +256,60 @@ static int overwrite_rb_find_range(void *buf, int mask, u64 head, u64 *start, u6
|
||||
return -1;
|
||||
}
|
||||
|
||||
int perf_mmap__push(struct perf_mmap *md, bool overwrite,
|
||||
void *to, int push(void *to, void *buf, size_t size))
|
||||
/*
|
||||
* Report the start and end of the available data in ringbuffer
|
||||
*/
|
||||
int perf_mmap__read_init(struct perf_mmap *md, bool overwrite,
|
||||
u64 *startp, u64 *endp)
|
||||
{
|
||||
u64 head = perf_mmap__read_head(md);
|
||||
u64 old = md->prev;
|
||||
u64 end = head, start = old;
|
||||
unsigned char *data = md->base + page_size;
|
||||
unsigned long size;
|
||||
void *buf;
|
||||
int rc = 0;
|
||||
|
||||
start = overwrite ? head : old;
|
||||
end = overwrite ? old : head;
|
||||
*startp = overwrite ? head : old;
|
||||
*endp = overwrite ? old : head;
|
||||
|
||||
if (start == end)
|
||||
return 0;
|
||||
if (*startp == *endp)
|
||||
return -EAGAIN;
|
||||
|
||||
size = end - start;
|
||||
size = *endp - *startp;
|
||||
if (size > (unsigned long)(md->mask) + 1) {
|
||||
if (!overwrite) {
|
||||
WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
|
||||
|
||||
md->prev = head;
|
||||
perf_mmap__consume(md, overwrite);
|
||||
return 0;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Backward ring buffer is full. We still have a chance to read
|
||||
* most of data from it.
|
||||
*/
|
||||
if (overwrite_rb_find_range(data, md->mask, head, &start, &end))
|
||||
return -1;
|
||||
if (overwrite_rb_find_range(data, md->mask, head, startp, endp))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int perf_mmap__push(struct perf_mmap *md, bool overwrite,
|
||||
void *to, int push(void *to, void *buf, size_t size))
|
||||
{
|
||||
u64 head = perf_mmap__read_head(md);
|
||||
u64 end, start;
|
||||
unsigned char *data = md->base + page_size;
|
||||
unsigned long size;
|
||||
void *buf;
|
||||
int rc = 0;
|
||||
|
||||
rc = perf_mmap__read_init(md, overwrite, &start, &end);
|
||||
if (rc < 0)
|
||||
return (rc == -EAGAIN) ? 0 : -1;
|
||||
|
||||
size = end - start;
|
||||
|
||||
if ((start & md->mask) + size != (end & md->mask)) {
|
||||
buf = &data[start & md->mask];
|
||||
size = md->mask + 1 - (start & md->mask);
|
||||
@@ -327,3 +335,14 @@ int perf_mmap__push(struct perf_mmap *md, bool overwrite,
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mandatory for overwrite mode
|
||||
* The direction of overwrite mode is backward.
|
||||
* The last perf_mmap__read() will set tail to map->prev.
|
||||
* Need to correct the map->prev to head which is the end of next read.
|
||||
*/
|
||||
void perf_mmap__read_done(struct perf_mmap *map)
|
||||
{
|
||||
map->prev = perf_mmap__read_head(map);
|
||||
}
|
||||
|
||||
@@ -65,8 +65,6 @@ void perf_mmap__put(struct perf_mmap *map);
|
||||
|
||||
void perf_mmap__consume(struct perf_mmap *map, bool overwrite);
|
||||
|
||||
void perf_mmap__read_catchup(struct perf_mmap *md);
|
||||
|
||||
static inline u64 perf_mmap__read_head(struct perf_mmap *mm)
|
||||
{
|
||||
struct perf_event_mmap_page *pc = mm->base;
|
||||
@@ -87,11 +85,17 @@ static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail)
|
||||
}
|
||||
|
||||
union perf_event *perf_mmap__read_forward(struct perf_mmap *map);
|
||||
union perf_event *perf_mmap__read_backward(struct perf_mmap *map);
|
||||
|
||||
union perf_event *perf_mmap__read_event(struct perf_mmap *map,
|
||||
bool overwrite,
|
||||
u64 *startp, u64 end);
|
||||
|
||||
int perf_mmap__push(struct perf_mmap *md, bool backward,
|
||||
void *to, int push(void *to, void *buf, size_t size));
|
||||
|
||||
size_t perf_mmap__mmap_len(struct perf_mmap *map);
|
||||
|
||||
int perf_mmap__read_init(struct perf_mmap *md, bool overwrite,
|
||||
u64 *startp, u64 *endp);
|
||||
void perf_mmap__read_done(struct perf_mmap *map);
|
||||
#endif /*__PERF_MMAP_H */
|
||||
|
||||
@@ -340,35 +340,15 @@ size_t hex_width(u64 v)
|
||||
return n;
|
||||
}
|
||||
|
||||
static int hex(char ch)
|
||||
{
|
||||
if ((ch >= '0') && (ch <= '9'))
|
||||
return ch - '0';
|
||||
if ((ch >= 'a') && (ch <= 'f'))
|
||||
return ch - 'a' + 10;
|
||||
if ((ch >= 'A') && (ch <= 'F'))
|
||||
return ch - 'A' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* While we find nice hex chars, build a long_val.
|
||||
* Return number of chars processed.
|
||||
*/
|
||||
int hex2u64(const char *ptr, u64 *long_val)
|
||||
{
|
||||
const char *p = ptr;
|
||||
*long_val = 0;
|
||||
char *p;
|
||||
|
||||
while (*p) {
|
||||
const int hex_val = hex(*p);
|
||||
|
||||
if (hex_val < 0)
|
||||
break;
|
||||
|
||||
*long_val = (*long_val << 4) | hex_val;
|
||||
p++;
|
||||
}
|
||||
*long_val = strtoull(ptr, &p, 16);
|
||||
|
||||
return p - ptr;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2017, Intel Corp.
|
||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2017, Intel Corp.
|
||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2017, Intel Corp.
|
||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2017, Intel Corp.
|
||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2017, Intel Corp.
|
||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2017, Intel Corp.
|
||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2017, Intel Corp.
|
||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2017, Intel Corp.
|
||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2017, Intel Corp.
|
||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2017, Intel Corp.
|
||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -99,5 +99,6 @@ ifneq ($(silent),1)
|
||||
|
||||
QUIET_CLEAN = @printf ' CLEAN %s\n' $1;
|
||||
QUIET_INSTALL = @printf ' INSTALL %s\n' $1;
|
||||
QUIET_UNINST = @printf ' UNINST %s\n' $1;
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -37,10 +37,12 @@ obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
|
||||
|
||||
nfit-y := $(ACPI_SRC)/core.o
|
||||
nfit-$(CONFIG_X86_MCE) += $(ACPI_SRC)/mce.o
|
||||
nfit-y += acpi_nfit_test.o
|
||||
nfit-y += config_check.o
|
||||
|
||||
nd_pmem-y := $(NVDIMM_SRC)/pmem.o
|
||||
nd_pmem-y += pmem-dax.o
|
||||
nd_pmem-y += pmem_test.o
|
||||
nd_pmem-y += config_check.o
|
||||
|
||||
nd_btt-y := $(NVDIMM_SRC)/btt.o
|
||||
@@ -57,6 +59,7 @@ dax-y += config_check.o
|
||||
|
||||
device_dax-y := $(DAX_SRC)/device.o
|
||||
device_dax-y += dax-dev.o
|
||||
device_dax-y += device_dax_test.o
|
||||
device_dax-y += config_check.o
|
||||
|
||||
dax_pmem-y := $(DAX_SRC)/pmem.o
|
||||
@@ -75,6 +78,7 @@ libnvdimm-$(CONFIG_ND_CLAIM) += $(NVDIMM_SRC)/claim.o
|
||||
libnvdimm-$(CONFIG_BTT) += $(NVDIMM_SRC)/btt_devs.o
|
||||
libnvdimm-$(CONFIG_NVDIMM_PFN) += $(NVDIMM_SRC)/pfn_devs.o
|
||||
libnvdimm-$(CONFIG_NVDIMM_DAX) += $(NVDIMM_SRC)/dax_devs.o
|
||||
libnvdimm-y += libnvdimm_test.o
|
||||
libnvdimm-y += config_check.o
|
||||
|
||||
obj-m += test/
|
||||
|
||||
8
tools/testing/nvdimm/acpi_nfit_test.c
Normal file
8
tools/testing/nvdimm/acpi_nfit_test.c
Normal file
@@ -0,0 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright(c) 2018 Intel Corporation. All rights reserved.
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/printk.h>
|
||||
#include "watermark.h"
|
||||
|
||||
nfit_test_watermark(acpi_nfit);
|
||||
8
tools/testing/nvdimm/device_dax_test.c
Normal file
8
tools/testing/nvdimm/device_dax_test.c
Normal file
@@ -0,0 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright(c) 2018 Intel Corporation. All rights reserved.
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/printk.h>
|
||||
#include "watermark.h"
|
||||
|
||||
nfit_test_watermark(device_dax);
|
||||
8
tools/testing/nvdimm/libnvdimm_test.c
Normal file
8
tools/testing/nvdimm/libnvdimm_test.c
Normal file
@@ -0,0 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright(c) 2018 Intel Corporation. All rights reserved.
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/printk.h>
|
||||
#include "watermark.h"
|
||||
|
||||
nfit_test_watermark(libnvdimm);
|
||||
8
tools/testing/nvdimm/pmem_test.c
Normal file
8
tools/testing/nvdimm/pmem_test.c
Normal file
@@ -0,0 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright(c) 2018 Intel Corporation. All rights reserved.
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/printk.h>
|
||||
#include "watermark.h"
|
||||
|
||||
nfit_test_watermark(pmem);
|
||||
@@ -104,15 +104,14 @@ void *__wrap_devm_memremap(struct device *dev, resource_size_t offset,
|
||||
}
|
||||
EXPORT_SYMBOL(__wrap_devm_memremap);
|
||||
|
||||
void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res,
|
||||
struct percpu_ref *ref, struct vmem_altmap *altmap)
|
||||
void *__wrap_devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
|
||||
{
|
||||
resource_size_t offset = res->start;
|
||||
resource_size_t offset = pgmap->res.start;
|
||||
struct nfit_test_resource *nfit_res = get_nfit_res(offset);
|
||||
|
||||
if (nfit_res)
|
||||
return nfit_res->buf + offset - nfit_res->res.start;
|
||||
return devm_memremap_pages(dev, res, ref, altmap);
|
||||
return devm_memremap_pages(dev, pgmap);
|
||||
}
|
||||
EXPORT_SYMBOL(__wrap_devm_memremap_pages);
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <nfit.h>
|
||||
#include <nd.h>
|
||||
#include "nfit_test.h"
|
||||
#include "../watermark.h"
|
||||
|
||||
/*
|
||||
* Generate an NFIT table to describe the following topology:
|
||||
@@ -137,6 +138,14 @@ static u32 handle[] = {
|
||||
|
||||
static unsigned long dimm_fail_cmd_flags[NUM_DCR];
|
||||
|
||||
struct nfit_test_fw {
|
||||
enum intel_fw_update_state state;
|
||||
u32 context;
|
||||
u64 version;
|
||||
u32 size_received;
|
||||
u64 end_time;
|
||||
};
|
||||
|
||||
struct nfit_test {
|
||||
struct acpi_nfit_desc acpi_desc;
|
||||
struct platform_device pdev;
|
||||
@@ -168,8 +177,11 @@ struct nfit_test {
|
||||
spinlock_t lock;
|
||||
} ars_state;
|
||||
struct device *dimm_dev[NUM_DCR];
|
||||
struct nd_intel_smart *smart;
|
||||
struct nd_intel_smart_threshold *smart_threshold;
|
||||
struct badrange badrange;
|
||||
struct work_struct work;
|
||||
struct nfit_test_fw *fw;
|
||||
};
|
||||
|
||||
static struct workqueue_struct *nfit_wq;
|
||||
@@ -181,6 +193,226 @@ static struct nfit_test *to_nfit_test(struct device *dev)
|
||||
return container_of(pdev, struct nfit_test, pdev);
|
||||
}
|
||||
|
||||
static int nd_intel_test_get_fw_info(struct nfit_test *t,
|
||||
struct nd_intel_fw_info *nd_cmd, unsigned int buf_len,
|
||||
int idx)
|
||||
{
|
||||
struct device *dev = &t->pdev.dev;
|
||||
struct nfit_test_fw *fw = &t->fw[idx];
|
||||
|
||||
dev_dbg(dev, "%s(nfit_test: %p nd_cmd: %p, buf_len: %u, idx: %d\n",
|
||||
__func__, t, nd_cmd, buf_len, idx);
|
||||
|
||||
if (buf_len < sizeof(*nd_cmd))
|
||||
return -EINVAL;
|
||||
|
||||
nd_cmd->status = 0;
|
||||
nd_cmd->storage_size = INTEL_FW_STORAGE_SIZE;
|
||||
nd_cmd->max_send_len = INTEL_FW_MAX_SEND_LEN;
|
||||
nd_cmd->query_interval = INTEL_FW_QUERY_INTERVAL;
|
||||
nd_cmd->max_query_time = INTEL_FW_QUERY_MAX_TIME;
|
||||
nd_cmd->update_cap = 0;
|
||||
nd_cmd->fis_version = INTEL_FW_FIS_VERSION;
|
||||
nd_cmd->run_version = 0;
|
||||
nd_cmd->updated_version = fw->version;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nd_intel_test_start_update(struct nfit_test *t,
|
||||
struct nd_intel_fw_start *nd_cmd, unsigned int buf_len,
|
||||
int idx)
|
||||
{
|
||||
struct device *dev = &t->pdev.dev;
|
||||
struct nfit_test_fw *fw = &t->fw[idx];
|
||||
|
||||
dev_dbg(dev, "%s(nfit_test: %p nd_cmd: %p buf_len: %u idx: %d)\n",
|
||||
__func__, t, nd_cmd, buf_len, idx);
|
||||
|
||||
if (buf_len < sizeof(*nd_cmd))
|
||||
return -EINVAL;
|
||||
|
||||
if (fw->state != FW_STATE_NEW) {
|
||||
/* extended status, FW update in progress */
|
||||
nd_cmd->status = 0x10007;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fw->state = FW_STATE_IN_PROGRESS;
|
||||
fw->context++;
|
||||
fw->size_received = 0;
|
||||
nd_cmd->status = 0;
|
||||
nd_cmd->context = fw->context;
|
||||
|
||||
dev_dbg(dev, "%s: context issued: %#x\n", __func__, nd_cmd->context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nd_intel_test_send_data(struct nfit_test *t,
|
||||
struct nd_intel_fw_send_data *nd_cmd, unsigned int buf_len,
|
||||
int idx)
|
||||
{
|
||||
struct device *dev = &t->pdev.dev;
|
||||
struct nfit_test_fw *fw = &t->fw[idx];
|
||||
u32 *status = (u32 *)&nd_cmd->data[nd_cmd->length];
|
||||
|
||||
dev_dbg(dev, "%s(nfit_test: %p nd_cmd: %p buf_len: %u idx: %d)\n",
|
||||
__func__, t, nd_cmd, buf_len, idx);
|
||||
|
||||
if (buf_len < sizeof(*nd_cmd))
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
dev_dbg(dev, "%s: cmd->status: %#x\n", __func__, *status);
|
||||
dev_dbg(dev, "%s: cmd->data[0]: %#x\n", __func__, nd_cmd->data[0]);
|
||||
dev_dbg(dev, "%s: cmd->data[%u]: %#x\n", __func__, nd_cmd->length-1,
|
||||
nd_cmd->data[nd_cmd->length-1]);
|
||||
|
||||
if (fw->state != FW_STATE_IN_PROGRESS) {
|
||||
dev_dbg(dev, "%s: not in IN_PROGRESS state\n", __func__);
|
||||
*status = 0x5;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nd_cmd->context != fw->context) {
|
||||
dev_dbg(dev, "%s: incorrect context: in: %#x correct: %#x\n",
|
||||
__func__, nd_cmd->context, fw->context);
|
||||
*status = 0x10007;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* check offset + len > size of fw storage
|
||||
* check length is > max send length
|
||||
*/
|
||||
if (nd_cmd->offset + nd_cmd->length > INTEL_FW_STORAGE_SIZE ||
|
||||
nd_cmd->length > INTEL_FW_MAX_SEND_LEN) {
|
||||
*status = 0x3;
|
||||
dev_dbg(dev, "%s: buffer boundary violation\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fw->size_received += nd_cmd->length;
|
||||
dev_dbg(dev, "%s: copying %u bytes, %u bytes so far\n",
|
||||
__func__, nd_cmd->length, fw->size_received);
|
||||
*status = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nd_intel_test_finish_fw(struct nfit_test *t,
|
||||
struct nd_intel_fw_finish_update *nd_cmd,
|
||||
unsigned int buf_len, int idx)
|
||||
{
|
||||
struct device *dev = &t->pdev.dev;
|
||||
struct nfit_test_fw *fw = &t->fw[idx];
|
||||
|
||||
dev_dbg(dev, "%s(nfit_test: %p nd_cmd: %p buf_len: %u idx: %d)\n",
|
||||
__func__, t, nd_cmd, buf_len, idx);
|
||||
|
||||
if (fw->state == FW_STATE_UPDATED) {
|
||||
/* update already done, need cold boot */
|
||||
nd_cmd->status = 0x20007;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%s: context: %#x ctrl_flags: %#x\n",
|
||||
__func__, nd_cmd->context, nd_cmd->ctrl_flags);
|
||||
|
||||
switch (nd_cmd->ctrl_flags) {
|
||||
case 0: /* finish */
|
||||
if (nd_cmd->context != fw->context) {
|
||||
dev_dbg(dev, "%s: incorrect context: in: %#x correct: %#x\n",
|
||||
__func__, nd_cmd->context,
|
||||
fw->context);
|
||||
nd_cmd->status = 0x10007;
|
||||
return 0;
|
||||
}
|
||||
nd_cmd->status = 0;
|
||||
fw->state = FW_STATE_VERIFY;
|
||||
/* set 1 second of time for firmware "update" */
|
||||
fw->end_time = jiffies + HZ;
|
||||
break;
|
||||
|
||||
case 1: /* abort */
|
||||
fw->size_received = 0;
|
||||
/* successfully aborted status */
|
||||
nd_cmd->status = 0x40007;
|
||||
fw->state = FW_STATE_NEW;
|
||||
dev_dbg(dev, "%s: abort successful\n", __func__);
|
||||
break;
|
||||
|
||||
default: /* bad control flag */
|
||||
dev_warn(dev, "%s: unknown control flag: %#x\n",
|
||||
__func__, nd_cmd->ctrl_flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nd_intel_test_finish_query(struct nfit_test *t,
|
||||
struct nd_intel_fw_finish_query *nd_cmd,
|
||||
unsigned int buf_len, int idx)
|
||||
{
|
||||
struct device *dev = &t->pdev.dev;
|
||||
struct nfit_test_fw *fw = &t->fw[idx];
|
||||
|
||||
dev_dbg(dev, "%s(nfit_test: %p nd_cmd: %p buf_len: %u idx: %d)\n",
|
||||
__func__, t, nd_cmd, buf_len, idx);
|
||||
|
||||
if (buf_len < sizeof(*nd_cmd))
|
||||
return -EINVAL;
|
||||
|
||||
if (nd_cmd->context != fw->context) {
|
||||
dev_dbg(dev, "%s: incorrect context: in: %#x correct: %#x\n",
|
||||
__func__, nd_cmd->context, fw->context);
|
||||
nd_cmd->status = 0x10007;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%s context: %#x\n", __func__, nd_cmd->context);
|
||||
|
||||
switch (fw->state) {
|
||||
case FW_STATE_NEW:
|
||||
nd_cmd->updated_fw_rev = 0;
|
||||
nd_cmd->status = 0;
|
||||
dev_dbg(dev, "%s: new state\n", __func__);
|
||||
break;
|
||||
|
||||
case FW_STATE_IN_PROGRESS:
|
||||
/* sequencing error */
|
||||
nd_cmd->status = 0x40007;
|
||||
nd_cmd->updated_fw_rev = 0;
|
||||
dev_dbg(dev, "%s: sequence error\n", __func__);
|
||||
break;
|
||||
|
||||
case FW_STATE_VERIFY:
|
||||
if (time_is_after_jiffies64(fw->end_time)) {
|
||||
nd_cmd->updated_fw_rev = 0;
|
||||
nd_cmd->status = 0x20007;
|
||||
dev_dbg(dev, "%s: still verifying\n", __func__);
|
||||
break;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%s: transition out verify\n", __func__);
|
||||
fw->state = FW_STATE_UPDATED;
|
||||
/* we are going to fall through if it's "done" */
|
||||
case FW_STATE_UPDATED:
|
||||
nd_cmd->status = 0;
|
||||
/* bogus test version */
|
||||
fw->version = nd_cmd->updated_fw_rev =
|
||||
INTEL_FW_FAKE_VERSION;
|
||||
dev_dbg(dev, "%s: updated\n", __func__);
|
||||
break;
|
||||
|
||||
default: /* we should never get here */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nfit_test_cmd_get_config_size(struct nd_cmd_get_config_size *nd_cmd,
|
||||
unsigned int buf_len)
|
||||
{
|
||||
@@ -440,39 +672,66 @@ static int nfit_test_cmd_translate_spa(struct nvdimm_bus *bus,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nfit_test_cmd_smart(struct nd_cmd_smart *smart, unsigned int buf_len)
|
||||
static int nfit_test_cmd_smart(struct nd_intel_smart *smart, unsigned int buf_len,
|
||||
struct nd_intel_smart *smart_data)
|
||||
{
|
||||
static const struct nd_smart_payload smart_data = {
|
||||
.flags = ND_SMART_HEALTH_VALID | ND_SMART_TEMP_VALID
|
||||
| ND_SMART_SPARES_VALID | ND_SMART_ALARM_VALID
|
||||
| ND_SMART_USED_VALID | ND_SMART_SHUTDOWN_VALID,
|
||||
.health = ND_SMART_NON_CRITICAL_HEALTH,
|
||||
.temperature = 23 * 16,
|
||||
.spares = 75,
|
||||
.alarm_flags = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP,
|
||||
.life_used = 5,
|
||||
.shutdown_state = 0,
|
||||
.vendor_size = 0,
|
||||
};
|
||||
|
||||
if (buf_len < sizeof(*smart))
|
||||
return -EINVAL;
|
||||
memcpy(smart->data, &smart_data, sizeof(smart_data));
|
||||
memcpy(smart, smart_data, sizeof(*smart));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nfit_test_cmd_smart_threshold(struct nd_cmd_smart_threshold *smart_t,
|
||||
unsigned int buf_len)
|
||||
static int nfit_test_cmd_smart_threshold(
|
||||
struct nd_intel_smart_threshold *out,
|
||||
unsigned int buf_len,
|
||||
struct nd_intel_smart_threshold *smart_t)
|
||||
{
|
||||
static const struct nd_smart_threshold_payload smart_t_data = {
|
||||
.alarm_control = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP,
|
||||
.temperature = 40 * 16,
|
||||
.spares = 5,
|
||||
};
|
||||
|
||||
if (buf_len < sizeof(*smart_t))
|
||||
return -EINVAL;
|
||||
memcpy(smart_t->data, &smart_t_data, sizeof(smart_t_data));
|
||||
memcpy(out, smart_t, sizeof(*smart_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void smart_notify(struct device *bus_dev,
|
||||
struct device *dimm_dev, struct nd_intel_smart *smart,
|
||||
struct nd_intel_smart_threshold *thresh)
|
||||
{
|
||||
dev_dbg(dimm_dev, "%s: alarm: %#x spares: %d (%d) mtemp: %d (%d) ctemp: %d (%d)\n",
|
||||
__func__, thresh->alarm_control, thresh->spares,
|
||||
smart->spares, thresh->media_temperature,
|
||||
smart->media_temperature, thresh->ctrl_temperature,
|
||||
smart->ctrl_temperature);
|
||||
if (((thresh->alarm_control & ND_INTEL_SMART_SPARE_TRIP)
|
||||
&& smart->spares
|
||||
<= thresh->spares)
|
||||
|| ((thresh->alarm_control & ND_INTEL_SMART_TEMP_TRIP)
|
||||
&& smart->media_temperature
|
||||
>= thresh->media_temperature)
|
||||
|| ((thresh->alarm_control & ND_INTEL_SMART_CTEMP_TRIP)
|
||||
&& smart->ctrl_temperature
|
||||
>= thresh->ctrl_temperature)) {
|
||||
device_lock(bus_dev);
|
||||
__acpi_nvdimm_notify(dimm_dev, 0x81);
|
||||
device_unlock(bus_dev);
|
||||
}
|
||||
}
|
||||
|
||||
static int nfit_test_cmd_smart_set_threshold(
|
||||
struct nd_intel_smart_set_threshold *in,
|
||||
unsigned int buf_len,
|
||||
struct nd_intel_smart_threshold *thresh,
|
||||
struct nd_intel_smart *smart,
|
||||
struct device *bus_dev, struct device *dimm_dev)
|
||||
{
|
||||
unsigned int size;
|
||||
|
||||
size = sizeof(*in) - 4;
|
||||
if (buf_len < size)
|
||||
return -EINVAL;
|
||||
memcpy(thresh->data, in, size);
|
||||
in->status = 0;
|
||||
smart_notify(bus_dev, dimm_dev, smart, thresh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -563,6 +822,52 @@ static int nfit_test_cmd_ars_inject_status(struct nfit_test *t,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nd_intel_test_cmd_set_lss_status(struct nfit_test *t,
|
||||
struct nd_intel_lss *nd_cmd, unsigned int buf_len)
|
||||
{
|
||||
struct device *dev = &t->pdev.dev;
|
||||
|
||||
if (buf_len < sizeof(*nd_cmd))
|
||||
return -EINVAL;
|
||||
|
||||
switch (nd_cmd->enable) {
|
||||
case 0:
|
||||
nd_cmd->status = 0;
|
||||
dev_dbg(dev, "%s: Latch System Shutdown Status disabled\n",
|
||||
__func__);
|
||||
break;
|
||||
case 1:
|
||||
nd_cmd->status = 0;
|
||||
dev_dbg(dev, "%s: Latch System Shutdown Status enabled\n",
|
||||
__func__);
|
||||
break;
|
||||
default:
|
||||
dev_warn(dev, "Unknown enable value: %#x\n", nd_cmd->enable);
|
||||
nd_cmd->status = 0x3;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_dimm(struct nfit_mem *nfit_mem, unsigned int func)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* lookup per-dimm data */
|
||||
for (i = 0; i < ARRAY_SIZE(handle); i++)
|
||||
if (__to_nfit_memdev(nfit_mem)->device_handle == handle[i])
|
||||
break;
|
||||
if (i >= ARRAY_SIZE(handle))
|
||||
return -ENXIO;
|
||||
|
||||
if ((1 << func) & dimm_fail_cmd_flags[i])
|
||||
return -EIO;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
|
||||
struct nvdimm *nvdimm, unsigned int cmd, void *buf,
|
||||
unsigned int buf_len, int *cmd_rc)
|
||||
@@ -591,22 +896,57 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
|
||||
func = call_pkg->nd_command;
|
||||
if (call_pkg->nd_family != nfit_mem->family)
|
||||
return -ENOTTY;
|
||||
|
||||
i = get_dimm(nfit_mem, func);
|
||||
if (i < 0)
|
||||
return i;
|
||||
|
||||
switch (func) {
|
||||
case ND_INTEL_ENABLE_LSS_STATUS:
|
||||
return nd_intel_test_cmd_set_lss_status(t,
|
||||
buf, buf_len);
|
||||
case ND_INTEL_FW_GET_INFO:
|
||||
return nd_intel_test_get_fw_info(t, buf,
|
||||
buf_len, i - t->dcr_idx);
|
||||
case ND_INTEL_FW_START_UPDATE:
|
||||
return nd_intel_test_start_update(t, buf,
|
||||
buf_len, i - t->dcr_idx);
|
||||
case ND_INTEL_FW_SEND_DATA:
|
||||
return nd_intel_test_send_data(t, buf,
|
||||
buf_len, i - t->dcr_idx);
|
||||
case ND_INTEL_FW_FINISH_UPDATE:
|
||||
return nd_intel_test_finish_fw(t, buf,
|
||||
buf_len, i - t->dcr_idx);
|
||||
case ND_INTEL_FW_FINISH_QUERY:
|
||||
return nd_intel_test_finish_query(t, buf,
|
||||
buf_len, i - t->dcr_idx);
|
||||
case ND_INTEL_SMART:
|
||||
return nfit_test_cmd_smart(buf, buf_len,
|
||||
&t->smart[i - t->dcr_idx]);
|
||||
case ND_INTEL_SMART_THRESHOLD:
|
||||
return nfit_test_cmd_smart_threshold(buf,
|
||||
buf_len,
|
||||
&t->smart_threshold[i -
|
||||
t->dcr_idx]);
|
||||
case ND_INTEL_SMART_SET_THRESHOLD:
|
||||
return nfit_test_cmd_smart_set_threshold(buf,
|
||||
buf_len,
|
||||
&t->smart_threshold[i -
|
||||
t->dcr_idx],
|
||||
&t->smart[i - t->dcr_idx],
|
||||
&t->pdev.dev, t->dimm_dev[i]);
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
}
|
||||
|
||||
if (!test_bit(cmd, &cmd_mask)
|
||||
|| !test_bit(func, &nfit_mem->dsm_mask))
|
||||
return -ENOTTY;
|
||||
|
||||
/* lookup label space for the given dimm */
|
||||
for (i = 0; i < ARRAY_SIZE(handle); i++)
|
||||
if (__to_nfit_memdev(nfit_mem)->device_handle ==
|
||||
handle[i])
|
||||
break;
|
||||
if (i >= ARRAY_SIZE(handle))
|
||||
return -ENXIO;
|
||||
|
||||
if ((1 << func) & dimm_fail_cmd_flags[i])
|
||||
return -EIO;
|
||||
i = get_dimm(nfit_mem, func);
|
||||
if (i < 0)
|
||||
return i;
|
||||
|
||||
switch (func) {
|
||||
case ND_CMD_GET_CONFIG_SIZE:
|
||||
@@ -620,15 +960,6 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
|
||||
rc = nfit_test_cmd_set_config_data(buf, buf_len,
|
||||
t->label[i - t->dcr_idx]);
|
||||
break;
|
||||
case ND_CMD_SMART:
|
||||
rc = nfit_test_cmd_smart(buf, buf_len);
|
||||
break;
|
||||
case ND_CMD_SMART_THRESHOLD:
|
||||
rc = nfit_test_cmd_smart_threshold(buf, buf_len);
|
||||
device_lock(&t->pdev.dev);
|
||||
__acpi_nvdimm_notify(t->dimm_dev[i], 0x81);
|
||||
device_unlock(&t->pdev.dev);
|
||||
break;
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
@@ -872,6 +1203,44 @@ static const struct attribute_group *nfit_test_dimm_attribute_groups[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void smart_init(struct nfit_test *t)
|
||||
{
|
||||
int i;
|
||||
const struct nd_intel_smart_threshold smart_t_data = {
|
||||
.alarm_control = ND_INTEL_SMART_SPARE_TRIP
|
||||
| ND_INTEL_SMART_TEMP_TRIP,
|
||||
.media_temperature = 40 * 16,
|
||||
.ctrl_temperature = 30 * 16,
|
||||
.spares = 5,
|
||||
};
|
||||
const struct nd_intel_smart smart_data = {
|
||||
.flags = ND_INTEL_SMART_HEALTH_VALID
|
||||
| ND_INTEL_SMART_SPARES_VALID
|
||||
| ND_INTEL_SMART_ALARM_VALID
|
||||
| ND_INTEL_SMART_USED_VALID
|
||||
| ND_INTEL_SMART_SHUTDOWN_VALID
|
||||
| ND_INTEL_SMART_MTEMP_VALID,
|
||||
.health = ND_INTEL_SMART_NON_CRITICAL_HEALTH,
|
||||
.media_temperature = 23 * 16,
|
||||
.ctrl_temperature = 30 * 16,
|
||||
.pmic_temperature = 40 * 16,
|
||||
.spares = 75,
|
||||
.alarm_flags = ND_INTEL_SMART_SPARE_TRIP
|
||||
| ND_INTEL_SMART_TEMP_TRIP,
|
||||
.ait_status = 1,
|
||||
.life_used = 5,
|
||||
.shutdown_state = 0,
|
||||
.vendor_size = 0,
|
||||
.shutdown_count = 100,
|
||||
};
|
||||
|
||||
for (i = 0; i < t->num_dcr; i++) {
|
||||
memcpy(&t->smart[i], &smart_data, sizeof(smart_data));
|
||||
memcpy(&t->smart_threshold[i], &smart_t_data,
|
||||
sizeof(smart_t_data));
|
||||
}
|
||||
}
|
||||
|
||||
static int nfit_test0_alloc(struct nfit_test *t)
|
||||
{
|
||||
size_t nfit_size = sizeof(struct acpi_nfit_system_address) * NUM_SPA
|
||||
@@ -881,7 +1250,8 @@ static int nfit_test0_alloc(struct nfit_test *t)
|
||||
window_size) * NUM_DCR
|
||||
+ sizeof(struct acpi_nfit_data_region) * NUM_BDW
|
||||
+ (sizeof(struct acpi_nfit_flush_address)
|
||||
+ sizeof(u64) * NUM_HINTS) * NUM_DCR;
|
||||
+ sizeof(u64) * NUM_HINTS) * NUM_DCR
|
||||
+ sizeof(struct acpi_nfit_capabilities);
|
||||
int i;
|
||||
|
||||
t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma);
|
||||
@@ -939,6 +1309,7 @@ static int nfit_test0_alloc(struct nfit_test *t)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
smart_init(t);
|
||||
return ars_state_init(&t->pdev.dev, &t->ars_state);
|
||||
}
|
||||
|
||||
@@ -969,6 +1340,7 @@ static int nfit_test1_alloc(struct nfit_test *t)
|
||||
if (!t->spa_set[1])
|
||||
return -ENOMEM;
|
||||
|
||||
smart_init(t);
|
||||
return ars_state_init(&t->pdev.dev, &t->ars_state);
|
||||
}
|
||||
|
||||
@@ -993,6 +1365,7 @@ static void nfit_test0_setup(struct nfit_test *t)
|
||||
struct acpi_nfit_control_region *dcr;
|
||||
struct acpi_nfit_data_region *bdw;
|
||||
struct acpi_nfit_flush_address *flush;
|
||||
struct acpi_nfit_capabilities *pcap;
|
||||
unsigned int offset, i;
|
||||
|
||||
/*
|
||||
@@ -1500,8 +1873,16 @@ static void nfit_test0_setup(struct nfit_test *t)
|
||||
for (i = 0; i < NUM_HINTS; i++)
|
||||
flush->hint_address[i] = t->flush_dma[3] + i * sizeof(u64);
|
||||
|
||||
/* platform capabilities */
|
||||
pcap = nfit_buf + offset + flush_hint_size * 4;
|
||||
pcap->header.type = ACPI_NFIT_TYPE_CAPABILITIES;
|
||||
pcap->header.length = sizeof(*pcap);
|
||||
pcap->highest_capability = 1;
|
||||
pcap->capabilities = ACPI_NFIT_CAPABILITY_CACHE_FLUSH |
|
||||
ACPI_NFIT_CAPABILITY_MEM_FLUSH;
|
||||
|
||||
if (t->setup_hotplug) {
|
||||
offset = offset + flush_hint_size * 4;
|
||||
offset = offset + flush_hint_size * 4 + sizeof(*pcap);
|
||||
/* dcr-descriptor4: blk */
|
||||
dcr = nfit_buf + offset;
|
||||
dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
|
||||
@@ -1642,17 +2023,24 @@ static void nfit_test0_setup(struct nfit_test *t)
|
||||
set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_CMD_SMART, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_INTEL_SMART, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_INTEL_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_INTEL_SMART_SET_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
|
||||
set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
|
||||
set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
|
||||
set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
|
||||
set_bit(ND_CMD_CALL, &acpi_desc->bus_cmd_force_en);
|
||||
set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(NFIT_CMD_TRANSLATE_SPA, &acpi_desc->bus_nfit_cmd_force_en);
|
||||
set_bit(NFIT_CMD_ARS_INJECT_SET, &acpi_desc->bus_nfit_cmd_force_en);
|
||||
set_bit(NFIT_CMD_ARS_INJECT_CLEAR, &acpi_desc->bus_nfit_cmd_force_en);
|
||||
set_bit(NFIT_CMD_ARS_INJECT_GET, &acpi_desc->bus_nfit_cmd_force_en);
|
||||
set_bit(ND_INTEL_FW_GET_INFO, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_INTEL_FW_START_UPDATE, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_INTEL_FW_SEND_DATA, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_INTEL_FW_FINISH_UPDATE, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_INTEL_FW_FINISH_QUERY, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_INTEL_ENABLE_LSS_STATUS, &acpi_desc->dimm_cmd_force_en);
|
||||
}
|
||||
|
||||
static void nfit_test1_setup(struct nfit_test *t)
|
||||
@@ -1750,6 +2138,7 @@ static void nfit_test1_setup(struct nfit_test *t)
|
||||
set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
|
||||
set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
|
||||
set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
|
||||
set_bit(ND_INTEL_ENABLE_LSS_STATUS, &acpi_desc->dimm_cmd_force_en);
|
||||
}
|
||||
|
||||
static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
|
||||
@@ -2054,10 +2443,18 @@ static int nfit_test_probe(struct platform_device *pdev)
|
||||
sizeof(struct nfit_test_dcr *), GFP_KERNEL);
|
||||
nfit_test->dcr_dma = devm_kcalloc(dev, num,
|
||||
sizeof(dma_addr_t), GFP_KERNEL);
|
||||
nfit_test->smart = devm_kcalloc(dev, num,
|
||||
sizeof(struct nd_intel_smart), GFP_KERNEL);
|
||||
nfit_test->smart_threshold = devm_kcalloc(dev, num,
|
||||
sizeof(struct nd_intel_smart_threshold),
|
||||
GFP_KERNEL);
|
||||
nfit_test->fw = devm_kcalloc(dev, num,
|
||||
sizeof(struct nfit_test_fw), GFP_KERNEL);
|
||||
if (nfit_test->dimm && nfit_test->dimm_dma && nfit_test->label
|
||||
&& nfit_test->label_dma && nfit_test->dcr
|
||||
&& nfit_test->dcr_dma && nfit_test->flush
|
||||
&& nfit_test->flush_dma)
|
||||
&& nfit_test->flush_dma
|
||||
&& nfit_test->fw)
|
||||
/* pass */;
|
||||
else
|
||||
return -ENOMEM;
|
||||
@@ -2159,6 +2556,11 @@ static __init int nfit_test_init(void)
|
||||
{
|
||||
int rc, i;
|
||||
|
||||
pmem_test();
|
||||
libnvdimm_test();
|
||||
acpi_nfit_test();
|
||||
device_dax_test();
|
||||
|
||||
nfit_test_setup(nfit_test_lookup, nfit_test_evaluate_dsm);
|
||||
|
||||
nfit_wq = create_singlethread_workqueue("nfit");
|
||||
|
||||
@@ -84,6 +84,140 @@ struct nd_cmd_ars_err_inj_stat {
|
||||
} __packed record[0];
|
||||
} __packed;
|
||||
|
||||
#define ND_INTEL_SMART 1
|
||||
#define ND_INTEL_SMART_THRESHOLD 2
|
||||
#define ND_INTEL_ENABLE_LSS_STATUS 10
|
||||
#define ND_INTEL_FW_GET_INFO 12
|
||||
#define ND_INTEL_FW_START_UPDATE 13
|
||||
#define ND_INTEL_FW_SEND_DATA 14
|
||||
#define ND_INTEL_FW_FINISH_UPDATE 15
|
||||
#define ND_INTEL_FW_FINISH_QUERY 16
|
||||
#define ND_INTEL_SMART_SET_THRESHOLD 17
|
||||
|
||||
#define ND_INTEL_SMART_HEALTH_VALID (1 << 0)
|
||||
#define ND_INTEL_SMART_SPARES_VALID (1 << 1)
|
||||
#define ND_INTEL_SMART_USED_VALID (1 << 2)
|
||||
#define ND_INTEL_SMART_MTEMP_VALID (1 << 3)
|
||||
#define ND_INTEL_SMART_CTEMP_VALID (1 << 4)
|
||||
#define ND_INTEL_SMART_SHUTDOWN_COUNT_VALID (1 << 5)
|
||||
#define ND_INTEL_SMART_AIT_STATUS_VALID (1 << 6)
|
||||
#define ND_INTEL_SMART_PTEMP_VALID (1 << 7)
|
||||
#define ND_INTEL_SMART_ALARM_VALID (1 << 9)
|
||||
#define ND_INTEL_SMART_SHUTDOWN_VALID (1 << 10)
|
||||
#define ND_INTEL_SMART_VENDOR_VALID (1 << 11)
|
||||
#define ND_INTEL_SMART_SPARE_TRIP (1 << 0)
|
||||
#define ND_INTEL_SMART_TEMP_TRIP (1 << 1)
|
||||
#define ND_INTEL_SMART_CTEMP_TRIP (1 << 2)
|
||||
#define ND_INTEL_SMART_NON_CRITICAL_HEALTH (1 << 0)
|
||||
#define ND_INTEL_SMART_CRITICAL_HEALTH (1 << 1)
|
||||
#define ND_INTEL_SMART_FATAL_HEALTH (1 << 2)
|
||||
|
||||
struct nd_intel_smart {
|
||||
__u32 status;
|
||||
union {
|
||||
struct {
|
||||
__u32 flags;
|
||||
__u8 reserved0[4];
|
||||
__u8 health;
|
||||
__u8 spares;
|
||||
__u8 life_used;
|
||||
__u8 alarm_flags;
|
||||
__u16 media_temperature;
|
||||
__u16 ctrl_temperature;
|
||||
__u32 shutdown_count;
|
||||
__u8 ait_status;
|
||||
__u16 pmic_temperature;
|
||||
__u8 reserved1[8];
|
||||
__u8 shutdown_state;
|
||||
__u32 vendor_size;
|
||||
__u8 vendor_data[92];
|
||||
} __packed;
|
||||
__u8 data[128];
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct nd_intel_smart_threshold {
|
||||
__u32 status;
|
||||
union {
|
||||
struct {
|
||||
__u16 alarm_control;
|
||||
__u8 spares;
|
||||
__u16 media_temperature;
|
||||
__u16 ctrl_temperature;
|
||||
__u8 reserved[1];
|
||||
} __packed;
|
||||
__u8 data[8];
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct nd_intel_smart_set_threshold {
|
||||
__u16 alarm_control;
|
||||
__u8 spares;
|
||||
__u16 media_temperature;
|
||||
__u16 ctrl_temperature;
|
||||
__u32 status;
|
||||
} __packed;
|
||||
|
||||
#define INTEL_FW_STORAGE_SIZE 0x100000
|
||||
#define INTEL_FW_MAX_SEND_LEN 0xFFEC
|
||||
#define INTEL_FW_QUERY_INTERVAL 250000
|
||||
#define INTEL_FW_QUERY_MAX_TIME 3000000
|
||||
#define INTEL_FW_FIS_VERSION 0x0105
|
||||
#define INTEL_FW_FAKE_VERSION 0xffffffffabcd
|
||||
|
||||
enum intel_fw_update_state {
|
||||
FW_STATE_NEW = 0,
|
||||
FW_STATE_IN_PROGRESS,
|
||||
FW_STATE_VERIFY,
|
||||
FW_STATE_UPDATED,
|
||||
};
|
||||
|
||||
struct nd_intel_fw_info {
|
||||
__u32 status;
|
||||
__u32 storage_size;
|
||||
__u32 max_send_len;
|
||||
__u32 query_interval;
|
||||
__u32 max_query_time;
|
||||
__u8 update_cap;
|
||||
__u8 reserved[3];
|
||||
__u32 fis_version;
|
||||
__u64 run_version;
|
||||
__u64 updated_version;
|
||||
} __packed;
|
||||
|
||||
struct nd_intel_fw_start {
|
||||
__u32 status;
|
||||
__u32 context;
|
||||
} __packed;
|
||||
|
||||
/* this one has the output first because the variable input data size */
|
||||
struct nd_intel_fw_send_data {
|
||||
__u32 context;
|
||||
__u32 offset;
|
||||
__u32 length;
|
||||
__u8 data[0];
|
||||
/* this field is not declared due ot variable data from input */
|
||||
/* __u32 status; */
|
||||
} __packed;
|
||||
|
||||
struct nd_intel_fw_finish_update {
|
||||
__u8 ctrl_flags;
|
||||
__u8 reserved[3];
|
||||
__u32 context;
|
||||
__u32 status;
|
||||
} __packed;
|
||||
|
||||
struct nd_intel_fw_finish_query {
|
||||
__u32 context;
|
||||
__u32 status;
|
||||
__u64 updated_fw_rev;
|
||||
} __packed;
|
||||
|
||||
struct nd_intel_lss {
|
||||
__u8 enable;
|
||||
__u32 status;
|
||||
} __packed;
|
||||
|
||||
union acpi_object;
|
||||
typedef void *acpi_handle;
|
||||
|
||||
|
||||
21
tools/testing/nvdimm/watermark.h
Normal file
21
tools/testing/nvdimm/watermark.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright(c) 2018 Intel Corporation. All rights reserved.
|
||||
#ifndef _TEST_NVDIMM_WATERMARK_H_
|
||||
#define _TEST_NVDIMM_WATERMARK_H_
|
||||
int pmem_test(void);
|
||||
int libnvdimm_test(void);
|
||||
int acpi_nfit_test(void);
|
||||
int device_dax_test(void);
|
||||
|
||||
/*
|
||||
* dummy routine for nfit_test to validate it is linking to the properly
|
||||
* mocked module and not the standard one from the base tree.
|
||||
*/
|
||||
#define nfit_test_watermark(x) \
|
||||
int x##_test(void) \
|
||||
{ \
|
||||
pr_debug("%s for nfit_test\n", KBUILD_MODNAME); \
|
||||
return 0; \
|
||||
} \
|
||||
EXPORT_SYMBOL(x##_test)
|
||||
#endif /* _TEST_NVDIMM_WATERMARK_H_ */
|
||||
@@ -153,11 +153,12 @@ void idr_nowait_test(void)
|
||||
idr_destroy(&idr);
|
||||
}
|
||||
|
||||
void idr_get_next_test(void)
|
||||
void idr_get_next_test(int base)
|
||||
{
|
||||
unsigned long i;
|
||||
int nextid;
|
||||
DEFINE_IDR(idr);
|
||||
idr_init_base(&idr, base);
|
||||
|
||||
int indices[] = {4, 7, 9, 15, 65, 128, 1000, 99999, 0};
|
||||
|
||||
@@ -207,6 +208,7 @@ void idr_checks(void)
|
||||
assert(idr_alloc(&idr, item, i, i + 10, GFP_KERNEL) == i);
|
||||
}
|
||||
assert(idr_alloc(&idr, DUMMY_PTR, i - 2, i, GFP_KERNEL) == -ENOSPC);
|
||||
assert(idr_alloc(&idr, DUMMY_PTR, i - 2, i + 10, GFP_KERNEL) == -ENOSPC);
|
||||
|
||||
idr_for_each(&idr, item_idr_free, &idr);
|
||||
idr_destroy(&idr);
|
||||
@@ -214,6 +216,23 @@ void idr_checks(void)
|
||||
|
||||
assert(idr_is_empty(&idr));
|
||||
|
||||
idr_set_cursor(&idr, INT_MAX - 3UL);
|
||||
for (i = INT_MAX - 3UL; i < INT_MAX + 3UL; i++) {
|
||||
struct item *item;
|
||||
unsigned int id;
|
||||
if (i <= INT_MAX)
|
||||
item = item_create(i, 0);
|
||||
else
|
||||
item = item_create(i - INT_MAX - 1, 0);
|
||||
|
||||
id = idr_alloc_cyclic(&idr, item, 0, 0, GFP_KERNEL);
|
||||
assert(id == item->index);
|
||||
}
|
||||
|
||||
idr_for_each(&idr, item_idr_free, &idr);
|
||||
idr_destroy(&idr);
|
||||
assert(idr_is_empty(&idr));
|
||||
|
||||
for (i = 1; i < 10000; i++) {
|
||||
struct item *item = item_create(i, 0);
|
||||
assert(idr_alloc(&idr, item, 1, 20000, GFP_KERNEL) == i);
|
||||
@@ -226,7 +245,9 @@ void idr_checks(void)
|
||||
idr_alloc_test();
|
||||
idr_null_test();
|
||||
idr_nowait_test();
|
||||
idr_get_next_test();
|
||||
idr_get_next_test(0);
|
||||
idr_get_next_test(1);
|
||||
idr_get_next_test(4);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -380,7 +401,7 @@ void ida_check_random(void)
|
||||
do {
|
||||
ida_pre_get(&ida, GFP_KERNEL);
|
||||
err = ida_get_new_above(&ida, bit, &id);
|
||||
} while (err == -ENOMEM);
|
||||
} while (err == -EAGAIN);
|
||||
assert(!err);
|
||||
assert(id == bit);
|
||||
}
|
||||
@@ -489,7 +510,7 @@ static void *ida_random_fn(void *arg)
|
||||
|
||||
void ida_thread_tests(void)
|
||||
{
|
||||
pthread_t threads[10];
|
||||
pthread_t threads[20];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(threads); i++)
|
||||
|
||||
@@ -17,6 +17,4 @@
|
||||
#define pr_debug printk
|
||||
#define pr_cont printk
|
||||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
#endif /* _KERNEL_H */
|
||||
|
||||
@@ -116,8 +116,15 @@ ifdef INSTALL_PATH
|
||||
|
||||
@# Ask all targets to emit their test scripts
|
||||
echo "#!/bin/sh" > $(ALL_SCRIPT)
|
||||
echo "cd \$$(dirname \$$0)" >> $(ALL_SCRIPT)
|
||||
echo "BASE_DIR=\$$(realpath \$$(dirname \$$0))" >> $(ALL_SCRIPT)
|
||||
echo "cd \$$BASE_DIR" >> $(ALL_SCRIPT)
|
||||
echo "ROOT=\$$PWD" >> $(ALL_SCRIPT)
|
||||
echo "if [ \"\$$1\" = \"--summary\" ]; then" >> $(ALL_SCRIPT)
|
||||
echo " OUTPUT=\$$BASE_DIR/output.log" >> $(ALL_SCRIPT)
|
||||
echo " cat /dev/null > \$$OUTPUT" >> $(ALL_SCRIPT)
|
||||
echo "else" >> $(ALL_SCRIPT)
|
||||
echo " OUTPUT=/dev/stdout" >> $(ALL_SCRIPT)
|
||||
echo "fi" >> $(ALL_SCRIPT)
|
||||
|
||||
for TARGET in $(TARGETS); do \
|
||||
BUILD_TARGET=$$BUILD/$$TARGET; \
|
||||
|
||||
8
tools/testing/selftests/bpf/.gitignore
vendored
8
tools/testing/selftests/bpf/.gitignore
vendored
@@ -3,3 +3,11 @@ test_maps
|
||||
test_lru_map
|
||||
test_lpm_map
|
||||
test_tag
|
||||
FEATURE-DUMP.libbpf
|
||||
fixdep
|
||||
test_align
|
||||
test_dev_cgroup
|
||||
test_progs
|
||||
test_tcpbpf_user
|
||||
test_verifier_log
|
||||
feature
|
||||
|
||||
@@ -11,23 +11,36 @@ ifneq ($(wildcard $(GENHDR)),)
|
||||
endif
|
||||
|
||||
CFLAGS += -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include
|
||||
LDLIBS += -lcap -lelf -lrt
|
||||
LDLIBS += -lcap -lelf -lrt -lpthread
|
||||
|
||||
# Order correspond to 'make run_tests' order
|
||||
TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
|
||||
test_align test_verifier_log test_dev_cgroup
|
||||
test_align test_verifier_log test_dev_cgroup test_tcpbpf_user
|
||||
|
||||
TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \
|
||||
test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \
|
||||
sockmap_verdict_prog.o dev_cgroup.o
|
||||
sockmap_verdict_prog.o dev_cgroup.o sample_ret0.o test_tracepoint.o \
|
||||
test_l4lb_noinline.o test_xdp_noinline.o test_stacktrace_map.o \
|
||||
sample_map_ret0.o test_tcpbpf_kern.o
|
||||
|
||||
TEST_PROGS := test_kmod.sh test_xdp_redirect.sh test_xdp_meta.sh
|
||||
# Order correspond to 'make run_tests' order
|
||||
TEST_PROGS := test_kmod.sh \
|
||||
test_libbpf.sh \
|
||||
test_xdp_redirect.sh \
|
||||
test_xdp_meta.sh \
|
||||
test_offload.py
|
||||
|
||||
# Compile but not part of 'make run_tests'
|
||||
TEST_GEN_PROGS_EXTENDED = test_libbpf_open
|
||||
|
||||
include ../lib.mk
|
||||
|
||||
BPFOBJ := $(OUTPUT)/libbpf.a $(OUTPUT)/cgroup_helpers.c
|
||||
BPFOBJ := $(OUTPUT)/libbpf.a cgroup_helpers.c
|
||||
|
||||
$(TEST_GEN_PROGS): $(BPFOBJ)
|
||||
|
||||
$(TEST_GEN_PROGS_EXTENDED): $(OUTPUT)/libbpf.a
|
||||
|
||||
.PHONY: force
|
||||
|
||||
# force a rebuild of BPFOBJ when its dependencies are updated
|
||||
@@ -49,8 +62,13 @@ else
|
||||
CPU ?= generic
|
||||
endif
|
||||
|
||||
%.o: %.c
|
||||
$(CLANG) -I. -I./include/uapi -I../../../include/uapi \
|
||||
-Wno-compare-distinct-pointer-types \
|
||||
CLANG_FLAGS = -I. -I./include/uapi -I../../../include/uapi \
|
||||
-Wno-compare-distinct-pointer-types
|
||||
|
||||
$(OUTPUT)/test_l4lb_noinline.o: CLANG_FLAGS += -fno-inline
|
||||
$(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline
|
||||
|
||||
$(OUTPUT)/%.o: %.c
|
||||
$(CLANG) $(CLANG_FLAGS) \
|
||||
-O2 -target bpf -emit-llvm -c $< -o - | \
|
||||
$(LLC) -march=bpf -mcpu=$(CPU) -filetype=obj -o $@
|
||||
|
||||
@@ -71,6 +71,8 @@ static int (*bpf_setsockopt)(void *ctx, int level, int optname, void *optval,
|
||||
static int (*bpf_getsockopt)(void *ctx, int level, int optname, void *optval,
|
||||
int optlen) =
|
||||
(void *) BPF_FUNC_getsockopt;
|
||||
static int (*bpf_sock_ops_cb_flags_set)(void *ctx, int flags) =
|
||||
(void *) BPF_FUNC_sock_ops_cb_flags_set;
|
||||
static int (*bpf_sk_redirect_map)(void *ctx, void *map, int key, int flags) =
|
||||
(void *) BPF_FUNC_sk_redirect_map;
|
||||
static int (*bpf_sock_map_update)(void *map, void *key, void *value,
|
||||
@@ -82,7 +84,8 @@ static int (*bpf_perf_event_read_value)(void *map, unsigned long long flags,
|
||||
static int (*bpf_perf_prog_read_value)(void *ctx, void *buf,
|
||||
unsigned int buf_size) =
|
||||
(void *) BPF_FUNC_perf_prog_read_value;
|
||||
|
||||
static int (*bpf_override_return)(void *ctx, unsigned long rc) =
|
||||
(void *) BPF_FUNC_override_return;
|
||||
|
||||
/* llvm builtin functions that eBPF C program may use to
|
||||
* emit BPF_LD_ABS and BPF_LD_IND instructions
|
||||
|
||||
@@ -3,3 +3,5 @@ CONFIG_BPF_SYSCALL=y
|
||||
CONFIG_NET_CLS_BPF=m
|
||||
CONFIG_BPF_EVENTS=y
|
||||
CONFIG_TEST_BPF=m
|
||||
CONFIG_CGROUP_BPF=y
|
||||
CONFIG_NETDEVSIM=m
|
||||
|
||||
34
tools/testing/selftests/bpf/sample_map_ret0.c
Normal file
34
tools/testing/selftests/bpf/sample_map_ret0.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
|
||||
#include <linux/bpf.h>
|
||||
#include "bpf_helpers.h"
|
||||
|
||||
struct bpf_map_def SEC("maps") htab = {
|
||||
.type = BPF_MAP_TYPE_HASH,
|
||||
.key_size = sizeof(__u32),
|
||||
.value_size = sizeof(long),
|
||||
.max_entries = 2,
|
||||
};
|
||||
|
||||
struct bpf_map_def SEC("maps") array = {
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
.key_size = sizeof(__u32),
|
||||
.value_size = sizeof(long),
|
||||
.max_entries = 2,
|
||||
};
|
||||
|
||||
/* Sample program which should always load for testing control paths. */
|
||||
SEC(".text") int func()
|
||||
{
|
||||
__u64 key64 = 0;
|
||||
__u32 key = 0;
|
||||
long *value;
|
||||
|
||||
value = bpf_map_lookup_elem(&htab, &key);
|
||||
if (!value)
|
||||
return 1;
|
||||
value = bpf_map_lookup_elem(&array, &key64);
|
||||
if (!value)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
7
tools/testing/selftests/bpf/sample_ret0.c
Normal file
7
tools/testing/selftests/bpf/sample_ret0.c
Normal file
@@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
|
||||
|
||||
/* Sample program which should always load for testing control paths. */
|
||||
int func()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user