12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- // SPDX-License-Identifier: GPL-2.0
- #include <linux/compiler.h>
- #include <linux/init.h>
- #include <linux/export.h>
- #include <linux/highmem.h>
- #include <linux/sched.h>
- #include <linux/smp.h>
- #include <asm/fixmap.h>
- #include <asm/tlbflush.h>
- static pte_t *kmap_pte;
- unsigned long highstart_pfn, highend_pfn;
- void kmap_flush_tlb(unsigned long addr)
- {
- flush_tlb_one(addr);
- }
- EXPORT_SYMBOL(kmap_flush_tlb);
- void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
- {
- unsigned long vaddr;
- int idx, type;
- type = kmap_atomic_idx_push();
- idx = type + KM_TYPE_NR*smp_processor_id();
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- #ifdef CONFIG_DEBUG_HIGHMEM
- BUG_ON(!pte_none(*(kmap_pte - idx)));
- #endif
- set_pte(kmap_pte-idx, mk_pte(page, prot));
- local_flush_tlb_one((unsigned long)vaddr);
- return (void*) vaddr;
- }
- EXPORT_SYMBOL(kmap_atomic_high_prot);
- void kunmap_atomic_high(void *kvaddr)
- {
- unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
- int type __maybe_unused;
- if (vaddr < FIXADDR_START)
- return;
- type = kmap_atomic_idx();
- #ifdef CONFIG_DEBUG_HIGHMEM
- {
- int idx = type + KM_TYPE_NR * smp_processor_id();
- BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
- /*
- * force other mappings to Oops if they'll try to access
- * this pte without first remap it
- */
- pte_clear(&init_mm, vaddr, kmap_pte-idx);
- local_flush_tlb_one(vaddr);
- }
- #endif
- kmap_atomic_idx_pop();
- }
- EXPORT_SYMBOL(kunmap_atomic_high);
- /*
- * This is the same as kmap_atomic() but can map memory that doesn't
- * have a struct page associated with it.
- */
- void *kmap_atomic_pfn(unsigned long pfn)
- {
- unsigned long vaddr;
- int idx, type;
- preempt_disable();
- pagefault_disable();
- type = kmap_atomic_idx_push();
- idx = type + KM_TYPE_NR*smp_processor_id();
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- set_pte(kmap_pte-idx, pfn_pte(pfn, PAGE_KERNEL));
- flush_tlb_one(vaddr);
- return (void*) vaddr;
- }
- void __init kmap_init(void)
- {
- unsigned long kmap_vstart;
- /* cache the first kmap pte */
- kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
- kmap_pte = virt_to_kpte(kmap_vstart);
- }
|