Re: [PATCH 3/5] Nested VMX patch 3 implements vmptrld and vmptrst

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




Avi Kivity <avi@xxxxxxxxxx> wrote on 20/10/2009 06:24:33:

> From:
>
> Avi Kivity <avi@xxxxxxxxxx>
>
> To:
>
> Orit Wasserman/Haifa/IBM@IBMIL
>
> Cc:
>
> kvm@xxxxxxxxxxxxxxx, Ben-Ami Yassour1/Haifa/IBM@IBMIL, Abel Gordon/
> Haifa/IBM@IBMIL, Muli Ben-Yehuda/Haifa/IBM@IBMIL,
> aliguori@xxxxxxxxxx, mdday@xxxxxxxxxx
>
> Date:
>
> 20/10/2009 06:24
>
> Subject:
>
> Re: [PATCH 3/5] Nested VMX patch 3 implements vmptrld and vmptrst
>
> On 10/15/2009 11:41 PM, oritw@xxxxxxxxxx wrote:
> >
> > +
> > +struct __attribute__ ((__packed__)) shadow_vmcs {
> >
>
> Since this is in guest memory, we need it packed so the binary format is
> preserved across migration.  Please add a comment so it isn't changed
> (at least without changing the revision_id).
I will add a comment.
>
> vmclear state should be here, that will help multiguest support.
Working on it ...
>
> >
> >   struct nested_vmx {
> >      /* Has the level1 guest done vmxon? */
> >      bool vmxon;
> > -
> > +   /* What is the location of the  vmcs l1 keeps for l2? (in level1
gpa) */
> > +   u64 vmptr;
> >
>
> Need to expose it for live migration.
I will look into it.
>
> >      /*
> >       * Level 2 state : includes vmcs,registers and
> >       * a copy of vmcs12 for vmread/vmwrite
> >       */
> >      struct level_state *l2_state;
> > +   /* Level 1 state for switching to level 2 and back */
> > +   struct level_state *l1_state;
> >
>
> This creates a ton of duplication.
>
> Some of the data is completely unnecessary, for example we can
> recalculate cr0 from HOST_CR0 and GUEST_CR0.
I will look into it .
>
> > +
> > +static int vmptrld(struct kvm_vcpu *vcpu,
> > +         u64 phys_addr)
> > +{
> > +   u8 error;
> > +
> > +   asm volatile (__ex(ASM_VMX_VMPTRLD_RAX) "; setna %0"
> > +            : "=g"(error) : "a"(&phys_addr), "m"(phys_addr)
> > +            : "cc");
> > +   if (error) {
> > +      printk(KERN_ERR "kvm: %s vmptrld %llx failed\n",
> > +             __func__, phys_addr);
> > +      return 1;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> >   /*
> >    * Switches to specified vcpu, until a matching vcpu_put(), but
assumes
> >    * vcpu mutex is already taken.
> > @@ -736,15 +923,8 @@ static void vmx_vcpu_load(struct kvm_vcpu
> *vcpu, int cpu)
> >      }
> >
> >      if (per_cpu(current_vmcs, cpu) != vmx->vmcs) {
> > -      u8 error;
> > -
> >         per_cpu(current_vmcs, cpu) = vmx->vmcs;
> > -      asm volatile (__ex(ASM_VMX_VMPTRLD_RAX) "; setna %0"
> > -               : "=g"(error) : "a"(&phys_addr), "m"(phys_addr)
> > -               : "cc");
> > -      if (error)
> > -         printk(KERN_ERR "kvm: vmptrld %p/%llx fail\n",
> > -                vmx->vmcs, phys_addr);
> > +      vmptrld(vcpu, phys_addr);
> >      }
> >
>
> This part of the patch is no longer needed.
I will remove it.
> > +   if (cpu_has_vmx_msr_bitmap())
> > +      vmx->nested.l2_state->msr_bitmap = vmcs_read64(MSR_BITMAP);
> > +   else
> > +      vmx->nested.l2_state->msr_bitmap = 0;
> > +
> > +   vmx->nested.l2_state->io_bitmap_a = vmcs_read64(IO_BITMAP_A);
> > +   vmx->nested.l2_state->io_bitmap_b = vmcs_read64(IO_BITMAP_B);
> > +
> >
>
> This no longer works, since we don't load the guest vmcs.
I will look into it.
>
> > +int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes,
> > +         struct kvm_vcpu *vcpu);
> >
>
> Isn't this in a header somewhere?
I will move it into the header.
>
> > +
> > +int read_guest_vmcs_gpa(struct kvm_vcpu *vcpu, u64 *gentry)
> > +{
> > +
> > +   int r = 0;
> > +
> > +   r = kvm_read_guest_virt(vcpu->arch.regs[VCPU_REGS_RAX], gentry,
> > +            sizeof(u64), vcpu);
> > +   if (r) {
> > +      printk(KERN_ERR "%s cannot read guest vmcs addr %lx : %d\n",
> > +             __func__, vcpu->arch.regs[VCPU_REGS_RAX], r);
> > +      return r;
> > +   }
> > +
> > +   if (!IS_ALIGNED(*gentry, PAGE_SIZE)) {
> > +      printk(KERN_DEBUG "%s addr %llx not aligned\n",
> > +             __func__, *gentry);
> > +      return 1;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> >
>
> Should go through the emulator to evaluate arguments.
OK.
>
> > +static int handle_vmptrld(struct kvm_vcpu *vcpu)
> > +{
> > +   struct vcpu_vmx *vmx = to_vmx(vcpu);
> > +   struct page *vmcs_page;
> > +   u64 guest_vmcs_addr;
> > +
> > +   if (!nested_vmx_check_permission(vcpu))
> > +      return 1;
> > +
> > +   if (read_guest_vmcs_gpa(vcpu,&guest_vmcs_addr))
> > +      return 1;
> > +
> > +   if (create_l1_state(vcpu)) {
> > +      printk(KERN_ERR "%s create_l1_state failed\n", __func__);
> > +      return 1;
> > +   }
> > +
> > +   if (create_l2_state(vcpu)) {
> > +      printk(KERN_ERR "%s create_l2_state failed\n", __func__);
> > +      return 1;
> > +   }
> >
>
> return errors here, so we see the problem.
OK.
>
> > +
> > +static int handle_vmptrst(struct kvm_vcpu *vcpu)
> > +{
> > +   int r = 0;
> > +
> > +   if (!nested_vmx_check_permission(vcpu))
> > +      return 1;
> > +
> > +   r = kvm_write_guest_virt(vcpu->arch.regs[VCPU_REGS_RAX],
> > +             (void *)&to_vmx(vcpu)->nested.vmptr,
> > +             sizeof(u64), vcpu);
> >
>
> Emulator again.
OK.
>
> > +void save_vmcs(struct shadow_vmcs *dst)
> > +{
> >
> > +   dst->io_bitmap_a = vmcs_read64(IO_BITMAP_A);
> > +   dst->io_bitmap_b = vmcs_read64(IO_BITMAP_B);
> >
>
> These (and many others) can never change due to a nested guest running,
> so no need to save them.
>
> > +   dst->virtual_apic_page_addr = vmcs_read64(VIRTUAL_APIC_PAGE_ADDR);
> >
>
> In general, you need to translate host physical addresses to guest
> physical addresses.
If this is VMCS12 than it is already guest physical address.
>
> > +   dst->apic_access_addr = vmcs_read64(APIC_ACCESS_ADDR);
> > +   if (enable_ept)
> > +      dst->ept_pointer = vmcs_read64(EPT_POINTER);
> > +
> >
>
> Not all hosts support these features.
I will add a check.
>
> --
> I have a truly marvellous patch that fixes the bug which this
> signature is too narrow to contain.
>

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux