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.c146
1 files changed, 57 insertions, 89 deletions
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index c8e8e1354e1d..0c35dee10b00 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -102,16 +102,6 @@ EXPORT_SYMBOL(lowcore_ptr);
102 102
103#include <asm/setup.h> 103#include <asm/setup.h>
104 104
105static struct resource code_resource = {
106 .name = "Kernel code",
107 .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
108};
109
110static struct resource data_resource = {
111 .name = "Kernel data",
112 .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
113};
114
115/* 105/*
116 * condev= and conmode= setup parameter. 106 * condev= and conmode= setup parameter.
117 */ 107 */
@@ -315,8 +305,7 @@ static int set_amode_and_uaccess(unsigned long user_amode,
315 */ 305 */
316static int __init early_parse_switch_amode(char *p) 306static int __init early_parse_switch_amode(char *p)
317{ 307{
318 if (user_mode != SECONDARY_SPACE_MODE) 308 user_mode = PRIMARY_SPACE_MODE;
319 user_mode = PRIMARY_SPACE_MODE;
320 return 0; 309 return 0;
321} 310}
322early_param("switch_amode", early_parse_switch_amode); 311early_param("switch_amode", early_parse_switch_amode);
@@ -325,10 +314,6 @@ static int __init early_parse_user_mode(char *p)
325{ 314{
326 if (p && strcmp(p, "primary") == 0) 315 if (p && strcmp(p, "primary") == 0)
327 user_mode = PRIMARY_SPACE_MODE; 316 user_mode = PRIMARY_SPACE_MODE;
328#ifdef CONFIG_S390_EXEC_PROTECT
329 else if (p && strcmp(p, "secondary") == 0)
330 user_mode = SECONDARY_SPACE_MODE;
331#endif
332 else if (!p || strcmp(p, "home") == 0) 317 else if (!p || strcmp(p, "home") == 0)
333 user_mode = HOME_SPACE_MODE; 318 user_mode = HOME_SPACE_MODE;
334 else 319 else
@@ -337,31 +322,9 @@ static int __init early_parse_user_mode(char *p)
337} 322}
338early_param("user_mode", early_parse_user_mode); 323early_param("user_mode", early_parse_user_mode);
339 324
340#ifdef CONFIG_S390_EXEC_PROTECT
341/*
342 * Enable execute protection?
343 */
344static int __init early_parse_noexec(char *p)
345{
346 if (!strncmp(p, "off", 3))
347 return 0;
348 user_mode = SECONDARY_SPACE_MODE;
349 return 0;
350}
351early_param("noexec", early_parse_noexec);
352#endif /* CONFIG_S390_EXEC_PROTECT */
353
354static void setup_addressing_mode(void) 325static void setup_addressing_mode(void)
355{ 326{
356 if (user_mode == SECONDARY_SPACE_MODE) { 327 if (user_mode == PRIMARY_SPACE_MODE) {
357 if (set_amode_and_uaccess(PSW_ASC_SECONDARY,
358 PSW32_ASC_SECONDARY))
359 pr_info("Execute protection active, "
360 "mvcos available\n");
361 else
362 pr_info("Execute protection active, "
363 "mvcos not available\n");
364 } else if (user_mode == PRIMARY_SPACE_MODE) {
365 if (set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY)) 328 if (set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY))
366 pr_info("Address spaces switched, " 329 pr_info("Address spaces switched, "
367 "mvcos available\n"); 330 "mvcos available\n");
@@ -409,6 +372,9 @@ setup_lowcore(void)
409 lc->current_task = (unsigned long) init_thread_union.thread_info.task; 372 lc->current_task = (unsigned long) init_thread_union.thread_info.task;
410 lc->thread_info = (unsigned long) &init_thread_union; 373 lc->thread_info = (unsigned long) &init_thread_union;
411 lc->machine_flags = S390_lowcore.machine_flags; 374 lc->machine_flags = S390_lowcore.machine_flags;
375 lc->stfl_fac_list = S390_lowcore.stfl_fac_list;
376 memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
377 MAX_FACILITY_BIT/8);
412#ifndef CONFIG_64BIT 378#ifndef CONFIG_64BIT
413 if (MACHINE_HAS_IEEE) { 379 if (MACHINE_HAS_IEEE) {
414 lc->extended_save_area_addr = (__u32) 380 lc->extended_save_area_addr = (__u32)
@@ -433,21 +399,43 @@ setup_lowcore(void)
433 lowcore_ptr[0] = lc; 399 lowcore_ptr[0] = lc;
434} 400}
435 401
436static void __init 402static struct resource code_resource = {
437setup_resources(void) 403 .name = "Kernel code",
404 .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
405};
406
407static struct resource data_resource = {
408 .name = "Kernel data",
409 .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
410};
411
412static struct resource bss_resource = {
413 .name = "Kernel bss",
414 .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
415};
416
417static struct resource __initdata *standard_resources[] = {
418 &code_resource,
419 &data_resource,
420 &bss_resource,
421};
422
423static void __init setup_resources(void)
438{ 424{
439 struct resource *res, *sub_res; 425 struct resource *res, *std_res, *sub_res;
440 int i; 426 int i, j;
441 427
442 code_resource.start = (unsigned long) &_text; 428 code_resource.start = (unsigned long) &_text;
443 code_resource.end = (unsigned long) &_etext - 1; 429 code_resource.end = (unsigned long) &_etext - 1;
444 data_resource.start = (unsigned long) &_etext; 430 data_resource.start = (unsigned long) &_etext;
445 data_resource.end = (unsigned long) &_edata - 1; 431 data_resource.end = (unsigned long) &_edata - 1;
432 bss_resource.start = (unsigned long) &__bss_start;
433 bss_resource.end = (unsigned long) &__bss_stop - 1;
446 434
447 for (i = 0; i < MEMORY_CHUNKS; i++) { 435 for (i = 0; i < MEMORY_CHUNKS; i++) {
448 if (!memory_chunk[i].size) 436 if (!memory_chunk[i].size)
449 continue; 437 continue;
450 res = alloc_bootmem_low(sizeof(struct resource)); 438 res = alloc_bootmem_low(sizeof(*res));
451 res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; 439 res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
452 switch (memory_chunk[i].type) { 440 switch (memory_chunk[i].type) {
453 case CHUNK_READ_WRITE: 441 case CHUNK_READ_WRITE:
@@ -461,40 +449,24 @@ setup_resources(void)
461 res->name = "reserved"; 449 res->name = "reserved";
462 } 450 }
463 res->start = memory_chunk[i].addr; 451 res->start = memory_chunk[i].addr;
464 res->end = memory_chunk[i].addr + memory_chunk[i].size - 1; 452 res->end = res->start + memory_chunk[i].size - 1;
465 request_resource(&iomem_resource, res); 453 request_resource(&iomem_resource, res);
466 454
467 if (code_resource.start >= res->start && 455 for (j = 0; j < ARRAY_SIZE(standard_resources); j++) {
468 code_resource.start <= res->end && 456 std_res = standard_resources[j];
469 code_resource.end > res->end) { 457 if (std_res->start < res->start ||
470 sub_res = alloc_bootmem_low(sizeof(struct resource)); 458 std_res->start > res->end)
471 memcpy(sub_res, &code_resource, 459 continue;
472 sizeof(struct resource)); 460 if (std_res->end > res->end) {
473 sub_res->end = res->end; 461 sub_res = alloc_bootmem_low(sizeof(*sub_res));
474 code_resource.start = res->end + 1; 462 *sub_res = *std_res;
475 request_resource(res, sub_res); 463 sub_res->end = res->end;
476 } 464 std_res->start = res->end + 1;
477 465 request_resource(res, sub_res);
478 if (code_resource.start >= res->start && 466 } else {
479 code_resource.start <= res->end && 467 request_resource(res, std_res);
480 code_resource.end <= res->end) 468 }
481 request_resource(res, &code_resource);
482
483 if (data_resource.start >= res->start &&
484 data_resource.start <= res->end &&
485 data_resource.end > res->end) {
486 sub_res = alloc_bootmem_low(sizeof(struct resource));
487 memcpy(sub_res, &data_resource,
488 sizeof(struct resource));
489 sub_res->end = res->end;
490 data_resource.start = res->end + 1;
491 request_resource(res, sub_res);
492 } 469 }
493
494 if (data_resource.start >= res->start &&
495 data_resource.start <= res->end &&
496 data_resource.end <= res->end)
497 request_resource(res, &data_resource);
498 } 470 }
499} 471}
500 472
@@ -627,7 +599,8 @@ setup_memory(void)
627 add_active_range(0, start_chunk, end_chunk); 599 add_active_range(0, start_chunk, end_chunk);
628 pfn = max(start_chunk, start_pfn); 600 pfn = max(start_chunk, start_pfn);
629 for (; pfn < end_chunk; pfn++) 601 for (; pfn < end_chunk; pfn++)
630 page_set_storage_key(PFN_PHYS(pfn), PAGE_DEFAULT_KEY); 602 page_set_storage_key(PFN_PHYS(pfn),
603 PAGE_DEFAULT_KEY, 0);
631 } 604 }
632 605
633 psw_set_key(PAGE_DEFAULT_KEY); 606 psw_set_key(PAGE_DEFAULT_KEY);
@@ -674,12 +647,9 @@ setup_memory(void)
674static void __init setup_hwcaps(void) 647static void __init setup_hwcaps(void)
675{ 648{
676 static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; 649 static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 };
677 unsigned long long facility_list_extended;
678 unsigned int facility_list;
679 struct cpuid cpu_id; 650 struct cpuid cpu_id;
680 int i; 651 int i;
681 652
682 facility_list = stfl();
683 /* 653 /*
684 * The store facility list bits numbers as found in the principles 654 * The store facility list bits numbers as found in the principles
685 * of operation are numbered with bit 1UL<<31 as number 0 to 655 * of operation are numbered with bit 1UL<<31 as number 0 to
@@ -699,11 +669,10 @@ static void __init setup_hwcaps(void)
699 * HWCAP_S390_ETF3EH bit 8 (22 && 30). 669 * HWCAP_S390_ETF3EH bit 8 (22 && 30).
700 */ 670 */
701 for (i = 0; i < 6; i++) 671 for (i = 0; i < 6; i++)
702 if (facility_list & (1UL << (31 - stfl_bits[i]))) 672 if (test_facility(stfl_bits[i]))
703 elf_hwcap |= 1UL << i; 673 elf_hwcap |= 1UL << i;
704 674
705 if ((facility_list & (1UL << (31 - 22))) 675 if (test_facility(22) && test_facility(30))
706 && (facility_list & (1UL << (31 - 30))))
707 elf_hwcap |= HWCAP_S390_ETF3EH; 676 elf_hwcap |= HWCAP_S390_ETF3EH;
708 677
709 /* 678 /*
@@ -712,19 +681,15 @@ static void __init setup_hwcaps(void)
712 * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information 681 * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information
713 * as stored by stfl, bits 32-xxx contain additional facilities. 682 * as stored by stfl, bits 32-xxx contain additional facilities.
714 * How many facility words are stored depends on the number of 683 * How many facility words are stored depends on the number of
715 * doublewords passed to the instruction. The additional facilites 684 * doublewords passed to the instruction. The additional facilities
716 * are: 685 * are:
717 * Bit 42: decimal floating point facility is installed 686 * Bit 42: decimal floating point facility is installed
718 * Bit 44: perform floating point operation facility is installed 687 * Bit 44: perform floating point operation facility is installed
719 * translated to: 688 * translated to:
720 * HWCAP_S390_DFP bit 6 (42 && 44). 689 * HWCAP_S390_DFP bit 6 (42 && 44).
721 */ 690 */
722 if ((elf_hwcap & (1UL << 2)) && 691 if ((elf_hwcap & (1UL << 2)) && test_facility(42) && test_facility(44))
723 __stfle(&facility_list_extended, 1) > 0) { 692 elf_hwcap |= HWCAP_S390_DFP;
724 if ((facility_list_extended & (1ULL << (63 - 42)))
725 && (facility_list_extended & (1ULL << (63 - 44))))
726 elf_hwcap |= HWCAP_S390_DFP;
727 }
728 693
729 /* 694 /*
730 * Huge page support HWCAP_S390_HPAGE is bit 7. 695 * Huge page support HWCAP_S390_HPAGE is bit 7.
@@ -765,6 +730,9 @@ static void __init setup_hwcaps(void)
765 case 0x2098: 730 case 0x2098:
766 strcpy(elf_platform, "z10"); 731 strcpy(elf_platform, "z10");
767 break; 732 break;
733 case 0x2817:
734 strcpy(elf_platform, "z196");
735 break;
768 } 736 }
769} 737}
770 738