~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to xen/arch/x86/x86_64/entry.S

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Hypercall and fault low-level handling routines.
 
3
 *
 
4
 * Copyright (c) 2005, K A Fraser
 
5
 */
 
6
 
 
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>
 
14
 
 
15
#define GET_GUEST_REGS(reg)                     \
 
16
        movq $~(STACK_SIZE-1),reg;              \
 
17
        andq %rsp,reg;                          \
 
18
        orq  $(STACK_SIZE-CPUINFO_sizeof),reg;
 
19
 
 
20
#define GET_CURRENT(reg)         \
 
21
        movq $STACK_SIZE-8, reg; \
 
22
        orq  %rsp, reg;          \
 
23
        andq $~7,reg;            \
 
24
        movq (reg),reg;
 
25
 
 
26
        ALIGN
 
27
/* %rbx: struct vcpu */
 
28
switch_to_kernel:
 
29
        leaq  VCPU_trap_bounce(%rbx),%rdx
 
30
        /* TB_eip = (32-bit syscall && syscall32_addr) ?
 
31
         *          syscall32_addr : syscall_addr */
 
32
        xor   %eax,%eax
 
33
        cmpw  $FLAT_USER_CS32,UREGS_cs(%rsp)
 
34
        cmoveq VCPU_syscall32_addr(%rbx),%rax
 
35
        testq %rax,%rax
 
36
        cmovzq VCPU_syscall_addr(%rbx),%rax
 
37
        movq  %rax,TRAPBOUNCE_eip(%rdx)
 
38
        /* TB_flags = VGCF_syscall_disables_events ? TBF_INTERRUPT : 0 */
 
39
        btl   $_VGCF_syscall_disables_events,VCPU_guest_context_flags(%rbx)
 
40
        setc  %cl
 
41
        leal  (,%rcx,TBF_INTERRUPT),%ecx
 
42
        movb  %cl,TRAPBOUNCE_flags(%rdx)
 
43
        call  create_bounce_frame
 
44
        andl  $~X86_EFLAGS_DF,UREGS_eflags(%rsp)
 
45
        jmp   test_all_events
 
46
 
 
47
/* %rbx: struct vcpu, interrupts disabled */
 
48
restore_all_guest:
 
49
        ASSERT_INTERRUPTS_DISABLED
 
50
        RESTORE_ALL
 
51
        testw $TRAP_syscall,4(%rsp)
 
52
        jz    iret_exit_to_guest
 
53
 
 
54
        addq  $8,%rsp
 
55
        popq  %rcx                    # RIP
 
56
        popq  %r11                    # CS
 
57
        cmpw  $FLAT_USER_CS32,%r11
 
58
        popq  %r11                    # RFLAGS
 
59
        popq  %rsp                    # RSP
 
60
        je    1f
 
61
        sysretq
 
62
1:      sysretl
 
63
 
 
64
        ALIGN
 
65
/* No special register assumptions. */
 
66
iret_exit_to_guest:
 
67
        addq  $8,%rsp
 
68
.Lft0:  iretq
 
69
 
 
70
.section .fixup,"ax"
 
71
.Lfx0:  sti
 
72
        SAVE_ALL
 
73
        movq  UREGS_error_code(%rsp),%rsi
 
74
        movq  %rsp,%rax
 
75
        andq  $~0xf,%rsp
 
76
        pushq $__HYPERVISOR_DS         # SS
 
77
        pushq %rax                     # RSP
 
78
        pushfq                         # RFLAGS
 
79
        pushq $__HYPERVISOR_CS         # CS
 
80
        leaq  .Ldf0(%rip),%rax
 
81
        pushq %rax                     # RIP
 
82
        pushq %rsi                     # error_code/entry_vector
 
83
        jmp   handle_exception
 
84
.Ldf0:  GET_CURRENT(%rbx)
 
85
        jmp   test_all_events
 
86
failsafe_callback:
 
87
        GET_CURRENT(%rbx)
 
88
        leaq  VCPU_trap_bounce(%rbx),%rdx
 
89
        movq  VCPU_failsafe_addr(%rbx),%rax
 
90
        movq  %rax,TRAPBOUNCE_eip(%rdx)
 
91
        movb  $TBF_FAILSAFE,TRAPBOUNCE_flags(%rdx)
 
92
        bt    $_VGCF_failsafe_disables_events,VCPU_guest_context_flags(%rbx)
 
93
        jnc   1f
 
94
        orb   $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx)
 
95
1:      call  create_bounce_frame
 
96
        jmp   test_all_events
 
97
.previous
 
98
.section __pre_ex_table,"a"
 
99
        .quad .Lft0,.Lfx0
 
100
.previous
 
101
.section __ex_table,"a"
 
102
        .quad .Ldf0,failsafe_callback
 
103
.previous
 
104
 
 
105
        ALIGN
 
106
/* No special register assumptions. */
 
107
restore_all_xen:
 
