--- zzzz-none-000/linux-2.6.39.4/tools/testing/ktest/ktest.pl 2011-08-03 19:43:28.000000000 +0000 +++ puma6-atom-6490-729/linux-2.6.39.4/tools/testing/ktest/ktest.pl 2021-11-10 13:38:18.000000000 +0000 @@ -947,11 +947,17 @@ sub make_oldconfig { my ($defconfig) = @_; - if (!run_command "$defconfig $make oldnoconfig") { - # Perhaps oldnoconfig doesn't exist in this version of the kernel + my @force_list = keys %force_config; + + if ($#force_list >= 0) { + apply_min_config; + } + + if (!run_command "$make olddefconfig") { + # Perhaps olddefconfig doesn't exist in this version of the kernel # try a yes '' | oldconfig - doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; - run_command "yes '' | $defconfig $make oldconfig" or + doprint "olddefconfig failed, trying yes '' | make oldconfig\n"; + run_command "yes '' | $make oldconfig" or dodie "failed make config oldconfig"; } } @@ -971,7 +977,7 @@ # old config can ask questions if ($type eq "oldconfig") { - $type = "oldnoconfig"; + $type = "olddefconfig"; # allow for empty configs run_command "touch $output_config"; @@ -1001,10 +1007,8 @@ $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; } - if ($type eq "oldnoconfig") { - make_oldconfig $defconfig; - } else { - run_command "$defconfig $make $type" or + if ($type ne "olddefconfig") { + run_command "$make $type" or dodie "failed make config"; } @@ -1403,6 +1407,15 @@ my %config_ignore; my %config_set; +# config_off holds the set of configs that the bad config had disabled. +# We need to record them and set them in the .config when running +# olddefconfig, because olddefconfig keeps the defaults. +my %config_off; + +# config_off_tmp holds a set of configs to turn off for now +my @config_off_tmp; + +# config_list is the set of configs that are being tested my %config_list; my %null_config; @@ -1861,6 +1874,542 @@ return 1; } +my %depends; +my %depcount; +my $iflevel = 0; +my @ifdeps; + +# prevent recursion +my %read_kconfigs; + +sub add_dep { + # $config depends on $dep + my ($config, $dep) = @_; + + if (defined($depends{$config})) { + $depends{$config} .= " " . $dep; + } else { + $depends{$config} = $dep; + } + + # record the number of configs depending on $dep + if (defined $depcount{$dep}) { + $depcount{$dep}++; + } else { + $depcount{$dep} = 1; + } +} + +# taken from streamline_config.pl +sub read_kconfig { + my ($kconfig) = @_; + + my $state = "NONE"; + my $config; + my @kconfigs; + + my $cont = 0; + my $line; + + + if (! -f $kconfig) { + doprint "file $kconfig does not exist, skipping\n"; + return; + } + + open(KIN, "$kconfig") + or die "Can't open $kconfig"; + while () { + chomp; + + # Make sure that lines ending with \ continue + if ($cont) { + $_ = $line . " " . $_; + } + + if (s/\\$//) { + $cont = 1; + $line = $_; + next; + } + + $cont = 0; + + # collect any Kconfig sources + if (/^source\s*"(.*)"/) { + $kconfigs[$#kconfigs+1] = $1; + } + + # configs found + if (/^\s*(menu)?config\s+(\S+)\s*$/) { + $state = "NEW"; + $config = $2; + + for (my $i = 0; $i < $iflevel; $i++) { + add_dep $config, $ifdeps[$i]; + } + + # collect the depends for the config + } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { + + add_dep $config, $1; + + # Get the configs that select this config + } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) { + + # selected by depends on config + add_dep $1, $config; + + # Check for if statements + } elsif (/^if\s+(.*\S)\s*$/) { + my $deps = $1; + # remove beginning and ending non text + $deps =~ s/^[^a-zA-Z0-9_]*//; + $deps =~ s/[^a-zA-Z0-9_]*$//; + + my @deps = split /[^a-zA-Z0-9_]+/, $deps; + + $ifdeps[$iflevel++] = join ':', @deps; + + } elsif (/^endif/) { + + $iflevel-- if ($iflevel); + + # stop on "help" + } elsif (/^\s*help\s*$/) { + $state = "NONE"; + } + } + close(KIN); + + # read in any configs that were found. + foreach $kconfig (@kconfigs) { + if (!defined($read_kconfigs{$kconfig})) { + $read_kconfigs{$kconfig} = 1; + read_kconfig("$builddir/$kconfig"); + } + } +} + +sub read_depends { + # find out which arch this is by the kconfig file + open (IN, $output_config) + or dodie "Failed to read $output_config"; + my $arch; + while () { + if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) { + $arch = $1; + last; + } + } + close IN; + + if (!defined($arch)) { + doprint "Could not find arch from config file\n"; + doprint "no dependencies used\n"; + return; + } + + # arch is really the subarch, we need to know + # what directory to look at. + if ($arch eq "i386" || $arch eq "x86_64") { + $arch = "x86"; + } elsif ($arch =~ /^tile/) { + $arch = "tile"; + } + + my $kconfig = "$builddir/arch/$arch/Kconfig"; + + if (! -f $kconfig && $arch =~ /\d$/) { + my $orig = $arch; + # some subarchs have numbers, truncate them + $arch =~ s/\d*$//; + $kconfig = "$builddir/arch/$arch/Kconfig"; + if (! -f $kconfig) { + doprint "No idea what arch dir $orig is for\n"; + doprint "no dependencies used\n"; + return; + } + } + + read_kconfig($kconfig); +} + +sub read_config_list { + my ($config) = @_; + + open (IN, $config) + or dodie "Failed to read $config"; + + while () { + if (/^((CONFIG\S*)=.*)/) { + if (!defined($config_ignore{$2})) { + $config_list{$2} = $1; + } + } + } + + close(IN); +} + +sub read_output_config { + my ($config) = @_; + + assign_configs \%config_ignore, $config; +} + +sub make_new_config { + my @configs = @_; + + open (OUT, ">$output_config") + or dodie "Failed to write $output_config"; + + foreach my $config (@configs) { + print OUT "$config\n"; + } + close OUT; +} + +sub chomp_config { + my ($config) = @_; + + $config =~ s/CONFIG_//; + + return $config; +} + +sub get_depends { + my ($dep) = @_; + + my $kconfig = chomp_config $dep; + + $dep = $depends{"$kconfig"}; + + # the dep string we have saves the dependencies as they + # were found, including expressions like ! && ||. We + # want to split this out into just an array of configs. + + my $valid = "A-Za-z_0-9"; + + my @configs; + + while ($dep =~ /[$valid]/) { + + if ($dep =~ /^[^$valid]*([$valid]+)/) { + my $conf = "CONFIG_" . $1; + + $configs[$#configs + 1] = $conf; + + $dep =~ s/^[^$valid]*[$valid]+//; + } else { + die "this should never happen"; + } + } + + return @configs; +} + +my %min_configs; +my %keep_configs; +my %save_configs; +my %processed_configs; +my %nochange_config; + +sub test_this_config { + my ($config) = @_; + + my $found; + + # if we already processed this config, skip it + if (defined($processed_configs{$config})) { + return undef; + } + $processed_configs{$config} = 1; + + # if this config failed during this round, skip it + if (defined($nochange_config{$config})) { + return undef; + } + + my $kconfig = chomp_config $config; + + # Test dependencies first + if (defined($depends{"$kconfig"})) { + my @parents = get_depends $config; + foreach my $parent (@parents) { + # if the parent is in the min config, check it first + next if (!defined($min_configs{$parent})); + $found = test_this_config($parent); + if (defined($found)) { + return $found; + } + } + } + + # Remove this config from the list of configs + # do a make olddefconfig and then read the resulting + # .config to make sure it is missing the config that + # we had before + my %configs = %min_configs; + delete $configs{$config}; + make_new_config ((values %configs), (values %keep_configs)); + make_oldconfig; + undef %configs; + assign_configs \%configs, $output_config; + + return $config if (!defined($configs{$config})); + + doprint "disabling config $config did not change .config\n"; + + $nochange_config{$config} = 1; + + return undef; +} + +sub make_min_config { + my ($i) = @_; + + my $type = $minconfig_type; + if ($type ne "boot" && $type ne "test") { + fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" . + " make_min_config works only with 'boot' and 'test'\n" and return; + } + + if (!defined($output_minconfig)) { + fail "OUTPUT_MIN_CONFIG not defined" and return; + } + + # If output_minconfig exists, and the start_minconfig + # came from min_config, than ask if we should use + # that instead. + if (-f $output_minconfig && !$start_minconfig_defined) { + print "$output_minconfig exists\n"; + if (!defined($use_output_minconfig)) { + if (read_yn " Use it as minconfig?") { + $start_minconfig = $output_minconfig; + } + } elsif ($use_output_minconfig > 0) { + doprint "Using $output_minconfig as MIN_CONFIG\n"; + $start_minconfig = $output_minconfig; + } else { + doprint "Set to still use MIN_CONFIG as starting point\n"; + } + } + + if (!defined($start_minconfig)) { + fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return; + } + + my $temp_config = "$tmpdir/temp_config"; + + # First things first. We build an allnoconfig to find + # out what the defaults are that we can't touch. + # Some are selections, but we really can't handle selections. + + my $save_minconfig = $minconfig; + undef $minconfig; + + run_command "$make allnoconfig" or return 0; + + read_depends; + + process_config_ignore $output_config; + + undef %save_configs; + undef %min_configs; + + if (defined($ignore_config)) { + # make sure the file exists + `touch $ignore_config`; + assign_configs \%save_configs, $ignore_config; + } + + %keep_configs = %save_configs; + + doprint "Load initial configs from $start_minconfig\n"; + + # Look at the current min configs, and save off all the + # ones that were set via the allnoconfig + assign_configs \%min_configs, $start_minconfig; + + my @config_keys = keys %min_configs; + + # All configs need a depcount + foreach my $config (@config_keys) { + my $kconfig = chomp_config $config; + if (!defined $depcount{$kconfig}) { + $depcount{$kconfig} = 0; + } + } + + # Remove anything that was set by the make allnoconfig + # we shouldn't need them as they get set for us anyway. + foreach my $config (@config_keys) { + # Remove anything in the ignore_config + if (defined($keep_configs{$config})) { + my $file = $ignore_config; + $file =~ s,.*/(.*?)$,$1,; + doprint "$config set by $file ... ignored\n"; + delete $min_configs{$config}; + next; + } + # But make sure the settings are the same. If a min config + # sets a selection, we do not want to get rid of it if + # it is not the same as what we have. Just move it into + # the keep configs. + if (defined($config_ignore{$config})) { + if ($config_ignore{$config} ne $min_configs{$config}) { + doprint "$config is in allnoconfig as '$config_ignore{$config}'"; + doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n"; + $keep_configs{$config} = $min_configs{$config}; + } else { + doprint "$config set by allnoconfig ... ignored\n"; + } + delete $min_configs{$config}; + } + } + + my $done = 0; + my $take_two = 0; + + while (!$done) { + + my $config; + my $found; + + # Now disable each config one by one and do a make oldconfig + # till we find a config that changes our list. + + my @test_configs = keys %min_configs; + + # Sort keys by who is most dependent on + @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} } + @test_configs ; + + # Put configs that did not modify the config at the end. + my $reset = 1; + for (my $i = 0; $i < $#test_configs; $i++) { + if (!defined($nochange_config{$test_configs[0]})) { + $reset = 0; + last; + } + # This config didn't change the .config last time. + # Place it at the end + my $config = shift @test_configs; + push @test_configs, $config; + } + + # if every test config has failed to modify the .config file + # in the past, then reset and start over. + if ($reset) { + undef %nochange_config; + } + + undef %processed_configs; + + foreach my $config (@test_configs) { + + $found = test_this_config $config; + + last if (defined($found)); + + # oh well, try another config + } + + if (!defined($found)) { + # we could have failed due to the nochange_config hash + # reset and try again + if (!$take_two) { + undef %nochange_config; + $take_two = 1; + next; + } + doprint "No more configs found that we can disable\n"; + $done = 1; + last; + } + $take_two = 0; + + $config = $found; + + doprint "Test with $config disabled\n"; + + # set in_bisect to keep build and monitor from dieing + $in_bisect = 1; + + my $failed = 0; + build "oldconfig" or $failed = 1; + if (!$failed) { + start_monitor_and_boot or $failed = 1; + + if ($type eq "test" && !$failed) { + do_run_test or $failed = 1; + } + + end_monitor; + } + + $in_bisect = 0; + + if ($failed) { + doprint "$min_configs{$config} is needed to boot the box... keeping\n"; + # this config is needed, add it to the ignore list. + $keep_configs{$config} = $min_configs{$config}; + $save_configs{$config} = $min_configs{$config}; + delete $min_configs{$config}; + + # update new ignore configs + if (defined($ignore_config)) { + open (OUT, ">$temp_config") + or die "Can't write to $temp_config"; + foreach my $config (keys %save_configs) { + print OUT "$save_configs{$config}\n"; + } + close OUT; + run_command "mv $temp_config $ignore_config" or + dodie "failed to copy update to $ignore_config"; + } + + } else { + # We booted without this config, remove it from the minconfigs. + doprint "$config is not needed, disabling\n"; + + delete $min_configs{$config}; + + # Also disable anything that is not enabled in this config + my %configs; + assign_configs \%configs, $output_config; + my @config_keys = keys %min_configs; + foreach my $config (@config_keys) { + if (!defined($configs{$config})) { + doprint "$config is not set, disabling\n"; + delete $min_configs{$config}; + } + } + + # Save off all the current mandidory configs + open (OUT, ">$temp_config") + or die "Can't write to $temp_config"; + foreach my $config (keys %keep_configs) { + print OUT "$keep_configs{$config}\n"; + } + foreach my $config (keys %min_configs) { + print OUT "$min_configs{$config}\n"; + } + close OUT; + + run_command "mv $temp_config $output_minconfig" or + dodie "failed to copy update to $output_minconfig"; + } + + doprint "Reboot and wait $sleep_time seconds\n"; + reboot_to_good $sleep_time; + } + + success $i; + return 1; +} + $#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; if ($#ARGV == 0) {