Commit d9a73c00 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  um, x86: Cast to (u64 *) inside set_64bit()
  x86-32, asm: Directly access per-cpu GDT
  x86-64, asm: Directly access per-cpu IST
  x86, asm: Merge cmpxchg_486_u64() and cmpxchg8b_emu()
  x86, asm: Move cmpxchg emulation code to arch/x86/lib
  x86, asm: Clean up and simplify <asm/cmpxchg.h>
  x86, asm: Clean up and simplify set_64bit()
  x86: Add memory modify constraints to xchg() and cmpxchg()
  x86-64: Simplify loading initial_gs
  x86: Use symbolic MSR names
  x86: Remove redundant K6 MSRs
parents b304441c bf676945
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
set_pud(pud, __pud(_PAGE_TABLE + __pa(pmd))) set_pud(pud, __pud(_PAGE_TABLE + __pa(pmd)))
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
#define set_pud(pudptr, pudval) set_64bit((phys_t *) (pudptr), pud_val(pudval)) #define set_pud(pudptr, pudval) set_64bit((u64 *) (pudptr), pud_val(pudval))
#else #else
#define set_pud(pudptr, pudval) (*(pudptr) = (pudval)) #define set_pud(pudptr, pudval) (*(pudptr) = (pudval))
#endif #endif
...@@ -73,7 +73,7 @@ static inline int pgd_newpage(pgd_t pgd) ...@@ -73,7 +73,7 @@ static inline int pgd_newpage(pgd_t pgd)
static inline void pgd_mkuptodate(pgd_t pgd) { pgd_val(pgd) &= ~_PAGE_NEWPAGE; } static inline void pgd_mkuptodate(pgd_t pgd) { pgd_val(pgd) &= ~_PAGE_NEWPAGE; }
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
#define set_pmd(pmdptr, pmdval) set_64bit((phys_t *) (pmdptr), pmd_val(pmdval)) #define set_pmd(pmdptr, pmdval) set_64bit((u64 *) (pmdptr), pmd_val(pmdval))
#else #else
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval)) #define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
#endif #endif
......
...@@ -11,38 +11,42 @@ ...@@ -11,38 +11,42 @@
extern void __xchg_wrong_size(void); extern void __xchg_wrong_size(void);
/* /*
* Note: no "lock" prefix even on SMP: xchg always implies lock anyway * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
* Note 2: xchg has side effect, so that attribute volatile is necessary, * Since this is generally used to protect other memory information, we
* but generally the primitive is invalid, *ptr is output argument. --ANK * use "asm volatile" and "memory" clobbers to prevent gcc from moving
* information around.
*/ */
struct __xchg_dummy {
unsigned long a[100];
};
#define __xg(x) ((struct __xchg_dummy *)(x))
#define __xchg(x, ptr, size) \ #define __xchg(x, ptr, size) \
({ \ ({ \
__typeof(*(ptr)) __x = (x); \ __typeof(*(ptr)) __x = (x); \
switch (size) { \ switch (size) { \
case 1: \ case 1: \
asm volatile("xchgb %b0,%1" \ { \
: "=q" (__x) \ volatile u8 *__ptr = (volatile u8 *)(ptr); \
: "m" (*__xg(ptr)), "0" (__x) \ asm volatile("xchgb %0,%1" \
: "=q" (__x), "+m" (*__ptr) \
: "0" (__x) \
: "memory"); \ : "memory"); \
break; \ break; \
} \
case 2: \ case 2: \
asm volatile("xchgw %w0,%1" \ { \
: "=r" (__x) \ volatile u16 *__ptr = (volatile u16 *)(ptr); \
: "m" (*__xg(ptr)), "0" (__x) \ asm volatile("xchgw %0,%1" \
: "=r" (__x), "+m" (*__ptr) \
: "0" (__x) \
: "memory"); \ : "memory"); \
break; \ break; \
} \
case 4: \ case 4: \
{ \
volatile u32 *__ptr = (volatile u32 *)(ptr); \
asm volatile("xchgl %0,%1" \ asm volatile("xchgl %0,%1" \
: "=r" (__x) \ : "=r" (__x), "+m" (*__ptr) \
: "m" (*__xg(ptr)), "0" (__x) \ : "0" (__x) \
: "memory"); \ : "memory"); \
break; \ break; \
} \
default: \ default: \
__xchg_wrong_size(); \ __xchg_wrong_size(); \
} \ } \
...@@ -53,60 +57,33 @@ struct __xchg_dummy { ...@@ -53,60 +57,33 @@ struct __xchg_dummy {
__xchg((v), (ptr), sizeof(*ptr)) __xchg((v), (ptr), sizeof(*ptr))
/* /*
* The semantics of XCHGCMP8B are a bit strange, this is why * CMPXCHG8B only writes to the target if we had the previous
* there is a loop and the loading of %%eax and %%edx has to * value in registers, otherwise it acts as a read and gives us the
* be inside. This inlines well in most cases, the cached * "new previous" value. That is why there is a loop. Preloading
* cost is around ~38 cycles. (in the future we might want * EDX:EAX is a performance optimization: in the common case it means
* to do an SIMD/3DNOW!/MMX/FPU 64-bit store here, but that * we need only one locked operation.
* might have an implicit FPU-save as a cost, so it's not
* clear which path to go.)
* *
* cmpxchg8b must be used with the lock prefix here to allow * A SIMD/3DNOW!/MMX/FPU 64-bit store here would require at the very
* the instruction to be executed atomically, see page 3-102 * least an FPU save and/or %cr0.ts manipulation.
* of the instruction set reference 24319102.pdf. We need *
* the reader side to see the coherent 64bit value. * cmpxchg8b must be used with the lock prefix here to allow the
* instruction to be executed atomically. We need to have the reader
* side to see the coherent 64bit value.
*/ */
static inline void __set_64bit(unsigned long long *ptr, static inline void set_64bit(volatile u64 *ptr, u64 value)
unsigned int low, unsigned int high)
{ {
u32 low = value;
u32 high = value >> 32;
u64 prev = *ptr;
asm volatile("\n1:\t" asm volatile("\n1:\t"
"movl (%0), %%eax\n\t" LOCK_PREFIX "cmpxchg8b %0\n\t"
"movl 4(%0), %%edx\n\t"
LOCK_PREFIX "cmpxchg8b (%0)\n\t"
"jnz 1b" "jnz 1b"
: /* no outputs */ : "=m" (*ptr), "+A" (prev)
: "D"(ptr), : "b" (low), "c" (high)
"b"(low), : "memory");
"c"(high)
: "ax", "dx", "memory");
}
static inline void __set_64bit_constant(unsigned long long *ptr,
unsigned long long value)
{
__set_64bit(ptr, (unsigned int)value, (unsigned int)(value >> 32));
}
#define ll_low(x) *(((unsigned int *)&(x)) + 0)
#define ll_high(x) *(((unsigned int *)&(x)) + 1)
static inline void __set_64bit_var(unsigned long long *ptr,
unsigned long long value)
{
__set_64bit(ptr, ll_low(value), ll_high(value));
} }
#define set_64bit(ptr, value) \
(__builtin_constant_p((value)) \
? __set_64bit_constant((ptr), (value)) \
: __set_64bit_var((ptr), (value)))
#define _set_64bit(ptr, value) \
(__builtin_constant_p(value) \
? __set_64bit(ptr, (unsigned int)(value), \
(unsigned int)((value) >> 32)) \
: __set_64bit(ptr, ll_low((value)), ll_high((value))))
extern void __cmpxchg_wrong_size(void); extern void __cmpxchg_wrong_size(void);
/* /*
...@@ -121,23 +98,32 @@ extern void __cmpxchg_wrong_size(void); ...@@ -121,23 +98,32 @@ extern void __cmpxchg_wrong_size(void);
__typeof__(*(ptr)) __new = (new); \ __typeof__(*(ptr)) __new = (new); \
switch (size) { \ switch (size) { \
case 1: \ case 1: \
asm volatile(lock "cmpxchgb %b1,%2" \ { \
: "=a"(__ret) \ volatile u8 *__ptr = (volatile u8 *)(ptr); \
: "q"(__new), "m"(*__xg(ptr)), "0"(__old) \ asm volatile(lock "cmpxchgb %2,%1" \
: "=a" (__ret), "+m" (*__ptr) \
: "q" (__new), "0" (__old) \
: "memory"); \ : "memory"); \
break; \ break; \
} \
case 2: \ case 2: \
asm volatile(lock "cmpxchgw %w1,%2" \ { \
: "=a"(__ret) \ volatile u16 *__ptr = (volatile u16 *)(ptr); \
: "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ asm volatile(lock "cmpxchgw %2,%1" \
: "=a" (__ret), "+m" (*__ptr) \
: "r" (__new), "0" (__old) \
: "memory"); \ : "memory"); \
break; \ break; \
} \
case 4: \ case 4: \
asm volatile(lock "cmpxchgl %1,%2" \ { \
: "=a"(__ret) \ volatile u32 *__ptr = (volatile u32 *)(ptr); \
: "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ asm volatile(lock "cmpxchgl %2,%1" \
: "=a" (__ret), "+m" (*__ptr) \
: "r" (__new), "0" (__old) \
: "memory"); \ : "memory"); \
break; \ break; \
} \
default: \ default: \
__cmpxchg_wrong_size(); \ __cmpxchg_wrong_size(); \
} \ } \
...@@ -175,32 +161,28 @@ extern void __cmpxchg_wrong_size(void); ...@@ -175,32 +161,28 @@ extern void __cmpxchg_wrong_size(void);
(unsigned long long)(n))) (unsigned long long)(n)))
#endif #endif
static inline unsigned long long __cmpxchg64(volatile void *ptr, static inline u64 __cmpxchg64(volatile u64 *ptr, u64 old, u64 new)
unsigned long long old,
unsigned long long new)
{ {
unsigned long long prev; u64 prev;
asm volatile(LOCK_PREFIX "cmpxchg8b %3" asm volatile(LOCK_PREFIX "cmpxchg8b %1"
: "=A"(prev) : "=A" (prev),
: "b"((unsigned long)new), "+m" (*ptr)
"c"((unsigned long)(new >> 32)), : "b" ((u32)new),
"m"(*__xg(ptr)), "c" ((u32)(new >> 32)),
"0"(old) "0" (old)
: "memory"); : "memory");
return prev; return prev;
} }
static inline unsigned long long __cmpxchg64_local(volatile void *ptr, static inline u64 __cmpxchg64_local(volatile u64 *ptr, u64 old, u64 new)
unsigned long long old,
unsigned long long new)
{ {
unsigned long long prev; u64 prev;
asm volatile("cmpxchg8b %3" asm volatile("cmpxchg8b %1"
: "=A"(prev) : "=A" (prev),
: "b"((unsigned long)new), "+m" (*ptr)
"c"((unsigned long)(new >> 32)), : "b" ((u32)new),
"m"(*__xg(ptr)), "c" ((u32)(new >> 32)),
"0"(old) "0" (old)
: "memory"); : "memory");
return prev; return prev;
} }
...@@ -264,8 +246,6 @@ static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old, ...@@ -264,8 +246,6 @@ static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
* to simulate the cmpxchg8b on the 80386 and 80486 CPU. * to simulate the cmpxchg8b on the 80386 and 80486 CPU.
*/ */
extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64);
#define cmpxchg64(ptr, o, n) \ #define cmpxchg64(ptr, o, n) \
({ \ ({ \
__typeof__(*(ptr)) __ret; \ __typeof__(*(ptr)) __ret; \
...@@ -283,20 +263,20 @@ extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64); ...@@ -283,20 +263,20 @@ extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64);
__ret; }) __ret; })
#define cmpxchg64_local(ptr, o, n) \
#define cmpxchg64_local(ptr, o, n) \ ({ \
({ \ __typeof__(*(ptr)) __ret; \
__typeof__(*(ptr)) __ret; \ __typeof__(*(ptr)) __old = (o); \
if (likely(boot_cpu_data.x86 > 4)) \ __typeof__(*(ptr)) __new = (n); \
__ret = (__typeof__(*(ptr)))__cmpxchg64_local((ptr), \ alternative_io("call cmpxchg8b_emu", \
(unsigned long long)(o), \ "cmpxchg8b (%%esi)" , \
(unsigned long long)(n)); \ X86_FEATURE_CX8, \
else \ "=A" (__ret), \
__ret = (__typeof__(*(ptr)))cmpxchg_486_u64((ptr), \ "S" ((ptr)), "0" (__old), \
(unsigned long long)(o), \ "b" ((unsigned int)__new), \
(unsigned long long)(n)); \ "c" ((unsigned int)(__new>>32)) \
__ret; \ : "memory"); \
}) __ret; })
#endif #endif
......
...@@ -3,51 +3,60 @@ ...@@ -3,51 +3,60 @@
#include <asm/alternative.h> /* Provides LOCK_PREFIX */ #include <asm/alternative.h> /* Provides LOCK_PREFIX */
#define __xg(x) ((volatile long *)(x)) static inline void set_64bit(volatile u64 *ptr, u64 val)
static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
{ {
*ptr = val; *ptr = val;
} }
#define _set_64bit set_64bit
extern void __xchg_wrong_size(void); extern void __xchg_wrong_size(void);
extern void __cmpxchg_wrong_size(void); extern void __cmpxchg_wrong_size(void);
/* /*
* Note: no "lock" prefix even on SMP: xchg always implies lock anyway * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
* Note 2: xchg has side effect, so that attribute volatile is necessary, * Since this is generally used to protect other memory information, we
* but generally the primitive is invalid, *ptr is output argument. --ANK * use "asm volatile" and "memory" clobbers to prevent gcc from moving
* information around.
*/ */
#define __xchg(x, ptr, size) \ #define __xchg(x, ptr, size) \
({ \ ({ \
__typeof(*(ptr)) __x = (x); \ __typeof(*(ptr)) __x = (x); \
switch (size) { \ switch (size) { \
case 1: \ case 1: \
asm volatile("xchgb %b0,%1" \ { \
: "=q" (__x) \ volatile u8 *__ptr = (volatile u8 *)(ptr); \
: "m" (*__xg(ptr)), "0" (__x) \ asm volatile("xchgb %0,%1" \
: "=q" (__x), "+m" (*__ptr) \
: "0" (__x) \
: "memory"); \ : "memory"); \
break; \ break; \
} \
case 2: \ case 2: \
asm volatile("xchgw %w0,%1" \ { \
: "=r" (__x) \ volatile u16 *__ptr = (volatile u16 *)(ptr); \
: "m" (*__xg(ptr)), "0" (__x) \ asm volatile("xchgw %0,%1" \
: "=r" (__x), "+m" (*__ptr) \
: "0" (__x) \
: "memory"); \ : "memory"); \
break; \ break; \
} \
case 4: \ case 4: \
asm volatile("xchgl %k0,%1" \ { \
: "=r" (__x) \ volatile u32 *__ptr = (volatile u32 *)(ptr); \
: "m" (*__xg(ptr)), "0" (__x) \ asm volatile("xchgl %0,%1" \
: "=r" (__x), "+m" (*__ptr) \
: "0" (__x) \
: "memory"); \ : "memory"); \
break; \ break; \
} \
case 8: \ case 8: \
{ \
volatile u64 *__ptr = (volatile u64 *)(ptr); \
asm volatile("xchgq %0,%1" \ asm volatile("xchgq %0,%1" \
: "=r" (__x) \ : "=r" (__x), "+m" (*__ptr) \
: "m" (*__xg(ptr)), "0" (__x) \ : "0" (__x) \
: "memory"); \ : "memory"); \
break; \ break; \
} \
default: \ default: \
__xchg_wrong_size(); \ __xchg_wrong_size(); \
} \ } \
...@@ -71,29 +80,41 @@ extern void __cmpxchg_wrong_size(void); ...@@ -71,29 +80,41 @@ extern void __cmpxchg_wrong_size(void);
__typeof__(*(ptr)) __new = (new); \ __typeof__(*(ptr)) __new = (new); \
switch (size) { \ switch (size) { \
case 1: \ case 1: \
asm volatile(lock "cmpxchgb %b1,%2" \ { \
: "=a"(__ret) \ volatile u8 *__ptr = (volatile u8 *)(ptr); \
: "q"(__new), "m"(*__xg(ptr)), "0"(__old) \ asm volatile(lock "cmpxchgb %2,%1" \
: "=a" (__ret), "+m" (*__ptr) \
: "q" (__new), "0" (__old) \
: "memory"); \ : "memory"); \
break; \ break; \
} \
case 2: \ case 2: \
asm volatile(lock "cmpxchgw %w1,%2" \ { \
: "=a"(__ret) \ volatile u16 *__ptr = (volatile u16 *)(ptr); \
: "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ asm volatile(lock "cmpxchgw %2,%1" \
: "=a" (__ret), "+m" (*__ptr) \
: "r" (__new), "0" (__old) \
: "memory"); \ : "memory"); \
break; \ break; \
} \
case 4: \ case 4: \
asm volatile(lock "cmpxchgl %k1,%2" \ { \
: "=a"(__ret) \ volatile u32 *__ptr = (volatile u32 *)(ptr); \
: "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ asm volatile(lock "cmpxchgl %2,%1" \
: "=a" (__ret), "+m" (*__ptr) \
: "r" (__new), "0" (__old) \
: "memory"); \ : "memory"); \
break; \ break; \
} \
case 8: \ case 8: \
asm volatile(lock "cmpxchgq %1,%2" \ { \
: "=a"(__ret) \ volatile u64 *__ptr = (volatile u64 *)(ptr); \
: "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ asm volatile(lock "cmpxchgq %2,%1" \
: "=a" (__ret), "+m" (*__ptr) \
: "r" (__new), "0" (__old) \
: "memory"); \ : "memory"); \
break; \ break; \
} \
default: \ default: \
__cmpxchg_wrong_size(); \ __cmpxchg_wrong_size(); \
} \ } \
......
...@@ -161,8 +161,6 @@ ...@@ -161,8 +161,6 @@
#define MSR_K7_FID_VID_STATUS 0xc0010042 #define MSR_K7_FID_VID_STATUS 0xc0010042
/* K6 MSRs */ /* K6 MSRs */
#define MSR_K6_EFER 0xc0000080
#define MSR_K6_STAR 0xc0000081
#define MSR_K6_WHCR 0xc0000082 #define MSR_K6_WHCR 0xc0000082
#define MSR_K6_UWCCR 0xc0000085 #define MSR_K6_UWCCR 0xc0000085
#define MSR_K6_EPMR 0xc0000086 #define MSR_K6_EPMR 0xc0000086
......
...@@ -104,7 +104,7 @@ _start: ...@@ -104,7 +104,7 @@ _start:
movl %eax, %ecx movl %eax, %ecx
orl %edx, %ecx orl %edx, %ecx
jz 1f jz 1f
movl $0xc0000080, %ecx movl $MSR_EFER, %ecx
wrmsr wrmsr
1: 1:
......
...@@ -16,7 +16,7 @@ obj-y := intel_cacheinfo.o scattered.o topology.o ...@@ -16,7 +16,7 @@ obj-y := intel_cacheinfo.o scattered.o topology.o
obj-y += proc.o capflags.o powerflags.o common.o obj-y += proc.o capflags.o powerflags.o common.o
obj-y += vmware.o hypervisor.o sched.o mshyperv.o obj-y += vmware.o hypervisor.o sched.o mshyperv.o
obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o obj-$(CONFIG_X86_32) += bugs.o
obj-$(CONFIG_X86_64) += bugs_64.o obj-$(CONFIG_X86_64) += bugs_64.o
obj-$(CONFIG_CPU_SUP_INTEL) += intel.o obj-$(CONFIG_CPU_SUP_INTEL) += intel.o
......
...@@ -611,14 +611,14 @@ ldt_ss: ...@@ -611,14 +611,14 @@ ldt_ss:
* compensating for the offset by changing to the ESPFIX segment with * compensating for the offset by changing to the ESPFIX segment with
* a base address that matches for the difference. * a base address that matches for the difference.
*/ */
#define GDT_ESPFIX_SS PER_CPU_VAR(gdt_page) + (GDT_ENTRY_ESPFIX_SS * 8)
mov %esp, %edx /* load kernel esp */ mov %esp, %edx /* load kernel esp */
mov PT_OLDESP(%esp), %eax /* load userspace esp */ mov PT_OLDESP(%esp), %eax /* load userspace esp */
mov %dx, %ax /* eax: new kernel esp */ mov %dx, %ax /* eax: new kernel esp */
sub %eax, %edx /* offset (low word is 0) */ sub %eax, %edx /* offset (low word is 0) */
PER_CPU(gdt_page, %ebx)
shr $16, %edx shr $16, %edx
mov %dl, GDT_ENTRY_ESPFIX_SS * 8 + 4(%ebx) /* bits 16..23 */ mov %dl, GDT_ESPFIX_SS + 4 /* bits 16..23 */
mov %dh, GDT_ENTRY_ESPFIX_SS * 8 + 7(%ebx) /* bits 24..31 */ mov %dh, GDT_ESPFIX_SS + 7 /* bits 24..31 */
pushl $__ESPFIX_SS pushl $__ESPFIX_SS
CFI_ADJUST_CFA_OFFSET 4 CFI_ADJUST_CFA_OFFSET 4
push %eax /* new kernel esp */ push %eax /* new kernel esp */
...@@ -791,9 +791,8 @@ ptregs_clone: ...@@ -791,9 +791,8 @@ ptregs_clone:
* normal stack and adjusts ESP with the matching offset. * normal stack and adjusts ESP with the matching offset.
*/ */
/* fixup the stack */ /* fixup the stack */
PER_CPU(gdt_page, %ebx) mov GDT_ESPFIX_SS + 4, %al /* bits 16..23 */
mov GDT_ENTRY_ESPFIX_SS * 8 + 4(%ebx), %al /* bits 16..23 */ mov GDT_ESPFIX_SS + 7, %ah /* bits 24..31 */
mov GDT_ENTRY_ESPFIX_SS * 8 + 7(%ebx), %ah /* bits 24..31 */
shl $16, %eax shl $16, %eax
addl %esp, %eax /* the adjusted stack pointer */ addl %esp, %eax /* the adjusted stack pointer */
pushl $__KERNEL_DS pushl $__KERNEL_DS
......
...@@ -1065,6 +1065,7 @@ ENTRY(\sym) ...@@ -1065,6 +1065,7 @@ ENTRY(\sym)
END(\sym) END(\sym)
.endm .endm
#define INIT_TSS_IST(x) PER_CPU_VAR(init_tss) + (TSS_ist + ((x) - 1) * 8)
.macro paranoidzeroentry_ist sym do_sym ist .macro paranoidzeroentry_ist sym do_sym ist
ENTRY(\sym) ENTRY(\sym)
INTR_FRAME INTR_FRAME
...@@ -1076,10 +1077,9 @@ ENTRY(\sym) ...@@ -1076,10 +1077,9 @@ ENTRY(\sym)
TRACE_IRQS_OFF TRACE_IRQS_OFF
movq %rsp,%rdi /* pt_regs pointer */ movq %rsp,%rdi /* pt_regs pointer */
xorl %esi,%esi /* no error code */ xorl %esi,%esi /* no error code */
PER_CPU(init_tss, %r12) subq $EXCEPTION_STKSZ, INIT_TSS_IST(\ist)
subq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%r12)
call \do_sym call \do_sym
addq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%r12) addq $EXCEPTION_STKSZ, INIT_TSS_IST(\ist)
jmp paranoid_exit /* %ebx: no swapgs flag */ jmp paranoid_exit /* %ebx: no swapgs flag */
CFI_ENDPROC CFI_ENDPROC
END(\sym) END(\sym)
......
...@@ -234,9 +234,8 @@ ENTRY(secondary_startup_64) ...@@ -234,9 +234,8 @@ ENTRY(secondary_startup_64)
* init data section till per cpu areas are set up. * init data section till per cpu areas are set up.
*/ */
movl $MSR_GS_BASE,%ecx movl $MSR_GS_BASE,%ecx
movq initial_gs(%rip),%rax movl initial_gs(%rip),%eax
movq %rax,%rdx movl initial_gs+4(%rip),%edx
shrq $32,%rdx
wrmsr wrmsr
/* esi is pointer to real mode structure with interesting info. /* esi is pointer to real mode structure with interesting info.
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
*/ */
#include <asm/cpufeature.h> #include <asm/cpufeature.h>
#include <asm/msr-index.h>
verify_cpu: verify_cpu:
pushfl # Save caller passed flags pushfl # Save caller passed flags
...@@ -88,7 +89,7 @@ verify_cpu_sse_test: ...@@ -88,7 +89,7 @@ verify_cpu_sse_test:
je verify_cpu_sse_ok je verify_cpu_sse_ok
test %di,%di test %di,%di
jz verify_cpu_no_longmode # only try to force SSE on AMD jz verify_cpu_no_longmode # only try to force SSE on AMD
movl $0xc0010015,%ecx # HWCR movl $MSR_K7_HWCR,%ecx
rdmsr rdmsr
btr $15,%eax # enable SSE btr $15,%eax # enable SSE
wrmsr wrmsr
......
...@@ -131,7 +131,7 @@ static struct svm_direct_access_msrs { ...@@ -131,7 +131,7 @@ static struct svm_direct_access_msrs {
u32 index; /* Index of the MSR */ u32 index; /* Index of the MSR */
bool always; /* True if intercept is always on */ bool always; /* True if intercept is always on */
} direct_access_msrs[] = { } direct_access_msrs[] = {
{ .index = MSR_K6_STAR, .always = true }, { .index = MSR_STAR, .always = true },
{ .index = MSR_IA32_SYSENTER_CS, .always = true }, { .index = MSR_IA32_SYSENTER_CS, .always = true },
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
{ .index = MSR_GS_BASE, .always = true }, { .index = MSR_GS_BASE, .always = true },
...@@ -2432,7 +2432,7 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data) ...@@ -2432,7 +2432,7 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)
*data = tsc_offset + native_read_tsc(); *data = tsc_offset + native_read_tsc();
break; break;
} }
case MSR_K6_STAR: case MSR_STAR:
*data = svm->vmcb->save.star; *data = svm->vmcb->save.star;
break; break;
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
...@@ -2556,7 +2556,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data) ...@@ -2556,7 +2556,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
break; break;
} }
case MSR_K6_STAR: case MSR_STAR:
svm->vmcb->save.star = data; svm->vmcb->save.star = data;
break; break;
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
......
...@@ -240,14 +240,14 @@ static u64 host_efer; ...@@ -240,14 +240,14 @@ static u64 host_efer;
static void ept_save_pdptrs(struct kvm_vcpu *vcpu); static void ept_save_pdptrs(struct kvm_vcpu *vcpu);
/* /*
* Keep MSR_K6_STAR at the end, as setup_msrs() will try to optimize it * Keep MSR_STAR at the end, as setup_msrs() will try to optimize it
* away by decrementing the array size. * away by decrementing the array size.
*/ */
static const u32 vmx_msr_index[] = { static const u32 vmx_msr_index[] = {
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR,
#endif #endif
MSR_EFER, MSR_TSC_AUX, MSR_K6_STAR, MSR_EFER, MSR_TSC_AUX, MSR_STAR,
}; };
#define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index) #define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index)
...@@ -1117,10 +1117,10 @@ static void setup_msrs(struct vcpu_vmx *vmx) ...@@ -1117,10 +1117,10 @@ static void setup_msrs(struct vcpu_vmx *vmx)
if (index >= 0 && vmx->rdtscp_enabled) if (index >= 0 && vmx->rdtscp_enabled)
move_msr_up(vmx, index, save_nmsrs++); move_msr_up(vmx, index, save_nmsrs++);
/* /*
* MSR_K6_STAR is only needed on long mode guests, and only * MSR_STAR is only needed on long mode guests, and only
* if efer.sce is enabled. * if efer.sce is enabled.
*/ */
index = __find_msr_index(vmx, MSR_K6_STAR); index = __find_msr_index(vmx, MSR_STAR);
if ((index >= 0) && (vmx->vcpu.arch.efer & EFER_SCE)) if ((index >= 0) && (vmx->vcpu.arch.efer & EFER_SCE))
move_msr_up(vmx, index, save_nmsrs++); move_msr_up(vmx, index, save_nmsrs++);
} }
......
...@@ -733,7 +733,7 @@ static u32 msrs_to_save[] = { ...@@ -733,7 +733,7 @@ static u32 msrs_to_save[] = {
HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL, HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL,
HV_X64_MSR_APIC_ASSIST_PAGE, HV_X64_MSR_APIC_ASSIST_PAGE,
MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
MSR_K6_STAR, MSR_STAR,
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
#endif #endif
......
...@@ -30,6 +30,7 @@ ifeq ($(CONFIG_X86_32),y) ...@@ -30,6 +30,7 @@ ifeq ($(CONFIG_X86_32),y)
lib-y += checksum_32.o lib-y += checksum_32.o
lib-y += strstr_32.o lib-y += strstr_32.o
lib-y += semaphore_32.o string_32.o lib-y += semaphore_32.o string_32.o
lib-y += cmpxchg.o
ifneq ($(CONFIG_X86_CMPXCHG64),y) ifneq ($(CONFIG_X86_CMPXCHG64),y)
lib-y += cmpxchg8b_emu.o atomic64_386_32.o lib-y += cmpxchg8b_emu.o atomic64_386_32.o
endif endif
......
...@@ -52,21 +52,3 @@ unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new) ...@@ -52,21 +52,3 @@ unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new)
} }
EXPORT_SYMBOL(cmpxchg_386_u32); EXPORT_SYMBOL(cmpxchg_386_u32);
#endif #endif
#ifndef CONFIG_X86_CMPXCHG64
unsigned long long cmpxchg_486_u64(volatile void *ptr, u64 old, u64 new)
{
u64 prev;
unsigned long flags;
/* Poor man's cmpxchg8b for 386 and 486. Unsuitable for SMP */
local_irq_save(flags);
prev = *(u64 *)ptr;
if (prev == old)
*(u64 *)ptr = new;
local_irq_restore(flags);
return prev;
}
EXPORT_SYMBOL(cmpxchg_486_u64);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment