rev |
line source |
kaf24@1452
|
1 /******************************************************************************
|
kaf24@3597
|
2 * arch/x86/traps.c
|
kaf24@1452
|
3 *
|
kaf24@2076
|
4 * Modifications to Linux original are copyright (c) 2002-2004, K A Fraser
|
kaf24@1452
|
5 *
|
kaf24@1452
|
6 * This program is free software; you can redistribute it and/or modify
|
kaf24@1452
|
7 * it under the terms of the GNU General Public License as published by
|
kaf24@1452
|
8 * the Free Software Foundation; either version 2 of the License, or
|
kaf24@1452
|
9 * (at your option) any later version.
|
kaf24@1452
|
10 *
|
kaf24@1452
|
11 * This program is distributed in the hope that it will be useful,
|
kaf24@1452
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
kaf24@1452
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
kaf24@1452
|
14 * GNU General Public License for more details.
|
kaf24@1452
|
15 *
|
kaf24@1452
|
16 * You should have received a copy of the GNU General Public License
|
kaf24@1452
|
17 * along with this program; if not, write to the Free Software
|
kaf24@1452
|
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
kaf24@1452
|
19 */
|
kaf24@1452
|
20
|
kaf24@1452
|
21 /*
|
kaf24@1452
|
22 * Copyright (C) 1991, 1992 Linus Torvalds
|
kaf24@1452
|
23 *
|
kaf24@1452
|
24 * Pentium III FXSR, SSE support
|
kaf24@1452
|
25 * Gareth Hughes <gareth@valinux.com>, May 2000
|
kaf24@1452
|
26 */
|
kaf24@1452
|
27
|
kaf24@1452
|
28 #include <xen/config.h>
|
kaf24@1452
|
29 #include <xen/init.h>
|
kaf24@1452
|
30 #include <xen/sched.h>
|
kaf24@1452
|
31 #include <xen/lib.h>
|
kaf24@1452
|
32 #include <xen/errno.h>
|
kaf24@1452
|
33 #include <xen/mm.h>
|
kaf24@2041
|
34 #include <xen/console.h>
|
ach61@2805
|
35 #include <asm/regs.h>
|
kaf24@1452
|
36 #include <xen/delay.h>
|
kaf24@2047
|
37 #include <xen/event.h>
|
kaf24@1452
|
38 #include <xen/spinlock.h>
|
kaf24@1452
|
39 #include <xen/irq.h>
|
kaf24@1452
|
40 #include <xen/perfc.h>
|
kaf24@2047
|
41 #include <xen/softirq.h>
|
kaf24@5356
|
42 #include <xen/domain_page.h>
|
kaf24@5824
|
43 #include <xen/symbols.h>
|
kaf24@1749
|
44 #include <asm/shadow.h>
|
kaf24@1452
|
45 #include <asm/system.h>
|
kaf24@1452
|
46 #include <asm/io.h>
|
kaf24@1452
|
47 #include <asm/atomic.h>
|
kaf24@1452
|
48 #include <asm/desc.h>
|
kaf24@1452
|
49 #include <asm/debugreg.h>
|
kaf24@1452
|
50 #include <asm/smp.h>
|
kaf24@1452
|
51 #include <asm/flushtlb.h>
|
kaf24@1452
|
52 #include <asm/uaccess.h>
|
kaf24@1452
|
53 #include <asm/i387.h>
|
kaf24@2971
|
54 #include <asm/debugger.h>
|
kaf24@3337
|
55 #include <asm/msr.h>
|
kaf24@4047
|
56 #include <asm/x86_emulate.h>
|
kaf24@1452
|
57
|
kaf24@3334
|
58 /*
|
kaf24@3334
|
59 * opt_nmi: one of 'ignore', 'dom0', or 'fatal'.
|
kaf24@3334
|
60 * fatal: Xen prints diagnostic message and then hangs.
|
kaf24@3334
|
61 * dom0: The NMI is virtualised to DOM0.
|
kaf24@3334
|
62 * ignore: The NMI error is cleared and ignored.
|
kaf24@3334
|
63 */
|
kaf24@3334
|
64 #ifdef NDEBUG
|
kaf24@3334
|
65 char opt_nmi[10] = "dom0";
|
kaf24@3334
|
66 #else
|
kaf24@3334
|
67 char opt_nmi[10] = "fatal";
|
kaf24@3334
|
68 #endif
|
kaf24@3334
|
69 string_param("nmi", opt_nmi);
|
kaf24@3334
|
70
|
kaf24@3774
|
71 /* Master table, used by all CPUs on x86/64, and by CPU0 on x86/32.*/
|
kaf24@3847
|
72 idt_entry_t idt_table[IDT_ENTRIES];
|
kaf24@1452
|
73
|
kaf24@4972
|
74 #define DECLARE_TRAP_HANDLER(_name) \
|
kaf24@4972
|
75 asmlinkage void _name(void); \
|
kaf24@4972
|
76 asmlinkage int do_ ## _name(struct cpu_user_regs *regs)
|
kaf24@1452
|
77
|
kaf24@1452
|
78 asmlinkage void nmi(void);
|
kaf24@4972
|
79 DECLARE_TRAP_HANDLER(divide_error);
|
kaf24@4972
|
80 DECLARE_TRAP_HANDLER(debug);
|
kaf24@4972
|
81 DECLARE_TRAP_HANDLER(int3);
|
kaf24@4972
|
82 DECLARE_TRAP_HANDLER(overflow);
|
kaf24@4972
|
83 DECLARE_TRAP_HANDLER(bounds);
|
kaf24@4972
|
84 DECLARE_TRAP_HANDLER(invalid_op);
|
kaf24@4972
|
85 DECLARE_TRAP_HANDLER(device_not_available);
|
kaf24@4972
|
86 DECLARE_TRAP_HANDLER(coprocessor_segment_overrun);
|
kaf24@4972
|
87 DECLARE_TRAP_HANDLER(invalid_TSS);
|
kaf24@4972
|
88 DECLARE_TRAP_HANDLER(segment_not_present);
|
kaf24@4972
|
89 DECLARE_TRAP_HANDLER(stack_segment);
|
kaf24@4972
|
90 DECLARE_TRAP_HANDLER(general_protection);
|
kaf24@4972
|
91 DECLARE_TRAP_HANDLER(page_fault);
|
kaf24@4972
|
92 DECLARE_TRAP_HANDLER(coprocessor_error);
|
kaf24@4972
|
93 DECLARE_TRAP_HANDLER(simd_coprocessor_error);
|
kaf24@4972
|
94 DECLARE_TRAP_HANDLER(alignment_check);
|
kaf24@4972
|
95 DECLARE_TRAP_HANDLER(spurious_interrupt_bug);
|
kaf24@4972
|
96 DECLARE_TRAP_HANDLER(machine_check);
|
kaf24@1452
|
97
|
kaf24@5696
|
98 long do_set_debugreg(int reg, unsigned long value);
|
kaf24@5696
|
99 unsigned long do_get_debugreg(int reg);
|
kaf24@5696
|
100
|
kaf24@4923
|
101 static int debug_stack_lines = 20;
|
kaf24@4923
|
102 integer_param("debug_stack_lines", debug_stack_lines);
|
kaf24@6573
|
103
|
kaf24@6573
|
104 #ifdef CONFIG_X86_32
|
kaf24@6573
|
105 #define stack_words_per_line 8
|
kaf24@6573
|
106 #define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)®s->esp)
|
kaf24@6573
|
107 #else
|
kaf24@6573
|
108 #define stack_words_per_line 4
|
kaf24@6756
|
109 #define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)regs->rsp)
|
kaf24@6573
|
110 #endif
|
kaf24@1452
|
111
|
kaf24@5824
|
112 int is_kernel_text(unsigned long addr)
|
kaf24@1452
|
113 {
|
kaf24@5146
|
114 extern char _stext, _etext;
|
kaf24@1452
|
115 if (addr >= (unsigned long) &_stext &&
|
kaf24@1452
|
116 addr <= (unsigned long) &_etext)
|
kaf24@1452
|
117 return 1;
|
kaf24@1452
|
118 return 0;
|
kaf24@1452
|
119
|
kaf24@1452
|
120 }
|
kaf24@1452
|
121
|
kaf24@5824
|
122 unsigned long kernel_text_end(void)
|
kaf24@5824
|
123 {
|
kaf24@5824
|
124 extern char _etext;
|
kaf24@5824
|
125 return (unsigned long) &_etext;
|
kaf24@5824
|
126 }
|
kaf24@5824
|
127
|
kaf24@6573
|
128 static void show_guest_stack(struct cpu_user_regs *regs)
|
iap10@2441
|
129 {
|
iap10@2441
|
130 int i;
|
kaf24@4923
|
131 unsigned long *stack = (unsigned long *)regs->esp, addr;
|
iap10@2441
|
132
|
kaf24@4923
|
133 printk("Guest stack trace from "__OP"sp=%p:\n ", stack);
|
kaf24@4923
|
134
|
kaf24@6477
|
135 for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )
|
iap10@2441
|
136 {
|
kaf24@6573
|
137 if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )
|
iap10@2441
|
138 break;
|
kaf24@4923
|
139 if ( get_user(addr, stack) )
|
kaf24@4923
|
140 {
|
kaf24@4923
|
141 if ( i != 0 )
|
kaf24@4923
|
142 printk("\n ");
|
kaf24@4923
|
143 printk("Fault while accessing guest memory.");
|
kaf24@4923
|
144 i = 1;
|
kaf24@4923
|
145 break;
|
kaf24@4923
|
146 }
|
kaf24@6477
|
147 if ( (i != 0) && ((i % stack_words_per_line) == 0) )
|
kaf24@4923
|
148 printk("\n ");
|
kaf24@4923
|
149 printk("%p ", _p(addr));
|
kaf24@4923
|
150 stack++;
|
iap10@2441
|
151 }
|
kaf24@4923
|
152 if ( i == 0 )
|
kaf24@4923
|
153 printk("Stack empty.");
|
iap10@2441
|
154 printk("\n");
|
iap10@2441
|
155 }
|
iap10@2441
|
156
|
kaf24@6573
|
157 #ifdef NDEBUG
|
kaf24@6573
|
158
|
kaf24@6573
|
159 static void show_trace(struct cpu_user_regs *regs)
|
iap10@2471
|
160 {
|
kaf24@6573
|
161 unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;
|
kaf24@6573
|
162
|
kaf24@6573
|
163 printk("Xen call trace:\n ");
|
kaf24@4923
|
164
|
kaf24@6573
|
165 printk("[<%p>]", _p(regs->eip));
|
kaf24@6573
|
166 print_symbol(" %s\n ", regs->eip);
|
iap10@2471
|
167
|
kaf24@6573
|
168 while ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) != 0 )
|
kaf24@4923
|
169 {
|
iap10@2471
|
170 addr = *stack++;
|
kaf24@5824
|
171 if ( is_kernel_text(addr) )
|
kaf24@4923
|
172 {
|
kaf24@5824
|
173 printk("[<%p>]", _p(addr));
|
kaf24@6232
|
174 print_symbol(" %s\n ", addr);
|
iap10@2471
|
175 }
|
iap10@2471
|
176 }
|
kaf24@6573
|
177
|
iap10@2471
|
178 printk("\n");
|
iap10@2471
|
179 }
|
iap10@2471
|
180
|
kaf24@6573
|
181 #else
|
kaf24@6573
|
182
|
kaf24@6573
|
183 static void show_trace(struct cpu_user_regs *regs)
|
kaf24@1452
|
184 {
|
kaf24@6573
|
185 unsigned long *frame, next, addr, low, high;
|
kaf24@6573
|
186
|
kaf24@6573
|
187 printk("Xen call trace:\n ");
|
kaf24@6573
|
188
|
kaf24@6573
|
189 printk("[<%p>]", _p(regs->eip));
|
kaf24@6573
|
190 print_symbol(" %s\n ", regs->eip);
|
kaf24@6573
|
191
|
kaf24@6573
|
192 /* Bounds for range of valid frame pointer. */
|
kaf24@6573
|
193 low = (unsigned long)(ESP_BEFORE_EXCEPTION(regs) - 2);
|
kaf24@6573
|
194 high = (low & ~(STACK_SIZE - 1)) + (STACK_SIZE - sizeof(struct cpu_info));
|
kaf24@6573
|
195
|
kaf24@6573
|
196 /* The initial frame pointer. */
|
kaf24@6573
|
197 next = regs->ebp;
|
kaf24@6573
|
198
|
kaf24@6573
|
199 for ( ; ; )
|
kaf24@6573
|
200 {
|
kaf24@6573
|
201 /* Valid frame pointer? */
|
kaf24@6573
|
202 if ( (next < low) || (next > high) )
|
kaf24@6573
|
203 {
|
kaf24@6573
|
204 /*
|
kaf24@6573
|
205 * Exception stack frames have a different layout, denoted by an
|
kaf24@6573
|
206 * inverted frame pointer.
|
kaf24@6573
|
207 */
|
kaf24@6573
|
208 next = ~next;
|
kaf24@6573
|
209 if ( (next < low) || (next > high) )
|
kaf24@6573
|
210 break;
|
kaf24@6573
|
211 frame = (unsigned long *)next;
|
kaf24@6573
|
212 next = frame[0];
|
kaf24@6573
|
213 addr = frame[(offsetof(struct cpu_user_regs, eip) -
|
kaf24@6573
|
214 offsetof(struct cpu_user_regs, ebp))
|
kaf24@6573
|
215 / BYTES_PER_LONG];
|
kaf24@6573
|
216 }
|
kaf24@6573
|
217 else
|
kaf24@6573
|
218 {
|
kaf24@6573
|
219 /* Ordinary stack frame. */
|
kaf24@6573
|
220 frame = (unsigned long *)next;
|
kaf24@6573
|
221 next = frame[0];
|
kaf24@6573
|
222 addr = frame[1];
|
kaf24@6573
|
223 }
|
kaf24@6573
|
224
|
kaf24@6573
|
225 printk("[<%p>]", _p(addr));
|
kaf24@6573
|
226 print_symbol(" %s\n ", addr);
|
kaf24@6573
|
227
|
kaf24@6573
|
228 low = (unsigned long)&frame[2];
|
kaf24@6573
|
229 }
|
kaf24@6573
|
230
|
kaf24@6573
|
231 printk("\n");
|
kaf24@6573
|
232 }
|
kaf24@6573
|
233
|
kaf24@6573
|
234 #endif
|
kaf24@6573
|
235
|
kaf24@6573
|
236 void show_stack(struct cpu_user_regs *regs)
|
kaf24@6573
|
237 {
|
kaf24@6573
|
238 unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;
|
kaf24@1452
|
239 int i;
|
kaf24@1452
|
240
|
kaf24@6756
|
241 if ( GUEST_CONTEXT(current, regs) )
|
kaf24@6573
|
242 return show_guest_stack(regs);
|
kaf24@6573
|
243
|
kaf24@4923
|
244 printk("Xen stack trace from "__OP"sp=%p:\n ", stack);
|
kaf24@1452
|
245
|
kaf24@6477
|
246 for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )
|
kaf24@1452
|
247 {
|
kaf24@6573
|
248 if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )
|
kaf24@1452
|
249 break;
|
kaf24@6477
|
250 if ( (i != 0) && ((i % stack_words_per_line) == 0) )
|
kaf24@4923
|
251 printk("\n ");
|
kaf24@4923
|
252 addr = *stack++;
|
kaf24@5824
|
253 printk("%p ", _p(addr));
|
kaf24@1452
|
254 }
|
kaf24@4923
|
255 if ( i == 0 )
|
kaf24@4923
|
256 printk("Stack empty.");
|
kaf24@1452
|
257 printk("\n");
|
kaf24@1452
|
258
|
kaf24@6573
|
259 show_trace(regs);
|
kaf24@1452
|
260 }
|
kaf24@1452
|
261
|
kaf24@3041
|
262 /*
|
kaf24@3041
|
263 * This is called for faults at very unexpected times (e.g., when interrupts
|
kaf24@3041
|
264 * are disabled). In such situations we can't do much that is safe. We try to
|
kaf24@3041
|
265 * print out some tracing and then we just spin.
|
kaf24@3041
|
266 */
|
kaf24@4683
|
267 asmlinkage void fatal_trap(int trapnr, struct cpu_user_regs *regs)
|
kaf24@1452
|
268 {
|
kaf24@3041
|
269 int cpu = smp_processor_id();
|
kaf24@3089
|
270 unsigned long cr2;
|
kaf24@3041
|
271 static char *trapstr[] = {
|
kaf24@3041
|
272 "divide error", "debug", "nmi", "bkpt", "overflow", "bounds",
|
kaf24@3041
|
273 "invalid operation", "device not available", "double fault",
|
kaf24@3041
|
274 "coprocessor segment", "invalid tss", "segment not found",
|
kaf24@3041
|
275 "stack error", "general protection fault", "page fault",
|
kaf24@3041
|
276 "spurious interrupt", "coprocessor error", "alignment check",
|
kaf24@3041
|
277 "machine check", "simd error"
|
kaf24@3041
|
278 };
|
kaf24@3041
|
279
|
kaf24@4926
|
280 watchdog_disable();
|
kaf24@5321
|
281 console_start_sync();
|
kaf24@3849
|
282
|
kaf24@1452
|
283 show_registers(regs);
|
kaf24@3089
|
284
|
kaf24@3089
|
285 if ( trapnr == TRAP_page_fault )
|
kaf24@3089
|
286 {
|
kaf24@3602
|
287 __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (cr2) : );
|
kaf24@4817
|
288 printk("Faulting linear address: %p\n", _p(cr2));
|
kaf24@4817
|
289 show_page_walk(cr2);
|
kaf24@3089
|
290 }
|
kaf24@3089
|
291
|
kaf24@3041
|
292 printk("************************************\n");
|
kaf24@3089
|
293 printk("CPU%d FATAL TRAP %d (%s), ERROR_CODE %04x%s.\n",
|
kaf24@3089
|
294 cpu, trapnr, trapstr[trapnr], regs->error_code,
|
kaf24@3041
|
295 (regs->eflags & X86_EFLAGS_IF) ? "" : ", IN INTERRUPT CONTEXT");
|
kaf24@3041
|
296 printk("System shutting down -- need manual reset.\n");
|
kaf24@3041
|
297 printk("************************************\n");
|
kaf24@3041
|
298
|
sos22@3792
|
299 (void)debugger_trap_fatal(trapnr, regs);
|
sos22@3771
|
300
|
kaf24@3041
|
301 /* Lock up the console to prevent spurious output from other CPUs. */
|
kaf24@3041
|
302 console_force_lock();
|
kaf24@3041
|
303
|
kaf24@3041
|
304 /* Wait for manual reset. */
|
kaf24@3041
|
305 for ( ; ; )
|
kaf24@3041
|
306 __asm__ __volatile__ ( "hlt" );
|
kaf24@1452
|
307 }
|
kaf24@1452
|
308
|
kaf24@3052
|
309 static inline int do_trap(int trapnr, char *str,
|
kaf24@4683
|
310 struct cpu_user_regs *regs,
|
kaf24@3089
|
311 int use_error_code)
|
kaf24@1452
|
312 {
|
kaf24@5289
|
313 struct vcpu *v = current;
|
kaf24@5289
|
314 struct trap_bounce *tb = &v->arch.trap_bounce;
|
kaf24@1452
|
315 trap_info_t *ti;
|
kaf24@1452
|
316 unsigned long fixup;
|
kaf24@1452
|
317
|
kaf24@3089
|
318 DEBUGGER_trap_entry(trapnr, regs);
|
kaf24@2971
|
319
|
kaf24@3754
|
320 if ( !GUEST_MODE(regs) )
|
kaf24@1590
|
321 goto xen_fault;
|
kaf24@1452
|
322
|
kaf24@4689
|
323 ti = ¤t->arch.guest_context.trap_ctxt[trapnr];
|
kaf24@3089
|
324 tb->flags = TBF_EXCEPTION;
|
kaf24@3089
|
325 tb->cs = ti->cs;
|
kaf24@3089
|
326 tb->eip = ti->address;
|
kaf24@3089
|
327 if ( use_error_code )
|
kaf24@3089
|
328 {
|
kaf24@3089
|
329 tb->flags |= TBF_EXCEPTION_ERRCODE;
|
kaf24@3089
|
330 tb->error_code = regs->error_code;
|
kaf24@3089
|
331 }
|
kaf24@1452
|
332 if ( TI_GET_IF(ti) )
|
kaf24@4949
|
333 tb->flags |= TBF_INTERRUPT;
|
kaf24@3052
|
334 return 0;
|
kaf24@1452
|
335
|
kaf24@1590
|
336 xen_fault:
|
kaf24@1452
|
337
|
kaf24@1452
|
338 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
|
kaf24@1452
|
339 {
|
kaf24@4654
|
340 DPRINTK("Trap %d: %p -> %p\n", trapnr, _p(regs->eip), _p(fixup));
|
kaf24@1452
|
341 regs->eip = fixup;
|
kaf24@3052
|
342 return 0;
|
kaf24@1452
|
343 }
|
kaf24@1452
|
344
|
kaf24@3089
|
345 DEBUGGER_trap_fatal(trapnr, regs);
|
cl349@2957
|
346
|
kaf24@1452
|
347 show_registers(regs);
|
kaf24@1452
|
348 panic("CPU%d FATAL TRAP: vector = %d (%s)\n"
|
kaf24@3089
|
349 "[error_code=%04x]\n",
|
kaf24@3089
|
350 smp_processor_id(), trapnr, str, regs->error_code);
|
kaf24@3052
|
351 return 0;
|
kaf24@1452
|
352 }
|
kaf24@1452
|
353
|
kaf24@1452
|
354 #define DO_ERROR_NOCODE(trapnr, str, name) \
|
kaf24@4683
|
355 asmlinkage int do_##name(struct cpu_user_regs *regs) \
|
kaf24@1452
|
356 { \
|
kaf24@3089
|
357 return do_trap(trapnr, str, regs, 0); \
|
kaf24@1452
|
358 }
|
kaf24@1452
|
359
|
kaf24@1452
|
360 #define DO_ERROR(trapnr, str, name) \
|
kaf24@4683
|
361 asmlinkage int do_##name(struct cpu_user_regs *regs) \
|
kaf24@1452
|
362 { \
|
kaf24@3089
|
363 return do_trap(trapnr, str, regs, 1); \
|
kaf24@1452
|
364 }
|
kaf24@1452
|
365
|
kaf24@1452
|
366 DO_ERROR_NOCODE( 0, "divide error", divide_error)
|
kaf24@2076
|
367 DO_ERROR_NOCODE( 4, "overflow", overflow)
|
kaf24@2076
|
368 DO_ERROR_NOCODE( 5, "bounds", bounds)
|
kaf24@2076
|
369 DO_ERROR_NOCODE( 6, "invalid operand", invalid_op)
|
kaf24@2076
|
370 DO_ERROR_NOCODE( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
|
kaf24@2076
|
371 DO_ERROR(10, "invalid TSS", invalid_TSS)
|
kaf24@2076
|
372 DO_ERROR(11, "segment not present", segment_not_present)
|
kaf24@2076
|
373 DO_ERROR(12, "stack segment", stack_segment)
|
kaf24@2076
|
374 DO_ERROR_NOCODE(16, "fpu error", coprocessor_error)
|
kaf24@2076
|
375 DO_ERROR(17, "alignment check", alignment_check)
|
kaf24@2076
|
376 DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
|
kaf24@1452
|
377
|
kaf24@4683
|
378 asmlinkage int do_int3(struct cpu_user_regs *regs)
|
kaf24@1452
|
379 {
|
kaf24@5289
|
380 struct vcpu *v = current;
|
kaf24@5289
|
381 struct trap_bounce *tb = &v->arch.trap_bounce;
|
kaf24@1452
|
382 trap_info_t *ti;
|
kaf24@1452
|
383
|
kaf24@3089
|
384 DEBUGGER_trap_entry(TRAP_int3, regs);
|
kaf24@1452
|
385
|
kaf24@3754
|
386 if ( !GUEST_MODE(regs) )
|
kaf24@1452
|
387 {
|
kaf24@3089
|
388 DEBUGGER_trap_fatal(TRAP_int3, regs);
|
kaf24@2971
|
389 show_registers(regs);
|
kaf24@3089
|
390 panic("CPU%d FATAL TRAP: vector = 3 (Int3)\n", smp_processor_id());
|
kmacy@4118
|
391 }
|
kaf24@1452
|
392
|
kaf24@4689
|
393 ti = ¤t->arch.guest_context.trap_ctxt[TRAP_int3];
|
kaf24@3089
|
394 tb->flags = TBF_EXCEPTION;
|
kaf24@3089
|
395 tb->cs = ti->cs;
|
kaf24@3089
|
396 tb->eip = ti->address;
|
kaf24@1452
|
397 if ( TI_GET_IF(ti) )
|
kaf24@4949
|
398 tb->flags |= TBF_INTERRUPT;
|
kaf24@3052
|
399
|
kaf24@3052
|
400 return 0;
|
kaf24@1452
|
401 }
|
kaf24@1452
|
402
|
kaf24@4972
|
403 asmlinkage int do_machine_check(struct cpu_user_regs *regs)
|
kaf24@3041
|
404 {
|
kaf24@3089
|
405 fatal_trap(TRAP_machine_check, regs);
|
kaf24@4972
|
406 return 0;
|
kaf24@1452
|
407 }
|
kaf24@1452
|
408
|
kaf24@3424
|
409 void propagate_page_fault(unsigned long addr, u16 error_code)
|
kaf24@3424
|
410 {
|
kaf24@3424
|
411 trap_info_t *ti;
|
kaf24@5289
|
412 struct vcpu *v = current;
|
kaf24@5289
|
413 struct trap_bounce *tb = &v->arch.trap_bounce;
|
kaf24@3424
|
414
|
kaf24@5289
|
415 ti = &v->arch.guest_context.trap_ctxt[TRAP_page_fault];
|
kaf24@3424
|
416 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE | TBF_EXCEPTION_CR2;
|
kaf24@3424
|
417 tb->cr2 = addr;
|
kaf24@3424
|
418 tb->error_code = error_code;
|
kaf24@3424
|
419 tb->cs = ti->cs;
|
kaf24@3424
|
420 tb->eip = ti->address;
|
kaf24@3424
|
421 if ( TI_GET_IF(ti) )
|
kaf24@4949
|
422 tb->flags |= TBF_INTERRUPT;
|
kaf24@3405
|
423
|
kaf24@5576
|
424 v->arch.guest_context.ctrlreg[2] = addr;
|
kaf24@3424
|
425 }
|
kaf24@3424
|
426
|
kaf24@4972
|
427 static int handle_perdomain_mapping_fault(
|
kaf24@4972
|
428 unsigned long offset, struct cpu_user_regs *regs)
|
kaf24@1452
|
429 {
|
kaf24@1452
|
430 extern int map_ldt_shadow_page(unsigned int);
|
kaf24@4972
|
431
|
kaf24@5289
|
432 struct vcpu *v = current;
|
kaf24@5289
|
433 struct domain *d = v->domain;
|
kaf24@4972
|
434 int ret;
|
kaf24@4972
|
435
|
kaf24@4972
|
436 /* Which vcpu's area did we fault in, and is it in the ldt sub-area? */
|
kaf24@4972
|
437 unsigned int is_ldt_area = (offset >> (PDPT_VCPU_VA_SHIFT-1)) & 1;
|
kaf24@4972
|
438 unsigned int vcpu_area = (offset >> PDPT_VCPU_VA_SHIFT);
|
kaf24@4972
|
439
|
kaf24@4972
|
440 /* Should never fault in another vcpu's area. */
|
kaf24@4972
|
441 BUG_ON(vcpu_area != current->vcpu_id);
|
kaf24@4972
|
442
|
kaf24@4972
|
443 /* Byte offset within the gdt/ldt sub-area. */
|
kaf24@4972
|
444 offset &= (1UL << (PDPT_VCPU_VA_SHIFT-1)) - 1UL;
|
kaf24@4972
|
445
|
kaf24@4972
|
446 if ( likely(is_ldt_area) )
|
kaf24@4972
|
447 {
|
kaf24@4972
|
448 /* LDT fault: Copy a mapping from the guest's LDT, if it is valid. */
|
kaf24@4972
|
449 LOCK_BIGLOCK(d);
|
kaf24@4972
|
450 ret = map_ldt_shadow_page(offset >> PAGE_SHIFT);
|
kaf24@4972
|
451 UNLOCK_BIGLOCK(d);
|
kaf24@1452
|
452
|
kaf24@4972
|
453 if ( unlikely(ret == 0) )
|
kaf24@4972
|
454 {
|
kaf24@4972
|
455 /* In hypervisor mode? Leave it to the #PF handler to fix up. */
|
kaf24@4972
|
456 if ( !GUEST_MODE(regs) )
|
kaf24@4972
|
457 return 0;
|
kaf24@4972
|
458 /* In guest mode? Propagate #PF to guest, with adjusted %cr2. */
|
kaf24@4972
|
459 propagate_page_fault(
|
kaf24@5289
|
460 v->arch.guest_context.ldt_base + offset, regs->error_code);
|
kaf24@4972
|
461 }
|
kaf24@4972
|
462 }
|
kaf24@4972
|
463 else
|
kaf24@4972
|
464 {
|
kaf24@4972
|
465 /* GDT fault: handle the fault as #GP(selector). */
|
kaf24@4972
|
466 regs->error_code = (u16)offset & ~7;
|
kaf24@4972
|
467 (void)do_general_protection(regs);
|
kaf24@4972
|
468 }
|
kaf24@4972
|
469
|
kaf24@4972
|
470 return EXCRET_fault_fixed;
|
kaf24@4972
|
471 }
|
kaf24@4972
|
472
|
kaf24@6702
|
473 #ifdef HYPERVISOR_VIRT_END
|
kaf24@6702
|
474 #define IN_HYPERVISOR_RANGE(va) \
|
kaf24@6702
|
475 (((va) >= HYPERVISOR_VIRT_START) && ((va) < HYPERVISOR_VIRT_END))
|
kaf24@6702
|
476 #else
|
kaf24@6702
|
477 #define IN_HYPERVISOR_RANGE(va) \
|
kaf24@6702
|
478 (((va) >= HYPERVISOR_VIRT_START))
|
kaf24@6702
|
479 #endif
|
kaf24@6702
|
480
|
kaf24@6702
|
481 static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs)
|
kaf24@1452
|
482 {
|
kaf24@6702
|
483 struct vcpu *v = current;
|
kaf24@5289
|
484 struct domain *d = v->domain;
|
kaf24@1452
|
485
|
kaf24@6702
|
486 if ( unlikely(IN_HYPERVISOR_RANGE(addr)) )
|
kaf24@6702
|
487 {
|
kaf24@6702
|
488 if ( shadow_mode_external(d) && GUEST_CONTEXT(v, regs) )
|
kaf24@6702
|
489 return shadow_fault(addr, regs);
|
kaf24@6702
|
490 if ( (addr >= PERDOMAIN_VIRT_START) && (addr < PERDOMAIN_VIRT_END) )
|
kaf24@6702
|
491 return handle_perdomain_mapping_fault(
|
kaf24@6702
|
492 addr - PERDOMAIN_VIRT_START, regs);
|
kaf24@6702
|
493 }
|
kaf24@6702
|
494 else if ( unlikely(shadow_mode_enabled(d)) )
|
kaf24@6702
|
495 {
|
kaf24@6702
|
496 return shadow_fault(addr, regs);
|
kaf24@6702
|
497 }
|
kaf24@6702
|
498 else if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
|
kaf24@2073
|
499 {
|
cl349@3148
|
500 LOCK_BIGLOCK(d);
|
kaf24@4455
|
501 if ( unlikely(d->arch.ptwr[PTWR_PT_ACTIVE].l1va) &&
|
kaf24@6039
|
502 unlikely(l2_linear_offset(addr) ==
|
kaf24@4455
|
503 d->arch.ptwr[PTWR_PT_ACTIVE].l2_idx) )
|
kaf24@2337
|
504 {
|
kaf24@4455
|
505 ptwr_flush(d, PTWR_PT_ACTIVE);
|
cl349@2998
|
506 UNLOCK_BIGLOCK(d);
|
kaf24@3052
|
507 return EXCRET_fault_fixed;
|
kaf24@2337
|
508 }
|
cl349@1822
|
509
|
kaf24@6702
|
510 if ( KERNEL_MODE(v, regs) &&
|
kaf24@6702
|
511 /* Protection violation on write? No reserved-bit violation? */
|
kaf24@6702
|
512 ((regs->error_code & 0xb) == 0x3) &&
|
iap10@6135
|
513 ptwr_do_page_fault(d, addr, regs) )
|
kaf24@3052
|
514 {
|
cl349@3148
|
515 UNLOCK_BIGLOCK(d);
|
kaf24@3052
|
516 return EXCRET_fault_fixed;
|
kaf24@3052
|
517 }
|
cl349@3148
|
518 UNLOCK_BIGLOCK(d);
|
kaf24@2337
|
519 }
|
cl349@1822
|
520
|
kaf24@6702
|
521 return 0;
|
kaf24@6702
|
522 }
|
kaf24@6702
|
523
|
kaf24@6702
|
524 /*
|
kaf24@6702
|
525 * #PF error code:
|
kaf24@6702
|
526 * Bit 0: Protection violation (=1) ; Page not present (=0)
|
kaf24@6702
|
527 * Bit 1: Write access
|
kaf24@6702
|
528 * Bit 2: Supervisor mode
|
kaf24@6702
|
529 * Bit 3: Reserved bit violation
|
kaf24@6702
|
530 * Bit 4: Instruction fetch
|
kaf24@6702
|
531 */
|
kaf24@6702
|
532 asmlinkage int do_page_fault(struct cpu_user_regs *regs)
|
kaf24@6702
|
533 {
|
kaf24@6702
|
534 unsigned long addr, fixup;
|
kaf24@6702
|
535 int rc;
|
kaf24@6702
|
536
|
kaf24@6702
|
537 __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : );
|
kaf24@6702
|
538
|
kaf24@6702
|
539 DEBUGGER_trap_entry(TRAP_page_fault, regs);
|
kaf24@6702
|
540
|
kaf24@6702
|
541 perfc_incrc(page_faults);
|
kaf24@1452
|
542
|
kaf24@6702
|
543 if ( unlikely((rc = fixup_page_fault(addr, regs)) != 0) )
|
kaf24@6702
|
544 return rc;
|
iap10@2573
|
545
|
kaf24@6702
|
546 if ( unlikely(!GUEST_MODE(regs)) )
|
kaf24@6702
|
547 {
|
kaf24@6702
|
548 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
|
kaf24@6702
|
549 {
|
kaf24@6702
|
550 perfc_incrc(copy_user_faults);
|
kaf24@6702
|
551 regs->eip = fixup;
|
kaf24@6702
|
552 return 0;
|
kaf24@6702
|
553 }
|
kaf24@6702
|
554
|
kaf24@6702
|
555 DEBUGGER_trap_fatal(TRAP_page_fault, regs);
|
kaf24@6702
|
556
|
kaf24@6702
|
557 show_registers(regs);
|
kaf24@6702
|
558 show_page_walk(addr);
|
kaf24@6702
|
559 panic("CPU%d FATAL PAGE FAULT\n"
|
kaf24@6702
|
560 "[error_code=%04x]\n"
|
kaf24@6702
|
561 "Faulting linear address: %p\n",
|
kaf24@6702
|
562 smp_processor_id(), regs->error_code, addr);
|
kaf24@6702
|
563 }
|
kaf24@1452
|
564
|
kaf24@3424
|
565 propagate_page_fault(addr, regs->error_code);
|
kaf24@6039
|
566 return 0;
|
kaf24@1452
|
567 }
|
kaf24@1452
|
568
|
kaf24@3917
|
569 long do_fpu_taskswitch(int set)
|
kaf24@3917
|
570 {
|
kaf24@5289
|
571 struct vcpu *v = current;
|
kaf24@3917
|
572
|
kaf24@3917
|
573 if ( set )
|
kaf24@3917
|
574 {
|
kaf24@5576
|
575 v->arch.guest_context.ctrlreg[0] |= X86_CR0_TS;
|
kaf24@3917
|
576 stts();
|
kaf24@3917
|
577 }
|
kaf24@3917
|
578 else
|
kaf24@3917
|
579 {
|
kaf24@5576
|
580 v->arch.guest_context.ctrlreg[0] &= ~X86_CR0_TS;
|
kaf24@5289
|
581 if ( test_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) )
|
kaf24@3917
|
582 clts();
|
kaf24@3917
|
583 }
|
kaf24@3917
|
584
|
kaf24@3917
|
585 return 0;
|
kaf24@3917
|
586 }
|
kaf24@3917
|
587
|
kaf24@4275
|
588 /* Has the guest requested sufficient permission for this I/O access? */
|
kaf24@4275
|
589 static inline int guest_io_okay(
|
kaf24@4275
|
590 unsigned int port, unsigned int bytes,
|
kaf24@5289
|
591 struct vcpu *v, struct cpu_user_regs *regs)
|
kaf24@4275
|
592 {
|
kaf24@4275
|
593 u16 x;
|
kaf24@4276
|
594 #if defined(__x86_64__)
|
kaf24@4276
|
595 /* If in user mode, switch to kernel mode just to read I/O bitmap. */
|
kaf24@5289
|
596 extern void toggle_guest_mode(struct vcpu *);
|
kaf24@5289
|
597 int user_mode = !(v->arch.flags & TF_kernel_mode);
|
kaf24@5289
|
598 #define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v)
|
kaf24@4276
|
599 #elif defined(__i386__)
|
kaf24@4276
|
600 #define TOGGLE_MODE() ((void)0)
|
kaf24@4276
|
601 #endif
|
kaf24@4276
|
602
|
kaf24@5289
|
603 if ( v->arch.iopl >= (KERNEL_MODE(v, regs) ? 1 : 3) )
|
kaf24@4275
|
604 return 1;
|
kaf24@4276
|
605
|
kaf24@5289
|
606 if ( v->arch.iobmp_limit > (port + bytes) )
|
kaf24@4276
|
607 {
|
kaf24@4276
|
608 TOGGLE_MODE();
|
kaf24@5289
|
609 __get_user(x, (u16 *)(v->arch.iobmp+(port>>3)));
|
kaf24@4276
|
610 TOGGLE_MODE();
|
kaf24@4276
|
611 if ( (x & (((1<<bytes)-1) << (port&7))) == 0 )
|
kaf24@4276
|
612 return 1;
|
kaf24@4276
|
613 }
|
kaf24@4276
|
614
|
kaf24@4275
|
615 return 0;
|
kaf24@4275
|
616 }
|
kaf24@4275
|
617
|
kaf24@4275
|
618 /* Has the administrator granted sufficient permission for this I/O access? */
|
kaf24@4275
|
619 static inline int admin_io_okay(
|
kaf24@4103
|
620 unsigned int port, unsigned int bytes,
|
kaf24@5289
|
621 struct vcpu *v, struct cpu_user_regs *regs)
|
kaf24@4103
|
622 {
|
kaf24@5289
|
623 struct domain *d = v->domain;
|
kaf24@4275
|
624 u16 x;
|
kaf24@4276
|
625
|
kaf24@4275
|
626 if ( d->arch.iobmp_mask != NULL )
|
kaf24@4275
|
627 {
|
kaf24@4275
|
628 x = *(u16 *)(d->arch.iobmp_mask + (port >> 3));
|
kaf24@4275
|
629 if ( (x & (((1<<bytes)-1) << (port&7))) == 0 )
|
kaf24@4275
|
630 return 1;
|
kaf24@4275
|
631 }
|
kaf24@4276
|
632
|
kaf24@4275
|
633 return 0;
|
kaf24@4103
|
634 }
|
kaf24@4103
|
635
|
kaf24@4275
|
636 /* Check admin limits. Silently fail the access if it is disallowed. */
|
kaf24@4275
|
637 #define inb_user(_p, _d, _r) (admin_io_okay(_p, 1, _d, _r) ? inb(_p) : ~0)
|
kaf24@4275
|
638 #define inw_user(_p, _d, _r) (admin_io_okay(_p, 2, _d, _r) ? inw(_p) : ~0)
|
kaf24@4275
|
639 #define inl_user(_p, _d, _r) (admin_io_okay(_p, 4, _d, _r) ? inl(_p) : ~0)
|
kaf24@4275
|
640 #define outb_user(_v, _p, _d, _r) \
|
kaf24@4275
|
641 (admin_io_okay(_p, 1, _d, _r) ? outb(_v, _p) : ((void)0))
|
kaf24@4275
|
642 #define outw_user(_v, _p, _d, _r) \
|
kaf24@4275
|
643 (admin_io_okay(_p, 2, _d, _r) ? outw(_v, _p) : ((void)0))
|
kaf24@4275
|
644 #define outl_user(_v, _p, _d, _r) \
|
kaf24@4275
|
645 (admin_io_okay(_p, 4, _d, _r) ? outl(_v, _p) : ((void)0))
|
kaf24@4275
|
646
|
kaf24@4862
|
647 /* Propagate a fault back to the guest kernel. */
|
kaf24@4862
|
648 #define USER_READ_FAULT 4 /* user mode, read fault */
|
kaf24@4862
|
649 #define USER_WRITE_FAULT 6 /* user mode, write fault */
|
kaf24@4862
|
650 #define PAGE_FAULT(_faultaddr, _errcode) \
|
kaf24@4862
|
651 ({ propagate_page_fault(_faultaddr, _errcode); \
|
kaf24@4862
|
652 return EXCRET_fault_fixed; \
|
kaf24@4862
|
653 })
|
kaf24@4862
|
654
|
kaf24@4862
|
655 /* Isntruction fetch with error handling. */
|
kaf24@4103
|
656 #define insn_fetch(_type, _size, _ptr) \
|
kaf24@4103
|
657 ({ unsigned long _x; \
|
kaf24@4103
|
658 if ( get_user(_x, (_type *)eip) ) \
|
kaf24@4862
|
659 PAGE_FAULT(eip, USER_READ_FAULT); \
|
kaf24@4103
|
660 eip += _size; (_type)_x; })
|
kaf24@4103
|
661
|
kaf24@4683
|
662 static int emulate_privileged_op(struct cpu_user_regs *regs)
|
kaf24@1452
|
663 {
|
kaf24@5289
|
664 struct vcpu *v = current;
|
kaf24@5696
|
665 unsigned long *reg, eip = regs->eip, res;
|
kaf24@5696
|
666 u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0;
|
kaf24@4103
|
667 unsigned int port, i, op_bytes = 4, data;
|
kaf24@4103
|
668
|
kaf24@4103
|
669 /* Legacy prefixes. */
|
kaf24@4103
|
670 for ( i = 0; i < 8; i++ )
|
kaf24@4103
|
671 {
|
kaf24@4103
|
672 switch ( opcode = insn_fetch(u8, 1, eip) )
|
kaf24@4103
|
673 {
|
kaf24@4103
|
674 case 0x66: /* operand-size override */
|
kaf24@4103
|
675 op_bytes ^= 6; /* switch between 2/4 bytes */
|
kaf24@4103
|
676 break;
|
kaf24@4103
|
677 case 0x67: /* address-size override */
|
kaf24@4103
|
678 case 0x2e: /* CS override */
|
kaf24@4103
|
679 case 0x3e: /* DS override */
|
kaf24@4103
|
680 case 0x26: /* ES override */
|
kaf24@4103
|
681 case 0x64: /* FS override */
|
kaf24@4103
|
682 case 0x65: /* GS override */
|
kaf24@4103
|
683 case 0x36: /* SS override */
|
kaf24@4103
|
684 case 0xf0: /* LOCK */
|
kaf24@4103
|
685 case 0xf2: /* REPNE/REPNZ */
|
kaf24@4103
|
686 break;
|
kaf24@4103
|
687 case 0xf3: /* REP/REPE/REPZ */
|
kaf24@4103
|
688 rep_prefix = 1;
|
kaf24@4103
|
689 break;
|
kaf24@4103
|
690 default:
|
kaf24@4103
|
691 goto done_prefixes;
|
kaf24@4103
|
692 }
|
kaf24@4103
|
693 }
|
kaf24@4103
|
694 done_prefixes:
|
kaf24@4103
|
695
|
kaf24@4103
|
696 #ifdef __x86_64__
|
kaf24@4103
|
697 /* REX prefix. */
|
kaf24@4103
|
698 if ( (opcode & 0xf0) == 0x40 )
|
kaf24@4103
|
699 {
|
kaf24@4103
|
700 modrm_reg = (opcode & 4) << 1; /* REX.R */
|
kaf24@5696
|
701 modrm_rm = (opcode & 1) << 3; /* REX.B */
|
kaf24@5696
|
702
|
kaf24@5696
|
703 /* REX.W and REX.X do not need to be decoded. */
|
kaf24@4103
|
704 opcode = insn_fetch(u8, 1, eip);
|
kaf24@4103
|
705 }
|
kaf24@4103
|
706 #endif
|
kaf24@4103
|
707
|
kaf24@4103
|
708 /* Input/Output String instructions. */
|
kaf24@4103
|
709 if ( (opcode >= 0x6c) && (opcode <= 0x6f) )
|
kaf24@4103
|
710 {
|
kaf24@4103
|
711 if ( rep_prefix && (regs->ecx == 0) )
|
kaf24@4103
|
712 goto done;
|
kaf24@4103
|
713
|
kaf24@4103
|
714 continue_io_string:
|
kaf24@4103
|
715 switch ( opcode )
|
kaf24@4103
|
716 {
|
kaf24@4103
|
717 case 0x6c: /* INSB */
|
kaf24@4103
|
718 op_bytes = 1;
|
kaf24@4103
|
719 case 0x6d: /* INSW/INSL */
|
kaf24@5289
|
720 if ( !guest_io_okay((u16)regs->edx, op_bytes, v, regs) )
|
kaf24@4103
|
721 goto fail;
|
kaf24@4103
|
722 switch ( op_bytes )
|
kaf24@4103
|
723 {
|
kaf24@4103
|
724 case 1:
|
kaf24@5289
|
725 data = (u8)inb_user((u16)regs->edx, v, regs);
|
kaf24@4103
|
726 if ( put_user((u8)data, (u8 *)regs->edi) )
|
kaf24@4862
|
727 PAGE_FAULT(regs->edi, USER_WRITE_FAULT);
|
kaf24@4103
|
728 break;
|
kaf24@4103
|
729 case 2:
|
kaf24@5289
|
730 data = (u16)inw_user((u16)regs->edx, v, regs);
|
kaf24@4103
|
731 if ( put_user((u16)data, (u16 *)regs->edi) )
|
kaf24@4862
|
732 PAGE_FAULT(regs->edi, USER_WRITE_FAULT);
|
kaf24@4103
|
733 break;
|
kaf24@4103
|
734 case 4:
|
kaf24@5289
|
735 data = (u32)inl_user((u16)regs->edx, v, regs);
|
kaf24@4103
|
736 if ( put_user((u32)data, (u32 *)regs->edi) )
|
kaf24@4862
|
737 PAGE_FAULT(regs->edi, USER_WRITE_FAULT);
|
kaf24@4103
|
738 break;
|
kaf24@4103
|
739 }
|
kaf24@4103
|
740 regs->edi += (regs->eflags & EF_DF) ? -op_bytes : op_bytes;
|
kaf24@4103
|
741 break;
|
kaf24@3405
|
742
|
kaf24@4103
|
743 case 0x6e: /* OUTSB */
|
kaf24@4103
|
744 op_bytes = 1;
|
kaf24@4103
|
745 case 0x6f: /* OUTSW/OUTSL */
|
kaf24@5289
|
746 if ( !guest_io_okay((u16)regs->edx, op_bytes, v, regs) )
|
kaf24@4103
|
747 goto fail;
|
kaf24@4103
|
748 switch ( op_bytes )
|
kaf24@4103
|
749 {
|
kaf24@4103
|
750 case 1:
|
kaf24@4103
|
751 if ( get_user(data, (u8 *)regs->esi) )
|
kaf24@4862
|
752 PAGE_FAULT(regs->esi, USER_READ_FAULT);
|
kaf24@5289
|
753 outb_user((u8)data, (u16)regs->edx, v, regs);
|
kaf24@4103
|
754 break;
|
kaf24@4103
|
755 case 2:
|
kaf24@4103
|
756 if ( get_user(data, (u16 *)regs->esi) )
|
kaf24@4862
|
757 PAGE_FAULT(regs->esi, USER_READ_FAULT);
|
kaf24@5289
|
758 outw_user((u16)data, (u16)regs->edx, v, regs);
|
kaf24@4103
|
759 break;
|
kaf24@4103
|
760 case 4:
|
kaf24@4103
|
761 if ( get_user(data, (u32 *)regs->esi) )
|
kaf24@4862
|
762 PAGE_FAULT(regs->esi, USER_READ_FAULT);
|
kaf24@5289
|
763 outl_user((u32)data, (u16)regs->edx, v, regs);
|
kaf24@4103
|
764 break;
|
kaf24@4103
|
765 }
|
kaf24@4103
|
766 regs->esi += (regs->eflags & EF_DF) ? -op_bytes : op_bytes;
|
kaf24@4103
|
767 break;
|
kaf24@4103
|
768 }
|
kaf24@4103
|
769
|
kaf24@4103
|
770 if ( rep_prefix && (--regs->ecx != 0) )
|
kaf24@4103
|
771 {
|
kaf24@4103
|
772 if ( !hypercall_preempt_check() )
|
kaf24@4103
|
773 goto continue_io_string;
|
kaf24@4103
|
774 eip = regs->eip;
|
kaf24@4103
|
775 }
|
kaf24@4103
|
776
|
kaf24@4103
|
777 goto done;
|
kaf24@4103
|
778 }
|
kaf24@4103
|
779
|
kaf24@4103
|
780 /* I/O Port and Interrupt Flag instructions. */
|
kaf24@4103
|
781 switch ( opcode )
|
kaf24@4103
|
782 {
|
kaf24@4103
|
783 case 0xe4: /* IN imm8,%al */
|
kaf24@4103
|
784 op_bytes = 1;
|
kaf24@4103
|
785 case 0xe5: /* IN imm8,%eax */
|
kaf24@4103
|
786 port = insn_fetch(u8, 1, eip);
|
kaf24@4103
|
787 exec_in:
|
kaf24@5289
|
788 if ( !guest_io_okay(port, op_bytes, v, regs) )
|
kaf24@4103
|
789 goto fail;
|
kaf24@4103
|
790 switch ( op_bytes )
|
kaf24@4103
|
791 {
|
kaf24@4103
|
792 case 1:
|
kaf24@4103
|
793 regs->eax &= ~0xffUL;
|
kaf24@5289
|
794 regs->eax |= (u8)inb_user(port, v, regs);
|
kaf24@4103
|
795 break;
|
kaf24@4103
|
796 case 2:
|
kaf24@4103
|
797 regs->eax &= ~0xffffUL;
|
kaf24@5289
|
798 regs->eax |= (u16)inw_user(port, v, regs);
|
kaf24@4103
|
799 break;
|
kaf24@4103
|
800 case 4:
|
kaf24@5289
|
801 regs->eax = (u32)inl_user(port, v, regs);
|
kaf24@4103
|
802 break;
|
kaf24@4103
|
803 }
|
kaf24@4103
|
804 goto done;
|
kaf24@4103
|
805
|
kaf24@4103
|
806 case 0xec: /* IN %dx,%al */
|
kaf24@4103
|
807 op_bytes = 1;
|
kaf24@4103
|
808 case 0xed: /* IN %dx,%eax */
|
kaf24@4103
|
809 port = (u16)regs->edx;
|
kaf24@4103
|
810 goto exec_in;
|
kaf24@4103
|
811
|
kaf24@4103
|
812 case 0xe6: /* OUT %al,imm8 */
|
kaf24@4103
|
813 op_bytes = 1;
|
kaf24@4103
|
814 case 0xe7: /* OUT %eax,imm8 */
|
kaf24@4103
|
815 port = insn_fetch(u8, 1, eip);
|
kaf24@4103
|
816 exec_out:
|
kaf24@5289
|
817 if ( !guest_io_okay(port, op_bytes, v, regs) )
|
kaf24@4103
|
818 goto fail;
|
kaf24@4103
|
819 switch ( op_bytes )
|
kaf24@4103
|
820 {
|
kaf24@4103
|
821 case 1:
|
kaf24@5289
|
822 outb_user((u8)regs->eax, port, v, regs);
|
kaf24@4103
|
823 break;
|
kaf24@4103
|
824 case 2:
|
kaf24@5289
|
825 outw_user((u16)regs->eax, port, v, regs);
|
kaf24@4103
|
826 break;
|
kaf24@4103
|
827 case 4:
|
kaf24@5289
|
828 outl_user((u32)regs->eax, port, v, regs);
|
kaf24@4103
|
829 break;
|
kaf24@4103
|
830 }
|
kaf24@4103
|
831 goto done;
|
kaf24@4103
|
832
|
kaf24@4103
|
833 case 0xee: /* OUT %al,%dx */
|
kaf24@4103
|
834 op_bytes = 1;
|
kaf24@4103
|
835 case 0xef: /* OUT %eax,%dx */
|
kaf24@4103
|
836 port = (u16)regs->edx;
|
kaf24@4103
|
837 goto exec_out;
|
kaf24@4103
|
838
|
kaf24@4103
|
839 case 0xfa: /* CLI */
|
kaf24@4103
|
840 case 0xfb: /* STI */
|
kaf24@5289
|
841 if ( v->arch.iopl < (KERNEL_MODE(v, regs) ? 1 : 3) )
|
kaf24@4103
|
842 goto fail;
|
kaf24@4103
|
843 /*
|
kaf24@4103
|
844 * This is just too dangerous to allow, in my opinion. Consider if the
|
kaf24@4103
|
845 * caller then tries to reenable interrupts using POPF: we can't trap
|
kaf24@4103
|
846 * that and we'll end up with hard-to-debug lockups. Fast & loose will
|
kaf24@4103
|
847 * do for us. :-)
|
kaf24@4103
|
848 */
|
kaf24@5289
|
849 /*v->vcpu_info->evtchn_upcall_mask = (opcode == 0xfa);*/
|
kaf24@4103
|
850 goto done;
|
kaf24@4103
|
851
|
kaf24@4103
|
852 case 0x0f: /* Two-byte opcode */
|
kaf24@4103
|
853 break;
|
kaf24@4103
|
854
|
kaf24@4103
|
855 default:
|
kaf24@4103
|
856 goto fail;
|
kaf24@4103
|
857 }
|
kaf24@4103
|
858
|
kaf24@4103
|
859 /* Remaining instructions only emulated from guest kernel. */
|
kaf24@5289
|
860 if ( !KERNEL_MODE(v, regs) )
|
kaf24@3405
|
861 goto fail;
|
kaf24@3311
|
862
|
kaf24@4103
|
863 /* Privileged (ring 0) instructions. */
|
kaf24@4103
|
864 opcode = insn_fetch(u8, 1, eip);
|
kaf24@3405
|
865 switch ( opcode )
|
kaf24@3311
|
866 {
|
kaf24@3405
|
867 case 0x06: /* CLTS */
|
kaf24@3917
|
868 (void)do_fpu_taskswitch(0);
|
kaf24@3405
|
869 break;
|
kaf24@3405
|
870
|
kaf24@3311
|
871 case 0x09: /* WBINVD */
|
kaf24@3861
|
872 /* Ignore the instruction if unprivileged. */
|
kaf24@5289
|
873 if ( !IS_CAPABLE_PHYSDEV(v->domain) )
|
kaf24@3311
|
874 DPRINTK("Non-physdev domain attempted WBINVD.\n");
|
kaf24@3861
|
875 else
|
kaf24@3861
|
876 wbinvd();
|
kaf24@3405
|
877 break;
|
kaf24@3405
|
878
|
kaf24@3405
|
879 case 0x20: /* MOV CR?,<reg> */
|
kaf24@4103
|
880 opcode = insn_fetch(u8, 1, eip);
|
kaf24@5696
|
881 modrm_reg |= (opcode >> 3) & 7;
|
kaf24@5696
|
882 modrm_rm |= (opcode >> 0) & 7;
|
kaf24@5696
|
883 reg = decode_register(modrm_rm, regs, 0);
|
kaf24@5696
|
884 switch ( modrm_reg )
|
kaf24@3405
|
885 {
|
kaf24@3405
|
886 case 0: /* Read CR0 */
|
kaf24@5576
|
887 *reg = v->arch.guest_context.ctrlreg[0];
|
kaf24@3405
|
888 break;
|
kaf24@3405
|
889
|
kaf24@3405
|
890 case 2: /* Read CR2 */
|
kaf24@5576
|
891 *reg = v->arch.guest_context.ctrlreg[2];
|
kaf24@3405
|
892 break;
|
kaf24@3405
|
893
|
kaf24@3405
|
894 case 3: /* Read CR3 */
|
kaf24@5289
|
895 *reg = pagetable_get_paddr(v->arch.guest_table);
|
kaf24@3405
|
896 break;
|
kaf24@3405
|
897
|
kaf24@3405
|
898 default:
|
kaf24@3405
|
899 goto fail;
|
kaf24@3405
|
900 }
|
kaf24@3405
|
901 break;
|
kaf24@3405
|
902
|
kaf24@5696
|
903 case 0x21: /* MOV DR?,<reg> */
|
kaf24@5696
|
904 opcode = insn_fetch(u8, 1, eip);
|
kaf24@5696
|
905 modrm_reg |= (opcode >> 3) & 7;
|
kaf24@5696
|
906 modrm_rm |= (opcode >> 0) & 7;
|
kaf24@5696
|
907 reg = decode_register(modrm_rm, regs, 0);
|
kaf24@5696
|
908 if ( (res = do_get_debugreg(modrm_reg)) > (unsigned long)-256 )
|
kaf24@5696
|
909 goto fail;
|
kaf24@5696
|
910 *reg = res;
|
kaf24@5696
|
911 break;
|
kaf24@5696
|
912
|
kaf24@3405
|
913 case 0x22: /* MOV <reg>,CR? */
|
kaf24@4103
|
914 opcode = insn_fetch(u8, 1, eip);
|
kaf24@5696
|
915 modrm_reg |= (opcode >> 3) & 7;
|
kaf24@5696
|
916 modrm_rm |= (opcode >> 0) & 7;
|
kaf24@5696
|
917 reg = decode_register(modrm_rm, regs, 0);
|
kaf24@5696
|
918 switch ( modrm_reg )
|
kaf24@3405
|
919 {
|
kaf24@3405
|
920 case 0: /* Write CR0 */
|
kaf24@3917
|
921 (void)do_fpu_taskswitch(!!(*reg & X86_CR0_TS));
|
kaf24@3405
|
922 break;
|
kaf24@3405
|
923
|
kaf24@3405
|
924 case 2: /* Write CR2 */
|
kaf24@5576
|
925 v->arch.guest_context.ctrlreg[2] = *reg;
|
kaf24@3405
|
926 break;
|
kaf24@3405
|
927
|
kaf24@3405
|
928 case 3: /* Write CR3 */
|
kaf24@5289
|
929 LOCK_BIGLOCK(v->domain);
|
kaf24@3405
|
930 (void)new_guest_cr3(*reg);
|
kaf24@5289
|
931 UNLOCK_BIGLOCK(v->domain);
|
kaf24@3405
|
932 break;
|
kaf24@3405
|
933
|
kaf24@5723
|
934 default:
|
kaf24@5723
|
935 goto fail;
|
kaf24@5723
|
936 }
|
kaf24@5723
|
937 break;
|
kaf24@5723
|
938
|
kaf24@5696
|
939 case 0x23: /* MOV <reg>,DR? */
|
kaf24@5696
|
940 opcode = insn_fetch(u8, 1, eip);
|
kaf24@5696
|
941 modrm_reg |= (opcode >> 3) & 7;
|
kaf24@5696
|
942 modrm_rm |= (opcode >> 0) & 7;
|
kaf24@5696
|
943 reg = decode_register(modrm_rm, regs, 0);
|
kaf24@5696
|
944 if ( do_set_debugreg(modrm_reg, *reg) != 0 )
|
kaf24@5696
|
945 goto fail;
|
kaf24@5696
|
946 break;
|
kaf24@5696
|
947
|
kaf24@3311
|
948 case 0x30: /* WRMSR */
|
kaf24@3861
|
949 /* Ignore the instruction if unprivileged. */
|
kaf24@5289
|
950 if ( !IS_PRIV(v->domain) )
|
kaf24@3861
|
951 DPRINTK("Non-priv domain attempted WRMSR(%p,%08lx,%08lx).\n",
|
kaf24@4654
|
952 _p(regs->ecx), (long)regs->eax, (long)regs->edx);
|
kaf24@3861
|
953 else if ( wrmsr_user(regs->ecx, regs->eax, regs->edx) )
|
kaf24@3405
|
954 goto fail;
|
kaf24@3405
|
955 break;
|
kaf24@3311
|
956
|
kaf24@3311
|
957 case 0x32: /* RDMSR */
|
kaf24@5289
|
958 if ( !IS_PRIV(v->domain) )
|
kaf24@3861
|
959 DPRINTK("Non-priv domain attempted RDMSR(%p,%08lx,%08lx).\n",
|
kaf24@4654
|
960 _p(regs->ecx), (long)regs->eax, (long)regs->edx);
|
kaf24@3861
|
961 /* Everyone can read the MSR space. */
|
kaf24@3861
|
962 if ( rdmsr_user(regs->ecx, regs->eax, regs->edx) )
|
kaf24@3405
|
963 goto fail;
|
kaf24@3405
|
964 break;
|
kaf24@3405
|
965
|
kaf24@3405
|
966 default:
|
kaf24@3405
|
967 goto fail;
|
kaf24@3311
|
968 }
|
kaf24@3311
|
969
|
kaf24@4103
|
970 done:
|
kaf24@3405
|
971 regs->eip = eip;
|
kaf24@3405
|
972 return EXCRET_fault_fixed;
|
kaf24@3405
|
973
|
kaf24@3405
|
974 fail:
|
kaf24@3311
|
975 return 0;
|
kaf24@3311
|
976 }
|
kaf24@3311
|
977
|
kaf24@4683
|
978 asmlinkage int do_general_protection(struct cpu_user_regs *regs)
|
kaf24@1452
|
979 {
|
kaf24@5289
|
980 struct vcpu *v = current;
|
kaf24@5289
|
981 struct trap_bounce *tb = &v->arch.trap_bounce;
|
kaf24@1452
|
982 trap_info_t *ti;
|
kaf24@1452
|
983 unsigned long fixup;
|
kaf24@1452
|
984
|
kaf24@3089
|
985 DEBUGGER_trap_entry(TRAP_gp_fault, regs);
|
kaf24@3650
|
986
|
kaf24@3169
|
987 if ( regs->error_code & 1 )
|
kaf24@3169
|
988 goto hardware_gp;
|
kaf24@3169
|
989
|
kaf24@3754
|
990 if ( !GUEST_MODE(regs) )
|
kaf24@1452
|
991 goto gp_in_kernel;
|
kaf24@1452
|
992
|
kaf24@1452
|
993 /*
|
kaf24@1452
|
994 * Cunning trick to allow arbitrary "INT n" handling.
|
kaf24@1452
|
995 *
|
kaf24@1452
|
996 * We set DPL == 0 on all vectors in the IDT. This prevents any INT <n>
|
kaf24@1452
|
997 * instruction from trapping to the appropriate vector, when that might not
|
kaf24@1452
|
998 * be expected by Xen or the guest OS. For example, that entry might be for
|
kaf24@1452
|
999 * a fault handler (unlike traps, faults don't increment EIP), or might
|
kaf24@1452
|
1000 * expect an error code on the stack (which a software trap never
|
kaf24@1452
|
1001 * provides), or might be a hardware interrupt handler that doesn't like
|
kaf24@1452
|
1002 * being called spuriously.
|
kaf24@1452
|
1003 *
|
kaf24@1452
|
1004 * Instead, a GPF occurs with the faulting IDT vector in the error code.
|
kaf24@1452
|
1005 * Bit 1 is set to indicate that an IDT entry caused the fault. Bit 0 is
|
kaf24@1452
|
1006 * clear to indicate that it's a software fault, not hardware.
|
kaf24@1452
|
1007 *
|
kaf24@1452
|
1008 * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is
|
kaf24@1452
|
1009 * okay because they can only be triggered by an explicit DPL-checked
|
kaf24@1452
|
1010 * instruction. The DPL specified by the guest OS for these vectors is NOT
|
kaf24@1452
|
1011 * CHECKED!!
|
kaf24@1452
|
1012 */
|
kaf24@3089
|
1013 if ( (regs->error_code & 3) == 2 )
|
kaf24@1452
|
1014 {
|
kaf24@1452
|
1015 /* This fault must be due to <INT n> instruction. */
|
kaf24@4689
|
1016 ti = ¤t->arch.guest_context.trap_ctxt[regs->error_code>>3];
|
kaf24@5289
|
1017 if ( PERMIT_SOFTINT(TI_GET_DPL(ti), v, regs) )
|
kaf24@1452
|
1018 {
|
kaf24@3089
|
1019 tb->flags = TBF_EXCEPTION;
|
kaf24@1452
|
1020 regs->eip += 2;
|
kaf24@1452
|
1021 goto finish_propagation;
|
kaf24@1452
|
1022 }
|
kaf24@1452
|
1023 }
|
kaf24@1816
|
1024
|
kaf24@4103
|
1025 /* Emulate some simple privileged and I/O instructions. */
|
kaf24@3311
|
1026 if ( (regs->error_code == 0) &&
|
kaf24@3311
|
1027 emulate_privileged_op(regs) )
|
kaf24@3311
|
1028 return 0;
|
kaf24@3311
|
1029
|
kaf24@1816
|
1030 #if defined(__i386__)
|
kaf24@5289
|
1031 if ( VM_ASSIST(v->domain, VMASST_TYPE_4gb_segments) &&
|
kaf24@3089
|
1032 (regs->error_code == 0) &&
|
kaf24@2073
|
1033 gpf_emulate_4gb(regs) )
|
kaf24@3052
|
1034 return 0;
|
kaf24@1816
|
1035 #endif
|
kaf24@2971
|
1036
|
kaf24@1452
|
1037 /* Pass on GPF as is. */
|
kaf24@4689
|
1038 ti = ¤t->arch.guest_context.trap_ctxt[TRAP_gp_fault];
|
kaf24@3089
|
1039 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE;
|
kaf24@3089
|
1040 tb->error_code = regs->error_code;
|
kaf24@1452
|
1041 finish_propagation:
|
kaf24@3043
|
1042 tb->cs = ti->cs;
|
kaf24@3043
|
1043 tb->eip = ti->address;
|
kaf24@1452
|
1044 if ( TI_GET_IF(ti) )
|
kaf24@4949
|
1045 tb->flags |= TBF_INTERRUPT;
|
kaf24@3052
|
1046 return 0;
|
kaf24@1452
|
1047
|
kaf24@1452
|
1048 gp_in_kernel:
|
kaf24@1452
|
1049
|
kaf24@1452
|
1050 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
|
kaf24@1452
|
1051 {
|
kaf24@3621
|
1052 DPRINTK("GPF (%04x): %p -> %p\n",
|
kaf24@4654
|
1053 regs->error_code, _p(regs->eip), _p(fixup));
|
kaf24@1452
|
1054 regs->eip = fixup;
|
kaf24@3052
|
1055 return 0;
|
kaf24@1452
|
1056 }
|
kaf24@1452
|
1057
|
kaf24@3089
|
1058 DEBUGGER_trap_fatal(TRAP_gp_fault, regs);
|
cl349@2957
|
1059
|
kaf24@3169
|
1060 hardware_gp:
|
kaf24@3041
|
1061 show_registers(regs);
|
kaf24@3089
|
1062 panic("CPU%d GENERAL PROTECTION FAULT\n[error_code=%04x]\n",
|
kaf24@3089
|
1063 smp_processor_id(), regs->error_code);
|
kaf24@3052
|
1064 return 0;
|
kaf24@1452
|
1065 }
|
kaf24@1452
|
1066
|
kaf24@3695
|
1067 unsigned long nmi_softirq_reason;
|
kaf24@3695
|
1068 static void nmi_softirq(void)
|
kaf24@1452
|
1069 {
|
kaf24@3695
|
1070 if ( dom0 == NULL )
|
kaf24@3695
|
1071 return;
|
kaf24@3695
|
1072
|
kaf24@3695
|
1073 if ( test_and_clear_bit(0, &nmi_softirq_reason) )
|
kaf24@5289
|
1074 send_guest_virq(dom0->vcpu[0], VIRQ_PARITY_ERR);
|
kaf24@3695
|
1075
|
kaf24@3695
|
1076 if ( test_and_clear_bit(1, &nmi_softirq_reason) )
|
kaf24@5289
|
1077 send_guest_virq(dom0->vcpu[0], VIRQ_IO_ERR);
|
kaf24@1452
|
1078 }
|
kaf24@1452
|
1079
|
kaf24@4683
|
1080 asmlinkage void mem_parity_error(struct cpu_user_regs *regs)
|
kaf24@1452
|
1081 {
|
kaf24@3695
|
1082 /* Clear and disable the parity-error line. */
|
kaf24@3695
|
1083 outb((inb(0x61)&15)|4,0x61);
|
kaf24@3695
|
1084
|
kaf24@3695
|
1085 switch ( opt_nmi[0] )
|
kaf24@3695
|
1086 {
|
kaf24@3695
|
1087 case 'd': /* 'dom0' */
|
kaf24@3695
|
1088 set_bit(0, &nmi_softirq_reason);
|
kaf24@3695
|
1089 raise_softirq(NMI_SOFTIRQ);
|
kaf24@3695
|
1090 case 'i': /* 'ignore' */
|
kaf24@3695
|
1091 break;
|
kaf24@3695
|
1092 default: /* 'fatal' */
|
kaf24@3695
|
1093 console_force_unlock();
|
kaf24@3695
|
1094 printk("\n\nNMI - MEMORY ERROR\n");
|
kaf24@3695
|
1095 fatal_trap(TRAP_nmi, regs);
|
kaf24@3695
|
1096 }
|
kaf24@1452
|
1097 }
|
kaf24@2041
|
1098
|
kaf24@4683
|
1099 asmlinkage void io_check_error(struct cpu_user_regs *regs)
|
kaf24@1452
|
1100 {
|
kaf24@3695
|
1101 /* Clear and disable the I/O-error line. */
|
kaf24@3695
|
1102 outb((inb(0x61)&15)|8,0x61);
|
kaf24@2041
|
1103
|
kaf24@3695
|
1104 switch ( opt_nmi[0] )
|
kaf24@3695
|
1105 {
|
kaf24@3695
|
1106 case 'd': /* 'dom0' */
|
kaf24@3695
|
1107 set_bit(0, &nmi_softirq_reason);
|
kaf24@3695
|
1108 raise_softirq(NMI_SOFTIRQ);
|
kaf24@3695
|
1109 case 'i': /* 'ignore' */
|
kaf24@3695
|
1110 break;
|
kaf24@3695
|
1111 default: /* 'fatal' */
|
kaf24@3695
|
1112 console_force_unlock();
|
kaf24@3695
|
1113 printk("\n\nNMI - I/O ERROR\n");
|
kaf24@3695
|
1114 fatal_trap(TRAP_nmi, regs);
|
kaf24@3695
|
1115 }
|
kaf24@1452
|
1116 }
|
kaf24@1452
|
1117
|
kaf24@3669
|
1118 static void unknown_nmi_error(unsigned char reason)
|
kaf24@1452
|
1119 {
|
kaf24@1452
|
1120 printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
|
kaf24@1452
|
1121 printk("Dazed and confused, but trying to continue\n");
|
kaf24@1452
|
1122 printk("Do you have a strange power saving mode enabled?\n");
|
kaf24@1452
|
1123 }
|
kaf24@1452
|
1124
|
kaf24@4683
|
1125 asmlinkage void do_nmi(struct cpu_user_regs *regs, unsigned long reason)
|
kaf24@1452
|
1126 {
|
kaf24@1452
|
1127 ++nmi_count(smp_processor_id());
|
kaf24@1452
|
1128
|
kaf24@1452
|
1129 if ( nmi_watchdog )
|
kaf24@1452
|
1130 nmi_watchdog_tick(regs);
|
kaf24@3695
|
1131
|
kaf24@3695
|
1132 if ( reason & 0x80 )
|
kaf24@3695
|
1133 mem_parity_error(regs);
|
kaf24@3695
|
1134 else if ( reason & 0x40 )
|
kaf24@3695
|
1135 io_check_error(regs);
|
kaf24@3695
|
1136 else if ( !nmi_watchdog )
|
kaf24@3669
|
1137 unknown_nmi_error((unsigned char)(reason&0xff));
|
kaf24@1452
|
1138 }
|
kaf24@1452
|
1139
|
kaf24@4683
|
1140 asmlinkage int math_state_restore(struct cpu_user_regs *regs)
|
kaf24@1452
|
1141 {
|
kaf24@1452
|
1142 /* Prevent recursion. */
|
kaf24@1452
|
1143 clts();
|
kaf24@1452
|
1144
|
cl349@4856
|
1145 setup_fpu(current);
|
kaf24@1452
|
1146
|
kaf24@5576
|
1147 if ( current->arch.guest_context.ctrlreg[0] & X86_CR0_TS )
|
kaf24@1452
|
1148 {
|
kaf24@3677
|
1149 struct trap_bounce *tb = ¤t->arch.trap_bounce;
|
kaf24@4689
|
1150 tb->flags = TBF_EXCEPTION;
|
kaf24@4689
|
1151 tb->cs = current->arch.guest_context.trap_ctxt[7].cs;
|
kaf24@4689
|
1152 tb->eip = current->arch.guest_context.trap_ctxt[7].address;
|
kaf24@5576
|
1153 current->arch.guest_context.ctrlreg[0] &= ~X86_CR0_TS;
|
kaf24@1452
|
1154 }
|
kaf24@3052
|
1155
|
kaf24@3052
|
1156 return EXCRET_fault_fixed;
|
kaf24@1452
|
1157 }
|
kaf24@1452
|
1158
|
kaf24@4683
|
1159 asmlinkage int do_debug(struct cpu_user_regs *regs)
|
kaf24@1452
|
1160 {
|
kaf24@3602
|
1161 unsigned long condition;
|
kaf24@5289
|
1162 struct vcpu *v = current;
|
kaf24@5289
|
1163 struct trap_bounce *tb = &v->arch.trap_bounce;
|
kaf24@1452
|
1164
|
kaf24@3602
|
1165 __asm__ __volatile__("mov %%db6,%0" : "=r" (condition));
|
kaf24@1452
|
1166
|
kaf24@1452
|
1167 /* Mask out spurious debug traps due to lazy DR7 setting */
|
kaf24@1452
|
1168 if ( (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) &&
|
kaf24@5289
|
1169 (v->arch.guest_context.debugreg[7] == 0) )
|
kaf24@1452
|
1170 {
|
kaf24@3602
|
1171 __asm__("mov %0,%%db7" : : "r" (0UL));
|
kaf24@3052
|
1172 goto out;
|
kaf24@1452
|
1173 }
|
kaf24@1452
|
1174
|
cl349@4339
|
1175 DEBUGGER_trap_entry(TRAP_debug, regs);
|
cl349@4339
|
1176
|
kaf24@3754
|
1177 if ( !GUEST_MODE(regs) )
|
kaf24@1452
|
1178 {
|
kaf24@1452
|
1179 /* Clear TF just for absolute sanity. */
|
kaf24@1452
|
1180 regs->eflags &= ~EF_TF;
|
kaf24@1452
|
1181 /*
|
kaf24@1590
|
1182 * We ignore watchpoints when they trigger within Xen. This may happen
|
kaf24@1590
|
1183 * when a buffer is passed to us which previously had a watchpoint set
|
kaf24@1590
|
1184 * on it. No need to bump EIP; the only faulting trap is an instruction
|
kaf24@1590
|
1185 * breakpoint, which can't happen to us.
|
kaf24@1452
|
1186 */
|
kaf24@3052
|
1187 goto out;
|
kmacy@4118
|
1188 }
|
kaf24@1452
|
1189
|
kaf24@1452
|
1190 /* Save debug status register where guest OS can peek at it */
|
kaf24@5289
|
1191 v->arch.guest_context.debugreg[6] = condition;
|
kaf24@1452
|
1192
|
kaf24@3089
|
1193 tb->flags = TBF_EXCEPTION;
|
kaf24@5289
|
1194 tb->cs = v->arch.guest_context.trap_ctxt[TRAP_debug].cs;
|
kaf24@5289
|
1195 tb->eip = v->arch.guest_context.trap_ctxt[TRAP_debug].address;
|
kaf24@3052
|
1196
|
kaf24@3052
|
1197 out:
|
kaf24@3052
|
1198 return EXCRET_not_a_fault;
|
kaf24@1452
|
1199 }
|
kaf24@1452
|
1200
|
kaf24@4683
|
1201 asmlinkage int do_spurious_interrupt_bug(struct cpu_user_regs *regs)
|
kaf24@3052
|
1202 {
|
kaf24@3052
|
1203 return EXCRET_not_a_fault;
|
kaf24@3052
|
1204 }
|
kaf24@1452
|
1205
|
kaf24@1452
|
1206 void set_intr_gate(unsigned int n, void *addr)
|
kaf24@3669
|
1207 {
|
kaf24@3847
|
1208 #ifdef __i386__
|
kaf24@3847
|
1209 int i;
|
kaf24@3847
|
1210 /* Keep secondary tables in sync with IRQ updates. */
|
kaf24@3847
|
1211 for ( i = 1; i < NR_CPUS; i++ )
|
kaf24@3847
|
1212 if ( idt_tables[i] != NULL )
|
kaf24@3847
|
1213 _set_gate(&idt_tables[i][n], 14, 0, addr);
|
kaf24@3847
|
1214 #endif
|
kaf24@3847
|
1215 _set_gate(&idt_table[n], 14, 0, addr);
|
kaf24@3669
|
1216 }
|
kaf24@3669
|
1217
|
kaf24@3602
|
1218 void set_system_gate(unsigned int n, void *addr)
|
kaf24@1452
|
1219 {
|
kaf24@1452
|
1220 _set_gate(idt_table+n,14,3,addr);
|
kaf24@1452
|
1221 }
|
kaf24@1452
|
1222
|
kaf24@3602
|
1223 void set_task_gate(unsigned int n, unsigned int sel)
|
kaf24@1452
|
1224 {
|
kaf24@1452
|
1225 idt_table[n].a = sel << 16;
|
kaf24@1452
|
1226 idt_table[n].b = 0x8500;
|
kaf24@1452
|
1227 }
|
kaf24@1452
|
1228
|
kaf24@1452
|
1229 void set_tss_desc(unsigned int n, void *addr)
|
kaf24@1452
|
1230 {
|
kaf24@3075
|
1231 _set_tssldt_desc(
|
kaf24@4972
|
1232 gdt_table + __TSS(n) - FIRST_RESERVED_GDT_ENTRY,
|
kaf24@3623
|
1233 (unsigned long)addr,
|
kaf24@3075
|
1234 offsetof(struct tss_struct, __cacheline_filler) - 1,
|
kaf24@3623
|
1235 9);
|
kaf24@1452
|
1236 }
|
kaf24@1452
|
1237
|
kaf24@1452
|
1238 void __init trap_init(void)
|
kaf24@1452
|
1239 {
|
kaf24@3695
|
1240 extern void percpu_traps_init(void);
|
kaf24@1452
|
1241
|
kaf24@1452
|
1242 /*
|
kaf24@1452
|
1243 * Note that interrupt gates are always used, rather than trap gates. We
|
kaf24@1452
|
1244 * must have interrupts disabled until DS/ES/FS/GS are saved because the
|
kaf24@1452
|
1245 * first activation must have the "bad" value(s) for these registers and
|
kaf24@1452
|
1246 * we may lose them if another activation is installed before they are
|
kaf24@1452
|
1247 * saved. The page-fault handler also needs interrupts disabled until %cr2
|
kaf24@1452
|
1248 * has been read and saved on the stack.
|
kaf24@1452
|
1249 */
|
kaf24@3041
|
1250 set_intr_gate(TRAP_divide_error,÷_error);
|
kaf24@3041
|
1251 set_intr_gate(TRAP_debug,&debug);
|
kaf24@3041
|
1252 set_intr_gate(TRAP_nmi,&nmi);
|
kaf24@3041
|
1253 set_system_gate(TRAP_int3,&int3); /* usable from all privileges */
|
kaf24@3041
|
1254 set_system_gate(TRAP_overflow,&overflow); /* usable from all privileges */
|
kaf24@3041
|
1255 set_intr_gate(TRAP_bounds,&bounds);
|
kaf24@3041
|
1256 set_intr_gate(TRAP_invalid_op,&invalid_op);
|
kaf24@3041
|
1257 set_intr_gate(TRAP_no_device,&device_not_available);
|
kaf24@3041
|
1258 set_intr_gate(TRAP_copro_seg,&coprocessor_segment_overrun);
|
kaf24@3041
|
1259 set_intr_gate(TRAP_invalid_tss,&invalid_TSS);
|
kaf24@3041
|
1260 set_intr_gate(TRAP_no_segment,&segment_not_present);
|
kaf24@3041
|
1261 set_intr_gate(TRAP_stack_error,&stack_segment);
|
kaf24@3041
|
1262 set_intr_gate(TRAP_gp_fault,&general_protection);
|
kaf24@3041
|
1263 set_intr_gate(TRAP_page_fault,&page_fault);
|
kaf24@3041
|
1264 set_intr_gate(TRAP_spurious_int,&spurious_interrupt_bug);
|
kaf24@3041
|
1265 set_intr_gate(TRAP_copro_error,&coprocessor_error);
|
kaf24@3041
|
1266 set_intr_gate(TRAP_alignment_check,&alignment_check);
|
kaf24@3041
|
1267 set_intr_gate(TRAP_machine_check,&machine_check);
|
kaf24@3041
|
1268 set_intr_gate(TRAP_simd_error,&simd_coprocessor_error);
|
kaf24@1452
|
1269
|
kaf24@3695
|
1270 percpu_traps_init();
|
kaf24@3695
|
1271
|
kaf24@3695
|
1272 cpu_init();
|
kaf24@2047
|
1273
|
kaf24@2047
|
1274 open_softirq(NMI_SOFTIRQ, nmi_softirq);
|
kaf24@1452
|
1275 }
|
kaf24@1452
|
1276
|
kaf24@1452
|
1277
|
kaf24@1452
|
1278 long do_set_trap_table(trap_info_t *traps)
|
kaf24@1452
|
1279 {
|
kaf24@1452
|
1280 trap_info_t cur;
|
kaf24@4689
|
1281 trap_info_t *dst = current->arch.guest_context.trap_ctxt;
|
kaf24@4105
|
1282 long rc = 0;
|
kaf24@1452
|
1283
|
cl349@2998
|
1284 LOCK_BIGLOCK(current->domain);
|
kaf24@1452
|
1285
|
kaf24@1452
|
1286 for ( ; ; )
|
kaf24@1452
|
1287 {
|
kaf24@3139
|
1288 if ( hypercall_preempt_check() )
|
kaf24@3139
|
1289 {
|
kaf24@4105
|
1290 rc = hypercall1_create_continuation(
|
kaf24@3702
|
1291 __HYPERVISOR_set_trap_table, traps);
|
kaf24@4105
|
1292 break;
|
kaf24@3139
|
1293 }
|
kaf24@3091
|
1294
|
kaf24@4105
|
1295 if ( copy_from_user(&cur, traps, sizeof(cur)) )
|
kaf24@4105
|
1296 {
|
kaf24@4105
|
1297 rc = -EFAULT;
|
kaf24@4105
|
1298 break;
|
kaf24@4105
|
1299 }
|
kaf24@1452
|
1300
|
kaf24@4105
|
1301 if ( cur.address == 0 )
|
kaf24@4105
|
1302 break;
|
kaf24@1452
|
1303
|
kaf24@4105
|
1304 if ( !VALID_CODESEL(cur.cs) )
|
kaf24@4105
|
1305 {
|
kaf24@4105
|
1306 rc = -EPERM;
|
kaf24@4105
|
1307 break;
|
kaf24@4105
|
1308 }
|
kaf24@1452
|
1309
|
kaf24@4930
|
1310 memcpy(&dst[cur.vector], &cur, sizeof(cur));
|
kaf24@4930
|
1311
|
kaf24@4930
|
1312 if ( cur.vector == 0x80 )
|
kaf24@4930
|
1313 init_int80_direct_trap(current);
|
kaf24@4930
|
1314
|
kaf24@1452
|
1315 traps++;
|
kaf24@1452
|
1316 }
|
kaf24@1452
|
1317
|
cl349@2998
|
1318 UNLOCK_BIGLOCK(current->domain);
|
kaf24@1452
|
1319
|
kaf24@4105
|
1320 return rc;
|
kaf24@1452
|
1321 }
|
kaf24@1452
|
1322
|
kaf24@1452
|
1323
|
kaf24@5289
|
1324 long set_debugreg(struct vcpu *p, int reg, unsigned long value)
|
kaf24@1452
|
1325 {
|
kaf24@1452
|
1326 int i;
|
kaf24@1452
|
1327
|
kaf24@1452
|
1328 switch ( reg )
|
kaf24@1452
|
1329 {
|
kaf24@1452
|
1330 case 0:
|
kaf24@4573
|
1331 if ( !access_ok(value, sizeof(long)) )
|
kaf24@4572
|
1332 return -EPERM;
|
kaf24@1452
|
1333 if ( p == current )
|
kaf24@3602
|
1334 __asm__ ( "mov %0, %%db0" : : "r" (value) );
|
kaf24@1452
|
1335 break;
|
kaf24@1452
|
1336 case 1:
|
kaf24@4573
|
1337 if ( !access_ok(value, sizeof(long)) )
|
kaf24@4572
|
1338 return -EPERM;
|
kaf24@1452
|
1339 if ( p == current )
|
kaf24@3602
|
1340 __asm__ ( "mov %0, %%db1" : : "r" (value) );
|
kaf24@1452
|
1341 break;
|
kaf24@1452
|
1342 case 2:
|
kaf24@4573
|
1343 if ( !access_ok(value, sizeof(long)) )
|
kaf24@4572
|
1344 return -EPERM;
|
kaf24@1452
|
1345 if ( p == current )
|
kaf24@3602
|
1346 __asm__ ( "mov %0, %%db2" : : "r" (value) );
|
kaf24@1452
|
1347 break;
|
kaf24@1452
|
1348 case 3:
|
kaf24@4573
|
1349 if ( !access_ok(value, sizeof(long)) )
|
kaf24@4572
|
1350 return -EPERM;
|
kaf24@1452
|
1351 if ( p == current )
|
kaf24@3602
|
1352 __asm__ ( "mov %0, %%db3" : : "r" (value) );
|
kaf24@1452
|
1353 break;
|
kaf24@1452
|
1354 case 6:
|
kaf24@1452
|
1355 /*
|
kaf24@1452
|
1356 * DR6: Bits 4-11,16-31 reserved (set to 1).
|
kaf24@1452
|
1357 * Bit 12 reserved (set to 0).
|
kaf24@1452
|
1358 */
|
kaf24@1452
|
1359 value &= 0xffffefff; /* reserved bits => 0 */
|
kaf24@1452
|
1360 value |= 0xffff0ff0; /* reserved bits => 1 */
|
kaf24@1452
|
1361 if ( p == current )
|
kaf24@3602
|
1362 __asm__ ( "mov %0, %%db6" : : "r" (value) );
|
kaf24@1452
|
1363 break;
|
kaf24@1452
|
1364 case 7:
|
kaf24@1452
|
1365 /*
|
kaf24@1452
|
1366 * DR7: Bit 10 reserved (set to 1).
|
kaf24@1452
|
1367 * Bits 11-12,14-15 reserved (set to 0).
|
kaf24@1452
|
1368 * Privileged bits:
|
kaf24@1452
|
1369 * GD (bit 13): must be 0.
|
kaf24@1452
|
1370 * R/Wn (bits 16-17,20-21,24-25,28-29): mustn't be 10.
|
kaf24@1452
|
1371 * LENn (bits 18-19,22-23,26-27,30-31): mustn't be 10.
|
kaf24@1452
|
1372 */
|
kaf24@1452
|
1373 /* DR7 == 0 => debugging disabled for this domain. */
|
kaf24@1452
|
1374 if ( value != 0 )
|
kaf24@1452
|
1375 {
|
kaf24@1452
|
1376 value &= 0xffff27ff; /* reserved bits => 0 */
|
kaf24@1452
|
1377 value |= 0x00000400; /* reserved bits => 1 */
|
kaf24@1452
|
1378 if ( (value & (1<<13)) != 0 ) return -EPERM;
|
kaf24@1452
|
1379 for ( i = 0; i < 16; i += 2 )
|
kaf24@1452
|
1380 if ( ((value >> (i+16)) & 3) == 2 ) return -EPERM;
|
kaf24@1452
|
1381 }
|
kaf24@1452
|
1382 if ( p == current )
|
kaf24@3602
|
1383 __asm__ ( "mov %0, %%db7" : : "r" (value) );
|
kaf24@1452
|
1384 break;
|
kaf24@1452
|
1385 default:
|
kaf24@1452
|
1386 return -EINVAL;
|
kaf24@1452
|
1387 }
|
kaf24@1452
|
1388
|
kaf24@4689
|
1389 p->arch.guest_context.debugreg[reg] = value;
|
kaf24@1452
|
1390 return 0;
|
kaf24@1452
|
1391 }
|
kaf24@1452
|
1392
|
kaf24@1452
|
1393 long do_set_debugreg(int reg, unsigned long value)
|
kaf24@1452
|
1394 {
|
kaf24@1452
|
1395 return set_debugreg(current, reg, value);
|
kaf24@1452
|
1396 }
|
kaf24@1452
|
1397
|
kaf24@1452
|
1398 unsigned long do_get_debugreg(int reg)
|
kaf24@1452
|
1399 {
|
kaf24@1452
|
1400 if ( (reg < 0) || (reg > 7) ) return -EINVAL;
|
kaf24@4689
|
1401 return current->arch.guest_context.debugreg[reg];
|
kaf24@1452
|
1402 }
|
kaf24@1672
|
1403
|
kaf24@3914
|
1404 /*
|
kaf24@3914
|
1405 * Local variables:
|
kaf24@3914
|
1406 * mode: C
|
kaf24@3914
|
1407 * c-set-style: "BSD"
|
kaf24@3914
|
1408 * c-basic-offset: 4
|
kaf24@3914
|
1409 * tab-width: 4
|
kaf24@3914
|
1410 * indent-tabs-mode: nil
|
kaf24@3988
|
1411 * End:
|
kaf24@3914
|
1412 */
|