162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ARC700 mmap 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * (started from arm version - for VIPT alias handling) 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/fs.h> 1162306a36Sopenharmony_ci#include <linux/mm.h> 1262306a36Sopenharmony_ci#include <linux/mman.h> 1362306a36Sopenharmony_ci#include <linux/sched/mm.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <asm/cacheflush.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define COLOUR_ALIGN(addr, pgoff) \ 1862306a36Sopenharmony_ci ((((addr) + SHMLBA - 1) & ~(SHMLBA - 1)) + \ 1962306a36Sopenharmony_ci (((pgoff) << PAGE_SHIFT) & (SHMLBA - 1))) 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* 2262306a36Sopenharmony_ci * Ensure that shared mappings are correctly aligned to 2362306a36Sopenharmony_ci * avoid aliasing issues with VIPT caches. 2462306a36Sopenharmony_ci * We need to ensure that 2562306a36Sopenharmony_ci * a specific page of an object is always mapped at a multiple of 2662306a36Sopenharmony_ci * SHMLBA bytes. 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_ciunsigned long 2962306a36Sopenharmony_ciarch_get_unmapped_area(struct file *filp, unsigned long addr, 3062306a36Sopenharmony_ci unsigned long len, unsigned long pgoff, unsigned long flags) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci struct mm_struct *mm = current->mm; 3362306a36Sopenharmony_ci struct vm_area_struct *vma; 3462306a36Sopenharmony_ci int do_align = 0; 3562306a36Sopenharmony_ci int aliasing = cache_is_vipt_aliasing(); 3662306a36Sopenharmony_ci struct vm_unmapped_area_info info; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci /* 3962306a36Sopenharmony_ci * We only need to do colour alignment if D cache aliases. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci if (aliasing) 4262306a36Sopenharmony_ci do_align = filp || (flags & MAP_SHARED); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci /* 4562306a36Sopenharmony_ci * We enforce the MAP_FIXED case. 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_ci if (flags & MAP_FIXED) { 4862306a36Sopenharmony_ci if (aliasing && flags & MAP_SHARED && 4962306a36Sopenharmony_ci (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)) 5062306a36Sopenharmony_ci return -EINVAL; 5162306a36Sopenharmony_ci return addr; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci if (len > TASK_SIZE) 5562306a36Sopenharmony_ci return -ENOMEM; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci if (addr) { 5862306a36Sopenharmony_ci if (do_align) 5962306a36Sopenharmony_ci addr = COLOUR_ALIGN(addr, pgoff); 6062306a36Sopenharmony_ci else 6162306a36Sopenharmony_ci addr = PAGE_ALIGN(addr); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci vma = find_vma(mm, addr); 6462306a36Sopenharmony_ci if (TASK_SIZE - len >= addr && 6562306a36Sopenharmony_ci (!vma || addr + len <= vm_start_gap(vma))) 6662306a36Sopenharmony_ci return addr; 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci info.flags = 0; 7062306a36Sopenharmony_ci info.length = len; 7162306a36Sopenharmony_ci info.low_limit = mm->mmap_base; 7262306a36Sopenharmony_ci info.high_limit = TASK_SIZE; 7362306a36Sopenharmony_ci info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; 7462306a36Sopenharmony_ci info.align_offset = pgoff << PAGE_SHIFT; 7562306a36Sopenharmony_ci return vm_unmapped_area(&info); 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic const pgprot_t protection_map[16] = { 7962306a36Sopenharmony_ci [VM_NONE] = PAGE_U_NONE, 8062306a36Sopenharmony_ci [VM_READ] = PAGE_U_R, 8162306a36Sopenharmony_ci [VM_WRITE] = PAGE_U_R, 8262306a36Sopenharmony_ci [VM_WRITE | VM_READ] = PAGE_U_R, 8362306a36Sopenharmony_ci [VM_EXEC] = PAGE_U_X_R, 8462306a36Sopenharmony_ci [VM_EXEC | VM_READ] = PAGE_U_X_R, 8562306a36Sopenharmony_ci [VM_EXEC | VM_WRITE] = PAGE_U_X_R, 8662306a36Sopenharmony_ci [VM_EXEC | VM_WRITE | VM_READ] = PAGE_U_X_R, 8762306a36Sopenharmony_ci [VM_SHARED] = PAGE_U_NONE, 8862306a36Sopenharmony_ci [VM_SHARED | VM_READ] = PAGE_U_R, 8962306a36Sopenharmony_ci [VM_SHARED | VM_WRITE] = PAGE_U_W_R, 9062306a36Sopenharmony_ci [VM_SHARED | VM_WRITE | VM_READ] = PAGE_U_W_R, 9162306a36Sopenharmony_ci [VM_SHARED | VM_EXEC] = PAGE_U_X_R, 9262306a36Sopenharmony_ci [VM_SHARED | VM_EXEC | VM_READ] = PAGE_U_X_R, 9362306a36Sopenharmony_ci [VM_SHARED | VM_EXEC | VM_WRITE] = PAGE_U_X_W_R, 9462306a36Sopenharmony_ci [VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] = PAGE_U_X_W_R 9562306a36Sopenharmony_ci}; 9662306a36Sopenharmony_ciDECLARE_VM_GET_PAGE_PROT 97