diff options
Diffstat (limited to 'arch/s390/kernel/setup.c')
-rw-r--r-- | arch/s390/kernel/setup.c | 146 |
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 | ||
105 | static struct resource code_resource = { | ||
106 | .name = "Kernel code", | ||
107 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM, | ||
108 | }; | ||
109 | |||
110 | static 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 | */ |
316 | static int __init early_parse_switch_amode(char *p) | 306 | static 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 | } |
322 | early_param("switch_amode", early_parse_switch_amode); | 311 | early_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 | } |
338 | early_param("user_mode", early_parse_user_mode); | 323 | early_param("user_mode", early_parse_user_mode); |
339 | 324 | ||
340 | #ifdef CONFIG_S390_EXEC_PROTECT | ||
341 | /* | ||
342 | * Enable execute protection? | ||
343 | */ | ||
344 | static 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 | } | ||
351 | early_param("noexec", early_parse_noexec); | ||
352 | #endif /* CONFIG_S390_EXEC_PROTECT */ | ||
353 | |||
354 | static void setup_addressing_mode(void) | 325 | static 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 | ||
436 | static void __init | 402 | static struct resource code_resource = { |
437 | setup_resources(void) | 403 | .name = "Kernel code", |
404 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM, | ||
405 | }; | ||
406 | |||
407 | static struct resource data_resource = { | ||
408 | .name = "Kernel data", | ||
409 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM, | ||
410 | }; | ||
411 | |||
412 | static struct resource bss_resource = { | ||
413 | .name = "Kernel bss", | ||
414 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM, | ||
415 | }; | ||
416 | |||
417 | static struct resource __initdata *standard_resources[] = { | ||
418 | &code_resource, | ||
419 | &data_resource, | ||
420 | &bss_resource, | ||
421 | }; | ||
422 | |||
423 | static 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) | |||
674 | static void __init setup_hwcaps(void) | 647 | static 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 | ||