diff mbox

[v3] x86emul: support XSETBV

Message ID 57EE4ED9020000780011415A@prv-mh.provo.novell.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jan Beulich Sept. 30, 2016, 9:39 a.m. UTC
This is a prereq for switching PV privileged op emulation to the
generic instruction emulator. Since handle_xsetbv() is already capable
of dealing with all guest kinds, avoid introducing another hook here.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v3: Include asm/xstate.h, requiring adjustments to EFER_* definition
    placement (which otherwise causes conflicts with their definition
    elsewhere).
v2: Explicitly generate #UD when vex.pfx is non-zero.
x86emul: support XSETBV

This is a prereq for switching PV privileged op emulation to the
generic instruction emulator. Since handle_xsetbv() is already capable
of dealing with all guest kinds, avoid introducing another hook here.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v3: Include asm/xstate.h, requiring adjustments to EFER_* definition
    placement (which otherwise causes conflicts with their definition
    elsewhere).
v2: Explicitly generate #UD when vex.pfx is non-zero.

--- a/tools/tests/x86_emulator/x86_emulate.c
+++ b/tools/tests/x86_emulator/x86_emulate.c
@@ -10,6 +10,9 @@ typedef bool bool_t;
 
 #define is_canonical_address(x) (((int64_t)(x) >> 47) == ((int64_t)(x) >> 63))
 
+#define EFER_SCE       (1 << 0)
+#define EFER_LMA       (1 << 10)
+
 #define BUG() abort()
 #define ASSERT assert
 #define ASSERT_UNREACHABLE() assert(!__LINE__)
--- a/xen/arch/x86/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate.c
@@ -13,6 +13,7 @@
 #include <asm/x86_emulate.h>
 #include <asm/asm_defns.h> /* mark_regs_dirty() */
 #include <asm/processor.h> /* current_cpu_info */
+#include <asm/xstate.h>
 #include <asm/amd.h> /* cpu_has_amd_erratum() */
 
 /* Avoid namespace pollution. */
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -410,8 +410,6 @@ typedef union {
 #define MSR_SYSENTER_ESP 0x00000175
 #define MSR_SYSENTER_EIP 0x00000176
 #define MSR_EFER         0xc0000080
-#define EFER_SCE         (1u<<0)
-#define EFER_LMA         (1u<<10)
 #define MSR_STAR         0xc0000081
 #define MSR_LSTAR        0xc0000082
 #define MSR_CSTAR        0xc0000083
@@ -4163,6 +4161,23 @@ x86_emulate(
 
         switch( modrm )
         {
+#ifdef __XEN__
+        case 0xd1: /* xsetbv */
+        {
+            unsigned long cr4;
+
+            generate_exception_if(vex.pfx, EXC_UD, -1);
+            if ( !ops->read_cr || ops->read_cr(4, &cr4, ctxt) != X86EMUL_OKAY )
+                cr4 = 0;
+            generate_exception_if(!(cr4 & X86_CR4_OSXSAVE), EXC_UD, -1);
+            generate_exception_if(!mode_ring0() ||
+                                  handle_xsetbv(_regs._ecx,
+                                                _regs._eax | (_regs.rdx << 32)),
+                                  EXC_GP, 0);
+            goto no_writeback;
+        }
+#endif
+
         case 0xdf: /* invlpga */
             generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1);
             generate_exception_if(!mode_ring0(), EXC_GP, 0);

Comments

Andrew Cooper Sept. 30, 2016, 10:10 a.m. UTC | #1
On 30/09/16 10:39, Jan Beulich wrote:
> This is a prereq for switching PV privileged op emulation to the
> generic instruction emulator. Since handle_xsetbv() is already capable
> of dealing with all guest kinds, avoid introducing another hook here.
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
diff mbox

Patch

--- a/tools/tests/x86_emulator/x86_emulate.c
+++ b/tools/tests/x86_emulator/x86_emulate.c
@@ -10,6 +10,9 @@  typedef bool bool_t;
 
 #define is_canonical_address(x) (((int64_t)(x) >> 47) == ((int64_t)(x) >> 63))
 
+#define EFER_SCE       (1 << 0)
+#define EFER_LMA       (1 << 10)
+
 #define BUG() abort()
 #define ASSERT assert
 #define ASSERT_UNREACHABLE() assert(!__LINE__)
--- a/xen/arch/x86/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate.c
@@ -13,6 +13,7 @@ 
 #include <asm/x86_emulate.h>
 #include <asm/asm_defns.h> /* mark_regs_dirty() */
 #include <asm/processor.h> /* current_cpu_info */
+#include <asm/xstate.h>
 #include <asm/amd.h> /* cpu_has_amd_erratum() */
 
 /* Avoid namespace pollution. */
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -410,8 +410,6 @@  typedef union {
 #define MSR_SYSENTER_ESP 0x00000175
 #define MSR_SYSENTER_EIP 0x00000176
 #define MSR_EFER         0xc0000080
-#define EFER_SCE         (1u<<0)
-#define EFER_LMA         (1u<<10)
 #define MSR_STAR         0xc0000081
 #define MSR_LSTAR        0xc0000082
 #define MSR_CSTAR        0xc0000083
@@ -4163,6 +4161,23 @@  x86_emulate(
 
         switch( modrm )
         {
+#ifdef __XEN__
+        case 0xd1: /* xsetbv */
+        {
+            unsigned long cr4;
+
+            generate_exception_if(vex.pfx, EXC_UD, -1);
+            if ( !ops->read_cr || ops->read_cr(4, &cr4, ctxt) != X86EMUL_OKAY )
+                cr4 = 0;
+            generate_exception_if(!(cr4 & X86_CR4_OSXSAVE), EXC_UD, -1);
+            generate_exception_if(!mode_ring0() ||
+                                  handle_xsetbv(_regs._ecx,
+                                                _regs._eax | (_regs.rdx << 32)),
+                                  EXC_GP, 0);
+            goto no_writeback;
+        }
+#endif
+
         case 0xdf: /* invlpga */
             generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1);
             generate_exception_if(!mode_ring0(), EXC_GP, 0);