ia64/xen-unstable

view xen/arch/x86/x86_64/entry.S @ 3761:118e0a3af9b0

bitkeeper revision 1.1159.1.564 (420b44edsb8XzPev-TiGW16GSsCW6g)

More x86_64 stuff. Added hypercalls to register a user-space pagetable,
modify FS/GS base addresses, and switch to user mode. User mode switches
back to kernel mode automatically on executing SYSCALL instruction.
Still todo: 1. getdomaininfo needs to include pagetable_user
2. get writable and shadow pagetables working
3. testing
Signed-off-by: keir.fraser@cl.cam.ac.uk
author kaf24@scramble.cl.cam.ac.uk
date Thu Feb 10 11:26:37 2005 +0000 (2005-02-10)
parents 1494093616a3
children 0a4b76b6b5a0 f368e743fc2e
line source
1 /*
2 * Hypercall and fault low-level handling routines.
3 *
4 * Copyright (c) 2005, K A Fraser
5 */
7 #include <xen/config.h>
8 #include <xen/errno.h>
9 #include <xen/softirq.h>
10 #include <asm/asm_defns.h>
11 #include <asm/apicdef.h>
12 #include <asm/page.h>
13 #include <public/xen.h>
15 #define GET_CURRENT(reg) \
16 movq $STACK_SIZE-8, reg; \
17 orq %rsp, reg; \
18 andq $~7,reg; \
19 movq (reg),reg;
21 ALIGN
22 restore_all_guest:
23 btr $_TF_failsafe_return,EDOMAIN_thread_flags(%rbx)
24 jc failsafe_callback
25 RESTORE_ALL
26 testw $TRAP_syscall,4(%rsp)
27 jz 1f
28 addq $8,%rsp
29 popq %rcx
30 addq $8,%rsp
31 popq %r11
32 popq %rsp
33 sysretq
34 1: addq $8,%rsp
35 FLT1: iretq
36 .section .fixup,"ax"
37 FIX1: popq -15*8-8(%rsp) # error_code/entry_vector
38 SAVE_ALL # 15*8 bytes pushed
39 movq -8(%rsp),%rsi # error_code/entry_vector
40 sti # after stack abuse (-1024(%rsp))
41 pushq $__HYPERVISOR_DS # SS
42 leaq 8(%rsp),%rax
43 pushq %rax # RSP
44 pushf # RFLAGS
45 pushq $__HYPERVISOR_CS # CS
46 leaq DBLFLT1(%rip),%rax
47 pushq %rax # RIP
48 pushq %rsi # error_code/entry_vector
49 jmp error_code
50 DBLFLT1:GET_CURRENT(%rbx)
51 jmp test_all_events
52 DBLFIX1:GET_CURRENT(%rbx)
53 bts $_TF_failsafe_return,EDOMAIN_thread_flags(%rbx)
54 jc domain_crash # cannot reenter failsafe code
55 jmp test_all_events # will return via failsafe code
56 .previous
57 .section __pre_ex_table,"a"
58 .quad FLT1,FIX1
59 .previous
60 .section __ex_table,"a"
61 .quad DBLFLT1,DBLFIX1
62 .previous
64 /* No special register assumptions */
65 failsafe_callback:
66 GET_CURRENT(%rbx)
67 leaq EDOMAIN_trap_bounce(%rbx),%rdx
68 movq EDOMAIN_failsafe_addr(%rbx),%rax
69 movq %rax,TRAPBOUNCE_eip(%rdx)
70 movw $TBF_FAILSAFE,TRAPBOUNCE_flags(%rdx)
71 call create_bounce_frame
72 RESTORE_ALL
73 addq $8,%rsp
74 FLT2: iret
75 .section .fixup,"ax"
76 FIX2: pushq %rbx
77 GET_CURRENT(%rbx)
78 orb $TF_failsafe_return,EDOMAIN_thread_flags(%rbx)
79 popq %rbx
80 jmp FIX1
81 .section __pre_ex_table,"a"
82 .quad FLT2,FIX2
83 .previous
85 ALIGN
86 restore_all_xen:
87 RESTORE_ALL
88 addq $8,%rsp
89 iretq
91 /*
92 * %rax = hypercall vector
93 * %rdi, %rsi, %rdx, %r10, %r8, %9 = hypercall arguments
94 * %r11, %rcx = SYSCALL-saved %rflags and %rip
95 * NB. We must move %r10 to %rcx for C function-calling ABI.
96 */
97 ALIGN
98 ENTRY(syscall_enter)
99 movl $__GUEST_SS,8(%rsp)
100 pushq %r11
101 pushq $__GUEST_CS
102 pushq %rcx
103 pushq $0
104 movl $TRAP_syscall,4(%rsp)
105 SAVE_ALL
106 GET_CURRENT(%rbx)
107 bts $_TF_kernel_mode,EDOMAIN_thread_flags(%rbx)
108 jc hypercall
109 swapgs
110 movq %rbx,%rdi
111 call SYMBOL_NAME(write_ptbase)
112 jmp restore_all_guest
114 hypercall:
115 sti
116 movq %r10,%rcx
117 andq $(NR_hypercalls-1),%rax
118 leaq SYMBOL_NAME(hypercall_table)(%rip),%r10
119 callq *(%r10,%rax,8)
120 movq %rax,XREGS_rax(%rsp) # save the return value
122 test_all_events:
123 cli # tests must not race interrupts
124 /*test_softirqs:*/
125 movl EDOMAIN_processor(%rbx),%eax
126 shl $6,%rax # sizeof(irq_cpustat) == 64
127 leaq SYMBOL_NAME(irq_stat)(%rip),%rcx
128 testl $~0,(%rcx,%rax,1)
129 jnz process_softirqs
130 /*test_guest_events:*/
131 movq EDOMAIN_vcpu_info(%rbx),%rax
132 testb $0xFF,VCPUINFO_upcall_mask(%rax)
133 jnz restore_all_guest
134 testb $0xFF,VCPUINFO_upcall_pending(%rax)
135 jz restore_all_guest
136 /*process_guest_events:*/
137 leaq EDOMAIN_trap_bounce(%rbx),%rdx
138 movq EDOMAIN_event_addr(%rbx),%rax
139 movq %rax,TRAPBOUNCE_eip(%rdx)
140 movw $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx)
141 call create_bounce_frame
142 movq EDOMAIN_vcpu_info(%rbx),%rax
143 movb $1,VCPUINFO_upcall_mask(%rax) # Upcalls masked during delivery
144 jmp restore_all_guest
146 ALIGN
147 process_softirqs:
148 sti
149 call SYMBOL_NAME(do_softirq)
150 jmp test_all_events
152 /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS STACK: */
153 /* { RCX, R11, [DS-GS,] [CR2,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS } */
154 /* %rdx == trap_bounce, %rbx == task_struct */
155 /* %rax,%rcx are clobbered. %rsi contains new XREGS_rsp. */
156 create_bounce_frame:
157 /* Push new frame at existing %rsp if already in guest-OS mode. */
158 movq XREGS_rsp+8(%rsp),%rsi
159 testb $TF_kernel_mode,EDOMAIN_thread_flags(%rbx)
160 jnz 1f
161 /* Push new frame at registered guest-OS stack base. */
162 movq EDOMAIN_kernel_sp(%rbx),%rsi
163 1: movq $HYPERVISOR_VIRT_START,%rax
164 cmpq %rax,%rsi
165 jb 1f # In +ve address space? Then okay.
166 movq $HYPERVISOR_VIRT_END+60,%rax
167 cmpq %rax,%rsi
168 jb domain_crash # Above Xen private area? Then okay.
169 1: subq $40,%rsi
170 movq XREGS_ss+8(%rsp),%rax
171 FLT3: movq %rax,32(%rsi) # SS
172 movq XREGS_rsp+8(%rsp),%rax
173 FLT4: movq %rax,24(%rsi) # RSP
174 movq XREGS_eflags+8(%rsp),%rax
175 FLT5: movq %rax,16(%rsi) # RFLAGS
176 movq XREGS_cs+8(%rsp),%rax
177 FLT6: movq %rax,8(%rsi) # CS
178 movq XREGS_rip+8(%rsp),%rax
179 FLT7: movq %rax,(%rsi) # RIP
180 movb TRAPBOUNCE_flags(%rdx),%cl
181 testb $TBF_EXCEPTION_ERRCODE,%cl
182 jz 1f
183 subq $8,%rsi
184 movq TRAPBOUNCE_error_code(%rdx),%rax
185 FLT8: movq %rax,(%rsi) # ERROR CODE
186 testb $TBF_EXCEPTION_CR2,%cl
187 jz 2f
188 subq $8,%rsi
189 movq TRAPBOUNCE_cr2(%rdx),%rax
190 FLT9: movq %rax,(%rsi) # CR2
191 1: testb $TBF_FAILSAFE,%cl
192 jz 2f
193 subq $32,%rsi
194 movl %gs,%eax
195 FLT10: movq %rax,24(%rsi) # GS
196 movl %fs,%eax
197 FLT11: movq %rax,16(%rsi) # FS
198 movl %es,%eax
199 FLT12: movq %rax,8(%rsi) # ES
200 movl %ds,%eax
201 FLT13: movq %rax,(%rsi) # DS
202 2: subq $16,%rsi
203 movq XREGS_r11+8(%rsp),%rax
204 FLT14: movq %rax,(%rsi) # R11
205 movq XREGS_rcx+8(%rsp),%rax
206 FLT15: movq %rax,(%rsi) # RCX
207 /* Rewrite our stack frame and return to guest-OS mode. */
208 /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */
209 movb $0,TRAPBOUNCE_flags(%rdx)
210 bts $_TF_kernel_mode,EDOMAIN_thread_flags(%rbx)
211 jc 1f
212 swapgs
213 movq %rbx,%rdi
214 call SYMBOL_NAME(write_ptbase)
215 1: movl $TRAP_syscall,XREGS_entry_vector+8(%rsp)
216 andl $0xfffcbeff,XREGS_eflags+8(%rsp)
217 movl $__GUEST_SS,XREGS_ss+8(%rsp)
218 movq %rsi,XREGS_rsp+8(%rsp)
219 movl $__GUEST_CS,XREGS_cs+8(%rsp)
220 movq TRAPBOUNCE_eip(%rdx),%rax
221 movq %rax,XREGS_rip+8(%rsp)
222 ret
223 .section .fixup,"ax"
224 FIX3: sti
225 popq %rsi
226 addq $8,%rsp # Discard create_b_frame return address
227 pushq $__HYPERVISOR_DS # SS
228 leaq 8(%rsp),%rax
229 pushq %rax # RSP
230 pushf # RFLAGS
231 pushq $__HYPERVISOR_CS # CS
232 leaq DBLFLT2(%rip),%rax
233 pushq %rax # RIP
234 pushq %rsi # error_code/entry_vector
235 jmp error_code
236 DBLFLT2:jmp process_guest_exception_and_events
237 .previous
238 .section __pre_ex_table,"a"
239 .quad FLT3,FIX3 , FLT4,FIX3 , FLT5,FIX3 , FLT6,FIX3
240 .quad FLT7,FIX3 , FLT8,FIX3 , FLT9,FIX3 , FLT10,FIX3
241 .quad FLT11,FIX3 , FLT12,FIX3 , FLT13,FIX3 , FLT14,FIX3 , FLT15,FIX3
242 .previous
243 .section __ex_table,"a"
244 .quad DBLFLT2,domain_crash
245 .previous
247 ALIGN
248 process_guest_exception_and_events:
249 leaq EDOMAIN_trap_bounce(%rbx),%rdx
250 testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%rdx)
251 jz test_all_events
252 cli # create_bounce_frame needs CLI for pre-exceptions to work
253 call create_bounce_frame
254 jmp test_all_events
256 ALIGN
257 ENTRY(ret_from_intr)
258 GET_CURRENT(%rbx)
259 testb $3,XREGS_cs(%rsp)
260 jnz test_all_events
261 jmp restore_all_xen
263 ALIGN
264 error_code:
265 SAVE_ALL
266 testb $X86_EFLAGS_IF>>8,XREGS_eflags+1(%rsp)
267 jz exception_with_ints_disabled
268 1: sti
269 movq %rsp,%rdi
270 movl XREGS_entry_vector(%rsp),%eax
271 leaq SYMBOL_NAME(exception_table)(%rip),%rdx
272 callq *(%rdx,%rax,8)
273 jmp restore_all_xen
275 exception_with_ints_disabled:
276 testb $3,XREGS_cs(%rsp) # interrupts disabled outside Xen?
277 jnz 1b # it really does happen!
278 # (e.g., DOM0 X server)
279 movq XREGS_rip(%rsp),%rdi
280 call search_pre_exception_table
281 testq %rax,%rax # no fixup code for faulting EIP?
282 jz FATAL_exception_with_ints_disabled
283 movq %rax,XREGS_rip(%rsp)
284 movq %rsp,%rsi
285 subq $8,%rsp
286 movq %rsp,%rdi
287 movq $XREGS_kernel_sizeof/8,%rcx
288 rep; movsq # make room for error_code/entry_vector
289 movq XREGS_error_code(%rsp),%rax # error_code/entry_vector
290 movq %rax,XREGS_kernel_sizeof(%rsp)
291 jmp restore_all_xen # return to fixup code
293 FATAL_exception_with_ints_disabled:
294 movl XREGS_entry_vector(%rsp),%edi
295 movq %rsp,%rsi
296 call SYMBOL_NAME(fatal_trap)
297 ud2
299 ENTRY(divide_error)
300 pushq $0
301 movl $TRAP_divide_error,4(%rsp)
302 jmp error_code
304 ENTRY(coprocessor_error)
305 pushq $0
306 movl $TRAP_copro_error,4(%rsp)
307 jmp error_code
309 ENTRY(simd_coprocessor_error)
310 pushq $0
311 movl $TRAP_simd_error,4(%rsp)
312 jmp error_code
314 ENTRY(device_not_available)
315 pushq $0
316 movl $TRAP_no_device,4(%rsp)
317 jmp error_code
319 ENTRY(debug)
320 pushq $0
321 movl $TRAP_debug,4(%rsp)
322 jmp error_code
324 ENTRY(int3)
325 pushq $0
326 movl $TRAP_int3,4(%rsp)
327 jmp error_code
329 ENTRY(overflow)
330 pushq $0
331 movl $TRAP_overflow,4(%rsp)
332 jmp error_code
334 ENTRY(bounds)
335 pushq $0
336 movl $TRAP_bounds,4(%rsp)
337 jmp error_code
339 ENTRY(invalid_op)
340 pushq $0
341 movl $TRAP_invalid_op,4(%rsp)
342 jmp error_code
344 ENTRY(coprocessor_segment_overrun)
345 pushq $0
346 movl $TRAP_copro_seg,4(%rsp)
347 jmp error_code
349 ENTRY(invalid_TSS)
350 movl $TRAP_invalid_tss,4(%rsp)
351 jmp error_code
353 ENTRY(segment_not_present)
354 movl $TRAP_no_segment,4(%rsp)
355 jmp error_code
357 ENTRY(stack_segment)
358 movl $TRAP_stack_error,4(%rsp)
359 jmp error_code
361 ENTRY(general_protection)
362 movl $TRAP_gp_fault,4(%rsp)
363 jmp error_code
365 ENTRY(alignment_check)
366 movl $TRAP_alignment_check,4(%rsp)
367 jmp error_code
369 ENTRY(page_fault)
370 movl $TRAP_page_fault,4(%rsp)
371 jmp error_code
373 ENTRY(machine_check)
374 pushq $0
375 movl $TRAP_machine_check,4(%rsp)
376 jmp error_code
378 ENTRY(spurious_interrupt_bug)
379 pushq $0
380 movl $TRAP_spurious_int,4(%rsp)
381 jmp error_code
383 ENTRY(double_fault)
384 movl $TRAP_double_fault,4(%rsp)
385 jmp error_code
387 ENTRY(nmi)
388 pushq $0
389 SAVE_ALL
390 inb $0x61,%al
391 movl %eax,%esi # reason
392 movq %rsp,%rdi # regs
393 call SYMBOL_NAME(do_nmi)
394 jmp restore_all_xen
396 .data
398 ENTRY(exception_table)
399 .quad SYMBOL_NAME(do_divide_error)
400 .quad SYMBOL_NAME(do_debug)
401 .quad 0 # nmi
402 .quad SYMBOL_NAME(do_int3)
403 .quad SYMBOL_NAME(do_overflow)
404 .quad SYMBOL_NAME(do_bounds)
405 .quad SYMBOL_NAME(do_invalid_op)
406 .quad SYMBOL_NAME(math_state_restore)
407 .quad SYMBOL_NAME(do_double_fault)
408 .quad SYMBOL_NAME(do_coprocessor_segment_overrun)
409 .quad SYMBOL_NAME(do_invalid_TSS)
410 .quad SYMBOL_NAME(do_segment_not_present)
411 .quad SYMBOL_NAME(do_stack_segment)
412 .quad SYMBOL_NAME(do_general_protection)
413 .quad SYMBOL_NAME(do_page_fault)
414 .quad SYMBOL_NAME(do_spurious_interrupt_bug)
415 .quad SYMBOL_NAME(do_coprocessor_error)
416 .quad SYMBOL_NAME(do_alignment_check)
417 .quad SYMBOL_NAME(do_machine_check)
418 .quad SYMBOL_NAME(do_simd_coprocessor_error)
420 ENTRY(hypercall_table)
421 .quad SYMBOL_NAME(do_set_trap_table) /* 0 */
422 .quad SYMBOL_NAME(do_mmu_update)
423 .quad SYMBOL_NAME(do_set_gdt)
424 .quad SYMBOL_NAME(do_stack_switch)
425 .quad SYMBOL_NAME(do_set_callbacks)
426 .quad SYMBOL_NAME(do_fpu_taskswitch) /* 5 */
427 .quad SYMBOL_NAME(do_sched_op)
428 .quad SYMBOL_NAME(do_dom0_op)
429 .quad SYMBOL_NAME(do_set_debugreg)
430 .quad SYMBOL_NAME(do_get_debugreg)
431 .quad SYMBOL_NAME(do_update_descriptor) /* 10 */
432 .quad SYMBOL_NAME(do_ni_hypercall)
433 .quad SYMBOL_NAME(do_dom_mem_op)
434 .quad SYMBOL_NAME(do_multicall)
435 .quad SYMBOL_NAME(do_update_va_mapping)
436 .quad SYMBOL_NAME(do_set_timer_op) /* 15 */
437 .quad SYMBOL_NAME(do_event_channel_op)
438 .quad SYMBOL_NAME(do_xen_version)
439 .quad SYMBOL_NAME(do_console_io)
440 .quad SYMBOL_NAME(do_physdev_op)
441 .quad SYMBOL_NAME(do_grant_table_op) /* 20 */
442 .quad SYMBOL_NAME(do_vm_assist)
443 .quad SYMBOL_NAME(do_update_va_mapping_otherdomain)
444 .quad SYMBOL_NAME(do_switch_to_user)
445 .quad SYMBOL_NAME(do_boot_vcpu)
446 .quad SYMBOL_NAME(do_set_segment_base) /* 25 */
447 .rept NR_hypercalls-((.-hypercall_table)/4)
448 .quad SYMBOL_NAME(do_ni_hypercall)
449 .endr