aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStuart Bennett <stuart@freedesktop.org>2009-01-30 12:38:59 -0500
committerIngo Molnar <mingo@elte.hu>2009-03-02 04:20:35 -0500
commite9d54cae8f03e7f963a12f44bd50d68f49b9ea36 (patch)
treebe77d162ae2179f604de9cc6fbc5ab5c9d89b3fe
parent5ff93697fcfe1e2b9e61db82961d8f50d1ad5d57 (diff)
x86 mmiotrace: WARN_ONCE if dis/arming a page fails
Print a full warning once, if arming or disarming a page fails. Also, if initial arming fails, do not handle the page further. This avoids the possibility of a page failing to arm and then later claiming to have handled any fault on that page. WARN_ONCE added by Pekka Paalanen. Signed-off-by: Stuart Bennett <stuart@freedesktop.org> Signed-off-by: Pekka Paalanen <pq@iki.fi> Cc: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/mm/kmmio.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c
index 93d82038af4b..fb1f11546fcd 100644
--- a/arch/x86/mm/kmmio.c
+++ b/arch/x86/mm/kmmio.c
@@ -105,7 +105,7 @@ static struct kmmio_fault_page *get_kmmio_fault_page(unsigned long page)
105 return NULL; 105 return NULL;
106} 106}
107 107
108static void set_page_present(unsigned long addr, bool present, 108static int set_page_present(unsigned long addr, bool present,
109 unsigned int *pglevel) 109 unsigned int *pglevel)
110{ 110{
111 pteval_t pteval; 111 pteval_t pteval;
@@ -116,7 +116,7 @@ static void set_page_present(unsigned long addr, bool present,
116 116
117 if (!pte) { 117 if (!pte) {
118 pr_err("kmmio: no pte for page 0x%08lx\n", addr); 118 pr_err("kmmio: no pte for page 0x%08lx\n", addr);
119 return; 119 return -1;
120 } 120 }
121 121
122 if (pglevel) 122 if (pglevel)
@@ -140,22 +140,27 @@ static void set_page_present(unsigned long addr, bool present,
140 140
141 default: 141 default:
142 pr_err("kmmio: unexpected page level 0x%x.\n", level); 142 pr_err("kmmio: unexpected page level 0x%x.\n", level);
143 return; 143 return -1;
144 } 144 }
145 145
146 __flush_tlb_one(addr); 146 __flush_tlb_one(addr);
147
148 return 0;
147} 149}
148 150
149/** Mark the given page as not present. Access to it will trigger a fault. */ 151/** Mark the given page as not present. Access to it will trigger a fault. */
150static void arm_kmmio_fault_page(unsigned long page, unsigned int *pglevel) 152static int arm_kmmio_fault_page(unsigned long page, unsigned int *pglevel)
151{ 153{
152 set_page_present(page & PAGE_MASK, false, pglevel); 154 int ret = set_page_present(page & PAGE_MASK, false, pglevel);
155 WARN_ONCE(ret < 0, KERN_ERR "kmmio arming 0x%08lx failed.\n", page);
156 return ret;
153} 157}
154 158
155/** Mark the given page as present. */ 159/** Mark the given page as present. */
156static void disarm_kmmio_fault_page(unsigned long page, unsigned int *pglevel) 160static void disarm_kmmio_fault_page(unsigned long page, unsigned int *pglevel)
157{ 161{
158 set_page_present(page & PAGE_MASK, true, pglevel); 162 int ret = set_page_present(page & PAGE_MASK, true, pglevel);
163 WARN_ONCE(ret < 0, KERN_ERR "kmmio disarming 0x%08lx failed.\n", page);
159} 164}
160 165
161/* 166/*
@@ -326,9 +331,13 @@ static int add_kmmio_fault_page(unsigned long page)
326 331
327 f->count = 1; 332 f->count = 1;
328 f->page = page; 333 f->page = page;
329 list_add_rcu(&f->list, kmmio_page_list(f->page));
330 334
331 arm_kmmio_fault_page(f->page, NULL); 335 if (arm_kmmio_fault_page(f->page, NULL)) {
336 kfree(f);
337 return -1;
338 }
339
340 list_add_rcu(&f->list, kmmio_page_list(f->page));
332 341
333 return 0; 342 return 0;
334} 343}