On Sun, Aug 10, 2008 at 11:09 AM, Avi Kivity <[EMAIL PROTECTED]> wrote:
> Mohammed Gamal wrote:
>>
>> This patch aims to allow emulation whenever guest state is not valid for
>> VMX operation. This usually happens in mode switches with guests such as
>> older versions of gfxboot and FreeDOS with HIMEM.
>> The patch aims to address this issue, it introduces the following:
>>
>> - A function that invokes the x86 emulator when the guest state is not
>> valid (borrowed from Guillaume Thouvenin's real mode patches)
>> - A function that checks that guest register state is VMX compliant
>> - A module parameter that enables these operations. It is disabled by
>> default, in order not to intervene with KVM's normal operation
>>
>
>>  +/*
>> + * Check if guest state is valid. Returns true if valid, false if
>> + * not.
>> + * We assume that registers are always usable
>> + */
>> +static bool guest_state_valid(struct kvm_vcpu *vcpu)
>> +{
>> +       u16 cs,ds,ss,es,fs,gs,tr,ldtr;
>> +       u64 cs_limit, ds_limit, ss_limit, es_limit, fs_limit, gs_limit;
>> +       u64 tr_limit, ldtr_limit;
>> +       u32 cs_ar, ds_ar, ss_ar, es_ar, fs_ar, gs_ar, tr_ar, ldtr_ar;
>> +
>> +       cs = vmcs_read16(GUEST_CS_SELECTOR);
>> +       ds = vmcs_read16(GUEST_DS_SELECTOR);
>> +       ss = vmcs_read16(GUEST_SS_SELECTOR);
>> +       es = vmcs_read16(GUEST_ES_SELECTOR);
>> +       fs = vmcs_read16(GUEST_FS_SELECTOR);
>> +       gs = vmcs_read16(GUEST_GS_SELECTOR);
>> +       tr = vmcs_read16(GUEST_TR_SELECTOR);
>> +       ldtr = vmcs_read16(GUEST_LDTR_SELECTOR);
>> +
>> +       cs_limit = vmcs_readl(GUEST_SS_LIMIT);
>> +       ds_limit = vmcs_readl(GUEST_DS_LIMIT);
>> +       ss_limit = vmcs_readl(GUEST_SS_LIMIT);
>> +       es_limit = vmcs_readl(GUEST_ES_LIMIT);
>> +       fs_limit = vmcs_readl(GUEST_FS_LIMIT);
>> +       gs_limit = vmcs_readl(GUEST_GS_LIMIT);
>> +       tr_limit = vmcs_readl(GUEST_TR_LIMIT);
>> +
>> +       cs_ar = vmcs_read32(GUEST_CS_AR_BYTES);
>> +       ds_ar = vmcs_read32(GUEST_DS_AR_BYTES);
>> +       ss_ar = vmcs_read32(GUEST_SS_AR_BYTES);
>> +       es_ar = vmcs_read32(GUEST_ES_AR_BYTES);
>> +       fs_ar = vmcs_read32(GUEST_FS_AR_BYTES);
>> +       gs_ar = vmcs_read32(GUEST_GS_AR_BYTES);
>> +       tr_ar = vmcs_read32(GUEST_TR_AR_BYTES);
>> +       ldtr_ar = vmcs_read32(GUEST_LDTR_AR_BYTES);
>> +
>> +       if(tr & 0x02)   /* TI = 1 */
>> +               return false;
>> +
>> +       if(ldtr & 0x02) /* TI = 1 */
>> +               return false;
>> +
>> +       /* vm86 mode guest state checks */
>> +       if(vcpu->arch.rmode.active) {
>>
>
> Better to check cr0 here.

Why? when cr0.PE bit is cleared, enter_rmode() is called and
vcpu->arch.rmode.active is set, or do you mean it should be checked in
addition?

>
>> +               /* Check segment limits */
>> +               if( (cs_limit != 0xffff) || (ds_limit != 0xffff) ||
>> +                   (ss_limit != 0xffff) || (es_limit != 0xffff) ||
>> +                   (fs_limit != 0xffff) || (gs_limit != 0xffff) )
>> +                       return false;
>>
>
> Would be nice to get code reuse, here and below (i.e. data_segment_valid()
> for ds,es..gs.).  Also, vmx_get_segment() will make the code tidier.

I think the function can be further broken down into smaller functions
each checking for a certain segment parameter (e.g.
segment_limit_valid(), segment_ar_valid(), rip_valid() ...etc.) and
then call all these functions in guest_state_valid().

>
>> +
>>  static void fix_pmode_dataseg(int seg, struct kvm_save_segment *save)
>>  {
>>        struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
>> @@ -1311,10 +1486,12 @@ static void enter_pmode(struct kvm_vcpu *vcpu)
>>          update_exception_bitmap(vcpu);
>>  -       fix_pmode_dataseg(VCPU_SREG_ES, &vcpu->arch.rmode.es);
>> -       fix_pmode_dataseg(VCPU_SREG_DS, &vcpu->arch.rmode.ds);
>> -       fix_pmode_dataseg(VCPU_SREG_GS, &vcpu->arch.rmode.gs);
>> -       fix_pmode_dataseg(VCPU_SREG_FS, &vcpu->arch.rmode.fs);
>> +       if(!emulate_invalid_guest_state) {
>> +               fix_pmode_dataseg(VCPU_SREG_ES, &vcpu->arch.rmode.es);
>> +               fix_pmode_dataseg(VCPU_SREG_DS, &vcpu->arch.rmode.ds);
>> +               fix_pmode_dataseg(VCPU_SREG_GS, &vcpu->arch.rmode.gs);
>> +               fix_pmode_dataseg(VCPU_SREG_FS, &vcpu->arch.rmode.fs);
>> +       }
>>          vmcs_write16(GUEST_SS_SELECTOR, 0);
>>        vmcs_write32(GUEST_SS_AR_BYTES, 0x93);
>>
>
> These (and the other hacks below) need also to be qualified with
> emulate_invalid_guest_state.
>

I've already done that, I'll update my patch to take your suggestions
in consideration.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to