aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/setup.c')
-rw-r--r--arch/s390/kernel/setup.c98
1 files changed, 93 insertions, 5 deletions
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 25bf7277d311..b1b9a931237d 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -50,6 +50,13 @@
50#include <asm/page.h> 50#include <asm/page.h>
51#include <asm/ptrace.h> 51#include <asm/ptrace.h>
52#include <asm/sections.h> 52#include <asm/sections.h>
53#include <asm/compat.h>
54
55long psw_kernel_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY |
56 PSW_MASK_MCHECK | PSW_DEFAULT_KEY);
57long psw_user_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
58 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
59 PSW_MASK_PSTATE | PSW_DEFAULT_KEY);
53 60
54/* 61/*
55 * User copy operations. 62 * User copy operations.
@@ -383,6 +390,84 @@ static int __init early_parse_ipldelay(char *p)
383} 390}
384early_param("ipldelay", early_parse_ipldelay); 391early_param("ipldelay", early_parse_ipldelay);
385 392
393#ifdef CONFIG_S390_SWITCH_AMODE
394unsigned int switch_amode = 0;
395EXPORT_SYMBOL_GPL(switch_amode);
396
397static inline void set_amode_and_uaccess(unsigned long user_amode,
398 unsigned long user32_amode)
399{
400 psw_user_bits = PSW_BASE_BITS | PSW_MASK_DAT | user_amode |
401 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
402 PSW_MASK_PSTATE | PSW_DEFAULT_KEY;
403#ifdef CONFIG_COMPAT
404 psw_user32_bits = PSW_BASE32_BITS | PSW_MASK_DAT | user_amode |
405 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
406 PSW_MASK_PSTATE | PSW_DEFAULT_KEY;
407 psw32_user_bits = PSW32_BASE_BITS | PSW32_MASK_DAT | user32_amode |
408 PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK |
409 PSW32_MASK_PSTATE;
410#endif
411 psw_kernel_bits = PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
412 PSW_MASK_MCHECK | PSW_DEFAULT_KEY;
413
414 if (MACHINE_HAS_MVCOS) {
415 printk("mvcos available.\n");
416 memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess));
417 } else {
418 printk("mvcos not available.\n");
419 memcpy(&uaccess, &uaccess_pt, sizeof(uaccess));
420 }
421}
422
423/*
424 * Switch kernel/user addressing modes?
425 */
426static int __init early_parse_switch_amode(char *p)
427{
428 switch_amode = 1;
429 return 0;
430}
431early_param("switch_amode", early_parse_switch_amode);
432
433#else /* CONFIG_S390_SWITCH_AMODE */
434static inline void set_amode_and_uaccess(unsigned long user_amode,
435 unsigned long user32_amode)
436{
437}
438#endif /* CONFIG_S390_SWITCH_AMODE */
439
440#ifdef CONFIG_S390_EXEC_PROTECT
441unsigned int s390_noexec = 0;
442EXPORT_SYMBOL_GPL(s390_noexec);
443
444/*
445 * Enable execute protection?
446 */
447static int __init early_parse_noexec(char *p)
448{
449 if (!strncmp(p, "off", 3))
450 return 0;
451 switch_amode = 1;
452 s390_noexec = 1;
453 return 0;
454}
455early_param("noexec", early_parse_noexec);
456#endif /* CONFIG_S390_EXEC_PROTECT */
457
458static void setup_addressing_mode(void)
459{
460 if (s390_noexec) {
461 printk("S390 execute protection active, ");
462 set_amode_and_uaccess(PSW_ASC_SECONDARY, PSW32_ASC_SECONDARY);
463 return;
464 }
465 if (switch_amode) {
466 printk("S390 address spaces switched, ");
467 set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY);
468 }
469}
470
386static void __init 471static void __init
387setup_lowcore(void) 472setup_lowcore(void)
388{ 473{
@@ -399,19 +484,21 @@ setup_lowcore(void)
399 lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; 484 lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
400 lc->restart_psw.addr = 485 lc->restart_psw.addr =
401 PSW_ADDR_AMODE | (unsigned long) restart_int_handler; 486 PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
402 lc->external_new_psw.mask = PSW_KERNEL_BITS; 487 if (switch_amode)
488 lc->restart_psw.mask |= PSW_ASC_HOME;
489 lc->external_new_psw.mask = psw_kernel_bits;
403 lc->external_new_psw.addr = 490 lc->external_new_psw.addr =
404 PSW_ADDR_AMODE | (unsigned long) ext_int_handler; 491 PSW_ADDR_AMODE | (unsigned long) ext_int_handler;
405 lc->svc_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT; 492 lc->svc_new_psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT;
406 lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call; 493 lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call;
407 lc->program_new_psw.mask = PSW_KERNEL_BITS; 494 lc->program_new_psw.mask = psw_kernel_bits;
408 lc->program_new_psw.addr = 495 lc->program_new_psw.addr =
409 PSW_ADDR_AMODE | (unsigned long)pgm_check_handler; 496 PSW_ADDR_AMODE | (unsigned long)pgm_check_handler;
410 lc->mcck_new_psw.mask = 497 lc->mcck_new_psw.mask =
411 PSW_KERNEL_BITS & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT; 498 psw_kernel_bits & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT;
412 lc->mcck_new_psw.addr = 499 lc->mcck_new_psw.addr =
413 PSW_ADDR_AMODE | (unsigned long) mcck_int_handler; 500 PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
414 lc->io_new_psw.mask = PSW_KERNEL_BITS; 501 lc->io_new_psw.mask = psw_kernel_bits;
415 lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler; 502 lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
416 lc->ipl_device = S390_lowcore.ipl_device; 503 lc->ipl_device = S390_lowcore.ipl_device;
417 lc->jiffy_timer = -1LL; 504 lc->jiffy_timer = -1LL;
@@ -645,6 +732,7 @@ setup_arch(char **cmdline_p)
645 parse_early_param(); 732 parse_early_param();
646 733
647 setup_memory_end(); 734 setup_memory_end();
735 setup_addressing_mode();
648 setup_memory(); 736 setup_memory();
649 setup_resources(); 737 setup_resources();
650 setup_lowcore(); 738 setup_lowcore();