108
        RESTORE_ALL
 
109
        addq  $8,%rsp
 
110
        iretq
 
111
 
 
112
/*
 
113
 * When entering SYSCALL from kernel mode:
 
114
 *  %rax                            = hypercall vector
 
115
 *  %rdi, %rsi, %rdx, %r10, %r8, %9 = hypercall arguments
 
116
 *  %rcx                            = SYSCALL-saved %rip
 
117
 *  NB. We must move %r10 to %rcx for C function-calling ABI.
 
118
 *
 
119
 * When entering SYSCALL from user mode:
 
120
 *  Vector directly to the registered arch.syscall_addr.
 
121
 *
 
122
 * Initial work is done by per-CPU stack trampolines. At this point %rsp
 
123
 * has been initialised to point at the correct Xen stack, and %rsp, %rflags
 
124
 * and %cs have been saved. All other registers are still to be saved onto
 
125
 * the stack, starting with %rip, and an appropriate %ss must be saved into
 
126
 * the space left by the trampoline.
 
127
 */
 
128
        ALIGN
 
129
ENTRY(syscall_enter)
 
130
        sti
 
131
        movl  $FLAT_KERNEL_SS,24(%rsp)
 
132
        pushq %rcx
 
133
        pushq $0
 
134
        movl  $TRAP_syscall,4(%rsp)
 
135
        movq  24(%rsp),%r11 /* Re-load user RFLAGS into %r11 before SAVE_ALL */
 
136
        SAVE_ALL
 
137
        GET_CURRENT(%rbx)
 
138
        movq  VCPU_domain(%rbx),%rcx
 
139
        testb $1,DOMAIN_is_32bit_pv(%rcx)
 
140
        jnz   compat_syscall
 
141
        testb $TF_kernel_mode,VCPU_thread_flags(%rbx)
 
142
        jz    switch_to_kernel
 
143
 
 
144
/*hypercall:*/
 
145
        movq  %r10,%rcx
 
146
        cmpq  $NR_hypercalls,%rax
 
147
        jae   bad_hypercall
 
148
#ifndef NDEBUG
 
149
        /* Deliberately corrupt parameter regs not used by this hypercall. */
 
150
        pushq %rdi; pushq %rsi; pushq %rdx; pushq %rcx; pushq %r8 ; pushq %r9 
 
151
        leaq  hypercall_args_table(%rip),%r10
 
152
        movq  $6,%rcx
 
153
        sub   (%r10,%rax,1),%cl
 
154
        movq  %rsp,%rdi
 
155
        movl  $0xDEADBEEF,%eax
 
156
        rep   stosq
 
157
        popq  %r9 ; popq  %r8 ; popq  %rcx; popq  %rdx; popq  %rsi; popq  %rdi
 
158
        movq  UREGS_rax(%rsp),%rax
 
159
        pushq %rax
 
160
        pushq UREGS_rip+8(%rsp)
 
161
#define SHADOW_BYTES 16 /* Shadow EIP + shadow hypercall # */
 
162
#else
 
163
#define SHADOW_BYTES 0  /* No on-stack shadow state */
 
164
#endif
 
165
        cmpb  $0,tb_init_done(%rip)
 
166
        je    1f
 
167
        call  trace_hypercall
 
168
        /* Now restore all the registers that trace_hypercall clobbered */
 
169
        movq  UREGS_rax+SHADOW_BYTES(%rsp),%rax   /* Hypercall #  */
 
170
        movq  UREGS_rdi+SHADOW_BYTES(%rsp),%rdi   /* Arg 1        */
 
171
        movq  UREGS_rsi+SHADOW_BYTES(%rsp),%rsi   /* Arg 2        */
 
172
        movq  UREGS_rdx+SHADOW_BYTES(%rsp),%rdx   /* Arg 3        */
 
173
        movq  UREGS_r10+SHADOW_BYTES(%rsp),%rcx   /* Arg 4        */
 
174
        movq  UREGS_rdi+SHADOW_BYTES(%rsp),%r8    /* Arg 5        */
 
175
        movq  UREGS_rbp+SHADOW_BYTES(%rsp),%r9    /* Arg 6        */
 
176
#undef SHADOW_BYTES
 
177
1:      leaq  hypercall_table(%rip),%r10
 
178
        PERFC_INCR(PERFC_hypercalls, %rax, %rbx)
 
179
        callq *(%r10,%rax,8)
 
180
#ifndef NDEBUG
 
181
        /* Deliberately corrupt parameter regs used by this hypercall. */
 
182
        popq  %r10         # Shadow RIP
 
183
        cmpq  %r10,UREGS_rip+8(%rsp)
 
184
        popq  %rcx         # Shadow hypercall index
 
185
        jne   skip_clobber /* If RIP has changed then don't clobber. */
 
186
        leaq  hypercall_args_table(%rip),%r10
 
187
        movb  (%r10,%rcx,1),%cl
 
