[added back cc] Paul Turner wrote: > On 7/13/07, Avi Kivity <[EMAIL PROTECTED]> wrote: >> Paul Turner wrote: >> > From: Paul Turner <[EMAIL PROTECTED]> >> > >> > - vcpus now allocated on demand >> > - vmx/svm fields separated into arch specific structures on vcpus >> > - vmx/svm fields now only allocated on corresponding architectures >> > >> > - Paul >> > >> > diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h >> > index 0f7a4d9..c631192 100644 >> > --- a/drivers/kvm/kvm.h >> > +++ b/drivers/kvm/kvm.h >> > @@ -16,6 +16,7 @@ #include <linux/mm.h> >> > #include <asm/signal.h> >> > >> > #include "vmx.h" >> > +#include "kvm_svm.h" >> >> This can probably be avoided, see below. >> >> > #include <linux/kvm.h> >> > #include <linux/kvm_para.h> >> > >> > @@ -326,16 +327,64 @@ struct kvm_io_device *kvm_io_bus_find_de >> > void kvm_io_bus_register_dev(struct kvm_io_bus *bus, >> > struct kvm_io_device *dev); >> > >> > +struct kvm_vmx_data { >> > + int msr_offset_efer; >> > + >> > + #ifdef CONFIG_X86_64 >> > + int msr_offset_kernel_gs_base; >> > + #endif >> > + >> > + struct vmx_host_state { >> > + int loaded; >> > + u16 fs_sel, gs_sel, ldt_sel; >> > + int fs_gs_ldt_reload_needed; >> > + } host_state; >> > + >> > + struct vmx_msr_entry *guest_msrs; >> > + struct vmx_msr_entry *host_msrs; >> > + >> > + struct { >> > + int active; >> > + u8 save_iopl; >> > + struct kvm_save_segment { >> > + u16 selector; >> > + unsigned long base; >> > + u32 limit; >> > + u32 ar; >> > + } tr, es, ds, fs, gs; >> > + } rmode; >> > + int halt_request; /* real mode */ >> > + + struct vmcs *vmcs; >> > +}; >> > + >> >> If this is moved to vmx.c, we can avoid including vmx.h and have no arch >> dependent code here (given that we don't even need the size). >> > > I originally did this however gcc refuses to compile with the > incomplete types, although after further investigation it turns out > it's a bug in gcc with an incomplete implementation of zero sized > arrays under a union, so I can fix this now. See notes below.. >
Looks like you forgot the notes below :) Anyway the only fix I can see is to have a long[0] member at the end, and have vmx.c define a function vmx(vcpu) which returns the vmx specific data. Accesses would look like vmx(vcpu)->cr0 = 42; which is odd, but I've seen worse. But if you have a better solution, let's hear it. >> > +struct kvm_svm_data { >> > + struct vmcb *vmcb; >> > + unsigned long vmcb_pa; >> > + struct svm_cpu_data *svm_data; >> > + uint64_t asid_generation; >> > + >> > + unsigned long db_regs[NUM_DB_REGS]; >> > + >> > + u64 next_rip; >> > + >> > + u64 host_user_msrs[NR_HOST_SAVE_USER_MSRS]; >> > + u64 host_gs_base; >> > + unsigned long host_cr2; >> > + unsigned long host_db_regs[NUM_DB_REGS]; >> > + unsigned long host_dr6; >> > + unsigned long host_dr7; >> > +}; >> >> This can remain in kvm_svm.h. > > I was going to move both structures out in a small follow up patch, I > didn't in this one because of the compile issue above + not wanting to > make this patch any larger than it already is.. :) I can merge it > into this one if you prefer.. Don't understand. If it remains in kvm_svm.h, the patch gets smaller, not larger. > >> >> >> > + >> > + >> > struct kvm_vcpu { >> > struct kvm *kvm; >> > + struct mutex *mutex; /* refers to corresponding vcpu_mutex on >> kvm */ >> >> Please keep this as a real structure, not a pointer. Existence testing >> of the vcpu is now simply if (kvm->vcpus[slot]). > > Some of the existing code makes the assumption that locking the cpu > locks the slot as well; also if we don't have an associated lock/mutex > then we'd have to take a global lock on slot updates/checks. Finally > you'd still have a race in between checking it's a valid vcpu and > trying to acquire it's mutex.. The only place the race matters is in vcpu creation. There, we can do something like vcpu = kvm_arch_ops->vcpu_create(...); spin_lock(kvm); if (kvm->vcpus[slot]) { r = -EEXIST; vcpu_free(vcpu); } else kvm->vcpus[slot] = vcpu; spin_unlock(kvm); In the other places, if the user has a thread creating a vcpu and another thread performing an operation on it, it's perfectly legitimate to return -ENOENT. >> > - page = alloc_page(GFP_KERNEL | __GFP_ZERO); >> > + vcpu->mutex = &kvm->vcpu_mutex[n]; >> > + vcpu->cpu = -1; >> > + vcpu->kvm = kvm; >> > + vcpu->mmu.root_hpa = INVALID_PAGE; >> > + >> > + vcpu->vcpu_id = n; >> > + kvm->vcpus[n] = vcpu; >> > + >> > + run_page = alloc_page(GFP_KERNEL | __GFP_ZERO); >> > r = -ENOMEM; >> > - if (!page) >> > - goto out_unlock; >> > - vcpu->run = page_address(page); >> > + if (!run_page) >> > + goto out_deallocate; >> > + vcpu->run = page_address(run_page); >> > >> >> This cleanup is good, but makes the patch larger. Please defer it. >> > > this needs to be done on vcpu creation (it was part of vm init > before), if you're concerned about patch size I can break up the > structure separation and dynamic allocation fairly easily since they > are different commits in my repository (I just didn't originally want > to rebase them both :) Yes, you're right -- it is necessary. It can live in the main patch. > > please advise on splits/etc as above and ill resubmit > One patch is okay. We should aim for kvm_main.c not knowing (including) anything about vmx or svm. -- Do not meddle in the internals of kernels, for they are subtle and quick to panic. ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/ _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel