]> xenbits.xensource.com Git - xen.git/commitdiff
x86: Avoid assumptions about C struct layouts from asm code.
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 13 Jul 2010 17:12:15 +0000 (18:12 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 13 Jul 2010 17:12:15 +0000 (18:12 +0100)
Largely this involves avoiding assumptions about 'struct cpu_info'.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
12 files changed:
xen/arch/x86/acpi/suspend.c
xen/arch/x86/acpi/wakeup_prot.S
xen/arch/x86/boot/head.S
xen/arch/x86/hvm/svm/entry.S
xen/arch/x86/hvm/vmx/entry.S
xen/arch/x86/x86_32/asm-offsets.c
xen/arch/x86/x86_32/entry.S
xen/arch/x86/x86_64/asm-offsets.c
xen/arch/x86/x86_64/compat/entry.S
xen/arch/x86/x86_64/entry.S
xen/include/asm-x86/x86_32/asm_defns.h
xen/include/asm-x86/x86_64/asm_defns.h

index ddddbc89218350f54c5eb4444d3043efc6b59bf2..c82ea96a82cfee443a715163cb31b35d9e4a5b77 100644 (file)
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/support.h>
 #include <asm/i387.h>
+#include <xen/hypercall.h>
 
 #if defined(CONFIG_X86_64)
 static unsigned long saved_lstar, saved_cstar;
 static unsigned long saved_sysenter_esp, saved_sysenter_eip;
+static unsigned long saved_fs_base, saved_gs_base, saved_kernel_gs_base;
+static uint16_t saved_segs[4];
 #endif
 
 void save_rest_processor_state(void)
@@ -25,6 +28,12 @@ void save_rest_processor_state(void)
         unlazy_fpu(current);
 
 #if defined(CONFIG_X86_64)
+    asm volatile (
+        "mov %%ds,(%0); mov %%es,2(%0); mov %%fs,4(%0); mov %%gs,6(%0)"
+        : : "r" (saved_segs) : "memory" );
+    rdmsrl(MSR_FS_BASE, saved_fs_base);
+    rdmsrl(MSR_GS_BASE, saved_gs_base);
+    rdmsrl(MSR_SHADOW_GS_BASE, saved_kernel_gs_base);
     rdmsrl(MSR_CSTAR, saved_cstar);
     rdmsrl(MSR_LSTAR, saved_lstar);
     if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
@@ -35,9 +44,10 @@ void save_rest_processor_state(void)
 #endif
 }
 
+
 void restore_rest_processor_state(void)
 {
-    struct vcpu *v = current;
+    struct vcpu *curr = current;
 
     load_TR();
 
@@ -51,6 +61,10 @@ void restore_rest_processor_state(void)
           X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_TF,
           0U);
 
+    wrmsrl(MSR_FS_BASE, saved_fs_base);
+    wrmsrl(MSR_GS_BASE, saved_gs_base);
+    wrmsrl(MSR_SHADOW_GS_BASE, saved_kernel_gs_base);
+
     if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
     {
         /* Recover sysenter MSRs */
@@ -58,21 +72,30 @@ void restore_rest_processor_state(void)
         wrmsrl(MSR_IA32_SYSENTER_EIP, saved_sysenter_eip);
         wrmsr(MSR_IA32_SYSENTER_CS, __HYPERVISOR_CS, 0);
     }
+
+    if ( !is_idle_vcpu(curr) )
+    {
+        asm volatile (
+            "mov (%0),%%ds; mov 2(%0),%%es; mov 4(%0),%%fs"
+            : : "r" (saved_segs) : "memory" );
+        do_set_segment_base(SEGBASE_GS_USER_SEL, saved_segs[3]);
+    }
+
 #else /* !defined(CONFIG_X86_64) */
     if ( supervisor_mode_kernel && cpu_has_sep )
         wrmsr(MSR_IA32_SYSENTER_ESP, &this_cpu(init_tss).esp1, 0);
 #endif
 
     /* Maybe load the debug registers. */
