@samitouri / QOSamiQemu / commits / 9489224382

whpx: i386: fetch segments on-demand

Instead of save/restore, fetch segments dynamically. Rely on the fetched state instead of loading from memory. Or, if available, on the VM exit context. Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr> Link: https://lore.kernel.org/r/20260324151323.74473-12-mohamed@unpredictable.fr Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Mohamed Mediouni committed Mar 24, 2026 at 16:13 UTC 9489224382b43893069899a2b543bcc22b6d7b4f
1 file changed +60 -11
target/i386/whpx/whpx-all.c
+60 -11
@@ -868,21 +868,70 @@ static int whpx_handle_portio(CPUState *cpu,
868 return 0;
869 }
870
871 +static void whpx_segment_to_x86_descriptor(CPUState *cpu, WHV_X64_SEGMENT_REGISTER* reg,
872 + struct x86_segment_descriptor *desc)
873 +{
874 + uint32_t limit;
875 + desc->g = reg->Granularity;
876 +
877 + /*
878 + * Hyper-V can return reg->Granularity == 0
879 + * with a higher limit than 0xfffff.
880 + *
881 + * Detect that case and set desc->g
882 + * with shifting the limit properly.
883 + */
884 + if (!desc->g && reg->Limit <= 0xfffff) {
885 + limit = reg->Limit;
886 + } else {
887 + limit = (reg->Limit >> 12);
888 + desc->g = 1;
889 + }
890 +
891 + x86_set_segment_limit(desc, limit);
892 + x86_set_segment_base(desc, reg->Base);
893 +
894 + desc->type = reg->SegmentType;
895 + desc->s = reg->NonSystemSegment;
896 + desc->dpl = reg->DescriptorPrivilegeLevel;
897 + desc->p = reg->Present;
898 + desc->avl = reg->Available;
899 + desc->l = reg->Long;
900 + desc->db = reg->Default;
901 +}
902 +
903 +static void whpx_read_segment_descriptor(CPUState *cpu, WHV_X64_SEGMENT_REGISTER* reg,
904 + X86Seg seg)
905 +{
906 + AccelCPUState *vcpu = cpu->accel;
907 + WHV_REGISTER_NAME reg_name = WHvX64RegisterEs + seg;
908 + WHV_REGISTER_VALUE val;
909 +
910 + if (seg == R_CS) {
911 + *reg = vcpu->exit_ctx.VpContext.Cs;
912 + return;
913 + }
914 + if (vcpu->exit_ctx.ExitReason == WHvRunVpExitReasonX64IoPortAccess) {
915 + if (seg == R_DS) {
916 + *reg = vcpu->exit_ctx.IoPortAccess.Ds;
917 + return;
918 + } else if (seg == R_ES) {
919 + *reg = vcpu->exit_ctx.IoPortAccess.Es;
920 + return;
921 + }
922 + }
923 +
924 + whpx_get_reg(cpu, reg_name, &val);
925 + *reg = val.Segment;
926 +}
927 +
928 static void read_segment_descriptor(CPUState *cpu,
929 struct x86_segment_descriptor *desc,
930 enum X86Seg seg_idx)
931 {
875 - bool ret;
876 - X86CPU *x86_cpu = X86_CPU(cpu);
877 - CPUX86State *env = &x86_cpu->env;
878 - SegmentCache *seg = &env->segs[seg_idx];
879 - x86_segment_selector sel = { .sel = seg->selector & 0xFFFF };
880 -
881 - ret = x86_read_segment_descriptor(cpu, desc, sel);
882 - if (ret == false) {
883 - error_report("failed to read segment descriptor");
884 - abort();
885 - }
932 + WHV_X64_SEGMENT_REGISTER reg;
933 + whpx_read_segment_descriptor(cpu, &reg, seg_idx);
934 + whpx_segment_to_x86_descriptor(cpu, &reg, desc);
935 }
936
937 static bool is_protected_mode(CPUState *cpu)