ioremap.c 17.8 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8
/*
 * Re-map IO memory to kernel address space so that we can access it.
 * This is needed for high PCI addresses that aren't mapped in the
 * 640k-1MB IO memory area on PC's
 *
 * (C) Copyright 1995 1996 Linus Torvalds
 */

9
#include <linux/bootmem.h>
L
Linus Torvalds 已提交
10
#include <linux/init.h>
11
#include <linux/io.h>
T
Thomas Gleixner 已提交
12 13 14
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
P
Pekka Paalanen 已提交
15
#include <linux/mmiotrace.h>
T
Thomas Gleixner 已提交
16

L
Linus Torvalds 已提交
17
#include <asm/cacheflush.h>
T
Thomas Gleixner 已提交
18 19
#include <asm/e820.h>
#include <asm/fixmap.h>
L
Linus Torvalds 已提交
20
#include <asm/pgtable.h>
T
Thomas Gleixner 已提交
21
#include <asm/tlbflush.h>
22
#include <asm/pgalloc.h>
23
#include <asm/pat.h>
L
Linus Torvalds 已提交
24

T
Thomas Gleixner 已提交
25 26
#ifdef CONFIG_X86_64

J
Jiri Slaby 已提交
27
static inline int phys_addr_valid(unsigned long addr)
T
Thomas Gleixner 已提交
28
{
J
Jiri Slaby 已提交
29
	return addr < (1UL << boot_cpu_data.x86_phys_bits);
T
Thomas Gleixner 已提交
30 31
}

J
Jiri Slaby 已提交
32
unsigned long __phys_addr(unsigned long x)
33
{
J
Jiri Slaby 已提交
34 35 36 37 38 39 40 41 42 43 44
	if (x >= __START_KERNEL_map) {
		x -= __START_KERNEL_map;
		VIRTUAL_BUG_ON(x >= KERNEL_IMAGE_SIZE);
		x += phys_base;
	} else {
		VIRTUAL_BUG_ON(x < PAGE_OFFSET);
		x -= PAGE_OFFSET;
		VIRTUAL_BUG_ON(system_state == SYSTEM_BOOTING ? x > MAXMEM :
					!phys_addr_valid(x));
	}
	return x;
45
}
J
Jiri Slaby 已提交
46
EXPORT_SYMBOL(__phys_addr);
47

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
bool __virt_addr_valid(unsigned long x)
{
	if (x >= __START_KERNEL_map) {
		x -= __START_KERNEL_map;
		if (x >= KERNEL_IMAGE_SIZE)
			return false;
		x += phys_base;
	} else {
		if (x < PAGE_OFFSET)
			return false;
		x -= PAGE_OFFSET;
		if (system_state == SYSTEM_BOOTING ?
				x > MAXMEM : !phys_addr_valid(x)) {
			return false;
		}
	}

	return pfn_valid(x >> PAGE_SHIFT);
}
EXPORT_SYMBOL(__virt_addr_valid);

69 70 71 72 73 74 75
#else

static inline int phys_addr_valid(unsigned long addr)
{
	return 1;
}

J
Jiri Slaby 已提交
76
#ifdef CONFIG_DEBUG_VIRTUAL
J
Jiri Slaby 已提交
77 78 79
unsigned long __phys_addr(unsigned long x)
{
	/* VMALLOC_* aren't constants; not available at the boot time */
80 81 82
	VIRTUAL_BUG_ON(x < PAGE_OFFSET);
	VIRTUAL_BUG_ON(system_state != SYSTEM_BOOTING &&
		is_vmalloc_addr((void *) x));
J
Jiri Slaby 已提交
83 84 85
	return x - PAGE_OFFSET;
}
EXPORT_SYMBOL(__phys_addr);
J
Jiri Slaby 已提交
86
#endif
J
Jiri Slaby 已提交
87

88 89 90 91 92 93 94 95 96 97
bool __virt_addr_valid(unsigned long x)
{
	if (x < PAGE_OFFSET)
		return false;
	if (system_state != SYSTEM_BOOTING && is_vmalloc_addr((void *) x))
		return false;
	return pfn_valid((x - PAGE_OFFSET) >> PAGE_SHIFT);
}
EXPORT_SYMBOL(__virt_addr_valid);

T
Thomas Gleixner 已提交
98 99
#endif

