qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [5318] SYSENTER/SYSEXIT IA-32e implementation (Alexander Graf).
@ 2008-09-25 18:16 Andrzej Zaborowski
  2008-09-29 16:10 ` Anthony Liguori
  0 siblings, 1 reply; 4+ messages in thread
From: Andrzej Zaborowski @ 2008-09-25 18:16 UTC (permalink / raw)
  To: qemu-devel

Revision: 5318
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5318
Author:   balrog
Date:     2008-09-25 18:16:18 +0000 (Thu, 25 Sep 2008)

Log Message:
-----------
SYSENTER/SYSEXIT IA-32e implementation (Alexander Graf).

On Intel CPUs, sysenter and sysexit are valid in 64-bit mode. This patch
makes both 64-bit aware and enables them for Intel CPUs.
Add cpu save/load for 64-bit wide sysenter variables.

Signed-off-by: Alexander Graf <agraf@suse.de>

Modified Paths:
--------------
    trunk/target-i386/cpu.h
    trunk/target-i386/helper.h
    trunk/target-i386/machine.c
    trunk/target-i386/op_helper.c
    trunk/target-i386/translate.c

Modified: trunk/target-i386/cpu.h
===================================================================
--- trunk/target-i386/cpu.h	2008-09-25 18:11:30 UTC (rev 5317)
+++ trunk/target-i386/cpu.h	2008-09-25 18:16:18 UTC (rev 5318)
@@ -549,8 +549,8 @@
 
     /* sysenter registers */
     uint32_t sysenter_cs;
-    uint32_t sysenter_esp;
-    uint32_t sysenter_eip;
+    target_ulong sysenter_esp;
+    target_ulong sysenter_eip;
     uint64_t efer;
     uint64_t star;
 
@@ -737,7 +737,7 @@
 #define cpu_signal_handler cpu_x86_signal_handler
 #define cpu_list x86_cpu_list
 
-#define CPU_SAVE_VERSION 6
+#define CPU_SAVE_VERSION 7
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel

Modified: trunk/target-i386/helper.h
===================================================================
--- trunk/target-i386/helper.h	2008-09-25 18:11:30 UTC (rev 5317)
+++ trunk/target-i386/helper.h	2008-09-25 18:16:18 UTC (rev 5318)
@@ -55,7 +55,7 @@
 DEF_HELPER(void, helper_enter64_level, (int level, int data64, target_ulong t1))
 #endif
 DEF_HELPER(void, helper_sysenter, (void))
-DEF_HELPER(void, helper_sysexit, (void))
+DEF_HELPER(void, helper_sysexit, (int dflag))
 #ifdef TARGET_X86_64
 DEF_HELPER(void, helper_syscall, (int next_eip_addend))
 DEF_HELPER(void, helper_sysret, (int dflag))

Modified: trunk/target-i386/machine.c
===================================================================
--- trunk/target-i386/machine.c	2008-09-25 18:11:30 UTC (rev 5317)
+++ trunk/target-i386/machine.c	2008-09-25 18:16:18 UTC (rev 5318)
@@ -88,9 +88,9 @@
     cpu_put_seg(f, &env->gdt);
     cpu_put_seg(f, &env->idt);
 
-    qemu_put_be32s(f, &env->sysenter_cs);
-    qemu_put_be32s(f, &env->sysenter_esp);
-    qemu_put_be32s(f, &env->sysenter_eip);
+    qemu_put_betls(f, &env->sysenter_cs);
+    qemu_put_betls(f, &env->sysenter_esp);
+    qemu_put_betls(f, &env->sysenter_eip);
 
     qemu_put_betls(f, &env->cr[0]);
     qemu_put_betls(f, &env->cr[2]);
@@ -169,7 +169,7 @@
     int32_t a20_mask;
 
     if (version_id != 3 && version_id != 4 && version_id != 5
-        && version_id != 6)
+        && version_id != 6 && version_id != 7)
         return -EINVAL;
     for(i = 0; i < CPU_NB_REGS; i++)
         qemu_get_betls(f, &env->regs[i]);
@@ -244,8 +244,13 @@
     cpu_get_seg(f, &env->idt);
 
     qemu_get_be32s(f, &env->sysenter_cs);
-    qemu_get_be32s(f, &env->sysenter_esp);
-    qemu_get_be32s(f, &env->sysenter_eip);
+    if (version_id >= 7) {
+        qemu_get_betls(f, &env->sysenter_esp);
+        qemu_get_betls(f, &env->sysenter_eip);
+    } else {
+        qemu_get_be32s(f, &env->sysenter_esp);
+        qemu_get_be32s(f, &env->sysenter_eip);
+    }
 
     qemu_get_betls(f, &env->cr[0]);
     qemu_get_betls(f, &env->cr[2]);

Modified: trunk/target-i386/op_helper.c
===================================================================
--- trunk/target-i386/op_helper.c	2008-09-25 18:11:30 UTC (rev 5317)
+++ trunk/target-i386/op_helper.c	2008-09-25 18:16:18 UTC (rev 5318)
@@ -2919,11 +2919,23 @@
     }
     env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
     cpu_x86_set_cpl(env, 0);
-    cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
-                           0, 0xffffffff,
-                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
-                           DESC_S_MASK |
-                           DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
+
+#ifdef TARGET_X86_64
+    if (env->hflags & HF_LMA_MASK) {
+        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
+                               0, 0xffffffff,
+                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_S_MASK |
+                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
+    } else
+#endif
+    {
+        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
+                               0, 0xffffffff,
+                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_S_MASK |
+                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
+    }
     cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
                            0, 0xffffffff,
                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
@@ -2933,7 +2945,7 @@
     EIP = env->sysenter_eip;
 }
 
-void helper_sysexit(void)
+void helper_sysexit(int dflag)
 {
     int cpl;
 
@@ -2942,16 +2954,32 @@
         raise_exception_err(EXCP0D_GPF, 0);
     }
     cpu_x86_set_cpl(env, 3);
-    cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
-                           0, 0xffffffff,
-                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
-                           DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
-                           DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
-    cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
-                           0, 0xffffffff,
-                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
-                           DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
-                           DESC_W_MASK | DESC_A_MASK);
+#ifdef TARGET_X86_64
+    if (dflag == 2) {
+        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 32) & 0xfffc) | 3,
+                               0, 0xffffffff,
+                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
+                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
+        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 40) & 0xfffc) | 3,
+                               0, 0xffffffff,
+                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
+                               DESC_W_MASK | DESC_A_MASK);
+    } else
+#endif
+    {
+        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
+                               0, 0xffffffff,
+                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
+                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
+        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
+                               0, 0xffffffff,
+                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
+                               DESC_W_MASK | DESC_A_MASK);
+    }
     ESP = ECX;
     EIP = EDX;
 #ifdef USE_KQEMU

Modified: trunk/target-i386/translate.c
===================================================================
--- trunk/target-i386/translate.c	2008-09-25 18:11:30 UTC (rev 5317)
+++ trunk/target-i386/translate.c	2008-09-25 18:16:18 UTC (rev 5318)
@@ -6505,7 +6505,8 @@
         tcg_gen_helper_0_0(helper_rdpmc);
         break;
     case 0x134: /* sysenter */
-        if (CODE64(s))
+        /* For Intel SYSENTER is valid on 64-bit */
+        if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
             goto illegal_op;
         if (!s->pe) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
@@ -6520,7 +6521,8 @@
         }
         break;
     case 0x135: /* sysexit */
-        if (CODE64(s))
+        /* For Intel SYSEXIT is valid on 64-bit */
+        if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
             goto illegal_op;
         if (!s->pe) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
@@ -6530,7 +6532,7 @@
                 s->cc_op = CC_OP_DYNAMIC;
             }
             gen_jmp_im(pc_start - s->cs_base);
-            tcg_gen_helper_0_0(helper_sysexit);
+            tcg_gen_helper_0_1(helper_sysexit, tcg_const_i32(dflag));
             gen_eob(s);
         }
         break;

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [5318] SYSENTER/SYSEXIT IA-32e implementation (Alexander Graf).
  2008-09-25 18:16 [Qemu-devel] [5318] SYSENTER/SYSEXIT IA-32e implementation (Alexander Graf) Andrzej Zaborowski
@ 2008-09-29 16:10 ` Anthony Liguori
  2008-09-29 16:20   ` Alexander Graf
  0 siblings, 1 reply; 4+ messages in thread
From: Anthony Liguori @ 2008-09-29 16:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: Alexander Graf

Andrzej Zaborowski wrote:
> Revision: 5318
>           http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5318
> Author:   balrog
> Date:     2008-09-25 18:16:18 +0000 (Thu, 25 Sep 2008)
>
> Log Message:
> -----------
> SYSENTER/SYSEXIT IA-32e implementation (Alexander Graf).
>
> On Intel CPUs, sysenter and sysexit are valid in 64-bit mode. This patch
> makes both 64-bit aware and enables them for Intel CPUs.
> Add cpu save/load for 64-bit wide sysenter variables.
>
> Signed-off-by: Alexander Graf <agraf@suse.de>
>   

This change broke save/restore.  It was already broken when this commit 
happened so it really just further broke it :-)

> Modified: trunk/target-i386/cpu.h
> ===================================================================
> --- trunk/target-i386/cpu.h	2008-09-25 18:11:30 UTC (rev 5317)
> +++ trunk/target-i386/cpu.h	2008-09-25 18:16:18 UTC (rev 5318)
> @@ -549,8 +549,8 @@
>  
>      /* sysenter registers */
>      uint32_t sysenter_cs;
>   

is a u32

> -    uint32_t sysenter_esp;
> -    uint32_t sysenter_eip;
> +    target_ulong sysenter_esp;
> +    target_ulong sysenter_eip;
>      uint64_t efer;
>      uint64_t star;
>   

But is being saved as a target_ulong.

> -    qemu_put_be32s(f, &env->sysenter_cs);
> -    qemu_put_be32s(f, &env->sysenter_esp);
> -    qemu_put_be32s(f, &env->sysenter_eip);
> +    qemu_put_betls(f, &env->sysenter_cs);
> +    qemu_put_betls(f, &env->sysenter_esp);
> +    qemu_put_betls(f, &env->sysenter_eip);
>  
>      qemu_put_betls(f, &env->cr[0]);
>      qemu_put_betls(f, &env->cr[2]);
> @@ -169,7 +169,7 @@

And loaded as a u32.

>  
>      qemu_get_be32s(f, &env->sysenter_cs);
> -    qemu_get_be32s(f, &env->sysenter_esp);
> -    qemu_get_be32s(f, &env->sysenter_eip);
> +    if (version_id >= 7) {
> +        qemu_get_betls(f, &env->sysenter_esp);
> +        qemu_get_betls(f, &env->sysenter_eip);
> +    } else {
> +        qemu_get_be32s(f, &env->sysenter_esp);
> +        qemu_get_be32s(f, &env->sysenter_eip);
> +    }
>  

When making changes to target-i386, please make sure to test both qemu 
and qemu-system-x86_64.  In this case, the code would have worked with 
qemu but it doesn't work with qemu-system-x86_64.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [5318] SYSENTER/SYSEXIT IA-32e implementation (Alexander Graf).
  2008-09-29 16:10 ` Anthony Liguori
