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

ioremap_fixed.c (2661B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Re-map IO memory to kernel address space so that we can access it.
      4 *
      5 * These functions should only be used when it is necessary to map a
      6 * physical address space into the kernel address space before ioremap()
      7 * can be used, e.g. early in boot before paging_init().
      8 *
      9 * Copyright (C) 2009  Matt Fleming
     10 */
     11
     12#include <linux/vmalloc.h>
     13#include <linux/ioport.h>
     14#include <linux/module.h>
     15#include <linux/mm.h>
     16#include <linux/io.h>
     17#include <linux/memblock.h>
     18#include <linux/proc_fs.h>
     19#include <asm/fixmap.h>
     20#include <asm/page.h>
     21#include <asm/addrspace.h>
     22#include <asm/cacheflush.h>
     23#include <asm/tlbflush.h>
     24#include <asm/mmu.h>
     25#include <asm/mmu_context.h>
     26#include "ioremap.h"
     27
     28struct ioremap_map {
     29	void __iomem *addr;
     30	unsigned long size;
     31	unsigned long fixmap_addr;
     32};
     33
     34static struct ioremap_map ioremap_maps[FIX_N_IOREMAPS];
     35
     36void __init ioremap_fixed_init(void)
     37{
     38	struct ioremap_map *map;
     39	int i;
     40
     41	for (i = 0; i < FIX_N_IOREMAPS; i++) {
     42		map = &ioremap_maps[i];
     43		map->fixmap_addr = __fix_to_virt(FIX_IOREMAP_BEGIN + i);
     44	}
     45}
     46
     47void __init __iomem *
     48ioremap_fixed(phys_addr_t phys_addr, unsigned long size, pgprot_t prot)
     49{
     50	enum fixed_addresses idx0, idx;
     51	struct ioremap_map *map;
     52	unsigned int nrpages;
     53	unsigned long offset;
     54	int i, slot;
     55
     56	/*
     57	 * Mappings have to be page-aligned
     58	 */
     59	offset = phys_addr & ~PAGE_MASK;
     60	phys_addr &= PAGE_MASK;
     61	size = PAGE_ALIGN(phys_addr + size) - phys_addr;
     62
     63	slot = -1;
     64	for (i = 0; i < FIX_N_IOREMAPS; i++) {
     65		map = &ioremap_maps[i];
     66		if (!map->addr) {
     67			map->size = size;
     68			slot = i;
     69			break;
     70		}
     71	}
     72
     73	if (slot < 0)
     74		return NULL;
     75
     76	/*
     77	 * Mappings have to fit in the FIX_IOREMAP area.
     78	 */
     79	nrpages = size >> PAGE_SHIFT;
     80	if (nrpages > FIX_N_IOREMAPS)
     81		return NULL;
     82
     83	/*
     84	 * Ok, go for it..
     85	 */
     86	idx0 = FIX_IOREMAP_BEGIN + slot;
     87	idx = idx0;
     88	while (nrpages > 0) {
     89		pgprot_val(prot) |= _PAGE_WIRED;
     90		__set_fixmap(idx, phys_addr, prot);
     91		phys_addr += PAGE_SIZE;
     92		idx++;
     93		--nrpages;
     94	}
     95
     96	map->addr = (void __iomem *)(offset + map->fixmap_addr);
     97	return map->addr;
     98}
     99
    100int iounmap_fixed(void __iomem *addr)
    101{
    102	enum fixed_addresses idx;
    103	struct ioremap_map *map;
    104	unsigned int nrpages;
    105	int i, slot;
    106
    107	slot = -1;
    108	for (i = 0; i < FIX_N_IOREMAPS; i++) {
    109		map = &ioremap_maps[i];
    110		if (map->addr == addr) {
    111			slot = i;
    112			break;
    113		}
    114	}
    115
    116	/*
    117	 * If we don't match, it's not for us.
    118	 */
    119	if (slot < 0)
    120		return -EINVAL;
    121
    122	nrpages = map->size >> PAGE_SHIFT;
    123
    124	idx = FIX_IOREMAP_BEGIN + slot + nrpages - 1;
    125	while (nrpages > 0) {
    126		__clear_fixmap(idx, __pgprot(_PAGE_WIRED));
    127		--idx;
    128		--nrpages;
    129	}
    130
    131	map->size = 0;
    132	map->addr = NULL;
    133
    134	return 0;
    135}