diff options
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/include/asm/page.h | 14 | ||||
-rw-r--r-- | arch/s390/include/asm/setup.h | 3 | ||||
-rw-r--r-- | arch/s390/kernel/early.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 38 |
4 files changed, 51 insertions, 6 deletions
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 27ab3c7c1e8b..6d5367060a56 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h | |||
@@ -30,12 +30,20 @@ | |||
30 | #include <asm/setup.h> | 30 | #include <asm/setup.h> |
31 | #ifndef __ASSEMBLY__ | 31 | #ifndef __ASSEMBLY__ |
32 | 32 | ||
33 | static unsigned long pfmf(unsigned long function, unsigned long address) | ||
34 | { | ||
35 | asm volatile( | ||
36 | " .insn rre,0xb9af0000,%[function],%[address]" | ||
37 | : [address] "+a" (address) | ||
38 | : [function] "d" (function) | ||
39 | : "memory"); | ||
40 | return address; | ||
41 | } | ||
42 | |||
33 | static inline void clear_page(void *page) | 43 | static inline void clear_page(void *page) |
34 | { | 44 | { |
35 | if (MACHINE_HAS_PFMF) { | 45 | if (MACHINE_HAS_PFMF) { |
36 | asm volatile( | 46 | pfmf(0x10000, (unsigned long)page); |
37 | " .insn rre,0xb9af0000,%0,%1" | ||
38 | : : "d" (0x10000), "a" (page) : "memory", "cc"); | ||
39 | } else { | 47 | } else { |
40 | register unsigned long reg1 asm ("1") = 0; | 48 | register unsigned long reg1 asm ("1") = 0; |
41 | register void *reg2 asm ("2") = page; | 49 | register void *reg2 asm ("2") = page; |
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index a798985515b7..bc1b87b7453a 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h | |||
@@ -76,6 +76,7 @@ extern unsigned int s390_user_mode; | |||
76 | #define MACHINE_FLAG_MVCOS (1UL << 8) | 76 | #define MACHINE_FLAG_MVCOS (1UL << 8) |
77 | #define MACHINE_FLAG_KVM (1UL << 9) | 77 | #define MACHINE_FLAG_KVM (1UL << 9) |
78 | #define MACHINE_FLAG_EDAT1 (1UL << 10) | 78 | #define MACHINE_FLAG_EDAT1 (1UL << 10) |
79 | #define MACHINE_FLAG_EDAT2 (1UL << 11) | ||
79 | #define MACHINE_FLAG_LPAR (1UL << 12) | 80 | #define MACHINE_FLAG_LPAR (1UL << 12) |
80 | #define MACHINE_FLAG_SPP (1UL << 13) | 81 | #define MACHINE_FLAG_SPP (1UL << 13) |
81 | #define MACHINE_FLAG_TOPOLOGY (1UL << 14) | 82 | #define MACHINE_FLAG_TOPOLOGY (1UL << 14) |
@@ -98,6 +99,7 @@ extern unsigned int s390_user_mode; | |||
98 | #define MACHINE_HAS_MVPG (S390_lowcore.machine_flags & MACHINE_FLAG_MVPG) | 99 | #define MACHINE_HAS_MVPG (S390_lowcore.machine_flags & MACHINE_FLAG_MVPG) |
99 | #define MACHINE_HAS_MVCOS (0) | 100 | #define MACHINE_HAS_MVCOS (0) |
100 | #define MACHINE_HAS_EDAT1 (0) | 101 | #define MACHINE_HAS_EDAT1 (0) |
102 | #define MACHINE_HAS_EDAT2 (0) | ||
101 | #define MACHINE_HAS_SPP (0) | 103 | #define MACHINE_HAS_SPP (0) |
102 | #define MACHINE_HAS_TOPOLOGY (0) | 104 | #define MACHINE_HAS_TOPOLOGY (0) |
103 | #define MACHINE_HAS_TE (0) | 105 | #define MACHINE_HAS_TE (0) |
@@ -110,6 +112,7 @@ extern unsigned int s390_user_mode; | |||
110 | #define MACHINE_HAS_MVPG (1) | 112 | #define MACHINE_HAS_MVPG (1) |
111 | #define MACHINE_HAS_MVCOS (S390_lowcore.machine_flags & MACHINE_FLAG_MVCOS) | 113 | #define MACHINE_HAS_MVCOS (S390_lowcore.machine_flags & MACHINE_FLAG_MVCOS) |
112 | #define MACHINE_HAS_EDAT1 (S390_lowcore.machine_flags & MACHINE_FLAG_EDAT1) | 114 | #define MACHINE_HAS_EDAT1 (S390_lowcore.machine_flags & MACHINE_FLAG_EDAT1) |
115 | #define MACHINE_HAS_EDAT2 (S390_lowcore.machine_flags & MACHINE_FLAG_EDAT2) | ||
113 | #define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP) | 116 | #define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP) |
114 | #define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY) | 117 | #define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY) |
115 | #define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE) | 118 | #define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE) |
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 4c91d078d091..1f0eee9e7daa 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -374,6 +374,8 @@ static __init void detect_machine_facilities(void) | |||
374 | S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT1; | 374 | S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT1; |
375 | __ctl_set_bit(0, 23); | 375 | __ctl_set_bit(0, 23); |
376 | } | 376 | } |
377 | if (test_facility(78)) | ||
378 | S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT2; | ||
377 | if (test_facility(3)) | 379 | if (test_facility(3)) |
378 | S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; | 380 | S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; |
379 | if (test_facility(27)) | 381 | if (test_facility(27)) |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index afa9fdba200e..bfb48f18169c 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -768,6 +768,40 @@ static void __init reserve_crashkernel(void) | |||
768 | #endif | 768 | #endif |
769 | } | 769 | } |
770 | 770 | ||
771 | static void __init init_storage_keys(unsigned long start, unsigned long end) | ||
772 | { | ||
773 | unsigned long boundary, function, size; | ||
774 | |||
775 | while (start < end) { | ||
776 | if (MACHINE_HAS_EDAT2) { | ||
777 | /* set storage keys for a 2GB frame */ | ||
778 | function = 0x22000 | PAGE_DEFAULT_KEY; | ||
779 | size = 1UL << 31; | ||
780 | boundary = (start + size) & ~(size - 1); | ||
781 | if (boundary <= end) { | ||
782 | do { | ||
783 | start = pfmf(function, start); | ||
784 | } while (start < boundary); | ||
785 | continue; | ||
786 | } | ||
787 | } | ||
788 | if (MACHINE_HAS_EDAT1) { | ||
789 | /* set storage keys for a 1MB frame */ | ||
790 | function = 0x21000 | PAGE_DEFAULT_KEY; | ||
791 | size = 1UL << 20; | ||
792 | boundary = (start + size) & ~(size - 1); | ||
793 | if (boundary <= end) { | ||
794 | do { | ||
795 | start = pfmf(function, start); | ||
796 | } while (start < boundary); | ||
797 | continue; | ||
798 | } | ||
799 | } | ||
800 | page_set_storage_key(start, PAGE_DEFAULT_KEY, 0); | ||
801 | start += PAGE_SIZE; | ||
802 | } | ||
803 | } | ||
804 | |||
771 | static void __init setup_memory(void) | 805 | static void __init setup_memory(void) |
772 | { | 806 | { |
773 | unsigned long bootmap_size; | 807 | unsigned long bootmap_size; |
@@ -846,9 +880,7 @@ static void __init setup_memory(void) | |||
846 | memblock_add_node(PFN_PHYS(start_chunk), | 880 | memblock_add_node(PFN_PHYS(start_chunk), |
847 | PFN_PHYS(end_chunk - start_chunk), 0); | 881 | PFN_PHYS(end_chunk - start_chunk), 0); |
848 | pfn = max(start_chunk, start_pfn); | 882 | pfn = max(start_chunk, start_pfn); |
849 | for (; pfn < end_chunk; pfn++) | 883 | init_storage_keys(PFN_PHYS(pfn), PFN_PHYS(end_chunk)); |
850 | page_set_storage_key(PFN_PHYS(pfn), | ||
851 | PAGE_DEFAULT_KEY, 0); | ||
852 | } | 884 | } |
853 | 885 | ||
854 | psw_set_key(PAGE_DEFAULT_KEY); | 886 | psw_set_key(PAGE_DEFAULT_KEY); |