diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2013-03-14 16:46:05 +0100 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-04-17 14:07:29 +0200 |
commit | f7f8d7e51d3c31426ee006c38d5b0ae3c9b8733e (patch) | |
tree | de91adcab7bc1b86dfc40194595d827f0c1dc41b | |
parent | 1bca09f7144450989e409c82ff0db83dddf489ac (diff) | |
download | op-kernel-dev-f7f8d7e51d3c31426ee006c38d5b0ae3c9b8733e.zip op-kernel-dev-f7f8d7e51d3c31426ee006c38d5b0ae3c9b8733e.tar.gz |
s390/mm: speedup storage key initialization
Use sske with multiple block control to initialize storage keys within
a 1 MB frame at once.
It turned out that the sske with mb=1 is an order of magnitude faster
than pfmf. This is only an issue for very large systems (several 100GB)
where storage key initialization could last more than a minute.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | arch/s390/mm/pageattr.c | 24 |
1 files changed, 9 insertions, 15 deletions
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c index d21040e..80adfbf 100644 --- a/arch/s390/mm/pageattr.c +++ b/arch/s390/mm/pageattr.c @@ -9,31 +9,25 @@ #include <asm/pgtable.h> #include <asm/page.h> +static inline unsigned long sske_frame(unsigned long addr, unsigned char skey) +{ + asm volatile(".insn rrf,0xb22b0000,%[skey],%[addr],9,0" + : [addr] "+a" (addr) : [skey] "d" (skey)); + return addr; +} + void storage_key_init_range(unsigned long start, unsigned long end) { - unsigned long boundary, function, size; + unsigned long boundary, 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); + start = sske_frame(start, PAGE_DEFAULT_KEY); } while (start < boundary); continue; } |