188
        movl  $0xDEADBEEF,%r10d
 
189
        cmpb  $1,%cl; jb skip_clobber; movq %r10,UREGS_rdi(%rsp)
 
190
        cmpb  $2,%cl; jb skip_clobber; movq %r10,UREGS_rsi(%rsp)
 
191
        cmpb  $3,%cl; jb skip_clobber; movq %r10,UREGS_rdx(%rsp)
 
192
        cmpb  $4,%cl; jb skip_clobber; movq %r10,UREGS_r10(%rsp)
 
193
        cmpb  $5,%cl; jb skip_clobber; movq %r10,UREGS_r8(%rsp)
 
194
        cmpb  $6,%cl; jb skip_clobber; movq %r10,UREGS_r9(%rsp)
 
195
skip_clobber:
 
196
#endif
 
197
        movq  %rax,UREGS_rax(%rsp)       # save the return value
 
198
 
 
199
/* %rbx: struct vcpu */
 
200
test_all_events:
 
201
        cli                             # tests must not race interrupts
 
202
/*test_softirqs:*/  
 
203
        movl  VCPU_processor(%rbx),%eax
 
204
        shl   $IRQSTAT_shift,%rax
 
205
        leaq  irq_stat(%rip),%rcx
 
206
        testl $~0,(%rcx,%rax,1)
 
207
        jnz   process_softirqs
 
208
        testb $1,VCPU_mce_pending(%rbx)
 
209
        jnz   process_mce
 
210
        testb $1,VCPU_nmi_pending(%rbx)
 
211
        jnz   process_nmi
 
212
test_guest_events:
 
213
        movq  VCPU_vcpu_info(%rbx),%rax
 
214
        testb $0xFF,VCPUINFO_upcall_mask(%rax)
 
215
        jnz   restore_all_guest
 
216
        testb $0xFF,VCPUINFO_upcall_pending(%rax)
 
217
        jz    restore_all_guest
 
218
/*process_guest_events:*/
 
219
        sti
 
220
        leaq  VCPU_trap_bounce(%rbx),%rdx
 
221
        movq  VCPU_event_addr(%rbx),%rax
 
222
        movq  %rax,TRAPBOUNCE_eip(%rdx)
 
223
        movb  $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx)
 
224
        call  create_bounce_frame
 
225
        jmp   test_all_events
 
226
 
 
227
        ALIGN
 
228
/* %rbx: struct vcpu */
 
229
process_softirqs:
 
230
        sti       
 
231
        call do_softirq
 
232
        jmp  test_all_events
 
233
 
 
234
        ALIGN
 
235
/* %rbx: struct vcpu */
 
236
process_mce:
 
237
        testb $1 << VCPU_TRAP_MCE,VCPU_async_exception_mask(%rbx)
 
238
        jnz  test_guest_events
 
239
        sti
 
240
        movb $0,VCPU_mce_pending(%rbx)
 
241
        call set_guest_machinecheck_trapbounce
 
242
        test %eax,%eax
 
243
        jz   test_all_events
 
244
        movzbl VCPU_async_exception_mask(%rbx),%edx # save mask for the
 
245
        movb %dl,VCPU_mce_old_mask(%rbx)            # iret hypercall
 
246
        orl  $1 << VCPU_TRAP_MCE,%edx
 
247
        movb %dl,VCPU_async_exception_mask(%rbx)
 
248
        jmp  process_trap
 
249
 
 
250
        ALIGN
 
251
/* %rbx: struct vcpu */
 
252
process_nmi:
 
253
        cmpw $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%rbx)
 
254
        jnz  test_guest_events
 
255
        sti
 
256
        movb $0,VCPU_nmi_pending(%rbx)
 
257
        call set_guest_nmi_trapbounce
 
258
        test %eax,%eax
 
259
        jz   test_all_events
 
260
        movzbl VCPU_async_exception_mask(%rbx),%edx # save mask for the
 
261
        movb %dl,VCPU_nmi_old_mask(%rbx)            # iret hypercall
 
262
        orl  $1 << VCPU_TRAP_NMI,%edx
 
263
        movb %dl,VCPU_async_exception_mask(%rbx)
 
264
        /* FALLTHROUGH */
 
265
process_trap:
 
266
        leaq VCPU_trap_bounce(%rbx),%rdx
 
267
        call create_bounce_frame
 
268
        jmp  test_all_events
 
269
 
 
270
bad_hypercall:
 
271
        movq $-ENOSYS,UREGS_rax(%rsp)
 
272
        jmp  test_all_events
 
273
 
 
274
ENTRY(sysenter_entry)
 
275
        sti
 
276
        pushq $FLAT_USER_SS
 
277
        pushq $0
 
278
        pushfq
 
279
        .globl sysenter_eflags_saved
 
280
sysenter_eflags_saved:
 
281
        pushq $0
 
282
        pushq $0
 
283
        pushq $0
 
284
        movl  $TRAP_syscall,4(%rsp)
 