100 101
int page_is_ram(unsigned long pagenr)
{
102
	resource_size_t addr, end;
103 104
	int i;

105 106 107 108 109 110 111 112
	/*
	 * A special case is the first 4Kb of memory;
	 * This is a BIOS owned area, not kernel ram, but generally
	 * not listed as such in the E820 table.
	 */
	if (pagenr == 0)
		return 0;

A
Arjan van de Ven 已提交
113 114 115 116 117 118 119
	/*
	 * Second special case: Some BIOSen report the PC BIOS
	 * area (640->1Mb) as ram even though it is not.
	 */
	if (pagenr >= (BIOS_BEGIN >> PAGE_SHIFT) &&
		    pagenr < (BIOS_END >> PAGE_SHIFT))
		return 0;
120

121 122 123 124 125 126 127 128
	for (i = 0; i < e820.nr_map; i++) {
		/*
		 * Not usable memory:
		 */
		if (e820.map[i].type != E820_RAM)
			continue;
		addr = (e820.map[i].addr + PAGE_SIZE-1) >> PAGE_SHIFT;
		end = (e820.map[i].addr + e820.map[i].size) >> PAGE_SHIFT;
129 130


131 132 133 134 135 136
		if ((pagenr >= addr) && (pagenr < end))
			return 1;
	}
	return 0;
}

137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
int pagerange_is_ram(unsigned long start, unsigned long end)
{
	int ram_page = 0, not_rampage = 0;
	unsigned long page_nr;

	for (page_nr = (start >> PAGE_SHIFT); page_nr < (end >> PAGE_SHIFT);
	     ++page_nr) {
		if (page_is_ram(page_nr))
			ram_page = 1;
		else
			not_rampage = 1;

		if (ram_page == not_rampage)
			return -1;
	}

	return ram_page;
}

156 157 158 159
/*
 * Fix up the linear direct mapping of the kernel to avoid cache attribute
 * conflicts.
 */
160 161
int ioremap_change_attr(unsigned long vaddr, unsigned long size,
			       unsigned long prot_val)
162
{
163
	unsigned long nrpages = size >> PAGE_SHIFT;
164
	int err;
165

166 167
	switch (prot_val) {
	case _PAGE_CACHE_UC:
168
	default:
169
		err = _set_memory_uc(vaddr, nrpages);
170
		break;
171 172 173
	case _PAGE_CACHE_WC:
		err = _set_memory_wc(vaddr, nrpages);
		break;
174
	case _PAGE_CACHE_WB:
175
		err = _set_memory_wb(vaddr, nrpages);
176 177
		break;
	}
178 179 180 181

	return err;
}

L
Linus Torvalds 已提交
182 183 184 185 186 187 188 189 190
/*
 * Remap an arbitrary physical address space into the kernel virtual
 * address space. Needed when the kernel wants to access high addresses
 * directly.
 *
 * NOTE! We need to allow non-page-aligned mappings too: we will obviously
 * have to convert them into an offset in a page-aligned mapping, but the
 * caller shouldn't need to know that small detail.
 */
191 192
static void __iomem *__ioremap_caller(resource_size_t phys_addr,
		unsigned long size, unsigned long prot_val, void *caller)
