highmem.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * highmem.c: virtual kernel memory mappings for high memory
  4. *
  5. * Provides kernel-static versions of atomic kmap functions originally
  6. * found as inlines in include/asm-sparc/highmem.h. These became
  7. * needed as kmap_atomic() and kunmap_atomic() started getting
  8. * called from within modules.
  9. * -- Tomas Szepe <szepe@pinerecords.com>, September 2002
  10. *
  11. * But kmap_atomic() and kunmap_atomic() cannot be inlined in
  12. * modules because they are loaded with btfixup-ped functions.
  13. */
  14. /*
  15. * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
  16. * gives a more generic (and caching) interface. But kmap_atomic can
  17. * be used in IRQ contexts, so in some (very limited) cases we need it.
  18. *
  19. * XXX This is an old text. Actually, it's good to use atomic kmaps,
  20. * provided you remember that they are atomic and not try to sleep
  21. * with a kmap taken, much like a spinlock. Non-atomic kmaps are
  22. * shared by CPUs, and so precious, and establishing them requires IPI.
  23. * Atomic kmaps are lightweight and we may have NCPUS more of them.
  24. */
  25. #include <linux/highmem.h>
  26. #include <linux/export.h>
  27. #include <linux/mm.h>
  28. #include <asm/cacheflush.h>
  29. #include <asm/tlbflush.h>
  30. #include <asm/vaddrs.h>
  31. static pte_t *kmap_pte;
  32. void __init kmap_init(void)
  33. {
  34. unsigned long address = __fix_to_virt(FIX_KMAP_BEGIN);
  35. /* cache the first kmap pte */
  36. kmap_pte = virt_to_kpte(address);
  37. }
  38. void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
  39. {
  40. unsigned long vaddr;
  41. long idx, type;
  42. type = kmap_atomic_idx_push();
  43. idx = type + KM_TYPE_NR*smp_processor_id();
  44. vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
  45. /* XXX Fix - Anton */
  46. #if 0
  47. __flush_cache_one(vaddr);
  48. #else
  49. flush_cache_all();
  50. #endif
  51. #ifdef CONFIG_DEBUG_HIGHMEM
  52. BUG_ON(!pte_none(*(kmap_pte-idx)));
  53. #endif
  54. set_pte(kmap_pte-idx, mk_pte(page, prot));
  55. /* XXX Fix - Anton */
  56. #if 0
  57. __flush_tlb_one(vaddr);
  58. #else
  59. flush_tlb_all();
  60. #endif
  61. return (void*) vaddr;
  62. }
  63. EXPORT_SYMBOL(kmap_atomic_high_prot);
  64. void kunmap_atomic_high(void *kvaddr)
  65. {
  66. unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
  67. int type;
  68. if (vaddr < FIXADDR_START)
  69. return;
  70. type = kmap_atomic_idx();
  71. #ifdef CONFIG_DEBUG_HIGHMEM
  72. {
  73. unsigned long idx;
  74. idx = type + KM_TYPE_NR * smp_processor_id();
  75. BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx));
  76. /* XXX Fix - Anton */
  77. #if 0
  78. __flush_cache_one(vaddr);
  79. #else
  80. flush_cache_all();
  81. #endif
  82. /*
  83. * force other mappings to Oops if they'll try to access
  84. * this pte without first remap it
  85. */
  86. pte_clear(&init_mm, vaddr, kmap_pte-idx);
  87. /* XXX Fix - Anton */
  88. #if 0
  89. __flush_tlb_one(vaddr);
  90. #else
  91. flush_tlb_all();
  92. #endif
  93. }
  94. #endif
  95. kmap_atomic_idx_pop();
  96. }
  97. EXPORT_SYMBOL(kunmap_atomic_high);