All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] target/i386/mshv: Fix segment regression in MMIO emu
@ 2026-04-10 14:26 Magnus Kulke
  2026-04-10 16:19 ` Mohamed Mediouni
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Magnus Kulke @ 2026-04-10 14:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: Magnus Kulke, Doru Blânzeanu, Magnus Kulke, Mohamed Mediouni,
	Wei Liu, Wei Liu

When the segmentation code has been reworked, there is now an
unconditional call to emul_ops->read_segment_descriptor(). The MSHV impl
was delegating this to x86_read_segement_descriptor(), which read from
the GDT in guest memory. This fails for selector.idx == 0 and when no
GDT is set up (which is the case in real mode).

In the fix we change the MSHV impl to fill segment descriptor from
SegmentCache, that was populated from the hypervisor by mshv_load_regs()
before instruction emulation.

Fixes: 09442d98ab (target/i386: emulate: segmentation rework)

Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
---
 target/i386/mshv/mshv-cpu.c | 39 ++++++++++++++++++++++++++++++-------
 1 file changed, 32 insertions(+), 7 deletions(-)

diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index 2bc978deb2..4ed6e7548f 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -1552,17 +1552,42 @@ static void read_segment_descriptor(CPUState *cpu,
                                     struct x86_segment_descriptor *desc,
                                     enum X86Seg seg_idx)
 {
-    bool ret;
     X86CPU *x86_cpu = X86_CPU(cpu);
     CPUX86State *env = &x86_cpu->env;
     SegmentCache *seg = &env->segs[seg_idx];
-    x86_segment_selector sel = { .sel = seg->selector & 0xFFFF };
-
-    ret = x86_read_segment_descriptor(cpu, desc, sel);
-    if (ret == false) {
-        error_report("failed to read segment descriptor");
-        abort();
+    uint32_t limit;
+
+    memset(desc, 0, sizeof(struct x86_segment_descriptor));
+
+    desc->type = (seg->flags & DESC_TYPE_MASK) >> DESC_TYPE_SHIFT;
+    desc->s    = (seg->flags & DESC_S_MASK)    >> DESC_S_SHIFT;
+    desc->dpl  = (seg->flags & DESC_DPL_MASK)  >> DESC_DPL_SHIFT;
+    desc->p    = (seg->flags & DESC_P_MASK)    >> DESC_P_SHIFT;
+    desc->avl  = (seg->flags & DESC_AVL_MASK)  >> DESC_AVL_SHIFT;
+    desc->l    = (seg->flags & DESC_L_MASK)    >> DESC_L_SHIFT;
+    desc->db   = (seg->flags & DESC_B_MASK)    >> DESC_B_SHIFT;
+    desc->g    = (seg->flags & DESC_G_MASK)    >> DESC_G_SHIFT;
+
+    /*
+     * SegmentCache stores the hypervisor-provided value verbatim (populated by
+     * mshv_load_regs). We need to convert it to format expected by the
+     * instruction emulator. We can have a limit value > 0xfffff with
+     * granularity of 0 (byte granularity), which is not representable
+     * in real x86_segment_descriptor. In this case we set granularity to 1
+     * (4k granularity) and shift the limit accordingly.
+     *
+     * This quirk has been adopted from "whpx_segment_to_x86_description()"
+     */
+
+    if (!desc->g && seg->limit <= 0xfffff) {
+        limit = seg->limit;
+    } else {
+        limit = seg->limit >> 12;
+        desc->g = 1;
     }
+
+    x86_set_segment_limit(desc, limit);
+    x86_set_segment_base(desc, seg->base);
 }
 
 static const struct x86_emul_ops mshv_x86_emul_ops = {
-- 
2.34.1



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

end of thread, other threads:[~2026-04-25  8:11 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-10 14:26 [PATCH] target/i386/mshv: Fix segment regression in MMIO emu Magnus Kulke
2026-04-10 16:19 ` Mohamed Mediouni
2026-04-11 12:26 ` Paolo Bonzini
2026-04-24 21:35 ` Michael Tokarev
2026-04-25  8:10   ` Magnus Kulke

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.