L
Linus Torvalds 已提交
193
{
194 195
	unsigned long pfn, offset, vaddr;
	resource_size_t last_addr;
196 197
	const resource_size_t unaligned_phys_addr = phys_addr;
	const unsigned long unaligned_size = size;
198
	struct vm_struct *area;
199
	unsigned long new_prot_val;
200
	pgprot_t prot;
201
	int retval;
P
Pekka Paalanen 已提交
202
	void __iomem *ret_addr;
L
Linus Torvalds 已提交
203 204 205 206 207 208

	/* Don't allow wraparound or zero size */
	last_addr = phys_addr + size - 1;
	if (!size || last_addr < phys_addr)
		return NULL;

209
	if (!phys_addr_valid(phys_addr)) {
210
		printk(KERN_WARNING "ioremap: invalid physical address %llx\n",
211
		       (unsigned long long)phys_addr);
212 213 214 215
		WARN_ON_ONCE(1);
		return NULL;
	}

L
Linus Torvalds 已提交
216 217 218
	/*
	 * Don't remap the low PCI/ISA area, it's always mapped..
	 */
219
	if (is_ISA_range(phys_addr, last_addr))
T
Thomas Gleixner 已提交
220
		return (__force void __iomem *)phys_to_virt(phys_addr);
L
Linus Torvalds 已提交
221 222 223 224

	/*
	 * Don't allow anybody to remap normal RAM that we're using..
	 */
A
Andres Salomon 已提交
225 226 227
	for (pfn = phys_addr >> PAGE_SHIFT;
				(pfn << PAGE_SHIFT) < (last_addr & PAGE_MASK);
				pfn++) {
228

229 230 231
		int is_ram = page_is_ram(pfn);

		if (is_ram && pfn_valid(pfn) && !PageReserved(pfn_to_page(pfn)))
T
Thomas Gleixner 已提交
232
			return NULL;
233
		WARN_ON_ONCE(is_ram);
L
Linus Torvalds 已提交
234 235
	}

236 237 238 239 240 241 242
	/*
	 * Mappings have to be page-aligned
	 */
	offset = phys_addr & ~PAGE_MASK;
	phys_addr &= PAGE_MASK;
	size = PAGE_ALIGN(last_addr+1) - phys_addr;

A
Andi Kleen 已提交
243
	retval = reserve_memtype(phys_addr, (u64)phys_addr + size,
244 245
						prot_val, &new_prot_val);
	if (retval) {
246
		pr_debug("Warning: reserve_memtype returned %d\n", retval);
247 248 249 250
		return NULL;
	}

	if (prot_val != new_prot_val) {
251 252 253
		/*
		 * Do not fallback to certain memory types with certain
		 * requested type:
254 255
		 * - request is uc-, return cannot be write-back
		 * - request is uc-, return cannot be write-combine
256
		 * - request is write-combine, return cannot be write-back
257
		 */
258
		if ((prot_val == _PAGE_CACHE_UC_MINUS &&
259 260 261
		     (new_prot_val == _PAGE_CACHE_WB ||
		      new_prot_val == _PAGE_CACHE_WC)) ||
		    (prot_val == _PAGE_CACHE_WC &&
262
		     new_prot_val == _PAGE_CACHE_WB)) {
263
			pr_debug(
264
		"ioremap error for 0x%llx-0x%llx, requested 0x%lx, got 0x%lx\n",
265 266
				(unsigned long long)phys_addr,
				(unsigned long long)(phys_addr + size),
267
				prot_val, new_prot_val);
268 269 270 271 272 273
			free_memtype(phys_addr, phys_addr + size);
			return NULL;
		}
		prot_val = new_prot_val;
	}

274 275
	switch (prot_val) {
	case _PAGE_CACHE_UC:
276
	default:
277
		prot = PAGE_KERNEL_IO_NOCACHE;
278
		break;
279
	case _PAGE_CACHE_UC_MINUS:
280
		prot = PAGE_KERNEL_IO_UC_MINUS;
281
		break;
282
	case _PAGE_CACHE_WC:
283
		prot = PAGE_KERNEL_IO_WC;
284
		break;
285
	case _PAGE_CACHE_WB:
286
		prot = PAGE_KERNEL_IO;
287 288
		break;
	}
289

L
Linus Torvalds 已提交
290 291 292
	/*
	 * Ok, go for it..
	 */
293
	area = get_vm_area_caller(size, VM_IOREMAP, caller);
L
Linus Torvalds 已提交
294 295 296
	if (!area)
		return NULL;
	area->phys_addr = phys_addr;
T
Thomas Gleixner 已提交
297 298
	vaddr = (unsigned long) area->addr;
	if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot)) {
299
		free_memtype(phys_addr, phys_addr + size);
300
		free_vm_area(area);
L
Linus Torvalds 已提交
301 302
		return NULL;
	}
303

304
	if (ioremap_change_attr(vaddr, size, prot_val) < 0) {
305
		free_memtype(phys_addr, phys_addr + size);
T
Thomas Gleixner 已提交
306
		vunmap(area->addr);
307 308 309
		return NULL;
	}

P
Pekka Paalanen 已提交
310
	ret_addr = (void __iomem *) (vaddr + offset);
311
	mmiotrace_ioremap(unaligned_phys_addr, unaligned_size, ret_addr);
P
Pekka Paalanen 已提交
312 313

	return ret_addr;
