brintos

brintos / linux-shallow public Read only

0
0
Text · 6.7 KiB · ce06b28 Raw
298 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Provide common bits of early_ioremap() support for architectures needing4 * temporary mappings during boot before ioremap() is available.5 *6 * This is mostly a direct copy of the x86 early_ioremap implementation.7 *8 * (C) Copyright 1995 1996, 2014 Linus Torvalds9 *10 */11#include <linux/kernel.h>12#include <linux/init.h>13#include <linux/io.h>14#include <linux/module.h>15#include <linux/slab.h>16#include <linux/mm.h>17#include <linux/vmalloc.h>18#include <asm/fixmap.h>19#include <asm/early_ioremap.h>20#include "internal.h"21 22#ifdef CONFIG_MMU23static int early_ioremap_debug __initdata;24 25static int __init early_ioremap_debug_setup(char *str)26{27	early_ioremap_debug = 1;28 29	return 0;30}31early_param("early_ioremap_debug", early_ioremap_debug_setup);32 33static int after_paging_init __initdata;34 35pgprot_t __init __weak early_memremap_pgprot_adjust(resource_size_t phys_addr,36						    unsigned long size,37						    pgprot_t prot)38{39	return prot;40}41 42void __init early_ioremap_reset(void)43{44	after_paging_init = 1;45}46 47/*48 * Generally, ioremap() is available after paging_init() has been called.49 * Architectures wanting to allow early_ioremap after paging_init() can50 * define __late_set_fixmap and __late_clear_fixmap to do the right thing.51 */52#ifndef __late_set_fixmap53static inline void __init __late_set_fixmap(enum fixed_addresses idx,54					    phys_addr_t phys, pgprot_t prot)55{56	BUG();57}58#endif59 60#ifndef __late_clear_fixmap61static inline void __init __late_clear_fixmap(enum fixed_addresses idx)62{63	BUG();64}65#endif66 67static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata;68static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata;69static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata;70 71void __init early_ioremap_setup(void)72{73	int i;74 75	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {76		WARN_ON_ONCE(prev_map[i]);77		slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i);78	}79}80 81static int __init check_early_ioremap_leak(void)82{83	int count = 0;84	int i;85 86	for (i = 0; i < FIX_BTMAPS_SLOTS; i++)87		if (prev_map[i])88			count++;89 90	if (WARN(count, KERN_WARNING91		 "Debug warning: early ioremap leak of %d areas detected.\n"92		 "please boot with early_ioremap_debug and report the dmesg.\n",93		 count))94		return 1;95	return 0;96}97late_initcall(check_early_ioremap_leak);98 99static void __init __iomem *100__early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot)101{102	unsigned long offset;103	resource_size_t last_addr;104	unsigned int nrpages;105	enum fixed_addresses idx;106	int i, slot;107 108	WARN_ON(system_state >= SYSTEM_RUNNING);109 110	slot = -1;111	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {112		if (!prev_map[i]) {113			slot = i;114			break;115		}116	}117 118	if (WARN(slot < 0, "%s(%pa, %08lx) not found slot\n",119		 __func__, &phys_addr, size))120		return NULL;121 122	/* Don't allow wraparound or zero size */123	last_addr = phys_addr + size - 1;124	if (WARN_ON(!size || last_addr < phys_addr))125		return NULL;126 127	prev_size[slot] = size;128	/*129	 * Mappings have to be page-aligned130	 */131	offset = offset_in_page(phys_addr);132	phys_addr &= PAGE_MASK;133	size = PAGE_ALIGN(last_addr + 1) - phys_addr;134 135	/*136	 * Mappings have to fit in the FIX_BTMAP area.137	 */138	nrpages = size >> PAGE_SHIFT;139	if (WARN_ON(nrpages > NR_FIX_BTMAPS))140		return NULL;141 142	/*143	 * Ok, go for it..144	 */145	idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;146	while (nrpages > 0) {147		if (after_paging_init)148			__late_set_fixmap(idx, phys_addr, prot);149		else150			__early_set_fixmap(idx, phys_addr, prot);151		phys_addr += PAGE_SIZE;152		--idx;153		--nrpages;154	}155	WARN(early_ioremap_debug, "%s(%pa, %08lx) [%d] => %08lx + %08lx\n",156	     __func__, &phys_addr, size, slot, offset, slot_virt[slot]);157 158	prev_map[slot] = (void __iomem *)(offset + slot_virt[slot]);159	return prev_map[slot];160}161 162void __init early_iounmap(void __iomem *addr, unsigned long size)163{164	unsigned long virt_addr;165	unsigned long offset;166	unsigned int nrpages;167	enum fixed_addresses idx;168	int i, slot;169 170	slot = -1;171	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {172		if (prev_map[i] == addr) {173			slot = i;174			break;175		}176	}177 178	if (WARN(slot < 0, "%s(%p, %08lx) not found slot\n",179		  __func__, addr, size))180		return;181 182	if (WARN(prev_size[slot] != size,183		 "%s(%p, %08lx) [%d] size not consistent %08lx\n",184		  __func__, addr, size, slot, prev_size[slot]))185		return;186 187	WARN(early_ioremap_debug, "%s(%p, %08lx) [%d]\n",188	      __func__, addr, size, slot);189 190	virt_addr = (unsigned long)addr;191	if (WARN_ON(virt_addr < fix_to_virt(FIX_BTMAP_BEGIN)))192		return;193 194	offset = offset_in_page(virt_addr);195	nrpages = PAGE_ALIGN(offset + size) >> PAGE_SHIFT;196 197	idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;198	while (nrpages > 0) {199		if (after_paging_init)200			__late_clear_fixmap(idx);201		else202			__early_set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR);203		--idx;204		--nrpages;205	}206	prev_map[slot] = NULL;207}208 209/* Remap an IO device */210void __init __iomem *211early_ioremap(resource_size_t phys_addr, unsigned long size)212{213	return __early_ioremap(phys_addr, size, FIXMAP_PAGE_IO);214}215 216/* Remap memory */217void __init *218early_memremap(resource_size_t phys_addr, unsigned long size)219{220	pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size,221						     FIXMAP_PAGE_NORMAL);222 223	return (__force void *)__early_ioremap(phys_addr, size, prot);224}225#ifdef FIXMAP_PAGE_RO226void __init *227early_memremap_ro(resource_size_t phys_addr, unsigned long size)228{229	pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size,230						     FIXMAP_PAGE_RO);231 232	return (__force void *)__early_ioremap(phys_addr, size, prot);233}234#endif235 236#ifdef CONFIG_ARCH_USE_MEMREMAP_PROT237void __init *238early_memremap_prot(resource_size_t phys_addr, unsigned long size,239		    unsigned long prot_val)240{241	return (__force void *)__early_ioremap(phys_addr, size,242					       __pgprot(prot_val));243}244#endif245 246#define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)247 248void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)249{250	unsigned long slop, clen;251	char *p;252 253	while (size) {254		slop = offset_in_page(src);255		clen = size;256		if (clen > MAX_MAP_CHUNK - slop)257			clen = MAX_MAP_CHUNK - slop;258		p = early_memremap(src & PAGE_MASK, clen + slop);259		memcpy(dest, p + slop, clen);260		early_memunmap(p, clen + slop);261		dest += clen;262		src += clen;263		size -= clen;264	}265}266 267#else /* CONFIG_MMU */268 269void __init __iomem *270early_ioremap(resource_size_t phys_addr, unsigned long size)271{272	return (__force void __iomem *)phys_addr;273}274 275/* Remap memory */276void __init *277early_memremap(resource_size_t phys_addr, unsigned long size)278{279	return (void *)phys_addr;280}281void __init *282early_memremap_ro(resource_size_t phys_addr, unsigned long size)283{284	return (void *)phys_addr;285}286 287void __init early_iounmap(void __iomem *addr, unsigned long size)288{289}290 291#endif /* CONFIG_MMU */292 293 294void __init early_memunmap(void *addr, unsigned long size)295{296	early_iounmap((__force void __iomem *)addr, size);297}298