cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mmap-nommu.c (2367B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/* NOMMU mmap support for RomFS on MTD devices
      3 *
      4 * Copyright © 2007 Red Hat, Inc. All Rights Reserved.
      5 * Written by David Howells (dhowells@redhat.com)
      6 */
      7
      8#include <linux/mm.h>
      9#include <linux/mtd/super.h>
     10#include "internal.h"
     11
     12/*
     13 * try to determine where a shared mapping can be made
     14 * - only supported for NOMMU at the moment (MMU can't doesn't copy private
     15 *   mappings)
     16 * - attempts to map through to the underlying MTD device
     17 */
     18static unsigned long romfs_get_unmapped_area(struct file *file,
     19					     unsigned long addr,
     20					     unsigned long len,
     21					     unsigned long pgoff,
     22					     unsigned long flags)
     23{
     24	struct inode *inode = file->f_mapping->host;
     25	struct mtd_info *mtd = inode->i_sb->s_mtd;
     26	unsigned long isize, offset, maxpages, lpages;
     27	int ret;
     28
     29	if (!mtd)
     30		return (unsigned long) -ENOSYS;
     31
     32	/* the mapping mustn't extend beyond the EOF */
     33	lpages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
     34	isize = i_size_read(inode);
     35	offset = pgoff << PAGE_SHIFT;
     36
     37	maxpages = (isize + PAGE_SIZE - 1) >> PAGE_SHIFT;
     38	if ((pgoff >= maxpages) || (maxpages - pgoff < lpages))
     39		return (unsigned long) -EINVAL;
     40
     41	if (addr != 0)
     42		return (unsigned long) -EINVAL;
     43
     44	if (len > mtd->size || pgoff >= (mtd->size >> PAGE_SHIFT))
     45		return (unsigned long) -EINVAL;
     46
     47	offset += ROMFS_I(inode)->i_dataoffset;
     48	if (offset >= mtd->size)
     49		return (unsigned long) -EINVAL;
     50	/* the mapping mustn't extend beyond the EOF */
     51	if ((offset + len) > mtd->size)
     52		len = mtd->size - offset;
     53
     54	ret = mtd_get_unmapped_area(mtd, len, offset, flags);
     55	if (ret == -EOPNOTSUPP)
     56		ret = -ENOSYS;
     57	return (unsigned long) ret;
     58}
     59
     60/*
     61 * permit a R/O mapping to be made directly through onto an MTD device if
     62 * possible
     63 */
     64static int romfs_mmap(struct file *file, struct vm_area_struct *vma)
     65{
     66	return vma->vm_flags & (VM_SHARED | VM_MAYSHARE) ? 0 : -ENOSYS;
     67}
     68
     69static unsigned romfs_mmap_capabilities(struct file *file)
     70{
     71	struct mtd_info *mtd = file_inode(file)->i_sb->s_mtd;
     72
     73	if (!mtd)
     74		return NOMMU_MAP_COPY;
     75	return mtd_mmap_capabilities(mtd);
     76}
     77
     78const struct file_operations romfs_ro_fops = {
     79	.llseek			= generic_file_llseek,
     80	.read_iter		= generic_file_read_iter,
     81	.splice_read		= generic_file_splice_read,
     82	.mmap			= romfs_mmap,
     83	.get_unmapped_area	= romfs_get_unmapped_area,
     84	.mmap_capabilities	= romfs_mmap_capabilities,
     85};