L
Linus Torvalds 已提交
314 315 316 317 318 319 320 321 322 323 324
}

/**
 * ioremap_nocache     -   map bus memory into CPU space
 * @offset:    bus address of the memory
 * @size:      size of the resource to map
 *
 * ioremap_nocache performs a platform specific sequence of operations to
 * make bus memory CPU accessible via the readb/readw/readl/writeb/
 * writew/writel functions and the other mmio helpers. The returned
 * address is not guaranteed to be usable directly as a virtual
325
 * address.
L
Linus Torvalds 已提交
326 327 328
 *
 * This version of ioremap ensures that the memory is marked uncachable
 * on the CPU as well as honouring existing caching rules from things like
329
 * the PCI bus. Note that there are other caches and buffers on many
L
Linus Torvalds 已提交
330 331 332 333
 * busses. In particular driver authors should read up on PCI writes
 *
 * It's useful if some control registers are in such an area and
 * write combining or read caching is not desirable:
334
 *
L
Linus Torvalds 已提交
335 336
 * Must be freed with iounmap.
 */
337
void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
L
Linus Torvalds 已提交
338
{
339 340
	/*
	 * Ideally, this should be:
341
	 *	pat_enabled ? _PAGE_CACHE_UC : _PAGE_CACHE_UC_MINUS;
342 343 344 345 346 347 348
	 *
	 * Till we fix all X drivers to use ioremap_wc(), we will use
	 * UC MINUS.
	 */
	unsigned long val = _PAGE_CACHE_UC_MINUS;

	return __ioremap_caller(phys_addr, size, val,
349
				__builtin_return_address(0));
L
Linus Torvalds 已提交
350
}
351
EXPORT_SYMBOL(ioremap_nocache);
L
Linus Torvalds 已提交
352

353 354 355 356 357 358 359 360 361 362 363 364
/**
 * ioremap_wc	-	map memory into CPU space write combined
 * @offset:	bus address of the memory
 * @size:	size of the resource to map
 *
 * This version of ioremap ensures that the memory is marked write combining.
 * Write combining allows faster writes to some hardware devices.
 *
 * Must be freed with iounmap.
 */
void __iomem *ioremap_wc(unsigned long phys_addr, unsigned long size)
{
365
	if (pat_enabled)
366 367
		return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WC,
					__builtin_return_address(0));
368 369 370 371 372
	else
		return ioremap_nocache(phys_addr, size);
}
EXPORT_SYMBOL(ioremap_wc);

373
void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size)
T
Thomas Gleixner 已提交
374
{
375 376
	return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WB,
				__builtin_return_address(0));
T
Thomas Gleixner 已提交
377 378 379
}
EXPORT_SYMBOL(ioremap_cache);

380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
static void __iomem *ioremap_default(resource_size_t phys_addr,
					unsigned long size)
{
	unsigned long flags;
	void *ret;
	int err;

	/*
	 * - WB for WB-able memory and no other conflicting mappings
	 * - UC_MINUS for non-WB-able memory with no other conflicting mappings
	 * - Inherit from confliting mappings otherwise
	 */
	err = reserve_memtype(phys_addr, phys_addr + size, -1, &flags);
	if (err < 0)
		return NULL;

	ret = (void *) __ioremap_caller(phys_addr, size, flags,
					__builtin_return_address(0));

	free_memtype(phys_addr, phys_addr + size);
	return (void __iomem *)ret;
}

403 404 405 406 407 408 409 410
void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size,
				unsigned long prot_val)
{
	return __ioremap_caller(phys_addr, size, (prot_val & _PAGE_CACHE_MASK),
				__builtin_return_address(0));
}
EXPORT_SYMBOL(ioremap_prot);

411 412 413 414 415 416
/**
 * iounmap - Free a IO remapping
 * @addr: virtual address from ioremap_*
 *
 * Caller must ensure there is only one unmapping for the same pointer.
 */