285
        SAVE_ALL
 
286
        GET_CURRENT(%rbx)
 
287
        cmpb  $0,VCPU_sysenter_disables_events(%rbx)
 
288
        movq  $0,UREGS_rip(%rsp) /* null rip */
 
289
        movl  $3,UREGS_cs(%rsp)  /* ring 3 null cs */
 
290
        movq  VCPU_sysenter_addr(%rbx),%rax
 
291
        setne %cl
 
292
        leaq  VCPU_trap_bounce(%rbx),%rdx
 
293
        testq %rax,%rax
 
294
        leal  (,%rcx,TBF_INTERRUPT),%ecx
 
295
        jz    2f
 
296
1:      movq  VCPU_domain(%rbx),%rdi
 
297
        movq  %rax,TRAPBOUNCE_eip(%rdx)
 
298
        movb  %cl,TRAPBOUNCE_flags(%rdx)
 
299
        testb $1,DOMAIN_is_32bit_pv(%rdi)
 
300
        jnz   compat_sysenter
 
301
        call  create_bounce_frame
 
302
        jmp   test_all_events
 
303
2:      movl  %eax,TRAPBOUNCE_error_code(%rdx)
 
304
        movq  VCPU_gp_fault_addr(%rbx),%rax
 
305
        movb  $(TBF_EXCEPTION|TBF_EXCEPTION_ERRCODE|TBF_INTERRUPT),%cl
 
306
        movl  $TRAP_gp_fault,UREGS_entry_vector(%rsp)
 
307
        jmp   1b
 
308
 
 
309
ENTRY(int80_direct_trap)
 
310
        pushq $0
 
311
        SAVE_ALL
 
312
 
 
313
        GET_CURRENT(%rbx)
 
314
 
 
315
        /* Check that the callback is non-null. */
 
316
        leaq  VCPU_int80_bounce(%rbx),%rdx
 
317
        cmpb  $0,TRAPBOUNCE_flags(%rdx)
 
318
        jz    int80_slow_path
 
319
 
 
320
        movq  VCPU_domain(%rbx),%rax
 
321
        testb $1,DOMAIN_is_32bit_pv(%rax)
 
322
        jnz   compat_int80_direct_trap
 
323
 
 
324
        call  create_bounce_frame
 
325
        jmp   test_all_events
 
326
 
 
327
int80_slow_path:
 
328
        /* 
 
329
         * Setup entry vector and error code as if this was a GPF caused by an
 
330
         * IDT entry with DPL==0.
 
331
         */
 
332
        movl  $((0x80 << 3) | 0x2),UREGS_error_code(%rsp)
 
333
        movl  $TRAP_gp_fault,UREGS_entry_vector(%rsp)
 
334
        /* A GPF wouldn't have incremented the instruction pointer. */
 
335
        subq  $2,UREGS_rip(%rsp)
 
336
        jmp   handle_exception_saved
 
337
 
 
338
/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS STACK:                     */
 
339
/*   { RCX, R11, [DS-GS,] [CR2,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS }   */
 
340
/* %rdx: trap_bounce, %rbx: struct vcpu                                  */
 
341
/* On return only %rbx and %rdx are guaranteed non-clobbered.            */
 
342
create_bounce_frame:
 
343
        ASSERT_INTERRUPTS_ENABLED
 
344
        testb $TF_kernel_mode,VCPU_thread_flags(%rbx)
 
345
        jnz   1f
 
346
        /* Push new frame at registered guest-OS stack base. */
 
347
        pushq %rdx
 
348
        movq  %rbx,%rdi
 
349
        call  toggle_guest_mode
 
350
        popq  %rdx
 
351
        movq  VCPU_kernel_sp(%rbx),%rsi
 
352
        jmp   2f
 
353
1:      /* In kernel context already: push new frame at existing %rsp. */
 
354
        movq  UREGS_rsp+8(%rsp),%rsi
 
355
        andb  $0xfc,UREGS_cs+8(%rsp)    # Indicate kernel context to guest.
 
356
2:      andq  $~0xf,%rsi                # Stack frames are 16-byte aligned.
 
357
        movq  $HYPERVISOR_VIRT_START,%rax
 
358
        cmpq  %rax,%rsi
 
359
        jb    1f                        # In +ve address space? Then okay.
 
360
        movq  $HYPERVISOR_VIRT_END+60,%rax
 
361
        cmpq  %rax,%rsi
 
362
        jb    domain_crash_synchronous  # Above Xen private area? Then okay.
 
363
1:      movb  TRAPBOUNCE_flags(%rdx),%cl
 
364
        subq  $40,%rsi
 
365
        movq  UREGS_ss+8(%rsp),%rax
 
366
.Lft2:  movq  %rax,32(%rsi)             # SS
 
367
        movq  UREGS_rsp+8(%rsp),%rax
 
368
.Lft3:  movq  %rax,24(%rsi)             # RSP
 
369
        movq  VCPU_vcpu_info(%rbx),%rax
 
370
        pushq VCPUINFO_upcall_mask(%rax)
 
371
        testb $TBF_INTERRUPT,%cl
 
372
        setnz %ch                       # TBF_INTERRUPT -> set upcall mask
 
373
        orb   %ch,VCPUINFO_upcall_mask(%rax)
 
374
        popq  %rax
 
375
        shlq  $32,%rax                  # Bits 32-39: saved_upcall_mask
 
376
        movw  UREGS_cs+8(%rsp),%ax      # Bits  0-15: CS
 
377
.Lft4:  movq  %rax,8(%rsi)              # CS / saved_upcall_mask
 
378
        shrq  $32,%rax
 
379
        testb $0xFF,%al                 # Bits 0-7: saved_upcall_mask
 
380
        setz  %ch                       # %ch == !saved_upcall_mask
 
381
        movl  UREGS_eflags+8(%rsp),%eax
 
382
        andl  $~X86_EFLAGS_IF,%eax
 
383
        addb  %ch,%ch                   # Bit 9 (EFLAGS.IF)
 
384
        orb   %ch,%ah                   # Fold EFLAGS.IF into %eax
 
385
.Lft5:  movq  %rax,16(%rsi)             # RFLAGS
 
386
        movq  UREGS_rip+8(%rsp),%rax
 
387
.Lft6:  movq  %rax,(%rsi)               # RIP
 
388
        testb $TBF_EXCEPTION_ERRCODE,%cl
 
389
        jz    1f
 
390
        subq  $8,%rsi
 
391
        movl  TRAPBOUNCE_error_code(%rdx),%eax
 
392
.Lft7:  movq  %rax,(%rsi)               # ERROR CODE
 
393
1:      testb $TBF_FAILSAFE,%cl
 
394
        jz    2f
 
395
        subq  $32,%rsi
 
396
        movl  %gs,%eax
 
397
.Lft8:  movq  %rax,24(%rsi)             # GS
 
398
        movl  %fs,%eax
 
399
.Lft9:  movq  %rax,16(%rsi)             # FS
 
400
        movl  %es,%eax
 
401
.Lft10: movq  %rax,8(%rsi)              # ES
 
402
        movl  %ds,%eax
 
403
.Lft11: movq  %rax,(%rsi)               # DS
 
404
2:      subq  $16,%rsi
 
405
        movq  UREGS_r11+8(%rsp),%rax
 
406
.Lft12: movq  %rax,8(%rsi)              # R11
 
407
        movq  UREGS_rcx+8(%rsp),%rax
 
408
.Lft13: movq  %rax,(%rsi)               # RCX
 
409
        /* Rewrite our stack frame and return to guest-OS mode. */
 
410
        /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */
 
411
        /* Also clear AC: alignment checks shouldn't trigger in kernel mode. */
 
412
        movl  $TRAP_syscall,UREGS_entry_vector+8(%rsp)
 
413
        andl  $~(X86_EFLAGS_AC|X86_EFLAGS_VM|X86_EFLAGS_RF|\
 
414
                 X86_EFLAGS_NT|X86_EFLAGS_TF),UREGS_eflags+8(%rsp)
 
415
        movq  $FLAT_KERNEL_SS,UREGS_ss+8(%rsp)
 
416
        movq  %rsi,UREGS_rsp+8(%rsp)
 
417
        movq  $FLAT_KERNEL_CS,UREGS_cs+8(%rsp)
 
418
        movq  TRAPBOUNCE_eip(%rdx),%rax
 
419
        testq %rax,%rax
 
420
        jz    domain_crash_synchronous
 
421
        movq  %rax,UREGS_rip+8(%rsp)
 
422
        ret
 
423
.section __ex_table,"a"
 
424
        .quad  .Lft2,domain_crash_synchronous ,  .Lft3,domain_crash_synchronous
 
425
        .quad  .Lft4,domain_crash_synchronous ,  .Lft5,domain_crash_synchronous
 
426
        .quad  .Lft6,domain_crash_synchronous ,  .Lft7,domain_crash_synchronous
 
427
        .quad  .Lft8,domain_crash_synchronous ,  .Lft9,domain_crash_synchronous
 
428
        .quad .Lft10,domain_crash_synchronous , .Lft11,domain_crash_synchronous
 
429
        .quad .Lft12,domain_crash_synchronous , .Lft13,domain_crash_synchronous
 
430
.previous
 
431
 
 
432
domain_crash_synchronous_string:
 
433
        .asciz "domain_crash_sync called from entry.S\n"
 
434
 
 
435
ENTRY(domain_crash_synchronous)
 
436
        # Get out of the guest-save area of the stack.
 
437
        GET_GUEST_REGS(%rax)
 
438
        movq  %rax,%rsp
 
439
        # create_bounce_frame() temporarily clobbers CS.RPL. Fix up.
 
440
        movq  CPUINFO_current_vcpu(%rax),%rax
 
441
        movq  VCPU_domain(%rax),%rax
 
442
        testb $1,DOMAIN_is_32bit_pv(%rax)
 
443
        setz  %al
 
444
        leal  (%rax,%rax,2),%eax
 
445
        orb   %al,UREGS_cs(%rsp)
 
446
        # printk(domain_crash_synchronous_string)
 
447
        leaq  domain_crash_synchronous_string(%rip),%rdi
 
448
        xorl  %eax,%eax
 
449
        call  printk
 
450
        jmp  __domain_crash_synchronous
 
451
 
 
452
        ALIGN
 
453
/* No special register assumptions. */
 
454
ENTRY(ret_from_intr)
 
455
        GET_CURRENT(%rbx)
 
456
        testb $3,UREGS_cs(%rsp)
 
457
        jz    restore_all_xen
 
458
        movq  VCPU_domain(%rbx),%rax
 
459
        testb $1,DOMAIN_is_32bit_pv(%rax)
 
460
        jz    test_all_events
 
461
        jmp   compat_test_all_events
 
462
 
 
463
        ALIGN
 
464
/* No special register assumptions. */
 
465
ENTRY(handle_exception)
 
466
        SAVE_ALL
 
467
handle_exception_saved:
 
468
        testb $X86_EFLAGS_IF>>8,UREGS_eflags+1(%rsp)
 
469
        jz    exception_with_ints_disabled
 
470
        sti
 
471
1:      movq  %rsp,%rdi
 
472
        movl  UREGS_entry_vector(%rsp),%eax
 
473
        leaq  exception_table(%rip),%rdx
 
474
        GET_CURRENT(%rbx)
 
475
        PERFC_INCR(PERFC_exceptions, %rax, %rbx)
 
476
        callq *(%rdx,%rax,8)
 
477
        testb $3,UREGS_cs(%rsp)
 
478
        jz    restore_all_xen
 
479
        leaq  VCPU_trap_bounce(%rbx),%rdx
 
480
        movq  VCPU_domain(%rbx),%rax
 
481
        testb $1,DOMAIN_is_32bit_pv(%rax)
 
482
        jnz   compat_post_handle_exception
 
483
        testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%rdx)
 
484
        jz    test_all_events
 
485
        call  create_bounce_frame
 
486
        movb  $0,TRAPBOUNCE_flags(%rdx)
 
487
        jmp   test_all_events
 
488
 
 
489
/* No special register assumptions. */
 
490
exception_with_ints_disabled:
 
491
        testb $3,UREGS_cs(%rsp)         # interrupts disabled outside Xen?
 
492
        jnz   FATAL_exception_with_ints_disabled
 
493
        movq  %rsp,%rdi
 
494
        call  search_pre_exception_table
 
495
        testq %rax,%rax                 # no fixup code for faulting EIP?
 
496
        jz    1b
 
497
        movq  %rax,UREGS_rip(%rsp)
 
498
        subq  $8,UREGS_rsp(%rsp)        # add ec/ev to previous stack frame
 
499
        testb $15,UREGS_rsp(%rsp)       # return %rsp is now aligned?
 
500
        jz    1f                        # then there is a pad quadword already
 
501
        movq  %rsp,%rsi
 
502
        subq  $8,%rsp
 
503
        movq  %rsp,%rdi
 
504
        movq  $UREGS_kernel_sizeof/8,%rcx
 
505
        rep;  movsq                     # make room for ec/ev
 
506
1:      movq  UREGS_error_code(%rsp),%rax # ec/ev
 
507
        movq  %rax,UREGS_kernel_sizeof(%rsp)
 
508
        jmp   restore_all_xen           # return to fixup code
 
509
 
 
510
/* No special register assumptions. */
 
511
FATAL_exception_with_ints_disabled:
 
512
        movl  UREGS_entry_vector(%rsp),%edi
 
513
        movq  %rsp,%rsi
 
514
        call  fatal_trap
 
515
        ud2
 
516
 
 
517
ENTRY(divide_error)
 
518
        pushq $0
 
519
        movl  $TRAP_divide_error,4(%rsp)
 
520
        jmp   handle_exception
 
521
 
 
522
ENTRY(coprocessor_error)
 
523
        pushq $0
 
524
        movl  $TRAP_copro_error,4(%rsp)
 
525
        jmp   handle_exception
 
526
 
 
527
ENTRY(simd_coprocessor_error)
 
528
        pushq $0
 
529
        movl  $TRAP_simd_error,4(%rsp)
 
530
        jmp   handle_exception
 
531
 
 
532
ENTRY(device_not_available)
 
533
        pushq $0
 
534
        movl  $TRAP_no_device,4(%rsp)
 
535
        jmp   handle_exception
 
536
 
 
537
ENTRY(debug)
 
538
        pushq $0
 
539
        movl  $TRAP_debug,4(%rsp)
 
