338 lines
13 KiB
Diff
338 lines
13 KiB
Diff
Index: 2007-05-14/xen/arch/x86/mm.c
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/arch/x86/mm.c 2007-05-14 14:40:28.000000000 +0200
|
|
+++ 2007-05-14/xen/arch/x86/mm.c 2007-05-14 14:40:43.000000000 +0200
|
|
@@ -3499,6 +3499,7 @@ static int ptwr_emulated_cmpxchg(
|
|
container_of(ctxt, struct ptwr_emulate_ctxt, ctxt));
|
|
}
|
|
|
|
+#ifdef __i386__
|
|
static int ptwr_emulated_cmpxchg8b(
|
|
enum x86_segment seg,
|
|
unsigned long offset,
|
|
@@ -3514,13 +3515,16 @@ static int ptwr_emulated_cmpxchg8b(
|
|
offset, ((u64)old_hi << 32) | old, ((u64)new_hi << 32) | new, 8, 1,
|
|
container_of(ctxt, struct ptwr_emulate_ctxt, ctxt));
|
|
}
|
|
+#endif
|
|
|
|
static struct x86_emulate_ops ptwr_emulate_ops = {
|
|
.read = ptwr_emulated_read,
|
|
.insn_fetch = ptwr_emulated_read,
|
|
.write = ptwr_emulated_write,
|
|
.cmpxchg = ptwr_emulated_cmpxchg,
|
|
- .cmpxchg8b = ptwr_emulated_cmpxchg8b
|
|
+#ifdef __i386__
|
|
+ .cmpxchg2 = ptwr_emulated_cmpxchg8b
|
|
+#endif
|
|
};
|
|
|
|
/* Write page fault handler: check if guest is trying to modify a PTE. */
|
|
Index: 2007-05-14/xen/arch/x86/mm/shadow/common.c
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/arch/x86/mm/shadow/common.c 2007-05-14 14:40:28.000000000 +0200
|
|
+++ 2007-05-14/xen/arch/x86/mm/shadow/common.c 2007-05-14 14:40:43.000000000 +0200
|
|
@@ -310,6 +310,7 @@ hvm_emulate_cmpxchg(enum x86_segment seg
|
|
v, addr, old, new, bytes, sh_ctxt);
|
|
}
|
|
|
|
+#ifdef __i386__
|
|
static int
|
|
hvm_emulate_cmpxchg8b(enum x86_segment seg,
|
|
unsigned long offset,
|
|
@@ -333,13 +334,16 @@ hvm_emulate_cmpxchg8b(enum x86_segment s
|
|
return v->arch.paging.mode->shadow.x86_emulate_cmpxchg8b(
|
|
v, addr, old_lo, old_hi, new_lo, new_hi, sh_ctxt);
|
|
}
|
|
+#endif
|
|
|
|
static struct x86_emulate_ops hvm_shadow_emulator_ops = {
|
|
.read = hvm_emulate_read,
|
|
.insn_fetch = hvm_emulate_insn_fetch,
|
|
.write = hvm_emulate_write,
|
|
.cmpxchg = hvm_emulate_cmpxchg,
|
|
- .cmpxchg8b = hvm_emulate_cmpxchg8b,
|
|
+#ifdef __i386__
|
|
+ .cmpxchg2 = hvm_emulate_cmpxchg8b,
|
|
+#endif
|
|
};
|
|
|
|
static int
|
|
@@ -390,6 +394,7 @@ pv_emulate_cmpxchg(enum x86_segment seg,
|
|
v, offset, old, new, bytes, sh_ctxt);
|
|
}
|
|
|
|
+#ifdef __i386__
|
|
static int
|
|
pv_emulate_cmpxchg8b(enum x86_segment seg,
|
|
unsigned long offset,
|
|
@@ -405,13 +410,16 @@ pv_emulate_cmpxchg8b(enum x86_segment se
|
|
return v->arch.paging.mode->shadow.x86_emulate_cmpxchg8b(
|
|
v, offset, old_lo, old_hi, new_lo, new_hi, sh_ctxt);
|
|
}
|
|
+#endif
|
|
|
|
static struct x86_emulate_ops pv_shadow_emulator_ops = {
|
|
.read = pv_emulate_read,
|
|
.insn_fetch = pv_emulate_read,
|
|
.write = pv_emulate_write,
|
|
.cmpxchg = pv_emulate_cmpxchg,
|
|
- .cmpxchg8b = pv_emulate_cmpxchg8b,
|
|
+#ifdef __i386__
|
|
+ .cmpxchg2 = pv_emulate_cmpxchg8b,
|
|
+#endif
|
|
};
|
|
|
|
struct x86_emulate_ops *shadow_init_emulation(
|
|
@@ -425,7 +433,12 @@ struct x86_emulate_ops *shadow_init_emul
|
|
|
|
if ( !is_hvm_vcpu(v) )
|
|
{
|
|
+#ifndef CONFIG_COMPAT
|
|
sh_ctxt->ctxt.addr_size = sh_ctxt->ctxt.sp_size = BITS_PER_LONG;
|
|
+#else
|
|
+ sh_ctxt->ctxt.addr_size = sh_ctxt->ctxt.sp_size =
|
|
+ !is_pv_32on64_vcpu(v) ? BITS_PER_LONG : COMPAT_BITS_PER_LONG;
|
|
+#endif
|
|
return &pv_shadow_emulator_ops;
|
|
}
|
|
|
|
Index: 2007-05-14/xen/arch/x86/mm/shadow/multi.c
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/arch/x86/mm/shadow/multi.c 2007-05-14 14:40:28.000000000 +0200
|
|
+++ 2007-05-14/xen/arch/x86/mm/shadow/multi.c 2007-05-14 14:40:43.000000000 +0200
|
|
@@ -4025,7 +4025,8 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, u
|
|
return rv;
|
|
}
|
|
|
|
-int
|
|
+#ifdef __i386__
|
|
+static int
|
|
sh_x86_emulate_cmpxchg8b(struct vcpu *v, unsigned long vaddr,
|
|
unsigned long old_lo, unsigned long old_hi,
|
|
unsigned long new_lo, unsigned long new_hi,
|
|
@@ -4068,6 +4069,7 @@ sh_x86_emulate_cmpxchg8b(struct vcpu *v,
|
|
shadow_audit_tables(v);
|
|
return rv;
|
|
}
|
|
+#endif
|
|
|
|
|
|
/**************************************************************************/
|
|
@@ -4352,7 +4354,9 @@ struct paging_mode sh_paging_mode = {
|
|
.shadow.detach_old_tables = sh_detach_old_tables,
|
|
.shadow.x86_emulate_write = sh_x86_emulate_write,
|
|
.shadow.x86_emulate_cmpxchg = sh_x86_emulate_cmpxchg,
|
|
+#ifdef __i386__
|
|
.shadow.x86_emulate_cmpxchg8b = sh_x86_emulate_cmpxchg8b,
|
|
+#endif
|
|
.shadow.make_monitor_table = sh_make_monitor_table,
|
|
.shadow.destroy_monitor_table = sh_destroy_monitor_table,
|
|
#if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC
|
|
Index: 2007-05-14/xen/arch/x86/x86_emulate.c
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/arch/x86/x86_emulate.c 2007-04-23 10:01:43.000000000 +0200
|
|
+++ 2007-05-14/xen/arch/x86/x86_emulate.c 2007-05-14 14:40:43.000000000 +0200
|
|
@@ -30,6 +30,7 @@
|
|
#include <xen/types.h>
|
|
#include <xen/lib.h>
|
|
#include <asm/regs.h>
|
|
+#include <asm/processor.h>
|
|
#undef cmpxchg
|
|
#endif
|
|
#include <asm-x86/x86_emulate.h>
|
|
@@ -2336,58 +2337,63 @@ x86_emulate(
|
|
break;
|
|
}
|
|
|
|
- case 0xc7: /* Grp9 (cmpxchg8b) */
|
|
-#if defined(__i386__)
|
|
- {
|
|
- unsigned long old_lo, old_hi;
|
|
+ case 0xc7: /* Grp9 (cmpxchg{8,16}b) */
|
|
generate_exception_if((modrm_reg & 7) != 1, EXC_UD);
|
|
- if ( (rc = ops->read(ea.mem.seg, ea.mem.off+0, &old_lo, 4, ctxt)) ||
|
|
- (rc = ops->read(ea.mem.seg, ea.mem.off+4, &old_hi, 4, ctxt)) )
|
|
- goto done;
|
|
- if ( (old_lo != _regs.eax) || (old_hi != _regs.edx) )
|
|
- {
|
|
- _regs.eax = old_lo;
|
|
- _regs.edx = old_hi;
|
|
- _regs.eflags &= ~EFLG_ZF;
|
|
- }
|
|
- else if ( ops->cmpxchg8b == NULL )
|
|
- {
|
|
- rc = X86EMUL_UNHANDLEABLE;
|
|
- goto done;
|
|
- }
|
|
- else
|
|
+#ifdef __x86_64__
|
|
+ if ( op_bytes != 8 )
|
|
{
|
|
- if ( (rc = ops->cmpxchg8b(ea.mem.seg, ea.mem.off, old_lo, old_hi,
|
|
- _regs.ebx, _regs.ecx, ctxt)) != 0 )
|
|
+ unsigned long old, new;
|
|
+
|
|
+ if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &old, 8, ctxt)) != 0 )
|
|
goto done;
|
|
- _regs.eflags |= EFLG_ZF;
|
|
- }
|
|
- break;
|
|
- }
|
|
-#elif defined(__x86_64__)
|
|
- {
|
|
- unsigned long old, new;
|
|
- generate_exception_if((modrm_reg & 7) != 1, EXC_UD);
|
|
- if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &old, 8, ctxt)) != 0 )
|
|
- goto done;
|
|
- if ( ((uint32_t)(old>>0) != (uint32_t)_regs.eax) ||
|
|
- ((uint32_t)(old>>32) != (uint32_t)_regs.edx) )
|
|
- {
|
|
- _regs.eax = (uint32_t)(old>>0);
|
|
- _regs.edx = (uint32_t)(old>>32);
|
|
- _regs.eflags &= ~EFLG_ZF;
|
|
+ if ( ((uint32_t)(old>>0) != (uint32_t)_regs.eax) ||
|
|
+ ((uint32_t)(old>>32) != (uint32_t)_regs.edx) )
|
|
+ {
|
|
+ _regs.eax = (uint32_t)(old>>0);
|
|
+ _regs.edx = (uint32_t)(old>>32);
|
|
+ _regs.eflags &= ~EFLG_ZF;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ new = (_regs.ecx<<32)|(uint32_t)_regs.ebx;
|
|
+ if ( (rc = ops->cmpxchg(ea.mem.seg, ea.mem.off, old,
|
|
+ new, 8, ctxt)) != 0 )
|
|
+ goto done;
|
|
+ _regs.eflags |= EFLG_ZF;
|
|
+ }
|
|
}
|
|
+ else if ( !cpu_has_cmpxchg16b )
|
|
+ generate_exception_if(1, EXC_UD);
|
|
else
|
|
+#endif
|
|
{
|
|
- new = (_regs.ecx<<32)|(uint32_t)_regs.ebx;
|
|
- if ( (rc = ops->cmpxchg(ea.mem.seg, ea.mem.off, old,
|
|
- new, 8, ctxt)) != 0 )
|
|
+ unsigned long old_lo, old_hi;
|
|
+
|
|
+ if ( (rc = ops->read(ea.mem.seg, ea.mem.off,
|
|
+ &old_lo, sizeof(old_lo), ctxt)) ||
|
|
+ (rc = ops->read(ea.mem.seg, ea.mem.off+sizeof(old_lo),
|
|
+ &old_hi, sizeof(old_lo), ctxt)) )
|
|
goto done;
|
|
- _regs.eflags |= EFLG_ZF;
|
|
+ if ( (old_lo != _regs.eax) || (old_hi != _regs.edx) )
|
|
+ {
|
|
+ _regs.eax = old_lo;
|
|
+ _regs.edx = old_hi;
|
|
+ _regs.eflags &= ~EFLG_ZF;
|
|
+ }
|
|
+ else if ( ops->cmpxchg2 == NULL )
|
|
+ {
|
|
+ rc = X86EMUL_UNHANDLEABLE;
|
|
+ goto done;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if ( (rc = ops->cmpxchg2(ea.mem.seg, ea.mem.off, old_lo, old_hi,
|
|
+ _regs.ebx, _regs.ecx, ctxt)) != 0 )
|
|
+ goto done;
|
|
+ _regs.eflags |= EFLG_ZF;
|
|
+ }
|
|
}
|
|
break;
|
|
- }
|
|
-#endif
|
|
|
|
case 0xc8 ... 0xcf: /* bswap */
|
|
dst.type = OP_REG;
|
|
@@ -2397,7 +2403,7 @@ x86_emulate(
|
|
{
|
|
default: /* case 2: */
|
|
/* Undefined behaviour. Writes zero on all tested CPUs. */
|
|
- dst.val = 0;
|
|
+ __asm__("data16 bswap %k0" : "+r" (dst.val));
|
|
break;
|
|
case 4:
|
|
#ifdef __x86_64__
|
|
Index: 2007-05-14/xen/include/asm-x86/cpufeature.h
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/include/asm-x86/cpufeature.h 2007-05-14 14:40:20.000000000 +0200
|
|
+++ 2007-05-14/xen/include/asm-x86/cpufeature.h 2007-05-14 14:40:43.000000000 +0200
|
|
@@ -121,6 +121,7 @@
|
|
#define cpu_has_cyrix_arr boot_cpu_has(X86_FEATURE_CYRIX_ARR)
|
|
#define cpu_has_centaur_mcr boot_cpu_has(X86_FEATURE_CENTAUR_MCR)
|
|
#define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLSH)
|
|
+#define cpu_has_cmpxchg16b 0
|
|
#else /* __x86_64__ */
|
|
#define cpu_has_vme 0
|
|
#define cpu_has_de 1
|
|
@@ -144,6 +145,7 @@
|
|
#define cpu_has_cyrix_arr 0
|
|
#define cpu_has_centaur_mcr 0
|
|
#define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLSH)
|
|
+#define cpu_has_cmpxchg16b boot_cpu_has(X86_FEATURE_CX16)
|
|
#endif
|
|
|
|
#endif /* __ASM_I386_CPUFEATURE_H */
|
|
Index: 2007-05-14/xen/include/asm-x86/x86_emulate.h
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/include/asm-x86/x86_emulate.h 2007-04-23 10:01:47.000000000 +0200
|
|
+++ 2007-05-14/xen/include/asm-x86/x86_emulate.h 2007-05-14 14:40:43.000000000 +0200
|
|
@@ -68,8 +68,9 @@ enum x86_segment {
|
|
* some out-of-band mechanism, unknown to the emulator. The memop signals
|
|
* failure by returning X86EMUL_EXCEPTION to the emulator, which will
|
|
* then immediately bail.
|
|
- * 2. Valid access sizes are 1, 2, 4 and 8 bytes. On x86/32 systems only
|
|
- * cmpxchg8b_emulated need support 8-byte accesses.
|
|
+ * 2. Valid access sizes are 1, 2, 4, 8, and 16 bytes. On x86/32 systems only
|
|
+ * cmpxchg2_emulated need support 8-byte accesses. On x86/64 systems only
|
|
+ * cmpxchg2_emulated need support 16-byte accesses.
|
|
* 3. The emulator cannot handle 64-bit mode emulation on an x86/32 system.
|
|
*/
|
|
struct x86_emulate_ops
|
|
@@ -129,16 +130,17 @@ struct x86_emulate_ops
|
|
struct x86_emulate_ctxt *ctxt);
|
|
|
|
/*
|
|
- * cmpxchg8b: Emulate an atomic (LOCKed) CMPXCHG8B operation.
|
|
+ * cmpxchg2: Emulate an atomic (LOCKed) CMPXCHG{8,16}B operation.
|
|
* @old: [IN ] Value expected to be current at @addr.
|
|
* @new: [IN ] Value to write to @addr.
|
|
* NOTES:
|
|
- * 1. This function is only ever called when emulating a real CMPXCHG8B.
|
|
- * 2. This function is *never* called on x86/64 systems.
|
|
- * 2. Not defining this function (i.e., specifying NULL) is equivalent
|
|
+ * 1. This function is only ever called when emulating a real CMPXCHG{8,16}B.
|
|
+ * 2. This function is *never* called on x86/64 systems for emulating
|
|
+ * CMPXCHG8B.
|
|
+ * 3. Not defining this function (i.e., specifying NULL) is equivalent
|
|
* to defining a function that always returns X86EMUL_UNHANDLEABLE.
|
|
*/
|
|
- int (*cmpxchg8b)(
|
|
+ int (*cmpxchg2)(
|
|
enum x86_segment seg,
|
|
unsigned long offset,
|
|
unsigned long old_lo,
|
|
Index: 2007-05-14/xen/include/asm-x86/paging.h
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/include/asm-x86/paging.h 2007-04-23 10:01:46.000000000 +0200
|
|
+++ 2007-05-14/xen/include/asm-x86/paging.h 2007-05-14 14:40:43.000000000 +0200
|
|
@@ -93,12 +93,14 @@ struct shadow_paging_mode {
|
|
unsigned long new,
|
|
unsigned int bytes,
|
|
struct sh_emulate_ctxt *sh_ctxt);
|
|
+#ifdef __i386__
|
|
int (*x86_emulate_cmpxchg8b )(struct vcpu *v, unsigned long va,
|
|
unsigned long old_lo,
|
|
unsigned long old_hi,
|
|
unsigned long new_lo,
|
|
unsigned long new_hi,
|
|
struct sh_emulate_ctxt *sh_ctxt);
|
|
+#endif
|
|
mfn_t (*make_monitor_table )(struct vcpu *v);
|
|
void (*destroy_monitor_table )(struct vcpu *v, mfn_t mmfn);
|
|
int (*guess_wrmap )(struct vcpu *v,
|