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