@ 2008-09-29 16:20   ` Alexander Graf
  2008-09-29 16:28     ` Anthony Liguori
  0 siblings, 1 reply; 4+ messages in thread
From: Alexander Graf @ 2008-09-29 16:20 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 2386 bytes --]

Anthony Liguori wrote:
> Andrzej Zaborowski wrote:
>> Revision: 5318
>>           http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5318
>> Author:   balrog
>> Date:     2008-09-25 18:16:18 +0000 (Thu, 25 Sep 2008)
>>
>> Log Message:
>> -----------
>> SYSENTER/SYSEXIT IA-32e implementation (Alexander Graf).
>>
>> On Intel CPUs, sysenter and sysexit are valid in 64-bit mode. This patch
>> makes both 64-bit aware and enables them for Intel CPUs.
>> Add cpu save/load for 64-bit wide sysenter variables.
>>
>> Signed-off-by: Alexander Graf <agraf@suse.de>
>>   
>
> This change broke save/restore.  It was already broken when this 
> commit happened so it really just further broke it :-)
>
>> Modified: trunk/target-i386/cpu.h
>> ===================================================================
>> --- trunk/target-i386/cpu.h    2008-09-25 18:11:30 UTC (rev 5317)
>> +++ trunk/target-i386/cpu.h    2008-09-25 18:16:18 UTC (rev 5318)
>> @@ -549,8 +549,8 @@
>>  
>>      /* sysenter registers */
>>      uint32_t sysenter_cs;
>>   
>
> is a u32
>
>> -    uint32_t sysenter_esp;
>> -    uint32_t sysenter_eip;
>> +    target_ulong sysenter_esp;
>> +    target_ulong sysenter_eip;
>>      uint64_t efer;
>>      uint64_t star;
>>   
>
> But is being saved as a target_ulong.
>
>> -    qemu_put_be32s(f, &env->sysenter_cs);
>> -    qemu_put_be32s(f, &env->sysenter_esp);
>> -    qemu_put_be32s(f, &env->sysenter_eip);
>> +    qemu_put_betls(f, &env->sysenter_cs);
>> +    qemu_put_betls(f, &env->sysenter_esp);
>> +    qemu_put_betls(f, &env->sysenter_eip);
>>  
>>      qemu_put_betls(f, &env->cr[0]);
>>      qemu_put_betls(f, &env->cr[2]);
>> @@ -169,7 +169,7 @@
>
> And loaded as a u32.
>
>>  
>>      qemu_get_be32s(f, &env->sysenter_cs);
>> -    qemu_get_be32s(f, &env->sysenter_esp);
>> -    qemu_get_be32s(f, &env->sysenter_eip);
>> +    if (version_id >= 7) {
>> +        qemu_get_betls(f, &env->sysenter_esp);
>> +        qemu_get_betls(f, &env->sysenter_eip);
>> +    } else {
>> +        qemu_get_be32s(f, &env->sysenter_esp);
>> +        qemu_get_be32s(f, &env->sysenter_eip);
>> +    }
>>  
>
> When making changes to target-i386, please make sure to test both qemu 
> and qemu-system-x86_64.  In this case, the code would have worked with 
> qemu but it doesn't work with qemu-system-x86_64.

