2 * Re-map IO memory to kernel address space so that we can access it.
3 * This is needed for high PCI addresses that aren't mapped in the
4 * 640k-1MB IO memory area on PC's
6 * (C) Copyright 1995 1996 Linus Torvalds
8 #include <linux/vmalloc.h>
10 #include <linux/sched.h>
12 #include <linux/export.h>
13 #include <asm/cacheflush.h>
14 #include <asm/pgtable.h>
16 #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
17 static int __read_mostly ioremap_p4d_capable
;
18 static int __read_mostly ioremap_pud_capable
;
19 static int __read_mostly ioremap_pmd_capable
;
20 static int __read_mostly ioremap_huge_disabled
;
22 static int __init
set_nohugeiomap(char *str
)
24 ioremap_huge_disabled
= 1;
27 early_param("nohugeiomap", set_nohugeiomap
);
29 void __init
ioremap_huge_init(void)
31 if (!ioremap_huge_disabled
) {
32 if (arch_ioremap_pud_supported())
33 ioremap_pud_capable
= 1;
34 if (arch_ioremap_pmd_supported())
35 ioremap_pmd_capable
= 1;
39 static inline int ioremap_p4d_enabled(void)
41 return ioremap_p4d_capable
;
44 static inline int ioremap_pud_enabled(void)
46 return ioremap_pud_capable
;
49 static inline int ioremap_pmd_enabled(void)
51 return ioremap_pmd_capable
;
54 #else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
55 static inline int ioremap_p4d_enabled(void) { return 0; }
56 static inline int ioremap_pud_enabled(void) { return 0; }
57 static inline int ioremap_pmd_enabled(void) { return 0; }
58 #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
60 static int ioremap_pte_range(pmd_t
*pmd
, unsigned long addr
,
61 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
66 pfn
= phys_addr
>> PAGE_SHIFT
;
67 pte
= pte_alloc_kernel(pmd
, addr
);
71 BUG_ON(!pte_none(*pte
));
72 set_pte_at(&init_mm
, addr
, pte
, pfn_pte(pfn
, prot
));
74 } while (pte
++, addr
+= PAGE_SIZE
, addr
!= end
);
78 static inline int ioremap_pmd_range(pud_t
*pud
, unsigned long addr
,
79 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
85 pmd
= pmd_alloc(&init_mm
, pud
, addr
);
89 next
= pmd_addr_end(addr
, end
);
91 if (ioremap_pmd_enabled() &&
92 ((next
- addr
) == PMD_SIZE
) &&
93 IS_ALIGNED(phys_addr
+ addr
, PMD_SIZE
)) {
94 if (pmd_set_huge(pmd
, phys_addr
+ addr
, prot
))
98 if (ioremap_pte_range(pmd
, addr
, next
, phys_addr
+ addr
, prot
))
100 } while (pmd
++, addr
= next
, addr
!= end
);
104 static inline int ioremap_pud_range(p4d_t
*p4d
, unsigned long addr
,
105 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
111 pud
= pud_alloc(&init_mm
, p4d
, addr
);
115 next
= pud_addr_end(addr
, end
);
117 if (ioremap_pud_enabled() &&
118 ((next
- addr
) == PUD_SIZE
) &&
119 IS_ALIGNED(phys_addr
+ addr
, PUD_SIZE
)) {
120 if (pud_set_huge(pud
, phys_addr
+ addr
, prot
))
124 if (ioremap_pmd_range(pud
, addr
, next
, phys_addr
+ addr
, prot
))
126 } while (pud
++, addr
= next
, addr
!= end
);
130 static inline int ioremap_p4d_range(pgd_t
*pgd
, unsigned long addr
,
131 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
137 p4d
= p4d_alloc(&init_mm
, pgd
, addr
);
141 next
= p4d_addr_end(addr
, end
);
143 if (ioremap_p4d_enabled() &&
144 ((next
- addr
) == P4D_SIZE
) &&
145 IS_ALIGNED(phys_addr
+ addr
, P4D_SIZE
)) {
146 if (p4d_set_huge(p4d
, phys_addr
+ addr
, prot
))
150 if (ioremap_pud_range(p4d
, addr
, next
, phys_addr
+ addr
, prot
))
152 } while (p4d
++, addr
= next
, addr
!= end
);
156 int ioremap_page_range(unsigned long addr
,
157 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
168 pgd
= pgd_offset_k(addr
);
170 next
= pgd_addr_end(addr
, end
);
171 err
= ioremap_p4d_range(pgd
, addr
, next
, phys_addr
+addr
, prot
);
174 } while (pgd
++, addr
= next
, addr
!= end
);
176 flush_cache_vmap(start
, end
);