L
Linus Torvalds 已提交
417 418
void iounmap(volatile void __iomem *addr)
{
419
	struct vm_struct *p, *o;
A
Andrew Morton 已提交
420 421

	if ((void __force *)addr <= high_memory)
L
Linus Torvalds 已提交
422 423 424 425 426 427 428
		return;

	/*
	 * __ioremap special-cases the PCI/ISA range by not instantiating a
	 * vm_area and by simply returning an address into the kernel mapping
	 * of ISA space.   So handle that here.
	 */
429 430
	if ((void __force *)addr >= phys_to_virt(ISA_START_ADDRESS) &&
	    (void __force *)addr < phys_to_virt(ISA_END_ADDRESS))
L
Linus Torvalds 已提交
431 432
		return;

433 434
	addr = (volatile void __iomem *)
		(PAGE_MASK & (unsigned long __force)addr);
435

P
Pekka Paalanen 已提交
436 437
	mmiotrace_iounmap(addr);

438 439 440 441 442 443 444
	/* Use the vm area unlocked, assuming the caller
	   ensures there isn't another iounmap for the same address
	   in parallel. Reuse of the virtual address is prevented by
	   leaving it in the global lists until we're done with it.
	   cpa takes care of the direct mappings. */
	read_lock(&vmlist_lock);
	for (p = vmlist; p; p = p->next) {
445
		if (p->addr == (void __force *)addr)
446 447 448 449 450
			break;
	}
	read_unlock(&vmlist_lock);

	if (!p) {
451
		printk(KERN_ERR "iounmap: bad address %p\n", addr);
A
Andrew Morton 已提交
452
		dump_stack();
453
		return;
L
Linus Torvalds 已提交
454 455
	}

456 457
	free_memtype(p->phys_addr, p->phys_addr + get_vm_area_size(p));

458
	/* Finally remove it */
459
	o = remove_vm_area((void __force *)addr);
460
	BUG_ON(p != o || o == NULL);
461
	kfree(p);
L
Linus Torvalds 已提交
462
}
463
EXPORT_SYMBOL(iounmap);
L
Linus Torvalds 已提交
464

465 466 467 468 469 470 471 472 473 474 475 476 477
/*
 * Convert a physical pointer to a virtual kernel pointer for /dev/mem
 * access
 */
void *xlate_dev_mem_ptr(unsigned long phys)
{
	void *addr;
	unsigned long start = phys & PAGE_MASK;

	/* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
	if (page_is_ram(start >> PAGE_SHIFT))
		return __va(phys);

I
Ingo Molnar 已提交
478
	addr = (void __force *)ioremap_default(start, PAGE_SIZE);
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
	if (addr)
		addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));

	return addr;
}

void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
{
	if (page_is_ram(phys >> PAGE_SHIFT))
		return;

	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
	return;
}

494
static int __initdata early_ioremap_debug;
I
Ingo Molnar 已提交
495 496 497 498 499

static int __init early_ioremap_debug_setup(char *str)
{
	early_ioremap_debug = 1;

500
	return 0;
I
Ingo Molnar 已提交
501
}
502
early_param("early_ioremap_debug", early_ioremap_debug_setup);
I
Ingo Molnar 已提交
503

504
static __initdata int after_paging_init;
505
static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
506

507
static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
508
{
509 510 511
	/* Don't assume we're using swapper_pg_dir at this point */
	pgd_t *base = __va(read_cr3());
	pgd_t *pgd = &base[pgd_index(addr)];
512 513 514 515
	pud_t *pud = pud_offset(pgd, addr);
	pmd_t *pmd = pmd_offset(pud, addr);

	return pmd;
516 517
}

518
static inline pte_t * __init early_ioremap_pte(unsigned long addr)
519
{
520
	return &bm_pte[pte_index(addr)];
521 522
}

523
void __init early_ioremap_init(void)
524
{
525
	pmd_t *pmd;
526

I
Ingo Molnar 已提交
527
	if (early_ioremap_debug)
I
Ingo Molnar 已提交
528
		printk(KERN_INFO "early_ioremap_init()\n");
I
Ingo Molnar 已提交
529

530
	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
531
	memset(bm_pte, 0, sizeof(bm_pte));
532
	pmd_populate_kernel(&init_mm, pmd, bm_pte);
533

534
	/*
535
	 * The boot-ioremap range spans multiple pmds, for which
536 537
	 * we are not prepared:
	 */
538
	if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) {
539
		WARN_ON(1);
540 541
		printk(KERN_WARNING "pmd %p != %p\n",
		       pmd, early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END)));
542
		printk(KERN_WARNING "fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
543
			fix_to_virt(FIX_BTMAP_BEGIN));
