diff options
Diffstat (limited to 'arch/s390/kernel/setup.c')
-rw-r--r-- | arch/s390/kernel/setup.c | 98 |
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 | |||
55 | long psw_kernel_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | | ||
56 | PSW_MASK_MCHECK | PSW_DEFAULT_KEY); | ||
57 | long 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 | } |
384 | early_param("ipldelay", early_parse_ipldelay); | 391 | early_param("ipldelay", early_parse_ipldelay); |
385 | 392 | ||
393 | #ifdef CONFIG_S390_SWITCH_AMODE | ||
394 | unsigned int switch_amode = 0; | ||
395 | EXPORT_SYMBOL_GPL(switch_amode); | ||
396 | |||
397 | static 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 | */ | ||
426 | static int __init early_parse_switch_amode(char *p) | ||
427 | { | ||
428 | switch_amode = 1; | ||
429 | return 0; | ||
430 | } | ||
431 | early_param("switch_amode", early_parse_switch_amode); | ||
432 | |||
433 | #else /* CONFIG_S390_SWITCH_AMODE */ | ||
434 | static 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 | ||
441 | unsigned int s390_noexec = 0; | ||
442 | EXPORT_SYMBOL_GPL(s390_noexec); | ||
443 | |||
444 | /* | ||
445 | * Enable execute protection? | ||
446 | */ | ||
447 | static 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 | } | ||
455 | early_param("noexec", early_parse_noexec); | ||
456 | #endif /* CONFIG_S390_EXEC_PROTECT */ | ||
457 | |||
458 | static 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 | |||
386 | static void __init | 471 | static void __init |
387 | setup_lowcore(void) | 472 | setup_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(); |