-    BUG_ON(is_hvm_vcpu(v));
-    if ( !is_idle_vcpu(v) && unlikely(v->arch.guest_context.debugreg[7]) )
+    BUG_ON(is_hvm_vcpu(curr));
+    if ( !is_idle_vcpu(curr) && curr->arch.guest_context.debugreg[7] )
     {
-        write_debugreg(0, v->arch.guest_context.debugreg[0]);
-        write_debugreg(1, v->arch.guest_context.debugreg[1]);
-        write_debugreg(2, v->arch.guest_context.debugreg[2]);
-        write_debugreg(3, v->arch.guest_context.debugreg[3]);
-        write_debugreg(6, v->arch.guest_context.debugreg[6]);
-        write_debugreg(7, v->arch.guest_context.debugreg[7]);
+        write_debugreg(0, curr->arch.guest_context.debugreg[0]);
+        write_debugreg(1, curr->arch.guest_context.debugreg[1]);
+        write_debugreg(2, curr->arch.guest_context.debugreg[2]);
+        write_debugreg(3, curr->arch.guest_context.debugreg[3]);
+        write_debugreg(6, curr->arch.guest_context.debugreg[6]);
+        write_debugreg(7, curr->arch.guest_context.debugreg[7]);
     }
 
     /* Reload FPU state on next FPU use. */
index cf876ed1472e1cd0ad20fdeea5a4f2ab348d6f4d..34ea9b113220a4a5e34f1ad744b43fe5ebff7c16 100644 (file)
 
 #define REF(x)          x(%rip)
 
-#define RDMSR(ind, m)                   \
-        xorq    %rdx, %rdx;             \
-        mov     $ind, %ecx;             \
-        rdmsr;                          \
-        shlq    $0x20, %rdx;              \
-        orq     %rax, %rdx;             \
-        movq    %rdx, m(%rip);
-
-#define WRMSR(ind, m)                   \
-        mov     $ind, %ecx;             \
-        movq    m(%rip), %rdx;          \
-        mov     %edx, %eax;             \
-        shrq    $0x20, %rdx;              \
-        wrmsr;
-
 #else /* !defined(__x86_64__) */
 
         .code32
@@ -76,21 +61,16 @@ ENTRY(do_suspend_lowlevel)
         mov     %cr8, GREG(ax)
         mov     GREG(ax), REF(saved_cr8)
 
-        RDMSR(MSR_FS_BASE, saved_fs_base)
-        RDMSR(MSR_GS_BASE, saved_gs_base)
-        RDMSR(MSR_SHADOW_GS_BASE, saved_kernel_gs_base)
-
 #else /* !defined(__x86_64__) */
 
         pushfl;
         popl    SAVED_GREG(flags)
 
-#endif
-
         mov     %ds, REF(saved_ds)
         mov     %es, REF(saved_es)
-        mov     %fs, REF(saved_fs)
-        mov     %gs, REF(saved_gs)
+
+#endif
+
         mov     %ss, REF(saved_ss)
 
         sgdt    REF(saved_gdt)
@@ -148,41 +128,12 @@ __ret_point:
         pushq   %rax
         lretq
 1:
-
         mov     REF(saved_cr8), %rax
         mov     %rax, %cr8
 
         pushq   SAVED_GREG(flags)
         popfq
 
-        /* Idle vcpu doesn't need segment selectors reload, since
-         * those may contain stale value from other domains and 
-         * reload may result page fault due to no matched gdt entry
-         */
-        mov     $(STACK_SIZE - 8), %rax
-        or      %rsp, %rax
-        and     $~7, %rax
-        mov     (%rax), %rax
-        mov     0x10(%rax), %rax
-        cmpw    $0x7fff, (%rax)
-        je      1f
-
-        /* These selectors are from guest, and thus need reload */
-        mov     REF(saved_ds), %ds
-        mov     REF(saved_es), %es
-        mov     REF(saved_fs), %fs
-
-        /* gs load is special */
-        mov     REF(saved_gs), %rsi
-        mov     $3, %rdi        # SEGBASE_GS_USER_SEL
-        call    do_set_segment_base
-
-1:
-        # MSR restore
-        WRMSR(MSR_FS_BASE, saved_fs_base)
-        WRMSR(MSR_GS_BASE, saved_gs_base)
-        WRMSR(MSR_SHADOW_GS_BASE, saved_kernel_gs_base)
-
 #else /* !defined(__x86_64__) */
 
         pushl   SAVED_GREG(flags)
