All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] target/i386: tcg: fixes for 16-bit protected mode tasks
@ 2021-06-03 14:27 Paolo Bonzini
  2021-06-03 14:27 ` [PATCH 1/3] target/i386: tcg: fix segment register offsets for 16-bit TSS Paolo Bonzini
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Paolo Bonzini @ 2021-06-03 14:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell

A few bugs found by inspection---either by me or, in the case of the first
patch, by Peter on a rare i386 incursion of his.

Paolo

Paolo Bonzini (3):
  target/i386: tcg: fix segment register offsets for 16-bit TSS
  target/i386: tcg: fix loading of registers from 16-bit TSS
  target/i386: tcg: fix switching from 16-bit to 32-bit tasks or vice
    versa

 target/i386/tcg/seg_helper.c | 31 ++++++++++++++-----------------
 1 file changed, 14 insertions(+), 17 deletions(-)

-- 
2.31.1



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

* [PATCH 1/3] target/i386: tcg: fix segment register offsets for 16-bit TSS
  2021-06-03 14:27 [PATCH 0/3] target/i386: tcg: fixes for 16-bit protected mode tasks Paolo Bonzini
@ 2021-06-03 14:27 ` Paolo Bonzini
  2021-06-03 14:41   ` Peter Maydell
  2021-06-03 14:27 ` [PATCH 2/3] target/i386: tcg: fix loading of registers from " Paolo Bonzini
  2021-06-03 14:27 ` [PATCH 3/3] target/i386: tcg: fix switching from 16-bit to 32-bit tasks or vice versa Paolo Bonzini
  2 siblings, 1 reply; 5+ messages in thread
From: Paolo Bonzini @ 2021-06-03 14:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell

The TSS offsets in the manuals have only 2-byte slots for the
segment registers.  QEMU incorrectly uses 4-byte slots, so
that SS overlaps the LDT selector.

Resolves: #382
Reported-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/tcg/seg_helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
index 2f6cdc8239..547b959689 100644
--- a/target/i386/tcg/seg_helper.c
+++ b/target/i386/tcg/seg_helper.c
@@ -281,7 +281,7 @@ static void switch_tss_ra(CPUX86State *env, int tss_selector,
                                              retaddr) | 0xffff0000;
         }
         for (i = 0; i < 4; i++) {
-            new_segs[i] = cpu_lduw_kernel_ra(env, tss_base + (0x22 + i * 4),
+            new_segs[i] = cpu_lduw_kernel_ra(env, tss_base + (0x22 + i * 2),
                                              retaddr);
         }
         new_ldt = cpu_lduw_kernel_ra(env, tss_base + 0x2a, retaddr);
@@ -349,7 +349,7 @@ static void switch_tss_ra(CPUX86State *env, int tss_selector,
         cpu_stw_kernel_ra(env, env->tr.base + (0x12 + 6 * 2), env->regs[R_ESI], retaddr);
         cpu_stw_kernel_ra(env, env->tr.base + (0x12 + 7 * 2), env->regs[R_EDI], retaddr);
         for (i = 0; i < 4; i++) {
-            cpu_stw_kernel_ra(env, env->tr.base + (0x22 + i * 4),
+            cpu_stw_kernel_ra(env, env->tr.base + (0x22 + i * 2),
                               env->segs[i].selector, retaddr);
         }
     }
-- 
2.31.1




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

* [PATCH 2/3] target/i386: tcg: fix loading of registers from 16-bit TSS
  2021-06-03 14:27 [PATCH 0/3] target/i386: tcg: fixes for 16-bit protected mode tasks Paolo Bonzini
  2021-06-03 14:27 ` [PATCH 1/3] target/i386: tcg: fix segment register offsets for 16-bit TSS Paolo Bonzini
@ 2021-06-03 14:27 ` Paolo Bonzini
  2021-06-03 14:27 ` [PATCH 3/3] target/i386: tcg: fix switching from 16-bit to 32-bit tasks or vice versa Paolo Bonzini
  2 siblings, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2021-06-03 14:27 UTC (permalink / raw)
  To: qemu-devel

