#include <linux/ctype.h>
#include <linux/reboot.h>
#include <linux/topology.h>
+#include <linux/ftrace.h>
#include <asm/ipl.h>
#include <asm/uaccess.h>
* Machine setup..
*/
unsigned int console_mode = 0;
+EXPORT_SYMBOL(console_mode);
+
unsigned int console_devno = -1;
+EXPORT_SYMBOL(console_devno);
+
unsigned int console_irq = -1;
-unsigned long machine_flags;
+EXPORT_SYMBOL(console_irq);
+
unsigned long elf_hwcap = 0;
char elf_platform[ELF_PLATFORM_SIZE];
int __initdata memory_end_set;
unsigned long __initdata memory_end;
+/* An array with a pointer to the lowcore of every CPU. */
+struct _lowcore *lowcore_ptr[NR_CPUS];
+EXPORT_SYMBOL(lowcore_ptr);
+
/*
* This is set up by the setup-routine at boot-time
* for S390 need to find out, what we have to setup
*/
void __cpuinit cpu_init(void)
{
- int addr = hard_smp_processor_id();
-
/*
* Store processor id in lowcore (used e.g. in timer_interrupt)
*/
- get_cpu_id(&S390_lowcore.cpu_data.cpu_id);
- S390_lowcore.cpu_data.cpu_addr = addr;
-
- /*
- * Force FPU initialization:
- */
- clear_thread_flag(TIF_USEDFPU);
- clear_used_math();
+ get_cpu_id(&S390_lowcore.cpu_id);
atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm;
- if (current->mm)
- BUG();
+ BUG_ON(current->mm);
enter_lazy_tlb(&init_mm, current);
}
__setup("condev=", condev_setup);
+static void __init set_preferred_console(void)
+{
+ if (MACHINE_IS_KVM)
+ add_preferred_console("hvc", 0, NULL);
+ else if (CONSOLE_IS_3215 || CONSOLE_IS_SCLP)
+ add_preferred_console("ttyS", 0, NULL);
+ else if (CONSOLE_IS_3270)
+ add_preferred_console("tty3270", 0, NULL);
+}
+
static int __init conmode_setup(char *str)
{
#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
if (strncmp(str, "3270", 5) == 0)
SET_CONSOLE_3270;
#endif
+ set_preferred_console();
return 1;
}
}
}
-#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
+#ifdef CONFIG_ZFCPDUMP
static void __init setup_zfcpdump(unsigned int console_devno)
{
static char str[41];
}
early_param("mem", early_parse_mem);
-#ifdef CONFIG_S390_SWITCH_AMODE
-#ifdef CONFIG_PGSTE
-unsigned int switch_amode = 1;
-#else
-unsigned int switch_amode = 0;
-#endif
-EXPORT_SYMBOL_GPL(switch_amode);
+unsigned int user_mode = HOME_SPACE_MODE;
+EXPORT_SYMBOL_GPL(user_mode);
static int set_amode_and_uaccess(unsigned long user_amode,
unsigned long user32_amode)
*/
static int __init early_parse_switch_amode(char *p)
{
- switch_amode = 1;
+ if (user_mode != SECONDARY_SPACE_MODE)
+ user_mode = PRIMARY_SPACE_MODE;
return 0;
}
early_param("switch_amode", early_parse_switch_amode);
-#else /* CONFIG_S390_SWITCH_AMODE */
-static inline int set_amode_and_uaccess(unsigned long user_amode,
- unsigned long user32_amode)
+static int __init early_parse_user_mode(char *p)
{
+ if (p && strcmp(p, "primary") == 0)
+ user_mode = PRIMARY_SPACE_MODE;
+#ifdef CONFIG_S390_EXEC_PROTECT
+ else if (p && strcmp(p, "secondary") == 0)
+ user_mode = SECONDARY_SPACE_MODE;
+#endif
+ else if (!p || strcmp(p, "home") == 0)
+ user_mode = HOME_SPACE_MODE;
+ else
+ return 1;
return 0;
}
-#endif /* CONFIG_S390_SWITCH_AMODE */
+early_param("user_mode", early_parse_user_mode);
#ifdef CONFIG_S390_EXEC_PROTECT
-unsigned int s390_noexec = 0;
-EXPORT_SYMBOL_GPL(s390_noexec);
-
/*
* Enable execute protection?
*/
{
if (!strncmp(p, "off", 3))
return 0;
- switch_amode = 1;
- s390_noexec = 1;
+ user_mode = SECONDARY_SPACE_MODE;
return 0;
}
early_param("noexec", early_parse_noexec);
static void setup_addressing_mode(void)
{
- if (s390_noexec) {
+ if (user_mode == SECONDARY_SPACE_MODE) {
if (set_amode_and_uaccess(PSW_ASC_SECONDARY,
PSW32_ASC_SECONDARY))
pr_info("Execute protection active, "
else
pr_info("Execute protection active, "
"mvcos not available\n");
- } else if (switch_amode) {
+ } else if (user_mode == PRIMARY_SPACE_MODE) {
if (set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY))
pr_info("Address spaces switched, "
"mvcos available\n");
lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
lc->restart_psw.addr =
PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
- if (switch_amode)
+ if (user_mode != HOME_SPACE_MODE)
lc->restart_psw.mask |= PSW_ASC_HOME;
lc->external_new_psw.mask = psw_kernel_bits;
lc->external_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
lc->io_new_psw.mask = psw_kernel_bits;
lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
- lc->ipl_device = S390_lowcore.ipl_device;
lc->clock_comparator = -1ULL;
lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
lc->async_stack = (unsigned long)
__alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE;
lc->current_task = (unsigned long) init_thread_union.thread_info.task;
lc->thread_info = (unsigned long) &init_thread_union;
+ lc->machine_flags = S390_lowcore.machine_flags;
#ifndef CONFIG_64BIT
if (MACHINE_HAS_IEEE) {
lc->extended_save_area_addr = (__u32)
#else
lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0];
#endif
+ lc->sync_enter_timer = S390_lowcore.sync_enter_timer;
+ lc->async_enter_timer = S390_lowcore.async_enter_timer;
+ lc->exit_timer = S390_lowcore.exit_timer;
+ lc->user_timer = S390_lowcore.user_timer;
+ lc->system_timer = S390_lowcore.system_timer;
+ lc->steal_timer = S390_lowcore.steal_timer;
+ lc->last_update_timer = S390_lowcore.last_update_timer;
+ lc->last_update_clock = S390_lowcore.last_update_clock;
+ lc->ftrace_func = S390_lowcore.ftrace_func;
set_prefix((u32)(unsigned long) lc);
+ lowcore_ptr[0] = lc;
}
static void __init
unsigned long max_mem;
int i;
-#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
+#ifdef CONFIG_ZFCPDUMP
if (ipl_info.type == IPL_TYPE_FCP_DUMP) {
memory_end = ZFCPDUMP_HSA_SIZE;
memory_end_set = 1;
static void __init setup_hwcaps(void)
{
static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 };
- struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
unsigned long long facility_list_extended;
unsigned int facility_list;
int i;
* Bit 17: the message-security assist is installed
* Bit 19: the long-displacement facility is installed
* Bit 21: the extended-immediate facility is installed
+ * Bit 22: extended-translation facility 3 is installed
+ * Bit 30: extended-translation facility 3 enhancement facility
* These get translated to:
* HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1,
* HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3,
- * HWCAP_S390_LDISP bit 4, and HWCAP_S390_EIMM bit 5.
+ * HWCAP_S390_LDISP bit 4, HWCAP_S390_EIMM bit 5 and
+ * HWCAP_S390_ETF3EH bit 8 (22 && 30).
*/
for (i = 0; i < 6; i++)
if (facility_list & (1UL << (31 - stfl_bits[i])))
elf_hwcap |= 1UL << i;
+ if ((facility_list & (1UL << (31 - 22)))
+ && (facility_list & (1UL << (31 - 30))))
+ elf_hwcap |= HWCAP_S390_ETF3EH;
+
/*
* Check for additional facilities with store-facility-list-extended.
* stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0
* How many facility words are stored depends on the number of
* doublewords passed to the instruction. The additional facilites
* are:
- * Bit 43: decimal floating point facility is installed
+ * Bit 42: decimal floating point facility is installed
+ * Bit 44: perform floating point operation facility is installed
* translated to:
- * HWCAP_S390_DFP bit 6.
+ * HWCAP_S390_DFP bit 6 (42 && 44).
*/
if ((elf_hwcap & (1UL << 2)) &&
__stfle(&facility_list_extended, 1) > 0) {
- if (facility_list_extended & (1ULL << (64 - 43)))
- elf_hwcap |= 1UL << 6;
+ if ((facility_list_extended & (1ULL << (63 - 42)))
+ && (facility_list_extended & (1ULL << (63 - 44))))
+ elf_hwcap |= HWCAP_S390_DFP;
}
+ /*
+ * Huge page support HWCAP_S390_HPAGE is bit 7.
+ */
if (MACHINE_HAS_HPAGE)
- elf_hwcap |= 1UL << 7;
+ elf_hwcap |= HWCAP_S390_HPAGE;
+
+ /*
+ * 64-bit register support for 31-bit processes
+ * HWCAP_S390_HIGH_GPRS is bit 9.
+ */
+ elf_hwcap |= HWCAP_S390_HIGH_GPRS;
- switch (cpuinfo->cpu_id.machine) {
+ switch (S390_lowcore.cpu_id.machine) {
case 0x9672:
#if !defined(CONFIG_64BIT)
default: /* Use "g5" as default for 31 bit kernels. */
void __init
setup_arch(char **cmdline_p)
{
- /* set up preferred console */
- add_preferred_console("ttyS", 0, NULL);
-
/*
* print what head.S has found out about the machine
*/
if (MACHINE_IS_VM)
pr_info("Linux is running as a z/VM "
"guest operating system in 64-bit mode\n");
- else if (MACHINE_IS_KVM) {
+ else if (MACHINE_IS_KVM)
pr_info("Linux is running under KVM in 64-bit mode\n");
- add_preferred_console("hvc", 0, NULL);
- s390_virtio_console_init();
- } else
+ else
pr_info("Linux is running natively in 64-bit mode\n");
#endif /* CONFIG_64BIT */
setup_lowcore();
cpu_init();
- __cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr;
+ __cpu_logical_map[0] = stap();
s390_init_cpu_topology();
/*
/* Setup default console */
conmode_default();
+ set_preferred_console();
/* Setup zfcpdump support */
setup_zfcpdump(console_devno);