diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2012-09-27 10:45:06 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-10-09 14:16:55 +0200 |
commit | 85e9d0e5ffabfede5facbac5b0d9b90768bc6e90 (patch) | |
tree | b158c8bde347cd8cabd24265dfe65884a08db701 /arch/s390/kernel | |
parent | 3c7ef08bba65d1fef0b7486b30b5bbcdb42c5d9c (diff) |
s390/mm: use pfmf instruction to initialize storage keys
Make use of the pfmf instruction, if available, to initialize storage keys
of whole 1MB or 2GB frames instead of initializing every single page with
the sske instruction.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/early.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 38 |
2 files changed, 37 insertions, 3 deletions
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 4c91d078d09..1f0eee9e7da 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -374,6 +374,8 @@ static __init void detect_machine_facilities(void) S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT1; __ctl_set_bit(0, 23); } + if (test_facility(78)) + S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT2; if (test_facility(3)) S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; if (test_facility(27)) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index afa9fdba200..bfb48f18169 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -768,6 +768,40 @@ static void __init reserve_crashkernel(void) #endif } +static void __init init_storage_keys(unsigned long start, unsigned long end) +{ + unsigned long boundary, function, size; + + while (start < end) { + if (MACHINE_HAS_EDAT2) { + /* set storage keys for a 2GB frame */ + function = 0x22000 | PAGE_DEFAULT_KEY; + size = 1UL << 31; + boundary = (start + size) & ~(size - 1); + if (boundary <= end) { + do { + start = pfmf(function, start); + } while (start < boundary); + continue; + } + } + if (MACHINE_HAS_EDAT1) { + /* set storage keys for a 1MB frame */ + function = 0x21000 | PAGE_DEFAULT_KEY; + size = 1UL << 20; + boundary = (start + size) & ~(size - 1); + if (boundary <= end) { + do { + start = pfmf(function, start); + } while (start < boundary); + continue; + } + } + page_set_storage_key(start, PAGE_DEFAULT_KEY, 0); + start += PAGE_SIZE; + } +} + static void __init setup_memory(void) { unsigned long bootmap_size; @@ -846,9 +880,7 @@ static void __init setup_memory(void) memblock_add_node(PFN_PHYS(start_chunk), PFN_PHYS(end_chunk - start_chunk), 0); pfn = max(start_chunk, start_pfn); - for (; pfn < end_chunk; pfn++) - page_set_storage_key(PFN_PHYS(pfn), - PAGE_DEFAULT_KEY, 0); + init_storage_keys(PFN_PHYS(pfn), PFN_PHYS(end_chunk)); } psw_set_key(PAGE_DEFAULT_KEY); |