aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-07-13 18:12:15 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-07-13 18:12:15 +0100
commit917335d8b352cb59b5d54592693d80f160582d83 (patch)
tree6f0a58884f1bd6e942f9d49995cf09630cab20ae
parentf65bd343b074358ce3222e9aebd70908d0362f25 (diff)
downloadxen-917335d8b352cb59b5d54592693d80f160582d83.tar.gz
xen-917335d8b352cb59b5d54592693d80f160582d83.tar.bz2
xen-917335d8b352cb59b5d54592693d80f160582d83.zip
x86: Avoid assumptions about C struct layouts from asm code.
Largely this involves avoiding assumptions about 'struct cpu_info'. Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r--xen/arch/x86/acpi/suspend.c41
-rw-r--r--xen/arch/x86/acpi/wakeup_prot.S71
-rw-r--r--xen/arch/x86/boot/head.S2
-rw-r--r--xen/arch/x86/hvm/svm/entry.S8
-rw-r--r--xen/arch/x86/hvm/vmx/entry.S6
-rw-r--r--xen/arch/x86/x86_32/asm-offsets.c5
-rw-r--r--xen/arch/x86/x86_32/entry.S13
-rw-r--r--xen/arch/x86/x86_64/asm-offsets.c4
-rw-r--r--xen/arch/x86/x86_64/compat/entry.S11
-rw-r--r--xen/arch/x86/x86_64/entry.S17
-rw-r--r--xen/include/asm-x86/x86_32/asm_defns.h8
-rw-r--r--xen/include/asm-x86/x86_64/asm_defns.h8
12 files changed, 71 insertions, 123 deletions
diff --git a/xen/arch/x86/acpi/suspend.c b/xen/arch/x86/acpi/suspend.c
index ddddbc8921..c82ea96a82 100644
--- a/xen/arch/x86/acpi/suspend.c
+++ b/xen/arch/x86/acpi/suspend.c
@@ -13,10 +13,13 @@
#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. */
diff --git a/xen/arch/x86/acpi/wakeup_prot.S b/xen/arch/x86/acpi/wakeup_prot.S
index cf876ed147..34ea9b1132 100644
--- a/xen/arch/x86/acpi/wakeup_prot.S
+++ b/xen/arch/x86/acpi/wakeup_prot.S
@@ -20,21 +20,6 @@
#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
diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index 139797c799..aa657234d5 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -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. */
diff --git a/xen/arch/x86/hvm/svm/entry.S b/xen/arch/x86/hvm/svm/entry.S
index 30af14cb17..73c66c7bae 100644
--- a/xen/arch/x86/hvm/svm/entry.S
+++ b/xen/arch/x86/hvm/svm/entry.S
@@ -31,12 +31,8 @@
#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)
diff --git a/xen/arch/x86/hvm/vmx/entry.S b/xen/arch/x86/hvm/vmx/entry.S
index 9fb7ecb97c..fd7d6a6c90 100644
--- a/xen/arch/x86/hvm/vmx/entry.S
+++ b/xen/arch/x86/hvm/vmx/entry.S
@@ -36,11 +36,7 @@
#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
diff --git a/xen/arch/x86/x86_32/asm-offsets.c b/xen/arch/x86/x86_32/asm-offsets.c
index a3d3680d00..4124ce7edc 100644
--- a/xen/arch/x86/x86_32/asm-offsets.c
+++ b/xen/arch/x86/x86_32/asm-offsets.c
@@ -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);
diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S
index 85d527b6e9..57915e295e 100644
--- a/xen/arch/x86/x86_32/entry.S
+++ b/xen/arch/x86/x86_32/entry.S
@@ -61,17 +61,6 @@
#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
diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c
index 7fe1934b61..424137ce43 100644
--- a/xen/arch/x86/x86_64/asm-offsets.c
+++ b/xen/arch/x86/x86_64/asm-offsets.c
@@ -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);
diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S
index 597683ccf5..06581f0934 100644
--- a/xen/arch/x86/x86_64/compat/entry.S
+++ b/xen/arch/x86/x86_64/compat/entry.S
@@ -11,17 +11,6 @@
#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
diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
index 4cb902ec09..8bb3e228c1 100644
--- a/xen/arch/x86/x86_64/entry.S
+++ b/xen/arch/x86/x86_64/entry.S
@@ -12,17 +12,6 @@
#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
diff --git a/xen/include/asm-x86/x86_32/asm_defns.h b/xen/include/asm-x86/x86_32/asm_defns.h
index 10bf8fe25a..9e2bb3adac 100644
--- a/xen/include/asm-x86/x86_32/asm_defns.h
+++ b/xen/include/asm-x86/x86_32/asm_defns.h
@@ -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__ */
diff --git a/xen/include/asm-x86/x86_64/asm_defns.h b/xen/include/asm-x86/x86_64/asm_defns.h
index 7a8cfdbb6a..a56ac63211 100644
--- a/xen/include/asm-x86/x86_64/asm_defns.h
+++ b/xen/include/asm-x86/x86_64/asm_defns.h
@@ -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__ */