diff options
author | Mark Salter <msalter@redhat.com> | 2014-04-07 18:39:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-07 19:36:15 -0400 |
commit | 5b7c73e00968c7fdf908c3ced31e1cc83c01ba14 (patch) | |
tree | 5d733047855bc22d40e022ea27a11ba7b52b03e4 | |
parent | 9e5c33d7aeeef62e5fa7e74f94432685bd03026b (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/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/Kbuild | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/fixmap.h | 6 | ||||
-rw-r--r-- | arch/x86/include/asm/io.h | 15 | ||||
-rw-r--r-- | arch/x86/mm/ioremap.c | 228 | ||||
-rw-r--r-- | arch/x86/mm/pgtable_32.c | 2 |
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 | |||
5 | genhdr-y += unistd_x32.h | 5 | genhdr-y += unistd_x32.h |
6 | 6 | ||
7 | generic-y += clkdev.h | 7 | generic-y += clkdev.h |
8 | generic-y += early_ioremap.h | ||
8 | generic-y += cputime.h | 9 | generic-y += cputime.h |
9 | generic-y += mcs_spinlock.h | 10 | generic-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 | |||
169 | void __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) \ |
44 | static inline type name(const volatile void __iomem *addr) \ | 45 | static 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); |
317 | extern void __iomem *ioremap_wc(resource_size_t offset, unsigned long size); | 318 | extern 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 | */ | ||
324 | extern void early_ioremap_init(void); | ||
325 | extern void early_ioremap_reset(void); | ||
326 | extern void __iomem *early_ioremap(resource_size_t phys_addr, | ||
327 | unsigned long size); | ||
328 | extern void *early_memremap(resource_size_t phys_addr, | ||
329 | unsigned long size); | ||
330 | extern void early_iounmap(void __iomem *addr, unsigned long size); | ||
331 | extern void early_memunmap(void *addr, unsigned long size); | ||
332 | extern void fixup_early_ioremap(void); | ||
333 | extern bool is_early_ioremap_ptep(pte_t *ptep); | 320 | extern 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 | ||
331 | static int __initdata early_ioremap_debug; | ||
332 | |||
333 | static int __init early_ioremap_debug_setup(char *str) | ||
334 | { | ||
335 | early_ioremap_debug = 1; | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | early_param("early_ioremap_debug", early_ioremap_debug_setup); | ||
340 | |||
341 | static __initdata int after_paging_init; | ||
342 | static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss; | 331 | static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss; |
343 | 332 | ||
344 | static inline pmd_t * __init early_ioremap_pmd(unsigned long addr) | 333 | static 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 | ||
365 | static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata; | ||
366 | |||
367 | void __init early_ioremap_init(void) | 354 | void __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 | ||
405 | void __init early_ioremap_reset(void) | 387 | void __init __early_set_fixmap(enum fixed_addresses idx, |
406 | { | 388 | phys_addr_t phys, pgprot_t flags) |
407 | after_paging_init = 1; | ||
408 | } | ||
409 | |||
410 | static 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 | |||
429 | static 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 | |||
438 | static 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 | |||
446 | static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata; | ||
447 | static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata; | ||
448 | |||
449 | void __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 | |||
463 | static 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 | } | ||
482 | late_initcall(check_early_ioremap_leak); | ||
483 | |||
484 | static 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 */ | ||
558 | void __init __iomem * | ||
559 | early_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 */ | ||
565 | void __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 | |||
570 | void __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 | |||
623 | void __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 | } |
133 | early_param("reservetop", parse_reservetop); | 133 | early_param("reservetop", parse_reservetop); |