ia64/xen-unstable

view xen/arch/x86/x86_64/traps.c @ 12215:46fad06ab0b3

[XEN] Fix x86/64 build.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Nov 01 18:48:57 2006 +0000 (2006-11-01)
parents 7b5115221dfc
children e3abede54214
line source
2 #include <xen/config.h>
3 #include <xen/version.h>
4 #include <xen/init.h>
5 #include <xen/sched.h>
6 #include <xen/lib.h>
7 #include <xen/errno.h>
8 #include <xen/mm.h>
9 #include <xen/irq.h>
10 #include <xen/symbols.h>
11 #include <xen/console.h>
12 #include <xen/sched.h>
13 #include <xen/shutdown.h>
14 #include <xen/nmi.h>
15 #include <asm/current.h>
16 #include <asm/flushtlb.h>
17 #include <asm/msr.h>
18 #include <asm/page.h>
19 #include <asm/shadow.h>
20 #include <asm/hvm/hvm.h>
21 #include <asm/hvm/support.h>
23 #include <public/callback.h>
25 static void print_xen_info(void)
26 {
27 char taint_str[TAINT_STRING_MAX_LEN];
28 char debug = 'n';
30 #ifndef NDEBUG
31 debug = 'y';
32 #endif
34 printk("----[ Xen-%d.%d%s x86_64 debug=%c %s ]----\n",
35 xen_major_version(), xen_minor_version(), xen_extra_version(),
36 debug, print_tainted(taint_str));
37 }
39 void show_registers(struct cpu_user_regs *regs)
40 {
41 struct cpu_user_regs fault_regs = *regs;
42 unsigned long fault_crs[8];
43 const char *context;
45 if ( is_hvm_vcpu(current) && guest_mode(regs) )
46 {
47 context = "hvm";
48 hvm_store_cpu_guest_regs(current, &fault_regs, fault_crs);
49 }
50 else
51 {
52 if ( guest_mode(regs) )
53 {
54 context = "guest";
55 fault_crs[2] = current->vcpu_info->arch.cr2;
56 }
57 else
58 {
59 context = "hypervisor";
60 fault_crs[2] = read_cr2();
61 }
63 fault_crs[0] = read_cr0();
64 fault_crs[3] = read_cr3();
65 fault_crs[4] = read_cr4();
66 fault_regs.ds = read_segment_register(ds);
67 fault_regs.es = read_segment_register(es);
68 fault_regs.fs = read_segment_register(fs);
69 fault_regs.gs = read_segment_register(gs);
70 }
72 print_xen_info();
73 printk("CPU: %d\nRIP: %04x:[<%016lx>]",
74 smp_processor_id(), fault_regs.cs, fault_regs.rip);
75 if ( !guest_mode(regs) )
76 print_symbol(" %s", fault_regs.rip);
77 printk("\nRFLAGS: %016lx CONTEXT: %s\n", fault_regs.rflags, context);
78 printk("rax: %016lx rbx: %016lx rcx: %016lx\n",
79 fault_regs.rax, fault_regs.rbx, fault_regs.rcx);
80 printk("rdx: %016lx rsi: %016lx rdi: %016lx\n",
81 fault_regs.rdx, fault_regs.rsi, fault_regs.rdi);
82 printk("rbp: %016lx rsp: %016lx r8: %016lx\n",
83 fault_regs.rbp, fault_regs.rsp, fault_regs.r8);
84 printk("r9: %016lx r10: %016lx r11: %016lx\n",
85 fault_regs.r9, fault_regs.r10, fault_regs.r11);
86 printk("r12: %016lx r13: %016lx r14: %016lx\n",
87 fault_regs.r12, fault_regs.r13, fault_regs.r14);
88 printk("r15: %016lx cr0: %016lx cr4: %016lx\n",
89 fault_regs.r15, fault_crs[0], fault_crs[4]);
90 printk("cr3: %016lx cr2: %016lx\n", fault_crs[3], fault_crs[2]);
91 printk("ds: %04x es: %04x fs: %04x gs: %04x "
92 "ss: %04x cs: %04x\n",
93 fault_regs.ds, fault_regs.es, fault_regs.fs,
94 fault_regs.gs, fault_regs.ss, fault_regs.cs);
95 }
97 void show_page_walk(unsigned long addr)
98 {
99 unsigned long pfn, mfn = read_cr3() >> PAGE_SHIFT;
100 l4_pgentry_t l4e, *l4t;
101 l3_pgentry_t l3e, *l3t;
102 l2_pgentry_t l2e, *l2t;
103 l1_pgentry_t l1e, *l1t;
105 printk("Pagetable walk from %016lx:\n", addr);
107 l4t = mfn_to_virt(mfn);
108 l4e = l4t[l4_table_offset(addr)];
109 mfn = l4e_get_pfn(l4e);
110 pfn = get_gpfn_from_mfn(mfn);
111 printk(" L4[0x%03lx] = %"PRIpte" %016lx\n",
112 l4_table_offset(addr), l4e_get_intpte(l4e), pfn);
113 if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
114 return;
116 l3t = mfn_to_virt(mfn);
117 l3e = l3t[l3_table_offset(addr)];
118 mfn = l3e_get_pfn(l3e);
119 pfn = get_gpfn_from_mfn(mfn);
120 printk(" L3[0x%03lx] = %"PRIpte" %016lx\n",
121 l3_table_offset(addr), l3e_get_intpte(l3e), pfn);
122 if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
123 return;
125 l2t = mfn_to_virt(mfn);
126 l2e = l2t[l2_table_offset(addr)];
127 mfn = l2e_get_pfn(l2e);
128 pfn = get_gpfn_from_mfn(mfn);
129 printk(" L2[0x%03lx] = %"PRIpte" %016lx %s\n",
130 l2_table_offset(addr), l2e_get_intpte(l2e), pfn,
131 (l2e_get_flags(l2e) & _PAGE_PSE) ? "(PSE)" : "");
132 if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ||
133 (l2e_get_flags(l2e) & _PAGE_PSE) )
134 return;
136 l1t = mfn_to_virt(mfn);
137 l1e = l1t[l1_table_offset(addr)];
138 mfn = l1e_get_pfn(l1e);
139 pfn = get_gpfn_from_mfn(mfn);
140 printk(" L1[0x%03lx] = %"PRIpte" %016lx\n",
141 l1_table_offset(addr), l1e_get_intpte(l1e), pfn);
142 }
144 asmlinkage void double_fault(void);
145 asmlinkage void do_double_fault(struct cpu_user_regs *regs)
146 {
147 unsigned int cpu, tr;
149 asm ( "str %0" : "=r" (tr) );
150 cpu = ((tr >> 3) - __FIRST_TSS_ENTRY) >> 2;
152 watchdog_disable();
154 console_force_unlock();
156 /* Find information saved during fault and dump it to the console. */
157 printk("*** DOUBLE FAULT ***\n");
158 print_xen_info();
159 printk("CPU: %d\nRIP: %04x:[<%016lx>]",
160 cpu, regs->cs, regs->rip);
161 print_symbol(" %s", regs->rip);
162 printk("\nRFLAGS: %016lx\n", regs->rflags);
163 printk("rax: %016lx rbx: %016lx rcx: %016lx\n",
164 regs->rax, regs->rbx, regs->rcx);
165 printk("rdx: %016lx rsi: %016lx rdi: %016lx\n",
166 regs->rdx, regs->rsi, regs->rdi);
167 printk("rbp: %016lx rsp: %016lx r8: %016lx\n",
168 regs->rbp, regs->rsp, regs->r8);
169 printk("r9: %016lx r10: %016lx r11: %016lx\n",
170 regs->r9, regs->r10, regs->r11);
171 printk("r12: %016lx r13: %016lx r14: %016lx\n",
172 regs->r12, regs->r13, regs->r14);
173 printk("r15: %016lx\n", regs->r15);
174 show_stack_overflow(regs->rsp);
175 printk("************************************\n");
176 printk("CPU%d DOUBLE FAULT -- system shutdown\n", cpu);
177 printk("System needs manual reset.\n");
178 printk("************************************\n");
180 /* Lock up the console to prevent spurious output from other CPUs. */
181 console_force_lock();
183 /* Wait for manual reset. */
184 machine_halt();
185 }
187 void toggle_guest_mode(struct vcpu *v)
188 {
189 v->arch.flags ^= TF_kernel_mode;
190 __asm__ __volatile__ ( "swapgs" );
191 update_cr3(v);
192 #ifdef USER_MAPPINGS_ARE_GLOBAL
193 /* Don't flush user global mappings from the TLB. Don't tick TLB clock. */
194 __asm__ __volatile__ ( "mov %0, %%cr3" : : "r" (v->arch.cr3) : "memory" );
195 #else
196 write_ptbase(v);
197 #endif
198 }
200 unsigned long do_iret(void)
201 {
202 struct cpu_user_regs *regs = guest_cpu_user_regs();
203 struct iret_context iret_saved;
204 struct vcpu *v = current;
206 if ( unlikely(copy_from_user(&iret_saved, (void *)regs->rsp,
207 sizeof(iret_saved))) )
208 {
209 gdprintk(XENLOG_ERR, "Fault while reading IRET context from "
210 "guest stack\n");
211 domain_crash_synchronous();
212 }
214 /* Returning to user mode? */
215 if ( (iret_saved.cs & 3) == 3 )
216 {
217 if ( unlikely(pagetable_is_null(v->arch.guest_table_user)) )
218 {
219 gdprintk(XENLOG_ERR, "Guest switching to user mode with no "
220 "user page tables\n");
221 domain_crash_synchronous();
222 }
223 toggle_guest_mode(v);
224 }
226 regs->rip = iret_saved.rip;
227 regs->cs = iret_saved.cs | 3; /* force guest privilege */
228 regs->rflags = (iret_saved.rflags & ~(EF_IOPL|EF_VM)) | EF_IE;
229 regs->rsp = iret_saved.rsp;
230 regs->ss = iret_saved.ss | 3; /* force guest privilege */
232 if ( !(iret_saved.flags & VGCF_in_syscall) )
233 {
234 regs->entry_vector = 0;
235 regs->r11 = iret_saved.r11;
236 regs->rcx = iret_saved.rcx;
237 }
239 /* No longer in NMI context. */
240 clear_bit(_VCPUF_nmi_masked, &current->vcpu_flags);
242 /* Restore upcall mask from supplied EFLAGS.IF. */
243 current->vcpu_info->evtchn_upcall_mask = !(iret_saved.rflags & EF_IE);
245 /* Saved %rax gets written back to regs->rax in entry.S. */
246 return iret_saved.rax;
247 }
249 asmlinkage void syscall_enter(void);
250 void __init percpu_traps_init(void)
251 {
252 char *stack_bottom, *stack;
253 int cpu = smp_processor_id();
255 if ( cpu == 0 )
256 {
257 /* Specify dedicated interrupt stacks for NMIs and double faults. */
258 set_intr_gate(TRAP_double_fault, &double_fault);
259 idt_table[TRAP_double_fault].a |= 1UL << 32; /* IST1 */
260 idt_table[TRAP_nmi].a |= 2UL << 32; /* IST2 */
261 }
263 stack_bottom = (char *)get_stack_bottom();
264 stack = (char *)((unsigned long)stack_bottom & ~(STACK_SIZE - 1));
266 /* Double-fault handler has its own per-CPU 1kB stack. */
267 init_tss[cpu].ist[0] = (unsigned long)&stack[1024];
269 /* NMI handler has its own per-CPU 1kB stack. */
270 init_tss[cpu].ist[1] = (unsigned long)&stack[2048];
272 /*
273 * Trampoline for SYSCALL entry from long mode.
274 */
276 /* Skip the NMI and DF stacks. */
277 stack = &stack[2048];
278 wrmsr(MSR_LSTAR, (unsigned long)stack, ((unsigned long)stack>>32));
280 /* movq %rsp, saversp(%rip) */
281 stack[0] = 0x48;
282 stack[1] = 0x89;
283 stack[2] = 0x25;
284 *(u32 *)&stack[3] = (stack_bottom - &stack[7]) - 16;
286 /* leaq saversp(%rip), %rsp */
287 stack[7] = 0x48;
288 stack[8] = 0x8d;
289 stack[9] = 0x25;
290 *(u32 *)&stack[10] = (stack_bottom - &stack[14]) - 16;
292 /* pushq %r11 */
293 stack[14] = 0x41;
294 stack[15] = 0x53;
296 /* pushq $__GUEST_CS64 */
297 stack[16] = 0x68;
298 *(u32 *)&stack[17] = __GUEST_CS64;
300 /* jmp syscall_enter */
301 stack[21] = 0xe9;
302 *(u32 *)&stack[22] = (char *)syscall_enter - &stack[26];
304 /*
305 * Trampoline for SYSCALL entry from compatibility mode.
306 */
308 /* Skip the long-mode entry trampoline. */
309 stack = &stack[26];
310 wrmsr(MSR_CSTAR, (unsigned long)stack, ((unsigned long)stack>>32));
312 /* movq %rsp, saversp(%rip) */
313 stack[0] = 0x48;
314 stack[1] = 0x89;
315 stack[2] = 0x25;
316 *(u32 *)&stack[3] = (stack_bottom - &stack[7]) - 16;
318 /* leaq saversp(%rip), %rsp */
319 stack[7] = 0x48;
320 stack[8] = 0x8d;
321 stack[9] = 0x25;
322 *(u32 *)&stack[10] = (stack_bottom - &stack[14]) - 16;
324 /* pushq %r11 */
325 stack[14] = 0x41;
326 stack[15] = 0x53;
328 /* pushq $__GUEST_CS32 */
329 stack[16] = 0x68;
330 *(u32 *)&stack[17] = __GUEST_CS32;
332 /* jmp syscall_enter */
333 stack[21] = 0xe9;
334 *(u32 *)&stack[22] = (char *)syscall_enter - &stack[26];
336 /*
337 * Common SYSCALL parameters.
338 */
340 wrmsr(MSR_STAR, 0, (FLAT_RING3_CS32<<16) | __HYPERVISOR_CS);
341 wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U);
342 }
344 static long register_guest_callback(struct callback_register *reg)
345 {
346 long ret = 0;
347 struct vcpu *v = current;
349 switch ( reg->type )
350 {
351 case CALLBACKTYPE_event:
352 v->arch.guest_context.event_callback_eip = reg->address;
353 break;
355 case CALLBACKTYPE_failsafe:
356 v->arch.guest_context.failsafe_callback_eip = reg->address;
357 if ( reg->flags & CALLBACKF_mask_events )
358 set_bit(_VGCF_failsafe_disables_events,
359 &v->arch.guest_context.flags);
360 else
361 clear_bit(_VGCF_failsafe_disables_events,
362 &v->arch.guest_context.flags);
363 break;
365 case CALLBACKTYPE_syscall:
366 v->arch.guest_context.syscall_callback_eip = reg->address;
367 if ( reg->flags & CALLBACKF_mask_events )
368 set_bit(_VGCF_syscall_disables_events,
369 &v->arch.guest_context.flags);
370 else
371 clear_bit(_VGCF_syscall_disables_events,
372 &v->arch.guest_context.flags);
373 break;
375 case CALLBACKTYPE_nmi:
376 ret = register_guest_nmi_callback(reg->address);
377 break;
379 default:
380 ret = -EINVAL;
381 break;
382 }
384 return ret;
385 }
387 static long unregister_guest_callback(struct callback_unregister *unreg)
388 {
389 long ret;
391 switch ( unreg->type )
392 {
393 case CALLBACKTYPE_nmi:
394 ret = unregister_guest_nmi_callback();
395 break;
397 default:
398 ret = -EINVAL;
399 break;
400 }
402 return ret;
403 }
406 long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg)
407 {
408 long ret;
410 switch ( cmd )
411 {
412 case CALLBACKOP_register:
413 {
414 struct callback_register reg;
416 ret = -EFAULT;
417 if ( copy_from_guest(&reg, arg, 1) )
418 break;
420 ret = register_guest_callback(&reg);
421 }
422 break;
424 case CALLBACKOP_unregister:
425 {
426 struct callback_unregister unreg;
428 ret = -EFAULT;
429 if ( copy_from_guest(&unreg, arg, 1) )
430 break;
432 ret = unregister_guest_callback(&unreg);
433 }
434 break;
436 default:
437 ret = -EINVAL;
438 break;
439 }
441 return ret;
442 }
444 long do_set_callbacks(unsigned long event_address,
445 unsigned long failsafe_address,
446 unsigned long syscall_address)
447 {
448 struct callback_register event = {
449 .type = CALLBACKTYPE_event,
450 .address = event_address,
451 };
452 struct callback_register failsafe = {
453 .type = CALLBACKTYPE_failsafe,
454 .address = failsafe_address,
455 };
456 struct callback_register syscall = {
457 .type = CALLBACKTYPE_syscall,
458 .address = syscall_address,
459 };
461 register_guest_callback(&event);
462 register_guest_callback(&failsafe);
463 register_guest_callback(&syscall);
465 return 0;
466 }
468 static void hypercall_page_initialise_ring3_kernel(void *hypercall_page)
469 {
470 char *p;
471 int i;
473 /* Fill in all the transfer points with template machine code. */
474 for ( i = 0; i < (PAGE_SIZE / 32); i++ )
475 {
476 p = (char *)(hypercall_page + (i * 32));
477 *(u8 *)(p+ 0) = 0x51; /* push %rcx */
478 *(u16 *)(p+ 1) = 0x5341; /* push %r11 */
479 *(u8 *)(p+ 3) = 0xb8; /* mov $<i>,%eax */
480 *(u32 *)(p+ 4) = i;
481 *(u16 *)(p+ 8) = 0x050f; /* syscall */
482 *(u16 *)(p+10) = 0x5b41; /* pop %r11 */
483 *(u8 *)(p+12) = 0x59; /* pop %rcx */
484 *(u8 *)(p+13) = 0xc3; /* ret */
485 }
487 /*
488 * HYPERVISOR_iret is special because it doesn't return and expects a
489 * special stack frame. Guests jump at this transfer point instead of
490 * calling it.
491 */
492 p = (char *)(hypercall_page + (__HYPERVISOR_iret * 32));
493 *(u8 *)(p+ 0) = 0x51; /* push %rcx */
494 *(u16 *)(p+ 1) = 0x5341; /* push %r11 */
495 *(u8 *)(p+ 3) = 0x50; /* push %rax */
496 *(u8 *)(p+ 4) = 0xb8; /* mov $__HYPERVISOR_iret,%eax */
497 *(u32 *)(p+ 5) = __HYPERVISOR_iret;
498 *(u16 *)(p+ 9) = 0x050f; /* syscall */
499 }
501 void hypercall_page_initialise(struct domain *d, void *hypercall_page)
502 {
503 if ( is_hvm_domain(d) )
504 hvm_hypercall_page_initialise(d, hypercall_page);
505 else
506 hypercall_page_initialise_ring3_kernel(hypercall_page);
507 }
509 /*
510 * Local variables:
511 * mode: C
512 * c-set-style: "BSD"
513 * c-basic-offset: 4
514 * tab-width: 4
515 * indent-tabs-mode: nil
516 * End:
517 */