From mboxrd@z Thu Jan 1 00:00:00 1970 From: Rusty Russell Subject: [PATCH 4/4] Use kmem cache for allocating vcpus, simplify FPU ops Date: Mon, 30 Jul 2007 16:39:01 +1000 Message-ID: <1185777542.12151.156.camel@localhost.localdomain> References: <1185777103.12151.147.camel@localhost.localdomain> <1185777179.12151.149.camel@localhost.localdomain> <1185777368.12151.152.camel@localhost.localdomain> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: kvm-devel Return-path: In-Reply-To: <1185777368.12151.152.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: kvm-devel-bounces-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org Errors-To: kvm-devel-bounces-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org List-Id: kvm.vger.kernel.org If we use a kmem cache for allocating vcpus, we can get the 16-byte alignment required by fxsave & fxrstor instructions, and avoid manually aligning the buffer. Signed-off-by: Rusty Russell diff -r 39421cbc0486 drivers/kvm/kvm.h --- a/drivers/kvm/kvm.h Mon Jul 30 15:01:44 2007 +1000 +++ b/drivers/kvm/kvm.h Mon Jul 30 15:09:54 2007 +1000 @@ -43,10 +43,6 @@ #define KVM_MIN_FREE_MMU_PAGES 5 #define KVM_REFILL_PAGES 25 #define KVM_MAX_CPUID_ENTRIES 40 - -#define FX_IMAGE_SIZE 512 -#define FX_IMAGE_ALIGN 16 -#define FX_BUF_SIZE (2 * FX_IMAGE_SIZE + FX_IMAGE_ALIGN) #define DE_VECTOR 0 #define NM_VECTOR 7 @@ -339,9 +335,8 @@ struct kvm_vcpu { struct kvm_guest_debug guest_debug; - char fx_buf[FX_BUF_SIZE]; - char *host_fx_image; - char *guest_fx_image; + struct i387_fxsave_struct host_fx_image; + struct i387_fxsave_struct guest_fx_image; int fpu_active; int guest_fpu_loaded; @@ -697,12 +692,12 @@ static inline unsigned long read_msr(uns } #endif -static inline void fx_save(void *image) +static inline void fx_save(struct i387_fxsave_struct *image) { asm ("fxsave (%0)":: "r" (image)); } -static inline void fx_restore(void *image) +static inline void fx_restore(struct i387_fxsave_struct *image) { asm ("fxrstor (%0)":: "r" (image)); } diff -r 39421cbc0486 drivers/kvm/kvm_main.c --- a/drivers/kvm/kvm_main.c Mon Jul 30 15:01:44 2007 +1000 +++ b/drivers/kvm/kvm_main.c Mon Jul 30 15:10:09 2007 +1000 @@ -218,8 +218,8 @@ void kvm_load_guest_fpu(struct kvm_vcpu return; vcpu->guest_fpu_loaded = 1; - fx_save(vcpu->host_fx_image); - fx_restore(vcpu->guest_fx_image); + fx_save(&vcpu->host_fx_image); + fx_restore(&vcpu->guest_fx_image); } EXPORT_SYMBOL_GPL(kvm_load_guest_fpu); @@ -229,8 +229,8 @@ void kvm_put_guest_fpu(struct kvm_vcpu * return; vcpu->guest_fpu_loaded = 0; - fx_save(vcpu->guest_fx_image); - fx_restore(vcpu->host_fx_image); + fx_save(&vcpu->guest_fx_image); + fx_restore(&vcpu->host_fx_image); } EXPORT_SYMBOL_GPL(kvm_put_guest_fpu); @@ -317,10 +317,6 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, goto fail_free_run; } vcpu->pio_data = page_address(page); - - vcpu->host_fx_image = (char*)ALIGN((hva_t)vcpu->fx_buf, - FX_IMAGE_ALIGN); - vcpu->guest_fx_image = vcpu->host_fx_image + FX_IMAGE_SIZE; r = kvm_mmu_create(vcpu); if (r < 0) @@ -672,30 +668,20 @@ EXPORT_SYMBOL_GPL(set_cr8); void fx_init(struct kvm_vcpu *vcpu) { - struct __attribute__ ((__packed__)) fx_image_s { - u16 control; //fcw - u16 status; //fsw - u16 tag; // ftw - u16 opcode; //fop - u64 ip; // fpu ip - u64 operand;// fpu dp - u32 mxcsr; - u32 mxcsr_mask; - - } *fx_image; + unsigned after_mxcsr_mask; /* Initialize guest FPU by resetting ours and saving into guest's */ preempt_disable(); - fx_save(vcpu->host_fx_image); + fx_save(&vcpu->host_fx_image); fpu_init(); - fx_save(vcpu->guest_fx_image); - fx_restore(vcpu->host_fx_image); + fx_save(&vcpu->guest_fx_image); + fx_restore(&vcpu->host_fx_image); preempt_enable(); - fx_image = (struct fx_image_s *)vcpu->guest_fx_image; - fx_image->mxcsr = 0x1f80; - memset(vcpu->guest_fx_image + sizeof(struct fx_image_s), - 0, FX_IMAGE_SIZE - sizeof(struct fx_image_s)); + after_mxcsr_mask = offsetof(struct i387_fxsave_struct, st_space); + vcpu->guest_fx_image.mxcsr = 0x1f80; + memset((void *)&vcpu->guest_fx_image + after_mxcsr_mask, + 0, sizeof(struct i387_fxsave_struct) - after_mxcsr_mask); } EXPORT_SYMBOL_GPL(fx_init); @@ -2414,6 +2400,9 @@ static int kvm_vm_ioctl_create_vcpu(stru if (IS_ERR(vcpu)) return PTR_ERR(vcpu); + /* We do fxsave: this must be aligned. */ + BUG_ON((unsigned long)&vcpu->host_fx_image & 0xF); + vcpu_load(vcpu); r = kvm_mmu_setup(vcpu); vcpu_put(vcpu); @@ -2526,7 +2515,7 @@ struct fxsave { static int kvm_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) { - struct fxsave *fxsave = (struct fxsave *)vcpu->guest_fx_image; + struct fxsave *fxsave = (struct fxsave *)&vcpu->guest_fx_image; vcpu_load(vcpu); @@ -2546,7 +2535,7 @@ static int kvm_vcpu_ioctl_get_fpu(struct static int kvm_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) { - struct fxsave *fxsave = (struct fxsave *)vcpu->guest_fx_image; + struct fxsave *fxsave = (struct fxsave *)&vcpu->guest_fx_image; vcpu_load(vcpu); diff -r 39421cbc0486 drivers/kvm/svm.c --- a/drivers/kvm/svm.c Mon Jul 30 15:01:44 2007 +1000 +++ b/drivers/kvm/svm.c Mon Jul 30 15:09:54 2007 +1000 @@ -79,6 +79,7 @@ struct svm_cpu_data { static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data); static uint32_t svm_features; +static struct kmem_cache *svm_kmem_cache; struct svm_init_data { int cpu; @@ -559,7 +560,7 @@ static struct kvm_vcpu *svm_create_vcpu( struct page *page; int err; - svm = kzalloc(sizeof *svm, GFP_KERNEL); + svm = kmem_cache_zalloc(svm_kmem_cache, GFP_KERNEL); if (!svm) { err = -ENOMEM; goto out; @@ -1540,8 +1541,8 @@ again: } if (vcpu->fpu_active) { - fx_save(vcpu->host_fx_image); - fx_restore(vcpu->guest_fx_image); + fx_save(&vcpu->host_fx_image); + fx_restore(&vcpu->guest_fx_image); } asm volatile ( @@ -1653,8 +1654,8 @@ again: vcpu->guest_mode = 0; if (vcpu->fpu_active) { - fx_save(vcpu->guest_fx_image); - fx_restore(vcpu->host_fx_image); + fx_save(&vcpu->guest_fx_image); + fx_restore(&vcpu->host_fx_image); } if ((svm->vmcb->save.dr7 & 0xff)) @@ -1832,12 +1833,23 @@ static struct kvm_arch_ops svm_arch_ops static int __init svm_init(void) { - return kvm_init_arch(&svm_arch_ops, THIS_MODULE); + int err; + + /* A kmem cache lets us meet the alignment requirements of fx_save. */ + svm_kmem_cache = KMEM_CACHE(vcpu_svm, 0); + if (!svm_kmem_cache) + return -ENOMEM; + + err = kvm_init_arch(&svm_arch_ops, THIS_MODULE); + if (err) + kmem_cache_destroy(svm_kmem_cache); + return err; } static void __exit svm_exit(void) { kvm_exit_arch(); + kmem_cache_destroy(svm_kmem_cache); } module_init(svm_init) diff -r 39421cbc0486 drivers/kvm/vmx.c --- a/drivers/kvm/vmx.c Mon Jul 30 15:01:44 2007 +1000 +++ b/drivers/kvm/vmx.c Mon Jul 30 15:09:54 2007 +1000 @@ -70,6 +70,7 @@ static DEFINE_PER_CPU(struct vmcs *, cur static struct page *vmx_io_bitmap_a; static struct page *vmx_io_bitmap_b; +static struct kmem_cache *vmx_kmem_cache; #ifdef CONFIG_X86_64 #define HOST_IS_64 1 @@ -2295,7 +2296,7 @@ static struct kvm_vcpu *vmx_create_vcpu( static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id) { int err; - struct vcpu_vmx *vmx = kzalloc(sizeof(*vmx), GFP_KERNEL); + struct vcpu_vmx *vmx = kmem_cache_zalloc(vmx_kmem_cache, GFP_KERNEL); if (!vmx) return ERR_PTR(-ENOMEM); @@ -2404,6 +2405,13 @@ static int __init vmx_init(void) goto out; } + /* A kmem cache lets us meet the alignment requirements of fx_save. */ + vmx_kmem_cache = KMEM_CACHE(vcpu_vmx, 0); + if (!vmx_kmem_cache) { + r = -ENOMEM; + goto out1; + } + /* * Allow direct access to the PC debug port (it is often used for I/O * delays, but the vmexits simply slow things down). @@ -2419,10 +2427,12 @@ static int __init vmx_init(void) r = kvm_init_arch(&vmx_arch_ops, THIS_MODULE); if (r) - goto out1; + goto out2; return 0; +out2: + kmem_cache_destroy(vmx_kmem_cache); out1: __free_page(vmx_io_bitmap_b); out: @@ -2432,6 +2442,7 @@ out: static void __exit vmx_exit(void) { + kmem_cache_destroy(vmx_kmem_cache); __free_page(vmx_io_bitmap_b); __free_page(vmx_io_bitmap_a); ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/