544
		printk(KERN_WARNING "fix_to_virt(FIX_BTMAP_END):   %08lx\n",
545
			fix_to_virt(FIX_BTMAP_END));
546 547 548 549

		printk(KERN_WARNING "FIX_BTMAP_END:       %d\n", FIX_BTMAP_END);
		printk(KERN_WARNING "FIX_BTMAP_BEGIN:     %d\n",
		       FIX_BTMAP_BEGIN);
550
	}
551 552
}

553
void __init early_ioremap_clear(void)
554
{
555
	pmd_t *pmd;
556

I
Ingo Molnar 已提交
557
	if (early_ioremap_debug)
I
Ingo Molnar 已提交
558
		printk(KERN_INFO "early_ioremap_clear()\n");
I
Ingo Molnar 已提交
559

560 561
	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
	pmd_clear(pmd);
562
	paravirt_release_pte(__pa(bm_pte) >> PAGE_SHIFT);
563 564 565
	__flush_tlb_all();
}

566
void __init early_ioremap_reset(void)
567 568
{
	enum fixed_addresses idx;
569 570
	unsigned long addr, phys;
	pte_t *pte;
571 572

	after_paging_init = 1;
H
Huang, Ying 已提交
573
	for (idx = FIX_BTMAP_BEGIN; idx >= FIX_BTMAP_END; idx--) {
574
		addr = fix_to_virt(idx);
575
		pte = early_ioremap_pte(addr);
576 577
		if (pte_present(*pte)) {
			phys = pte_val(*pte) & PAGE_MASK;
578 579 580 581 582
			set_fixmap(idx, phys);
		}
	}
}

583
static void __init __early_set_fixmap(enum fixed_addresses idx,
584 585
				   unsigned long phys, pgprot_t flags)
{
586 587
	unsigned long addr = __fix_to_virt(idx);
	pte_t *pte;
588 589 590 591 592

	if (idx >= __end_of_fixed_addresses) {
		BUG();
		return;
	}
593
	pte = early_ioremap_pte(addr);
594

595
	if (pgprot_val(flags))
596
		set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, flags));
597
	else
598
		pte_clear(&init_mm, addr, pte);
599 600 601
	__flush_tlb_one(addr);
}

602
static inline void __init early_set_fixmap(enum fixed_addresses idx,
J
Jeremy Fitzhardinge 已提交
603
					   unsigned long phys, pgprot_t prot)
604 605
{
	if (after_paging_init)
J
Jeremy Fitzhardinge 已提交
606
		__set_fixmap(idx, phys, prot);
607
	else
J
Jeremy Fitzhardinge 已提交
608
		__early_set_fixmap(idx, phys, prot);
609 610
}

611
static inline void __init early_clear_fixmap(enum fixed_addresses idx)
612 613 614 615
{
	if (after_paging_init)
		clear_fixmap(idx);
	else
616
		__early_set_fixmap(idx, 0, __pgprot(0));
617 618
}

I
Ingo Molnar 已提交
619

620
static int __initdata early_ioremap_nested;
I
Ingo Molnar 已提交
621

622 623 624 625
static int __init check_early_ioremap_leak(void)
{
	if (!early_ioremap_nested)
		return 0;
626
	WARN(1, KERN_WARNING
627
	       "Debug warning: early ioremap leak of %d areas detected.\n",
628
		early_ioremap_nested);
629
	printk(KERN_WARNING
630
		"please boot with early_ioremap_debug and report the dmesg.\n");
631 632 633 634 635

	return 1;
}
late_initcall(check_early_ioremap_leak);