@@ -217,16 +168,11 @@ __ret_point:
 
 .data
         .align 16
-saved_ds:        .word   0
-saved_es:        .word   0
-saved_ss:        .word   0
-saved_gs:        .word   0
-saved_fs:        .word   0
-
-        .align 4
         .globl   saved_magic
 saved_magic:     .long   0x9abcdef0
 
+saved_ss:        .word   0
+
         .align 8
 DECLARE_GREG(sp)
 DECLARE_GREG(bp)
@@ -257,10 +203,6 @@ saved_cr0:      .quad   0
 saved_cr3:      .quad   0
 saved_cr8:      .quad   0
 
-saved_gs_base:  .quad   0
-saved_fs_base:  .quad   0
-saved_kernel_gs_base:   .quad   0
-
 #else /* !defined(__x86_64__) */
 
 saved_gdt:      .long   0,0
@@ -270,4 +212,7 @@ saved_ldt:      .long   0
 saved_cr0:      .long   0
 saved_cr3:      .long   0
 
+saved_ds:       .word   0
+saved_es:       .word   0
+
 #endif 
index 139797c7994c934c0cae55f6e21f3cb6bd597782..aa657234d54299de56fe31027f6705d19f0736ff 100644 (file)
@@ -101,7 +101,7 @@ __start:
         mov     $0x80000001,%eax
         cpuid
 1:      mov     %edx,sym_phys(cpuid_ext_features)
-        mov     %edx,sym_phys(boot_cpu_data)+CPUINFO_ext_features
+        mov     %edx,sym_phys(boot_cpu_data)+CPUINFO86_ext_features
 
 #if defined(__x86_64__)
         /* Check for availability of long mode. */
index 30af14cb1796fb3537e07f216d9a2df6677d7da0..73c66c7bae4944be44beab58cd551844c911f9f6 100644 (file)
 #define STGI   .byte 0x0F,0x01,0xDC
 #define CLGI   .byte 0x0F,0x01,0xDD
 
-#define get_current(reg)                        \
-        mov $STACK_SIZE-BYTES_PER_LONG, r(reg); \
-        or  r(sp), r(reg);                      \
-        and $~(BYTES_PER_LONG-1),r(reg);        \
-        mov (r(reg)),r(reg);
-
+#define get_current(reg) GET_CURRENT(r(reg))
+        
 #if defined(__x86_64__)
 #define r(reg) %r##reg
 #define addr_of(lbl) lbl(%rip)
index 9fb7ecb97cee0e6204efcc7fc12ef1cc79da5895..fd7d6a6c90e874529e0038119b3719c973cbae0d 100644 (file)
 #define GUEST_RIP    0x681e
 #define GUEST_RFLAGS 0x6820
 
-#define get_current(reg)                        \
-        mov $STACK_SIZE-BYTES_PER_LONG, r(reg); \
-        or  r(sp), r(reg);                      \
-        and $~(BYTES_PER_LONG-1),r(reg);        \
-        mov (r(reg)),r(reg);
+#define get_current(reg) GET_CURRENT(r(reg))
 
 #if defined(__x86_64__)
 #define r(reg) %r##reg
index a3d3680d0032ce0ea050c51e7454034564617fc7..4124ce7edcd92b49ae562d83b549c2f03a78a681 100644 (file)
@@ -106,6 +106,9 @@ void __dummy__(void)
     OFFSET(VCPUINFO_upcall_mask, vcpu_info_t, evtchn_upcall_mask);
     BLANK();
 
