aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/mmiotrace/kmmio.c
diff options
context:
space:
mode:
authorPekka Paalanen <pq@iki.fi>2008-05-12 15:20:56 -0400
committerThomas Gleixner <tglx@linutronix.de>2008-05-24 05:21:32 -0400
commit75bb88350e0501b3cf5ac096a1008757844414a9 (patch)
tree13b836138e77455fa0f188a01c0a10b641ddc266 /arch/x86/kernel/mmiotrace/kmmio.c
parent8b7d89d02ef3c6a7c73d6596f28cea7632850af4 (diff)
x86 mmiotrace: use lookup_address()
Use lookup_address() from pageattr.c instead of doing the same manually. Also had to EXPORT_SYMBOL_GPL(lookup_address) to make this work for modules. This also fixes "undefined symbol 'init_mm'" compile error for x86_32. Signed-off-by: Pekka Paalanen <pq@iki.fi> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/mmiotrace/kmmio.c')
-rw-r--r--arch/x86/kernel/mmiotrace/kmmio.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/arch/x86/kernel/mmiotrace/kmmio.c b/arch/x86/kernel/mmiotrace/kmmio.c
index 8ba48f9c91b4..28411dadb8b3 100644
--- a/arch/x86/kernel/mmiotrace/kmmio.c
+++ b/arch/x86/kernel/mmiotrace/kmmio.c
@@ -20,6 +20,7 @@
20#include <asm/cacheflush.h> 20#include <asm/cacheflush.h>
21#include <asm/errno.h> 21#include <asm/errno.h>
22#include <asm/tlbflush.h> 22#include <asm/tlbflush.h>
23#include <asm/pgtable.h>
23 24
24#include "kmmio.h" 25#include "kmmio.h"
25 26
@@ -117,40 +118,55 @@ static struct kmmio_fault_page *get_kmmio_fault_page(unsigned long page)
117 return NULL; 118 return NULL;
118} 119}
119 120
120static void arm_kmmio_fault_page(unsigned long page, int *large) 121static void arm_kmmio_fault_page(unsigned long page, int *page_level)
121{ 122{
122 unsigned long address = page & PAGE_MASK; 123 unsigned long address = page & PAGE_MASK;
123 pgd_t *pgd = pgd_offset_k(address); 124 int level;
124 pud_t *pud = pud_offset(pgd, address); 125 pte_t *pte = lookup_address(address, &level);
125 pmd_t *pmd = pmd_offset(pud, address);
126 pte_t *pte = pte_offset_kernel(pmd, address);
127 126
128 if (pmd_large(*pmd)) { 127 if (!pte) {
128 printk(KERN_ERR "Error in %s: no pte for page 0x%08lx\n",
129 __FUNCTION__, page);
130 return;
131 }
132
133 if (level == PG_LEVEL_2M) {
134 pmd_t *pmd = (pmd_t *)pte;
129 set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_PRESENT)); 135 set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_PRESENT));
130 if (large)
131 *large = 1;
132 } else { 136 } else {
137 /* PG_LEVEL_4K */
133 set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_PRESENT)); 138 set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_PRESENT));
134 } 139 }
135 140
141 if (page_level)
142 *page_level = level;
143
136 __flush_tlb_one(page); 144 __flush_tlb_one(page);
137} 145}
138 146
139static void disarm_kmmio_fault_page(unsigned long page, int *large) 147static void disarm_kmmio_fault_page(unsigned long page, int *page_level)
140{ 148{
141 unsigned long address = page & PAGE_MASK; 149 unsigned long address = page & PAGE_MASK;
142 pgd_t *pgd = pgd_offset_k(address); 150 int level;
143 pud_t *pud = pud_offset(pgd, address); 151 pte_t *pte = lookup_address(address, &level);
144 pmd_t *pmd = pmd_offset(pud, address);
145 pte_t *pte = pte_offset_kernel(pmd, address);
146 152
147 if (large && *large) { 153 if (!pte) {
154 printk(KERN_ERR "Error in %s: no pte for page 0x%08lx\n",
155 __FUNCTION__, page);
156 return;
157 }
158
159 if (level == PG_LEVEL_2M) {
160 pmd_t *pmd = (pmd_t *)pte;
148 set_pmd(pmd, __pmd(pmd_val(*pmd) | _PAGE_PRESENT)); 161 set_pmd(pmd, __pmd(pmd_val(*pmd) | _PAGE_PRESENT));
149 *large = 0;
150 } else { 162 } else {
163 /* PG_LEVEL_4K */
151 set_pte(pte, __pte(pte_val(*pte) | _PAGE_PRESENT)); 164 set_pte(pte, __pte(pte_val(*pte) | _PAGE_PRESENT));
152 } 165 }
153 166
167 if (page_level)
168 *page_level = level;
169
154 __flush_tlb_one(page); 170 __flush_tlb_one(page);
155} 171}
156 172