540
        jmp   handle_exception
 
541
 
 
542
ENTRY(int3)
 
543
        pushq $0
 
544
        movl  $TRAP_int3,4(%rsp)
 
545
        jmp   handle_exception
 
546
 
 
547
ENTRY(overflow)
 
548
        pushq $0
 
549
        movl  $TRAP_overflow,4(%rsp)
 
550
        jmp   handle_exception
 
551
 
 
552
ENTRY(bounds)
 
553
        pushq $0
 
554
        movl  $TRAP_bounds,4(%rsp)
 
555
        jmp   handle_exception
 
556
 
 
557
ENTRY(invalid_op)
 
558
        pushq $0
 
559
        movl  $TRAP_invalid_op,4(%rsp)
 
560
        jmp   handle_exception
 
561
 
 
562
ENTRY(coprocessor_segment_overrun)
 
563
        pushq $0
 
564
        movl  $TRAP_copro_seg,4(%rsp)
 
565
        jmp   handle_exception
 
566
 
 
567
ENTRY(invalid_TSS)
 
568
        movl  $TRAP_invalid_tss,4(%rsp)
 
569
        jmp   handle_exception
 
570
 
 
571
ENTRY(segment_not_present)
 
572
        movl  $TRAP_no_segment,4(%rsp)
 
573
        jmp   handle_exception
 
574
 
 
575
ENTRY(stack_segment)
 
576
        movl  $TRAP_stack_error,4(%rsp)
 
577
        jmp   handle_exception
 
578
 
 
579
ENTRY(general_protection)
 
580
        movl  $TRAP_gp_fault,4(%rsp)
 
581
        jmp   handle_exception
 
582
 
 
583
ENTRY(alignment_check)
 
584
        movl  $TRAP_alignment_check,4(%rsp)
 
585
        jmp   handle_exception
 
586
 
 
587
ENTRY(page_fault)
 
588
        movl  $TRAP_page_fault,4(%rsp)
 
589
        jmp   handle_exception
 
590
 
 
591
ENTRY(spurious_interrupt_bug)
 
592
        pushq $0
 
593
        movl  $TRAP_spurious_int,4(%rsp)
 
594
        jmp   handle_exception
 
595
 
 
596
ENTRY(double_fault)
 
597
        SAVE_ALL
 
598
        movq  %rsp,%rdi
 
599
        call  do_double_fault
 
600
        ud2
 
601
 
 
602
ENTRY(early_page_fault)
 
603
        SAVE_ALL
 
604
        movq  %rsp,%rdi
 
605
        call  do_early_page_fault
 
606
        jmp   restore_all_xen
 
607
 
 
608
handle_ist_exception:
 
609
        SAVE_ALL
 
610
        testb $3,UREGS_cs(%rsp)
 
611
        jz    1f
 
612
        /* Interrupted guest context. Copy the context to stack bottom. */
 
613
        GET_GUEST_REGS(%rdi)
 
614
        movq  %rsp,%rsi
 
615
        movl  $UREGS_kernel_sizeof/8,%ecx
 
616
        movq  %rdi,%rsp
 
617
        rep   movsq
 
618
1:      movq  %rsp,%rdi
 
619
        movl  UREGS_entry_vector(%rsp),%eax
 
620
        leaq  exception_table(%rip),%rdx
 
621
        callq *(%rdx,%rax,8)
 
622
        jmp   ret_from_intr
 
623
 
 
624
ENTRY(nmi)
 
625
        pushq $0
 
626
        movl  $TRAP_nmi,4(%rsp)
 
627
        jmp   handle_ist_exception
 
628
 
 
629
ENTRY(machine_check)
 
630
        pushq $0
 
631
        movl  $TRAP_machine_check,4(%rsp)
 
632
        jmp   handle_ist_exception
 
633
 
 
634
.section .rodata, "a", @progbits
 
635
 
 
636
ENTRY(exception_table)
 
637
        .quad do_divide_error
 
638
        .quad do_debug
 
639
        .quad do_nmi
 
640
        .quad do_int3
 
641
        .quad do_overflow
 
642
        .quad do_bounds
 
643
        .quad do_invalid_op
 
644
        .quad do_device_not_available
 
645
        .quad 0 # double_fault
 
646
        .quad do_coprocessor_segment_overrun
 
647
        .quad do_invalid_TSS
 
648
        .quad do_segment_not_present
 
649
        .quad do_stack_segment
 
650
        .quad do_general_protection
 
651
        .quad do_page_fault
 
652
        .quad do_spurious_interrupt_bug
 
653
        .quad do_coprocessor_error
 
654
        .quad do_alignment_check
 
655
        .quad do_machine_check
 
656
        .quad do_simd_coprocessor_error
 
657
 
 
658
ENTRY(hypercall_table)
 
659
        .quad do_set_trap_table     /*  0 */
 
660
        .quad do_mmu_update
 
