1552
struct x86_segment_descriptor *desc,
1553
enum X86Seg seg_idx)
1554
{
1555
- bool ret;
1555
X86CPU *x86_cpu = X86_CPU(cpu);
1556
CPUX86State *env = &x86_cpu->env;
1557
SegmentCache *seg = &env->segs[seg_idx];
1559
- x86_segment_selector sel = { .sel = seg->selector & 0xFFFF };
1560
-
1561
- ret = x86_read_segment_descriptor(cpu, desc, sel);
1562
- if (ret == false) {
1563
- error_report("failed to read segment descriptor");
1564
- abort();
1558
+ uint32_t limit;
1559
+
1560
+ memset(desc, 0, sizeof(struct x86_segment_descriptor));
1561
+
1562
+ desc->type = (seg->flags & DESC_TYPE_MASK) >> DESC_TYPE_SHIFT;
1563
+ desc->s = (seg->flags & DESC_S_MASK) >> DESC_S_SHIFT;
1564
+ desc->dpl = (seg->flags & DESC_DPL_MASK) >> DESC_DPL_SHIFT;
1565
+ desc->p = (seg->flags & DESC_P_MASK) >> DESC_P_SHIFT;
1566
+ desc->avl = (seg->flags & DESC_AVL_MASK) >> DESC_AVL_SHIFT;
1567
+ desc->l = (seg->flags & DESC_L_MASK) >> DESC_L_SHIFT;
1568
+ desc->db = (seg->flags & DESC_B_MASK) >> DESC_B_SHIFT;
1569
+ desc->g = (seg->flags & DESC_G_MASK) >> DESC_G_SHIFT;
1570
+
1571
+ /*
1572
+ * SegmentCache stores the hypervisor-provided value verbatim (populated by
1573
+ * mshv_load_regs). We need to convert it to format expected by the
1574
+ * instruction emulator. We can have a limit value > 0xfffff with
1575
+ * granularity of 0 (byte granularity), which is not representable
1576
+ * in real x86_segment_descriptor. In this case we set granularity to 1
1577
+ * (4k granularity) and shift the limit accordingly.
1578
+ *
1579
+ * This quirk has been adopted from "whpx_segment_to_x86_description()"
1580
+ */
1581
+
1582
+ if (!desc->g && seg->limit <= 0xfffff) {
1583
+ limit = seg->limit;
1584
+ } else {
1585
+ limit = seg->limit >> 12;
1586
+ desc->g = 1;
1587
}
1588
+
1589
+ x86_set_segment_limit(desc, limit);
1590
+ x86_set_segment_base(desc, seg->base);
1591
}
1592
1593
static const struct x86_emul_ops mshv_x86_emul_ops = {