diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2012-10-08 09:18:26 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-11-23 11:14:24 +0100 |
commit | 18da236908793abccebc6f365fbe6e95a5b41db0 (patch) | |
tree | 34899d0c737b625660a44f2b47436e5e82a17511 /arch/s390/mm/vmem.c | |
parent | 26d29d06ea020411559f75ec908db235ca1838d9 (diff) | |
download | op-kernel-dev-18da236908793abccebc6f365fbe6e95a5b41db0.zip op-kernel-dev-18da236908793abccebc6f365fbe6e95a5b41db0.tar.gz |
s390/mm,vmem: use 2GB frames for identity mapping
Use 2GB frames for indentity mapping if EDAT2 is
available to reduce TLB pressure.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/mm/vmem.c')
-rw-r--r-- | arch/s390/mm/vmem.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index 387c7c6..bf37a09 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c @@ -89,6 +89,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) int ret = -ENOMEM; while (address < end) { + pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0)); pg_dir = pgd_offset_k(address); if (pgd_none(*pg_dir)) { pu_dir = vmem_pud_alloc(); @@ -96,18 +97,24 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) goto out; pgd_populate(&init_mm, pg_dir, pu_dir); } - pu_dir = pud_offset(pg_dir, address); +#if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC) + if (MACHINE_HAS_EDAT2 && pud_none(*pu_dir) && address && + !(address & ~PUD_MASK) && (address + PUD_SIZE <= end)) { + pte_val(pte) |= _REGION3_ENTRY_LARGE; + pte_val(pte) |= _REGION_ENTRY_TYPE_R3; + pud_val(*pu_dir) = pte_val(pte); + address += PUD_SIZE; + continue; + } +#endif if (pud_none(*pu_dir)) { pm_dir = vmem_pmd_alloc(); if (!pm_dir) goto out; pud_populate(&init_mm, pu_dir, pm_dir); } - - pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0)); pm_dir = pmd_offset(pu_dir, address); - #if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC) if (MACHINE_HAS_EDAT1 && pmd_none(*pm_dir) && address && !(address & ~PMD_MASK) && (address + PMD_SIZE <= end)) { @@ -160,6 +167,11 @@ static void vmem_remove_range(unsigned long start, unsigned long size) address += PUD_SIZE; continue; } + if (pud_large(*pu_dir)) { + pud_clear(pu_dir); + address += PUD_SIZE; + continue; + } pm_dir = pmd_offset(pu_dir, address); if (pmd_none(*pm_dir)) { address += PMD_SIZE; |