661
        .quad do_set_gdt
 
662
        .quad do_stack_switch
 
663
        .quad do_set_callbacks
 
664
        .quad do_fpu_taskswitch     /*  5 */
 
665
        .quad do_sched_op_compat
 
666
        .quad do_platform_op
 
667
        .quad do_set_debugreg
 
668
        .quad do_get_debugreg
 
669
        .quad do_update_descriptor  /* 10 */
 
670
        .quad do_ni_hypercall
 
671
        .quad do_memory_op
 
672
        .quad do_multicall
 
673
        .quad do_update_va_mapping
 
674
        .quad do_set_timer_op       /* 15 */
 
675
        .quad do_event_channel_op_compat
 
676
        .quad do_xen_version
 
677
        .quad do_console_io
 
678
        .quad do_physdev_op_compat
 
679
        .quad do_grant_table_op     /* 20 */
 
680
        .quad do_vm_assist
 
681
        .quad do_update_va_mapping_otherdomain
 
682
        .quad do_iret
 
683
        .quad do_vcpu_op
 
684
        .quad do_set_segment_base   /* 25 */
 
685
        .quad do_mmuext_op
 
686
        .quad do_xsm_op
 
687
        .quad do_nmi_op
 
688
        .quad do_sched_op
 
689
        .quad do_callback_op        /* 30 */
 
690
        .quad do_xenoprof_op
 
691
        .quad do_event_channel_op
 
692
        .quad do_physdev_op
 
693
        .quad do_hvm_op
 
694
        .quad do_sysctl             /* 35 */
 
695
        .quad do_domctl
 
696
        .quad do_kexec_op
 
697
        .quad do_tmem_op
 
698
        .rept __HYPERVISOR_arch_0-((.-hypercall_table)/8)
 
699
        .quad do_ni_hypercall
 
700
        .endr
 
701
        .quad do_mca                /* 48 */
 
702
        .rept NR_hypercalls-((.-hypercall_table)/8)
 
703
        .quad do_ni_hypercall
 
704
        .endr
 
705
 
 
706
ENTRY(hypercall_args_table)
 
707
        .byte 1 /* do_set_trap_table    */  /*  0 */
 
708
        .byte 4 /* do_mmu_update        */
 
709
        .byte 2 /* do_set_gdt           */
 
710
        .byte 2 /* do_stack_switch      */
 
711
        .byte 3 /* do_set_callbacks     */
 
712
        .byte 1 /* do_fpu_taskswitch    */  /*  5 */
 
713
        .byte 2 /* do_sched_op_compat   */
 
714
        .byte 1 /* do_platform_op       */
 
715
        .byte 2 /* do_set_debugreg      */
 
716
        .byte 1 /* do_get_debugreg      */
 
717
        .byte 2 /* do_update_descriptor */  /* 10 */
 
718
        .byte 0 /* do_ni_hypercall      */
 
719
        .byte 2 /* do_memory_op         */
 
720
        .byte 2 /* do_multicall         */
 
721
        .byte 3 /* do_update_va_mapping */
 
722
        .byte 1 /* do_set_timer_op      */  /* 15 */
 
723
        .byte 1 /* do_event_channel_op_compat */
 
724
        .byte 2 /* do_xen_version       */
 
725
        .byte 3 /* do_console_io        */
 
726
        .byte 1 /* do_physdev_op_compat */
 
727
        .byte 3 /* do_grant_table_op    */  /* 20 */
 
728
        .byte 2 /* do_vm_assist         */
 
729
        .byte 4 /* do_update_va_mapping_otherdomain */
 
730
        .byte 0 /* do_iret              */
 
731
        .byte 3 /* do_vcpu_op           */
 
732
        .byte 2 /* do_set_segment_base  */  /* 25 */
 
733
        .byte 4 /* do_mmuext_op         */
 
734
        .byte 1 /* do_xsm_op            */
 
735
        .byte 2 /* do_nmi_op            */
 
736
        .byte 2 /* do_sched_op          */
 
737
        .byte 2 /* do_callback_op       */  /* 30 */
 
738
        .byte 2 /* do_xenoprof_op       */
 
739
        .byte 2 /* do_event_channel_op  */
 
740
        .byte 2 /* do_physdev_op        */
 
741
        .byte 2 /* do_hvm_op            */
 
742
        .byte 1 /* do_sysctl            */  /* 35 */
 
743
        .byte 1 /* do_domctl            */
 
744
        .byte 2 /* do_kexec             */
 
745
        .byte 1 /* do_tmem_op           */
 
746
        .rept __HYPERVISOR_arch_0-(.-hypercall_args_table)
 
747
        .byte 0 /* do_ni_hypercall      */
 
748
        .endr
 
749
        .byte 1 /* do_mca               */  /* 48 */
 
750
        .rept NR_hypercalls-(.-hypercall_args_table)
 
751
        .byte 0 /* do_ni_hypercall      */
 
752
        .endr