J
Jeremy Fitzhardinge 已提交
636
static void __init *__early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot)
L
Linus Torvalds 已提交
637 638
{
	unsigned long offset, last_addr;
I
Ingo Molnar 已提交
639 640 641 642 643 644
	unsigned int nrpages, nesting;
	enum fixed_addresses idx0, idx;

	WARN_ON(system_state != SYSTEM_BOOTING);

	nesting = early_ioremap_nested;
I
Ingo Molnar 已提交
645
	if (early_ioremap_debug) {
I
Ingo Molnar 已提交
646
		printk(KERN_INFO "early_ioremap(%08lx, %08lx) [%d] => ",
647
		       phys_addr, size, nesting);
I
Ingo Molnar 已提交
648 649
		dump_stack();
	}
L
Linus Torvalds 已提交
650 651 652

	/* Don't allow wraparound or zero size */
	last_addr = phys_addr + size - 1;
653 654
	if (!size || last_addr < phys_addr) {
		WARN_ON(1);
L
Linus Torvalds 已提交
655
		return NULL;
656
	}
L
Linus Torvalds 已提交
657

658 659
	if (nesting >= FIX_BTMAPS_NESTING) {
		WARN_ON(1);
I
Ingo Molnar 已提交
660
		return NULL;
661
	}
I
Ingo Molnar 已提交
662
	early_ioremap_nested++;
L
Linus Torvalds 已提交
663 664 665 666 667
	/*
	 * Mappings have to be page-aligned
	 */
	offset = phys_addr & ~PAGE_MASK;
	phys_addr &= PAGE_MASK;
A
Alan Cox 已提交
668
	size = PAGE_ALIGN(last_addr + 1) - phys_addr;
L
Linus Torvalds 已提交
669 670 671 672 673

	/*
	 * Mappings have to fit in the FIX_BTMAP area.
	 */
	nrpages = size >> PAGE_SHIFT;
674 675
	if (nrpages > NR_FIX_BTMAPS) {
		WARN_ON(1);
L
Linus Torvalds 已提交
676
		return NULL;
677
	}
L
Linus Torvalds 已提交
678 679 680 681

	/*
	 * Ok, go for it..
	 */
I
Ingo Molnar 已提交
682 683
	idx0 = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*nesting;
	idx = idx0;
L
Linus Torvalds 已提交
684
	while (nrpages > 0) {
J
Jeremy Fitzhardinge 已提交
685
		early_set_fixmap(idx, phys_addr, prot);
L
Linus Torvalds 已提交
686 687 688 689
		phys_addr += PAGE_SIZE;
		--idx;
		--nrpages;
	}
I
Ingo Molnar 已提交
690 691
	if (early_ioremap_debug)
		printk(KERN_CONT "%08lx + %08lx\n", offset, fix_to_virt(idx0));
I
Ingo Molnar 已提交
692

693
	return (void *) (offset + fix_to_virt(idx0));
L
Linus Torvalds 已提交
694 695
}

J
Jeremy Fitzhardinge 已提交
696 697 698 699 700 701 702 703 704 705 706 707
/* Remap an IO device */
void __init *early_ioremap(unsigned long phys_addr, unsigned long size)
{
	return __early_ioremap(phys_addr, size, PAGE_KERNEL_IO);
}

/* Remap memory */
void __init *early_memremap(unsigned long phys_addr, unsigned long size)
{
	return __early_ioremap(phys_addr, size, PAGE_KERNEL);
}

708
void __init early_iounmap(void *addr, unsigned long size)
L
Linus Torvalds 已提交
709 710 711 712 713
{
	unsigned long virt_addr;
	unsigned long offset;
	unsigned int nrpages;
	enum fixed_addresses idx;
714
	int nesting;
I
Ingo Molnar 已提交
715 716

	nesting = --early_ioremap_nested;
717 718
	if (WARN_ON(nesting < 0))
		return;
L
Linus Torvalds 已提交
719

I
Ingo Molnar 已提交
720
	if (early_ioremap_debug) {
I
Ingo Molnar 已提交
721
		printk(KERN_INFO "early_iounmap(%p, %08lx) [%d]\n", addr,
722
		       size, nesting);
I
Ingo Molnar 已提交
723 724 725
		dump_stack();
	}

L
Linus Torvalds 已提交
726
	virt_addr = (unsigned long)addr;
727 728
	if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN)) {
		WARN_ON(1);
L
Linus Torvalds 已提交
729
		return;
730
	}
L
Linus Torvalds 已提交
731 732 733
	offset = virt_addr & ~PAGE_MASK;
	nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT;

I
Ingo Molnar 已提交
734
	idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*nesting;
L
Linus Torvalds 已提交
735
	while (nrpages > 0) {
736
		early_clear_fixmap(idx);
L
Linus Torvalds 已提交
737 738 739 740
		--idx;
		--nrpages;
	}
}
I
Ingo Molnar 已提交
741 742 743 744 745

void __this_fixmap_does_not_exist(void)
{
	WARN_ON(1);
}