diff options
Diffstat (limited to 'arch/s390/kernel/setup.c')
-rw-r--r-- | arch/s390/kernel/setup.c | 185 |
1 files changed, 54 insertions, 131 deletions
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 400b040df7fa..b7a1efd5522c 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -14,6 +14,9 @@ | |||
14 | * This file handles the architecture-dependent parts of initialization | 14 | * This file handles the architecture-dependent parts of initialization |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define KMSG_COMPONENT "setup" | ||
18 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
19 | |||
17 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
18 | #include <linux/module.h> | 21 | #include <linux/module.h> |
19 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
@@ -32,7 +35,6 @@ | |||
32 | #include <linux/bootmem.h> | 35 | #include <linux/bootmem.h> |
33 | #include <linux/root_dev.h> | 36 | #include <linux/root_dev.h> |
34 | #include <linux/console.h> | 37 | #include <linux/console.h> |
35 | #include <linux/seq_file.h> | ||
36 | #include <linux/kernel_stat.h> | 38 | #include <linux/kernel_stat.h> |
37 | #include <linux/device.h> | 39 | #include <linux/device.h> |
38 | #include <linux/notifier.h> | 40 | #include <linux/notifier.h> |
@@ -291,8 +293,8 @@ unsigned int switch_amode = 0; | |||
291 | #endif | 293 | #endif |
292 | EXPORT_SYMBOL_GPL(switch_amode); | 294 | EXPORT_SYMBOL_GPL(switch_amode); |
293 | 295 | ||
294 | static void set_amode_and_uaccess(unsigned long user_amode, | 296 | static int set_amode_and_uaccess(unsigned long user_amode, |
295 | unsigned long user32_amode) | 297 | unsigned long user32_amode) |
296 | { | 298 | { |
297 | psw_user_bits = PSW_BASE_BITS | PSW_MASK_DAT | user_amode | | 299 | psw_user_bits = PSW_BASE_BITS | PSW_MASK_DAT | user_amode | |
298 | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | | 300 | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | |
@@ -309,11 +311,11 @@ static void set_amode_and_uaccess(unsigned long user_amode, | |||
309 | PSW_MASK_MCHECK | PSW_DEFAULT_KEY; | 311 | PSW_MASK_MCHECK | PSW_DEFAULT_KEY; |
310 | 312 | ||
311 | if (MACHINE_HAS_MVCOS) { | 313 | if (MACHINE_HAS_MVCOS) { |
312 | printk("mvcos available.\n"); | ||
313 | memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess)); | 314 | memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess)); |
315 | return 1; | ||
314 | } else { | 316 | } else { |
315 | printk("mvcos not available.\n"); | ||
316 | memcpy(&uaccess, &uaccess_pt, sizeof(uaccess)); | 317 | memcpy(&uaccess, &uaccess_pt, sizeof(uaccess)); |
318 | return 0; | ||
317 | } | 319 | } |
318 | } | 320 | } |
319 | 321 | ||
@@ -328,9 +330,10 @@ static int __init early_parse_switch_amode(char *p) | |||
328 | early_param("switch_amode", early_parse_switch_amode); | 330 | early_param("switch_amode", early_parse_switch_amode); |
329 | 331 | ||
330 | #else /* CONFIG_S390_SWITCH_AMODE */ | 332 | #else /* CONFIG_S390_SWITCH_AMODE */ |
331 | static inline void set_amode_and_uaccess(unsigned long user_amode, | 333 | static inline int set_amode_and_uaccess(unsigned long user_amode, |
332 | unsigned long user32_amode) | 334 | unsigned long user32_amode) |
333 | { | 335 | { |
336 | return 0; | ||
334 | } | 337 | } |
335 | #endif /* CONFIG_S390_SWITCH_AMODE */ | 338 | #endif /* CONFIG_S390_SWITCH_AMODE */ |
336 | 339 | ||
@@ -355,11 +358,20 @@ early_param("noexec", early_parse_noexec); | |||
355 | static void setup_addressing_mode(void) | 358 | static void setup_addressing_mode(void) |
356 | { | 359 | { |
357 | if (s390_noexec) { | 360 | if (s390_noexec) { |
358 | printk("S390 execute protection active, "); | 361 | if (set_amode_and_uaccess(PSW_ASC_SECONDARY, |
359 | set_amode_and_uaccess(PSW_ASC_SECONDARY, PSW32_ASC_SECONDARY); | 362 | PSW32_ASC_SECONDARY)) |
363 | pr_info("Execute protection active, " | ||
364 | "mvcos available\n"); | ||
365 | else | ||
366 | pr_info("Execute protection active, " | ||
367 | "mvcos not available\n"); | ||
360 | } else if (switch_amode) { | 368 | } else if (switch_amode) { |
361 | printk("S390 address spaces switched, "); | 369 | if (set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY)) |
362 | set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY); | 370 | pr_info("Address spaces switched, " |
371 | "mvcos available\n"); | ||
372 | else | ||
373 | pr_info("Address spaces switched, " | ||
374 | "mvcos not available\n"); | ||
363 | } | 375 | } |
364 | #ifdef CONFIG_TRACE_IRQFLAGS | 376 | #ifdef CONFIG_TRACE_IRQFLAGS |
365 | sysc_restore_trace_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; | 377 | sysc_restore_trace_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; |
@@ -572,15 +584,15 @@ setup_memory(void) | |||
572 | start = PFN_PHYS(start_pfn) + bmap_size + PAGE_SIZE; | 584 | start = PFN_PHYS(start_pfn) + bmap_size + PAGE_SIZE; |
573 | 585 | ||
574 | if (start + INITRD_SIZE > memory_end) { | 586 | if (start + INITRD_SIZE > memory_end) { |
575 | printk("initrd extends beyond end of memory " | 587 | pr_err("initrd extends beyond end of " |
576 | "(0x%08lx > 0x%08lx)\n" | 588 | "memory (0x%08lx > 0x%08lx) " |
577 | "disabling initrd\n", | 589 | "disabling initrd\n", |
578 | start + INITRD_SIZE, memory_end); | 590 | start + INITRD_SIZE, memory_end); |
579 | INITRD_START = INITRD_SIZE = 0; | 591 | INITRD_START = INITRD_SIZE = 0; |
580 | } else { | 592 | } else { |
581 | printk("Moving initrd (0x%08lx -> 0x%08lx, " | 593 | pr_info("Moving initrd (0x%08lx -> " |
582 | "size: %ld)\n", | 594 | "0x%08lx, size: %ld)\n", |
583 | INITRD_START, start, INITRD_SIZE); | 595 | INITRD_START, start, INITRD_SIZE); |
584 | memmove((void *) start, (void *) INITRD_START, | 596 | memmove((void *) start, (void *) INITRD_START, |
585 | INITRD_SIZE); | 597 | INITRD_SIZE); |
586 | INITRD_START = start; | 598 | INITRD_START = start; |
@@ -642,8 +654,9 @@ setup_memory(void) | |||
642 | initrd_start = INITRD_START; | 654 | initrd_start = INITRD_START; |
643 | initrd_end = initrd_start + INITRD_SIZE; | 655 | initrd_end = initrd_start + INITRD_SIZE; |
644 | } else { | 656 | } else { |
645 | printk("initrd extends beyond end of memory " | 657 | pr_err("initrd extends beyond end of " |
646 | "(0x%08lx > 0x%08lx)\ndisabling initrd\n", | 658 | "memory (0x%08lx > 0x%08lx) " |
659 | "disabling initrd\n", | ||
647 | initrd_start + INITRD_SIZE, memory_end); | 660 | initrd_start + INITRD_SIZE, memory_end); |
648 | initrd_start = initrd_end = 0; | 661 | initrd_start = initrd_end = 0; |
649 | } | 662 | } |
@@ -651,23 +664,6 @@ setup_memory(void) | |||
651 | #endif | 664 | #endif |
652 | } | 665 | } |
653 | 666 | ||
654 | static int __init __stfle(unsigned long long *list, int doublewords) | ||
655 | { | ||
656 | typedef struct { unsigned long long _[doublewords]; } addrtype; | ||
657 | register unsigned long __nr asm("0") = doublewords - 1; | ||
658 | |||
659 | asm volatile(".insn s,0xb2b00000,%0" /* stfle */ | ||
660 | : "=m" (*(addrtype *) list), "+d" (__nr) : : "cc"); | ||
661 | return __nr + 1; | ||
662 | } | ||
663 | |||
664 | int __init stfle(unsigned long long *list, int doublewords) | ||
665 | { | ||
666 | if (!(stfl() & (1UL << 24))) | ||
667 | return -EOPNOTSUPP; | ||
668 | return __stfle(list, doublewords); | ||
669 | } | ||
670 | |||
671 | /* | 667 | /* |
672 | * Setup hardware capabilities. | 668 | * Setup hardware capabilities. |
673 | */ | 669 | */ |
@@ -739,8 +735,13 @@ static void __init setup_hwcaps(void) | |||
739 | strcpy(elf_platform, "z990"); | 735 | strcpy(elf_platform, "z990"); |
740 | break; | 736 | break; |
741 | case 0x2094: | 737 | case 0x2094: |
738 | case 0x2096: | ||
742 | strcpy(elf_platform, "z9-109"); | 739 | strcpy(elf_platform, "z9-109"); |
743 | break; | 740 | break; |
741 | case 0x2097: | ||
742 | case 0x2098: | ||
743 | strcpy(elf_platform, "z10"); | ||
744 | break; | ||
744 | } | 745 | } |
745 | } | 746 | } |
746 | 747 | ||
@@ -752,25 +753,34 @@ static void __init setup_hwcaps(void) | |||
752 | void __init | 753 | void __init |
753 | setup_arch(char **cmdline_p) | 754 | setup_arch(char **cmdline_p) |
754 | { | 755 | { |
756 | /* set up preferred console */ | ||
757 | add_preferred_console("ttyS", 0, NULL); | ||
758 | |||
755 | /* | 759 | /* |
756 | * print what head.S has found out about the machine | 760 | * print what head.S has found out about the machine |
757 | */ | 761 | */ |
758 | #ifndef CONFIG_64BIT | 762 | #ifndef CONFIG_64BIT |
759 | printk((MACHINE_IS_VM) ? | 763 | if (MACHINE_IS_VM) |
760 | "We are running under VM (31 bit mode)\n" : | 764 | pr_info("Linux is running as a z/VM " |
761 | "We are running native (31 bit mode)\n"); | 765 | "guest operating system in 31-bit mode\n"); |
762 | printk((MACHINE_HAS_IEEE) ? | 766 | else |
763 | "This machine has an IEEE fpu\n" : | 767 | pr_info("Linux is running natively in 31-bit mode\n"); |
764 | "This machine has no IEEE fpu\n"); | 768 | if (MACHINE_HAS_IEEE) |
769 | pr_info("The hardware system has IEEE compatible " | ||
770 | "floating point units\n"); | ||
771 | else | ||
772 | pr_info("The hardware system has no IEEE compatible " | ||
773 | "floating point units\n"); | ||
765 | #else /* CONFIG_64BIT */ | 774 | #else /* CONFIG_64BIT */ |
766 | if (MACHINE_IS_VM) | 775 | if (MACHINE_IS_VM) |
767 | printk("We are running under VM (64 bit mode)\n"); | 776 | pr_info("Linux is running as a z/VM " |
777 | "guest operating system in 64-bit mode\n"); | ||
768 | else if (MACHINE_IS_KVM) { | 778 | else if (MACHINE_IS_KVM) { |
769 | printk("We are running under KVM (64 bit mode)\n"); | 779 | pr_info("Linux is running under KVM in 64-bit mode\n"); |
770 | add_preferred_console("hvc", 0, NULL); | 780 | add_preferred_console("hvc", 0, NULL); |
771 | s390_virtio_console_init(); | 781 | s390_virtio_console_init(); |
772 | } else | 782 | } else |
773 | printk("We are running native (64 bit mode)\n"); | 783 | pr_info("Linux is running natively in 64-bit mode\n"); |
774 | #endif /* CONFIG_64BIT */ | 784 | #endif /* CONFIG_64BIT */ |
775 | 785 | ||
776 | /* Have one command line that is parsed and saved in /proc/cmdline */ | 786 | /* Have one command line that is parsed and saved in /proc/cmdline */ |
@@ -818,90 +828,3 @@ setup_arch(char **cmdline_p) | |||
818 | /* Setup zfcpdump support */ | 828 | /* Setup zfcpdump support */ |
819 | setup_zfcpdump(console_devno); | 829 | setup_zfcpdump(console_devno); |
820 | } | 830 | } |
821 | |||
822 | void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo) | ||
823 | { | ||
824 | printk(KERN_INFO "cpu %d " | ||
825 | #ifdef CONFIG_SMP | ||
826 | "phys_idx=%d " | ||
827 | #endif | ||
828 | "vers=%02X ident=%06X machine=%04X unused=%04X\n", | ||
829 | cpuinfo->cpu_nr, | ||
830 | #ifdef CONFIG_SMP | ||
831 | cpuinfo->cpu_addr, | ||
832 | #endif | ||
833 | cpuinfo->cpu_id.version, | ||
834 | cpuinfo->cpu_id.ident, | ||
835 | cpuinfo->cpu_id.machine, | ||
836 | cpuinfo->cpu_id.unused); | ||
837 | } | ||
838 | |||
839 | /* | ||
840 | * show_cpuinfo - Get information on one CPU for use by procfs. | ||
841 | */ | ||
842 | |||
843 | static int show_cpuinfo(struct seq_file *m, void *v) | ||
844 | { | ||
845 | static const char *hwcap_str[8] = { | ||
846 | "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", | ||
847 | "edat" | ||
848 | }; | ||
849 | struct cpuinfo_S390 *cpuinfo; | ||
850 | unsigned long n = (unsigned long) v - 1; | ||
851 | int i; | ||
852 | |||
853 | s390_adjust_jiffies(); | ||
854 | preempt_disable(); | ||
855 | if (!n) { | ||
856 | seq_printf(m, "vendor_id : IBM/S390\n" | ||
857 | "# processors : %i\n" | ||
858 | "bogomips per cpu: %lu.%02lu\n", | ||
859 | num_online_cpus(), loops_per_jiffy/(500000/HZ), | ||
860 | (loops_per_jiffy/(5000/HZ))%100); | ||
861 | seq_puts(m, "features\t: "); | ||
862 | for (i = 0; i < 8; i++) | ||
863 | if (hwcap_str[i] && (elf_hwcap & (1UL << i))) | ||
864 | seq_printf(m, "%s ", hwcap_str[i]); | ||
865 | seq_puts(m, "\n"); | ||
866 | } | ||
867 | |||
868 | if (cpu_online(n)) { | ||
869 | #ifdef CONFIG_SMP | ||
870 | if (smp_processor_id() == n) | ||
871 | cpuinfo = &S390_lowcore.cpu_data; | ||
872 | else | ||
873 | cpuinfo = &lowcore_ptr[n]->cpu_data; | ||
874 | #else | ||
875 | cpuinfo = &S390_lowcore.cpu_data; | ||
876 | #endif | ||
877 | seq_printf(m, "processor %li: " | ||
878 | "version = %02X, " | ||
879 | "identification = %06X, " | ||
880 | "machine = %04X\n", | ||
881 | n, cpuinfo->cpu_id.version, | ||
882 | cpuinfo->cpu_id.ident, | ||
883 | cpuinfo->cpu_id.machine); | ||
884 | } | ||
885 | preempt_enable(); | ||
886 | return 0; | ||
887 | } | ||
888 | |||
889 | static void *c_start(struct seq_file *m, loff_t *pos) | ||
890 | { | ||
891 | return *pos < NR_CPUS ? (void *)((unsigned long) *pos + 1) : NULL; | ||
892 | } | ||
893 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | ||
894 | { | ||
895 | ++*pos; | ||
896 | return c_start(m, pos); | ||
897 | } | ||
898 | static void c_stop(struct seq_file *m, void *v) | ||
899 | { | ||
900 | } | ||
901 | const struct seq_operations cpuinfo_op = { | ||
902 | .start = c_start, | ||
903 | .next = c_next, | ||
904 | .stop = c_stop, | ||
905 | .show = show_cpuinfo, | ||
906 | }; | ||
907 | |||