diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-03-20 06:27:18 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-03-20 06:27:18 -0400 |
commit | 4958134df54c2c84e9c22ea042761d439164d26e (patch) | |
tree | 503177afab11f7d25b12a84ce25b481d305c51ba /tools | |
parent | c4f528795d1add8b63652673f7262729f679c6c1 (diff) | |
parent | c698ca5278934c0ae32297a8725ced2e27585d7f (diff) |
Merge 4.16-rc6 into tty-next
We want the serial/tty fixes in here as well.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'tools')
39 files changed, 664 insertions, 286 deletions
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h index 0dfe4d3f74e2..f41079da38c5 100644 --- a/tools/arch/x86/include/asm/cpufeatures.h +++ b/tools/arch/x86/include/asm/cpufeatures.h | |||
@@ -213,6 +213,7 @@ | |||
213 | #define X86_FEATURE_SEV ( 7*32+20) /* AMD Secure Encrypted Virtualization */ | 213 | #define X86_FEATURE_SEV ( 7*32+20) /* AMD Secure Encrypted Virtualization */ |
214 | 214 | ||
215 | #define X86_FEATURE_USE_IBPB ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */ | 215 | #define X86_FEATURE_USE_IBPB ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */ |
216 | #define X86_FEATURE_USE_IBRS_FW ( 7*32+22) /* "" Use IBRS during runtime firmware calls */ | ||
216 | 217 | ||
217 | /* Virtualization flags: Linux defined, word 8 */ | 218 | /* Virtualization flags: Linux defined, word 8 */ |
218 | #define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ | 219 | #define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ |
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h index 0fb5ef939732..7b26d4b0b052 100644 --- a/tools/include/uapi/linux/kvm.h +++ b/tools/include/uapi/linux/kvm.h | |||
@@ -761,6 +761,7 @@ struct kvm_ppc_resize_hpt { | |||
761 | #define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07 | 761 | #define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07 |
762 | #define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08 | 762 | #define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08 |
763 | #define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2) | 763 | #define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2) |
764 | #define KVM_GET_MSR_FEATURE_INDEX_LIST _IOWR(KVMIO, 0x0a, struct kvm_msr_list) | ||
764 | 765 | ||
765 | /* | 766 | /* |
766 | * Extension capability list. | 767 | * Extension capability list. |
@@ -934,6 +935,7 @@ struct kvm_ppc_resize_hpt { | |||
934 | #define KVM_CAP_S390_AIS_MIGRATION 150 | 935 | #define KVM_CAP_S390_AIS_MIGRATION 150 |
935 | #define KVM_CAP_PPC_GET_CPU_CHAR 151 | 936 | #define KVM_CAP_PPC_GET_CPU_CHAR 151 |
936 | #define KVM_CAP_S390_BPB 152 | 937 | #define KVM_CAP_S390_BPB 152 |
938 | #define KVM_CAP_GET_MSR_FEATURES 153 | ||
937 | 939 | ||
938 | #ifdef KVM_CAP_IRQ_ROUTING | 940 | #ifdef KVM_CAP_IRQ_ROUTING |
939 | 941 | ||
diff --git a/tools/kvm/kvm_stat/kvm_stat b/tools/kvm/kvm_stat/kvm_stat index a5684d0968b4..5898c22ba310 100755 --- a/tools/kvm/kvm_stat/kvm_stat +++ b/tools/kvm/kvm_stat/kvm_stat | |||
@@ -33,7 +33,7 @@ import resource | |||
33 | import struct | 33 | import struct |
34 | import re | 34 | import re |
35 | import subprocess | 35 | import subprocess |
36 | from collections import defaultdict | 36 | from collections import defaultdict, namedtuple |
37 | 37 | ||
38 | VMX_EXIT_REASONS = { | 38 | VMX_EXIT_REASONS = { |
39 | 'EXCEPTION_NMI': 0, | 39 | 'EXCEPTION_NMI': 0, |
@@ -228,6 +228,7 @@ IOCTL_NUMBERS = { | |||
228 | } | 228 | } |
229 | 229 | ||
230 | ENCODING = locale.getpreferredencoding(False) | 230 | ENCODING = locale.getpreferredencoding(False) |
231 | TRACE_FILTER = re.compile(r'^[^\(]*$') | ||
231 | 232 | ||
232 | 233 | ||
233 | class Arch(object): | 234 | class Arch(object): |
@@ -260,6 +261,11 @@ class Arch(object): | |||
260 | return ArchX86(SVM_EXIT_REASONS) | 261 | return ArchX86(SVM_EXIT_REASONS) |
261 | return | 262 | return |
262 | 263 | ||
264 | def tracepoint_is_child(self, field): | ||
265 | if (TRACE_FILTER.match(field)): | ||
266 | return None | ||
267 | return field.split('(', 1)[0] | ||
268 | |||
263 | 269 | ||
264 | class ArchX86(Arch): | 270 | class ArchX86(Arch): |
265 | def __init__(self, exit_reasons): | 271 | def __init__(self, exit_reasons): |
@@ -267,6 +273,10 @@ class ArchX86(Arch): | |||
267 | self.ioctl_numbers = IOCTL_NUMBERS | 273 | self.ioctl_numbers = IOCTL_NUMBERS |
268 | self.exit_reasons = exit_reasons | 274 | self.exit_reasons = exit_reasons |
269 | 275 | ||
276 | def debugfs_is_child(self, field): | ||
277 | """ Returns name of parent if 'field' is a child, None otherwise """ | ||
278 | return None | ||
279 | |||
270 | 280 | ||
271 | class ArchPPC(Arch): | 281 | class ArchPPC(Arch): |
272 | def __init__(self): | 282 | def __init__(self): |
@@ -282,6 +292,10 @@ class ArchPPC(Arch): | |||
282 | self.ioctl_numbers['SET_FILTER'] = 0x80002406 | char_ptr_size << 16 | 292 | self.ioctl_numbers['SET_FILTER'] = 0x80002406 | char_ptr_size << 16 |
283 | self.exit_reasons = {} | 293 | self.exit_reasons = {} |
284 | 294 | ||
295 | def debugfs_is_child(self, field): | ||
296 | """ Returns name of parent if 'field' is a child, None otherwise """ | ||
297 | return None | ||
298 | |||
285 | 299 | ||
286 | class ArchA64(Arch): | 300 | class ArchA64(Arch): |
287 | def __init__(self): | 301 | def __init__(self): |
@@ -289,6 +303,10 @@ class ArchA64(Arch): | |||
289 | self.ioctl_numbers = IOCTL_NUMBERS | 303 | self.ioctl_numbers = IOCTL_NUMBERS |
290 | self.exit_reasons = AARCH64_EXIT_REASONS | 304 | self.exit_reasons = AARCH64_EXIT_REASONS |
291 | 305 | ||
306 | def debugfs_is_child(self, field): | ||
307 | """ Returns name of parent if 'field' is a child, None otherwise """ | ||
308 | return None | ||
309 | |||
292 | 310 | ||
293 | class ArchS390(Arch): | 311 | class ArchS390(Arch): |
294 | def __init__(self): | 312 | def __init__(self): |
@@ -296,6 +314,12 @@ class ArchS390(Arch): | |||
296 | self.ioctl_numbers = IOCTL_NUMBERS | 314 | self.ioctl_numbers = IOCTL_NUMBERS |
297 | self.exit_reasons = None | 315 | self.exit_reasons = None |
298 | 316 | ||
317 | def debugfs_is_child(self, field): | ||
318 | """ Returns name of parent if 'field' is a child, None otherwise """ | ||
319 | if field.startswith('instruction_'): | ||
320 | return 'exit_instruction' | ||
321 | |||
322 | |||
299 | ARCH = Arch.get_arch() | 323 | ARCH = Arch.get_arch() |
300 | 324 | ||
301 | 325 | ||
@@ -331,9 +355,6 @@ class perf_event_attr(ctypes.Structure): | |||
331 | PERF_TYPE_TRACEPOINT = 2 | 355 | PERF_TYPE_TRACEPOINT = 2 |
332 | PERF_FORMAT_GROUP = 1 << 3 | 356 | PERF_FORMAT_GROUP = 1 << 3 |
333 | 357 | ||
334 | PATH_DEBUGFS_TRACING = '/sys/kernel/debug/tracing' | ||
335 | PATH_DEBUGFS_KVM = '/sys/kernel/debug/kvm' | ||
336 | |||
337 | 358 | ||
338 | class Group(object): | 359 | class Group(object): |
339 | """Represents a perf event group.""" | 360 | """Represents a perf event group.""" |
@@ -376,8 +397,8 @@ class Event(object): | |||
376 | self.syscall = self.libc.syscall | 397 | self.syscall = self.libc.syscall |
377 | self.name = name | 398 | self.name = name |
378 | self.fd = None | 399 | self.fd = None |
379 | self.setup_event(group, trace_cpu, trace_pid, trace_point, | 400 | self._setup_event(group, trace_cpu, trace_pid, trace_point, |
380 | trace_filter, trace_set) | 401 | trace_filter, trace_set) |
381 | 402 | ||
382 | def __del__(self): | 403 | def __del__(self): |
383 | """Closes the event's file descriptor. | 404 | """Closes the event's file descriptor. |
@@ -390,7 +411,7 @@ class Event(object): | |||
390 | if self.fd: | 411 | if self.fd: |
391 | os.close(self.fd) | 412 | os.close(self.fd) |
392 | 413 | ||
393 | def perf_event_open(self, attr, pid, cpu, group_fd, flags): | 414 | def _perf_event_open(self, attr, pid, cpu, group_fd, flags): |
394 | """Wrapper for the sys_perf_evt_open() syscall. | 415 | """Wrapper for the sys_perf_evt_open() syscall. |
395 | 416 | ||
396 | Used to set up performance events, returns a file descriptor or -1 | 417 | Used to set up performance events, returns a file descriptor or -1 |
@@ -409,7 +430,7 @@ class Event(object): | |||
409 | ctypes.c_int(pid), ctypes.c_int(cpu), | 430 | ctypes.c_int(pid), ctypes.c_int(cpu), |
410 | ctypes.c_int(group_fd), ctypes.c_long(flags)) | 431 | ctypes.c_int(group_fd), ctypes.c_long(flags)) |
411 | 432 | ||
412 | def setup_event_attribute(self, trace_set, trace_point): | 433 | def _setup_event_attribute(self, trace_set, trace_point): |
413 | """Returns an initialized ctype perf_event_attr struct.""" | 434 | """Returns an initialized ctype perf_event_attr struct.""" |
414 | 435 | ||
415 | id_path = os.path.join(PATH_DEBUGFS_TRACING, 'events', trace_set, | 436 | id_path = os.path.join(PATH_DEBUGFS_TRACING, 'events', trace_set, |
@@ -419,8 +440,8 @@ class Event(object): | |||
419 | event_attr.config = int(open(id_path).read()) | 440 | event_attr.config = int(open(id_path).read()) |
420 | return event_attr | 441 | return event_attr |
421 | 442 | ||
422 | def setup_event(self, group, trace_cpu, trace_pid, trace_point, | 443 | def _setup_event(self, group, trace_cpu, trace_pid, trace_point, |
423 | trace_filter, trace_set): | 444 | trace_filter, trace_set): |
424 | """Sets up the perf event in Linux. | 445 | """Sets up the perf event in Linux. |
425 | 446 | ||
426 | Issues the syscall to register the event in the kernel and | 447 | Issues the syscall to register the event in the kernel and |
@@ -428,7 +449,7 @@ class Event(object): | |||
428 | 449 | ||
429 | """ | 450 | """ |
430 | 451 | ||
431 | event_attr = self.setup_event_attribute(trace_set, trace_point) | 452 | event_attr = self._setup_event_attribute(trace_set, trace_point) |
432 | 453 | ||
433 | # First event will be group leader. | 454 | # First event will be group leader. |
434 | group_leader = -1 | 455 | group_leader = -1 |
@@ -437,8 +458,8 @@ class Event(object): | |||
437 | if group.events: | 458 | if group.events: |
438 | group_leader = group.events[0].fd | 459 | group_leader = group.events[0].fd |
439 | 460 | ||
440 | fd = self.perf_event_open(event_attr, trace_pid, | 461 | fd = self._perf_event_open(event_attr, trace_pid, |
441 | trace_cpu, group_leader, 0) | 462 | trace_cpu, group_leader, 0) |
442 | if fd == -1: | 463 | if fd == -1: |
443 | err = ctypes.get_errno() | 464 | err = ctypes.get_errno() |
444 | raise OSError(err, os.strerror(err), | 465 | raise OSError(err, os.strerror(err), |
@@ -475,6 +496,10 @@ class Event(object): | |||
475 | 496 | ||
476 | class Provider(object): | 497 | class Provider(object): |
477 | """Encapsulates functionalities used by all providers.""" | 498 | """Encapsulates functionalities used by all providers.""" |
499 | def __init__(self, pid): | ||
500 | self.child_events = False | ||
501 | self.pid = pid | ||
502 | |||
478 | @staticmethod | 503 | @staticmethod |
479 | def is_field_wanted(fields_filter, field): | 504 | def is_field_wanted(fields_filter, field): |
480 | """Indicate whether field is valid according to fields_filter.""" | 505 | """Indicate whether field is valid according to fields_filter.""" |
@@ -500,12 +525,12 @@ class TracepointProvider(Provider): | |||
500 | """ | 525 | """ |
501 | def __init__(self, pid, fields_filter): | 526 | def __init__(self, pid, fields_filter): |
502 | self.group_leaders = [] | 527 | self.group_leaders = [] |
503 | self.filters = self.get_filters() | 528 | self.filters = self._get_filters() |
504 | self.update_fields(fields_filter) | 529 | self.update_fields(fields_filter) |
505 | self.pid = pid | 530 | super(TracepointProvider, self).__init__(pid) |
506 | 531 | ||
507 | @staticmethod | 532 | @staticmethod |
508 | def get_filters(): | 533 | def _get_filters(): |
509 | """Returns a dict of trace events, their filter ids and | 534 | """Returns a dict of trace events, their filter ids and |
510 | the values that can be filtered. | 535 | the values that can be filtered. |
511 | 536 | ||
@@ -521,8 +546,8 @@ class TracepointProvider(Provider): | |||
521 | filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons) | 546 | filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons) |
522 | return filters | 547 | return filters |
523 | 548 | ||
524 | def get_available_fields(self): | 549 | def _get_available_fields(self): |
525 | """Returns a list of available event's of format 'event name(filter | 550 | """Returns a list of available events of format 'event name(filter |
526 | name)'. | 551 | name)'. |
527 | 552 | ||
528 | All available events have directories under | 553 | All available events have directories under |
@@ -549,11 +574,12 @@ class TracepointProvider(Provider): | |||
549 | 574 | ||
550 | def update_fields(self, fields_filter): | 575 | def update_fields(self, fields_filter): |
551 | """Refresh fields, applying fields_filter""" | 576 | """Refresh fields, applying fields_filter""" |
552 | self.fields = [field for field in self.get_available_fields() | 577 | self.fields = [field for field in self._get_available_fields() |
553 | if self.is_field_wanted(fields_filter, field)] | 578 | if self.is_field_wanted(fields_filter, field) or |
579 | ARCH.tracepoint_is_child(field)] | ||
554 | 580 | ||
555 | @staticmethod | 581 | @staticmethod |
556 | def get_online_cpus(): | 582 | def _get_online_cpus(): |
557 | """Returns a list of cpu id integers.""" | 583 | """Returns a list of cpu id integers.""" |
558 | def parse_int_list(list_string): | 584 | def parse_int_list(list_string): |
559 | """Returns an int list from a string of comma separated integers and | 585 | """Returns an int list from a string of comma separated integers and |
@@ -575,17 +601,17 @@ class TracepointProvider(Provider): | |||
575 | cpu_string = cpu_list.readline() | 601 | cpu_string = cpu_list.readline() |
576 | return parse_int_list(cpu_string) | 602 | return parse_int_list(cpu_string) |
577 | 603 | ||
578 | def setup_traces(self): | 604 | def _setup_traces(self): |
579 | """Creates all event and group objects needed to be able to retrieve | 605 | """Creates all event and group objects needed to be able to retrieve |
580 | data.""" | 606 | data.""" |
581 | fields = self.get_available_fields() | 607 | fields = self._get_available_fields() |
582 | if self._pid > 0: | 608 | if self._pid > 0: |
583 | # Fetch list of all threads of the monitored pid, as qemu | 609 | # Fetch list of all threads of the monitored pid, as qemu |
584 | # starts a thread for each vcpu. | 610 | # starts a thread for each vcpu. |
585 | path = os.path.join('/proc', str(self._pid), 'task') | 611 | path = os.path.join('/proc', str(self._pid), 'task') |
586 | groupids = self.walkdir(path)[1] | 612 | groupids = self.walkdir(path)[1] |
587 | else: | 613 | else: |
588 | groupids = self.get_online_cpus() | 614 | groupids = self._get_online_cpus() |
589 | 615 | ||
590 | # The constant is needed as a buffer for python libs, std | 616 | # The constant is needed as a buffer for python libs, std |
591 | # streams and other files that the script opens. | 617 | # streams and other files that the script opens. |
@@ -663,7 +689,7 @@ class TracepointProvider(Provider): | |||
663 | # The garbage collector will get rid of all Event/Group | 689 | # The garbage collector will get rid of all Event/Group |
664 | # objects and open files after removing the references. | 690 | # objects and open files after removing the references. |
665 | self.group_leaders = [] | 691 | self.group_leaders = [] |
666 | self.setup_traces() | 692 | self._setup_traces() |
667 | self.fields = self._fields | 693 | self.fields = self._fields |
668 | 694 | ||
669 | def read(self, by_guest=0): | 695 | def read(self, by_guest=0): |
@@ -671,8 +697,12 @@ class TracepointProvider(Provider): | |||
671 | ret = defaultdict(int) | 697 | ret = defaultdict(int) |
672 | for group in self.group_leaders: | 698 | for group in self.group_leaders: |
673 | for name, val in group.read().items(): | 699 | for name, val in group.read().items(): |
674 | if name in self._fields: | 700 | if name not in self._fields: |
675 | ret[name] += val | 701 | continue |
702 | parent = ARCH.tracepoint_is_child(name) | ||
703 | if parent: | ||
704 | name += ' ' + parent | ||
705 | ret[name] += val | ||
676 | return ret | 706 | return ret |
677 | 707 | ||
678 | def reset(self): | 708 | def reset(self): |
@@ -690,11 +720,11 @@ class DebugfsProvider(Provider): | |||
690 | self._baseline = {} | 720 | self._baseline = {} |
691 | self.do_read = True | 721 | self.do_read = True |
692 | self.paths = [] | 722 | self.paths = [] |
693 | self.pid = pid | 723 | super(DebugfsProvider, self).__init__(pid) |
694 | if include_past: | 724 | if include_past: |
695 | self.restore() | 725 | self._restore() |
696 | 726 | ||
697 | def get_available_fields(self): | 727 | def _get_available_fields(self): |
698 | """"Returns a list of available fields. | 728 | """"Returns a list of available fields. |
699 | 729 | ||
700 | The fields are all available KVM debugfs files | 730 | The fields are all available KVM debugfs files |
@@ -704,8 +734,9 @@ class DebugfsProvider(Provider): | |||
704 | 734 | ||
705 | def update_fields(self, fields_filter): | 735 | def update_fields(self, fields_filter): |
706 | """Refresh fields, applying fields_filter""" | 736 | """Refresh fields, applying fields_filter""" |
707 | self._fields = [field for field in self.get_available_fields() | 737 | self._fields = [field for field in self._get_available_fields() |
708 | if self.is_field_wanted(fields_filter, field)] | 738 | if self.is_field_wanted(fields_filter, field) or |
739 | ARCH.debugfs_is_child(field)] | ||
709 | 740 | ||
710 | @property | 741 | @property |
711 | def fields(self): | 742 | def fields(self): |
@@ -758,7 +789,7 @@ class DebugfsProvider(Provider): | |||
758 | paths.append(dir) | 789 | paths.append(dir) |
759 | for path in paths: | 790 | for path in paths: |
760 | for field in self._fields: | 791 | for field in self._fields: |
761 | value = self.read_field(field, path) | 792 | value = self._read_field(field, path) |
762 | key = path + field | 793 | key = path + field |
763 | if reset == 1: | 794 | if reset == 1: |
764 | self._baseline[key] = value | 795 | self._baseline[key] = value |
@@ -766,20 +797,21 @@ class DebugfsProvider(Provider): | |||
766 | self._baseline[key] = 0 | 797 | self._baseline[key] = 0 |
767 | if self._baseline.get(key, -1) == -1: | 798 | if self._baseline.get(key, -1) == -1: |
768 | self._baseline[key] = value | 799 | self._baseline[key] = value |
769 | increment = (results.get(field, 0) + value - | 800 | parent = ARCH.debugfs_is_child(field) |
770 | self._baseline.get(key, 0)) | 801 | if parent: |
771 | if by_guest: | 802 | field = field + ' ' + parent |
772 | pid = key.split('-')[0] | 803 | else: |
773 | if pid in results: | 804 | if by_guest: |
774 | results[pid] += increment | 805 | field = key.split('-')[0] # set 'field' to 'pid' |
775 | else: | 806 | increment = value - self._baseline.get(key, 0) |
776 | results[pid] = increment | 807 | if field in results: |
808 | results[field] += increment | ||
777 | else: | 809 | else: |
778 | results[field] = increment | 810 | results[field] = increment |
779 | 811 | ||
780 | return results | 812 | return results |
781 | 813 | ||
782 | def read_field(self, field, path): | 814 | def _read_field(self, field, path): |
783 | """Returns the value of a single field from a specific VM.""" | 815 | """Returns the value of a single field from a specific VM.""" |
784 | try: | 816 | try: |
785 | return int(open(os.path.join(PATH_DEBUGFS_KVM, | 817 | return int(open(os.path.join(PATH_DEBUGFS_KVM, |
@@ -794,12 +826,15 @@ class DebugfsProvider(Provider): | |||
794 | self._baseline = {} | 826 | self._baseline = {} |
795 | self.read(1) | 827 | self.read(1) |
796 | 828 | ||
797 | def restore(self): | 829 | def _restore(self): |
798 | """Reset field counters""" | 830 | """Reset field counters""" |
799 | self._baseline = {} | 831 | self._baseline = {} |
800 | self.read(2) | 832 | self.read(2) |
801 | 833 | ||
802 | 834 | ||
835 | EventStat = namedtuple('EventStat', ['value', 'delta']) | ||
836 | |||
837 | |||
803 | class Stats(object): | 838 | class Stats(object): |
804 | """Manages the data providers and the data they provide. | 839 | """Manages the data providers and the data they provide. |
805 | 840 | ||
@@ -808,13 +843,13 @@ class Stats(object): | |||
808 | 843 | ||
809 | """ | 844 | """ |
810 | def __init__(self, options): | 845 | def __init__(self, options): |
811 | self.providers = self.get_providers(options) | 846 | self.providers = self._get_providers(options) |
812 | self._pid_filter = options.pid | 847 | self._pid_filter = options.pid |
813 | self._fields_filter = options.fields | 848 | self._fields_filter = options.fields |
814 | self.values = {} | 849 | self.values = {} |
850 | self._child_events = False | ||
815 | 851 | ||
816 | @staticmethod | 852 | def _get_providers(self, options): |
817 | def get_providers(options): | ||
818 | """Returns a list of data providers depending on the passed options.""" | 853 | """Returns a list of data providers depending on the passed options.""" |
819 | providers = [] | 854 | providers = [] |
820 | 855 | ||
@@ -826,7 +861,7 @@ class Stats(object): | |||
826 | 861 | ||
827 | return providers | 862 | return providers |
828 | 863 | ||
829 | def update_provider_filters(self): | 864 | def _update_provider_filters(self): |
830 | """Propagates fields filters to providers.""" | 865 | """Propagates fields filters to providers.""" |
831 | # As we reset the counters when updating the fields we can | 866 | # As we reset the counters when updating the fields we can |
832 | # also clear the cache of old values. | 867 | # also clear the cache of old values. |
@@ -847,7 +882,7 @@ class Stats(object): | |||
847 | def fields_filter(self, fields_filter): | 882 | def fields_filter(self, fields_filter): |
848 | if fields_filter != self._fields_filter: | 883 | if fields_filter != self._fields_filter: |
849 | self._fields_filter = fields_filter | 884 | self._fields_filter = fields_filter |
850 | self.update_provider_filters() | 885 | self._update_provider_filters() |
851 | 886 | ||
852 | @property | 887 | @property |
853 | def pid_filter(self): | 888 | def pid_filter(self): |
@@ -861,16 +896,33 @@ class Stats(object): | |||
861 | for provider in self.providers: | 896 | for provider in self.providers: |
862 | provider.pid = self._pid_filter | 897 | provider.pid = self._pid_filter |
863 | 898 | ||
899 | @property | ||
900 | def child_events(self): | ||
901 | return self._child_events | ||
902 | |||
903 | @child_events.setter | ||
904 | def child_events(self, val): | ||
905 | self._child_events = val | ||
906 | for provider in self.providers: | ||
907 | provider.child_events = val | ||
908 | |||
864 | def get(self, by_guest=0): | 909 | def get(self, by_guest=0): |
865 | """Returns a dict with field -> (value, delta to last value) of all | 910 | """Returns a dict with field -> (value, delta to last value) of all |
866 | provider data.""" | 911 | provider data. |
912 | Key formats: | ||
913 | * plain: 'key' is event name | ||
914 | * child-parent: 'key' is in format '<child> <parent>' | ||
915 | * pid: 'key' is the pid of the guest, and the record contains the | ||
916 | aggregated event data | ||
917 | These formats are generated by the providers, and handled in class TUI. | ||
918 | """ | ||
867 | for provider in self.providers: | 919 | for provider in self.providers: |
868 | new = provider.read(by_guest=by_guest) | 920 | new = provider.read(by_guest=by_guest) |
869 | for key in new if by_guest else provider.fields: | 921 | for key in new: |
870 | oldval = self.values.get(key, (0, 0))[0] | 922 | oldval = self.values.get(key, EventStat(0, 0)).value |
871 | newval = new.get(key, 0) | 923 | newval = new.get(key, 0) |
872 | newdelta = newval - oldval | 924 | newdelta = newval - oldval |
873 | self.values[key] = (newval, newdelta) | 925 | self.values[key] = EventStat(newval, newdelta) |
874 | return self.values | 926 | return self.values |
875 | 927 | ||
876 | def toggle_display_guests(self, to_pid): | 928 | def toggle_display_guests(self, to_pid): |
@@ -899,10 +951,10 @@ class Stats(object): | |||
899 | self.get(to_pid) | 951 | self.get(to_pid) |
900 | return 0 | 952 | return 0 |
901 | 953 | ||
954 | |||
902 | DELAY_DEFAULT = 3.0 | 955 | DELAY_DEFAULT = 3.0 |
903 | MAX_GUEST_NAME_LEN = 48 | 956 | MAX_GUEST_NAME_LEN = 48 |
904 | MAX_REGEX_LEN = 44 | 957 | MAX_REGEX_LEN = 44 |
905 | DEFAULT_REGEX = r'^[^\(]*$' | ||
906 | SORT_DEFAULT = 0 | 958 | SORT_DEFAULT = 0 |
907 | 959 | ||
908 | 960 | ||
@@ -969,7 +1021,7 @@ class Tui(object): | |||
969 | 1021 | ||
970 | return res | 1022 | return res |
971 | 1023 | ||
972 | def print_all_gnames(self, row): | 1024 | def _print_all_gnames(self, row): |
973 | """Print a list of all running guests along with their pids.""" | 1025 | """Print a list of all running guests along with their pids.""" |
974 | self.screen.addstr(row, 2, '%8s %-60s' % | 1026 | self.screen.addstr(row, 2, '%8s %-60s' % |
975 | ('Pid', 'Guest Name (fuzzy list, might be ' | 1027 | ('Pid', 'Guest Name (fuzzy list, might be ' |
@@ -1032,19 +1084,13 @@ class Tui(object): | |||
1032 | 1084 | ||
1033 | return name | 1085 | return name |
1034 | 1086 | ||
1035 | def update_drilldown(self): | 1087 | def _update_pid(self, pid): |
1036 | """Sets or removes a filter that only allows fields without braces.""" | ||
1037 | if not self.stats.fields_filter: | ||
1038 | self.stats.fields_filter = DEFAULT_REGEX | ||
1039 | |||
1040 | elif self.stats.fields_filter == DEFAULT_REGEX: | ||
1041 | self.stats.fields_filter = None | ||
1042 | |||
1043 | def update_pid(self, pid): | ||
1044 | """Propagates pid selection to stats object.""" | 1088 | """Propagates pid selection to stats object.""" |
1089 | self.screen.addstr(4, 1, 'Updating pid filter...') | ||
1090 | self.screen.refresh() | ||
1045 | self.stats.pid_filter = pid | 1091 | self.stats.pid_filter = pid |
1046 | 1092 | ||
1047 | def refresh_header(self, pid=None): | 1093 | def _refresh_header(self, pid=None): |
1048 | """Refreshes the header.""" | 1094 | """Refreshes the header.""" |
1049 | if pid is None: | 1095 | if pid is None: |
1050 | pid = self.stats.pid_filter | 1096 | pid = self.stats.pid_filter |
@@ -1059,8 +1105,7 @@ class Tui(object): | |||
1059 | .format(pid, gname), curses.A_BOLD) | 1105 | .format(pid, gname), curses.A_BOLD) |
1060 | else: | 1106 | else: |
1061 | self.screen.addstr(0, 0, 'kvm statistics - summary', curses.A_BOLD) | 1107 | self.screen.addstr(0, 0, 'kvm statistics - summary', curses.A_BOLD) |
1062 | if self.stats.fields_filter and self.stats.fields_filter \ | 1108 | if self.stats.fields_filter: |
1063 | != DEFAULT_REGEX: | ||
1064 | regex = self.stats.fields_filter | 1109 | regex = self.stats.fields_filter |
1065 | if len(regex) > MAX_REGEX_LEN: | 1110 | if len(regex) > MAX_REGEX_LEN: |
1066 | regex = regex[:MAX_REGEX_LEN] + '...' | 1111 | regex = regex[:MAX_REGEX_LEN] + '...' |
@@ -1075,56 +1120,99 @@ class Tui(object): | |||
1075 | self.screen.addstr(4, 1, 'Collecting data...') | 1120 | self.screen.addstr(4, 1, 'Collecting data...') |
1076 | self.screen.refresh() | 1121 | self.screen.refresh() |
1077 | 1122 | ||
1078 | def refresh_body(self, sleeptime): | 1123 | def _refresh_body(self, sleeptime): |
1124 | def is_child_field(field): | ||
1125 | return field.find('(') != -1 | ||
1126 | |||
1127 | def insert_child(sorted_items, child, values, parent): | ||
1128 | num = len(sorted_items) | ||
1129 | for i in range(0, num): | ||
1130 | # only add child if parent is present | ||
1131 | if parent.startswith(sorted_items[i][0]): | ||
1132 | sorted_items.insert(i + 1, (' ' + child, values)) | ||
1133 | |||
1134 | def get_sorted_events(self, stats): | ||
1135 | """ separate parent and child events """ | ||
1136 | if self._sorting == SORT_DEFAULT: | ||
1137 | def sortkey((_k, v)): | ||
1138 | # sort by (delta value, overall value) | ||
1139 | return (v.delta, v.value) | ||
1140 | else: | ||
1141 | def sortkey((_k, v)): | ||
1142 | # sort by overall value | ||
1143 | return v.value | ||
1144 | |||
1145 | childs = [] | ||
1146 | sorted_items = [] | ||
1147 | # we can't rule out child events to appear prior to parents even | ||
1148 | # when sorted - separate out all children first, and add in later | ||
1149 | for key, values in sorted(stats.items(), key=sortkey, | ||
1150 | reverse=True): | ||
1151 | if values == (0, 0): | ||
1152 | continue | ||
1153 | if key.find(' ') != -1: | ||
1154 | if not self.stats.child_events: | ||
1155 | continue | ||
1156 | childs.insert(0, (key, values)) | ||
1157 | else: | ||
1158 | sorted_items.append((key, values)) | ||
1159 | if self.stats.child_events: | ||
1160 | for key, values in childs: | ||
1161 | (child, parent) = key.split(' ') | ||
1162 | insert_child(sorted_items, child, values, parent) | ||
1163 | |||
1164 | return sorted_items | ||
1165 | |||
1079 | row = 3 | 1166 | row = 3 |
1080 | self.screen.move(row, 0) | 1167 | self.screen.move(row, 0) |
1081 | self.screen.clrtobot() | 1168 | self.screen.clrtobot() |
1082 | stats = self.stats.get(self._display_guests) | 1169 | stats = self.stats.get(self._display_guests) |
1083 | 1170 | total = 0. | |
1084 | def sortCurAvg(x): | 1171 | ctotal = 0. |
1085 | # sort by current events if available | 1172 | for key, values in stats.items(): |
1086 | if stats[x][1]: | 1173 | if self._display_guests: |
1087 | return (-stats[x][1], -stats[x][0]) | 1174 | if self.get_gname_from_pid(key): |
1175 | total += values.value | ||
1176 | continue | ||
1177 | if not key.find(' ') != -1: | ||
1178 | total += values.value | ||
1088 | else: | 1179 | else: |
1089 | return (0, -stats[x][0]) | 1180 | ctotal += values.value |
1181 | if total == 0.: | ||
1182 | # we don't have any fields, or all non-child events are filtered | ||
1183 | total = ctotal | ||
1090 | 1184 | ||
1091 | def sortTotal(x): | 1185 | # print events |
1092 | # sort by totals | ||
1093 | return (0, -stats[x][0]) | ||
1094 | total = 0. | ||
1095 | for key in stats.keys(): | ||
1096 | if key.find('(') is -1: | ||
1097 | total += stats[key][0] | ||
1098 | if self._sorting == SORT_DEFAULT: | ||
1099 | sortkey = sortCurAvg | ||
1100 | else: | ||
1101 | sortkey = sortTotal | ||
1102 | tavg = 0 | 1186 | tavg = 0 |
1103 | for key in sorted(stats.keys(), key=sortkey): | 1187 | tcur = 0 |
1104 | if row >= self.screen.getmaxyx()[0] - 1: | 1188 | for key, values in get_sorted_events(self, stats): |
1105 | break | 1189 | if row >= self.screen.getmaxyx()[0] - 1 or values == (0, 0): |
1106 | values = stats[key] | ||
1107 | if not values[0] and not values[1]: | ||
1108 | break | 1190 | break |
1109 | if values[0] is not None: | 1191 | if self._display_guests: |
1110 | cur = int(round(values[1] / sleeptime)) if values[1] else '' | 1192 | key = self.get_gname_from_pid(key) |
1111 | if self._display_guests: | 1193 | if not key: |
1112 | key = self.get_gname_from_pid(key) | 1194 | continue |
1113 | self.screen.addstr(row, 1, '%-40s %10d%7.1f %8s' % | 1195 | cur = int(round(values.delta / sleeptime)) if values.delta else '' |
1114 | (key, values[0], values[0] * 100 / total, | 1196 | if key[0] != ' ': |
1115 | cur)) | 1197 | if values.delta: |
1116 | if cur is not '' and key.find('(') is -1: | 1198 | tcur += values.delta |
1117 | tavg += cur | 1199 | ptotal = values.value |
1200 | ltotal = total | ||
1201 | else: | ||
1202 | ltotal = ptotal | ||
1203 | self.screen.addstr(row, 1, '%-40s %10d%7.1f %8s' % (key, | ||
1204 | values.value, | ||
1205 | values.value * 100 / float(ltotal), cur)) | ||
1118 | row += 1 | 1206 | row += 1 |
1119 | if row == 3: | 1207 | if row == 3: |
1120 | self.screen.addstr(4, 1, 'No matching events reported yet') | 1208 | self.screen.addstr(4, 1, 'No matching events reported yet') |
1121 | else: | 1209 | if row > 4: |
1210 | tavg = int(round(tcur / sleeptime)) if tcur > 0 else '' | ||
1122 | self.screen.addstr(row, 1, '%-40s %10d %8s' % | 1211 | self.screen.addstr(row, 1, '%-40s %10d %8s' % |
1123 | ('Total', total, tavg if tavg else ''), | 1212 | ('Total', total, tavg), curses.A_BOLD) |
1124 | curses.A_BOLD) | ||
1125 | self.screen.refresh() | 1213 | self.screen.refresh() |
1126 | 1214 | ||
1127 | def show_msg(self, text): | 1215 | def _show_msg(self, text): |
1128 | """Display message centered text and exit on key press""" | 1216 | """Display message centered text and exit on key press""" |
1129 | hint = 'Press any key to continue' | 1217 | hint = 'Press any key to continue' |
1130 | curses.cbreak() | 1218 | curses.cbreak() |
@@ -1139,16 +1227,16 @@ class Tui(object): | |||
1139 | curses.A_STANDOUT) | 1227 | curses.A_STANDOUT) |
1140 | self.screen.getkey() | 1228 | self.screen.getkey() |
1141 | 1229 | ||
1142 | def show_help_interactive(self): | 1230 | def _show_help_interactive(self): |
1143 | """Display help with list of interactive commands""" | 1231 | """Display help with list of interactive commands""" |
1144 | msg = (' b toggle events by guests (debugfs only, honors' | 1232 | msg = (' b toggle events by guests (debugfs only, honors' |
1145 | ' filters)', | 1233 | ' filters)', |
1146 | ' c clear filter', | 1234 | ' c clear filter', |
1147 | ' f filter by regular expression', | 1235 | ' f filter by regular expression', |
1148 | ' g filter by guest name', | 1236 | ' g filter by guest name/PID', |
1149 | ' h display interactive commands reference', | 1237 | ' h display interactive commands reference', |
1150 | ' o toggle sorting order (Total vs CurAvg/s)', | 1238 | ' o toggle sorting order (Total vs CurAvg/s)', |
1151 | ' p filter by PID', | 1239 | ' p filter by guest name/PID', |
1152 | ' q quit', | 1240 | ' q quit', |
1153 | ' r reset stats', | 1241 | ' r reset stats', |
1154 | ' s set update interval', | 1242 | ' s set update interval', |
@@ -1165,14 +1253,15 @@ class Tui(object): | |||
1165 | self.screen.addstr(row, 0, line) | 1253 | self.screen.addstr(row, 0, line) |
1166 | row += 1 | 1254 | row += 1 |
1167 | self.screen.getkey() | 1255 | self.screen.getkey() |
1168 | self.refresh_header() | 1256 | self._refresh_header() |
1169 | 1257 | ||
1170 | def show_filter_selection(self): | 1258 | def _show_filter_selection(self): |
1171 | """Draws filter selection mask. | 1259 | """Draws filter selection mask. |
1172 | 1260 | ||
1173 | Asks for a valid regex and sets the fields filter accordingly. | 1261 | Asks for a valid regex and sets the fields filter accordingly. |
1174 | 1262 | ||
1175 | """ | 1263 | """ |
1264 | msg = '' | ||
1176 | while True: | 1265 | while True: |
1177 | self.screen.erase() | 1266 | self.screen.erase() |
1178 | self.screen.addstr(0, 0, | 1267 | self.screen.addstr(0, 0, |
@@ -1181,61 +1270,25 @@ class Tui(object): | |||
1181 | self.screen.addstr(2, 0, | 1270 | self.screen.addstr(2, 0, |
1182 | "Current regex: {0}" | 1271 | "Current regex: {0}" |
1183 | .format(self.stats.fields_filter)) | 1272 | .format(self.stats.fields_filter)) |
1273 | self.screen.addstr(5, 0, msg) | ||
1184 | self.screen.addstr(3, 0, "New regex: ") | 1274 | self.screen.addstr(3, 0, "New regex: ") |
1185 | curses.echo() | 1275 | curses.echo() |
1186 | regex = self.screen.getstr().decode(ENCODING) | 1276 | regex = self.screen.getstr().decode(ENCODING) |
1187 | curses.noecho() | 1277 | curses.noecho() |
1188 | if len(regex) == 0: | 1278 | if len(regex) == 0: |
1189 | self.stats.fields_filter = DEFAULT_REGEX | 1279 | self.stats.fields_filter = '' |
1190 | self.refresh_header() | 1280 | self._refresh_header() |
1191 | return | 1281 | return |
1192 | try: | 1282 | try: |
1193 | re.compile(regex) | 1283 | re.compile(regex) |
1194 | self.stats.fields_filter = regex | 1284 | self.stats.fields_filter = regex |
1195 | self.refresh_header() | 1285 | self._refresh_header() |
1196 | return | 1286 | return |
1197 | except re.error: | 1287 | except re.error: |
1288 | msg = '"' + regex + '": Not a valid regular expression' | ||
1198 | continue | 1289 | continue |
1199 | 1290 | ||
1200 | def show_vm_selection_by_pid(self): | 1291 | def _show_set_update_interval(self): |
1201 | """Draws PID selection mask. | ||
1202 | |||
1203 | Asks for a pid until a valid pid or 0 has been entered. | ||
1204 | |||
1205 | """ | ||
1206 | msg = '' | ||
1207 | while True: | ||
1208 | self.screen.erase() | ||
1209 | self.screen.addstr(0, 0, | ||
1210 | 'Show statistics for specific pid.', | ||
1211 | curses.A_BOLD) | ||
1212 | self.screen.addstr(1, 0, | ||
1213 | 'This might limit the shown data to the trace ' | ||
1214 | 'statistics.') | ||
1215 | self.screen.addstr(5, 0, msg) | ||
1216 | self.print_all_gnames(7) | ||
1217 | |||
1218 | curses.echo() | ||
1219 | self.screen.addstr(3, 0, "Pid [0 or pid]: ") | ||
1220 | pid = self.screen.getstr().decode(ENCODING) | ||
1221 | curses.noecho() | ||
1222 | |||
1223 | try: | ||
1224 | if len(pid) > 0: | ||
1225 | pid = int(pid) | ||
1226 | if pid != 0 and not os.path.isdir(os.path.join('/proc/', | ||
1227 | str(pid))): | ||
1228 | msg = '"' + str(pid) + '": Not a running process' | ||
1229 | continue | ||
1230 | else: | ||
1231 | pid = 0 | ||
1232 | self.refresh_header(pid) | ||
1233 | self.update_pid(pid) | ||
1234 | break | ||
1235 | except ValueError: | ||
1236 | msg = '"' + str(pid) + '": Not a valid pid' | ||
1237 | |||
1238 | def show_set_update_interval(self): | ||
1239 | """Draws update interval selection mask.""" | 1292 | """Draws update interval selection mask.""" |
1240 | msg = '' | 1293 | msg = '' |
1241 | while True: | 1294 | while True: |
@@ -1265,60 +1318,67 @@ class Tui(object): | |||
1265 | 1318 | ||
1266 | except ValueError: | 1319 | except ValueError: |
1267 | msg = '"' + str(val) + '": Invalid value' | 1320 | msg = '"' + str(val) + '": Invalid value' |
1268 | self.refresh_header() | 1321 | self._refresh_header() |
1269 | 1322 | ||
1270 | def show_vm_selection_by_guest_name(self): | 1323 | def _show_vm_selection_by_guest(self): |
1271 | """Draws guest selection mask. | 1324 | """Draws guest selection mask. |
1272 | 1325 | ||
1273 | Asks for a guest name until a valid guest name or '' is entered. | 1326 | Asks for a guest name or pid until a valid guest name or '' is entered. |
1274 | 1327 | ||
1275 | """ | 1328 | """ |
1276 | msg = '' | 1329 | msg = '' |
1277 | while True: | 1330 | while True: |
1278 | self.screen.erase() | 1331 | self.screen.erase() |
1279 | self.screen.addstr(0, 0, | 1332 | self.screen.addstr(0, 0, |
1280 | 'Show statistics for specific guest.', | 1333 | 'Show statistics for specific guest or pid.', |
1281 | curses.A_BOLD) | 1334 | curses.A_BOLD) |
1282 | self.screen.addstr(1, 0, | 1335 | self.screen.addstr(1, 0, |
1283 | 'This might limit the shown data to the trace ' | 1336 | 'This might limit the shown data to the trace ' |
1284 | 'statistics.') | 1337 | 'statistics.') |
1285 | self.screen.addstr(5, 0, msg) | 1338 | self.screen.addstr(5, 0, msg) |
1286 | self.print_all_gnames(7) | 1339 | self._print_all_gnames(7) |
1287 | curses.echo() | 1340 | curses.echo() |
1288 | self.screen.addstr(3, 0, "Guest [ENTER or guest]: ") | 1341 | curses.curs_set(1) |
1289 | gname = self.screen.getstr().decode(ENCODING) | 1342 | self.screen.addstr(3, 0, "Guest or pid [ENTER exits]: ") |
1343 | guest = self.screen.getstr().decode(ENCODING) | ||
1290 | curses.noecho() | 1344 | curses.noecho() |
1291 | 1345 | ||
1292 | if not gname: | 1346 | pid = 0 |
1293 | self.refresh_header(0) | 1347 | if not guest or guest == '0': |
1294 | self.update_pid(0) | ||
1295 | break | 1348 | break |
1296 | else: | 1349 | if guest.isdigit(): |
1297 | pids = [] | 1350 | if not os.path.isdir(os.path.join('/proc/', guest)): |
1298 | try: | 1351 | msg = '"' + guest + '": Not a running process' |
1299 | pids = self.get_pid_from_gname(gname) | ||
1300 | except: | ||
1301 | msg = '"' + gname + '": Internal error while searching, ' \ | ||
1302 | 'use pid filter instead' | ||
1303 | continue | ||
1304 | if len(pids) == 0: | ||
1305 | msg = '"' + gname + '": Not an active guest' | ||
1306 | continue | 1352 | continue |
1307 | if len(pids) > 1: | 1353 | pid = int(guest) |
1308 | msg = '"' + gname + '": Multiple matches found, use pid ' \ | ||
1309 | 'filter instead' | ||
1310 | continue | ||
1311 | self.refresh_header(pids[0]) | ||
1312 | self.update_pid(pids[0]) | ||
1313 | break | 1354 | break |
1355 | pids = [] | ||
1356 | try: | ||
1357 | pids = self.get_pid_from_gname(guest) | ||
1358 | except: | ||
1359 | msg = '"' + guest + '": Internal error while searching, ' \ | ||
1360 | 'use pid filter instead' | ||
1361 | continue | ||
1362 | if len(pids) == 0: | ||
1363 | msg = '"' + guest + '": Not an active guest' | ||
1364 | continue | ||
1365 | if len(pids) > 1: | ||
1366 | msg = '"' + guest + '": Multiple matches found, use pid ' \ | ||
1367 | 'filter instead' | ||
1368 | continue | ||
1369 | pid = pids[0] | ||
1370 | break | ||
1371 | curses.curs_set(0) | ||
1372 | self._refresh_header(pid) | ||
1373 | self._update_pid(pid) | ||
1314 | 1374 | ||
1315 | def show_stats(self): | 1375 | def show_stats(self): |
1316 | """Refreshes the screen and processes user input.""" | 1376 | """Refreshes the screen and processes user input.""" |
1317 | sleeptime = self._delay_initial | 1377 | sleeptime = self._delay_initial |
1318 | self.refresh_header() | 1378 | self._refresh_header() |
1319 | start = 0.0 # result based on init value never appears on screen | 1379 | start = 0.0 # result based on init value never appears on screen |
1320 | while True: | 1380 | while True: |
1321 | self.refresh_body(time.time() - start) | 1381 | self._refresh_body(time.time() - start) |
1322 | curses.halfdelay(int(sleeptime * 10)) | 1382 | curses.halfdelay(int(sleeptime * 10)) |
1323 | start = time.time() | 1383 | start = time.time() |
1324 | sleeptime = self._delay_regular | 1384 | sleeptime = self._delay_regular |
@@ -1327,47 +1387,39 @@ class Tui(object): | |||
1327 | if char == 'b': | 1387 | if char == 'b': |
1328 | self._display_guests = not self._display_guests | 1388 | self._display_guests = not self._display_guests |
1329 | if self.stats.toggle_display_guests(self._display_guests): | 1389 | if self.stats.toggle_display_guests(self._display_guests): |
1330 | self.show_msg(['Command not available with tracepoints' | 1390 | self._show_msg(['Command not available with ' |
1331 | ' enabled', 'Restart with debugfs only ' | 1391 | 'tracepoints enabled', 'Restart with ' |
1332 | '(see option \'-d\') and try again!']) | 1392 | 'debugfs only (see option \'-d\') and ' |
1393 | 'try again!']) | ||
1333 | self._display_guests = not self._display_guests | 1394 | self._display_guests = not self._display_guests |
1334 | self.refresh_header() | 1395 | self._refresh_header() |
1335 | if char == 'c': | 1396 | if char == 'c': |
1336 | self.stats.fields_filter = DEFAULT_REGEX | 1397 | self.stats.fields_filter = '' |
1337 | self.refresh_header(0) | 1398 | self._refresh_header(0) |
1338 | self.update_pid(0) | 1399 | self._update_pid(0) |
1339 | if char == 'f': | 1400 | if char == 'f': |
1340 | curses.curs_set(1) | 1401 | curses.curs_set(1) |
1341 | self.show_filter_selection() | 1402 | self._show_filter_selection() |
1342 | curses.curs_set(0) | 1403 | curses.curs_set(0) |
1343 | sleeptime = self._delay_initial | 1404 | sleeptime = self._delay_initial |
1344 | if char == 'g': | 1405 | if char == 'g' or char == 'p': |
1345 | curses.curs_set(1) | 1406 | self._show_vm_selection_by_guest() |
1346 | self.show_vm_selection_by_guest_name() | ||
1347 | curses.curs_set(0) | ||
1348 | sleeptime = self._delay_initial | 1407 | sleeptime = self._delay_initial |
1349 | if char == 'h': | 1408 | if char == 'h': |
1350 | self.show_help_interactive() | 1409 | self._show_help_interactive() |
1351 | if char == 'o': | 1410 | if char == 'o': |
1352 | self._sorting = not self._sorting | 1411 | self._sorting = not self._sorting |
1353 | if char == 'p': | ||
1354 | curses.curs_set(1) | ||
1355 | self.show_vm_selection_by_pid() | ||
1356 | curses.curs_set(0) | ||
1357 | sleeptime = self._delay_initial | ||
1358 | if char == 'q': | 1412 | if char == 'q': |
1359 | break | 1413 | break |
1360 | if char == 'r': | 1414 | if char == 'r': |
1361 | self.stats.reset() | 1415 | self.stats.reset() |
1362 | if char == 's': | 1416 | if char == 's': |
1363 | curses.curs_set(1) | 1417 | curses.curs_set(1) |
1364 | self.show_set_update_interval() | 1418 | self._show_set_update_interval() |
1365 | curses.curs_set(0) | 1419 | curses.curs_set(0) |
1366 | sleeptime = self._delay_initial | 1420 | sleeptime = self._delay_initial |
1367 | if char == 'x': | 1421 | if char == 'x': |
1368 | self.update_drilldown() | 1422 | self.stats.child_events = not self.stats.child_events |
1369 | # prevents display of current values on next refresh | ||
1370 | self.stats.get(self._display_guests) | ||
1371 | except KeyboardInterrupt: | 1423 | except KeyboardInterrupt: |
1372 | break | 1424 | break |
1373 | except curses.error: | 1425 | except curses.error: |
@@ -1380,9 +1432,9 @@ def batch(stats): | |||
1380 | s = stats.get() | 1432 | s = stats.get() |
1381 | time.sleep(1) | 1433 | time.sleep(1) |
1382 | s = stats.get() | 1434 | s = stats.get() |
1383 | for key in sorted(s.keys()): | 1435 | for key, values in sorted(s.items()): |
1384 | values = s[key] | 1436 | print('%-42s%10d%10d' % (key.split(' ')[0], values.value, |
1385 | print('%-42s%10d%10d' % (key, values[0], values[1])) | 1437 | values.delta)) |
1386 | except KeyboardInterrupt: | 1438 | except KeyboardInterrupt: |
1387 | pass | 1439 | pass |
1388 | 1440 | ||
@@ -1392,14 +1444,14 @@ def log(stats): | |||
1392 | keys = sorted(stats.get().keys()) | 1444 | keys = sorted(stats.get().keys()) |
1393 | 1445 | ||
1394 | def banner(): | 1446 | def banner(): |
1395 | for k in keys: | 1447 | for key in keys: |
1396 | print(k, end=' ') | 1448 | print(key.split(' ')[0], end=' ') |
1397 | print() | 1449 | print() |
1398 | 1450 | ||
1399 | def statline(): | 1451 | def statline(): |
1400 | s = stats.get() | 1452 | s = stats.get() |
1401 | for k in keys: | 1453 | for key in keys: |
1402 | print(' %9d' % s[k][1], end=' ') | 1454 | print(' %9d' % s[key].delta, end=' ') |
1403 | print() | 1455 | print() |
1404 | line = 0 | 1456 | line = 0 |
1405 | banner_repeat = 20 | 1457 | banner_repeat = 20 |
@@ -1504,7 +1556,7 @@ Press any other key to refresh statistics immediately. | |||
1504 | ) | 1556 | ) |
1505 | optparser.add_option('-f', '--fields', | 1557 | optparser.add_option('-f', '--fields', |
1506 | action='store', | 1558 | action='store', |
1507 | default=DEFAULT_REGEX, | 1559 | default='', |
1508 | dest='fields', | 1560 | dest='fields', |
1509 | help='''fields to display (regex) | 1561 | help='''fields to display (regex) |
1510 | "-f help" for a list of available events''', | 1562 | "-f help" for a list of available events''', |
@@ -1539,17 +1591,6 @@ Press any other key to refresh statistics immediately. | |||
1539 | 1591 | ||
1540 | def check_access(options): | 1592 | def check_access(options): |
1541 | """Exits if the current user can't access all needed directories.""" | 1593 | """Exits if the current user can't access all needed directories.""" |
1542 | if not os.path.exists('/sys/kernel/debug'): | ||
1543 | sys.stderr.write('Please enable CONFIG_DEBUG_FS in your kernel.') | ||
1544 | sys.exit(1) | ||
1545 | |||
1546 | if not os.path.exists(PATH_DEBUGFS_KVM): | ||
1547 | sys.stderr.write("Please make sure, that debugfs is mounted and " | ||
1548 | "readable by the current user:\n" | ||
1549 | "('mount -t debugfs debugfs /sys/kernel/debug')\n" | ||
1550 | "Also ensure, that the kvm modules are loaded.\n") | ||
1551 | sys.exit(1) | ||
1552 | |||
1553 | if not os.path.exists(PATH_DEBUGFS_TRACING) and (options.tracepoints or | 1594 | if not os.path.exists(PATH_DEBUGFS_TRACING) and (options.tracepoints or |
1554 | not options.debugfs): | 1595 | not options.debugfs): |
1555 | sys.stderr.write("Please enable CONFIG_TRACING in your kernel " | 1596 | sys.stderr.write("Please enable CONFIG_TRACING in your kernel " |
@@ -1567,7 +1608,33 @@ def check_access(options): | |||
1567 | return options | 1608 | return options |
1568 | 1609 | ||
1569 | 1610 | ||
1611 | def assign_globals(): | ||
1612 | global PATH_DEBUGFS_KVM | ||
1613 | global PATH_DEBUGFS_TRACING | ||
1614 | |||
1615 | debugfs = '' | ||
1616 | for line in file('/proc/mounts'): | ||
1617 | if line.split(' ')[0] == 'debugfs': | ||
1618 | debugfs = line.split(' ')[1] | ||
1619 | break | ||
1620 | if debugfs == '': | ||
1621 | sys.stderr.write("Please make sure that CONFIG_DEBUG_FS is enabled in " | ||
1622 | "your kernel, mounted and\nreadable by the current " | ||
1623 | "user:\n" | ||
1624 | "('mount -t debugfs debugfs /sys/kernel/debug')\n") | ||
1625 | sys.exit(1) | ||
1626 | |||
1627 | PATH_DEBUGFS_KVM = os.path.join(debugfs, 'kvm') | ||
1628 | PATH_DEBUGFS_TRACING = os.path.join(debugfs, 'tracing') | ||
1629 | |||
1630 | if not os.path.exists(PATH_DEBUGFS_KVM): | ||
1631 | sys.stderr.write("Please make sure that CONFIG_KVM is enabled in " | ||
1632 | "your kernel and that the modules are loaded.\n") | ||
1633 | sys.exit(1) | ||
1634 | |||
1635 | |||
1570 | def main(): | 1636 | def main(): |
1637 | assign_globals() | ||
1571 | options = get_options() | 1638 | options = get_options() |
1572 | options = check_access(options) | 1639 | options = check_access(options) |
1573 | 1640 | ||
diff --git a/tools/kvm/kvm_stat/kvm_stat.txt b/tools/kvm/kvm_stat/kvm_stat.txt index b5b3810c9e94..0811d860fe75 100644 --- a/tools/kvm/kvm_stat/kvm_stat.txt +++ b/tools/kvm/kvm_stat/kvm_stat.txt | |||
@@ -35,13 +35,13 @@ INTERACTIVE COMMANDS | |||
35 | 35 | ||
36 | *f*:: filter by regular expression | 36 | *f*:: filter by regular expression |
37 | 37 | ||
38 | *g*:: filter by guest name | 38 | *g*:: filter by guest name/PID |
39 | 39 | ||
40 | *h*:: display interactive commands reference | 40 | *h*:: display interactive commands reference |
41 | 41 | ||
42 | *o*:: toggle sorting order (Total vs CurAvg/s) | 42 | *o*:: toggle sorting order (Total vs CurAvg/s) |
43 | 43 | ||
44 | *p*:: filter by PID | 44 | *p*:: filter by guest name/PID |
45 | 45 | ||
46 | *q*:: quit | 46 | *q*:: quit |
47 | 47 | ||
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c index 57254f5b2779..694abc628e9b 100644 --- a/tools/objtool/builtin-check.c +++ b/tools/objtool/builtin-check.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include "builtin.h" | 29 | #include "builtin.h" |
30 | #include "check.h" | 30 | #include "check.h" |
31 | 31 | ||
32 | bool no_fp, no_unreachable; | 32 | bool no_fp, no_unreachable, retpoline, module; |
33 | 33 | ||
34 | static const char * const check_usage[] = { | 34 | static const char * const check_usage[] = { |
35 | "objtool check [<options>] file.o", | 35 | "objtool check [<options>] file.o", |
@@ -39,6 +39,8 @@ static const char * const check_usage[] = { | |||
39 | const struct option check_options[] = { | 39 | const struct option check_options[] = { |
40 | OPT_BOOLEAN('f', "no-fp", &no_fp, "Skip frame pointer validation"), | 40 | OPT_BOOLEAN('f', "no-fp", &no_fp, "Skip frame pointer validation"), |
41 | OPT_BOOLEAN('u', "no-unreachable", &no_unreachable, "Skip 'unreachable instruction' warnings"), | 41 | OPT_BOOLEAN('u', "no-unreachable", &no_unreachable, "Skip 'unreachable instruction' warnings"), |
42 | OPT_BOOLEAN('r', "retpoline", &retpoline, "Validate retpoline assumptions"), | ||
43 | OPT_BOOLEAN('m', "module", &module, "Indicates the object will be part of a kernel module"), | ||
42 | OPT_END(), | 44 | OPT_END(), |
43 | }; | 45 | }; |
44 | 46 | ||
@@ -53,5 +55,5 @@ int cmd_check(int argc, const char **argv) | |||
53 | 55 | ||
54 | objname = argv[0]; | 56 | objname = argv[0]; |
55 | 57 | ||
56 | return check(objname, no_fp, no_unreachable, false); | 58 | return check(objname, false); |
57 | } | 59 | } |
diff --git a/tools/objtool/builtin-orc.c b/tools/objtool/builtin-orc.c index 91e8e19ff5e0..77ea2b97117d 100644 --- a/tools/objtool/builtin-orc.c +++ b/tools/objtool/builtin-orc.c | |||
@@ -25,7 +25,6 @@ | |||
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <string.h> | 27 | #include <string.h> |
28 | #include <subcmd/parse-options.h> | ||
29 | #include "builtin.h" | 28 | #include "builtin.h" |
30 | #include "check.h" | 29 | #include "check.h" |
31 | 30 | ||
@@ -36,9 +35,6 @@ static const char *orc_usage[] = { | |||
36 | NULL, | 35 | NULL, |
37 | }; | 36 | }; |
38 | 37 | ||
39 | extern const struct option check_options[]; | ||
40 | extern bool no_fp, no_unreachable; | ||
41 | |||
42 | int cmd_orc(int argc, const char **argv) | 38 | int cmd_orc(int argc, const char **argv) |
43 | { | 39 | { |
44 | const char *objname; | 40 | const char *objname; |
@@ -54,7 +50,7 @@ int cmd_orc(int argc, const char **argv) | |||
54 | 50 | ||
55 | objname = argv[0]; | 51 | objname = argv[0]; |
56 | 52 | ||
57 | return check(objname, no_fp, no_unreachable, true); | 53 | return check(objname, true); |
58 | } | 54 | } |
59 | 55 | ||
60 | if (!strcmp(argv[0], "dump")) { | 56 | if (!strcmp(argv[0], "dump")) { |
diff --git a/tools/objtool/builtin.h b/tools/objtool/builtin.h index dd526067fed5..28ff40e19a14 100644 --- a/tools/objtool/builtin.h +++ b/tools/objtool/builtin.h | |||
@@ -17,6 +17,11 @@ | |||
17 | #ifndef _BUILTIN_H | 17 | #ifndef _BUILTIN_H |
18 | #define _BUILTIN_H | 18 | #define _BUILTIN_H |
19 | 19 | ||
20 | #include <subcmd/parse-options.h> | ||
21 | |||
22 | extern const struct option check_options[]; | ||
23 | extern bool no_fp, no_unreachable, retpoline, module; | ||
24 | |||
20 | extern int cmd_check(int argc, const char **argv); | 25 | extern int cmd_check(int argc, const char **argv); |
21 | extern int cmd_orc(int argc, const char **argv); | 26 | extern int cmd_orc(int argc, const char **argv); |
22 | 27 | ||
diff --git a/tools/objtool/check.c b/tools/objtool/check.c index a8cb69a26576..92b6a2c21631 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <string.h> | 18 | #include <string.h> |
19 | #include <stdlib.h> | 19 | #include <stdlib.h> |
20 | 20 | ||
21 | #include "builtin.h" | ||
21 | #include "check.h" | 22 | #include "check.h" |
22 | #include "elf.h" | 23 | #include "elf.h" |
23 | #include "special.h" | 24 | #include "special.h" |
@@ -33,7 +34,6 @@ struct alternative { | |||
33 | }; | 34 | }; |
34 | 35 | ||
35 | const char *objname; | 36 | const char *objname; |
36 | static bool no_fp; | ||
37 | struct cfi_state initial_func_cfi; | 37 | struct cfi_state initial_func_cfi; |
38 | 38 | ||
39 | struct instruction *find_insn(struct objtool_file *file, | 39 | struct instruction *find_insn(struct objtool_file *file, |
@@ -497,6 +497,7 @@ static int add_jump_destinations(struct objtool_file *file) | |||
497 | * disguise, so convert them accordingly. | 497 | * disguise, so convert them accordingly. |
498 | */ | 498 | */ |
499 | insn->type = INSN_JUMP_DYNAMIC; | 499 | insn->type = INSN_JUMP_DYNAMIC; |
500 | insn->retpoline_safe = true; | ||
500 | continue; | 501 | continue; |
501 | } else { | 502 | } else { |
502 | /* sibling call */ | 503 | /* sibling call */ |
@@ -548,7 +549,8 @@ static int add_call_destinations(struct objtool_file *file) | |||
548 | if (!insn->call_dest && !insn->ignore) { | 549 | if (!insn->call_dest && !insn->ignore) { |
549 | WARN_FUNC("unsupported intra-function call", | 550 | WARN_FUNC("unsupported intra-function call", |
550 | insn->sec, insn->offset); | 551 | insn->sec, insn->offset); |
551 | WARN("If this is a retpoline, please patch it in with alternatives and annotate it with ANNOTATE_NOSPEC_ALTERNATIVE."); | 552 | if (retpoline) |
553 | WARN("If this is a retpoline, please patch it in with alternatives and annotate it with ANNOTATE_NOSPEC_ALTERNATIVE."); | ||
552 | return -1; | 554 | return -1; |
553 | } | 555 | } |
554 | 556 | ||
@@ -923,7 +925,11 @@ static struct rela *find_switch_table(struct objtool_file *file, | |||
923 | if (find_symbol_containing(file->rodata, text_rela->addend)) | 925 | if (find_symbol_containing(file->rodata, text_rela->addend)) |
924 | continue; | 926 | continue; |
925 | 927 | ||
926 | return find_rela_by_dest(file->rodata, text_rela->addend); | 928 | rodata_rela = find_rela_by_dest(file->rodata, text_rela->addend); |
929 | if (!rodata_rela) | ||
930 | continue; | ||
931 | |||
932 | return rodata_rela; | ||
927 | } | 933 | } |
928 | 934 | ||
929 | return NULL; | 935 | return NULL; |
@@ -1108,6 +1114,41 @@ static int read_unwind_hints(struct objtool_file *file) | |||
1108 | return 0; | 1114 | return 0; |
1109 | } | 1115 | } |
1110 | 1116 | ||
1117 | static int read_retpoline_hints(struct objtool_file *file) | ||
1118 | { | ||
1119 | struct section *sec; | ||
1120 | struct instruction *insn; | ||
1121 | struct rela *rela; | ||
1122 | |||
1123 | sec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe"); | ||
1124 | if (!sec) | ||
1125 | return 0; | ||
1126 | |||
1127 | list_for_each_entry(rela, &sec->rela_list, list) { | ||
1128 | if (rela->sym->type != STT_SECTION) { | ||
1129 | WARN("unexpected relocation symbol type in %s", sec->name); | ||
1130 | return -1; | ||
1131 | } | ||
1132 | |||
1133 | insn = find_insn(file, rela->sym->sec, rela->addend); | ||
1134 | if (!insn) { | ||
1135 | WARN("bad .discard.retpoline_safe entry"); | ||
1136 | return -1; | ||
1137 | } | ||
1138 | |||
1139 | if (insn->type != INSN_JUMP_DYNAMIC && | ||
1140 | insn->type != INSN_CALL_DYNAMIC) { | ||
1141 | WARN_FUNC("retpoline_safe hint not an indirect jump/call", | ||
1142 | insn->sec, insn->offset); | ||
1143 | return -1; | ||
1144 | } | ||
1145 | |||
1146 | insn->retpoline_safe = true; | ||
1147 | } | ||
1148 | |||
1149 | return 0; | ||
1150 | } | ||
1151 | |||
1111 | static int decode_sections(struct objtool_file *file) | 1152 | static int decode_sections(struct objtool_file *file) |
1112 | { | 1153 | { |
1113 | int ret; | 1154 | int ret; |
@@ -1146,6 +1187,10 @@ static int decode_sections(struct objtool_file *file) | |||
1146 | if (ret) | 1187 | if (ret) |
1147 | return ret; | 1188 | return ret; |
1148 | 1189 | ||
1190 | ret = read_retpoline_hints(file); | ||
1191 | if (ret) | ||
1192 | return ret; | ||
1193 | |||
1149 | return 0; | 1194 | return 0; |
1150 | } | 1195 | } |
1151 | 1196 | ||
@@ -1891,6 +1936,38 @@ static int validate_unwind_hints(struct objtool_file *file) | |||
1891 | return warnings; | 1936 | return warnings; |
1892 | } | 1937 | } |
1893 | 1938 | ||
1939 | static int validate_retpoline(struct objtool_file *file) | ||
1940 | { | ||
1941 | struct instruction *insn; | ||
1942 | int warnings = 0; | ||
1943 | |||
1944 | for_each_insn(file, insn) { | ||
1945 | if (insn->type != INSN_JUMP_DYNAMIC && | ||
1946 | insn->type != INSN_CALL_DYNAMIC) | ||
1947 | continue; | ||
1948 | |||
1949 | if (insn->retpoline_safe) | ||
1950 | continue; | ||
1951 | |||
1952 | /* | ||
1953 | * .init.text code is ran before userspace and thus doesn't | ||
1954 | * strictly need retpolines, except for modules which are | ||
1955 | * loaded late, they very much do need retpoline in their | ||
1956 | * .init.text | ||
1957 | */ | ||
1958 | if (!strcmp(insn->sec->name, ".init.text") && !module) | ||
1959 | continue; | ||
1960 | |||
1961 | WARN_FUNC("indirect %s found in RETPOLINE build", | ||
1962 | insn->sec, insn->offset, | ||
1963 | insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call"); | ||
1964 | |||
1965 | warnings++; | ||
1966 | } | ||
1967 | |||
1968 | return warnings; | ||
1969 | } | ||
1970 | |||
1894 | static bool is_kasan_insn(struct instruction *insn) | 1971 | static bool is_kasan_insn(struct instruction *insn) |
1895 | { | 1972 | { |
1896 | return (insn->type == INSN_CALL && | 1973 | return (insn->type == INSN_CALL && |
@@ -2022,13 +2099,12 @@ static void cleanup(struct objtool_file *file) | |||
2022 | elf_close(file->elf); | 2099 | elf_close(file->elf); |
2023 | } | 2100 | } |
2024 | 2101 | ||
2025 | int check(const char *_objname, bool _no_fp, bool no_unreachable, bool orc) | 2102 | int check(const char *_objname, bool orc) |
2026 | { | 2103 | { |
2027 | struct objtool_file file; | 2104 | struct objtool_file file; |
2028 | int ret, warnings = 0; | 2105 | int ret, warnings = 0; |
2029 | 2106 | ||
2030 | objname = _objname; | 2107 | objname = _objname; |
2031 | no_fp = _no_fp; | ||
2032 | 2108 | ||
2033 | file.elf = elf_open(objname, orc ? O_RDWR : O_RDONLY); | 2109 | file.elf = elf_open(objname, orc ? O_RDWR : O_RDONLY); |
2034 | if (!file.elf) | 2110 | if (!file.elf) |
@@ -2052,6 +2128,13 @@ int check(const char *_objname, bool _no_fp, bool no_unreachable, bool orc) | |||
2052 | if (list_empty(&file.insn_list)) | 2128 | if (list_empty(&file.insn_list)) |
2053 | goto out; | 2129 | goto out; |
2054 | 2130 | ||
2131 | if (retpoline) { | ||
2132 | ret = validate_retpoline(&file); | ||
2133 | if (ret < 0) | ||
2134 | return ret; | ||
2135 | warnings += ret; | ||
2136 | } | ||
2137 | |||
2055 | ret = validate_functions(&file); | 2138 | ret = validate_functions(&file); |
2056 | if (ret < 0) | 2139 | if (ret < 0) |
2057 | goto out; | 2140 | goto out; |
diff --git a/tools/objtool/check.h b/tools/objtool/check.h index 23a1d065cae1..c6b68fcb926f 100644 --- a/tools/objtool/check.h +++ b/tools/objtool/check.h | |||
@@ -45,6 +45,7 @@ struct instruction { | |||
45 | unsigned char type; | 45 | unsigned char type; |
46 | unsigned long immediate; | 46 | unsigned long immediate; |
47 | bool alt_group, visited, dead_end, ignore, hint, save, restore, ignore_alts; | 47 | bool alt_group, visited, dead_end, ignore, hint, save, restore, ignore_alts; |
48 | bool retpoline_safe; | ||
48 | struct symbol *call_dest; | 49 | struct symbol *call_dest; |
49 | struct instruction *jump_dest; | 50 | struct instruction *jump_dest; |
50 | struct instruction *first_jump_src; | 51 | struct instruction *first_jump_src; |
@@ -63,7 +64,7 @@ struct objtool_file { | |||
63 | bool ignore_unreachables, c_file, hints; | 64 | bool ignore_unreachables, c_file, hints; |
64 | }; | 65 | }; |
65 | 66 | ||
66 | int check(const char *objname, bool no_fp, bool no_unreachable, bool orc); | 67 | int check(const char *objname, bool orc); |
67 | 68 | ||
68 | struct instruction *find_insn(struct objtool_file *file, | 69 | struct instruction *find_insn(struct objtool_file *file, |
69 | struct section *sec, unsigned long offset); | 70 | struct section *sec, unsigned long offset); |
diff --git a/tools/perf/Documentation/perf-kallsyms.txt b/tools/perf/Documentation/perf-kallsyms.txt index 954ea9e21236..cf9f4040ea5c 100644 --- a/tools/perf/Documentation/perf-kallsyms.txt +++ b/tools/perf/Documentation/perf-kallsyms.txt | |||
@@ -8,7 +8,7 @@ perf-kallsyms - Searches running kernel for symbols | |||
8 | SYNOPSIS | 8 | SYNOPSIS |
9 | -------- | 9 | -------- |
10 | [verse] | 10 | [verse] |
11 | 'perf kallsyms <options> symbol_name[,symbol_name...]' | 11 | 'perf kallsyms' [<options>] symbol_name[,symbol_name...] |
12 | 12 | ||
13 | DESCRIPTION | 13 | DESCRIPTION |
14 | ----------- | 14 | ----------- |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index bf4ca749d1ac..a217623fec2e 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -881,6 +881,15 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
881 | } | 881 | } |
882 | } | 882 | } |
883 | 883 | ||
884 | /* | ||
885 | * If we have just single event and are sending data | ||
886 | * through pipe, we need to force the ids allocation, | ||
887 | * because we synthesize event name through the pipe | ||
888 | * and need the id for that. | ||
889 | */ | ||
890 | if (data->is_pipe && rec->evlist->nr_entries == 1) | ||
891 | rec->opts.sample_id = true; | ||
892 | |||
884 | if (record__open(rec) != 0) { | 893 | if (record__open(rec) != 0) { |
885 | err = -1; | 894 | err = -1; |
886 | goto out_child; | 895 | goto out_child; |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 98bf9d32f222..54a4c152edb3 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -917,7 +917,7 @@ static void print_metric_csv(void *ctx, | |||
917 | char buf[64], *vals, *ends; | 917 | char buf[64], *vals, *ends; |
918 | 918 | ||
919 | if (unit == NULL || fmt == NULL) { | 919 | if (unit == NULL || fmt == NULL) { |
920 | fprintf(out, "%s%s%s%s", csv_sep, csv_sep, csv_sep, csv_sep); | 920 | fprintf(out, "%s%s", csv_sep, csv_sep); |
921 | return; | 921 | return; |
922 | } | 922 | } |
923 | snprintf(buf, sizeof(buf), fmt, val); | 923 | snprintf(buf, sizeof(buf), fmt, val); |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index b7c823ba8374..35ac016fcb98 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -991,7 +991,7 @@ static int perf_top_overwrite_fallback(struct perf_top *top, | |||
991 | evlist__for_each_entry(evlist, counter) | 991 | evlist__for_each_entry(evlist, counter) |
992 | counter->attr.write_backward = false; | 992 | counter->attr.write_backward = false; |
993 | opts->overwrite = false; | 993 | opts->overwrite = false; |
994 | ui__warning("fall back to non-overwrite mode\n"); | 994 | pr_debug2("fall back to non-overwrite mode\n"); |
995 | return 1; | 995 | return 1; |
996 | } | 996 | } |
997 | 997 | ||
diff --git a/tools/perf/perf.h b/tools/perf/perf.h index cfe46236a5e5..57b9b342d533 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h | |||
@@ -61,6 +61,7 @@ struct record_opts { | |||
61 | bool tail_synthesize; | 61 | bool tail_synthesize; |
62 | bool overwrite; | 62 | bool overwrite; |
63 | bool ignore_missing_thread; | 63 | bool ignore_missing_thread; |
64 | bool sample_id; | ||
64 | unsigned int freq; | 65 | unsigned int freq; |
65 | unsigned int mmap_pages; | 66 | unsigned int mmap_pages; |
66 | unsigned int auxtrace_mmap_pages; | 67 | unsigned int auxtrace_mmap_pages; |
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 286427975112..fbf927cf775d 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c | |||
@@ -327,7 +327,32 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) | |||
327 | if (!disasm_line__is_valid_jump(cursor, sym)) | 327 | if (!disasm_line__is_valid_jump(cursor, sym)) |
328 | return; | 328 | return; |
329 | 329 | ||
330 | /* | ||
331 | * This first was seen with a gcc function, _cpp_lex_token, that | ||
332 | * has the usual jumps: | ||
333 | * | ||
334 | * │1159e6c: ↓ jne 115aa32 <_cpp_lex_token@@Base+0xf92> | ||
335 | * | ||
336 | * I.e. jumps to a label inside that function (_cpp_lex_token), and | ||
337 | * those works, but also this kind: | ||
338 | * | ||
339 | * │1159e8b: ↓ jne c469be <cpp_named_operator2name@@Base+0xa72> | ||
340 | * | ||
341 | * I.e. jumps to another function, outside _cpp_lex_token, which | ||
342 | * are not being correctly handled generating as a side effect references | ||
343 | * to ab->offset[] entries that are set to NULL, so to make this code | ||
344 | * more robust, check that here. | ||
345 | * | ||
346 | * A proper fix for will be put in place, looking at the function | ||
347 | * name right after the '<' token and probably treating this like a | ||
348 | * 'call' instruction. | ||
349 | */ | ||
330 | target = ab->offsets[cursor->ops.target.offset]; | 350 | target = ab->offsets[cursor->ops.target.offset]; |
351 | if (target == NULL) { | ||
352 | ui_helpline__printf("WARN: jump target inconsistency, press 'o', ab->offsets[%#x] = NULL\n", | ||
353 | cursor->ops.target.offset); | ||
354 | return; | ||
355 | } | ||
331 | 356 | ||
332 | bcursor = browser_line(&cursor->al); | 357 | bcursor = browser_line(&cursor->al); |
333 | btarget = browser_line(target); | 358 | btarget = browser_line(target); |
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 9faf3b5367db..6470ea2aa25e 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c | |||
@@ -60,6 +60,12 @@ | |||
60 | #include "sane_ctype.h" | 60 | #include "sane_ctype.h" |
61 | #include "symbol/kallsyms.h" | 61 | #include "symbol/kallsyms.h" |
62 | 62 | ||
63 | static bool auxtrace__dont_decode(struct perf_session *session) | ||
64 | { | ||
65 | return !session->itrace_synth_opts || | ||
66 | session->itrace_synth_opts->dont_decode; | ||
67 | } | ||
68 | |||
63 | int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, | 69 | int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, |
64 | struct auxtrace_mmap_params *mp, | 70 | struct auxtrace_mmap_params *mp, |
65 | void *userpg, int fd) | 71 | void *userpg, int fd) |
@@ -762,6 +768,9 @@ int auxtrace_queues__process_index(struct auxtrace_queues *queues, | |||
762 | size_t i; | 768 | size_t i; |
763 | int err; | 769 | int err; |
764 | 770 | ||
771 | if (auxtrace__dont_decode(session)) | ||
772 | return 0; | ||
773 | |||
765 | list_for_each_entry(auxtrace_index, &session->auxtrace_index, list) { | 774 | list_for_each_entry(auxtrace_index, &session->auxtrace_index, list) { |
766 | for (i = 0; i < auxtrace_index->nr; i++) { | 775 | for (i = 0; i < auxtrace_index->nr; i++) { |
767 | ent = &auxtrace_index->entries[i]; | 776 | ent = &auxtrace_index->entries[i]; |
@@ -892,12 +901,6 @@ out_free: | |||
892 | return err; | 901 | return err; |
893 | } | 902 | } |
894 | 903 | ||
895 | static bool auxtrace__dont_decode(struct perf_session *session) | ||
896 | { | ||
897 | return !session->itrace_synth_opts || | ||
898 | session->itrace_synth_opts->dont_decode; | ||
899 | } | ||
900 | |||
901 | int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused, | 904 | int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused, |
902 | union perf_event *event, | 905 | union perf_event *event, |
903 | struct perf_session *session) | 906 | struct perf_session *session) |
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index 1e97937b03a9..6f09e4962dad 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c | |||
@@ -137,6 +137,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts, | |||
137 | struct perf_evsel *evsel; | 137 | struct perf_evsel *evsel; |
138 | bool use_sample_identifier = false; | 138 | bool use_sample_identifier = false; |
139 | bool use_comm_exec; | 139 | bool use_comm_exec; |
140 | bool sample_id = opts->sample_id; | ||
140 | 141 | ||
141 | /* | 142 | /* |
142 | * Set the evsel leader links before we configure attributes, | 143 | * Set the evsel leader links before we configure attributes, |
@@ -163,8 +164,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts, | |||
163 | * match the id. | 164 | * match the id. |
164 | */ | 165 | */ |
165 | use_sample_identifier = perf_can_sample_identifier(); | 166 | use_sample_identifier = perf_can_sample_identifier(); |
166 | evlist__for_each_entry(evlist, evsel) | 167 | sample_id = true; |
167 | perf_evsel__set_sample_id(evsel, use_sample_identifier); | ||
168 | } else if (evlist->nr_entries > 1) { | 168 | } else if (evlist->nr_entries > 1) { |
169 | struct perf_evsel *first = perf_evlist__first(evlist); | 169 | struct perf_evsel *first = perf_evlist__first(evlist); |
170 | 170 | ||
@@ -174,6 +174,10 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts, | |||
174 | use_sample_identifier = perf_can_sample_identifier(); | 174 | use_sample_identifier = perf_can_sample_identifier(); |
175 | break; | 175 | break; |
176 | } | 176 | } |
177 | sample_id = true; | ||
178 | } | ||
179 | |||
180 | if (sample_id) { | ||
177 | evlist__for_each_entry(evlist, evsel) | 181 | evlist__for_each_entry(evlist, evsel) |
178 | perf_evsel__set_sample_id(evsel, use_sample_identifier); | 182 | perf_evsel__set_sample_id(evsel, use_sample_identifier); |
179 | } | 183 | } |
diff --git a/tools/perf/util/trigger.h b/tools/perf/util/trigger.h index 370138e7e35c..88223bc7c82b 100644 --- a/tools/perf/util/trigger.h +++ b/tools/perf/util/trigger.h | |||
@@ -12,7 +12,7 @@ | |||
12 | * States and transits: | 12 | * States and transits: |
13 | * | 13 | * |
14 | * | 14 | * |
15 | * OFF--(on)--> READY --(hit)--> HIT | 15 | * OFF--> ON --> READY --(hit)--> HIT |
16 | * ^ | | 16 | * ^ | |
17 | * | (ready) | 17 | * | (ready) |
18 | * | | | 18 | * | | |
@@ -27,8 +27,9 @@ struct trigger { | |||
27 | volatile enum { | 27 | volatile enum { |
28 | TRIGGER_ERROR = -2, | 28 | TRIGGER_ERROR = -2, |
29 | TRIGGER_OFF = -1, | 29 | TRIGGER_OFF = -1, |
30 | TRIGGER_READY = 0, | 30 | TRIGGER_ON = 0, |
31 | TRIGGER_HIT = 1, | 31 | TRIGGER_READY = 1, |
32 | TRIGGER_HIT = 2, | ||
32 | } state; | 33 | } state; |
33 | const char *name; | 34 | const char *name; |
34 | }; | 35 | }; |
@@ -50,7 +51,7 @@ static inline bool trigger_is_error(struct trigger *t) | |||
50 | static inline void trigger_on(struct trigger *t) | 51 | static inline void trigger_on(struct trigger *t) |
51 | { | 52 | { |
52 | TRIGGER_WARN_ONCE(t, TRIGGER_OFF); | 53 | TRIGGER_WARN_ONCE(t, TRIGGER_OFF); |
53 | t->state = TRIGGER_READY; | 54 | t->state = TRIGGER_ON; |
54 | } | 55 | } |
55 | 56 | ||
56 | static inline void trigger_ready(struct trigger *t) | 57 | static inline void trigger_ready(struct trigger *t) |
diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c index 44ef9eba5a7a..6c645eb77d42 100644 --- a/tools/testing/radix-tree/idr-test.c +++ b/tools/testing/radix-tree/idr-test.c | |||
@@ -178,6 +178,55 @@ void idr_get_next_test(int base) | |||
178 | idr_destroy(&idr); | 178 | idr_destroy(&idr); |
179 | } | 179 | } |
180 | 180 | ||
181 | int idr_u32_cb(int id, void *ptr, void *data) | ||
182 | { | ||
183 | BUG_ON(id < 0); | ||
184 | BUG_ON(ptr != DUMMY_PTR); | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | void idr_u32_test1(struct idr *idr, u32 handle) | ||
189 | { | ||
190 | static bool warned = false; | ||
191 | u32 id = handle; | ||
192 | int sid = 0; | ||
193 | void *ptr; | ||
194 | |||
195 | BUG_ON(idr_alloc_u32(idr, DUMMY_PTR, &id, id, GFP_KERNEL)); | ||
196 | BUG_ON(id != handle); | ||
197 | BUG_ON(idr_alloc_u32(idr, DUMMY_PTR, &id, id, GFP_KERNEL) != -ENOSPC); | ||
198 | BUG_ON(id != handle); | ||
199 | if (!warned && id > INT_MAX) | ||
200 | printk("vvv Ignore these warnings\n"); | ||
201 | ptr = idr_get_next(idr, &sid); | ||
202 | if (id > INT_MAX) { | ||
203 | BUG_ON(ptr != NULL); | ||
204 | BUG_ON(sid != 0); | ||
205 | } else { | ||
206 | BUG_ON(ptr != DUMMY_PTR); | ||
207 | BUG_ON(sid != id); | ||
208 | } | ||
209 | idr_for_each(idr, idr_u32_cb, NULL); | ||
210 | if (!warned && id > INT_MAX) { | ||
211 | printk("^^^ Warnings over\n"); | ||
212 | warned = true; | ||
213 | } | ||
214 | BUG_ON(idr_remove(idr, id) != DUMMY_PTR); | ||
215 | BUG_ON(!idr_is_empty(idr)); | ||
216 | } | ||
217 | |||
218 | void idr_u32_test(int base) | ||
219 | { | ||
220 | DEFINE_IDR(idr); | ||
221 | idr_init_base(&idr, base); | ||
222 | idr_u32_test1(&idr, 10); | ||
223 | idr_u32_test1(&idr, 0x7fffffff); | ||
224 | idr_u32_test1(&idr, 0x80000000); | ||
225 | idr_u32_test1(&idr, 0x80000001); | ||
226 | idr_u32_test1(&idr, 0xffe00000); | ||
227 | idr_u32_test1(&idr, 0xffffffff); | ||
228 | } | ||
229 | |||
181 | void idr_checks(void) | 230 | void idr_checks(void) |
182 | { | 231 | { |
183 | unsigned long i; | 232 | unsigned long i; |
@@ -248,6 +297,9 @@ void idr_checks(void) | |||
248 | idr_get_next_test(0); | 297 | idr_get_next_test(0); |
249 | idr_get_next_test(1); | 298 | idr_get_next_test(1); |
250 | idr_get_next_test(4); | 299 | idr_get_next_test(4); |
300 | idr_u32_test(4); | ||
301 | idr_u32_test(1); | ||
302 | idr_u32_test(0); | ||
251 | } | 303 | } |
252 | 304 | ||
253 | /* | 305 | /* |
diff --git a/tools/testing/radix-tree/linux.c b/tools/testing/radix-tree/linux.c index 6903ccf35595..44a0d1ad4408 100644 --- a/tools/testing/radix-tree/linux.c +++ b/tools/testing/radix-tree/linux.c | |||
@@ -29,7 +29,7 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, int flags) | |||
29 | { | 29 | { |
30 | struct radix_tree_node *node; | 30 | struct radix_tree_node *node; |
31 | 31 | ||
32 | if (flags & __GFP_NOWARN) | 32 | if (!(flags & __GFP_DIRECT_RECLAIM)) |
33 | return NULL; | 33 | return NULL; |
34 | 34 | ||
35 | pthread_mutex_lock(&cachep->lock); | 35 | pthread_mutex_lock(&cachep->lock); |
@@ -73,10 +73,17 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp) | |||
73 | 73 | ||
74 | void *kmalloc(size_t size, gfp_t gfp) | 74 | void *kmalloc(size_t size, gfp_t gfp) |
75 | { | 75 | { |
76 | void *ret = malloc(size); | 76 | void *ret; |
77 | |||
78 | if (!(gfp & __GFP_DIRECT_RECLAIM)) | ||
79 | return NULL; | ||
80 | |||
81 | ret = malloc(size); | ||
77 | uatomic_inc(&nr_allocated); | 82 | uatomic_inc(&nr_allocated); |
78 | if (kmalloc_verbose) | 83 | if (kmalloc_verbose) |
79 | printf("Allocating %p from malloc\n", ret); | 84 | printf("Allocating %p from malloc\n", ret); |
85 | if (gfp & __GFP_ZERO) | ||
86 | memset(ret, 0, size); | ||
80 | return ret; | 87 | return ret; |
81 | } | 88 | } |
82 | 89 | ||
diff --git a/tools/testing/radix-tree/linux/compiler_types.h b/tools/testing/radix-tree/linux/compiler_types.h new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/tools/testing/radix-tree/linux/compiler_types.h | |||
diff --git a/tools/testing/radix-tree/linux/gfp.h b/tools/testing/radix-tree/linux/gfp.h index e9fff59dfd8a..e3201ccf54c3 100644 --- a/tools/testing/radix-tree/linux/gfp.h +++ b/tools/testing/radix-tree/linux/gfp.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #define __GFP_IO 0x40u | 11 | #define __GFP_IO 0x40u |
12 | #define __GFP_FS 0x80u | 12 | #define __GFP_FS 0x80u |
13 | #define __GFP_NOWARN 0x200u | 13 | #define __GFP_NOWARN 0x200u |
14 | #define __GFP_ZERO 0x8000u | ||
14 | #define __GFP_ATOMIC 0x80000u | 15 | #define __GFP_ATOMIC 0x80000u |
15 | #define __GFP_ACCOUNT 0x100000u | 16 | #define __GFP_ACCOUNT 0x100000u |
16 | #define __GFP_DIRECT_RECLAIM 0x400000u | 17 | #define __GFP_DIRECT_RECLAIM 0x400000u |
diff --git a/tools/testing/radix-tree/linux/slab.h b/tools/testing/radix-tree/linux/slab.h index 979baeec7e70..a037def0dec6 100644 --- a/tools/testing/radix-tree/linux/slab.h +++ b/tools/testing/radix-tree/linux/slab.h | |||
@@ -3,6 +3,7 @@ | |||
3 | #define SLAB_H | 3 | #define SLAB_H |
4 | 4 | ||
5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
6 | #include <linux/gfp.h> | ||
6 | 7 | ||
7 | #define SLAB_HWCACHE_ALIGN 1 | 8 | #define SLAB_HWCACHE_ALIGN 1 |
8 | #define SLAB_PANIC 2 | 9 | #define SLAB_PANIC 2 |
@@ -11,6 +12,11 @@ | |||
11 | void *kmalloc(size_t size, gfp_t); | 12 | void *kmalloc(size_t size, gfp_t); |
12 | void kfree(void *); | 13 | void kfree(void *); |
13 | 14 | ||
15 | static inline void *kzalloc(size_t size, gfp_t gfp) | ||
16 | { | ||
17 | return kmalloc(size, gfp | __GFP_ZERO); | ||
18 | } | ||
19 | |||
14 | void *kmem_cache_alloc(struct kmem_cache *cachep, int flags); | 20 | void *kmem_cache_alloc(struct kmem_cache *cachep, int flags); |
15 | void kmem_cache_free(struct kmem_cache *cachep, void *objp); | 21 | void kmem_cache_free(struct kmem_cache *cachep, void *objp); |
16 | 22 | ||
diff --git a/tools/testing/selftests/android/Makefile b/tools/testing/selftests/android/Makefile index 1a7492268993..f6304d2be90c 100644 --- a/tools/testing/selftests/android/Makefile +++ b/tools/testing/selftests/android/Makefile | |||
@@ -11,11 +11,11 @@ all: | |||
11 | BUILD_TARGET=$(OUTPUT)/$$DIR; \ | 11 | BUILD_TARGET=$(OUTPUT)/$$DIR; \ |
12 | mkdir $$BUILD_TARGET -p; \ | 12 | mkdir $$BUILD_TARGET -p; \ |
13 | make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\ | 13 | make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\ |
14 | #SUBDIR test prog name should be in the form: SUBDIR_test.sh | 14 | #SUBDIR test prog name should be in the form: SUBDIR_test.sh \ |
15 | TEST=$$DIR"_test.sh"; \ | 15 | TEST=$$DIR"_test.sh"; \ |
16 | if [ -e $$DIR/$$TEST ]; then | 16 | if [ -e $$DIR/$$TEST ]; then \ |
17 | rsync -a $$DIR/$$TEST $$BUILD_TARGET/; | 17 | rsync -a $$DIR/$$TEST $$BUILD_TARGET/; \ |
18 | fi | 18 | fi \ |
19 | done | 19 | done |
20 | 20 | ||
21 | override define RUN_TESTS | 21 | override define RUN_TESTS |
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index c73592fa3d41..437c0b1c9d21 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c | |||
@@ -11163,6 +11163,64 @@ static struct bpf_test tests[] = { | |||
11163 | .result = REJECT, | 11163 | .result = REJECT, |
11164 | .prog_type = BPF_PROG_TYPE_TRACEPOINT, | 11164 | .prog_type = BPF_PROG_TYPE_TRACEPOINT, |
11165 | }, | 11165 | }, |
11166 | { | ||
11167 | "xadd/w check unaligned stack", | ||
11168 | .insns = { | ||
11169 | BPF_MOV64_IMM(BPF_REG_0, 1), | ||
11170 | BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8), | ||
11171 | BPF_STX_XADD(BPF_W, BPF_REG_10, BPF_REG_0, -7), | ||
11172 | BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8), | ||
11173 | BPF_EXIT_INSN(), | ||
11174 | }, | ||
11175 | .result = REJECT, | ||
11176 | .errstr = "misaligned stack access off", | ||
11177 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | ||
11178 | }, | ||
11179 | { | ||
11180 | "xadd/w check unaligned map", | ||
11181 | .insns = { | ||
11182 | BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), | ||
11183 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
11184 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
11185 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
11186 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, | ||
11187 | BPF_FUNC_map_lookup_elem), | ||
11188 | BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), | ||
11189 | BPF_EXIT_INSN(), | ||
11190 | BPF_MOV64_IMM(BPF_REG_1, 1), | ||
11191 | BPF_STX_XADD(BPF_W, BPF_REG_0, BPF_REG_1, 3), | ||
11192 | BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, 3), | ||
11193 | BPF_EXIT_INSN(), | ||
11194 | }, | ||
11195 | .fixup_map1 = { 3 }, | ||
11196 | .result = REJECT, | ||
11197 | .errstr = "misaligned value access off", | ||
11198 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | ||
11199 | }, | ||
11200 | { | ||
11201 | "xadd/w check unaligned pkt", | ||
11202 | .insns = { | ||
11203 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | ||
11204 | offsetof(struct xdp_md, data)), | ||
11205 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | ||
11206 | offsetof(struct xdp_md, data_end)), | ||
11207 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | ||
11208 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | ||
11209 | BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 2), | ||
11210 | BPF_MOV64_IMM(BPF_REG_0, 99), | ||
11211 | BPF_JMP_IMM(BPF_JA, 0, 0, 6), | ||
11212 | BPF_MOV64_IMM(BPF_REG_0, 1), | ||
11213 | BPF_ST_MEM(BPF_W, BPF_REG_2, 0, 0), | ||
11214 | BPF_ST_MEM(BPF_W, BPF_REG_2, 3, 0), | ||
11215 | BPF_STX_XADD(BPF_W, BPF_REG_2, BPF_REG_0, 1), | ||
11216 | BPF_STX_XADD(BPF_W, BPF_REG_2, BPF_REG_0, 2), | ||
11217 | BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_2, 1), | ||
11218 | BPF_EXIT_INSN(), | ||
11219 | }, | ||
11220 | .result = REJECT, | ||
11221 | .errstr = "BPF_XADD stores into R2 packet", | ||
11222 | .prog_type = BPF_PROG_TYPE_XDP, | ||
11223 | }, | ||
11166 | }; | 11224 | }; |
11167 | 11225 | ||
11168 | static int probe_filter_length(const struct bpf_insn *fp) | 11226 | static int probe_filter_length(const struct bpf_insn *fp) |
diff --git a/tools/testing/selftests/futex/Makefile b/tools/testing/selftests/futex/Makefile index cea4adcd42b8..a63e8453984d 100644 --- a/tools/testing/selftests/futex/Makefile +++ b/tools/testing/selftests/futex/Makefile | |||
@@ -12,9 +12,9 @@ all: | |||
12 | BUILD_TARGET=$(OUTPUT)/$$DIR; \ | 12 | BUILD_TARGET=$(OUTPUT)/$$DIR; \ |
13 | mkdir $$BUILD_TARGET -p; \ | 13 | mkdir $$BUILD_TARGET -p; \ |
14 | make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\ | 14 | make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\ |
15 | if [ -e $$DIR/$(TEST_PROGS) ]; then | 15 | if [ -e $$DIR/$(TEST_PROGS) ]; then \ |
16 | rsync -a $$DIR/$(TEST_PROGS) $$BUILD_TARGET/; | 16 | rsync -a $$DIR/$(TEST_PROGS) $$BUILD_TARGET/; \ |
17 | fi | 17 | fi \ |
18 | done | 18 | done |
19 | 19 | ||
20 | override define RUN_TESTS | 20 | override define RUN_TESTS |
diff --git a/tools/testing/selftests/memfd/config b/tools/testing/selftests/memfd/config new file mode 100644 index 000000000000..835c7f4dadcd --- /dev/null +++ b/tools/testing/selftests/memfd/config | |||
@@ -0,0 +1 @@ | |||
CONFIG_FUSE_FS=m | |||
diff --git a/tools/testing/selftests/memory-hotplug/Makefile b/tools/testing/selftests/memory-hotplug/Makefile index 86636d207adf..686da510f989 100644 --- a/tools/testing/selftests/memory-hotplug/Makefile +++ b/tools/testing/selftests/memory-hotplug/Makefile | |||
@@ -4,8 +4,9 @@ all: | |||
4 | include ../lib.mk | 4 | include ../lib.mk |
5 | 5 | ||
6 | TEST_PROGS := mem-on-off-test.sh | 6 | TEST_PROGS := mem-on-off-test.sh |
7 | override RUN_TESTS := ./mem-on-off-test.sh -r 2 && echo "selftests: memory-hotplug [PASS]" || echo "selftests: memory-hotplug [FAIL]" | 7 | override RUN_TESTS := @./mem-on-off-test.sh -r 2 && echo "selftests: memory-hotplug [PASS]" || echo "selftests: memory-hotplug [FAIL]" |
8 | override EMIT_TESTS := echo "$(RUN_TESTS)" | 8 | |
9 | override EMIT_TESTS := echo "$(subst @,,$(RUN_TESTS))" | ||
9 | 10 | ||
10 | run_full_test: | 11 | run_full_test: |
11 | @/bin/bash ./mem-on-off-test.sh && echo "memory-hotplug selftests: [PASS]" || echo "memory-hotplug selftests: [FAIL]" | 12 | @/bin/bash ./mem-on-off-test.sh && echo "memory-hotplug selftests: [PASS]" || echo "memory-hotplug selftests: [FAIL]" |
diff --git a/tools/testing/selftests/powerpc/mm/subpage_prot.c b/tools/testing/selftests/powerpc/mm/subpage_prot.c index 35ade7406dcd..3ae77ba93208 100644 --- a/tools/testing/selftests/powerpc/mm/subpage_prot.c +++ b/tools/testing/selftests/powerpc/mm/subpage_prot.c | |||
@@ -135,6 +135,16 @@ static int run_test(void *addr, unsigned long size) | |||
135 | return 0; | 135 | return 0; |
136 | } | 136 | } |
137 | 137 | ||
138 | static int syscall_available(void) | ||
139 | { | ||
140 | int rc; | ||
141 | |||
142 | errno = 0; | ||
143 | rc = syscall(__NR_subpage_prot, 0, 0, 0); | ||
144 | |||
145 | return rc == 0 || (errno != ENOENT && errno != ENOSYS); | ||
146 | } | ||
147 | |||
138 | int test_anon(void) | 148 | int test_anon(void) |
139 | { | 149 | { |
140 | unsigned long align; | 150 | unsigned long align; |
@@ -145,6 +155,8 @@ int test_anon(void) | |||
145 | void *mallocblock; | 155 | void *mallocblock; |
146 | unsigned long mallocsize; | 156 | unsigned long mallocsize; |
147 | 157 | ||
158 | SKIP_IF(!syscall_available()); | ||
159 | |||
148 | if (getpagesize() != 0x10000) { | 160 | if (getpagesize() != 0x10000) { |
149 | fprintf(stderr, "Kernel page size must be 64K!\n"); | 161 | fprintf(stderr, "Kernel page size must be 64K!\n"); |
150 | return 1; | 162 | return 1; |
@@ -180,6 +192,8 @@ int test_file(void) | |||
180 | off_t filesize; | 192 | off_t filesize; |
181 | int fd; | 193 | int fd; |
182 | 194 | ||
195 | SKIP_IF(!syscall_available()); | ||
196 | |||
183 | fd = open(file_name, O_RDWR); | 197 | fd = open(file_name, O_RDWR); |
184 | if (fd == -1) { | 198 | if (fd == -1) { |
185 | perror("failed to open file"); | 199 | perror("failed to open file"); |
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile index a23453943ad2..5c72ff978f27 100644 --- a/tools/testing/selftests/powerpc/tm/Makefile +++ b/tools/testing/selftests/powerpc/tm/Makefile | |||
@@ -16,7 +16,7 @@ $(OUTPUT)/tm-syscall: tm-syscall-asm.S | |||
16 | $(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include | 16 | $(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include |
17 | $(OUTPUT)/tm-tmspr: CFLAGS += -pthread | 17 | $(OUTPUT)/tm-tmspr: CFLAGS += -pthread |
18 | $(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64 | 18 | $(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64 |
19 | $(OUTPUT)/tm-resched-dscr: ../pmu/lib.o | 19 | $(OUTPUT)/tm-resched-dscr: ../pmu/lib.c |
20 | $(OUTPUT)/tm-unavailable: CFLAGS += -O0 -pthread -m64 -Wno-error=uninitialized -mvsx | 20 | $(OUTPUT)/tm-unavailable: CFLAGS += -O0 -pthread -m64 -Wno-error=uninitialized -mvsx |
21 | $(OUTPUT)/tm-trap: CFLAGS += -O0 -pthread -m64 | 21 | $(OUTPUT)/tm-trap: CFLAGS += -O0 -pthread -m64 |
22 | 22 | ||
diff --git a/tools/testing/selftests/powerpc/tm/tm-trap.c b/tools/testing/selftests/powerpc/tm/tm-trap.c index 5d92c23ee6cb..179d592f0073 100644 --- a/tools/testing/selftests/powerpc/tm/tm-trap.c +++ b/tools/testing/selftests/powerpc/tm/tm-trap.c | |||
@@ -255,6 +255,8 @@ int tm_trap_test(void) | |||
255 | 255 | ||
256 | struct sigaction trap_sa; | 256 | struct sigaction trap_sa; |
257 | 257 | ||
258 | SKIP_IF(!have_htm()); | ||
259 | |||
258 | trap_sa.sa_flags = SA_SIGINFO; | 260 | trap_sa.sa_flags = SA_SIGINFO; |
259 | trap_sa.sa_sigaction = trap_signal_handler; | 261 | trap_sa.sa_sigaction = trap_signal_handler; |
260 | sigaction(SIGTRAP, &trap_sa, NULL); | 262 | sigaction(SIGTRAP, &trap_sa, NULL); |
diff --git a/tools/testing/selftests/pstore/config b/tools/testing/selftests/pstore/config index 6a8e5a9bfc10..d148f9f89fb6 100644 --- a/tools/testing/selftests/pstore/config +++ b/tools/testing/selftests/pstore/config | |||
@@ -2,3 +2,4 @@ CONFIG_MISC_FILESYSTEMS=y | |||
2 | CONFIG_PSTORE=y | 2 | CONFIG_PSTORE=y |
3 | CONFIG_PSTORE_PMSG=y | 3 | CONFIG_PSTORE_PMSG=y |
4 | CONFIG_PSTORE_CONSOLE=y | 4 | CONFIG_PSTORE_CONSOLE=y |
5 | CONFIG_PSTORE_RAM=m | ||
diff --git a/tools/testing/selftests/sync/Makefile b/tools/testing/selftests/sync/Makefile index b3c8ba3cb668..d0121a8a3523 100644 --- a/tools/testing/selftests/sync/Makefile +++ b/tools/testing/selftests/sync/Makefile | |||
@@ -30,7 +30,7 @@ $(TEST_CUSTOM_PROGS): $(TESTS) $(OBJS) | |||
30 | $(CC) -o $(TEST_CUSTOM_PROGS) $(OBJS) $(TESTS) $(CFLAGS) $(LDFLAGS) | 30 | $(CC) -o $(TEST_CUSTOM_PROGS) $(OBJS) $(TESTS) $(CFLAGS) $(LDFLAGS) |
31 | 31 | ||
32 | $(OBJS): $(OUTPUT)/%.o: %.c | 32 | $(OBJS): $(OUTPUT)/%.o: %.c |
33 | $(CC) -c $^ -o $@ | 33 | $(CC) -c $^ -o $@ $(CFLAGS) |
34 | 34 | ||
35 | $(TESTS): $(OUTPUT)/%.o: %.c | 35 | $(TESTS): $(OUTPUT)/%.o: %.c |
36 | $(CC) -c $^ -o $@ | 36 | $(CC) -c $^ -o $@ |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json b/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json index e34075059c26..90bba48c3f07 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json | |||
@@ -315,7 +315,7 @@ | |||
315 | "cmdUnderTest": "$TC actions ls action skbmod", | 315 | "cmdUnderTest": "$TC actions ls action skbmod", |
316 | "expExitCode": "0", | 316 | "expExitCode": "0", |
317 | "verifyCmd": "$TC actions get action skbmod index 4", | 317 | "verifyCmd": "$TC actions get action skbmod index 4", |
318 | "matchPattern": "action order [0-9]*: skbmod pipe set etype 0x0031", | 318 | "matchPattern": "action order [0-9]*: skbmod pipe set etype 0x31", |
319 | "matchCount": "1", | 319 | "matchCount": "1", |
320 | "teardown": [ | 320 | "teardown": [ |
321 | "$TC actions flush action skbmod" | 321 | "$TC actions flush action skbmod" |
diff --git a/tools/testing/selftests/vDSO/Makefile b/tools/testing/selftests/vDSO/Makefile index 3d5a62ff7d31..f5d7a7851e21 100644 --- a/tools/testing/selftests/vDSO/Makefile +++ b/tools/testing/selftests/vDSO/Makefile | |||
@@ -1,4 +1,6 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | include ../lib.mk | ||
3 | |||
2 | ifndef CROSS_COMPILE | 4 | ifndef CROSS_COMPILE |
3 | CFLAGS := -std=gnu99 | 5 | CFLAGS := -std=gnu99 |
4 | CFLAGS_vdso_standalone_test_x86 := -nostdlib -fno-asynchronous-unwind-tables -fno-stack-protector | 6 | CFLAGS_vdso_standalone_test_x86 := -nostdlib -fno-asynchronous-unwind-tables -fno-stack-protector |
@@ -6,16 +8,14 @@ ifeq ($(CONFIG_X86_32),y) | |||
6 | LDLIBS += -lgcc_s | 8 | LDLIBS += -lgcc_s |
7 | endif | 9 | endif |
8 | 10 | ||
9 | TEST_PROGS := vdso_test vdso_standalone_test_x86 | 11 | TEST_PROGS := $(OUTPUT)/vdso_test $(OUTPUT)/vdso_standalone_test_x86 |
10 | 12 | ||
11 | all: $(TEST_PROGS) | 13 | all: $(TEST_PROGS) |
12 | vdso_test: parse_vdso.c vdso_test.c | 14 | $(OUTPUT)/vdso_test: parse_vdso.c vdso_test.c |
13 | vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c | 15 | $(OUTPUT)/vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c |
14 | $(CC) $(CFLAGS) $(CFLAGS_vdso_standalone_test_x86) \ | 16 | $(CC) $(CFLAGS) $(CFLAGS_vdso_standalone_test_x86) \ |
15 | vdso_standalone_test_x86.c parse_vdso.c \ | 17 | vdso_standalone_test_x86.c parse_vdso.c \ |
16 | -o vdso_standalone_test_x86 | 18 | -o $@ |
17 | 19 | ||
18 | include ../lib.mk | 20 | EXTRA_CLEAN := $(TEST_PROGS) |
19 | clean: | ||
20 | rm -fr $(TEST_PROGS) | ||
21 | endif | 21 | endif |
diff --git a/tools/testing/selftests/vm/.gitignore b/tools/testing/selftests/vm/.gitignore index 63c94d776e89..342c7bc9dc8c 100644 --- a/tools/testing/selftests/vm/.gitignore +++ b/tools/testing/selftests/vm/.gitignore | |||
@@ -11,3 +11,4 @@ mlock-intersect-test | |||
11 | mlock-random-test | 11 | mlock-random-test |
12 | virtual_address_range | 12 | virtual_address_range |
13 | gup_benchmark | 13 | gup_benchmark |
14 | va_128TBswitch | ||
diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests index d2561895a021..22d564673830 100755 --- a/tools/testing/selftests/vm/run_vmtests +++ b/tools/testing/selftests/vm/run_vmtests | |||
@@ -2,25 +2,33 @@ | |||
2 | # SPDX-License-Identifier: GPL-2.0 | 2 | # SPDX-License-Identifier: GPL-2.0 |
3 | #please run as root | 3 | #please run as root |
4 | 4 | ||
5 | #we need 256M, below is the size in kB | ||
6 | needmem=262144 | ||
7 | mnt=./huge | 5 | mnt=./huge |
8 | exitcode=0 | 6 | exitcode=0 |
9 | 7 | ||
10 | #get pagesize and freepages from /proc/meminfo | 8 | #get huge pagesize and freepages from /proc/meminfo |
11 | while read name size unit; do | 9 | while read name size unit; do |
12 | if [ "$name" = "HugePages_Free:" ]; then | 10 | if [ "$name" = "HugePages_Free:" ]; then |
13 | freepgs=$size | 11 | freepgs=$size |
14 | fi | 12 | fi |
15 | if [ "$name" = "Hugepagesize:" ]; then | 13 | if [ "$name" = "Hugepagesize:" ]; then |
16 | pgsize=$size | 14 | hpgsize_KB=$size |
17 | fi | 15 | fi |
18 | done < /proc/meminfo | 16 | done < /proc/meminfo |
19 | 17 | ||
18 | # Simple hugetlbfs tests have a hardcoded minimum requirement of | ||
19 | # huge pages totaling 256MB (262144KB) in size. The userfaultfd | ||
20 | # hugetlb test requires a minimum of 2 * nr_cpus huge pages. Take | ||
21 | # both of these requirements into account and attempt to increase | ||
22 | # number of huge pages available. | ||
23 | nr_cpus=$(nproc) | ||
24 | hpgsize_MB=$((hpgsize_KB / 1024)) | ||
25 | half_ufd_size_MB=$((((nr_cpus * hpgsize_MB + 127) / 128) * 128)) | ||
26 | needmem_KB=$((half_ufd_size_MB * 2 * 1024)) | ||
27 | |||
20 | #set proper nr_hugepages | 28 | #set proper nr_hugepages |
21 | if [ -n "$freepgs" ] && [ -n "$pgsize" ]; then | 29 | if [ -n "$freepgs" ] && [ -n "$hpgsize_KB" ]; then |
22 | nr_hugepgs=`cat /proc/sys/vm/nr_hugepages` | 30 | nr_hugepgs=`cat /proc/sys/vm/nr_hugepages` |
23 | needpgs=`expr $needmem / $pgsize` | 31 | needpgs=$((needmem_KB / hpgsize_KB)) |
24 | tries=2 | 32 | tries=2 |
25 | while [ $tries -gt 0 ] && [ $freepgs -lt $needpgs ]; do | 33 | while [ $tries -gt 0 ] && [ $freepgs -lt $needpgs ]; do |
26 | lackpgs=$(( $needpgs - $freepgs )) | 34 | lackpgs=$(( $needpgs - $freepgs )) |
@@ -107,8 +115,9 @@ fi | |||
107 | echo "---------------------------" | 115 | echo "---------------------------" |
108 | echo "running userfaultfd_hugetlb" | 116 | echo "running userfaultfd_hugetlb" |
109 | echo "---------------------------" | 117 | echo "---------------------------" |
110 | # 256MB total huge pages == 128MB src and 128MB dst | 118 | # Test requires source and destination huge pages. Size of source |
111 | ./userfaultfd hugetlb 128 32 $mnt/ufd_test_file | 119 | # (half_ufd_size_MB) is passed as argument to test. |
120 | ./userfaultfd hugetlb $half_ufd_size_MB 32 $mnt/ufd_test_file | ||
112 | if [ $? -ne 0 ]; then | 121 | if [ $? -ne 0 ]; then |
113 | echo "[FAIL]" | 122 | echo "[FAIL]" |
114 | exitcode=1 | 123 | exitcode=1 |
diff --git a/tools/testing/selftests/x86/entry_from_vm86.c b/tools/testing/selftests/x86/entry_from_vm86.c index 361466a2eaef..ade443a88421 100644 --- a/tools/testing/selftests/x86/entry_from_vm86.c +++ b/tools/testing/selftests/x86/entry_from_vm86.c | |||
@@ -95,6 +95,10 @@ asm ( | |||
95 | "int3\n\t" | 95 | "int3\n\t" |
96 | "vmcode_int80:\n\t" | 96 | "vmcode_int80:\n\t" |
97 | "int $0x80\n\t" | 97 | "int $0x80\n\t" |
98 | "vmcode_popf_hlt:\n\t" | ||
99 | "push %ax\n\t" | ||
100 | "popf\n\t" | ||
101 | "hlt\n\t" | ||
98 | "vmcode_umip:\n\t" | 102 | "vmcode_umip:\n\t" |
99 | /* addressing via displacements */ | 103 | /* addressing via displacements */ |
100 | "smsw (2052)\n\t" | 104 | "smsw (2052)\n\t" |
@@ -124,8 +128,8 @@ asm ( | |||
124 | 128 | ||
125 | extern unsigned char vmcode[], end_vmcode[]; | 129 | extern unsigned char vmcode[], end_vmcode[]; |
126 | extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[], | 130 | extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[], |
127 | vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[], | 131 | vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_popf_hlt[], |
128 | vmcode_umip_str[], vmcode_umip_sldt[]; | 132 | vmcode_umip[], vmcode_umip_str[], vmcode_umip_sldt[]; |
129 | 133 | ||
130 | /* Returns false if the test was skipped. */ | 134 | /* Returns false if the test was skipped. */ |
131 | static bool do_test(struct vm86plus_struct *v86, unsigned long eip, | 135 | static bool do_test(struct vm86plus_struct *v86, unsigned long eip, |
@@ -175,7 +179,7 @@ static bool do_test(struct vm86plus_struct *v86, unsigned long eip, | |||
175 | (VM86_TYPE(ret) == rettype && VM86_ARG(ret) == retarg)) { | 179 | (VM86_TYPE(ret) == rettype && VM86_ARG(ret) == retarg)) { |
176 | printf("[OK]\tReturned correctly\n"); | 180 | printf("[OK]\tReturned correctly\n"); |
177 | } else { | 181 | } else { |
178 | printf("[FAIL]\tIncorrect return reason\n"); | 182 | printf("[FAIL]\tIncorrect return reason (started at eip = 0x%lx, ended at eip = 0x%lx)\n", eip, v86->regs.eip); |
179 | nerrs++; | 183 | nerrs++; |
180 | } | 184 | } |
181 | 185 | ||
@@ -264,6 +268,9 @@ int main(void) | |||
264 | v86.regs.ds = load_addr / 16; | 268 | v86.regs.ds = load_addr / 16; |
265 | v86.regs.es = load_addr / 16; | 269 | v86.regs.es = load_addr / 16; |
266 | 270 | ||
271 | /* Use the end of the page as our stack. */ | ||
272 | v86.regs.esp = 4096; | ||
273 | |||
267 | assert((v86.regs.cs & 3) == 0); /* Looks like RPL = 0 */ | 274 | assert((v86.regs.cs & 3) == 0); /* Looks like RPL = 0 */ |
268 | 275 | ||
269 | /* #BR -- should deliver SIG??? */ | 276 | /* #BR -- should deliver SIG??? */ |
@@ -295,6 +302,23 @@ int main(void) | |||
295 | v86.regs.eflags &= ~X86_EFLAGS_IF; | 302 | v86.regs.eflags &= ~X86_EFLAGS_IF; |
296 | do_test(&v86, vmcode_sti - vmcode, VM86_STI, 0, "STI with VIP set"); | 303 | do_test(&v86, vmcode_sti - vmcode, VM86_STI, 0, "STI with VIP set"); |
297 | 304 | ||
305 | /* POPF with VIP set but IF clear: should not trap */ | ||
306 | v86.regs.eflags = X86_EFLAGS_VIP; | ||
307 | v86.regs.eax = 0; | ||
308 | do_test(&v86, vmcode_popf_hlt - vmcode, VM86_UNKNOWN, 0, "POPF with VIP set and IF clear"); | ||
309 | |||
310 | /* POPF with VIP set and IF set: should trap */ | ||
311 | v86.regs.eflags = X86_EFLAGS_VIP; | ||
312 | v86.regs.eax = X86_EFLAGS_IF; | ||
313 | do_test(&v86, vmcode_popf_hlt - vmcode, VM86_STI, 0, "POPF with VIP and IF set"); | ||
314 | |||
315 | /* POPF with VIP clear and IF set: should not trap */ | ||
316 | v86.regs.eflags = 0; | ||
317 | v86.regs.eax = X86_EFLAGS_IF; | ||
318 | do_test(&v86, vmcode_popf_hlt - vmcode, VM86_UNKNOWN, 0, "POPF with VIP clear and IF set"); | ||
319 | |||
320 | v86.regs.eflags = 0; | ||
321 | |||
298 | /* INT3 -- should cause #BP */ | 322 | /* INT3 -- should cause #BP */ |
299 | do_test(&v86, vmcode_int3 - vmcode, VM86_TRAP, 3, "INT3"); | 323 | do_test(&v86, vmcode_int3 - vmcode, VM86_TRAP, 3, "INT3"); |
300 | 324 | ||
@@ -318,7 +342,7 @@ int main(void) | |||
318 | clearhandler(SIGSEGV); | 342 | clearhandler(SIGSEGV); |
319 | 343 | ||
320 | /* Make sure nothing explodes if we fork. */ | 344 | /* Make sure nothing explodes if we fork. */ |
321 | if (fork() > 0) | 345 | if (fork() == 0) |
322 | return 0; | 346 | return 0; |
323 | 347 | ||
324 | return (nerrs == 0 ? 0 : 1); | 348 | return (nerrs == 0 ? 0 : 1); |
diff --git a/tools/testing/selftests/x86/test_vsyscall.c b/tools/testing/selftests/x86/test_vsyscall.c index be81621446f0..0b4f1cc2291c 100644 --- a/tools/testing/selftests/x86/test_vsyscall.c +++ b/tools/testing/selftests/x86/test_vsyscall.c | |||
@@ -450,7 +450,7 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void) | |||
450 | num_vsyscall_traps++; | 450 | num_vsyscall_traps++; |
451 | } | 451 | } |
452 | 452 | ||
453 | static int test_native_vsyscall(void) | 453 | static int test_emulation(void) |
454 | { | 454 | { |
455 | time_t tmp; | 455 | time_t tmp; |
456 | bool is_native; | 456 | bool is_native; |
@@ -458,7 +458,7 @@ static int test_native_vsyscall(void) | |||
458 | if (!vtime) | 458 | if (!vtime) |
459 | return 0; | 459 | return 0; |
460 | 460 | ||
461 | printf("[RUN]\tchecking for native vsyscall\n"); | 461 | printf("[RUN]\tchecking that vsyscalls are emulated\n"); |
462 | sethandler(SIGTRAP, sigtrap, 0); | 462 | sethandler(SIGTRAP, sigtrap, 0); |
463 | set_eflags(get_eflags() | X86_EFLAGS_TF); | 463 | set_eflags(get_eflags() | X86_EFLAGS_TF); |
464 | vtime(&tmp); | 464 | vtime(&tmp); |
@@ -474,11 +474,12 @@ static int test_native_vsyscall(void) | |||
474 | */ | 474 | */ |
475 | is_native = (num_vsyscall_traps > 1); | 475 | is_native = (num_vsyscall_traps > 1); |
476 | 476 | ||
477 | printf("\tvsyscalls are %s (%d instructions in vsyscall page)\n", | 477 | printf("[%s]\tvsyscalls are %s (%d instructions in vsyscall page)\n", |
478 | (is_native ? "FAIL" : "OK"), | ||
478 | (is_native ? "native" : "emulated"), | 479 | (is_native ? "native" : "emulated"), |
479 | (int)num_vsyscall_traps); | 480 | (int)num_vsyscall_traps); |
480 | 481 | ||
481 | return 0; | 482 | return is_native; |
482 | } | 483 | } |
483 | #endif | 484 | #endif |
484 | 485 | ||
@@ -498,7 +499,7 @@ int main(int argc, char **argv) | |||
498 | nerrs += test_vsys_r(); | 499 | nerrs += test_vsys_r(); |
499 | 500 | ||
500 | #ifdef __x86_64__ | 501 | #ifdef __x86_64__ |
501 | nerrs += test_native_vsyscall(); | 502 | nerrs += test_emulation(); |
502 | #endif | 503 | #endif |
503 | 504 | ||
504 | return nerrs ? 1 : 0; | 505 | return nerrs ? 1 : 0; |