The format of synthesized events is determined by the attribute config. For the formats for Intel PT power and ptwrite events, create tables and populate them when the synth_data handler is called. If the tables remain empty, drop them at the end. The tables and views, including a combined power_events_view, will display automatically from the tables menu of the exported exported-sql-viewer.py script. Note, currently only Atoms since Gemini Lake have support for ptwrite and mwait, pwre, exstop and pwrx, but all Intel PT implementations support cbr.
Showing the changes to tools/perf/scripts/python (1 of 1 file). Show all
Unified · Split
| @@ -447,6 +447,38 @@ if perf_db_export_calls: · 446 unmodified lines | ||
| 447 | 447 | 'insn_count bigint,' |
| 448 | 448 | 'cyc_count bigint)') |
| 449 | 449 | |
| 450 | +do_query(query, 'CREATE TABLE ptwrite (' | |
| 451 | + 'id bigint NOT NULL,' | |
| 452 | + 'payload bigint,' | |
| 453 | + 'exact_ip boolean)') | |
| 454 | + | |
| 455 | +do_query(query, 'CREATE TABLE cbr (' | |
| 456 | + 'id bigint NOT NULL,' | |
| 457 | + 'cbr integer,' | |
| 458 | + 'mhz integer,' | |
| 459 | + 'percent integer)') | |
| 460 | + | |
| 461 | +do_query(query, 'CREATE TABLE mwait (' | |
| 462 | + 'id bigint NOT NULL,' | |
| 463 | + 'hints integer,' | |
| 464 | + 'extensions integer)') | |
| 465 | + | |
| 466 | +do_query(query, 'CREATE TABLE pwre (' | |
| 467 | + 'id bigint NOT NULL,' | |
| 468 | + 'cstate integer,' | |
| 469 | + 'subcstate integer,' | |
| 470 | + 'hw boolean)') | |
| 471 | + | |
| 472 | +do_query(query, 'CREATE TABLE exstop (' | |
| 473 | + 'id bigint NOT NULL,' | |
| 474 | + 'exact_ip boolean)') | |
| 475 | + | |
| 476 | +do_query(query, 'CREATE TABLE pwrx (' | |
| 477 | + 'id bigint NOT NULL,' | |
| 478 | + 'deepest_cstate integer,' | |
| 479 | + 'last_cstate integer,' | |
| 480 | + 'wake_reason integer)') | |
| 481 | + | |
| 450 | 482 | do_query(query, 'CREATE VIEW machines_view AS ' |
| 451 | 483 | 'SELECT ' |
| 452 | 484 | 'id,' |
| @@ -561,6 +593,104 @@ do_query(query, 'CREATE VIEW samples_view AS ' · 108 unmodified lines | ||
| 561 | 593 | 'CASE WHEN cyc_count=0 THEN CAST(0 AS NUMERIC(20, 2)) ELSE CAST((CAST(insn_count AS FLOAT) / cyc_count) AS NUMERIC(20, 2)) END AS IPC' |
| 562 | 594 | ' FROM samples') |
| 563 | 595 | |
| 596 | +do_query(query, 'CREATE VIEW ptwrite_view AS ' | |
| 597 | + 'SELECT ' | |
| 598 | + 'ptwrite.id,' | |
| 599 | + 'time,' | |
| 600 | + 'cpu,' | |
| 601 | + 'to_hex(payload) AS payload_hex,' | |
| 602 | + 'CASE WHEN exact_ip=FALSE THEN \'False\' ELSE \'True\' END AS exact_ip' | |
| 603 | + ' FROM ptwrite' | |
| 604 | + ' INNER JOIN samples ON samples.id = ptwrite.id') | |
| 605 | + | |
| 606 | +do_query(query, 'CREATE VIEW cbr_view AS ' | |
| 607 | + 'SELECT ' | |
| 608 | + 'cbr.id,' | |
| 609 | + 'time,' | |
| 610 | + 'cpu,' | |
| 611 | + 'cbr,' | |
| 612 | + 'mhz,' | |
| 613 | + 'percent' | |
| 614 | + ' FROM cbr' | |
| 615 | + ' INNER JOIN samples ON samples.id = cbr.id') | |
| 616 | + | |
| 617 | +do_query(query, 'CREATE VIEW mwait_view AS ' | |
| 618 | + 'SELECT ' | |
| 619 | + 'mwait.id,' | |
| 620 | + 'time,' | |
| 621 | + 'cpu,' | |
| 622 | + 'to_hex(hints) AS hints_hex,' | |
| 623 | + 'to_hex(extensions) AS extensions_hex' | |
| 624 | + ' FROM mwait' | |
| 625 | + ' INNER JOIN samples ON samples.id = mwait.id') | |
| 626 | + | |
| 627 | +do_query(query, 'CREATE VIEW pwre_view AS ' | |
| 628 | + 'SELECT ' | |
| 629 | + 'pwre.id,' | |
| 630 | + 'time,' | |
| 631 | + 'cpu,' | |
| 632 | + 'cstate,' | |
| 633 | + 'subcstate,' | |
| 634 | + 'CASE WHEN hw=FALSE THEN \'False\' ELSE \'True\' END AS hw' | |
| 635 | + ' FROM pwre' | |
| 636 | + ' INNER JOIN samples ON samples.id = pwre.id') | |
| 637 | + | |
| 638 | +do_query(query, 'CREATE VIEW exstop_view AS ' | |
| 639 | + 'SELECT ' | |
| 640 | + 'exstop.id,' | |
| 641 | + 'time,' | |
| 642 | + 'cpu,' | |
| 643 | + 'CASE WHEN exact_ip=FALSE THEN \'False\' ELSE \'True\' END AS exact_ip' | |
| 644 | + ' FROM exstop' | |
| 645 | + ' INNER JOIN samples ON samples.id = exstop.id') | |
| 646 | + | |
| 647 | +do_query(query, 'CREATE VIEW pwrx_view AS ' | |
| 648 | + 'SELECT ' | |
| 649 | + 'pwrx.id,' | |
| 650 | + 'time,' | |
| 651 | + 'cpu,' | |
| 652 | + 'deepest_cstate,' | |
| 653 | + 'last_cstate,' | |
| 654 | + 'CASE WHEN wake_reason=1 THEN \'Interrupt\'' | |
| 655 | + ' WHEN wake_reason=2 THEN \'Timer Deadline\'' | |
| 656 | + ' WHEN wake_reason=4 THEN \'Monitored Address\'' | |
| 657 | + ' WHEN wake_reason=8 THEN \'HW\'' | |
| 658 | + ' ELSE CAST ( wake_reason AS VARCHAR(2) )' | |
| 659 | + 'END AS wake_reason' | |
| 660 | + ' FROM pwrx' | |
| 661 | + ' INNER JOIN samples ON samples.id = pwrx.id') | |
| 662 | + | |
| 663 | +do_query(query, 'CREATE VIEW power_events_view AS ' | |
| 664 | + 'SELECT ' | |
| 665 | + 'samples.id,' | |
| 666 | + 'samples.time,' | |
| 667 | + 'samples.cpu,' | |
| 668 | + 'selected_events.name AS event,' | |
| 669 | + 'FORMAT(\'%6s\', cbr.cbr) AS cbr,' | |
| 670 | + 'FORMAT(\'%6s\', cbr.mhz) AS MHz,' | |
| 671 | + 'FORMAT(\'%5s\', cbr.percent) AS percent,' | |
| 672 | + 'to_hex(mwait.hints) AS hints_hex,' | |
| 673 | + 'to_hex(mwait.extensions) AS extensions_hex,' | |
| 674 | + 'FORMAT(\'%3s\', pwre.cstate) AS cstate,' | |
| 675 | + 'FORMAT(\'%3s\', pwre.subcstate) AS subcstate,' | |
| 676 | + 'CASE WHEN pwre.hw=FALSE THEN \'False\' WHEN pwre.hw=TRUE THEN \'True\' ELSE NULL END AS hw,' | |
| 677 | + 'CASE WHEN exstop.exact_ip=FALSE THEN \'False\' WHEN exstop.exact_ip=TRUE THEN \'True\' ELSE NULL END AS exact_ip,' | |
| 678 | + 'FORMAT(\'%3s\', pwrx.deepest_cstate) AS deepest_cstate,' | |
| 679 | + 'FORMAT(\'%3s\', pwrx.last_cstate) AS last_cstate,' | |
| 680 | + 'CASE WHEN pwrx.wake_reason=1 THEN \'Interrupt\'' | |
| 681 | + ' WHEN pwrx.wake_reason=2 THEN \'Timer Deadline\'' | |
| 682 | + ' WHEN pwrx.wake_reason=4 THEN \'Monitored Address\'' | |
| 683 | + ' WHEN pwrx.wake_reason=8 THEN \'HW\'' | |
| 684 | + ' ELSE FORMAT(\'%2s\', pwrx.wake_reason)' | |
| 685 | + 'END AS wake_reason' | |
| 686 | + ' FROM cbr' | |
| 687 | + ' FULL JOIN mwait ON mwait.id = cbr.id' | |
| 688 | + ' FULL JOIN pwre ON pwre.id = cbr.id' | |
| 689 | + ' FULL JOIN exstop ON exstop.id = cbr.id' | |
| 690 | + ' FULL JOIN pwrx ON pwrx.id = cbr.id' | |
| 691 | + ' INNER JOIN samples ON samples.id = coalesce(cbr.id, mwait.id, pwre.id, exstop.id, pwrx.id)' | |
| 692 | + ' INNER JOIN selected_events ON selected_events.id = samples.evsel_id' | |
| 693 | + ' ORDER BY samples.id') | |
| 564 | 694 | |
| 565 | 695 | file_header = struct.pack("!11sii", b"PGCOPY\n\377\r\n\0", 0, 0) |
| 566 | 696 | file_trailer = b"\377\377" |
| @@ -620,6 +750,12 @@ if perf_db_export_calls or perf_db_export_callchains: · 53 unmodified lines | ||
| 620 | 750 | call_path_file = open_output_file("call_path_table.bin") |
| 621 | 751 | if perf_db_export_calls: |
| 622 | 752 | call_file = open_output_file("call_table.bin") |
| 753 | +ptwrite_file = open_output_file("ptwrite_table.bin") | |
| 754 | +cbr_file = open_output_file("cbr_table.bin") | |
| 755 | +mwait_file = open_output_file("mwait_table.bin") | |
| 756 | +pwre_file = open_output_file("pwre_table.bin") | |
| 757 | +exstop_file = open_output_file("exstop_table.bin") | |
| 758 | +pwrx_file = open_output_file("pwrx_table.bin") | |
| 623 | 759 | |
| 624 | 760 | def trace_begin(): |
| 625 | 761 | printdate("Writing to intermediate files...") |
| @@ -637,6 +773,16 @@ def trace_begin(): · 11 unmodified lines | ||
| 637 | 773 | |
| 638 | 774 | unhandled_count = 0 |
| 639 | 775 | |
| 776 | +def is_table_empty(table_name): | |
| 777 | + do_query(query, 'SELECT * FROM ' + table_name + ' LIMIT 1'); | |
| 778 | + if query.next(): | |
| 779 | + return False | |
| 780 | + return True | |
| 781 | + | |
| 782 | +def drop(table_name): | |
| 783 | + do_query(query, 'DROP VIEW ' + table_name + '_view'); | |
| 784 | + do_query(query, 'DROP TABLE ' + table_name); | |
| 785 | + | |
| 640 | 786 | def trace_end(): |
| 641 | 787 | printdate("Copying to database...") |
| 642 | 788 | copy_output_file(evsel_file, "selected_events") |
| @@ -652,6 +798,12 @@ def trace_end(): · 9 unmodified lines | ||
| 652 | 798 | copy_output_file(call_path_file, "call_paths") |
| 653 | 799 | if perf_db_export_calls: |
| 654 | 800 | copy_output_file(call_file, "calls") |
| 801 | + copy_output_file(ptwrite_file, "ptwrite") | |
| 802 | + copy_output_file(cbr_file, "cbr") | |
| 803 | + copy_output_file(mwait_file, "mwait") | |
| 804 | + copy_output_file(pwre_file, "pwre") | |
| 805 | + copy_output_file(exstop_file, "exstop") | |
| 806 | + copy_output_file(pwrx_file, "pwrx") | |
| 655 | 807 | |
| 656 | 808 | printdate("Removing intermediate files...") |
| 657 | 809 | remove_output_file(evsel_file) |
| @@ -667,6 +819,12 @@ def trace_end(): · 9 unmodified lines | ||
| 667 | 819 | remove_output_file(call_path_file) |
| 668 | 820 | if perf_db_export_calls: |
| 669 | 821 | remove_output_file(call_file) |
| 822 | + remove_output_file(ptwrite_file) | |
| 823 | + remove_output_file(cbr_file) | |
| 824 | + remove_output_file(mwait_file) | |
| 825 | + remove_output_file(pwre_file) | |
| 826 | + remove_output_file(exstop_file) | |
| 827 | + remove_output_file(pwrx_file) | |
| 670 | 828 | os.rmdir(output_dir_name) |
| 671 | 829 | printdate("Adding primary keys") |
| 672 | 830 | do_query(query, 'ALTER TABLE selected_events ADD PRIMARY KEY (id)') |
| @@ -682,6 +840,12 @@ def trace_end(): · 9 unmodified lines | ||
| 682 | 840 | do_query(query, 'ALTER TABLE call_paths ADD PRIMARY KEY (id)') |
| 683 | 841 | if perf_db_export_calls: |
| 684 | 842 | do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)') |
| 843 | + do_query(query, 'ALTER TABLE ptwrite ADD PRIMARY KEY (id)') | |
| 844 | + do_query(query, 'ALTER TABLE cbr ADD PRIMARY KEY (id)') | |
| 845 | + do_query(query, 'ALTER TABLE mwait ADD PRIMARY KEY (id)') | |
| 846 | + do_query(query, 'ALTER TABLE pwre ADD PRIMARY KEY (id)') | |
| 847 | + do_query(query, 'ALTER TABLE exstop ADD PRIMARY KEY (id)') | |
| 848 | + do_query(query, 'ALTER TABLE pwrx ADD PRIMARY KEY (id)') | |
| 685 | 849 | |
| 686 | 850 | printdate("Adding foreign keys") |
| 687 | 851 | do_query(query, 'ALTER TABLE threads ' |
| @@ -717,6 +881,30 @@ def trace_end(): · 29 unmodified lines | ||
| 717 | 881 | 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)') |
| 718 | 882 | do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') |
| 719 | 883 | do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)') |
| 884 | + do_query(query, 'ALTER TABLE ptwrite ' | |
| 885 | + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') | |
| 886 | + do_query(query, 'ALTER TABLE cbr ' | |
| 887 | + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') | |
| 888 | + do_query(query, 'ALTER TABLE mwait ' | |
| 889 | + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') | |
| 890 | + do_query(query, 'ALTER TABLE pwre ' | |
| 891 | + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') | |
| 892 | + do_query(query, 'ALTER TABLE exstop ' | |
| 893 | + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') | |
| 894 | + do_query(query, 'ALTER TABLE pwrx ' | |
| 895 | + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') | |
| 896 | + | |
| 897 | + printdate("Dropping unused tables") | |
| 898 | + if is_table_empty("ptwrite"): | |
| 899 | + drop("ptwrite") | |
| 900 | + if is_table_empty("mwait") and is_table_empty("pwre") and is_table_empty("exstop") and is_table_empty("pwrx"): | |
| 901 | + drop("mwait") | |
| 902 | + drop("pwre") | |
| 903 | + drop("exstop") | |
| 904 | + drop("pwrx") | |
| 905 | + do_query(query, 'DROP VIEW power_events_view'); | |
| 906 | + if is_table_empty("cbr"): | |
| 907 | + drop("cbr") | |
| 720 | 908 | |
| 721 | 909 | if (unhandled_count): |
| 722 | 910 | printdate("Warning: ", unhandled_count, " unhandled events") |
| @@ -800,3 +988,66 @@ def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return · 77 unmodified lines | ||
| 800 | 988 | fmt = "!hiqiqiqiqiqiqiqiqiqiqiiiqiqiq" |
| 801 | 989 | value = struct.pack(fmt, 14, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags, 8, parent_id, 8, insn_cnt, 8, cyc_cnt) |
| 802 | 990 | call_file.write(value) |
| 991 | + | |
| 992 | +def ptwrite(id, raw_buf): | |
| 993 | + data = struct.unpack_from("<IQ", raw_buf) | |
| 994 | + flags = data[0] | |
| 995 | + payload = data[1] | |
| 996 | + exact_ip = flags & 1 | |
| 997 | + value = struct.pack("!hiqiqiB", 3, 8, id, 8, payload, 1, exact_ip) | |
| 998 | + ptwrite_file.write(value) | |
| 999 | + | |
| 1000 | +def cbr(id, raw_buf): | |
| 1001 | + data = struct.unpack_from("<BBBBII", raw_buf) | |
| 1002 | + cbr = data[0] | |
| 1003 | + MHz = (data[4] + 500) / 1000 | |
| 1004 | + percent = ((cbr * 1000 / data[2]) + 5) / 10 | |
| 1005 | + value = struct.pack("!hiqiiiiii", 4, 8, id, 4, cbr, 4, MHz, 4, percent) | |
| 1006 | + cbr_file.write(value) | |
| 1007 | + | |
| 1008 | +def mwait(id, raw_buf): | |
| 1009 | + data = struct.unpack_from("<IQ", raw_buf) | |
| 1010 | + payload = data[1] | |
| 1011 | + hints = payload & 0xff | |
| 1012 | + extensions = (payload >> 32) & 0x3 | |
| 1013 | + value = struct.pack("!hiqiiii", 3, 8, id, 4, hints, 4, extensions) | |
| 1014 | + mwait_file.write(value) | |
| 1015 | + | |
| 1016 | +def pwre(id, raw_buf): | |
| 1017 | + data = struct.unpack_from("<IQ", raw_buf) | |
| 1018 | + payload = data[1] | |
| 1019 | + hw = (payload >> 7) & 1 | |
| 1020 | + cstate = (payload >> 12) & 0xf | |
| 1021 | + subcstate = (payload >> 8) & 0xf | |
| 1022 | + value = struct.pack("!hiqiiiiiB", 4, 8, id, 4, cstate, 4, subcstate, 1, hw) | |
| 1023 | + pwre_file.write(value) | |
| 1024 | + | |
| 1025 | +def exstop(id, raw_buf): | |
| 1026 | + data = struct.unpack_from("<I", raw_buf) | |
| 1027 | + flags = data[0] | |
| 1028 | + exact_ip = flags & 1 | |
| 1029 | + value = struct.pack("!hiqiB", 2, 8, id, 1, exact_ip) | |
| 1030 | + exstop_file.write(value) | |
| 1031 | + | |
| 1032 | +def pwrx(id, raw_buf): | |
| 1033 | + data = struct.unpack_from("<IQ", raw_buf) | |
| 1034 | + payload = data[1] | |
| 1035 | + deepest_cstate = payload & 0xf | |
| 1036 | + last_cstate = (payload >> 4) & 0xf | |
| 1037 | + wake_reason = (payload >> 8) & 0xf | |
| 1038 | + value = struct.pack("!hiqiiiiii", 4, 8, id, 4, deepest_cstate, 4, last_cstate, 4, wake_reason) | |
| 1039 | + pwrx_file.write(value) | |
| 1040 | + | |
| 1041 | +def synth_data(id, config, raw_buf, *x): | |
| 1042 | + if config == 0: | |
| 1043 | + ptwrite(id, raw_buf) | |
| 1044 | + elif config == 1: | |
| 1045 | + mwait(id, raw_buf) | |
| 1046 | + elif config == 2: | |
| 1047 | + pwre(id, raw_buf) | |
| 1048 | + elif config == 3: | |
| 1049 | + exstop(id, raw_buf) | |
| 1050 | + elif config == 4: | |
| 1051 | + pwrx(id, raw_buf) | |
| 1052 | + elif config == 5: | |
| 1053 | + cbr(id, raw_buf) | |