1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (C) 2005-2017 Andes Technology Corporation 3 4 #include <linux/export.h> 5 #include <linux/highmem.h> 6 #include <linux/sched.h> 7 #include <linux/smp.h> 8 #include <linux/interrupt.h> 9 #include <linux/memblock.h> 10 #include <asm/fixmap.h> 11 #include <asm/tlbflush.h> 12 kmap(struct page * page)13void *kmap(struct page *page) 14 { 15 unsigned long vaddr; 16 might_sleep(); 17 if (!PageHighMem(page)) 18 return page_address(page); 19 vaddr = (unsigned long)kmap_high(page); 20 return (void *)vaddr; 21 } 22 23 EXPORT_SYMBOL(kmap); 24 kunmap(struct page * page)25void kunmap(struct page *page) 26 { 27 BUG_ON(in_interrupt()); 28 if (!PageHighMem(page)) 29 return; 30 kunmap_high(page); 31 } 32 33 EXPORT_SYMBOL(kunmap); 34 kmap_atomic(struct page * page)35void *kmap_atomic(struct page *page) 36 { 37 unsigned int idx; 38 unsigned long vaddr, pte; 39 int type; 40 pte_t *ptep; 41 42 preempt_disable(); 43 pagefault_disable(); 44 if (!PageHighMem(page)) 45 return page_address(page); 46 47 type = kmap_atomic_idx_push(); 48 49 idx = type + KM_TYPE_NR * smp_processor_id(); 50 vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); 51 pte = (page_to_pfn(page) << PAGE_SHIFT) | (PAGE_KERNEL); 52 ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr); 53 set_pte(ptep, pte); 54 55 __nds32__tlbop_inv(vaddr); 56 __nds32__mtsr_dsb(vaddr, NDS32_SR_TLB_VPN); 57 __nds32__tlbop_rwr(pte); 58 __nds32__isb(); 59 return (void *)vaddr; 60 } 61 62 EXPORT_SYMBOL(kmap_atomic); 63 __kunmap_atomic(void * kvaddr)64void __kunmap_atomic(void *kvaddr) 65 { 66 if (kvaddr >= (void *)FIXADDR_START) { 67 unsigned long vaddr = (unsigned long)kvaddr; 68 pte_t *ptep; 69 kmap_atomic_idx_pop(); 70 __nds32__tlbop_inv(vaddr); 71 __nds32__isb(); 72 ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr); 73 set_pte(ptep, 0); 74 } 75 pagefault_enable(); 76 preempt_enable(); 77 } 78 79 EXPORT_SYMBOL(__kunmap_atomic); 80