+    OFFSET(CPUINFO_guest_cpu_user_regs, struct cpu_info, guest_cpu_user_regs);
+    OFFSET(CPUINFO_processor_id, struct cpu_info, processor_id);
+    OFFSET(CPUINFO_current_vcpu, struct cpu_info, current_vcpu);
     DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
     BLANK();
 
@@ -127,7 +130,7 @@ void __dummy__(void)
     DEFINE(IRQSTAT_shift, LOG_2(sizeof(irq_cpustat_t)));
     BLANK();
 
-    OFFSET(CPUINFO_ext_features, struct cpuinfo_x86, x86_capability[1]);
+    OFFSET(CPUINFO86_ext_features, struct cpuinfo_x86, x86_capability[1]);
     BLANK();
 
     OFFSET(MB_flags, multiboot_info_t, flags);
index 85d527b6e981cedcf527dc6a4f82a7fddca92e72..57915e295ea6251db92d72497031fb4616b13398 100644 (file)
 #include <asm/page.h>
 #include <public/xen.h>
 
-#define GET_GUEST_REGS(reg)                     \
-        movl $~(STACK_SIZE-1),reg;              \
-        andl %esp,reg;                          \
-        orl  $(STACK_SIZE-CPUINFO_sizeof),reg;
-
-#define GET_CURRENT(reg)         \
-        movl $STACK_SIZE-4, reg; \
-        orl  %esp, reg;          \
-        andl $~3,reg;            \
-        movl (reg),reg;
-
         ALIGN
 restore_all_guest:
         ASSERT_INTERRUPTS_DISABLED
@@ -590,7 +579,7 @@ handle_nmi_mce:
         jmp   ret_from_intr
 .Lnmi_mce_xen:
         /* Check the outer (guest) context for %ds/%es state validity. */
-        GET_GUEST_REGS(%ebx)
+        GET_CPUINFO_FIELD(CPUINFO_guest_cpu_user_regs,%ebx)
         testl $X86_EFLAGS_VM,%ss:UREGS_eflags(%ebx)
         mov   %ds,%eax
         mov   %es,%edx
index 7fe1934b61b63d83d8219a776c0c7c46fde97956..424137ce4359e8425e0c6551f4d83ba2f38e746a 100644 (file)
@@ -132,6 +132,8 @@ void __dummy__(void)
     OFFSET(COMPAT_VCPUINFO_upcall_mask, struct compat_vcpu_info, evtchn_upcall_mask);
     BLANK();
 
+    OFFSET(CPUINFO_guest_cpu_user_regs, struct cpu_info, guest_cpu_user_regs);
+    OFFSET(CPUINFO_processor_id, struct cpu_info, processor_id);
     OFFSET(CPUINFO_current_vcpu, struct cpu_info, current_vcpu);
     DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
     BLANK();
@@ -151,7 +153,7 @@ void __dummy__(void)
     DEFINE(IRQSTAT_shift, LOG_2(sizeof(irq_cpustat_t)));
     BLANK();
 
-    OFFSET(CPUINFO_ext_features, struct cpuinfo_x86, x86_capability[1]);
+    OFFSET(CPUINFO86_ext_features, struct cpuinfo_x86, x86_capability[1]);
     BLANK();
 
     OFFSET(MB_flags, multiboot_info_t, flags);
index 597683ccf5e0ceb1c1a8e73d8c49600c27df6157..06581f093494fe3ffe6c9bc2f67a1b755ef6d324 100644 (file)
 #include <asm/desc.h>
 #include <public/xen.h>
 
-#define GET_GUEST_REGS(reg)                     \
-        movq $~(STACK_SIZE-1),reg;              \
-        andq %rsp,reg;                          \
-        orq  $(STACK_SIZE-CPUINFO_sizeof),reg;
-
-#define GET_CURRENT(reg)         \
-        movq $STACK_SIZE-8, reg; \
-        orq  %rsp, reg;          \
-        andq $~7,reg;            \
-        movq (reg),reg;
-
         ALIGN
 ENTRY(compat_hypercall)
         pushq $0