Ouch, thanks for the catch. Please  double-check and apply :-).

Alex

[-- Attachment #2: sysenter-save.patch --]
[-- Type: text/x-patch, Size: 440 bytes --]

Index: target-i386/machine.c
===================================================================
--- target-i386/machine.c	(revision 5350)
+++ target-i386/machine.c	(working copy)
@@ -88,7 +88,7 @@
     cpu_put_seg(f, &env->gdt);
     cpu_put_seg(f, &env->idt);
 
-    qemu_put_betls(f, &env->sysenter_cs);
+    qemu_put_be32s(f, &env->sysenter_cs);
     qemu_put_betls(f, &env->sysenter_esp);
     qemu_put_betls(f, &env->sysenter_eip);
 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [5318] SYSENTER/SYSEXIT IA-32e implementation (Alexander Graf).
  2008-09-29 16:20   ` Alexander Graf
@ 2008-09-29 16:28     ` Anthony Liguori
  0 siblings, 0 replies; 4+ messages in thread
From: Anthony Liguori @ 2008-09-29 16:28 UTC (permalink / raw)
  To: Alexander Graf; +Cc: qemu-devel

Alexander Graf wrote:
> Ouch, thanks for the catch. Please  double-check and apply :-).

Already did.

Regards,

Anthony Liguori

> Alex

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-09-29 16:29 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-25 18:16 [Qemu-devel] [5318] SYSENTER/SYSEXIT IA-32e implementation (Alexander Graf) Andrzej Zaborowski
2008-09-29 16:10 ` Anthony Liguori
2008-09-29 16:20   ` Alexander Graf
2008-09-29 16:28     ` Anthony Liguori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).