ia64/xen-unstable

changeset 13289:5a690aa51fb5

Add entry points for handling hypercalls from and returning to
compatibility mode guests.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Emmanuel Ackaouy <ack@xensource.com>
date Fri Jan 05 17:34:27 2007 +0000 (2007-01-05)
parents 7c5eea5feebd
children e98b092c2057
files xen/arch/x86/traps.c xen/arch/x86/x86_64/Makefile xen/arch/x86/x86_64/asm-offsets.c xen/arch/x86/x86_64/compat/entry.S xen/arch/x86/x86_64/compat/traps.c xen/arch/x86/x86_64/entry.S xen/arch/x86/x86_64/traps.c xen/include/asm-x86/processor.h
line diff
     1.1 --- a/xen/arch/x86/traps.c	Fri Jan 05 17:32:00 2007 +0000
     1.2 +++ b/xen/arch/x86/traps.c	Fri Jan 05 17:34:27 2007 +0000
     1.3 @@ -123,6 +123,12 @@ static void show_guest_stack(struct cpu_
     1.4      if ( is_hvm_vcpu(current) )
     1.5          return;
     1.6  
     1.7 +    if ( IS_COMPAT(container_of(regs, struct cpu_info, guest_cpu_user_regs)->current_vcpu->domain) )
     1.8 +    {
     1.9 +        compat_show_guest_stack(regs, debug_stack_lines);
    1.10 +        return;
    1.11 +    }
    1.12 +
    1.13      if ( vm86_mode(regs) )
    1.14      {
    1.15          stack = (unsigned long *)((regs->ss << 4) + (regs->esp & 0xffff));
     2.1 --- a/xen/arch/x86/x86_64/Makefile	Fri Jan 05 17:32:00 2007 +0000
     2.2 +++ b/xen/arch/x86/x86_64/Makefile	Fri Jan 05 17:34:27 2007 +0000
     2.3 @@ -2,3 +2,9 @@ obj-y += entry.o
     2.4  obj-y += gpr_switch.o
     2.5  obj-y += mm.o
     2.6  obj-y += traps.o
     2.7 +
     2.8 +ifeq ($(CONFIG_COMPAT),y)
     2.9 +# extra dependencies
    2.10 +entry.o:	compat/entry.S
    2.11 +traps.o:	compat/traps.c
    2.12 +endif
     3.1 --- a/xen/arch/x86/x86_64/asm-offsets.c	Fri Jan 05 17:32:00 2007 +0000
     3.2 +++ b/xen/arch/x86/x86_64/asm-offsets.c	Fri Jan 05 17:34:27 2007 +0000
     3.3 @@ -53,6 +53,7 @@ void __dummy__(void)
     3.4      BLANK();
     3.5  
     3.6      OFFSET(VCPU_processor, struct vcpu, processor);
     3.7 +    OFFSET(VCPU_domain, struct vcpu, domain);
     3.8      OFFSET(VCPU_vcpu_info, struct vcpu, vcpu_info);
     3.9      OFFSET(VCPU_trap_bounce, struct vcpu, arch.trap_bounce);
    3.10      OFFSET(VCPU_thread_flags, struct vcpu, arch.flags);
    3.11 @@ -87,6 +88,10 @@ void __dummy__(void)
    3.12      OFFSET(VCPU_vmx_cr2, struct vcpu, arch.hvm_vmx.cpu_cr2);
    3.13      BLANK();
    3.14  
    3.15 +    OFFSET(DOMAIN_domain_flags, struct domain, domain_flags);
    3.16 +    DEFINE(_DOMF_compat, _DOMF_compat);
    3.17 +    BLANK();
    3.18 +
    3.19      OFFSET(VMCB_rax, struct vmcb_struct, rax);
    3.20      OFFSET(VMCB_tsc_offset, struct vmcb_struct, tsc_offset);
    3.21      BLANK();
    3.22 @@ -95,6 +100,7 @@ void __dummy__(void)
    3.23      OFFSET(VCPUINFO_upcall_mask, vcpu_info_t, evtchn_upcall_mask);
    3.24      BLANK();
    3.25  
    3.26 +    OFFSET(CPUINFO_current_vcpu, struct cpu_info, current_vcpu);
    3.27      DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
    3.28      BLANK();
    3.29  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/xen/arch/x86/x86_64/compat/entry.S	Fri Jan 05 17:34:27 2007 +0000
     4.3 @@ -0,0 +1,395 @@
     4.4 +/*
     4.5 + * Compatibility hypercall routines.
     4.6 + */
     4.7 +
     4.8 +#include <asm/desc.h>
     4.9 +
    4.10 +.text
    4.11 +
    4.12 +ENTRY(compat_hypercall)
    4.13 +        pushq $0
    4.14 +        movl  $TRAP_syscall,4(%rsp)
    4.15 +        SAVE_ALL
    4.16 +        GET_CURRENT(%rbx)
    4.17 +
    4.18 +        cmpl  $NR_hypercalls,%eax
    4.19 +        jae   compat_bad_hypercall
    4.20 +#ifndef NDEBUG
    4.21 +        /* Deliberately corrupt parameter regs not used by this hypercall. */
    4.22 +        pushq UREGS_rbx(%rsp); pushq %rcx; pushq %rdx; pushq %rsi; pushq %rdi; pushq UREGS_rbp+5*8(%rsp)
    4.23 +        leaq  compat_hypercall_args_table(%rip),%r10
    4.24 +        movq  $6,%rcx
    4.25 +        subb  (%r10,%rax,1),%cl
    4.26 +        movq  %rsp,%rdi
    4.27 +        movl  $0xDEADBEEF,%eax
    4.28 +        rep   stosq
    4.29 +        popq  %r9 ; popq  %r8 ; popq  %rcx; popq  %rdx; popq  %rsi; popq  %rdi
    4.30 +        movl  UREGS_rax(%rsp),%eax
    4.31 +        pushq %rax
    4.32 +        pushq UREGS_rip+8(%rsp)
    4.33 +#else
    4.34 +        movl  %eax,%eax
    4.35 +        movl  %ebp,%r9d
    4.36 +        movl  %edi,%r8d
    4.37 +        xchgl  %ecx,%esi
    4.38 +        movl  UREGS_rbx(%rsp),%edi
    4.39 +#endif
    4.40 +        leaq  compat_hypercall_table(%rip),%r10
    4.41 +        PERFC_INCR(PERFC_hypercalls, %rax)
    4.42 +        callq *(%r10,%rax,8)
    4.43 +#ifndef NDEBUG
    4.44 +        /* Deliberately corrupt parameter regs used by this hypercall. */
    4.45 +        popq  %r10         # Shadow RIP
    4.46 +        cmpq  %r10,UREGS_rip+8(%rsp)
    4.47 +        popq  %rcx         # Shadow hypercall index
    4.48 +        jne   compat_skip_clobber /* If RIP has changed then don't clobber. */
    4.49 +        leaq  compat_hypercall_args_table(%rip),%r10
    4.50 +        movb  (%r10,%rcx,1),%cl
    4.51 +        movl  $0xDEADBEEF,%r10d
    4.52 +        testb %cl,%cl; jz compat_skip_clobber; movl %r10d,UREGS_rbx(%rsp)
    4.53 +        cmpb  $2, %cl; jb compat_skip_clobber; movl %r10d,UREGS_rcx(%rsp)
    4.54 +        cmpb  $3, %cl; jb compat_skip_clobber; movl %r10d,UREGS_rdx(%rsp)
    4.55 +        cmpb  $4, %cl; jb compat_skip_clobber; movl %r10d,UREGS_rsi(%rsp)
    4.56 +        cmpb  $5, %cl; jb compat_skip_clobber; movl %r10d,UREGS_rdi(%rsp)
    4.57 +        cmpb  $6, %cl; jb compat_skip_clobber; movl %r10d,UREGS_rbp(%rsp)
    4.58 +compat_skip_clobber:
    4.59 +#endif
    4.60 +        movl  %eax,UREGS_rax(%rsp)       # save the return value
    4.61 +
    4.62 +/* %rbx: struct vcpu */
    4.63 +compat_test_all_events:
    4.64 +        cli                             # tests must not race interrupts
    4.65 +/*compat_test_softirqs:*/
    4.66 +        movl  VCPU_processor(%rbx),%eax
    4.67 +        shlq  $IRQSTAT_shift,%rax
    4.68 +        leaq  irq_stat(%rip),%rcx
    4.69 +        testl $~0,(%rcx,%rax,1)
    4.70 +        jnz   compat_process_softirqs
    4.71 +        btrq  $_VCPUF_nmi_pending,VCPU_flags(%rbx)
    4.72 +        jc    compat_process_nmi
    4.73 +compat_test_guest_events:
    4.74 +        movq  VCPU_vcpu_info(%rbx),%rax
    4.75 +        testb $0xFF,VCPUINFO_upcall_mask(%rax)
    4.76 +        jnz   compat_restore_all_guest
    4.77 +        testb $0xFF,VCPUINFO_upcall_pending(%rax)
    4.78 +        jz    compat_restore_all_guest
    4.79 +/*compat_process_guest_events:*/
    4.80 +        sti
    4.81 +        leaq  VCPU_trap_bounce(%rbx),%rdx
    4.82 +        movl  VCPU_event_addr(%rbx),%eax
    4.83 +        movl  %eax,TRAPBOUNCE_eip(%rdx)
    4.84 +        movl  VCPU_event_sel(%rbx),%eax
    4.85 +        movl  %eax,TRAPBOUNCE_cs(%rdx)
    4.86 +        movw  $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx)
    4.87 +        call  compat_create_bounce_frame
    4.88 +        jmp   compat_test_all_events
    4.89 +
    4.90 +        ALIGN
    4.91 +/* %rbx: struct vcpu */
    4.92 +compat_process_softirqs:
    4.93 +        sti
    4.94 +        call  do_softirq
    4.95 +        jmp   compat_test_all_events
    4.96 +
    4.97 +	ALIGN
    4.98 +/* %rbx: struct vcpu */
    4.99 +compat_process_nmi:
   4.100 +        movl  VCPU_nmi_addr(%rbx),%eax
   4.101 +        testl %eax,%eax
   4.102 +        jz    compat_test_all_events
   4.103 +        btsq  $_VCPUF_nmi_masked,VCPU_flags(%rbx)
   4.104 +        jc    1f
   4.105 +        sti
   4.106 +        leaq  VCPU_trap_bounce(%rbx),%rdx
   4.107 +        movl  %eax,TRAPBOUNCE_eip(%rdx)
   4.108 +        movl  $FLAT_COMPAT_KERNEL_CS,TRAPBOUNCE_cs(%rdx)
   4.109 +        movw  $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx)
   4.110 +        call  compat_create_bounce_frame
   4.111 +        jmp   compat_test_all_events
   4.112 +1:
   4.113 +        btsq  $_VCPUF_nmi_pending,VCPU_flags(%rbx)
   4.114 +        jmp   compat_test_guest_events
   4.115 +
   4.116 +compat_bad_hypercall:
   4.117 +        movl $-ENOSYS,UREGS_rax(%rsp)
   4.118 +        jmp  compat_test_all_events
   4.119 +
   4.120 +/* %rbx: struct vcpu, interrupts disabled */
   4.121 +compat_restore_all_guest:
   4.122 +        RESTORE_ALL
   4.123 +        addq  $8,%rsp
   4.124 +CFLT0:  iretq
   4.125 +
   4.126 +.section .fixup,"ax"
   4.127 +CFIX0:  popq  -15*8-8(%rsp)            # error_code/entry_vector
   4.128 +        SAVE_ALL                       # 15*8 bytes pushed
   4.129 +        movq  -8(%rsp),%rsi            # error_code/entry_vector
   4.130 +        sti                            # after stack abuse (-1024(%rsp))
   4.131 +        pushq $__HYPERVISOR_DS         # SS
   4.132 +        leaq  8(%rsp),%rax
   4.133 +        pushq %rax                     # RSP
   4.134 +        pushfq                         # RFLAGS
   4.135 +        pushq $__HYPERVISOR_CS         # CS
   4.136 +        leaq  CDBLFLT0(%rip),%rax
   4.137 +        pushq %rax                     # RIP
   4.138 +        pushq %rsi                     # error_code/entry_vector
   4.139 +        jmp   handle_exception
   4.140 +CDBLFLT0:GET_CURRENT(%rbx)
   4.141 +        jmp   compat_test_all_events
   4.142 +compat_failsafe_callback:
   4.143 +        GET_CURRENT(%rbx)
   4.144 +        leaq  VCPU_trap_bounce(%rbx),%rdx
   4.145 +        movl  VCPU_failsafe_addr(%rbx),%eax
   4.146 +        movl  %eax,TRAPBOUNCE_eip(%rdx)
   4.147 +        movl  VCPU_failsafe_sel(%rbx),%eax
   4.148 +        movl  %eax,TRAPBOUNCE_cs(%rdx)
   4.149 +        movw  $TBF_FAILSAFE,TRAPBOUNCE_flags(%rdx)
   4.150 +        btq   $_VGCF_failsafe_disables_events,VCPU_guest_context_flags(%rbx)
   4.151 +        jnc   1f
   4.152 +        orw   $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx)
   4.153 +1:
   4.154 +        call  compat_create_bounce_frame
   4.155 +        jmp   compat_test_all_events
   4.156 +.previous
   4.157 +.section __pre_ex_table,"a"
   4.158 +	.quad CFLT0,CFIX0
   4.159 +.previous
   4.160 +.section __ex_table,"a"
   4.161 +        .quad CDBLFLT0,compat_failsafe_callback
   4.162 +.previous
   4.163 +
   4.164 +/* %rdx: trap_bounce, %rbx: struct vcpu */
   4.165 +compat_post_handle_exception:
   4.166 +        testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%rdx)
   4.167 +        jz    compat_test_all_events
   4.168 +        call  compat_create_bounce_frame
   4.169 +        jmp   compat_test_all_events
   4.170 +
   4.171 +/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK:            */
   4.172 +/*   {[ERRCODE,] EIP, CS, EFLAGS, [ESP, SS]}                             */
   4.173 +/* %rdx: trap_bounce, %rbx: struct vcpu                                  */
   4.174 +/* On return only %rbx is guaranteed non-clobbered.                      */
   4.175 +compat_create_bounce_frame:
   4.176 +        mov   %fs,%edi
   4.177 +        testb $2,UREGS_cs+8(%rsp)
   4.178 +        jz    1f
   4.179 +        /* Push new frame at registered guest-OS stack base. */
   4.180 +        movl  VCPU_kernel_sp(%rbx),%esi
   4.181 +CFLT1:  mov   VCPU_kernel_ss(%rbx),%fs
   4.182 +        subl  $2*4,%esi
   4.183 +        movl  UREGS_rsp+8(%rsp),%eax
   4.184 +CFLT2:  movl  %eax,%fs:(%rsi)
   4.185 +        movl  UREGS_ss+8(%rsp),%eax
   4.186 +CFLT3:  movl  %eax,%fs:4(%rsi)
   4.187 +        jmp   2f
   4.188 +1:      /* In kernel context already: push new frame at existing %rsp. */
   4.189 +        movl  UREGS_rsp+8(%rsp),%esi
   4.190 +CFLT4:  mov   UREGS_ss+8(%rsp),%fs
   4.191 +2:
   4.192 +        movb  TRAPBOUNCE_flags(%rdx),%cl
   4.193 +        subl  $3*4,%esi
   4.194 +        movq  VCPU_vcpu_info(%rbx),%rax
   4.195 +        pushq VCPUINFO_upcall_mask(%rax)
   4.196 +        testb $TBF_INTERRUPT,%cl
   4.197 +        setnz %ch                       # TBF_INTERRUPT -> set upcall mask
   4.198 +        orb   %ch,VCPUINFO_upcall_mask(%rax)
   4.199 +        popq  %rax
   4.200 +        shll  $16,%eax                  # Bits 16-23: saved_upcall_mask
   4.201 +        movw  UREGS_cs+8(%rsp),%ax      # Bits  0-15: CS
   4.202 +CFLT5:  movl  %eax,%fs:4(%rsi)          # CS / saved_upcall_mask
   4.203 +        shrl  $16,%eax
   4.204 +        testb %al,%al                   # Bits 0-7: saved_upcall_mask
   4.205 +        setz  %ch                       # %ch == !saved_upcall_mask
   4.206 +        movl  UREGS_eflags+8(%rsp),%eax
   4.207 +        andl  $~X86_EFLAGS_IF,%eax
   4.208 +        shlb  $1,%ch                    # Bit 9 (EFLAGS.IF)
   4.209 +        orb   %ch,%ah                   # Fold EFLAGS.IF into %eax
   4.210 +CFLT6:  movl  %eax,%fs:2*4(%rsi)        # EFLAGS
   4.211 +        movl  UREGS_rip+8(%rsp),%eax
   4.212 +CFLT7:  movl  %eax,%fs:(%rsi)           # EIP
   4.213 +        testb $TBF_EXCEPTION_ERRCODE,%cl
   4.214 +        jz    1f
   4.215 +        subl  $4,%esi
   4.216 +        movl  TRAPBOUNCE_error_code(%rdx),%eax
   4.217 +CFLT8:  movl  %eax,%fs:(%rsi)           # ERROR CODE
   4.218 +1:
   4.219 +        testb $TBF_FAILSAFE,%cl
   4.220 +        jz    2f
   4.221 +        subl  $4*4,%esi
   4.222 +        movl  %gs,%eax
   4.223 +CFLT9:  movl  %eax,%fs:3*4(%rsi)        # GS
   4.224 +CFLT10: movl  %edi,%fs:2*4(%rsi)        # FS
   4.225 +        movl  %es,%eax
   4.226 +CFLT11: movl  %eax,%fs:1*4(%rsi)        # ES
   4.227 +        movl  %ds,%eax
   4.228 +CFLT12: movl  %eax,%fs:0*4(%rsi)        # DS
   4.229 +2:
   4.230 +        /* Rewrite our stack frame and return to guest-OS mode. */
   4.231 +        /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */
   4.232 +        movl  $TRAP_syscall,UREGS_entry_vector+8(%rsp)
   4.233 +        andl  $~(X86_EFLAGS_VM|X86_EFLAGS_RF|\
   4.234 +                 X86_EFLAGS_NT|X86_EFLAGS_TF),UREGS_eflags+8(%rsp)
   4.235 +        mov   %fs,UREGS_ss+8(%rsp)
   4.236 +        movl  %esi,UREGS_rsp+8(%rsp)
   4.237 +CFLT13: mov   %edi,%fs
   4.238 +        movzwl TRAPBOUNCE_cs(%rdx),%eax
   4.239 +        /* Null selectors (0-3) are not allowed. */
   4.240 +        testl $~3,%eax
   4.241 +        jz    domain_crash_synchronous
   4.242 +        movl  %eax,UREGS_cs+8(%rsp)
   4.243 +        movl  TRAPBOUNCE_eip(%rdx),%eax
   4.244 +        movl  %eax,UREGS_rip+8(%rsp)
   4.245 +        movb  $0,TRAPBOUNCE_flags(%rdx)
   4.246 +        ret
   4.247 +.section .fixup,"ax"
   4.248 +CFIX13:
   4.249 +        xorl  %edi,%edi
   4.250 +        jmp   CFLT13
   4.251 +.previous
   4.252 +.section __ex_table,"a"
   4.253 +        .quad  CFLT1,domain_crash_synchronous  ,  CFLT2,compat_crash_page_fault
   4.254 +        .quad  CFLT3,compat_crash_page_fault_4 ,  CFLT4,domain_crash_synchronous
   4.255 +        .quad  CFLT5,compat_crash_page_fault_4 ,  CFLT6,compat_crash_page_fault_8
   4.256 +        .quad  CFLT7,compat_crash_page_fault   ,  CFLT8,compat_crash_page_fault
   4.257 +        .quad  CFLT9,compat_crash_page_fault_12, CFLT10,compat_crash_page_fault_8
   4.258 +        .quad CFLT11,compat_crash_page_fault_4 , CFLT12,compat_crash_page_fault
   4.259 +        .quad CFLT13,CFIX13
   4.260 +.previous
   4.261 +
   4.262 +compat_crash_page_fault_12:
   4.263 +        addl  $4,%esi
   4.264 +compat_crash_page_fault_8:
   4.265 +        addl  $4,%esi
   4.266 +compat_crash_page_fault_4:
   4.267 +        addl  $4,%esi
   4.268 +compat_crash_page_fault:
   4.269 +CFLT14: mov   %edi,%fs
   4.270 +        movl  %esi,%edi
   4.271 +        call  show_page_walk
   4.272 +        jmp   domain_crash_synchronous
   4.273 +.section .fixup,"ax"
   4.274 +CFIX14:
   4.275 +        xorl  %edi,%edi
   4.276 +        jmp   CFLT14
   4.277 +.previous
   4.278 +.section __ex_table,"a"
   4.279 +        .quad CFLT14,CFIX14
   4.280 +.previous
   4.281 +
   4.282 +.section .rodata, "a", @progbits
   4.283 +
   4.284 +#define compat_set_trap_table domain_crash_synchronous
   4.285 +#define compat_mmu_update domain_crash_synchronous
   4.286 +#define compat_set_gdt domain_crash_synchronous
   4.287 +#define compat_stack_switch domain_crash_synchronous
   4.288 +#define compat_fpu_taskswitch domain_crash_synchronous
   4.289 +#define compat_arch_sched_op_compat domain_crash_synchronous
   4.290 +#define compat_platform_op domain_crash_synchronous
   4.291 +#define compat_set_debugreg domain_crash_synchronous
   4.292 +#define compat_get_debugreg domain_crash_synchronous
   4.293 +#define compat_update_descriptor domain_crash_synchronous
   4.294 +#define compat_memory_op domain_crash_synchronous
   4.295 +#define compat_multicall domain_crash_synchronous
   4.296 +#define compat_update_va_mapping domain_crash_synchronous
   4.297 +#define compat_set_timer_op domain_crash_synchronous
   4.298 +#define compat_event_channel_op_compat domain_crash_synchronous
   4.299 +#define compat_xen_version domain_crash_synchronous
   4.300 +#define compat_console_io domain_crash_synchronous
   4.301 +#define compat_physdev_op_compat domain_crash_synchronous
   4.302 +#define compat_grant_table_op domain_crash_synchronous
   4.303 +#define compat_vm_assist domain_crash_synchronous
   4.304 +#define compat_update_va_mapping_otherdomain domain_crash_synchronous
   4.305 +#define compat_vcpu_op domain_crash_synchronous
   4.306 +#define compat_mmuext_op domain_crash_synchronous
   4.307 +#define compat_acm_op domain_crash_synchronous
   4.308 +#define compat_nmi_op domain_crash_synchronous
   4.309 +#define compat_arch_sched_op domain_crash_synchronous
   4.310 +#define compat_xenoprof_op domain_crash_synchronous
   4.311 +#define compat_event_channel_op domain_crash_synchronous
   4.312 +#define compat_physdev_op domain_crash_synchronous
   4.313 +#define compat_sysctl domain_crash_synchronous
   4.314 +#define compat_domctl domain_crash_synchronous
   4.315 +
   4.316 +ENTRY(compat_hypercall_table)
   4.317 +        .quad compat_set_trap_table     /*  0 */
   4.318 +        .quad compat_mmu_update
   4.319 +        .quad compat_set_gdt
   4.320 +        .quad compat_stack_switch
   4.321 +        .quad compat_set_callbacks
   4.322 +        .quad compat_fpu_taskswitch     /*  5 */
   4.323 +        .quad compat_arch_sched_op_compat
   4.324 +        .quad compat_platform_op
   4.325 +        .quad compat_set_debugreg
   4.326 +        .quad compat_get_debugreg
   4.327 +        .quad compat_update_descriptor  /* 10 */
   4.328 +        .quad do_ni_hypercall
   4.329 +        .quad compat_memory_op
   4.330 +        .quad compat_multicall
   4.331 +        .quad compat_update_va_mapping
   4.332 +        .quad compat_set_timer_op       /* 15 */
   4.333 +        .quad compat_event_channel_op_compat
   4.334 +        .quad compat_xen_version
   4.335 +        .quad compat_console_io
   4.336 +        .quad compat_physdev_op_compat
   4.337 +        .quad compat_grant_table_op     /* 20 */
   4.338 +        .quad compat_vm_assist
   4.339 +        .quad compat_update_va_mapping_otherdomain
   4.340 +        .quad compat_iret
   4.341 +        .quad compat_vcpu_op
   4.342 +        .quad do_ni_hypercall           /* 25 */
   4.343 +        .quad compat_mmuext_op
   4.344 +        .quad compat_acm_op
   4.345 +        .quad compat_nmi_op
   4.346 +        .quad compat_arch_sched_op
   4.347 +        .quad compat_callback_op        /* 30 */
   4.348 +        .quad compat_xenoprof_op
   4.349 +        .quad compat_event_channel_op
   4.350 +        .quad compat_physdev_op
   4.351 +        .quad do_ni_hypercall
   4.352 +        .quad compat_sysctl             /* 35 */
   4.353 +        .quad compat_domctl
   4.354 +        .rept NR_hypercalls-((.-compat_hypercall_table)/8)
   4.355 +        .quad do_ni_hypercall
   4.356 +        .endr
   4.357 +
   4.358 +ENTRY(compat_hypercall_args_table)
   4.359 +        .byte 1 /* compat_set_trap_table    */  /*  0 */
   4.360 +        .byte 4 /* compat_mmu_update        */
   4.361 +        .byte 2 /* compat_set_gdt           */
   4.362 +        .byte 2 /* compat_stack_switch      */
   4.363 +        .byte 4 /* compat_set_callbacks     */
   4.364 +        .byte 1 /* compat_fpu_taskswitch    */  /*  5 */
   4.365 +        .byte 2 /* compat_arch_sched_op_compat */
   4.366 +        .byte 1 /* compat_platform_op       */
   4.367 +        .byte 2 /* compat_set_debugreg      */
   4.368 +        .byte 1 /* compat_get_debugreg      */
   4.369 +        .byte 4 /* compat_update_descriptor */  /* 10 */
   4.370 +        .byte 0 /* do_ni_hypercall          */
   4.371 +        .byte 2 /* compat_memory_op         */
   4.372 +        .byte 2 /* compat_multicall         */
   4.373 +        .byte 4 /* compat_update_va_mapping */
   4.374 +        .byte 2 /* compat_set_timer_op      */  /* 15 */
   4.375 +        .byte 1 /* compat_event_channel_op_compat */
   4.376 +        .byte 2 /* compat_xen_version       */
   4.377 +        .byte 3 /* compat_console_io        */
   4.378 +        .byte 1 /* compat_physdev_op_compat */
   4.379 +        .byte 3 /* compat_grant_table_op    */  /* 20 */
   4.380 +        .byte 2 /* compat_vm_assist         */
   4.381 +        .byte 5 /* compat_update_va_mapping_otherdomain */
   4.382 +        .byte 0 /* compat_iret              */
   4.383 +        .byte 3 /* compat_vcpu_op           */
   4.384 +        .byte 0 /* do_ni_hypercall          */  /* 25 */
   4.385 +        .byte 4 /* compat_mmuext_op         */
   4.386 +        .byte 1 /* compat_acm_op            */
   4.387 +        .byte 2 /* compat_nmi_op            */
   4.388 +        .byte 2 /* compat_arch_sched_op     */
   4.389 +        .byte 2 /* compat_callback_op       */  /* 30 */
   4.390 +        .byte 2 /* compat_xenoprof_op       */
   4.391 +        .byte 2 /* compat_event_channel_op  */
   4.392 +        .byte 2 /* compat_physdev_op        */
   4.393 +        .byte 0 /* do_ni_hypercall          */
   4.394 +        .byte 1 /* compat_sysctl            */  /* 35 */
   4.395 +        .byte 1 /* compat_domctl            */
   4.396 +        .rept NR_hypercalls-(.-compat_hypercall_args_table)
   4.397 +        .byte 0 /* do_ni_hypercall          */
   4.398 +        .endr
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xen/arch/x86/x86_64/compat/traps.c	Fri Jan 05 17:34:27 2007 +0000
     5.3 @@ -0,0 +1,312 @@
     5.4 +#ifdef CONFIG_COMPAT
     5.5 +
     5.6 +#if 0 /* XXX */
     5.7 +#include <compat/callback.h>
     5.8 +#else
     5.9 +struct compat_xen_callback {
    5.10 +    unsigned int cs;
    5.11 +    unsigned int eip;
    5.12 +};
    5.13 +typedef struct compat_xen_callback xen_callback_compat_t;
    5.14 +
    5.15 +struct compat_callback_register {
    5.16 +    uint16_t type;
    5.17 +    uint16_t flags;
    5.18 +    xen_callback_compat_t address;
    5.19 +};
    5.20 +
    5.21 +struct compat_callback_unregister {
    5.22 +    uint16_t type;
    5.23 +    uint16_t _unused;
    5.24 +};
    5.25 +#endif
    5.26 +
    5.27 +void compat_show_guest_stack(struct cpu_user_regs *regs, int debug_stack_lines)
    5.28 +{
    5.29 +    unsigned int i, *stack, addr;
    5.30 +
    5.31 +    stack = (unsigned int *)(unsigned long)regs->_esp;
    5.32 +    printk("Guest stack trace from esp=%08lx:\n ", (unsigned long)stack);
    5.33 +
    5.34 +    for ( i = 0; i < debug_stack_lines * 8; i++ )
    5.35 +    {
    5.36 +        if ( (((long)stack + 3) & (STACK_SIZE - 4)) == 0 )
    5.37 +            break;
    5.38 +        if ( get_user(addr, stack) )
    5.39 +        {
    5.40 +            if ( i != 0 )
    5.41 +                printk("\n    ");
    5.42 +            printk("Fault while accessing guest memory.");
    5.43 +            i = 1;
    5.44 +            break;
    5.45 +        }
    5.46 +        if ( (i != 0) && ((i % 8) == 0) )
    5.47 +            printk("\n ");
    5.48 +        printk(" %08x", addr);
    5.49 +        stack++;
    5.50 +    }
    5.51 +    if ( i == 0 )
    5.52 +        printk("Stack empty.");
    5.53 +    printk("\n");
    5.54 +}
    5.55 +
    5.56 +unsigned int compat_iret(void)
    5.57 +{
    5.58 +    struct cpu_user_regs *regs = guest_cpu_user_regs();
    5.59 +    u32 eflags;
    5.60 +
    5.61 +    /* Restore EAX (clobbered by hypercall). */
    5.62 +    if ( unlikely(__get_user(regs->_eax, (u32 __user *)regs->rsp)) )
    5.63 +        goto exit_and_crash;
    5.64 +
    5.65 +    /* Restore CS and EIP. */
    5.66 +    if ( unlikely(__get_user(regs->_eip, (u32 __user *)regs->rsp + 1)) ||
    5.67 +        unlikely(__get_user(regs->cs, (u32 __user *)regs->rsp + 2)) )
    5.68 +        goto exit_and_crash;
    5.69 +
    5.70 +    /*
    5.71 +     * Fix up and restore EFLAGS. We fix up in a local staging area
    5.72 +     * to avoid firing the BUG_ON(IOPL) check in arch_getdomaininfo_ctxt.
    5.73 +     */
    5.74 +    if ( unlikely(__get_user(eflags, (u32 __user *)regs->rsp + 3)) )
    5.75 +        goto exit_and_crash;
    5.76 +    regs->_eflags = (eflags & ~X86_EFLAGS_IOPL) | X86_EFLAGS_IF;
    5.77 +
    5.78 +    if ( unlikely(eflags & X86_EFLAGS_VM) )
    5.79 +    {
    5.80 +        /*
    5.81 +         * Cannot return to VM86 mode: inject a GP fault instead. Note that
    5.82 +         * the GP fault is reported on the first VM86 mode instruction, not on
    5.83 +         * the IRET (which is why we can simply leave the stack frame as-is
    5.84 +         * (except for perhaps having to copy it), which in turn seems better
    5.85 +         * than teaching create_bounce_frame() to needlessly deal with vm86
    5.86 +         * mode frames).
    5.87 +         */
    5.88 +        const struct trap_info *ti;
    5.89 +        u32 x, ksp = current->arch.guest_context.kernel_sp - 40;
    5.90 +        unsigned int i;
    5.91 +        int rc = 0;
    5.92 +
    5.93 +        gdprintk(XENLOG_ERR, "VM86 mode unavailable (ksp:%08X->%08X)\n",
    5.94 +                 regs->_esp, ksp);
    5.95 +        if ( ksp < regs->_esp )
    5.96 +        {
    5.97 +            for (i = 1; i < 10; ++i)
    5.98 +            {
    5.99 +                rc |= __get_user(x, (u32 __user *)regs->rsp + i);
   5.100 +                rc |= __put_user(x, (u32 __user *)(unsigned long)ksp + i);
   5.101 +            }
   5.102 +        }
   5.103 +        else if ( ksp > regs->_esp )
   5.104 +        {
   5.105 +            for (i = 9; i > 0; ++i)
   5.106 +            {
   5.107 +                rc |= __get_user(x, (u32 __user *)regs->rsp + i);
   5.108 +                rc |= __put_user(x, (u32 __user *)(unsigned long)ksp + i);
   5.109 +            }
   5.110 +        }
   5.111 +        if ( rc )
   5.112 +            goto exit_and_crash;
   5.113 +        regs->_esp = ksp;
   5.114 +        regs->ss = current->arch.guest_context.kernel_ss;
   5.115 +
   5.116 +        ti = &current->arch.guest_context.trap_ctxt[13];
   5.117 +        if ( TI_GET_IF(ti) )
   5.118 +            eflags &= ~X86_EFLAGS_IF;
   5.119 +        regs->_eflags = eflags & ~(X86_EFLAGS_VM|X86_EFLAGS_RF|
   5.120 +                                   X86_EFLAGS_NT|X86_EFLAGS_TF);
   5.121 +
   5.122 +        if ( unlikely(__put_user(0, (u32 __user *)regs->rsp)) )
   5.123 +            goto exit_and_crash;
   5.124 +        regs->_eip = ti->address;
   5.125 +        regs->cs = ti->cs;
   5.126 +    }
   5.127 +    else if ( unlikely(ring_0(regs)) )
   5.128 +        goto exit_and_crash;
   5.129 +    else if ( !ring_1(regs) )
   5.130 +    {
   5.131 +        /* Return to ring 2/3: restore ESP and SS. */
   5.132 +        if ( __get_user(regs->ss, (u32 __user *)regs->rsp + 5)
   5.133 +            || __get_user(regs->_esp, (u32 __user *)regs->rsp + 4))
   5.134 +            goto exit_and_crash;
   5.135 +    }
   5.136 +    else
   5.137 +        regs->_esp += 16;
   5.138 +
   5.139 +    /* No longer in NMI context. */
   5.140 +    clear_bit(_VCPUF_nmi_masked, &current->vcpu_flags);
   5.141 +
   5.142 +    /* Restore upcall mask from supplied EFLAGS.IF. */
   5.143 +    current->vcpu_info->evtchn_upcall_mask = !(eflags & X86_EFLAGS_IF);
   5.144 +
   5.145 +    /*
   5.146 +     * The hypercall exit path will overwrite EAX with this return
   5.147 +     * value.
   5.148 +     */
   5.149 +    return regs->_eax;
   5.150 +
   5.151 + exit_and_crash:
   5.152 +    gdprintk(XENLOG_ERR, "Fatal error\n");
   5.153 +    domain_crash(current->domain);
   5.154 +    return 0;
   5.155 +}
   5.156 +
   5.157 +static long compat_register_guest_callback(struct compat_callback_register *reg)
   5.158 +{
   5.159 +    long ret = 0;
   5.160 +    struct vcpu *v = current;
   5.161 +
   5.162 +    fixup_guest_code_selector(v->domain, reg->address.cs);
   5.163 +
   5.164 +    switch ( reg->type )
   5.165 +    {
   5.166 +    case CALLBACKTYPE_event:
   5.167 +        v->arch.guest_context.event_callback_cs     = reg->address.cs;
   5.168 +        v->arch.guest_context.event_callback_eip    = reg->address.eip;
   5.169 +        break;
   5.170 +
   5.171 +    case CALLBACKTYPE_failsafe:
   5.172 +        v->arch.guest_context.failsafe_callback_cs  = reg->address.cs;
   5.173 +        v->arch.guest_context.failsafe_callback_eip = reg->address.eip;
   5.174 +        if ( reg->flags & CALLBACKF_mask_events )
   5.175 +            set_bit(_VGCF_failsafe_disables_events,
   5.176 +                    &v->arch.guest_context.flags);
   5.177 +        else
   5.178 +            clear_bit(_VGCF_failsafe_disables_events,
   5.179 +                      &v->arch.guest_context.flags);
   5.180 +        break;
   5.181 +
   5.182 +    case CALLBACKTYPE_nmi:
   5.183 +        ret = register_guest_nmi_callback(reg->address.eip);
   5.184 +        break;
   5.185 +
   5.186 +    default:
   5.187 +        ret = -EINVAL;
   5.188 +        break;
   5.189 +    }
   5.190 +
   5.191 +    return ret;
   5.192 +}
   5.193 +
   5.194 +static long compat_unregister_guest_callback(struct compat_callback_unregister *unreg)
   5.195 +{
   5.196 +    long ret;
   5.197 +
   5.198 +    switch ( unreg->type )
   5.199 +    {
   5.200 +    case CALLBACKTYPE_nmi:
   5.201 +        ret = unregister_guest_nmi_callback();
   5.202 +        break;
   5.203 +
   5.204 +    default:
   5.205 +        ret = -EINVAL;
   5.206 +        break;
   5.207 +    }
   5.208 +
   5.209 +    return ret;
   5.210 +}
   5.211 +
   5.212 +
   5.213 +long compat_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg)
   5.214 +{
   5.215 +    long ret;
   5.216 +
   5.217 +    switch ( cmd )
   5.218 +    {
   5.219 +    case CALLBACKOP_register:
   5.220 +    {
   5.221 +        struct compat_callback_register reg;
   5.222 +
   5.223 +        ret = -EFAULT;
   5.224 +        if ( copy_from_guest(&reg, arg, 1) )
   5.225 +            break;
   5.226 +
   5.227 +        ret = compat_register_guest_callback(&reg);
   5.228 +    }
   5.229 +    break;
   5.230 +
   5.231 +    case CALLBACKOP_unregister:
   5.232 +    {
   5.233 +        struct compat_callback_unregister unreg;
   5.234 +
   5.235 +        ret = -EFAULT;
   5.236 +        if ( copy_from_guest(&unreg, arg, 1) )
   5.237 +            break;
   5.238 +
   5.239 +        ret = compat_unregister_guest_callback(&unreg);
   5.240 +    }
   5.241 +    break;
   5.242 +
   5.243 +    default:
   5.244 +        ret = -EINVAL;
   5.245 +        break;
   5.246 +    }
   5.247 +
   5.248 +    return ret;
   5.249 +}
   5.250 +
   5.251 +long compat_set_callbacks(unsigned long event_selector,
   5.252 +                          unsigned long event_address,
   5.253 +                          unsigned long failsafe_selector,
   5.254 +                          unsigned long failsafe_address)
   5.255 +{
   5.256 +    struct compat_callback_register event = {
   5.257 +        .type = CALLBACKTYPE_event,
   5.258 +        .address = {
   5.259 +            .cs = event_selector,
   5.260 +            .eip = event_address
   5.261 +        }
   5.262 +    };
   5.263 +    struct compat_callback_register failsafe = {
   5.264 +        .type = CALLBACKTYPE_failsafe,
   5.265 +        .address = {
   5.266 +            .cs = failsafe_selector,
   5.267 +            .eip = failsafe_address
   5.268 +        }
   5.269 +    };
   5.270 +
   5.271 +    compat_register_guest_callback(&event);
   5.272 +    compat_register_guest_callback(&failsafe);
   5.273 +
   5.274 +    return 0;
   5.275 +}
   5.276 +
   5.277 +#endif /* CONFIG_COMPAT */
   5.278 +
   5.279 +static void hypercall_page_initialise_ring1_kernel(void *hypercall_page)
   5.280 +{
   5.281 +    char *p;
   5.282 +    int i;
   5.283 +
   5.284 +    /* Fill in all the transfer points with template machine code. */
   5.285 +
   5.286 +    for ( i = 0; i < (PAGE_SIZE / 32); i++ )
   5.287 +    {
   5.288 +        p = (char *)(hypercall_page + (i * 32));
   5.289 +        *(u8  *)(p+ 0) = 0xb8;    /* mov  $<i>,%eax */
   5.290 +        *(u32 *)(p+ 1) = i;
   5.291 +        *(u16 *)(p+ 5) = 0x82cd;  /* int  $0x82 */
   5.292 +        *(u8  *)(p+ 7) = 0xc3;    /* ret */
   5.293 +    }
   5.294 +
   5.295 +    /*
   5.296 +     * HYPERVISOR_iret is special because it doesn't return and expects a
   5.297 +     * special stack frame. Guests jump at this transfer point instead of
   5.298 +     * calling it.
   5.299 +     */
   5.300 +    p = (char *)(hypercall_page + (__HYPERVISOR_iret * 32));
   5.301 +    *(u8  *)(p+ 0) = 0x50;    /* push %eax */
   5.302 +    *(u8  *)(p+ 1) = 0xb8;    /* mov  $__HYPERVISOR_iret,%eax */
   5.303 +    *(u32 *)(p+ 2) = __HYPERVISOR_iret;
   5.304 +    *(u16 *)(p+ 6) = 0x82cd;  /* int  $0x82 */
   5.305 +}
   5.306 +
   5.307 +/*
   5.308 + * Local variables:
   5.309 + * mode: C
   5.310 + * c-set-style: "BSD"
   5.311 + * c-basic-offset: 4
   5.312 + * tab-width: 4
   5.313 + * indent-tabs-mode: nil
   5.314 + * End:
   5.315 + */
     6.1 --- a/xen/arch/x86/x86_64/entry.S	Fri Jan 05 17:32:00 2007 +0000
     6.2 +++ b/xen/arch/x86/x86_64/entry.S	Fri Jan 05 17:34:27 2007 +0000
     6.3 @@ -324,7 +324,16 @@ domain_crash_synchronous:
     6.4          GET_GUEST_REGS(%rax)
     6.5          movq  %rax,%rsp
     6.6          # create_bounce_frame() temporarily clobbers CS.RPL. Fix up.
     6.7 +#ifdef CONFIG_COMPAT
     6.8 +        movq  CPUINFO_current_vcpu(%rax),%rax
     6.9 +        movq  VCPU_domain(%rax),%rax
    6.10 +        btl   $_DOMF_compat,DOMAIN_domain_flags(%rax)
    6.11 +        setnc %al
    6.12 +        leal  (%rax,%rax,2),%eax
    6.13 +        orb   %al,UREGS_cs(%rsp)
    6.14 +#else
    6.15          orb   $3,UREGS_cs(%rsp)
    6.16 +#endif
    6.17          # printk(domain_crash_synchronous_string)
    6.18          leaq  domain_crash_synchronous_string(%rip),%rdi
    6.19          xorl  %eax,%eax
    6.20 @@ -336,8 +345,15 @@ domain_crash_synchronous:
    6.21  ENTRY(ret_from_intr)
    6.22          GET_CURRENT(%rbx)
    6.23          testb $3,UREGS_cs(%rsp)
    6.24 -        jnz   test_all_events
    6.25 -        jmp   restore_all_xen
    6.26 +        jz    restore_all_xen
    6.27 +#ifndef CONFIG_COMPAT
    6.28 +        jmp   test_all_events
    6.29 +#else
    6.30 +        movq  VCPU_domain(%rbx),%rax
    6.31 +        btl   $_DOMF_compat,DOMAIN_domain_flags(%rax)
    6.32 +        jnc   test_all_events
    6.33 +        jmp   compat_test_all_events
    6.34 +#endif
    6.35  
    6.36          ALIGN
    6.37  /* No special register assumptions. */
    6.38 @@ -355,6 +371,11 @@ handle_exception:
    6.39          testb $3,UREGS_cs(%rsp)
    6.40          jz    restore_all_xen
    6.41          leaq  VCPU_trap_bounce(%rbx),%rdx
    6.42 +#ifdef CONFIG_COMPAT
    6.43 +        movq  VCPU_domain(%rbx),%rax
    6.44 +        btl   $_DOMF_compat,DOMAIN_domain_flags(%rax)
    6.45 +        jc    compat_post_handle_exception
    6.46 +#endif
    6.47          testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%rdx)
    6.48          jz    test_all_events
    6.49          call  create_bounce_frame
    6.50 @@ -612,3 +633,7 @@ ENTRY(hypercall_args_table)
    6.51          .rept NR_hypercalls-(.-hypercall_args_table)
    6.52          .byte 0 /* do_ni_hypercall      */
    6.53          .endr
    6.54 +
    6.55 +#ifdef CONFIG_COMPAT
    6.56 +#include "compat/entry.S"
    6.57 +#endif
     7.1 --- a/xen/arch/x86/x86_64/traps.c	Fri Jan 05 17:32:00 2007 +0000
     7.2 +++ b/xen/arch/x86/x86_64/traps.c	Fri Jan 05 17:34:27 2007 +0000
     7.3 @@ -246,6 +246,7 @@ unsigned long do_iret(void)
     7.4  }
     7.5  
     7.6  asmlinkage void syscall_enter(void);
     7.7 +asmlinkage void compat_hypercall(void);
     7.8  void __init percpu_traps_init(void)
     7.9  {
    7.10      char *stack_bottom, *stack;
    7.11 @@ -257,6 +258,11 @@ void __init percpu_traps_init(void)
    7.12          set_intr_gate(TRAP_double_fault, &double_fault);
    7.13          idt_table[TRAP_double_fault].a |= 1UL << 32; /* IST1 */
    7.14          idt_table[TRAP_nmi].a          |= 2UL << 32; /* IST2 */
    7.15 +
    7.16 +#ifdef CONFIG_COMPAT
    7.17 +        /* The hypercall entry vector is only accessible from ring 1. */
    7.18 +        _set_gate(idt_table+HYPERCALL_VECTOR, 15, 1, &compat_hypercall);
    7.19 +#endif
    7.20      }
    7.21  
    7.22      stack_bottom = (char *)get_stack_bottom();
    7.23 @@ -503,12 +509,16 @@ static void hypercall_page_initialise_ri
    7.24      *(u16 *)(p+ 9) = 0x050f;  /* syscall */
    7.25  }
    7.26  
    7.27 +#include "compat/traps.c"
    7.28 +
    7.29  void hypercall_page_initialise(struct domain *d, void *hypercall_page)
    7.30  {
    7.31      if ( is_hvm_domain(d) )
    7.32          hvm_hypercall_page_initialise(d, hypercall_page);
    7.33 +    else if ( !IS_COMPAT(d) )
    7.34 +        hypercall_page_initialise_ring3_kernel(hypercall_page);
    7.35      else
    7.36 -        hypercall_page_initialise_ring3_kernel(hypercall_page);
    7.37 +        hypercall_page_initialise_ring1_kernel(hypercall_page);
    7.38  }
    7.39  
    7.40  /*
     8.1 --- a/xen/include/asm-x86/processor.h	Fri Jan 05 17:32:00 2007 +0000
     8.2 +++ b/xen/include/asm-x86/processor.h	Fri Jan 05 17:34:27 2007 +0000
     8.3 @@ -559,6 +559,12 @@ void show_execution_state(struct cpu_use
     8.4  void show_page_walk(unsigned long addr);
     8.5  asmlinkage void fatal_trap(int trapnr, struct cpu_user_regs *regs);
     8.6  
     8.7 +#ifdef CONFIG_COMPAT
     8.8 +void compat_show_guest_stack(struct cpu_user_regs *, int lines);
     8.9 +#else
    8.10 +#define compat_show_guest_stack(regs, lines) ((void)0)
    8.11 +#endif
    8.12 +
    8.13  /* Dumps current register and stack state. */
    8.14  #define dump_execution_state()                                              \
    8.15      /* NB. Needs interrupts enabled else we end up in fatal_trap(). */      \