1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/arch/m68k/mm/kmap.c 4 * 5 * Copyright (C) 1997 Roman Hodek 6 * 7 * 10/01/99 cleaned up the code and changing to the same interface 8 * used by other architectures /Roman Zippel 9 */ 10 11 #include <linux/module.h> 12 #include <linux/mm.h> 13 #include <linux/kernel.h> 14 #include <linux/string.h> 15 #include <linux/types.h> 16 #include <linux/slab.h> 17 #include <linux/vmalloc.h> 18 19 #include <asm/setup.h> 20 #include <asm/segment.h> 21 #include <asm/page.h> 22 #include <asm/pgalloc.h> 23 #include <asm/io.h> 24 25 #undef DEBUG 26 27 /* 28 * For 040/060 we can use the virtual memory area like other architectures, 29 * but for 020/030 we want to use early termination page descriptors and we 30 * can't mix this with normal page descriptors, so we have to copy that code 31 * (mm/vmalloc.c) and return appropriately aligned addresses. 32 */ 33 34 #ifdef CPU_M68040_OR_M68060_ONLY 35 36 #define IO_SIZE PAGE_SIZE 37 38 static inline struct vm_struct *get_io_area(unsigned long size) 39 { 40 return get_vm_area(size, VM_IOREMAP); 41 } 42 43 44 static inline void free_io_area(void *addr) 45 { 46 vfree((void *)(PAGE_MASK & (unsigned long)addr)); 47 } 48 49 #else 50 51 #define IO_SIZE PMD_SIZE 52 53 static struct vm_struct *iolist; 54 55 /* 56 * __free_io_area unmaps nearly everything, so be careful 57 * Currently it doesn't free pointer/page tables anymore but this 58 * wasn't used anyway and might be added later. 59 */ 60 static void __free_io_area(void *addr, unsigned long size) 61 { 62 unsigned long virtaddr = (unsigned long)addr; 63 pgd_t *pgd_dir; 64 p4d_t *p4d_dir; 65 pud_t *pud_dir; 66 pmd_t *pmd_dir; 67 pte_t *pte_dir; 68 69 while ((long)size > 0) { 70 pgd_dir = pgd_offset_k(virtaddr); 71 p4d_dir = p4d_offset(pgd_dir, virtaddr); 72 pud_dir = pud_offset(p4d_dir, virtaddr); 73 if (pud_bad(*pud_dir)) { 74 printk("iounmap: bad pud(%08lx)\n", pud_val(*pud_dir)); 75 pud_clear(pud_dir); 76 return; 77 } 78 pmd_dir = pmd_offset(pud_dir, virtaddr); 79 80 #if CONFIG_PGTABLE_LEVELS == 3 81 if (CPU_IS_020_OR_030) { 82 int pmd_type = pmd_val(*pmd_dir) & _DESCTYPE_MASK; 83 84 if (pmd_type == _PAGE_PRESENT) { 85 pmd_clear(pmd_dir); 86 virtaddr += PMD_SIZE; 87 size -= PMD_SIZE; 88 89 } else if (pmd_type == 0) 90 continue; 91 } 92 #endif 93 94 if (pmd_bad(*pmd_dir)) { 95 printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir)); 96 pmd_clear(pmd_dir); 97 return; 98 } 99 pte_dir = pte_offset_kernel(pmd_dir, virtaddr); 100 101 pte_val(*pte_dir) = 0; 102 virtaddr += PAGE_SIZE; 103 size -= PAGE_SIZE; 104 } 105 106 flush_tlb_all(); 107 } 108 109 static struct vm_struct *get_io_area(unsigned long size) 110 { 111 unsigned long addr; 112 struct vm_struct **p, *tmp, *area; 113 114 area = kmalloc(sizeof(*area), GFP_KERNEL); 115 if (!area) 116 return NULL; 117 addr = KMAP_START; 118 for (p = &iolist; (tmp = *p) ; p = &tmp->next) { 119 if (size + addr < (unsigned long)tmp->addr) 120 break; 121 if (addr > KMAP_END-size) { 122 kfree(area); 123 return NULL; 124 } 125 addr = tmp->size + (unsigned long)tmp->addr; 126 } 127 area->addr = (void *)addr; 128 area->size = size + IO_SIZE; 129 area->next = *p; 130 *p = area; 131 return area; 132 } 133 134 static inline void free_io_area(void *addr) 135 { 136 struct vm_struct **p, *tmp; 137 138 if (!addr) 139 return; 140 addr = (void *)((unsigned long)addr & -IO_SIZE); 141 for (p = &iolist ; (tmp = *p) ; p = &tmp->next) { 142 if (tmp->addr == addr) { 143 *p = tmp->next; 144 /* remove gap added in get_io_area() */ 145 __free_io_area(tmp->addr, tmp->size - IO_SIZE); 146 kfree(tmp); 147 return; 148 } 149 } 150 } 151 152 #endif 153 154 /* 155 * Map some physical address range into the kernel address space. 156 */ 157 /* Rewritten by Andreas Schwab to remove all races. */ 158 159 void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) 160 { 161 struct vm_struct *area; 162 unsigned long virtaddr, retaddr; 163 long offset; 164 pgd_t *pgd_dir; 165 p4d_t *p4d_dir; 166 pud_t *pud_dir; 167 pmd_t *pmd_dir; 168 pte_t *pte_dir; 169 170 /* 171 * Don't allow mappings that wrap.. 172 */ 173 if (!size || physaddr > (unsigned long)(-size)) 174 return NULL; 175 176 #ifdef CONFIG_AMIGA 177 if (MACH_IS_AMIGA) { 178 if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000) 179 && (cacheflag == IOMAP_NOCACHE_SER)) 180 return (void __iomem *)physaddr; 181 } 182 #endif 183 #ifdef CONFIG_COLDFIRE 184 if (__cf_internalio(physaddr)) 185 return (void __iomem *) physaddr; 186 #endif 187 188 #ifdef DEBUG 189 printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag); 190 #endif 191 /* 192 * Mappings have to be aligned 193 */ 194 offset = physaddr & (IO_SIZE - 1); 195 physaddr &= -IO_SIZE; 196 size = (size + offset + IO_SIZE - 1) & -IO_SIZE; 197 198 /* 199 * Ok, go for it.. 200 */ 201 area = get_io_area(size); 202 if (!area) 203 return NULL; 204 205 virtaddr = (unsigned long)area->addr; 206 retaddr = virtaddr + offset; 207 #ifdef DEBUG 208 printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr); 209 #endif 210 211 /* 212 * add cache and table flags to physical address 213 */ 214 if (CPU_IS_040_OR_060) { 215 physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 | 216 _PAGE_ACCESSED | _PAGE_DIRTY); 217 switch (cacheflag) { 218 case IOMAP_FULL_CACHING: 219 physaddr |= _PAGE_CACHE040; 220 break; 221 case IOMAP_NOCACHE_SER: 222 default: 223 physaddr |= _PAGE_NOCACHE_S; 224 break; 225 case IOMAP_NOCACHE_NONSER: 226 physaddr |= _PAGE_NOCACHE; 227 break; 228 case IOMAP_WRITETHROUGH: 229 physaddr |= _PAGE_CACHE040W; 230 break; 231 } 232 } else { 233 physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | 234 _PAGE_DIRTY | _PAGE_READWRITE); 235 switch (cacheflag) { 236 case IOMAP_NOCACHE_SER: 237 case IOMAP_NOCACHE_NONSER: 238 default: 239 physaddr |= _PAGE_NOCACHE030; 240 break; 241 case IOMAP_FULL_CACHING: 242 case IOMAP_WRITETHROUGH: 243 break; 244 } 245 } 246 247 while ((long)size > 0) { 248 #ifdef DEBUG 249 if (!(virtaddr & (PMD_SIZE-1))) 250 printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr); 251 #endif 252 pgd_dir = pgd_offset_k(virtaddr); 253 p4d_dir = p4d_offset(pgd_dir, virtaddr); 254 pud_dir = pud_offset(p4d_dir, virtaddr); 255 pmd_dir = pmd_alloc(&init_mm, pud_dir, virtaddr); 256 if (!pmd_dir) { 257 printk("ioremap: no mem for pmd_dir\n"); 258 return NULL; 259 } 260 261 #if CONFIG_PGTABLE_LEVELS == 3 262 if (CPU_IS_020_OR_030) { 263 pmd_val(*pmd_dir) = physaddr; 264 physaddr += PMD_SIZE; 265 virtaddr += PMD_SIZE; 266 size -= PMD_SIZE; 267 } else 268 #endif 269 { 270 pte_dir = pte_alloc_kernel(pmd_dir, virtaddr); 271 if (!pte_dir) { 272 printk("ioremap: no mem for pte_dir\n"); 273 return NULL; 274 } 275 276 pte_val(*pte_dir) = physaddr; 277 virtaddr += PAGE_SIZE; 278 physaddr += PAGE_SIZE; 279 size -= PAGE_SIZE; 280 } 281 } 282 #ifdef DEBUG 283 printk("\n"); 284 #endif 285 flush_tlb_all(); 286 287 return (void __iomem *)retaddr; 288 } 289 EXPORT_SYMBOL(__ioremap); 290 291 /* 292 * Unmap an ioremap()ed region again 293 */ 294 void iounmap(void __iomem *addr) 295 { 296 #ifdef CONFIG_AMIGA 297 if ((!MACH_IS_AMIGA) || 298 (((unsigned long)addr < 0x40000000) || 299 ((unsigned long)addr > 0x60000000))) 300 free_io_area((__force void *)addr); 301 #else 302 #ifdef CONFIG_COLDFIRE 303 if (cf_internalio(addr)) 304 return; 305 #endif 306 free_io_area((__force void *)addr); 307 #endif 308 } 309 EXPORT_SYMBOL(iounmap); 310 311 /* 312 * Set new cache mode for some kernel address space. 313 * The caller must push data for that range itself, if such data may already 314 * be in the cache. 315 */ 316 void kernel_set_cachemode(void *addr, unsigned long size, int cmode) 317 { 318 unsigned long virtaddr = (unsigned long)addr; 319 pgd_t *pgd_dir; 320 p4d_t *p4d_dir; 321 pud_t *pud_dir; 322 pmd_t *pmd_dir; 323 pte_t *pte_dir; 324 325 if (CPU_IS_040_OR_060) { 326 switch (cmode) { 327 case IOMAP_FULL_CACHING: 328 cmode = _PAGE_CACHE040; 329 break; 330 case IOMAP_NOCACHE_SER: 331 default: 332 cmode = _PAGE_NOCACHE_S; 333 break; 334 case IOMAP_NOCACHE_NONSER: 335 cmode = _PAGE_NOCACHE; 336 break; 337 case IOMAP_WRITETHROUGH: 338 cmode = _PAGE_CACHE040W; 339 break; 340 } 341 } else { 342 switch (cmode) { 343 case IOMAP_NOCACHE_SER: 344 case IOMAP_NOCACHE_NONSER: 345 default: 346 cmode = _PAGE_NOCACHE030; 347 break; 348 case IOMAP_FULL_CACHING: 349 case IOMAP_WRITETHROUGH: 350 cmode = 0; 351 } 352 } 353 354 while ((long)size > 0) { 355 pgd_dir = pgd_offset_k(virtaddr); 356 p4d_dir = p4d_offset(pgd_dir, virtaddr); 357 pud_dir = pud_offset(p4d_dir, virtaddr); 358 if (pud_bad(*pud_dir)) { 359 printk("iocachemode: bad pud(%08lx)\n", pud_val(*pud_dir)); 360 pud_clear(pud_dir); 361 return; 362 } 363 pmd_dir = pmd_offset(pud_dir, virtaddr); 364 365 #if CONFIG_PGTABLE_LEVELS == 3 366 if (CPU_IS_020_OR_030) { 367 unsigned long pmd = pmd_val(*pmd_dir); 368 369 if ((pmd & _DESCTYPE_MASK) == _PAGE_PRESENT) { 370 *pmd_dir = __pmd((pmd & _CACHEMASK040) | cmode); 371 virtaddr += PMD_SIZE; 372 size -= PMD_SIZE; 373 continue; 374 } 375 } 376 #endif 377 378 if (pmd_bad(*pmd_dir)) { 379 printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir)); 380 pmd_clear(pmd_dir); 381 return; 382 } 383 pte_dir = pte_offset_kernel(pmd_dir, virtaddr); 384 385 pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode; 386 virtaddr += PAGE_SIZE; 387 size -= PAGE_SIZE; 388 } 389 390 flush_tlb_all(); 391 } 392 EXPORT_SYMBOL(kernel_set_cachemode); 393