aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-powerpc/highmem.h
diff options
context:
space:
mode:
authorKumar Gala <galak@kernel.crashing.org>2008-04-23 09:05:20 -0400
committerPaul Mackerras <paulus@samba.org>2008-04-24 06:58:02 -0400
commit2c419bdeca1d958bb02228b5141695f312d8c633 (patch)
tree4553b9bf7b75025c5bbeb25528d97f5338673b0b /include/asm-powerpc/highmem.h
parent2fd53e02be9a73cc49d69e0ff8860daa7b5bf8ab (diff)
[POWERPC] Port fixmap from x86 and use for kmap_atomic
The fixmap code from x86 allows us to have compile time virtual addresses that we change the physical addresses of at run time. This is useful for applications like kmap_atomic, PCI config that is done via direct memory map, kexec/kdump. We got ride of CONFIG_HIGHMEM_START as we can now determine a more optimal location for PKMAP_BASE based on where the fixmap addresses start and working back from there. Additionally, the kmap code in asm-powerpc/highmem.h always had debug enabled. Moved to using CONFIG_DEBUG_HIGHMEM to determine if we should have the extra debug checking. Signed-off-by: Kumar Gala <galak@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'include/asm-powerpc/highmem.h')
-rw-r--r--include/asm-powerpc/highmem.h41
1 files changed, 22 insertions, 19 deletions
diff --git a/include/asm-powerpc/highmem.h b/include/asm-powerpc/highmem.h
index f7b21ee302b4..5d99b6489d56 100644
--- a/include/asm-powerpc/highmem.h
+++ b/include/asm-powerpc/highmem.h
@@ -27,9 +27,7 @@
27#include <asm/kmap_types.h> 27#include <asm/kmap_types.h>
28#include <asm/tlbflush.h> 28#include <asm/tlbflush.h>
29#include <asm/page.h> 29#include <asm/page.h>
30 30#include <asm/fixmap.h>
31/* undef for production */
32#define HIGHMEM_DEBUG 1
33 31
34extern pte_t *kmap_pte; 32extern pte_t *kmap_pte;
35extern pgprot_t kmap_prot; 33extern pgprot_t kmap_prot;
@@ -40,14 +38,12 @@ extern pte_t *pkmap_page_table;
40 * easily, subsequent pte tables have to be allocated in one physical 38 * easily, subsequent pte tables have to be allocated in one physical
41 * chunk of RAM. 39 * chunk of RAM.
42 */ 40 */
43#define PKMAP_BASE CONFIG_HIGHMEM_START
44#define LAST_PKMAP (1 << PTE_SHIFT) 41#define LAST_PKMAP (1 << PTE_SHIFT)
45#define LAST_PKMAP_MASK (LAST_PKMAP-1) 42#define LAST_PKMAP_MASK (LAST_PKMAP-1)
43#define PKMAP_BASE ((FIXADDR_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK)
46#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT) 44#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT)
47#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) 45#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
48 46
49#define KMAP_FIX_BEGIN (PKMAP_BASE + 0x00400000UL)
50
51extern void *kmap_high(struct page *page); 47extern void *kmap_high(struct page *page);
52extern void kunmap_high(struct page *page); 48extern void kunmap_high(struct page *page);
53 49
@@ -73,7 +69,7 @@ static inline void kunmap(struct page *page)
73 * be used in IRQ contexts, so in some (very limited) cases we need 69 * be used in IRQ contexts, so in some (very limited) cases we need
74 * it. 70 * it.
75 */ 71 */
76static inline void *kmap_atomic(struct page *page, enum km_type type) 72static inline void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
77{ 73{
78 unsigned int idx; 74 unsigned int idx;
79 unsigned long vaddr; 75 unsigned long vaddr;
@@ -84,34 +80,39 @@ static inline void *kmap_atomic(struct page *page, enum km_type type)
84 return page_address(page); 80 return page_address(page);
85 81
86 idx = type + KM_TYPE_NR*smp_processor_id(); 82 idx = type + KM_TYPE_NR*smp_processor_id();
87 vaddr = KMAP_FIX_BEGIN + idx * PAGE_SIZE; 83 vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
88#ifdef HIGHMEM_DEBUG 84#ifdef CONFIG_DEBUG_HIGHMEM
89 BUG_ON(!pte_none(*(kmap_pte+idx))); 85 BUG_ON(!pte_none(*(kmap_pte-idx)));
90#endif 86#endif
91 set_pte_at(&init_mm, vaddr, kmap_pte+idx, mk_pte(page, kmap_prot)); 87 set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
92 flush_tlb_page(NULL, vaddr); 88 flush_tlb_page(NULL, vaddr);
93 89
94 return (void*) vaddr; 90 return (void*) vaddr;
95} 91}
96 92
93static inline void *kmap_atomic(struct page *page, enum km_type type)
94{
95 return kmap_atomic_prot(page, type, kmap_prot);
96}
97
97static inline void kunmap_atomic(void *kvaddr, enum km_type type) 98static inline void kunmap_atomic(void *kvaddr, enum km_type type)
98{ 99{
99#ifdef HIGHMEM_DEBUG 100#ifdef CONFIG_DEBUG_HIGHMEM
100 unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; 101 unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
101 unsigned int idx = type + KM_TYPE_NR*smp_processor_id(); 102 enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
102 103
103 if (vaddr < KMAP_FIX_BEGIN) { // FIXME 104 if (vaddr < __fix_to_virt(FIX_KMAP_END)) {
104 pagefault_enable(); 105 pagefault_enable();
105 return; 106 return;
106 } 107 }
107 108
108 BUG_ON(vaddr != KMAP_FIX_BEGIN + idx * PAGE_SIZE); 109 BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
109 110
110 /* 111 /*
111 * force other mappings to Oops if they'll try to access 112 * force other mappings to Oops if they'll try to access
112 * this pte without first remap it 113 * this pte without first remap it
113 */ 114 */
114 pte_clear(&init_mm, vaddr, kmap_pte+idx); 115 pte_clear(&init_mm, vaddr, kmap_pte-idx);
115 flush_tlb_page(NULL, vaddr); 116 flush_tlb_page(NULL, vaddr);
116#endif 117#endif
117 pagefault_enable(); 118 pagefault_enable();
@@ -120,12 +121,14 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type)
120static inline struct page *kmap_atomic_to_page(void *ptr) 121static inline struct page *kmap_atomic_to_page(void *ptr)
121{ 122{
122 unsigned long idx, vaddr = (unsigned long) ptr; 123 unsigned long idx, vaddr = (unsigned long) ptr;
124 pte_t *pte;
123 125
124 if (vaddr < KMAP_FIX_BEGIN) 126 if (vaddr < FIXADDR_START)
125 return virt_to_page(ptr); 127 return virt_to_page(ptr);
126 128
127 idx = (vaddr - KMAP_FIX_BEGIN) >> PAGE_SHIFT; 129 idx = virt_to_fix(vaddr);
128 return pte_page(kmap_pte[idx]); 130 pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
131 return pte_page(*pte);
129} 132}
130 133
131#define flush_cache_kmaps() flush_cache_all() 134#define flush_cache_kmaps() flush_cache_all()