According to the manual, the high 16-bit of the registers are preserved
when switching to a 16-bit task.  Implement this in switch_tss_ra.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/tcg/seg_helper.c | 25 +++++++++++--------------
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
index 547b959689..2112c5fc51 100644
--- a/target/i386/tcg/seg_helper.c
+++ b/target/i386/tcg/seg_helper.c
@@ -277,8 +277,7 @@ static void switch_tss_ra(CPUX86State *env, int tss_selector,
         new_eip = cpu_lduw_kernel_ra(env, tss_base + 0x0e, retaddr);
         new_eflags = cpu_lduw_kernel_ra(env, tss_base + 0x10, retaddr);
         for (i = 0; i < 8; i++) {
-            new_regs[i] = cpu_lduw_kernel_ra(env, tss_base + (0x12 + i * 2),
-                                             retaddr) | 0xffff0000;
+            new_regs[i] = cpu_lduw_kernel_ra(env, tss_base + (0x12 + i * 2), retaddr);
         }
         for (i = 0; i < 4; i++) {
             new_segs[i] = cpu_lduw_kernel_ra(env, tss_base + (0x22 + i * 2),
@@ -391,19 +390,17 @@ static void switch_tss_ra(CPUX86State *env, int tss_selector,
     env->eip = new_eip;
     eflags_mask = TF_MASK | AC_MASK | ID_MASK |
         IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
-    if (!(type & 8)) {
-        eflags_mask &= 0xffff;
+    if (type & 8) {
+        cpu_load_eflags(env, new_eflags, eflags_mask);
+        for (i = 0; i < 8; i++) {
+            env->regs[i] = new_regs[i];
+        }
+    } else {
+        cpu_load_eflags(env, new_eflags, eflags_mask & 0xffff);
+        for (i = 0; i < 8; i++) {
+            env->regs[i] = (env->regs[i] & 0xffff0000) | new_regs[i];
+        }
     }
-    cpu_load_eflags(env, new_eflags, eflags_mask);
-    /* XXX: what to do in 16 bit case? */
-    env->regs[R_EAX] = new_regs[0];
-    env->regs[R_ECX] = new_regs[1];
-    env->regs[R_EDX] = new_regs[2];
-    env->regs[R_EBX] = new_regs[3];
-    env->regs[R_ESP] = new_regs[4];
-    env->regs[R_EBP] = new_regs[5];
-    env->regs[R_ESI] = new_regs[6];
-    env->regs[R_EDI] = new_regs[7];
     if (new_eflags & VM_MASK) {
         for (i = 0; i < 6; i++) {
             load_seg_vm(env, i, new_segs[i]);
-- 
2.31.1




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

* [PATCH 3/3] target/i386: tcg: fix switching from 16-bit to 32-bit tasks or vice versa
  2021-06-03 14:27 [PATCH 0/3] target/i386: tcg: fixes for 16-bit protected mode tasks Paolo Bonzini
  2021-06-03 14:27 ` [PATCH 1/3] target/i386: tcg: fix segment register offsets for 16-bit TSS Paolo Bonzini
  2021-06-03 14:27 ` [PATCH 2/3] target/i386: tcg: fix loading of registers from " Paolo Bonzini
@ 2021-06-03 14:27 ` Paolo Bonzini
  2 siblings, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2021-06-03 14:27 UTC (permalink / raw)
  To: qemu-devel

The format of the task state segment is governed by bit 3 in the
descriptor type field.  On a task switch, the format for saving
is given by the current value of TR's type field, while the
format for loading is given by the new descriptor.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/tcg/seg_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
index 2112c5fc51..3ed20ca31d 100644
--- a/target/i386/tcg/seg_helper.c
+++ b/target/i386/tcg/seg_helper.c
@@ -319,7 +319,7 @@ static void switch_tss_ra(CPUX86State *env, int tss_selector,
     }
 
     /* save the current state in the old TSS */
-    if (type & 8) {
+    if (old_type & 8) {
         /* 32 bit */
         cpu_stl_kernel_ra(env, env->tr.base + 0x20, next_eip, retaddr);
         cpu_stl_kernel_ra(env, env->tr.base + 0x24, old_eflags, retaddr);
-- 
2.31.1



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

* Re: [PATCH 1/3] target/i386: tcg: fix segment register offsets for 16-bit TSS
  2021-06-03 14:27 ` [PATCH 1/3] target/i386: tcg: fix segment register offsets for 16-bit TSS Paolo Bonzini
@ 2021-06-03 14:41   ` Peter Maydell
  0 siblings, 0 replies; 5+ messages in thread
From: Peter Maydell @ 2021-06-03 14:41 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: QEMU Developers

On Thu, 3 Jun 2021 at 15:27, Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> The TSS offsets in the manuals have only 2-byte slots for the
> segment registers.  QEMU incorrectly uses 4-byte slots, so
> that SS overlaps the LDT selector.
>
> Resolves: #382
> Reported-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


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

end of thread, other threads:[~2021-06-03 14:42 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-03 14:27 [PATCH 0/3] target/i386: tcg: fixes for 16-bit protected mode tasks Paolo Bonzini
2021-06-03 14:27 ` [PATCH 1/3] target/i386: tcg: fix segment register offsets for 16-bit TSS Paolo Bonzini
2021-06-03 14:41   ` Peter Maydell
2021-06-03 14:27 ` [PATCH 2/3] target/i386: tcg: fix loading of registers from " Paolo Bonzini
2021-06-03 14:27 ` [PATCH 3/3] target/i386: tcg: fix switching from 16-bit to 32-bit tasks or vice versa Paolo Bonzini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.