1 /* 2 * linux/arch/arm/mm/nommu.c 3 * 4 * ARM uCLinux supporting functions. 5 */ 6 #include <linux/module.h> 7 #include <linux/mm.h> 8 #include <linux/pagemap.h> 9 #include <linux/io.h> 10 #include <linux/memblock.h> 11 #include <linux/kernel.h> 12 13 #include <asm/cacheflush.h> 14 #include <asm/cp15.h> 15 #include <asm/sections.h> 16 #include <asm/page.h> 17 #include <asm/setup.h> 18 #include <asm/traps.h> 19 #include <asm/mach/arch.h> 20 #include <asm/cputype.h> 21 #include <asm/mpu.h> 22 #include <asm/procinfo.h> 23 24 #include "mm.h" 25 26 unsigned long vectors_base; 27 28 #ifdef CONFIG_ARM_MPU 29 struct mpu_rgn_info mpu_rgn_info; 30 #endif 31 32 #ifdef CONFIG_CPU_CP15 33 #ifdef CONFIG_CPU_HIGH_VECTOR 34 static unsigned long __init setup_vectors_base(void) 35 { 36 unsigned long reg = get_cr(); 37 38 set_cr(reg | CR_V); 39 return 0xffff0000; 40 } 41 #else /* CONFIG_CPU_HIGH_VECTOR */ 42 /* Write exception base address to VBAR */ 43 static inline void set_vbar(unsigned long val) 44 { 45 asm("mcr p15, 0, %0, c12, c0, 0" : : "r" (val) : "cc"); 46 } 47 48 /* 49 * Security extensions, bits[7:4], permitted values, 50 * 0b0000 - not implemented, 0b0001/0b0010 - implemented 51 */ 52 static inline bool security_extensions_enabled(void) 53 { 54 /* Check CPUID Identification Scheme before ID_PFR1 read */ 55 if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) 56 return !!cpuid_feature_extract(CPUID_EXT_PFR1, 4); 57 return 0; 58 } 59 60 static unsigned long __init setup_vectors_base(void) 61 { 62 unsigned long base = 0, reg = get_cr(); 63 64 set_cr(reg & ~CR_V); 65 if (security_extensions_enabled()) { 66 if (IS_ENABLED(CONFIG_REMAP_VECTORS_TO_RAM)) 67 base = CONFIG_DRAM_BASE; 68 set_vbar(base); 69 } else if (IS_ENABLED(CONFIG_REMAP_VECTORS_TO_RAM)) { 70 if (CONFIG_DRAM_BASE != 0) 71 pr_err("Security extensions not enabled, vectors cannot be remapped to RAM, vectors base will be 0x00000000\n"); 72 } 73 74 return base; 75 } 76 #endif /* CONFIG_CPU_HIGH_VECTOR */ 77 #endif /* CONFIG_CPU_CP15 */ 78 79 void __init arm_mm_memblock_reserve(void) 80 { 81 #ifndef CONFIG_CPU_V7M 82 vectors_base = IS_ENABLED(CONFIG_CPU_CP15) ? setup_vectors_base() : 0; 83 /* 84 * Register the exception vector page. 85 * some architectures which the DRAM is the exception vector to trap, 86 * alloc_page breaks with error, although it is not NULL, but "0." 87 */ 88 memblock_reserve(vectors_base, 2 * PAGE_SIZE); 89 #else /* ifndef CONFIG_CPU_V7M */ 90 /* 91 * There is no dedicated vector page on V7-M. So nothing needs to be 92 * reserved here. 93 */ 94 #endif 95 /* 96 * In any case, always ensure address 0 is never used as many things 97 * get very confused if 0 is returned as a legitimate address. 98 */ 99 memblock_reserve(0, 1); 100 } 101 102 void __init adjust_lowmem_bounds(void) 103 { 104 phys_addr_t end; 105 adjust_lowmem_bounds_mpu(); 106 end = memblock_end_of_DRAM(); 107 high_memory = __va(end - 1) + 1; 108 memblock_set_current_limit(end); 109 } 110 111 /* 112 * paging_init() sets up the page tables, initialises the zone memory 113 * maps, and sets up the zero page, bad page and bad page tables. 114 */ 115 void __init paging_init(const struct machine_desc *mdesc) 116 { 117 early_trap_init((void *)vectors_base); 118 mpu_setup(); 119 bootmem_init(); 120 } 121 122 /* 123 * We don't need to do anything here for nommu machines. 124 */ 125 void setup_mm_for_reboot(void) 126 { 127 } 128 129 void flush_dcache_page(struct page *page) 130 { 131 __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE); 132 } 133 EXPORT_SYMBOL(flush_dcache_page); 134 135 void flush_kernel_dcache_page(struct page *page) 136 { 137 __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE); 138 } 139 EXPORT_SYMBOL(flush_kernel_dcache_page); 140 141 void copy_to_user_page(struct vm_area_struct *vma, struct page *page, 142 unsigned long uaddr, void *dst, const void *src, 143 unsigned long len) 144 { 145 memcpy(dst, src, len); 146 if (vma->vm_flags & VM_EXEC) 147 __cpuc_coherent_user_range(uaddr, uaddr + len); 148 } 149 150 void __iomem *__arm_ioremap_pfn(unsigned long pfn, unsigned long offset, 151 size_t size, unsigned int mtype) 152 { 153 if (pfn >= (0x100000000ULL >> PAGE_SHIFT)) 154 return NULL; 155 return (void __iomem *) (offset + (pfn << PAGE_SHIFT)); 156 } 157 EXPORT_SYMBOL(__arm_ioremap_pfn); 158 159 void __iomem *__arm_ioremap_caller(phys_addr_t phys_addr, size_t size, 160 unsigned int mtype, void *caller) 161 { 162 return (void __iomem *)phys_addr; 163 } 164 165 void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *); 166 167 void __iomem *ioremap(resource_size_t res_cookie, size_t size) 168 { 169 return __arm_ioremap_caller(res_cookie, size, MT_DEVICE, 170 __builtin_return_address(0)); 171 } 172 EXPORT_SYMBOL(ioremap); 173 174 void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size) 175 __alias(ioremap_cached); 176 177 void __iomem *ioremap_cached(resource_size_t res_cookie, size_t size) 178 { 179 return __arm_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED, 180 __builtin_return_address(0)); 181 } 182 EXPORT_SYMBOL(ioremap_cache); 183 EXPORT_SYMBOL(ioremap_cached); 184 185 void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size) 186 { 187 return __arm_ioremap_caller(res_cookie, size, MT_DEVICE_WC, 188 __builtin_return_address(0)); 189 } 190 EXPORT_SYMBOL(ioremap_wc); 191 192 #ifdef CONFIG_PCI 193 194 #include <asm/mach/map.h> 195 196 void __iomem *pci_remap_cfgspace(resource_size_t res_cookie, size_t size) 197 { 198 return arch_ioremap_caller(res_cookie, size, MT_UNCACHED, 199 __builtin_return_address(0)); 200 } 201 EXPORT_SYMBOL_GPL(pci_remap_cfgspace); 202 #endif 203 204 void *arch_memremap_wb(phys_addr_t phys_addr, size_t size) 205 { 206 return (void *)phys_addr; 207 } 208 209 void __iounmap(volatile void __iomem *addr) 210 { 211 } 212 EXPORT_SYMBOL(__iounmap); 213 214 void (*arch_iounmap)(volatile void __iomem *); 215 216 void iounmap(volatile void __iomem *addr) 217 { 218 } 219 EXPORT_SYMBOL(iounmap); 220