This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / include / asm-i386 / atomic_kmap.h
1 /*
2  * atomic_kmap.h: temporary virtual kernel memory mappings
3  *
4  * Copyright (C) 2003 Ingo Molnar <mingo@redhat.com>
5  */
6
7 #ifndef _ASM_ATOMIC_KMAP_H
8 #define _ASM_ATOMIC_KMAP_H
9
10 #ifdef __KERNEL__
11
12 #include <linux/config.h>
13 #include <asm/tlbflush.h>
14
15 #ifdef CONFIG_DEBUG_HIGHMEM
16 #define HIGHMEM_DEBUG 1
17 #else
18 #define HIGHMEM_DEBUG 0
19 #endif
20
21 extern pte_t *kmap_pte;
22 #define kmap_prot PAGE_KERNEL
23 #define kmap_prot_nocache PAGE_KERNEL_NOCACHE
24
25 #define PKMAP_BASE (0xff000000UL)
26 #define NR_SHARED_PMDS ((0xffffffff-PKMAP_BASE+1)/PMD_SIZE)
27
28 static inline unsigned long __kmap_atomic_vaddr(enum km_type type)
29 {
30         enum fixed_addresses idx;
31
32         idx = type + KM_TYPE_NR*smp_processor_id();
33         return __fix_to_virt(FIX_KMAP_BEGIN + idx);
34 }
35
36 static inline void *__kmap_atomic_noflush(struct page *page, enum km_type type)
37 {
38         enum fixed_addresses idx;
39         unsigned long vaddr;
40
41         idx = type + KM_TYPE_NR*smp_processor_id();
42         vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
43         /*
44          * NOTE: entries that rely on some secondary TLB-flush
45          * effect must not be global:
46          */
47         set_pte(kmap_pte-idx, mk_pte(page, PAGE_KERNEL));
48
49         return (void*) vaddr;
50 }
51
52 static inline void *__kmap_atomic(struct page *page, enum km_type type)
53 {
54         enum fixed_addresses idx;
55         unsigned long vaddr;
56
57         idx = type + KM_TYPE_NR*smp_processor_id();
58         vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
59 #if HIGHMEM_DEBUG
60         BUG_ON(!pte_none(*(kmap_pte-idx)));
61 #else
62         /*
63          * Performance optimization - do not flush if the new
64          * pte is the same as the old one:
65          */
66         if (pte_val(*(kmap_pte-idx)) == pte_val(mk_pte(page, kmap_prot)))
67                 return (void *) vaddr;
68 #endif
69         set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
70         __flush_tlb_one(vaddr);
71
72         return (void*) vaddr;
73 }
74
75 static inline void __kunmap_atomic(void *kvaddr, enum km_type type)
76 {
77 #if HIGHMEM_DEBUG
78         unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
79         enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
80
81         BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx));
82         /*
83          * force other mappings to Oops if they'll try to access
84          * this pte without first remap it
85          */
86         pte_clear(kmap_pte-idx);
87         __flush_tlb_one(vaddr);
88 #endif
89 }
90
91 #define __kunmap_atomic_type(type) \
92                 __kunmap_atomic((void *)__kmap_atomic_vaddr(type), (type))
93
94 #endif /* __KERNEL__ */
95
96 #endif /* _ASM_ATOMIC_KMAP_H */