1cb77f0d6SKamil Rytarowski#!/usr/bin/env perl 2*c2e30119SThomas Gleixner# SPDX-License-Identifier: GPL-2.0-only 3aa5d9151SArjan van de Ven 4aa5d9151SArjan van de Ven# Copyright 2008, Intel Corporation 5aa5d9151SArjan van de Ven# 6aa5d9151SArjan van de Ven# This file is part of the Linux kernel 7aa5d9151SArjan van de Ven# 8aa5d9151SArjan van de Ven# Authors: 9aa5d9151SArjan van de Ven# Arjan van de Ven <arjan@linux.intel.com> 10aa5d9151SArjan van de Ven 11aa5d9151SArjan van de Ven 12aa5d9151SArjan van de Ven# 13aa5d9151SArjan van de Ven# This script turns a dmesg output into a SVG graphic that shows which 14aa5d9151SArjan van de Ven# functions take how much time. You can view SVG graphics with various 15aa5d9151SArjan van de Ven# programs, including Inkscape, The Gimp and Firefox. 16aa5d9151SArjan van de Ven# 17aa5d9151SArjan van de Ven# 18aa5d9151SArjan van de Ven# For this script to work, the kernel needs to be compiled with the 19aa5d9151SArjan van de Ven# CONFIG_PRINTK_TIME configuration option enabled, and with 20aa5d9151SArjan van de Ven# "initcall_debug" passed on the kernel command line. 21aa5d9151SArjan van de Ven# 22aa5d9151SArjan van de Ven# usage: 23aa5d9151SArjan van de Ven# dmesg | perl scripts/bootgraph.pl > output.svg 24aa5d9151SArjan van de Ven# 25aa5d9151SArjan van de Ven 262a813f8cSAlan Jenkinsuse strict; 2767554faaSFabian Frederickuse Getopt::Long; 2867554faaSFabian Frederickmy $header = 0; 2967554faaSFabian Frederick 3067554faaSFabian Fredericksub help { 3167554faaSFabian Frederick my $text = << "EOM"; 3267554faaSFabian FrederickUsage: 3367554faaSFabian Frederick1) dmesg | perl scripts/bootgraph.pl [OPTION] > output.svg 3467554faaSFabian Frederick2) perl scripts/bootgraph.pl -h 3567554faaSFabian Frederick 3667554faaSFabian FrederickOptions: 3767554faaSFabian Frederick -header Insert kernel version and date 3867554faaSFabian FrederickEOM 3967554faaSFabian Frederick my $std=shift; 4067554faaSFabian Frederick if ($std == 1) { 4167554faaSFabian Frederick print STDERR $text; 4267554faaSFabian Frederick } else { 4367554faaSFabian Frederick print $text; 4467554faaSFabian Frederick } 4567554faaSFabian Frederick exit; 4667554faaSFabian Frederick} 4767554faaSFabian Frederick 4867554faaSFabian FrederickGetOptions( 4967554faaSFabian Frederick 'h|help' =>\&help, 5067554faaSFabian Frederick 'header' =>\$header 5167554faaSFabian Frederick); 522a813f8cSAlan Jenkins 532a813f8cSAlan Jenkinsmy %start; 542a813f8cSAlan Jenkinsmy %end; 55d3f8ddeaSArjan van de Venmy %type; 56aa5d9151SArjan van de Venmy $done = 0; 57aa5d9151SArjan van de Venmy $maxtime = 0; 58c443453cSAndrew Murraymy $firsttime = 99999; 59aa5d9151SArjan van de Venmy $count = 0; 60ddc7a01aSFrederic Weisbeckermy %pids; 61d3f8ddeaSArjan van de Venmy %pidctr; 62ddc7a01aSFrederic Weisbecker 6367554faaSFabian Frederickmy $headerstep = 20; 6467554faaSFabian Frederickmy $xheader = 15; 6567554faaSFabian Frederickmy $yheader = 25; 6667554faaSFabian Frederickmy $cyheader = 0; 6767554faaSFabian Frederick 68aa5d9151SArjan van de Venwhile (<>) { 69aa5d9151SArjan van de Ven my $line = $_; 700bb98e23SMichael Neuling if ($line =~ /([0-9\.]+)\] calling ([a-zA-Z0-9\_\.]+)\+/) { 71aa5d9151SArjan van de Ven my $func = $2; 72aa5d9151SArjan van de Ven if ($done == 0) { 73aa5d9151SArjan van de Ven $start{$func} = $1; 74d3f8ddeaSArjan van de Ven $type{$func} = 0; 7580a398a5SArjan van de Ven if ($1 < $firsttime) { 7680a398a5SArjan van de Ven $firsttime = $1; 7780a398a5SArjan van de Ven } 78aa5d9151SArjan van de Ven } 79aa5d9151SArjan van de Ven if ($line =~ /\@ ([0-9]+)/) { 80ddc7a01aSFrederic Weisbecker $pids{$func} = $1; 81aa5d9151SArjan van de Ven } 82aa5d9151SArjan van de Ven $count = $count + 1; 83aa5d9151SArjan van de Ven } 84aa5d9151SArjan van de Ven 85d3f8ddeaSArjan van de Ven if ($line =~ /([0-9\.]+)\] async_waiting @ ([0-9]+)/) { 86d3f8ddeaSArjan van de Ven my $pid = $2; 87d3f8ddeaSArjan van de Ven my $func; 88d3f8ddeaSArjan van de Ven if (!defined($pidctr{$pid})) { 89d3f8ddeaSArjan van de Ven $func = "wait_" . $pid . "_1"; 90d3f8ddeaSArjan van de Ven $pidctr{$pid} = 1; 91d3f8ddeaSArjan van de Ven } else { 92d3f8ddeaSArjan van de Ven $pidctr{$pid} = $pidctr{$pid} + 1; 93d3f8ddeaSArjan van de Ven $func = "wait_" . $pid . "_" . $pidctr{$pid}; 94d3f8ddeaSArjan van de Ven } 95d3f8ddeaSArjan van de Ven if ($done == 0) { 96d3f8ddeaSArjan van de Ven $start{$func} = $1; 97d3f8ddeaSArjan van de Ven $type{$func} = 1; 98d3f8ddeaSArjan van de Ven if ($1 < $firsttime) { 99d3f8ddeaSArjan van de Ven $firsttime = $1; 100d3f8ddeaSArjan van de Ven } 101d3f8ddeaSArjan van de Ven } 102d3f8ddeaSArjan van de Ven $pids{$func} = $pid; 103d3f8ddeaSArjan van de Ven $count = $count + 1; 104d3f8ddeaSArjan van de Ven } 105d3f8ddeaSArjan van de Ven 1060bb98e23SMichael Neuling if ($line =~ /([0-9\.]+)\] initcall ([a-zA-Z0-9\_\.]+)\+.*returned/) { 107aa5d9151SArjan van de Ven if ($done == 0) { 108aa5d9151SArjan van de Ven $end{$2} = $1; 109aa5d9151SArjan van de Ven $maxtime = $1; 110aa5d9151SArjan van de Ven } 111aa5d9151SArjan van de Ven } 112d3f8ddeaSArjan van de Ven 113d3f8ddeaSArjan van de Ven if ($line =~ /([0-9\.]+)\] async_continuing @ ([0-9]+)/) { 114d3f8ddeaSArjan van de Ven my $pid = $2; 115d3f8ddeaSArjan van de Ven my $func = "wait_" . $pid . "_" . $pidctr{$pid}; 116d3f8ddeaSArjan van de Ven $end{$func} = $1; 117d3f8ddeaSArjan van de Ven $maxtime = $1; 118d3f8ddeaSArjan van de Ven } 119aa5d9151SArjan van de Ven if ($line =~ /Write protecting the/) { 120aa5d9151SArjan van de Ven $done = 1; 121aa5d9151SArjan van de Ven } 12280a398a5SArjan van de Ven if ($line =~ /Freeing unused kernel memory/) { 12380a398a5SArjan van de Ven $done = 1; 12480a398a5SArjan van de Ven } 125aa5d9151SArjan van de Ven} 126aa5d9151SArjan van de Ven 127aa5d9151SArjan van de Venif ($count == 0) { 128d1aaf8cfSStephen Hemminger print STDERR <<END; 129d1aaf8cfSStephen HemmingerNo data found in the dmesg. Make sure that 'printk.time=1' and 130d1aaf8cfSStephen Hemminger'initcall_debug' are passed on the kernel command line. 131d1aaf8cfSStephen HemmingerEND 13267554faaSFabian Frederick help(1); 133d1aaf8cfSStephen Hemminger exit 1; 134aa5d9151SArjan van de Ven} 135aa5d9151SArjan van de Ven 136aa5d9151SArjan van de Venprint "<?xml version=\"1.0\" standalone=\"no\"?> \n"; 13740c8c85aSArjan van de Venprint "<svg width=\"2000\" height=\"100%\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n"; 138aa5d9151SArjan van de Ven 13967554faaSFabian Frederick 14067554faaSFabian Frederickif ($header) { 14167554faaSFabian Frederick my $version = `uname -a`; 14267554faaSFabian Frederick my $date = `date`; 14367554faaSFabian Frederick print "<text transform=\"translate($xheader,$yheader)\">Kernel version: $version</text>\n"; 14467554faaSFabian Frederick $cyheader = $yheader+$headerstep; 14567554faaSFabian Frederick print "<text transform=\"translate($xheader,$cyheader)\">Date: $date</text>\n"; 14667554faaSFabian Frederick} 14767554faaSFabian Frederick 148aa5d9151SArjan van de Venmy @styles; 149aa5d9151SArjan van de Ven 150aa5d9151SArjan van de Ven$styles[0] = "fill:rgb(0,0,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 151aa5d9151SArjan van de Ven$styles[1] = "fill:rgb(0,255,0);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 152aa5d9151SArjan van de Ven$styles[2] = "fill:rgb(255,0,20);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 153aa5d9151SArjan van de Ven$styles[3] = "fill:rgb(255,255,20);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 154aa5d9151SArjan van de Ven$styles[4] = "fill:rgb(255,0,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 155aa5d9151SArjan van de Ven$styles[5] = "fill:rgb(0,255,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 156aa5d9151SArjan van de Ven$styles[6] = "fill:rgb(0,128,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 157aa5d9151SArjan van de Ven$styles[7] = "fill:rgb(0,255,128);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 158aa5d9151SArjan van de Ven$styles[8] = "fill:rgb(255,0,128);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 159aa5d9151SArjan van de Ven$styles[9] = "fill:rgb(255,255,128);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 160aa5d9151SArjan van de Ven$styles[10] = "fill:rgb(255,128,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 161aa5d9151SArjan van de Ven$styles[11] = "fill:rgb(128,255,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 162aa5d9151SArjan van de Ven 163d3f8ddeaSArjan van de Venmy $style_wait = "fill:rgb(128,128,128);fill-opacity:0.5;stroke-width:0;stroke:rgb(0,0,0)"; 164d3f8ddeaSArjan van de Ven 16540c8c85aSArjan van de Venmy $mult = 1950.0 / ($maxtime - $firsttime); 16640c8c85aSArjan van de Venmy $threshold2 = ($maxtime - $firsttime) / 120.0; 16740c8c85aSArjan van de Venmy $threshold = $threshold2/10; 168aa5d9151SArjan van de Venmy $stylecounter = 0; 169ddc7a01aSFrederic Weisbeckermy %rows; 170ddc7a01aSFrederic Weisbeckermy $rowscount = 1; 17106d1cd26SAlan Jenkinsmy @initcalls = sort { $start{$a} <=> $start{$b} } keys(%start); 17268f96c0cSStephen Hemminger 17368f96c0cSStephen Hemmingerforeach my $key (@initcalls) { 174aa5d9151SArjan van de Ven my $duration = $end{$key} - $start{$key}; 175aa5d9151SArjan van de Ven 176aa5d9151SArjan van de Ven if ($duration >= $threshold) { 17740c8c85aSArjan van de Ven my ($s, $s2, $s3, $e, $w, $y, $y2, $style); 1782a813f8cSAlan Jenkins my $pid = $pids{$key}; 17907d18904SFrederic Weisbecker 18007d18904SFrederic Weisbecker if (!defined($rows{$pid})) { 18107d18904SFrederic Weisbecker $rows{$pid} = $rowscount; 18207d18904SFrederic Weisbecker $rowscount = $rowscount + 1; 18307d18904SFrederic Weisbecker } 18406d1cd26SAlan Jenkins $s = ($start{$key} - $firsttime) * $mult; 185aa5d9151SArjan van de Ven $s2 = $s + 6; 18640c8c85aSArjan van de Ven $s3 = $s + 1; 18780a398a5SArjan van de Ven $e = ($end{$key} - $firsttime) * $mult; 188aa5d9151SArjan van de Ven $w = $e - $s; 189aa5d9151SArjan van de Ven 190ddc7a01aSFrederic Weisbecker $y = $rows{$pid} * 150; 191aa5d9151SArjan van de Ven $y2 = $y + 4; 192aa5d9151SArjan van de Ven 193aa5d9151SArjan van de Ven $style = $styles[$stylecounter]; 194aa5d9151SArjan van de Ven $stylecounter = $stylecounter + 1; 195aa5d9151SArjan van de Ven if ($stylecounter > 11) { 196aa5d9151SArjan van de Ven $stylecounter = 0; 197aa5d9151SArjan van de Ven }; 198aa5d9151SArjan van de Ven 199d3f8ddeaSArjan van de Ven if ($type{$key} == 1) { 200d3f8ddeaSArjan van de Ven $y = $y + 15; 201d3f8ddeaSArjan van de Ven print "<rect x=\"$s\" width=\"$w\" y=\"$y\" height=\"115\" style=\"$style_wait\"/>\n"; 202d3f8ddeaSArjan van de Ven } else { 203aa5d9151SArjan van de Ven print "<rect x=\"$s\" width=\"$w\" y=\"$y\" height=\"145\" style=\"$style\"/>\n"; 20440c8c85aSArjan van de Ven if ($duration >= $threshold2) { 205aa5d9151SArjan van de Ven print "<text transform=\"translate($s2,$y2) rotate(90)\">$key</text>\n"; 20640c8c85aSArjan van de Ven } else { 20740c8c85aSArjan van de Ven print "<text transform=\"translate($s3,$y2) rotate(90)\" font-size=\"3pt\">$key</text>\n"; 20840c8c85aSArjan van de Ven } 209aa5d9151SArjan van de Ven } 210aa5d9151SArjan van de Ven } 211d3f8ddeaSArjan van de Ven} 212aa5d9151SArjan van de Ven 213aa5d9151SArjan van de Ven 214aa5d9151SArjan van de Ven# print the time line on top 21580a398a5SArjan van de Venmy $time = $firsttime; 21680a398a5SArjan van de Venmy $step = ($maxtime - $firsttime) / 15; 217aa5d9151SArjan van de Venwhile ($time < $maxtime) { 2182a813f8cSAlan Jenkins my $s3 = ($time - $firsttime) * $mult; 21980a398a5SArjan van de Ven my $tm = int($time * 100) / 100.0; 2202a813f8cSAlan Jenkins print "<text transform=\"translate($s3,89) rotate(90)\">$tm</text>\n"; 22180a398a5SArjan van de Ven $time = $time + $step; 222aa5d9151SArjan van de Ven} 223aa5d9151SArjan van de Ven 224aa5d9151SArjan van de Venprint "</svg>\n"; 225