index 4cb902ec09bd2bec18a78a077f0e0871bc1900bd..8bb3e228c18811ded090f262afe040af26c50db1 100644 (file)
 #include <asm/page.h>
 #include <public/xen.h>
 
-#define GET_GUEST_REGS(reg)                     \
-        movq $~(STACK_SIZE-1),reg;              \
-        andq %rsp,reg;                          \
-        orq  $(STACK_SIZE-CPUINFO_sizeof),reg;
-
-#define GET_CURRENT(reg)         \
-        movq $STACK_SIZE-8, reg; \
-        orq  %rsp, reg;          \
-        andq $~7,reg;            \
-        movq (reg),reg;
-
         ALIGN
 /* %rbx: struct vcpu */
 switch_to_kernel:
@@ -434,10 +423,10 @@ domain_crash_synchronous_string:
 
 ENTRY(domain_crash_synchronous)
         # Get out of the guest-save area of the stack.
-        GET_GUEST_REGS(%rax)
+        GET_CPUINFO_FIELD(CPUINFO_guest_cpu_user_regs,%rax)
         movq  %rax,%rsp
         # create_bounce_frame() temporarily clobbers CS.RPL. Fix up.
-        movq  CPUINFO_current_vcpu(%rax),%rax
+        GET_CURRENT(%rax)
         movq  VCPU_domain(%rax),%rax
         testb $1,DOMAIN_is_32bit_pv(%rax)
         setz  %al
@@ -610,7 +599,7 @@ handle_ist_exception:
         testb $3,UREGS_cs(%rsp)
         jz    1f
         /* Interrupted guest context. Copy the context to stack bottom. */
-        GET_GUEST_REGS(%rdi)
+        GET_CPUINFO_FIELD(CPUINFO_guest_cpu_user_regs,%rdi)
         movq  %rsp,%rsi
         movl  $UREGS_kernel_sizeof/8,%ecx
         movq  %rdi,%rsp
index 10bf8fe25ab5a0be436482956d0fa05615e091c2..9e2bb3adac59f7881e18d988f9dd03a86761336c 100644 (file)
@@ -142,4 +142,12 @@ STR(IRQ) #nr "_interrupt:\n\t"                  \
     "pushl $"#nr"<<16\n\t"                      \
     "jmp common_interrupt");
 
+#define GET_CPUINFO_FIELD(field,reg)                    \
+        movl $~(STACK_SIZE-1),reg;                      \
+        andl %esp,reg;                                  \
+        orl  $(STACK_SIZE-CPUINFO_sizeof+field),reg;
+#define GET_CURRENT(reg)                                \
+        GET_CPUINFO_FIELD(CPUINFO_current_vcpu,reg)     \
+        movl (reg),reg;
+
 #endif /* __X86_32_ASM_DEFNS_H__ */
index 7a8cfdbb6ade153d25a7d210ebc8787a1419b7c5..a56ac63211af1074dcc7fa587e8ae7e00901ad84 100644 (file)
@@ -122,4 +122,12 @@ STR(IRQ) #nr "_interrupt:\n\t"                  \
     "movl $"#nr",4(%rsp)\n\t"                   \
     "jmp common_interrupt");
 
+#define GET_CPUINFO_FIELD(field,reg)                    \
+        movq $~(STACK_SIZE-1),reg;                      \
+        andq %rsp,reg;                                  \
+        orq  $(STACK_SIZE-CPUINFO_sizeof+field),reg;
+#define GET_CURRENT(reg)                                \
+        GET_CPUINFO_FIELD(CPUINFO_current_vcpu,reg)     \
+        movq (reg),reg;
+
 #endif /* __X86_64_ASM_DEFNS_H__ */