aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Salter <msalter@redhat.com>2014-04-07 18:39:49 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-07 19:36:15 -0400
commit5b7c73e00968c7fdf908c3ced31e1cc83c01ba14 (patch)
tree5d733047855bc22d40e022ea27a11ba7b52b03e4
parent9e5c33d7aeeef62e5fa7e74f94432685bd03026b (diff)
x86: use generic early_ioremap
Move x86 over to the generic early ioremap implementation. Signed-off-by: Mark Salter <msalter@redhat.com> Acked-by: H. Peter Anvin <hpa@zytor.com> Cc: Borislav Petkov <borislav.petkov@amd.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Dave Young <dyoung@redhat.com> Cc: Will Deacon <will.deacon@arm.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/include/asm/Kbuild1
-rw-r--r--arch/x86/include/asm/fixmap.h6
-rw-r--r--arch/x86/include/asm/io.h15
-rw-r--r--arch/x86/mm/ioremap.c228
-rw-r--r--arch/x86/mm/pgtable_32.c2
6 files changed, 13 insertions, 240 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index f73071742975..5b8ec0f53b57 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -43,6 +43,7 @@ config X86
43 select HAVE_DMA_ATTRS 43 select HAVE_DMA_ATTRS
44 select HAVE_DMA_CONTIGUOUS if !SWIOTLB 44 select HAVE_DMA_CONTIGUOUS if !SWIOTLB
45 select HAVE_KRETPROBES 45 select HAVE_KRETPROBES
46 select GENERIC_EARLY_IOREMAP
46 select HAVE_OPTPROBES 47 select HAVE_OPTPROBES
47 select HAVE_KPROBES_ON_FTRACE 48 select HAVE_KPROBES_ON_FTRACE
48 select HAVE_FTRACE_MCOUNT_RECORD 49 select HAVE_FTRACE_MCOUNT_RECORD
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 4acddc43ee0c..3ca9762e1649 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -5,5 +5,6 @@ genhdr-y += unistd_64.h
5genhdr-y += unistd_x32.h 5genhdr-y += unistd_x32.h
6 6
7generic-y += clkdev.h 7generic-y += clkdev.h
8generic-y += early_ioremap.h
8generic-y += cputime.h 9generic-y += cputime.h
9generic-y += mcs_spinlock.h 10generic-y += mcs_spinlock.h
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 8dcd35c4c787..43f482a0db37 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -163,5 +163,11 @@ static inline void __set_fixmap(enum fixed_addresses idx,
163 163
164#include <asm-generic/fixmap.h> 164#include <asm-generic/fixmap.h>
165 165
166#define __late_set_fixmap(idx, phys, flags) __set_fixmap(idx, phys, flags)
167#define __late_clear_fixmap(idx) __set_fixmap(idx, 0, __pgprot(0))
168
169void __early_set_fixmap(enum fixed_addresses idx,
170 phys_addr_t phys, pgprot_t flags);
171
166#endif /* !__ASSEMBLY__ */ 172#endif /* !__ASSEMBLY__ */
167#endif /* _ASM_X86_FIXMAP_H */ 173#endif /* _ASM_X86_FIXMAP_H */
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 7cec9ef3a73a..b8237d8a1e0c 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -39,6 +39,7 @@
39#include <linux/string.h> 39#include <linux/string.h>
40#include <linux/compiler.h> 40#include <linux/compiler.h>
41#include <asm/page.h> 41#include <asm/page.h>
42#include <asm/early_ioremap.h>
42 43
43#define build_mmio_read(name, size, type, reg, barrier) \ 44#define build_mmio_read(name, size, type, reg, barrier) \
44static inline type name(const volatile void __iomem *addr) \ 45static inline type name(const volatile void __iomem *addr) \
@@ -316,20 +317,6 @@ extern int ioremap_change_attr(unsigned long vaddr, unsigned long size,
316 unsigned long prot_val); 317 unsigned long prot_val);
317extern void __iomem *ioremap_wc(resource_size_t offset, unsigned long size); 318extern void __iomem *ioremap_wc(resource_size_t offset, unsigned long size);
318 319
319/*
320 * early_ioremap() and early_iounmap() are for temporary early boot-time
321 * mappings, before the real ioremap() is functional.
322 * A boot-time mapping is currently limited to at most 16 pages.
323 */
324extern void early_ioremap_init(void);
325extern void early_ioremap_reset(void);
326extern void __iomem *early_ioremap(resource_size_t phys_addr,
327 unsigned long size);
328extern void *early_memremap(resource_size_t phys_addr,
329 unsigned long size);
330extern void early_iounmap(void __iomem *addr, unsigned long size);
331extern void early_memunmap(void *addr, unsigned long size);
332extern void fixup_early_ioremap(void);
333extern bool is_early_ioremap_ptep(pte_t *ptep); 320extern bool is_early_ioremap_ptep(pte_t *ptep);
334 321
335#ifdef CONFIG_XEN 322#ifdef CONFIG_XEN
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index bbb450412810..597ac155c91c 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -328,17 +328,6 @@ void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
328 return; 328 return;
329} 329}
330 330
331static int __initdata early_ioremap_debug;
332
333static int __init early_ioremap_debug_setup(char *str)
334{
335 early_ioremap_debug = 1;
336
337 return 0;
338}
339early_param("early_ioremap_debug", early_ioremap_debug_setup);
340
341static __initdata int after_paging_init;
342static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss; 331static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
343 332
344static inline pmd_t * __init early_ioremap_pmd(unsigned long addr) 333static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
@@ -362,18 +351,11 @@ bool __init is_early_ioremap_ptep(pte_t *ptep)
362 return ptep >= &bm_pte[0] && ptep < &bm_pte[PAGE_SIZE/sizeof(pte_t)]; 351 return ptep >= &bm_pte[0] && ptep < &bm_pte[PAGE_SIZE/sizeof(pte_t)];
363} 352}
364 353
365static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata;
366
367void __init early_ioremap_init(void) 354void __init early_ioremap_init(void)
368{ 355{
369 pmd_t *pmd; 356 pmd_t *pmd;
370 int i;
371 357
372 if (early_ioremap_debug) 358 early_ioremap_setup();
373 printk(KERN_INFO "early_ioremap_init()\n");
374
375 for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
376 slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i);
377 359
378 pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN)); 360 pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
379 memset(bm_pte, 0, sizeof(bm_pte)); 361 memset(bm_pte, 0, sizeof(bm_pte));
@@ -402,13 +384,8 @@ void __init early_ioremap_init(void)
402 } 384 }
403} 385}
404 386
405void __init early_ioremap_reset(void) 387void __init __early_set_fixmap(enum fixed_addresses idx,
406{ 388 phys_addr_t phys, pgprot_t flags)
407 after_paging_init = 1;
408}
409
410static void __init __early_set_fixmap(enum fixed_addresses idx,
411 phys_addr_t phys, pgprot_t flags)
412{ 389{
413 unsigned long addr = __fix_to_virt(idx); 390 unsigned long addr = __fix_to_virt(idx);
414 pte_t *pte; 391 pte_t *pte;
@@ -425,202 +402,3 @@ static void __init __early_set_fixmap(enum fixed_addresses idx,
425 pte_clear(&init_mm, addr, pte); 402 pte_clear(&init_mm, addr, pte);
426 __flush_tlb_one(addr); 403 __flush_tlb_one(addr);
427} 404}
428
429static inline void __init early_set_fixmap(enum fixed_addresses idx,
430 phys_addr_t phys, pgprot_t prot)
431{
432 if (after_paging_init)
433 __set_fixmap(idx, phys, prot);
434 else
435 __early_set_fixmap(idx, phys, prot);
436}
437
438static inline void __init early_clear_fixmap(enum fixed_addresses idx)
439{
440 if (after_paging_init)
441 clear_fixmap(idx);
442 else
443 __early_set_fixmap(idx, 0, __pgprot(0));
444}
445
446static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata;
447static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata;
448
449void __init fixup_early_ioremap(void)
450{
451 int i;
452
453 for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
454 if (prev_map[i]) {
455 WARN_ON(1);
456 break;
457 }
458 }
459
460 early_ioremap_init();
461}
462
463static int __init check_early_ioremap_leak(void)
464{
465 int count = 0;
466 int i;
467
468 for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
469 if (prev_map[i])
470 count++;
471
472 if (!count)
473 return 0;
474 WARN(1, KERN_WARNING
475 "Debug warning: early ioremap leak of %d areas detected.\n",
476 count);
477 printk(KERN_WARNING
478 "please boot with early_ioremap_debug and report the dmesg.\n");
479
480 return 1;
481}
482late_initcall(check_early_ioremap_leak);
483
484static void __init __iomem *
485__early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot)
486{
487 unsigned long offset;
488 resource_size_t last_addr;
489 unsigned int nrpages;
490 enum fixed_addresses idx;
491 int i, slot;
492
493 WARN_ON(system_state != SYSTEM_BOOTING);
494
495 slot = -1;
496 for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
497 if (!prev_map[i]) {
498 slot = i;
499 break;
500 }
501 }
502
503 if (slot < 0) {
504 printk(KERN_INFO "%s(%08llx, %08lx) not found slot\n",
505 __func__, (u64)phys_addr, size);
506 WARN_ON(1);
507 return NULL;
508 }
509
510 if (early_ioremap_debug) {
511 printk(KERN_INFO "%s(%08llx, %08lx) [%d] => ",
512 __func__, (u64)phys_addr, size, slot);
513 dump_stack();
514 }
515
516 /* Don't allow wraparound or zero size */
517 last_addr = phys_addr + size - 1;
518 if (!size || last_addr < phys_addr) {
519 WARN_ON(1);
520 return NULL;
521 }
522
523 prev_size[slot] = size;
524 /*
525 * Mappings have to be page-aligned
526 */
527 offset = phys_addr & ~PAGE_MASK;
528 phys_addr &= PAGE_MASK;
529 size = PAGE_ALIGN(last_addr + 1) - phys_addr;
530
531 /*
532 * Mappings have to fit in the FIX_BTMAP area.
533 */
534 nrpages = size >> PAGE_SHIFT;
535 if (nrpages > NR_FIX_BTMAPS) {
536 WARN_ON(1);
537 return NULL;
538 }
539
540 /*
541 * Ok, go for it..
542 */
543 idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
544 while (nrpages > 0) {
545 early_set_fixmap(idx, phys_addr, prot);
546 phys_addr += PAGE_SIZE;
547 --idx;
548 --nrpages;
549 }
550 if (early_ioremap_debug)
551 printk(KERN_CONT "%08lx + %08lx\n", offset, slot_virt[slot]);
552
553 prev_map[slot] = (void __iomem *)(offset + slot_virt[slot]);
554 return prev_map[slot];
555}
556
557/* Remap an IO device */
558void __init __iomem *
559early_ioremap(resource_size_t phys_addr, unsigned long size)
560{
561 return __early_ioremap(phys_addr, size, PAGE_KERNEL_IO);
562}
563
564/* Remap memory */
565void __init *early_memremap(resource_size_t phys_addr, unsigned long size)
566{
567 return (__force void *)__early_ioremap(phys_addr, size, PAGE_KERNEL);
568}
569
570void __init early_iounmap(void __iomem *addr, unsigned long size)
571{
572 unsigned long virt_addr;
573 unsigned long offset;
574 unsigned int nrpages;
575 enum fixed_addresses idx;
576 int i, slot;
577
578 slot = -1;
579 for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
580 if (prev_map[i] == addr) {
581 slot = i;
582 break;
583 }
584 }
585
586 if (slot < 0) {
587 printk(KERN_INFO "early_iounmap(%p, %08lx) not found slot\n",
588 addr, size);
589 WARN_ON(1);
590 return;
591 }
592
593 if (prev_size[slot] != size) {
594 printk(KERN_INFO "early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n",
595 addr, size, slot, prev_size[slot]);
596 WARN_ON(1);
597 return;
598 }
599
600 if (early_ioremap_debug) {
601 printk(KERN_INFO "early_iounmap(%p, %08lx) [%d]\n", addr,
602 size, slot);
603 dump_stack();
604 }
605
606 virt_addr = (unsigned long)addr;
607 if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN)) {
608 WARN_ON(1);
609 return;
610 }
611 offset = virt_addr & ~PAGE_MASK;
612 nrpages = PAGE_ALIGN(offset + size) >> PAGE_SHIFT;
613
614 idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
615 while (nrpages > 0) {
616 early_clear_fixmap(idx);
617 --idx;
618 --nrpages;
619 }
620 prev_map[slot] = NULL;
621}
622
623void __init early_memunmap(void *addr, unsigned long size)
624{
625 early_iounmap((__force void __iomem *)addr, size);
626}
diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c
index a69bcb8c7621..4dd8cf652579 100644
--- a/arch/x86/mm/pgtable_32.c
+++ b/arch/x86/mm/pgtable_32.c
@@ -127,7 +127,7 @@ static int __init parse_reservetop(char *arg)
127 127
128 address = memparse(arg, &arg); 128 address = memparse(arg, &arg);
129 reserve_top_address(address); 129 reserve_top_address(address);
130 fixup_early_ioremap(); 130 early_ioremap_init();
131 return 0; 131 return 0;
132} 132}
133early_param("reservetop", parse_reservetop); 133early_param("reservetop", parse_reservetop);