summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2016-06-29 23:56:47 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2016-07-31 11:27:59 +0200
commita02d1988b56f87fcce292f4f2f89b063a97ee7ea (patch)
tree7db41139fe97aef5984b4535248ebb627fa1e90f
parents390/als: print machine type on facility mismatch (diff)
downloadlinux-a02d1988b56f87fcce292f4f2f89b063a97ee7ea.tar.xz
linux-a02d1988b56f87fcce292f4f2f89b063a97ee7ea.zip
s390/als: print missing facilities on facility mismatch
If the kernel needs more facilities to run than the machine provides it is running on, print the facility bit numbers which are missing. This allows to easily tell what went wrong and if simply the machine does not provide a required facility or if either the kernel or the hypervisor may have a bug. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Reviewed-by: Sascha Silbe <silbe@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/kernel/als.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/arch/s390/kernel/als.c b/arch/s390/kernel/als.c
index 0eff858c2434..a16e9d1bf9e3 100644
--- a/arch/s390/kernel/als.c
+++ b/arch/s390/kernel/als.c
@@ -44,10 +44,58 @@ static void __init print_machine_type(void)
_sclp_print_early(mach_str);
}
+static void __init u16_to_decimal(char *str, u16 val)
+{
+ int div = 1;
+
+ while (div * 10 <= val)
+ div *= 10;
+ while (div) {
+ *str++ = '0' + val / div;
+ val %= div;
+ div /= 10;
+ }
+ *str = '\0';
+}
+
+static void __init print_missing_facilities(void)
+{
+ static char als_str[80] __initdata = "Missing facilities: ";
+ unsigned long val;
+ char val_str[6];
+ int i, j, first;
+
+ first = 1;
+ for (i = 0; i < ARRAY_SIZE(als); i++) {
+ val = ~S390_lowcore.stfle_fac_list[i] & als[i];
+ for (j = 0; j < BITS_PER_LONG; j++) {
+ if (!(val & (1UL << (BITS_PER_LONG - 1 - j))))
+ continue;
+ if (!first)
+ strcat(als_str, ",");
+ /*
+ * Make sure we stay within one line. Consider that
+ * each facility bit adds up to five characters and
+ * z/VM adds a four character prefix.
+ */
+ if (strlen(als_str) > 70) {
+ _sclp_print_early(als_str);
+ *als_str = '\0';
+ }
+ u16_to_decimal(val_str, i * BITS_PER_LONG + j);
+ strcat(als_str, val_str);
+ first = 0;
+ }
+ }
+ _sclp_print_early(als_str);
+ _sclp_print_early("See Principles of Operations for facility bits");
+}
+
static void __init facility_mismatch(void)
{
_sclp_print_early("The Linux kernel requires more recent processor hardware");
print_machine_type();
+ print_missing_facilities();
disabled_wait(0x8badcccc);
}