mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

Similar to x86 and loongarch add a "debug-alternative" command line parameter, which allows for alternative debugging. The parameter itself comes with architecture specific semantics: "debug-alternative" -> print debug message for every single alternative "debug-alternative=0;2" -> print debug message for all alternatives with type 0 and 2 "debug-alternative=0:0-7" -> print debug message for all alternatives with type 0 which have a facility number within the range of 0-7 "debug-alternative=0:!8;1" -> print debug message for all alternatives with type 0, for all facility numbers, except facility 8, and in addition print all alternatives with type 1 A defconfig build currently results in a kernel with more than 20.000 alternatives, where the majority is for the niai alternative (spinlocks), and the relocated lowcore alternative. The following kernel command like options limit alternative debug output, and enable dynamic debug messages: debug-alternative=0:!49;1:!0 earlyprintk bootdebug ignore_loglevel loglevel=8 dyndbg="file alternative.c +p" This results in output like this: alt: [0/ 11] 0000021b9ce8680c: c0f400000089 -> c00400000000 alt: [0/ 64] 0000021b9ce87e60: c0f400000043 -> c00400000000 alt: [0/133] 0000021b9ce88c56: c0f400000027 -> c00400000000 alt: [0/ 74] 0000021b9ce89410: c0f40000002a -> c00400000000 alt: [0/ 40] 0000021b9dc3720a: 47000000 -> b280d398 alt: [0/193] 0000021b9dc37306: 47000000 -> b201d2b0 alt: [0/193] 0000021b9dc37354: c00400000000 -> d20720c0d2b0 alt: [1/ 5] 0000038d720d7bf2: c0f400000016 -> c00400000000 With [<alternative type>/<alternative data>] <address> oldcode -> newcode Alternative data depends on the alternative type: for type 0 (ALT_TYPE_FACILITY) data is the facility. For type 1 (ALT_TYPE_FEATURE) data is the corresponding machine feature. Acked-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
138 lines
2.7 KiB
C
138 lines
2.7 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#define boot_fmt(fmt) "alt: " fmt
|
|
#include "boot.h"
|
|
|
|
#define a_debug boot_debug
|
|
|
|
#include "../kernel/alternative.c"
|
|
|
|
static void alt_debug_all(int type)
|
|
{
|
|
int i;
|
|
|
|
switch (type) {
|
|
case ALT_TYPE_FACILITY:
|
|
for (i = 0; i < ARRAY_SIZE(alt_debug.facilities); i++)
|
|
alt_debug.facilities[i] = -1UL;
|
|
break;
|
|
case ALT_TYPE_FEATURE:
|
|
for (i = 0; i < ARRAY_SIZE(alt_debug.mfeatures); i++)
|
|
alt_debug.mfeatures[i] = -1UL;
|
|
break;
|
|
case ALT_TYPE_SPEC:
|
|
alt_debug.spec = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void alt_debug_modify(int type, unsigned int nr, bool clear)
|
|
{
|
|
switch (type) {
|
|
case ALT_TYPE_FACILITY:
|
|
if (clear)
|
|
__clear_facility(nr, alt_debug.facilities);
|
|
else
|
|
__set_facility(nr, alt_debug.facilities);
|
|
break;
|
|
case ALT_TYPE_FEATURE:
|
|
if (clear)
|
|
__clear_machine_feature(nr, alt_debug.mfeatures);
|
|
else
|
|
__set_machine_feature(nr, alt_debug.mfeatures);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static char *alt_debug_parse(int type, char *str)
|
|
{
|
|
unsigned long val, endval;
|
|
char *endp;
|
|
bool clear;
|
|
int i;
|
|
|
|
if (*str == ':') {
|
|
str++;
|
|
} else {
|
|
alt_debug_all(type);
|
|
return str;
|
|
}
|
|
clear = false;
|
|
if (*str == '!') {
|
|
alt_debug_all(type);
|
|
clear = true;
|
|
str++;
|
|
}
|
|
while (*str) {
|
|
val = simple_strtoull(str, &endp, 0);
|
|
if (str == endp)
|
|
break;
|
|
str = endp;
|
|
if (*str == '-') {
|
|
str++;
|
|
endval = simple_strtoull(str, &endp, 0);
|
|
if (str == endp)
|
|
break;
|
|
str = endp;
|
|
while (val <= endval) {
|
|
alt_debug_modify(type, val, clear);
|
|
val++;
|
|
}
|
|
} else {
|
|
alt_debug_modify(type, val, clear);
|
|
}
|
|
if (*str != ',')
|
|
break;
|
|
str++;
|
|
}
|
|
return str;
|
|
}
|
|
|
|
/*
|
|
* Use debug-alternative command line parameter for debugging:
|
|
* "debug-alternative"
|
|
* -> print debug message for every single alternative
|
|
*
|
|
* "debug-alternative=0;2"
|
|
* -> print debug message for all alternatives with type 0 and 2
|
|
*
|
|
* "debug-alternative=0:0-7"
|
|
* -> print debug message for all alternatives with type 0 and with
|
|
* facility numbers within the range of 0-7
|
|
* (if type 0 is ALT_TYPE_FACILITY)
|
|
*
|
|
* "debug-alternative=0:!8;1"
|
|
* -> print debug message for all alternatives with type 0, for all
|
|
* facility number, except facility 8, and in addition print all
|
|
* alternatives with type 1
|
|
*/
|
|
void alt_debug_setup(char *str)
|
|
{
|
|
unsigned long type;
|
|
char *endp;
|
|
int i;
|
|
|
|
if (!str) {
|
|
alt_debug_all(ALT_TYPE_FACILITY);
|
|
alt_debug_all(ALT_TYPE_FEATURE);
|
|
alt_debug_all(ALT_TYPE_SPEC);
|
|
return;
|
|
}
|
|
while (*str) {
|
|
type = simple_strtoull(str, &endp, 0);
|
|
if (str == endp)
|
|
break;
|
|
str = endp;
|
|
switch (type) {
|
|
case ALT_TYPE_FACILITY:
|
|
case ALT_TYPE_FEATURE:
|
|
str = alt_debug_parse(type, str);
|
|
break;
|
|
case ALT_TYPE_SPEC:
|
|
alt_debug_all(ALT_TYPE_SPEC);
|
|
break;
|
|
}
|
|
if (*str != ';')
|
|
break;
|
|
str++;
|
|
}
|
|
}
|