| 1 | /* |
|---|
| 2 | * arch/i386/mm/ioremap.c |
|---|
| 3 | * |
|---|
| 4 | * Re-map IO memory to kernel address space so that we can access it. |
|---|
| 5 | * This is needed for high PCI addresses that aren't mapped in the |
|---|
| 6 | * 640k-1MB IO memory area on PC's |
|---|
| 7 | * |
|---|
| 8 | * (C) Copyright 1995 1996 Linus Torvalds |
|---|
| 9 | */ |
|---|
| 10 | |
|---|
| 11 | #include <linux/vmalloc.h> |
|---|
| 12 | #include <linux/init.h> |
|---|
| 13 | #include <linux/slab.h> |
|---|
| 14 | #include <linux/module.h> |
|---|
| 15 | #include <asm/io.h> |
|---|
| 16 | #include <asm/fixmap.h> |
|---|
| 17 | #include <asm/cacheflush.h> |
|---|
| 18 | #include <asm/tlbflush.h> |
|---|
| 19 | #include <asm/pgtable.h> |
|---|
| 20 | #include <asm/pgalloc.h> |
|---|
| 21 | |
|---|
| 22 | #define ISA_START_ADDRESS 0x0 |
|---|
| 23 | #define ISA_END_ADDRESS 0x100000 |
|---|
| 24 | |
|---|
| 25 | static int direct_remap_area_pte_fn(pte_t *pte, |
|---|
| 26 | struct page *pmd_page, |
|---|
| 27 | unsigned long address, |
|---|
| 28 | void *data) |
|---|
| 29 | { |
|---|
| 30 | mmu_update_t **v = (mmu_update_t **)data; |
|---|
| 31 | |
|---|
| 32 | BUG_ON(!pte_none(*pte)); |
|---|
| 33 | |
|---|
| 34 | (*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pmd_page)) << |
|---|
| 35 | PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK); |
|---|
| 36 | (*v)++; |
|---|
| 37 | |
|---|
| 38 | return 0; |
|---|
| 39 | } |
|---|
| 40 | |
|---|
| 41 | static int __direct_remap_pfn_range(struct mm_struct *mm, |
|---|
| 42 | unsigned long address, |
|---|
| 43 | unsigned long mfn, |
|---|
| 44 | unsigned long size, |
|---|
| 45 | pgprot_t prot, |
|---|
| 46 | domid_t domid) |
|---|
| 47 | { |
|---|
| 48 | int rc; |
|---|
| 49 | unsigned long i, start_address; |
|---|
| 50 | mmu_update_t *u, *v, *w; |
|---|
| 51 | |
|---|
| 52 | u = v = w = (mmu_update_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT); |
|---|
| 53 | if (u == NULL) |
|---|
| 54 | return -ENOMEM; |
|---|
| 55 | |
|---|
| 56 | start_address = address; |
|---|
| 57 | |
|---|
| 58 | flush_cache_all(); |
|---|
| 59 | |
|---|
| 60 | for (i = 0; i < size; i += PAGE_SIZE) { |
|---|
| 61 | if ((v - u) == (PAGE_SIZE / sizeof(mmu_update_t))) { |
|---|
| 62 | /* Flush a full batch after filling in the PTE ptrs. */ |
|---|
| 63 | rc = apply_to_page_range(mm, start_address, |
|---|
| 64 | address - start_address, |
|---|
| 65 | direct_remap_area_pte_fn, &w); |
|---|
| 66 | if (rc) |
|---|
| 67 | goto out; |
|---|
| 68 | rc = -EFAULT; |
|---|
| 69 | if (HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0) |
|---|
| 70 | goto out; |
|---|
| 71 | v = w = u; |
|---|
| 72 | start_address = address; |
|---|
| 73 | } |
|---|
| 74 | |
|---|
| 75 | /* |
|---|
| 76 | * Fill in the machine address: PTE ptr is done later by |
|---|
| 77 | * __direct_remap_area_pages(). |
|---|
| 78 | */ |
|---|
| 79 | v->val = pte_val_ma(pfn_pte_ma(mfn, prot)); |
|---|
| 80 | |
|---|
| 81 | mfn++; |
|---|
| 82 | address += PAGE_SIZE; |
|---|
| 83 | v++; |
|---|
| 84 | } |
|---|
| 85 | |
|---|
| 86 | if (v != u) { |
|---|
| 87 | /* Final batch. */ |
|---|
| 88 | rc = apply_to_page_range(mm, start_address, |
|---|
| 89 | address - start_address, |
|---|
| 90 | direct_remap_area_pte_fn, &w); |
|---|
| 91 | if (rc) |
|---|
| 92 | goto out; |
|---|
| 93 | rc = -EFAULT; |
|---|
| 94 | if (unlikely(HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0)) |
|---|
| 95 | goto out; |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | rc = 0; |
|---|
| 99 | |
|---|
| 100 | out: |
|---|
| 101 | flush_tlb_all(); |
|---|
| 102 | |
|---|
| 103 | free_page((unsigned long)u); |
|---|
| 104 | |
|---|
| 105 | return rc; |
|---|
| 106 | } |
|---|
| 107 | |
|---|
| 108 | int direct_remap_pfn_range(struct vm_area_struct *vma, |
|---|
| 109 | unsigned long address, |
|---|
| 110 | unsigned long mfn, |
|---|
| 111 | unsigned long size, |
|---|
| 112 | pgprot_t prot, |
|---|
| 113 | domid_t domid) |
|---|
| 114 | { |
|---|
| 115 | if (xen_feature(XENFEAT_auto_translated_physmap)) |
|---|
| 116 | return remap_pfn_range(vma, address, mfn, size, prot); |
|---|
| 117 | |
|---|
| 118 | if (domid == DOMID_SELF) |
|---|
| 119 | return -EINVAL; |
|---|
| 120 | |
|---|
| 121 | vma->vm_flags |= VM_IO | VM_RESERVED; |
|---|
| 122 | |
|---|
| 123 | vma->vm_mm->context.has_foreign_mappings = 1; |
|---|
| 124 | |
|---|
| 125 | return __direct_remap_pfn_range( |
|---|
| 126 | vma->vm_mm, address, mfn, size, prot, domid); |
|---|
| 127 | } |
|---|
| 128 | EXPORT_SYMBOL(direct_remap_pfn_range); |
|---|
| 129 | |
|---|
| 130 | int direct_kernel_remap_pfn_range(unsigned long address, |
|---|
| 131 | unsigned long mfn, |
|---|
| 132 | unsigned long size, |
|---|
| 133 | pgprot_t prot, |
|---|
| 134 | domid_t domid) |
|---|
| 135 | { |
|---|
| 136 | return __direct_remap_pfn_range( |
|---|
| 137 | &init_mm, address, mfn, size, prot, domid); |
|---|
| 138 | } |
|---|
| 139 | EXPORT_SYMBOL(direct_kernel_remap_pfn_range); |
|---|
| 140 | |
|---|
| 141 | static int lookup_pte_fn( |
|---|
| 142 | pte_t *pte, struct page *pmd_page, unsigned long addr, void *data) |
|---|
| 143 | { |
|---|
| 144 | uint64_t *ptep = (uint64_t *)data; |
|---|
| 145 | if (ptep) |
|---|
| 146 | *ptep = ((uint64_t)pfn_to_mfn(page_to_pfn(pmd_page)) << |
|---|
| 147 | PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK); |
|---|
| 148 | return 0; |
|---|
| 149 | } |
|---|
| 150 | |
|---|
| 151 | int create_lookup_pte_addr(struct mm_struct *mm, |
|---|
| 152 | unsigned long address, |
|---|
| 153 | uint64_t *ptep) |
|---|
| 154 | { |
|---|
| 155 | return apply_to_page_range(mm, address, PAGE_SIZE, |
|---|
| 156 | lookup_pte_fn, ptep); |
|---|
| 157 | } |
|---|
| 158 | |
|---|
| 159 | EXPORT_SYMBOL(create_lookup_pte_addr); |
|---|
| 160 | |
|---|
| 161 | static int noop_fn( |
|---|
| 162 | pte_t *pte, struct page *pmd_page, unsigned long addr, void *data) |
|---|
| 163 | { |
|---|
| 164 | return 0; |
|---|
| 165 | } |
|---|
| 166 | |
|---|
| 167 | int touch_pte_range(struct mm_struct *mm, |
|---|
| 168 | unsigned long address, |
|---|
| 169 | unsigned long size) |
|---|
| 170 | { |
|---|
| 171 | return apply_to_page_range(mm, address, size, noop_fn, NULL); |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | EXPORT_SYMBOL(touch_pte_range); |
|---|
| 175 | |
|---|
| 176 | /* |
|---|
| 177 | * Does @address reside within a non-highmem page that is local to this virtual |
|---|
| 178 | * machine (i.e., not an I/O page, nor a memory page belonging to another VM). |
|---|
| 179 | * See the comment that accompanies mfn_to_local_pfn() in page.h to understand |
|---|
| 180 | * why this works. |
|---|
| 181 | */ |
|---|
| 182 | static inline int is_local_lowmem(unsigned long address) |
|---|
| 183 | { |
|---|
| 184 | extern unsigned long max_low_pfn; |
|---|
| 185 | return (mfn_to_local_pfn(address >> PAGE_SHIFT) < max_low_pfn); |
|---|
| 186 | } |
|---|
| 187 | |
|---|
| 188 | /* |
|---|
| 189 | * Generic mapping function (not visible outside): |
|---|
| 190 | */ |
|---|
| 191 | |
|---|
| 192 | /* |
|---|
| 193 | * Remap an arbitrary physical address space into the kernel virtual |
|---|
| 194 | * address space. Needed when the kernel wants to access high addresses |
|---|
| 195 | * directly. |
|---|
| 196 | * |
|---|
| 197 | * NOTE! We need to allow non-page-aligned mappings too: we will obviously |
|---|
| 198 | * have to convert them into an offset in a page-aligned mapping, but the |
|---|
| 199 | * caller shouldn't need to know that small detail. |
|---|
| 200 | */ |
|---|
| 201 | void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) |
|---|
| 202 | { |
|---|
| 203 | void __iomem * addr; |
|---|
| 204 | struct vm_struct * area; |
|---|
| 205 | unsigned long offset, last_addr; |
|---|
| 206 | domid_t domid = DOMID_IO; |
|---|
| 207 | |
|---|
| 208 | /* Don't allow wraparound or zero size */ |
|---|
| 209 | last_addr = phys_addr + size - 1; |
|---|
| 210 | if (!size || last_addr < phys_addr) |
|---|
| 211 | return NULL; |
|---|
| 212 | |
|---|
| 213 | /* |
|---|
| 214 | * Don't remap the low PCI/ISA area, it's always mapped.. |
|---|
| 215 | */ |
|---|
| 216 | if (is_initial_xendomain() && |
|---|
| 217 | phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS) |
|---|
| 218 | return (void __iomem *) isa_bus_to_virt(phys_addr); |
|---|
| 219 | |
|---|
| 220 | /* |
|---|
| 221 | * Don't allow anybody to remap normal RAM that we're using.. |
|---|
| 222 | */ |
|---|
| 223 | if (is_local_lowmem(phys_addr)) { |
|---|
| 224 | char *t_addr, *t_end; |
|---|
| 225 | struct page *page; |
|---|
| 226 | |
|---|
| 227 | t_addr = bus_to_virt(phys_addr); |
|---|
| 228 | t_end = t_addr + (size - 1); |
|---|
| 229 | |
|---|
| 230 | for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) |
|---|
| 231 | if(!PageReserved(page)) |
|---|
| 232 | return NULL; |
|---|
| 233 | |
|---|
| 234 | domid = DOMID_SELF; |
|---|
| 235 | } |
|---|
| 236 | |
|---|
| 237 | /* |
|---|
| 238 | * Mappings have to be page-aligned |
|---|
| 239 | */ |
|---|
| 240 | offset = phys_addr & ~PAGE_MASK; |
|---|
| 241 | phys_addr &= PAGE_MASK; |
|---|
| 242 | size = PAGE_ALIGN(last_addr+1) - phys_addr; |
|---|
| 243 | |
|---|
| 244 | /* |
|---|
| 245 | * Ok, go for it.. |
|---|
| 246 | */ |
|---|
| 247 | area = get_vm_area(size, VM_IOREMAP | (flags << 20)); |
|---|
| 248 | if (!area) |
|---|
| 249 | return NULL; |
|---|
| 250 | area->phys_addr = phys_addr; |
|---|
| 251 | addr = (void __iomem *) area->addr; |
|---|
| 252 | flags |= _KERNPG_TABLE; |
|---|
| 253 | if (__direct_remap_pfn_range(&init_mm, (unsigned long)addr, |
|---|
| 254 | phys_addr>>PAGE_SHIFT, |
|---|
| 255 | size, __pgprot(flags), domid)) { |
|---|
| 256 | vunmap((void __force *) addr); |
|---|
| 257 | return NULL; |
|---|
| 258 | } |
|---|
| 259 | return (void __iomem *) (offset + (char __iomem *)addr); |
|---|
| 260 | } |
|---|
| 261 | EXPORT_SYMBOL(__ioremap); |
|---|
| 262 | |
|---|
| 263 | /** |
|---|
| 264 | * ioremap_nocache - map bus memory into CPU space |
|---|
| 265 | * @offset: bus address of the memory |
|---|
| 266 | * @size: size of the resource to map |
|---|
| 267 | * |
|---|
| 268 | * ioremap_nocache performs a platform specific sequence of operations to |
|---|
| 269 | * make bus memory CPU accessible via the readb/readw/readl/writeb/ |
|---|
| 270 | * writew/writel functions and the other mmio helpers. The returned |
|---|
| 271 | * address is not guaranteed to be usable directly as a virtual |
|---|
| 272 | * address. |
|---|
| 273 | * |
|---|
| 274 | * This version of ioremap ensures that the memory is marked uncachable |
|---|
| 275 | * on the CPU as well as honouring existing caching rules from things like |
|---|
| 276 | * the PCI bus. Note that there are other caches and buffers on many |
|---|
| 277 | * busses. In particular driver authors should read up on PCI writes |
|---|
| 278 | * |
|---|
| 279 | * It's useful if some control registers are in such an area and |
|---|
| 280 | * write combining or read caching is not desirable: |
|---|
| 281 | * |
|---|
| 282 | * Must be freed with iounmap. |
|---|
| 283 | */ |
|---|
| 284 | |
|---|
| 285 | void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size) |
|---|
| 286 | { |
|---|
| 287 | unsigned long last_addr; |
|---|
| 288 | void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD); |
|---|
| 289 | if (!p) |
|---|
| 290 | return p; |
|---|
| 291 | |
|---|
| 292 | /* Guaranteed to be > phys_addr, as per __ioremap() */ |
|---|
| 293 | last_addr = phys_addr + size - 1; |
|---|
| 294 | |
|---|
| 295 | if (is_local_lowmem(last_addr)) { |
|---|
| 296 | struct page *ppage = virt_to_page(bus_to_virt(phys_addr)); |
|---|
| 297 | unsigned long npages; |
|---|
| 298 | |
|---|
| 299 | phys_addr &= PAGE_MASK; |
|---|
| 300 | |
|---|
| 301 | /* This might overflow and become zero.. */ |
|---|
| 302 | last_addr = PAGE_ALIGN(last_addr); |
|---|
| 303 | |
|---|
| 304 | /* .. but that's ok, because modulo-2**n arithmetic will make |
|---|
| 305 | * the page-aligned "last - first" come out right. |
|---|
| 306 | */ |
|---|
| 307 | npages = (last_addr - phys_addr) >> PAGE_SHIFT; |
|---|
| 308 | |
|---|
| 309 | if (change_page_attr(ppage, npages, PAGE_KERNEL_NOCACHE) < 0) { |
|---|
| 310 | iounmap(p); |
|---|
| 311 | p = NULL; |
|---|
| 312 | } |
|---|
| 313 | global_flush_tlb(); |
|---|
| 314 | } |
|---|
| 315 | |
|---|
| 316 | return p; |
|---|
| 317 | } |
|---|
| 318 | EXPORT_SYMBOL(ioremap_nocache); |
|---|
| 319 | |
|---|
| 320 | /** |
|---|
| 321 | * iounmap - Free a IO remapping |
|---|
| 322 | * @addr: virtual address from ioremap_* |
|---|
| 323 | * |
|---|
| 324 | * Caller must ensure there is only one unmapping for the same pointer. |
|---|
| 325 | */ |
|---|
| 326 | void iounmap(volatile void __iomem *addr) |
|---|
| 327 | { |
|---|
| 328 | struct vm_struct *p, *o; |
|---|
| 329 | |
|---|
| 330 | if ((void __force *)addr <= high_memory) |
|---|
| 331 | return; |
|---|
| 332 | |
|---|
| 333 | /* |
|---|
| 334 | * __ioremap special-cases the PCI/ISA range by not instantiating a |
|---|
| 335 | * vm_area and by simply returning an address into the kernel mapping |
|---|
| 336 | * of ISA space. So handle that here. |
|---|
| 337 | */ |
|---|
| 338 | if ((unsigned long) addr >= fix_to_virt(FIX_ISAMAP_BEGIN)) |
|---|
| 339 | return; |
|---|
| 340 | |
|---|
| 341 | addr = (volatile void __iomem *)(PAGE_MASK & (unsigned long __force)addr); |
|---|
| 342 | |
|---|
| 343 | /* Use the vm area unlocked, assuming the caller |
|---|
| 344 | ensures there isn't another iounmap for the same address |
|---|
| 345 | in parallel. Reuse of the virtual address is prevented by |
|---|
| 346 | leaving it in the global lists until we're done with it. |
|---|
| 347 | cpa takes care of the direct mappings. */ |
|---|
| 348 | read_lock(&vmlist_lock); |
|---|
| 349 | for (p = vmlist; p; p = p->next) { |
|---|
| 350 | if (p->addr == addr) |
|---|
| 351 | break; |
|---|
| 352 | } |
|---|
| 353 | read_unlock(&vmlist_lock); |
|---|
| 354 | |
|---|
| 355 | if (!p) { |
|---|
| 356 | printk("iounmap: bad address %p\n", addr); |
|---|
| 357 | dump_stack(); |
|---|
| 358 | return; |
|---|
| 359 | } |
|---|
| 360 | |
|---|
| 361 | /* Reset the direct mapping. Can block */ |
|---|
| 362 | if ((p->flags >> 20) && is_local_lowmem(p->phys_addr)) { |
|---|
| 363 | /* p->size includes the guard page, but cpa doesn't like that */ |
|---|
| 364 | change_page_attr(virt_to_page(bus_to_virt(p->phys_addr)), |
|---|
| 365 | (p->size - PAGE_SIZE) >> PAGE_SHIFT, |
|---|
| 366 | PAGE_KERNEL); |
|---|
| 367 | global_flush_tlb(); |
|---|
| 368 | } |
|---|
| 369 | |
|---|
| 370 | /* Finally remove it */ |
|---|
| 371 | o = remove_vm_area((void *)addr); |
|---|
| 372 | BUG_ON(p != o || o == NULL); |
|---|
| 373 | kfree(p); |
|---|
| 374 | } |
|---|
| 375 | EXPORT_SYMBOL(iounmap); |
|---|
| 376 | |
|---|
| 377 | void __init *bt_ioremap(unsigned long phys_addr, unsigned long size) |
|---|
| 378 | { |
|---|
| 379 | unsigned long offset, last_addr; |
|---|
| 380 | unsigned int nrpages; |
|---|
| 381 | enum fixed_addresses idx; |
|---|
| 382 | |
|---|
| 383 | /* Don't allow wraparound or zero size */ |
|---|
| 384 | last_addr = phys_addr + size - 1; |
|---|
| 385 | if (!size || last_addr < phys_addr) |
|---|
| 386 | return NULL; |
|---|
| 387 | |
|---|
| 388 | /* |
|---|
| 389 | * Don't remap the low PCI/ISA area, it's always mapped.. |
|---|
| 390 | */ |
|---|
| 391 | if (is_initial_xendomain() && |
|---|
| 392 | phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS) |
|---|
| 393 | return isa_bus_to_virt(phys_addr); |
|---|
| 394 | |
|---|
| 395 | /* |
|---|
| 396 | * Mappings have to be page-aligned |
|---|
| 397 | */ |
|---|
| 398 | offset = phys_addr & ~PAGE_MASK; |
|---|
| 399 | phys_addr &= PAGE_MASK; |
|---|
| 400 | size = PAGE_ALIGN(last_addr) - phys_addr; |
|---|
| 401 | |
|---|
| 402 | /* |
|---|
| 403 | * Mappings have to fit in the FIX_BTMAP area. |
|---|
| 404 | */ |
|---|
| 405 | nrpages = size >> PAGE_SHIFT; |
|---|
| 406 | if (nrpages > NR_FIX_BTMAPS) |
|---|
| 407 | return NULL; |
|---|
| 408 | |
|---|
| 409 | /* |
|---|
| 410 | * Ok, go for it.. |
|---|
| 411 | */ |
|---|
| 412 | idx = FIX_BTMAP_BEGIN; |
|---|
| 413 | while (nrpages > 0) { |
|---|
| 414 | set_fixmap(idx, phys_addr); |
|---|
| 415 | phys_addr += PAGE_SIZE; |
|---|
| 416 | --idx; |
|---|
| 417 | --nrpages; |
|---|
| 418 | } |
|---|
| 419 | return (void*) (offset + fix_to_virt(FIX_BTMAP_BEGIN)); |
|---|
| 420 | } |
|---|
| 421 | |
|---|
| 422 | void __init bt_iounmap(void *addr, unsigned long size) |
|---|
| 423 | { |
|---|
| 424 | unsigned long virt_addr; |
|---|
| 425 | unsigned long offset; |
|---|
| 426 | unsigned int nrpages; |
|---|
| 427 | enum fixed_addresses idx; |
|---|
| 428 | |
|---|
| 429 | virt_addr = (unsigned long)addr; |
|---|
| 430 | if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN)) |
|---|
| 431 | return; |
|---|
| 432 | if (virt_addr >= fix_to_virt(FIX_ISAMAP_BEGIN)) |
|---|
| 433 | return; |
|---|
| 434 | offset = virt_addr & ~PAGE_MASK; |
|---|
| 435 | nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT; |
|---|
| 436 | |
|---|
| 437 | idx = FIX_BTMAP_BEGIN; |
|---|
| 438 | while (nrpages > 0) { |
|---|
| 439 | clear_fixmap(idx); |
|---|
| 440 | --idx; |
|---|
| 441 | --nrpages; |
|---|
| 442 | } |
|---|
| 443 | } |
|---|