https://github.com/torvalds/linux
Revision b5b1404d0815894de0690de8a1ab58269e56eae6 authored by Linus Torvalds on 12 August 2018, 19:19:42 UTC, committed by Linus Torvalds on 12 August 2018, 19:19:42 UTC
This is purely a preparatory patch for upcoming changes during the 4.19
merge window.

We have a function called "boot_cpu_state_init()" that isn't really
about the bootup cpu state: that is done much earlier by the similarly
named "boot_cpu_init()" (note lack of "state" in name).

This function initializes some hotplug CPU state, and needs to run after
the percpu data has been properly initialized.  It even has a comment to
that effect.

Except it _doesn't_ actually run after the percpu data has been properly
initialized.  On x86 it happens to do that, but on at least arm and
arm64, the percpu base pointers are initialized by the arch-specific
'smp_prepare_boot_cpu()' hook, which ran _after_ boot_cpu_state_init().

This had some unexpected results, and in particular we have a patch
pending for the merge window that did the obvious cleanup of using
'this_cpu_write()' in the cpu hotplug init code:

  -       per_cpu_ptr(&cpuhp_state, smp_processor_id())->state = CPUHP_ONLINE;
  +       this_cpu_write(cpuhp_state.state, CPUHP_ONLINE);

which is obviously the right thing to do.  Except because of the
ordering issue, it actually failed miserably and unexpectedly on arm64.

So this just fixes the ordering, and changes the name of the function to
be 'boot_cpu_hotplug_init()' to make it obvious that it's about cpu
hotplug state, because the core CPU state was supposed to have already
been done earlier.

Marked for stable, since the (not yet merged) patch that will show this
problem is marked for stable.

Reported-by: Vlastimil Babka <vbabka@suse.cz>
Reported-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
Suggested-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Will Deacon <will.deacon@arm.com>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent d6dd643
Raw File
Tip revision: b5b1404d0815894de0690de8a1ab58269e56eae6 authored by Linus Torvalds on 12 August 2018, 19:19:42 UTC
init: rename and re-order boot_cpu_state_init()
Tip revision: b5b1404
extract-module-sig.pl
#!/usr/bin/env perl
# SPDX-License-Identifier: GPL-2.0
#
# extract-mod-sig <part> <module-file>
#
# Reads the module file and writes out some or all of the signature
# section to stdout.  Part is the bit to be written and is one of:
#
#  -0: The unsigned module, no signature data at all
#  -a: All of the signature data, including magic number
#  -d: Just the descriptor values as a sequence of numbers
#  -n: Just the signer's name
#  -k: Just the key ID
#  -s: Just the crypto signature or PKCS#7 message
#
use warnings;
use strict;

die "Format: $0 -[0adnks] module-file >out\n"
    if ($#ARGV != 1);

my $part = $ARGV[0];
my $modfile = $ARGV[1];

my $magic_number = "~Module signature appended~\n";

#
# Read the module contents
#
open FD, "<$modfile" || die $modfile;
binmode(FD);
my @st = stat(FD);
die "$modfile" unless (@st);
my $buf = "";
my $len = sysread(FD, $buf, $st[7]);
die "$modfile" unless (defined($len));
die "Short read on $modfile\n" unless ($len == $st[7]);
close(FD) || die $modfile;

print STDERR "Read ", $len, " bytes from module file\n";

die "The file is too short to have a sig magic number and descriptor\n"
    if ($len < 12 + length($magic_number));

#
# Check for the magic number and extract the information block
#
my $p = $len - length($magic_number);
my $raw_magic = substr($buf, $p);

die "Magic number not found at $len\n"
    if ($raw_magic ne $magic_number);
print STDERR "Found magic number at $len\n";

$p -= 12;
my $raw_info = substr($buf, $p, 12);

my @info = unpack("CCCCCxxxN", $raw_info);
my ($algo, $hash, $id_type, $name_len, $kid_len, $sig_len) = @info;

if ($id_type == 0) {
    print STDERR "Found PGP key identifier\n";
} elsif ($id_type == 1) {
    print STDERR "Found X.509 cert identifier\n";
} elsif ($id_type == 2) {
    print STDERR "Found PKCS#7/CMS encapsulation\n";
} else {
    print STDERR "Found unsupported identifier type $id_type\n";
}

#
# Extract the three pieces of info data
#
die "Insufficient name+kid+sig data in file\n"
    unless ($p >= $name_len + $kid_len + $sig_len);

$p -= $sig_len;
my $raw_sig = substr($buf, $p, $sig_len);
$p -= $kid_len;
my $raw_kid = substr($buf, $p, $kid_len);
$p -= $name_len;
my $raw_name = substr($buf, $p, $name_len);

my $module_len = $p;

if ($sig_len > 0) {
    print STDERR "Found $sig_len bytes of signature [";
    my $n = $sig_len > 16 ? 16 : $sig_len;
    foreach my $i (unpack("C" x $n, substr($raw_sig, 0, $n))) {
	printf STDERR "%02x", $i;
    }
    print STDERR "]\n";
}

if ($kid_len > 0) {
    print STDERR "Found $kid_len bytes of key identifier [";
    my $n = $kid_len > 16 ? 16 : $kid_len;
    foreach my $i (unpack("C" x $n, substr($raw_kid, 0, $n))) {
	printf STDERR "%02x", $i;
    }
    print STDERR "]\n";
}

if ($name_len > 0) {
    print STDERR "Found $name_len bytes of signer's name [$raw_name]\n";
}

#
# Produce the requested output
#
if ($part eq "-0") {
    # The unsigned module, no signature data at all
    binmode(STDOUT);
    print substr($buf, 0, $module_len);
} elsif ($part eq "-a") {
    # All of the signature data, including magic number
    binmode(STDOUT);
    print substr($buf, $module_len);
} elsif ($part eq "-d") {
    # Just the descriptor values as a sequence of numbers
    print join(" ", @info), "\n";
} elsif ($part eq "-n") {
    # Just the signer's name
    print STDERR "No signer's name for PKCS#7 message type sig\n"
	if ($id_type == 2);
    binmode(STDOUT);
    print $raw_name;
} elsif ($part eq "-k") {
    # Just the key identifier
    print STDERR "No key ID for PKCS#7 message type sig\n"
	if ($id_type == 2);
    binmode(STDOUT);
    print $raw_kid;
} elsif ($part eq "-s") {
    # Just the crypto signature or PKCS#7 message
    binmode(STDOUT);
    print $raw_sig;
}
back to top