1#include <linux/module.h> 2#include <linux/highmem.h> 3#include <linux/sched.h> 4#include <linux/smp.h> 5#include <asm/fixmap.h> 6#include <asm/tlbflush.h> 7 8static pte_t *kmap_pte; 9 10unsigned long highstart_pfn, highend_pfn; 11 12void *kmap(struct page *page) 13{ 14 void *addr; 15 16 might_sleep(); 17 if (!PageHighMem(page)) 18 return page_address(page); 19 addr = kmap_high(page); 20 flush_tlb_one((unsigned long)addr); 21 22 return addr; 23} 24EXPORT_SYMBOL(kmap); 25 26void kunmap(struct page *page) 27{ 28 BUG_ON(in_interrupt()); 29 if (!PageHighMem(page)) 30 return; 31 kunmap_high(page); 32} 33EXPORT_SYMBOL(kunmap); 34 35/* 36 * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because 37 * no global lock is needed and because the kmap code must perform a global TLB 38 * invalidation when the kmap pool wraps. 39 * 40 * However when holding an atomic kmap is is not legal to sleep, so atomic 41 * kmaps are appropriate for short, tight code paths only. 42 */ 43 44void *kmap_atomic(struct page *page) 45{ 46 unsigned long vaddr; 47 int idx, type; 48 49 /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ 50 pagefault_disable(); 51 if (!PageHighMem(page)) 52 return page_address(page); 53 54 type = kmap_atomic_idx_push(); 55 idx = type + KM_TYPE_NR*smp_processor_id(); 56 vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); 57#ifdef CONFIG_DEBUG_HIGHMEM 58 BUG_ON(!pte_none(*(kmap_pte - idx))); 59#endif 60 set_pte(kmap_pte-idx, mk_pte(page, PAGE_KERNEL)); 61 local_flush_tlb_one((unsigned long)vaddr); 62 63 return (void*) vaddr; 64} 65EXPORT_SYMBOL(kmap_atomic); 66 67void __kunmap_atomic(void *kvaddr) 68{ 69 unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; 70 int type; 71 72 if (vaddr < FIXADDR_START) { // FIXME 73 pagefault_enable(); 74 return; 75 } 76 77 type = kmap_atomic_idx(); 78#ifdef CONFIG_DEBUG_HIGHMEM 79 { 80 int idx = type + KM_TYPE_NR * smp_processor_id(); 81 82 BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); 83 84 /* 85 * force other mappings to Oops if they'll try to access 86 * this pte without first remap it 87 */ 88 pte_clear(&init_mm, vaddr, kmap_pte-idx); 89 local_flush_tlb_one(vaddr); 90 } 91#endif 92 kmap_atomic_idx_pop(); 93 pagefault_enable(); 94} 95EXPORT_SYMBOL(__kunmap_atomic); 96 97/* 98 * This is the same as kmap_atomic() but can map memory that doesn't 99 * have a struct page associated with it. 100 */ 101void *kmap_atomic_pfn(unsigned long pfn) 102{ 103 unsigned long vaddr; 104 int idx, type; 105 106 pagefault_disable(); 107 108 type = kmap_atomic_idx_push(); 109 idx = type + KM_TYPE_NR*smp_processor_id(); 110 vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); 111 set_pte(kmap_pte-idx, pfn_pte(pfn, PAGE_KERNEL)); 112 flush_tlb_one(vaddr); 113 114 return (void*) vaddr; 115} 116 117struct page *kmap_atomic_to_page(void *ptr) 118{ 119 unsigned long idx, vaddr = (unsigned long)ptr; 120 pte_t *pte; 121 122 if (vaddr < FIXADDR_START) 123 return virt_to_page(ptr); 124 125 idx = virt_to_fix(vaddr); 126 pte = kmap_pte - (idx - FIX_KMAP_BEGIN); 127 return pte_page(*pte); 128} 129 130void __init kmap_init(void) 131{ 132 unsigned long kmap_vstart; 133 134 /* cache the first kmap pte */ 135 kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); 136 kmap_pte = kmap_get_fixmap_pte(kmap_vstart); 137} 138