rev |
line source |
kaf24@3602
|
1
|
kaf24@3602
|
2 #include <xen/config.h>
|
kaf24@3602
|
3 #include <xen/init.h>
|
kaf24@3602
|
4 #include <xen/sched.h>
|
kaf24@3602
|
5 #include <xen/lib.h>
|
kaf24@3602
|
6 #include <xen/errno.h>
|
kaf24@3602
|
7 #include <xen/mm.h>
|
kaf24@3602
|
8 #include <xen/irq.h>
|
kaf24@5824
|
9 #include <xen/symbols.h>
|
kaf24@3630
|
10 #include <xen/console.h>
|
kaf24@3650
|
11 #include <xen/sched.h>
|
cl349@5291
|
12 #include <asm/current.h>
|
kaf24@5159
|
13 #include <asm/flushtlb.h>
|
kaf24@3650
|
14 #include <asm/msr.h>
|
kaf24@3602
|
15
|
kaf24@4683
|
16 void show_registers(struct cpu_user_regs *regs)
|
kaf24@3602
|
17 {
|
kaf24@6477
|
18 printk("CPU: %d\nRIP: %04x:[<%016lx>]",
|
kaf24@5824
|
19 smp_processor_id(), 0xffff & regs->cs, regs->rip);
|
kaf24@6232
|
20 if ( !GUEST_MODE(regs) )
|
kaf24@6233
|
21 print_symbol(" %s", regs->rip);
|
kaf24@6477
|
22 printk("\nRFLAGS: %016lx\n", regs->eflags);
|
kaf24@6477
|
23 printk("rax: %016lx rbx: %016lx rcx: %016lx\n",
|
kaf24@6477
|
24 regs->rax, regs->rbx, regs->rcx);
|
kaf24@6477
|
25 printk("rdx: %016lx rsi: %016lx rdi: %016lx\n",
|
kaf24@6477
|
26 regs->rdx, regs->rsi, regs->rdi);
|
kaf24@6477
|
27 printk("rbp: %016lx rsp: %016lx r8: %016lx\n",
|
kaf24@6477
|
28 regs->rbp, regs->rsp, regs->r8);
|
kaf24@6477
|
29 printk("r9: %016lx r10: %016lx r11: %016lx\n",
|
kaf24@6477
|
30 regs->r9, regs->r10, regs->r11);
|
kaf24@6477
|
31 printk("r12: %016lx r13: %016lx r14: %016lx\n",
|
kaf24@6477
|
32 regs->r12, regs->r13, regs->r14);
|
kaf24@6477
|
33 printk("r15: %016lx\n", regs->r15);
|
kaf24@3602
|
34
|
kaf24@6573
|
35 show_stack(regs);
|
kaf24@5073
|
36 }
|
kaf24@3602
|
37
|
kaf24@3630
|
38 void show_page_walk(unsigned long addr)
|
kaf24@3630
|
39 {
|
kaf24@3630
|
40 unsigned long page = read_cr3();
|
kaf24@3630
|
41
|
kaf24@4654
|
42 printk("Pagetable walk from %016lx:\n", addr);
|
kaf24@3630
|
43
|
kaf24@3630
|
44 page &= PAGE_MASK;
|
kaf24@3630
|
45 page = ((unsigned long *) __va(page))[l4_table_offset(addr)];
|
kaf24@4654
|
46 printk(" L4 = %016lx\n", page);
|
kaf24@3630
|
47 if ( !(page & _PAGE_PRESENT) )
|
kaf24@3630
|
48 return;
|
kaf24@3630
|
49
|
kaf24@3630
|
50 page &= PAGE_MASK;
|
kaf24@3630
|
51 page = ((unsigned long *) __va(page))[l3_table_offset(addr)];
|
kaf24@4654
|
52 printk(" L3 = %016lx\n", page);
|
kaf24@3630
|
53 if ( !(page & _PAGE_PRESENT) )
|
kaf24@3630
|
54 return;
|
kaf24@3630
|
55
|
kaf24@3630
|
56 page &= PAGE_MASK;
|
kaf24@3630
|
57 page = ((unsigned long *) __va(page))[l2_table_offset(addr)];
|
kaf24@4654
|
58 printk(" L2 = %016lx %s\n", page, (page & _PAGE_PSE) ? "(2MB)" : "");
|
kaf24@3630
|
59 if ( !(page & _PAGE_PRESENT) || (page & _PAGE_PSE) )
|
kaf24@3630
|
60 return;
|
kaf24@3630
|
61
|
kaf24@3630
|
62 page &= PAGE_MASK;
|
kaf24@3630
|
63 page = ((unsigned long *) __va(page))[l1_table_offset(addr)];
|
kaf24@4654
|
64 printk(" L1 = %016lx\n", page);
|
kaf24@3630
|
65 }
|
kaf24@3630
|
66
|
kaf24@3630
|
67 asmlinkage void double_fault(void);
|
kaf24@4683
|
68 asmlinkage void do_double_fault(struct cpu_user_regs *regs)
|
kaf24@3630
|
69 {
|
kaf24@4926
|
70 watchdog_disable();
|
kaf24@3630
|
71
|
kaf24@3686
|
72 console_force_unlock();
|
kaf24@3686
|
73
|
kaf24@3630
|
74 /* Find information saved during fault and dump it to the console. */
|
kaf24@3630
|
75 printk("************************************\n");
|
kaf24@3695
|
76 show_registers(regs);
|
kaf24@3630
|
77 printk("************************************\n");
|
kaf24@3695
|
78 printk("CPU%d DOUBLE FAULT -- system shutdown\n", smp_processor_id());
|
kaf24@3630
|
79 printk("System needs manual reset.\n");
|
kaf24@3630
|
80 printk("************************************\n");
|
kaf24@3630
|
81
|
kaf24@3630
|
82 /* Lock up the console to prevent spurious output from other CPUs. */
|
kaf24@3630
|
83 console_force_lock();
|
kaf24@3630
|
84
|
kaf24@3630
|
85 /* Wait for manual reset. */
|
kaf24@3630
|
86 for ( ; ; )
|
kaf24@3630
|
87 __asm__ __volatile__ ( "hlt" );
|
kaf24@3630
|
88 }
|
kaf24@3630
|
89
|
kaf24@3761
|
90 asmlinkage void syscall_enter(void);
|
kaf24@3650
|
91 void __init percpu_traps_init(void)
|
kaf24@3650
|
92 {
|
kaf24@3761
|
93 char *stack_bottom, *stack;
|
kaf24@3761
|
94 int cpu = smp_processor_id();
|
kaf24@3761
|
95
|
kaf24@3774
|
96 if ( cpu == 0 )
|
kaf24@3774
|
97 {
|
kaf24@3774
|
98 /* Specify dedicated interrupt stacks for NMIs and double faults. */
|
kaf24@3774
|
99 set_intr_gate(TRAP_double_fault, &double_fault);
|
kaf24@3774
|
100 idt_table[TRAP_double_fault].a |= 1UL << 32; /* IST1 */
|
kaf24@3774
|
101 idt_table[TRAP_nmi].a |= 2UL << 32; /* IST2 */
|
kaf24@3774
|
102 }
|
kaf24@3774
|
103
|
kaf24@3761
|
104 stack_bottom = (char *)get_stack_bottom();
|
kaf24@3761
|
105 stack = (char *)((unsigned long)stack_bottom & ~(STACK_SIZE - 1));
|
kaf24@3695
|
106
|
kaf24@3695
|
107 /* Double-fault handler has its own per-CPU 1kB stack. */
|
kaf24@3695
|
108 init_tss[cpu].ist[0] = (unsigned long)&stack[1024];
|
kaf24@3695
|
109
|
kaf24@3695
|
110 /* NMI handler has its own per-CPU 1kB stack. */
|
kaf24@3695
|
111 init_tss[cpu].ist[1] = (unsigned long)&stack[2048];
|
kaf24@3695
|
112
|
kaf24@3695
|
113 /*
|
kaf24@3695
|
114 * Trampoline for SYSCALL entry from long mode.
|
kaf24@3695
|
115 */
|
kaf24@3695
|
116
|
kaf24@3695
|
117 /* Skip the NMI and DF stacks. */
|
kaf24@3695
|
118 stack = &stack[2048];
|
kaf24@3695
|
119 wrmsr(MSR_LSTAR, (unsigned long)stack, ((unsigned long)stack>>32));
|
kaf24@3650
|
120
|
kaf24@3650
|
121 /* movq %rsp, saversp(%rip) */
|
kaf24@3650
|
122 stack[0] = 0x48;
|
kaf24@3650
|
123 stack[1] = 0x89;
|
kaf24@3650
|
124 stack[2] = 0x25;
|
kaf24@3761
|
125 *(u32 *)&stack[3] = (stack_bottom - &stack[7]) - 16;
|
kaf24@3650
|
126
|
kaf24@3650
|
127 /* leaq saversp(%rip), %rsp */
|
kaf24@3650
|
128 stack[7] = 0x48;
|
kaf24@3650
|
129 stack[8] = 0x8d;
|
kaf24@3650
|
130 stack[9] = 0x25;
|
kaf24@3761
|
131 *(u32 *)&stack[10] = (stack_bottom - &stack[14]) - 16;
|
kaf24@3650
|
132
|
kaf24@3783
|
133 /* pushq %r11 */
|
kaf24@3783
|
134 stack[14] = 0x41;
|
kaf24@3783
|
135 stack[15] = 0x53;
|
kaf24@3783
|
136
|
kaf24@3783
|
137 /* pushq $__GUEST_CS64 */
|
kaf24@3783
|
138 stack[16] = 0x68;
|
kaf24@3783
|
139 *(u32 *)&stack[17] = __GUEST_CS64;
|
kaf24@3783
|
140
|
kaf24@3761
|
141 /* jmp syscall_enter */
|
kaf24@3783
|
142 stack[21] = 0xe9;
|
kaf24@3783
|
143 *(u32 *)&stack[22] = (char *)syscall_enter - &stack[26];
|
kaf24@3650
|
144
|
kaf24@3695
|
145 /*
|
kaf24@3695
|
146 * Trampoline for SYSCALL entry from compatibility mode.
|
kaf24@3695
|
147 */
|
kaf24@3695
|
148
|
kaf24@3695
|
149 /* Skip the long-mode entry trampoline. */
|
kaf24@3783
|
150 stack = &stack[26];
|
kaf24@3695
|
151 wrmsr(MSR_CSTAR, (unsigned long)stack, ((unsigned long)stack>>32));
|
kaf24@3695
|
152
|
kaf24@3695
|
153 /* movq %rsp, saversp(%rip) */
|
kaf24@3695
|
154 stack[0] = 0x48;
|
kaf24@3695
|
155 stack[1] = 0x89;
|
kaf24@3695
|
156 stack[2] = 0x25;
|
kaf24@3761
|
157 *(u32 *)&stack[3] = (stack_bottom - &stack[7]) - 16;
|
kaf24@3695
|
158
|
kaf24@3695
|
159 /* leaq saversp(%rip), %rsp */
|
kaf24@3695
|
160 stack[7] = 0x48;
|
kaf24@3695
|
161 stack[8] = 0x8d;
|
kaf24@3695
|
162 stack[9] = 0x25;
|
kaf24@3761
|
163 *(u32 *)&stack[10] = (stack_bottom - &stack[14]) - 16;
|
kaf24@3695
|
164
|
kaf24@3783
|
165 /* pushq %r11 */
|
kaf24@3783
|
166 stack[14] = 0x41;
|
kaf24@3783
|
167 stack[15] = 0x53;
|
kaf24@3783
|
168
|
kaf24@3783
|
169 /* pushq $__GUEST_CS32 */
|
kaf24@3783
|
170 stack[16] = 0x68;
|
kaf24@3783
|
171 *(u32 *)&stack[17] = __GUEST_CS32;
|
kaf24@3783
|
172
|
kaf24@3761
|
173 /* jmp syscall_enter */
|
kaf24@3783
|
174 stack[21] = 0xe9;
|
kaf24@3783
|
175 *(u32 *)&stack[22] = (char *)syscall_enter - &stack[26];
|
kaf24@3695
|
176
|
kaf24@3695
|
177 /*
|
kaf24@3695
|
178 * Common SYSCALL parameters.
|
kaf24@3695
|
179 */
|
kaf24@3695
|
180
|
kaf24@3696
|
181 wrmsr(MSR_STAR, 0, (FLAT_RING3_CS32<<16) | __HYPERVISOR_CS);
|
kaf24@3822
|
182 wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U);
|
kaf24@3650
|
183 }
|
kaf24@3650
|
184
|
kaf24@3780
|
185 long do_set_callbacks(unsigned long event_address,
|
kaf24@3780
|
186 unsigned long failsafe_address,
|
kaf24@3780
|
187 unsigned long syscall_address)
|
kaf24@3780
|
188 {
|
kaf24@5289
|
189 struct vcpu *d = current;
|
kaf24@3780
|
190
|
kaf24@4689
|
191 d->arch.guest_context.event_callback_eip = event_address;
|
kaf24@4689
|
192 d->arch.guest_context.failsafe_callback_eip = failsafe_address;
|
kaf24@4689
|
193 d->arch.guest_context.syscall_callback_eip = syscall_address;
|
kaf24@3780
|
194
|
kaf24@3780
|
195 return 0;
|
kaf24@3780
|
196 }
|